[SCM] Packaging for Google Go branch, weekly-debian-sid, updated. debian-weekly/2011.09.07-1-48-ge4a4b27

Ondřej Surý ondrej at sury.org
Fri Mar 9 08:43:11 UTC 2012


The following commit has been merged in the weekly-debian-sid branch:
commit 3e609a8872e69b2df7447de5f308a5d4340f1cbf
Author: Ondřej Surý <ondrej at sury.org>
Date:   Mon Jan 30 15:38:19 2012 +0100

    Imported Upstream version 2012.01.27

diff --git a/AUTHORS b/AUTHORS
index e15ad26..6ffa22e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -14,6 +14,7 @@ Albert Strasheim <fullung at gmail.com>
 Aleksandar Dezelin <dezelin at gmail.com>
 Alex Brainman <alex.brainman at gmail.com>
 Alexander Orlov <alexander.orlov at loxal.net>
+Alexander Reece <awreece at gmail.com>
 Alexey Borzenkov <snaury at gmail.com>
 Amrut Joshi <amrut.joshi at gmail.com>
 Andrei Vieru <euvieru at gmail.com>
@@ -29,13 +30,17 @@ Aron Nopanen <aron.nopanen at gmail.com>
 Arvindh Rajesh Tamilmani <art at a-30.net>
 Ben Olive <sionide21 at gmail.com>
 Benny Siegert <bsiegert at gmail.com>
+Berengar Lehr <berengar.lehr at gmx.de>
+Blake Mizerany <blake.mizerany at gmail.com>
 Bobby Powers <bobbypowers at gmail.com>
 Caine Tighe <arctanofyourface at gmail.com>
 Charles L. Dorian <cldorian at gmail.com>
 Chris Dollin <ehog.hedge at gmail.com>
+Chris Farmiloe <chrisfarms at gmail.com>
 Chris Jones <chris at cjones.org>
 Chris Lennert <calennert at gmail.com>
 Christian Himpel <chressie at googlemail.com>
+Christoph Hack <christoph at tux21b.org>
 Christopher Nielsen <m4dh4tt3r at gmail.com>
 Christopher Wedgwood <cw at f00f.org>
 Clement Skau <clementskau at gmail.com>
@@ -57,16 +62,19 @@ Eivind Uggedal <eivind at uggedal.com>
 Eoghan Sherry <ejsherry at gmail.com>
 Eric Clark <zerohp at gmail.com>
 Eric Eisner <eric.d.eisner at gmail.com>
+Esko Luontola <esko.luontola at gmail.com>
 Evan Shaw <chickencha at gmail.com>
 Fan Hongjian <fan.howard at gmail.com>
 Fazlul Shahriar <fshahriar at gmail.com>
 Firmansyah Adiputra <frm.adiputra at gmail.com>
 Florian Uekermann <florian at uekermann-online.de>
+Florian Weimer <fw at deneb.enyo.de>
 Gary Burd <gary at beagledreams.com>
 Gideon Jan-Wessel Redelinghuys <gjredelinghuys at gmail.com>
 Giles Lean <giles.lean at pobox.com>
 Google Inc.
 Graham Miller <graham.miller at gmail.com>
+Gustav Paul <gustav.paul at gmail.com>
 Gustavo Niemeyer <gustavo at niemeyer.net>
 Harley Laue <losinggeneration at gmail.com>
 Hector Chu <hectorchu at gmail.com>
@@ -74,10 +82,13 @@ Icarus Sparry <golang at icarus.freeuk.com>
 Isaac Wagner <ibw at isaacwagner.me>
 James Fysh <james.fysh at gmail.com>
 James Meneghello <rawrz0r at gmail.com>
+James P. Cooper <jamespcooper at gmail.com>
 James Toy <nil at opensesame.st>
 James Whitehead <jnwhiteh at gmail.com>
 Jan H. Hosang <jan.hosang at gmail.com>
 Jan Mercl <befelemepeseveze at gmail.com>
+Jan Newmarch <jan.newmarch at gmail.com>
+Jani Monoses <jani.monoses at ubuntu.com>
 Jaroslavas Počepko <jp at webmaster.ms>
 Jeff Hodges <jeff at somethingsimilar.com>
 Jeff R. Allen <jra at nella.org>
@@ -86,6 +97,7 @@ Joe Poirier <jdpoirier at gmail.com>
 John Asmuth <jasmuth at gmail.com>
 Jonathan Mark <jhmark at xenops.com>
 Jonathan Wills <runningwild at gmail.com>
+Jongmin Kim <atomaths at gmail.com>
 Jose Luis Vázquez González <josvazg at gmail.com>
 Josh Goebel <dreamer3 at gmail.com>
 Jukka-Pekka Kekkonen <karatepekka at gmail.com>
@@ -99,6 +111,7 @@ Kevin Ballard <kevin at sb.org>
 Kyle Consalus <consalus at gmail.com>
 Kyle Lemons <kyle at kylelemons.net>
 Lorenzo Stoakes <lstoakes at gmail.com>
+Luca Greco <luca.greco at alcacoop.it>
 Lucio De Re <lucio.dere at gmail.com>
 Luit van Drongelen <luitvd at gmail.com>
 Markus Duft <markus.duft at salomon.at>
@@ -109,9 +122,11 @@ Matthew Horsnell <matthew.horsnell at gmail.com>
 Micah Stetson <micah.stetson at gmail.com>
 Michael Elkins <michael.elkins at gmail.com>
 Michael Hoisie <hoisie at gmail.com>
+Michał Derkacz <ziutek at lnet.pl>
 Miek Gieben <miek at miek.nl>
 Mikael Tillenius <mikti42 at gmail.com>
 Mike Rosset <mike.rosset at gmail.com>
+Miki Tebeka <miki.tebeka at gmail.com>
 Mikio Hara <mikioh.mikioh at gmail.com>
 Mikkel Krautz <mikkel at krautz.dk>
 Moriyoshi Koizumi <mozo at mozo.jp>
@@ -120,6 +135,7 @@ ngmoco, LLC
 Nicholas Waples <nwaples at gmail.com>
 Nigel Kerr <nigel.kerr at gmail.com>
 Olivier Antoine <olivier.antoine at gmail.com>
+Olivier Duperray <duperray.olivier at gmail.com>
 Padraig Kitterick <padraigkitterick at gmail.com>
 Paolo Giarrusso <p.giarrusso at gmail.com>
 Pascal S. de Kloe <pascal at quies.net>
@@ -133,24 +149,33 @@ Peter Williams <pwil3058 at gmail.com>
 Pieter Droogendijk <pieter at binky.org.uk>
 Quan Yong Zhai <qyzhai at gmail.com>
 Raif S. Naffah <go at naffah-raif.name>
+Rémy Oudompheng <oudomphe at phare.normalesup.org>
 Risto Jaakko Saarelma <rsaarelm at gmail.com>
+Robert Figueiredo <robfig at gmail.com>
 Robert Hencke <robert.hencke at gmail.com>
 Roger Pau Monné <royger at gmail.com>
 Roger Peppe <rogpeppe at gmail.com>
+Ron Minnich <rminnich at gmail.com>
 Ross Light <rlight2 at gmail.com>
 Ryan Hitchman <hitchmanr at gmail.com>
+Sanjay Menakuru <balasanjay at gmail.com>
 Scott Lawrence <bytbox at gmail.com>
 Sebastien Binet	<seb.binet at gmail.com>
+Sébastien Paolacci <sebastien.paolacci at gmail.com>
 Sergei Skorobogatov <skorobo at rambler.ru>
 Sergey 'SnakE'  Gromov <snake.scaly at gmail.com>
 Sergio Luis O. B. Correia <sergio at larces.uece.br>
+Shenghou Ma <minux.ma at gmail.com>
 Spring Mc <heresy.mc at gmail.com>
-Stefan Nilsson <snilsson at nada.kth.se>
+Stefan Nilsson <snilsson at nada.kth.se> <trolleriprofessorn at gmail.com>
 Stephen Weinberg <stephen at q5comm.com>
 Sven Almgren <sven at tras.se>
+Szabolcs Nagy <nsz at port70.net>
 Tarmigan Casebolt <tarmigan at gmail.com>
+Taru Karttunen <taruti at taruti.net>
 Timo Savola <timo.savola at gmail.com>
 Tor Andersson <tor.andersson at gmail.com>
+Vadim Vygonets <unixdj at gmail.com>
 Vincent Ambo <tazjin at googlemail.com>
 Vincent Vanackere <vincent.vanackere at gmail.com>
 Vinu Rajashekhar <vinutheraj at gmail.com>
@@ -159,6 +184,7 @@ Wei Guangjing <vcc.163 at gmail.com>
 William Josephson <wjosephson at gmail.com>
 Yasuhiro Matsumoto <mattn.jp at gmail.com>
 Yongjian Xu <i3dmaster at gmail.com>
+Yoshiyuki Kanno <nekotaroh at gmail.com> <yoshiyuki.kanno at stoic.co.jp>
 Yuusei Kuwana <kuwana at kumama.org>
 Yuval Pavel Zholkover <paulzhol at gmail.com>
 Ziad Hatahet <hatahet at gmail.com>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index ca5d5ff..b982c71 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -38,8 +38,11 @@ Albert Strasheim <fullung at gmail.com>
 Aleksandar Dezelin <dezelin at gmail.com>
 Alex Brainman <alex.brainman at gmail.com>
 Alexander Orlov <alexander.orlov at loxal.net>
+Alexander Reece <awreece at gmail.com>
+Alexandru Moșoi <brtzsnr at gmail.com>
 Alexey Borzenkov <snaury at gmail.com>
 Amrut Joshi <amrut.joshi at gmail.com>
+Andrea Spadaccini <spadaccio at google.com>
 Andrei Vieru <euvieru at gmail.com>
 Andrew Balholm <andybalholm at gmail.com>
 Andrew Gerrand <adg at golang.org>
@@ -60,6 +63,7 @@ Ben Olive <sionide21 at gmail.com>
 Benny Siegert <bsiegert at gmail.com>
 Berengar Lehr <Berengar.Lehr at gmx.de>
 Bill Neubauer <wcn at golang.org> <wcn at google.com>
+Blake Mizerany <blake.mizerany at gmail.com>
 Bobby Powers <bobbypowers at gmail.com>
 Brad Fitzpatrick <bradfitz at golang.org> <bradfitz at gmail.com>
 Brendan O'Dea <bod at golang.org>
@@ -67,9 +71,12 @@ Caine Tighe <arctanofyourface at gmail.com>
 Cary Hull <chull at google.com>
 Charles L. Dorian <cldorian at gmail.com>
 Chris Dollin <ehog.hedge at gmail.com>
+Chris Farmiloe <chrisfarms at gmail.com>
+Chris Hundt <hundt at google.com>
 Chris Jones <chris at cjones.org> <chris.jones.yar at gmail.com>
 Chris Lennert <calennert at gmail.com>
 Christian Himpel <chressie at googlemail.com> <chressie at gmail.com>
+Christoph Hack <christoph at tux21b.org>
 Christopher Nielsen <m4dh4tt3r at gmail.com>
 Christopher Wedgwood <cw at f00f.org>
 Clement Skau <clementskau at gmail.com>
@@ -82,7 +89,7 @@ Daniel Theophanes <kardianos at gmail.com>
 Dave Cheney <dave at cheney.net>
 Dave Grijalva <dgrijalva at ngmoco.com>
 David Anderson <danderson at google.com>
-David Crawshaw <david.crawshaw at zentus.com>
+David Crawshaw <david.crawshaw at zentus.com> <crawshaw at google.com>
 David Forsythe <dforsythe at gmail.com>
 David G. Andersen <dave.andersen at gmail.com>
 David Jakob Fritz <david.jakob.fritz at gmail.com>
@@ -97,17 +104,20 @@ Eivind Uggedal <eivind at uggedal.com>
 Eoghan Sherry <ejsherry at gmail.com>
 Eric Clark <zerohp at gmail.com>
 Eric Eisner <eric.d.eisner at gmail.com>
+Esko Luontola <esko.luontola at gmail.com>
 Evan Martin <evan.martin at gmail.com>
 Evan Shaw <chickencha at gmail.com>
 Fan Hongjian <fan.howard at gmail.com>
 Fazlul Shahriar <fshahriar at gmail.com>
 Firmansyah Adiputra <frm.adiputra at gmail.com>
 Florian Uekermann <florian at uekermann-online.de> <f1 at uekermann-online.de>
+Florian Weimer <fw at deneb.enyo.de>
 Fumitoshi Ukai <ukai at google.com>
 Gary Burd <gary at beagledreams.com> <gary.burd at gmail.com>
 Gideon Jan-Wessel Redelinghuys <gjredelinghuys at gmail.com>
 Giles Lean <giles.lean at pobox.com>
 Graham Miller <graham.miller at gmail.com>
+Gustav Paul <gustav.paul at gmail.com>
 Gustavo Niemeyer <gustavo at niemeyer.net> <n13m3y3r at gmail.com>
 Harley Laue <losinggeneration at gmail.com>
 Hector Chu <hectorchu at gmail.com>
@@ -119,11 +129,14 @@ Jacob Baskin <jbaskin at google.com>
 James Aguilar <jaguilar at google.com>
 James Fysh <james.fysh at gmail.com>
 James Meneghello <rawrz0r at gmail.com>
+James P. Cooper <jamespcooper at gmail.com>
 James Toy <nil at opensesame.st>
 James Whitehead <jnwhiteh at gmail.com>
 Jamie Gennis <jgennis at google.com>
 Jan H. Hosang <jan.hosang at gmail.com>
 Jan Mercl <befelemepeseveze at gmail.com>
+Jan Newmarch <jan.newmarch at gmail.com>
+Jani Monoses <jani.monoses at ubuntu.com> <jani.monoses at gmail.com>
 Jaroslavas Počepko <jp at webmaster.ms>
 Jeff Hodges <jeff at somethingsimilar.com>
 Jeff R. Allen <jra at nella.org> <jeff.allen at gmail.com>
@@ -132,10 +145,13 @@ Joe Poirier <jdpoirier at gmail.com>
 Joel Sing <jsing at google.com>
 Johan Euphrosine <proppy at google.com>
 John Asmuth <jasmuth at gmail.com>
+John Beisley <huin at google.com>
 John DeNero <denero at google.com>
 Jonathan Allie <jonallie at google.com>
 Jonathan Mark <jhmark at xenops.com> <jhmark000 at gmail.com>
+Jonathan Pittman <jmpittman at google.com> <jonathan.mark.pittman at gmail.com>
 Jonathan Wills <runningwild at gmail.com>
+Jongmin Kim <atomaths at gmail.com>
 Jos Visser <josv at google.com>
 Jose Luis Vázquez González <josvazg at gmail.com>
 Josh Goebel <dreamer3 at gmail.com>
@@ -153,6 +169,8 @@ Kyle Consalus <consalus at gmail.com>
 Kyle Lemons <kyle at kylelemons.net> <kevlar at google.com>
 Larry Hosken <lahosken at golang.org>
 Lorenzo Stoakes <lstoakes at gmail.com>
+Louis Kruger <louisk at google.com>
+Luca Greco <luca.greco at alcacoop.it>
 Lucio De Re <lucio.dere at gmail.com>
 Luit van Drongelen <luitvd at gmail.com>
 Luuk van Dijk <lvd at golang.org> <lvd at google.com>
@@ -164,17 +182,20 @@ Mateusz Czapliński <czapkofan at gmail.com>
 Mathieu Lonjaret <mathieu.lonjaret at gmail.com>
 Matt Jones <mrjones at google.com>
 Matthew Horsnell <matthew.horsnell at gmail.com>
+Maxim Pimenov <mpimenov at google.com>
 Maxim Ushakov <ushakov at google.com>
 Micah Stetson <micah.stetson at gmail.com>
 Michael Elkins <michael.elkins at gmail.com>
 Michael Hoisie <hoisie at gmail.com>
 Michael Shields <mshields at google.com>
 Michael T. Jones <mtj at google.com> <michael.jones at gmail.com>
+Michał Derkacz <ziutek at lnet.pl>
 Miek Gieben <miek at miek.nl> <remigius.gieben at gmail.com>
 Mikael Tillenius <mikti42 at gmail.com>
 Mike Rosset <mike.rosset at gmail.com>
 Mike Samuel <mikesamuel at gmail.com>
 Mike Solomon <msolo at gmail.com>
+Miki Tebeka <miki.tebeka at gmail.com>
 Mikio Hara <mikioh.mikioh at gmail.com>
 Mikkel Krautz <mikkel at krautz.dk> <krautz at gmail.com>
 Moriyoshi Koizumi <mozo at mozo.jp>
@@ -183,6 +204,7 @@ Nicholas Waples <nwaples at gmail.com>
 Nigel Kerr <nigel.kerr at gmail.com>
 Nigel Tao <nigeltao at golang.org>
 Olivier Antoine <olivier.antoine at gmail.com>
+Olivier Duperray <duperray.olivier at gmail.com>
 Padraig Kitterick <padraigkitterick at gmail.com>
 Paolo Giarrusso <p.giarrusso at gmail.com>
 Pascal S. de Kloe <pascal at quies.net>
@@ -201,34 +223,43 @@ Pieter Droogendijk <pieter at binky.org.uk>
 Quan Yong Zhai <qyzhai at gmail.com>
 Raif S. Naffah <go at naffah-raif.name>
 Raph Levien <raph at google.com>
+Rémy Oudompheng <oudomphe at phare.normalesup.org> <remyoudompheng at gmail.com>
 Risto Jaakko Saarelma <rsaarelm at gmail.com>
 Rob Pike <r at golang.org>
+Robert Figueiredo <robfig at gmail.com>
 Robert Griesemer <gri at golang.org>
 Robert Hencke <robert.hencke at gmail.com>
 Roger Pau Monné <royger at gmail.com>
 Roger Peppe <rogpeppe at gmail.com>
+Ron Minnich <rminnich at gmail.com>
 Ross Light <rlight2 at gmail.com>
 Russ Cox <rsc at golang.org>
 Ryan Hitchman <hitchmanr at gmail.com>
 Sam Thorogood <thorogood at google.com> <sam.thorogood at gmail.com>
-Sameer Ajmani <ajmani at gmail.com>
+Sameer Ajmani <sameer at golang.org> <ajmani at gmail.com>
+Sanjay Menakuru <balasanjay at gmail.com>
 Scott Lawrence <bytbox at gmail.com>
 Scott Schwartz <scotts at golang.org>
 Sebastien Binet	<seb.binet at gmail.com>
+Sébastien Paolacci <sebastien.paolacci at gmail.com>
 Sergei Skorobogatov <skorobo at rambler.ru>
 Sergey 'SnakE' Gromov <snake.scaly at gmail.com>
 Sergio Luis O. B. Correia <sergio at larces.uece.br>
+Shenghou Ma <minux.ma at gmail.com>
 Spring Mc <heresy.mc at gmail.com>
-Stefan Nilsson <snilsson at nada.kth.se>
+Stefan Nilsson <snilsson at nada.kth.se> <trolleriprofessorn at gmail.com>
 Stephen Ma <stephenm at golang.org>
 Stephen Weinberg <stephen at q5comm.com>
 Sugu Sougoumarane <ssougou at gmail.com>
 Sven Almgren <sven at tras.se>
+Szabolcs Nagy <nsz at port70.net>
 Tarmigan Casebolt <tarmigan at gmail.com>
+Taru Karttunen <taruti at taruti.net>
 Timo Savola <timo.savola at gmail.com>
 Tom Szymanski <tgs at google.com>
 Tor Andersson <tor.andersson at gmail.com>
 Trevor Strohman <trevor.strohman at gmail.com>
+Vadim Vygonets <unixdj at gmail.com>
 Vincent Ambo <tazjin at googlemail.com>
 Vincent Vanackere <vincent.vanackere at gmail.com>
 Vinu Rajashekhar <vinutheraj at gmail.com>
@@ -239,6 +270,7 @@ William Chan <willchan at chromium.org>
 William Josephson <wjosephson at gmail.com>
 Yasuhiro Matsumoto <mattn.jp at gmail.com>
 Yongjian Xu <i3dmaster at gmail.com>
+Yoshiyuki Kanno <nekotaroh at gmail.com> <yoshiyuki.kanno at stoic.co.jp>
 Yuusei Kuwana <kuwana at kumama.org>
 Yuval Pavel Zholkover <paulzhol at gmail.com>
 Yves Junqueira <yves.junqueira at gmail.com>
diff --git a/VERSION b/VERSION
index 032afb7..7c8c3f5 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-weekly.2011-09-21 9846
+weekly.2012-01-27 11507
diff --git a/doc/GoCourseDay1.pdf b/doc/GoCourseDay1.pdf
deleted file mode 100644
index 5a7749c..0000000
Binary files a/doc/GoCourseDay1.pdf and /dev/null differ
diff --git a/doc/GoCourseDay2.pdf b/doc/GoCourseDay2.pdf
deleted file mode 100644
index 0d82ba4..0000000
Binary files a/doc/GoCourseDay2.pdf and /dev/null differ
diff --git a/doc/GoCourseDay3.pdf b/doc/GoCourseDay3.pdf
deleted file mode 100644
index 5a5463b..0000000
Binary files a/doc/GoCourseDay3.pdf and /dev/null differ
diff --git a/doc/Makefile b/doc/Makefile
index 29d7e2c..9a52b25 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -8,11 +8,17 @@ TARG=tmpltohtml
 GOFILES=\
 	tmpltohtml.go\
 
-go_tutorial.html: go_tutorial.tmpl tmpltohtml
-	makehtml go_tutorial.tmpl
+HTML=\
+	articles/defer_panic_recover.html\
+	articles/error_handling.html\
+	articles/slices_usage_and_internals.html\
+	effective_go.html\
+	go1.html\
+	go_tutorial.html\
 
-effective_go.html: effective_go.tmpl tmpltohtml
-	makehtml effective_go.tmpl
+all: tmpltohtml $(HTML)
 
+%.html: %.tmpl tmpltohtml
+	./makehtml $*.tmpl
 
 include ../src/Make.cmd
diff --git a/doc/all.css b/doc/all.css
index f8f8c65..8caab97 100644
--- a/doc/all.css
+++ b/doc/all.css
@@ -29,6 +29,9 @@ pre {
   background: #F0F0F0;
   padding: 0.5em 1em;
 }
+h3 {
+  font-size: 100%;
+}
 
 /* Top bar */
 #container {
@@ -78,15 +81,15 @@ h1#title {
   -webkit-box-shadow: 0 1px 1px #ccc;
 }
 #nav-main li:first-child {
-  -moz-border-top-left-radius: 4px;
+  -moz-border-radius-topleft: 4px;
   border-top-left-radius: 4px;
-  -moz-border-bottom-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
   border-bottom-left-radius: 4px;
 }
 #nav-main li:last-child {
-  -moz-border-top-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
   border-top-right-radius: 4px;
-  -moz-border-bottom-right-radius: 4px;
+  -moz-border-radius-bottomright: 4px;
   border-bottom-right-radius: 4px;
 }
 #nav-main .quickref {
@@ -202,3 +205,18 @@ sup.new {
   font-size: 8px;
   line-height: 0;
 }
+.example .expanded {
+  display: none;
+}
+.exampleVisible .collapsed {
+  display: none;
+}
+.exampleHeading {
+  cursor: pointer;
+}
+
+/* Table of code entries; used by go1.html */
+.codetable td {
+   font-family: monospace;
+   font-size: 120%;
+}
diff --git a/doc/articles/defer_panic_recover.html b/doc/articles/defer_panic_recover.html
new file mode 100644
index 0000000..18c0de2
--- /dev/null
+++ b/doc/articles/defer_panic_recover.html
@@ -0,0 +1,274 @@
+<!--{
+	"Title": "Defer, Panic, and Recover"
+}-->
+<!--
+  DO NOT EDIT: created by
+    tmpltohtml articles/defer_panic_recover.tmpl
+-->
+
+<p>
+Go has the usual mechanisms for control flow: if, for, switch, goto.  It also
+has the go statement to run code in a separate goroutine.  Here I'd like to
+discuss some of the less common ones: defer, panic, and recover.
+</p>
+ 
+<p>
+A <b>defer statement</b> pushes a function call onto a list. The list of saved
+calls is executed after the surrounding function returns. Defer is commonly
+used to simplify functions that perform various clean-up actions.
+</p>
+ 
+<p>
+For example, let's look at a function that opens two files and copies the
+contents of one file to the other:
+</p>
+ 
+<pre><!--{{code "progs/defer.go" `/func CopyFile/` `/STOP/`}}
+-->func CopyFile(dstName, srcName string) (written int64, err error) {
+    src, err := os.Open(srcName)
+    if err != nil {
+        return
+    }
+
+    dst, err := os.Create(dstName)
+    if err != nil {
+        return
+    }
+
+    written, err = io.Copy(dst, src)
+    dst.Close()
+    src.Close()
+    return
+}</pre>
+
+<p>
+This works, but there is a bug. If the second call to os.Open fails, the
+function will return without closing the source file. This can be easily
+remedied by putting a call to src.Close() before the second return statement,
+but if the function were more complex the problem might not be so easily
+noticed and resolved. By introducing defer statements we can ensure that the
+files are always closed:
+</p>
+ 
+<pre><!--{{code "progs/defer2.go" `/func CopyFile/` `/STOP/`}}
+-->func CopyFile(dstName, srcName string) (written int64, err error) {
+    src, err := os.Open(srcName)
+    if err != nil {
+        return
+    }
+    defer src.Close()
+
+    dst, err := os.Create(dstName)
+    if err != nil {
+        return
+    }
+    defer dst.Close()
+
+    return io.Copy(dst, src)
+}</pre>
+
+<p>
+Defer statements allow us to think about closing each file right after opening
+it, guaranteeing that, regardless of the number of return statements in the
+function, the files <i>will</i> be closed.
+</p>
+ 
+<p>
+The behavior of defer statements is straightforward and predictable. There are
+three simple rules:
+</p>
+ 
+<p>
+1. <i>A deferred function's arguments are evaluated when the defer statement is
+evaluated.</i> 
+</p>
+ 
+<p>
+In this example, the expression "i" is evaluated when the Println call is
+deferred. The deferred call will print "0" after the function returns.
+</p>
+ 
+<pre><!--{{code "progs/defer.go" `/func a/` `/STOP/`}}
+-->func a() {
+    i := 0
+    defer fmt.Println(i)
+    i++
+    return
+}</pre>
+
+<p>
+2. <i>Deferred function calls are executed in Last In First Out order
+</i>after<i> the surrounding function returns.</i> 
+</p>
+ 
+<p>
+This function prints "3210":
+</p>
+
+<pre><!--{{code "progs/defer.go" `/func b/` `/STOP/`}}
+-->func b() {
+    for i := 0; i < 4; i++ {
+        defer fmt.Print(i)
+    }
+}</pre>
+ 
+<p>
+3. <i>Deferred functions may read and assign to the returning function's named
+return values.</i> 
+</p>
+ 
+<p>
+In this example, a deferred function increments the return value i <i>after</i>
+the surrounding function returns. Thus, this function returns 2:
+</p>
+
+<pre><!--{{code "progs/defer.go" `/func c/` `/STOP/`}}
+-->func c() (i int) {
+    defer func() { i++ }()
+    return 1
+}</pre>
+ 
+<p>
+This is convenient for modifying the error return value of a function; we will
+see an example of this shortly.
+</p>
+ 
+<p>
+<b>Panic</b> is a built-in function that stops the ordinary flow of control and
+begins <i>panicking</i>. When the function F calls panic, execution of F stops,
+any deferred functions in F are executed normally, and then F returns to its
+caller. To the caller, F then behaves like a call to panic. The process
+continues up the stack until all functions in the current goroutine have
+returned, at which point the program crashes. Panics can be initiated by
+invoking panic directly. They can also be caused by runtime errors, such as
+out-of-bounds array accesses.
+</p>
+ 
+<p>
+<b>Recover</b> is a built-in function that regains control of a panicking
+goroutine. Recover is only useful inside deferred functions. During normal
+execution, a call to recover will return nil and have no other effect. If the
+current goroutine is panicking, a call to recover will capture the value given
+to panic and resume normal execution.
+</p>
+ 
+<p>
+Here's an example program that demonstrates the mechanics of panic and defer:
+</p>
+
+<pre><!--{{code "progs/defer2.go" `/package main/` `/STOP/`}}
+-->package main
+
+import "fmt"
+
+func main() {
+    f()
+    fmt.Println("Returned normally from f.")
+}
+
+func f() {
+    defer func() {
+        if r := recover(); r != nil {
+            fmt.Println("Recovered in f", r)
+        }
+    }()
+    fmt.Println("Calling g.")
+    g(0)
+    fmt.Println("Returned normally from g.")
+}
+
+func g(i int) {
+    if i > 3 {
+        fmt.Println("Panicking!")
+        panic(fmt.Sprintf("%v", i))
+    }
+    defer fmt.Println("Defer in g", i)
+    fmt.Println("Printing in g", i)
+    g(i + 1)
+}</pre>
+ 
+<p>
+The function g takes the int i, and panics if i is greater than 3, or else it
+calls itself with the argument i+1. The function f defers a function that calls
+recover and prints the recovered value (if it is non-nil). Try to picture what
+the output of this program might be before reading on.
+</p>
+ 
+<p>
+The program will output:
+</p>
+ 
+<pre>Calling g.
+Printing in g 0
+Printing in g 1
+Printing in g 2
+Printing in g 3
+Panicking!
+Defer in g 3
+Defer in g 2
+Defer in g 1
+Defer in g 0
+Recovered in f 4
+Returned normally from f.</pre> 
+
+<p>
+If we remove the deferred function from f the panic is not recovered and
+reaches the top of the goroutine's call stack, terminating the program. This
+modified program will output:
+</p>
+ 
+<pre>Calling g.
+Printing in g 0
+Printing in g 1
+Printing in g 2
+Printing in g 3
+Panicking!
+Defer in g 3
+Defer in g 2
+Defer in g 1
+Defer in g 0
+panic: 4
+ 
+panic PC=0x2a9cd8
+[stack trace omitted]</pre> 
+
+<p>
+For a real-world example of <b>panic</b> and <b>recover</b>, see the
+<a href="/pkg/encoding/json/">json package</a> from the Go standard library.
+It decodes JSON-encoded data with a set of recursive functions.
+When malformed JSON is encountered, the parser calls panic is to unwind the
+stack to the top-level function call, which recovers from the panic and returns
+an appropriate error value (see the 'error' and 'unmarshal' functions in
+<a href="/src/pkg/encoding/json/decode.go">decode.go</a>).
+</p>
+
+<p>
+The convention in the Go libraries is that even when a package uses panic
+internally, its external API still presents explicit error return values.
+</p>
+ 
+<p>
+Other uses of <b>defer</b> (beyond the file.Close() example given earlier)
+include releasing a mutex:
+</p>
+
+<pre>mu.Lock()
+defer mu.Unlock()</pre> 
+
+<p>
+printing a footer:
+</p>
+ 
+<pre>printHeader()
+defer printFooter()</pre> 
+
+<p>
+and more.
+</p>
+ 
+<p>
+In summary, the defer statement (with or without panic and recover) provides an
+unusual and powerful mechanism for control flow.  It can be used to model a
+number of features implemented by special-purpose structures in other
+programming languages. Try it out.
+</p>
diff --git a/doc/articles/defer_panic_recover.tmpl b/doc/articles/defer_panic_recover.tmpl
new file mode 100644
index 0000000..60c8eeb
--- /dev/null
+++ b/doc/articles/defer_panic_recover.tmpl
@@ -0,0 +1,195 @@
+<!--{
+	"Title": "Defer, Panic, and Recover"
+}-->
+{{donotedit}}
+<p>
+Go has the usual mechanisms for control flow: if, for, switch, goto.  It also
+has the go statement to run code in a separate goroutine.  Here I'd like to
+discuss some of the less common ones: defer, panic, and recover.
+</p>
+ 
+<p>
+A <b>defer statement</b> pushes a function call onto a list. The list of saved
+calls is executed after the surrounding function returns. Defer is commonly
+used to simplify functions that perform various clean-up actions.
+</p>
+ 
+<p>
+For example, let's look at a function that opens two files and copies the
+contents of one file to the other:
+</p>
+ 
+{{code "progs/defer.go" `/func CopyFile/` `/STOP/`}}
+
+<p>
+This works, but there is a bug. If the second call to os.Open fails, the
+function will return without closing the source file. This can be easily
+remedied by putting a call to src.Close() before the second return statement,
+but if the function were more complex the problem might not be so easily
+noticed and resolved. By introducing defer statements we can ensure that the
+files are always closed:
+</p>
+ 
+{{code "progs/defer2.go" `/func CopyFile/` `/STOP/`}}
+
+<p>
+Defer statements allow us to think about closing each file right after opening
+it, guaranteeing that, regardless of the number of return statements in the
+function, the files <i>will</i> be closed.
+</p>
+ 
+<p>
+The behavior of defer statements is straightforward and predictable. There are
+three simple rules:
+</p>
+ 
+<p>
+1. <i>A deferred function's arguments are evaluated when the defer statement is
+evaluated.</i> 
+</p>
+ 
+<p>
+In this example, the expression "i" is evaluated when the Println call is
+deferred. The deferred call will print "0" after the function returns.
+</p>
+ 
+{{code "progs/defer.go" `/func a/` `/STOP/`}}
+
+<p>
+2. <i>Deferred function calls are executed in Last In First Out order
+</i>after<i> the surrounding function returns.</i> 
+</p>
+ 
+<p>
+This function prints "3210":
+</p>
+
+{{code "progs/defer.go" `/func b/` `/STOP/`}}
+ 
+<p>
+3. <i>Deferred functions may read and assign to the returning function's named
+return values.</i> 
+</p>
+ 
+<p>
+In this example, a deferred function increments the return value i <i>after</i>
+the surrounding function returns. Thus, this function returns 2:
+</p>
+
+{{code "progs/defer.go" `/func c/` `/STOP/`}}
+ 
+<p>
+This is convenient for modifying the error return value of a function; we will
+see an example of this shortly.
+</p>
+ 
+<p>
+<b>Panic</b> is a built-in function that stops the ordinary flow of control and
+begins <i>panicking</i>. When the function F calls panic, execution of F stops,
+any deferred functions in F are executed normally, and then F returns to its
+caller. To the caller, F then behaves like a call to panic. The process
+continues up the stack until all functions in the current goroutine have
+returned, at which point the program crashes. Panics can be initiated by
+invoking panic directly. They can also be caused by runtime errors, such as
+out-of-bounds array accesses.
+</p>
+ 
+<p>
+<b>Recover</b> is a built-in function that regains control of a panicking
+goroutine. Recover is only useful inside deferred functions. During normal
+execution, a call to recover will return nil and have no other effect. If the
+current goroutine is panicking, a call to recover will capture the value given
+to panic and resume normal execution.
+</p>
+ 
+<p>
+Here's an example program that demonstrates the mechanics of panic and defer:
+</p>
+
+{{code "progs/defer2.go" `/package main/` `/STOP/`}}
+ 
+<p>
+The function g takes the int i, and panics if i is greater than 3, or else it
+calls itself with the argument i+1. The function f defers a function that calls
+recover and prints the recovered value (if it is non-nil). Try to picture what
+the output of this program might be before reading on.
+</p>
+ 
+<p>
+The program will output:
+</p>
+ 
+<pre>Calling g.
+Printing in g 0
+Printing in g 1
+Printing in g 2
+Printing in g 3
+Panicking!
+Defer in g 3
+Defer in g 2
+Defer in g 1
+Defer in g 0
+Recovered in f 4
+Returned normally from f.</pre> 
+
+<p>
+If we remove the deferred function from f the panic is not recovered and
+reaches the top of the goroutine's call stack, terminating the program. This
+modified program will output:
+</p>
+ 
+<pre>Calling g.
+Printing in g 0
+Printing in g 1
+Printing in g 2
+Printing in g 3
+Panicking!
+Defer in g 3
+Defer in g 2
+Defer in g 1
+Defer in g 0
+panic: 4
+ 
+panic PC=0x2a9cd8
+[stack trace omitted]</pre> 
+
+<p>
+For a real-world example of <b>panic</b> and <b>recover</b>, see the
+<a href="/pkg/encoding/json/">json package</a> from the Go standard library.
+It decodes JSON-encoded data with a set of recursive functions.
+When malformed JSON is encountered, the parser calls panic is to unwind the
+stack to the top-level function call, which recovers from the panic and returns
+an appropriate error value (see the 'error' and 'unmarshal' functions in
+<a href="/src/pkg/encoding/json/decode.go">decode.go</a>).
+</p>
+
+<p>
+The convention in the Go libraries is that even when a package uses panic
+internally, its external API still presents explicit error return values.
+</p>
+ 
+<p>
+Other uses of <b>defer</b> (beyond the file.Close() example given earlier)
+include releasing a mutex:
+</p>
+
+<pre>mu.Lock()
+defer mu.Unlock()</pre> 
+
+<p>
+printing a footer:
+</p>
+ 
+<pre>printHeader()
+defer printFooter()</pre> 
+
+<p>
+and more.
+</p>
+ 
+<p>
+In summary, the defer statement (with or without panic and recover) provides an
+unusual and powerful mechanism for control flow.  It can be used to model a
+number of features implemented by special-purpose structures in other
+programming languages. Try it out.
+</p>
diff --git a/doc/articles/error_handling.html b/doc/articles/error_handling.html
new file mode 100644
index 0000000..b9393a2
--- /dev/null
+++ b/doc/articles/error_handling.html
@@ -0,0 +1,433 @@
+<!--{
+	"Title": "Error Handling and Go"
+}-->
+<!--
+  DO NOT EDIT: created by
+    tmpltohtml articles/error_handling.tmpl
+-->
+
+<p>
+If you have written any Go code you have probably encountered the built-in
+<code>error</code> type. Go code uses <code>error</code> values to
+indicate an abnormal state. For example, the <code>os.Open</code> function
+returns a non-nil <code>error</code> value when it fails to open a file.
+</p>
+
+<pre><!--{{code "progs/error.go" `/func Open/`}}
+-->func Open(name string) (file *File, err error)</pre>
+
+<p>
+The following code uses <code>os.Open</code> to open a file. If an error
+occurs it calls <code>log.Fatal</code> to print the error message and stop.
+</p>
+
+<pre><!--{{code "progs/error.go" `/func openFile/` `/STOP/`}}
+-->    f, err := os.Open("filename.ext")
+    if err != nil {
+        log.Fatal(err)
+    }
+    // do something with the open *File f</pre>
+
+<p>
+You can get a lot done in Go knowing just this about the <code>error</code>
+type, but in this article we'll take a closer look at <code>error</code> and
+discuss some good practices for error handling in Go.
+</p>
+
+<p>
+<b>The error type</b>
+</p>
+
+<p>
+The <code>error</code> type is an interface type. An <code>error</code>
+variable represents any value that can describe itself as a string. Here is the
+interface's declaration:
+</p>
+
+<pre>type error interface {
+    Error() string
+}</pre>
+
+<p>
+The <code>error</code> type, as with all built in types, is
+<a href="/doc/go_spec.html#Predeclared_identifiers">predeclared</a> in the
+<a href="/doc/go_spec.html#Blocks">universe block</a>.
+</p>
+
+<p>
+The most commonly-used <code>error</code> implementation is the
+<a href="/pkg/errors/">errors</a> package's unexported <code>errorString</code> type.
+</p>
+
+<pre><!--{{code "progs/error.go" `/errorString/` `/STOP/`}}
+-->// errorString is a trivial implementation of error.
+type errorString struct {
+    s string
+}
+
+func (e *errorString) Error() string {
+    return e.s
+}</pre>
+
+<p>
+You can construct one of these values with the <code>errors.New</code>
+function. It takes a string that it converts to an <code>errors.errorString</code>
+and returns as an <code>error</code> value.
+</p>
+
+<pre><!--{{code "progs/error.go" `/New/` `/STOP/`}}
+-->// New returns an error that formats as the given text.
+func New(text string) error {
+    return &errorString{text}
+}</pre>
+
+<p>
+Here's how you might use <code>errors.New</code>:
+</p>
+
+<pre><!--{{code "progs/error.go" `/func Sqrt/` `/STOP/`}}
+-->func Sqrt(f float64) (float64, error) {
+    if f < 0 {
+        return 0, errors.New("math: square root of negative number")
+    }
+    // implementation
+}</pre>
+
+<p>
+A caller passing a negative argument to <code>Sqrt</code> receives a non-nil
+<code>error</code> value (whose concrete representation is an
+<code>errors.errorString</code> value). The caller can access the error string
+("math: square root of...") by calling the <code>error</code>'s
+<code>Error</code> method, or by just printing it:
+</p>
+
+<pre><!--{{code "progs/error.go" `/func printErr/` `/STOP/`}}
+-->    f, err := Sqrt(-1)
+    if err != nil {
+        fmt.Println(err)
+    }</pre>
+
+<p>
+The <a href="/pkg/fmt/">fmt</a> package formats an <code>error</code> value
+by calling its <code>Error() string</code> method.
+</p>
+
+<p>
+It is the error implementation's responsibility to summarize the context.
+The error returned by <code>os.Open</code> formats as "open /etc/passwd:
+permission denied," not just "permission denied."  The error returned by our
+<code>Sqrt</code> is missing information about the invalid argument.
+</p>
+
+<p>
+To add that information, a useful function is the <code>fmt</code> package's
+<code>Errorf</code>. It formats a string according to <code>Printf</code>'s
+rules and returns it as an <code>error</code> created by
+<code>errors.New</code>.
+</p>
+
+<pre><!--{{code "progs/error.go" `/fmtError/` `/STOP/`}}
+-->    if f < 0 {
+        return 0, fmt.Errorf("math: square root of negative number %g", f)
+    }</pre>
+
+<p>
+In many cases <code>fmt.Errorf</code> is good enough, but since
+<code>error</code> is an interface, you can use arbitrary data structures as
+error values, to allow callers to inspect the details of the error.
+</p>
+
+<p>
+For instance, our hypothetical callers might want to recover the invalid
+argument passed to <code>Sqrt</code>. We can enable that by defining a new
+error implementation instead of using <code>errors.errorString</code>:
+</p>
+
+<pre><!--{{code "progs/error.go" `/type NegativeSqrtError/` `/STOP/`}}
+-->type NegativeSqrtError float64
+
+func (f NegativeSqrtError) Error() string {
+    return fmt.Sprintf("math: square root of negative number %g", float64(f))
+}</pre>
+
+<p>
+A sophisticated caller can then use a
+<a href="/doc/go_spec.html#Type_assertions">type assertion</a> to check for a
+<code>NegativeSqrtError</code> and handle it specially, while callers that just
+pass the error to <code>fmt.Println</code> or <code>log.Fatal</code> will see
+no change in behavior.
+</p>
+
+<p>
+As another example, the <a href="/pkg/encoding/json/">json</a> package specifies a
+<code>SyntaxError</code> type that the <code>json.Decode</code> function
+returns when it encounters a syntax error parsing a JSON blob.
+</p>
+
+<pre><!--{{code "progs/error.go" `/type SyntaxError/` `/STOP/`}}
+-->type SyntaxError struct {
+    msg    string // description of error
+    Offset int64  // error occurred after reading Offset bytes
+}
+
+func (e *SyntaxError) Error() string { return e.msg }</pre>
+
+<p>
+The <code>Offset</code> field isn't even shown in the default formatting of the
+error, but callers can use it to add file and line information to their error
+messages:
+</p>
+
+<pre><!--{{code "progs/error.go" `/func decodeError/` `/STOP/`}}
+-->    if err := dec.Decode(&val); err != nil {
+        if serr, ok := err.(*json.SyntaxError); ok {
+            line, col := findLine(f, serr.Offset)
+            return fmt.Errorf("%s:%d:%d: %v", f.Name(), line, col, err)
+        }
+        return err
+    }</pre>
+
+<p>
+(This is a slightly simplified version of some
+<a href="http://camlistore.org/code/?p=camlistore.git;a=blob;f=lib/go/camli/jsonconfig/eval.go#l68">actual code</a>
+from the <a href="http://camlistore.org">Camlistore</a> project.)
+</p>
+
+<p>
+The <code>error</code> interface requires only a <code>Error</code> method;
+specific error implementations might have additional methods. For instance, the
+<a href="/pkg/net/">net</a> package returns errors of type
+<code>error</code>, following the usual convention, but some of the error
+implementations have additional methods defined by the <code>net.Error</code>
+interface:
+</p>
+
+<pre>package net
+
+type Error interface {
+    error
+    Timeout() bool   // Is the error a timeout?
+    Temporary() bool // Is the error temporary?
+}</pre>
+
+<p>
+Client code can test for a <code>net.Error</code> with a type assertion and
+then distinguish transient network errors from permanent ones. For instance, a
+web crawler might sleep and retry when it encounters a temporary error and give
+up otherwise.
+</p>
+
+<pre><!--{{code "progs/error.go" `/func netError/` `/STOP/`}}
+-->        if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
+            time.Sleep(1e9)
+            continue
+        }
+        if err != nil {
+            log.Fatal(err)
+        }</pre>
+
+<p>
+<b>Simplifying repetitive error handling</b>
+</p>
+
+<p>
+In Go, error handling is important. The language's design and conventions
+encourage you to explicitly check for errors where they occur (as distinct from
+the convention in other languages of throwing exceptions and sometimes catching
+them). In some cases this makes Go code verbose, but fortunately there are some
+techniques you can use to minimize repetitive error handling.
+</p>
+
+<p>
+Consider an <a href="http://code.google.com/appengine/docs/go/">App Engine</a>
+application with an HTTP handler that retrieves a record from the datastore and
+formats it with a template.
+</p>
+
+<pre><!--{{code "progs/error2.go" `/func init/` `/STOP/`}}
+-->func init() {
+    http.HandleFunc("/view", viewRecord)
+}
+
+func viewRecord(w http.ResponseWriter, r *http.Request) {
+    c := appengine.NewContext(r)
+    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
+    record := new(Record)
+    if err := datastore.Get(c, key, record); err != nil {
+        http.Error(w, err.Error(), 500)
+        return
+    }
+    if err := viewTemplate.Execute(w, record); err != nil {
+        http.Error(w, err.Error(), 500)
+    }
+}</pre>
+
+<p>
+This function handles errors returned by the <code>datastore.Get</code>
+function and <code>viewTemplate</code>'s <code>Execute</code> method. In both
+cases, it presents a simple error message to the user with the HTTP status code
+500 ("Internal Server Error"). This looks like a manageable amount of code, but
+add some more HTTP handlers and you quickly end up with many copies of
+identical error handling code.
+</p>
+
+<p>
+To reduce the repetition we can define our own HTTP <code>appHandler</code>
+type that includes an <code>error</code> return value:
+</p>
+
+<pre><!--{{code "progs/error3.go" `/type appHandler/`}}
+-->type appHandler func(http.ResponseWriter, *http.Request) error</pre>
+
+<p>
+Then we can change our <code>viewRecord</code> function to return errors:
+</p>
+
+<pre><!--{{code "progs/error3.go" `/func viewRecord/` `/STOP/`}}
+-->func viewRecord(w http.ResponseWriter, r *http.Request) error {
+    c := appengine.NewContext(r)
+    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
+    record := new(Record)
+    if err := datastore.Get(c, key, record); err != nil {
+        return err
+    }
+    return viewTemplate.Execute(w, record)
+}</pre>
+
+<p>
+This is simpler than the original version, but the <a
+href="/pkg/net/http/">http</a> package doesn't understand functions that return
+<code>error</code>.
+To fix this we can implement the <code>http.Handler</code> interface's
+<code>ServeHTTP</code> method on <code>appHandler</code>:
+</p>
+
+<pre><!--{{code "progs/error3.go" `/ServeHTTP/` `/STOP/`}}
+-->func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+    if err := fn(w, r); err != nil {
+        http.Error(w, err.Error(), 500)
+    }
+}</pre>
+
+<p>
+The <code>ServeHTTP</code> method calls the <code>appHandler</code> function
+and displays the returned error (if any) to the user.  Notice that the method's
+receiver, <code>fn</code>, is a function. (Go can do that!) The method invokes
+the function by calling the receiver in the expression <code>fn(w, r)</code>.
+</p>
+
+<p>
+Now when registering <code>viewRecord</code> with the http package we use the
+<code>Handle</code> function (instead of <code>HandleFunc</code>) as
+<code>appHandler</code> is an <code>http.Handler</code> (not an
+<code>http.HandlerFunc</code>). 
+</p>
+
+<pre><!--{{code "progs/error3.go" `/func init/` `/STOP/`}}
+-->func init() {
+    http.Handle("/view", appHandler(viewRecord))
+}</pre>
+
+<p>
+With this basic error handling infrastructure in place, we can make it more
+user friendly. Rather than just displaying the error string, it would be better
+to give the user a simple error message with an appropriate HTTP status code,
+while logging the full error to the App Engine developer console for debugging
+purposes.
+</p>
+
+<p>
+To do this we create an <code>appError</code> struct containing an
+<code>error</code> and some other fields:
+</p>
+
+<pre><!--{{code "progs/error4.go" `/type appError/` `/STOP/`}}
+-->type appError struct {
+    Error   error
+    Message string
+    Code    int
+}</pre>
+
+<p>
+Next we modify the appHandler type to return <code>*appError</code> values:
+</p>
+
+<pre><!--{{code "progs/error4.go" `/type appHandler/`}}
+-->type appHandler func(http.ResponseWriter, *http.Request) *appError</pre>
+
+<p>
+(It's usually a mistake to pass back the concrete type of an error rather than
+<code>error</code>, for reasons to be discussed in another article, but
+it's the right thing to do here because <code>ServeHTTP</code> is the only
+place that sees the value and uses its contents.)
+</p>
+
+<p>
+And make <code>appHandler</code>'s <code>ServeHTTP</code> method display the
+<code>appError</code>'s <code>Message</code> to the user with the correct HTTP
+status <code>Code</code> and log the full <code>Error</code> to the developer
+console:
+</p>
+
+<pre><!--{{code "progs/error4.go" `/ServeHTTP/` `/STOP/`}}
+-->func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+    if e := fn(w, r); e != nil { // e is *appError, not os.Error.
+        c := appengine.NewContext(r)
+        c.Errorf("%v", e.Error)
+        http.Error(w, e.Message, e.Code)
+    }
+}</pre>
+
+<p>
+Finally, we update <code>viewRecord</code> to the new function signature and
+have it return more context when it encounters an error: 
+</p>
+
+<pre><!--{{code "progs/error4.go" `/func viewRecord/` `/STOP/`}}
+-->func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
+    c := appengine.NewContext(r)
+    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
+    record := new(Record)
+    if err := datastore.Get(c, key, record); err != nil {
+        return &appError{err, "Record not found", 404}
+    }
+    if err := viewTemplate.Execute(w, record); err != nil {
+        return &appError{err, "Can't display record", 500}
+    }
+    return nil
+}</pre>
+
+<p>
+This version of <code>viewRecord</code> is the same length as the original, but
+now each of those lines has specific meaning and we are providing a friendlier
+user experience.
+</p>
+
+<p>
+It doesn't end there; we can further improve the error handling in our
+application. Some ideas:
+</p>
+
+<ul>
+<li>give the error handler a pretty HTML template,
+<li>make debugging easier by writing the stack trace to the HTTP response when
+the user is an administrator,
+<li>write a constructor function for <code>appError</code> that stores the
+stack trace for easier debugging, 
+<li>recover from panics inside the <code>appHandler</code>, logging the error
+to the console as "Critical," while simply telling the user "a serious error
+has occurred." This is a nice touch to avoid exposing the user to inscrutable
+error messages caused by programming errors.
+See the <a href="defer_panic_recover.html">Defer, Panic, and Recover</a>
+article for more details.
+</ul>
+
+<p>
+<b>Conclusion</b>
+</p>
+
+<p>
+Proper error handling is an essential requirement of good software. By
+employing the techniques described in this post you should be able to write
+more reliable and succinct Go code.
+</p>
diff --git a/doc/articles/error_handling.tmpl b/doc/articles/error_handling.tmpl
new file mode 100644
index 0000000..141b4a5
--- /dev/null
+++ b/doc/articles/error_handling.tmpl
@@ -0,0 +1,314 @@
+<!--{
+	"Title": "Error Handling and Go"
+}-->
+{{donotedit}}
+<p>
+If you have written any Go code you have probably encountered the built-in
+<code>error</code> type. Go code uses <code>error</code> values to
+indicate an abnormal state. For example, the <code>os.Open</code> function
+returns a non-nil <code>error</code> value when it fails to open a file.
+</p>
+
+{{code "progs/error.go" `/func Open/`}}
+
+<p>
+The following code uses <code>os.Open</code> to open a file. If an error
+occurs it calls <code>log.Fatal</code> to print the error message and stop.
+</p>
+
+{{code "progs/error.go" `/func openFile/` `/STOP/`}}
+
+<p>
+You can get a lot done in Go knowing just this about the <code>error</code>
+type, but in this article we'll take a closer look at <code>error</code> and
+discuss some good practices for error handling in Go.
+</p>
+
+<p>
+<b>The error type</b>
+</p>
+
+<p>
+The <code>error</code> type is an interface type. An <code>error</code>
+variable represents any value that can describe itself as a string. Here is the
+interface's declaration:
+</p>
+
+<pre>type error interface {
+    Error() string
+}</pre>
+
+<p>
+The <code>error</code> type, as with all built in types, is
+<a href="/doc/go_spec.html#Predeclared_identifiers">predeclared</a> in the
+<a href="/doc/go_spec.html#Blocks">universe block</a>.
+</p>
+
+<p>
+The most commonly-used <code>error</code> implementation is the
+<a href="/pkg/errors/">errors</a> package's unexported <code>errorString</code> type.
+</p>
+
+{{code "progs/error.go" `/errorString/` `/STOP/`}}
+
+<p>
+You can construct one of these values with the <code>errors.New</code>
+function. It takes a string that it converts to an <code>errors.errorString</code>
+and returns as an <code>error</code> value.
+</p>
+
+{{code "progs/error.go" `/New/` `/STOP/`}}
+
+<p>
+Here's how you might use <code>errors.New</code>:
+</p>
+
+{{code "progs/error.go" `/func Sqrt/` `/STOP/`}}
+
+<p>
+A caller passing a negative argument to <code>Sqrt</code> receives a non-nil
+<code>error</code> value (whose concrete representation is an
+<code>errors.errorString</code> value). The caller can access the error string
+("math: square root of...") by calling the <code>error</code>'s
+<code>Error</code> method, or by just printing it:
+</p>
+
+{{code "progs/error.go" `/func printErr/` `/STOP/`}}
+
+<p>
+The <a href="/pkg/fmt/">fmt</a> package formats an <code>error</code> value
+by calling its <code>Error() string</code> method.
+</p>
+
+<p>
+It is the error implementation's responsibility to summarize the context.
+The error returned by <code>os.Open</code> formats as "open /etc/passwd:
+permission denied," not just "permission denied."  The error returned by our
+<code>Sqrt</code> is missing information about the invalid argument.
+</p>
+
+<p>
+To add that information, a useful function is the <code>fmt</code> package's
+<code>Errorf</code>. It formats a string according to <code>Printf</code>'s
+rules and returns it as an <code>error</code> created by
+<code>errors.New</code>.
+</p>
+
+{{code "progs/error.go" `/fmtError/` `/STOP/`}}
+
+<p>
+In many cases <code>fmt.Errorf</code> is good enough, but since
+<code>error</code> is an interface, you can use arbitrary data structures as
+error values, to allow callers to inspect the details of the error.
+</p>
+
+<p>
+For instance, our hypothetical callers might want to recover the invalid
+argument passed to <code>Sqrt</code>. We can enable that by defining a new
+error implementation instead of using <code>errors.errorString</code>:
+</p>
+
+{{code "progs/error.go" `/type NegativeSqrtError/` `/STOP/`}}
+
+<p>
+A sophisticated caller can then use a
+<a href="/doc/go_spec.html#Type_assertions">type assertion</a> to check for a
+<code>NegativeSqrtError</code> and handle it specially, while callers that just
+pass the error to <code>fmt.Println</code> or <code>log.Fatal</code> will see
+no change in behavior.
+</p>
+
+<p>
+As another example, the <a href="/pkg/encoding/json/">json</a> package specifies a
+<code>SyntaxError</code> type that the <code>json.Decode</code> function
+returns when it encounters a syntax error parsing a JSON blob.
+</p>
+
+{{code "progs/error.go" `/type SyntaxError/` `/STOP/`}}
+
+<p>
+The <code>Offset</code> field isn't even shown in the default formatting of the
+error, but callers can use it to add file and line information to their error
+messages:
+</p>
+
+{{code "progs/error.go" `/func decodeError/` `/STOP/`}}
+
+<p>
+(This is a slightly simplified version of some
+<a href="http://camlistore.org/code/?p=camlistore.git;a=blob;f=lib/go/camli/jsonconfig/eval.go#l68">actual code</a>
+from the <a href="http://camlistore.org">Camlistore</a> project.)
+</p>
+
+<p>
+The <code>error</code> interface requires only a <code>Error</code> method;
+specific error implementations might have additional methods. For instance, the
+<a href="/pkg/net/">net</a> package returns errors of type
+<code>error</code>, following the usual convention, but some of the error
+implementations have additional methods defined by the <code>net.Error</code>
+interface:
+</p>
+
+<pre>package net
+
+type Error interface {
+    error
+    Timeout() bool   // Is the error a timeout?
+    Temporary() bool // Is the error temporary?
+}</pre>
+
+<p>
+Client code can test for a <code>net.Error</code> with a type assertion and
+then distinguish transient network errors from permanent ones. For instance, a
+web crawler might sleep and retry when it encounters a temporary error and give
+up otherwise.
+</p>
+
+{{code "progs/error.go" `/func netError/` `/STOP/`}}
+
+<p>
+<b>Simplifying repetitive error handling</b>
+</p>
+
+<p>
+In Go, error handling is important. The language's design and conventions
+encourage you to explicitly check for errors where they occur (as distinct from
+the convention in other languages of throwing exceptions and sometimes catching
+them). In some cases this makes Go code verbose, but fortunately there are some
+techniques you can use to minimize repetitive error handling.
+</p>
+
+<p>
+Consider an <a href="http://code.google.com/appengine/docs/go/">App Engine</a>
+application with an HTTP handler that retrieves a record from the datastore and
+formats it with a template.
+</p>
+
+{{code "progs/error2.go" `/func init/` `/STOP/`}}
+
+<p>
+This function handles errors returned by the <code>datastore.Get</code>
+function and <code>viewTemplate</code>'s <code>Execute</code> method. In both
+cases, it presents a simple error message to the user with the HTTP status code
+500 ("Internal Server Error"). This looks like a manageable amount of code, but
+add some more HTTP handlers and you quickly end up with many copies of
+identical error handling code.
+</p>
+
+<p>
+To reduce the repetition we can define our own HTTP <code>appHandler</code>
+type that includes an <code>error</code> return value:
+</p>
+
+{{code "progs/error3.go" `/type appHandler/`}}
+
+<p>
+Then we can change our <code>viewRecord</code> function to return errors:
+</p>
+
+{{code "progs/error3.go" `/func viewRecord/` `/STOP/`}}
+
+<p>
+This is simpler than the original version, but the <a
+href="/pkg/net/http/">http</a> package doesn't understand functions that return
+<code>error</code>.
+To fix this we can implement the <code>http.Handler</code> interface's
+<code>ServeHTTP</code> method on <code>appHandler</code>:
+</p>
+
+{{code "progs/error3.go" `/ServeHTTP/` `/STOP/`}}
+
+<p>
+The <code>ServeHTTP</code> method calls the <code>appHandler</code> function
+and displays the returned error (if any) to the user.  Notice that the method's
+receiver, <code>fn</code>, is a function. (Go can do that!) The method invokes
+the function by calling the receiver in the expression <code>fn(w, r)</code>.
+</p>
+
+<p>
+Now when registering <code>viewRecord</code> with the http package we use the
+<code>Handle</code> function (instead of <code>HandleFunc</code>) as
+<code>appHandler</code> is an <code>http.Handler</code> (not an
+<code>http.HandlerFunc</code>). 
+</p>
+
+{{code "progs/error3.go" `/func init/` `/STOP/`}}
+
+<p>
+With this basic error handling infrastructure in place, we can make it more
+user friendly. Rather than just displaying the error string, it would be better
+to give the user a simple error message with an appropriate HTTP status code,
+while logging the full error to the App Engine developer console for debugging
+purposes.
+</p>
+
+<p>
+To do this we create an <code>appError</code> struct containing an
+<code>error</code> and some other fields:
+</p>
+
+{{code "progs/error4.go" `/type appError/` `/STOP/`}}
+
+<p>
+Next we modify the appHandler type to return <code>*appError</code> values:
+</p>
+
+{{code "progs/error4.go" `/type appHandler/`}}
+
+<p>
+(It's usually a mistake to pass back the concrete type of an error rather than
+<code>error</code>, for reasons to be discussed in another article, but
+it's the right thing to do here because <code>ServeHTTP</code> is the only
+place that sees the value and uses its contents.)
+</p>
+
+<p>
+And make <code>appHandler</code>'s <code>ServeHTTP</code> method display the
+<code>appError</code>'s <code>Message</code> to the user with the correct HTTP
+status <code>Code</code> and log the full <code>Error</code> to the developer
+console:
+</p>
+
+{{code "progs/error4.go" `/ServeHTTP/` `/STOP/`}}
+
+<p>
+Finally, we update <code>viewRecord</code> to the new function signature and
+have it return more context when it encounters an error: 
+</p>
+
+{{code "progs/error4.go" `/func viewRecord/` `/STOP/`}}
+
+<p>
+This version of <code>viewRecord</code> is the same length as the original, but
+now each of those lines has specific meaning and we are providing a friendlier
+user experience.
+</p>
+
+<p>
+It doesn't end there; we can further improve the error handling in our
+application. Some ideas:
+</p>
+
+<ul>
+<li>give the error handler a pretty HTML template,
+<li>make debugging easier by writing the stack trace to the HTTP response when
+the user is an administrator,
+<li>write a constructor function for <code>appError</code> that stores the
+stack trace for easier debugging, 
+<li>recover from panics inside the <code>appHandler</code>, logging the error
+to the console as "Critical," while simply telling the user "a serious error
+has occurred." This is a nice touch to avoid exposing the user to inscrutable
+error messages caused by programming errors.
+See the <a href="defer_panic_recover.html">Defer, Panic, and Recover</a>
+article for more details.
+</ul>
+
+<p>
+<b>Conclusion</b>
+</p>
+
+<p>
+Proper error handling is an essential requirement of good software. By
+employing the techniques described in this post you should be able to write
+more reliable and succinct Go code.
+</p>
diff --git a/doc/articles/slice-1.png b/doc/articles/slice-1.png
new file mode 100644
index 0000000..ba465cf
Binary files /dev/null and b/doc/articles/slice-1.png differ
diff --git a/doc/articles/slice-2.png b/doc/articles/slice-2.png
new file mode 100644
index 0000000..a57581e
Binary files /dev/null and b/doc/articles/slice-2.png differ
diff --git a/doc/articles/slice-3.png b/doc/articles/slice-3.png
new file mode 100644
index 0000000..64ece5e
Binary files /dev/null and b/doc/articles/slice-3.png differ
diff --git a/doc/articles/slice-array.png b/doc/articles/slice-array.png
new file mode 100644
index 0000000..a533702
Binary files /dev/null and b/doc/articles/slice-array.png differ
diff --git a/doc/articles/slice-struct.png b/doc/articles/slice-struct.png
new file mode 100644
index 0000000..f9141fc
Binary files /dev/null and b/doc/articles/slice-struct.png differ
diff --git a/doc/articles/slices_usage_and_internals.html b/doc/articles/slices_usage_and_internals.html
new file mode 100644
index 0000000..c10dfe0
--- /dev/null
+++ b/doc/articles/slices_usage_and_internals.html
@@ -0,0 +1,479 @@
+<!--{
+	"Title": "Slices: usage and internals"
+}-->
+<!--
+  DO NOT EDIT: created by
+    tmpltohtml articles/slices_usage_and_internals.tmpl
+-->
+
+
+<p>
+Go's slice type provides a convenient and efficient means of working with
+sequences of typed data. Slices are analogous to arrays in other languages, but
+have some unusual properties. This article will look at what slices are and how
+they are used.
+</p>
+
+<p>
+<b>Arrays</b>
+</p>
+
+<p>
+The slice type is an abstraction built on top of Go's array type, and so to
+understand slices we must first understand arrays.
+</p>
+
+<p>
+An array type definition specifies a length and an element type. For example,
+the type <code>[4]int</code> represents an array of four integers. An array's
+size is fixed; its length is part of its type (<code>[4]int</code> and
+<code>[5]int</code> are distinct, incompatible types). Arrays can be indexed in
+the usual way, so the expression <code>s[n]</code> accesses the <i>n</i>th
+element:
+</p>
+
+<pre>
+var a [4]int
+a[0] = 1
+i := a[0]
+// i == 1
+</pre>
+
+<p>
+Arrays do not need to be initialized explicitly; the zero value of an array is
+a ready-to-use array whose elements are themselves zeroed:
+</p>
+
+<pre>
+// a[2] == 0, the zero value of the int type
+</pre>
+
+<p>
+The in-memory representation of <code>[4]int</code> is just four integer values laid out sequentially:
+</p>
+
+<p>
+<img src="slice-array.png">
+</p>
+
+<p>
+Go's arrays are values. An array variable denotes the entire array; it is not a
+pointer to the first array element (as would be the case in C).  This means
+that when you assign or pass around an array value you will make a copy of its
+contents. (To avoid the copy you could pass a <i>pointer</i> to the array, but
+then that's a pointer to an array, not an array.) One way to think about arrays
+is as a sort of struct but with indexed rather than named fields: a fixed-size
+composite value.
+</p>
+
+<p>
+An array literal can be specified like so:
+</p>
+
+<pre>
+b := [2]string{"Penn", "Teller"}
+</pre>
+
+<p>
+Or, you can have the compiler count the array elements for you:
+</p>
+
+<pre>
+b := [...]string{"Penn", "Teller"}
+</pre>
+
+<p>
+In both cases, the type of <code>b</code> is <code>[2]string</code>.
+</p>
+
+<p>
+<b>Slices</b>
+</p>
+
+<p>
+Arrays have their place, but they're a bit inflexible, so you don't see them
+too often in Go code. Slices, though, are everywhere. They build on arrays to
+provide great power and convenience.
+</p>
+
+<p>
+The type specification for a slice is <code>[]T</code>, where <code>T</code> is
+the type of the elements of the slice. Unlike an array type, a slice type has
+no specified length.
+</p>
+
+<p>
+A slice literal is declared just like an array literal, except you leave out
+the element count:
+</p>
+
+<pre>
+letters := []string{"a", "b", "c", "d"}
+</pre>
+
+<p>
+A slice can be created with the built-in function called <code>make</code>,
+which has the signature,
+</p>
+
+<pre>
+func make([]T, len, cap) []T
+</pre>
+
+<p>
+where T stands for the element type of the slice to be created. The
+<code>make</code> function takes a type, a length, and an optional capacity.
+When called, <code>make</code> allocates an array and returns a slice that
+refers to that array.
+</p>
+
+<pre>
+var s []byte
+s = make([]byte, 5, 5)
+// s == []byte{0, 0, 0, 0, 0}
+</pre>
+
+<p>
+When the capacity argument is omitted, it defaults to the specified length.
+Here's a more succinct version of the same code:
+</p>
+
+<pre>
+s := make([]byte, 5)
+</pre>
+
+<p>
+The length and capacity of a slice can be inspected using the built-in
+<code>len</code> and <code>cap</code> functions.
+</p>
+
+<pre>
+len(s) == 5
+cap(s) == 5
+</pre>
+
+<p>
+The next two sections discuss the relationship between length and capacity.
+</p>
+
+<p>
+The zero value of a slice is <code>nil</code>. The <code>len</code> and
+<code>cap</code> functions will both return 0 for a nil slice.
+</p>
+
+<p>
+A slice can also be formed by "slicing" an existing slice or array. Slicing is
+done by specifying a half-open range with two indices separated by a colon. For
+example, the expression <code>b[1:4]</code> creates a slice including elements
+1 through 3 of <code>b</code> (the indices of the resulting slice will be 0
+through 2).
+</p>
+
+<pre>
+b := []byte{'g', 'o', 'l', 'a', 'n', 'g'}
+// b[1:4] == []byte{'o', 'l', 'a'}, sharing the same storage as b
+</pre>
+
+<p>
+The start and end indices of a slice expression are optional; they default to zero and the slice's length respectively:
+</p>
+
+<pre>
+// b[:2] == []byte{'g', 'o'}
+// b[2:] == []byte{'l', 'a', 'n', 'g'}
+// b[:] == b
+</pre>
+
+<p>
+This is also the syntax to create a slice given an array:
+</p>
+
+<pre>
+x := [3]string{"Лайка", "Белка", "Стрелка"}
+s := x[:] // a slice referencing the storage of x
+</pre>
+
+<p>
+<b>Slice internals</b>
+</p>
+
+<p>
+A slice is a descriptor of an array segment. It consists of a pointer to the
+array, the length of the segment, and its capacity (the maximum length of the
+segment).
+</p>
+
+<p>
+<img src="slice-struct.png">
+</p>
+
+<p>
+Our variable <code>s</code>, created earlier by <code>make([]byte, 5)</code>,
+is structured like this:
+</p>
+
+<p>
+<img src="slice-1.png">
+</p>
+
+<p>
+The length is the number of elements referred to by the slice. The capacity is
+the number of elements in the underlying array (beginning at the element
+referred to by the slice pointer). The distinction between length and capacity
+will be made clear as we walk through the next few examples.
+</p>
+
+<p>
+As we slice <code>s</code>, observe the changes in the slice data structure and
+their relation to the underlying array:
+</p>
+
+<pre>
+s = s[2:4]
+</pre>
+
+<p>
+<img src="slice-2.png">
+</p>
+
+<p>
+Slicing does not copy the slice's data. It creates a new slice value that
+points to the original array. This makes slice operations as efficient as
+manipulating array indices. Therefore, modifying the <i>elements</i> (not the
+slice itself) of a re-slice modifies the elements of the original slice:
+</p>
+
+<pre>
+d := []byte{'r', 'o', 'a', 'd'}
+e := d[2:] 
+// e == []byte{'a', 'd'}
+e[1] == 'm'
+// e == []byte{'a', 'm'}
+// d == []byte{'r', 'o', 'a', 'm'}
+</pre>
+
+<p>
+Earlier we sliced <code>s</code> to a length shorter than its capacity. We can
+grow s to its capacity by slicing it again:
+</p>
+
+<pre>
+s = s[:cap(s)]
+</pre>
+
+<p>
+<img src="slice-3.png">
+</p>
+
+<p>
+A slice cannot be grown beyond its capacity. Attempting to do so will cause a
+runtime panic, just as when indexing outside the bounds of a slice or array.
+Similarly, slices cannot be re-sliced below zero to access earlier elements in
+the array.
+</p>
+
+<p>
+<b>Growing slices (the copy and append functions)</b>
+</p>
+
+<p>
+To increase the capacity of a slice one must create a new, larger slice and
+copy the contents of the original slice into it. This technique is how dynamic
+array implementations from other languages work behind the scenes. The next
+example doubles the capacity of <code>s</code> by making a new slice,
+<code>t</code>, copying the contents of <code>s</code> into <code>t</code>, and
+then assigning the slice value <code>t</code> to <code>s</code>:
+</p>
+
+<pre>
+t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
+for i := range s {
+        t[i] = s[i]
+}
+s = t
+</pre>
+
+<p>
+The looping piece of this common operation is made easier by the built-in copy
+function. As the name suggests, copy copies data from a source slice to a
+destination slice. It returns the number of elements copied.
+</p>
+
+<pre>
+func copy(dst, src []T) int
+</pre>
+
+<p>
+The <code>copy</code> function supports copying between slices of different
+lengths (it will copy only up to the smaller number of elements). In addition,
+<code>copy</code> can handle source and destination slices that share the same
+underlying array, handling overlapping slices correctly.
+</p>
+
+<p>
+Using <code>copy</code>, we can simplify the code snippet above:
+</p>
+
+<pre>
+t := make([]byte, len(s), (cap(s)+1)*2)
+copy(t, s)
+s = t
+</pre>
+
+<p>
+A common operation is to append data to the end of a slice. This function
+appends byte elements to a slice of bytes, growing the slice if necessary, and
+returns the updated slice value:
+</p>
+
+<pre><!--{{code "progs/slices.go" `/AppendByte/` `/STOP/`}}
+-->func AppendByte(slice []byte, data ...byte) []byte {
+    m := len(slice)
+    n := m + len(data)
+    if n > cap(slice) { // if necessary, reallocate
+        // allocate double what's needed, for future growth.
+        newSlice := make([]byte, (n+1)*2)
+        copy(newSlice, slice)
+        slice = newSlice
+    }
+    slice = slice[0:n]
+    copy(slice[m:n], data)
+    return slice
+}</pre>
+
+<p>
+One could use <code>AppendByte</code> like this:
+</p>
+
+<pre>
+p := []byte{2, 3, 5}
+p = AppendByte(p, 7, 11, 13)
+// p == []byte{2, 3, 5, 7, 11, 13}
+</pre>
+
+<p>
+Functions like <code>AppendByte</code> are useful because they offer complete
+control over the way the slice is grown. Depending on the characteristics of
+the program, it may be desirable to allocate in smaller or larger chunks, or to
+put a ceiling on the size of a reallocation.
+</p>
+
+<p>
+But most programs don't need complete control, so Go provides a built-in
+<code>append</code> function that's good for most purposes; it has the
+signature
+</p>
+
+<pre>
+func append(s []T, x ...T) []T 
+</pre>
+
+<p>
+The <code>append</code> function appends the elements <code>x</code> to the end
+of the slice <code>s</code>, and grows the slice if a greater capacity is
+needed.
+</p>
+
+<pre>
+a := make([]int, 1)
+// a == []int{0}
+a = append(a, 1, 2, 3)
+// a == []int{0, 1, 2, 3}
+</pre>
+
+<p>
+To append one slice to another, use <code>...</code> to expand the second
+argument to a list of arguments.
+</p>
+
+<pre>
+a := []string{"John", "Paul"}
+b := []string{"George", "Ringo", "Pete"}
+a = append(a, b...) // equivalent to "append(a, b[0], b[1], b[2])"
+// a == []string{"John", "Paul", "George", "Ringo", "Pete"}
+</pre>
+
+<p>
+Since the zero value of a slice (<code>nil</code>) acts like a zero-length
+slice, you can declare a slice variable and then append to it in a loop:
+</p>
+
+<pre><!--{{code "progs/slices.go" `/Filter/` `/STOP/`}}
+-->// Filter returns a new slice holding only
+// the elements of s that satisfy f()
+func Filter(s []int, fn func(int) bool) []int {
+    var p []int // == nil
+    for _, i := range s {
+        if fn(i) {
+            p = append(p, i)
+        }
+    }
+    return p
+}</pre>
+
+<p>
+<b>A possible "gotcha"</b>
+</p>
+
+<p>
+As mentioned earlier, re-slicing a slice doesn't make a copy of the underlying
+array. The full array will be kept in memory until it is no longer referenced.
+Occasionally this can cause the program to hold all the data in memory when
+only a small piece of it is needed.
+</p>
+
+<p>
+For example, this <code>FindDigits</code> function loads a file into memory and
+searches it for the first group of consecutive numeric digits, returning them
+as a new slice.
+</p>
+
+<pre><!--{{code "progs/slices.go" `/digit/` `/STOP/`}}
+-->var digitRegexp = regexp.MustCompile("[0-9]+")
+
+func FindDigits(filename string) []byte {
+    b, _ := ioutil.ReadFile(filename)
+    return digitRegexp.Find(b)
+}</pre>
+
+<p>
+This code behaves as advertised, but the returned <code>[]byte</code> points
+into an array containing the entire file. Since the slice references the
+original array, as long as the slice is kept around the garbage collector can't
+release the array; the few useful bytes of the file keep the entire contents in
+memory.
+</p>
+
+<p>
+To fix this problem one can copy the interesting data to a new slice before
+returning it:
+</p>
+
+<pre><!--{{code "progs/slices.go" `/CopyDigits/` `/STOP/`}}
+-->func CopyDigits(filename string) []byte {
+    b, _ := ioutil.ReadFile(filename)
+    b = digitRegexp.Find(b)
+    c := make([]byte, len(b))
+    copy(c, b)
+    return c
+}</pre>
+
+<p>
+A more concise version of this function could be constructed by using
+<code>append</code>. This is left as an exercise for the reader.
+</p>
+
+<p>
+<b>Further Reading</b>
+</p>
+
+<p>
+<a href="/doc/effective_go.html">Effective Go</a> contains an
+in-depth treatment of <a href="/doc/effective_go.html#slices">slices</a>
+and <a href="/doc/effective_go.html#arrays">arrays</a>, 
+and the Go <a href="/doc/go_spec.html">language specification</a>
+defines <a href="/doc/go_spec.html#Slice_types">slices</a> and their
+<a href="/doc/go_spec.html#Length_and_capacity">associated</a>
+<a href="/doc/go_spec.html#Making_slices_maps_and_channels">helper</a>
+<a href="/doc/go_spec.html#Appending_and_copying_slices">functions</a>.
+</p>
diff --git a/doc/articles/slices_usage_and_internals.tmpl b/doc/articles/slices_usage_and_internals.tmpl
new file mode 100644
index 0000000..d2f8fb7
--- /dev/null
+++ b/doc/articles/slices_usage_and_internals.tmpl
@@ -0,0 +1,438 @@
+<!--{
+	"Title": "Slices: usage and internals"
+}-->
+{{donotedit}}
+
+<p>
+Go's slice type provides a convenient and efficient means of working with
+sequences of typed data. Slices are analogous to arrays in other languages, but
+have some unusual properties. This article will look at what slices are and how
+they are used.
+</p>
+
+<p>
+<b>Arrays</b>
+</p>
+
+<p>
+The slice type is an abstraction built on top of Go's array type, and so to
+understand slices we must first understand arrays.
+</p>
+
+<p>
+An array type definition specifies a length and an element type. For example,
+the type <code>[4]int</code> represents an array of four integers. An array's
+size is fixed; its length is part of its type (<code>[4]int</code> and
+<code>[5]int</code> are distinct, incompatible types). Arrays can be indexed in
+the usual way, so the expression <code>s[n]</code> accesses the <i>n</i>th
+element:
+</p>
+
+<pre>
+var a [4]int
+a[0] = 1
+i := a[0]
+// i == 1
+</pre>
+
+<p>
+Arrays do not need to be initialized explicitly; the zero value of an array is
+a ready-to-use array whose elements are themselves zeroed:
+</p>
+
+<pre>
+// a[2] == 0, the zero value of the int type
+</pre>
+
+<p>
+The in-memory representation of <code>[4]int</code> is just four integer values laid out sequentially:
+</p>
+
+<p>
+<img src="slice-array.png">
+</p>
+
+<p>
+Go's arrays are values. An array variable denotes the entire array; it is not a
+pointer to the first array element (as would be the case in C).  This means
+that when you assign or pass around an array value you will make a copy of its
+contents. (To avoid the copy you could pass a <i>pointer</i> to the array, but
+then that's a pointer to an array, not an array.) One way to think about arrays
+is as a sort of struct but with indexed rather than named fields: a fixed-size
+composite value.
+</p>
+
+<p>
+An array literal can be specified like so:
+</p>
+
+<pre>
+b := [2]string{"Penn", "Teller"}
+</pre>
+
+<p>
+Or, you can have the compiler count the array elements for you:
+</p>
+
+<pre>
+b := [...]string{"Penn", "Teller"}
+</pre>
+
+<p>
+In both cases, the type of <code>b</code> is <code>[2]string</code>.
+</p>
+
+<p>
+<b>Slices</b>
+</p>
+
+<p>
+Arrays have their place, but they're a bit inflexible, so you don't see them
+too often in Go code. Slices, though, are everywhere. They build on arrays to
+provide great power and convenience.
+</p>
+
+<p>
+The type specification for a slice is <code>[]T</code>, where <code>T</code> is
+the type of the elements of the slice. Unlike an array type, a slice type has
+no specified length.
+</p>
+
+<p>
+A slice literal is declared just like an array literal, except you leave out
+the element count:
+</p>
+
+<pre>
+letters := []string{"a", "b", "c", "d"}
+</pre>
+
+<p>
+A slice can be created with the built-in function called <code>make</code>,
+which has the signature,
+</p>
+
+<pre>
+func make([]T, len, cap) []T
+</pre>
+
+<p>
+where T stands for the element type of the slice to be created. The
+<code>make</code> function takes a type, a length, and an optional capacity.
+When called, <code>make</code> allocates an array and returns a slice that
+refers to that array.
+</p>
+
+<pre>
+var s []byte
+s = make([]byte, 5, 5)
+// s == []byte{0, 0, 0, 0, 0}
+</pre>
+
+<p>
+When the capacity argument is omitted, it defaults to the specified length.
+Here's a more succinct version of the same code:
+</p>
+
+<pre>
+s := make([]byte, 5)
+</pre>
+
+<p>
+The length and capacity of a slice can be inspected using the built-in
+<code>len</code> and <code>cap</code> functions.
+</p>
+
+<pre>
+len(s) == 5
+cap(s) == 5
+</pre>
+
+<p>
+The next two sections discuss the relationship between length and capacity.
+</p>
+
+<p>
+The zero value of a slice is <code>nil</code>. The <code>len</code> and
+<code>cap</code> functions will both return 0 for a nil slice.
+</p>
+
+<p>
+A slice can also be formed by "slicing" an existing slice or array. Slicing is
+done by specifying a half-open range with two indices separated by a colon. For
+example, the expression <code>b[1:4]</code> creates a slice including elements
+1 through 3 of <code>b</code> (the indices of the resulting slice will be 0
+through 2).
+</p>
+
+<pre>
+b := []byte{'g', 'o', 'l', 'a', 'n', 'g'}
+// b[1:4] == []byte{'o', 'l', 'a'}, sharing the same storage as b
+</pre>
+
+<p>
+The start and end indices of a slice expression are optional; they default to zero and the slice's length respectively:
+</p>
+
+<pre>
+// b[:2] == []byte{'g', 'o'}
+// b[2:] == []byte{'l', 'a', 'n', 'g'}
+// b[:] == b
+</pre>
+
+<p>
+This is also the syntax to create a slice given an array:
+</p>
+
+<pre>
+x := [3]string{"Лайка", "Белка", "Стрелка"}
+s := x[:] // a slice referencing the storage of x
+</pre>
+
+<p>
+<b>Slice internals</b>
+</p>
+
+<p>
+A slice is a descriptor of an array segment. It consists of a pointer to the
+array, the length of the segment, and its capacity (the maximum length of the
+segment).
+</p>
+
+<p>
+<img src="slice-struct.png">
+</p>
+
+<p>
+Our variable <code>s</code>, created earlier by <code>make([]byte, 5)</code>,
+is structured like this:
+</p>
+
+<p>
+<img src="slice-1.png">
+</p>
+
+<p>
+The length is the number of elements referred to by the slice. The capacity is
+the number of elements in the underlying array (beginning at the element
+referred to by the slice pointer). The distinction between length and capacity
+will be made clear as we walk through the next few examples.
+</p>
+
+<p>
+As we slice <code>s</code>, observe the changes in the slice data structure and
+their relation to the underlying array:
+</p>
+
+<pre>
+s = s[2:4]
+</pre>
+
+<p>
+<img src="slice-2.png">
+</p>
+
+<p>
+Slicing does not copy the slice's data. It creates a new slice value that
+points to the original array. This makes slice operations as efficient as
+manipulating array indices. Therefore, modifying the <i>elements</i> (not the
+slice itself) of a re-slice modifies the elements of the original slice:
+</p>
+
+<pre>
+d := []byte{'r', 'o', 'a', 'd'}
+e := d[2:] 
+// e == []byte{'a', 'd'}
+e[1] == 'm'
+// e == []byte{'a', 'm'}
+// d == []byte{'r', 'o', 'a', 'm'}
+</pre>
+
+<p>
+Earlier we sliced <code>s</code> to a length shorter than its capacity. We can
+grow s to its capacity by slicing it again:
+</p>
+
+<pre>
+s = s[:cap(s)]
+</pre>
+
+<p>
+<img src="slice-3.png">
+</p>
+
+<p>
+A slice cannot be grown beyond its capacity. Attempting to do so will cause a
+runtime panic, just as when indexing outside the bounds of a slice or array.
+Similarly, slices cannot be re-sliced below zero to access earlier elements in
+the array.
+</p>
+
+<p>
+<b>Growing slices (the copy and append functions)</b>
+</p>
+
+<p>
+To increase the capacity of a slice one must create a new, larger slice and
+copy the contents of the original slice into it. This technique is how dynamic
+array implementations from other languages work behind the scenes. The next
+example doubles the capacity of <code>s</code> by making a new slice,
+<code>t</code>, copying the contents of <code>s</code> into <code>t</code>, and
+then assigning the slice value <code>t</code> to <code>s</code>:
+</p>
+
+<pre>
+t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
+for i := range s {
+        t[i] = s[i]
+}
+s = t
+</pre>
+
+<p>
+The looping piece of this common operation is made easier by the built-in copy
+function. As the name suggests, copy copies data from a source slice to a
+destination slice. It returns the number of elements copied.
+</p>
+
+<pre>
+func copy(dst, src []T) int
+</pre>
+
+<p>
+The <code>copy</code> function supports copying between slices of different
+lengths (it will copy only up to the smaller number of elements). In addition,
+<code>copy</code> can handle source and destination slices that share the same
+underlying array, handling overlapping slices correctly.
+</p>
+
+<p>
+Using <code>copy</code>, we can simplify the code snippet above:
+</p>
+
+<pre>
+t := make([]byte, len(s), (cap(s)+1)*2)
+copy(t, s)
+s = t
+</pre>
+
+<p>
+A common operation is to append data to the end of a slice. This function
+appends byte elements to a slice of bytes, growing the slice if necessary, and
+returns the updated slice value:
+</p>
+
+{{code "progs/slices.go" `/AppendByte/` `/STOP/`}}
+
+<p>
+One could use <code>AppendByte</code> like this:
+</p>
+
+<pre>
+p := []byte{2, 3, 5}
+p = AppendByte(p, 7, 11, 13)
+// p == []byte{2, 3, 5, 7, 11, 13}
+</pre>
+
+<p>
+Functions like <code>AppendByte</code> are useful because they offer complete
+control over the way the slice is grown. Depending on the characteristics of
+the program, it may be desirable to allocate in smaller or larger chunks, or to
+put a ceiling on the size of a reallocation.
+</p>
+
+<p>
+But most programs don't need complete control, so Go provides a built-in
+<code>append</code> function that's good for most purposes; it has the
+signature
+</p>
+
+<pre>
+func append(s []T, x ...T) []T 
+</pre>
+
+<p>
+The <code>append</code> function appends the elements <code>x</code> to the end
+of the slice <code>s</code>, and grows the slice if a greater capacity is
+needed.
+</p>
+
+<pre>
+a := make([]int, 1)
+// a == []int{0}
+a = append(a, 1, 2, 3)
+// a == []int{0, 1, 2, 3}
+</pre>
+
+<p>
+To append one slice to another, use <code>...</code> to expand the second
+argument to a list of arguments.
+</p>
+
+<pre>
+a := []string{"John", "Paul"}
+b := []string{"George", "Ringo", "Pete"}
+a = append(a, b...) // equivalent to "append(a, b[0], b[1], b[2])"
+// a == []string{"John", "Paul", "George", "Ringo", "Pete"}
+</pre>
+
+<p>
+Since the zero value of a slice (<code>nil</code>) acts like a zero-length
+slice, you can declare a slice variable and then append to it in a loop:
+</p>
+
+{{code "progs/slices.go" `/Filter/` `/STOP/`}}
+
+<p>
+<b>A possible "gotcha"</b>
+</p>
+
+<p>
+As mentioned earlier, re-slicing a slice doesn't make a copy of the underlying
+array. The full array will be kept in memory until it is no longer referenced.
+Occasionally this can cause the program to hold all the data in memory when
+only a small piece of it is needed.
+</p>
+
+<p>
+For example, this <code>FindDigits</code> function loads a file into memory and
+searches it for the first group of consecutive numeric digits, returning them
+as a new slice.
+</p>
+
+{{code "progs/slices.go" `/digit/` `/STOP/`}}
+
+<p>
+This code behaves as advertised, but the returned <code>[]byte</code> points
+into an array containing the entire file. Since the slice references the
+original array, as long as the slice is kept around the garbage collector can't
+release the array; the few useful bytes of the file keep the entire contents in
+memory.
+</p>
+
+<p>
+To fix this problem one can copy the interesting data to a new slice before
+returning it:
+</p>
+
+{{code "progs/slices.go" `/CopyDigits/` `/STOP/`}}
+
+<p>
+A more concise version of this function could be constructed by using
+<code>append</code>. This is left as an exercise for the reader.
+</p>
+
+<p>
+<b>Further Reading</b>
+</p>
+
+<p>
+<a href="/doc/effective_go.html">Effective Go</a> contains an
+in-depth treatment of <a href="/doc/effective_go.html#slices">slices</a>
+and <a href="/doc/effective_go.html#arrays">arrays</a>, 
+and the Go <a href="/doc/go_spec.html">language specification</a>
+defines <a href="/doc/go_spec.html#Slice_types">slices</a> and their
+<a href="/doc/go_spec.html#Length_and_capacity">associated</a>
+<a href="/doc/go_spec.html#Making_slices_maps_and_channels">helper</a>
+<a href="/doc/go_spec.html#Appending_and_copying_slices">functions</a>.
+</p>
diff --git a/doc/code.html b/doc/code.html
index cdc60b0..76d25e1 100644
--- a/doc/code.html
+++ b/doc/code.html
@@ -1,4 +1,6 @@
-<!-- How to Write Go Code -->
+<!--{
+	"Title": "How to Write Go Code"
+}-->
 
 <h2 id="Introduction">Introduction</h2>
 
@@ -45,120 +47,89 @@ that receives a message summarizing each checkin to the Go repository.
 
 <h2 id="New_package">Creating a new package</h2>
 
+<h3>Choosing an import path</h3>
+
 <p>
-The source code for the package with import path
-<code>x/y</code> is, by convention, kept in the
-directory <code>$GOROOT/src/pkg/x/y</code>.
+The standard packages are given short names like <code>fmt</code> and
+<code>net/http</code> for convenience.
+For your own projects, choose a name space that is unlikely
+to collide with future additions to the standard library or other
+external libraries.
 </p>
 
-<h3>Makefile</h3>
-
 <p>
-It would be nice to have Go-specific tools that
-inspect the source files to determine what to build and in
-what order, but for now, Go uses GNU <code>make</code>.
-Thus, the first file to create in a new package directory is
-usually the <code>Makefile</code>.
-The basic form used in the Go source tree
-is illustrated by <a href="../src/pkg/container/vector/Makefile"><code>src/pkg/container/vector/Makefile</code></a>:
+For instance, if your source repository is at <code>example.com</code> 
+or <code>code.google.com/p/example</code>, you should begin your package
+paths with that URL, as in "<code>example.com/foo/bar</code>" or
+"<code>code.google.com/p/example/foo/bar</code>".
+This way the <a href="/cmd/go/"><code>go</code> tool</a> can automatically
+check out and build the source code from its import path.
 </p>
 
-<pre>
-include ../../../Make.inc
-
-TARG=container/vector
-GOFILES=\
-	intvector.go\
-	stringvector.go\
-	vector.go\
-
-include ../../../Make.pkg
-</pre>
-
 <p>
-Outside the Go source tree (for personal packages), the standard form is
+If you don't intend your code to be installed in this way, you should at
+least use a unique prefix like "<code>widgets/</code>", as in
+"<code>widgets/foo/bar</code>". A good rule is to use a prefix such as your
+company or project name since it is unlikely to be used by another group.
 </p>
 
-<pre>
-include $(GOROOT)/src/Make.inc
-
-TARG=mypackage
-GOFILES=\
-	my1.go\
-	my2.go\
 
-include $(GOROOT)/src/Make.pkg
-</pre>
+<h3>The <code>go</code> tool and <code>GOPATH</code></h3>
 
 <p>
-The first and last lines <code>include</code> standard definitions and rules.
-Packages maintained in the standard Go tree use a relative path (instead of
-<code>$(GOROOT)/src</code>) so that <code>make</code> will work correctly
-even if <code>$(GOROOT)</code> contains spaces.
-This makes it easy for programmers to try Go.
+The <a href="/cmd/go/"><code>go</code> tool</a> is the standard means of
+building and installing Go libraries and programs. It is a "zero configuration"
+tool; it determines how to build Go packages from their source code alone.
 </p>
 
 <p>
-If you have not set <code>$GOROOT</code> in your environment,
-you must run <code>gomake</code> to use this form of makefile.
-<code>Gomake</code> also takes care to invoke GNU Make
-even on systems where it is installed as <code>gmake</code>
-rather than <code>make</code>.
+To use the <code>go</code> tool effectively you must set the
+<code>GOPATH</code> variable.
+<code>GOPATH</code> specifies a list of paths that contain Go source code
+and package binaries. Source code, package objects, and command binaries are
+located inside the <code>GOPATH</code>s' <code>src</code>, <code>pkg</code>,
+and <code>bin</code> subdirectories respectively.
 </p>
 
 <p>
-<code>TARG</code> is the target install path for the package,
-the string that clients will use to import it.
-Inside the Go tree, this string should be the same as the directory
-in which the <code>Makefile</code> appears, with the
-<code>$GOROOT/src/pkg/</code> prefix removed.
-Outside the Go tree, you can use any <code>TARG</code> you
-want that doesn't conflict with the standard Go package names.
-A common convention is to use an identifying top-level name
-to group your packages: <code>myname/tree</code>, <code>myname/filter</code>, etc.
-Note that even if you keep your package source outside the
-Go tree, running <code>make install</code> installs your
-package binaries in the standard location—<code>$GOROOT/pkg</code>—to
-make it easy to find them.
+You should set <code>GOPATH</code> in your shell profile
+(<code>$HOME/.bashrc</code>, <code>$HOME/.profile</code>, or equivalent).
 </p>
 
 <p>
-<code>GOFILES</code> is a list of source files to compile to
-create the package.  The trailing <code>\</code> characters
-allow the list to be split onto multiple lines
-for easy sorting.
+This shell session demonstrates setting <code>GOPATH</code>, creating a trivial
+<code>widgets/foo</code> package, and building and installing the package.
 </p>
 
-<p>
-If you create a new package directory in the Go tree, add it to the list in
-<code>$GOROOT/src/pkg/Makefile</code> so that it
-is included in the standard build.  Then run:
 <pre>
-cd $GOROOT/src/pkg
-./deps.bash
+$ export GOPATH=$HOME/gocode
+$ mkdir -p $GOPATH/src/widgets/foo
+$ cat > $GOPATH/src/widgets/foo/foo.go
+package foo
+const String = "Go rules!"
+^D
+$ go install widgets/foo
+$ ls $GOPATH/pkg/*/example
+foo.a
 </pre>
-<p>
-to update the dependency file <code>Make.deps</code>.
-(This happens automatically each time you run <code>all.bash</code>
-or <code>make.bash</code>.)
-</p>
+
+<p>(<code>^D</code> means to type Control-D.)</p>
 
 <p>
-If you change the imports of an existing package,
-you do not need to edit <code>$GOROOT/src/pkg/Makefile</code>
-but you will still need to run <code>deps.bash</code> as above.
+Type <code>go help gopath</code> on the command line for more information
+about <code>GOPATH</code>.
 </p>
 
 
 <h3>Go source files</h3>
 
 <p>
-The first statement in each of the source files listed in the <code>Makefile</code>
-should be <code>package <i>name</i></code>, where <code><i>name</i></code>
-is the package's default name for imports.
+The first statement in a Go source file should be <code>package
+<i>name</i></code>, where <code><i>name</i></code> is the package's default
+name for imports.
 (All files in a package must use the same <code><i>name</i></code>.)
 Go's convention is that the package name is the last element of the
-import path: the package imported as <code>"crypto/rot13"</code>
+import path: the package imported as "<code>crypto/rot13</code>"
 should be named <code>rot13</code>.
 There is no requirement that package names be unique
 across all packages linked into a single binary,
@@ -178,63 +149,81 @@ that topic.
 </p>
 
 <h2 id="Building_programs">Building programs</h2>
-<p>To build a Go program with gomake, create a Makefile alongside your program's
-source files. It should be similar to the example above, but include
-<code>Make.cmd</code> instead of <code>Make.pkg</code>:
+
+<p>
+The <a href="/cmd/go/"><code>go</code> tool</a> treats code belonging to
+<code>package main</code> as an executable command, and installs the package
+binary to the <code>GOPATH</code>'s <code>bin</code> subdirectory.
+</p>
+
+<p>
+Building executable commands is the same as building packages.
+Use "<code>go install</code>":
+</p>
 
 <pre>
-include $(GOROOT)/src/Make.inc
+$ cat > $GOPATH/src/widgets/bar/bar.go
+package main
 
-TARG=helloworld
-GOFILES=\
-	helloworld.go\
+import (
+    "fmt"
+    "widgets/foo"
+)
 
-include $(GOROOT)/src/Make.cmd
+func main() {
+    fmt.Println(foo.String)
+}
+^D
+$ go install widgets/bar
+$ $GOPATH/bin/bar
+Go rules!
 </pre>
 
-<p>Running <code>gomake</code> will compile <code>helloworld.go</code>
-and produce an executable named <code>helloworld</code> in the current
-directory.
-</p>
-
 <p>
-Running <code>gomake install</code> will build <code>helloworld</code> if
-necessary and copy it to the <code>$GOBIN</code> directory
-(<code>$GOROOT/bin/</code> is the default).
+Run <code>go help build</code> and <code>go help install</code> for more
+about building and installing Go binaries.
 </p>
 
 <h2 id="Testing">Testing</h2>
 
 <p>
-Go has a lightweight test framework known as <code>gotest</code>.
+Go has a lightweight test framework composed of the <code>go</code> tool and
+the <code>testing</code> package.
 You write a test by creating a file with a name ending in <code>_test.go</code>
-that contains functions named <code>TestXXX</code> with signature <code>func (t *testing.T)</code>.
+that contains functions named <code>TestXXX</code> with signature
+<code>func (t *testing.T)</code>.
 The test framework runs each such function;
-if the function calls a failure function such as <code>t.Error</code> or <code>t.Fail</code>, the test is considered to have failed.
-The <a href="/cmd/gotest/">gotest command documentation</a>
-and the <a href="/pkg/testing/">testing package documentation</a> give more detail.
+if the function calls a failure function such as <code>t.Error</code> or
+<code>t.Fail</code>, the test is considered to have failed.
+Run <code>go help test</code> and see the
+<a href="/pkg/testing/">testing package documentation</a> for more detail.
 </p>
 
 <p>
-The <code>*_test.go</code> files should not be listed in the <code>Makefile</code>.
+To run the test, run "<code>go test</code>":
 </p>
 
-<p>
-To run the test, run either <code>make test</code> or <code>gotest</code>
-(they are equivalent).
-To run only the tests in a single test file, for instance <code>one_test.go</code>,
-run <code>gotest one_test.go</code>.
-</p>
+<pre>
+$ cat > $GOPATH/src/widgets/foo/foo_test.go
+package foo
 
-<p>
-If your change affects performance, add a <code>Benchmark</code> function 
-(see the <a href="/cmd/gotest/">gotest command documentation</a>)
-and run it using <code>gotest -test.bench=.</code>.
-</p>
+import "testing"
+
+func TestString(t *testing.T) {
+    const expect = "Go rules!"
+    if String != expect {
+        t.Errorf("String == %q, want %q", String, expect)
+    }
+}
+^D
+$ go test widgets/foo
+ok  	widgets/foo
+</pre>
 
 <p>
-Once your new code is tested and working,
-it's time to get it <a href="contribute.html">reviewed and submitted</a>.
+If your change affects performance, add a <code>Benchmark</code> function 
+(run <code>go help testfunc</code>) and run it using <code>go test
+-test.bench=.*</code>.
 </p>
 
 <h2 id="pkg_example">An example package with tests</h2>
@@ -242,7 +231,7 @@ it's time to get it <a href="contribute.html">reviewed and submitted</a>.
 <p>
 This example package, <code>numbers</code>, consists of the function
 <code>Double</code>, which takes an <code>int</code> and returns that value 
-multiplied by 2. It consists of three files.
+multiplied by 2. It consists of two files.
 </p>
 
 <p>
@@ -289,38 +278,24 @@ func TestDouble(t *testing.T) {
 </pre>
 
 <p>
-Finally, the <code>Makefile</code>:
-</p>
-
-<pre>
-include $(GOROOT)/src/Make.inc
-
-TARG=numbers
-GOFILES=\
-	numbers.go\
-
-include $(GOROOT)/src/Make.pkg
-</pre>
-
-<p>
-Running <code>gomake install</code> will build and install the package to
-the <code>$GOROOT/pkg/</code> directory (it can then be used by any
-program on the system).
+Running <code>go install</code> will build and install the package to
+the <code>GOPATH</code>'s <code>pkg</code> directory
+(it can then be imported by any other Go program).
 </p>
 
 <p>
-Running <code>gomake test</code> (or just running the command
-<code>gotest</code>) will rebuild the package, including the
+Running <code>go test</code> will rebuild the package, including the
 <code>numbers_test.go</code> file, and then run the <code>TestDouble</code>
-function. The output "<code>PASS</code>" indicates that all tests passed
+function. The output "<code>ok</code>" indicates that all tests passed
 successfully.  Breaking the implementation by changing the multiplier from
 <code>2</code> to <code>3</code> will allow you to see how failing tests are 
 reported.
 </p>
 
 <p>
-See the <a href="/cmd/gotest/">gotest documentation</a> and the 
-<a href="/pkg/testing/">testing package</a> for more detail.
+Run <code>go help test</code>, <code>go help testfunc</code>,
+and <code>go help testflag</code> and see the
+<a href="/pkg/testing/">testing package documentation</a> for more detail.
 </p>
 
 <h2 id="arch_os_specific">Architecture- and operating system-specific code</h2>
@@ -335,34 +310,34 @@ different operating systems.</p>
 
 <p>To compile such code, use the <code>$GOOS</code> and <code>$GOARCH</code>
 <a href="/doc/install.html#environment">environment variables</a> in your
-source file names and <code>Makefile</code>.</p>
+source file names.</p>
 
-<p>For example, this <code>Makefile</code> describes a package that builds on
-different operating systems by parameterizing the file name with
-<code>$GOOS</code>.</p>
+<p>For example, consider the package <code>foo</code> that consists of four
+files:</p>
 
 <pre>
-include $(GOROOT)/src/Make.inc
-
-TARG=mypackage
-GOFILES=\
-	my.go\
-	my_$(GOOS).go\
-
-include $(GOROOT)/src/Make.pkg
+foo.go
+foo_386.go
+foo_amd64.go
+foo_arm.go
 </pre>
 
-<p>The OS-specific code goes in <code>my_linux.go</code>,
-<code>my_darwin.go</code>, and so on.</p>
+describes a package that builds on
+different operating systems by parameterizing the file name with
+<code>$GOOS</code>.</p>
+
+<p>The general code goes in <code>foo.go</code>, while architecture-specific
+code goes in <code>foo_386.go</code>, <code>foo_amd64.go</code>, and
+<code>foo_arm.go</code>.</p>
 
-<p>If you follow these conventional parameterizations, tools such as
-<a href="/cmd/goinstall/">goinstall</a> will work seamlessly with your package:
-</p>
+<p>If you follow these conventional parameterizations, tools such as the <a
+href="/cmd/go/"><code>go</code> tool</a> will work seamlessly with your
+package:</p>
 
 <pre>
-my_$(GOOS).go
-my_$(GOARCH).go
-my_$(GOOS)_$(GOARCH).go
+foo_$GOOS.go
+foo_$GOARCH.go
+foo_$GOOS_$GOARCH.go
 </pre>
 
-<p>The same holds for <code>.s</code> (assembly) files.</p>
+<p>The same holds for <code>.s</code> (assembly) and <code>.c</code> files.</p>
diff --git a/doc/codelab/wiki/Makefile b/doc/codelab/wiki/Makefile
index 32dc1a1..233917f 100644
--- a/doc/codelab/wiki/Makefile
+++ b/doc/codelab/wiki/Makefile
@@ -8,7 +8,7 @@ all: index.html
 
 include ../../../src/Make.common
 
-CLEANFILES+=index.html srcextract.bin htmlify.bin get.bin
+CLEANFILES+=srcextract.bin htmlify.bin get.bin
 
 index.html: wiki.html srcextract.bin htmlify.bin
 	PATH=.:$$PATH awk '/^!/{system(substr($$0,2)); next} {print}' < wiki.html | tr -d '\r' > index.html
@@ -21,5 +21,5 @@ test: get.bin
 	$(LD) -o $@ $<
 
 %.$O: %.go
-	$(GC) $*.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) $*.go
 
diff --git a/doc/codelab/wiki/final-noclosure.go b/doc/codelab/wiki/final-noclosure.go
index 067f502..a0428d4 100644
--- a/doc/codelab/wiki/final-noclosure.go
+++ b/doc/codelab/wiki/final-noclosure.go
@@ -1,11 +1,15 @@
+// Copyright 2010 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 (
-	"http"
+	"errors"
 	"io/ioutil"
-	"os"
+	"net/http"
 	"regexp"
-	"template"
+	"text/template"
 )
 
 type Page struct {
@@ -13,12 +17,12 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
@@ -61,21 +65,21 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
 	p := &Page{Title: title, Body: []byte(body)}
 	err = p.save()
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	http.Redirect(w, r, "/view/"+title, http.StatusFound)
 }
 
 func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
-	t, err := template.ParseFile(tmpl+".html")
+	t, err := template.ParseFiles(tmpl + ".html")
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	err = t.Execute(w, p)
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 	}
 }
 
@@ -83,11 +87,11 @@ const lenPath = len("/view/")
 
 var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$")
 
-func getTitle(w http.ResponseWriter, r *http.Request) (title string, err os.Error) {
+func getTitle(w http.ResponseWriter, r *http.Request) (title string, err error) {
 	title = r.URL.Path[lenPath:]
 	if !titleValidator.MatchString(title) {
 		http.NotFound(w, r)
-		err = os.NewError("Invalid Page Title")
+		err = errors.New("Invalid Page Title")
 	}
 	return
 }
diff --git a/doc/codelab/wiki/final-noerror.go b/doc/codelab/wiki/final-noerror.go
index b8edbee..e86bc1a 100644
--- a/doc/codelab/wiki/final-noerror.go
+++ b/doc/codelab/wiki/final-noerror.go
@@ -1,10 +1,13 @@
+// Copyright 2010 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 (
-	"http"
 	"io/ioutil"
-	"os"
-	"template"
+	"net/http"
+	"text/template"
 )
 
 type Page struct {
@@ -12,12 +15,12 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
@@ -34,14 +37,14 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
 	if err != nil {
 		p = &Page{Title: title}
 	}
-	t, _ := template.ParseFile("edit.html")
+	t, _ := template.ParseFiles("edit.html")
 	t.Execute(w, p)
 }
 
 func viewHandler(w http.ResponseWriter, r *http.Request) {
 	title := r.URL.Path[lenPath:]
 	p, _ := loadPage(title)
-	t, _ := template.ParseFile("view.html")
+	t, _ := template.ParseFiles("view.html")
 	t.Execute(w, p)
 }
 
diff --git a/doc/codelab/wiki/final-parsetemplate.go b/doc/codelab/wiki/final-parsetemplate.go
index f25012e..c068a61 100644
--- a/doc/codelab/wiki/final-parsetemplate.go
+++ b/doc/codelab/wiki/final-parsetemplate.go
@@ -1,11 +1,14 @@
+// Copyright 2010 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 (
-	"http"
 	"io/ioutil"
-	"os"
+	"net/http"
 	"regexp"
-	"template"
+	"text/template"
 )
 
 type Page struct {
@@ -13,12 +16,12 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
@@ -49,21 +52,21 @@ func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
 	p := &Page{Title: title, Body: []byte(body)}
 	err := p.save()
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	http.Redirect(w, r, "/view/"+title, http.StatusFound)
 }
 
 func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
-	t, err := template.ParseFile(tmpl+".html", nil)
+	t, err := template.ParseFiles(tmpl+".html", nil)
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	err = t.Execute(w, p)
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 	}
 }
 
diff --git a/doc/codelab/wiki/final-template.go b/doc/codelab/wiki/final-template.go
index aab536e..5386210 100644
--- a/doc/codelab/wiki/final-template.go
+++ b/doc/codelab/wiki/final-template.go
@@ -1,10 +1,13 @@
+// Copyright 2010 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 (
-	"http"
 	"io/ioutil"
-	"os"
-	"template"
+	"net/http"
+	"text/template"
 )
 
 type Page struct {
@@ -12,12 +15,12 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
@@ -52,7 +55,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
-	t, _ := template.ParseFile(tmpl+".html", nil)
+	t, _ := template.ParseFiles(tmpl+".html", nil)
 	t.Execute(w, p)
 }
 
diff --git a/doc/codelab/wiki/final.go b/doc/codelab/wiki/final.go
index 47a4c34..97f0a16 100644
--- a/doc/codelab/wiki/final.go
+++ b/doc/codelab/wiki/final.go
@@ -1,11 +1,14 @@
+// Copyright 2010 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 (
-	"http"
 	"io/ioutil"
-	"os"
+	"net/http"
 	"regexp"
-	"template"
+	"text/template"
 )
 
 type Page struct {
@@ -13,12 +16,12 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
@@ -49,7 +52,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
 	p := &Page{Title: title, Body: []byte(body)}
 	err := p.save()
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	http.Redirect(w, r, "/view/"+title, http.StatusFound)
@@ -59,7 +62,7 @@ var templates = make(map[string]*template.Template)
 
 func init() {
 	for _, tmpl := range []string{"edit", "view"} {
-		t := template.Must(template.ParseFile(tmpl+".html"))
+		t := template.Must(template.ParseFiles(tmpl + ".html"))
 		templates[tmpl] = t
 	}
 }
@@ -67,7 +70,7 @@ func init() {
 func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
 	err := templates[tmpl].Execute(w, p)
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 	}
 }
 
diff --git a/doc/codelab/wiki/get.go b/doc/codelab/wiki/get.go
index c36684e..c6e9bf2 100644
--- a/doc/codelab/wiki/get.go
+++ b/doc/codelab/wiki/get.go
@@ -1,12 +1,16 @@
+// Copyright 2011 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 (
-	"http"
 	"flag"
 	"fmt"
 	"io"
 	"log"
 	"net"
+	"net/http"
 	"os"
 	"strings"
 )
@@ -32,7 +36,7 @@ func main() {
 		log.Fatal("no url supplied")
 	}
 	var r *http.Response
-	var err os.Error
+	var err error
 	if *post != "" {
 		b := strings.NewReader(*post)
 		r, err = http.Post(url, "application/x-www-form-urlencoded", b)
diff --git a/doc/codelab/wiki/htmlify.go b/doc/codelab/wiki/htmlify.go
index 9e7605b..2a845a1 100644
--- a/doc/codelab/wiki/htmlify.go
+++ b/doc/codelab/wiki/htmlify.go
@@ -1,9 +1,13 @@
+// Copyright 2010 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 (
-	"template"
-	"os"
 	"io/ioutil"
+	"os"
+	"text/template"
 )
 
 func main() {
diff --git a/doc/codelab/wiki/http-sample.go b/doc/codelab/wiki/http-sample.go
index 33379a1..ac8cc4f 100644
--- a/doc/codelab/wiki/http-sample.go
+++ b/doc/codelab/wiki/http-sample.go
@@ -2,7 +2,7 @@ package main
 
 import (
 	"fmt"
-	"http"
+	"net/http"
 )
 
 func handler(w http.ResponseWriter, r *http.Request) {
diff --git a/doc/codelab/wiki/index.html b/doc/codelab/wiki/index.html
index 50e9db5..ae71a40 100644
--- a/doc/codelab/wiki/index.html
+++ b/doc/codelab/wiki/index.html
@@ -98,7 +98,7 @@ But what about persistent storage? We can address that by creating a
 </p>
 
 <pre>
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
@@ -107,7 +107,7 @@ func (p *Page) save() os.Error {
 <p>
 This method's signature reads: "This is a method named <code>save</code> that
 takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes
-no parameters, and returns a value of type <code>os.Error</code>." 
+no parameters, and returns a value of type <code>error</code>." 
 </p>
 
 <p>
@@ -116,7 +116,7 @@ file. For simplicity, we will use the <code>Title</code> as the file name.
 </p>
 
 <p>
-The <code>save</code> method returns an <code>os.Error</code> value because
+The <code>save</code> method returns an <code>error</code> value because
 that is the return type of <code>WriteFile</code> (a standard library function
 that writes a byte slice to a file).  The <code>save</code> method returns the
 error value, to let the application handle it should anything go wrong while
@@ -152,7 +152,7 @@ The function <code>loadPage</code> constructs the file name from
 
 <p>
 Functions can return multiple values. The standard library function 
-<code>io.ReadFile</code> returns <code>[]byte</code> and <code>os.Error</code>. 
+<code>io.ReadFile</code> returns <code>[]byte</code> and <code>error</code>. 
 In <code>loadPage</code>, error isn't being handled yet; the "blank identifier"
 represented by the underscore (<code>_</code>) symbol is used to throw away the
 error return value (in essence, assigning the value to nothing). 
@@ -161,11 +161,11 @@ error return value (in essence, assigning the value to nothing).
 <p>
 But what happens if <code>ReadFile</code> encounters an error?  For example,
 the file might not exist. We should not ignore such errors.  Let's modify the
-function to return <code>*Page</code> and <code>os.Error</code>.
+function to return <code>*Page</code> and <code>error</code>.
 </p>
 
 <pre>
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
@@ -178,7 +178,7 @@ func loadPage(title string) (*Page, os.Error) {
 <p>
 Callers of this function can now check the second parameter; if it is
 <code>nil</code> then it has successfully loaded a Page. If not, it will be an
-<code>os.Error</code> that can be handled by the caller (see the <a
+<code>error</code> that can be handled by the caller (see the <a
 href="http://golang.org/pkg/os/#Error">os package documentation</a> for 
 details).
 </p>
@@ -237,7 +237,7 @@ package main
 
 import (
 	"fmt"
-	"http"
+	"net/http"
 )
 
 func handler(w http.ResponseWriter, r *http.Request) {
@@ -337,7 +337,7 @@ HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>.
 </p>
 
 <p>
-Again, note the use of <code>_</code> to ignore the <code>os.Error</code> 
+Again, note the use of <code>_</code> to ignore the <code>error</code> 
 return value from <code>loadPage</code>. This is done here for simplicity
 and generally considered bad practice. We will attend to this later.
 </p>
@@ -476,7 +476,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
 	if err != nil {
 		p = &Page{Title: title}
 	}
-	t, _ := template.ParseFile("edit.html")
+	t, _ := template.ParseFiles("edit.html")
 	t.Execute(w, p)
 }
 </pre>
@@ -530,7 +530,7 @@ Modify <code>viewHandler</code> accordingly:
 func viewHandler(w http.ResponseWriter, r *http.Request) {
 	title := r.URL.Path[lenPath:]
 	p, _ := loadPage(title)
-	t, _ := template.ParseFile("view.html")
+	t, _ := template.ParseFiles("view.html")
 	t.Execute(w, p)
 }
 </pre>
@@ -558,7 +558,7 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
-	t, _ := template.ParseFile(tmpl+".html", nil)
+	t, _ := template.ParseFiles(tmpl+".html", nil)
 	t.Execute(w, p)
 }
 </pre>
@@ -643,14 +643,14 @@ First, let's handle the errors in <code>renderTemplate</code>:
 
 <pre>
 func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
-	t, err := template.ParseFile(tmpl+".html", nil)
+	t, err := template.ParseFiles(tmpl+".html", nil)
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	err = t.Execute(w, p)
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 	}
 }
 </pre>
@@ -675,7 +675,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
 	p := &Page{Title: title, Body: []byte(body)}
 	err = p.save()
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	http.Redirect(w, r, "/view/"+title, http.StatusFound)
@@ -711,7 +711,7 @@ var templates = make(map[string]*template.Template)
 Then we create an <code>init</code> function, which will be called before
 <code>main</code> at program initialization. The function
 <code>template.Must</code> is a convenience wrapper that panics when passed a
-non-nil <code>os.Error</code> value, and otherwise returns the
+non-nil <code>error</code> value, and otherwise returns the
 <code>*Template</code> unaltered. A panic is appropriate here; if the templates
 can't be loaded the only sensible thing to do is exit the program.
 </p>
@@ -719,7 +719,7 @@ can't be loaded the only sensible thing to do is exit the program.
 <pre>
 func init() {
 	for _, tmpl := range []string{"edit", "view"} {
-		t := template.Must(template.ParseFile(tmpl + ".html"))
+		t := template.Must(template.ParseFiles(tmpl + ".html"))
 		templates[tmpl] = t
 	}
 }
@@ -741,7 +741,7 @@ the <code>Execute</code> method on the appropriate <code>Template</code> from
 func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
 	err := templates[tmpl].Execute(w, p)
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 	}
 }
 </pre>
@@ -768,7 +768,7 @@ The function <code>regexp.MustCompile</code> will parse and compile the
 regular expression, and return a <code>regexp.Regexp</code>. 
 <code>MustCompile</code> is distinct from <code>Compile</code> in that it will
 panic if the expression compilation fails, while <code>Compile</code> returns
-an <code>os.Error</code> as a second parameter. 
+an <code>error</code> as a second parameter. 
 </p>
 
 <p>
@@ -777,11 +777,11 @@ URL, and tests it against our <code>TitleValidator</code> expression:
 </p>
 
 <pre>
-func getTitle(w http.ResponseWriter, r *http.Request) (title string, err os.Error) {
+func getTitle(w http.ResponseWriter, r *http.Request) (title string, err error) {
 	title = r.URL.Path[lenPath:]
 	if !titleValidator.MatchString(title) {
 		http.NotFound(w, r)
-		err = os.NewError("Invalid Page Title")
+		err = errors.New("Invalid Page Title")
 	}
 	return
 }
@@ -833,7 +833,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) {
 	p := &Page{Title: title, Body: []byte(body)}
 	err = p.save()
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	http.Redirect(w, r, "/view/"+title, http.StatusFound)
@@ -958,7 +958,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
 	p := &Page{Title: title, Body: []byte(body)}
 	err := p.save()
 	if err != nil {
-		http.Error(w, err.String(), http.StatusInternalServerError)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
 	http.Redirect(w, r, "/view/"+title, http.StatusFound)
diff --git a/doc/codelab/wiki/notemplate.go b/doc/codelab/wiki/notemplate.go
index 9cbe9ad..33006ac 100644
--- a/doc/codelab/wiki/notemplate.go
+++ b/doc/codelab/wiki/notemplate.go
@@ -1,10 +1,13 @@
+// Copyright 2010 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"
-	"http"
 	"io/ioutil"
-	"os"
+	"net/http"
 )
 
 type Page struct {
@@ -12,12 +15,12 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
diff --git a/doc/codelab/wiki/part1-noerror.go b/doc/codelab/wiki/part1-noerror.go
index 14cfc32..7577b7b 100644
--- a/doc/codelab/wiki/part1-noerror.go
+++ b/doc/codelab/wiki/part1-noerror.go
@@ -1,9 +1,12 @@
+// Copyright 2010 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"
 	"io/ioutil"
-	"os"
 )
 
 type Page struct {
@@ -11,7 +14,7 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
diff --git a/doc/codelab/wiki/part1.go b/doc/codelab/wiki/part1.go
index 4b0654f..d7bf1be 100644
--- a/doc/codelab/wiki/part1.go
+++ b/doc/codelab/wiki/part1.go
@@ -1,9 +1,12 @@
+// Copyright 2010 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"
 	"io/ioutil"
-	"os"
 )
 
 type Page struct {
@@ -11,12 +14,12 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
diff --git a/doc/codelab/wiki/part2.go b/doc/codelab/wiki/part2.go
index d57c3a0..dd4365c 100644
--- a/doc/codelab/wiki/part2.go
+++ b/doc/codelab/wiki/part2.go
@@ -1,10 +1,13 @@
+// Copyright 2010 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"
-	"http"
 	"io/ioutil"
-	"os"
+	"net/http"
 )
 
 type Page struct {
@@ -12,12 +15,12 @@ type Page struct {
 	Body  []byte
 }
 
-func (p *Page) save() os.Error {
+func (p *Page) save() error {
 	filename := p.Title + ".txt"
 	return ioutil.WriteFile(filename, p.Body, 0600)
 }
 
-func loadPage(title string) (*Page, os.Error) {
+func loadPage(title string) (*Page, error) {
 	filename := title + ".txt"
 	body, err := ioutil.ReadFile(filename)
 	if err != nil {
diff --git a/doc/codelab/wiki/srcextract.go b/doc/codelab/wiki/srcextract.go
index 6b5fbcb..813e252 100644
--- a/doc/codelab/wiki/srcextract.go
+++ b/doc/codelab/wiki/srcextract.go
@@ -1,15 +1,19 @@
+// Copyright 2010 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 (
 	"bytes"
 	"flag"
+	"go/ast"
 	"go/parser"
 	"go/printer"
-	"go/ast"
 	"go/token"
 	"log"
-	"template"
 	"os"
+	"text/template"
 )
 
 var (
diff --git a/doc/codelab/wiki/wiki.html b/doc/codelab/wiki/wiki.html
index 634babd..c3dee3f 100644
--- a/doc/codelab/wiki/wiki.html
+++ b/doc/codelab/wiki/wiki.html
@@ -101,7 +101,7 @@ But what about persistent storage? We can address that by creating a
 <p>
 This method's signature reads: "This is a method named <code>save</code> that
 takes as its receiver <code>p</code>, a pointer to <code>Page</code> . It takes
-no parameters, and returns a value of type <code>os.Error</code>." 
+no parameters, and returns a value of type <code>error</code>." 
 </p>
 
 <p>
@@ -110,7 +110,7 @@ file. For simplicity, we will use the <code>Title</code> as the file name.
 </p>
 
 <p>
-The <code>save</code> method returns an <code>os.Error</code> value because
+The <code>save</code> method returns an <code>error</code> value because
 that is the return type of <code>WriteFile</code> (a standard library function
 that writes a byte slice to a file).  The <code>save</code> method returns the
 error value, to let the application handle it should anything go wrong while
@@ -142,7 +142,7 @@ The function <code>loadPage</code> constructs the file name from
 
 <p>
 Functions can return multiple values. The standard library function 
-<code>io.ReadFile</code> returns <code>[]byte</code> and <code>os.Error</code>. 
+<code>io.ReadFile</code> returns <code>[]byte</code> and <code>error</code>. 
 In <code>loadPage</code>, error isn't being handled yet; the "blank identifier"
 represented by the underscore (<code>_</code>) symbol is used to throw away the
 error return value (in essence, assigning the value to nothing). 
@@ -151,7 +151,7 @@ error return value (in essence, assigning the value to nothing).
 <p>
 But what happens if <code>ReadFile</code> encounters an error?  For example,
 the file might not exist. We should not ignore such errors.  Let's modify the
-function to return <code>*Page</code> and <code>os.Error</code>.
+function to return <code>*Page</code> and <code>error</code>.
 </p>
 
 <pre>
@@ -161,7 +161,7 @@ function to return <code>*Page</code> and <code>os.Error</code>.
 <p>
 Callers of this function can now check the second parameter; if it is
 <code>nil</code> then it has successfully loaded a Page. If not, it will be an
-<code>os.Error</code> that can be handled by the caller (see the <a
+<code>error</code> that can be handled by the caller (see the <a
 href="http://golang.org/pkg/os/#Error">os package documentation</a> for 
 details).
 </p>
@@ -297,7 +297,7 @@ HTML, and writes it to <code>w</code>, the <code>http.ResponseWriter</code>.
 </p>
 
 <p>
-Again, note the use of <code>_</code> to ignore the <code>os.Error</code> 
+Again, note the use of <code>_</code> to ignore the <code>error</code> 
 return value from <code>loadPage</code>. This is done here for simplicity
 and generally considered bad practice. We will attend to this later.
 </p>
@@ -575,7 +575,7 @@ our <code>*Template</code> values, keyed by <code>string</code>
 Then we create an <code>init</code> function, which will be called before
 <code>main</code> at program initialization. The function
 <code>template.Must</code> is a convenience wrapper that panics when passed a
-non-nil <code>os.Error</code> value, and otherwise returns the
+non-nil <code>error</code> value, and otherwise returns the
 <code>*Template</code> unaltered. A panic is appropriate here; if the templates
 can't be loaded the only sensible thing to do is exit the program.
 </p>
@@ -622,7 +622,7 @@ The function <code>regexp.MustCompile</code> will parse and compile the
 regular expression, and return a <code>regexp.Regexp</code>. 
 <code>MustCompile</code> is distinct from <code>Compile</code> in that it will
 panic if the expression compilation fails, while <code>Compile</code> returns
-an <code>os.Error</code> as a second parameter. 
+an <code>error</code> as a second parameter. 
 </p>
 
 <p>
diff --git a/doc/codereview_with_mq.html b/doc/codereview_with_mq.html
index 33f415f..38ecbda 100644
--- a/doc/codereview_with_mq.html
+++ b/doc/codereview_with_mq.html
@@ -1,4 +1,6 @@
-<!-- Using Mercurial Queues with Codereview -->
+<!--{
+	"Title": "Using Mercurial Queues with Codereview"
+}-->
 
 <h2 id="Introduction">Introduction</h2>
 
diff --git a/doc/codewalk/functions.xml b/doc/codewalk/functions.xml
index 986a017..db518dc 100644
--- a/doc/codewalk/functions.xml
+++ b/doc/codewalk/functions.xml
@@ -45,7 +45,7 @@
   turn.
 </step>
 
-<step title="Multiple return values" src="doc/codewalk/pig.go:/\/\/ roll returns/,/stay.*true\n}/">
+<step title="Multiple return values" src="doc/codewalk/pig.go:/\/\/ roll returns/,/true\n}/">
 	Go functions can return multiple values.  
 	<br/><br/>
 
@@ -82,16 +82,6 @@
   associated with the current player.
 </step>
 
-<step title="Comparing functions" src="doc/codewalk/pig.go:/if action/,/currentPlayer\)\)\n\t\t}/">
-	Functions can be compared for equality in Go.  From the 
-	<a href="http://golang.org/doc/go_spec.html#Comparison_operators">language specification</a>:
-  Function values are equal if they refer to the same function or if both are <code>nil</code>.
-	<br/><br/>
-
-  We enforce that a <code>strategy</code> function can only return a legal
-  <code>action</code>: either <code>roll</code> or <code>stay</code>.
-</step>
-
 <step title="Simulating a tournament" src="doc/codewalk/pig.go:/\/\/ roundRobin/,/gamesPerStrategy\n}/">
 	The <code>roundRobin</code> function simulates a tournament and tallies wins.
 	Each strategy plays each other strategy <code>gamesPerSeries</code> times.
diff --git a/doc/codewalk/markov.go b/doc/codewalk/markov.go
index 959c2b1..cb28eb0 100644
--- a/doc/codewalk/markov.go
+++ b/doc/codewalk/markov.go
@@ -50,8 +50,8 @@ import (
 	"flag"
 	"fmt"
 	"io"
+	"math/rand"
 	"os"
-	"rand"
 	"strings"
 	"time"
 )
diff --git a/doc/codewalk/markov.xml b/doc/codewalk/markov.xml
index a89b4d0..81df128 100644
--- a/doc/codewalk/markov.xml
+++ b/doc/codewalk/markov.xml
@@ -105,7 +105,7 @@ Prefix               Map key
 	reads space-separated values from an <code>io.Reader</code>.
 	<br/><br/>
 	The <code>Build</code> method returns once the <code>Reader</code>'s
-	<code>Read</code> method returns <code>os.EOF</code> (end of file)
+	<code>Read</code> method returns <code>io.EOF</code> (end of file)
 	or some other read error occurs.
 </step>
 
@@ -133,7 +133,7 @@ Prefix               Map key
 	(including punctuation), which is exactly what we need.
 	<br/><br/>
 	<code>Fscan</code> returns an error if it encounters a read error
-	(<code>os.EOF</code>, for example) or if it can't scan the requested
+	(<code>io.EOF</code>, for example) or if it can't scan the requested
 	value (in our case, a single string). In either case we just want to
 	stop scanning, so we <code>break</code> out of the loop.
 </step>
diff --git a/doc/codewalk/pig.go b/doc/codewalk/pig.go
index 9e415f5..10963b4 100644
--- a/doc/codewalk/pig.go
+++ b/doc/codewalk/pig.go
@@ -6,7 +6,7 @@ package main
 
 import (
 	"fmt"
-	"rand"
+	"math/rand"
 )
 
 const (
@@ -61,9 +61,6 @@ func play(strategy0, strategy1 strategy) int {
 	currentPlayer := rand.Intn(2) // Randomly decide who plays first
 	for s.player+s.thisTurn < win {
 		action := strategies[currentPlayer](s)
-		if action != roll && action != stay {
-			panic(fmt.Sprintf("Player %d is cheating", currentPlayer))
-		}
 		s, turnIsOver = action(s)
 		if turnIsOver {
 			currentPlayer = (currentPlayer + 1) % 2
diff --git a/doc/codewalk/urlpoll.go b/doc/codewalk/urlpoll.go
index b51be95..e716c7e 100644
--- a/doc/codewalk/urlpoll.go
+++ b/doc/codewalk/urlpoll.go
@@ -5,17 +5,16 @@
 package main
 
 import (
-	"http"
 	"log"
+	"net/http"
 	"time"
 )
 
 const (
-	numPollers     = 2           // number of Poller goroutines to launch
-	second         = 1e9         // one second is 1e9 nanoseconds
-	pollInterval   = 60 * second // how often to poll each URL
-	statusInterval = 10 * second // how often to log status to stdout
-	errTimeout     = 10 * second // back-off timeout on error
+	numPollers     = 2                // number of Poller goroutines to launch
+	pollInterval   = 60 * time.Second // how often to poll each URL
+	statusInterval = 10 * time.Second // how often to log status to stdout
+	errTimeout     = 10 * time.Second // back-off timeout on error
 )
 
 var urls = []string{
@@ -33,7 +32,7 @@ type State struct {
 // StateMonitor maintains a map that stores the state of the URLs being
 // polled, and prints the current state every updateInterval nanoseconds.
 // It returns a chan State to which resource state should be sent.
-func StateMonitor(updateInterval int64) chan<- State {
+func StateMonitor(updateInterval time.Duration) chan<- State {
 	updates := make(chan State)
 	urlStatus := make(map[string]string)
 	ticker := time.NewTicker(updateInterval)
@@ -61,7 +60,7 @@ func logState(s map[string]string) {
 // Resource represents an HTTP URL to be polled by this program.
 type Resource struct {
 	url      string
-	errCount int64
+	errCount int
 }
 
 // Poll executes an HTTP HEAD request for url
@@ -71,7 +70,7 @@ func (r *Resource) Poll() string {
 	if err != nil {
 		log.Println("Error", r.url, err)
 		r.errCount++
-		return err.String()
+		return err.Error()
 	}
 	r.errCount = 0
 	return resp.Status
@@ -79,8 +78,8 @@ func (r *Resource) Poll() string {
 
 // Sleep sleeps for an appropriate interval (dependant on error state)
 // before sending the Resource to done.
-func (r *Resource) Sleep(done chan *Resource) {
-	time.Sleep(pollInterval + errTimeout*r.errCount)
+func (r *Resource) Sleep(done chan<- *Resource) {
+	time.Sleep(pollInterval + errTimeout*time.Duration(r.errCount))
 	done <- r
 }
 
@@ -93,18 +92,18 @@ func Poller(in <-chan *Resource, out chan<- *Resource, status chan<- State) {
 }
 
 func main() {
-	// create our input and output channels
+	// Create our input and output channels.
 	pending, complete := make(chan *Resource), make(chan *Resource)
 
-	// launch the StateMonitor
+	// Launch the StateMonitor.
 	status := StateMonitor(statusInterval)
 
-	// launch some Poller goroutines
+	// Launch some Poller goroutines.
 	for i := 0; i < numPollers; i++ {
 		go Poller(pending, complete, status)
 	}
 
-	// send some Resources to the pending queue
+	// Send some Resources to the pending queue.
 	go func() {
 		for _, url := range urls {
 			pending <- &Resource{url: url}
diff --git a/doc/community.html b/doc/community.html
index c3b16ca..aee731e 100644
--- a/doc/community.html
+++ b/doc/community.html
@@ -1,4 +1,6 @@
-<!-- title Community -->
+<!--{
+	"Title": "Community"
+}-->
 
 <div class="left-column">
 
diff --git a/doc/contrib.html b/doc/contrib.html
index 84d2cda..3ef7d56 100644
--- a/doc/contrib.html
+++ b/doc/contrib.html
@@ -1,4 +1,6 @@
-<!-- title Contributing -->
+<!--{
+	"Title": "Contributing"
+}-->
 
 <div class="left-column">
 
@@ -41,7 +43,7 @@ are particularly in need of outside help.
 
 <h2 id="the_go_project">The Go Project</h2>
 
-<h3 id="build_status"><a href="http://godashboard.appspot.com/">Build Status</a></h3>
+<h3 id="build_status"><a href="http://build.golang.org/">Build Status</a></h3>
 <p>View the status of Go builds across the supported operating
 systems and architectures.</p>
 
diff --git a/doc/contribute.html b/doc/contribute.html
index c4b1ce2..5af9af4 100644
--- a/doc/contribute.html
+++ b/doc/contribute.html
@@ -1,4 +1,6 @@
-<!-- Contribution Guidelines -->
+<!--{
+	"Title": "Contribution Guidelines"
+}-->
 
 <h2 id="Introduction">Introduction</h2>
 
@@ -210,10 +212,10 @@ to this change, and the <code>CC</code> line lists people to
 notify about the change.
 These can be code review nicknames or arbitrary email addresses.
 Unless explicitly told otherwise, such as in the discussion leading
-up to sending in the change list, set the
-reviewer field to the
+up to sending in the change list, leave the reviewer field blank.
+This means that the
 <a href="http://groups.google.com/group/golang-dev">golang-dev at googlegroups.com</a>
-mailing list.
+mailing list will be used as the reviewer.
 </p>
 
 <p>
@@ -523,7 +525,7 @@ This rigmarole needs to be done only for your first submission.
 <p>Code that you contribute should use the standard copyright header:</p>
 
 <pre>
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 </pre>
diff --git a/doc/debugging_with_gdb.html b/doc/debugging_with_gdb.html
new file mode 100644
index 0000000..d5c1a88
--- /dev/null
+++ b/doc/debugging_with_gdb.html
@@ -0,0 +1,481 @@
+<!--{
+	"Title": "Debugging Go Code with GDB"
+}-->
+
+<p><i>
+This applies to the 6g toolchain. Gccgo has native gdb support. Besides this
+overview you might want to consult the
+<a href="http://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>.
+</i></p>
+
+<h2 id="Introduction">Introduction</h2>
+
+<p>
+When you compile and link your Go programs with the 6g/6l or 8g/8l toolchains
+on Linux, Mac OSX or FreeBSD, the resulting binaries contain DWARFv3
+debugging information that recent versions (>7.1) of the GDB debugger can
+use to inspect a live process or a core dump.
+</p>
+
+<p>
+Pass the <code>'-s'</code> flag to the linker to omit the debug information.
+</p>
+
+
+<h3 id="Common_Operations">Common Operations</h3>
+
+<ul>
+<li>
+Show file and line number for code 
+and set breakpoints:
+<pre>(gdb) <b>list</b>
+(gdb) <b>list <i>line</i></b>
+(gdb) <b>list <i>file.go</i>:<i>line</i></b>
+(gdb) <b>break <i>line</i></b>
+(gdb) <b>break <i>file.go</i>:<i>line</i></b>
+(gdb) <b>disas</b></pre>
+</li>
+<li>
+Unwind stack frames:
+<pre>(gdb) <b>bt</b>
+(gdb) <b>frame <i>n</i></b></pre>
+</li>
+<li>
+Show the name, type and location on the stack frame of local variables,
+arguments and return values:
+<pre>(gdb) <b>info locals</b>
+(gdb) <b>info args</b>
+(gdb) <b>p variable</b>
+(gdb) <b>whatis variable</b></pre>
+</li>
+<li>
+Show the name, type and location of global variables:
+<pre>(gdb) <b>info variables <i>regexp</i></b></pre>
+</li>
+</ul>
+
+
+<h3 id="Go_Extensions">Go Extensions</h3>
+
+<p>
+A recent extension mechanism to GDB allows it to load extension scripts for a
+given binary. The tool chain uses this to extend GDB with a handful of
+commands to inspect internals of the runtime code (such as goroutines) and to
+pretty print the built-in map, slice and channel types.
+</p>
+
+<ul>
+<li>
+Pretty printing a string, slice, map, channel or interface:
+<pre>(gdb) <b>p <i>var</i></b></pre>
+</li>
+<li>
+A $len() and $cap() function for strings, slices and maps:
+<pre>(gdb) <b>p $len(<i>var</i>)</b></pre>
+</li>
+<li>
+A function to cast interfaces to their dynamic types:
+<pre>(gdb) <b>p $dtype(<i>var</i>)</b>
+(gdb) <b>iface <i>var</i></b></pre>
+<p class="detail"><b>Known issue:</b> GDB can’t automatically find the dynamic
+type of an interface value if its long name differs from its short name
+(annoying when printing stacktraces, the pretty printer falls back to printing
+the short type name and a pointer).</p>
+</li>
+<li>
+Inspecting goroutines:
+<pre>(gdb) <b>info goroutines</b>
+(gdb) <b>goroutine <i>n</i> <i>cmd</i></b>
+(gdb) <b>help goroutine</b></pre>
+For example:
+<pre>(gdb) <b>goroutine 12 bt</b></pre>
+</li>
+</ul>
+
+<p>
+If you'd like to see how this works, or want to extend it, take a look at <a
+href="/src/pkg/runtime/runtime-gdb.py">src/pkg/runtime/runtime-gdb.py</a> in
+the Go source distribution. It depends on some special magic types
+(<code>hash<T,U></code>) and variables (<code>runtime.m</code> and
+<code>runtime.g</code>) that the linker
+(<a href="/src/cmd/ld/dwarf.c">src/cmd/ld/dwarf.c</a>) ensures are described in
+the DWARF code.
+</ines
+
+<p>
+If you're interested in what the debugging information looks like, run
+'<code>objdump -W 6.out</code>' and browse through the <code>.debug_*</code>
+sections.
+</p>
+
+
+<h3 id="Known_Issues">Known Issues</h3>
+
+<ol>
+<li>String pretty printing only triggers for type string, not for types derived
+from it.</li>
+<li>Type information is missing for the C parts of the runtime library.</li>
+<li>GDB does not understand Go’s name qualifications and treats
+<code>"fmt.Print"</code> as an unstructured literal with a <code>"."</code>
+that needs to be quoted.  It objects even more strongly to method names of
+the form <code>pkg.(*MyType).Meth</code>.
+<li>All global variables are lumped into package <code>"main"</code>.</li>
+</ol>
+
+<h2 id="Tutorial">Tutorial</h2>
+
+<p>
+In this tutorial we will inspect the binary of the
+<a href="/pkg/regexp/">regexp</a> package's unit tests. To build the binary,
+change to <code>$GOROOT/src/pkg/regexp</code> and run <code>gotest</code>.
+This should produce an executable file named <code>6.out</code>.
+</p>
+
+
+<h3 id="Getting_Started">Getting Started</h3>
+
+<p>
+Launch GDB, debugging <code>6.out</code>:
+</p>
+
+<pre>
+$ <b>gdb 6.out</b>
+GNU gdb (GDB) 7.2-gg8
+Copyright (C) 2010 Free Software Foundation, Inc.
+License GPLv  3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+Type "show copying" and "show warranty" for licensing/warranty details.
+This GDB was configured as "x86_64-linux".
+
+Reading symbols from  /home/user/go/src/pkg/regexp/6.out...
+done.
+Loading Go Runtime support.
+(gdb) 
+</pre>
+
+<p>
+The message <code>"Loading Go Runtime support"</code> means that GDB loaded the
+extension from <code>$GOROOT/src/pkg/runtime/runtime-gdb.py</code>.
+</p>
+
+<p>
+To help GDB find the Go runtime sources and the accompanying support script,
+pass your <code>$GOROOT</code> with the <code>'-d'</code> flag:
+</p>
+
+<pre>
+$ <b>gdb 6.out -d $GOROOT</b>
+</pre>
+
+<p>
+If for some reason GDB still can't find that directory or that script, you can load
+it by hand by telling gdb (assuming you have the go sources in
+<code>~/go/</code>):
+<p>
+
+<pre>
+(gdb) <b>source ~/go/src/pkg/runtime/runtime-gdb.py</b>
+Loading Go Runtime support.
+</pre>
+
+<h3 id="Inspecting_the_source">Inspecting the source</h3>
+
+<p>
+Use the <code>"l"</code> or <code>"list"</code> command to inspect source code.
+</p>
+
+<pre>
+(gdb) <b>l</b>
+</pre>
+
+<p>
+List a specific part of the source parametrizing <code>"list"</code> with a
+function name (it must be qualified with its package name).
+</p>
+
+<pre>
+(gdb) <b>l main.main</b>
+</pre>
+
+<p>
+List a specific file and line number:
+</p>
+
+<pre>
+(gdb) <b>l regexp.go:1</b>
+(gdb) <i># Hit enter to repeat last command. Here, this lists next 10 lines.</i>
+</pre>
+
+
+<h3 id="Naming">Naming</h3>
+
+<p>
+Variable and function names must be qualified with the name of the packages
+they belong to. The <code>Compile</code> function from the <code>regexp</code>
+package is known to GDB as <code>'regexp.Compile'</code>. 
+</p>
+
+<p>
+Methods must be qualified with the name of their receiver types. For example,
+the <code>*Regexp</code> type’s <code>doParse</code> method is known as
+<code>'regexp.*Regexp.doParse'</code>. (Note that the second dot is a "middot,"
+an artifact of Go’s internal representation of methods.)
+</p>
+
+<p>
+Variables that shadow other variables are magically suffixed with a number in the debug info.
+Variables referenced by closures will appear as pointers magically prefixed with '&amp'.
+</p>
+
+<h3 id="Setting_breakpoints">Setting breakpoints</h3>
+
+<p>
+Set a breakpoint at the <code>TestFind</code> function:
+</p>
+
+<pre>
+(gdb) <b>b 'regexp.TestFind'</b>
+Breakpoint 1 at 0x424908: file /home/user/go/src/pkg/regexp/find_test.go, line 148.
+</pre>
+
+<p>
+Run the program:
+</p>
+
+<pre>
+(gdb) <b>run</b>
+Starting program: /home/lvd/g/src/pkg/regexp/6.out 
+
+Breakpoint 1, regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
+148	func TestFind(t *testing.T) {
+</pre>
+
+<p>
+Execution has paused at the breakpoint.
+See which goroutines are running, and what they're doing:
+</p>
+
+<pre>
+(gdb) <b>info goroutines</b>
+  1  waiting runtime.gosched
+* 13  running runtime.goexit
+</pre>
+
+<p>
+the one marked with the <code>*</code> is the current goroutine.
+</p>
+
+<h3 id="Inspecting_the_stack">Inspecting the stack</h3>
+
+<p>
+Look at the stack trace for where we’ve paused the program:
+</p>
+
+<pre>
+(gdb) <b>bt</b>  <i># backtrace</i>
+#0  regexp.TestFind (t=0xf8404a89c0) at /home/user/go/src/pkg/regexp/find_test.go:148
+#1  0x000000000042f60b in testing.tRunner (t=0xf8404a89c0, test=0x573720) at /home/user/go/src/pkg/testing/testing.go:156
+#2  0x000000000040df64 in runtime.initdone () at /home/user/go/src/pkg/runtime/proc.c:242
+#3  0x000000f8404a89c0 in ?? ()
+#4  0x0000000000573720 in ?? ()
+#5  0x0000000000000000 in ?? ()
+</pre>
+
+<p>
+The other goroutine, number 1, is stuck in <code>runtime.gosched</code>, blocked on a channel receive:
+</p>
+
+<pre>
+(gdb) <b>goroutine 1 bt</b>
+#0  0x000000000040facb in runtime.gosched () at /home/lvd/g/src/pkg/runtime/proc.c:873
+#1  0x00000000004031c9 in runtime.chanrecv (c=void, ep=void, selected=void, received=void)
+ at  /home/lvd/g/src/pkg/runtime/chan.c:342
+#2  0x0000000000403299 in runtime.chanrecv1 (t=void, c=void) at/home/lvd/g/src/pkg/runtime/chan.c:423
+#3  0x000000000043075b in testing.RunTests (matchString={void (struct string, struct string, bool *, error *)} 0x7ffff7f9ef60, tests=  []testing.InternalTest = {...}) at /home/lvd/g/src/pkg/testing/testing.go:201
+#4  0x00000000004302b1 in testing.Main (matchString={void (struct string, struct string, bool *, error *)} 0x7ffff7f9ef80, tests= []testing.InternalTest = {...}, benchmarks= []testing.InternalBenchmark = {...})
+    at /home/lvd/g/src/pkg/testing/testing.go:168
+#5  0x0000000000400dc1 in main.main () at /home/lvd/g/src/pkg/regexp/_testmain.go:98
+#6  0x00000000004022e7 in runtime.mainstart () at /home/lvd/g/src/pkg/runtime/amd64/asm.s:78
+#7  0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243
+#8  0x0000000000000000 in ?? ()
+</pre>
+
+<p>
+The stack frame shows we’re currently executing the <code>regexp.TestFind</code> function, as expected.
+</p>
+
+<pre>
+(gdb) <b>info frame</b>
+Stack level 0, frame at 0x7ffff7f9ff88:
+ rip = 0x425530 in regexp.TestFind (/home/lvd/g/src/pkg/regexp/find_test.go:148); 
+    saved rip 0x430233
+ called by frame at 0x7ffff7f9ffa8
+ source language minimal.
+ Arglist at 0x7ffff7f9ff78, args: t=0xf840688b60
+ Locals at 0x7ffff7f9ff78, Previous frame's sp is 0x7ffff7f9ff88
+ Saved registers:
+  rip at 0x7ffff7f9ff80
+</pre>
+
+<p>
+The command <code>info locals</code> lists all variables local to the function and their values, but is a bit
+dangerous to use, since it will also try to print uninitialized variables. Uninitialized slices may cause gdb to try
+to print arbitrary large arrays.
+</p>
+
+<p>
+The function’s arguments:
+</p>
+
+<pre>
+(gdb) <b>info args</b>
+t = 0xf840688b60
+</pre>
+
+<p>
+When printing the argument, notice that it’s a pointer to a
+<code>Regexp</code> value. Note that GDB has incorrectly put the <code>*</code>
+on the right-hand side of the type name and made up a 'struct' keyword, in traditional C style.
+</p>
+
+<pre>
+(gdb) <b>p re</b>
+(gdb) p t
+$1 = (struct testing.T *) 0xf840688b60
+(gdb) p t
+$1 = (struct testing.T *) 0xf840688b60
+(gdb) p *t
+$2 = {errors = "", failed = false, ch = 0xf8406f5690}
+(gdb) p *t->ch
+$3 = struct hchan<*testing.T>
+</pre>
+
+<p>
+That <code>struct hchan<*testing.T></code> is the runtime-internal represntation of a channel.  It is currently empty, or gdb would have pretty-printed it's contents.
+</p>
+
+<p>
+Stepping forward:
+</p>
+
+<pre>
+(gdb) <b>n</b>  <i># execute next line</i>
+149             for _, test := range findTests {
+(gdb)    <i># enter is repeat</i>
+150                     re := MustCompile(test.pat)
+(gdb) <b>p test.pat</b>
+$4 = ""
+(gdb) <b>p re</b>
+$5 = (struct regexp.Regexp *) 0xf84068d070
+(gdb) <b>p *re</b>
+$6 = {expr = "", prog = 0xf840688b80, prefix = "", prefixBytes =  []uint8, prefixComplete = true, 
+  prefixRune = 0, cond = 0 '\000', numSubexp = 0, longest = false, mu = {state = 0, sema = 0}, 
+  machine =  []*regexp.machine}
+(gdb) <b>p *re->prog</b>
+$7 = {Inst =  []regexp/syntax.Inst = {{Op = 5 '\005', Out = 0, Arg = 0, Rune =  []int}, {Op = 
+    6 '\006', Out = 2, Arg = 0, Rune =  []int}, {Op = 4 '\004', Out = 0, Arg = 0, Rune =  []int}}, 
+  Start = 1, NumCap = 2}
+</pre>
+
+
+<p>
+We can step into the <code>String</code>function call with <code>"s"</code>:
+</p>
+
+<pre>
+(gdb) <b>s</b>
+regexp.(*Regexp).String (re=0xf84068d070, noname=void) at /home/lvd/g/src/pkg/regexp/regexp.go:97
+97      func (re *Regexp) String() string {
+</pre>
+
+<p>
+Get a stack trace to see where we are:
+</p>
+
+<pre>
+(gdb) <b>bt</b>
+(gdb) bt
+#0  regexp.(*Regexp).String (re=0xf84068d070, noname=void)
+    at /home/lvd/g/src/pkg/regexp/regexp.go:97
+#1  0x0000000000425615 in regexp.TestFind (t=0xf840688b60)
+    at /home/lvd/g/src/pkg/regexp/find_test.go:151
+#2  0x0000000000430233 in testing.tRunner (t=0xf840688b60, test=0x5747b8)
+    at /home/lvd/g/src/pkg/testing/testing.go:156
+#3  0x000000000040ea6f in runtime.initdone () at /home/lvd/g/src/pkg/runtime/proc.c:243
+....
+</pre>
+
+<p>
+Look at the source code:
+</p>
+
+<pre>
+(gdb) <b>l</b>
+92              mu      sync.Mutex
+93              machine []*machine
+94      }
+95
+96      // String returns the source text used to compile the regular expression.
+97      func (re *Regexp) String() string {
+98              return re.expr
+99      }
+100
+101     // Compile parses a regular expression and returns, if successful,
+</pre>
+
+<h3 id="Pretty_Printing">Pretty Printing</h3>
+
+<p>
+GDB's pretty printing mechanism is triggered by regexp matches on type names.  An example for slices:
+</p>
+
+<pre>
+(gdb) <b>p utf</b>
+$22 =  []uint8 = {0 '\000', 0 '\000', 0 '\000', 0 '\000'}
+</pre>
+
+<p>
+Since slices, arrays and strings are not C pointers, GDB can't interpret the subscripting operation for you, but
+you can look inside the runtime representation to do that (tab completion helps here):
+</p>
+<pre>
+
+(gdb) <b>p slc</b>
+$11 =  []int = {0, 0}
+(gdb) <b>p slc-&gt</b><i>&ltTAB&gt</i>
+array  slc    len    
+(gdb) <b>p slc->array</b>
+$12 = (int *) 0xf84057af00
+(gdb) <b>p slc->array[1]</b>
+$13 = 0</pre>
+
+
+
+<p>
+The extension functions $len and $cap work on strings, arrays and slices:
+</p>
+
+<pre>
+(gdb) <b>p $len(utf)</b>
+$23 = 4
+(gdb) <b>p $cap(utf)</b>
+$24 = 4
+</pre>
+
+<p>
+Channels and maps are 'reference' types, which gdb shows as pointers to C++-like types <code>hash&ltint,string&gt*</code>.  Dereferencing will trigger prettyprinting
+</p>
+
+<p>
+Interfaces are represented in the runtime as a pointer to a type descriptor and a pointer to a value.  The Go GDB runtime extension decodes this and automatically triggers pretty printing for the runtime type.  The extension function <code>$dtype</code> decodes the dynamic type for you (examples are taken from a breakpoint at <code>regexp.go</code> line 293.)
+</p>
+
+<pre>
+(gdb) <b>p i</b>
+$4 = {str = "cbb"}
+(gdb) <b>whatis i</b>
+type = regexp.input
+(gdb) <b>p $dtype(i)</b>
+$26 = (struct regexp.inputBytes *) 0xf8400b4930
+(gdb) <b>iface i</b>
+regexp.input: struct regexp.inputBytes *
+</pre>
diff --git a/doc/devel/index.html b/doc/devel/index.html
index ae405bf..7fcfe8d 100644
--- a/doc/devel/index.html
+++ b/doc/devel/index.html
@@ -4,7 +4,7 @@
 <li><a href="roadmap.html">Roadmap</a></li>
 <li><a href="release.html">Release history</a></li>
 <li><a href="weekly.html">Weekly snapshot history</a></li>
-<li><a href="http://godashboard.appspot.com">Build and benchmark status</a></li>
+<li><a href="http://build.golang.org/">Build status</a></li>
 </ul>
 <ul>
 <li><a href="../contribute.html">Contributing code</a></li>
diff --git a/doc/devel/release.html b/doc/devel/release.html
index 4ce3d37..984e674 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -104,6 +104,17 @@ a new
 option</a>.
 </p>
 
+<p>
+r60.2
+<a href="http://code.google.com/p/go/source/detail?r=ff19536042ac">fixes</a>
+a memory leak involving maps.
+</p>
+
+<p>
+r60.3 fixes a
+<a href="http://code.google.com/p/go/source/detail?r=01fa62f5e4e5">reflect bug</a>.
+</p>
+
 <h2 id="r59">r59 (released 2011/08/01)</h2>
 
 <p>
diff --git a/doc/devel/weekly.html b/doc/devel/weekly.html
index 08e24b9..dfaef70 100644
--- a/doc/devel/weekly.html
+++ b/doc/devel/weekly.html
@@ -14,6 +14,1273 @@ hg pull
 hg update weekly.<i>YYYY-MM-DD</i>
 </pre>
 
+<h2 id="2012-01-27">2012-01-27</h2>
+
+<pre>
+This weekly snapshot renamed the html package to exp/html. The package will not
+be present in the Go 1 distribution, but will be installable from source.
+
+Error variables in the archive/tar, archive/zip, compress/gzip, compress/zlib,
+and crypto/bcrypt packages have been renamed from FooError to ErrFoo. 
+There is no gofix, but the compiler will flag code that needs updating.
+
+Other changes:
+* 6c, 8c: make floating point code NaN-safe.
+* 6l, 8l: remove unused macro definition (thanks Shenghou Ma).
+* archive/tar: fix race in TestNonSeekable.
+* archive/zip: add functions to convert between os.FileInfo & FileHeader.
+* build: do not build all C compilers (thanks Shenghou Ma),
+	remove code now in subrepositories.
+* bytes: remove dead code, complete documentation,
+	restore panic on out-of-memory,
+	turn buffer size overflows into errors.
+* cgo: -cdefs should translate unsafe.Pointer to void * (thanks Shenghou Ma).
+* cmd/gc: forgotten recursion on ninit itself in order.c.
+* cmd/go: bug fixes, implement go get,
+	correctly handle -n and -x flags for 'go run' (thanks Shenghou Ma),
+	solve ambiguity of get lp.net/project/foo (thanks Gustavo Niemeyer),
+	update doc.go with text generated from the usage strings.
+* cmd/goapi: new tool for tracking exported API over time.
+* codereview: support for subrepositories.
+* compress/flate: fix a typo, improve compression rate by 3-4%,
+	increase the length of hash table from 1<<15 to 1<<17. 0%-16% speedup,
+	make lazy matching work,
+	reduce memory pressure at cost of additional arithmetic operation,
+	use append instead of slice+counter.
+* crypto: rename some FooError to ErrFoo.
+* dashboard: fix -commit for new xml package.
+* database/sql: add NullInt64, NullFloat64, NullBool (thanks James P. Cooper),
+	convert SQL null values to []byte as nil (thanks James P. Cooper),
+	fix Tx.Query (thanks Blake Mizerany).
+* doc: expand FAQ on GOMAXPROCS, update to Go 1.
+* doc/go1: add encoding/xml and net/url changes (thanks Gustavo Niemeyer),
+	add more info about hash and net changes, delete reference to html,
+	add flag, runtime, testing, image , mime, filepath.Walk,
+	document sub-repositories.
+* encoding/binary: document that PutVarint, PutUvarint may panic.
+* encoding/varint: deleted WriteXvarint.
+* encoding/xml: add docs for ignoring tag (thanks Gustavo Niemeyer),
+	bring API closer to other packages (thanks Gustavo Niemeyer),
+	improve []byte handling (thanks Gustavo Niemeyer),
+	remove Marshaler support (thanks Gustavo Niemeyer),
+	support ignoring fields with "-" (thanks Gustavo Niemeyer).
+* exp/ebnflint: test spec during 'go test'.
+* exp/norm: fixes a subtle bug introduced by change 10087: random offset.
+* gc, runtime: handle floating point map keys.
+* gc: avoid DOT in error messages,
+	do not try to add a key with incorrect type to a hash (thanks Jeff R. Allen),
+	fix order of evaluation,
+	fix recursion loop in interface comparison,
+	handle function calls in arguments to builtin complex operations,
+	missed typecheck in subscripting a const string,
+	permit unsafe.Pointer for inlined functions,
+	softer criteria for inlinability,
+	static implements check on typeswitches only applies to concrete case types,
+	test case for recursive interface bug.
+* go/ast: respect ImportSpec.EndPos (thanks Scott Lawrence).
+* go/build: add BuildTags to Context, allow !tag.
+* go/doc: rewrite and add lots of tests.
+* go/parser: use explicit parser.Mode type.
+* go/printer, gofmt: respect line breaks in signatures.
+* go/scanner: use explicit scanner.Mode type.
+* gob: annotate debug.go so it's not normally built,
+	reduce the maximum message size.
+* godoc: log node printing error,
+	move overview before API TOC,
+	update metadata upon launch.
+* gofix: add -debug flag for quicker diagnosis of internal errors,
+	handle xml.Unmarshal in xmlapi fix (thanks Gustavo Niemeyer),
+	update go1pkgrename for subrepositories.
+* goyacc: fix indexing bug when yydebug >= 2.
+* ld: fix Mach-O code signing for non-cgo binaries (thanks Mikkel Krautz).
+* libmach: cross compiling support (thanks Shenghou Ma).
+* math/big: assembly versions of bitLen for x86-64, 386, and ARM (thanks David G. Andersen),
+	return type of bitLen is an int; use MOVL on amd64 (thanks David G. Andersen),
+	add examples for Rat and Int's SetString and Scan methods,
+	slight improvement to algorithm used for internal bitLen function (thanks David G. Andersen),
+	test both bitLen and bitLen_g.
+* net/http: add Request.RequestURI field,
+	disabled test for Transport race / deadlock bug,
+	fix Transport deadlock (thanks Yoshiyuki Kanno),
+	make ParseForm ignore unknown content types (thanks Roger Peppe),
+	parse CONNECT requests (thanks Andrew Balholm).
+* net/rpc: fix data race in benchmark,
+	fix race in TestClientWriteError test,
+	log Call reply discard.
+* net: Dial, ListenPacket with "ip:protocol" network for raw IP sockets (thanks Mikio Hara),
+	actually reset deadline when time is zero,
+	consistent OpError message (thanks Mikio Hara),
+	fix dialing google test (thanks Mikio Hara),
+	make WriteTo fail when UDPConn is already connected (thanks Mikio Hara).
+* regexp: remove vestigial Error type.
+* runtime: add type algorithms for zero-sized types,
+	move NumCPU declaration into debug.go.
+* spec: function invocation, panic on *nil.
+* syscall: add NOTE_* constants on OS X (thanks Robert Figueiredo).
+* test: explicitly use variables to avoid gccgo "not used" error.
+* text/template: add example for Template.
+</pre>
+
+<h2 id="2012-01-20">2012-01-20</h2>
+
+<pre>
+This weekly snapshot renamed the exp/sql package to database/sql, and moved
+utf8.String from unicode/utf8 to exp/utf8string.
+
+Package net's SetTimeout methods were changed to SetDeadline.
+
+Many functions in package os now take a os.FileMode argument instead of a
+plain uint32. An os.ModeSticky constant is also now defined.
+
+The meaning of the first buffer element for image.YCbCr has changed to match
+the semantics of the other image types like image.RGBA.
+
+The NewMD5, NewSHA1 and NewSHA256 functions in crypto/hmac have been
+deprecated. Use New instead, explicitly passing the hash function.
+
+Other changes:
+* buildscripts: move to buildscript directory (thanks Shenghou Ma).
+* bytes: add the usual copyright notice to example_test.go (thanks Olivier Duperray).
+* cmd/go: remove mentions of 'gotest' from the documentation,
+	skip _obj directories in package scans.
+* container/heap: better package documentation.
+* crypto/elliptic: add constant-time P224.
+* crypto/hmac: Add HMAC-SHA224 and HMAC-SHA384/512 (thanks Luit van Drongelen),
+* crypto/tls: add FreeBSD root certificate location (thanks Shenghou Ma).
+* crypto/x509: remove explicit uses of rsa.
+* doc: various updates (thanks Jongmin Kim, Scott Lawrence, Shenghou Ma, Stefan Nilsson).
+* encoding/json: allow / and % in tag names,
+	document angle bracket escaping,
+	fix comments, tweak tests for tag names (thanks Mikio Hara).
+* encoding/xml: marshal/unmarshal xml.Name in field (thanks Gustavo Niemeyer).
+* exp/inotify: fix data race in linux tests.
+* exp/proxy: fix build after URL changes (thanks Gustavo Niemeyer).
+* exp/sql: copy when scanning into []byte by default,
+	rename NullableString to NullString and allow its use as a parameter.
+* exp/ssh: add marshal functions for uint32 and uint64 types,
+	handle versions with just '\n',
+	rename (some) fields (thanks Christopher Wedgwood).
+* exp/terminal: fix build on non-Linux using Makefiles.
+* fmt: enable and fix malloc test,
+* gc: don't emit pkgpath for error type,
+	don't fault on return outside function (thanks Scott Lawrence),
+	fieldnames in structliterals in exported inlines should not be qualified if they're embedded builtin types,
+	fix infinite recursion for embedded interfaces,
+	give esc.c's sink an orig so -mm diagnostics work again,
+	handle printing of string/arrayrune conversions.
+	remove redundant code (thanks Shenghou Ma).
+* go/build: no back slash in FindTree returned pkg name (thanks Alex Brainman).
+* go/doc: collect imports,
+	don't shadow receiver.
+	rewrote and completed test framework.
+	print only one newline between paragraphs
+* go/parser: expressions may have comments.
+* go/scanner: fix example (thanks Olivier Duperray).
+* go/token: replaced Files() with Iterate().
+* godoc: add anchors to cmd documentation headings,
+	remove "need more packages?" link,
+	specify HTML page metadata with a JSON blob,
+	support canonical Paths in HTML metadata.
+* html/template: fix docs after API changes (thanks Gustavo Niemeyer).
+* html: in foreign content, check for HTML integration points in breakout.
+* image/color: rename modelYCbCr to yCbCrModel (thanks Benny Siegert),
+	simplify documentation (thanks David Crawshaw).
+* image: add PixOffset methods.
+* math/rand: decrease test duration in short mode,
+	document default initial seed for global generator (thanks Scott Lawrence).
+* mime: make FormatMediaType take full type for consistency.
+* misc/cgo/test: make tests run on windows (thanks Alex Brainman).
+* net/http/cgi: increase a flaky test timeout.
+* net/http: change test to use override param instead of chan,
+	log handler panic before closing HTTP connection,
+	send cookies in jar on redirect (thanks Jeff Hodges),
+	the documentation should call NewRequest with the right signature (thanks Christoph Hack),
+	update the Client docs a bit.
+* net/url: cleaned up URL interface (v2) (thanks Gustavo Niemeyer).
+* net: consistent log format in test (thanks Mikio Hara),
+	various build fixes (thanks Mikio Hara),
+	use NewTimer, not NewTicker, in fd_windows.go.
+* old/netchan: fix data race on client hashmap.
+* os/exec: trivial allocation removal in LookPath (thanks Gustavo Niemeyer).
+* os: remove old note about NewSyscallError being special (thanks Alex Brainman),
+* path: added examples (thanks Sanjay Menakuru).
+* pkg: Add and fix Copyright of "hand generated" files (thanks Olivier Duperray),
+	add missing godoc comments to windows versions (thanks Alex Brainman).
+* regexp: add SubexpNames.
+* runtime: implement runtime.usleep for FreeBSD/386 and amd64 (thanks Shenghou Ma),
+	madvise and SysUnused for Darwin (thanks Dave Cheney).
+* sync/atomic: fix data race in tests.
+* syscall: add Unix method to TimeSpec, TimeVal,
+	fix plan9 build (thanks Mikio Hara).
+* test: change several tests to not print,
+	fix bug364 to actually run,
+	match gccgo error messages for bug345,
+	split golden.out into expected output per test.
+* testing: do not recover example's panic (thanks Shenghou Ma),
+	document examples.
+* text/template/parse: use human error prints.
+* text/template: fix nil error on redefinition.
+* time: add Since, which returns the time elapsed since some past time t.
+</pre>
+
+<h2 id="2012-01-15">2012-01-15</h2>
+
+<pre>
+This weekly snapshot includes two package changes that may require changes to
+client code.
+
+The image package's Tiled type has been renamed to Repeated.
+
+The encoding/xml package has been changed to make more idiomatic use of struct
+tags, among other things. If you use the xml package please read the change
+description to see if your code is affected:
+	http://code.google.com/p/go/source/detail?r=70e914beb409
+
+Function inlining is now enabled by default in the gc compiler.
+
+Other changes:
+* bytes: Buffer read of 0 bytes at EOF shouldn't be an EOF.
+* cgo: if value for constant did not parse, get it from DWARF info,
+	write _cgo_export.h to object directory, not source dir.
+* cmd/go: add -p flag for parallelism (like make -j),
+	add -v flag to build and install,
+	add ... patterns in import path arguments,
+	fix data race during build,
+	fix import directory list for compilation,
+	fix linker arguments,
+	handle cgo pkg-config pragmas,
+	handle path to cmd directory,
+	include test files in fmt, vet, and fix (thanks Sanjay Menakuru),
+	kill test processes after 10 minutes,
+	pass arguments to command for run (thanks Eric Eisner),
+	rely on exit code to tell if test passed,
+	use relative paths in go fix, go fmt, go vet output.
+* cmd/gofmt: fix simplify.go by running gofmt on cmd/gofmt (thanks Olivier Duperray).
+* crypto/openpgp: assorted cleanups,
+	truncate hashes before checking DSA signatures.
+* crypto/tls: improve TLS Client Authentication (thanks Jeff R. Allen),
+	update generate_cert.go for new time package.
+* dashboard: better caching, bug fixes.
+* doc: update "How to Write Go Code" to use the go tool.
+	fix broken function codewalk examples.
+* encoding/asn1: document support for *big.Int (thanks Florian Weimer).
+* encoding/gob: fix panic when decoding []byte to incompatible slice types (thanks Alexey Borzenkov).
+* encoding/json: don't marshal special float values (thanks Evan Shaw).
+* encoding/xml: major Go 1 fixup (thanks Gustavo Niemeyer).
+* exp/proxy: new package.
+* exp/sql:  add time.Time support,
+	close Rows on EOF,
+	fix potential corruption in QueryRow.Scan into a *[]byte.
+* exp/ssh: various small fixes (thanks Dave Cheney).
+* exp/terminal: add SetPrompt and handle large pastes,
+	add to level Makefile for the (non-Linux?) systems that need it.
+* flag: add Duration flag type,
+	change Set method Value interface to return error instead of bool.
+* gc: better errors messages,
+	avoid false positives when using scalar struct fields (thanks Rémy Oudompheng),
+	closure code gen improvements,
+	disallow declaration of variables outside package,
+	fix switch on interface values (thanks Rémy Oudompheng),
+	inlining bug fixes,
+	improve unsafe.Pointer type-check error messages (thanks Ryan Hitchman),
+	put limit on size of exported recursive interface (thanks Lorenzo Stoakes),
+* go-mode.el: fix syntax highlighting of backticks (thanks Florian Weimer).
+* go/ast: remove unnecessary result value from ast.Fprint/Print.
+* go/build: allow colon in #cgo flags,
+	pass CgoLDFLAGS at end of link command.
+* go/doc: new API, don't ignore anonymous non-exported fields, initial testing support.
+* go/parser: remove unused Parse* functions. Simplified ParseExpr signature.
+* go/printer: don't crash if AST contains BadXXX nodes.
+* go/scanner: 17% faster scanning, remove InsertSemis mode.
+* goinstall: use correct checkout URL for Google Code svn repos.
+* gotest: make _testmain.go conform to gofmt rules (thanks Benny Siegert).
+* goyacc: fix units.y build breakage (thanks Shenghou Ma).
+* html/template: reenable testcases and fix mis-escaped sequences (thanks Mike Samuel).
+* html: "in select in table" insertion mode (thanks Andrew Balholm),
+	adjust foreign attributes,
+	foreign element HTML integration points, tag name adjustment,
+	parse <frameset> inside body (thanks Andrew Balholm),
+	propagate foreign namespaces only when adding foreign content.
+* json: better error messages when the ,string option is misused.
+* ld: parse but do not implement -X flag.
+* log/syslog: add Alert method (thanks Vadim Vygonets).
+* make.bash: remove old dregs (thanks Alex Brainman).
+* math/big: simplify fast string conversion.
+* math: fix typo in all_test.go (thanks Charles L. Dorian).
+* misc/windows: add src/pkg/runtime/z* files to installation script (thanks Alex Brainman).
+* net/http: don't ignore Request.Write's Flush error,
+	allow cookies with negative Max-Age attribute as these are (thanks Volker Dobler).
+* net/textproto: avoid corruption when reading a single header.
+* net: add IP-level socket option helpers for Unix variants (thanks Mikio Hara),
+	fix incorrect mode on ListenIP, ListenUDP (thanks Mikio Hara),
+	make use of the kernel state to listen on TCP, Unix (thanks Mikio Hara),
+	platform-dependent default socket options (thanks Mikio Hara).
+* os: add ModeCharDevice.
+* runtime: add NumCPU,
+	delete duplicate implementation of pcln walker,
+	distinct panic message for call of nil func value,
+	enable runtime.ncpu on FreeBSD (thanks Devon H. O'Dell),
+	make garbage collector faster by deleting code,
+	regenerate defs_darwin_{386,amd64}.h (thanks Dave Cheney),
+	runtime.usleep() bugfix on darwin/amd64 and linux/arm (thanks Shenghou Ma).
+* spec: pointer comparison for pointers to 0-sized variables,
+	change the wording regarding select statement choice.
+* strconv: fix round up corner case,
+	faster FormatFloat(x, *, -1, 64) using Grisu3 algorithm (thanks Rémy Oudompheng),
+	implement fast path for rounding already short numbers (thanks Rémy Oudompheng),
+	return ErrSyntax when unquoting illegal octal sequences.
+* syscall: linux-only support for parent death signal (thanks Albert Strasheim),
+	make Environ return original order.
+* testing: fix defer race,
+	use flag.Duration for -timeout flag.
+* text/template: handle panic values that are not errors (thanks Rémy Oudompheng),
+	for range on a map, sort the keys if feasible.
+* time: add ParseDuration,
+	fix docs for After and NewTicker.
+* windows: use ArbitraryUserPointer as TLS slot (thanks Wei Guangjing).
+</pre>
+
+<h2 id="2011-12-22">2011-12-22</h2>
+
+<pre>
+This snapshot includes changes to the images/ycbcr and testing packages, and
+changes to the build system.
+
+The types for managing Y'CbCr images in the image/ycbcr have been moved to the
+image and image/color packages. A gofix module will rewrite affected code.
+
+The testing package's B type (used when running benchmarks) now has the same
+methods as T (used in tests), such as Print, Error, and Fatal.
+
+This weekly adds a new command named 'go' for building and testing go programs.
+For Go 1, the go command will replace the makefile-based approach that we have
+been using. It is not yet ready for general use, but all.bash does use it to
+build the tree. If you have problems building the weekly, you can 'export
+USE_GO_TOOL=false' before running all.bash to fall back to the makefiles.
+
+Other changes:
+* archive/zip: add SetModTime method to FileHeader.
+* build: make use of env (thanks Mikio Hara),
+	fixes to make "go install" work on windows (thanks Alex Brainman).
+* bytes: add two Buffer examples.
+* cgo: support export for built-in types (thanks Maxim Pimenov).
+* cmd/go: avoid infinite loop with package specific flags (thanks Mikio Hara),
+	fixes to build standard library,
+	implement test command,
+	make sure use of pthread for gcc-4.5 and beyond (thanks Mikio Hara),
+	respect $GCFLAGS,
+	use spaces consistently in help message (thanks Roger Peppe),
+	many other improvements.
+* codereview: initialize "found" in codereview.py (thanks Miki Tebeka).
+* crypto/mime/net/time: add netbsd to +build tags (thanks Joel Sing).
+* crypto/tls: don't assume an RSA private key in the API.
+* crypto/x509: don't crash with nil receiver in accessor method.
+* doc/effective_go: discuss redeclaration.
+* doc: delete go course notes,
+	refer to http://build.golang.org/ where applicable (thanks Robert Hencke),
+	suggest code.google.com/p/go instead of go.googlecode.com/hg.
+* encoding/binary: add Write and Read examples,
+	add more benchmarks (thanks Roger Peppe).
+* encoding/gob: arrays are zero only if their elements are zero.
+* encoding/json: cleanup leftover variables in array decoding (thanks Rémy Oudompheng),
+	examples for Marshal and Unmarshal.
+* exp/ssh: rename ClientAuthPublicKey helper ClientAuthKeyring (thanks Dave Cheney),
+	simplify Stdin/out/errPipe methods (thanks Dave Cheney).
+* fmt: speed up floating point print, clean up some code,
+	make the malloc test check its counts.
+* gc: allow use of unsafe.Pointer in generated code,
+	avoid unsafe in defn of package runtime,
+	better linenumbers for inlined functions,
+	better loopdepth analysis for labels,
+	implement and test \r in raw strings,
+	inlining, allow empty bodies, fix _ arguments,
+	omit argument names from function types in error messages.
+* go/ast, parser: remember short variable decls. w/ correspoding ident objects.
+* go/build: add new +build tags 'cgo' and 'nocgo'.
+* go/doc, godoc: move export filtering into go/doc
+* go/printer, gofmt: fine tuning of line spacing.
+* go/scanner: strip CRs from raw literals.
+* gob: isZero for struct values.
+* godoc: allow examples for methods (thanks Volker Dobler),
+	show methods of anonymous fields.
+* goinstall: only suggest -fix for bad imports when appropriate.
+* govet: add checking for printf verbs,
+	divide the program into one file per vetting suite.
+* html: more parser improvements (thanks Andrew Balholm).
+* json: some tests to demonstrate bad error messages,
+	use strconv.Append variants to avoid allocations in encoding.
+* ld: add support for netbsd signature note section (thanks Joel Sing),
+	allow for IMAGE_REL_AMD64_ADDR32NB relocation type (thanks Alex Brainman).
+* math/big: Rand shouldn't hang if argument is also receiver.
+* misc/builder: set default builder host to build.golang.org.
+* misc/dashboard: delete old build dashboard code ,
+	improvements and fixes for the go implementation.
+* misc/vim: fix go filetype detection (thanks Paul Sbarra).
+* net, syscall, os: set CLOEXEC flag on epoll/kqueue descriptor.
+* net, syscall: interface address and mask (thanks Mikio Hara).
+* net/http: added interface for a cookie jar (thanks Volker Dobler),
+	test fixes (thanks Alex Brainman).
+* net: add DialTimeout,
+	sort Makefile entries (thanks Mikio Hara).
+* os, syscall: beginnings of NetBSD support (thanks Christopher Nielsen).
+* os/exec: add test to verify net package's epoll fd doesn't go to child,
+	disable the ExtraFiles test on darwin.
+* os: don't trust O_CLOEXEC on OS X,
+	make sure Remove returns correct error on windows (thanks Alex Brainman).
+* path, path/filepath: add Dir to complement Base.
+* path/filepath.Rel: document that the returned path is always relative.
+* runtime: don't panic on SIGILL, just crash.
+* spec: be precise about newlines.
+* sql: add Rows.Columns.
+* strconv: fix bug in extended-float based conversion,
+	implement faster parsing of decimal numbers, and
+	reduce buffer size for multi-precision decimals (thanks Rémy Oudompheng).
+* syscall: regenerate z-files for linux/arm (thanks Mikio Hara),
+	sort Makefile, mkall.sh and mkerrors.sh entries (thanks Mikio Hara).
+* test/bench/go1: first draft of Go 1 benchmark suite.
+* testing: compare Log to Println (thanks Robert Hencke),
+	make signalling safer for parallel tests.
+* text/template: better error message for empty templates,
+	fix handing of nil arguments to functions (thanks Gustavo Niemeyer).
+* time: add JSON marshaler for Time (thanks Robert Hencke),
+	new AddDate method (thanks Roger Peppe).
+* various: use $GCFLAGS and $GCIMPORTS like Make does (thanks Maxim Pimenov).
+</pre>
+
+<h2 id="2011-12-14">2011-12-14</h2>
+
+<pre>
+This snapshot includes language changes and changes to goinstall and gofmt.
+
+Equality and inequality (== and !=) are now defined for struct and array
+values, respectively, provided the elements of the data structures can
+themselves be compared. See the Go 1 release notes for the details:
+	http://weekly.golang.org/doc/go1.html#equality
+
+The rune type is now an alias for int32 and character literals have the default
+type of rune. Code that uses int where it should use rune will break. 
+See the Go 1 release notes for the details:
+	http://weekly.golang.org/doc/go1.html#rune
+
+Goinstall now expects Google Code import paths to be of the form:
+	"code.google.com/p/go-tour/tree"
+It will reject imports in the old style "go-tour.googlecode.com/hg/tree".
+There is a gofix module to rename such imports.
+Use goinstall -fix to update broken packages.
+
+Gofmt's flags have been modified slightly.
+The -tabintent flag has been renamed -tabs.
+The -spaces flag has been removed.
+
+Other changes:
+* 5c, 6c, 8c: support 64-bit switch value (thanks Anthony Martin).
+* 8c: handle 64-bit switch value.
+* archive/tar: use struct comparison not DeepEqual (thanks Christopher Wedgwood).
+* archive/zip: make zip understand os.FileMode (thanks Roger Peppe).
+* bufio: make the minimum read buffer size 16 bytes.
+* build: disable cgo on Windows/amd64,
+	regularize packages so they may be built without Makefiles.
+* bytes: faster Count, Index, Equal.
+* cgo: add basic gccgo support (thanks Rémy Oudompheng).
+* codereview: fix path slash issue (thanks Yasuhiro Matsumoto).
+* compress/flate: fix out of bounds error.
+* contribute.html: do not fill in the reviewer field (thanks Florian Weimer).
+* crypto/aes: made faster by eliminating some indirection (thanks Taru Karttunen).
+* crypto/dsa: don't truncate input hashes.
+* doc/go_tutorial: make clear the file example is Unix-specific.
+* doc: add Defer, Panic, and Recover article,
+	add Error Handling article,
+	add Go 1 release notes document.
+* encoding/gob: better error messages when types mismatch.
+* env.bash: export CGO_ENABLED so cgo tests run (thanks Alex Brainman).
+* exp/sql: simplify some string conversions.
+* exp/ssh: Wait returns an *ExitError (thanks Gustav Paul).
+* exp/ssh: improve client channel close behavior (thanks Dave Cheney).
+* fmt: don't recur if String method (etc.) misbehaves.
+* gc: better error messages,
+	inlining (disabled without -l),
+	many bug fixes (thanks Lucio De Re and Rémy Oudompheng).
+* go/printer, godoc: print comments in example code.
+* go: implement doc, fmt, fix, list, vet, build, and install.
+* gobuilder: goinstall packages after building go tree.
+* godoc: <pre> must not occur inside <p> (thanks Olivier Duperray),
+	added an opensearch description document (thanks Christoph Hack),
+	text wrapping.
+* gofix: add httputil fix (thanks Yasuhiro Matsumoto).
+* gotest: use go/build more (thanks Robert Hencke).
+* gzip: convert between Latin-1 and Unicode (thanks Vadim Vygonets).
+* html/template: define the FuncMap type locally.
+* html: a first step at parsing foreign content (MathML, SVG),
+	more parser improvements (thanks Andrew Balholm).
+* http: close connection after printing panic stack trace (thanks Roger Peppe),
+	fix failing Transport HEAD request with gzip-looking response.
+* json: treat renamed byte slices the same as []byte.
+* ld: first pass at linker support for NetBSD binaries (thanks Christopher Nielsen),
+	fix memory leaks (thanks Scott Lawrence),
+	increase default stack size on Windows for cgo.
+* math: delete non-Sqrt-based Hypot,
+	implement, document, and fix special cases (thanks Charles L. Dorian),
+* misc/benchcmp: don't require "Benchmark" at beginning of line.
+* misc/osx: rename profile.go to profile_go (thanks Scott Lawrence).
+* net/http: fix trivial example server (thanks Olivier Duperray),
+	net/http: make test remove temporary file and directory.
+* net/smtp: add CRAM-MD5 authentication (thanks Vadim Vygonets).
+* reflect: fix Slice cap (thanks Gustavo Niemeyer).
+* regexp: performance improvements; avoid allocation of input interface.
+* runtime: bump gc 'extra bytes' check (thanks Christopher Wedgwood),
+	madvise and SysUnused for Linux (thanks Sébastien Paolacci),
+	make gc_test test extra allocated space, not total space,
+	support for NetBSD (thanks Christopher Nielsen).
+* spec: adjust complex constant example (thanks Robert Hencke),
+	values of underlying type uintptr can be converted to unsafe.Pointer,
+	var x = 'a' defaults to type rune.
+* strconv: include package and function name in error strings,
+	make QuoteRune etc. take a rune argument,
+	some performance improvements.
+* syscall: add constants for flock() system call under Linux,
+	regenerate z-files for darwin, freebsd (thanks Mikio Hara),
+	regenerate z-files for openbsd,
+	return error, not uintptr, when function returns error (thanks Alex Brainman).
+* test/bench: move to test/bench/shootout.
+* test/garbage: move to test/bench/garbage.
+* test: make array smaller in nilptr test.
+* time: allow sleep tests to run for 200% too long,
+	fix Time.Add (thanks Hector Chu),
+	fix daysIn for December (thanks Peter Mundy),
+	gob marshaler for Time (thanks Robert Hencke),
+	use Duration for AfterFunc.
+* various: a grab-bag of time.Duration cleanups.
+</pre>
+
+<h2 id="2011-12-06">2011-12-06</h2>
+
+<pre>
+This snapshot includes a language change and changes to the strconv and go/doc
+packages. The package changes require changes to client code.
+The language change is backwards-compatible.
+
+Type elision in arrays, slices, or maps of composite literals has been
+extended to include pointers to composite literals. Code like this
+	var t = []*T{&T{}, &T{}}
+may now be written as
+	var t = []*T{{}, {}}
+You can use gofmt -s to simplify such code.
+
+The strconv package has been given a more idiomatic and efficient interface.
+Client code can be updated with gofix. See the docs for the details:
+	http://weekly.golang.org/pkg/strconv/
+
+The go/doc package's ToHTML function now takes a []byte argument instead of a
+string.
+
+Other changes:
+* crypto/aes: eliminate some bounds checking and truncation (thanks Rémy Oudompheng).
+* crypto/x509: if a parent cert has a raw subject, use it.
+* encoding/gob: don't send type info for unexported fields.
+* exp/ssh: allow for msgUserAuthBanner during authentication (thanks Gustav Paul).
+* fmt: benchmark floating point,
+	only use Stringer or Error for strings.
+* gc: changes in export format in preparation of inlining,
+	disallow map/func equality via interface comparison,
+	use gofmt spacing when printing map type.
+* go/doc: exclude lines ending in ':' from possible headings.
+* gobuilder: -commit mode for packages,
+	cripple -package mode temporarily,
+	use new dashboard protocol.
+* godoc: improved output of examples in html (thanks Volker Dobler).
+* gofmt: handle &T in composite literal simplify.
+* goinstall: honour -install=false flag when -make=true.
+* hash: rewrite comment on Hash.Sum method.
+* html: more parser improvements (thanks Andrew Balholm).
+* image: avoid func comparison during ColorModel comparison.
+* math: add special-cases comments to Sinh and Tanh (thanks Charles L. Dorian).
+* misc/dashboard: further implementation work.
+* net, syscall: remove BindToDevice from UDPConn, IPConn (thanks Mikio Hara).
+* net/mail: correctly compare parsed times in the test.
+* os/exec: make LookPath always search CWD under Windows (thanks Benny Siegert).
+* runtime: prep for type-specific algorithms.
+* strconv: 34% to 63% faster conversions.
+</pre>
+
+<h2 id="2011-12-02">2011-12-02</h2>
+
+<pre>
+This weekly snapshot includes changes to the hash package and a gofix for the
+time and os.FileInfo changes in the last snapshot.
+
+The hash.Hash's Sum method has been given a []byte argument,
+permitting the user to append the hash to an existing byte slice.
+Existing code that uses Sum can pass nil as the argument.
+Gofix will make this change automatically.
+
+Other changes:
+* crypto/tls: cleanup certificate load on windows (thanks Alex Brainman).
+* exp/ssh: add Std{in,out,err}Pipe methods to Session (thanks Dave Cheney).
+* dashboard: don't choke on weird builder names.
+* exp/ssh: export type signal, now Signal (thanks Gustav Paul).
+* os: add ModeType constant to mask file type bits (thanks Gustavo Niemeyer).
+* text/template: replace Add with AddParseTree.
+* go/doc: detect headings and format them in html (thanks Volker Dobler).
+</pre>
+
+<h2 id="2011-12-01">2011-12-01</h2>
+
+<pre>
+This weekly snapshot includes changes to the time, os, and text/template
+packages. The changes to the time and os packages are significant and related.
+Code that uses package time, package text/template, or package os's FileInfo
+type will require changes.
+
+In package time, there is now one type - time.Time - to represent times.
+Note that time.Time should be used as a value, in contrast to old code
+which typically used a *time.Time, a pointer to a large struct.  (Drop the *.)
+Any function that previously accepted a *time.Time, an int64
+number of seconds since 1970, or an int64 number of nanoseconds
+since 1970 should now accept a time.Time.  Especially as a replacement
+for the int64s, the type is good documentation about the meaning of
+its value.
+
+Whether you were previously calling time.Seconds, time.Nanoseconds,
+time.LocalTime, or time.UTC, the replacement is the new function
+time.Now.
+
+If you previously wrote code like:
+
+       t0 := time.Nanoseconds()
+       myFunction()
+       t1 := time.Nanoseconds()
+       delta := t1 - t0
+       fmt.Printf("That took %.2f seconds\n", float64(t1-t0)/1e9)
+
+you can now write:
+
+       t0 := time.Now()
+       myFunction()
+       t1 := time.Now()
+       delta := t1.Sub(t0)
+       fmt.Printf("That took %s\n", delta)
+
+In this snippet, the variable delta is of the new type time.Duration, the
+replacement for the many int64 parameters that were nanosecond
+counts (but not since 1970).
+
+Gofix can do the above conversions and some others, but it does not
+rewrite explicit int64 types as time.Time. It is very likely that you will
+need to edit your program to change these types after running gofix.
+As always, be sure to read the changes that gofix makes using your
+version control system's diff feature.
+
+See http://weekly.golang.org/pkg/time/ for details.
+
+In package os, the FileInfo struct is replaced by a FileInfo interface,
+admitting implementations by code beyond the operating system.
+Code that refers to *os.FileInfo (a pointer to the old struct) should
+instead refer to os.FileInfo (the new interface).
+The interface has just a few methods:
+
+       type FileInfo interface {
+               Name() string       // base name of the file
+               Size() int64        // length in bytes
+               Mode() FileMode     // file mode bits
+               ModTime() time.Time // modification time
+               IsDir() bool        // abbreviation for Mode().IsDir()
+       }
+
+If you need access to the underlying stat_t provided by the operating
+system kernel, you can access it by assuming that the FileInfo you are
+holding is actually an *os.FileStat, and that it's Sys field is actually a
+*syscall.Stat_t, as in:
+
+       dev := fi.(*os.FileStat).Sys.(*syscall.Stat_t).Dev
+
+Of course, this is not necessarily portable across different operating
+systems.
+
+Gofix will take care of rewriting *os.FileInfo to os.FileInfo for you,
+and it will also rewrite expressions like fi.Name into calls like fi.Name().
+
+See http://weekly.golang.org/pkg/os/#FileInfo for details.
+
+The template package has been changed to export a new, simpler API.
+The Set type is gone. Instead, templates are automatically associated by
+being parsed together; nested definitions implicitly create associations.
+Only associated templates can invoke one another.
+This approach dramatically reduces the breadth of the construction API.
+The html/template package has been updated also.
+There's a gofix for the simplest and most common uses of the old API.
+Code that doesn't mention the Set type is likely to work after running gofix;
+code that uses Set will need to be updated by hand.
+The template definition language itself is unchanged.
+
+See http://weekly.golang.org/pkg/text/template/ for details.
+
+
+Other changes:
+* cgo: add support for callbacks from dynamic libraries.
+* codereview: gofmt check for non-src/ files (thanks David Crawshaw).
+* crypto/openpgp/packet: fix private key checksum.
+* crypto/tls: add openbsd root certificate location,
+	don't rely on map iteration order.
+* crypto/x509, crypto/tls: support PKCS#8 private keys.
+* dashboard: start of reimplementation in Go for App Engine.
+* encoding/xml: fix copy bug.
+* exp/gui: move exp/gui and exp/gui/x11 to http://code.google.com/p/x-go-binding
+* exp/ssh: various improvements (thanks Dave Cheney and Gustav Paul).
+* filepath/path: fix Rel buffer sizing (thanks Gustavo Niemeyer).
+* gc: fix Nconv bug (thanks Rémy Oudompheng) and other fixes.
+* go/printer, gofmt: performance improvements.
+* gofix: test and fix missorted renames.
+* goinstall: add -fix flag to run gofix on packages on build failure,
+	better error reporting,
+	don't hit network unless a checkout or update is required,
+	support Google Code sub-repositories.
+* html: parser improvements (thanks Andrew Balholm).
+* http: fix sniffing bug causing short writes.
+* json: speed up encoding, caching reflect calls.
+* ld: align ELF data sections.
+* math/big: fix destination leak into result value (thanks Roger Peppe),
+	use recursive subdivision for significant speedup.
+* math: faster Cbrt and Sincos (thanks Charles L. Dorian).
+* misc/osx: scripts to make OS X package and disk image (thanks Scott Lawrence).
+* os: fail if Open("") is called on windows (thanks Alex Brainman).
+* runtime: make sure stack is 16-byte aligned on syscall (thanks Alex Brainman).
+* spec, gc: allow direct conversion between string and named []byte, []rune.
+* sql: add Tx.Stmt to use an existing prepared stmt in a transaction,
+	more driver docs & tests; no functional changes.
+* strings: add ContainsAny and ContainsRune (thanks Scott Lawrence).
+* syscall: add SUSv3 RLIMIT/RUSAGE constants (thanks Sébastien Paolacci),
+	fix openbsd sysctl hostname/domainname workaround,
+	implement Syscall15 (thanks Alex Brainman).
+* time: fix Timer stop.
+</pre>
+
+<h2 id="2011-11-18">2011-11-18</h2>
+
+<pre>
+This snapshot includes some language changes.
+
+Map and function value comparisons are now disallowed (except for comparison
+with nil) as per the Go 1 plan. Function equality was problematic in some
+contexts and map equality compares pointers, not the maps' content.
+
+As an experiment, structs are now allowed to be copied even if they contain
+unexported fields. This gives packages the ability to return opaque values in
+their APIs.
+
+Other changes:
+* 6a, 8a: allow $(-1) for consistency with $1, $(1), $-1.
+* 6l: code generation fixes (thanks Michał Derkacz).
+* build: fix check for selinux allow_execstack on Fedora (thanks Bobby Powers).
+* builtin: document delete.
+* cgo: don't panic on undeclared enums/structs (thanks Rémy Oudompheng),
+	fix g0 stack guard.
+* crypto/tls: fix handshake message test.
+* crypto: update incorrect references to Cipher interface; should be Block.
+* doc: clean ups, additions, and fixes to several documents.
+* doc/install: add openbsd (thanks Joel Sing!).
+* doc: link to Chinese translation of A Tour of Go.
+* encoding/json: add marshal/unmarshal benchmark,
+	decode [] as empty slice, not nil slice,
+	make BenchmarkSkipValue more consistent.
+* env.bash: check for presence of make/gmake (thanks Scott Lawrence).
+* exp/sql: NumInput() allow -1 to ignore checking (thanks Yasuhiro Matsumoto),
+	add DB.Close, fix bugs, remove Execer on Driver (only Conn),
+	document that for drivers, io.EOF means no more rows,
+	add client side support for publickey auth (thanks Dave Cheney),
+	add direct-tcpip client support (thanks Dave Cheney),
+	change test listen address, also exit test if fails,
+	other fixes and improvements (thanks Dave Cheney).
+* exp/terminal: rename shell to terminal and add SetSize.
+* fcgi: fix server capability discovery.
+* fmt: distinguish empty vs nil slice/map in %#v.
+* gc: better error, type checks, and many fixes,
+	remove m[k] = x, false syntax (use delete(m, k) instead),
+	support for building with Plan 9 yacc (thanks Anthony Martin).
+* go/printer: make //line formatting idempotent.
+* godefs: delete, replaced by cgo -godefs.
+* godoc: document -templates flag, fix remote search,
+	provide mode for flat (non-indented) directory listings.
+* gofmt: leave nil nodes of the AST unchanged (thanks Rémy Oudompheng).
+* html/template: indirect top-level values before printing.
+* html: more parser improvements (thanks Andrew Balholm).
+* http: fix serving from CWD with http.ServeFile,
+	make Dir("") equivalent to Dir(".").
+* ld: fix .bss for ldpe (thanks Wei Guangjing).
+* math/big: replace nat{} -> nat(nil).
+* math: faster Lgamma (thanks Charles L. Dorian).
+* mime: implement TypeByExtension for windows.
+* misc/bbedit: error and rune support (thanks Anthony Starks).
+* misc/benchcmp: benchmark comparison script.
+* misc/emacs: add delete builtin (thanks Bobby Powers).
+* misc/kate: add error and rune (thanks Evan Shaw).
+* misc/notepadplus: error and rune support (thanks Anthony Starks).
+* misc/windows: Windows installer in MSI format (thanks Joe Poirier).
+* net, io/ioutil: remove use of os.Time (thanks Anthony Martin).
+* net/http: fix EOF handling on response body (thanks Gustavo Niemeyer),
+	fix sniffing when using ReadFrom,
+	use t.Errorf from alternate goroutine in test.
+* os: remove undocumented Envs (use os.Environ instead).
+* reflect: empty slice/map is not DeepEqual to nil,
+	make Value an opaque struct.
+* runtime, syscall: convert from godefs to cgo.
+* runtime: add nanotime for Plan 9 (thanks Anthony Martin),
+	add timer support, use for package time,
+	avoid allocation for make([]T, 0).
+* strconv: add Ftoa benchmarks, make Ftoa faster.
+* syscall: delete syscall.Sleep, take over env implementation, use error.
+* testing: add file:line stamps to messages, print results to standard output.
+* text/template: refactor set parsing.
+* time: add ISOWeek method to Time (thanks Volker Dobler).
+* various: avoid func compare, reduce overuse of os.EINVAL + others.
+</pre>
+
+<h2 id="2011-11-09">2011-11-09</h2>
+
+<pre>
+This weekly snapshot renames various Go packages as described in the Go 1 plan.
+Import statements in client code can be updated automatically with gofix.
+
+The changes are:
+	asn1              -> encoding/asn1
+	big               -> math/big
+	cmath             -> math/cmplx
+	csv               -> encoding/csv
+	exec              -> os/exec
+	exp/template/html -> html/template
+	gob               -> encoding/gob
+	http              -> net/http
+	http/cgi          -> net/http/cgi
+	http/fcgi         -> net/http/fcgi
+	http/httptest     -> net/http/httptest
+	http/pprof        -> net/http/pprof
+	json              -> encoding/json
+	mail              -> net/mail
+	rpc               -> net/rpc
+	rpc/jsonrpc       -> net/rpc/jsonrpc
+	scanner           -> text/scanner
+	smtp              -> net/smtp
+	syslog            -> log/syslog
+	tabwriter         -> text/tabwriter
+	template          -> text/template
+	template/parse    -> text/template/parse
+	rand              -> math/rand
+	url               -> net/url
+	utf16             -> unicode/utf16
+	utf8              -> unicode/utf8
+	xml               -> encoding/xml
+</pre>
+
+<h2 id="2011-11-08">2011-11-08</h2>
+
+<pre>
+This weekly snapshot includes some package changes.
+
+In preparation for the Go 1 package reorganziation the sources for various
+packages have been moved, but the import paths remain unchanged. This
+inconsistency breaks goinstall at this snapshot. If you use goinstall, please
+stay synced to the previous weekly snapshot until the next one is tagged.
+
+The Error methods in the html, bzip2, and sql packages that return error values
+have been renamed to Err.
+
+Some non-core parts of the http package have been moved to net/http/httputil.
+The Dump* and NewChunked* functions and ClientConn, ServerConn, and
+ReverseProxy types have been moved from http to httputil.
+
+The API for html/template is now a direct copy of the template API, instead of
+exposing a single Escape function. For HTML templates, simply use the
+html/template package as you would the template package.
+
+Other changes:
+* all: rename os.EOF to io.EOF in non-code contexts (thanks Vincent Vanackere),
+	sort imports with gofix.
+* archive/zip: close file opened with OpenReader (thanks Dmitry Chestnykh).
+* bufio: return nil line from ReadLine on error, as documented.
+* builtin: document basic types and the built-in error type.
+* bytes: add Contains function.
+* exp/sql: finish implementation of transactions, flesh out types, docs.
+* exp/ssh: improved client authentication support (thanks Dave Cheney).
+* gc: better error message for range over non-receive channel,
+	bug fixes and clean-ups,
+	detect type switch variable not used cases,
+	fix escaping of package paths in symbol names,
+	helpful error message on method call on pointer to pointer,
+	portably read archive headers (thanks Ron Minnich).
+* gob: fix bug when registering the same type multiple times.
+* gofix: avoid panic on body-less functions in netudpgroup,
+	make fix order implicit by date.
+* gofmt, gofix: sort imports.
+* goinstall: support launchpad.net/~user branches (thanks Jani Monoses).
+* gopack: do not look for Go metadata in non-Go objects.
+* gotest: don't run examples that have no expected output.
+* html: the parser bug fixing campaign continues (thanks Andrew Balholm).
+* http: fix whitespace handling in sniffer,
+	only recognize application/x-www-form-urlencoded in ParseForm,
+	support Trailers in ReadRequest.
+* lib9: add ctime.
+* math: faster Gamma (thanks Charles L. Dorian),
+	improved accuracy for Tan (thanks Charles L. Dorian),
+	improved high-angle test for Cos, Sin and Tan (thanks Charles L. Dorian).
+* net: implement LookupTXT for windows (thanks Alex Brainman).
+* os,text,unicode: renamings.
+* runtime/cgo: fix data declaration to be extern.
+* runtime: add timespec definition for freebsd,
+	add windows callback tests (thanks Alex Brainman),
+	fix prototype for openbsd thrsleep,
+	fix set and not used,
+	unify mutex code across OSes,
+	windows_386 sighandler to use correct g (thanks Alex Brainman).
+* template: format error with pointer receiver,
+	make redefinition of a template in a set more consistent.
+* test: clear execute bit from source file (thanks Mikio Hara),
+	make closedchan.go exit with failure if something fails.
+* time: faster Nanoseconds call.
+* websocket: return an error HTTP response for bad websocket request.
+* xml: allow parsing of <_> </_>. (thanks David Crawshaw).
+</pre>
+
+<h2 id="2011-11-02">2011-11-02 (new error type)</h2>
+
+<pre>
+This snapshot introduces the built-in error type, defined as
+
+       type error interface {
+               Error() string
+       }
+
+The error type replaces os.Error. Notice that the method name has changed from
+String to Error. Package fmt's Print formats both Stringers and errors:
+in general there is no need to implement both String and Error methods.
+
+Gofix can update most code. If you have split your package across many files,
+it may help to use the -force=error command-line option, which forces gofix to
+apply the error fix even if it is not obvious that a particular file needs it.
+As always, it is a good idea to read and test the changes that gofix made
+before committing them to your version control system.
+</pre>
+
+<h2 id="2011-11-01">2011-11-01</h2>
+
+<pre>
+* 6l: remove mention of -e flag - it does nothing.
+* cc: change cas to newcase (thanks Ron Minnich).
+* crypto/openpgp/error: use Error in names of error impl types.
+* crypto/rsa: change public exponent from 3 to 65537.
+* crypto/tls: add Error method to alert.
+* doc: add link to A Tour of Go in Japanese,
+	add 'all' make rule to build all docs,
+	refer to tour.golang.org instead of go-tour.appspot.com.
+* exp/norm: fixed bug that crept in with moving to the new regexp.
+* exp/ssh: fix length header leaking into channel data (thanks Dave Cheney).
+* fmt: handle os.Error values explicity (as distinct from Stringer).
+* gc: clean up printing,
+	fix [568]g -V crash (thanks Mikio Hara),
+	test + fix escape analysis bug.
+* go/build: avoid os.Error in tests.
+* go/doc: remove os.NewError anti-heuristic.
+* go/parser: test and fix := scoping bug.
+* gob: split uses of gobError, remove unnecessary embedding.
+* gofix: test import insertion, deletion.
+* goinstall: intelligent vcs selection for common sites (thanks Julian Phillips).
+* gopack: change archive file name length back to 16.
+* html: fix print argument in test,
+	more parser improvements (thanks Andrew Balholm).
+* json: properly handle nil slices (thanks Alexander Reece).
+* math: improved accuracy for Sin and Cos (thanks Charles L. Dorian).
+* misc/emacs: fix restoration of windows after gofmt (thanks Jan Newmarch).
+* misc/vim: add rune keyword (thanks Jongmin Kim).
+* misc/windows: can be used for amd64 (thanks Alex Brainman).
+* net: document why we do not use SO_REUSEADDR on windows (thanks Alex Brainman).
+* os: do not interpret 0-length read as EOF.
+* pkg: remove .String() from some print arguments.
+* rpc: avoid infinite loop on input error.
+* runtime/pprof: document OS X being broken.
+* runtime: lock the main goroutine to the main OS thread during init.
+* spec: define that initialization is sequential.
+* strconv: use better errors than os.EINVAL, os.ERANGE.
+* syscall: fix Await msg on Plan 9 (thanks Andrey Mirtchovski).
+* template: do not use error as stringer,
+	fix error checking on execute without parse (thanks Scott Lawrence).
+* test/alias.go: additional tests.
+* test: error-related fixes.
+* textproto: prevent long lines in HTTP headers from causing HTTP 400 responses.
+* time: add RFC1123 with numeric timezone format (thanks Scott Lawrence).
+</pre>
+
+<h2 id="2011-10-26">2011-10-26 (new rune type)</h2>
+
+<pre>
+This snapshot introduces the rune type, an alias for int that
+should be used for Unicode code points.
+
+A future release of Go (after Go 1) will change rune to be an
+alias for int32 instead of int.  Using rune consistently is the way
+to make your code build both before and after this change.
+
+To test your code for rune safety, you can rebuild the Go tree with
+
+	GOEXPERIMENT=rune32 ./all.bash
+
+which builds a compiler in which rune is an alias for int32 instead of int.
+
+Also, run govet on your code to identify methods that might need to have their
+signatures updated.
+</pre>
+
+<h2 id="2011-10-25">2011-10-25</h2>
+
+<pre>
+* big: make SetString return nil if an error occurs,
+	new Rat.Inv method,
+	usable zero Rat values without need for explicit initialization.
+* codereview: show LGTMs in hg p.
+* crypto/x509: fix names in certificate generation.
+* exp/ssh: add experimental ssh client,
+	introduce Session to replace Cmd for interactive commands,
+	server cleanups (thanks Dave Cheney).
+* exp/types: fix crash in parseBasicType on unknown type.
+* fmt: don't panic formatting nil interfaces (thanks Gustavo Niemeyer).
+* go/ast, go/token: actually run tests; fix go/ast test.
+* gotest: explicit -help flag, use $GCFLAGS like make does.
+* govet: check canonical dynamic method signatures.
+* html: improved parsing (thanks Andrew Balholm),
+	parse <select> tags, parse and render comment nodes,
+	remove the Tokenizer.ReturnComments option.
+* http: Transport: with TLS InsecureSkipVerify, skip hostname check.
+* misc/vim: add highlighting for delete (thanks Dave Cheney).
+* net: do not set SO_REUSEADDR for windows (thanks Alex Brainman).
+* os/inotify: move to exp/inotify (thanks Mikio Hara).
+* runtime: include bootstrap m in mcpu accounting (thanks Hector Chu).
+* syscall: use uintptr for Mount flags.
+</pre>
+
+<h2 id="2011-10-18">2011-10-18</h2>
+
+<pre>
+This weekly snapshot includes some language and package changes that may
+require code changes. Please read these notes carefully, as there are many
+changes and your code will likely be affected.
+
+The syntax for map deletion has been changed. Code that looks like:
+	m[x] = 0, false
+should be written as:
+	delete(m, x)
+The compiler still accepts m[x] = 0, false for now; even so, you can use gofix
+to rewrite such assignments into delete(m, x).
+
+The Go compiler will reject a return statement without arguments when any of
+the result variables has been shadowed. Code rejected as a result of this
+change is likely to be buggy.
+
+Receive-only channels (<-chan T) cannot be closed.
+The compiler will diagnose such attempts.
+
+The first element of a map iteration is chosen at random. Code that depends on
+iteration order will need to be updated.
+
+Goroutines may be run during program initialization.
+
+A string may be appended to a byte slice. This code is now legal:
+	var b []byte
+	var s string
+	b = append(b, s...)
+
+The gotry command and its associated try package have been deleted.
+It was a fun experiment that - in the end - didn't carry its weight.
+
+The gotype tool has been moved to exp/gotype and its associated go/types
+package has been moved to exp/types. The deprecated go/typechecker package has
+been deleted.
+
+The enbflint tool has been moved to pkg/exp/ebnflint and its associated ebnf
+package has been moved to pkg/exp/ebnf.
+
+The netchan package has been moved to old/netchan.
+
+The http/spdy package has been moved to exp/spdy.
+
+The exp/datafmt package has been deleted.
+
+The container/vector package has been deleted. Slices are better:
+	http://code.google.com/p/go-wiki/wiki/SliceTricks
+
+Other changes:
+* 5l/6l/8l: correct ELFRESERVE diagnostic (thanks Anthony Martin).
+* 6l/8l: support OS X code signing (thanks Mikkel Krautz).
+* asn1: accept UTF8 strings as ASN.1 ANY values.
+* big: handle aliasing correctly for Rat.SetFrac.
+* build: add missing nuke target (thanks Anthony Martin),
+	catch future accidental dependencies to exp or old packages,
+	more robustly detect gold 2.20 (thanks Christopher Wedgwood),
+	pass $GCFLAGS to compiler,
+	stop on failed deps.bash.
+* crypto/tls: add 3DES ciphersuites,
+	add server side SNI support,
+	fetch root CA from Windows store (thanks Mikkel Krautz),
+	fetch root certificates using Mac OS API (thanks Mikkel Krautz),
+	fix broken looping code in windows root CA fetcher (thanks Mikkel Krautz),
+	more Unix root certificate locations.
+* crypto/x509: add code for dealing with PKIX public keys,
+	keep the raw Subject and Issuer.
+* csv: fix overly aggressive TrimLeadingSpace.
+* exp/ssh: general cleanups for client support (thanks Dave Cheney).
+* exp/template/html: fix bug in cssEscaper.
+* exp/terminal: split terminal handling from exp/ssh.
+* exp/winfsnotify: filesystem watcher for Windows (thanks Hector Chu).
+* fmt: fix test relying on map iteration order.
+* gc: changes to export format in preparation for inlining,
+	pass FlagNoPointers to runtime.new,
+	preserve uint8 and byte distinction in errors and import data,
+	stricter multiple assignment + test,
+	treat uintptr as potentially containing a pointer.
+* go/scanner: remove AllowIllegalChars mode.
+* go/token: document deserialization property.
+* gob: avoid one copy for every message written.
+* godefs: add enum/const testdata (thanks Dave Cheney).
+* godoc: generate package toc in template, not in JavaScript,
+	show "unexported" declarations when executing "godoc builtin",
+	show correct source name with -path.
+* gofix: make fix order explicit, add mapdelete.
+* gofmt: fix //line handling,
+	disallow rewrites for incomplete programs.
+* gotest: avoid conflicts with the name of the tested package (thanks Esko Luontola),
+	test example code.
+* goyacc: clean up after units (thanks Anthony Martin),
+	make more gofmt-compliant.
+* html: add a Render function, various bug fixes and improvements,
+	parser improvements (thanks Andrew Balholm).
+* http: DoS protection: cap non-Handler Request.Body reads,
+	RoundTrippers shouldn't mutate Request,
+	avoid panic caused by nil URL (thanks Anthony Martin),
+	fix read timeouts and closing,
+	remove Request.RawURL.
+* image/tiff: implement PackBits decoding (thanks Benny Siegert).
+* ld: fix "cannot create 8.out.exe" (thanks Jaroslavas Počepko).
+* misc/emacs: add a "godoc" command, like M-x man (thanks Evan Martin).
+* misc/swig: delete binaries (thanks Anthony Martin).
+* misc/windows: automated toolchain packager (thanks Joe Poirier).
+* net/windows: implement ip protocol name to number resolver (thanks Alex Brainman).
+* net: add File method to IPConn (thanks Mikio Hara),
+	allow LookupSRV on non-standard DNS names,
+	fix "unexpected socket family" error from WriteToUDP (thanks Albert Strasheim),
+	fix socket leak in case of Dial failure (thanks Chris Farmiloe),
+	remove duplicate error information in Dial (thanks Andrey Mirtchovski),
+	return error from CloseRead and CloseWrite (thanks Albert Strasheim),
+	skip ICMP test on Windows too unless uid 0.
+* reflect: disallow Interface method on Value obtained via unexported name,
+	make unsafe use of SliceHeader gc-friendly.
+* rpc: don't panic on write error.
+* runtime: faster strings,
+	fix crash if user sets MemProfileRate=0,
+	fix crash when returning from syscall during gc (thanks Hector Chu),
+	fix memory leak in parallel garbage collector.
+* scanner: invalidate scanner.Position when no token is present.
+* spec: define order of multiple assignment.
+* syscall/windows: dll function load and calling changes (thanks Alex Brainman).
+* syscall: add #ifdefs to fix the manual corrections in ztypes_linux_arm.go (thanks Dave Cheney),
+	adjust Mount to accomodate stricter FS implementations.
+* testing: fix time reported for failing tests.
+* utf8: add Valid and ValidString.
+* websocket: tweak hybi ReadHandshake to support Firefox (thanks Luca Greco).
+* xml: match Marshal's XMLName behavior in Unmarshal (thanks Chris Farmiloe).
+</pre>
+
+<h2 id="2011-10-06">2011-10-06</h2>
+
+<pre>
+This weekly snapshot includes changes to the io, image, and math packages that
+may require changes to client code.
+
+The io package's Copyn function has been renamed to CopyN.
+
+The math package's Fabs, Fdim, Fmax, Fmin and Fmod functions
+have been renamed to Abs, Dim, Max, Min, and Mod.
+
+Parts of the image package have been moved to the new image/color package.
+The spin-off renames some types. The new names are simply better:
+	image.Color              -> color.Color
+	image.ColorModel         -> color.Model
+	image.ColorModelFunc     -> color.ModelFunc
+	image.PalettedColorModel -> color.Palette
+	image.RGBAColor          -> color.RGBA
+	image.RGBAColorModel     -> color.RGBAModel
+	image.RGBA64Color        -> color.RGBA64
+	image.RGBA64ColorModel   -> color.RGBA64Model
+(similarly for NRGBAColor, GrayColorModel, etc)
+The image.ColorImage type stays in the image package, but is renamed:
+	image.ColorImage -> image.Uniform
+The image.Image implementations (image.RGBA, image.RGBA64, image.NRGBA,
+image.Alpha, etc) do not change their name, and gain a nice symmetry:
+an image.RGBA is an image of color.RGBA, etc.
+The image.Black, image.Opaque uniform images remain unchanged (although their
+type is renamed from image.ColorImage to image.Uniform).
+The corresponding color types (color.Black, color.Opaque, etc) are new.
+Nothing in the image/ycbcr is renamed yet. The ycbcr.YCbCrColor and
+ycbcr.YCbCrImage types will eventually migrate to color.YCbCr and image.YCbCr,
+at a later date.
+
+* 5g/6g/8g: fix loop finding bug, fix -f(), registerize variables again.
+* 5l/6l/8l: add a DT_DEBUG dynamic tag to a dynamic ELF binary.
+* archive/zip: read and write unix file modes (thanks Gustavo Niemeyer).
+* build: clear execute bit from source files (thanks Mikio Hara).
+* bytes: add EqualFold.
+* cgo: allow Windows path characters in flag directives (thanks Joe Poirier),
+	support for mingw-w64 4.5.1 and newer (thanks Wei Guangjing).
+* codereview: extra repo sanity check,
+	fix for Mercurial 1.9.2,
+	fix hg change in Windows console (thanks Yasuhiro Matsumoto).
+* crypto/elliptic: use %x consistently in error print.
+* doc/spec: remove notes about gccgo limitations, now fixed.
+* doc: add 'Debugging Go code with GDB' tutorial,
+	fix memory model read visibility bug.
+* encoding/binary: PutX functions require buffer of sufficient size,
+	added benchmarks, support for varint encoding.
+* exec: add Command.ExtraFiles.
+* exp/sql{,/driver}: new database packages.
+* exp/ssh: move common code to common.go (thanks Dave Cheney).
+* exp/template/html: work continues.
+* fmt: replace channel cache with slice.
+* gc: limit helper threads based on ncpu.
+* go/doc, godoc, gotest: support for reading example documentation.
+* go: documentation and skeleton implementation of new command.
+* gob: protect against invalid message length,
+	allow sequential decoders on the same input stream.
+* hgpatch: do not use hg exit status (thanks Yasuhiro Matsumoto).
+* http: add Location method to Response,
+	don't send a 400 Bad Request after a client shutdown.
+* index/suffixarray: 4.5x faster index serialization (to memory).
+* io/ioutil: add a comment on why devNull is a ReaderFrom.
+* json: use strings.EqualFold instead of strings.ToLower.
+* misc/emacs: fix indent bug.
+* net: add shutdown: TCPConn.CloseWrite and CloseRead.
+* net: use AF_UNSPEC instead of individual address family (thanks Mikio Hara).
+* path/filepath: added Rel as the complement of Abs (thanks Gustavo Niemeyer).
+* pkg/syscall: add Mkfifo for linux platforms.
+* regexp: move to old/regexp, replace with exp/regexp, speedups.
+* runtime/gdb: fix pretty printing of channels,
+	gracefully handle not being able to find types.
+* runtime: check for nil value pointer in select syncsend case,
+	faster finalizers,
+	fix malloc sampling bug,
+	fix map memory leak,
+	fix spurious deadlock reporting,
+	fix usleep on linux/386 and re-enable parallel gc (thanks Hector Chu),
+	parallelize garbage collector mark + sweep.
+* strconv: faster Unquote in common case.
+* strings: add EqualFold, Replacer, NewReplacer.
+* suffixarray: add benchmarks for construction (thanks Eric Eisner).
+* syscall: add GetsockoptByte, SetsockoptByte for openbsd (thanks Mikio Hara),
+	add IPv4 ancillary data for linux (thanks Mikio Hara),
+	mark stdin, stdout, stderr non-inheritable by child processes (thanks Alex Brainman),
+	mksyscall_windows.pl creates non-syscall packages (thanks Jaroslavas Počepko),
+	update multicast socket options (thanks Mikio Hara).
+* testing: support for running tests in parallel (thanks Miki Tebeka).
+* time: make month/day name comparisons case insenstive.
+* unicode: fix make tables.
+* vim: Send GoFmt errors to a location list (thanks Paul Sbarra).
+* websocket: add hybi-13 support, add mutex to make websocket full-duplex.
+</pre>
+
 <h2 id="2011-09-21">2011-09-21</h2>
 
 <pre>
@@ -544,7 +1811,7 @@ Other changes:
 * exp/regexp/syntax: add Prog.NumCap.
 * exp/template: API changes, bug fixes, and tweaks.
 * flag: make -help nicer.
-* fmt: Scan(&int) was mishandling a lone digit.
+* fmt: Scan(&int) was mishandling a lone digit.
 * gc: fix closure bug,
 	fix to build with clang (thanks Dave Cheney),
 	make size of struct{} and [0]byte 0 bytes (thanks Robert Hencke),
@@ -702,7 +1969,7 @@ Other changes:
 <h2 id="2011-06-23">2011-06-23</h2>
 
 <pre>
-This release includes a language change that restricts the use of goto.
+This snapshot includes a language change that restricts the use of goto.
 In essence, a "goto" statement outside a block cannot jump to a label inside
 that block. Your code may require changes if it uses goto.
 This changeset shows how the new rule affected the Go tree:
@@ -725,7 +1992,7 @@ Other changes:
         add support for Plan 9 (thanks Anthony Martin),
         better error message for windows LookPath (thanks Alex Brainman).
 * fmt: catch panics from calls to String etc.
-* gc: descriptive panic for nil pointer -> value method call,
+* gc: descriptive panic for nil pointer -> value method call,
         implement goto restriction,
         unsafe.Alignof, unsafe.Offsetof, unsafe.Sizeof now return uintptr.
 * go/build: include Import objects in Script Inputs.
@@ -763,7 +2030,7 @@ Other changes:
 <h2 id="2011-06-16">2011-06-16</h2>
 
 <pre>
-This release includes changes to the sort and image/draw packages that will
+This snapshot includes changes to the sort and image/draw packages that will
 require changes to client code.
 
 The sort.IntArray type has been renamed to IntSlice, and similarly for
@@ -800,7 +2067,7 @@ Other changes:
 * net: export all fields in Interface (thanks Mikio Hara),
         rearrange source to run more tests on Windows (thanks Alex Brainman),
         sendfile for win32 (thanks Yasuhiro Matsumoto).
-* os: Plan 9, fix OpenFile & Chmod, add Process.Kill (thanks Yuval Pavel Zholkover).
+* os: Plan 9, fix OpenFile & Chmod, add Process.Kill (thanks Yuval Pavel Zholkover).
 * runtime: fix Plan 9 "lingering goroutines bug" (thanks Yuval Pavel Zholkover).
 * spec: clarify rules for append, scope rules for :=,
         specify constant conversions,
@@ -816,7 +2083,7 @@ Other changes:
 <h2 id="2011-06-09">2011-06-09 (<a href="release.html#r58">base for r58</a>)</h2>
 
 <pre>
-This release includes changes to the strconv, http, and exp/draw packages.
+This snapshot includes changes to the strconv, http, and exp/draw packages.
 Client code that uses the http or exp/draw packages will need to be changed,
 and code that uses strconv or fmt's "%q" formatting directive merits checking.
 
@@ -874,7 +2141,7 @@ Other changes:
 <h2 id="2011-06-02">2011-06-02</h2>
 
 <pre>
-This release includes changes to the exec package that will require changes
+This snapshot includes changes to the exec package that will require changes
 to client code.
 
 The exec package has been re-designed with a more convenient and succinct API.
@@ -886,7 +2153,7 @@ This code:
 		return nil, err
 	}
 	var buf bytes.Buffer
-	io.Copy(&buf, p.Stdout)
+	io.Copy(&buf, p.Stdout)
 	w, err := p.Wait(0)
 	p.Close()
 	if err != nil {
@@ -944,7 +2211,7 @@ Other changes:
 * goinstall: fixes for windows (thanks Alex Brainman),
 	more verbose logging with -v.
 * gotest, pkg/exec: use bash to run shell scripts on windows (thanks Alex Brainman).
-* http/spdy: redo interfaces, flesh out implementation & frame types (thanks William Chan).
+* http/spdy: redo interfaces, flesh out implementation & frame types (thanks William Chan).
 * http: Transport hook to register non-http(s) protocols,
 	add client+server benchmark,
 	catch Handler goroutine panics,
@@ -995,7 +2262,7 @@ Other changes:
 <h2 id="2011-05-22">2011-05-22</h2>
 
 <pre>
-This release includes changes to the http package that will require changes to
+This snapshot includes changes to the http package that will require changes to
 client code.
 
 The finalURL return value of the Client.Get method has been removed.
@@ -1015,7 +2282,7 @@ should be rewritten as:
 Uses of http.Get that assign the finalURL value to _ can be rewritten
 automatically with gofix.
 
-This release also includes an optimization to the append function that makes it
+This snapshot also includes an optimization to the append function that makes it
 between 2 and 5 times faster in typical use cases.
 
 Other changes:
@@ -1100,7 +2367,7 @@ Other changes:
 * image/tiff: implement a decoder (thanks Benny Siegert).
 * image: add type-specific Set methods and use them when decoding PNG,
 	make AlphaColor.Set conform to usual signature (thanks Roger Peppe),
-	png & jpeg encoding benchmarks.
+	png & jpeg encoding benchmarks.
 * ld: do not emit reference to dynamic library named "",
 	fix alignment of rodata section on Plan 9 (thanks Anthony Martin),
 	make ELF binaries with no shared library dependencies static binaries.
@@ -1119,7 +2386,7 @@ Other changes:
 	protocol family adaptive address family selection (thanks Mikio Hara),
 	re-enable wildcard listening (thanks Mikio Hara),
 	sort records returned by LookupSRV (thanks Gary Burd).
-* os: make Readdir & Readdirnames return os.EOF at end,
+* os: make Readdir & Readdirnames return os.EOF at end,
 	make Setenv update C environment variables.
 * reflect: allow unexported key in Value.MapIndex.
 * runtime, sync/atomic: fix arm cas.
@@ -1149,7 +2416,7 @@ Other changes:
 <h2 id="2011-04-27">2011-04-27 (<a href="release.html#r57">base for r57</a>)</h2>
 
 <pre>
-This release includes revisions to the reflect package to make it more
+This snapshot includes revisions to the reflect package to make it more
 efficient, after the last weekly's major API update. If your code uses reflect
 it may require further changes, not all of which can be made automatically by
 gofix. For the full details of the change, see
@@ -1370,7 +2637,7 @@ Other changes:
 <h2 id="2011-04-04">2011-04-04</h2>
 
 <pre>
-This release includes changes to the net package. Your code will require
+This snapshot includes changes to the net package. Your code will require
 changes if it uses the Dial or LookupHost functions.
 
 The laddr argument has been removed from net.Dial, and the cname return value
@@ -1459,7 +2726,7 @@ Other changes:
 * go/printer, gofmt: avoid exponential layout algorithm,
         gofmt: simplify struct formatting and respect line breaks.
 * go/scanner: to interpret line comments with Windows filenames (thanks Alex Brainman).
-* go/token: use array instead of map for token->string table.
+* go/token: use array instead of map for token->string table.
 * gob: optimizations to reduce allocations,
         use pointers in bootstrapType so interfaces behave properly.
 * gobuilder: recognize CLs of the form weekly.DATE.
@@ -1565,7 +2832,7 @@ arguments as an *os.ProcAttr and *syscall.ProcAttr values, respectively. This
 code:
 	os.StartProcess(bin, args, env, dir, fds)
 should now be written as:
-	os.StartProcess(bin, args, &os.ProcAttr{Files: fds, Dir: dir, Env: env})
+	os.StartProcess(bin, args, &os.ProcAttr{Files: fds, Dir: dir, Env: env})
 
 The gob package will now encode and decode values of types that implement the
 gob.GobEncoder and gob.GobDecoder interfaces. This allows types with unexported
@@ -1966,12 +3233,12 @@ This release also changes some of the internal structure of the memory
 allocator in preparation for other garbage collector changes. 
 If you run into problems, please let us know.
 There is one known issue that we are aware of but have not debugged yet:
-	http://code.google.com/p/go/issues/detail?id=1464&.
+	http://code.google.com/p/go/issues/detail?id=1464&.
 
 Other changes in this release:
 * 5l: document -F, force it on old ARMs (software floating point emulation)
 * 6g: fix registerization of temporaries (thanks Eoghan Sherry),
-        fix uint64(uintptr(unsafe.Pointer(&x))).
+        fix uint64(uintptr(unsafe.Pointer(&x))).
 * 6l: Relocate CMOV* instructions (thanks Gustavo Niemeyer),
         windows/amd64 port (thanks Wei Guangjing).
 * 8l: add PE dynexport, emit DWARF in Windows PE, and
@@ -2175,7 +3442,7 @@ This release includes several fixes and changes:
         normalize processing of format string.
 * gc: return constant floats for parts of complex constants (thanks Anthony Martin),
         rewrite complex /= to l = l / r (thanks Patrick Gavlin),
-        fix &^=.
+        fix &^=.
 * go/ast: provide complete node text range info.
 * gob: generate a better error message in one confusing place.
 * godoc: fix godoc -src (thanks Icarus Sparry).
@@ -2366,9 +3633,9 @@ will fail to compile rather than behave erroneously.
 The bytes package has changed. Its Add and AddByte functions have been removed,
 as their functionality is provided by the recently-introduced built-in function
 "append". Any code that uses them will need to be changed:
-s = bytes.Add(s, b)    ->    s = append(s, b...)
-s = bytes.AddByte(b, c)    ->    s = append(s, b)
-s = bytes.Add(nil, c)    ->    append([]byte(nil), c)
+s = bytes.Add(s, b)    ->    s = append(s, b...)
+s = bytes.AddByte(b, c)    ->    s = append(s, b)
+s = bytes.Add(nil, c)    ->    append([]byte(nil), c)
 
 The template package has changed. Your code will need to be updated if it calls
 the HTMLFormatter or StringFormatter functions, or implements its own formatter
@@ -2634,12 +3901,12 @@ standard error by default.  The names have also changed, although the old names
 are still supported.  They will be deleted in the next release, though, so it
 would be good to update now if you can.  For most purposes all you need to do
 is make these substitutions:
-        log.Stderr -> log.Println or log.Print
-        log.Stderrf -> log.Printf
-        log.Crash -> log.Panicln or log.Panic
-        log.Crashf -> log.Panicf
-        log.Exit -> log.Exitln or log.Exit
-        log.Exitf -> log.Exitf (no change)
+        log.Stderr -> log.Println or log.Print
+        log.Stderrf -> log.Printf
+        log.Crash -> log.Panicln or log.Panic
+        log.Crashf -> log.Panicf
+        log.Exit -> log.Exitln or log.Exit
+        log.Exitf -> log.Exitf (no change)
 Calls to log.New() must drop the second argument.
 Also, custom loggers with exit or panic properties will need to be reworked.
 For full details, see the change description:
@@ -2878,7 +4145,7 @@ as well as the following fixes and changes:
         implement new slice spec (thanks Scott Lawrence)
         make string x + y + z + ... + w efficient
         more accurate line numbers for ATEXT
-        remove &[10]int -> []int conversion
+        remove &[10]int -> []int conversion
 * go-mode.el: fix highlighting for 'chan' type (thanks Scott Lawrence)
 * godoc: better support for directory trees for user-supplied paths
         use correct delay time (bug fix)
@@ -3364,7 +4631,7 @@ clarifications and consolidations to the Language Specification.
 
 The type checking rules around assignments and conversions are simpler but more
 restrictive: assignments no longer convert implicitly from *[10]int to []int
-(write x[0:] instead of &x), and conversions can no longer change the names of
+(write x[0:] instead of &x), and conversions can no longer change the names of
 types inside composite types.
 
 The fmt package now includes flexible type-driven (fmt.Scan) and 
@@ -3396,7 +4663,7 @@ format-driven (fmt.Scanf) scanners for all basic types.
 * os/signal: correct the regexp for finding Unix signal names (thanks Vinu Rajashekhar).
 * regexp: optimizations (thanks Kyle Consalus).
 * runtime: fix printing -Inf (thanks Evan Shaw),
-        finish pchw -> tiny, added gettime for tiny (thanks Daniel Theophanes).
+        finish pchw -> tiny, added gettime for tiny (thanks Daniel Theophanes).
 * spec: clean-ups and consolidation.
 * syscall: additional Windows compatibility fixes (thanks Alex Brainman).
 * test/bench: added regex-dna-parallel.go (thanks Kyle Consalus).
@@ -3419,10 +4686,10 @@ preparing for Google I/O.
 * cmath: update range of Phase and Polar due to signed zero (thanks Charles L. Dorian).
 * codereview: work better with mq (thanks Peter Williams).
 * compress: renamings
-	NewDeflater -> NewWriter
-	NewInflater -> NewReader
-	Deflater -> Compressor
-	Inflater -> Decompressor
+	NewDeflater -> NewWriter
+	NewInflater -> NewReader
+	Deflater -> Compressor
+	Inflater -> Decompressor
 * exp/draw/x11: respect $XAUTHORITY,
         treat $DISPLAY the same way x-go-bindings does.
 * exp/draw: fast path for glyph images, other optimizations,
@@ -3444,7 +4711,7 @@ preparing for Google I/O.
         fix printing of labels.
 * http: prevent crash if remote server is not responding with "HTTP/".
 * json: accept escaped slash in string scanner (thanks Michael Hoisie),
-        fix array -> non-array decoding.
+        fix array -> non-array decoding.
 * libmach: skip __nl_symbol_ptr section on OS X.
 * math: amd64 versions of Fdim, Fmax, Fmin,
         signed zero Sqrt special case (thanks Charles L. Dorian).
@@ -3739,8 +5006,8 @@ This release also includes the goinstall command-line tool.
 There is one language change: the ability to convert a string to []byte or 
 []int.  This deprecates the strings.Bytes and strings.Runes functions.
 You can convert your existing sources using these gofmt commands:
-	gofmt -r 'strings.Bytes(x) -> []byte(x)' -w file-or-directory-list
-	gofmt -r 'strings.Runes(x) -> []int(x)' -w file-or-directory-list
+	gofmt -r 'strings.Bytes(x) -> []byte(x)' -w file-or-directory-list
+	gofmt -r 'strings.Runes(x) -> []int(x)' -w file-or-directory-list
 After running these you might need to delete unused imports of the "strings" 
 package.
 
@@ -3900,7 +5167,7 @@ There are no language changes.
 
 build: $GOBIN should no longer be required in $PATH (thanks Devon H. O'Dell),
 	new package target "make bench" to run benchmarks
-8g: faster float -> uint64 conversion (thanks Evan Shaw)
+8g: faster float -> uint64 conversion (thanks Evan Shaw)
 5g, 6g, 8g:
 	clean opnames.h to avoid stale errors (thanks Yongjian Xu),
 	a handful of small compiler fixes
diff --git a/doc/docs.html b/doc/docs.html
index b6e8028..e99017f 100644
--- a/doc/docs.html
+++ b/doc/docs.html
@@ -1,4 +1,7 @@
-<!-- title Documentation -->
+<!--{
+	"Title": "Documentation",
+	"Path": "/doc/"
+}-->
 
 <div class="left-column">
 
@@ -16,6 +19,16 @@ Once you've learned a little about the language,
 idioms of programming in Go.
 </p>
 
+<h3 id="go_tour"><a href="http://tour.golang.org/">A Tour of Go</a></h3>
+<p>
+An interactive introduction to Go in three sections.
+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="http://tour.golang.org/">take the tour online</a> or
+<a href="http://code.google.com/p/go-tour/">install it locally</a>.
+</p>
+
 <h3 id="orig_tutorial"><a href="go_tutorial.html">A Tutorial for the Go Programming Language</a></h3>
 <p>
 The first tutorial. An introductory text that touches upon several core
@@ -23,17 +36,6 @@ concepts: syntax, types, allocation, constants, I/O, sorting, printing,
 goroutines, and channels.
 </p>
 
-<h3 id="course_notes">Course Notes</h3>
-<p>
-Slides from a 3-day course about the Go programming language.
-A more thorough introduction than the tutorial.
-</p>
-<ul>
-<li><a href="GoCourseDay1.pdf">Day 1: Basics</a> <small>[270KB PDF]</small></li>
-<li><a href="GoCourseDay2.pdf">Day 2: Types, Methods, Interfaces</a> <small>[270KB PDF]</small></li>
-<li><a href="GoCourseDay3.pdf">Day 3: Concurrency and Communication</a> <small>[180KB PDF]</small></li>
-</ul>
-
 <h3 id="effective_go"><a href="effective_go.html">Effective Go</a></h3>
 <p>
 A document that gives tips for writing clear, idiomatic Go code.
@@ -94,9 +96,11 @@ Notable articles from the <a href="http://blog.golang.org/">Go Blog</a>.
 <h3>Packages</h3>
 
 <ul>
-<li><a href="http://blog.golang.org/2011/01/json-and-go.html">JSON and Go</a> - using the <a href="/pkg/json/">json</a> package.</li>
-<li><a href="http://blog.golang.org/2011/03/gobs-of-data.html">Gobs of data</a> - the design and use of the <a href="/pkg/gob/">gob</a> package.</li>
+<li><a href="http://blog.golang.org/2011/01/json-and-go.html">JSON and Go</a> - using the <a href="/pkg/encoding/json/">json</a> package.</li>
+<li><a href="http://blog.golang.org/2011/03/gobs-of-data.html">Gobs of data</a> - the design and use of the <a href="/pkg/encoding/gob/">gob</a> package.</li>
 <li><a href="http://blog.golang.org/2011/09/laws-of-reflection.html">The Laws of Reflection</a> - the fundamentals of the <a href="/pkg/reflect/">reflect</a> package.</li>
+<li><a href="http://blog.golang.org/2011/09/go-image-package.html">The Go image package</a> - the fundamentals of the <a href="/pkg/image/">image</a> package.</li>
+<li><a href="http://blog.golang.org/2011/09/go-imagedraw-package.html">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
 </ul>
 
 <h3>Tools</h3>
@@ -118,10 +122,17 @@ Notable articles from the <a href="http://blog.golang.org/">Go Blog</a>.
 <h3 id="docs_cn">Chinese — 中文</h3>
 
 <ul>
+<li><a href="http://go-tour-zh.appspot.com/">A Tour of Go</a></li>
 <li><a href="http://code.google.com/p/golang-china/">golang-china</a> - a broad range of Go documentation.</li>
 <li><a href="http://code.google.com/p/ac-me/downloads/detail?name=fango.pdf">Effective Go and Tutorial</a></li>
 </ul>
 
+<h3 id="docs_cz">Czech — ÄŒeÅ¡tina</h3>
+
+<ul>
+<li><a href="http://www.abclinuxu.cz/clanky/google-go-pravidla-reflexe">Pravidla reflexe</a> - a translation of <a href="http://blog.golang.org/2011/09/laws-of-reflection.html">The Laws of Reflection</a>.</li>
+</ul>
+
 <h3 id="docs_fr">French — Français</h3>
 
 <ul>
@@ -139,17 +150,14 @@ Notable articles from the <a href="http://blog.golang.org/">Go Blog</a>.
 
 <h3 id="docs_jp">Japanese — 日本語</h3>
 <ul>
-<li><a href="http://golang.jp/">golang.jp</a> - Go documentation and news.
+<li><a href="http://go-tour-jp.appspot.com/">A Tour of Go</a></li>
+<li><a href="http://golang.jp/">golang.jp</a> - Go documentation and news.</li>
 </ul>
 
 <h3 id="docs_kr">Korean — 한국어</h3>
 <ul>
-<li><a href="http://code.google.com/p/golang-korea">golang-korea</a> - Go documentation and news.
-</ul>
-
-<h3 id="docs_ru">Russian — Русский</h3>
-<ul>
-<li><a href="http://golanguage.ru/">golanguage.ru</a> - Go documentation.
+<li><a href="http://go-tour-kr.appspot.com">A Tour of Go</a></li>
+<li><a href="http://code.google.com/p/golang-korea">golang-korea</a> - Go documentation and news.</li>
 </ul>
 
 </div>
@@ -186,6 +194,11 @@ one goroutine can be guaranteed to observe values produced by writes to the
 same variable in a different goroutine.
 </p>
 
+<h3 id="debugging_with_gdb"><a href="debugging_with_gdb.html">Debugging Go Code with GDB</a></h3>
+<p>
+Using GDB to debug Go programs.
+</p>
+
 <h2 id="videos_talks">Videos and Talks</h2>
 
 <h3 id="writing_web_apps"><a href="http://www.youtube.com/watch?v=-i0hat7pdpk">Writing Web Apps in Go</a></h3>
diff --git a/doc/effective_go.html b/doc/effective_go.html
index 6adf7e5..4ecbe19 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -1,4 +1,11 @@
-<!-- Effective Go -->
+<!--{
+	"Title": "Effective Go"
+}-->
+<!--
+  DO NOT EDIT: created by
+    tmpltohtml effective_go.tmpl
+-->
+
 
 <h2 id="introduction">Introduction</h2>
 
@@ -221,7 +228,7 @@ starts with the name being declared.
 <pre>
 // Compile parses a regular expression and returns, if successful, a Regexp
 // object that can be used to match against text.
-func Compile(str string) (regexp *Regexp, error os.Error) {
+func Compile(str string) (regexp *Regexp, err error) {
 </pre>
 
 <p>
@@ -233,9 +240,9 @@ Since the whole declaration is presented, such a comment can often be perfunctor
 <pre>
 // Error codes returned by failures to parse an expression.
 var (
-    ErrInternal      = os.NewError("regexp: internal error")
-    ErrUnmatchedLpar = os.NewError("regexp: unmatched '('")
-    ErrUnmatchedRpar = os.NewError("regexp: unmatched ')'")
+    ErrInternal      = errors.New("regexp: internal error")
+    ErrUnmatchedLpar = errors.New("regexp: unmatched '('")
+    ErrUnmatchedRpar = errors.New("regexp: unmatched ')'")
     ...
 )
 </pre>
@@ -526,12 +533,62 @@ if err != nil {
 }
 d, err := f.Stat()
 if err != nil {
+    f.Close()
     return err
 }
 codeUsing(f, d)
 </pre>
 
 
+<h3 id="redeclaration">Redeclaration</h3>
+
+<p>
+An aside: The last example in the previous section demonstrates a detail of how the
+<code>:=</code> short declaration form works.
+The declaration that calls <code>os.Open</code> reads,
+</p>
+
+<pre>
+f, err := os.Open(name)
+</pre>
+
+<p>
+This statement declares two variables, <code>f</code> and <code>err</code>.
+A few lines later, the call to <code>f.Stat</code> reads,
+</p>
+
+<pre>
+d, err := f.Stat()
+</pre>
+
+<p>
+which looks as if it declares <code>d</code> and <code>err</code>.
+Notice, though, that <code>err</code> appears in both statements.
+This duplication is legal: <code>err</code> is declared by the first statement,
+but only <em>re-assigned</em> in the second.
+This means that the call to <code>f.Stat</code> uses the existing
+<code>err</code> variable declared above, and just gives it a new value.
+</p>
+
+<p>
+In a <code>:=</code> declaration a variable <code>v</code> may appear even
+if it has already been declared, provided:
+</p>
+
+<ul>
+<li>this declaration is in the same scope as the existing declaration of <code>v</code>
+(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable),</li>
+<li>the corresponding value in the initialization is assignable to <code>v</code>, and</li>
+<li>there is at least one other variable in the declaration that is being declared anew.</li>
+</ul>
+
+<p>
+This unusual property is pure pragmatism,
+making it easy to use a single <code>err</code> value, for example,
+in a long <code>if-else</code> chain.
+You'll see it used often.
+</p>
+
 <h3 id="for">For</h3>
 
 <p>
@@ -717,12 +774,12 @@ The signature of <code>*File.Write</code> in package <code>os</code> is:
 </p>
 
 <pre>
-func (file *File) Write(b []byte) (n int, err Error)
+func (file *File) Write(b []byte) (n int, err error)
 </pre>
 
 <p>
 and as the documentation says, it returns the number of bytes
-written and a non-nil <code>Error</code> when <code>n</code>
+written and a non-nil <code>error</code> when <code>n</code>
 <code>!=</code> <code>len(b)</code>.
 This is a common style; see the section on error handling for more examples.
 </p>
@@ -788,7 +845,7 @@ of <code>io.ReadFull</code> that uses them well:
 </p>
 
 <pre>
-func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
+func ReadFull(r Reader, buf []byte) (n int, err error) {
     for len(buf) > 0 && err == nil {
         var nr int
         nr, err = r.Read(buf)
@@ -812,7 +869,7 @@ canonical examples are unlocking a mutex or closing a file.
 
 <pre>
 // Contents returns the file's contents as a string.
-func Contents(filename string) (string, os.Error) {
+func Contents(filename string) (string, error) {
     f, err := os.Open(filename)
     if err != nil {
         return "", err
@@ -825,7 +882,7 @@ func Contents(filename string) (string, os.Error) {
         n, err := f.Read(buf[0:])
         result = append(result, buf[0:n]...) // append is discussed later.
         if err != nil {
-            if err == os.EOF {
+            if err == io.EOF {
                 break
             }
             return "", err  // f will be closed if we return here.
@@ -1195,7 +1252,7 @@ limit of how much data to read.  Here is the signature of the
 <code>os</code>:
 </p>
 <pre>
-func (file *File) Read(buf []byte) (n int, err os.Error)
+func (file *File) Read(buf []byte) (n int, err error)
 </pre>
 <p>
 The method returns the number of bytes read and an error value, if
@@ -1211,7 +1268,7 @@ the moment, this snippet would also read the first 32 bytes of the buffer.
 </p>
 <pre>
     var n int
-    var err os.Error
+    var err error
     for i := 0; i < 32; i++ {
         nbytes, e := f.Read(buf[i:i+1])  // Read one byte.
         if nbytes == 0 || e != nil {
@@ -1439,7 +1496,7 @@ format <code>%#v</code> prints the value in full Go syntax.
 <pre>
 type T struct {
     a int
-    b float
+    b float64
     c string
 }
 t := &T{ 7, -2.35, "abc\tdef" }
@@ -1509,7 +1566,7 @@ for its final argument to specify that an arbitrary number of parameters (of arb
 can appear after the format.
 </p>
 <pre>
-func Printf(format string, v ...interface{}) (n int, errno os.Error) {
+func Printf(format string, v ...interface{}) (n int, err error) {
 </pre>
 <p>
 Within the function <code>Printf</code>, <code>v</code> acts like a variable of type
@@ -1635,8 +1692,7 @@ const (
     EB
     ZB
     YB
-)
-</pre>
+)</pre>
 <p>
 The ability to attach a method such as <code>String</code> to a
 type makes it possible for such values to format themselves
@@ -1663,8 +1719,7 @@ automatically for printing, even as part of a general type.
         return fmt.Sprintf("%.2fKB", float64(b/KB))
     }
     return fmt.Sprintf("%.2fB", float64(b))
-}
-</pre>
+}</pre>
 <p>
 (The <code>float64</code> conversions prevent <code>Sprintf</code> 
 from recurring back through the <code>String</code> method for 
@@ -1760,7 +1815,7 @@ In fact, we can do even better.  If we modify our function so it looks
 like a standard <code>Write</code> method, like this,
 </p>
 <pre>
-func (p *ByteSlice) Write(data []byte) (n int, err os.Error) {
+func (p *ByteSlice) Write(data []byte) (n int, err error) {
     slice := *p
     // Again as above.
     *p = slice
@@ -1838,8 +1893,7 @@ func (s Sequence) String() string {
         str += fmt.Sprint(elem)
     }
     return str + "]"
-}
-</pre>
+}</pre>
 
 <h3 id="conversions">Conversions</h3>
 
@@ -1871,7 +1925,7 @@ do create a new value.)
 It's an idiom in Go programs to convert the
 type of an expression to access a different
 set of methods. As an example, we could use the existing
-type <code>sort.IntArray</code> to reduce the entire example
+type <code>sort.IntSlice</code> to reduce the entire example
 to this:
 </p>
 <pre>
@@ -1879,14 +1933,14 @@ type Sequence []int
 
 // Method for printing - sorts the elements before printing
 func (s Sequence) String() string {
-    sort.IntArray(s).Sort()
+    sort.IntSlice(s).Sort()
     return fmt.Sprint([]int(s))
 }
 </pre>
 <p>
 Now, instead of having <code>Sequence</code> implement multiple
 interfaces (sorting and printing), we're using the ability of a data item to be
-converted to multiple types (<code>Sequence</code>, <code>sort.IntArray</code>
+converted to multiple types (<code>Sequence</code>, <code>sort.IntSlice</code>
 and <code>[]int</code>), each of which does some part of the job.
 That's more unusual in practice but can be effective.
 </p>
@@ -1915,42 +1969,53 @@ the rest of the code is unaffected by the change of algorithm.
 </p>
 <p>
 A similar approach allows the streaming cipher algorithms
-in the <code>crypto/block</code> package to be
+in the various <code>crypto</code> packages to be
 separated from the block ciphers they chain together.
-By analogy with the <code>bufio</code> package,
-they wrap a <code>Cipher</code> interface
-and return <code>hash.Hash</code>,
-<code>io.Reader</code>, or <code>io.Writer</code>
-interface values, not specific implementations.
+The <code>Block</code> interface
+in the <code>crypto/cipher</code>package specifies the
+behavior of a block cipher, which provides encryption
+of a single block of data.
+Then, by analogy with the <code>bufio</code> package,
+cipher packages that implement this interface
+can be used to construct streaming ciphers, represented
+by the <code>Stream</code> interface, without
+knowing the details of the block encryption.
 </p>
 <p>
-The interface to <code>crypto/block</code> includes:
+The  <code>crypto/cipher</code> interfaces look like this:
 </p>
 <pre>
-type Cipher interface {
+type Block interface {
     BlockSize() int
     Encrypt(src, dst []byte)
     Decrypt(src, dst []byte)
 }
 
-// NewECBDecrypter returns a reader that reads data
-// from r and decrypts it using c in electronic codebook (ECB) mode.
-func NewECBDecrypter(c Cipher, r io.Reader) io.Reader
+type Stream interface {
+    XORKeyStream(dst, src []byte)
+}
+</pre>
+
+<p>
+Here's the definition of the counter mode (CTR) stream,
+which turns a block cipher into a streaming cipher; notice
+that the block cipher's details are abstracted away:
+</p>
 
-// NewCBCDecrypter returns a reader that reads data
-// from r and decrypts it using c in cipher block chaining (CBC) mode
-// with the initialization vector iv.
-func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader
+<pre>
+// NewCTR returns a Stream that encrypts/decrypts using the given Block in
+// counter mode. The length of iv must be the same as the Block's block size.
+func NewCTR(block Block, iv []byte) Stream
 </pre>
 <p>
-<code>NewECBDecrypter</code> and <code>NewCBCReader</code> apply not
+<code>NewCTR</code> applies not
 just to one specific encryption algorithm and data source but to any
-implementation of the <code>Cipher</code> interface and any
-<code>io.Reader</code>.  Because they return <code>io.Reader</code>
-interface values, replacing ECB
-encryption with CBC encryption is a localized change.  The constructor
+implementation of the <code>Block</code> interface and any
+<code>Stream</code>.  Because they return
+interface values, replacing CTR
+encryption with other encryption modes is a localized change.  The constructor
 calls must be edited, but because the surrounding code must treat the result only
-as an <code>io.Reader</code>, it won't notice the difference.
+as a <code>Stream</code>, it won't notice the difference.
 </p>
 
 <h3 id="interface_methods">Interfaces and methods</h3>
@@ -1996,7 +2061,7 @@ func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 <code>http.ResponseWriter</code>.)
 For reference, here's how to attach such a server to a node on the URL tree.
 <pre>
-import "http"
+import "net/http"
 ...
 ctr := new(Counter)
 http.Handle("/counter", ctr)
@@ -2035,7 +2100,7 @@ It's easy to write a function to print the arguments.
 </p>
 <pre>
 func ArgServer() {
-    for i, s := range os.Args {
+    for _, s := range os.Args {
         fmt.Println(s)
     }
 }
@@ -2073,7 +2138,7 @@ to have the right signature.
 <pre>
 // Argument server.
 func ArgServer(w http.ResponseWriter, req *http.Request) {
-    for i, s := range os.Args {
+    for _, s := range os.Args {
         fmt.Fprintln(w, s)
     }
 }
@@ -2081,8 +2146,8 @@ func ArgServer(w http.ResponseWriter, req *http.Request) {
 <p>
 <code>ArgServer</code> now has same signature as <code>HandlerFunc</code>,
 so it can be converted to that type to access its methods,
-just as we converted <code>Sequence</code> to <code>IntArray</code>
-to access <code>IntArray.Sort</code>.
+just as we converted <code>Sequence</code> to <code>IntSlice</code>
+to access <code>IntSlice.Sort</code>.
 The code to set it up is concise:
 </p>
 <pre>
@@ -2119,11 +2184,11 @@ here are their definitions.
 </p>
 <pre>
 type Reader interface {
-    Read(p []byte) (n int, err os.Error)
+    Read(p []byte) (n int, err error)
 }
 
 type Writer interface {
-    Write(p []byte) (n int, err os.Error)
+    Write(p []byte) (n int, err error)
 }
 </pre>
 <p>
@@ -2185,7 +2250,7 @@ satisfy the <code>io</code> interfaces, we would also need
 to provide forwarding methods, like this:
 </p>
 <pre>
-func (rw *ReadWriter) Read(p []byte) (n int, err os.Error) {
+func (rw *ReadWriter) Read(p []byte) (n int, err error) {
     return rw.reader.Read(p)
 }
 </pre>
@@ -2560,8 +2625,10 @@ is if you want CPU parallelism you must tell the run-time
 how many goroutines you want executing code simultaneously.  There
 are two related ways to do this.  Either run your job with environment
 variable <code>GOMAXPROCS</code> set to the number of cores to use
-(default 1); or import the <code>runtime</code> package and call
+or import the <code>runtime</code> package and call
 <code>runtime.GOMAXPROCS(NCPU)</code>.
+A helpful value might be <code>runtime.NumCPU()</code>, which reports the number
+of logical CPUs on the local machine.
 Again, this requirement is expected to be retired as the scheduling and run-time improve.
 </p>
 
@@ -2637,12 +2704,12 @@ the garbage collector for bookkeeping.
 Library routines must often return some sort of error indication to
 the caller.  As mentioned earlier, Go's multivalue return makes it
 easy to return a detailed error description alongside the normal
-return value.  By convention, errors have type <code>os.Error</code>,
-a simple interface.
+return value.  By convention, errors have type <code>error</code>,
+a simple built-in interface.
 </p>
 <pre>
-type Error interface {
-    String() string
+type error interface {
+    Error() string
 }
 </pre>
 <p>
@@ -2657,15 +2724,15 @@ For example, <code>os.Open</code> returns an <code>os.PathError</code>.
 type PathError struct {
     Op string    // "open", "unlink", etc.
     Path string  // The associated file.
-    Error Error  // Returned by the system call.
+    Err error    // Returned by the system call.
 }
 
-func (e *PathError) String() string {
-    return e.Op + " " + e.Path + ": " + e.Error.String()
+func (e *PathError) Error() string {
+    return e.Op + " " + e.Path + ": " + e.Err.Error()
 }
 </pre>
 <p>
-<code>PathError</code>'s <code>String</code> generates
+<code>PathError</code>'s <code>Error</code> generates
 a string like this:
 </p>
 <pre>
@@ -2690,7 +2757,7 @@ is "image: unknown format".
 Callers that care about the precise error details can
 use a type switch or a type assertion to look for specific
 errors and extract details.  For <code>PathErrors</code>
-this might include examining the internal <code>Error</code>
+this might include examining the internal <code>Err</code>
 field for recoverable failures.
 </p>
 
@@ -2700,7 +2767,7 @@ for try := 0; try < 2; try++ {
     if err == nil {
         return
     }
-    if e, ok := err.(*os.PathError); ok && e.Error == os.ENOSPC {
+    if e, ok := err.(*os.PathError); ok && e.Err == os.ENOSPC {
         deleteTempFiles()  // Recover some space.
         continue
     }
@@ -2708,13 +2775,25 @@ for try := 0; try < 2; try++ {
 }
 </pre>
 
+<p>
+The second <code>if</code> statement here is idiomatic Go.
+The type assertion <code>err.(*os.PathError)</code> is
+checked with the "comma ok" idiom (mentioned <a href="#maps">earlier</a>
+in the context of examining maps).
+If the type assertion fails, <code>ok</code> will be false, and <code>e</code>
+will be <code>nil</code>.
+If it succeeds,  <code>ok</code> will be true, which means the
+error was of type <code>*os.PathError</code>, and then so is <code>e</code>,
+which we can examine for more information about the error.
+</p>
+
 <h3 id="panic">Panic</h3>
 
 <p>
 The usual way to report an error to a caller is to return an
-<code>os.Error</code> as an extra return value.  The canonical
+<code>error</code> as an extra return value.  The canonical
 <code>Read</code> method is a well-known instance; it returns a byte
-count and an <code>os.Error</code>.  But what if the error is
+count and an <code>error</code>.  But what if the error is
 unrecoverable?  Sometimes the program simply cannot continue.
 </p>
 
@@ -2830,14 +2909,14 @@ cleanly by calling <code>panic</code>.  We can use that idea to
 simplify error handling in complex software.  Let's look at an
 idealized excerpt from the <code>regexp</code> package, which reports
 parsing errors by calling <code>panic</code> with a local
-<code>Error</code> type.  Here's the definition of <code>Error</code>,
+error type.  Here's the definition of <code>Error</code>,
 an <code>error</code> method, and the <code>Compile</code> function.
 </p>
 
 <pre>
-// Error is the type of a parse error; it satisfies os.Error.
+// Error is the type of a parse error; it satisfies the error interface.
 type Error string
-func (e Error) String() string {
+func (e Error) Error() string {
     return string(e)
 }
 
@@ -2848,7 +2927,7 @@ func (regexp *Regexp) error(err string) {
 }
 
 // Compile returns a parsed representation of the regular expression.
-func Compile(str string) (regexp *Regexp, err os.Error) {
+func Compile(str string) (regexp *Regexp, err error) {
     regexp = new(Regexp)
     // doParse will panic if there is a parse error.
     defer func() {
@@ -2866,7 +2945,7 @@ If <code>doParse</code> panics, the recovery block will set the
 return value to <code>nil</code>—deferred functions can modify
 named return values.  It then will then check, in the assignment
 to <code>err</code>, that the problem was a parse error by asserting
-that it has type <code>Error</code>.
+that it has the local type <code>Error</code>.
 If it does not, the type assertion will fail, causing a run-time error
 that continues the stack unwinding as though nothing had interrupted
 it.  This check means that if something unexpected happens, such
@@ -2884,7 +2963,7 @@ the parse stack by hand.
 <p>
 Useful though this pattern is, it should be used only within a package.
 <code>Parse</code> turns its internal <code>panic</code> calls into
-<code>os.Error</code> values; it does not expose <code>panics</code>
+<code>error</code> values; it does not expose <code>panics</code>
 to its client.  That is a good rule to follow.
 </p>
 
@@ -2925,9 +3004,9 @@ An explanation follows.
 
 import (
     "flag"
-    "http"
     "log"
-    "template"
+    "net/http"
+    "text/template"
 )
 
 var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
@@ -2966,8 +3045,7 @@ value="Show QR" name=qr>
 </form>
 </body>
 </html>
-`
-</pre>
+`</pre>
 <p>
 The pieces up to <code>main</code> should be easy to follow.
 The one flag sets a default HTTP port for our server.  The template
diff --git a/doc/effective_go.tmpl b/doc/effective_go.tmpl
index 46d774a..782c700 100644
--- a/doc/effective_go.tmpl
+++ b/doc/effective_go.tmpl
@@ -1,4 +1,7 @@
-<!-- Effective Go -->
+<!--{
+	"Title": "Effective Go"
+}-->
+{{donotedit}}
 
 <h2 id="introduction">Introduction</h2>
 
@@ -221,7 +224,7 @@ starts with the name being declared.
 <pre>
 // Compile parses a regular expression and returns, if successful, a Regexp
 // object that can be used to match against text.
-func Compile(str string) (regexp *Regexp, error os.Error) {
+func Compile(str string) (regexp *Regexp, err error) {
 </pre>
 
 <p>
@@ -233,9 +236,9 @@ Since the whole declaration is presented, such a comment can often be perfunctor
 <pre>
 // Error codes returned by failures to parse an expression.
 var (
-    ErrInternal      = os.NewError("regexp: internal error")
-    ErrUnmatchedLpar = os.NewError("regexp: unmatched '('")
-    ErrUnmatchedRpar = os.NewError("regexp: unmatched ')'")
+    ErrInternal      = errors.New("regexp: internal error")
+    ErrUnmatchedLpar = errors.New("regexp: unmatched '('")
+    ErrUnmatchedRpar = errors.New("regexp: unmatched ')'")
     ...
 )
 </pre>
@@ -526,12 +529,62 @@ if err != nil {
 }
 d, err := f.Stat()
 if err != nil {
+    f.Close()
     return err
 }
 codeUsing(f, d)
 </pre>
 
 
+<h3 id="redeclaration">Redeclaration</h3>
+
+<p>
+An aside: The last example in the previous section demonstrates a detail of how the
+<code>:=</code> short declaration form works.
+The declaration that calls <code>os.Open</code> reads,
+</p>
+
+<pre>
+f, err := os.Open(name)
+</pre>
+
+<p>
+This statement declares two variables, <code>f</code> and <code>err</code>.
+A few lines later, the call to <code>f.Stat</code> reads,
+</p>
+
+<pre>
+d, err := f.Stat()
+</pre>
+
+<p>
+which looks as if it declares <code>d</code> and <code>err</code>.
+Notice, though, that <code>err</code> appears in both statements.
+This duplication is legal: <code>err</code> is declared by the first statement,
+but only <em>re-assigned</em> in the second.
+This means that the call to <code>f.Stat</code> uses the existing
+<code>err</code> variable declared above, and just gives it a new value.
+</p>
+
+<p>
+In a <code>:=</code> declaration a variable <code>v</code> may appear even
+if it has already been declared, provided:
+</p>
+
+<ul>
+<li>this declaration is in the same scope as the existing declaration of <code>v</code>
+(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable),</li>
+<li>the corresponding value in the initialization is assignable to <code>v</code>, and</li>
+<li>there is at least one other variable in the declaration that is being declared anew.</li>
+</ul>
+
+<p>
+This unusual property is pure pragmatism,
+making it easy to use a single <code>err</code> value, for example,
+in a long <code>if-else</code> chain.
+You'll see it used often.
+</p>
+
 <h3 id="for">For</h3>
 
 <p>
@@ -717,12 +770,12 @@ The signature of <code>*File.Write</code> in package <code>os</code> is:
 </p>
 
 <pre>
-func (file *File) Write(b []byte) (n int, err Error)
+func (file *File) Write(b []byte) (n int, err error)
 </pre>
 
 <p>
 and as the documentation says, it returns the number of bytes
-written and a non-nil <code>Error</code> when <code>n</code>
+written and a non-nil <code>error</code> when <code>n</code>
 <code>!=</code> <code>len(b)</code>.
 This is a common style; see the section on error handling for more examples.
 </p>
@@ -788,7 +841,7 @@ of <code>io.ReadFull</code> that uses them well:
 </p>
 
 <pre>
-func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
+func ReadFull(r Reader, buf []byte) (n int, err error) {
     for len(buf) > 0 && err == nil {
         var nr int
         nr, err = r.Read(buf)
@@ -812,7 +865,7 @@ canonical examples are unlocking a mutex or closing a file.
 
 <pre>
 // Contents returns the file's contents as a string.
-func Contents(filename string) (string, os.Error) {
+func Contents(filename string) (string, error) {
     f, err := os.Open(filename)
     if err != nil {
         return "", err
@@ -825,7 +878,7 @@ func Contents(filename string) (string, os.Error) {
         n, err := f.Read(buf[0:])
         result = append(result, buf[0:n]...) // append is discussed later.
         if err != nil {
-            if err == os.EOF {
+            if err == io.EOF {
                 break
             }
             return "", err  // f will be closed if we return here.
@@ -1195,7 +1248,7 @@ limit of how much data to read.  Here is the signature of the
 <code>os</code>:
 </p>
 <pre>
-func (file *File) Read(buf []byte) (n int, err os.Error)
+func (file *File) Read(buf []byte) (n int, err error)
 </pre>
 <p>
 The method returns the number of bytes read and an error value, if
@@ -1211,7 +1264,7 @@ the moment, this snippet would also read the first 32 bytes of the buffer.
 </p>
 <pre>
     var n int
-    var err os.Error
+    var err error
     for i := 0; i < 32; i++ {
         nbytes, e := f.Read(buf[i:i+1])  // Read one byte.
         if nbytes == 0 || e != nil {
@@ -1439,7 +1492,7 @@ format <code>%#v</code> prints the value in full Go syntax.
 <pre>
 type T struct {
     a int
-    b float
+    b float64
     c string
 }
 t := &T{ 7, -2.35, "abc\tdef" }
@@ -1509,7 +1562,7 @@ for its final argument to specify that an arbitrary number of parameters (of arb
 can appear after the format.
 </p>
 <pre>
-func Printf(format string, v ...interface{}) (n int, errno os.Error) {
+func Printf(format string, v ...interface{}) (n int, err error) {
 </pre>
 <p>
 Within the function <code>Printf</code>, <code>v</code> acts like a variable of type
@@ -1724,7 +1777,7 @@ In fact, we can do even better.  If we modify our function so it looks
 like a standard <code>Write</code> method, like this,
 </p>
 <pre>
-func (p *ByteSlice) Write(data []byte) (n int, err os.Error) {
+func (p *ByteSlice) Write(data []byte) (n int, err error) {
     slice := *p
     // Again as above.
     *p = slice
@@ -1809,7 +1862,7 @@ do create a new value.)
 It's an idiom in Go programs to convert the
 type of an expression to access a different
 set of methods. As an example, we could use the existing
-type <code>sort.IntArray</code> to reduce the entire example
+type <code>sort.IntSlice</code> to reduce the entire example
 to this:
 </p>
 <pre>
@@ -1817,14 +1870,14 @@ type Sequence []int
 
 // Method for printing - sorts the elements before printing
 func (s Sequence) String() string {
-    sort.IntArray(s).Sort()
+    sort.IntSlice(s).Sort()
     return fmt.Sprint([]int(s))
 }
 </pre>
 <p>
 Now, instead of having <code>Sequence</code> implement multiple
 interfaces (sorting and printing), we're using the ability of a data item to be
-converted to multiple types (<code>Sequence</code>, <code>sort.IntArray</code>
+converted to multiple types (<code>Sequence</code>, <code>sort.IntSlice</code>
 and <code>[]int</code>), each of which does some part of the job.
 That's more unusual in practice but can be effective.
 </p>
@@ -1853,42 +1906,53 @@ the rest of the code is unaffected by the change of algorithm.
 </p>
 <p>
 A similar approach allows the streaming cipher algorithms
-in the <code>crypto/block</code> package to be
+in the various <code>crypto</code> packages to be
 separated from the block ciphers they chain together.
-By analogy with the <code>bufio</code> package,
-they wrap a <code>Cipher</code> interface
-and return <code>hash.Hash</code>,
-<code>io.Reader</code>, or <code>io.Writer</code>
-interface values, not specific implementations.
+The <code>Block</code> interface
+in the <code>crypto/cipher</code>package specifies the
+behavior of a block cipher, which provides encryption
+of a single block of data.
+Then, by analogy with the <code>bufio</code> package,
+cipher packages that implement this interface
+can be used to construct streaming ciphers, represented
+by the <code>Stream</code> interface, without
+knowing the details of the block encryption.
 </p>
 <p>
-The interface to <code>crypto/block</code> includes:
+The  <code>crypto/cipher</code> interfaces look like this:
 </p>
 <pre>
-type Cipher interface {
+type Block interface {
     BlockSize() int
     Encrypt(src, dst []byte)
     Decrypt(src, dst []byte)
 }
 
-// NewECBDecrypter returns a reader that reads data
-// from r and decrypts it using c in electronic codebook (ECB) mode.
-func NewECBDecrypter(c Cipher, r io.Reader) io.Reader
+type Stream interface {
+    XORKeyStream(dst, src []byte)
+}
+</pre>
+
+<p>
+Here's the definition of the counter mode (CTR) stream,
+which turns a block cipher into a streaming cipher; notice
+that the block cipher's details are abstracted away:
+</p>
 
-// NewCBCDecrypter returns a reader that reads data
-// from r and decrypts it using c in cipher block chaining (CBC) mode
-// with the initialization vector iv.
-func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader
+<pre>
+// NewCTR returns a Stream that encrypts/decrypts using the given Block in
+// counter mode. The length of iv must be the same as the Block's block size.
+func NewCTR(block Block, iv []byte) Stream
 </pre>
 <p>
-<code>NewECBDecrypter</code> and <code>NewCBCReader</code> apply not
+<code>NewCTR</code> applies not
 just to one specific encryption algorithm and data source but to any
-implementation of the <code>Cipher</code> interface and any
-<code>io.Reader</code>.  Because they return <code>io.Reader</code>
-interface values, replacing ECB
-encryption with CBC encryption is a localized change.  The constructor
+implementation of the <code>Block</code> interface and any
+<code>Stream</code>.  Because they return
+interface values, replacing CTR
+encryption with other encryption modes is a localized change.  The constructor
 calls must be edited, but because the surrounding code must treat the result only
-as an <code>io.Reader</code>, it won't notice the difference.
+as a <code>Stream</code>, it won't notice the difference.
 </p>
 
 <h3 id="interface_methods">Interfaces and methods</h3>
@@ -1934,7 +1998,7 @@ func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 <code>http.ResponseWriter</code>.)
 For reference, here's how to attach such a server to a node on the URL tree.
 <pre>
-import "http"
+import "net/http"
 ...
 ctr := new(Counter)
 http.Handle("/counter", ctr)
@@ -1973,7 +2037,7 @@ It's easy to write a function to print the arguments.
 </p>
 <pre>
 func ArgServer() {
-    for i, s := range os.Args {
+    for _, s := range os.Args {
         fmt.Println(s)
     }
 }
@@ -2011,7 +2075,7 @@ to have the right signature.
 <pre>
 // Argument server.
 func ArgServer(w http.ResponseWriter, req *http.Request) {
-    for i, s := range os.Args {
+    for _, s := range os.Args {
         fmt.Fprintln(w, s)
     }
 }
@@ -2019,8 +2083,8 @@ func ArgServer(w http.ResponseWriter, req *http.Request) {
 <p>
 <code>ArgServer</code> now has same signature as <code>HandlerFunc</code>,
 so it can be converted to that type to access its methods,
-just as we converted <code>Sequence</code> to <code>IntArray</code>
-to access <code>IntArray.Sort</code>.
+just as we converted <code>Sequence</code> to <code>IntSlice</code>
+to access <code>IntSlice.Sort</code>.
 The code to set it up is concise:
 </p>
 <pre>
@@ -2057,11 +2121,11 @@ here are their definitions.
 </p>
 <pre>
 type Reader interface {
-    Read(p []byte) (n int, err os.Error)
+    Read(p []byte) (n int, err error)
 }
 
 type Writer interface {
-    Write(p []byte) (n int, err os.Error)
+    Write(p []byte) (n int, err error)
 }
 </pre>
 <p>
@@ -2123,7 +2187,7 @@ satisfy the <code>io</code> interfaces, we would also need
 to provide forwarding methods, like this:
 </p>
 <pre>
-func (rw *ReadWriter) Read(p []byte) (n int, err os.Error) {
+func (rw *ReadWriter) Read(p []byte) (n int, err error) {
     return rw.reader.Read(p)
 }
 </pre>
@@ -2498,8 +2562,10 @@ is if you want CPU parallelism you must tell the run-time
 how many goroutines you want executing code simultaneously.  There
 are two related ways to do this.  Either run your job with environment
 variable <code>GOMAXPROCS</code> set to the number of cores to use
-(default 1); or import the <code>runtime</code> package and call
+or import the <code>runtime</code> package and call
 <code>runtime.GOMAXPROCS(NCPU)</code>.
+A helpful value might be <code>runtime.NumCPU()</code>, which reports the number
+of logical CPUs on the local machine.
 Again, this requirement is expected to be retired as the scheduling and run-time improve.
 </p>
 
@@ -2575,12 +2641,12 @@ the garbage collector for bookkeeping.
 Library routines must often return some sort of error indication to
 the caller.  As mentioned earlier, Go's multivalue return makes it
 easy to return a detailed error description alongside the normal
-return value.  By convention, errors have type <code>os.Error</code>,
-a simple interface.
+return value.  By convention, errors have type <code>error</code>,
+a simple built-in interface.
 </p>
 <pre>
-type Error interface {
-    String() string
+type error interface {
+    Error() string
 }
 </pre>
 <p>
@@ -2595,15 +2661,15 @@ For example, <code>os.Open</code> returns an <code>os.PathError</code>.
 type PathError struct {
     Op string    // "open", "unlink", etc.
     Path string  // The associated file.
-    Error Error  // Returned by the system call.
+    Err error    // Returned by the system call.
 }
 
-func (e *PathError) String() string {
-    return e.Op + " " + e.Path + ": " + e.Error.String()
+func (e *PathError) Error() string {
+    return e.Op + " " + e.Path + ": " + e.Err.Error()
 }
 </pre>
 <p>
-<code>PathError</code>'s <code>String</code> generates
+<code>PathError</code>'s <code>Error</code> generates
 a string like this:
 </p>
 <pre>
@@ -2628,7 +2694,7 @@ is "image: unknown format".
 Callers that care about the precise error details can
 use a type switch or a type assertion to look for specific
 errors and extract details.  For <code>PathErrors</code>
-this might include examining the internal <code>Error</code>
+this might include examining the internal <code>Err</code>
 field for recoverable failures.
 </p>
 
@@ -2638,7 +2704,7 @@ for try := 0; try < 2; try++ {
     if err == nil {
         return
     }
-    if e, ok := err.(*os.PathError); ok && e.Error == os.ENOSPC {
+    if e, ok := err.(*os.PathError); ok && e.Err == os.ENOSPC {
         deleteTempFiles()  // Recover some space.
         continue
     }
@@ -2646,13 +2712,25 @@ for try := 0; try < 2; try++ {
 }
 </pre>
 
+<p>
+The second <code>if</code> statement here is idiomatic Go.
+The type assertion <code>err.(*os.PathError)</code> is
+checked with the "comma ok" idiom (mentioned <a href="#maps">earlier</a>
+in the context of examining maps).
+If the type assertion fails, <code>ok</code> will be false, and <code>e</code>
+will be <code>nil</code>.
+If it succeeds,  <code>ok</code> will be true, which means the
+error was of type <code>*os.PathError</code>, and then so is <code>e</code>,
+which we can examine for more information about the error.
+</p>
+
 <h3 id="panic">Panic</h3>
 
 <p>
 The usual way to report an error to a caller is to return an
-<code>os.Error</code> as an extra return value.  The canonical
+<code>error</code> as an extra return value.  The canonical
 <code>Read</code> method is a well-known instance; it returns a byte
-count and an <code>os.Error</code>.  But what if the error is
+count and an <code>error</code>.  But what if the error is
 unrecoverable?  Sometimes the program simply cannot continue.
 </p>
 
@@ -2768,14 +2846,14 @@ cleanly by calling <code>panic</code>.  We can use that idea to
 simplify error handling in complex software.  Let's look at an
 idealized excerpt from the <code>regexp</code> package, which reports
 parsing errors by calling <code>panic</code> with a local
-<code>Error</code> type.  Here's the definition of <code>Error</code>,
+error type.  Here's the definition of <code>Error</code>,
 an <code>error</code> method, and the <code>Compile</code> function.
 </p>
 
 <pre>
-// Error is the type of a parse error; it satisfies os.Error.
+// Error is the type of a parse error; it satisfies the error interface.
 type Error string
-func (e Error) String() string {
+func (e Error) Error() string {
     return string(e)
 }
 
@@ -2786,7 +2864,7 @@ func (regexp *Regexp) error(err string) {
 }
 
 // Compile returns a parsed representation of the regular expression.
-func Compile(str string) (regexp *Regexp, err os.Error) {
+func Compile(str string) (regexp *Regexp, err error) {
     regexp = new(Regexp)
     // doParse will panic if there is a parse error.
     defer func() {
@@ -2804,7 +2882,7 @@ If <code>doParse</code> panics, the recovery block will set the
 return value to <code>nil</code>—deferred functions can modify
 named return values.  It then will then check, in the assignment
 to <code>err</code>, that the problem was a parse error by asserting
-that it has type <code>Error</code>.
+that it has the local type <code>Error</code>.
 If it does not, the type assertion will fail, causing a run-time error
 that continues the stack unwinding as though nothing had interrupted
 it.  This check means that if something unexpected happens, such
@@ -2822,7 +2900,7 @@ the parse stack by hand.
 <p>
 Useful though this pattern is, it should be used only within a package.
 <code>Parse</code> turns its internal <code>panic</code> calls into
-<code>os.Error</code> values; it does not expose <code>panics</code>
+<code>error</code> values; it does not expose <code>panics</code>
 to its client.  That is a good rule to follow.
 </p>
 
diff --git a/doc/gccgo_contribute.html b/doc/gccgo_contribute.html
index 8eeb3a5..b641c1a 100644
--- a/doc/gccgo_contribute.html
+++ b/doc/gccgo_contribute.html
@@ -1,4 +1,6 @@
-<!-- Contributing to the gccgo frontend -->
+<!--{
+	"Title": "Contributing to the gccgo frontend"
+}-->
 
 <h2>Introduction</h2>
 
diff --git a/doc/gccgo_install.html b/doc/gccgo_install.html
index 38a30e9..1aaf64e 100644
--- a/doc/gccgo_install.html
+++ b/doc/gccgo_install.html
@@ -1,4 +1,6 @@
-<!-- Setting up and using gccgo -->
+<!--{
+	"Title": "Setting up and using gccgo"
+}-->
 
 <p>
 This document explains how to use <code>gccgo</code>, a compiler for
diff --git a/doc/go1.html b/doc/go1.html
new file mode 100644
index 0000000..23ed370
--- /dev/null
+++ b/doc/go1.html
@@ -0,0 +1,1570 @@
+<!--{
+	"Title": "Go 1 Release Notes"
+}-->
+<!--
+  DO NOT EDIT: created by
+    tmpltohtml go1.tmpl
+-->
+
+
+<h2 id="introduction">Introduction to Go 1</h2>
+
+<p>
+For a full explanation of the motivation and design of Go 1, see XXX.
+Here follows a summary.
+</p>
+
+<p>
+Go 1 is intended to be a stable language and core library set that
+will form a reliable foundation for people and organizations that
+want to make a long-term commitment to developing in the Go programming
+language. Go will continue to develop, but in a way that guarantees
+code written to the Go 1 specification will continue to work. For
+instance, Go 1 will be a supported platform on Google App Engine
+for the next few years. Incompatible changes to the environment,
+should they arise, will be done in a distinct version.
+</p>
+
+<p>
+This document describes the changes in the language and libraries
+in Go 1, relative to the previous release, r60 (at the time of
+writing, tagged as r60.3). It also explains how to update code at
+r60 to compile and run under Go 1. Finally, it outlines the new
+<code>go</code> command for building Go programs and the new binary
+release process being introduced. Most of these topics have more
+thorough presentations elsewhere; such documents are linked below.
+</p>
+
+<h2 id="language">Changes to the language</h2>
+
+<h3 id="append">Append</h3>
+
+<p>
+The <code>append</code> built-in function is variadic, so one can
+append to a byte slice using the <code>...</code> syntax in the
+call.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
+-->    greeting := []byte{}
+    greeting = append(greeting, []byte("hello ")...)</pre>
+
+<p>
+By analogy with the similar property of <code>copy</code>, Go 1
+permits a string to be appended (byte-wise) directly to a byte
+slice; the conversion is no longer necessary:
+</p>
+
+<pre><!--{{code "progs/go1.go" `/append.*world/`}}
+-->    greeting = append(greeting, "world"...)</pre>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="close">Close</h3>
+
+<p>
+The <code>close</code> built-in function lets a sender tell a receiver
+that no more data will be transmitted on the channel.  In Go 1 the
+type system enforces the directionality when possible: it is illegal
+to call <code>close</code> on a receive-only channel:
+</p>
+
+<pre>
+    var c chan int
+    var csend chan<- int = c
+    var crecv <-chan int = c
+    close(c)     // legal
+    close(csend) // legal
+    close(crecv) // illegal
+</pre>
+
+<p>
+<em>Updating</em>:
+Existing code that attempts to close a receive-only channel was
+erroneous even before Go 1 and should be fixed.  The compiler will
+now reject such code.
+</p>
+
+<h3 id="literals">Composite literals</h3>
+
+<p>
+In Go 1, a composite literal of array, slice, or map type can elide the
+type specification for the elements' initializers if they are of pointer type.
+All four of the initializations in this example are legal; the last one was illegal before Go 1.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/type Date struct/` `/STOP/`}}
+-->    type Date struct {
+        month string
+        day   int
+    }
+    // Struct values, fully qualified; always legal.
+    holiday1 := []Date{
+        Date{"Feb", 14},
+        Date{"Nov", 11},
+        Date{"Dec", 25},
+    }
+    // Struct values, type name elided; always legal.
+    holiday2 := []Date{
+        {"Feb", 14},
+        {"Nov", 11},
+        {"Dec", 25},
+    }
+    // Pointers, fully qualified, always legal.
+    holiday3 := []*Date{
+        &Date{"Feb", 14},
+        &Date{"Nov", 11},
+        &Date{"Dec", 25},
+    }
+    // Pointers, type name elided; legal in Go 1.
+    holiday4 := []*Date{
+        {"Feb", 14},
+        {"Nov", 11},
+        {"Dec", 25},
+    }</pre>
+
+<p>
+<em>Updating</em>:
+This change has no effect on existing code, but the command
+<code>gofmt</code> <code>-s</code> applied to existing source
+will, among other things, elide explicit element types wherever permitted.
+</p>
+
+
+<h3 id="init">Goroutines during init</h3>
+
+<p>
+Go 1 allows goroutines to be created and run during initialization.
+(They used to be created but were not run until after initialization
+completed.) Code that uses goroutines can now be called from
+<code>init</code> routines and global initialization expressions
+without introducing a deadlock.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/PackageGlobal/` `/^}/`}}
+-->var PackageGlobal int
+
+func init() {
+    c := make(chan int)
+    go initializationFunction(c)
+    PackageGlobal = <-c
+}</pre>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes,
+although it's possible that code that depends on goroutines not starting before <code>main</code> will break.
+There was no such code in the standard repository.
+</p>
+
+<h3 id="rune">The rune type</h3>
+
+<p>
+Go 1 introduces a new basic type, <code>rune</code>, to be used to represent
+individual Unicode code points.
+It is an alias for <code>int32</code>, analogous to <code>byte</code>
+as an alias for <code>uint8</code>.
+</p>
+
+<p>
+Character literals such as <code>'a'</code>, <code>'語'</code>, and <code>'\u0345'</code>
+now have default type <code>rune</code>,
+analogous to <code>1.0</code> having default type <code>float64</code>.
+A variable initialized to a character constant will therefore
+have type <code>rune</code> unless otherwise specified.
+</p>
+
+<p>
+Libraries have been updated to use <code>rune</code> rather than <code>int</code>
+when appropriate. For instance, the functions <code>unicode.ToLower</code> and
+relatives now take and return a <code>rune</code>.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/STARTRUNE/` `/ENDRUNE/`}}
+-->    delta := 'δ' // delta has type rune.
+    var DELTA rune
+    DELTA = unicode.ToUpper(delta)
+    epsilon := unicode.ToLower(DELTA + 1)
+    if epsilon != 'δ'+1 {
+        log.Fatal("inconsistent casing for Greek")
+    }</pre>
+
+<p>
+<em>Updating</em>:
+Most source code will be unaffected by this because the type inference from
+<code>:=</code> initializers introduces the new type silently, and it propagates
+from there.
+Some code may get type errors that a trivial conversion will resolve.
+</p>
+
+<h3 id="error">The error type</h3>
+
+<p>
+Go 1 introduces a new built-in type, <code>error</code>, which has the following definition:
+</p>
+
+<pre>
+    type error interface {
+        Error() string
+    }
+</pre>
+
+<p>
+Since the consequences of this type are all in the package library,
+it is discussed <a href="#errors">below</a>.
+</p>
+
+<h3 id="delete">Deleting from maps</h3>
+
+<p>
+The original syntax for deleting an element in a map was:
+</p>
+
+<pre>
+    m[k] = ignored, false
+</pre>
+
+<p>
+In Go 1, that syntax has gone; instead there is a new built-in
+function, <code>delete</code>.  The call
+</p>
+
+<pre><!--{{code "progs/go1.go" `/delete\(m, k\)/`}}
+-->    delete(m, k)</pre>
+
+<p>
+will delete the map entry retrieved by the expression <code>m[k]</code>.
+There is no return value. Deleting a non-existent entry is a no-op.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will convert expressions of the form <code>m[k] = ignored,
+false</code> into <code>delete(m, k)</code> when it is clear that
+the ignored value can be safely discarded from the program and
+<code>false</code> refers to the predefined boolean constant.  Gofix
+will flag other uses of the syntax for inspection by the programmer.
+</p>
+
+<h3 id="iteration">Iterating in maps</h3>
+
+<p>
+In Go 1, the order in which elements are visited when iterating
+over a map using a <code>for</code> <code>range</code> statement
+is defined to be unpredictable, even if the same loop is run multiple
+times with the same map.
+Code should not assume that the elements are visited in any particular order.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/Sunday/` `/^	}/`}}
+-->    m := map[string]int{"Sunday": 0, "Monday": 1}
+    for name, value := range m {
+        // This loop should not assume Sunday will be visited first.
+        f(name, value)
+    }</pre>
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help.  Most existing code
+will be unaffected, but some programs may break or misbehave; we
+recommend manual checking of all range statements over maps to
+verify they do not depend on iteration order. There were a few such
+examples in the standard repository; they have been fixed.
+Note that it was already incorrect to depend on the iteration order, which
+was unspecified. This change codifies the unpredictability.
+</p>
+
+<h3 id="multiple_assignment">Multiple assignment</h3>
+
+<p>
+Go 1 fully specifies the evaluation order in multiple assignment
+statements. In particular, if the left-hand side of the assignment
+statement contains expressions that require evaluation, such as
+function calls or array indexing operations, these will all be done
+using the usual left-to-right rule before any variables are assigned
+their value.  Once everything is evaluated, the actual assignments
+proceed in left-to-right order.
+</p>
+
+<p>
+These examples illustrate the behavior.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
+-->    sa := []int{1, 2, 3}
+    i := 0
+    i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2
+
+    sb := []int{1, 2, 3}
+    j := 0
+    sb[j], j = 2, 1 // sets sb[0] = 2, j = 1
+
+    sc := []int{1, 2, 3}
+    sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)</pre>
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help, but breakage is unlikely.
+No code in the standard repository was broken by this change, and code
+that depended on the previous unspecified behavior was already incorrect.
+</p>
+
+<h3 id="shadowing">Returns and shadowed variables</h3>
+
+<p>
+A shadowed variable is one that has the same name as another variable in an inner scope.
+In functions with named return values,
+the Go 1 compilers disallow return statements without arguments if any of the named return values is shadowed at the point of the return statement.
+(It isn't part of the specification, because this is one area we are still exploring;
+the situation is analogous to the compilers rejecting functions that do not end with an explicit return statement.)
+</p>
+
+<p>
+This function implicitly returns a shadowed return value and will be rejected by the compiler:
+</p>
+
+<pre>
+    func Bug() (i, j, k int) {
+        for i = 0; i < 5; i++ {
+            for j := 0; j < 5; j++ { // Redeclares j.
+                k += i*j
+                if k > 100 {
+                    return // Rejected: j is shadowed here.
+                }
+            }
+        }
+        return // OK: j is not shadowed here.
+    }
+</pre>
+
+<p>
+<em>Updating</em>:
+Code that shadows return values in this way will be rejected by the compiler and will need to be fixed by hand.
+The few cases that arose in the standard repository were mostly bugs.
+</p>
+
+<h3 id="unexported">Copying structs with unexported fields</h3>
+
+<p>
+Go 1 relaxes the rules about accessing structs with unexported (lower-case) fields,
+permitting a client package to assign (and therefore copy) such a struct.
+Of course, the client package still cannot access such fields individually.
+</p>
+
+<p>
+As an example, if package <code>p</code> includes the definitions,
+</p>
+
+<pre>
+    type Struct struct {
+        Public int
+        secret int
+    }
+    func NewStruct(a int) Struct {  // Note: not a pointer.
+        return Struct{a, f(a)}
+    }
+    func (s Struct) String() string {
+        return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
+    }
+</pre>
+
+<p>
+a package that imports <code>p</code> can assign and copy values of type
+<code>p.Struct</code> at will.
+Behind the scenes the unexported fields will be assigned and copied just
+as if they were exported,
+but the client code will never be aware of them. The code
+</p>
+
+<pre>
+    import "p"
+
+    myStruct := p.NewStruct(23)
+    copyOfMyStruct := myStruct
+    fmt.Println(myStruct, copyOfMyStruct)
+</pre>
+
+<p>
+will show that the secret field of the struct has been copied to the new value.
+</p>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="equality">Equality of structs and arrays</h3>
+
+<p>
+Go 1 defines equality and inequality (<code>==</code> and
+<code>!=</code>) for struct and array values, respectively, provided
+the elements of the data structures can themselves be compared.
+That is, if equality is defined for all the fields of a struct (or
+an array element), then it is defined for the struct (or array).
+</p>
+
+<p>
+As a result, structs and arrays can now be used as map keys:
+</p>
+
+<pre><!--{{code "progs/go1.go" `/type Day struct/` `/Printf/`}}
+-->    type Day struct {
+        long  string
+        short string
+    }
+    Christmas := Day{"Christmas", "XMas"}
+    Thanksgiving := Day{"Thanksgiving", "Turkey"}
+    holiday := map[Day]bool{
+        Christmas:    true,
+        Thanksgiving: true,
+    }
+    fmt.Printf("Christmas is a holiday: %t\n", holiday[Christmas])</pre>
+
+<p>
+Note that equality is still undefined for slices, for which the
+calculation is in general infeasible.  Also note that the ordered
+comparison operators (<code><</code> <code><=</code>
+<code>></code> <code>>=</code>) are still undefined for
+structs and arrays.
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="funcs">Function and map equality</h3>
+
+<p>
+Go 1 disallows checking for equality of functions and maps,
+respectively, except to compare them directly to <code>nil</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing code that depends on function or map equality will be
+rejected by the compiler and will need to be fixed by hand.
+Few programs will be affected, but the fix may require some
+redesign.
+</p>
+
+<h2 id="packages">The package hierarchy</h2>
+
+<p>
+This section describes how the packages have been rearranged in Go 1.
+Some have moved, some have been renamed, some have been deleted.
+New packages are described in later sections.
+</p>
+
+<h3 id="hierarchy">The package hierarchy</h3>
+
+<p>
+Go 1 has a rearranged package hierarchy that groups related items
+into subdirectories. For instance, <code>utf8</code> and
+<code>utf16</code> now occupy subdirectories of <code>unicode</code>.
+Also, <a href="#subrepo">some packages</a> have moved into
+subrepositories of
+<a href="http://code.google.com/p/go"><code>code.google.com/p/go</code></a>
+while <a href="#deleted">others</a> have been deleted outright.
+</p>
+
+<table class="codetable" frame="border" summary="Moved packages">
+<colgroup align="left" width="60%"></colgroup>
+<colgroup align="left" width="40%"></colgroup>
+<tr>
+<th align="left">Old path</th>
+<th align="left">New path</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>asn1</td> <td>encoding/asn1</td></tr>
+<tr><td>csv</td> <td>encoding/csv</td></tr>
+<tr><td>gob</td> <td>encoding/gob</td></tr>
+<tr><td>json</td> <td>encoding/json</td></tr>
+<tr><td>xml</td> <td>encoding/xml</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exp/template/html</td> <td>html/template</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>big</td> <td>math/big</td></tr>
+<tr><td>cmath</td> <td>math/cmplx</td></tr>
+<tr><td>rand</td> <td>math/rand</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>http</td> <td>net/http</td></tr>
+<tr><td>http/cgi</td> <td>net/http/cgi</td></tr>
+<tr><td>http/fcgi</td> <td>net/http/fcgi</td></tr>
+<tr><td>http/httptest</td> <td>net/http/httptest</td></tr>
+<tr><td>http/pprof</td> <td>net/http/pprof</td></tr>
+<tr><td>mail</td> <td>net/mail</td></tr>
+<tr><td>rpc</td> <td>net/rpc</td></tr>
+<tr><td>rpc/jsonrpc</td> <td>net/rpc/jsonrpc</td></tr>
+<tr><td>smtp</td> <td>net/smtp</td></tr>
+<tr><td>url</td> <td>net/url</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exec</td> <td>os/exec</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>scanner</td> <td>text/scanner</td></tr>
+<tr><td>tabwriter</td> <td>text/tabwriter</td></tr>
+<tr><td>template</td> <td>text/template</td></tr>
+<tr><td>template/parse</td> <td>text/template/parse</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>utf8</td> <td>unicode/utf8</td></tr>
+<tr><td>utf16</td> <td>unicode/utf16</td></tr>
+</table>
+
+<p>
+Note that the package names for the old <code>cmath</code> and
+<code>exp/template/html</code> packages have changed to <code>cmplx</code>
+and <code>template</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update all imports and package renames for packages that
+remain inside the standard repository.  Programs that import packages
+that are no longer in the standard repository will need to be edited
+by hand.
+<br>
+<font color="red">TODO: gofix should warn about deletions.</font>
+</p>
+
+<h3 id="exp">The package tree exp</h3>
+
+<p>
+Because they are not standardized, the packages under the <code>exp</code> directory will not be available in the
+standard Go 1 release distributions, although they will be available in source code form
+in <a href="http://code.google.com/p/go/">the repository</a> for
+developers who wish to use them.
+</p>
+
+<p>
+Several packages have moved under <code>exp</code> at the time of Go 1's release:
+</p>
+
+<ul>
+<li><code>ebnf</code></li>
+<li><code>go/types</code></li>
+<li><code>http/spdy</code></li>
+</ul>
+
+<p>
+All these packages are available under the same names, with the prefix <code>exp/</code>: <code>exp/ebnf</code> etc.
+</p>
+
+<p>
+Also, the <code>utf8.String</code> type has been moved to its own package, <code>exp/utf8string</code>.
+</p>
+
+<p>
+Finally, the <code>gotype</code> command now resides in <code>exp/gotype</code>, while
+<code>ebnflint</code> is now in <code>exp/ebnflint</code>
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses packages in <code>exp</code> will need to be updated by hand,
+or else compiled from an installation that has <code>exp</code> available.
+Gofix or the compiler will complain about such uses.
+<br>
+<font color="red">TODO: gofix should warn about such uses.</font>
+</p>
+
+<h3 id="old">The package tree old</h3>
+
+<p>
+Because they are deprecated, the packages under the <code>old</code> directory will not be available in the
+standard Go 1 release distributions, although they will be available in source code form for
+developers who wish to use them.
+</p>
+
+<p>
+The packages in their new locations are:
+</p>
+
+<ul>
+<li><code>old/netchan</code></li>
+<li><code>old/regexp</code></li>
+<li><code>old/template</code></li>
+</ul>
+
+<p>
+<em>Updating</em>:
+Code that uses packages now in <code>old</code> will need to be updated by hand,
+or else compiled from an installation that has <code>old</code> available.
+Gofix will warn about such uses.
+<br>
+<font color="red">TODO: gofix should warn about such uses.</font>
+</p>
+
+<h3 id="deleted">Deleted packages</h3>
+
+<p>
+Go 1 deletes several packages outright:
+</p>
+
+<ul>
+<li><code>container/vector</code></li>
+<li><code>exp/datafmt</code></li>
+<li><code>go/typechecker</code></li>
+<li><code>try</code></li>
+</ul>
+
+<p>
+and also the command <code>gotry</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses <code>container/vector</code> should be updated to use
+slices directly.  See
+<a href="http://code.google.com/p/go-wiki/wiki/SliceTricks">the Go
+Language Community Wiki</a> for some suggestions.
+Code that uses the other packages (there should be almost zero) will need to be rethought.
+<br>
+<font color="red">TODO: gofix should warn such uses.</font>
+</p>
+
+<h3 id="subrepo">Packages moving to subrepositories</h3>
+
+<p>
+Go 1 has moved a number of packages into sub-repositories of
+<a href="http://code.google.com/p/go/">the main Go repository</a>.
+This table lists the old and new import paths:
+
+<table class="codetable" frame="border" summary="Sub-repositories">
+<colgroup align="left" width="40%"></colgroup>
+<colgroup align="left" width="60%"></colgroup>
+<tr>
+<th align="left">Old</th>
+<th align="left">New</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>crypto/bcrypt</td> <td>code.google.com/p/go.crypto/bcrypt</tr>
+<tr><td>crypto/blowfish</td> <td>code.google.com/p/go.crypto/blowfish</tr>
+<tr><td>crypto/cast5</td> <td>code.google.com/p/go.crypto/cast5</tr>
+<tr><td>crypto/md4</td> <td>code.google.com/p/go.crypto/md4</tr>
+<tr><td>crypto/ocsp</td> <td>code.google.com/p/go.crypto/ocsp</tr>
+<tr><td>crypto/openpgp</td> <td>code.google.com/p/go.crypto/openpgp</tr>
+<tr><td>crypto/openpgp/armor</td> <td>code.google.com/p/go.crypto/openpgp/armor</tr>
+<tr><td>crypto/openpgp/elgamal</td> <td>code.google.com/p/go.crypto/openpgp/elgamal</tr>
+<tr><td>crypto/openpgp/errors</td> <td>code.google.com/p/go.crypto/openpgp/errors</tr>
+<tr><td>crypto/openpgp/packet</td> <td>code.google.com/p/go.crypto/openpgp/packet</tr>
+<tr><td>crypto/openpgp/s2k</td> <td>code.google.com/p/go.crypto/openpgp/s2k</tr>
+<tr><td>crypto/ripemd160</td> <td>code.google.com/p/go.crypto/ripemd160</tr>
+<tr><td>crypto/twofish</td> <td>code.google.com/p/go.crypto/twofish</tr>
+<tr><td>crypto/xtea</td> <td>code.google.com/p/go.crypto/xtea</tr>
+<tr><td>exp/ssh</td> <td>code.google.com/p/go.crypto/ssh</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>net/dict</td> <td>code.google.com/p/go.net/dict</tr>
+<tr><td>net/websocket</td> <td>code.google.com/p/go.net/websocket</tr>
+<tr><td>exp/spdy</td> <td>code.google.com/p/go.net/spdy</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>encoding/git85</td> <td>code.google.com/p/go.codereview/git85</tr>
+<tr><td>patch</td> <td>code.google.com/p/go.codereview/patch</tr>
+</table>
+
+<p>
+<em>Updating</em>:
+Gofix will update imports of these packages to use the new import paths.
+Installations that depend on these packages will need to install them using
+a <code>go install</code> command.
+</p>
+
+<h2 id="major">Major changes to the library</h2>
+
+<p>
+This section describes significant changes to the core libraries, the ones that
+affect the most programs.
+</p>
+
+<h3 id="errors">The error type and errors package</h3>
+
+<p>
+As mentioned above, Go 1 introduces a new built-in interface type called <code>error</code>.
+Its intent is to replace the old <code>os.Error</code> type with a more central concept.
+So the widely-used <code>String</code> method does not cause accidental satisfaction
+of the <code>error</code> interface, the <code>error</code> interface uses instead
+the name <code>Error</code> for that method:
+</p>
+
+<pre>
+    type error interface {
+        Error() string
+    }
+</pre>
+
+<p>
+The <code>fmt</code> library automatically invokes <code>Error</code>, as it already
+does for <code>String</code>, for easy printing of error values.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/START ERROR EXAMPLE/` `/END ERROR EXAMPLE/`}}
+-->type SyntaxError struct {
+    File    string
+    Line    int
+    Message string
+}
+
+func (se *SyntaxError) Error() string {
+    return fmt.Sprintf("%s:%d: %s", se.File, se.Line, se.Message)
+}</pre>
+
+<p>
+All standard packages have been updated to use the new interface; the old <code>os.Error</code> is gone.
+</p>
+
+<p>
+A new package, <a href="/pkg/errors/"><code>errors</code></a>, contains the function
+</p>
+
+<pre>
+func New(text string) error
+</pre>
+
+<p>
+to turn a string into an error. It replaces the old <code>os.NewError</code>.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/ErrSyntax/`}}
+-->    var ErrSyntax = errors.New("syntax error")</pre>
+		
+<p>
+<em>Updating</em>:
+Gofix will update almost all code affected by the change.
+Code that defines error types with a <code>String</code> method will need to be updated
+by hand to rename the methods to <code>Error</code>.
+</p>
+
+<h3 id="errno">System call errors</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/syscall/"><code>syscall</code></a>
+package returns an <code>error</code> for system call errors,
+rather than plain integer <code>errno</code> values.
+On Unix, the implementation is done by a 
+<a href="/pkg/syscall/#Errno"><code>syscall.Errno</code></a> type
+that satisfies <code>error</code> and replaces the old <code>os.Errno</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update almost all code affected by the change.
+Regardless, most code should use the <code>os</code> package
+rather than <code>syscall</code> and so will be unaffected.
+</p>
+
+<h3 id="time">Time</h3>
+
+<p>
+One of the most sweeping changes in the Go 1 library is the
+complete redesign of the 
+<a href="/pkg/time/"><code>time</code></a> package.
+Instead of an integer number of nanoseconds as an <code>int64</code>,
+and a separate <code>*time.Time</code> type to deal with human
+units such as hours and years,
+there are now two fundamental types:
+<a href="/pkg/time/#Time"><code>time.Time</code></a>
+(a value, so the <code>*</code> is gone), which represents a moment in time;
+and <a href="/pkg/time/#Duration"><code>time.Duration</code></a>,
+which represents an interval.
+Both have nanosecond resolution.
+A <code>Time</code> can represent any time into the ancient
+past and remote future, while a <code>Duration</code> can
+span plus or minus only about 290 years.
+There are methods on these types, plus a number of helpful
+predefined constant durations such as <code>time.Second</code>.
+</p>
+
+<p>
+Among the new methods are things like
+<a href="/pkg/time/#Time.Add"><code>Time.Add</code></a>,
+which adds a <code>Duration</code> to a <code>Time</code>, and
+<a href="/pkg/time/#Time.Sub"><code>Time.Sub</code></a>,
+which subtracts two <code>Times</code> to yield a <code>Duration</code>.
+</p>
+
+<p>
+The most important semantic change is that the Unix epoch (Jan 1, 1970) is now
+relevant only for those functions and methods that mention Unix:
+<a href="/pkg/time/#Unix"><code>time.Unix</code></a>
+and the <a href="/pkg/time/#Time.Unix"><code>Unix</code></a>
+and <a href="/pkg/time/#Time.UnixNano"><code>UnixNano</code></a> methods
+of the <code>Time</code> type.
+In particular,
+<a href="/pkg/time/#Now"><code>time.Now</code></a>
+returns a <code>time.Time</code> value rather than, in the old
+API, an integer nanosecond count since the Unix epoch.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/sleepUntil/` `/^}/`}}
+-->// sleepUntil sleeps until the specified time. It returns immediately if it's too late.
+func sleepUntil(wakeup time.Time) {
+    now := time.Now() // A Time.
+    if !wakeup.After(now) {
+        return
+    }
+    delta := wakeup.Sub(now) // A Duration.
+    log.Printf("Sleeping for %.3fs", delta.Seconds())
+    time.Sleep(delta)
+}</pre>
+
+<p>
+The new types, methods, and constants have been propagated through
+all the standard packages that use time, such as <code>os</code> and
+its representation of file time stamps.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update many uses of the old <code>time</code> package to use the new
+types and methods, although it does not replace values such as <code>1e9</code>
+representing nanoseconds per second.
+Also, because of type changes in some of the values that arise,
+some of the expressions rewritten by gofix may require
+further hand editing; in such cases the rewrite will include
+the correct function or method for the old functionality, but
+may have the wrong type or require further analysis.
+</p>
+
+<h2 id="minor">Minor changes to the library</h2>
+
+<p>
+This section describes smaller changes, such as those to less commonly
+used packages or that affect
+few programs beyond the need to run gofix.
+This category includes packages that are new in Go 1.
+</p>
+
+<h3 id="crypto_elliptic">The crypto/elliptic package</h3>
+
+<p>
+In Go 1, <a href="/pkg/crypto/elliptic/#Curve"><code>elliptic.Curve</code></a>
+has been made an interface to permit alternative implementations. The curve
+parameters have been moved to the
+<a href="/pkg/crypto/elliptic/#CurveParams"><code>elliptic.CurveParams</code></a>
+structure.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing users of <code>*elliptic.Curve</code> will need to change to
+simply <code>elliptic.Curve</code>. Calls to <code>Marshal</code>,
+<code>Unmarshal</code> and <code>GenerateKey</code> are now functions
+in <code>crypto/elliptic</code> that take an <code>elliptic.Curve</code>
+as their first argument.
+</p>
+
+<h3 id="crypto_x509">The crypto/x509 package</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
+and
+<a href="/pkg/crypto/x509/#CreateCRL"><code>CreateCRL</code></a>
+functions in <code>crypto/x509</code> have been altered to take an
+<code>interface{}</code> where they previously took a <code>*rsa.PublicKey</code>
+or <code>*rsa.PrivateKey</code>. This will allow other public key algorithms
+to be implemented in the future.
+</p>
+
+<p>
+<em>Updating</em>:
+No changes will be needed.
+</p>
+
+<h3 id="flag">The flag package</h3>
+
+<p>
+In Go 1, the interface <a href="/pkg/flag/#Value"><code>flag.Value</code></a> has changed slightly.
+The <code>Set</code> method now returns an <code>error</code> instead of
+a <code>bool</code> to indicate success or failure.
+</p>
+
+<p>
+There is also a new kind of flag, <code>Duration</code>, to support argument
+values specifying time intervals.
+Values for such flags must be given units, just as <code>time.Duration</code>
+formats them: <code>10s</code>, <code>1h30m</code>, etc.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/timeout/`}}
+-->var timeout = flag.Duration("timeout", 30*time.Second, "how long to wait for completion")</pre>
+
+<p>
+<em>Updating</em>:
+Programs that implement their own flags will need minor manual fixes to update their
+<code>Set</code> methods.
+The <code>Duration</code> flag is new and affects no existing code.
+</p>
+
+
+<h3 id="go">The go/* packages</h3>
+
+<p>
+Several packages under <code>go</code> have slightly revised APIs.
+</p>
+
+<p>
+The modes <code>AllowIllegalChars</code> and <code>InsertSemis</code> have been removed
+from the <a href="/pkg/go/scanner/"><code>go/scanner</code></a> package. They were mostly
+useful for scanning text other then Go source files. Instead, the
+<a href="/pkg/text/scanner/"><code>text/scanner</code></a> package should be used
+for that purpose.
+</p>
+
+<p>
+The set of parse functions provided by the <a href="/pkg/go/parser/"><code>go/parser</code></a>
+package has been reduced to the primary parse function
+<a href="/pkg/go/parser/#ParseFile"><code>ParseFile</code></a>, and a couple of
+convenience functions <a href="/pkg/go/parser/#ParseDir"><code>ParseDir</code></a>
+and <a href="/pkg/go/parser/#ParseExpr"><code>ParseExpr</code></a>.
+</p>
+
+<p>
+The type names of the <a href="/pkg/go/doc/"><code>go/doc</code></a> package have been
+streamlined by removing the <code>Doc</code> suffix: <code>PackageDoc</code>
+is now <code>Package</code>, <code>ValueDoc</code> is <code>Value</code>, etc.
+Also, all types now consistently have a <code>Name</code> field (or <code>Names</code>,
+in the case of type <code>Value</code>) and <code>Type.Factories</code> has become
+<code>Type.Funcs</code>.
+Instead of calling <code>doc.NewPackageDoc(pkg, importpath)</code>,
+documentation for a package is created with:
+</p>
+
+<pre>
+    doc.New(pkg, importpath, mode)
+</pre>
+
+<p>
+where the new <code>mode</code> parameter specifies the operation mode:
+if set to <a href="/pkg/go/doc/#AllDecls"><code>AllDecls</code></a>, all declarations
+(not just exported ones) are considered.
+The function <code>NewFileDoc</code> was removed, and the function
+<code>CommentText</code> has become the method
+<a href="/pkg/go/ast/#Text"><code>Text</code></a> of
+<a href="/pkg/go/ast/#CommentGroup"><code>ast.CommentGroup</code></a>.
+</p>
+
+<p>
+In package <a href="/pkg/go/token/"><code>go/token</code></a>, the
+<a href="/pkg/go/token/#FileSet"><code>token.FileSet</code></a> method <code>Files</code>
+(which originally returned a channel of <code>*token.File</code>s) has been replaced
+with the iterator <a href="/pkg/go/token/#FileSet.Iterate"><code>Iterate</code></a> that
+accepts a function argument instead.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses packages in <code>go</code> will have to be updated by hand; the
+compiler will reject incorrect uses. Templates used in conjuction with any of the
+<code>go/doc</code> types may need manual fixes; the renamed fields will lead
+to run-time errors.
+</p>
+
+<h3 id="hash">The hash package</h3>
+
+<p>
+In Go 1, the definition of <a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> includes
+a new method, <code>BlockSize</code>.  This new method is used primarily in the 
+cryptographic libraries.
+</p>
+
+<p>
+The <code>Sum</code> method of the
+<a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> interface now takes a
+<code>[]byte</code> argument, to which the hash value will be appended.
+The previous behavior can be recreated by adding a <code>nil</code> argument to the call.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing implementations of <code>hash.Hash</code> will need to add a
+<code>BlockSize</code> method.  Hashes that process the input one byte at
+a time can implement <code>BlockSize</code> to return 1.
+Gofix will update calls to the <code>Sum</code> methods of the various
+implementations of <code>hash.Hash</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Since the package's functionality is new, no updating is necessary.
+</p>
+
+<h3 id="http">The http package</h3>
+
+<p>
+In Go 1 the <a href="/pkg/net/http/"><code>http</code></a> package is refactored,
+putting some of the utilities into a
+<a href="/pkg/net/httputil/"><code>httputil</code></a> subdirectory.
+These pieces are only rarely needed by HTTP clients.
+The affected items are:
+</p>
+
+<ul>
+<li>ClientConn</li>
+<li>DumpRequest</li>
+<li>DumpRequest</li>
+<li>DumpRequestOut</li>
+<li>DumpResponse</li>
+<li>NewChunkedReader</li>
+<li>NewChunkedWriter</li>
+<li>NewClientConn</li>
+<li>NewProxyClientConn</li>
+<li>NewServerConn</li>
+<li>NewSingleHostReverseProxy</li>
+<li>ReverseProxy</li>
+<li>ServerConn</li>
+</ul>
+
+<p>
+Also, the <code>Request.RawURL</code> field has been removed; it was a
+historical artifact.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update the few programs that are affected except for
+uses of <code>RawURL</code>, which must be fixed by hand.
+</p>
+
+<h3 id="image">The image package</h3>
+
+<p>
+The <a href="/pkg/image/"><code>image</code></a> package has had a number of
+minor changes, rearrangements and renamings.
+</p>
+
+<p>
+Most of the color handling code has been moved into its own package,
+<a href="/pkg/image/color/"><code>image/color</code></a>.
+For the elements that moved, a symmetry arises; for instance,
+each pixel of an
+<a href="/pkg/image/#RGBA"><code>image.RGBA</code></a>
+is a
+<a href="/pkg/image/color/#RGBA"><code>color.RGBA</code></a>.
+</p>
+
+<p>
+The old <code>image/ycbcr</code> package has been folded, with some
+renamings, into the
+<a href="/pkg/image/"><code>image</code></a>
+and
+<a href="/pkg/image/color/"><code>image/color</code></a>
+packages.
+</p>
+
+<p>
+The old <code>image.ColorImage</code> type is still in the <code>image</code>
+package but has been renamed
+<a href="/pkg/image/#Uniform"><code>image.Uniform</code></a>,
+while <code>image.Tiled</code>
+has been renamed
+<a href="/pkg/image/#Repeated"><code>image.Repeated</code></a>.
+</p>
+
+<p>
+This table lists the renamings.
+</p>
+
+<table class="codetable" frame="border" summary="image renames">
+<colgroup align="left" width="50%"></colgroup>
+<colgroup align="left" width="50%"></colgroup>
+<tr>
+<th align="left">Old</th>
+<th align="left">New</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.Color</td> <td>color.Color</td></tr>
+<tr><td>image.ColorModel</td> <td>color.Model</td></tr>
+<tr><td>image.ColorModelFunc</td> <td>color.ModelFunc</td></tr>
+<tr><td>image.PalettedColorModel</td> <td>color.Palette</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.RGBAColor</td> <td>color.RGBA</td></tr>
+<tr><td>image.RGBA64Color</td> <td>color.RGBA64</td></tr>
+<tr><td>image.NRGBAColor</td> <td>color.NRGBA</td></tr>
+<tr><td>image.NRGBA64Color</td> <td>color.NRGBA64</td></tr>
+<tr><td>image.AlphaColor</td> <td>color.Alpha</td></tr>
+<tr><td>image.Alpha16Color</td> <td>color.Alpha16</td></tr>
+<tr><td>image.GrayColor</td> <td>color.Gray</td></tr>
+<tr><td>image.Gray16Color</td> <td>color.Gray16</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.RGBAColorModel</td> <td>color.RGBAModel</td></tr>
+<tr><td>image.RGBA64ColorModel</td> <td>color.RGBA64Model</td></tr>
+<tr><td>image.NRGBAColorModel</td> <td>color.NRGBAModel</td></tr>
+<tr><td>image.NRGBA64ColorModel</td> <td>color.NRGBA64Model</td></tr>
+<tr><td>image.AlphaColorModel</td> <td>color.AlphaModel</td></tr>
+<tr><td>image.Alpha16ColorModel</td> <td>color.Alpha16Model</td></tr>
+<tr><td>image.GrayColorModel</td> <td>color.GrayModel</td></tr>
+<tr><td>image.Gray16ColorModel</td> <td>color.Gray16Model</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>ycbcr.RGBToYCbCr</td> <td>color.RGBToYCbCr</td></tr>
+<tr><td>ycbcr.YCbCrToRGB</td> <td>color.YCbCrToRGB</td></tr>
+<tr><td>ycbcr.YCbCrColorModel</td> <td>color.YCbCrModel</td></tr>
+<tr><td>ycbcr.YCbCrColor</td> <td>color.YCbCr</td></tr>
+<tr><td>ycbcr.YCbCr</td> <td>image.YCbCr</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>ycbcr.SubsampleRatio444</td> <td>image.YCbCrSubsampleRatio444</td></tr>
+<tr><td>ycbcr.SubsampleRatio422</td> <td>image.YCbCrSubsampleRatio422</td></tr>
+<tr><td>ycbcr.SubsampleRatio420</td> <td>image.YCbCrSubsampleRatio420</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.ColorImage</td> <td>image.Uniform</td></tr>
+<tr><td>image.Tiled</td> <td>image.Repeated</td></tr>
+</table>
+
+<p>
+The image package's <code>New</code> functions
+(<a href="/pkg/image/#NewRGBA"><code>NewRGBA</code></a>,
+<a href="/pkg/image/#NewRGBA64"><code>NewRGBA64</code></a>, etc.)
+take an <a href="/pkg/image/#Rectangle"><code>image.Rectangle</code></a> as an argument
+instead of four integers.
+</p>
+
+<p>
+Finally, there are new predefined <code>color.Color</code> variables
+<a href="/pkg/image/color/#Black"><code>color.Black</code></a>,
+<a href="/pkg/image/color/#White"><code>color.White</code></a>,
+<a href="/pkg/image/color/#Opaque"><code>color.Opaque</code></a>
+and
+<a href="/pkg/image/color/#Transparent"><code>color.Transparent</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update almost all code affected by the change.
+</p>
+
+<h3 id="mime">The mime package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/mime/#FormatMediaType"><code>FormatMediaType</code></a> function
+of the <code>mime</code> package has  been simplified to make it
+consistent with
+<a href="/pkg/mime/#ParseMediaType"><code>ParseMediaType</code></a>. 
+It now takes <code>"text/html"</code> rather than <code>"text"</code> and <code>"html"</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="net">The net package</h3>
+
+<p>
+In Go 1, the various <code>SetTimeout</code>,
+<code>SetReadTimeout</code>, and <code>SetWriteTimeout</code> methods
+have been replaced with 
+<a href="/pkg/net/#IPConn.SetDeadline"><code>SetDeadline</code></a>,
+<a href="/pkg/net/#IPConn.SetReadDeadline"><code>SetReadDeadline</code></a>, and 
+<a href="/pkg/net/#IPConn.SetWriteDeadline"><code>SetWriteDeadline</code></a>,
+respectively.  Rather than taking a timeout value in nanoseconds that
+apply to any activity on the connection, the new methods set an
+absolute deadline (as a <code>time.Time</code> value) after which
+reads and writes will time out and no longer block.
+</p>
+
+<p>
+There is also a new <a href="/pkg/net/#DialTimeout"><code>net.DialTimeout</code></a> method to simplify
+timing out dialing a network address.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the old methods will fail to compile and must be updated by hand.
+The semantic change makes it difficult for gofix to update automatically.
+</p>
+
+<h3 id="os_fileinfo">The os.FileInfo type</h3>
+
+<p>
+Go 1 redefines the <a href="/pkg/os/#FileInfo"><code>os.FileInfo</code></a> type,
+changing it from a struct to an interface:
+</p>
+
+<pre>
+    type FileInfo interface {
+        Name() string       // base name of the file
+        Size() int64        // length in bytes
+        Mode() FileMode     // file mode bits
+        ModTime() time.Time // modification time
+        IsDir() bool        // abbreviation for Mode().IsDir()
+    }
+</pre>
+
+<p>
+The file mode information has been moved into a subtype called
+<a href="/pkg/os/#FileMode"><code>os.FileMode</code></a>,
+a simple integer type with <code>IsDir</code>, <code>Perm</code>, and <code>String</code>
+methods.
+</p>
+
+<p>
+The system-specific details of file modes and properties such as (on Unix)
+i-number have been removed from <code>FileInfo</code> altogether.
+Instead, each operating system's <code>os</code> package provides an
+implementation of the <code>FileInfo</code> interface, <code>*os.FileStat</code>,
+which in turn contains a <code>Sys</code> field that stores the
+system-specific representation of file metadata.
+For instance, to discover the i-number of a file on a Unix system, unpack
+the <code>FileInfo</code> like this:
+</p>
+
+<pre>
+    fi, err := os.Stat("hello.go")
+    if err != nil {
+        log.Fatal(err)
+    }
+    // Make sure it's an implementation known to package os.
+    fileStat, ok := fi.(*os.FileStat)
+    if !ok {
+        log.Fatal("hello.go: not an os File")
+    }
+    // Now check that it's a Unix file.
+    unixStat, ok := fileStat.Sys.(*syscall.Stat_t)
+    if !ok {
+        log.Fatal("hello.go: not a Unix file")
+    }
+    fmt.Printf("file i-number: %d\n", unixStat.Ino)
+</pre>
+
+<p>
+Assuming (which is unwise) that <code>"hello.go"</code> is a Unix file,
+the i-number expression could be contracted to
+</p>
+
+<pre>
+    fi.(*os.FileStat).Sys.(*syscall.Stat_t).Ino
+</pre>
+
+<p>
+The vast majority of uses of <code>FileInfo</code> need only the methods
+of the standard interface.
+</p>
+	
+<p>
+<em>Updating</em>:
+Gofix will update code that uses the old equivalent of the current <code>os.FileInfo</code>
+and <code>os.FileMode</code> API.
+Code that needs system-specific file details will need to be updated by hand.
+</p>
+
+<h3 id="path_filepath">The path/filepath package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/path/filepath/#Walk"><code>Walk</code></a> function of the
+<code>path/filepath</code> package
+has been changed to take a function value of type
+<a href="/pkg/path/filepath/#WalkFunc"><code>WalkFunc</code></a>
+instead of a <code>Visitor</code> interface value.
+<code>WalkFunc</code> unifies the handling of both files and directories.
+</p>
+
+<pre>
+    type WalkFunc func(path string, info *os.FileInfo, err os.Error) os.Error
+</pre>
+
+<p>
+The <code>WalkFunc</code> function will be called even for files or directories that could not be opened;
+in such cases the error argument will describe the failure.
+If a directory's contents are to be skipped,
+the function should return the value <code>SkipDir</code>.
+</p>
+
+<p>
+<font color="red">TODO: add an example?</font>
+</p>
+
+<p>
+<em>Updating</em>:
+The change simplifies most code but has subtle consequences, so affected programs
+will need to be updated by hand.
+The compiler will catch code using the old interface.
+</p>
+
+<h3 id="runtime">The runtime package</h3>
+
+<p>
+The <code>runtime</code> package in Go 1 includes a new niladic function,
+<a href="/pkg/runtime/#NumCPU"><code>runtime.NumCPU</code></a>, that returns the number of CPUs available
+for parallel execution, as reported by the operating system kernel.
+Its value can inform the setting of <code>GOMAXPROCS</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+No existing code is affected.
+</p>
+
+<h3 id="strconv">The strconv package</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/strconv/"><code>strconv</code></a>
+package has been significantly reworked to make it more Go-like and less C-like,
+although <code>Atoi</code> lives on (it's similar to
+<code>int(ParseInt(x, 10, 0))</code>, as does
+<code>Itoa(x)</code> (<code>FormatInt(int64(x), 10)</code>).
+There are also new variants of some of the functions that append to byte slices rather than
+return strings, to allow control over allocation.
+</p>
+
+<p>
+This table summarizes the renamings; see the
+<a href="/pkg/strconv/">package documentation</a>
+for full details.
+</p>
+
+<table class="codetable" frame="border" summary="strconv renames">
+<colgroup align="left" width="50%"></colgroup>
+<colgroup align="left" width="50%"></colgroup>
+<tr>
+<th align="left">Old call</th>
+<th align="left">New call</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atob(x)</td> <td>ParseBool(x)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atof32(x)</td> <td>ParseFloat(x, 32)§</td></tr>
+<tr><td>Atof64(x)</td> <td>ParseFloat(x, 64)</td></tr>
+<tr><td>AtofN(x, n)</td> <td>ParseFloat(x, n)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atoi(x)</td> <td>Atoi(x)</td></tr>
+<tr><td>Atoi(x)</td> <td>ParseInt(x, 10, 0)§</td></tr>
+<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atoui(x)</td> <td>ParseUint(x, 10, 0)§</td></tr>
+<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Btoi64(x, b)</td> <td>ParseInt(x, b, 64)</td></tr>
+<tr><td>Btoui64(x, b)</td> <td>ParseUint(x, b, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Btoa(x)</td> <td>FormatBool(x)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Ftoa32(x, f, p)</td> <td>FormatFloat(x, float64(f), p, 32)</td></tr>
+<tr><td>Ftoa64(x, f, p)</td> <td>FormatFloat(x, f, p, 64)</td></tr>
+<tr><td>FtoaN(x, f, p, n)</td> <td>FormatFloat(x, f, p, n)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Itoa(x)</td> <td>Itoa(x)</td></tr>
+<tr><td>Itoa(x)</td> <td>FormatInt(int64(x), 10)</td></tr>
+<tr><td>Itoa64(x)</td> <td>FormatInt(x, 10)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Itob(x, b)</td> <td>FormatInt(int64(x), b)</td></tr>
+<tr><td>Itob64(x, b)</td> <td>FormatInt(x, b)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Uitoa(x)</td> <td>FormatUint(uint64(x), 10)</td></tr>
+<tr><td>Uitoa64(x)</td> <td>FormatUint(x, 10)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Uitob(x, b)</td> <td>FormatUint(uint64(x), b)</td></tr>
+<tr><td>Uitob64(x, b)</td> <td>FormatUint(x, b)</td></tr>
+</table>
+		
+<p>
+<em>Updating</em>:
+Gofix will update almost all code affected by the change.
+<br>
+§ <code>Atoi</code> persists but <code>Atoui</code> and <code>Atof32</code> do not, so
+they may require
+a cast that must be added by hand; gofix will warn about it.
+</p>
+
+
+<h3 id="testing">The testing package</h3>
+
+<p>
+The testing package has a type, <code>B</code>, passed as an argument to benchmark functions.
+In Go 1, <code>B</code> has new methods, analogous to those of <code>T</code>, enabling
+logging and failure reporting.
+</p>
+
+<pre><!--{{code "progs/go1.go" `/func.*Benchmark/` `/^}/`}}
+-->func BenchmarkSprintf(b *testing.B) {
+    // Verify correctness before running benchmark.
+    b.StopTimer()
+    got := fmt.Sprintf("%x", 23)
+    const expect = "17"
+    if expect != got {
+        b.Fatalf("expected %q; got %q", expect, got)
+    }
+    b.StartTimer()
+    for i := 0; i < b.N; i++ {
+        fmt.Sprintf("%x", 23)
+    }
+}</pre>
+
+<p>
+<em>Updating</em>:
+Existing code is unaffected, although benchmarks that use <code>println</code>
+or <code>panic</code> should be updated to use the new methods.
+</p>
+
+<h3 id="url">The url package</h3>
+
+<p>
+In Go 1 several fields from the <a href="/pkg/net/url/#URL"><code>url.URL</code></a> type
+were removed or replaced.
+</p>
+
+<p>
+The <a href="/pkg/net/url/#URL.String"><code>String</code></a> method now
+predictably rebuilds an encoded URL string using all of <code>URL</code>'s
+fields as necessary. The resulting string will also no longer have
+passwords escaped.
+</p>
+
+<p>
+The <code>Raw</code> field has been removed. In most cases the <code>String</code>
+method may be used in its place.
+</p>
+
+<p>
+The old <code>RawUserinfo</code> field is replaced by the <code>User</code>
+field, of type <a href="/pkg/net/url/#Userinfo"><code>*net.Userinfo</code></a>.
+Values of this type may be created using the new <a href="/pkg/net/url/#User"><code>net.User</code></a>
+and <a href="/pkg/net/url/#UserPassword"><code>net.UserPassword</code></a>
+functions. The <code>EscapeUserinfo</code> and <code>UnescapeUserinfo</code>
+functions are also gone.
+</p>
+
+<p>
+The <code>RawAuthority</code> field has been removed. The same information is
+available in the <code>Host</code> and <code>User</code> fields.
+</p>
+
+<p>
+The <code>RawPath</code> field and the <code>EncodedPath</code> method have
+been removed. The path information in rooted URLs (with a slash following the
+schema) is now available only in decoded form in the <code>Path</code> field.
+Occasionally, the encoded data may be required to obtain information that
+was lost in the decoding process. These cases must be handled by accessing
+the data the URL was built from.
+</p>
+
+<p>
+URLs with non-rooted paths, such as <code>"mailto:dev at golang.org?subject=Hi"</code>,
+are also handled differently. The <code>OpaquePath</code> boolean field has been
+removed and a new <code>Opaque</code> string field introduced to hold the encoded
+path for such URLs. In Go 1, the cited URL parses as:
+</p>
+
+<pre>
+    URL{
+        Scheme: "mailto",
+        Opaque: "dev at golang.org",
+        RawQuery: "subject=Hi",
+    }
+</pre>
+
+<p>
+A new <a href="/pkg/net/url/#URL.RequestURI"><code>RequestURI</code></a> method was
+added to <code>URL</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the old fields will fail to compile and must be updated by hand.
+The semantic changes make it difficult for gofix to update automatically.
+</p>
+
+<h3 id="xml">The xml package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/encoding/xml/"><code>xml</code></a> package
+has been brought closer in design to the other marshaling packages such
+as <a href="/pkg/encoding/gob/"><code>encoding/gob</code></a>.
+</p>
+
+<p>
+The old <code>Parser</code> type is renamed
+<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> and has a new
+<a href="/pkg/encoding/xml/#Decoder.Decode"><code>Decode</code></a> method. An
+<a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a> type was also
+introduced.
+</p>
+
+<p>
+The functions <a href="/pkg/encoding/xml/#Marshal"><code>Marshal</code></a>
+and <a href="/pkg/encoding/xml/#Unmarshal"><code>Unmarshal</code></a>
+work with <code>[]byte</code> values now. To work with streams,
+use the new <a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a>
+and <a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> types.
+</p>
+
+<p>
+When marshaling or unmarshaling values, the format of supported flags in
+field tags has changed to be closer to the
+<a href="/pkg/encoding/json"><code>json</code></a> package
+(<code>`xml:"name,flag"`</code>). The matching done between field tags, field
+names, and the XML attribute and element names is now case-sensitive.
+The <code>XMLName</code> field tag, if present, must also match the name
+of the XML element being marshaled.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update most uses of the package except for some calls to
+<code>Unmarshal</code>. Special care must be taken with field tags,
+since gofix will not update them and if not fixed by hand they will
+misbehave silently in some cases. For example, the old
+<code>"attr"</code> is now written <code>",attr"</code> while plain
+<code>"attr"</code> remains valid but with a different meaning.
+</p>
+
+<h2 id="go_command">The go command</h2>
+
+<h2 id="releases">Packaged releases</h2>
+
diff --git a/doc/go1.tmpl b/doc/go1.tmpl
new file mode 100644
index 0000000..fd005b1
--- /dev/null
+++ b/doc/go1.tmpl
@@ -0,0 +1,1460 @@
+<!--{
+	"Title": "Go 1 Release Notes"
+}-->
+{{donotedit}}
+
+<h2 id="introduction">Introduction to Go 1</h2>
+
+<p>
+For a full explanation of the motivation and design of Go 1, see XXX.
+Here follows a summary.
+</p>
+
+<p>
+Go 1 is intended to be a stable language and core library set that
+will form a reliable foundation for people and organizations that
+want to make a long-term commitment to developing in the Go programming
+language. Go will continue to develop, but in a way that guarantees
+code written to the Go 1 specification will continue to work. For
+instance, Go 1 will be a supported platform on Google App Engine
+for the next few years. Incompatible changes to the environment,
+should they arise, will be done in a distinct version.
+</p>
+
+<p>
+This document describes the changes in the language and libraries
+in Go 1, relative to the previous release, r60 (at the time of
+writing, tagged as r60.3). It also explains how to update code at
+r60 to compile and run under Go 1. Finally, it outlines the new
+<code>go</code> command for building Go programs and the new binary
+release process being introduced. Most of these topics have more
+thorough presentations elsewhere; such documents are linked below.
+</p>
+
+<h2 id="language">Changes to the language</h2>
+
+<h3 id="append">Append</h3>
+
+<p>
+The <code>append</code> built-in function is variadic, so one can
+append to a byte slice using the <code>...</code> syntax in the
+call.
+</p>
+
+{{code "progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
+
+<p>
+By analogy with the similar property of <code>copy</code>, Go 1
+permits a string to be appended (byte-wise) directly to a byte
+slice; the conversion is no longer necessary:
+</p>
+
+{{code "progs/go1.go" `/append.*world/`}}
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="close">Close</h3>
+
+<p>
+The <code>close</code> built-in function lets a sender tell a receiver
+that no more data will be transmitted on the channel.  In Go 1 the
+type system enforces the directionality when possible: it is illegal
+to call <code>close</code> on a receive-only channel:
+</p>
+
+<pre>
+    var c chan int
+    var csend chan<- int = c
+    var crecv <-chan int = c
+    close(c)     // legal
+    close(csend) // legal
+    close(crecv) // illegal
+</pre>
+
+<p>
+<em>Updating</em>:
+Existing code that attempts to close a receive-only channel was
+erroneous even before Go 1 and should be fixed.  The compiler will
+now reject such code.
+</p>
+
+<h3 id="literals">Composite literals</h3>
+
+<p>
+In Go 1, a composite literal of array, slice, or map type can elide the
+type specification for the elements' initializers if they are of pointer type.
+All four of the initializations in this example are legal; the last one was illegal before Go 1.
+</p>
+
+{{code "progs/go1.go" `/type Date struct/` `/STOP/`}}
+
+<p>
+<em>Updating</em>:
+This change has no effect on existing code, but the command
+<code>gofmt</code> <code>-s</code> applied to existing source
+will, among other things, elide explicit element types wherever permitted.
+</p>
+
+
+<h3 id="init">Goroutines during init</h3>
+
+<p>
+Go 1 allows goroutines to be created and run during initialization.
+(They used to be created but were not run until after initialization
+completed.) Code that uses goroutines can now be called from
+<code>init</code> routines and global initialization expressions
+without introducing a deadlock.
+</p>
+
+{{code "progs/go1.go" `/PackageGlobal/` `/^}/`}}
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes,
+although it's possible that code that depends on goroutines not starting before <code>main</code> will break.
+There was no such code in the standard repository.
+</p>
+
+<h3 id="rune">The rune type</h3>
+
+<p>
+Go 1 introduces a new basic type, <code>rune</code>, to be used to represent
+individual Unicode code points.
+It is an alias for <code>int32</code>, analogous to <code>byte</code>
+as an alias for <code>uint8</code>.
+</p>
+
+<p>
+Character literals such as <code>'a'</code>, <code>'語'</code>, and <code>'\u0345'</code>
+now have default type <code>rune</code>,
+analogous to <code>1.0</code> having default type <code>float64</code>.
+A variable initialized to a character constant will therefore
+have type <code>rune</code> unless otherwise specified.
+</p>
+
+<p>
+Libraries have been updated to use <code>rune</code> rather than <code>int</code>
+when appropriate. For instance, the functions <code>unicode.ToLower</code> and
+relatives now take and return a <code>rune</code>.
+</p>
+
+{{code "progs/go1.go" `/STARTRUNE/` `/ENDRUNE/`}}
+
+<p>
+<em>Updating</em>:
+Most source code will be unaffected by this because the type inference from
+<code>:=</code> initializers introduces the new type silently, and it propagates
+from there.
+Some code may get type errors that a trivial conversion will resolve.
+</p>
+
+<h3 id="error">The error type</h3>
+
+<p>
+Go 1 introduces a new built-in type, <code>error</code>, which has the following definition:
+</p>
+
+<pre>
+    type error interface {
+        Error() string
+    }
+</pre>
+
+<p>
+Since the consequences of this type are all in the package library,
+it is discussed <a href="#errors">below</a>.
+</p>
+
+<h3 id="delete">Deleting from maps</h3>
+
+<p>
+The original syntax for deleting an element in a map was:
+</p>
+
+<pre>
+    m[k] = ignored, false
+</pre>
+
+<p>
+In Go 1, that syntax has gone; instead there is a new built-in
+function, <code>delete</code>.  The call
+</p>
+
+{{code "progs/go1.go" `/delete\(m, k\)/`}}
+
+<p>
+will delete the map entry retrieved by the expression <code>m[k]</code>.
+There is no return value. Deleting a non-existent entry is a no-op.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will convert expressions of the form <code>m[k] = ignored,
+false</code> into <code>delete(m, k)</code> when it is clear that
+the ignored value can be safely discarded from the program and
+<code>false</code> refers to the predefined boolean constant.  Gofix
+will flag other uses of the syntax for inspection by the programmer.
+</p>
+
+<h3 id="iteration">Iterating in maps</h3>
+
+<p>
+In Go 1, the order in which elements are visited when iterating
+over a map using a <code>for</code> <code>range</code> statement
+is defined to be unpredictable, even if the same loop is run multiple
+times with the same map.
+Code should not assume that the elements are visited in any particular order.
+</p>
+
+{{code "progs/go1.go" `/Sunday/` `/^	}/`}}
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help.  Most existing code
+will be unaffected, but some programs may break or misbehave; we
+recommend manual checking of all range statements over maps to
+verify they do not depend on iteration order. There were a few such
+examples in the standard repository; they have been fixed.
+Note that it was already incorrect to depend on the iteration order, which
+was unspecified. This change codifies the unpredictability.
+</p>
+
+<h3 id="multiple_assignment">Multiple assignment</h3>
+
+<p>
+Go 1 fully specifies the evaluation order in multiple assignment
+statements. In particular, if the left-hand side of the assignment
+statement contains expressions that require evaluation, such as
+function calls or array indexing operations, these will all be done
+using the usual left-to-right rule before any variables are assigned
+their value.  Once everything is evaluated, the actual assignments
+proceed in left-to-right order.
+</p>
+
+<p>
+These examples illustrate the behavior.
+</p>
+
+{{code "progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
+
+<p>
+<em>Updating</em>:
+This is one change where tools cannot help, but breakage is unlikely.
+No code in the standard repository was broken by this change, and code
+that depended on the previous unspecified behavior was already incorrect.
+</p>
+
+<h3 id="shadowing">Returns and shadowed variables</h3>
+
+<p>
+A shadowed variable is one that has the same name as another variable in an inner scope.
+In functions with named return values,
+the Go 1 compilers disallow return statements without arguments if any of the named return values is shadowed at the point of the return statement.
+(It isn't part of the specification, because this is one area we are still exploring;
+the situation is analogous to the compilers rejecting functions that do not end with an explicit return statement.)
+</p>
+
+<p>
+This function implicitly returns a shadowed return value and will be rejected by the compiler:
+</p>
+
+<pre>
+    func Bug() (i, j, k int) {
+        for i = 0; i < 5; i++ {
+            for j := 0; j < 5; j++ { // Redeclares j.
+                k += i*j
+                if k > 100 {
+                    return // Rejected: j is shadowed here.
+                }
+            }
+        }
+        return // OK: j is not shadowed here.
+    }
+</pre>
+
+<p>
+<em>Updating</em>:
+Code that shadows return values in this way will be rejected by the compiler and will need to be fixed by hand.
+The few cases that arose in the standard repository were mostly bugs.
+</p>
+
+<h3 id="unexported">Copying structs with unexported fields</h3>
+
+<p>
+Go 1 relaxes the rules about accessing structs with unexported (lower-case) fields,
+permitting a client package to assign (and therefore copy) such a struct.
+Of course, the client package still cannot access such fields individually.
+</p>
+
+<p>
+As an example, if package <code>p</code> includes the definitions,
+</p>
+
+<pre>
+    type Struct struct {
+        Public int
+        secret int
+    }
+    func NewStruct(a int) Struct {  // Note: not a pointer.
+        return Struct{a, f(a)}
+    }
+    func (s Struct) String() string {
+        return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
+    }
+</pre>
+
+<p>
+a package that imports <code>p</code> can assign and copy values of type
+<code>p.Struct</code> at will.
+Behind the scenes the unexported fields will be assigned and copied just
+as if they were exported,
+but the client code will never be aware of them. The code
+</p>
+
+<pre>
+    import "p"
+
+    myStruct := p.NewStruct(23)
+    copyOfMyStruct := myStruct
+    fmt.Println(myStruct, copyOfMyStruct)
+</pre>
+
+<p>
+will show that the secret field of the struct has been copied to the new value.
+</p>
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="equality">Equality of structs and arrays</h3>
+
+<p>
+Go 1 defines equality and inequality (<code>==</code> and
+<code>!=</code>) for struct and array values, respectively, provided
+the elements of the data structures can themselves be compared.
+That is, if equality is defined for all the fields of a struct (or
+an array element), then it is defined for the struct (or array).
+</p>
+
+<p>
+As a result, structs and arrays can now be used as map keys:
+</p>
+
+{{code "progs/go1.go" `/type Day struct/` `/Printf/`}}
+
+<p>
+Note that equality is still undefined for slices, for which the
+calculation is in general infeasible.  Also note that the ordered
+comparison operators (<code><</code> <code><=</code>
+<code>></code> <code>>=</code>) are still undefined for
+structs and arrays.
+
+<p>
+<em>Updating</em>:
+This is a new feature, so existing code needs no changes.
+</p>
+
+<h3 id="funcs">Function and map equality</h3>
+
+<p>
+Go 1 disallows checking for equality of functions and maps,
+respectively, except to compare them directly to <code>nil</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing code that depends on function or map equality will be
+rejected by the compiler and will need to be fixed by hand.
+Few programs will be affected, but the fix may require some
+redesign.
+</p>
+
+<h2 id="packages">The package hierarchy</h2>
+
+<p>
+This section describes how the packages have been rearranged in Go 1.
+Some have moved, some have been renamed, some have been deleted.
+New packages are described in later sections.
+</p>
+
+<h3 id="hierarchy">The package hierarchy</h3>
+
+<p>
+Go 1 has a rearranged package hierarchy that groups related items
+into subdirectories. For instance, <code>utf8</code> and
+<code>utf16</code> now occupy subdirectories of <code>unicode</code>.
+Also, <a href="#subrepo">some packages</a> have moved into
+subrepositories of
+<a href="http://code.google.com/p/go"><code>code.google.com/p/go</code></a>
+while <a href="#deleted">others</a> have been deleted outright.
+</p>
+
+<table class="codetable" frame="border" summary="Moved packages">
+<colgroup align="left" width="60%"></colgroup>
+<colgroup align="left" width="40%"></colgroup>
+<tr>
+<th align="left">Old path</th>
+<th align="left">New path</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>asn1</td> <td>encoding/asn1</td></tr>
+<tr><td>csv</td> <td>encoding/csv</td></tr>
+<tr><td>gob</td> <td>encoding/gob</td></tr>
+<tr><td>json</td> <td>encoding/json</td></tr>
+<tr><td>xml</td> <td>encoding/xml</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exp/template/html</td> <td>html/template</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>big</td> <td>math/big</td></tr>
+<tr><td>cmath</td> <td>math/cmplx</td></tr>
+<tr><td>rand</td> <td>math/rand</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>http</td> <td>net/http</td></tr>
+<tr><td>http/cgi</td> <td>net/http/cgi</td></tr>
+<tr><td>http/fcgi</td> <td>net/http/fcgi</td></tr>
+<tr><td>http/httptest</td> <td>net/http/httptest</td></tr>
+<tr><td>http/pprof</td> <td>net/http/pprof</td></tr>
+<tr><td>mail</td> <td>net/mail</td></tr>
+<tr><td>rpc</td> <td>net/rpc</td></tr>
+<tr><td>rpc/jsonrpc</td> <td>net/rpc/jsonrpc</td></tr>
+<tr><td>smtp</td> <td>net/smtp</td></tr>
+<tr><td>url</td> <td>net/url</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>exec</td> <td>os/exec</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>scanner</td> <td>text/scanner</td></tr>
+<tr><td>tabwriter</td> <td>text/tabwriter</td></tr>
+<tr><td>template</td> <td>text/template</td></tr>
+<tr><td>template/parse</td> <td>text/template/parse</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>utf8</td> <td>unicode/utf8</td></tr>
+<tr><td>utf16</td> <td>unicode/utf16</td></tr>
+</table>
+
+<p>
+Note that the package names for the old <code>cmath</code> and
+<code>exp/template/html</code> packages have changed to <code>cmplx</code>
+and <code>template</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update all imports and package renames for packages that
+remain inside the standard repository.  Programs that import packages
+that are no longer in the standard repository will need to be edited
+by hand.
+<br>
+<font color="red">TODO: gofix should warn about deletions.</font>
+</p>
+
+<h3 id="exp">The package tree exp</h3>
+
+<p>
+Because they are not standardized, the packages under the <code>exp</code> directory will not be available in the
+standard Go 1 release distributions, although they will be available in source code form
+in <a href="http://code.google.com/p/go/">the repository</a> for
+developers who wish to use them.
+</p>
+
+<p>
+Several packages have moved under <code>exp</code> at the time of Go 1's release:
+</p>
+
+<ul>
+<li><code>ebnf</code></li>
+<li><code>go/types</code></li>
+<li><code>http/spdy</code></li>
+</ul>
+
+<p>
+All these packages are available under the same names, with the prefix <code>exp/</code>: <code>exp/ebnf</code> etc.
+</p>
+
+<p>
+Also, the <code>utf8.String</code> type has been moved to its own package, <code>exp/utf8string</code>.
+</p>
+
+<p>
+Finally, the <code>gotype</code> command now resides in <code>exp/gotype</code>, while
+<code>ebnflint</code> is now in <code>exp/ebnflint</code>
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses packages in <code>exp</code> will need to be updated by hand,
+or else compiled from an installation that has <code>exp</code> available.
+Gofix or the compiler will complain about such uses.
+<br>
+<font color="red">TODO: gofix should warn about such uses.</font>
+</p>
+
+<h3 id="old">The package tree old</h3>
+
+<p>
+Because they are deprecated, the packages under the <code>old</code> directory will not be available in the
+standard Go 1 release distributions, although they will be available in source code form for
+developers who wish to use them.
+</p>
+
+<p>
+The packages in their new locations are:
+</p>
+
+<ul>
+<li><code>old/netchan</code></li>
+<li><code>old/regexp</code></li>
+<li><code>old/template</code></li>
+</ul>
+
+<p>
+<em>Updating</em>:
+Code that uses packages now in <code>old</code> will need to be updated by hand,
+or else compiled from an installation that has <code>old</code> available.
+Gofix will warn about such uses.
+<br>
+<font color="red">TODO: gofix should warn about such uses.</font>
+</p>
+
+<h3 id="deleted">Deleted packages</h3>
+
+<p>
+Go 1 deletes several packages outright:
+</p>
+
+<ul>
+<li><code>container/vector</code></li>
+<li><code>exp/datafmt</code></li>
+<li><code>go/typechecker</code></li>
+<li><code>try</code></li>
+</ul>
+
+<p>
+and also the command <code>gotry</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses <code>container/vector</code> should be updated to use
+slices directly.  See
+<a href="http://code.google.com/p/go-wiki/wiki/SliceTricks">the Go
+Language Community Wiki</a> for some suggestions.
+Code that uses the other packages (there should be almost zero) will need to be rethought.
+<br>
+<font color="red">TODO: gofix should warn such uses.</font>
+</p>
+
+<h3 id="subrepo">Packages moving to subrepositories</h3>
+
+<p>
+Go 1 has moved a number of packages into sub-repositories of
+<a href="http://code.google.com/p/go/">the main Go repository</a>.
+This table lists the old and new import paths:
+
+<table class="codetable" frame="border" summary="Sub-repositories">
+<colgroup align="left" width="40%"></colgroup>
+<colgroup align="left" width="60%"></colgroup>
+<tr>
+<th align="left">Old</th>
+<th align="left">New</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>crypto/bcrypt</td> <td>code.google.com/p/go.crypto/bcrypt</tr>
+<tr><td>crypto/blowfish</td> <td>code.google.com/p/go.crypto/blowfish</tr>
+<tr><td>crypto/cast5</td> <td>code.google.com/p/go.crypto/cast5</tr>
+<tr><td>crypto/md4</td> <td>code.google.com/p/go.crypto/md4</tr>
+<tr><td>crypto/ocsp</td> <td>code.google.com/p/go.crypto/ocsp</tr>
+<tr><td>crypto/openpgp</td> <td>code.google.com/p/go.crypto/openpgp</tr>
+<tr><td>crypto/openpgp/armor</td> <td>code.google.com/p/go.crypto/openpgp/armor</tr>
+<tr><td>crypto/openpgp/elgamal</td> <td>code.google.com/p/go.crypto/openpgp/elgamal</tr>
+<tr><td>crypto/openpgp/errors</td> <td>code.google.com/p/go.crypto/openpgp/errors</tr>
+<tr><td>crypto/openpgp/packet</td> <td>code.google.com/p/go.crypto/openpgp/packet</tr>
+<tr><td>crypto/openpgp/s2k</td> <td>code.google.com/p/go.crypto/openpgp/s2k</tr>
+<tr><td>crypto/ripemd160</td> <td>code.google.com/p/go.crypto/ripemd160</tr>
+<tr><td>crypto/twofish</td> <td>code.google.com/p/go.crypto/twofish</tr>
+<tr><td>crypto/xtea</td> <td>code.google.com/p/go.crypto/xtea</tr>
+<tr><td>exp/ssh</td> <td>code.google.com/p/go.crypto/ssh</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>net/dict</td> <td>code.google.com/p/go.net/dict</tr>
+<tr><td>net/websocket</td> <td>code.google.com/p/go.net/websocket</tr>
+<tr><td>exp/spdy</td> <td>code.google.com/p/go.net/spdy</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>encoding/git85</td> <td>code.google.com/p/go.codereview/git85</tr>
+<tr><td>patch</td> <td>code.google.com/p/go.codereview/patch</tr>
+</table>
+
+<p>
+<em>Updating</em>:
+Gofix will update imports of these packages to use the new import paths.
+Installations that depend on these packages will need to install them using
+a <code>go install</code> command.
+</p>
+
+<h2 id="major">Major changes to the library</h2>
+
+<p>
+This section describes significant changes to the core libraries, the ones that
+affect the most programs.
+</p>
+
+<h3 id="errors">The error type and errors package</h3>
+
+<p>
+As mentioned above, Go 1 introduces a new built-in interface type called <code>error</code>.
+Its intent is to replace the old <code>os.Error</code> type with a more central concept.
+So the widely-used <code>String</code> method does not cause accidental satisfaction
+of the <code>error</code> interface, the <code>error</code> interface uses instead
+the name <code>Error</code> for that method:
+</p>
+
+<pre>
+    type error interface {
+        Error() string
+    }
+</pre>
+
+<p>
+The <code>fmt</code> library automatically invokes <code>Error</code>, as it already
+does for <code>String</code>, for easy printing of error values.
+</p>
+
+{{code "progs/go1.go" `/START ERROR EXAMPLE/` `/END ERROR EXAMPLE/`}}
+
+<p>
+All standard packages have been updated to use the new interface; the old <code>os.Error</code> is gone.
+</p>
+
+<p>
+A new package, <a href="/pkg/errors/"><code>errors</code></a>, contains the function
+</p>
+
+<pre>
+func New(text string) error
+</pre>
+
+<p>
+to turn a string into an error. It replaces the old <code>os.NewError</code>.
+</p>
+
+{{code "progs/go1.go" `/ErrSyntax/`}}
+		
+<p>
+<em>Updating</em>:
+Gofix will update almost all code affected by the change.
+Code that defines error types with a <code>String</code> method will need to be updated
+by hand to rename the methods to <code>Error</code>.
+</p>
+
+<h3 id="errno">System call errors</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/syscall/"><code>syscall</code></a>
+package returns an <code>error</code> for system call errors,
+rather than plain integer <code>errno</code> values.
+On Unix, the implementation is done by a 
+<a href="/pkg/syscall/#Errno"><code>syscall.Errno</code></a> type
+that satisfies <code>error</code> and replaces the old <code>os.Errno</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update almost all code affected by the change.
+Regardless, most code should use the <code>os</code> package
+rather than <code>syscall</code> and so will be unaffected.
+</p>
+
+<h3 id="time">Time</h3>
+
+<p>
+One of the most sweeping changes in the Go 1 library is the
+complete redesign of the 
+<a href="/pkg/time/"><code>time</code></a> package.
+Instead of an integer number of nanoseconds as an <code>int64</code>,
+and a separate <code>*time.Time</code> type to deal with human
+units such as hours and years,
+there are now two fundamental types:
+<a href="/pkg/time/#Time"><code>time.Time</code></a>
+(a value, so the <code>*</code> is gone), which represents a moment in time;
+and <a href="/pkg/time/#Duration"><code>time.Duration</code></a>,
+which represents an interval.
+Both have nanosecond resolution.
+A <code>Time</code> can represent any time into the ancient
+past and remote future, while a <code>Duration</code> can
+span plus or minus only about 290 years.
+There are methods on these types, plus a number of helpful
+predefined constant durations such as <code>time.Second</code>.
+</p>
+
+<p>
+Among the new methods are things like
+<a href="/pkg/time/#Time.Add"><code>Time.Add</code></a>,
+which adds a <code>Duration</code> to a <code>Time</code>, and
+<a href="/pkg/time/#Time.Sub"><code>Time.Sub</code></a>,
+which subtracts two <code>Times</code> to yield a <code>Duration</code>.
+</p>
+
+<p>
+The most important semantic change is that the Unix epoch (Jan 1, 1970) is now
+relevant only for those functions and methods that mention Unix:
+<a href="/pkg/time/#Unix"><code>time.Unix</code></a>
+and the <a href="/pkg/time/#Time.Unix"><code>Unix</code></a>
+and <a href="/pkg/time/#Time.UnixNano"><code>UnixNano</code></a> methods
+of the <code>Time</code> type.
+In particular,
+<a href="/pkg/time/#Now"><code>time.Now</code></a>
+returns a <code>time.Time</code> value rather than, in the old
+API, an integer nanosecond count since the Unix epoch.
+</p>
+
+{{code "progs/go1.go" `/sleepUntil/` `/^}/`}}
+
+<p>
+The new types, methods, and constants have been propagated through
+all the standard packages that use time, such as <code>os</code> and
+its representation of file time stamps.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update many uses of the old <code>time</code> package to use the new
+types and methods, although it does not replace values such as <code>1e9</code>
+representing nanoseconds per second.
+Also, because of type changes in some of the values that arise,
+some of the expressions rewritten by gofix may require
+further hand editing; in such cases the rewrite will include
+the correct function or method for the old functionality, but
+may have the wrong type or require further analysis.
+</p>
+
+<h2 id="minor">Minor changes to the library</h2>
+
+<p>
+This section describes smaller changes, such as those to less commonly
+used packages or that affect
+few programs beyond the need to run gofix.
+This category includes packages that are new in Go 1.
+</p>
+
+<h3 id="crypto_elliptic">The crypto/elliptic package</h3>
+
+<p>
+In Go 1, <a href="/pkg/crypto/elliptic/#Curve"><code>elliptic.Curve</code></a>
+has been made an interface to permit alternative implementations. The curve
+parameters have been moved to the
+<a href="/pkg/crypto/elliptic/#CurveParams"><code>elliptic.CurveParams</code></a>
+structure.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing users of <code>*elliptic.Curve</code> will need to change to
+simply <code>elliptic.Curve</code>. Calls to <code>Marshal</code>,
+<code>Unmarshal</code> and <code>GenerateKey</code> are now functions
+in <code>crypto/elliptic</code> that take an <code>elliptic.Curve</code>
+as their first argument.
+</p>
+
+<h3 id="crypto_x509">The crypto/x509 package</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
+and
+<a href="/pkg/crypto/x509/#CreateCRL"><code>CreateCRL</code></a>
+functions in <code>crypto/x509</code> have been altered to take an
+<code>interface{}</code> where they previously took a <code>*rsa.PublicKey</code>
+or <code>*rsa.PrivateKey</code>. This will allow other public key algorithms
+to be implemented in the future.
+</p>
+
+<p>
+<em>Updating</em>:
+No changes will be needed.
+</p>
+
+<h3 id="flag">The flag package</h3>
+
+<p>
+In Go 1, the interface <a href="/pkg/flag/#Value"><code>flag.Value</code></a> has changed slightly.
+The <code>Set</code> method now returns an <code>error</code> instead of
+a <code>bool</code> to indicate success or failure.
+</p>
+
+<p>
+There is also a new kind of flag, <code>Duration</code>, to support argument
+values specifying time intervals.
+Values for such flags must be given units, just as <code>time.Duration</code>
+formats them: <code>10s</code>, <code>1h30m</code>, etc.
+</p>
+
+{{code "progs/go1.go" `/timeout/`}}
+
+<p>
+<em>Updating</em>:
+Programs that implement their own flags will need minor manual fixes to update their
+<code>Set</code> methods.
+The <code>Duration</code> flag is new and affects no existing code.
+</p>
+
+
+<h3 id="go">The go/* packages</h3>
+
+<p>
+Several packages under <code>go</code> have slightly revised APIs.
+</p>
+
+<p>
+The modes <code>AllowIllegalChars</code> and <code>InsertSemis</code> have been removed
+from the <a href="/pkg/go/scanner/"><code>go/scanner</code></a> package. They were mostly
+useful for scanning text other then Go source files. Instead, the
+<a href="/pkg/text/scanner/"><code>text/scanner</code></a> package should be used
+for that purpose.
+</p>
+
+<p>
+The set of parse functions provided by the <a href="/pkg/go/parser/"><code>go/parser</code></a>
+package has been reduced to the primary parse function
+<a href="/pkg/go/parser/#ParseFile"><code>ParseFile</code></a>, and a couple of
+convenience functions <a href="/pkg/go/parser/#ParseDir"><code>ParseDir</code></a>
+and <a href="/pkg/go/parser/#ParseExpr"><code>ParseExpr</code></a>.
+</p>
+
+<p>
+The type names of the <a href="/pkg/go/doc/"><code>go/doc</code></a> package have been
+streamlined by removing the <code>Doc</code> suffix: <code>PackageDoc</code>
+is now <code>Package</code>, <code>ValueDoc</code> is <code>Value</code>, etc.
+Also, all types now consistently have a <code>Name</code> field (or <code>Names</code>,
+in the case of type <code>Value</code>) and <code>Type.Factories</code> has become
+<code>Type.Funcs</code>.
+Instead of calling <code>doc.NewPackageDoc(pkg, importpath)</code>,
+documentation for a package is created with:
+</p>
+
+<pre>
+    doc.New(pkg, importpath, mode)
+</pre>
+
+<p>
+where the new <code>mode</code> parameter specifies the operation mode:
+if set to <a href="/pkg/go/doc/#AllDecls"><code>AllDecls</code></a>, all declarations
+(not just exported ones) are considered.
+The function <code>NewFileDoc</code> was removed, and the function
+<code>CommentText</code> has become the method
+<a href="/pkg/go/ast/#Text"><code>Text</code></a> of
+<a href="/pkg/go/ast/#CommentGroup"><code>ast.CommentGroup</code></a>.
+</p>
+
+<p>
+In package <a href="/pkg/go/token/"><code>go/token</code></a>, the
+<a href="/pkg/go/token/#FileSet"><code>token.FileSet</code></a> method <code>Files</code>
+(which originally returned a channel of <code>*token.File</code>s) has been replaced
+with the iterator <a href="/pkg/go/token/#FileSet.Iterate"><code>Iterate</code></a> that
+accepts a function argument instead.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses packages in <code>go</code> will have to be updated by hand; the
+compiler will reject incorrect uses. Templates used in conjuction with any of the
+<code>go/doc</code> types may need manual fixes; the renamed fields will lead
+to run-time errors.
+</p>
+
+<h3 id="hash">The hash package</h3>
+
+<p>
+In Go 1, the definition of <a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> includes
+a new method, <code>BlockSize</code>.  This new method is used primarily in the 
+cryptographic libraries.
+</p>
+
+<p>
+The <code>Sum</code> method of the
+<a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> interface now takes a
+<code>[]byte</code> argument, to which the hash value will be appended.
+The previous behavior can be recreated by adding a <code>nil</code> argument to the call.
+</p>
+
+<p>
+<em>Updating</em>:
+Existing implementations of <code>hash.Hash</code> will need to add a
+<code>BlockSize</code> method.  Hashes that process the input one byte at
+a time can implement <code>BlockSize</code> to return 1.
+Gofix will update calls to the <code>Sum</code> methods of the various
+implementations of <code>hash.Hash</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Since the package's functionality is new, no updating is necessary.
+</p>
+
+<h3 id="http">The http package</h3>
+
+<p>
+In Go 1 the <a href="/pkg/net/http/"><code>http</code></a> package is refactored,
+putting some of the utilities into a
+<a href="/pkg/net/httputil/"><code>httputil</code></a> subdirectory.
+These pieces are only rarely needed by HTTP clients.
+The affected items are:
+</p>
+
+<ul>
+<li>ClientConn</li>
+<li>DumpRequest</li>
+<li>DumpRequest</li>
+<li>DumpRequestOut</li>
+<li>DumpResponse</li>
+<li>NewChunkedReader</li>
+<li>NewChunkedWriter</li>
+<li>NewClientConn</li>
+<li>NewProxyClientConn</li>
+<li>NewServerConn</li>
+<li>NewSingleHostReverseProxy</li>
+<li>ReverseProxy</li>
+<li>ServerConn</li>
+</ul>
+
+<p>
+Also, the <code>Request.RawURL</code> field has been removed; it was a
+historical artifact.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update the few programs that are affected except for
+uses of <code>RawURL</code>, which must be fixed by hand.
+</p>
+
+<h3 id="image">The image package</h3>
+
+<p>
+The <a href="/pkg/image/"><code>image</code></a> package has had a number of
+minor changes, rearrangements and renamings.
+</p>
+
+<p>
+Most of the color handling code has been moved into its own package,
+<a href="/pkg/image/color/"><code>image/color</code></a>.
+For the elements that moved, a symmetry arises; for instance,
+each pixel of an
+<a href="/pkg/image/#RGBA"><code>image.RGBA</code></a>
+is a
+<a href="/pkg/image/color/#RGBA"><code>color.RGBA</code></a>.
+</p>
+
+<p>
+The old <code>image/ycbcr</code> package has been folded, with some
+renamings, into the
+<a href="/pkg/image/"><code>image</code></a>
+and
+<a href="/pkg/image/color/"><code>image/color</code></a>
+packages.
+</p>
+
+<p>
+The old <code>image.ColorImage</code> type is still in the <code>image</code>
+package but has been renamed
+<a href="/pkg/image/#Uniform"><code>image.Uniform</code></a>,
+while <code>image.Tiled</code>
+has been renamed
+<a href="/pkg/image/#Repeated"><code>image.Repeated</code></a>.
+</p>
+
+<p>
+This table lists the renamings.
+</p>
+
+<table class="codetable" frame="border" summary="image renames">
+<colgroup align="left" width="50%"></colgroup>
+<colgroup align="left" width="50%"></colgroup>
+<tr>
+<th align="left">Old</th>
+<th align="left">New</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.Color</td> <td>color.Color</td></tr>
+<tr><td>image.ColorModel</td> <td>color.Model</td></tr>
+<tr><td>image.ColorModelFunc</td> <td>color.ModelFunc</td></tr>
+<tr><td>image.PalettedColorModel</td> <td>color.Palette</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.RGBAColor</td> <td>color.RGBA</td></tr>
+<tr><td>image.RGBA64Color</td> <td>color.RGBA64</td></tr>
+<tr><td>image.NRGBAColor</td> <td>color.NRGBA</td></tr>
+<tr><td>image.NRGBA64Color</td> <td>color.NRGBA64</td></tr>
+<tr><td>image.AlphaColor</td> <td>color.Alpha</td></tr>
+<tr><td>image.Alpha16Color</td> <td>color.Alpha16</td></tr>
+<tr><td>image.GrayColor</td> <td>color.Gray</td></tr>
+<tr><td>image.Gray16Color</td> <td>color.Gray16</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.RGBAColorModel</td> <td>color.RGBAModel</td></tr>
+<tr><td>image.RGBA64ColorModel</td> <td>color.RGBA64Model</td></tr>
+<tr><td>image.NRGBAColorModel</td> <td>color.NRGBAModel</td></tr>
+<tr><td>image.NRGBA64ColorModel</td> <td>color.NRGBA64Model</td></tr>
+<tr><td>image.AlphaColorModel</td> <td>color.AlphaModel</td></tr>
+<tr><td>image.Alpha16ColorModel</td> <td>color.Alpha16Model</td></tr>
+<tr><td>image.GrayColorModel</td> <td>color.GrayModel</td></tr>
+<tr><td>image.Gray16ColorModel</td> <td>color.Gray16Model</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>ycbcr.RGBToYCbCr</td> <td>color.RGBToYCbCr</td></tr>
+<tr><td>ycbcr.YCbCrToRGB</td> <td>color.YCbCrToRGB</td></tr>
+<tr><td>ycbcr.YCbCrColorModel</td> <td>color.YCbCrModel</td></tr>
+<tr><td>ycbcr.YCbCrColor</td> <td>color.YCbCr</td></tr>
+<tr><td>ycbcr.YCbCr</td> <td>image.YCbCr</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>ycbcr.SubsampleRatio444</td> <td>image.YCbCrSubsampleRatio444</td></tr>
+<tr><td>ycbcr.SubsampleRatio422</td> <td>image.YCbCrSubsampleRatio422</td></tr>
+<tr><td>ycbcr.SubsampleRatio420</td> <td>image.YCbCrSubsampleRatio420</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>image.ColorImage</td> <td>image.Uniform</td></tr>
+<tr><td>image.Tiled</td> <td>image.Repeated</td></tr>
+</table>
+
+<p>
+The image package's <code>New</code> functions
+(<a href="/pkg/image/#NewRGBA"><code>NewRGBA</code></a>,
+<a href="/pkg/image/#NewRGBA64"><code>NewRGBA64</code></a>, etc.)
+take an <a href="/pkg/image/#Rectangle"><code>image.Rectangle</code></a> as an argument
+instead of four integers.
+</p>
+
+<p>
+Finally, there are new predefined <code>color.Color</code> variables
+<a href="/pkg/image/color/#Black"><code>color.Black</code></a>,
+<a href="/pkg/image/color/#White"><code>color.White</code></a>,
+<a href="/pkg/image/color/#Opaque"><code>color.Opaque</code></a>
+and
+<a href="/pkg/image/color/#Transparent"><code>color.Transparent</code></a>.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update almost all code affected by the change.
+</p>
+
+<h3 id="mime">The mime package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/mime/#FormatMediaType"><code>FormatMediaType</code></a> function
+of the <code>mime</code> package has  been simplified to make it
+consistent with
+<a href="/pkg/mime/#ParseMediaType"><code>ParseMediaType</code></a>. 
+It now takes <code>"text/html"</code> rather than <code>"text"</code> and <code>"html"</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+What little code is affected will be caught by the compiler and must be updated by hand.
+</p>
+
+<h3 id="net">The net package</h3>
+
+<p>
+In Go 1, the various <code>SetTimeout</code>,
+<code>SetReadTimeout</code>, and <code>SetWriteTimeout</code> methods
+have been replaced with 
+<a href="/pkg/net/#IPConn.SetDeadline"><code>SetDeadline</code></a>,
+<a href="/pkg/net/#IPConn.SetReadDeadline"><code>SetReadDeadline</code></a>, and 
+<a href="/pkg/net/#IPConn.SetWriteDeadline"><code>SetWriteDeadline</code></a>,
+respectively.  Rather than taking a timeout value in nanoseconds that
+apply to any activity on the connection, the new methods set an
+absolute deadline (as a <code>time.Time</code> value) after which
+reads and writes will time out and no longer block.
+</p>
+
+<p>
+There is also a new <a href="/pkg/net/#DialTimeout"><code>net.DialTimeout</code></a> method to simplify
+timing out dialing a network address.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the old methods will fail to compile and must be updated by hand.
+The semantic change makes it difficult for gofix to update automatically.
+</p>
+
+<h3 id="os_fileinfo">The os.FileInfo type</h3>
+
+<p>
+Go 1 redefines the <a href="/pkg/os/#FileInfo"><code>os.FileInfo</code></a> type,
+changing it from a struct to an interface:
+</p>
+
+<pre>
+    type FileInfo interface {
+        Name() string       // base name of the file
+        Size() int64        // length in bytes
+        Mode() FileMode     // file mode bits
+        ModTime() time.Time // modification time
+        IsDir() bool        // abbreviation for Mode().IsDir()
+    }
+</pre>
+
+<p>
+The file mode information has been moved into a subtype called
+<a href="/pkg/os/#FileMode"><code>os.FileMode</code></a>,
+a simple integer type with <code>IsDir</code>, <code>Perm</code>, and <code>String</code>
+methods.
+</p>
+
+<p>
+The system-specific details of file modes and properties such as (on Unix)
+i-number have been removed from <code>FileInfo</code> altogether.
+Instead, each operating system's <code>os</code> package provides an
+implementation of the <code>FileInfo</code> interface, <code>*os.FileStat</code>,
+which in turn contains a <code>Sys</code> field that stores the
+system-specific representation of file metadata.
+For instance, to discover the i-number of a file on a Unix system, unpack
+the <code>FileInfo</code> like this:
+</p>
+
+<pre>
+    fi, err := os.Stat("hello.go")
+    if err != nil {
+        log.Fatal(err)
+    }
+    // Make sure it's an implementation known to package os.
+    fileStat, ok := fi.(*os.FileStat)
+    if !ok {
+        log.Fatal("hello.go: not an os File")
+    }
+    // Now check that it's a Unix file.
+    unixStat, ok := fileStat.Sys.(*syscall.Stat_t)
+    if !ok {
+        log.Fatal("hello.go: not a Unix file")
+    }
+    fmt.Printf("file i-number: %d\n", unixStat.Ino)
+</pre>
+
+<p>
+Assuming (which is unwise) that <code>"hello.go"</code> is a Unix file,
+the i-number expression could be contracted to
+</p>
+
+<pre>
+    fi.(*os.FileStat).Sys.(*syscall.Stat_t).Ino
+</pre>
+
+<p>
+The vast majority of uses of <code>FileInfo</code> need only the methods
+of the standard interface.
+</p>
+	
+<p>
+<em>Updating</em>:
+Gofix will update code that uses the old equivalent of the current <code>os.FileInfo</code>
+and <code>os.FileMode</code> API.
+Code that needs system-specific file details will need to be updated by hand.
+</p>
+
+<h3 id="path_filepath">The path/filepath package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/path/filepath/#Walk"><code>Walk</code></a> function of the
+<code>path/filepath</code> package
+has been changed to take a function value of type
+<a href="/pkg/path/filepath/#WalkFunc"><code>WalkFunc</code></a>
+instead of a <code>Visitor</code> interface value.
+<code>WalkFunc</code> unifies the handling of both files and directories.
+</p>
+
+<pre>
+    type WalkFunc func(path string, info *os.FileInfo, err os.Error) os.Error
+</pre>
+
+<p>
+The <code>WalkFunc</code> function will be called even for files or directories that could not be opened;
+in such cases the error argument will describe the failure.
+If a directory's contents are to be skipped,
+the function should return the value <code>SkipDir</code>.
+</p>
+
+<p>
+<font color="red">TODO: add an example?</font>
+</p>
+
+<p>
+<em>Updating</em>:
+The change simplifies most code but has subtle consequences, so affected programs
+will need to be updated by hand.
+The compiler will catch code using the old interface.
+</p>
+
+<h3 id="runtime">The runtime package</h3>
+
+<p>
+The <code>runtime</code> package in Go 1 includes a new niladic function,
+<a href="/pkg/runtime/#NumCPU"><code>runtime.NumCPU</code></a>, that returns the number of CPUs available
+for parallel execution, as reported by the operating system kernel.
+Its value can inform the setting of <code>GOMAXPROCS</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+No existing code is affected.
+</p>
+
+<h3 id="strconv">The strconv package</h3>
+
+<p>
+In Go 1, the
+<a href="/pkg/strconv/"><code>strconv</code></a>
+package has been significantly reworked to make it more Go-like and less C-like,
+although <code>Atoi</code> lives on (it's similar to
+<code>int(ParseInt(x, 10, 0))</code>, as does
+<code>Itoa(x)</code> (<code>FormatInt(int64(x), 10)</code>).
+There are also new variants of some of the functions that append to byte slices rather than
+return strings, to allow control over allocation.
+</p>
+
+<p>
+This table summarizes the renamings; see the
+<a href="/pkg/strconv/">package documentation</a>
+for full details.
+</p>
+
+<table class="codetable" frame="border" summary="strconv renames">
+<colgroup align="left" width="50%"></colgroup>
+<colgroup align="left" width="50%"></colgroup>
+<tr>
+<th align="left">Old call</th>
+<th align="left">New call</th>
+</tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atob(x)</td> <td>ParseBool(x)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atof32(x)</td> <td>ParseFloat(x, 32)§</td></tr>
+<tr><td>Atof64(x)</td> <td>ParseFloat(x, 64)</td></tr>
+<tr><td>AtofN(x, n)</td> <td>ParseFloat(x, n)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atoi(x)</td> <td>Atoi(x)</td></tr>
+<tr><td>Atoi(x)</td> <td>ParseInt(x, 10, 0)§</td></tr>
+<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Atoui(x)</td> <td>ParseUint(x, 10, 0)§</td></tr>
+<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Btoi64(x, b)</td> <td>ParseInt(x, b, 64)</td></tr>
+<tr><td>Btoui64(x, b)</td> <td>ParseUint(x, b, 64)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Btoa(x)</td> <td>FormatBool(x)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Ftoa32(x, f, p)</td> <td>FormatFloat(x, float64(f), p, 32)</td></tr>
+<tr><td>Ftoa64(x, f, p)</td> <td>FormatFloat(x, f, p, 64)</td></tr>
+<tr><td>FtoaN(x, f, p, n)</td> <td>FormatFloat(x, f, p, n)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Itoa(x)</td> <td>Itoa(x)</td></tr>
+<tr><td>Itoa(x)</td> <td>FormatInt(int64(x), 10)</td></tr>
+<tr><td>Itoa64(x)</td> <td>FormatInt(x, 10)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Itob(x, b)</td> <td>FormatInt(int64(x), b)</td></tr>
+<tr><td>Itob64(x, b)</td> <td>FormatInt(x, b)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Uitoa(x)</td> <td>FormatUint(uint64(x), 10)</td></tr>
+<tr><td>Uitoa64(x)</td> <td>FormatUint(x, 10)</td></tr>
+<tr>
+<td colspan="2"><hr></td>
+</tr>
+<tr><td>Uitob(x, b)</td> <td>FormatUint(uint64(x), b)</td></tr>
+<tr><td>Uitob64(x, b)</td> <td>FormatUint(x, b)</td></tr>
+</table>
+		
+<p>
+<em>Updating</em>:
+Gofix will update almost all code affected by the change.
+<br>
+§ <code>Atoi</code> persists but <code>Atoui</code> and <code>Atof32</code> do not, so
+they may require
+a cast that must be added by hand; gofix will warn about it.
+</p>
+
+
+<h3 id="testing">The testing package</h3>
+
+<p>
+The testing package has a type, <code>B</code>, passed as an argument to benchmark functions.
+In Go 1, <code>B</code> has new methods, analogous to those of <code>T</code>, enabling
+logging and failure reporting.
+</p>
+
+{{code "progs/go1.go" `/func.*Benchmark/` `/^}/`}}
+
+<p>
+<em>Updating</em>:
+Existing code is unaffected, although benchmarks that use <code>println</code>
+or <code>panic</code> should be updated to use the new methods.
+</p>
+
+<h3 id="url">The url package</h3>
+
+<p>
+In Go 1 several fields from the <a href="/pkg/net/url/#URL"><code>url.URL</code></a> type
+were removed or replaced.
+</p>
+
+<p>
+The <a href="/pkg/net/url/#URL.String"><code>String</code></a> method now
+predictably rebuilds an encoded URL string using all of <code>URL</code>'s
+fields as necessary. The resulting string will also no longer have
+passwords escaped.
+</p>
+
+<p>
+The <code>Raw</code> field has been removed. In most cases the <code>String</code>
+method may be used in its place.
+</p>
+
+<p>
+The old <code>RawUserinfo</code> field is replaced by the <code>User</code>
+field, of type <a href="/pkg/net/url/#Userinfo"><code>*net.Userinfo</code></a>.
+Values of this type may be created using the new <a href="/pkg/net/url/#User"><code>net.User</code></a>
+and <a href="/pkg/net/url/#UserPassword"><code>net.UserPassword</code></a>
+functions. The <code>EscapeUserinfo</code> and <code>UnescapeUserinfo</code>
+functions are also gone.
+</p>
+
+<p>
+The <code>RawAuthority</code> field has been removed. The same information is
+available in the <code>Host</code> and <code>User</code> fields.
+</p>
+
+<p>
+The <code>RawPath</code> field and the <code>EncodedPath</code> method have
+been removed. The path information in rooted URLs (with a slash following the
+schema) is now available only in decoded form in the <code>Path</code> field.
+Occasionally, the encoded data may be required to obtain information that
+was lost in the decoding process. These cases must be handled by accessing
+the data the URL was built from.
+</p>
+
+<p>
+URLs with non-rooted paths, such as <code>"mailto:dev at golang.org?subject=Hi"</code>,
+are also handled differently. The <code>OpaquePath</code> boolean field has been
+removed and a new <code>Opaque</code> string field introduced to hold the encoded
+path for such URLs. In Go 1, the cited URL parses as:
+</p>
+
+<pre>
+    URL{
+        Scheme: "mailto",
+        Opaque: "dev at golang.org",
+        RawQuery: "subject=Hi",
+    }
+</pre>
+
+<p>
+A new <a href="/pkg/net/url/#URL.RequestURI"><code>RequestURI</code></a> method was
+added to <code>URL</code>.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that uses the old fields will fail to compile and must be updated by hand.
+The semantic changes make it difficult for gofix to update automatically.
+</p>
+
+<h3 id="xml">The xml package</h3>
+
+<p>
+In Go 1, the <a href="/pkg/encoding/xml/"><code>xml</code></a> package
+has been brought closer in design to the other marshaling packages such
+as <a href="/pkg/encoding/gob/"><code>encoding/gob</code></a>.
+</p>
+
+<p>
+The old <code>Parser</code> type is renamed
+<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> and has a new
+<a href="/pkg/encoding/xml/#Decoder.Decode"><code>Decode</code></a> method. An
+<a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a> type was also
+introduced.
+</p>
+
+<p>
+The functions <a href="/pkg/encoding/xml/#Marshal"><code>Marshal</code></a>
+and <a href="/pkg/encoding/xml/#Unmarshal"><code>Unmarshal</code></a>
+work with <code>[]byte</code> values now. To work with streams,
+use the new <a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a>
+and <a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> types.
+</p>
+
+<p>
+When marshaling or unmarshaling values, the format of supported flags in
+field tags has changed to be closer to the
+<a href="/pkg/encoding/json"><code>json</code></a> package
+(<code>`xml:"name,flag"`</code>). The matching done between field tags, field
+names, and the XML attribute and element names is now case-sensitive.
+The <code>XMLName</code> field tag, if present, must also match the name
+of the XML element being marshaled.
+</p>
+
+<p>
+<em>Updating</em>:
+Gofix will update most uses of the package except for some calls to
+<code>Unmarshal</code>. Special care must be taken with field tags,
+since gofix will not update them and if not fixed by hand they will
+misbehave silently in some cases. For example, the old
+<code>"attr"</code> is now written <code>",attr"</code> while plain
+<code>"attr"</code> remains valid but with a different meaning.
+</p>
+
+<h2 id="go_command">The go command</h2>
+
+<h2 id="releases">Packaged releases</h2>
+
diff --git a/doc/go_faq.html b/doc/go_faq.html
index aeed537..93e1ea4 100644
--- a/doc/go_faq.html
+++ b/doc/go_faq.html
@@ -1,4 +1,6 @@
-<!-- FAQ -->
+<!--{
+	"Title": "FAQ"
+}-->
 
 <h2 id="Origins">Origins</h2>
 
@@ -188,10 +190,11 @@ easier to understand what happens when things combine.
 
 <p>
 Yes. There are now several Go programs deployed in 
-production inside Google.  For instance, the server behind
-<a href="http://golang.org">http://golang.org</a> is a Go program; 
-in fact it's just the <a href="/cmd/godoc"><code>godoc</code></a>
-document server running in a production configuration.
+production inside Google.  A public example is the server behind
+<a href="http://golang.org">http://golang.org</a>.
+It's just the <a href="/cmd/godoc"><code>godoc</code></a>
+document server running in a production configuration on
+<a href="http://code.google.com/appengine/">Google App Engine</a>.
 </p>
 
 <h3 id="Do_Go_programs_link_with_Cpp_programs">
@@ -351,26 +354,6 @@ not familiar with the code.
 </p>
 
 <p>
-The same arguments apply to the use of <code>assert()</code> in test programs. Proper
-error handling means letting other tests run after one has failed, so
-that the person debugging the failure gets a complete picture of what is
-wrong. It is more useful for a test to report that
-<code>isPrime</code> gives the wrong answer for 2, 3, 5, and 7 (or for
-2, 4, 8, and 16) than to report that <code>isPrime</code> gives the wrong
-answer for 2 and therefore no more tests were run. The programmer who
-triggers the test failure may not be familiar with the code that fails.
-Time invested writing a good error message now pays off later when the
-test breaks.
-</p>
-
-<p>
-In testing, if the amount of extra code required to write
-good errors seems repetitive and overwhelming, it might work better as a
-table-driven test instead.
-Go has excellent support for data structure literals.
-</p>
-
-<p>
 We understand that this is a point of contention. There are many things in
 the Go language and libraries that differ from modern practices, simply
 because we feel it's sometimes worth trying a different approach.
@@ -380,7 +363,7 @@ because we feel it's sometimes worth trying a different approach.
 Why build concurrency on the ideas of CSP?</h3>
 <p>
 Concurrency and multi-threaded programming have a reputation
-for difficulty.  We believe the problem is due partly to complex
+for difficulty.  We believe this is due partly to complex
 designs such as pthreads and partly to overemphasis on low-level details
 such as mutexes, condition variables, and memory barriers.
 Higher-level interfaces enable much simpler code, even if there are still
@@ -451,7 +434,9 @@ we believe is easy to use and in some ways more general. There are
 also ways to embed types in other types to provide something
 analogous—but not identical—to subclassing.
 Moreover, methods in Go are more general than in C++ or Java:
-they can be defined for any sort of data, not just structs.
+they can be defined for any sort of data, even built-in types such
+as plain, “unboxed” integers.
+They are not restricted to structs (classes).
 </p>
 
 <p>
@@ -464,7 +449,7 @@ How do I get dynamic dispatch of methods?</h3>
 
 <p>
 The only way to have dynamically dispatched methods is through an
-interface. Methods on structs or other types are always resolved statically.
+interface. Methods on a struct or any other concrete type are always resolved statically.
 </p>
 
 <h3 id="inheritance">
@@ -496,8 +481,8 @@ It's possible to use these ideas to construct something analogous to
 type-safe Unix pipes.  For instance, see how <code>fmt.Fprintf</code>
 enables formatted printing to any output, not just a file, or how the
 <code>bufio</code> package can be completely separate from file I/O,
-or how the <code>crypto</code> packages stitch together block and
-stream ciphers.  All these ideas stem from a single interface
+or how the <code>image</code> packages generate compressed
+image files.  All these ideas stem from a single interface
 (<code>io.Writer</code>) representing a single method
 (<code>Write</code>).  And that's only scratching the surface.
 </p>
@@ -559,7 +544,7 @@ interface <code>I</code> by attempting an assignment:
 
 <pre>
 type T struct{}
-var _ I = T{}
+var _ I = T{}   // Verify that T implements I.
 </pre>
 
 <p>
@@ -575,8 +560,8 @@ For example:
 
 <pre>
 type Fooer interface {
-	Foo()
-	ImplementsFooer()
+    Foo()
+    ImplementsFooer()
 }
 </pre>
 
@@ -608,7 +593,7 @@ itself with another value:
 
 <pre>
 type Equaler interface {
-	Equal(Equaler) bool
+    Equal(Equaler) bool
 }
 </pre>
 
@@ -681,7 +666,7 @@ examples and also have them be statically checked.
 Can I convert a []T to an []interface{}?</h3>
 
 <p>
-Not directly because they do not have the same representation in memory.
+Not directly, because they do not have the same representation in memory.
 It is necessary to copy the elements individually to the destination
 slice. This example converts a slice of <code>int</code> to a slice of
 <code>interface{}</code>:
@@ -691,7 +676,7 @@ slice. This example converts a slice of <code>int</code> to a slice of
 t := []int{1, 2, 3, 4}
 s := make([]interface{}, len(t))
 for i, v := range t {
-	s[i] = v
+    s[i] = v
 }
 </pre>
 
@@ -768,17 +753,22 @@ to write one but it will not be as convenient syntactically; this seems a reason
 </p>
 
 <h3 id="map_keys">
-Why don't maps allow structs and arrays as keys?</h3>
+Why don't maps allow slices as keys?</h3>
 <p>
-Map lookup requires an equality operator, which structs and arrays do not implement.
+Map lookup requires an equality operator, which slices do not implement.
 They don't implement equality because equality is not well defined on such types;
 there are multiple considerations involving shallow vs. deep comparison, pointer vs.
-value comparison, how to deal with recursive structures, and so on.
-We may revisit this issue—and implementing equality for structs and arrays
+value comparison, how to deal with recursive types, and so on.
+We may revisit this issue—and implementing equality for slices
 will not invalidate any existing programs—but without a clear idea of what
 equality of structs and arrays should mean, it was simpler to leave it out for now.
 </p>
 
+<p>
+In Go 1, equality is defined for structs and arrays, so such
+types can be used as map keys, but slices still do not have a definition of equality.
+</p>
+
 <h3 id="references">
 Why are maps, slices, and channels references while arrays are values?</h3>
 <p>
@@ -841,14 +831,17 @@ for more information about how to proceed.
 When are function parameters passed by value?</h3>
 
 <p>
-Everything in Go is passed by value.  A function always gets a copy of the
+As in all languages in the C family, everything in Go is passed by value.
+That is, a function always gets a copy of the
 thing being passed, as if there were an assignment statement assigning the
-value to the parameter.  For instance, copying a pointer value makes a copy of
-the pointer, not the data it points to. 
+value to the parameter.  For instance, passing an <code>int</code> value
+to a function makes a copy of the <code>int</code>, and passing a pointer
+value makes a copy of the pointer, but not the data it points to.
+(See the next section for a discussion of how this affects method receivers.)
 </p>
 
 <p>
-Map and slice values behave like pointers; they are descriptors that
+Map and slice values behave like pointers: they are descriptors that
 contain pointers to the underlying map or slice data.  Copying a map or
 slice value doesn't copy the data it points to.  Copying an interface value
 makes a copy of the thing stored in the interface value.  If the interface
@@ -946,6 +939,12 @@ floating-point numbers.
 The default size of a floating-point constant is <code>float64</code>.
 </p>
 
+<p>
+At the moment, all implementations use 32-bit ints, an essentially arbitrary decision.
+However, we expect that <code>int</code> will be increased to 64 bits on 64-bit
+architectures in a future release of Go.
+</p>
+
 <h3 id="stack_or_heap">
 How do I know whether a variable is allocated on the heap or the stack?</h3>
 
@@ -963,12 +962,15 @@ local to a function in that function's stack frame.  However, if the
 compiler cannot prove that the variable is not referenced after the
 function returns, then the compiler must allocate the variable on the
 garbage-collected heap to avoid dangling pointer errors.
+Also, if a local variable is very large, it might make more sense
+to store it on the heap rather than the stack.
 </p>
 
 <p>
-In the current compilers, the analysis is crude: if a variable has its address
-taken, that variable is allocated on the heap. We are working to improve this
-analysis so that more data is kept on the stack. 
+In the current compilers, if a variable has its address taken, that variable
+is a candidate for allocation on the heap. However, a basic <em>escape
+analysis</em> recognizes some cases when such variables will not
+live past the return from the function and can reside on the stack.
 </p>
 
 <h2 id="Concurrency">Concurrency</h2>
@@ -1001,14 +1003,12 @@ See the <a href="/doc/codewalk/sharemem/">Share Memory By Communicating</a> code
 Why doesn't my multi-goroutine program use multiple CPUs?</h3>
 
 <p>
-Under the gc compilers you must set <code>GOMAXPROCS</code> to allow the
-run-time support to utilise more than one OS thread. Under <code>gccgo</code> an OS
-thread will be created for each goroutine, and <code>GOMAXPROCS</code> is
-effectively equal to the number of running goroutines.  
+You must set <code>GOMAXPROCS</code> to allow the
+run-time support to utilize more than one OS thread. 
 </p>
 
 <p>
-Programs that perform concurrent computation should benefit from an increase in
+Programs that perform parallel computation should benefit from an increase in
 <code>GOMAXPROCS</code>. (See the <a
 href="http://golang.org/pkg/runtime/#GOMAXPROCS"><code>runtime</code> package's
 documentation</a>.)
@@ -1019,15 +1019,24 @@ Why does using <code>GOMAXPROCS</code> > 1 sometimes make my program
 slower?</h3>
 
 <p>
-(This is specific to the gc compilers. See above.)
+It depends on the nature of your program. 
+Problems that are intrinsically sequential cannot be sped up by adding
+more goroutines.
+Concurrency only becomes parallelism when the problem is
+intrinsically parallel.
 </p>
 
 <p>
-It depends on the nature of your program. 
-Programs that contain several goroutines that spend a lot of time
-communicating on channels will experience performance degradation when using
-multiple OS threads. This is because of the significant context-switching
-penalty involved in sending data between threads.
+In practical terms, programs that spend more time
+communicating on channels than doing computation
+will experience performance degradation when using
+multiple OS threads.
+This is because sending data between threads involves switching
+contexts, which has significant cost.
+For instance, the <a href="/doc/go_spec.html#An_example_package">prime sieve example</a>
+from the Go specification has no significant parallelism although it launches many
+goroutines; increasing <code>GOMAXPROCS</code> is more likely to slow it down than
+to speed it up.
 </p>
 
 <p>
@@ -1075,7 +1084,7 @@ This is almost never the desired behavior.
 </p>
 
 <h3 id="closures_and_goroutines">
-Why am I confused by the way my closures behave as goroutines?</h3>
+What happens with closures running as goroutines?</h3>
 
 <p>
 Some confusion may arise when using closures with concurrency.
@@ -1084,29 +1093,30 @@ Consider the following program:
 
 <pre>
 func main() {
-	done := make(chan bool)
-
-	values := []string{ "a", "b", "c" }
-	for _, v := range values {
-		go func() {
-			fmt.Println(v)
-			done <- true
-		}()
-	}
-
-	// wait for all goroutines to complete before exiting
-	for _ = range values {
-		<-done 
-	}
+    done := make(chan bool)
+
+    values := []string{ "a", "b", "c" }
+    for _, v := range values {
+        go func() {
+            fmt.Println(v)
+            done <- true
+        }()
+    }
+
+    // wait for all goroutines to complete before exiting
+    for _ = range values {
+        <-done 
+    }
 }
 </pre>
 
 <p>
 One might mistakenly expect to see <code>a, b, c</code> as the output. 
 What you'll probably see instead is <code>c, c, c</code>.  This is because 
-each closure shares the same variable <code>v</code>. Each closure prints the 
-value of <code>v</code> at the time <code>fmt.Println</code> is executed, 
-rather than the value of <code>v</code> when the goroutine was launched. 
+each iteration of the loop uses the same instance of the variable <code>v</code>, so
+each closure shares that single variable. When the closure runs, it prints the 
+value of <code>v</code> at the time <code>fmt.Println</code> is executed,
+but <code>v</code> may have been modified since the goroutine was launched. 
 </p>
 
 <p>
@@ -1115,12 +1125,12 @@ could modify the inner loop to read:
 </p>
 
 <pre>
-	for _, v := range values {
-		go func(<b>u</b> string) {
-			fmt.Println(<b>u</b>)
-			done <- true
-		}(<b>v</b>)
-	}
+    for _, v := range values {
+        go func(<b>u</b> string) {
+            fmt.Println(<b>u</b>)
+            done <- true
+        }(<b>v</b>)
+    }
 </pre>
 
 <p>
@@ -1141,9 +1151,9 @@ result:
 
 <pre>
 if expr {
-	n = trueVal
+    n = trueVal
 } else {
-	n = falseVal
+    n = falseVal
 }
 </pre>
 
@@ -1186,6 +1196,45 @@ builds a test binary, and runs it.
 
 <p>See the <a href="/doc/code.html">How to Write Go Code</a> document for more details.</p>
 
+<h3 id="testing_framework">
+Where is my favorite helper function for testing?</h3>
+
+<p>
+Go's standard <code>testing</code> package makes it easy to write unit tests, but it lacks
+features provided in other language's testing frameworks such as assertion functions.
+An <a href="#assertions">earlier section</a> of this document explained why Go
+doesn't have assertions, and
+the same arguments apply to the use of <code>assert</code> in tests.
+Proper error handling means letting other tests run after one has failed, so
+that the person debugging the failure gets a complete picture of what is
+wrong. It is more useful for a test to report that
+<code>isPrime</code> gives the wrong answer for 2, 3, 5, and 7 (or for
+2, 4, 8, and 16) than to report that <code>isPrime</code> gives the wrong
+answer for 2 and therefore no more tests were run. The programmer who
+triggers the test failure may not be familiar with the code that fails.
+Time invested writing a good error message now pays off later when the
+test breaks.
+</p>
+
+<p>
+A related point is that testing frameworks tend to develop into mini-languages
+of their own, with conditionals and controls and printing mechanisms,
+but Go already has all those capabilities; why recreate them?
+We'd rather write tests in Go; it's one fewer language to learn and the
+approach keeps the tests straightforward and easy to understand.
+</p>
+
+<p>
+If the amount of extra code required to write
+good errors seems repetitive and overwhelming, the test might work better if
+table-driven, iterating over a list of inputs and outputs defined
+in a data structure (Go has excellent support for data structure literals).
+The work to write a good test and good error messages will then be amortized over many
+test cases. The standard Go library is full of illustrative examples, such as in
+<a href="http://golang.org/src/pkg/fmt/fmt_test.go">the formatting
+tests for the <code>fmt</code> package</a>.
+</p>
+
 
 <h2 id="Implementation">Implementation</h2>
 
@@ -1227,16 +1276,16 @@ it now. <code>Gccgo</code>'s run-time support uses <code>glibc</code>.
 control; it is
 compiled with a version of the Plan 9 C compiler that supports
 segmented stacks for goroutines.
-Work is underway to provide the same stack management in
-<code>gccgo</code>.
+The <code>gccgo</code> compiler also implements segmented
+stacks, supported by recent modifications to its linker.
 </p>
 
 <h3 id="Why_is_my_trivial_program_such_a_large_binary">
 Why is my trivial program such a large binary?</h3>
 
 <p>
-The gc tool chain (<code>5l</code>, <code>6l</code>, and <code>8l</code>) only
-generate statically linked binaries.  All Go binaries therefore include the Go
+The linkers in the gc tool chain (<code>5l</code>, <code>6l</code>, and <code>8l</code>)
+do static linking.  All Go binaries therefore include the Go
 run-time, along with the run-time type information necessary to support dynamic
 type checks, reflection, and even panic-time stack traces.
 </p>
@@ -1296,9 +1345,9 @@ import "unused"
 var _ = unused.Item  // TODO: Delete before committing!
 
 func main() {
-	debugData := debug.Profile()
-	_ = debugData // Used only during debugging.
-	....
+    debugData := debug.Profile()
+    _ = debugData // Used only during debugging.
+    ....
 }
 </pre>
 
@@ -1312,18 +1361,21 @@ One of Go's design goals is to approach the performance of C for comparable
 programs, yet on some benchmarks it does quite poorly, including several 
 in <a href="/test/bench/">test/bench</a>. The slowest depend on libraries 
 for which versions of comparable performance are not available in Go. 
-For instance, pidigits depends on a multi-precision math package, and the C
+For instance, <a href="/test/bench/shootout/pidigits.go">pidigits.go</a>
+depends on a multi-precision math package, and the C
 versions, unlike Go's, use <a href="http://gmplib.org/">GMP</a> (which is
 written in optimized assembler). 
-Benchmarks that depend on regular expressions (regex-dna, for instance) are
-essentially comparing Go's stopgap <a href="/pkg/regexp">regexp package</a> to
+Benchmarks that depend on regular expressions
+(<a href="/test/bench/shootout/regex-dna.go">regex-dna.go</a>, for instance) are
+essentially comparing Go's native <a href="/pkg/regexp">regexp package</a> to
 mature, highly optimized regular expression libraries like PCRE.
 </p>
 
 <p>
 Benchmark games are won by extensive tuning and the Go versions of most
 of the benchmarks need attention.  If you measure comparable C
-and Go programs (reverse-complement is one example), you'll see the two
+and Go programs
+(<a href="/test/bench/shootout/reverse-complement.go">reverse-complement.go</a> is one example), you'll see the two
 languages are much closer in raw performance than this suite would
 indicate.
 </p>
@@ -1331,8 +1383,8 @@ indicate.
 <p>
 Still, there is room for improvement. The compilers are good but could be
 better, many libraries need major performance work, and the garbage collector
-isn't fast enough yet (even if it were, taking care not to generate unnecessary 
-garbage can have a huge effect).
+isn't fast enough yet. (Even if it were, taking care not to generate unnecessary 
+garbage can have a huge effect.)
 </p>
 
 <p>
@@ -1367,13 +1419,13 @@ prefix <code>*</code> for pointers is an exception that proves the rule).  In C,
 the declaration
 </p>
 <pre>
-	int* a, b;
+    int* a, b;
 </pre>
 <p>
 declares <code>a</code> to be a pointer but not <code>b</code>; in Go
 </p>
 <pre>
-	var a, b *int;
+    var a, b *int
 </pre>
 <p>
 declares both to be pointers.  This is clearer and more regular.
@@ -1381,11 +1433,11 @@ Also, the <code>:=</code> short declaration form argues that a full variable
 declaration should present the same order as <code>:=</code> so
 </p>
 <pre>
-	var a uint64 = 1;
+    var a uint64 = 1
 </pre>
 has the same effect as
 <pre>
-	a := uint64(1);
+    a := uint64(1)
 </pre>
 <p>
 Parsing is also simplified by having a distinct grammar for types that
@@ -1464,8 +1516,7 @@ memory management.  We feel it's critical to eliminate that
 programmer overhead, and advances in garbage collection
 technology in the last few years give us confidence that we can
 implement it with low enough overhead and no significant
-latency.  (The current implementation is a plain mark-and-sweep
-collector but a replacement is in the works.)
+latency.
 </p>
 
 <p>
@@ -1485,6 +1536,11 @@ simpler because they don't need to specify how memory is managed across them.
 </p>
 
 <p>
+The current implementation is a parallel mark-and-sweep
+collector but a future version might take a different approach.
+</p>
+
+<p>
 On the topic of performance, keep in mind that Go gives the programmer
 considerable control over memory layout and allocation, much more than
 is typical in garbage-collected languages. A careful programmer can reduce
diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html
index 7168f1d..8e21519 100644
--- a/doc/go_for_cpp_programmers.html
+++ b/doc/go_for_cpp_programmers.html
@@ -1,4 +1,6 @@
-<!-- Go For C++ Programmers -->
+<!--{
+	"Title": "Go For C++ Programmers"
+}-->
 
 <p>
 Go is a systems programming language intended to be a general-purpose
@@ -223,7 +225,7 @@ f(v9.i, p9.i)
 </pre>
 
 <p>
-Go does not require parentheses around the condition of a <code>if</code>
+Go does not require parentheses around the condition of an <code>if</code>
 statement, or the expressions of a <code>for</code> statement, or the value of a
 <code>switch</code> statement.  On the other hand, it does require curly braces
 around the body of an <code>if</code> or <code>for</code> statement.
@@ -536,7 +538,7 @@ func f2() {
 
 <p>
 The <code>set</code> method is effectively inherited from
-<code>myChildType</code>, because
+<code>myType</code>, because
 methods associated with the anonymous field are promoted to become methods
 of the enclosing type.  In this case, because <code>myChildType</code> has an
 anonymous field of type <code>myType</code>, the methods of
diff --git a/doc/go_mem.html b/doc/go_mem.html
index a388283..2e34177 100644
--- a/doc/go_mem.html
+++ b/doc/go_mem.html
@@ -1,5 +1,7 @@
-<!-- The Go Memory Model -->
-<!-- subtitle Version of June 10, 2011 -->
+<!--{
+	"Title": "The Go Memory Model",
+	"Subtitle": "Version of June 10, 2011"
+}-->
 
 <style>
 p.rule {
@@ -54,7 +56,7 @@ if both of the following hold:
 </p>
 
 <ol>
-<li><span class="event">w</span> happens before <span class="event">r</span>.</li>
+<li><span class="event">r</span> does not happen before <span class="event">w</span>.</li>
 <li>There is no other write <span class="event">w'</span> to <code>v</code> that happens
     after <span class="event">w</span> but before <span class="event">r</span>.</li>
 </ol>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index f46e2f8..d7b0d76 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,5 +1,7 @@
-<!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of August 31, 2011 -->
+<!--{
+	"Title": "The Go Programming Language Specification",
+	"Subtitle": "Version of January 21, 2012"
+}-->
 
 <!--
 TODO
@@ -13,7 +15,6 @@ TODO
 [ ] should probably write something about evaluation order of statements even
 	though obvious
 [ ] review language on implicit dereferencing
-[ ] clarify what it means for two functions to be "the same" when comparing them
 -->
 
 
@@ -146,7 +147,7 @@ and stop at the end of the line. A line comment acts like a newline.
 <li>
 <i>General comments</i> start with the character sequence <code>/*</code>
 and continue through the character sequence <code>*/</code>. A general
-comment that spans multiple lines acts like a newline, otherwise it acts
+comment containing one or more newlines acts like a newline, otherwise it acts
 like a space.
 </li>
 </ol>
@@ -191,7 +192,7 @@ token is
 	<li>an
 	    <a href="#Identifiers">identifier</a>
 	</li>
-	
+
 	<li>an
 	    <a href="#Integer_literals">integer</a>,
 	    <a href="#Floating-point_literals">floating-point</a>,
@@ -199,14 +200,14 @@ token is
 	    <a href="#Character_literals">character</a>, or
 	    <a href="#String_literals">string</a> literal
 	</li>
-	
+
 	<li>one of the <a href="#Keywords">keywords</a>
 	    <code>break</code>,
 	    <code>continue</code>,
 	    <code>fallthrough</code>, or
 	    <code>return</code>
 	</li>
-	
+
 	<li>one of the <a href="#Operators_and_Delimiters">operators and delimiters</a>
 	    <code>++</code>,
 	    <code>--</code>,
@@ -361,7 +362,7 @@ imaginary_lit = (decimals | float_lit) "i" .
 <h3 id="Character_literals">Character literals</h3>
 
 <p>
-A character literal represents an <a href="#Constants">integer constant</a>,
+A character literal represents a <a href="#Constants">character constant</a>,
 typically a Unicode code point, as one or more characters enclosed in single
 quotes.  Within the quotes, any character may appear except single
 quote and newline. A single quoted character represents itself,
@@ -453,12 +454,14 @@ Raw string literals are character sequences between back quotes
 back quote. The value of a raw string literal is the
 string composed of the uninterpreted characters between the quotes;
 in particular, backslashes have no special meaning and the string may
-span multiple lines.
+contain newlines.
+Carriage returns inside raw string literals
+are discarded from the raw string value.
 </p>
 <p>
 Interpreted string literals are character sequences between double
 quotes <code>""</code>. The text between the quotes,
-which may not span multiple lines, forms the
+which may not contain newlines, forms the
 value of the literal, with backslash escapes interpreted as they
 are in character literals (except that <code>\'</code> is illegal and
 <code>\"</code> is legal).  The three-digit octal (<code>\</code><i>nnn</i>)
@@ -513,19 +516,22 @@ literal.
 
 <h2 id="Constants">Constants</h2>
 
-<p>There are <i>boolean constants</i>, <i>integer constants</i>,
+<p>There are <i>boolean constants</i>,
+<i>character constants</i>,
+<i>integer constants</i>,
 <i>floating-point constants</i>, <i>complex constants</i>,
-and <i>string constants</i>. Integer, floating-point,
+and <i>string constants</i>. Character, integer, floating-point,
 and complex constants are
 collectively called <i>numeric constants</i>.
 </p>
 
 <p>
-A constant value is represented by an
+A constant value is represented by a
+<a href="#Character_literals">character</a>,
 <a href="#Integer_literals">integer</a>,
 <a href="#Floating-point_literals">floating-point</a>,
 <a href="#Imaginary_literals">imaginary</a>,
-<a href="#Character_literals">character</a>, or
+or
 <a href="#String_literals">string</a> literal,
 an identifier denoting a constant,
 a <a href="#Constant_expressions">constant expression</a>,
@@ -691,7 +697,8 @@ float64     the set of all IEEE-754 64-bit floating-point numbers
 complex64   the set of all complex numbers with float32 real and imaginary parts
 complex128  the set of all complex numbers with float64 real and imaginary parts
 
-byte        familiar alias for uint8
+byte        alias for uint8
+rune        alias for int32
 </pre>
 
 <p>
@@ -711,7 +718,8 @@ uintptr  an unsigned integer large enough to store the uninterpreted bits of a p
 
 <p>
 To avoid portability issues all numeric types are distinct except
-<code>byte</code>, which is an alias for <code>uint8</code>.
+<code>byte</code>, which is an alias for <code>uint8</code>, and
+<code>rune</code>, which is an alias for <code>int32</code>.
 Conversions
 are required when different numeric types are mixed in an expression
 or assignment. For instance, <code>int32</code> and <code>int</code>
@@ -760,7 +768,7 @@ The length is part of the array's type and must be a
 integer value.  The length of array <code>a</code> can be discovered
 using the built-in function <a href="#Length_and_capacity"><code>len(a)</code></a>.
 The elements can be indexed by integer
-indices 0 through the <code>len(a)-1</code> (§<a href="#Indexes">Indexes</a>).
+indices 0 through <code>len(a)-1</code> (§<a href="#Indexes">Indexes</a>).
 Array types are always one-dimensional but may be composed to form
 multi-dimensional types.
 </p>
@@ -909,9 +917,9 @@ in a struct type:
 
 <pre>
 struct {
-	T         // conflicts with anonymous field *T and *P.T
-	*T        // conflicts with anonymous field T and *P.T
-	*P.T      // conflicts with anonymous field T and *T
+	T     // conflicts with anonymous field *T and *P.T
+	*T    // conflicts with anonymous field T and *P.T
+	*P.T  // conflicts with anonymous field T and *T
 }
 </pre>
 
@@ -971,7 +979,7 @@ BaseType = Type .
 
 <pre>
 *int
-*map[string] *chan int
+*map[string]*chan int
 </pre>
 
 <h3 id="Function_types">Function types</h3>
@@ -1150,18 +1158,19 @@ failure will cause a <a href="#Run_time_panics">run-time panic</a>.
 </p>
 
 <pre>
-map [string] int
-map [*T] struct { x, y float64 }
-map [string] interface {}
+map[string]int
+map[*T]struct{ x, y float64 }
+map[string]interface{}
 </pre>
 
 <p>
 The number of map elements is called its length.
 For a map <code>m</code>, it can be discovered using the
 built-in function <a href="#Length_and_capacity"><code>len(m)</code></a>
-and may change during execution. Elements may be added and removed
-during execution using special forms of <a href="#Assignments">assignment</a>;
-and they may be accessed with <a href="#Indexes">index</a> expressions.
+and may change during execution. Elements may be added during execution
+using <a href="#Assignments">assignments</a> and retrieved with
+<a href="#Indexes">index</a> expressions; they may be removed with the
+<a href="#Deletion_of_map_elements"><code>delete</code></a> built-in function.
 </p>
 <p>
 A new, empty map value is made using the built-in
@@ -1170,8 +1179,8 @@ which takes the map type and an optional capacity hint as arguments:
 </p>
 
 <pre>
-make(map[string] int)
-make(map[string] int, 100)
+make(map[string]int)
+make(map[string]int, 100)
 </pre>
 
 <p>
@@ -1203,9 +1212,9 @@ A channel may be constrained only to send or only to receive by
 </p>
 
 <pre>
-chan T         // can be used to send and receive values of type T
-chan<- float64 // can only be used to send float64s
-<-chan int     // can only be used to receive ints
+chan T          // can be used to send and receive values of type T
+chan<- float64  // can only be used to send float64s
+<-chan int      // can only be used to receive ints
 </pre>
 
 <p>
@@ -1214,9 +1223,9 @@ possible:
 </p>
 
 <pre>
-chan<- chan int     // same as chan<- (chan int)
-chan<- <-chan int   // same as chan<- (<-chan int)
-<-chan <-chan int   // same as <-chan (<-chan int)
+chan<- chan int    // same as chan<- (chan int)
+chan<- <-chan int  // same as chan<- (<-chan int)
+<-chan <-chan int  // same as <-chan (<-chan int)
 chan (<-chan int)
 </pre>
 
@@ -1233,7 +1242,7 @@ make(chan int, 100)
 
 <p>
 The capacity, in number of elements, sets the size of the buffer in the channel. If the
-capacity is greater than zero, the channel is asynchronous: communication operations 
+capacity is greater than zero, the channel is asynchronous: communication operations
 succeed without blocking if the buffer is not full (sends) or not empty (receives),
 and elements are received in the order they are sent.
 If the capacity is zero or absent, the communication succeeds only when both a sender and
@@ -1302,8 +1311,8 @@ Given the declarations
 type (
 	T0 []string
 	T1 []string
-	T2 struct { a, b int }
-	T3 struct { a, c int }
+	T2 struct{ a, b int }
+	T3 struct{ a, c int }
 	T4 func(int, float64) *T0
 	T5 func(x int, y float64) *[]string
 )
@@ -1316,7 +1325,7 @@ these types are identical:
 <pre>
 T0 and T0
 []int and []int
-struct { a, b *T5 } and struct { a, b *T5 }
+struct{ a, b *T5 } and struct{ a, b *T5 }
 func(x int, y float64) *[]string and func(int, float64) (result *[]string)
 </pre>
 
@@ -1364,15 +1373,6 @@ by a value of type <code>T</code>.
 </ul>
 
 <p>
-If <code>T</code> is a struct type with non-<a href="#Exported_identifiers">exported</a>
-fields, the assignment must be in the same package in which <code>T</code> is declared,
-or <code>x</code> must be the receiver of a method call.
-In other words, a struct value can be assigned to a struct variable only if
-every field of the struct may be legally assigned individually by the program,
-or if the assignment is initializing the receiver of a method of the struct type.
-</p>
-
-<p>
 Any value may be assigned to the <a href="#Blank_identifier">blank identifier</a>.
 </p>
 
@@ -1494,12 +1494,10 @@ the body of any nested function.
 The following identifiers are implicitly declared in the universe block:
 </p>
 <pre class="grammar">
-Basic types:
-	bool byte complex64 complex128 float32 float64
-	int8 int16 int32 int64 string uint8 uint16 uint32 uint64
-
-Architecture-specific convenience types:
-	int uint uintptr
+Types:
+	bool byte complex64 complex128 error float32 float64
+	int int8 int16 int32 int64 rune string
+	uint uint8 uint16 uint32 uint64 uintptr
 
 Constants:
 	true false iota
@@ -1508,7 +1506,7 @@ Zero value:
 	nil
 
 Functions:
-	append cap close complex copy imag len
+	append cap close complex copy delete imag len
 	make new panic print println real recover
 </pre>
 
@@ -1571,10 +1569,10 @@ constant, even if the literal's fractional part is zero.
 
 <pre>
 const Pi float64 = 3.14159265358979323846
-const zero = 0.0             // untyped floating-point constant
+const zero = 0.0         // untyped floating-point constant
 const (
 	size int64 = 1024
-	eof = -1             // untyped integer constant
+	eof        = -1  // untyped integer constant
 )
 const a, b, c = 3, 4, "foo"  // a = 3, b = 4, c = "foo", untyped integer and string constants
 const u, v float32 = 0, 3    // u = 0.0, v = 3.0
@@ -1646,10 +1644,10 @@ it is only incremented after each ConstSpec:
 
 <pre>
 const (
-	bit0, mask0 = 1 << iota, 1 << iota - 1  // bit0 == 1, mask0 == 0
-	bit1, mask1                             // bit1 == 2, mask1 == 1
-	_, _                                    // skips iota == 2
-	bit3, mask3                             // bit3 == 8, mask3 == 7
+	bit0, mask0 = 1 << iota, 1<<iota - 1  // bit0 == 1, mask0 == 0
+	bit1, mask1                           // bit1 == 2, mask1 == 1
+	_, _                                  // skips iota == 2
+	bit3, mask3                           // bit3 == 8, mask3 == 7
 )
 </pre>
 
@@ -1677,7 +1675,7 @@ TypeSpec     = identifier Type .
 type IntArray [16]int
 
 type (
-	Point struct { x, y float64 }
+	Point struct{ x, y float64 }
 	Polar Point
 )
 
@@ -1686,7 +1684,7 @@ type TreeNode struct {
 	value *Comparable
 }
 
-type Cipher interface {
+type Block interface {
 	BlockSize() int
 	Encrypt(src, dst []byte)
 	Decrypt(src, dst []byte)
@@ -1718,8 +1716,8 @@ type PrintableMutex struct {
 	Mutex
 }
 
-// MyCipher is an interface type that has the same method set as Cipher.
-type MyCipher Cipher
+// MyBlock is an interface type that has the same method set as Block.
+type MyBlock Block
 </pre>
 
 <p>
@@ -1760,7 +1758,7 @@ var U, V, W float64
 var k = 0
 var x, y float32 = -1, -2
 var (
-	i int
+	i       int
 	u, v, s = 2.0, 3.0, "bar"
 )
 var re, im = complexSqrt(-1)
@@ -1783,17 +1781,7 @@ of the expression list.
 <p>
 If the type is absent and the corresponding expression evaluates to an
 untyped <a href="#Constants">constant</a>, the type of the declared variable
-is <code>bool</code>, <code>int</code>, <code>float64</code>, or <code>string</code>
-respectively, depending on whether the value is a boolean, integer,
-floating-point, or string constant:
-</p>
-
-<pre>
-var b = true    // t has type bool
-var i = 0       // i has type int
-var f = 3.0     // f has type float64
-var s = "OMDB"  // s has type string
-</pre>
+is as described in §<a href="#Assignments">Assignments</a>.
 
 <h3 id="Short_variable_declarations">Short variable declarations</h3>
 
@@ -2091,9 +2079,9 @@ to the maximum element index plus one.
 </p>
 
 <pre>
-buffer := [10]string{}               // len(buffer) == 10
-intSet := [6]int{1, 2, 3, 5}         // len(intSet) == 6
-days := [...]string{"Sat", "Sun"}    // len(days) == 2
+buffer := [10]string{}             // len(buffer) == 10
+intSet := [6]int{1, 2, 3, 5}       // len(intSet) == 6
+days := [...]string{"Sat", "Sun"}  // len(days) == 2
 </pre>
 
 <p>
@@ -2107,22 +2095,29 @@ element index plus one. A slice literal has the form
 </pre>
 
 <p>
-and is a shortcut for a slice operation applied to an array literal:
+and is a shortcut for a slice operation applied to an array:
 </p>
 
 <pre>
-[n]T{x1, x2, … xn}[0 : n]
+tmp := [n]T{x1, x2, … xn}
+tmp[0 : n]
 </pre>
 
 <p>
 Within a composite literal of array, slice, or map type <code>T</code>,
 elements that are themselves composite literals may elide the respective
 literal type if it is identical to the element type of <code>T</code>.
+Similarly, elements that are addresses of composite literals may elide
+the <code>&T</code> when the the element type is <code>*T</code>.
 </p>
 
+
+
 <pre>
-[...]Point{{1.5, -3.5}, {0, 0}}  // same as [...]Point{Point{1.5, -3.5}, Point{0, 0}}
-[][]int{{1, 2, 3}, {4, 5}}       // same as [][]int{[]int{1, 2, 3}, []int{4, 5}}
+[...]Point{{1.5, -3.5}, {0, 0}}   // same as [...]Point{Point{1.5, -3.5}, Point{0, 0}}
+[][]int{{1, 2, 3}, {4, 5}}        // same as [][]int{[]int{1, 2, 3}, []int{4, 5}}
+
+[...]*Point{{1.5, -3.5}, {0, 0}}  // same as [...]*Point{&Point{1.5, -3.5}, &Point{0, 0}}
 </pre>
 
 <p>
@@ -2332,13 +2327,13 @@ one may write:
 </p>
 
 <pre>
-p.z         // (*p).z
-p.y         // ((*p).T1).y
-p.x         // (*(*p).T0).x
+p.z   // (*p).z
+p.y   // ((*p).T1).y
+p.x   // (*(*p).T0).x
 
-p.M2        // (*p).M2
-p.M1        // ((*p).T1).M1
-p.M0        // ((*p).T0).M0
+p.M2  // (*p).M2
+p.M1  // ((*p).T1).M1
+p.M0  // ((*p).T0).M0
 </pre>
 
 
@@ -2432,21 +2427,6 @@ where the result of the index expression is a pair of values with types
 </p>
 
 <p>
-Similarly, if an assignment to a map element has the special form
-</p>
-
-<pre>
-a[x] = v, ok
-</pre>
-
-<p>
-and boolean <code>ok</code> has the value <code>false</code>,
-the entry for key <code>x</code> is deleted from the map; if
-<code>ok</code> is <code>true</code>, the construct acts like
-a regular assignment to an element of the map.
-</p>
-
-<p>
 Assigning to an element of a <code>nil</code> map causes a
 <a href="#Run_time_panics">run-time panic</a>.
 </p>
@@ -2455,7 +2435,7 @@ Assigning to an element of a <code>nil</code> map causes a
 <h3 id="Slices">Slices</h3>
 
 <p>
-For a string, array, or slice <code>a</code>, the primary expression
+For a string, array, pointer to array, or slice <code>a</code>, the primary expression
 </p>
 
 <pre>
@@ -2492,9 +2472,9 @@ sliced operand:
 </p>
 
 <pre>
-a[2:]	// same a[2 : len(a)]
-a[:3]   // same as a[0 : 3]
-a[:]    // same as a[0 : len(a)]
+a[2:]  // same a[2 : len(a)]
+a[:3]  // same as a[0 : 3]
+a[:]   // same as a[0 : len(a)]
 </pre>
 
 <p>
@@ -2587,12 +2567,26 @@ the method.
 </p>
 
 <pre>
-math.Atan2(x, y)    // function call
+math.Atan2(x, y)  // function call
 var pt *Point
 pt.Scale(3.5)  // method call with receiver pt
 </pre>
 
 <p>
+In a function call, the function value and arguments are evaluated in
+<a href="#Order_of_evaluation">the usual order</a>.
+After they are evaluated, the parameters of the call are passed by value to the function
+and the called function begins execution.
+The return parameters of the function are passed by value
+back to the calling function when the function returns.
+</p>
+
+<p>
+Calling a <code>nil</code> function value 
+causes a <a href="#Run_time_panics">run-time panic</a>.
+</p>
+
+<p>
 As a special case, if the return parameters of a function or method
 <code>g</code> are equal in number and individually
 assignable to the parameters of another function or method
@@ -2932,76 +2926,104 @@ Comparison operators compare two operands and yield a value of type <code>bool</
 !=    not equal
 <     less
 <=    less or equal
->     greater
->=    greater or equal
+>     greater
+>=    greater or equal
 </pre>
 
 <p>
-The operands must be <i>comparable</i>; that is, the first operand
+In any comparison, the first operand
 must be <a href="#Assignability">assignable</a>
 to the type of the second operand, or vice versa.
 </p>
 <p>
-The operators <code>==</code> and <code>!=</code> apply
-to operands of all types except arrays and structs.
-All other comparison operators apply only to integer, floating-point
-and string values. The result of a comparison is defined as follows:
+The equality operators <code>==</code> and <code>!=</code> apply
+to operands that are <i>comparable</i>.
+The ordering operators <code><</code>, <code><=</code>, <code>></code>, and <code>>=</code>
+apply to operands that are <i>ordered</i>.
+These terms and the result of the comparisons are defined as follows:
 </p>
 
 <ul>
 	<li>
-	Integer values are compared in the usual way.
-	</li>
-	<li>
-	Floating point values are compared as defined by the IEEE-754
-	standard.
+	Boolean values are comparable.
+	Two boolean values are equal if they are either both
+	<code>true</code> or both <code>false</code>.
 	</li>
+
 	<li>
-	Two complex values <code>u</code>, <code>v</code> are
-	equal if both <code>real(u) == real(v)</code> and
-	<code>imag(u) == imag(v)</code>.
+	Integer values are comparable and ordered, in the usual way.
 	</li>
+	
 	<li>
-	String values are compared byte-wise (lexically).
+	Floating point values are comparable and ordered,
+	as defined by the IEEE-754 standard.
 	</li>
+	
 	<li>
-	Boolean values are equal if they are either both
-	<code>true</code> or both <code>false</code>.
+	Complex values are comparable.
+	Two complex values <code>u</code> and <code>v</code> are
+	equal if both <code>real(u) == real(v)</code> and
+	<code>imag(u) == imag(v)</code>.
 	</li>
+	
 	<li>
-	Pointer values are equal if they point to the same location
-	or if both are <code>nil</code>.
+	String values are comparable and ordered, lexically byte-wise.
 	</li>
+	
 	<li>
-	Function values are equal if they refer to the same function
-	or if both are <code>nil</code>.
+	Pointer values are comparable.
+	Two pointer values are equal if they point to the same variable or if both have value <code>nil</code>.
+	Pointers to distinct <a href="#Size_and_alignment_guarantees">zero-size</a> variables may or may not be equal.
 	</li>
+	
 	<li>
-	A slice value may only be compared to <code>nil</code>.
+	Channel values are comparable.
+	Two channel values are equal if they were created by the same call to <code>make</code>
+	(§<a href="#Making_slices_maps_and_channels">Making slices, maps, and channels</a>)
+	or if both have value <code>nil</code>.
 	</li>
+
 	<li>
-	Channel and map values are equal if they were created by the same call to <code>make</code>
-	(§<a href="#Making_slices_maps_and_channels">Making slices, maps, and channels</a>)
-	or if both are <code>nil</code>.
+	Interface values are comparable.
+	Two interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types
+	and equal dynamic values or if both have value <code>nil</code>.
 	</li>
+	
 	<li>
-	Interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types and
-	equal dynamic values or if both are <code>nil</code>.
+	A value <code>x</code> of non-interface type <code>X</code> and
+	a value <code>t</code> of interface type <code>T</code> are comparable when values
+	of type <code>X</code> are comparable and
+	<code>X</code> implements <code>T</code>.
+	They are equal if <code>t</code>'s dynamic type is identical to <code>X</code>
+	and <code>t</code>'s dynamic value is equal to <code>x</code>.
 	</li>
+
 	<li>
-	An interface value <code>x</code> is equal to a non-interface value
-	<code>y</code> if the dynamic type of <code>x</code> is identical to
-	the static type of <code>y</code> and the dynamic value of <code>x</code>
-	is equal to <code>y</code>.
+	Struct values are comparable if all the fields are comparable.
+	Two struct values are equal if their corresponding fields are equal.
 	</li>
+	
 	<li>
-	A pointer, function, slice, channel, map, or interface value is equal
-	to <code>nil</code> if it has been assigned the explicit value
-	<code>nil</code>, if it is uninitialized, or if it has been assigned
-	another value equal to <code>nil</code>.
+	Array values are comparable if values of the array element type are comparable.
+	Two array values are equal if their corresponding elements are equal.
 	</li>
 </ul>
 
+<p>
+A comparison of two interface values with identical dynamic types
+causes a <a href="#Run_time_panics">run-time panic</a> if values
+of that type are not comparable.  This behavior applies not only to direct interface
+value comparisons but also when comparing arrays of interface values
+or structs with interface-valued fields.
+</p>
+
+<p>
+Slice, map, and function values are not comparable.
+However, as a special case, a slice, map, or function value may
+be compared to the predeclared identifier <code>nil</code>.
+Comparison of pointer, channel, and interface values to <code>nil</code>
+is also allowed and follows from the general rules above.
+</p>
 
 <h3 id="Logical_operators">Logical operators</h3>
 
@@ -3034,6 +3056,8 @@ As an exception to the addressability requirement, <code>x</code> may also be a
 For an operand <code>x</code> of pointer type <code>*T</code>, the pointer
 indirection <code>*x</code> denotes the value of type <code>T</code> pointed
 to by <code>x</code>.
+If <code>x</code> is <code>nil</code>, an attempt to evaluate <code>*x</code>
+will cause a <a href="#Run_time_panics">run-time panic</a>.
 </p>
 
 <pre>
@@ -3111,7 +3135,7 @@ Consider a struct type <code>T</code> with two methods,
 type T struct {
 	a int
 }
-func (tv  T) Mv(a int)     int     { return 0 }  // value receiver
+func (tv  T) Mv(a int) int         { return 0 }  // value receiver
 func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver
 var t T
 </pre>
@@ -3288,11 +3312,11 @@ in any of these cases:
 	</li>
 	<li>
 	<code>x</code> is an integer or has type <code>[]byte</code> or
-	<code>[]int</code> and <code>T</code> is a string type.
+	<code>[]rune</code> and <code>T</code> is a string type.
 	</li>
 	<li>
 	<code>x</code> is a string and <code>T</code> is <code>[]byte</code> or
-	<code>[]int</code>.
+	<code>[]rune</code>.
 	</li>
 </ul>
 
@@ -3357,51 +3381,59 @@ string containing the UTF-8 representation of the integer. Values outside
 the range of valid Unicode code points are converted to <code>"\uFFFD"</code>.
 
 <pre>
-string('a')           // "a"
-string(-1)            // "\ufffd" == "\xef\xbf\xbd "
-string(0xf8)          // "\u00f8" == "ø" == "\xc3\xb8"
+string('a')       // "a"
+string(-1)        // "\ufffd" == "\xef\xbf\xbd "
+string(0xf8)      // "\u00f8" == "ø" == "\xc3\xb8"
 type MyString string
-MyString(0x65e5)      // "\u65e5" == "æ—¥" == "\xe6\x97\xa5"
+MyString(0x65e5)  // "\u65e5" == "æ—¥" == "\xe6\x97\xa5"
 </pre>
 </li>
 
 <li>
-Converting a value of type <code>[]byte</code> (or
-the equivalent <code>[]uint8</code>) to a string type yields a
-string whose successive bytes are the elements of the slice.  If
+Converting a slice of bytes to a string type yields
+a string whose successive bytes are the elements of the slice.  If
 the slice value is <code>nil</code>, the result is the empty string.
 
 <pre>
 string([]byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'})  // "hellø"
+
+type MyBytes []byte
+string(MyBytes{'h', 'e', 'l', 'l', '\xc3', '\xb8'})  // "hellø"
 </pre>
 </li>
 
 <li>
-Converting a value of type <code>[]int</code> to a string type yields
-a string that is the concatenation of the individual integers
+Converting a slice of runes to a string type yields
+a string that is the concatenation of the individual rune values
 converted to strings.  If the slice value is <code>nil</code>, the
 result is the empty string.
+
 <pre>
-string([]int{0x767d, 0x9d6c, 0x7fd4})  // "\u767d\u9d6c\u7fd4" == "白鵬翔"
+string([]rune{0x767d, 0x9d6c, 0x7fd4})  // "\u767d\u9d6c\u7fd4" == "白鵬翔"
+
+type MyRunes []rune
+string(MyRunes{0x767d, 0x9d6c, 0x7fd4})  // "\u767d\u9d6c\u7fd4" == "白鵬翔"
 </pre>
 </li>
 
 <li>
-Converting a value of a string type to <code>[]byte</code> (or <code>[]uint8</code>)
+Converting a value of a string type to a slice of bytes type
 yields a slice whose successive elements are the bytes of the string.
 If the string is empty, the result is <code>[]byte(nil)</code>.
 
 <pre>
-[]byte("hellø")  // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
+[]byte("hellø")   // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
+MyBytes("hellø")  // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
 </pre>
 </li>
 
 <li>
-Converting a value of a string type to <code>[]int</code> yields a
-slice containing the individual Unicode code points of the string.
-If the string is empty, the result is <code>[]int(nil)</code>.
+Converting a value of a string type to a slice of runes type
+yields a slice containing the individual Unicode code points of the string.
+If the string is empty, the result is <code>[]rune(nil)</code>.
 <pre>
-[]int(MyString("白鵬翔"))  // []int{0x767d, 0x9d6c, 0x7fd4}
+[]rune(MyString("白鵬翔"))  // []rune{0x767d, 0x9d6c, 0x7fd4}
+MyRunes("白鵬翔")           // []rune{0x767d, 0x9d6c, 0x7fd4}
 </pre>
 </li>
 </ol>
@@ -3417,19 +3449,17 @@ operands and are evaluated at compile-time.
 <p>
 Untyped boolean, numeric, and string constants may be used as operands
 wherever it is legal to use an operand of boolean, numeric, or string type,
-respectively. Except for shift operations, if the operands of a binary operation
-are an untyped integer constant and an untyped floating-point constant,
-the integer constant is converted to an untyped floating-point constant
-(relevant for <code>/</code> and <code>%</code>).
-Similarly, untyped integer or floating-point constants may be used as operands
-wherever it is legal to use an operand of complex type;
-the integer or floating point constant is converted to a
-complex constant with a zero imaginary part.
+respectively.
+Except for shift operations, if the operands of a binary operation are
+different kinds of untyped constants, the operation and result use
+the kind that appears later in this list: integer, character, floating-point, complex.
+For example, an untyped integer constant divided by an
+untyped complex constant yields an untyped complex constant.
 </p>
 
 <p>
 A constant <a href="#Comparison_operators">comparison</a> always yields
-a constant of type <code>bool</code>. If the left operand of a constant
+an untyped boolean constant. If the left operand of a constant
 <a href="#Operators">shift expression</a> is an untyped constant, the
 result is an integer constant; otherwise it is a constant of the same
 type as the left operand, which must be of integer type
@@ -3440,32 +3470,33 @@ complex, or string constant).
 </p>
 
 <pre>
-const a = 2 + 3.0          // a == 5.0   (floating-point constant)
-const b = 15 / 4           // b == 3     (integer constant)
-const c = 15 / 4.0         // c == 3.75  (floating-point constant)
-const d = 1 << 3.0         // d == 8     (integer constant)
-const e = 1.0 << 3         // e == 8     (integer constant)
+const a = 2 + 3.0          // a == 5.0   (untyped floating-point constant)
+const b = 15 / 4           // b == 3     (untyped integer constant)
+const c = 15 / 4.0         // c == 3.75  (untyped floating-point constant)
+const Θ float64 = 3/2      // Θ == 1.5   (type float64)
+const d = 1 << 3.0         // d == 8     (untyped integer constant)
+const e = 1.0 << 3         // e == 8     (untyped integer constant)
 const f = int32(1) << 33   // f == 0     (type int32)
 const g = float64(2) >> 1  // illegal    (float64(2) is a typed floating-point constant)
-const h = "foo" > "bar"    // h == true  (type bool)
+const h = "foo" > "bar"    // h == true  (untyped boolean constant)
+const j = true             // j == true  (untyped boolean constant)
+const k = 'w' + 1          // k == 'x'   (untyped character constant)
+const l = "hi"             // l == "hi"  (untyped string constant)
+const m = string(k)        // m == "x"   (type string)
+const Σ = 1 - 0.707i       //            (untyped complex constant)
+const Δ = Σ + 2.0e-4       //            (untyped complex constant)
+const Φ = iota*1i - 1/1i   //            (untyped complex constant)
 </pre>
 
 <p>
-Imaginary literals are untyped complex constants (with zero real part)
-and may be combined in binary
-operations with untyped integer and floating-point constants; the
-result is an untyped complex constant.
-Complex constants are always constructed from
-constant expressions involving imaginary
-literals or constants derived from them, or calls of the built-in function
-<a href="#Complex_numbers"><code>complex</code></a>.
+Applying the built-in function <code>complex</code> to untyped
+integer, character, or floating-point constants yields
+an untyped complex constant.
 </p>
 
 <pre>
-const Σ = 1 - 0.707i
-const Δ = Σ + 2.0e-4 - 1/1i
-const Φ = iota * 1i
-const iΓ = complex(0, Γ)
+const ic = complex(0, c)   // ic == 3.75i (untyped complex constant)
+const iΘ = complex(0, Θ)   // iΘ == 1.5i  (type complex128)
 </pre>
 
 <p>
@@ -3485,11 +3516,11 @@ of the constant type. The following constant expressions are illegal:
 </p>
 
 <pre>
-uint(-1)       // -1 cannot be represented as a uint
-int(3.14)      // 3.14 cannot be represented as an int
-int64(Huge)    // 1<<100 cannot be represented as an int64
-Four * 300     // 300 cannot be represented as an int8
-Four * 100     // 400 cannot be represented as an int8
+uint(-1)     // -1 cannot be represented as a uint
+int(3.14)    // 3.14 cannot be represented as an int
+int64(Huge)  // 1<<100 cannot be represented as an int64
+Four * 300   // 300 cannot be represented as an int8
+Four * 100   // 400 cannot be represented as an int8
 </pre>
 
 <p>
@@ -3499,11 +3530,11 @@ and -1 for signed and untyped constants.
 </p>
 
 <pre>
-^1          // untyped integer constant, equal to -2
-uint8(^1)   // error, same as uint8(-2), out of range
-^uint8(1)   // typed uint8 constant, same as 0xFF ^ uint8(1) = uint8(0xFE)
-int8(^1)    // same as int8(-2)
-^int8(1)    // same as -1 ^ int8(1) = -2
+^1         // untyped integer constant, equal to -2
+uint8(^1)  // error, same as uint8(-2), out of range
+^uint8(1)  // typed uint8 constant, same as 0xFF ^ uint8(1) = uint8(0xFE)
+int8(^1)   // same as int8(-2)
+^int8(1)   // same as -1 ^ int8(1) = -2
 </pre>
 
 <!--
@@ -3529,7 +3560,7 @@ order.
 For example, in the assignment
 </p>
 <pre>
-y[f()], ok = g(h(), i() + x[j()], <-c), k()
+y[f()], ok = g(h(), i()+x[j()], <-c), k()
 </pre>
 <p>
 the function calls and communication happen in the order
@@ -3730,14 +3761,32 @@ x, _ = f()  // ignore second value returned by f()
 In the second form, the number of operands on the left must equal the number
 of expressions on the right, each of which must be single-valued, and the
 <i>n</i>th expression on the right is assigned to the <i>n</i>th
-operand on the left.
-The expressions on the right are evaluated before assigning to
-any of the operands on the left, but otherwise the evaluation
-order is unspecified beyond <a href="#Order_of_evaluation">the usual rules</a>.
+operand on the left.  The assignment proceeds in two phases.
+First, the operands of <a href="#Indexes">index expressions</a>
+and <a href="#Address_operators">pointer indirections</a>
+(including implicit pointer indirections in <a href="#Selectors">selectors</a>)
+on the left and the expressions on the right are all
+<a href="#Order_of_evaluation">evaluated in the usual order</a>.
+Second, the assignments are carried out in left-to-right order.
 </p>
 
 <pre>
 a, b = b, a  // exchange a and b
+
+x := []int{1, 2, 3}
+i := 0
+i, x[i] = 1, 2  // set i = 1, x[0] = 2
+
+i = 0
+x[i], i = 2, 1  // set x[0] = 2, i = 1
+
+x[0], x[0] = 1, 2  // set x[0] = 1, then x[0] = 2 (so x[0] = 2 at end)
+
+x[1], x[3] = 4, 5  // set x[1] = 4, then panic setting x[3] = 5.
+
+type Point struct { x, y int }
+var p *Point
+x[2], p.x = 6, 7  // set x[2] = 6, then panic setting p.x = 7
 </pre>
 
 <p>
@@ -3745,10 +3794,10 @@ In assignments, each value must be
 <a href="#Assignability">assignable</a> to the type of the
 operand to which it is assigned. If an untyped <a href="#Constants">constant</a>
 is assigned to a variable of interface type, the constant is <a href="#Conversions">converted</a>
-to type <code>bool</code>, <code>int</code>, <code>float64</code>,
+to type <code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
 <code>complex128</code> or <code>string</code>
-respectively, depending on whether the value is a boolean, integer, floating-point,
-complex, or string constant.
+respectively, depending on whether the value is a boolean,
+character, integer, floating-point, complex, or string constant.
 </p>
 
 
@@ -4053,7 +4102,7 @@ For each iteration, iteration values are produced as follows:
 Range expression                          1st value          2nd value (if 2nd variable is present)
 
 array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
-string          s  string type            index    i  int    see below  int
+string          s  string type            index    i  int    see below  rune
 map             m  map[K]V                key      k  K      m[k]       V
 channel         c  chan E                 element  e  E
 </pre>
@@ -4071,7 +4120,7 @@ or slice itself. For a <code>nil</code> slice, the number of iterations is 0.
 For a string value, the "range" clause iterates over the Unicode code points
 in the string starting at byte index 0.  On successive iterations, the index value will be the
 index of the first byte of successive UTF-8-encoded code points in the string,
-and the second value, of type <code>int</code>, will be the value of
+and the second value, of type <code>rune</code>, will be the value of
 the corresponding code point.  If the iteration encounters an invalid
 UTF-8 sequence, the second value will be <code>0xFFFD</code>,
 the Unicode replacement character, and the next iteration will advance
@@ -4079,7 +4128,8 @@ a single byte in the string.
 </li>
 
 <li>
-The iteration order over maps is not specified.
+The iteration order over maps is not specified
+and is not guaranteed to be the same from one iteration to the next.
 If map entries that have not yet been reached are deleted during iteration,
 the corresponding iteration values will not be produced. If map entries are
 inserted during iteration, the behavior is implementation-dependent, but the
@@ -4155,9 +4205,17 @@ GoStmt = "go" Expression .
 </pre>
 
 <p>
-The expression must be a call, and
+The expression must be a call.
+The function value and parameters are
+<a href="#Calls">evaluated as usual</a>
+in the calling goroutine, but
 unlike with a regular call, program execution does not wait
 for the invoked function to complete.
+Instead, the function begins executing independently
+in a new goroutine.
+When the function terminates, its goroutine also terminates.
+If the function has any return values, they are discarded when the
+function completes.
 </p>
 
 <pre>
@@ -4208,7 +4266,7 @@ effects in that evaluation will occur for all the communications
 in the "select" statement.
 </p>
 <p>
-If multiple cases can proceed, a pseudo-random fair choice is made to decide
+If multiple cases can proceed, a uniform pseudo-random choice is made to decide
 which single communication will execute.
 <p>
 The receive case may declare one or two new variables using a
@@ -4240,7 +4298,7 @@ for {  // send random sequence of bits to c
 	}
 }
 
-select { }  // block forever
+select {}  // block forever
 </pre>
 
 
@@ -4309,10 +4367,10 @@ func complex_f3() (re float64, im float64) {
 	return
 }
 
-func (devnull) Write(p []byte) (n int, _ os.Error) {
+func (devnull) Write(p []byte) (n int, _ error) {
 	n = len(p)
 	return
-} 
+}
 </pre>
 	</li>
 </ol>
@@ -4325,8 +4383,6 @@ Regardless of how they are declared, all the result values are initialized to th
 <p>
 <span class="alert">
 TODO: Define when return is required.<br />
-TODO: Language about result parameters needs to go into a section on
-      function/method invocation<br />
 </span>
 </p>
 -->
@@ -4427,7 +4483,7 @@ L1:
 </pre>
 
 <p>
-is erroneous because the label <code>L1</code> is inside 
+is erroneous because the label <code>L1</code> is inside
 the "for" statement's block but the <code>goto</code> is not.
 </p>
 
@@ -4459,9 +4515,11 @@ DeferStmt = "defer" Expression .
 <p>
 The expression must be a function or method call.
 Each time the "defer" statement
-executes, the parameters to the function call are evaluated and saved anew but the
-function is not invoked.
-Deferred function calls are executed in LIFO order
+executes, the function value and parameters to the call are
+<a href="#Calls">evaluated as usual</a>
+and saved anew but the
+actual function is not invoked.
+Instead, deferred calls are executed in LIFO order
 immediately before the surrounding function returns,
 after the return values, if any, have been evaluated, but before they
 are returned to the caller. For instance, if the deferred function is
@@ -4469,6 +4527,8 @@ a <a href="#Function_literals">function literal</a> and the surrounding
 function has <a href="#Function_types">named result parameters</a> that
 are in scope within the literal, the deferred function may access and modify
 the result parameters before they are returned.
+If the deferred function has any return values, they are discarded when
+the function completes.
 </p>
 
 <pre>
@@ -4513,12 +4573,13 @@ BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList .
 
 <p>
 For a channel <code>c</code>, the built-in function <code>close(c)</code>
-marks the channel as unable to accept more values through a send operation;
-sending to or closing a closed channel causes a <a href="#Run_time_panics">run-time panic</a>.
+records that no more values will be sent on the channel.
+It is an error if <code>c</code> is a receive-only channel.
+Sending to or closing a closed channel causes a <a href="#Run_time_panics">run-time panic</a>.
+Closing the nil channel also causes a <a href="#Run_time_panics">run-time panic</a>.
 After calling <code>close</code>, and after any previously
 sent values have been received, receive operations will return
 the zero value for the channel's type without blocking.
-
 The multi-valued <a href="#Receive_operator">receive operation</a>
 returns a received value along with an indication of whether the channel is closed.
 </p>
@@ -4636,10 +4697,10 @@ is negative or larger than <code>m</code>, or if <code>n</code> or
 </p>
 
 <pre>
-s := make([]int, 10, 100)        // slice with len(s) == 10, cap(s) == 100
-s := make([]int, 10)             // slice with len(s) == cap(s) == 10
-c := make(chan int, 10)          // channel with a buffer size of 10
-m := make(map[string] int, 100)  // map with initial space for 100 elements
+s := make([]int, 10, 100)       // slice with len(s) == 10, cap(s) == 100
+s := make([]int, 10)            // slice with len(s) == cap(s) == 10
+c := make(chan int, 10)         // channel with a buffer size of 10
+m := make(map[string]int, 100)  // map with initial space for 100 elements
 </pre>
 
 
@@ -4658,6 +4719,10 @@ The values <code>x</code> are passed to a parameter of type <code>...T</code>
 where <code>T</code> is the <a href="#Slice_types">element type</a> of
 <code>S</code> and the respective
 <a href="#Passing_arguments_to_..._parameters">parameter passing rules</a> apply.
+As a special case, <code>append</code> also accepts a first argument
+assignable to type <code>[]byte</code> with a second argument of
+string type followed by <code>...</code>. This form appends the
+bytes of the string.
 </p>
 
 <pre class="grammar">
@@ -4668,7 +4733,7 @@ append(s S, x ...T) S  // T is the element type of S
 If the capacity of <code>s</code> is not large enough to fit the additional
 values, <code>append</code> allocates a new, sufficiently large slice that fits
 both the existing slice elements and the additional values. Thus, the returned
-slice may refer to a different underlying array. 
+slice may refer to a different underlying array.
 </p>
 
 <pre>
@@ -4679,6 +4744,9 @@ s3 := append(s2, s0...)    // append a slice              s3 == []int{0, 0, 2, 3
 
 var t []interface{}
 t = append(t, 42, 3.1415, "foo")                          t == []interface{}{42, 3.1415, "foo"}
+
+var b []byte
+b = append(b, "bar"...)  // append string contents      b == []byte{'b', 'a', 'r' }
 </pre>
 
 <p>
@@ -4712,6 +4780,27 @@ n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
 n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
 </pre>
 
+
+<h3 id="Deletion_of_map_elements">Deletion of map elements</h3>
+
+<p>
+The built-in function <code>delete</code> removes the element with key
+<code>k</code> from a <a href="#Map_types">map</a> <code>m</code>. The
+type of <code>k</code> must be <a href="#Assignability">assignable</a>
+to the key type of <code>m</code>.
+</p>
+
+<pre class="grammar">
+delete(m, k)  // remove element m[k] from map m
+</pre>
+
+<p>
+If the element <code>m[k]</code> does not exist, <code>delete</code> is
+a no-op. Calling <code>delete</code> with a nil map causes a
+<a href="#Run_time_panics">run-time panic</a>.
+</p>
+
+
 <h3 id="Complex_numbers">Assembling and disassembling complex numbers</h3>
 
 <p>
@@ -4758,7 +4847,7 @@ var rl = real(c64)                 // float32
 
 <p> Two built-in functions, <code>panic</code> and <code>recover</code>,
 assist in reporting and handling <a href="#Run_time_panics">run-time panics</a>
-and program-defined error conditions. 
+and program-defined error conditions.
 </p>
 
 <pre class="grammar">
@@ -4808,7 +4897,7 @@ run-time panics raised by <code>g</code>.
 <pre>
 func protect(g func()) {
 	defer func() {
-		log.Println("done")  // Println executes normally even in there is a panic
+		log.Println("done")  // Println executes normally even if there is a panic
 		if x := recover(); x != nil {
 			log.Printf("run time panic: %v", x)
 		}
@@ -4972,7 +5061,7 @@ func generate(ch chan<- int) {
 // Copy the values from channel 'src' to channel 'dst',
 // removing those divisible by 'prime'.
 func filter(src <-chan int, dst chan<- int, prime int) {
-	for i := range src {	// Loop over values received from 'src'.
+	for i := range src {  // Loop over values received from 'src'.
 		if i%prime != 0 {
 			dst <- i  // Send 'i' to channel 'dst'.
 		}
@@ -5084,12 +5173,6 @@ unspecified results  if <code>A</code>'s initializer calls a function defined
 in another package that refers to <code>B</code>.
 </p>
 <p>
-Initialization code may contain "go" statements, but the functions
-they invoke do not begin execution until initialization of the entire
-program is complete. Therefore, all initialization code is run in a single
-goroutine.
-</p>
-<p>
 An <code>init</code> function cannot be referred to from anywhere
 in a program. In particular, <code>init</code> cannot be called explicitly,
 nor can a pointer to <code>init</code> be assigned to a function variable.
@@ -5108,7 +5191,7 @@ A complete program is created by linking a single, unimported package
 called the <i>main package</i> with all the packages it imports, transitively.
 The main package must
 have package name <code>main</code> and
-declare a function <code>main</code> that takes no 
+declare a function <code>main</code> that takes no
 arguments and returns no value.
 </p>
 
@@ -5119,12 +5202,44 @@ func main() { … }
 <p>
 Program execution begins by initializing the main package and then
 invoking the function <code>main</code>.
-</p>
-<p>
 When the function <code>main</code> returns, the program exits.
 It does not wait for other (non-<code>main</code>) goroutines to complete.
 </p>
 
+<p>
+Package initialization—variable initialization and the invocation of
+<code>init</code> functions—happens in a single goroutine,
+sequentially, one package at a time.
+An <code>init</code> function may launch other goroutines, which can run
+concurrently with the initialization code. However, initialization
+always sequences
+the <code>init</code> functions: it will not start the next
+<code>init</code> until
+the previous one has returned.
+</p>
+
+<h2 id="Errors">Errors</h2>
+
+<p>
+The predeclared type <code>error</code> is defined as
+</p>
+
+<pre>
+type error interface {
+	Error() string
+}
+</pre>
+
+<p>
+It is the conventional interface for representing an error condition,
+with the nil value representing no error.
+For instance, a function to read data from a file might be defined:
+</p>
+
+<pre>
+func Read(f *File, b []byte) (n int, err error)
+</pre>
+
 <h2 id="Run_time_panics">Run-time panics</h2>
 
 <p>
@@ -5132,18 +5247,18 @@ Execution errors such as attempting to index an array out
 of bounds trigger a <i>run-time panic</i> equivalent to a call of
 the built-in function <a href="#Handling_panics"><code>panic</code></a>
 with a value of the implementation-defined interface type <code>runtime.Error</code>.
-That type defines at least the method
-<code>String() string</code>.  The exact error values that
-represent distinct run-time error conditions are unspecified,
-at least for now.
+That type satisfies the predeclared interface type
+<a href="#Errors"><code>error</code></a>.
+The exact error values that
+represent distinct run-time error conditions are unspecified.
 </p>
 
 <pre>
 package runtime
 
 type Error interface {
-	String() string
-	// and perhaps others
+	error
+	// and perhaps other methods
 }
 </pre>
 
@@ -5175,7 +5290,7 @@ func Unreflect(typ runtime.Type, addr uintptr) interface{}
 </pre>
 
 <p>
-Any pointer or value of type <code>uintptr</code> can be converted into
+Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted into
 a <code>Pointer</code> and vice versa.
 </p>
 <p>
@@ -5261,11 +5376,12 @@ The following minimal alignment properties are guaranteed:
 </li>
 </ol>
 
-<span class="alert">
+<p>
+A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.
+</p>
+
+
 <h2 id="Implementation_differences">Implementation differences - TODO</h2>
 <ul>
-	<li><code>len(a)</code> is only a constant if <code>a</code> is a (qualified) identifier denoting an array or pointer to an array.</li>
-	<li>In gccgo, <code>nil</code> maps are not treated like empty maps.</li>
-	<li>In gccgo, trying to send/receive from a <code>nil</code> channel causes a run-time panic.</li>
+	<li><span class="alert"><code>len(x)</code> is only a constant if <code>x</code> is a (qualified) identifier denoting an array or pointer to an array.</span></li>
 </ul>
-</span>
diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html
index 0b366bb..eaa989a 100644
--- a/doc/go_tutorial.html
+++ b/doc/go_tutorial.html
@@ -1,4 +1,12 @@
-<!-- A Tutorial for the Go Programming Language -->
+<!--{
+	"Title": "A Tutorial for the Go Programming Language"
+}-->
+<!--
+  DO NOT EDIT: created by
+    tmpltohtml go_tutorial.tmpl
+-->
+
+
 <h2>Introduction</h2>
 <p>
 This document is a tutorial introduction to the basics of the Go programming
@@ -9,11 +17,8 @@ After you've read this tutorial, you should look at
 <a href='/doc/effective_go.html'>Effective Go</a>,
 which digs deeper into how the language is used and
 talks about the style and idioms of programming in Go.
-Also, slides from a 3-day course about Go are available.
-They provide some background and a lot of examples:
-<a href='/doc/GoCourseDay1.pdf'>Day 1</a>,
-<a href='/doc/GoCourseDay2.pdf'>Day 2</a>,
-<a href='/doc/GoCourseDay3.pdf'>Day 3</a>.
+An interactive introduction to Go is available, called
+<a href='http://tour.golang.org/'>A Tour of Go</a>.
 <p>
 The presentation here proceeds through a series of modest programs to illustrate
 key features of the language.  All the programs work (at time of writing) and are
@@ -30,8 +35,7 @@ import fmt "fmt" // Package implementing formatted I/O.
 
 func main() {
     fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n")
-}
-</pre>
+}</pre>
 <p>
 Every Go source file declares, using a <code>package</code> statement, which package it's part of.
 It may also import other packages to use their facilities.
@@ -95,7 +99,7 @@ Here's how to compile and run our program.  With <code>6g</code>, say,
 <pre>
 $ 6g helloworld.go  # compile; object goes into helloworld.6
 $ 6l helloworld.6   # link; output goes into 6.out
-$ 6.out
+$ ./6.out
 Hello, world; or Καλημέρα κόσμε; or こんにちは 世界
 $
 </pre>
@@ -104,7 +108,7 @@ With <code>gccgo</code> it looks a little more traditional.
 <p>
 <pre>
 $ gccgo helloworld.go
-$ a.out
+$ ./a.out
 Hello, world; or Καλημέρα κόσμε; or こんにちは 世界
 $
 </pre>
@@ -117,8 +121,8 @@ Next up, here's a version of the Unix utility <code>echo(1)</code>:
 -->package main
 
 import (
-    "os"
     "flag" // command line option parser
+    "os"
 )
 
 var omitNewline = flag.Bool("n", false, "don't print final newline")
@@ -141,8 +145,7 @@ func main() {
         s += Newline
     }
     os.Stdout.WriteString(s)
-}
-</pre>
+}</pre>
 <p>
 This program is small but it's doing a number of new things.  In the last example,
 we saw <code>func</code> introduce a function.  The keywords <code>var</code>, <code>const</code>, and <code>type</code>
@@ -208,8 +211,7 @@ The <code>:=</code> operator is used a lot in Go to represent an initializing de
 There's one in the <code>for</code> clause on the next line:
 <p>
 <pre><!--{{code "progs/echo.go" `/for/`}}
--->    for i := 0; i < flag.NArg(); i++ {
-</pre>
+-->    for i := 0; i < flag.NArg(); i++ {</pre>
 <p>
 The <code>flag</code> package has parsed the arguments and left the non-flag arguments
 in a list that can be iterated over in the obvious way.
@@ -264,8 +266,7 @@ reassigning it.  This snippet from <code>strings.go</code> is legal code:
     }
     s = "good bye"
     var p *string = &s
-    *p = "ciao"
-</pre>
+    *p = "ciao"</pre>
 <p>
 However the following statements are illegal because they would modify
 a <code>string</code> value:
@@ -337,25 +338,26 @@ Using slices one can write this function (from <code>sum.go</code>):
         s += a[i]
     }
     return s
-}
-</pre>
+}</pre>
 <p>
 Note how the return type (<code>int</code>) is defined for <code>sum</code> by stating it
 after the parameter list.
 <p>
-To call the function, we slice the array.  This intricate call (we'll show
+To call the function, we slice the array.  This code (we'll show
 a simpler way in a moment) constructs
 an array and slices it:
 <p>
 <pre>
-s := sum([3]int{1,2,3}[:])
+x := [3]int{1,2,3}
+s := sum(x[:])
 </pre>
 <p>
 If you are creating a regular array but want the compiler to count the
 elements for you, use <code>...</code> as the array size:
 <p>
 <pre>
-s := sum([...]int{1,2,3}[:])
+x := [...]int{1,2,3}
+s := sum(x[:])
 </pre>
 <p>
 That's fussier than necessary, though.
@@ -473,8 +475,9 @@ assigned to a variable.
 <p>
 <h2>An I/O Package</h2>
 <p>
-Next we'll look at a simple package for doing file I/O with an
-open/close/read/write interface.  Here's the start of <code>file.go</code>:
+Next we'll look at a simple package for doing Unix file I/O with an
+open/close/read/write interface.
+Here's the start of <code>file.go</code>:
 <p>
 <pre><!--{{code "progs/file.go" `/package/` `/^}/`}}
 -->package file
@@ -487,8 +490,7 @@ import (
 type File struct {
     fd   int    // file descriptor number
     name string // file name at Open time
-}
-</pre>
+}</pre>
 <p>
 The first few lines declare the name of the
 package—<code>file</code>—and then import two packages.  The <code>os</code>
@@ -499,6 +501,11 @@ and reproduce the rudiments of its file I/O.
 <p>
 The other item is the low-level, external <code>syscall</code> package, which provides
 a primitive interface to the underlying operating system's calls.
+The <code>syscall</code> package is very system-dependent, and the way it's
+used here works only on Unix-like systems,
+but the general ideas explored here apply broadly.
+(A Windows version is available in
+<a href="progs/file_windows.go"><code>file_windows.go</code></a>.)
 <p>
 Next is a type definition: the <code>type</code> keyword introduces a type declaration,
 in this case a data structure called <code>File</code>.
@@ -524,8 +531,7 @@ First, though, here is a factory to create a <code>File</code>:
         return nil
     }
     return &File{fd, name}
-}
-</pre>
+}</pre>
 <p>
 This returns a pointer to a new <code>File</code> structure with the file descriptor and name
 filled in.  This code uses Go's notion of a ''composite literal'', analogous to
@@ -544,27 +550,21 @@ composite literal, as is done here in the <code>return</code> statement from <co
 <p>
 We can use the factory to construct some familiar, exported variables of type <code>*File</code>:
 <p>
-<pre><!--{{code "progs/file.go" `/var/` `/^.$/`}}
+<pre><!--{{code "progs/file.go" `/var/` `/^\)/`}}
 -->var (
     Stdin  = newFile(syscall.Stdin, "/dev/stdin")
     Stdout = newFile(syscall.Stdout, "/dev/stdout")
     Stderr = newFile(syscall.Stderr, "/dev/stderr")
-)
-
-</pre>
+)</pre>
 <p>
 The <code>newFile</code> function was not exported because it's internal. The proper,
 exported factory to use is <code>OpenFile</code> (we'll explain that name in a moment):
 <p>
 <pre><!--{{code "progs/file.go" `/func.OpenFile/` `/^}/`}}
--->func OpenFile(name string, mode int, perm uint32) (file *File, err os.Error) {
-    r, e := syscall.Open(name, mode, perm)
-    if e != 0 {
-        err = os.Errno(e)
-    }
+-->func OpenFile(name string, mode int, perm uint32) (file *File, err error) {
+    r, err := syscall.Open(name, mode, perm)
     return newFile(r, name), err
-}
-</pre>
+}</pre>
 <p>
 There are a number of new things in these few lines.  First, <code>OpenFile</code> returns
 multiple values, a <code>File</code> and an error (more about errors in a moment).
@@ -579,11 +579,13 @@ to see that).  Finally, <code>OpenFile</code> returns two values: a pointer to t
 and the error.  If <code>syscall.Open</code> fails, the file descriptor <code>r</code> will
 be negative and <code>newFile</code> will return <code>nil</code>.
 <p>
-About those errors:  The <code>os</code> library includes a general notion of an error.
+About those errors:  The Go language includes a general notion of an error:
+a pre-defined type <code>error</code> with properties (described below)
+that make it a good basis for representing and handling errors.
 It's a good idea to use its facility in your own interfaces, as we do here, for
 consistent error handling throughout Go code.   In <code>Open</code> we use a
 conversion to translate Unix's integer <code>errno</code> value into the integer type
-<code>os.Errno</code>, which implements <code>os.Error</code>.
+<code>os.Errno</code>, which is an implementation of <code>error</code>
 <p>
 Why <code>OpenFile</code> and not <code>Open</code>? To mimic Go's <code>os</code> package, which
 our exercise is emulating. The <code>os</code> package takes the opportunity
@@ -602,16 +604,14 @@ the tricky standard arguments to open and, especially, to create a file:
     O_TRUNC  = syscall.O_TRUNC
 )
 
-func Open(name string) (file *File, err os.Error) {
+func Open(name string) (file *File, err error) {
     return OpenFile(name, O_RDONLY, 0)
-}
-</pre>
+}</pre>
 <p>
 <pre><!--{{code "progs/file.go" `/func.Create/` `/^}/`}}
--->func Create(name string) (file *File, err os.Error) {
+-->func Create(name string) (file *File, err error) {
     return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
-}
-</pre>
+}</pre>
 <p>
 Back to our main story.
 Now that we can build <code>Files</code>, we can write methods for them. To declare
@@ -621,44 +621,34 @@ in parentheses before the function name. Here are some methods for <code>*File</
 each of which declares a receiver variable <code>file</code>.
 <p>
 <pre><!--{{code "progs/file.go" `/Close/` "$"}}
--->func (file *File) Close() os.Error {
+-->func (file *File) Close() error {
     if file == nil {
         return os.EINVAL
     }
-    e := syscall.Close(file.fd)
+    err := syscall.Close(file.fd)
     file.fd = -1 // so it can't be closed again
-    if e != 0 {
-        return os.Errno(e)
-    }
-    return nil
+    return err
 }
 
-func (file *File) Read(b []byte) (ret int, err os.Error) {
+func (file *File) Read(b []byte) (ret int, err error) {
     if file == nil {
         return -1, os.EINVAL
     }
-    r, e := syscall.Read(file.fd, b)
-    if e != 0 {
-        err = os.Errno(e)
-    }
+    r, err := syscall.Read(file.fd, b)
     return int(r), err
 }
 
-func (file *File) Write(b []byte) (ret int, err os.Error) {
+func (file *File) Write(b []byte) (ret int, err error) {
     if file == nil {
         return -1, os.EINVAL
     }
-    r, e := syscall.Write(file.fd, b)
-    if e != 0 {
-        err = os.Errno(e)
-    }
+    r, err := syscall.Write(file.fd, b)
     return int(r), err
 }
 
 func (file *File) String() string {
     return file.name
-}
-</pre>
+}</pre>
 <p>
 There is no implicit <code>this</code> and the receiver variable must be used to access
 members of the structure.  Methods are not declared within
@@ -669,7 +659,7 @@ array, not just for <code>structs</code>.   We'll see an example with arrays lat
 The <code>String</code> method is so called because of a printing convention we'll
 describe later.
 <p>
-The methods use the public variable <code>os.EINVAL</code> to return the (<code>os.Error</code>
+The methods use the public variable <code>os.EINVAL</code> to return the (<code>error</code>
 version of the) Unix error code <code>EINVAL</code>.  The <code>os</code> library defines a standard
 set of such error values.
 <p>
@@ -689,11 +679,10 @@ func main() {
     file.Stdout.Write(hello)
     f, err := file.Open("/does/not/exist")
     if f == nil {
-        fmt.Printf("can't open file; err=%s\n", err.String())
+        fmt.Printf("can't open file; err=%s\n", err.Error())
         os.Exit(1)
     }
-}
-</pre>
+}</pre>
 <p>
 The ''<code>./</code>'' in the import of ''<code>./file</code>'' tells the compiler
 to use our own package rather than
@@ -707,7 +696,7 @@ Now we can compile and run the program. On Unix, this would be the result:
 $ 6g file.go                       # compile file package
 $ 6g helloworld3.go                # compile main package
 $ 6l -o helloworld3 helloworld3.6  # link - no need to mention "file"
-$ helloworld3
+$ ./helloworld3
 hello, world
 can't open file; err=No such file or directory
 $
@@ -734,13 +723,13 @@ func cat(f *file.File) {
     for {
         switch nr, er := f.Read(buf[:]); true {
         case nr < 0:
-            fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", f.String(), er.String())
+            fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", f, er)
             os.Exit(1)
         case nr == 0: // EOF
             return
         case nr > 0:
             if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
-                fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", f.String(), ew.String())
+                fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", f, ew)
                 os.Exit(1)
             }
         }
@@ -761,8 +750,7 @@ func main() {
         cat(f)
         f.Close()
     }
-}
-</pre>
+}</pre>
 <p>
 By now this should be easy to follow, but the <code>switch</code> statement introduces some
 new features.  Like a <code>for</code> loop, an <code>if</code> or <code>switch</code> can include an
@@ -792,10 +780,9 @@ Here is code from <code>progs/cat_rot13.go</code>:
 <p>
 <pre><!--{{code "progs/cat_rot13.go" `/type.reader/` `/^}/`}}
 -->type reader interface {
-    Read(b []byte) (ret int, err os.Error)
+    Read(b []byte) (ret int, err error)
     String() string
-}
-</pre>
+}</pre>
 <p>
 Any type that has the two methods of <code>reader</code>—regardless of whatever
 other methods the type may also have—is said to <i>implement</i> the
@@ -816,7 +803,7 @@ func newRotate13(source reader) *rotate13 {
     return &rotate13{source}
 }
 
-func (r13 *rotate13) Read(b []byte) (ret int, err os.Error) {
+func (r13 *rotate13) Read(b []byte) (ret int, err error) {
     r, e := r13.source.Read(b)
     for i := 0; i < r; i++ {
         b[i] = rot13(b[i])
@@ -826,17 +813,14 @@ func (r13 *rotate13) Read(b []byte) (ret int, err os.Error) {
 
 func (r13 *rotate13) String() string {
     return r13.source.String()
-}
-// end of rotate13 implementation
-</pre>
+}</pre>
 <p>
 (The <code>rot13</code> function called in <code>Read</code> is trivial and not worth reproducing here.)
 <p>
 To use the new feature, we define a flag:
 <p>
 <pre><!--{{code "progs/cat_rot13.go" `/rot13Flag/`}}
--->var rot13Flag = flag.Bool("rot13", false, "rot13 the input")
-</pre>
+-->var rot13Flag = flag.Bool("rot13", false, "rot13 the input")</pre>
 <p>
 and use it from within a mostly unchanged <code>cat</code> function:
 <p>
@@ -851,20 +835,19 @@ and use it from within a mostly unchanged <code>cat</code> function:
     for {
         switch nr, er := r.Read(buf[:]); {
         case nr < 0:
-            fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r.String(), er.String())
+            fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r, er)
             os.Exit(1)
         case nr == 0: // EOF
             return
         case nr > 0:
             nw, ew := file.Stdout.Write(buf[0:nr])
             if nw != nr {
-                fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", r.String(), ew.String())
+                fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", r, ew)
                 os.Exit(1)
             }
         }
     }
-}
-</pre>
+}</pre>
 <p>
 (We could also do the wrapping in <code>main</code> and leave <code>cat</code> mostly alone, except
 for changing the type of the argument; consider that an exercise.)
@@ -918,8 +901,7 @@ As an example, consider this simple sort algorithm taken from <code>progs/sort.g
             data.Swap(j, j-1)
         }
     }
-}
-</pre>
+}</pre>
 <p>
 The code needs only three methods, which we wrap into sort's <code>Interface</code>:
 <p>
@@ -928,8 +910,7 @@ The code needs only three methods, which we wrap into sort's <code>Interface</co
     Len() int
     Less(i, j int) bool
     Swap(i, j int)
-}
-</pre>
+}</pre>
 <p>
 We can apply <code>Sort</code> to any type that implements <code>Len</code>, <code>Less</code>, and <code>Swap</code>.
 The <code>sort</code> package includes the necessary methods to allow sorting of
@@ -940,8 +921,7 @@ arrays of integers, strings, etc.; here's the code for arrays of <code>int</code
 
 func (p IntSlice) Len() int           { return len(p) }
 func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
-func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
-</pre>
+func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }</pre>
 <p>
 Here we see methods defined for non-<code>struct</code> types.  You can define methods
 for any type you define and name in your package.
@@ -958,8 +938,7 @@ to test that the result is sorted.
     if !sort.IsSorted(a) {
         panic("fail")
     }
-}
-</pre>
+}</pre>
 <p>
 If we have a new type we want to be able to sort, all we need to do is
 to implement the three methods for that type, like this:
@@ -977,8 +956,7 @@ type dayArray struct {
 
 func (p *dayArray) Len() int           { return len(p.data) }
 func (p *dayArray) Less(i, j int) bool { return p.data[i].num < p.data[j].num }
-func (p *dayArray) Swap(i, j int)      { p.data[i], p.data[j] = p.data[j], p.data[i] }
-</pre>
+func (p *dayArray) Swap(i, j int)      { p.data[i], p.data[j] = p.data[j], p.data[i] }</pre>
 <p>
 <p>
 <h2>Printing</h2>
@@ -991,7 +969,7 @@ implements <code>Printf</code>, <code>Fprintf</code>, and so on.
 Within the <code>fmt</code> package, <code>Printf</code> is declared with this signature:
 <p>
 <pre>
-Printf(format string, v ...interface{}) (n int, errno os.Error)
+Printf(format string, v ...interface{}) (n int, errno error)
 </pre>
 <p>
 The token <code>...</code> introduces a variable-length argument list that in C would
@@ -1014,8 +992,7 @@ integer and can do the right thing for you.  The snippet
 <p>
 <pre><!--{{code "progs/print.go" 10 11}}
 -->    var u64 uint64 = 1<<64 - 1
-    fmt.Printf("%d %d\n", u64, int64(u64))
-</pre>
+    fmt.Printf("%d %d\n", u64, int64(u64))</pre>
 <p>
 prints
 <p>
@@ -1033,8 +1010,7 @@ appropriate style, any value, even an array or structure.  The output of
     }
     t := T{77, "Sunset Strip"}
     a := []int{1, 2, 3, 4}
-    fmt.Printf("%v %v %v\n", u64, t, a)
-</pre>
+    fmt.Printf("%v %v %v\n", u64, t, a)</pre>
 <p>
 is
 <p>
@@ -1051,8 +1027,7 @@ to that of the <code>Printf</code> call above.
 <p>
 <pre><!--{{code "progs/print.go" 21 22}}
 -->    fmt.Print(u64, " ", t, " ", a, "\n")
-    fmt.Println(u64, t, a)
-</pre>
+    fmt.Println(u64, t, a)</pre>
 <p>
 If you have your own type you'd like <code>Printf</code> or <code>Print</code> to format,
 just give it a <code>String</code> method that returns a string.  The print
@@ -1073,8 +1048,7 @@ func (t *testType) String() string {
 func main() {
     t := &testType{77, "Sunset Strip"}
     fmt.Println(t)
-}
-</pre>
+}</pre>
 <p>
 Since <code>*testType</code> has a <code>String</code> method, the
 default formatter for that type will use it and produce the output
@@ -1128,6 +1102,21 @@ If the value does not satisfy the interface, <code>ok</code> will be false.
 In this snippet the name <code>Stringer</code> follows the convention that we add ''[e]r''
 to interfaces describing simple method sets like this.
 <p>
+A related interface is that defined by the <code>error</code> builtin type, which is just
+<p>
+<pre>
+type error interface {
+    Error() string
+}
+</pre>
+<p>
+Other than the method name (<code>Error</code> vs. <code>String</code>), this looks like
+a <code>Stringer</code>; the different name guarantees that types that implement <code>Stringer</code>
+don't accidentally satisfy the <code>error</code> interface.
+Naturally, <code>Printf</code> and its relatives recognize the <code>error</code> interface,
+just as they do <code>Stringer</code>,
+so it's trivial to print an error as a string.
+<p>
 One last wrinkle.  To complete the suite, besides <code>Printf</code> etc. and <code>Sprintf</code>
 etc., there are also <code>Fprintf</code> etc.  Unlike in C, <code>Fprintf</code>'s first argument is
 not a file.  Instead, it is a variable of type <code>io.Writer</code>, which is an
@@ -1135,7 +1124,7 @@ interface type defined in the <code>io</code> library:
 <p>
 <pre>
 type Writer interface {
-    Write(p []byte) (n int, err os.Error)
+    Write(p []byte) (n int, err error)
 }
 </pre>
 <p>
@@ -1185,8 +1174,7 @@ func generate(ch chan int) {
     for i := 2; ; i++ {
         ch <- i // Send 'i' to channel 'ch'.
     }
-}
-</pre>
+}</pre>
 <p>
 The <code>generate</code> function sends the sequence 2, 3, 4, 5, ... to its
 argument channel, <code>ch</code>, using the binary communications operator <code><-</code>.
@@ -1208,8 +1196,7 @@ func filter(in, out chan int, prime int) {
             out <- i // Send 'i' to channel 'out'.
         }
     }
-}
-</pre>
+}</pre>
 <p>
 The generator and filters execute concurrently.  Go has
 its own model of process/threads/light-weight processes/coroutines,
@@ -1247,8 +1234,7 @@ together:
         go filter(ch, ch1, prime)
         ch = ch1
     }
-}
-</pre>
+}</pre>
 <p>
 The first line of <code>main</code> creates the initial channel to pass to <code>generate</code>, which it
 then starts up.  As each prime pops out of the channel, a new <code>filter</code>
@@ -1268,8 +1254,7 @@ of <code>generate</code>, from <code>progs/sieve1.go</code>:
         }
     }()
     return ch
-}
-</pre>
+}</pre>
 <p>
 This version does all the setup internally. It creates the output
 channel, launches a goroutine running a function literal, and
@@ -1294,8 +1279,7 @@ The same change can be made to <code>filter</code>:
         }
     }()
     return out
-}
-</pre>
+}</pre>
 <p>
 The <code>sieve</code> function's main loop becomes simpler and clearer as a
 result, and while we're at it let's turn it into a factory too:
@@ -1312,8 +1296,7 @@ result, and while we're at it let's turn it into a factory too:
         }
     }()
     return out
-}
-</pre>
+}</pre>
 <p>
 Now <code>main</code>'s interface to the prime sieve is a channel of primes:
 <p>
@@ -1323,8 +1306,7 @@ Now <code>main</code>'s interface to the prime sieve is a channel of primes:
     for i := 0; i < 100; i++ { // Print the first hundred primes.
         fmt.Println(<-primes)
     }
-}
-</pre>
+}</pre>
 <p>
 <h2>Multiplexing</h2>
 <p>
@@ -1339,8 +1321,7 @@ that will be used for the reply.
 -->type request struct {
     a, b   int
     replyc chan int
-}
-</pre>
+}</pre>
 <p>
 The server will be trivial: it will do simple binary operations on integers.  Here's the
 code that invokes the operation and responds to the request:
@@ -1351,8 +1332,7 @@ code that invokes the operation and responds to the request:
 func run(op binOp, req *request) {
     reply := op(req.a, req.b)
     req.replyc <- reply
-}
-</pre>
+}</pre>
 <p>
 The type declaration makes <code>binOp</code> represent a function taking two integers and
 returning a third.
@@ -1361,24 +1341,46 @@ The <code>server</code> routine loops forever, receiving requests and, to avoid
 a long-running operation, starting a goroutine to do the actual work.
 <p>
 <pre><!--{{code "progs/server.go" `/func.server/` `/^}/`}}
--->func server(op binOp, service chan *request) {
+-->func server(op binOp, service <-chan *request) {
     for {
         req := <-service
         go run(op, req) // don't wait for it
     }
-}
-</pre>
-<p>
-We construct a server in a familiar way, starting it and returning a channel
+}</pre>
+<p>
+There's a new feature in the signature of <code>server</code>: the type of the
+<code>service</code> channel specifies the direction of communication.
+A channel of plain <code>chan</code> type can be used both for sending and receiving.
+However, the type used when declaring a channel can be decorated with an arrow to
+indicate that the channel can be used only to send (<code>chan<-</code>) or to
+receive (<code><-chan</code>) data.
+The arrow points towards or away from the <code>chan</code> to indicate whether data flows into or out of
+the channel.
+In the <code>server</code> function, <code>service <-chan *request</code> is a "receive only" channel
+that the function can use only to <em>read</em> new requests.
+<p>
+We instantiate a server in a familiar way, starting it and returning a channel
 connected to it:
 <p>
 <pre><!--{{code "progs/server.go" `/func.startServer/` `/^}/`}}
--->func startServer(op binOp) chan *request {
+-->func startServer(op binOp) chan<- *request {
     req := make(chan *request)
     go server(op, req)
     return req
-}
-</pre>
+}</pre>
+<p>
+The returned channel is send only, even though the channel was created bidirectionally.
+The read end is passed to <code>server</code>, while the send end is returned
+to the caller of <code>startServer</code>, so the two halves of the channel
+are distinguished, just as we did in <code>startServer</code>.
+<p>
+Bidirectional channels can be assigned to unidirectional channels but not the
+other way around, so if you annotate your channel directions when you declare
+them, such as in function signatures, the type system can help you set up and
+use channels correctly.
+Note that it's pointless to <code>make</code> unidirectional channels, since you can't
+use them to communicate. Their purpose is served by variables assigned from bidirectional channels
+to distinguish the input and output halves.
 <p>
 Here's a simple test.  It starts a server with an addition operator and sends out
 <code>N</code> requests without waiting for the replies.  Only after all the requests are sent
@@ -1402,8 +1404,7 @@ does it check the results.
         }
     }
     fmt.Println("done")
-}
-</pre>
+}</pre>
 <p>
 One annoyance with this program is that it doesn't shut down the server cleanly; when <code>main</code> returns
 there are a number of lingering goroutines blocked on communication.  To solve this,
@@ -1415,13 +1416,12 @@ we can provide a second, <code>quit</code> channel to the server:
     quit = make(chan bool)
     go server(op, service, quit)
     return service, quit
-}
-</pre>
+}</pre>
 <p>
 It passes the quit channel to the <code>server</code> function, which uses it like this:
 <p>
 <pre><!--{{code "progs/server1.go" `/func.server/` `/^}/`}}
--->func server(op binOp, service chan *request, quit chan bool) {
+-->func server(op binOp, service <-chan *request, quit <-chan bool) {
     for {
         select {
         case req := <-service:
@@ -1430,8 +1430,7 @@ It passes the quit channel to the <code>server</code> function, which uses it li
             return
         }
     }
-}
-</pre>
+}</pre>
 <p>
 Inside <code>server</code>, the <code>select</code> statement chooses which of the multiple communications
 listed by its cases can proceed.  If all are blocked, it waits until one can proceed; if
@@ -1444,12 +1443,10 @@ All that's left is to strobe the <code>quit</code> channel
 at the end of main:
 <p>
 <pre><!--{{code "progs/server1.go" `/adder,.quit/`}}
--->    adder, quit := startServer(func(a, b int) int { return a + b })
-</pre>
+-->    adder, quit := startServer(func(a, b int) int { return a + b })</pre>
 ...
 <pre><!--{{code "progs/server1.go" `/quit....true/`}}
--->    quit <- true
-</pre>
+-->    quit <- true</pre>
 <p>
 There's a lot more to Go programming and concurrent programming in general but this
 quick tour should give you some of the basics.
diff --git a/doc/go_tutorial.tmpl b/doc/go_tutorial.tmpl
index c170c25..bde724c 100644
--- a/doc/go_tutorial.tmpl
+++ b/doc/go_tutorial.tmpl
@@ -1,4 +1,8 @@
-<!-- A Tutorial for the Go Programming Language -->
+<!--{
+	"Title": "A Tutorial for the Go Programming Language"
+}-->
+{{donotedit}}
+
 <h2>Introduction</h2>
 <p>
 This document is a tutorial introduction to the basics of the Go programming
@@ -9,11 +13,8 @@ After you've read this tutorial, you should look at
 <a href='/doc/effective_go.html'>Effective Go</a>,
 which digs deeper into how the language is used and
 talks about the style and idioms of programming in Go.
-Also, slides from a 3-day course about Go are available.
-They provide some background and a lot of examples:
-<a href='/doc/GoCourseDay1.pdf'>Day 1</a>,
-<a href='/doc/GoCourseDay2.pdf'>Day 2</a>,
-<a href='/doc/GoCourseDay3.pdf'>Day 3</a>.
+An interactive introduction to Go is available, called
+<a href='http://tour.golang.org/'>A Tour of Go</a>.
 <p>
 The presentation here proceeds through a series of modest programs to illustrate
 key features of the language.  All the programs work (at time of writing) and are
@@ -87,7 +88,7 @@ Here's how to compile and run our program.  With <code>6g</code>, say,
 <pre>
 $ 6g helloworld.go  # compile; object goes into helloworld.6
 $ 6l helloworld.6   # link; output goes into 6.out
-$ 6.out
+$ ./6.out
 Hello, world; or Καλημέρα κόσμε; or こんにちは 世界
 $
 </pre>
@@ -96,7 +97,7 @@ With <code>gccgo</code> it looks a little more traditional.
 <p>
 <pre>
 $ gccgo helloworld.go
-$ a.out
+$ ./a.out
 Hello, world; or Καλημέρα κόσμε; or こんにちは 世界
 $
 </pre>
@@ -288,19 +289,21 @@ Using slices one can write this function (from <code>sum.go</code>):
 Note how the return type (<code>int</code>) is defined for <code>sum</code> by stating it
 after the parameter list.
 <p>
-To call the function, we slice the array.  This intricate call (we'll show
+To call the function, we slice the array.  This code (we'll show
 a simpler way in a moment) constructs
 an array and slices it:
 <p>
 <pre>
-s := sum([3]int{1,2,3}[:])
+x := [3]int{1,2,3}
+s := sum(x[:])
 </pre>
 <p>
 If you are creating a regular array but want the compiler to count the
 elements for you, use <code>...</code> as the array size:
 <p>
 <pre>
-s := sum([...]int{1,2,3}[:])
+x := [...]int{1,2,3}
+s := sum(x[:])
 </pre>
 <p>
 That's fussier than necessary, though.
@@ -418,8 +421,9 @@ assigned to a variable.
 <p>
 <h2>An I/O Package</h2>
 <p>
-Next we'll look at a simple package for doing file I/O with an
-open/close/read/write interface.  Here's the start of <code>file.go</code>:
+Next we'll look at a simple package for doing Unix file I/O with an
+open/close/read/write interface.
+Here's the start of <code>file.go</code>:
 <p>
 {{code "progs/file.go" `/package/` `/^}/`}}
 <p>
@@ -432,6 +436,11 @@ and reproduce the rudiments of its file I/O.
 <p>
 The other item is the low-level, external <code>syscall</code> package, which provides
 a primitive interface to the underlying operating system's calls.
+The <code>syscall</code> package is very system-dependent, and the way it's
+used here works only on Unix-like systems,
+but the general ideas explored here apply broadly.
+(A Windows version is available in
+<a href="progs/file_windows.go"><code>file_windows.go</code></a>.)
 <p>
 Next is a type definition: the <code>type</code> keyword introduces a type declaration,
 in this case a data structure called <code>File</code>.
@@ -470,7 +479,7 @@ composite literal, as is done here in the <code>return</code> statement from <co
 <p>
 We can use the factory to construct some familiar, exported variables of type <code>*File</code>:
 <p>
-{{code "progs/file.go" `/var/` `/^.$/`}}
+{{code "progs/file.go" `/var/` `/^\)/`}}
 <p>
 The <code>newFile</code> function was not exported because it's internal. The proper,
 exported factory to use is <code>OpenFile</code> (we'll explain that name in a moment):
@@ -490,11 +499,13 @@ to see that).  Finally, <code>OpenFile</code> returns two values: a pointer to t
 and the error.  If <code>syscall.Open</code> fails, the file descriptor <code>r</code> will
 be negative and <code>newFile</code> will return <code>nil</code>.
 <p>
-About those errors:  The <code>os</code> library includes a general notion of an error.
+About those errors:  The Go language includes a general notion of an error:
+a pre-defined type <code>error</code> with properties (described below)
+that make it a good basis for representing and handling errors.
 It's a good idea to use its facility in your own interfaces, as we do here, for
 consistent error handling throughout Go code.   In <code>Open</code> we use a
 conversion to translate Unix's integer <code>errno</code> value into the integer type
-<code>os.Errno</code>, which implements <code>os.Error</code>.
+<code>os.Errno</code>, which is an implementation of <code>error</code>
 <p>
 Why <code>OpenFile</code> and not <code>Open</code>? To mimic Go's <code>os</code> package, which
 our exercise is emulating. The <code>os</code> package takes the opportunity
@@ -527,7 +538,7 @@ array, not just for <code>structs</code>.   We'll see an example with arrays lat
 The <code>String</code> method is so called because of a printing convention we'll
 describe later.
 <p>
-The methods use the public variable <code>os.EINVAL</code> to return the (<code>os.Error</code>
+The methods use the public variable <code>os.EINVAL</code> to return the (<code>error</code>
 version of the) Unix error code <code>EINVAL</code>.  The <code>os</code> library defines a standard
 set of such error values.
 <p>
@@ -547,7 +558,7 @@ Now we can compile and run the program. On Unix, this would be the result:
 $ 6g file.go                       # compile file package
 $ 6g helloworld3.go                # compile main package
 $ 6l -o helloworld3 helloworld3.6  # link - no need to mention "file"
-$ helloworld3
+$ ./helloworld3
 hello, world
 can't open file; err=No such file or directory
 $
@@ -692,7 +703,7 @@ implements <code>Printf</code>, <code>Fprintf</code>, and so on.
 Within the <code>fmt</code> package, <code>Printf</code> is declared with this signature:
 <p>
 <pre>
-Printf(format string, v ...interface{}) (n int, errno os.Error)
+Printf(format string, v ...interface{}) (n int, errno error)
 </pre>
 <p>
 The token <code>...</code> introduces a variable-length argument list that in C would
@@ -801,6 +812,21 @@ If the value does not satisfy the interface, <code>ok</code> will be false.
 In this snippet the name <code>Stringer</code> follows the convention that we add ''[e]r''
 to interfaces describing simple method sets like this.
 <p>
+A related interface is that defined by the <code>error</code> builtin type, which is just
+<p>
+<pre>
+type error interface {
+    Error() string
+}
+</pre>
+<p>
+Other than the method name (<code>Error</code> vs. <code>String</code>), this looks like
+a <code>Stringer</code>; the different name guarantees that types that implement <code>Stringer</code>
+don't accidentally satisfy the <code>error</code> interface.
+Naturally, <code>Printf</code> and its relatives recognize the <code>error</code> interface,
+just as they do <code>Stringer</code>,
+so it's trivial to print an error as a string.
+<p>
 One last wrinkle.  To complete the suite, besides <code>Printf</code> etc. and <code>Sprintf</code>
 etc., there are also <code>Fprintf</code> etc.  Unlike in C, <code>Fprintf</code>'s first argument is
 not a file.  Instead, it is a variable of type <code>io.Writer</code>, which is an
@@ -808,7 +834,7 @@ interface type defined in the <code>io</code> library:
 <p>
 <pre>
 type Writer interface {
-    Write(p []byte) (n int, err os.Error)
+    Write(p []byte) (n int, err error)
 }
 </pre>
 <p>
@@ -951,11 +977,35 @@ a long-running operation, starting a goroutine to do the actual work.
 <p>
 {{code "progs/server.go" `/func.server/` `/^}/`}}
 <p>
-We construct a server in a familiar way, starting it and returning a channel
+There's a new feature in the signature of <code>server</code>: the type of the
+<code>service</code> channel specifies the direction of communication.
+A channel of plain <code>chan</code> type can be used both for sending and receiving.
+However, the type used when declaring a channel can be decorated with an arrow to
+indicate that the channel can be used only to send (<code>chan<-</code>) or to
+receive (<code><-chan</code>) data.
+The arrow points towards or away from the <code>chan</code> to indicate whether data flows into or out of
+the channel.
+In the <code>server</code> function, <code>service <-chan *request</code> is a "receive only" channel
+that the function can use only to <em>read</em> new requests.
+<p>
+We instantiate a server in a familiar way, starting it and returning a channel
 connected to it:
 <p>
 {{code "progs/server.go" `/func.startServer/` `/^}/`}}
 <p>
+The returned channel is send only, even though the channel was created bidirectionally.
+The read end is passed to <code>server</code>, while the send end is returned
+to the caller of <code>startServer</code>, so the two halves of the channel
+are distinguished, just as we did in <code>startServer</code>.
+<p>
+Bidirectional channels can be assigned to unidirectional channels but not the
+other way around, so if you annotate your channel directions when you declare
+them, such as in function signatures, the type system can help you set up and
+use channels correctly.
+Note that it's pointless to <code>make</code> unidirectional channels, since you can't
+use them to communicate. Their purpose is served by variables assigned from bidirectional channels
+to distinguish the input and output halves.
+<p>
 Here's a simple test.  It starts a server with an addition operator and sends out
 <code>N</code> requests without waiting for the replies.  Only after all the requests are sent
 does it check the results.
diff --git a/doc/godocs.js b/doc/godocs.js
index 946c4c3..3b8625a 100644
--- a/doc/godocs.js
+++ b/doc/godocs.js
@@ -24,6 +24,7 @@ function godocs_onload() {
   godocs_bindSearchEvents();
   godocs_generateTOC();
   godocs_addTopLinks();
+  godocs_bindExampleToggles();
 }
 
 function godocs_bindSearchEvents() {
@@ -56,6 +57,7 @@ function godocs_bindSearchEvents() {
  * links.  "Decorates" the element with id=="nav" with this table of contents.
  */
 function godocs_generateTOC() {
+  if (document.getElementById('manual-nav')) { return; }
   var navbar = document.getElementById('nav');
   if (!navbar) { return; }
 
@@ -64,44 +66,32 @@ function godocs_generateTOC() {
   var i;
   for (i = 0; i < navbar.parentNode.childNodes.length; i++) {
     var node = navbar.parentNode.childNodes[i];
-    if ((node.tagName == 'h2') || (node.tagName == 'H2')) {
-      if (!node.id) {
-        node.id = 'tmp_' + i;
-      }
-      var text = godocs_nodeToText(node);
-      if (!text) { continue; }
-
-      var textNode = document.createTextNode(text);
-
-      var link = document.createElement('a');
-      link.href = '#' + node.id;
-      link.appendChild(textNode);
-
-      // Then create the item itself
-      var item = document.createElement('dt');
-
-      item.appendChild(link);
-      toc_items.push(item);
+    if ((node.tagName != 'h2') && (node.tagName != 'H2') &&
+        (node.tagName != 'h3') && (node.tagName != 'H3')) {
+      continue;
     }
-    if ((node.tagName == 'h3') || (node.tagName == 'H3')) {
-      if (!node.id) {
-        node.id = 'tmp_' + i;
-      }
-      var text = godocs_nodeToText(node);
-      if (!text) { continue; }
-
-      var textNode = document.createTextNode(text);
+    if (!node.id) {
+      node.id = 'tmp_' + i;
+    }
+    var text = godocs_nodeToText(node);
+    if (!text) { continue; }
 
-      var link = document.createElement('a');
-      link.href = '#' + node.id;
-      link.appendChild(textNode);
+    var textNode = document.createTextNode(text);
 
-      // Then create the item itself
-      var item = document.createElement('dd');
+    var link = document.createElement('a');
+    link.href = '#' + node.id;
+    link.appendChild(textNode);
 
-      item.appendChild(link);
-      toc_items.push(item);
+    // Then create the item itself
+    var item;
+    if ((node.tagName == 'h2') || (node.tagName == 'H2')) {
+      item = document.createElement('dt');
+    } else { // h3
+      item = document.createElement('dd');
     }
+
+    item.appendChild(link);
+    toc_items.push(item);
   }
 
   if (toc_items.length <= 1) { return; }
@@ -188,3 +178,23 @@ function godocs_addTopLinks() {
     headers[i].appendChild(span);
   }
 }
+
+function godocs_bindExampleToggles() {
+  var examples = document.getElementsByClassName("example");
+  for (var i = 0; i < examples.length; i++) {
+    var eg = examples[i];
+    godocs_bindExampleToggle(eg);
+  }
+}
+function godocs_bindExampleToggle(eg) {
+  var heading = eg.getElementsByClassName("exampleHeading");
+  for (var i = 0; i < heading.length; i++) {
+    bindEvent(heading[i], "click", function() {
+      if (eg.className == "example") {
+        eg.className = "exampleVisible";
+      } else {
+        eg.className = "example";
+      }
+    });
+  }
+}
diff --git a/doc/install.html b/doc/install.html
index 21a6636..61a90da 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -1,4 +1,6 @@
-<!-- Getting Started -->
+<!--{
+	"Title": "Getting Started"
+}-->
 
 <h2 id="introduction">Introduction</h2>
 
@@ -61,7 +63,7 @@ support for segmented stacks, and a strong goroutine implementation.
 </p>
 
 <p>
-The compilers can target the FreeBSD, Linux,
+The compilers can target the FreeBSD, Linux, OpenBSD
 and OS X (a.k.a. Darwin) operating systems.
 (A port to Microsoft Windows is in progress but incomplete.  See the 
 <a href="http://code.google.com/p/go/wiki/WindowsPort">Windows Port</a>
@@ -88,7 +90,7 @@ and
 
 <p>On OS X, they can be
 installed as part of
-<a href="http://developer.apple.com/TOOLS/Xcode/">Xcode</a>. 
+<a href="http://developer.apple.com/Xcode/">Xcode</a>. 
 </p>
 
 <p>On Ubuntu/Debian, use <code>sudo apt-get install bison gawk gcc libc6-dev
@@ -102,7 +104,7 @@ also need the <code>libc6-dev-i386</code> package.
 To perform the next step you must have Mercurial installed. (Check that you  have an <code>hg</code> command.) This suffices to install Mercurial on most systems:
 </p>
 <pre>
-sudo easy_install mercurial
+sudo easy_install mercurial==2.0
 </pre>
 (On Ubuntu/Debian, you might try <code>apt-get install python-setuptools
 python-dev build-essential</code> first. The Mercurial in your distribution's
@@ -118,7 +120,7 @@ Mercurial versions 1.7.x and up require the configuration of
 (CAs). Error messages of the form:
 </p>
 <pre>
-warning: go.googlecode.com certificate with fingerprint b1:af: ... bc not verified (check hostfingerprints or web.cacerts config setting)
+warning: code.google.com certificate with fingerprint b1:af: ... bc not verified (check hostfingerprints or web.cacerts config setting)
 </pre>
 <p>
 when using Mercurial indicate that the CAs are missing.
@@ -136,7 +138,7 @@ and make sure the <code>go</code> directory does not exist.
 Then check out the repository:</p>
 
 <pre>
-$ hg clone -u release https://go.googlecode.com/hg/ go
+$ hg clone -u release https://code.google.com/p/go
 </pre>
 
 <h2 id="install">Install Go</h2>
@@ -257,7 +259,8 @@ the process of building and testing Go programs.
 <h2 id="next">What's next</h2>
 
 <p>
-Start by reading the <a href="go_tutorial.html">Go Tutorial</a>.
+Start by taking <a href="http://code.google.com/p/go-tour/">A Tour of Go</a>
+or reading the <a href="go_tutorial.html">Go Tutorial</a>.
 </p>
 
 <p>
@@ -372,9 +375,9 @@ to override the defaults.
 	<code>$GOHOSTARCH</code> respectively (described below).
 
 	<p>
-	Choices for <code>$GOOS</code> are <code>linux</code>,
-	<code>freebsd</code>,
+	Choices for <code>$GOOS</code> are
 	<code>darwin</code> (Mac OS X 10.5 or 10.6),
+	<code>freebsd</code>, <code>linux</code>, <code>openbsd</code>,
 	and <code>windows</code> (Windows, an incomplete port).
 	Choices for <code>$GOARCH</code> are <code>amd64</code> (64-bit x86, the most mature port),
 	<code>386</code> (32-bit x86), and
@@ -406,6 +409,12 @@ to override the defaults.
 	<td></td><td><code>linux</code></td> <td><code>arm</code></td> <td><i>incomplete</i></td>
 	</tr>
 	<tr>
+	<td></td><td><code>openbsd</code></td> <td><code>386</code></td>
+	</tr>
+	<tr>
+	<td></td><td><code>openbsd</code></td> <td><code>amd64</code></td>
+	</tr>
+	<tr>
 	<td></td><td><code>windows</code></td> <td><code>386</code></td> <td><i>incomplete</i></td>
 	</tr>
 	</table>
diff --git a/doc/makehtml b/doc/makehtml
index 69e8e2b..8a02913 100755
--- a/doc/makehtml
+++ b/doc/makehtml
@@ -5,8 +5,8 @@
 
 set -e
 
-TMPL=${1:-go_tutorial.tmpl}		# input file
-HTML=$(basename $TMPL .tmpl).html		# output file (basename)
+TMPL=${1:-go_tutorial.tmpl}                        # input file
+HTML=$(dirname $TMPL)/$(basename $TMPL .tmpl).html # output file
 
 if ! test -w $HTML
 then
diff --git a/doc/playground.html b/doc/playground.html
index 01d3adc..746b29c 100644
--- a/doc/playground.html
+++ b/doc/playground.html
@@ -1,4 +1,6 @@
-<!-- About the Go Playground -->
+<!--{
+	"Title": "About the Go Playground"
+}-->
 
 <div class="left-column">
 <p>
diff --git a/doc/progs/cat.go b/doc/progs/cat.go
index 9f0b8d4..79ad015 100644
--- a/doc/progs/cat.go
+++ b/doc/progs/cat.go
@@ -17,13 +17,13 @@ func cat(f *file.File) {
 	for {
 		switch nr, er := f.Read(buf[:]); true {
 		case nr < 0:
-			fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", f.String(), er.String())
+			fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", f, er)
 			os.Exit(1)
 		case nr == 0: // EOF
 			return
 		case nr > 0:
 			if nw, ew := file.Stdout.Write(buf[0:nr]); nw != nr {
-				fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", f.String(), ew.String())
+				fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", f, ew)
 				os.Exit(1)
 			}
 		}
diff --git a/doc/progs/cat_rot13.go b/doc/progs/cat_rot13.go
index 0eefe7c..c8584ed 100644
--- a/doc/progs/cat_rot13.go
+++ b/doc/progs/cat_rot13.go
@@ -24,7 +24,7 @@ func rot13(b byte) byte {
 }
 
 type reader interface {
-	Read(b []byte) (ret int, err os.Error)
+	Read(b []byte) (ret int, err error)
 	String() string
 }
 
@@ -36,7 +36,7 @@ func newRotate13(source reader) *rotate13 {
 	return &rotate13{source}
 }
 
-func (r13 *rotate13) Read(b []byte) (ret int, err os.Error) {
+func (r13 *rotate13) Read(b []byte) (ret int, err error) {
 	r, e := r13.source.Read(b)
 	for i := 0; i < r; i++ {
 		b[i] = rot13(b[i])
@@ -47,7 +47,8 @@ func (r13 *rotate13) Read(b []byte) (ret int, err os.Error) {
 func (r13 *rotate13) String() string {
 	return r13.source.String()
 }
-// end of rotate13 implementation
+
+// end of rotate13 implementation OMIT
 
 func cat(r reader) {
 	const NBUF = 512
@@ -59,14 +60,14 @@ func cat(r reader) {
 	for {
 		switch nr, er := r.Read(buf[:]); {
 		case nr < 0:
-			fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r.String(), er.String())
+			fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n", r, er)
 			os.Exit(1)
 		case nr == 0: // EOF
 			return
 		case nr > 0:
 			nw, ew := file.Stdout.Write(buf[0:nr])
 			if nw != nr {
-				fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", r.String(), ew.String())
+				fmt.Fprintf(os.Stderr, "cat: error writing from %s: %s\n", r, ew)
 				os.Exit(1)
 			}
 		}
diff --git a/doc/progs/defer.go b/doc/progs/defer.go
new file mode 100644
index 0000000..2e11020
--- /dev/null
+++ b/doc/progs/defer.go
@@ -0,0 +1,64 @@
+// Copyright 2011 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 file contains the code snippets included in "Defer, Panic, and Recover."
+
+package main
+
+import (
+	"fmt"
+	"io"
+	"os"
+)
+
+func a() {
+	i := 0
+	defer fmt.Println(i)
+	i++
+	return
+}
+
+// STOP OMIT
+
+func b() {
+	for i := 0; i < 4; i++ {
+		defer fmt.Print(i)
+	}
+}
+
+// STOP OMIT
+
+func c() (i int) {
+	defer func() { i++ }()
+	return 1
+}
+
+// STOP OMIT
+
+// Initial version.
+func CopyFile(dstName, srcName string) (written int64, err error) {
+	src, err := os.Open(srcName)
+	if err != nil {
+		return
+	}
+
+	dst, err := os.Create(dstName)
+	if err != nil {
+		return
+	}
+
+	written, err = io.Copy(dst, src)
+	dst.Close()
+	src.Close()
+	return
+}
+
+// STOP OMIT
+
+func main() {
+	a()
+	b()
+	fmt.Println()
+	fmt.Println(c())
+}
diff --git a/doc/progs/defer2.go b/doc/progs/defer2.go
new file mode 100644
index 0000000..cad66b0
--- /dev/null
+++ b/doc/progs/defer2.go
@@ -0,0 +1,58 @@
+// Copyright 2011 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 file contains the code snippets included in "Defer, Panic, and Recover."
+
+package main
+
+import "fmt"
+import "io" // OMIT
+import "os" // OMIT
+
+func main() {
+	f()
+	fmt.Println("Returned normally from f.")
+}
+
+func f() {
+	defer func() {
+		if r := recover(); r != nil {
+			fmt.Println("Recovered in f", r)
+		}
+	}()
+	fmt.Println("Calling g.")
+	g(0)
+	fmt.Println("Returned normally from g.")
+}
+
+func g(i int) {
+	if i > 3 {
+		fmt.Println("Panicking!")
+		panic(fmt.Sprintf("%v", i))
+	}
+	defer fmt.Println("Defer in g", i)
+	fmt.Println("Printing in g", i)
+	g(i + 1)
+}
+
+// STOP OMIT
+
+// Revised version.
+func CopyFile(dstName, srcName string) (written int64, err error) {
+	src, err := os.Open(srcName)
+	if err != nil {
+		return
+	}
+	defer src.Close()
+
+	dst, err := os.Create(dstName)
+	if err != nil {
+		return
+	}
+	defer dst.Close()
+
+	return io.Copy(dst, src)
+}
+
+// STOP OMIT
diff --git a/doc/progs/echo.go b/doc/progs/echo.go
index 3260edd..432e808 100644
--- a/doc/progs/echo.go
+++ b/doc/progs/echo.go
@@ -5,8 +5,8 @@
 package main
 
 import (
-	"os"
 	"flag" // command line option parser
+	"os"
 )
 
 var omitNewline = flag.Bool("n", false, "don't print final newline")
diff --git a/doc/progs/eff_qr.go b/doc/progs/eff_qr.go
index 5d1fd38..de96a02 100644
--- a/doc/progs/eff_qr.go
+++ b/doc/progs/eff_qr.go
@@ -2,9 +2,9 @@ package main
 
 import (
 	"flag"
-	"http"
 	"log"
-	"template"
+	"net/http"
+	"text/template"
 )
 
 var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
diff --git a/doc/progs/error.go b/doc/progs/error.go
new file mode 100644
index 0000000..ffa7ec1
--- /dev/null
+++ b/doc/progs/error.go
@@ -0,0 +1,120 @@
+// Copyright 2011 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 file contains the code snippets included in "Error Handling and Go."
+
+package main
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"log"
+	"net"
+	"os"
+	"time"
+)
+
+type File struct{}
+
+func Open(name string) (file *File, err error)
+
+func openFile() { // OMIT
+	f, err := os.Open("filename.ext")
+	if err != nil {
+		log.Fatal(err)
+	}
+	// do something with the open *File f
+	// STOP OMIT
+	_ = f
+}
+
+// errorString is a trivial implementation of error.
+type errorString struct {
+	s string
+}
+
+func (e *errorString) Error() string {
+	return e.s
+}
+
+// STOP OMIT
+
+// New returns an error that formats as the given text.
+func New(text string) error {
+	return &errorString{text}
+}
+
+// STOP OMIT
+
+func Sqrt(f float64) (float64, error) {
+	if f < 0 {
+		return 0, errors.New("math: square root of negative number")
+	}
+	// implementation
+	return 0, nil // OMIT
+}
+
+// STOP OMIT
+
+func printErr() (int, error) { // OMIT
+	f, err := Sqrt(-1)
+	if err != nil {
+		fmt.Println(err)
+	}
+	// STOP OMIT
+	// fmtError OMIT
+	if f < 0 {
+		return 0, fmt.Errorf("math: square root of negative number %g", f)
+	}
+	// STOP OMIT
+	return 0, nil
+}
+
+type NegativeSqrtError float64
+
+func (f NegativeSqrtError) Error() string {
+	return fmt.Sprintf("math: square root of negative number %g", float64(f))
+}
+
+// STOP OMIT
+
+type SyntaxError struct {
+	msg    string // description of error
+	Offset int64  // error occurred after reading Offset bytes
+}
+
+func (e *SyntaxError) Error() string { return e.msg }
+
+// STOP OMIT
+
+func decodeError(dec *json.Decoder, val struct{}) error { // OMIT
+	var f os.FileInfo // OMIT
+	if err := dec.Decode(&val); err != nil {
+		if serr, ok := err.(*json.SyntaxError); ok {
+			line, col := findLine(f, serr.Offset)
+			return fmt.Errorf("%s:%d:%d: %v", f.Name(), line, col, err)
+		}
+		return err
+	}
+	// STOP OMIT
+	return nil
+}
+
+func findLine(os.FileInfo, int64) (int, int)
+
+func netError(err error) { // OMIT
+	for { // OMIT
+		if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
+			time.Sleep(1e9)
+			continue
+		}
+		if err != nil {
+			log.Fatal(err)
+		}
+		// STOP OMIT
+	}
+}
+
+func main() {}
diff --git a/doc/progs/error2.go b/doc/progs/error2.go
new file mode 100644
index 0000000..2b0e0c3
--- /dev/null
+++ b/doc/progs/error2.go
@@ -0,0 +1,54 @@
+// Copyright 2011 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 file contains the code snippets included in "Error Handling and Go."
+
+package main
+
+import (
+	"net/http"
+	"text/template"
+)
+
+func init() {
+	http.HandleFunc("/view", viewRecord)
+}
+
+func viewRecord(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+	key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
+	record := new(Record)
+	if err := datastore.Get(c, key, record); err != nil {
+		http.Error(w, err.Error(), 500)
+		return
+	}
+	if err := viewTemplate.Execute(w, record); err != nil {
+		http.Error(w, err.Error(), 500)
+	}
+}
+
+// STOP OMIT
+
+type ap struct{}
+
+func (ap) NewContext(*http.Request) *ctx { return nil }
+
+type ctx struct{}
+
+func (*ctx) Errorf(string, ...interface{}) {}
+
+var appengine ap
+
+type ds struct{}
+
+func (ds) NewKey(*ctx, string, string, int, *int) string { return "" }
+func (ds) Get(*ctx, string, *Record) error               { return nil }
+
+var datastore ds
+
+type Record struct{}
+
+var viewTemplate *template.Template
+
+func main() {}
diff --git a/doc/progs/error3.go b/doc/progs/error3.go
new file mode 100644
index 0000000..e4e57e0
--- /dev/null
+++ b/doc/progs/error3.go
@@ -0,0 +1,63 @@
+// Copyright 2011 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 file contains the code snippets included in "Error Handling and Go."
+
+package main
+
+import (
+	"net/http"
+	"text/template"
+)
+
+func init() {
+	http.Handle("/view", appHandler(viewRecord))
+}
+
+// STOP OMIT
+
+func viewRecord(w http.ResponseWriter, r *http.Request) error {
+	c := appengine.NewContext(r)
+	key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
+	record := new(Record)
+	if err := datastore.Get(c, key, record); err != nil {
+		return err
+	}
+	return viewTemplate.Execute(w, record)
+}
+
+// STOP OMIT
+
+type appHandler func(http.ResponseWriter, *http.Request) error
+
+func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if err := fn(w, r); err != nil {
+		http.Error(w, err.Error(), 500)
+	}
+}
+
+// STOP OMIT
+
+type ap struct{}
+
+func (ap) NewContext(*http.Request) *ctx { return nil }
+
+type ctx struct{}
+
+func (*ctx) Errorf(string, ...interface{}) {}
+
+var appengine ap
+
+type ds struct{}
+
+func (ds) NewKey(*ctx, string, string, int, *int) string { return "" }
+func (ds) Get(*ctx, string, *Record) error               { return nil }
+
+var datastore ds
+
+type Record struct{}
+
+var viewTemplate *template.Template
+
+func main() {}
diff --git a/doc/progs/error4.go b/doc/progs/error4.go
new file mode 100644
index 0000000..8f35cf7
--- /dev/null
+++ b/doc/progs/error4.go
@@ -0,0 +1,74 @@
+// Copyright 2011 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 file contains the code snippets included in "Error Handling and Go."
+
+package main
+
+import (
+	"net/http"
+	"text/template"
+)
+
+type appError struct {
+	Error   error
+	Message string
+	Code    int
+}
+
+// STOP OMIT
+
+type appHandler func(http.ResponseWriter, *http.Request) *appError
+
+func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if e := fn(w, r); e != nil { // e is *appError, not os.Error.
+		c := appengine.NewContext(r)
+		c.Errorf("%v", e.Error)
+		http.Error(w, e.Message, e.Code)
+	}
+}
+
+// STOP OMIT
+
+func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
+	c := appengine.NewContext(r)
+	key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
+	record := new(Record)
+	if err := datastore.Get(c, key, record); err != nil {
+		return &appError{err, "Record not found", 404}
+	}
+	if err := viewTemplate.Execute(w, record); err != nil {
+		return &appError{err, "Can't display record", 500}
+	}
+	return nil
+}
+
+// STOP OMIT
+
+func init() {
+	http.Handle("/view", appHandler(viewRecord))
+}
+
+type ap struct{}
+
+func (ap) NewContext(*http.Request) *ctx { return nil }
+
+type ctx struct{}
+
+func (*ctx) Errorf(string, ...interface{}) {}
+
+var appengine ap
+
+type ds struct{}
+
+func (ds) NewKey(*ctx, string, string, int, *int) string { return "" }
+func (ds) Get(*ctx, string, *Record) error               { return nil }
+
+var datastore ds
+
+type Record struct{}
+
+var viewTemplate *template.Template
+
+func main() {}
diff --git a/doc/progs/file.go b/doc/progs/file.go
index 2875ce7..e1aadaa 100644
--- a/doc/progs/file.go
+++ b/doc/progs/file.go
@@ -27,11 +27,8 @@ var (
 	Stderr = newFile(syscall.Stderr, "/dev/stderr")
 )
 
-func OpenFile(name string, mode int, perm uint32) (file *File, err os.Error) {
-	r, e := syscall.Open(name, mode, perm)
-	if e != 0 {
-		err = os.Errno(e)
-	}
+func OpenFile(name string, mode int, perm uint32) (file *File, err error) {
+	r, err := syscall.Open(name, mode, perm)
 	return newFile(r, name), err
 }
 
@@ -42,45 +39,36 @@ const (
 	O_TRUNC  = syscall.O_TRUNC
 )
 
-func Open(name string) (file *File, err os.Error) {
+func Open(name string) (file *File, err error) {
 	return OpenFile(name, O_RDONLY, 0)
 }
 
-func Create(name string) (file *File, err os.Error) {
+func Create(name string) (file *File, err error) {
 	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
 }
 
-func (file *File) Close() os.Error {
+func (file *File) Close() error {
 	if file == nil {
 		return os.EINVAL
 	}
-	e := syscall.Close(file.fd)
+	err := syscall.Close(file.fd)
 	file.fd = -1 // so it can't be closed again
-	if e != 0 {
-		return os.Errno(e)
-	}
-	return nil
+	return err
 }
 
-func (file *File) Read(b []byte) (ret int, err os.Error) {
+func (file *File) Read(b []byte) (ret int, err error) {
 	if file == nil {
 		return -1, os.EINVAL
 	}
-	r, e := syscall.Read(file.fd, b)
-	if e != 0 {
-		err = os.Errno(e)
-	}
+	r, err := syscall.Read(file.fd, b)
 	return int(r), err
 }
 
-func (file *File) Write(b []byte) (ret int, err os.Error) {
+func (file *File) Write(b []byte) (ret int, err error) {
 	if file == nil {
 		return -1, os.EINVAL
 	}
-	r, e := syscall.Write(file.fd, b)
-	if e != 0 {
-		err = os.Errno(e)
-	}
+	r, err := syscall.Write(file.fd, b)
 	return int(r), err
 }
 
diff --git a/doc/progs/file_windows.go b/doc/progs/file_windows.go
index bfbac75..e6a3550 100644
--- a/doc/progs/file_windows.go
+++ b/doc/progs/file_windows.go
@@ -27,11 +27,8 @@ var (
 	Stderr = newFile(syscall.Stderr, "/dev/stderr")
 )
 
-func OpenFile(name string, mode int, perm uint32) (file *File, err os.Error) {
-	r, e := syscall.Open(name, mode, perm)
-	if e != 0 {
-		err = os.Errno(e)
-	}
+func OpenFile(name string, mode int, perm uint32) (file *File, err error) {
+	r, err := syscall.Open(name, mode, perm)
 	return newFile(r, name), err
 }
 
@@ -42,45 +39,36 @@ const (
 	O_TRUNC  = syscall.O_TRUNC
 )
 
-func Open(name string) (file *File, err os.Error) {
+func Open(name string) (file *File, err error) {
 	return OpenFile(name, O_RDONLY, 0)
 }
 
-func Create(name string) (file *File, err os.Error) {
+func Create(name string) (file *File, err error) {
 	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
 }
 
-func (file *File) Close() os.Error {
+func (file *File) Close() error {
 	if file == nil {
 		return os.EINVAL
 	}
-	e := syscall.Close(file.fd)
+	err := syscall.Close(file.fd)
 	file.fd = syscall.InvalidHandle // so it can't be closed again
-	if e != 0 {
-		return os.Errno(e)
-	}
-	return nil
+	return err
 }
 
-func (file *File) Read(b []byte) (ret int, err os.Error) {
+func (file *File) Read(b []byte) (ret int, err error) {
 	if file == nil {
 		return -1, os.EINVAL
 	}
-	r, e := syscall.Read(file.fd, b)
-	if e != 0 {
-		err = os.Errno(e)
-	}
+	r, err := syscall.Read(file.fd, b)
 	return int(r), err
 }
 
-func (file *File) Write(b []byte) (ret int, err os.Error) {
+func (file *File) Write(b []byte) (ret int, err error) {
 	if file == nil {
 		return -1, os.EINVAL
 	}
-	r, e := syscall.Write(file.fd, b)
-	if e != 0 {
-		err = os.Errno(e)
-	}
+	r, err := syscall.Write(file.fd, b)
 	return int(r), err
 }
 
diff --git a/doc/progs/go1.go b/doc/progs/go1.go
new file mode 100644
index 0000000..0348aa3
--- /dev/null
+++ b/doc/progs/go1.go
@@ -0,0 +1,208 @@
+// Copyright 2011 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 file contains examples to embed in the Go 1 release notes document.
+
+package main
+
+import (
+	"errors"
+	"flag"
+	"fmt"
+	"log"
+	"testing"
+	"time"
+	"unicode"
+)
+
+func main() {
+	flag.Parse()
+	stringAppend()
+	mapDelete()
+	mapIteration()
+	multipleAssignment()
+	structEquality()
+	compositeLiterals()
+	runeType()
+	errorExample()
+	timePackage()
+}
+
+var timeout = flag.Duration("timeout", 30*time.Second, "how long to wait for completion")
+
+func mapDelete() {
+	m := map[string]int{"7": 7, "23": 23}
+	k := "7"
+	delete(m, k)
+	if m["7"] != 0 || m["23"] != 23 {
+		log.Fatal("mapDelete:", m)
+	}
+}
+
+func stringAppend() {
+	greeting := []byte{}
+	greeting = append(greeting, []byte("hello ")...)
+	greeting = append(greeting, "world"...)
+	if string(greeting) != "hello world" {
+		log.Fatal("stringAppend: ", string(greeting))
+	}
+}
+
+func mapIteration() {
+	m := map[string]int{"Sunday": 0, "Monday": 1}
+	for name, value := range m {
+		// This loop should not assume Sunday will be visited first.
+		f(name, value)
+	}
+}
+
+func f(string, int) {
+}
+
+func assert(t bool) {
+	if !t {
+		log.Panic("assertion fail")
+	}
+}
+
+func multipleAssignment() {
+	sa := []int{1, 2, 3}
+	i := 0
+	i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2
+
+	sb := []int{1, 2, 3}
+	j := 0
+	sb[j], j = 2, 1 // sets sb[0] = 2, j = 1
+
+	sc := []int{1, 2, 3}
+	sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)
+
+	assert(i == 1 && sa[0] == 2)
+	assert(j == 1 && sb[0] == 2)
+	assert(sc[0] == 2)
+}
+
+func structEquality() {
+	type Day struct {
+		long  string
+		short string
+	}
+	Christmas := Day{"Christmas", "XMas"}
+	Thanksgiving := Day{"Thanksgiving", "Turkey"}
+	holiday := map[Day]bool{
+		Christmas:    true,
+		Thanksgiving: true,
+	}
+	fmt.Printf("Christmas is a holiday: %t\n", holiday[Christmas])
+}
+
+func compositeLiterals() {
+	type Date struct {
+		month string
+		day   int
+	}
+	// Struct values, fully qualified; always legal.
+	holiday1 := []Date{
+		Date{"Feb", 14},
+		Date{"Nov", 11},
+		Date{"Dec", 25},
+	}
+	// Struct values, type name elided; always legal.
+	holiday2 := []Date{
+		{"Feb", 14},
+		{"Nov", 11},
+		{"Dec", 25},
+	}
+	// Pointers, fully qualified, always legal.
+	holiday3 := []*Date{
+		&Date{"Feb", 14},
+		&Date{"Nov", 11},
+		&Date{"Dec", 25},
+	}
+	// Pointers, type name elided; legal in Go 1.
+	holiday4 := []*Date{
+		{"Feb", 14},
+		{"Nov", 11},
+		{"Dec", 25},
+	}
+	// STOP OMIT
+	_, _, _, _ = holiday1, holiday2, holiday3, holiday4
+}
+
+func runeType() {
+	// STARTRUNE OMIT
+	delta := 'δ' // delta has type rune.
+	var DELTA rune
+	DELTA = unicode.ToUpper(delta)
+	epsilon := unicode.ToLower(DELTA + 1)
+	if epsilon != 'δ'+1 {
+		log.Fatal("inconsistent casing for Greek")
+	}
+	// ENDRUNE OMIT
+}
+
+// START ERROR EXAMPLE OMIT
+type SyntaxError struct {
+	File    string
+	Line    int
+	Message string
+}
+
+func (se *SyntaxError) Error() string {
+	return fmt.Sprintf("%s:%d: %s", se.File, se.Line, se.Message)
+}
+
+// END ERROR EXAMPLE OMIT
+
+func errorExample() {
+	var ErrSyntax = errors.New("syntax error")
+	_ = ErrSyntax
+	se := &SyntaxError{"file", 7, "error"}
+	got := fmt.Sprint(se)
+	const expect = "file:7: error"
+	if got != expect {
+		log.Fatalf("errorsPackage: expected %q got %q", expect, got)
+	}
+}
+
+// sleepUntil sleeps until the specified time. It returns immediately if it's too late.
+func sleepUntil(wakeup time.Time) {
+	now := time.Now() // A Time.
+	if !wakeup.After(now) {
+		return
+	}
+	delta := wakeup.Sub(now) // A Duration.
+	log.Printf("Sleeping for %.3fs", delta.Seconds())
+	time.Sleep(delta)
+}
+
+func timePackage() {
+	sleepUntil(time.Now().Add(123 * time.Millisecond))
+}
+
+func initializationFunction(c chan int) {
+	c <- 1
+}
+
+var PackageGlobal int
+
+func init() {
+	c := make(chan int)
+	go initializationFunction(c)
+	PackageGlobal = <-c
+}
+
+func BenchmarkSprintf(b *testing.B) {
+	// Verify correctness before running benchmark.
+	b.StopTimer()
+	got := fmt.Sprintf("%x", 23)
+	const expect = "17"
+	if expect != got {
+		b.Fatalf("expected %q; got %q", expect, got)
+	}
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		fmt.Sprintf("%x", 23)
+	}
+}
diff --git a/doc/progs/helloworld3.go b/doc/progs/helloworld3.go
index 2011513..05d26df 100644
--- a/doc/progs/helloworld3.go
+++ b/doc/progs/helloworld3.go
@@ -15,7 +15,7 @@ func main() {
 	file.Stdout.Write(hello)
 	f, err := file.Open("/does/not/exist")
 	if f == nil {
-		fmt.Printf("can't open file; err=%s\n", err.String())
+		fmt.Printf("can't open file; err=%s\n", err.Error())
 		os.Exit(1)
 	}
 }
diff --git a/doc/progs/run b/doc/progs/run
index 9d56049..5a2b786 100755
--- a/doc/progs/run
+++ b/doc/progs/run
@@ -20,31 +20,60 @@ else
 	$GC file.go
 fi
 
+defer_panic_recover="
+	defer.go 
+	defer2.go 
+"
+
+effective_go="
+	eff_bytesize.go
+	eff_qr.go 
+	eff_sequence.go
+"
+
+error_handling="
+	error.go
+	error2.go
+	error3.go
+	error4.go
+"
+
+go_tutorial="
+	cat.go 
+	cat_rot13.go 
+	echo.go 
+	helloworld.go 
+	helloworld3.go 
+	print.go 
+	print_string.go 
+	server.go 
+	server1.go 
+	sieve.go 
+	sieve1.go 
+	sort.go 
+	sortmain.go 
+	strings.go 
+	sum.go 
+"
+
 for i in \
-	helloworld.go \
-	helloworld3.go \
-	echo.go \
-	cat.go \
-	cat_rot13.go \
-	sum.go \
-	sort.go \
-	sortmain.go \
-	print.go \
-	print_string.go \
-	sieve.go \
-	sieve1.go \
-	server1.go \
-	strings.go \
-	eff_bytesize.go\
-	eff_qr.go \
-	eff_sequence.go\
+	$defer_panic_recover \
+	$effective_go \
+	$error_handling \
+	$go_tutorial \
+	slices.go \
+	go1.go \
 ; do
 	$GC $i
 done
 
+# Write to temporary file to avoid mingw bash bug.
+TMPFILE="/tmp/gotest3.$USER"
+
 function testit {
 	$LD $1.$O
-	x=$(echo $(./$O.out $2 2>&1))  # extra echo canonicalizes
+	./$O.out $2 2>&1 >"$TMPFILE" || true
+	x=$(echo $(cat "$TMPFILE")) # extra echo canonicalizes
 	if [ "$x" != "$3" ]
 	then
 		echo $1 failed: '"'$x'"' is not '"'$3'"'
@@ -53,7 +82,8 @@ function testit {
 
 function testitpipe {
 	$LD $1.$O
-	x=$(echo $(./$O.out | $2 2>&1))  # extra echo canonicalizes
+	./$O.out | $2 2>&1 >"$TMPFILE" || true
+	x=$(echo $(cat "$TMPFILE")) # extra echo canonicalizes
 	if [ "$x" != "$3" ]
 	then
 		echo $1 failed: '"'$x'"' is not '"'$3'"'
@@ -66,6 +96,8 @@ testit helloworld3 "" "hello, world can't open file; err=no such file or directo
 testit echo "hello, world" "hello, world"
 testit sum "" "6"
 testit strings "" ""
+testit defer "" "0 3210 2"
+testit defer2 "" "Calling g. Printing in g 0 Printing in g 1 Printing in g 2 Printing in g 3 Panicking! Defer in g 3 Defer in g 2 Defer in g 1 Defer in g 0 Recovered in f 4 Returned normally from f."
 
 alphabet=abcdefghijklmnopqrstuvwxyz
 rot13=nopqrstuvwxyzabcdefghijklm
@@ -88,4 +120,6 @@ testit server1 "" ""
 testit eff_bytesize "" "1.00YB 9.09TB"
 testit eff_sequence "" "[-1 2 6 16 44]"
 
-rm -f $O.out *.$O
+testit go1 "" "Christmas is a holiday: true"
+
+rm -f $O.out $O.out.exe *.$O "$TMPFILE"
diff --git a/doc/progs/server.go b/doc/progs/server.go
index b498b53..4d8409b 100644
--- a/doc/progs/server.go
+++ b/doc/progs/server.go
@@ -18,14 +18,14 @@ func run(op binOp, req *request) {
 	req.replyc <- reply
 }
 
-func server(op binOp, service chan *request) {
+func server(op binOp, service <-chan *request) {
 	for {
 		req := <-service
 		go run(op, req) // don't wait for it
 	}
 }
 
-func startServer(op binOp) chan *request {
+func startServer(op binOp) chan<- *request {
 	req := make(chan *request)
 	go server(op, req)
 	return req
diff --git a/doc/progs/server1.go b/doc/progs/server1.go
index a409392..39e3dde 100644
--- a/doc/progs/server1.go
+++ b/doc/progs/server1.go
@@ -18,7 +18,7 @@ func run(op binOp, req *request) {
 	req.replyc <- reply
 }
 
-func server(op binOp, service chan *request, quit chan bool) {
+func server(op binOp, service <-chan *request, quit <-chan bool) {
 	for {
 		select {
 		case req := <-service:
diff --git a/doc/progs/slices.go b/doc/progs/slices.go
new file mode 100644
index 0000000..72fb4b7
--- /dev/null
+++ b/doc/progs/slices.go
@@ -0,0 +1,59 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"io/ioutil"
+	"regexp"
+)
+
+func AppendByte(slice []byte, data ...byte) []byte {
+	m := len(slice)
+	n := m + len(data)
+	if n > cap(slice) { // if necessary, reallocate
+		// allocate double what's needed, for future growth.
+		newSlice := make([]byte, (n+1)*2)
+		copy(newSlice, slice)
+		slice = newSlice
+	}
+	slice = slice[0:n]
+	copy(slice[m:n], data)
+	return slice
+}
+
+// STOP OMIT
+
+// Filter returns a new slice holding only
+// the elements of s that satisfy f()
+func Filter(s []int, fn func(int) bool) []int {
+	var p []int // == nil
+	for _, i := range s {
+		if fn(i) {
+			p = append(p, i)
+		}
+	}
+	return p
+}
+
+// STOP OMIT
+
+var digitRegexp = regexp.MustCompile("[0-9]+")
+
+func FindDigits(filename string) []byte {
+	b, _ := ioutil.ReadFile(filename)
+	return digitRegexp.Find(b)
+}
+
+// STOP OMIT
+
+func CopyDigits(filename string) []byte {
+	b, _ := ioutil.ReadFile(filename)
+	b = digitRegexp.Find(b)
+	c := make([]byte, len(b))
+	copy(c, b)
+	return c
+}
+
+// STOP OMIT
diff --git a/doc/progs/sortmain.go b/doc/progs/sortmain.go
index c1babb0..1bc3355 100644
--- a/doc/progs/sortmain.go
+++ b/doc/progs/sortmain.go
@@ -5,8 +5,8 @@
 package main
 
 import (
-	"fmt"
 	"./sort"
+	"fmt"
 )
 
 func ints() {
@@ -61,7 +61,6 @@ func days() {
 	fmt.Printf("\n")
 }
 
-
 func main() {
 	ints()
 	strings()
diff --git a/doc/progs/sum.go b/doc/progs/sum.go
index e022195..0f316bc 100644
--- a/doc/progs/sum.go
+++ b/doc/progs/sum.go
@@ -15,6 +15,7 @@ func sum(a []int) int { // returns an int
 }
 
 func main() {
-	s := sum([3]int{1, 2, 3}[:]) // a slice of the array is passed to sum
+	x := [3]int{1, 2, 3}
+	s := sum(x[:]) // a slice of the array is passed to sum
 	fmt.Print(s, "\n")
 }
diff --git a/doc/root.html b/doc/root.html
index 8d76928..23a35eb 100644
--- a/doc/root.html
+++ b/doc/root.html
@@ -1,3 +1,7 @@
+<!--{
+	"Path": "/"
+}-->
+
 <link rel="stylesheet" type="text/css" href="/doc/frontpage.css">
 
 <script src="http://www.google.com/jsapi" type="text/javascript"></script>
@@ -49,10 +53,14 @@ google.setOnLoadCallback(loadFeed);
         It's a fast, statically typed, compiled language that feels like a 
         dynamically typed, interpreted language.
       </p>
-      <h2>Check it out!</h2>
+      <h2>
+        Get started now with
+	<a target="_blank" href="http://tour.golang.org/">A Tour of Go</a>
+        in your browser.
+      </h2>
       <p>
       <div class="how">[<a href="/doc/playground.html">How does this work?</a>]</div>
-      <a href="/doc/install.html">Install Go now</a>, or try it right here in your browser:</p>
+      Or try Go right here:</p>
       <div id="playground" class="small"></div>
       <script src="/doc/play/playground.js"></script>
     </div>
@@ -86,7 +94,7 @@ google.setOnLoadCallback(loadFeed);
           <ul>
             <li><a href="http://godashboard.appspot.com/package">Package Dashboard</a></li>
             <li><a href="http://code.google.com/p/go/issues">Issue Tracker</a></li>
-            <li><a href="http://godashboard.appspot.com/">Build Status</a></li>
+            <li><a href="http://build.golang.org/">Build Status</a></li>
             <li><a href="http://code.google.com/p/go/source/browse/">Go Source</a> [<a href="http://code.google.com/p/go/source/list">changes</a>]</li>
             <li><a href="/pkg/">Package Reference</a></li>
             <li><a href="/doc/go_spec.html">Language Specification</a></li>
diff --git a/doc/talks/io2010/balance.go b/doc/talks/io2010/balance.go
index b01f746..a3825cb 100644
--- a/doc/talks/io2010/balance.go
+++ b/doc/talks/io2010/balance.go
@@ -8,7 +8,7 @@ import (
 	"container/heap"
 	"flag"
 	"fmt"
-	"rand"
+	"math/rand"
 	"time"
 )
 
diff --git a/doc/talks/io2010/decrypt.go b/doc/talks/io2010/decrypt.go
index 0a6c006..e63418b 100644
--- a/doc/talks/io2010/decrypt.go
+++ b/doc/talks/io2010/decrypt.go
@@ -15,7 +15,7 @@ import (
 	"os"
 )
 
-func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) os.Error {
+func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error {
 	r, err := os.Open(srcfile)
 	if err != nil {
 		return err
@@ -39,7 +39,7 @@ func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) os.Error {
 	return err
 }
 
-func DecryptAndGunzip(dstfile, srcfile string, key, iv []byte) os.Error {
+func DecryptAndGunzip(dstfile, srcfile string, key, iv []byte) error {
 	f, err := os.Open(srcfile)
 	if err != nil {
 		return err
diff --git a/doc/talks/io2010/encrypt.go b/doc/talks/io2010/encrypt.go
index c6508bb..57c888c 100644
--- a/doc/talks/io2010/encrypt.go
+++ b/doc/talks/io2010/encrypt.go
@@ -15,7 +15,7 @@ import (
 	"os"
 )
 
-func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) os.Error {
+func EncryptAndGzip(dstfile, srcfile string, key, iv []byte) error {
 	r, err := os.Open(srcfile)
 	if err != nil {
 		return err
diff --git a/doc/talks/io2010/eval1.go b/doc/talks/io2010/eval1.go
index 2d7fc3b..582f43e 100644
--- a/doc/talks/io2010/eval1.go
+++ b/doc/talks/io2010/eval1.go
@@ -101,7 +101,6 @@ func main() {
 	}
 }
 
-
 // Custom grammar and values
 
 var precTab = map[string]int{
@@ -125,7 +124,7 @@ func newVal(lit string) Value {
 	if err == nil {
 		return Int(x)
 	}
-	b, err := strconv.Atob(lit)
+	b, err := strconv.ParseBool(lit)
 	if err == nil {
 		return Bool(b)
 	}
@@ -175,7 +174,7 @@ func (x Int) BinaryOp(op string, y Value) Value {
 
 type Bool bool
 
-func (x Bool) String() string { return strconv.Btoa(bool(x)) }
+func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
 func (x Bool) BinaryOp(op string, y Value) Value {
 	switch y := y.(type) {
 	case Error:
@@ -195,7 +194,6 @@ func (x Bool) BinaryOp(op string, y Value) Value {
 	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
 }
 
-
 func trace(newVal func(string) Value) func(string) Value {
 	return func(s string) Value {
 		v := newVal(s)
diff --git a/doc/talks/io2010/eval2.go b/doc/talks/io2010/eval2.go
index 5524c8b..6f826e1 100644
--- a/doc/talks/io2010/eval2.go
+++ b/doc/talks/io2010/eval2.go
@@ -101,7 +101,6 @@ func main() {
 	}
 }
 
-
 // Custom grammar and values
 
 var precTab = map[string]int{
@@ -125,7 +124,7 @@ func newVal(lit string) Value {
 	if err == nil {
 		return Int(x)
 	}
-	b, err := strconv.Atob(lit)
+	b, err := strconv.ParseBool(lit)
 	if err == nil {
 		return Bool(b)
 	}
@@ -184,7 +183,7 @@ func (x Int) BinaryOp(op string, y Value) Value {
 
 type Bool bool
 
-func (x Bool) String() string { return strconv.Btoa(bool(x)) }
+func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
 func (x Bool) BinaryOp(op string, y Value) Value {
 	switch y := y.(type) {
 	case Error:
@@ -227,7 +226,6 @@ func (x String) BinaryOp(op string, y Value) Value {
 	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
 }
 
-
 func trace(newVal func(string) Value) func(string) Value {
 	return func(s string) Value {
 		v := newVal(s)
diff --git a/doc/tmpltohtml.go b/doc/tmpltohtml.go
index 4a8d026..70745f4 100644
--- a/doc/tmpltohtml.go
+++ b/doc/tmpltohtml.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-
 // The template uses the function "code" to inject program
 // source into the output by extracting code from files and
 // injecting them as HTML-escaped <pre> blocks.
@@ -17,7 +16,13 @@
 //	{{code "foo.go" `/^func.main/` `/^}/`
 //
 // Patterns can be `/regular expression/`, a decimal number, or "$"
-// to signify the end of the file.
+// to signify the end of the file. In multi-line matches,
+// lines that end with the four characters
+//	OMIT
+// are omitted from the output, making it easy to provide marker
+// lines in the input that will not appear in the output but are easy
+// to identify by pattern.
+
 package main
 
 import (
@@ -26,9 +31,10 @@ import (
 	"io/ioutil"
 	"log"
 	"os"
+	"path/filepath"
 	"regexp"
 	"strings"
-	"template"
+	"text/template"
 )
 
 func Usage() {
@@ -36,6 +42,11 @@ func Usage() {
 	os.Exit(2)
 }
 
+var templateFuncs = template.FuncMap{
+	"code":      code,
+	"donotedit": donotedit,
+}
+
 func main() {
 	flag.Usage = Usage
 	flag.Parse()
@@ -44,9 +55,9 @@ func main() {
 	}
 
 	// Read and parse the input.
-	name := flag.Args()[0]
-	tmpl := template.New(name).Funcs(template.FuncMap{"code": code})
-	if _, err := tmpl.ParseFile(name); err != nil {
+	name := flag.Arg(0)
+	tmpl := template.New(filepath.Base(name)).Funcs(templateFuncs)
+	if _, err := tmpl.ParseFiles(name); err != nil {
 		log.Fatal(err)
 	}
 
@@ -81,7 +92,12 @@ func format(arg interface{}) string {
 	return ""
 }
 
-func code(file string, arg ...interface{}) (string, os.Error) {
+func donotedit() string {
+	// No editing please.
+	return fmt.Sprintf("<!--\n  DO NOT EDIT: created by\n    tmpltohtml %s\n-->\n", flag.Args()[0])
+}
+
+func code(file string, arg ...interface{}) (string, error) {
 	text := contents(file)
 	var command string
 	switch len(arg) {
@@ -97,6 +113,8 @@ func code(file string, arg ...interface{}) (string, os.Error) {
 	default:
 		return "", fmt.Errorf("incorrect code invocation: code %q %q", file, arg)
 	}
+	// Trim spaces from output.
+	text = strings.Trim(text, "\n")
 	// Replace tabs by spaces, which work better in HTML.
 	text = strings.Replace(text, "\t", "    ", -1)
 	// Escape the program text for HTML.
@@ -142,7 +160,12 @@ func multipleLines(file, text string, arg1, arg2 interface{}) string {
 	if !isInt2 {
 		line2 = match(file, line1, lines, pattern2)
 	} else if line2 < line1 {
-		log.Fatal("lines out of order for %q: %d %d", line1, line2)
+		log.Fatalf("lines out of order for %q: %d %d", text, line1, line2)
+	}
+	for k := line1 - 1; k < line2; k++ {
+		if strings.HasSuffix(lines[k], "OMIT\n") {
+			lines[k] = ""
+		}
 	}
 	return strings.Join(lines[line1-1:line2], "")
 }
@@ -154,7 +177,7 @@ func match(file string, start int, lines []string, pattern string) int {
 	// $ matches the end of the file.
 	if pattern == "$" {
 		if len(lines) == 0 {
-			log.Fatal("%q: empty file", file)
+			log.Fatalf("%q: empty file", file)
 		}
 		return len(lines)
 	}
diff --git a/include/ar.h b/include/ar.h
index b565ac9..d5636b3 100644
--- a/include/ar.h
+++ b/include/ar.h
@@ -32,7 +32,7 @@
 #define	SARMAG	8
 
 #define	ARFMAG	"`\n"
-#define SARNAME	64
+#define	SARNAME	16
 
 struct	ar_hdr
 {
diff --git a/include/libc.h b/include/libc.h
index f9ad963..b464cb4 100644
--- a/include/libc.h
+++ b/include/libc.h
@@ -95,6 +95,7 @@ extern	void	perror(const char*);
 extern	int	postnote(int, int, char *);
 extern	double	p9pow10(int);
 extern	char*	searchpath(char*);
+extern	char*	p9ctime(long);
 #define p9setjmp(b)	sigsetjmp((void*)(b), 1)
 
 extern	void	sysfatal(char*, ...);
@@ -115,6 +116,7 @@ extern	void	sysfatal(char*, ...);
 #undef  strtod
 #define strtod		fmtstrtod
 #define charstod	fmtcharstod
+#define ctime	p9ctime
 #endif
 
 /*
@@ -185,7 +187,7 @@ extern	void	sysfatal(char*, ...);
 #define DMWRITE		0x2		/* mode bit for write permission */
 #define DMEXEC		0x1		/* mode bit for execute permission */
 
-#ifdef RFMEM	/* FreeBSD, OpenBSD */
+#ifdef RFMEM	/* FreeBSD, OpenBSD, NetBSD */
 #undef RFFDG
 #undef RFNOTEG
 #undef RFPROC
diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py
index 7614763..5730bc2 100644
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -22,7 +22,7 @@ To configure, set the following options in
 your repository's .hg/hgrc file.
 
 	[extensions]
-	codereview = path/to/codereview.py
+	codereview = /path/to/codereview.py
 
 	[codereview]
 	server = codereview.appspot.com
@@ -38,100 +38,60 @@ For example, if change 123456 contains the files x.go and y.go,
 "hg diff @123456" is equivalent to"hg diff x.go y.go".
 '''
 
-from mercurial import cmdutil, commands, hg, util, error, match
-from mercurial.node import nullrev, hex, nullid, short
-import os, re, time
-import stat
-import subprocess
-import threading
-from HTMLParser import HTMLParser
-
-# The standard 'json' package is new in Python 2.6.
-# Before that it was an external package named simplejson.
-try:
-	# Standard location in 2.6 and beyond.
-	import json
-except Exception, e:
-	try:
-		# Conventional name for earlier package.
-		import simplejson as json
-	except:
-		try:
-			# Was also bundled with django, which is commonly installed.
-			from django.utils import simplejson as json
-		except:
-			# We give up.
-			raise e
-
-try:
-	hgversion = util.version()
-except:
-	from mercurial.version import version as v
-	hgversion = v.get_version()
-
-try:
-	from mercurial.discovery import findcommonincoming
-except:
-	def findcommonincoming(repo, remote):
-		return repo.findcommonincoming(remote)
-
-# in Mercurial 1.9 the cmdutil.match and cmdutil.revpair moved to scmutil
-if hgversion >= '1.9':
-    from mercurial import scmutil
-else:
-    scmutil = cmdutil
-
-oldMessage = """
-The code review extension requires Mercurial 1.3 or newer.
-
-To install a new Mercurial,
-
-	sudo easy_install mercurial
-
-works on most systems.
-"""
+import sys
 
-linuxMessage = """
-You may need to clear your current Mercurial installation by running:
+if __name__ == "__main__":
+	print >>sys.stderr, "This is a Mercurial extension and should not be invoked directly."
+	sys.exit(2)
 
-	sudo apt-get remove mercurial mercurial-common
-	sudo rm -rf /etc/mercurial
-"""
+# We require Python 2.6 for the json package.
+if sys.version < '2.6':
+	print >>sys.stderr, "The codereview extension requires Python 2.6 or newer."
+	print >>sys.stderr, "You are running Python " + sys.version
+	sys.exit(2)
 
-if hgversion < '1.3':
-	msg = oldMessage
-	if os.access("/etc/mercurial", 0):
-		msg += linuxMessage
-	raise util.Abort(msg)
+import json
+import os
+import re
+import stat
+import subprocess
+import threading
+import time
 
-def promptyesno(ui, msg):
-	# Arguments to ui.prompt changed between 1.3 and 1.3.1.
-	# Even so, some 1.3.1 distributions seem to have the old prompt!?!?
-	# What a terrible way to maintain software.
-	try:
-		return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0
-	except AttributeError:
-		return ui.prompt(msg, ["&yes", "&no"], "y") != "n"
+from mercurial import commands as hg_commands
+from mercurial import util as hg_util
 
-# To experiment with Mercurial in the python interpreter:
-#    >>> repo = hg.repository(ui.ui(), path = ".")
+defaultcc = None
+codereview_disabled = None
+real_rollback = None
+releaseBranch = None
+server = "codereview.appspot.com"
+server_url_base = None
 
 #######################################################################
 # Normally I would split this into multiple files, but it simplifies
 # import path headaches to keep it all in one file.  Sorry.
+# The different parts of the file are separated by banners like this one.
 
-import sys
-if __name__ == "__main__":
-	print >>sys.stderr, "This is a Mercurial extension and should not be invoked directly."
-	sys.exit(2)
+#######################################################################
+# Helpers
 
-server = "codereview.appspot.com"
-server_url_base = None
-defaultcc = None
-contributors = {}
-missing_codereview = None
-real_rollback = None
-releaseBranch = None
+def RelativePath(path, cwd):
+	n = len(cwd)
+	if path.startswith(cwd) and path[n] == '/':
+		return path[n+1:]
+	return path
+
+def Sub(l1, l2):
+	return [l for l in l1 if l not in l2]
+
+def Add(l1, l2):
+	l = l1 + Sub(l2, l1)
+	l.sort()
+	return l
+
+def Intersect(l1, l2):
+	return [l for l in l1 if l in l2]
 
 #######################################################################
 # RE: UNICODE STRING HANDLING
@@ -158,7 +118,7 @@ releaseBranch = None
 
 def typecheck(s, t):
 	if type(s) != t:
-		raise util.Abort("type check failed: %s has type %s != %s" % (repr(s), type(s), t))
+		raise hg_util.Abort("type check failed: %s has type %s != %s" % (repr(s), type(s), t))
 
 # If we have to pass unicode instead of str, ustr does that conversion clearly.
 def ustr(s):
@@ -182,12 +142,48 @@ set_mercurial_encoding_to_utf8()
 # encoding for all of Python to 'utf-8', not 'ascii'.
 def default_to_utf8():
 	import sys
+	stdout, __stdout__ = sys.stdout, sys.__stdout__
 	reload(sys)  # site.py deleted setdefaultencoding; get it back
+	sys.stdout, sys.__stdout__ = stdout, __stdout__
 	sys.setdefaultencoding('utf-8')
 
 default_to_utf8()
 
 #######################################################################
+# Status printer for long-running commands
+
+global_status = None
+
+def set_status(s):
+	# print >>sys.stderr, "\t", time.asctime(), s
+	global global_status
+	global_status = s
+
+class StatusThread(threading.Thread):
+	def __init__(self):
+		threading.Thread.__init__(self)
+	def run(self):
+		# pause a reasonable amount of time before
+		# starting to display status messages, so that
+		# most hg commands won't ever see them.
+		time.sleep(30)
+
+		# now show status every 15 seconds
+		while True:
+			time.sleep(15 - time.time() % 15)
+			s = global_status
+			if s is None:
+				continue
+			if s == "":
+				s = "(unknown status)"
+			print >>sys.stderr, time.asctime(), s
+
+def start_status_thread():
+	t = StatusThread()
+	t.setDaemon(True)  # allowed to exit if t is still running
+	t.start()
+
+#######################################################################
 # Change list parsing.
 #
 # Change lists are stored in .hg/codereview/cl.nnnnnn
@@ -218,6 +214,7 @@ class CL(object):
 		self.copied_from = None	# None means current user
 		self.mailed = False
 		self.private = False
+		self.lgtm = []
 
 	def DiskText(self):
 		cl = self
@@ -262,15 +259,18 @@ class CL(object):
 		typecheck(s, str)
 		return s
 
-	def PendingText(self):
+	def PendingText(self, quick=False):
 		cl = self
 		s = cl.name + ":" + "\n"
 		s += Indent(cl.desc, "\t")
 		s += "\n"
 		if cl.copied_from:
 			s += "\tAuthor: " + cl.copied_from + "\n"
-		s += "\tReviewer: " + JoinComma(cl.reviewer) + "\n"
-		s += "\tCC: " + JoinComma(cl.cc) + "\n"
+		if not quick:
+			s += "\tReviewer: " + JoinComma(cl.reviewer) + "\n"
+			for (who, line) in cl.lgtm:
+				s += "\t\t" + who + ": " + line + "\n"
+			s += "\tCC: " + JoinComma(cl.cc) + "\n"
 		s += "\tFiles:\n"
 		for f in cl.files:
 			s += "\t\t" + f + "\n"
@@ -345,7 +345,7 @@ class CL(object):
 			uploaded_diff_file = [("data", "data.diff", emptydiff)]
 		
 		if vcs and self.name != "new":
-			form_fields.append(("subject", "diff -r " + vcs.base_rev + " " + getremote(ui, repo, {}).path))
+			form_fields.append(("subject", "diff -r " + vcs.base_rev + " " + ui.expandpath("default")))
 		else:
 			# First upload sets the subject for the CL itself.
 			form_fields.append(("subject", self.Subject()))
@@ -364,7 +364,7 @@ class CL(object):
 			ui.status(msg + "\n")
 		set_status("uploaded CL metadata + diffs")
 		if not response_body.startswith("Issue created.") and not response_body.startswith("Issue updated."):
-			raise util.Abort("failed to update issue: " + response_body)
+			raise hg_util.Abort("failed to update issue: " + response_body)
 		issue = msg[msg.rfind("/")+1:]
 		self.name = issue
 		if not self.url:
@@ -389,7 +389,7 @@ class CL(object):
 			pmsg += " (cc: %s)" % (', '.join(self.cc),)
 		pmsg += ",\n"
 		pmsg += "\n"
-		repourl = getremote(ui, repo, {}).path
+		repourl = ui.expandpath("default")
 		if not self.mailed:
 			pmsg += "I'd like you to review this change to\n" + repourl + "\n"
 		else:
@@ -542,40 +542,16 @@ def LoadCL(ui, repo, name, web=True):
 		cl.url = server_url_base + name
 		cl.web = True
 		cl.private = d.get('private', False) != False
+		cl.lgtm = []
+		for m in d.get('messages', []):
+			if m.get('approval', False) == True:
+				who = re.sub('@.*', '', m.get('sender', ''))
+				text = re.sub("\n(.|\n)*", '', m.get('text', ''))
+				cl.lgtm.append((who, text))
+
 	set_status("loaded CL " + name)
 	return cl, ''
 
-global_status = None
-
-def set_status(s):
-	# print >>sys.stderr, "\t", time.asctime(), s
-	global global_status
-	global_status = s
-
-class StatusThread(threading.Thread):
-	def __init__(self):
-		threading.Thread.__init__(self)
-	def run(self):
-		# pause a reasonable amount of time before
-		# starting to display status messages, so that
-		# most hg commands won't ever see them.
-		time.sleep(30)
-
-		# now show status every 15 seconds
-		while True:
-			time.sleep(15 - time.time() % 15)
-			s = global_status
-			if s is None:
-				continue
-			if s == "":
-				s = "(unknown status)"
-			print >>sys.stderr, time.asctime(), s
-
-def start_status_thread():
-	t = StatusThread()
-	t.setDaemon(True)  # allowed to exit if t is still running
-	t.start()
-
 class LoadCLThread(threading.Thread):
 	def __init__(self, ui, repo, dir, f, web):
 		threading.Thread.__init__(self)
@@ -713,105 +689,6 @@ _change_prolog = """# Change list.
 # Multi-line values should be indented.
 """
 
-#######################################################################
-# Mercurial helper functions
-
-# Get effective change nodes taking into account applied MQ patches
-def effective_revpair(repo):
-    try:
-	return scmutil.revpair(repo, ['qparent'])
-    except:
-	return scmutil.revpair(repo, None)
-
-# Return list of changed files in repository that match pats.
-# Warn about patterns that did not match.
-def matchpats(ui, repo, pats, opts):
-	matcher = scmutil.match(repo, pats, opts)
-	node1, node2 = effective_revpair(repo)
-	modified, added, removed, deleted, unknown, ignored, clean = repo.status(node1, node2, matcher, ignored=True, clean=True, unknown=True)
-	return (modified, added, removed, deleted, unknown, ignored, clean)
-
-# Return list of changed files in repository that match pats.
-# The patterns came from the command line, so we warn
-# if they have no effect or cannot be understood.
-def ChangedFiles(ui, repo, pats, opts, taken=None):
-	taken = taken or {}
-	# Run each pattern separately so that we can warn about
-	# patterns that didn't do anything useful.
-	for p in pats:
-		modified, added, removed, deleted, unknown, ignored, clean = matchpats(ui, repo, [p], opts)
-		redo = False
-		for f in unknown:
-			promptadd(ui, repo, f)
-			redo = True
-		for f in deleted:
-			promptremove(ui, repo, f)
-			redo = True
-		if redo:
-			modified, added, removed, deleted, unknown, ignored, clean = matchpats(ui, repo, [p], opts)
-		for f in modified + added + removed:
-			if f in taken:
-				ui.warn("warning: %s already in CL %s\n" % (f, taken[f].name))
-		if not modified and not added and not removed:
-			ui.warn("warning: %s did not match any modified files\n" % (p,))
-
-	# Again, all at once (eliminates duplicates)
-	modified, added, removed = matchpats(ui, repo, pats, opts)[:3]
-	l = modified + added + removed
-	l.sort()
-	if taken:
-		l = Sub(l, taken.keys())
-	return l
-
-# Return list of changed files in repository that match pats and still exist.
-def ChangedExistingFiles(ui, repo, pats, opts):
-	modified, added = matchpats(ui, repo, pats, opts)[:2]
-	l = modified + added
-	l.sort()
-	return l
-
-# Return list of files claimed by existing CLs
-def Taken(ui, repo):
-	all = LoadAllCL(ui, repo, web=False)
-	taken = {}
-	for _, cl in all.items():
-		for f in cl.files:
-			taken[f] = cl
-	return taken
-
-# Return list of changed files that are not claimed by other CLs
-def DefaultFiles(ui, repo, pats, opts):
-	return ChangedFiles(ui, repo, pats, opts, taken=Taken(ui, repo))
-
-def Sub(l1, l2):
-	return [l for l in l1 if l not in l2]
-
-def Add(l1, l2):
-	l = l1 + Sub(l2, l1)
-	l.sort()
-	return l
-
-def Intersect(l1, l2):
-	return [l for l in l1 if l in l2]
-
-def getremote(ui, repo, opts):
-	# save $http_proxy; creating the HTTP repo object will
-	# delete it in an attempt to "help"
-	proxy = os.environ.get('http_proxy')
-	source = hg.parseurl(ui.expandpath("default"), None)[0]
-	try:
-		remoteui = hg.remoteui # hg 1.6
-	except:
-		remoteui = cmdutil.remoteui
-	other = hg.repository(remoteui(repo, opts), source)
-	if proxy is not None:
-		os.environ['http_proxy'] = proxy
-	return other
-
-def Incoming(ui, repo, opts):
-	_, incoming, _ = findcommonincoming(repo, getremote(ui, repo, opts))
-	return incoming
-
 desc_re = '^(.+: |(tag )?(release|weekly)\.|fix build|undo CL)'
 
 desc_msg = '''Your CL description appears not to use the standard form.
@@ -833,15 +710,17 @@ Examples:
 
 '''
 
+def promptyesno(ui, msg):
+	return ui.promptchoice(msg, ["&yes", "&no"], 0) == 0
 
 def promptremove(ui, repo, f):
 	if promptyesno(ui, "hg remove %s (y/n)?" % (f,)):
-		if commands.remove(ui, repo, 'path:'+f) != 0:
+		if hg_commands.remove(ui, repo, 'path:'+f) != 0:
 			ui.warn("error removing %s" % (f,))
 
 def promptadd(ui, repo, f):
 	if promptyesno(ui, "hg add %s (y/n)?" % (f,)):
-		if commands.add(ui, repo, 'path:'+f) != 0:
+		if hg_commands.add(ui, repo, 'path:'+f) != 0:
 			ui.warn("error adding %s" % (f,))
 
 def EditCL(ui, repo, cl):
@@ -881,10 +760,14 @@ def EditCL(ui, repo, cl):
 		# Check file list for files that need to be hg added or hg removed
 		# or simply aren't understood.
 		pats = ['path:'+f for f in clx.files]
-		modified, added, removed, deleted, unknown, ignored, clean = matchpats(ui, repo, pats, {})
+		changed = hg_matchPattern(ui, repo, *pats, modified=True, added=True, removed=True)
+		deleted = hg_matchPattern(ui, repo, *pats, deleted=True)
+		unknown = hg_matchPattern(ui, repo, *pats, unknown=True)
+		ignored = hg_matchPattern(ui, repo, *pats, ignored=True)
+		clean = hg_matchPattern(ui, repo, *pats, clean=True)
 		files = []
 		for f in clx.files:
-			if f in modified or f in added or f in removed:
+			if f in changed:
 				files.append(f)
 				continue
 			if f in deleted:
@@ -936,7 +819,7 @@ def CommandLineCL(ui, repo, pats, opts, defaultcc=None):
 	else:
 		cl = CL("new")
 		cl.local = True
-		cl.files = ChangedFiles(ui, repo, pats, opts, taken=Taken(ui, repo))
+		cl.files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
 		if not cl.files:
 			return None, "no files changed"
 	if opts.get('reviewer'):
@@ -954,41 +837,56 @@ def CommandLineCL(ui, repo, pats, opts, defaultcc=None):
 				return None, err
 	return cl, ""
 
-# reposetup replaces cmdutil.match with this wrapper,
-# which expands the syntax @clnumber to mean the files
-# in that CL.
-original_match = None
-global_repo = None
-def ReplacementForCmdutilMatch(ctx, pats=None, opts=None, globbed=False, default='relpath'):
-	taken = []
-	files = []
-	pats = pats or []
-	opts = opts or {}
-	
+#######################################################################
+# Change list file management
+
+# Return list of changed files in repository that match pats.
+# The patterns came from the command line, so we warn
+# if they have no effect or cannot be understood.
+def ChangedFiles(ui, repo, pats, taken=None):
+	taken = taken or {}
+	# Run each pattern separately so that we can warn about
+	# patterns that didn't do anything useful.
 	for p in pats:
-		if p.startswith('@'):
-			taken.append(p)
-			clname = p[1:]
-			if not GoodCLName(clname):
-				raise util.Abort("invalid CL name " + clname)
-			cl, err = LoadCL(global_repo.ui, global_repo, clname, web=False)
-			if err != '':
-				raise util.Abort("loading CL " + clname + ": " + err)
-			if not cl.files:
-				raise util.Abort("no files in CL " + clname)
-			files = Add(files, cl.files)
-	pats = Sub(pats, taken) + ['path:'+f for f in files]
+		for f in hg_matchPattern(ui, repo, p, unknown=True):
+			promptadd(ui, repo, f)
+		for f in hg_matchPattern(ui, repo, p, removed=True):
+			promptremove(ui, repo, f)
+		files = hg_matchPattern(ui, repo, p, modified=True, added=True, removed=True)
+		for f in files:
+			if f in taken:
+				ui.warn("warning: %s already in CL %s\n" % (f, taken[f].name))
+		if not files:
+			ui.warn("warning: %s did not match any modified files\n" % (p,))
 
-	# work-around for http://selenic.com/hg/rev/785bbc8634f8
-	if hgversion >= '1.9' and not hasattr(ctx, 'match'):
-		ctx = ctx[None]
-	return original_match(ctx, pats=pats, opts=opts, globbed=globbed, default=default)
+	# Again, all at once (eliminates duplicates)
+	l = hg_matchPattern(ui, repo, *pats, modified=True, added=True, removed=True)
+	l.sort()
+	if taken:
+		l = Sub(l, taken.keys())
+	return l
 
-def RelativePath(path, cwd):
-	n = len(cwd)
-	if path.startswith(cwd) and path[n] == '/':
-		return path[n+1:]
-	return path
+# Return list of changed files in repository that match pats and still exist.
+def ChangedExistingFiles(ui, repo, pats, opts):
+	l = hg_matchPattern(ui, repo, *pats, modified=True, added=True)
+	l.sort()
+	return l
+
+# Return list of files claimed by existing CLs
+def Taken(ui, repo):
+	all = LoadAllCL(ui, repo, web=False)
+	taken = {}
+	for _, cl in all.items():
+		for f in cl.files:
+			taken[f] = cl
+	return taken
+
+# Return list of changed files that are not claimed by other CLs
+def DefaultFiles(ui, repo, pats):
+	return ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
+
+#######################################################################
+# File format checking.
 
 def CheckFormat(ui, repo, files, just_warn=False):
 	set_status("running gofmt")
@@ -997,7 +895,7 @@ def CheckFormat(ui, repo, files, just_warn=False):
 
 # Check that gofmt run on the list of files does not change them
 def CheckGofmt(ui, repo, files, just_warn):
-	files = [f for f in files if (f.startswith('src/') or f.startswith('test/bench/')) and f.endswith('.go')]
+	files = [f for f in files if (not f.startswith('test/') or f.startswith('test/bench/')) and f.endswith('.go')]
 	if not files:
 		return
 	cwd = os.getcwd()
@@ -1009,7 +907,7 @@ def CheckGofmt(ui, repo, files, just_warn):
 		cmd = subprocess.Popen(["gofmt", "-l"] + files, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=sys.platform != "win32")
 		cmd.stdin.close()
 	except:
-		raise util.Abort("gofmt: " + ExceptionDetail())
+		raise hg_util.Abort("gofmt: " + ExceptionDetail())
 	data = cmd.stdout.read()
 	errors = cmd.stderr.read()
 	cmd.wait()
@@ -1022,7 +920,7 @@ def CheckGofmt(ui, repo, files, just_warn):
 		if just_warn:
 			ui.warn("warning: " + msg + "\n")
 		else:
-			raise util.Abort(msg)
+			raise hg_util.Abort(msg)
 	return
 
 # Check that *.[chys] files indent using tabs.
@@ -1051,19 +949,306 @@ def CheckTabfmt(ui, repo, files, just_warn):
 		if just_warn:
 			ui.warn("warning: " + msg + "\n")
 		else:
-			raise util.Abort(msg)
+			raise hg_util.Abort(msg)
 	return
 
 #######################################################################
-# Mercurial commands
+# CONTRIBUTORS file parsing
 
-# every command must take a ui and and repo as arguments.
-# opts is a dict where you can find other command line flags
-#
-# Other parameters are taken in order from items on the command line that
-# don't start with a dash.  If no default value is given in the parameter list,
-# they are required.
-#
+contributorsCache = None
+contributorsURL = None
+
+def ReadContributors(ui, repo):
+	global contributorsCache
+	if contributorsCache is not None:
+		return contributorsCache
+
+	try:
+		if contributorsURL is not None:
+			opening = contributorsURL
+			f = urllib2.urlopen(contributorsURL)
+		else:
+			opening = repo.root + '/CONTRIBUTORS'
+			f = open(repo.root + '/CONTRIBUTORS', 'r')
+	except:
+		ui.write("warning: cannot open %s: %s\n" % (opening, ExceptionDetail()))
+		return
+
+	contributors = {}
+	for line in f:
+		# CONTRIBUTORS is a list of lines like:
+		#	Person <email>
+		#	Person <email> <alt-email>
+		# The first email address is the one used in commit logs.
+		if line.startswith('#'):
+			continue
+		m = re.match(r"([^<>]+\S)\s+(<[^<>\s]+>)((\s+<[^<>\s]+>)*)\s*$", line)
+		if m:
+			name = m.group(1)
+			email = m.group(2)[1:-1]
+			contributors[email.lower()] = (name, email)
+			for extra in m.group(3).split():
+				contributors[extra[1:-1].lower()] = (name, email)
+
+	contributorsCache = contributors
+	return contributors
+
+def CheckContributor(ui, repo, user=None):
+	set_status("checking CONTRIBUTORS file")
+	user, userline = FindContributor(ui, repo, user, warn=False)
+	if not userline:
+		raise hg_util.Abort("cannot find %s in CONTRIBUTORS" % (user,))
+	return userline
+
+def FindContributor(ui, repo, user=None, warn=True):
+	if not user:
+		user = ui.config("ui", "username")
+		if not user:
+			raise hg_util.Abort("[ui] username is not configured in .hgrc")
+	user = user.lower()
+	m = re.match(r".*<(.*)>", user)
+	if m:
+		user = m.group(1)
+
+	contributors = ReadContributors(ui, repo)
+	if user not in contributors:
+		if warn:
+			ui.warn("warning: cannot find %s in CONTRIBUTORS\n" % (user,))
+		return user, None
+	
+	user, email = contributors[user]
+	return email, "%s <%s>" % (user, email)
+
+#######################################################################
+# Mercurial helper functions.
+# Read http://mercurial.selenic.com/wiki/MercurialApi before writing any of these.
+# We use the ui.pushbuffer/ui.popbuffer + hg_commands.xxx tricks for all interaction
+# with Mercurial.  It has proved the most stable as they make changes.
+
+hgversion = hg_util.version()
+
+# We require Mercurial 1.9 and suggest Mercurial 2.0.
+# The details of the scmutil package changed then,
+# so allowing earlier versions would require extra band-aids below.
+# Ubuntu 11.10 ships with Mercurial 1.9.1 as the default version.
+hg_required = "1.9"
+hg_suggested = "2.0"
+
+old_message = """
+
+The code review extension requires Mercurial """+hg_required+""" or newer.
+You are using Mercurial """+hgversion+""".
+
+To install a new Mercurial, use
+
+	sudo easy_install mercurial=="""+hg_suggested+"""
+
+or visit http://mercurial.selenic.com/downloads/.
+"""
+
+linux_message = """
+You may need to clear your current Mercurial installation by running:
+
+	sudo apt-get remove mercurial mercurial-common
+	sudo rm -rf /etc/mercurial
+"""
+
+if hgversion < hg_required:
+	msg = old_message
+	if os.access("/etc/mercurial", 0):
+		msg += linux_message
+	raise hg_util.Abort(msg)
+
+from mercurial.hg import clean as hg_clean
+from mercurial import cmdutil as hg_cmdutil
+from mercurial import error as hg_error
+from mercurial import match as hg_match
+from mercurial import node as hg_node
+
+class uiwrap(object):
+	def __init__(self, ui):
+		self.ui = ui
+		ui.pushbuffer()
+		self.oldQuiet = ui.quiet
+		ui.quiet = True
+		self.oldVerbose = ui.verbose
+		ui.verbose = False
+	def output(self):
+		ui = self.ui
+		ui.quiet = self.oldQuiet
+		ui.verbose = self.oldVerbose
+		return ui.popbuffer()
+
+def to_slash(path):
+	if sys.platform == "win32":
+		return path.replace('\\', '/')
+	return path
+
+def hg_matchPattern(ui, repo, *pats, **opts):
+	w = uiwrap(ui)
+	hg_commands.status(ui, repo, *pats, **opts)
+	text = w.output()
+	ret = []
+	prefix = to_slash(os.path.realpath(repo.root))+'/'
+	for line in text.split('\n'):
+		f = line.split()
+		if len(f) > 1:
+			if len(pats) > 0:
+				# Given patterns, Mercurial shows relative to cwd
+				p = to_slash(os.path.realpath(f[1]))
+				if not p.startswith(prefix):
+					print >>sys.stderr, "File %s not in repo root %s.\n" % (p, prefix)
+				else:
+					ret.append(p[len(prefix):])
+			else:
+				# Without patterns, Mercurial shows relative to root (what we want)
+				ret.append(to_slash(f[1]))
+	return ret
+
+def hg_heads(ui, repo):
+	w = uiwrap(ui)
+	hg_commands.heads(ui, repo)
+	return w.output()
+
+noise = [
+	"",
+	"resolving manifests",
+	"searching for changes",
+	"couldn't find merge tool hgmerge",
+	"adding changesets",
+	"adding manifests",
+	"adding file changes",
+	"all local heads known remotely",
+]
+
+def isNoise(line):
+	line = str(line)
+	for x in noise:
+		if line == x:
+			return True
+	return False
+
+def hg_incoming(ui, repo):
+	w = uiwrap(ui)
+	ret = hg_commands.incoming(ui, repo, force=False, bundle="")
+	if ret and ret != 1:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_log(ui, repo, **opts):
+	for k in ['date', 'keyword', 'rev', 'user']:
+		if not opts.has_key(k):
+			opts[k] = ""
+	w = uiwrap(ui)
+	ret = hg_commands.log(ui, repo, **opts)
+	if ret:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_outgoing(ui, repo, **opts):
+	w = uiwrap(ui)
+	ret = hg_commands.outgoing(ui, repo, **opts)
+	if ret and ret != 1:
+		raise hg_util.Abort(ret)
+	return w.output()
+
+def hg_pull(ui, repo, **opts):
+	w = uiwrap(ui)
+	ui.quiet = False
+	ui.verbose = True  # for file list
+	err = hg_commands.pull(ui, repo, **opts)
+	for line in w.output().split('\n'):
+		if isNoise(line):
+			continue
+		if line.startswith('moving '):
+			line = 'mv ' + line[len('moving '):]
+		if line.startswith('getting ') and line.find(' to ') >= 0:
+			line = 'mv ' + line[len('getting '):]
+		if line.startswith('getting '):
+			line = '+ ' + line[len('getting '):]
+		if line.startswith('removing '):
+			line = '- ' + line[len('removing '):]
+		ui.write(line + '\n')
+	return err
+
+def hg_push(ui, repo, **opts):
+	w = uiwrap(ui)
+	ui.quiet = False
+	ui.verbose = True
+	err = hg_commands.push(ui, repo, **opts)
+	for line in w.output().split('\n'):
+		if not isNoise(line):
+			ui.write(line + '\n')
+	return err
+
+def hg_commit(ui, repo, *pats, **opts):
+	return hg_commands.commit(ui, repo, *pats, **opts)
+
+#######################################################################
+# Mercurial precommit hook to disable commit except through this interface.
+
+commit_okay = False
+
+def precommithook(ui, repo, **opts):
+	if commit_okay:
+		return False  # False means okay.
+	ui.write("\ncodereview extension enabled; use mail, upload, or submit instead of commit\n\n")
+	return True
+
+#######################################################################
+# @clnumber file pattern support
+
+# We replace scmutil.match with the MatchAt wrapper to add the @clnumber pattern.
+
+match_repo = None
+match_ui = None
+match_orig = None
+
+def InstallMatch(ui, repo):
+	global match_repo
+	global match_ui
+	global match_orig
+
+	match_ui = ui
+	match_repo = repo
+
+	from mercurial import scmutil
+	match_orig = scmutil.match
+	scmutil.match = MatchAt
+
+def MatchAt(ctx, pats=None, opts=None, globbed=False, default='relpath'):
+	taken = []
+	files = []
+	pats = pats or []
+	opts = opts or {}
+	
+	for p in pats:
+		if p.startswith('@'):
+			taken.append(p)
+			clname = p[1:]
+			if clname == "default":
+				files = DefaultFiles(match_ui, match_repo, [])
+			else:
+				if not GoodCLName(clname):
+					raise hg_util.Abort("invalid CL name " + clname)
+				cl, err = LoadCL(match_repo.ui, match_repo, clname, web=False)
+				if err != '':
+					raise hg_util.Abort("loading CL " + clname + ": " + err)
+				if not cl.files:
+					raise hg_util.Abort("no files in CL " + clname)
+				files = Add(files, cl.files)
+	pats = Sub(pats, taken) + ['path:'+f for f in files]
+
+	# work-around for http://selenic.com/hg/rev/785bbc8634f8
+	if not hasattr(ctx, 'match'):
+		ctx = ctx[None]
+	return match_orig(ctx, pats=pats, opts=opts, globbed=globbed, default=default)
+
+#######################################################################
+# Commands added by code review extension.
+
+#######################################################################
+# hg change
 
 def change(ui, repo, *pats, **opts):
 	"""create, edit or delete a change list
@@ -1087,8 +1272,8 @@ def change(ui, repo, *pats, **opts):
 	before running hg change -d 123456.
 	"""
 
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 	
 	dirty = {}
 	if len(pats) > 0 and GoodCLName(pats[0]):
@@ -1102,12 +1287,12 @@ def change(ui, repo, *pats, **opts):
 		if not cl.local and (opts["stdin"] or not opts["stdout"]):
 			return "cannot change non-local CL " + name
 	else:
-		if repo[None].branch() != "default":
-			return "cannot run hg change outside default branch"
 		name = "new"
 		cl = CL("new")
+		if repo[None].branch() != "default":
+			return "cannot create CL outside default branch"
 		dirty[cl] = True
-		files = ChangedFiles(ui, repo, pats, opts, taken=Taken(ui, repo))
+		files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
 
 	if opts["delete"] or opts["deletelocal"]:
 		if opts["delete"] and opts["deletelocal"]:
@@ -1175,17 +1360,24 @@ def change(ui, repo, *pats, **opts):
 			ui.write("CL created: " + cl.url + "\n")
 	return
 
+#######################################################################
+# hg code-login (broken?)
+
 def code_login(ui, repo, **opts):
 	"""log in to code review server
 
 	Logs in to the code review server, saving a cookie in
 	a file in your home directory.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	MySend(None)
 
+#######################################################################
+# hg clpatch / undo / release-apply / download
+# All concerned with applying or unapplying patches to the repository.
+
 def clpatch(ui, repo, clname, **opts):
 	"""import a patch from the code review server
 
@@ -1255,16 +1447,16 @@ def release_apply(ui, repo, clname, **opts):
 		return "no active release branches"
 	if c.branch() != releaseBranch:
 		if c.modified() or c.added() or c.removed():
-			raise util.Abort("uncommitted local changes - cannot switch branches")
-		err = hg.clean(repo, releaseBranch)
+			raise hg_util.Abort("uncommitted local changes - cannot switch branches")
+		err = hg_clean(repo, releaseBranch)
 		if err:
 			return err
 	try:
 		err = clpatch_or_undo(ui, repo, clname, opts, mode="backport")
 		if err:
-			raise util.Abort(err)
+			raise hg_util.Abort(err)
 	except Exception, e:
-		hg.clean(repo, "default")
+		hg_clean(repo, "default")
 		raise e
 	return None
 
@@ -1299,14 +1491,10 @@ backportFooter = """
 
 # Implementation of clpatch/undo.
 def clpatch_or_undo(ui, repo, clname, opts, mode):
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	if mode == "undo" or mode == "backport":
-		if hgversion < '1.4':
-			# Don't have cmdutil.match (see implementation of sync command).
-			return "hg is too old to run hg %s - update to 1.4 or newer" % mode
-
 		# Find revision in Mercurial repository.
 		# Assume CL number is 7+ decimal digits.
 		# Otherwise is either change log sequence number (fewer decimal digits),
@@ -1315,11 +1503,8 @@ def clpatch_or_undo(ui, repo, clname, opts, mode):
 		# sequence numbers get to be 7 digits long.
 		if re.match('^[0-9]{7,}$', clname):
 			found = False
-			matchfn = scmutil.match(repo, [], {'rev': None})
-			def prep(ctx, fns):
-				pass
-			for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev': None}, prep):
-				rev = repo[ctx.rev()]
+			for r in hg_log(ui, repo, keyword="codereview.appspot.com/"+clname, limit=100, template="{node}\n").split():
+				rev = repo[r]
 				# Last line with a code review URL is the actual review URL.
 				# Earlier ones might be part of the CL description.
 				n = rev2clname(rev)
@@ -1337,7 +1522,7 @@ def clpatch_or_undo(ui, repo, clname, opts, mode):
 				return "cannot find CL name in revision description"
 		
 		# Create fresh CL and start with patch that would reverse the change.
-		vers = short(rev.node())
+		vers = hg_node.short(rev.node())
 		cl = CL("new")
 		desc = str(rev.description())
 		if mode == "undo":
@@ -1345,7 +1530,7 @@ def clpatch_or_undo(ui, repo, clname, opts, mode):
 		else:
 			cl.desc = (backportHeader % (releaseBranch, line1(desc), clname, vers)) + desc + undoFooter
 		v1 = vers
-		v0 = short(rev.parents()[0].node())
+		v0 = hg_node.short(rev.parents()[0].node())
 		if mode == "undo":
 			arg = v1 + ":" + v0
 		else:
@@ -1363,7 +1548,7 @@ def clpatch_or_undo(ui, repo, clname, opts, mode):
 	# find current hg version (hg identify)
 	ctx = repo[None]
 	parents = ctx.parents()
-	id = '+'.join([short(p.node()) for p in parents])
+	id = '+'.join([hg_node.short(p.node()) for p in parents])
 
 	# if version does not match the patch version,
 	# try to update the patch line numbers.
@@ -1396,7 +1581,7 @@ def clpatch_or_undo(ui, repo, clname, opts, mode):
 	cl.files = out.strip().split()
 	if not cl.files and not opts["ignore_hgpatch_failure"]:
 		return "codereview issue %s has no changed files" % clname
-	files = ChangedFiles(ui, repo, [], opts)
+	files = ChangedFiles(ui, repo, [])
 	extra = Sub(cl.files, files)
 	if extra:
 		ui.warn("warning: these files were listed in the patch but not changed:\n\t" + "\n\t".join(extra) + "\n")
@@ -1476,8 +1661,8 @@ def download(ui, repo, clname, **opts):
 	Download prints a description of the given change list
 	followed by its diff, downloaded from the code review server.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	cl, vers, patch, err = DownloadCL(ui, repo, clname)
 	if err != "":
@@ -1486,6 +1671,9 @@ def download(ui, repo, clname, **opts):
 	ui.write(patch + "\n")
 	return
 
+#######################################################################
+# hg file
+
 def file(ui, repo, clname, pat, *pats, **opts):
 	"""assign files to or remove files from a change list
 
@@ -1494,8 +1682,8 @@ def file(ui, repo, clname, pat, *pats, **opts):
 	The -d option only removes files from the change list.
 	It does not edit them or remove them from the repository.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	pats = tuple([pat] + list(pats))
 	if not GoodCLName(clname):
@@ -1508,7 +1696,7 @@ def file(ui, repo, clname, pat, *pats, **opts):
 	if not cl.local:
 		return "cannot change non-local CL " + clname
 
-	files = ChangedFiles(ui, repo, pats, opts)
+	files = ChangedFiles(ui, repo, pats)
 
 	if opts["delete"]:
 		oldfiles = Intersect(files, cl.files)
@@ -1548,14 +1736,17 @@ def file(ui, repo, clname, pat, *pats, **opts):
 		d.Flush(ui, repo)
 	return
 
+#######################################################################
+# hg gofmt
+
 def gofmt(ui, repo, *pats, **opts):
 	"""apply gofmt to modified files
 
 	Applies gofmt to the modified files in the repository that match
 	the given patterns.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	files = ChangedExistingFiles(ui, repo, pats, opts)
 	files = [f for f in files if f.endswith(".go")]
@@ -1568,21 +1759,24 @@ def gofmt(ui, repo, *pats, **opts):
 		if not opts["list"]:
 			cmd += ["-w"]
 		if os.spawnvp(os.P_WAIT, "gofmt", cmd + files) != 0:
-			raise util.Abort("gofmt did not exit cleanly")
-	except error.Abort, e:
+			raise hg_util.Abort("gofmt did not exit cleanly")
+	except hg_error.Abort, e:
 		raise
 	except:
-		raise util.Abort("gofmt: " + ExceptionDetail())
+		raise hg_util.Abort("gofmt: " + ExceptionDetail())
 	return
 
+#######################################################################
+# hg mail
+
 def mail(ui, repo, *pats, **opts):
 	"""mail a change for review
 
 	Uploads a patch to the code review server and then sends mail
 	to the reviewer and CC list asking for a review.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	cl, err = CommandLineCL(ui, repo, pats, opts, defaultcc=defaultcc)
 	if err != "":
@@ -1604,62 +1798,55 @@ def mail(ui, repo, *pats, **opts):
 
 	cl.Mail(ui, repo)		
 
+#######################################################################
+# hg p / hg pq / hg ps / hg pending
+
+def ps(ui, repo, *pats, **opts):
+	"""alias for hg p --short
+	"""
+	opts['short'] = True
+	return pending(ui, repo, *pats, **opts)
+
+def pq(ui, repo, *pats, **opts):
+	"""alias for hg p --quick
+	"""
+	opts['quick'] = True
+	return pending(ui, repo, *pats, **opts)
+
 def pending(ui, repo, *pats, **opts):
 	"""show pending changes
 
 	Lists pending changes followed by a list of unassigned but modified files.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
-	m = LoadAllCL(ui, repo, web=True)
+	quick = opts.get('quick', False)
+	short = opts.get('short', False)
+	m = LoadAllCL(ui, repo, web=not quick and not short)
 	names = m.keys()
 	names.sort()
 	for name in names:
 		cl = m[name]
-		ui.write(cl.PendingText() + "\n")
+		if short:
+			ui.write(name + "\t" + line1(cl.desc) + "\n")
+		else:
+			ui.write(cl.PendingText(quick=quick) + "\n")
 
-	files = DefaultFiles(ui, repo, [], opts)
+	if short:
+		return
+	files = DefaultFiles(ui, repo, [])
 	if len(files) > 0:
 		s = "Changed files not in any CL:\n"
 		for f in files:
 			s += "\t" + f + "\n"
 		ui.write(s)
 
-def reposetup(ui, repo):
-	global original_match
-	if original_match is None:
-		global global_repo
-		global_repo = repo
-		start_status_thread()
-		original_match = scmutil.match
-		scmutil.match = ReplacementForCmdutilMatch
-		RietveldSetup(ui, repo)
-
-def CheckContributor(ui, repo, user=None):
-	set_status("checking CONTRIBUTORS file")
-	user, userline = FindContributor(ui, repo, user, warn=False)
-	if not userline:
-		raise util.Abort("cannot find %s in CONTRIBUTORS" % (user,))
-	return userline
-
-def FindContributor(ui, repo, user=None, warn=True):
-	if not user:
-		user = ui.config("ui", "username")
-		if not user:
-			raise util.Abort("[ui] username is not configured in .hgrc")
-	user = user.lower()
-	m = re.match(r".*<(.*)>", user)
-	if m:
-		user = m.group(1)
+#######################################################################
+# hg submit
 
-	if user not in contributors:
-		if warn:
-			ui.warn("warning: cannot find %s in CONTRIBUTORS\n" % (user,))
-		return user, None
-	
-	user, email = contributors[user]
-	return email, "%s <%s>" % (user, email)
+def need_sync():
+	raise hg_util.Abort("local repository out of date; must sync before submit")
 
 def submit(ui, repo, *pats, **opts):
 	"""submit change to remote repository
@@ -1667,15 +1854,14 @@ def submit(ui, repo, *pats, **opts):
 	Submits change to remote repository.
 	Bails out if the local repository is not in sync with the remote one.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	# We already called this on startup but sometimes Mercurial forgets.
 	set_mercurial_encoding_to_utf8()
 
-	repo.ui.quiet = True
-	if not opts["no_incoming"] and Incoming(ui, repo, opts):
-		return "local repository out of date; must sync before submit"
+	if not opts["no_incoming"] and hg_incoming(ui, repo):
+		need_sync()
 
 	cl, err = CommandLineCL(ui, repo, pats, opts, defaultcc=defaultcc)
 	if err != "":
@@ -1721,60 +1907,51 @@ def submit(ui, repo, *pats, **opts):
 		cl.Mail(ui, repo)
 
 	# submit changes locally
-	date = opts.get('date')
-	if date:
-		opts['date'] = util.parsedate(date)
-		typecheck(opts['date'], str)
-	opts['message'] = cl.desc.rstrip() + "\n\n" + about
-	typecheck(opts['message'], str)
-
-	if opts['dryrun']:
-		print "NOT SUBMITTING:"
-		print "User: ", userline
-		print "Message:"
-		print Indent(opts['message'], "\t")
-		print "Files:"
-		print Indent('\n'.join(cl.files), "\t")
-		return "dry run; not submitted"
+	message = cl.desc.rstrip() + "\n\n" + about
+	typecheck(message, str)
 
 	set_status("pushing " + cl.name + " to remote server")
-	m = match.exact(repo.root, repo.getcwd(), cl.files)
-	node = repo.commit(ustr(opts['message']), ustr(userline), opts.get('date'), m)
-	if not node:
-		return "nothing changed"
 
+	if hg_outgoing(ui, repo):
+		raise hg_util.Abort("local repository corrupt or out-of-phase with remote: found outgoing changes")
+	
+	old_heads = len(hg_heads(ui, repo).split())
+
+	global commit_okay
+	commit_okay = True
+	ret = hg_commit(ui, repo, *['path:'+f for f in cl.files], message=message, user=userline)
+	commit_okay = False
+	if ret:
+		return "nothing changed"
+	node = repo["-1"].node()
 	# push to remote; if it fails for any reason, roll back
 	try:
-		log = repo.changelog
-		rev = log.rev(node)
-		parents = log.parentrevs(rev)
-		if (rev-1 not in parents and
-				(parents == (nullrev, nullrev) or
-				len(log.heads(log.node(parents[0]))) > 1 and
-				(parents[1] == nullrev or len(log.heads(log.node(parents[1]))) > 1))):
-			# created new head
-			raise util.Abort("local repository out of date; must sync before submit")
-
-		# push changes to remote.
-		# if it works, we're committed.
-		# if not, roll back
-		other = getremote(ui, repo, opts)
-		r = repo.push(other, False, None)
-		if r == 0:
-			raise util.Abort("local repository out of date; must sync before submit")
+		new_heads = len(hg_heads(ui, repo).split())
+		if old_heads != new_heads and not (old_heads == 0 and new_heads == 1):
+			# Created new head, so we weren't up to date.
+			need_sync()
+
+		# Push changes to remote.  If it works, we're committed.  If not, roll back.
+		try:
+			hg_push(ui, repo)
+		except hg_error.Abort, e:
+			if e.message.find("push creates new heads") >= 0:
+				# Remote repository had changes we missed.
+				need_sync()
+			raise
 	except:
 		real_rollback()
 		raise
 
-	# we're committed. upload final patch, close review, add commit message
-	changeURL = short(node)
-	url = other.url()
+	# We're committed. Upload final patch, close review, add commit message.
+	changeURL = hg_node.short(node)
+	url = ui.expandpath("default")
 	m = re.match("^https?://([^@/]+@)?([^.]+)\.googlecode\.com/hg/?", url)
 	if m:
 		changeURL = "http://code.google.com/p/%s/source/detail?r=%s" % (m.group(2), changeURL)
 	else:
 		print >>sys.stderr, "URL: ", url
-	pmsg = "*** Submitted as " + changeURL + " ***\n\n" + opts['message']
+	pmsg = "*** Submitted as " + changeURL + " ***\n\n" + message
 
 	# When posting, move reviewers to CC line,
 	# so that the issue stops showing up in their "My Issues" page.
@@ -1783,53 +1960,38 @@ def submit(ui, repo, *pats, **opts):
 	if not cl.copied_from:
 		EditDesc(cl.name, closed=True, private=cl.private)
 	cl.Delete(ui, repo)
-	
+
 	c = repo[None]
 	if c.branch() == releaseBranch and not c.modified() and not c.added() and not c.removed():
 		ui.write("switching from %s to default branch.\n" % releaseBranch)
-		err = hg.clean(repo, "default")
+		err = hg_clean(repo, "default")
 		if err:
 			return err
 	return None
 
+#######################################################################
+# hg sync
+
 def sync(ui, repo, **opts):
 	"""synchronize with remote repository
 
 	Incorporates recent changes from the remote repository
 	into the local repository.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	if not opts["local"]:
-		ui.status = sync_note
-		ui.note = sync_note
-		other = getremote(ui, repo, opts)
-		modheads = repo.pull(other)
-		err = commands.postincoming(ui, repo, modheads, True, "tip")
+		err = hg_pull(ui, repo, update=True)
 		if err:
 			return err
-	commands.update(ui, repo, rev="default")
 	sync_changes(ui, repo)
 
-def sync_note(msg):
-	# we run sync (pull -u) in verbose mode to get the
-	# list of files being updated, but that drags along
-	# a bunch of messages we don't care about.
-	# omit them.
-	if msg == 'resolving manifests\n':
-		return
-	if msg == 'searching for changes\n':
-		return
-	if msg == "couldn't find merge tool hgmerge\n":
-		return
-	sys.stdout.write(msg)
-
 def sync_changes(ui, repo):
 	# Look through recent change log descriptions to find
 	# potential references to http://.*/our-CL-number.
 	# Double-check them by looking at the Rietveld log.
-	def Rev(rev):
+	for rev in hg_log(ui, repo, limit=100, template="{node}\n").split():
 		desc = repo[rev].description().strip()
 		for clname in re.findall('(?m)^http://(?:[^\n]+)/([0-9]+)$', desc):
 			if IsLocalCL(ui, repo, clname) and IsRietveldSubmitted(ui, clname, repo[rev].hex()):
@@ -1842,28 +2004,10 @@ def sync_changes(ui, repo):
 					EditDesc(cl.name, closed=True, private=cl.private)
 				cl.Delete(ui, repo)
 
-	if hgversion < '1.4':
-		get = util.cachefunc(lambda r: repo[r].changeset())
-		changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, [], get, {'rev': None})
-		n = 0
-		for st, rev, fns in changeiter:
-			if st != 'iter':
-				continue
-			n += 1
-			if n > 100:
-				break
-			Rev(rev)
-	else:
-		matchfn = scmutil.match(repo, [], {'rev': None})
-		def prep(ctx, fns):
-			pass
-		for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev': None}, prep):
-			Rev(ctx.rev())
-
 	# Remove files that are not modified from the CLs in which they appear.
 	all = LoadAllCL(ui, repo, web=False)
-	changed = ChangedFiles(ui, repo, [], {})
-	for _, cl in all.items():
+	changed = ChangedFiles(ui, repo, [])
+	for cl in all.values():
 		extra = Sub(cl.files, changed)
 		if extra:
 			ui.warn("Removing unmodified files from CL %s:\n" % (cl.name,))
@@ -1878,13 +2022,16 @@ def sync_changes(ui, repo):
 				ui.warn("CL %s has no files; delete locally with hg change -D %s\n" % (cl.name, cl.name))
 	return
 
+#######################################################################
+# hg upload
+
 def upload(ui, repo, name, **opts):
 	"""upload diffs to the code review server
 
 	Uploads the current modifications for a given change to the server.
 	"""
-	if missing_codereview:
-		return missing_codereview
+	if codereview_disabled:
+		return codereview_disabled
 
 	repo.ui.quiet = True
 	cl, err = LoadCL(ui, repo, name, web=True)
@@ -1896,6 +2043,9 @@ def upload(ui, repo, name, **opts):
 	print "%s%s\n" % (server_url_base, cl.name)
 	return
 
+#######################################################################
+# Table of commands, supplied to Mercurial for installation.
+
 review_opts = [
 	('r', 'reviewer', '', 'add reviewer'),
 	('', 'cc', '', 'add cc'),
@@ -1954,13 +2104,26 @@ cmdtable = {
 	),
 	"^pending|p": (
 		pending,
+		[
+			('s', 'short', False, 'show short result form'),
+			('', 'quick', False, 'do not consult codereview server'),
+		],
+		"[FILE ...]"
+	),
+	"^ps": (
+		ps,
+		[],
+		"[FILE ...]"
+	),
+	"^pq": (
+		pq,
 		[],
 		"[FILE ...]"
 	),
 	"^mail": (
 		mail,
 		review_opts + [
-		] + commands.walkopts,
+		] + hg_commands.walkopts,
 		"[-r reviewer] [--cc cc] [change# | file ...]"
 	),
 	"^release-apply": (
@@ -1976,8 +2139,7 @@ cmdtable = {
 		submit,
 		review_opts + [
 			('', 'no_incoming', None, 'disable initial incoming check (for testing)'),
-			('n', 'dryrun', None, 'make change only locally (for testing)'),
-		] + commands.walkopts + commands.commitopts + commands.commitopts2,
+		] + hg_commands.walkopts + hg_commands.commitopts + hg_commands.commitopts2,
 		"[-r reviewer] [--cc cc] [change# | file ...]"
 	),
 	"^sync": (
@@ -2002,10 +2164,63 @@ cmdtable = {
 	),
 }
 
+#######################################################################
+# Mercurial extension initialization
+
+def norollback(*pats, **opts):
+	"""(disabled when using this extension)"""
+	raise hg_util.Abort("codereview extension enabled; use undo instead of rollback")
+
+def reposetup(ui, repo):
+	global codereview_disabled
+	global defaultcc
+	
+	# Read repository-specific options from lib/codereview/codereview.cfg or codereview.cfg.
+	root = ''
+	try:
+		root = repo.root
+	except:
+		# Yes, repo might not have root; see issue 959.
+		codereview_disabled = 'codereview disabled: repository has no root'
+		return
+
+	repo_config_path = ''
+	p1 = root + '/lib/codereview/codereview.cfg'
+	p2 = root + '/codereview.cfg'
+	if os.access(p1, os.F_OK):
+		repo_config_path = p1
+	else:
+		repo_config_path = p2
+	try:
+		f = open(repo_config_path)
+		for line in f:
+			if line.startswith('defaultcc:'):
+				defaultcc = SplitCommaSpace(line[len('defaultcc:'):])
+			if line.startswith('contributors:'):
+				global contributorsURL
+				contributorsURL = line[len('contributors:'):].strip()
+	except:
+		codereview_disabled = 'codereview disabled: cannot open ' + repo_config_path
+		return
+
+	InstallMatch(ui, repo)
+	RietveldSetup(ui, repo)
+
+	# Disable the Mercurial commands that might change the repository.
+	# Only commands in this extension are supposed to do that.
+	ui.setconfig("hooks", "precommit.codereview", precommithook)
+
+	# Rollback removes an existing commit.  Don't do that either.
+	global real_rollback
+	real_rollback = repo.rollback
+	repo.rollback = norollback
+	
 
 #######################################################################
 # Wrappers around upload.py for interacting with Rietveld
 
+from HTMLParser import HTMLParser
+
 # HTML form parser
 class FormParser(HTMLParser):
 	def __init__(self):
@@ -2081,7 +2296,7 @@ def fix_json(x):
 		for k in todel:
 			del x[k]
 	else:
-		raise util.Abort("unknown type " + str(type(x)) + " in fix_json")
+		raise hg_util.Abort("unknown type " + str(type(x)) + " in fix_json")
 	if type(x) is str:
 		x = x.replace('\r\n', '\n')
 	return x
@@ -2284,68 +2499,13 @@ def PostMessage(ui, issue, message, reviewers=None, cc=None, send_mail=True, sub
 class opt(object):
 	pass
 
-def nocommit(*pats, **opts):
-	"""(disabled when using this extension)"""
-	raise util.Abort("codereview extension enabled; use mail, upload, or submit instead of commit")
-
-def nobackout(*pats, **opts):
-	"""(disabled when using this extension)"""
-	raise util.Abort("codereview extension enabled; use undo instead of backout")
-
-def norollback(*pats, **opts):
-	"""(disabled when using this extension)"""
-	raise util.Abort("codereview extension enabled; use undo instead of rollback")
-
 def RietveldSetup(ui, repo):
-	global defaultcc, upload_options, rpc, server, server_url_base, force_google_account, verbosity, contributors
-	global missing_codereview
-
-	repo_config_path = ''
-	# Read repository-specific options from lib/codereview/codereview.cfg
-	try:
-		repo_config_path = repo.root + '/lib/codereview/codereview.cfg'
-		f = open(repo_config_path)
-		for line in f:
-			if line.startswith('defaultcc: '):
-				defaultcc = SplitCommaSpace(line[10:])
-	except:
-		# If there are no options, chances are good this is not
-		# a code review repository; stop now before we foul
-		# things up even worse.  Might also be that repo doesn't
-		# even have a root.  See issue 959.
-		if repo_config_path == '':
-			missing_codereview = 'codereview disabled: repository has no root'
-		else:
-			missing_codereview = 'codereview disabled: cannot open ' + repo_config_path
-		return
-
-	# Should only modify repository with hg submit.
-	# Disable the built-in Mercurial commands that might
-	# trip things up.
-	cmdutil.commit = nocommit
-	global real_rollback
-	real_rollback = repo.rollback
-	repo.rollback = norollback
-	# would install nobackout if we could; oh well
-
-	try:
-		f = open(repo.root + '/CONTRIBUTORS', 'r')
-	except:
-		raise util.Abort("cannot open %s: %s" % (repo.root+'/CONTRIBUTORS', ExceptionDetail()))
-	for line in f:
-		# CONTRIBUTORS is a list of lines like:
-		#	Person <email>
-		#	Person <email> <alt-email>
-		# The first email address is the one used in commit logs.
-		if line.startswith('#'):
-			continue
-		m = re.match(r"([^<>]+\S)\s+(<[^<>\s]+>)((\s+<[^<>\s]+>)*)\s*$", line)
-		if m:
-			name = m.group(1)
-			email = m.group(2)[1:-1]
-			contributors[email.lower()] = (name, email)
-			for extra in m.group(3).split():
-				contributors[extra[1:-1].lower()] = (name, email)
+	global force_google_account
+	global rpc
+	global server
+	global server_url_base
+	global upload_options
+	global verbosity
 
 	if not ui.verbose:
 		verbosity = 0
@@ -2396,7 +2556,7 @@ def RietveldSetup(ui, repo):
 		# answer when comparing release-branch.r99 with
 		# release-branch.r100.  If we do ten releases a year
 		# that gives us 4 years before we have to worry about this.
-		raise util.Abort('tags.sort needs to be fixed for release-branch.r100')
+		raise hg_util.Abort('tags.sort needs to be fixed for release-branch.r100')
 	tags.sort()
 	for t in tags:
 		if t.startswith('release-branch.'):
@@ -3005,7 +3165,7 @@ class VersionControlSystem(object):
 				unused, filename = line.split(':', 1)
 				# On Windows if a file has property changes its filename uses '\'
 				# instead of '/'.
-				filename = filename.strip().replace('\\', '/')
+				filename = to_slash(filename.strip())
 				files[filename] = self.GetBaseFile(filename)
 		return files
 
@@ -3113,6 +3273,7 @@ class VersionControlSystem(object):
 			return False
 		return not mimetype.startswith("text/")
 
+
 class FakeMercurialUI(object):
 	def __init__(self):
 		self.quiet = True
@@ -3120,6 +3281,19 @@ class FakeMercurialUI(object):
 	
 	def write(self, *args, **opts):
 		self.output += ' '.join(args)
+	def copy(self):
+		return self
+	def status(self, *args, **opts):
+		pass
+	
+	def readconfig(self, *args, **opts):
+		pass
+	def expandpath(self, *args, **opts):
+		return global_ui.expandpath(*args, **opts)
+	def configitems(self, *args, **opts):
+		return global_ui.configitems(*args, **opts)
+	def config(self, *args, **opts):
+		return global_ui.config(*args, **opts)
 
 use_hg_shell = False	# set to True to shell out to hg always; slower
 
@@ -3130,6 +3304,7 @@ class MercurialVCS(VersionControlSystem):
 		super(MercurialVCS, self).__init__(options)
 		self.ui = ui
 		self.repo = repo
+		self.status = None
 		# Absolute path to repository (we can be in a subdir)
 		self.repo_dir = os.path.normpath(repo.root)
 		# Compute the subdir
@@ -3143,7 +3318,11 @@ class MercurialVCS(VersionControlSystem):
 			if not err and mqparent != "":
 				self.base_rev = mqparent
 			else:
-				self.base_rev = RunShell(["hg", "parents", "-q"]).split(':')[1].strip()
+				out = RunShell(["hg", "parents", "-q"], silent_ok=True).strip()
+				if not out:
+					# No revisions; use 0 to mean a repository with nothing.
+					out = "0:0"
+				self.base_rev = out.split(':')[1].strip()
 	def _GetRelPath(self, filename):
 		"""Get relative path of a file according to the current directory,
 		given its logical path in the repo."""
@@ -3188,6 +3367,33 @@ class MercurialVCS(VersionControlSystem):
 				unknown_files.append(fn)
 		return unknown_files
 
+	def get_hg_status(self, rev, path):
+		# We'd like to use 'hg status -C path', but that is buggy
+		# (see http://mercurial.selenic.com/bts/issue3023).
+		# Instead, run 'hg status -C' without a path
+		# and skim the output for the path we want.
+		if self.status is None:
+			if use_hg_shell:
+				out = RunShell(["hg", "status", "-C", "--rev", rev])
+			else:
+				fui = FakeMercurialUI()
+				ret = hg_commands.status(fui, self.repo, *[], **{'rev': [rev], 'copies': True})
+				if ret:
+					raise hg_util.Abort(ret)
+				out = fui.output
+			self.status = out.splitlines()
+		for i in range(len(self.status)):
+			# line is
+			#	A path
+			#	M path
+			# etc
+			line = to_slash(self.status[i])
+			if line[2:] == path:
+				if i+1 < len(self.status) and self.status[i+1][:2] == '  ':
+					return self.status[i:i+2]
+				return self.status[i:i+1]
+		raise hg_util.Abort("no status for " + path)
+	
 	def GetBaseFile(self, filename):
 		set_status("inspecting " + filename)
 		# "hg status" and "hg cat" both take a path relative to the current subdir
@@ -3197,20 +3403,7 @@ class MercurialVCS(VersionControlSystem):
 		new_content = None
 		is_binary = False
 		oldrelpath = relpath = self._GetRelPath(filename)
-		# "hg status -C" returns two lines for moved/copied files, one otherwise
-		if use_hg_shell:
-			out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath])
-		else:
-			fui = FakeMercurialUI()
-			ret = commands.status(fui, self.repo, *[relpath], **{'rev': [self.base_rev], 'copies': True})
-			if ret:
-				raise util.Abort(ret)
-			out = fui.output
-		out = out.splitlines()
-		# HACK: strip error message about missing file/directory if it isn't in
-		# the working copy
-		if out[0].startswith('%s: ' % relpath):
-			out = out[1:]
+		out = self.get_hg_status(self.base_rev, relpath)
 		status, what = out[0].split(' ', 1)
 		if len(out) > 1 and status == "A" and what == relpath:
 			oldrelpath = out[1].strip()
@@ -3261,7 +3454,7 @@ def SplitPatch(data):
 			# When a file is modified, paths use '/' between directories, however
 			# when a property is modified '\' is used on Windows.  Make them the same
 			# otherwise the file shows up twice.
-			temp_filename = temp_filename.strip().replace('\\', '/')
+			temp_filename = to_slash(temp_filename.strip())
 			if temp_filename != filename:
 				# File has property changes but no modifications, create a new diff.
 				new_filename = temp_filename
diff --git a/lib/codereview/test.sh b/lib/codereview/test.sh
new file mode 100755
index 0000000..13f2b9c
--- /dev/null
+++ b/lib/codereview/test.sh
@@ -0,0 +1,198 @@
+#!/bin/bash
+# Copyright 2011 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 the code review plugin.
+# Assumes a local Rietveld is running using the App Engine SDK
+# at http://localhost:7777/
+#
+# dev_appserver.py -p 7777 $HOME/pub/rietveld
+
+codereview_script=$(pwd)/codereview.py
+server=localhost:7777
+master=/tmp/go.test
+clone1=/tmp/go.test1
+clone2=/tmp/go.test2
+export HGEDITOR=true
+
+must() {
+	if ! "$@"; then
+		echo "$@" failed >&2
+		exit 1
+	fi
+}
+
+not() {
+	if "$@"; then
+		false
+	else
+		true
+	fi
+}
+
+status() {
+	echo '+++' "$@" >&2
+}
+
+firstcl() {
+	hg pending | sed 1q | tr -d ':'
+}
+
+# Initial setup.
+status Create repositories.
+rm -rf $master $clone1 $clone2
+mkdir $master
+cd $master
+must hg init .
+echo Initial state >file
+must hg add file
+must hg ci -m 'first commit' file
+must hg clone $master $clone1
+must hg clone $master $clone2
+
+echo "
+[ui]
+username=Grace R Emlin <gre at golang.org>
+[extensions]
+codereview=$codereview_script
+[codereview]
+server=$server
+" >>$clone1/.hg/hgrc
+cp $clone1/.hg/hgrc $clone2/.hg/hgrc
+
+status Codereview should be disabled.
+cd $clone1
+must hg status
+must not hg pending
+
+status Enabling code review.
+must mkdir lib lib/codereview
+must touch lib/codereview/codereview.cfg
+
+status Code review should work even without CONTRIBUTORS.
+must hg pending
+
+status Add CONTRIBUTORS.
+echo 'Grace R Emlin <gre at golang.org>' >CONTRIBUTORS
+must hg add lib/codereview/codereview.cfg CONTRIBUTORS
+
+status First submit.
+must hg submit -r gre at golang.org -m codereview \
+	lib/codereview/codereview.cfg CONTRIBUTORS
+
+status Should see change in other client.
+cd $clone2
+must hg pull -u
+must test -f lib/codereview/codereview.cfg
+must test -f CONTRIBUTORS
+
+test_clpatch() {
+	# The email address must be test at example.com to match
+	# the test code review server's default user.
+	# Clpatch will check.
+	
+	cd $clone1
+	# Tried to use UTF-8 here to test that, but dev_appserver.py crashes.  Ha ha.
+	if false; then
+		status Using UTF-8.
+		name="Grácè T Emlïn <test at example.com>"
+	else
+		status Using ASCII.
+		name="Grace T Emlin <test at example.com>"
+	fi
+	echo "$name" >>CONTRIBUTORS
+	cat .hg/hgrc | sed "s/Grace.*/$name/" >/tmp/x && mv /tmp/x .hg/hgrc
+	echo '
+Reviewer: gre at golang.org
+Description:
+	CONTRIBUTORS: add $name
+Files:
+	CONTRIBUTORS
+'	| must hg change -i
+	num=$(hg pending | sed 1q | tr -d :)
+	
+	status Patch CL.
+	cd $clone2
+	must hg clpatch $num
+	must [ "$num" = "$(firstcl)" ]
+	must hg submit $num
+	
+	status Issue should be open with no reviewers.
+	must curl http://$server/api/$num >/tmp/x
+	must not grep '"closed":true' /tmp/x
+	must grep '"reviewers":\[\]' /tmp/x
+	
+	status Sync should close issue.
+	cd $clone1
+	must hg sync
+	must curl http://$server/api/$num >/tmp/x
+	must grep '"closed":true' /tmp/x
+	must grep '"reviewers":\[\]' /tmp/x
+	must [ "$(firstcl)" = "" ]
+}
+
+test_reviewer() {
+	status Submit without reviewer should fail.
+	cd $clone1
+	echo dummy >dummy
+	must hg add dummy
+	echo '
+Description:
+	no reviewer
+Files:
+	dummy
+'	| must hg change -i
+	num=$(firstcl)
+	must not hg submit $num
+	must hg revert dummy
+	must rm dummy
+	must hg change -d $num
+}
+
+test_linearity() {
+	status Linearity of changes.
+	cd $clone1
+	echo file1 >file1
+	must hg add file1
+	echo '
+Reviewer: gre at golang.org
+Description: file1
+Files: file1
+	' | must hg change -i
+	must hg submit $(firstcl)
+	
+	cd $clone2
+	echo file2 >file2
+	must hg add file2
+	echo '
+Reviewer: gre at golang.org
+Description: file2
+Files: file2
+	' | must hg change -i
+	must not hg submit $(firstcl)
+	must hg sync
+	must hg submit $(firstcl)
+}
+
+test_restrict() {
+	status Cannot use hg ci.
+	cd $clone1
+	echo file1a >file1a
+	hg add file1a
+	must not hg ci -m commit file1a
+	must rm file1a
+	must hg revert file1a
+	
+	status Cannot use hg rollback.
+	must not hg rollback
+	
+	status Cannot use hg backout
+	must not hg backout -r -1
+}
+
+test_reviewer
+test_clpatch
+test_linearity
+test_restrict
+status ALL TESTS PASSED.
diff --git a/lib/godoc/example.html b/lib/godoc/example.html
new file mode 100644
index 0000000..7af9431
--- /dev/null
+++ b/lib/godoc/example.html
@@ -0,0 +1,14 @@
+<div class="example">
+	<div class="collapsed">
+		<p class="exampleHeading">â–¹ Example</p>
+	</div>
+	<div class="expanded">
+		<p class="exampleHeading">â–¾ Example</p>
+		<p>Code:</p>
+		<pre class="code">{{.Code}}</pre>
+		{{if .Output}}
+		<p>Output:</p>
+		<pre class="output">{{html .Output}}</pre>
+		{{end}}
+	</div>
+</div>
diff --git a/lib/godoc/godoc.html b/lib/godoc/godoc.html
index 671160d..e99b758 100644
--- a/lib/godoc/godoc.html
+++ b/lib/godoc/godoc.html
@@ -12,6 +12,9 @@
 <link rel="stylesheet" href="/doc/ie.css" type="text/css">
 <![endif]-->
 <script type="text/javascript" src="/doc/godocs.js"></script>
+{{if .SearchBox}}
+<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
+{{end}}
 </head>
 <body>
 <div id="container">
diff --git a/lib/godoc/opensearch.xml b/lib/godoc/opensearch.xml
new file mode 100644
index 0000000..1b652db
--- /dev/null
+++ b/lib/godoc/opensearch.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>godoc</ShortName>
+  <Description>The Go Programming Language</Description>
+  <Tags>go golang</Tags>
+  <Contact />
+  <Url type="text/html" template="{{.BaseURL}}/search?q={searchTerms}" />
+  <Image height="15" width="16" type="image/x-icon">/favicon.ico</Image>
+  <OutputEncoding>UTF-8</OutputEncoding>
+  <InputEncoding>UTF-8</InputEncoding>
+</OpenSearchDescription>
diff --git a/lib/godoc/package.html b/lib/godoc/package.html
index 559fe2d..c7a01a8 100644
--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -3,56 +3,92 @@
 	Use of this source code is governed by a BSD-style
 	license that can be found in the LICENSE file.
 -->
-{{with .PAst}}
-	<pre>{{node_html . $.FSet}}</pre>
-{{end}}
 {{with .PDoc}}
-	<!-- PackageName is printed as title by the top-level template -->
-	{{if $.IsPkg}}
-		<p><code>import "{{html .ImportPath}}"</code></p>
-	{{end}}
-	{{comment_html .Doc}}
 	{{if $.IsPkg}}
-		{{with .Filenames}}
-			<p>
-			<h4>Package files</h4>
-			<span style="font-size:90%">
+		<div id="short-nav">
+			<dl>
+			<dd><code>import "{{html .ImportPath}}"</code></dd>
+			</dl>
+			<dl>
+			<dd><a href="#Overview">Overview</a></dd>
+			<dd><a href="#Index">Index</a></dd>
+			</dl>
+		</div>
+		<h2 id="Overview">Overview</h2>
+		<!-- The package's Name is printed as title by the top-level template -->
+		{{comment_html .Doc}}
+	
+		<h2 id="Index">Index</h2>
+		<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
+		<div id="manual-nav">
+			<dl>
+			{{if .Consts}}
+				<dd><a href="#Constants">Constants</a></dd>
+			{{end}}
+			{{if .Vars}}
+				<dd><a href="#Variables">Variables</a></dd>
+			{{end}}
+			{{range .Funcs}}
+				{{$name_html := html .Name}}
+				<dd><a href="#{{$name_html}}">{{node_html .Decl $.FSet}}</a></dd>
+			{{end}}
+			{{range .Types}}
+				{{$tname_html := html .Name}}
+				<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
+				{{range .Funcs}}
+					{{$name_html := html .Name}}
+					<dd>    <a href="#{{$name_html}}">{{node_html .Decl $.FSet}}</a></dd>
+				{{end}}
+				{{range .Methods}}
+					{{$name_html := html .Name}}
+					<dd>    <a href="#{{$tname_html}}.{{$name_html}}">{{node_html .Decl $.FSet}}</a></dd>
+				{{end}}
+			{{end}}
+			{{if .Bugs}}
+				<dd><a href="#Bugs">Bugs</a></dd>
+			{{end}}
+			<dd>
+			{{with .Filenames}}
+				<h4>Package files</h4>
+				<p>
+				<span style="font-size:90%">
+				{{range .}}
+					<a href="/{{.|srcLink}}">{{.|filename|html}}</a>
+				{{end}}
+				</span>
+				</p>
+			{{end}}
+			</dd>
+		</dl>
+	
+		{{with .Consts}}
+			<h2 id="Constants">Constants</h2>
 			{{range .}}
-				<a href="/{{.|srcLink}}">{{.|filename|html}}</a>
+				{{comment_html .Doc}}
+				<pre>{{node_html .Decl $.FSet}}</pre>
 			{{end}}
-			</span>
-			</p>
-		{{end}}
-	{{end}}
-	{{with .Consts}}
-		<h2 id="Constants">Constants</h2>
-		{{range .}}
-			{{comment_html .Doc}}
-			<pre>{{node_html .Decl $.FSet}}</pre>
 		{{end}}
-	{{end}}
-	{{with .Vars}}
-		<h2 id="Variables">Variables</h2>
-		{{range .}}
-			{{comment_html .Doc}}
-			<pre>{{node_html .Decl $.FSet}}</pre>
+		{{with .Vars}}
+			<h2 id="Variables">Variables</h2>
+			{{range .}}
+				{{comment_html .Doc}}
+				<pre>{{node_html .Decl $.FSet}}</pre>
+			{{end}}
 		{{end}}
-	{{end}}
-	{{with .Funcs}}
-		{{range .}}
+		{{range .Funcs}}
 			{{/* Name is a string - no need for FSet */}}
 			{{$name_html := html .Name}}
 			<h2 id="{{$name_html}}">func <a href="/{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h2>
 			<p><code>{{node_html .Decl $.FSet}}</code></p>
 			{{comment_html .Doc}}
+			{{example_html .Name $.Examples $.FSet}}
 		{{end}}
-	{{end}}
-	{{with .Types}}
-		{{range .}}
-			{{$tname_html := node_html .Type.Name $.FSet}}
+		{{range .Types}}
+			{{$tname := .Name}}
+			{{$tname_html := html .Name}}
 			<h2 id="{{$tname_html}}">type <a href="/{{posLink_url .Decl $.FSet}}">{{$tname_html}}</a></h2>
 			{{comment_html .Doc}}
-			<p><pre>{{node_html .Decl $.FSet}}</pre></p>
+			<pre>{{node_html .Decl $.FSet}}</pre>
 			{{range .Consts}}
 				{{comment_html .Doc}}
 				<pre>{{node_html .Decl $.FSet}}</pre>
@@ -61,20 +97,27 @@
 				{{comment_html .Doc}}
 				<pre>{{node_html .Decl $.FSet}}</pre>
 			{{end}}
-			{{range .Factories}}
+			{{example_html $tname $.Examples $.FSet}}
+			{{range .Funcs}}
 				{{$name_html := html .Name}}
 				<h3 id="{{$name_html}}">func <a href="/{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h3>
 				<p><code>{{node_html .Decl $.FSet}}</code></p>
 				{{comment_html .Doc}}
+				{{example_html .Name $.Examples $.FSet}}
 			{{end}}
 			{{range .Methods}}
 				{{$name_html := html .Name}}
-				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{node_html .Recv $.FSet}}) <a href="/{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h3>
+				<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="/{{posLink_url .Decl $.FSet}}">{{$name_html}}</a></h3>
 				<p><code>{{node_html .Decl $.FSet}}</code></p>
 				{{comment_html .Doc}}
+				{{$name := printf "%s_%s" $tname .Name}}
+				{{example_html $name $.Examples $.FSet}}
 			{{end}}
 		{{end}}
+	{{else}}  {{/* not a package; is a command */}}
+		{{comment_html .Doc}}
 	{{end}}
+
 	{{with .Bugs}}
 		<h2 id="Bugs">Bugs</h2>
 		{{range .}}
@@ -82,6 +125,11 @@
 		{{end}}
 	{{end}}
 {{end}}
+
+{{with .PAst}}
+	<pre>{{node_html . $.FSet}}</pre>
+{{end}}
+
 {{with .PList}}
 	<h2>Other packages</h2>
 	<p>
@@ -91,28 +139,32 @@
 	{{end}}
 	</p>
 {{end}}
+
 {{with .Dirs}}
-	<p class="detail">
-	Need more packages? The
-	<a href="http://godashboard.appspot.com/package">Package Dashboard</a>
-	provides a list of <a href="/cmd/goinstall/">goinstallable</a> packages.
-	</p>
 	{{/* DirList entries are numbers and strings - no need for FSet */}}
 	<h2 id="Subdirectories">Subdirectories</h2>
 	<p>
 	<table class="layout">
 	<tr>
-	<th align="left" colspan="{{html .MaxHeight}}">Name</th>
-	<td width="25"> </td>
+	{{if $.DirFlat}}
+		<th align="left">Name</th>
+	{{else}}
+		<th align="left" colspan="{{html .MaxHeight}}">Name</th>
+	{{end}}
+	<th width="25"></th>
 	<th align="left">Synopsis</th>
 	</tr>
 	<tr>
-	<th align="left"><a href="..">..</a></th>
+	<td align="left"><a href="..">..</a></td>
 	</tr>
 	{{range .List}}
 		<tr>
-		{{repeat `<td width="25"></td>` .Depth}}
-		<td align="left" colspan="{{html .Height}}"><a href="{{html .Path}}">{{html .Name}}</a></td>
+		{{if $.DirFlat}}
+			<td align="left"><a href="{{html .Path}}">{{html .Path}}</a></td>
+		{{else}}
+			{{repeat `<td width="20"></td>` .Depth}}
+			<td align="left" colspan="{{html .Height}}"><a href="{{html .Path}}">{{html .Name}}</a></td>
+		{{end}}
 		<td></td>
 		<td align="left">{{html .Synopsis}}</td>
 		</tr>
diff --git a/lib/godoc/package.txt b/lib/godoc/package.txt
index 179b334..d88cda7 100644
--- a/lib/godoc/package.txt
+++ b/lib/godoc/package.txt
@@ -4,12 +4,12 @@
 
 */}}{{with .PDoc}}{{if $.IsPkg}}PACKAGE
 
-package {{.PackageName}}
-import "{{.ImportPath}}"
+package {{.Name}}
+    import "{{.ImportPath}}"
 
 {{else}}COMMAND DOCUMENTATION
 
-{{end}}{{.Doc}}{{/*
+{{end}}{{comment_text .Doc "    " "\t"}}{{/*
 
 ---------------------------------------
 
@@ -17,7 +17,7 @@ import "{{.ImportPath}}"
 CONSTANTS
 
 {{range .}}{{node .Decl $.FSet}}
-{{.Doc}}{{end}}
+{{comment_text .Doc "    " "\t"}}{{end}}
 {{end}}{{/*
 
 ---------------------------------------
@@ -26,7 +26,7 @@ CONSTANTS
 VARIABLES
 
 {{range .}}{{node .Decl $.FSet}}
-{{.Doc}}{{end}}
+{{comment_text .Doc "    " "\t"}}{{end}}
 {{end}}{{/*
 
 ---------------------------------------
@@ -35,7 +35,7 @@ VARIABLES
 FUNCTIONS
 
 {{range .}}{{node .Decl $.FSet}}
-{{.Doc}}
+{{comment_text .Doc "    " "\t"}}
 {{end}}{{end}}{{/*
 
 ---------------------------------------
@@ -44,15 +44,15 @@ FUNCTIONS
 TYPES
 
 {{range .}}{{node .Decl $.FSet}}
-{{.Doc}}
+{{comment_text .Doc "    " "\t"}}
 {{range .Consts}}{{node .Decl $.FSet}}
-{{.Doc}}
+{{comment_text .Doc "    " "\t"}}
 {{end}}{{range .Vars}}{{node .Decl $.FSet}}
-{{.Doc}}
-{{end}}{{range .Factories}}{{node .Decl $.FSet}}
-{{.Doc}}
+{{comment_text .Doc "    " "\t"}}
+{{end}}{{range .Funcs}}{{node .Decl $.FSet}}
+{{comment_text .Doc "    " "\t"}}
 {{end}}{{range .Methods}}{{node .Decl $.FSet}}
-{{.Doc}}
+{{comment_text .Doc "    " "\t"}}
 {{end}}{{end}}{{end}}{{/*
 
 ---------------------------------------
@@ -60,7 +60,7 @@ TYPES
 */}}{{with .Bugs}}
 BUGS
 
-{{range .}}{{.}}
+{{range .}}{{comment_text . "    " "\t"}}
 {{end}}{{end}}{{end}}{{/*
 
 ---------------------------------------
@@ -76,7 +76,8 @@ OTHER PACKAGES
 
 */}}{{with .Dirs}}
 SUBDIRECTORIES
-
-{{range .List}}
-	{{.Name}}{{end}}
-{{end}}
+{{if $.DirFlat}}{{range .List}}
+	{{.Path}}{{end}}
+{{else}}{{range .List}}
+	{{repeat `. ` .Depth}}{{.Name}}{{end}}
+{{end}}{{end}}
diff --git a/misc/bbedit/Go.plist b/misc/bbedit/Go.plist
index 4553535..791f93d 100755
--- a/misc/bbedit/Go.plist
+++ b/misc/bbedit/Go.plist
@@ -23,6 +23,7 @@
 		default,      
 		defer,
 		else,
+		error,
 		fallthrough,
 		false,
 		float32,
@@ -54,6 +55,7 @@
 		real,
 		recover,
 		return,
+		rune,
 		select,
 		string,
 		struct,
diff --git a/misc/benchcmp b/misc/benchcmp
new file mode 100755
index 0000000..24382b2
--- /dev/null
+++ b/misc/benchcmp
@@ -0,0 +1,66 @@
+#!/bin/sh
+# Copyright 2011 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.
+
+case "$1" in
+-*)	
+	echo 'usage: benchcmp old.txt new.txt' >&2
+	echo >&2
+	echo 'Each input file should be gotest -bench output.' >&2
+	echo 'Benchcmp compares the first and last for each benchmark.' >&2
+	exit 2
+esac
+
+awk '
+BEGIN {
+	n = 0
+}
+
+$1 ~ /Benchmark/ && $4 == "ns/op" {
+	if(old[$1]) {
+		if(!saw[$1]++) {
+			name[n++] = $1
+			if(length($1) > len)
+				len = length($1)
+		}
+		new[$1] = $3
+		if($6 == "MB/s")
+			newmb[$1] = $5
+	} else {
+		old[$1] = $3
+		if($6 = "MB/s")
+			oldmb[$1] = $5
+	}
+}
+
+END {
+	if(n == 0) {
+		print "benchcmp: no repeated benchmarks" >"/dev/stderr"
+		exit 1
+	}
+
+	printf("%-*s %12s %12s  %7s\n", len, "benchmark", "old ns/op", "new ns/op", "delta")
+
+	# print ns/op
+	for(i=0; i<n; i++) {
+		what = name[i]
+		printf("%-*s %12d %12d  %6s%%\n", len, what, old[what], new[what],
+			sprintf("%+.2f", 100*new[what]/old[what]-100))
+	}
+
+	# print mb/s
+	anymb = 0
+	for(i=0; i<n; i++) {
+		what = name[i]
+		if(!(what in newmb))
+			continue
+		if(anymb++ == 0)
+			printf("\n%-*s %12s %12s  %7s\n", len, "benchmark", "old MB/s", "new MB/s", "speedup")
+		printf("%-*s %12s %12s  %6sx\n", len, what,
+			sprintf("%.2f", oldmb[what]),
+			sprintf("%.2f", newmb[what]),
+			sprintf("%.2f", newmb[what]/oldmb[what]))
+	}
+}
+' "$@"
diff --git a/misc/cgo/gmp/Makefile b/misc/cgo/gmp/Makefile
index fc6209f..d9390c1 100644
--- a/misc/cgo/gmp/Makefile
+++ b/misc/cgo/gmp/Makefile
@@ -28,11 +28,11 @@ include ../../../src/Make.pkg
 
 # Computes 1000 digits of pi; single-threaded.
 pi: install pi.go
-	$(GC) pi.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) pi.go
 	$(LD) -o $@ pi.$O
 
 # Computes 200 Fibonacci numbers; multi-threaded.
 fib: install fib.go
-	$(GC) fib.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) fib.go
 	$(LD) -o $@ fib.$O
 
diff --git a/misc/cgo/gmp/gmp.go b/misc/cgo/gmp/gmp.go
index 3dbc022..9325d8b 100644
--- a/misc/cgo/gmp/gmp.go
+++ b/misc/cgo/gmp/gmp.go
@@ -179,7 +179,7 @@ func (z *Int) SetInt64(x int64) *Int {
 // SetString interprets s as a number in the given base
 // and sets z to that value.  The base must be in the range [2,36].
 // SetString returns an error if s cannot be parsed or the base is invalid.
-func (z *Int) SetString(s string, base int) os.Error {
+func (z *Int) SetString(s string, base int) error {
 	z.doinit()
 	if base < 2 || base > 36 {
 		return os.EINVAL
diff --git a/misc/cgo/gmp/pi.go b/misc/cgo/gmp/pi.go
index 45f61ab..3e40624 100644
--- a/misc/cgo/gmp/pi.go
+++ b/misc/cgo/gmp/pi.go
@@ -38,8 +38,8 @@ POSSIBILITY OF SUCH DAMAGE.
 package main
 
 import (
-	big "gmp"
 	"fmt"
+	big "gmp"
 	"runtime"
 )
 
diff --git a/misc/cgo/life/Makefile b/misc/cgo/life/Makefile
index 39ec13b..1568a67 100644
--- a/misc/cgo/life/Makefile
+++ b/misc/cgo/life/Makefile
@@ -11,7 +11,7 @@ CGOFILES=\
 
 CGO_OFILES=\
 	c-life.o\
-	
+
 ifeq ($(GOOS),windows)
 ifeq ($(GOARCH),amd64)
 CGO_OFILES+=\
@@ -31,5 +31,5 @@ CLEANFILES+=life
 include ../../../src/Make.pkg
 
 life: install main.go
-	$(GC) main.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) main.go
 	$(LD) -o $@ main.$O
diff --git a/misc/cgo/stdio/Makefile b/misc/cgo/stdio/Makefile
index 3f7a4c0..586132b 100644
--- a/misc/cgo/stdio/Makefile
+++ b/misc/cgo/stdio/Makefile
@@ -13,5 +13,5 @@ CLEANFILES+=hello fib chain run.out
 include ../../../src/Make.pkg
 
 %: install %.go
-	$(GC) $*.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) $*.go
 	$(LD) -o $@ $*.$O
diff --git a/misc/cgo/stdio/fib.go b/misc/cgo/stdio/fib.go
index c02e31f..431d9ce 100644
--- a/misc/cgo/stdio/fib.go
+++ b/misc/cgo/stdio/fib.go
@@ -26,7 +26,7 @@ func fibber(c, out chan int64, i int64) {
 	}
 	for {
 		j := <-c
-		stdio.Stdout.WriteString(strconv.Itoa64(j) + "\n")
+		stdio.Stdout.WriteString(strconv.FormatInt(j, 10) + "\n")
 		out <- j
 		<-out
 		i += j
diff --git a/misc/cgo/test/Makefile b/misc/cgo/test/Makefile
index 5617e78..4c1680d 100644
--- a/misc/cgo/test/Makefile
+++ b/misc/cgo/test/Makefile
@@ -16,6 +16,7 @@ CGOFILES=\
 	issue1222.go\
 	issue1328.go\
 	issue1560.go\
+	issue2462.go\
 	duplicate_symbol.go\
 
 CGO_OFILES=\
@@ -24,4 +25,21 @@ CGO_OFILES=\
 OFILES=\
 	runtime.$O\
 
+ifeq ($(GOOS),windows)
+GCCVERSION=$(shell gcc -dumpversion)
+ifeq ($(GOARCH),386)
+GCCLIBDIR=/mingw/lib/gcc/mingw32/$(GCCVERSION)
+CHKSTK=_chkstk.o
+else
+GCCLIBDIR=/mingw/lib/gcc/x86_64-w64-mingw32/$(GCCVERSION)
+CHKSTK=_chkstk_ms.o
+endif
+
+CGOFILES+=sleep_windows.go
+CGO_OFILES+=$(CHKSTK)
+
+$(CHKSTK):
+	ar -x "$(GCCLIBDIR)/libgcc.a" $@
+endif
+
 include ../../../src/Make.pkg
diff --git a/misc/cgo/test/align.go b/misc/cgo/test/align.go
index 07ab9ef..a23b44f 100644
--- a/misc/cgo/test/align.go
+++ b/misc/cgo/test/align.go
@@ -1,3 +1,7 @@
+// Copyright 2010 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
 
 /*
diff --git a/misc/cgo/test/basic.go b/misc/cgo/test/basic.go
index 626e0e9..7aaae15 100644
--- a/misc/cgo/test/basic.go
+++ b/misc/cgo/test/basic.go
@@ -69,18 +69,7 @@ func uuidgen() {
 	C.uuid_generate(&uuid[0])
 }
 
-func Size(name string) (int64, os.Error) {
-	var st C.struct_stat
-	p := C.CString(name)
-	_, err := C.stat(p, &st)
-	C.free(unsafe.Pointer(p))
-	if err != nil {
-		return 0, err
-	}
-	return int64(C.ulong(st.st_size)), nil
-}
-
-func Strtol(s string, base int) (int, os.Error) {
+func Strtol(s string, base int) (int, error) {
 	p := C.CString(s)
 	n, err := C.strtol(p, nil, C.int(base))
 	C.free(unsafe.Pointer(p))
@@ -112,9 +101,17 @@ func testAtol(t *testing.T) {
 }
 
 func testErrno(t *testing.T) {
-	n, err := Strtol("asdf", 123)
-	if n != 0 || err != os.EINVAL {
-		t.Error("Strtol: ", n, err)
+	p := C.CString("no-such-file")
+	m := C.CString("r")
+	f, err := C.fopen(p, m)
+	C.free(unsafe.Pointer(p))
+	C.free(unsafe.Pointer(m))
+	if err == nil {
+		C.fclose(f)
+		t.Fatalf("C.fopen: should fail")
+	}
+	if err != os.ENOENT {
+		t.Fatalf("C.fopen: unexpected error: ", err)
 	}
 }
 
@@ -128,9 +125,9 @@ func testMultipleAssign(t *testing.T) {
 }
 
 var (
-	uint  = (C.uint)(0)
-	ulong C.ulong
-	char  C.char
+	cuint  = (C.uint)(0)
+	culong C.ulong
+	cchar  C.char
 )
 
 type Context struct {
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
index d20790e..ef85256 100644
--- a/misc/cgo/test/callback.go
+++ b/misc/cgo/test/callback.go
@@ -1,3 +1,7 @@
+// Copyright 2011 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
 
 /*
diff --git a/misc/cgo/test/callback_c.c b/misc/cgo/test/callback_c.c
index 5983a5e..c296d70 100644
--- a/misc/cgo/test/callback_c.c
+++ b/misc/cgo/test/callback_c.c
@@ -8,5 +8,10 @@
 void
 callback(void *f)
 {
+	// use some stack space
+	volatile char data[64*1024];
+
+	data[0] = 0;
 	goCallback(f);
+        data[sizeof(data)-1] = 0;
 }
diff --git a/misc/cgo/test/env.go b/misc/cgo/test/env.go
index 1fb4e68..8d3ba58 100644
--- a/misc/cgo/test/env.go
+++ b/misc/cgo/test/env.go
@@ -10,12 +10,21 @@ package cgotest
 import "C"
 import (
 	"os"
+	"runtime"
 	"testing"
 	"unsafe"
 )
 
 // This is really an os package test but here for convenience.
 func testSetEnv(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		// Go uses SetEnvironmentVariable on windows. Howerver,
+		// C runtime takes a *copy* at process startup of thei
+		// OS environment, and stores it in environ/envp.
+		// It is this copy that	getenv/putenv manipulate.
+		t.Logf("skipping test")
+		return
+	}
 	const key = "CGO_OS_TEST_KEY"
 	const val = "CGO_OS_TEST_VALUE"
 	os.Setenv(key, val)
diff --git a/misc/cgo/test/helpers.go b/misc/cgo/test/helpers.go
index de14d19..890dcbd 100644
--- a/misc/cgo/test/helpers.go
+++ b/misc/cgo/test/helpers.go
@@ -29,7 +29,7 @@ var testPairs = []testPair{
 func testHelpers(t *testing.T) {
 	for _, pair := range testPairs {
 		if !reflect.DeepEqual(pair.Got, pair.Want) {
-			t.Errorf("%s: got %#v, want %#v", pair.Got, pair.Want)
+			t.Errorf("%s: got %#v, want %#v", pair.Name, pair.Got, pair.Want)
 		}
 	}
 }
diff --git a/misc/cgo/test/issue1560.go b/misc/cgo/test/issue1560.go
index e534cce..833b14a 100644
--- a/misc/cgo/test/issue1560.go
+++ b/misc/cgo/test/issue1560.go
@@ -7,6 +7,8 @@ package cgotest
 /*
 #include <unistd.h>
 
+unsigned int sleep(unsigned int seconds);
+
 extern void BackgroundSleep(int);
 void twoSleep(int n) {
 	BackgroundSleep(n);
@@ -36,11 +38,11 @@ func BackgroundSleep(n int) {
 }
 
 func testParallelSleep(t *testing.T) {
-	dt := -time.Nanoseconds()
+	start := time.Now()
 	parallelSleep(1)
-	dt += time.Nanoseconds()
+	dt := time.Now().Sub(start)
 	// bug used to run sleeps in serial, producing a 2-second delay.
-	if dt >= 1.3e9 {
-		t.Fatalf("parallel 1-second sleeps slept for %f seconds", float64(dt)/1e9)
+	if dt >= 1300*time.Millisecond {
+		t.Fatalf("parallel 1-second sleeps slept for %f seconds", dt.Seconds())
 	}
 }
diff --git a/misc/cgo/test/issue2462.go b/misc/cgo/test/issue2462.go
new file mode 100644
index 0000000..12cd91d
--- /dev/null
+++ b/misc/cgo/test/issue2462.go
@@ -0,0 +1,102 @@
+// Copyright 2011 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
+
+import "C"
+
+//export exportbyte
+func exportbyte() byte {
+	return 0
+}
+
+//export exportbool
+func exportbool() bool {
+	return false
+}
+
+//export exportrune
+func exportrune() rune {
+	return 0
+}
+
+//export exporterror
+func exporterror() error {
+	return nil
+}
+
+//export exportint
+func exportint() int {
+	return 0
+}
+
+//export exportuint
+func exportuint() uint {
+	return 0
+}
+
+//export exportuintptr
+func exportuintptr() uintptr {
+	return (uintptr)(0)
+}
+
+//export exportint8
+func exportint8() int8 {
+	return 0
+}
+
+//export exportuint8
+func exportuint8() uint8 {
+	return 0
+}
+
+//export exportint16
+func exportint16() int16 {
+	return 0
+}
+
+//export exportuint16
+func exportuint16() uint16 {
+	return 0
+}
+
+//export exportint32
+func exportint32() int32 {
+	return 0
+}
+
+//export exportuint32
+func exportuint32() uint32 {
+	return 0
+}
+
+//export exportint64
+func exportint64() int64 {
+	return 0
+}
+
+//export exportuint64
+func exportuint64() uint64 {
+	return 0
+}
+
+//export exportfloat32
+func exportfloat32() float32 {
+	return 0
+}
+
+//export exportfloat64
+func exportfloat64() float64 {
+	return 0
+}
+
+//export exportcomplex64
+func exportcomplex64() complex64 {
+	return 0
+}
+
+//export exportcomplex128
+func exportcomplex128() complex128 {
+	return 0
+}
diff --git a/misc/cgo/test/sleep_windows.go b/misc/cgo/test/sleep_windows.go
new file mode 100644
index 0000000..007a1bb
--- /dev/null
+++ b/misc/cgo/test/sleep_windows.go
@@ -0,0 +1,16 @@
+// Copyright 2011 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
+
+/*
+#include <windows.h>
+
+unsigned int sleep(unsigned int seconds) {
+	Sleep(1000 * seconds);
+	return 0;
+}
+
+*/
+import "C"
diff --git a/misc/cgo/testso/Makefile b/misc/cgo/testso/Makefile
new file mode 100644
index 0000000..e472cf2
--- /dev/null
+++ b/misc/cgo/testso/Makefile
@@ -0,0 +1,22 @@
+# Copyright 2011 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../src/Make.inc
+
+TARG=cgosotest
+
+CGO_DEPS+=libcgoso.so
+CGO_LDFLAGS+=-lcgoso -L.
+CLEANFILES+=out libcgoso.so
+CGOFILES=\
+	cgoso.go\
+
+include ../../../src/Make.pkg
+
+libcgoso.so: cgoso_c.c
+	gcc cgoso_c.c -fPIC -o $@ $(_CGO_CFLAGS_$(GOARCH)) $(_CGO_LDFLAGS_$(GOOS))
+
+out: install main.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) main.go
+	$(LD) -o $@ main.$O
diff --git a/misc/cgo/testso/cgoso.go b/misc/cgo/testso/cgoso.go
new file mode 100644
index 0000000..6eb9f40
--- /dev/null
+++ b/misc/cgo/testso/cgoso.go
@@ -0,0 +1,16 @@
+// Copyright 2011 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 cgosotest
+
+//void sofunc(void);
+import "C"
+
+func Test() {
+	C.sofunc()
+}
+
+//export goCallback
+func goCallback() {
+}
diff --git a/misc/cgo/testso/cgoso_c.c b/misc/cgo/testso/cgoso_c.c
new file mode 100644
index 0000000..e29f7e8
--- /dev/null
+++ b/misc/cgo/testso/cgoso_c.c
@@ -0,0 +1,9 @@
+// Copyright 2011 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.
+
+void sofunc(void)
+{
+	extern void goCallback(void);
+	goCallback();
+}
diff --git a/misc/cgo/testso/main.go b/misc/cgo/testso/main.go
new file mode 100644
index 0000000..672ab26
--- /dev/null
+++ b/misc/cgo/testso/main.go
@@ -0,0 +1,11 @@
+// Copyright 2011 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 "cgosotest"
+
+func main() {
+	cgosotest.Test()
+}
diff --git a/misc/cgo/testso/test.bash b/misc/cgo/testso/test.bash
new file mode 100755
index 0000000..f275eb5
--- /dev/null
+++ b/misc/cgo/testso/test.bash
@@ -0,0 +1,9 @@
+#!/bin/sh
+# Copyright 2011 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
+gomake out
+LD_LIBRARY_PATH=. ./out
+gomake clean
diff --git a/misc/dashboard/app/app.yaml b/misc/dashboard/app/app.yaml
new file mode 100644
index 0000000..685ca6e
--- /dev/null
+++ b/misc/dashboard/app/app.yaml
@@ -0,0 +1,20 @@
+# Update with
+#	google_appengine/appcfg.py [-V test-build] update .
+#
+# Using -V test-build will run as test-build.golang.org.
+
+application: golang-org
+version: build
+runtime: go
+api_version: 3
+
+handlers:
+- url: /static
+  static_dir: static
+- url: /log/.+
+  script: _go_app
+- url: /(|commit|packages|result|tag|todo)
+  script: _go_app
+- url: /(init|buildtest|key|_ah/queue/go/delay)
+  script: _go_app
+  login: admin
diff --git a/misc/dashboard/app/build/build.go b/misc/dashboard/app/build/build.go
new file mode 100644
index 0000000..175812a
--- /dev/null
+++ b/misc/dashboard/app/build/build.go
@@ -0,0 +1,294 @@
+// Copyright 2011 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 build
+
+import (
+	"bytes"
+	"compress/gzip"
+	"crypto/sha1"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"strings"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+const maxDatastoreStringLen = 500
+
+// A Package describes a package that is listed on the dashboard.
+type Package struct {
+	Name    string
+	Path    string // (empty for the main Go tree)
+	NextNum int    // Num of the next head Commit
+}
+
+func (p *Package) String() string {
+	return fmt.Sprintf("%s: %q", p.Path, p.Name)
+}
+
+func (p *Package) Key(c appengine.Context) *datastore.Key {
+	key := p.Path
+	if key == "" {
+		key = "go"
+	}
+	return datastore.NewKey(c, "Package", key, 0, nil)
+}
+
+// LastCommit returns the most recent Commit for this Package.
+func (p *Package) LastCommit(c appengine.Context) (*Commit, os.Error) {
+	var commits []*Commit
+	_, err := datastore.NewQuery("Commit").
+		Ancestor(p.Key(c)).
+		Order("-Time").
+		Limit(1).
+		GetAll(c, &commits)
+	if err != nil {
+		return nil, err
+	}
+	if len(commits) != 1 {
+		return nil, datastore.ErrNoSuchEntity
+	}
+	return commits[0], nil
+}
+
+// GetPackage fetches a Package by path from the datastore.
+func GetPackage(c appengine.Context, path string) (*Package, os.Error) {
+	p := &Package{Path: path}
+	err := datastore.Get(c, p.Key(c), p)
+	if err == datastore.ErrNoSuchEntity {
+		return nil, fmt.Errorf("package %q not found", path)
+	}
+	return p, err
+}
+
+// A Commit describes an individual commit in a package.
+//
+// Each Commit entity is a descendant of its associated Package entity.
+// In other words, all Commits with the same PackagePath belong to the same
+// datastore entity group.
+type Commit struct {
+	PackagePath string // (empty for Go commits)
+	Hash        string
+	ParentHash  string
+	Num         int // Internal monotonic counter unique to this package.
+
+	User string
+	Desc string `datastore:",noindex"`
+	Time datastore.Time
+
+	// ResultData is the Data string of each build Result for this Commit.
+	// For non-Go commits, only the Results for the current Go tip, weekly,
+	// and release Tags are stored here. This is purely de-normalized data.
+	// The complete data set is stored in Result entities.
+	ResultData []string `datastore:",noindex"`
+
+	FailNotificationSent bool
+}
+
+func (com *Commit) Key(c appengine.Context) *datastore.Key {
+	if com.Hash == "" {
+		panic("tried Key on Commit with empty Hash")
+	}
+	p := Package{Path: com.PackagePath}
+	key := com.PackagePath + "|" + com.Hash
+	return datastore.NewKey(c, "Commit", key, 0, p.Key(c))
+}
+
+func (c *Commit) Valid() os.Error {
+	if !validHash(c.Hash) {
+		return os.NewError("invalid Hash")
+	}
+	if c.ParentHash != "" && !validHash(c.ParentHash) { // empty is OK
+		return os.NewError("invalid ParentHash")
+	}
+	return nil
+}
+
+// AddResult adds the denormalized Reuslt data to the Commit's Result field.
+// It must be called from inside a datastore transaction.
+func (com *Commit) AddResult(c appengine.Context, r *Result) os.Error {
+	if err := datastore.Get(c, com.Key(c), com); err != nil {
+		return fmt.Errorf("getting Commit: %v", err)
+	}
+	com.ResultData = append(com.ResultData, r.Data())
+	if _, err := datastore.Put(c, com.Key(c), com); err != nil {
+		return fmt.Errorf("putting Commit: %v", err)
+	}
+	return nil
+}
+
+// Result returns the build Result for this Commit for the given builder/goHash.
+func (c *Commit) Result(builder, goHash string) *Result {
+	for _, r := range c.ResultData {
+		p := strings.SplitN(r, "|", 4)
+		if len(p) != 4 || p[0] != builder || p[3] != goHash {
+			continue
+		}
+		return partsToHash(c, p)
+	}
+	return nil
+}
+
+// Results returns the build Results for this Commit for the given goHash.
+func (c *Commit) Results(goHash string) (results []*Result) {
+	for _, r := range c.ResultData {
+		p := strings.SplitN(r, "|", 4)
+		if len(p) != 4 || p[3] != goHash {
+			continue
+		}
+		results = append(results, partsToHash(c, p))
+	}
+	return
+}
+
+// partsToHash converts a Commit and ResultData substrings to a Result.
+func partsToHash(c *Commit, p []string) *Result {
+	return &Result{
+		Builder:     p[0],
+		Hash:        c.Hash,
+		PackagePath: c.PackagePath,
+		GoHash:      p[3],
+		OK:          p[1] == "true",
+		LogHash:     p[2],
+	}
+}
+
+// OK returns the Commit's build state for a specific builder and goHash.
+func (c *Commit) OK(builder, goHash string) (ok, present bool) {
+	r := c.Result(builder, goHash)
+	if r == nil {
+		return false, false
+	}
+	return r.OK, true
+}
+
+// A Result describes a build result for a Commit on an OS/architecture.
+//
+// Each Result entity is a descendant of its associated Commit entity.
+type Result struct {
+	Builder     string // "arch-os[-note]"
+	Hash        string
+	PackagePath string // (empty for Go commits)
+
+	// The Go Commit this was built against (empty for Go commits).
+	GoHash string
+
+	OK      bool
+	Log     string `datastore:"-"`        // for JSON unmarshaling only
+	LogHash string `datastore:",noindex"` // Key to the Log record.
+
+	RunTime int64 // time to build+test in nanoseconds 
+}
+
+func (r *Result) Key(c appengine.Context) *datastore.Key {
+	p := Package{Path: r.PackagePath}
+	key := r.Builder + "|" + r.PackagePath + "|" + r.Hash + "|" + r.GoHash
+	return datastore.NewKey(c, "Result", key, 0, p.Key(c))
+}
+
+func (r *Result) Valid() os.Error {
+	if !validHash(r.Hash) {
+		return os.NewError("invalid Hash")
+	}
+	if r.PackagePath != "" && !validHash(r.GoHash) {
+		return os.NewError("invalid GoHash")
+	}
+	return nil
+}
+
+// Data returns the Result in string format
+// to be stored in Commit's ResultData field.
+func (r *Result) Data() string {
+	return fmt.Sprintf("%v|%v|%v|%v", r.Builder, r.OK, r.LogHash, r.GoHash)
+}
+
+// A Log is a gzip-compressed log file stored under the SHA1 hash of the
+// uncompressed log text.
+type Log struct {
+	CompressedLog []byte
+}
+
+func (l *Log) Text() ([]byte, os.Error) {
+	d, err := gzip.NewReader(bytes.NewBuffer(l.CompressedLog))
+	if err != nil {
+		return nil, fmt.Errorf("reading log data: %v", err)
+	}
+	b, err := ioutil.ReadAll(d)
+	if err != nil {
+		return nil, fmt.Errorf("reading log data: %v", err)
+	}
+	return b, nil
+}
+
+func PutLog(c appengine.Context, text string) (hash string, err os.Error) {
+	h := sha1.New()
+	io.WriteString(h, text)
+	b := new(bytes.Buffer)
+	z, _ := gzip.NewWriterLevel(b, gzip.BestCompression)
+	io.WriteString(z, text)
+	z.Close()
+	hash = fmt.Sprintf("%x", h.Sum())
+	key := datastore.NewKey(c, "Log", hash, 0, nil)
+	_, err = datastore.Put(c, key, &Log{b.Bytes()})
+	return
+}
+
+// A Tag is used to keep track of the most recent Go weekly and release tags.
+// Typically there will be one Tag entity for each kind of hg tag.
+type Tag struct {
+	Kind string // "weekly", "release", or "tip"
+	Name string // the tag itself (for example: "release.r60")
+	Hash string
+}
+
+func (t *Tag) Key(c appengine.Context) *datastore.Key {
+	p := &Package{}
+	return datastore.NewKey(c, "Tag", t.Kind, 0, p.Key(c))
+}
+
+func (t *Tag) Valid() os.Error {
+	if t.Kind != "weekly" && t.Kind != "release" && t.Kind != "tip" {
+		return os.NewError("invalid Kind")
+	}
+	if !validHash(t.Hash) {
+		return os.NewError("invalid Hash")
+	}
+	return nil
+}
+
+// GetTag fetches a Tag by name from the datastore.
+func GetTag(c appengine.Context, tag string) (*Tag, os.Error) {
+	t := &Tag{Kind: tag}
+	if err := datastore.Get(c, t.Key(c), t); err != nil {
+		if err == datastore.ErrNoSuchEntity {
+			return nil, os.NewError("tag not found: " + tag)
+		}
+		return nil, err
+	}
+	if err := t.Valid(); err != nil {
+		return nil, err
+	}
+	return t, nil
+}
+
+// Packages returns all non-Go packages.
+func Packages(c appengine.Context) ([]*Package, os.Error) {
+	var pkgs []*Package
+	for t := datastore.NewQuery("Package").Run(c); ; {
+		pkg := new(Package)
+		if _, err := t.Next(pkg); err == datastore.Done {
+			break
+		} else if err != nil {
+			return nil, err
+		}
+		if pkg.Path != "" {
+			pkgs = append(pkgs, pkg)
+		}
+	}
+	return pkgs, nil
+}
diff --git a/misc/dashboard/app/build/handler.go b/misc/dashboard/app/build/handler.go
new file mode 100644
index 0000000..b3e62ad
--- /dev/null
+++ b/misc/dashboard/app/build/handler.go
@@ -0,0 +1,428 @@
+// Copyright 2011 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 build
+
+import (
+	"crypto/hmac"
+	"fmt"
+	"http"
+	"json"
+	"os"
+
+	"appengine"
+	"appengine/datastore"
+	"cache"
+)
+
+const commitsPerPage = 30
+
+// defaultPackages specifies the Package records to be created by initHandler.
+var defaultPackages = []*Package{
+	&Package{Name: "Go"},
+}
+
+// commitHandler retrieves commit data or records a new commit.
+//
+// For GET requests it returns a Commit value for the specified
+// packagePath and hash.
+//
+// For POST requests it reads a JSON-encoded Commit value from the request
+// body and creates a new Commit entity. It also updates the "tip" Tag for
+// each new commit at tip.
+//
+// This handler is used by a gobuilder process in -commit mode.
+func commitHandler(r *http.Request) (interface{}, os.Error) {
+	c := appengine.NewContext(r)
+	com := new(Commit)
+
+	if r.Method == "GET" {
+		com.PackagePath = r.FormValue("packagePath")
+		com.Hash = r.FormValue("hash")
+		if err := datastore.Get(c, com.Key(c), com); err != nil {
+			return nil, fmt.Errorf("getting Commit: %v", err)
+		}
+		return com, nil
+	}
+	if r.Method != "POST" {
+		return nil, errBadMethod(r.Method)
+	}
+
+	// POST request
+	defer r.Body.Close()
+	if err := json.NewDecoder(r.Body).Decode(com); err != nil {
+		return nil, fmt.Errorf("decoding Body: %v", err)
+	}
+	if len(com.Desc) > maxDatastoreStringLen {
+		com.Desc = com.Desc[:maxDatastoreStringLen]
+	}
+	if err := com.Valid(); err != nil {
+		return nil, fmt.Errorf("validating Commit: %v", err)
+	}
+	defer cache.Tick(c)
+	tx := func(c appengine.Context) os.Error {
+		return addCommit(c, com)
+	}
+	return nil, datastore.RunInTransaction(c, tx, nil)
+}
+
+// addCommit adds the Commit entity to the datastore and updates the tip Tag.
+// It must be run inside a datastore transaction.
+func addCommit(c appengine.Context, com *Commit) os.Error {
+	var tc Commit // temp value so we don't clobber com
+	err := datastore.Get(c, com.Key(c), &tc)
+	if err != datastore.ErrNoSuchEntity {
+		// if this commit is already in the datastore, do nothing
+		if err == nil {
+			return nil
+		}
+		return fmt.Errorf("getting Commit: %v", err)
+	}
+	// get the next commit number
+	p, err := GetPackage(c, com.PackagePath)
+	if err != nil {
+		return fmt.Errorf("GetPackage: %v", err)
+	}
+	com.Num = p.NextNum
+	p.NextNum++
+	if _, err := datastore.Put(c, p.Key(c), p); err != nil {
+		return fmt.Errorf("putting Package: %v", err)
+	}
+	// if this isn't the first Commit test the parent commit exists
+	if com.Num > 0 {
+		n, err := datastore.NewQuery("Commit").
+			Filter("Hash =", com.ParentHash).
+			Ancestor(p.Key(c)).
+			Count(c)
+		if err != nil {
+			return fmt.Errorf("testing for parent Commit: %v", err)
+		}
+		if n == 0 {
+			return os.NewError("parent commit not found")
+		}
+	}
+	// update the tip Tag if this is the Go repo
+	if p.Path == "" {
+		t := &Tag{Kind: "tip", Hash: com.Hash}
+		if _, err = datastore.Put(c, t.Key(c), t); err != nil {
+			return fmt.Errorf("putting Tag: %v", err)
+		}
+	}
+	// put the Commit
+	if _, err = datastore.Put(c, com.Key(c), com); err != nil {
+		return fmt.Errorf("putting Commit: %v", err)
+	}
+	return nil
+}
+
+// tagHandler records a new tag. It reads a JSON-encoded Tag value from the
+// request body and updates the Tag entity for the Kind of tag provided.
+//
+// This handler is used by a gobuilder process in -commit mode.
+func tagHandler(r *http.Request) (interface{}, os.Error) {
+	if r.Method != "POST" {
+		return nil, errBadMethod(r.Method)
+	}
+
+	t := new(Tag)
+	defer r.Body.Close()
+	if err := json.NewDecoder(r.Body).Decode(t); err != nil {
+		return nil, err
+	}
+	if err := t.Valid(); err != nil {
+		return nil, err
+	}
+	c := appengine.NewContext(r)
+	defer cache.Tick(c)
+	_, err := datastore.Put(c, t.Key(c), t)
+	return nil, err
+}
+
+// Todo is a todoHandler response.
+type Todo struct {
+	Kind string // "build-go-commit" or "build-package"
+	Data interface{}
+}
+
+// todoHandler returns the next action to be performed by a builder.
+// It expects "builder" and "kind" query parameters and returns a *Todo value.
+// Multiple "kind" parameters may be specified.
+func todoHandler(r *http.Request) (interface{}, os.Error) {
+	c := appengine.NewContext(r)
+	now := cache.Now(c)
+	key := "build-todo-" + r.Form.Encode()
+	var todo *Todo
+	if cache.Get(r, now, key, &todo) {
+		return todo, nil
+	}
+	var err os.Error
+	builder := r.FormValue("builder")
+	for _, kind := range r.Form["kind"] {
+		var data interface{}
+		switch kind {
+		case "build-go-commit":
+			data, err = buildTodo(c, builder, "", "")
+		case "build-package":
+			packagePath := r.FormValue("packagePath")
+			goHash := r.FormValue("goHash")
+			data, err = buildTodo(c, builder, packagePath, goHash)
+		}
+		if data != nil || err != nil {
+			todo = &Todo{Kind: kind, Data: data}
+			break
+		}
+	}
+	if err == nil {
+		cache.Set(r, now, key, todo)
+	}
+	return todo, err
+}
+
+// buildTodo returns the next Commit to be built (or nil if none available).
+//
+// If packagePath and goHash are empty, it scans the first 20 Go Commits in
+// Num-descending order and returns the first one it finds that doesn't have a
+// Result for this builder.
+//
+// If provided with non-empty packagePath and goHash args, it scans the first
+// 20 Commits in Num-descending order for the specified packagePath and
+// returns the first that doesn't have a Result for this builder and goHash.
+func buildTodo(c appengine.Context, builder, packagePath, goHash string) (interface{}, os.Error) {
+	p, err := GetPackage(c, packagePath)
+	if err != nil {
+		return nil, err
+	}
+
+	t := datastore.NewQuery("Commit").
+		Ancestor(p.Key(c)).
+		Limit(commitsPerPage).
+		Order("-Num").
+		Run(c)
+	for {
+		com := new(Commit)
+		if _, err := t.Next(com); err != nil {
+			if err == datastore.Done {
+				err = nil
+			}
+			return nil, err
+		}
+		if com.Result(builder, goHash) == nil {
+			return com, nil
+		}
+	}
+	panic("unreachable")
+}
+
+// packagesHandler returns a list of the non-Go Packages monitored
+// by the dashboard.
+func packagesHandler(r *http.Request) (interface{}, os.Error) {
+	c := appengine.NewContext(r)
+	now := cache.Now(c)
+	const key = "build-packages"
+	var p []*Package
+	if cache.Get(r, now, key, &p) {
+		return p, nil
+	}
+	p, err := Packages(c)
+	if err != nil {
+		return nil, err
+	}
+	cache.Set(r, now, key, p)
+	return p, nil
+}
+
+// resultHandler records a build result.
+// It reads a JSON-encoded Result value from the request body,
+// creates a new Result entity, and updates the relevant Commit entity.
+// If the Log field is not empty, resultHandler creates a new Log entity
+// and updates the LogHash field before putting the Commit entity.
+func resultHandler(r *http.Request) (interface{}, os.Error) {
+	if r.Method != "POST" {
+		return nil, errBadMethod(r.Method)
+	}
+
+	c := appengine.NewContext(r)
+	res := new(Result)
+	defer r.Body.Close()
+	if err := json.NewDecoder(r.Body).Decode(res); err != nil {
+		return nil, fmt.Errorf("decoding Body: %v", err)
+	}
+	if err := res.Valid(); err != nil {
+		return nil, fmt.Errorf("validating Result: %v", err)
+	}
+	defer cache.Tick(c)
+	// store the Log text if supplied
+	if len(res.Log) > 0 {
+		hash, err := PutLog(c, res.Log)
+		if err != nil {
+			return nil, fmt.Errorf("putting Log: %v", err)
+		}
+		res.LogHash = hash
+	}
+	tx := func(c appengine.Context) os.Error {
+		// check Package exists
+		if _, err := GetPackage(c, res.PackagePath); err != nil {
+			return fmt.Errorf("GetPackage: %v", err)
+		}
+		// put Result
+		if _, err := datastore.Put(c, res.Key(c), res); err != nil {
+			return fmt.Errorf("putting Result: %v", err)
+		}
+		// add Result to Commit
+		com := &Commit{PackagePath: res.PackagePath, Hash: res.Hash}
+		if err := com.AddResult(c, res); err != nil {
+			return fmt.Errorf("AddResult: %v", err)
+		}
+		// Send build failure notifications, if necessary.
+		// Note this must run after the call AddResult, which
+		// populates the Commit's ResultData field.
+		return notifyOnFailure(c, com, res.Builder)
+	}
+	return nil, datastore.RunInTransaction(c, tx, nil)
+}
+
+// logHandler displays log text for a given hash.
+// It handles paths like "/log/hash".
+func logHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-type", "text/plain")
+	c := appengine.NewContext(r)
+	hash := r.URL.Path[len("/log/"):]
+	key := datastore.NewKey(c, "Log", hash, 0, nil)
+	l := new(Log)
+	if err := datastore.Get(c, key, l); err != nil {
+		logErr(w, r, err)
+		return
+	}
+	b, err := l.Text()
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+	w.Write(b)
+}
+
+type dashHandler func(*http.Request) (interface{}, os.Error)
+
+type dashResponse struct {
+	Response interface{}
+	Error    string
+}
+
+// errBadMethod is returned by a dashHandler when
+// the request has an unsuitable method.
+type errBadMethod string
+
+func (e errBadMethod) String() string {
+	return "bad method: " + string(e)
+}
+
+// AuthHandler wraps a http.HandlerFunc with a handler that validates the
+// supplied key and builder query parameters.
+func AuthHandler(h dashHandler) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		c := appengine.NewContext(r)
+
+		// Put the URL Query values into r.Form to avoid parsing the
+		// request body when calling r.FormValue.
+		r.Form = r.URL.Query()
+
+		var err os.Error
+		var resp interface{}
+
+		// Validate key query parameter for POST requests only.
+		key := r.FormValue("key")
+		builder := r.FormValue("builder")
+		if r.Method == "POST" && !validKey(c, key, builder) {
+			err = os.NewError("invalid key: " + key)
+		}
+
+		// Call the original HandlerFunc and return the response.
+		if err == nil {
+			resp, err = h(r)
+		}
+
+		// Write JSON response.
+		dashResp := &dashResponse{Response: resp}
+		if err != nil {
+			c.Errorf("%v", err)
+			dashResp.Error = err.String()
+		}
+		w.Header().Set("Content-Type", "application/json")
+		if err = json.NewEncoder(w).Encode(dashResp); err != nil {
+			c.Criticalf("encoding response: %v", err)
+		}
+	}
+}
+
+func initHandler(w http.ResponseWriter, r *http.Request) {
+	// TODO(adg): devise a better way of bootstrapping new packages
+	c := appengine.NewContext(r)
+	defer cache.Tick(c)
+	for _, p := range defaultPackages {
+		if err := datastore.Get(c, p.Key(c), new(Package)); err == nil {
+			continue
+		} else if err != datastore.ErrNoSuchEntity {
+			logErr(w, r, err)
+			return
+		}
+		if _, err := datastore.Put(c, p.Key(c), p); err != nil {
+			logErr(w, r, err)
+			return
+		}
+	}
+	fmt.Fprint(w, "OK")
+}
+
+func keyHandler(w http.ResponseWriter, r *http.Request) {
+	builder := r.FormValue("builder")
+	if builder == "" {
+		logErr(w, r, os.NewError("must supply builder in query string"))
+		return
+	}
+	c := appengine.NewContext(r)
+	fmt.Fprint(w, builderKey(c, builder))
+}
+
+func init() {
+	// admin handlers
+	http.HandleFunc("/init", initHandler)
+	http.HandleFunc("/key", keyHandler)
+
+	// authenticated handlers
+	http.HandleFunc("/commit", AuthHandler(commitHandler))
+	http.HandleFunc("/packages", AuthHandler(packagesHandler))
+	http.HandleFunc("/result", AuthHandler(resultHandler))
+	http.HandleFunc("/tag", AuthHandler(tagHandler))
+	http.HandleFunc("/todo", AuthHandler(todoHandler))
+
+	// public handlers
+	http.HandleFunc("/log/", logHandler)
+}
+
+func validHash(hash string) bool {
+	// TODO(adg): correctly validate a hash
+	return hash != ""
+}
+
+func validKey(c appengine.Context, key, builder string) bool {
+	if appengine.IsDevAppServer() {
+		return true
+	}
+	if key == secretKey(c) {
+		return true
+	}
+	return key == builderKey(c, builder)
+}
+
+func builderKey(c appengine.Context, builder string) string {
+	h := hmac.NewMD5([]byte(secretKey(c)))
+	h.Write([]byte(builder))
+	return fmt.Sprintf("%x", h.Sum())
+}
+
+func logErr(w http.ResponseWriter, r *http.Request, err os.Error) {
+	appengine.NewContext(r).Errorf("Error: %v", err)
+	w.WriteHeader(http.StatusInternalServerError)
+	fmt.Fprint(w, "Error: ", err)
+}
diff --git a/misc/dashboard/app/build/key.go b/misc/dashboard/app/build/key.go
new file mode 100644
index 0000000..5306c3b
--- /dev/null
+++ b/misc/dashboard/app/build/key.go
@@ -0,0 +1,62 @@
+// Copyright 2011 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 build
+
+import (
+	"sync"
+
+	"appengine"
+	"appengine/datastore"
+)
+
+var theKey struct {
+	sync.RWMutex
+	BuilderKey
+}
+
+type BuilderKey struct {
+	Secret string
+}
+
+func (k *BuilderKey) Key(c appengine.Context) *datastore.Key {
+	return datastore.NewKey(c, "BuilderKey", "root", 0, nil)
+}
+
+func secretKey(c appengine.Context) string {
+	// check with rlock
+	theKey.RLock()
+	k := theKey.Secret
+	theKey.RUnlock()
+	if k != "" {
+		return k
+	}
+
+	// prepare to fill; check with lock and keep lock
+	theKey.Lock()
+	defer theKey.Unlock()
+	if theKey.Secret != "" {
+		return theKey.Secret
+	}
+
+	// fill
+	if err := datastore.Get(c, theKey.Key(c), &theKey.BuilderKey); err != nil {
+		if err == datastore.ErrNoSuchEntity {
+			// If the key is not stored in datastore, write it.
+			// This only happens at the beginning of a new deployment.
+			// The code is left here for SDK use and in case a fresh
+			// deployment is ever needed.  "gophers rule" is not the
+			// real key.
+			if !appengine.IsDevAppServer() {
+				panic("lost key from datastore")
+			}
+			theKey.Secret = "gophers rule"
+			datastore.Put(c, theKey.Key(c), &theKey.BuilderKey)
+			return theKey.Secret
+		}
+		panic("cannot load builder key: " + err.String())
+	}
+
+	return theKey.Secret
+}
diff --git a/misc/dashboard/app/build/notify.go b/misc/dashboard/app/build/notify.go
new file mode 100644
index 0000000..826132b
--- /dev/null
+++ b/misc/dashboard/app/build/notify.go
@@ -0,0 +1,150 @@
+// Copyright 2011 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 build
+
+import (
+	"appengine"
+	"appengine/datastore"
+	"appengine/delay"
+	"appengine/mail"
+	"bytes"
+	"fmt"
+	"gob"
+	"os"
+	"template"
+)
+
+const (
+	mailFrom   = "builder at golang.org" // use this for sending any mail
+	failMailTo = "golang-dev at googlegroups.com"
+	domain     = "build.golang.org"
+)
+
+// notifyOnFailure checks whether the supplied Commit or the subsequent
+// Commit (if present) breaks the build for this builder.
+// If either of those commits break the build an email notification is sent
+// from a delayed task. (We use a task because this way the mail won't be
+// sent if the enclosing datastore transaction fails.)
+//
+// This must be run in a datastore transaction, and the provided *Commit must
+// have been retrieved from the datastore within that transaction.
+func notifyOnFailure(c appengine.Context, com *Commit, builder string) os.Error {
+	// TODO(adg): implement notifications for packages
+	if com.PackagePath != "" {
+		return nil
+	}
+
+	p := &Package{Path: com.PackagePath}
+	var broken *Commit
+	ok, present := com.OK(builder, "")
+	if !present {
+		return fmt.Errorf("no result for %s/%s", com.Hash, builder)
+	}
+	q := datastore.NewQuery("Commit").Ancestor(p.Key(c))
+	if ok {
+		// This commit is OK. Notify if next Commit is broken.
+		next := new(Commit)
+		q.Filter("ParentHash=", com.Hash)
+		if err := firstMatch(c, q, next); err != nil {
+			if err == datastore.ErrNoSuchEntity {
+				// OK at tip, no notification necessary.
+				return nil
+			}
+			return err
+		}
+		if ok, present := next.OK(builder, ""); present && !ok {
+			broken = next
+		}
+	} else {
+		// This commit is broken. Notify if the previous Commit is OK.
+		prev := new(Commit)
+		q.Filter("Hash=", com.ParentHash)
+		if err := firstMatch(c, q, prev); err != nil {
+			if err == datastore.ErrNoSuchEntity {
+				// No previous result, let the backfill of
+				// this result trigger the notification.
+				return nil
+			}
+			return err
+		}
+		if ok, present := prev.OK(builder, ""); present && ok {
+			broken = com
+		}
+	}
+	var err os.Error
+	if broken != nil && !broken.FailNotificationSent {
+		c.Infof("%s is broken commit; notifying", broken.Hash)
+		sendFailMailLater.Call(c, broken, builder) // add task to queue
+		broken.FailNotificationSent = true
+		_, err = datastore.Put(c, broken.Key(c), broken)
+	}
+	return err
+}
+
+// firstMatch executes the query q and loads the first entity into v.
+func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) os.Error {
+	t := q.Limit(1).Run(c)
+	_, err := t.Next(v)
+	if err == datastore.Done {
+		err = datastore.ErrNoSuchEntity
+	}
+	return err
+}
+
+var (
+	sendFailMailLater = delay.Func("sendFailMail", sendFailMail)
+	sendFailMailTmpl  = template.Must(
+		template.New("notify").Funcs(tmplFuncs).ParseFile("build/notify.txt"),
+	)
+)
+
+func init() {
+	gob.Register(&Commit{}) // for delay
+}
+
+// sendFailMail sends a mail notification that the build failed on the
+// provided commit and builder.
+func sendFailMail(c appengine.Context, com *Commit, builder string) {
+	// TODO(adg): handle packages
+
+	// get Result
+	r := com.Result(builder, "")
+	if r == nil {
+		c.Errorf("finding result for %q: %+v", builder, com)
+		return
+	}
+
+	// get Log
+	k := datastore.NewKey(c, "Log", r.LogHash, 0, nil)
+	l := new(Log)
+	if err := datastore.Get(c, k, l); err != nil {
+		c.Errorf("finding Log record %v: %v", r.LogHash, err)
+		return
+	}
+
+	// prepare mail message
+	var body bytes.Buffer
+	err := sendFailMailTmpl.Execute(&body, map[string]interface{}{
+		"Builder": builder, "Commit": com, "Result": r, "Log": l,
+		"Hostname": domain,
+	})
+	if err != nil {
+		c.Errorf("rendering mail template: %v", err)
+		return
+	}
+	subject := fmt.Sprintf("%s broken by %s", builder, shortDesc(com.Desc))
+	msg := &mail.Message{
+		Sender:  mailFrom,
+		To:      []string{failMailTo},
+		ReplyTo: failMailTo,
+		Subject: subject,
+		Body:    body.String(),
+	}
+
+	// send mail
+	if err := mail.Send(c, msg); err != nil {
+		c.Errorf("sending mail: %v", err)
+	}
+}
diff --git a/misc/dashboard/app/build/notify.txt b/misc/dashboard/app/build/notify.txt
new file mode 100644
index 0000000..6c90067
--- /dev/null
+++ b/misc/dashboard/app/build/notify.txt
@@ -0,0 +1,9 @@
+Change {{shortHash .Commit.Hash}} broke the {{.Builder}} build:
+http://{{.Hostname}}/log/{{.Result.LogHash}}
+
+{{.Commit.Desc}}
+
+http://code.google.com/p/go/source/detail?r={{shortHash .Commit.Hash}}
+
+$ tail -200 < log
+{{printf "%s" .Log.Text | tail 200}}
diff --git a/misc/dashboard/app/build/test.go b/misc/dashboard/app/build/test.go
new file mode 100644
index 0000000..a923969
--- /dev/null
+++ b/misc/dashboard/app/build/test.go
@@ -0,0 +1,251 @@
+// Copyright 2011 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 build
+
+// TODO(adg): test authentication
+
+import (
+	"appengine"
+	"appengine/datastore"
+	"bytes"
+	"fmt"
+	"http"
+	"http/httptest"
+	"io"
+	"json"
+	"os"
+	"strings"
+	"time"
+	"url"
+)
+
+func init() {
+	http.HandleFunc("/buildtest", testHandler)
+}
+
+var testEntityKinds = []string{
+	"Package",
+	"Commit",
+	"Result",
+	"Log",
+}
+
+const testPkg = "code.google.com/p/go.test"
+
+var testPackage = &Package{Name: "Test", Path: testPkg}
+
+var testPackages = []*Package{
+	&Package{Name: "Go", Path: ""},
+	testPackage,
+}
+
+var tCommitTime = time.Seconds() - 60*60*24*7
+
+func tCommit(hash, parentHash string) *Commit {
+	tCommitTime += 60 * 60 * 12 // each commit should have a different time
+	return &Commit{
+		Hash:       hash,
+		ParentHash: parentHash,
+		Time:       datastore.Time(tCommitTime * 1e6),
+		User:       "adg",
+		Desc:       "change description",
+	}
+}
+
+var testRequests = []struct {
+	path string
+	vals url.Values
+	req  interface{}
+	res  interface{}
+}{
+	// Packages
+	{"/packages", nil, nil, []*Package{testPackage}},
+
+	// Go repo
+	{"/commit", nil, tCommit("0001", "0000"), nil},
+	{"/commit", nil, tCommit("0002", "0001"), nil},
+	{"/commit", nil, tCommit("0003", "0002"), nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0002", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+
+	// multiple builders
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/result", nil, &Result{Builder: "linux-amd64", Hash: "0003", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0002"}}},
+
+	// branches
+	{"/commit", nil, tCommit("0004", "0003"), nil},
+	{"/commit", nil, tCommit("0005", "0002"), nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0005"}}},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0005", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0004"}}},
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0004", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+
+	// logs
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0003", OK: false, Log: "test"}, nil},
+	{"/log/a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", nil, nil, "test"},
+	{"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, nil},
+
+	// repeat failure (shouldn't re-send mail)
+	{"/result", nil, &Result{Builder: "linux-386", Hash: "0003", OK: false, Log: "test"}, nil},
+
+	// non-Go repos
+	{"/commit", nil, &Commit{PackagePath: testPkg, Hash: "1001", ParentHash: "1000"}, nil},
+	{"/commit", nil, &Commit{PackagePath: testPkg, Hash: "1002", ParentHash: "1001"}, nil},
+	{"/commit", nil, &Commit{PackagePath: testPkg, Hash: "1003", ParentHash: "1002"}, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1003"}}},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1003", GoHash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1002"}}},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1002", GoHash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1001"}}},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1001", GoHash: "0001", OK: true}, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, nil},
+	{"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0002"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1003"}}},
+	{"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1001", GoHash: "0005", OK: false, Log: "boo"}, nil},
+}
+
+func testHandler(w http.ResponseWriter, r *http.Request) {
+	if !appengine.IsDevAppServer() {
+		fmt.Fprint(w, "These tests must be run under the dev_appserver.")
+		return
+	}
+	c := appengine.NewContext(r)
+	if err := nukeEntities(c, testEntityKinds); err != nil {
+		logErr(w, r, err)
+		return
+	}
+	if r.FormValue("nukeonly") != "" {
+		fmt.Fprint(w, "OK")
+		return
+	}
+
+	for _, p := range testPackages {
+		if _, err := datastore.Put(c, p.Key(c), p); err != nil {
+			logErr(w, r, err)
+			return
+		}
+	}
+
+	for i, t := range testRequests {
+		c.Infof("running test %d %s", i, t.path)
+		errorf := func(format string, args ...interface{}) {
+			fmt.Fprintf(w, "%d %s: ", i, t.path)
+			fmt.Fprintf(w, format, args...)
+			fmt.Fprintln(w)
+		}
+		var body io.ReadWriter
+		if t.req != nil {
+			body = new(bytes.Buffer)
+			json.NewEncoder(body).Encode(t.req)
+		}
+		url := "http://" + domain + t.path
+		if t.vals != nil {
+			url += "?" + t.vals.Encode()
+		}
+		req, err := http.NewRequest("POST", url, body)
+		if err != nil {
+			logErr(w, r, err)
+			return
+		}
+		if t.req != nil {
+			req.Method = "POST"
+		}
+		req.Header = r.Header
+		rec := httptest.NewRecorder()
+
+		// Make the request
+		http.DefaultServeMux.ServeHTTP(rec, req)
+
+		if rec.Code != 0 && rec.Code != 200 {
+			errorf(rec.Body.String())
+			return
+		}
+		resp := new(dashResponse)
+
+		// If we're expecting a *Todo value,
+		// prime the Response field with a Todo and a Commit inside it.
+		if _, ok := t.res.(*Todo); ok {
+			resp.Response = &Todo{Data: &Commit{}}
+		}
+
+		if strings.HasPrefix(t.path, "/log/") {
+			resp.Response = rec.Body.String()
+		} else {
+			err := json.NewDecoder(rec.Body).Decode(resp)
+			if err != nil {
+				errorf("decoding response: %v", err)
+				return
+			}
+		}
+		if e, ok := t.res.(string); ok {
+			g, ok := resp.Response.(string)
+			if !ok {
+				errorf("Response not string: %T", resp.Response)
+				return
+			}
+			if g != e {
+				errorf("response mismatch: got %q want %q", g, e)
+				return
+			}
+		}
+		if e, ok := t.res.(*Todo); ok {
+			g, ok := resp.Response.(*Todo)
+			if !ok {
+				errorf("Response not *Todo: %T", resp.Response)
+				return
+			}
+			if e.Data == nil && g.Data != nil {
+				errorf("Response.Data should be nil, got: %v", g.Data)
+				return
+			}
+			if g.Data == nil {
+				errorf("Response.Data is nil, want: %v", e.Data)
+				return
+			}
+			gd, ok := g.Data.(*Commit)
+			if !ok {
+				errorf("Response.Data not *Commit: %T", g.Data)
+				return
+			}
+			if e.Data.(*Commit).Hash != gd.Hash {
+				errorf("hashes don't match: got %q, want %q", g, e)
+				return
+			}
+		}
+		if t.res == nil && resp.Response != nil {
+			errorf("response mismatch: got %q expected <nil>",
+				resp.Response)
+			return
+		}
+	}
+	fmt.Fprint(w, "PASS")
+}
+
+func nukeEntities(c appengine.Context, kinds []string) os.Error {
+	if !appengine.IsDevAppServer() {
+		return os.NewError("can't nuke production data")
+	}
+	var keys []*datastore.Key
+	for _, kind := range kinds {
+		q := datastore.NewQuery(kind).KeysOnly()
+		for t := q.Run(c); ; {
+			k, err := t.Next(nil)
+			if err == datastore.Done {
+				break
+			}
+			if err != nil {
+				return err
+			}
+			keys = append(keys, k)
+		}
+	}
+	return datastore.DeleteMulti(c, keys)
+}
diff --git a/misc/dashboard/app/build/ui.go b/misc/dashboard/app/build/ui.go
new file mode 100644
index 0000000..032fdbd
--- /dev/null
+++ b/misc/dashboard/app/build/ui.go
@@ -0,0 +1,313 @@
+// Copyright 2011 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.
+
+// TODO(adg): packages at weekly/release
+// TODO(adg): some means to register new packages
+
+package build
+
+import (
+	"bytes"
+	"exp/template/html"
+	"http"
+	"os"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"template"
+
+	"appengine"
+	"appengine/datastore"
+	"cache"
+)
+
+func init() {
+	http.HandleFunc("/", uiHandler)
+	html.Escape(uiTemplate)
+}
+
+// uiHandler draws the build status page.
+func uiHandler(w http.ResponseWriter, r *http.Request) {
+	c := appengine.NewContext(r)
+	now := cache.Now(c)
+	const key = "build-ui"
+
+	page, _ := strconv.Atoi(r.FormValue("page"))
+	if page < 0 {
+		page = 0
+	}
+
+	// Used cached version of front page, if available.
+	if page == 0 {
+		var b []byte
+		if cache.Get(r, now, key, &b) {
+			w.Write(b)
+			return
+		}
+	}
+
+	commits, err := goCommits(c, page)
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+	builders := commitBuilders(commits)
+
+	tipState, err := TagState(c, "tip")
+	if err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	p := &Pagination{}
+	if len(commits) == commitsPerPage {
+		p.Next = page + 1
+	}
+	if page > 0 {
+		p.Prev = page - 1
+		p.HasPrev = true
+	}
+	data := &uiTemplateData{commits, builders, tipState, p}
+
+	var buf bytes.Buffer
+	if err := uiTemplate.Execute(&buf, data); err != nil {
+		logErr(w, r, err)
+		return
+	}
+
+	// Cache the front page.
+	if page == 0 {
+		cache.Set(r, now, key, buf.Bytes())
+	}
+
+	buf.WriteTo(w)
+}
+
+type Pagination struct {
+	Next, Prev int
+	HasPrev    bool
+}
+
+// goCommits gets a slice of the latest Commits to the Go repository.
+// If page > 0 it paginates by commitsPerPage.
+func goCommits(c appengine.Context, page int) ([]*Commit, os.Error) {
+	q := datastore.NewQuery("Commit").
+		Ancestor((&Package{}).Key(c)).
+		Order("-Time").
+		Limit(commitsPerPage).
+		Offset(page * commitsPerPage)
+	var commits []*Commit
+	_, err := q.GetAll(c, &commits)
+	return commits, err
+}
+
+// commitBuilders returns the names of the builders that provided
+// Results for the provided commits.
+func commitBuilders(commits []*Commit) []string {
+	builders := make(map[string]bool)
+	for _, commit := range commits {
+		for _, r := range commit.Results("") {
+			builders[r.Builder] = true
+		}
+	}
+	return keys(builders)
+}
+
+func keys(m map[string]bool) (s []string) {
+	for k := range m {
+		s = append(s, k)
+	}
+	sort.Strings(s)
+	return
+}
+
+// PackageState represents the state of a Package at a tag.
+type PackageState struct {
+	*Package
+	*Commit
+	Results []*Result
+	OK      bool
+}
+
+// TagState fetches the results for all non-Go packages at the specified tag.
+func TagState(c appengine.Context, name string) ([]*PackageState, os.Error) {
+	tag, err := GetTag(c, name)
+	if err != nil {
+		return nil, err
+	}
+	pkgs, err := Packages(c)
+	if err != nil {
+		return nil, err
+	}
+	var states []*PackageState
+	for _, pkg := range pkgs {
+		commit, err := pkg.LastCommit(c)
+		if err != nil {
+			c.Errorf("no Commit found: %v", pkg)
+			continue
+		}
+		results := commit.Results(tag.Hash)
+		ok := len(results) > 0
+		for _, r := range results {
+			ok = ok && r.OK
+		}
+		states = append(states, &PackageState{
+			pkg, commit, results, ok,
+		})
+	}
+	return states, nil
+}
+
+type uiTemplateData struct {
+	Commits    []*Commit
+	Builders   []string
+	TipState   []*PackageState
+	Pagination *Pagination
+}
+
+var uiTemplate = template.Must(
+	template.New("ui").Funcs(tmplFuncs).ParseFile("build/ui.html"),
+)
+
+var tmplFuncs = template.FuncMap{
+	"builderOS":        builderOS,
+	"builderArch":      builderArch,
+	"builderArchShort": builderArchShort,
+	"builderArchChar":  builderArchChar,
+	"builderTitle":     builderTitle,
+	"builderSpans":     builderSpans,
+	"repoURL":          repoURL,
+	"shortDesc":        shortDesc,
+	"shortHash":        shortHash,
+	"shortUser":        shortUser,
+	"tail":             tail,
+}
+
+func splitDash(s string) (string, string) {
+	i := strings.Index(s, "-")
+	if i >= 0 {
+		return s[:i], s[i+1:]
+	}
+	return s, ""
+}
+
+// builderOS returns the os tag for a builder string
+func builderOS(s string) string {
+	os, _ := splitDash(s)
+	return os
+}
+
+// builderArch returns the arch tag for a builder string
+func builderArch(s string) string {
+	_, arch := splitDash(s)
+	arch, _ = splitDash(arch) // chop third part
+	return arch
+}
+
+// builderArchShort returns a short arch tag for a builder string
+func builderArchShort(s string) string {
+	arch := builderArch(s)
+	switch arch {
+	case "amd64":
+		return "x64"
+	}
+	return arch
+}
+
+// builderArchChar returns the architecture letter for a builder string
+func builderArchChar(s string) string {
+	arch := builderArch(s)
+	switch arch {
+	case "386":
+		return "8"
+	case "amd64":
+		return "6"
+	case "arm":
+		return "5"
+	}
+	return arch
+}
+
+type builderSpan struct {
+	N  int
+	OS string
+}
+
+// builderSpans creates a list of tags showing
+// the builder's operating system names, spanning
+// the appropriate number of columns.
+func builderSpans(s []string) []builderSpan {
+	var sp []builderSpan
+	for len(s) > 0 {
+		i := 1
+		os := builderOS(s[0])
+		for i < len(s) && builderOS(s[i]) == os {
+			i++
+		}
+		sp = append(sp, builderSpan{i, os})
+		s = s[i:]
+	}
+	return sp
+}
+
+// builderTitle formats "linux-amd64-foo" as "linux amd64 foo".
+func builderTitle(s string) string {
+	return strings.Replace(s, "-", " ", -1)
+}
+
+// shortDesc returns the first line of a description.
+func shortDesc(desc string) string {
+	if i := strings.Index(desc, "\n"); i != -1 {
+		desc = desc[:i]
+	}
+	return desc
+}
+
+// shortHash returns a short version of a hash.
+func shortHash(hash string) string {
+	if len(hash) > 12 {
+		hash = hash[:12]
+	}
+	return hash
+}
+
+// shortUser returns a shortened version of a user string.
+func shortUser(user string) string {
+	if i, j := strings.Index(user, "<"), strings.Index(user, ">"); 0 <= i && i < j {
+		user = user[i+1 : j]
+	}
+	if i := strings.Index(user, "@"); i >= 0 {
+		return user[:i]
+	}
+	return user
+}
+
+// repoRe matches Google Code repositories and subrepositories (without paths).
+var repoRe = regexp.MustCompile(`^code\.google\.com/p/([a-z0-9\-]+)(\.[a-z0-9\-]+)?$`)
+
+// repoURL returns the URL of a change at a Google Code repository or subrepo.
+func repoURL(hash, packagePath string) (string, os.Error) {
+	if packagePath == "" {
+		return "https://code.google.com/p/go/source/detail?r=" + hash, nil
+	}
+	m := repoRe.FindStringSubmatch(packagePath)
+	if m == nil {
+		return "", os.NewError("unrecognized package: " + packagePath)
+	}
+	url := "https://code.google.com/p/" + m[1] + "/source/detail?r=" + hash
+	if len(m) > 2 {
+		url += "&repo=" + m[2][1:]
+	}
+	return url, nil
+}
+
+// tail returns the trailing n lines of s.
+func tail(n int, s string) string {
+	lines := strings.Split(s, "\n")
+	if len(lines) < n {
+		return s
+	}
+	return strings.Join(lines[len(lines)-n:], "\n")
+}
diff --git a/misc/dashboard/app/build/ui.html b/misc/dashboard/app/build/ui.html
new file mode 100644
index 0000000..678c952
--- /dev/null
+++ b/misc/dashboard/app/build/ui.html
@@ -0,0 +1,178 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <title>Go Build Dashboard</title>
+    <style>
+      body {
+        font-family: sans-serif;
+        padding: 0; margin: 0;
+      }
+      h1, h2 {
+        margin: 0;
+        padding: 5px;
+      }
+      h1 {
+        background: #eee;
+      }
+      h2 {
+        margin-top: 10px;
+      }
+      .build, .packages {
+        margin: 5px;
+        border-collapse: collapse;
+      }
+      .build td, .build th, .packages td, .packages th {
+        vertical-align: top;
+        padding: 2px 4px;
+        font-size: 10pt;
+      }
+      .build tr.commit:nth-child(2n) {
+        background-color: #f0f0f0;
+      }
+      .build .hash {
+        font-family: monospace;
+	font-size: 9pt;
+      }
+      .build .result {
+        text-align: center;
+        width: 2em;
+      }
+      .col-hash, .col-result {
+        border-right: solid 1px #ccc;
+      }
+      .build .arch {
+        font-size: 66%;
+        font-weight: normal;
+      }
+      .build .time {
+        color: #666;
+      }
+      .build .ok {
+        font-size: 83%;
+      }
+      .build .desc, .build .time, .build .user {
+        white-space: nowrap;
+      }
+      .paginate {
+        padding: 0.5em;
+      }
+      .paginate a {
+        padding: 0.5em;
+        background: #eee;
+        color: blue;
+      }
+      .paginate a.inactive {
+        color: #999;
+      }
+      .fail {
+        color: #C00;
+      }
+    </style>
+  </head>
+  <body>
+
+    <h1>Go Build Status</h1>
+
+  {{if $.Commits}}
+
+    <table class="build">
+      <colgroup class="col-hash"></colgroup>
+    {{range $.Builders | builderSpans}}
+      <colgroup class="col-result" span="{{.N}}"></colgroup>
+    {{end}}
+      <colgroup class="col-user"></colgroup>
+      <colgroup class="col-time"></colgroup>
+      <colgroup class="col-desc"></colgroup>
+      <tr>
+        <!-- extra row to make alternating colors use dark for first result -->
+      </tr>
+      <tr>
+        <th> </th>
+    {{range $.Builders | builderSpans}}
+        <th colspan="{{.N}}">{{.OS}}</th>
+    {{end}}
+        <th></th>
+        <th></th>
+        <th></th>
+      </tr>
+      <tr>
+        <th> </th>
+    {{range $.Builders}}
+        <th class="result arch" title="{{.}}">{{builderArchShort .}}</th>
+    {{end}}
+      </tr>
+    {{range $c := $.Commits}}
+      <tr class="commit">
+      <td class="hash"><a href="{{repoURL .Hash ""}}">{{shortHash .Hash}}</a></td>
+      {{range $.Builders}}
+      <td class="result">
+      {{with $c.Result . ""}}
+        {{if .OK}}
+        <span class="ok">ok</span>
+        {{else}}
+        <a href="/log/{{.LogHash}}" class="fail">fail</a>
+        {{end}}
+      {{else}}
+         
+      {{end}}
+      </td>
+      {{end}}
+      <td class="user" title="{{.User}}">{{shortUser .User}}</td>
+      <td class="time">{{.Time.Time.Format "Mon 02 Jan 15:04"}}</td>
+      <td class="desc" title="{{.Desc}}">{{shortDesc .Desc}}</td>
+      </tr>
+    {{end}}
+    </table>
+
+    {{with $.Pagination}}
+    <div class="paginate">
+      <a {{if .HasPrev}}href="?page={{.Prev}}"{{else}}class="inactive"{{end}}>prev</a>
+      <a {{if .Next}}href="?page={{.Next}}"{{else}}class="inactive"{{end}}>next</a>
+      <a {{if .HasPrev}}href="?page=0}"{{else}}class="inactive"{{end}}>top</a>
+    </div>
+    {{end}}
+
+  {{else}}
+    <p>No commits to display. Hm.</p>
+  {{end}}
+
+  {{if $.TipState}}
+    <h2>Other packages</h2>
+
+    <table class="packages">
+    <tr>
+      <th>State</th>
+      <th>Package</th>
+      <th> </th>
+    </tr>
+  {{range $state := $.TipState}}
+    <tr>
+      <td>
+    {{if .Results}}
+        <img src="/static/status_{{if .OK}}good{{else}}alert{{end}}.gif" />
+    {{else}}
+         
+    {{end}}
+      </td>
+      <td><a title="{{.Package.Path}}">{{.Package.Name}}</a></td>
+      <td>
+    {{range .Results}}
+        <div>
+          {{$h := $state.Commit.Hash}}
+          <a href="{{repoURL $h $state.Commit.PackagePath}}">{{shortHash $h}}</a>
+          {{if .OK}}
+            ok
+          {{else}}
+            <a href="/log/{{.LogHash}}" class="fail">failed</a>
+          {{end}}
+          on {{.Builder}}/<a href="{{repoURL .GoHash ""}}">{{shortHash .GoHash}}</a>
+        </a></div>
+    {{end}}
+      </td>
+    </tr>
+  {{end}}
+    </table>
+  {{end}}
+
+  </body>
+</html>
diff --git a/misc/dashboard/app/cache/cache.go b/misc/dashboard/app/cache/cache.go
new file mode 100644
index 0000000..d290ed4
--- /dev/null
+++ b/misc/dashboard/app/cache/cache.go
@@ -0,0 +1,82 @@
+// Copyright 2011 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 cache
+
+import (
+	"fmt"
+	"http"
+	"time"
+
+	"appengine"
+	"appengine/memcache"
+)
+
+const (
+	nocache = "nocache"
+	timeKey = "cachetime"
+	expiry  = 600 // 10 minutes
+)
+
+func newTime() uint64 { return uint64(time.Seconds()) << 32 }
+
+// Now returns the current logical datastore time to use for cache lookups.
+func Now(c appengine.Context) uint64 {
+	t, err := memcache.Increment(c, timeKey, 0, newTime())
+	if err != nil {
+		c.Errorf("cache.Now: %v", err)
+		return 0
+	}
+	return t
+}
+
+// Tick sets the current logical datastore time to a never-before-used time
+// and returns that time. It should be called to invalidate the cache.
+func Tick(c appengine.Context) uint64 {
+	t, err := memcache.Increment(c, timeKey, 1, newTime())
+	if err != nil {
+		c.Errorf("cache.Tick: %v", err)
+		return 0
+	}
+	return t
+}
+
+// Get fetches data for name at time now from memcache and unmarshals it into
+// value. It reports whether it found the cache record and logs any errors to
+// the admin console.
+func Get(r *http.Request, now uint64, name string, value interface{}) bool {
+	if now == 0 || r.FormValue(nocache) != "" {
+		return false
+	}
+	c := appengine.NewContext(r)
+	key := fmt.Sprintf("%s.%d", name, now)
+	_, err := memcache.JSON.Get(c, key, value)
+	if err == nil {
+		c.Debugf("cache hit %q", key)
+		return true
+	}
+	c.Debugf("cache miss %q", key)
+	if err != memcache.ErrCacheMiss {
+		c.Errorf("get cache %q: %v", key, err)
+	}
+	return false
+}
+
+// Set puts value into memcache under name at time now.
+// It logs any errors to the admin console.
+func Set(r *http.Request, now uint64, name string, value interface{}) {
+	if now == 0 || r.FormValue(nocache) != "" {
+		return
+	}
+	c := appengine.NewContext(r)
+	key := fmt.Sprintf("%s.%d", name, now)
+	err := memcache.JSON.Set(c, &memcache.Item{
+		Key:        key,
+		Object:     value,
+		Expiration: expiry,
+	})
+	if err != nil {
+		c.Errorf("set cache %q: %v", key, err)
+	}
+}
diff --git a/misc/dashboard/app/static/status_alert.gif b/misc/dashboard/app/static/status_alert.gif
new file mode 100644
index 0000000..495d9d2
Binary files /dev/null and b/misc/dashboard/app/static/status_alert.gif differ
diff --git a/misc/dashboard/app/static/status_good.gif b/misc/dashboard/app/static/status_good.gif
new file mode 100644
index 0000000..ef9c5a8
Binary files /dev/null and b/misc/dashboard/app/static/status_good.gif differ
diff --git a/misc/dashboard/builder/exec.go b/misc/dashboard/builder/exec.go
index a042c56..7f21aba 100644
--- a/misc/dashboard/builder/exec.go
+++ b/misc/dashboard/builder/exec.go
@@ -6,15 +6,15 @@ package main
 
 import (
 	"bytes"
-	"exec"
 	"io"
 	"log"
 	"os"
+	"os/exec"
 	"strings"
 )
 
 // run is a simple wrapper for exec.Run/Close
-func run(envv []string, dir string, argv ...string) os.Error {
+func run(envv []string, dir string, argv ...string) error {
 	if *verbose {
 		log.Println("run", argv)
 	}
@@ -31,7 +31,7 @@ func run(envv []string, dir string, argv ...string) os.Error {
 // process combined stdout and stderr output, exit status and error.
 // The error returned is nil, if process is started successfully,
 // even if exit status is not 0.
-func runLog(envv []string, logfile, dir string, argv ...string) (string, int, os.Error) {
+func runLog(envv []string, logfile, dir string, argv ...string) (string, int, error) {
 	if *verbose {
 		log.Println("runLog", argv)
 	}
@@ -56,11 +56,11 @@ func runLog(envv []string, logfile, dir string, argv ...string) (string, int, os
 
 	err := cmd.Run()
 	if err != nil {
-		if ws, ok := err.(*os.Waitmsg); ok {
+		if ws, ok := err.(*exec.ExitError); ok {
 			return b.String(), ws.ExitStatus(), nil
 		}
 	}
-	return b.String(), 0, nil
+	return b.String(), 0, err
 }
 
 // useBash prefixes a list of args with 'bash' if the first argument
diff --git a/misc/dashboard/builder/http.go b/misc/dashboard/builder/http.go
index abef8fa..b25b417 100644
--- a/misc/dashboard/builder/http.go
+++ b/misc/dashboard/builder/http.go
@@ -6,98 +6,129 @@ package main
 
 import (
 	"bytes"
+	"encoding/json"
+	"errors"
 	"fmt"
-	"http"
-	"json"
+	"io"
 	"log"
-	"os"
-	"strconv"
-	"url"
+	"net/http"
+	"net/url"
+	"time"
 )
 
-type param map[string]string
+type obj map[string]interface{}
 
 // dash runs the given method and command on the dashboard.
-// If args is not nil, it is the query or post parameters.
-// If resp is not nil, dash unmarshals the body as JSON into resp.
-func dash(meth, cmd string, resp interface{}, args param) os.Error {
+// If args is non-nil it is encoded as the URL query string.
+// If req is non-nil it is JSON-encoded and passed as the body of the HTTP POST.
+// If resp is non-nil the server's response is decoded into the value pointed
+// to by resp (resp must be a pointer).
+func dash(meth, cmd string, args url.Values, req, resp interface{}) error {
 	var r *http.Response
-	var err os.Error
+	var err error
 	if *verbose {
-		log.Println("dash", cmd, args)
+		log.Println("dash", meth, cmd, args, req)
 	}
 	cmd = "http://" + *dashboard + "/" + cmd
-	vals := make(url.Values)
-	for k, v := range args {
-		vals.Add(k, v)
+	if len(args) > 0 {
+		cmd += "?" + args.Encode()
 	}
 	switch meth {
 	case "GET":
-		if q := vals.Encode(); q != "" {
-			cmd += "?" + q
+		if req != nil {
+			log.Panicf("%s to %s with req", meth, cmd)
 		}
 		r, err = http.Get(cmd)
 	case "POST":
-		r, err = http.PostForm(cmd, vals)
+		var body io.Reader
+		if req != nil {
+			b, err := json.Marshal(req)
+			if err != nil {
+				return err
+			}
+			body = bytes.NewBuffer(b)
+		}
+		r, err = http.Post(cmd, "text/json", body)
 	default:
-		return fmt.Errorf("unknown method %q", meth)
+		log.Panicf("%s: invalid method %q", cmd, meth)
+		panic("invalid method: " + meth)
 	}
 	if err != nil {
 		return err
 	}
+
 	defer r.Body.Close()
-	var buf bytes.Buffer
-	buf.ReadFrom(r.Body)
-	if resp != nil {
-		if err = json.Unmarshal(buf.Bytes(), resp); err != nil {
-			log.Printf("json unmarshal %#q: %s\n", buf.Bytes(), err)
-			return err
-		}
+	body := new(bytes.Buffer)
+	if _, err := body.ReadFrom(r.Body); err != nil {
+		return err
 	}
-	return nil
-}
 
-func dashStatus(meth, cmd string, args param) os.Error {
-	var resp struct {
-		Status string
-		Error  string
+	// Read JSON-encoded Response into provided resp
+	// and return an error if present.
+	var result = struct {
+		Response interface{}
+		Error    string
+	}{
+		// Put the provided resp in here as it can be a pointer to
+		// some value we should unmarshal into.
+		Response: resp,
 	}
-	err := dash(meth, cmd, &resp, args)
-	if err != nil {
+	if err = json.Unmarshal(body.Bytes(), &result); err != nil {
+		log.Printf("json unmarshal %#q: %s\n", body.Bytes(), err)
 		return err
 	}
-	if resp.Status != "OK" {
-		return os.NewError("/build: " + resp.Error)
+	if result.Error != "" {
+		return errors.New(result.Error)
 	}
+
 	return nil
 }
 
 // todo returns the next hash to build.
-func (b *Builder) todo() (rev string, err os.Error) {
-	var resp []struct {
-		Hash string
+func (b *Builder) todo(kind, pkg, goHash string) (rev string, err error) {
+	args := url.Values{
+		"kind":        {kind},
+		"builder":     {b.name},
+		"packagePath": {pkg},
+		"goHash":      {goHash},
 	}
-	if err = dash("GET", "todo", &resp, param{"builder": b.name}); err != nil {
-		return
+	var resp *struct {
+		Kind string
+		Data struct {
+			Hash string
+		}
 	}
-	if len(resp) > 0 {
-		rev = resp[0].Hash
+	if err = dash("GET", "todo", args, nil, &resp); err != nil {
+		return "", err
 	}
-	return
+	if resp == nil {
+		return "", nil
+	}
+	if kind != resp.Kind {
+		return "", fmt.Errorf("expecting Kind %q, got %q", kind, resp.Kind)
+	}
+	return resp.Data.Hash, nil
 }
 
 // recordResult sends build results to the dashboard
-func (b *Builder) recordResult(buildLog string, hash string) os.Error {
-	return dash("POST", "build", nil, param{
-		"builder": b.name,
-		"key":     b.key,
-		"node":    hash,
-		"log":     buildLog,
-	})
+func (b *Builder) recordResult(ok bool, pkg, hash, goHash, buildLog string, runTime time.Duration) error {
+	req := obj{
+		"Builder":     b.name,
+		"PackagePath": pkg,
+		"Hash":        hash,
+		"GoHash":      goHash,
+		"OK":          ok,
+		"Log":         buildLog,
+		"RunTime":     runTime,
+	}
+	args := url.Values{"key": {b.key}, "builder": {b.name}}
+	return dash("POST", "result", args, req, nil)
 }
 
 // packages fetches a list of package paths from the dashboard
-func packages() (pkgs []string, err os.Error) {
+func packages() (pkgs []string, err error) {
+	return nil, nil
+	/* TODO(adg): un-stub this once the new package builder design is done
 	var resp struct {
 		Packages []struct {
 			Path string
@@ -111,38 +142,58 @@ func packages() (pkgs []string, err os.Error) {
 		pkgs = append(pkgs, p.Path)
 	}
 	return
+	*/
 }
 
-// updatePackage sends package build results and info dashboard
-func (b *Builder) updatePackage(pkg string, ok bool, buildLog, info string) os.Error {
+// updatePackage sends package build results and info to the dashboard
+func (b *Builder) updatePackage(pkg string, ok bool, buildLog, info string) error {
+	return nil
+	/* TODO(adg): un-stub this once the new package builder design is done
 	return dash("POST", "package", nil, param{
 		"builder": b.name,
 		"key":     b.key,
 		"path":    pkg,
-		"ok":      strconv.Btoa(ok),
+		"ok":      strconv.FormatBool(ok),
 		"log":     buildLog,
 		"info":    info,
 	})
+	*/
 }
 
-// postCommit informs the dashboard of a new commit
-func postCommit(key string, l *HgLog) os.Error {
-	return dashStatus("POST", "commit", param{
-		"key":    key,
-		"node":   l.Hash,
-		"date":   l.Date,
-		"user":   l.Author,
-		"parent": l.Parent,
-		"desc":   l.Desc,
-	})
+func postCommit(key, pkg string, l *HgLog) error {
+	t, err := time.Parse(time.RFC3339, l.Date)
+	if err != nil {
+		return fmt.Errorf("parsing %q: %v", l.Date, t)
+	}
+	return dash("POST", "commit", url.Values{"key": {key}}, obj{
+		"PackagePath": pkg,
+		"Hash":        l.Hash,
+		"ParentHash":  l.Parent,
+		"Time":        t.Unix() * 1e6, // in microseconds, yuck!
+		"User":        l.Author,
+		"Desc":        l.Desc,
+	}, nil)
 }
 
-// dashboardCommit returns true if the dashboard knows about hash.
-func dashboardCommit(hash string) bool {
-	err := dashStatus("GET", "commit", param{"node": hash})
-	if err != nil {
-		log.Printf("check %s: %s", hash, err)
-		return false
+func dashboardCommit(pkg, hash string) bool {
+	err := dash("GET", "commit", url.Values{
+		"packagePath": {pkg},
+		"hash":        {hash},
+	}, nil, nil)
+	return err == nil
+}
+
+func dashboardPackages() []string {
+	var resp []struct {
+		Path string
+	}
+	if err := dash("GET", "packages", nil, nil, &resp); err != nil {
+		log.Println("dashboardPackages:", err)
+		return nil
+	}
+	var pkgs []string
+	for _, r := range resp {
+		pkgs = append(pkgs, r.Path)
 	}
-	return true
+	return pkgs
 }
diff --git a/misc/dashboard/builder/main.go b/misc/dashboard/builder/main.go
index a547984..3556a45 100644
--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -5,38 +5,39 @@
 package main
 
 import (
+	"encoding/xml"
+	"errors"
 	"flag"
 	"fmt"
 	"io/ioutil"
 	"log"
 	"os"
 	"path"
+	"path/filepath"
 	"regexp"
 	"runtime"
 	"strconv"
 	"strings"
 	"time"
-	"xml"
 )
 
 const (
 	codeProject      = "go"
 	codePyScript     = "misc/dashboard/googlecode_upload.py"
 	hgUrl            = "https://go.googlecode.com/hg/"
-	waitInterval     = 30e9 // time to wait before checking for new revs
 	mkdirPerm        = 0750
-	pkgBuildInterval = 1e9 * 60 * 60 * 24 // rebuild packages every 24 hours
+	waitInterval     = 30 * time.Second // time to wait before checking for new revs
+	pkgBuildInterval = 24 * time.Hour   // rebuild packages every 24 hours
 )
 
 // These variables are copied from the gobuilder's environment
 // to the envv of its subprocesses.
 var extraEnv = []string{
-	"GOHOSTOS",
+	"GOARM",
 	"GOHOSTARCH",
+	"GOHOSTOS",
 	"PATH",
-	"DISABLE_NET_TESTS",
-	"MAKEFLAGS",
-	"GOARM",
+	"TMPDIR",
 }
 
 type Builder struct {
@@ -50,7 +51,7 @@ type Builder struct {
 var (
 	buildroot     = flag.String("buildroot", path.Join(os.TempDir(), "gobuilder"), "Directory under which to build")
 	commitFlag    = flag.Bool("commit", false, "upload information about new commits")
-	dashboard     = flag.String("dashboard", "godashboard.appspot.com", "Go Dashboard Host")
+	dashboard     = flag.String("dashboard", "build.golang.org", "Go Dashboard Host")
 	buildRelease  = flag.Bool("release", false, "Build and upload binary release archives")
 	buildRevision = flag.String("rev", "", "Build specified revision and exit")
 	buildCmd      = flag.String("cmd", "./all.bash", "Build command (specify absolute or relative to go/src/)")
@@ -92,7 +93,7 @@ func main() {
 	if err := os.Mkdir(*buildroot, mkdirPerm); err != nil {
 		log.Fatalf("Error making build root (%s): %s", *buildroot, err)
 	}
-	if err := run(nil, *buildroot, "hg", "clone", hgUrl, goroot); err != nil {
+	if err := hgClone(hgUrl, goroot); err != nil {
 		log.Fatal("Error cloning repository:", err)
 	}
 
@@ -106,7 +107,7 @@ func main() {
 
 	// if specified, build revision and return
 	if *buildRevision != "" {
-		hash, err := fullHash(*buildRevision)
+		hash, err := fullHash(goroot, *buildRevision)
 		if err != nil {
 			log.Fatal("Error finding revision: ", err)
 		}
@@ -130,7 +131,7 @@ func main() {
 	// check for new commits and build them
 	for {
 		built := false
-		t := time.Nanoseconds()
+		t := time.Now()
 		if *parallel {
 			done := make(chan bool)
 			for _, b := range builders {
@@ -151,14 +152,14 @@ func main() {
 			time.Sleep(waitInterval)
 		}
 		// sleep if we're looping too fast.
-		t1 := time.Nanoseconds() - t
-		if t1 < waitInterval {
-			time.Sleep(waitInterval - t1)
+		dt := time.Now().Sub(t)
+		if dt < waitInterval {
+			time.Sleep(waitInterval - dt)
 		}
 	}
 }
 
-func NewBuilder(builder string) (*Builder, os.Error) {
+func NewBuilder(builder string) (*Builder, error) {
 	b := &Builder{name: builder}
 
 	// get goos/goarch from builder string
@@ -193,7 +194,7 @@ func NewBuilder(builder string) (*Builder, os.Error) {
 // a new release tag is found.
 func (b *Builder) buildExternal() {
 	var prevTag string
-	var nextBuild int64
+	var nextBuild time.Time
 	for {
 		time.Sleep(waitInterval)
 		err := run(nil, goroot, "hg", "pull", "-u")
@@ -212,7 +213,7 @@ func (b *Builder) buildExternal() {
 		// don't rebuild if there's no new release
 		// and it's been less than pkgBuildInterval
 		// nanoseconds since the last build.
-		if tag == prevTag && time.Nanoseconds() < nextBuild {
+		if tag == prevTag && time.Now().Before(nextBuild) {
 			continue
 		}
 		// build will also build the packages
@@ -221,7 +222,7 @@ func (b *Builder) buildExternal() {
 			continue
 		}
 		prevTag = tag
-		nextBuild = time.Nanoseconds() + pkgBuildInterval
+		nextBuild = time.Now().Add(pkgBuildInterval)
 	}
 }
 
@@ -235,7 +236,7 @@ func (b *Builder) build() bool {
 			log.Println(b.name, "build:", err)
 		}
 	}()
-	hash, err := b.todo()
+	hash, err := b.todo("build-go-commit", "", "")
 	if err != nil {
 		log.Println(err)
 		return false
@@ -245,7 +246,7 @@ func (b *Builder) build() bool {
 	}
 	// Look for hash locally before running hg pull.
 
-	if _, err := fullHash(hash[:12]); err != nil {
+	if _, err := fullHash(goroot, hash[:12]); err != nil {
 		// Don't have hash, so run hg pull.
 		if err := run(nil, goroot, "hg", "pull"); err != nil {
 			log.Println("hg pull failed:", err)
@@ -259,7 +260,7 @@ func (b *Builder) build() bool {
 	return true
 }
 
-func (b *Builder) buildHash(hash string) (err os.Error) {
+func (b *Builder) buildHash(hash string) (err error) {
 	defer func() {
 		if err != nil {
 			err = fmt.Errorf("%s build: %s: %s", b.name, hash, err)
@@ -283,8 +284,7 @@ func (b *Builder) buildHash(hash string) (err os.Error) {
 	}
 
 	// update to specified revision
-	err = run(nil, path.Join(workpath, "go"),
-		"hg", "update", hash)
+	err = run(nil, path.Join(workpath, "go"), "hg", "update", hash)
 	if err != nil {
 		return
 	}
@@ -293,7 +293,9 @@ func (b *Builder) buildHash(hash string) (err os.Error) {
 
 	// build
 	logfile := path.Join(workpath, "build.log")
+	startTime := time.Now()
 	buildLog, status, err := runLog(b.envv(), logfile, srcDir, *buildCmd)
+	runTime := time.Now().Sub(startTime)
 	if err != nil {
 		return fmt.Errorf("%s: %s", *buildCmd, err)
 	}
@@ -301,21 +303,24 @@ func (b *Builder) buildHash(hash string) (err os.Error) {
 	// if we're in external mode, build all packages and return
 	if *external {
 		if status != 0 {
-			return os.NewError("go build failed")
+			return errors.New("go build failed")
 		}
-		return b.buildPackages(workpath, hash)
+		return b.buildExternalPackages(workpath, hash)
 	}
 
 	if status != 0 {
 		// record failure
-		return b.recordResult(buildLog, hash)
+		return b.recordResult(false, "", hash, "", buildLog, runTime)
 	}
 
 	// record success
-	if err = b.recordResult("", hash); err != nil {
+	if err = b.recordResult(true, "", hash, "", "", runTime); err != nil {
 		return fmt.Errorf("recordResult: %s", err)
 	}
 
+	// build goinstallable packages
+	b.buildPackages(filepath.Join(workpath, "go"), hash)
+
 	// finish here if codeUsername and codePassword aren't set
 	if b.codeUsername == "" || b.codePassword == "" || !*buildRelease {
 		return
@@ -342,11 +347,67 @@ func (b *Builder) buildHash(hash string) (err os.Error) {
 			"-w", b.codePassword,
 			"-l", fmt.Sprintf("%s,%s", b.goos, b.goarch),
 			fn)
+		if err != nil {
+			return fmt.Errorf("%s: %s", codePyScript, err)
+		}
 	}
 
 	return
 }
 
+func (b *Builder) buildPackages(goRoot, goHash string) {
+	for _, pkg := range dashboardPackages() {
+		// get the latest todo for this package
+		hash, err := b.todo("build-package", pkg, goHash)
+		if err != nil {
+			log.Printf("buildPackages %s: %v", pkg, err)
+			continue
+		}
+		if hash == "" {
+			continue
+		}
+
+		// goinstall the package
+		if *verbose {
+			log.Printf("buildPackages %s: installing %q", pkg, hash)
+		}
+		buildLog, err := b.goinstall(goRoot, pkg, hash)
+		ok := buildLog == ""
+		if err != nil {
+			ok = false
+			log.Printf("buildPackages %s: %v", pkg, err)
+		}
+
+		// record the result
+		err = b.recordResult(ok, pkg, hash, goHash, buildLog, 0)
+		if err != nil {
+			log.Printf("buildPackages %s: %v", pkg, err)
+		}
+	}
+}
+
+func (b *Builder) goinstall(goRoot, pkg, hash string) (string, error) {
+	bin := filepath.Join(goRoot, "bin/goinstall")
+	env := append(b.envv(), "GOROOT="+goRoot)
+
+	// fetch package and dependencies
+	log, status, err := runLog(env, "", goRoot, bin,
+		"-dashboard=false", "-install=false", pkg)
+	if err != nil || status != 0 {
+		return log, err
+	}
+
+	// hg update to the specified hash
+	pkgPath := filepath.Join(goRoot, "src/pkg", pkg)
+	if err := run(nil, pkgPath, "hg", "update", hash); err != nil {
+		return "", err
+	}
+
+	// build the package
+	log, _, err = runLog(env, "", goRoot, bin, "-dashboard=false", pkg)
+	return log, err
+}
+
 // envv returns an environment for build/bench execution
 func (b *Builder) envv() []string {
 	if runtime.GOOS == "windows" {
@@ -409,12 +470,12 @@ func (b *Builder) envvWindows() []string {
 
 func isDirectory(name string) bool {
 	s, err := os.Stat(name)
-	return err == nil && s.IsDirectory()
+	return err == nil && s.IsDir()
 }
 
 func isFile(name string) bool {
 	s, err := os.Stat(name)
-	return err == nil && (s.IsRegular() || s.IsSymlink())
+	return err == nil && !s.IsDir()
 }
 
 // commitWatcher polls hg for new commits and tells the dashboard about them.
@@ -424,11 +485,16 @@ func commitWatcher() {
 	if err != nil {
 		log.Fatal(err)
 	}
+	key := b.key
+
 	for {
 		if *verbose {
 			log.Printf("poll...")
 		}
-		commitPoll(b.key)
+		commitPoll(key, "")
+		for _, pkg := range dashboardPackages() {
+			commitPoll(key, pkg)
+		}
 		if *verbose {
 			log.Printf("sleep...")
 		}
@@ -436,6 +502,18 @@ func commitWatcher() {
 	}
 }
 
+func hgClone(url, path string) error {
+	return run(nil, *buildroot, "hg", "clone", url, path)
+}
+
+func hgRepoExists(path string) bool {
+	fi, err := os.Stat(filepath.Join(path, ".hg"))
+	if err != nil {
+		return false
+	}
+	return fi.IsDir()
+}
+
 // HgLog represents a single Mercurial revision.
 type HgLog struct {
 	Hash   string
@@ -455,18 +533,18 @@ var logByHash = map[string]*HgLog{}
 // xmlLogTemplate is a template to pass to Mercurial to make
 // hg log print the log in valid XML for parsing with xml.Unmarshal.
 const xmlLogTemplate = `
-	<log>
-	<hash>{node|escape}</hash>
-	<parent>{parent|escape}</parent>
-	<author>{author|escape}</author>
-	<date>{date}</date>
-	<desc>{desc|escape}</desc>
-	</log>
+	<Log>
+	<Hash>{node|escape}</Hash>
+	<Parent>{parent|escape}</Parent>
+	<Author>{author|escape}</Author>
+	<Date>{date|rfc3339date}</Date>
+	<Desc>{desc|escape}</Desc>
+	</Log>
 `
 
 // commitPoll pulls any new revisions from the hg server
 // and tells the server about them.
-func commitPoll(key string) {
+func commitPoll(key, pkg string) {
 	// Catch unexpected panics.
 	defer func() {
 		if err := recover(); err != nil {
@@ -474,14 +552,29 @@ func commitPoll(key string) {
 		}
 	}()
 
-	if err := run(nil, goroot, "hg", "pull"); err != nil {
+	pkgRoot := goroot
+
+	if pkg != "" {
+		pkgRoot = path.Join(*buildroot, pkg)
+		if !hgRepoExists(pkgRoot) {
+			if err := hgClone(repoURL(pkg), pkgRoot); err != nil {
+				log.Printf("%s: hg clone failed: %v", pkg, err)
+				if err := os.RemoveAll(pkgRoot); err != nil {
+					log.Printf("%s: %v", pkg, err)
+				}
+				return
+			}
+		}
+	}
+
+	if err := run(nil, pkgRoot, "hg", "pull"); err != nil {
 		log.Printf("hg pull: %v", err)
 		return
 	}
 
 	const N = 50 // how many revisions to grab
 
-	data, _, err := runLog(nil, "", goroot, "hg", "log",
+	data, _, err := runLog(nil, "", pkgRoot, "hg", "log",
 		"--encoding=utf-8",
 		"--limit="+strconv.Itoa(N),
 		"--template="+xmlLogTemplate,
@@ -494,7 +587,7 @@ func commitPoll(key string) {
 	var logStruct struct {
 		Log []HgLog
 	}
-	err = xml.Unmarshal(strings.NewReader("<top>"+data+"</top>"), &logStruct)
+	err = xml.Unmarshal([]byte("<Top>"+data+"</Top>"), &logStruct)
 	if err != nil {
 		log.Printf("unmarshal hg log: %v", err)
 		return
@@ -510,14 +603,11 @@ func commitPoll(key string) {
 		if l.Parent == "" && i+1 < len(logs) {
 			l.Parent = logs[i+1].Hash
 		} else if l.Parent != "" {
-			l.Parent, _ = fullHash(l.Parent)
+			l.Parent, _ = fullHash(pkgRoot, l.Parent)
 		}
-		log.Printf("hg log: %s < %s\n", l.Hash, l.Parent)
-		if l.Parent == "" {
-			// Can't create node without parent.
-			continue
+		if *verbose {
+			log.Printf("hg log %s: %s < %s\n", pkg, l.Hash, l.Parent)
 		}
-
 		if logByHash[l.Hash] == nil {
 			// Make copy to avoid pinning entire slice when only one entry is new.
 			t := *l
@@ -527,17 +617,14 @@ func commitPoll(key string) {
 
 	for i := range logs {
 		l := &logs[i]
-		if l.Parent == "" {
-			continue
-		}
-		addCommit(l.Hash, key)
+		addCommit(pkg, l.Hash, key)
 	}
 }
 
 // addCommit adds the commit with the named hash to the dashboard.
 // key is the secret key for authentication to the dashboard.
 // It avoids duplicate effort.
-func addCommit(hash, key string) bool {
+func addCommit(pkg, hash, key string) bool {
 	l := logByHash[hash]
 	if l == nil {
 		return false
@@ -547,7 +634,7 @@ func addCommit(hash, key string) bool {
 	}
 
 	// Check for already added, perhaps in an earlier run.
-	if dashboardCommit(hash) {
+	if dashboardCommit(pkg, hash) {
 		log.Printf("%s already on dashboard\n", hash)
 		// Record that this hash is on the dashboard,
 		// as must be all its parents.
@@ -559,12 +646,14 @@ func addCommit(hash, key string) bool {
 	}
 
 	// Create parent first, to maintain some semblance of order.
-	if !addCommit(l.Parent, key) {
-		return false
+	if l.Parent != "" {
+		if !addCommit(pkg, l.Parent, key) {
+			return false
+		}
 	}
 
 	// Create commit.
-	if err := postCommit(key, l); err != nil {
+	if err := postCommit(key, pkg, l); err != nil {
 		log.Printf("failed to add %s to dashboard: %v", key, err)
 		return false
 	}
@@ -572,13 +661,13 @@ func addCommit(hash, key string) bool {
 }
 
 // fullHash returns the full hash for the given Mercurial revision.
-func fullHash(rev string) (hash string, err os.Error) {
+func fullHash(root, rev string) (hash string, err error) {
 	defer func() {
 		if err != nil {
 			err = fmt.Errorf("fullHash: %s: %s", rev, err)
 		}
 	}()
-	s, _, err := runLog(nil, "", goroot,
+	s, _, err := runLog(nil, "", root,
 		"hg", "log",
 		"--encoding=utf-8",
 		"--rev="+rev,
@@ -601,7 +690,7 @@ func fullHash(rev string) (hash string, err os.Error) {
 var revisionRe = regexp.MustCompile(`^([^ ]+) +[0-9]+:([0-9a-f]+)$`)
 
 // firstTag returns the hash and tag of the most recent tag matching re.
-func firstTag(re *regexp.Regexp) (hash string, tag string, err os.Error) {
+func firstTag(re *regexp.Regexp) (hash string, tag string, err error) {
 	o, _, err := runLog(nil, "", goroot, "hg", "tags")
 	for _, l := range strings.Split(o, "\n") {
 		if l == "" {
@@ -609,16 +698,28 @@ func firstTag(re *regexp.Regexp) (hash string, tag string, err os.Error) {
 		}
 		s := revisionRe.FindStringSubmatch(l)
 		if s == nil {
-			err = os.NewError("couldn't find revision number")
+			err = errors.New("couldn't find revision number")
 			return
 		}
 		if !re.MatchString(s[1]) {
 			continue
 		}
 		tag = s[1]
-		hash, err = fullHash(s[2])
+		hash, err = fullHash(goroot, s[2])
 		return
 	}
-	err = os.NewError("no matching tag found")
+	err = errors.New("no matching tag found")
 	return
 }
+
+var repoRe = regexp.MustCompile(`^code\.google\.com/p/([a-z0-9\-]+(\.[a-z0-9\-]+)?)(/[a-z0-9A-Z_.\-/]+)?$`)
+
+// repoURL returns the repository URL for the supplied import path.
+func repoURL(importPath string) string {
+	m := repoRe.FindStringSubmatch(importPath)
+	if len(m) < 2 {
+		log.Printf("repoURL: couldn't decipher %q", importPath)
+		return ""
+	}
+	return "https://code.google.com/p/" + m[1]
+}
diff --git a/misc/dashboard/builder/package.go b/misc/dashboard/builder/package.go
index ebf4dd3..dcd449a 100644
--- a/misc/dashboard/builder/package.go
+++ b/misc/dashboard/builder/package.go
@@ -5,6 +5,7 @@
 package main
 
 import (
+	"errors"
 	"fmt"
 	"go/doc"
 	"go/parser"
@@ -17,7 +18,7 @@ import (
 
 const MaxCommentLength = 500 // App Engine won't store more in a StringProperty.
 
-func (b *Builder) buildPackages(workpath string, hash string) os.Error {
+func (b *Builder) buildExternalPackages(workpath string, hash string) error {
 	logdir := filepath.Join(*buildroot, "log")
 	if err := os.Mkdir(logdir, 0755); err != nil {
 		return err
@@ -80,14 +81,14 @@ func (b *Builder) buildPackages(workpath string, hash string) os.Error {
 	return nil
 }
 
-func isGoFile(fi *os.FileInfo) bool {
-	return fi.IsRegular() && // exclude directories
-		!strings.HasPrefix(fi.Name, ".") && // ignore .files
-		!strings.HasSuffix(fi.Name, "_test.go") && // ignore tests
-		filepath.Ext(fi.Name) == ".go"
+func isGoFile(fi os.FileInfo) bool {
+	return !fi.IsDir() && // exclude directories
+		!strings.HasPrefix(fi.Name(), ".") && // ignore .files
+		!strings.HasSuffix(fi.Name(), "_test.go") && // ignore tests
+		filepath.Ext(fi.Name()) == ".go"
 }
 
-func packageComment(pkg, pkgpath string) (info string, err os.Error) {
+func packageComment(pkg, pkgpath string) (info string, err error) {
 	fset := token.NewFileSet()
 	pkgs, err := parser.ParseDir(fset, pkgpath, isGoFile, parser.PackageClauseOnly|parser.ParseComments)
 	if err != nil {
@@ -97,12 +98,12 @@ func packageComment(pkg, pkgpath string) (info string, err os.Error) {
 		if name == "main" {
 			continue
 		}
-		pdoc := doc.NewPackageDoc(pkgs[name], pkg)
+		pdoc := doc.New(pkgs[name], pkg, doc.AllDecls)
 		if pdoc.Doc == "" {
 			continue
 		}
 		if info != "" {
-			return "", os.NewError("multiple packages with docs")
+			return "", errors.New("multiple packages with docs")
 		}
 		info = pdoc.Doc
 	}
diff --git a/misc/dashboard/godashboard/app.yaml b/misc/dashboard/godashboard/app.yaml
index 215c163..8c76704 100644
--- a/misc/dashboard/godashboard/app.yaml
+++ b/misc/dashboard/godashboard/app.yaml
@@ -1,5 +1,5 @@
 application: godashboard
-version: 8
+version: 9
 runtime: python
 api_version: 1
 
@@ -21,5 +21,6 @@ handlers:
 - url: /project.*
   script: package.py
 
-- url: /.*
-  script: gobuild.py
+- url: /
+  static_files: main.html
+  upload: main.html
diff --git a/misc/dashboard/godashboard/fail-notify.txt b/misc/dashboard/godashboard/fail-notify.txt
index a699005..f75d09a 100644
--- a/misc/dashboard/godashboard/fail-notify.txt
+++ b/misc/dashboard/godashboard/fail-notify.txt
@@ -4,3 +4,6 @@ http://godashboard.appspot.com/log/{{loghash}}
 {{desc}}
 
 http://code.google.com/p/go/source/detail?r={{node}}
+
+$ tail -n 100 < log
+{{log}}
diff --git a/misc/dashboard/godashboard/gobuild.py b/misc/dashboard/godashboard/gobuild.py
deleted file mode 100644
index ae8d99b..0000000
--- a/misc/dashboard/godashboard/gobuild.py
+++ /dev/null
@@ -1,561 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# This is the server part of the continuous build system for Go. It must be run
-# by AppEngine.
-
-from django.utils import simplejson
-from google.appengine.api import mail
-from google.appengine.api import memcache
-from google.appengine.ext import db
-from google.appengine.ext import webapp
-from google.appengine.ext.webapp import template
-from google.appengine.ext.webapp.util import run_wsgi_app
-import datetime
-import hashlib
-import logging
-import os
-import re
-import bz2
-
-# local imports
-from auth import auth
-import const
-
-# The majority of our state are commit objects. One of these exists for each of
-# the commits known to the build system. Their key names are of the form
-# <commit number (%08x)> "-" <hg hash>. This means that a sorting by the key
-# name is sufficient to order the commits.
-#
-# The commit numbers are purely local. They need not match up to the commit
-# numbers in an hg repo. When inserting a new commit, the parent commit must be
-# given and this is used to generate the new commit number. In order to create
-# the first Commit object, a special command (/init) is used.
-#
-# N.B. user is a StringProperty, so it must be type 'unicode'.
-# desc is a BlobProperty, so it must be type 'string'.  [sic]
-class Commit(db.Model):
-    num = db.IntegerProperty() # internal, monotonic counter.
-    node = db.StringProperty() # Hg hash
-    parentnode = db.StringProperty() # Hg hash
-    user = db.StringProperty()
-    date = db.DateTimeProperty()
-    desc = db.BlobProperty()
-
-    # This is the list of builds. Each element is a string of the form <builder
-    # name> '`' <log hash>. If the log hash is empty, then the build was
-    # successful.
-    builds = db.StringListProperty()
-
-    fail_notification_sent = db.BooleanProperty()
-
-# A CompressedLog contains the textual build log of a failed build. 
-# The key name is the hex digest of the SHA256 hash of the contents.
-# The contents is bz2 compressed.
-class CompressedLog(db.Model):
-    log = db.BlobProperty()
-
-N = 30
-
-def builderInfo(b):
-    f = b.split('-', 3)
-    goos = f[0]
-    goarch = f[1]
-    note = ""
-    if len(f) > 2:
-        note = f[2]
-    return {'name': b, 'goos': goos, 'goarch': goarch, 'note': note}
-
-def builderset():
-    q = Commit.all()
-    q.order('-__key__')
-    results = q.fetch(N)
-    builders = set()
-    for c in results:
-        builders.update(set(parseBuild(build)['builder'] for build in c.builds))
-    return builders
-
-class MainPage(webapp.RequestHandler):
-    def get(self):
-        self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
-
-        try:
-            page = int(self.request.get('p', 1))
-            if not page > 0:
-                raise
-        except:
-            page = 1
-
-        try:
-            num = int(self.request.get('n', N))
-            if num <= 0 or num > 200:
-                raise
-        except:
-            num = N
-
-        offset = (page-1) * num
-
-        q = Commit.all()
-        q.order('-__key__')
-        results = q.fetch(num, offset)
-
-        revs = [toRev(r) for r in results]
-        builders = {}
-
-        for r in revs:
-            for b in r['builds']:
-                builders[b['builder']] = builderInfo(b['builder'])
-
-        for r in revs:
-            have = set(x['builder'] for x in r['builds'])
-            need = set(builders.keys()).difference(have)
-            for n in need:
-                r['builds'].append({'builder': n, 'log':'', 'ok': False})
-            r['builds'].sort(cmp = byBuilder)
-
-        builders = list(builders.items())
-        builders.sort()
-        values = {"revs": revs, "builders": [v for k,v in builders]}
-
-        values['num'] = num
-        values['prev'] = page - 1
-        if len(results) == num:
-            values['next'] = page + 1
-
-        path = os.path.join(os.path.dirname(__file__), 'main.html')
-        self.response.out.write(template.render(path, values))
-
-# A DashboardHandler is a webapp.RequestHandler but provides
-#    authenticated_post - called by post after authenticating
-#    json - writes object in json format to response output
-class DashboardHandler(webapp.RequestHandler):
-    def post(self):
-        if not auth(self.request):
-            self.response.set_status(403)
-            return
-        self.authenticated_post()
-
-    def authenticated_post(self):
-        return
-    
-    def json(self, obj):
-        self.response.set_status(200)
-        simplejson.dump(obj, self.response.out)
-        return
-
-# Todo serves /todo.  It tells the builder which commits need to be built.
-class Todo(DashboardHandler):
-    def get(self):
-        builder = self.request.get('builder')
-        key = 'todo-%s' % builder
-        response = memcache.get(key)
-        if response is None:
-            # Fell out of memcache.  Rebuild from datastore results.
-            # We walk the commit list looking for nodes that have not
-            # been built by this builder.
-            q = Commit.all()
-            q.order('-__key__')
-            todo = []
-            first = None
-            for c in q.fetch(N+1):
-                if first is None:
-                    first = c
-                if not built(c, builder):
-                    todo.append({'Hash': c.node})
-            response = simplejson.dumps(todo)
-            memcache.set(key, response, 3600)
-        self.response.set_status(200)
-        self.response.out.write(response)
-
-def built(c, builder):
-    for b in c.builds:
-        if b.startswith(builder+'`'):
-            return True
-    return False
-
-# Log serves /log/.  It retrieves log data by content hash.
-class LogHandler(DashboardHandler):
-    def get(self):
-        self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
-        hash = self.request.path[5:]
-        l = CompressedLog.get_by_key_name(hash)
-        if l is None:
-            self.response.set_status(404)
-            return
-        log = bz2.decompress(l.log)
-        self.response.set_status(200)
-        self.response.out.write(log)
-
-# Init creates the commit with id 0. Since this commit doesn't have a parent,
-# it cannot be created by Build.
-class Init(DashboardHandler):
-    def authenticated_post(self):
-        date = parseDate(self.request.get('date'))
-        node = self.request.get('node')
-        if not validNode(node) or date is None:
-            logging.error("Not valid node ('%s') or bad date (%s %s)", node, date, self.request.get('date'))
-            self.response.set_status(500)
-            return
-
-        commit = Commit(key_name = '00000000-%s' % node)
-        commit.num = 0
-        commit.node = node
-        commit.parentnode = ''
-        commit.user = self.request.get('user')
-        commit.date = date
-        commit.desc = self.request.get('desc').encode('utf8')
-
-        commit.put()
-
-        self.response.set_status(200)
-
-# The last commit when we switched to using entity groups.
-# This is the root of the new commit entity group.
-RootCommitKeyName = '00000f26-f32c6f1038207c55d5780231f7484f311020747e'
-
-# CommitHandler serves /commit.
-# A GET of /commit retrieves information about the specified commit.
-# A POST of /commit creates a node for the given commit.
-# If the commit already exists, the POST silently succeeds (like mkdir -p).
-class CommitHandler(DashboardHandler):
-    def get(self):
-        node = self.request.get('node')
-        if not validNode(node):
-            return self.json({'Status': 'FAIL', 'Error': 'malformed node hash'})
-        n = nodeByHash(node)
-        if n is None:
-            return self.json({'Status': 'FAIL', 'Error': 'unknown revision'})
-        return self.json({'Status': 'OK', 'Node': nodeObj(n)})
-
-    def authenticated_post(self):
-        # Require auth with the master key, not a per-builder key.
-        if self.request.get('builder'):
-            self.response.set_status(403)
-            return
-
-        node = self.request.get('node')
-        date = parseDate(self.request.get('date'))
-        user = self.request.get('user')
-        desc = self.request.get('desc').encode('utf8')
-        parenthash = self.request.get('parent')
-
-        if not validNode(node) or not validNode(parenthash) or date is None:
-            return self.json({'Status': 'FAIL', 'Error': 'malformed node, parent, or date'})
-
-        n = nodeByHash(node)
-        if n is None:
-            p = nodeByHash(parenthash)
-            if p is None:
-                return self.json({'Status': 'FAIL', 'Error': 'unknown parent'})
-
-            # Want to create new node in a transaction so that multiple
-            # requests creating it do not collide and so that multiple requests
-            # creating different nodes get different sequence numbers.
-            # All queries within a transaction must include an ancestor,
-            # but the original datastore objects we used for the dashboard
-            # have no common ancestor.  Instead, we use a well-known
-            # root node - the last one before we switched to entity groups -
-            # as the as the common ancestor.
-            root = Commit.get_by_key_name(RootCommitKeyName)
-
-            def add_commit():
-                if nodeByHash(node, ancestor=root) is not None:
-                    return
-
-                # Determine number for this commit.
-                # Once we have created one new entry it will be lastRooted.num+1,
-                # but the very first commit created in this scheme will have to use
-                # last.num's number instead (last is likely not rooted).
-                q = Commit.all()
-                q.order('-__key__')
-                q.ancestor(root)
-                last = q.fetch(1)[0]
-                num = last.num+1
-
-                n = Commit(key_name = '%08x-%s' % (num, node), parent = root)
-                n.num = num
-                n.node = node
-                n.parentnode = parenthash
-                n.user = user
-                n.date = date
-                n.desc = desc
-                n.put()
-            db.run_in_transaction(add_commit)
-            n = nodeByHash(node)
-            if n is None:
-                return self.json({'Status': 'FAIL', 'Error': 'failed to create commit node'})
-
-        return self.json({'Status': 'OK', 'Node': nodeObj(n)})
-
-# Build serves /build.
-# A POST to /build records a new build result.
-class Build(webapp.RequestHandler):
-    def post(self):
-        if not auth(self.request):
-            self.response.set_status(403)
-            return
-
-        builder = self.request.get('builder')
-        log = self.request.get('log').encode('utf8')
-
-        loghash = ''
-        if len(log) > 0:
-            loghash = hashlib.sha256(log).hexdigest()
-            l = CompressedLog(key_name=loghash)
-            l.log = bz2.compress(log)
-            l.put()
-
-        node = self.request.get('node')
-        if not validNode(node):
-            logging.error('Invalid node %s' % (node))
-            self.response.set_status(500)
-            return
-
-        n = nodeByHash(node)
-        if n is None:
-            logging.error('Cannot find node %s' % (node))
-            self.response.set_status(404)
-            return
-        nn = n
-
-        def add_build():
-            n = nodeByHash(node, ancestor=nn)
-            if n is None:
-                logging.error('Cannot find hash in add_build: %s %s' % (builder, node))
-                return
-
-            s = '%s`%s' % (builder, loghash)
-            for i, b in enumerate(n.builds):
-                if b.split('`', 1)[0] == builder:
-                    # logging.error('Found result for %s %s already' % (builder, node))
-                    n.builds[i] = s
-                    break
-            else:
-                # logging.error('Added result for %s %s' % (builder, node))
-                n.builds.append(s)
-            n.put()
-
-        db.run_in_transaction(add_build)
-
-        key = 'todo-%s' % builder
-        memcache.delete(key)
-
-        c = getBrokenCommit(node, builder)
-        if c is not None and not c.fail_notification_sent:
-            notifyBroken(c, builder)
-
-        self.response.set_status(200)
-
-
-def getBrokenCommit(node, builder):
-    """
-    getBrokenCommit returns a Commit that breaks the build.
-    The Commit will be either the one specified by node or the one after.
-    """
-
-    # Squelch mail if already fixed.
-    head = firstResult(builder)
-    if broken(head, builder) == False:
-        return
-
-    # Get current node and node before, after.
-    cur = nodeByHash(node)
-    if cur is None:
-        return
-    before = nodeBefore(cur)
-    after = nodeAfter(cur)
-
-    if broken(before, builder) == False and broken(cur, builder):
-        return cur
-    if broken(cur, builder) == False and broken(after, builder):
-        return after
-
-    return
-
-def firstResult(builder):
-    q = Commit.all().order('-__key__')
-    for c in q.fetch(20):
-        for i, b in enumerate(c.builds):
-            p = b.split('`', 1)
-            if p[0] == builder:
-                return c
-    return None
-
-def nodeBefore(c):
-    return nodeByHash(c.parentnode)
-
-def nodeAfter(c):
-    return Commit.all().filter('parenthash', c.node).get()
-
-def notifyBroken(c, builder):
-    def send():
-        n = Commit.get(c.key())
-        if n is None:
-            logging.error("couldn't retrieve Commit '%s'" % c.key())
-            return False
-        if n.fail_notification_sent:
-            return False
-        n.fail_notification_sent = True
-        return n.put()
-    if not db.run_in_transaction(send):
-	return
-
-    subject = const.mail_fail_subject % (builder, c.desc.split('\n')[0])
-    path = os.path.join(os.path.dirname(__file__), 'fail-notify.txt')
-    body = template.render(path, {
-        "builder": builder,
-        "node": c.node,
-        "user": c.user,
-        "desc": c.desc,
-        "loghash": logHash(c, builder)
-    })
-    mail.send_mail(
-        sender=const.mail_from,
-        to=const.mail_fail_to,
-        subject=subject,
-        body=body
-    )
-
-def logHash(c, builder):
-    for i, b in enumerate(c.builds):
-        p = b.split('`', 1)
-        if p[0] == builder:
-            return p[1]
-    return ""
-
-def broken(c, builder):
-    """
-    broken returns True if commit c breaks the build for the specified builder,
-    False if it is a good build, and None if no results exist for this builder.
-    """
-    if c is None:
-        return None
-    for i, b in enumerate(c.builds):
-        p = b.split('`', 1)
-        if p[0] == builder:
-            return len(p[1]) > 0
-    return None
-
-def node(num):
-    q = Commit.all()
-    q.filter('num =', num)
-    n = q.get()
-    return n
-
-def nodeByHash(hash, ancestor=None):
-    q = Commit.all()
-    q.filter('node =', hash)
-    if ancestor is not None:
-      q.ancestor(ancestor)
-    n = q.get()
-    return n
-
-# nodeObj returns a JSON object (ready to be passed to simplejson.dump) describing node.
-def nodeObj(n):
-    return {
-        'Hash': n.node,
-        'ParentHash': n.parentnode,
-        'User': n.user,
-        'Date': n.date.strftime('%Y-%m-%d %H:%M %z'),
-        'Desc': n.desc,
-    }
-
-class FixedOffset(datetime.tzinfo):
-    """Fixed offset in minutes east from UTC."""
-
-    def __init__(self, offset):
-        self.__offset = datetime.timedelta(seconds = offset)
-
-    def utcoffset(self, dt):
-        return self.__offset
-
-    def tzname(self, dt):
-        return None
-
-    def dst(self, dt):
-        return datetime.timedelta(0)
-
-def validNode(node):
-    if len(node) != 40:
-        return False
-    for x in node:
-        o = ord(x)
-        if (o < ord('0') or o > ord('9')) and (o < ord('a') or o > ord('f')):
-            return False
-    return True
-
-def parseDate(date):
-    if '-' in date:
-        (a, offset) = date.split('-', 1)
-        try:
-            return datetime.datetime.fromtimestamp(float(a), FixedOffset(0-int(offset)))
-        except ValueError:
-            return None
-    if '+' in date:
-        (a, offset) = date.split('+', 1)
-        try:
-            return datetime.datetime.fromtimestamp(float(a), FixedOffset(int(offset)))
-        except ValueError:
-            return None
-    try:
-        return datetime.datetime.utcfromtimestamp(float(date))
-    except ValueError:
-        return None
-
-email_re = re.compile('^[^<]+<([^>]*)>$')
-
-def toUsername(user):
-    r = email_re.match(user)
-    if r is None:
-        return user
-    email = r.groups()[0]
-    return email.replace('@golang.org', '')
-
-def dateToShortStr(d):
-    return d.strftime('%a %b %d %H:%M')
-
-def parseBuild(build):
-    [builder, logblob] = build.split('`')
-    return {'builder': builder, 'log': logblob, 'ok': len(logblob) == 0}
-
-def nodeInfo(c):
-    return {
-        "node": c.node,
-        "user": toUsername(c.user),
-        "date": dateToShortStr(c.date),
-        "desc": c.desc,
-        "shortdesc": c.desc.split('\n', 2)[0]
-    }
-
-def toRev(c):
-    b = nodeInfo(c)
-    b['builds'] = [parseBuild(build) for build in c.builds]
-    return b
-
-def byBuilder(x, y):
-    return cmp(x['builder'], y['builder'])
-
-# Give old builders work; otherwise they pound on the web site.
-class Hwget(DashboardHandler):
-    def get(self):
-        self.response.out.write("8000\n")
-
-# This is the URL map for the server. The first three entries are public, the
-# rest are only used by the builders.
-application = webapp.WSGIApplication(
-                                     [('/', MainPage),
-                                      ('/hw-get', Hwget),
-                                      ('/log/.*', LogHandler),
-                                      ('/commit', CommitHandler),
-                                      ('/init', Init),
-                                      ('/todo', Todo),
-                                      ('/build', Build),
-                                     ], debug=True)
-
-def main():
-    run_wsgi_app(application)
-
-if __name__ == "__main__":
-    main()
-
diff --git a/misc/dashboard/godashboard/main.html b/misc/dashboard/godashboard/main.html
index 5390afc..4cd98d8 100644
--- a/misc/dashboard/godashboard/main.html
+++ b/misc/dashboard/godashboard/main.html
@@ -6,8 +6,6 @@
   </head>
 
   <body>
-    <a id="top"></a>
-
     <ul class="menu">
       <li>Build Status</li>
       <li><a href="/package">Packages</a></li>
@@ -18,45 +16,8 @@
     <h1>Go Dashboard</h1>
     
     <h2>Build Status</h2>
-    <table class="alternate" cellpadding="0" cellspacing="0">
-      <tr>
-        <th></th>
-        {% for b in builders %}
-          <th class="builder">{{b.goos}}<br>{{b.goarch}}<br>{{b.note}}</th>
-        {% endfor %}
-        <th></th>
-        <th></th>
-        <th></th>
-      </tr>
-
-      {% for r in revs %}
-      <tr>
-        <td class="revision"><span class="hash"><a href="https://code.google.com/p/go/source/detail?r={{r.node}}">{{r.node|slice:":12"}}</a></span></td>
 
-        {% for b in r.builds %}
-          <td class="result">
-          {% if b.ok %}
-            <span class="ok">ok</span>
-          {% else %}
-            {% if b.log %}
-              <a class="fail" href="/log/{{b.log}}">fail</a>
-            {% else %}
-               
-            {% endif %}
-          {% endif %}
-          </td>
-        {% endfor %}
+    <p class="notice">The build status dashboard has moved to <a href="http://build.golang.org">build.golang.org</a>.</p>
 
-        <td class="user">{{r.user|escape}}</td>
-        <td class="date">{{r.date|escape}}</td>
-        <td class="desc">{{r.shortdesc|escape}}</td>
-      </tr>
-      {% endfor %}
-    </table>
-    <div class="paginate">
-	<a{% if prev %} href="?n={{num}}&p={{prev}}"{% else %} class="inactive"{% endif %}>prev</a>
-	<a{% if next %} href="?n={{num}}&p={{next}}"{% else %} class="inactive"{% endif %}>next</a>
-	<a{% if prev %} href="?n={{num}}&p=1"{% else %} class="inactive"{% endif %}>top</a>
-    </div>
   </body>
 </html>
diff --git a/misc/dashboard/godashboard/package.html b/misc/dashboard/godashboard/package.html
index 8a9d0a3..b688af9 100644
--- a/misc/dashboard/godashboard/package.html
+++ b/misc/dashboard/godashboard/package.html
@@ -20,12 +20,14 @@
     may or may not build or be safe to use.
     </p>
 
+<!--
     <p>
     An "ok" in the <b>build</b> column indicates that the package is
     <a href="http://golang.org/cmd/goinstall/">goinstallable</a>
     with the latest
     <a href="http://golang.org/doc/devel/release.html">release</a> of Go.
     </p>
+-->
 
     <p>
     The <b>info</b> column shows the first paragraph from the
@@ -39,7 +41,7 @@
         <tr>
           <td class="time">{{r.last_install|date:"Y-M-d H:i"}}</td>
           <td class="count">{{r.week_count}}</td>
-          <td class="ok">{% if r.ok %}<a title="{{r.last_ok|date:"Y-M-d H:i"}}">ok</a>{% else %} {% endif %}</td>
+<!--          <td class="ok">{% if r.ok %}<a title="{{r.last_ok|date:"Y-M-d H:i"}}">ok</a>{% else %} {% endif %}</td> -->
           <td class="path"><a href="{{r.web_url}}">{{r.path}}</a></td>
           <td class="info">{% if r.info %}{{r.info|escape}}{% endif %}</td>
         </tr>
@@ -53,7 +55,7 @@
         <tr>
           <td class="time">{{r.last_install|date:"Y-M-d H:i"}}</td>
           <td class="count">{{r.count}}</td>
-          <td class="ok">{% if r.ok %}<a title="{{r.last_ok|date:"Y-M-d H:i"}}">ok</a>{% else %} {% endif %}</td>
+<!--          <td class="ok">{% if r.ok %}<a title="{{r.last_ok|date:"Y-M-d H:i"}}">ok</a>{% else %} {% endif %}</td> -->
           <td class="path"><a href="{{r.web_url}}">{{r.path}}</a></td>
           <td class="info">{% if r.info %}{{r.info|escape}}{% endif %}</td>
         </tr>
@@ -67,7 +69,7 @@
         <tr>
           <td class="time">{{r.last_install|date:"Y-M-d H:i"}}</td>
           <td class="count">{{r.count}}</td>
-          <td class="ok">{% if r.ok %}<a title="{{r.last_ok|date:"Y-M-d H:i"}}">ok</a>{% else %} {% endif %}</td>
+<!--          <td class="ok">{% if r.ok %}<a title="{{r.last_ok|date:"Y-M-d H:i"}}">ok</a>{% else %} {% endif %}</td> -->
           <td class="path"><a href="{{r.web_url}}">{{r.path}}</a></td>
           <td class="info">{% if r.info %}{{r.info|escape}}{% endif %}</td>
         </tr>
diff --git a/misc/dashboard/godashboard/static/style.css b/misc/dashboard/godashboard/static/style.css
index d6d23b5..0ce583a 100644
--- a/misc/dashboard/godashboard/static/style.css
+++ b/misc/dashboard/godashboard/static/style.css
@@ -116,3 +116,14 @@ div.paginate a.inactive {
 td.time {
 	font-family: monospace;
 }
+.notice {
+	padding: 10px;
+	margin: 10px;
+	border: 2px solid #FF6;
+	background: #900;
+	color: white;
+	text-align: center;
+}
+.notice a {
+	color: #FF6;
+}
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index 1c90af8..7fe0934 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -7,6 +7,7 @@
 ;;; To do:
 
 ;; * Indentation is *almost* identical to gofmt
+;; ** We think struct literal keys are labels and outdent them
 ;; ** We disagree on the indentation of function literals in arguments
 ;; ** There are bugs with the close brace of struct literals
 ;; * Highlight identifiers according to their syntactic context: type,
@@ -43,17 +44,11 @@
     (modify-syntax-entry ?<  "." st)
     (modify-syntax-entry ?>  "." st)
 
-    ;; Strings
-    (modify-syntax-entry ?\" "\"" st)
-    (modify-syntax-entry ?\' "\"" st)
-    (modify-syntax-entry ?`  "\"" st)
-    (modify-syntax-entry ?\\ "\\" st)
-
-    ;; Comments
-    (modify-syntax-entry ?/  ". 124b" st)
-    (modify-syntax-entry ?*  ". 23"   st)
-    (modify-syntax-entry ?\n "> b"    st)
-    (modify-syntax-entry ?\^m "> b"   st)
+    ;; Strings and comments are font-locked separately.
+    (modify-syntax-entry ?\" "." st)
+    (modify-syntax-entry ?\' "." st)
+    (modify-syntax-entry ?`  "." st)
+    (modify-syntax-entry ?\\ "." st)
 
     st)
   "Syntax table for Go mode.")
@@ -68,12 +63,14 @@
 some syntax analysis.")
 
 (defvar go-mode-font-lock-keywords
-  (let ((builtins '("append" "cap" "close" "complex" "copy" "imag" "len"
+  (let ((builtins '("append" "cap" "close" "complex" "copy" "delete" "imag" "len"
                     "make" "new" "panic" "print" "println" "real" "recover"))
         (constants '("nil" "true" "false" "iota"))
         (type-name "\\s *\\(?:[*(]\\s *\\)*\\(?:\\w+\\s *\\.\\s *\\)?\\(\\w+\\)")
         )
-    `((,(regexp-opt go-mode-keywords 'words) . font-lock-keyword-face)
+    `((go-mode-font-lock-cs-comment 0 font-lock-comment-face t)
+      (go-mode-font-lock-cs-string 0 font-lock-string-face t)
+      (,(regexp-opt go-mode-keywords 'words) . font-lock-keyword-face)
       (,(regexp-opt builtins 'words) . font-lock-builtin-face)
       (,(regexp-opt constants 'words) . font-lock-constant-face)
       ;; Function names in declarations
@@ -87,7 +84,7 @@ some syntax analysis.")
       (,(concat "\\<type\\>\\s *\\w+\\s *" type-name) 1 font-lock-type-face)
       ;; Arrays/slices/map value type
       ;; XXX Wrong.  Marks 0 in expression "foo[0] * x"
-;;      (,(concat "]" type-name) 1 font-lock-type-face)
+      ;;      (,(concat "]" type-name) 1 font-lock-type-face)
       ;; Map key type
       (,(concat "\\<map\\s *\\[" type-name) 1 font-lock-type-face)
       ;; Channel value type
@@ -164,27 +161,25 @@ will be marked from the beginning up to this point (that is, up
 to and including character (1- go-mode-mark-cs-end)).")
 (make-variable-buffer-local 'go-mode-mark-cs-end)
 
-(defvar go-mode-mark-cs-state nil
-  "The `parse-partial-sexp' state of the comment/string parser as
-of the point `go-mode-mark-cs-end'.")
-(make-variable-buffer-local 'go-mode-mark-cs-state)
-
 (defvar go-mode-mark-nesting-end 1
   "The point at which the nesting cache ends.  The buffer will be
 marked from the beginning up to this point.")
 (make-variable-buffer-local 'go-mode-mark-nesting-end)
 
-(defun go-mode-mark-clear-cache (b e l)
-  "An after-change-function that clears the comment/string and
+(defun go-mode-mark-clear-cache (b e)
+  "A before-change-function that clears the comment/string and
 nesting caches from the modified point on."
 
   (save-restriction
     (widen)
-    (when (< b go-mode-mark-cs-end)
-      (remove-text-properties b (min go-mode-mark-cs-end (point-max)) '(go-mode-cs nil))
-      (setq go-mode-mark-cs-end b
-            go-mode-mark-cs-state nil))
-
+    (when (<= b go-mode-mark-cs-end)
+      ;; Remove the property adjacent to the change position.
+      ;; It may contain positions pointing beyond the new end mark.
+      (let ((b (let ((cs (get-text-property (max 1 (1- b)) 'go-mode-cs)))
+		 (if cs (car cs) b))))
+	(remove-text-properties
+	 b (min go-mode-mark-cs-end (point-max)) '(go-mode-cs nil))
+	(setq go-mode-mark-cs-end b)))
     (when (< b go-mode-mark-nesting-end)
       (remove-text-properties b (min go-mode-mark-nesting-end (point-max)) '(go-mode-nesting nil))
       (setq go-mode-mark-nesting-end b))))
@@ -209,7 +204,7 @@ context-sensitive."
                (progn , at body)
              (set-buffer-modified-p ,modified-var)))))))
 
-(defsubst go-mode-cs (&optional pos)
+(defun go-mode-cs (&optional pos)
   "Return the comment/string state at point POS.  If point is
 inside a comment or string (including the delimiters), this
 returns a pair (START . END) indicating the extents of the
@@ -217,45 +212,111 @@ comment or string."
 
   (unless pos
     (setq pos (point)))
-  (if (= pos 1)
-      nil
-    (when (> pos go-mode-mark-cs-end)
-      (go-mode-mark-cs pos))
-    (get-text-property (- pos 1) 'go-mode-cs)))
+  (when (> pos go-mode-mark-cs-end)
+    (go-mode-mark-cs pos))
+  (get-text-property pos 'go-mode-cs))
 
 (defun go-mode-mark-cs (end)
   "Mark comments and strings up to point END.  Don't call this
 directly; use `go-mode-cs'."
-
   (setq end (min end (point-max)))
   (go-mode-parser
-   (let* ((pos go-mode-mark-cs-end)
-          (state (or go-mode-mark-cs-state (syntax-ppss pos))))
-     ;; Mark comments and strings
-     (when (nth 8 state)
-       ;; Get to the beginning of the comment/string
-       (setq pos (nth 8 state)
-             state nil))
-     (while (> end pos)
-       ;; Find beginning of comment/string
-       (while (and (> end pos)
-                   (progn
-                     (setq state (parse-partial-sexp pos end nil nil state 'syntax-table)
-                           pos (point))
-                     (not (nth 8 state)))))
-       ;; Find end of comment/string
-       (let ((start (nth 8 state)))
-         (when start
-           (setq state (parse-partial-sexp pos (point-max) nil nil state 'syntax-table)
-                 pos (point))
-           ;; Mark comment
-           (put-text-property start (- pos 1) 'go-mode-cs (cons start pos))
-           (when nil
-             (put-text-property start (- pos 1) 'face
-                                `((:background "midnight blue")))))))
-     ;; Update state
-     (setq go-mode-mark-cs-end   pos
-           go-mode-mark-cs-state state))))
+   (save-match-data
+     (let ((pos
+	    ;; Back up to the last known state.
+	    (let ((last-cs
+		   (and (> go-mode-mark-cs-end 1)
+			(get-text-property (1- go-mode-mark-cs-end) 
+					   'go-mode-cs))))
+	      (if last-cs
+		  (car last-cs)
+		(max 1 (1- go-mode-mark-cs-end))))))
+       (while (< pos end)
+	 (goto-char pos)
+	 (let ((cs-end			; end of the text property
+		(cond
+		 ((looking-at "//")
+		  (end-of-line)
+		  (point))
+		 ((looking-at "/\\*")
+		  (goto-char (+ pos 2))
+		  (if (search-forward "*/" (1+ end) t)
+		      (point)
+		    end))
+		 ((looking-at "\"")
+		  (goto-char (1+ pos))
+		  (if (looking-at "[^\"\n\\\\]*\\(\\\\.[^\"\n\\\\]*\\)*\"")
+		      (match-end 0)
+		    (end-of-line)
+		    (point)))
+		 ((looking-at "'")
+		  (goto-char (1+ pos))
+		  (if (looking-at "[^'\n\\\\]*\\(\\\\.[^'\n\\\\]*\\)*'")
+		      (match-end 0)
+		    (end-of-line)
+		    (point)))
+		 ((looking-at "`")
+		  (goto-char (1+ pos))
+		  (while (if (search-forward "`" end t)
+			     (if (eq (char-after) ?`)
+				 (goto-char (1+ (point))))
+			   (goto-char end)
+			   nil))
+		  (point)))))
+	   (cond
+	    (cs-end
+	     (put-text-property pos cs-end 'go-mode-cs (cons pos cs-end))
+	     (setq pos cs-end))
+	    ((re-search-forward "[\"'`]\\|/[/*]" end t)
+	     (setq pos (match-beginning 0)))
+	    (t
+	     (setq pos end)))))
+       (setq go-mode-mark-cs-end pos)))))
+
+
+
+(defun go-mode-font-lock-cs (limit comment)
+  "Helper function for highlighting comment/strings.  If COMMENT is t,
+set match data to the next comment after point, and advance point
+after it.  If COMMENT is nil, use the next string.  Returns nil
+if no further tokens of the type exist."
+  ;; Ensures that `next-single-property-change' below will work properly.
+  (go-mode-cs limit)
+  (let (cs next (result 'scan))
+    (while (eq result 'scan)
+      (if (or (>= (point) limit) (eobp))
+	  (setq result nil)
+	(setq cs (go-mode-cs))
+	(if cs
+	    (if (eq (= (char-after (car cs)) ?/) comment)
+		;; If inside the expected comment/string, highlight it.
+		(progn
+		  ;; If the match includes a "\n", we have a
+		  ;; multi-line construct.  Mark it as such.
+		  (goto-char (car cs))
+		  (when (search-forward "\n" (cdr cs) t)
+		    (put-text-property
+		     (car cs) (cdr cs) 'font-lock-multline t))
+		  (set-match-data (list (car cs) (cdr cs) (current-buffer)))
+		  (goto-char (cdr cs))
+		  (setq result t))
+	      ;; Wrong type.  Look for next comment/string after this one.
+	      (goto-char (cdr cs)))
+	  ;; Not inside comment/string.  Search for next comment/string.
+	  (setq next (next-single-property-change
+		      (point) 'go-mode-cs nil limit))
+	  (if (and next (< next limit))
+	      (goto-char next)
+	    (setq result nil)))))
+    result))
+
+(defun go-mode-font-lock-cs-string (limit)
+  "Font-lock iterator for strings."
+  (go-mode-font-lock-cs limit nil))
+
+(defun go-mode-font-lock-cs-comment (limit)
+  "Font-lock iterator for comments."
+  (go-mode-font-lock-cs limit t))
 
 (defsubst go-mode-nesting (&optional pos)
   "Return the nesting at point POS.  The nesting is a list
@@ -400,8 +461,7 @@ indented one level."
                 (setq first nil))))
 
           ;; case, default, and labels are outdented 1 level
-          ;; assume that labels are alone on the line
-          (when (looking-at "\\<case\\>\\|\\<default\\>\\|\\w+\\s *:\\s *$")
+          (when (looking-at "\\<case\\>\\|\\<default\\>\\|\\w+\\s *:\\(\\S.\\|$\\)")
             (decf indent tab-width))
 
           ;; Continuation lines are indented 1 level
@@ -470,9 +530,8 @@ functions, and some types.  It also provides indentation that is
 
   ;; Reset the syntax mark caches
   (setq go-mode-mark-cs-end      1
-        go-mode-mark-cs-state    nil
         go-mode-mark-nesting-end 1)
-  (add-hook 'after-change-functions #'go-mode-mark-clear-cache nil t)
+  (add-hook 'before-change-functions #'go-mode-mark-clear-cache nil t)
 
   ;; Indentation
   (set (make-local-variable 'indent-line-function)
@@ -500,45 +559,92 @@ Useful for development work."
 
 ;;;###autoload
 (defun gofmt ()
- "Pipe the current buffer through the external tool `gofmt`.
+  "Pipe the current buffer through the external tool `gofmt`.
 Replace the current buffer on success; display errors on failure."
 
- (interactive)
- (let ((srcbuf (current-buffer)))
-   (with-temp-buffer
-     (let ((outbuf (current-buffer))
-           (errbuf (get-buffer-create "*Gofmt Errors*"))
-           (coding-system-for-read 'utf-8)    ;; use utf-8 with subprocesses
-           (coding-system-for-write 'utf-8))
-       (with-current-buffer errbuf (erase-buffer))
-       (with-current-buffer srcbuf
-         (save-restriction
-           (let (deactivate-mark)
-             (widen)
-             (if (= 0 (shell-command-on-region (point-min) (point-max) "gofmt"
-                                               outbuf nil errbuf))
-                 ;; gofmt succeeded: replace the current buffer with outbuf,
-                 ;; restore the mark and point, and discard errbuf.
-                 (let ((old-mark (mark t)) (old-point (point)))
-                   (erase-buffer)
-                   (insert-buffer-substring outbuf)
-                   (goto-char (min old-point (point-max)))
-                   (if old-mark (push-mark (min old-mark (point-max)) t))
-                   (kill-buffer errbuf))
-
-               ;; gofmt failed: display the errors
-               (display-buffer errbuf)))))
-
-       ;; Collapse any window opened on outbuf if shell-command-on-region
-       ;; displayed it.
-       (delete-windows-on outbuf)))))
+  (interactive)
+  (let ((currconf (current-window-configuration)))
+    (let ((srcbuf (current-buffer)))
+      (with-temp-buffer
+	(let ((outbuf (current-buffer))
+	      (errbuf (get-buffer-create "*Gofmt Errors*"))
+	      (coding-system-for-read 'utf-8)    ;; use utf-8 with subprocesses
+	      (coding-system-for-write 'utf-8))
+	  (with-current-buffer errbuf (erase-buffer))
+	  (with-current-buffer srcbuf
+	    (save-restriction
+	      (let (deactivate-mark)
+		(widen)
+		(if (= 0 (shell-command-on-region (point-min) (point-max) "gofmt"
+						  outbuf nil errbuf))
+		    ;; restore window config
+		    ;; gofmt succeeded: replace the current buffer with outbuf,
+		    ;; restore the mark and point, and discard errbuf.
+		    (let ((old-mark (mark t)) (old-point (point)))
+		      (set-window-configuration currconf)
+		      (erase-buffer)
+		      (insert-buffer-substring outbuf)
+		      (goto-char (min old-point (point-max)))
+		      (if old-mark (push-mark (min old-mark (point-max)) t))
+		      (kill-buffer errbuf))
+
+		  ;; gofmt failed: display the errors
+		  (display-buffer errbuf)))))
+
+	  ;; Collapse any window opened on outbuf if shell-command-on-region
+	  ;; displayed it.
+	  (delete-windows-on outbuf))))))
 
 ;;;###autoload
 (defun gofmt-before-save ()
- "Add this to .emacs to run gofmt on the current buffer when saving:
+  "Add this to .emacs to run gofmt on the current buffer when saving:
  (add-hook 'before-save-hook #'gofmt-before-save)"
 
- (interactive)
- (when (eq major-mode 'go-mode) (gofmt)))
+  (interactive)
+  (when (eq major-mode 'go-mode) (gofmt)))
+
+(defun godoc-read-query ()
+  "Read a godoc query from the minibuffer."
+  ;; Compute the default query as the symbol under the cursor.
+  ;; TODO: This does the wrong thing for e.g. multipart.NewReader (it only grabs
+  ;; half) but I see no way to disambiguate that from e.g. foobar.SomeMethod.
+  (let* ((bounds (bounds-of-thing-at-point 'symbol))
+         (symbol (if bounds
+                     (buffer-substring-no-properties (car bounds)
+                                                     (cdr bounds)))))
+    (read-string (if symbol
+                     (format "godoc (default %s): " symbol)
+                   "godoc: ")
+                 nil nil symbol)))
+
+(defun godoc-get-buffer (query)
+  "Get an empty buffer for a godoc query."
+  (let* ((buffer-name (concat "*godoc " query "*"))
+         (buffer (get-buffer buffer-name)))
+    ;; Kill the existing buffer if it already exists.
+    (when buffer (kill-buffer buffer))
+    (get-buffer-create buffer-name)))
+
+(defun godoc-buffer-sentinel (proc event)
+  "Sentinel function run when godoc command completes."
+  (with-current-buffer (process-buffer proc)
+    (cond ((string= event "finished\n")  ;; Successful exit.
+           (goto-char (point-min))
+           (display-buffer (current-buffer) 'not-this-window))
+          ((not (= (process-exit-status proc) 0))  ;; Error exit.
+           (let ((output (buffer-string)))
+             (kill-buffer (current-buffer))
+             (message (concat "godoc: " output)))))))
+
+;;;###autoload
+(defun godoc (query)
+  "Show go documentation for a query, much like M-x man."
+  (interactive (list (godoc-read-query)))
+  (unless (string= query "")
+    (set-process-sentinel
+     (start-process-shell-command "godoc" (godoc-get-buffer query)
+                                  (concat "godoc " query))
+     'godoc-buffer-sentinel)
+    nil))
 
 (provide 'go-mode)
diff --git a/misc/godoc/README b/misc/godoc/README
deleted file mode 100644
index 3c8d830..0000000
--- a/misc/godoc/README
+++ /dev/null
@@ -1,22 +0,0 @@
-Instructions to get an initial godoc running on a local app engine emulator
----------------------------------------------------------------------------
-
-To run godoc under the app engine emulator, create a ("goroot") godoc
-directory that contains the app.yaml file, the doc and lib directories
-from the Go distribution, as well as a godoc directory with the godoc
-sources from src/cmd/godoc. In the godoc source directory, replace
-main.go with init.go. The directory structure should look as follows:
-
-godoc				// "goroot" directory
-	app.yaml		// app engine control file
-	doc			// goroot/doc directory
-	favicon.ico
-	godoc			// contains godoc sources
-		godoc.go	// unchanged godoc file
-		init.go		// this file instead of godoc/main.go
-		...		// remaining godoc files
-	lib			// goroot/lib directory
-
-Run app engine emulator locally: dev_appserver.py -a <hostname> godoc
-where godoc is the top-level "goroot" directory. The godoc home page
-is then served at: <hostname>:8080 .
diff --git a/misc/godoc/app.yaml b/misc/godoc/app.yaml
deleted file mode 100644
index f8b46db..0000000
--- a/misc/godoc/app.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2011 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.
-
-application: godoc
-version: 1
-runtime: go
-api_version: 1
-
-handlers:
-- url: /.*
-  script: _go_app
diff --git a/misc/godoc/init.go b/misc/godoc/init.go
deleted file mode 100644
index 0fd0bd5..0000000
--- a/misc/godoc/init.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2011 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 file replaces main.go when running godoc under the app engine emulator.
-// See the README file for instructions.
-
-package main
-
-import (
-	"http"
-	"log"
-	"os"
-	"path/filepath"
-)
-
-func serveError(w http.ResponseWriter, r *http.Request, relpath string, err os.Error) {
-	contents := applyTemplate(errorHTML, "errorHTML", err) // err may contain an absolute path!
-	w.WriteHeader(http.StatusNotFound)
-	servePage(w, "File "+relpath, "", "", contents)
-}
-
-func init() {
-	// set goroot
-	cwd, err := os.Getwd()
-	if err != nil {
-		log.Fatalf("cwd: %s", err)
-	}
-	log.Printf("cwd = %s", cwd)
-	*goroot = filepath.Clean(cwd)
-
-	initHandlers()
-	readTemplates()
-	registerPublicHandlers(http.DefaultServeMux)
-}
diff --git a/misc/goplay/goplay.go b/misc/goplay/goplay.go
index a1eb617..aa09e38 100644
--- a/misc/goplay/goplay.go
+++ b/misc/goplay/goplay.go
@@ -5,16 +5,16 @@
 package main
 
 import (
-	"exec"
 	"flag"
-	"http"
 	"io"
 	"io/ioutil"
 	"log"
+	"net/http"
 	"os"
+	"os/exec"
 	"runtime"
 	"strconv"
-	"template"
+	"text/template"
 )
 
 var (
@@ -84,14 +84,14 @@ func Compile(w http.ResponseWriter, req *http.Request) {
 	// write request Body to x.go
 	f, err := os.Create(src)
 	if err != nil {
-		error(w, nil, err)
+		error_(w, nil, err)
 		return
 	}
 	defer os.Remove(src)
 	defer f.Close()
 	_, err = io.Copy(f, req.Body)
 	if err != nil {
-		error(w, nil, err)
+		error_(w, nil, err)
 		return
 	}
 	f.Close()
@@ -100,7 +100,7 @@ func Compile(w http.ResponseWriter, req *http.Request) {
 	out, err := run(archChar+"g", "-o", obj, src)
 	defer os.Remove(obj)
 	if err != nil {
-		error(w, out, err)
+		error_(w, out, err)
 		return
 	}
 
@@ -108,14 +108,14 @@ func Compile(w http.ResponseWriter, req *http.Request) {
 	out, err = run(archChar+"l", "-o", bin, obj)
 	defer os.Remove(bin)
 	if err != nil {
-		error(w, out, err)
+		error_(w, out, err)
 		return
 	}
 
 	// run x
 	out, err = run(bin)
 	if err != nil {
-		error(w, out, err)
+		error_(w, out, err)
 	}
 
 	// write the output of x as the http response
@@ -128,17 +128,17 @@ func Compile(w http.ResponseWriter, req *http.Request) {
 
 // error writes compile, link, or runtime errors to the HTTP connection.
 // The JavaScript interface uses the 404 status code to identify the error.
-func error(w http.ResponseWriter, out []byte, err os.Error) {
+func error_(w http.ResponseWriter, out []byte, err error) {
 	w.WriteHeader(404)
 	if out != nil {
 		output.Execute(w, out)
 	} else {
-		output.Execute(w, err.String())
+		output.Execute(w, err.Error())
 	}
 }
 
 // run executes the specified command and returns its output and an error.
-func run(cmd ...string) ([]byte, os.Error) {
+func run(cmd ...string) ([]byte, error) {
 	return exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
 }
 
diff --git a/misc/kate/go.xml b/misc/kate/go.xml
index 14d88b2..1e00cfc 100644
--- a/misc/kate/go.xml
+++ b/misc/kate/go.xml
@@ -47,6 +47,7 @@
       <item> byte </item>
       <item> complex64 </item>
       <item> complex128 </item>
+      <item> error </item>
       <item> float32 </item>
       <item> float64 </item>
       <item> int </item>
@@ -54,6 +55,7 @@
       <item> int16 </item>
       <item> int32 </item>
       <item> int64 </item>
+      <item> rune </item>
       <item> string </item>
       <item> uint </item>
       <item> uintptr </item>
diff --git a/misc/notepadplus/go.xml b/misc/notepadplus/go.xml
index 7c5d8a1..237ef6b 100755
--- a/misc/notepadplus/go.xml
+++ b/misc/notepadplus/go.xml
@@ -17,7 +17,8 @@
 		<KeyWord name="copy" />
 		<KeyWord name="default" /> 
 		<KeyWord name="defer" /> 
-		<KeyWord name="else" /> 
+		<KeyWord name="else" />
+		<KeyWord name="error" />
 		<KeyWord name="fallthrough" /> 
 		<KeyWord name="false" /> 
 		<KeyWord name="float32" /> 
@@ -49,6 +50,7 @@
 		<KeyWord name="real" />
 		<KeyWord name="recover" />
 		<KeyWord name="return" />
+		<KeyWord name="rune" />
 		<KeyWord name="select" /> 
 		<KeyWord name="string" /> 
 		<KeyWord name="struct" /> 
diff --git a/misc/notepadplus/userDefineLang.xml b/misc/notepadplus/userDefineLang.xml
index d1927a3..2954aad 100755
--- a/misc/notepadplus/userDefineLang.xml
+++ b/misc/notepadplus/userDefineLang.xml
@@ -11,7 +11,7 @@
             <Keywords name="Folder-"></Keywords>
             <Keywords name="Operators">( ) [ ] { } ... . , _ & ^ %  > < ! = + - *  | :</Keywords>
             <Keywords name="Comment"> 1/* 2*/ 0//</Keywords>
-            <Keywords name="Words1">append bool break byte cap case chan close complex complex128 complex64 const continue copy default defer else fallthrough false float32 float64 for func go goto if iota imag import int int16 int32 int64 int8 interface len make map new nil package panic print println range real recover return select string struct switch true type uint uint16 uint32 uint64 uint8 uintptr var</Keywords>
+            <Keywords name="Words1">append bool break byte cap case chan close complex complex128 complex64 const continue copy default defer else error fallthrough false float32 float64 for func go goto if iota imag import int int16 int32 int64 int8 interface len make map new nil package panic print println range real recover return rune select string struct switch true type uint uint16 uint32 uint64 uint8 uintptr var</Keywords>
             <Keywords name="Words2"></Keywords>
             <Keywords name="Words3"></Keywords>
             <Keywords name="Words4"></Keywords>
diff --git a/misc/osx/README b/misc/osx/README
new file mode 100644
index 0000000..87476da
--- /dev/null
+++ b/misc/osx/README
@@ -0,0 +1,9 @@
+Use image.bash to construct a disk image.
+
+package.bash constructs a package file (Go.pkg) for installation on OS X, and
+is used by image.bash to construct a disk image. Strictly speaking, the disk
+image is unnecessary, but they are more common by convention.
+
+These scripts depend on PackageMaker (Developer Tools), osascript, and hdiutil.
+Appropriate checks are run in utils.bash, called at the beginning of each
+script.
diff --git a/misc/osx/ReadMe.txt b/misc/osx/ReadMe.txt
new file mode 100644
index 0000000..d8de1db
--- /dev/null
+++ b/misc/osx/ReadMe.txt
@@ -0,0 +1,4 @@
+See http://golang.org/doc/go_tutorial.html for help getting started. Note that
+the installation steps described in the "getting started" guide are performed
+for you by the installer packaged in this directory.
+
diff --git a/misc/osx/etc/paths.d/go b/misc/osx/etc/paths.d/go
new file mode 100644
index 0000000..532e5f9
--- /dev/null
+++ b/misc/osx/etc/paths.d/go
@@ -0,0 +1 @@
+/usr/local/go/bin
diff --git a/misc/osx/etc/profile_go b/misc/osx/etc/profile_go
new file mode 100755
index 0000000..6c52ac4
--- /dev/null
+++ b/misc/osx/etc/profile_go
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 2011 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.
+
+# The output of this script will be eval'd by the user's shell on startup. This
+# script decides what type of shell is being used in the same way as
+# /usr/libexec/path_helper
+
+if echo $SHELL | grep csh$ > /dev/null; then
+	echo 'setenv GOROOT /usr/local/go'
+else
+	echo 'export GOROOT=/usr/local/go'
+fi
+
diff --git a/misc/osx/image.bash b/misc/osx/image.bash
new file mode 100755
index 0000000..ff8f761
--- /dev/null
+++ b/misc/osx/image.bash
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Copyright 2011 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
+
+source utils.bash
+
+if ! test -f ../../src/env.bash; then
+	echo "package.bash must be run from $GOROOT/misc/osx" 1>&2
+fi
+
+ROOT=`hg root`
+
+echo "Running package.bash"
+./package.bash
+
+echo "Preparing image directory"
+IMGDIR=/tmp/"Go `hg id`"
+rm -rf "${IMGDIR}"
+mkdir -p "${IMGDIR}"
+
+# Copy in files
+cp "Go `hg id`.pkg" "${IMGDIR}/Go.pkg"
+cp ${ROOT}/LICENSE "${IMGDIR}/License.txt"
+cp ReadMe.txt "${IMGDIR}/ReadMe.txt"
+cp "${ROOT}/doc/gopher/bumper640x360.png" "${IMGDIR}/.background"
+
+# Call out to applescript (osascript) to prettify things
+#${OSASCRIPT} prepare.applescript
+
+echo "Creating dmg"
+${HDIUTIL} create -srcfolder "${IMGDIR}" "Go `hg id`.dmg"
+
+echo "Removing image directory"
+rm -rf ${IMGDIR}
+
diff --git a/misc/osx/package.bash b/misc/osx/package.bash
new file mode 100755
index 0000000..ac37176
--- /dev/null
+++ b/misc/osx/package.bash
@@ -0,0 +1,51 @@
+#!/bin/bash
+# Copyright 2011 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
+
+source utils.bash
+
+if ! test -f ../../src/env.bash; then
+	echo "package.bash must be run from $GOROOT/misc/osx" 1>&2
+fi
+
+BUILD=/tmp/go.build.tmp
+ROOT=`hg root`
+
+echo "Removing old images"
+rm -f *.pkg *.dmg
+
+echo "Preparing temporary directory"
+rm -rf ${BUILD}
+mkdir -p ${BUILD}
+
+echo "Preparing template"
+mkdir -p ${BUILD}/root/usr/local/
+
+echo "Copying go source distribution"
+cp -r $ROOT ${BUILD}/root/usr/local/go
+cp -r etc ${BUILD}/root/etc
+
+echo "Building go"
+pushd . > /dev/null
+cd ${BUILD}/root/usr/local/go
+GOROOT=`pwd`
+src/version.bash -save
+rm -rf .hg .hgignore .hgtags
+cd src
+./all.bash | sed "s/^/  /"
+cd ..
+popd > /dev/null
+
+echo "Building package"
+${PM} -v -r ${BUILD}/root -o "Go `hg id`.pkg" \
+	--scripts scripts \
+	--id com.googlecode.go \
+	--title Go \
+	--version "0.1" \
+	--target "10.5"
+
+echo "Removing temporary directory"
+rm -rf ${BUILD}
diff --git a/misc/osx/scripts/postinstall b/misc/osx/scripts/postinstall
new file mode 100644
index 0000000..f8545b8
--- /dev/null
+++ b/misc/osx/scripts/postinstall
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+GOROOT=/usr/local/go
+
+echo "Fixing permissions"
+cd $GOROOT
+find . -exec chmod ugo+r \{\} \;
+find bin -exec chmod ugo+rx \{\} \;
+find . -type d -exec chmod ugo+rx \{\} \;
+chmod o-w .
+
+echo "Setting GOROOT system-wide"
+echo "eval \`/etc/profile_go\`" >> /etc/csh.login
+echo "eval \`/etc/profile_go\`" >> /etc/zshenv
+echo "eval \`/etc/profile_go\`" >> /etc/profile
+
+echo "Fixing debuggers via sudo.bash"
+# setgrp procmod the debuggers (sudo.bash)
+cd $GOROOT/src
+./sudo.bash
+
+echo "Installing miscellaneous files:"
+XCODE_MISC_DIR="/Library/Application Support/Developer/Shared/Xcode/Specifications/"
+if [ -f $XCODE_MISC_DIR ]; then
+	echo "  XCode"
+	cp $GOROOT/misc/xcode/* $XCODE_MISC_DIR
+fi
+
diff --git a/misc/osx/utils.bash b/misc/osx/utils.bash
new file mode 100644
index 0000000..022a0bd
--- /dev/null
+++ b/misc/osx/utils.bash
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Copyright 2011 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
+
+echo "Attempting to locate needed utilities..."
+
+# PackageMaker
+PM=/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker
+if [ ! -x ${PM} ]; then
+	PM=/Developer${PM}
+	if [ ! -x ${PM} ]; then
+		echo "Could not find PackageMaker; aborting!"
+	fi
+fi
+echo "  PackageMaker : ${PM}"
+
+# hdiutil. If this doesn't exist, your OS X installation is horribly borked,
+# but let's check anyway...
+if which hdiutil > /dev/null; then
+	HDIUTIL=`which hdiutil`
+	echo "  hdiutil      : ${HDIUTIL}"
+fi
+
+# Ditto for osascript
+if which osascript > /dev/null; then
+	OSASCRIPT=`which osascript`
+	echo "  osascript    : ${OSASCRIPT}"
+fi
diff --git a/misc/swig/callback/Makefile b/misc/swig/callback/Makefile
index fde0d10..0ca33ef 100644
--- a/misc/swig/callback/Makefile
+++ b/misc/swig/callback/Makefile
@@ -13,5 +13,5 @@ CLEANFILES+=run
 include ../../../src/Make.pkg
 
 %: install %.go
-	$(GC) $*.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) $*.go
 	$(LD) $(SWIG_RPATH) -o $@ $*.$O
diff --git a/misc/swig/callback/run b/misc/swig/callback/run
deleted file mode 100755
index de150ed..0000000
Binary files a/misc/swig/callback/run and /dev/null differ
diff --git a/misc/swig/callback/run.go b/misc/swig/callback/run.go
index a76e636..b3f13ad 100644
--- a/misc/swig/callback/run.go
+++ b/misc/swig/callback/run.go
@@ -5,8 +5,8 @@
 package main
 
 import (
-	"swig/callback"
 	"fmt"
+	"swig/callback"
 )
 
 type GoCallback struct{}
diff --git a/misc/swig/stdio/Makefile b/misc/swig/stdio/Makefile
index e7d3305..0f23345 100644
--- a/misc/swig/stdio/Makefile
+++ b/misc/swig/stdio/Makefile
@@ -13,5 +13,5 @@ CLEANFILES+=hello
 include ../../../src/Make.pkg
 
 %: install %.go
-	$(GC) $*.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) $*.go
 	$(LD) $(SWIG_RPATH) -o $@ $*.$O
diff --git a/misc/swig/stdio/hello b/misc/swig/stdio/hello
deleted file mode 100755
index 10c5563..0000000
Binary files a/misc/swig/stdio/hello and /dev/null differ
diff --git a/misc/vim/ftdetect/gofiletype.vim b/misc/vim/ftdetect/gofiletype.vim
index f03a1d8..096d052 100644
--- a/misc/vim/ftdetect/gofiletype.vim
+++ b/misc/vim/ftdetect/gofiletype.vim
@@ -1 +1 @@
-au BufReadPre,BufNewFile *.go set filetype=go fileencoding=utf-8 fileencodings=utf-8
+au BufRead,BufNewFile *.go set filetype=go fileencoding=utf-8 fileencodings=utf-8
diff --git a/misc/vim/ftplugin/go/fmt.vim b/misc/vim/ftplugin/go/fmt.vim
index a299dfc..0ee44cd 100644
--- a/misc/vim/ftplugin/go/fmt.vim
+++ b/misc/vim/ftplugin/go/fmt.vim
@@ -17,12 +17,26 @@ command! -buffer Fmt call s:GoFormat()
 
 function! s:GoFormat()
     let view = winsaveview()
-    %!gofmt
+    silent %!gofmt
     if v:shell_error
-        %| " output errors returned by gofmt
-           " TODO(dchest): perhaps, errors should go to quickfix
+        let errors = []
+        for line in getline(1, line('$'))
+            let tokens = matchlist(line, '^\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)')
+            if !empty(tokens)
+                call add(errors, {"filename": @%,
+                                 \"lnum":     tokens[2],
+                                 \"col":      tokens[3],
+                                 \"text":     tokens[4]})
+            endif
+        endfor
+        if empty(errors)
+            % | " Couldn't detect gofmt error format, output errors
+        endif
         undo
-	echohl Error | echomsg "Gofmt returned error" | echohl None
+        if !empty(errors)
+            call setloclist(0, errors, 'r')
+        endif
+        echohl Error | echomsg "Gofmt returned error" | echohl None
     endif
     call winrestview(view)
 endfunction
diff --git a/misc/vim/syntax/go.vim b/misc/vim/syntax/go.vim
index 26d7def..1ce6cb2 100644
--- a/misc/vim/syntax/go.vim
+++ b/misc/vim/syntax/go.vim
@@ -18,7 +18,7 @@
 "     Highlights white space around the communications operator that don't follow
 "     the standard style.
 "   - go_highlight_extra_types
-"     Highlights commonly used library types (os.Error, etc.).
+"     Highlights commonly used library types (io.Reader, etc.).
 "   - go_highlight_space_tab_error
 "     Highlights instances of tabs following spaces.
 "   - go_highlight_trailing_whitespace_error
@@ -67,8 +67,8 @@ hi def link     goLabel             Label
 hi def link     goRepeat            Repeat
 
 " Predefined types
-syn keyword     goType              chan map bool string
-syn keyword     goSignedInts        int int8 int16 int32 int64
+syn keyword     goType              chan map bool string error
+syn keyword     goSignedInts        int int8 int16 int32 int64 rune
 syn keyword     goUnsignedInts      byte uint uint8 uint16 uint32 uint64 uintptr
 syn keyword     goFloats            float32 float64
 syn keyword     goComplexes         complex64 complex128
@@ -85,7 +85,7 @@ syn match       goType              /\<func\>/
 syn match       goDeclaration       /^func\>/
 
 " Predefined functions and values
-syn keyword     goBuiltins          append cap close complex copy imag len
+syn keyword     goBuiltins          append cap close complex copy delete imag len
 syn keyword     goBuiltins          make new panic print println real recover
 syn keyword     goConstants         iota true false nil
 
@@ -180,7 +180,6 @@ endif
 if go_highlight_extra_types != 0
   syn match goExtraType /\<bytes\.\(Buffer\)\>/
   syn match goExtraType /\<io\.\(Reader\|Writer\|ReadWriter\|ReadWriteCloser\)\>/
-  syn match goExtraType /\<\(os\.Error\)\>/
   syn match goExtraType /\<reflect\.\(Kind\|Type\|Value\)\>/
   syn match goExtraType /\<unsafe\.Pointer\>/
 endif
diff --git a/misc/windows/LICENSE b/misc/windows/LICENSE
new file mode 100644
index 0000000..b2b0be6
Binary files /dev/null and b/misc/windows/LICENSE differ
diff --git a/misc/windows/README b/misc/windows/README
new file mode 100644
index 0000000..c345d45
--- /dev/null
+++ b/misc/windows/README
@@ -0,0 +1,20 @@
+package.bash packages the Go toolchain for Windows in 
+zip and installer (msi) format. 
+
+Dependencies
+============
+- WiX Installer XML (WiX) toolset: http://wix.sourceforge.net/
+- 7Zip command-line: http://www.7-zip.org/download.html
+- MinGW/Msys tools
+
+Unzip and place 7za.exe in msys' bin directory.
+Add the WiX bin directory to PATH.
+
+Packaging
+=========
+- have a go tree at $GOROOT
+- make sure $GOBIN=$GOROOT\bin or is empty
+- make sure $GOARCH=386 or $GOARCH=amd64
+- select appropriate version "hg up -r ..."
+- build go "cd $GOROOT/src; ./all.bash"
+- create Windows packages "cd $GOROOT/misc/windows; ./package.bash"
diff --git a/misc/windows/godocserver.bat b/misc/windows/godocserver.bat
new file mode 100644
index 0000000..70b35de
--- /dev/null
+++ b/misc/windows/godocserver.bat
@@ -0,0 +1,14 @@
+ at echo off
+setlocal
+for /f "delims=" %%i in ('cd') do set cwd=%%i
+
+if exist bin\godoc.exe goto ok
+echo Unable to find the godoc executable
+echo This batch file must run from the root Go folder
+pause
+exit
+
+:ok
+start bin\godoc -http=localhost:6060 -goroot="%cwd%"
+start http://localhost:6060
+endlocal
diff --git a/misc/windows/goenv.bat b/misc/windows/goenv.bat
new file mode 100644
index 0000000..e6ae164
--- /dev/null
+++ b/misc/windows/goenv.bat
@@ -0,0 +1,29 @@
+ at echo off
+setlocal
+for /f %%i in ("%0") do set cwd=%%~dpi
+cd /d %cwd%
+
+:: sanity checks
+if exist "%cwd%"\bin\6g.exe (
+set GOARCH=amd64
+goto ok
+)
+
+if exist "%cwd%"\bin\8g.exe (
+set GOARCH=386
+goto ok
+)
+
+echo Unable to find the Go compiler
+echo This batch file must run from the root Go folder
+pause
+exit
+
+:ok
+set GOROOT=%cwd%
+set GOBIN=%GOROOT%\bin
+set PATH=%GOBIN%;%PATH%
+
+ at CMD /F:ON
+endlocal
+
diff --git a/misc/windows/installer.wxs b/misc/windows/installer.wxs
new file mode 100644
index 0000000..e15bfcf
--- /dev/null
+++ b/misc/windows/installer.wxs
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+<!--
+# Copyright 2010 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.
+-->
+
+<?if $(var.Arch) = 386 ?>
+  <?define SYSFOLDER=SystemFolder ?>
+  <?define Win64=no ?>
+<?else?>
+  <?define SYSFOLDER=System64Folder ?>
+  <?define Win64=yes ?>
+<?endif?>
+
+<Product
+    Id="FF5B30B2-08C2-11E1-85A2-6ACA4824019B"
+    Name="The Go Programming Language $(var.Arch) $(var.Version)"
+    Language="1033"
+    Version="0.0.0.0"
+    Manufacturer="http://golang.org"
+    UpgradeCode="1C3114EA-08C3-11E1-9095-7FCA4824019B" >
+    <!-- Version="$(var.Version)" TODO: Version requires X.X.X.X format -->
+
+<Package
+    Id='*' Keywords='Installer'
+    Description="The Go Programming Language Installer"
+    Comments="The Go programming language is an open source project to make programmers more productive."
+    InstallerVersion="300"
+    Compressed="yes"
+    Manufacturer="http://golang.org"
+    InstallScope="perMachine"
+    Languages="1033" />
+     <!--    Platform="x86 or x64" -->
+<!--
+<Upgrade Id="">
+    <UpgradeVersion
+        IncludeMaximum="yes"
+        IncludeMinimum="yes"
+        Language="1033"
+        Maximum=""
+        Minimum=""
+        Property="" />
+</Upgrade>
+-->
+<Media Id='1' Cabinet="go.cab" EmbedCab="yes" CompressionLevel="high" />
+<Condition Message="Windows 2000 or greater required."> VersionNT >= 500</Condition>
+<SetDirectory Id="INSTALLDIRROOT" Value="C:\"/>
+
+<CustomAction
+    Id="SetApplicationRootDirectory"
+    Property="ARPINSTALLLOCATION"
+    Value="[INSTALLDIR]" />
+
+<!-- Define the directory structure and environment variables -->
+<Directory Id="TARGETDIR" Name="SourceDir">
+  <Directory Id="INSTALLDIRROOT">
+    <Directory Id="INSTALLDIR" Name="Go"/>
+  </Directory>
+  <Directory Id="ProgramMenuFolder">
+    <Directory Id="GoProgramShortcutsDir" Name="Go Programming"/>
+  </Directory>
+  <Directory Id="DesktopFolder" Name="Desktop"/>
+</Directory>
+
+<!-- Programs Menu & Desktop Shortcuts -->
+<DirectoryRef Id="GoProgramShortcutsDir">
+  <Component Id="Component_GoShortCuts" Guid="f5fbfb5e-6c5c-423b-9298-21b0e3c98f4b">
+    <Shortcut
+        Id="GoEnvStartMenuShortcut"
+        Name="GoEnv"
+        Description="Sets the Go environment and spawns a shell window"
+        Target="[INSTALLDIR]goenv.bat" />
+    <Shortcut
+        Id="GoEnvDesktopShortcut"
+        Directory="DesktopFolder"
+        Name="GoEnv"
+        Description="Sets the Go environment and spawns a shell window"
+        Target="[INSTALLDIR]goenv.bat" />
+    <Shortcut
+        Id="GoDocServerStartMenuShortcut"
+        Name="GoDocServer"
+        Description="Starts the godoc server on localhost:6060"
+        Target="[INSTALLDIR]godocserver.bat" />
+    <Shortcut
+        Id="GoDocServerDesktopShortcut"
+        Directory="DesktopFolder"
+        Name="GoDocServer"
+        Description="Starts the godoc server on localhost:6060"
+        Target="[INSTALLDIR]godocserver.bat" />
+    <Shortcut
+        Id="UninstallShortcut"
+        Name="Uninstall Go"
+        Description="Uninstalls Go and all of its components"
+        Target="[$(var.SYSFOLDER)]msiexec.exe"
+        Arguments="/x [ProductCode]" />
+    <RemoveFolder
+        Id="GoProgramShortcutsDir"
+        On="uninstall" />
+    <RegistryValue
+        Root="HKCU"
+        Key="Software\Microsoft\TheGoProgrammingLanguage"
+        Name="installed"
+        Type="integer"
+        Value="1"
+        KeyPath="yes" />
+  </Component>
+</DirectoryRef>
+
+<!-- Components -->
+<DirectoryRef Id="INSTALLDIR">
+  <Component Id="Component_GoDocServerBAT" Guid="c40ea60a-4290-4a91-864d-e1d8eb5cf693">
+    <File
+        Id="FILE_GoDocServerBat"
+        Source="godocserver.bat"
+        KeyPath="yes" />
+  </Component>
+  <Component Id="Component_GoEnvBAT" Guid="ee4587d3-fba3-47f9-b45e-ec9ca9c8a9c3">
+    <File
+        Id="FILE_GoEnvBat"
+        Source="goenv.bat"
+        KeyPath="yes" />
+  </Component>
+</DirectoryRef>
+
+<!-- Install the files -->
+<Feature
+    Id="GoTools"
+    Title="Go"
+    Level="1">
+
+      <ComponentGroupRef Id="AppFiles" />
+      <ComponentRef Id="Component_GoDocServerBAT" />
+      <ComponentRef Id="Component_GoEnvBAT" />
+      <ComponentRef Id="Component_GoShortCuts" />
+</Feature>
+
+<!-- Update the environment -->
+<InstallExecuteSequence>
+  <Custom
+    Action="SetApplicationRootDirectory"
+    Before="InstallFinalize" />
+</InstallExecuteSequence>
+
+<!-- Include the user interface -->
+<WixVariable Id="WixUILicenseRtf" Value="LICENSE" />
+<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
+<UIRef Id="WixUI_InstallDir" />
+
+</Product>
+</Wix>
diff --git a/misc/windows/package.bash b/misc/windows/package.bash
new file mode 100755
index 0000000..995e47d
--- /dev/null
+++ b/misc/windows/package.bash
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+# Copyright 2011 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
+
+PROGS="
+	candle
+	light
+	heat
+"
+
+echo "%%%%% Checking for WiX executables %%%%%" 1>&2
+for i in $PROGS; do
+	if ! which -a $1 >/dev/null; then
+		echo "Cannot find '$i' on search path." 1>$2
+		exit 1
+	fi
+done
+
+echo "%%%%% Checking the packager's path %%%%%" 1>&2
+if ! test -f ../../src/env.bash; then
+	echo "package.bash must be run from $GOROOT/misc/windows" 1>&2
+fi
+
+echo "%%%%% Setting the go package version info %%%%%" 1>&2
+ver="$(bash ../../src/version.bash | sed 's/ .*//')"
+
+rm -rf go
+mkdir go
+
+echo "%%%%% Cloning the go tree %%%%%" 1>&2
+hg clone -r $(hg id -n | sed 's/+//') $(hg root) go
+
+rm -rf ./go/.hg ./go/.hgignore ./go/.hgtags
+
+echo "%%%%% Copying pkg, bin and src/pkg/runtime/z* %%%%%" 1>&2
+cp -a ../../pkg go/pkg
+cp -a ../../bin go/bin
+cp ../../src/pkg/runtime/z*.c go/src/pkg/runtime/
+cp ../../src/pkg/runtime/z*.go go/src/pkg/runtime/
+cp ../../src/pkg/runtime/z*.h go/src/pkg/runtime/
+
+echo "%%%%% Starting zip packaging %%%%%" 1>&2
+7za a -tzip -mx=9 gowin$GOARCH"_"$ver.zip "go/" >/dev/null
+
+echo "%%%%% Starting Go directory file harvesting %%%%%" 1>&2
+heat dir go -nologo -cg AppFiles -gg -g1 -srd -sfrag -template fragment -dr INSTALLDIR -var var.SourceDir -out AppFiles.wxs
+
+echo "%%%%% Starting installer packaging %%%%%" 1>&2
+candle -nologo -dVersion=$ver -dArch=$GOARCH -dSourceDir=go installer.wxs AppFiles.wxs
+light -nologo -ext WixUIExtension -ext WixUtilExtension installer.wixobj AppFiles.wixobj -o gowin$GOARCH"_"$ver.msi
+
+rm -f *.wixobj AppFiles.wxs *.wixpdb
+
diff --git a/misc/xcode/go.xclangspec b/misc/xcode/go.xclangspec
index e515564..4a8c94d 100644
--- a/misc/xcode/go.xclangspec
+++ b/misc/xcode/go.xclangspec
@@ -273,8 +273,8 @@
 			StartChars = "BMTF!?";
 			Match = (
 				// Go-specific markers
-				"^\(BUG.*$\)$",			// inlude "BUG" in the markers list
-				"^\(TODO.*$\)$",		// inlude "TODO" in the markers list
+				"^\(BUG.*$\)$",			// include "BUG" in the markers list
+				"^\(TODO.*$\)$",		// include "TODO" in the markers list
 				// inherited markers
 				"^MARK:[ \t]+\(.*\)$",
 				"^\(TODO:[ \t]+.*\)$",		// include "TODO: " in the markers list
diff --git a/src/Make.cmd b/src/Make.cmd
index 27c6a2e..d663edb 100644
--- a/src/Make.cmd
+++ b/src/Make.cmd
@@ -20,7 +20,7 @@ $(TARG): _go_.$O
 	$(LD) $(LDIMPORTS) -o $@ _go_.$O
 
 _go_.$O: $(GOFILES) $(PREREQ)
-	$(GC) $(GCIMPORTS) -o $@ $(GOFILES)
+	$(GC) $(GCFLAGS) $(GCIMPORTS) -o $@ $(GOFILES)
 
 install: $(TARGDIR)/$(TARG)
 
@@ -44,7 +44,7 @@ _test/main.a: _gotest_.$O
 	gopack grc $@ _gotest_.$O
 
 _gotest_.$O: $(GOFILES) $(GOTESTFILES)
-	$(GC) $(GCIMPORTS) -o $@ $(GOFILES) $(GOTESTFILES)
+	$(GC) $(GCFLAGS) $(GCIMPORTS) -o $@ $(GOFILES) $(GOTESTFILES)
 
 importpath:
 	echo main
diff --git a/src/Make.inc b/src/Make.inc
index c770b76..7b4ccd0 100644
--- a/src/Make.inc
+++ b/src/Make.inc
@@ -33,6 +33,7 @@ GOOS_LIST=\
 	darwin\
 	freebsd\
 	linux\
+	netbsd\
 	openbsd\
 	plan9\
 	windows\
@@ -138,6 +139,9 @@ endif
 ifeq ($(GOOS),openbsd)  # ... and not on OpenBSD
 CGO_ENABLED:=0
 endif
+ifeq ($(GOOS),netbsd)  # ... and not on NetBSD
+CGO_ENABLED:=0
+endif
 endif
 
 # Make environment more standard.
diff --git a/src/Make.pkg b/src/Make.pkg
index ad7d10b..4a61cf9 100644
--- a/src/Make.pkg
+++ b/src/Make.pkg
@@ -65,7 +65,7 @@ test:
 	gotest
 
 testshort:
-	gotest -test.short -test.timeout=120
+	gotest -test.short -test.timeout=2m
 
 bench:
 	gotest -test.bench=. -test.run="Do not run tests"
@@ -83,10 +83,10 @@ $(TARGDIR)/$(TARG).a: _obj/$(TARG).a
 	cp _obj/$(TARG).a "$@"
 
 _go_.$O: $(GOFILES) $(PREREQ)
-	$(GC) $(GCIMPORTS) -p $(TARG) -o $@ $(GOFILES)
+	$(GC) $(GCFLAGS) $(GCIMPORTS) -p $(TARG) -o $@ $(GOFILES)
 
 _gotest_.$O: $(GOFILES) $(GOTESTFILES) $(PREREQ)
-	$(GC) $(GCIMPORTS) -p $(TARG) -o $@ $(GOFILES) $(GOTESTFILES)
+	$(GC) $(GCFLAGS) $(GCIMPORTS) -p $(TARG) -o $@ $(GOFILES) $(GOTESTFILES)
 
 _obj/$(TARG).a: _go_.$O $(OFILES)
 	@mkdir -p _obj/$(dir)
@@ -149,10 +149,10 @@ endif
 
 # Compile rules for gcc source files.
 %.o: %.c
-	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $(_CGO_CFLAGS) $*.c
+	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ -c -I_obj $(CGO_CFLAGS) $(_CGO_CFLAGS) $*.c
 
 %.o: _obj/%.c
-	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -I . -g -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $(_CGO_CFLAGS) $^
+	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -I . -g -fPIC -O2 -o $@ -c -I_obj $(CGO_CFLAGS) $(_CGO_CFLAGS) $^
 
 # To find out which symbols are needed from external libraries
 # and which libraries are needed, we build a simple a.out that
@@ -162,7 +162,7 @@ endif
 # After main we have to define all the symbols that will be provided
 # by Go code.  That's crosscall2 and any exported symbols.
 
-_cgo1_.o: _cgo_main.o $(CGO_OFILES)
+_cgo1_.o: _cgo_main.o $(CGO_OFILES) $(CGO_DEPS)
 	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -fPIC -O2 -o $@ $^ $(CGO_LDFLAGS) $(_CGO_LDFLAGS)
 
 _obj/_cgo_import.c: _cgo1_.o
@@ -245,5 +245,5 @@ endif
 %.$O: _obj/%.c $(HFILES)
 	$(CC) $(CFLAGS) -I . -o "$@" _obj/$*.c
 
-%.$O: %.s
-	$(AS) $*.s
+%.$O: %.s $(HFILES)
+	$(AS) $(AFLAGS) $*.s
diff --git a/src/buildinfo.sh b/src/buildinfo.sh
new file mode 100644
index 0000000..4725b39
--- /dev/null
+++ b/src/buildinfo.sh
@@ -0,0 +1,40 @@
+# Copyright 2011 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 file is included by shell scripts that need to know the
+# full list of architectures, operating systems, and combinations
+# that Go runs on.
+
+GOARCHES="
+	386
+	amd64
+	arm
+"
+
+GOOSES="
+	darwin
+	freebsd
+	linux
+	netbsd
+	openbsd
+	plan9
+	windows
+"
+
+GOOSARCHES="
+	darwin_386
+	darwin_amd64
+	freebsd_386
+	freebsd_amd64
+	linux_386
+	linux_amd64
+	linux_arm
+	netbsd_386
+	netbsd_amd64
+	openbsd_386
+	openbsd_amd64
+	plan9_386
+	windows_386
+	windows_amd64
+"
diff --git a/src/buildscript.sh b/src/buildscript.sh
new file mode 100755
index 0000000..1afdb69
--- /dev/null
+++ b/src/buildscript.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Copyright 2011 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.
+
+. ./buildinfo.sh
+
+for sys in $GOOSARCHES
+do
+	export GOOS=$(echo $sys | sed 's/_.*//')
+	export GOARCH=$(echo $sys | sed 's/.*_//')
+	targ=buildscript/${GOOS}_$GOARCH.sh
+	rm -f $targ
+
+	(echo '#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS='$GOOS'
+export GOARCH='$GOARCH'
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+'
+	# Save script printed by go install but make shell safe
+	# by quoting variable expansions.  On Windows, rewrite
+	# \ paths into / paths.  This avoids the \ being interpreted
+	# as a shell escape but also makes sure that we generate the
+	# same scripts on Unix and Windows systems.
+	go install -a -n -t cmd_go_bootstrap cmd/go | sed '
+		s/\$GOBIN/"$GOBIN"/g
+		s/\$GOROOT/"$GOROOT"/g
+		s/\$WORK/"$WORK"/g
+		s;"\$GOBIN"/go;&_bootstrap;g
+		s;\\;/;g
+	'
+	)>$targ
+	chmod +x $targ
+done
diff --git a/src/buildscript/darwin_386.sh b/src/buildscript/darwin_386.sh
new file mode 100755
index 0000000..baa3fd6
--- /dev/null
+++ b/src/buildscript/darwin_386.sh
@@ -0,0 +1,498 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=darwin
+export GOARCH=386
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+8g -o "$WORK"/runtime/_obj/_go_.8 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_386.go ./zgoos_darwin.go ./zruntime_defs_darwin_386.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_386.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_darwin_386.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_darwin.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_darwin.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_darwin_386.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/alg.8 -DGOOS_darwin -DGOARCH_386 ./alg.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/atomic_386.8 -DGOOS_darwin -DGOARCH_386 ./atomic_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/cgocall.8 -DGOOS_darwin -DGOARCH_386 ./cgocall.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/chan.8 -DGOOS_darwin -DGOARCH_386 ./chan.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/closure_386.8 -DGOOS_darwin -DGOARCH_386 ./closure_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/complex.8 -DGOOS_darwin -DGOARCH_386 ./complex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/cpuprof.8 -DGOOS_darwin -DGOARCH_386 ./cpuprof.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/float.8 -DGOOS_darwin -DGOARCH_386 ./float.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/hashmap.8 -DGOOS_darwin -DGOARCH_386 ./hashmap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/iface.8 -DGOOS_darwin -DGOARCH_386 ./iface.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/lock_sema.8 -DGOOS_darwin -DGOARCH_386 ./lock_sema.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/mcache.8 -DGOOS_darwin -DGOARCH_386 ./mcache.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/mcentral.8 -DGOOS_darwin -DGOARCH_386 ./mcentral.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/mem_darwin.8 -DGOOS_darwin -DGOARCH_386 ./mem_darwin.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/mfinal.8 -DGOOS_darwin -DGOARCH_386 ./mfinal.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/mfixalloc.8 -DGOOS_darwin -DGOARCH_386 ./mfixalloc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/mgc0.8 -DGOOS_darwin -DGOARCH_386 ./mgc0.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/mheap.8 -DGOOS_darwin -DGOARCH_386 ./mheap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/msize.8 -DGOOS_darwin -DGOARCH_386 ./msize.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/print.8 -DGOOS_darwin -DGOARCH_386 ./print.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/proc.8 -DGOOS_darwin -DGOARCH_386 ./proc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/rune.8 -DGOOS_darwin -DGOARCH_386 ./rune.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/runtime.8 -DGOOS_darwin -DGOARCH_386 ./runtime.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/signal_darwin_386.8 -DGOOS_darwin -DGOARCH_386 ./signal_darwin_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/slice.8 -DGOOS_darwin -DGOARCH_386 ./slice.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/symtab.8 -DGOOS_darwin -DGOARCH_386 ./symtab.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/thread_darwin.8 -DGOOS_darwin -DGOARCH_386 ./thread_darwin.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/traceback_x86.8 -DGOOS_darwin -DGOARCH_386 ./traceback_x86.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/vlrt_386.8 -DGOOS_darwin -DGOARCH_386 ./vlrt_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/zmalloc_386.8 -DGOOS_darwin -DGOARCH_386 ./zmalloc_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/zmprof_386.8 -DGOOS_darwin -DGOARCH_386 ./zmprof_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/zruntime1_386.8 -DGOOS_darwin -DGOARCH_386 ./zruntime1_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/zsema_386.8 -DGOOS_darwin -DGOARCH_386 ./zsema_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/zsigqueue_386.8 -DGOOS_darwin -DGOARCH_386 ./zsigqueue_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/zstring_386.8 -DGOOS_darwin -DGOARCH_386 ./zstring_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_386 -o "$WORK"/runtime/_obj/ztime_386.8 -DGOOS_darwin -DGOARCH_386 ./ztime_386.c
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_386.8 -DGOOS_darwin -DGOARCH_386 ./asm_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_386.8 -DGOOS_darwin -DGOARCH_386 ./memmove_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_darwin_386.8 -DGOOS_darwin -DGOARCH_386 ./rt0_darwin_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_darwin_386.8 -DGOOS_darwin -DGOARCH_386 ./sys_darwin_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/vlop_386.8 -DGOOS_darwin -DGOARCH_386 ./vlop_386.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.8 "$WORK"/runtime/_obj/alg.8 "$WORK"/runtime/_obj/atomic_386.8 "$WORK"/runtime/_obj/cgocall.8 "$WORK"/runtime/_obj/chan.8 "$WORK"/runtime/_obj/closure_386.8 "$WORK"/runtime/_obj/complex.8 "$WORK"/runtime/_obj/cpuprof.8 "$WORK"/runtime/_obj/float.8 "$WORK"/runtime/_obj/hashmap.8 "$WORK"/runtime/_obj/iface.8 "$WORK"/runtime/_obj/lock_sema.8 "$WORK"/runtime/_obj/mcache.8 "$WORK"/runtime/_obj/mcentral.8 "$WORK"/runtime/_obj/mem_darwin.8 "$WORK"/runtime/_obj/mfinal.8 "$WORK"/runtime/_obj/mfixalloc.8 "$WORK"/runtime/_obj/mgc0.8 "$WORK"/runtime/_obj/mheap.8 "$WORK"/runtime/_obj/msize.8 "$WORK"/runtime/_obj/print.8 "$WORK"/runtime/_obj/proc.8 "$WORK"/runtime/_obj/rune.8 "$WORK"/runtime/_obj/runtime.8 "$WORK"/runtime/_obj/signal_darwin_386.8 "$WORK"/runtime/_obj/slice.8 "$WORK"/runtime/_obj/symtab.8 "$WORK"/runtime/_obj/thread_darwin.8 "$WORK"/runtime/_obj/traceback_x86.8 "$WORK"/runtime/_obj/vlrt_386.8 "$WORK"/runtime/_obj/zmalloc_386.8 "$WORK"/runtime/_obj/zmprof_386.8 "$WORK"/runtime/_obj/zruntime1_386.8 "$WORK"/runtime/_obj/zsema_386.8 "$WORK"/runtime/_obj/zsigqueue_386.8 "$WORK"/runtime/_obj/zstring_386.8 "$WORK"/runtime/_obj/ztime_386.8 "$WORK"/runtime/_obj/asm_386.8 "$WORK"/runtime/_obj/memmove_386.8 "$WORK"/runtime/_obj/rt0_darwin_386.8 "$WORK"/runtime/_obj/sys_darwin_386.8 "$WORK"/runtime/_obj/vlop_386.8
+mkdir -p "$GOROOT"/pkg/darwin_386/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/darwin_386/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+8g -o "$WORK"/errors/_obj/_go_.8 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.8
+cp "$WORK"/errors.a "$GOROOT"/pkg/darwin_386/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+8g -o "$WORK"/sync/atomic/_obj/_go_.8 -p sync/atomic -I "$WORK" ./doc.go
+8a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_386.8 -DGOOS_darwin -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.8 "$WORK"/sync/atomic/_obj/asm_386.8
+mkdir -p "$GOROOT"/pkg/darwin_386/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/darwin_386/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+8g -o "$WORK"/sync/_obj/_go_.8 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.8
+cp "$WORK"/sync.a "$GOROOT"/pkg/darwin_386/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+8g -o "$WORK"/io/_obj/_go_.8 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.8
+cp "$WORK"/io.a "$GOROOT"/pkg/darwin_386/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+8g -o "$WORK"/unicode/_obj/_go_.8 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.8
+cp "$WORK"/unicode.a "$GOROOT"/pkg/darwin_386/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+8g -o "$WORK"/unicode/utf8/_obj/_go_.8 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/darwin_386/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+8g -o "$WORK"/bytes/_obj/_go_.8 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+8a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_386.8 -DGOOS_darwin -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.8 "$WORK"/bytes/_obj/asm_386.8
+cp "$WORK"/bytes.a "$GOROOT"/pkg/darwin_386/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+8g -o "$WORK"/math/_obj/_go_.8 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_386.8 -DGOOS_darwin -DGOARCH_386 ./abs_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_386.8 -DGOOS_darwin -DGOARCH_386 ./asin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_386.8 -DGOOS_darwin -DGOARCH_386 ./atan2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_386.8 -DGOOS_darwin -DGOARCH_386 ./atan_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_386.8 -DGOOS_darwin -DGOARCH_386 ./dim_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_386.8 -DGOOS_darwin -DGOARCH_386 ./exp2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_386.8 -DGOOS_darwin -DGOARCH_386 ./exp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_386.8 -DGOOS_darwin -DGOARCH_386 ./expm1_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_386.8 -DGOOS_darwin -DGOARCH_386 ./floor_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_386.8 -DGOOS_darwin -DGOARCH_386 ./frexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_386.8 -DGOOS_darwin -DGOARCH_386 ./hypot_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_386.8 -DGOOS_darwin -DGOARCH_386 ./ldexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_386.8 -DGOOS_darwin -DGOARCH_386 ./log10_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_386.8 -DGOOS_darwin -DGOARCH_386 ./log1p_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_386.8 -DGOOS_darwin -DGOARCH_386 ./log_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_386.8 -DGOOS_darwin -DGOARCH_386 ./mod_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_386.8 -DGOOS_darwin -DGOARCH_386 ./modf_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_386.8 -DGOOS_darwin -DGOARCH_386 ./remainder_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_386.8 -DGOOS_darwin -DGOARCH_386 ./sin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_386.8 -DGOOS_darwin -DGOARCH_386 ./sincos_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_386.8 -DGOOS_darwin -DGOARCH_386 ./sqrt_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_386.8 -DGOOS_darwin -DGOARCH_386 ./tan_386.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.8 "$WORK"/math/_obj/abs_386.8 "$WORK"/math/_obj/asin_386.8 "$WORK"/math/_obj/atan2_386.8 "$WORK"/math/_obj/atan_386.8 "$WORK"/math/_obj/dim_386.8 "$WORK"/math/_obj/exp2_386.8 "$WORK"/math/_obj/exp_386.8 "$WORK"/math/_obj/expm1_386.8 "$WORK"/math/_obj/floor_386.8 "$WORK"/math/_obj/frexp_386.8 "$WORK"/math/_obj/hypot_386.8 "$WORK"/math/_obj/ldexp_386.8 "$WORK"/math/_obj/log10_386.8 "$WORK"/math/_obj/log1p_386.8 "$WORK"/math/_obj/log_386.8 "$WORK"/math/_obj/mod_386.8 "$WORK"/math/_obj/modf_386.8 "$WORK"/math/_obj/remainder_386.8 "$WORK"/math/_obj/sin_386.8 "$WORK"/math/_obj/sincos_386.8 "$WORK"/math/_obj/sqrt_386.8 "$WORK"/math/_obj/tan_386.8
+cp "$WORK"/math.a "$GOROOT"/pkg/darwin_386/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+8g -o "$WORK"/sort/_obj/_go_.8 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.8
+cp "$WORK"/sort.a "$GOROOT"/pkg/darwin_386/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+8g -o "$WORK"/container/heap/_obj/_go_.8 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/darwin_386/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+8g -o "$WORK"/strings/_obj/_go_.8 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.8
+cp "$WORK"/strings.a "$GOROOT"/pkg/darwin_386/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+8g -o "$WORK"/strconv/_obj/_go_.8 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.8
+cp "$WORK"/strconv.a "$GOROOT"/pkg/darwin_386/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+8g -o "$WORK"/encoding/base64/_obj/_go_.8 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/darwin_386/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_darwin.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_darwin.go ./syscall_darwin_386.go ./syscall_unix.go ./zerrors_darwin_386.go ./zsyscall_darwin_386.go ./zsysnum_darwin_386.go ./ztypes_darwin_386.go
+8a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_darwin_386.8 -DGOOS_darwin -DGOARCH_386 ./asm_darwin_386.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.8 "$WORK"/syscall/_obj/asm_darwin_386.8
+cp "$WORK"/syscall.a "$GOROOT"/pkg/darwin_386/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+8g -o "$WORK"/time/_obj/_go_.8 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.8
+cp "$WORK"/time.a "$GOROOT"/pkg/darwin_386/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+8g -o "$WORK"/os/_obj/_go_.8 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_darwin.go ./sys_bsd.go ./time.go ./types.go ./zsignal_darwin_386.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.8
+cp "$WORK"/os.a "$GOROOT"/pkg/darwin_386/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+8g -o "$WORK"/reflect/_obj/_go_.8 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.8
+cp "$WORK"/reflect.a "$GOROOT"/pkg/darwin_386/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+8g -o "$WORK"/fmt/_obj/_go_.8 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.8
+cp "$WORK"/fmt.a "$GOROOT"/pkg/darwin_386/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+8g -o "$WORK"/unicode/utf16/_obj/_go_.8 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.8
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/darwin_386/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+8g -o "$WORK"/encoding/json/_obj/_go_.8 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.8
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/darwin_386/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+8g -o "$WORK"/flag/_obj/_go_.8 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.8
+cp "$WORK"/flag.a "$GOROOT"/pkg/darwin_386/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+8g -o "$WORK"/bufio/_obj/_go_.8 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.8
+cp "$WORK"/bufio.a "$GOROOT"/pkg/darwin_386/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+8g -o "$WORK"/encoding/gob/_obj/_go_.8 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.8
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/darwin_386/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+8g -o "$WORK"/go/token/_obj/_go_.8 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/darwin_386/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+8g -o "$WORK"/path/filepath/_obj/_go_.8 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/darwin_386/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+8g -o "$WORK"/go/scanner/_obj/_go_.8 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.8
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/darwin_386/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+8g -o "$WORK"/go/ast/_obj/_go_.8 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.8
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/darwin_386/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+8g -o "$WORK"/io/ioutil/_obj/_go_.8 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/darwin_386/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+8g -o "$WORK"/go/parser/_obj/_go_.8 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.8
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/darwin_386/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+8g -o "$WORK"/log/_obj/_go_.8 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.8
+cp "$WORK"/log.a "$GOROOT"/pkg/darwin_386/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+8g -o "$WORK"/path/_obj/_go_.8 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.8
+cp "$WORK"/path.a "$GOROOT"/pkg/darwin_386/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+8g -o "$WORK"/go/build/_obj/_go_.8 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.8
+cp "$WORK"/go/build.a "$GOROOT"/pkg/darwin_386/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+8g -o "$WORK"/os/exec/_obj/_go_.8 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/darwin_386/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+8g -o "$WORK"/regexp/syntax/_obj/_go_.8 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/darwin_386/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+8g -o "$WORK"/regexp/_obj/_go_.8 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.8
+cp "$WORK"/regexp.a "$GOROOT"/pkg/darwin_386/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+8g -o "$WORK"/net/url/_obj/_go_.8 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/darwin_386/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+8g -o "$WORK"/text/template/parse/_obj/_go_.8 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/darwin_386/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+8g -o "$WORK"/text/template/_obj/_go_.8 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/darwin_386/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/darwin_386/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+8g -o "$WORK"/cmd/go/_obj/_go_.8 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.8
+8l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/darwin_amd64.sh b/src/buildscript/darwin_amd64.sh
new file mode 100755
index 0000000..e31d6f9
--- /dev/null
+++ b/src/buildscript/darwin_amd64.sh
@@ -0,0 +1,497 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=darwin
+export GOARCH=amd64
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+6g -o "$WORK"/runtime/_obj/_go_.6 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_amd64.go ./zgoos_darwin.go ./zruntime_defs_darwin_amd64.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_amd64.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_darwin_amd64.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_darwin.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_darwin.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_darwin_amd64.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/alg.6 -DGOOS_darwin -DGOARCH_amd64 ./alg.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/atomic_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./atomic_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/cgocall.6 -DGOOS_darwin -DGOARCH_amd64 ./cgocall.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/chan.6 -DGOOS_darwin -DGOARCH_amd64 ./chan.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/closure_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./closure_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/complex.6 -DGOOS_darwin -DGOARCH_amd64 ./complex.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/cpuprof.6 -DGOOS_darwin -DGOARCH_amd64 ./cpuprof.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/float.6 -DGOOS_darwin -DGOARCH_amd64 ./float.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/hashmap.6 -DGOOS_darwin -DGOARCH_amd64 ./hashmap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/iface.6 -DGOOS_darwin -DGOARCH_amd64 ./iface.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/lock_sema.6 -DGOOS_darwin -DGOARCH_amd64 ./lock_sema.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/mcache.6 -DGOOS_darwin -DGOARCH_amd64 ./mcache.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/mcentral.6 -DGOOS_darwin -DGOARCH_amd64 ./mcentral.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/mem_darwin.6 -DGOOS_darwin -DGOARCH_amd64 ./mem_darwin.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/mfinal.6 -DGOOS_darwin -DGOARCH_amd64 ./mfinal.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/mfixalloc.6 -DGOOS_darwin -DGOARCH_amd64 ./mfixalloc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/mgc0.6 -DGOOS_darwin -DGOARCH_amd64 ./mgc0.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/mheap.6 -DGOOS_darwin -DGOARCH_amd64 ./mheap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/msize.6 -DGOOS_darwin -DGOARCH_amd64 ./msize.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/print.6 -DGOOS_darwin -DGOARCH_amd64 ./print.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/proc.6 -DGOOS_darwin -DGOARCH_amd64 ./proc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/rune.6 -DGOOS_darwin -DGOARCH_amd64 ./rune.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/runtime.6 -DGOOS_darwin -DGOARCH_amd64 ./runtime.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/signal_darwin_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./signal_darwin_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/slice.6 -DGOOS_darwin -DGOARCH_amd64 ./slice.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/symtab.6 -DGOOS_darwin -DGOARCH_amd64 ./symtab.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/thread_darwin.6 -DGOOS_darwin -DGOARCH_amd64 ./thread_darwin.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/traceback_x86.6 -DGOOS_darwin -DGOARCH_amd64 ./traceback_x86.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/zmalloc_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./zmalloc_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/zmprof_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./zmprof_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/zruntime1_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./zruntime1_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/zsema_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./zsema_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/zsigqueue_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./zsigqueue_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/zstring_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./zstring_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/darwin_amd64 -o "$WORK"/runtime/_obj/ztime_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./ztime_amd64.c
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./asm_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./memmove_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_darwin_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./rt0_darwin_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_darwin_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./sys_darwin_amd64.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.6 "$WORK"/runtime/_obj/alg.6 "$WORK"/runtime/_obj/atomic_amd64.6 "$WORK"/runtime/_obj/cgocall.6 "$WORK"/runtime/_obj/chan.6 "$WORK"/runtime/_obj/closure_amd64.6 "$WORK"/runtime/_obj/complex.6 "$WORK"/runtime/_obj/cpuprof.6 "$WORK"/runtime/_obj/float.6 "$WORK"/runtime/_obj/hashmap.6 "$WORK"/runtime/_obj/iface.6 "$WORK"/runtime/_obj/lock_sema.6 "$WORK"/runtime/_obj/mcache.6 "$WORK"/runtime/_obj/mcentral.6 "$WORK"/runtime/_obj/mem_darwin.6 "$WORK"/runtime/_obj/mfinal.6 "$WORK"/runtime/_obj/mfixalloc.6 "$WORK"/runtime/_obj/mgc0.6 "$WORK"/runtime/_obj/mheap.6 "$WORK"/runtime/_obj/msize.6 "$WORK"/runtime/_obj/print.6 "$WORK"/runtime/_obj/proc.6 "$WORK"/runtime/_obj/rune.6 "$WORK"/runtime/_obj/runtime.6 "$WORK"/runtime/_obj/signal_darwin_amd64.6 "$WORK"/runtime/_obj/slice.6 "$WORK"/runtime/_obj/symtab.6 "$WORK"/runtime/_obj/thread_darwin.6 "$WORK"/runtime/_obj/traceback_x86.6 "$WORK"/runtime/_obj/zmalloc_amd64.6 "$WORK"/runtime/_obj/zmprof_amd64.6 "$WORK"/runtime/_obj/zruntime1_amd64.6 "$WORK"/runtime/_obj/zsema_amd64.6 "$WORK"/runtime/_obj/zsigqueue_amd64.6 "$WORK"/runtime/_obj/zstring_amd64.6 "$WORK"/runtime/_obj/ztime_amd64.6 "$WORK"/runtime/_obj/asm_amd64.6 "$WORK"/runtime/_obj/memmove_amd64.6 "$WORK"/runtime/_obj/rt0_darwin_amd64.6 "$WORK"/runtime/_obj/sys_darwin_amd64.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/darwin_amd64/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+6g -o "$WORK"/errors/_obj/_go_.6 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.6
+cp "$WORK"/errors.a "$GOROOT"/pkg/darwin_amd64/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+6g -o "$WORK"/sync/atomic/_obj/_go_.6 -p sync/atomic -I "$WORK" ./doc.go
+6a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.6 "$WORK"/sync/atomic/_obj/asm_amd64.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/darwin_amd64/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+6g -o "$WORK"/sync/_obj/_go_.6 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.6
+cp "$WORK"/sync.a "$GOROOT"/pkg/darwin_amd64/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+6g -o "$WORK"/io/_obj/_go_.6 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.6
+cp "$WORK"/io.a "$GOROOT"/pkg/darwin_amd64/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+6g -o "$WORK"/unicode/_obj/_go_.6 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.6
+cp "$WORK"/unicode.a "$GOROOT"/pkg/darwin_amd64/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+6g -o "$WORK"/unicode/utf8/_obj/_go_.6 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/darwin_amd64/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+6g -o "$WORK"/bytes/_obj/_go_.6 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+6a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.6 "$WORK"/bytes/_obj/asm_amd64.6
+cp "$WORK"/bytes.a "$GOROOT"/pkg/darwin_amd64/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+6g -o "$WORK"/math/_obj/_go_.6 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./abs_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./asin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./atan2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./atan_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./dim_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./exp2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./exp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./expm1_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./floor_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/fltasm_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./fltasm_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./frexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./hypot_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./ldexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./log10_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./log1p_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./log_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./mod_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./modf_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./remainder_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./sin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./sincos_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./sqrt_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./tan_amd64.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.6 "$WORK"/math/_obj/abs_amd64.6 "$WORK"/math/_obj/asin_amd64.6 "$WORK"/math/_obj/atan2_amd64.6 "$WORK"/math/_obj/atan_amd64.6 "$WORK"/math/_obj/dim_amd64.6 "$WORK"/math/_obj/exp2_amd64.6 "$WORK"/math/_obj/exp_amd64.6 "$WORK"/math/_obj/expm1_amd64.6 "$WORK"/math/_obj/floor_amd64.6 "$WORK"/math/_obj/fltasm_amd64.6 "$WORK"/math/_obj/frexp_amd64.6 "$WORK"/math/_obj/hypot_amd64.6 "$WORK"/math/_obj/ldexp_amd64.6 "$WORK"/math/_obj/log10_amd64.6 "$WORK"/math/_obj/log1p_amd64.6 "$WORK"/math/_obj/log_amd64.6 "$WORK"/math/_obj/mod_amd64.6 "$WORK"/math/_obj/modf_amd64.6 "$WORK"/math/_obj/remainder_amd64.6 "$WORK"/math/_obj/sin_amd64.6 "$WORK"/math/_obj/sincos_amd64.6 "$WORK"/math/_obj/sqrt_amd64.6 "$WORK"/math/_obj/tan_amd64.6
+cp "$WORK"/math.a "$GOROOT"/pkg/darwin_amd64/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+6g -o "$WORK"/sort/_obj/_go_.6 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.6
+cp "$WORK"/sort.a "$GOROOT"/pkg/darwin_amd64/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+6g -o "$WORK"/container/heap/_obj/_go_.6 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/darwin_amd64/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+6g -o "$WORK"/strings/_obj/_go_.6 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.6
+cp "$WORK"/strings.a "$GOROOT"/pkg/darwin_amd64/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+6g -o "$WORK"/strconv/_obj/_go_.6 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.6
+cp "$WORK"/strconv.a "$GOROOT"/pkg/darwin_amd64/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+6g -o "$WORK"/encoding/base64/_obj/_go_.6 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/darwin_amd64/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+6g -o "$WORK"/syscall/_obj/_go_.6 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_darwin.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_darwin.go ./syscall_darwin_amd64.go ./syscall_unix.go ./zerrors_darwin_amd64.go ./zsyscall_darwin_amd64.go ./zsysnum_darwin_amd64.go ./ztypes_darwin_amd64.go
+6a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_darwin_amd64.6 -DGOOS_darwin -DGOARCH_amd64 ./asm_darwin_amd64.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.6 "$WORK"/syscall/_obj/asm_darwin_amd64.6
+cp "$WORK"/syscall.a "$GOROOT"/pkg/darwin_amd64/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+6g -o "$WORK"/time/_obj/_go_.6 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.6
+cp "$WORK"/time.a "$GOROOT"/pkg/darwin_amd64/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+6g -o "$WORK"/os/_obj/_go_.6 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_darwin.go ./sys_bsd.go ./time.go ./types.go ./zsignal_darwin_amd64.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.6
+cp "$WORK"/os.a "$GOROOT"/pkg/darwin_amd64/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+6g -o "$WORK"/reflect/_obj/_go_.6 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.6
+cp "$WORK"/reflect.a "$GOROOT"/pkg/darwin_amd64/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+6g -o "$WORK"/fmt/_obj/_go_.6 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.6
+cp "$WORK"/fmt.a "$GOROOT"/pkg/darwin_amd64/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+6g -o "$WORK"/unicode/utf16/_obj/_go_.6 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.6
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/darwin_amd64/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+6g -o "$WORK"/encoding/json/_obj/_go_.6 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.6
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/darwin_amd64/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+6g -o "$WORK"/flag/_obj/_go_.6 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.6
+cp "$WORK"/flag.a "$GOROOT"/pkg/darwin_amd64/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+6g -o "$WORK"/bufio/_obj/_go_.6 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.6
+cp "$WORK"/bufio.a "$GOROOT"/pkg/darwin_amd64/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+6g -o "$WORK"/encoding/gob/_obj/_go_.6 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.6
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/darwin_amd64/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+6g -o "$WORK"/go/token/_obj/_go_.6 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/darwin_amd64/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+6g -o "$WORK"/path/filepath/_obj/_go_.6 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/darwin_amd64/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+6g -o "$WORK"/go/scanner/_obj/_go_.6 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.6
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/darwin_amd64/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+6g -o "$WORK"/go/ast/_obj/_go_.6 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.6
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/darwin_amd64/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+6g -o "$WORK"/io/ioutil/_obj/_go_.6 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/darwin_amd64/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+6g -o "$WORK"/go/parser/_obj/_go_.6 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.6
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/darwin_amd64/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+6g -o "$WORK"/log/_obj/_go_.6 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.6
+cp "$WORK"/log.a "$GOROOT"/pkg/darwin_amd64/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+6g -o "$WORK"/path/_obj/_go_.6 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.6
+cp "$WORK"/path.a "$GOROOT"/pkg/darwin_amd64/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+6g -o "$WORK"/go/build/_obj/_go_.6 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.6
+cp "$WORK"/go/build.a "$GOROOT"/pkg/darwin_amd64/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+6g -o "$WORK"/os/exec/_obj/_go_.6 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/darwin_amd64/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+6g -o "$WORK"/regexp/syntax/_obj/_go_.6 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/darwin_amd64/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+6g -o "$WORK"/regexp/_obj/_go_.6 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.6
+cp "$WORK"/regexp.a "$GOROOT"/pkg/darwin_amd64/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+6g -o "$WORK"/net/url/_obj/_go_.6 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/darwin_amd64/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+6g -o "$WORK"/text/template/parse/_obj/_go_.6 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/darwin_amd64/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+6g -o "$WORK"/text/template/_obj/_go_.6 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/darwin_amd64/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/darwin_amd64/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+6g -o "$WORK"/cmd/go/_obj/_go_.6 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.6
+6l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/freebsd_386.sh b/src/buildscript/freebsd_386.sh
new file mode 100755
index 0000000..f17f9da
--- /dev/null
+++ b/src/buildscript/freebsd_386.sh
@@ -0,0 +1,498 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=freebsd
+export GOARCH=386
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+8g -o "$WORK"/runtime/_obj/_go_.8 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_386.go ./zgoos_freebsd.go ./zruntime_defs_freebsd_386.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_386.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_freebsd_386.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_freebsd.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_freebsd.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_freebsd_386.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/alg.8 -DGOOS_freebsd -DGOARCH_386 ./alg.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/atomic_386.8 -DGOOS_freebsd -DGOARCH_386 ./atomic_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/cgocall.8 -DGOOS_freebsd -DGOARCH_386 ./cgocall.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/chan.8 -DGOOS_freebsd -DGOARCH_386 ./chan.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/closure_386.8 -DGOOS_freebsd -DGOARCH_386 ./closure_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/complex.8 -DGOOS_freebsd -DGOARCH_386 ./complex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/cpuprof.8 -DGOOS_freebsd -DGOARCH_386 ./cpuprof.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/float.8 -DGOOS_freebsd -DGOARCH_386 ./float.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/hashmap.8 -DGOOS_freebsd -DGOARCH_386 ./hashmap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/iface.8 -DGOOS_freebsd -DGOARCH_386 ./iface.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/lock_futex.8 -DGOOS_freebsd -DGOARCH_386 ./lock_futex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/mcache.8 -DGOOS_freebsd -DGOARCH_386 ./mcache.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/mcentral.8 -DGOOS_freebsd -DGOARCH_386 ./mcentral.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/mem_freebsd.8 -DGOOS_freebsd -DGOARCH_386 ./mem_freebsd.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/mfinal.8 -DGOOS_freebsd -DGOARCH_386 ./mfinal.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/mfixalloc.8 -DGOOS_freebsd -DGOARCH_386 ./mfixalloc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/mgc0.8 -DGOOS_freebsd -DGOARCH_386 ./mgc0.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/mheap.8 -DGOOS_freebsd -DGOARCH_386 ./mheap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/msize.8 -DGOOS_freebsd -DGOARCH_386 ./msize.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/print.8 -DGOOS_freebsd -DGOARCH_386 ./print.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/proc.8 -DGOOS_freebsd -DGOARCH_386 ./proc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/rune.8 -DGOOS_freebsd -DGOARCH_386 ./rune.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/runtime.8 -DGOOS_freebsd -DGOARCH_386 ./runtime.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/signal_freebsd_386.8 -DGOOS_freebsd -DGOARCH_386 ./signal_freebsd_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/slice.8 -DGOOS_freebsd -DGOARCH_386 ./slice.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/symtab.8 -DGOOS_freebsd -DGOARCH_386 ./symtab.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/thread_freebsd.8 -DGOOS_freebsd -DGOARCH_386 ./thread_freebsd.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/traceback_x86.8 -DGOOS_freebsd -DGOARCH_386 ./traceback_x86.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/vlrt_386.8 -DGOOS_freebsd -DGOARCH_386 ./vlrt_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/zmalloc_386.8 -DGOOS_freebsd -DGOARCH_386 ./zmalloc_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/zmprof_386.8 -DGOOS_freebsd -DGOARCH_386 ./zmprof_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/zruntime1_386.8 -DGOOS_freebsd -DGOARCH_386 ./zruntime1_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/zsema_386.8 -DGOOS_freebsd -DGOARCH_386 ./zsema_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/zsigqueue_386.8 -DGOOS_freebsd -DGOARCH_386 ./zsigqueue_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/zstring_386.8 -DGOOS_freebsd -DGOARCH_386 ./zstring_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_386 -o "$WORK"/runtime/_obj/ztime_386.8 -DGOOS_freebsd -DGOARCH_386 ./ztime_386.c
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_386.8 -DGOOS_freebsd -DGOARCH_386 ./asm_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_386.8 -DGOOS_freebsd -DGOARCH_386 ./memmove_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_freebsd_386.8 -DGOOS_freebsd -DGOARCH_386 ./rt0_freebsd_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_freebsd_386.8 -DGOOS_freebsd -DGOARCH_386 ./sys_freebsd_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/vlop_386.8 -DGOOS_freebsd -DGOARCH_386 ./vlop_386.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.8 "$WORK"/runtime/_obj/alg.8 "$WORK"/runtime/_obj/atomic_386.8 "$WORK"/runtime/_obj/cgocall.8 "$WORK"/runtime/_obj/chan.8 "$WORK"/runtime/_obj/closure_386.8 "$WORK"/runtime/_obj/complex.8 "$WORK"/runtime/_obj/cpuprof.8 "$WORK"/runtime/_obj/float.8 "$WORK"/runtime/_obj/hashmap.8 "$WORK"/runtime/_obj/iface.8 "$WORK"/runtime/_obj/lock_futex.8 "$WORK"/runtime/_obj/mcache.8 "$WORK"/runtime/_obj/mcentral.8 "$WORK"/runtime/_obj/mem_freebsd.8 "$WORK"/runtime/_obj/mfinal.8 "$WORK"/runtime/_obj/mfixalloc.8 "$WORK"/runtime/_obj/mgc0.8 "$WORK"/runtime/_obj/mheap.8 "$WORK"/runtime/_obj/msize.8 "$WORK"/runtime/_obj/print.8 "$WORK"/runtime/_obj/proc.8 "$WORK"/runtime/_obj/rune.8 "$WORK"/runtime/_obj/runtime.8 "$WORK"/runtime/_obj/signal_freebsd_386.8 "$WORK"/runtime/_obj/slice.8 "$WORK"/runtime/_obj/symtab.8 "$WORK"/runtime/_obj/thread_freebsd.8 "$WORK"/runtime/_obj/traceback_x86.8 "$WORK"/runtime/_obj/vlrt_386.8 "$WORK"/runtime/_obj/zmalloc_386.8 "$WORK"/runtime/_obj/zmprof_386.8 "$WORK"/runtime/_obj/zruntime1_386.8 "$WORK"/runtime/_obj/zsema_386.8 "$WORK"/runtime/_obj/zsigqueue_386.8 "$WORK"/runtime/_obj/zstring_386.8 "$WORK"/runtime/_obj/ztime_386.8 "$WORK"/runtime/_obj/asm_386.8 "$WORK"/runtime/_obj/memmove_386.8 "$WORK"/runtime/_obj/rt0_freebsd_386.8 "$WORK"/runtime/_obj/sys_freebsd_386.8 "$WORK"/runtime/_obj/vlop_386.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/freebsd_386/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+8g -o "$WORK"/errors/_obj/_go_.8 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.8
+cp "$WORK"/errors.a "$GOROOT"/pkg/freebsd_386/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+8g -o "$WORK"/sync/atomic/_obj/_go_.8 -p sync/atomic -I "$WORK" ./doc.go
+8a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_386.8 -DGOOS_freebsd -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.8 "$WORK"/sync/atomic/_obj/asm_386.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/freebsd_386/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+8g -o "$WORK"/sync/_obj/_go_.8 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.8
+cp "$WORK"/sync.a "$GOROOT"/pkg/freebsd_386/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+8g -o "$WORK"/io/_obj/_go_.8 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.8
+cp "$WORK"/io.a "$GOROOT"/pkg/freebsd_386/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+8g -o "$WORK"/unicode/_obj/_go_.8 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.8
+cp "$WORK"/unicode.a "$GOROOT"/pkg/freebsd_386/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+8g -o "$WORK"/unicode/utf8/_obj/_go_.8 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/freebsd_386/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+8g -o "$WORK"/bytes/_obj/_go_.8 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+8a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_386.8 -DGOOS_freebsd -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.8 "$WORK"/bytes/_obj/asm_386.8
+cp "$WORK"/bytes.a "$GOROOT"/pkg/freebsd_386/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+8g -o "$WORK"/math/_obj/_go_.8 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_386.8 -DGOOS_freebsd -DGOARCH_386 ./abs_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_386.8 -DGOOS_freebsd -DGOARCH_386 ./asin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_386.8 -DGOOS_freebsd -DGOARCH_386 ./atan2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_386.8 -DGOOS_freebsd -DGOARCH_386 ./atan_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_386.8 -DGOOS_freebsd -DGOARCH_386 ./dim_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_386.8 -DGOOS_freebsd -DGOARCH_386 ./exp2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_386.8 -DGOOS_freebsd -DGOARCH_386 ./exp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_386.8 -DGOOS_freebsd -DGOARCH_386 ./expm1_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_386.8 -DGOOS_freebsd -DGOARCH_386 ./floor_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_386.8 -DGOOS_freebsd -DGOARCH_386 ./frexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_386.8 -DGOOS_freebsd -DGOARCH_386 ./hypot_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_386.8 -DGOOS_freebsd -DGOARCH_386 ./ldexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_386.8 -DGOOS_freebsd -DGOARCH_386 ./log10_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_386.8 -DGOOS_freebsd -DGOARCH_386 ./log1p_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_386.8 -DGOOS_freebsd -DGOARCH_386 ./log_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_386.8 -DGOOS_freebsd -DGOARCH_386 ./mod_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_386.8 -DGOOS_freebsd -DGOARCH_386 ./modf_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_386.8 -DGOOS_freebsd -DGOARCH_386 ./remainder_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_386.8 -DGOOS_freebsd -DGOARCH_386 ./sin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_386.8 -DGOOS_freebsd -DGOARCH_386 ./sincos_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_386.8 -DGOOS_freebsd -DGOARCH_386 ./sqrt_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_386.8 -DGOOS_freebsd -DGOARCH_386 ./tan_386.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.8 "$WORK"/math/_obj/abs_386.8 "$WORK"/math/_obj/asin_386.8 "$WORK"/math/_obj/atan2_386.8 "$WORK"/math/_obj/atan_386.8 "$WORK"/math/_obj/dim_386.8 "$WORK"/math/_obj/exp2_386.8 "$WORK"/math/_obj/exp_386.8 "$WORK"/math/_obj/expm1_386.8 "$WORK"/math/_obj/floor_386.8 "$WORK"/math/_obj/frexp_386.8 "$WORK"/math/_obj/hypot_386.8 "$WORK"/math/_obj/ldexp_386.8 "$WORK"/math/_obj/log10_386.8 "$WORK"/math/_obj/log1p_386.8 "$WORK"/math/_obj/log_386.8 "$WORK"/math/_obj/mod_386.8 "$WORK"/math/_obj/modf_386.8 "$WORK"/math/_obj/remainder_386.8 "$WORK"/math/_obj/sin_386.8 "$WORK"/math/_obj/sincos_386.8 "$WORK"/math/_obj/sqrt_386.8 "$WORK"/math/_obj/tan_386.8
+cp "$WORK"/math.a "$GOROOT"/pkg/freebsd_386/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+8g -o "$WORK"/sort/_obj/_go_.8 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.8
+cp "$WORK"/sort.a "$GOROOT"/pkg/freebsd_386/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+8g -o "$WORK"/container/heap/_obj/_go_.8 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/freebsd_386/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+8g -o "$WORK"/strings/_obj/_go_.8 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.8
+cp "$WORK"/strings.a "$GOROOT"/pkg/freebsd_386/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+8g -o "$WORK"/strconv/_obj/_go_.8 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.8
+cp "$WORK"/strconv.a "$GOROOT"/pkg/freebsd_386/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+8g -o "$WORK"/encoding/base64/_obj/_go_.8 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/freebsd_386/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_freebsd.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_freebsd.go ./syscall_freebsd_386.go ./syscall_unix.go ./zerrors_freebsd_386.go ./zsyscall_freebsd_386.go ./zsysnum_freebsd_386.go ./ztypes_freebsd_386.go
+8a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_freebsd_386.8 -DGOOS_freebsd -DGOARCH_386 ./asm_freebsd_386.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.8 "$WORK"/syscall/_obj/asm_freebsd_386.8
+cp "$WORK"/syscall.a "$GOROOT"/pkg/freebsd_386/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+8g -o "$WORK"/time/_obj/_go_.8 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.8
+cp "$WORK"/time.a "$GOROOT"/pkg/freebsd_386/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+8g -o "$WORK"/os/_obj/_go_.8 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_freebsd.go ./sys_bsd.go ./time.go ./types.go ./zsignal_freebsd_386.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.8
+cp "$WORK"/os.a "$GOROOT"/pkg/freebsd_386/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+8g -o "$WORK"/reflect/_obj/_go_.8 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.8
+cp "$WORK"/reflect.a "$GOROOT"/pkg/freebsd_386/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+8g -o "$WORK"/fmt/_obj/_go_.8 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.8
+cp "$WORK"/fmt.a "$GOROOT"/pkg/freebsd_386/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+8g -o "$WORK"/unicode/utf16/_obj/_go_.8 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.8
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/freebsd_386/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+8g -o "$WORK"/encoding/json/_obj/_go_.8 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.8
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/freebsd_386/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+8g -o "$WORK"/flag/_obj/_go_.8 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.8
+cp "$WORK"/flag.a "$GOROOT"/pkg/freebsd_386/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+8g -o "$WORK"/bufio/_obj/_go_.8 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.8
+cp "$WORK"/bufio.a "$GOROOT"/pkg/freebsd_386/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+8g -o "$WORK"/encoding/gob/_obj/_go_.8 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.8
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/freebsd_386/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+8g -o "$WORK"/go/token/_obj/_go_.8 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/freebsd_386/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+8g -o "$WORK"/path/filepath/_obj/_go_.8 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/freebsd_386/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+8g -o "$WORK"/go/scanner/_obj/_go_.8 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.8
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/freebsd_386/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+8g -o "$WORK"/go/ast/_obj/_go_.8 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.8
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/freebsd_386/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+8g -o "$WORK"/io/ioutil/_obj/_go_.8 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/freebsd_386/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+8g -o "$WORK"/go/parser/_obj/_go_.8 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.8
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/freebsd_386/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+8g -o "$WORK"/log/_obj/_go_.8 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.8
+cp "$WORK"/log.a "$GOROOT"/pkg/freebsd_386/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+8g -o "$WORK"/path/_obj/_go_.8 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.8
+cp "$WORK"/path.a "$GOROOT"/pkg/freebsd_386/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+8g -o "$WORK"/go/build/_obj/_go_.8 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.8
+cp "$WORK"/go/build.a "$GOROOT"/pkg/freebsd_386/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+8g -o "$WORK"/os/exec/_obj/_go_.8 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/freebsd_386/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+8g -o "$WORK"/regexp/syntax/_obj/_go_.8 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/freebsd_386/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+8g -o "$WORK"/regexp/_obj/_go_.8 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.8
+cp "$WORK"/regexp.a "$GOROOT"/pkg/freebsd_386/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+8g -o "$WORK"/net/url/_obj/_go_.8 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/freebsd_386/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+8g -o "$WORK"/text/template/parse/_obj/_go_.8 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/freebsd_386/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+8g -o "$WORK"/text/template/_obj/_go_.8 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/freebsd_386/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/freebsd_386/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+8g -o "$WORK"/cmd/go/_obj/_go_.8 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.8
+8l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/freebsd_amd64.sh b/src/buildscript/freebsd_amd64.sh
new file mode 100755
index 0000000..be0070a
--- /dev/null
+++ b/src/buildscript/freebsd_amd64.sh
@@ -0,0 +1,497 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=freebsd
+export GOARCH=amd64
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+6g -o "$WORK"/runtime/_obj/_go_.6 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_amd64.go ./zgoos_freebsd.go ./zruntime_defs_freebsd_amd64.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_amd64.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_freebsd_amd64.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_freebsd.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_freebsd.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_freebsd_amd64.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/alg.6 -DGOOS_freebsd -DGOARCH_amd64 ./alg.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/atomic_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./atomic_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/cgocall.6 -DGOOS_freebsd -DGOARCH_amd64 ./cgocall.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/chan.6 -DGOOS_freebsd -DGOARCH_amd64 ./chan.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/closure_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./closure_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/complex.6 -DGOOS_freebsd -DGOARCH_amd64 ./complex.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/cpuprof.6 -DGOOS_freebsd -DGOARCH_amd64 ./cpuprof.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/float.6 -DGOOS_freebsd -DGOARCH_amd64 ./float.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/hashmap.6 -DGOOS_freebsd -DGOARCH_amd64 ./hashmap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/iface.6 -DGOOS_freebsd -DGOARCH_amd64 ./iface.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/lock_futex.6 -DGOOS_freebsd -DGOARCH_amd64 ./lock_futex.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/mcache.6 -DGOOS_freebsd -DGOARCH_amd64 ./mcache.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/mcentral.6 -DGOOS_freebsd -DGOARCH_amd64 ./mcentral.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/mem_freebsd.6 -DGOOS_freebsd -DGOARCH_amd64 ./mem_freebsd.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/mfinal.6 -DGOOS_freebsd -DGOARCH_amd64 ./mfinal.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/mfixalloc.6 -DGOOS_freebsd -DGOARCH_amd64 ./mfixalloc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/mgc0.6 -DGOOS_freebsd -DGOARCH_amd64 ./mgc0.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/mheap.6 -DGOOS_freebsd -DGOARCH_amd64 ./mheap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/msize.6 -DGOOS_freebsd -DGOARCH_amd64 ./msize.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/print.6 -DGOOS_freebsd -DGOARCH_amd64 ./print.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/proc.6 -DGOOS_freebsd -DGOARCH_amd64 ./proc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/rune.6 -DGOOS_freebsd -DGOARCH_amd64 ./rune.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/runtime.6 -DGOOS_freebsd -DGOARCH_amd64 ./runtime.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/signal_freebsd_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./signal_freebsd_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/slice.6 -DGOOS_freebsd -DGOARCH_amd64 ./slice.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/symtab.6 -DGOOS_freebsd -DGOARCH_amd64 ./symtab.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/thread_freebsd.6 -DGOOS_freebsd -DGOARCH_amd64 ./thread_freebsd.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/traceback_x86.6 -DGOOS_freebsd -DGOARCH_amd64 ./traceback_x86.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/zmalloc_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./zmalloc_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/zmprof_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./zmprof_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/zruntime1_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./zruntime1_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/zsema_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./zsema_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/zsigqueue_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./zsigqueue_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/zstring_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./zstring_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/freebsd_amd64 -o "$WORK"/runtime/_obj/ztime_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./ztime_amd64.c
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./asm_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./memmove_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_freebsd_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./rt0_freebsd_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_freebsd_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./sys_freebsd_amd64.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.6 "$WORK"/runtime/_obj/alg.6 "$WORK"/runtime/_obj/atomic_amd64.6 "$WORK"/runtime/_obj/cgocall.6 "$WORK"/runtime/_obj/chan.6 "$WORK"/runtime/_obj/closure_amd64.6 "$WORK"/runtime/_obj/complex.6 "$WORK"/runtime/_obj/cpuprof.6 "$WORK"/runtime/_obj/float.6 "$WORK"/runtime/_obj/hashmap.6 "$WORK"/runtime/_obj/iface.6 "$WORK"/runtime/_obj/lock_futex.6 "$WORK"/runtime/_obj/mcache.6 "$WORK"/runtime/_obj/mcentral.6 "$WORK"/runtime/_obj/mem_freebsd.6 "$WORK"/runtime/_obj/mfinal.6 "$WORK"/runtime/_obj/mfixalloc.6 "$WORK"/runtime/_obj/mgc0.6 "$WORK"/runtime/_obj/mheap.6 "$WORK"/runtime/_obj/msize.6 "$WORK"/runtime/_obj/print.6 "$WORK"/runtime/_obj/proc.6 "$WORK"/runtime/_obj/rune.6 "$WORK"/runtime/_obj/runtime.6 "$WORK"/runtime/_obj/signal_freebsd_amd64.6 "$WORK"/runtime/_obj/slice.6 "$WORK"/runtime/_obj/symtab.6 "$WORK"/runtime/_obj/thread_freebsd.6 "$WORK"/runtime/_obj/traceback_x86.6 "$WORK"/runtime/_obj/zmalloc_amd64.6 "$WORK"/runtime/_obj/zmprof_amd64.6 "$WORK"/runtime/_obj/zruntime1_amd64.6 "$WORK"/runtime/_obj/zsema_amd64.6 "$WORK"/runtime/_obj/zsigqueue_amd64.6 "$WORK"/runtime/_obj/zstring_amd64.6 "$WORK"/runtime/_obj/ztime_amd64.6 "$WORK"/runtime/_obj/asm_amd64.6 "$WORK"/runtime/_obj/memmove_amd64.6 "$WORK"/runtime/_obj/rt0_freebsd_amd64.6 "$WORK"/runtime/_obj/sys_freebsd_amd64.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/freebsd_amd64/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+6g -o "$WORK"/errors/_obj/_go_.6 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.6
+cp "$WORK"/errors.a "$GOROOT"/pkg/freebsd_amd64/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+6g -o "$WORK"/sync/atomic/_obj/_go_.6 -p sync/atomic -I "$WORK" ./doc.go
+6a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.6 "$WORK"/sync/atomic/_obj/asm_amd64.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/freebsd_amd64/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+6g -o "$WORK"/sync/_obj/_go_.6 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.6
+cp "$WORK"/sync.a "$GOROOT"/pkg/freebsd_amd64/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+6g -o "$WORK"/io/_obj/_go_.6 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.6
+cp "$WORK"/io.a "$GOROOT"/pkg/freebsd_amd64/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+6g -o "$WORK"/unicode/_obj/_go_.6 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.6
+cp "$WORK"/unicode.a "$GOROOT"/pkg/freebsd_amd64/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+6g -o "$WORK"/unicode/utf8/_obj/_go_.6 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/freebsd_amd64/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+6g -o "$WORK"/bytes/_obj/_go_.6 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+6a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.6 "$WORK"/bytes/_obj/asm_amd64.6
+cp "$WORK"/bytes.a "$GOROOT"/pkg/freebsd_amd64/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+6g -o "$WORK"/math/_obj/_go_.6 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./abs_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./asin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./atan2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./atan_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./dim_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./exp2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./exp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./expm1_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./floor_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/fltasm_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./fltasm_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./frexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./hypot_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./ldexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./log10_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./log1p_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./log_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./mod_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./modf_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./remainder_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./sin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./sincos_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./sqrt_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./tan_amd64.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.6 "$WORK"/math/_obj/abs_amd64.6 "$WORK"/math/_obj/asin_amd64.6 "$WORK"/math/_obj/atan2_amd64.6 "$WORK"/math/_obj/atan_amd64.6 "$WORK"/math/_obj/dim_amd64.6 "$WORK"/math/_obj/exp2_amd64.6 "$WORK"/math/_obj/exp_amd64.6 "$WORK"/math/_obj/expm1_amd64.6 "$WORK"/math/_obj/floor_amd64.6 "$WORK"/math/_obj/fltasm_amd64.6 "$WORK"/math/_obj/frexp_amd64.6 "$WORK"/math/_obj/hypot_amd64.6 "$WORK"/math/_obj/ldexp_amd64.6 "$WORK"/math/_obj/log10_amd64.6 "$WORK"/math/_obj/log1p_amd64.6 "$WORK"/math/_obj/log_amd64.6 "$WORK"/math/_obj/mod_amd64.6 "$WORK"/math/_obj/modf_amd64.6 "$WORK"/math/_obj/remainder_amd64.6 "$WORK"/math/_obj/sin_amd64.6 "$WORK"/math/_obj/sincos_amd64.6 "$WORK"/math/_obj/sqrt_amd64.6 "$WORK"/math/_obj/tan_amd64.6
+cp "$WORK"/math.a "$GOROOT"/pkg/freebsd_amd64/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+6g -o "$WORK"/sort/_obj/_go_.6 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.6
+cp "$WORK"/sort.a "$GOROOT"/pkg/freebsd_amd64/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+6g -o "$WORK"/container/heap/_obj/_go_.6 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/freebsd_amd64/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+6g -o "$WORK"/strings/_obj/_go_.6 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.6
+cp "$WORK"/strings.a "$GOROOT"/pkg/freebsd_amd64/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+6g -o "$WORK"/strconv/_obj/_go_.6 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.6
+cp "$WORK"/strconv.a "$GOROOT"/pkg/freebsd_amd64/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+6g -o "$WORK"/encoding/base64/_obj/_go_.6 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/freebsd_amd64/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+6g -o "$WORK"/syscall/_obj/_go_.6 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_freebsd.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_freebsd.go ./syscall_freebsd_amd64.go ./syscall_unix.go ./zerrors_freebsd_amd64.go ./zsyscall_freebsd_amd64.go ./zsysnum_freebsd_amd64.go ./ztypes_freebsd_amd64.go
+6a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_freebsd_amd64.6 -DGOOS_freebsd -DGOARCH_amd64 ./asm_freebsd_amd64.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.6 "$WORK"/syscall/_obj/asm_freebsd_amd64.6
+cp "$WORK"/syscall.a "$GOROOT"/pkg/freebsd_amd64/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+6g -o "$WORK"/time/_obj/_go_.6 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.6
+cp "$WORK"/time.a "$GOROOT"/pkg/freebsd_amd64/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+6g -o "$WORK"/os/_obj/_go_.6 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_freebsd.go ./sys_bsd.go ./time.go ./types.go ./zsignal_freebsd_amd64.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.6
+cp "$WORK"/os.a "$GOROOT"/pkg/freebsd_amd64/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+6g -o "$WORK"/reflect/_obj/_go_.6 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.6
+cp "$WORK"/reflect.a "$GOROOT"/pkg/freebsd_amd64/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+6g -o "$WORK"/fmt/_obj/_go_.6 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.6
+cp "$WORK"/fmt.a "$GOROOT"/pkg/freebsd_amd64/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+6g -o "$WORK"/unicode/utf16/_obj/_go_.6 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.6
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/freebsd_amd64/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+6g -o "$WORK"/encoding/json/_obj/_go_.6 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.6
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/freebsd_amd64/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+6g -o "$WORK"/flag/_obj/_go_.6 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.6
+cp "$WORK"/flag.a "$GOROOT"/pkg/freebsd_amd64/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+6g -o "$WORK"/bufio/_obj/_go_.6 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.6
+cp "$WORK"/bufio.a "$GOROOT"/pkg/freebsd_amd64/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+6g -o "$WORK"/encoding/gob/_obj/_go_.6 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.6
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/freebsd_amd64/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+6g -o "$WORK"/go/token/_obj/_go_.6 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/freebsd_amd64/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+6g -o "$WORK"/path/filepath/_obj/_go_.6 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/freebsd_amd64/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+6g -o "$WORK"/go/scanner/_obj/_go_.6 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.6
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/freebsd_amd64/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+6g -o "$WORK"/go/ast/_obj/_go_.6 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.6
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/freebsd_amd64/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+6g -o "$WORK"/io/ioutil/_obj/_go_.6 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/freebsd_amd64/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+6g -o "$WORK"/go/parser/_obj/_go_.6 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.6
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/freebsd_amd64/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+6g -o "$WORK"/log/_obj/_go_.6 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.6
+cp "$WORK"/log.a "$GOROOT"/pkg/freebsd_amd64/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+6g -o "$WORK"/path/_obj/_go_.6 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.6
+cp "$WORK"/path.a "$GOROOT"/pkg/freebsd_amd64/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+6g -o "$WORK"/go/build/_obj/_go_.6 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.6
+cp "$WORK"/go/build.a "$GOROOT"/pkg/freebsd_amd64/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+6g -o "$WORK"/os/exec/_obj/_go_.6 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/freebsd_amd64/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+6g -o "$WORK"/regexp/syntax/_obj/_go_.6 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/freebsd_amd64/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+6g -o "$WORK"/regexp/_obj/_go_.6 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.6
+cp "$WORK"/regexp.a "$GOROOT"/pkg/freebsd_amd64/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+6g -o "$WORK"/net/url/_obj/_go_.6 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/freebsd_amd64/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+6g -o "$WORK"/text/template/parse/_obj/_go_.6 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/freebsd_amd64/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+6g -o "$WORK"/text/template/_obj/_go_.6 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/freebsd_amd64/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/freebsd_amd64/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+6g -o "$WORK"/cmd/go/_obj/_go_.6 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.6
+6l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/linux_386.sh b/src/buildscript/linux_386.sh
new file mode 100755
index 0000000..8ae424d
--- /dev/null
+++ b/src/buildscript/linux_386.sh
@@ -0,0 +1,498 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=linux
+export GOARCH=386
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+8g -o "$WORK"/runtime/_obj/_go_.8 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_386.go ./zgoos_linux.go ./zruntime_defs_linux_386.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_386.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_linux_386.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_linux.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_linux.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_linux_386.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/alg.8 -DGOOS_linux -DGOARCH_386 ./alg.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/atomic_386.8 -DGOOS_linux -DGOARCH_386 ./atomic_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/cgocall.8 -DGOOS_linux -DGOARCH_386 ./cgocall.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/chan.8 -DGOOS_linux -DGOARCH_386 ./chan.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/closure_386.8 -DGOOS_linux -DGOARCH_386 ./closure_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/complex.8 -DGOOS_linux -DGOARCH_386 ./complex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/cpuprof.8 -DGOOS_linux -DGOARCH_386 ./cpuprof.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/float.8 -DGOOS_linux -DGOARCH_386 ./float.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/hashmap.8 -DGOOS_linux -DGOARCH_386 ./hashmap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/iface.8 -DGOOS_linux -DGOARCH_386 ./iface.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/lock_futex.8 -DGOOS_linux -DGOARCH_386 ./lock_futex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/mcache.8 -DGOOS_linux -DGOARCH_386 ./mcache.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/mcentral.8 -DGOOS_linux -DGOARCH_386 ./mcentral.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/mem_linux.8 -DGOOS_linux -DGOARCH_386 ./mem_linux.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/mfinal.8 -DGOOS_linux -DGOARCH_386 ./mfinal.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/mfixalloc.8 -DGOOS_linux -DGOARCH_386 ./mfixalloc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/mgc0.8 -DGOOS_linux -DGOARCH_386 ./mgc0.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/mheap.8 -DGOOS_linux -DGOARCH_386 ./mheap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/msize.8 -DGOOS_linux -DGOARCH_386 ./msize.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/print.8 -DGOOS_linux -DGOARCH_386 ./print.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/proc.8 -DGOOS_linux -DGOARCH_386 ./proc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/rune.8 -DGOOS_linux -DGOARCH_386 ./rune.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/runtime.8 -DGOOS_linux -DGOARCH_386 ./runtime.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/signal_linux_386.8 -DGOOS_linux -DGOARCH_386 ./signal_linux_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/slice.8 -DGOOS_linux -DGOARCH_386 ./slice.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/symtab.8 -DGOOS_linux -DGOARCH_386 ./symtab.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/thread_linux.8 -DGOOS_linux -DGOARCH_386 ./thread_linux.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/traceback_x86.8 -DGOOS_linux -DGOARCH_386 ./traceback_x86.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/vlrt_386.8 -DGOOS_linux -DGOARCH_386 ./vlrt_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/zmalloc_386.8 -DGOOS_linux -DGOARCH_386 ./zmalloc_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/zmprof_386.8 -DGOOS_linux -DGOARCH_386 ./zmprof_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/zruntime1_386.8 -DGOOS_linux -DGOARCH_386 ./zruntime1_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/zsema_386.8 -DGOOS_linux -DGOARCH_386 ./zsema_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/zsigqueue_386.8 -DGOOS_linux -DGOARCH_386 ./zsigqueue_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/zstring_386.8 -DGOOS_linux -DGOARCH_386 ./zstring_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_386 -o "$WORK"/runtime/_obj/ztime_386.8 -DGOOS_linux -DGOARCH_386 ./ztime_386.c
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_386.8 -DGOOS_linux -DGOARCH_386 ./asm_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_386.8 -DGOOS_linux -DGOARCH_386 ./memmove_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_linux_386.8 -DGOOS_linux -DGOARCH_386 ./rt0_linux_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_linux_386.8 -DGOOS_linux -DGOARCH_386 ./sys_linux_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/vlop_386.8 -DGOOS_linux -DGOARCH_386 ./vlop_386.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.8 "$WORK"/runtime/_obj/alg.8 "$WORK"/runtime/_obj/atomic_386.8 "$WORK"/runtime/_obj/cgocall.8 "$WORK"/runtime/_obj/chan.8 "$WORK"/runtime/_obj/closure_386.8 "$WORK"/runtime/_obj/complex.8 "$WORK"/runtime/_obj/cpuprof.8 "$WORK"/runtime/_obj/float.8 "$WORK"/runtime/_obj/hashmap.8 "$WORK"/runtime/_obj/iface.8 "$WORK"/runtime/_obj/lock_futex.8 "$WORK"/runtime/_obj/mcache.8 "$WORK"/runtime/_obj/mcentral.8 "$WORK"/runtime/_obj/mem_linux.8 "$WORK"/runtime/_obj/mfinal.8 "$WORK"/runtime/_obj/mfixalloc.8 "$WORK"/runtime/_obj/mgc0.8 "$WORK"/runtime/_obj/mheap.8 "$WORK"/runtime/_obj/msize.8 "$WORK"/runtime/_obj/print.8 "$WORK"/runtime/_obj/proc.8 "$WORK"/runtime/_obj/rune.8 "$WORK"/runtime/_obj/runtime.8 "$WORK"/runtime/_obj/signal_linux_386.8 "$WORK"/runtime/_obj/slice.8 "$WORK"/runtime/_obj/symtab.8 "$WORK"/runtime/_obj/thread_linux.8 "$WORK"/runtime/_obj/traceback_x86.8 "$WORK"/runtime/_obj/vlrt_386.8 "$WORK"/runtime/_obj/zmalloc_386.8 "$WORK"/runtime/_obj/zmprof_386.8 "$WORK"/runtime/_obj/zruntime1_386.8 "$WORK"/runtime/_obj/zsema_386.8 "$WORK"/runtime/_obj/zsigqueue_386.8 "$WORK"/runtime/_obj/zstring_386.8 "$WORK"/runtime/_obj/ztime_386.8 "$WORK"/runtime/_obj/asm_386.8 "$WORK"/runtime/_obj/memmove_386.8 "$WORK"/runtime/_obj/rt0_linux_386.8 "$WORK"/runtime/_obj/sys_linux_386.8 "$WORK"/runtime/_obj/vlop_386.8
+mkdir -p "$GOROOT"/pkg/linux_386/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/linux_386/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+8g -o "$WORK"/errors/_obj/_go_.8 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.8
+cp "$WORK"/errors.a "$GOROOT"/pkg/linux_386/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+8g -o "$WORK"/sync/atomic/_obj/_go_.8 -p sync/atomic -I "$WORK" ./doc.go
+8a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_386.8 -DGOOS_linux -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.8 "$WORK"/sync/atomic/_obj/asm_386.8
+mkdir -p "$GOROOT"/pkg/linux_386/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/linux_386/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+8g -o "$WORK"/sync/_obj/_go_.8 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.8
+cp "$WORK"/sync.a "$GOROOT"/pkg/linux_386/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+8g -o "$WORK"/io/_obj/_go_.8 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.8
+cp "$WORK"/io.a "$GOROOT"/pkg/linux_386/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+8g -o "$WORK"/unicode/_obj/_go_.8 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.8
+cp "$WORK"/unicode.a "$GOROOT"/pkg/linux_386/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+8g -o "$WORK"/unicode/utf8/_obj/_go_.8 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/linux_386/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+8g -o "$WORK"/bytes/_obj/_go_.8 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+8a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_386.8 -DGOOS_linux -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.8 "$WORK"/bytes/_obj/asm_386.8
+cp "$WORK"/bytes.a "$GOROOT"/pkg/linux_386/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+8g -o "$WORK"/math/_obj/_go_.8 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_386.8 -DGOOS_linux -DGOARCH_386 ./abs_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_386.8 -DGOOS_linux -DGOARCH_386 ./asin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_386.8 -DGOOS_linux -DGOARCH_386 ./atan2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_386.8 -DGOOS_linux -DGOARCH_386 ./atan_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_386.8 -DGOOS_linux -DGOARCH_386 ./dim_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_386.8 -DGOOS_linux -DGOARCH_386 ./exp2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_386.8 -DGOOS_linux -DGOARCH_386 ./exp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_386.8 -DGOOS_linux -DGOARCH_386 ./expm1_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_386.8 -DGOOS_linux -DGOARCH_386 ./floor_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_386.8 -DGOOS_linux -DGOARCH_386 ./frexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_386.8 -DGOOS_linux -DGOARCH_386 ./hypot_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_386.8 -DGOOS_linux -DGOARCH_386 ./ldexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_386.8 -DGOOS_linux -DGOARCH_386 ./log10_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_386.8 -DGOOS_linux -DGOARCH_386 ./log1p_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_386.8 -DGOOS_linux -DGOARCH_386 ./log_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_386.8 -DGOOS_linux -DGOARCH_386 ./mod_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_386.8 -DGOOS_linux -DGOARCH_386 ./modf_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_386.8 -DGOOS_linux -DGOARCH_386 ./remainder_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_386.8 -DGOOS_linux -DGOARCH_386 ./sin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_386.8 -DGOOS_linux -DGOARCH_386 ./sincos_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_386.8 -DGOOS_linux -DGOARCH_386 ./sqrt_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_386.8 -DGOOS_linux -DGOARCH_386 ./tan_386.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.8 "$WORK"/math/_obj/abs_386.8 "$WORK"/math/_obj/asin_386.8 "$WORK"/math/_obj/atan2_386.8 "$WORK"/math/_obj/atan_386.8 "$WORK"/math/_obj/dim_386.8 "$WORK"/math/_obj/exp2_386.8 "$WORK"/math/_obj/exp_386.8 "$WORK"/math/_obj/expm1_386.8 "$WORK"/math/_obj/floor_386.8 "$WORK"/math/_obj/frexp_386.8 "$WORK"/math/_obj/hypot_386.8 "$WORK"/math/_obj/ldexp_386.8 "$WORK"/math/_obj/log10_386.8 "$WORK"/math/_obj/log1p_386.8 "$WORK"/math/_obj/log_386.8 "$WORK"/math/_obj/mod_386.8 "$WORK"/math/_obj/modf_386.8 "$WORK"/math/_obj/remainder_386.8 "$WORK"/math/_obj/sin_386.8 "$WORK"/math/_obj/sincos_386.8 "$WORK"/math/_obj/sqrt_386.8 "$WORK"/math/_obj/tan_386.8
+cp "$WORK"/math.a "$GOROOT"/pkg/linux_386/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+8g -o "$WORK"/sort/_obj/_go_.8 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.8
+cp "$WORK"/sort.a "$GOROOT"/pkg/linux_386/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+8g -o "$WORK"/container/heap/_obj/_go_.8 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/linux_386/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+8g -o "$WORK"/strings/_obj/_go_.8 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.8
+cp "$WORK"/strings.a "$GOROOT"/pkg/linux_386/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+8g -o "$WORK"/strconv/_obj/_go_.8 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.8
+cp "$WORK"/strconv.a "$GOROOT"/pkg/linux_386/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+8g -o "$WORK"/encoding/base64/_obj/_go_.8 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/linux_386/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./env_unix.go ./exec_linux.go ./exec_unix.go ./lsf_linux.go ./netlink_linux.go ./sockcmsg_linux.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_linux.go ./syscall_linux_386.go ./syscall_unix.go ./zerrors_linux_386.go ./zsyscall_linux_386.go ./zsysnum_linux_386.go ./ztypes_linux_386.go
+8a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_linux_386.8 -DGOOS_linux -DGOARCH_386 ./asm_linux_386.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.8 "$WORK"/syscall/_obj/asm_linux_386.8
+cp "$WORK"/syscall.a "$GOROOT"/pkg/linux_386/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+8g -o "$WORK"/time/_obj/_go_.8 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.8
+cp "$WORK"/time.a "$GOROOT"/pkg/linux_386/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+8g -o "$WORK"/os/_obj/_go_.8 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_linux.go ./sys_linux.go ./time.go ./types.go ./zsignal_linux_386.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.8
+cp "$WORK"/os.a "$GOROOT"/pkg/linux_386/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+8g -o "$WORK"/reflect/_obj/_go_.8 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.8
+cp "$WORK"/reflect.a "$GOROOT"/pkg/linux_386/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+8g -o "$WORK"/fmt/_obj/_go_.8 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.8
+cp "$WORK"/fmt.a "$GOROOT"/pkg/linux_386/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+8g -o "$WORK"/unicode/utf16/_obj/_go_.8 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.8
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/linux_386/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+8g -o "$WORK"/encoding/json/_obj/_go_.8 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.8
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/linux_386/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+8g -o "$WORK"/flag/_obj/_go_.8 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.8
+cp "$WORK"/flag.a "$GOROOT"/pkg/linux_386/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+8g -o "$WORK"/bufio/_obj/_go_.8 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.8
+cp "$WORK"/bufio.a "$GOROOT"/pkg/linux_386/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+8g -o "$WORK"/encoding/gob/_obj/_go_.8 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.8
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/linux_386/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+8g -o "$WORK"/go/token/_obj/_go_.8 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/linux_386/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+8g -o "$WORK"/path/filepath/_obj/_go_.8 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/linux_386/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+8g -o "$WORK"/go/scanner/_obj/_go_.8 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.8
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/linux_386/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+8g -o "$WORK"/go/ast/_obj/_go_.8 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.8
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/linux_386/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+8g -o "$WORK"/io/ioutil/_obj/_go_.8 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/linux_386/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+8g -o "$WORK"/go/parser/_obj/_go_.8 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.8
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/linux_386/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+8g -o "$WORK"/log/_obj/_go_.8 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.8
+cp "$WORK"/log.a "$GOROOT"/pkg/linux_386/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+8g -o "$WORK"/path/_obj/_go_.8 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.8
+cp "$WORK"/path.a "$GOROOT"/pkg/linux_386/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+8g -o "$WORK"/go/build/_obj/_go_.8 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.8
+cp "$WORK"/go/build.a "$GOROOT"/pkg/linux_386/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+8g -o "$WORK"/os/exec/_obj/_go_.8 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/linux_386/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+8g -o "$WORK"/regexp/syntax/_obj/_go_.8 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/linux_386/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+8g -o "$WORK"/regexp/_obj/_go_.8 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.8
+cp "$WORK"/regexp.a "$GOROOT"/pkg/linux_386/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+8g -o "$WORK"/net/url/_obj/_go_.8 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/linux_386/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+8g -o "$WORK"/text/template/parse/_obj/_go_.8 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/linux_386/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+8g -o "$WORK"/text/template/_obj/_go_.8 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/linux_386/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/linux_386/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+8g -o "$WORK"/cmd/go/_obj/_go_.8 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.8
+8l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/linux_amd64.sh b/src/buildscript/linux_amd64.sh
new file mode 100755
index 0000000..4786f61
--- /dev/null
+++ b/src/buildscript/linux_amd64.sh
@@ -0,0 +1,497 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=linux
+export GOARCH=amd64
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+6g -o "$WORK"/runtime/_obj/_go_.6 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_amd64.go ./zgoos_linux.go ./zruntime_defs_linux_amd64.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_amd64.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_linux_amd64.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_linux.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_linux.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_linux_amd64.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/alg.6 -DGOOS_linux -DGOARCH_amd64 ./alg.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/atomic_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./atomic_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/cgocall.6 -DGOOS_linux -DGOARCH_amd64 ./cgocall.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/chan.6 -DGOOS_linux -DGOARCH_amd64 ./chan.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/closure_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./closure_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/complex.6 -DGOOS_linux -DGOARCH_amd64 ./complex.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/cpuprof.6 -DGOOS_linux -DGOARCH_amd64 ./cpuprof.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/float.6 -DGOOS_linux -DGOARCH_amd64 ./float.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/hashmap.6 -DGOOS_linux -DGOARCH_amd64 ./hashmap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/iface.6 -DGOOS_linux -DGOARCH_amd64 ./iface.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/lock_futex.6 -DGOOS_linux -DGOARCH_amd64 ./lock_futex.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/mcache.6 -DGOOS_linux -DGOARCH_amd64 ./mcache.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/mcentral.6 -DGOOS_linux -DGOARCH_amd64 ./mcentral.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/mem_linux.6 -DGOOS_linux -DGOARCH_amd64 ./mem_linux.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/mfinal.6 -DGOOS_linux -DGOARCH_amd64 ./mfinal.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/mfixalloc.6 -DGOOS_linux -DGOARCH_amd64 ./mfixalloc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/mgc0.6 -DGOOS_linux -DGOARCH_amd64 ./mgc0.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/mheap.6 -DGOOS_linux -DGOARCH_amd64 ./mheap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/msize.6 -DGOOS_linux -DGOARCH_amd64 ./msize.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/print.6 -DGOOS_linux -DGOARCH_amd64 ./print.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/proc.6 -DGOOS_linux -DGOARCH_amd64 ./proc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/rune.6 -DGOOS_linux -DGOARCH_amd64 ./rune.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/runtime.6 -DGOOS_linux -DGOARCH_amd64 ./runtime.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/signal_linux_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./signal_linux_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/slice.6 -DGOOS_linux -DGOARCH_amd64 ./slice.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/symtab.6 -DGOOS_linux -DGOARCH_amd64 ./symtab.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/thread_linux.6 -DGOOS_linux -DGOARCH_amd64 ./thread_linux.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/traceback_x86.6 -DGOOS_linux -DGOARCH_amd64 ./traceback_x86.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/zmalloc_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./zmalloc_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/zmprof_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./zmprof_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/zruntime1_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./zruntime1_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/zsema_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./zsema_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/zsigqueue_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./zsigqueue_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/zstring_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./zstring_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_amd64 -o "$WORK"/runtime/_obj/ztime_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./ztime_amd64.c
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./asm_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./memmove_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_linux_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./rt0_linux_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_linux_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./sys_linux_amd64.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.6 "$WORK"/runtime/_obj/alg.6 "$WORK"/runtime/_obj/atomic_amd64.6 "$WORK"/runtime/_obj/cgocall.6 "$WORK"/runtime/_obj/chan.6 "$WORK"/runtime/_obj/closure_amd64.6 "$WORK"/runtime/_obj/complex.6 "$WORK"/runtime/_obj/cpuprof.6 "$WORK"/runtime/_obj/float.6 "$WORK"/runtime/_obj/hashmap.6 "$WORK"/runtime/_obj/iface.6 "$WORK"/runtime/_obj/lock_futex.6 "$WORK"/runtime/_obj/mcache.6 "$WORK"/runtime/_obj/mcentral.6 "$WORK"/runtime/_obj/mem_linux.6 "$WORK"/runtime/_obj/mfinal.6 "$WORK"/runtime/_obj/mfixalloc.6 "$WORK"/runtime/_obj/mgc0.6 "$WORK"/runtime/_obj/mheap.6 "$WORK"/runtime/_obj/msize.6 "$WORK"/runtime/_obj/print.6 "$WORK"/runtime/_obj/proc.6 "$WORK"/runtime/_obj/rune.6 "$WORK"/runtime/_obj/runtime.6 "$WORK"/runtime/_obj/signal_linux_amd64.6 "$WORK"/runtime/_obj/slice.6 "$WORK"/runtime/_obj/symtab.6 "$WORK"/runtime/_obj/thread_linux.6 "$WORK"/runtime/_obj/traceback_x86.6 "$WORK"/runtime/_obj/zmalloc_amd64.6 "$WORK"/runtime/_obj/zmprof_amd64.6 "$WORK"/runtime/_obj/zruntime1_amd64.6 "$WORK"/runtime/_obj/zsema_amd64.6 "$WORK"/runtime/_obj/zsigqueue_amd64.6 "$WORK"/runtime/_obj/zstring_amd64.6 "$WORK"/runtime/_obj/ztime_amd64.6 "$WORK"/runtime/_obj/asm_amd64.6 "$WORK"/runtime/_obj/memmove_amd64.6 "$WORK"/runtime/_obj/rt0_linux_amd64.6 "$WORK"/runtime/_obj/sys_linux_amd64.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/linux_amd64/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+6g -o "$WORK"/errors/_obj/_go_.6 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.6
+cp "$WORK"/errors.a "$GOROOT"/pkg/linux_amd64/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+6g -o "$WORK"/sync/atomic/_obj/_go_.6 -p sync/atomic -I "$WORK" ./doc.go
+6a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.6 "$WORK"/sync/atomic/_obj/asm_amd64.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/linux_amd64/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+6g -o "$WORK"/sync/_obj/_go_.6 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.6
+cp "$WORK"/sync.a "$GOROOT"/pkg/linux_amd64/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+6g -o "$WORK"/io/_obj/_go_.6 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.6
+cp "$WORK"/io.a "$GOROOT"/pkg/linux_amd64/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+6g -o "$WORK"/unicode/_obj/_go_.6 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.6
+cp "$WORK"/unicode.a "$GOROOT"/pkg/linux_amd64/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+6g -o "$WORK"/unicode/utf8/_obj/_go_.6 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/linux_amd64/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+6g -o "$WORK"/bytes/_obj/_go_.6 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+6a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.6 "$WORK"/bytes/_obj/asm_amd64.6
+cp "$WORK"/bytes.a "$GOROOT"/pkg/linux_amd64/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+6g -o "$WORK"/math/_obj/_go_.6 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./abs_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./asin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./atan2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./atan_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./dim_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./exp2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./exp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./expm1_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./floor_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/fltasm_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./fltasm_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./frexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./hypot_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./ldexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./log10_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./log1p_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./log_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./mod_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./modf_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./remainder_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./sin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./sincos_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./sqrt_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./tan_amd64.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.6 "$WORK"/math/_obj/abs_amd64.6 "$WORK"/math/_obj/asin_amd64.6 "$WORK"/math/_obj/atan2_amd64.6 "$WORK"/math/_obj/atan_amd64.6 "$WORK"/math/_obj/dim_amd64.6 "$WORK"/math/_obj/exp2_amd64.6 "$WORK"/math/_obj/exp_amd64.6 "$WORK"/math/_obj/expm1_amd64.6 "$WORK"/math/_obj/floor_amd64.6 "$WORK"/math/_obj/fltasm_amd64.6 "$WORK"/math/_obj/frexp_amd64.6 "$WORK"/math/_obj/hypot_amd64.6 "$WORK"/math/_obj/ldexp_amd64.6 "$WORK"/math/_obj/log10_amd64.6 "$WORK"/math/_obj/log1p_amd64.6 "$WORK"/math/_obj/log_amd64.6 "$WORK"/math/_obj/mod_amd64.6 "$WORK"/math/_obj/modf_amd64.6 "$WORK"/math/_obj/remainder_amd64.6 "$WORK"/math/_obj/sin_amd64.6 "$WORK"/math/_obj/sincos_amd64.6 "$WORK"/math/_obj/sqrt_amd64.6 "$WORK"/math/_obj/tan_amd64.6
+cp "$WORK"/math.a "$GOROOT"/pkg/linux_amd64/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+6g -o "$WORK"/sort/_obj/_go_.6 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.6
+cp "$WORK"/sort.a "$GOROOT"/pkg/linux_amd64/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+6g -o "$WORK"/container/heap/_obj/_go_.6 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/linux_amd64/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+6g -o "$WORK"/strings/_obj/_go_.6 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.6
+cp "$WORK"/strings.a "$GOROOT"/pkg/linux_amd64/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+6g -o "$WORK"/strconv/_obj/_go_.6 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.6
+cp "$WORK"/strconv.a "$GOROOT"/pkg/linux_amd64/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+6g -o "$WORK"/encoding/base64/_obj/_go_.6 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/linux_amd64/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+6g -o "$WORK"/syscall/_obj/_go_.6 -p syscall -I "$WORK" ./env_unix.go ./exec_linux.go ./exec_unix.go ./lsf_linux.go ./netlink_linux.go ./sockcmsg_linux.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_linux.go ./syscall_linux_amd64.go ./syscall_unix.go ./zerrors_linux_amd64.go ./zsyscall_linux_amd64.go ./zsysnum_linux_amd64.go ./ztypes_linux_amd64.go
+6a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_linux_amd64.6 -DGOOS_linux -DGOARCH_amd64 ./asm_linux_amd64.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.6 "$WORK"/syscall/_obj/asm_linux_amd64.6
+cp "$WORK"/syscall.a "$GOROOT"/pkg/linux_amd64/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+6g -o "$WORK"/time/_obj/_go_.6 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.6
+cp "$WORK"/time.a "$GOROOT"/pkg/linux_amd64/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+6g -o "$WORK"/os/_obj/_go_.6 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_linux.go ./sys_linux.go ./time.go ./types.go ./zsignal_linux_amd64.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.6
+cp "$WORK"/os.a "$GOROOT"/pkg/linux_amd64/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+6g -o "$WORK"/reflect/_obj/_go_.6 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.6
+cp "$WORK"/reflect.a "$GOROOT"/pkg/linux_amd64/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+6g -o "$WORK"/fmt/_obj/_go_.6 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.6
+cp "$WORK"/fmt.a "$GOROOT"/pkg/linux_amd64/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+6g -o "$WORK"/unicode/utf16/_obj/_go_.6 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.6
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/linux_amd64/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+6g -o "$WORK"/encoding/json/_obj/_go_.6 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.6
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/linux_amd64/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+6g -o "$WORK"/flag/_obj/_go_.6 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.6
+cp "$WORK"/flag.a "$GOROOT"/pkg/linux_amd64/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+6g -o "$WORK"/bufio/_obj/_go_.6 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.6
+cp "$WORK"/bufio.a "$GOROOT"/pkg/linux_amd64/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+6g -o "$WORK"/encoding/gob/_obj/_go_.6 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.6
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/linux_amd64/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+6g -o "$WORK"/go/token/_obj/_go_.6 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/linux_amd64/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+6g -o "$WORK"/path/filepath/_obj/_go_.6 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/linux_amd64/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+6g -o "$WORK"/go/scanner/_obj/_go_.6 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.6
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/linux_amd64/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+6g -o "$WORK"/go/ast/_obj/_go_.6 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.6
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/linux_amd64/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+6g -o "$WORK"/io/ioutil/_obj/_go_.6 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/linux_amd64/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+6g -o "$WORK"/go/parser/_obj/_go_.6 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.6
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/linux_amd64/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+6g -o "$WORK"/log/_obj/_go_.6 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.6
+cp "$WORK"/log.a "$GOROOT"/pkg/linux_amd64/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+6g -o "$WORK"/path/_obj/_go_.6 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.6
+cp "$WORK"/path.a "$GOROOT"/pkg/linux_amd64/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+6g -o "$WORK"/go/build/_obj/_go_.6 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.6
+cp "$WORK"/go/build.a "$GOROOT"/pkg/linux_amd64/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+6g -o "$WORK"/os/exec/_obj/_go_.6 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/linux_amd64/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+6g -o "$WORK"/regexp/syntax/_obj/_go_.6 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/linux_amd64/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+6g -o "$WORK"/regexp/_obj/_go_.6 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.6
+cp "$WORK"/regexp.a "$GOROOT"/pkg/linux_amd64/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+6g -o "$WORK"/net/url/_obj/_go_.6 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/linux_amd64/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+6g -o "$WORK"/text/template/parse/_obj/_go_.6 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/linux_amd64/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+6g -o "$WORK"/text/template/_obj/_go_.6 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/linux_amd64/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/linux_amd64/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+6g -o "$WORK"/cmd/go/_obj/_go_.6 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.6
+6l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/linux_arm.sh b/src/buildscript/linux_arm.sh
new file mode 100755
index 0000000..bfa8143
--- /dev/null
+++ b/src/buildscript/linux_arm.sh
@@ -0,0 +1,501 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=linux
+export GOARCH=arm
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+5g -o "$WORK"/runtime/_obj/_go_.5 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_arm.go ./zgoos_linux.go ./zruntime_defs_linux_arm.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_arm.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_linux_arm.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_linux.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_linux.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_linux_arm.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/alg.5 -DGOOS_linux -DGOARCH_arm ./alg.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/atomic_arm.5 -DGOOS_linux -DGOARCH_arm ./atomic_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/cgocall.5 -DGOOS_linux -DGOARCH_arm ./cgocall.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/chan.5 -DGOOS_linux -DGOARCH_arm ./chan.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/closure_arm.5 -DGOOS_linux -DGOARCH_arm ./closure_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/complex.5 -DGOOS_linux -DGOARCH_arm ./complex.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/cpuprof.5 -DGOOS_linux -DGOARCH_arm ./cpuprof.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/float.5 -DGOOS_linux -DGOARCH_arm ./float.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/hashmap.5 -DGOOS_linux -DGOARCH_arm ./hashmap.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/iface.5 -DGOOS_linux -DGOARCH_arm ./iface.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/lock_futex.5 -DGOOS_linux -DGOARCH_arm ./lock_futex.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/mcache.5 -DGOOS_linux -DGOARCH_arm ./mcache.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/mcentral.5 -DGOOS_linux -DGOARCH_arm ./mcentral.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/mem_linux.5 -DGOOS_linux -DGOARCH_arm ./mem_linux.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/mfinal.5 -DGOOS_linux -DGOARCH_arm ./mfinal.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/mfixalloc.5 -DGOOS_linux -DGOARCH_arm ./mfixalloc.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/mgc0.5 -DGOOS_linux -DGOARCH_arm ./mgc0.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/mheap.5 -DGOOS_linux -DGOARCH_arm ./mheap.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/msize.5 -DGOOS_linux -DGOARCH_arm ./msize.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/print.5 -DGOOS_linux -DGOARCH_arm ./print.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/proc.5 -DGOOS_linux -DGOARCH_arm ./proc.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/rune.5 -DGOOS_linux -DGOARCH_arm ./rune.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/runtime.5 -DGOOS_linux -DGOARCH_arm ./runtime.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/signal_linux_arm.5 -DGOOS_linux -DGOARCH_arm ./signal_linux_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/slice.5 -DGOOS_linux -DGOARCH_arm ./slice.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/softfloat_arm.5 -DGOOS_linux -DGOARCH_arm ./softfloat_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/symtab.5 -DGOOS_linux -DGOARCH_arm ./symtab.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/thread_linux.5 -DGOOS_linux -DGOARCH_arm ./thread_linux.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/traceback_arm.5 -DGOOS_linux -DGOARCH_arm ./traceback_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/vlrt_arm.5 -DGOOS_linux -DGOARCH_arm ./vlrt_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/zmalloc_arm.5 -DGOOS_linux -DGOARCH_arm ./zmalloc_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/zmprof_arm.5 -DGOOS_linux -DGOARCH_arm ./zmprof_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/zruntime1_arm.5 -DGOOS_linux -DGOARCH_arm ./zruntime1_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/zsema_arm.5 -DGOOS_linux -DGOARCH_arm ./zsema_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/zsigqueue_arm.5 -DGOOS_linux -DGOARCH_arm ./zsigqueue_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/zstring_arm.5 -DGOOS_linux -DGOARCH_arm ./zstring_arm.c
+5c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/linux_arm -o "$WORK"/runtime/_obj/ztime_arm.5 -DGOOS_linux -DGOARCH_arm ./ztime_arm.c
+5a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_arm.5 -DGOOS_linux -DGOARCH_arm ./asm_arm.s
+5a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_arm.5 -DGOOS_linux -DGOARCH_arm ./memmove_arm.s
+5a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memset_arm.5 -DGOOS_linux -DGOARCH_arm ./memset_arm.s
+5a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_linux_arm.5 -DGOOS_linux -DGOARCH_arm ./rt0_linux_arm.s
+5a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_linux_arm.5 -DGOOS_linux -DGOARCH_arm ./sys_linux_arm.s
+5a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/vlop_arm.5 -DGOOS_linux -DGOARCH_arm ./vlop_arm.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.5 "$WORK"/runtime/_obj/alg.5 "$WORK"/runtime/_obj/atomic_arm.5 "$WORK"/runtime/_obj/cgocall.5 "$WORK"/runtime/_obj/chan.5 "$WORK"/runtime/_obj/closure_arm.5 "$WORK"/runtime/_obj/complex.5 "$WORK"/runtime/_obj/cpuprof.5 "$WORK"/runtime/_obj/float.5 "$WORK"/runtime/_obj/hashmap.5 "$WORK"/runtime/_obj/iface.5 "$WORK"/runtime/_obj/lock_futex.5 "$WORK"/runtime/_obj/mcache.5 "$WORK"/runtime/_obj/mcentral.5 "$WORK"/runtime/_obj/mem_linux.5 "$WORK"/runtime/_obj/mfinal.5 "$WORK"/runtime/_obj/mfixalloc.5 "$WORK"/runtime/_obj/mgc0.5 "$WORK"/runtime/_obj/mheap.5 "$WORK"/runtime/_obj/msize.5 "$WORK"/runtime/_obj/print.5 "$WORK"/runtime/_obj/proc.5 "$WORK"/runtime/_obj/rune.5 "$WORK"/runtime/_obj/runtime.5 "$WORK"/runtime/_obj/signal_linux_arm.5 "$WORK"/runtime/_obj/slice.5 "$WORK"/runtime/_obj/softfloat_arm.5 "$WORK"/runtime/_obj/symtab.5 "$WORK"/runtime/_obj/thread_linux.5 "$WORK"/runtime/_obj/traceback_arm.5 "$WORK"/runtime/_obj/vlrt_arm.5 "$WORK"/runtime/_obj/zmalloc_arm.5 "$WORK"/runtime/_obj/zmprof_arm.5 "$WORK"/runtime/_obj/zruntime1_arm.5 "$WORK"/runtime/_obj/zsema_arm.5 "$WORK"/runtime/_obj/zsigqueue_arm.5 "$WORK"/runtime/_obj/zstring_arm.5 "$WORK"/runtime/_obj/ztime_arm.5 "$WORK"/runtime/_obj/asm_arm.5 "$WORK"/runtime/_obj/memmove_arm.5 "$WORK"/runtime/_obj/memset_arm.5 "$WORK"/runtime/_obj/rt0_linux_arm.5 "$WORK"/runtime/_obj/sys_linux_arm.5 "$WORK"/runtime/_obj/vlop_arm.5
+mkdir -p "$GOROOT"/pkg/linux_arm/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/linux_arm/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+5g -o "$WORK"/errors/_obj/_go_.5 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.5
+cp "$WORK"/errors.a "$GOROOT"/pkg/linux_arm/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+5g -o "$WORK"/sync/atomic/_obj/_go_.5 -p sync/atomic -I "$WORK" ./doc.go
+5a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_arm.5 -DGOOS_linux -DGOARCH_arm ./asm_arm.s
+5a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_linux_arm.5 -DGOOS_linux -DGOARCH_arm ./asm_linux_arm.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.5 "$WORK"/sync/atomic/_obj/asm_arm.5 "$WORK"/sync/atomic/_obj/asm_linux_arm.5
+mkdir -p "$GOROOT"/pkg/linux_arm/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/linux_arm/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+5g -o "$WORK"/sync/_obj/_go_.5 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.5
+cp "$WORK"/sync.a "$GOROOT"/pkg/linux_arm/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+5g -o "$WORK"/io/_obj/_go_.5 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.5
+cp "$WORK"/io.a "$GOROOT"/pkg/linux_arm/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+5g -o "$WORK"/unicode/_obj/_go_.5 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.5
+cp "$WORK"/unicode.a "$GOROOT"/pkg/linux_arm/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+5g -o "$WORK"/unicode/utf8/_obj/_go_.5 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/linux_arm/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+5g -o "$WORK"/bytes/_obj/_go_.5 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+5a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_arm.5 -DGOOS_linux -DGOARCH_arm ./asm_arm.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.5 "$WORK"/bytes/_obj/asm_arm.5
+cp "$WORK"/bytes.a "$GOROOT"/pkg/linux_arm/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+5g -o "$WORK"/math/_obj/_go_.5 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_arm.5 -DGOOS_linux -DGOARCH_arm ./abs_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_arm.5 -DGOOS_linux -DGOARCH_arm ./asin_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_arm.5 -DGOOS_linux -DGOARCH_arm ./atan2_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_arm.5 -DGOOS_linux -DGOARCH_arm ./atan_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_arm.5 -DGOOS_linux -DGOARCH_arm ./dim_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_arm.5 -DGOOS_linux -DGOARCH_arm ./exp2_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_arm.5 -DGOOS_linux -DGOARCH_arm ./exp_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_arm.5 -DGOOS_linux -DGOARCH_arm ./expm1_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_arm.5 -DGOOS_linux -DGOARCH_arm ./floor_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_arm.5 -DGOOS_linux -DGOARCH_arm ./frexp_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_arm.5 -DGOOS_linux -DGOARCH_arm ./hypot_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_arm.5 -DGOOS_linux -DGOARCH_arm ./ldexp_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_arm.5 -DGOOS_linux -DGOARCH_arm ./log10_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_arm.5 -DGOOS_linux -DGOARCH_arm ./log1p_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_arm.5 -DGOOS_linux -DGOARCH_arm ./log_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_arm.5 -DGOOS_linux -DGOARCH_arm ./mod_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_arm.5 -DGOOS_linux -DGOARCH_arm ./modf_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_arm.5 -DGOOS_linux -DGOARCH_arm ./remainder_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_arm.5 -DGOOS_linux -DGOARCH_arm ./sin_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_arm.5 -DGOOS_linux -DGOARCH_arm ./sincos_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_arm.5 -DGOOS_linux -DGOARCH_arm ./sqrt_arm.s
+5a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_arm.5 -DGOOS_linux -DGOARCH_arm ./tan_arm.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.5 "$WORK"/math/_obj/abs_arm.5 "$WORK"/math/_obj/asin_arm.5 "$WORK"/math/_obj/atan2_arm.5 "$WORK"/math/_obj/atan_arm.5 "$WORK"/math/_obj/dim_arm.5 "$WORK"/math/_obj/exp2_arm.5 "$WORK"/math/_obj/exp_arm.5 "$WORK"/math/_obj/expm1_arm.5 "$WORK"/math/_obj/floor_arm.5 "$WORK"/math/_obj/frexp_arm.5 "$WORK"/math/_obj/hypot_arm.5 "$WORK"/math/_obj/ldexp_arm.5 "$WORK"/math/_obj/log10_arm.5 "$WORK"/math/_obj/log1p_arm.5 "$WORK"/math/_obj/log_arm.5 "$WORK"/math/_obj/mod_arm.5 "$WORK"/math/_obj/modf_arm.5 "$WORK"/math/_obj/remainder_arm.5 "$WORK"/math/_obj/sin_arm.5 "$WORK"/math/_obj/sincos_arm.5 "$WORK"/math/_obj/sqrt_arm.5 "$WORK"/math/_obj/tan_arm.5
+cp "$WORK"/math.a "$GOROOT"/pkg/linux_arm/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+5g -o "$WORK"/sort/_obj/_go_.5 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.5
+cp "$WORK"/sort.a "$GOROOT"/pkg/linux_arm/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+5g -o "$WORK"/container/heap/_obj/_go_.5 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/linux_arm/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+5g -o "$WORK"/strings/_obj/_go_.5 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.5
+cp "$WORK"/strings.a "$GOROOT"/pkg/linux_arm/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+5g -o "$WORK"/strconv/_obj/_go_.5 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.5
+cp "$WORK"/strconv.a "$GOROOT"/pkg/linux_arm/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+5g -o "$WORK"/encoding/base64/_obj/_go_.5 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/linux_arm/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+5g -o "$WORK"/syscall/_obj/_go_.5 -p syscall -I "$WORK" ./env_unix.go ./exec_linux.go ./exec_unix.go ./lsf_linux.go ./netlink_linux.go ./sockcmsg_linux.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_linux.go ./syscall_linux_arm.go ./syscall_unix.go ./zerrors_linux_arm.go ./zsyscall_linux_arm.go ./zsysnum_linux_arm.go ./ztypes_linux_arm.go
+5a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_linux_arm.5 -DGOOS_linux -DGOARCH_arm ./asm_linux_arm.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.5 "$WORK"/syscall/_obj/asm_linux_arm.5
+cp "$WORK"/syscall.a "$GOROOT"/pkg/linux_arm/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+5g -o "$WORK"/time/_obj/_go_.5 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.5
+cp "$WORK"/time.a "$GOROOT"/pkg/linux_arm/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+5g -o "$WORK"/os/_obj/_go_.5 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_linux.go ./sys_linux.go ./time.go ./types.go ./zsignal_linux_arm.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.5
+cp "$WORK"/os.a "$GOROOT"/pkg/linux_arm/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+5g -o "$WORK"/reflect/_obj/_go_.5 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.5
+cp "$WORK"/reflect.a "$GOROOT"/pkg/linux_arm/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+5g -o "$WORK"/fmt/_obj/_go_.5 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.5
+cp "$WORK"/fmt.a "$GOROOT"/pkg/linux_arm/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+5g -o "$WORK"/unicode/utf16/_obj/_go_.5 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.5
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/linux_arm/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+5g -o "$WORK"/encoding/json/_obj/_go_.5 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.5
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/linux_arm/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+5g -o "$WORK"/flag/_obj/_go_.5 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.5
+cp "$WORK"/flag.a "$GOROOT"/pkg/linux_arm/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+5g -o "$WORK"/bufio/_obj/_go_.5 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.5
+cp "$WORK"/bufio.a "$GOROOT"/pkg/linux_arm/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+5g -o "$WORK"/encoding/gob/_obj/_go_.5 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.5
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/linux_arm/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+5g -o "$WORK"/go/token/_obj/_go_.5 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/linux_arm/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+5g -o "$WORK"/path/filepath/_obj/_go_.5 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/linux_arm/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+5g -o "$WORK"/go/scanner/_obj/_go_.5 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.5
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/linux_arm/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+5g -o "$WORK"/go/ast/_obj/_go_.5 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.5
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/linux_arm/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+5g -o "$WORK"/io/ioutil/_obj/_go_.5 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/linux_arm/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+5g -o "$WORK"/go/parser/_obj/_go_.5 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.5
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/linux_arm/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+5g -o "$WORK"/log/_obj/_go_.5 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.5
+cp "$WORK"/log.a "$GOROOT"/pkg/linux_arm/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+5g -o "$WORK"/path/_obj/_go_.5 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.5
+cp "$WORK"/path.a "$GOROOT"/pkg/linux_arm/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+5g -o "$WORK"/go/build/_obj/_go_.5 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.5
+cp "$WORK"/go/build.a "$GOROOT"/pkg/linux_arm/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+5g -o "$WORK"/os/exec/_obj/_go_.5 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/linux_arm/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+5g -o "$WORK"/regexp/syntax/_obj/_go_.5 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/linux_arm/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+5g -o "$WORK"/regexp/_obj/_go_.5 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.5
+cp "$WORK"/regexp.a "$GOROOT"/pkg/linux_arm/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+5g -o "$WORK"/net/url/_obj/_go_.5 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/linux_arm/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+5g -o "$WORK"/text/template/parse/_obj/_go_.5 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/linux_arm/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+5g -o "$WORK"/text/template/_obj/_go_.5 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.5
+mkdir -p "$GOROOT"/pkg/linux_arm/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/linux_arm/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+5g -o "$WORK"/cmd/go/_obj/_go_.5 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.5
+5l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/netbsd_386.sh b/src/buildscript/netbsd_386.sh
new file mode 100755
index 0000000..6235a2f
--- /dev/null
+++ b/src/buildscript/netbsd_386.sh
@@ -0,0 +1,498 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=netbsd
+export GOARCH=386
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+8g -o "$WORK"/runtime/_obj/_go_.8 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_386.go ./zgoos_netbsd.go ./zruntime_defs_netbsd_386.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_386.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_netbsd_386.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_netbsd.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_netbsd.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_netbsd_386.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/alg.8 -DGOOS_netbsd -DGOARCH_386 ./alg.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/atomic_386.8 -DGOOS_netbsd -DGOARCH_386 ./atomic_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/cgocall.8 -DGOOS_netbsd -DGOARCH_386 ./cgocall.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/chan.8 -DGOOS_netbsd -DGOARCH_386 ./chan.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/closure_386.8 -DGOOS_netbsd -DGOARCH_386 ./closure_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/complex.8 -DGOOS_netbsd -DGOARCH_386 ./complex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/cpuprof.8 -DGOOS_netbsd -DGOARCH_386 ./cpuprof.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/float.8 -DGOOS_netbsd -DGOARCH_386 ./float.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/hashmap.8 -DGOOS_netbsd -DGOARCH_386 ./hashmap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/iface.8 -DGOOS_netbsd -DGOARCH_386 ./iface.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/lock_sema.8 -DGOOS_netbsd -DGOARCH_386 ./lock_sema.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/mcache.8 -DGOOS_netbsd -DGOARCH_386 ./mcache.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/mcentral.8 -DGOOS_netbsd -DGOARCH_386 ./mcentral.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/mem_netbsd.8 -DGOOS_netbsd -DGOARCH_386 ./mem_netbsd.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/mfinal.8 -DGOOS_netbsd -DGOARCH_386 ./mfinal.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/mfixalloc.8 -DGOOS_netbsd -DGOARCH_386 ./mfixalloc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/mgc0.8 -DGOOS_netbsd -DGOARCH_386 ./mgc0.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/mheap.8 -DGOOS_netbsd -DGOARCH_386 ./mheap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/msize.8 -DGOOS_netbsd -DGOARCH_386 ./msize.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/print.8 -DGOOS_netbsd -DGOARCH_386 ./print.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/proc.8 -DGOOS_netbsd -DGOARCH_386 ./proc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/rune.8 -DGOOS_netbsd -DGOARCH_386 ./rune.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/runtime.8 -DGOOS_netbsd -DGOARCH_386 ./runtime.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/signal_netbsd_386.8 -DGOOS_netbsd -DGOARCH_386 ./signal_netbsd_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/slice.8 -DGOOS_netbsd -DGOARCH_386 ./slice.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/symtab.8 -DGOOS_netbsd -DGOARCH_386 ./symtab.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/thread_netbsd.8 -DGOOS_netbsd -DGOARCH_386 ./thread_netbsd.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/traceback_x86.8 -DGOOS_netbsd -DGOARCH_386 ./traceback_x86.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/vlrt_386.8 -DGOOS_netbsd -DGOARCH_386 ./vlrt_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/zmalloc_386.8 -DGOOS_netbsd -DGOARCH_386 ./zmalloc_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/zmprof_386.8 -DGOOS_netbsd -DGOARCH_386 ./zmprof_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/zruntime1_386.8 -DGOOS_netbsd -DGOARCH_386 ./zruntime1_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/zsema_386.8 -DGOOS_netbsd -DGOARCH_386 ./zsema_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/zsigqueue_386.8 -DGOOS_netbsd -DGOARCH_386 ./zsigqueue_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/zstring_386.8 -DGOOS_netbsd -DGOARCH_386 ./zstring_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_386 -o "$WORK"/runtime/_obj/ztime_386.8 -DGOOS_netbsd -DGOARCH_386 ./ztime_386.c
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_386.8 -DGOOS_netbsd -DGOARCH_386 ./asm_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_386.8 -DGOOS_netbsd -DGOARCH_386 ./memmove_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_netbsd_386.8 -DGOOS_netbsd -DGOARCH_386 ./rt0_netbsd_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_netbsd_386.8 -DGOOS_netbsd -DGOARCH_386 ./sys_netbsd_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/vlop_386.8 -DGOOS_netbsd -DGOARCH_386 ./vlop_386.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.8 "$WORK"/runtime/_obj/alg.8 "$WORK"/runtime/_obj/atomic_386.8 "$WORK"/runtime/_obj/cgocall.8 "$WORK"/runtime/_obj/chan.8 "$WORK"/runtime/_obj/closure_386.8 "$WORK"/runtime/_obj/complex.8 "$WORK"/runtime/_obj/cpuprof.8 "$WORK"/runtime/_obj/float.8 "$WORK"/runtime/_obj/hashmap.8 "$WORK"/runtime/_obj/iface.8 "$WORK"/runtime/_obj/lock_sema.8 "$WORK"/runtime/_obj/mcache.8 "$WORK"/runtime/_obj/mcentral.8 "$WORK"/runtime/_obj/mem_netbsd.8 "$WORK"/runtime/_obj/mfinal.8 "$WORK"/runtime/_obj/mfixalloc.8 "$WORK"/runtime/_obj/mgc0.8 "$WORK"/runtime/_obj/mheap.8 "$WORK"/runtime/_obj/msize.8 "$WORK"/runtime/_obj/print.8 "$WORK"/runtime/_obj/proc.8 "$WORK"/runtime/_obj/rune.8 "$WORK"/runtime/_obj/runtime.8 "$WORK"/runtime/_obj/signal_netbsd_386.8 "$WORK"/runtime/_obj/slice.8 "$WORK"/runtime/_obj/symtab.8 "$WORK"/runtime/_obj/thread_netbsd.8 "$WORK"/runtime/_obj/traceback_x86.8 "$WORK"/runtime/_obj/vlrt_386.8 "$WORK"/runtime/_obj/zmalloc_386.8 "$WORK"/runtime/_obj/zmprof_386.8 "$WORK"/runtime/_obj/zruntime1_386.8 "$WORK"/runtime/_obj/zsema_386.8 "$WORK"/runtime/_obj/zsigqueue_386.8 "$WORK"/runtime/_obj/zstring_386.8 "$WORK"/runtime/_obj/ztime_386.8 "$WORK"/runtime/_obj/asm_386.8 "$WORK"/runtime/_obj/memmove_386.8 "$WORK"/runtime/_obj/rt0_netbsd_386.8 "$WORK"/runtime/_obj/sys_netbsd_386.8 "$WORK"/runtime/_obj/vlop_386.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/netbsd_386/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+8g -o "$WORK"/errors/_obj/_go_.8 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.8
+cp "$WORK"/errors.a "$GOROOT"/pkg/netbsd_386/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+8g -o "$WORK"/sync/atomic/_obj/_go_.8 -p sync/atomic -I "$WORK" ./doc.go
+8a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_386.8 -DGOOS_netbsd -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.8 "$WORK"/sync/atomic/_obj/asm_386.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/netbsd_386/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+8g -o "$WORK"/sync/_obj/_go_.8 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.8
+cp "$WORK"/sync.a "$GOROOT"/pkg/netbsd_386/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+8g -o "$WORK"/io/_obj/_go_.8 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.8
+cp "$WORK"/io.a "$GOROOT"/pkg/netbsd_386/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+8g -o "$WORK"/unicode/_obj/_go_.8 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.8
+cp "$WORK"/unicode.a "$GOROOT"/pkg/netbsd_386/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+8g -o "$WORK"/unicode/utf8/_obj/_go_.8 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/netbsd_386/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+8g -o "$WORK"/bytes/_obj/_go_.8 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+8a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_386.8 -DGOOS_netbsd -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.8 "$WORK"/bytes/_obj/asm_386.8
+cp "$WORK"/bytes.a "$GOROOT"/pkg/netbsd_386/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+8g -o "$WORK"/math/_obj/_go_.8 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_386.8 -DGOOS_netbsd -DGOARCH_386 ./abs_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_386.8 -DGOOS_netbsd -DGOARCH_386 ./asin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_386.8 -DGOOS_netbsd -DGOARCH_386 ./atan2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_386.8 -DGOOS_netbsd -DGOARCH_386 ./atan_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_386.8 -DGOOS_netbsd -DGOARCH_386 ./dim_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_386.8 -DGOOS_netbsd -DGOARCH_386 ./exp2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_386.8 -DGOOS_netbsd -DGOARCH_386 ./exp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_386.8 -DGOOS_netbsd -DGOARCH_386 ./expm1_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_386.8 -DGOOS_netbsd -DGOARCH_386 ./floor_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_386.8 -DGOOS_netbsd -DGOARCH_386 ./frexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_386.8 -DGOOS_netbsd -DGOARCH_386 ./hypot_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_386.8 -DGOOS_netbsd -DGOARCH_386 ./ldexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_386.8 -DGOOS_netbsd -DGOARCH_386 ./log10_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_386.8 -DGOOS_netbsd -DGOARCH_386 ./log1p_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_386.8 -DGOOS_netbsd -DGOARCH_386 ./log_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_386.8 -DGOOS_netbsd -DGOARCH_386 ./mod_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_386.8 -DGOOS_netbsd -DGOARCH_386 ./modf_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_386.8 -DGOOS_netbsd -DGOARCH_386 ./remainder_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_386.8 -DGOOS_netbsd -DGOARCH_386 ./sin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_386.8 -DGOOS_netbsd -DGOARCH_386 ./sincos_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_386.8 -DGOOS_netbsd -DGOARCH_386 ./sqrt_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_386.8 -DGOOS_netbsd -DGOARCH_386 ./tan_386.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.8 "$WORK"/math/_obj/abs_386.8 "$WORK"/math/_obj/asin_386.8 "$WORK"/math/_obj/atan2_386.8 "$WORK"/math/_obj/atan_386.8 "$WORK"/math/_obj/dim_386.8 "$WORK"/math/_obj/exp2_386.8 "$WORK"/math/_obj/exp_386.8 "$WORK"/math/_obj/expm1_386.8 "$WORK"/math/_obj/floor_386.8 "$WORK"/math/_obj/frexp_386.8 "$WORK"/math/_obj/hypot_386.8 "$WORK"/math/_obj/ldexp_386.8 "$WORK"/math/_obj/log10_386.8 "$WORK"/math/_obj/log1p_386.8 "$WORK"/math/_obj/log_386.8 "$WORK"/math/_obj/mod_386.8 "$WORK"/math/_obj/modf_386.8 "$WORK"/math/_obj/remainder_386.8 "$WORK"/math/_obj/sin_386.8 "$WORK"/math/_obj/sincos_386.8 "$WORK"/math/_obj/sqrt_386.8 "$WORK"/math/_obj/tan_386.8
+cp "$WORK"/math.a "$GOROOT"/pkg/netbsd_386/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+8g -o "$WORK"/sort/_obj/_go_.8 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.8
+cp "$WORK"/sort.a "$GOROOT"/pkg/netbsd_386/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+8g -o "$WORK"/container/heap/_obj/_go_.8 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/netbsd_386/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+8g -o "$WORK"/strings/_obj/_go_.8 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.8
+cp "$WORK"/strings.a "$GOROOT"/pkg/netbsd_386/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+8g -o "$WORK"/strconv/_obj/_go_.8 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.8
+cp "$WORK"/strconv.a "$GOROOT"/pkg/netbsd_386/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+8g -o "$WORK"/encoding/base64/_obj/_go_.8 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/netbsd_386/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_netbsd.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_netbsd.go ./syscall_netbsd_386.go ./syscall_unix.go ./zerrors_netbsd_386.go ./zsyscall_netbsd_386.go ./zsysnum_netbsd_386.go ./ztypes_netbsd_386.go
+8a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_netbsd_386.8 -DGOOS_netbsd -DGOARCH_386 ./asm_netbsd_386.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.8 "$WORK"/syscall/_obj/asm_netbsd_386.8
+cp "$WORK"/syscall.a "$GOROOT"/pkg/netbsd_386/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+8g -o "$WORK"/time/_obj/_go_.8 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.8
+cp "$WORK"/time.a "$GOROOT"/pkg/netbsd_386/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+8g -o "$WORK"/os/_obj/_go_.8 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_netbsd.go ./sys_bsd.go ./time.go ./types.go ./zsignal_netbsd_386.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.8
+cp "$WORK"/os.a "$GOROOT"/pkg/netbsd_386/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+8g -o "$WORK"/reflect/_obj/_go_.8 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.8
+cp "$WORK"/reflect.a "$GOROOT"/pkg/netbsd_386/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+8g -o "$WORK"/fmt/_obj/_go_.8 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.8
+cp "$WORK"/fmt.a "$GOROOT"/pkg/netbsd_386/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+8g -o "$WORK"/unicode/utf16/_obj/_go_.8 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.8
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/netbsd_386/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+8g -o "$WORK"/encoding/json/_obj/_go_.8 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.8
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/netbsd_386/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+8g -o "$WORK"/flag/_obj/_go_.8 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.8
+cp "$WORK"/flag.a "$GOROOT"/pkg/netbsd_386/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+8g -o "$WORK"/bufio/_obj/_go_.8 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.8
+cp "$WORK"/bufio.a "$GOROOT"/pkg/netbsd_386/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+8g -o "$WORK"/encoding/gob/_obj/_go_.8 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.8
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/netbsd_386/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+8g -o "$WORK"/go/token/_obj/_go_.8 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/netbsd_386/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+8g -o "$WORK"/path/filepath/_obj/_go_.8 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/netbsd_386/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+8g -o "$WORK"/go/scanner/_obj/_go_.8 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.8
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/netbsd_386/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+8g -o "$WORK"/go/ast/_obj/_go_.8 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.8
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/netbsd_386/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+8g -o "$WORK"/io/ioutil/_obj/_go_.8 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/netbsd_386/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+8g -o "$WORK"/go/parser/_obj/_go_.8 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.8
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/netbsd_386/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+8g -o "$WORK"/log/_obj/_go_.8 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.8
+cp "$WORK"/log.a "$GOROOT"/pkg/netbsd_386/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+8g -o "$WORK"/path/_obj/_go_.8 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.8
+cp "$WORK"/path.a "$GOROOT"/pkg/netbsd_386/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+8g -o "$WORK"/go/build/_obj/_go_.8 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.8
+cp "$WORK"/go/build.a "$GOROOT"/pkg/netbsd_386/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+8g -o "$WORK"/os/exec/_obj/_go_.8 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/netbsd_386/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+8g -o "$WORK"/regexp/syntax/_obj/_go_.8 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/netbsd_386/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+8g -o "$WORK"/regexp/_obj/_go_.8 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.8
+cp "$WORK"/regexp.a "$GOROOT"/pkg/netbsd_386/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+8g -o "$WORK"/net/url/_obj/_go_.8 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/netbsd_386/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+8g -o "$WORK"/text/template/parse/_obj/_go_.8 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/netbsd_386/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+8g -o "$WORK"/text/template/_obj/_go_.8 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/netbsd_386/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/netbsd_386/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+8g -o "$WORK"/cmd/go/_obj/_go_.8 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.8
+8l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/netbsd_amd64.sh b/src/buildscript/netbsd_amd64.sh
new file mode 100755
index 0000000..cf4c91a
--- /dev/null
+++ b/src/buildscript/netbsd_amd64.sh
@@ -0,0 +1,497 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=netbsd
+export GOARCH=amd64
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+6g -o "$WORK"/runtime/_obj/_go_.6 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_amd64.go ./zgoos_netbsd.go ./zruntime_defs_netbsd_amd64.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_amd64.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_netbsd_amd64.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_netbsd.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_netbsd.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_netbsd_amd64.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/alg.6 -DGOOS_netbsd -DGOARCH_amd64 ./alg.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/atomic_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./atomic_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/cgocall.6 -DGOOS_netbsd -DGOARCH_amd64 ./cgocall.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/chan.6 -DGOOS_netbsd -DGOARCH_amd64 ./chan.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/closure_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./closure_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/complex.6 -DGOOS_netbsd -DGOARCH_amd64 ./complex.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/cpuprof.6 -DGOOS_netbsd -DGOARCH_amd64 ./cpuprof.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/float.6 -DGOOS_netbsd -DGOARCH_amd64 ./float.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/hashmap.6 -DGOOS_netbsd -DGOARCH_amd64 ./hashmap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/iface.6 -DGOOS_netbsd -DGOARCH_amd64 ./iface.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/lock_sema.6 -DGOOS_netbsd -DGOARCH_amd64 ./lock_sema.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/mcache.6 -DGOOS_netbsd -DGOARCH_amd64 ./mcache.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/mcentral.6 -DGOOS_netbsd -DGOARCH_amd64 ./mcentral.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/mem_netbsd.6 -DGOOS_netbsd -DGOARCH_amd64 ./mem_netbsd.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/mfinal.6 -DGOOS_netbsd -DGOARCH_amd64 ./mfinal.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/mfixalloc.6 -DGOOS_netbsd -DGOARCH_amd64 ./mfixalloc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/mgc0.6 -DGOOS_netbsd -DGOARCH_amd64 ./mgc0.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/mheap.6 -DGOOS_netbsd -DGOARCH_amd64 ./mheap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/msize.6 -DGOOS_netbsd -DGOARCH_amd64 ./msize.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/print.6 -DGOOS_netbsd -DGOARCH_amd64 ./print.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/proc.6 -DGOOS_netbsd -DGOARCH_amd64 ./proc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/rune.6 -DGOOS_netbsd -DGOARCH_amd64 ./rune.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/runtime.6 -DGOOS_netbsd -DGOARCH_amd64 ./runtime.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/signal_netbsd_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./signal_netbsd_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/slice.6 -DGOOS_netbsd -DGOARCH_amd64 ./slice.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/symtab.6 -DGOOS_netbsd -DGOARCH_amd64 ./symtab.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/thread_netbsd.6 -DGOOS_netbsd -DGOARCH_amd64 ./thread_netbsd.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/traceback_x86.6 -DGOOS_netbsd -DGOARCH_amd64 ./traceback_x86.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/zmalloc_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./zmalloc_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/zmprof_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./zmprof_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/zruntime1_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./zruntime1_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/zsema_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./zsema_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/zsigqueue_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./zsigqueue_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/zstring_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./zstring_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/netbsd_amd64 -o "$WORK"/runtime/_obj/ztime_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./ztime_amd64.c
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./asm_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./memmove_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_netbsd_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./rt0_netbsd_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_netbsd_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./sys_netbsd_amd64.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.6 "$WORK"/runtime/_obj/alg.6 "$WORK"/runtime/_obj/atomic_amd64.6 "$WORK"/runtime/_obj/cgocall.6 "$WORK"/runtime/_obj/chan.6 "$WORK"/runtime/_obj/closure_amd64.6 "$WORK"/runtime/_obj/complex.6 "$WORK"/runtime/_obj/cpuprof.6 "$WORK"/runtime/_obj/float.6 "$WORK"/runtime/_obj/hashmap.6 "$WORK"/runtime/_obj/iface.6 "$WORK"/runtime/_obj/lock_sema.6 "$WORK"/runtime/_obj/mcache.6 "$WORK"/runtime/_obj/mcentral.6 "$WORK"/runtime/_obj/mem_netbsd.6 "$WORK"/runtime/_obj/mfinal.6 "$WORK"/runtime/_obj/mfixalloc.6 "$WORK"/runtime/_obj/mgc0.6 "$WORK"/runtime/_obj/mheap.6 "$WORK"/runtime/_obj/msize.6 "$WORK"/runtime/_obj/print.6 "$WORK"/runtime/_obj/proc.6 "$WORK"/runtime/_obj/rune.6 "$WORK"/runtime/_obj/runtime.6 "$WORK"/runtime/_obj/signal_netbsd_amd64.6 "$WORK"/runtime/_obj/slice.6 "$WORK"/runtime/_obj/symtab.6 "$WORK"/runtime/_obj/thread_netbsd.6 "$WORK"/runtime/_obj/traceback_x86.6 "$WORK"/runtime/_obj/zmalloc_amd64.6 "$WORK"/runtime/_obj/zmprof_amd64.6 "$WORK"/runtime/_obj/zruntime1_amd64.6 "$WORK"/runtime/_obj/zsema_amd64.6 "$WORK"/runtime/_obj/zsigqueue_amd64.6 "$WORK"/runtime/_obj/zstring_amd64.6 "$WORK"/runtime/_obj/ztime_amd64.6 "$WORK"/runtime/_obj/asm_amd64.6 "$WORK"/runtime/_obj/memmove_amd64.6 "$WORK"/runtime/_obj/rt0_netbsd_amd64.6 "$WORK"/runtime/_obj/sys_netbsd_amd64.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/netbsd_amd64/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+6g -o "$WORK"/errors/_obj/_go_.6 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.6
+cp "$WORK"/errors.a "$GOROOT"/pkg/netbsd_amd64/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+6g -o "$WORK"/sync/atomic/_obj/_go_.6 -p sync/atomic -I "$WORK" ./doc.go
+6a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.6 "$WORK"/sync/atomic/_obj/asm_amd64.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/netbsd_amd64/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+6g -o "$WORK"/sync/_obj/_go_.6 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.6
+cp "$WORK"/sync.a "$GOROOT"/pkg/netbsd_amd64/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+6g -o "$WORK"/io/_obj/_go_.6 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.6
+cp "$WORK"/io.a "$GOROOT"/pkg/netbsd_amd64/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+6g -o "$WORK"/unicode/_obj/_go_.6 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.6
+cp "$WORK"/unicode.a "$GOROOT"/pkg/netbsd_amd64/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+6g -o "$WORK"/unicode/utf8/_obj/_go_.6 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/netbsd_amd64/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+6g -o "$WORK"/bytes/_obj/_go_.6 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+6a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.6 "$WORK"/bytes/_obj/asm_amd64.6
+cp "$WORK"/bytes.a "$GOROOT"/pkg/netbsd_amd64/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+6g -o "$WORK"/math/_obj/_go_.6 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./abs_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./asin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./atan2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./atan_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./dim_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./exp2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./exp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./expm1_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./floor_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/fltasm_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./fltasm_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./frexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./hypot_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./ldexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./log10_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./log1p_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./log_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./mod_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./modf_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./remainder_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./sin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./sincos_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./sqrt_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./tan_amd64.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.6 "$WORK"/math/_obj/abs_amd64.6 "$WORK"/math/_obj/asin_amd64.6 "$WORK"/math/_obj/atan2_amd64.6 "$WORK"/math/_obj/atan_amd64.6 "$WORK"/math/_obj/dim_amd64.6 "$WORK"/math/_obj/exp2_amd64.6 "$WORK"/math/_obj/exp_amd64.6 "$WORK"/math/_obj/expm1_amd64.6 "$WORK"/math/_obj/floor_amd64.6 "$WORK"/math/_obj/fltasm_amd64.6 "$WORK"/math/_obj/frexp_amd64.6 "$WORK"/math/_obj/hypot_amd64.6 "$WORK"/math/_obj/ldexp_amd64.6 "$WORK"/math/_obj/log10_amd64.6 "$WORK"/math/_obj/log1p_amd64.6 "$WORK"/math/_obj/log_amd64.6 "$WORK"/math/_obj/mod_amd64.6 "$WORK"/math/_obj/modf_amd64.6 "$WORK"/math/_obj/remainder_amd64.6 "$WORK"/math/_obj/sin_amd64.6 "$WORK"/math/_obj/sincos_amd64.6 "$WORK"/math/_obj/sqrt_amd64.6 "$WORK"/math/_obj/tan_amd64.6
+cp "$WORK"/math.a "$GOROOT"/pkg/netbsd_amd64/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+6g -o "$WORK"/sort/_obj/_go_.6 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.6
+cp "$WORK"/sort.a "$GOROOT"/pkg/netbsd_amd64/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+6g -o "$WORK"/container/heap/_obj/_go_.6 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/netbsd_amd64/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+6g -o "$WORK"/strings/_obj/_go_.6 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.6
+cp "$WORK"/strings.a "$GOROOT"/pkg/netbsd_amd64/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+6g -o "$WORK"/strconv/_obj/_go_.6 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.6
+cp "$WORK"/strconv.a "$GOROOT"/pkg/netbsd_amd64/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+6g -o "$WORK"/encoding/base64/_obj/_go_.6 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/netbsd_amd64/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+6g -o "$WORK"/syscall/_obj/_go_.6 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_netbsd.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_netbsd.go ./syscall_netbsd_amd64.go ./syscall_unix.go ./zerrors_netbsd_amd64.go ./zsyscall_netbsd_amd64.go ./zsysnum_netbsd_amd64.go ./ztypes_netbsd_amd64.go
+6a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_netbsd_amd64.6 -DGOOS_netbsd -DGOARCH_amd64 ./asm_netbsd_amd64.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.6 "$WORK"/syscall/_obj/asm_netbsd_amd64.6
+cp "$WORK"/syscall.a "$GOROOT"/pkg/netbsd_amd64/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+6g -o "$WORK"/time/_obj/_go_.6 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.6
+cp "$WORK"/time.a "$GOROOT"/pkg/netbsd_amd64/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+6g -o "$WORK"/os/_obj/_go_.6 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_netbsd.go ./sys_bsd.go ./time.go ./types.go ./zsignal_netbsd_amd64.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.6
+cp "$WORK"/os.a "$GOROOT"/pkg/netbsd_amd64/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+6g -o "$WORK"/reflect/_obj/_go_.6 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.6
+cp "$WORK"/reflect.a "$GOROOT"/pkg/netbsd_amd64/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+6g -o "$WORK"/fmt/_obj/_go_.6 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.6
+cp "$WORK"/fmt.a "$GOROOT"/pkg/netbsd_amd64/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+6g -o "$WORK"/unicode/utf16/_obj/_go_.6 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.6
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/netbsd_amd64/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+6g -o "$WORK"/encoding/json/_obj/_go_.6 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.6
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/netbsd_amd64/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+6g -o "$WORK"/flag/_obj/_go_.6 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.6
+cp "$WORK"/flag.a "$GOROOT"/pkg/netbsd_amd64/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+6g -o "$WORK"/bufio/_obj/_go_.6 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.6
+cp "$WORK"/bufio.a "$GOROOT"/pkg/netbsd_amd64/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+6g -o "$WORK"/encoding/gob/_obj/_go_.6 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.6
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/netbsd_amd64/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+6g -o "$WORK"/go/token/_obj/_go_.6 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/netbsd_amd64/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+6g -o "$WORK"/path/filepath/_obj/_go_.6 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/netbsd_amd64/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+6g -o "$WORK"/go/scanner/_obj/_go_.6 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.6
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/netbsd_amd64/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+6g -o "$WORK"/go/ast/_obj/_go_.6 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.6
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/netbsd_amd64/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+6g -o "$WORK"/io/ioutil/_obj/_go_.6 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/netbsd_amd64/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+6g -o "$WORK"/go/parser/_obj/_go_.6 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.6
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/netbsd_amd64/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+6g -o "$WORK"/log/_obj/_go_.6 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.6
+cp "$WORK"/log.a "$GOROOT"/pkg/netbsd_amd64/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+6g -o "$WORK"/path/_obj/_go_.6 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.6
+cp "$WORK"/path.a "$GOROOT"/pkg/netbsd_amd64/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+6g -o "$WORK"/go/build/_obj/_go_.6 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.6
+cp "$WORK"/go/build.a "$GOROOT"/pkg/netbsd_amd64/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+6g -o "$WORK"/os/exec/_obj/_go_.6 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/netbsd_amd64/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+6g -o "$WORK"/regexp/syntax/_obj/_go_.6 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/netbsd_amd64/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+6g -o "$WORK"/regexp/_obj/_go_.6 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.6
+cp "$WORK"/regexp.a "$GOROOT"/pkg/netbsd_amd64/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+6g -o "$WORK"/net/url/_obj/_go_.6 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/netbsd_amd64/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+6g -o "$WORK"/text/template/parse/_obj/_go_.6 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/netbsd_amd64/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+6g -o "$WORK"/text/template/_obj/_go_.6 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/netbsd_amd64/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/netbsd_amd64/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+6g -o "$WORK"/cmd/go/_obj/_go_.6 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.6
+6l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/openbsd_386.sh b/src/buildscript/openbsd_386.sh
new file mode 100755
index 0000000..5907822
--- /dev/null
+++ b/src/buildscript/openbsd_386.sh
@@ -0,0 +1,498 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=openbsd
+export GOARCH=386
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+8g -o "$WORK"/runtime/_obj/_go_.8 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_386.go ./zgoos_openbsd.go ./zruntime_defs_openbsd_386.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_386.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_openbsd_386.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_openbsd.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_openbsd.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_openbsd_386.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/alg.8 -DGOOS_openbsd -DGOARCH_386 ./alg.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/atomic_386.8 -DGOOS_openbsd -DGOARCH_386 ./atomic_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/cgocall.8 -DGOOS_openbsd -DGOARCH_386 ./cgocall.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/chan.8 -DGOOS_openbsd -DGOARCH_386 ./chan.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/closure_386.8 -DGOOS_openbsd -DGOARCH_386 ./closure_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/complex.8 -DGOOS_openbsd -DGOARCH_386 ./complex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/cpuprof.8 -DGOOS_openbsd -DGOARCH_386 ./cpuprof.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/float.8 -DGOOS_openbsd -DGOARCH_386 ./float.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/hashmap.8 -DGOOS_openbsd -DGOARCH_386 ./hashmap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/iface.8 -DGOOS_openbsd -DGOARCH_386 ./iface.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/lock_sema.8 -DGOOS_openbsd -DGOARCH_386 ./lock_sema.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/mcache.8 -DGOOS_openbsd -DGOARCH_386 ./mcache.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/mcentral.8 -DGOOS_openbsd -DGOARCH_386 ./mcentral.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/mem_openbsd.8 -DGOOS_openbsd -DGOARCH_386 ./mem_openbsd.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/mfinal.8 -DGOOS_openbsd -DGOARCH_386 ./mfinal.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/mfixalloc.8 -DGOOS_openbsd -DGOARCH_386 ./mfixalloc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/mgc0.8 -DGOOS_openbsd -DGOARCH_386 ./mgc0.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/mheap.8 -DGOOS_openbsd -DGOARCH_386 ./mheap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/msize.8 -DGOOS_openbsd -DGOARCH_386 ./msize.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/print.8 -DGOOS_openbsd -DGOARCH_386 ./print.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/proc.8 -DGOOS_openbsd -DGOARCH_386 ./proc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/rune.8 -DGOOS_openbsd -DGOARCH_386 ./rune.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/runtime.8 -DGOOS_openbsd -DGOARCH_386 ./runtime.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/signal_openbsd_386.8 -DGOOS_openbsd -DGOARCH_386 ./signal_openbsd_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/slice.8 -DGOOS_openbsd -DGOARCH_386 ./slice.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/symtab.8 -DGOOS_openbsd -DGOARCH_386 ./symtab.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/thread_openbsd.8 -DGOOS_openbsd -DGOARCH_386 ./thread_openbsd.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/traceback_x86.8 -DGOOS_openbsd -DGOARCH_386 ./traceback_x86.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/vlrt_386.8 -DGOOS_openbsd -DGOARCH_386 ./vlrt_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/zmalloc_386.8 -DGOOS_openbsd -DGOARCH_386 ./zmalloc_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/zmprof_386.8 -DGOOS_openbsd -DGOARCH_386 ./zmprof_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/zruntime1_386.8 -DGOOS_openbsd -DGOARCH_386 ./zruntime1_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/zsema_386.8 -DGOOS_openbsd -DGOARCH_386 ./zsema_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/zsigqueue_386.8 -DGOOS_openbsd -DGOARCH_386 ./zsigqueue_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/zstring_386.8 -DGOOS_openbsd -DGOARCH_386 ./zstring_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_386 -o "$WORK"/runtime/_obj/ztime_386.8 -DGOOS_openbsd -DGOARCH_386 ./ztime_386.c
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_386.8 -DGOOS_openbsd -DGOARCH_386 ./asm_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_386.8 -DGOOS_openbsd -DGOARCH_386 ./memmove_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_openbsd_386.8 -DGOOS_openbsd -DGOARCH_386 ./rt0_openbsd_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_openbsd_386.8 -DGOOS_openbsd -DGOARCH_386 ./sys_openbsd_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/vlop_386.8 -DGOOS_openbsd -DGOARCH_386 ./vlop_386.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.8 "$WORK"/runtime/_obj/alg.8 "$WORK"/runtime/_obj/atomic_386.8 "$WORK"/runtime/_obj/cgocall.8 "$WORK"/runtime/_obj/chan.8 "$WORK"/runtime/_obj/closure_386.8 "$WORK"/runtime/_obj/complex.8 "$WORK"/runtime/_obj/cpuprof.8 "$WORK"/runtime/_obj/float.8 "$WORK"/runtime/_obj/hashmap.8 "$WORK"/runtime/_obj/iface.8 "$WORK"/runtime/_obj/lock_sema.8 "$WORK"/runtime/_obj/mcache.8 "$WORK"/runtime/_obj/mcentral.8 "$WORK"/runtime/_obj/mem_openbsd.8 "$WORK"/runtime/_obj/mfinal.8 "$WORK"/runtime/_obj/mfixalloc.8 "$WORK"/runtime/_obj/mgc0.8 "$WORK"/runtime/_obj/mheap.8 "$WORK"/runtime/_obj/msize.8 "$WORK"/runtime/_obj/print.8 "$WORK"/runtime/_obj/proc.8 "$WORK"/runtime/_obj/rune.8 "$WORK"/runtime/_obj/runtime.8 "$WORK"/runtime/_obj/signal_openbsd_386.8 "$WORK"/runtime/_obj/slice.8 "$WORK"/runtime/_obj/symtab.8 "$WORK"/runtime/_obj/thread_openbsd.8 "$WORK"/runtime/_obj/traceback_x86.8 "$WORK"/runtime/_obj/vlrt_386.8 "$WORK"/runtime/_obj/zmalloc_386.8 "$WORK"/runtime/_obj/zmprof_386.8 "$WORK"/runtime/_obj/zruntime1_386.8 "$WORK"/runtime/_obj/zsema_386.8 "$WORK"/runtime/_obj/zsigqueue_386.8 "$WORK"/runtime/_obj/zstring_386.8 "$WORK"/runtime/_obj/ztime_386.8 "$WORK"/runtime/_obj/asm_386.8 "$WORK"/runtime/_obj/memmove_386.8 "$WORK"/runtime/_obj/rt0_openbsd_386.8 "$WORK"/runtime/_obj/sys_openbsd_386.8 "$WORK"/runtime/_obj/vlop_386.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/openbsd_386/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+8g -o "$WORK"/errors/_obj/_go_.8 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.8
+cp "$WORK"/errors.a "$GOROOT"/pkg/openbsd_386/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+8g -o "$WORK"/sync/atomic/_obj/_go_.8 -p sync/atomic -I "$WORK" ./doc.go
+8a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_386.8 -DGOOS_openbsd -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.8 "$WORK"/sync/atomic/_obj/asm_386.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/openbsd_386/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+8g -o "$WORK"/sync/_obj/_go_.8 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.8
+cp "$WORK"/sync.a "$GOROOT"/pkg/openbsd_386/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+8g -o "$WORK"/io/_obj/_go_.8 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.8
+cp "$WORK"/io.a "$GOROOT"/pkg/openbsd_386/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+8g -o "$WORK"/unicode/_obj/_go_.8 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.8
+cp "$WORK"/unicode.a "$GOROOT"/pkg/openbsd_386/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+8g -o "$WORK"/unicode/utf8/_obj/_go_.8 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/openbsd_386/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+8g -o "$WORK"/bytes/_obj/_go_.8 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+8a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_386.8 -DGOOS_openbsd -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.8 "$WORK"/bytes/_obj/asm_386.8
+cp "$WORK"/bytes.a "$GOROOT"/pkg/openbsd_386/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+8g -o "$WORK"/math/_obj/_go_.8 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_386.8 -DGOOS_openbsd -DGOARCH_386 ./abs_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_386.8 -DGOOS_openbsd -DGOARCH_386 ./asin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_386.8 -DGOOS_openbsd -DGOARCH_386 ./atan2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_386.8 -DGOOS_openbsd -DGOARCH_386 ./atan_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_386.8 -DGOOS_openbsd -DGOARCH_386 ./dim_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_386.8 -DGOOS_openbsd -DGOARCH_386 ./exp2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_386.8 -DGOOS_openbsd -DGOARCH_386 ./exp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_386.8 -DGOOS_openbsd -DGOARCH_386 ./expm1_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_386.8 -DGOOS_openbsd -DGOARCH_386 ./floor_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_386.8 -DGOOS_openbsd -DGOARCH_386 ./frexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_386.8 -DGOOS_openbsd -DGOARCH_386 ./hypot_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_386.8 -DGOOS_openbsd -DGOARCH_386 ./ldexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_386.8 -DGOOS_openbsd -DGOARCH_386 ./log10_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_386.8 -DGOOS_openbsd -DGOARCH_386 ./log1p_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_386.8 -DGOOS_openbsd -DGOARCH_386 ./log_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_386.8 -DGOOS_openbsd -DGOARCH_386 ./mod_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_386.8 -DGOOS_openbsd -DGOARCH_386 ./modf_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_386.8 -DGOOS_openbsd -DGOARCH_386 ./remainder_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_386.8 -DGOOS_openbsd -DGOARCH_386 ./sin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_386.8 -DGOOS_openbsd -DGOARCH_386 ./sincos_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_386.8 -DGOOS_openbsd -DGOARCH_386 ./sqrt_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_386.8 -DGOOS_openbsd -DGOARCH_386 ./tan_386.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.8 "$WORK"/math/_obj/abs_386.8 "$WORK"/math/_obj/asin_386.8 "$WORK"/math/_obj/atan2_386.8 "$WORK"/math/_obj/atan_386.8 "$WORK"/math/_obj/dim_386.8 "$WORK"/math/_obj/exp2_386.8 "$WORK"/math/_obj/exp_386.8 "$WORK"/math/_obj/expm1_386.8 "$WORK"/math/_obj/floor_386.8 "$WORK"/math/_obj/frexp_386.8 "$WORK"/math/_obj/hypot_386.8 "$WORK"/math/_obj/ldexp_386.8 "$WORK"/math/_obj/log10_386.8 "$WORK"/math/_obj/log1p_386.8 "$WORK"/math/_obj/log_386.8 "$WORK"/math/_obj/mod_386.8 "$WORK"/math/_obj/modf_386.8 "$WORK"/math/_obj/remainder_386.8 "$WORK"/math/_obj/sin_386.8 "$WORK"/math/_obj/sincos_386.8 "$WORK"/math/_obj/sqrt_386.8 "$WORK"/math/_obj/tan_386.8
+cp "$WORK"/math.a "$GOROOT"/pkg/openbsd_386/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+8g -o "$WORK"/sort/_obj/_go_.8 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.8
+cp "$WORK"/sort.a "$GOROOT"/pkg/openbsd_386/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+8g -o "$WORK"/container/heap/_obj/_go_.8 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/openbsd_386/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+8g -o "$WORK"/strings/_obj/_go_.8 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.8
+cp "$WORK"/strings.a "$GOROOT"/pkg/openbsd_386/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+8g -o "$WORK"/strconv/_obj/_go_.8 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.8
+cp "$WORK"/strconv.a "$GOROOT"/pkg/openbsd_386/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+8g -o "$WORK"/encoding/base64/_obj/_go_.8 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/openbsd_386/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_openbsd.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_openbsd.go ./syscall_openbsd_386.go ./syscall_unix.go ./zerrors_openbsd_386.go ./zsyscall_openbsd_386.go ./zsysctl_openbsd.go ./zsysnum_openbsd_386.go ./ztypes_openbsd_386.go
+8a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_openbsd_386.8 -DGOOS_openbsd -DGOARCH_386 ./asm_openbsd_386.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.8 "$WORK"/syscall/_obj/asm_openbsd_386.8
+cp "$WORK"/syscall.a "$GOROOT"/pkg/openbsd_386/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+8g -o "$WORK"/time/_obj/_go_.8 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.8
+cp "$WORK"/time.a "$GOROOT"/pkg/openbsd_386/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+8g -o "$WORK"/os/_obj/_go_.8 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_openbsd.go ./sys_bsd.go ./time.go ./types.go ./zsignal_openbsd_386.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.8
+cp "$WORK"/os.a "$GOROOT"/pkg/openbsd_386/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+8g -o "$WORK"/reflect/_obj/_go_.8 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.8
+cp "$WORK"/reflect.a "$GOROOT"/pkg/openbsd_386/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+8g -o "$WORK"/fmt/_obj/_go_.8 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.8
+cp "$WORK"/fmt.a "$GOROOT"/pkg/openbsd_386/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+8g -o "$WORK"/unicode/utf16/_obj/_go_.8 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.8
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/openbsd_386/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+8g -o "$WORK"/encoding/json/_obj/_go_.8 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.8
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/openbsd_386/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+8g -o "$WORK"/flag/_obj/_go_.8 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.8
+cp "$WORK"/flag.a "$GOROOT"/pkg/openbsd_386/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+8g -o "$WORK"/bufio/_obj/_go_.8 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.8
+cp "$WORK"/bufio.a "$GOROOT"/pkg/openbsd_386/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+8g -o "$WORK"/encoding/gob/_obj/_go_.8 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.8
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/openbsd_386/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+8g -o "$WORK"/go/token/_obj/_go_.8 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/openbsd_386/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+8g -o "$WORK"/path/filepath/_obj/_go_.8 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/openbsd_386/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+8g -o "$WORK"/go/scanner/_obj/_go_.8 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.8
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/openbsd_386/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+8g -o "$WORK"/go/ast/_obj/_go_.8 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.8
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/openbsd_386/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+8g -o "$WORK"/io/ioutil/_obj/_go_.8 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/openbsd_386/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+8g -o "$WORK"/go/parser/_obj/_go_.8 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.8
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/openbsd_386/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+8g -o "$WORK"/log/_obj/_go_.8 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.8
+cp "$WORK"/log.a "$GOROOT"/pkg/openbsd_386/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+8g -o "$WORK"/path/_obj/_go_.8 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.8
+cp "$WORK"/path.a "$GOROOT"/pkg/openbsd_386/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+8g -o "$WORK"/go/build/_obj/_go_.8 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.8
+cp "$WORK"/go/build.a "$GOROOT"/pkg/openbsd_386/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+8g -o "$WORK"/os/exec/_obj/_go_.8 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/openbsd_386/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+8g -o "$WORK"/regexp/syntax/_obj/_go_.8 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/openbsd_386/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+8g -o "$WORK"/regexp/_obj/_go_.8 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.8
+cp "$WORK"/regexp.a "$GOROOT"/pkg/openbsd_386/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+8g -o "$WORK"/net/url/_obj/_go_.8 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/openbsd_386/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+8g -o "$WORK"/text/template/parse/_obj/_go_.8 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/openbsd_386/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+8g -o "$WORK"/text/template/_obj/_go_.8 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/openbsd_386/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/openbsd_386/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+8g -o "$WORK"/cmd/go/_obj/_go_.8 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.8
+8l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/openbsd_amd64.sh b/src/buildscript/openbsd_amd64.sh
new file mode 100755
index 0000000..7db8d8e
--- /dev/null
+++ b/src/buildscript/openbsd_amd64.sh
@@ -0,0 +1,497 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=openbsd
+export GOARCH=amd64
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+6g -o "$WORK"/runtime/_obj/_go_.6 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_amd64.go ./zgoos_openbsd.go ./zruntime_defs_openbsd_amd64.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_amd64.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_openbsd_amd64.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_openbsd.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_openbsd.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_openbsd_amd64.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/alg.6 -DGOOS_openbsd -DGOARCH_amd64 ./alg.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/atomic_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./atomic_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/cgocall.6 -DGOOS_openbsd -DGOARCH_amd64 ./cgocall.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/chan.6 -DGOOS_openbsd -DGOARCH_amd64 ./chan.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/closure_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./closure_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/complex.6 -DGOOS_openbsd -DGOARCH_amd64 ./complex.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/cpuprof.6 -DGOOS_openbsd -DGOARCH_amd64 ./cpuprof.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/float.6 -DGOOS_openbsd -DGOARCH_amd64 ./float.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/hashmap.6 -DGOOS_openbsd -DGOARCH_amd64 ./hashmap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/iface.6 -DGOOS_openbsd -DGOARCH_amd64 ./iface.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/lock_sema.6 -DGOOS_openbsd -DGOARCH_amd64 ./lock_sema.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/mcache.6 -DGOOS_openbsd -DGOARCH_amd64 ./mcache.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/mcentral.6 -DGOOS_openbsd -DGOARCH_amd64 ./mcentral.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/mem_openbsd.6 -DGOOS_openbsd -DGOARCH_amd64 ./mem_openbsd.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/mfinal.6 -DGOOS_openbsd -DGOARCH_amd64 ./mfinal.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/mfixalloc.6 -DGOOS_openbsd -DGOARCH_amd64 ./mfixalloc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/mgc0.6 -DGOOS_openbsd -DGOARCH_amd64 ./mgc0.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/mheap.6 -DGOOS_openbsd -DGOARCH_amd64 ./mheap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/msize.6 -DGOOS_openbsd -DGOARCH_amd64 ./msize.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/print.6 -DGOOS_openbsd -DGOARCH_amd64 ./print.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/proc.6 -DGOOS_openbsd -DGOARCH_amd64 ./proc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/rune.6 -DGOOS_openbsd -DGOARCH_amd64 ./rune.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/runtime.6 -DGOOS_openbsd -DGOARCH_amd64 ./runtime.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/signal_openbsd_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./signal_openbsd_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/slice.6 -DGOOS_openbsd -DGOARCH_amd64 ./slice.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/symtab.6 -DGOOS_openbsd -DGOARCH_amd64 ./symtab.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/thread_openbsd.6 -DGOOS_openbsd -DGOARCH_amd64 ./thread_openbsd.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/traceback_x86.6 -DGOOS_openbsd -DGOARCH_amd64 ./traceback_x86.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/zmalloc_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./zmalloc_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/zmprof_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./zmprof_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/zruntime1_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./zruntime1_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/zsema_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./zsema_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/zsigqueue_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./zsigqueue_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/zstring_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./zstring_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/openbsd_amd64 -o "$WORK"/runtime/_obj/ztime_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./ztime_amd64.c
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./asm_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./memmove_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_openbsd_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./rt0_openbsd_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_openbsd_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./sys_openbsd_amd64.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.6 "$WORK"/runtime/_obj/alg.6 "$WORK"/runtime/_obj/atomic_amd64.6 "$WORK"/runtime/_obj/cgocall.6 "$WORK"/runtime/_obj/chan.6 "$WORK"/runtime/_obj/closure_amd64.6 "$WORK"/runtime/_obj/complex.6 "$WORK"/runtime/_obj/cpuprof.6 "$WORK"/runtime/_obj/float.6 "$WORK"/runtime/_obj/hashmap.6 "$WORK"/runtime/_obj/iface.6 "$WORK"/runtime/_obj/lock_sema.6 "$WORK"/runtime/_obj/mcache.6 "$WORK"/runtime/_obj/mcentral.6 "$WORK"/runtime/_obj/mem_openbsd.6 "$WORK"/runtime/_obj/mfinal.6 "$WORK"/runtime/_obj/mfixalloc.6 "$WORK"/runtime/_obj/mgc0.6 "$WORK"/runtime/_obj/mheap.6 "$WORK"/runtime/_obj/msize.6 "$WORK"/runtime/_obj/print.6 "$WORK"/runtime/_obj/proc.6 "$WORK"/runtime/_obj/rune.6 "$WORK"/runtime/_obj/runtime.6 "$WORK"/runtime/_obj/signal_openbsd_amd64.6 "$WORK"/runtime/_obj/slice.6 "$WORK"/runtime/_obj/symtab.6 "$WORK"/runtime/_obj/thread_openbsd.6 "$WORK"/runtime/_obj/traceback_x86.6 "$WORK"/runtime/_obj/zmalloc_amd64.6 "$WORK"/runtime/_obj/zmprof_amd64.6 "$WORK"/runtime/_obj/zruntime1_amd64.6 "$WORK"/runtime/_obj/zsema_amd64.6 "$WORK"/runtime/_obj/zsigqueue_amd64.6 "$WORK"/runtime/_obj/zstring_amd64.6 "$WORK"/runtime/_obj/ztime_amd64.6 "$WORK"/runtime/_obj/asm_amd64.6 "$WORK"/runtime/_obj/memmove_amd64.6 "$WORK"/runtime/_obj/rt0_openbsd_amd64.6 "$WORK"/runtime/_obj/sys_openbsd_amd64.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/openbsd_amd64/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+6g -o "$WORK"/errors/_obj/_go_.6 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.6
+cp "$WORK"/errors.a "$GOROOT"/pkg/openbsd_amd64/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+6g -o "$WORK"/sync/atomic/_obj/_go_.6 -p sync/atomic -I "$WORK" ./doc.go
+6a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.6 "$WORK"/sync/atomic/_obj/asm_amd64.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/openbsd_amd64/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+6g -o "$WORK"/sync/_obj/_go_.6 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.6
+cp "$WORK"/sync.a "$GOROOT"/pkg/openbsd_amd64/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+6g -o "$WORK"/io/_obj/_go_.6 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.6
+cp "$WORK"/io.a "$GOROOT"/pkg/openbsd_amd64/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+6g -o "$WORK"/unicode/_obj/_go_.6 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.6
+cp "$WORK"/unicode.a "$GOROOT"/pkg/openbsd_amd64/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+6g -o "$WORK"/unicode/utf8/_obj/_go_.6 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/openbsd_amd64/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+6g -o "$WORK"/bytes/_obj/_go_.6 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+6a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.6 "$WORK"/bytes/_obj/asm_amd64.6
+cp "$WORK"/bytes.a "$GOROOT"/pkg/openbsd_amd64/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+6g -o "$WORK"/math/_obj/_go_.6 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./abs_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./asin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./atan2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./atan_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./dim_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./exp2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./exp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./expm1_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./floor_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/fltasm_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./fltasm_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./frexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./hypot_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./ldexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./log10_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./log1p_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./log_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./mod_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./modf_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./remainder_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./sin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./sincos_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./sqrt_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./tan_amd64.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.6 "$WORK"/math/_obj/abs_amd64.6 "$WORK"/math/_obj/asin_amd64.6 "$WORK"/math/_obj/atan2_amd64.6 "$WORK"/math/_obj/atan_amd64.6 "$WORK"/math/_obj/dim_amd64.6 "$WORK"/math/_obj/exp2_amd64.6 "$WORK"/math/_obj/exp_amd64.6 "$WORK"/math/_obj/expm1_amd64.6 "$WORK"/math/_obj/floor_amd64.6 "$WORK"/math/_obj/fltasm_amd64.6 "$WORK"/math/_obj/frexp_amd64.6 "$WORK"/math/_obj/hypot_amd64.6 "$WORK"/math/_obj/ldexp_amd64.6 "$WORK"/math/_obj/log10_amd64.6 "$WORK"/math/_obj/log1p_amd64.6 "$WORK"/math/_obj/log_amd64.6 "$WORK"/math/_obj/mod_amd64.6 "$WORK"/math/_obj/modf_amd64.6 "$WORK"/math/_obj/remainder_amd64.6 "$WORK"/math/_obj/sin_amd64.6 "$WORK"/math/_obj/sincos_amd64.6 "$WORK"/math/_obj/sqrt_amd64.6 "$WORK"/math/_obj/tan_amd64.6
+cp "$WORK"/math.a "$GOROOT"/pkg/openbsd_amd64/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+6g -o "$WORK"/sort/_obj/_go_.6 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.6
+cp "$WORK"/sort.a "$GOROOT"/pkg/openbsd_amd64/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+6g -o "$WORK"/container/heap/_obj/_go_.6 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/openbsd_amd64/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+6g -o "$WORK"/strings/_obj/_go_.6 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.6
+cp "$WORK"/strings.a "$GOROOT"/pkg/openbsd_amd64/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+6g -o "$WORK"/strconv/_obj/_go_.6 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.6
+cp "$WORK"/strconv.a "$GOROOT"/pkg/openbsd_amd64/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+6g -o "$WORK"/encoding/base64/_obj/_go_.6 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/openbsd_amd64/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+6g -o "$WORK"/syscall/_obj/_go_.6 -p syscall -I "$WORK" ./bpf_bsd.go ./env_unix.go ./exec_bsd.go ./exec_unix.go ./route_bsd.go ./route_openbsd.go ./sockcmsg_unix.go ./str.go ./syscall.go ./syscall_bsd.go ./syscall_openbsd.go ./syscall_openbsd_amd64.go ./syscall_unix.go ./zerrors_openbsd_amd64.go ./zsyscall_openbsd_amd64.go ./zsysctl_openbsd.go ./zsysnum_openbsd_amd64.go ./ztypes_openbsd_amd64.go
+6a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_openbsd_amd64.6 -DGOOS_openbsd -DGOARCH_amd64 ./asm_openbsd_amd64.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.6 "$WORK"/syscall/_obj/asm_openbsd_amd64.6
+cp "$WORK"/syscall.a "$GOROOT"/pkg/openbsd_amd64/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+6g -o "$WORK"/time/_obj/_go_.6 -p time -I "$WORK" ./format.go ./sleep.go ./sys_unix.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_unix.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.6
+cp "$WORK"/time.a "$GOROOT"/pkg/openbsd_amd64/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+6g -o "$WORK"/os/_obj/_go_.6 -p os -I "$WORK" ./dir_unix.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_unix.go ./file.go ./file_posix.go ./file_unix.go ./getwd.go ./path.go ./path_unix.go ./proc.go ./stat_openbsd.go ./sys_bsd.go ./time.go ./types.go ./zsignal_openbsd_amd64.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.6
+cp "$WORK"/os.a "$GOROOT"/pkg/openbsd_amd64/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+6g -o "$WORK"/reflect/_obj/_go_.6 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.6
+cp "$WORK"/reflect.a "$GOROOT"/pkg/openbsd_amd64/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+6g -o "$WORK"/fmt/_obj/_go_.6 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.6
+cp "$WORK"/fmt.a "$GOROOT"/pkg/openbsd_amd64/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+6g -o "$WORK"/unicode/utf16/_obj/_go_.6 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.6
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/openbsd_amd64/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+6g -o "$WORK"/encoding/json/_obj/_go_.6 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.6
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/openbsd_amd64/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+6g -o "$WORK"/flag/_obj/_go_.6 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.6
+cp "$WORK"/flag.a "$GOROOT"/pkg/openbsd_amd64/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+6g -o "$WORK"/bufio/_obj/_go_.6 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.6
+cp "$WORK"/bufio.a "$GOROOT"/pkg/openbsd_amd64/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+6g -o "$WORK"/encoding/gob/_obj/_go_.6 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.6
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/openbsd_amd64/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+6g -o "$WORK"/go/token/_obj/_go_.6 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/openbsd_amd64/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+6g -o "$WORK"/path/filepath/_obj/_go_.6 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_unix.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/openbsd_amd64/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+6g -o "$WORK"/go/scanner/_obj/_go_.6 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.6
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/openbsd_amd64/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+6g -o "$WORK"/go/ast/_obj/_go_.6 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.6
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/openbsd_amd64/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+6g -o "$WORK"/io/ioutil/_obj/_go_.6 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/openbsd_amd64/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+6g -o "$WORK"/go/parser/_obj/_go_.6 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.6
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/openbsd_amd64/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+6g -o "$WORK"/log/_obj/_go_.6 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.6
+cp "$WORK"/log.a "$GOROOT"/pkg/openbsd_amd64/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+6g -o "$WORK"/path/_obj/_go_.6 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.6
+cp "$WORK"/path.a "$GOROOT"/pkg/openbsd_amd64/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+6g -o "$WORK"/go/build/_obj/_go_.6 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.6
+cp "$WORK"/go/build.a "$GOROOT"/pkg/openbsd_amd64/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+6g -o "$WORK"/os/exec/_obj/_go_.6 -p os/exec -I "$WORK" ./exec.go ./lp_unix.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/openbsd_amd64/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+6g -o "$WORK"/regexp/syntax/_obj/_go_.6 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/openbsd_amd64/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+6g -o "$WORK"/regexp/_obj/_go_.6 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.6
+cp "$WORK"/regexp.a "$GOROOT"/pkg/openbsd_amd64/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+6g -o "$WORK"/net/url/_obj/_go_.6 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/openbsd_amd64/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+6g -o "$WORK"/text/template/parse/_obj/_go_.6 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/openbsd_amd64/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+6g -o "$WORK"/text/template/_obj/_go_.6 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/openbsd_amd64/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/openbsd_amd64/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+6g -o "$WORK"/cmd/go/_obj/_go_.6 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.6
+6l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/plan9_386.sh b/src/buildscript/plan9_386.sh
new file mode 100755
index 0000000..9e3303e
--- /dev/null
+++ b/src/buildscript/plan9_386.sh
@@ -0,0 +1,498 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=plan9
+export GOARCH=386
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+8g -o "$WORK"/runtime/_obj/_go_.8 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_386.go ./zgoos_plan9.go ./zruntime_defs_plan9_386.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_386.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_plan9_386.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_plan9.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_plan9.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_plan9_386.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/alg.8 -DGOOS_plan9 -DGOARCH_386 ./alg.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/atomic_386.8 -DGOOS_plan9 -DGOARCH_386 ./atomic_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/cgocall.8 -DGOOS_plan9 -DGOARCH_386 ./cgocall.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/chan.8 -DGOOS_plan9 -DGOARCH_386 ./chan.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/closure_386.8 -DGOOS_plan9 -DGOARCH_386 ./closure_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/complex.8 -DGOOS_plan9 -DGOARCH_386 ./complex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/cpuprof.8 -DGOOS_plan9 -DGOARCH_386 ./cpuprof.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/float.8 -DGOOS_plan9 -DGOARCH_386 ./float.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/hashmap.8 -DGOOS_plan9 -DGOARCH_386 ./hashmap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/iface.8 -DGOOS_plan9 -DGOARCH_386 ./iface.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/lock_sema.8 -DGOOS_plan9 -DGOARCH_386 ./lock_sema.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/mcache.8 -DGOOS_plan9 -DGOARCH_386 ./mcache.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/mcentral.8 -DGOOS_plan9 -DGOARCH_386 ./mcentral.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/mem_plan9.8 -DGOOS_plan9 -DGOARCH_386 ./mem_plan9.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/mfinal.8 -DGOOS_plan9 -DGOARCH_386 ./mfinal.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/mfixalloc.8 -DGOOS_plan9 -DGOARCH_386 ./mfixalloc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/mgc0.8 -DGOOS_plan9 -DGOARCH_386 ./mgc0.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/mheap.8 -DGOOS_plan9 -DGOARCH_386 ./mheap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/msize.8 -DGOOS_plan9 -DGOARCH_386 ./msize.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/print.8 -DGOOS_plan9 -DGOARCH_386 ./print.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/proc.8 -DGOOS_plan9 -DGOARCH_386 ./proc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/rune.8 -DGOOS_plan9 -DGOARCH_386 ./rune.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/runtime.8 -DGOOS_plan9 -DGOARCH_386 ./runtime.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/signal_plan9_386.8 -DGOOS_plan9 -DGOARCH_386 ./signal_plan9_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/slice.8 -DGOOS_plan9 -DGOARCH_386 ./slice.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/symtab.8 -DGOOS_plan9 -DGOARCH_386 ./symtab.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/thread_plan9.8 -DGOOS_plan9 -DGOARCH_386 ./thread_plan9.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/traceback_x86.8 -DGOOS_plan9 -DGOARCH_386 ./traceback_x86.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/vlrt_386.8 -DGOOS_plan9 -DGOARCH_386 ./vlrt_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/zmalloc_386.8 -DGOOS_plan9 -DGOARCH_386 ./zmalloc_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/zmprof_386.8 -DGOOS_plan9 -DGOARCH_386 ./zmprof_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/zruntime1_386.8 -DGOOS_plan9 -DGOARCH_386 ./zruntime1_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/zsema_386.8 -DGOOS_plan9 -DGOARCH_386 ./zsema_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/zsigqueue_386.8 -DGOOS_plan9 -DGOARCH_386 ./zsigqueue_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/zstring_386.8 -DGOOS_plan9 -DGOARCH_386 ./zstring_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/plan9_386 -o "$WORK"/runtime/_obj/ztime_386.8 -DGOOS_plan9 -DGOARCH_386 ./ztime_386.c
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_386.8 -DGOOS_plan9 -DGOARCH_386 ./asm_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_386.8 -DGOOS_plan9 -DGOARCH_386 ./memmove_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_plan9_386.8 -DGOOS_plan9 -DGOARCH_386 ./rt0_plan9_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_plan9_386.8 -DGOOS_plan9 -DGOARCH_386 ./sys_plan9_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/vlop_386.8 -DGOOS_plan9 -DGOARCH_386 ./vlop_386.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.8 "$WORK"/runtime/_obj/alg.8 "$WORK"/runtime/_obj/atomic_386.8 "$WORK"/runtime/_obj/cgocall.8 "$WORK"/runtime/_obj/chan.8 "$WORK"/runtime/_obj/closure_386.8 "$WORK"/runtime/_obj/complex.8 "$WORK"/runtime/_obj/cpuprof.8 "$WORK"/runtime/_obj/float.8 "$WORK"/runtime/_obj/hashmap.8 "$WORK"/runtime/_obj/iface.8 "$WORK"/runtime/_obj/lock_sema.8 "$WORK"/runtime/_obj/mcache.8 "$WORK"/runtime/_obj/mcentral.8 "$WORK"/runtime/_obj/mem_plan9.8 "$WORK"/runtime/_obj/mfinal.8 "$WORK"/runtime/_obj/mfixalloc.8 "$WORK"/runtime/_obj/mgc0.8 "$WORK"/runtime/_obj/mheap.8 "$WORK"/runtime/_obj/msize.8 "$WORK"/runtime/_obj/print.8 "$WORK"/runtime/_obj/proc.8 "$WORK"/runtime/_obj/rune.8 "$WORK"/runtime/_obj/runtime.8 "$WORK"/runtime/_obj/signal_plan9_386.8 "$WORK"/runtime/_obj/slice.8 "$WORK"/runtime/_obj/symtab.8 "$WORK"/runtime/_obj/thread_plan9.8 "$WORK"/runtime/_obj/traceback_x86.8 "$WORK"/runtime/_obj/vlrt_386.8 "$WORK"/runtime/_obj/zmalloc_386.8 "$WORK"/runtime/_obj/zmprof_386.8 "$WORK"/runtime/_obj/zruntime1_386.8 "$WORK"/runtime/_obj/zsema_386.8 "$WORK"/runtime/_obj/zsigqueue_386.8 "$WORK"/runtime/_obj/zstring_386.8 "$WORK"/runtime/_obj/ztime_386.8 "$WORK"/runtime/_obj/asm_386.8 "$WORK"/runtime/_obj/memmove_386.8 "$WORK"/runtime/_obj/rt0_plan9_386.8 "$WORK"/runtime/_obj/sys_plan9_386.8 "$WORK"/runtime/_obj/vlop_386.8
+mkdir -p "$GOROOT"/pkg/plan9_386/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/plan9_386/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+8g -o "$WORK"/errors/_obj/_go_.8 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.8
+cp "$WORK"/errors.a "$GOROOT"/pkg/plan9_386/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+8g -o "$WORK"/sync/atomic/_obj/_go_.8 -p sync/atomic -I "$WORK" ./doc.go
+8a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_386.8 -DGOOS_plan9 -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.8 "$WORK"/sync/atomic/_obj/asm_386.8
+mkdir -p "$GOROOT"/pkg/plan9_386/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/plan9_386/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+8g -o "$WORK"/sync/_obj/_go_.8 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.8
+cp "$WORK"/sync.a "$GOROOT"/pkg/plan9_386/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+8g -o "$WORK"/io/_obj/_go_.8 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.8
+cp "$WORK"/io.a "$GOROOT"/pkg/plan9_386/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+8g -o "$WORK"/unicode/_obj/_go_.8 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.8
+cp "$WORK"/unicode.a "$GOROOT"/pkg/plan9_386/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+8g -o "$WORK"/unicode/utf8/_obj/_go_.8 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/plan9_386/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+8g -o "$WORK"/bytes/_obj/_go_.8 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+8a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_386.8 -DGOOS_plan9 -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.8 "$WORK"/bytes/_obj/asm_386.8
+cp "$WORK"/bytes.a "$GOROOT"/pkg/plan9_386/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+8g -o "$WORK"/math/_obj/_go_.8 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_386.8 -DGOOS_plan9 -DGOARCH_386 ./abs_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_386.8 -DGOOS_plan9 -DGOARCH_386 ./asin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_386.8 -DGOOS_plan9 -DGOARCH_386 ./atan2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_386.8 -DGOOS_plan9 -DGOARCH_386 ./atan_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_386.8 -DGOOS_plan9 -DGOARCH_386 ./dim_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_386.8 -DGOOS_plan9 -DGOARCH_386 ./exp2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_386.8 -DGOOS_plan9 -DGOARCH_386 ./exp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_386.8 -DGOOS_plan9 -DGOARCH_386 ./expm1_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_386.8 -DGOOS_plan9 -DGOARCH_386 ./floor_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_386.8 -DGOOS_plan9 -DGOARCH_386 ./frexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_386.8 -DGOOS_plan9 -DGOARCH_386 ./hypot_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_386.8 -DGOOS_plan9 -DGOARCH_386 ./ldexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_386.8 -DGOOS_plan9 -DGOARCH_386 ./log10_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_386.8 -DGOOS_plan9 -DGOARCH_386 ./log1p_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_386.8 -DGOOS_plan9 -DGOARCH_386 ./log_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_386.8 -DGOOS_plan9 -DGOARCH_386 ./mod_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_386.8 -DGOOS_plan9 -DGOARCH_386 ./modf_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_386.8 -DGOOS_plan9 -DGOARCH_386 ./remainder_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_386.8 -DGOOS_plan9 -DGOARCH_386 ./sin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_386.8 -DGOOS_plan9 -DGOARCH_386 ./sincos_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_386.8 -DGOOS_plan9 -DGOARCH_386 ./sqrt_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_386.8 -DGOOS_plan9 -DGOARCH_386 ./tan_386.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.8 "$WORK"/math/_obj/abs_386.8 "$WORK"/math/_obj/asin_386.8 "$WORK"/math/_obj/atan2_386.8 "$WORK"/math/_obj/atan_386.8 "$WORK"/math/_obj/dim_386.8 "$WORK"/math/_obj/exp2_386.8 "$WORK"/math/_obj/exp_386.8 "$WORK"/math/_obj/expm1_386.8 "$WORK"/math/_obj/floor_386.8 "$WORK"/math/_obj/frexp_386.8 "$WORK"/math/_obj/hypot_386.8 "$WORK"/math/_obj/ldexp_386.8 "$WORK"/math/_obj/log10_386.8 "$WORK"/math/_obj/log1p_386.8 "$WORK"/math/_obj/log_386.8 "$WORK"/math/_obj/mod_386.8 "$WORK"/math/_obj/modf_386.8 "$WORK"/math/_obj/remainder_386.8 "$WORK"/math/_obj/sin_386.8 "$WORK"/math/_obj/sincos_386.8 "$WORK"/math/_obj/sqrt_386.8 "$WORK"/math/_obj/tan_386.8
+cp "$WORK"/math.a "$GOROOT"/pkg/plan9_386/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+8g -o "$WORK"/sort/_obj/_go_.8 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.8
+cp "$WORK"/sort.a "$GOROOT"/pkg/plan9_386/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+8g -o "$WORK"/container/heap/_obj/_go_.8 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/plan9_386/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+8g -o "$WORK"/strings/_obj/_go_.8 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.8
+cp "$WORK"/strings.a "$GOROOT"/pkg/plan9_386/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+8g -o "$WORK"/strconv/_obj/_go_.8 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.8
+cp "$WORK"/strconv.a "$GOROOT"/pkg/plan9_386/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+8g -o "$WORK"/encoding/base64/_obj/_go_.8 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/plan9_386/encoding/base64.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./env_plan9.go ./exec_plan9.go ./str.go ./syscall.go ./syscall_plan9.go ./syscall_plan9_386.go ./zerrors_plan9_386.go ./zsyscall_plan9_386.go ./zsysnum_plan9_386.go ./ztypes_plan9_386.go
+8a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_plan9_386.8 -DGOOS_plan9 -DGOARCH_386 ./asm_plan9_386.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.8 "$WORK"/syscall/_obj/asm_plan9_386.8
+cp "$WORK"/syscall.a "$GOROOT"/pkg/plan9_386/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+8g -o "$WORK"/time/_obj/_go_.8 -p time -I "$WORK" ./format.go ./sleep.go ./sys_plan9.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_plan9.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.8
+cp "$WORK"/time.a "$GOROOT"/pkg/plan9_386/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+8g -o "$WORK"/os/_obj/_go_.8 -p os -I "$WORK" ./dir_plan9.go ./doc.go ./env.go ./error.go ./error_plan9.go ./exec.go ./exec_plan9.go ./file.go ./file_plan9.go ./getwd.go ./path.go ./path_plan9.go ./proc.go ./stat_plan9.go ./str.go ./sys_plan9.go ./time.go ./types.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.8
+cp "$WORK"/os.a "$GOROOT"/pkg/plan9_386/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+8g -o "$WORK"/reflect/_obj/_go_.8 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.8
+cp "$WORK"/reflect.a "$GOROOT"/pkg/plan9_386/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+8g -o "$WORK"/fmt/_obj/_go_.8 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.8
+cp "$WORK"/fmt.a "$GOROOT"/pkg/plan9_386/fmt.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+8g -o "$WORK"/unicode/utf16/_obj/_go_.8 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.8
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/plan9_386/unicode/utf16.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+8g -o "$WORK"/encoding/json/_obj/_go_.8 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.8
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/plan9_386/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+8g -o "$WORK"/flag/_obj/_go_.8 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.8
+cp "$WORK"/flag.a "$GOROOT"/pkg/plan9_386/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+8g -o "$WORK"/bufio/_obj/_go_.8 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.8
+cp "$WORK"/bufio.a "$GOROOT"/pkg/plan9_386/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+8g -o "$WORK"/encoding/gob/_obj/_go_.8 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.8
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/plan9_386/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+8g -o "$WORK"/go/token/_obj/_go_.8 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/plan9_386/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+8g -o "$WORK"/path/filepath/_obj/_go_.8 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_plan9.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/plan9_386/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+8g -o "$WORK"/go/scanner/_obj/_go_.8 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.8
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/plan9_386/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+8g -o "$WORK"/go/ast/_obj/_go_.8 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.8
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/plan9_386/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+8g -o "$WORK"/io/ioutil/_obj/_go_.8 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/plan9_386/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+8g -o "$WORK"/go/parser/_obj/_go_.8 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.8
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/plan9_386/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+8g -o "$WORK"/log/_obj/_go_.8 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.8
+cp "$WORK"/log.a "$GOROOT"/pkg/plan9_386/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+8g -o "$WORK"/path/_obj/_go_.8 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.8
+cp "$WORK"/path.a "$GOROOT"/pkg/plan9_386/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+8g -o "$WORK"/go/build/_obj/_go_.8 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.8
+cp "$WORK"/go/build.a "$GOROOT"/pkg/plan9_386/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+8g -o "$WORK"/os/exec/_obj/_go_.8 -p os/exec -I "$WORK" ./exec.go ./lp_plan9.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/plan9_386/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+8g -o "$WORK"/regexp/syntax/_obj/_go_.8 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/plan9_386/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+8g -o "$WORK"/regexp/_obj/_go_.8 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.8
+cp "$WORK"/regexp.a "$GOROOT"/pkg/plan9_386/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+8g -o "$WORK"/net/url/_obj/_go_.8 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/plan9_386/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+8g -o "$WORK"/text/template/parse/_obj/_go_.8 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/plan9_386/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+8g -o "$WORK"/text/template/_obj/_go_.8 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/plan9_386/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/plan9_386/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+8g -o "$WORK"/cmd/go/_obj/_go_.8 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.8
+8l -o "$WORK"/cmd/go/_obj/a.out -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out "$GOBIN"/go_bootstrap
diff --git a/src/buildscript/windows_386.sh b/src/buildscript/windows_386.sh
new file mode 100755
index 0000000..3a3ec03
--- /dev/null
+++ b/src/buildscript/windows_386.sh
@@ -0,0 +1,500 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=windows
+export GOARCH=386
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+8g -o "$WORK"/runtime/_obj/_go_.8 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_386.go ./zgoos_windows.go ./zruntime_defs_windows_386.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_386.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_windows_386.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_windows.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_windows.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_windows_386.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/alg.8 -DGOOS_windows -DGOARCH_386 ./alg.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/atomic_386.8 -DGOOS_windows -DGOARCH_386 ./atomic_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/callback_windows_386.8 -DGOOS_windows -DGOARCH_386 ./callback_windows_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/cgocall.8 -DGOOS_windows -DGOARCH_386 ./cgocall.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/chan.8 -DGOOS_windows -DGOARCH_386 ./chan.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/closure_386.8 -DGOOS_windows -DGOARCH_386 ./closure_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/complex.8 -DGOOS_windows -DGOARCH_386 ./complex.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/cpuprof.8 -DGOOS_windows -DGOARCH_386 ./cpuprof.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/float.8 -DGOOS_windows -DGOARCH_386 ./float.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/hashmap.8 -DGOOS_windows -DGOARCH_386 ./hashmap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/iface.8 -DGOOS_windows -DGOARCH_386 ./iface.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/lock_sema.8 -DGOOS_windows -DGOARCH_386 ./lock_sema.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/mcache.8 -DGOOS_windows -DGOARCH_386 ./mcache.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/mcentral.8 -DGOOS_windows -DGOARCH_386 ./mcentral.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/mem_windows.8 -DGOOS_windows -DGOARCH_386 ./mem_windows.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/mfinal.8 -DGOOS_windows -DGOARCH_386 ./mfinal.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/mfixalloc.8 -DGOOS_windows -DGOARCH_386 ./mfixalloc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/mgc0.8 -DGOOS_windows -DGOARCH_386 ./mgc0.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/mheap.8 -DGOOS_windows -DGOARCH_386 ./mheap.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/msize.8 -DGOOS_windows -DGOARCH_386 ./msize.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/print.8 -DGOOS_windows -DGOARCH_386 ./print.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/proc.8 -DGOOS_windows -DGOARCH_386 ./proc.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/rune.8 -DGOOS_windows -DGOARCH_386 ./rune.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/runtime.8 -DGOOS_windows -DGOARCH_386 ./runtime.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/signal_windows_386.8 -DGOOS_windows -DGOARCH_386 ./signal_windows_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/slice.8 -DGOOS_windows -DGOARCH_386 ./slice.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/symtab.8 -DGOOS_windows -DGOARCH_386 ./symtab.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/thread_windows.8 -DGOOS_windows -DGOARCH_386 ./thread_windows.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/traceback_x86.8 -DGOOS_windows -DGOARCH_386 ./traceback_x86.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/vlrt_386.8 -DGOOS_windows -DGOARCH_386 ./vlrt_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/zmalloc_386.8 -DGOOS_windows -DGOARCH_386 ./zmalloc_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/zmprof_386.8 -DGOOS_windows -DGOARCH_386 ./zmprof_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/zruntime1_386.8 -DGOOS_windows -DGOARCH_386 ./zruntime1_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/zsema_386.8 -DGOOS_windows -DGOARCH_386 ./zsema_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/zsigqueue_386.8 -DGOOS_windows -DGOARCH_386 ./zsigqueue_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/zstring_386.8 -DGOOS_windows -DGOARCH_386 ./zstring_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/zsyscall_windows_386.8 -DGOOS_windows -DGOARCH_386 ./zsyscall_windows_386.c
+8c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_386 -o "$WORK"/runtime/_obj/ztime_386.8 -DGOOS_windows -DGOARCH_386 ./ztime_386.c
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_386.8 -DGOOS_windows -DGOARCH_386 ./asm_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_386.8 -DGOOS_windows -DGOARCH_386 ./memmove_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_windows_386.8 -DGOOS_windows -DGOARCH_386 ./rt0_windows_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_windows_386.8 -DGOOS_windows -DGOARCH_386 ./sys_windows_386.s
+8a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/vlop_386.8 -DGOOS_windows -DGOARCH_386 ./vlop_386.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.8 "$WORK"/runtime/_obj/alg.8 "$WORK"/runtime/_obj/atomic_386.8 "$WORK"/runtime/_obj/callback_windows_386.8 "$WORK"/runtime/_obj/cgocall.8 "$WORK"/runtime/_obj/chan.8 "$WORK"/runtime/_obj/closure_386.8 "$WORK"/runtime/_obj/complex.8 "$WORK"/runtime/_obj/cpuprof.8 "$WORK"/runtime/_obj/float.8 "$WORK"/runtime/_obj/hashmap.8 "$WORK"/runtime/_obj/iface.8 "$WORK"/runtime/_obj/lock_sema.8 "$WORK"/runtime/_obj/mcache.8 "$WORK"/runtime/_obj/mcentral.8 "$WORK"/runtime/_obj/mem_windows.8 "$WORK"/runtime/_obj/mfinal.8 "$WORK"/runtime/_obj/mfixalloc.8 "$WORK"/runtime/_obj/mgc0.8 "$WORK"/runtime/_obj/mheap.8 "$WORK"/runtime/_obj/msize.8 "$WORK"/runtime/_obj/print.8 "$WORK"/runtime/_obj/proc.8 "$WORK"/runtime/_obj/rune.8 "$WORK"/runtime/_obj/runtime.8 "$WORK"/runtime/_obj/signal_windows_386.8 "$WORK"/runtime/_obj/slice.8 "$WORK"/runtime/_obj/symtab.8 "$WORK"/runtime/_obj/thread_windows.8 "$WORK"/runtime/_obj/traceback_x86.8 "$WORK"/runtime/_obj/vlrt_386.8 "$WORK"/runtime/_obj/zmalloc_386.8 "$WORK"/runtime/_obj/zmprof_386.8 "$WORK"/runtime/_obj/zruntime1_386.8 "$WORK"/runtime/_obj/zsema_386.8 "$WORK"/runtime/_obj/zsigqueue_386.8 "$WORK"/runtime/_obj/zstring_386.8 "$WORK"/runtime/_obj/zsyscall_windows_386.8 "$WORK"/runtime/_obj/ztime_386.8 "$WORK"/runtime/_obj/asm_386.8 "$WORK"/runtime/_obj/memmove_386.8 "$WORK"/runtime/_obj/rt0_windows_386.8 "$WORK"/runtime/_obj/sys_windows_386.8 "$WORK"/runtime/_obj/vlop_386.8
+mkdir -p "$GOROOT"/pkg/windows_386/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/windows_386/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+8g -o "$WORK"/errors/_obj/_go_.8 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.8
+cp "$WORK"/errors.a "$GOROOT"/pkg/windows_386/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+8g -o "$WORK"/sync/atomic/_obj/_go_.8 -p sync/atomic -I "$WORK" ./doc.go
+8a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_386.8 -DGOOS_windows -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.8 "$WORK"/sync/atomic/_obj/asm_386.8
+mkdir -p "$GOROOT"/pkg/windows_386/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/windows_386/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+8g -o "$WORK"/sync/_obj/_go_.8 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.8
+cp "$WORK"/sync.a "$GOROOT"/pkg/windows_386/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+8g -o "$WORK"/io/_obj/_go_.8 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.8
+cp "$WORK"/io.a "$GOROOT"/pkg/windows_386/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+8g -o "$WORK"/unicode/_obj/_go_.8 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.8
+cp "$WORK"/unicode.a "$GOROOT"/pkg/windows_386/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+8g -o "$WORK"/unicode/utf8/_obj/_go_.8 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/windows_386/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+8g -o "$WORK"/bytes/_obj/_go_.8 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+8a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_386.8 -DGOOS_windows -DGOARCH_386 ./asm_386.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.8 "$WORK"/bytes/_obj/asm_386.8
+cp "$WORK"/bytes.a "$GOROOT"/pkg/windows_386/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+8g -o "$WORK"/math/_obj/_go_.8 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_386.8 -DGOOS_windows -DGOARCH_386 ./abs_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_386.8 -DGOOS_windows -DGOARCH_386 ./asin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_386.8 -DGOOS_windows -DGOARCH_386 ./atan2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_386.8 -DGOOS_windows -DGOARCH_386 ./atan_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_386.8 -DGOOS_windows -DGOARCH_386 ./dim_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_386.8 -DGOOS_windows -DGOARCH_386 ./exp2_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_386.8 -DGOOS_windows -DGOARCH_386 ./exp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_386.8 -DGOOS_windows -DGOARCH_386 ./expm1_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_386.8 -DGOOS_windows -DGOARCH_386 ./floor_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_386.8 -DGOOS_windows -DGOARCH_386 ./frexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_386.8 -DGOOS_windows -DGOARCH_386 ./hypot_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_386.8 -DGOOS_windows -DGOARCH_386 ./ldexp_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_386.8 -DGOOS_windows -DGOARCH_386 ./log10_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_386.8 -DGOOS_windows -DGOARCH_386 ./log1p_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_386.8 -DGOOS_windows -DGOARCH_386 ./log_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_386.8 -DGOOS_windows -DGOARCH_386 ./mod_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_386.8 -DGOOS_windows -DGOARCH_386 ./modf_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_386.8 -DGOOS_windows -DGOARCH_386 ./remainder_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_386.8 -DGOOS_windows -DGOARCH_386 ./sin_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_386.8 -DGOOS_windows -DGOARCH_386 ./sincos_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_386.8 -DGOOS_windows -DGOARCH_386 ./sqrt_386.s
+8a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_386.8 -DGOOS_windows -DGOARCH_386 ./tan_386.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.8 "$WORK"/math/_obj/abs_386.8 "$WORK"/math/_obj/asin_386.8 "$WORK"/math/_obj/atan2_386.8 "$WORK"/math/_obj/atan_386.8 "$WORK"/math/_obj/dim_386.8 "$WORK"/math/_obj/exp2_386.8 "$WORK"/math/_obj/exp_386.8 "$WORK"/math/_obj/expm1_386.8 "$WORK"/math/_obj/floor_386.8 "$WORK"/math/_obj/frexp_386.8 "$WORK"/math/_obj/hypot_386.8 "$WORK"/math/_obj/ldexp_386.8 "$WORK"/math/_obj/log10_386.8 "$WORK"/math/_obj/log1p_386.8 "$WORK"/math/_obj/log_386.8 "$WORK"/math/_obj/mod_386.8 "$WORK"/math/_obj/modf_386.8 "$WORK"/math/_obj/remainder_386.8 "$WORK"/math/_obj/sin_386.8 "$WORK"/math/_obj/sincos_386.8 "$WORK"/math/_obj/sqrt_386.8 "$WORK"/math/_obj/tan_386.8
+cp "$WORK"/math.a "$GOROOT"/pkg/windows_386/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+8g -o "$WORK"/sort/_obj/_go_.8 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.8
+cp "$WORK"/sort.a "$GOROOT"/pkg/windows_386/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+8g -o "$WORK"/container/heap/_obj/_go_.8 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/windows_386/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+8g -o "$WORK"/strings/_obj/_go_.8 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.8
+cp "$WORK"/strings.a "$GOROOT"/pkg/windows_386/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+8g -o "$WORK"/strconv/_obj/_go_.8 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.8
+cp "$WORK"/strconv.a "$GOROOT"/pkg/windows_386/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+8g -o "$WORK"/encoding/base64/_obj/_go_.8 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/windows_386/encoding/base64.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+8g -o "$WORK"/unicode/utf16/_obj/_go_.8 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.8
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/windows_386/unicode/utf16.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+8g -o "$WORK"/syscall/_obj/_go_.8 -p syscall -I "$WORK" ./dll_windows.go ./env_windows.go ./exec_windows.go ./str.go ./syscall.go ./syscall_windows.go ./syscall_windows_386.go ./zerrors_windows.go ./zerrors_windows_386.go ./zsyscall_windows_386.go ./zsysnum_windows_386.go ./ztypes_windows.go ./ztypes_windows_386.go
+8a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_windows_386.8 -DGOOS_windows -DGOARCH_386 ./asm_windows_386.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.8 "$WORK"/syscall/_obj/asm_windows_386.8
+cp "$WORK"/syscall.a "$GOROOT"/pkg/windows_386/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+8g -o "$WORK"/time/_obj/_go_.8 -p time -I "$WORK" ./format.go ./sleep.go ./sys_windows.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_windows.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.8
+cp "$WORK"/time.a "$GOROOT"/pkg/windows_386/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+8g -o "$WORK"/os/_obj/_go_.8 -p os -I "$WORK" ./dir_windows.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_windows.go ./file.go ./file_posix.go ./file_windows.go ./getwd.go ./path.go ./path_windows.go ./proc.go ./stat_windows.go ./sys_windows.go ./time.go ./types.go ./zsignal_windows_386.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.8
+cp "$WORK"/os.a "$GOROOT"/pkg/windows_386/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+8g -o "$WORK"/reflect/_obj/_go_.8 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.8
+cp "$WORK"/reflect.a "$GOROOT"/pkg/windows_386/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+8g -o "$WORK"/fmt/_obj/_go_.8 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.8
+cp "$WORK"/fmt.a "$GOROOT"/pkg/windows_386/fmt.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+8g -o "$WORK"/encoding/json/_obj/_go_.8 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.8
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/windows_386/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+8g -o "$WORK"/flag/_obj/_go_.8 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.8
+cp "$WORK"/flag.a "$GOROOT"/pkg/windows_386/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+8g -o "$WORK"/bufio/_obj/_go_.8 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.8
+cp "$WORK"/bufio.a "$GOROOT"/pkg/windows_386/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+8g -o "$WORK"/encoding/gob/_obj/_go_.8 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.8
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/windows_386/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+8g -o "$WORK"/go/token/_obj/_go_.8 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/windows_386/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+8g -o "$WORK"/path/filepath/_obj/_go_.8 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_windows.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/windows_386/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+8g -o "$WORK"/go/scanner/_obj/_go_.8 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.8
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/windows_386/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+8g -o "$WORK"/go/ast/_obj/_go_.8 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.8
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/windows_386/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+8g -o "$WORK"/io/ioutil/_obj/_go_.8 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/windows_386/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+8g -o "$WORK"/go/parser/_obj/_go_.8 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.8
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/windows_386/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+8g -o "$WORK"/log/_obj/_go_.8 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.8
+cp "$WORK"/log.a "$GOROOT"/pkg/windows_386/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+8g -o "$WORK"/path/_obj/_go_.8 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.8
+cp "$WORK"/path.a "$GOROOT"/pkg/windows_386/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+8g -o "$WORK"/go/build/_obj/_go_.8 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.8
+cp "$WORK"/go/build.a "$GOROOT"/pkg/windows_386/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+8g -o "$WORK"/os/exec/_obj/_go_.8 -p os/exec -I "$WORK" ./exec.go ./lp_windows.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/windows_386/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+8g -o "$WORK"/regexp/syntax/_obj/_go_.8 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/windows_386/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+8g -o "$WORK"/regexp/_obj/_go_.8 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.8
+cp "$WORK"/regexp.a "$GOROOT"/pkg/windows_386/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+8g -o "$WORK"/net/url/_obj/_go_.8 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/windows_386/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+8g -o "$WORK"/text/template/parse/_obj/_go_.8 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/windows_386/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+8g -o "$WORK"/text/template/_obj/_go_.8 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.8
+mkdir -p "$GOROOT"/pkg/windows_386/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/windows_386/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+8g -o "$WORK"/cmd/go/_obj/_go_.8 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.8
+8l -o "$WORK"/cmd/go/_obj/a.out.exe -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out.exe "$GOBIN"/go_bootstrap.exe
diff --git a/src/buildscript/windows_amd64.sh b/src/buildscript/windows_amd64.sh
new file mode 100755
index 0000000..1858b22
--- /dev/null
+++ b/src/buildscript/windows_amd64.sh
@@ -0,0 +1,499 @@
+#!/usr/bin/env bash
+# AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
+# This script builds the go command (written in Go),
+# and then the go command can build the rest of the tree.
+
+export GOOS=windows
+export GOARCH=amd64
+export WORK=$(mktemp -d -t go-build.XXXXXX)
+trap "rm -rf $WORK" EXIT SIGINT SIGTERM
+set -e
+
+
+
+#
+# runtime
+#
+
+mkdir -p "$WORK"/runtime/_obj/
+cd "$GOROOT"/src/pkg/runtime
+6g -o "$WORK"/runtime/_obj/_go_.6 -p runtime -+ -I "$WORK" ./debug.go ./error.go ./extern.go ./mem.go ./sig.go ./softfloat64.go ./type.go ./zgoarch_amd64.go ./zgoos_windows.go ./zruntime_defs_windows_amd64.go ./zversion.go
+cp "$GOROOT"/src/pkg/runtime/arch_amd64.h "$WORK"/runtime/_obj/arch_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/defs_windows_amd64.h "$WORK"/runtime/_obj/defs_GOOS_GOARCH.h
+cp "$GOROOT"/src/pkg/runtime/os_windows.h "$WORK"/runtime/_obj/os_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/signals_windows.h "$WORK"/runtime/_obj/signals_GOOS.h
+cp "$GOROOT"/src/pkg/runtime/zasm_windows_amd64.h "$WORK"/runtime/_obj/zasm_GOOS_GOARCH.h
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/alg.6 -DGOOS_windows -DGOARCH_amd64 ./alg.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/atomic_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./atomic_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/callback_windows_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./callback_windows_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/cgocall.6 -DGOOS_windows -DGOARCH_amd64 ./cgocall.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/chan.6 -DGOOS_windows -DGOARCH_amd64 ./chan.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/closure_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./closure_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/complex.6 -DGOOS_windows -DGOARCH_amd64 ./complex.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/cpuprof.6 -DGOOS_windows -DGOARCH_amd64 ./cpuprof.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/float.6 -DGOOS_windows -DGOARCH_amd64 ./float.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/hashmap.6 -DGOOS_windows -DGOARCH_amd64 ./hashmap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/iface.6 -DGOOS_windows -DGOARCH_amd64 ./iface.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/lock_sema.6 -DGOOS_windows -DGOARCH_amd64 ./lock_sema.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/mcache.6 -DGOOS_windows -DGOARCH_amd64 ./mcache.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/mcentral.6 -DGOOS_windows -DGOARCH_amd64 ./mcentral.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/mem_windows.6 -DGOOS_windows -DGOARCH_amd64 ./mem_windows.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/mfinal.6 -DGOOS_windows -DGOARCH_amd64 ./mfinal.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/mfixalloc.6 -DGOOS_windows -DGOARCH_amd64 ./mfixalloc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/mgc0.6 -DGOOS_windows -DGOARCH_amd64 ./mgc0.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/mheap.6 -DGOOS_windows -DGOARCH_amd64 ./mheap.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/msize.6 -DGOOS_windows -DGOARCH_amd64 ./msize.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/print.6 -DGOOS_windows -DGOARCH_amd64 ./print.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/proc.6 -DGOOS_windows -DGOARCH_amd64 ./proc.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/rune.6 -DGOOS_windows -DGOARCH_amd64 ./rune.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/runtime.6 -DGOOS_windows -DGOARCH_amd64 ./runtime.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/signal_windows_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./signal_windows_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/slice.6 -DGOOS_windows -DGOARCH_amd64 ./slice.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/symtab.6 -DGOOS_windows -DGOARCH_amd64 ./symtab.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/thread_windows.6 -DGOOS_windows -DGOARCH_amd64 ./thread_windows.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/traceback_x86.6 -DGOOS_windows -DGOARCH_amd64 ./traceback_x86.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/zmalloc_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./zmalloc_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/zmprof_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./zmprof_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/zruntime1_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./zruntime1_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/zsema_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./zsema_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/zsigqueue_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./zsigqueue_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/zstring_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./zstring_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/zsyscall_windows_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./zsyscall_windows_amd64.c
+6c -FVw -I "$WORK"/runtime/_obj/ -I "$GOROOT"/pkg/windows_amd64 -o "$WORK"/runtime/_obj/ztime_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./ztime_amd64.c
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/asm_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./asm_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/memmove_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./memmove_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/rt0_windows_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./rt0_windows_amd64.s
+6a -I "$WORK"/runtime/_obj/ -o "$WORK"/runtime/_obj/sys_windows_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./sys_windows_amd64.s
+gopack grc "$WORK"/runtime.a "$WORK"/runtime/_obj/_go_.6 "$WORK"/runtime/_obj/alg.6 "$WORK"/runtime/_obj/atomic_amd64.6 "$WORK"/runtime/_obj/callback_windows_amd64.6 "$WORK"/runtime/_obj/cgocall.6 "$WORK"/runtime/_obj/chan.6 "$WORK"/runtime/_obj/closure_amd64.6 "$WORK"/runtime/_obj/complex.6 "$WORK"/runtime/_obj/cpuprof.6 "$WORK"/runtime/_obj/float.6 "$WORK"/runtime/_obj/hashmap.6 "$WORK"/runtime/_obj/iface.6 "$WORK"/runtime/_obj/lock_sema.6 "$WORK"/runtime/_obj/mcache.6 "$WORK"/runtime/_obj/mcentral.6 "$WORK"/runtime/_obj/mem_windows.6 "$WORK"/runtime/_obj/mfinal.6 "$WORK"/runtime/_obj/mfixalloc.6 "$WORK"/runtime/_obj/mgc0.6 "$WORK"/runtime/_obj/mheap.6 "$WORK"/runtime/_obj/msize.6 "$WORK"/runtime/_obj/print.6 "$WORK"/runtime/_obj/proc.6 "$WORK"/runtime/_obj/rune.6 "$WORK"/runtime/_obj/runtime.6 "$WORK"/runtime/_obj/signal_windows_amd64.6 "$WORK"/runtime/_obj/slice.6 "$WORK"/runtime/_obj/symtab.6 "$WORK"/runtime/_obj/thread_windows.6 "$WORK"/runtime/_obj/traceback_x86.6 "$WORK"/runtime/_obj/zmalloc_amd64.6 "$WORK"/runtime/_obj/zmprof_amd64.6 "$WORK"/runtime/_obj/zruntime1_amd64.6 "$WORK"/runtime/_obj/zsema_amd64.6 "$WORK"/runtime/_obj/zsigqueue_amd64.6 "$WORK"/runtime/_obj/zstring_amd64.6 "$WORK"/runtime/_obj/zsyscall_windows_amd64.6 "$WORK"/runtime/_obj/ztime_amd64.6 "$WORK"/runtime/_obj/asm_amd64.6 "$WORK"/runtime/_obj/memmove_amd64.6 "$WORK"/runtime/_obj/rt0_windows_amd64.6 "$WORK"/runtime/_obj/sys_windows_amd64.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/
+cp "$WORK"/runtime.a "$GOROOT"/pkg/windows_amd64/runtime.a
+
+#
+# errors
+#
+
+mkdir -p "$WORK"/errors/_obj/
+cd "$GOROOT"/src/pkg/errors
+6g -o "$WORK"/errors/_obj/_go_.6 -p errors -I "$WORK" ./errors.go
+gopack grc "$WORK"/errors.a "$WORK"/errors/_obj/_go_.6
+cp "$WORK"/errors.a "$GOROOT"/pkg/windows_amd64/errors.a
+
+#
+# sync/atomic
+#
+
+mkdir -p "$WORK"/sync/atomic/_obj/
+cd "$GOROOT"/src/pkg/sync/atomic
+6g -o "$WORK"/sync/atomic/_obj/_go_.6 -p sync/atomic -I "$WORK" ./doc.go
+6a -I "$WORK"/sync/atomic/_obj/ -o "$WORK"/sync/atomic/_obj/asm_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/sync/atomic.a "$WORK"/sync/atomic/_obj/_go_.6 "$WORK"/sync/atomic/_obj/asm_amd64.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/sync/
+cp "$WORK"/sync/atomic.a "$GOROOT"/pkg/windows_amd64/sync/atomic.a
+
+#
+# sync
+#
+
+mkdir -p "$WORK"/sync/_obj/
+cd "$GOROOT"/src/pkg/sync
+6g -o "$WORK"/sync/_obj/_go_.6 -p sync -I "$WORK" ./cond.go ./mutex.go ./once.go ./rwmutex.go ./waitgroup.go
+gopack grc "$WORK"/sync.a "$WORK"/sync/_obj/_go_.6
+cp "$WORK"/sync.a "$GOROOT"/pkg/windows_amd64/sync.a
+
+#
+# io
+#
+
+mkdir -p "$WORK"/io/_obj/
+cd "$GOROOT"/src/pkg/io
+6g -o "$WORK"/io/_obj/_go_.6 -p io -I "$WORK" ./io.go ./multi.go ./pipe.go
+gopack grc "$WORK"/io.a "$WORK"/io/_obj/_go_.6
+cp "$WORK"/io.a "$GOROOT"/pkg/windows_amd64/io.a
+
+#
+# unicode
+#
+
+mkdir -p "$WORK"/unicode/_obj/
+cd "$GOROOT"/src/pkg/unicode
+6g -o "$WORK"/unicode/_obj/_go_.6 -p unicode -I "$WORK" ./casetables.go ./digit.go ./graphic.go ./letter.go ./tables.go
+gopack grc "$WORK"/unicode.a "$WORK"/unicode/_obj/_go_.6
+cp "$WORK"/unicode.a "$GOROOT"/pkg/windows_amd64/unicode.a
+
+#
+# unicode/utf8
+#
+
+mkdir -p "$WORK"/unicode/utf8/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf8
+6g -o "$WORK"/unicode/utf8/_obj/_go_.6 -p unicode/utf8 -I "$WORK" ./utf8.go
+gopack grc "$WORK"/unicode/utf8.a "$WORK"/unicode/utf8/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/unicode/
+cp "$WORK"/unicode/utf8.a "$GOROOT"/pkg/windows_amd64/unicode/utf8.a
+
+#
+# bytes
+#
+
+mkdir -p "$WORK"/bytes/_obj/
+cd "$GOROOT"/src/pkg/bytes
+6g -o "$WORK"/bytes/_obj/_go_.6 -p bytes -I "$WORK" ./buffer.go ./bytes.go ./bytes_decl.go
+6a -I "$WORK"/bytes/_obj/ -o "$WORK"/bytes/_obj/asm_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./asm_amd64.s
+gopack grc "$WORK"/bytes.a "$WORK"/bytes/_obj/_go_.6 "$WORK"/bytes/_obj/asm_amd64.6
+cp "$WORK"/bytes.a "$GOROOT"/pkg/windows_amd64/bytes.a
+
+#
+# math
+#
+
+mkdir -p "$WORK"/math/_obj/
+cd "$GOROOT"/src/pkg/math
+6g -o "$WORK"/math/_obj/_go_.6 -p math -I "$WORK" ./abs.go ./acosh.go ./asin.go ./asinh.go ./atan.go ./atan2.go ./atanh.go ./bits.go ./cbrt.go ./const.go ./copysign.go ./dim.go ./erf.go ./exp.go ./expm1.go ./floor.go ./frexp.go ./gamma.go ./hypot.go ./j0.go ./j1.go ./jn.go ./ldexp.go ./lgamma.go ./log.go ./log10.go ./log1p.go ./logb.go ./mod.go ./modf.go ./nextafter.go ./pow.go ./pow10.go ./remainder.go ./signbit.go ./sin.go ./sincos.go ./sinh.go ./sqrt.go ./tan.go ./tanh.go ./unsafe.go
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/abs_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./abs_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/asin_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./asin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan2_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./atan2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/atan_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./atan_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/dim_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./dim_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp2_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./exp2_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/exp_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./exp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/expm1_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./expm1_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/floor_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./floor_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/fltasm_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./fltasm_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/frexp_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./frexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/hypot_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./hypot_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/ldexp_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./ldexp_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log10_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./log10_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log1p_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./log1p_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/log_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./log_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/mod_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./mod_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/modf_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./modf_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/remainder_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./remainder_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sin_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./sin_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sincos_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./sincos_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/sqrt_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./sqrt_amd64.s
+6a -I "$WORK"/math/_obj/ -o "$WORK"/math/_obj/tan_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./tan_amd64.s
+gopack grc "$WORK"/math.a "$WORK"/math/_obj/_go_.6 "$WORK"/math/_obj/abs_amd64.6 "$WORK"/math/_obj/asin_amd64.6 "$WORK"/math/_obj/atan2_amd64.6 "$WORK"/math/_obj/atan_amd64.6 "$WORK"/math/_obj/dim_amd64.6 "$WORK"/math/_obj/exp2_amd64.6 "$WORK"/math/_obj/exp_amd64.6 "$WORK"/math/_obj/expm1_amd64.6 "$WORK"/math/_obj/floor_amd64.6 "$WORK"/math/_obj/fltasm_amd64.6 "$WORK"/math/_obj/frexp_amd64.6 "$WORK"/math/_obj/hypot_amd64.6 "$WORK"/math/_obj/ldexp_amd64.6 "$WORK"/math/_obj/log10_amd64.6 "$WORK"/math/_obj/log1p_amd64.6 "$WORK"/math/_obj/log_amd64.6 "$WORK"/math/_obj/mod_amd64.6 "$WORK"/math/_obj/modf_amd64.6 "$WORK"/math/_obj/remainder_amd64.6 "$WORK"/math/_obj/sin_amd64.6 "$WORK"/math/_obj/sincos_amd64.6 "$WORK"/math/_obj/sqrt_amd64.6 "$WORK"/math/_obj/tan_amd64.6
+cp "$WORK"/math.a "$GOROOT"/pkg/windows_amd64/math.a
+
+#
+# sort
+#
+
+mkdir -p "$WORK"/sort/_obj/
+cd "$GOROOT"/src/pkg/sort
+6g -o "$WORK"/sort/_obj/_go_.6 -p sort -I "$WORK" ./search.go ./sort.go
+gopack grc "$WORK"/sort.a "$WORK"/sort/_obj/_go_.6
+cp "$WORK"/sort.a "$GOROOT"/pkg/windows_amd64/sort.a
+
+#
+# container/heap
+#
+
+mkdir -p "$WORK"/container/heap/_obj/
+cd "$GOROOT"/src/pkg/container/heap
+6g -o "$WORK"/container/heap/_obj/_go_.6 -p container/heap -I "$WORK" ./heap.go
+gopack grc "$WORK"/container/heap.a "$WORK"/container/heap/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/container/
+cp "$WORK"/container/heap.a "$GOROOT"/pkg/windows_amd64/container/heap.a
+
+#
+# strings
+#
+
+mkdir -p "$WORK"/strings/_obj/
+cd "$GOROOT"/src/pkg/strings
+6g -o "$WORK"/strings/_obj/_go_.6 -p strings -I "$WORK" ./reader.go ./replace.go ./strings.go
+gopack grc "$WORK"/strings.a "$WORK"/strings/_obj/_go_.6
+cp "$WORK"/strings.a "$GOROOT"/pkg/windows_amd64/strings.a
+
+#
+# strconv
+#
+
+mkdir -p "$WORK"/strconv/_obj/
+cd "$GOROOT"/src/pkg/strconv
+6g -o "$WORK"/strconv/_obj/_go_.6 -p strconv -I "$WORK" ./atob.go ./atof.go ./atoi.go ./decimal.go ./extfloat.go ./ftoa.go ./itoa.go ./quote.go
+gopack grc "$WORK"/strconv.a "$WORK"/strconv/_obj/_go_.6
+cp "$WORK"/strconv.a "$GOROOT"/pkg/windows_amd64/strconv.a
+
+#
+# encoding/base64
+#
+
+mkdir -p "$WORK"/encoding/base64/_obj/
+cd "$GOROOT"/src/pkg/encoding/base64
+6g -o "$WORK"/encoding/base64/_obj/_go_.6 -p encoding/base64 -I "$WORK" ./base64.go
+gopack grc "$WORK"/encoding/base64.a "$WORK"/encoding/base64/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/encoding/
+cp "$WORK"/encoding/base64.a "$GOROOT"/pkg/windows_amd64/encoding/base64.a
+
+#
+# unicode/utf16
+#
+
+mkdir -p "$WORK"/unicode/utf16/_obj/
+cd "$GOROOT"/src/pkg/unicode/utf16
+6g -o "$WORK"/unicode/utf16/_obj/_go_.6 -p unicode/utf16 -I "$WORK" ./utf16.go
+gopack grc "$WORK"/unicode/utf16.a "$WORK"/unicode/utf16/_obj/_go_.6
+cp "$WORK"/unicode/utf16.a "$GOROOT"/pkg/windows_amd64/unicode/utf16.a
+
+#
+# syscall
+#
+
+mkdir -p "$WORK"/syscall/_obj/
+cd "$GOROOT"/src/pkg/syscall
+6g -o "$WORK"/syscall/_obj/_go_.6 -p syscall -I "$WORK" ./dll_windows.go ./env_windows.go ./exec_windows.go ./str.go ./syscall.go ./syscall_windows.go ./syscall_windows_amd64.go ./zerrors_windows.go ./zerrors_windows_amd64.go ./zsyscall_windows_amd64.go ./zsysnum_windows_amd64.go ./ztypes_windows.go ./ztypes_windows_amd64.go
+6a -I "$WORK"/syscall/_obj/ -o "$WORK"/syscall/_obj/asm_windows_amd64.6 -DGOOS_windows -DGOARCH_amd64 ./asm_windows_amd64.s
+gopack grc "$WORK"/syscall.a "$WORK"/syscall/_obj/_go_.6 "$WORK"/syscall/_obj/asm_windows_amd64.6
+cp "$WORK"/syscall.a "$GOROOT"/pkg/windows_amd64/syscall.a
+
+#
+# time
+#
+
+mkdir -p "$WORK"/time/_obj/
+cd "$GOROOT"/src/pkg/time
+6g -o "$WORK"/time/_obj/_go_.6 -p time -I "$WORK" ./format.go ./sleep.go ./sys_windows.go ./tick.go ./time.go ./zoneinfo.go ./zoneinfo_windows.go
+gopack grc "$WORK"/time.a "$WORK"/time/_obj/_go_.6
+cp "$WORK"/time.a "$GOROOT"/pkg/windows_amd64/time.a
+
+#
+# os
+#
+
+mkdir -p "$WORK"/os/_obj/
+cd "$GOROOT"/src/pkg/os
+6g -o "$WORK"/os/_obj/_go_.6 -p os -I "$WORK" ./dir_windows.go ./doc.go ./env.go ./error.go ./error_posix.go ./exec.go ./exec_posix.go ./exec_windows.go ./file.go ./file_posix.go ./file_windows.go ./getwd.go ./path.go ./path_windows.go ./proc.go ./stat_windows.go ./sys_windows.go ./time.go ./types.go ./zsignal_windows_amd64.go
+gopack grc "$WORK"/os.a "$WORK"/os/_obj/_go_.6
+cp "$WORK"/os.a "$GOROOT"/pkg/windows_amd64/os.a
+
+#
+# reflect
+#
+
+mkdir -p "$WORK"/reflect/_obj/
+cd "$GOROOT"/src/pkg/reflect
+6g -o "$WORK"/reflect/_obj/_go_.6 -p reflect -I "$WORK" ./deepequal.go ./type.go ./value.go
+gopack grc "$WORK"/reflect.a "$WORK"/reflect/_obj/_go_.6
+cp "$WORK"/reflect.a "$GOROOT"/pkg/windows_amd64/reflect.a
+
+#
+# fmt
+#
+
+mkdir -p "$WORK"/fmt/_obj/
+cd "$GOROOT"/src/pkg/fmt
+6g -o "$WORK"/fmt/_obj/_go_.6 -p fmt -I "$WORK" ./doc.go ./format.go ./print.go ./scan.go
+gopack grc "$WORK"/fmt.a "$WORK"/fmt/_obj/_go_.6
+cp "$WORK"/fmt.a "$GOROOT"/pkg/windows_amd64/fmt.a
+
+#
+# encoding/json
+#
+
+mkdir -p "$WORK"/encoding/json/_obj/
+cd "$GOROOT"/src/pkg/encoding/json
+6g -o "$WORK"/encoding/json/_obj/_go_.6 -p encoding/json -I "$WORK" ./decode.go ./encode.go ./indent.go ./scanner.go ./stream.go ./tags.go
+gopack grc "$WORK"/encoding/json.a "$WORK"/encoding/json/_obj/_go_.6
+cp "$WORK"/encoding/json.a "$GOROOT"/pkg/windows_amd64/encoding/json.a
+
+#
+# flag
+#
+
+mkdir -p "$WORK"/flag/_obj/
+cd "$GOROOT"/src/pkg/flag
+6g -o "$WORK"/flag/_obj/_go_.6 -p flag -I "$WORK" ./flag.go
+gopack grc "$WORK"/flag.a "$WORK"/flag/_obj/_go_.6
+cp "$WORK"/flag.a "$GOROOT"/pkg/windows_amd64/flag.a
+
+#
+# bufio
+#
+
+mkdir -p "$WORK"/bufio/_obj/
+cd "$GOROOT"/src/pkg/bufio
+6g -o "$WORK"/bufio/_obj/_go_.6 -p bufio -I "$WORK" ./bufio.go
+gopack grc "$WORK"/bufio.a "$WORK"/bufio/_obj/_go_.6
+cp "$WORK"/bufio.a "$GOROOT"/pkg/windows_amd64/bufio.a
+
+#
+# encoding/gob
+#
+
+mkdir -p "$WORK"/encoding/gob/_obj/
+cd "$GOROOT"/src/pkg/encoding/gob
+6g -o "$WORK"/encoding/gob/_obj/_go_.6 -p encoding/gob -I "$WORK" ./decode.go ./decoder.go ./doc.go ./encode.go ./encoder.go ./error.go ./type.go
+gopack grc "$WORK"/encoding/gob.a "$WORK"/encoding/gob/_obj/_go_.6
+cp "$WORK"/encoding/gob.a "$GOROOT"/pkg/windows_amd64/encoding/gob.a
+
+#
+# go/token
+#
+
+mkdir -p "$WORK"/go/token/_obj/
+cd "$GOROOT"/src/pkg/go/token
+6g -o "$WORK"/go/token/_obj/_go_.6 -p go/token -I "$WORK" ./position.go ./serialize.go ./token.go
+gopack grc "$WORK"/go/token.a "$WORK"/go/token/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/go/
+cp "$WORK"/go/token.a "$GOROOT"/pkg/windows_amd64/go/token.a
+
+#
+# path/filepath
+#
+
+mkdir -p "$WORK"/path/filepath/_obj/
+cd "$GOROOT"/src/pkg/path/filepath
+6g -o "$WORK"/path/filepath/_obj/_go_.6 -p path/filepath -I "$WORK" ./match.go ./path.go ./path_windows.go
+gopack grc "$WORK"/path/filepath.a "$WORK"/path/filepath/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/path/
+cp "$WORK"/path/filepath.a "$GOROOT"/pkg/windows_amd64/path/filepath.a
+
+#
+# go/scanner
+#
+
+mkdir -p "$WORK"/go/scanner/_obj/
+cd "$GOROOT"/src/pkg/go/scanner
+6g -o "$WORK"/go/scanner/_obj/_go_.6 -p go/scanner -I "$WORK" ./errors.go ./scanner.go
+gopack grc "$WORK"/go/scanner.a "$WORK"/go/scanner/_obj/_go_.6
+cp "$WORK"/go/scanner.a "$GOROOT"/pkg/windows_amd64/go/scanner.a
+
+#
+# go/ast
+#
+
+mkdir -p "$WORK"/go/ast/_obj/
+cd "$GOROOT"/src/pkg/go/ast
+6g -o "$WORK"/go/ast/_obj/_go_.6 -p go/ast -I "$WORK" ./ast.go ./filter.go ./import.go ./print.go ./resolve.go ./scope.go ./walk.go
+gopack grc "$WORK"/go/ast.a "$WORK"/go/ast/_obj/_go_.6
+cp "$WORK"/go/ast.a "$GOROOT"/pkg/windows_amd64/go/ast.a
+
+#
+# io/ioutil
+#
+
+mkdir -p "$WORK"/io/ioutil/_obj/
+cd "$GOROOT"/src/pkg/io/ioutil
+6g -o "$WORK"/io/ioutil/_obj/_go_.6 -p io/ioutil -I "$WORK" ./ioutil.go ./tempfile.go
+gopack grc "$WORK"/io/ioutil.a "$WORK"/io/ioutil/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/io/
+cp "$WORK"/io/ioutil.a "$GOROOT"/pkg/windows_amd64/io/ioutil.a
+
+#
+# go/parser
+#
+
+mkdir -p "$WORK"/go/parser/_obj/
+cd "$GOROOT"/src/pkg/go/parser
+6g -o "$WORK"/go/parser/_obj/_go_.6 -p go/parser -I "$WORK" ./interface.go ./parser.go
+gopack grc "$WORK"/go/parser.a "$WORK"/go/parser/_obj/_go_.6
+cp "$WORK"/go/parser.a "$GOROOT"/pkg/windows_amd64/go/parser.a
+
+#
+# log
+#
+
+mkdir -p "$WORK"/log/_obj/
+cd "$GOROOT"/src/pkg/log
+6g -o "$WORK"/log/_obj/_go_.6 -p log -I "$WORK" ./log.go
+gopack grc "$WORK"/log.a "$WORK"/log/_obj/_go_.6
+cp "$WORK"/log.a "$GOROOT"/pkg/windows_amd64/log.a
+
+#
+# path
+#
+
+mkdir -p "$WORK"/path/_obj/
+cd "$GOROOT"/src/pkg/path
+6g -o "$WORK"/path/_obj/_go_.6 -p path -I "$WORK" ./match.go ./path.go
+gopack grc "$WORK"/path.a "$WORK"/path/_obj/_go_.6
+cp "$WORK"/path.a "$GOROOT"/pkg/windows_amd64/path.a
+
+#
+# go/build
+#
+
+mkdir -p "$WORK"/go/build/_obj/
+cd "$GOROOT"/src/pkg/go/build
+6g -o "$WORK"/go/build/_obj/_go_.6 -p go/build -I "$WORK" ./build.go ./dir.go ./path.go ./syslist.go
+gopack grc "$WORK"/go/build.a "$WORK"/go/build/_obj/_go_.6
+cp "$WORK"/go/build.a "$GOROOT"/pkg/windows_amd64/go/build.a
+
+#
+# os/exec
+#
+
+mkdir -p "$WORK"/os/exec/_obj/
+cd "$GOROOT"/src/pkg/os/exec
+6g -o "$WORK"/os/exec/_obj/_go_.6 -p os/exec -I "$WORK" ./exec.go ./lp_windows.go
+gopack grc "$WORK"/os/exec.a "$WORK"/os/exec/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/os/
+cp "$WORK"/os/exec.a "$GOROOT"/pkg/windows_amd64/os/exec.a
+
+#
+# regexp/syntax
+#
+
+mkdir -p "$WORK"/regexp/syntax/_obj/
+cd "$GOROOT"/src/pkg/regexp/syntax
+6g -o "$WORK"/regexp/syntax/_obj/_go_.6 -p regexp/syntax -I "$WORK" ./compile.go ./parse.go ./perl_groups.go ./prog.go ./regexp.go ./simplify.go
+gopack grc "$WORK"/regexp/syntax.a "$WORK"/regexp/syntax/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/regexp/
+cp "$WORK"/regexp/syntax.a "$GOROOT"/pkg/windows_amd64/regexp/syntax.a
+
+#
+# regexp
+#
+
+mkdir -p "$WORK"/regexp/_obj/
+cd "$GOROOT"/src/pkg/regexp
+6g -o "$WORK"/regexp/_obj/_go_.6 -p regexp -I "$WORK" ./exec.go ./regexp.go
+gopack grc "$WORK"/regexp.a "$WORK"/regexp/_obj/_go_.6
+cp "$WORK"/regexp.a "$GOROOT"/pkg/windows_amd64/regexp.a
+
+#
+# net/url
+#
+
+mkdir -p "$WORK"/net/url/_obj/
+cd "$GOROOT"/src/pkg/net/url
+6g -o "$WORK"/net/url/_obj/_go_.6 -p net/url -I "$WORK" ./url.go
+gopack grc "$WORK"/net/url.a "$WORK"/net/url/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/net/
+cp "$WORK"/net/url.a "$GOROOT"/pkg/windows_amd64/net/url.a
+
+#
+# text/template/parse
+#
+
+mkdir -p "$WORK"/text/template/parse/_obj/
+cd "$GOROOT"/src/pkg/text/template/parse
+6g -o "$WORK"/text/template/parse/_obj/_go_.6 -p text/template/parse -I "$WORK" ./lex.go ./node.go ./parse.go
+gopack grc "$WORK"/text/template/parse.a "$WORK"/text/template/parse/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/text/template/
+cp "$WORK"/text/template/parse.a "$GOROOT"/pkg/windows_amd64/text/template/parse.a
+
+#
+# text/template
+#
+
+mkdir -p "$WORK"/text/template/_obj/
+cd "$GOROOT"/src/pkg/text/template
+6g -o "$WORK"/text/template/_obj/_go_.6 -p text/template -I "$WORK" ./doc.go ./exec.go ./funcs.go ./helper.go ./template.go
+gopack grc "$WORK"/text/template.a "$WORK"/text/template/_obj/_go_.6
+mkdir -p "$GOROOT"/pkg/windows_amd64/text/
+cp "$WORK"/text/template.a "$GOROOT"/pkg/windows_amd64/text/template.a
+
+#
+# cmd/go
+#
+
+mkdir -p "$WORK"/cmd/go/_obj/
+cd "$GOROOT"/src/cmd/go
+6g -o "$WORK"/cmd/go/_obj/_go_.6 -p cmd/go -I "$WORK" ./bootstrap.go ./build.go ./fix.go ./fmt.go ./get.go ./help.go ./list.go ./main.go ./pkg.go ./run.go ./test.go ./testflag.go ./vcs.go ./version.go ./vet.go
+gopack grc "$WORK"/cmd/go.a "$WORK"/cmd/go/_obj/_go_.6
+6l -o "$WORK"/cmd/go/_obj/a.out.exe -L "$WORK" "$WORK"/cmd/go.a
+mkdir -p "$GOBIN"/
+cp "$WORK"/cmd/go/_obj/a.out.exe "$GOBIN"/go_bootstrap.exe
diff --git a/src/clean.bash b/src/clean.bash
index 1955b58..4930c25 100755
--- a/src/clean.bash
+++ b/src/clean.bash
@@ -22,7 +22,9 @@ rm -f "$GOROOT"/lib/*.a
 for i in lib9 libbio libmach cmd pkg \
 	../misc/cgo/gmp ../misc/cgo/stdio \
 	../misc/cgo/life ../misc/cgo/test \
-	../test/bench ../test/garbage
+	../misc/dashboard/builder ../misc/goplay\
+	../doc/codelab/wiki\
+	../test/bench/shootout ../test/bench/garbage ../test/bench/go1
 do
 	# Do not use gomake here. It may not be available.
 	$MAKE -C "$GOROOT/src/$i" clean
diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h
index 5349114..2065268 100644
--- a/src/cmd/5c/gc.h
+++ b/src/cmd/5c/gc.h
@@ -304,7 +304,8 @@ void	gpseudo(int, Sym*, Node*);
 int	swcmp(const void*, const void*);
 void	doswit(Node*);
 void	swit1(C1*, int, int32, Node*);
-void	cas(void);
+void	swit2(C1*, int, int32, Node*);
+void	newcase(void);
 void	bitload(Node*, Node*, Node*, Node*, Node*);
 void	bitstore(Node*, Node*, Node*, Node*, Node*);
 int	mulcon(Node*, Node*);
diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c
index 3203253..7268f9a 100644
--- a/src/cmd/5c/swt.c
+++ b/src/cmd/5c/swt.c
@@ -28,12 +28,31 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-
 #include "gc.h"
 
 void
 swit1(C1 *q, int nc, int32 def, Node *n)
 {
+	Node nreg;
+
+	if(typev[n->type->etype]) {
+		regsalloc(&nreg, n);
+		nreg.type = types[TVLONG];
+		cgen(n, &nreg);
+		swit2(q, nc, def, &nreg);
+		return;
+	}
+
+	regalloc(&nreg, n, Z);
+	nreg.type = types[TLONG];
+	cgen(n, &nreg);
+	swit2(q, nc, def, &nreg);
+	regfree(&nreg);
+}
+
+void
+swit2(C1 *q, int nc, int32 def, Node *n)
+{
 	C1 *r;
 	int i;
 	int32 v;
@@ -65,12 +84,12 @@ swit1(C1 *q, int nc, int32 def, Node *n)
 	sp = p;
 	gopcode(OEQ, nodconst(r->val), n, Z);	/* just gen the B.EQ */
 	patch(p, r->label);
-	swit1(q, i, def, n);
+	swit2(q, i, def, n);
 
 	if(debug['W'])
 		print("case < %.8ux\n", r->val);
 	patch(sp, pc);
-	swit1(r+1, nc-i-1, def, n);
+	swit2(r+1, nc-i-1, def, n);
 	return;
 
 direct:
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 0ea8695..8865027 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -213,11 +213,11 @@ cgen(Node *n, Node *res)
 		goto ret;
 
 	case OMINUS:
+		regalloc(&n1, nl->type, N);
+		cgen(nl, &n1);
 		nodconst(&n3, nl->type, 0);
 		regalloc(&n2, nl->type, res);
-		regalloc(&n1, nl->type, N);
 		gmove(&n3, &n2);
-		cgen(nl, &n1);
 		gins(optoas(OSUB, nl->type), &n1, &n2);
 		gmove(&n2, res);
 		regfree(&n1);
@@ -850,6 +850,7 @@ bgen(Node *n, int true, Prog *to)
 	int et, a;
 	Node *nl, *nr, *r;
 	Node n1, n2, n3, n4, tmp;
+	NodeList *ll;
 	Prog *p1, *p2;
 
 	USED(n4);			// in unreachable code below
@@ -950,7 +951,10 @@ bgen(Node *n, int true, Prog *to)
 				p1 = gbranch(AB, T);
 				p2 = gbranch(AB, T);
 				patch(p1, pc);
+				ll = n->ninit;
+				n->ninit = nil;
 				bgen(n, 1, p2);
+				n->ninit = ll;
 				patch(gbranch(AB, T), to);
 				patch(p2, pc);
 				goto ret;
@@ -1062,7 +1066,7 @@ bgen(Node *n, int true, Prog *to)
 		}
 
 		if(nr->op == OLITERAL) {
-			if(nr->val.ctype == CTINT &&  mpgetfix(nr->val.u.xval) == 0) {
+			if(isconst(nr, CTINT) &&  mpgetfix(nr->val.u.xval) == 0) {
 				gencmp0(nl, nl->type, a, to);
 				break;
 			}
@@ -1189,7 +1193,7 @@ stkof(Node *n)
  * NB: character copy assumed little endian architecture
  */
 void
-sgen(Node *n, Node *res, int32 w)
+sgen(Node *n, Node *res, int64 w)
 {
 	Node dst, src, tmp, nend;
 	int32 c, odst, osrc;
@@ -1197,14 +1201,17 @@ sgen(Node *n, Node *res, int32 w)
 	Prog *p, *ploop;
 
 	if(debug['g']) {
-		print("\nsgen w=%d\n", w);
+		print("\nsgen w=%lld\n", w);
 		dump("r", n);
 		dump("res", res);
 	}
-	if(w < 0)
-		fatal("sgen copy %d", w);
+
 	if(n->ullman >= UINF && res->ullman >= UINF)
 		fatal("sgen UINF");
+
+	if(w < 0 || (int32)w != w)
+		fatal("sgen copy %lld", w);
+
 	if(n->type == T)
 		fatal("sgen: missing type");
 
@@ -1236,7 +1243,7 @@ sgen(Node *n, Node *res, int32 w)
 		break;
 	}
 	if(w%align)
-		fatal("sgen: unaligned size %d (align=%d) for %T", w, align, n->type);
+		fatal("sgen: unaligned size %lld (align=%d) for %T", w, align, n->type);
 	c = w / align;
 
 	// offset on the stack
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index c826d26..7dbf3be 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -43,6 +43,8 @@ struct	Prog
 	uchar	scond;
 };
 
+#define TEXTFLAG reg
+
 #define REGALLOC_R0 0
 #define REGALLOC_RMAX REGEXT
 #define REGALLOC_F0 (REGALLOC_RMAX+1)
@@ -92,7 +94,7 @@ void	igen(Node*, Node*, Node*);
 void agenr(Node *n, Node *a, Node *res);
 vlong	fieldoffset(Type*, Node*);
 void	bgen(Node*, int, Prog*);
-void	sgen(Node*, Node*, int32);
+void	sgen(Node*, Node*, int64);
 void	gmove(Node*, Node*);
 Prog*	gins(int, Node*, Node*);
 int	samaddr(Node*, Node*);
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index 3f38318..832767e 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -14,7 +14,6 @@ defframe(Prog *ptxt)
 {
 	// fill in argument size
 	ptxt->to.type = D_CONST2;
-	ptxt->reg = 0; // flags
 	ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
 
 	// fill in final stack size
diff --git a/src/cmd/5g/gobj.c b/src/cmd/5g/gobj.c
index 9f728de..b562ba8 100644
--- a/src/cmd/5g/gobj.c
+++ b/src/cmd/5g/gobj.c
@@ -307,6 +307,7 @@ datastring(char *s, int len, Addr *a)
 	a->offset = widthptr+4;  // skip header
 	a->reg = NREG;
 	a->sym = sym;
+	a->node = sym->def;
 }
 
 /*
@@ -325,6 +326,7 @@ datagostring(Strlit *sval, Addr *a)
 	a->offset = 0;  // header
 	a->reg = NREG;
 	a->sym = sym;
+	a->node = sym->def;
 }
 
 void
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index f8920df..d8460ff 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -356,7 +356,7 @@ regalloc(Node *n, Type *t, Node *o)
 {
 	int i, et, fixfree, floatfree;
 
-	if(debug['r']) {
+	if(0 && debug['r']) {
 		fixfree = 0;
 		for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
 			if(reg[i] == 0)
@@ -429,7 +429,7 @@ regfree(Node *n)
 {
 	int i, fixfree, floatfree;
 
-	if(debug['r']) {
+	if(0 && debug['r']) {
 		fixfree = 0;
 		for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
 			if(reg[i] == 0)
@@ -512,8 +512,15 @@ nodarg(Type *t, int fp)
 		fatal("nodarg: offset not computed for %T", t);
 	n->xoffset = t->width;
 	n->addable = 1;
+	n->orig = t->nname;
 
 fp:
+	// Rewrite argument named _ to __,
+	// or else the assignment to _ will be
+	// discarded during code generation.
+	if(isblank(n))
+		n->sym = lookup("__");
+
 	switch(fp) {
 	default:
 		fatal("nodarg %T %d", t, fp);
@@ -1263,6 +1270,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 		a->sym = n->left->sym;
 		a->type = D_OREG;
 		a->name = D_PARAM;
+		a->node = n->left->orig;
 		break;
 
 	case ONAME:
@@ -1275,6 +1283,9 @@ naddr(Node *n, Addr *a, int canemitcode)
 		}
 		a->offset = n->xoffset;
 		a->sym = n->sym;
+		a->node = n->orig;
+		//if(a->node >= (Node*)&n)
+		//	fatal("stack node");
 		if(a->sym == S)
 			a->sym = lookup(".noname");
 		if(n->method) {
@@ -1293,8 +1304,6 @@ naddr(Node *n, Addr *a, int canemitcode)
 			break;
 		case PAUTO:
 			a->name = D_AUTO;
-			if (n->sym)
-				a->node = n->orig;
 			break;
 		case PPARAM:
 		case PPARAMOUT:
@@ -1317,6 +1326,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 			a->dval = mpgetflt(n->val.u.fval);
 			break;
 		case CTINT:
+		case CTRUNE:
 			a->sym = S;
 			a->type = D_CONST;
 			a->offset = mpgetfix(n->val.u.xval);
@@ -1774,7 +1784,7 @@ sudoaddable(int as, Node *n, Addr *a, int *w)
 
 	switch(n->op) {
 	case OLITERAL:
-		if(n->val.ctype != CTINT)
+		if(!isconst(n, CTINT))
 			break;
 		v = mpgetfix(n->val.u.xval);
 		if(v >= 32000 || v <= -32000)
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 9dd3f07..b72b9c1 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -42,6 +42,9 @@
 	int	noreturn(Prog *p);
 static	int	first	= 0;
 
+static	void	fixjmp(Prog*);
+
+
 Reg*
 rega(void)
 {
@@ -92,8 +95,8 @@ setoutvar(void)
 			ovar.b[z] |= bit.b[z];
 		t = structnext(&save);
 	}
-//if(bany(b))
-//print("ovars = %Q\n", &ovar);
+//if(bany(ovar))
+//print("ovar = %Q\n", ovar);
 }
 
 void
@@ -171,6 +174,8 @@ regopt(Prog *firstp)
 	if(first == 0) {
 		fmtinstall('Q', Qconv);
 	}
+	
+	fixjmp(firstp);
 
 	first++;
 	if(debug['K']) {
@@ -911,10 +916,12 @@ mkvar(Reg *r, Adr *a)
 	}
 
 	node = a->node;
-	if(node == N || node->op != ONAME || node->orig != N)
+	if(node == N || node->op != ONAME || node->orig == N)
 		goto none;
 	node = node->orig;
-	if(node->sym->name[0] == '.')
+	if(node->orig != node)
+		fatal("%D: bad node", a);
+	if(node->sym == S || node->sym->name[0] == '.')
 		goto none;
 	et = a->etype;
 	o = a->offset;
@@ -1157,10 +1164,12 @@ loopit(Reg *r, int32 nr)
 		r1 = rpo2r[i];
 		me = r1->rpo;
 		d = -1;
-		if(r1->p1 != R && r1->p1->rpo < me)
+		// rpo2r[r->rpo] == r protects against considering dead code,
+		// which has r->rpo == 0.
+		if(r1->p1 != R && rpo2r[r1->p1->rpo] == r1->p1 && r1->p1->rpo < me)
 			d = r1->p1->rpo;
 		for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
-			if(r1->rpo < me)
+			if(rpo2r[r1->rpo] == r1 && r1->rpo < me)
 				d = rpolca(idom, d, r1->rpo);
 		idom[i] = d;
 	}
@@ -1571,7 +1580,7 @@ dumpone(Reg *r)
 		if(bany(&r->refahead))
 			print(" ra:%Q ", r->refahead);
 		if(bany(&r->calbehind))
-			print("cb:%Q ", r->calbehind);
+			print(" cb:%Q ", r->calbehind);
 		if(bany(&r->calahead))
 			print(" ca:%Q ", r->calahead);
 		if(bany(&r->regdiff))
@@ -1606,3 +1615,123 @@ dumpit(char *str, Reg *r0)
 //		}
 	}
 }
+
+/*
+ * the code generator depends on being able to write out JMP (B)
+ * instructions that it can jump to now but fill in later.
+ * the linker will resolve them nicely, but they make the code
+ * longer and more difficult to follow during debugging.
+ * remove them.
+ */
+
+/* what instruction does a JMP to p eventually land on? */
+static Prog*
+chasejmp(Prog *p, int *jmploop)
+{
+	int n;
+
+	n = 0;
+	while(p != P && p->as == AB && p->to.type == D_BRANCH) {
+		if(++n > 10) {
+			*jmploop = 1;
+			break;
+		}
+		p = p->to.branch;
+	}
+	return p;
+}
+
+/*
+ * reuse reg pointer for mark/sweep state.
+ * leave reg==nil at end because alive==nil.
+ */
+#define alive ((void*)0)
+#define dead ((void*)1)
+
+/* mark all code reachable from firstp as alive */
+static void
+mark(Prog *firstp)
+{
+	Prog *p;
+	
+	for(p=firstp; p; p=p->link) {
+		if(p->regp != dead)
+			break;
+		p->regp = alive;
+		if(p->as != ABL && p->to.type == D_BRANCH && p->to.branch)
+			mark(p->to.branch);
+		if(p->as == AB || p->as == ARET || (p->as == ABL && noreturn(p)))
+			break;
+	}
+}
+
+static void
+fixjmp(Prog *firstp)
+{
+	int jmploop;
+	Prog *p, *last;
+	
+	if(debug['R'] && debug['v'])
+		print("\nfixjmp\n");
+
+	// pass 1: resolve jump to B, mark all code as dead.
+	jmploop = 0;
+	for(p=firstp; p; p=p->link) {
+		if(debug['R'] && debug['v'])
+			print("%P\n", p);
+		if(p->as != ABL && p->to.type == D_BRANCH && p->to.branch && p->to.branch->as == AB) {
+			p->to.branch = chasejmp(p->to.branch, &jmploop);
+			if(debug['R'] && debug['v'])
+				print("->%P\n", p);
+		}
+		p->regp = dead;
+	}
+	if(debug['R'] && debug['v'])
+		print("\n");
+
+	// pass 2: mark all reachable code alive
+	mark(firstp);
+	
+	// pass 3: delete dead code (mostly JMPs).
+	last = nil;
+	for(p=firstp; p; p=p->link) {
+		if(p->regp == dead) {
+			if(p->link == P && p->as == ARET && last && last->as != ARET) {
+				// This is the final ARET, and the code so far doesn't have one.
+				// Let it stay.
+			} else {
+				if(debug['R'] && debug['v'])
+					print("del %P\n", p);
+				continue;
+			}
+		}
+		if(last)
+			last->link = p;
+		last = p;
+	}
+	last->link = P;
+	
+	// pass 4: elide JMP to next instruction.
+	// only safe if there are no jumps to JMPs anymore.
+	if(!jmploop) {
+		last = nil;
+		for(p=firstp; p; p=p->link) {
+			if(p->as == AB && p->to.type == D_BRANCH && p->to.branch == p->link) {
+				if(debug['R'] && debug['v'])
+					print("del %P\n", p);
+				continue;
+			}
+			if(last)
+				last->link = p;
+			last = p;
+		}
+		last->link = P;
+	}
+	
+	if(debug['R'] && debug['v']) {
+		print("\n");
+		for(p=firstp; p; p=p->link)
+			print("%P\n", p);
+		print("\n");
+	}
+}
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 5b7f6f1..fe3a2f3 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -73,6 +73,7 @@ enum {
 	ElfStrShstrtab,
 	ElfStrRelPlt,
 	ElfStrPlt,
+	ElfStrNoteNetbsdIdent,
 	NElfStr
 };
 
@@ -164,6 +165,8 @@ doelf(void)
 	elfstr[ElfStrText] = addstring(shstrtab, ".text");
 	elfstr[ElfStrData] = addstring(shstrtab, ".data");
 	elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
+	if(HEADTYPE == Hnetbsd)
+		elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
 	addstring(shstrtab, ".rodata");
 	addstring(shstrtab, ".gosymtab");
 	addstring(shstrtab, ".gopclntab");
@@ -232,7 +235,7 @@ doelf(void)
 		/* define dynamic elf table */
 		s = lookup(".dynamic", 0);
 		s->reachable = 1;
-		s->type = SELFROSECT;
+		s->type = SELFSECT; // writable
 
 		/*
 		 * .dynamic table
@@ -251,6 +254,7 @@ doelf(void)
 		elfwritedynent(s, DT_PLTREL, DT_REL);
 		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
 		elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
+		elfwritedynent(s, DT_DEBUG, 0);
 		elfwritedynent(s, DT_NULL, 0);
 	}
 }
@@ -293,7 +297,7 @@ asmb(void)
 {
 	int32 t;
 	int a, dynsym;
-	uint32 fo, symo, startva;
+	uint32 fo, symo, startva, resoff;
 	ElfEhdr *eh;
 	ElfPhdr *ph, *pph;
 	ElfShdr *sh;
@@ -321,11 +325,6 @@ asmb(void)
 	cseek(segdata.fileoff);
 	datblk(segdata.vaddr, segdata.filelen);
 
-	/* output read-only data in text segment */
-	sect = segtext.sect->next;
-	cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
-	datblk(sect->vaddr, sect->len);
-
 	if(iself) {
 		/* index of elf text section; needed by asmelfsym, double-checked below */
 		/* !debug['d'] causes extra sections before the .text section */
@@ -335,6 +334,8 @@ asmb(void)
 			if(elfverneed)
 				elftextsh += 2;
 		}
+		if(HEADTYPE == Hnetbsd)
+			elftextsh += 1;
 	}
 
 	/* output symbol table */
@@ -370,7 +371,7 @@ asmb(void)
 		cseek(symo);
 		if(iself) {
 			if(debug['v'])
-			       Bprint(&bso, "%5.2f elfsym\n", cputime());
+				Bprint(&bso, "%5.2f elfsym\n", cputime());
 			asmelfsym();
 			cflush();
 			cwrite(elfstrdat, elfstrsize);
@@ -454,6 +455,7 @@ asmb(void)
 		eh = getElfEhdr();
 		fo = HEADR;
 		startva = INITTEXT - fo;	/* va of byte 0 of file */
+		resoff = ELFRESERVE;
 		
 		/* This null SHdr must appear before all others */
 		newElfShdr(elfstr[ElfStrEmpty]);
@@ -486,7 +488,7 @@ asmb(void)
 			sh->addralign = 1;
 			if(interpreter == nil)
 				interpreter = linuxdynld;
-			elfinterp(sh, startva, interpreter);
+			resoff -= elfinterp(sh, startva, resoff, interpreter);
 
 			ph = newElfPhdr();
 			ph->type = PT_INTERP;
@@ -494,11 +496,24 @@ asmb(void)
 			phsh(ph, sh);
 		}
 
+		if(HEADTYPE == Hnetbsd) {
+			sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
+			sh->type = SHT_NOTE;
+			sh->flags = SHF_ALLOC;
+			sh->addralign = 4;
+			resoff -= elfnetbsdsig(sh, startva, resoff);
+
+			ph = newElfPhdr();
+			ph->type = PT_NOTE;
+			ph->flags = PF_R;
+			phsh(ph, sh);
+		}
+
 		elfphload(&segtext);
 		elfphload(&segdata);
 
 		/* Dynamic linking sections */
-		if (!debug['d']) {	/* -d suppresses dynamic loader format */
+		if(!debug['d']) {	/* -d suppresses dynamic loader format */
 			/* S headers for dynamic linking */
 			sh = newElfShdr(elfstr[ElfStrGot]);
 			sh->type = SHT_PROGBITS;
@@ -589,7 +604,7 @@ asmb(void)
 		for(sect=segdata.sect; sect!=nil; sect=sect->next)
 			elfshbits(sect);
 
-		if (!debug['s']) {
+		if(!debug['s']) {
 			sh = newElfShdr(elfstr[ElfStrSymtab]);
 			sh->type = SHT_SYMTAB;
 			sh->off = symo;
@@ -631,8 +646,10 @@ asmb(void)
 		a += elfwritehdr();
 		a += elfwritephdrs();
 		a += elfwriteshdrs();
-		cflush();
-		if(a+elfwriteinterp() > ELFRESERVE)	
+		a += elfwriteinterp(elfstr[ElfStrInterp]);
+		if(HEADTYPE == Hnetbsd)
+			a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
+		if(a > ELFRESERVE)	
 			diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
 		break;
 	}
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index dabe93d..b1a48de 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -143,6 +143,7 @@ struct	Sym
 	int32	value;
 	int32	sig;
 	int32	size;
+	int32	align;	// if non-zero, required alignment in bytes
 	uchar	special;
 	uchar	fnptr;	// used as fn ptr
 	Sym*	hash;	// in hash table
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index fc5806a..1496719 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -136,6 +136,11 @@ main(int argc, char *argv[])
 	case 'V':
 		print("%cl version %s\n", thechar, getgoversion());
 		errorexit();
+	case 'X':
+		// TODO: golang.org/issue/2676
+		EARGF(usage());
+		EARGF(usage());
+		break;
 	} ARGEND
 
 	USED(argc);
@@ -585,6 +590,10 @@ loop:
 			errorexit();
 		}
 		cursym = s;
+		if(s->type != 0 && s->type != SXREF && (p->reg & DUPOK)) {
+			skip = 1;
+			goto casedef;
+		}
 		if(ntext++ == 0 && s->type != 0 && s->type != SXREF) {
 			/* redefinition, so file has probably been seen before */
 			if(debug['v'])
@@ -592,13 +601,8 @@ loop:
 			return;
 		}
 		skip = 0;
-		if(s->type != 0 && s->type != SXREF) {
-			if(p->reg & DUPOK) {
-				skip = 1;
-				goto casedef;
-			}
+		if(s->type != 0 && s->type != SXREF)
 			diag("redefinition: %s\n%P", s->name, p);
-		}
 		if(etextp)
 			etextp->next = s;
 		else
diff --git a/src/cmd/6a/a.y b/src/cmd/6a/a.y
index c0fa410..8459ff3 100644
--- a/src/cmd/6a/a.y
+++ b/src/cmd/6a/a.y
@@ -429,6 +429,12 @@ imm:
 		$$.type = D_FCONST;
 		$$.dval = $3;
 	}
+|	'$' '(' '-' LFCONST ')'
+	{
+		$$ = nullgen;
+		$$.type = D_FCONST;
+		$$.dval = -$4;
+	}
 |	'$' '-' LFCONST
 	{
 		$$ = nullgen;
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
index 7f717dc..7182258 100644
--- a/src/cmd/6c/cgen.c
+++ b/src/cmd/6c/cgen.c
@@ -1237,11 +1237,12 @@ void
 boolgen(Node *n, int true, Node *nn)
 {
 	int o;
-	Prog *p1, *p2;
+	Prog *p1, *p2, *p3;
 	Node *l, *r, nod, nod1;
 	int32 curs;
 
 	if(debug['g']) {
+		print("boolgen %d\n", true);
 		prtree(nn, "boolgen lhs");
 		prtree(n, "boolgen");
 	}
@@ -1353,6 +1354,15 @@ boolgen(Node *n, int true, Node *nn)
 	case OLO:
 	case OLS:
 		o = n->op;
+		if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
+			// Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
+			// Jump around instead.
+			boolgen(n, 0, Z);
+			p1 = p;
+			gbranch(OGOTO);
+			patch(p1, pc);
+			goto com;
+		}
 		if(true)
 			o = comrel[relindex(o)];
 		if(l->complex >= FNX && r->complex >= FNX) {
@@ -1367,6 +1377,10 @@ boolgen(Node *n, int true, Node *nn)
 			break;
 		}
 		if(immconst(l)) {
+			// NOTE: Reversing the comparison here is wrong
+			// for floating point ordering comparisons involving NaN,
+			// but we don't have any of those yet so we don't
+			// bother worrying about it.
 			o = invrel[relindex(o)];
 			/* bad, 13 is address of external that becomes constant */
 			if(r->addable < INDEXED || r->addable == 13) {
@@ -1388,10 +1402,11 @@ boolgen(Node *n, int true, Node *nn)
 				cgen(r, &nod1);
 				gopcode(o, l->type, &nod, &nod1);
 				regfree(&nod1);
-			} else
+			} else {
 				gopcode(o, l->type, &nod, r);
+			}
 			regfree(&nod);
-			goto com;
+			goto fixfloat;
 		}
 		regalloc(&nod, r, nn);
 		cgen(r, &nod);
@@ -1406,6 +1421,33 @@ boolgen(Node *n, int true, Node *nn)
 		} else
 			gopcode(o, l->type, l, &nod);
 		regfree(&nod);
+	fixfloat:
+		if(typefd[l->type->etype]) {
+			switch(o) {
+			case OEQ:
+				// Already emitted AJEQ; want AJEQ and AJPC.
+				p1 = p;
+				gbranch(OGOTO);
+				p2 = p;
+				patch(p1, pc);
+				gins(AJPC, Z, Z);
+				patch(p2, pc);
+				break;
+
+			case ONE:
+				// Already emitted AJNE; want AJNE or AJPS.
+				p1 = p;
+				gins(AJPS, Z, Z);
+				p2 = p;
+				gbranch(OGOTO);
+				p3 = p;
+				patch(p1, pc);
+				patch(p2, pc);
+				gbranch(OGOTO);
+				patch(p3, pc);
+				break;
+			}
+		}
 
 	com:
 		if(nn != Z) {
diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h
index 0c23b11..b0081ab 100644
--- a/src/cmd/6c/gc.h
+++ b/src/cmd/6c/gc.h
@@ -299,7 +299,8 @@ void	gpseudo(int, Sym*, Node*);
 int	swcmp(const void*, const void*);
 void	doswit(Node*);
 void	swit1(C1*, int, int32, Node*);
-void	cas(void);
+void	swit2(C1*, int, int32, Node*);
+void	newcase(void);
 void	bitload(Node*, Node*, Node*, Node*, Node*);
 void	bitstore(Node*, Node*, Node*, Node*, Node*);
 int32	outstring(char*, int32);
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
index 3de8630..f16d0f7 100644
--- a/src/cmd/6c/swt.c
+++ b/src/cmd/6c/swt.c
@@ -33,6 +33,21 @@
 void
 swit1(C1 *q, int nc, int32 def, Node *n)
 {
+	Node nreg;
+
+	regalloc(&nreg, n, Z);
+	if(typev[n->type->etype])
+		nreg.type = types[TVLONG];
+	else
+		nreg.type = types[TLONG];
+	cgen(n, &nreg);
+	swit2(q, nc, def, &nreg);
+	regfree(&nreg);
+}
+
+void
+swit2(C1 *q, int nc, int32 def, Node *n)
+{
 	C1 *r;
 	int i;
 	Prog *sp;
@@ -58,12 +73,12 @@ swit1(C1 *q, int nc, int32 def, Node *n)
 	gbranch(OGOTO);
 	p->as = AJEQ;
 	patch(p, r->label);
-	swit1(q, i, def, n);
+	swit2(q, i, def, n);
 
 	if(debug['W'])
 		print("case < %.8llux\n", r->val);
 	patch(sp, pc);
-	swit1(r+1, nc-i-1, def, n);
+	swit2(r+1, nc-i-1, def, n);
 }
 
 void
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index 43bec00..fd84932 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -717,6 +717,7 @@ bgen(Node *n, int true, Prog *to)
 	int et, a;
 	Node *nl, *nr, *l, *r;
 	Node n1, n2, tmp;
+	NodeList *ll;
 	Prog *p1, *p2;
 
 	if(debug['g']) {
@@ -834,7 +835,10 @@ bgen(Node *n, int true, Prog *to)
 				p1 = gbranch(AJMP, T);
 				p2 = gbranch(AJMP, T);
 				patch(p1, pc);
+				ll = n->ninit;   // avoid re-genning ninit
+				n->ninit = nil;
 				bgen(n, 1, p2);
+				n->ninit = ll;
 				patch(gbranch(AJMP, T), to);
 				patch(p2, pc);
 				goto ret;
@@ -1019,13 +1023,13 @@ stkof(Node *n)
  *	memmove(&ns, &n, w);
  */
 void
-sgen(Node *n, Node *ns, int32 w)
+sgen(Node *n, Node *ns, int64 w)
 {
 	Node nodl, nodr, oldl, oldr, cx, oldcx, tmp;
 	int32 c, q, odst, osrc;
 
 	if(debug['g']) {
-		print("\nsgen w=%d\n", w);
+		print("\nsgen w=%lld\n", w);
 		dump("r", n);
 		dump("res", ns);
 	}
@@ -1034,7 +1038,7 @@ sgen(Node *n, Node *ns, int32 w)
 		fatal("sgen UINF");
 
 	if(w < 0)
-		fatal("sgen copy %d", w);
+		fatal("sgen copy %lld", w);
 
 	if(w == 16)
 		if(componentgen(n, ns))
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index 8a80ee9..47a5400 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -41,6 +41,8 @@ struct	Prog
 	void*	reg;		// pointer to containing Reg struct
 };
 
+#define TEXTFLAG from.scale
+
 EXTERN	int32	dynloc;
 EXTERN	uchar	reg[D_NONE];
 EXTERN	int32	pcloc;		// instruction counter
@@ -85,7 +87,7 @@ void	agen(Node*, Node*);
 void	igen(Node*, Node*, Node*);
 vlong	fieldoffset(Type*, Node*);
 void	bgen(Node*, int, Prog*);
-void	sgen(Node*, Node*, int32);
+void	sgen(Node*, Node*, int64);
 void	gmove(Node*, Node*);
 Prog*	gins(int, Node*, Node*);
 int	samaddr(Node*, Node*);
diff --git a/src/cmd/6g/gobj.c b/src/cmd/6g/gobj.c
index 4dcce39..80de2f7 100644
--- a/src/cmd/6g/gobj.c
+++ b/src/cmd/6g/gobj.c
@@ -310,6 +310,7 @@ datastring(char *s, int len, Addr *a)
 	sym = stringsym(s, len);
 	a->type = D_EXTERN;
 	a->sym = sym;
+	a->node = sym->def;
 	a->offset = widthptr+4;  // skip header
 	a->etype = TINT32;
 }
@@ -326,6 +327,7 @@ datagostring(Strlit *sval, Addr *a)
 	sym = stringsym(sval->s, sval->len);
 	a->type = D_EXTERN;
 	a->sym = sym;
+	a->node = sym->def;
 	a->offset = 0;  // header
 	a->etype = TINT32;
 }
@@ -504,7 +506,7 @@ genembedtramp(Type *rcvr, Type *method, Sym *newnam, int iface)
 	
 	USED(iface);
 
-	if(debug['r'])
+	if(0 && debug['r'])
 		print("genembedtramp %T %T %S\n", rcvr, method, newnam);
 
 	e = method->sym;
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index 92b15ef..cf00c3c 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -481,12 +481,20 @@ nodarg(Type *t, int fp)
 	n = nod(ONAME, N, N);
 	n->type = t->type;
 	n->sym = t->sym;
+	
 	if(t->width == BADWIDTH)
 		fatal("nodarg: offset not computed for %T", t);
 	n->xoffset = t->width;
 	n->addable = 1;
+	n->orig = t->nname;
 
 fp:
+	// Rewrite argument named _ to __,
+	// or else the assignment to _ will be
+	// discarded during code generation.
+	if(isblank(n))
+		n->sym = lookup("__");
+
 	switch(fp) {
 	case 0:		// output arg
 		n->op = OINDREG;
@@ -1119,6 +1127,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 		a->offset = n->xoffset;
 		a->sym = n->left->sym;
 		a->type = D_PARAM;
+		a->node = n->left->orig;
 		break;
 
 	case ONAME:
@@ -1131,6 +1140,9 @@ naddr(Node *n, Addr *a, int canemitcode)
 		}
 		a->offset = n->xoffset;
 		a->sym = n->sym;
+		a->node = n->orig;
+		//if(a->node >= (Node*)&n)
+		//	fatal("stack node");
 		if(a->sym == S)
 			a->sym = lookup(".noname");
 		if(n->method) {
@@ -1148,8 +1160,6 @@ naddr(Node *n, Addr *a, int canemitcode)
 			break;
 		case PAUTO:
 			a->type = D_AUTO;
-			if (n->sym)
-				a->node = n->orig;
 			break;
 		case PPARAM:
 		case PPARAMOUT:
@@ -1172,6 +1182,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 			a->dval = mpgetflt(n->val.u.fval);
 			break;
 		case CTINT:
+		case CTRUNE:
 			a->sym = S;
 			a->type = D_CONST;
 			a->offset = mpgetfix(n->val.u.xval);
@@ -1875,7 +1886,7 @@ sudoaddable(int as, Node *n, Addr *a)
 
 	switch(n->op) {
 	case OLITERAL:
-		if(n->val.ctype != CTINT)
+		if(!isconst(n, CTINT))
 			break;
 		v = mpgetfix(n->val.u.xval);
 		if(v >= 32000 || v <= -32000)
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index f380ced..82a2ce3 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -89,8 +89,8 @@ setoutvar(void)
 			ovar.b[z] |= bit.b[z];
 		t = structnext(&save);
 	}
-//if(bany(b))
-//print("ovars = %Q\n", &ovar);
+//if(bany(&ovar))
+//print("ovars = %Q\n", ovar);
 }
 
 static void
@@ -151,6 +151,8 @@ static char* regname[] = {
 	".X15",
 };
 
+static void fixjmp(Prog*);
+
 void
 regopt(Prog *firstp)
 {
@@ -166,6 +168,8 @@ regopt(Prog *firstp)
 		first = 0;
 	}
 
+	fixjmp(firstp);
+
 	// count instructions
 	nr = 0;
 	for(p=firstp; p!=P; p=p->link)
@@ -800,9 +804,9 @@ brk:
 		if(ostats.ndelmov)
 			print("	%4d delmov\n", ostats.ndelmov);
 		if(ostats.nvar)
-			print("	%4d delmov\n", ostats.nvar);
+			print("	%4d var\n", ostats.nvar);
 		if(ostats.naddr)
-			print("	%4d delmov\n", ostats.naddr);
+			print("	%4d addr\n", ostats.naddr);
 
 		memset(&ostats, 0, sizeof(ostats));
 	}
@@ -968,11 +972,14 @@ mkvar(Reg *r, Adr *a)
 		n = t;
 		break;
 	}
+
 	node = a->node;
-	if(node == N || node->op != ONAME || node->orig != N)
+	if(node == N || node->op != ONAME || node->orig == N)
 		goto none;
 	node = node->orig;
-	if(node->sym->name[0] == '.')
+	if(node->orig != node)
+		fatal("%D: bad node", a);
+	if(node->sym == S || node->sym->name[0] == '.')
 		goto none;
 	et = a->etype;
 	o = a->offset;
@@ -1214,10 +1221,12 @@ loopit(Reg *r, int32 nr)
 		r1 = rpo2r[i];
 		me = r1->rpo;
 		d = -1;
-		if(r1->p1 != R && r1->p1->rpo < me)
+		// rpo2r[r->rpo] == r protects against considering dead code,
+		// which has r->rpo == 0.
+		if(r1->p1 != R && rpo2r[r1->p1->rpo] == r1->p1 && r1->p1->rpo < me)
 			d = r1->p1->rpo;
 		for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
-			if(r1->rpo < me)
+			if(rpo2r[r1->rpo] == r1 && r1->rpo < me)
 				d = rpolca(idom, d, r1->rpo);
 		idom[i] = d;
 	}
@@ -1622,7 +1631,7 @@ dumpone(Reg *r)
 		if(bany(&r->refahead))
 			print(" ra:%Q ", r->refahead);
 		if(bany(&r->calbehind))
-			print("cb:%Q ", r->calbehind);
+			print(" cb:%Q ", r->calbehind);
 		if(bany(&r->calahead))
 			print(" ca:%Q ", r->calahead);
 		if(bany(&r->regdiff))
@@ -1682,3 +1691,123 @@ noreturn(Prog *p)
 			return 1;
 	return 0;
 }
+
+/*
+ * the code generator depends on being able to write out JMP
+ * instructions that it can jump to now but fill in later.
+ * the linker will resolve them nicely, but they make the code
+ * longer and more difficult to follow during debugging.
+ * remove them.
+ */
+
+/* what instruction does a JMP to p eventually land on? */
+static Prog*
+chasejmp(Prog *p, int *jmploop)
+{
+	int n;
+
+	n = 0;
+	while(p != P && p->as == AJMP && p->to.type == D_BRANCH) {
+		if(++n > 10) {
+			*jmploop = 1;
+			break;
+		}
+		p = p->to.branch;
+	}
+	return p;
+}
+
+/*
+ * reuse reg pointer for mark/sweep state.
+ * leave reg==nil at end because alive==nil.
+ */
+#define alive ((void*)0)
+#define dead ((void*)1)
+
+/* mark all code reachable from firstp as alive */
+static void
+mark(Prog *firstp)
+{
+	Prog *p;
+	
+	for(p=firstp; p; p=p->link) {
+		if(p->reg != dead)
+			break;
+		p->reg = alive;
+		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch)
+			mark(p->to.branch);
+		if(p->as == AJMP || p->as == ARET || (p->as == ACALL && noreturn(p)))
+			break;
+	}
+}
+
+static void
+fixjmp(Prog *firstp)
+{
+	int jmploop;
+	Prog *p, *last;
+	
+	if(debug['R'] && debug['v'])
+		print("\nfixjmp\n");
+
+	// pass 1: resolve jump to AJMP, mark all code as dead.
+	jmploop = 0;
+	for(p=firstp; p; p=p->link) {
+		if(debug['R'] && debug['v'])
+			print("%P\n", p);
+		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch && p->to.branch->as == AJMP) {
+			p->to.branch = chasejmp(p->to.branch, &jmploop);
+			if(debug['R'] && debug['v'])
+				print("->%P\n", p);
+		}
+		p->reg = dead;
+	}
+	if(debug['R'] && debug['v'])
+		print("\n");
+
+	// pass 2: mark all reachable code alive
+	mark(firstp);
+	
+	// pass 3: delete dead code (mostly JMPs).
+	last = nil;
+	for(p=firstp; p; p=p->link) {
+		if(p->reg == dead) {
+			if(p->link == P && p->as == ARET && last && last->as != ARET) {
+				// This is the final ARET, and the code so far doesn't have one.
+				// Let it stay.
+			} else {
+				if(debug['R'] && debug['v'])
+					print("del %P\n", p);
+				continue;
+			}
+		}
+		if(last)
+			last->link = p;
+		last = p;
+	}
+	last->link = P;
+	
+	// pass 4: elide JMP to next instruction.
+	// only safe if there are no jumps to JMPs anymore.
+	if(!jmploop) {
+		last = nil;
+		for(p=firstp; p; p=p->link) {
+			if(p->as == AJMP && p->to.type == D_BRANCH && p->to.branch == p->link) {
+				if(debug['R'] && debug['v'])
+					print("del %P\n", p);
+				continue;
+			}
+			if(last)
+				last->link = p;
+			last = p;
+		}
+		last->link = P;
+	}
+	
+	if(debug['R'] && debug['v']) {
+		print("\n");
+		for(p=firstp; p; p=p->link)
+			print("%P\n", p);
+		print("\n");
+	}
+}
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 3a8223e..7d36b17 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -37,13 +37,12 @@
 #include	"../ld/macho.h"
 #include	"../ld/pe.h"
 
-#define	Dbufslop	100
-
 #define PADDR(a)	((uint32)(a) & ~0x80000000)
 
 char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2";
 char freebsddynld[] = "/libexec/ld-elf.so.1";
 char openbsddynld[] = "/usr/libexec/ld.so";
+char netbsddynld[] = "/libexec/ld.elf_so";
 
 char	zeroes[32];
 
@@ -95,6 +94,7 @@ enum {
 	ElfStrPlt,
 	ElfStrGnuVersion,
 	ElfStrGnuVersionR,
+	ElfStrNoteNetbsdIdent,
 	NElfStr
 };
 
@@ -558,7 +558,7 @@ doelf(void)
 {
 	Sym *s, *shstrtab, *dynstr;
 
-	if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd)
+	if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd && HEADTYPE != Hnetbsd)
 		return;
 
 	/* predefine strings we need for section headers */
@@ -570,6 +570,8 @@ doelf(void)
 	elfstr[ElfStrText] = addstring(shstrtab, ".text");
 	elfstr[ElfStrData] = addstring(shstrtab, ".data");
 	elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
+	if(HEADTYPE == Hnetbsd)
+		elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
 	addstring(shstrtab, ".elfdata");
 	addstring(shstrtab, ".rodata");
 	addstring(shstrtab, ".gosymtab");
@@ -649,7 +651,7 @@ doelf(void)
 		/* define dynamic elf table */
 		s = lookup(".dynamic", 0);
 		s->reachable = 1;
-		s->type = SELFROSECT;
+		s->type = SELFSECT; // writable
 
 		/*
 		 * .dynamic table
@@ -670,6 +672,8 @@ doelf(void)
 		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
 		elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
 		
+		elfwritedynent(s, DT_DEBUG, 0);
+
 		// Do not write DT_NULL.  elfdynhash will finish it.
 	}
 }
@@ -701,7 +705,7 @@ asmb(void)
 {
 	int32 magic;
 	int a, dynsym;
-	vlong vl, startva, symo, machlink;
+	vlong vl, startva, symo, dwarfoff, machlink, resoff;
 	ElfEhdr *eh;
 	ElfPhdr *ph, *pph;
 	ElfShdr *sh;
@@ -736,8 +740,19 @@ asmb(void)
 	datblk(segdata.vaddr, segdata.filelen);
 
 	machlink = 0;
-	if(HEADTYPE == Hdarwin)
+	if(HEADTYPE == Hdarwin) {
+		if(debug['v'])
+			Bprint(&bso, "%5.2f dwarf\n", cputime());
+
+		dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND);
+		cseek(dwarfoff);
+
+		segdwarf.fileoff = cpos();
+		dwarfemitdebugsections();
+		segdwarf.filelen = cpos() - segdwarf.fileoff;
+
 		machlink = domacholink();
+	}
 
 	switch(HEADTYPE) {
 	default:
@@ -750,6 +765,7 @@ asmb(void)
 		break;
 	case Hlinux:
 	case Hfreebsd:
+	case Hnetbsd:
 	case Hopenbsd:
 		debug['8'] = 1;	/* 64-bit addresses */
 		/* index of elf text section; needed by asmelfsym, double-checked below */
@@ -760,6 +776,8 @@ asmb(void)
 			if(elfverneed)
 				elftextsh += 2;
 		}
+		if(HEADTYPE == Hnetbsd)
+			elftextsh += 1;
 		break;
 	case Hwindows:
 		break;
@@ -785,6 +803,7 @@ asmb(void)
 			break;
 		case Hlinux:
 		case Hfreebsd:
+		case Hnetbsd:
 		case Hopenbsd:
 			symo = rnd(HEADR+segtext.len, INITRND)+segdata.filelen;
 			symo = rnd(symo, INITRND);
@@ -809,7 +828,6 @@ asmb(void)
 				dwarfemitdebugsections();
 			}
 			break;
-		case Hdarwin:
 		case Hwindows:
 			if(debug['v'])
 			       Bprint(&bso, "%5.2f dwarf\n", cputime());
@@ -855,11 +873,13 @@ asmb(void)
 		break;
 	case Hlinux:
 	case Hfreebsd:
+	case Hnetbsd:
 	case Hopenbsd:
 		/* elf amd-64 */
 
 		eh = getElfEhdr();
 		startva = INITTEXT - HEADR;
+		resoff = ELFRESERVE;
 
 		/* This null SHdr must appear before all others */
 		newElfShdr(elfstr[ElfStrEmpty]);
@@ -898,12 +918,15 @@ asmb(void)
 				case Hfreebsd:
 					interpreter = freebsddynld;
 					break;
+				case Hnetbsd:
+					interpreter = netbsddynld;
+					break;
 				case Hopenbsd:
 					interpreter = openbsddynld;
 					break;
 				}
 			}
-			elfinterp(sh, startva, interpreter);
+			resoff -= elfinterp(sh, startva, resoff, interpreter);
 
 			ph = newElfPhdr();
 			ph->type = PT_INTERP;
@@ -911,11 +934,24 @@ asmb(void)
 			phsh(ph, sh);
 		}
 
+		if(HEADTYPE == Hnetbsd) {
+			sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
+			sh->type = SHT_NOTE;
+			sh->flags = SHF_ALLOC;
+			sh->addralign = 4;
+			resoff -= elfnetbsdsig(sh, startva, resoff);
+
+			ph = newElfPhdr();
+			ph->type = PT_NOTE;
+			ph->flags = PF_R;
+			phsh(ph, sh);
+		}
+
 		elfphload(&segtext);
 		elfphload(&segdata);
 
 		/* Dynamic linking sections */
-		if (!debug['d']) {	/* -d suppresses dynamic loader format */
+		if(!debug['d']) {	/* -d suppresses dynamic loader format */
 			/* S headers for dynamic linking */
 			sh = newElfShdr(elfstr[ElfStrGot]);
 			sh->type = SHT_PROGBITS;
@@ -1039,7 +1075,7 @@ asmb(void)
 		for(sect=segdata.sect; sect!=nil; sect=sect->next)
 			elfshbits(sect);
 
-		if (!debug['s']) {
+		if(!debug['s']) {
 			sh = newElfShdr(elfstr[ElfStrSymtab]);
 			sh->type = SHT_SYMTAB;
 			sh->off = symo;
@@ -1064,6 +1100,8 @@ asmb(void)
 		eh->ident[EI_MAG3] = 'F';
 		if(HEADTYPE == Hfreebsd)
 			eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
+		else if(HEADTYPE == Hnetbsd)
+			eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
 		else if(HEADTYPE == Hopenbsd)
 			eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
 		eh->ident[EI_CLASS] = ELFCLASS64;
@@ -1083,8 +1121,10 @@ asmb(void)
 		a += elfwritehdr();
 		a += elfwritephdrs();
 		a += elfwriteshdrs();
-		cflush();
-		if(a+elfwriteinterp() > ELFRESERVE)	
+		a += elfwriteinterp(elfstr[ElfStrInterp]);
+		if(HEADTYPE == Hnetbsd)
+			a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
+		if(a > ELFRESERVE)	
 			diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
 		break;
 	case Hwindows:
diff --git a/src/cmd/6l/doc.go b/src/cmd/6l/doc.go
index b8a6013..c18b0f2 100644
--- a/src/cmd/6l/doc.go
+++ b/src/cmd/6l/doc.go
@@ -25,15 +25,14 @@ Options new in this version:
 	Elide the dynamic linking header.  With this option, the binary
 	is statically linked and does not refer to dynld.  Without this option
 	(the default), the binary's contents are identical but it is loaded with dynld.
--e
-	Emit an extra ELF-compatible symbol table useful with tools such as
-	nm, gdb, and oprofile. This option makes the binary file considerably larger.
 -Hdarwin
 	Write Apple Mach-O binaries (default when $GOOS is darwin)
 -Hlinux
 	Write Linux ELF binaries (default when $GOOS is linux)
 -Hfreebsd
 	Write FreeBSD ELF binaries (default when $GOOS is freebsd)
+-Hnetbsd
+	Write NetBSD ELF binaries (default when $GOOS is netbsd)
 -Hopenbsd
 	Write OpenBSD ELF binaries (default when $GOOS is openbsd)
 -Hwindows
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index b291d5f..5f62239 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -133,6 +133,7 @@ struct	Sym
 	int32	sig;
 	int32	plt;
 	int32	got;
+	int32	align;	// if non-zero, required alignment in bytes
 	Sym*	hash;	// in hash table
 	Sym*	allsym;	// in all symbol list
 	Sym*	next;	// in text or data list
@@ -163,7 +164,7 @@ struct	Optab
 	short	as;
 	uchar*	ytab;
 	uchar	prefix;
-	uchar	op[20];
+	uchar	op[22];
 };
 struct	Movtab
 {
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index a7ef58d..d258f05 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -44,16 +44,17 @@ char*	thestring 	= "amd64";
 char*	paramspace	= "FP";
 
 Header headers[] = {
-   "plan9x32", Hplan9x32,
-   "plan9", Hplan9x64,
-   "elf", Helf,
-   "darwin", Hdarwin,
-   "linux", Hlinux,
-   "freebsd", Hfreebsd,
-   "openbsd", Hopenbsd,
-   "windows", Hwindows,
-   "windowsgui", Hwindows,
-   0, 0
+	"plan9x32", Hplan9x32,
+	"plan9", Hplan9x64,
+	"elf", Helf,
+	"darwin", Hdarwin,
+	"linux", Hlinux,
+	"freebsd", Hfreebsd,
+	"netbsd", Hnetbsd,
+	"openbsd", Hopenbsd,
+	"windows", Hwindows,
+	"windowsgui", Hwindows,
+	0, 0
 };
 
 /*
@@ -63,6 +64,7 @@ Header headers[] = {
  *	-Hdarwin -Tx -Rx		is apple MH-exec
  *	-Hlinux -Tx -Rx			is linux elf-exec
  *	-Hfreebsd -Tx -Rx		is FreeBSD elf-exec
+ *	-Hnetbsd -Tx -Rx		is NetBSD elf-exec
  *	-Hopenbsd -Tx -Rx		is OpenBSD elf-exec
  *	-Hwindows -Tx -Rx		is MS Windows PE32+
  *
@@ -130,6 +132,11 @@ main(int argc, char *argv[])
 	case 'V':
 		print("%cl version %s\n", thechar, getgoversion());
 		errorexit();
+	case 'X':
+		// TODO: golang.org/issue/2676
+		EARGF(usage());
+		EARGF(usage());
+		break;
 	} ARGEND
 
 	if(argc != 1)
@@ -183,7 +190,7 @@ main(int argc, char *argv[])
 	case Hdarwin:	/* apple MACH */
 		/*
 		 * OS X system constant - offset from 0(GS) to our TLS.
-		 * Explained in ../../libcgo/darwin_amd64.c.
+		 * Explained in ../../pkg/runtime/cgo/gcc_darwin_amd64.c.
 		 */
 		tlsoffset = 0x8a0;
 		machoinit();
@@ -197,12 +204,13 @@ main(int argc, char *argv[])
 		break;
 	case Hlinux:	/* elf64 executable */
 	case Hfreebsd:	/* freebsd */
+	case Hnetbsd:	/* netbsd */
 	case Hopenbsd:	/* openbsd */
 		/*
 		 * ELF uses TLS offset negative from FS.
 		 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
-		 * Also known to ../../pkg/runtime/linux/amd64/sys.s
-		 * and ../../libcgo/linux_amd64.s.
+		 * Also known to ../../pkg/runtime/sys_linux_amd64.s
+		 * and ../../pkg/runtime/cgo/gcc_linux_amd64.c.
 		 */
 		tlsoffset = -16;
 		elfinit();
@@ -462,7 +470,7 @@ loop:
 			sig = 1729;
 		if(sig != 0){
 			if(s->sig != 0 && s->sig != sig)
-				diag("incompatible type signatures"
+				diag("incompatible type signatures "
 					"%ux(%s) and %ux(%s) for %s",
 					s->sig, s->file, sig, pn, s->name);
 			s->sig = sig;
@@ -589,6 +597,10 @@ loop:
 	case ATEXT:
 		s = p->from.sym;
 		if(s->text != nil) {
+			if(p->from.scale & DUPOK) {
+				skip = 1;
+				goto casdef;
+			}
 			diag("%s: %s: redefinition", pn, s->name);
 			return;
 		}
diff --git a/src/cmd/6l/optab.c b/src/cmd/6l/optab.c
index 0a4c0eb..2308e0d 100644
--- a/src/cmd/6l/optab.c
+++ b/src/cmd/6l/optab.c
@@ -200,7 +200,8 @@ uchar	ymovq[] =
 	Ymm,	Ymr,	Zm_r_xm,	1,	// MMX MOVD
 	Ymr,	Ymm,	Zr_m_xm,	1,	// MMX MOVD
 	Yxr,	Ymr,	Zm_r_xm_nr,	2,	// MOVDQ2Q
-	Yxr,	Ym,	Zr_m_xm_nr,	2,	// MOVQ xmm store
+	Yxm,	Yxr,	Zm_r_xm_nr,	2, // MOVQ xmm1/m64 -> xmm2
+	Yxr,	Yxm,	Zr_m_xm_nr,	2, // MOVQ xmm1 -> xmm2/m64
 	Yml,	Yxr,	Zm_r_xm,	2,	// MOVD xmm load
 	Yxr,	Yml,	Zr_m_xm,	2,	// MOVD xmm store
 	Yiauto,	Yrl,	Zaut_r,	2,	// built-in LEAQ
@@ -862,7 +863,7 @@ Optab optab[] =
 	{ AMOVNTPD,	yxr_ml,	Pe, 0x2b },
 	{ AMOVNTPS,	yxr_ml,	Pm, 0x2b },
 	{ AMOVNTQ,	ymr_ml,	Pm, 0xe7 },
-	{ AMOVQ,	ymovq,	Pw, 0x89,0x8b,0x31,0xc7,(00),0xb8,0xc7,(00),0x6f,0x7f,0x6e,0x7e,Pf2,0xd6,Pe,0xd6,Pe,0x6e,Pe,0x7e },
+	{ AMOVQ,	ymovq,	Pw, 0x89, 0x8b, 0x31, 0xc7,(00), 0xb8, 0xc7,(00), 0x6f, 0x7f, 0x6e, 0x7e, Pf2,0xd6, Pf3,0x7e, Pe,0xd6, Pe,0x6e, Pe,0x7e },
 	{ AMOVQOZX,	ymrxr,	Pf3, 0xd6,0x7e },
 	{ AMOVSB,	ynone,	Pb, 0xa4 },
 	{ AMOVSD,	yxmov,	Pf2, 0x10,0x11 },
@@ -978,7 +979,7 @@ Optab optab[] =
 	{ APSHUFW,	ymshuf,	Pm, 0x70 },
 	{ APSLLO,	ypsdq,	Pq, 0x73,(07) },
 	{ APSLLL,	yps,	Py, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) },
-	{ APSLLQ,	yps,	Py, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x7e,(06) },
+	{ APSLLQ,	yps,	Py, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
 	{ APSLLW,	yps,	Py, 0xf1, 0x71,(06), Pe,0xf1, Pe,0x71,(06) },
 	{ APSRAL,	yps,	Py, 0xe2, 0x72,(04), Pe,0xe2, Pe,0x72,(04) },
 	{ APSRAW,	yps,	Py, 0xe1, 0x71,(04), Pe,0xe1, Pe,0x71,(04) },
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c
index d9e0b2f..2357a7f 100644
--- a/src/cmd/6l/pass.c
+++ b/src/cmd/6l/pass.c
@@ -276,7 +276,7 @@ patch(void)
 			// Convert
 			//   op	  n(GS), reg
 			// to
-			//   MOVL 0x58(GS), reg
+			//   MOVL 0x28(GS), reg
 			//   op	  n(reg), reg
 			// The purpose of this patch is to fix some accesses
 			// to extern register variables (TLS) on Windows, as
@@ -291,11 +291,11 @@ patch(void)
 				q->as = p->as;
 				p->as = AMOVQ;
 				p->from.type = D_INDIR+D_GS;
-				p->from.offset = 0x58;
+				p->from.offset = 0x28;
 			}
 		}
 		if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
-		|| HEADTYPE == Hopenbsd) {
+		|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd) {
 			// ELF uses FS instead of GS.
 			if(p->from.type == D_INDIR+D_GS)
 				p->from.type = D_INDIR+D_FS;
@@ -421,18 +421,18 @@ dostkoff(void)
 			p = appendp(p);	// load g into CX
 			p->as = AMOVQ;
 			if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
-			|| HEADTYPE == Hopenbsd)	// ELF uses FS
+			|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd)	// ELF uses FS
 				p->from.type = D_INDIR+D_FS;
 			else
 				p->from.type = D_INDIR+D_GS;
 			p->from.offset = tlsoffset+0;
 			p->to.type = D_CX;
 			if(HEADTYPE == Hwindows) {
-				// movq %gs:0x58, %rcx
+				// movq %gs:0x28, %rcx
 				// movq (%rcx), %rcx
 				p->as = AMOVQ;
 				p->from.type = D_INDIR+D_GS;
-				p->from.offset = 0x58;
+				p->from.offset = 0x28;
 				p->to.type = D_CX;
 
 			
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index 9b869a4..28eb38f 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -266,10 +266,6 @@ instinit(void)
 	ycover[Ym*Ymax + Ymm] = 1;
 	ycover[Ymr*Ymax + Ymm] = 1;
 
-	ycover[Yax*Ymax + Yxm] = 1;
-	ycover[Ycx*Ymax + Yxm] = 1;
-	ycover[Yrx*Ymax + Yxm] = 1;
-	ycover[Yrl*Ymax + Yxm] = 1;
 	ycover[Ym*Ymax + Yxm] = 1;
 	ycover[Yxr*Ymax + Yxm] = 1;
 
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y
index 9697608..f188180 100644
--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -392,6 +392,12 @@ imm:
 		$$.type = D_FCONST;
 		$$.dval = $3;
 	}
+|	'$' '(' '-' LFCONST ')'
+	{
+		$$ = nullgen;
+		$$.type = D_FCONST;
+		$$.dval = -$4;
+	}
 |	'$' '-' LFCONST
 	{
 		$$ = nullgen;
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
index ca2e2c1..4036694 100644
--- a/src/cmd/8a/lex.c
+++ b/src/cmd/8a/lex.c
@@ -313,8 +313,8 @@ struct
 	"IDIVL",	LTYPE2,	AIDIVL,
 	"IDIVW",	LTYPE2,	AIDIVW,
 	"IMULB",	LTYPE2,	AIMULB,
-	"IMULL",	LTYPE2,	AIMULL,
-	"IMULW",	LTYPE2,	AIMULW,
+	"IMULL",	LTYPEI,	AIMULL,
+	"IMULW",	LTYPEI,	AIMULW,
 	"INB",		LTYPE0,	AINB,
 	"INL",		LTYPE0,	AINL,
 	"INW",		LTYPE0,	AINW,
diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c
index 7f02bd9..869d31a 100644
--- a/src/cmd/8c/cgen.c
+++ b/src/cmd/8c/cgen.c
@@ -1221,7 +1221,7 @@ void
 boolgen(Node *n, int true, Node *nn)
 {
 	int o;
-	Prog *p1, *p2;
+	Prog *p1, *p2, *p3;
 	Node *l, *r, nod, nod1;
 	int32 curs;
 
@@ -1346,6 +1346,15 @@ boolgen(Node *n, int true, Node *nn)
 			cgen64(n, Z);
 			goto com;
 		}
+		if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
+			// Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
+			// Jump around instead.
+			boolgen(n, 0, Z);
+			p1 = p;
+			gbranch(OGOTO);
+			patch(p1, pc);
+			goto com;
+		}
 		if(true)
 			o = comrel[relindex(o)];
 		if(l->complex >= FNX && r->complex >= FNX) {
@@ -1378,6 +1387,30 @@ boolgen(Node *n, int true, Node *nn)
 				} else
 					fgopcode(o, l, &fregnode0, 0, 1);
 			}
+			switch(o) {
+			case OEQ:
+				// Already emitted AJEQ; want AJEQ and AJPC.
+				p1 = p;
+				gbranch(OGOTO);
+				p2 = p;
+				patch(p1, pc);
+				gins(AJPC, Z, Z);
+				patch(p2, pc);
+				break;
+
+			case ONE:
+				// Already emitted AJNE; want AJNE or AJPS.
+				p1 = p;
+				gins(AJPS, Z, Z);
+				p2 = p;
+				gbranch(OGOTO);
+				p3 = p;
+				patch(p1, pc);
+				patch(p2, pc);
+				gbranch(OGOTO);
+				patch(p3, pc);
+				break;
+			}
 			goto com;
 		}
 		if(l->op == OCONST) {
diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h
index 32b80e9..4a57f5d 100644
--- a/src/cmd/8c/gc.h
+++ b/src/cmd/8c/gc.h
@@ -304,7 +304,8 @@ void	gpseudo(int, Sym*, Node*);
 int	swcmp(const void*, const void*);
 void	doswit(Node*);
 void	swit1(C1*, int, int32, Node*);
-void	cas(void);
+void	swit2(C1*, int, int32, Node*);
+void	newcase(void);
 void	bitload(Node*, Node*, Node*, Node*, Node*);
 void	bitstore(Node*, Node*, Node*, Node*, Node*);
 int32	outstring(char*, int32);
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
index 006bfdf..f1ca4c2 100644
--- a/src/cmd/8c/swt.c
+++ b/src/cmd/8c/swt.c
@@ -33,6 +33,26 @@
 void
 swit1(C1 *q, int nc, int32 def, Node *n)
 {
+	Node nreg;
+
+	if(typev[n->type->etype]) {
+		regsalloc(&nreg, n);
+		nreg.type = types[TVLONG];
+		cgen(n, &nreg);
+		swit2(q, nc, def, &nreg);
+		return;
+	}
+
+	regalloc(&nreg, n, Z);
+	nreg.type = types[TLONG];
+	cgen(n, &nreg);
+	swit2(q, nc, def, &nreg);
+	regfree(&nreg);
+}
+
+void
+swit2(C1 *q, int nc, int32 def, Node *n)
+{
 	C1 *r;
 	int i;
 	Prog *sp;
@@ -58,12 +78,12 @@ swit1(C1 *q, int nc, int32 def, Node *n)
 	gbranch(OGOTO);
 	p->as = AJEQ;
 	patch(p, r->label);
-	swit1(q, i, def, n);
+	swit2(q, i, def, n);
 
 	if(debug['W'])
 		print("case < %.8ux\n", r->val);
 	patch(sp, pc);
-	swit1(r+1, nc-i-1, def, n);
+	swit2(r+1, nc-i-1, def, n);
 }
 
 void
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 21b7815..7dd3a7b 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -787,6 +787,7 @@ bgen(Node *n, int true, Prog *to)
 	int et, a;
 	Node *nl, *nr, *r;
 	Node n1, n2, tmp, t1, t2, ax;
+	NodeList *ll;
 	Prog *p1, *p2;
 
 	if(debug['g']) {
@@ -902,7 +903,10 @@ bgen(Node *n, int true, Prog *to)
 				p1 = gbranch(AJMP, T);
 				p2 = gbranch(AJMP, T);
 				patch(p1, pc);
+				ll = n->ninit;  // avoid re-genning ninit
+				n->ninit = nil;
 				bgen(n, 1, p2);
+				n->ninit = ll;
 				patch(gbranch(AJMP, T), to);
 				patch(p2, pc);
 				break;
@@ -1126,21 +1130,21 @@ stkof(Node *n)
  *	memmove(&res, &n, w);
  */
 void
-sgen(Node *n, Node *res, int32 w)
+sgen(Node *n, Node *res, int64 w)
 {
 	Node dst, src, tdst, tsrc;
 	int32 c, q, odst, osrc;
 
 	if(debug['g']) {
-		print("\nsgen w=%d\n", w);
+		print("\nsgen w=%ld\n", w);
 		dump("r", n);
 		dump("res", res);
 	}
 	if(n->ullman >= UINF && res->ullman >= UINF)
 		fatal("sgen UINF");
 
-	if(w < 0)
-		fatal("sgen copy %d", w);
+	if(w < 0 || (int32)w != w)
+		fatal("sgen copy %lld", w);
 
 	if(w == 0) {
 		// evaluate side effects only.
diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h
index e23ee9e..0a4f0ad 100644
--- a/src/cmd/8g/gg.h
+++ b/src/cmd/8g/gg.h
@@ -43,6 +43,8 @@ struct	Prog
 	void*	reg;		// pointer to containing Reg struct
 };
 
+#define TEXTFLAG from.scale
+
 // foptoas flags
 enum
 {
@@ -97,7 +99,7 @@ void	agenr(Node *n, Node *a, Node *res);
 void	igen(Node*, Node*, Node*);
 vlong	fieldoffset(Type*, Node*);
 void	bgen(Node*, int, Prog*);
-void	sgen(Node*, Node*, int32);
+void	sgen(Node*, Node*, int64);
 void	gmove(Node*, Node*);
 Prog*	gins(int, Node*, Node*);
 int	samaddr(Node*, Node*);
diff --git a/src/cmd/8g/gobj.c b/src/cmd/8g/gobj.c
index 7025a53..d8c8f5a 100644
--- a/src/cmd/8g/gobj.c
+++ b/src/cmd/8g/gobj.c
@@ -308,6 +308,7 @@ datastring(char *s, int len, Addr *a)
 	sym = stringsym(s, len);
 	a->type = D_EXTERN;
 	a->sym = sym;
+	a->node = sym->def;
 	a->offset = widthptr+4;  // skip header
 	a->etype = TINT32;
 }
@@ -324,6 +325,7 @@ datagostring(Strlit *sval, Addr *a)
 	sym = stringsym(sval->s, sval->len);
 	a->type = D_EXTERN;
 	a->sym = sym;
+	a->node = sym->def;
 	a->offset = 0;  // header
 	a->etype = TINT32;
 }
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index 1aae34e..9d0f702 100644
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -964,8 +964,15 @@ nodarg(Type *t, int fp)
 			fatal("nodarg: offset not computed for %T", t);
 		n->xoffset = t->width;
 		n->addable = 1;
+		n->orig = t->nname;
 		break;
 	}
+	
+	// Rewrite argument named _ to __,
+	// or else the assignment to _ will be
+	// discarded during code generation.
+	if(isblank(n))
+		n->sym = lookup("__");
 
 	switch(fp) {
 	default:
@@ -1152,6 +1159,7 @@ memname(Node *n, Type *t)
 	strcpy(namebuf, n->sym->name);
 	namebuf[0] = '.';	// keep optimizer from registerizing
 	n->sym = lookup(namebuf);
+	n->orig->sym = n->sym;
 }
 
 void
@@ -1828,6 +1836,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 		a->offset = n->xoffset;
 		a->sym = n->left->sym;
 		a->type = D_PARAM;
+		a->node = n->left->orig;
 		break;
 
 	case ONAME:
@@ -1840,6 +1849,9 @@ naddr(Node *n, Addr *a, int canemitcode)
 		}
 		a->offset = n->xoffset;
 		a->sym = n->sym;
+		a->node = n->orig;
+		//if(a->node >= (Node*)&n)
+		//	fatal("stack node");
 		if(a->sym == S)
 			a->sym = lookup(".noname");
 		if(n->method) {
@@ -1857,8 +1869,6 @@ naddr(Node *n, Addr *a, int canemitcode)
 			break;
 		case PAUTO:
 			a->type = D_AUTO;
-			if (n->sym)
-				a->node = n->orig;
 			break;
 		case PPARAM:
 		case PPARAMOUT:
@@ -1881,6 +1891,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 			a->dval = mpgetflt(n->val.u.fval);
 			break;
 		case CTINT:
+		case CTRUNE:
 			a->sym = S;
 			a->type = D_CONST;
 			a->offset = mpgetfix(n->val.u.xval);
diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c
index de5fd87..2276282 100644
--- a/src/cmd/8g/reg.c
+++ b/src/cmd/8g/reg.c
@@ -39,6 +39,8 @@
 
 static	int	first	= 1;
 
+static	void	fixjmp(Prog*);
+
 Reg*
 rega(void)
 {
@@ -89,8 +91,8 @@ setoutvar(void)
 			ovar.b[z] |= bit.b[z];
 		t = structnext(&save);
 	}
-//if(bany(b))
-//print("ovars = %Q\n", &ovar);
+//if(bany(ovar))
+//print("ovars = %Q\n", ovar);
 }
 
 static void
@@ -132,6 +134,8 @@ regopt(Prog *firstp)
 		exregoffset = D_DI;	// no externals
 		first = 0;
 	}
+	
+	fixjmp(firstp);
 
 	// count instructions
 	nr = 0;
@@ -694,9 +698,9 @@ brk:
 		if(ostats.ndelmov)
 			print("	%4d delmov\n", ostats.ndelmov);
 		if(ostats.nvar)
-			print("	%4d delmov\n", ostats.nvar);
+			print("	%4d var\n", ostats.nvar);
 		if(ostats.naddr)
-			print("	%4d delmov\n", ostats.naddr);
+			print("	%4d addr\n", ostats.naddr);
 
 		memset(&ostats, 0, sizeof(ostats));
 	}
@@ -848,10 +852,12 @@ mkvar(Reg *r, Adr *a)
 	}
 
 	node = a->node;
-	if(node == N || node->op != ONAME || node->orig != N)
+	if(node == N || node->op != ONAME || node->orig == N)
 		goto none;
 	node = node->orig;
-	if(node->sym->name[0] == '.')
+	if(node->orig != node)
+		fatal("%D: bad node", a);
+	if(node->sym == S || node->sym->name[0] == '.')
 		goto none;
 	et = a->etype;
 	o = a->offset;
@@ -1095,10 +1101,12 @@ loopit(Reg *r, int32 nr)
 		r1 = rpo2r[i];
 		me = r1->rpo;
 		d = -1;
-		if(r1->p1 != R && r1->p1->rpo < me)
+		// rpo2r[r->rpo] == r protects against considering dead code,
+		// which has r->rpo == 0.
+		if(r1->p1 != R && rpo2r[r1->p1->rpo] == r1->p1 && r1->p1->rpo < me)
 			d = r1->p1->rpo;
 		for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
-			if(r1->rpo < me)
+			if(rpo2r[r1->rpo] == r1 && r1->rpo < me)
 				d = rpolca(idom, d, r1->rpo);
 		idom[i] = d;
 	}
@@ -1482,7 +1490,7 @@ dumpone(Reg *r)
 		if(bany(&r->refahead))
 			print(" ra:%Q ", r->refahead);
 		if(bany(&r->calbehind))
-			print("cb:%Q ", r->calbehind);
+			print(" cb:%Q ", r->calbehind);
 		if(bany(&r->calahead))
 			print(" ca:%Q ", r->calahead);
 		if(bany(&r->regdiff))
@@ -1542,3 +1550,123 @@ noreturn(Prog *p)
 			return 1;
 	return 0;
 }
+
+/*
+ * the code generator depends on being able to write out JMP
+ * instructions that it can jump to now but fill in later.
+ * the linker will resolve them nicely, but they make the code
+ * longer and more difficult to follow during debugging.
+ * remove them.
+ */
+
+/* what instruction does a JMP to p eventually land on? */
+static Prog*
+chasejmp(Prog *p, int *jmploop)
+{
+	int n;
+
+	n = 0;
+	while(p != P && p->as == AJMP && p->to.type == D_BRANCH) {
+		if(++n > 10) {
+			*jmploop = 1;
+			break;
+		}
+		p = p->to.branch;
+	}
+	return p;
+}
+
+/*
+ * reuse reg pointer for mark/sweep state.
+ * leave reg==nil at end because alive==nil.
+ */
+#define alive ((void*)0)
+#define dead ((void*)1)
+
+/* mark all code reachable from firstp as alive */
+static void
+mark(Prog *firstp)
+{
+	Prog *p;
+	
+	for(p=firstp; p; p=p->link) {
+		if(p->reg != dead)
+			break;
+		p->reg = alive;
+		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch)
+			mark(p->to.branch);
+		if(p->as == AJMP || p->as == ARET || (p->as == ACALL && noreturn(p)))
+			break;
+	}
+}
+
+static void
+fixjmp(Prog *firstp)
+{
+	int jmploop;
+	Prog *p, *last;
+	
+	if(debug['R'] && debug['v'])
+		print("\nfixjmp\n");
+
+	// pass 1: resolve jump to AJMP, mark all code as dead.
+	jmploop = 0;
+	for(p=firstp; p; p=p->link) {
+		if(debug['R'] && debug['v'])
+			print("%P\n", p);
+		if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch && p->to.branch->as == AJMP) {
+			p->to.branch = chasejmp(p->to.branch, &jmploop);
+			if(debug['R'] && debug['v'])
+				print("->%P\n", p);
+		}
+		p->reg = dead;
+	}
+	if(debug['R'] && debug['v'])
+		print("\n");
+
+	// pass 2: mark all reachable code alive
+	mark(firstp);
+	
+	// pass 3: delete dead code (mostly JMPs).
+	last = nil;
+	for(p=firstp; p; p=p->link) {
+		if(p->reg == dead) {
+			if(p->link == P && p->as == ARET && last && last->as != ARET) {
+				// This is the final ARET, and the code so far doesn't have one.
+				// Let it stay.
+			} else {
+				if(debug['R'] && debug['v'])
+					print("del %P\n", p);
+				continue;
+			}
+		}
+		if(last)
+			last->link = p;
+		last = p;
+	}
+	last->link = P;
+	
+	// pass 4: elide JMP to next instruction.
+	// only safe if there are no jumps to JMPs anymore.
+	if(!jmploop) {
+		last = nil;
+		for(p=firstp; p; p=p->link) {
+			if(p->as == AJMP && p->to.type == D_BRANCH && p->to.branch == p->link) {
+				if(debug['R'] && debug['v'])
+					print("del %P\n", p);
+				continue;
+			}
+			if(last)
+				last->link = p;
+			last = p;
+		}
+		last->link = P;
+	}
+	
+	if(debug['R'] && debug['v']) {
+		print("\n");
+		for(p=firstp; p; p=p->link)
+			print("%P\n", p);
+		print("\n");
+	}
+}
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 6c7f964..0fe4cf1 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -37,11 +37,10 @@
 #include	"../ld/macho.h"
 #include	"../ld/pe.h"
 
-#define	Dbufslop	100
-
 char linuxdynld[] = "/lib/ld-linux.so.2";
 char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
 char openbsddynld[] = "/usr/libexec/ld.so";
+char netbsddynld[] = "/usr/libexec/ld.elf_so";
 
 int32
 entryvalue(void)
@@ -91,6 +90,7 @@ enum {
 	ElfStrPlt,
 	ElfStrGnuVersion,
 	ElfStrGnuVersionR,
+	ElfStrNoteNetbsdIdent,
 	NElfStr
 };
 
@@ -527,6 +527,8 @@ doelf(void)
 	elfstr[ElfStrText] = addstring(shstrtab, ".text");
 	elfstr[ElfStrData] = addstring(shstrtab, ".data");
 	elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
+	if(HEADTYPE == Hnetbsd)
+		elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
 	addstring(shstrtab, ".elfdata");
 	addstring(shstrtab, ".rodata");
 	addstring(shstrtab, ".gosymtab");
@@ -607,7 +609,7 @@ doelf(void)
 		/* define dynamic elf table */
 		s = lookup(".dynamic", 0);
 		s->reachable = 1;
-		s->type = SELFROSECT;
+		s->type = SELFSECT; // writable
 
 		/*
 		 * .dynamic table
@@ -627,6 +629,8 @@ doelf(void)
 		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
 		elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
 
+		elfwritedynent(s, DT_DEBUG, 0);
+
 		// Do not write DT_NULL.  elfdynhash will finish it.
 	}
 }
@@ -658,7 +662,7 @@ asmb(void)
 {
 	int32 v, magic;
 	int a, dynsym;
-	uint32 symo, startva, machlink;
+	uint32 symo, startva, dwarfoff, machlink, resoff;
 	ElfEhdr *eh;
 	ElfPhdr *ph, *pph;
 	ElfShdr *sh;
@@ -689,8 +693,19 @@ asmb(void)
 	datblk(segdata.vaddr, segdata.filelen);
 
 	machlink = 0;
-	if(HEADTYPE == Hdarwin)
+	if(HEADTYPE == Hdarwin) {
+		if(debug['v'])
+			Bprint(&bso, "%5.2f dwarf\n", cputime());
+
+		dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND);
+		cseek(dwarfoff);
+
+		segdwarf.fileoff = cpos();
+		dwarfemitdebugsections();
+		segdwarf.filelen = cpos() - segdwarf.fileoff;
+
 		machlink = domacholink();
+	}
 
 	if(iself) {
 		/* index of elf text section; needed by asmelfsym, double-checked below */
@@ -701,6 +716,8 @@ asmb(void)
 			if(elfverneed)
 				elftextsh += 2;
 		}
+		if(HEADTYPE == Hnetbsd)
+			elftextsh += 1;
 	}
 
 	symsize = 0;
@@ -747,7 +764,7 @@ asmb(void)
 		default:
 			if(iself) {
 				if(debug['v'])
-				       Bprint(&bso, "%5.2f elfsym\n", cputime());
+					Bprint(&bso, "%5.2f elfsym\n", cputime());
 				asmelfsym();
 				cflush();
 				cwrite(elfstrdat, elfstrsize);
@@ -770,7 +787,6 @@ asmb(void)
 				cflush();
 			}
 			break;
-		case Hdarwin:
 		case Hwindows:
 			if(debug['v'])
 				Bprint(&bso, "%5.2f dwarf\n", cputime());
@@ -919,6 +935,7 @@ asmb(void)
 	Elfput:
 		eh = getElfEhdr();
 		startva = INITTEXT - HEADR;
+		resoff = ELFRESERVE;
 
 		/* This null SHdr must appear before all others */
 		newElfShdr(elfstr[ElfStrEmpty]);
@@ -957,12 +974,15 @@ asmb(void)
 				case Hfreebsd:
 					interpreter = freebsddynld;
 					break;
+				case Hnetbsd:
+					interpreter = netbsddynld;
+					break;
 				case Hopenbsd:
 					interpreter = openbsddynld;
 					break;
 				}
 			}
-			elfinterp(sh, startva, interpreter);
+			resoff -= elfinterp(sh, startva, resoff, interpreter);
 
 			ph = newElfPhdr();
 			ph->type = PT_INTERP;
@@ -970,11 +990,24 @@ asmb(void)
 			phsh(ph, sh);
 		}
 
+		if(HEADTYPE == Hnetbsd) {
+			sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
+			sh->type = SHT_NOTE;
+			sh->flags = SHF_ALLOC;
+			sh->addralign = 4;
+			resoff -= elfnetbsdsig(sh, startva, resoff);
+
+			ph = newElfPhdr();
+			ph->type = PT_NOTE;
+			ph->flags = PF_R;
+			phsh(ph, sh);
+		}
+
 		elfphload(&segtext);
 		elfphload(&segdata);
 
 		/* Dynamic linking sections */
-		if (!debug['d']) {	/* -d suppresses dynamic loader format */
+		if(!debug['d']) {	/* -d suppresses dynamic loader format */
 			/* S headers for dynamic linking */
 			sh = newElfShdr(elfstr[ElfStrGot]);
 			sh->type = SHT_PROGBITS;
@@ -1098,7 +1131,7 @@ asmb(void)
 		for(sect=segdata.sect; sect!=nil; sect=sect->next)
 			elfshbits(sect);
 
-		if (!debug['s']) {
+		if(!debug['s']) {
 			sh = newElfShdr(elfstr[ElfStrSymtab]);
 			sh->type = SHT_SYMTAB;
 			sh->off = symo;
@@ -1128,6 +1161,9 @@ asmb(void)
 		case Hfreebsd:
 			eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
 			break;
+		case Hnetbsd:
+			eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
+			break;
 		case Hopenbsd:
 			eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
 			break;
@@ -1148,8 +1184,10 @@ asmb(void)
 		a += elfwritehdr();
 		a += elfwritephdrs();
 		a += elfwriteshdrs();
-		cflush();
-		if(a+elfwriteinterp() > ELFRESERVE)	
+		a += elfwriteinterp(elfstr[ElfStrInterp]);
+		if(HEADTYPE == Hnetbsd)
+			a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
+		if(a > ELFRESERVE)	
 			diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
 		break;
 
diff --git a/src/cmd/8l/doc.go b/src/cmd/8l/doc.go
index de877bb..edd6838 100644
--- a/src/cmd/8l/doc.go
+++ b/src/cmd/8l/doc.go
@@ -33,6 +33,8 @@ Options new in this version:
 	Write Linux ELF binaries (default when $GOOS is linux)
 -Hfreebsd
 	Write FreeBSD ELF binaries (default when $GOOS is freebsd)
+-Hnetbsd
+	Write NetBSD ELF binaries (default when $GOOS is netbsd)
 -Hopenbsd
 	Write OpenBSD ELF binaries (default when $GOOS is openbsd)
 -Hwindows
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index a721f38..b974f46 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -134,6 +134,7 @@ struct	Sym
 	int32	dynid;
 	int32	plt;
 	int32	got;
+	int32	align;	// if non-zero, required alignment in bytes
 	Sym*	hash;	// in hash table
 	Sym*	allsym;	// in all symbol list
 	Sym*	next;	// in text or data list
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 297b5be..1d0f1ec 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -47,18 +47,19 @@ char	*noname		= "<none>";
 char	*thestring 	= "386";
 
 Header headers[] = {
-   "garbunix", Hgarbunix,
-   "unixcoff", Hunixcoff,
-   "plan9", Hplan9x32,
-   "msdoscom", Hmsdoscom,
-   "msdosexe", Hmsdosexe,
-   "darwin", Hdarwin,
-   "linux", Hlinux,
-   "freebsd", Hfreebsd,
-   "openbsd", Hopenbsd,
-   "windows", Hwindows,
-   "windowsgui", Hwindows,
-   0, 0
+	"garbunix", Hgarbunix,
+	"unixcoff", Hunixcoff,
+	"plan9", Hplan9x32,
+	"msdoscom", Hmsdoscom,
+	"msdosexe", Hmsdosexe,
+	"darwin", Hdarwin,
+	"linux", Hlinux,
+	"freebsd", Hfreebsd,
+	"netbsd", Hnetbsd,
+	"openbsd", Hopenbsd,
+	"windows", Hwindows,
+	"windowsgui", Hwindows,
+	0, 0
 };
 
 /*
@@ -70,6 +71,7 @@ Header headers[] = {
  *	-Hdarwin -Tx -Rx			is Apple Mach-O
  *	-Hlinux -Tx -Rx				is Linux ELF32
  *	-Hfreebsd -Tx -Rx			is FreeBSD ELF32
+ *	-Hnetbsd -Tx -Rx			is NetBSD ELF32
  *	-Hopenbsd -Tx -Rx			is OpenBSD ELF32
  *	-Hwindows -Tx -Rx			is MS Windows PE32
  */
@@ -135,6 +137,11 @@ main(int argc, char *argv[])
 	case 'V':
 		print("%cl version %s\n", thechar, getgoversion());
 		errorexit();
+	case 'X':
+		// TODO: golang.org/issue/2676
+		EARGF(usage());
+		EARGF(usage());
+		break;
 	} ARGEND
 
 	if(argc != 1)
@@ -211,7 +218,7 @@ main(int argc, char *argv[])
 	case Hdarwin:	/* apple MACH */
 		/*
 		 * OS X system constant - offset from %gs to our TLS.
-		 * Explained in ../../libcgo/darwin_386.c.
+		 * Explained in ../../pkg/runtime/cgo/gcc_darwin_386.c.
 		 */
 		tlsoffset = 0x468;
 		machoinit();
@@ -225,12 +232,13 @@ main(int argc, char *argv[])
 		break;
 	case Hlinux:	/* elf32 executable */
 	case Hfreebsd:
+	case Hnetbsd:
 	case Hopenbsd:
 		/*
 		 * ELF uses TLS offsets negative from %gs.
 		 * Translate 0(GS) and 4(GS) into -8(GS) and -4(GS).
-		 * Also known to ../../pkg/runtime/linux/386/sys.s
-		 * and ../../libcgo/linux_386.c.
+		 * Also known to ../../pkg/runtime/sys_linux_386.s
+		 * and ../../pkg/runtime/cgo/gcc_linux_386.c.
 		 */
 		tlsoffset = -8;
 		elfinit();
@@ -480,7 +488,7 @@ loop:
 			sig = 1729;
 		if(sig != 0){
 			if(s->sig != 0 && s->sig != sig)
-				diag("incompatible type signatures"
+				diag("incompatible type signatures "
 					"%ux(%s) and %ux(%s) for %s",
 					s->sig, s->file, sig, pn, s->name);
 			s->sig = sig;
@@ -597,6 +605,10 @@ loop:
 	case ATEXT:
 		s = p->from.sym;
 		if(s->text != nil) {
+			if(p->from.scale & DUPOK) {
+				skip = 1;
+				goto casdef;
+			}
 			diag("%s: %s: redefinition", pn, s->name);
 			return;
 		}
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 54ea965..b900a5f 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -259,7 +259,7 @@ patch(void)
 				// Convert
 				//   op	  n(GS), reg
 				// to
-				//   MOVL 0x2C(FS), reg
+				//   MOVL 0x14(FS), reg
 				//   op	  n(reg), reg
 				// The purpose of this patch is to fix some accesses
 				// to extern register variables (TLS) on Windows, as
@@ -273,7 +273,7 @@ patch(void)
 					q->as = p->as;
 					p->as = AMOVL;
 					p->from.type = D_INDIR+D_FS;
-					p->from.offset = 0x2C;
+					p->from.offset = 0x14;
 				}
 			}
 			if(HEADTYPE == Hlinux) {
@@ -424,7 +424,7 @@ dostkoff(void)
 			case Hwindows:
 				p->as = AMOVL;
 				p->from.type = D_INDIR+D_FS;
-				p->from.offset = 0x2c;
+				p->from.offset = 0x14;
 				p->to.type = D_CX;
 
 				p = appendp(p);
diff --git a/src/cmd/Makefile b/src/cmd/Makefile
index 5a37733..ee82b83 100644
--- a/src/cmd/Makefile
+++ b/src/cmd/Makefile
@@ -16,9 +16,7 @@ DIRS=\
 	cc\
 	cov\
 	gc\
-	godefs\
 	gopack\
-	gotry\
 	nm\
 	prof\
 	
@@ -39,18 +37,16 @@ CLEANDIRS=\
 	8g\
 	8l\
 	cgo\
-	ebnflint\
 	godoc\
 	gofix\
 	gofmt\
 	goinstall\
 	gotest\
-	gotype\
 	goyacc\
-	hgpatch\
 
 install: $(patsubst %,%.install,$(DIRS))
 clean: $(patsubst %,%.clean,$(CLEANDIRS))
+nuke: $(patsubst %,%.nuke,$(CLEANDIRS))
 
 %.install:
 	@echo
@@ -58,12 +54,15 @@ clean: $(patsubst %,%.clean,$(CLEANDIRS))
 	@echo
 	$(MAKE) -C $* install
 
-gc.install $(O)c.install: cc.install
+gc.install 5c.install 6c.install 8c.install: cc.install
 $(O)g.install: gc.install
 $(O)a.install $(O)c.install $(O)g.install: $(O)l.install
 
 %.clean:
 	$(MAKE) -C $* clean
 
+%.nuke:
+	$(MAKE) -C $* nuke
+
 echo-dirs:
 	@echo $(DIRS)
diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c
index 3ba979c..4274c56 100644
--- a/src/cmd/cc/godefs.c
+++ b/src/cmd/cc/godefs.c
@@ -124,11 +124,11 @@ Uconv(Fmt *fp)
 
 	if(s && *s) {
 		if(upper)
-			str[0] = toupper(*s);
+			str[0] = toupper((uchar)*s);
 		else
-			str[0] = tolower(*s);
+			str[0] = tolower((uchar)*s);
 		for(i = 1; i < STRINGSZ && s[i] != 0; i++)
-			str[i] = tolower(s[i]);
+			str[i] = tolower((uchar)s[i]);
 		str[i] = 0;
 	}
 
diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c
index 0e5e8c0..3a68610 100644
--- a/src/cmd/cc/pgen.c
+++ b/src/cmd/cc/pgen.c
@@ -266,7 +266,7 @@ loop:
 		if(cases == C)
 			diag(n, "case/default outside a switch");
 		if(l == Z) {
-			cas();
+			newcase();
 			cases->val = 0;
 			cases->def = 1;
 			cases->label = pc;
@@ -278,7 +278,7 @@ loop:
 			goto rloop;
 		if(l->op == OCONST)
 		if(typeword[l->type->etype] && l->type->etype != TIND) {
-			cas();
+			newcase();
 			cases->val = l->vconst;
 			cases->def = 0;
 			cases->label = pc;
@@ -293,7 +293,7 @@ loop:
 		complex(l);
 		if(l->type == T)
 			break;
-		if(!typeword[l->type->etype] || l->type->etype == TIND) {
+		if(!typechlvp[l->type->etype] || l->type->etype == TIND) {
 			diag(n, "switch expression must be integer");
 			break;
 		}
@@ -303,7 +303,7 @@ loop:
 
 		cn = cases;
 		cases = C;
-		cas();
+		newcase();
 
 		sbc = breakpc;
 		breakpc = pc;
@@ -320,15 +320,7 @@ loop:
 		}
 
 		patch(sp, pc);
-		regalloc(&nod, l, Z);
-		/* always signed */
-		if(typev[l->type->etype])
-			nod.type = types[TVLONG];
-		else
-			nod.type = types[TLONG];
-		cgen(l, &nod);
-		doswit(&nod);
-		regfree(&nod);
+		doswit(l);
 		patch(spb, pc);
 
 		cases = cn;
diff --git a/src/cmd/cc/pswt.c b/src/cmd/cc/pswt.c
index 0e402de..b94035f 100644
--- a/src/cmd/cc/pswt.c
+++ b/src/cmd/cc/pswt.c
@@ -92,7 +92,7 @@ doswit(Node *n)
 }
 
 void
-cas(void)
+newcase(void)
 {
 	Case *c;
 
diff --git a/src/cmd/cgo/Makefile b/src/cmd/cgo/Makefile
index 5458c3e..a3f034f 100644
--- a/src/cmd/cgo/Makefile
+++ b/src/cmd/cgo/Makefile
@@ -8,6 +8,7 @@ TARG=cgo
 GOFILES=\
 	ast.go\
 	gcc.go\
+	godefs.go\
 	main.go\
 	out.go\
 	util.go\
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
index 73b7313..da6ae41 100644
--- a/src/cmd/cgo/ast.go
+++ b/src/cmd/cgo/ast.go
@@ -9,7 +9,6 @@ package main
 import (
 	"fmt"
 	"go/ast"
-	"go/doc"
 	"go/parser"
 	"go/scanner"
 	"go/token"
@@ -17,7 +16,7 @@ import (
 	"strings"
 )
 
-func parse(name string, flags uint) *ast.File {
+func parse(name string, flags parser.Mode) *ast.File {
 	ast1, err := parser.ParseFile(fset, name, nil, flags)
 	if err != nil {
 		if list, ok := err.(scanner.ErrorList); ok {
@@ -71,7 +70,7 @@ func (f *File) ReadGo(name string) {
 			}
 			sawC = true
 			if s.Name != nil {
-				error(s.Path.Pos(), `cannot rename import "C"`)
+				error_(s.Path.Pos(), `cannot rename import "C"`)
 			}
 			cg := s.Doc
 			if cg == nil && len(d.Specs) == 1 {
@@ -79,12 +78,12 @@ func (f *File) ReadGo(name string) {
 			}
 			if cg != nil {
 				f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name)
-				f.Preamble += doc.CommentText(cg) + "\n"
+				f.Preamble += cg.Text() + "\n"
 			}
 		}
 	}
 	if !sawC {
-		error(token.NoPos, `cannot find import "C"`)
+		error_(token.NoPos, `cannot find import "C"`)
 	}
 
 	// In ast2, strip the import "C" line.
@@ -128,6 +127,7 @@ func (f *File) ReadGo(name string) {
 	f.walk(ast1, "prog", (*File).saveExport)
 	f.walk(ast2, "prog", (*File).saveExport2)
 
+	f.Comments = ast1.Comments
 	f.AST = ast2
 }
 
@@ -149,7 +149,7 @@ func (f *File) saveRef(x interface{}, context string) {
 			}
 			goname := sel.Sel.Name
 			if goname == "errno" {
-				error(sel.Pos(), "cannot refer to errno directly; see documentation")
+				error_(sel.Pos(), "cannot refer to errno directly; see documentation")
 				return
 			}
 			name := f.Name[goname]
@@ -186,11 +186,11 @@ func (f *File) saveExport(x interface{}, context string) {
 
 		name := strings.TrimSpace(string(c.Text[9:]))
 		if name == "" {
-			error(c.Pos(), "export missing name")
+			error_(c.Pos(), "export missing name")
 		}
 
 		if name != n.Name.Name {
-			error(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name)
+			error_(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name)
 		}
 
 		f.ExpFunc = append(f.ExpFunc, &ExpFunc{
@@ -225,7 +225,7 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
 
 	// everything else just recurs
 	default:
-		error(token.NoPos, "unexpected type %T in walk", x, visit)
+		error_(token.NoPos, "unexpected type %T in walk", x, visit)
 		panic("unexpected type")
 
 	case nil:
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index dc9edd6..6282c0b 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -59,7 +59,7 @@ struct_, union_, or enum_, as in C.struct_stat.
 
 Any C function that returns a value may be called in a multiple
 assignment context to retrieve both the return value and the
-C errno variable as an os.Error.  For example:
+C errno variable as an error.  For example:
 
 	n, err := C.atoi("abc")
 
@@ -87,6 +87,23 @@ by making copies of the data.  In pseudo-Go definitions:
 	// C pointer, length to Go []byte
 	func C.GoBytes(unsafe.Pointer, C.int) []byte
 
+Go functions can be exported for use by C code in the following way:
+
+	//export MyFunction
+	func MyFunction(arg1, arg2 int, arg3 string) int64 {...}
+
+	//export MyFunction2
+	func MyFunction2(arg1, arg2 int, arg3 string) (int64, *C.char) {...}
+
+They will be available in the C code as:
+
+	extern int64 MyFunction(int arg1, int arg2, GoString arg3);
+	extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
+
+found in _cgo_export.h generated header. Functions with multiple
+return values are mapped to functions returning a struct.
+Not all Go types can be mapped to C types in a useful way.
+
 Cgo transforms the input file into four output files: two Go source
 files, a C file for 6c (or 8c or 5c), and a C file for gcc.
 
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 04d95f0..155eb04 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -14,6 +14,7 @@ import (
 	"debug/macho"
 	"debug/pe"
 	"encoding/binary"
+	"errors"
 	"flag"
 	"fmt"
 	"go/ast"
@@ -23,6 +24,7 @@ import (
 	"strconv"
 	"strings"
 	"unicode"
+	"unicode/utf8"
 )
 
 var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
@@ -58,6 +60,9 @@ func cname(s string) string {
 	if strings.HasPrefix(s, "enum_") {
 		return "enum " + s[len("enum_"):]
 	}
+	if strings.HasPrefix(s, "sizeof_") {
+		return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
+	}
 	return s
 }
 
@@ -71,7 +76,7 @@ func (p *Package) ParseFlags(f *File, srcfile string) {
 NextLine:
 	for _, line := range linesIn {
 		l := strings.TrimSpace(line)
-		if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(int(l[4])) {
+		if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
 			linesOut = append(linesOut, line)
 			continue
 		}
@@ -147,10 +152,10 @@ func (p *Package) addToFlag(flag string, args []string) {
 
 // pkgConfig runs pkg-config and extracts --libs and --cflags information
 // for packages.
-func pkgConfig(packages []string) (cflags, ldflags []string, err os.Error) {
+func pkgConfig(packages []string) (cflags, ldflags []string, err error) {
 	for _, name := range packages {
 		if len(name) == 0 || name[0] == '-' {
-			return nil, nil, os.NewError(fmt.Sprintf("invalid name: %q", name))
+			return nil, nil, errors.New(fmt.Sprintf("invalid name: %q", name))
 		}
 	}
 
@@ -158,7 +163,7 @@ func pkgConfig(packages []string) (cflags, ldflags []string, err os.Error) {
 	stdout, stderr, ok := run(nil, args)
 	if !ok {
 		os.Stderr.Write(stderr)
-		return nil, nil, os.NewError("pkg-config failed")
+		return nil, nil, errors.New("pkg-config failed")
 	}
 	cflags, err = splitQuoted(string(stdout))
 	if err != nil {
@@ -169,7 +174,7 @@ func pkgConfig(packages []string) (cflags, ldflags []string, err os.Error) {
 	stdout, stderr, ok = run(nil, args)
 	if !ok {
 		os.Stderr.Write(stderr)
-		return nil, nil, os.NewError("pkg-config failed")
+		return nil, nil, errors.New("pkg-config failed")
 	}
 	ldflags, err = splitQuoted(string(stdout))
 	return
@@ -191,30 +196,30 @@ func pkgConfig(packages []string) (cflags, ldflags []string, err os.Error) {
 //
 //     []string{"a", "b:c d", "ef", `g"`}
 //
-func splitQuoted(s string) (r []string, err os.Error) {
+func splitQuoted(s string) (r []string, err error) {
 	var args []string
-	arg := make([]int, len(s))
+	arg := make([]rune, len(s))
 	escaped := false
 	quoted := false
-	quote := 0
+	quote := '\x00'
 	i := 0
-	for _, rune := range s {
+	for _, r := range s {
 		switch {
 		case escaped:
 			escaped = false
-		case rune == '\\':
+		case r == '\\':
 			escaped = true
 			continue
 		case quote != 0:
-			if rune == quote {
+			if r == quote {
 				quote = 0
 				continue
 			}
-		case rune == '"' || rune == '\'':
+		case r == '"' || r == '\'':
 			quoted = true
-			quote = rune
+			quote = r
 			continue
-		case unicode.IsSpace(rune):
+		case unicode.IsSpace(r):
 			if quoted || i > 0 {
 				quoted = false
 				args = append(args, string(arg[:i]))
@@ -222,21 +227,21 @@ func splitQuoted(s string) (r []string, err os.Error) {
 			}
 			continue
 		}
-		arg[i] = rune
+		arg[i] = r
 		i++
 	}
 	if quoted || i > 0 {
 		args = append(args, string(arg[:i]))
 	}
 	if quote != 0 {
-		err = os.NewError("unclosed quote")
+		err = errors.New("unclosed quote")
 	} else if escaped {
-		err = os.NewError("unfinished escaping")
+		err = errors.New("unfinished escaping")
 	}
 	return args, err
 }
 
-var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`)
 
 func safeName(s string) bool {
 	if s == "" {
@@ -339,14 +344,22 @@ func (p *Package) guessKinds(f *File) []*Name {
 			if _, err := strconv.Atoi(n.Define); err == nil {
 				ok = true
 			} else if n.Define[0] == '"' || n.Define[0] == '\'' {
-				_, err := parser.ParseExpr(fset, "", n.Define)
-				if err == nil {
+				if _, err := parser.ParseExpr(n.Define); err == nil {
 					ok = true
 				}
 			}
 			if ok {
 				n.Kind = "const"
-				n.Const = n.Define
+				// Turn decimal into hex, just for consistency
+				// with enum-derived constants.  Otherwise
+				// in the cgo -godefs output half the constants
+				// are in hex and half are in whatever the #define used.
+				i, err := strconv.ParseInt(n.Define, 0, 64)
+				if err == nil {
+					n.Const = fmt.Sprintf("%#x", i)
+				} else {
+					n.Const = n.Define
+				}
 				continue
 			}
 
@@ -420,7 +433,7 @@ func (p *Package) guessKinds(f *File) []*Name {
 		case strings.Contains(line, ": statement with no effect"):
 			what = "not-type" // const or func or var
 		case strings.Contains(line, "undeclared"):
-			error(token.NoPos, "%s", strings.TrimSpace(line[colon+1:]))
+			error_(token.NoPos, "%s", strings.TrimSpace(line[colon+1:]))
 		case strings.Contains(line, "is not an integer constant"):
 			isConst[i] = false
 			continue
@@ -439,6 +452,11 @@ func (p *Package) guessKinds(f *File) []*Name {
 	for i, b := range isConst {
 		if b {
 			names[i].Kind = "const"
+			if toSniff[i] != nil && names[i].Const == "" {
+				j := len(needType)
+				needType = needType[0 : j+1]
+				needType[j] = names[i]
+			}
 		}
 	}
 	for _, n := range toSniff {
@@ -448,7 +466,7 @@ func (p *Package) guessKinds(f *File) []*Name {
 		if n.Kind != "" {
 			continue
 		}
-		error(token.NoPos, "could not determine kind of name for C.%s", n.Go)
+		error_(token.NoPos, "could not determine kind of name for C.%s", n.Go)
 	}
 	if nerrors > 0 {
 		fatalf("unresolved names")
@@ -576,6 +594,9 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
 	var conv typeConv
 	conv.Init(p.PtrSize)
 	for i, n := range names {
+		if types[i] == nil {
+			continue
+		}
 		f, fok := types[i].(*dwarf.FuncType)
 		if n.Kind != "type" && fok {
 			n.Kind = "func"
@@ -585,12 +606,12 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
 			if enums[i] != 0 && n.Type.EnumValues != nil {
 				k := fmt.Sprintf("__cgo_enum__%d", i)
 				n.Kind = "const"
-				n.Const = strconv.Itoa64(n.Type.EnumValues[k])
+				n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
 				// Remove injected enum to ensure the value will deep-compare
 				// equally in future loads of the same constant.
-				n.Type.EnumValues[k] = 0, false
+				delete(n.Type.EnumValues, k)
 			} else if n.Kind == "const" && i < len(enumVal) {
-				n.Const = strconv.Itoa64(enumVal[i])
+				n.Const = fmt.Sprintf("%#x", enumVal[i])
 			}
 		}
 	}
@@ -599,7 +620,8 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
 
 // rewriteRef rewrites all the C.xxx references in f.AST to refer to the
 // Go equivalents, now that we have figured out the meaning of all
-// the xxx.
+// the xxx.  In *godefs or *cdefs mode, rewriteRef replaces the names
+// with full definitions instead of mangled names.
 func (p *Package) rewriteRef(f *File) {
 	// Assign mangled names.
 	for _, n := range f.Name {
@@ -617,7 +639,7 @@ func (p *Package) rewriteRef(f *File) {
 	// functions are only used in calls.
 	for _, r := range f.Ref {
 		if r.Name.Kind == "const" && r.Name.Const == "" {
-			error(r.Pos(), "unable to find value of constant C.%s", r.Name.Go)
+			error_(r.Pos(), "unable to find value of constant C.%s", r.Name.Go)
 		}
 		var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
 		switch r.Context {
@@ -628,12 +650,12 @@ func (p *Package) rewriteRef(f *File) {
 					expr = r.Name.Type.Go
 					break
 				}
-				error(r.Pos(), "call of non-function C.%s", r.Name.Go)
+				error_(r.Pos(), "call of non-function C.%s", r.Name.Go)
 				break
 			}
 			if r.Context == "call2" {
 				if r.Name.FuncType.Result == nil {
-					error(r.Pos(), "assignment count mismatch: 2 = 0")
+					error_(r.Pos(), "assignment count mismatch: 2 = 0")
 				}
 				// Invent new Name for the two-result function.
 				n := f.Name["2"+r.Name.Go]
@@ -650,7 +672,7 @@ func (p *Package) rewriteRef(f *File) {
 			}
 		case "expr":
 			if r.Name.Kind == "func" {
-				error(r.Pos(), "must call C.%s", r.Name.Go)
+				error_(r.Pos(), "must call C.%s", r.Name.Go)
 			}
 			if r.Name.Kind == "type" {
 				// Okay - might be new(T)
@@ -662,13 +684,28 @@ func (p *Package) rewriteRef(f *File) {
 
 		case "type":
 			if r.Name.Kind != "type" {
-				error(r.Pos(), "expression C.%s used as type", r.Name.Go)
+				error_(r.Pos(), "expression C.%s used as type", r.Name.Go)
+			} else if r.Name.Type == nil {
+				// Use of C.enum_x, C.struct_x or C.union_x without C definition.
+				// GCC won't raise an error when using pointers to such unknown types.
+				error_(r.Pos(), "type C.%s: undefined C type '%s'", r.Name.Go, r.Name.C)
 			} else {
 				expr = r.Name.Type.Go
 			}
 		default:
 			if r.Name.Kind == "func" {
-				error(r.Pos(), "must call C.%s", r.Name.Go)
+				error_(r.Pos(), "must call C.%s", r.Name.Go)
+			}
+		}
+		if *godefs || *cdefs {
+			// Substitute definition for mangled type name.
+			if id, ok := expr.(*ast.Ident); ok {
+				if t := typedef[id.Name]; t != nil {
+					expr = t
+				}
+				if id.Name == r.Name.Mangle && r.Name.Const != "" {
+					expr = ast.NewIdent(r.Name.Const)
+				}
 			}
 		}
 		*r.Expr = expr
@@ -696,7 +733,9 @@ func (p *Package) gccMachine() []string {
 	return nil
 }
 
-var gccTmp = objDir + "_cgo_.o"
+func gccTmp() string {
+	return *objDir + "_cgo_.o"
+}
 
 // gccCmd returns the gcc command line to use for compiling
 // the input.
@@ -705,7 +744,7 @@ func (p *Package) gccCmd() []string {
 		p.gccName(),
 		"-Wall",                             // many warnings
 		"-Werror",                           // warnings are errors
-		"-o" + gccTmp,                       // write object to tmp
+		"-o" + gccTmp(),                     // write object to tmp
 		"-gdwarf-2",                         // generate DWARF v2 debugging symbols
 		"-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise
 		"-c",                                // do not link
@@ -722,10 +761,10 @@ func (p *Package) gccCmd() []string {
 func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
 	runGcc(stdin, p.gccCmd())
 
-	if f, err := macho.Open(gccTmp); err == nil {
+	if f, err := macho.Open(gccTmp()); err == nil {
 		d, err := f.DWARF()
 		if err != nil {
-			fatalf("cannot load DWARF output from %s: %v", gccTmp, err)
+			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
 		}
 		var data []byte
 		if f.Symtab != nil {
@@ -751,23 +790,23 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
 	// Can skip debug data block in ELF and PE for now.
 	// The DWARF information is complete.
 
-	if f, err := elf.Open(gccTmp); err == nil {
+	if f, err := elf.Open(gccTmp()); err == nil {
 		d, err := f.DWARF()
 		if err != nil {
-			fatalf("cannot load DWARF output from %s: %v", gccTmp, err)
+			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
 		}
 		return d, f.ByteOrder, nil
 	}
 
-	if f, err := pe.Open(gccTmp); err == nil {
+	if f, err := pe.Open(gccTmp()); err == nil {
 		d, err := f.DWARF()
 		if err != nil {
-			fatalf("cannot load DWARF output from %s: %v", gccTmp, err)
+			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
 		}
 		return d, binary.LittleEndian, nil
 	}
 
-	fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp)
+	fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
 	panic("not reached")
 }
 
@@ -848,6 +887,7 @@ type typeConv struct {
 
 var tagGen int
 var typedef = make(map[string]ast.Expr)
+var goIdent = make(map[string]*ast.Ident)
 
 func (c *typeConv) Init(ptrSize int64) {
 	c.ptrSize = ptrSize
@@ -1113,6 +1153,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
 		}
 		name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
 		t.Go = name // publish before recursive calls
+		goIdent[name.Name] = name
 		switch dt.Kind {
 		case "union", "class":
 			typedef[name.Name] = c.Opaque(t.Size)
@@ -1147,7 +1188,8 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
 			t.Align = c.ptrSize
 			break
 		}
-		name := c.Ident("_Ctypedef_" + dt.Name)
+		name := c.Ident("_Ctype_" + dt.Name)
+		goIdent[name.Name] = name
 		t.Go = name // publish before recursive call
 		sub := c.Type(dt.Type)
 		t.Size = sub.Size
@@ -1155,6 +1197,9 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
 		if _, ok := typedef[name.Name]; !ok {
 			typedef[name.Name] = sub.Go
 		}
+		if *godefs || *cdefs {
+			t.Go = sub.Go
+		}
 
 	case *dwarf.UcharType:
 		if t.Size != 1 {
@@ -1198,7 +1243,9 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
 			s = strings.Join(strings.Split(s, " "), "") // strip spaces
 			name := c.Ident("_Ctype_" + s)
 			typedef[name.Name] = t.Go
-			t.Go = name
+			if !*godefs && !*cdefs {
+				t.Go = name
+			}
 		}
 	}
 
@@ -1263,7 +1310,7 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType) *FuncType {
 	var gr []*ast.Field
 	if _, ok := dtype.ReturnType.(*dwarf.VoidType); !ok && dtype.ReturnType != nil {
 		r = c.Type(dtype.ReturnType)
-		gr = []*ast.Field{&ast.Field{Type: r.Go}}
+		gr = []*ast.Field{{Type: r.Go}}
 	}
 	return &FuncType{
 		Params: p,
@@ -1292,7 +1339,7 @@ func (c *typeConv) Opaque(n int64) ast.Expr {
 func (c *typeConv) intExpr(n int64) ast.Expr {
 	return &ast.BasicLit{
 		Kind:  token.INT,
-		Value: strconv.Itoa64(n),
+		Value: strconv.FormatInt(n, 10),
 	}
 }
 
@@ -1323,38 +1370,61 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
 		ident[f.Name] = f.Name
 		used[f.Name] = true
 	}
-	for cid, goid := range ident {
-		if token.Lookup([]byte(goid)).IsKeyword() {
-			// Avoid keyword
-			goid = "_" + goid
 
-			// Also avoid existing fields
-			for _, exist := used[goid]; exist; _, exist = used[goid] {
+	if !*godefs && !*cdefs {
+		for cid, goid := range ident {
+			if token.Lookup(goid).IsKeyword() {
+				// Avoid keyword
 				goid = "_" + goid
-			}
 
-			used[goid] = true
-			ident[cid] = goid
+				// Also avoid existing fields
+				for _, exist := used[goid]; exist; _, exist = used[goid] {
+					goid = "_" + goid
+				}
+
+				used[goid] = true
+				ident[cid] = goid
+			}
 		}
 	}
 
+	anon := 0
 	for _, f := range dt.Field {
-		if f.BitSize > 0 && f.BitSize != f.ByteSize*8 {
-			continue
-		}
 		if f.ByteOffset > off {
 			fld = c.pad(fld, f.ByteOffset-off)
 			off = f.ByteOffset
 		}
 		t := c.Type(f.Type)
+		tgo := t.Go
+		size := t.Size
+
+		if f.BitSize > 0 {
+			if f.BitSize%8 != 0 {
+				continue
+			}
+			size = f.BitSize / 8
+			name := tgo.(*ast.Ident).String()
+			if strings.HasPrefix(name, "int") {
+				name = "int"
+			} else {
+				name = "uint"
+			}
+			tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
+		}
+
 		n := len(fld)
 		fld = fld[0 : n+1]
-
-		fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[f.Name])}, Type: t.Go}
-		off += t.Size
+		name := f.Name
+		if name == "" {
+			name = fmt.Sprintf("anon%d", anon)
+			anon++
+			ident[name] = name
+		}
+		fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
+		off += size
 		buf.WriteString(t.C.String())
 		buf.WriteString(" ")
-		buf.WriteString(f.Name)
+		buf.WriteString(name)
 		buf.WriteString("; ")
 		if t.Align > align {
 			align = t.Align
@@ -1369,6 +1439,96 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
 	}
 	buf.WriteString("}")
 	csyntax = buf.String()
+
+	if *godefs || *cdefs {
+		godefsFields(fld)
+	}
 	expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
 	return
 }
+
+func upper(s string) string {
+	if s == "" {
+		return ""
+	}
+	r, size := utf8.DecodeRuneInString(s)
+	if r == '_' {
+		return "X" + s
+	}
+	return string(unicode.ToUpper(r)) + s[size:]
+}
+
+// godefsFields rewrites field names for use in Go or C definitions.
+// It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
+// converts names to upper case, and rewrites _ into Pad_godefs_n,
+// so that all fields are exported.
+func godefsFields(fld []*ast.Field) {
+	prefix := fieldPrefix(fld)
+	npad := 0
+	for _, f := range fld {
+		for _, n := range f.Names {
+			if strings.HasPrefix(n.Name, prefix) && n.Name != prefix {
+				n.Name = n.Name[len(prefix):]
+			}
+			if n.Name == "_" {
+				// Use exported name instead.
+				n.Name = "Pad_cgo_" + strconv.Itoa(npad)
+				npad++
+			}
+			if !*cdefs {
+				n.Name = upper(n.Name)
+			}
+		}
+		p := &f.Type
+		t := *p
+		if star, ok := t.(*ast.StarExpr); ok {
+			star = &ast.StarExpr{X: star.X}
+			*p = star
+			p = &star.X
+			t = *p
+		}
+		if id, ok := t.(*ast.Ident); ok {
+			if id.Name == "unsafe.Pointer" {
+				*p = ast.NewIdent("*byte")
+			}
+		}
+	}
+}
+
+// fieldPrefix returns the prefix that should be removed from all the
+// field names when generating the C or Go code.  For generated 
+// C, we leave the names as is (tv_sec, tv_usec), since that's what
+// people are used to seeing in C.  For generated Go code, such as
+// package syscall's data structures, we drop a common prefix
+// (so sec, usec, which will get turned into Sec, Usec for exporting).
+func fieldPrefix(fld []*ast.Field) string {
+	if *cdefs {
+		return ""
+	}
+	prefix := ""
+	for _, f := range fld {
+		for _, n := range f.Names {
+			// Ignore field names that don't have the prefix we're
+			// looking for.  It is common in C headers to have fields
+			// named, say, _pad in an otherwise prefixed header.
+			// If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
+			// still want to remove the tv_ prefix.
+			// The check for "orig_" here handles orig_eax in the 
+			// x86 ptrace register sets, which otherwise have all fields
+			// with reg_ prefixes.
+			if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
+				continue
+			}
+			i := strings.Index(n.Name, "_")
+			if i < 0 {
+				continue
+			}
+			if prefix == "" {
+				prefix = n.Name[:i+1]
+			} else if prefix != n.Name[:i+1] {
+				return ""
+			}
+		}
+	}
+	return prefix
+}
diff --git a/src/cmd/cgo/godefs.go b/src/cmd/cgo/godefs.go
new file mode 100644
index 0000000..6838729
--- /dev/null
+++ b/src/cmd/cgo/godefs.go
@@ -0,0 +1,289 @@
+// Copyright 2011 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 (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/printer"
+	"go/token"
+	"os"
+	"strings"
+)
+
+// godefs returns the output for -godefs mode.
+func (p *Package) godefs(f *File, srcfile string) string {
+	var buf bytes.Buffer
+
+	fmt.Fprintf(&buf, "// Created by cgo -godefs - DO NOT EDIT\n")
+	fmt.Fprintf(&buf, "// %s\n", strings.Join(os.Args, " "))
+	fmt.Fprintf(&buf, "\n")
+
+	override := make(map[string]string)
+
+	// Allow source file to specify override mappings.
+	// For example, the socket data structures refer
+	// to in_addr and in_addr6 structs but we want to be
+	// able to treat them as byte arrays, so the godefs
+	// inputs in package syscall say
+	//
+	//	// +godefs map struct_in_addr [4]byte
+	//	// +godefs map struct_in_addr6 [16]byte
+	//
+	for _, g := range f.Comments {
+		for _, c := range g.List {
+			i := strings.Index(c.Text, "+godefs map")
+			if i < 0 {
+				continue
+			}
+			s := strings.TrimSpace(c.Text[i+len("+godefs map"):])
+			i = strings.Index(s, " ")
+			if i < 0 {
+				fmt.Fprintf(os.Stderr, "invalid +godefs map comment: %s\n", c.Text)
+				continue
+			}
+			override["_Ctype_"+strings.TrimSpace(s[:i])] = strings.TrimSpace(s[i:])
+		}
+	}
+	for _, n := range f.Name {
+		if s := override[n.Go]; s != "" {
+			override[n.Mangle] = s
+		}
+	}
+
+	// Otherwise, if the source file says type T C.whatever,
+	// use "T" as the mangling of C.whatever,
+	// except in the definition (handled at end of function).
+	refName := make(map[*ast.Expr]*Name)
+	for _, r := range f.Ref {
+		refName[r.Expr] = r.Name
+	}
+	for _, d := range f.AST.Decls {
+		d, ok := d.(*ast.GenDecl)
+		if !ok || d.Tok != token.TYPE {
+			continue
+		}
+		for _, s := range d.Specs {
+			s := s.(*ast.TypeSpec)
+			n := refName[&s.Type]
+			if n != nil && n.Mangle != "" {
+				override[n.Mangle] = s.Name.Name
+			}
+		}
+	}
+
+	// Extend overrides using typedefs:
+	// If we know that C.xxx should format as T
+	// and xxx is a typedef for yyy, make C.yyy format as T.
+	for typ, def := range typedef {
+		if new := override[typ]; new != "" {
+			if id, ok := def.(*ast.Ident); ok {
+				override[id.Name] = new
+			}
+		}
+	}
+
+	// Apply overrides.
+	for old, new := range override {
+		if id := goIdent[old]; id != nil {
+			id.Name = new
+		}
+	}
+
+	// Any names still using the _C syntax are not going to compile,
+	// although in general we don't know whether they all made it
+	// into the file, so we can't warn here.
+	//
+	// The most common case is union types, which begin with
+	// _Ctype_union and for which typedef[name] is a Go byte
+	// array of the appropriate size (such as [4]byte).
+	// Substitute those union types with byte arrays.
+	for name, id := range goIdent {
+		if id.Name == name && strings.Contains(name, "_Ctype_union") {
+			if def := typedef[name]; def != nil {
+				id.Name = gofmt(def)
+			}
+		}
+	}
+
+	printer.Fprint(&buf, fset, f.AST)
+
+	return buf.String()
+}
+
+// cdefs returns the output for -cdefs mode.
+// The easiest way to do this is to translate the godefs Go to C.
+func (p *Package) cdefs(f *File, srcfile string) string {
+	godefsOutput := p.godefs(f, srcfile)
+
+	lines := strings.Split(godefsOutput, "\n")
+	lines[0] = "// Created by cgo -cdefs - DO NOT EDIT"
+
+	for i, line := range lines {
+		lines[i] = strings.TrimSpace(line)
+	}
+
+	var out bytes.Buffer
+	printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, format, args...) }
+
+	didTypedef := false
+	for i := 0; i < len(lines); i++ {
+		line := lines[i]
+
+		// Delete
+		//	package x
+		if strings.HasPrefix(line, "package ") {
+			continue
+		}
+
+		// Convert
+		//	const (
+		//		A = 1
+		//		B = 2
+		//	)
+		//
+		// to
+		//
+		//	enum {
+		//		A = 1,
+		//		B = 2,
+		//	};
+		if line == "const (" {
+			printf("enum {\n")
+			for i++; i < len(lines) && lines[i] != ")"; i++ {
+				line = lines[i]
+				if line != "" {
+					printf("\t%s,", line)
+				}
+				printf("\n")
+			}
+			printf("};\n")
+			continue
+		}
+
+		// Convert
+		//	const A = 1
+		// to
+		//	enum { A = 1 };
+		if strings.HasPrefix(line, "const ") {
+			printf("enum { %s };\n", line[len("const "):])
+			continue
+		}
+
+		// On first type definition, typedef all the structs
+		// in case there are dependencies between them.
+		if !didTypedef && strings.HasPrefix(line, "type ") {
+			didTypedef = true
+			for _, line := range lines {
+				line = strings.TrimSpace(line)
+				if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
+					s := line[len("type ") : len(line)-len(" struct {")]
+					printf("typedef struct %s %s;\n", s, s)
+				}
+			}
+			printf("\n")
+			printf("#pragma pack on\n")
+			printf("\n")
+		}
+
+		// Convert
+		//	type T struct {
+		//		X int64
+		//		Y *int32
+		//		Z [4]byte
+		//	}
+		//
+		// to
+		//
+		//	struct T {
+		//		int64 X;
+		//		int32 *Y;
+		//		byte Z[4];
+		//	}
+		if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
+			s := line[len("type ") : len(line)-len(" struct {")]
+			printf("struct %s {\n", s)
+			for i++; i < len(lines) && lines[i] != "}"; i++ {
+				line := lines[i]
+				if line != "" {
+					f := strings.Fields(line)
+					if len(f) != 2 {
+						fmt.Fprintf(os.Stderr, "cgo: cannot parse struct field: %s\n", line)
+						nerrors++
+						continue
+					}
+					printf("\t%s;", cdecl(f[0], f[1]))
+				}
+				printf("\n")
+			}
+			printf("};\n")
+			continue
+		}
+
+		// Convert
+		//	type T int
+		// to
+		//	typedef int T;
+		if strings.HasPrefix(line, "type ") {
+			f := strings.Fields(line[len("type "):])
+			if len(f) != 2 {
+				fmt.Fprintf(os.Stderr, "cgo: cannot parse type definition: %s\n", line)
+				nerrors++
+				continue
+			}
+			printf("typedef\t%s;\n", cdecl(f[0], f[1]))
+			continue
+		}
+
+		printf("%s\n", line)
+	}
+
+	if didTypedef {
+		printf("\n")
+		printf("#pragma pack off\n")
+	}
+
+	return out.String()
+}
+
+// cdecl returns the C declaration for the given Go name and type.
+// It only handles the specific cases necessary for converting godefs output.
+func cdecl(name, typ string) string {
+	// X *[0]byte -> X *void
+	if strings.HasPrefix(typ, "*[0]") {
+		typ = "*void"
+	}
+	// X *byte -> *X byte
+	if strings.HasPrefix(typ, "*") {
+		name = "*" + name
+		typ = typ[1:]
+	}
+	// X [4]byte -> X[4] byte
+	if strings.HasPrefix(typ, "[") {
+		i := strings.Index(typ, "]") + 1
+		name = name + typ[:i]
+		typ = typ[i:]
+	}
+	// X T -> T X
+	// Handle the special case: 'unsafe.Pointer' is 'void *'
+	if typ == "unsafe.Pointer" {
+		typ = "void"
+		name = "*" + name
+	}
+	return typ + "\t" + name
+}
+
+var gofmtBuf bytes.Buffer
+
+// gofmt returns the gofmt-formatted string for an AST node.
+func gofmt(n interface{}) string {
+	gofmtBuf.Reset()
+	err := printer.Fprint(&gofmtBuf, fset, n)
+	if err != nil {
+		return "<" + err.Error() + ">"
+	}
+	return gofmtBuf.String()
+}
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 1066981..f582912 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -43,6 +43,7 @@ type Package struct {
 // A File collects information about a single Go input file.
 type File struct {
 	AST      *ast.File           // parsed AST
+	Comments []*ast.CommentGroup // comments from file
 	Package  string              // Package name
 	Preamble string              // C preamble (doc comment on import "C")
 	Ref      []*Ref              // all references to C.xxx in AST
@@ -122,7 +123,17 @@ var cPrefix string
 var fset = token.NewFileSet()
 
 var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file")
+var dynout = flag.String("dynout", "", "write -dynobj output to this file")
 
+// These flags are for bootstrapping a new Go implementation,
+// to generate Go and C headers that match the data layout and
+// constant values used in the host's C libraries and system calls.
+var godefs = flag.Bool("godefs", false, "for bootstrap: write Go definitions for C file to standard output")
+var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C file to standard output")
+var objDir = flag.String("objdir", "", "object directory")
+
+var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
+var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
 var goarch, goos string
 
 func main() {
@@ -142,6 +153,11 @@ func main() {
 		return
 	}
 
+	if *godefs && *cdefs {
+		fmt.Fprintf(os.Stderr, "cgo: cannot use -cdefs and -godefs together\n")
+		os.Exit(2)
+	}
+
 	args := flag.Args()
 	if len(args) < 1 {
 		usage()
@@ -159,36 +175,9 @@ func main() {
 		usage()
 	}
 
-	// Copy it to a new slice so it can grow.
-	gccOptions := make([]string, i)
-	copy(gccOptions, args[0:i])
-
 	goFiles := args[i:]
 
-	goarch = runtime.GOARCH
-	if s := os.Getenv("GOARCH"); s != "" {
-		goarch = s
-	}
-	goos = runtime.GOOS
-	if s := os.Getenv("GOOS"); s != "" {
-		goos = s
-	}
-	ptrSize := ptrSizeMap[goarch]
-	if ptrSize == 0 {
-		fatalf("unknown $GOARCH %q", goarch)
-	}
-
-	// Clear locale variables so gcc emits English errors [sic].
-	os.Setenv("LANG", "en_US.UTF-8")
-	os.Setenv("LC_ALL", "C")
-	os.Setenv("LC_CTYPE", "C")
-
-	p := &Package{
-		PtrSize:    ptrSize,
-		GccOptions: gccOptions,
-		CgoFlags:   make(map[string]string),
-		Written:    make(map[string]bool),
-	}
+	p := newPackage(args[:i])
 
 	// Need a unique prefix for the global C symbols that
 	// we use to coordinate between gcc and ourselves.
@@ -204,7 +193,7 @@ func main() {
 		io.Copy(h, f)
 		f.Close()
 	}
-	cPrefix = fmt.Sprintf("_%x", h.Sum()[0:6])
+	cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6])
 
 	fs := make([]*File, len(goFiles))
 	for i, input := range goFiles {
@@ -215,9 +204,13 @@ func main() {
 		fs[i] = f
 	}
 
-	// make sure that _obj directory exists, so that we can write
-	// all the output files there.
-	os.Mkdir("_obj", 0777)
+	if *objDir == "" {
+		// make sure that _obj directory exists, so that we can write
+		// all the output files there.
+		os.Mkdir("_obj", 0777)
+		*objDir = "_obj"
+	}
+	*objDir += string(filepath.Separator)
 
 	for i, input := range goFiles {
 		f := fs[i]
@@ -239,23 +232,64 @@ func main() {
 			pkg = filepath.Join(dir, pkg)
 		}
 		p.PackagePath = pkg
-		p.writeOutput(f, input)
-
 		p.Record(f)
+		if *godefs {
+			os.Stdout.WriteString(p.godefs(f, input))
+		} else if *cdefs {
+			os.Stdout.WriteString(p.cdefs(f, input))
+		} else {
+			p.writeOutput(f, input)
+		}
 	}
 
-	p.writeDefs()
+	if !*godefs && !*cdefs {
+		p.writeDefs()
+	}
 	if nerrors > 0 {
 		os.Exit(2)
 	}
 }
 
+// newPackage returns a new Package that will invoke
+// gcc with the additional arguments specified in args.
+func newPackage(args []string) *Package {
+	// Copy the gcc options to a new slice so the list
+	// can grow without overwriting the slice that args is in.
+	gccOptions := make([]string, len(args))
+	copy(gccOptions, args)
+
+	goarch = runtime.GOARCH
+	if s := os.Getenv("GOARCH"); s != "" {
+		goarch = s
+	}
+	goos = runtime.GOOS
+	if s := os.Getenv("GOOS"); s != "" {
+		goos = s
+	}
+	ptrSize := ptrSizeMap[goarch]
+	if ptrSize == 0 {
+		fatalf("unknown $GOARCH %q", goarch)
+	}
+
+	// Reset locale variables so gcc emits English errors [sic].
+	os.Setenv("LANG", "en_US.UTF-8")
+	os.Setenv("LC_ALL", "C")
+
+	p := &Package{
+		PtrSize:    ptrSize,
+		GccOptions: gccOptions,
+		CgoFlags:   make(map[string]string),
+		Written:    make(map[string]bool),
+	}
+	return p
+}
+
 // Record what needs to be recorded about f.
 func (p *Package) Record(f *File) {
 	if p.PackageName == "" {
 		p.PackageName = f.Package
 	} else if p.PackageName != f.Package {
-		error(token.NoPos, "inconsistent package names: %s, %s", p.PackageName, f.Package)
+		error_(token.NoPos, "inconsistent package names: %s, %s", p.PackageName, f.Package)
 	}
 
 	if p.Name == nil {
@@ -265,7 +299,7 @@ func (p *Package) Record(f *File) {
 			if p.Name[k] == nil {
 				p.Name[k] = v
 			} else if !reflect.DeepEqual(p.Name[k], v) {
-				error(token.NoPos, "inconsistent definitions for C.%s", k)
+				error_(token.NoPos, "inconsistent definitions for C.%s", k)
 			}
 		}
 	}
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 498ab15..3e25b20 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -14,20 +14,17 @@ import (
 	"go/printer"
 	"go/token"
 	"os"
-	"path/filepath"
 	"strings"
 )
 
-var objDir = "_obj" + string(filepath.Separator)
-
 // writeDefs creates output files to be compiled by 6g, 6c, and gcc.
 // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
 func (p *Package) writeDefs() {
-	fgo2 := creat(objDir + "_cgo_gotypes.go")
-	fc := creat(objDir + "_cgo_defun.c")
-	fm := creat(objDir + "_cgo_main.c")
+	fgo2 := creat(*objDir + "_cgo_gotypes.go")
+	fc := creat(*objDir + "_cgo_defun.c")
+	fm := creat(*objDir + "_cgo_main.c")
 
-	fflg := creat(objDir + "_cgo_flags")
+	fflg := creat(*objDir + "_cgo_flags")
 	for k, v := range p.CgoFlags {
 		fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v)
 	}
@@ -35,7 +32,13 @@ func (p *Package) writeDefs() {
 
 	// Write C main file for using gcc to resolve imports.
 	fmt.Fprintf(fm, "int main() { return 0; }\n")
-	fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
+	if *importRuntimeCgo {
+		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
+	} else {
+		// If we're not importing runtime/cgo, we *are* runtime/cgo,
+		// which provides crosscall2.  We just need a prototype.
+		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);")
+	}
 	fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
 	fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
 
@@ -45,19 +48,25 @@ func (p *Package) writeDefs() {
 	fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
 	fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
 	fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
-	fmt.Fprintf(fgo2, "import \"os\"\n\n")
-	fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
+	fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
+	if !*gccgo && *importRuntimeCgo {
+		fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
+	}
 	fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
-	fmt.Fprintf(fgo2, "func _Cerrno(dst *os.Error, x int) { *dst = os.Errno(x) }\n")
+	fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int) { *dst = syscall.Errno(x) }\n")
 
 	for name, def := range typedef {
 		fmt.Fprintf(fgo2, "type %s ", name)
 		printer.Fprint(fgo2, fset, def)
-		fmt.Fprintf(fgo2, "\n")
+		fmt.Fprintf(fgo2, "\n\n")
 	}
 	fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
 
-	fmt.Fprintf(fc, cProlog)
+	if *gccgo {
+		fmt.Fprintf(fc, cPrologGccgo)
+	} else {
+		fmt.Fprintf(fc, cProlog)
+	}
 
 	cVars := make(map[string]bool)
 	for _, n := range p.Name {
@@ -103,6 +112,15 @@ func (p *Package) writeDefs() {
 }
 
 func dynimport(obj string) {
+	stdout := os.Stdout
+	if *dynout != "" {
+		f, err := os.Create(*dynout)
+		if err != nil {
+			fatalf("%s", err)
+		}
+		stdout = f
+	}
+
 	if f, err := elf.Open(obj); err == nil {
 		sym, err := f.ImportedSymbols()
 		if err != nil {
@@ -113,14 +131,14 @@ func dynimport(obj string) {
 			if s.Version != "" {
 				targ += "@" + s.Version
 			}
-			fmt.Printf("#pragma dynimport %s %s %q\n", s.Name, targ, s.Library)
+			fmt.Fprintf(stdout, "#pragma dynimport %s %s %q\n", s.Name, targ, s.Library)
 		}
 		lib, err := f.ImportedLibraries()
 		if err != nil {
 			fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
 		}
 		for _, l := range lib {
-			fmt.Printf("#pragma dynimport _ _ %q\n", l)
+			fmt.Fprintf(stdout, "#pragma dynimport _ _ %q\n", l)
 		}
 		return
 	}
@@ -134,14 +152,14 @@ func dynimport(obj string) {
 			if len(s) > 0 && s[0] == '_' {
 				s = s[1:]
 			}
-			fmt.Printf("#pragma dynimport %s %s %q\n", s, s, "")
+			fmt.Fprintf(stdout, "#pragma dynimport %s %s %q\n", s, s, "")
 		}
 		lib, err := f.ImportedLibraries()
 		if err != nil {
 			fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
 		}
 		for _, l := range lib {
-			fmt.Printf("#pragma dynimport _ _ %q\n", l)
+			fmt.Fprintf(stdout, "#pragma dynimport _ _ %q\n", l)
 		}
 		return
 	}
@@ -153,7 +171,7 @@ func dynimport(obj string) {
 		}
 		for _, s := range sym {
 			ss := strings.Split(s, ":")
-			fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
+			fmt.Fprintf(stdout, "#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1]))
 		}
 		return
 	}
@@ -203,7 +221,7 @@ func (p *Package) structType(n *Name) (string, int64) {
 		off += pad
 	}
 	if n.AddError {
-		fmt.Fprint(&buf, "\t\tvoid *e[2]; /* os.Error */\n")
+		fmt.Fprint(&buf, "\t\tvoid *e[2]; /* error */\n")
 		off += 2 * p.PtrSize
 	}
 	if off == 0 {
@@ -217,9 +235,9 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
 	name := n.Go
 	gtype := n.FuncType.Go
 	if n.AddError {
-		// Add "os.Error" to return type list.
+		// Add "error" to return type list.
 		// Type list is known to be 0 or 1 element - it's a C function.
-		err := &ast.Field{Type: ast.NewIdent("os.Error")}
+		err := &ast.Field{Type: ast.NewIdent("error")}
 		l := gtype.Results.List
 		if len(l) == 0 {
 			l = []*ast.Field{err}
@@ -238,13 +256,22 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
 		Type: gtype,
 	}
 	printer.Fprint(fgo2, fset, d)
-	fmt.Fprintf(fgo2, "\n")
+	if *gccgo {
+		fmt.Fprintf(fgo2, " __asm__(\"%s\")\n", n.C)
+	} else {
+		fmt.Fprintf(fgo2, "\n")
+	}
 
 	if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" {
 		// The builtins are already defined in the C prolog.
 		return
 	}
 
+	// gccgo does not require a wrapper unless an error must be returned.
+	if *gccgo && !n.AddError {
+		return
+	}
+
 	var argSize int64
 	_, argSize = p.structType(n)
 
@@ -276,7 +303,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
 				v[0] = 0;
 				v[1] = 0;
 			} else {
-				·_Cerrno(v, e);	/* fill in v as os.Error for errno e */
+				·_Cerrno(v, e);	/* fill in v as error for errno e */
 			}
 		}`)
 	}
@@ -292,8 +319,8 @@ func (p *Package) writeOutput(f *File, srcfile string) {
 		base = base[0 : len(base)-3]
 	}
 	base = strings.Map(slashToUnderscore, base)
-	fgo1 := creat(objDir + base + ".cgo1.go")
-	fgcc := creat(objDir + base + ".cgo2.c")
+	fgo1 := creat(*objDir + base + ".cgo1.go")
+	fgcc := creat(*objDir + base + ".cgo2.c")
 
 	p.GoFiles = append(p.GoFiles, base+".cgo1.go")
 	p.GccFiles = append(p.GccFiles, base+".cgo2.c")
@@ -368,8 +395,8 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
 // Write out the various stubs we need to support functions exported
 // from Go so that they are callable from C.
 func (p *Package) writeExports(fgo2, fc, fm *os.File) {
-	fgcc := creat(objDir + "_cgo_export.c")
-	fgcch := creat("_cgo_export.h")
+	fgcc := creat(*objDir + "_cgo_export.c")
+	fgcch := creat(*objDir + "_cgo_export.h")
 
 	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
 	fmt.Fprintf(fgcch, "%s\n", gccExportHeaderProlog)
@@ -501,6 +528,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
 		if fn.Recv != nil {
 			goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
 		}
+		fmt.Fprintf(fc, "#pragma dynexport %s %s\n", goname, goname)
 		fmt.Fprintf(fc, "extern void ·%s();\n", goname)
 		fmt.Fprintf(fc, "\nvoid\n")
 		fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
@@ -577,22 +605,25 @@ func c(repr string, args ...interface{}) *TypeRepr {
 
 // Map predeclared Go types to Type.
 var goTypes = map[string]*Type{
-	"int":        &Type{Size: 4, Align: 4, C: c("int")},
-	"uint":       &Type{Size: 4, Align: 4, C: c("uint")},
-	"int8":       &Type{Size: 1, Align: 1, C: c("schar")},
-	"uint8":      &Type{Size: 1, Align: 1, C: c("uchar")},
-	"int16":      &Type{Size: 2, Align: 2, C: c("short")},
-	"uint16":     &Type{Size: 2, Align: 2, C: c("ushort")},
-	"int32":      &Type{Size: 4, Align: 4, C: c("int")},
-	"uint32":     &Type{Size: 4, Align: 4, C: c("uint")},
-	"int64":      &Type{Size: 8, Align: 8, C: c("int64")},
-	"uint64":     &Type{Size: 8, Align: 8, C: c("uint64")},
-	"float":      &Type{Size: 4, Align: 4, C: c("float")},
-	"float32":    &Type{Size: 4, Align: 4, C: c("float")},
-	"float64":    &Type{Size: 8, Align: 8, C: c("double")},
-	"complex":    &Type{Size: 8, Align: 8, C: c("__complex float")},
-	"complex64":  &Type{Size: 8, Align: 8, C: c("__complex float")},
-	"complex128": &Type{Size: 16, Align: 16, C: c("__complex double")},
+	"bool":       {Size: 1, Align: 1, C: c("uchar")},
+	"byte":       {Size: 1, Align: 1, C: c("uchar")},
+	"int":        {Size: 4, Align: 4, C: c("int")},
+	"uint":       {Size: 4, Align: 4, C: c("uint")},
+	"rune":       {Size: 4, Align: 4, C: c("int")},
+	"int8":       {Size: 1, Align: 1, C: c("schar")},
+	"uint8":      {Size: 1, Align: 1, C: c("uchar")},
+	"int16":      {Size: 2, Align: 2, C: c("short")},
+	"uint16":     {Size: 2, Align: 2, C: c("ushort")},
+	"int32":      {Size: 4, Align: 4, C: c("int")},
+	"uint32":     {Size: 4, Align: 4, C: c("uint")},
+	"int64":      {Size: 8, Align: 8, C: c("int64")},
+	"uint64":     {Size: 8, Align: 8, C: c("uint64")},
+	"float":      {Size: 4, Align: 4, C: c("float")},
+	"float32":    {Size: 4, Align: 4, C: c("float")},
+	"float64":    {Size: 8, Align: 8, C: c("double")},
+	"complex":    {Size: 8, Align: 8, C: c("__complex float")},
+	"complex64":  {Size: 8, Align: 8, C: c("__complex float")},
+	"complex128": {Size: 16, Align: 16, C: c("__complex double")},
 }
 
 // Map an ast type to a Type.
@@ -610,7 +641,7 @@ func (p *Package) cgoType(e ast.Expr) *Type {
 	case *ast.FuncType:
 		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
 	case *ast.InterfaceType:
-		return &Type{Size: 3 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
+		return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
 	case *ast.MapType:
 		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
 	case *ast.ChanType:
@@ -644,13 +675,16 @@ func (p *Package) cgoType(e ast.Expr) *Type {
 		if t.Name == "string" {
 			return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: c("GoString")}
 		}
+		if t.Name == "error" {
+			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
+		}
 		if r, ok := goTypes[t.Name]; ok {
 			if r.Align > p.PtrSize {
 				r.Align = p.PtrSize
 			}
 			return r
 		}
-		error(e.Pos(), "unrecognized Go type %s", t.Name)
+		error_(e.Pos(), "unrecognized Go type %s", t.Name)
 		return &Type{Size: 4, Align: 4, C: c("int")}
 	case *ast.SelectorExpr:
 		id, ok := t.X.(*ast.Ident)
@@ -658,7 +692,7 @@ func (p *Package) cgoType(e ast.Expr) *Type {
 			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
 		}
 	}
-	error(e.Pos(), "unrecognized Go type %T", e)
+	error_(e.Pos(), "unrecognized Go type %T", e)
 	return &Type{Size: 4, Align: 4, C: c("int")}
 }
 
@@ -729,6 +763,42 @@ void
 }
 `
 
+const cPrologGccgo = `
+#include <stdint.h>
+#include <string.h>
+
+struct __go_string {
+	const unsigned char *__data;
+	int __length;
+};
+
+typedef struct __go_open_array {
+	void* __values;
+	int __count;
+	int __capacity;
+} Slice;
+
+struct __go_string __go_byte_array_to_string(const void* p, int len);
+struct __go_open_array __go_string_to_byte_array (struct __go_string str);
+
+const char *CString(struct __go_string s) {
+	return strndup(s.__data, s.__length);
+}
+
+struct __go_string GoString(char *p) {
+	return __go_byte_array_to_string(p, strlen(p));
+}
+
+struct __go_string GoStringN(char *p, int n) {
+	return __go_byte_array_to_string(p, n);
+}
+
+Slice GoBytes(char *p, int n) {
+	struct __go_string s = { p, n };
+	return __go_string_to_byte_array(s);
+}
+`
+
 const gccExportHeaderProlog = `
 typedef unsigned int uint;
 typedef signed char schar;
diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go
index e79b0e1..8a77841 100644
--- a/src/cmd/cgo/util.go
+++ b/src/cmd/cgo/util.go
@@ -5,11 +5,11 @@
 package main
 
 import (
-	"exec"
 	"fmt"
 	"go/token"
 	"io/ioutil"
 	"os"
+	"os/exec"
 )
 
 // run runs the command argv, feeding in stdin on standard input.
@@ -72,7 +72,7 @@ func fatalf(msg string, args ...interface{}) {
 
 var nerrors int
 
-func error(pos token.Pos, msg string, args ...interface{}) {
+func error_(pos token.Pos, msg string, args ...interface{}) {
 	nerrors++
 	if pos.IsValid() {
 		fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String())
@@ -102,7 +102,7 @@ func creat(name string) *os.File {
 	return f
 }
 
-func slashToUnderscore(c int) int {
+func slashToUnderscore(c rune) rune {
 	if c == '/' || c == '\\' || c == ':' {
 		c = '_'
 	}
diff --git a/src/cmd/cov/Makefile b/src/cmd/cov/Makefile
index 62836fc..c080f4a 100644
--- a/src/cmd/cov/Makefile
+++ b/src/cmd/cov/Makefile
@@ -29,6 +29,7 @@ endif
 install: install-$(NAME)
 install-linux: install-default
 install-freebsd: install-default
+install-netbsd: install-default
 install-openbsd: install-default
 install-windows: install-default
 
diff --git a/src/cmd/cov/main.c b/src/cmd/cov/main.c
index ecbabf3..9496632 100644
--- a/src/cmd/cov/main.c
+++ b/src/cmd/cov/main.c
@@ -7,10 +7,8 @@
  */
 
 #include <u.h>
-#include <time.h>
 #include <libc.h>
 #include <bio.h>
-#include <ctype.h>
 #include "tree.h"
 
 #include <ureg_amd64.h>
@@ -394,7 +392,7 @@ startprocess(char **argv)
 		pid = getpid();
 		if(ctlproc(pid, "hang") < 0)
 			sysfatal("ctlproc hang: %r");
-		execv(argv[0], argv);
+		exec(argv[0], argv);
 		sysfatal("exec %s: %r", argv[0]);
 	}
 	if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0)
@@ -454,7 +452,6 @@ main(int argc, char **argv)
 
 	if(argc == 0) {
 		*--argv = "6.out";
-		argc++;
 	}
 	fd = open(argv[0], OREAD);
 	if(fd < 0)
diff --git a/src/cmd/ebnflint/Makefile b/src/cmd/ebnflint/Makefile
deleted file mode 100644
index 8f030aa..0000000
--- a/src/cmd/ebnflint/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=ebnflint
-GOFILES=\
-	ebnflint.go\
-
-include ../../Make.cmd
-
-test: $(TARG)
-	$(TARG) -start="SourceFile" "$(GOROOT)"/doc/go_spec.html
-
diff --git a/src/cmd/ebnflint/ebnflint.go b/src/cmd/ebnflint/ebnflint.go
deleted file mode 100644
index 009b336..0000000
--- a/src/cmd/ebnflint/ebnflint.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-	"bytes"
-	"ebnf"
-	"flag"
-	"fmt"
-	"go/scanner"
-	"go/token"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-)
-
-var fset = token.NewFileSet()
-var start = flag.String("start", "Start", "name of start production")
-
-func usage() {
-	fmt.Fprintf(os.Stderr, "usage: ebnflint [flags] [filename]\n")
-	flag.PrintDefaults()
-	os.Exit(1)
-}
-
-// Markers around EBNF sections in .html files
-var (
-	open  = []byte(`<pre class="ebnf">`)
-	close = []byte(`</pre>`)
-)
-
-func report(err os.Error) {
-	scanner.PrintError(os.Stderr, err)
-	os.Exit(1)
-}
-
-func extractEBNF(src []byte) []byte {
-	var buf bytes.Buffer
-
-	for {
-		// i = beginning of EBNF text
-		i := bytes.Index(src, open)
-		if i < 0 {
-			break // no EBNF found - we are done
-		}
-		i += len(open)
-
-		// write as many newlines as found in the excluded text
-		// to maintain correct line numbers in error messages
-		for _, ch := range src[0:i] {
-			if ch == '\n' {
-				buf.WriteByte('\n')
-			}
-		}
-
-		// j = end of EBNF text (or end of source)
-		j := bytes.Index(src[i:], close) // close marker
-		if j < 0 {
-			j = len(src) - i
-		}
-		j += i
-
-		// copy EBNF text
-		buf.Write(src[i:j])
-
-		// advance
-		src = src[j:]
-	}
-
-	return buf.Bytes()
-}
-
-func main() {
-	flag.Parse()
-
-	var (
-		filename string
-		src      []byte
-		err      os.Error
-	)
-	switch flag.NArg() {
-	case 0:
-		filename = "<stdin>"
-		src, err = ioutil.ReadAll(os.Stdin)
-	case 1:
-		filename = flag.Arg(0)
-		src, err = ioutil.ReadFile(filename)
-	default:
-		usage()
-	}
-	if err != nil {
-		report(err)
-	}
-
-	if filepath.Ext(filename) == ".html" || bytes.Index(src, open) >= 0 {
-		src = extractEBNF(src)
-	}
-
-	grammar, err := ebnf.Parse(fset, filename, src)
-	if err != nil {
-		report(err)
-	}
-
-	if err = ebnf.Verify(fset, grammar, *start); err != nil {
-		report(err)
-	}
-}
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index f7e3051..bb0d016 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -24,15 +24,17 @@ OFILES=\
 	dcl.$O\
 	esc.$O\
 	export.$O\
+	fmt.$O\
 	gen.$O\
 	init.$O\
+	inl.$O\
 	lex.$O\
 	md5.$O\
 	mparith1.$O\
 	mparith2.$O\
 	mparith3.$O\
 	obj.$O\
-	print.$O\
+	order.$O\
 	range.$O\
 	reflect.$O\
 	select.$O\
@@ -44,6 +46,8 @@ OFILES=\
 	walk.$O\
 	y1.tab.$O\
 
+HOST_CFLAGS+=-DGOEXPERIMENT='"$(GOEXPERIMENT)"' 
+
 NOINSTALL=1
 include ../../Make.clib
 
@@ -60,7 +64,7 @@ subr.$O: yerr.h
 builtin.c: builtin.c.boot
 	cp builtin.c.boot builtin.c
 
-subr.$O: opnames.h
+fmt.$O: opnames.h
 
 opnames.h:	mkopnames go.h
 	./mkopnames go.h >opnames.h
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index f316c19..6982bbe 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -285,6 +285,9 @@ dowidth(Type *t)
 		break;
 	}
 
+	if(widthptr == 4 && w != (int32)w)
+		yyerror("type %T too large", t);
+
 	t->width = w;
 	if(t->align == 0) {
 		if(w > 8 || (w&(w-1)) != 0)
@@ -491,12 +494,13 @@ typeinit(void)
 	okforeq[TPTR64] = 1;
 	okforeq[TUNSAFEPTR] = 1;
 	okforeq[TINTER] = 1;
-	okforeq[TMAP] = 1;
 	okforeq[TCHAN] = 1;
-	okforeq[TFUNC] = 1;
 	okforeq[TSTRING] = 1;
 	okforeq[TBOOL] = 1;
-	okforeq[TARRAY] = 1;	// refined in typecheck
+	okforeq[TMAP] = 1;	// nil only; refined in typecheck
+	okforeq[TFUNC] = 1;	// nil only; refined in typecheck
+	okforeq[TARRAY] = 1;	// nil slice only; refined in typecheck
+	okforeq[TSTRUCT] = 1;	// it's complicated; refined in typecheck
 
 	okforcmp[TSTRING] = 1;
 
diff --git a/src/cmd/gc/bisonerrors b/src/cmd/gc/bisonerrors
index 5110f53..0f865d0 100755
--- a/src/cmd/gc/bisonerrors
+++ b/src/cmd/gc/bisonerrors
@@ -46,24 +46,36 @@ bison && /^state 0/ { grammar = 0; states = 1 }
 states && /^state / { state = $2 }
 states { statetext[state] = statetext[state] $0 "\n" }
 
-states && / shift, and go to state/ {
+states && / shift/ {
 	n = nshift[state]++
-	shift[state,n] = $7
+	if($0 ~ /and go to/)
+		shift[state,n] = $7 # GNU Bison
+	else
+		shift[state,n] = $3 # Plan 9 Yacc
 	shifttoken[state,n] = $1
 	next
 }
-states && / go to state/ {
+states && / (go to|goto)/ {
 	n = nshift[state]++
-	shift[state,n] = $5
+	if($0 ~ /go to/)
+		shift[state,n] = $5 # GNU Bison
+	else
+		shift[state,n] = $3 # Plan 9 Yacc
 	shifttoken[state,n] = $1
 	next
 }
-states && / reduce using rule/ {
+states && / reduce/ {
 	n = nreduce[state]++
-	reduce[state,n] = $5
+	if($0 ~ /reduce using rule/)
+		reduce[state,n] = $5 # GNU Bison
+	else
+		reduce[state,n] = $3 # Plan 9 yacc
 	reducetoken[state,n] = $1
 	next
-}	
+}
+
+# Skip over the summary information printed by Plan 9 yacc.
+/nonterminals$/,/^maximum spread/ { next }
 
 # First // comment marks the beginning of the pattern file.
 /^\/\// { bison = 0; grammar = 0; state = 0 }
@@ -96,7 +108,8 @@ $1 == "%" {
 		if(found)
 			continue
 		for(j=0; j<nreduce[state]; j++) {
-			if(reducetoken[state,j] == tok || reducetoken[state,j] == "$default") {
+			t = reducetoken[state,j]
+			if(t == tok || t == "$default" || t == ".") {
 				stack[nstack++] = state
 				rule = reduce[state,j]
 				nstack -= rulesize[rule]
diff --git a/src/cmd/gc/bits.c b/src/cmd/gc/bits.c
index f3b031c..c0fd4d8 100644
--- a/src/cmd/gc/bits.c
+++ b/src/cmd/gc/bits.c
@@ -151,9 +151,9 @@ Qconv(Fmt *fp)
 		else
 			fmtprint(fp, " ");
 		if(var[i].node == N || var[i].node->sym == S)
-			fmtprint(fp, "$%lld", var[i].offset);
+			fmtprint(fp, "$%d", i);
 		else {
-			fmtprint(fp, var[i].node->sym->name);
+			fmtprint(fp, "%s", var[i].node->sym->name);
 			if(var[i].offset != 0)
 				fmtprint(fp, "%+lld", (vlong)var[i].offset);
 		}
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index 190c560..23d3696 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -1,114 +1,123 @@
 char *runtimeimport =
 	"package runtime\n"
 	"import runtime \"runtime\"\n"
-	"func \"\".new (? int32) *any\n"
-	"func \"\".panicindex ()\n"
-	"func \"\".panicslice ()\n"
-	"func \"\".throwreturn ()\n"
-	"func \"\".throwinit ()\n"
-	"func \"\".panicwrap (? string, ? string, ? string)\n"
-	"func \"\".panic (? interface { })\n"
-	"func \"\".recover (? *int32) interface { }\n"
-	"func \"\".printbool (? bool)\n"
-	"func \"\".printfloat (? float64)\n"
-	"func \"\".printint (? int64)\n"
-	"func \"\".printuint (? uint64)\n"
-	"func \"\".printcomplex (? complex128)\n"
-	"func \"\".printstring (? string)\n"
-	"func \"\".printpointer (? any)\n"
-	"func \"\".printiface (? any)\n"
-	"func \"\".printeface (? any)\n"
-	"func \"\".printslice (? any)\n"
-	"func \"\".printnl ()\n"
-	"func \"\".printsp ()\n"
-	"func \"\".goprintf ()\n"
-	"func \"\".concatstring ()\n"
-	"func \"\".append ()\n"
-	"func \"\".appendslice (typ *uint8, x any, y []any) any\n"
-	"func \"\".cmpstring (? string, ? string) int\n"
-	"func \"\".slicestring (? string, ? int, ? int) string\n"
-	"func \"\".slicestring1 (? string, ? int) string\n"
-	"func \"\".intstring (? int64) string\n"
-	"func \"\".slicebytetostring (? []uint8) string\n"
-	"func \"\".sliceinttostring (? []int) string\n"
-	"func \"\".stringtoslicebyte (? string) []uint8\n"
-	"func \"\".stringtosliceint (? string) []int\n"
-	"func \"\".stringiter (? string, ? int) int\n"
-	"func \"\".stringiter2 (? string, ? int) (retk int, retv int)\n"
-	"func \"\".slicecopy (to any, fr any, wid uint32) int\n"
-	"func \"\".slicestringcopy (to any, fr any) int\n"
-	"func \"\".convI2E (elem any) any\n"
-	"func \"\".convI2I (typ *uint8, elem any) any\n"
-	"func \"\".convT2E (typ *uint8, elem any) any\n"
-	"func \"\".convT2I (typ *uint8, typ2 *uint8, elem any) any\n"
-	"func \"\".assertE2E (typ *uint8, iface any) any\n"
-	"func \"\".assertE2E2 (typ *uint8, iface any) (ret any, ok bool)\n"
-	"func \"\".assertE2I (typ *uint8, iface any) any\n"
-	"func \"\".assertE2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
-	"func \"\".assertE2T (typ *uint8, iface any) any\n"
-	"func \"\".assertE2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
-	"func \"\".assertI2E (typ *uint8, iface any) any\n"
-	"func \"\".assertI2E2 (typ *uint8, iface any) (ret any, ok bool)\n"
-	"func \"\".assertI2I (typ *uint8, iface any) any\n"
-	"func \"\".assertI2I2 (typ *uint8, iface any) (ret any, ok bool)\n"
-	"func \"\".assertI2T (typ *uint8, iface any) any\n"
-	"func \"\".assertI2T2 (typ *uint8, iface any) (ret any, ok bool)\n"
-	"func \"\".ifaceeq (i1 any, i2 any) bool\n"
-	"func \"\".efaceeq (i1 any, i2 any) bool\n"
-	"func \"\".ifacethash (i1 any) uint32\n"
-	"func \"\".efacethash (i1 any) uint32\n"
-	"func \"\".makemap (mapType *uint8, hint int64) map[any] any\n"
-	"func \"\".mapaccess1 (mapType *uint8, hmap map[any] any, key any) any\n"
-	"func \"\".mapaccess2 (mapType *uint8, hmap map[any] any, key any) (val any, pres bool)\n"
-	"func \"\".mapassign1 (mapType *uint8, hmap map[any] any, key any, val any)\n"
-	"func \"\".mapassign2 (mapType *uint8, hmap map[any] any, key any, val any, pres bool)\n"
-	"func \"\".mapiterinit (mapType *uint8, hmap map[any] any, hiter *any)\n"
-	"func \"\".mapiternext (hiter *any)\n"
-	"func \"\".mapiter1 (hiter *any) any\n"
-	"func \"\".mapiter2 (hiter *any) (key any, val any)\n"
-	"func \"\".makechan (chanType *uint8, hint int64) chan any\n"
-	"func \"\".chanrecv1 (chanType *uint8, hchan <-chan any) any\n"
-	"func \"\".chanrecv2 (chanType *uint8, hchan <-chan any) (elem any, received bool)\n"
-	"func \"\".chansend1 (chanType *uint8, hchan chan<- any, elem any)\n"
-	"func \"\".closechan (hchan any)\n"
-	"func \"\".selectnbsend (chanType *uint8, hchan chan<- any, elem any) bool\n"
-	"func \"\".selectnbrecv (chanType *uint8, elem *any, hchan <-chan any) bool\n"
-	"func \"\".selectnbrecv2 (chanType *uint8, elem *any, received *bool, hchan <-chan any) bool\n"
-	"func \"\".newselect (size int) *uint8\n"
-	"func \"\".selectsend (sel *uint8, hchan chan<- any, elem *any) bool\n"
-	"func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n"
-	"func \"\".selectrecv2 (sel *uint8, hchan <-chan any, elem *any, received *bool) bool\n"
-	"func \"\".selectdefault (sel *uint8) bool\n"
-	"func \"\".selectgo (sel *uint8)\n"
-	"func \"\".block ()\n"
-	"func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
-	"func \"\".growslice (typ *uint8, old []any, n int64) []any\n"
-	"func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
-	"func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
-	"func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
-	"func \"\".closure ()\n"
-	"func \"\".int64div (? int64, ? int64) int64\n"
-	"func \"\".uint64div (? uint64, ? uint64) uint64\n"
-	"func \"\".int64mod (? int64, ? int64) int64\n"
-	"func \"\".uint64mod (? uint64, ? uint64) uint64\n"
-	"func \"\".float64toint64 (? float64) int64\n"
-	"func \"\".float64touint64 (? float64) uint64\n"
-	"func \"\".int64tofloat64 (? int64) float64\n"
-	"func \"\".uint64tofloat64 (? uint64) float64\n"
-	"func \"\".complex128div (num complex128, den complex128) complex128\n"
+	"func @\"\".new(@\"\".typ *byte) *any\n"
+	"func @\"\".panicindex()\n"
+	"func @\"\".panicslice()\n"
+	"func @\"\".throwreturn()\n"
+	"func @\"\".throwinit()\n"
+	"func @\"\".panicwrap(? string, ? string, ? string)\n"
+	"func @\"\".panic(? interface {})\n"
+	"func @\"\".recover(? *int32) interface {}\n"
+	"func @\"\".printbool(? bool)\n"
+	"func @\"\".printfloat(? float64)\n"
+	"func @\"\".printint(? int64)\n"
+	"func @\"\".printuint(? uint64)\n"
+	"func @\"\".printcomplex(? complex128)\n"
+	"func @\"\".printstring(? string)\n"
+	"func @\"\".printpointer(? any)\n"
+	"func @\"\".printiface(? any)\n"
+	"func @\"\".printeface(? any)\n"
+	"func @\"\".printslice(? any)\n"
+	"func @\"\".printnl()\n"
+	"func @\"\".printsp()\n"
+	"func @\"\".goprintf()\n"
+	"func @\"\".concatstring()\n"
+	"func @\"\".append()\n"
+	"func @\"\".appendslice(@\"\".typ *byte, @\"\".x any, @\"\".y []any) any\n"
+	"func @\"\".appendstr(@\"\".typ *byte, @\"\".x []byte, @\"\".y string) []byte\n"
+	"func @\"\".cmpstring(? string, ? string) int\n"
+	"func @\"\".slicestring(? string, ? int, ? int) string\n"
+	"func @\"\".slicestring1(? string, ? int) string\n"
+	"func @\"\".intstring(? int64) string\n"
+	"func @\"\".slicebytetostring(? []byte) string\n"
+	"func @\"\".slicerunetostring(? []rune) string\n"
+	"func @\"\".stringtoslicebyte(? string) []byte\n"
+	"func @\"\".stringtoslicerune(? string) []rune\n"
+	"func @\"\".stringiter(? string, ? int) int\n"
+	"func @\"\".stringiter2(? string, ? int) (@\"\".retk int, @\"\".retv rune)\n"
+	"func @\"\".copy(@\"\".to any, @\"\".fr any, @\"\".wid uint32) int\n"
+	"func @\"\".slicestringcopy(@\"\".to any, @\"\".fr any) int\n"
+	"func @\"\".convI2E(@\"\".elem any) any\n"
+	"func @\"\".convI2I(@\"\".typ *byte, @\"\".elem any) any\n"
+	"func @\"\".convT2E(@\"\".typ *byte, @\"\".elem any) any\n"
+	"func @\"\".convT2I(@\"\".typ *byte, @\"\".typ2 *byte, @\"\".elem any) any\n"
+	"func @\"\".assertE2E(@\"\".typ *byte, @\"\".iface any) any\n"
+	"func @\"\".assertE2E2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
+	"func @\"\".assertE2I(@\"\".typ *byte, @\"\".iface any) any\n"
+	"func @\"\".assertE2I2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
+	"func @\"\".assertE2T(@\"\".typ *byte, @\"\".iface any) any\n"
+	"func @\"\".assertE2T2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
+	"func @\"\".assertI2E(@\"\".typ *byte, @\"\".iface any) any\n"
+	"func @\"\".assertI2E2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
+	"func @\"\".assertI2I(@\"\".typ *byte, @\"\".iface any) any\n"
+	"func @\"\".assertI2I2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
+	"func @\"\".assertI2T(@\"\".typ *byte, @\"\".iface any) any\n"
+	"func @\"\".assertI2T2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
+	"func @\"\".ifaceeq(@\"\".i1 any, @\"\".i2 any) bool\n"
+	"func @\"\".efaceeq(@\"\".i1 any, @\"\".i2 any) bool\n"
+	"func @\"\".ifacethash(@\"\".i1 any) uint32\n"
+	"func @\"\".efacethash(@\"\".i1 any) uint32\n"
+	"func @\"\".equal(@\"\".typ *byte, @\"\".x1 any, @\"\".x2 any) bool\n"
+	"func @\"\".makemap(@\"\".mapType *byte, @\"\".hint int64) map[any]any\n"
+	"func @\"\".mapaccess1(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any) any\n"
+	"func @\"\".mapaccess2(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any) (@\"\".val any, @\"\".pres bool)\n"
+	"func @\"\".mapassign1(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any, @\"\".val any)\n"
+	"func @\"\".mapassign2(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any, @\"\".val any, @\"\".pres bool)\n"
+	"func @\"\".mapiterinit(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".hiter *any)\n"
+	"func @\"\".mapdelete(@\"\".mapType *byte, @\"\".hmap map[any]any, @\"\".key any)\n"
+	"func @\"\".mapiternext(@\"\".hiter *any)\n"
+	"func @\"\".mapiter1(@\"\".hiter *any) any\n"
+	"func @\"\".mapiter2(@\"\".hiter *any) (@\"\".key any, @\"\".val any)\n"
+	"func @\"\".makechan(@\"\".chanType *byte, @\"\".hint int64) chan any\n"
+	"func @\"\".chanrecv1(@\"\".chanType *byte, @\"\".hchan <-chan any) any\n"
+	"func @\"\".chanrecv2(@\"\".chanType *byte, @\"\".hchan <-chan any) (@\"\".elem any, @\"\".received bool)\n"
+	"func @\"\".chansend1(@\"\".chanType *byte, @\"\".hchan chan<- any, @\"\".elem any)\n"
+	"func @\"\".closechan(@\"\".hchan any)\n"
+	"func @\"\".selectnbsend(@\"\".chanType *byte, @\"\".hchan chan<- any, @\"\".elem any) bool\n"
+	"func @\"\".selectnbrecv(@\"\".chanType *byte, @\"\".elem *any, @\"\".hchan <-chan any) bool\n"
+	"func @\"\".selectnbrecv2(@\"\".chanType *byte, @\"\".elem *any, @\"\".received *bool, @\"\".hchan <-chan any) bool\n"
+	"func @\"\".newselect(@\"\".size int) *byte\n"
+	"func @\"\".selectsend(@\"\".sel *byte, @\"\".hchan chan<- any, @\"\".elem *any) bool\n"
+	"func @\"\".selectrecv(@\"\".sel *byte, @\"\".hchan <-chan any, @\"\".elem *any) bool\n"
+	"func @\"\".selectrecv2(@\"\".sel *byte, @\"\".hchan <-chan any, @\"\".elem *any, @\"\".received *bool) bool\n"
+	"func @\"\".selectdefault(@\"\".sel *byte) bool\n"
+	"func @\"\".selectgo(@\"\".sel *byte)\n"
+	"func @\"\".block()\n"
+	"func @\"\".makeslice(@\"\".typ *byte, @\"\".nel int64, @\"\".cap int64) []any\n"
+	"func @\"\".growslice(@\"\".typ *byte, @\"\".old []any, @\"\".n int64) []any\n"
+	"func @\"\".sliceslice1(@\"\".old []any, @\"\".lb uint64, @\"\".width uint64) []any\n"
+	"func @\"\".sliceslice(@\"\".old []any, @\"\".lb uint64, @\"\".hb uint64, @\"\".width uint64) []any\n"
+	"func @\"\".slicearray(@\"\".old *any, @\"\".nel uint64, @\"\".lb uint64, @\"\".hb uint64, @\"\".width uint64) []any\n"
+	"func @\"\".closure()\n"
+	"func @\"\".memequal(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
+	"func @\"\".memequal8(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
+	"func @\"\".memequal16(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
+	"func @\"\".memequal32(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
+	"func @\"\".memequal64(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
+	"func @\"\".memequal128(@\"\".eq *bool, @\"\".size uintptr, @\"\".x *any, @\"\".y *any)\n"
+	"func @\"\".int64div(? int64, ? int64) int64\n"
+	"func @\"\".uint64div(? uint64, ? uint64) uint64\n"
+	"func @\"\".int64mod(? int64, ? int64) int64\n"
+	"func @\"\".uint64mod(? uint64, ? uint64) uint64\n"
+	"func @\"\".float64toint64(? float64) int64\n"
+	"func @\"\".float64touint64(? float64) uint64\n"
+	"func @\"\".int64tofloat64(? int64) float64\n"
+	"func @\"\".uint64tofloat64(? uint64) float64\n"
+	"func @\"\".complex128div(@\"\".num complex128, @\"\".den complex128) complex128\n"
 	"\n"
 	"$$\n";
 char *unsafeimport =
 	"package unsafe\n"
 	"import runtime \"runtime\"\n"
-	"type \"\".Pointer uintptr\n"
-	"func \"\".Offsetof (? any) uintptr\n"
-	"func \"\".Sizeof (? any) uintptr\n"
-	"func \"\".Alignof (? any) uintptr\n"
-	"func \"\".Typeof (i interface { }) interface { }\n"
-	"func \"\".Reflect (i interface { }) (typ interface { }, addr \"\".Pointer)\n"
-	"func \"\".Unreflect (typ interface { }, addr \"\".Pointer) interface { }\n"
-	"func \"\".New (typ interface { }) \"\".Pointer\n"
-	"func \"\".NewArray (typ interface { }, n int) \"\".Pointer\n"
+	"type @\"\".Pointer uintptr\n"
+	"func @\"\".Offsetof(? any) uintptr\n"
+	"func @\"\".Sizeof(? any) uintptr\n"
+	"func @\"\".Alignof(? any) uintptr\n"
+	"func @\"\".Typeof(@\"\".i interface {}) interface {}\n"
+	"func @\"\".Reflect(@\"\".i interface {}) (@\"\".typ interface {}, @\"\".addr @\"\".Pointer)\n"
+	"func @\"\".Unreflect(@\"\".typ interface {}, @\"\".addr @\"\".Pointer) interface {}\n"
+	"func @\"\".New(@\"\".typ interface {}) @\"\".Pointer\n"
+	"func @\"\".NewArray(@\"\".typ interface {}, @\"\".n int) @\"\".Pointer\n"
 	"\n"
 	"$$\n";
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index d29e8cb..fa44e40 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -192,6 +192,10 @@ walkclosure(Node *func, NodeList **init)
 	Node *xtype, *xfunc, *call, *clos;
 	NodeList *l, *in;
 
+	// no closure vars, don't bother wrapping
+	if(func->cvars == nil)
+		return makeclosure(func, init, 1)->nname;
+
 	/*
 	 * wrap body in external function
 	 * with extra closure parameters.
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 135a810..01c4f15 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -108,7 +108,7 @@ convlit1(Node **np, Type *t, int explicit)
 		if(t != T && t->etype == TIDEAL && n->val.ctype != CTINT)
 			n->val = toint(n->val);
 		if(t != T && !isint[t->etype]) {
-			yyerror("invalid operation: %#N (shift of type %T)", n, t);
+			yyerror("invalid operation: %N (shift of type %T)", n, t);
 			t = T;
 		}
 		n->type = t;
@@ -170,6 +170,7 @@ convlit1(Node **np, Type *t, int explicit)
 		break;
 
 	case CTINT:
+	case CTRUNE:
 	case CTFLT:
 	case CTCPLX:
 		ct = n->val.ctype;
@@ -179,6 +180,7 @@ convlit1(Node **np, Type *t, int explicit)
 				goto bad;
 			case CTCPLX:
 			case CTFLT:
+			case CTRUNE:
 				n->val = toint(n->val);
 				// flowthrough
 			case CTINT:
@@ -192,6 +194,7 @@ convlit1(Node **np, Type *t, int explicit)
 				goto bad;
 			case CTCPLX:
 			case CTINT:
+			case CTRUNE:
 				n->val = toflt(n->val);
 				// flowthrough
 			case CTFLT:
@@ -206,6 +209,7 @@ convlit1(Node **np, Type *t, int explicit)
 				goto bad;
 			case CTFLT:
 			case CTINT:
+			case CTRUNE:
 				n->val = tocplx(n->val);
 				break;
 			case CTCPLX:
@@ -213,7 +217,7 @@ convlit1(Node **np, Type *t, int explicit)
 				break;
 			}
 		} else
-		if(et == TSTRING && ct == CTINT && explicit)
+		if(et == TSTRING && (ct == CTINT || ct == CTRUNE) && explicit)
 			n->val = tostr(n->val);
 		else
 			goto bad;
@@ -224,7 +228,7 @@ convlit1(Node **np, Type *t, int explicit)
 
 bad:
 	if(!n->diag) {
-		yyerror("cannot convert %#N to type %T", n, t);
+		yyerror("cannot convert %N to type %T", n, t);
 		n->diag = 1;
 	}
 	if(isideal(n->type)) {
@@ -243,6 +247,7 @@ copyval(Val v)
 
 	switch(v.ctype) {
 	case CTINT:
+	case CTRUNE:
 		i = mal(sizeof(*i));
 		mpmovefixfix(i, v.u.xval);
 		v.u.xval = i;
@@ -269,6 +274,7 @@ tocplx(Val v)
 
 	switch(v.ctype) {
 	case CTINT:
+	case CTRUNE:
 		c = mal(sizeof(*c));
 		mpmovefixflt(&c->real, v.u.xval);
 		mpmovecflt(&c->imag, 0.0);
@@ -293,6 +299,7 @@ toflt(Val v)
 
 	switch(v.ctype) {
 	case CTINT:
+	case CTRUNE:
 		f = mal(sizeof(*f));
 		mpmovefixflt(f, v.u.xval);
 		v.ctype = CTFLT;
@@ -316,6 +323,9 @@ toint(Val v)
 	Mpint *i;
 
 	switch(v.ctype) {
+	case CTRUNE:
+		v.ctype = CTINT;
+		break;
 	case CTFLT:
 		i = mal(sizeof(*i));
 		if(mpmovefltfix(i, v.u.fval) < 0)
@@ -345,6 +355,7 @@ overflow(Val v, Type *t)
 		return;
 	switch(v.ctype) {
 	case CTINT:
+	case CTRUNE:
 		if(!isint[t->etype])
 			fatal("overflow: %T integer constant", t);
 		if(mpcmpfixfix(v.u.xval, minintval[t->etype]) < 0 ||
@@ -379,6 +390,7 @@ tostr(Val v)
 
 	switch(v.ctype) {
 	case CTINT:
+	case CTRUNE:
 		if(mpcmpfixfix(v.u.xval, minintval[TINT]) < 0 ||
 		   mpcmpfixfix(v.u.xval, maxintval[TINT]) > 0)
 			yyerror("overflow in int -> string");
@@ -415,7 +427,12 @@ consttype(Node *n)
 int
 isconst(Node *n, int ct)
 {
-	return consttype(n) == ct;
+	int t;
+	
+	t = consttype(n);
+	// If the caller is asking for CTINT, allow CTRUNE too.
+	// Makes life easier for back ends.
+	return t == ct || (ct == CTINT && t == CTRUNE);
 }
 
 /*
@@ -424,7 +441,7 @@ isconst(Node *n, int ct)
 void
 evconst(Node *n)
 {
-	Node *nl, *nr;
+	Node *nl, *nr, *norig;
 	int32 len;
 	Strlit *str;
 	int wl, wr, lno, et;
@@ -518,7 +535,8 @@ evconst(Node *n)
 		n->right = nr;
 		if(nr->type && (issigned[nr->type->etype] || !isint[nr->type->etype]))
 			goto illegal;
-		nl->val = toint(nl->val);
+		if(nl->val.ctype != CTRUNE)
+			nl->val = toint(nl->val);
 		nr->val = toint(nr->val);
 		break;
 	}
@@ -540,6 +558,17 @@ evconst(Node *n)
 		v = toflt(v);
 		rv = toflt(rv);
 	}
+
+	// Rune and int turns into rune.
+	if(v.ctype == CTRUNE && rv.ctype == CTINT)
+		rv.ctype = CTRUNE;
+	if(v.ctype == CTINT && rv.ctype == CTRUNE) {
+		if(n->op == OLSH || n->op == ORSH)
+			rv.ctype = CTINT;
+		else
+			v.ctype = CTRUNE;
+	}
+
 	if(v.ctype != rv.ctype) {
 		// Use of undefined name as constant?
 		if((v.ctype == 0 || rv.ctype == 0) && nerrors > 0)
@@ -559,15 +588,19 @@ evconst(Node *n)
 		return;
 
 	case TUP(OADD, CTINT):
+	case TUP(OADD, CTRUNE):
 		mpaddfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(OSUB, CTINT):
+	case TUP(OSUB, CTRUNE):
 		mpsubfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(OMUL, CTINT):
+	case TUP(OMUL, CTRUNE):
 		mpmulfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(ODIV, CTINT):
+	case TUP(ODIV, CTRUNE):
 		if(mpcmpfixc(rv.u.xval, 0) == 0) {
 			yyerror("division by zero");
 			mpmovecfix(v.u.xval, 1);
@@ -576,6 +609,7 @@ evconst(Node *n)
 		mpdivfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(OMOD, CTINT):
+	case TUP(OMOD, CTRUNE):
 		if(mpcmpfixc(rv.u.xval, 0) == 0) {
 			yyerror("division by zero");
 			mpmovecfix(v.u.xval, 1);
@@ -585,21 +619,27 @@ evconst(Node *n)
 		break;
 
 	case TUP(OLSH, CTINT):
+	case TUP(OLSH, CTRUNE):
 		mplshfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(ORSH, CTINT):
+	case TUP(ORSH, CTRUNE):
 		mprshfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(OOR, CTINT):
+	case TUP(OOR, CTRUNE):
 		mporfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(OAND, CTINT):
+	case TUP(OAND, CTRUNE):
 		mpandfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(OANDNOT, CTINT):
+	case TUP(OANDNOT, CTRUNE):
 		mpandnotfixfix(v.u.xval, rv.u.xval);
 		break;
 	case TUP(OXOR, CTINT):
+	case TUP(OXOR, CTRUNE):
 		mpxorfixfix(v.u.xval, rv.u.xval);
 		break;
 
@@ -649,26 +689,32 @@ evconst(Node *n)
 		goto setfalse;
 
 	case TUP(OEQ, CTINT):
+	case TUP(OEQ, CTRUNE):
 		if(mpcmpfixfix(v.u.xval, rv.u.xval) == 0)
 			goto settrue;
 		goto setfalse;
 	case TUP(ONE, CTINT):
+	case TUP(ONE, CTRUNE):
 		if(mpcmpfixfix(v.u.xval, rv.u.xval) != 0)
 			goto settrue;
 		goto setfalse;
 	case TUP(OLT, CTINT):
+	case TUP(OLT, CTRUNE):
 		if(mpcmpfixfix(v.u.xval, rv.u.xval) < 0)
 			goto settrue;
 		goto setfalse;
 	case TUP(OLE, CTINT):
+	case TUP(OLE, CTRUNE):
 		if(mpcmpfixfix(v.u.xval, rv.u.xval) <= 0)
 			goto settrue;
 		goto setfalse;
 	case TUP(OGE, CTINT):
+	case TUP(OGE, CTRUNE):
 		if(mpcmpfixfix(v.u.xval, rv.u.xval) >= 0)
 			goto settrue;
 		goto setfalse;
 	case TUP(OGT, CTINT):
+	case TUP(OGT, CTRUNE):
 		if(mpcmpfixfix(v.u.xval, rv.u.xval) > 0)
 			goto settrue;
 		goto setfalse;
@@ -786,17 +832,21 @@ unary:
 		}
 		// fall through
 	case TUP(OCONV, CTINT):
+	case TUP(OCONV, CTRUNE):
 	case TUP(OCONV, CTFLT):
 	case TUP(OCONV, CTSTR):
 		convlit1(&nl, n->type, 1);
 		break;
 
 	case TUP(OPLUS, CTINT):
+	case TUP(OPLUS, CTRUNE):
 		break;
 	case TUP(OMINUS, CTINT):
+	case TUP(OMINUS, CTRUNE):
 		mpnegfix(v.u.xval);
 		break;
 	case TUP(OCOM, CTINT):
+	case TUP(OCOM, CTRUNE):
 		et = Txxx;
 		if(nl->type != T)
 			et = nl->type->etype;
@@ -842,8 +892,15 @@ unary:
 	}
 
 ret:
-	// rewrite n in place.
+	if(n == n->orig) {
+		// duplicate node for n->orig.
+		norig = nod(OLITERAL, N, N);
+		*norig = *n;
+	} else
+		norig = n->orig;
 	*n = *nl;
+	// restore value of n->orig.
+	n->orig = norig;
 	n->val = v;
 
 	// check range.
@@ -882,6 +939,7 @@ nodlit(Val v)
 		n->type = idealbool;
 		break;
 	case CTINT:
+	case CTRUNE:
 	case CTFLT:
 	case CTCPLX:
 		n->type = types[TIDEAL];
@@ -939,7 +997,7 @@ defaultlit(Node **np, Type *t)
 		defaultlit(&n->left, t);
 		t = n->left->type;
 		if(t != T && !isint[t->etype]) {
-			yyerror("invalid operation: %#N (shift of type %T)", n, t);
+			yyerror("invalid operation: %N (shift of type %T)", n, t);
 			t = T;
 		}
 		n->type = t;
@@ -991,7 +1049,7 @@ defaultlit(Node **np, Type *t)
 			n->type = types[TSTRING];
 			break;
 		}
-		yyerror("defaultlit: unknown literal: %#N", n);
+		yyerror("defaultlit: unknown literal: %N", n);
 		break;
 	case CTBOOL:
 		n->type = types[TBOOL];
@@ -1001,6 +1059,9 @@ defaultlit(Node **np, Type *t)
 	case CTINT:
 		n->type = types[TINT];
 		goto num;
+	case CTRUNE:
+		n->type = runetype;
+		goto num;
 	case CTFLT:
 		n->type = types[TFLOAT64];
 		goto num;
@@ -1065,6 +1126,13 @@ defaultlit2(Node **lp, Node **rp, int force)
 		convlit(rp, types[TFLOAT64]);
 		return;
 	}
+
+	if(isconst(l, CTRUNE) || isconst(r, CTRUNE)) {
+		convlit(lp, runetype);
+		convlit(rp, runetype);
+		return;
+	}
+
 	convlit(lp, types[TINT]);
 	convlit(rp, types[TINT]);
 }
@@ -1101,7 +1169,7 @@ cmpslit(Node *l, Node *r)
 int
 smallintconst(Node *n)
 {
-	if(n->op == OLITERAL && n->val.ctype == CTINT && n->type != T)
+	if(n->op == OLITERAL && isconst(n, CTINT) && n->type != T)
 	switch(simtype[n->type->etype]) {
 	case TINT8:
 	case TUINT8:
@@ -1203,6 +1271,7 @@ convconst(Node *con, Type *t, Val *val)
 		default:
 			fatal("convconst ctype=%d %lT", val->ctype, t);
 		case CTINT:
+		case CTRUNE:
 			i = mpgetfix(val->u.xval);
 			break;
 		case CTBOOL:
diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c
index 52038e7..dea7bc3 100644
--- a/src/cmd/gc/cplx.c
+++ b/src/cmd/gc/cplx.c
@@ -204,6 +204,8 @@ complexgen(Node *n, Node *res)
 	case OIND:
 	case ONAME:	// PHEAP or PPARAMREF var
 	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
 		igen(n, &n1, res);
 		complexmove(&n1, res);
 		regfree(&n1);
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index d8b89b4..66edab9 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -8,6 +8,7 @@
 #include	"y.tab.h"
 
 static	void	funcargs(Node*);
+static	void	funcargs2(Type*);
 
 static int
 dflag(void)
@@ -174,6 +175,11 @@ declare(Node *n, int ctxt)
 
 	n->lineno = parserline();
 	s = n->sym;
+
+	// kludgy: typecheckok means we're past parsing.  Eg genwrapper may declare out of package names later.
+	if(importpkg == nil && !typecheckok && s->pkg != localpkg)
+		yyerror("cannot declare name %S", s);
+
 	gen = 0;
 	if(ctxt == PEXTERN) {
 		externdcl = list(externdcl, n);
@@ -415,6 +421,7 @@ oldname(Sym *s)
 			c->funcdepth = funcdepth;
 			c->outer = n->closure;
 			n->closure = c;
+			n->addrtaken = 1;
 			c->closure = n;
 			c->xoffset = 0;
 			curfn->cvars = list(curfn->cvars, c);
@@ -472,7 +479,7 @@ colasdefn(NodeList *left, Node *defn)
 		if(isblank(n))
 			continue;
 		if(!colasname(n)) {
-			yyerror("non-name %#N on left side of :=", n);
+			yyerror("non-name %N on left side of :=", n);
 			nerr++;
 			continue;
 		}
@@ -546,13 +553,6 @@ ifacedcl(Node *n)
 void
 funchdr(Node *n)
 {
-
-	if(n->nname != N) {
-		n->nname->op = ONAME;
-		declare(n->nname, PFUNC);
-		n->nname->defn = n;
-	}
-
 	// change the declaration context from extern to auto
 	if(funcdepth == 0 && dclcontext != PEXTERN)
 		fatal("funchdr: dclcontext");
@@ -563,16 +563,19 @@ funchdr(Node *n)
 
 	n->outer = curfn;
 	curfn = n;
+
 	if(n->nname)
 		funcargs(n->nname->ntype);
-	else
+	else if (n->ntype)
 		funcargs(n->ntype);
+	else
+		funcargs2(n->type);
 }
 
 static void
 funcargs(Node *nt)
 {
-	Node *n;
+	Node *n, *nn;
 	NodeList *l;
 	int gen;
 
@@ -581,11 +584,11 @@ funcargs(Node *nt)
 
 	// declare the receiver and in arguments.
 	// no n->defn because type checking of func header
-	// will fill in the types before we can demand them.
+	// will not fill in the types until later
 	if(nt->left != N) {
 		n = nt->left;
 		if(n->op != ODCLFIELD)
-			fatal("funcargs1 %O", n->op);
+			fatal("funcargs receiver %O", n->op);
 		if(n->left != N) {
 			n->left->op = ONAME;
 			n->left->ntype = n->right;
@@ -595,7 +598,7 @@ funcargs(Node *nt)
 	for(l=nt->list; l; l=l->next) {
 		n = l->n;
 		if(n->op != ODCLFIELD)
-			fatal("funcargs2 %O", n->op);
+			fatal("funcargs in %O", n->op);
 		if(n->left != N) {
 			n->left->op = ONAME;
 			n->left->ntype = n->right;
@@ -608,12 +611,16 @@ funcargs(Node *nt)
 	for(l=nt->rlist; l; l=l->next) {
 		n = l->n;
 		if(n->op != ODCLFIELD)
-			fatal("funcargs3 %O", n->op);
+			fatal("funcargs out %O", n->op);
 		if(n->left != N) {
 			n->left->op = ONAME;
 			n->left->ntype = n->right;
 			if(isblank(n->left)) {
 				// Give it a name so we can assign to it during return.
+				// preserve the original in ->orig
+				nn = nod(OXXX, N, N);
+				*nn = *n->left;
+				n->left = nn;
 				snprint(namebuf, sizeof(namebuf), ".anon%d", gen++);
 				n->left->sym = lookup(namebuf);
 			}
@@ -623,6 +630,48 @@ funcargs(Node *nt)
 }
 
 /*
+ * Same as funcargs, except run over an already constructed TFUNC.
+ * This happens during import, where the hidden_fndcl rule has
+ * used functype directly to parse the function's type.
+ */
+static void
+funcargs2(Type *t)
+{
+	Type *ft;
+	Node *n;
+
+	if(t->etype != TFUNC)
+		fatal("funcargs2 %T", t);
+	
+	if(t->thistuple)
+		for(ft=getthisx(t)->type; ft; ft=ft->down) {
+			if(!ft->nname || !ft->nname->sym)
+				continue;
+			n = ft->nname;  // no need for newname(ft->nname->sym)
+			n->type = ft->type;
+			declare(n, PPARAM);
+		}
+
+	if(t->intuple)
+		for(ft=getinargx(t)->type; ft; ft=ft->down) {
+			if(!ft->nname || !ft->nname->sym)
+				continue;
+			n = ft->nname;
+			n->type = ft->type;
+			declare(n, PPARAM);
+		}
+
+	if(t->outtuple)
+		for(ft=getoutargx(t)->type; ft; ft=ft->down) {
+			if(!ft->nname || !ft->nname->sym)
+				continue;
+			n = ft->nname;
+			n->type = ft->type;
+			declare(n, PPARAMOUT);
+		}
+}
+
+/*
  * finish the body.
  * called in auto-declaration context.
  * returns in extern-declaration context.
@@ -649,7 +698,7 @@ typedcl0(Sym *s)
 {
 	Node *n;
 
-	n = dclname(s);
+	n = newname(s);
 	n->op = OTYPE;
 	declare(n, dclcontext);
 	return n;
@@ -669,220 +718,265 @@ typedcl1(Node *n, Node *t, int local)
 }
 
 /*
- * typedcl1 but during imports
+ * structs, functions, and methods.
+ * they don't belong here, but where do they belong?
  */
-void
-typedcl2(Type *pt, Type *t)
+
+static void
+checkembeddedtype(Type *t)
 {
-	Node *n;
+	if (t == T)
+		return;
 
-	// override declaration in unsafe.go for Pointer.
-	// there is no way in Go code to define unsafe.Pointer
-	// so we have to supply it.
-	if(incannedimport &&
-	   strcmp(importpkg->name, "unsafe") == 0 &&
-	   strcmp(pt->nod->sym->name, "Pointer") == 0) {
-		t = types[TUNSAFEPTR];
+	if(t->sym == S && isptr[t->etype]) {
+		t = t->type;
+		if(t->etype == TINTER)
+			yyerror("embedded type cannot be a pointer to interface");
 	}
+	if(isptr[t->etype])
+		yyerror("embedded type cannot be a pointer");
+	else if(t->etype == TFORW && t->embedlineno == 0)
+		t->embedlineno = lineno;
+}
 
-	if(pt->etype == TFORW)
-		goto ok;
-	if(!eqtype(pt->orig, t))
-		yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t);
-	return;
+static Type*
+structfield(Node *n)
+{
+	Type *f;
+	int lno;
+
+	lno = lineno;
+	lineno = n->lineno;
+
+	if(n->op != ODCLFIELD)
+		fatal("structfield: oops %N\n", n);
 
-ok:
-	n = pt->nod;
-	copytype(pt->nod, t);
-	// unzero nod
-	pt->nod = n;
+	f = typ(TFIELD);
+	f->isddd = n->isddd;
 
-	pt->sym->lastlineno = parserline();
-	declare(n, PEXTERN);
+	if(n->right != N) {
+		typecheck(&n->right, Etype);
+		n->type = n->right->type;
+		if(n->left != N)
+			n->left->type = n->type;
+		if(n->embedded)
+			checkembeddedtype(n->type);
+	}
+	n->right = N;
+		
+	f->type = n->type;
+	if(f->type == T)
+		f->broke = 1;
+
+	switch(n->val.ctype) {
+	case CTSTR:
+		f->note = n->val.u.sval;
+		break;
+	default:
+		yyerror("field annotation must be string");
+		// fallthrough
+	case CTxxx:
+		f->note = nil;
+		break;
+	}
 
-	checkwidth(pt);
+	if(n->left && n->left->op == ONAME) {
+		f->nname = n->left;
+		f->embedded = n->embedded;
+		f->sym = f->nname->sym;
+	}
+
+	lineno = lno;
+	return f;
 }
 
-/*
- * structs, functions, and methods.
- * they don't belong here, but where do they belong?
- */
+static void
+checkdupfields(Type *t, char* what)
+{
+	Type* t1;
+	int lno;
 
+	lno = lineno;
+
+	for( ; t; t=t->down)
+		if(t->sym && t->nname && !isblank(t->nname))
+			for(t1=t->down; t1; t1=t1->down)
+				if(t1->sym == t->sym) {
+					lineno = t->nname->lineno;
+					yyerror("duplicate %s %s", what, t->sym->name);
+					break;
+				}
+
+	lineno = lno;
+}
 
 /*
- * turn a parsed struct into a type
+ * convert a parsed id/type list into
+ * a type for struct/interface/arglist
  */
-static Type**
-stotype(NodeList *l, int et, Type **t, int funarg)
+Type*
+tostruct(NodeList *l)
+{
+	Type *t, *f, **tp;
+	t = typ(TSTRUCT);
+
+	for(tp = &t->type; l; l=l->next) {
+		f = structfield(l->n);
+
+		*tp = f;
+		tp = &f->down;
+	}
+
+	for(f=t->type; f && !t->broke; f=f->down)
+		if(f->broke)
+			t->broke = 1;
+
+	checkdupfields(t->type, "field");
+
+	if (!t->broke)
+		checkwidth(t);
+
+	return t;
+}
+
+static Type*
+tofunargs(NodeList *l)
+{
+	Type *t, *f, **tp;
+
+	t = typ(TSTRUCT);
+	t->funarg = 1;
+
+	for(tp = &t->type; l; l=l->next) {
+		f = structfield(l->n);
+		f->funarg = 1;
+
+		// esc.c needs to find f given a PPARAM to add the tag.
+		if(l->n->left && l->n->left->class == PPARAM)
+			l->n->left->paramfld = f;
+
+		*tp = f;
+		tp = &f->down;
+	}
+
+	for(f=t->type; f && !t->broke; f=f->down)
+		if(f->broke)
+			t->broke = 1;
+
+	checkdupfields(t->type, "argument");
+	return t;
+}
+
+static Type*
+interfacefield(Node *n)
 {
-	Type *f, *t1, *t2, **t0;
-	Strlit *note;
+	Type *f;
 	int lno;
-	Node *n, *left;
-	char *what;
 
-	t0 = t;
 	lno = lineno;
-	what = "field";
-	if(et == TINTER)
-		what = "method";
+	lineno = n->lineno;
 
-	for(; l; l=l->next) {
-		n = l->n;
-		lineno = n->lineno;
+	if(n->op != ODCLFIELD)
+		fatal("interfacefield: oops %N\n", n);
 
-		if(n->op != ODCLFIELD)
-			fatal("stotype: oops %N\n", n);
-		left = n->left;
-		if(funarg && isblank(left))
-			left = N;
-		if(n->right != N) {
-			if(et == TINTER && left != N) {
-				// queue resolution of method type for later.
-				// right now all we need is the name list.
-				// avoids cycles for recursive interface types.
-				n->type = typ(TINTERMETH);
-				n->type->nname = n->right;
-				n->right = N;
-				left->type = n->type;
-				queuemethod(n);
-			} else {
-				typecheck(&n->right, Etype);
-				n->type = n->right->type;
-				if(n->type == T)
-					continue;
-				if(left != N)
-					left->type = n->type;
-				n->right = N;
-				if(n->embedded && n->type != T) {
-					t1 = n->type;
-					if(t1->sym == S && isptr[t1->etype]) {
-						t1 = t1->type;
-						if(t1->etype == TINTER)
-							yyerror("embedded type cannot be a pointer to interface");
-					}
-					if(isptr[t1->etype])
-						yyerror("embedded type cannot be a pointer");
-					else if(t1->etype == TFORW && t1->embedlineno == 0)
-						t1->embedlineno = lineno;
-				}
+	if (n->val.ctype != CTxxx)
+		yyerror("interface method cannot have annotation");
+
+	f = typ(TFIELD);
+	f->isddd = n->isddd;
+	
+	if(n->right != N) {
+		if(n->left != N) {
+			// queue resolution of method type for later.
+			// right now all we need is the name list.
+			// avoids cycles for recursive interface types.
+			n->type = typ(TINTERMETH);
+			n->type->nname = n->right;
+			n->left->type = n->type;
+			queuemethod(n);
+
+			if(n->left->op == ONAME) {
+				f->nname = n->left;
+				f->embedded = n->embedded;
+				f->sym = f->nname->sym;
+				if(importpkg && !exportname(f->sym->name))
+					f->sym = pkglookup(f->sym->name, structpkg);
 			}
-		}
 
-		if(n->type == T) {
-			// assume error already printed
-			continue;
-		}
+		} else {
 
-		switch(n->val.ctype) {
-		case CTSTR:
-			if(et != TSTRUCT)
-				yyerror("interface method cannot have annotation");
-			note = n->val.u.sval;
-			break;
-		default:
-			if(et != TSTRUCT)
-				yyerror("interface method cannot have annotation");
-			else
-				yyerror("field annotation must be string");
-		case CTxxx:
-			note = nil;
-			break;
-		}
+			typecheck(&n->right, Etype);
+			n->type = n->right->type;
 
-		if(et == TINTER && left == N) {
-			// embedded interface - inline the methods
-			if(n->type->etype != TINTER) {
-				if(n->type->etype == TFORW)
+			if(n->embedded)
+				checkembeddedtype(n->type);
+
+			if(n->type)
+				switch(n->type->etype) {
+				case TINTER:
+					break;
+				case TFORW:
 					yyerror("interface type loop involving %T", n->type);
-				else
+					f->broke = 1;
+					break;
+				default:
 					yyerror("interface contains embedded non-interface %T", n->type);
-				continue;
-			}
-			for(t1=n->type->type; t1!=T; t1=t1->down) {
-				f = typ(TFIELD);
-				f->type = t1->type;
-				f->width = BADWIDTH;
-				f->nname = newname(t1->sym);
-				f->sym = t1->sym;
-				for(t2=*t0; t2!=T; t2=t2->down) {
-					if(t2->sym == f->sym) {
-						yyerror("duplicate method %s", t2->sym->name);
-						break;
-					}
-				}
-				*t = f;
-				t = &f->down;
-			}
-			continue;
-		}
-
-		f = typ(TFIELD);
-		f->type = n->type;
-		f->note = note;
-		f->width = BADWIDTH;
-		f->isddd = n->isddd;
-
-		// esc.c needs to find f given a PPARAM to add the tag.
-		if(funarg && n->left && n->left->class == PPARAM)
-			n->left->paramfld = f;
-
-		if(left != N && left->op == ONAME) {
-			f->nname = left;
-			f->embedded = n->embedded;
-			f->sym = f->nname->sym;
-			if(importpkg && !exportname(f->sym->name))
-				f->sym = pkglookup(f->sym->name, structpkg);
-			if(f->sym && !isblank(f->nname)) {
-				for(t1=*t0; t1!=T; t1=t1->down) {
-					if(t1->sym == f->sym) {
-						yyerror("duplicate %s %s", what, t1->sym->name);
-						break;
-					}
+					f->broke = 1;
+					break;
 				}
-			}
 		}
-
-		*t = f;
-		t = &f->down;
 	}
 
-	*t = T;
+	n->right = N;
+	
+	f->type = n->type;
+	if(f->type == T)
+		f->broke = 1;
+	
 	lineno = lno;
-	return t;
+	return f;
 }
 
 Type*
-dostruct(NodeList *l, int et)
+tointerface(NodeList *l)
 {
-	Type *t;
-	int funarg;
+	Type *t, *f, **tp, *t1;
 
-	/*
-	 * convert a parsed id/type list into
-	 * a type for struct/interface/arglist
-	 */
+	t = typ(TINTER);
 
-	funarg = 0;
-	if(et == TFUNC) {
-		funarg = 1;
-		et = TSTRUCT;
-	}
-	t = typ(et);
-	t->funarg = funarg;
-	stotype(l, et, &t->type, funarg);
-	if(t->type == T && l != nil) {
-		t->broke = 1;
-		return t;
+	tp = &t->type;
+	for(; l; l=l->next) {
+		f = interfacefield(l->n);
+
+		if (l->n->left == N && f->type->etype == TINTER) {
+			// embedded interface, inline methods
+			for(t1=f->type->type; t1; t1=t1->down) {
+				f = typ(TFIELD);
+				f->type = t1->type;
+				f->broke = t1->broke;
+				f->sym = t1->sym;
+				if(f->sym)
+					f->nname = newname(f->sym);
+				*tp = f;
+				tp = &f->down;
+			}
+		} else {
+			*tp = f;
+			tp = &f->down;
+		}
 	}
-	if(et == TINTER)
-		t = sortinter(t);
-	if(!funarg)
-		checkwidth(t);
+
+	for(f=t->type; f && !t->broke; f=f->down)
+		if(f->broke)
+			t->broke = 1;
+
+	checkdupfields(t->type, "method");
+	t = sortinter(t);
+	checkwidth(t);
+
 	return t;
 }
 
-
 Node*
 embedded(Sym *s)
 {
@@ -899,7 +993,10 @@ embedded(Sym *s)
 		*utfrune(name, CenterDot) = 0;
 	}
 
-	n = newname(lookup(name));
+	if(exportname(name) || s->pkg == builtinpkg)  // old behaviour, tests pass, but is it correct?
+		n = newname(lookup(name));
+	else
+		n = newname(pkglookup(name, s->pkg));
 	n = nod(ODCLFIELD, n, oldname(s));
 	n->embedded = 1;
 	return n;
@@ -964,6 +1061,17 @@ checkarglist(NodeList *all, int input)
 			t = n;
 			n = N;
 		}
+
+		// during import l->n->op is OKEY, but l->n->left->sym == S
+		// means it was a '?', not that it was
+		// a lone type This doesn't matter for the exported
+		// declarations, which are parsed by rules that don't
+		// use checkargs, but can happen for func literals in
+		// the inline bodies.
+		// TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.c prints _ instead of ?
+		if(importpkg && n->sym == S)
+			n = N;
+
 		if(n != N && n->sym == S) {
 			t = n;
 			n = N;
@@ -1037,9 +1145,12 @@ functype(Node *this, NodeList *in, NodeList *out)
 	rcvr = nil;
 	if(this)
 		rcvr = list1(this);
-	t->type = dostruct(rcvr, TFUNC);
-	t->type->down = dostruct(out, TFUNC);
-	t->type->down->down = dostruct(in, TFUNC);
+	t->type = tofunargs(rcvr);
+	t->type->down = tofunargs(out);
+	t->type->down->down = tofunargs(in);
+
+	if (t->type->broke || t->type->down->broke || t->type->down->down->broke)
+		t->broke = 1;
 
 	if(this)
 		t->thistuple = 1;
@@ -1085,9 +1196,9 @@ methodsym(Sym *nsym, Type *t0, int iface)
 			suffix = "·i";
 	}
 	if(t0->sym == S && isptr[t0->etype])
-		p = smprint("(%#hT).%s%s", t0, nsym->name, suffix);
+		p = smprint("(%-hT).%s%s", t0, nsym->name, suffix);
 	else
-		p = smprint("%#hT.%s%s", t0, nsym->name, suffix);
+		p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
 	s = pkglookup(p, s->pkg);
 	free(p);
 	return s;
@@ -1121,11 +1232,16 @@ methodname1(Node *n, Node *t)
 	}
 	if(t->sym == S || isblank(n))
 		return newname(n->sym);
+
 	if(star)
 		p = smprint("(%s%S).%S", star, t->sym, n->sym);
 	else
 		p = smprint("%S.%S", t->sym, n->sym);
-	n = newname(pkglookup(p, t->sym->pkg));
+
+	if(exportname(t->sym->name))
+		n = newname(lookup(p));
+	else
+		n = newname(pkglookup(p, t->sym->pkg));
 	free(p);
 	return n;
 }
@@ -1164,6 +1280,8 @@ addmethod(Sym *sf, Type *t, int local)
 				t = t->type;
 			}
 		}
+		if(t->broke) // rely on typecheck having complained before
+			return;
 		if(t != T) {
 			if(t->sym == S) {
 				yyerror("invalid receiver type %T (%T is an unnamed type)", pa, t);
@@ -1185,8 +1303,6 @@ addmethod(Sym *sf, Type *t, int local)
 	}
 
 	pa = f;
-	if(importpkg && !exportname(sf->name))
-		sf = pkglookup(sf->name, importpkg);
 
 	n = nod(ODCLFIELD, newname(sf), N);
 	n->type = t;
@@ -1209,10 +1325,16 @@ addmethod(Sym *sf, Type *t, int local)
 		return;
 	}
 
+	f = structfield(n);
+
+	// during import unexported method names should be in the type's package
+	if(importpkg && f->sym && !exportname(f->sym->name) && f->sym->pkg != structpkg)
+		fatal("imported method name %+S in wrong package %s\n", f->sym, structpkg->name);
+
 	if(d == T)
-		stotype(list1(n), 0, &pa->method, 0);
+		pa->method = f;
 	else
-		stotype(list1(n), 0, &d->down, 0);
+		d->down = f;
 	return;
 }
 
@@ -1254,6 +1376,3 @@ funccompile(Node *n, int isclosure)
 	funcdepth = 0;
 	dclcontext = PEXTERN;
 }
-
-
-
diff --git a/src/cmd/gc/doc.go b/src/cmd/gc/doc.go
index 5bb5e0e..c704011 100644
--- a/src/cmd/gc/doc.go
+++ b/src/cmd/gc/doc.go
@@ -42,6 +42,8 @@ Flags:
 		show entire file path when printing line numbers in errors
 	-I dir1 -I dir2
 		add dir1 and dir2 to the list of paths to check for imported packages
+	-N
+		disable optimizations
 	-S
 		write assembly language text to standard output
 	-u
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index cd1f977..7e20457 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -35,6 +35,8 @@
 static void escfunc(Node *func);
 static void esclist(NodeList *l);
 static void esc(Node *n);
+static void escloopdepthlist(NodeList *l);
+static void escloopdepth(Node *n);
 static void escassign(Node *dst, Node *src);
 static void esccall(Node*);
 static void escflows(Node *dst, Node *src);
@@ -62,6 +64,7 @@ escapes(void)
 	NodeList *l;
 
 	theSink.op = ONAME;
+	theSink.orig = &theSink;
 	theSink.class = PEXTERN;
 	theSink.sym = lookup(".sink");
 	theSink.escloopdepth = -1;
@@ -88,7 +91,7 @@ escapes(void)
 	if(debug['m']) {
 		for(l=noesc; l; l=l->next)
 			if(l->n->esc == EscNone)
-				warnl(l->n->lineno, "%S %#N does not escape",
+				warnl(l->n->lineno, "%S %hN does not escape",
 					(l->n->curfn && l->n->curfn->nname) ? l->n->curfn->nname->sym : S,
 					l->n);
 	}
@@ -138,11 +141,64 @@ escfunc(Node *func)
 		escassign(curfn, n);
 	}
 
+	escloopdepthlist(curfn->nbody);
 	esclist(curfn->nbody);
 	curfn = savefn;
 	loopdepth = saveld;
 }
 
+// Mark labels that have no backjumps to them as not increasing loopdepth.
+// Walk hasn't generated (goto|label)->left->sym->label yet, so we'll cheat
+// and set it to one of the following two.  Then in esc we'll clear it again.
+static Label looping;
+static Label nonlooping;
+
+static void
+escloopdepthlist(NodeList *l)
+{
+	for(; l; l=l->next)
+		escloopdepth(l->n);
+}
+
+static void
+escloopdepth(Node *n)
+{
+	if(n == N)
+		return;
+
+	escloopdepthlist(n->ninit);
+
+	switch(n->op) {
+	case OLABEL:
+		if(!n->left || !n->left->sym)
+			fatal("esc:label without label: %+N", n);
+		// Walk will complain about this label being already defined, but that's not until
+		// after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
+		// if(n->left->sym->label != nil)
+		//	fatal("escape analysis messed up analyzing label: %+N", n);
+		n->left->sym->label = &nonlooping;
+		break;
+	case OGOTO:
+		if(!n->left || !n->left->sym)
+			fatal("esc:goto without label: %+N", n);
+		// If we come past one that's uninitialized, this must be a (harmless) forward jump
+		// but if it's set to nonlooping the label must have preceded this goto.
+		if(n->left->sym->label == &nonlooping)
+			n->left->sym->label = &looping;
+		break;
+	}
+
+	escloopdepth(n->left);
+	escloopdepth(n->right);
+	escloopdepthlist(n->list);
+	escloopdepth(n->ntest);
+	escloopdepth(n->nincr);
+	escloopdepthlist(n->nbody);
+	escloopdepthlist(n->nelse);
+	escloopdepthlist(n->rlist);
+
+}
+
 static void
 esclist(NodeList *l)
 {
@@ -178,7 +234,7 @@ esc(Node *n)
 		loopdepth--;
 
 	if(debug['m'] > 1)
-		print("%L:[%d] %#S esc: %#N\n", lineno, loopdepth,
+		print("%L:[%d] %S esc: %N\n", lineno, loopdepth,
 		      (curfn && curfn->nname) ? curfn->nname->sym : S, n);
 
 	switch(n->op) {
@@ -188,9 +244,20 @@ esc(Node *n)
 			n->left->escloopdepth = loopdepth;
 		break;
 
-	case OLABEL:  // TODO: new loop/scope only if there are backjumps to it.
-		loopdepth++;
-		break;
+	case OLABEL:
+		if(n->left->sym->label == &nonlooping) {
+			if(debug['m'] > 1)
+				print("%L:%N non-looping label\n", lineno, n);
+		} else if(n->left->sym->label == &looping) {
+			if(debug['m'] > 1)
+				print("%L: %N looping label\n", lineno, n);
+			loopdepth++;
+		}
+		// See case OLABEL in escloopdepth above
+		// else if(n->left->sym->label == nil)
+		//	fatal("escape anaylysis missed or messed up a label: %+N", n);
+
+		n->left->sym->label = nil;
 
 	case ORANGE:
 		// Everything but fixed array is a dereference.
@@ -222,7 +289,6 @@ esc(Node *n)
 	case OAS2RECV:		// v, ok = <-ch
 	case OAS2MAPR:		// v, ok = m[k]
 	case OAS2DOTTYPE:	// v, ok = x.(type)
-	case OAS2MAPW:		// m[k] = x, ok
 		escassign(n->list->n, n->rlist->n);
 		break;
 
@@ -239,6 +305,7 @@ esc(Node *n)
 	case OPROC:
 		// go f(x) - f and x escape
 		escassign(&theSink, n->left->left);
+		escassign(&theSink, n->left->right);  // ODDDARG for call
 		for(ll=n->left->list; ll; ll=ll->next)
 			escassign(&theSink, ll->n);
 		break;
@@ -291,6 +358,14 @@ esc(Node *n)
 		for(ll=n->list; ll; ll=ll->next)
 			escassign(n, ll->n->right);
 		break;
+	
+	case OPTRLIT:
+		n->esc = EscNone;  // until proven otherwise
+		noesc = list(noesc, n);
+		n->escloopdepth = loopdepth;
+		// Contents make it to memory, lose track.
+		escassign(&theSink, n->left);
+		break;
 
 	case OMAPLIT:
 		n->esc = EscNone;  // until proven otherwise
@@ -331,7 +406,7 @@ escassign(Node *dst, Node *src)
 		return;
 
 	if(debug['m'] > 1)
-		print("%L:[%d] %#S escassign: %hN = %hN\n", lineno, loopdepth,
+		print("%L:[%d] %S escassign: %hN = %hN\n", lineno, loopdepth,
 		      (curfn && curfn->nname) ? curfn->nname->sym : S, dst, src);
 
 	setlineno(dst);
@@ -387,6 +462,7 @@ escassign(Node *dst, Node *src)
 	case ONAME:
 	case OPARAM:
 	case ODDDARG:
+	case OPTRLIT:
 	case OARRAYLIT:
 	case OMAPLIT:
 	case OSTRUCTLIT:
@@ -394,10 +470,14 @@ escassign(Node *dst, Node *src)
 		escflows(dst, src);
 		break;
 
+	case ODOT:
+		// A non-pointer escaping from a struct does not concern us.
+		if(src->type && !haspointers(src->type))
+			break;
+		// fallthrough
 	case OCONV:
 	case OCONVIFACE:
 	case OCONVNOP:
-	case ODOT:
 	case ODOTMETH:	// treat recv.meth as a value with recv in it, only happens in ODEFER and OPROC
 			// iface.method already leaks iface in esccall, no need to put in extra ODOTINTER edge here
 	case ODOTTYPE:
@@ -609,7 +689,7 @@ escflood(Node *dst)
 	}
 
 	if(debug['m']>1)
-		print("\nescflood:%d: dst %hN scope:%#S[%d]\n", walkgen, dst,
+		print("\nescflood:%d: dst %hN scope:%S[%d]\n", walkgen, dst,
 		      (dst->curfn && dst->curfn->nname) ? dst->curfn->nname->sym : S,
 		      dst->escloopdepth);
 
@@ -630,7 +710,7 @@ escwalk(int level, Node *dst, Node *src)
 	src->walkgen = walkgen;
 
 	if(debug['m']>1)
-		print("escwalk: level:%d depth:%d %.*s %hN scope:%#S[%d]\n",
+		print("escwalk: level:%d depth:%d %.*s %hN scope:%S[%d]\n",
 		      level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src,
 		      (src->curfn && src->curfn->nname) ? src->curfn->nname->sym : S, src->escloopdepth);
 
@@ -647,12 +727,13 @@ escwalk(int level, Node *dst, Node *src)
 		}
 		break;
 
+	case OPTRLIT:
 	case OADDR:
 		if(leaks) {
 			src->esc = EscHeap;
 			addrescapes(src->left);
 			if(debug['m'])
-				warnl(src->lineno, "%#N escapes to heap", src);
+				warnl(src->lineno, "%hN escapes to heap", src);
 		}
 		escwalk(level-1, dst, src->left);
 		break;
@@ -671,7 +752,7 @@ escwalk(int level, Node *dst, Node *src)
 		if(leaks) {
 			src->esc = EscHeap;
 			if(debug['m'])
-				warnl(src->lineno, "%#N escapes to heap", src);
+				warnl(src->lineno, "%hN escapes to heap", src);
 		}
 		break;
 
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
index 421afda..05fdcbf 100644
--- a/src/cmd/gc/export.c
+++ b/src/cmd/gc/export.c
@@ -7,11 +7,9 @@
 #include	"go.h"
 #include	"y.tab.h"
 
-static	void dumpsym(Sym*);
-static	void	dumpexporttype(Sym*);
-static	void	dumpexportvar(Sym*);
-static	void	dumpexportconst(Sym*);
+static void	dumpexporttype(Type *t);
 
+// Mark n's symbol as exported
 void
 exportsym(Node *n)
 {
@@ -27,6 +25,7 @@ exportsym(Node *n)
 	exportlist = list(exportlist, n);
 }
 
+// Mark n's symbol as package-local
 static void
 packagesym(Node *n)
 {
@@ -79,7 +78,7 @@ dumppkg(Pkg *p)
 {
 	char *suffix;
 
-	if(p == nil || p == localpkg || p->exported)
+	if(p == nil || p == localpkg || p->exported || p == builtinpkg)
 		return;
 	p->exported = 1;
 	suffix = "";
@@ -88,25 +87,84 @@ dumppkg(Pkg *p)
 	Bprint(bout, "\timport %s \"%Z\"%s\n", p->name, p->path, suffix);
 }
 
+// Look for anything we need for the inline body
+static void reexportdep(Node *n);
 static void
-dumpprereq(Type *t)
+reexportdeplist(NodeList *ll)
 {
-	if(t == T)
-		return;
+	for(; ll ;ll=ll->next)
+		reexportdep(ll->n);
+}
+
+static void
+reexportdep(Node *n)
+{
+	Type *t;
 
-	if(t->printed || t == types[t->etype])
+	if(!n)
 		return;
-	t->printed = 1;
 
-	if(t->sym != S) {
-		dumppkg(t->sym->pkg);
-		if(t->etype != TFIELD)
-			dumpsym(t->sym);
+//	print("reexportdep %+hN\n", n);
+	switch(n->op) {
+	case ONAME:
+		switch(n->class&~PHEAP) {
+		case PFUNC:
+			// methods will be printed along with their type
+			if(!n->type || n->type->thistuple > 0)
+				break;
+			// fallthrough
+		case PEXTERN:
+			if (n->sym && n->sym->pkg != localpkg && n->sym->pkg != builtinpkg)
+				exportlist = list(exportlist, n);
+		}
+		break;
+
+
+	case OLITERAL:
+		t = n->type;
+		if(t != types[n->type->etype] && t != idealbool && t != idealstring) {
+			if(isptr[t->etype])
+				t = t->type;
+			if (t && t->sym && t->sym->def && t->sym->pkg != localpkg  && t->sym->pkg != builtinpkg) {
+//				print("reexport literal type %+hN\n", t->sym->def);
+				exportlist = list(exportlist, t->sym->def);
+			}
+		}
+		// fallthrough
+	case OTYPE:
+		if (n->sym && n->sym->pkg != localpkg && n->sym->pkg != builtinpkg)
+			exportlist = list(exportlist, n);
+		break;
+
+	// for operations that need a type when rendered, put the type on the export list.
+	case OCONV:
+	case OCONVIFACE:
+	case OCONVNOP:
+	case ODOTTYPE:
+	case OSTRUCTLIT:
+	case OPTRLIT:
+		t = n->type;
+		if(!t->sym && t->type)
+			t = t->type;
+		if (t && t->sym && t->sym->def && t->sym->pkg != localpkg  && t->sym->pkg != builtinpkg) {
+//			print("reexport convnop %+hN\n", t->sym->def);
+			exportlist = list(exportlist, t->sym->def);
+		}
+		break;
 	}
-	dumpprereq(t->type);
-	dumpprereq(t->down);
+
+	reexportdep(n->left);
+	reexportdep(n->right);
+	reexportdeplist(n->list);
+	reexportdeplist(n->rlist);
+	reexportdeplist(n->ninit);
+	reexportdep(n->ntest);
+	reexportdep(n->nincr);
+	reexportdeplist(n->nbody);
+	reexportdeplist(n->nelse);
 }
 
+
 static void
 dumpexportconst(Sym *s)
 {
@@ -119,37 +177,12 @@ dumpexportconst(Sym *s)
 		fatal("dumpexportconst: oconst nil: %S", s);
 
 	t = n->type;	// may or may not be specified
-	if(t != T)
-		dumpprereq(t);
+	dumpexporttype(t);
 
-	Bprint(bout, "\t");
-	Bprint(bout, "const %#S", s);
 	if(t != T && !isideal(t))
-		Bprint(bout, " %#T", t);
-	Bprint(bout, " = ");
-
-	switch(n->val.ctype) {
-	default:
-		fatal("dumpexportconst: unknown ctype: %S %d", s, n->val.ctype);
-	case CTINT:
-		Bprint(bout, "%B\n", n->val.u.xval);
-		break;
-	case CTBOOL:
-		if(n->val.u.bval)
-			Bprint(bout, "true\n");
-		else
-			Bprint(bout, "false\n");
-		break;
-	case CTFLT:
-		Bprint(bout, "%F\n", n->val.u.fval);
-		break;
-	case CTCPLX:
-		Bprint(bout, "(%F+%F)\n", &n->val.u.cval->real, &n->val.u.cval->imag);
-		break;
-	case CTSTR:
-		Bprint(bout, "\"%Z\"\n", n->val.u.sval);
-		break;
-	}
+		Bprint(bout, "\tconst %#S %#T = %#V\n", s, t, &n->val);
+	else
+		Bprint(bout, "\tconst %#S = %#V\n", s, &n->val);
 }
 
 static void
@@ -159,38 +192,27 @@ dumpexportvar(Sym *s)
 	Type *t;
 
 	n = s->def;
-	typecheck(&n, Erv);
+	typecheck(&n, Erv|Ecall);
 	if(n == N || n->type == T) {
 		yyerror("variable exported but not defined: %S", s);
 		return;
 	}
 
 	t = n->type;
-	dumpprereq(t);
-
-	Bprint(bout, "\t");
-	if(t->etype == TFUNC && n->class == PFUNC)
-		Bprint(bout, "func %#S %#hhT", s, t);
-	else
-		Bprint(bout, "var %#S %#T", s, t);
-	Bprint(bout, "\n");
-}
-
-static void
-dumpexporttype(Sym *s)
-{
-	Type *t;
-
-	t = s->def->type;
-	dumpprereq(t);
-	Bprint(bout, "\t");
-	switch (t->etype) {
-	case TFORW:
-		yyerror("export of incomplete type %T", t);
-		return;
-	}
-	if(Bprint(bout, "type %#T %l#T\n",  t, t) < 0)
-		fatal("Bprint failed for %T", t);
+	dumpexporttype(t);
+
+	if(t->etype == TFUNC && n->class == PFUNC) {
+		if (n->inl) {
+			// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
+			// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
+			if(debug['l'] < 2)
+				typecheckinl(n);
+			Bprint(bout, "\tfunc %#S%#hT { %#H }\n", s, t, n->inl);
+			reexportdeplist(n->inl);
+		} else
+			Bprint(bout, "\tfunc %#S%#hT\n", s, t);
+	} else
+		Bprint(bout, "\tvar %#S %#T\n", s, t);
 }
 
 static int
@@ -204,12 +226,57 @@ methcmp(const void *va, const void *vb)
 }
 
 static void
-dumpsym(Sym *s)
+dumpexporttype(Type *t)
 {
-	Type *f, *t;
+	Type *f;
 	Type **m;
 	int i, n;
 
+	if(t == T)
+		return;
+	if(t->printed || t == types[t->etype] || t == bytetype || t == runetype || t == errortype)
+		return;
+	t->printed = 1;
+
+	if(t->sym != S && t->etype != TFIELD)
+		dumppkg(t->sym->pkg);
+
+	dumpexporttype(t->type);
+	dumpexporttype(t->down);
+
+	if (t->sym == S || t->etype == TFIELD)
+		return;
+
+	n = 0;
+	for(f=t->method; f!=T; f=f->down) {	
+		dumpexporttype(f);
+		n++;
+	}
+
+	m = mal(n*sizeof m[0]);
+	i = 0;
+	for(f=t->method; f!=T; f=f->down)
+		m[i++] = f;
+	qsort(m, n, sizeof m[0], methcmp);
+
+	Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
+	for(i=0; i<n; i++) {
+		f = m[i];
+		if (f->type->nname && f->type->nname->inl) { // nname was set by caninl
+			// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
+			// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
+			if(debug['l'] < 2)
+				typecheckinl(f->type->nname);
+			Bprint(bout, "\tfunc (%#T) %#hhS%#hT { %#H }\n", getthisx(f->type)->type, f->sym, f->type, f->type->nname->inl);
+			reexportdeplist(f->type->nname->inl);
+		} else
+			Bprint(bout, "\tfunc (%#T) %#hhS%#hT\n", getthisx(f->type)->type, f->sym, f->type);
+	}
+}
+
+static void
+dumpsym(Sym *s)
+{
 	if(s->flags & SymExported)
 		return;
 	s->flags |= SymExported;
@@ -218,56 +285,31 @@ dumpsym(Sym *s)
 		yyerror("unknown export symbol: %S", s);
 		return;
 	}
-	
+//	print("dumpsym %O %+S\n", s->def->op, s);
 	dumppkg(s->pkg);
 
 	switch(s->def->op) {
 	default:
 		yyerror("unexpected export symbol: %O %S", s->def->op, s);
 		break;
+
 	case OLITERAL:
 		dumpexportconst(s);
 		break;
+
 	case OTYPE:
-		t = s->def->type;
-		n = 0;
-		for(f=t->method; f!=T; f=f->down) {	
-			dumpprereq(f);
-			n++;
-		}
-		m = mal(n*sizeof m[0]);
-		i = 0;
-		for(f=t->method; f!=T; f=f->down)
-			m[i++] = f;
-		qsort(m, n, sizeof m[0], methcmp);
-
-		dumpexporttype(s);
-		for(i=0; i<n; i++) {
-			f = m[i];
-			Bprint(bout, "\tfunc (%#T) %hS %#hhT\n",
-				f->type->type->type, f->sym, f->type);
-		}
+		if(s->def->type->etype == TFORW)
+			yyerror("export of incomplete type %S", s);
+		else
+			dumpexporttype(s->def->type);
 		break;
+
 	case ONAME:
 		dumpexportvar(s);
 		break;
 	}
 }
 
-static void
-dumptype(Type *t)
-{
-	// no need to re-dump type if already exported
-	if(t->printed)
-		return;
-
-	// no need to dump type if it's not ours (was imported)
-	if(t->sym != S && t->sym->def == typenod(t) && !t->local)
-		return;
-
-	Bprint(bout, "type %#T %l#T\n",  t, t);
-}
-
 void
 dumpexport(void)
 {
@@ -277,10 +319,7 @@ dumpexport(void)
 
 	lno = lineno;
 
-	packagequotes = 1;
-	Bprint(bout, "\n$$  // exports\n");
-
-	Bprint(bout, "    package %s", localpkg->name);
+	Bprint(bout, "\n$$  // exports\n    package %s", localpkg->name);
 	if(safemode)
 		Bprint(bout, " safe");
 	Bprint(bout, "\n");
@@ -295,15 +334,7 @@ dumpexport(void)
 		dumpsym(l->n->sym);
 	}
 
-	Bprint(bout, "\n$$  // local types\n");
-
-	for(l=typelist; l; l=l->next) {
-		lineno = l->n->lineno;
-		dumptype(l->n->type);
-	}
-
-	Bprint(bout, "\n$$\n");
-	packagequotes = 0;
+	Bprint(bout, "\n$$  // local types\n\n$$\n");   // 6l expects this. (see ld/go.c)
 
 	lineno = lno;
 }
@@ -346,16 +377,29 @@ pkgtype(Sym *s)
 		s->def = typenod(t);
 	}
 	if(s->def->type == T)
-		yyerror("pkgtype %lS", s);
+		yyerror("pkgtype %S", s);
 	return s->def->type;
 }
 
-static int
-mypackage(Sym *s)
+void
+importimport(Sym *s, Strlit *z)
 {
-	// we import all definitions for runtime.
-	// lowercase ones can only be used by the compiler.
-	return s->pkg == localpkg || s->pkg == runtimepkg;
+	// Informational: record package name
+	// associated with import path, for use in
+	// human-readable messages.
+	Pkg *p;
+
+	p = mkpkg(z);
+	if(p->name == nil) {
+		p->name = s->name;
+		pkglookup(s->name, nil)->npkg++;
+	} else if(strcmp(p->name, s->name) != 0)
+		yyerror("conflicting names %s and %s for package \"%Z\"", p->name, s->name, p->path);
+	
+	if(!incannedimport && myimportpath != nil && strcmp(z->s, myimportpath) == 0) {
+		yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, z);
+		errorexit();
+	}
 }
 
 void
@@ -363,19 +407,17 @@ importconst(Sym *s, Type *t, Node *n)
 {
 	Node *n1;
 
-	if(!exportname(s->name) && !mypackage(s))
-		return;
 	importsym(s, OLITERAL);
 	convlit(&n, t);
-	if(s->def != N) {
-		// TODO: check if already the same.
+
+	if(s->def != N)	 // TODO: check if already the same.
 		return;
-	}
 
 	if(n->op != OLITERAL) {
 		yyerror("expression must be a constant");
 		return;
 	}
+
 	if(n->sym != S) {
 		n1 = nod(OXXX, N, N);
 		*n1 = *n;
@@ -389,23 +431,19 @@ importconst(Sym *s, Type *t, Node *n)
 }
 
 void
-importvar(Sym *s, Type *t, int ctxt)
+importvar(Sym *s, Type *t)
 {
 	Node *n;
 
-	if(!exportname(s->name) && !initname(s->name) && !mypackage(s))
-		return;
-
 	importsym(s, ONAME);
 	if(s->def != N && s->def->op == ONAME) {
 		if(eqtype(t, s->def->type))
 			return;
-		yyerror("inconsistent definition for var %S during import\n\t%T\n\t%T",
-			s, s->def->type, t);
+		yyerror("inconsistent definition for var %S during import\n\t%T\n\t%T", s, s->def->type, t);
 	}
 	n = newname(s);
 	n->type = t;
-	declare(n, ctxt);
+	declare(n, PEXTERN);
 
 	if(debug['E'])
 		print("import var %S %lT\n", s, t);
@@ -414,17 +452,27 @@ importvar(Sym *s, Type *t, int ctxt)
 void
 importtype(Type *pt, Type *t)
 {
-	if(pt != T && t != T)
-		typedcl2(pt, t);
+	Node *n;
+
+	// override declaration in unsafe.go for Pointer.
+	// there is no way in Go code to define unsafe.Pointer
+	// so we have to supply it.
+	if(incannedimport &&
+	   strcmp(importpkg->name, "unsafe") == 0 &&
+	   strcmp(pt->nod->sym->name, "Pointer") == 0) {
+		t = types[TUNSAFEPTR];
+	}
+
+	if(pt->etype == TFORW) {
+		n = pt->nod;
+		copytype(pt->nod, t);
+		pt->nod = n;		// unzero nod
+		pt->sym->lastlineno = parserline();
+		declare(n, PEXTERN);
+		checkwidth(pt);
+	} else if(!eqtype(pt->orig, t))
+		yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt, t);
 
 	if(debug['E'])
 		print("import type %T %lT\n", pt, t);
 }
-
-void
-importmethod(Sym *s, Type *t)
-{
-	checkwidth(t);
-	addmethod(s, t, 0);
-}
-
diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c
new file mode 100644
index 0000000..31b0a62
--- /dev/null
+++ b/src/cmd/gc/fmt.c
@@ -0,0 +1,1626 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include	<u.h>
+#include	<libc.h>
+#include	"go.h"
+#include	"opnames.h"
+
+//
+// Format conversions
+//	%L int		Line numbers
+//
+//	%E int		etype values (aka 'Kind')
+//
+//	%O int		Node Opcodes
+//		Flags: "%#O": print go syntax. (automatic unless fmtmode == FDbg)
+//
+//	%J Node*	Node details
+//		Flags: "%hJ" supresses things not relevant until walk.
+//
+//	%V Val*		Constant values
+//
+//	%S Sym*		Symbols
+//		Flags: +,- #: mode (see below)
+//			"%hS"	unqualified identifier in any mode
+//			"%hhS"  in export mode: unqualified identifier if exported, qualified if not
+//
+//	%T Type*	Types
+//		Flags: +,- #: mode (see below)
+//			'l' definition instead of name.
+//			'h' omit "func" and receiver in function types
+//			'u' (only in -/Sym mode) print type identifiers wit package name instead of prefix.
+//
+//	%N Node*	Nodes
+//		Flags: +,- #: mode (see below)
+//			'h' (only in +/debug mode) suppress recursion
+//			'l' (only in Error mode) print "foo (type Bar)"
+//
+//	%H NodeList*	NodeLists
+//		Flags: those of %N
+//			','  separate items with ',' instead of ';'
+//
+//	%Z Strlit*	String literals
+//
+//   In mparith1.c:
+//      %B Mpint*	Big integers
+//	%F Mpflt*	Big floats
+//
+//   %S, %T and %N obey use the following flags to set the format mode:
+enum {
+	FErr,	//     error mode (default)
+	FDbg,	//     "%+N" debug mode
+	FExp,	//     "%#N" export mode
+	FTypeId,  //   "%-N" turning-types-into-symbols-mode: identical types give identical strings
+};
+static int fmtmode;
+static int fmtpkgpfx;	// %uT stickyness
+//
+// E.g. for %S:	%+S %#S %-S	print an identifier properly qualified for debug/export/internal mode.
+//
+// The mode flags  +, - and # are sticky, meaning they persist through
+// recursions of %N, %T and %S, but not the h and l flags.  The u flag is
+// sticky only on %T recursions and only used in %-/Sym mode.
+
+//
+// Useful format combinations:
+//
+//	%+N   %+H	multiline recursive debug dump of node/nodelist
+//	%+hN  %+hH	non recursive debug dump
+//
+//	%#N   %#T	export format
+//	%#lT		type definition instead of name
+//	%#hT		omit"func" and receiver in function signature
+//
+//	%lN		"foo (type Bar)" for error messages
+//
+//	%-T		type identifiers
+//	%-hT		type identifiers without "func" and arg names in type signatures (methodsym)
+//	%-uT		type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
+//
+
+
+static int
+setfmode(unsigned long *flags)
+{
+	int fm;
+
+	fm = fmtmode;
+	if(*flags & FmtSign)
+		fmtmode = FDbg;
+	else if(*flags & FmtSharp)
+		fmtmode = FExp;
+	else if(*flags & FmtLeft)
+		fmtmode = FTypeId;
+
+	*flags &= ~(FmtSharp|FmtLeft|FmtSign);
+	return fm;
+}
+
+// Fmt "%L": Linenumbers
+static int
+Lconv(Fmt *fp)
+{
+	struct
+	{
+		Hist*	incl;	/* start of this include file */
+		int32	idel;	/* delta line number to apply to include */
+		Hist*	line;	/* start of this #line directive */
+		int32	ldel;	/* delta line number to apply to #line */
+	} a[HISTSZ];
+	int32 lno, d;
+	int i, n;
+	Hist *h;
+
+	lno = va_arg(fp->args, int32);
+
+	n = 0;
+	for(h=hist; h!=H; h=h->link) {
+		if(h->offset < 0)
+			continue;
+		if(lno < h->line)
+			break;
+		if(h->name) {
+			if(h->offset > 0) {
+				// #line directive
+				if(n > 0 && n < HISTSZ) {
+					a[n-1].line = h;
+					a[n-1].ldel = h->line - h->offset + 1;
+				}
+			} else {
+				// beginning of file
+				if(n < HISTSZ) {
+					a[n].incl = h;
+					a[n].idel = h->line;
+					a[n].line = 0;
+				}
+				n++;
+			}
+			continue;
+		}
+		n--;
+		if(n > 0 && n < HISTSZ) {
+			d = h->line - a[n].incl->line;
+			a[n-1].ldel += d;
+			a[n-1].idel += d;
+		}
+	}
+
+	if(n > HISTSZ)
+		n = HISTSZ;
+
+	for(i=n-1; i>=0; i--) {
+		if(i != n-1) {
+			if(fp->flags & ~(FmtWidth|FmtPrec))
+				break;
+			fmtprint(fp, " ");
+		}
+		if(debug['L'] || (fp->flags&FmtLong))
+			fmtprint(fp, "%s/", pathname);
+		if(a[i].line)
+			fmtprint(fp, "%s:%d[%s:%d]",
+				a[i].line->name, lno-a[i].ldel+1,
+				a[i].incl->name, lno-a[i].idel+1);
+		else
+			fmtprint(fp, "%s:%d",
+				a[i].incl->name, lno-a[i].idel+1);
+		lno = a[i].incl->line - 1;	// now print out start of this file
+	}
+	if(n == 0)
+		fmtprint(fp, "<epoch>");
+
+	return 0;
+}
+
+static char*
+goopnames[] =
+{
+	[OADDR]		= "&",
+	[OADD]		= "+",
+	[OADDSTR]	= "+",
+	[OANDAND]	= "&&",
+	[OANDNOT]	= "&^",
+	[OAND]		= "&",
+	[OAPPEND]	= "append",
+	[OAS]		= "=",
+	[OAS2]		= "=",
+	[OBREAK]	= "break",
+	[OCALL]		= "function call",	// not actual syntax
+	[OCAP]		= "cap",
+	[OCASE]		= "case",
+	[OCLOSE]	= "close",
+	[OCOMPLEX]	= "complex",
+	[OCOM]		= "^",
+	[OCONTINUE]	= "continue",
+	[OCOPY]		= "copy",
+	[ODEC]		= "--",
+	[ODELETE]	= "delete",
+	[ODEFER]	= "defer",
+	[ODIV]		= "/",
+	[OEQ]		= "==",
+	[OFALL]		= "fallthrough",
+	[OFOR]		= "for",
+	[OGE]		= ">=",
+	[OGOTO]		= "goto",
+	[OGT]		= ">",
+	[OIF]		= "if",
+	[OIMAG]		= "imag",
+	[OINC]		= "++",
+	[OIND]		= "*",
+	[OLEN]		= "len",
+	[OLE]		= "<=",
+	[OLSH]		= "<<",
+	[OLT]		= "<",
+	[OMAKE]		= "make",
+	[OMINUS]	= "-",
+	[OMOD]		= "%",
+	[OMUL]		= "*",
+	[ONEW]		= "new",
+	[ONE]		= "!=",
+	[ONOT]		= "!",
+	[OOROR]		= "||",
+	[OOR]		= "|",
+	[OPANIC]	= "panic",
+	[OPLUS]		= "+",
+	[OPRINTN]	= "println",
+	[OPRINT]	= "print",
+	[ORANGE]	= "range",
+	[OREAL]		= "real",
+	[ORECV]		= "<-",
+	[ORETURN]	= "return",
+	[ORSH]		= ">>",
+	[OSELECT]	= "select",
+	[OSEND]		= "<-",
+	[OSUB]		= "-",
+	[OSWITCH]	= "switch",
+	[OXOR]		= "^",
+};
+
+// Fmt "%O":  Node opcodes
+static int
+Oconv(Fmt *fp)
+{
+	int o;
+
+	o = va_arg(fp->args, int);
+	if((fp->flags & FmtSharp) || fmtmode != FDbg)
+		if(o >= 0 && o < nelem(goopnames) && goopnames[o] != nil)
+			return fmtstrcpy(fp, goopnames[o]);
+
+	if(o >= 0 && o < nelem(opnames) && opnames[o] != nil)
+		return fmtstrcpy(fp, opnames[o]);
+
+	return fmtprint(fp, "O-%d", o);
+}
+
+static const char* classnames[] = {
+	"Pxxx",
+	"PEXTERN",
+	"PAUTO",
+	"PPARAM",
+	"PPARAMOUT",
+	"PPARAMREF",
+	"PFUNC",
+};
+
+// Fmt "%J": Node details.
+static int
+Jconv(Fmt *fp)
+{
+	Node *n;
+	char *s;
+	int c;
+
+	n = va_arg(fp->args, Node*);
+
+	c = fp->flags&FmtShort;
+
+	if(!c && n->ullman != 0)
+		fmtprint(fp, " u(%d)", n->ullman);
+
+	if(!c && n->addable != 0)
+		fmtprint(fp, " a(%d)", n->addable);
+
+	if(!c && n->vargen != 0)
+		fmtprint(fp, " g(%d)", n->vargen);
+
+	if(n->lineno != 0)
+		fmtprint(fp, " l(%d)", n->lineno);
+
+	if(!c && n->xoffset != BADWIDTH)
+		fmtprint(fp, " x(%lld%+d)", n->xoffset, n->stkdelta);
+
+	if(n->class != 0) {
+		s = "";
+		if(n->class & PHEAP) s = ",heap";
+		if((n->class & ~PHEAP) < nelem(classnames))
+			fmtprint(fp, " class(%s%s)", classnames[n->class&~PHEAP], s);
+		else
+			fmtprint(fp, " class(%d?%s)", n->class&~PHEAP, s);
+	}
+
+	if(n->colas != 0)
+		fmtprint(fp, " colas(%d)", n->colas);
+
+	if(n->funcdepth != 0)
+		fmtprint(fp, " f(%d)", n->funcdepth);
+
+	switch(n->esc) {
+	case EscUnknown:
+		break;
+	case EscHeap:
+		fmtprint(fp, " esc(h)");
+		break;
+	case EscScope:
+		fmtprint(fp, " esc(s)");
+		break;
+	case EscNone:
+		fmtprint(fp, " esc(no)");
+		break;
+	case EscNever:
+		if(!c)
+			fmtprint(fp, " esc(N)");
+		break;
+	default:
+		fmtprint(fp, " esc(%d)", n->esc);
+		break;
+	}
+
+	if(n->escloopdepth)
+		fmtprint(fp, " ld(%d)", n->escloopdepth);
+
+	if(!c && n->typecheck != 0)
+		fmtprint(fp, " tc(%d)", n->typecheck);
+
+	if(!c && n->dodata != 0)
+		fmtprint(fp, " dd(%d)", n->dodata);
+
+	if(n->isddd != 0)
+		fmtprint(fp, " isddd(%d)", n->isddd);
+
+	if(n->implicit != 0)
+		fmtprint(fp, " implicit(%d)", n->implicit);
+
+	if(n->embedded != 0)
+		fmtprint(fp, " embedded(%d)", n->embedded);
+
+	if(!c && n->used != 0)
+		fmtprint(fp, " used(%d)", n->used);
+	return 0;
+}
+
+// Fmt "%V": Values
+static int
+Vconv(Fmt *fp)
+{
+	Val *v;
+	vlong x;
+
+	v = va_arg(fp->args, Val*);
+
+	switch(v->ctype) {
+	case CTINT:
+		return fmtprint(fp, "%B", v->u.xval);
+	case CTRUNE:
+		x = mpgetfix(v->u.xval);
+		if(' ' <= x && x < 0x80 && x != '\\' && x != '\'')
+			return fmtprint(fp, "'%c'", (int)x);
+		if(0 <= x && x < (1<<16))
+			return fmtprint(fp, "'\\u%04ux'", (int)x);
+		if(0 <= x && x <= Runemax)
+			return fmtprint(fp, "'\\U%08llux'", x);
+		return fmtprint(fp, "('\\x00' + %B)", v->u.xval);
+	case CTFLT:
+		if((fp->flags & FmtSharp) || fmtmode == FExp)
+			return fmtprint(fp, "%F", v->u.fval);
+		return fmtprint(fp, "%#F", v->u.fval);
+	case CTCPLX:
+		if((fp->flags & FmtSharp) || fmtmode == FExp)
+			return fmtprint(fp, "(%F+%F)", &v->u.cval->real, &v->u.cval->imag);
+		return fmtprint(fp, "(%#F + %#Fi)", &v->u.cval->real, &v->u.cval->imag);
+	case CTSTR:
+		return fmtprint(fp, "\"%Z\"", v->u.sval);
+	case CTBOOL:
+		if( v->u.bval)
+			return fmtstrcpy(fp, "true");
+		return fmtstrcpy(fp, "false");
+	case CTNIL:
+		return fmtstrcpy(fp, "nil");
+	}
+	return fmtprint(fp, "<%d>", v->ctype);
+}
+
+// Fmt "%Z": escaped string literals
+static int
+Zconv(Fmt *fp)
+{
+	Rune r;
+	Strlit *sp;
+	char *s, *se;
+	int n;
+
+	sp = va_arg(fp->args, Strlit*);
+	if(sp == nil)
+		return fmtstrcpy(fp, "<nil>");
+
+	s = sp->s;
+	se = s + sp->len;
+	while(s < se) {
+		n = chartorune(&r, s);
+		s += n;
+		switch(r) {
+		case Runeerror:
+			if(n == 1) {
+				fmtprint(fp, "\\x%02x", (uchar)*(s-1));
+				break;
+			}
+			// fall through
+		default:
+			if(r < ' ') {
+				fmtprint(fp, "\\x%02x", r);
+				break;
+			}
+			fmtrune(fp, r);
+			break;
+		case '\t':
+			fmtstrcpy(fp, "\\t");
+			break;
+		case '\n':
+			fmtstrcpy(fp, "\\n");
+			break;
+		case '\"':
+		case '\\':
+			fmtrune(fp, '\\');
+			fmtrune(fp, r);
+			break;
+		}
+	}
+	return 0;
+}
+
+/*
+s%,%,\n%g
+s%\n+%\n%g
+s%^[	]*T%%g
+s%,.*%%g
+s%.+%	[T&]		= "&",%g
+s%^	........*\]%&~%g
+s%~	%%g
+*/
+
+static char*
+etnames[] =
+{
+	[TINT]		= "INT",
+	[TUINT]		= "UINT",
+	[TINT8]		= "INT8",
+	[TUINT8]	= "UINT8",
+	[TINT16]	= "INT16",
+	[TUINT16]	= "UINT16",
+	[TINT32]	= "INT32",
+	[TUINT32]	= "UINT32",
+	[TINT64]	= "INT64",
+	[TUINT64]	= "UINT64",
+	[TUINTPTR]	= "UINTPTR",
+	[TFLOAT32]	= "FLOAT32",
+	[TFLOAT64]	= "FLOAT64",
+	[TCOMPLEX64]	= "COMPLEX64",
+	[TCOMPLEX128]	= "COMPLEX128",
+	[TBOOL]		= "BOOL",
+	[TPTR32]	= "PTR32",
+	[TPTR64]	= "PTR64",
+	[TFUNC]		= "FUNC",
+	[TARRAY]	= "ARRAY",
+	[TSTRUCT]	= "STRUCT",
+	[TCHAN]		= "CHAN",
+	[TMAP]		= "MAP",
+	[TINTER]	= "INTER",
+	[TFORW]		= "FORW",
+	[TFIELD]	= "FIELD",
+	[TSTRING]	= "STRING",
+	[TANY]		= "ANY",
+};
+
+// Fmt "%E": etype
+static int
+Econv(Fmt *fp)
+{
+	int et;
+
+	et = va_arg(fp->args, int);
+	if(et >= 0 && et < nelem(etnames) && etnames[et] != nil)
+		return fmtstrcpy(fp, etnames[et]);
+	return fmtprint(fp, "E-%d", et);
+}
+
+// Fmt "%S": syms
+static int
+symfmt(Fmt *fp, Sym *s)
+{
+	char *p;
+
+	if(s->pkg && !(fp->flags&FmtShort)) {
+		switch(fmtmode) {
+		case FErr:	// This is for the user
+			if(s->pkg == localpkg)
+				return fmtstrcpy(fp, s->name);
+			// If the name was used by multiple packages, display the full path,
+			if(s->pkg->name && pkglookup(s->pkg->name, nil)->npkg > 1)
+				return fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name);
+			return fmtprint(fp, "%s.%s", s->pkg->name, s->name);
+		case FDbg:
+			return fmtprint(fp, "%s.%s", s->pkg->name, s->name);
+		case FTypeId:
+			if(fp->flags&FmtUnsigned)
+				return fmtprint(fp, "%s.%s", s->pkg->name, s->name);	// dcommontype, typehash
+			return fmtprint(fp, "%s.%s", s->pkg->prefix, s->name);	// (methodsym), typesym, weaksym
+		case FExp:
+			if(s->pkg != builtinpkg)
+				return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, s->name);
+		}
+	}
+
+	if(fp->flags&FmtByte) {  // FmtByte (hh) implies FmtShort (h)
+		// skip leading "type." in method name
+		p = utfrrune(s->name, '.');
+		if(p)
+			p++;
+		else
+			p = s->name;
+
+		// exportname needs to see the name without the prefix too.
+		if((fmtmode == FExp && !exportname(p)) || fmtmode == FDbg)
+			return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, p);
+
+		return fmtstrcpy(fp, p);
+	}
+
+	return fmtstrcpy(fp, s->name);
+}
+
+static char*
+basicnames[] =
+{
+	[TINT]		= "int",
+	[TUINT]		= "uint",
+	[TINT8]		= "int8",
+	[TUINT8]	= "uint8",
+	[TINT16]	= "int16",
+	[TUINT16]	= "uint16",
+	[TINT32]	= "int32",
+	[TUINT32]	= "uint32",
+	[TINT64]	= "int64",
+	[TUINT64]	= "uint64",
+	[TUINTPTR]	= "uintptr",
+	[TFLOAT32]	= "float32",
+	[TFLOAT64]	= "float64",
+	[TCOMPLEX64]	= "complex64",
+	[TCOMPLEX128]	= "complex128",
+	[TBOOL]		= "bool",
+	[TANY]		= "any",
+	[TSTRING]	= "string",
+	[TNIL]		= "nil",
+	[TIDEAL]	= "ideal",
+	[TBLANK]	= "blank",
+};
+
+static int
+typefmt(Fmt *fp, Type *t)
+{
+	Type *t1;
+	Sym *s;
+
+	if(t == T)
+		return fmtstrcpy(fp, "<T>");
+
+	if (t == bytetype || t == runetype) {
+		// in %-T mode collapse rune and byte with their originals.
+		if(fmtmode != FTypeId)
+			return fmtprint(fp, "%hS", t->sym);
+		t = types[t->etype];
+	}
+
+	if(t == errortype)
+		return fmtstrcpy(fp, "error");
+
+	// Unless the 'l' flag was specified, if the type has a name, just print that name.
+	if(!(fp->flags&FmtLong) && t->sym && t->etype != TFIELD && t != types[t->etype]) {
+		switch(fmtmode) {
+		case FTypeId:
+			if(fp->flags&FmtShort)
+				return fmtprint(fp, "%hS", t->sym);
+			if(fp->flags&FmtUnsigned)
+				return fmtprint(fp, "%uS", t->sym);
+			// fallthrough
+		case FExp:
+			if(t->sym->pkg == localpkg && t->vargen)
+				return fmtprint(fp, "%S·%d", t->sym, t->vargen);
+			break;
+		}
+		return fmtprint(fp, "%S", t->sym);
+	}
+
+	if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil) {
+		if(fmtmode == FErr && (t == idealbool || t == idealstring))
+			fmtstrcpy(fp, "ideal ");
+		return fmtstrcpy(fp, basicnames[t->etype]);
+	}
+
+	if(fmtmode == FDbg)
+		fmtprint(fp, "%E-", t->etype);
+
+	switch(t->etype) {
+	case TPTR32:
+	case TPTR64:
+		if(fmtmode == FTypeId && (fp->flags&FmtShort))
+			return fmtprint(fp, "*%hT", t->type);
+		return fmtprint(fp, "*%T", t->type);
+
+	case TARRAY:
+		if(t->bound >= 0)
+			return fmtprint(fp, "[%d]%T", (int)t->bound, t->type);
+		if(t->bound == -100)
+			return fmtprint(fp, "[...]%T", t->type);
+		return fmtprint(fp, "[]%T", t->type);
+
+	case TCHAN:
+		switch(t->chan) {
+		case Crecv:
+			return fmtprint(fp, "<-chan %T", t->type);
+		case Csend:
+			return fmtprint(fp, "chan<- %T", t->type);
+		}
+
+		if(t->type != T && t->type->etype == TCHAN && t->type->sym == S && t->type->chan == Crecv)
+			return fmtprint(fp, "chan (%T)", t->type);
+		return fmtprint(fp, "chan %T", t->type);
+
+	case TMAP:
+		return fmtprint(fp, "map[%T]%T", t->down, t->type);
+
+	case TINTER:
+		fmtstrcpy(fp, "interface {");
+		for(t1=t->type; t1!=T; t1=t1->down)
+			if(exportname(t1->sym->name)) {
+				if(t1->down)
+					fmtprint(fp, " %hS%hT;", t1->sym, t1->type);
+				else
+					fmtprint(fp, " %hS%hT ", t1->sym, t1->type);
+			} else {
+				// non-exported method names must be qualified
+				if(t1->down)
+					fmtprint(fp, " %uS%hT;", t1->sym, t1->type);
+				else
+					fmtprint(fp, " %uS%hT ", t1->sym, t1->type);
+			}
+		fmtstrcpy(fp, "}");
+		return 0;
+
+	case TFUNC:
+		if(fp->flags & FmtShort) {
+			fmtprint(fp, "%T", getinargx(t));
+		} else {
+			if(t->thistuple)
+				fmtprint(fp, "method%T func%T", getthisx(t), getinargx(t));
+			else
+				fmtprint(fp, "func%T", getinargx(t));
+		}
+		switch(t->outtuple) {
+		case 0:
+			break;
+		case 1:
+			if(fmtmode != FExp) {
+				fmtprint(fp, " %T", getoutargx(t)->type->type);	 // struct->field->field's type
+				break;
+			}
+		default:
+			fmtprint(fp, " %T", getoutargx(t));
+			break;
+		}
+		return 0;
+
+	case TSTRUCT:
+		if(t->funarg) {
+			fmtstrcpy(fp, "(");
+			if(fmtmode == FTypeId || fmtmode == FErr) {	// no argument names on function signature, and no "noescape" tags
+				for(t1=t->type; t1!=T; t1=t1->down)
+					if(t1->down)
+						fmtprint(fp, "%hT, ", t1);
+					else
+						fmtprint(fp, "%hT", t1);
+			} else {
+				for(t1=t->type; t1!=T; t1=t1->down)
+					if(t1->down)
+						fmtprint(fp, "%T, ", t1);
+					else
+						fmtprint(fp, "%T", t1);
+			}
+			fmtstrcpy(fp, ")");
+		} else {
+			fmtstrcpy(fp, "struct {");
+			for(t1=t->type; t1!=T; t1=t1->down)
+				if(t1->down)
+					fmtprint(fp, " %lT;", t1);
+				else
+					fmtprint(fp, " %lT ", t1);
+			fmtstrcpy(fp, "}");
+		}
+		return 0;
+
+	case TFIELD:
+		if(!(fp->flags&FmtShort)) {
+			s = t->sym;
+			// Take the name from the original, lest we substituted it with .anon%d
+			if (t->nname && (fmtmode == FErr || fmtmode == FExp))
+				s = t->nname->orig->sym;
+			
+			if(s != S && !t->embedded) {
+				if(fp->flags&FmtLong)
+					fmtprint(fp, "%hhS ", s);  // qualify non-exported names (used on structs, not on funarg)
+				else 
+					fmtprint(fp, "%S ", s);
+			} else if(fmtmode == FExp) {
+				// TODO(rsc) this breaks on the eliding of unused arguments in the backend
+				// when this is fixed, the special case in dcl.c checkarglist can go.
+				//if(t->funarg)
+				//	fmtstrcpy(fp, "_ ");
+				//else
+					fmtstrcpy(fp, "? ");
+			}
+		}
+
+		if(t->isddd)
+			fmtprint(fp, "...%T", t->type->type);
+		else
+			fmtprint(fp, "%T", t->type);
+
+		if(!(fp->flags&FmtShort) && t->note)
+			fmtprint(fp, " \"%Z\"", t->note);
+		return 0;
+
+	case TFORW:
+		if(t->sym)
+			return fmtprint(fp, "undefined %S", t->sym);
+		return fmtstrcpy(fp, "undefined");
+
+	case TUNSAFEPTR:
+		if(fmtmode == FExp)
+			return fmtprint(fp, "@\"unsafe\".Pointer");
+		return fmtprint(fp, "unsafe.Pointer");
+	}
+
+	if(fmtmode == FExp)
+		fatal("missing %E case during export", t->etype);
+	// Don't know how to handle - fall back to detailed prints.
+	return fmtprint(fp, "%E <%S> %T", t->etype, t->sym, t->type);
+}
+
+// Statements which may be rendered with a simplestmt as init.
+static int
+stmtwithinit(int op)
+{
+	switch(op) {
+	case OIF:
+	case OFOR:
+	case OSWITCH:
+		return 1;
+	}
+	return 0;
+}
+
+static int
+stmtfmt(Fmt *f, Node *n)
+{
+	int complexinit, simpleinit, extrablock;
+
+	// some statements allow for an init, but at most one,
+	// but we may have an arbitrary number added, eg by typecheck
+	// and inlining.  If it doesn't fit the syntax, emit an enclosing
+	// block starting with the init statements.
+
+	// if we can just say "for" n->ninit; ... then do so
+	simpleinit = n->ninit && !n->ninit->next && !n->ninit->n->ninit && stmtwithinit(n->op);
+	// otherwise, print the inits as separate statements
+	complexinit = n->ninit && !simpleinit && (fmtmode != FErr);
+	// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
+	extrablock = complexinit && stmtwithinit(n->op);
+
+	if(extrablock)
+		fmtstrcpy(f, "{");
+
+	if(complexinit)
+		fmtprint(f, " %H; ", n->ninit);
+
+	switch(n->op){
+	case ODCL:
+		fmtprint(f, "var %S %T", n->left->sym, n->left->type);
+		break;
+
+	case ODCLFIELD:
+		if(n->left)
+			fmtprint(f, "%N %N", n->left, n->right);
+		else
+			fmtprint(f, "%N", n->right);
+		break;
+
+	case OAS:
+		if(n->colas && !complexinit)
+			fmtprint(f, "%N := %N", n->left, n->right);
+		else
+			fmtprint(f, "%N = %N", n->left, n->right);
+		break;
+
+	case OASOP:
+		fmtprint(f, "%N %#O= %N", n->left, n->etype, n->right);
+		break;
+
+	case OAS2:
+		if(n->colas && !complexinit) {
+			fmtprint(f, "%,H := %,H", n->list, n->rlist);
+			break;
+		}
+		// fallthrough
+	case OAS2DOTTYPE:
+	case OAS2FUNC:
+	case OAS2MAPR:
+	case OAS2RECV:
+		fmtprint(f, "%,H = %,H", n->list, n->rlist);
+		break;
+
+	case ORETURN:
+		fmtprint(f, "return %,H", n->list);
+		break;
+
+	case OPROC:
+		fmtprint(f, "go %N", n->left);
+		break;
+
+	case ODEFER:
+		fmtprint(f, "defer %N", n->left);
+		break;
+
+	case OIF:
+		if(simpleinit)
+			fmtprint(f, "if %N; %N { %H }", n->ninit->n, n->ntest, n->nbody);
+		else
+			fmtprint(f, "if %N { %H }", n->ntest, n->nbody);
+		if(n->nelse)
+			fmtprint(f, " else { %H }", n->nelse);
+		break;
+
+	case OFOR:
+		if(fmtmode == FErr) {	// TODO maybe only if FmtShort, same below
+			fmtstrcpy(f, "for loop");
+			break;
+		}
+
+		fmtstrcpy(f, "for");
+		if(simpleinit)
+			fmtprint(f, " %N;", n->ninit->n);
+		else if(n->nincr)
+			fmtstrcpy(f, " ;");
+
+		if(n->ntest)
+			fmtprint(f, " %N", n->ntest);
+
+		if(n->nincr)
+			fmtprint(f, "; %N", n->nincr);
+		else if(simpleinit)
+			fmtstrcpy(f, ";");
+
+
+		fmtprint(f, " { %H }", n->nbody);
+		break;
+
+	case ORANGE:
+		if(fmtmode == FErr) {
+			fmtstrcpy(f, "for loop");
+			break;
+		}
+
+		fmtprint(f, "for %,H = range %N { %H }", n->list, n->right, n->nbody);
+		break;
+
+	case OSELECT:
+	case OSWITCH:
+		if(fmtmode == FErr) {
+			fmtprint(f, "%O statement", n->op);
+			break;
+		}
+
+		fmtprint(f, "%#O", n->op);
+		if(simpleinit)
+			fmtprint(f, " %N;", n->ninit->n);
+		if(n->ntest)
+			fmtprint(f, "%N", n->ntest);
+
+		fmtprint(f, " { %H }", n->list);
+		break;
+
+	case OCASE:
+	case OXCASE:
+		if(n->list)
+			fmtprint(f, "case %,H: %H", n->list, n->nbody);
+		else
+			fmtprint(f, "default: %H", n->nbody);
+		break;
+
+	case OBREAK:
+	case OCONTINUE:
+	case OGOTO:
+	case OFALL:
+	case OXFALL:
+		if(n->left)
+			fmtprint(f, "%#O %N", n->op, n->left);
+		else
+			fmtprint(f, "%#O", n->op);
+		break;
+
+	case OEMPTY:
+		break;
+
+	case OLABEL:
+		fmtprint(f, "%N: ", n->left);
+		break;
+	  
+	}
+
+	if(extrablock)
+		fmtstrcpy(f, "}");
+
+	return 0;
+}
+
+
+static int opprec[] = {
+	[OAPPEND] = 8,
+	[OARRAYBYTESTR] = 8,
+	[OARRAYLIT] = 8,
+	[OARRAYRUNESTR] = 8,
+	[OCALLFUNC] = 8,
+	[OCALLINTER] = 8,
+	[OCALLMETH] = 8,
+	[OCALL] = 8,
+	[OCAP] = 8,
+	[OCLOSE] = 8,
+	[OCONVIFACE] = 8,
+	[OCONVNOP] = 8,
+	[OCONV] = 8,
+	[OCOPY] = 8,
+	[ODELETE] = 8,
+	[OLEN] = 8,
+	[OLITERAL] = 8,
+	[OMAKESLICE] = 8,
+	[OMAKE] = 8,
+	[OMAPLIT] = 8,
+	[ONAME] = 8,
+	[ONEW] = 8,
+	[ONONAME] = 8,
+	[OPACK] = 8,
+	[OPANIC] = 8,
+	[OPAREN] = 8,
+	[OPRINTN] = 8,
+	[OPRINT] = 8,
+	[ORECV] = 8,
+	[ORUNESTR] = 8,
+	[OSTRARRAYBYTE] = 8,
+	[OSTRARRAYRUNE] = 8,
+	[OSTRUCTLIT] = 8,
+	[OTARRAY] = 8,
+	[OTCHAN] = 8,
+	[OTFUNC] = 8,
+	[OTINTER] = 8,
+	[OTMAP] = 8,
+	[OTPAREN] = 8,
+	[OTSTRUCT] = 8,
+
+	[OINDEXMAP] = 8,
+	[OINDEX] = 8,
+	[OSLICE] = 8,
+	[OSLICESTR] = 8,
+	[OSLICEARR] = 8,
+	[ODOTINTER] = 8,
+	[ODOTMETH] = 8,
+	[ODOTPTR] = 8,
+	[ODOTTYPE2] = 8,
+	[ODOTTYPE] = 8,
+	[ODOT] = 8,
+	[OXDOT] = 8,
+
+	[OPLUS] = 7,
+	[ONOT] = 7,
+	[OCOM] = 7,
+	[OMINUS] = 7,
+	[OADDR] = 7,
+	[OIND] = 7,
+
+	[OMUL] = 6,
+	[ODIV] = 6,
+	[OMOD] = 6,
+	[OLSH] = 6,
+	[ORSH] = 6,
+	[OAND] = 6,
+	[OANDNOT] = 6,
+
+	[OADD] = 5,
+	[OSUB] = 5,
+	[OOR] = 5,
+	[OXOR] = 5,
+
+	[OEQ] = 4,
+	[OLT] = 4,
+	[OLE] = 4,
+	[OGE] = 4,
+	[OGT] = 4,
+	[ONE] = 4,
+	[OCMPSTR] = 4,
+	[OCMPIFACE] = 4,
+
+	[OSEND] = 3,
+	[OANDAND] = 2,
+	[OOROR] = 1,
+
+	// Statements handled by stmtfmt
+	[OAS] = -1,
+	[OAS2] = -1,
+	[OAS2DOTTYPE] = -1,
+	[OAS2FUNC] = -1,
+	[OAS2MAPR] = -1,
+	[OAS2RECV] = -1,
+	[OASOP] = -1,
+	[OBREAK] = -1,
+	[OCASE] = -1,
+	[OCONTINUE] = -1,
+	[ODCL] = -1,
+	[ODCLFIELD] = -1,
+	[ODEFER] = -1,
+	[OEMPTY] = -1,
+	[OFALL] = -1,
+	[OFOR] = -1,
+	[OIF] = -1,
+	[OLABEL] = -1,
+	[OPROC] = -1,
+	[ORANGE] = -1,
+	[ORETURN] = -1,
+	[OSELECT] = -1,
+	[OSWITCH] = -1,
+	[OXCASE] = -1,
+	[OXFALL] = -1,
+
+	[OEND] = 0
+};
+
+static int
+exprfmt(Fmt *f, Node *n, int prec)
+{
+	int nprec;
+	NodeList *l;
+	Type *t;
+
+	while(n && n->implicit)
+		n = n->left;
+
+	if(n == N)
+		return fmtstrcpy(f, "<N>");
+
+	nprec = opprec[n->op];
+	if(n->op == OTYPE && n->sym != S)
+		nprec = 8;
+
+	if(prec > nprec)
+		return fmtprint(f, "(%N)", n);
+
+	switch(n->op) {
+	case OPAREN:
+		return fmtprint(f, "(%N)", n->left);
+
+	case ODDDARG:
+		return fmtprint(f, "... argument");
+
+	case OREGISTER:
+		return fmtprint(f, "%R", n->val.u.reg);
+
+	case OLITERAL:  // this is a bit of a mess
+		if(fmtmode == FErr && n->sym != S)
+			return fmtprint(f, "%S", n->sym);
+		if(n->val.ctype == CTNIL)
+			n = n->orig; // if this node was a nil decorated with at type, print the original naked nil
+		if(n->type != types[n->type->etype] && n->type != idealbool && n->type != idealstring) {
+			// Need parens when type begins with what might
+			// be misinterpreted as a unary operator: * or <-.
+			if(isptr[n->type->etype] || (n->type->etype == TCHAN && n->type->chan == Crecv))
+				return fmtprint(f, "(%T)(%V)", n->type, &n->val);
+			else 
+				return fmtprint(f, "%T(%V)", n->type, &n->val);
+		}
+		return fmtprint(f, "%V", &n->val);
+
+	case ONAME:
+	case OPACK:
+	case ONONAME:
+		return fmtprint(f, "%S", n->sym);
+
+	case OTYPE:
+		if(n->type == T && n->sym != S)
+			return fmtprint(f, "%S", n->sym);
+		return fmtprint(f, "%T", n->type);
+
+	case OTARRAY:
+		if(n->left)
+			return fmtprint(f, "[]%N", n->left);
+		return fmtprint(f, "[]%N", n->right);  // happens before typecheck
+
+	case OTPAREN:
+		return fmtprint(f, "(%N)", n->left);
+
+	case OTMAP:
+		return fmtprint(f, "map[%N]%N", n->left, n->right);
+
+	case OTCHAN:
+		switch(n->etype) {
+		case Crecv:
+			return fmtprint(f, "<-chan %N", n->left);
+		case Csend:
+			return fmtprint(f, "chan<- %N", n->left);
+		default:
+			if(n->left != N && n->left->op == TCHAN && n->left->sym == S && n->left->etype == Crecv)
+				return fmtprint(f, "chan (%N)", n->left);
+			else
+				return fmtprint(f, "chan %N", n->left);
+		}
+
+	case OTSTRUCT:
+		return fmtprint(f, "<struct>");
+
+	case OTINTER:
+		return fmtprint(f, "<inter>");
+
+	case OTFUNC:
+		return fmtprint(f, "<func>");
+
+	case OCLOSURE:
+		if(fmtmode == FErr)
+			return fmtstrcpy(f, "func literal");
+		return fmtprint(f, "%T { %H }", n->type, n->nbody);
+
+	case OCOMPLIT:
+		if(fmtmode == FErr)
+			return fmtstrcpy(f, "composite literal");
+		return fmtprint(f, "%N{ %,H }", n->right, n->list);
+
+	case OPTRLIT:
+		return fmtprint(f, "&%N", n->left);
+
+	case OSTRUCTLIT:
+		if (fmtmode == FExp) {   // requires special handling of field names
+			fmtprint(f, "%T{", n->type);
+			for(l=n->list; l; l=l->next) {
+				// another special case: if n->left is an embedded field of builtin type,
+				// it needs to be non-qualified.  Can't figure that out in %S, so do it here
+				if(l->n->left->type->embedded) {
+					t = l->n->left->type->type;
+					if(t->sym == S)
+						t = t->type;
+					fmtprint(f, " %T:%N", t, l->n->right);
+				} else
+					fmtprint(f, " %hhS:%N", l->n->left->sym, l->n->right);
+
+				if(l->next)
+					fmtstrcpy(f, ",");
+				else
+					fmtstrcpy(f, " ");
+			}
+			return fmtstrcpy(f, "}");
+		}
+		// fallthrough
+
+	case OARRAYLIT:
+	case OMAPLIT:
+		if(fmtmode == FErr)
+			return fmtprint(f, "%T literal", n->type);
+		return fmtprint(f, "%T{ %,H }", n->type, n->list);
+
+	case OKEY:
+		if(n->left && n->right)
+			return fmtprint(f, "%N:%N", n->left, n->right);
+		if(!n->left && n->right)
+			return fmtprint(f, ":%N", n->right);
+		if(n->left && !n->right)
+			return fmtprint(f, "%N:", n->left);
+		return fmtstrcpy(f, ":");
+
+	case OXDOT:
+	case ODOT:
+	case ODOTPTR:
+	case ODOTINTER:
+	case ODOTMETH:
+		exprfmt(f, n->left, nprec);
+		if(n->right == N || n->right->sym == S)
+			fmtstrcpy(f, ".<nil>");
+		return fmtprint(f, ".%hhS", n->right->sym);
+
+	case ODOTTYPE:
+	case ODOTTYPE2:
+		exprfmt(f, n->left, nprec);
+		if(n->right != N)
+			return fmtprint(f, ".(%N)", n->right);
+		return fmtprint(f, ".(%T)", n->type);
+
+	case OINDEX:
+	case OINDEXMAP:
+	case OSLICE:
+	case OSLICESTR:
+	case OSLICEARR:
+		exprfmt(f, n->left, nprec);
+		return fmtprint(f, "[%N]", n->right);
+
+	case OCOPY:
+	case OCOMPLEX:
+		return fmtprint(f, "%#O(%N, %N)", n->op, n->left, n->right);
+
+	case OCONV:
+	case OCONVIFACE:
+	case OCONVNOP:
+	case OARRAYBYTESTR:
+	case OARRAYRUNESTR:
+	case OSTRARRAYBYTE:
+	case OSTRARRAYRUNE:
+	case ORUNESTR:
+		if(n->type == T || n->type->sym == S)
+			return fmtprint(f, "(%T)(%N)", n->type, n->left);
+		if(n->left)
+			return fmtprint(f, "%T(%N)", n->type, n->left);
+		return fmtprint(f, "%T(%,H)", n->type, n->list);
+
+	case OREAL:
+	case OIMAG:
+	case OAPPEND:
+	case OCAP:
+	case OCLOSE:
+	case ODELETE:
+	case OLEN:
+	case OMAKE:
+	case ONEW:
+	case OPANIC:
+	case OPRINT:
+	case OPRINTN:
+		if(n->left)
+			return fmtprint(f, "%#O(%N)", n->op, n->left);
+		if(n->isddd)
+			return fmtprint(f, "%#O(%,H...)", n->op, n->list);
+		return fmtprint(f, "%#O(%,H)", n->op, n->list);
+
+	case OCALL:
+	case OCALLFUNC:
+	case OCALLINTER:
+	case OCALLMETH:
+		exprfmt(f, n->left, nprec);
+		if(n->isddd)
+			return fmtprint(f, "(%,H...)", n->list);
+		return fmtprint(f, "(%,H)", n->list);
+
+	case OMAKEMAP:
+	case OMAKECHAN:
+	case OMAKESLICE:
+		if(n->list) // pre-typecheck
+			return fmtprint(f, "make(%T, %,H)", n->type, n->list);
+		if(n->right)
+			return fmtprint(f, "make(%T, %N, %N)", n->type, n->left, n->right);
+		if(n->left)
+			return fmtprint(f, "make(%T, %N)", n->type, n->left);
+		return fmtprint(f, "make(%T)", n->type);
+
+	// Unary
+	case OPLUS:
+	case OMINUS:
+	case OADDR:
+	case OCOM:
+	case OIND:
+	case ONOT:
+	case ORECV:
+		if(n->left->op == n->op)
+			fmtprint(f, "%#O ", n->op);
+		else
+			fmtprint(f, "%#O", n->op);
+		return exprfmt(f, n->left, nprec+1);
+
+	// Binary
+	case OADD:
+	case OADDSTR:
+	case OAND:
+	case OANDAND:
+	case OANDNOT:
+	case ODIV:
+	case OEQ:
+	case OGE:
+	case OGT:
+	case OLE:
+	case OLT:
+	case OLSH:
+	case OMOD:
+	case OMUL:
+	case ONE:
+	case OOR:
+	case OOROR:
+	case ORSH:
+	case OSEND:
+	case OSUB:
+	case OXOR:
+		exprfmt(f, n->left, nprec);
+		fmtprint(f, " %#O ", n->op);
+		exprfmt(f, n->right, nprec+1);
+		return 0;
+
+	case OCMPSTR:
+	case OCMPIFACE:
+		exprfmt(f, n->left, nprec);
+		fmtprint(f, " %#O ", n->etype);
+		exprfmt(f, n->right, nprec+1);
+		return 0;
+	}
+
+	return fmtprint(f, "<node %O>", n->op);
+}
+
+static int
+nodefmt(Fmt *f, Node *n)
+{
+	Type *t;
+
+	t = n->type;
+	if(n->orig == N) {
+		n->orig = n;
+		fatal("node with no orig %N", n);
+	}
+
+	// we almost always want the original, except in export mode for literals
+	// this saves the importer some work, and avoids us having to redo some
+	// special casing for package unsafe
+	if(fmtmode != FExp || n->op != OLITERAL)
+		n = n->orig;
+
+	if(f->flags&FmtLong && t != T) {
+		if(t->etype == TNIL)
+			return fmtprint(f, "nil");
+		else
+			return fmtprint(f, "%N (type %T)", n, t);
+	}
+
+	// TODO inlining produces expressions with ninits. we can't print these yet.
+
+	if(opprec[n->op] < 0)
+		return stmtfmt(f, n);
+
+	return exprfmt(f, n, 0);
+}
+
+static int dumpdepth;
+
+static void
+indent(Fmt *fp)
+{
+	int i;
+
+	fmtstrcpy(fp, "\n");
+	for(i = 0; i < dumpdepth; ++i)
+		fmtstrcpy(fp, ".   ");
+}
+
+static int
+nodedump(Fmt *fp, Node *n)
+{
+	int recur;
+
+	if(n == N)
+		return 0;
+
+	recur = !(fp->flags&FmtShort);
+
+	if(recur) {
+		indent(fp);
+		if(dumpdepth > 10)
+			return fmtstrcpy(fp, "...");
+
+		if(n->ninit != nil) {
+			fmtprint(fp, "%O-init%H", n->op, n->ninit);
+			indent(fp);
+		}
+	}
+
+//	fmtprint(fp, "[%p]", n);
+
+	switch(n->op) {
+	default:
+		fmtprint(fp, "%O%J", n->op, n);
+		break;
+	case OREGISTER:
+		fmtprint(fp, "%O-%R%J", n->op, n->val.u.reg, n);
+		break;
+	case OLITERAL:
+		fmtprint(fp, "%O-%V%J", n->op, &n->val, n);
+		break;
+	case ONAME:
+	case ONONAME:
+		if(n->sym != S)
+			fmtprint(fp, "%O-%S%J", n->op, n->sym, n);
+		else
+			fmtprint(fp, "%O%J", n->op, n);
+		break;
+	case OASOP:
+		fmtprint(fp, "%O-%O%J", n->op, n->etype, n);
+		break;
+	case OTYPE:
+		fmtprint(fp, "%O %S type=%T", n->op, n->sym, n->type);
+		if(recur && n->type == T && n->ntype) {
+			indent(fp);
+			fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
+		}
+		break;
+	}
+
+	if(n->sym != S && n->op != ONAME)
+		fmtprint(fp, " %S G%d", n->sym, n->vargen);
+
+	if(n->type != T)
+		fmtprint(fp, " %T", n->type);
+
+	if(recur) {
+		if(n->left)
+			fmtprint(fp, "%N", n->left);
+		if(n->right)
+			fmtprint(fp, "%N", n->right);
+		if(n->list) {
+			indent(fp);
+			fmtprint(fp, "%O-list%H", n->op, n->list);
+		}
+		if(n->rlist) {
+			indent(fp);
+			fmtprint(fp, "%O-rlist%H", n->op, n->rlist);
+		}
+		if(n->ntest) {
+			indent(fp);
+			fmtprint(fp, "%O-test%N", n->op, n->ntest);
+		}
+		if(n->nbody) {
+			indent(fp);
+			fmtprint(fp, "%O-body%H", n->op, n->nbody);
+		}
+		if(n->nelse) {
+			indent(fp);
+			fmtprint(fp, "%O-else%H", n->op, n->nelse);
+		}
+		if(n->nincr) {
+			indent(fp);
+			fmtprint(fp, "%O-incr%N", n->op, n->nincr);
+		}
+	}
+
+	return 0;
+}
+
+// Fmt "%S": syms
+// Flags:  "%hS" suppresses qualifying with package
+static int
+Sconv(Fmt *fp)
+{
+	Sym *s;
+	int r, sm;
+	unsigned long sf;
+
+	s = va_arg(fp->args, Sym*);
+	if(s == S)
+		return fmtstrcpy(fp, "<S>");
+
+	if(s->name && s->name[0] == '_' && s->name[1] == '\0')
+		return fmtstrcpy(fp, "_");
+
+	sf = fp->flags;
+	sm = setfmode(&fp->flags);
+	r = symfmt(fp, s);
+	fp->flags = sf;
+	fmtmode = sm;
+	return r;
+}
+
+// Fmt "%T": types.
+// Flags: 'l' print definition, not name
+//	  'h' omit 'func' and receiver from function types, short type names
+//	  'u' package name, not prefix (FTypeId mode, sticky)
+static int
+Tconv(Fmt *fp)
+{
+	Type *t;
+	int r, sm;
+	unsigned long sf;
+
+	t = va_arg(fp->args, Type*);
+	if(t == T)
+		return fmtstrcpy(fp, "<T>");
+
+	if(t->trecur > 4)
+		return fmtstrcpy(fp, "<...>");
+
+	t->trecur++;
+	sf = fp->flags;
+	sm = setfmode(&fp->flags);
+
+	if(fmtmode == FTypeId && (sf&FmtUnsigned))
+		fmtpkgpfx++;
+	if(fmtpkgpfx)
+		fp->flags |= FmtUnsigned;
+
+	r = typefmt(fp, t);
+
+	if(fmtmode == FTypeId && (sf&FmtUnsigned))
+		fmtpkgpfx--;
+
+	fp->flags = sf;
+	fmtmode = sm;
+	t->trecur--;
+	return r;
+}
+
+// Fmt '%N': Nodes.
+// Flags: 'l' suffix with "(type %T)" where possible
+//	  '+h' in debug mode, don't recurse, no multiline output
+static int
+Nconv(Fmt *fp)
+{
+	Node *n;
+	int r, sm;
+	unsigned long sf;
+
+	n = va_arg(fp->args, Node*);
+	if(n == N)
+		return fmtstrcpy(fp, "<N>");
+	sf = fp->flags;
+	sm = setfmode(&fp->flags);
+
+	r = -1;
+	switch(fmtmode) {
+	case FErr:
+	case FExp:
+		r = nodefmt(fp, n);
+		break;
+	case FDbg:
+		dumpdepth++;
+		r = nodedump(fp, n);
+		dumpdepth--;
+		break;
+	default:
+		fatal("unhandled %%N mode");
+	}
+
+	fp->flags = sf;
+	fmtmode = sm;
+	return r;
+}
+
+// Fmt '%H': NodeList.
+// Flags: all those of %N plus ',': separate with comma's instead of semicolons.
+static int
+Hconv(Fmt *fp)
+{
+	NodeList *l;
+	int r, sm;
+	unsigned long sf;
+	char *sep;
+
+	l = va_arg(fp->args, NodeList*);
+
+	if(l == nil && fmtmode == FDbg)
+		return fmtstrcpy(fp, "<nil>");
+
+	sf = fp->flags;
+	sm = setfmode(&fp->flags);
+	r = 0;
+	sep = "; ";
+	if(fmtmode == FDbg)
+		sep = "\n";
+	else if(fp->flags & FmtComma)
+		sep = ", ";
+
+	for(;l; l=l->next) {
+		r += fmtprint(fp, "%N", l->n);
+		if(l->next)
+			r += fmtstrcpy(fp, sep);
+	}
+
+	fp->flags = sf;
+	fmtmode = sm;
+	return r;
+}
+
+void
+fmtinstallgo(void)
+{
+	fmtmode = FErr;
+	fmtinstall('E', Econv);		// etype opcodes
+	fmtinstall('J', Jconv);		// all the node flags
+	fmtinstall('H', Hconv);		// node lists
+	fmtinstall('L', Lconv);		// line number
+	fmtinstall('N', Nconv);		// node pointer
+	fmtinstall('O', Oconv);		// node opcodes
+	fmtinstall('S', Sconv);		// sym pointer
+	fmtinstall('T', Tconv);		// type pointer
+	fmtinstall('V', Vconv);		// val pointer
+	fmtinstall('Z', Zconv);		// escaped string
+
+	// These are in mparith1.c
+	fmtinstall('B', Bconv);	// big numbers
+	fmtinstall('F', Fconv);	// big float numbers
+
+}
+
+void
+dumplist(char *s, NodeList *l)
+{
+	print("%s\n%+H\n", s, l);
+}
+
+void
+dump(char *s, Node *n)
+{
+	print("%s [%p]\n%+N\n", s, n, n);
+}
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index a818dbc..694a10a 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -54,7 +54,7 @@ addrescapes(Node *n)
 		if(n->class == PAUTO && n->esc == EscNever)
 			break;
 
-		if(debug['s'] && n->esc != EscUnknown)
+		if(debug['N'] && n->esc != EscUnknown)
 			fatal("without escape analysis, only PAUTO's should have esc: %N", n);
 
 		switch(n->class) {
@@ -91,10 +91,10 @@ addrescapes(Node *n)
 			snprint(buf, sizeof buf, "&%S", n->sym);
 			n->heapaddr->sym = lookup(buf);
 			n->heapaddr->orig->sym = n->heapaddr->sym;
-			if(!debug['s'])
+			if(!debug['N'])
 				n->esc = EscHeap;
 			if(debug['m'])
-				print("%L: moved to heap: %hN\n", n->lineno, n);
+				print("%L: moved to heap: %N\n", n->lineno, n);
 			curfn = oldfn;
 			break;
 		}
@@ -805,6 +805,7 @@ tempname(Node *nn, Type *t)
 	s = lookup(namebuf);
 	n = nod(ONAME, N, N);
 	n->sym = s;
+	s->def = n;
 	n->type = t;
 	n->class = PAUTO;
 	n->addable = 1;
@@ -825,5 +826,6 @@ temp(Type *t)
 	
 	n = nod(OXXX, N, N);
 	tempname(n, t);
+	n->sym->def->used = 1;
 	return n;
 }
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index f727994..9584bb7 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -16,6 +16,12 @@
 
 #undef	BUFSIZ
 
+// The parser's maximum stack size.
+// We have to use a #define macro here since yacc
+// or bison will check for its definition and use
+// a potentially smaller value if it is undefined.
+#define YYMAXDEPTH 500
+
 enum
 {
 	NHUNK		= 50000,
@@ -23,7 +29,6 @@ enum
 	NSYMB		= 500,
 	NHASH		= 1024,
 	STRINGSZ	= 200,
-	YYMAXDEPTH	= 500,
 	MAXALIGN	= 7,
 	UINF		= 100,
 	HISTSZ		= 10,
@@ -32,23 +37,30 @@ enum
 
 	AUNK		= 100,
 
-	// these values are known by runtime
+	// These values are known by runtime.
+	// The MEMx and NOEQx values must run in parallel.  See algtype.
 	AMEM		= 0,
-	ANOEQ,
-	ASTRING,
-	AINTER,
-	ANILINTER,
-	ASLICE,
+	AMEM0,
 	AMEM8,
 	AMEM16,
 	AMEM32,
 	AMEM64,
 	AMEM128,
+	ANOEQ,
+	ANOEQ0,
 	ANOEQ8,
 	ANOEQ16,
 	ANOEQ32,
 	ANOEQ64,
 	ANOEQ128,
+	ASTRING,
+	AINTER,
+	ANILINTER,
+	ASLICE,
+	AFLOAT32,
+	AFLOAT64,
+	ACPLX64,
+	ACPLX128,
 
 	BADWIDTH	= -1000000000,
 };
@@ -67,33 +79,6 @@ struct	Strlit
 	char	s[3];	// variable
 };
 
-/*
- * note this is the runtime representation
- * of hashmap iterator. it is probably
- * insafe to use it this way, but it puts
- * all the changes in one place.
- * only flag is referenced from go.
- * actual placement does not matter as long
- * as the size is >= actual size.
- */
-typedef	struct	Hiter	Hiter;
-struct	Hiter
-{
-	uchar	data[8];		// return val from next
-	int32	elemsize;		// size of elements in table */
-	int32	changes;		// number of changes observed last time */
-	int32	i;			// stack pointer in subtable_state */
-	uchar	last[8];		// last hash value returned */
-	uchar	h[8];			// the hash table */
-	struct
-	{
-		uchar	sub[8];		// pointer into subtable */
-		uchar	start[8];	// pointer into start of subtable */
-		uchar	end[8];		// pointer into end of subtable */
-		uchar	pad[8];
-	} sub[4];
-};
-
 enum
 {
 	Mpscale	= 29,		// safely smaller than bits in a long
@@ -135,7 +120,7 @@ struct	Val
 	{
 		short	reg;		// OREGISTER
 		short	bval;		// bool value CTBOOL
-		Mpint*	xval;		// int CTINT
+		Mpint*	xval;		// int CTINT, rune CTRUNE
 		Mpflt*	fval;		// float CTFLT
 		Mpcplx*	cval;		// float CTCPLX
 		Strlit*	sval;		// string CTSTR
@@ -157,12 +142,12 @@ struct	Type
 	uchar	printed;
 	uchar	embedded;	// TFIELD embedded type
 	uchar	siggen;
-	uchar	funarg;
+	uchar	funarg;		// on TSTRUCT and TFIELD
 	uchar	copyany;
 	uchar	local;		// created in this file
 	uchar	deferwidth;
 	uchar	broke;
-	uchar	isddd;	// TFIELD is ... argument
+	uchar	isddd;		// TFIELD is ... argument
 	uchar	align;
 
 	Node*	nod;		// canonical OTYPE node
@@ -266,6 +251,8 @@ struct	Node
 	uchar	isddd;
 	uchar	readonly;
 	uchar	implicit;	// don't show in printout
+	uchar	addrtaken;	// address taken, even if not moved to heap
+	uchar	dupok;	// duplicate definitions ok (for func)
 
 	// most nodes
 	Type*	type;
@@ -279,6 +266,7 @@ struct	Node
 	NodeList*	exit;
 	NodeList*	cvars;	// closure params
 	NodeList*	dcl;	// autodcl for this func/closure
+	NodeList*	inl;	// copy of the body for use in inlining
 
 	// OLITERAL/OREGISTER
 	Val	val;
@@ -299,6 +287,9 @@ struct	Node
 	Node*	outer;	// outer PPARAMREF in nested closure
 	Node*	closure;	// ONAME/PHEAP <-> ONAME/PPARAMREF
 
+	// ONAME substitute while inlining
+	Node* inlvar;
+
 	// OPACK
 	Pkg*	pkg;
 	
@@ -346,9 +337,9 @@ struct	NodeList
 
 enum
 {
-	SymExport	= 1<<0,
+	SymExport	= 1<<0,	// to be exported
 	SymPackage	= 1<<1,
-	SymExported	= 1<<2,
+	SymExported	= 1<<2,	// already written out by export
 	SymUniq		= 1<<3,
 	SymSiggen	= 1<<4,
 };
@@ -375,10 +366,10 @@ EXTERN	Sym*	dclstack;
 
 struct	Pkg
 {
-	char*	name;
-	Strlit*	path;
+	char*	name;		// package name
+	Strlit*	path;		// string literal used in import statement
 	Sym*	pathsym;
-	char*	prefix;
+	char*	prefix;		// escaped path for use in symbol table
 	Pkg*	link;
 	char	exported;	// import line written in export data
 	char	direct;	// imported directly
@@ -422,17 +413,19 @@ enum
 	OAPPEND,
 	OARRAYBYTESTR, OARRAYRUNESTR,
 	OSTRARRAYBYTE, OSTRARRAYRUNE,
-	OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE, OASOP,
+	OAS, OAS2, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE,
+	OASOP,
 	OBAD,
 	OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
 	OCAP,
 	OCLOSE,
 	OCLOSURE,
 	OCMPIFACE, OCMPSTR,
-	OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
+	OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT, OPTRLIT,
 	OCONV, OCONVIFACE, OCONVNOP,
 	OCOPY,
 	ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE,
+	ODELETE,
 	ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
 	ODOTTYPE,
 	ODOTTYPE2,
@@ -490,6 +483,7 @@ enum
 	// misc
 	ODDD,
 	ODDDARG,
+	OINLCALL,	// intermediary representation of an inlined call
 
 	// for back ends
 	OCMP, ODEC, OEXTEND, OINC, OREGISTER, OINDREG,
@@ -546,6 +540,7 @@ enum
 	CTxxx,
 
 	CTINT,
+	CTRUNE,
 	CTFLT,
 	CTCPLX,
 	CTSTR,
@@ -779,6 +774,9 @@ EXTERN	Idir*	idirs;
 EXTERN	Type*	types[NTYPE];
 EXTERN	Type*	idealstring;
 EXTERN	Type*	idealbool;
+EXTERN	Type*	bytetype;
+EXTERN	Type*	runetype;
+EXTERN	Type*	errortype;
 EXTERN	uchar	simtype[NTYPE];
 EXTERN	uchar	isptr[NTYPE];
 EXTERN	uchar	isforw[NTYPE];
@@ -810,7 +808,7 @@ EXTERN	NodeList*	xtop;
 EXTERN	NodeList*	externdcl;
 EXTERN	NodeList*	closures;
 EXTERN	NodeList*	exportlist;
-EXTERN	NodeList*	typelist;
+EXTERN	NodeList*	importlist;	// imported functions and methods with inlinable bodies
 EXTERN	int	dclcontext;		// PEXTERN/PAUTO
 EXTERN	int	incannedimport;
 EXTERN	int	statuniqgen;		// name generator for static temps
@@ -834,18 +832,13 @@ EXTERN	Node*	nblank;
 
 extern	int	thechar;
 extern	char*	thestring;
+
 EXTERN	char*	hunk;
 EXTERN	int32	nhunk;
 EXTERN	int32	thunk;
 
-EXTERN	int	exporting;
-EXTERN	int	erroring;
-EXTERN	int	noargnames;
-
 EXTERN	int	funcdepth;
 EXTERN	int	typecheckok;
-EXTERN	int	packagequotes;
-EXTERN	int	longsymnames;
 EXTERN	int	compiling_runtime;
 
 /*
@@ -930,7 +923,6 @@ void	colasdefn(NodeList *left, Node *defn);
 NodeList*	constiter(NodeList *vl, Node *t, NodeList *cl);
 Node*	dclname(Sym *s);
 void	declare(Node *n, int ctxt);
-Type*	dostruct(NodeList *l, int et);
 void	dumpdcl(char *st);
 Node*	embedded(Sym *s);
 Node*	fakethis(void);
@@ -951,9 +943,10 @@ void	popdcl(void);
 void	poptodcl(void);
 void	redeclare(Sym *s, char *where);
 void	testdclstack(void);
+Type*	tointerface(NodeList *l);
+Type*	tostruct(NodeList *l);
 Node*	typedcl0(Sym *s);
 Node*	typedcl1(Node *n, Node *t, int local);
-void	typedcl2(Type *pt, Type *t);
 Node*	typenod(Type *t);
 NodeList*	variter(NodeList *vl, Node *t, NodeList *el);
 
@@ -969,14 +962,21 @@ void	autoexport(Node *n, int ctxt);
 void	dumpexport(void);
 int	exportname(char *s);
 void	exportsym(Node *n);
-void	importconst(Sym *s, Type *t, Node *n);
-void	importmethod(Sym *s, Type *t);
-Sym*	importsym(Sym *s, int op);
-void	importtype(Type *pt, Type *t);
-void	importvar(Sym *s, Type *t, int ctxt);
+void    importconst(Sym *s, Type *t, Node *n);
+void	importimport(Sym *s, Strlit *z);
+Sym*    importsym(Sym *s, int op);
+void    importtype(Type *pt, Type *t);
+void    importvar(Sym *s, Type *t);
 Type*	pkgtype(Sym *s);
 
 /*
+ *	fmt.c
+ */
+void	fmtinstallgo(void);
+void	dump(char *s, Node *n);
+void	dumplist(char *s, NodeList *l);
+
+/*
  *	gen.c
  */
 void	addrescapes(Node *n);
@@ -995,7 +995,14 @@ Node*	temp(Type*);
  *	init.c
  */
 void	fninit(NodeList *n);
-Node*	renameinit(Node *n);
+Sym*	renameinit(void);
+
+/*
+ *	inl.c
+ */
+void	caninl(Node *fn);
+void	inlcalls(Node *fn);
+void	typecheckinl(Node *fn);
 
 /*
  *	lex.c
@@ -1003,6 +1010,7 @@ Node*	renameinit(Node *n);
 void	cannedimports(char *file, char *cp);
 void	importfile(Val *f, int line);
 char*	lexname(int lex);
+char*	expstring(void);
 void	mkpackage(char* pkgname);
 void	unimportfile(void);
 int32	yylex(void);
@@ -1085,10 +1093,9 @@ void	ieeedtod(uint64 *ieee, double native);
 Sym*	stringsym(char*, int);
 
 /*
- *	print.c
+ *	order.c
  */
-void	exprfmt(Fmt *f, Node *n, int prec);
-void	exprlistfmt(Fmt *f, NodeList *l);
+void	order(Node *fn);
 
 /*
  *	range.c
@@ -1103,6 +1110,7 @@ void	dumptypestructs(void);
 Type*	methodfunc(Type *f, Type*);
 Node*	typename(Type *t);
 Sym*	typesym(Type *t);
+Sym*	typesymprefix(char *prefix, Type *t);
 int	haspointers(Type *t);
 
 /*
@@ -1123,19 +1131,12 @@ int	stataddr(Node *nam, Node *n);
 /*
  *	subr.c
  */
-int	Econv(Fmt *fp);
-int	Jconv(Fmt *fp);
-int	Lconv(Fmt *fp);
-int	Nconv(Fmt *fp);
-int	Oconv(Fmt *fp);
-int	Sconv(Fmt *fp);
-int	Tconv(Fmt *fp);
-int	Tpretty(Fmt *fp, Type *t);
-int	Zconv(Fmt *fp);
 Node*	adddot(Node *n);
 int	adddot1(Sym *s, Type *t, int d, Type **save, int ignorecase);
+void	addinit(Node**, NodeList*);
 Type*	aindex(Node *b, Type *t);
 int	algtype(Type *t);
+int	algtype1(Type *t, Type **bad);
 void	argtype(Node *on, Type *t);
 Node*	assignconv(Node *n, Type *t, char *context);
 int	assignop(Type *src, Type *dst, char **why);
@@ -1144,10 +1145,9 @@ int	brcom(int a);
 int	brrev(int a);
 NodeList*	concat(NodeList *a, NodeList *b);
 int	convertop(Type *src, Type *dst, char **why);
+Node*	copyexpr(Node*, Type*, NodeList**);
 int	count(NodeList *l);
 int	cplxsubtype(int et);
-void	dump(char *s, Node *n);
-void	dumplist(char *s, NodeList *l);
 int	eqtype(Type *t1, Type *t2);
 int	eqtypenoname(Type *t1, Type *t2);
 void	errorexit(void);
@@ -1158,6 +1158,8 @@ void	frame(int context);
 Type*	funcfirst(Iter *s, Type *t);
 Type*	funcnext(Iter *s);
 void	genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface);
+void	genhash(Sym *sym, Type *t);
+void	geneq(Sym *sym, Type *t);
 Type**	getinarg(Type *t);
 Type*	getinargx(Type *t);
 Type**	getoutarg(Type *t);
@@ -1237,7 +1239,6 @@ void	walkswitch(Node *sw);
 /*
  *	typecheck.c
  */
-int	exportassignok(Type *t, char *desc);
 int	islvalue(Node *n);
 Node*	typecheck(Node **np, int top);
 void	typechecklist(NodeList *l, int top);
@@ -1250,6 +1251,7 @@ void	queuemethod(Node *n);
 /*
  *	unsafe.c
  */
+int	isunsafebuiltin(Node *n);
 Node*	unsafenmagic(Node *n);
 
 /*
@@ -1266,6 +1268,7 @@ void	walkexprlist(NodeList *l, NodeList **init);
 void	walkexprlistsafe(NodeList *l, NodeList **init);
 void	walkstmt(Node **np);
 void	walkstmtlist(NodeList *l);
+Node*	conv(Node*, Type*);
 
 /*
  *	arch-specific ggen.c/gsubr.c/gobj.c/pgen.c
@@ -1335,11 +1338,16 @@ void	zname(Biobuf *b, Sym *s, int t);
 #pragma	varargck	type	"D"	Addr*
 #pragma	varargck	type	"lD"	Addr*
 #pragma	varargck	type	"E"	int
+#pragma	varargck	type	"E"	uint
 #pragma	varargck	type	"F"	Mpflt*
+#pragma	varargck	type	"H"	NodeList*
 #pragma	varargck	type	"J"	Node*
+#pragma	varargck	type	"lL"	int
+#pragma	varargck	type	"lL"	uint
 #pragma	varargck	type	"L"	int
 #pragma	varargck	type	"L"	uint
 #pragma	varargck	type	"N"	Node*
+#pragma	varargck	type	"lN"	Node*
 #pragma	varargck	type	"O"	uint
 #pragma	varargck	type	"P"	Prog*
 #pragma	varargck	type	"Q"	Bits
@@ -1348,5 +1356,6 @@ void	zname(Biobuf *b, Sym *s, int t);
 #pragma	varargck	type	"lS"	Sym*
 #pragma	varargck	type	"T"	Type*
 #pragma	varargck	type	"lT"	Type*
+#pragma	varargck	type	"V"	Val*
 #pragma	varargck	type	"Y"	char*
 #pragma	varargck	type	"Z"	Strlit*
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 0c007f5..de07354 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -31,13 +31,13 @@ static void fixlbrace(int);
 	Type*		type;
 	Sym*		sym;
 	struct	Val	val;
-	int		lint;
+	int		i;
 }
 
 // |sed 's/.*	//' |9 fmt -l1 |sort |9 fmt -l50 | sed 's/^/%xxx		/'
 
 %token	<val>	LLITERAL
-%token	<lint>	LASOP
+%token	<i>	LASOP
 %token	<sym>	LBREAK LCASE LCHAN LCOLAS LCONST LCONTINUE LDDD
 %token	<sym>	LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
 %token	<sym>	LIF LIMPORT LINTERFACE LMAP LNAME
@@ -47,7 +47,7 @@ static void fixlbrace(int);
 %token		LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
 %token		LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
 
-%type	<lint>	lbrace import_here
+%type	<i>	lbrace import_here
 %type	<sym>	sym packname
 %type	<val>	oliteral
 
@@ -56,7 +56,7 @@ static void fixlbrace(int);
 %type	<node>	case caseblock
 %type	<node>	compound_stmt dotname embed expr complitexpr
 %type	<node>	expr_or_type
-%type	<node>	fndcl fnliteral
+%type	<node>	fndcl hidden_fndcl fnliteral
 %type	<node>	for_body for_header for_stmt if_header if_stmt else non_dcl_stmt
 %type	<node>	interfacedcl keyval labelname name
 %type	<node>	name_or_type non_expr_type
@@ -66,7 +66,7 @@ static void fixlbrace(int);
 %type	<node>	pseudocall range_stmt select_stmt
 %type	<node>	simple_stmt
 %type	<node>	switch_stmt uexpr
-%type	<node>	xfndcl typedcl
+%type	<node>	xfndcl typedcl start_complit
 
 %type	<list>	xdcl fnbody fnres loop_body dcl_name_list
 %type	<list>	new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
@@ -78,12 +78,10 @@ static void fixlbrace(int);
 %type	<node>	indcl interfacetype structtype ptrtype
 %type	<node>	recvchantype non_recvchantype othertype fnret_type fntype
 
-%type	<val>	hidden_tag
-
 %type	<sym>	hidden_importsym hidden_pkg_importsym
 
-%type	<node>	hidden_constant hidden_literal hidden_dcl
-%type	<node>	hidden_interfacedcl hidden_structdcl hidden_opt_sym
+%type	<node>	hidden_constant hidden_literal hidden_funarg
+%type	<node>	hidden_interfacedcl hidden_structdcl
 
 %type	<list>	hidden_funres
 %type	<list>	ohidden_funres
@@ -237,7 +235,7 @@ import_here:
 	}
 
 import_package:
-	LPACKAGE sym import_safety ';'
+	LPACKAGE LNAME import_safety ';'
 	{
 		if(importpkg->name == nil) {
 			importpkg->name = $2->name;
@@ -420,18 +418,15 @@ simple_stmt:
 |	expr_list LCOLAS expr_list
 	{
 		if($3->n->op == OTYPESW) {
-			Node *n;
-			
-			n = N;
+			$$ = nod(OTYPESW, N, $3->n->right);
 			if($3->next != nil)
 				yyerror("expr.(type) must be alone in list");
 			if($1->next != nil)
 				yyerror("argument count mismatch: %d = %d", count($1), 1);
 			else if($1->n->op != ONAME && $1->n->op != OTYPE && $1->n->op != ONONAME)
-				yyerror("invalid variable name %#N in type switch", $1->n);
+				yyerror("invalid variable name %N in type switch", $1->n);
 			else
-				n = $1->n;
-			$$ = nod(OTYPESW, n, $3->n->right);
+				$$->left = dclname($1->n->sym);  // it's a colas, so must not re-use an oldname.
 			break;
 		}
 		$$ = colas($1, $3);
@@ -450,7 +445,7 @@ simple_stmt:
 case:
 	LCASE expr_or_type_list ':'
 	{
-		Node *n;
+		Node *n, *nn;
 
 		// will be converted to OCASE
 		// right will point to next case
@@ -460,12 +455,13 @@ case:
 		$$->list = $2;
 		if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
 			// type switch - declare variable
-			n = newname(n->sym);
-			n->used = 1;	// TODO(rsc): better job here
-			declare(n, dclcontext);
-			$$->nname = n;
+			nn = newname(n->sym);
+			declare(nn, dclcontext);
+			$$->nname = nn;
+
+			// keep track of the instances for reporting unused
+			nn->defn = typesw->right;
 		}
-		break;
 	}
 |	LCASE expr_or_type_list '=' expr ':'
 	{
@@ -496,16 +492,18 @@ case:
 	}
 |	LDEFAULT ':'
 	{
-		Node *n;
+		Node *n, *nn;
 
 		markdcl();
 		$$ = nod(OXCASE, N, N);
 		if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
 			// type switch - declare variable
-			n = newname(n->sym);
-			n->used = 1;	// TODO(rsc): better job here
-			declare(n, dclcontext);
-			$$->nname = n;
+			nn = newname(n->sym);
+			declare(nn, dclcontext);
+			$$->nname = nn;
+
+			// keep track of the instances for reporting unused
+			nn->defn = typesw->right;
 		}
 	}
 
@@ -806,7 +804,14 @@ uexpr:
 	}
 |	'&' uexpr
 	{
-		$$ = nod(OADDR, $2, N);
+		if($2->op == OCOMPLIT) {
+			// Special case for &T{...}: turn into (*T){...}.
+			$$ = $2;
+			$$->right = nod(OIND, $$->right, N);
+			$$->right->implicit = 1;
+		} else {
+			$$ = nod(OADDR, $2, N);
+		}
 	}
 |	'+' uexpr
 	{
@@ -895,29 +900,35 @@ pexpr_no_paren:
 		$$ = nod(OCALL, $1, N);
 		$$->list = list1($3);
 	}
-|	comptype lbrace braced_keyval_list '}'
+|	comptype lbrace start_complit braced_keyval_list '}'
 	{
-		// composite expression
-		$$ = nod(OCOMPLIT, N, $1);
-		$$->list = $3;
-		
+		$$ = $3;
+		$$->right = $1;
+		$$->list = $4;
 		fixlbrace($2);
 	}
-|	pexpr_no_paren '{' braced_keyval_list '}'
+|	pexpr_no_paren '{' start_complit braced_keyval_list '}'
 	{
-		// composite expression
-		$$ = nod(OCOMPLIT, N, $1);
-		$$->list = $3;
+		$$ = $3;
+		$$->right = $1;
+		$$->list = $4;
 	}
-|	'(' expr_or_type ')' '{' braced_keyval_list '}'
+|	'(' expr_or_type ')' '{' start_complit braced_keyval_list '}'
 	{
 		yyerror("cannot parenthesize type in composite literal");
-		// composite expression
-		$$ = nod(OCOMPLIT, N, $2);
-		$$->list = $5;
+		$$ = $5;
+		$$->right = $2;
+		$$->list = $6;
 	}
 |	fnliteral
 
+start_complit:
+	{
+		// composite expression.
+		// make node early so we get the right line number.
+		$$ = nod(OCOMPLIT, N, N);
+	}
+
 keyval:
 	expr ':' complitexpr
 	{
@@ -926,10 +937,10 @@ keyval:
 
 complitexpr:
 	expr
-|	'{' braced_keyval_list '}'
+|	'{' start_complit braced_keyval_list '}'
 	{
-		$$ = nod(OCOMPLIT, N, N);
-		$$->list = $2;
+		$$ = $2;
+		$$->list = $3;
 	}
 
 pexpr:
@@ -993,6 +1004,26 @@ onew_name:
 
 sym:
 	LNAME
+	{
+		$$ = $1;
+		// during imports, unqualified non-exported identifiers are from builtinpkg
+		if(importpkg != nil && !exportname($1->name))
+			$$ = pkglookup($1->name, builtinpkg);
+	}
+|	hidden_importsym
+|	'?'
+	{
+		$$ = S;
+	}
+
+hidden_importsym:
+	'@' LLITERAL '.' LNAME
+	{
+		if($2.u.sval->len == 0)
+			$$ = pkglookup($4->name, importpkg);
+		else
+			$$ = pkglookup($4->name, mkpkg($2.u.sval));
+	}
 
 name:
 	sym	%prec NotParen
@@ -1165,38 +1196,43 @@ xfndcl:
 	}
 
 fndcl:
-	dcl_name '(' oarg_type_list_ocomma ')' fnres
+	sym '(' oarg_type_list_ocomma ')' fnres
 	{
-		Node *n;
+		Node *t;
 
+		$$ = N;
 		$3 = checkarglist($3, 1);
-		$$ = nod(ODCLFUNC, N, N);
-		$$->nname = $1;
-		n = nod(OTFUNC, N, N);
-		n->list = $3;
-		n->rlist = $5;
-		if(strcmp($1->sym->name, "init") == 0) {
-			$$->nname = renameinit($1);
+
+		if(strcmp($1->name, "init") == 0) {
+			$1 = renameinit();
 			if($3 != nil || $5 != nil)
 				yyerror("func init must have no arguments and no return values");
 		}
-		if(strcmp(localpkg->name, "main") == 0 && strcmp($1->sym->name, "main") == 0) {
+		if(strcmp(localpkg->name, "main") == 0 && strcmp($1->name, "main") == 0) {
 			if($3 != nil || $5 != nil)
 				yyerror("func main must have no arguments and no return values");
 		}
-		// TODO: check if nname already has an ntype
-		$$->nname->ntype = n;
+
+		t = nod(OTFUNC, N, N);
+		t->list = $3;
+		t->rlist = $5;
+
+		$$ = nod(ODCLFUNC, N, N);
+		$$->nname = newname($1);
+		$$->nname->defn = $$;
+		$$->nname->ntype = t;		// TODO: check if nname already has an ntype
+		declare($$->nname, PFUNC);
+
 		funchdr($$);
 	}
 |	'(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
 	{
 		Node *rcvr, *t;
-		Node *name;
-		
-		name = newname($4);
+
+		$$ = N;
 		$2 = checkarglist($2, 0);
 		$6 = checkarglist($6, 1);
-		$$ = N;
+
 		if($2 == nil) {
 			yyerror("method has no receiver");
 			break;
@@ -1213,15 +1249,59 @@ fndcl:
 		if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN))
 			yyerror("cannot parenthesize receiver type");
 
-		$$ = nod(ODCLFUNC, N, N);
-		$$->nname = methodname1(name, rcvr->right);
 		t = nod(OTFUNC, rcvr, N);
 		t->list = $6;
 		t->rlist = $8;
+
+		$$ = nod(ODCLFUNC, N, N);
+		$$->shortname = newname($4);
+		$$->nname = methodname1($$->shortname, rcvr->right);
+		$$->nname->defn = $$;
 		$$->nname->ntype = t;
-		$$->shortname = name;
+		declare($$->nname, PFUNC);
+
+		funchdr($$);
+	}
+
+hidden_fndcl:
+	hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres
+	{
+		Sym *s;
+		Type *t;
+
+		$$ = N;
+
+		s = $1;
+		t = functype(N, $3, $5);
+
+		importsym(s, ONAME);
+		if(s->def != N && s->def->op == ONAME) {
+			if(eqtype(t, s->def->type))
+				break;
+			yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t);
+		}
+
+		$$ = newname(s);
+		$$->type = t;
+		declare($$, PFUNC);
+
 		funchdr($$);
 	}
+|	'(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
+	{
+		$$ = methodname1(newname($4), $2->n->right); 
+		$$->type = functype($2->n, $6, $8);
+
+		checkwidth($$->type);
+		addmethod($4, $$->type, 0);
+		funchdr($$);
+		
+		// inl.c's inlnode in on a dotmeth node expects to find the inlineable body as
+		// (dotmeth's type)->nname->inl, and dotmeth's type has been pulled
+		// out by typecheck's lookdot as this $$->ttype.  So by providing
+		// this back link here we avoid special casing there.
+		$$->type->nname = $$;
+	}
 
 fntype:
 	LFUNC '(' oarg_type_list_ocomma ')' fnres
@@ -1538,6 +1618,18 @@ non_dcl_stmt:
 	{
 		$$ = nod(ORETURN, N, N);
 		$$->list = $2;
+		if($$->list == nil && curfn != N) {
+			NodeList *l;
+
+			for(l=curfn->dcl; l; l=l->next) {
+				if(l->n->class == PPARAM)
+					continue;
+				if(l->n->class != PPARAMOUT)
+					break;
+				if(l->n->sym->def != l->n)
+					yyerror("%s is shadowed during return", l->n->sym->name);
+			}
+		}
 	}
 
 stmt_list:
@@ -1676,31 +1768,16 @@ oliteral:
 |	LLITERAL
 
 /*
- * import syntax from header of
- * an output package
+ * import syntax from package header
  */
 hidden_import:
-	LIMPORT sym LLITERAL ';'
+	LIMPORT LNAME LLITERAL ';'
 	{
-		// Informational: record package name
-		// associated with import path, for use in
-		// human-readable messages.
-		Pkg *p;
-
-		p = mkpkg($3.u.sval);
-		if(p->name == nil) {
-			p->name = $2->name;
-			pkglookup($2->name, nil)->npkg++;
-		} else if(strcmp(p->name, $2->name) != 0)
-			yyerror("conflicting names %s and %s for package \"%Z\"", p->name, $2->name, p->path);
-		if(!incannedimport && myimportpath != nil && strcmp($3.u.sval->s, myimportpath) == 0) {
-			yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, $3.u.sval);
-			errorexit();
-		}
+		importimport($2, $3.u.sval);
 	}
 |	LVAR hidden_pkg_importsym hidden_type ';'
 	{
-		importvar($2, $3, PEXTERN);
+		importvar($2, $3);
 	}
 |	LCONST hidden_pkg_importsym '=' hidden_constant ';'
 	{
@@ -1714,17 +1791,28 @@ hidden_import:
 	{
 		importtype($2, $3);
 	}
-|	LFUNC hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres ';'
+|	LFUNC hidden_fndcl fnbody ';'
 	{
-		importvar($2, functype(N, $4, $6), PFUNC);
+		if($2 == N)
+			break;
+
+		$2->inl = $3;
+
+		funcbody($2);
+		importlist = list(importlist, $2);
+
+		if(debug['E']) {
+			print("import [%Z] func %lN \n", importpkg->path, $2);
+			if(debug['l'] > 2 && $2->inl)
+				print("inl body:%+H\n", $2->inl);
+		}
 	}
-|	LFUNC '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres ';'
+
+hidden_pkg_importsym:
+	hidden_importsym
 	{
-		if($3->next != nil || $3->n->op != ODCLFIELD) {
-			yyerror("bad receiver in method");
-			YYERROR;
-		}
-		importmethod($5, functype($3->n, $7, $9));
+		$$ = $1;
+		structpkg = $$->pkg;
 	}
 
 hidden_pkgtype:
@@ -1734,6 +1822,10 @@ hidden_pkgtype:
 		importsym($1, OTYPE);
 	}
 
+/*
+ *  importing types
+ */
+
 hidden_type:
 	hidden_type_misc
 |	hidden_type_recv_chan
@@ -1772,11 +1864,11 @@ hidden_type_misc:
 	}
 |	LSTRUCT '{' ohidden_structdcl_list '}'
 	{
-		$$ = dostruct($3, TSTRUCT);
+		$$ = tostruct($3);
 	}
 |	LINTERFACE '{' ohidden_interfacedcl_list '}'
 	{
-		$$ = dostruct($3, TINTER);
+		$$ = tointerface($3);
 	}
 |	'*' hidden_type
 	{
@@ -1815,61 +1907,45 @@ hidden_type_func:
 		$$ = functype(nil, $3, $5);
 	}
 
-hidden_opt_sym:
-	sym
-	{
-		$$ = newname($1);
-	}
-|	'?'
-	{
-		$$ = N;
-	}
-
-hidden_dcl:
-	hidden_opt_sym hidden_type hidden_tag
+hidden_funarg:
+	sym hidden_type oliteral
 	{
-		$$ = nod(ODCLFIELD, $1, typenod($2));
+		$$ = nod(ODCLFIELD, N, typenod($2));
+		if($1)
+			$$->left = newname($1);
 		$$->val = $3;
 	}
-|	hidden_opt_sym LDDD hidden_type hidden_tag
+|	sym LDDD hidden_type oliteral
 	{
 		Type *t;
-		
+	
 		t = typ(TARRAY);
 		t->bound = -1;
 		t->type = $3;
-		$$ = nod(ODCLFIELD, $1, typenod(t));
+
+		$$ = nod(ODCLFIELD, N, typenod(t));
+		if($1)
+			$$->left = newname($1);
 		$$->isddd = 1;
 		$$->val = $4;
 	}
 
 hidden_structdcl:
-	sym hidden_type hidden_tag
-	{
-		$$ = nod(ODCLFIELD, newname($1), typenod($2));
-		$$->val = $3;
-	}
-|	'?' hidden_type hidden_tag
+	sym hidden_type oliteral
 	{
 		Sym *s;
 
-		s = $2->sym;
-		if(s == S && isptr[$2->etype])
-			s = $2->type->sym;
-		if(s && s->pkg == builtinpkg)
-			s = lookup(s->name);
-		$$ = embedded(s);
-		$$->right = typenod($2);
-		$$->val = $3;
-	}
-
-hidden_tag:
-	{
-		$$.ctype = CTxxx;
-	}
-|	':' LLITERAL	// extra colon avoids conflict with "" looking like beginning of "".typename
-	{
-		$$ = $2;
+		if($1 != S) {
+			$$ = nod(ODCLFIELD, newname($1), typenod($2));
+			$$->val = $3;
+		} else {
+			s = $2->sym;
+			if(s == S && isptr[$2->etype])
+				s = $2->type->sym;
+			$$ = embedded(s);
+			$$->right = typenod($2);
+			$$->val = $3;
+		}
 	}
 
 hidden_interfacedcl:
@@ -1877,9 +1953,9 @@ hidden_interfacedcl:
 	{
 		$$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
 	}
-|	hidden_importsym '(' ohidden_funarg_list ')' ohidden_funres
+|	hidden_type
 	{
-		$$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
+		$$ = nod(ODCLFIELD, N, typenod($1));
 	}
 
 ohidden_funres:
@@ -1898,6 +1974,10 @@ hidden_funres:
 		$$ = list1(nod(ODCLFIELD, N, typenod($1)));
 	}
 
+/*
+ *  importing constants
+ */
+
 hidden_literal:
 	LLITERAL
 	{
@@ -1908,6 +1988,7 @@ hidden_literal:
 		$$ = nodlit($2);
 		switch($$->val.ctype){
 		case CTINT:
+		case CTRUNE:
 			mpnegfix($$->val.u.xval);
 			break;
 		case CTFLT:
@@ -1928,37 +2009,23 @@ hidden_constant:
 	hidden_literal
 |	'(' hidden_literal '+' hidden_literal ')'
 	{
+		if($2->val.ctype == CTRUNE && $4->val.ctype == CTINT) {
+			$$ = $2;
+			mpaddfixfix($2->val.u.xval, $4->val.u.xval);
+			break;
+		}
 		$$ = nodcplxlit($2->val, $4->val);
 	}
 
-hidden_importsym:
-	LLITERAL '.' sym
-	{
-		Pkg *p;
-
-		if($1.u.sval->len == 0)
-			p = importpkg;
-		else
-			p = mkpkg($1.u.sval);
-		$$ = pkglookup($3->name, p);
-	}
-
-hidden_pkg_importsym:
-	hidden_importsym
-	{
-		$$ = $1;
-		structpkg = $$->pkg;
-	}
-
 hidden_import_list:
 |	hidden_import_list hidden_import
 
 hidden_funarg_list:
-	hidden_dcl
+	hidden_funarg
 	{
 		$$ = list1($1);
 	}
-|	hidden_funarg_list ',' hidden_dcl
+|	hidden_funarg_list ',' hidden_funarg
 	{
 		$$ = list($1, $3);
 	}
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
index da69e41..be402cc 100644
--- a/src/cmd/gc/init.c
+++ b/src/cmd/gc/init.c
@@ -13,21 +13,13 @@
  * package and also uncallable, the name,
  * normally "pkg.init", is altered to "pkg.init·1".
  */
-Node*
-renameinit(Node *n)
+Sym*
+renameinit(void)
 {
-	Sym *s;
 	static int initgen;
 
-	s = n->sym;
-	if(s == S)
-		return n;
-	if(strcmp(s->name, "init") != 0)
-		return n;
-
 	snprint(namebuf, sizeof(namebuf), "init·%d", ++initgen);
-	s = lookup(namebuf);
-	return newname(s);
+	return lookup(namebuf);
 }
 
 /*
@@ -125,7 +117,9 @@ fninit(NodeList *n)
 	fn = nod(ODCLFUNC, N, N);
 	initsym = lookup(namebuf);
 	fn->nname = newname(initsym);
+	fn->nname->defn = fn;
 	fn->nname->ntype = nod(OTFUNC, N, N);
+	declare(fn->nname, PFUNC);
 	funchdr(fn);
 
 	// (3)
diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c
new file mode 100644
index 0000000..ed7a7eb
--- /dev/null
+++ b/src/cmd/gc/inl.c
@@ -0,0 +1,780 @@
+// Copyright 2011 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.
+//
+// The inlining facility makes 2 passes: first caninl determines which
+// functions are suitable for inlining, and for those that are it
+// saves a copy of the body. Then inlcalls walks each function body to
+// expand calls to inlinable functions.
+//
+// The debug['l'] flag controls the agressiveness. Note that main() swaps level 0 and 1,
+// making 1 the default and -l disable.  -ll and more is useful to flush out bugs.
+// These additional levels (beyond -l) may be buggy and are not supported.
+//      0: disabled
+//      1: 40-nodes leaf functions, oneliners, lazy typechecking (default)
+//      2: early typechecking of all imported bodies 
+//      3: 
+//      4: allow non-leaf functions , (breaks runtime.Caller)
+//      5: transitive inlining
+//
+//  At some point this may get another default and become switch-offable with -N.
+//
+//  The debug['m'] flag enables diagnostic output.  a single -m is useful for verifying
+//  which calls get inlined or not, more is for debugging, and may go away at any point.
+//
+// TODO:
+//   - inline functions with ... args
+//   - handle T.meth(f()) with func f() (t T, arg, arg, )
+
+#include <u.h>
+#include <libc.h>
+#include "go.h"
+
+// Used by caninl.
+static Node*	inlcopy(Node *n);
+static NodeList* inlcopylist(NodeList *ll);
+static int	ishairy(Node *n, int *budget);
+static int	ishairylist(NodeList *ll, int *budget); 
+
+// Used by inlcalls
+static void	inlnodelist(NodeList *l);
+static void	inlnode(Node **np);
+static void	mkinlcall(Node **np, Node *fn);
+static Node*	inlvar(Node *n);
+static Node*	retvar(Type *n, int i);
+static Node*	newlabel(void);
+static Node*	inlsubst(Node *n);
+static NodeList* inlsubstlist(NodeList *l);
+
+static void	setlno(Node*, int);
+
+// Used during inlsubst[list]
+static Node *inlfn;		// function currently being inlined
+static Node *inlretlabel;	// target of the goto substituted in place of a return
+static NodeList *inlretvars;	// temp out variables
+
+// Lazy typechecking of imported bodies.
+// TODO avoid redoing local functions (imporpkg would be wrong)
+void
+typecheckinl(Node *fn)
+{
+	Node *savefn;
+
+	if (debug['m']>2)
+		print("typecheck import [%S] %lN { %#H }\n", fn->sym, fn, fn->inl);
+
+	savefn = curfn;
+	curfn = fn;
+	importpkg = fn->sym->pkg;
+	typechecklist(fn->inl, Etop);
+	importpkg = nil;
+	curfn = savefn;
+}
+
+// Caninl determines whether fn is inlineable. Currently that means:
+// fn is exactly 1 statement, either a return or an assignment, and
+// some temporary constraints marked TODO.  If fn is inlineable, saves
+// fn->nbody in fn->inl and substitutes it with a copy.
+void
+caninl(Node *fn)
+{
+	Node *savefn;
+	Type *t;
+	int budget;
+
+	if(fn->op != ODCLFUNC)
+		fatal("caninl %N", fn);
+	if(!fn->nname)
+		fatal("caninl no nname %+N", fn);
+
+	// If fn has no body (is defined outside of Go), cannot inline it.
+	if(fn->nbody == nil)
+		return;
+
+	// can't handle ... args yet
+	for(t=fn->type->type->down->down->type; t; t=t->down)
+		if(t->isddd)
+			return;
+
+	budget = 40;  // allowed hairyness
+	if(ishairylist(fn->nbody, &budget))
+		return;
+
+	savefn = curfn;
+	curfn = fn;
+
+	fn->nname->inl = fn->nbody;
+	fn->nbody = inlcopylist(fn->nname->inl);
+
+	// hack, TODO, check for better way to link method nodes back to the thing with the ->inl
+	// this is so export can find the body of a method
+	fn->type->nname = fn->nname;
+
+	if(debug['m'] > 1)
+		print("%L: can inline %#N as: %#T { %#H }\n", fn->lineno, fn->nname, fn->type, fn->nname->inl);
+	else if(debug['m'])
+		print("%L: can inline %N\n", fn->lineno, fn->nname);
+
+	curfn = savefn;
+}
+
+// Look for anything we want to punt on.
+static int
+ishairylist(NodeList *ll, int* budget)
+{
+	for(;ll;ll=ll->next)
+		if(ishairy(ll->n, budget))
+			return 1;
+	return 0;
+}
+
+static int
+ishairy(Node *n, int *budget)
+{
+	if(!n)
+		return 0;
+
+	// Things that are too hairy, irrespective of the budget
+	switch(n->op) {
+	case OCALL:
+	case OCALLFUNC:
+	case OCALLINTER:
+	case OCALLMETH:
+		if(debug['l'] < 4)
+			return 1;
+		break;
+
+	case OCLOSURE:
+	case ORANGE:
+	case OFOR:
+	case OSELECT:
+	case OSWITCH:
+	case OPROC:
+	case ODEFER:
+	case ODCL:	// declares locals as globals b/c of @"". qualification
+	case ODCLTYPE:  // can't print yet
+	case ODCLCONST:  // can't print yet
+		return 1;
+
+		break;
+	case OAS:
+		// x = <N> zero initializing assignments aren't representible in export yet.
+		// alternatively we may just skip them in printing and hope their DCL printed
+		// as a var will regenerate it
+		if(n->right == N)
+			return 1;
+		break;
+	}
+
+	(*budget)--;
+
+	return  *budget < 0 ||
+		ishairy(n->left, budget) ||
+		ishairy(n->right, budget) ||
+		ishairylist(n->list, budget) ||
+		ishairylist(n->rlist, budget) ||
+		ishairylist(n->ninit, budget) ||
+		ishairy(n->ntest, budget) ||
+		ishairy(n->nincr, budget) ||
+		ishairylist(n->nbody, budget) ||
+		ishairylist(n->nelse, budget);
+}
+
+// Inlcopy and inlcopylist recursively copy the body of a function.
+// Any name-like node of non-local class is marked for re-export by adding it to
+// the exportlist.
+static NodeList*
+inlcopylist(NodeList *ll)
+{
+	NodeList *l;
+
+	l = nil;
+	for(; ll; ll=ll->next)
+		l = list(l, inlcopy(ll->n));
+	return l;
+}
+
+static Node*
+inlcopy(Node *n)
+{
+	Node *m;
+
+	if(n == N)
+		return N;
+
+	switch(n->op) {
+	case ONAME:
+	case OTYPE:
+	case OLITERAL:
+		return n;
+	}
+
+	m = nod(OXXX, N, N);
+	*m = *n;
+	m->inl = nil;
+	m->left	  = inlcopy(n->left);
+	m->right  = inlcopy(n->right);
+	m->list   = inlcopylist(n->list);
+	m->rlist  = inlcopylist(n->rlist);
+	m->ninit  = inlcopylist(n->ninit);
+	m->ntest  = inlcopy(n->ntest);
+	m->nincr  = inlcopy(n->nincr);
+	m->nbody  = inlcopylist(n->nbody);
+	m->nelse  = inlcopylist(n->nelse);
+
+	return m;
+}
+
+
+// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
+// calls made to inlineable functions.  This is the external entry point.
+void
+inlcalls(Node *fn)
+{
+	Node *savefn;
+
+	savefn = curfn;
+	curfn = fn;
+	inlnode(&fn);
+	if(fn != curfn)
+		fatal("inlnode replaced curfn");
+	curfn = savefn;
+}
+
+// Turn an OINLCALL into a statement.
+static void
+inlconv2stmt(Node *n)
+{
+	n->op = OBLOCK;
+	// n->ninit stays
+	n->list = n->nbody;
+	n->nbody = nil;
+	n->rlist = nil;
+}
+
+// Turn an OINLCALL into a single valued expression.
+static void
+inlconv2expr(Node **np)
+{
+	Node *n, *r;
+	n = *np;
+	r = n->rlist->n;
+	addinit(&r, concat(n->ninit, n->nbody));
+	*np = r;
+}
+
+// Turn the rlist (with the return values) of the OINLCALL in
+// n into an expression list lumping the ninit and body
+// containing the inlined statements on the first list element so
+// order will be preserved Used in return, oas2func and call
+// statements.
+static NodeList*
+inlconv2list(Node *n)
+{
+	NodeList *l;
+
+	if(n->op != OINLCALL || n->rlist == nil)
+		fatal("inlconv2list %+N\n", n);
+	
+	l = n->rlist;
+	addinit(&l->n, concat(n->ninit, n->nbody));
+	return l;
+} 
+ 
+static void
+inlnodelist(NodeList *l)
+{
+	for(; l; l=l->next)
+		inlnode(&l->n);
+}
+
+// inlnode recurses over the tree to find inlineable calls, which will
+// be turned into OINLCALLs by mkinlcall.  When the recursion comes
+// back up will examine left, right, list, rlist, ninit, ntest, nincr,
+// nbody and nelse and use one of the 4 inlconv/glue functions above
+// to turn the OINLCALL into an expression, a statement, or patch it
+// in to this nodes list or rlist as appropriate.
+// NOTE it makes no sense to pass the glue functions down the
+// recursion to the level where the OINLCALL gets created because they
+// have to edit /this/ n, so you'd have to push that one down as well,
+// but then you may as well do it here.  so this is cleaner and
+// shorter and less complicated.
+static void
+inlnode(Node **np)
+{
+	Node *n;
+	NodeList *l;
+	int lno;
+
+	if(*np == nil)
+		return;
+
+	n = *np;
+	
+	switch(n->op) {
+	case ODEFER:
+	case OPROC:
+		// inhibit inlining of their argument
+		switch(n->left->op) {
+		case OCALLFUNC:
+		case OCALLMETH:
+			n->left->etype = n->op;
+		}
+
+	case OCLOSURE:
+		// TODO do them here instead of in lex.c phase 6b, so escape analysis
+		// can avoid more heapmoves.
+		return;
+	}
+
+	lno = setlineno(n);
+
+	inlnodelist(n->ninit);
+	for(l=n->ninit; l; l=l->next)
+		if(l->n->op == OINLCALL)
+			inlconv2stmt(l->n);
+
+	inlnode(&n->left);
+	if(n->left && n->left->op == OINLCALL)
+		inlconv2expr(&n->left);
+
+	inlnode(&n->right);
+	if(n->right && n->right->op == OINLCALL)
+		inlconv2expr(&n->right);
+
+	inlnodelist(n->list);
+	switch(n->op) {
+	case OBLOCK:
+		for(l=n->list; l; l=l->next)
+			if(l->n->op == OINLCALL)
+				inlconv2stmt(l->n);
+		break;
+
+	case ORETURN:
+	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		// if we just replaced arg in f(arg()) or return arg with an inlined call
+		// and arg returns multiple values, glue as list
+		if(count(n->list) == 1 && n->list->n->op == OINLCALL && count(n->list->n->rlist) > 1) {
+			n->list = inlconv2list(n->list->n);
+			break;
+		}
+
+		// fallthrough
+	default:
+		for(l=n->list; l; l=l->next)
+			if(l->n->op == OINLCALL)
+				inlconv2expr(&l->n);
+	}
+
+	inlnodelist(n->rlist);
+	switch(n->op) {
+	case OAS2FUNC:
+		if(n->rlist->n->op == OINLCALL) {
+			n->rlist = inlconv2list(n->rlist->n);
+			n->op = OAS2;
+			n->typecheck = 0;
+			typecheck(np, Etop);
+			break;
+		}
+
+		// fallthrough
+	default:
+		for(l=n->rlist; l; l=l->next)
+			if(l->n->op == OINLCALL)
+				inlconv2expr(&l->n);
+
+	}
+
+	inlnode(&n->ntest);
+	if(n->ntest && n->ntest->op == OINLCALL)
+		inlconv2expr(&n->ntest);
+
+	inlnode(&n->nincr);
+	if(n->nincr && n->nincr->op == OINLCALL)
+		inlconv2stmt(n->nincr);
+
+	inlnodelist(n->nbody);
+	for(l=n->nbody; l; l=l->next)
+		if(l->n->op == OINLCALL)
+			inlconv2stmt(l->n);
+
+	inlnodelist(n->nelse);
+	for(l=n->nelse; l; l=l->next)
+		if(l->n->op == OINLCALL)
+			inlconv2stmt(l->n);
+
+	// with all the branches out of the way, it is now time to
+	// transmogrify this node itself unless inhibited by the
+	// switch at the top of this function.
+	switch(n->op) {
+	case OCALLFUNC:
+	case OCALLMETH:
+		if (n->etype == OPROC || n->etype == ODEFER)
+			return;
+	}
+
+	switch(n->op) {
+	case OCALLFUNC:
+		if(debug['m']>3)
+			print("%L:call to func %+N\n", n->lineno, n->left);
+		if(n->left->inl)	// normal case
+			mkinlcall(np, n->left);
+		else if(n->left->op == ONAME && n->left->left && n->left->left->op == OTYPE && n->left->right &&  n->left->right->op == ONAME)  // methods called as functions
+			if(n->left->sym->def)
+				mkinlcall(np, n->left->sym->def);
+		break;
+
+	case OCALLMETH:
+		if(debug['m']>3)
+			print("%L:call to meth %lN\n", n->lineno, n->left->right);
+		// typecheck should have resolved ODOTMETH->type, whose nname points to the actual function.
+		if(n->left->type == T) 
+			fatal("no function type for [%p] %+N\n", n->left, n->left);
+
+		if(n->left->type->nname == N) 
+			fatal("no function definition for [%p] %+T\n", n->left->type, n->left->type);
+
+		mkinlcall(np, n->left->type->nname);
+
+		break;
+	}
+	
+	lineno = lno;
+}
+
+// if *np is a call, and fn is a function with an inlinable body, substitute *np with an OINLCALL.
+// On return ninit has the parameter assignments, the nbody is the
+// inlined function body and list, rlist contain the input, output
+// parameters.
+static void
+mkinlcall(Node **np, Node *fn)
+{
+	int i;
+	Node *n, *call, *saveinlfn, *as, *m;
+	NodeList *dcl, *ll, *ninit, *body;
+	Type *t;
+
+	if (fn->inl == nil)
+		return;
+
+	if (fn == curfn || fn->defn == curfn)
+		return;
+
+	if(debug['l']<2)
+		typecheckinl(fn);
+
+	n = *np;
+
+	// Bingo, we have a function node, and it has an inlineable body
+	if(debug['m']>1)
+		print("%L: inlining call to %S %#T { %#H }\n", n->lineno, fn->sym, fn->type, fn->inl);
+	else if(debug['m'])
+		print("%L: inlining call to %N\n", n->lineno, fn);
+
+	if(debug['m']>2)
+		print("%L: Before inlining: %+N\n", n->lineno, n);
+
+	saveinlfn = inlfn;
+	inlfn = fn;
+
+	ninit = n->ninit;
+
+	if (fn->defn) // local function
+		dcl = fn->defn->dcl;
+	else // imported function
+		dcl = fn->dcl;
+
+	inlretvars = nil;
+	i = 0;
+	// Make temp names to use instead of the originals
+	for(ll = dcl; ll; ll=ll->next)
+		if(ll->n->op == ONAME) {
+			ll->n->inlvar = inlvar(ll->n);
+			ninit = list(ninit, nod(ODCL, ll->n->inlvar, N));  // otherwise gen won't emit the allocations for heapallocs
+			if (ll->n->class == PPARAMOUT)  // we rely on the order being correct here
+				inlretvars = list(inlretvars, ll->n->inlvar);
+		}
+
+	// anonymous return values, synthesize names for use in assignment that replaces return
+	if(inlretvars == nil && fn->type->outtuple > 0)
+		for(t = getoutargx(fn->type)->type; t; t = t->down) {
+			m = retvar(t, i++);
+			ninit = list(ninit, nod(ODCL, m, N));
+			inlretvars = list(inlretvars, m);
+		}
+
+	// assign arguments to the parameters' temp names
+	as = N;
+	if(fn->type->thistuple) {
+		t = getthisx(fn->type)->type;
+		if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
+			fatal("missing inlvar for %N\n", t->nname);
+
+		if(n->left->op == ODOTMETH) {
+			if(!n->left->left)
+				fatal("method call without receiver: %+N", n);
+			if(t == T)
+				fatal("method call unknown receiver type: %+N", n);
+			if(t->nname != N && !isblank(t->nname))
+				as = nod(OAS, t->nname->inlvar, n->left->left);
+			else
+				as = nod(OAS, temp(t->type), n->left->left);
+		} else {  // non-method call to method
+			if (!n->list)
+				fatal("non-method call to method without first arg: %+N", n);
+			if(t != T && t->nname != N && !isblank(t->nname))
+				as = nod(OAS, t->nname->inlvar, n->list->n);
+		}
+
+		if(as != N) {
+			typecheck(&as, Etop);
+			ninit = list(ninit, as);
+		}
+	}
+
+	as = nod(OAS2, N, N);
+	if(fn->type->intuple > 1 && n->list && !n->list->next) {
+		// TODO check that n->list->n is a call?
+		// TODO: non-method call to T.meth(f()) where f returns t, args...
+		as->rlist = n->list;
+		for(t = getinargx(fn->type)->type; t; t=t->down) {
+			if(t->nname && !isblank(t->nname)) {
+				if(!t->nname->inlvar)
+					fatal("missing inlvar for %N\n", t->nname);
+				as->list = list(as->list, t->nname->inlvar);
+			} else {
+				as->list = list(as->list, temp(t->type));
+			}
+		}		
+	} else {
+		ll = n->list;
+		if(fn->type->thistuple && n->left->op != ODOTMETH) // non method call to method
+			ll=ll->next;  // was handled above in if(thistuple)
+
+		for(t = getinargx(fn->type)->type; t && ll; t=t->down) {
+			if(t->nname && !isblank(t->nname)) {
+				if(!t->nname->inlvar)
+					fatal("missing inlvar for %N\n", t->nname);
+				as->list = list(as->list, t->nname->inlvar);
+				as->rlist = list(as->rlist, ll->n);
+			}
+			ll=ll->next;
+		}
+		if(ll || t)
+			fatal("arg count mismatch: %#T  vs %,H\n",  getinargx(fn->type), n->list);
+	}
+
+	if (as->rlist) {
+		typecheck(&as, Etop);
+		ninit = list(ninit, as);
+	}
+
+	// zero the outparams
+	for(ll = inlretvars; ll; ll=ll->next) {
+		as = nod(OAS, ll->n, N);
+		typecheck(&as, Etop);
+		ninit = list(ninit, as);
+	}
+
+	inlretlabel = newlabel();
+	body = inlsubstlist(fn->inl);
+
+	body = list(body, nod(OGOTO, inlretlabel, N));	// avoid 'not used' when function doesnt have return
+	body = list(body, nod(OLABEL, inlretlabel, N));
+
+	typechecklist(body, Etop);
+
+	call = nod(OINLCALL, N, N);
+	call->ninit = ninit;
+	call->nbody = body;
+	call->rlist = inlretvars;
+	call->type = n->type;
+	call->typecheck = 1;
+
+	setlno(call, n->lineno);
+
+	*np = call;
+
+	inlfn =	saveinlfn;
+	
+	// transitive inlining
+	// TODO do this pre-expansion on fn->inl directly.  requires
+	// either supporting exporting statemetns with complex ninits
+	// or saving inl and making inlinl
+	if(debug['l'] >= 5) {
+		body = fn->inl;
+		fn->inl = nil;	// prevent infinite recursion
+		inlnodelist(call->nbody);
+		for(ll=call->nbody; ll; ll=ll->next)
+			if(ll->n->op == OINLCALL)
+				inlconv2stmt(ll->n);
+		fn->inl = body;
+	}
+
+	if(debug['m']>2)
+		print("%L: After inlining %+N\n\n", n->lineno, *np);
+
+}
+
+// Every time we expand a function we generate a new set of tmpnames,
+// PAUTO's in the calling functions, and link them off of the
+// PPARAM's, PAUTOS and PPARAMOUTs of the called function. 
+static Node*
+inlvar(Node *var)
+{
+	Node *n;
+
+	if(debug['m']>3)
+		print("inlvar %+N\n", var);
+
+	n = newname(var->sym);
+	n->type = var->type;
+	n->class = PAUTO;
+	n->used = 1;
+	n->curfn = curfn;   // the calling function, not the called one
+	curfn->dcl = list(curfn->dcl, n);
+	return n;
+}
+
+// Synthesize a variable to store the inlined function's results in.
+static Node*
+retvar(Type *t, int i)
+{
+	Node *n;
+
+	snprint(namebuf, sizeof(namebuf), ".r%d", i);
+	n = newname(lookup(namebuf));
+	n->type = t->type;
+	n->class = PAUTO;
+	n->used = 1;
+	n->curfn = curfn;   // the calling function, not the called one
+	curfn->dcl = list(curfn->dcl, n);
+	return n;
+}
+
+static Node*
+newlabel(void)
+{
+	Node *n;
+	static int label;
+	
+	label++;
+	snprint(namebuf, sizeof(namebuf), ".inlret%.6d", label);
+	n = newname(lookup(namebuf));
+	n->etype = 1;  // flag 'safe' for escape analysis (no backjumps)
+	return n;
+}
+
+// inlsubst and inlsubstlist recursively copy the body of the saved
+// pristine ->inl body of the function while substituting references
+// to input/output parameters with ones to the tmpnames, and
+// substituting returns with assignments to the output.
+static NodeList*
+inlsubstlist(NodeList *ll)
+{
+	NodeList *l;
+
+	l = nil;
+	for(; ll; ll=ll->next)
+		l = list(l, inlsubst(ll->n));
+	return l;
+}
+
+static Node*
+inlsubst(Node *n)
+{
+	Node *m, *as;
+	NodeList *ll;
+
+	if(n == N)
+		return N;
+
+	switch(n->op) {
+	case ONAME:
+		if(n->inlvar) { // These will be set during inlnode
+			if (debug['m']>2)
+				print ("substituting name %+N  ->  %+N\n", n, n->inlvar);
+			return n->inlvar;
+		}
+		if (debug['m']>2)
+			print ("not substituting name %+N\n", n);
+		return n;
+
+	case OLITERAL:
+	case OTYPE:
+		return n;
+
+	case ORETURN:
+		// Since we don't handle bodies with closures, this return is guaranteed to belong to the current inlined function.
+
+//		dump("Return before substitution", n);
+		m = nod(OGOTO, inlretlabel, N);
+		m->ninit  = inlsubstlist(n->ninit);
+
+		if(inlretvars && n->list) {
+			as = nod(OAS2, N, N);
+			// shallow copy or OINLCALL->rlist will be the same list, and later walk and typecheck may clobber that.
+			for(ll=inlretvars; ll; ll=ll->next)
+				as->list = list(as->list, ll->n);
+			as->rlist = inlsubstlist(n->list);
+			typecheck(&as, Etop);
+			m->ninit = list(m->ninit, as);
+		}
+
+		typechecklist(m->ninit, Etop);
+		typecheck(&m, Etop);
+//		dump("Return after substitution", m);
+		return m;
+	}
+
+
+	m = nod(OXXX, N, N);
+	*m = *n;
+	m->ninit = nil;
+	
+	if(n->op == OCLOSURE)
+		fatal("cannot inline function containing closure: %+N", n);
+
+	m->left	  = inlsubst(n->left);
+	m->right  = inlsubst(n->right);
+	m->list	  = inlsubstlist(n->list);
+	m->rlist  = inlsubstlist(n->rlist);
+	m->ninit  = concat(m->ninit, inlsubstlist(n->ninit));
+	m->ntest  = inlsubst(n->ntest);
+	m->nincr  = inlsubst(n->nincr);
+	m->nbody  = inlsubstlist(n->nbody);
+	m->nelse  = inlsubstlist(n->nelse);
+
+	return m;
+}
+
+// Plaster over linenumbers
+static void
+setlnolist(NodeList *ll, int lno)
+{
+	for(;ll;ll=ll->next)
+		setlno(ll->n, lno);
+}
+
+static void
+setlno(Node *n, int lno)
+{
+	if(!n)
+		return;
+
+	// don't clobber names, unless they're freshly synthesized
+	if(n->op != ONAME || n->lineno == 0)
+		n->lineno = lno;
+	
+	setlno(n->left, lno);
+	setlno(n->right, lno);
+	setlnolist(n->list, lno);
+	setlnolist(n->rlist, lno);
+	setlnolist(n->ninit, lno);
+	setlno(n->ntest, lno);
+	setlno(n->nincr, lno);
+	setlnolist(n->nbody, lno);
+	setlnolist(n->nelse, lno);
+}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 0290fb1..db6dfc3 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -19,6 +19,7 @@ int yyprev;
 int yylast;
 
 static void	lexinit(void);
+static void	lexinit1(void);
 static void	lexfini(void);
 static void	yytinit(void);
 static int	getc(void);
@@ -29,6 +30,61 @@ static void	addidir(char*);
 static int	getlinepragma(void);
 static char *goos, *goarch, *goroot;
 
+// Compiler experiments.
+// These are controlled by the GOEXPERIMENT environment
+// variable recorded when the compiler is built.
+static struct {
+	char *name;
+	int *val;
+} exper[] = {
+//	{"rune32", &rune32},
+	{nil, nil},
+};
+
+static void
+addexp(char *s)
+{
+	int i;
+	
+	for(i=0; exper[i].name != nil; i++) {
+		if(strcmp(exper[i].name, s) == 0) {
+			*exper[i].val = 1;
+			return;
+		}
+	}
+	
+	print("unknown experiment %s\n", s);
+	exits("unknown experiment");
+}
+
+static void
+setexp(void)
+{
+	char *f[20];
+	int i, nf;
+	
+	// The makefile #defines GOEXPERIMENT for us.
+	nf = getfields(GOEXPERIMENT, f, nelem(f), 1, ",");
+	for(i=0; i<nf; i++)
+		addexp(f[i]);
+}
+
+char*
+expstring(void)
+{
+	int i;
+	static char buf[512];
+
+	strcpy(buf, "X");
+	for(i=0; exper[i].name != nil; i++)
+		if(*exper[i].val)
+			seprint(buf+strlen(buf), buf+sizeof buf, ",%s", exper[i].name);
+	if(strlen(buf) == 1)
+		strcpy(buf, "X,none");
+	buf[1] = ':';
+	return buf;
+}
+
 // Our own isdigit, isspace, isalpha, isalnum that take care 
 // of EOF and other out of range arguments.
 static int
@@ -82,6 +138,7 @@ usage(void)
 	print("  -N disable optimizer\n");
 	print("  -S print the assembly language\n");
 	print("  -V print the compiler version\n");
+	print("  -W print the parse tree after typing\n");
 	print("  -d print declarations\n");
 	print("  -e no limit on number of errors printed\n");
 	print("  -f print stack frame structure\n");
@@ -91,9 +148,9 @@ usage(void)
 	print("  -p assumed import path for this code\n");
 	print("  -s disable escape analysis\n");
 	print("  -u disable package unsafe\n");
-	print("  -w print the parse tree after typing\n");
+	print("  -w print type checking details\n");
 	print("  -x print lex tokens\n");
-	exits(0);
+	exits("usage");
 }
 
 void
@@ -143,6 +200,8 @@ main(int argc, char *argv[])
 	goroot = getgoroot();
 	goos = getgoos();
 	goarch = thestring;
+	
+	setexp();
 
 	outfile = nil;
 	ARGBEGIN {
@@ -169,9 +228,19 @@ main(int argc, char *argv[])
 		break;
 
 	case 'V':
-		print("%cg version %s\n", thechar, getgoversion());
+		p = expstring();
+		if(strcmp(p, "X:none") == 0)
+			p = "";
+		print("%cg version %s%s%s\n", thechar, getgoversion(), *p ? " " : "", p);
 		exits(0);
 	} ARGEND
+	
+	// enable inlining.  for now:
+	//	default: inlining on.  (debug['l'] == 1)
+	//	-l: inlining off  (debug['l'] == 0)
+	//	-ll, -lll: inlining on again, with extra debugging (debug['l'] > 1)
+	if(debug['l'] <= 1)
+		debug['l'] = 1 - debug['l'];
 
 	if(argc < 1)
 		usage();
@@ -193,23 +262,14 @@ main(int argc, char *argv[])
 				*p = '/';
 	}
 
-	fmtinstall('O', Oconv);		// node opcodes
-	fmtinstall('E', Econv);		// etype opcodes
-	fmtinstall('J', Jconv);		// all the node flags
-	fmtinstall('S', Sconv);		// sym pointer
-	fmtinstall('T', Tconv);		// type pointer
-	fmtinstall('N', Nconv);		// node pointer
-	fmtinstall('Z', Zconv);		// escaped string
-	fmtinstall('L', Lconv);		// line number
-	fmtinstall('B', Bconv);		// big numbers
-	fmtinstall('F', Fconv);		// big float numbers
-
+	fmtinstallgo();
 	betypeinit();
 	if(widthptr == 0)
 		fatal("betypeinit failed");
 
 	lexinit();
 	typeinit();
+	lexinit1();
 	yytinit();
 
 	blockgen = 1;
@@ -283,11 +343,37 @@ main(int argc, char *argv[])
 	if(nsavederrors+nerrors)
 		errorexit();
 
-	// Phase 3b: escape analysis.
-	if(!debug['s'])
+	// Phase 4: Inlining
+	if (debug['l'] > 1) {
+		// Typecheck imported function bodies if debug['l'] > 1,
+		// otherwise lazily when used or re-exported.
+		for(l=importlist; l; l=l->next)
+			if (l->n->inl) {
+				saveerrors();
+				typecheckinl(l->n);
+			}
+		
+		if(nsavederrors+nerrors)
+			errorexit();
+	}
+
+	if (debug['l']) {
+		// Find functions that can be inlined and clone them before walk expands them.
+		for(l=xtop; l; l=l->next)
+			if(l->n->op == ODCLFUNC)
+				caninl(l->n);
+		
+		// Expand inlineable calls in all functions
+		for(l=xtop; l; l=l->next)
+			if(l->n->op == ODCLFUNC)
+				inlcalls(l->n);
+	}
+
+	// Phase 5: escape analysis.
+	if(!debug['N'])
 		escapes();
 
-	// Phase 4: Compile function bodies.
+	// Phase 6: Compile top level functions.
 	for(l=xtop; l; l=l->next)
 		if(l->n->op == ODCLFUNC)
 			funccompile(l->n, 0);
@@ -295,16 +381,18 @@ main(int argc, char *argv[])
 	if(nsavederrors+nerrors == 0)
 		fninit(xtop);
 
-	// Phase 4b: Compile all closures.
+	// Phase 6b: Compile all closures.
 	while(closures) {
 		l = closures;
 		closures = nil;
 		for(; l; l=l->next) {
+			if (debug['l'])
+				inlcalls(l->n);
 			funccompile(l->n, 1);
 		}
 	}
 
-	// Phase 5: check external declarations.
+	// Phase 7: check external declarations.
 	for(l=externdcl; l; l=l->next)
 		if(l->n->op == ONAME)
 			typecheck(&l->n, Erv);
@@ -329,18 +417,30 @@ saveerrors(void)
 	nerrors = 0;
 }
 
+/*
+ *	macro to portably read/write archive header.
+ *	'cmd' is read/write/Bread/Bwrite, etc.
+ */
+#define	HEADER_IO(cmd, f, h)	cmd(f, h.name, sizeof(h.name)) != sizeof(h.name)\
+				|| cmd(f, h.date, sizeof(h.date)) != sizeof(h.date)\
+				|| cmd(f, h.uid, sizeof(h.uid)) != sizeof(h.uid)\
+				|| cmd(f, h.gid, sizeof(h.gid)) != sizeof(h.gid)\
+				|| cmd(f, h.mode, sizeof(h.mode)) != sizeof(h.mode)\
+				|| cmd(f, h.size, sizeof(h.size)) != sizeof(h.size)\
+				|| cmd(f, h.fmag, sizeof(h.fmag)) != sizeof(h.fmag)
+
 static int
 arsize(Biobuf *b, char *name)
 {
-	struct ar_hdr *a;
+	struct ar_hdr a;
 
-	if((a = Brdline(b, '\n')) == nil)
-		return -1;
-	if(Blinelen(b) != sizeof(struct ar_hdr))
+	if (HEADER_IO(Bread, b, a))
 		return -1;
-	if(strncmp(a->name, name, strlen(name)) != 0)
+
+	if(strncmp(a.name, name, strlen(name)) != 0)
 		return -1;
-	return atoi(a->size);
+
+	return atoi(a.size);
 }
 
 static int
@@ -537,7 +637,7 @@ importfile(Val *f, int line)
 			yyerror("import %s: not a go object file", file);
 			errorexit();
 		}
-		q = smprint("%s %s %s", getgoos(), thestring, getgoversion());
+		q = smprint("%s %s %s %s", getgoos(), thestring, getgoversion(), expstring());
 		if(strcmp(p+10, q) != 0) {
 			yyerror("import %s: object is [%s] expected [%s]", file, p+10, q);
 			errorexit();
@@ -744,6 +844,8 @@ l0:
 				ncp += ncp;
 			}
 			c = getr();
+			if(c == '\r')
+				continue;
 			if(c == EOF) {
 				yyerror("eof in string");
 				break;
@@ -777,7 +879,7 @@ l0:
 		}
 		yylval.val.u.xval = mal(sizeof(*yylval.val.u.xval));
 		mpmovecfix(yylval.val.u.xval, v);
-		yylval.val.ctype = CTINT;
+		yylval.val.ctype = CTRUNE;
 		DBG("lex: codepoint literal\n");
 		strcpy(litbuf, "string literal");
 		return LLITERAL;
@@ -1035,7 +1137,7 @@ lx:
 	return c;
 
 asop:
-	yylval.lint = c;	// rathole to hold which asop
+	yylval.i = c;	// rathole to hold which asop
 	DBG("lex: TOKEN ASOP %c\n", c);
 	return LASOP;
 
@@ -1273,7 +1375,7 @@ static int
 getlinepragma(void)
 {
 	int i, c, n;
-	char *cp, *ep;
+	char *cp, *ep, *linep;
 	Hist *h;
 
 	for(i=0; i<5; i++) {
@@ -1284,32 +1386,36 @@ getlinepragma(void)
 
 	cp = lexbuf;
 	ep = lexbuf+sizeof(lexbuf)-5;
+	linep = nil;
 	for(;;) {
 		c = getr();
-		if(c == '\n' || c == EOF)
+		if(c == EOF)
 			goto out;
+		if(c == '\n')
+			break;
 		if(c == ' ')
 			continue;
 		if(c == ':')
-			break;
+			linep = cp;
 		if(cp < ep)
 			*cp++ = c;
 	}
 	*cp = 0;
 
+	if(linep == nil || linep >= ep)
+		goto out;
+	*linep++ = '\0';
 	n = 0;
-	for(;;) {
-		c = getr();
-		if(!yy_isdigit(c))
-			break;
-		n = n*10 + (c-'0');
+	for(cp=linep; *cp; cp++) {
+		if(*cp < '0' || *cp > '9')
+			goto out;
+		n = n*10 + *cp - '0';
 		if(n > 1e8) {
 			yyerror("line number out of range");
 			errorexit();
 		}
 	}
-
-	if(c != '\n' || n <= 0)
+	if(n <= 0)
 		goto out;
 
 	// try to avoid allocating file name over and over
@@ -1360,7 +1466,7 @@ yylex(void)
 	// Track last two tokens returned by yylex.
 	yyprev = yylast;
 	yylast = lx;
- 	return lx;
+	return lx;
 }
 
 static int
@@ -1587,7 +1693,6 @@ static	struct
 	"complex128",	LNAME,		TCOMPLEX128,	OXXX,
 
 	"bool",		LNAME,		TBOOL,		OXXX,
-	"byte",		LNAME,		TUINT8,		OXXX,
 	"string",	LNAME,		TSTRING,	OXXX,
 
 	"any",		LNAME,		TANY,		OXXX,
@@ -1618,11 +1723,12 @@ static	struct
 	"type",		LTYPE,		Txxx,		OXXX,
 	"var",		LVAR,		Txxx,		OXXX,
 
-	"append",		LNAME,		Txxx,		OAPPEND,
+	"append",	LNAME,		Txxx,		OAPPEND,
 	"cap",		LNAME,		Txxx,		OCAP,
 	"close",	LNAME,		Txxx,		OCLOSE,
 	"complex",	LNAME,		Txxx,		OCOMPLEX,
 	"copy",		LNAME,		Txxx,		OCOPY,
+	"delete",	LNAME,		Txxx,		ODELETE,
 	"imag",		LNAME,		Txxx,		OIMAG,
 	"len",		LNAME,		Txxx,		OLEN,
 	"make",		LNAME,		Txxx,		OMAKE,
@@ -1647,6 +1753,7 @@ lexinit(void)
 	Sym *s, *s1;
 	Type *t;
 	int etype;
+	Val v;
 
 	/*
 	 * initialize basic types array
@@ -1675,6 +1782,16 @@ lexinit(void)
 			s1->def = typenod(t);
 			continue;
 		}
+
+		etype = syms[i].op;
+		if(etype != OXXX) {
+			s1 = pkglookup(syms[i].name, builtinpkg);
+			s1->lexical = LNAME;
+			s1->def = nod(ONAME, N, N);
+			s1->def->sym = s1;
+			s1->def->etype = etype;
+			s1->def->builtin = 1;
+		}
 	}
 
 	// logically, the type of a string literal.
@@ -1702,6 +1819,77 @@ lexinit(void)
 	types[TBLANK] = typ(TBLANK);
 	s->def->type = types[TBLANK];
 	nblank = s->def;
+
+	s = pkglookup("_", builtinpkg);
+	s->block = -100;
+	s->def = nod(ONAME, N, N);
+	s->def->sym = s;
+	types[TBLANK] = typ(TBLANK);
+	s->def->type = types[TBLANK];
+
+	types[TNIL] = typ(TNIL);
+	s = pkglookup("nil", builtinpkg);
+	v.ctype = CTNIL;
+	s->def = nodlit(v);
+	s->def->sym = s;
+}
+
+static void
+lexinit1(void)
+{
+	Sym *s, *s1;
+	Type *t, *f, *rcvr, *in, *out;
+
+	// t = interface { Error() string }
+	rcvr = typ(TSTRUCT);
+	rcvr->type = typ(TFIELD);
+	rcvr->type->type = ptrto(typ(TSTRUCT));
+	rcvr->funarg = 1;
+	in = typ(TSTRUCT);
+	in->funarg = 1;
+	out = typ(TSTRUCT);
+	out->type = typ(TFIELD);
+	out->type->type = types[TSTRING];
+	out->funarg = 1;
+	f = typ(TFUNC);
+	*getthis(f) = rcvr;
+	*getoutarg(f) = out;
+	*getinarg(f) = in;
+	f->thistuple = 1;
+	f->intuple = 0;
+	f->outnamed = 0;
+	f->outtuple = 1;
+	t = typ(TINTER);
+	t->type = typ(TFIELD);
+	t->type->sym = lookup("Error");
+	t->type->type = f;
+
+	// error type
+	s = lookup("error");
+	s->lexical = LNAME;
+	errortype = t;
+	errortype->sym = s;
+	s1 = pkglookup("error", builtinpkg);
+	s1->lexical = LNAME;
+	s1->def = typenod(errortype);
+
+	// byte alias
+	s = lookup("byte");
+	s->lexical = LNAME;
+	bytetype = typ(TUINT8);
+	bytetype->sym = s;
+	s1 = pkglookup("byte", builtinpkg);
+	s1->lexical = LNAME;
+	s1->def = typenod(bytetype);
+
+	// rune alias
+	s = lookup("rune");
+	s->lexical = LNAME;
+	runetype = typ(TINT32);
+	runetype->sym = s;
+	s1 = pkglookup("rune", builtinpkg);
+	s1->lexical = LNAME;
+	s1->def = typenod(runetype);
 }
 
 static void
@@ -1739,7 +1927,18 @@ lexfini(void)
 
 	// there's only so much table-driven we can handle.
 	// these are special cases.
-	types[TNIL] = typ(TNIL);
+	s = lookup("byte");
+	if(s->def == N)
+		s->def = typenod(bytetype);
+	
+	s = lookup("error");
+	if(s->def == N)
+		s->def = typenod(errortype);
+
+	s = lookup("rune");
+	if(s->def == N)
+		s->def = typenod(runetype);
+
 	s = lookup("nil");
 	if(s->def == N) {
 		v.ctype = CTNIL;
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 730b426..aae566d 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -23,7 +23,7 @@ dumpobj(void)
 		errorexit();
 	}
 
-	Bprint(bout, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
+	Bprint(bout, "go object %s %s %s %s\n", getgoos(), thestring, getgoversion(), expstring());
 	Bprint(bout, "  exports automatically generated from\n");
 	Bprint(bout, "  %s in package \"%s\"\n", curio.infile, localpkg->name);
 	dumpexport();
@@ -52,7 +52,7 @@ dumpglobls(void)
 			continue;
 
 		if(n->type == T)
-			fatal("external %#N nil type\n", n);
+			fatal("external %N nil type\n", n);
 		if(n->class == PFUNC)
 			continue;
 		if(n->sym->pkg != localpkg)
@@ -267,6 +267,7 @@ stringsym(char *s, int len)
 	if(sym->flags & SymUniq)
 		return sym;
 	sym->flags |= SymUniq;
+	sym->def = newname(sym);
 
 	off = 0;
 	
diff --git a/src/cmd/gc/order.c b/src/cmd/gc/order.c
new file mode 100644
index 0000000..2cab5fb
--- /dev/null
+++ b/src/cmd/gc/order.c
@@ -0,0 +1,358 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Rewrite tree to use separate statements to enforce
+// order of evaluation.  Makes walk easier, because it
+// can (after this runs) reorder at will within an expression.
+
+#include	<u.h>
+#include	<libc.h>
+#include	"go.h"
+
+static void	orderstmt(Node*, NodeList**);
+static void	orderstmtlist(NodeList*, NodeList**);
+static void	orderblock(NodeList **l);
+static void	orderexpr(Node**, NodeList**);
+static void	orderexprlist(NodeList*, NodeList**);
+
+void
+order(Node *fn)
+{
+	orderblock(&fn->nbody);
+}
+
+static void
+orderstmtlist(NodeList *l, NodeList **out)
+{
+	for(; l; l=l->next)
+		orderstmt(l->n, out);
+}
+
+// Order the block of statements *l onto a new list,
+// and then replace *l with that list.
+static void
+orderblock(NodeList **l)
+{
+	NodeList *out;
+	
+	out = nil;
+	orderstmtlist(*l, &out);
+	*l = out;
+}
+
+// Order the side effects in *np and leave them as
+// the init list of the final *np.
+static void
+orderexprinplace(Node **np)
+{
+	Node *n;
+	NodeList *out;
+	
+	n = *np;
+	out = nil;
+	orderexpr(&n, &out);
+	addinit(&n, out);
+	*np = n;
+}
+
+// Like orderblock, but applied to a single statement.
+static void
+orderstmtinplace(Node **np)
+{
+	Node *n;
+	NodeList *out;
+
+	n = *np;
+	out = nil;
+	orderstmt(n, &out);
+	*np = liststmt(out);
+}
+
+// Move n's init list to *out.
+static void
+orderinit(Node *n, NodeList **out)
+{
+	orderstmtlist(n->ninit, out);
+	n->ninit = nil;
+}
+
+// Is the list l actually just f() for a multi-value function?
+static int
+ismulticall(NodeList *l)
+{
+	Node *n;
+	
+	// one arg only
+	if(l == nil || l->next != nil)
+		return 0;
+	n = l->n;
+	
+	// must be call
+	switch(n->op) {
+	default:
+		return 0;
+	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		break;
+	}
+	
+	// call must return multiple values
+	return n->left->type->outtuple > 1;
+}
+
+// n is a multi-value function call.  Add t1, t2, .. = n to out
+// and return the list t1, t2, ...
+static NodeList*
+copyret(Node *n, NodeList **out)
+{
+	Type *t;
+	Node *tmp, *as;
+	NodeList *l1, *l2;
+	Iter tl;
+	
+	if(n->type->etype != TSTRUCT || !n->type->funarg)
+		fatal("copyret %T %d", n->type, n->left->type->outtuple);
+
+	l1 = nil;
+	l2 = nil;
+	for(t=structfirst(&tl, &n->type); t; t=structnext(&tl)) {
+		tmp = temp(t->type);
+		l1 = list(l1, tmp);
+		l2 = list(l2, tmp);
+	}
+	
+	as = nod(OAS2, N, N);
+	as->list = l1;
+	as->rlist = list1(n);
+	typecheck(&as, Etop);
+	orderstmt(as, out);
+
+	return l2;
+}
+
+static void
+ordercallargs(NodeList **l, NodeList **out)
+{
+	if(ismulticall(*l)) {
+		// return f() where f() is multiple values.
+		*l = copyret((*l)->n, out);
+	} else {
+		orderexprlist(*l, out);
+	}
+}
+
+static void
+ordercall(Node *n, NodeList **out)
+{
+	orderexpr(&n->left, out);
+	ordercallargs(&n->list, out);
+}
+
+static void
+orderstmt(Node *n, NodeList **out)
+{
+	int lno;
+	NodeList *l;
+	Node *r;
+
+	if(n == N)
+		return;
+
+	lno = setlineno(n);
+
+	orderinit(n, out);
+
+	switch(n->op) {
+	default:
+		fatal("orderstmt %O", n->op);
+
+	case OAS2:
+	case OAS2DOTTYPE:
+	case OAS2MAPR:
+	case OAS:
+	case OASOP:
+	case OCLOSE:
+	case OCOPY:
+	case ODELETE:
+	case OPANIC:
+	case OPRINT:
+	case OPRINTN:
+	case ORECOVER:
+	case ORECV:
+	case OSEND:
+		orderexpr(&n->left, out);
+		orderexpr(&n->right, out);
+		orderexprlist(n->list, out);
+		orderexprlist(n->rlist, out);
+		*out = list(*out, n);
+		break;
+	
+	case OAS2FUNC:
+		// Special: avoid copy of func call n->rlist->n.
+		orderexprlist(n->list, out);
+		ordercall(n->rlist->n, out);
+		*out = list(*out, n);
+		break;
+
+	case OAS2RECV:
+		// Special: avoid copy of receive.
+		orderexprlist(n->list, out);
+		orderexpr(&n->rlist->n->left, out);  // arg to recv
+		*out = list(*out, n);
+		break;
+
+	case OBLOCK:
+	case OEMPTY:
+		// Special: does not save n onto out.
+		orderstmtlist(n->list, out);
+		break;
+
+	case OBREAK:
+	case OCONTINUE:
+	case ODCL:
+	case ODCLCONST:
+	case ODCLTYPE:
+	case OFALL:
+	case_OFALL:
+	case OGOTO:
+	case OLABEL:
+		// Special: n->left is not an expression; save as is.
+		*out = list(*out, n);
+		break;
+
+	case OCALLFUNC:
+	case OCALLINTER:
+	case OCALLMETH:
+		// Special: handle call arguments.
+		ordercall(n, out);
+		*out = list(*out, n);
+		break;
+
+	case ODEFER:
+	case OPROC:
+		// Special: order arguments to inner call but not call itself.
+		ordercall(n->left, out);
+		*out = list(*out, n);
+		break;
+
+	case OFOR:
+		orderexprinplace(&n->ntest);
+		orderstmtinplace(&n->nincr);
+		orderblock(&n->nbody);
+		*out = list(*out, n);
+		break;
+		
+	case OIF:
+		orderexprinplace(&n->ntest);
+		orderblock(&n->nbody);
+		orderblock(&n->nelse);
+		*out = list(*out, n);
+		break;
+
+	case ORANGE:
+		orderexpr(&n->right, out);
+		for(l=n->list; l; l=l->next)
+			orderexprinplace(&l->n);
+		orderblock(&n->nbody);
+		*out = list(*out, n);
+		break;
+
+	case ORETURN:
+		ordercallargs(&n->list, out);
+		*out = list(*out, n);
+		break;
+		
+	case OSELECT:
+		for(l=n->list; l; l=l->next) {
+			if(l->n->op != OXCASE)
+				fatal("order select case %O", l->n->op);
+			r = l->n->left;
+			if(r == nil)
+				continue;
+			switch(r->op) {
+			case OSELRECV:
+			case OSELRECV2:
+				orderexprinplace(&r->left);
+				orderexprinplace(&r->ntest);
+				orderexpr(&r->right->left, out);
+				break;
+			case OSEND:
+				orderexpr(&r->left, out);
+				orderexpr(&r->right, out);
+				break;
+			}
+		}
+		*out = list(*out, n);
+		break;
+
+	case OSWITCH:
+		orderexpr(&n->ntest, out);
+		for(l=n->list; l; l=l->next) {
+			if(l->n->op != OXCASE)
+				fatal("order switch case %O", l->n->op);
+			orderexpr(&l->n->left, &l->n->ninit);
+		}
+		*out = list(*out, n);
+		break;
+
+	case OXFALL:
+		yyerror("fallthrough statement out of place");
+		n->op = OFALL;
+		goto case_OFALL;
+	}
+	
+	lineno = lno;
+}
+
+static void
+orderexprlist(NodeList *l, NodeList **out)
+{
+	for(; l; l=l->next)
+		orderexpr(&l->n, out);
+}
+
+static void
+orderexpr(Node **np, NodeList **out)
+{
+	Node *n;
+	int lno;
+
+	n = *np;
+	if(n == N)
+		return;
+
+	lno = setlineno(n);
+	orderinit(n, out);
+
+	switch(n->op) {
+	default:
+		orderexpr(&n->left, out);
+		orderexpr(&n->right, out);
+		orderexprlist(n->list, out);
+		orderexprlist(n->rlist, out);
+		break;
+	
+	case OANDAND:
+	case OOROR:
+		orderexpr(&n->left, out);
+		orderexprinplace(&n->right);
+		break;
+	
+	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		ordercall(n, out);
+		n = copyexpr(n, n->type, out);
+		break;
+
+	case ORECV:
+		n = copyexpr(n, n->type, out);
+		break;
+	}
+	
+	lineno = lno;
+
+	*np = n;
+}
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index d16481b..8e65ba2 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -54,7 +54,11 @@ compile(Node *fn)
 			t = structnext(&save);
 		}
 	}
-
+	
+	order(curfn);
+	if(nerrors != 0)
+		goto ret;
+	
 	hasdefer = 0;
 	walk(curfn);
 	if(nerrors != 0)
@@ -70,6 +74,8 @@ compile(Node *fn)
 
 	nodconst(&nod1, types[TINT32], 0);
 	ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
+	if(fn->dupok)
+		ptxt->TEXTFLAG = DUPOK;
 	afunclit(&ptxt->from);
 
 	ginit();
@@ -117,6 +123,10 @@ compile(Node *fn)
 	if(0)
 		print("allocauto: %lld to %lld\n", oldstksize, (vlong)stksize);
 
+	setlineno(curfn);
+	if(stksize+maxarg > (1ULL<<31))
+		yyerror("stack frame too large (>2GB)");
+
 	defframe(ptxt);
 
 	if(0)
diff --git a/src/cmd/gc/print.c b/src/cmd/gc/print.c
deleted file mode 100644
index 37e3e7a..0000000
--- a/src/cmd/gc/print.c
+++ /dev/null
@@ -1,486 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-enum
-{
-	PFIXME = 0,
-};
-
-void
-exprlistfmt(Fmt *f, NodeList *l)
-{
-	for(; l; l=l->next) {
-		exprfmt(f, l->n, 0);
-		if(l->next)
-			fmtprint(f, ", ");
-	}
-}
-
-void
-exprfmt(Fmt *f, Node *n, int prec)
-{
-	int nprec;
-	char *p;
-
-	nprec = 0;
-	if(n == nil) {
-		fmtprint(f, "<nil>");
-		return;
-	}
-	
-	if(n->implicit) {
-		exprfmt(f, n->left, prec);
-		return;
-	}
-
-	switch(n->op) {
-	case OAPPEND:
-	case ONAME:
-	case ONONAME:
-	case OPACK:
-	case OLITERAL:
-	case ODOT:
-	case ODOTPTR:
-	case ODOTINTER:
-	case ODOTMETH:
-	case ODOTTYPE:
-	case ODOTTYPE2:
-	case OXDOT:
-	case OARRAYBYTESTR:
-	case OCAP:
-	case OCLOSE:
-	case OCOPY:
-	case OLEN:
-	case OMAKE:
-	case ONEW:
-	case OPANIC:
-	case OPRINT:
-	case OPRINTN:
-	case OCALL:
-	case OCALLMETH:
-	case OCALLINTER:
-	case OCALLFUNC:
-	case OCONV:
-	case OCONVNOP:
-	case OMAKESLICE:
-	case ORUNESTR:
-	case OADDR:
-	case OCOM:
-	case OIND:
-	case OMINUS:
-	case ONOT:
-	case OPLUS:
-	case ORECV:
-	case OCONVIFACE:
-	case OTPAREN:
-	case OINDEX:
-	case OINDEXMAP:
-	case OPAREN:
-		nprec = 7;
-		break;
-
-	case OMUL:
-	case ODIV:
-	case OMOD:
-	case OLSH:
-	case ORSH:
-	case OAND:
-	case OANDNOT:
-		nprec = 6;
-		break;
-
-	case OADD:
-	case OSUB:
-	case OOR:
-	case OXOR:
-		nprec = 5;
-		break;
-
-	case OEQ:
-	case OLT:
-	case OLE:
-	case OGE:
-	case OGT:
-	case ONE:
-		nprec = 4;
-		break;
-
-	case OSEND:
-		nprec = 3;
-		break;
-
-	case OANDAND:
-		nprec = 2;
-		break;
-
-	case OOROR:
-		nprec = 1;
-		break;
-	
-	case OTYPE:
-		if(n->sym != S)
-			nprec = 7;
-		break;
-	}
-
-	if(prec > nprec)
-		fmtprint(f, "(");
-
-	switch(n->op) {
-	default:
-	bad:
-		fmtprint(f, "(node %O)", n->op);
-		break;
-
-	case OPAREN:
-		fmtprint(f, "(%#N)", n->left);
-		break;
-
-	case ODDDARG:
-		fmtprint(f, "... argument");
-		break;
-
-	case OREGISTER:
-		fmtprint(f, "%R", n->val.u.reg);
-		break;
-
-	case OLITERAL:
-		if(n->sym != S) {
-			fmtprint(f, "%S", n->sym);
-			break;
-		}
-		switch(n->val.ctype) {
-		default:
-			goto bad;
-		case CTINT:
-			fmtprint(f, "%B", n->val.u.xval);
-			break;
-		case CTBOOL:
-			if(n->val.u.bval)
-				fmtprint(f, "true");
-			else
-				fmtprint(f, "false");
-			break;
-		case CTCPLX:
-			fmtprint(f, "%.17g+%.17gi",
-				mpgetflt(&n->val.u.cval->real),
-				mpgetflt(&n->val.u.cval->imag));
-			break;
-		case CTFLT:
-			fmtprint(f, "%.17g", mpgetflt(n->val.u.fval));
-			break;
-		case CTSTR:
-			fmtprint(f, "\"%Z\"", n->val.u.sval);
-			break;
-		case CTNIL:
-			fmtprint(f, "nil");
-			break;
-		}
-		break;
-
-	case ONAME:
-	case OPACK:
-	case ONONAME:
-		fmtprint(f, "%S", n->sym);
-		break;
-
-	case OTYPE:
-		if(n->type == T && n->sym != S) {
-			fmtprint(f, "%S", n->sym);
-			break;
-		}
-		fmtprint(f, "%T", n->type);
-		break;
-
-	case OTARRAY:
-		fmtprint(f, "[]");
-		exprfmt(f, n->left, PFIXME);
-		break;
-	
-	case OTPAREN:
-		fmtprint(f, "(");
-		exprfmt(f, n->left, 0);
-		fmtprint(f, ")");
-		break;
-
-	case OTMAP:
-		fmtprint(f, "map[");
-		exprfmt(f, n->left, 0);
-		fmtprint(f, "] ");
-		exprfmt(f, n->right, 0);
-		break;
-
-	case OTCHAN:
-		if(n->etype == Crecv)
-			fmtprint(f, "<-");
-		fmtprint(f, "chan");
-		if(n->etype == Csend) {
-			fmtprint(f, "<- ");
-			exprfmt(f, n->left, 0);
-		} else {
-			fmtprint(f, " ");
-			if(n->left->op == OTCHAN && n->left->sym == S && n->left->etype == Crecv) {
-				fmtprint(f, "(");
-				exprfmt(f, n->left, 0);
-				fmtprint(f, ")");
-			} else
-				exprfmt(f, n->left, 0);
-		}
-		break;
-
-	case OTSTRUCT:
-		fmtprint(f, "<struct>");
-		break;
-
-	case OTINTER:
-		fmtprint(f, "<inter>");
-		break;
-
-	case OTFUNC:
-		fmtprint(f, "<func>");
-		break;
-
-	case OAS:
-		exprfmt(f, n->left, 0);
-		fmtprint(f, " = ");
-		exprfmt(f, n->right, 0);
-		break;
-
-	case OASOP:
-		exprfmt(f, n->left, 0);
-		fmtprint(f, " %#O= ", n->etype);
-		exprfmt(f, n->right, 0);
-		break;
-
-	case OAS2:
-	case OAS2DOTTYPE:
-	case OAS2FUNC:
-	case OAS2MAPR:
-	case OAS2MAPW:
-	case OAS2RECV:
-		exprlistfmt(f, n->list);
-		fmtprint(f, " = ");
-		exprlistfmt(f, n->rlist);
-		break;
-
-	case OADD:
-	case OANDAND:
-	case OANDNOT:
-	case ODIV:
-	case OEQ:
-	case OGE:
-	case OGT:
-	case OLE:
-	case OLT:
-	case OLSH:
-	case OMOD:
-	case OMUL:
-	case ONE:
-	case OOR:
-	case OOROR:
-	case ORSH:
-	case OSEND:
-	case OSUB:
-	case OXOR:
-		exprfmt(f, n->left, nprec);
-		fmtprint(f, " %#O ", n->op);
-		exprfmt(f, n->right, nprec+1);
-		break;
-
-	case OADDR:
-	case OCOM:
-	case OIND:
-	case OMINUS:
-	case ONOT:
-	case OPLUS:
-	case ORECV:
-		fmtprint(f, "%#O", n->op);
-		if((n->op == OMINUS || n->op == OPLUS) && n->left->op == n->op)
-			fmtprint(f, " ");
-		exprfmt(f, n->left, 0);
-		break;
-
-	case OCLOSURE:
-		fmtprint(f, "func literal");
-		break;
-
-	case OCOMPLIT:
-		fmtprint(f, "composite literal");
-		break;
-	
-	case OARRAYLIT:
-		if(isslice(n->type))
-			fmtprint(f, "slice literal");
-		else
-			fmtprint(f, "array literal");
-		break;
-	
-	case OMAPLIT:
-		fmtprint(f, "map literal");
-		break;
-	
-	case OSTRUCTLIT:
-		fmtprint(f, "struct literal");
-		break;
-
-	case OXDOT:
-	case ODOT:
-	case ODOTPTR:
-	case ODOTINTER:
-	case ODOTMETH:
-		exprfmt(f, n->left, 7);
-		if(n->right == N || n->right->sym == S)
-			fmtprint(f, ".<nil>");
-		else {
-			// skip leading type· in method name
-			p = utfrrune(n->right->sym->name, 0xb7);
-			if(p)
-				p+=2;
-			else
-				p = n->right->sym->name;
-			fmtprint(f, ".%s", p);
-		}
-		break;
-
-	case ODOTTYPE:
-	case ODOTTYPE2:
-		exprfmt(f, n->left, 7);
-		fmtprint(f, ".(");
-		if(n->right != N)
-			exprfmt(f, n->right, 0);
-		else
-			fmtprint(f, "%T", n->type);
-		fmtprint(f, ")");
-		break;
-
-	case OINDEX:
-	case OINDEXMAP:
-		exprfmt(f, n->left, 7);
-		fmtprint(f, "[");
-		exprfmt(f, n->right, 0);
-		fmtprint(f, "]");
-		break;
-
-	case OSLICE:
-	case OSLICESTR:
-	case OSLICEARR:
-		exprfmt(f, n->left, 7);
-		fmtprint(f, "[");
-		if(n->right->left != N)
-			exprfmt(f, n->right->left, 0);
-		fmtprint(f, ":");
-		if(n->right->right != N)
-			exprfmt(f, n->right->right, 0);
-		fmtprint(f, "]");
-		break;
-
-	case OCALL:
-	case OCALLFUNC:
-	case OCALLINTER:
-	case OCALLMETH:
-		exprfmt(f, n->left, 7);
-		fmtprint(f, "(");
-		exprlistfmt(f, n->list);
-		if(n->isddd)
-			fmtprint(f, "...");
-		fmtprint(f, ")");
-		break;
-
-	case OCOMPLEX:
-		fmtprint(f, "complex(");
-		exprfmt(f, n->left, 0);
-		fmtprint(f, ", ");
-		exprfmt(f, n->right, 0);
-		fmtprint(f, ")");
-		break;
-
-	case OREAL:
-		fmtprint(f, "real(");
-		exprfmt(f, n->left, 0);
-		fmtprint(f, ")");
-		break;
-
-	case OIMAG:
-		fmtprint(f, "imag(");
-		exprfmt(f, n->left, 0);
-		fmtprint(f, ")");
-		break;
-
-	case OCONV:
-	case OCONVIFACE:
-	case OCONVNOP:
-	case OARRAYBYTESTR:
-	case OSTRARRAYBYTE:
-	case ORUNESTR:
-		if(n->type == T || n->type->sym == S)
-			fmtprint(f, "(%T)(", n->type);
-		else
-			fmtprint(f, "%T(", n->type);
-		if(n->left == N)
-			exprlistfmt(f, n->list);
-		else
-			exprfmt(f, n->left, 0);
-		fmtprint(f, ")");
-		break;
-
-	case OAPPEND:
-	case OCAP:
-	case OCLOSE:
-	case OLEN:
-	case OCOPY:
-	case OMAKE:
-	case ONEW:
-	case OPANIC:
-	case OPRINT:
-	case OPRINTN:
-		fmtprint(f, "%#O(", n->op);
-		if(n->left)
-			exprfmt(f, n->left, 0);
-		else
-			exprlistfmt(f, n->list);
-		fmtprint(f, ")");
-		break;
-
-	case OMAKESLICE:
-		fmtprint(f, "make(%#T, ", n->type);
-		exprfmt(f, n->left, 0);
-		if(count(n->list) > 2) {
-			fmtprint(f, ", ");
-			exprfmt(f, n->right, 0);
-		}
-		fmtprint(f, ")");
-		break;
-
-	case OMAKEMAP:
-	case OMAKECHAN:
-		fmtprint(f, "make(%#T)", n->type);
-		break;
-
-	// Some statements
-
-	case ODCL:
-		fmtprint(f, "var %S %#T", n->left->sym, n->left->type);
-		break;
-
-	case ORETURN:
-		fmtprint(f, "return ");
-		exprlistfmt(f, n->list);
-		break;
-
-	case OPROC:
-		fmtprint(f, "go %#N", n->left);
-		break;
-
-	case ODEFER:
-		fmtprint(f, "defer %#N", n->left);
-		break;
-	}
-
-	if(prec > nprec)
-		fmtprint(f, ")");
-}
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
index 5cbafd8..9bcd833 100644
--- a/src/cmd/gc/range.c
+++ b/src/cmd/gc/range.c
@@ -32,7 +32,7 @@ typecheckrange(Node *n)
 
 	switch(t->etype) {
 	default:
-		yyerror("cannot range over %+N", n->right);
+		yyerror("cannot range over %lN", n->right);
 		goto out;
 
 	case TARRAY:
@@ -46,6 +46,10 @@ typecheckrange(Node *n)
 		break;
 
 	case TCHAN:
+		if(!(t->chan & Crecv)) {
+			yyerror("invalid operation: range %N (receive from send-only type %T)", n->right, n->right->type);
+			goto out;
+		}
 		t1 = t->type;
 		t2 = nil;
 		if(count(n->list) == 2)
@@ -54,7 +58,7 @@ typecheckrange(Node *n)
 
 	case TSTRING:
 		t1 = types[TINT];
-		t2 = types[TINT];
+		t2 = runetype;
 		break;
 	}
 
@@ -71,12 +75,12 @@ typecheckrange(Node *n)
 	if(v1->defn == n)
 		v1->type = t1;
 	else if(v1->type != T && assignop(t1, v1->type, &why) == 0)
-		yyerror("cannot assign type %T to %+N in range%s", t1, v1, why);
+		yyerror("cannot assign type %T to %lN in range%s", t1, v1, why);
 	if(v2) {
 		if(v2->defn == n)
 			v2->type = t2;
 		else if(v2->type != T && assignop(t2, v2->type, &why) == 0)
-			yyerror("cannot assign type %T to %+N in range%s", t2, v2, why);
+			yyerror("cannot assign type %T to %lN in range%s", t2, v2, why);
 	}
 
 out:
@@ -163,7 +167,9 @@ walkrange(Node *n)
 	case TMAP:
 		th = typ(TARRAY);
 		th->type = ptrto(types[TUINT8]);
-		th->bound = (sizeof(struct Hiter) + widthptr - 1) / widthptr;
+		// see ../../pkg/runtime/hashmap.h:/hash_iter
+		// Size in words.
+		th->bound = 5 + 4*3 + 4*4/widthptr;
 		hit = temp(th);
 
 		fn = syslook("mapiterinit", 1);
@@ -216,7 +222,7 @@ walkrange(Node *n)
 		if(v2 == N)
 			a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1));
 		else {
-			hv2 = temp(types[TINT]);
+			hv2 = temp(runetype);
 			a = nod(OAS2, N, N);
 			a->list = list(list1(hv1), hv2);
 			fn = syslook("stringiter2", 0);
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index ca7d08e..49aca09 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -13,6 +13,7 @@
 static	NodeList*	signatlist;
 static	Sym*	dtypesym(Type*);
 static	Sym*	weaktypesym(Type*);
+static	Sym*	dalgsym(Type*);
 
 static int
 sigcmp(Sig *a, Sig *b)
@@ -158,10 +159,13 @@ methods(Type *t)
 	// generating code if necessary.
 	a = nil;
 	for(f=mt->xmethod; f; f=f->down) {
-		if(f->type->etype != TFUNC)
-			continue;
 		if(f->etype != TFIELD)
-			fatal("methods: not field");
+			fatal("methods: not field %T", f);
+		if (f->type->etype != TFUNC || f->type->thistuple == 0)
+			fatal("non-method on %T method %S %T\n", mt, f->sym, f);
+		if (!getthisx(f->type)->type)
+			fatal("receiver with no type on %T method %S %T\n", mt, f->sym, f);
+
 		method = f->sym;
 		if(method == nil)
 			continue;
@@ -353,7 +357,7 @@ dextratype(Sym *sym, int off, Type *t, int ptroff)
 	s = sym;
 	if(t->sym) {
 		ot = dgostringptr(s, ot, t->sym->name);
-		if(t != types[t->etype])
+		if(t != types[t->etype] && t != errortype)
 			ot = dgopkgpath(s, ot, t->sym->pkg);
 		else
 			ot = dgostringptr(s, ot, nil);
@@ -550,12 +554,20 @@ haspointers(Type *t)
 static int
 dcommontype(Sym *s, int ot, Type *t)
 {
-	int i;
-	Sym *sptr;
+	int i, alg, sizeofAlg;
+	Sym *sptr, *algsym;
+	static Sym *algarray;
 	char *p;
 
+	sizeofAlg = 4*widthptr;
+	if(algarray == nil)
+		algarray = pkglookup("algarray", runtimepkg);
+	alg = algtype(t);
+	algsym = S;
+	if(alg < 0)
+		algsym = dalgsym(t);
+
 	dowidth(t);
-	
 	if(t->sym != nil && !isptr[t->etype])
 		sptr = dtypesym(ptrto(t));
 	else
@@ -583,7 +595,7 @@ dcommontype(Sym *s, int ot, Type *t)
 	//	}
 	ot = duintptr(s, ot, t->width);
 	ot = duint32(s, ot, typehash(t));
-	ot = duint8(s, ot, algtype(t));
+	ot = duint8(s, ot, 0);	// unused
 	ot = duint8(s, ot, t->align);	// align
 	ot = duint8(s, ot, t->align);	// fieldAlign
 	i = kinds[t->etype];
@@ -592,9 +604,12 @@ dcommontype(Sym *s, int ot, Type *t)
 	if(!haspointers(t))
 		i |= KindNoPointers;
 	ot = duint8(s, ot, i);  // kind
-	longsymnames = 1;
-	p = smprint("%-T", t);
-	longsymnames = 0;
+	if(alg >= 0)
+		ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
+	else
+		ot = dsymptr(s, ot, algsym, 0);
+	p = smprint("%-uT", t);
+	//print("dcommontype: %s\n", p);
 	ot = dgostringptr(s, ot, p);	// string
 	free(p);
 	
@@ -614,8 +629,22 @@ typesym(Type *t)
 	char *p;
 	Sym *s;
 
-	p = smprint("%#-T", t);
+	p = smprint("%-T", t);
+	s = pkglookup(p, typepkg);
+	//print("typesym: %s -> %+S\n", p, s);
+	free(p);
+	return s;
+}
+
+Sym*
+typesymprefix(char *prefix, Type *t)
+{
+	char *p;
+	Sym *s;
+
+	p = smprint("%s.%-T", prefix, t);
 	s = pkglookup(p, typepkg);
+	//print("algsym: %s -> %+S\n", p, s);
 	free(p);
 	return s;
 }
@@ -662,8 +691,9 @@ weaktypesym(Type *t)
 		weak->prefix = "weak.type";  // not weak%2etype
 	}
 	
-	p = smprint("%#-T", t);
+	p = smprint("%-T", t);
 	s = pkglookup(p, weak);
+	//print("weaktypesym: %s -> %+S\n", p, s);
 	free(p);
 	return s;
 }
@@ -692,8 +722,13 @@ dtypesym(Type *t)
 		tbase = t->type;
 	dupok = tbase->sym == S;
 
-	if(compiling_runtime && tbase == types[tbase->etype])	// int, float, etc
+	if(compiling_runtime && 
+			(tbase == types[tbase->etype] ||
+			tbase == bytetype ||
+			tbase == runetype ||
+			tbase == errortype)) { // int, float, etc
 		goto ok;
+	}
 
 	// named types from other files are defined only by those files
 	if(tbase->sym && !tbase->local)
@@ -902,9 +937,56 @@ dumptypestructs(void)
 			dtypesym(ptrto(types[i]));
 		dtypesym(ptrto(types[TSTRING]));
 		dtypesym(ptrto(types[TUNSAFEPTR]));
+
+		// emit type structs for error and func(error) string.
+		// The latter is the type of an auto-generated wrapper.
+		dtypesym(ptrto(errortype));
+		dtypesym(functype(nil, 
+			list1(nod(ODCLFIELD, N, typenod(errortype))),
+			list1(nod(ODCLFIELD, N, typenod(types[TSTRING])))));
 		
 		// add paths for runtime and main, which 6l imports implicitly.
 		dimportpath(runtimepkg);
 		dimportpath(mkpkg(strlit("main")));
 	}
 }
+
+Sym*
+dalgsym(Type *t)
+{
+	int ot;
+	Sym *s, *hash, *eq;
+	char buf[100];
+
+	// dalgsym is only called for a type that needs an algorithm table,
+	// which implies that the type is comparable (or else it would use ANOEQ).
+
+	s = typesymprefix(".alg", t);
+	hash = typesymprefix(".hash", t);
+	genhash(hash, t);
+	eq = typesymprefix(".eq", t);
+	geneq(eq, t);
+
+	// ../../pkg/runtime/runtime.h:/Alg
+	ot = 0;
+	ot = dsymptr(s, ot, hash, 0);
+	ot = dsymptr(s, ot, eq, 0);
+	ot = dsymptr(s, ot, pkglookup("memprint", runtimepkg), 0);
+	switch(t->width) {
+	default:
+		ot = dsymptr(s, ot, pkglookup("memcopy", runtimepkg), 0);
+		break;
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+	case 16:
+		snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8);
+		ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0);
+		break;
+	}
+
+	ggloblsym(s, ot, 1);
+	return s;
+}
+
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 549f7ab..000b232 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -6,11 +6,13 @@
 // to update builtin.c.boot.  This is not done automatically
 // to avoid depending on having a working compiler binary.
 
+// +build ignore
+
 package PACKAGE
 
 // emitted by compiler, not referred to by go programs
 
-func new(int32) *any
+func new(typ *byte) *any
 func panicindex()
 func panicslice()
 func throwreturn()
@@ -40,18 +42,19 @@ func concatstring()
 // filled in by compiler: Type*, int n, Slice, ...
 func append()
 func appendslice(typ *byte, x any, y []any) any
+func appendstr(typ *byte, x []byte, y string) []byte
 
 func cmpstring(string, string) int
 func slicestring(string, int, int) string
 func slicestring1(string, int) string
 func intstring(int64) string
 func slicebytetostring([]byte) string
-func sliceinttostring([]int) string
+func slicerunetostring([]rune) string
 func stringtoslicebyte(string) []byte
-func stringtosliceint(string) []int
+func stringtoslicerune(string) []rune
 func stringiter(string, int) int
-func stringiter2(string, int) (retk int, retv int)
-func slicecopy(to any, fr any, wid uint32) int
+func stringiter2(string, int) (retk int, retv rune)
+func copy(to any, fr any, wid uint32) int
 func slicestringcopy(to any, fr any) int
 
 // interface conversions
@@ -79,6 +82,8 @@ func efaceeq(i1 any, i2 any) (ret bool)
 func ifacethash(i1 any) (ret uint32)
 func efacethash(i1 any) (ret uint32)
 
+func equal(typ *byte, x1, x2 any) (ret bool)
+
 // *byte is really *runtime.Type
 func makemap(mapType *byte, hint int64) (hmap map[any]any)
 func mapaccess1(mapType *byte, hmap map[any]any, key any) (val any)
@@ -86,6 +91,7 @@ func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool)
 func mapassign1(mapType *byte, hmap map[any]any, key any, val any)
 func mapassign2(mapType *byte, hmap map[any]any, key any, val any, pres bool)
 func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
+func mapdelete(mapType *byte, hmap map[any]any, key any)
 func mapiternext(hiter *any)
 func mapiter1(hiter *any) (key any)
 func mapiter2(hiter *any) (key any, val any)
@@ -117,6 +123,13 @@ func slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary [
 
 func closure() // has args, but compiler fills in
 
+func memequal(eq *bool, size uintptr, x, y *any)
+func memequal8(eq *bool, size uintptr, x, y *any)
+func memequal16(eq *bool, size uintptr, x, y *any)
+func memequal32(eq *bool, size uintptr, x, y *any)
+func memequal64(eq *bool, size uintptr, x, y *any)
+func memequal128(eq *bool, size uintptr, x, y *any)
+
 // only used on 32-bit
 func int64div(int64, int64) int64
 func uint64div(uint64, uint64) uint64
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index 4550577..0cf21e2 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -154,6 +154,10 @@ init2(Node *n, NodeList **out)
 {
 	if(n == N || n->initorder == InitDone)
 		return;
+
+	if(n->op == ONAME && n->ninit)
+		fatal("name %S with ninit: %+N\n", n->sym, n);
+
 	init1(n, out);
 	init2(n->left, out);
 	init2(n->right, out);
@@ -262,6 +266,14 @@ staticcopy(Node *l, Node *r, NodeList **out)
 		case ONAME:
 			gdata(l, r, l->type->width);
 			return 1;
+		}
+		break;
+	
+	case OPTRLIT:
+		switch(r->left->op) {
+		default:
+			//dump("not static addr", r);
+			break;
 		case OARRAYLIT:
 		case OSTRUCTLIT:
 		case OMAPLIT:
@@ -294,18 +306,18 @@ staticcopy(Node *l, Node *r, NodeList **out)
 			n1.type = e->expr->type;
 			if(e->expr->op == OLITERAL)
 				gdata(&n1, e->expr, n1.type->width);
-			else if(staticassign(&n1, e->expr, out)) {
-				// Done
-			} else {
-				// Requires computation, but we're
-				// copying someone else's computation.
+			else {
 				ll = nod(OXXX, N, N);
 				*ll = n1;
-				rr = nod(OXXX, N, N);
-				*rr = *orig;
-				rr->type = ll->type;
-				rr->xoffset += e->xoffset;
-				*out = list(*out, nod(OAS, ll, rr));
+				if(!staticassign(ll, e->expr, out)) {
+					// Requires computation, but we're
+					// copying someone else's computation.
+					rr = nod(OXXX, N, N);
+					*rr = *orig;
+					rr->type = ll->type;
+					rr->xoffset += e->xoffset;
+					*out = list(*out, nod(OAS, ll, rr));
+				}
 			}
 		}
 		return 1;
@@ -347,7 +359,14 @@ staticassign(Node *l, Node *r, NodeList **out)
 		case ONAME:
 			gdata(l, r, l->type->width);
 			return 1;
-		
+		}
+	
+	case OPTRLIT:
+		switch(r->left->op) {
+		default:
+			//dump("not static ptrlit", r);
+			break;
+
 		case OARRAYLIT:
 		case OMAPLIT:
 		case OSTRUCTLIT:
@@ -392,12 +411,11 @@ staticassign(Node *l, Node *r, NodeList **out)
 			n1.type = e->expr->type;
 			if(e->expr->op == OLITERAL)
 				gdata(&n1, e->expr, n1.type->width);
-			else if(staticassign(&n1, e->expr, out)) {
-				// done
-			} else {
+			else {
 				a = nod(OXXX, N, N);
 				*a = n1;
-				*out = list(*out, nod(OAS, a, e->expr));
+				if(!staticassign(a, e->expr, out))
+					*out = list(*out, nod(OAS, a, e->expr));
 			}
 		}
 		return 1;
@@ -693,9 +711,10 @@ slicelit(int ctxt, Node *n, Node *var, NodeList **init)
 
 	// set auto to point at new temp or heap (3 assign)
 	if(n->esc == EscNone) {
-		a = temp(t);
-		*init = list(*init, nod(OAS, a, N));  // zero new temp
-		a = nod(OADDR, a, N);
+		a = nod(OAS, temp(t), N);
+		typecheck(&a, Etop);
+		*init = list(*init, a);  // zero new temp
+		a = nod(OADDR, a->left, N);
 	} else {
 		a = nod(ONEW, N, N);
 		a->list = list1(typenod(t));
@@ -918,6 +937,19 @@ anylit(int ctxt, Node *n, Node *var, NodeList **init)
 	default:
 		fatal("anylit: not lit");
 
+	case OPTRLIT:
+		if(!isptr[t->etype])
+			fatal("anylit: not ptr");
+
+		a = nod(OAS, var, callnew(t->type));
+		typecheck(&a, Etop);
+		*init = list(*init, a);
+
+		var = nod(OIND, var, N);
+		typecheck(&var, Erv | Easgn);
+		anylit(ctxt, n->left, var, init);
+		break;
+
 	case OSTRUCTLIT:
 		if(t->etype != TSTRUCT)
 			fatal("anylit: not struct");
@@ -1313,6 +1345,7 @@ iszero(Node *n)
 			return n->val.u.bval == 0;
 			
 		case CTINT:
+		case CTRUNE:
 			return mpcmpfixc(n->val.u.xval, 0) == 0;
 	
 		case CTFLT:
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index b450b9b..64a0070 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -7,11 +7,8 @@
 #include	"go.h"
 #include	"md5.h"
 #include	"y.tab.h"
-#include	"opnames.h"
 #include	"yerr.h"
 
-static	void	dodump(Node*, int);
-
 typedef struct Error Error;
 struct Error
 {
@@ -47,12 +44,10 @@ adderr(int line, char *fmt, va_list arg)
 	Fmt f;
 	Error *p;
 
-	erroring++;
 	fmtstrinit(&f);
 	fmtprint(&f, "%L: ", line);
 	fmtvprint(&f, fmt, arg);
 	fmtprint(&f, "\n");
-	erroring--;
 
 	if(nerr >= merr) {
 		if(merr == 0)
@@ -124,7 +119,7 @@ yyerrorl(int line, char *fmt, ...)
 
 	hcrash();
 	nerrors++;
-	if(nerrors >= 10 && !debug['e']) {
+	if(nsavederrors+nerrors >= 10 && !debug['e']) {
 		flusherrors();
 		print("%L: too many errors\n", line);
 		errorexit();
@@ -192,7 +187,7 @@ yyerror(char *fmt, ...)
 
 	hcrash();
 	nerrors++;
-	if(nerrors >= 10 && !debug['e']) {
+	if(nsavederrors+nerrors >= 10 && !debug['e']) {
 		flusherrors();
 		print("%L: too many errors\n", parserline());
 		errorexit();
@@ -500,45 +495,118 @@ nod(int op, Node *nleft, Node *nright)
 }
 
 int
+algtype1(Type *t, Type **bad)
+{
+	int a, ret;
+	Type *t1;
+	
+	if(bad)
+		*bad = T;
+
+	switch(t->etype) {
+	case TINT8:
+	case TUINT8:
+	case TINT16:
+	case TUINT16:
+	case TINT32:
+	case TUINT32:
+	case TINT64:
+	case TUINT64:
+	case TINT:
+	case TUINT:
+	case TUINTPTR:
+	case TBOOL:
+	case TPTR32:
+	case TPTR64:
+	case TCHAN:
+	case TUNSAFEPTR:
+		return AMEM;
+
+	case TFUNC:
+	case TMAP:
+		if(bad)
+			*bad = t;
+		return ANOEQ;
+
+	case TFLOAT32:
+		return AFLOAT32;
+
+	case TFLOAT64:
+		return AFLOAT64;
+
+	case TCOMPLEX64:
+		return ACPLX64;
+
+	case TCOMPLEX128:
+		return ACPLX128;
+
+	case TSTRING:
+		return ASTRING;
+	
+	case TINTER:
+		if(isnilinter(t))
+			return ANILINTER;
+		return AINTER;
+	
+	case TARRAY:
+		if(isslice(t)) {
+			if(bad)
+				*bad = t;
+			return ANOEQ;
+		}
+		if(t->bound == 0)
+			return AMEM;
+		a = algtype1(t->type, bad);
+		if(a == ANOEQ || a == AMEM) {
+			if(a == ANOEQ && bad)
+				*bad = t;
+			return a;
+		}
+		return -1;  // needs special compare
+
+	case TSTRUCT:
+		if(t->type != T && t->type->down == T) {
+			// One-field struct is same as that one field alone.
+			return algtype1(t->type->type, bad);
+		}
+		ret = AMEM;
+		for(t1=t->type; t1!=T; t1=t1->down) {
+			a = algtype1(t1->type, bad);
+			if(a == ANOEQ)
+				return ANOEQ;  // not comparable
+			if(a != AMEM)
+				ret = -1;  // needs special compare
+		}
+		return ret;
+	}
+
+	fatal("algtype1: unexpected type %T", t);
+	return 0;
+}
+
+int
 algtype(Type *t)
 {
 	int a;
-
-	if(issimple[t->etype] || isptr[t->etype] ||
-		t->etype == TCHAN || t->etype == TFUNC || t->etype == TMAP) {
-		if(t->width == 1)
-			a = AMEM8;
-		else if(t->width == 2)
-			a = AMEM16;
-		else if(t->width == 4)
-			a = AMEM32;
-		else if(t->width == 8)
-			a = AMEM64;
-		else if(t->width == 16)
-			a = AMEM128;
-		else
-			a = AMEM;	// just bytes (int, ptr, etc)
-	} else if(t->etype == TSTRING)
-		a = ASTRING;	// string
-	else if(isnilinter(t))
-		a = ANILINTER;	// nil interface
-	else if(t->etype == TINTER)
-		a = AINTER;	// interface
-	else if(isslice(t))
-		a = ASLICE;	// slice
-	else {
-		if(t->width == 1)
-			a = ANOEQ8;
-		else if(t->width == 2)
-			a = ANOEQ16;
-		else if(t->width == 4)
-			a = ANOEQ32;
-		else if(t->width == 8)
-			a = ANOEQ64;
-		else if(t->width == 16)
-			a = ANOEQ128;
-		else
-			a = ANOEQ;	// just bytes, but no hash/eq
+	
+	a = algtype1(t, nil);
+	if(a == AMEM || a == ANOEQ) {
+		if(isslice(t))
+			return ASLICE;
+		switch(t->width) {
+		case 0:
+			return a + AMEM0 - AMEM;
+		case 1:
+			return a + AMEM8 - AMEM;
+		case 2:
+			return a + AMEM16 - AMEM;
+		case 4:
+			return a + AMEM32 - AMEM;
+		case 8:
+			return a + AMEM64 - AMEM;
+		case 16:
+			return a + AMEM128 - AMEM;
+		}
 	}
 	return a;
 }
@@ -550,9 +618,12 @@ maptype(Type *key, Type *val)
 
 	if(key != nil) {
 		switch(key->etype) {
-		case TARRAY:
-		case TSTRUCT:
-			yyerror("invalid map key type %T", key);
+		default:
+			if(algtype1(key, nil) == ANOEQ)
+				yyerror("invalid map key type %T", key);
+			break;
+		case TANY:
+			// will be resolved later.
 			break;
 		case TFORW:
 			// map[key] used during definition of key.
@@ -702,933 +773,30 @@ nodbool(int b)
 Type*
 aindex(Node *b, Type *t)
 {
-	Type *r;
-	int bound;
-
-	bound = -1;	// open bound
-	typecheck(&b, Erv);
-	if(b != nil) {
-		switch(consttype(b)) {
-		default:
-			yyerror("array bound must be an integer expression");
-			break;
-		case CTINT:
-			bound = mpgetfix(b->val.u.xval);
-			if(bound < 0)
-				yyerror("array bound must be non negative");
-			break;
-		}
-	}
-
-	// fixed array
-	r = typ(TARRAY);
-	r->type = t;
-	r->bound = bound;
-	return r;
-}
-
-static void
-indent(int dep)
-{
-	int i;
-
-	for(i=0; i<dep; i++)
-		print(".   ");
-}
-
-static void
-dodumplist(NodeList *l, int dep)
-{
-	for(; l; l=l->next)
-		dodump(l->n, dep);
-}
-
-static void
-dodump(Node *n, int dep)
-{
-	if(n == N)
-		return;
-
-	indent(dep);
-	if(dep > 10) {
-		print("...\n");
-		return;
-	}
-
-	if(n->ninit != nil) {
-		print("%O-init\n", n->op);
-		dodumplist(n->ninit, dep+1);
-		indent(dep);
-	}
-
-	switch(n->op) {
-	default:
-		print("%N\n", n);
-		dodump(n->left, dep+1);
-		dodump(n->right, dep+1);
-		break;
-
-	case OTYPE:
-		print("%O %S type=%T\n", n->op, n->sym, n->type);
-		if(n->type == T && n->ntype) {
-			indent(dep);
-			print("%O-ntype\n", n->op);
-			dodump(n->ntype, dep+1);
-		}
-		break;
-
-	case OIF:
-		print("%O%J\n", n->op, n);
-		dodump(n->ntest, dep+1);
-		if(n->nbody != nil) {
-			indent(dep);
-			print("%O-then\n", n->op);
-			dodumplist(n->nbody, dep+1);
-		}
-		if(n->nelse != nil) {
-			indent(dep);
-			print("%O-else\n", n->op);
-			dodumplist(n->nelse, dep+1);
-		}
-		break;
-
-	case OSELECT:
-		print("%O%J\n", n->op, n);
-		dodumplist(n->nbody, dep+1);
-		break;
-
-	case OSWITCH:
-	case OFOR:
-		print("%O%J\n", n->op, n);
-		dodump(n->ntest, dep+1);
-
-		if(n->nbody != nil) {
-			indent(dep);
-			print("%O-body\n", n->op);
-			dodumplist(n->nbody, dep+1);
-		}
-
-		if(n->nincr != N) {
-			indent(dep);
-			print("%O-incr\n", n->op);
-			dodump(n->nincr, dep+1);
-		}
-		break;
-
-	case OCASE:
-		// the right side points to label of the body
-		if(n->right != N && n->right->op == OGOTO && n->right->left->op == ONAME)
-			print("%O%J GOTO %N\n", n->op, n, n->right->left);
-		else
-			print("%O%J\n", n->op, n);
-		dodump(n->left, dep+1);
-		break;
-
-	case OXCASE:
-		print("%N\n", n);
-		dodump(n->left, dep+1);
-		dodump(n->right, dep+1);
-		indent(dep);
-		print("%O-nbody\n", n->op);
-		dodumplist(n->nbody, dep+1);
-		break;
-	}
-
-	if(0 && n->ntype != nil) {
-		indent(dep);
-		print("%O-ntype\n", n->op);
-		dodump(n->ntype, dep+1);
-	}
-	if(n->list != nil) {
-		indent(dep);
-		print("%O-list\n", n->op);
-		dodumplist(n->list, dep+1);
-	}
-	if(n->rlist != nil) {
-		indent(dep);
-		print("%O-rlist\n", n->op);
-		dodumplist(n->rlist, dep+1);
-	}
-	if(n->op != OIF && n->nbody != nil) {
-		indent(dep);
-		print("%O-nbody\n", n->op);
-		dodumplist(n->nbody, dep+1);
-	}
-}
-
-void
-dumplist(char *s, NodeList *l)
-{
-	print("%s\n", s);
-	dodumplist(l, 1);
-}
-
-void
-dump(char *s, Node *n)
-{
-	print("%s [%p]\n", s, n);
-	dodump(n, 1);
-}
-
-static char*
-goopnames[] =
-{
-	[OADDR]		= "&",
-	[OADD]		= "+",
-	[OANDAND]	= "&&",
-	[OANDNOT]	= "&^",
-	[OAND]		= "&",
-	[OAPPEND]	= "append",
-	[OAS]		= "=",
-	[OAS2]		= "=",
-	[OBREAK]	= "break",
-	[OCALL]	= "function call",
-	[OCAP]		= "cap",
-	[OCASE]		= "case",
-	[OCLOSE]	= "close",
-	[OCOMPLEX]	= "complex",
-	[OCOM]		= "^",
-	[OCONTINUE]	= "continue",
-	[OCOPY]		= "copy",
-	[ODEC]		= "--",
-	[ODEFER]	= "defer",
-	[ODIV]		= "/",
-	[OEQ]		= "==",
-	[OFALL]		= "fallthrough",
-	[OFOR]		= "for",
-	[OGE]		= ">=",
-	[OGOTO]		= "goto",
-	[OGT]		= ">",
-	[OIF]		= "if",
-	[OIMAG]		= "imag",
-	[OINC]		= "++",
-	[OIND]		= "*",
-	[OLEN]		= "len",
-	[OLE]		= "<=",
-	[OLSH]		= "<<",
-	[OLT]		= "<",
-	[OMAKE]		= "make",
-	[OMINUS]	= "-",
-	[OMOD]		= "%",
-	[OMUL]		= "*",
-	[ONEW]		= "new",
-	[ONE]		= "!=",
-	[ONOT]		= "!",
-	[OOROR]		= "||",
-	[OOR]		= "|",
-	[OPANIC]	= "panic",
-	[OPLUS]		= "+",
-	[OPRINTN]	= "println",
-	[OPRINT]	= "print",
-	[ORANGE]	= "range",
-	[OREAL]		= "real",
-	[ORECV]		= "<-",
-	[ORETURN]	= "return",
-	[ORSH]		= ">>",
-	[OSELECT]	= "select",
-	[OSEND]		= "<-",
-	[OSUB]		= "-",
-	[OSWITCH]	= "switch",
-	[OXOR]		= "^",
-};
-
-int
-Oconv(Fmt *fp)
-{
-	int o;
-
-	o = va_arg(fp->args, int);
-	if((fp->flags & FmtSharp) && o >= 0 && o < nelem(goopnames) && goopnames[o] != nil)
-		return fmtstrcpy(fp, goopnames[o]);
-	if(o < 0 || o >= nelem(opnames) || opnames[o] == nil)
-		return fmtprint(fp, "O-%d", o);
-	return fmtstrcpy(fp, opnames[o]);
-}
-
-int
-Lconv(Fmt *fp)
-{
-	struct
-	{
-		Hist*	incl;	/* start of this include file */
-		int32	idel;	/* delta line number to apply to include */
-		Hist*	line;	/* start of this #line directive */
-		int32	ldel;	/* delta line number to apply to #line */
-	} a[HISTSZ];
-	int32 lno, d;
-	int i, n;
-	Hist *h;
-
-	lno = va_arg(fp->args, int32);
-
-	n = 0;
-	for(h=hist; h!=H; h=h->link) {
-		if(h->offset < 0)
-			continue;
-		if(lno < h->line)
-			break;
-		if(h->name) {
-			if(h->offset > 0) {
-				// #line directive
-				if(n > 0 && n < HISTSZ) {
-					a[n-1].line = h;
-					a[n-1].ldel = h->line - h->offset + 1;
-				}
-			} else {
-				// beginning of file
-				if(n < HISTSZ) {
-					a[n].incl = h;
-					a[n].idel = h->line;
-					a[n].line = 0;
-				}
-				n++;
-			}
-			continue;
-		}
-		n--;
-		if(n > 0 && n < HISTSZ) {
-			d = h->line - a[n].incl->line;
-			a[n-1].ldel += d;
-			a[n-1].idel += d;
-		}
-	}
-
-	if(n > HISTSZ)
-		n = HISTSZ;
-
-	for(i=n-1; i>=0; i--) {
-		if(i != n-1) {
-			if(fp->flags & ~(FmtWidth|FmtPrec))
-				break;
-			fmtprint(fp, " ");
-		}
-		if(debug['L'])
-			fmtprint(fp, "%s/", pathname);
-		if(a[i].line)
-			fmtprint(fp, "%s:%d[%s:%d]",
-				a[i].line->name, lno-a[i].ldel+1,
-				a[i].incl->name, lno-a[i].idel+1);
-		else
-			fmtprint(fp, "%s:%d",
-				a[i].incl->name, lno-a[i].idel+1);
-		lno = a[i].incl->line - 1;	// now print out start of this file
-	}
-	if(n == 0)
-		fmtprint(fp, "<epoch>");
-
-	return 0;
-}
-
-/*
-s%,%,\n%g
-s%\n+%\n%g
-s%^[ 	]*T%%g
-s%,.*%%g
-s%.+%	[T&]		= "&",%g
-s%^	........*\]%&~%g
-s%~	%%g
-*/
-
-static char*
-etnames[] =
-{
-	[TINT]		= "INT",
-	[TUINT]		= "UINT",
-	[TINT8]		= "INT8",
-	[TUINT8]	= "UINT8",
-	[TINT16]	= "INT16",
-	[TUINT16]	= "UINT16",
-	[TINT32]	= "INT32",
-	[TUINT32]	= "UINT32",
-	[TINT64]	= "INT64",
-	[TUINT64]	= "UINT64",
-	[TUINTPTR]	= "UINTPTR",
-	[TFLOAT32]	= "FLOAT32",
-	[TFLOAT64]	= "FLOAT64",
-	[TCOMPLEX64]	= "COMPLEX64",
-	[TCOMPLEX128]	= "COMPLEX128",
-	[TBOOL]		= "BOOL",
-	[TPTR32]	= "PTR32",
-	[TPTR64]	= "PTR64",
-	[TFUNC]		= "FUNC",
-	[TARRAY]	= "ARRAY",
-	[TSTRUCT]	= "STRUCT",
-	[TCHAN]		= "CHAN",
-	[TMAP]		= "MAP",
-	[TINTER]	= "INTER",
-	[TFORW]		= "FORW",
-	[TFIELD]	= "FIELD",
-	[TSTRING]	= "STRING",
-	[TANY]		= "ANY",
-};
-
-int
-Econv(Fmt *fp)
-{
-	int et;
-
-	et = va_arg(fp->args, int);
-	if(et < 0 || et >= nelem(etnames) || etnames[et] == nil)
-		return fmtprint(fp, "E-%d", et);
-	return fmtstrcpy(fp, etnames[et]);
-}
-
-static const char* classnames[] = {
-	"Pxxx",
-	"PEXTERN",
-	"PAUTO",
-	"PPARAM",
-	"PPARAMOUT",
-	"PPARAMREF",
-	"PFUNC",
-};
-
-int
-Jconv(Fmt *fp)
-{
-	Node *n;
-	char *s;
-	int c;
-
-	n = va_arg(fp->args, Node*);
-
-	c = fp->flags&FmtShort;
-
-	if(!c && n->ullman != 0)
-		fmtprint(fp, " u(%d)", n->ullman);
-
-	if(!c && n->addable != 0)
-		fmtprint(fp, " a(%d)", n->addable);
-
-	if(!c && n->vargen != 0)
-		fmtprint(fp, " g(%d)", n->vargen);
-
-	if(n->lineno != 0)
-		fmtprint(fp, " l(%d)", n->lineno);
-
-	if(!c && n->xoffset != BADWIDTH)
-		fmtprint(fp, " x(%lld%+d)", n->xoffset, n->stkdelta);
-
-	if(n->class != 0) {
-		s = "";
-		if(n->class & PHEAP) s = ",heap";
-		if((n->class & ~PHEAP) < nelem(classnames))
-			fmtprint(fp, " class(%s%s)", classnames[n->class&~PHEAP], s);
-		else
-			fmtprint(fp, " class(%d?%s)", n->class&~PHEAP, s);
-	}
- 
-	if(n->colas != 0)
-		fmtprint(fp, " colas(%d)", n->colas);
-
-	if(n->funcdepth != 0)
-		fmtprint(fp, " f(%d)", n->funcdepth);
-
-	switch(n->esc) {
-	case EscUnknown:
-		break;
-	case EscHeap:
-		fmtprint(fp, " esc(h)");
-		break;
-	case EscScope:
-		fmtprint(fp, " esc(s)");
-		break;
-	case EscNone:
-		fmtprint(fp, " esc(no)");
-		break;
-	case EscNever:
-		if(!c)
-			fmtprint(fp, " esc(N)");
-		break;
-	default:
-		fmtprint(fp, " esc(%d)", n->esc);
-		break;
-	}
-
-	if(n->escloopdepth)
-		fmtprint(fp, " ld(%d)", n->escloopdepth);
-
-	if(!c && n->typecheck != 0)
-		fmtprint(fp, " tc(%d)", n->typecheck);
-
-	if(!c && n->dodata != 0)
-		fmtprint(fp, " dd(%d)", n->dodata);
-
-	if(n->isddd != 0)
-		fmtprint(fp, " isddd(%d)", n->isddd);
-
-	if(n->implicit != 0)
-		fmtprint(fp, " implicit(%d)", n->implicit);
-
-	if(!c && n->used != 0)
-		fmtprint(fp, " used(%d)", n->used);
-	return 0;
-}
-
-int
-Sconv(Fmt *fp)
-{
-	Sym *s;
-
-	s = va_arg(fp->args, Sym*);
-	if(s == S) {
-		fmtstrcpy(fp, "<S>");
-		return 0;
-	}
-
-	if(fp->flags & FmtShort)
-		goto shrt;
-
-	if(exporting || (fp->flags & FmtSharp)) {
-		if(packagequotes)
-			fmtprint(fp, "\"%Z\"", s->pkg->path);
-		else
-			fmtprint(fp, "%s", s->pkg->prefix);
-		fmtprint(fp, ".%s", s->name);
-		return 0;
-	}
-
-	if(s->pkg && s->pkg != localpkg || longsymnames || (fp->flags & FmtLong)) {
-		// This one is for the user.  If the package name
-		// was used by multiple packages, give the full
-		// import path to disambiguate.
-		if(erroring && pkglookup(s->pkg->name, nil)->npkg > 1) {
-			fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name);
-			return 0;
-		}
-		fmtprint(fp, "%s.%s", s->pkg->name, s->name);
-		return 0;
-	}
-
-shrt:
-	fmtstrcpy(fp, s->name);
-	return 0;
-}
-
-static char*
-basicnames[] =
-{
-	[TINT]		= "int",
-	[TUINT]		= "uint",
-	[TINT8]		= "int8",
-	[TUINT8]	= "uint8",
-	[TINT16]	= "int16",
-	[TUINT16]	= "uint16",
-	[TINT32]	= "int32",
-	[TUINT32]	= "uint32",
-	[TINT64]	= "int64",
-	[TUINT64]	= "uint64",
-	[TUINTPTR]	= "uintptr",
-	[TFLOAT32]	= "float32",
-	[TFLOAT64]	= "float64",
-	[TCOMPLEX64]	= "complex64",
-	[TCOMPLEX128]	= "complex128",
-	[TBOOL]		= "bool",
-	[TANY]		= "any",
-	[TSTRING]	= "string",
-	[TNIL]		= "nil",
-	[TIDEAL]	= "ideal",
-	[TBLANK]	= "blank",
-};
-
-int
-Tpretty(Fmt *fp, Type *t)
-{
-	Type *t1;
-	Sym *s;
-	
-	if(0 && debug['r']) {
-		debug['r'] = 0;
-		fmtprint(fp, "%T (orig=%T)", t, t->orig);
-		debug['r'] = 1;
-		return 0;
-	}
-
-	if(t->etype != TFIELD
-	&& t->sym != S
-	&& !(fp->flags&FmtLong)) {
-		s = t->sym;
-		if(t == types[t->etype] && t->etype != TUNSAFEPTR)
-			return fmtprint(fp, "%s", s->name);
-		if(exporting) {
-			if(fp->flags & FmtShort)
-				fmtprint(fp, "%hS", s);
-			else
-				fmtprint(fp, "%S", s);
-			if(s->pkg != localpkg)
-				return 0;
-			if(t->vargen)
-				fmtprint(fp, "·%d", t->vargen);
-			return 0;
-		}
-		return fmtprint(fp, "%S", s);
-	}
-
-	if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil) {
-		if(isideal(t) && t->etype != TIDEAL && t->etype != TNIL)
-			fmtprint(fp, "ideal ");
-		return fmtprint(fp, "%s", basicnames[t->etype]);
-	}
-
-	switch(t->etype) {
-	case TPTR32:
-	case TPTR64:
-		if(fp->flags&FmtShort)	// pass flag thru for methodsym
-			return fmtprint(fp, "*%hT", t->type);
-		return fmtprint(fp, "*%T", t->type);
-
-	case TCHAN:
-		switch(t->chan) {
-		case Crecv:
-			return fmtprint(fp, "<-chan %T", t->type);
-		case Csend:
-			return fmtprint(fp, "chan<- %T", t->type);
-		}
-		if(t->type != T && t->type->etype == TCHAN && t->type->sym == S && t->type->chan == Crecv)
-			return fmtprint(fp, "chan (%T)", t->type);
-		return fmtprint(fp, "chan %T", t->type);
-
-	case TMAP:
-		return fmtprint(fp, "map[%T] %T", t->down, t->type);
-
-	case TFUNC:
-		// t->type is method struct
-		// t->type->down is result struct
-		// t->type->down->down is arg struct
-		if(t->thistuple && !(fp->flags&FmtSharp) && !(fp->flags&FmtShort)) {
-			fmtprint(fp, "method(");
-			for(t1=getthisx(t)->type; t1; t1=t1->down) {
-				fmtprint(fp, "%T", t1);
-				if(t1->down)
-					fmtprint(fp, ", ");
-			}
-			fmtprint(fp, ")");
-		}
-
-		if(!(fp->flags&FmtByte))
-			fmtprint(fp, "func");
-		fmtprint(fp, "(");
-		for(t1=getinargx(t)->type; t1; t1=t1->down) {
-			if(noargnames && t1->etype == TFIELD) {
-				if(t1->isddd)
-					fmtprint(fp, "...%T", t1->type->type);
-				else
-					fmtprint(fp, "%T", t1->type);
-			} else
-				fmtprint(fp, "%T", t1);
-			if(t1->down)
-				fmtprint(fp, ", ");
-		}
-		fmtprint(fp, ")");
-		switch(t->outtuple) {
-		case 0:
-			break;
-		case 1:
-			t1 = getoutargx(t)->type;
-			if(t1 == T) {
-				// failure to typecheck earlier; don't know the type
-				fmtprint(fp, " ?unknown-type?");
-				break;
-			}
-			if(t1->etype == TFIELD)
-				t1 = t1->type;
-			fmtprint(fp, " %T", t1);
-			break;
-		default:
-			t1 = getoutargx(t)->type;
-			fmtprint(fp, " (");
-			for(; t1; t1=t1->down) {
-				if(noargnames && t1->etype == TFIELD)
-					fmtprint(fp, "%T", t1->type);
-				else
-					fmtprint(fp, "%T", t1);
-				if(t1->down)
-					fmtprint(fp, ", ");
-			}
-			fmtprint(fp, ")");
-			break;
-		}
-		return 0;
-
-	case TARRAY:
-		if(t->bound >= 0)
-			return fmtprint(fp, "[%d]%T", (int)t->bound, t->type);
-		if(t->bound == -100)
-			return fmtprint(fp, "[...]%T", t->type);
-		return fmtprint(fp, "[]%T", t->type);
-
-	case TINTER:
-		fmtprint(fp, "interface {");
-		for(t1=t->type; t1!=T; t1=t1->down) {
-			fmtprint(fp, " ");
-			if(exportname(t1->sym->name))
-				fmtprint(fp, "%hS", t1->sym);
-			else
-				fmtprint(fp, "%S", t1->sym);
-			fmtprint(fp, "%hhT", t1->type);
-			if(t1->down)
-				fmtprint(fp, ";");
-		}
-		return fmtprint(fp, " }");
-
-	case TSTRUCT:
-		if(t->funarg) {
-			fmtprint(fp, "(");
-			for(t1=t->type; t1!=T; t1=t1->down) {
-				fmtprint(fp, "%T", t1);
-				if(t1->down)
-					fmtprint(fp, ", ");
-			}
-			return fmtprint(fp, ")");
-		}
-		fmtprint(fp, "struct {");
-		for(t1=t->type; t1!=T; t1=t1->down) {
-			fmtprint(fp, " %T", t1);
-			if(t1->down)
-				fmtprint(fp, ";");
-		}
-		return fmtprint(fp, " }");
-
-	case TFIELD:
-		if(t->sym == S || t->embedded) {
-			if(exporting)
-				fmtprint(fp, "? ");
-		} else
-			fmtprint(fp, "%hS ", t->sym);
-		if(t->isddd)
-			fmtprint(fp, "...%T", t->type->type);
-		else
-			fmtprint(fp, "%T", t->type);
-		if(t->note) {
-			fmtprint(fp, " ");
-			if(exporting)
-				fmtprint(fp, ":");
-			fmtprint(fp, "\"%Z\"", t->note);
-		}
-		return 0;
-
-	case TFORW:
-		if(exporting)
-			yyerror("undefined type %S", t->sym);
-		if(t->sym)
-			return fmtprint(fp, "undefined %S", t->sym);
-		return fmtprint(fp, "undefined");
-	
-	case TUNSAFEPTR:
-		if(exporting)
-			return fmtprint(fp, "\"unsafe\".Pointer");
-		return fmtprint(fp, "unsafe.Pointer");
-	}
-
-	// Don't know how to handle - fall back to detailed prints.
-	return -1;
-}
-
-int
-Tconv(Fmt *fp)
-{
-	Type *t, *t1;
-	int r, et, sharp, minus;
-
-	sharp = (fp->flags & FmtSharp);
-	minus = (fp->flags & FmtLeft);
-	fp->flags &= ~(FmtSharp|FmtLeft);
-
-	t = va_arg(fp->args, Type*);
-	if(t == T)
-		return fmtstrcpy(fp, "<T>");
-
-	t->trecur++;
-	if(t->trecur > 5) {
-		fmtprint(fp, "...");
-		goto out;
-	}
-
-	if(!debug['t']) {
-		if(sharp)
-			exporting++;
-		if(minus)
-			noargnames++;
-		r = Tpretty(fp, t);
-		if(sharp)
-			exporting--;
-		if(minus)
-			noargnames--;
-		if(r >= 0) {
-			t->trecur--;
-			return 0;
-		}
-	}
-
-	if(sharp || exporting)
-		fatal("missing %E case during export", t->etype);
-
-	et = t->etype;
-	fmtprint(fp, "%E ", et);
-	if(t->sym != S)
-		fmtprint(fp, "<%S>", t->sym);
-
-	switch(et) {
-	default:
-		if(t->type != T)
-			fmtprint(fp, " %T", t->type);
-		break;
-
-	case TFIELD:
-		fmtprint(fp, "%T", t->type);
-		break;
-
-	case TFUNC:
-		if(fp->flags & FmtLong)
-			fmtprint(fp, "%d%d%d(%lT,%lT)%lT",
-				t->thistuple, t->intuple, t->outtuple,
-				t->type, t->type->down->down, t->type->down);
-		else
-			fmtprint(fp, "%d%d%d(%T,%T)%T",
-				t->thistuple, t->intuple, t->outtuple,
-				t->type, t->type->down->down, t->type->down);
-		break;
-
-	case TINTER:
-		fmtprint(fp, "{");
-		if(fp->flags & FmtLong)
-			for(t1=t->type; t1!=T; t1=t1->down)
-				fmtprint(fp, "%lT;", t1);
-		fmtprint(fp, "}");
-		break;
-
-	case TSTRUCT:
-		fmtprint(fp, "{");
-		if(fp->flags & FmtLong)
-			for(t1=t->type; t1!=T; t1=t1->down)
-				fmtprint(fp, "%lT;", t1);
-		fmtprint(fp, "}");
-		break;
-
-	case TMAP:
-		fmtprint(fp, "[%T]%T", t->down, t->type);
-		break;
-
-	case TARRAY:
-		if(t->bound >= 0)
-			fmtprint(fp, "[%d]%T", t->bound, t->type);
-		else
-			fmtprint(fp, "[]%T", t->type);
-		break;
-
-	case TPTR32:
-	case TPTR64:
-		fmtprint(fp, "%T", t->type);
-		break;
-	}
-
-out:
-	t->trecur--;
-	return 0;
-}
-
-int
-Nconv(Fmt *fp)
-{
-	char buf1[500];
-	Node *n;
-
-	n = va_arg(fp->args, Node*);
-	if(n == N) {
-		fmtprint(fp, "<N>");
-		goto out;
-	}
-
-	if(fp->flags & FmtSign) {
-		if(n->type == T)
-			fmtprint(fp, "%#N", n);
-		else if(n->type->etype == TNIL)
-			fmtprint(fp, "nil");
-		else
-			fmtprint(fp, "%#N (type %T)", n, n->type);
-		goto out;
-	}
-
-	if(fp->flags & FmtSharp) {
-		if(n->orig != N)
-			n = n->orig;
-		exprfmt(fp, n, 0);
-		goto out;
-	}
-
-	switch(n->op) {
-	default:
-		if(fp->flags & FmtShort)
-			fmtprint(fp, "%O%hJ", n->op, n);
-		else
-			fmtprint(fp, "%O%J", n->op, n);
-		break;
-
-	case ONAME:
-	case ONONAME:
-		if(n->sym == S) {
-			if(fp->flags & FmtShort)
-				fmtprint(fp, "%O%hJ", n->op, n);
-			else
-				fmtprint(fp, "%O%J", n->op, n);
-			break;
-		}
-		if(fp->flags & FmtShort)
-			fmtprint(fp, "%O-%S%hJ", n->op, n->sym, n);
-		else
-			fmtprint(fp, "%O-%S%J", n->op, n->sym, n);
-		goto ptyp;
-
-	case OREGISTER:
-		fmtprint(fp, "%O-%R%J", n->op, n->val.u.reg, n);
-		break;
+	Type *r;
+	int bound;
 
-	case OLITERAL:
-		switch(n->val.ctype) {
+	bound = -1;	// open bound
+	typecheck(&b, Erv);
+	if(b != nil) {
+		switch(consttype(b)) {
 		default:
-			snprint(buf1, sizeof(buf1), "LITERAL-ctype=%d", n->val.ctype);
+			yyerror("array bound must be an integer expression");
 			break;
 		case CTINT:
-			snprint(buf1, sizeof(buf1), "I%B", n->val.u.xval);
-			break;
-		case CTFLT:
-			snprint(buf1, sizeof(buf1), "F%g", mpgetflt(n->val.u.fval));
-			break;
-		case CTCPLX:
-			snprint(buf1, sizeof(buf1), "(F%g+F%gi)",
-				mpgetflt(&n->val.u.cval->real),
-				mpgetflt(&n->val.u.cval->imag));
-			break;
-		case CTSTR:
-			snprint(buf1, sizeof(buf1), "S\"%Z\"", n->val.u.sval);
-			break;
-		case CTBOOL:
-			snprint(buf1, sizeof(buf1), "B%d", n->val.u.bval);
-			break;
-		case CTNIL:
-			snprint(buf1, sizeof(buf1), "N");
+		case CTRUNE:
+			bound = mpgetfix(b->val.u.xval);
+			if(bound < 0)
+				yyerror("array bound must be non negative");
 			break;
 		}
-		fmtprint(fp, "%O-%s%J", n->op, buf1, n);
-		break;
-
-	case OASOP:
-		fmtprint(fp, "%O-%O%J", n->op, n->etype, n);
-		break;
-
-	case OTYPE:
-		fmtprint(fp, "%O %T", n->op, n->type);
-		break;
 	}
-	if(n->sym != S)
-		fmtprint(fp, " %S G%d", n->sym, n->vargen);
 
-ptyp:
-	if(n->type != T)
-		fmtprint(fp, " %T", n->type);
-
-out:
-	return 0;
+	// fixed array
+	r = typ(TARRAY);
+	r->type = t;
+	r->bound = bound;
+	return r;
 }
 
 Node*
@@ -1671,52 +839,6 @@ treecopy(Node *n)
 	return m;
 }
 
-int
-Zconv(Fmt *fp)
-{
-	Rune r;
-	Strlit *sp;
-	char *s, *se;
-	int n;
-
-	sp = va_arg(fp->args, Strlit*);
-	if(sp == nil)
-		return fmtstrcpy(fp, "<nil>");
-
-	s = sp->s;
-	se = s + sp->len;
-	while(s < se) {
-		n = chartorune(&r, s);
-		s += n;
-		switch(r) {
-		case Runeerror:
-			if(n == 1) {
-				fmtprint(fp, "\\x%02x", (uchar)*(s-1));
-				break;
-			}
-			// fall through
-		default:
-			if(r < ' ') {
-				fmtprint(fp, "\\x%02x", r);
-				break;
-			}
-			fmtrune(fp, r);
-			break;
-		case '\t':
-			fmtstrcpy(fp, "\\t");
-			break;
-		case '\n':
-			fmtstrcpy(fp, "\\n");
-			break;
-		case '\"':
-		case '\\':
-			fmtrune(fp, '\\');
-			fmtrune(fp, r);
-			break;
-		}
-	}
-	return 0;
-}
 
 int
 isnil(Node *n)
@@ -1872,6 +994,25 @@ eqnote(Strlit *a, Strlit *b)
 	return memcmp(a->s, b->s, a->len) == 0;
 }
 
+typedef struct TypePairList TypePairList;
+struct TypePairList
+{
+	Type *t1;
+	Type *t2;
+	TypePairList *next;
+};
+
+static int
+onlist(TypePairList *l, Type *t1, Type *t2) 
+{
+	for(; l; l=l->next)
+		if((l->t1 == t1 && l->t2 == t2) || (l->t1 == t2 && l->t2 == t1))
+			return 1;
+	return 0;
+}
+
+static int eqtype1(Type*, Type*, TypePairList*);
+
 // Return 1 if t1 and t2 are identical, following the spec rules.
 //
 // Any cyclic type must go through a named type, and if one is
@@ -1881,10 +1022,40 @@ eqnote(Strlit *a, Strlit *b)
 int
 eqtype(Type *t1, Type *t2)
 {
+	return eqtype1(t1, t2, nil);
+}
+
+static int
+eqtype1(Type *t1, Type *t2, TypePairList *assumed_equal)
+{
+	TypePairList l;
+
 	if(t1 == t2)
 		return 1;
-	if(t1 == T || t2 == T || t1->etype != t2->etype || t1->sym || t2->sym)
+	if(t1 == T || t2 == T || t1->etype != t2->etype)
 		return 0;
+	if(t1->sym || t2->sym) {
+		// Special case: we keep byte and uint8 separate
+		// for error messages.  Treat them as equal.
+		switch(t1->etype) {
+		case TUINT8:
+			if((t1 == types[TUINT8] || t1 == bytetype) && (t2 == types[TUINT8] || t2 == bytetype))
+				return 1;
+			break;
+		case TINT:
+		case TINT32:
+			if((t1 == types[runetype->etype] || t1 == runetype) && (t2 == types[runetype->etype] || t2 == runetype))
+				return 1;
+			break;
+		}
+		return 0;
+	}
+
+	if(onlist(assumed_equal, t1, t2))
+		return 1;
+	l.next = assumed_equal;
+	l.t1 = t1;
+	l.t2 = t2;
 
 	switch(t1->etype) {
 	case TINTER:
@@ -1892,10 +1063,12 @@ eqtype(Type *t1, Type *t2)
 		for(t1=t1->type, t2=t2->type; t1 && t2; t1=t1->down, t2=t2->down) {
 			if(t1->etype != TFIELD || t2->etype != TFIELD)
 				fatal("struct/interface missing field: %T %T", t1, t2);
-			if(t1->sym != t2->sym || t1->embedded != t2->embedded || !eqtype(t1->type, t2->type) || !eqnote(t1->note, t2->note))
-				return 0;
+			if(t1->sym != t2->sym || t1->embedded != t2->embedded || !eqtype1(t1->type, t2->type, &l) || !eqnote(t1->note, t2->note))
+				goto no;
 		}
-		return t1 == T && t2 == T;
+		if(t1 == T && t2 == T)
+			goto yes;
+		goto no;
 
 	case TFUNC:
 		// Loop over structs: receiver, in, out.
@@ -1909,26 +1082,38 @@ eqtype(Type *t1, Type *t2)
 			for(ta=t1->type, tb=t2->type; ta && tb; ta=ta->down, tb=tb->down) {
 				if(ta->etype != TFIELD || tb->etype != TFIELD)
 					fatal("func struct missing field: %T %T", ta, tb);
-				if(ta->isddd != tb->isddd || !eqtype(ta->type, tb->type))
-					return 0;
+				if(ta->isddd != tb->isddd || !eqtype1(ta->type, tb->type, &l))
+					goto no;
 			}
 			if(ta != T || tb != T)
-				return 0;
+				goto no;
 		}
-		return t1 == T && t2 == T;
+		if(t1 == T && t2 == T)
+			goto yes;
+		goto no;
 	
 	case TARRAY:
 		if(t1->bound != t2->bound)
-			return 0;
+			goto no;
 		break;
 	
 	case TCHAN:
 		if(t1->chan != t2->chan)
-			return 0;
+			goto no;
 		break;
 	}
 
-	return eqtype(t1->down, t2->down) && eqtype(t1->type, t2->type);
+	if(eqtype1(t1->down, t2->down, &l) && eqtype1(t1->type, t2->type, &l))
+		goto yes;
+	goto no;
+
+yes:
+	assumed_equal = l.next;
+	return 1;
+
+no:
+	assumed_equal = l.next;
+	return 0;
 }
 
 // Are t1 and t2 equal struct types when field names are ignored?
@@ -1955,9 +1140,6 @@ eqtypenoname(Type *t1, Type *t2)
 // Is type src assignment compatible to type dst?
 // If so, return op code to use in conversion.
 // If not, return 0.
-//
-// It is the caller's responsibility to call exportassignok
-// to check for assignments to other packages' unexported fields,
 int
 assignop(Type *src, Type *dst, char **why)
 {
@@ -1967,7 +1149,9 @@ assignop(Type *src, Type *dst, char **why)
 	if(why != nil)
 		*why = "";
 
-	if(safemode && src != T && src->etype == TUNSAFEPTR) {
+	// TODO(rsc,lvd): This behaves poorly in the presence of inlining.
+	// https://code.google.com/p/go/issues/detail?id=2795
+	if(safemode && importpkg == nil && src != T && src->etype == TUNSAFEPTR) {
 		yyerror("cannot use unsafe.Pointer");
 		errorexit();
 	}
@@ -1991,6 +1175,11 @@ assignop(Type *src, Type *dst, char **why)
 	if(dst->etype == TINTER && src->etype != TNIL) {
 		if(implements(src, dst, &missing, &have, &ptr))
 			return OCONVIFACE;
+
+		// we'll have complained about this method anyway, supress spurious messages.
+		if(have && have->sym == missing->sym && (have->type->broke || missing->type->broke))
+			return OCONVIFACE;
+
 		if(why != nil) {
 			if(isptrto(src, TINTER))
 				*why = smprint(":\n\t%T is pointer to interface, not interface", src);
@@ -2107,29 +1296,25 @@ convertop(Type *src, Type *dst, char **why)
 		return OCONV;
 	}
 
-	// 6. src is an integer or has type []byte or []int
+	// 6. src is an integer or has type []byte or []rune
 	// and dst is a string type.
 	if(isint[src->etype] && dst->etype == TSTRING)
 		return ORUNESTR;
 
-	if(isslice(src) && src->sym == nil &&  src->type == types[src->type->etype] && dst->etype == TSTRING) {
-		switch(src->type->etype) {
-		case TUINT8:
+	if(isslice(src) && dst->etype == TSTRING) {
+		if(src->type->etype == bytetype->etype)
 			return OARRAYBYTESTR;
-		case TINT:
+		if(src->type->etype == runetype->etype)
 			return OARRAYRUNESTR;
-		}
 	}
 	
-	// 7. src is a string and dst is []byte or []int.
+	// 7. src is a string and dst is []byte or []rune.
 	// String to slice.
-	if(src->etype == TSTRING && isslice(dst) && dst->sym == nil && dst->type == types[dst->type->etype]) {
-		switch(dst->type->etype) {
-		case TUINT8:
+	if(src->etype == TSTRING && isslice(dst)) {
+		if(dst->type->etype == bytetype->etype)
 			return OSTRARRAYBYTE;
-		case TINT:
+		if(dst->type->etype == runetype->etype)
 			return OSTRARRAYRUNE;
-		}
 	}
 	
 	// 8. src is a pointer or uintptr and dst is unsafe.Pointer.
@@ -2161,13 +1346,12 @@ assignconv(Node *n, Type *t, char *context)
 	if(t->etype == TBLANK)
 		return n;
 
-	exportassignok(n->type, context);
 	if(eqtype(n->type, t))
 		return n;
 
 	op = assignop(n->type, t, &why);
 	if(op == 0) {
-		yyerror("cannot use %+N as type %T in %s%s", n, t, context, why);
+		yyerror("cannot use %lN as type %T in %s%s", n, t, context, why);
 		op = OCONV;
 	}
 
@@ -2392,7 +1576,7 @@ syslook(char *name, int copy)
  * compute a hash value for type t.
  * if t is a method type, ignore the receiver
  * so that the hash can be used in interface checks.
- * %-T (which calls Tpretty, above) already contains
+ * %T already contains
  * all the necessary logic to generate a representation
  * of the type that completely describes it.
  * using smprint here avoids duplicating that code.
@@ -2406,15 +1590,14 @@ typehash(Type *t)
 	char *p;
 	MD5 d;
 
-	longsymnames = 1;
 	if(t->thistuple) {
 		// hide method receiver from Tpretty
 		t->thistuple = 0;
-		p = smprint("%-T", t);
+		p = smprint("%-uT", t);
 		t->thistuple = 1;
-	}else
-		p = smprint("%-T", t);
-	longsymnames = 0;
+	} else
+		p = smprint("%-uT", t);
+	//print("typehash: %s\n", p);
 	md5reset(&d);
 	md5write(&d, (uchar*)p, strlen(p));
 	free(p);
@@ -2427,7 +1610,7 @@ ptrto(Type *t)
 	Type *t1;
 
 	if(tptr == 0)
-		fatal("ptrto: nil");
+		fatal("ptrto: no tptr");
 	t1 = typ(tptr);
 	t1->type = t;
 	t1->width = widthptr;
@@ -2784,7 +1967,7 @@ safeexpr(Node *n, NodeList **init)
 	return cheapexpr(n, init);
 }
 
-static Node*
+Node*
 copyexpr(Node *n, Type *t, NodeList **init)
 {
 	Node *a, *l;
@@ -2905,7 +2088,7 @@ lookdot0(Sym *s, Type *t, Type **save, int ignorecase)
 	return c;
 }
 
-// search depth d --
+// search depth d for field/method s --
 // return count of fields+methods
 // found at search depth.
 // answer is in dotlist array and
@@ -2983,7 +2166,7 @@ adddot(Node *n)
 
 out:
 	if(c > 1)
-		yyerror("ambiguous DOT reference %T.%S", t, s);
+		yyerror("ambiguous selector %T.%S", t, s);
 
 	// rebuild elided dots
 	for(c=d-1; c>=0; c--)
@@ -3028,8 +2211,6 @@ expand0(Type *t, int followptr)
 
 	if(u->etype == TINTER) {
 		for(f=u->type; f!=T; f=f->down) {
-			if(!exportname(f->sym->name) && f->sym->pkg != localpkg)
-				continue;
 			if(f->sym->flags & SymUniq)
 				continue;
 			f->sym->flags |= SymUniq;
@@ -3045,8 +2226,6 @@ expand0(Type *t, int followptr)
 	u = methtype(t);
 	if(u != T) {
 		for(f=u->method; f!=T; f=f->down) {
-			if(!exportname(f->sym->name) && f->sym->pkg != localpkg)
-				continue;
 			if(f->sym->flags & SymUniq)
 				continue;
 			f->sym->flags |= SymUniq;
@@ -3122,8 +2301,11 @@ expandmeth(Sym *s, Type *t)
 			if(c == 0)
 				continue;
 			if(c == 1) {
-				sl->good = 1;
-				sl->field = f;
+				// addot1 may have dug out arbitrary fields, we only want methods.
+				if(f->type->etype == TFUNC && f->type->thistuple > 0) {
+					sl->good = 1;
+					sl->field = f;
+				}
 			}
 			break;
 		}
@@ -3164,13 +2346,12 @@ structargs(Type **tl, int mustname)
 	gen = 0;
 	for(t = structfirst(&savet, tl); t != T; t = structnext(&savet)) {
 		n = N;
-		if(t->sym)
-			n = newname(t->sym);
-		else if(mustname) {
-			// have to give it a name so we can refer to it in trampoline
+		if(mustname && (t->sym == nil || strcmp(t->sym->name, "_") == 0)) {
+			// invent a name so that we can refer to it in the trampoline
 			snprint(buf, sizeof buf, ".anon%d", gen++);
 			n = newname(lookup(buf));
-		}
+		} else if(t->sym)
+			n = newname(t->sym);
 		a = nod(ODCLFIELD, n, typenod(t->type));
 		a->isddd = t->isddd;
 		if(n != N)
@@ -3212,7 +2393,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
 	int isddd;
 	Val v;
 
-	if(0 && debug['r'])
+	if(debug['r'])
 		print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
 			rcvr, method, newnam);
 
@@ -3226,8 +2407,6 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
 	in = structargs(getinarg(method->type), 1);
 	out = structargs(getoutarg(method->type), 0);
 
-	fn = nod(ODCLFUNC, N, N);
-	fn->nname = newname(newnam);
 	t = nod(OTFUNC, N, N);
 	l = list1(this);
 	if(iface && rcvr->width < types[tptr]->width) {
@@ -3244,7 +2423,12 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
 	}
 	t->list = concat(l, in);
 	t->rlist = out;
+
+	fn = nod(ODCLFUNC, N, N);
+	fn->nname = newname(newnam);
+	fn->nname->defn = fn;
 	fn->nname->ntype = t;
+	declare(fn->nname, PFUNC);
 	funchdr(fn);
 
 	// arg list
@@ -3298,6 +2482,443 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
 	funccompile(fn, 0);
 }
 
+static Node*
+hashmem(Type *t, vlong width)
+{
+	Node *tfn, *n;
+	Sym *sym;
+	
+	sym = pkglookup("memhash", runtimepkg);
+
+	n = newname(sym);
+	n->class = PFUNC;
+	tfn = nod(OTFUNC, N, N);
+	tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(types[TUINTPTR]))));
+	tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+	tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
+	typecheck(&tfn, Etype);
+	n->type = tfn->type;
+	return n;
+}
+
+static Node*
+hashfor(Type *t)
+{
+	int a;
+	Sym *sym;
+	Node *tfn, *n;
+
+	a = algtype1(t, nil);
+	switch(a) {
+	case AMEM:
+		return hashmem(t, t->width);
+	case AINTER:
+		sym = pkglookup("interhash", runtimepkg);
+		break;
+	case ANILINTER:
+		sym = pkglookup("nilinterhash", runtimepkg);
+		break;
+	case ASTRING:
+		sym = pkglookup("strhash", runtimepkg);
+		break;
+	case AFLOAT32:
+		sym = pkglookup("f32hash", runtimepkg);
+		break;
+	case AFLOAT64:
+		sym = pkglookup("f64hash", runtimepkg);
+		break;
+	case ACPLX64:
+		sym = pkglookup("c64hash", runtimepkg);
+		break;
+	case ACPLX128:
+		sym = pkglookup("c128hash", runtimepkg);
+		break;
+	default:
+		sym = typesymprefix(".hash", t);
+		break;
+	}
+
+	n = newname(sym);
+	n->class = PFUNC;
+	tfn = nod(OTFUNC, N, N);
+	tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(types[TUINTPTR]))));
+	tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+	tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
+	typecheck(&tfn, Etype);
+	n->type = tfn->type;
+	return n;
+}
+
+/*
+ * Generate a helper function to compute the hash of a value of type t.
+ */
+void
+genhash(Sym *sym, Type *t)
+{
+	Node *n, *fn, *np, *nh, *ni, *call, *nx, *na, *tfn;
+	Node *hashel;
+	Type *first, *t1;
+	int old_safemode;
+	int64 size, mul;
+
+	if(debug['r'])
+		print("genhash %S %T\n", sym, t);
+
+	lineno = 1;  // less confusing than end of input
+	dclcontext = PEXTERN;
+	markdcl();
+
+	// func sym(h *uintptr, s uintptr, p *T)
+	fn = nod(ODCLFUNC, N, N);
+	fn->nname = newname(sym);
+	fn->nname->class = PFUNC;
+	tfn = nod(OTFUNC, N, N);
+	fn->nname->ntype = tfn;
+
+	n = nod(ODCLFIELD, newname(lookup("h")), typenod(ptrto(types[TUINTPTR])));
+	tfn->list = list(tfn->list, n);
+	nh = n->left;
+	n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR]));
+	tfn->list = list(tfn->list, n);
+	n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t)));
+	tfn->list = list(tfn->list, n);
+	np = n->left;
+
+	funchdr(fn);
+	typecheck(&fn->nname->ntype, Etype);
+
+	// genhash is only called for types that have equality but
+	// cannot be handled by the standard algorithms,
+	// so t must be either an array or a struct.
+	switch(t->etype) {
+	default:
+		fatal("genhash %T", t);
+	case TARRAY:
+		if(isslice(t))
+			fatal("genhash %T", t);
+		// An array of pure memory would be handled by the
+		// standard algorithm, so the element type must not be
+		// pure memory.
+		hashel = hashfor(t->type);
+		n = nod(ORANGE, N, nod(OIND, np, N));
+		ni = newname(lookup("i"));
+		ni->type = types[TINT];
+		n->list = list1(ni);
+		n->colas = 1;
+		colasdefn(n->list, n);
+		ni = n->list->n;
+
+		// *h = *h<<3 | *h>>61
+		n->nbody = list(n->nbody,
+			nod(OAS,
+				nod(OIND, nh, N),
+				nod(OOR,
+					nod(OLSH, nod(OIND, nh, N), nodintconst(3)),
+					nod(ORSH, nod(OIND, nh, N), nodintconst(widthptr*8-3)))));
+
+		// *h *= mul
+		// Same multipliers as in runtime.memhash.
+		if(widthptr == 4)
+			mul = 3267000013LL;
+		else
+			mul = 23344194077549503LL;
+		n->nbody = list(n->nbody,
+			nod(OAS,
+				nod(OIND, nh, N),
+				nod(OMUL, nod(OIND, nh, N), nodintconst(mul))));
+
+		// hashel(h, sizeof(p[i]), &p[i])
+		call = nod(OCALL, hashel, N);
+		call->list = list(call->list, nh);
+		call->list = list(call->list, nodintconst(t->type->width));
+		nx = nod(OINDEX, np, ni);
+		nx->etype = 1;  // no bounds check
+		na = nod(OADDR, nx, N);
+		na->etype = 1;  // no escape to heap
+		call->list = list(call->list, na);
+		n->nbody = list(n->nbody, call);
+
+		fn->nbody = list(fn->nbody, n);
+		break;
+
+	case TSTRUCT:
+		// Walk the struct using memhash for runs of AMEM
+		// and calling specific hash functions for the others.
+		first = T;
+		for(t1=t->type;; t1=t1->down) {
+			if(t1 != T && algtype1(t1->type, nil) == AMEM) {
+				if(first == T)
+					first = t1;
+				continue;
+			}
+			// Run memhash for fields up to this one.
+			if(first != T) {
+				if(first->down == t1)
+					size = first->type->width;
+				else if(t1 == T)
+					size = t->width - first->width;  // first->width is offset
+				else
+					size = t1->width - first->width;  // both are offsets
+				hashel = hashmem(first->type, size);
+				// hashel(h, size, &p.first)
+				call = nod(OCALL, hashel, N);
+				call->list = list(call->list, nh);
+				call->list = list(call->list, nodintconst(size));
+				nx = nod(OXDOT, np, newname(first->sym));  // TODO: fields from other packages?
+				na = nod(OADDR, nx, N);
+				na->etype = 1;  // no escape to heap
+				call->list = list(call->list, na);
+				fn->nbody = list(fn->nbody, call);
+
+				first = T;
+			}
+			if(t1 == T)
+				break;
+
+			// Run hash for this field.
+			hashel = hashfor(t1->type);
+			// hashel(h, size, &p.t1)
+			call = nod(OCALL, hashel, N);
+			call->list = list(call->list, nh);
+			call->list = list(call->list, nodintconst(t1->type->width));
+			nx = nod(OXDOT, np, newname(t1->sym));  // TODO: fields from other packages?
+			na = nod(OADDR, nx, N);
+			na->etype = 1;  // no escape to heap
+			call->list = list(call->list, na);
+			fn->nbody = list(fn->nbody, call);
+		}
+		break;
+	}
+
+	if(debug['r'])
+		dumplist("genhash body", fn->nbody);
+
+	funcbody(fn);
+	curfn = fn;
+	fn->dupok = 1;
+	typecheck(&fn, Etop);
+	typechecklist(fn->nbody, Etop);
+	curfn = nil;
+
+	// Disable safemode while compiling this code: the code we
+	// generate internally can refer to unsafe.Pointer.
+	// In this case it can happen if we need to generate an ==
+	// for a struct containing a reflect.Value, which itself has
+	// an unexported field of type unsafe.Pointer.
+	old_safemode = safemode;
+	safemode = 0;
+	funccompile(fn, 0);
+	safemode = old_safemode;
+}
+
+// Return node for
+//	if p.field != q.field { *eq = false; return }
+static Node*
+eqfield(Node *p, Node *q, Node *field, Node *eq)
+{
+	Node *nif, *nx, *ny;
+
+	nx = nod(OXDOT, p, field);
+	ny = nod(OXDOT, q, field);
+	nif = nod(OIF, N, N);
+	nif->ntest = nod(ONE, nx, ny);
+	nif->nbody = list(nif->nbody, nod(OAS, nod(OIND, eq, N), nodbool(0)));
+	nif->nbody = list(nif->nbody, nod(ORETURN, N, N));
+	return nif;
+}
+
+static Node*
+eqmemfunc(vlong size, Type *type)
+{
+	char buf[30];
+	Node *fn;
+
+	switch(size) {
+	default:
+		fn = syslook("memequal", 1);
+		break;
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+	case 16:
+		snprint(buf, sizeof buf, "memequal%d", (int)size*8);
+		fn = syslook(buf, 1);
+		break;
+	}
+	argtype(fn, type);
+	argtype(fn, type);
+	return fn;
+}
+
+// Return node for
+//	if memequal(size, &p.field, &q.field, eq); !*eq { return }
+static Node*
+eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq)
+{
+	Node *nif, *nx, *ny, *call;
+
+	nx = nod(OADDR, nod(OXDOT, p, field), N);
+	nx->etype = 1;  // does not escape
+	ny = nod(OADDR, nod(OXDOT, q, field), N);
+	ny->etype = 1;  // does not escape
+	typecheck(&nx, Erv);
+	typecheck(&ny, Erv);
+
+	call = nod(OCALL, eqmemfunc(size, nx->type->type), N);
+	call->list = list(call->list, eq);
+	call->list = list(call->list, nodintconst(size));
+	call->list = list(call->list, nx);
+	call->list = list(call->list, ny);
+
+	nif = nod(OIF, N, N);
+	nif->ninit = list(nif->ninit, call);
+	nif->ntest = nod(ONOT, nod(OIND, eq, N), N);
+	nif->nbody = list(nif->nbody, nod(ORETURN, N, N));
+	return nif;
+}
+
+/*
+ * Generate a helper function to check equality of two values of type t.
+ */
+void
+geneq(Sym *sym, Type *t)
+{
+	Node *n, *fn, *np, *neq, *nq, *tfn, *nif, *ni, *nx, *ny, *nrange;
+	Type *t1, *first;
+	int old_safemode;
+	int64 size;
+
+	if(debug['r'])
+		print("geneq %S %T\n", sym, t);
+
+	lineno = 1;  // less confusing than end of input
+	dclcontext = PEXTERN;
+	markdcl();
+
+	// func sym(eq *bool, s uintptr, p, q *T)
+	fn = nod(ODCLFUNC, N, N);
+	fn->nname = newname(sym);
+	fn->nname->class = PFUNC;
+	tfn = nod(OTFUNC, N, N);
+	fn->nname->ntype = tfn;
+
+	n = nod(ODCLFIELD, newname(lookup("eq")), typenod(ptrto(types[TBOOL])));
+	tfn->list = list(tfn->list, n);
+	neq = n->left;
+	n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR]));
+	tfn->list = list(tfn->list, n);
+	n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t)));
+	tfn->list = list(tfn->list, n);
+	np = n->left;
+	n = nod(ODCLFIELD, newname(lookup("q")), typenod(ptrto(t)));
+	tfn->list = list(tfn->list, n);
+	nq = n->left;
+
+	funchdr(fn);
+
+	// geneq is only called for types that have equality but
+	// cannot be handled by the standard algorithms,
+	// so t must be either an array or a struct.
+	switch(t->etype) {
+	default:
+		fatal("geneq %T", t);
+	case TARRAY:
+		if(isslice(t))
+			fatal("geneq %T", t);
+		// An array of pure memory would be handled by the
+		// standard memequal, so the element type must not be
+		// pure memory.  Even if we unrolled the range loop,
+		// each iteration would be a function call, so don't bother
+		// unrolling.
+		nrange = nod(ORANGE, N, nod(OIND, np, N));
+		ni = newname(lookup("i"));
+		ni->type = types[TINT];
+		nrange->list = list1(ni);
+		nrange->colas = 1;
+		colasdefn(nrange->list, nrange);
+		ni = nrange->list->n;
+		
+		// if p[i] != q[i] { *eq = false; return }
+		nx = nod(OINDEX, np, ni);
+		nx->etype = 1;  // no bounds check
+		ny = nod(OINDEX, nq, ni);
+		ny->etype = 1;  // no bounds check
+
+		nif = nod(OIF, N, N);
+		nif->ntest = nod(ONE, nx, ny);
+		nif->nbody = list(nif->nbody, nod(OAS, nod(OIND, neq, N), nodbool(0)));
+		nif->nbody = list(nif->nbody, nod(ORETURN, N, N));
+		nrange->nbody = list(nrange->nbody, nif);
+		fn->nbody = list(fn->nbody, nrange);
+
+		// *eq = true;
+		fn->nbody = list(fn->nbody, nod(OAS, nod(OIND, neq, N), nodbool(1)));
+		break;
+
+	case TSTRUCT:
+		// Walk the struct using memequal for runs of AMEM
+		// and calling specific equality tests for the others.
+		first = T;
+		for(t1=t->type;; t1=t1->down) {
+			if(t1 != T && algtype1(t1->type, nil) == AMEM) {
+				if(first == T)
+					first = t1;
+				continue;
+			}
+			// Run memequal for fields up to this one.
+			// TODO(rsc): All the calls to newname are wrong for
+			// cross-package unexported fields.
+			if(first != T) {
+				if(first->down == t1) {
+					fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
+				} else if(first->down->down == t1) {
+					fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
+					first = first->down;
+					fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq));
+				} else {
+					// More than two fields: use memequal.
+					if(t1 == T)
+						size = t->width - first->width;  // first->width is offset
+					else
+						size = t1->width - first->width;  // both are offsets
+					fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size, neq));
+				}
+				first = T;
+			}
+			if(t1 == T)
+				break;
+
+			// Check this field, which is not just memory.
+			fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym), neq));
+		}
+
+		// *eq = true;
+		fn->nbody = list(fn->nbody, nod(OAS, nod(OIND, neq, N), nodbool(1)));
+		break;
+	}
+
+	if(debug['r'])
+		dumplist("geneq body", fn->nbody);
+
+	funcbody(fn);
+	curfn = fn;
+	fn->dupok = 1;
+	typecheck(&fn, Etop);
+	typechecklist(fn->nbody, Etop);
+	curfn = nil;
+	
+	// Disable safemode while compiling this code: the code we
+	// generate internally can refer to unsafe.Pointer.
+	// In this case it can happen if we need to generate an ==
+	// for a struct containing a reflect.Value, which itself has
+	// an unexported field of type unsafe.Pointer.
+	old_safemode = safemode;
+	safemode = 0;
+	funccompile(fn, 0);
+	safemode = old_safemode;
+}
+
 static Type*
 ifacelookdot(Sym *s, Type *t, int *followptr, int ignorecase)
 {
@@ -3855,21 +3476,31 @@ ngotype(Node *n)
 }
 
 /*
- * Convert raw string to the prefix that will be used in the symbol table.
- * Invalid bytes turn into %xx.  Right now the only bytes that need
- * escaping are %, ., and ", but we escape all control characters too.
+ * Convert raw string to the prefix that will be used in the symbol
+ * table.  All control characters, space, '%' and '"', as well as
+ * non-7-bit clean bytes turn into %xx.  The period needs escaping
+ * only in the last segment of the path, and it makes for happier
+ * users if we escape that as little as possible.
+ *
+ * If you edit this, edit ../ld/lib.c:/^pathtoprefix copy too.
  */
 static char*
 pathtoprefix(char *s)
 {
 	static char hex[] = "0123456789abcdef";
-	char *p, *r, *w;
+	char *p, *r, *w, *l;
 	int n;
 
+	// find first character past the last slash, if any.
+	l = s;
+	for(r=s; *r; r++)
+		if(*r == '/')
+			l = r+1;
+
 	// check for chars that need escaping
 	n = 0;
 	for(r=s; *r; r++)
-		if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"')
+		if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f)
 			n++;
 
 	// quick exit
@@ -3879,7 +3510,7 @@ pathtoprefix(char *s)
 	// escape
 	p = mal((r-s)+1+2*n);
 	for(r=s, w=p; *r; r++) {
-		if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"') {
+		if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f) {
 			*w++ = '%';
 			*w++ = hex[(*r>>4)&0xF];
 			*w++ = hex[*r&0xF];
@@ -3924,3 +3555,26 @@ strlit(char *s)
 	t->len = strlen(s);
 	return t;
 }
+
+void
+addinit(Node **np, NodeList *init)
+{
+	Node *n;
+	
+	if(init == nil)
+		return;
+
+	n = *np;
+	switch(n->op) {
+	case ONAME:
+	case OLITERAL:
+		// There may be multiple refs to this node;
+		// introduce OCONVNOP to hold init list.
+		n = nod(OCONVNOP, n, N);
+		n->type = n->left->type;
+		n->typecheck = 1;
+		*np = n;
+		break;
+	}
+	n->ninit = concat(init, n->ninit);
+}
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index 0381132..f1a9558 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -132,6 +132,7 @@ exprcmp(Case *c1, Case *c2)
 		n = mpcmpfltflt(n1->val.u.fval, n2->val.u.fval);
 		break;
 	case CTINT:
+	case CTRUNE:
 		n = mpcmpfixfix(n1->val.u.xval, n2->val.u.xval);
 		break;
 	case CTSTR:
@@ -380,6 +381,7 @@ mkcaselist(Node *sw, int arg)
 			switch(consttype(n->left)) {
 			case CTFLT:
 			case CTINT:
+			case CTRUNE:
 			case CTSTR:
 				c->type = Texprconst;
 			}
@@ -538,7 +540,7 @@ loop:
 	}
 
 	// deal with the variables one-at-a-time
-	if(c0->type != Texprconst) {
+	if(!okforcmp[t->etype] || c0->type != Texprconst) {
 		a = exprbsw(c0, 1, arg);
 		cas = list(cas, a);
 		c0 = c0->link;
@@ -790,7 +792,6 @@ walkswitch(Node *sw)
 	 * cases have OGOTO into statements.
 	 * both have inserted OBREAK statements
 	 */
-	walkstmtlist(sw->ninit);
 	if(sw->ntest == N) {
 		sw->ntest = nodbool(1);
 		typecheck(&sw->ntest, Erv);
@@ -810,14 +811,16 @@ walkswitch(Node *sw)
 void
 typecheckswitch(Node *n)
 {
-	int top, lno;
-	Type *t;
+	int top, lno, ptr;
+	char *nilonly;
+	Type *t, *missing, *have;
 	NodeList *l, *ll;
 	Node *ncase, *nvar;
 	Node *def;
 
 	lno = lineno;
 	typechecklist(n->ninit, Etop);
+	nilonly = nil;
 
 	if(n->ntest != N && n->ntest->op == OTYPESW) {
 		// type switch
@@ -825,7 +828,7 @@ typecheckswitch(Node *n)
 		typecheck(&n->ntest->right, Erv);
 		t = n->ntest->right->type;
 		if(t != T && t->etype != TINTER)
-			yyerror("cannot type switch on non-interface value %+N", n->ntest->right);
+			yyerror("cannot type switch on non-interface value %lN", n->ntest->right);
 	} else {
 		// value switch
 		top = Erv;
@@ -835,6 +838,16 @@ typecheckswitch(Node *n)
 			t = n->ntest->type;
 		} else
 			t = types[TBOOL];
+		if(t) {
+			if(!okforeq[t->etype] || isfixedarray(t))
+				yyerror("cannot switch on %lN", n->ntest);
+			else if(t->etype == TARRAY)
+				nilonly = "slice";
+			else if(t->etype == TFUNC)
+				nilonly = "func";
+			else if(t->etype == TMAP)
+				nilonly = "map";
+		}
 	}
 	n->type = t;
 
@@ -854,21 +867,37 @@ typecheckswitch(Node *n)
 				typecheck(&ll->n, Erv | Etype);
 				if(ll->n->type == T || t == T)
 					continue;
+				setlineno(ncase);
 				switch(top) {
 				case Erv:	// expression switch
 					defaultlit(&ll->n, t);
 					if(ll->n->op == OTYPE)
 						yyerror("type %T is not an expression", ll->n->type);
-					else if(ll->n->type != T && !eqtype(ll->n->type, t))
-						yyerror("case %+N in %T switch", ll->n, t);
+					else if(ll->n->type != T && !assignop(ll->n->type, t, nil) && !assignop(t, ll->n->type, nil)) {
+						if(n->ntest)
+							yyerror("invalid case %N in switch on %N (mismatched types %T and %T)", ll->n, n->ntest, ll->n->type, t);
+						else
+							yyerror("invalid case %N in switch (mismatched types %T and bool)", ll->n, ll->n->type);
+					} else if(nilonly && !isconst(ll->n, CTNIL)) {
+						yyerror("invalid case %N in switch (can only compare %s %N to nil)", ll->n, nilonly, n->ntest);
+					}
 					break;
 				case Etype:	// type switch
 					if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) {
 						;
-					} else if(ll->n->op != OTYPE && ll->n->type != T) {
-						yyerror("%#N is not a type", ll->n);
+					} else if(ll->n->op != OTYPE && ll->n->type != T) {  // should this be ||?
+						yyerror("%lN is not a type", ll->n);
 						// reset to original type
 						ll->n = n->ntest->right;
+					} else if(ll->n->type->etype != TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) {
+						if(have && !missing->broke && !have->broke)
+							yyerror("impossible type switch case: %lN cannot have dynamic type %T"
+								" (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT",
+								n->ntest->right, ll->n->type, missing->sym, have->sym, have->type,
+								missing->sym, missing->type);
+						else if(!missing->broke)
+							yyerror("impossible type switch case: %lN cannot have dynamic type %T"
+								" (missing %S method)", n->ntest->right, ll->n->type, missing->sym);
 					}
 					break;
 				}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index b9c302c..2e8c3b1 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -43,7 +43,7 @@ resolve(Node *n)
 {
 	Node *r;
 
-	if(n != N && n->op == ONONAME && (r = n->sym->def) != N) {
+	if(n != N && n->op == ONONAME && n->sym != S && (r = n->sym->def) != N) {
 		if(r->op != OIOTA)
 			n = r;
 		else if(n->iota >= 0)
@@ -79,6 +79,7 @@ static char* _typekind[] = {
 	[TSTRING]	= "string",
 	[TPTR32]	= "pointer",
 	[TPTR64]	= "pointer",
+	[TUNSAFEPTR]	= "unsafe.Pointer",
 	[TSTRUCT]	= "struct",
 	[TINTER]	= "interface",
 	[TCHAN]		= "chan",
@@ -90,11 +91,15 @@ static char* _typekind[] = {
 };
 
 static char*
-typekind(int et)
+typekind(Type *t)
 {
+	int et;
 	static char buf[50];
 	char *s;
 	
+	if(isslice(t))
+		return "slice";
+	et = t->etype;
 	if(0 <= et && et < nelem(_typekind) && (s=_typekind[et]) != nil)
 		return s;
 	snprint(buf, sizeof buf, "etype=%d", et);
@@ -113,8 +118,7 @@ typecheck(Node **np, int top)
 	Node *n, *l, *r;
 	NodeList *args;
 	int lno, ok, ntop;
-	Type *t, *tp, *ft, *missing, *have;
-	Sym *sym;
+	Type *t, *tp, *ft, *missing, *have, *badtype;
 	Val v;
 	char *why;
 
@@ -153,7 +157,7 @@ typecheck(Node **np, int top)
 	}
 
 	if(n->typecheck == 2) {
-		yyerror("typechecking loop involving %#N", n);
+		yyerror("typechecking loop involving %N", n);
 		lineno = lno;
 		return n;
 	}
@@ -210,6 +214,10 @@ reswitch:
 			}
 			n->used = 1;
 		}
+		if(!(top &Ecall) && isunsafebuiltin(n)) {
+			yyerror("%N is not an expression, must be called", n);
+			goto error;
+		}
 		ok |= Erv;
 		goto ret;
 
@@ -254,13 +262,14 @@ reswitch:
 			l = typecheck(&n->left, Erv);
 			switch(consttype(l)) {
 			case CTINT:
+			case CTRUNE:
 				v = l->val;
 				break;
 			case CTFLT:
 				v = toint(l->val);
 				break;
 			default:
-				yyerror("invalid array bound %#N", l);
+				yyerror("invalid array bound %N", l);
 				goto error;
 			}
 			t->bound = mpgetfix(v.u.xval);
@@ -311,7 +320,7 @@ reswitch:
 	case OTSTRUCT:
 		ok |= Etype;
 		n->op = OTYPE;
-		n->type = dostruct(n->list, TSTRUCT);
+		n->type = tostruct(n->list);
 		if(n->type == T)
 			goto error;
 		n->list = nil;
@@ -320,7 +329,7 @@ reswitch:
 	case OTINTER:
 		ok |= Etype;
 		n->op = OTYPE;
-		n->type = dostruct(n->list, TINTER);
+		n->type = tointerface(n->list);
 		if(n->type == T)
 			goto error;
 		break;
@@ -340,6 +349,7 @@ reswitch:
 		ntop = Erv | Etype;
 		if(!(top & Eaddr))  		// The *x in &*x is not an indirect.
 			ntop |= Eindir;
+		ntop |= top & Ecomplit;
 		l = typecheck(&n->left, ntop);
 		if((t = l->type) == T)
 			goto error;
@@ -351,7 +361,7 @@ reswitch:
 			goto ret;
 		}
 		if(!isptr[t->etype]) {
-			yyerror("invalid indirect of %+N", n->left);
+			yyerror("invalid indirect of %lN", n->left);
 			goto error;
 		}
 		ok |= Erv;
@@ -414,15 +424,25 @@ reswitch:
 		if(iscmp[n->op] && t->etype != TIDEAL && !eqtype(l->type, r->type)) {
 			// comparison is okay as long as one side is
 			// assignable to the other.  convert so they have
-			// the same type.  (the only conversion that isn't
-			// a no-op is concrete == interface.)
+			// the same type.
+			//
+			// the only conversion that isn't a no-op is concrete == interface.
+			// in that case, check comparability of the concrete type.
 			if(r->type->etype != TBLANK && (aop = assignop(l->type, r->type, nil)) != 0) {
+				if(isinter(r->type) && !isinter(l->type) && algtype1(l->type, nil) == ANOEQ) {
+					yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(l->type));
+					goto error;
+				}
 				l = nod(aop, l, N);
 				l->type = r->type;
 				l->typecheck = 1;
 				n->left = l;
 				t = l->type;
 			} else if(l->type->etype != TBLANK && (aop = assignop(r->type, l->type, nil)) != 0) {
+				if(isinter(l->type) && !isinter(r->type) && algtype1(r->type, nil) == ANOEQ) {
+					yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(r->type));
+					goto error;
+				}
 				r = nod(aop, r, N);
 				r->type = l->type;
 				r->typecheck = 1;
@@ -433,24 +453,36 @@ reswitch:
 		}
 		if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
 			defaultlit2(&l, &r, 1);
-			yyerror("invalid operation: %#N (mismatched types %T and %T)", n, l->type, r->type);
+			yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
 			goto error;
 		}
 		if(!okfor[op][et]) {
-		notokfor:
-			yyerror("invalid operation: %#N (operator %#O not defined on %s)", n, op, typekind(et));
+			yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(t));
+			goto error;
+		}
+		// okfor allows any array == array, map == map, func == func.
+		// restrict to slice/map/func == nil and nil == slice/map/func.
+		if(isfixedarray(l->type) && algtype1(l->type, nil) == ANOEQ) {
+			yyerror("invalid operation: %N (%T cannot be compared)", n, l->type);
 			goto error;
 		}
-		// okfor allows any array == array;
-		// restrict to slice == nil and nil == slice.
-		if(l->type->etype == TARRAY && !isslice(l->type))
-			goto notokfor;
-		if(r->type->etype == TARRAY && !isslice(r->type))
-			goto notokfor;
 		if(isslice(l->type) && !isnil(l) && !isnil(r)) {
-			yyerror("invalid operation: %#N (slice can only be compared to nil)", n);
+			yyerror("invalid operation: %N (slice can only be compared to nil)", n);
 			goto error;
 		}
+		if(l->type->etype == TMAP && !isnil(l) && !isnil(r)) {
+			yyerror("invalid operation: %N (map can only be compared to nil)", n);
+			goto error;
+		}
+		if(l->type->etype == TFUNC && !isnil(l) && !isnil(r)) {
+			yyerror("invalid operation: %N (func can only be compared to nil)", n);
+			goto error;
+		}
+		if(l->type->etype == TSTRUCT && algtype1(l->type, &badtype) == ANOEQ) {
+			yyerror("invalid operation: %N (struct containing %T cannot be compared)", n, badtype);
+			goto error;
+		}
+		
 		t = l->type;
 		if(iscmp[n->op]) {
 			evconst(n);
@@ -488,12 +520,12 @@ reswitch:
 		n->right = r;
 		t = r->type;
 		if(!isint[t->etype] || issigned[t->etype]) {
-			yyerror("invalid operation: %#N (shift count type %T, must be unsigned integer)", n, r->type);
+			yyerror("invalid operation: %N (shift count type %T, must be unsigned integer)", n, r->type);
 			goto error;
 		}
 		t = l->type;
 		if(t != T && t->etype != TIDEAL && !isint[t->etype]) {
-			yyerror("invalid operation: %#N (shift of type %T)", n, t);
+			yyerror("invalid operation: %N (shift of type %T)", n, t);
 			goto error;
 		}
 		// no defaultlit for left
@@ -510,7 +542,7 @@ reswitch:
 		if((t = l->type) == T)
 			goto error;
 		if(!okfor[n->op][t->etype]) {
-			yyerror("invalid operation: %#O %T", n->op, t);
+			yyerror("invalid operation: %O %T", n->op, t);
 			goto error;
 		}
 		n->type = t;
@@ -524,21 +556,17 @@ reswitch:
 		typecheck(&n->left, Erv | Eaddr);
 		if(n->left->type == T)
 			goto error;
-		switch(n->left->op) {
-		case OMAPLIT:
-		case OSTRUCTLIT:
-		case OARRAYLIT:
-			break;
-		default:
-			checklvalue(n->left, "take the address of");
-		}
+		checklvalue(n->left, "take the address of");
+		for(l=n->left; l->op == ODOT; l=l->left)
+			l->addrtaken = 1;
+		l->addrtaken = 1;
 		defaultlit(&n->left, T);
 		l = n->left;
 		if((t = l->type) == T)
 			goto error;
 		// top&Eindir means this is &x in *&x.  (or the arg to built-in print)
 		// n->etype means code generator flagged it as non-escaping.
-		if(debug['s'] && !(top & Eindir) && !n->etype)
+		if(debug['N'] && !(top & Eindir) && !n->etype)
 			addrescapes(n->left);
 		n->type = ptrto(t);
 		goto ret;
@@ -557,36 +585,34 @@ reswitch:
 	case ODOT:
 		typecheck(&n->left, Erv|Etype);
 		defaultlit(&n->left, T);
-		l = n->left;
-		if((t = l->type) == T)
+		if((t = n->left->type) == T)
 			goto error;
 		if(n->right->op != ONAME) {
 			yyerror("rhs of . must be a name");	// impossible
 			goto error;
 		}
-		sym = n->right->sym;
-		if(l->op == OTYPE) {
+
+		if(n->left->op == OTYPE) {
 			if(!looktypedot(n, t, 0)) {
 				if(looktypedot(n, t, 1))
-					yyerror("%#N undefined (cannot refer to unexported method %S)", n, n->right->sym);
+					yyerror("%N undefined (cannot refer to unexported method %S)", n, n->right->sym);
 				else
-					yyerror("%#N undefined (type %T has no method %S)", n, t, n->right->sym);
+					yyerror("%N undefined (type %T has no method %S)", n, t, n->right->sym);
 				goto error;
 			}
 			if(n->type->etype != TFUNC || n->type->thistuple != 1) {
-				yyerror("type %T has no method %hS", n->left->type, sym);
+				yyerror("type %T has no method %hS", n->left->type, n->right->sym);
 				n->type = T;
 				goto error;
 			}
 			n->op = ONAME;
-			n->sym = methodsym(sym, l->type, 0);
-			n->type = methodfunc(n->type, l->type);
+			n->sym = n->right->sym;
+			n->type = methodfunc(n->type, n->left->type);
 			n->xoffset = 0;
 			n->class = PFUNC;
 			ok = Erv;
 			goto ret;
 		}
-		tp = t;
 		if(isptr[t->etype] && t->type->etype != TINTER) {
 			t = t->type;
 			if(t == T)
@@ -596,9 +622,9 @@ reswitch:
 		}
 		if(!lookdot(n, t, 0)) {
 			if(lookdot(n, t, 1))
-				yyerror("%#N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);
+				yyerror("%N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);
 			else
-				yyerror("%#N undefined (type %T has no field or method %S)", n, tp, n->right->sym);
+				yyerror("%N undefined (type %T has no field or method %S)", n, n->left->type, n->right->sym);
 			goto error;
 		}
 		switch(n->op) {
@@ -620,7 +646,7 @@ reswitch:
 		if((t = l->type) == T)
 			goto error;
 		if(!isinter(t)) {
-			yyerror("invalid type assertion: %#N (non-interface type %T on left)", n, t);
+			yyerror("invalid type assertion: %N (non-interface type %T on left)", n, t);
 			goto error;
 		}
 		if(n->right != N) {
@@ -633,12 +659,12 @@ reswitch:
 		if(n->type != T && n->type->etype != TINTER)
 		if(!implements(n->type, t, &missing, &have, &ptr)) {
 			if(have)
-				yyerror("impossible type assertion: %+N cannot have dynamic type %T"
-					" (wrong type for %S method)\n\thave %S%hhT\n\twant %S%hhT",
+				yyerror("impossible type assertion: %lN cannot have dynamic type %T"
+					" (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT",
 					l, n->type, missing->sym, have->sym, have->type,
 					missing->sym, missing->type);
 			else
-				yyerror("impossible type assertion: %+N cannot have dynamic type %T"
+				yyerror("impossible type assertion: %lN cannot have dynamic type %T"
 					" (missing %S method)", l, n->type, missing->sym);
 			goto error;
 		}
@@ -656,13 +682,13 @@ reswitch:
 			goto error;
 		switch(t->etype) {
 		default:
-			yyerror("invalid operation: %#N (index of type %T)", n, t);
+			yyerror("invalid operation: %N (index of type %T)", n, t);
 			goto error;
 
 		case TARRAY:
 			defaultlit(&n->right, T);
 			if(n->right->type != T && !isint[n->right->type->etype])
-				yyerror("non-integer array index %#N", n->right);
+				yyerror("non-integer array index %N", n->right);
 			n->type = t->type;
 			break;
 
@@ -678,7 +704,7 @@ reswitch:
 		case TSTRING:
 			defaultlit(&n->right, types[TUINT]);
 			if(n->right->type != T && !isint[n->right->type->etype])
-				yyerror("non-integer string index %#N", n->right);
+				yyerror("non-integer string index %N", n->right);
 			n->type = types[TUINT8];
 			break;
 		}
@@ -692,11 +718,11 @@ reswitch:
 		if((t = l->type) == T)
 			goto error;
 		if(t->etype != TCHAN) {
-			yyerror("invalid operation: %#N (receive from non-chan type %T)", n, t);
+			yyerror("invalid operation: %N (receive from non-chan type %T)", n, t);
 			goto error;
 		}
 		if(!(t->chan & Crecv)) {
-			yyerror("invalid operation: %#N (receive from send-only type %T)", n, t);
+			yyerror("invalid operation: %N (receive from send-only type %T)", n, t);
 			goto error;
 		}
 		n->type = t->type;
@@ -704,7 +730,7 @@ reswitch:
 
 	case OSEND:
 		if(top & Erv) {
-			yyerror("send statement %#N used as value; use select for non-blocking send", n);
+			yyerror("send statement %N used as value; use select for non-blocking send", n);
 			goto error;
 		}
 		ok |= Etop | Erv;
@@ -715,11 +741,11 @@ reswitch:
 		if((t = l->type) == T)
 			goto error;
 		if(t->etype != TCHAN) {
-			yyerror("invalid operation: %#N (send to non-chan type %T)", n, t);
+			yyerror("invalid operation: %N (send to non-chan type %T)", n, t);
 			goto error;
 		}
 		if(!(t->chan & Csend)) {
-			yyerror("invalid operation: %#N (send to receive-only type %T)", n, t);
+			yyerror("invalid operation: %N (send to receive-only type %T)", n, t);
 			goto error;
 		}
 		defaultlit(&n->right, t->type);
@@ -741,14 +767,19 @@ reswitch:
 		defaultlit(&n->right->left, T);
 		defaultlit(&n->right->right, T);
 		if(isfixedarray(n->left->type)) {
+			if(!islvalue(n->left)) {
+				yyerror("invalid operation %N (slice of unaddressable value)", n);
+				goto error;
+			}
 			n->left = nod(OADDR, n->left, N);
-			typecheck(&n->left, top);
+			n->left->implicit = 1;
+			typecheck(&n->left, Erv);
 		}
 		if(n->right->left != N) {
 			if((t = n->right->left->type) == T)
 				goto error;
 			if(!isint[t->etype]) {
-				yyerror("invalid slice index %#N (type %T)", n->right->left, t);
+				yyerror("invalid slice index %N (type %T)", n->right->left, t);
 				goto error;
 			}
 		}
@@ -756,7 +787,7 @@ reswitch:
 			if((t = n->right->right->type) == T)
 				goto error;
 			if(!isint[t->etype]) {
-				yyerror("invalid slice index %#N (type %T)", n->right->right, t);
+				yyerror("invalid slice index %N (type %T)", n->right->right, t);
 				goto error;
 			}
 		}
@@ -780,7 +811,7 @@ reswitch:
 			n->type = t;
 			goto ret;
 		}
-		yyerror("cannot slice %#N (type %T)", l, t);
+		yyerror("cannot slice %N (type %T)", l, t);
 		goto error;
 
 	/*
@@ -790,7 +821,7 @@ reswitch:
 		l = n->left;
 		if(l->op == ONAME && (r = unsafenmagic(n)) != N) {
 			if(n->isddd)
-				yyerror("invalid use of ... with builtin %#N", l);
+				yyerror("invalid use of ... with builtin %N", l);
 			n = r;
 			goto reswitch;
 		}
@@ -798,7 +829,7 @@ reswitch:
 		l = n->left;
 		if(l->op == ONAME && l->etype != 0) {
 			if(n->isddd && l->etype != OAPPEND)
-				yyerror("invalid use of ... with builtin %#N", l);
+				yyerror("invalid use of ... with builtin %N", l);
 			// builtin: OLEN, OCAP, etc.
 			n->op = l->etype;
 			n->left = n->right;
@@ -848,7 +879,7 @@ reswitch:
 		default:
 			n->op = OCALLFUNC;
 			if(t->etype != TFUNC) {
-				yyerror("cannot call non-function %#N (type %T)", l, t);
+				yyerror("cannot call non-function %N (type %T)", l, t);
 				goto error;
 			}
 			break;
@@ -869,7 +900,7 @@ reswitch:
 		}
 		// multiple return
 		if(!(top & (Efnstruct | Etop))) {
-			yyerror("multiple-value %#N() in single-value context", l);
+			yyerror("multiple-value %N() in single-value context", l);
 			goto ret;
 		}
 		n->type = getoutargx(l->type);
@@ -880,7 +911,7 @@ reswitch:
 	case OREAL:
 	case OIMAG:
 		ok |= Erv;
-		if(onearg(n, "%#O", n->op) < 0)
+		if(onearg(n, "%O", n->op) < 0)
 			goto error;
 		typecheck(&n->left, Erv);
 		defaultlit(&n->left, T);
@@ -946,7 +977,7 @@ reswitch:
 		n->right = r;
 		if(l->type->etype != r->type->etype) {
 		badcmplx:
-			yyerror("invalid operation: %#N (complex of types %T, %T)", n, l->type, r->type);
+			yyerror("invalid operation: %N (complex of types %T, %T)", n, l->type, r->type);
 			goto error;
 		}
 		switch(l->type->etype) {
@@ -970,7 +1001,7 @@ reswitch:
 		goto ret;
 
 	case OCLOSE:
-		if(onearg(n, "%#O", n->op) < 0)
+		if(onearg(n, "%O", n->op) < 0)
 			goto error;
 		typecheck(&n->left, Erv);
 		defaultlit(&n->left, T);
@@ -978,10 +1009,39 @@ reswitch:
 		if((t = l->type) == T)
 			goto error;
 		if(t->etype != TCHAN) {
-			yyerror("invalid operation: %#N (non-chan type %T)", n, t);
+			yyerror("invalid operation: %N (non-chan type %T)", n, t);
+			goto error;
+		}
+		if(!(t->chan & Csend)) {
+			yyerror("invalid operation: %N (cannot close receive-only channel)", n);
+			goto error;
+		}
+		ok |= Etop;
+		goto ret;
+
+	case ODELETE:
+		args = n->list;
+		if(args == nil) {
+			yyerror("missing arguments to delete");
+			goto error;
+		}
+		if(args->next == nil) {
+			yyerror("missing second (key) argument to delete");
+			goto error;
+		}
+		if(args->next->next != nil) {
+			yyerror("too many arguments to delete");
 			goto error;
 		}
 		ok |= Etop;
+		typechecklist(args, Erv);
+		l = args->n;
+		r = args->next->n;
+		if(l->type != T && l->type->etype != TMAP) {
+			yyerror("first argument to delete must be map; have %lT", l->type);
+			goto error;
+		}
+		args->next->n = assignconv(r, l->type->down, "delete");
 		goto ret;
 
 	case OAPPEND:
@@ -999,6 +1059,7 @@ reswitch:
 			yyerror("first argument to append must be slice; have %lT", t);
 			goto error;
 		}
+
 		if(n->isddd) {
 			if(args->next == nil) {
 				yyerror("cannot use ... on first argument to append");
@@ -1008,6 +1069,10 @@ reswitch:
 				yyerror("too many arguments to append");
 				goto error;
 			}
+			if(istype(t->type, TUINT8) && istype(args->next->n->type, TSTRING)) {
+				defaultlit(&args->next->n, types[TSTRING]);
+				goto ret;
+			}
 			args->next->n = assignconv(args->next->n, t->orig, "append");
 			goto ret;
 		}
@@ -1039,15 +1104,15 @@ reswitch:
 			goto error;
 		defaultlit(&n->left, T);
 		defaultlit(&n->right, T);
-		
+
 		// copy([]byte, string)
 		if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
-			if(n->left->type->type == types[TUINT8])
+			if(eqtype(n->left->type->type, bytetype))
 				goto ret;
 			yyerror("arguments to copy have different element types: %lT and string", n->left->type);
 			goto error;
 		}
-			       
+
 		if(!isslice(n->left->type) || !isslice(n->right->type)) {
 			if(!isslice(n->left->type) && !isslice(n->right->type))
 				yyerror("arguments to copy must be slices; have %lT, %lT", n->left->type, n->right->type);
@@ -1071,7 +1136,7 @@ reswitch:
 		if((t = n->left->type) == T || n->type == T)
 			goto error;
 		if((n->op = convertop(t, n->type, &why)) == 0) {
-			yyerror("cannot convert %+N to type %T%s", n->left, n->type, why);
+			yyerror("cannot convert %lN to type %T%s", n->left, n->type, why);
 			n->op = OCONV;
 		}
 		switch(n->op) {
@@ -1096,6 +1161,7 @@ reswitch:
 			yyerror("missing argument to make");
 			goto error;
 		}
+		n->list = nil;
 		l = args->n;
 		args = args->next;
 		typecheck(&l, Etype);
@@ -1275,7 +1341,7 @@ reswitch:
 		typechecklist(n->ninit, Etop);
 		typecheck(&n->ntest, Erv);
 		if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
-			yyerror("non-bool %+N used as for condition", n->ntest);
+			yyerror("non-bool %lN used as for condition", n->ntest);
 		typecheck(&n->nincr, Etop);
 		typechecklist(n->nbody, Etop);
 		goto ret;
@@ -1285,7 +1351,7 @@ reswitch:
 		typechecklist(n->ninit, Etop);
 		typecheck(&n->ntest, Erv);
 		if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
-			yyerror("non-bool %+N used as if condition", n->ntest);
+			yyerror("non-bool %lN used as if condition", n->ntest);
 		typechecklist(n->nbody, Etop);
 		typechecklist(n->nelse, Etop);
 		goto ret;
@@ -1372,21 +1438,21 @@ ret:
 		goto error;
 	}
 	if((top & (Erv|Etype)) == Etype && n->op != OTYPE) {
-		yyerror("%#N is not a type", n);
+		yyerror("%N is not a type", n);
 		goto error;
 	}
 	if((ok & Ecall) && !(top & Ecall)) {
-		yyerror("method %#N is not an expression, must be called", n);
+		yyerror("method %N is not an expression, must be called", n);
 		goto error;
 	}
 	// TODO(rsc): simplify
 	if((top & (Ecall|Erv|Etype)) && !(top & Etop) && !(ok & (Erv|Etype|Ecall))) {
-		yyerror("%#N used as value", n);
+		yyerror("%N used as value", n);
 		goto error;
 	}
 	if((top & Etop) && !(top & (Ecall|Erv|Etype)) && !(ok & Etop)) {
 		if(n->diag == 0) {
-			yyerror("%#N not used", n);
+			yyerror("%N not used", n);
 			n->diag = 1;
 		}
 		goto error;
@@ -1399,7 +1465,7 @@ ret:
 	goto out;
 
 badcall1:
-	yyerror("invalid argument %#N (type %T) for %#O", n->left, n->left->type, n->op);
+	yyerror("invalid argument %lN for %O", n->left, n->op);
 	goto error;
 
 error:
@@ -1445,14 +1511,14 @@ onearg(Node *n, char *f, ...)
 		va_start(arg, f);
 		p = vsmprint(f, arg);
 		va_end(arg);
-		yyerror("missing argument to %s: %#N", p, n);
+		yyerror("missing argument to %s: %N", p, n);
 		return -1;
 	}
 	if(n->list->next != nil) {
 		va_start(arg, f);
 		p = vsmprint(f, arg);
 		va_end(arg);
-		yyerror("too many arguments to %s: %#N", p, n);
+		yyerror("too many arguments to %s: %N", p, n);
 		n->left = n->list->n;
 		n->list = nil;
 		return -1;
@@ -1468,17 +1534,17 @@ twoarg(Node *n)
 	if(n->left != N)
 		return 0;
 	if(n->list == nil) {
-		yyerror("missing argument to %#O - %#N", n->op, n);
+		yyerror("missing argument to %O - %N", n->op, n);
 		return -1;
 	}
 	n->left = n->list->n;
 	if(n->list->next == nil) {
-		yyerror("missing argument to %#O - %#N", n->op, n);
+		yyerror("missing argument to %O - %N", n->op, n);
 		n->list = nil;
 		return -1;
 	}
 	if(n->list->next->next != nil) {
-		yyerror("too many arguments to %#O - %#N", n->op, n);
+		yyerror("too many arguments to %O - %N", n->op, n);
 		n->list = nil;
 		return -1;
 	}
@@ -1499,7 +1565,7 @@ lookdot1(Sym *s, Type *t, Type *f, int dostrcmp)
 		if(f->sym != s)
 			continue;
 		if(r != T) {
-			yyerror("ambiguous DOT reference %T.%S", t, s);
+			yyerror("ambiguous selector %T.%S", t, s);
 			break;
 		}
 		r = f;
@@ -1547,7 +1613,7 @@ looktypedot(Node *n, Type *t, int dostrcmp)
 	&& !isptr[t->etype]
 	&& f2->embedded != 2
 	&& !isifacemethod(f2->type)) {
-		yyerror("invalid method expression %#N (needs pointer receiver: (*%T).%s)", n, t, f2->sym->name);
+		yyerror("invalid method expression %N (needs pointer receiver: (*%T).%hS)", n, t, f2->sym);
 		return 0;
 	}
 
@@ -1558,6 +1624,14 @@ looktypedot(Node *n, Type *t, int dostrcmp)
 	return 1;
 }
 
+static Type*
+derefall(Type* t)
+{
+	while(t && t->etype == tptr)
+		t = t->type;
+	return t;
+}
+
 static int
 lookdot(Node *n, Type *t, int dostrcmp)
 {
@@ -1583,7 +1657,7 @@ lookdot(Node *n, Type *t, int dostrcmp)
 
 	if(f1 != T) {
 		if(f2 != T)
-			yyerror("ambiguous DOT reference %S as both field and method",
+			yyerror("%S is both field and method",
 				n->right->sym);
 		if(f1->width == BADWIDTH)
 			fatal("lookdot badwidth %T %p", f1, f1);
@@ -1606,7 +1680,7 @@ lookdot(Node *n, Type *t, int dostrcmp)
 		if(!eqtype(rcvr, tt)) {
 			if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) {
 				checklvalue(n->left, "call pointer method on");
-				if(debug['s'])
+				if(debug['N'])
 					addrescapes(n->left);
 				n->left = nod(OADDR, n->left, N);
 				n->left->implicit = 1;
@@ -1615,14 +1689,22 @@ lookdot(Node *n, Type *t, int dostrcmp)
 				n->left = nod(OIND, n->left, N);
 				n->left->implicit = 1;
 				typecheck(&n->left, Etype|Erv);
+			} else if(tt->etype == tptr && tt->type->etype == tptr && eqtype(derefall(tt), rcvr)) {
+				yyerror("calling method %N with receiver %lN requires explicit dereference", n->right, n->left);
+				while(tt->etype == tptr) {
+					n->left = nod(OIND, n->left, N);
+					n->left->implicit = 1;
+					typecheck(&n->left, Etype|Erv);
+					tt = tt->type;
+				}
 			} else {
-				// method is attached to wrong type?
 				fatal("method mismatch: %T for %T", rcvr, tt);
 			}
 		}
 		n->right = methodname(n->right, n->left->type);
 		n->xoffset = f2->width;
 		n->type = f2->type;
+//		print("lookdot found [%p] %T\n", f2->type, f2->type);
 		n->op = ODOTMETH;
 		return 1;
 	}
@@ -1661,22 +1743,20 @@ typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *
 		for(tl=tstruct->type; tl; tl=tl->down) {
 			if(tl->isddd) {
 				for(; tn; tn=tn->down) {
-					exportassignok(tn->type, desc);
 					if(assignop(tn->type, tl->type->type, &why) == 0) {
 						if(call != N)
-							yyerror("cannot use %T as type %T in argument to %#N%s", tn->type, tl->type->type, call, why);
+							yyerror("cannot use %T as type %T in argument to %N%s", tn->type, tl->type, call, why);
 						else
-							yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type->type, desc, why);
+							yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why);
 					}
 				}
 				goto out;
 			}
 			if(tn == T)
 				goto notenough;
-			exportassignok(tn->type, desc);
 			if(assignop(tn->type, tl->type, &why) == 0) {
 				if(call != N)
-					yyerror("cannot use %T as type %T in argument to %#N%s", tn->type, tl->type, call, why);
+					yyerror("cannot use %T as type %T in argument to %N%s", tn->type, tl->type, call, why);
 				else
 					yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why);
 			}
@@ -1721,9 +1801,9 @@ typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *
 		goto toomany;
 	if(isddd) {
 		if(call != N)
-			yyerror("invalid use of ... in call to %#N", call);
+			yyerror("invalid use of ... in call to %N", call);
 		else
-			yyerror("invalid use of ... in %#O", op);
+			yyerror("invalid use of ... in %O", op);
 	}
 
 out:
@@ -1732,80 +1812,20 @@ out:
 
 notenough:
 	if(call != N)
-		yyerror("not enough arguments in call to %#N", call);
+		yyerror("not enough arguments in call to %N", call);
 	else
-		yyerror("not enough arguments to %#O", op);
+		yyerror("not enough arguments to %O", op);
 	goto out;
 
 toomany:
 	if(call != N)
-		yyerror("too many arguments in call to %#N", call);
+		yyerror("too many arguments in call to %N", call);
 	else
-		yyerror("too many arguments to %#O", op);
+		yyerror("too many arguments to %O", op);
 	goto out;
 }
 
 /*
- * do the export rules allow writing to this type?
- * cannot be implicitly assigning to any type with
- * an unavailable field.
- */
-int
-exportassignok(Type *t, char *desc)
-{
-	Type *f;
-	Sym *s;
-
-	if(t == T)
-		return 1;
-	if(t->trecur)
-		return 1;
-	t->trecur = 1;
-
-	switch(t->etype) {
-	default:
-		// most types can't contain others; they're all fine.
-		break;
-	case TSTRUCT:
-		for(f=t->type; f; f=f->down) {
-			if(f->etype != TFIELD)
-				fatal("structas: not field");
-			s = f->sym;
-			// s == nil doesn't happen for embedded fields (they get the type symbol).
-			// it only happens for fields in a ... struct.
-			if(s != nil && !exportname(s->name) && s->pkg != localpkg) {
-				char *prefix;
-
-				prefix = "";
-				if(desc != nil)
-					prefix = " in ";
-				else
-					desc = "";
-				yyerror("implicit assignment of unexported field '%s' of %T%s%s", s->name, t, prefix, desc);
-				goto no;
-			}
-			if(!exportassignok(f->type, desc))
-				goto no;
-		}
-		break;
-
-	case TARRAY:
-		if(t->bound < 0)	// slices are pointers; that's fine
-			break;
-		if(!exportassignok(t->type, desc))
-			goto no;
-		break;
-	}
-	t->trecur = 0;
-	return 1;
-
-no:
-	t->trecur = 0;
-	return 0;
-}
-
-
-/*
  * type check composite
  */
 
@@ -1850,6 +1870,7 @@ keydup(Node *n, Node *hash[], ulong nhash)
 		b = 23;
 		break;
 	case CTINT:
+	case CTRUNE:
 		b = mpgetfix(n->val.u.xval);
 		break;
 	case CTFLT:
@@ -1958,13 +1979,51 @@ inithash(Node *n, Node ***hash, Node **autohash, ulong nautohash)
 	return h;
 }
 
+static int
+iscomptype(Type *t)
+{
+	switch(t->etype) {
+	case TARRAY:
+	case TSTRUCT:
+	case TMAP:
+		return 1;
+	case TPTR32:
+	case TPTR64:
+		switch(t->type->etype) {
+		case TARRAY:
+		case TSTRUCT:
+		case TMAP:
+			return 1;
+		}
+		break;
+	}
+	return 0;
+}
+
+static void
+pushtype(Node *n, Type *t)
+{
+	if(n == N || n->op != OCOMPLIT || !iscomptype(t))
+		return;
+	
+	if(n->right == N) {
+		n->right = typenod(t);
+		n->right->implicit = 1;
+	}
+	else if(debug['s']) {
+		typecheck(&n->right, Etype);
+		if(n->right->type != T && eqtype(n->right->type, t))
+			print("%lL: redundant type: %T\n", n->lineno, t);
+	}
+}
+
 static void
 typecheckcomplit(Node **np)
 {
 	int bad, i, len, nerr;
-	Node *l, *n, **hash;
+	Node *l, *n, *r, **hash;
 	NodeList *ll;
-	Type *t, *f, *pushtype;
+	Type *t, *f;
 	Sym *s;
 	int32 lno;
 	ulong nhash;
@@ -1979,30 +2038,29 @@ typecheckcomplit(Node **np)
 		yyerror("missing type in composite literal");
 		goto error;
 	}
-
+	
 	setlineno(n->right);
 	l = typecheck(&n->right /* sic */, Etype|Ecomplit);
 	if((t = l->type) == T)
 		goto error;
 	nerr = nerrors;
-
-	// can omit type on composite literal values if the outer
-	// composite literal is array, slice, or map, and the 
-	// element type is itself a struct, array, slice, or map.
-	pushtype = T;
-	if(t->etype == TARRAY || t->etype == TMAP) {
-		pushtype = t->type;
-		if(pushtype != T) {
-			switch(pushtype->etype) {
-			case TSTRUCT:
-			case TARRAY:
-			case TMAP:
-				break;
-			default:
-				pushtype = T;
-				break;
-			}
+	n->type = t;
+	
+	if(isptr[t->etype]) {
+		// For better or worse, we don't allow pointers as
+		// the composite literal type, except when using
+		// the &T syntax, which sets implicit.
+		if(!n->right->implicit) {
+			yyerror("invalid pointer type %T for composite literal (use &%T instead)", t, t->type);
+			goto error;
+		}
+		
+		// Also, the underlying type must be a struct, map, slice, or array.
+		if(!iscomptype(t)) {
+			yyerror("invalid pointer type %T for composite literal", t);
+			goto error;
 		}
+		t = t->type;		
 	}
 
 	switch(t->etype) {
@@ -2045,11 +2103,11 @@ typecheckcomplit(Node **np)
 				}
 			}
 
-			if(l->right->op == OCOMPLIT && l->right->right == N && pushtype != T)
-				l->right->right = typenod(pushtype);
-			typecheck(&l->right, Erv);
-			defaultlit(&l->right, t->type);
-			l->right = assignconv(l->right, t->type, "array element");
+			r = l->right;
+			pushtype(r, t->type);
+			typecheck(&r, Erv);
+			defaultlit(&r, t->type);
+			l->right = assignconv(r, t->type, "array element");
 		}
 		if(t->bound == -100)
 			t->bound = len;
@@ -2073,13 +2131,14 @@ typecheckcomplit(Node **np)
 			typecheck(&l->left, Erv);
 			defaultlit(&l->left, t->down);
 			l->left = assignconv(l->left, t->down, "map key");
-			keydup(l->left, hash, nhash);
+			if (l->left->op != OCONV)
+				keydup(l->left, hash, nhash);
 
-			if(l->right->op == OCOMPLIT && l->right->right == N && pushtype != T)
-				l->right->right = typenod(pushtype);
-			typecheck(&l->right, Erv);
-			defaultlit(&l->right, t->type);
-			l->right = assignconv(l->right, t->type, "map value");
+			r = l->right;
+			pushtype(r, t->type);
+			typecheck(&r, Erv);
+			defaultlit(&r, t->type);
+			l->right = assignconv(r, t->type, "map value");
 		}
 		n->op = OMAPLIT;
 		break;
@@ -2100,6 +2159,7 @@ typecheckcomplit(Node **np)
 				s = f->sym;
 				if(s != nil && !exportname(s->name) && s->pkg != localpkg)
 					yyerror("implicit assignment of unexported field '%s' in %T literal", s->name, t);
+				// No pushtype allowed here.  Must name fields for that.
 				ll->n = assignconv(ll->n, f->type, "field value");
 				ll->n = nod(OKEY, newname(f->sym), ll->n);
 				ll->n->left->type = f;
@@ -2123,19 +2183,20 @@ typecheckcomplit(Node **np)
 				}
 				s = l->left->sym;
 				if(s == S) {
-					yyerror("invalid field name %#N in struct initializer", l->left);
+					yyerror("invalid field name %N in struct initializer", l->left);
 					typecheck(&l->right, Erv);
 					continue;
 				}
+
 				// Sym might have resolved to name in other top-level
 				// package, because of import dot.  Redirect to correct sym
 				// before we do the lookup.
-				if(s->pkg != localpkg)
+				if(s->pkg != localpkg && exportname(s->name))
 					s = lookup(s->name);
+
 				f = lookdot1(s, t, t->type, 0);
-				typecheck(&l->right, Erv);
 				if(f == nil) {
-					yyerror("unknown %T field '%s' in struct literal", t, s->name);
+					yyerror("unknown %T field '%S' in struct literal", t, s);
 					continue;
 				}
 				l->left = newname(s);
@@ -2143,7 +2204,10 @@ typecheckcomplit(Node **np)
 				l->left->type = f;
 				s = f->sym;
 				fielddup(newname(s), hash, nhash);
-				l->right = assignconv(l->right, f->type, "field value");
+				r = l->right;
+				// No pushtype allowed here.  Tried and rejected.
+				typecheck(&r, Erv);
+				l->right = assignconv(r, f->type, "field value");
 			}
 		}
 		n->op = OSTRUCTLIT;
@@ -2151,7 +2215,14 @@ typecheckcomplit(Node **np)
 	}
 	if(nerr != nerrors)
 		goto error;
-	n->type = t;
+	
+	if(isptr[n->type->etype]) {
+		n = nod(OPTRLIT, n, N);
+		n->typecheck = 1;
+		n->type = n->left->type;
+		n->left->type = t;
+		n->left->typecheck = 1;
+	}
 
 	*np = n;
 	lineno = lno;
@@ -2193,7 +2264,7 @@ static void
 checklvalue(Node *n, char *verb)
 {
 	if(!islvalue(n))
-		yyerror("cannot %s %#N", verb, n);
+		yyerror("cannot %s %N", verb, n);
 }
 
 static void
@@ -2205,7 +2276,7 @@ checkassign(Node *n)
 		n->etype = 1;
 		return;
 	}
-	yyerror("cannot assign to %#N", n);
+	yyerror("cannot assign to %N", n);
 }
 
 static void
@@ -2240,8 +2311,6 @@ typecheckas(Node *n)
 	if(n->right && n->right->type != T) {
 		if(n->left->type != T)
 			n->right = assignconv(n->right, n->left->type, "assignment");
-		else if(!isblank(n->left))
-			exportassignok(n->right->type, "assignment");
 	}
 	if(n->left->defn == n && n->left->ntype == N) {
 		defaultlit(&n->right, T);
@@ -2262,10 +2331,9 @@ checkassignto(Type *src, Node *dst)
 	char *why;
 
 	if(assignop(src, dst->type, &why) == 0) {
-		yyerror("cannot assign %T to %+N in multiple assignment%s", src, dst, why);
+		yyerror("cannot assign %T to %lN in multiple assignment%s", src, dst, why);
 		return;
 	}
-	exportassignok(dst->type, "multiple assignment");
 }
 
 static void
@@ -2312,10 +2380,7 @@ typecheckas2(Node *n)
 	if(cl == 1 && cr == 2 && l->op == OINDEXMAP) {
 		if(l->type == T)
 			goto out;
-		n->op = OAS2MAPW;
-		n->rlist->n = assignconv(r, l->type, "assignment");
-		r = n->rlist->next->n;
-		n->rlist->next->n = assignconv(r, types[TBOOL], "assignment");
+		yyerror("assignment count mismatch: %d = %d (use delete)", cl, cr);
 		goto out;
 	}
 
@@ -2397,7 +2462,7 @@ typecheckfunc(Node *n)
 	if((t = n->nname->type) == T)
 		return;
 	n->type = t;
-
+	t->nname = n->nname;
 	rcvr = getthisx(t)->type;
 	if(rcvr != nil && n->shortname != N && !isblank(n->shortname))
 		addmethod(n->shortname->sym, t, 1);
@@ -2427,7 +2492,7 @@ stringtoarraylit(Node **np)
 		while(p < ep)
 			l = list(l, nod(OKEY, nodintconst(i++), nodintconst((uchar)*p++)));
 	} else {
-		// utf-8 []int
+		// utf-8 []rune
 		while(p < ep) {
 			p += chartorune(&r, p);
 			l = list(l, nod(OKEY, nodintconst(i++), nodintconst(r)));
@@ -2467,6 +2532,7 @@ static void
 domethod(Node *n)
 {
 	Node *nt;
+	Type *t;
 
 	nt = n->type->nname;
 	typecheck(&nt, Etype);
@@ -2476,6 +2542,20 @@ domethod(Node *n)
 		n->type->nod = N;
 		return;
 	}
+	
+	// If we have
+	//	type I interface {
+	//		M(_ int)
+	//	}
+	// then even though I.M looks like it doesn't care about the
+	// value of its argument, a specific implementation of I may
+	// care.  The _ would suppress the assignment to that argument
+	// while generating a call, so remove it.
+	for(t=getinargx(nt->type)->type; t; t=t->down) {
+		if(t->sym != nil && strcmp(t->sym->name, "_") == 0)
+			t->sym = nil;
+	}
+
 	*n->type = *nt->type;
 	n->type->nod = N;
 	checkwidth(n->type);
@@ -2532,6 +2612,7 @@ copytype(Node *n, Type *t)
 	t->vargen = n->vargen;
 	t->siggen = 0;
 	t->method = nil;
+	t->xmethod = nil;
 	t->nod = N;
 	t->printed = 0;
 	t->deferwidth = 0;
@@ -2689,7 +2770,7 @@ typecheckdef(Node *n)
 				goto ret;
 			}
 			if(!isideal(e->type) && !eqtype(t, e->type)) {
-				yyerror("cannot use %+N as type %T in const initializer", e, t);
+				yyerror("cannot use %lN as type %T in const initializer", e, t);
 				goto ret;
 			}
 			convlit(&e, t);
diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c
index 6435492..95200ad 100644
--- a/src/cmd/gc/unsafe.c
+++ b/src/cmd/gc/unsafe.c
@@ -10,6 +10,7 @@
  * look for
  *	unsafe.Sizeof
  *	unsafe.Offsetof
+ *	unsafe.Alignof
  * rewrite with a constant
  */
 Node*
@@ -22,7 +23,7 @@ unsafenmagic(Node *nn)
 	Val val;
 	Node *fn;
 	NodeList *args;
-	
+
 	fn = nn->left;
 	args = nn->list;
 
@@ -80,10 +81,10 @@ no:
 	return N;
 
 bad:
-	yyerror("invalid expression %#N", nn);
+	yyerror("invalid expression %N", nn);
 	v = 0;
 	goto ret;
-	
+
 yes:
 	if(args->next != nil)
 		yyerror("extra arguments for %S", s);
@@ -93,7 +94,23 @@ ret:
 	val.u.xval = mal(sizeof(*n->val.u.xval));
 	mpmovecfix(val.u.xval, v);
 	n = nod(OLITERAL, N, N);
+	n->orig = nn;
 	n->val = val;
 	n->type = types[TUINTPTR];
+	nn->type = types[TUINTPTR];
 	return n;
 }
+
+int
+isunsafebuiltin(Node *n)
+{
+	if(n == N || n->op != ONAME || n->sym == S || n->sym->pkg != unsafepkg)
+		return 0;
+	if(strcmp(n->sym->name, "Sizeof") == 0)
+		return 1;
+	if(strcmp(n->sym->name, "Offsetof") == 0)
+		return 1;
+	if(strcmp(n->sym->name, "Alignof") == 0)
+		return 1;
+	return 0;
+}
diff --git a/src/cmd/gc/unsafe.go b/src/cmd/gc/unsafe.go
index db27d74..c7b48a8 100644
--- a/src/cmd/gc/unsafe.go
+++ b/src/cmd/gc/unsafe.go
@@ -6,6 +6,8 @@
 // to update builtin.c.boot.  This is not done automatically
 // to avoid depending on having a working compiler binary.
 
+// +build ignore
+
 package PACKAGE
 
 type Pointer uintptr // not really; filled in by compiler
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 8a84956..53040fe 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -7,9 +7,8 @@
 #include	"go.h"
 
 static	Node*	walkprint(Node*, NodeList**, int);
-static	Node*	conv(Node*, Type*);
 static	Node*	mapfn(char*, Type*);
-static	Node*	makenewvar(Type*, NodeList**, Node**);
+static	Node*	mapfndel(char*, Type*);
 static	Node*	ascompatee1(int, Node*, Node*, NodeList**);
 static	NodeList*	ascompatee(int, NodeList*, NodeList*, NodeList**);
 static	NodeList*	ascompatet(int, NodeList*, Type**, int, NodeList**);
@@ -22,6 +21,7 @@ static	NodeList*	reorder3(NodeList*);
 static	Node*	addstr(Node*, NodeList**);
 static	Node*	appendslice(Node*, NodeList**);
 static	Node*	append(Node*, NodeList**);
+static	void	walkcompare(Node**, NodeList**);
 
 // can this code branch reach the end
 // without an unconditional RETURN
@@ -62,7 +62,6 @@ walk(Node *fn)
 {
 	char s[50];
 	NodeList *l;
-	Node *n;
 	int lno;
 
 	curfn = fn;
@@ -76,15 +75,33 @@ walk(Node *fn)
 			yyerror("function ends without a return statement");
 
 	lno = lineno;
+
+	// Final typecheck for any unused variables.
+	// It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
+	for(l=fn->dcl; l; l=l->next)
+		if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO)
+			typecheck(&l->n, Erv | Easgn);
+
+	// Propagate the used flag for typeswitch variables up to the NONAME in it's definition.
+	for(l=fn->dcl; l; l=l->next)
+		if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO && l->n->defn && l->n->defn->op == OTYPESW && l->n->used)
+			l->n->defn->left->used++;
+	
 	for(l=fn->dcl; l; l=l->next) {
-		n = l->n;
-		if(n->op != ONAME || n->class != PAUTO)
+		if(l->n->op != ONAME || (l->n->class&~PHEAP) != PAUTO || l->n->sym->name[0] == '&' || l->n->used)
 			continue;
-		lineno = n->lineno;
-		typecheck(&n, Erv | Easgn);	// only needed for unused variables
-		if(!n->used && n->sym->name[0] != '&' && !nsyntaxerrors)
-			yyerror("%S declared and not used", n->sym);
-	}
+		if(l->n->defn && l->n->defn->op == OTYPESW) {
+			if(l->n->defn->left->used)
+				continue;
+			lineno = l->n->defn->left->lineno;
+			yyerror("%S declared and not used", l->n->sym);
+			l->n->defn->left->used = 1; // suppress repeats
+		} else {
+			lineno = l->n->lineno;
+			yyerror("%S declared and not used", l->n->sym);
+		}
+	}	
+
 	lineno = lno;
 	if(nerrors != 0)
 		return;
@@ -121,11 +138,12 @@ static int
 paramoutheap(Node *fn)
 {
 	NodeList *l;
-	
+
 	for(l=fn->dcl; l; l=l->next) {
 		switch(l->n->class) {
+		case PPARAMOUT:
 		case PPARAMOUT|PHEAP:
-			return 1;
+			return l->n->addrtaken;
 		case PAUTO:
 		case PAUTO|PHEAP:
 			// stop early - parameters are over
@@ -149,6 +167,8 @@ walkstmt(Node **np)
 
 	setlineno(n);
 
+	walkstmtlist(n->ninit);
+
 	switch(n->op) {
 	default:
 		if(n->op == ONAME)
@@ -164,7 +184,6 @@ walkstmt(Node **np)
 	case OAS2DOTTYPE:
 	case OAS2RECV:
 	case OAS2FUNC:
-	case OAS2MAPW:
 	case OAS2MAPR:
 	case OCLOSE:
 	case OCOPY:
@@ -172,6 +191,7 @@ walkstmt(Node **np)
 	case OCALLINTER:
 	case OCALL:
 	case OCALLFUNC:
+	case ODELETE:
 	case OSEND:
 	case ORECV:
 	case OPRINT:
@@ -179,14 +199,12 @@ walkstmt(Node **np)
 	case OPANIC:
 	case OEMPTY:
 	case ORECOVER:
-		if(n->typecheck == 0) {
-			dump("missing typecheck:", n);
-			fatal("missing typecheck");
-		}
+		if(n->typecheck == 0)
+			fatal("missing typecheck: %+N", n);
 		init = n->ninit;
 		n->ninit = nil;
 		walkexpr(&n, &init);
-		n->ninit = concat(init, n->ninit);
+		addinit(&n, init);
 		break;
 
 	case OBREAK:
@@ -225,20 +243,18 @@ walkstmt(Node **np)
 		break;
 
 	case OFOR:
-		walkstmtlist(n->ninit);
 		if(n->ntest != N) {
 			walkstmtlist(n->ntest->ninit);
 			init = n->ntest->ninit;
 			n->ntest->ninit = nil;
 			walkexpr(&n->ntest, &init);
-			n->ntest->ninit = concat(init, n->ntest->ninit);
+			addinit(&n->ntest, init);
 		}
 		walkstmt(&n->nincr);
 		walkstmtlist(n->nbody);
 		break;
 
 	case OIF:
-		walkstmtlist(n->ninit);
 		walkexpr(&n->ntest, &n->ninit);
 		walkstmtlist(n->nbody);
 		walkstmtlist(n->nelse);
@@ -281,10 +297,13 @@ walkstmt(Node **np)
 				// OAS2FUNC in disguise
 				f = n->list->n;
 				if(f->op != OCALLFUNC && f->op != OCALLMETH && f->op != OCALLINTER)
-					fatal("expected return of call, have %#N", f);
+					fatal("expected return of call, have %N", f);
 				n->list = concat(list1(f), ascompatet(n->op, rl, &f->type, 0, &n->ninit));
 				break;
 			}
+
+			// move function calls out, to make reorder3's job easier.
+			walkexprlistsafe(n->list, &n->ninit);
 			ll = ascompatee(n->op, rl, n->list, &n->ninit);
 			n->list = reorder3(ll);
 			break;
@@ -311,6 +330,9 @@ walkstmt(Node **np)
 		break;
 	}
 
+	if(n->op == ONAME)
+		fatal("walkstmt ended up with name: %+N", n);
+	
 	*np = n;
 }
 
@@ -363,6 +385,12 @@ walkexpr(Node **np, NodeList **init)
 		fatal("walkexpr init == &n->ninit");
 	}
 
+	if(n->ninit != nil) {
+		walkstmtlist(n->ninit);
+		*init = concat(*init, n->ninit);
+		n->ninit = nil;
+	}
+
 	// annoying case - not typechecked
 	if(n->op == OKEY) {
 		walkexpr(&n->left, init);
@@ -375,10 +403,8 @@ walkexpr(Node **np, NodeList **init)
 	if(debug['w'] > 1)
 		dump("walk-before", n);
 
-	if(n->typecheck != 1) {
-		dump("missed typecheck", n);
-		fatal("missed typecheck");
-	}
+	if(n->typecheck != 1)
+		fatal("missed typecheck: %+N\n", n);
 
 	switch(n->op) {
 	default:
@@ -409,7 +435,7 @@ walkexpr(Node **np, NodeList **init)
 	case OLEN:
 	case OCAP:
 		walkexpr(&n->left, init);
-		
+
 		// replace len(*[10]int) with 10.
 		// delayed until now to preserve side effects.
 		t = n->left->type;
@@ -421,7 +447,7 @@ walkexpr(Node **np, NodeList **init)
 			n->typecheck = 1;
 		}
 		goto ret;
-	
+
 	case OLSH:
 	case ORSH:
 	case OAND:
@@ -429,8 +455,6 @@ walkexpr(Node **np, NodeList **init)
 	case OXOR:
 	case OSUB:
 	case OMUL:
-	case OEQ:
-	case ONE:
 	case OLT:
 	case OLE:
 	case OGE:
@@ -440,7 +464,14 @@ walkexpr(Node **np, NodeList **init)
 		walkexpr(&n->left, init);
 		walkexpr(&n->right, init);
 		goto ret;
-	
+
+	case OEQ:
+	case ONE:
+		walkexpr(&n->left, init);
+		walkexpr(&n->right, init);
+		walkcompare(&n, init);
+		goto ret;
+
 	case OANDAND:
 	case OOROR:
 		walkexpr(&n->left, init);
@@ -449,7 +480,7 @@ walkexpr(Node **np, NodeList **init)
 		// save elsewhere and store on the eventual n->right.
 		ll = nil;
 		walkexpr(&n->right, &ll);
-		n->right->ninit = concat(n->right->ninit, ll);
+		addinit(&n->right, ll);
 		goto ret;
 
 	case OPRINT:
@@ -553,7 +584,7 @@ walkexpr(Node **np, NodeList **init)
 		walkexprlistsafe(n->list, init);
 		walkexpr(&r, init);
 		l = n->list->n;
-		
+
 		// all the really hard stuff - explicit function calls and so on -
 		// is gone, but map assignments remain.
 		// if there are map assignments here, assign via
@@ -606,15 +637,19 @@ walkexpr(Node **np, NodeList **init)
 		n->op = OAS2FUNC;
 		goto as2func;
 
-	case OAS2MAPW:
-		// map[] = a,b - mapassign2
-		// a,b = m[i];
+	case ODELETE:
 		*init = concat(*init, n->ninit);
 		n->ninit = nil;
-		walkexprlistsafe(n->list, init);
 		l = n->list->n;
-		t = l->left->type;
-		n = mkcall1(mapfn("mapassign2", t), T, init, typename(t), l->left, l->right, n->rlist->n, n->rlist->next->n);
+		r = n->list->next->n;
+		if(n->right != N) {
+			// TODO: Remove once two-element map assigment is gone.
+			l = safeexpr(l, init);
+			r = safeexpr(r, init);
+			safeexpr(n->right, init);  // cause side effects from n->right
+		}
+		t = l->type;
+		n = mkcall1(mapfndel("mapdelete", t), t->down, init, typename(t), l, r);
 		goto ret;
 
 	case OAS2DOTTYPE:
@@ -648,7 +683,7 @@ walkexpr(Node **np, NodeList **init)
 		if(n->op == ODOTTYPE2)
 			*p++ = '2';
 		*p = '\0';
-	
+
 		fn = syslook(buf, 1);
 		ll = list1(typename(n->type));
 		ll = list(ll, n->left);
@@ -679,7 +714,7 @@ walkexpr(Node **np, NodeList **init)
 		else
 			*p++ = 'I';
 		*p = '\0';
-		
+
 		fn = syslook(buf, 1);
 		ll = nil;
 		if(!isinter(n->left->type))
@@ -840,6 +875,7 @@ walkexpr(Node **np, NodeList **init)
 				// delayed until now because "abc"[2] is not
 				// an ideal constant.
 				nodconst(n, n->type, n->left->val.u.sval->s[v]);
+				n->typecheck = 1;
 			}
 		}
 		goto ret;
@@ -894,7 +930,7 @@ walkexpr(Node **np, NodeList **init)
 		}
 		if(v1 >= 0 && v2 >= 0 && v1 > v2)
 			yyerror("inverted slice range");
-		
+
 		if(n->op == OSLICEARR)
 			goto slicearray;
 
@@ -925,7 +961,7 @@ walkexpr(Node **np, NodeList **init)
 				l,
 				nodintconst(t->type->width));
 		}
-		n->etype = et;  // preserve no-typecheck flag from OSLICE to the slice* call.
+		n->etype = et;	// preserve no-typecheck flag from OSLICE to the slice* call.
 		goto ret;
 
 	slicearray:
@@ -950,32 +986,17 @@ walkexpr(Node **np, NodeList **init)
 			nodintconst(t->type->width));
 		goto ret;
 
-	case OADDR:;
-		Node *nvar, *nstar;
-
-		// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
-		// initialize with
-		//	nvar := new(*Point);
-		//	*nvar = Point(1, 2);
-		// and replace expression with nvar
-		switch(n->left->op) {
-		case OARRAYLIT:
-		case OMAPLIT:
-		case OSTRUCTLIT:
-			nvar = makenewvar(n->type, init, &nstar);
-			anylit(0, n->left, nstar, init);
-			n = nvar;
-			goto ret;
-		}
-
+	case OADDR:
 		walkexpr(&n->left, init);
 		goto ret;
 
 	case ONEW:
 		if(n->esc == EscNone && n->type->type->width < (1<<16)) {
 			r = temp(n->type->type);
-			*init = list(*init, nod(OAS, r, N));  // zero temp
-			r = nod(OADDR, r, N);
+			r = nod(OAS, r, N);  // zero temp
+			typecheck(&r, Etop);
+			*init = list(*init, r);
+			r = nod(OADDR, r->left, N);
 			typecheck(&r, Erv);
 			n = r;
 		} else {
@@ -1054,10 +1075,14 @@ walkexpr(Node **np, NodeList **init)
 				l);
 		}
 		goto ret;
-	
+
 	case OAPPEND:
-		if(n->isddd)
-			n = appendslice(n, init);
+		if(n->isddd) {
+			if(istype(n->type->type, TUINT8) && istype(n->list->next->n->type, TSTRING))
+				n = mkcall("appendstr", n->type, init, typename(n->type), n->list->n, n->list->next->n);
+			else
+				n = appendslice(n, init);
+		}
 		else
 			n = append(n, init);
 		goto ret;
@@ -1066,7 +1091,7 @@ walkexpr(Node **np, NodeList **init)
 		if(n->right->type->etype == TSTRING)
 			fn = syslook("slicestringcopy", 1);
 		else
-			fn = syslook("slicecopy", 1);
+			fn = syslook("copy", 1);
 		argtype(fn, n->left->type);
 		argtype(fn, n->right->type);
 		n = mkcall1(fn, n->type, init,
@@ -1126,8 +1151,8 @@ walkexpr(Node **np, NodeList **init)
 		goto ret;
 
 	case OARRAYRUNESTR:
-		// sliceinttostring([]int) string;
-		n = mkcall("sliceinttostring", n->type, init, n->left);
+		// slicerunetostring([]rune) string;
+		n = mkcall("slicerunetostring", n->type, init, n->left);
 		goto ret;
 
 	case OSTRARRAYBYTE:
@@ -1136,8 +1161,8 @@ walkexpr(Node **np, NodeList **init)
 		goto ret;
 
 	case OSTRARRAYRUNE:
-		// stringtosliceint(string) []int
-		n = mkcall("stringtosliceint", n->type, init, n->left);
+		// stringtoslicerune(string) []rune
+		n = mkcall("stringtoslicerune", n->type, init, n->left);
 		goto ret;
 
 	case OCMPIFACE:
@@ -1161,9 +1186,10 @@ walkexpr(Node **np, NodeList **init)
 	case OARRAYLIT:
 	case OMAPLIT:
 	case OSTRUCTLIT:
-		nvar = temp(n->type);
-		anylit(0, n, nvar, init);
-		n = nvar;
+	case OPTRLIT:
+		var = temp(n->type);
+		anylit(0, n, var, init);
+		n = var;
 		goto ret;
 
 	case OSEND:
@@ -1186,22 +1212,6 @@ ret:
 }
 
 static Node*
-makenewvar(Type *t, NodeList **init, Node **nstar)
-{
-	Node *nvar, *nas;
-
-	nvar = temp(t);
-	nas = nod(OAS, nvar, callnew(t->type));
-	typecheck(&nas, Etop);
-	walkexpr(&nas, init);
-	*init = list(*init, nas);
-
-	*nstar = nod(OIND, nvar, N);
-	typecheck(nstar, Erv);
-	return nvar;
-}
-
-static Node*
 ascompatee1(int op, Node *l, Node *r, NodeList **init)
 {
 	USED(op);
@@ -1232,7 +1242,7 @@ ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
 
 	// cannot happen: caller checked that lists had same length
 	if(ll || lr)
-		yyerror("error in shape across %O", op);
+		yyerror("error in shape across %+H %O %+H", nl, op, nr);
 	return nn;
 }
 
@@ -1304,10 +1314,11 @@ ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
 	}
 
 	if(ll != nil || r != T)
-		yyerror("assignment count mismatch: %d = %d",
+		yyerror("ascompatet: assignment count mismatch: %d = %d",
 			count(nl), structcount(*nr));
+
 	if(ucount)
-		fatal("reorder2: too many function calls evaluating parameters");
+		fatal("ascompatet: too many function calls evaluating parameters");
 	return concat(nn, mm);
 }
 
@@ -1319,7 +1330,7 @@ mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, int
 {
 	Node *a, *n;
 	Type *tslice;
-	
+
 	tslice = typ(TARRAY);
 	tslice->type = l->type->type;
 	tslice->bound = -1;
@@ -1413,7 +1424,7 @@ ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeL
 	if(lr)
 		r = lr->n;
 	nn = nil;
-	
+
 	// f(g()) where g has multiple return values
 	if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
 		// optimization - can do block copy
@@ -1423,7 +1434,7 @@ ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeL
 			nn = list1(convas(nod(OAS, a, r), init));
 			goto ret;
 		}
-		
+
 		// conversions involved.
 		// copy into temporaries.
 		alist = nil;
@@ -1540,6 +1551,9 @@ walkprint(Node *nn, NodeList **init, int defer)
 		n = l->n;
 		if(n->op == OLITERAL) {
 			switch(n->val.ctype) {
+			case CTRUNE:
+				defaultlit(&n, runetype);
+				break;
 			case CTINT:
 				defaultlit(&n, types[TINT64]);
 				break;
@@ -1682,7 +1696,7 @@ callnew(Type *t)
 	dowidth(t);
 	fn = syslook("new", 1);
 	argtype(fn, t);
-	return mkcall1(fn, ptrto(t), nil, nodintconst(t->width));
+	return mkcall1(fn, ptrto(t), nil, typename(t));
 }
 
 static Node*
@@ -1714,10 +1728,10 @@ convas(Node *n, NodeList **init)
 			n->left->left, n->left->right, n->right);
 		goto out;
 	}
-	
+
 	if(eqtype(lt, rt))
 		goto out;
-	
+
 	n->right = assignconv(n->right, lt, "assignment");
 	walkexpr(&n->right, init);
 
@@ -1786,28 +1800,242 @@ reorder1(NodeList *all)
 	return concat(g, r);
 }
 
+static void reorder3save(Node**, NodeList*, NodeList*, NodeList**);
+static int aliased(Node*, NodeList*, NodeList*);
+
 /*
  * from ascompat[ee]
  *	a,b = c,d
  * simultaneous assignment. there cannot
  * be later use of an earlier lvalue.
+ *
+ * function calls have been removed.
+ */
+static NodeList*
+reorder3(NodeList *all)
+{
+	NodeList *list, *early;
+	Node *l;
+
+	// If a needed expression may be affected by an
+	// earlier assignment, make an early copy of that
+	// expression and use the copy instead.
+	early = nil;
+	for(list=all; list; list=list->next) {
+		l = list->n->left;
+
+		// Save subexpressions needed on left side.
+		// Drill through non-dereferences.
+		for(;;) {
+			if(l->op == ODOT || l->op == OPAREN) {
+				l = l->left;
+				continue;
+			}
+			if(l->op == OINDEX && isfixedarray(l->left->type)) {
+				reorder3save(&l->right, all, list, &early);
+				l = l->left;
+				continue;
+			}
+			break;
+		}
+		switch(l->op) {
+		default:
+			fatal("reorder3 unexpected lvalue %#O", l->op);
+		case ONAME:
+			break;
+		case OINDEX:
+			reorder3save(&l->left, all, list, &early);
+			reorder3save(&l->right, all, list, &early);
+			break;
+		case OIND:
+		case ODOTPTR:
+			reorder3save(&l->left, all, list, &early);
+		}
+
+		// Save expression on right side.
+		reorder3save(&list->n->right, all, list, &early);
+	}
+
+	return concat(early, all);
+}
+
+static int vmatch2(Node*, Node*);
+static int varexpr(Node*);
+
+/*
+ * if the evaluation of *np would be affected by the 
+ * assignments in all up to but not including stop,
+ * copy into a temporary during *early and
+ * replace *np with that temp.
+ */
+static void
+reorder3save(Node **np, NodeList *all, NodeList *stop, NodeList **early)
+{
+	Node *n, *q;
+
+	n = *np;
+	if(!aliased(n, all, stop))
+		return;
+	
+	q = temp(n->type);
+	q = nod(OAS, q, n);
+	typecheck(&q, Etop);
+	*early = list(*early, q);
+	*np = q->left;
+}
+
+/*
+ * what's the outer value that a write to n affects?
+ * outer value means containing struct or array.
+ */
+static Node*
+outervalue(Node *n)
+{	
+	for(;;) {
+		if(n->op == ODOT || n->op == OPAREN) {
+			n = n->left;
+			continue;
+		}
+		if(n->op == OINDEX && isfixedarray(n->left->type)) {
+			n = n->left;
+			continue;
+		}
+		break;
+	}
+	return n;
+}
+
+/*
+ * Is it possible that the computation of n might be
+ * affected by writes in as up to but not including stop?
+ */
+static int
+aliased(Node *n, NodeList *all, NodeList *stop)
+{
+	int memwrite, varwrite;
+	Node *a;
+	NodeList *l;
+
+	if(n == N)
+		return 0;
+
+	// Look for obvious aliasing: a variable being assigned
+	// during the all list and appearing in n.
+	// Also record whether there are any writes to main memory.
+	// Also record whether there are any writes to variables
+	// whose addresses have been taken.
+	memwrite = 0;
+	varwrite = 0;
+	for(l=all; l!=stop; l=l->next) {
+		a = outervalue(l->n->left);
+		if(a->op != ONAME) {
+			memwrite = 1;
+			continue;
+		}
+		switch(n->class) {
+		default:
+			varwrite = 1;
+			continue;
+		case PAUTO:
+		case PPARAM:
+		case PPARAMOUT:
+			if(n->addrtaken) {
+				varwrite = 1;
+				continue;
+			}
+			if(vmatch2(a, n)) {
+				// Direct hit.
+				return 1;
+			}
+		}
+	}
+
+	// The variables being written do not appear in n.
+	// However, n might refer to computed addresses
+	// that are being written.
+	
+	// If no computed addresses are affected by the writes, no aliasing.
+	if(!memwrite && !varwrite)
+		return 0;
+
+	// If n does not refer to computed addresses
+	// (that is, if n only refers to variables whose addresses
+	// have not been taken), no aliasing.
+	if(varexpr(n))
+		return 0;
+
+	// Otherwise, both the writes and n refer to computed memory addresses.
+	// Assume that they might conflict.
+	return 1;
+}
+
+/*
+ * does the evaluation of n only refer to variables
+ * whose addresses have not been taken?
+ * (and no other memory)
  */
+static int
+varexpr(Node *n)
+{
+	if(n == N)
+		return 1;
+
+	switch(n->op) {
+	case OLITERAL:	
+		return 1;
+	case ONAME:
+		switch(n->class) {
+		case PAUTO:
+		case PPARAM:
+		case PPARAMOUT:
+			if(!n->addrtaken)
+				return 1;
+		}
+		return 0;
 
+	case OADD:
+	case OSUB:
+	case OOR:
+	case OXOR:
+	case OMUL:
+	case ODIV:
+	case OMOD:
+	case OLSH:
+	case ORSH:
+	case OAND:
+	case OANDNOT:
+	case OPLUS:
+	case OMINUS:
+	case OCOM:
+	case OPAREN:
+	case OANDAND:
+	case OOROR:
+	case ODOT:  // but not ODOTPTR
+	case OCONV:
+	case OCONVNOP:
+	case OCONVIFACE:
+	case ODOTTYPE:
+		return varexpr(n->left) && varexpr(n->right);
+	}
+
+	// Be conservative.
+	return 0;
+}
+
+/*
+ * is the name l mentioned in r?
+ */
 static int
 vmatch2(Node *l, Node *r)
 {
 	NodeList *ll;
 
-	/*
-	 * isolate all right sides
-	 */
 	if(r == N)
 		return 0;
 	switch(r->op) {
 	case ONAME:
 		// match each right given left
-		if(l == r)
-			return 1;
+		return l == r;
 	case OLITERAL:
 		return 0;
 	}
@@ -1821,6 +2049,10 @@ vmatch2(Node *l, Node *r)
 	return 0;
 }
 
+/*
+ * is any name mentioned in l also mentioned in r?
+ * called by sinit.c
+ */
 int
 vmatch1(Node *l, Node *r)
 {
@@ -1859,33 +2091,6 @@ vmatch1(Node *l, Node *r)
 	return 0;
 }
 
-static NodeList*
-reorder3(NodeList *all)
-{
-	Node *n1, *n2, *q;
-	int c1, c2;
-	NodeList *l1, *l2, *r;
-
-	r = nil;
-	for(l1=all, c1=0; l1; l1=l1->next, c1++) {
-		n1 = l1->n;
-		for(l2=all, c2=0; l2; l2=l2->next, c2++) {
-			n2 = l2->n;
-			if(c2 > c1) {
-				if(vmatch1(n1->left, n2->right)) {
-					// delay assignment to n1->left
-					q = temp(n1->right->type);
-					q = nod(OAS, n1->left, q);
-					n1->left = q->right;
-					r = list(r, q);
-					break;
-				}
-			}
-		}
-	}
-	return concat(all, r);
-}
-
 /*
  * walk through argin parameters.
  * generate and return code to allocate
@@ -1952,7 +2157,7 @@ heapmoves(void)
 {
 	NodeList *nn;
 	int32 lno;
-	
+
 	lno = lineno;
 	lineno = curfn->lineno;
 	nn = paramstoheap(getthis(curfn->type), 0);
@@ -1972,7 +2177,7 @@ vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
 	NodeList *args;
 
 	if(fn->type == T || fn->type->etype != TFUNC)
-		fatal("mkcall %#N %T", fn, fn->type);
+		fatal("mkcall %N %T", fn, fn->type);
 
 	args = nil;
 	n = fn->type->intuple;
@@ -2014,7 +2219,7 @@ mkcall1(Node *fn, Type *t, NodeList **init, ...)
 	return r;
 }
 
-static Node*
+Node*
 conv(Node *n, Type *t)
 {
 	if(eqtype(n->type, t))
@@ -2055,12 +2260,26 @@ mapfn(char *name, Type *t)
 }
 
 static Node*
+mapfndel(char *name, Type *t)
+{
+	Node *fn;
+
+	if(t->etype != TMAP)
+		fatal("mapfn %T", t);
+	fn = syslook(name, 1);
+	argtype(fn, t->down);
+	argtype(fn, t->type);
+	argtype(fn, t->down);
+	return fn;
+}
+
+static Node*
 addstr(Node *n, NodeList **init)
 {
 	Node *r, *cat, *typstr;
 	NodeList *in, *args;
 	int i, count;
-	
+
 	count = 0;
 	for(r=n; r->op == OADDSTR; r=r->left)
 		count++;	// r->right
@@ -2089,7 +2308,7 @@ addstr(Node *n, NodeList **init)
 	typecheck(&r, Erv);
 	walkexpr(&r, init);
 	r->type = n->type;
-	
+
 	return r;
 }
 
@@ -2097,7 +2316,7 @@ static Node*
 appendslice(Node *n, NodeList **init)
 {
 	Node *f;
-	
+
 	f = syslook("appendslice", 1);
 	argtype(f, n->type);
 	argtype(f, n->type->type);
@@ -2111,7 +2330,7 @@ appendslice(Node *n, NodeList **init)
 //     s := src
 //     const argc = len(args) - 1
 //     if cap(s) - len(s) < argc {
-//          s = growslice(s, argc) 
+//	    s = growslice(s, argc)
 //     }
 //     n := len(s)
 //     s = s[:n+argc]
@@ -2140,13 +2359,13 @@ append(Node *n, NodeList **init)
 	ns = temp(nsrc->type);
 	l = list(l, nod(OAS, ns, nsrc));  // s = src
 
-	na = nodintconst(argc);         // const argc
-	nx = nod(OIF, N, N);            // if cap(s) - len(s) < argc
+	na = nodintconst(argc);		// const argc
+	nx = nod(OIF, N, N);		// if cap(s) - len(s) < argc
 	nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
 
-	fn = syslook("growslice", 1);   //   growslice(<type>, old []T, n int64) (ret []T)
-	argtype(fn, ns->type->type);    // 1 old []any 
-	argtype(fn, ns->type->type);    // 2 ret []any
+	fn = syslook("growslice", 1);	//   growslice(<type>, old []T, n int64) (ret []T)
+	argtype(fn, ns->type->type);	// 1 old []any
+	argtype(fn, ns->type->type);	// 2 ret []any
 
 	nx->nbody = list1(nod(OAS, ns, mkcall1(fn,  ns->type, &nx->ninit,
 					       typename(ns->type),
@@ -2155,16 +2374,16 @@ append(Node *n, NodeList **init)
 	l = list(l, nx);
 
 	nn = temp(types[TINT]);
-	l = list(l, nod(OAS, nn, nod(OLEN, ns, N)));     // n = len(s)
+	l = list(l, nod(OAS, nn, nod(OLEN, ns, N)));	 // n = len(s)
 
-	nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na)));   // ...s[:n+argc]
-	nx->etype = 1;  // disable bounds check
-	l = list(l, nod(OAS, ns, nx));                  // s = s[:n+argc]
+	nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na)));	 // ...s[:n+argc]
+	nx->etype = 1;	// disable bounds check
+	l = list(l, nod(OAS, ns, nx));			// s = s[:n+argc]
 
-	for (a = n->list->next;  a != nil; a = a->next) {
-		nx = nod(OINDEX, ns, nn);               // s[n] ...
-		nx->etype = 1;  // disable bounds check
-		l = list(l, nod(OAS, nx, a->n));        // s[n] = arg
+	for (a = n->list->next;	 a != nil; a = a->next) {
+		nx = nod(OINDEX, ns, nn);		// s[n] ...
+		nx->etype = 1;	// disable bounds check
+		l = list(l, nod(OAS, nx, a->n));	// s[n] = arg
 		if (a->next != nil)
 			l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1))));  // n = n + 1
 	}
@@ -2174,3 +2393,186 @@ append(Node *n, NodeList **init)
 	*init = concat(*init, l);
 	return ns;
 }
+
+static Node*
+eqfor(Type *t)
+{
+	int a;
+	Node *n;
+	Node *ntype;
+	Sym *sym;
+
+	// Should only arrive here with large memory or
+	// a struct/array containing a non-memory field/element.
+	// Small memory is handled inline, and single non-memory
+	// is handled during type check (OCMPSTR etc).
+	a = algtype1(t, nil);
+	if(a != AMEM && a != -1)
+		fatal("eqfor %T", t);
+
+	if(a == AMEM) {
+		n = syslook("memequal", 1);
+		argtype(n, t);
+		argtype(n, t);
+		return n;
+	}
+
+	sym = typesymprefix(".eq", t);
+	n = newname(sym);
+	n->class = PFUNC;
+	ntype = nod(OTFUNC, N, N);
+	ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(types[TBOOL]))));
+	ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+	ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
+	ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
+	typecheck(&ntype, Etype);
+	n->type = ntype->type;
+	return n;
+}
+
+static int
+countfield(Type *t)
+{
+	Type *t1;
+	int n;
+	
+	n = 0;
+	for(t1=t->type; t1!=T; t1=t1->down)
+		n++;
+	return n;
+}
+
+static void
+walkcompare(Node **np, NodeList **init)
+{
+	Node *n, *l, *r, *fn, *call, *a, *li, *ri, *expr;
+	int andor, i;
+	Type *t, *t1;
+	static Node *tempbool;
+	
+	n = *np;
+	
+	// Must be comparison of array or struct.
+	// Otherwise back end handles it.
+	t = n->left->type;
+	switch(t->etype) {
+	default:
+		return;
+	case TARRAY:
+		if(isslice(t))
+			return;
+		break;
+	case TSTRUCT:
+		break;
+	}
+	
+	if(!islvalue(n->left) || !islvalue(n->right))
+		goto hard;
+
+	l = temp(ptrto(t));
+	a = nod(OAS, l, nod(OADDR, n->left, N));
+	a->right->etype = 1;  // addr does not escape
+	typecheck(&a, Etop);
+	*init = list(*init, a);
+
+	r = temp(ptrto(t));
+	a = nod(OAS, r, nod(OADDR, n->right, N));
+	a->right->etype = 1;  // addr does not escape
+	typecheck(&a, Etop);
+	*init = list(*init, a);
+
+	expr = N;
+	andor = OANDAND;
+	if(n->op == ONE)
+		andor = OOROR;
+
+	if(t->etype == TARRAY &&
+		t->bound <= 4 &&
+		issimple[t->type->etype]) {
+		// Four or fewer elements of a basic type.
+		// Unroll comparisons.
+		for(i=0; i<t->bound; i++) {
+			li = nod(OINDEX, l, nodintconst(i));
+			ri = nod(OINDEX, r, nodintconst(i));
+			a = nod(n->op, li, ri);
+			if(expr == N)
+				expr = a;
+			else
+				expr = nod(andor, expr, a);
+		}
+		if(expr == N)
+			expr = nodbool(n->op == OEQ);
+		typecheck(&expr, Erv);
+		walkexpr(&expr, init);
+		*np = expr;
+		return;
+	}
+	
+	if(t->etype == TSTRUCT && countfield(t) <= 4) {
+		// Struct of four or fewer fields.
+		// Inline comparisons.
+		for(t1=t->type; t1; t1=t1->down) {
+			li = nod(OXDOT, l, newname(t1->sym));
+			ri = nod(OXDOT, r, newname(t1->sym));
+			a = nod(n->op, li, ri);
+			if(expr == N)
+				expr = a;
+			else
+				expr = nod(andor, expr, a);
+		}
+		if(expr == N)
+			expr = nodbool(n->op == OEQ);
+		typecheck(&expr, Erv);
+		walkexpr(&expr, init);
+		*np = expr;
+		return;
+	}
+	
+	// Chose not to inline, but still have addresses.
+	// Call equality function directly.
+	// The equality function requires a bool pointer for
+	// storing its address, because it has to be callable
+	// from C, and C can't access an ordinary Go return value.
+	// To avoid creating many temporaries, cache one per function.
+	if(tempbool == N || tempbool->curfn != curfn)
+		tempbool = temp(types[TBOOL]);
+	
+	call = nod(OCALL, eqfor(t), N);
+	a = nod(OADDR, tempbool, N);
+	a->etype = 1;  // does not escape
+	call->list = list(call->list, a);
+	call->list = list(call->list, nodintconst(t->width));
+	call->list = list(call->list, l);
+	call->list = list(call->list, r);
+	typecheck(&call, Etop);
+	walkstmt(&call);
+	*init = list(*init, call);
+	
+	if(n->op == OEQ)
+		r = tempbool;
+	else
+		r = nod(ONOT, tempbool, N);
+	typecheck(&r, Erv);
+	walkexpr(&r, init);
+	*np = r;
+	return;
+
+hard:
+	// Cannot take address of one or both of the operands.
+	// Instead, pass directly to runtime helper function.
+	// Easier on the stack than passing the address
+	// of temporary variables, because we are better at reusing
+	// the argument space than temporary variable space.
+	fn = syslook("equal", 1);
+	l = n->left;
+	r = n->right;
+	argtype(fn, n->left->type);
+	argtype(fn, n->left->type);
+	r = mkcall1(fn, n->type, init, typename(n->left->type), l, r);
+	if(n->op == ONE) {
+		r = nod(ONOT, r, N);
+		typecheck(&r, Erv);
+	}
+	*np = r;
+	return;
+}
diff --git a/src/cmd/go/Makefile b/src/cmd/go/Makefile
new file mode 100644
index 0000000..295a144
--- /dev/null
+++ b/src/cmd/go/Makefile
@@ -0,0 +1,25 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../Make.inc
+
+TARG=go
+GOFILES=\
+	build.go\
+	fix.go\
+	get.go\
+	fmt.go\
+	help.go\
+	http.go\
+	list.go\
+	main.go\
+	pkg.go\
+	run.go\
+	test.go\
+	testflag.go\
+	version.go\
+	vet.go\
+	vcs.go\
+
+include ../../Make.cmd
diff --git a/src/cmd/go/bootstrap.go b/src/cmd/go/bootstrap.go
new file mode 100644
index 0000000..bc9a3db
--- /dev/null
+++ b/src/cmd/go/bootstrap.go
@@ -0,0 +1,17 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build cmd_go_bootstrap
+
+// This code is compiled only into the bootstrap 'go' binary.
+// These stubs avoid importing packages with large dependency
+// trees, like the use of "net/http" in vcs.go.
+
+package main
+
+import "errors"
+
+func httpGET(url string) ([]byte, error) {
+	return nil, errors.New("no http in bootstrap go command")
+}
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
new file mode 100644
index 0000000..cbe36f5
--- /dev/null
+++ b/src/cmd/go/build.go
@@ -0,0 +1,1142 @@
+// Copyright 2011 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 (
+	"bytes"
+	"container/heap"
+	"errors"
+	"fmt"
+	"go/build"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strings"
+	"sync"
+)
+
+var cmdBuild = &Command{
+	UsageLine: "build [-a] [-n] [-o output] [-p n] [-v] [-x] [importpath... | gofiles...]",
+	Short:     "compile packages and dependencies",
+	Long: `
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+If the arguments are a list of .go files, build treats them as a list
+of source files specifying a single package.
+
+When the command line specifies a single main package,
+build writes the resulting executable to output (default a.out).
+Otherwise build compiles the packages but discards the results,
+serving only as a check that the packages can be built.
+
+The -a flag forces rebuilding of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -v flag prints the names of packages as they are compiled.
+The -x flag prints the commands.
+
+The -o flag specifies the output file name.
+It is an error to use -o when the command line specifies multiple packages.
+
+The -p flag specifies the number of builds that can be run in parallel.
+The default is the number of CPUs available.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go install, go get, go clean.
+	`,
+}
+
+func init() {
+	// break init cycle
+	cmdBuild.Run = runBuild
+	cmdInstall.Run = runInstall
+
+	addBuildFlags(cmdBuild)
+	addBuildFlags(cmdInstall)
+}
+
+// Flags set by multiple commands.
+var buildA bool               // -a flag
+var buildN bool               // -n flag
+var buildP = runtime.NumCPU() // -p flag
+var buildV bool               // -v flag
+var buildX bool               // -x flag
+var buildO = cmdBuild.Flag.String("o", "", "output file")
+
+var buildContext = build.DefaultContext
+
+// addBuildFlags adds the flags common to the build and install commands.
+func addBuildFlags(cmd *Command) {
+	cmd.Flag.BoolVar(&buildA, "a", false, "")
+	cmd.Flag.BoolVar(&buildN, "n", false, "")
+	cmd.Flag.IntVar(&buildP, "p", buildP, "")
+	cmd.Flag.BoolVar(&buildV, "v", false, "")
+	cmd.Flag.BoolVar(&buildX, "x", false, "")
+
+	// TODO(rsc): This -t flag is used by buildscript.sh but
+	// not documented.  Should be documented but the
+	// usage lines are getting too long.  Probably need to say
+	// that these flags are applicable to every command and
+	// document them in one help message instead of on every
+	// command's help message.
+	cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "t", "")
+}
+
+type stringsFlag []string
+
+func (v *stringsFlag) Set(s string) error {
+	*v = append(*v, s)
+	return nil
+}
+
+func (v *stringsFlag) String() string {
+	return "<stringsFlag>"
+}
+
+func runBuild(cmd *Command, args []string) {
+	var b builder
+	b.init()
+
+	var pkgs []*Package
+	if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
+		pkg := goFilesPackage(args, "")
+		pkgs = append(pkgs, pkg)
+	} else {
+		pkgs = packagesForBuild(args)
+	}
+
+	if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" {
+		*buildO = "a.out"
+	}
+
+	if *buildO != "" {
+		if len(pkgs) > 1 {
+			fatalf("go build: cannot use -o with multiple packages")
+		}
+		p := pkgs[0]
+		p.target = "" // must build - not up to date
+		a := b.action(modeInstall, modeBuild, p)
+		a.target = *buildO
+		b.do(a)
+		return
+	}
+
+	a := &action{}
+	for _, p := range packages(args) {
+		a.deps = append(a.deps, b.action(modeBuild, modeBuild, p))
+	}
+	b.do(a)
+}
+
+var cmdInstall = &Command{
+	UsageLine: "install [-a] [-n] [-p n] [-v] [-x] [importpath...]",
+	Short:     "compile and install packages and dependencies",
+	Long: `
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+The -a flag forces reinstallation of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -v flag prints the names of packages as they are compiled.
+The -x flag prints the commands.
+
+The -p flag specifies the number of builds that can be run in parallel.
+The default is the number of CPUs available.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go get, go clean.
+	`,
+}
+
+func runInstall(cmd *Command, args []string) {
+	pkgs := packagesForBuild(args)
+
+	var b builder
+	b.init()
+	a := &action{}
+	for _, p := range pkgs {
+		a.deps = append(a.deps, b.action(modeInstall, modeInstall, p))
+	}
+	b.do(a)
+}
+
+// A builder holds global state about a build.
+// It does not hold per-package state, because eventually we will
+// build packages in parallel, and the builder will be shared.
+type builder struct {
+	work        string               // the temporary work directory (ends in filepath.Separator)
+	arch        string               // e.g., "6"
+	goroot      string               // the $GOROOT
+	goarch      string               // the $GOARCH
+	goos        string               // the $GOOS
+	gobin       string               // the $GOBIN
+	exe         string               // the executable suffix - "" or ".exe"
+	gcflags     []string             // additional flags for Go compiler
+	actionCache map[cacheKey]*action // a cache of already-constructed actions
+	mkdirCache  map[string]bool      // a cache of created directories
+
+	output    sync.Mutex
+	scriptDir string // current directory in printed script
+
+	exec      sync.Mutex
+	readySema chan bool
+	ready     actionQueue
+}
+
+// An action represents a single action in the action graph.
+type action struct {
+	p          *Package      // the package this action works on
+	deps       []*action     // actions that must happen before this one
+	triggers   []*action     // inverse of deps
+	cgo        *action       // action for cgo binary if needed
+	args       []string      // additional args for runProgram
+	testOutput *bytes.Buffer // test output buffer
+
+	f          func(*builder, *action) error // the action itself (nil = no-op)
+	ignoreFail bool                          // whether to run f even if dependencies fail
+
+	// Generated files, directories.
+	link   bool   // target is executable, not just package
+	pkgdir string // the -I or -L argument to use when importing this package
+	objdir string // directory for intermediate objects
+	objpkg string // the intermediate package .a file created during the action
+	target string // goal of the action: the created package or executable
+
+	// Execution state.
+	pending  int  // number of deps yet to complete
+	priority int  // relative execution priority
+	failed   bool // whether the action failed
+}
+
+// cacheKey is the key for the action cache.
+type cacheKey struct {
+	mode buildMode
+	p    *Package
+}
+
+// buildMode specifies the build mode:
+// are we just building things or also installing the results?
+type buildMode int
+
+const (
+	modeBuild buildMode = iota
+	modeInstall
+)
+
+func (b *builder) init() {
+	var err error
+	b.actionCache = make(map[cacheKey]*action)
+	b.mkdirCache = make(map[string]bool)
+	b.goarch = buildContext.GOARCH
+	b.goos = buildContext.GOOS
+	b.goroot = build.Path[0].Path
+	b.gobin = build.Path[0].BinDir()
+	if b.goos == "windows" {
+		b.exe = ".exe"
+	}
+	b.gcflags = strings.Fields(os.Getenv("GCFLAGS"))
+
+	b.arch, err = build.ArchChar(b.goarch)
+	if err != nil {
+		fatalf("%s", err)
+	}
+
+	if buildN {
+		b.work = "$WORK"
+	} else {
+		b.work, err = ioutil.TempDir("", "go-build")
+		if err != nil {
+			fatalf("%s", err)
+		}
+		if buildX {
+			fmt.Printf("WORK=%s\n", b.work)
+		}
+		atexit(func() { os.RemoveAll(b.work) })
+	}
+}
+
+// goFilesPackage creates a package for building a collection of Go files
+// (typically named on the command line).  If target is given, the package
+// target is target.  Otherwise, the target is named p.a for
+// package p or named after the first Go file for package main.
+func goFilesPackage(gofiles []string, target string) *Package {
+	// TODO: Remove this restriction.
+	for _, f := range gofiles {
+		if !strings.HasSuffix(f, ".go") || strings.Contains(f, "/") || strings.Contains(f, string(filepath.Separator)) {
+			fatalf("named files must be in current directory and .go files")
+		}
+	}
+
+	// Synthesize fake "directory" that only shows those two files,
+	// to make it look like this is a standard package or
+	// command directory.
+	var dir []os.FileInfo
+	for _, file := range gofiles {
+		fi, err := os.Stat(file)
+		if err != nil {
+			fatalf("%s", err)
+		}
+		if fi.IsDir() {
+			fatalf("%s is a directory, should be a Go file", file)
+		}
+		dir = append(dir, fi)
+	}
+	ctxt := buildContext
+	ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dir, nil }
+	pwd, _ := os.Getwd()
+	var stk importStack
+	pkg := scanPackage(&ctxt, &build.Tree{Path: "."}, "<command line>", "<command line>", pwd+"/.", &stk)
+	if pkg.Error != nil {
+		fatalf("%s", pkg.Error)
+	}
+	if target != "" {
+		pkg.target = target
+	} else if pkg.Name == "main" {
+		pkg.target = gofiles[0][:len(gofiles[0])-len(".go")]
+	} else {
+		pkg.target = pkg.Name + ".a"
+	}
+	pkg.ImportPath = "_/" + pkg.target
+	return pkg
+}
+
+// action returns the action for applying the given operation (mode) to the package.
+// depMode is the action to use when building dependencies.
+func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action {
+	key := cacheKey{mode, p}
+	a := b.actionCache[key]
+	if a != nil {
+		return a
+	}
+
+	a = &action{p: p, pkgdir: p.t.PkgDir()}
+	if p.pkgdir != "" { // overrides p.t
+		a.pkgdir = p.pkgdir
+	}
+
+	b.actionCache[key] = a
+
+	for _, p1 := range p.imports {
+		a.deps = append(a.deps, b.action(depMode, depMode, p1))
+	}
+
+	if len(p.CgoFiles) > 0 {
+		var stk importStack
+		p1 := loadPackage("cmd/cgo", &stk)
+		if p1.Error != nil {
+			fatalf("load cmd/cgo: %v", p1.Error)
+		}
+		a.cgo = b.action(depMode, depMode, p1)
+		a.deps = append(a.deps, a.cgo)
+	}
+
+	if p.Standard {
+		switch p.ImportPath {
+		case "builtin", "unsafe":
+			// Fake packages - nothing to build.
+			return a
+		}
+	}
+
+	if !p.Stale && !buildA && p.target != "" {
+		// p.Stale==false implies that p.target is up-to-date.
+		// Record target name for use by actions depending on this one.
+		a.target = p.target
+		return a
+	}
+
+	a.objdir = filepath.Join(b.work, filepath.FromSlash(a.p.ImportPath+"/_obj")) + string(filepath.Separator)
+	a.objpkg = filepath.Join(b.work, filepath.FromSlash(a.p.ImportPath+".a"))
+	a.link = p.Name == "main"
+
+	switch mode {
+	case modeInstall:
+		a.f = (*builder).install
+		a.deps = []*action{b.action(modeBuild, depMode, p)}
+		a.target = a.p.target
+	case modeBuild:
+		a.f = (*builder).build
+		a.target = a.objpkg
+		if a.link {
+			// An executable file.
+			// Have to use something other than .a for the suffix.
+			// It is easier on Windows if we use .exe, so use .exe everywhere.
+			// (This is the name of a temporary file.)
+			a.target = a.objdir + "a.out" + b.exe
+		}
+	}
+
+	return a
+}
+
+// actionList returns the list of actions in the dag rooted at root
+// as visited in a depth-first post-order traversal.
+func actionList(root *action) []*action {
+	seen := map[*action]bool{}
+	all := []*action{}
+	var walk func(*action)
+	walk = func(a *action) {
+		if seen[a] {
+			return
+		}
+		seen[a] = true
+		for _, a1 := range a.deps {
+			walk(a1)
+		}
+		all = append(all, a)
+	}
+	walk(root)
+	return all
+}
+
+// do runs the action graph rooted at root.
+func (b *builder) do(root *action) {
+	// Build list of all actions, assigning depth-first post-order priority.
+	// The original implementation here was a true queue
+	// (using a channel) but it had the effect of getting
+	// distracted by low-level leaf actions to the detriment
+	// of completing higher-level actions.  The order of
+	// work does not matter much to overall execution time,
+	// but when running "go test std" it is nice to see each test
+	// results as soon as possible.  The priorities assigned
+	// ensure that, all else being equal, the execution prefers
+	// to do what it would have done first in a simple depth-first
+	// dependency order traversal.
+	all := actionList(root)
+	for i, a := range all {
+		a.priority = i
+	}
+
+	b.readySema = make(chan bool, len(all))
+	done := make(chan bool)
+
+	// Initialize per-action execution state.
+	for _, a := range all {
+		for _, a1 := range a.deps {
+			a1.triggers = append(a1.triggers, a)
+		}
+		a.pending = len(a.deps)
+		if a.pending == 0 {
+			b.ready.push(a)
+			b.readySema <- true
+		}
+	}
+
+	// Handle runs a single action and takes care of triggering
+	// any actions that are runnable as a result.
+	handle := func(a *action) {
+		var err error
+		if a.f != nil && (!a.failed || a.ignoreFail) {
+			err = a.f(b, a)
+		}
+
+		// The actions run in parallel but all the updates to the
+		// shared work state are serialized through b.exec.
+		b.exec.Lock()
+		defer b.exec.Unlock()
+
+		if err != nil {
+			if err == errPrintedOutput {
+				exitStatus = 2
+			} else {
+				errorf("%s", err)
+			}
+			a.failed = true
+		}
+
+		for _, a0 := range a.triggers {
+			if a.failed {
+				a0.failed = true
+			}
+			if a0.pending--; a0.pending == 0 {
+				b.ready.push(a0)
+				b.readySema <- true
+			}
+		}
+
+		if a == root {
+			close(b.readySema)
+			done <- true
+		}
+	}
+
+	// Kick off goroutines according to parallelism.
+	// If we are using the -n flag (just printing commands)
+	// drop the parallelism to 1, both to make the output
+	// deterministic and because there is no real work anyway.
+	par := buildP
+	if buildN {
+		par = 1
+	}
+	for i := 0; i < par; i++ {
+		go func() {
+			for _ = range b.readySema {
+				// Receiving a value from b.sema entitles
+				// us to take from the ready queue.
+				b.exec.Lock()
+				a := b.ready.pop()
+				b.exec.Unlock()
+				handle(a)
+			}
+		}()
+	}
+
+	<-done
+}
+
+// build is the action for building a single package or command.
+func (b *builder) build(a *action) error {
+	if buildN {
+		// In -n mode, print a banner between packages.
+		// The banner is five lines so that when changes to
+		// different sections of the bootstrap script have to
+		// be merged, the banners give patch something
+		// to use to find its context.
+		fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath)
+	}
+
+	if buildV {
+		fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
+	}
+
+	// Make build directory.
+	obj := a.objdir
+	if err := b.mkdir(obj); err != nil {
+		return err
+	}
+
+	var gofiles, cfiles, sfiles, objects, cgoObjects []string
+	gofiles = append(gofiles, a.p.GoFiles...)
+	cfiles = append(cfiles, a.p.CFiles...)
+	sfiles = append(sfiles, a.p.SFiles...)
+
+	// Run cgo.
+	if len(a.p.CgoFiles) > 0 {
+		// In a package using cgo, cgo compiles the C and assembly files with gcc.  
+		// There is one exception: runtime/cgo's job is to bridge the
+		// cgo and non-cgo worlds, so it necessarily has files in both.
+		// In that case gcc only gets the gcc_* files.
+		var gccfiles []string
+		if a.p.Standard && a.p.ImportPath == "runtime/cgo" {
+			filter := func(files, nongcc, gcc []string) ([]string, []string) {
+				for _, f := range files {
+					if strings.HasPrefix(f, "gcc_") {
+						gcc = append(gcc, f)
+					} else {
+						nongcc = append(nongcc, f)
+					}
+				}
+				return nongcc, gcc
+			}
+			cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles)
+			sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
+		} else {
+			gccfiles = append(cfiles, sfiles...)
+			cfiles = nil
+			sfiles = nil
+		}
+
+		outGo, outObj, err := b.cgo(a.p, a.cgo.target, obj, gccfiles)
+		if err != nil {
+			return err
+		}
+		cgoObjects = append(cgoObjects, outObj...)
+		gofiles = append(gofiles, outGo...)
+	}
+
+	// Prepare Go import path list.
+	inc := b.includeArgs("-I", a.deps)
+
+	// Compile Go.
+	if len(gofiles) > 0 {
+		out := "_go_." + b.arch
+		gcargs := []string{"-p", a.p.ImportPath}
+		if a.p.Standard && a.p.ImportPath == "runtime" {
+			// runtime compiles with a special 6g flag to emit
+			// additional reflect type data.
+			gcargs = append(gcargs, "-+")
+		}
+		if err := b.gc(a.p, obj+out, gcargs, inc, gofiles); err != nil {
+			return err
+		}
+		objects = append(objects, out)
+	}
+
+	// Copy .h files named for goos or goarch or goos_goarch
+	// to names using GOOS and GOARCH.
+	// For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
+	_goos_goarch := "_" + b.goos + "_" + b.goarch + ".h"
+	_goos := "_" + b.goos + ".h"
+	_goarch := "_" + b.goarch + ".h"
+	for _, file := range a.p.HFiles {
+		switch {
+		case strings.HasSuffix(file, _goos_goarch):
+			targ := file[:len(file)-len(_goos_goarch)] + "_GOOS_GOARCH.h"
+			if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
+				return err
+			}
+		case strings.HasSuffix(file, _goarch):
+			targ := file[:len(file)-len(_goarch)] + "_GOARCH.h"
+			if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
+				return err
+			}
+		case strings.HasSuffix(file, _goos):
+			targ := file[:len(file)-len(_goos)] + "_GOOS.h"
+			if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
+				return err
+			}
+		}
+	}
+
+	for _, file := range cfiles {
+		out := file[:len(file)-len(".c")] + "." + b.arch
+		if err := b.cc(a.p, obj, obj+out, file); err != nil {
+			return err
+		}
+		objects = append(objects, out)
+	}
+
+	// Assemble .s files.
+	for _, file := range sfiles {
+		out := file[:len(file)-len(".s")] + "." + b.arch
+		if err := b.asm(a.p, obj, obj+out, file); err != nil {
+			return err
+		}
+		objects = append(objects, out)
+	}
+
+	// NOTE(rsc): On Windows, it is critically important that the
+	// gcc-compiled objects (cgoObjects) be listed after the ordinary
+	// objects in the archive.  I do not know why this is.
+	// http://golang.org/issue/2601
+	objects = append(objects, cgoObjects...)
+
+	// Pack into archive in obj directory
+	if err := b.gopack(a.p, obj, a.objpkg, objects); err != nil {
+		return err
+	}
+
+	// Link if needed.
+	if a.link {
+		// The compiler only cares about direct imports, but the
+		// linker needs the whole dependency tree.
+		all := actionList(a)
+		all = all[:len(all)-1] // drop a
+		inc := b.includeArgs("-L", all)
+		if err := b.ld(a.p, a.target, inc, a.objpkg); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// install is the action for installing a single package or executable.
+func (b *builder) install(a *action) error {
+	a1 := a.deps[0]
+	perm := os.FileMode(0666)
+	if a1.link {
+		perm = 0777
+	}
+
+	// make target directory
+	dir, _ := filepath.Split(a.target)
+	if dir != "" {
+		if err := b.mkdir(dir); err != nil {
+			return err
+		}
+	}
+
+	return b.copyFile(a.target, a1.target, perm)
+}
+
+// includeArgs returns the -I or -L directory list for access
+// to the results of the list of actions.
+func (b *builder) includeArgs(flag string, all []*action) []string {
+	inc := []string{}
+	incMap := map[string]bool{
+		b.work:                 true, // handled later
+		build.Path[0].PkgDir(): true, // goroot
+		"":                     true, // ignore empty strings
+	}
+
+	// Look in the temporary space for results of test-specific actions.
+	// This is the $WORK/my/package/_test directory for the
+	// package being built, so there are few of these.
+	for _, a1 := range all {
+		if dir := a1.pkgdir; dir != a1.p.t.PkgDir() && !incMap[dir] {
+			incMap[dir] = true
+			inc = append(inc, flag, dir)
+		}
+	}
+
+	// Also look in $WORK for any non-test packages that have
+	// been built but not installed.
+	inc = append(inc, flag, b.work)
+
+	// Finally, look in the installed package directories for each action.
+	for _, a1 := range all {
+		if dir := a1.pkgdir; dir == a1.p.t.PkgDir() && !incMap[dir] {
+			incMap[dir] = true
+			inc = append(inc, flag, dir)
+		}
+	}
+
+	return inc
+}
+
+// removeByRenaming removes file name by moving it to a tmp
+// directory and deleting the target if possible.
+func removeByRenaming(name string) error {
+	f, err := ioutil.TempFile("", "")
+	if err != nil {
+		return err
+	}
+	tmpname := f.Name()
+	f.Close()
+	err = os.Remove(tmpname)
+	if err != nil {
+		return err
+	}
+	err = os.Rename(name, tmpname)
+	if err != nil {
+		// assume name file does not exists,
+		// otherwise later code will fail.
+		return nil
+	}
+	err = os.Remove(tmpname)
+	if err != nil {
+		// TODO(brainman): file is locked and can't be deleted.
+		// We need to come up with a better way of doing it. 
+	}
+	return nil
+}
+
+// copyFile is like 'cp src dst'.
+func (b *builder) copyFile(dst, src string, perm os.FileMode) error {
+	if buildN || buildX {
+		b.showcmd("", "cp %s %s", src, dst)
+		if buildN {
+			return nil
+		}
+	}
+
+	sf, err := os.Open(src)
+	if err != nil {
+		return err
+	}
+	defer sf.Close()
+	os.Remove(dst)
+	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
+	if err != nil {
+		if runtime.GOOS != "windows" {
+			return err
+		}
+		// Windows does not allow to replace binary file
+		// while it is executing. We will cheat.
+		err = removeByRenaming(dst)
+		if err != nil {
+			return err
+		}
+		df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
+		if err != nil {
+			return err
+		}
+	}
+	_, err = io.Copy(df, sf)
+	df.Close()
+	if err != nil {
+		os.Remove(dst)
+		return err
+	}
+	return nil
+}
+
+// fmtcmd formats a command in the manner of fmt.Sprintf but also:
+//
+//	If dir is non-empty and the script is not in dir right now,
+//	fmtcmd inserts "cd dir\n" before the command.
+//
+//	fmtcmd replaces the value of b.work with $WORK.
+//	fmtcmd replaces the value of b.goroot with $GOROOT.
+//	fmtcmd replaces the value of b.gobin with $GOBIN.
+//
+//	fmtcmd replaces the name of the current directory with dot (.)
+//	but only when it is at the beginning of a space-separated token.
+//
+func (b *builder) fmtcmd(dir string, format string, args ...interface{}) string {
+	cmd := fmt.Sprintf(format, args...)
+	if dir != "" {
+		cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:]
+		if b.scriptDir != dir {
+			b.scriptDir = dir
+			cmd = "cd " + dir + "\n" + cmd
+		}
+	}
+	cmd = strings.Replace(cmd, b.work, "$WORK", -1)
+	cmd = strings.Replace(cmd, b.gobin, "$GOBIN", -1)
+	cmd = strings.Replace(cmd, b.goroot, "$GOROOT", -1)
+	return cmd
+}
+
+// showcmd prints the given command to standard output
+// for the implementation of -n or -x.
+func (b *builder) showcmd(dir string, format string, args ...interface{}) {
+	b.output.Lock()
+	defer b.output.Unlock()
+	fmt.Println(b.fmtcmd(dir, format, args...))
+}
+
+// showOutput prints "# desc" followed by the given output.
+// The output is expected to contain references to 'dir', usually
+// the source directory for the package that has failed to build.
+// showOutput rewrites mentions of dir with a relative path to dir
+// when the relative path is shorter.  This is usually more pleasant.
+// For example, if fmt doesn't compile and we are in src/pkg/html,
+// the output is
+//
+//	$ go build
+//	# fmt
+//	../fmt/print.go:1090: undefined: asdf
+//	$
+//
+// instead of
+//
+//	$ go build
+//	# fmt
+//	/usr/gopher/go/src/pkg/fmt/print.go:1090: undefined: asdf
+//	$
+//
+// showOutput also replaces references to the work directory with $WORK.
+//
+func (b *builder) showOutput(dir, desc, out string) {
+	prefix := "# " + desc
+	suffix := "\n" + out
+	pwd, _ := os.Getwd()
+	if reldir, err := filepath.Rel(pwd, dir); err == nil && len(reldir) < len(dir) {
+		suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1)
+		suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1)
+	}
+	suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1)
+
+	b.output.Lock()
+	defer b.output.Unlock()
+	fmt.Print(prefix, suffix)
+}
+
+// relPaths returns a copy of paths with absolute paths
+// made relative to the current directory if they would be shorter.
+func relPaths(paths []string) []string {
+	var out []string
+	pwd, _ := os.Getwd()
+	for _, p := range paths {
+		rel, err := filepath.Rel(pwd, p)
+		if err == nil && len(rel) < len(p) {
+			p = rel
+		}
+		out = append(out, p)
+	}
+	return out
+}
+
+// errPrintedOutput is a special error indicating that a command failed
+// but that it generated output as well, and that output has already
+// been printed, so there's no point showing 'exit status 1' or whatever
+// the wait status was.  The main executor, builder.do, knows not to
+// print this error.
+var errPrintedOutput = errors.New("already printed output - no need to show error")
+
+// run runs the command given by cmdline in the directory dir.
+// If the commnd fails, run prints information about the failure
+// and returns a non-nil error.
+func (b *builder) run(dir string, desc string, cmdargs ...interface{}) error {
+	out, err := b.runOut(dir, desc, cmdargs...)
+	if len(out) > 0 {
+		if out[len(out)-1] != '\n' {
+			out = append(out, '\n')
+		}
+		if desc == "" {
+			desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " "))
+		}
+		b.showOutput(dir, desc, string(out))
+		if err != nil {
+			err = errPrintedOutput
+		}
+	}
+	return err
+}
+
+// runOut runs the command given by cmdline in the directory dir.
+// It returns the command output and any errors that occurred.
+func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byte, error) {
+	cmdline := stringList(cmdargs...)
+	if buildN || buildX {
+		b.showcmd(dir, "%s", strings.Join(cmdline, " "))
+		if buildN {
+			return nil, nil
+		}
+	}
+
+	var buf bytes.Buffer
+	cmd := exec.Command(cmdline[0], cmdline[1:]...)
+	cmd.Stdout = &buf
+	cmd.Stderr = &buf
+	cmd.Dir = dir
+	// TODO: cmd.Env
+	err := cmd.Run()
+	return buf.Bytes(), err
+}
+
+// mkdir makes the named directory.
+func (b *builder) mkdir(dir string) error {
+	b.exec.Lock()
+	defer b.exec.Unlock()
+	// We can be a little aggressive about being
+	// sure directories exist.  Skip repeated calls.
+	if b.mkdirCache[dir] {
+		return nil
+	}
+	b.mkdirCache[dir] = true
+
+	if buildN || buildX {
+		b.showcmd("", "mkdir -p %s", dir)
+		if buildN {
+			return nil
+		}
+	}
+
+	if err := os.MkdirAll(dir, 0777); err != nil {
+		return err
+	}
+	return nil
+}
+
+// mkAbs returns an absolute path corresponding to
+// evaluating f in the directory dir.
+// We always pass absolute paths of source files so that
+// the error messages will include the full path to a file
+// in need of attention.
+func mkAbs(dir, f string) string {
+	// Leave absolute paths alone.
+	// Also, during -n mode we use the pseudo-directory $WORK
+	// instead of creating an actual work directory that won't be used.
+	// Leave paths beginning with $WORK alone too.
+	if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") {
+		return f
+	}
+	return filepath.Join(dir, f)
+}
+
+// gc runs the Go compiler in a specific directory on a set of files
+// to generate the named output file. 
+func (b *builder) gc(p *Package, ofile string, gcargs, importArgs []string, gofiles []string) error {
+	args := stringList(b.arch+"g", "-o", ofile, b.gcflags, gcargs, importArgs)
+	for _, f := range gofiles {
+		args = append(args, mkAbs(p.Dir, f))
+	}
+	return b.run(p.Dir, p.ImportPath, args)
+}
+
+// asm runs the assembler in a specific directory on a specific file
+// to generate the named output file. 
+func (b *builder) asm(p *Package, obj, ofile, sfile string) error {
+	sfile = mkAbs(p.Dir, sfile)
+	return b.run(p.Dir, p.ImportPath, b.arch+"a", "-I", obj, "-o", ofile, "-DGOOS_"+b.goos, "-DGOARCH_"+b.goarch, sfile)
+}
+
+// gopack runs the assembler in a specific directory to create
+// an archive from a set of object files.
+// typically it is run in the object directory.
+func (b *builder) gopack(p *Package, objDir, afile string, ofiles []string) error {
+	var absOfiles []string
+	for _, f := range ofiles {
+		absOfiles = append(absOfiles, mkAbs(objDir, f))
+	}
+	return b.run(p.Dir, p.ImportPath, "gopack", "grc", mkAbs(objDir, afile), absOfiles)
+}
+
+// ld runs the linker to create a package starting at mainpkg.
+func (b *builder) ld(p *Package, out string, importArgs []string, mainpkg string) error {
+	return b.run(p.Dir, p.ImportPath, b.arch+"l", "-o", out, importArgs, mainpkg)
+}
+
+// cc runs the gc-toolchain C compiler in a directory on a C file
+// to produce an output file.
+func (b *builder) cc(p *Package, objdir, ofile, cfile string) error {
+	inc := filepath.Join(b.goroot, "pkg", fmt.Sprintf("%s_%s", b.goos, b.goarch))
+	cfile = mkAbs(p.Dir, cfile)
+	return b.run(p.Dir, p.ImportPath, b.arch+"c", "-FVw",
+		"-I", objdir, "-I", inc, "-o", ofile,
+		"-DGOOS_"+b.goos, "-DGOARCH_"+b.goarch, cfile)
+}
+
+// gcc runs the gcc C compiler to create an object from a single C file.
+func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
+	cfile = mkAbs(p.Dir, cfile)
+	return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), flags, "-o", out, "-c", cfile)
+}
+
+// gccld runs the gcc linker to create an executable from a set of object files
+func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error {
+	return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", out, obj, flags)
+}
+
+// gccCmd returns a gcc command line prefix
+func (b *builder) gccCmd(objdir string) []string {
+	// TODO: HOST_CC?
+	a := []string{"gcc", "-I", objdir, "-g", "-O2"}
+
+	// Definitely want -fPIC but on Windows gcc complains
+	// "-fPIC ignored for target (all code is position independent)"
+	if b.goos != "windows" {
+		a = append(a, "-fPIC")
+	}
+	switch b.arch {
+	case "8":
+		a = append(a, "-m32")
+	case "6":
+		a = append(a, "-m64")
+	}
+	// gcc-4.5 and beyond require explicit "-pthread" flag
+	// for multithreading with pthread library.
+	if buildContext.CgoEnabled {
+		switch b.goos {
+		case "windows":
+			a = append(a, "-mthreads")
+		default:
+			a = append(a, "-pthread")
+		}
+	}
+	return a
+}
+
+var cgoRe = regexp.MustCompile(`[/\\:]`)
+
+func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, outObj []string, err error) {
+	if b.goos != runtime.GOOS {
+		return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
+	}
+
+	outObj = append(outObj, "") // for importObj, at end of function
+
+	cgoCFLAGS := stringList(p.info.CgoCFLAGS)
+	cgoLDFLAGS := stringList(p.info.CgoLDFLAGS)
+	if pkgs := p.info.CgoPkgConfig; len(pkgs) > 0 {
+		out, err := b.runOut(p.Dir, p.ImportPath, "pkg-config", "--cflags", pkgs)
+		if err != nil {
+			return nil, nil, err
+		}
+		if len(out) > 0 {
+			cgoCFLAGS = append(cgoCFLAGS, strings.Fields(string(out))...)
+		}
+		out, err = b.runOut(p.Dir, p.ImportPath, "pkg-config", "--libs", pkgs)
+		if err != nil {
+			return nil, nil, err
+		}
+		if len(out) > 0 {
+			cgoLDFLAGS = append(cgoLDFLAGS, strings.Fields(string(out))...)
+		}
+	}
+
+	// cgo
+	// TODO: CGOPKGPATH, CGO_FLAGS?
+	gofiles := []string{obj + "_cgo_gotypes.go"}
+	cfiles := []string{"_cgo_main.c", "_cgo_export.c"}
+	for _, fn := range p.CgoFiles {
+		f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_")
+		gofiles = append(gofiles, obj+f+"cgo1.go")
+		cfiles = append(cfiles, f+"cgo2.c")
+	}
+	defunC := obj + "_cgo_defun.c"
+	// TODO: make cgo not depend on $GOARCH?
+	var runtimeFlag []string
+	if p.Standard && p.ImportPath == "runtime/cgo" {
+		runtimeFlag = []string{"-import_runtime_cgo=false"}
+	}
+	if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, runtimeFlag, "--", p.CgoFiles); err != nil {
+		return nil, nil, err
+	}
+	outGo = append(outGo, gofiles...)
+
+	// cc _cgo_defun.c
+	defunObj := obj + "_cgo_defun." + b.arch
+	if err := b.cc(p, obj, defunObj, defunC); err != nil {
+		return nil, nil, err
+	}
+	outObj = append(outObj, defunObj)
+
+	// gcc
+	var linkobj []string
+	for _, cfile := range cfiles {
+		ofile := obj + cfile[:len(cfile)-1] + "o"
+		if err := b.gcc(p, ofile, cgoCFLAGS, obj+cfile); err != nil {
+			return nil, nil, err
+		}
+		linkobj = append(linkobj, ofile)
+		if !strings.HasSuffix(ofile, "_cgo_main.o") {
+			outObj = append(outObj, ofile)
+		}
+	}
+	for _, file := range gccfiles {
+		ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
+		if err := b.gcc(p, ofile, cgoCFLAGS, file); err != nil {
+			return nil, nil, err
+		}
+		linkobj = append(linkobj, ofile)
+		outObj = append(outObj, ofile)
+	}
+	dynobj := obj + "_cgo_.o"
+	if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil {
+		return nil, nil, err
+	}
+
+	// cgo -dynimport
+	importC := obj + "_cgo_import.c"
+	if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC); err != nil {
+		return nil, nil, err
+	}
+
+	// cc _cgo_import.ARCH
+	importObj := obj + "_cgo_import." + b.arch
+	if err := b.cc(p, obj, importObj, importC); err != nil {
+		return nil, nil, err
+	}
+
+	// NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
+	// must be processed before the gcc-generated objects.
+	// Put it first.  We left room above.  http://golang.org/issue/2601
+	outObj[0] = importObj
+
+	return outGo, outObj, nil
+}
+
+// An actionQueue is a priority queue of actions.
+type actionQueue []*action
+
+// Implement heap.Interface
+func (q *actionQueue) Len() int           { return len(*q) }
+func (q *actionQueue) Swap(i, j int)      { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
+func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority }
+func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) }
+func (q *actionQueue) Pop() interface{} {
+	n := len(*q) - 1
+	x := (*q)[n]
+	*q = (*q)[:n]
+	return x
+}
+
+func (q *actionQueue) push(a *action) {
+	heap.Push(q, a)
+}
+
+func (q *actionQueue) pop() *action {
+	return heap.Pop(q).(*action)
+}
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
new file mode 100644
index 0000000..27be32b
--- /dev/null
+++ b/src/cmd/go/doc.go
@@ -0,0 +1,601 @@
+// Copyright 2011 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.
+
+/*
+Go is a tool for managing Go source code.
+
+Usage: go command [arguments]
+
+The commands are:
+
+    build       compile packages and dependencies
+    doc         run godoc on package sources
+    fix         run gofix on packages
+    fmt         run gofmt on package sources
+    get         download and install packages and dependencies
+    install     compile and install packages and dependencies
+    list        list packages
+    run         compile and run Go program
+    test        test packages
+    version     print Go version
+    vet         run govet on packages
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+
+    gopath      GOPATH environment variable
+    importpath  description of import paths
+    remote      remote import path syntax
+    testflag    description of testing flags
+    testfunc    description of testing functions
+
+Use "go help [topic]" for more information about that topic.
+
+
+Compile packages and dependencies
+
+Usage:
+
+	go build [-a] [-n] [-o output] [-p n] [-v] [-x] [importpath... | gofiles...]
+
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+If the arguments are a list of .go files, build treats them as a list
+of source files specifying a single package.
+
+When the command line specifies a single main package,
+build writes the resulting executable to output (default a.out).
+Otherwise build compiles the packages but discards the results,
+serving only as a check that the packages can be built.
+
+The -a flag forces rebuilding of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -v flag prints the names of packages as they are compiled.
+The -x flag prints the commands.
+
+The -o flag specifies the output file name.
+It is an error to use -o when the command line specifies multiple packages.
+
+The -p flag specifies the number of builds that can be run in parallel.
+The default is the number of CPUs available.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go install, go get, go clean.
+
+
+Run godoc on package sources
+
+Usage:
+
+	go doc [importpath...]
+
+Doc runs the godoc command on the packages named by the
+import paths.
+
+For more about godoc, see 'godoc godoc'.
+For more about import paths, see 'go help importpath'.
+
+To run godoc with specific options, run godoc itself.
+
+See also: go fix, go fmt, go vet.
+
+
+Run gofix on packages
+
+Usage:
+
+	go fix [importpath...]
+
+Fix runs the gofix command on the packages named by the import paths.
+
+For more about gofix, see 'godoc gofix'.
+For more about import paths, see 'go help importpath'.
+
+To run gofix with specific options, run gofix itself.
+
+See also: go fmt, go vet.
+
+
+Run gofmt on package sources
+
+Usage:
+
+	go fmt [importpath...]
+
+Fmt runs the command 'gofmt -l -w' on the packages named
+by the import paths.  It prints the names of the files that are modified.
+
+For more about gofmt, see 'godoc gofmt'.
+For more about import paths, see 'go help importpath'.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go doc, go fix, go vet.
+
+
+Download and install packages and dependencies
+
+Usage:
+
+	go get [-a] [-d] [-fix] [-n] [-p n] [-u] [-v] [-x] [importpath...]
+
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+The -a, -n, -v, -x, and -p flags have the same meaning as in 'go build'
+and 'go install'.  See 'go help install'.
+
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+
+The -fix flag instructs get to run gofix on the downloaded packages
+before resolving dependencies or building the code.
+
+The -u flag instructs get to use the network to update the named packages
+and their dependencies.  By default, get uses the network to check out 
+missing packages but does not use it to look for updates to existing packages.
+
+TODO: Explain versions better.
+
+For more about import paths, see 'go help importpath'.
+
+For more about how 'go get' finds source code to
+download, see 'go help remote'.
+
+See also: go build, go install, go clean.
+
+
+Compile and install packages and dependencies
+
+Usage:
+
+	go install [-a] [-n] [-p n] [-v] [-x] [importpath...]
+
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+The -a flag forces reinstallation of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -v flag prints the names of packages as they are compiled.
+The -x flag prints the commands.
+
+The -p flag specifies the number of builds that can be run in parallel.
+The default is the number of CPUs available.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go get, go clean.
+
+
+List packages
+
+Usage:
+
+	go list [-e] [-f format] [-json] [importpath...]
+
+List lists the packages named by the import paths, one per line.
+
+The default output shows the package import path:
+
+    code.google.com/p/google-api-go-client/books/v1
+    code.google.com/p/goauth2/oauth
+    code.google.com/p/sqlite
+
+The -f flag specifies an alternate format for the list,
+using the syntax of package template.  The default output
+is equivalent to -f '{{.ImportPath}}'.  The struct
+being passed to the template is:
+
+    type Package struct {
+        Name       string // package name
+        Doc        string // package documentation string
+        ImportPath string // import path of package in dir
+        Dir        string // directory containing package sources
+        Version    string // version of installed package (TODO)
+        Stale      bool   // would 'go install' do anything for this package?
+
+        // Source files
+        GoFiles      []string // .go source files (excluding CgoFiles, TestGoFiles, and XTestGoFiles)
+        TestGoFiles  []string // _test.go source files internal to the package they are testing
+        XTestGoFiles []string // _test.go source files external to the package they are testing
+        CFiles       []string // .c source files
+        HFiles       []string // .h source files
+        SFiles       []string // .s source files
+        CgoFiles     []string // .go sources files that import "C"
+
+        // Dependency information
+        Imports []string // import paths used by this package
+        Deps    []string // all (recursively) imported dependencies
+
+        // Error information
+        Incomplete bool            // this package or a dependency has an error
+        Error *PackageError        // error loading package
+        DepsErrors []*PackageError // errors loading dependencies
+    }
+
+The -json flag causes the package data to be printed in JSON format
+instead of using the template format.
+
+The -e flag changes the handling of erroneous packages, those that
+cannot be found or are malformed.  By default, the list command
+prints an error to standard error for each erroneous package and
+omits the packages from consideration during the usual printing.
+With the -e flag, the list command never prints errors to standard
+error and instead processes the erroneous packages with the usual
+printing.  Erroneous packages will have a non-empty ImportPath and
+a non-nil Error field; other information may or may not be missing
+(zeroed).
+
+For more about import paths, see 'go help importpath'.
+
+
+Compile and run Go program
+
+Usage:
+
+	go run [-a] [-n] [-x] gofiles... [arguments...]
+
+Run compiles and runs the main package comprising the named Go source files.
+
+The -a flag forces reinstallation of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -x flag prints the commands.
+
+See also: go build.
+
+
+Test packages
+
+Usage:
+
+	go test [-c] [-file a.go -file b.go ...] [-p n] [-x] [importpath...] [flags for test binary]
+
+'Go test' automates testing the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+	ok   archive/tar   0.011s
+	FAIL archive/zip   0.022s
+	ok   compress/gzip 0.033s
+	...
+
+followed by detailed output for each failed package.
+
+'Go test' recompiles each package along with any files with names matching
+the file pattern "*_test.go".  These additional files can contain test functions,
+benchmark functions, and example functions.  See 'go help testfunc' for more.
+
+By default, go test needs no arguments.  It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+If file names are given (with flag -file=test.go, one per extra test source file),
+only those test files are added to the package.  (The non-test files are always
+compiled.)
+
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+
+See 'go help testflag' for details about flags handled by 'go test'
+and the test binary.
+
+See 'go help importpath' for more about import paths.
+
+See also: go build, go vet.
+
+
+Print Go version
+
+Usage:
+
+	go version
+
+Version prints the Go version, as reported by runtime.Version.
+
+
+Run govet on packages
+
+Usage:
+
+	go vet [importpath...]
+
+Vet runs the govet command on the packages named by the import paths.
+
+For more about govet, see 'godoc govet'.
+For more about import paths, see 'go help importpath'.
+
+To run govet with specific options, run govet itself.
+
+See also: go fmt, go fix.
+
+
+GOPATH environment variable
+
+The GOPATH environment variable lists places to look for Go code.
+On Unix, the value is a colon-separated string.
+On Windows, the value is a semicolon-separated string.
+On Plan 9, the value is a list.
+
+GOPATH must be set to build and install packages outside the
+standard Go tree.
+
+Each directory listed in GOPATH must have a prescribed structure:
+
+The src/ directory holds source code.  The path below 'src'
+determines the import path or executable name.
+
+The pkg/ directory holds installed package objects.
+As in the Go tree, each target operating system and
+architecture pair has its own subdirectory of pkg
+(pkg/GOOS_GOARCH).
+
+If DIR is a directory listed in the GOPATH, a package with
+source in DIR/src/foo/bar can be imported as "foo/bar" and
+has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
+
+The bin/ directory holds compiled commands.
+Each command is named for its source directory, but only
+the final element, not the entire path.  That is, the
+command with source in DIR/src/foo/quux is installed into
+DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.
+
+Here's an example directory layout:
+
+    GOPATH=/home/user/gocode
+
+    /home/user/gocode/
+        src/
+            foo/
+                bar/               (go code in package bar)
+                    x.go
+                quux/              (go code in package main)
+                    y.go
+        bin/
+            quux                   (installed command)
+        pkg/
+            linux_amd64/
+                foo/
+                    bar.a          (installed package object)
+
+Go searches each directory listed in GOPATH to find source code,
+but new packages are always downloaded into the first directory 
+in the list.
+
+
+Description of import paths
+
+Many commands apply to a set of packages named by import paths:
+
+	go action [importpath...]
+
+An import path that is a rooted path or that begins with
+a . or .. element is interpreted as a file system path and
+denotes the package in that directory.
+
+Otherwise, the import path P denotes the package found in
+the directory DIR/src/P for some DIR listed in the GOPATH
+environment variable (see 'go help gopath'). 
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+The special import path "all" expands to all package directories
+found in all the GOPATH trees.  For example, 'go list all' 
+lists all the packages on the local system.
+
+The special import path "std" is like all but expands to just the
+packages in the standard Go library.
+
+An import path is a pattern if it includes one or more "..." wildcards,
+each of which can match any string, including the empty string and
+strings containing slashes.  Such a pattern expands to all package
+directories found in the GOPATH trees with names matching the
+patterns.  For example, encoding/... expands to all packages
+in the encoding tree.
+
+An import path can also name a package to be downloaded from
+a remote repository.  Run 'go help remote' for details.
+
+Every package in a program must have a unique import path.
+By convention, this is arranged by starting each path with a
+unique prefix that belongs to you.  For example, paths used
+internally at Google all begin with 'google', and paths
+denoting remote repositories begin with the path to the code,
+such as 'code.google.com/p/project'.
+
+
+Remote import path syntax
+
+An import path (see 'go help importpath') denotes a package
+stored in the local file system.  Certain import paths also
+describe how to obtain the source code for the package using
+a revision control system.
+
+A few common code hosting sites have special syntax:
+
+	BitBucket (Mercurial)
+
+		import "bitbucket.org/user/project"
+		import "bitbucket.org/user/project/sub/directory"
+
+	GitHub (Git)
+
+		import "github.com/user/project"
+		import "github.com/user/project/sub/directory"
+
+	Google Code Project Hosting (Git, Mercurial, Subversion)
+
+		import "code.google.com/p/project"
+		import "code.google.com/p/project/sub/directory"
+
+		import "code.google.com/p/project.subrepository"
+		import "code.google.com/p/project.subrepository/sub/directory"
+
+	Launchpad (Bazaar)
+
+		import "launchpad.net/project"
+		import "launchpad.net/project/series"
+		import "launchpad.net/project/series/sub/directory"
+
+		import "launchpad.net/~user/project/branch"
+		import "launchpad.net/~user/project/branch/sub/directory"
+
+For code hosted on other servers, an import path of the form
+
+	repository.vcs/path
+
+specifies the given repository, with or without the .vcs suffix,
+using the named version control system, and then the path inside
+that repository.  The supported version control systems are:
+
+	Bazaar      .bzr
+	Git         .git
+	Mercurial   .hg
+	Subversion  .svn
+
+For example,
+
+	import "example.org/user/foo.hg"
+
+denotes the root directory of the Mercurial repository at
+example.org/user/foo or foo.hg, and
+
+	import "example.org/repo.git/foo/bar"
+
+denotes the foo/bar directory of the Git repository at
+example.com/repo or repo.git.
+
+When a version control system supports multiple protocols,
+each is tried in turn when downloading.  For example, a Git
+download tries git://, then https://, then http://.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (see 'go help gopath').
+
+The go command attempts to download the version of the
+package appropriate for the Go release being used.
+Run 'go help install' for more.
+
+
+Description of testing flags
+
+The 'go test' command takes both flags that apply to 'go test' itself
+and flags that apply to the resulting test binary.
+
+The flags handled by 'go test' are:
+
+	-c  Compile the test binary to test.out but do not run it.
+
+	-file a.go
+	    Use only the tests in the source file a.go.
+	    Multiple -file flags may be provided.
+
+	-p n
+	    Compile and test up to n packages in parallel.
+	    The default value is the number of CPUs available.
+
+	-x  Print each subcommand go test executes.
+
+The resulting test binary, called test.out, has its own flags:
+
+	-test.v
+	    Verbose output: log all tests as they are run.
+
+	-test.run pattern
+	    Run only those tests matching the regular expression.
+
+	-test.bench pattern
+	    Run benchmarks matching the regular expression.
+	    By default, no benchmarks run.
+
+	-test.cpuprofile cpu.out
+	    Write a CPU profile to the specified file before exiting.
+
+	-test.memprofile mem.out
+	    Write a memory profile to the specified file when all tests
+	    are complete.
+
+	-test.memprofilerate n
+	    Enable more precise (and expensive) memory profiles by setting
+	    runtime.MemProfileRate.  See 'godoc runtime MemProfileRate'.
+	    To profile all memory allocations, use -test.memprofilerate=1
+	    and set the environment variable GOGC=off to disable the
+	    garbage collector, provided the test can run in the available
+	    memory without garbage collection.
+
+	-test.parallel n
+	    Allow parallel execution of test functions that call t.Parallel.
+	    The value of this flag is the maximum number of tests to run
+	    simultaneously; by default, it is set to the value of GOMAXPROCS.
+
+	-test.short
+	    Tell long-running tests to shorten their run time.
+	    It is off by default but set during all.bash so that installing
+	    the Go tree can run a sanity check but not spend time running
+	    exhaustive tests.
+
+	-test.timeout t
+		If a test runs longer than t, panic.
+
+	-test.benchtime n
+		Run enough iterations of each benchmark to take n seconds.
+		The default is 1 second.
+
+	-test.cpu 1,2,4
+	    Specify a list of GOMAXPROCS values for which the tests or 
+	    benchmarks should be executed.  The default is the current value
+	    of GOMAXPROCS.
+
+For convenience, each of these -test.X flags of the test binary is
+also available as the flag -X in 'go test' itself.  Flags not listed
+here are passed through unaltered.  For instance, the command
+
+	go test -x -v -cpuprofile=prof.out -dir=testdata -update -file x_test.go
+
+will compile the test binary using x_test.go and then run it as
+
+	test.out -test.v -test.cpuprofile=prof.out -dir=testdata -update
+
+
+Description of testing functions
+
+The 'go test' command expects to find test, benchmark, and example functions
+in the "*_test.go" files corresponding to the package under test.
+
+A test function is one named TestXXX (where XXX is any alphanumeric string
+not starting with a lower case letter) and should have the signature,
+
+	func TestXXX(t *testing.T) { ... }
+
+A benchmark function is one named BenchmarkXXX and should have the signature,
+
+	func BenchmarkXXX(b *testing.B) { ... }
+
+An example function is similar to a test function but, instead of using *testing.T
+to report success or failure, prints output to os.Stdout and os.Stderr.
+That output is compared against the function's doc comment.
+An example without a doc comment is compiled but not executed.
+
+Godoc displays the body of ExampleXXX to demonstrate the use
+of the function, constant, or variable XXX.  An example of a method M with
+receiver type T or *T is named ExampleT_M.  There may be multiple examples
+for a given function, constant, or variable, distinguished by a trailing _xxx,
+where xxx is a suffix not beginning with an upper case letter.
+
+Here is an example of an example:
+
+	// The output of this example function.
+	func ExamplePrintln() {
+		Println("The output of this example function.")
+	}
+
+See the documentation of the testing package for more information.
+
+
+*/
+package documentation
+
+// NOTE: cmdDoc is in fmt.go.
diff --git a/src/cmd/go/fix.go b/src/cmd/go/fix.go
new file mode 100644
index 0000000..bae9f5c
--- /dev/null
+++ b/src/cmd/go/fix.go
@@ -0,0 +1,30 @@
+// Copyright 2011 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
+
+var cmdFix = &Command{
+	Run:       runFix,
+	UsageLine: "fix [importpath...]",
+	Short:     "run gofix on packages",
+	Long: `
+Fix runs the gofix command on the packages named by the import paths.
+
+For more about gofix, see 'godoc gofix'.
+For more about import paths, see 'go help importpath'.
+
+To run gofix with specific options, run gofix itself.
+
+See also: go fmt, go vet.
+	`,
+}
+
+func runFix(cmd *Command, args []string) {
+	for _, pkg := range packages(args) {
+		// Use pkg.gofiles instead of pkg.Dir so that
+		// the command only applies to this package,
+		// not to packages in subdirectories.
+		run(stringList("gofix", relPaths(pkg.gofiles)))
+	}
+}
diff --git a/src/cmd/go/fmt.go b/src/cmd/go/fmt.go
new file mode 100644
index 0000000..4a47e2e
--- /dev/null
+++ b/src/cmd/go/fmt.go
@@ -0,0 +1,54 @@
+// Copyright 2011 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
+
+var cmdFmt = &Command{
+	Run:       runFmt,
+	UsageLine: "fmt [importpath...]",
+	Short:     "run gofmt on package sources",
+	Long: `
+Fmt runs the command 'gofmt -l -w' on the packages named
+by the import paths.  It prints the names of the files that are modified.
+
+For more about gofmt, see 'godoc gofmt'.
+For more about import paths, see 'go help importpath'.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go doc, go fix, go vet.
+	`,
+}
+
+func runFmt(cmd *Command, args []string) {
+	for _, pkg := range packages(args) {
+		// Use pkg.gofiles instead of pkg.Dir so that
+		// the command only applies to this package,
+		// not to packages in subdirectories.
+		run(stringList("gofmt", "-l", "-w", relPaths(pkg.gofiles)))
+	}
+}
+
+var cmdDoc = &Command{
+	Run:       runDoc,
+	UsageLine: "doc [importpath...]",
+	Short:     "run godoc on package sources",
+	Long: `
+Doc runs the godoc command on the packages named by the
+import paths.
+
+For more about godoc, see 'godoc godoc'.
+For more about import paths, see 'go help importpath'.
+
+To run godoc with specific options, run godoc itself.
+
+See also: go fix, go fmt, go vet.
+	`,
+}
+
+func runDoc(cmd *Command, args []string) {
+	for _, pkg := range packages(args) {
+		run("godoc", pkg.Dir)
+	}
+}
diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go
new file mode 100644
index 0000000..cd57d30
--- /dev/null
+++ b/src/cmd/go/get.go
@@ -0,0 +1,269 @@
+// Copyright 2011 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.
+
+// TODO: Dashboard upload
+
+package main
+
+import (
+	"fmt"
+	"go/build"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+)
+
+var cmdGet = &Command{
+	UsageLine: "get [-a] [-d] [-fix] [-n] [-p n] [-u] [-v] [-x] [importpath...]",
+	Short:     "download and install packages and dependencies",
+	Long: `
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+The -a, -n, -v, -x, and -p flags have the same meaning as in 'go build'
+and 'go install'.  See 'go help install'.
+
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+
+The -fix flag instructs get to run gofix on the downloaded packages
+before resolving dependencies or building the code.
+
+The -u flag instructs get to use the network to update the named packages
+and their dependencies.  By default, get uses the network to check out 
+missing packages but does not use it to look for updates to existing packages.
+
+TODO: Explain versions better.
+
+For more about import paths, see 'go help importpath'.
+
+For more about how 'go get' finds source code to
+download, see 'go help remote'.
+
+See also: go build, go install, go clean.
+	`,
+}
+
+var getD = cmdGet.Flag.Bool("d", false, "")
+var getU = cmdGet.Flag.Bool("u", false, "")
+var getFix = cmdGet.Flag.Bool("fix", false, "")
+
+func init() {
+	addBuildFlags(cmdGet)
+	cmdGet.Run = runGet // break init loop
+}
+
+func runGet(cmd *Command, args []string) {
+	// Phase 1.  Download/update.
+	args = importPaths(args)
+	var stk importStack
+	for _, arg := range args {
+		download(arg, &stk)
+	}
+	exitIfErrors()
+
+	if *getD {
+		// download only
+		return
+	}
+
+	// Phase 2. Install.
+
+	// Code we downloaded and all code that depends on it
+	// needs to be evicted from the package cache so that
+	// the information will be recomputed.  Instead of keeping
+	// track of the reverse dependency information, evict
+	// everything.
+	for name := range packageCache {
+		delete(packageCache, name)
+	}
+
+	runInstall(cmd, args)
+}
+
+// downloadCache records the import paths we have already
+// considered during the download, to avoid duplicate work when
+// there is more than one dependency sequence leading to
+// a particular package.
+var downloadCache = map[string]bool{}
+
+// downloadRootCache records the version control repository
+// root directories we have already considered during the download.
+// For example, all the packages in the code.google.com/p/codesearch repo
+// share the same root (the directory for that path), and we only need
+// to run the hg commands to consider each repository once.
+var downloadRootCache = map[string]bool{}
+
+// download runs the download half of the get command
+// for the package named by the argument.
+func download(arg string, stk *importStack) {
+	p := loadPackage(arg, stk)
+
+	// There's nothing to do if this is a package in the standard library.
+	if p.Standard {
+		return
+	}
+
+	// Only process each package once.
+	if downloadCache[arg] {
+		return
+	}
+	downloadCache[arg] = true
+
+	// Download if the package is missing, or update if we're using -u.
+	if p.Dir == "" || *getU {
+		// The actual download.
+		stk.push(p.ImportPath)
+		defer stk.pop()
+		if err := downloadPackage(p); err != nil {
+			errorf("%s", &PackageError{stk.copy(), err.Error()})
+			return
+		}
+
+		// Reread the package information from the updated files.
+		p = reloadPackage(arg, stk)
+		if p.Error != nil {
+			errorf("%s", p.Error)
+			return
+		}
+	}
+
+	if *getFix {
+		run(stringList("gofix", relPaths(p.gofiles)))
+
+		// The imports might have changed, so reload again.
+		p = reloadPackage(arg, stk)
+		if p.Error != nil {
+			errorf("%s", p.Error)
+			return
+		}
+	}
+
+	// Process dependencies, now that we know what they are.
+	for _, dep := range p.deps {
+		download(dep.ImportPath, stk)
+	}
+}
+
+// downloadPackage runs the create or download command
+// to make the first copy of or update a copy of the given package.
+func downloadPackage(p *Package) error {
+	// Analyze the import path to determine the version control system,
+	// repository, and the import path for the root of the repository.
+	vcs, repo, rootPath, err := vcsForImportPath(p.ImportPath)
+	if err != nil {
+		return err
+	}
+	if p.t == nil {
+		// Package not found.  Put in first directory of $GOPATH or else $GOROOT.
+		p.t = build.Path[0] // $GOROOT
+		if len(build.Path) > 1 {
+			p.t = build.Path[1] // first in $GOPATH
+		}
+		p.Dir = filepath.Join(p.t.SrcDir(), p.ImportPath)
+	}
+	root := filepath.Join(p.t.SrcDir(), rootPath)
+
+	// If we've considered this repository already, don't do it again.
+	if downloadRootCache[root] {
+		return nil
+	}
+	downloadRootCache[root] = true
+
+	if buildV {
+		fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
+	}
+
+	// Check that this is an appropriate place for the repo to be checked out.
+	// The target directory must either not exist or have a repo checked out already.
+	meta := filepath.Join(root, "."+vcs.cmd)
+	st, err := os.Stat(meta)
+	if err == nil && !st.IsDir() {
+		return fmt.Errorf("%s exists but is not a directory", meta)
+	}
+	if err != nil {
+		// Metadata directory does not exist.  Prepare to checkout new copy.
+		// Some version control tools require the target directory not to exist.
+		// We require that too, just to avoid stepping on existing work.
+		if _, err := os.Stat(root); err == nil {
+			return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
+		}
+		// Some version control tools require the parent of the target to exist.
+		parent, _ := filepath.Split(root)
+		if err := os.MkdirAll(parent, 0777); err != nil {
+			return err
+		}
+		if err = vcs.create(root, repo); err != nil {
+			return err
+		}
+	} else {
+		// Metadata directory does exist; download incremental updates.
+		if err = vcs.download(root); err != nil {
+			return err
+		}
+	}
+
+	// Select and sync to appropriate version of the repository.
+	tags, err := vcs.tags(root)
+	if err != nil {
+		return err
+	}
+	vers := runtime.Version()
+	if i := strings.Index(vers, " "); i >= 0 {
+		vers = vers[:i]
+	}
+	tag := selectTag(vers, tags)
+	if tag == "" {
+		tag = vcs.tagDefault
+	}
+	if err := vcs.tagSync(root, tag); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// selectTag returns the closest matching tag for a given version.
+// Closest means the latest one that is not after the current release.
+// Version "release.rN" matches tags of the form "go.rN" (N being a decimal).
+// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
+func selectTag(goVersion string, tags []string) (match string) {
+	const rPrefix = "release.r"
+	if strings.HasPrefix(goVersion, rPrefix) {
+		p := "go.r"
+		v, err := strconv.ParseFloat(goVersion[len(rPrefix):], 64)
+		if err != nil {
+			return ""
+		}
+		var matchf float64
+		for _, t := range tags {
+			if !strings.HasPrefix(t, p) {
+				continue
+			}
+			tf, err := strconv.ParseFloat(t[len(p):], 64)
+			if err != nil {
+				continue
+			}
+			if matchf < tf && tf <= v {
+				match, matchf = t, tf
+			}
+		}
+	}
+	const wPrefix = "weekly."
+	if strings.HasPrefix(goVersion, wPrefix) {
+		p := "go.weekly."
+		v := goVersion[len(wPrefix):]
+		for _, t := range tags {
+			if !strings.HasPrefix(t, p) {
+				continue
+			}
+			if match < t && t[len(p):] <= v {
+				match = t
+			}
+		}
+	}
+	return match
+}
diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go
new file mode 100644
index 0000000..33716ef
--- /dev/null
+++ b/src/cmd/go/help.go
@@ -0,0 +1,185 @@
+// Copyright 2011 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
+
+var helpImportpath = &Command{
+	UsageLine: "importpath",
+	Short:     "description of import paths",
+	Long: `
+Many commands apply to a set of packages named by import paths:
+
+	go action [importpath...]
+
+An import path that is a rooted path or that begins with
+a . or .. element is interpreted as a file system path and
+denotes the package in that directory.
+
+Otherwise, the import path P denotes the package found in
+the directory DIR/src/P for some DIR listed in the GOPATH
+environment variable (see 'go help gopath'). 
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+The special import path "all" expands to all package directories
+found in all the GOPATH trees.  For example, 'go list all' 
+lists all the packages on the local system.
+
+The special import path "std" is like all but expands to just the
+packages in the standard Go library.
+
+An import path is a pattern if it includes one or more "..." wildcards,
+each of which can match any string, including the empty string and
+strings containing slashes.  Such a pattern expands to all package
+directories found in the GOPATH trees with names matching the
+patterns.  For example, encoding/... expands to all packages
+in the encoding tree.
+
+An import path can also name a package to be downloaded from
+a remote repository.  Run 'go help remote' for details.
+
+Every package in a program must have a unique import path.
+By convention, this is arranged by starting each path with a
+unique prefix that belongs to you.  For example, paths used
+internally at Google all begin with 'google', and paths
+denoting remote repositories begin with the path to the code,
+such as 'code.google.com/p/project'.
+	`,
+}
+
+var helpRemote = &Command{
+	UsageLine: "remote",
+	Short:     "remote import path syntax",
+	Long: `
+
+An import path (see 'go help importpath') denotes a package
+stored in the local file system.  Certain import paths also
+describe how to obtain the source code for the package using
+a revision control system.
+
+A few common code hosting sites have special syntax:
+
+	BitBucket (Mercurial)
+
+		import "bitbucket.org/user/project"
+		import "bitbucket.org/user/project/sub/directory"
+
+	GitHub (Git)
+
+		import "github.com/user/project"
+		import "github.com/user/project/sub/directory"
+
+	Google Code Project Hosting (Git, Mercurial, Subversion)
+
+		import "code.google.com/p/project"
+		import "code.google.com/p/project/sub/directory"
+
+		import "code.google.com/p/project.subrepository"
+		import "code.google.com/p/project.subrepository/sub/directory"
+
+	Launchpad (Bazaar)
+
+		import "launchpad.net/project"
+		import "launchpad.net/project/series"
+		import "launchpad.net/project/series/sub/directory"
+
+		import "launchpad.net/~user/project/branch"
+		import "launchpad.net/~user/project/branch/sub/directory"
+
+For code hosted on other servers, an import path of the form
+
+	repository.vcs/path
+
+specifies the given repository, with or without the .vcs suffix,
+using the named version control system, and then the path inside
+that repository.  The supported version control systems are:
+
+	Bazaar      .bzr
+	Git         .git
+	Mercurial   .hg
+	Subversion  .svn
+
+For example,
+
+	import "example.org/user/foo.hg"
+
+denotes the root directory of the Mercurial repository at
+example.org/user/foo or foo.hg, and
+
+	import "example.org/repo.git/foo/bar"
+
+denotes the foo/bar directory of the Git repository at
+example.com/repo or repo.git.
+
+When a version control system supports multiple protocols,
+each is tried in turn when downloading.  For example, a Git
+download tries git://, then https://, then http://.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (see 'go help gopath').
+
+The go command attempts to download the version of the
+package appropriate for the Go release being used.
+Run 'go help install' for more.
+	`,
+}
+
+var helpGopath = &Command{
+	UsageLine: "gopath",
+	Short:     "GOPATH environment variable",
+	Long: `
+The GOPATH environment variable lists places to look for Go code.
+On Unix, the value is a colon-separated string.
+On Windows, the value is a semicolon-separated string.
+On Plan 9, the value is a list.
+
+GOPATH must be set to build and install packages outside the
+standard Go tree.
+
+Each directory listed in GOPATH must have a prescribed structure:
+
+The src/ directory holds source code.  The path below 'src'
+determines the import path or executable name.
+
+The pkg/ directory holds installed package objects.
+As in the Go tree, each target operating system and
+architecture pair has its own subdirectory of pkg
+(pkg/GOOS_GOARCH).
+
+If DIR is a directory listed in the GOPATH, a package with
+source in DIR/src/foo/bar can be imported as "foo/bar" and
+has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
+
+The bin/ directory holds compiled commands.
+Each command is named for its source directory, but only
+the final element, not the entire path.  That is, the
+command with source in DIR/src/foo/quux is installed into
+DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.
+
+Here's an example directory layout:
+
+    GOPATH=/home/user/gocode
+
+    /home/user/gocode/
+        src/
+            foo/
+                bar/               (go code in package bar)
+                    x.go
+                quux/              (go code in package main)
+                    y.go
+        bin/
+            quux                   (installed command)
+        pkg/
+            linux_amd64/
+                foo/
+                    bar.a          (installed package object)
+
+Go searches each directory listed in GOPATH to find source code,
+but new packages are always downloaded into the first directory 
+in the list.
+	`,
+}
diff --git a/src/cmd/go/http.go b/src/cmd/go/http.go
new file mode 100644
index 0000000..8d9b2a1
--- /dev/null
+++ b/src/cmd/go/http.go
@@ -0,0 +1,35 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !cmd_go_bootstrap
+
+// This code is compiled into the real 'go' binary, but it is not
+// compiled into the binary that is built during all.bash, so as
+// to avoid needing to build net (and thus use cgo) during the
+// bootstrap process.
+
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net/http"
+)
+
+// httpGET returns the data from an HTTP GET request for the given URL.
+func httpGET(url string) ([]byte, error) {
+	resp, err := http.Get(url)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != 200 {
+		return nil, fmt.Errorf("%s: %s", url, resp.Status)
+	}
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, fmt.Errorf("%s: %v", url, err)
+	}
+	return b, nil
+}
diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go
new file mode 100644
index 0000000..af211f9
--- /dev/null
+++ b/src/cmd/go/list.go
@@ -0,0 +1,114 @@
+// Copyright 2011 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 (
+	"encoding/json"
+	"os"
+	"text/template"
+)
+
+var cmdList = &Command{
+	UsageLine: "list [-e] [-f format] [-json] [importpath...]",
+	Short:     "list packages",
+	Long: `
+List lists the packages named by the import paths, one per line.
+
+The default output shows the package import path:
+
+    code.google.com/p/google-api-go-client/books/v1
+    code.google.com/p/goauth2/oauth
+    code.google.com/p/sqlite
+
+The -f flag specifies an alternate format for the list,
+using the syntax of package template.  The default output
+is equivalent to -f '{{.ImportPath}}'.  The struct
+being passed to the template is:
+
+    type Package struct {
+        Name       string // package name
+        Doc        string // package documentation string
+        ImportPath string // import path of package in dir
+        Dir        string // directory containing package sources
+        Version    string // version of installed package (TODO)
+        Stale      bool   // would 'go install' do anything for this package?
+
+        // Source files
+        GoFiles      []string // .go source files (excluding CgoFiles, TestGoFiles, and XTestGoFiles)
+        TestGoFiles  []string // _test.go source files internal to the package they are testing
+        XTestGoFiles []string // _test.go source files external to the package they are testing
+        CFiles       []string // .c source files
+        HFiles       []string // .h source files
+        SFiles       []string // .s source files
+        CgoFiles     []string // .go sources files that import "C"
+
+        // Dependency information
+        Imports []string // import paths used by this package
+        Deps    []string // all (recursively) imported dependencies
+        
+        // Error information
+        Incomplete bool            // this package or a dependency has an error
+        Error *PackageError        // error loading package
+        DepsErrors []*PackageError // errors loading dependencies
+    }
+
+The -json flag causes the package data to be printed in JSON format
+instead of using the template format.
+
+The -e flag changes the handling of erroneous packages, those that
+cannot be found or are malformed.  By default, the list command
+prints an error to standard error for each erroneous package and
+omits the packages from consideration during the usual printing.
+With the -e flag, the list command never prints errors to standard
+error and instead processes the erroneous packages with the usual
+printing.  Erroneous packages will have a non-empty ImportPath and
+a non-nil Error field; other information may or may not be missing
+(zeroed).
+
+For more about import paths, see 'go help importpath'.
+	`,
+}
+
+func init() {
+	cmdList.Run = runList // break init cycle
+}
+
+var listE = cmdList.Flag.Bool("e", false, "")
+var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
+var listJson = cmdList.Flag.Bool("json", false, "")
+var nl = []byte{'\n'}
+
+func runList(cmd *Command, args []string) {
+	var do func(*Package)
+	if *listJson {
+		do = func(p *Package) {
+			b, err := json.MarshalIndent(p, "", "\t")
+			if err != nil {
+				fatalf("%s", err)
+			}
+			os.Stdout.Write(b)
+			os.Stdout.Write(nl)
+		}
+	} else {
+		tmpl, err := template.New("main").Parse(*listFmt + "\n")
+		if err != nil {
+			fatalf("%s", err)
+		}
+		do = func(p *Package) {
+			if err := tmpl.Execute(os.Stdout, p); err != nil {
+				fatalf("%s", err)
+			}
+		}
+	}
+
+	load := packages
+	if *listE {
+		load = packagesAndErrors
+	}
+
+	for _, pkg := range load(args) {
+		do(pkg)
+	}
+}
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
new file mode 100644
index 0000000..ca3b118
--- /dev/null
+++ b/src/cmd/go/main.go
@@ -0,0 +1,485 @@
+// Copyright 2011 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 (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/build"
+	"io"
+	"log"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"regexp"
+	"strings"
+	"text/template"
+	"unicode"
+	"unicode/utf8"
+)
+
+// A Command is an implementation of a go command
+// like go build or go fix.
+type Command struct {
+	// Run runs the command.
+	// The args are the arguments after the command name.
+	Run func(cmd *Command, args []string)
+
+	// UsageLine is the one-line usage message.
+	// The first word in the line is taken to be the command name.
+	UsageLine string
+
+	// Short is the short description shown in the 'go help' output.
+	Short string
+
+	// Long is the long message shown in the 'go help <this-command>' output.
+	Long string
+
+	// Flag is a set of flags specific to this command.
+	Flag flag.FlagSet
+
+	// CustomFlags indicates that the command will do its own
+	// flag parsing.
+	CustomFlags bool
+}
+
+// Name returns the command's name: the first word in the usage line.
+func (c *Command) Name() string {
+	name := c.UsageLine
+	i := strings.Index(name, " ")
+	if i >= 0 {
+		name = name[:i]
+	}
+	return name
+}
+
+func (c *Command) Usage() {
+	fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
+	fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
+	os.Exit(2)
+}
+
+// Commands lists the available commands and help topics.
+// The order here is the order in which they are printed by 'go help'.
+var commands = []*Command{
+	cmdBuild,
+	cmdDoc,
+	cmdFix,
+	cmdFmt,
+	cmdGet,
+	cmdInstall,
+	cmdList,
+	cmdRun,
+	cmdTest,
+	cmdVersion,
+	cmdVet,
+
+	helpGopath,
+	helpImportpath,
+	helpRemote,
+	helpTestflag,
+	helpTestfunc,
+}
+
+var exitStatus = 0
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+	log.SetFlags(0)
+
+	args := flag.Args()
+	if len(args) < 1 {
+		usage()
+	}
+
+	if args[0] == "help" {
+		help(args[1:])
+		return
+	}
+
+	for _, cmd := range commands {
+		if cmd.Name() == args[0] && cmd.Run != nil {
+			cmd.Flag.Usage = func() { cmd.Usage() }
+			if cmd.CustomFlags {
+				args = args[1:]
+			} else {
+				cmd.Flag.Parse(args[1:])
+				args = cmd.Flag.Args()
+			}
+			cmd.Run(cmd, args)
+			exit()
+			return
+		}
+	}
+
+	fmt.Fprintf(os.Stderr, "Unknown command %#q\n\n", args[0])
+	usage()
+}
+
+var usageTemplate = `Go is a tool for managing Go source code.
+
+Usage: go command [arguments]
+
+The commands are:
+{{range .}}{{if .Run}}
+    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+{{range .}}{{if not .Run}}
+    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "go help [topic]" for more information about that topic.
+
+`
+
+var helpTemplate = `{{if .Run}}usage: go {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+`
+
+var documentationTemplate = `// Copyright 2011 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.
+
+/*
+{{range .}}{{if .Short}}{{.Short | capitalize}}
+
+{{end}}{{if .Run}}Usage:
+
+	go {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+
+
+{{end}}*/
+package documentation
+
+// NOTE: cmdDoc is in fmt.go.
+`
+
+// tmpl executes the given template text on data, writing the result to w.
+func tmpl(w io.Writer, text string, data interface{}) {
+	t := template.New("top")
+	t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
+	template.Must(t.Parse(text))
+	if err := t.Execute(w, data); err != nil {
+		panic(err)
+	}
+}
+
+func capitalize(s string) string {
+	if s == "" {
+		return s
+	}
+	r, n := utf8.DecodeRuneInString(s)
+	return string(unicode.ToTitle(r)) + s[n:]
+}
+
+func printUsage(w io.Writer) {
+	tmpl(w, usageTemplate, commands)
+}
+
+func usage() {
+	printUsage(os.Stderr)
+	os.Exit(2)
+}
+
+// help implements the 'help' command.
+func help(args []string) {
+	if len(args) == 0 {
+		printUsage(os.Stdout)
+		// not exit 2: succeeded at 'go help'.
+		return
+	}
+	if len(args) != 1 {
+		fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
+		os.Exit(2) // failed at 'go help'
+	}
+
+	arg := args[0]
+
+	// 'go help documentation' generates doc.go.
+	if arg == "documentation" {
+		buf := new(bytes.Buffer)
+		printUsage(buf)
+		usage := &Command{Long: buf.String()}
+		tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...))
+		return
+	}
+
+	for _, cmd := range commands {
+		if cmd.Name() == arg {
+			tmpl(os.Stdout, helpTemplate, cmd)
+			// not exit 2: succeeded at 'go help cmd'.
+			return
+		}
+	}
+
+	fmt.Fprintf(os.Stderr, "Unknown help topic %#q.  Run 'go help'.\n", arg)
+	os.Exit(2) // failed at 'go help cmd'
+}
+
+// importPaths returns the import paths to use for the given command line.
+func importPaths(args []string) []string {
+	if len(args) == 0 {
+		return []string{"."}
+	}
+	var out []string
+	for _, a := range args {
+		if isLocalPath(a) && strings.Contains(a, "...") {
+			out = append(out, allPackagesInFS(a)...)
+			continue
+		}
+		if a == "all" || a == "std" || strings.Contains(a, "...") {
+			out = append(out, allPackages(a)...)
+			continue
+		}
+		out = append(out, a)
+	}
+	return out
+}
+
+var atexitFuncs []func()
+
+func atexit(f func()) {
+	atexitFuncs = append(atexitFuncs, f)
+}
+
+func exit() {
+	for _, f := range atexitFuncs {
+		f()
+	}
+	os.Exit(exitStatus)
+}
+
+func fatalf(format string, args ...interface{}) {
+	errorf(format, args...)
+	exit()
+}
+
+func errorf(format string, args ...interface{}) {
+	log.Printf(format, args...)
+	exitStatus = 1
+}
+
+var logf = log.Printf
+
+func exitIfErrors() {
+	if exitStatus != 0 {
+		exit()
+	}
+}
+
+func run(cmdargs ...interface{}) {
+	cmdline := stringList(cmdargs...)
+	cmd := exec.Command(cmdline[0], cmdline[1:]...)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		errorf("%v", err)
+	}
+}
+
+func runOut(dir string, cmdargs ...interface{}) []byte {
+	cmdline := stringList(cmdargs...)
+	cmd := exec.Command(cmdline[0], cmdline[1:]...)
+	cmd.Dir = dir
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		os.Stderr.Write(out)
+		errorf("%v", err)
+		out = nil
+	}
+	return out
+}
+
+// matchPattern(pattern)(name) reports whether
+// name matches pattern.  Pattern is a limited glob
+// pattern in which '...' means 'any string' and there
+// is no other special syntax.
+func matchPattern(pattern string) func(name string) bool {
+	re := regexp.QuoteMeta(pattern)
+	re = strings.Replace(re, `\.\.\.`, `.*`, -1)
+	reg := regexp.MustCompile(`^` + re + `$`)
+	return func(name string) bool {
+		return reg.MatchString(name)
+	}
+}
+
+// allPackages returns all the packages that can be found
+// under the $GOPATH directories and $GOROOT matching pattern.
+// The pattern is either "all" (all packages), "std" (standard packages)
+// or a path including "...".
+func allPackages(pattern string) []string {
+	match := func(string) bool { return true }
+	if pattern != "all" && pattern != "std" {
+		match = matchPattern(pattern)
+	}
+
+	have := map[string]bool{
+		"builtin": true, // ignore pseudo-package that exists only for documentation
+	}
+	if !buildContext.CgoEnabled {
+		have["runtime/cgo"] = true // ignore during walk
+	}
+	var pkgs []string
+
+	// Commands
+	goroot := build.Path[0].Path
+	cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
+	filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
+		if err != nil || !fi.IsDir() {
+			return nil
+		}
+		name := path[len(cmd):]
+		// Commands are all in cmd/, not in subdirectories.
+		if strings.Contains(name, string(filepath.Separator)) {
+			return filepath.SkipDir
+		}
+
+		_, err = build.ScanDir(path)
+		if err != nil {
+			return nil
+		}
+
+		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
+		name = "cmd/" + name
+		if !have[name] {
+			have[name] = true
+			if match(name) {
+				pkgs = append(pkgs, name)
+			}
+		}
+		return nil
+	})
+
+	for _, t := range build.Path {
+		if pattern == "std" && !t.Goroot {
+			continue
+		}
+		src := t.SrcDir() + string(filepath.Separator)
+		filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
+			if err != nil || !fi.IsDir() {
+				return nil
+			}
+
+			// Avoid .foo, _foo, and testdata directory trees.
+			_, elem := filepath.Split(path)
+			if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+				return filepath.SkipDir
+			}
+
+			name := filepath.ToSlash(path[len(src):])
+			if pattern == "std" && strings.Contains(name, ".") {
+				return filepath.SkipDir
+			}
+			if have[name] {
+				return nil
+			}
+			have[name] = true
+
+			_, err = build.ScanDir(path)
+			if err != nil {
+				return nil
+			}
+
+			if match(name) {
+				pkgs = append(pkgs, name)
+			}
+
+			// Avoid go/build test data.
+			// TODO: Move it into a testdata directory.
+			if path == filepath.Join(build.Path[0].SrcDir(), "go/build") {
+				return filepath.SkipDir
+			}
+
+			return nil
+		})
+	}
+
+	if len(pkgs) == 0 {
+		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+	}
+	return pkgs
+}
+
+// allPackagesInFS is like allPackages but is passed a pattern
+// beginning ./ or ../, meaning it should scan the tree rooted
+// at the given directory.  There are ... in the pattern too.
+func allPackagesInFS(pattern string) []string {
+	// Find directory to begin the scan.
+	// Could be smarter but this one optimization
+	// is enough for now, since ... is usually at the
+	// end of a path.
+	i := strings.Index(pattern, "...")
+	dir, _ := path.Split(pattern[:i])
+
+	// pattern begins with ./ or ../.
+	// path.Clean will discard the ./ but not the ../.
+	// We need to preserve the ./ for pattern matching
+	// and in the returned import paths.
+	prefix := ""
+	if strings.HasPrefix(pattern, "./") {
+		prefix = "./"
+	}
+	match := matchPattern(pattern)
+
+	var pkgs []string
+	filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
+		if err != nil || !fi.IsDir() {
+			return nil
+		}
+
+		// Avoid .foo, _foo, and testdata directory trees.
+		_, elem := filepath.Split(path)
+		if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+			return filepath.SkipDir
+		}
+
+		name := prefix + filepath.ToSlash(path)
+		if !match(name) {
+			return nil
+		}
+		if _, err = build.ScanDir(path); err != nil {
+			return nil
+		}
+		pkgs = append(pkgs, name)
+		return nil
+	})
+
+	if len(pkgs) == 0 {
+		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+	}
+	return pkgs
+}
+
+// stringList's arguments should be a sequence of string or []string values.
+// stringList flattens them into a single []string.
+func stringList(args ...interface{}) []string {
+	var x []string
+	for _, arg := range args {
+		switch arg := arg.(type) {
+		case []string:
+			x = append(x, arg...)
+		case string:
+			x = append(x, arg)
+		default:
+			panic("stringList: invalid argument")
+		}
+	}
+	return x
+}
+
+// isLocalPath returns true if arg is an import path denoting
+// a local file system directory.  That is, it returns true if the
+// path begins with ./ or ../ .
+func isLocalPath(arg string) bool {
+	return arg == "." || arg == ".." || strings.HasPrefix(arg, "./") || strings.HasPrefix(arg, "../")
+}
diff --git a/src/cmd/go/mkdoc.sh b/src/cmd/go/mkdoc.sh
new file mode 100755
index 0000000..7768bae
--- /dev/null
+++ b/src/cmd/go/mkdoc.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+# Copyright 2012 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+go help documentation > doc.go
+gofmt -w doc.go
+
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
new file mode 100644
index 0000000..09fa671
--- /dev/null
+++ b/src/cmd/go/pkg.go
@@ -0,0 +1,445 @@
+// Copyright 2011 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 (
+	"go/build"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+	"time"
+)
+
+// A Package describes a single package found in a directory.
+type Package struct {
+	// Note: These fields are part of the go command's public API.
+	// See list.go.  It is okay to add fields, but not to change or
+	// remove existing ones.  Keep in sync with list.go
+	ImportPath string        // import path of package in dir
+	Name       string        `json:",omitempty"` // package name
+	Doc        string        `json:",omitempty"` // package documentation string
+	Dir        string        `json:",omitempty"` // directory containing package sources
+	Version    string        `json:",omitempty"` // version of installed package (TODO)
+	Standard   bool          `json:",omitempty"` // is this package part of the standard Go library?
+	Stale      bool          `json:",omitempty"` // would 'go install' do anything for this package?
+	Incomplete bool          `json:",omitempty"` // was there an error loading this package or dependencies?
+	Error      *PackageError `json:",omitempty"` // error loading this package (not dependencies)
+
+	// Source files
+	GoFiles      []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles and XTestGoFiles)
+	TestGoFiles  []string `json:",omitempty"` // _test.go source files internal to the package they are testing
+	XTestGoFiles []string `json:",omitempty"` //_test.go source files external to the package they are testing
+	CFiles       []string `json:",omitempty"` // .c source files
+	HFiles       []string `json:",omitempty"` // .h source files
+	SFiles       []string `json:",omitempty"` // .s source files
+	CgoFiles     []string `json:",omitempty"` // .go sources files that import "C"
+	CgoCFLAGS    []string `json:",omitempty"` // cgo: flags for C compiler
+	CgoLDFLAGS   []string `json:",omitempty"` // cgo: flags for linker
+
+	// Dependency information
+	Imports    []string        `json:",omitempty"` // import paths used by this package
+	Deps       []string        `json:",omitempty"` // all (recursively) imported dependencies
+	DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
+
+	// Unexported fields are not part of the public API.
+	t       *build.Tree
+	pkgdir  string
+	info    *build.DirInfo
+	imports []*Package
+	deps    []*Package
+	gofiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
+	target  string   // installed file for this package (may be executable)
+	fake    bool     // synthesized package
+}
+
+// A PackageError describes an error loading information about a package.
+type PackageError struct {
+	ImportStack []string // shortest path from package named on command line to this one
+	Err         string   // the error itself
+}
+
+func (p *PackageError) Error() string {
+	return strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err
+}
+
+// An importStack is a stack of import paths.
+type importStack []string
+
+func (s *importStack) push(p string) {
+	*s = append(*s, p)
+}
+
+func (s *importStack) pop() {
+	*s = (*s)[0 : len(*s)-1]
+}
+
+func (s *importStack) copy() []string {
+	return append([]string{}, *s...)
+}
+
+// shorterThan returns true if sp is shorter than t.
+// We use this to record the shortest import sequence
+// that leads to a particular package.
+func (sp *importStack) shorterThan(t []string) bool {
+	s := *sp
+	if len(s) != len(t) {
+		return len(s) < len(t)
+	}
+	// If they are the same length, settle ties using string ordering.
+	for i := range s {
+		if s[i] != t[i] {
+			return s[i] < t[i]
+		}
+	}
+	return false // they are equal
+}
+
+// packageCache is a lookup cache for loadPackage,
+// so that if we look up a package multiple times
+// we return the same pointer each time.
+var packageCache = map[string]*Package{}
+
+// reloadPackage is like loadPackage but makes sure
+// not to use the package cache.
+func reloadPackage(arg string, stk *importStack) *Package {
+	p := packageCache[arg]
+	if p != nil {
+		delete(packageCache, p.Dir)
+		delete(packageCache, p.ImportPath)
+	}
+	return loadPackage(arg, stk)
+}
+
+// loadPackage scans directory named by arg,
+// which is either an import path or a file system path
+// (if the latter, must be rooted or begin with . or ..),
+// and returns a *Package describing the package
+// found in that directory.
+func loadPackage(arg string, stk *importStack) *Package {
+	stk.push(arg)
+	defer stk.pop()
+
+	// Check package cache.
+	if p := packageCache[arg]; p != nil {
+		return reusePackage(p, stk)
+	}
+
+	// Find basic information about package path.
+	t, importPath, err := build.FindTree(arg)
+	dir := ""
+	// Maybe it is a standard command.
+	if err != nil && strings.HasPrefix(arg, "cmd/") {
+		goroot := build.Path[0]
+		p := filepath.Join(goroot.Path, "src", arg)
+		if st, err1 := os.Stat(p); err1 == nil && st.IsDir() {
+			t = goroot
+			importPath = arg
+			dir = p
+			err = nil
+		}
+	}
+	// Maybe it is a path to a standard command.
+	if err != nil && (filepath.IsAbs(arg) || isLocalPath(arg)) {
+		arg, _ := filepath.Abs(arg)
+		goroot := build.Path[0]
+		cmd := filepath.Join(goroot.Path, "src", "cmd") + string(filepath.Separator)
+		if st, err1 := os.Stat(arg); err1 == nil && st.IsDir() && strings.HasPrefix(arg, cmd) {
+			t = goroot
+			importPath = filepath.FromSlash(arg[len(cmd):])
+			dir = arg
+			err = nil
+		}
+	}
+	if err != nil {
+		p := &Package{
+			ImportPath: arg,
+			Error: &PackageError{
+				ImportStack: stk.copy(),
+				Err:         err.Error(),
+			},
+			Incomplete: true,
+		}
+		packageCache[arg] = p
+		return p
+	}
+
+	if dir == "" {
+		dir = filepath.Join(t.SrcDir(), filepath.FromSlash(importPath))
+	}
+
+	// Maybe we know the package by its directory.
+	if p := packageCache[dir]; p != nil {
+		packageCache[importPath] = p
+		return reusePackage(p, stk)
+	}
+
+	return scanPackage(&buildContext, t, arg, importPath, dir, stk)
+}
+
+func reusePackage(p *Package, stk *importStack) *Package {
+	// We use p.imports==nil to detect a package that
+	// is in the midst of its own loadPackage call
+	// (all the recursion below happens before p.imports gets set).
+	if p.imports == nil {
+		if p.Error == nil {
+			p.Error = &PackageError{
+				ImportStack: stk.copy(),
+				Err:         "import loop",
+			}
+		}
+		p.Incomplete = true
+	}
+	if p.Error != nil && stk.shorterThan(p.Error.ImportStack) {
+		p.Error.ImportStack = stk.copy()
+	}
+	return p
+}
+
+// firstSentence returns the first sentence of the document text.
+// The sentence ends after the first period followed by a space.
+// The returned sentence will have no \n \r or \t characters and
+// will use only single spaces between words.
+func firstSentence(text string) string {
+	var b []byte
+	space := true
+Loop:
+	for i := 0; i < len(text); i++ {
+		switch c := text[i]; c {
+		case ' ', '\t', '\r', '\n':
+			if !space {
+				space = true
+				if len(b) > 0 && b[len(b)-1] == '.' {
+					break Loop
+				}
+				b = append(b, ' ')
+			}
+		default:
+			space = false
+			b = append(b, c)
+		}
+	}
+	return string(b)
+}
+
+func scanPackage(ctxt *build.Context, t *build.Tree, arg, importPath, dir string, stk *importStack) *Package {
+	// Read the files in the directory to learn the structure
+	// of the package.
+	p := &Package{
+		ImportPath: importPath,
+		Dir:        dir,
+		Standard:   t.Goroot && !strings.Contains(importPath, "."),
+		t:          t,
+	}
+	packageCache[dir] = p
+	packageCache[importPath] = p
+
+	info, err := ctxt.ScanDir(dir)
+	if err != nil {
+		p.Error = &PackageError{
+			ImportStack: stk.copy(),
+			Err:         err.Error(),
+		}
+		p.Incomplete = true
+		return p
+	}
+
+	p.info = info
+	p.Name = info.Package
+	p.Doc = firstSentence(info.PackageComment.Text())
+	p.Imports = info.Imports
+	p.GoFiles = info.GoFiles
+	p.TestGoFiles = info.TestGoFiles
+	p.XTestGoFiles = info.XTestGoFiles
+	p.CFiles = info.CFiles
+	p.HFiles = info.HFiles
+	p.SFiles = info.SFiles
+	p.CgoFiles = info.CgoFiles
+	p.CgoCFLAGS = info.CgoCFLAGS
+	p.CgoLDFLAGS = info.CgoLDFLAGS
+
+	if info.Package == "main" {
+		_, elem := filepath.Split(importPath)
+		p.target = filepath.Join(t.BinDir(), elem)
+		if ctxt.GOOS == "windows" {
+			p.target += ".exe"
+		}
+	} else {
+		p.target = filepath.Join(t.PkgDir(), filepath.FromSlash(importPath)+".a")
+	}
+
+	var built time.Time
+	if fi, err := os.Stat(p.target); err == nil {
+		built = fi.ModTime()
+	}
+
+	// Build list of full paths to all Go files in the package,
+	// for use by commands like go fmt.
+	for _, f := range info.GoFiles {
+		p.gofiles = append(p.gofiles, filepath.Join(dir, f))
+	}
+	for _, f := range info.CgoFiles {
+		p.gofiles = append(p.gofiles, filepath.Join(dir, f))
+	}
+	for _, f := range info.TestGoFiles {
+		p.gofiles = append(p.gofiles, filepath.Join(dir, f))
+	}
+	for _, f := range info.XTestGoFiles {
+		p.gofiles = append(p.gofiles, filepath.Join(dir, f))
+	}
+
+	sort.Strings(p.gofiles)
+
+	srcss := [][]string{
+		p.GoFiles,
+		p.CFiles,
+		p.HFiles,
+		p.SFiles,
+		p.CgoFiles,
+	}
+Stale:
+	for _, srcs := range srcss {
+		for _, src := range srcs {
+			if fi, err := os.Stat(filepath.Join(p.Dir, src)); err != nil || fi.ModTime().After(built) {
+				//println("STALE", p.ImportPath, "needs", src, err)
+				p.Stale = true
+				break Stale
+			}
+		}
+	}
+
+	importPaths := p.Imports
+	// Packages that use cgo import runtime/cgo implicitly,
+	// except runtime/cgo itself.
+	if len(info.CgoFiles) > 0 && (!p.Standard || p.ImportPath != "runtime/cgo") {
+		importPaths = append(importPaths, "runtime/cgo")
+	}
+	// Everything depends on runtime, except runtime and unsafe.
+	if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
+		importPaths = append(importPaths, "runtime")
+	}
+
+	// Record package under both import path and full directory name.
+	packageCache[dir] = p
+	packageCache[importPath] = p
+
+	// Build list of imported packages and full dependency list.
+	imports := make([]*Package, 0, len(p.Imports))
+	deps := make(map[string]bool)
+	for _, path := range importPaths {
+		if path == "C" {
+			continue
+		}
+		deps[path] = true
+		p1 := loadPackage(path, stk)
+		imports = append(imports, p1)
+		for _, dep := range p1.Deps {
+			deps[dep] = true
+		}
+		if p1.Stale {
+			p.Stale = true
+		}
+		if p1.Incomplete {
+			p.Incomplete = true
+		}
+		// p1.target can be empty only if p1 is not a real package,
+		// such as package unsafe or the temporary packages
+		// created during go test.
+		if !p.Stale && p1.target != "" {
+			if fi, err := os.Stat(p1.target); err != nil || fi.ModTime().After(built) {
+				//println("STALE", p.ImportPath, "needs", p1.target, err)
+				//println("BUILT", built.String(), "VS", fi.ModTime().String())
+				p.Stale = true
+			}
+		}
+	}
+	p.imports = imports
+
+	p.Deps = make([]string, 0, len(deps))
+	for dep := range deps {
+		p.Deps = append(p.Deps, dep)
+	}
+	sort.Strings(p.Deps)
+	for _, dep := range p.Deps {
+		p1 := packageCache[dep]
+		if p1 == nil {
+			panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath)
+		}
+		p.deps = append(p.deps, p1)
+		if p1.Error != nil {
+			p.DepsErrors = append(p.DepsErrors, p1.Error)
+		}
+	}
+
+	// unsafe is a fake package and is never out-of-date.
+	if p.Standard && p.ImportPath == "unsafe" {
+		p.Stale = false
+		p.target = ""
+	}
+
+	return p
+}
+
+// packages returns the packages named by the
+// command line arguments 'args'.  If a named package
+// cannot be loaded at all (for example, if the directory does not exist),
+// then packages prints an error and does not include that
+// package in the results.  However, if errors occur trying
+// to load dependencies of a named package, the named
+// package is still returned, with p.Incomplete = true
+// and details in p.DepsErrors.
+func packages(args []string) []*Package {
+	args = importPaths(args)
+	var pkgs []*Package
+	var stk importStack
+	for _, arg := range args {
+		pkg := loadPackage(arg, &stk)
+		if pkg.Error != nil {
+			errorf("%s", pkg.Error)
+			continue
+		}
+		pkgs = append(pkgs, pkg)
+	}
+	return pkgs
+}
+
+// packagesAndErrors is like 'packages' but returns a 
+// *Package for every argument, even the ones that
+// cannot be loaded at all.
+// The packages that fail to load will have p.Error != nil.
+func packagesAndErrors(args []string) []*Package {
+	args = importPaths(args)
+	var pkgs []*Package
+	var stk importStack
+	for _, arg := range args {
+		pkgs = append(pkgs, loadPackage(arg, &stk))
+	}
+	return pkgs
+}
+
+// packagesForBuild is like 'packages' but fails if any of
+// the packages or their dependencies have errors
+// (cannot be built).
+func packagesForBuild(args []string) []*Package {
+	pkgs := packagesAndErrors(args)
+	printed := map[*PackageError]bool{}
+	for _, pkg := range pkgs {
+		if pkg.Error != nil {
+			errorf("%s", pkg.Error)
+		}
+		for _, err := range pkg.DepsErrors {
+			// Since these are errors in dependencies,
+			// the same error might show up multiple times,
+			// once in each package that depends on it.
+			// Only print each once.
+			if !printed[err] {
+				printed[err] = true
+				errorf("%s", err)
+			}
+		}
+	}
+	exitIfErrors()
+	return pkgs
+}
diff --git a/src/cmd/go/run.go b/src/cmd/go/run.go
new file mode 100644
index 0000000..714cd40
--- /dev/null
+++ b/src/cmd/go/run.go
@@ -0,0 +1,57 @@
+// Copyright 2011 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 "strings"
+
+var cmdRun = &Command{
+	UsageLine: "run [-a] [-n] [-x] gofiles... [arguments...]",
+	Short:     "compile and run Go program",
+	Long: `
+Run compiles and runs the main package comprising the named Go source files.
+
+The -a flag forces reinstallation of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -x flag prints the commands.
+
+See also: go build.
+	`,
+}
+
+func init() {
+	cmdRun.Run = runRun // break init loop
+
+	cmdRun.Flag.BoolVar(&buildA, "a", false, "")
+	cmdRun.Flag.BoolVar(&buildN, "n", false, "")
+	cmdRun.Flag.BoolVar(&buildX, "x", false, "")
+}
+
+func runRun(cmd *Command, args []string) {
+	var b builder
+	b.init()
+	i := 0
+	for i < len(args) && strings.HasSuffix(args[i], ".go") {
+		i++
+	}
+	files, cmdArgs := args[:i], args[i:]
+	p := goFilesPackage(files, "")
+	p.target = "" // must build - not up to date
+	a1 := b.action(modeBuild, modeBuild, p)
+	a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
+	b.do(a)
+}
+
+// runProgram is the action for running a binary that has already
+// been compiled.  We ignore exit status.
+func (b *builder) runProgram(a *action) error {
+	if buildN || buildX {
+		b.showcmd("", "%s %s", a.deps[0].target, strings.Join(a.args, " "))
+		if buildN {
+			return nil
+		}
+	}
+	run(a.deps[0].target, a.args)
+	return nil
+}
diff --git a/src/cmd/go/script b/src/cmd/go/script
new file mode 100755
index 0000000..340a7e8
--- /dev/null
+++ b/src/cmd/go/script
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+x() {
+	echo '--- ' "$@"
+	"$@"
+	echo '---'
+	echo
+}
+
+x go help
+x go help build
+x go help clean
+x go help install
+x go help fix
+x go help fmt
+x go help get
+x go help list
+x go help test
+x go help version
+x go help vet
+x go help gopath
+x go help importpath
+x go help remote
diff --git a/src/cmd/go/script.txt b/src/cmd/go/script.txt
new file mode 100644
index 0000000..a672146
--- /dev/null
+++ b/src/cmd/go/script.txt
@@ -0,0 +1,352 @@
+---  go help
+usage: go command [arguments]
+
+go manages Go source code.
+
+The commands are:
+
+    build       compile and install packages and dependencies
+    clean       remove intermediate objects
+    fix         run gofix on packages
+    fmt         run gofmt -w on packages
+    get         download and install packages and dependencies
+    install     install packages and dependencies
+    list        list packages
+    test        test packages
+    version     print Go version
+    vet         run govet on packages
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+
+    gopath      GOPATH environment variable
+    importpath  description of import paths
+    remote      remote import path syntax
+
+Use "go help [topic]" for more information about that topic.
+
+---
+
+---  go help build
+usage: go build [-n] [-v] [importpath...]
+
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+The -n flag prints the commands but does not run them.
+The -v flag prints the commands.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go install, go get, go clean.
+---
+
+---  go help clean
+usage: go clean [-nuke] [importpath...]
+
+Clean removes intermediate object files generated during
+the compilation of the packages named by the import paths,
+but by default it does not remove the installed package binaries.
+
+The -nuke flag causes clean to remove the installed package binaries too.
+
+TODO: Clean does not clean dependencies of the packages.
+
+For more about import paths, see 'go help importpath'.
+---
+
+---  go help install
+usage: go install [-n] [-v] [importpath...]
+
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+The -n flag prints the commands but does not run them.
+The -v flag prints the commands.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go get, go clean.
+---
+
+---  go help fix
+usage: go fix [importpath...]
+
+Fix runs the gofix command on the packages named by the import paths.
+
+For more about gofix, see 'godoc gofix'.
+For more about import paths, see 'go help importpath'.
+
+To run gofix with specific options, run gofix itself.
+
+See also: go fmt, go vet.
+---
+
+---  go help fmt
+usage: go fmt [importpath...]
+
+Fmt runs the command 'gofmt -w' on the packages named by the import paths.
+
+For more about gofmt, see 'godoc gofmt'.
+For more about import paths, see 'go help importpath'.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go fix, go vet.
+---
+
+---  go help get
+usage: go get [importpath...]
+
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+After downloading the code, 'go get' looks for a tag beginning
+with "go." that corresponds to the local Go version.
+For Go "release.r58" it looks for a tag named "go.r58".
+For "weekly.2011-06-03" it looks for "go.weekly.2011-06-03".
+If the specific "go.X" tag is not found, it uses the latest earlier
+version it can find.  Otherwise, it uses the default version for
+the version control system: HEAD for git, tip for Mercurial,
+and so on.
+
+TODO: Explain versions better.
+
+For more about import paths, see 'go help importpath'.
+
+For more about how 'go get' finds source code to
+download, see 'go help remote'.
+
+See also: go build, go install, go clean.
+---
+
+---  go help list
+usage: go list [-f format] [-json] [importpath...]
+
+List lists the packages named by the import paths.
+
+The default output shows the package name and file system location:
+
+    books /home/you/src/google-api-go-client.googlecode.com/hg/books/v1
+    oauth /home/you/src/goauth2.googlecode.com/hg/oauth
+    sqlite /home/you/src/gosqlite.googlecode.com/hg/sqlite
+
+The -f flag specifies an alternate format for the list,
+using the syntax of package template.  The default output
+is equivalent to -f '{{.Name}} {{.Dir}}'  The struct
+being passed to the template is:
+
+    type Package struct {
+        Name string         // package name
+        Doc string          // package documentation string
+        GoFiles []string    // names of Go source files in package
+        ImportPath string   // import path denoting package
+        Imports []string    // import paths used by this package
+        Deps []string       // all (recursively) imported dependencies
+        Dir string          // directory containing package sources
+        Version string      // version of installed package
+    }
+
+The -json flag causes the package data to be printed in JSON format.
+
+For more about import paths, see 'go help importpath'.
+---
+
+---  go help test
+usage: go test [importpath...]
+
+Test runs gotest to test the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+	test archive/tar
+	FAIL archive/zip
+	test compress/gzip
+	...
+
+followed by gotest output for each failed package.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go compile, go vet.
+---
+
+---  go help version
+usage: go version
+
+Version prints the Go version, as reported by runtime.Version.
+---
+
+---  go help vet
+usage: go vet [importpath...]
+
+Vet runs the govet command on the packages named by the import paths.
+
+For more about govet, see 'godoc govet'.
+For more about import paths, see 'go help importpath'.
+
+To run govet with specific options, run govet itself.
+
+See also: go fmt, go fix.
+---
+
+---  go help gopath
+The GOPATH environment variable lists places to look for Go code.
+On Unix, the value is a colon-separated string.
+On Windows, the value is a semicolon-separated string.
+On Plan 9, the value is a list.
+
+GOPATH must be set to build and install packages outside the
+standard Go tree.
+
+Each directory listed in GOPATH must have a prescribed structure:
+
+The src/ directory holds source code.  The path below 'src'
+determines the import path or executable name.
+
+The pkg/ directory holds installed package objects.
+As in the Go tree, each target operating system and
+architecture pair has its own subdirectory of pkg
+(pkg/GOOS_GOARCH).
+
+If DIR is a directory listed in the GOPATH, a package with
+source in DIR/src/foo/bar can be imported as "foo/bar" and
+has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
+
+The bin/ directory holds compiled commands.
+Each command is named for its source directory, but only
+the final element, not the entire path.  That is, the
+command with source in DIR/src/foo/quux is installed into
+DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.
+
+Here's an example directory layout:
+
+    GOPATH=/home/user/gocode
+
+    /home/user/gocode/
+        src/
+            foo/
+                bar/               (go code in package bar)
+                    x.go
+                quux/              (go code in package main)
+                    y.go
+        bin/
+            quux                   (installed command)
+		pkg/
+		    linux_amd64/
+		        foo/
+		            bar.a          (installed package object)
+
+Go searches each directory listed in GOPATH to find source code,
+but new packages are always downloaded into the first directory 
+in the list.
+---
+
+---  go help importpath
+Many commands apply to a set of packages named by import paths:
+
+	go action [importpath...]
+
+An import path that is a rooted path or that begins with
+a . or .. element is interpreted as a file system path and
+denotes the package in that directory.
+
+Otherwise, the import path P denotes the package found in
+the directory DIR/src/P for some DIR listed in the GOPATH
+environment variable (see 'go help gopath'). 
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+The special import path "all" expands to all package directories
+found in all the GOPATH trees.  For example, 'go list all' 
+lists all the packages on the local system.
+
+An import path can also name a package to be downloaded from
+a remote repository.  Run 'go help remote' for details.
+
+Every package in a program must have a unique import path.
+By convention, this is arranged by starting each path with a
+unique prefix that belongs to you.  For example, paths used
+internally at Google all begin with 'google', and paths
+denoting remote repositories begin with the path to the code,
+such as 'project.googlecode.com/'.
+---
+
+---  go help remote
+An import path (see 'go help importpath') denotes a package
+stored in the local file system.  Certain import paths also
+describe how to obtain the source code for the package using
+a revision control system.
+
+A few common code hosting sites have special syntax:
+
+	BitBucket (Mercurial)
+
+		import "bitbucket.org/user/project"
+		import "bitbucket.org/user/project/sub/directory"
+
+	GitHub (Git)
+
+		import "github.com/user/project"
+		import "github.com/user/project/sub/directory"
+
+	Google Code Project Hosting (Git, Mercurial, Subversion)
+
+		import "project.googlecode.com/git"
+		import "project.googlecode.com/git/sub/directory"
+
+		import "project.googlecode.com/hg"
+		import "project.googlecode.com/hg/sub/directory"
+
+		import "project.googlecode.com/svn/trunk"
+		import "project.googlecode.com/svn/trunk/sub/directory"
+
+	Launchpad (Bazaar)
+
+		import "launchpad.net/project"
+		import "launchpad.net/project/series"
+		import "launchpad.net/project/series/sub/directory"
+
+		import "launchpad.net/~user/project/branch"
+		import "launchpad.net/~user/project/branch/sub/directory"
+
+For code hosted on other servers, an import path of the form
+
+	repository.vcs/path
+
+specifies the given repository, with or without the .vcs suffix,
+using the named version control system, and then the path inside
+that repository.  The supported version control systems are:
+
+	Bazaar      .bzr
+	Git         .git
+	Mercurial   .hg
+	Subversion  .svn
+
+For example,
+
+	import "example.org/user/foo.hg"
+
+denotes the root directory of the Mercurial repository at
+example.org/user/foo or foo.hg, and
+
+	import "example.org/repo.git/foo/bar"
+
+denotes the foo/bar directory of the Git repository at
+example.com/repo or repo.git.
+
+When a version control system supports multiple protocols,
+each is tried in turn when downloading.  For example, a Git
+download tries git://, then https://, then http://.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (see 'go help gopath').
+
+The go command attempts to download the version of the
+package appropriate for the Go release being used.
+Run 'go help install' for more.
+---
+
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
new file mode 100644
index 0000000..6cd49fe
--- /dev/null
+++ b/src/cmd/go/test.go
@@ -0,0 +1,681 @@
+// Copyright 2011 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 (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/parser"
+	"go/token"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"text/template"
+	"time"
+	"unicode"
+	"unicode/utf8"
+)
+
+// Break init loop.
+func init() {
+	cmdTest.Run = runTest
+}
+
+var cmdTest = &Command{
+	CustomFlags: true,
+	UsageLine:   "test [-c] [-file a.go -file b.go ...] [-p n] [-x] [importpath...] [flags for test binary]",
+	Short:       "test packages",
+	Long: `
+'Go test' automates testing the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+	ok   archive/tar   0.011s
+	FAIL archive/zip   0.022s
+	ok   compress/gzip 0.033s
+	...
+
+followed by detailed output for each failed package.
+
+'Go test' recompiles each package along with any files with names matching
+the file pattern "*_test.go".  These additional files can contain test functions,
+benchmark functions, and example functions.  See 'go help testfunc' for more.
+
+By default, go test needs no arguments.  It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+If file names are given (with flag -file=test.go, one per extra test source file),
+only those test files are added to the package.  (The non-test files are always
+compiled.)
+
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+
+See 'go help testflag' for details about flags handled by 'go test'
+and the test binary.
+
+See 'go help importpath' for more about import paths.
+
+See also: go build, go vet.
+	`,
+}
+
+var helpTestflag = &Command{
+	UsageLine: "testflag",
+	Short:     "description of testing flags",
+	Long: `
+The 'go test' command takes both flags that apply to 'go test' itself
+and flags that apply to the resulting test binary.
+
+The flags handled by 'go test' are:
+
+	-c  Compile the test binary to test.out but do not run it.
+
+	-file a.go
+	    Use only the tests in the source file a.go.
+	    Multiple -file flags may be provided.
+
+	-p n
+	    Compile and test up to n packages in parallel.
+	    The default value is the number of CPUs available.
+
+	-x  Print each subcommand go test executes.
+
+The resulting test binary, called test.out, has its own flags:
+
+	-test.v
+	    Verbose output: log all tests as they are run.
+
+	-test.run pattern
+	    Run only those tests matching the regular expression.
+
+	-test.bench pattern
+	    Run benchmarks matching the regular expression.
+	    By default, no benchmarks run.
+
+	-test.cpuprofile cpu.out
+	    Write a CPU profile to the specified file before exiting.
+
+	-test.memprofile mem.out
+	    Write a memory profile to the specified file when all tests
+	    are complete.
+
+	-test.memprofilerate n
+	    Enable more precise (and expensive) memory profiles by setting
+	    runtime.MemProfileRate.  See 'godoc runtime MemProfileRate'.
+	    To profile all memory allocations, use -test.memprofilerate=1
+	    and set the environment variable GOGC=off to disable the
+	    garbage collector, provided the test can run in the available
+	    memory without garbage collection.
+
+	-test.parallel n
+	    Allow parallel execution of test functions that call t.Parallel.
+	    The value of this flag is the maximum number of tests to run
+	    simultaneously; by default, it is set to the value of GOMAXPROCS.
+
+	-test.short
+	    Tell long-running tests to shorten their run time.
+	    It is off by default but set during all.bash so that installing
+	    the Go tree can run a sanity check but not spend time running
+	    exhaustive tests.
+
+	-test.timeout t
+		If a test runs longer than t, panic.
+
+	-test.benchtime n
+		Run enough iterations of each benchmark to take n seconds.
+		The default is 1 second.
+
+	-test.cpu 1,2,4
+	    Specify a list of GOMAXPROCS values for which the tests or 
+	    benchmarks should be executed.  The default is the current value
+	    of GOMAXPROCS.
+
+For convenience, each of these -test.X flags of the test binary is
+also available as the flag -X in 'go test' itself.  Flags not listed
+here are passed through unaltered.  For instance, the command
+
+	go test -x -v -cpuprofile=prof.out -dir=testdata -update -file x_test.go
+
+will compile the test binary using x_test.go and then run it as
+
+	test.out -test.v -test.cpuprofile=prof.out -dir=testdata -update
+	`,
+}
+
+var helpTestfunc = &Command{
+	UsageLine: "testfunc",
+	Short:     "description of testing functions",
+	Long: `
+The 'go test' command expects to find test, benchmark, and example functions
+in the "*_test.go" files corresponding to the package under test.
+
+A test function is one named TestXXX (where XXX is any alphanumeric string
+not starting with a lower case letter) and should have the signature,
+
+	func TestXXX(t *testing.T) { ... }
+
+A benchmark function is one named BenchmarkXXX and should have the signature,
+
+	func BenchmarkXXX(b *testing.B) { ... }
+
+An example function is similar to a test function but, instead of using *testing.T
+to report success or failure, prints output to os.Stdout and os.Stderr.
+That output is compared against the function's doc comment.
+An example without a doc comment is compiled but not executed.
+
+Godoc displays the body of ExampleXXX to demonstrate the use
+of the function, constant, or variable XXX.  An example of a method M with
+receiver type T or *T is named ExampleT_M.  There may be multiple examples
+for a given function, constant, or variable, distinguished by a trailing _xxx,
+where xxx is a suffix not beginning with an upper case letter.
+
+Here is an example of an example:
+
+	// The output of this example function.
+	func ExamplePrintln() {
+		Println("The output of this example function.")
+	}
+
+See the documentation of the testing package for more information.
+		`,
+}
+
+var (
+	testC        bool     // -c flag
+	testP        int      // -p flag
+	testX        bool     // -x flag
+	testV        bool     // -v flag
+	testFiles    []string // -file flag(s)  TODO: not respected
+	testArgs     []string
+	testShowPass bool // whether to display passing output
+	testBench    bool
+)
+
+func runTest(cmd *Command, args []string) {
+	var pkgArgs []string
+	pkgArgs, testArgs = testFlags(args)
+
+	// show test PASS output when no packages
+	// are listed (implicitly current directory: "go test")
+	// or when the -v flag has been given.
+	testShowPass = len(pkgArgs) == 0 || testV
+
+	pkgs := packagesForBuild(pkgArgs)
+	if len(pkgs) == 0 {
+		fatalf("no packages to test")
+	}
+
+	if testC && len(pkgs) != 1 {
+		fatalf("cannot use -c flag with multiple packages")
+	}
+
+	buildX = testX
+	if testP > 0 {
+		buildP = testP
+	}
+
+	var b builder
+	b.init()
+
+	var builds, runs, prints []*action
+
+	// Prepare build + run + print actions for all packages being tested.
+	for _, p := range pkgs {
+		buildTest, runTest, printTest, err := b.test(p)
+		if err != nil {
+			errorf("%s", err)
+			continue
+		}
+		builds = append(builds, buildTest)
+		runs = append(runs, runTest)
+		prints = append(prints, printTest)
+	}
+
+	// Ultimately the goal is to print the output.
+	root := &action{deps: prints}
+
+	// Force the printing of results to happen in order,
+	// one at a time.
+	for i, a := range prints {
+		if i > 0 {
+			a.deps = append(a.deps, prints[i-1])
+		}
+	}
+
+	// If we are benchmarking, force everything to
+	// happen in serial.  Could instead allow all the
+	// builds to run before any benchmarks start,
+	// but try this for now.
+	if testBench {
+		for i, a := range builds {
+			if i > 0 {
+				// Make build of test i depend on
+				// completing the run of test i-1.
+				a.deps = append(a.deps, runs[i-1])
+			}
+		}
+	}
+
+	// If we are building any out-of-date packages other
+	// than those under test, warn.
+	okBuild := map[*Package]bool{}
+	for _, p := range pkgs {
+		okBuild[p] = true
+	}
+
+	warned := false
+	for _, a := range actionList(root) {
+		if a.p != nil && a.f != nil && !okBuild[a.p] && !a.p.fake {
+			okBuild[a.p] = true // don't warn again
+			if !warned {
+				fmt.Fprintf(os.Stderr, "warning: building out-of-date packages:\n")
+				warned = true
+			}
+			fmt.Fprintf(os.Stderr, "\t%s\n", a.p.ImportPath)
+		}
+	}
+	if warned {
+		fmt.Fprintf(os.Stderr, "installing these packages with 'go install' will speed future tests.\n\n")
+	}
+
+	b.do(root)
+}
+
+func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) {
+	if len(p.info.TestGoFiles)+len(p.info.XTestGoFiles) == 0 {
+		build := &action{p: p}
+		run := &action{p: p}
+		print := &action{f: (*builder).notest, p: p, deps: []*action{build}}
+		return build, run, print, nil
+	}
+
+	// Build Package structs describing:
+	//	ptest - package + test files
+	//	pxtest - package of external test files
+	//	pmain - test.out binary
+	var ptest, pxtest, pmain *Package
+
+	// go/build does not distinguish the dependencies used
+	// by the TestGoFiles from the dependencies used by the
+	// XTestGoFiles, so we build one list and use it for both
+	// ptest and pxtest.  No harm done.
+	var imports []*Package
+	var stk importStack
+	stk.push(p.ImportPath + "_test")
+	for _, path := range p.info.TestImports {
+		p1 := loadPackage(path, &stk)
+		if p1.Error != nil {
+			return nil, nil, nil, p1.Error
+		}
+		imports = append(imports, p1)
+	}
+	stk.pop()
+
+	// The ptest package needs to be importable under the
+	// same import path that p has, but we cannot put it in
+	// the usual place in the temporary tree, because then
+	// other tests will see it as the real package.
+	// Instead we make a _test directory under the import path
+	// and then repeat the import path there.  We tell the
+	// compiler and linker to look in that _test directory first.
+	//
+	// That is, if the package under test is unicode/utf8,
+	// then the normal place to write the package archive is
+	// $WORK/unicode/utf8.a, but we write the test package archive to
+	// $WORK/unicode/utf8/_test/unicode/utf8.a.
+	// We write the external test package archive to
+	// $WORK/unicode/utf8/_test/unicode/utf8_test.a.
+	testDir := filepath.Join(b.work, filepath.FromSlash(p.ImportPath+"/_test"))
+	ptestObj := filepath.Join(testDir, filepath.FromSlash(p.ImportPath+".a"))
+	pxtestObj := filepath.Join(testDir, filepath.FromSlash(p.ImportPath+"_test.a"))
+
+	// Create the directory for the .a files.
+	ptestDir, _ := filepath.Split(ptestObj)
+	if err := b.mkdir(ptestDir); err != nil {
+		return nil, nil, nil, err
+	}
+	if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), p); err != nil {
+		return nil, nil, nil, err
+	}
+
+	// Test package.
+	if len(p.info.TestGoFiles) > 0 {
+		ptest = new(Package)
+		*ptest = *p
+		ptest.GoFiles = nil
+		ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
+		ptest.GoFiles = append(ptest.GoFiles, p.info.TestGoFiles...)
+		ptest.target = ""
+		ptest.Imports = stringList(p.info.Imports, p.info.TestImports)
+		ptest.imports = append(append([]*Package{}, p.imports...), imports...)
+		ptest.pkgdir = testDir
+		ptest.fake = true
+		a := b.action(modeBuild, modeBuild, ptest)
+		a.objdir = testDir + string(filepath.Separator)
+		a.objpkg = ptestObj
+		a.target = ptestObj
+		a.link = false
+	} else {
+		ptest = p
+	}
+
+	// External test package.
+	if len(p.info.XTestGoFiles) > 0 {
+		pxtest = &Package{
+			Name:       p.Name + "_test",
+			ImportPath: p.ImportPath + "_test",
+			Dir:        p.Dir,
+			GoFiles:    p.info.XTestGoFiles,
+			Imports:    p.info.TestImports,
+			t:          p.t,
+			info:       &build.DirInfo{},
+			imports:    imports,
+			pkgdir:     testDir,
+			fake:       true,
+		}
+		pxtest.imports = append(pxtest.imports, ptest)
+		a := b.action(modeBuild, modeBuild, pxtest)
+		a.objdir = testDir + string(filepath.Separator)
+		a.objpkg = pxtestObj
+		a.target = pxtestObj
+	}
+
+	// Action for building test.out.
+	pmain = &Package{
+		Name:    "main",
+		Dir:     testDir,
+		GoFiles: []string{"_testmain.go"},
+		t:       p.t,
+		info:    &build.DirInfo{},
+		imports: []*Package{ptest},
+		fake:    true,
+	}
+	if pxtest != nil {
+		pmain.imports = append(pmain.imports, pxtest)
+	}
+
+	// The generated main also imports testing and regexp.
+	stk.push("testmain")
+	ptesting := loadPackage("testing", &stk)
+	if ptesting.Error != nil {
+		return nil, nil, nil, ptesting.Error
+	}
+	pregexp := loadPackage("regexp", &stk)
+	if pregexp.Error != nil {
+		return nil, nil, nil, pregexp.Error
+	}
+	pmain.imports = append(pmain.imports, ptesting, pregexp)
+
+	a := b.action(modeBuild, modeBuild, pmain)
+	a.objdir = testDir + string(filepath.Separator)
+	a.objpkg = filepath.Join(testDir, "main.a")
+	a.target = filepath.Join(testDir, "test.out") + b.exe
+	pmainAction := a
+
+	if testC {
+		// -c flag: create action to copy binary to ./test.out.
+		runAction = &action{
+			f:      (*builder).install,
+			deps:   []*action{pmainAction},
+			p:      pmain,
+			target: "test.out" + b.exe,
+		}
+		printAction = &action{p: p, deps: []*action{runAction}} // nop
+	} else {
+		// run test
+		runAction = &action{
+			f:          (*builder).runTest,
+			deps:       []*action{pmainAction},
+			p:          p,
+			ignoreFail: true,
+		}
+		printAction = &action{
+			f:    (*builder).printTest,
+			deps: []*action{runAction},
+			p:    p,
+		}
+	}
+
+	return pmainAction, runAction, printAction, nil
+}
+
+// runTest is the action for running a test binary.
+func (b *builder) runTest(a *action) error {
+	args := stringList(a.deps[0].target, testArgs)
+	a.testOutput = new(bytes.Buffer)
+
+	if buildN || buildX {
+		b.showcmd("", "%s", strings.Join(args, " "))
+		if buildN {
+			return nil
+		}
+	}
+
+	if a.failed {
+		// We were unable to build the binary.
+		a.failed = false
+		fmt.Fprintf(a.testOutput, "FAIL\t%s [build failed]\n", a.p.ImportPath)
+		exitStatus = 1
+		return nil
+	}
+
+	cmd := exec.Command(args[0], args[1:]...)
+	cmd.Dir = a.p.Dir
+	var buf bytes.Buffer
+	cmd.Stdout = &buf
+	cmd.Stderr = &buf
+
+	t0 := time.Now()
+	err := cmd.Start()
+
+	// This is a last-ditch deadline to detect and
+	// stop wedged test binaries, to keep the builders
+	// running.
+	const deadline = 10 * time.Minute
+
+	tick := time.NewTimer(deadline)
+	if err == nil {
+		done := make(chan error)
+		go func() {
+			done <- cmd.Wait()
+		}()
+		select {
+		case err = <-done:
+			// ok
+		case <-tick.C:
+			cmd.Process.Kill()
+			err = <-done
+			fmt.Fprintf(&buf, "*** Test killed: ran too long.\n")
+		}
+		tick.Stop()
+	}
+	out := buf.Bytes()
+	t1 := time.Now()
+	t := fmt.Sprintf("%.3fs", t1.Sub(t0).Seconds())
+	if err == nil {
+		fmt.Fprintf(a.testOutput, "ok  \t%s\t%s\n", a.p.ImportPath, t)
+		if testShowPass {
+			a.testOutput.Write(out)
+		}
+		return nil
+	}
+
+	fmt.Fprintf(a.testOutput, "FAIL\t%s\t%s\n", a.p.ImportPath, t)
+	exitStatus = 1
+	if len(out) > 0 {
+		a.testOutput.Write(out)
+		// assume printing the test binary's exit status is superfluous
+	} else {
+		fmt.Fprintf(a.testOutput, "%s\n", err)
+	}
+	return nil
+}
+
+// printTest is the action for printing a test result.
+func (b *builder) printTest(a *action) error {
+	run := a.deps[0]
+	os.Stdout.Write(run.testOutput.Bytes())
+	run.testOutput = nil
+	return nil
+}
+
+// notest is the action for testing a package with no test files.
+func (b *builder) notest(a *action) error {
+	fmt.Printf("?   \t%s\t[no test files]\n", a.p.ImportPath)
+	return nil
+}
+
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+	if !strings.HasPrefix(name, prefix) {
+		return false
+	}
+	if len(name) == len(prefix) { // "Test" is ok
+		return true
+	}
+	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
+	return !unicode.IsLower(rune)
+}
+
+// writeTestmain writes the _testmain.go file for package p to
+// the file named out.
+func writeTestmain(out string, p *Package) error {
+	t := &testFuncs{
+		Package: p,
+		Info:    p.info,
+	}
+	for _, file := range p.info.TestGoFiles {
+		if err := t.load(filepath.Join(p.Dir, file), "_test", &t.NeedTest); err != nil {
+			return err
+		}
+	}
+	for _, file := range p.info.XTestGoFiles {
+		if err := t.load(filepath.Join(p.Dir, file), "_xtest", &t.NeedXtest); err != nil {
+			return err
+		}
+	}
+
+	f, err := os.Create(out)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	if err := testmainTmpl.Execute(f, t); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+type testFuncs struct {
+	Tests      []testFunc
+	Benchmarks []testFunc
+	Examples   []testFunc
+	Package    *Package
+	Info       *build.DirInfo
+	NeedTest   bool
+	NeedXtest  bool
+}
+
+type testFunc struct {
+	Package string // imported package name (_test or _xtest)
+	Name    string // function name
+	Output  string // output, for examples
+}
+
+var testFileSet = token.NewFileSet()
+
+func (t *testFuncs) load(filename, pkg string, seen *bool) error {
+	f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
+	if err != nil {
+		return err
+	}
+	for _, d := range f.Decls {
+		n, ok := d.(*ast.FuncDecl)
+		if !ok {
+			continue
+		}
+		if n.Recv != nil {
+			continue
+		}
+		name := n.Name.String()
+		switch {
+		case isTest(name, "Test"):
+			t.Tests = append(t.Tests, testFunc{pkg, name, ""})
+			*seen = true
+		case isTest(name, "Benchmark"):
+			t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, ""})
+			*seen = true
+		case isTest(name, "Example"):
+			output := n.Doc.Text()
+			if output == "" {
+				// Don't run examples with no output.
+				continue
+			}
+			t.Examples = append(t.Examples, testFunc{pkg, name, output})
+			*seen = true
+		}
+	}
+
+	return nil
+}
+
+var testmainTmpl = template.Must(template.New("main").Parse(`
+package main
+
+import (
+	"regexp"
+	"testing"
+
+{{if .NeedTest}}
+	_test {{.Package.ImportPath | printf "%q"}}
+{{end}}
+{{if .NeedXtest}}
+	_xtest {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
+{{end}}
+)
+
+var tests = []testing.InternalTest{
+{{range .Tests}}
+	{"{{.Name}}", {{.Package}}.{{.Name}}},
+{{end}}
+}
+
+var benchmarks = []testing.InternalBenchmark{
+{{range .Benchmarks}}
+	{"{{.Name}}", {{.Package}}.{{.Name}}},
+{{end}}
+}
+
+var examples = []testing.InternalExample{
+{{range .Examples}}
+	{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}},
+{{end}}
+}
+
+var matchPat string
+var matchRe *regexp.Regexp
+
+func matchString(pat, str string) (result bool, err error) {
+	if matchRe == nil || matchPat != pat {
+		matchPat = pat
+		matchRe, err = regexp.Compile(matchPat)
+		if err != nil {
+			return
+		}
+	}
+	return matchRe.MatchString(str), nil
+}
+
+func main() {
+	testing.Main(matchString, tests, benchmarks, examples)
+}
+
+`))
diff --git a/src/cmd/go/testflag.go b/src/cmd/go/testflag.go
new file mode 100644
index 0000000..a3cacd6
--- /dev/null
+++ b/src/cmd/go/testflag.go
@@ -0,0 +1,215 @@
+// Copyright 2011 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"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// The flag handling part of go test is large and distracting.
+// We can't use the flag package because some of the flags from
+// our command line are for us, and some are for 6.out, and
+// some are for both.
+
+var usageMessage = `Usage of go test:
+  -c=false: compile but do not run the test binary
+  -file=file_test.go: specify file to use for tests;
+      use multiple times for multiple files
+  -p=n: build and test up to n packages in parallel
+  -x=false: print command lines as they are executed
+
+  // These flags can be passed with or without a "test." prefix: -v or -test.v.
+  -bench="": passes -test.bench to test
+  -benchtime=1: passes -test.benchtime to test
+  -cpu="": passes -test.cpu to test
+  -cpuprofile="": passes -test.cpuprofile to test
+  -memprofile="": passes -test.memprofile to test
+  -memprofilerate=0: passes -test.memprofilerate to test
+  -parallel=0: passes -test.parallel to test
+  -run="": passes -test.run to test
+  -short=false: passes -test.short to test
+  -timeout=0: passes -test.timeout to test
+  -v=false: passes -test.v to test
+`
+
+// usage prints a usage message and exits.
+func testUsage() {
+	fmt.Fprint(os.Stderr, usageMessage)
+	exitStatus = 2
+	exit()
+}
+
+// testFlagSpec defines a flag we know about.
+type testFlagSpec struct {
+	name       string
+	isBool     bool
+	passToTest bool // pass to Test
+	multiOK    bool // OK to have multiple instances
+	present    bool // flag has been seen
+}
+
+// testFlagDefn is the set of flags we process.
+var testFlagDefn = []*testFlagSpec{
+	// local.
+	{name: "c", isBool: true},
+	{name: "file", multiOK: true},
+	{name: "p"},
+	{name: "x", isBool: true},
+
+	// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
+	{name: "bench", passToTest: true},
+	{name: "benchtime", passToTest: true},
+	{name: "cpu", passToTest: true},
+	{name: "cpuprofile", passToTest: true},
+	{name: "memprofile", passToTest: true},
+	{name: "memprofilerate", passToTest: true},
+	{name: "parallel", passToTest: true},
+	{name: "run", passToTest: true},
+	{name: "short", isBool: true, passToTest: true},
+	{name: "timeout", passToTest: true},
+	{name: "v", isBool: true, passToTest: true},
+}
+
+// testFlags processes the command line, grabbing -x and -c, rewriting known flags
+// to have "test" before them, and reading the command line for the 6.out.
+// Unfortunately for us, we need to do our own flag processing because go test
+// grabs some flags but otherwise its command line is just a holding place for
+// test.out's arguments.
+// We allow known flags both before and after the package name list,
+// to allow both
+//	go test fmt -custom-flag-for-fmt-test
+//	go test -x math
+func testFlags(args []string) (packageNames, passToTest []string) {
+	inPkg := false
+	for i := 0; i < len(args); i++ {
+		if !strings.HasPrefix(args[i], "-") {
+			if !inPkg && packageNames == nil {
+				// First package name we've seen.
+				inPkg = true
+			}
+			if inPkg {
+				packageNames = append(packageNames, args[i])
+				continue
+			}
+		}
+
+		if inPkg {
+			// Found an argument beginning with "-"; end of package list.
+			inPkg = false
+		}
+
+		f, value, extraWord := testFlag(args, i)
+		if f == nil {
+			// This is a flag we do not know; we must assume
+			// that any args we see after this might be flag 
+			// arguments, not package names.
+			inPkg = false
+			if packageNames == nil {
+				// make non-nil: we have seen the empty package list
+				packageNames = []string{}
+			}
+			passToTest = append(passToTest, args[i])
+			continue
+		}
+		switch f.name {
+		case "c":
+			setBoolFlag(&testC, value)
+		case "p":
+			setIntFlag(&testP, value)
+		case "x":
+			setBoolFlag(&testX, value)
+		case "v":
+			setBoolFlag(&testV, value)
+		case "file":
+			testFiles = append(testFiles, value)
+		case "bench":
+			// record that we saw the flag; don't care about the value
+			testBench = true
+		}
+		if extraWord {
+			i++
+		}
+		if f.passToTest {
+			passToTest = append(passToTest, "-test."+f.name+"="+value)
+		}
+	}
+	return
+}
+
+// testFlag sees if argument i is a known flag and returns its definition, value, and whether it consumed an extra word.
+func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool) {
+	arg := args[i]
+	if strings.HasPrefix(arg, "--") { // reduce two minuses to one
+		arg = arg[1:]
+	}
+	switch arg {
+	case "-?", "-h", "-help":
+		usage()
+	}
+	if arg == "" || arg[0] != '-' {
+		return
+	}
+	name := arg[1:]
+	// If there's already "test.", drop it for now.
+	if strings.HasPrefix(name, "test.") {
+		name = name[5:]
+	}
+	equals := strings.Index(name, "=")
+	if equals >= 0 {
+		value = name[equals+1:]
+		name = name[:equals]
+	}
+	for _, f = range testFlagDefn {
+		if name == f.name {
+			// Booleans are special because they have modes -x, -x=true, -x=false.
+			if f.isBool {
+				if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag
+					value = "true"
+				} else {
+					// verify it parses
+					setBoolFlag(new(bool), value)
+				}
+			} else { // Non-booleans must have a value.
+				extra = equals < 0
+				if extra {
+					if i+1 >= len(args) {
+						usage()
+					}
+					value = args[i+1]
+				}
+			}
+			if f.present && !f.multiOK {
+				usage()
+			}
+			f.present = true
+			return
+		}
+	}
+	f = nil
+	return
+}
+
+// setBoolFlag sets the addressed boolean to the value.
+func setBoolFlag(flag *bool, value string) {
+	x, err := strconv.ParseBool(value)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "go test: illegal bool flag value %s\n", value)
+		usage()
+	}
+	*flag = x
+}
+
+// setIntFlag sets the addressed integer to the value.
+func setIntFlag(flag *int, value string) {
+	x, err := strconv.Atoi(value)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "go test: illegal int flag value %s\n", value)
+		usage()
+	}
+	*flag = x
+}
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
new file mode 100644
index 0000000..da35048
--- /dev/null
+++ b/src/cmd/go/vcs.go
@@ -0,0 +1,425 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"os"
+	"os/exec"
+	"regexp"
+	"strings"
+)
+
+// A vcsCmd describes how to use a version control system
+// like Mercurial, Git, or Subversion.
+type vcsCmd struct {
+	name string
+	cmd  string // name of binary to invoke command
+
+	createCmd   string // command to download a fresh copy of a repository
+	downloadCmd string // command to download updates into an existing repository
+
+	tagCmd     []tagCmd // commands to list tags
+	tagDefault string   // default tag to use
+	tagSyncCmd string   // command to sync to specific tag
+}
+
+// A tagCmd describes a command to list available tags
+// that can be passed to tagSyncCmd.
+type tagCmd struct {
+	cmd     string // command to list tags
+	pattern string // regexp to extract tags from list
+}
+
+// vcsList lists the known version control systems
+var vcsList = []*vcsCmd{
+	vcsHg,
+	vcsGit,
+	vcsSvn,
+	vcsBzr,
+}
+
+// vcsByCmd returns the version control system for the given
+// command name (hg, git, svn, bzr).
+func vcsByCmd(cmd string) *vcsCmd {
+	for _, vcs := range vcsList {
+		if vcs.cmd == cmd {
+			return vcs
+		}
+	}
+	return nil
+}
+
+// vcsHg describes how to use Mercurial.
+var vcsHg = &vcsCmd{
+	name: "Mercurial",
+	cmd:  "hg",
+
+	createCmd:   "clone -U {repo} {dir}",
+	downloadCmd: "pull",
+
+	// We allow both tag and branch names as 'tags'
+	// for selecting a version.  This lets people have
+	// a go.release.r60 branch and a go.1 branch
+	// and make changes in both, without constantly
+	// editing .hgtags.
+	tagCmd: []tagCmd{
+		{"tags", `^(\S+)`},
+		{"branches", `^(\S+)`},
+	},
+	tagDefault: "default",
+	tagSyncCmd: "update -r {tag}",
+}
+
+// vcsGit describes how to use Git.
+var vcsGit = &vcsCmd{
+	name: "Git",
+	cmd:  "git",
+
+	createCmd:   "clone {repo} {dir}",
+	downloadCmd: "fetch",
+
+	tagCmd:     []tagCmd{{"tag", `^(\S+)$`}},
+	tagDefault: "master",
+	tagSyncCmd: "checkout {tag}",
+}
+
+// vcsBzr describes how to use Bazaar.
+var vcsBzr = &vcsCmd{
+	name: "Bazaar",
+	cmd:  "bzr",
+
+	createCmd: "branch {repo} {dir}",
+
+	// Without --overwrite bzr will not pull tags that changed.
+	// Replace by --overwrite-tags after http://pad.lv/681792 goes in.
+	downloadCmd: "pull --overwrite",
+
+	tagCmd:     []tagCmd{{"tags", `^(\S+)`}},
+	tagDefault: "revno:-1",
+	tagSyncCmd: "update -r {tag}",
+}
+
+// vcsSvn describes how to use Subversion.
+var vcsSvn = &vcsCmd{
+	name: "Subversion",
+	cmd:  "svn",
+
+	createCmd:   "checkout {repo} {dir}",
+	downloadCmd: "update",
+
+	// There is no tag command in subversion.
+	// The branch information is all in the path names.
+}
+
+func (v *vcsCmd) String() string {
+	return v.name
+}
+
+// run runs the command line cmd in the given directory.
+// keyval is a list of key, value pairs.  run expands
+// instances of {key} in cmd into value, but only after
+// splitting cmd into individual arguments.
+// If an error occurs, run prints the command line and the
+// command's combined stdout+stderr to standard error.
+// Otherwise run discards the command's output.
+func (v *vcsCmd) run(dir string, cmd string, keyval ...string) error {
+	_, err := v.run1(dir, false, cmd, keyval)
+	return err
+}
+
+// runOutput is like run but returns the output of the command.
+func (v *vcsCmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) {
+	return v.run1(dir, true, cmd, keyval)
+}
+
+// run1 is the generalized implementation of run and runOutput.
+func (v *vcsCmd) run1(dir string, output bool, cmdline string, keyval []string) ([]byte, error) {
+	m := make(map[string]string)
+	for i := 0; i < len(keyval); i += 2 {
+		m[keyval[i]] = keyval[i+1]
+	}
+	args := strings.Fields(cmdline)
+	for i, arg := range args {
+		args[i] = expand(m, arg)
+	}
+
+	cmd := exec.Command(v.cmd, args...)
+	cmd.Dir = dir
+	if buildX {
+		fmt.Printf("cd %s\n", dir)
+		fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))
+	}
+	var buf bytes.Buffer
+	cmd.Stdout = &buf
+	cmd.Stderr = &buf
+	out := buf.Bytes()
+	err := cmd.Run()
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
+		os.Stderr.Write(out)
+		return nil, err
+	}
+	return out, nil
+}
+
+// create creates a new copy of repo in dir.
+// The parent of dir must exist; dir must not.
+func (v *vcsCmd) create(dir, repo string) error {
+	return v.run(".", v.createCmd, "dir", dir, "repo", repo)
+}
+
+// download downloads any new changes for the repo in dir.
+func (v *vcsCmd) download(dir string) error {
+	return v.run(dir, v.downloadCmd)
+}
+
+// tags returns the list of available tags for the repo in dir.
+func (v *vcsCmd) tags(dir string) ([]string, error) {
+	var tags []string
+	for _, tc := range v.tagCmd {
+		out, err := v.runOutput(dir, tc.cmd)
+		if err != nil {
+			return nil, err
+		}
+		re := regexp.MustCompile(`(?m-s)` + tc.pattern)
+		tags = append(tags, re.FindAllString(string(out), -1)...)
+	}
+	return tags, nil
+}
+
+// tagSync syncs the repo in dir to the named tag,
+// which either is a tag returned by tags or is v.tagDefault.
+func (v *vcsCmd) tagSync(dir, tag string) error {
+	if v.tagSyncCmd == "" {
+		return nil
+	}
+	return v.run(dir, v.tagSyncCmd, "tag", tag)
+}
+
+// A vcsPath describes how to convert an import path into a
+// version control system and repository name.
+type vcsPath struct {
+	prefix string                              // prefix this description applies to
+	re     string                              // pattern for import path
+	repo   string                              // repository to use (expand with match of re)
+	vcs    string                              // version control system to use (expand with match of re)
+	check  func(match map[string]string) error // additional checks
+
+	regexp *regexp.Regexp // cached compiled form of re
+}
+
+// vcsForImportPath analyzes importPath to determine the
+// version control system, and code repository to use.
+// On return, repo is the repository URL and root is the
+// import path corresponding to the root of the repository
+// (thus root is a prefix of importPath).
+func vcsForImportPath(importPath string) (vcs *vcsCmd, repo, root string, err error) {
+	for _, srv := range vcsPaths {
+		if !strings.HasPrefix(importPath, srv.prefix) {
+			continue
+		}
+		m := srv.regexp.FindStringSubmatch(importPath)
+		if m == nil {
+			if srv.prefix != "" {
+				return nil, "", "", fmt.Errorf("invalid %s import path %q", srv.prefix, importPath)
+			}
+			continue
+		}
+
+		// Build map of named subexpression matches for expand.
+		match := map[string]string{
+			"prefix": srv.prefix,
+			"import": importPath,
+		}
+		for i, name := range srv.regexp.SubexpNames() {
+			if name != "" && match[name] == "" {
+				match[name] = m[i]
+			}
+		}
+		if srv.vcs != "" {
+			match["vcs"] = expand(match, srv.vcs)
+		}
+		if srv.repo != "" {
+			match["repo"] = expand(match, srv.repo)
+		}
+		if srv.check != nil {
+			if err := srv.check(match); err != nil {
+				return nil, "", "", err
+			}
+		}
+		vcs := vcsByCmd(match["vcs"])
+		if vcs == nil {
+			return nil, "", "", fmt.Errorf("unknown version control system %q", match["vcs"])
+		}
+		return vcs, match["repo"], match["root"], nil
+	}
+	return nil, "", "", fmt.Errorf("unrecognized import path %q", importPath)
+}
+
+// expand rewrites s to replace {k} with match[k] for each key k in match.
+func expand(match map[string]string, s string) string {
+	for k, v := range match {
+		s = strings.Replace(s, "{"+k+"}", v, -1)
+	}
+	return s
+}
+
+// vcsPaths lists the known vcs paths.
+var vcsPaths = []*vcsPath{
+	// Google Code - new syntax
+	{
+		prefix: "code.google.com/",
+		re:     `^(?P<root>code\.google\.com/p/(?P<project>[a-z0-9\-]+)(\.(?P<subrepo>[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
+		repo:   "https://{root}",
+		check:  googleCodeVCS,
+	},
+
+	// Google Code - old syntax
+	{
+		re:    `^(?P<project>[a-z0-9_\-.]+)\.googlecode\.com/(git|hg|svn)(?P<path>/.*)?$`,
+		check: oldGoogleCode,
+	},
+
+	// Github
+	{
+		prefix: "github.com/",
+		re:     `^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
+		vcs:    "git",
+		repo:   "https://{root}",
+		check:  noVCSSuffix,
+	},
+
+	// Bitbucket
+	{
+		prefix: "bitbucket.org/",
+		re:     `^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+		repo:   "https://{root}",
+		check:  bitbucketVCS,
+	},
+
+	// Launchpad
+	{
+		prefix: "launchpad.net/",
+		re:     `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+		vcs:    "bzr",
+		repo:   "https://{root}",
+		check:  launchpadVCS,
+	},
+
+	// General syntax for any server.
+	{
+		re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
+	},
+}
+
+func init() {
+	// fill in cached regexps.
+	// Doing this eagerly discovers invalid regexp syntax
+	// without having to run a command that needs that regexp.
+	for _, srv := range vcsPaths {
+		srv.regexp = regexp.MustCompile(srv.re)
+	}
+}
+
+// noVCSSuffix checks that the repository name does not
+// end in .foo for any version control system foo.
+// The usual culprit is ".git".
+func noVCSSuffix(match map[string]string) error {
+	repo := match["repo"]
+	for _, vcs := range vcsList {
+		if strings.HasSuffix(repo, "."+vcs.cmd) {
+			return fmt.Errorf("invalid version control suffix in %s path", match["prefix"])
+		}
+	}
+	return nil
+}
+
+var googleCheckout = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
+
+// googleCodeVCS determines the version control system for
+// a code.google.com repository, by scraping the project's
+// /source/checkout page.
+func googleCodeVCS(match map[string]string) error {
+	if err := noVCSSuffix(match); err != nil {
+		return err
+	}
+	data, err := httpGET(expand(match, "https://code.google.com/p/{project}/source/checkout?repo={subrepo}"))
+	if err != nil {
+		return err
+	}
+
+	if m := googleCheckout.FindSubmatch(data); m != nil {
+		if vcs := vcsByCmd(string(m[1])); vcs != nil {
+			// Subversion requires the old URLs.
+			// TODO: Test.
+			if vcs == vcsSvn {
+				if match["subrepo"] != "" {
+					return fmt.Errorf("sub-repositories not supported in Google Code Subversion projects")
+				}
+				match["repo"] = expand(match, "https://{project}.googlecode.com/svn")
+			}
+			match["vcs"] = vcs.cmd
+			return nil
+		}
+	}
+
+	return fmt.Errorf("unable to detect version control system for code.google.com/ path")
+}
+
+// oldGoogleCode is invoked for old-style foo.googlecode.com paths.
+// It prints an error giving the equivalent new path.
+func oldGoogleCode(match map[string]string) error {
+	return fmt.Errorf("invalid Google Code import path: use %s instead",
+		expand(match, "code.google.com/p/{project}{path}"))
+}
+
+// bitbucketVCS determines the version control system for a
+// BitBucket repository, by using the BitBucket API.
+func bitbucketVCS(match map[string]string) error {
+	if err := noVCSSuffix(match); err != nil {
+		return err
+	}
+
+	var resp struct {
+		SCM string `json:"scm"`
+	}
+	url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}")
+	data, err := httpGET(url)
+	if err != nil {
+		return err
+	}
+	if err := json.Unmarshal(data, &resp); err != nil {
+		return fmt.Errorf("decoding %s: %v", url, err)
+	}
+
+	if vcsByCmd(resp.SCM) != nil {
+		match["vcs"] = resp.SCM
+		if resp.SCM == "git" {
+			match["repo"] += ".git"
+		}
+		return nil
+	}
+
+	return fmt.Errorf("unable to detect version control system for bitbucket.org/ path")
+}
+
+// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case,
+// "foo" could be a series name registered in Launchpad with its own branch,
+// and it could also be the name of a directory within the main project
+// branch one level up.
+func launchpadVCS(match map[string]string) error {
+	if match["project"] == "" || match["series"] == "" {
+		return nil
+	}
+	_, err := httpGET(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format"))
+	if err != nil {
+		match["root"] = expand(match, "launchpad.net/{project}")
+		match["repo"] = expand(match, "https://{root}")
+	}
+	return nil
+}
diff --git a/src/cmd/go/version.go b/src/cmd/go/version.go
new file mode 100644
index 0000000..09e2f16
--- /dev/null
+++ b/src/cmd/go/version.go
@@ -0,0 +1,25 @@
+// Copyright 2011 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"
+	"runtime"
+)
+
+var cmdVersion = &Command{
+	Run:       runVersion,
+	UsageLine: "version",
+	Short:     "print Go version",
+	Long:      `Version prints the Go version, as reported by runtime.Version.`,
+}
+
+func runVersion(cmd *Command, args []string) {
+	if len(args) != 0 {
+		cmd.Usage()
+	}
+
+	fmt.Printf("go version %s\n", runtime.Version())
+}
diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go
new file mode 100644
index 0000000..52c3200
--- /dev/null
+++ b/src/cmd/go/vet.go
@@ -0,0 +1,30 @@
+// Copyright 2011 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
+
+var cmdVet = &Command{
+	Run:       runVet,
+	UsageLine: "vet [importpath...]",
+	Short:     "run govet on packages",
+	Long: `
+Vet runs the govet command on the packages named by the import paths.
+
+For more about govet, see 'godoc govet'.
+For more about import paths, see 'go help importpath'.
+
+To run govet with specific options, run govet itself.
+
+See also: go fmt, go fix.
+	`,
+}
+
+func runVet(cmd *Command, args []string) {
+	for _, pkg := range packages(args) {
+		// Use pkg.gofiles instead of pkg.Dir so that
+		// the command only applies to this package,
+		// not to packages in subdirectories.
+		run("govet", relPaths(pkg.gofiles))
+	}
+}
diff --git a/src/cmd/goapi/goapi.go b/src/cmd/goapi/goapi.go
new file mode 100644
index 0000000..a64edca
--- /dev/null
+++ b/src/cmd/goapi/goapi.go
@@ -0,0 +1,722 @@
+// Copyright 2011 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.
+
+// Goapi computes the exported API of a set of Go packages.
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/doc"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"sort"
+	"strings"
+)
+
+// Flags
+var (
+	checkFile = flag.String("c", "", "optional filename to check API against")
+	verbose   = flag.Bool("v", false, "Verbose debugging")
+)
+
+func main() {
+	flag.Parse()
+
+	var pkgs []string
+	if flag.NArg() > 0 {
+		pkgs = flag.Args()
+	} else {
+		stds, err := exec.Command("go", "list", "std").Output()
+		if err != nil {
+			log.Fatal(err)
+		}
+		pkgs = strings.Fields(string(stds))
+	}
+
+	w := NewWalker()
+	tree, _, err := build.FindTree("os") // some known package
+	if err != nil {
+		log.Fatalf("failed to find tree: %v", err)
+	}
+
+	for _, pkg := range pkgs {
+		if strings.HasPrefix(pkg, "cmd/") ||
+			strings.HasPrefix(pkg, "exp/") ||
+			strings.HasPrefix(pkg, "old/") {
+			continue
+		}
+		if !tree.HasSrc(pkg) {
+			log.Fatalf("no source in tree for package %q", pkg)
+		}
+		pkgSrcDir := filepath.Join(tree.SrcDir(), filepath.FromSlash(pkg))
+		w.WalkPackage(pkg, pkgSrcDir)
+	}
+
+	bw := bufio.NewWriter(os.Stdout)
+	defer bw.Flush()
+
+	if *checkFile != "" {
+		bs, err := ioutil.ReadFile(*checkFile)
+		if err != nil {
+			log.Fatalf("Error reading file %s: %v", *checkFile, err)
+		}
+		v1 := strings.Split(string(bs), "\n")
+		sort.Strings(v1)
+		v2 := w.Features()
+		take := func(sl *[]string) string {
+			s := (*sl)[0]
+			*sl = (*sl)[1:]
+			return s
+		}
+		for len(v1) > 0 || len(v2) > 0 {
+			switch {
+			case len(v2) == 0 || v1[0] < v2[0]:
+				fmt.Fprintf(bw, "-%s\n", take(&v1))
+			case len(v1) == 0 || v1[0] > v2[0]:
+				fmt.Fprintf(bw, "+%s\n", take(&v2))
+			default:
+				take(&v1)
+				take(&v2)
+			}
+		}
+	} else {
+		for _, f := range w.Features() {
+			fmt.Fprintf(bw, "%s\n", f)
+		}
+	}
+}
+
+type Walker struct {
+	fset           *token.FileSet
+	scope          []string
+	features       map[string]bool // set
+	lastConstType  string
+	curPackageName string
+	curPackage     *ast.Package
+	prevConstType  map[string]string // identifer -> "ideal-int"
+}
+
+func NewWalker() *Walker {
+	return &Walker{
+		fset:     token.NewFileSet(),
+		features: make(map[string]bool),
+	}
+}
+
+// hardCodedConstantType is a hack until the type checker is sufficient for our needs.
+// Rather than litter the code with unnecessary type annotations, we'll hard-code
+// the cases we can't handle yet.
+func (w *Walker) hardCodedConstantType(name string) (typ string, ok bool) {
+	switch w.scope[0] {
+	case "pkg compress/gzip", "pkg compress/zlib":
+		switch name {
+		case "NoCompression", "BestSpeed", "BestCompression", "DefaultCompression":
+			return "ideal-int", true
+		}
+	case "pkg os":
+		switch name {
+		case "WNOHANG", "WSTOPPED", "WUNTRACED":
+			return "ideal-int", true
+		}
+	case "pkg path/filepath":
+		switch name {
+		case "Separator", "ListSeparator":
+			return "char", true
+		}
+	case "pkg unicode/utf8":
+		switch name {
+		case "RuneError":
+			return "char", true
+		}
+	case "pkg text/scanner":
+		// TODO: currently this tool only resolves const types
+		// that reference other constant types if they appear
+		// in the right order.  the scanner package has
+		// ScanIdents and such coming before the Ident/Int/etc
+		// tokens, hence this hack.
+		if strings.HasPrefix(name, "Scan") || name == "SkipComments" {
+			return "ideal-int", true
+		}
+	}
+	return "", false
+}
+
+func (w *Walker) Features() (fs []string) {
+	for f := range w.features {
+		fs = append(fs, f)
+	}
+	sort.Strings(fs)
+	return
+}
+
+func (w *Walker) WalkPackage(name, dir string) {
+	log.Printf("package %s", name)
+	pop := w.pushScope("pkg " + name)
+	defer pop()
+
+	info, err := build.ScanDir(dir)
+	if err != nil {
+		log.Fatalf("pkg %q, dir %q: ScanDir: %v", name, dir, err)
+	}
+
+	apkg := &ast.Package{
+		Files: make(map[string]*ast.File),
+	}
+
+	files := append(append([]string{}, info.GoFiles...), info.CgoFiles...)
+	for _, file := range files {
+		f, err := parser.ParseFile(w.fset, filepath.Join(dir, file), nil, 0)
+		if err != nil {
+			log.Fatalf("error parsing package %s, file %s: %v", name, file, err)
+		}
+		apkg.Files[file] = f
+	}
+
+	w.curPackageName = name
+	w.curPackage = apkg
+	w.prevConstType = map[string]string{}
+	for name, afile := range apkg.Files {
+		w.walkFile(filepath.Join(dir, name), afile)
+	}
+
+	// Now that we're done walking types, vars and consts
+	// in the *ast.Package, use go/doc to do the rest
+	// (functions and methods). This is done here because
+	// go/doc is destructive.  We can't use the
+	// *ast.Package after this.
+	dpkg := doc.New(apkg, name, 0)
+
+	for _, t := range dpkg.Types {
+		// Move funcs up to the top-level, not hiding in the Types.
+		dpkg.Funcs = append(dpkg.Funcs, t.Funcs...)
+
+		for _, m := range t.Methods {
+			w.walkFuncDecl(m.Decl)
+		}
+	}
+
+	for _, f := range dpkg.Funcs {
+		w.walkFuncDecl(f.Decl)
+	}
+}
+
+// pushScope enters a new scope (walking a package, type, node, etc)
+// and returns a function that will leave the scope (with sanity checking
+// for mismatched pushes & pops)
+func (w *Walker) pushScope(name string) (popFunc func()) {
+	w.scope = append(w.scope, name)
+	return func() {
+		if len(w.scope) == 0 {
+			log.Fatalf("attempt to leave scope %q with empty scope list", name)
+		}
+		if w.scope[len(w.scope)-1] != name {
+			log.Fatalf("attempt to leave scope %q, but scope is currently %#v", name, w.scope)
+		}
+		w.scope = w.scope[:len(w.scope)-1]
+	}
+}
+
+func (w *Walker) walkFile(name string, file *ast.File) {
+	// Not entering a scope here; file boundaries aren't interesting.
+
+	for _, di := range file.Decls {
+		switch d := di.(type) {
+		case *ast.GenDecl:
+			switch d.Tok {
+			case token.IMPORT:
+				continue
+			case token.CONST:
+				for _, sp := range d.Specs {
+					w.walkConst(sp.(*ast.ValueSpec))
+				}
+			case token.TYPE:
+				for _, sp := range d.Specs {
+					w.walkTypeSpec(sp.(*ast.TypeSpec))
+				}
+			case token.VAR:
+				for _, sp := range d.Specs {
+					w.walkVar(sp.(*ast.ValueSpec))
+				}
+			default:
+				log.Fatalf("unknown token type %d in GenDecl", d.Tok)
+			}
+		case *ast.FuncDecl:
+			// Ignore. Handled in subsequent pass, by go/doc.
+		default:
+			log.Printf("unhandled %T, %#v\n", di, di)
+			printer.Fprint(os.Stderr, w.fset, di)
+			os.Stderr.Write([]byte("\n"))
+		}
+	}
+}
+
+var constType = map[token.Token]string{
+	token.INT:    "ideal-int",
+	token.FLOAT:  "ideal-float",
+	token.STRING: "ideal-string",
+	token.CHAR:   "ideal-char",
+	token.IMAG:   "ideal-imag",
+}
+
+var varType = map[token.Token]string{
+	token.INT:    "int",
+	token.FLOAT:  "float64",
+	token.STRING: "string",
+	token.CHAR:   "rune",
+	token.IMAG:   "complex128",
+}
+
+var errTODO = errors.New("TODO")
+
+func (w *Walker) constValueType(vi interface{}) (string, error) {
+	switch v := vi.(type) {
+	case *ast.BasicLit:
+		litType, ok := constType[v.Kind]
+		if !ok {
+			return "", fmt.Errorf("unknown basic literal kind %#v", v)
+		}
+		return litType, nil
+	case *ast.UnaryExpr:
+		return w.constValueType(v.X)
+	case *ast.SelectorExpr:
+		// e.g. compress/gzip's BestSpeed == flate.BestSpeed
+		return "", errTODO
+	case *ast.Ident:
+		if v.Name == "iota" {
+			return "ideal-int", nil // hack.
+		}
+		if v.Name == "false" || v.Name == "true" {
+			return "ideal-bool", nil
+		}
+		if v.Name == "intSize" && w.curPackageName == "strconv" {
+			// Hack.
+			return "ideal-int", nil
+		}
+		if t, ok := w.prevConstType[v.Name]; ok {
+			return t, nil
+		}
+		return "", fmt.Errorf("can't resolve existing constant %q", v.Name)
+	case *ast.BinaryExpr:
+		left, err := w.constValueType(v.X)
+		if err != nil {
+			return "", err
+		}
+		right, err := w.constValueType(v.Y)
+		if err != nil {
+			return "", err
+		}
+		if left != right {
+			if left == "ideal-int" && right == "ideal-float" {
+				return "ideal-float", nil // math.Log2E
+			}
+			if left == "ideal-char" && right == "ideal-int" {
+				return "ideal-int", nil // math/big.MaxBase
+			}
+			if left == "ideal-int" && right == "ideal-char" {
+				return "ideal-int", nil // text/scanner.GoWhitespace
+			}
+			if left == "ideal-int" && right == "Duration" {
+				// Hack, for package time.
+				return "Duration", nil
+			}
+			return "", fmt.Errorf("in BinaryExpr, unhandled type mismatch; left=%q, right=%q", left, right)
+		}
+		return left, nil
+	case *ast.CallExpr:
+		// Not a call, but a type conversion.
+		return w.nodeString(v.Fun), nil
+	case *ast.ParenExpr:
+		return w.constValueType(v.X)
+	}
+	return "", fmt.Errorf("unknown const value type %T", vi)
+}
+
+func (w *Walker) varValueType(vi interface{}) (string, error) {
+	valStr := w.nodeString(vi)
+	if strings.HasPrefix(valStr, "errors.New(") {
+		return "error", nil
+	}
+
+	switch v := vi.(type) {
+	case *ast.BasicLit:
+		litType, ok := varType[v.Kind]
+		if !ok {
+			return "", fmt.Errorf("unknown basic literal kind %#v", v)
+		}
+		return litType, nil
+	case *ast.CompositeLit:
+		return w.nodeString(v.Type), nil
+	case *ast.FuncLit:
+		return w.nodeString(w.namelessType(v.Type)), nil
+	case *ast.UnaryExpr:
+		if v.Op == token.AND {
+			typ, err := w.varValueType(v.X)
+			return "*" + typ, err
+		}
+		return "", fmt.Errorf("unknown unary expr: %#v", v)
+	case *ast.SelectorExpr:
+		return "", errTODO
+	case *ast.Ident:
+		node, _, ok := w.resolveName(v.Name)
+		if !ok {
+			return "", fmt.Errorf("unresolved identifier: %q", v.Name)
+		}
+		return w.varValueType(node)
+	case *ast.BinaryExpr:
+		left, err := w.varValueType(v.X)
+		if err != nil {
+			return "", err
+		}
+		right, err := w.varValueType(v.Y)
+		if err != nil {
+			return "", err
+		}
+		if left != right {
+			return "", fmt.Errorf("in BinaryExpr, unhandled type mismatch; left=%q, right=%q", left, right)
+		}
+		return left, nil
+	case *ast.ParenExpr:
+		return w.varValueType(v.X)
+	case *ast.CallExpr:
+		funStr := w.nodeString(v.Fun)
+		node, _, ok := w.resolveName(funStr)
+		if !ok {
+			return "", fmt.Errorf("unresolved named %q", funStr)
+		}
+		if funcd, ok := node.(*ast.FuncDecl); ok {
+			// Assume at the top level that all functions have exactly 1 result
+			return w.nodeString(w.namelessType(funcd.Type.Results.List[0].Type)), nil
+		}
+		// maybe a function call; maybe a conversion.  Need to lookup type.
+		return "", fmt.Errorf("resolved name %q to a %T: %#v", funStr, node, node)
+	default:
+		return "", fmt.Errorf("unknown const value type %T", vi)
+	}
+	panic("unreachable")
+}
+
+// resolveName finds a top-level node named name and returns the node
+// v and its type t, if known.
+func (w *Walker) resolveName(name string) (v interface{}, t interface{}, ok bool) {
+	for _, file := range w.curPackage.Files {
+		for _, di := range file.Decls {
+			switch d := di.(type) {
+			case *ast.FuncDecl:
+				if d.Name.Name == name {
+					return d, d.Type, true
+				}
+			case *ast.GenDecl:
+				switch d.Tok {
+				case token.TYPE:
+					for _, sp := range d.Specs {
+						ts := sp.(*ast.TypeSpec)
+						if ts.Name.Name == name {
+							return ts, ts.Type, true
+						}
+					}
+				case token.VAR:
+					for _, sp := range d.Specs {
+						vs := sp.(*ast.ValueSpec)
+						for i, vname := range vs.Names {
+							if vname.Name == name {
+								if len(vs.Values) > i {
+									return vs.Values[i], vs.Type, true
+								}
+								return nil, vs.Type, true
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	return nil, nil, false
+}
+
+func (w *Walker) walkConst(vs *ast.ValueSpec) {
+	for _, ident := range vs.Names {
+		if !ast.IsExported(ident.Name) {
+			continue
+		}
+		litType := ""
+		if vs.Type != nil {
+			litType = w.nodeString(vs.Type)
+		} else {
+			litType = w.lastConstType
+			if vs.Values != nil {
+				if len(vs.Values) != 1 {
+					log.Fatalf("const %q, values: %#v", ident.Name, vs.Values)
+				}
+				var err error
+				litType, err = w.constValueType(vs.Values[0])
+				if err != nil {
+					if t, ok := w.hardCodedConstantType(ident.Name); ok {
+						litType = t
+						err = nil
+					} else {
+						log.Fatalf("unknown kind in const %q (%T): %v", ident.Name, vs.Values[0], err)
+					}
+				}
+			}
+		}
+		if litType == "" {
+			log.Fatalf("unknown kind in const %q", ident.Name)
+		}
+		w.lastConstType = litType
+
+		w.emitFeature(fmt.Sprintf("const %s %s", ident, litType))
+		w.prevConstType[ident.Name] = litType
+	}
+}
+
+func (w *Walker) walkVar(vs *ast.ValueSpec) {
+	for i, ident := range vs.Names {
+		if !ast.IsExported(ident.Name) {
+			continue
+		}
+
+		typ := ""
+		if vs.Type != nil {
+			typ = w.nodeString(vs.Type)
+		} else {
+			if len(vs.Values) == 0 {
+				log.Fatalf("no values for var %q", ident.Name)
+			}
+			if len(vs.Values) > 1 {
+				log.Fatalf("more than 1 values in ValueSpec not handled, var %q", ident.Name)
+			}
+			var err error
+			typ, err = w.varValueType(vs.Values[i])
+			if err != nil {
+				log.Fatalf("unknown type of variable %q, type %T, error = %v\ncode: %s",
+					ident.Name, vs.Values[i], err, w.nodeString(vs.Values[i]))
+			}
+		}
+		w.emitFeature(fmt.Sprintf("var %s %s", ident, typ))
+	}
+}
+
+func (w *Walker) nodeString(node interface{}) string {
+	if node == nil {
+		return ""
+	}
+	var b bytes.Buffer
+	printer.Fprint(&b, w.fset, node)
+	return b.String()
+}
+
+func (w *Walker) nodeDebug(node interface{}) string {
+	if node == nil {
+		return ""
+	}
+	var b bytes.Buffer
+	ast.Fprint(&b, w.fset, node, nil)
+	return b.String()
+}
+
+func (w *Walker) walkTypeSpec(ts *ast.TypeSpec) {
+	name := ts.Name.Name
+	if !ast.IsExported(name) {
+		return
+	}
+
+	switch t := ts.Type.(type) {
+	case *ast.StructType:
+		w.walkStructType(name, t)
+	case *ast.InterfaceType:
+		w.walkInterfaceType(name, t)
+	default:
+		w.emitFeature(fmt.Sprintf("type %s %s", name, w.nodeString(ts.Type)))
+		//log.Fatalf("unknown typespec %T", ts.Type)
+	}
+}
+
+func (w *Walker) walkStructType(name string, t *ast.StructType) {
+	typeStruct := fmt.Sprintf("type %s struct", name)
+	w.emitFeature(typeStruct)
+	pop := w.pushScope(typeStruct)
+	defer pop()
+	for _, f := range t.Fields.List {
+		typ := f.Type
+		for _, name := range f.Names {
+			if ast.IsExported(name.Name) {
+				w.emitFeature(fmt.Sprintf("%s %s", name, w.nodeString(w.namelessType(typ))))
+			}
+		}
+		if f.Names == nil {
+			switch v := typ.(type) {
+			case *ast.Ident:
+				if ast.IsExported(v.Name) {
+					w.emitFeature(fmt.Sprintf("embedded %s", v.Name))
+				}
+			case *ast.StarExpr:
+				switch vv := v.X.(type) {
+				case *ast.Ident:
+					if ast.IsExported(vv.Name) {
+						w.emitFeature(fmt.Sprintf("embedded *%s", vv.Name))
+					}
+				case *ast.SelectorExpr:
+					w.emitFeature(fmt.Sprintf("embedded %s", w.nodeString(typ)))
+				default:
+					log.Fatal("unable to handle embedded starexpr before %T", typ)
+				}
+			case *ast.SelectorExpr:
+				w.emitFeature(fmt.Sprintf("embedded %s", w.nodeString(typ)))
+			default:
+				log.Fatalf("unable to handle embedded %T", typ)
+			}
+		}
+	}
+}
+
+func (w *Walker) walkInterfaceType(name string, t *ast.InterfaceType) {
+	methods := []string{}
+
+	pop := w.pushScope("type " + name + " interface")
+	for _, f := range t.Methods.List {
+		typ := f.Type
+		for _, name := range f.Names {
+			if ast.IsExported(name.Name) {
+				ft := typ.(*ast.FuncType)
+				w.emitFeature(fmt.Sprintf("%s%s", name, w.funcSigString(ft)))
+				methods = append(methods, name.Name)
+			}
+		}
+	}
+	pop()
+
+	sort.Strings(methods)
+	if len(methods) == 0 {
+		w.emitFeature(fmt.Sprintf("type %s interface {}", name))
+	} else {
+		w.emitFeature(fmt.Sprintf("type %s interface { %s }", name, strings.Join(methods, ", ")))
+	}
+}
+
+func (w *Walker) walkFuncDecl(f *ast.FuncDecl) {
+	if !ast.IsExported(f.Name.Name) {
+		return
+	}
+	if f.Recv != nil {
+		// Method.
+		recvType := w.nodeString(f.Recv.List[0].Type)
+		keep := ast.IsExported(recvType) ||
+			(strings.HasPrefix(recvType, "*") &&
+				ast.IsExported(recvType[1:]))
+		if !keep {
+			return
+		}
+		w.emitFeature(fmt.Sprintf("method (%s) %s%s", recvType, f.Name.Name, w.funcSigString(f.Type)))
+		return
+	}
+	// Else, a function
+	w.emitFeature(fmt.Sprintf("func %s%s", f.Name.Name, w.funcSigString(f.Type)))
+}
+
+func (w *Walker) funcSigString(ft *ast.FuncType) string {
+	var b bytes.Buffer
+	b.WriteByte('(')
+	if ft.Params != nil {
+		for i, f := range ft.Params.List {
+			if i > 0 {
+				b.WriteString(", ")
+			}
+			b.WriteString(w.nodeString(w.namelessType(f.Type)))
+		}
+	}
+	b.WriteByte(')')
+	if ft.Results != nil {
+		if nr := len(ft.Results.List); nr > 0 {
+			b.WriteByte(' ')
+			if nr > 1 {
+				b.WriteByte('(')
+			}
+			for i, f := range ft.Results.List {
+				if i > 0 {
+					b.WriteString(", ")
+				}
+				b.WriteString(w.nodeString(w.namelessType(f.Type)))
+			}
+			if nr > 1 {
+				b.WriteByte(')')
+			}
+		}
+	}
+	return b.String()
+}
+
+// namelessType returns a type node that lacks any variable names.
+func (w *Walker) namelessType(t interface{}) interface{} {
+	ft, ok := t.(*ast.FuncType)
+	if !ok {
+		return t
+	}
+	return &ast.FuncType{
+		Params:  w.namelessFieldList(ft.Params),
+		Results: w.namelessFieldList(ft.Results),
+	}
+}
+
+// namelessFieldList returns a deep clone of fl, with the cloned fields
+// lacking names.
+func (w *Walker) namelessFieldList(fl *ast.FieldList) *ast.FieldList {
+	fl2 := &ast.FieldList{}
+	if fl != nil {
+		for _, f := range fl.List {
+			fl2.List = append(fl2.List, w.namelessField(f))
+		}
+	}
+	return fl2
+}
+
+// namelessField clones f, but not preserving the names of fields.
+// (comments and tags are also ignored)
+func (w *Walker) namelessField(f *ast.Field) *ast.Field {
+	return &ast.Field{
+		Type: f.Type,
+	}
+}
+
+func (w *Walker) emitFeature(feature string) {
+	f := strings.Join(w.scope, ", ") + ", " + feature
+	if _, dup := w.features[f]; dup {
+		panic("duplicate feature inserted: " + f)
+	}
+
+	if strings.Contains(f, "\n") {
+		// TODO: for now, just skip over the
+		// runtime.MemStatsType.BySize type, which this tool
+		// doesn't properly handle. It's pretty low-level,
+		// though, so not super important to protect against.
+		if strings.HasPrefix(f, "pkg runtime") && strings.Contains(f, "BySize [61]struct") {
+			return
+		}
+		panic("feature contains newlines: " + f)
+	}
+	w.features[f] = true
+	if *verbose {
+		log.Printf("feature: %s", f)
+	}
+}
+
+func strListContains(l []string, s string) bool {
+	for _, v := range l {
+		if v == s {
+			return true
+		}
+	}
+	return false
+}
diff --git a/src/cmd/goapi/goapi_test.go b/src/cmd/goapi/goapi_test.go
new file mode 100644
index 0000000..1f23b1d
--- /dev/null
+++ b/src/cmd/goapi/goapi_test.go
@@ -0,0 +1,73 @@
+// Copyright 2011 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 (
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+	"testing"
+)
+
+var (
+	updateGolden = flag.Bool("updategolden", false, "update golden files")
+)
+
+func TestGolden(t *testing.T) {
+	td, err := os.Open("testdata")
+	if err != nil {
+		t.Fatal(err)
+	}
+	fis, err := td.Readdir(0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, fi := range fis {
+		if !fi.IsDir() {
+			continue
+		}
+		w := NewWalker()
+		goldenFile := filepath.Join("testdata", fi.Name(), "golden.txt")
+
+		w.WalkPackage(fi.Name(), filepath.Join("testdata", fi.Name()))
+
+		if *updateGolden {
+			os.Remove(goldenFile)
+			f, err := os.Create(goldenFile)
+			if err != nil {
+				t.Fatal(err)
+			}
+			for _, feat := range w.Features() {
+				fmt.Fprintf(f, "%s\n", feat)
+			}
+			f.Close()
+		}
+
+		bs, err := ioutil.ReadFile(goldenFile)
+		if err != nil {
+			t.Fatalf("opening golden.txt for package %q: %v", fi.Name(), err)
+		}
+		wanted := strings.Split(string(bs), "\n")
+		sort.Strings(wanted)
+		for _, feature := range wanted {
+			if feature == "" {
+				continue
+			}
+			_, ok := w.features[feature]
+			if !ok {
+				t.Errorf("package %s: missing feature %q", fi.Name(), feature)
+			}
+			delete(w.features, feature)
+		}
+
+		for _, feature := range w.Features() {
+			t.Errorf("package %s: extra feature not in golden file: %q", fi.Name(), feature)
+		}
+	}
+}
diff --git a/src/cmd/goapi/testdata/p1/golden.txt b/src/cmd/goapi/testdata/p1/golden.txt
new file mode 100644
index 0000000..5b2aff5
--- /dev/null
+++ b/src/cmd/goapi/testdata/p1/golden.txt
@@ -0,0 +1,57 @@
+pkg p1, const A ideal-int
+pkg p1, const A64 int64
+pkg p1, const B ideal-int
+pkg p1, const ConversionConst MyInt
+pkg p1, const FloatConst ideal-float
+pkg p1, const StrConst ideal-string
+pkg p1, func Bar(int8, int16, int64)
+pkg p1, func Bar1(int8, int16, int64) uint64
+pkg p1, func Bar2(int8, int16, int64) (uint8, uint64)
+pkg p1, func TakesFunc(func(int) int)
+pkg p1, method (*B) JustOnB()
+pkg p1, method (*B) OnBothTandBPtr()
+pkg p1, method (*Embedded) OnEmbedded()
+pkg p1, method (*S2) SMethod(int8, int16, int64)
+pkg p1, method (*T) JustOnT()
+pkg p1, method (*T) OnBothTandBPtr()
+pkg p1, method (B) OnBothTandBVal()
+pkg p1, method (S) StructValueMethod()
+pkg p1, method (S) StructValueMethodNamedRecv()
+pkg p1, method (S2) StructValueMethod()
+pkg p1, method (S2) StructValueMethodNamedRecv()
+pkg p1, method (T) OnBothTandBVal()
+pkg p1, method (TPtrExported) OnEmbedded()
+pkg p1, method (TPtrUnexported) OnBothTandBPtr()
+pkg p1, method (TPtrUnexported) OnBothTandBVal()
+pkg p1, type B struct
+pkg p1, type Codec struct
+pkg p1, type Codec struct, Func func(int, int) int
+pkg p1, type EmbedSelector struct
+pkg p1, type EmbedSelector struct, embedded time.Time
+pkg p1, type EmbedURLPtr struct
+pkg p1, type EmbedURLPtr struct, embedded *url.URL
+pkg p1, type Embedded struct
+pkg p1, type I interface { Get, GetNamed, Set }
+pkg p1, type I interface, Get(string) int64
+pkg p1, type I interface, GetNamed(string) int64
+pkg p1, type I interface, Set(string, int64)
+pkg p1, type MyInt int
+pkg p1, type S struct
+pkg p1, type S struct, Public *int
+pkg p1, type S struct, PublicTime time.Time
+pkg p1, type S2 struct
+pkg p1, type S2 struct, Extra bool
+pkg p1, type S2 struct, embedded S
+pkg p1, type SI struct
+pkg p1, type SI struct, I int
+pkg p1, type T struct
+pkg p1, type TPtrExported struct
+pkg p1, type TPtrExported struct, embedded *Embedded
+pkg p1, type TPtrUnexported struct
+pkg p1, var ChecksumError error
+pkg p1, var SIPtr *SI
+pkg p1, var SIPtr2 *SI
+pkg p1, var SIVal SI
+pkg p1, var X I
+pkg p1, var X int64
+pkg p1, var Y int
diff --git a/src/cmd/goapi/testdata/p1/p1.go b/src/cmd/goapi/testdata/p1/p1.go
new file mode 100644
index 0000000..67a0ed9
--- /dev/null
+++ b/src/cmd/goapi/testdata/p1/p1.go
@@ -0,0 +1,123 @@
+package foo
+
+import (
+	"time"
+	"url"
+)
+
+const (
+	A         = 1
+	a         = 11
+	A64 int64 = 1
+)
+
+const (
+	ConversionConst = MyInt(5)
+)
+
+var ChecksumError = errors.New("gzip checksum error")
+
+const B = 2
+const StrConst = "foo"
+const FloatConst = 1.5
+
+type myInt int
+
+type MyInt int
+
+type S struct {
+	Public     *int
+	private    *int
+	PublicTime time.Time
+}
+
+type EmbedURLPtr struct {
+	*url.URL
+}
+
+type S2 struct {
+	S
+	Extra bool
+}
+
+var X int64
+
+var (
+	Y int
+	X I // todo: resolve this to foo.I? probably doesn't matter.
+)
+
+type I interface {
+	Set(name string, balance int64)
+	Get(string) int64
+	GetNamed(string) (balance int64)
+	private()
+}
+
+func (myInt) privateTypeMethod()           {}
+func (myInt) CapitalMethodUnexportedType() {}
+
+func (s *S2) SMethod(x int8, y int16, z int64) {}
+
+type s struct{}
+
+func (s) method()
+func (s) Method()
+
+func (S) StructValueMethod()
+func (ignored S) StructValueMethodNamedRecv()
+
+func (s *S2) unexported(x int8, y int16, z int64) {}
+
+func Bar(x int8, y int16, z int64)                  {}
+func Bar1(x int8, y int16, z int64) uint64          {}
+func Bar2(x int8, y int16, z int64) (uint8, uint64) {}
+
+func unexported(x int8, y int16, z int64) {}
+
+func TakesFunc(f func(dontWantName int) int)
+
+type Codec struct {
+	Func func(x int, y int) (z int)
+}
+
+type SI struct {
+	I int
+}
+
+var SIVal = SI{}
+var SIPtr = &SI{}
+var SIPtr2 *SI
+
+type T struct {
+	common
+}
+
+type B struct {
+	common
+}
+
+type common struct {
+	i int
+}
+
+type TPtrUnexported struct {
+	*common
+}
+
+type TPtrExported struct {
+	*Embedded
+}
+
+type Embedded struct{}
+
+func (*Embedded) OnEmbedded() {}
+
+func (*T) JustOnT()             {}
+func (*B) JustOnB()             {}
+func (*common) OnBothTandBPtr() {}
+func (common) OnBothTandBVal()  {}
+
+type EmbedSelector struct {
+	time.Time
+}
diff --git a/src/cmd/godefs/Makefile b/src/cmd/godefs/Makefile
deleted file mode 100644
index 77cd26c..0000000
--- a/src/cmd/godefs/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-O:=$(HOST_O)
-
-TARG=godefs
-OFILES=\
-	main.$O\
-	stabs.$O\
-	util.$O\
-
-HFILES=a.h
-
-include ../../Make.ccmd
-
-test: $(TARG)
-	./test.sh
diff --git a/src/cmd/godefs/a.h b/src/cmd/godefs/a.h
deleted file mode 100644
index 9b49574..0000000
--- a/src/cmd/godefs/a.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-enum
-{
-	Void = 1,
-	Int8,
-	Uint8,
-	Int16,
-	Uint16,
-	Int32,
-	Uint32,
-	Int64,
-	Uint64,
-	Float32,
-	Float64,
-	Ptr,
-	Struct,
-	Array,
-	Union,
-	Typedef,
-};
-
-typedef struct Field Field;
-typedef struct Type Type;
-
-struct Type
-{
-	Type *next;	// next in hash table
-
-	// stabs name and two-integer id
-	char *name;
-	int n1;
-	int n2;
-
-	// int kind
-	int kind;
-
-	// sub-type for ptr, array
-	Type *type;
-
-	// struct fields
-	Field *f;
-	int nf;
-	int size;
-
-	int saved;	// recorded in typ array
-	int warned;	// warned about needing type
-	int printed;	// has the definition been printed yet?
-};
-
-struct Field
-{
-	char *name;
-	Type *type;
-	int offset;
-	int size;
-};
-
-// Constants
-typedef struct Const Const;
-struct Const
-{
-	char *name;
-	vlong value;
-};
-
-// Recorded constants and types, to be printed.
-extern Const *con;
-extern int ncon;
-extern Type **typ;
-extern int ntyp;
-extern int kindsize[];
-
-// Language output
-typedef struct Lang Lang;
-struct Lang
-{
-	char *constbegin;
-	char *constfmt;
-	char *constend;
-
-	char *typdef;
-	char *typdefend;
-
-	char *structbegin;
-	char *unionbegin;
-	char *structpadfmt;
-	char *structend;
-
-	int (*typefmt)(Fmt*);
-};
-
-extern Lang go, c;
-
-void*	emalloc(int);
-char*	estrdup(char*);
-void*	erealloc(void*, int);
-void		parsestabtype(char*);
diff --git a/src/cmd/godefs/doc.go b/src/cmd/godefs/doc.go
deleted file mode 100644
index 365c7cf..0000000
--- a/src/cmd/godefs/doc.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-
-Godefs is a bootstrapping tool for porting the Go runtime to new systems.
-It translates C type declarations into C or Go type declarations
-with the same memory layout.
-
-Usage: godefs [-g package] [-c cc] [-f cc-arg]... [defs.c ...]
-
-Godefs takes as input a host-compilable C file that includes
-standard system headers.  From that input file, it generates
-a standalone (no #includes) C or Go file containing equivalent
-definitions.
-
-The input to godefs is a C input file that can be compiled by
-the host system's standard C compiler (typically gcc).
-This file is expected to define new types and enumerated constants
-whose names begin with $ (a legal identifier character in gcc).
-Godefs compile the given input file with the host compiler and
-then parses the debug info embedded in the assembly output.
-This is far easier than reading system headers on most machines.
-
-The output from godefs is either C output intended for the
-Plan 9 C compiler tool chain (6c, 8c, or 5c) or Go output.
-
-The options are:
-
-	-g package
-		generate Go output using the given package name.
-		In the Go output, struct fields have leading xx_ prefixes
-		removed and the first character capitalized (exported).
-
-	-c cc
-		set the name of the host system's C compiler (default "gcc")
-
-	-f cc-arg
-		add cc-arg to the command line when invoking the system C compiler
-		(for example, -f -m64 to invoke gcc -m64).
-		Repeating this option adds multiple flags to the command line.
-
-For example, if this is x.c:
-
-	#include <sys/stat.h>
-
-	typedef struct timespec $Timespec;
-	enum {
-		$S_IFMT = S_IFMT,
-		$S_IFIFO = S_IFIFO,
-		$S_IFCHR = S_IFCHR,
-	};
-
-then "godefs x.c" generates:
-
-	// godefs x.c
-	// MACHINE GENERATED - DO NOT EDIT.
-
-	// Constants
-	enum {
-		S_IFMT = 0xf000,
-		S_IFIFO = 0x1000,
-		S_IFCHR = 0x2000,
-	};
-
-	// Types
-	#pragma pack on
-
-	typedef struct Timespec Timespec;
-	struct Timespec {
-		int64 tv_sec;
-		int64 tv_nsec;
-	};
-	#pragma pack off
-
-and "godefs -g MyPackage x.c" generates:
-
-	// godefs -g MyPackage x.c
-	// MACHINE GENERATED - DO NOT EDIT.
-
-	package MyPackage
-
-	// Constants
-	const (
-		S_IFMT = 0xf000;
-		S_IFIFO = 0x1000;
-		S_IFCHR = 0x2000;
-	)
-
-	// Types
-
-	type Timespec struct {
-		Sec int64;
-		Nsec int64;
-	}
-
-*/
-package documentation
diff --git a/src/cmd/godefs/main.c b/src/cmd/godefs/main.c
deleted file mode 100644
index 38b2962..0000000
--- a/src/cmd/godefs/main.c
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Godefs takes as input a host-compilable C file that includes
-// standard system headers.  From that input file, it generates
-// a standalone (no #includes) C or Go file containing equivalent
-// definitions.
-//
-// The input C file is expected to define new types and enumerated
-// constants whose names begin with $ (a legal identifier character
-// in gcc).  The output is the standalone definitions of those names,
-// with the $ removed.
-//
-// For example, if this is x.c:
-//
-//	#include <sys/stat.h>
-//
-//	typedef struct timespec $Timespec;
-//	typedef struct stat $Stat;
-//	enum {
-//		$S_IFMT = S_IFMT,
-//		$S_IFIFO = S_IFIFO,
-//		$S_IFCHR = S_IFCHR,
-//	};
-//
-// then "godefs x.c" generates:
-//
-//	// godefs x.c
-//
-//	// MACHINE GENERATED - DO NOT EDIT.
-//
-//	// Constants
-//	enum {
-//		S_IFMT = 0xf000,
-//		S_IFIFO = 0x1000,
-//		S_IFCHR = 0x2000,
-//	};
-//
-//	// Types
-//	#pragma pack on
-//
-//	typedef struct Timespec Timespec;
-//	struct Timespec {
-//		int32 tv_sec;
-//		int32 tv_nsec;
-//	};
-//
-//	typedef struct Stat Stat;
-//	struct Stat {
-//		int32 st_dev;
-//		uint32 st_ino;
-//		uint16 st_mode;
-//		uint16 st_nlink;
-//		uint32 st_uid;
-//		uint32 st_gid;
-//		int32 st_rdev;
-//		Timespec st_atimespec;
-//		Timespec st_mtimespec;
-//		Timespec st_ctimespec;
-//		int64 st_size;
-//		int64 st_blocks;
-//		int32 st_blksize;
-//		uint32 st_flags;
-//		uint32 st_gen;
-//		int32 st_lspare;
-//		int64 st_qspare[2];
-//	};
-//	#pragma pack off
-//
-// The -g flag to godefs causes it to generate Go output, not C.
-// In the Go output, struct fields have leading xx_ prefixes removed
-// and the first character capitalized (exported).
-//
-// Godefs works by invoking gcc to compile the given input file
-// and then parses the debug info embedded in the assembly output.
-// This is far easier than reading system headers on most machines.
-//
-// The -c flag sets the compiler (default "gcc").
-//
-// The -f flag adds a flag to pass to the compiler (e.g., -f -m64).
-
-#include "a.h"
-
-#ifdef _WIN32
-int
-spawn(char *prog, char **argv)
-{
-	return _spawnvp(P_NOWAIT, prog, (const char**)argv);
-}
-#undef waitfor
-void
-waitfor(int pid)
-{
-	_cwait(0, pid, 0);
-}
-#else
-int
-spawn(char *prog, char **argv)
-{
-	int pid;
-	
-	USED(prog);
-	pid = fork();
-	if(pid < 0)
-		sysfatal("fork: %r");
-	if(pid == 0) {
-		exec(argv[0], argv);
-		fprint(2, "exec gcc: %r\n");
-		exit(1);
-	}
-	return pid;
-}
-#endif
-
-void
-usage(void)
-{
-	fprint(2, "usage: godefs [-g package] [-c cc] [-f cc-arg] [defs.c ...]\n");
-	exit(1);
-}
-
-int gotypefmt(Fmt*);
-int ctypefmt(Fmt*);
-int prefixlen(Type*);
-int cutprefix(char*);
-
-Lang go =
-{
-	"const (\n",
-	"\t%s = %#llx;\n",
-	")\n",
-
-	"type",
-	"\n",
-
-	"type %s struct {\n",
-	"type %s struct {\n",
-	"\tPad_godefs_%d [%d]byte;\n",
-	"}\n",
-
-	gotypefmt,
-};
-
-Lang c =
-{
-	"enum {\n",
-	"\t%s = %#llx,\n",
-	"};\n",
-
-	"typedef",
-	";\n",
-
-	"typedef struct %s %s;\nstruct %s {\n",
-	"typedef union %s %s;\nunion %s {\n",
-	"\tbyte pad_godefs_%d[%d];\n",
-	"};\n",
-
-	ctypefmt,
-};
-
-char *pkg;
-
-int oargc;
-char **oargv;
-Lang *lang = &c;
-
-Const *con;
-int ncon;
-
-Type **typ;
-int ntyp;
-
-void
-waitforgcc(void)
-{
-	waitpid();
-}
-
-void
-main(int argc, char **argv)
-{
-	int p[2], pid, i, j, n, off, npad, prefix;
-	char **av, *q, *r, *tofree, *name;
-	char nambuf[100];
-	Biobuf *bin, *bout;
-	Type *t, *tt;
-	Field *f;
-	int orig_output_fd;
-
-	quotefmtinstall();
-
-	oargc = argc;
-	oargv = argv;
-	av = emalloc((30+argc)*sizeof av[0]);
-	atexit(waitforgcc);
-
-	n = 0;
-	av[n++] = "gcc";
-	av[n++] = "-fdollars-in-identifiers";
-	av[n++] = "-S";	// write assembly
-	av[n++] = "-gstabs+";	// include stabs info
-	av[n++] = "-o";	// to ...
-	av[n++] = "-";	// ... stdout
-	av[n++] = "-xc";	// read C
-
-	ARGBEGIN{
-	case 'g':
-		lang = &go;
-		pkg = EARGF(usage());
-		break;
-	case 'c':
-		av[0] = EARGF(usage());
-		break;
-	case 'f':
-		av[n++] = EARGF(usage());
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	if(argc == 0)
-		av[n++] = "-";
-	else
-		av[n++] = argv[0];
-	av[n] = nil;
-
-	orig_output_fd = dup(1, -1);
-	for(i=0; i==0 || i < argc; i++) {
-		// Some versions of gcc do not accept -S with multiple files.
-		// Run gcc once for each file.
-		// Write assembly and stabs debugging to p[1].
-		if(pipe(p) < 0)
-			sysfatal("pipe: %r");
-		dup(p[1], 1);
-		close(p[1]);
-		if (argc)
-			av[n-1] = argv[i];
-		pid = spawn(av[0], av);
-		dup(orig_output_fd, 1);
-
-		// Read assembly, pulling out .stabs lines.
-		bin = Bfdopen(p[0], OREAD);
-		while((q = Brdstr(bin, '\n', 1)) != nil) {
-			//	.stabs	"float:t(0,12)=r(0,1);4;0;",128,0,0,0
-			tofree = q;
-			while(*q == ' ' || *q == '\t')
-				q++;
-			if(strncmp(q, ".stabs", 6) != 0)
-				goto Continue;
-			q += 6;
-			while(*q == ' ' || *q == '\t')
-				q++;
-			if(*q++ != '\"') {
-Bad:
-				sysfatal("cannot parse .stabs line:\n%s", tofree);
-			}
-
-			r = strchr(q, '\"');
-			if(r == nil)
-				goto Bad;
-			*r++ = '\0';
-			if(*r++ != ',')
-				goto Bad;
-			if(*r < '0' || *r > '9')
-				goto Bad;
-			if(atoi(r) != 128)	// stabs kind = local symbol
-				goto Continue;
-
-			parsestabtype(q);
-
-Continue:
-			free(tofree);
-		}
-		Bterm(bin);
-		waitfor(pid);
-	}
-	close(orig_output_fd);
-
-	// Write defs to standard output.
-	bout = Bfdopen(1, OWRITE);
-	fmtinstall('T', lang->typefmt);
-
-	// Echo original command line in header.
-	Bprint(bout, "//");
-	for(i=0; i<oargc; i++)
-		Bprint(bout, " %q", oargv[i]);
-	Bprint(bout, "\n");
-	Bprint(bout, "\n");
-	Bprint(bout, "// MACHINE GENERATED - DO NOT EDIT.\n");
-	Bprint(bout, "\n");
-
-	if(pkg)
-		Bprint(bout, "package %s\n\n", pkg);
-
-	// Constants.
-	Bprint(bout, "// Constants\n");
-	if(ncon > 0) {
-		Bprint(bout, lang->constbegin);
-		for(i=0; i<ncon; i++) {
-			// Go can handle negative constants,
-			// but C enums may not be able to.
-			if(lang == &go)
-				Bprint(bout, lang->constfmt, con[i].name, con[i].value);
-			else
-				Bprint(bout, lang->constfmt, con[i].name, con[i].value & 0xFFFFFFFF);
-		}
-		Bprint(bout, lang->constend);
-	}
-	Bprint(bout, "\n");
-
-	// Types
-
-	// push our names down
-	for(i=0; i<ntyp; i++) {
-		t = typ[i];
-		name = t->name;
-		while(t && t->kind == Typedef)
-			t = t->type;
-		if(t)
-			t->name = name;
-	}
-
-	Bprint(bout, "// Types\n");
-
-	// Have to turn off structure padding in Plan 9 compiler,
-	// mainly because it is more aggressive than gcc tends to be.
-	if(lang == &c)
-		Bprint(bout, "#pragma pack on\n");
-
-	for(i=0; i<ntyp; i++) {
-		Bprint(bout, "\n");
-		t = typ[i];
-		name = t->name;
-		while(t && t->kind == Typedef) {
-			if(name == nil && t->name != nil) {
-				name = t->name;
-				if(t->printed)
-					break;
-			}
-			t = t->type;
-		}
-		if(name == nil && t->name != nil) {
-			name = t->name;
-			if(t->printed)
-				continue;
-			t->printed = 1;
-		}
-		if(name == nil) {
-			fprint(2, "unknown name for %T", typ[i]);
-			continue;
-		}
-		if(name[0] == '$')
-			name++;
-		npad = 0;
-		off = 0;
-		switch(t->kind) {
-		case 0:
-			fprint(2, "unknown type definition for %s\n", name);
-			break;
-		default:	// numeric, array, or pointer
-		case Array:
-		case Ptr:
-			Bprint(bout, "%s %lT%s", lang->typdef, name, t, lang->typdefend);
-			break;
-		case Union:
-			// In Go, print union as struct with only first element,
-			// padded the rest of the way.
-			Bprint(bout, lang->unionbegin, name, name, name);
-			goto StructBody;
-		case Struct:
-			Bprint(bout, lang->structbegin, name, name, name);
-		StructBody:
-			prefix = 0;
-			if(lang == &go)
-				prefix = prefixlen(t);
-			for(j=0; j<t->nf; j++) {
-				f = &t->f[j];
-				if(f->type->kind == 0 && f->size <= 64 && (f->size&(f->size-1)) == 0) {
-					// unknown type but <= 64 bits and bit size is a power of two.
-					// could be enum - make Uint64 and then let it reduce
-					tt = emalloc(sizeof *tt);
-					*tt = *f->type;
-					f->type = tt;
-					tt->kind = Uint64;
-					while(tt->kind > Uint8 && kindsize[tt->kind] > f->size)
-						tt->kind -= 2;
-				}
-				// padding
-				if(t->kind == Struct || lang == &go) {
-					if(f->offset%8 != 0 || f->size%8 != 0) {
-						fprint(2, "ignoring bitfield %s.%s\n", t->name, f->name);
-						continue;
-					}
-					if(f->offset < off)
-						sysfatal("%s: struct fields went backward", t->name);
-					if(off < f->offset) {
-						Bprint(bout, lang->structpadfmt, npad++, (f->offset - off) / 8);
-						off = f->offset;
-					}
-					off += f->size;
-				}
-				name = f->name;
-				if(cutprefix(name))
-					name += prefix;
-				if(strcmp(name, "") == 0) {
-					snprint(nambuf, sizeof nambuf, "Pad_godefs_%d", npad++);
-					name = nambuf;
-				}
-				Bprint(bout, "\t%#lT;\n", name, f->type);
-				if(t->kind == Union && lang == &go)
-					break;
-			}
-			// final padding
-			if(t->kind == Struct || lang == &go) {
-				if(off/8 < t->size)
-					Bprint(bout, lang->structpadfmt, npad++, t->size - off/8);
-			}
-			Bprint(bout, lang->structend);
-		}
-	}
-	if(lang == &c)
-		Bprint(bout, "#pragma pack off\n");
-	Bterm(bout);
-	exit(0);
-}
-
-char *kindnames[] = {
-	"void",	// actually unknown, but byte is good for pointers
-	"void",
-	"int8",
-	"uint8",
-	"int16",
-	"uint16",
-	"int32",
-	"uint32",
-	"int64",
-	"uint64",
-	"float32",
-	"float64",
-	"ptr",
-	"struct",
-	"array",
-	"union",
-	"typedef",
-};
-
-int
-ctypefmt(Fmt *f)
-{
-	char *name, *s;
-	Type *t;
-
-	name = nil;
-	if(f->flags & FmtLong) {
-		name = va_arg(f->args, char*);
-		if(name == nil || name[0] == '\0')
-			name = "_anon_";
-	}
-	t = va_arg(f->args, Type*);
-	while(t && t->kind == Typedef)
-		t = t->type;
-	switch(t->kind) {
-	case Struct:
-	case Union:
-		// must be named
-		s = t->name;
-		if(s == nil) {
-			fprint(2, "need name for anonymous struct\n");
-			goto bad;
-		}
-		else if(s[0] != '$')
-			fprint(2, "need name for struct %s\n", s);
-		else
-			s++;
-		fmtprint(f, "%s", s);
-		if(name)
-			fmtprint(f, " %s", name);
-		break;
-
-	case Array:
-		if(name)
-			fmtprint(f, "%T %s[%d]", t->type, name, t->size);
-		else
-			fmtprint(f, "%T[%d]", t->type, t->size);
-		break;
-
-	case Ptr:
-		if(name)
-			fmtprint(f, "%T *%s", t->type, name);
-		else
-			fmtprint(f, "%T*", t->type);
-		break;
-
-	default:
-		fmtprint(f, "%s", kindnames[t->kind]);
-		if(name)
-			fmtprint(f, " %s", name);
-		break;
-
-	bad:
-		if(name)
-			fmtprint(f, "byte %s[%d]", name, t->size);
-		else
-			fmtprint(f, "byte[%d]", t->size);
-		break;
-	}
-
-	return 0;
-}
-
-int
-gotypefmt(Fmt *f)
-{
-	char *name, *s;
-	Type *t;
-
-	if(f->flags & FmtLong) {
-		name = va_arg(f->args, char*);
-		if('a' <= name[0] && name[0] <= 'z')
-			name[0] += 'A' - 'a';
-		if(name[0] == '_' && (f->flags & FmtSharp))
-			fmtprint(f, "X");
-		fmtprint(f, "%s ", name);
-	}
-	t = va_arg(f->args, Type*);
-	while(t && t->kind == Typedef)
-		t = t->type;
-
-	switch(t->kind) {
-	case Struct:
-	case Union:
-		// must be named
-		s = t->name;
-		if(s == nil) {
-			fprint(2, "need name for anonymous struct\n");
-			fmtprint(f, "STRUCT");
-		}
-		else if(s[0] != '$') {
-			fprint(2, "warning: missing name for struct %s\n", s);
-			fmtprint(f, "[%d]byte /* %s */", t->size, s);
-		} else
-			fmtprint(f, "%s", s+1);
-		break;
-
-	case Array:
-		fmtprint(f, "[%d]%T", t->size, t->type);
-		break;
-
-	case Ptr:
-		fmtprint(f, "*%T", t->type);
-		break;
-
-	default:
-		s = kindnames[t->kind];
-		if(strcmp(s, "void") == 0)
-			s = "byte";
-		fmtprint(f, "%s", s);
-	}
-
-	return 0;
-}
-
-// Is this the kind of name we should cut a prefix from?
-// The rule is that the name cannot begin with underscore
-// and must have an underscore eventually.
-int
-cutprefix(char *name)
-{
-	char *p;
-
-	// special case: orig_ in register struct
-	if(strncmp(name, "orig_", 5) == 0)
-		return 0;
-
-	for(p=name; *p; p++) {
-		if(*p == '_')
-			return p-name > 0;
-	}
-	return 0;
-}
-
-// Figure out common struct prefix len
-int
-prefixlen(Type *t)
-{
-	int i;
-	int len;
-	char *p, *name;
-	Field *f;
-
-	len = 0;
-	name = nil;
-	for(i=0; i<t->nf; i++) {
-		f = &t->f[i];
-		if(!cutprefix(f->name))
-			continue;
-		p = strchr(f->name, '_');
-		if(p == nil)
-			return 0;
-		if(name == nil) {
-			name = f->name;
-			len = p+1 - name;
-		}
-		else if(strncmp(f->name, name, len) != 0)
-			return 0;
-	}
-	return len;
-}
diff --git a/src/cmd/godefs/stabs.c b/src/cmd/godefs/stabs.c
deleted file mode 100644
index 2c3d431..0000000
--- a/src/cmd/godefs/stabs.c
+++ /dev/null
@@ -1,456 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Parse stabs debug info.
-
-#include "a.h"
-
-int stabsdebug = 1;
-
-// Hash table for type lookup by number.
-Type *hash[1024];
-
-// Look up type by number pair.
-// TODO(rsc): Iant points out that n1 and n2 are always small and dense,
-// so an array of arrays would be a better representation.
-Type*
-typebynum(uint n1, uint n2)
-{
-	uint h;
-	Type *t;
-
-	h = (n1*53+n2) % nelem(hash);
-	for(t=hash[h]; t; t=t->next)
-		if(t->n1 == n1 && t->n2 == n2)
-			return t;
-	t = emalloc(sizeof *t);
-	t->next = hash[h];
-	hash[h] = t;
-	t->n1 = n1;
-	t->n2 = n2;
-	return t;
-}
-
-// Parse name and colon from *pp, leaving copy in *sp.
-static int
-parsename(char **pp, char **sp)
-{
-	char *p;
-	char *s;
-
-	p = *pp;
-	while(*p != '\0' && *p != ':')
-		p++;
-	if(*p == '\0') {
-		fprint(2, "parsename expected colon\n");
-		return -1;
-	}
-	s = emalloc(p - *pp + 1);
-	memmove(s, *pp, p - *pp);
-	*sp = s;
-	*pp = p+1;
-	return 0;
-}
-
-// Parse single number from *pp.
-static int
-parsenum1(char **pp, vlong *np)
-{
-	char *p;
-
-	p = *pp;
-	if(*p != '-' && (*p < '0' || *p > '9')) {
-		fprint(2, "parsenum expected minus or digit\n");
-		return -1;
-	}
-	*np = strtoll(p, pp, 10);
-	return 0;
-}
-
-// Parse type number - either single number or (n1, n2).
-static int
-parsetypenum(char **pp, vlong *n1p, vlong *n2p)
-{
-	char *p;
-
-	p = *pp;
-	if(*p == '(') {
-		p++;
-		if(parsenum1(&p, n1p) < 0)
-			return -1;
-		if(*p++ != ',') {
-			if(stabsdebug)
-				fprint(2, "parsetypenum expected comma\n");
-			return -1;
-		}
-		if(parsenum1(&p, n2p) < 0)
-			return -1;
-		if(*p++ != ')') {
-			if(stabsdebug)
-				fprint(2, "parsetypenum expected right paren\n");
-			return -1;
-		}
-		*pp = p;
-		return 0;
-	}
-
-	if(parsenum1(&p, n1p) < 0)
-		return -1;
-	*n2p = 0;
-	*pp = p;
-	return 0;
-}
-
-// Written to parse max/min of vlong correctly.
-static vlong
-parseoctal(char **pp)
-{
-	char *p;
-	vlong n;
-
-	p = *pp;
-	if(*p++ != '0')
-		return 0;
-	n = 0;
-	while(*p >= '0' && *p <= '9')
-		n = n << 3 | *p++ - '0';
-	*pp = p;
-	return n;
-}
-
-// Integer types are represented in stabs as a "range"
-// type with a lo and a hi value.  The lo and hi used to
-// be lo and hi for the type, but there are now odd
-// extensions for floating point and 64-bit numbers.
-//
-// Have to keep signs separate from values because
-// Int64's lo is -0.
-typedef struct Intrange Intrange;
-struct Intrange
-{
-	vlong lo;
-	vlong hi;
-	int kind;
-};
-
-Intrange intranges[] = {
-	0, 127, Int8,		// char
-	-128, 127, Int8,	// signed char
-	0, 255, Uint8,
-	-32768, 32767, Int16,
-	0, 65535, Uint16,
-	-2147483648LL, 2147483647LL, Int32,
-	0, 4294967295LL, Uint32,
-	1LL << 63, ~(1LL << 63), Int64,
-	0, -1, Uint64,
-	4, 0, Float32,
-	8, 0, Float64,
-	16, 0, Void,
-};
-
-int kindsize[] = {
-	0,
-	0,
-	8,
-	8,
-	16,
-	16,
-	32,
-	32,
-	64,
-	64,
-};
-
-// Parse a single type definition from *pp.
-static Type*
-parsedef(char **pp, char *name)
-{
-	char *p;
-	Type *t, *tt;
-	int i;
-	vlong n1, n2, lo, hi;
-	Field *f;
-	Intrange *r;
-
-	p = *pp;
-
-	// reference to another type?
-	if(isdigit(*p) || *p == '(') {
-		if(parsetypenum(&p, &n1, &n2) < 0)
-			return nil;
-		t = typebynum(n1, n2);
-		if(name && t->name == nil) {
-			t->name = name;
-			// save definitions of names beginning with $
-			if(name[0] == '$' && !t->saved) {
-				typ = erealloc(typ, (ntyp+1)*sizeof typ[0]);
-				typ[ntyp] = t;
-				ntyp++;
-			}
-		}
-
-		// is there an =def suffix?
-		if(*p == '=') {
-			p++;
-			tt = parsedef(&p, name);
-			if(tt == nil)
-				return nil;
-
-			if(tt == t) {
-				tt->kind = Void;
-			} else {
-				t->type = tt;
-				t->kind = Typedef;
-			}
-
-			// assign given name, but do not record in typ.
-			// assume the name came from a typedef
-			// which will be recorded.
-			if(name)
-				tt->name = name;
-		}
-
-		*pp = p;
-		return t;
-	}
-
-	// otherwise a type literal.  first letter identifies kind
-	t = emalloc(sizeof *t);
-	switch(*p) {
-	default:
-		fprint(2, "unknown type char %c in %s\n", *p, p);
-		*pp = "";
-		return t;
-
-	case '@':	// type attribute
-		while (*++p != ';');
-		*pp = ++p;
-		return parsedef(pp, nil);
-
-	case '*':	// pointer
-		p++;
-		t->kind = Ptr;
-		tt = parsedef(&p, nil);
-		if(tt == nil)
-			return nil;
-		t->type = tt;
-		break;
-
-	case 'a':	// array
-		p++;
-		t->kind = Array;
-		// index type
-		tt = parsedef(&p, nil);
-		if(tt == nil)
-			return nil;
-		t->size = tt->size;
-		// element type
-		tt = parsedef(&p, nil);
-		if(tt == nil)
-			return nil;
-		t->type = tt;
-		break;
-
-	case 'e':	// enum type - record $names in con array.
-		p++;
-		for(;;) {
-			if(*p == '\0')
-				return nil;
-			if(*p == ';') {
-				p++;
-				break;
-			}
-			if(parsename(&p, &name) < 0)
-				return nil;
-			if(parsenum1(&p, &n1) < 0)
-				return nil;
-			if(name[0] == '$') {
-				con = erealloc(con, (ncon+1)*sizeof con[0]);
-				name++;
-				con[ncon].name = name;
-				con[ncon].value = n1;
-				ncon++;
-			}
-			if(*p != ',')
-				return nil;
-			p++;
-		}
-		break;
-
-	case 'f':	// function
-		p++;
-		if(parsedef(&p, nil) == nil)
-			return nil;
-		break;
-
-	case 'B':	// volatile
-	case 'k':	// const
-		++*pp;
-		return parsedef(pp, nil);
-
-	case 'r':	// sub-range (used for integers)
-		p++;
-		if(parsedef(&p, nil) == nil)
-			return nil;
-		// usually, the return from parsedef == t, but not always.
-
-		if(*p != ';' || *++p == ';') {
-			if(stabsdebug)
-				fprint(2, "range expected number: %s\n", p);
-			return nil;
-		}
-		if(*p == '0')
-			lo = parseoctal(&p);
-		else
-			lo = strtoll(p, &p, 10);
-		if(*p != ';' || *++p == ';') {
-			if(stabsdebug)
-				fprint(2, "range expected number: %s\n", p);
-			return nil;
-		}
-		if(*p == '0')
-			hi = parseoctal(&p);
-		else
-			hi = strtoll(p, &p, 10);
-		if(*p != ';') {
-			if(stabsdebug)
-				fprint(2, "range expected trailing semi: %s\n", p);
-			return nil;
-		}
-		p++;
-		t->size = hi+1;	// might be array size
-		for(i=0; i<nelem(intranges); i++) {
-			r = &intranges[i];
-			if(r->lo == lo && r->hi == hi) {
-				t->kind = r->kind;
-				break;
-			}
-		}
-		break;
-
-	case 's':	// struct
-	case 'u':	// union
-		t->kind = Struct;
-		if(*p == 'u')
-			t->kind = Union;
-
-		// assign given name, but do not record in typ.
-		// assume the name came from a typedef
-		// which will be recorded.
-		if(name)
-			t->name = name;
-		p++;
-		if(parsenum1(&p, &n1) < 0)
-			return nil;
-		t->size = n1;
-		for(;;) {
-			if(*p == '\0')
-				return nil;
-			if(*p == ';') {
-				p++;
-				break;
-			}
-			t->f = erealloc(t->f, (t->nf+1)*sizeof t->f[0]);
-			f = &t->f[t->nf];
-			if(parsename(&p, &f->name) < 0)
-				return nil;
-			f->type = parsedef(&p, nil);
-			if(f->type == nil)
-				return nil;
-			if(*p != ',') {
-				fprint(2, "expected comma after def of %s:\n%s\n", f->name, p);
-				return nil;
-			}
-			p++;
-			if(parsenum1(&p, &n1) < 0)
-				return nil;
-			f->offset = n1;
-			if(*p != ',') {
-				fprint(2, "expected comma after offset of %s:\n%s\n", f->name, p);
-				return nil;
-			}
-			p++;
-			if(parsenum1(&p, &n1) < 0)
-				return nil;
-			f->size = n1;
-			if(*p != ';') {
-				fprint(2, "expected semi after size of %s:\n%s\n", f->name, p);
-				return nil;
-			}
-
-			while(f->type->kind == Typedef)
-				f->type = f->type->type;
-
-			// rewrite
-			//	uint32 x : 8;
-			// into
-			//	uint8 x;
-			// hooray for bitfields.
-			while(Int16 <= f->type->kind && f->type->kind <= Uint64 && kindsize[f->type->kind] > f->size) {
-				tt = emalloc(sizeof *tt);
-				*tt = *f->type;
-				f->type = tt;
-				f->type->kind -= 2;
-			}
-			p++;
-			t->nf++;
-		}
-		break;
-
-	case 'x':
-		// reference to struct, union not yet defined.
-		p++;
-		switch(*p) {
-		case 's':
-			t->kind = Struct;
-			break;
-		case 'u':
-			t->kind = Union;
-			break;
-		default:
-			fprint(2, "unknown x type char x%c", *p);
-			*pp = "";
-			return t;
-		}
-		if(parsename(&p, &t->name) < 0)
-			return nil;
-		break;
-	}
-	*pp = p;
-	return t;
-}
-
-
-// Parse a stab type in p, saving info in the type hash table
-// and also in the list of recorded types if appropriate.
-void
-parsestabtype(char *p)
-{
-	char *p0, *name;
-
-	p0 = p;
-
-	// p is the quoted string output from gcc -gstabs on a .stabs line.
-	//	name:t(1,2)
-	//	name:t(1,2)=def
-	if(parsename(&p, &name) < 0) {
-	Bad:
-		// Use fprint instead of sysfatal to avoid
-		// sysfatal's internal buffer size limit.
-		fprint(2, "cannot parse stabs type:\n%s\n(at %s)\n", p0, p);
-		sysfatal("stabs parse");
-	}
-	if(*p != 't' && *p != 'T')
-		goto Bad;
-	p++;
-
-	// parse the definition.
-	if(name[0] == '\0')
-		name = nil;
-	if(parsedef(&p, name) == nil)
-		goto Bad;
-	if(*p != '\0')
-		goto Bad;
-}
-
diff --git a/src/cmd/godefs/test.sh b/src/cmd/godefs/test.sh
deleted file mode 100755
index c035af8..0000000
--- a/src/cmd/godefs/test.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2011 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.
-
-eval $(gomake --no-print-directory -f ../../Make.inc go-env)
-
-TMP="testdata_tmp.go"
-TEST="testdata.c"
-GOLDEN="testdata_${GOOS}_${GOARCH}.golden"
-
-case ${GOARCH} in
-"amd64") CCARG="-f-m64";;
-"386") CCARG="-f-m32";;
-*) CCARG="";;
-esac
-
-cleanup() {
-	rm ${TMP}
-}
-
-error() {
-	cleanup
-	echo $1
-	exit 1
-}
-
-if [ ! -e ${GOLDEN} ]; then
-	echo "skipping - no golden defined for this platform"
-	exit
-fi
-
-./godefs -g test ${CCARG} ${TEST} > ${TMP}
-if [ $? != 0 ]; then
-	error "Error: Could not run godefs for ${TEST}"
-fi
-
-diff ${TMP} ${GOLDEN}
-if [ $? != 0 ]; then
-	error "FAIL: godefs for ${TEST} did not match ${GOLDEN}"
-fi
-
-cleanup
-
-echo "PASS"
diff --git a/src/cmd/godefs/testdata.c b/src/cmd/godefs/testdata.c
deleted file mode 100644
index 3f459c4..0000000
--- a/src/cmd/godefs/testdata.c
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <stdint.h>
-
-// Issue 432 - enum fields in struct can cause misaligned struct fields
-typedef enum {
-	a
-} T1;
-
-struct T2 {
-	uint8_t a;
-	T1 b;
-	T1 c;
-	uint16_t d;
-};
-
-typedef struct T2 T2;
-typedef T2 $T2;
-
-// Issue 1162 - structs with fields named Pad[0-9]+ conflict with field
-// names used by godefs for padding
-struct T3 {
-	uint8_t a;
-	int Pad0;
-};
-
-typedef struct T3 $T3;
-
-// Issue 1466 - forward references to types in stabs debug info were
-// always treated as enums
-struct T4 {};
-
-struct T5 {
-	struct T4 *a;
-};
-
-typedef struct T5 T5;
-typedef struct T4 $T4;
-typedef T5 $T5;
\ No newline at end of file
diff --git a/src/cmd/godefs/testdata_darwin_386.golden b/src/cmd/godefs/testdata_darwin_386.golden
deleted file mode 100644
index d929238..0000000
--- a/src/cmd/godefs/testdata_darwin_386.golden
+++ /dev/null
@@ -1,31 +0,0 @@
-// ./godefs -g test -f-m32 testdata.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-package test
-
-// Constants
-
-// Types
-
-type T2 struct {
-	A uint8;
-	Pad_godefs_0 [3]byte;
-	B uint32;
-	C uint32;
-	D uint16;
-	Pad_godefs_1 [2]byte;
-}
-
-type T3 struct {
-	A uint8;
-	Pad_godefs_0 [3]byte;
-	Pad0 int32;
-}
-
-type T4 struct {
-}
-
-type T5 struct {
-	A *T4;
-}
diff --git a/src/cmd/godefs/testdata_darwin_amd64.golden b/src/cmd/godefs/testdata_darwin_amd64.golden
deleted file mode 100644
index a694f4a..0000000
--- a/src/cmd/godefs/testdata_darwin_amd64.golden
+++ /dev/null
@@ -1,31 +0,0 @@
-// ./godefs -g test -f-m64 testdata.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-package test
-
-// Constants
-
-// Types
-
-type T2 struct {
-	A uint8;
-	Pad_godefs_0 [3]byte;
-	B uint32;
-	C uint32;
-	D uint16;
-	Pad_godefs_1 [2]byte;
-}
-
-type T3 struct {
-	A uint8;
-	Pad_godefs_0 [3]byte;
-	Pad0 int32;
-}
-
-type T4 struct {
-}
-
-type T5 struct {
-	A *T4;
-}
diff --git a/src/cmd/godefs/util.c b/src/cmd/godefs/util.c
deleted file mode 100644
index 18be004..0000000
--- a/src/cmd/godefs/util.c
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "a.h"
-
-void*
-emalloc(int n)
-{
-	void *p;
-
-	p = malloc(n);
-	if(p == nil)
-		sysfatal("out of memory");
-	memset(p, 0, n);
-	return p;
-}
-
-char*
-estrdup(char *s)
-{
-	s = strdup(s);
-	if(s == nil)
-		sysfatal("out of memory");
-	return s;
-}
-
-void*
-erealloc(void *v, int n)
-{
-	v = realloc(v, n);
-	if(v == nil)
-		sysfatal("out of memory");
-	return v;
-}
-
diff --git a/src/cmd/godoc/README.godoc-app b/src/cmd/godoc/README.godoc-app
new file mode 100644
index 0000000..88cfee4
--- /dev/null
+++ b/src/cmd/godoc/README.godoc-app
@@ -0,0 +1,80 @@
+Copyright 2011 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.
+
+godoc on appengine
+------------------
+
+Prerequisites
+-------------
+
+* Go appengine SDK 1.5.5 - 2011-10-11
+  http://code.google.com/appengine/downloads.html#Google_App_Engine_SDK_for_Go
+
+* Go sources at tip under $GOROOT
+
+
+Directory structure
+-------------------
+
+* Let $APPDIR be the directory containing the app engine files.
+  (e.g., $APPDIR=$HOME/godoc-app)
+
+* $APPDIR contains the following entries (this may change depending on
+  app-engine release and version of godoc):
+
+	alt/
+		encoding/binary/
+		go/*
+		index/suffixarray/
+	app.yaml
+	godoc.zip
+	godoc/
+	index.split.*
+
+* The app.yaml file is set up per app engine documentation.
+  For instance:
+
+	application: godoc-app
+	version: 1-5-5
+	runtime: go
+	api_version: 3
+
+	handlers:
+	- url: /.*
+	  script: _go_app
+
+* The godoc/ directory contains a copy of the files under $GOROOT/src/cmd/godoc
+  with modifications:
+
+	- doc.go is excluded (it belongs to pseudo-package ÒdocumentationÓ)
+	- main.go is excluded (appinit.go is taking its place)
+
+  Additional manual modifications are required to refer to the alt/ packages
+  where the app-engine library is not up-to-date with the godoc version.
+
+* The alt/ directory contains up-to-date copies of Go packages that a tip-based
+  godoc is dependent on but which do not yet exist in the current app-engine SDK.
+  At the time of this writing (10/14/2011) this is the entire go directory tree
+  (for the missing FileSet serialization code in go/token) as well as the
+  index/suffixarray package (for the missing suffix array serialization code).
+  The latest (alt/)index/suffixarray package internally requires the latest
+  version of encoding/binary, which is why it also needs to be present under
+  alt/.
+
+
+Configuring and running godoc
+-----------------------------
+
+To configure godoc, run
+
+	bash setup-godoc-app.bash
+
+to create the godoc.zip, index.split.*, and godoc/appconfig.go files
+based on $GOROOT and $APPDIR. See the script for details on usage.
+
+To run godoc locally, using the app-engine emulator, run
+
+	<path to google_appengine>/dev_appserver.py $APPDIR
+
+godoc should come up at http://localhost:8080 .
diff --git a/src/cmd/godoc/appconfig.go b/src/cmd/godoc/appconfig.go
deleted file mode 100644
index 052a9eb..0000000
--- a/src/cmd/godoc/appconfig.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2011 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 file contains configuration information used by
-// godoc when running on app engine. Adjust as needed
-// (typically when the .zip file changes).
-
-package main
-
-const (
-	// zipFilename is the name of the .zip file
-	// containing the file system served by godoc.
-	zipFilename = "godoc.zip"
-
-	// zipGoroot is the path of the goroot directory
-	// in the .zip file.
-	zipGoroot = "/home/user/go"
-
-	// If indexFilenames != "", the search index is
-	// initialized with the index stored in these
-	// files (otherwise it will be built at run-time,
-	// eventually). indexFilenames is a glob pattern;
-	// the specified files are concatenated in sorted
-	// order (by filename).
-	// app-engine limit: file sizes must be <= 10MB;
-	// use "split -b8m indexfile index.split." to get
-	// smaller files.
-	indexFilenames = "index.split.*"
-)
diff --git a/src/cmd/godoc/appinit.go b/src/cmd/godoc/appinit.go
index 8c93425..3113498 100644
--- a/src/cmd/godoc/appinit.go
+++ b/src/cmd/godoc/appinit.go
@@ -2,52 +2,21 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// To run godoc under app engine, substitute main.go with
-// this file (appinit.go), provide a .zip file containing
-// the file system to serve, the index file (or files)
-// containing the pre-computed search index and adjust
-// the configuration parameters in appconfig.go accordingly.
-//
-// The current app engine SDK may be based on an older Go
-// release version. To correct for version skew, copy newer
-// packages into the alt directory (e.g. alt/strings) and
-// adjust the imports in the godoc source files (e.g. from
-// `import "strings"` to `import "alt/strings"`). Both old
-// and new packages may be used simultaneously as long as
-// there is no package global state that needs to be shared.
-//
-// The directory structure should look as follows:
-//
-// godoc-app			// directory containing the app engine app
-//      alt			// alternative packages directory to
-//				//	correct for version skew
-//		strings		// never version of the strings package
-//		...		//
-//	app.yaml		// app engine control file
-//	godoc.zip		// .zip file containing the file system to serve
-//	godoc			// contains godoc sources
-//		appinit.go	// this file instead of godoc/main.go
-//		appconfig.go	// godoc for app engine configuration
-//		...		//
-//	index.split.*		// index file(s) containing the search index to serve
-//
-// To run app the engine emulator locally:
-//
-//	dev_appserver.py -a 0 godoc-app
-//
-// The godoc home page is served at: <hostname>:8080 and localhost:8080.
+// +build ignore
 
 package main
 
+// This file replaces main.go when running godoc under app-engine.
+// See README.godoc-app for details.
+
 import (
 	"archive/zip"
-	"http"
 	"log"
-	"os"
+	"net/http"
 	"path"
 )
 
-func serveError(w http.ResponseWriter, r *http.Request, relpath string, err os.Error) {
+func serveError(w http.ResponseWriter, r *http.Request, relpath string, err error) {
 	contents := applyTemplate(errorHTML, "errorHTML", err) // err may contain an absolute path!
 	w.WriteHeader(http.StatusNotFound)
 	servePage(w, "File "+relpath, "", "", contents)
diff --git a/src/cmd/godoc/codewalk.go b/src/cmd/godoc/codewalk.go
index fb5f275..b3bc79a 100644
--- a/src/cmd/godoc/codewalk.go
+++ b/src/cmd/godoc/codewalk.go
@@ -13,18 +13,19 @@
 package main
 
 import (
+	"encoding/xml"
+	"errors"
 	"fmt"
-	"http"
 	"io"
 	"log"
+	"net/http"
 	"os"
-	"exp/regexp"
+	"regexp"
 	"sort"
 	"strconv"
 	"strings"
-	"template"
-	"utf8"
-	"xml"
+	"text/template"
+	"unicode/utf8"
 )
 
 // Handler for /doc/codewalk/ and below.
@@ -40,7 +41,7 @@ func codewalk(w http.ResponseWriter, r *http.Request) {
 
 	// If directory exists, serve list of code walks.
 	dir, err := fs.Lstat(abspath)
-	if err == nil && dir.IsDirectory() {
+	if err == nil && dir.IsDir() {
 		codewalkDir(w, r, relpath, abspath)
 		return
 	}
@@ -84,7 +85,7 @@ type Codestep struct {
 	XML   string `xml:"innerxml"`
 
 	// Derived from Src; not in XML.
-	Err    os.Error
+	Err    error
 	File   string
 	Lo     int
 	LoByte int
@@ -107,16 +108,16 @@ func (st *Codestep) String() string {
 }
 
 // loadCodewalk reads a codewalk from the named XML file.
-func loadCodewalk(filename string) (*Codewalk, os.Error) {
+func loadCodewalk(filename string) (*Codewalk, error) {
 	f, err := fs.Open(filename)
 	if err != nil {
 		return nil, err
 	}
 	defer f.Close()
 	cw := new(Codewalk)
-	p := xml.NewParser(f)
-	p.Entity = xml.HTMLEntity
-	err = p.Unmarshal(cw, nil)
+	d := xml.NewDecoder(f)
+	d.Entity = xml.HTMLEntity
+	err = d.Decode(cw)
 	if err != nil {
 		return nil, &os.PathError{"parsing", filename, err}
 	}
@@ -185,7 +186,7 @@ func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string
 	var v []interface{}
 	for _, fi := range dir {
 		name := fi.Name()
-		if fi.IsDirectory() {
+		if fi.IsDir() {
 			v = append(v, &elem{name + "/", ""})
 		} else if strings.HasSuffix(name, ".xml") {
 			cw, err := loadCodewalk(abspath + "/" + name)
@@ -252,7 +253,7 @@ func codewalkFileprint(w http.ResponseWriter, r *http.Request, f string) {
 // It returns the lo and hi byte offset of the matched region within data.
 // See http://plan9.bell-labs.com/sys/doc/sam/sam.html Table II
 // for details on the syntax.
-func addrToByteRange(addr string, start int, data []byte) (lo, hi int, err os.Error) {
+func addrToByteRange(addr string, start int, data []byte) (lo, hi int, err error) {
 	var (
 		dir        byte
 		prevc      byte
@@ -264,7 +265,7 @@ func addrToByteRange(addr string, start int, data []byte) (lo, hi int, err os.Er
 		c := addr[0]
 		switch c {
 		default:
-			err = os.NewError("invalid address syntax near " + string(c))
+			err = errors.New("invalid address syntax near " + string(c))
 		case ',':
 			if len(addr) == 1 {
 				hi = len(data)
@@ -348,7 +349,7 @@ func addrToByteRange(addr string, start int, data []byte) (lo, hi int, err os.Er
 // (or characters) after hi.  Applying -n (or -#n) means to back up n lines
 // (or characters) before lo.
 // The return value is the new lo, hi.
-func addrNumber(data []byte, lo, hi int, dir byte, n int, charOffset bool) (int, int, os.Error) {
+func addrNumber(data []byte, lo, hi int, dir byte, n int, charOffset bool) (int, int, error) {
 	switch dir {
 	case 0:
 		lo = 0
@@ -424,13 +425,13 @@ func addrNumber(data []byte, lo, hi int, dir byte, n int, charOffset bool) (int,
 		}
 	}
 
-	return 0, 0, os.NewError("address out of range")
+	return 0, 0, errors.New("address out of range")
 }
 
 // addrRegexp searches for pattern in the given direction starting at lo, hi.
 // The direction dir is '+' (search forward from hi) or '-' (search backward from lo).
 // Backward searches are unimplemented.
-func addrRegexp(data []byte, lo, hi int, dir byte, pattern string) (int, int, os.Error) {
+func addrRegexp(data []byte, lo, hi int, dir byte, pattern string) (int, int, error) {
 	re, err := regexp.Compile(pattern)
 	if err != nil {
 		return 0, 0, err
@@ -438,7 +439,7 @@ func addrRegexp(data []byte, lo, hi int, dir byte, pattern string) (int, int, os
 	if dir == '-' {
 		// Could implement reverse search using binary search
 		// through file, but that seems like overkill.
-		return 0, 0, os.NewError("reverse search not implemented")
+		return 0, 0, errors.New("reverse search not implemented")
 	}
 	m := re.FindIndex(data[hi:])
 	if len(m) > 0 {
@@ -449,7 +450,7 @@ func addrRegexp(data []byte, lo, hi int, dir byte, pattern string) (int, int, os
 		m = re.FindIndex(data)
 	}
 	if len(m) == 0 {
-		return 0, 0, os.NewError("no match for " + pattern)
+		return 0, 0, errors.New("no match for " + pattern)
 	}
 	return m[0], m[1], nil
 }
diff --git a/src/cmd/godoc/dirtrees.go b/src/cmd/godoc/dirtrees.go
index 7595ef9..c61f791 100644
--- a/src/cmd/godoc/dirtrees.go
+++ b/src/cmd/godoc/dirtrees.go
@@ -8,10 +8,10 @@ package main
 
 import (
 	"bytes"
-	"go/doc"
 	"go/parser"
 	"go/token"
 	"log"
+	"os"
 	"path/filepath"
 	"strings"
 	"unicode"
@@ -25,21 +25,21 @@ type Directory struct {
 	Dirs  []*Directory // subdirectories
 }
 
-func isGoFile(fi FileInfo) bool {
+func isGoFile(fi os.FileInfo) bool {
 	name := fi.Name()
-	return fi.IsRegular() &&
+	return !fi.IsDir() &&
 		len(name) > 0 && name[0] != '.' && // ignore .files
 		filepath.Ext(name) == ".go"
 }
 
-func isPkgFile(fi FileInfo) bool {
+func isPkgFile(fi os.FileInfo) bool {
 	return isGoFile(fi) &&
 		!strings.HasSuffix(fi.Name(), "_test.go") // ignore test files
 }
 
-func isPkgDir(fi FileInfo) bool {
+func isPkgDir(fi os.FileInfo) bool {
 	name := fi.Name()
-	return fi.IsDirectory() && len(name) > 0 &&
+	return fi.IsDir() && len(name) > 0 &&
 		name[0] != '_' && name[0] != '.' // ignore _files and .files
 }
 
@@ -135,7 +135,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
 							i = 3 // none of the above
 						}
 						if 0 <= i && i < len(synopses) && synopses[i] == "" {
-							synopses[i] = firstSentence(doc.CommentText(file.Doc))
+							synopses[i] = firstSentence(file.Doc.Text())
 						}
 					}
 				}
diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go
index 3f0b8e4..acea2b5 100644
--- a/src/cmd/godoc/doc.go
+++ b/src/cmd/godoc/doc.go
@@ -80,6 +80,10 @@ The flags are:
 		repository holding the source files.
 	-sync_minutes=0
 		sync interval in minutes; sync is disabled if <= 0
+	-templates=""
+		directory containing alternate template files; if set,
+		the directory may provide alternative template files
+		for the files in $GOROOT/lib/godoc
 	-filter=""
 		filter file containing permitted package directory paths
 	-filter_minutes=0
@@ -124,6 +128,18 @@ via regular expressions). The maximum number of full text search results shown
 can be set with the -maxresults flag; if set to 0, no full text results are
 shown, and only an identifier index but no full text search index is created.
 
+The presentation mode of web pages served by godoc can be controlled with the
+"m" URL parameter; it accepts a comma-separated list of flag names as value:
+
+	all	show documentation for all (not just exported) declarations
+	src	show the original source code rather then the extracted documentation
+	text	present the page in textual (command-line) form rather than HTML
+	flat	present flat (not indented) directory listings using full paths
+
+For instance, http://golang.org/pkg/math/big/?m=all,text shows the documentation
+for all (not just the exported) declarations of package big, in textual form (as
+it would appear when using godoc from the command line: "godoc -src math/big .*").
+
 By default, godoc serves files from the file system of the underlying OS.
 Instead, a .zip file may be provided via the -zip flag, which contains
 the file system to serve. The file paths stored in the .zip file must use
@@ -137,7 +153,6 @@ one may run godoc as follows:
 
 	godoc -http=:6060 -zip=go.zip -goroot=$HOME/go
 
-
 See "Godoc: documenting Go code" for how to write good comments for godoc:
 http://blog.golang.org/2011/03/godoc-documenting-go-code.html
 */
diff --git a/src/cmd/godoc/filesystem.go b/src/cmd/godoc/filesystem.go
index 011977a..4e48c9e 100644
--- a/src/cmd/godoc/filesystem.go
+++ b/src/cmd/godoc/filesystem.go
@@ -15,26 +15,17 @@ import (
 	"os"
 )
 
-// The FileInfo interface provides access to file information.
-type FileInfo interface {
-	Name() string
-	Size() int64
-	Mtime_ns() int64
-	IsRegular() bool
-	IsDirectory() bool
-}
-
 // The FileSystem interface specifies the methods godoc is using
 // to access the file system for which it serves documentation.
 type FileSystem interface {
-	Open(path string) (io.ReadCloser, os.Error)
-	Lstat(path string) (FileInfo, os.Error)
-	Stat(path string) (FileInfo, os.Error)
-	ReadDir(path string) ([]FileInfo, os.Error)
+	Open(path string) (io.ReadCloser, error)
+	Lstat(path string) (os.FileInfo, error)
+	Stat(path string) (os.FileInfo, error)
+	ReadDir(path string) ([]os.FileInfo, error)
 }
 
 // ReadFile reads the file named by path from fs and returns the contents.
-func ReadFile(fs FileSystem, path string) ([]byte, os.Error) {
+func ReadFile(fs FileSystem, path string) ([]byte, error) {
 	rc, err := fs.Open(path)
 	if err != nil {
 		return nil, err
@@ -48,30 +39,10 @@ func ReadFile(fs FileSystem, path string) ([]byte, os.Error) {
 
 var OS FileSystem = osFS{}
 
-// osFI is the OS-specific implementation of FileInfo.
-type osFI struct {
-	*os.FileInfo
-}
-
-func (fi osFI) Name() string {
-	return fi.FileInfo.Name
-}
-
-func (fi osFI) Size() int64 {
-	if fi.IsDirectory() {
-		return 0
-	}
-	return fi.FileInfo.Size
-}
-
-func (fi osFI) Mtime_ns() int64 {
-	return fi.FileInfo.Mtime_ns
-}
-
 // osFS is the OS-specific implementation of FileSystem
 type osFS struct{}
 
-func (osFS) Open(path string) (io.ReadCloser, os.Error) {
+func (osFS) Open(path string) (io.ReadCloser, error) {
 	f, err := os.Open(path)
 	if err != nil {
 		return nil, err
@@ -80,30 +51,20 @@ func (osFS) Open(path string) (io.ReadCloser, os.Error) {
 	if err != nil {
 		return nil, err
 	}
-	if fi.IsDirectory() {
+	if fi.IsDir() {
 		return nil, fmt.Errorf("Open: %s is a directory", path)
 	}
 	return f, nil
 }
 
-func (osFS) Lstat(path string) (FileInfo, os.Error) {
-	fi, err := os.Lstat(path)
-	return osFI{fi}, err
+func (osFS) Lstat(path string) (os.FileInfo, error) {
+	return os.Lstat(path)
 }
 
-func (osFS) Stat(path string) (FileInfo, os.Error) {
-	fi, err := os.Stat(path)
-	return osFI{fi}, err
+func (osFS) Stat(path string) (os.FileInfo, error) {
+	return os.Stat(path)
 }
 
-func (osFS) ReadDir(path string) ([]FileInfo, os.Error) {
-	l0, err := ioutil.ReadDir(path) // l0 is sorted
-	if err != nil {
-		return nil, err
-	}
-	l1 := make([]FileInfo, len(l0))
-	for i, e := range l0 {
-		l1[i] = osFI{e}
-	}
-	return l1, nil
+func (osFS) ReadDir(path string) ([]os.FileInfo, error) {
+	return ioutil.ReadDir(path) // is sorted
 }
diff --git a/src/cmd/godoc/format.go b/src/cmd/godoc/format.go
index 91b7460..3b1b9a8 100644
--- a/src/cmd/godoc/format.go
+++ b/src/cmd/godoc/format.go
@@ -15,9 +15,9 @@ import (
 	"go/scanner"
 	"go/token"
 	"io"
-	"exp/regexp"
+	"regexp"
 	"strconv"
-	"template"
+	"text/template"
 )
 
 // ----------------------------------------------------------------------------
@@ -231,7 +231,7 @@ func commentSelection(src []byte) Selection {
 	var s scanner.Scanner
 	fset := token.NewFileSet()
 	file := fset.AddFile("", fset.Base(), len(src))
-	s.Init(file, src, nil, scanner.ScanComments+scanner.InsertSemis)
+	s.Init(file, src, nil, scanner.ScanComments)
 	return func() (seg []int) {
 		for {
 			pos, tok, lit := s.Scan()
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index 3bf721b..86983fb 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -6,6 +6,7 @@ package main
 
 import (
 	"bytes"
+	"encoding/json"
 	"flag"
 	"fmt"
 	"go/ast"
@@ -13,18 +14,21 @@ import (
 	"go/doc"
 	"go/printer"
 	"go/token"
-	"http"
 	"io"
 	"log"
+	"net/http"
+	"net/url"
 	"os"
 	"path"
 	"path/filepath"
-	"exp/regexp"
+	"regexp"
 	"runtime"
 	"sort"
 	"strings"
-	"template"
+	"text/template"
 	"time"
+	"unicode"
+	"unicode/utf8"
 )
 
 // ----------------------------------------------------------------------------
@@ -34,9 +38,9 @@ type delayTime struct {
 	RWValue
 }
 
-func (dt *delayTime) backoff(max int) {
+func (dt *delayTime) backoff(max time.Duration) {
 	dt.mutex.Lock()
-	v := dt.value.(int) * 2
+	v := dt.value.(time.Duration) * 2
 	if v > max {
 		v = max
 	}
@@ -70,12 +74,13 @@ var (
 	indexThrottle = flag.Float64("index_throttle", 0.75, "index throttle value; 0.0 = no time allocated, 1.0 = full throttle")
 
 	// file system mapping
-	fs         FileSystem      // the underlying file system for godoc
-	fsHttp     http.FileSystem // the underlying file system for http
-	fsMap      Mapping         // user-defined mapping
-	fsTree     RWValue         // *Directory tree of packages, updated with each sync
-	pathFilter RWValue         // filter used when building fsMap directory trees
-	fsModified RWValue         // timestamp of last call to invalidateIndex
+	fs          FileSystem      // the underlying file system for godoc
+	fsHttp      http.FileSystem // the underlying file system for http
+	fsMap       Mapping         // user-defined mapping
+	fsTree      RWValue         // *Directory tree of packages, updated with each sync
+	pathFilter  RWValue         // filter used when building fsMap directory trees
+	fsModified  RWValue         // timestamp of last call to invalidateIndex
+	docMetadata RWValue         // mapping from paths to *Metadata
 
 	// http handlers
 	fileServer http.Handler // default file server
@@ -104,6 +109,7 @@ func registerPublicHandlers(mux *http.ServeMux) {
 	mux.HandleFunc("/doc/codewalk/", codewalk)
 	mux.HandleFunc("/search", search)
 	mux.Handle("/robots.txt", fileServer)
+	mux.HandleFunc("/opensearch.xml", serveSearchDesc)
 	mux.HandleFunc("/", serveFile)
 }
 
@@ -148,7 +154,7 @@ func getPathFilter() func(string) bool {
 
 // readDirList reads a file containing a newline-separated list
 // of directory paths and returns the list of paths.
-func readDirList(filename string) ([]string, os.Error) {
+func readDirList(filename string) ([]string, error) {
 	contents, err := ReadFile(fs, filename)
 	if err != nil {
 		return nil, err
@@ -206,7 +212,7 @@ func updateFilterFile() {
 	// update filter file
 	if err := writeFileAtomically(*filter, buf.Bytes()); err != nil {
 		log.Printf("writeFileAtomically(%s): %s", *filter, err)
-		filterDelay.backoff(24 * 60) // back off exponentially, but try at least once a day
+		filterDelay.backoff(24 * time.Hour) // back off exponentially, but try at least once a day
 	} else {
 		filterDelay.set(*filterMin) // revert to regular filter update schedule
 	}
@@ -229,7 +235,7 @@ func initDirTrees() {
 
 	// start filter update goroutine, if enabled.
 	if *filter != "" && *filterMin > 0 {
-		filterDelay.set(*filterMin) // initial filter update delay
+		filterDelay.set(time.Duration(*filterMin) * time.Minute) // initial filter update delay
 		go func() {
 			for {
 				if *verbose {
@@ -237,10 +243,11 @@ func initDirTrees() {
 				}
 				updateFilterFile()
 				delay, _ := filterDelay.get()
+				dt := delay.(time.Duration)
 				if *verbose {
-					log.Printf("next filter update in %dmin", delay.(int))
+					log.Printf("next filter update in %s", dt)
 				}
-				time.Sleep(int64(delay.(int)) * 60e9)
+				time.Sleep(dt)
 			}
 		}()
 	}
@@ -299,7 +306,7 @@ type tconv struct {
 	indent int // valid if state == indenting
 }
 
-func (p *tconv) writeIndent() (err os.Error) {
+func (p *tconv) writeIndent() (err error) {
 	i := p.indent
 	for i >= len(spaces) {
 		i -= len(spaces)
@@ -314,7 +321,7 @@ func (p *tconv) writeIndent() (err os.Error) {
 	return
 }
 
-func (p *tconv) Write(data []byte) (n int, err os.Error) {
+func (p *tconv) Write(data []byte) (n int, err error) {
 	if len(data) == 0 {
 		return
 	}
@@ -371,7 +378,10 @@ func writeNode(w io.Writer, fset *token.FileSet, x interface{}) {
 	//           with an another printer mode (which is more efficiently
 	//           implemented in the printer than here with another layer)
 	mode := printer.TabIndent | printer.UseSpaces
-	(&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x)
+	err := (&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x)
+	if err != nil {
+		log.Print(err)
+	}
 }
 
 func filenameFunc(path string) string {
@@ -379,17 +389,17 @@ func filenameFunc(path string) string {
 	return localname
 }
 
-func fileInfoNameFunc(fi FileInfo) string {
+func fileInfoNameFunc(fi os.FileInfo) string {
 	name := fi.Name()
-	if fi.IsDirectory() {
+	if fi.IsDir() {
 		name += "/"
 	}
 	return name
 }
 
-func fileInfoTimeFunc(fi FileInfo) string {
-	if t := fi.Mtime_ns(); t != 0 {
-		return time.SecondsToLocalTime(t / 1e9).String()
+func fileInfoTimeFunc(fi os.FileInfo) string {
+	if t := fi.ModTime(); t.Unix() != 0 {
+		return t.Local().String()
 	}
 	return "" // don't return epoch if time is obviously not set
 }
@@ -454,7 +464,65 @@ func comment_htmlFunc(comment string) string {
 	var buf bytes.Buffer
 	// TODO(gri) Provide list of words (e.g. function parameters)
 	//           to be emphasized by ToHTML.
-	doc.ToHTML(&buf, []byte(comment), nil) // does html-escaping
+	doc.ToHTML(&buf, comment, nil) // does html-escaping
+	return buf.String()
+}
+
+// punchCardWidth is the number of columns of fixed-width
+// characters to assume when wrapping text.  Very few people
+// use terminals or cards smaller than 80 characters, so 80 it is.
+// We do not try to sniff the environment or the tty to adapt to
+// the situation; instead, by using a constant we make sure that
+// godoc always produces the same output regardless of context,
+// a consistency that is lost otherwise.  For example, if we sniffed
+// the environment or tty, then http://golang.org/pkg/math/?m=text
+// would depend on the width of the terminal where godoc started,
+// which is clearly bogus.  More generally, the Unix tools that behave
+// differently when writing to a tty than when writing to a file have
+// a history of causing confusion (compare `ls` and `ls | cat`), and we
+// want to avoid that mistake here.
+const punchCardWidth = 80
+
+func comment_textFunc(comment, indent, preIndent string) string {
+	var buf bytes.Buffer
+	doc.ToText(&buf, comment, indent, preIndent, punchCardWidth-2*len(indent))
+	return buf.String()
+}
+
+func startsWithUppercase(s string) bool {
+	r, _ := utf8.DecodeRuneInString(s)
+	return unicode.IsUpper(r)
+}
+
+func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.FileSet) string {
+	var buf bytes.Buffer
+	for _, eg := range examples {
+		name := eg.Name
+
+		// strip lowercase braz in Foo_braz or Foo_Bar_braz from name 
+		// while keeping uppercase Braz in Foo_Braz
+		if i := strings.LastIndex(name, "_"); i != -1 {
+			if i < len(name)-1 && !startsWithUppercase(name[i+1:]) {
+				name = name[:i]
+			}
+		}
+
+		if name != funcName {
+			continue
+		}
+
+		// print code, unindent and remove surrounding braces
+		code := node_htmlFunc(eg.Body, fset)
+		code = strings.Replace(code, "\n    ", "\n", -1)
+		code = code[2 : len(code)-2]
+
+		err := exampleHTML.Execute(&buf, struct {
+			Code, Output string
+		}{code, eg.Output})
+		if err != nil {
+			log.Print(err)
+		}
+	}
 	return buf.String()
 }
 
@@ -526,11 +594,15 @@ var fmap = template.FuncMap{
 	"node":         nodeFunc,
 	"node_html":    node_htmlFunc,
 	"comment_html": comment_htmlFunc,
+	"comment_text": comment_textFunc,
 
 	// support for URL attributes
 	"pkgLink":     pkgLinkFunc,
 	"srcLink":     relativeURL,
 	"posLink_url": posLink_urlFunc,
+
+	// formatting of Examples
+	"example_html": example_htmlFunc,
 }
 
 func readTemplate(name string) *template.Template {
@@ -563,11 +635,13 @@ var (
 	codewalkdirHTML,
 	dirlistHTML,
 	errorHTML,
+	exampleHTML,
 	godocHTML,
 	packageHTML,
 	packageText,
 	searchHTML,
-	searchText *template.Template
+	searchText,
+	searchDescXML *template.Template
 )
 
 func readTemplates() {
@@ -576,11 +650,13 @@ func readTemplates() {
 	codewalkdirHTML = readTemplate("codewalkdir.html")
 	dirlistHTML = readTemplate("dirlist.html")
 	errorHTML = readTemplate("error.html")
+	exampleHTML = readTemplate("example.html")
 	godocHTML = readTemplate("godoc.html")
 	packageHTML = readTemplate("package.html")
 	packageText = readTemplate("package.txt")
 	searchHTML = readTemplate("search.html")
 	searchText = readTemplate("search.txt")
+	searchDescXML = readTemplate("opensearch.xml")
 }
 
 // ----------------------------------------------------------------------------
@@ -621,19 +697,11 @@ func serveText(w http.ResponseWriter, text []byte) {
 // Files
 
 var (
-	titleRx        = regexp.MustCompile(`<!-- title ([^\-]*)-->`)
-	subtitleRx     = regexp.MustCompile(`<!-- subtitle ([^\-]*)-->`)
-	firstCommentRx = regexp.MustCompile(`<!--([^\-]*)-->`)
+	doctype   = []byte("<!DOCTYPE ")
+	jsonStart = []byte("<!--{")
+	jsonEnd   = []byte("}-->")
 )
 
-func extractString(src []byte, rx *regexp.Regexp) (s string) {
-	m := rx.FindSubmatch(src)
-	if m != nil {
-		s = strings.TrimSpace(string(m[1]))
-	}
-	return
-}
-
 func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
 	// get HTML body contents
 	src, err := ReadFile(fs, abspath)
@@ -645,27 +713,25 @@ func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath strin
 
 	// if it begins with "<!DOCTYPE " assume it is standalone
 	// html that doesn't need the template wrapping.
-	if bytes.HasPrefix(src, []byte("<!DOCTYPE ")) {
+	if bytes.HasPrefix(src, doctype) {
 		w.Write(src)
 		return
 	}
 
+	// if it begins with a JSON blob, read in the metadata.
+	meta, src, err := extractMetadata(src)
+	if err != nil {
+		log.Printf("decoding metadata %s: %v", relpath, err)
+	}
+
 	// if it's the language spec, add tags to EBNF productions
 	if strings.HasSuffix(abspath, "go_spec.html") {
 		var buf bytes.Buffer
-		linkify(&buf, src)
+		Linkify(&buf, src)
 		src = buf.Bytes()
 	}
 
-	// get title and subtitle, if any
-	title := extractString(src, titleRx)
-	if title == "" {
-		// no title found; try first comment for backward-compatibility
-		title = extractString(src, firstCommentRx)
-	}
-	subtitle := extractString(src, subtitleRx)
-
-	servePage(w, title, subtitle, "", src)
+	servePage(w, meta.Title, meta.Subtitle, "", src)
 }
 
 func applyTemplate(t *template.Template, name string, data interface{}) []byte {
@@ -717,21 +783,22 @@ func serveDirectory(w http.ResponseWriter, r *http.Request, abspath, relpath str
 }
 
 func serveFile(w http.ResponseWriter, r *http.Request) {
-	relpath := r.URL.Path[1:] // serveFile URL paths start with '/'
-	abspath := absolutePath(relpath, *goroot)
+	relpath := r.URL.Path
 
-	// pick off special cases and hand the rest to the standard file server
-	switch r.URL.Path {
-	case "/":
-		serveHTMLDoc(w, r, filepath.Join(*goroot, "doc", "root.html"), "doc/root.html")
-		return
-
-	case "/doc/root.html":
-		// hide landing page from its real name
-		http.Redirect(w, r, "/", http.StatusMovedPermanently)
-		return
+	// Check to see if we need to redirect or serve another file.
+	if m := metadataFor(relpath); m != nil {
+		if m.Path != relpath {
+			// Redirect to canonical path.
+			http.Redirect(w, r, m.Path, http.StatusMovedPermanently)
+			return
+		}
+		// Serve from the actual filesystem path.
+		relpath = m.filePath
 	}
 
+	relpath = relpath[1:] // strip leading slash
+	abspath := absolutePath(relpath, *goroot)
+
 	switch path.Ext(relpath) {
 	case ".html":
 		if strings.HasSuffix(relpath, "/index.html") {
@@ -755,7 +822,7 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if dir != nil && dir.IsDirectory() {
+	if dir != nil && dir.IsDir() {
 		if redirect(w, r) {
 			return
 		}
@@ -775,6 +842,16 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
 	fileServer.ServeHTTP(w, r)
 }
 
+func serveSearchDesc(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/opensearchdescription+xml")
+	data := map[string]interface{}{
+		"BaseURL": fmt.Sprintf("http://%s", r.Host),
+	}
+	if err := searchDescXML.Execute(w, &data); err != nil {
+		log.Printf("searchDescXML.Execute: %s", err)
+	}
+}
+
 // ----------------------------------------------------------------------------
 // Packages
 
@@ -784,25 +861,69 @@ const fakePkgName = "documentation"
 
 // Fake relative package path for built-ins. Documentation for all globals
 // (not just exported ones) will be shown for packages in this directory.
-const builtinPkgPath = "builtin/"
+const builtinPkgPath = "builtin"
 
 type PageInfoMode uint
 
 const (
-	exportsOnly PageInfoMode = 1 << iota // only keep exported stuff
-	genDoc                               // generate documentation
+	noFiltering PageInfoMode = 1 << iota // do not filter exports
+	showSource                           // show source code, do not extract documentation
+	noHtml                               // show result in textual form, do not generate HTML
+	flatDir                              // show directory in a flat (non-indented) manner
 )
 
+// modeNames defines names for each PageInfoMode flag.
+var modeNames = map[string]PageInfoMode{
+	"all":  noFiltering,
+	"src":  showSource,
+	"text": noHtml,
+	"flat": flatDir,
+}
+
+// getPageInfoMode computes the PageInfoMode flags by analyzing the request
+// URL form value "m". It is value is a comma-separated list of mode names
+// as defined by modeNames (e.g.: m=src,text).
+func getPageInfoMode(r *http.Request) PageInfoMode {
+	var mode PageInfoMode
+	for _, k := range strings.Split(r.FormValue("m"), ",") {
+		if m, found := modeNames[strings.TrimSpace(k)]; found {
+			mode |= m
+		}
+	}
+	return adjustPageInfoMode(r, mode)
+}
+
+// Specialized versions of godoc may adjust the PageInfoMode by overriding
+// this variable.
+var adjustPageInfoMode = func(_ *http.Request, mode PageInfoMode) PageInfoMode {
+	return mode
+}
+
+// remoteSearchURL returns the search URL for a given query as needed by
+// remoteSearch. If html is set, an html result is requested; otherwise
+// the result is in textual form.
+// Adjust this function as necessary if modeNames or FormValue parameters
+// change.
+func remoteSearchURL(query string, html bool) string {
+	s := "/search?m=text&q="
+	if html {
+		s = "/search?q="
+	}
+	return s + url.QueryEscape(query)
+}
+
 type PageInfo struct {
-	Dirname string          // directory containing the package
-	PList   []string        // list of package names found
-	FSet    *token.FileSet  // corresponding file set
-	PAst    *ast.File       // nil if no single AST with package exports
-	PDoc    *doc.PackageDoc // nil if no single package documentation
-	Dirs    *DirList        // nil if no directory information
-	DirTime int64           // directory time stamp in seconds since epoch
-	IsPkg   bool            // false if this is not documenting a real package
-	Err     os.Error        // directory read error or nil
+	Dirname  string         // directory containing the package
+	PList    []string       // list of package names found
+	FSet     *token.FileSet // corresponding file set
+	PAst     *ast.File      // nil if no single AST with package exports
+	PDoc     *doc.Package   // nil if no single package documentation
+	Examples []*doc.Example // nil if no example code
+	Dirs     *DirList       // nil if no directory information
+	DirTime  time.Time      // directory time stamp
+	DirFlat  bool           // if set, show directory in a flat (non-indented) manner
+	IsPkg    bool           // false if this is not documenting a real package
+	Err      error          // I/O error or nil
 }
 
 func (info *PageInfo) IsEmpty() bool {
@@ -816,26 +937,12 @@ type httpHandler struct {
 }
 
 // fsReadDir implements ReadDir for the go/build package.
-func fsReadDir(dir string) ([]*os.FileInfo, os.Error) {
-	fi, err := fs.ReadDir(dir)
-	if err != nil {
-		return nil, err
-	}
-
-	// Convert []FileInfo to []*os.FileInfo.
-	osfi := make([]*os.FileInfo, len(fi))
-	for i, f := range fi {
-		mode := uint32(S_IFREG)
-		if f.IsDirectory() {
-			mode = S_IFDIR
-		}
-		osfi[i] = &os.FileInfo{Name: f.Name(), Size: f.Size(), Mtime_ns: f.Mtime_ns(), Mode: mode}
-	}
-	return osfi, nil
+func fsReadDir(dir string) ([]os.FileInfo, error) {
+	return fs.ReadDir(dir)
 }
 
 // fsReadFile implements ReadFile for the go/build package.
-func fsReadFile(dir, name string) (path string, data []byte, err os.Error) {
+func fsReadFile(dir, name string) (path string, data []byte, err error) {
 	path = filepath.Join(dir, name)
 	data, err = ReadFile(fs, path)
 	return
@@ -881,7 +988,7 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
 	}
 
 	// filter function to select the desired .go files
-	filter := func(d FileInfo) bool {
+	filter := func(d os.FileInfo) bool {
 		// Only Go files.
 		if !isPkgFile(d) {
 			return false
@@ -958,23 +1065,44 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
 		plist = plist[0:i]
 	}
 
+	// get examples from *_test.go files
+	var examples []*doc.Example
+	filter = func(d os.FileInfo) bool {
+		return isGoFile(d) && strings.HasSuffix(d.Name(), "_test.go")
+	}
+	if testpkgs, err := parseDir(fset, abspath, filter); err != nil {
+		log.Println("parsing test files:", err)
+	} else {
+		for _, testpkg := range testpkgs {
+			examples = append(examples, doc.Examples(testpkg)...)
+		}
+	}
+
 	// compute package documentation
 	var past *ast.File
-	var pdoc *doc.PackageDoc
+	var pdoc *doc.Package
 	if pkg != nil {
-		if mode&exportsOnly != 0 {
-			ast.PackageExports(pkg)
-		}
-		if mode&genDoc != 0 {
-			pdoc = doc.NewPackageDoc(pkg, path.Clean(relpath)) // no trailing '/' in importpath
+		if mode&showSource == 0 {
+			// show extracted documentation
+			var m doc.Mode
+			if mode&noFiltering != 0 {
+				m = doc.AllDecls
+			}
+			pdoc = doc.New(pkg, path.Clean(relpath), m) // no trailing '/' in importpath
 		} else {
+			// show source code
+			// TODO(gri) Consider eliminating export filtering in this mode,
+			//           or perhaps eliminating the mode altogether.
+			if mode&noFiltering == 0 {
+				ast.PackageExports(pkg)
+			}
 			past = ast.MergePackageFiles(pkg, ast.FilterUnassociatedComments)
 		}
 	}
 
 	// get directory information
 	var dir *Directory
-	var timestamp int64
+	var timestamp time.Time
 	if tree, ts := fsTree.get(); tree != nil && tree.(*Directory) != nil {
 		// directory tree is present; lookup respective directory
 		// (may still fail if the file system was updated and the
@@ -1011,10 +1139,22 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
 		// note: cannot use path filter here because in general
 		//       it doesn't contain the fsTree path
 		dir = newDirectory(abspath, nil, 1)
-		timestamp = time.Seconds()
+		timestamp = time.Now()
+	}
+
+	return PageInfo{
+		Dirname:  abspath,
+		PList:    plist,
+		FSet:     fset,
+		PAst:     past,
+		PDoc:     pdoc,
+		Examples: examples,
+		Dirs:     dir.listing(true),
+		DirTime:  timestamp,
+		DirFlat:  mode&flatDir != 0,
+		IsPkg:    h.isPkg,
+		Err:      nil,
 	}
-
-	return PageInfo{abspath, plist, fset, past, pdoc, dir.listing(true), timestamp, h.isPkg, nil}
 }
 
 func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -1022,14 +1162,11 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	relpath := r.URL.Path[len(h.pattern):]
+	relpath := path.Clean(r.URL.Path[len(h.pattern):])
 	abspath := absolutePath(relpath, h.fsRoot)
-	var mode PageInfoMode
-	if relpath != builtinPkgPath {
-		mode = exportsOnly
-	}
-	if r.FormValue("m") != "src" {
-		mode |= genDoc
+	mode := getPageInfoMode(r)
+	if relpath == builtinPkgPath {
+		mode = noFiltering
 	}
 	info := h.getPageInfo(abspath, relpath, r.FormValue("p"), mode)
 	if info.Err != nil {
@@ -1038,7 +1175,7 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if r.FormValue("f") == "text" {
+	if mode&noHtml != 0 {
 		contents := applyTemplate(packageText, "packageText", info)
 		serveText(w, contents)
 		return
@@ -1051,18 +1188,18 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	case info.PDoc != nil:
 		switch {
 		case info.IsPkg:
-			title = "Package " + info.PDoc.PackageName
-		case info.PDoc.PackageName == fakePkgName:
+			title = "Package " + info.PDoc.Name
+		case info.PDoc.Name == fakePkgName:
 			// assume that the directory name is the command name
-			_, pkgname := path.Split(path.Clean(relpath))
+			_, pkgname := path.Split(relpath)
 			title = "Command " + pkgname
 		default:
-			title = "Command " + info.PDoc.PackageName
+			title = "Command " + info.PDoc.Name
 		}
 	default:
 		title = "Directory " + relativeURL(info.Dirname)
 		if *showTimestamps {
-			subtitle = "Last update: " + time.SecondsToLocalTime(info.DirTime).String()
+			subtitle = "Last update: " + info.DirTime.String()
 		}
 	}
 
@@ -1098,12 +1235,12 @@ func lookup(query string) (result SearchResult) {
 		index := index.(*Index)
 
 		// identifier search
-		var err os.Error
+		var err error
 		result.Pak, result.Hit, result.Alt, err = index.Lookup(query)
 		if err != nil && *maxResults <= 0 {
 			// ignore the error if full text search is enabled
 			// since the query may be a valid regular expression
-			result.Alert = "Error in query string: " + err.String()
+			result.Alert = "Error in query string: " + err.Error()
 			return
 		}
 
@@ -1111,7 +1248,7 @@ func lookup(query string) (result SearchResult) {
 		if *maxResults > 0 && query != "" {
 			rx, err := regexp.Compile(query)
 			if err != nil {
-				result.Alert = "Error in query regular expression: " + err.String()
+				result.Alert = "Error in query regular expression: " + err.Error()
 				return
 			}
 			// If we get maxResults+1 results we know that there are more than
@@ -1128,7 +1265,7 @@ func lookup(query string) (result SearchResult) {
 
 	// is the result accurate?
 	if *indexEnabled {
-		if _, ts := fsModified.get(); timestamp < ts {
+		if _, ts := fsModified.get(); timestamp.Before(ts) {
 			// The index is older than the latest file system change under godoc's observation.
 			result.Alert = "Indexing in progress: result may be inaccurate"
 		}
@@ -1143,7 +1280,7 @@ func search(w http.ResponseWriter, r *http.Request) {
 	query := strings.TrimSpace(r.FormValue("q"))
 	result := lookup(query)
 
-	if r.FormValue("f") == "text" {
+	if getPageInfoMode(r)&noHtml != 0 {
 		contents := applyTemplate(searchText, "searchText", result)
 		serveText(w, contents)
 		return
@@ -1161,6 +1298,120 @@ func search(w http.ResponseWriter, r *http.Request) {
 }
 
 // ----------------------------------------------------------------------------
+// Documentation Metadata
+
+type Metadata struct {
+	Title    string
+	Subtitle string
+	Path     string // canonical path for this page
+	filePath string // filesystem path relative to goroot
+}
+
+// extractMetadata extracts the Metadata from a byte slice.
+// It returns the Metadata value and the remaining data.
+// If no metadata is present the original byte slice is returned.
+//
+func extractMetadata(b []byte) (meta Metadata, tail []byte, err error) {
+	tail = b
+	if !bytes.HasPrefix(b, jsonStart) {
+		return
+	}
+	end := bytes.Index(b, jsonEnd)
+	if end < 0 {
+		return
+	}
+	b = b[len(jsonStart)-1 : end+1] // drop leading <!-- and include trailing }
+	if err = json.Unmarshal(b, &meta); err != nil {
+		return
+	}
+	tail = tail[end+len(jsonEnd):]
+	return
+}
+
+// updateMetadata scans $GOROOT/doc for HTML files, reads their metadata,
+// and updates the docMetadata map.
+//
+func updateMetadata() {
+	metadata := make(map[string]*Metadata)
+	var scan func(string) // scan is recursive
+	scan = func(dir string) {
+		fis, err := fs.ReadDir(dir)
+		if err != nil {
+			log.Println("updateMetadata:", err)
+			return
+		}
+		for _, fi := range fis {
+			name := filepath.Join(dir, fi.Name())
+			if fi.IsDir() {
+				scan(name) // recurse
+				continue
+			}
+			if !strings.HasSuffix(name, ".html") {
+				continue
+			}
+			// Extract metadata from the file.
+			b, err := ReadFile(fs, name)
+			if err != nil {
+				log.Printf("updateMetadata %s: %v", name, err)
+				continue
+			}
+			meta, _, err := extractMetadata(b)
+			if err != nil {
+				log.Printf("updateMetadata: %s: %v", name, err)
+				continue
+			}
+			// Store relative filesystem path in Metadata.
+			meta.filePath = filepath.Join("/", name[len(*goroot):])
+			if meta.Path == "" {
+				// If no Path, canonical path is actual path.
+				meta.Path = meta.filePath
+			}
+			// Store under both paths.
+			metadata[meta.Path] = &meta
+			metadata[meta.filePath] = &meta
+		}
+	}
+	scan(filepath.Join(*goroot, "doc"))
+	docMetadata.set(metadata)
+}
+
+// Send a value on this channel to trigger a metadata refresh.
+// It is buffered so that if a signal is not lost if sent during a refresh.
+//
+var refreshMetadataSignal = make(chan bool, 1)
+
+// refreshMetadata sends a signal to update docMetadata. If a refresh is in
+// progress the metadata will be refreshed again afterward.
+//
+func refreshMetadata() {
+	select {
+	case refreshMetadataSignal <- true:
+	default:
+	}
+}
+
+// refreshMetadataLoop runs forever, updating docMetadata when the underlying
+// file system changes. It should be launched in a goroutine by main.
+//
+func refreshMetadataLoop() {
+	for {
+		<-refreshMetadataSignal
+		updateMetadata()
+		time.Sleep(10 * time.Second) // at most once every 10 seconds
+	}
+}
+
+// metadataFor returns the *Metadata for a given relative path or nil if none
+// exists.
+//
+func metadataFor(relpath string) *Metadata {
+	if m, _ := docMetadata.get(); m != nil {
+		return m.(map[string]*Metadata)[relpath]
+	}
+	return nil
+}
+
+// ----------------------------------------------------------------------------
 // Indexer
 
 // invalidateIndex should be called whenever any of the file systems
@@ -1168,6 +1419,7 @@ func search(w http.ResponseWriter, r *http.Request) {
 //
 func invalidateIndex() {
 	fsModified.set(nil)
+	refreshMetadata()
 }
 
 // indexUpToDate() returns true if the search index is not older
@@ -1176,7 +1428,7 @@ func invalidateIndex() {
 func indexUpToDate() bool {
 	_, fsTime := fsModified.get()
 	_, siTime := searchIndex.get()
-	return fsTime <= siTime
+	return !fsTime.After(siTime)
 }
 
 // feedDirnames feeds the directory names of all directories
@@ -1206,7 +1458,7 @@ func fsDirnames() <-chan string {
 	return c
 }
 
-func readIndex(filenames string) os.Error {
+func readIndex(filenames string) error {
 	matches, err := filepath.Glob(filenames)
 	if err != nil {
 		return err
@@ -1233,12 +1485,12 @@ func updateIndex() {
 	if *verbose {
 		log.Printf("updating index...")
 	}
-	start := time.Nanoseconds()
+	start := time.Now()
 	index := NewIndex(fsDirnames(), *maxResults > 0, *indexThrottle)
-	stop := time.Nanoseconds()
+	stop := time.Now()
 	searchIndex.set(index)
 	if *verbose {
-		secs := float64((stop-start)/1e6) / 1e3
+		secs := stop.Sub(start).Seconds()
 		stats := index.Stats()
 		log.Printf("index updated (%gs, %d bytes of source, %d files, %d lines, %d unique words, %d spots)",
 			secs, stats.Bytes, stats.Files, stats.Lines, stats.Words, stats.Spots)
@@ -1262,10 +1514,10 @@ func indexer() {
 			// index possibly out of date - make a new one
 			updateIndex()
 		}
-		var delay int64 = 60 * 1e9 // by default, try every 60s
+		delay := 60 * time.Second // by default, try every 60s
 		if *testDir != "" {
 			// in test mode, try once a second for fast startup
-			delay = 1 * 1e9
+			delay = 1 * time.Second
 		}
 		time.Sleep(delay)
 	}
diff --git a/src/cmd/godoc/httpzip.go b/src/cmd/godoc/httpzip.go
index cb8322e..9f3da08 100644
--- a/src/cmd/godoc/httpzip.go
+++ b/src/cmd/godoc/httpzip.go
@@ -26,21 +26,27 @@ package main
 import (
 	"archive/zip"
 	"fmt"
-	"http"
 	"io"
+	"net/http"
 	"os"
 	"path"
 	"sort"
 	"strings"
+	"time"
 )
 
-// We cannot import syscall on app engine.
-// TODO(gri) Once we have a truly abstract FileInfo implementation
-//           this won't be needed anymore.
-const (
-	S_IFDIR = 0x4000 // == syscall.S_IFDIR
-	S_IFREG = 0x8000 // == syscall.S_IFREG
-)
+type fileInfo struct {
+	name  string
+	mode  os.FileMode
+	size  int64
+	mtime time.Time
+}
+
+func (fi *fileInfo) Name() string       { return fi.name }
+func (fi *fileInfo) Mode() os.FileMode  { return fi.mode }
+func (fi *fileInfo) Size() int64        { return fi.size }
+func (fi *fileInfo) ModTime() time.Time { return fi.mtime }
+func (fi *fileInfo) IsDir() bool        { return fi.mode.IsDir() }
 
 // httpZipFile is the zip-file based implementation of http.File
 type httpZipFile struct {
@@ -50,19 +56,19 @@ type httpZipFile struct {
 	list          zipList
 }
 
-func (f *httpZipFile) Close() os.Error {
-	if f.info.IsRegular() {
+func (f *httpZipFile) Close() error {
+	if !f.info.IsDir() {
 		return f.ReadCloser.Close()
 	}
 	f.list = nil
 	return nil
 }
 
-func (f *httpZipFile) Stat() (*os.FileInfo, os.Error) {
-	return &f.info, nil
+func (f *httpZipFile) Stat() (os.FileInfo, error) {
+	return f.info, nil
 }
 
-func (f *httpZipFile) Readdir(count int) ([]os.FileInfo, os.Error) {
+func (f *httpZipFile) Readdir(count int) ([]os.FileInfo, error) {
 	var list []os.FileInfo
 	dirname := f.path + "/"
 	prevname := ""
@@ -76,29 +82,30 @@ func (f *httpZipFile) Readdir(count int) ([]os.FileInfo, os.Error) {
 			break // not in the same directory anymore
 		}
 		name := e.Name[len(dirname):] // local name
-		var mode uint32
-		var size, mtime_ns int64
+		var mode os.FileMode
+		var size int64
+		var mtime time.Time
 		if i := strings.IndexRune(name, '/'); i >= 0 {
 			// We infer directories from files in subdirectories.
 			// If we have x/y, return a directory entry for x.
 			name = name[0:i] // keep local directory name only
-			mode = S_IFDIR
-			// no size or mtime_ns for directories
+			mode = os.ModeDir
+			// no size or mtime for directories
 		} else {
-			mode = S_IFREG
+			mode = 0
 			size = int64(e.UncompressedSize)
-			mtime_ns = e.Mtime_ns()
+			mtime = e.ModTime()
 		}
 		// If we have x/y and x/z, don't return two directory entries for x.
 		// TODO(gri): It should be possible to do this more efficiently
 		// by determining the (fs.list) range of local directory entries
 		// (via two binary searches).
 		if name != prevname {
-			list = append(list, os.FileInfo{
-				Name:     name,
-				Mode:     mode,
-				Size:     size,
-				Mtime_ns: mtime_ns,
+			list = append(list, &fileInfo{
+				name,
+				mode,
+				size,
+				mtime,
 			})
 			prevname = name
 			count--
@@ -106,14 +113,14 @@ func (f *httpZipFile) Readdir(count int) ([]os.FileInfo, os.Error) {
 	}
 
 	if count >= 0 && len(list) == 0 {
-		return nil, os.EOF
+		return nil, io.EOF
 	}
 
 	return list, nil
 }
 
-func (f *httpZipFile) Seek(offset int64, whence int) (int64, os.Error) {
-	return 0, fmt.Errorf("Seek not implemented for zip file entry: %s", f.info.Name)
+func (f *httpZipFile) Seek(offset int64, whence int) (int64, error) {
+	return 0, fmt.Errorf("Seek not implemented for zip file entry: %s", f.info.Name())
 }
 
 // httpZipFS is the zip-file based implementation of http.FileSystem
@@ -123,7 +130,7 @@ type httpZipFS struct {
 	root string
 }
 
-func (fs *httpZipFS) Open(name string) (http.File, os.Error) {
+func (fs *httpZipFS) Open(name string) (http.File, error) {
 	// fs.root does not start with '/'.
 	path := path.Join(fs.root, name) // path is clean
 	index, exact := fs.list.lookup(path)
@@ -141,11 +148,11 @@ func (fs *httpZipFS) Open(name string) (http.File, os.Error) {
 		}
 		return &httpZipFile{
 			path,
-			os.FileInfo{
-				Name:     name,
-				Mode:     S_IFREG,
-				Size:     int64(f.UncompressedSize),
-				Mtime_ns: f.Mtime_ns(),
+			&fileInfo{
+				name,
+				0,
+				int64(f.UncompressedSize),
+				f.ModTime(),
 			},
 			rc,
 			nil,
@@ -155,17 +162,18 @@ func (fs *httpZipFS) Open(name string) (http.File, os.Error) {
 	// not an exact match - must be a directory
 	return &httpZipFile{
 		path,
-		os.FileInfo{
-			Name: name,
-			Mode: S_IFDIR,
-			// no size or mtime_ns for directories
+		&fileInfo{
+			name,
+			os.ModeDir,
+			0,           // no size for directory
+			time.Time{}, // no mtime for directory
 		},
 		nil,
 		fs.list[index:],
 	}, nil
 }
 
-func (fs *httpZipFS) Close() os.Error {
+func (fs *httpZipFS) Close() error {
 	fs.list = nil
 	return fs.ReadCloser.Close()
 }
diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go
index 2543f92..3d2c3ff 100644
--- a/src/cmd/godoc/index.go
+++ b/src/cmd/godoc/index.go
@@ -38,19 +38,22 @@
 package main
 
 import (
+	"bufio"
 	"bytes"
+	"encoding/gob"
+	"errors"
 	"go/ast"
 	"go/parser"
-	"go/token"
 	"go/scanner"
-	"gob"
+	"go/token"
 	"index/suffixarray"
 	"io"
 	"os"
 	"path/filepath"
-	"exp/regexp"
+	"regexp"
 	"sort"
 	"strings"
+	"time"
 )
 
 // ----------------------------------------------------------------------------
@@ -700,8 +703,8 @@ func isWhitelisted(filename string) bool {
 	return whitelisted[key]
 }
 
-func (x *Indexer) visitFile(dirname string, f FileInfo, fulltextIndex bool) {
-	if !f.IsRegular() {
+func (x *Indexer) visitFile(dirname string, f os.FileInfo, fulltextIndex bool) {
+	if f.IsDir() {
 		return
 	}
 
@@ -765,7 +768,7 @@ func canonical(w string) string { return strings.ToLower(w) }
 //
 func NewIndex(dirnames <-chan string, fulltextIndex bool, throttle float64) *Index {
 	var x Indexer
-	th := NewThrottle(throttle, 0.1e9) // run at least 0.1s at a time
+	th := NewThrottle(throttle, 100*time.Millisecond) // run at least 0.1s at a time
 
 	// initialize Indexer
 	// (use some reasonably sized maps to start)
@@ -780,7 +783,7 @@ func NewIndex(dirnames <-chan string, fulltextIndex bool, throttle float64) *Ind
 			continue // ignore this directory
 		}
 		for _, f := range list {
-			if !f.IsDirectory() {
+			if !f.IsDir() {
 				x.visitFile(dirname, f, fulltextIndex)
 			}
 			th.Throttle()
@@ -840,8 +843,16 @@ type fileIndex struct {
 	Fulltext bool
 }
 
+func (x *fileIndex) Write(w io.Writer) error {
+	return gob.NewEncoder(w).Encode(x)
+}
+
+func (x *fileIndex) Read(r io.Reader) error {
+	return gob.NewDecoder(r).Decode(x)
+}
+
 // Write writes the index x to w.
-func (x *Index) Write(w io.Writer) os.Error {
+func (x *Index) Write(w io.Writer) error {
 	fulltext := false
 	if x.suffixes != nil {
 		fulltext = true
@@ -852,7 +863,7 @@ func (x *Index) Write(w io.Writer) os.Error {
 		x.snippets,
 		fulltext,
 	}
-	if err := gob.NewEncoder(w).Encode(fx); err != nil {
+	if err := fx.Write(w); err != nil {
 		return err
 	}
 	if fulltext {
@@ -867,9 +878,14 @@ func (x *Index) Write(w io.Writer) os.Error {
 }
 
 // Read reads the index from r into x; x must not be nil.
-func (x *Index) Read(r io.Reader) os.Error {
+// If r does not also implement io.ByteReader, it will be wrapped in a bufio.Reader.
+func (x *Index) Read(r io.Reader) error {
+	// We use the ability to read bytes as a plausible surrogate for buffering.
+	if _, ok := r.(io.ByteReader); !ok {
+		r = bufio.NewReader(r)
+	}
 	var fx fileIndex
-	if err := gob.NewDecoder(r).Decode(&fx); err != nil {
+	if err := fx.Read(r); err != nil {
 		return err
 	}
 	x.words = fx.Words
@@ -920,13 +936,13 @@ func isIdentifier(s string) bool {
 // identifier, Lookup returns a list of packages, a LookupResult, and a
 // list of alternative spellings, if any. Any and all results may be nil.
 // If the query syntax is wrong, an error is reported.
-func (x *Index) Lookup(query string) (paks HitList, match *LookupResult, alt *AltWords, err os.Error) {
+func (x *Index) Lookup(query string) (paks HitList, match *LookupResult, alt *AltWords, err error) {
 	ss := strings.Split(query, ".")
 
 	// check query syntax
 	for _, s := range ss {
 		if !isIdentifier(s) {
-			err = os.NewError("all query parts must be identifiers")
+			err = errors.New("all query parts must be identifiers")
 			return
 		}
 	}
@@ -954,7 +970,7 @@ func (x *Index) Lookup(query string) (paks HitList, match *LookupResult, alt *Al
 		}
 
 	default:
-		err = os.NewError("query is not a (qualified) identifier")
+		err = errors.New("query is not a (qualified) identifier")
 	}
 
 	return
diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go
index 15d70c4..f74b6f4 100644
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -28,23 +28,23 @@ package main
 import (
 	"archive/zip"
 	"bytes"
+	"errors"
 	_ "expvar" // to serve /debug/vars
 	"flag"
 	"fmt"
 	"go/ast"
 	"go/build"
-	"http"
-	_ "http/pprof" // to serve /debug/pprof/*
 	"io"
 	"log"
+	"net/http"
+	_ "net/http/pprof" // to serve /debug/pprof/*
 	"os"
 	"path"
 	"path/filepath"
-	"exp/regexp"
+	"regexp"
 	"runtime"
 	"strings"
 	"time"
-	"url"
 )
 
 const defaultAddr = ":6060" // default webserver address
@@ -74,7 +74,7 @@ var (
 	query = flag.Bool("q", false, "arguments are considered search queries")
 )
 
-func serveError(w http.ResponseWriter, r *http.Request, relpath string, err os.Error) {
+func serveError(w http.ResponseWriter, r *http.Request, relpath string, err error) {
 	contents := applyTemplate(errorHTML, "errorHTML", err) // err may contain an absolute path!
 	w.WriteHeader(http.StatusNotFound)
 	servePage(w, "File "+relpath, "", "", contents)
@@ -141,10 +141,10 @@ func dosync(w http.ResponseWriter, r *http.Request) {
 	case 1:
 		// sync failed because no files changed;
 		// don't change the package tree
-		syncDelay.set(*syncMin) //  revert to regular sync schedule
+		syncDelay.set(time.Duration(*syncMin) * time.Minute) //  revert to regular sync schedule
 	default:
 		// sync failed because of an error - back off exponentially, but try at least once a day
-		syncDelay.backoff(24 * 60)
+		syncDelay.backoff(24 * time.Hour)
 	}
 }
 
@@ -163,9 +163,7 @@ func loggingHandler(h http.Handler) http.Handler {
 	})
 }
 
-func remoteSearch(query string) (res *http.Response, err os.Error) {
-	search := "/search?f=text&q=" + url.QueryEscape(query)
-
+func remoteSearch(query string) (res *http.Response, err error) {
 	// list of addresses to try
 	var addrs []string
 	if *serverAddr != "" {
@@ -179,6 +177,7 @@ func remoteSearch(query string) (res *http.Response, err os.Error) {
 	}
 
 	// remote search
+	search := remoteSearchURL(query, *html)
 	for _, addr := range addrs {
 		url := "http://" + addr + search
 		res, err = http.Get(url)
@@ -188,7 +187,7 @@ func remoteSearch(query string) (res *http.Response, err os.Error) {
 	}
 
 	if err == nil && res.StatusCode != http.StatusOK {
-		err = os.NewError(res.Status)
+		err = errors.New(res.Status)
 	}
 
 	return
@@ -329,14 +328,20 @@ func main() {
 				for {
 					dosync(nil, nil)
 					delay, _ := syncDelay.get()
+					dt := delay.(time.Duration)
 					if *verbose {
-						log.Printf("next sync in %dmin", delay.(int))
+						log.Printf("next sync in %s", dt)
 					}
-					time.Sleep(int64(delay.(int)) * 60e9)
+					time.Sleep(dt)
 				}
 			}()
 		}
 
+		// Immediately update metadata.
+		updateMetadata()
+		// Periodically refresh metadata.
+		go refreshMetadataLoop()
+
 		// Initialize search index.
 		if *indexEnabled {
 			go indexer()
@@ -387,13 +392,15 @@ func main() {
 	}
 
 	var mode PageInfoMode
+	if relpath == builtinPkgPath {
+		mode = noFiltering
+	}
 	if *srcMode {
 		// only filter exports if we don't have explicit command-line filter arguments
-		if flag.NArg() == 1 {
-			mode |= exportsOnly
+		if flag.NArg() > 1 {
+			mode |= noFiltering
 		}
-	} else {
-		mode = exportsOnly | genDoc
+		mode |= showSource
 	}
 	// TODO(gri): Provide a mechanism (flag?) to select a package
 	//            if there are multiple packages in a directory.
diff --git a/src/cmd/godoc/mapping.go b/src/cmd/godoc/mapping.go
index 51f23ab..89e531e 100644
--- a/src/cmd/godoc/mapping.go
+++ b/src/cmd/godoc/mapping.go
@@ -139,13 +139,18 @@ func (m *Mapping) Fprint(w io.Writer) {
 	}
 }
 
+// splitFirst splits a path at the first path separator and returns
+// the path's head (the top-most directory specified by the path) and
+// its tail (the rest of the path). If there is no path separator,
+// splitFirst returns path as head, and the the empty string as tail.
+// Specifically, splitFirst("foo") == splitFirst("foo/").
+//
 func splitFirst(path string) (head, tail string) {
-	i := strings.Index(path, string(filepath.Separator))
-	if i > 0 {
+	if i := strings.Index(path, string(filepath.Separator)); i > 0 {
 		// 0 < i < len(path)
 		return path[0:i], path[i+1:]
 	}
-	return "", path
+	return path, ""
 }
 
 // ToAbsolute maps a slash-separated relative path to an absolute filesystem
@@ -156,20 +161,14 @@ func (m *Mapping) ToAbsolute(spath string) string {
 	fpath := filepath.FromSlash(spath)
 	prefix, tail := splitFirst(fpath)
 	for _, e := range m.list {
-		switch {
-		case e.prefix == prefix:
-			// use tail
-		case e.prefix == "":
-			tail = fpath
-		default:
-			continue // no match
-		}
-		abspath := filepath.Join(e.path, tail)
-		if _, err := fs.Stat(abspath); err == nil {
-			return abspath
+		if e.prefix == prefix {
+			// found potential mapping
+			abspath := filepath.Join(e.path, tail)
+			if _, err := fs.Stat(abspath); err == nil {
+				return abspath
+			}
 		}
 	}
-
 	return "" // no match
 }
 
diff --git a/src/cmd/godoc/parser.go b/src/cmd/godoc/parser.go
index a292053..da38c52 100644
--- a/src/cmd/godoc/parser.go
+++ b/src/cmd/godoc/parser.go
@@ -17,7 +17,7 @@ import (
 	"path/filepath"
 )
 
-func parseFile(fset *token.FileSet, filename string, mode uint) (*ast.File, os.Error) {
+func parseFile(fset *token.FileSet, filename string, mode parser.Mode) (*ast.File, error) {
 	src, err := ReadFile(fs, filename)
 	if err != nil {
 		return nil, err
@@ -25,7 +25,7 @@ func parseFile(fset *token.FileSet, filename string, mode uint) (*ast.File, os.E
 	return parser.ParseFile(fset, filename, src, mode)
 }
 
-func parseFiles(fset *token.FileSet, filenames []string) (pkgs map[string]*ast.Package, first os.Error) {
+func parseFiles(fset *token.FileSet, filenames []string) (pkgs map[string]*ast.Package, first error) {
 	pkgs = make(map[string]*ast.Package)
 	for _, filename := range filenames {
 		file, err := parseFile(fset, filename, parser.ParseComments)
@@ -48,7 +48,7 @@ func parseFiles(fset *token.FileSet, filenames []string) (pkgs map[string]*ast.P
 	return
 }
 
-func parseDir(fset *token.FileSet, path string, filter func(FileInfo) bool) (map[string]*ast.Package, os.Error) {
+func parseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool) (map[string]*ast.Package, error) {
 	list, err := fs.ReadDir(path)
 	if err != nil {
 		return nil, err
diff --git a/src/cmd/godoc/setup-godoc-app.bash b/src/cmd/godoc/setup-godoc-app.bash
new file mode 100644
index 0000000..755d965
--- /dev/null
+++ b/src/cmd/godoc/setup-godoc-app.bash
@@ -0,0 +1,121 @@
+#!/usr/bin/env bash
+
+# Copyright 2011 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 script creates the .zip, index, and configuration files for running
+# godoc on app-engine.
+#
+# If an argument is provided it is assumed to be the app-engine godoc directory.
+# Without an argument, $APPDIR is used instead. If GOROOT is not set, the
+# current working directory is assumed to be $GOROOT. Various sanity checks
+# prevent accidents.
+#
+# The script creates a .zip file representing the $GOROOT file system
+# and computes the correspondig search index files. These files are then
+# copied to $APPDIR. A corresponding godoc configuration file is created
+# in $APPDIR/appconfig.go.
+
+ZIPFILE=godoc.zip
+INDEXFILE=godoc.index
+SPLITFILES=index.split.
+CONFIGFILE=godoc/appconfig.go
+
+error() {
+	echo "error: $1"
+	exit 2
+}
+
+getArgs() {
+	if [ -z $GOROOT ]; then
+		GOROOT=$(pwd)
+		echo "GOROOT not set, using cwd instead"
+	fi
+	if [ -z $APPDIR ]; then
+		if [ $# == 0 ]; then
+			error "APPDIR not set, and no argument provided"
+		fi
+		APPDIR=$1
+		echo "APPDIR not set, using argument instead"
+	fi
+	
+	# safety checks
+	if [ ! -d $GOROOT ]; then
+		error "$GOROOT is not a directory"
+	fi
+	if [ ! -x $GOROOT/src/cmd/godoc/godoc ]; then
+		error "$GOROOT/src/cmd/godoc/godoc does not exist or is not executable"
+	fi
+	if [ ! -d $APPDIR ]; then
+		error "$APPDIR is not a directory"
+	fi
+	if [ ! -e $APPDIR/app.yaml ]; then
+		error "$APPDIR is not an app-engine directory; missing file app.yaml"
+	fi
+	if [ ! -d $APPDIR/godoc ]; then
+		error "$APPDIR is missing directory godoc"
+	fi
+
+	# reporting
+	echo "GOROOT = $GOROOT"
+	echo "APPDIR = $APPDIR"
+}
+
+cleanup() {
+	echo "*** cleanup $APPDIR"
+	rm $APPDIR/$ZIPFILE
+	rm $APPDIR/$INDEXFILE
+	rm $APPDIR/$SPLITFILES*
+	rm $APPDIR/$CONFIGFILE
+}
+
+makeZipfile() {
+	echo "*** make $APPDIR/$ZIPFILE"
+	zip -q -r $APPDIR/$ZIPFILE $GOROOT -i \*.go -i \*.html -i \*.css -i \*.js -i \*.txt -i \*.c -i \*.h -i \*.s -i \*.png -i \*.jpg -i \*.sh -i \*.ico
+}
+
+makeIndexfile() {
+	echo "*** make $APPDIR/$INDEXFILE"
+	OUT=/tmp/godoc.out
+	$GOROOT/src/cmd/godoc/godoc -write_index -index_files=$APPDIR/$INDEXFILE -zip=$APPDIR/$ZIPFILE 2> $OUT
+	if [ $? != 0 ]; then
+		error "$GOROOT/src/cmd/godoc/godoc failed - see $OUT for details"
+	fi
+}
+
+splitIndexfile() {
+	echo "*** split $APPDIR/$INDEXFILE"
+	split -b8m $APPDIR/$INDEXFILE $APPDIR/$SPLITFILES
+}
+
+makeConfigfile() {
+	echo "*** make $APPDIR/$CONFIGFILE"
+	cat > $APPDIR/$CONFIGFILE <<EOF
+package main
+
+// GENERATED FILE - DO NOT MODIFY BY HAND.
+// (generated by $GOROOT/src/cmd/godoc/setup-godoc-app.bash)
+
+const (
+	// .zip filename
+	zipFilename = "$ZIPFILE"
+
+	// goroot directory in .zip file
+	zipGoroot = "$GOROOT"
+
+	// glob pattern describing search index files
+	// (if empty, the index is built at run-time)
+	indexFilenames = "$SPLITFILES*"
+)
+EOF
+}
+
+getArgs "$@"
+cleanup
+makeZipfile
+makeIndexfile
+splitIndexfile
+makeConfigfile
+
+echo "*** setup complete"
diff --git a/src/cmd/godoc/snippet.go b/src/cmd/godoc/snippet.go
index 68e27d9..c2b74ee 100644
--- a/src/cmd/godoc/snippet.go
+++ b/src/cmd/godoc/snippet.go
@@ -11,9 +11,9 @@ package main
 
 import (
 	"bytes"
+	"fmt"
 	"go/ast"
 	"go/token"
-	"fmt"
 )
 
 type Snippet struct {
diff --git a/src/cmd/godoc/spec.go b/src/cmd/godoc/spec.go
index 3f69add..c11f25d 100644
--- a/src/cmd/godoc/spec.go
+++ b/src/cmd/godoc/spec.go
@@ -2,118 +2,103 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+package main
+
 // This file contains the mechanism to "linkify" html source
 // text containing EBNF sections (as found in go_spec.html).
 // The result is the input source text with the EBNF sections
 // modified such that identifiers are linked to the respective
 // definitions.
 
-package main
-
 import (
 	"bytes"
 	"fmt"
-	"go/scanner"
-	"go/token"
 	"io"
+	"text/scanner"
 )
 
 type ebnfParser struct {
-	out     io.Writer   // parser output
-	src     []byte      // parser source
-	file    *token.File // for position information
+	out     io.Writer // parser output
+	src     []byte    // parser input
 	scanner scanner.Scanner
-	prev    int         // offset of previous token
-	pos     token.Pos   // token position
-	tok     token.Token // one token look-ahead
-	lit     string      // token literal
+	prev    int    // offset of previous token
+	pos     int    // offset of current token
+	tok     rune   // one token look-ahead
+	lit     string // token literal
 }
 
 func (p *ebnfParser) flush() {
-	offs := p.file.Offset(p.pos)
-	p.out.Write(p.src[p.prev:offs])
-	p.prev = offs
+	p.out.Write(p.src[p.prev:p.pos])
+	p.prev = p.pos
 }
 
 func (p *ebnfParser) next() {
-	if p.pos.IsValid() {
-		p.flush()
-	}
-	p.pos, p.tok, p.lit = p.scanner.Scan()
-	if p.tok.IsKeyword() {
-		// TODO Should keyword mapping always happen outside scanner?
-		//      Or should there be a flag to scanner to enable keyword mapping?
-		p.tok = token.IDENT
-	}
+	p.tok = p.scanner.Scan()
+	p.pos = p.scanner.Position.Offset
+	p.lit = p.scanner.TokenText()
 }
 
-func (p *ebnfParser) Error(pos token.Position, msg string) {
-	fmt.Fprintf(p.out, `<span class="alert">error: %s</span>`, msg)
+func (p *ebnfParser) printf(format string, args ...interface{}) {
+	p.flush()
+	fmt.Fprintf(p.out, format, args...)
 }
 
-func (p *ebnfParser) errorExpected(pos token.Pos, msg string) {
-	msg = "expected " + msg
-	if pos == p.pos {
-		// the error happened at the current position;
-		// make the error message more specific
-		msg += ", found '" + p.tok.String() + "'"
-		if p.tok.IsLiteral() {
-			msg += " " + p.lit
-		}
-	}
-	p.Error(p.file.Position(pos), msg)
+func (p *ebnfParser) errorExpected(msg string) {
+	p.printf(`<span class="highlight">error: expected %s, found %s</span>`, msg, scanner.TokenString(p.tok))
 }
 
-func (p *ebnfParser) expect(tok token.Token) token.Pos {
-	pos := p.pos
+func (p *ebnfParser) expect(tok rune) {
 	if p.tok != tok {
-		p.errorExpected(pos, "'"+tok.String()+"'")
+		p.errorExpected(scanner.TokenString(tok))
 	}
 	p.next() // make progress in any case
-	return pos
 }
 
 func (p *ebnfParser) parseIdentifier(def bool) {
-	name := p.lit
-	p.expect(token.IDENT)
-	if def {
-		fmt.Fprintf(p.out, `<a id="%s">%s</a>`, name, name)
+	if p.tok == scanner.Ident {
+		name := p.lit
+		if def {
+			p.printf(`<a id="%s">%s</a>`, name, name)
+		} else {
+			p.printf(`<a href="#%s" class="noline">%s</a>`, name, name)
+		}
+		p.prev += len(name) // skip identifier when printing next time
+		p.next()
 	} else {
-		fmt.Fprintf(p.out, `<a href="#%s" class="noline">%s</a>`, name, name)
+		p.expect(scanner.Ident)
 	}
-	p.prev += len(name) // skip identifier when calling flush
 }
 
 func (p *ebnfParser) parseTerm() bool {
 	switch p.tok {
-	case token.IDENT:
+	case scanner.Ident:
 		p.parseIdentifier(false)
 
-	case token.STRING:
+	case scanner.String:
 		p.next()
-		const ellipsis = "…" // U+2026, the horizontal ellipsis character
-		if p.tok == token.ILLEGAL && p.lit == ellipsis {
+		const ellipsis = '…' // U+2026, the horizontal ellipsis character
+		if p.tok == ellipsis {
 			p.next()
-			p.expect(token.STRING)
+			p.expect(scanner.String)
 		}
 
-	case token.LPAREN:
+	case '(':
 		p.next()
 		p.parseExpression()
-		p.expect(token.RPAREN)
+		p.expect(')')
 
-	case token.LBRACK:
+	case '[':
 		p.next()
 		p.parseExpression()
-		p.expect(token.RBRACK)
+		p.expect(']')
 
-	case token.LBRACE:
+	case '{':
 		p.next()
 		p.parseExpression()
-		p.expect(token.RBRACE)
+		p.expect('}')
 
 	default:
-		return false
+		return false // no term found
 	}
 
 	return true
@@ -121,7 +106,7 @@ func (p *ebnfParser) parseTerm() bool {
 
 func (p *ebnfParser) parseSequence() {
 	if !p.parseTerm() {
-		p.errorExpected(p.pos, "term")
+		p.errorExpected("term")
 	}
 	for p.parseTerm() {
 	}
@@ -130,7 +115,7 @@ func (p *ebnfParser) parseSequence() {
 func (p *ebnfParser) parseExpression() {
 	for {
 		p.parseSequence()
-		if p.tok != token.OR {
+		if p.tok != '|' {
 			break
 		}
 		p.next()
@@ -139,23 +124,22 @@ func (p *ebnfParser) parseExpression() {
 
 func (p *ebnfParser) parseProduction() {
 	p.parseIdentifier(true)
-	p.expect(token.ASSIGN)
-	if p.tok != token.PERIOD {
+	p.expect('=')
+	if p.tok != '.' {
 		p.parseExpression()
 	}
-	p.expect(token.PERIOD)
+	p.expect('.')
 }
 
-func (p *ebnfParser) parse(fset *token.FileSet, out io.Writer, src []byte) {
+func (p *ebnfParser) parse(out io.Writer, src []byte) {
 	// initialize ebnfParser
 	p.out = out
 	p.src = src
-	p.file = fset.AddFile("", fset.Base(), len(src))
-	p.scanner.Init(p.file, src, p, scanner.AllowIllegalChars)
+	p.scanner.Init(bytes.NewBuffer(src))
 	p.next() // initializes pos, tok, lit
 
 	// process source
-	for p.tok != token.EOF {
+	for p.tok != scanner.EOF {
 		p.parseProduction()
 	}
 	p.flush()
@@ -167,32 +151,29 @@ var (
 	closeTag = []byte(`</pre>`)
 )
 
-func linkify(out io.Writer, src []byte) {
-	fset := token.NewFileSet()
+func Linkify(out io.Writer, src []byte) {
 	for len(src) > 0 {
-		n := len(src)
-
 		// i: beginning of EBNF text (or end of source)
 		i := bytes.Index(src, openTag)
 		if i < 0 {
-			i = n - len(openTag)
+			i = len(src) - len(openTag)
 		}
 		i += len(openTag)
 
 		// j: end of EBNF text (or end of source)
-		j := bytes.Index(src[i:n], closeTag) // close marker
+		j := bytes.Index(src[i:], closeTag) // close marker
 		if j < 0 {
-			j = n - i
+			j = len(src) - i
 		}
 		j += i
 
 		// write text before EBNF
 		out.Write(src[0:i])
-		// parse and write EBNF
+		// process EBNF
 		var p ebnfParser
-		p.parse(fset, out, src[i:j])
+		p.parse(out, src[i:j])
 
 		// advance
-		src = src[j:n]
+		src = src[j:]
 	}
 }
diff --git a/src/cmd/godoc/throttle.go b/src/cmd/godoc/throttle.go
index 1934928..ac18b44 100644
--- a/src/cmd/godoc/throttle.go
+++ b/src/cmd/godoc/throttle.go
@@ -10,15 +10,15 @@ import "time"
 // calling the Throttle method repeatedly.
 //
 type Throttle struct {
-	f  float64 // f = (1-r)/r for 0 < r < 1
-	tm int64   // minimum run time slice; >= 0
-	tr int64   // accumulated time running
-	ts int64   // accumulated time stopped
-	tt int64   // earliest throttle time (= time Throttle returned + tm)
+	f  float64       // f = (1-r)/r for 0 < r < 1
+	dt time.Duration // minimum run time slice; >= 0
+	tr time.Duration // accumulated time running
+	ts time.Duration // accumulated time stopped
+	tt time.Time     // earliest throttle time (= time Throttle returned + tm)
 }
 
 // NewThrottle creates a new Throttle with a throttle value r and
-// a minimum allocated run time slice of tm nanoseconds:
+// a minimum allocated run time slice of dt:
 //
 //	r == 0: "empty" throttle; the goroutine is always sleeping
 //	r == 1: full throttle; the goroutine is never sleeping
@@ -26,9 +26,9 @@ type Throttle struct {
 // A value of r == 0.6 throttles a goroutine such that it runs
 // approx. 60% of the time, and sleeps approx. 40% of the time.
 // Values of r < 0 or r > 1 are clamped down to values between 0 and 1.
-// Values of tm < 0 are set to 0.
+// Values of dt < 0 are set to 0.
 //
-func NewThrottle(r float64, tm int64) *Throttle {
+func NewThrottle(r float64, dt time.Duration) *Throttle {
 	var f float64
 	switch {
 	case r <= 0:
@@ -39,10 +39,10 @@ func NewThrottle(r float64, tm int64) *Throttle {
 		// 0 < r < 1
 		f = (1 - r) / r
 	}
-	if tm < 0 {
-		tm = 0
+	if dt < 0 {
+		dt = 0
 	}
-	return &Throttle{f: f, tm: tm, tt: time.Nanoseconds() + tm}
+	return &Throttle{f: f, dt: dt, tt: time.Now().Add(dt)}
 }
 
 // Throttle calls time.Sleep such that over time the ratio tr/ts between
@@ -55,13 +55,13 @@ func (p *Throttle) Throttle() {
 		select {} // always sleep
 	}
 
-	t0 := time.Nanoseconds()
-	if t0 < p.tt {
+	t0 := time.Now()
+	if t0.Before(p.tt) {
 		return // keep running (minimum time slice not exhausted yet)
 	}
 
 	// accumulate running time
-	p.tr += t0 - (p.tt - p.tm)
+	p.tr += t0.Sub(p.tt) + p.dt
 
 	// compute sleep time
 	// Over time we want:
@@ -75,14 +75,14 @@ func (p *Throttle) Throttle() {
 	// After some incremental run time δr added to the total run time
 	// tr, the incremental sleep-time δs to get to the same ratio again
 	// after waking up from time.Sleep is:
-	if δs := int64(float64(p.tr)*p.f) - p.ts; δs > 0 {
+	if δs := time.Duration(float64(p.tr)*p.f) - p.ts; δs > 0 {
 		time.Sleep(δs)
 	}
 
 	// accumulate (actual) sleep time
-	t1 := time.Nanoseconds()
-	p.ts += t1 - t0
+	t1 := time.Now()
+	p.ts += t1.Sub(t0)
 
 	// set earliest next throttle time
-	p.tt = t1 + p.tm
+	p.tt = t1.Add(p.dt)
 }
diff --git a/src/cmd/godoc/utils.go b/src/cmd/godoc/utils.go
index 11e46ae..be0bdc3 100644
--- a/src/cmd/godoc/utils.go
+++ b/src/cmd/godoc/utils.go
@@ -15,7 +15,7 @@ import (
 	"strings"
 	"sync"
 	"time"
-	"utf8"
+	"unicode/utf8"
 )
 
 // An RWValue wraps a value and permits mutually exclusive
@@ -24,17 +24,17 @@ import (
 type RWValue struct {
 	mutex     sync.RWMutex
 	value     interface{}
-	timestamp int64 // time of last set(), in seconds since epoch
+	timestamp time.Time // time of last set()
 }
 
 func (v *RWValue) set(value interface{}) {
 	v.mutex.Lock()
 	v.value = value
-	v.timestamp = time.Seconds()
+	v.timestamp = time.Now()
 	v.mutex.Unlock()
 }
 
-func (v *RWValue) get() (interface{}, int64) {
+func (v *RWValue) get() (interface{}, time.Time) {
 	v.mutex.RLock()
 	defer v.mutex.RUnlock()
 	return v.value, v.timestamp
@@ -93,7 +93,7 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string {
 // writeFileAtomically writes data to a temporary file and then
 // atomically renames that file to the file named by filename.
 //
-func writeFileAtomically(filename string, data []byte) os.Error {
+func writeFileAtomically(filename string, data []byte) error {
 	// TODO(gri) this won't work on appengine
 	f, err := ioutil.TempFile(filepath.Split(filename))
 	if err != nil {
diff --git a/src/cmd/godoc/zip.go b/src/cmd/godoc/zip.go
index 86cd79b..cd38ed9 100644
--- a/src/cmd/godoc/zip.go
+++ b/src/cmd/godoc/zip.go
@@ -26,6 +26,7 @@ import (
 	"path"
 	"sort"
 	"strings"
+	"time"
 )
 
 // zipFI is the zip-file based implementation of FileInfo
@@ -45,19 +46,23 @@ func (fi zipFI) Size() int64 {
 	return 0 // directory
 }
 
-func (fi zipFI) Mtime_ns() int64 {
+func (fi zipFI) ModTime() time.Time {
 	if f := fi.file; f != nil {
-		return f.Mtime_ns()
+		return f.ModTime()
 	}
-	return 0 // directory has no modified time entry
+	return time.Time{} // directory has no modified time entry
 }
 
-func (fi zipFI) IsDirectory() bool {
-	return fi.file == nil
+func (fi zipFI) Mode() os.FileMode {
+	if fi.file == nil {
+		// Unix directories typically are executable, hence 555.
+		return os.ModeDir | 0555
+	}
+	return 0444
 }
 
-func (fi zipFI) IsRegular() bool {
-	return fi.file != nil
+func (fi zipFI) IsDir() bool {
+	return fi.file == nil
 }
 
 // zipFS is the zip-file based implementation of FileSystem
@@ -66,7 +71,7 @@ type zipFS struct {
 	list zipList
 }
 
-func (fs *zipFS) Close() os.Error {
+func (fs *zipFS) Close() error {
 	fs.list = nil
 	return fs.ReadCloser.Close()
 }
@@ -79,7 +84,7 @@ func zipPath(name string) string {
 	return name[1:] // strip leading '/'
 }
 
-func (fs *zipFS) stat(abspath string) (int, zipFI, os.Error) {
+func (fs *zipFS) stat(abspath string) (int, zipFI, error) {
 	i, exact := fs.list.lookup(abspath)
 	if i < 0 {
 		// abspath has leading '/' stripped - print it explicitly
@@ -93,38 +98,38 @@ func (fs *zipFS) stat(abspath string) (int, zipFI, os.Error) {
 	return i, zipFI{name, file}, nil
 }
 
-func (fs *zipFS) Open(abspath string) (io.ReadCloser, os.Error) {
+func (fs *zipFS) Open(abspath string) (io.ReadCloser, error) {
 	_, fi, err := fs.stat(zipPath(abspath))
 	if err != nil {
 		return nil, err
 	}
-	if fi.IsDirectory() {
+	if fi.IsDir() {
 		return nil, fmt.Errorf("Open: %s is a directory", abspath)
 	}
 	return fi.file.Open()
 }
 
-func (fs *zipFS) Lstat(abspath string) (FileInfo, os.Error) {
+func (fs *zipFS) Lstat(abspath string) (os.FileInfo, error) {
 	_, fi, err := fs.stat(zipPath(abspath))
 	return fi, err
 }
 
-func (fs *zipFS) Stat(abspath string) (FileInfo, os.Error) {
+func (fs *zipFS) Stat(abspath string) (os.FileInfo, error) {
 	_, fi, err := fs.stat(zipPath(abspath))
 	return fi, err
 }
 
-func (fs *zipFS) ReadDir(abspath string) ([]FileInfo, os.Error) {
+func (fs *zipFS) ReadDir(abspath string) ([]os.FileInfo, error) {
 	path := zipPath(abspath)
 	i, fi, err := fs.stat(path)
 	if err != nil {
 		return nil, err
 	}
-	if !fi.IsDirectory() {
+	if !fi.IsDir() {
 		return nil, fmt.Errorf("ReadDir: %s is not a directory", abspath)
 	}
 
-	var list []FileInfo
+	var list []os.FileInfo
 	dirname := path + "/"
 	prevname := ""
 	for _, e := range fs.list[i:] {
diff --git a/src/cmd/gofix/Makefile b/src/cmd/gofix/Makefile
index b2725c5..553f4f7 100644
--- a/src/cmd/gofix/Makefile
+++ b/src/cmd/gofix/Makefile
@@ -6,14 +6,27 @@ include ../../Make.inc
 
 TARG=gofix
 GOFILES=\
+	error.go\
 	filepath.go\
 	fix.go\
+	go1pkgrename.go\
+	googlecode.go\
+	hashsum.go\
+	hmacnew.go\
+	htmlerr.go\
 	httpfinalurl.go\
 	httpfs.go\
 	httpheaders.go\
 	httpserver.go\
+	httputil.go\
+	imagecolor.go\
 	imagenew.go\
+	imagetiled.go\
+	imageycbcr.go\
+	iocopyn.go\
 	main.go\
+	mapdelete.go\
+	math.go\
 	netdial.go\
 	netudpgroup.go\
 	oserrorstring.go\
@@ -23,9 +36,13 @@ GOFILES=\
 	signal.go\
 	sorthelpers.go\
 	sortslice.go\
+	strconv.go\
 	stringssplit.go\
+	template.go\
+	timefileinfo.go\
 	typecheck.go\
 	url.go\
+	xmlapi.go\
 
 include ../../Make.cmd
 
diff --git a/src/cmd/gofix/error.go b/src/cmd/gofix/error.go
new file mode 100644
index 0000000..5561321
--- /dev/null
+++ b/src/cmd/gofix/error.go
@@ -0,0 +1,353 @@
+// Copyright 2011 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 (
+	"go/ast"
+	"regexp"
+	"strings"
+)
+
+func init() {
+	register(errorFix)
+}
+
+var errorFix = fix{
+	"error",
+	"2011-11-02",
+	errorFn,
+	`Use error instead of os.Error.
+
+This fix rewrites code using os.Error to use error:
+
+	os.Error -> error
+	os.NewError -> errors.New
+	os.EOF -> io.EOF
+
+Seeing the old names above (os.Error and so on) triggers the following
+heuristic rewrites.  The heuristics can be forced using the -force=error flag.
+
+A top-level function, variable, or constant named error is renamed error_.
+
+Error implementations—those types used as os.Error or named
+XxxError—have their String methods renamed to Error.  Any existing
+Error field or method is renamed to Err.
+
+Error values—those with type os.Error or named e, err, error, err1,
+and so on—have method calls and field references rewritten just
+as the types do (String to Error, Error to Err).  Also, a type assertion
+of the form err.(*os.Waitmsg) becomes err.(*exec.ExitError).
+
+http://codereview.appspot.com/5305066
+`,
+}
+
+// At minimum, this fix applies the following rewrites:
+//
+//	os.Error -> error
+//	os.NewError -> errors.New
+//	os.EOF -> io.EOF
+//
+// However, if can apply any of those rewrites, it assumes that the
+// file predates the error type and tries to update the code to use
+// the new definition for error - an Error method, not a String method.
+// This more heuristic procedure may not be 100% accurate, so it is
+// only run when the file needs updating anyway.  The heuristic can
+// be forced to run using -force=error.
+//
+// First, we must identify the implementations of os.Error.
+// These include the type of any value returned as or assigned to an os.Error.
+// To that set we add any type whose name contains "Error" or "error".
+// The heuristic helps for implementations that are not used as os.Error
+// in the file in which they are defined.
+//
+// In any implementation of os.Error, we rename an existing struct field
+// or method named Error to Err and rename the String method to Error.
+//
+// Second, we must identify the values of type os.Error.
+// These include any value that obviously has type os.Error.
+// To that set we add any variable whose name is e or err or error
+// possibly followed by _ or a numeric or capitalized suffix.
+// The heuristic helps for variables that are initialized using calls
+// to functions in other packages.  The type checker does not have
+// information about those packages available, and in general cannot
+// (because the packages may themselves not compile).
+//
+// For any value of type os.Error, we replace a call to String with a call to Error.
+// We also replace type assertion err.(*os.Waitmsg) with err.(*exec.ExitError).
+
+// Variables matching this regexp are assumed to have type os.Error.
+var errVar = regexp.MustCompile(`^(e|err|error)_?([A-Z0-9].*)?$`)
+
+// Types matching this regexp are assumed to be implementations of os.Error.
+var errType = regexp.MustCompile(`^\*?([Ee]rror|.*Error)$`)
+
+// Type-checking configuration: tell the type-checker this basic
+// information about types, functions, and variables in external packages.
+var errorTypeConfig = &TypeConfig{
+	Type: map[string]*Type{
+		"os.Error": {},
+	},
+	Func: map[string]string{
+		"fmt.Errorf":  "os.Error",
+		"os.NewError": "os.Error",
+	},
+	Var: map[string]string{
+		"os.EPERM":        "os.Error",
+		"os.ENOENT":       "os.Error",
+		"os.ESRCH":        "os.Error",
+		"os.EINTR":        "os.Error",
+		"os.EIO":          "os.Error",
+		"os.ENXIO":        "os.Error",
+		"os.E2BIG":        "os.Error",
+		"os.ENOEXEC":      "os.Error",
+		"os.EBADF":        "os.Error",
+		"os.ECHILD":       "os.Error",
+		"os.EDEADLK":      "os.Error",
+		"os.ENOMEM":       "os.Error",
+		"os.EACCES":       "os.Error",
+		"os.EFAULT":       "os.Error",
+		"os.EBUSY":        "os.Error",
+		"os.EEXIST":       "os.Error",
+		"os.EXDEV":        "os.Error",
+		"os.ENODEV":       "os.Error",
+		"os.ENOTDIR":      "os.Error",
+		"os.EISDIR":       "os.Error",
+		"os.EINVAL":       "os.Error",
+		"os.ENFILE":       "os.Error",
+		"os.EMFILE":       "os.Error",
+		"os.ENOTTY":       "os.Error",
+		"os.EFBIG":        "os.Error",
+		"os.ENOSPC":       "os.Error",
+		"os.ESPIPE":       "os.Error",
+		"os.EROFS":        "os.Error",
+		"os.EMLINK":       "os.Error",
+		"os.EPIPE":        "os.Error",
+		"os.EAGAIN":       "os.Error",
+		"os.EDOM":         "os.Error",
+		"os.ERANGE":       "os.Error",
+		"os.EADDRINUSE":   "os.Error",
+		"os.ECONNREFUSED": "os.Error",
+		"os.ENAMETOOLONG": "os.Error",
+		"os.EAFNOSUPPORT": "os.Error",
+		"os.ETIMEDOUT":    "os.Error",
+		"os.ENOTCONN":     "os.Error",
+	},
+}
+
+func errorFn(f *ast.File) bool {
+	if !imports(f, "os") && !force["error"] {
+		return false
+	}
+
+	// Fix gets called once to run the heuristics described above
+	// when we notice that this file definitely needs fixing
+	// (it mentions os.Error or something similar).
+	var fixed bool
+	var didHeuristic bool
+	heuristic := func() {
+		if didHeuristic {
+			return
+		}
+		didHeuristic = true
+
+		// We have identified a necessary fix (like os.Error -> error)
+		// but have not applied it or any others yet.  Prepare the file
+		// for fixing and apply heuristic fixes.
+
+		// Rename error to error_ to make room for error.
+		fixed = renameTop(f, "error", "error_") || fixed
+
+		// Use type checker to build list of error implementations.
+		typeof, assign := typecheck(errorTypeConfig, f)
+
+		isError := map[string]bool{}
+		for _, val := range assign["os.Error"] {
+			t := typeof[val]
+			if strings.HasPrefix(t, "*") {
+				t = t[1:]
+			}
+			if t != "" && !strings.HasPrefix(t, "func(") {
+				isError[t] = true
+			}
+		}
+
+		// We use both the type check results and the "Error" name heuristic
+		// to identify implementations of os.Error.
+		isErrorImpl := func(typ string) bool {
+			return isError[typ] || errType.MatchString(typ)
+		}
+
+		isErrorVar := func(x ast.Expr) bool {
+			if typ := typeof[x]; typ != "" {
+				return isErrorImpl(typ) || typ == "os.Error"
+			}
+			if sel, ok := x.(*ast.SelectorExpr); ok {
+				return sel.Sel.Name == "Error" || sel.Sel.Name == "Err"
+			}
+			if id, ok := x.(*ast.Ident); ok {
+				return errVar.MatchString(id.Name)
+			}
+			return false
+		}
+
+		walk(f, func(n interface{}) {
+			// In method declaration on error implementation type,
+			// rename String() to Error() and Error() to Err().
+			fn, ok := n.(*ast.FuncDecl)
+			if ok &&
+				fn.Recv != nil &&
+				len(fn.Recv.List) == 1 &&
+				isErrorImpl(typeName(fn.Recv.List[0].Type)) {
+				// Rename.
+				switch fn.Name.Name {
+				case "String":
+					fn.Name.Name = "Error"
+					fixed = true
+				case "Error":
+					fn.Name.Name = "Err"
+					fixed = true
+				}
+				return
+			}
+
+			// In type definition of an error implementation type,
+			// rename Error field to Err to make room for method.
+			// Given type XxxError struct { ... Error T } rename field to Err.
+			d, ok := n.(*ast.GenDecl)
+			if ok {
+				for _, s := range d.Specs {
+					switch s := s.(type) {
+					case *ast.TypeSpec:
+						if isErrorImpl(typeName(s.Name)) {
+							st, ok := s.Type.(*ast.StructType)
+							if ok {
+								for _, f := range st.Fields.List {
+									for _, n := range f.Names {
+										if n.Name == "Error" {
+											n.Name = "Err"
+											fixed = true
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+
+			// For values that are an error implementation type,
+			// rename .Error to .Err and .String to .Error
+			sel, selok := n.(*ast.SelectorExpr)
+			if selok && isErrorImpl(typeof[sel.X]) {
+				switch sel.Sel.Name {
+				case "Error":
+					sel.Sel.Name = "Err"
+					fixed = true
+				case "String":
+					sel.Sel.Name = "Error"
+					fixed = true
+				}
+			}
+
+			// Assume x.Err is an error value and rename .String to .Error
+			// Children have been processed so the rewrite from Error to Err
+			// has already happened there.
+			if selok {
+				if subsel, ok := sel.X.(*ast.SelectorExpr); ok && subsel.Sel.Name == "Err" && sel.Sel.Name == "String" {
+					sel.Sel.Name = "Error"
+					fixed = true
+				}
+			}
+
+			// For values that are an error variable, rename .String to .Error.
+			if selok && isErrorVar(sel.X) && sel.Sel.Name == "String" {
+				sel.Sel.Name = "Error"
+				fixed = true
+			}
+
+			// Rewrite composite literal of error type to turn Error: into Err:.
+			lit, ok := n.(*ast.CompositeLit)
+			if ok && isErrorImpl(typeof[lit]) {
+				for _, e := range lit.Elts {
+					if kv, ok := e.(*ast.KeyValueExpr); ok && isName(kv.Key, "Error") {
+						kv.Key.(*ast.Ident).Name = "Err"
+						fixed = true
+					}
+				}
+			}
+
+			// Rename os.Waitmsg to exec.ExitError
+			// when used in a type assertion on an error.
+			ta, ok := n.(*ast.TypeAssertExpr)
+			if ok && isErrorVar(ta.X) && isPtrPkgDot(ta.Type, "os", "Waitmsg") {
+				addImport(f, "exec")
+				sel := ta.Type.(*ast.StarExpr).X.(*ast.SelectorExpr)
+				sel.X.(*ast.Ident).Name = "exec"
+				sel.Sel.Name = "ExitError"
+				fixed = true
+			}
+
+		})
+	}
+
+	fix := func() {
+		if fixed {
+			return
+		}
+		fixed = true
+		heuristic()
+	}
+
+	if force["error"] {
+		heuristic()
+	}
+
+	walk(f, func(n interface{}) {
+		p, ok := n.(*ast.Expr)
+		if !ok {
+			return
+		}
+		sel, ok := (*p).(*ast.SelectorExpr)
+		if !ok {
+			return
+		}
+		switch {
+		case isPkgDot(sel, "os", "Error"):
+			fix()
+			*p = &ast.Ident{NamePos: sel.Pos(), Name: "error"}
+		case isPkgDot(sel, "os", "NewError"):
+			fix()
+			addImport(f, "errors")
+			sel.X.(*ast.Ident).Name = "errors"
+			sel.Sel.Name = "New"
+		case isPkgDot(sel, "os", "EOF"):
+			fix()
+			addImport(f, "io")
+			sel.X.(*ast.Ident).Name = "io"
+		}
+	})
+
+	if fixed && !usesImport(f, "os") {
+		deleteImport(f, "os")
+	}
+
+	return fixed
+}
+
+func typeName(typ ast.Expr) string {
+	if p, ok := typ.(*ast.StarExpr); ok {
+		typ = p.X
+	}
+	id, ok := typ.(*ast.Ident)
+	if ok {
+		return id.Name
+	}
+	sel, ok := typ.(*ast.SelectorExpr)
+	if ok {
+		return typeName(sel.X) + "." + sel.Sel.Name
+	}
+	return ""
+}
diff --git a/src/cmd/gofix/error_test.go b/src/cmd/gofix/error_test.go
new file mode 100644
index 0000000..eeab7e2
--- /dev/null
+++ b/src/cmd/gofix/error_test.go
@@ -0,0 +1,232 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(errorTests, errorFn)
+}
+
+var errorTests = []testCase{
+	{
+		Name: "error.0",
+		In: `package main
+
+func error() {}
+
+var error int
+`,
+		Out: `package main
+
+func error() {}
+
+var error int
+`,
+	},
+	{
+		Name: "error.1",
+		In: `package main
+
+import "os"
+
+func f() os.Error {
+	return os.EOF
+}
+
+func error() {}
+
+var error int
+
+func g() {
+	error := 1
+	_ = error
+}
+`,
+		Out: `package main
+
+import "io"
+
+func f() error {
+	return io.EOF
+}
+
+func error_() {}
+
+var error_ int
+
+func g() {
+	error := 1
+	_ = error
+}
+`,
+	},
+	{
+		Name: "error.2",
+		In: `package main
+
+import "os"
+
+func f() os.Error {
+	return os.EOF
+}
+
+func g() string {
+	// these all convert because f is known
+	if err := f(); err != nil {
+		return err.String()
+	}
+	if err1 := f(); err1 != nil {
+		return err1.String()
+	}
+	if e := f(); e != nil {
+		return e.String()
+	}
+	if x := f(); x != nil {
+		return x.String()
+	}
+
+	// only the error names (err, err1, e) convert; u is not known
+	if err := u(); err != nil {
+		return err.String()
+	}
+	if err1 := u(); err1 != nil {
+		return err1.String()
+	}
+	if e := u(); e != nil {
+		return e.String()
+	}
+	if x := u(); x != nil {
+		return x.String()
+	}
+	return ""
+}
+
+type T int
+
+func (t T) String() string { return "t" }
+
+type PT int
+
+func (p *PT) String() string { return "pt" }
+
+type MyError int
+
+func (t MyError) String() string { return "myerror" }
+
+type PMyError int
+
+func (p *PMyError) String() string { return "pmyerror" }
+
+func error() {}
+
+var error int
+`,
+		Out: `package main
+
+import "io"
+
+func f() error {
+	return io.EOF
+}
+
+func g() string {
+	// these all convert because f is known
+	if err := f(); err != nil {
+		return err.Error()
+	}
+	if err1 := f(); err1 != nil {
+		return err1.Error()
+	}
+	if e := f(); e != nil {
+		return e.Error()
+	}
+	if x := f(); x != nil {
+		return x.Error()
+	}
+
+	// only the error names (err, err1, e) convert; u is not known
+	if err := u(); err != nil {
+		return err.Error()
+	}
+	if err1 := u(); err1 != nil {
+		return err1.Error()
+	}
+	if e := u(); e != nil {
+		return e.Error()
+	}
+	if x := u(); x != nil {
+		return x.String()
+	}
+	return ""
+}
+
+type T int
+
+func (t T) String() string { return "t" }
+
+type PT int
+
+func (p *PT) String() string { return "pt" }
+
+type MyError int
+
+func (t MyError) Error() string { return "myerror" }
+
+type PMyError int
+
+func (p *PMyError) Error() string { return "pmyerror" }
+
+func error_() {}
+
+var error_ int
+`,
+	},
+	{
+		Name: "error.3",
+		In: `package main
+
+import "os"
+
+func f() os.Error {
+	return os.EOF
+}
+
+type PathError struct {
+	Name  string
+	Error os.Error
+}
+
+func (p *PathError) String() string {
+	return p.Name + ": " + p.Error.String()
+}
+
+func (p *PathError) Error1() string {
+	p = &PathError{Error: nil}
+	return fmt.Sprint(p.Name, ": ", p.Error)
+}
+`,
+		Out: `package main
+
+import "io"
+
+func f() error {
+	return io.EOF
+}
+
+type PathError struct {
+	Name string
+	Err  error
+}
+
+func (p *PathError) Error() string {
+	return p.Name + ": " + p.Err.Error()
+}
+
+func (p *PathError) Error1() string {
+	p = &PathError{Err: nil}
+	return fmt.Sprint(p.Name, ": ", p.Err)
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/filepath.go b/src/cmd/gofix/filepath.go
index 1d0ad68..f312260 100644
--- a/src/cmd/gofix/filepath.go
+++ b/src/cmd/gofix/filepath.go
@@ -9,14 +9,17 @@ import (
 )
 
 func init() {
-	register(fix{
-		"filepath",
-		filepathFunc,
-		`Adapt code from filepath.[List]SeparatorString to string(filepath.[List]Separator).
+	register(filepathFix)
+}
+
+var filepathFix = fix{
+	"filepath",
+	"2011-06-26",
+	filepathFunc,
+	`Adapt code from filepath.[List]SeparatorString to string(filepath.[List]Separator).
 
 http://codereview.appspot.com/4527090
 `,
-	})
 }
 
 func filepathFunc(f *ast.File) (fixed bool) {
diff --git a/src/cmd/gofix/filepath_test.go b/src/cmd/gofix/filepath_test.go
index d170c3a..37a2f5d 100644
--- a/src/cmd/gofix/filepath_test.go
+++ b/src/cmd/gofix/filepath_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(filepathTests)
+	addTestCases(filepathTests, filepathFunc)
 }
 
 var filepathTests = []testCase{
diff --git a/src/cmd/gofix/fix.go b/src/cmd/gofix/fix.go
index cc85cea..d1a7bc8 100644
--- a/src/cmd/gofix/fix.go
+++ b/src/cmd/gofix/fix.go
@@ -4,29 +4,47 @@
 
 package main
 
+/*
+receiver named error
+function named error
+method on error
+exiterror
+slice of named type (go/scanner)
+*/
+
 import (
 	"fmt"
 	"go/ast"
+	"go/parser"
 	"go/token"
 	"os"
+	"path"
 	"strconv"
 	"strings"
 )
 
 type fix struct {
 	name string
+	date string // date that fix was introduced, in YYYY-MM-DD format
 	f    func(*ast.File) bool
 	desc string
 }
 
-// main runs sort.Sort(fixes) after init process is done.
-type fixlist []fix
+// main runs sort.Sort(byName(fixes)) before printing list of fixes.
+type byName []fix
+
+func (f byName) Len() int           { return len(f) }
+func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
+func (f byName) Less(i, j int) bool { return f[i].name < f[j].name }
+
+// main runs sort.Sort(byDate(fixes)) before applying fixes.
+type byDate []fix
 
-func (f fixlist) Len() int           { return len(f) }
-func (f fixlist) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
-func (f fixlist) Less(i, j int) bool { return f[i].name < f[j].name }
+func (f byDate) Len() int           { return len(f) }
+func (f byDate) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
+func (f byDate) Less(i, j int) bool { return f[i].date < f[j].date }
 
-var fixes fixlist
+var fixes []fix
 
 func register(f fix) {
 	fixes = append(fixes, f)
@@ -73,6 +91,8 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) {
 		walkBeforeAfter(*n, before, after)
 	case **ast.Ident:
 		walkBeforeAfter(*n, before, after)
+	case **ast.BasicLit:
+		walkBeforeAfter(*n, before, after)
 
 	// pointers to slices
 	case *[]ast.Decl:
@@ -90,7 +110,9 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) {
 
 	// These are ordered and grouped to match ../../pkg/go/ast/ast.go
 	case *ast.Field:
+		walkBeforeAfter(&n.Names, before, after)
 		walkBeforeAfter(&n.Type, before, after)
+		walkBeforeAfter(&n.Tag, before, after)
 	case *ast.FieldList:
 		for _, field := range n.List {
 			walkBeforeAfter(field, before, after)
@@ -292,6 +314,20 @@ func importPath(s *ast.ImportSpec) string {
 	return ""
 }
 
+// declImports reports whether gen contains an import of path.
+func declImports(gen *ast.GenDecl, path string) bool {
+	if gen.Tok != token.IMPORT {
+		return false
+	}
+	for _, spec := range gen.Specs {
+		impspec := spec.(*ast.ImportSpec)
+		if importPath(impspec) == path {
+			return true
+		}
+	}
+	return false
+}
+
 // isPkgDot returns true if t is the expression "pkg.name"
 // where pkg is an imported identifier.
 func isPkgDot(t ast.Expr, pkg, name string) bool {
@@ -446,66 +482,172 @@ func newPkgDot(pos token.Pos, pkg, name string) ast.Expr {
 	}
 }
 
+// renameTop renames all references to the top-level name old.
+// It returns true if it makes any changes.
+func renameTop(f *ast.File, old, new string) bool {
+	var fixed bool
+
+	// Rename any conflicting imports
+	// (assuming package name is last element of path).
+	for _, s := range f.Imports {
+		if s.Name != nil {
+			if s.Name.Name == old {
+				s.Name.Name = new
+				fixed = true
+			}
+		} else {
+			_, thisName := path.Split(importPath(s))
+			if thisName == old {
+				s.Name = ast.NewIdent(new)
+				fixed = true
+			}
+		}
+	}
+
+	// Rename any top-level declarations.
+	for _, d := range f.Decls {
+		switch d := d.(type) {
+		case *ast.FuncDecl:
+			if d.Recv == nil && d.Name.Name == old {
+				d.Name.Name = new
+				d.Name.Obj.Name = new
+				fixed = true
+			}
+		case *ast.GenDecl:
+			for _, s := range d.Specs {
+				switch s := s.(type) {
+				case *ast.TypeSpec:
+					if s.Name.Name == old {
+						s.Name.Name = new
+						s.Name.Obj.Name = new
+						fixed = true
+					}
+				case *ast.ValueSpec:
+					for _, n := range s.Names {
+						if n.Name == old {
+							n.Name = new
+							n.Obj.Name = new
+							fixed = true
+						}
+					}
+				}
+			}
+		}
+	}
+
+	// Rename top-level old to new, both unresolved names
+	// (probably defined in another file) and names that resolve
+	// to a declaration we renamed.
+	walk(f, func(n interface{}) {
+		id, ok := n.(*ast.Ident)
+		if ok && isTopName(id, old) {
+			id.Name = new
+			fixed = true
+		}
+		if ok && id.Obj != nil && id.Name == old && id.Obj.Name == new {
+			id.Name = id.Obj.Name
+			fixed = true
+		}
+	})
+
+	return fixed
+}
+
+// matchLen returns the length of the longest prefix shared by x and y.
+func matchLen(x, y string) int {
+	i := 0
+	for i < len(x) && i < len(y) && x[i] == y[i] {
+		i++
+	}
+	return i
+}
+
 // addImport adds the import path to the file f, if absent.
-func addImport(f *ast.File, path string) {
-	if imports(f, path) {
-		return
+func addImport(f *ast.File, ipath string) (added bool) {
+	if imports(f, ipath) {
+		return false
 	}
 
+	// Determine name of import.
+	// Assume added imports follow convention of using last element.
+	_, name := path.Split(ipath)
+
+	// Rename any conflicting top-level references from name to name_.
+	renameTop(f, name, name+"_")
+
 	newImport := &ast.ImportSpec{
 		Path: &ast.BasicLit{
 			Kind:  token.STRING,
-			Value: strconv.Quote(path),
+			Value: strconv.Quote(ipath),
 		},
 	}
 
-	var impdecl *ast.GenDecl
-
 	// Find an import decl to add to.
-	for _, decl := range f.Decls {
+	var (
+		bestMatch  = -1
+		lastImport = -1
+		impDecl    *ast.GenDecl
+		impIndex   = -1
+	)
+	for i, decl := range f.Decls {
 		gen, ok := decl.(*ast.GenDecl)
-
 		if ok && gen.Tok == token.IMPORT {
-			impdecl = gen
-			break
+			lastImport = i
+			// Do not add to import "C", to avoid disrupting the
+			// association with its doc comment, breaking cgo.
+			if declImports(gen, "C") {
+				continue
+			}
+
+			// Compute longest shared prefix with imports in this block.
+			for j, spec := range gen.Specs {
+				impspec := spec.(*ast.ImportSpec)
+				n := matchLen(importPath(impspec), ipath)
+				if n > bestMatch {
+					bestMatch = n
+					impDecl = gen
+					impIndex = j
+				}
+			}
 		}
 	}
 
-	// No import decl found.  Add one.
-	if impdecl == nil {
-		impdecl = &ast.GenDecl{
+	// If no import decl found, add one after the last import.
+	if impDecl == nil {
+		impDecl = &ast.GenDecl{
 			Tok: token.IMPORT,
 		}
 		f.Decls = append(f.Decls, nil)
-		copy(f.Decls[1:], f.Decls)
-		f.Decls[0] = impdecl
+		copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:])
+		f.Decls[lastImport+1] = impDecl
 	}
 
 	// Ensure the import decl has parentheses, if needed.
-	if len(impdecl.Specs) > 0 && !impdecl.Lparen.IsValid() {
-		impdecl.Lparen = impdecl.Pos()
+	if len(impDecl.Specs) > 0 && !impDecl.Lparen.IsValid() {
+		impDecl.Lparen = impDecl.Pos()
 	}
 
-	// Assume the import paths are alphabetically ordered.
-	// If they are not, the result is ugly, but legal.
-	insertAt := len(impdecl.Specs) // default to end of specs
-	for i, spec := range impdecl.Specs {
-		impspec := spec.(*ast.ImportSpec)
-		if importPath(impspec) > path {
-			insertAt = i
-			break
-		}
+	insertAt := impIndex + 1
+	if insertAt == 0 {
+		insertAt = len(impDecl.Specs)
+	}
+	impDecl.Specs = append(impDecl.Specs, nil)
+	copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:])
+	impDecl.Specs[insertAt] = newImport
+	if insertAt > 0 {
+		// Assign same position as the previous import,
+		// so that the sorter sees it as being in the same block.
+		prev := impDecl.Specs[insertAt-1]
+		newImport.Path.ValuePos = prev.Pos()
+		newImport.EndPos = prev.Pos()
 	}
-
-	impdecl.Specs = append(impdecl.Specs, nil)
-	copy(impdecl.Specs[insertAt+1:], impdecl.Specs[insertAt:])
-	impdecl.Specs[insertAt] = newImport
 
 	f.Imports = append(f.Imports, newImport)
+	return true
 }
 
 // deleteImport deletes the import path from the file f, if present.
-func deleteImport(f *ast.File, path string) {
+func deleteImport(f *ast.File, path string) (deleted bool) {
 	oldImport := importSpec(f, path)
 
 	// Find the import node that imports path, if any.
@@ -516,13 +658,13 @@ func deleteImport(f *ast.File, path string) {
 		}
 		for j, spec := range gen.Specs {
 			impspec := spec.(*ast.ImportSpec)
-
 			if oldImport != impspec {
 				continue
 			}
 
 			// We found an import spec that imports path.
 			// Delete it.
+			deleted = true
 			copy(gen.Specs[j:], gen.Specs[j+1:])
 			gen.Specs = gen.Specs[:len(gen.Specs)-1]
 
@@ -534,7 +676,13 @@ func deleteImport(f *ast.File, path string) {
 			} else if len(gen.Specs) == 1 {
 				gen.Lparen = token.NoPos // drop parens
 			}
-
+			if j > 0 {
+				// We deleted an entry but now there will be
+				// a blank line-sized hole where the import was.
+				// Close the hole by making the previous
+				// import appear to "end" where this one did.
+				gen.Specs[j-1].(*ast.ImportSpec).EndPos = impspec.End()
+			}
 			break
 		}
 	}
@@ -547,6 +695,22 @@ func deleteImport(f *ast.File, path string) {
 			break
 		}
 	}
+
+	return
+}
+
+// rewriteImport rewrites any import of path oldPath to path newPath.
+func rewriteImport(f *ast.File, oldPath, newPath string) (rewrote bool) {
+	for _, imp := range f.Imports {
+		if importPath(imp) == oldPath {
+			rewrote = true
+			// record old End, beacuse the default is to compute
+			// it using the length of imp.Path.Value.
+			imp.EndPos = imp.End()
+			imp.Path.Value = strconv.Quote(newPath)
+		}
+	}
+	return
 }
 
 func usesImport(f *ast.File, path string) (used bool) {
@@ -580,3 +744,11 @@ func usesImport(f *ast.File, path string) (used bool) {
 
 	return
 }
+
+func expr(s string) ast.Expr {
+	x, err := parser.ParseExpr(s)
+	if err != nil {
+		panic("parsing " + s + ": " + err.Error())
+	}
+	return x
+}
diff --git a/src/cmd/gofix/go1pkgrename.go b/src/cmd/gofix/go1pkgrename.go
new file mode 100644
index 0000000..7dc952d
--- /dev/null
+++ b/src/cmd/gofix/go1pkgrename.go
@@ -0,0 +1,119 @@
+// Copyright 2011 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 (
+	"go/ast"
+)
+
+func init() {
+	register(go1pkgrenameFix)
+}
+
+var go1pkgrenameFix = fix{
+	"go1rename",
+	"2011-11-08",
+	go1pkgrename,
+	`Rewrite imports for packages moved during transition to Go 1.
+
+http://codereview.appspot.com/5316078
+`,
+}
+
+var go1PackageRenames = []struct{ old, new string }{
+	{"asn1", "encoding/asn1"},
+	{"big", "math/big"},
+	{"cmath", "math/cmplx"},
+	{"csv", "encoding/csv"},
+	{"exec", "os/exec"},
+	{"exp/template/html", "html/template"},
+	{"gob", "encoding/gob"},
+	{"http", "net/http"},
+	{"http/cgi", "net/http/cgi"},
+	{"http/fcgi", "net/http/fcgi"},
+	{"http/httptest", "net/http/httptest"},
+	{"http/pprof", "net/http/pprof"},
+	{"json", "encoding/json"},
+	{"mail", "net/mail"},
+	{"rpc", "net/rpc"},
+	{"rpc/jsonrpc", "net/rpc/jsonrpc"},
+	{"scanner", "text/scanner"},
+	{"smtp", "net/smtp"},
+	{"syslog", "log/syslog"},
+	{"tabwriter", "text/tabwriter"},
+	{"template", "text/template"},
+	{"template/parse", "text/template/parse"},
+	{"rand", "math/rand"},
+	{"url", "net/url"},
+	{"utf16", "unicode/utf16"},
+	{"utf8", "unicode/utf8"},
+	{"xml", "encoding/xml"},
+
+	// go.crypto sub-repository
+	{"crypto/bcrypt", "code.google.com/p/go.crypto/bcrypt"},
+	{"crypto/blowfish", "code.google.com/p/go.crypto/blowfish"},
+	{"crypto/cast5", "code.google.com/p/go.crypto/cast5"},
+	{"crypto/md4", "code.google.com/p/go.crypto/md4"},
+	{"crypto/ocsp", "code.google.com/p/go.crypto/ocsp"},
+	{"crypto/openpgp", "code.google.com/p/go.crypto/openpgp"},
+	{"crypto/openpgp/armor", "code.google.com/p/go.crypto/openpgp/armor"},
+	{"crypto/openpgp/elgamal", "code.google.com/p/go.crypto/openpgp/elgamal"},
+	{"crypto/openpgp/errors", "code.google.com/p/go.crypto/openpgp/errors"},
+	{"crypto/openpgp/packet", "code.google.com/p/go.crypto/openpgp/packet"},
+	{"crypto/openpgp/s2k", "code.google.com/p/go.crypto/openpgp/s2k"},
+	{"crypto/ripemd160", "code.google.com/p/go.crypto/ripemd160"},
+	{"crypto/twofish", "code.google.com/p/go.crypto/twofish"},
+	{"crypto/xtea", "code.google.com/p/go.crypto/xtea"},
+	{"exp/ssh", "code.google.com/p/go.crypto/ssh"},
+
+	// go.net sub-repository
+	{"net/dict", "code.google.com/p/go.net/dict"},
+	{"net/websocket", "code.google.com/p/go.net/websocket"},
+	{"exp/spdy", "code.google.com/p/go.net/spdy"},
+
+	// go.codereview sub-repository
+	{"encoding/git85", "code.google.com/p/go.codereview/git85"},
+	{"patch", "code.google.com/p/go.codereview/patch"},
+}
+
+var go1PackageNameRenames = []struct{ newPath, old, new string }{
+	{"html/template", "html", "template"},
+	{"math/cmplx", "cmath", "cmplx"},
+}
+
+func go1pkgrename(f *ast.File) bool {
+	fixed := false
+
+	// First update the imports.
+	for _, rename := range go1PackageRenames {
+		if !imports(f, rename.old) {
+			continue
+		}
+		if rewriteImport(f, rename.old, rename.new) {
+			fixed = true
+		}
+	}
+	if !fixed {
+		return false
+	}
+
+	// Now update the package names used by importers.
+	for _, rename := range go1PackageNameRenames {
+		// These are rare packages, so do the import test before walking.
+		if imports(f, rename.newPath) {
+			walk(f, func(n interface{}) {
+				if sel, ok := n.(*ast.SelectorExpr); ok {
+					if isTopName(sel.X, rename.old) {
+						// We know Sel.X is an Ident.
+						sel.X.(*ast.Ident).Name = rename.new
+						return
+					}
+				}
+			})
+		}
+	}
+
+	return fixed
+}
diff --git a/src/cmd/gofix/go1pkgrename_test.go b/src/cmd/gofix/go1pkgrename_test.go
new file mode 100644
index 0000000..736e7ed
--- /dev/null
+++ b/src/cmd/gofix/go1pkgrename_test.go
@@ -0,0 +1,129 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(go1renameTests, go1pkgrename)
+}
+
+var go1renameTests = []testCase{
+	{
+		Name: "go1rename.0",
+		In: `package main
+
+import (
+	"asn1"
+	"big"
+	"cmath"
+	"csv"
+	"exec"
+	"exp/template/html"
+	"gob"
+	"http"
+	"http/cgi"
+	"http/fcgi"
+	"http/httptest"
+	"http/pprof"
+	"json"
+	"mail"
+	"rand"
+	"rpc"
+	"rpc/jsonrpc"
+	"scanner"
+	"smtp"
+	"syslog"
+	"tabwriter"
+	"template"
+	"template/parse"
+	"url"
+	"utf16"
+	"utf8"
+	"xml"
+
+	"crypto/bcrypt"
+)
+`,
+		Out: `package main
+
+import (
+	"encoding/asn1"
+	"encoding/csv"
+	"encoding/gob"
+	"encoding/json"
+	"encoding/xml"
+	"html/template"
+	"log/syslog"
+	"math/big"
+	"math/cmplx"
+	"math/rand"
+	"net/http"
+	"net/http/cgi"
+	"net/http/fcgi"
+	"net/http/httptest"
+	"net/http/pprof"
+	"net/mail"
+	"net/rpc"
+	"net/rpc/jsonrpc"
+	"net/smtp"
+	"net/url"
+	"os/exec"
+	"text/scanner"
+	"text/tabwriter"
+	"text/template"
+	"text/template/parse"
+	"unicode/utf16"
+	"unicode/utf8"
+
+	"code.google.com/p/go.crypto/bcrypt"
+)
+`,
+	},
+	{
+		Name: "go1rename.1",
+		In: `package main
+
+import "cmath"
+import poot "exp/template/html"
+
+var _ = cmath.Sin
+var _ = poot.Poot
+`,
+		Out: `package main
+
+import "math/cmplx"
+import poot "html/template"
+
+var _ = cmplx.Sin
+var _ = poot.Poot
+`,
+	},
+	{
+		Name: "go1rename.2",
+		In: `package foo
+
+import (
+	"fmt"
+	"http"
+	"url"
+
+	"google/secret/project/go"
+)
+
+func main() {}
+`,
+		Out: `package foo
+
+import (
+	"fmt"
+	"net/http"
+	"net/url"
+
+	"google/secret/project/go"
+)
+
+func main() {}
+`,
+	},
+}
diff --git a/src/cmd/gofix/googlecode.go b/src/cmd/gofix/googlecode.go
new file mode 100644
index 0000000..143781a
--- /dev/null
+++ b/src/cmd/gofix/googlecode.go
@@ -0,0 +1,41 @@
+// Copyright 2011 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 (
+	"go/ast"
+	"regexp"
+)
+
+func init() {
+	register(googlecodeFix)
+}
+
+var googlecodeFix = fix{
+	"googlecode",
+	"2011-11-21",
+	googlecode,
+	`Rewrite Google Code imports from the deprecated form
+"foo.googlecode.com/vcs/path" to "code.google.com/p/foo/path".
+`,
+}
+
+var googlecodeRe = regexp.MustCompile(`^([a-z0-9\-]+)\.googlecode\.com/(svn|git|hg)(/[a-z0-9A-Z_.\-/]+)?$`)
+
+func googlecode(f *ast.File) bool {
+	fixed := false
+
+	for _, s := range f.Imports {
+		old := importPath(s)
+		if m := googlecodeRe.FindStringSubmatch(old); m != nil {
+			new := "code.google.com/p/" + m[1] + m[3]
+			if rewriteImport(f, old, new) {
+				fixed = true
+			}
+		}
+	}
+
+	return fixed
+}
diff --git a/src/cmd/gofix/googlecode_test.go b/src/cmd/gofix/googlecode_test.go
new file mode 100644
index 0000000..c62ee4f
--- /dev/null
+++ b/src/cmd/gofix/googlecode_test.go
@@ -0,0 +1,31 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(googlecodeTests, googlecode)
+}
+
+var googlecodeTests = []testCase{
+	{
+		Name: "googlecode.0",
+		In: `package main
+
+import (
+	"foo.googlecode.com/hg/bar"
+	"go-qux-23.googlecode.com/svn"
+	"zap.googlecode.com/git/some/path"
+)
+`,
+		Out: `package main
+
+import (
+	"code.google.com/p/foo/bar"
+	"code.google.com/p/go-qux-23"
+	"code.google.com/p/zap/some/path"
+)
+`,
+	},
+}
diff --git a/src/cmd/gofix/hashsum.go b/src/cmd/gofix/hashsum.go
new file mode 100644
index 0000000..0df6ad7
--- /dev/null
+++ b/src/cmd/gofix/hashsum.go
@@ -0,0 +1,94 @@
+// Copyright 2011 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 (
+	"go/ast"
+)
+
+func init() {
+	register(hashSumFix)
+}
+
+var hashSumFix = fix{
+	"hashsum",
+	"2011-11-30",
+	hashSumFn,
+	`Pass a nil argument to calls to hash.Sum
+
+This fix rewrites code so that it passes a nil argument to hash.Sum.
+The additional argument will allow callers to avoid an
+allocation in the future.
+
+http://codereview.appspot.com/5448065
+`,
+}
+
+// Type-checking configuration: tell the type-checker this basic
+// information about types, functions, and variables in external packages.
+var hashSumTypeConfig = &TypeConfig{
+	Var: map[string]string{
+		"crypto.MD4":       "crypto.Hash",
+		"crypto.MD5":       "crypto.Hash",
+		"crypto.SHA1":      "crypto.Hash",
+		"crypto.SHA224":    "crypto.Hash",
+		"crypto.SHA256":    "crypto.Hash",
+		"crypto.SHA384":    "crypto.Hash",
+		"crypto.SHA512":    "crypto.Hash",
+		"crypto.MD5SHA1":   "crypto.Hash",
+		"crypto.RIPEMD160": "crypto.Hash",
+	},
+
+	Func: map[string]string{
+		"adler32.New":    "hash.Hash",
+		"crc32.New":      "hash.Hash",
+		"crc32.NewIEEE":  "hash.Hash",
+		"crc64.New":      "hash.Hash",
+		"fnv.New32a":     "hash.Hash",
+		"fnv.New32":      "hash.Hash",
+		"fnv.New64a":     "hash.Hash",
+		"fnv.New64":      "hash.Hash",
+		"hmac.New":       "hash.Hash",
+		"hmac.NewMD5":    "hash.Hash",
+		"hmac.NewSHA1":   "hash.Hash",
+		"hmac.NewSHA256": "hash.Hash",
+		"md4.New":        "hash.Hash",
+		"md5.New":        "hash.Hash",
+		"ripemd160.New":  "hash.Hash",
+		"sha1.New224":    "hash.Hash",
+		"sha1.New":       "hash.Hash",
+		"sha256.New224":  "hash.Hash",
+		"sha256.New":     "hash.Hash",
+		"sha512.New384":  "hash.Hash",
+		"sha512.New":     "hash.Hash",
+	},
+
+	Type: map[string]*Type{
+		"crypto.Hash": {
+			Method: map[string]string{
+				"New": "func() hash.Hash",
+			},
+		},
+	},
+}
+
+func hashSumFn(f *ast.File) bool {
+	typeof, _ := typecheck(hashSumTypeConfig, f)
+
+	fixed := false
+
+	walk(f, func(n interface{}) {
+		call, ok := n.(*ast.CallExpr)
+		if ok && len(call.Args) == 0 {
+			sel, ok := call.Fun.(*ast.SelectorExpr)
+			if ok && sel.Sel.Name == "Sum" && typeof[sel.X] == "hash.Hash" {
+				call.Args = append(call.Args, ast.NewIdent("nil"))
+				fixed = true
+			}
+		}
+	})
+
+	return fixed
+}
diff --git a/src/cmd/gofix/hashsum_test.go b/src/cmd/gofix/hashsum_test.go
new file mode 100644
index 0000000..241af20
--- /dev/null
+++ b/src/cmd/gofix/hashsum_test.go
@@ -0,0 +1,99 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(hashSumTests, hashSumFn)
+}
+
+var hashSumTests = []testCase{
+	{
+		Name: "hashsum.0",
+		In: `package main
+
+import "crypto/sha256"
+
+func f() []byte {
+	h := sha256.New()
+	return h.Sum()
+}
+`,
+		Out: `package main
+
+import "crypto/sha256"
+
+func f() []byte {
+	h := sha256.New()
+	return h.Sum(nil)
+}
+`,
+	},
+
+	{
+		Name: "hashsum.1",
+		In: `package main
+
+func f(h hash.Hash) []byte {
+	return h.Sum()
+}
+`,
+		Out: `package main
+
+func f(h hash.Hash) []byte {
+	return h.Sum(nil)
+}
+`,
+	},
+
+	{
+		Name: "hashsum.0",
+		In: `package main
+
+import "crypto/sha256"
+
+func f() []byte {
+	h := sha256.New()
+	h.Write([]byte("foo"))
+	digest := h.Sum()
+}
+`,
+		Out: `package main
+
+import "crypto/sha256"
+
+func f() []byte {
+	h := sha256.New()
+	h.Write([]byte("foo"))
+	digest := h.Sum(nil)
+}
+`,
+	},
+
+	{
+		Name: "hashsum.0",
+		In: `package main
+
+import _ "crypto/sha256"
+import "crypto"
+
+func f() []byte {
+	hashType := crypto.SHA256
+	h := hashType.New()
+	digest := h.Sum()
+}
+`,
+		Out: `package main
+
+import _ "crypto/sha256"
+import "crypto"
+
+func f() []byte {
+	hashType := crypto.SHA256
+	h := hashType.New()
+	digest := h.Sum(nil)
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/hmacnew.go b/src/cmd/gofix/hmacnew.go
new file mode 100644
index 0000000..c0c44ef
--- /dev/null
+++ b/src/cmd/gofix/hmacnew.go
@@ -0,0 +1,61 @@
+// Copyright 2011 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 "go/ast"
+
+func init() {
+	register(hmacNewFix)
+}
+
+var hmacNewFix = fix{
+	"hmacnew",
+	"2012-01-19",
+	hmacnew,
+	`Deprecate hmac.NewMD5, hmac.NewSHA1 and hmac.NewSHA256.
+
+This fix rewrites code using hmac.NewMD5, hmac.NewSHA1 and hmac.NewSHA256 to
+use hmac.New:
+
+	hmac.NewMD5(key) -> hmac.New(md5.New, key)
+	hmac.NewSHA1(key) -> hmac.New(sha1.New, key)
+	hmac.NewSHA256(key) -> hmac.New(sha256.New, key)
+
+`,
+}
+
+func hmacnew(f *ast.File) (fixed bool) {
+	if !imports(f, "crypto/hmac") {
+		return
+	}
+
+	walk(f, func(n interface{}) {
+		ce, ok := n.(*ast.CallExpr)
+		if !ok {
+			return
+		}
+
+		var pkg string
+		switch {
+		case isPkgDot(ce.Fun, "hmac", "NewMD5"):
+			pkg = "md5"
+		case isPkgDot(ce.Fun, "hmac", "NewSHA1"):
+			pkg = "sha1"
+		case isPkgDot(ce.Fun, "hmac", "NewSHA256"):
+			pkg = "sha256"
+		default:
+			return
+		}
+
+		addImport(f, "crypto/"+pkg)
+
+		ce.Fun = ast.NewIdent("hmac.New")
+		ce.Args = append([]ast.Expr{ast.NewIdent(pkg + ".New")}, ce.Args...)
+
+		fixed = true
+	})
+
+	return
+}
diff --git a/src/cmd/gofix/hmacnew_test.go b/src/cmd/gofix/hmacnew_test.go
new file mode 100644
index 0000000..5aeee85
--- /dev/null
+++ b/src/cmd/gofix/hmacnew_test.go
@@ -0,0 +1,107 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(hmacNewTests, hmacnew)
+}
+
+var hmacNewTests = []testCase{
+	{
+		Name: "hmacnew.0",
+		In: `package main
+
+import "crypto/hmac"
+
+var f = hmac.NewSHA1([]byte("some key"))
+`,
+		Out: `package main
+
+import (
+	"crypto/hmac"
+	"crypto/sha1"
+)
+
+var f = hmac.New(sha1.New, []byte("some key"))
+`,
+	},
+	{
+		Name: "hmacnew.1",
+		In: `package main
+
+import "crypto/hmac"
+
+var key = make([]byte, 8)
+var f = hmac.NewSHA1(key)
+`,
+		Out: `package main
+
+import (
+	"crypto/hmac"
+	"crypto/sha1"
+)
+
+var key = make([]byte, 8)
+var f = hmac.New(sha1.New, key)
+`,
+	},
+	{
+		Name: "hmacnew.2",
+		In: `package main
+
+import "crypto/hmac"
+
+var f = hmac.NewMD5([]byte("some key"))
+`,
+		Out: `package main
+
+import (
+	"crypto/hmac"
+	"crypto/md5"
+)
+
+var f = hmac.New(md5.New, []byte("some key"))
+`,
+	},
+	{
+		Name: "hmacnew.3",
+		In: `package main
+
+import "crypto/hmac"
+
+var f = hmac.NewSHA256([]byte("some key"))
+`,
+		Out: `package main
+
+import (
+	"crypto/hmac"
+	"crypto/sha256"
+)
+
+var f = hmac.New(sha256.New, []byte("some key"))
+`,
+	},
+	{
+		Name: "hmacnew.4",
+		In: `package main
+
+import (
+	"crypto/hmac"
+	"crypto/sha1"
+)
+
+var f = hmac.New(sha1.New, []byte("some key"))
+`,
+		Out: `package main
+
+import (
+	"crypto/hmac"
+	"crypto/sha1"
+)
+
+var f = hmac.New(sha1.New, []byte("some key"))
+`,
+	},
+}
diff --git a/src/cmd/gofix/htmlerr.go b/src/cmd/gofix/htmlerr.go
new file mode 100644
index 0000000..b5105c8
--- /dev/null
+++ b/src/cmd/gofix/htmlerr.go
@@ -0,0 +1,47 @@
+// Copyright 2011 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 (
+	"go/ast"
+)
+
+func init() {
+	register(htmlerrFix)
+}
+
+var htmlerrFix = fix{
+	"htmlerr",
+	"2011-11-04",
+	htmlerr,
+	`Rename html's Tokenizer.Error method to Err.
+
+http://codereview.appspot.com/5327064/
+`,
+}
+
+var htmlerrTypeConfig = &TypeConfig{
+	Func: map[string]string{
+		"html.NewTokenizer": "html.Tokenizer",
+	},
+}
+
+func htmlerr(f *ast.File) bool {
+	if !imports(f, "html") {
+		return false
+	}
+
+	typeof, _ := typecheck(htmlerrTypeConfig, f)
+
+	fixed := false
+	walk(f, func(n interface{}) {
+		s, ok := n.(*ast.SelectorExpr)
+		if ok && typeof[s.X] == "html.Tokenizer" && s.Sel.Name == "Error" {
+			s.Sel.Name = "Err"
+			fixed = true
+		}
+	})
+	return fixed
+}
diff --git a/src/cmd/gofix/htmlerr_test.go b/src/cmd/gofix/htmlerr_test.go
new file mode 100644
index 0000000..043abc4
--- /dev/null
+++ b/src/cmd/gofix/htmlerr_test.go
@@ -0,0 +1,39 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(htmlerrTests, htmlerr)
+}
+
+var htmlerrTests = []testCase{
+	{
+		Name: "htmlerr.0",
+		In: `package main
+
+import (
+	"html"
+)
+
+func f() {
+	e := errors.New("")
+	t := html.NewTokenizer(r)
+	_, _ = e.Error(), t.Error()
+}
+`,
+		Out: `package main
+
+import (
+	"html"
+)
+
+func f() {
+	e := errors.New("")
+	t := html.NewTokenizer(r)
+	_, _ = e.Error(), t.Err()
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/httpfinalurl.go b/src/cmd/gofix/httpfinalurl.go
index 9e6cbf6..49b9f1c 100644
--- a/src/cmd/gofix/httpfinalurl.go
+++ b/src/cmd/gofix/httpfinalurl.go
@@ -8,8 +8,13 @@ import (
 	"go/ast"
 )
 
+func init() {
+	register(httpFinalURLFix)
+}
+
 var httpFinalURLFix = fix{
 	"httpfinalurl",
+	"2011-05-13",
 	httpfinalurl,
 	`Adapt http Get calls to not have a finalURL result parameter.
 
@@ -17,10 +22,6 @@ http://codereview.appspot.com/4535056/
 `,
 }
 
-func init() {
-	register(httpFinalURLFix)
-}
-
 func httpfinalurl(f *ast.File) bool {
 	if !imports(f, "http") {
 		return false
diff --git a/src/cmd/gofix/httpfinalurl_test.go b/src/cmd/gofix/httpfinalurl_test.go
index 9e7d624..9249f7e 100644
--- a/src/cmd/gofix/httpfinalurl_test.go
+++ b/src/cmd/gofix/httpfinalurl_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(httpfinalurlTests)
+	addTestCases(httpfinalurlTests, httpfinalurl)
 }
 
 var httpfinalurlTests = []testCase{
diff --git a/src/cmd/gofix/httpfs.go b/src/cmd/gofix/httpfs.go
index 7f27656..625dd0f 100644
--- a/src/cmd/gofix/httpfs.go
+++ b/src/cmd/gofix/httpfs.go
@@ -9,8 +9,13 @@ import (
 	"go/token"
 )
 
+func init() {
+	register(httpFileSystemFix)
+}
+
 var httpFileSystemFix = fix{
 	"httpfs",
+	"2011-06-27",
 	httpfs,
 	`Adapt http FileServer to take a FileSystem.
 
@@ -18,10 +23,6 @@ http://codereview.appspot.com/4629047  http FileSystem interface
 `,
 }
 
-func init() {
-	register(httpFileSystemFix)
-}
-
 func httpfs(f *ast.File) bool {
 	if !imports(f, "http") {
 		return false
diff --git a/src/cmd/gofix/httpfs_test.go b/src/cmd/gofix/httpfs_test.go
index d1804e9..dd8ef2c 100644
--- a/src/cmd/gofix/httpfs_test.go
+++ b/src/cmd/gofix/httpfs_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(httpFileSystemTests)
+	addTestCases(httpFileSystemTests, httpfs)
 }
 
 var httpFileSystemTests = []testCase{
diff --git a/src/cmd/gofix/httpheaders.go b/src/cmd/gofix/httpheaders.go
index 8a9080e..15c21ac 100644
--- a/src/cmd/gofix/httpheaders.go
+++ b/src/cmd/gofix/httpheaders.go
@@ -8,8 +8,13 @@ import (
 	"go/ast"
 )
 
+func init() {
+	register(httpHeadersFix)
+}
+
 var httpHeadersFix = fix{
 	"httpheaders",
+	"2011-06-16",
 	httpheaders,
 	`Rename http Referer, UserAgent, Cookie, SetCookie, which are now methods.
 
@@ -17,10 +22,6 @@ http://codereview.appspot.com/4620049/
 `,
 }
 
-func init() {
-	register(httpHeadersFix)
-}
-
 func httpheaders(f *ast.File) bool {
 	if !imports(f, "http") {
 		return false
@@ -35,7 +36,7 @@ func httpheaders(f *ast.File) bool {
 	})
 
 	fixed := false
-	typeof := typecheck(headerTypeConfig, f)
+	typeof, _ := typecheck(headerTypeConfig, f)
 	walk(f, func(ni interface{}) {
 		switch n := ni.(type) {
 		case *ast.SelectorExpr:
@@ -60,7 +61,7 @@ func httpheaders(f *ast.File) bool {
 
 var headerTypeConfig = &TypeConfig{
 	Type: map[string]*Type{
-		"*http.Request":  &Type{},
-		"*http.Response": &Type{},
+		"*http.Request":  {},
+		"*http.Response": {},
 	},
 }
diff --git a/src/cmd/gofix/httpheaders_test.go b/src/cmd/gofix/httpheaders_test.go
index cc82b58..37506b8 100644
--- a/src/cmd/gofix/httpheaders_test.go
+++ b/src/cmd/gofix/httpheaders_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(httpHeadersTests)
+	addTestCases(httpHeadersTests, httpheaders)
 }
 
 var httpHeadersTests = []testCase{
diff --git a/src/cmd/gofix/httpserver.go b/src/cmd/gofix/httpserver.go
index 37866e8..7aa6517 100644
--- a/src/cmd/gofix/httpserver.go
+++ b/src/cmd/gofix/httpserver.go
@@ -9,8 +9,13 @@ import (
 	"go/token"
 )
 
+func init() {
+	register(httpserverFix)
+}
+
 var httpserverFix = fix{
 	"httpserver",
+	"2011-03-15",
 	httpserver,
 	`Adapt http server methods and functions to changes
 made to the http ResponseWriter interface.
@@ -22,10 +27,6 @@ http://codereview.appspot.com/4248075  RemoteAddr, UsingTLS
 `,
 }
 
-func init() {
-	register(httpserverFix)
-}
-
 func httpserver(f *ast.File) bool {
 	if !imports(f, "http") {
 		return false
diff --git a/src/cmd/gofix/httpserver_test.go b/src/cmd/gofix/httpserver_test.go
index 89bb4fa..b6ddff2 100644
--- a/src/cmd/gofix/httpserver_test.go
+++ b/src/cmd/gofix/httpserver_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(httpserverTests)
+	addTestCases(httpserverTests, httpserver)
 }
 
 var httpserverTests = []testCase{
diff --git a/src/cmd/gofix/httputil.go b/src/cmd/gofix/httputil.go
new file mode 100644
index 0000000..86c42e1
--- /dev/null
+++ b/src/cmd/gofix/httputil.go
@@ -0,0 +1,63 @@
+// Copyright 2011 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 "go/ast"
+
+func init() {
+	register(httputilFix)
+}
+
+var httputilFix = fix{
+	"httputil",
+	"2011-11-18",
+	httputil,
+	`Move some functions in http package into httputil package.
+
+http://codereview.appspot.com/5336049
+`,
+}
+
+var httputilFuncs = []string{
+	"DumpRequest",
+	"DumpRequestOut",
+	"DumpResponse",
+	"NewChunkedReader",
+	"NewChunkedWriter",
+	"NewClientConn",
+	"NewProxyClientConn",
+	"NewServerConn",
+	"NewSingleHostReverseProxy",
+}
+
+func httputil(f *ast.File) bool {
+	if imports(f, "net/http/httputil") {
+		return false
+	}
+
+	fixed := false
+
+	walk(f, func(n interface{}) {
+		// Rename package name.
+		if expr, ok := n.(ast.Expr); ok {
+			for _, s := range httputilFuncs {
+				if isPkgDot(expr, "http", s) {
+					if !fixed {
+						addImport(f, "net/http/httputil")
+						fixed = true
+					}
+					expr.(*ast.SelectorExpr).X.(*ast.Ident).Name = "httputil"
+				}
+			}
+		}
+	})
+
+	// Remove the net/http import if no longer needed.
+	if fixed && !usesImport(f, "net/http") {
+		deleteImport(f, "net/http")
+	}
+
+	return fixed
+}
diff --git a/src/cmd/gofix/httputil_test.go b/src/cmd/gofix/httputil_test.go
new file mode 100644
index 0000000..83e9f6d
--- /dev/null
+++ b/src/cmd/gofix/httputil_test.go
@@ -0,0 +1,122 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(httputilTests, httputil)
+}
+
+var httputilTests = []testCase{
+	{
+		Name: "httputil.0",
+		In: `package main
+
+import "net/http"
+
+func f() {
+	http.DumpRequest(nil, false)
+	http.DumpRequestOut(nil, false)
+	http.DumpResponse(nil, false)
+	http.NewChunkedReader(nil)
+	http.NewChunkedWriter(nil)
+	http.NewClientConn(nil, nil)
+	http.NewProxyClientConn(nil, nil)
+	http.NewServerConn(nil, nil)
+	http.NewSingleHostReverseProxy(nil)
+}
+`,
+		Out: `package main
+
+import "net/http/httputil"
+
+func f() {
+	httputil.DumpRequest(nil, false)
+	httputil.DumpRequestOut(nil, false)
+	httputil.DumpResponse(nil, false)
+	httputil.NewChunkedReader(nil)
+	httputil.NewChunkedWriter(nil)
+	httputil.NewClientConn(nil, nil)
+	httputil.NewProxyClientConn(nil, nil)
+	httputil.NewServerConn(nil, nil)
+	httputil.NewSingleHostReverseProxy(nil)
+}
+`,
+	},
+	{
+		Name: "httputil.1",
+		In: `package main
+
+import "net/http"
+
+func f() {
+	http.DumpRequest(nil, false)
+	http.DumpRequestOut(nil, false)
+	http.DumpResponse(nil, false)
+	http.NewChunkedReader(nil)
+	http.NewChunkedWriter(nil)
+	http.NewClientConn(nil, nil)
+	http.NewProxyClientConn(nil, nil)
+	http.NewServerConn(nil, nil)
+	http.NewSingleHostReverseProxy(nil)
+}
+`,
+		Out: `package main
+
+import "net/http/httputil"
+
+func f() {
+	httputil.DumpRequest(nil, false)
+	httputil.DumpRequestOut(nil, false)
+	httputil.DumpResponse(nil, false)
+	httputil.NewChunkedReader(nil)
+	httputil.NewChunkedWriter(nil)
+	httputil.NewClientConn(nil, nil)
+	httputil.NewProxyClientConn(nil, nil)
+	httputil.NewServerConn(nil, nil)
+	httputil.NewSingleHostReverseProxy(nil)
+}
+`,
+	},
+	{
+		Name: "httputil.2",
+		In: `package main
+
+import "net/http"
+
+func f() {
+	http.DumpRequest(nil, false)
+	http.DumpRequestOut(nil, false)
+	http.DumpResponse(nil, false)
+	http.NewChunkedReader(nil)
+	http.NewChunkedWriter(nil)
+	http.NewClientConn(nil, nil)
+	http.NewProxyClientConn(nil, nil)
+	http.NewServerConn(nil, nil)
+	http.NewSingleHostReverseProxy(nil)
+	http.Get("")
+}
+`,
+		Out: `package main
+
+import (
+	"net/http"
+	"net/http/httputil"
+)
+
+func f() {
+	httputil.DumpRequest(nil, false)
+	httputil.DumpRequestOut(nil, false)
+	httputil.DumpResponse(nil, false)
+	httputil.NewChunkedReader(nil)
+	httputil.NewChunkedWriter(nil)
+	httputil.NewClientConn(nil, nil)
+	httputil.NewProxyClientConn(nil, nil)
+	httputil.NewServerConn(nil, nil)
+	httputil.NewSingleHostReverseProxy(nil)
+	http.Get("")
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/imagecolor.go b/src/cmd/gofix/imagecolor.go
new file mode 100644
index 0000000..1aac40a
--- /dev/null
+++ b/src/cmd/gofix/imagecolor.go
@@ -0,0 +1,85 @@
+// Copyright 2011 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 (
+	"go/ast"
+)
+
+func init() {
+	register(imagecolorFix)
+}
+
+var imagecolorFix = fix{
+	"imagecolor",
+	"2011-10-04",
+	imagecolor,
+	`Adapt code to types moved from image to color.
+
+http://codereview.appspot.com/5132048
+`,
+}
+
+var colorRenames = []struct{ in, out string }{
+	{"Color", "Color"},
+	{"ColorModel", "Model"},
+	{"ColorModelFunc", "ModelFunc"},
+	{"PalettedColorModel", "Palette"},
+
+	{"RGBAColor", "RGBA"},
+	{"RGBA64Color", "RGBA64"},
+	{"NRGBAColor", "NRGBA"},
+	{"NRGBA64Color", "NRGBA64"},
+	{"AlphaColor", "Alpha"},
+	{"Alpha16Color", "Alpha16"},
+	{"GrayColor", "Gray"},
+	{"Gray16Color", "Gray16"},
+
+	{"RGBAColorModel", "RGBAModel"},
+	{"RGBA64ColorModel", "RGBA64Model"},
+	{"NRGBAColorModel", "NRGBAModel"},
+	{"NRGBA64ColorModel", "NRGBA64Model"},
+	{"AlphaColorModel", "AlphaModel"},
+	{"Alpha16ColorModel", "Alpha16Model"},
+	{"GrayColorModel", "GrayModel"},
+	{"Gray16ColorModel", "Gray16Model"},
+}
+
+func imagecolor(f *ast.File) (fixed bool) {
+	if !imports(f, "image") {
+		return
+	}
+
+	walk(f, func(n interface{}) {
+		s, ok := n.(*ast.SelectorExpr)
+
+		if !ok || !isTopName(s.X, "image") {
+			return
+		}
+
+		switch sel := s.Sel.String(); {
+		case sel == "ColorImage":
+			s.Sel = &ast.Ident{Name: "Uniform"}
+			fixed = true
+		case sel == "NewColorImage":
+			s.Sel = &ast.Ident{Name: "NewUniform"}
+			fixed = true
+		default:
+			for _, rename := range colorRenames {
+				if sel == rename.in {
+					addImport(f, "image/color")
+					s.X.(*ast.Ident).Name = "color"
+					s.Sel.Name = rename.out
+					fixed = true
+				}
+			}
+		}
+	})
+
+	if fixed && !usesImport(f, "image") {
+		deleteImport(f, "image")
+	}
+	return
+}
diff --git a/src/cmd/gofix/imagecolor_test.go b/src/cmd/gofix/imagecolor_test.go
new file mode 100644
index 0000000..c623654
--- /dev/null
+++ b/src/cmd/gofix/imagecolor_test.go
@@ -0,0 +1,126 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(colorTests, imagecolor)
+}
+
+var colorTests = []testCase{
+	{
+		Name: "color.0",
+		In: `package main
+
+import (
+	"image"
+)
+
+var (
+	_ image.Image
+	_ image.RGBA
+	_ image.Black
+	_ image.Color
+	_ image.ColorModel
+	_ image.ColorModelFunc
+	_ image.PalettedColorModel
+	_ image.RGBAColor
+	_ image.RGBA64Color
+	_ image.NRGBAColor
+	_ image.NRGBA64Color
+	_ image.AlphaColor
+	_ image.Alpha16Color
+	_ image.GrayColor
+	_ image.Gray16Color
+)
+
+func f() {
+	_ = image.RGBAColorModel
+	_ = image.RGBA64ColorModel
+	_ = image.NRGBAColorModel
+	_ = image.NRGBA64ColorModel
+	_ = image.AlphaColorModel
+	_ = image.Alpha16ColorModel
+	_ = image.GrayColorModel
+	_ = image.Gray16ColorModel
+}
+`,
+		Out: `package main
+
+import (
+	"image"
+	"image/color"
+)
+
+var (
+	_ image.Image
+	_ image.RGBA
+	_ image.Black
+	_ color.Color
+	_ color.Model
+	_ color.ModelFunc
+	_ color.Palette
+	_ color.RGBA
+	_ color.RGBA64
+	_ color.NRGBA
+	_ color.NRGBA64
+	_ color.Alpha
+	_ color.Alpha16
+	_ color.Gray
+	_ color.Gray16
+)
+
+func f() {
+	_ = color.RGBAModel
+	_ = color.RGBA64Model
+	_ = color.NRGBAModel
+	_ = color.NRGBA64Model
+	_ = color.AlphaModel
+	_ = color.Alpha16Model
+	_ = color.GrayModel
+	_ = color.Gray16Model
+}
+`,
+	},
+	{
+		Name: "color.1",
+		In: `package main
+
+import (
+	"fmt"
+	"image"
+)
+
+func f() {
+	fmt.Println(image.RGBAColor{1, 2, 3, 4}.RGBA())
+}
+`,
+		Out: `package main
+
+import (
+	"fmt"
+	"image/color"
+)
+
+func f() {
+	fmt.Println(color.RGBA{1, 2, 3, 4}.RGBA())
+}
+`,
+	},
+	{
+		Name: "color.2",
+		In: `package main
+
+import "image"
+
+var c *image.ColorImage = image.NewColorImage(nil)
+`,
+		Out: `package main
+
+import "image"
+
+var c *image.Uniform = image.NewUniform(nil)
+`,
+	},
+}
diff --git a/src/cmd/gofix/imagenew.go b/src/cmd/gofix/imagenew.go
index 0b3c0a3..b4e36d4 100644
--- a/src/cmd/gofix/imagenew.go
+++ b/src/cmd/gofix/imagenew.go
@@ -8,8 +8,13 @@ import (
 	"go/ast"
 )
 
+func init() {
+	register(imagenewFix)
+}
+
 var imagenewFix = fix{
 	"imagenew",
+	"2011-09-14",
 	imagenew,
 	`Adapt image.NewXxx calls to pass an image.Rectangle instead of (w, h int).
 
@@ -17,10 +22,6 @@ http://codereview.appspot.com/4964073
 `,
 }
 
-func init() {
-	register(imagenewFix)
-}
-
 var imagenewFuncs = map[string]bool{
 	"NewRGBA":    true,
 	"NewRGBA64":  true,
diff --git a/src/cmd/gofix/imagenew_test.go b/src/cmd/gofix/imagenew_test.go
index 3d40fea..30abed2 100644
--- a/src/cmd/gofix/imagenew_test.go
+++ b/src/cmd/gofix/imagenew_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(imagenewTests)
+	addTestCases(imagenewTests, imagenew)
 }
 
 var imagenewTests = []testCase{
@@ -26,8 +26,7 @@ func f() {
 	image.NewAlpha16(1, 2)
 	image.NewGray(1, 2)
 	image.NewGray16(1, 2)
-	var m image.PalettedColorModel
-	image.NewPaletted(1, 2, m)
+	image.NewPaletted(1, 2, nil)
 }
 `,
 		Out: `package main
@@ -45,8 +44,7 @@ func f() {
 	image.NewAlpha16(image.Rect(0, 0, 1, 2))
 	image.NewGray(image.Rect(0, 0, 1, 2))
 	image.NewGray16(image.Rect(0, 0, 1, 2))
-	var m image.PalettedColorModel
-	image.NewPaletted(image.Rect(0, 0, 1, 2), m)
+	image.NewPaletted(image.Rect(0, 0, 1, 2), nil)
 }
 `,
 	},
diff --git a/src/cmd/gofix/imagetiled.go b/src/cmd/gofix/imagetiled.go
new file mode 100644
index 0000000..d8f3f79
--- /dev/null
+++ b/src/cmd/gofix/imagetiled.go
@@ -0,0 +1,40 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"go/ast"
+)
+
+func init() {
+	register(imagetiledFix)
+}
+
+var imagetiledFix = fix{
+	"imagetiled",
+	"2012-01-10",
+	imagetiled,
+	`Rename image.Tiled to image.Repeated.
+
+http://codereview.appspot.com/5530062
+`,
+}
+
+func imagetiled(f *ast.File) bool {
+	if !imports(f, "image") {
+		return false
+	}
+
+	fixed := false
+	walk(f, func(n interface{}) {
+		s, ok := n.(*ast.SelectorExpr)
+		if !ok || !isTopName(s.X, "image") || s.Sel.String() != "Tiled" {
+			return
+		}
+		s.Sel = &ast.Ident{Name: "Repeated"}
+		fixed = true
+	})
+	return fixed
+}
diff --git a/src/cmd/gofix/imagetiled_test.go b/src/cmd/gofix/imagetiled_test.go
new file mode 100644
index 0000000..98a9c0a
--- /dev/null
+++ b/src/cmd/gofix/imagetiled_test.go
@@ -0,0 +1,41 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func init() {
+	addTestCases(imagetiledTests, imagetiled)
+}
+
+var imagetiledTests = []testCase{
+	{
+		Name: "imagetiled.0",
+		In: `package main
+
+import (
+	"foo"
+	"image"
+)
+
+var (
+	_ foo.Tiled
+	_ image.RGBA
+	_ image.Tiled
+)
+`,
+		Out: `package main
+
+import (
+	"foo"
+	"image"
+)
+
+var (
+	_ foo.Tiled
+	_ image.RGBA
+	_ image.Repeated
+)
+`,
+	},
+}
diff --git a/src/cmd/gofix/imageycbcr.go b/src/cmd/gofix/imageycbcr.go
new file mode 100644
index 0000000..41b96d1
--- /dev/null
+++ b/src/cmd/gofix/imageycbcr.go
@@ -0,0 +1,64 @@
+// Copyright 2011 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 (
+	"go/ast"
+)
+
+func init() {
+	register(imageycbcrFix)
+}
+
+var imageycbcrFix = fix{
+	"imageycbcr",
+	"2011-12-20",
+	imageycbcr,
+	`Adapt code to types moved from image/ycbcr to image and image/color.
+
+http://codereview.appspot.com/5493084
+`,
+}
+
+func imageycbcr(f *ast.File) (fixed bool) {
+	if !imports(f, "image/ycbcr") {
+		return
+	}
+
+	walk(f, func(n interface{}) {
+		s, ok := n.(*ast.SelectorExpr)
+
+		if !ok || !isTopName(s.X, "ycbcr") {
+			return
+		}
+
+		switch s.Sel.String() {
+		case "RGBToYCbCr", "YCbCrToRGB":
+			addImport(f, "image/color")
+			s.X.(*ast.Ident).Name = "color"
+		case "YCbCrColor":
+			addImport(f, "image/color")
+			s.X.(*ast.Ident).Name = "color"
+			s.Sel.Name = "YCbCr"
+		case "YCbCrColorModel":
+			addImport(f, "image/color")
+			s.X.(*ast.Ident).Name = "color"
+			s.Sel.Name = "YCbCrModel"
+		case "SubsampleRatio", "SubsampleRatio444", "SubsampleRatio422", "SubsampleRatio420":
+			addImport(f, "image")
+			s.X.(*ast.Ident).Name = "image"
+			s.Sel.Name = "YCbCr" + s.Sel.Name
+		case "YCbCr":
+			addImport(f, "image")
+			s.X.(*ast.Ident).Name = "image"
+		default:
+			return
+		}
+		fixed = true
+	})
+
+	deleteImport(f, "image/ycbcr")
+	return
+}
diff --git a/src/cmd/gofix/imageycbcr_test.go b/src/cmd/gofix/imageycbcr_test.go
new file mode 100644
index 0000000..23b599d
--- /dev/null
+++ b/src/cmd/gofix/imageycbcr_test.go
@@ -0,0 +1,54 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(ycbcrTests, imageycbcr)
+}
+
+var ycbcrTests = []testCase{
+	{
+		Name: "ycbcr.0",
+		In: `package main
+
+import (
+	"image/ycbcr"
+)
+
+func f() {
+	_ = ycbcr.RGBToYCbCr
+	_ = ycbcr.YCbCrToRGB
+	_ = ycbcr.YCbCrColorModel
+	var _ ycbcr.YCbCrColor
+	var _ ycbcr.YCbCr
+	var (
+		_ ycbcr.SubsampleRatio = ycbcr.SubsampleRatio444
+		_ ycbcr.SubsampleRatio = ycbcr.SubsampleRatio422
+		_ ycbcr.SubsampleRatio = ycbcr.SubsampleRatio420
+	)
+}
+`,
+		Out: `package main
+
+import (
+	"image"
+	"image/color"
+)
+
+func f() {
+	_ = color.RGBToYCbCr
+	_ = color.YCbCrToRGB
+	_ = color.YCbCrModel
+	var _ color.YCbCr
+	var _ image.YCbCr
+	var (
+		_ image.YCbCrSubsampleRatio = image.YCbCrSubsampleRatio444
+		_ image.YCbCrSubsampleRatio = image.YCbCrSubsampleRatio422
+		_ image.YCbCrSubsampleRatio = image.YCbCrSubsampleRatio420
+	)
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/import_test.go b/src/cmd/gofix/import_test.go
new file mode 100644
index 0000000..7301192
--- /dev/null
+++ b/src/cmd/gofix/import_test.go
@@ -0,0 +1,458 @@
+// Copyright 2011 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 "go/ast"
+
+func init() {
+	addTestCases(importTests, nil)
+}
+
+var importTests = []testCase{
+	{
+		Name: "import.0",
+		Fn:   addImportFn("os"),
+		In: `package main
+
+import (
+	"os"
+)
+`,
+		Out: `package main
+
+import (
+	"os"
+)
+`,
+	},
+	{
+		Name: "import.1",
+		Fn:   addImportFn("os"),
+		In: `package main
+`,
+		Out: `package main
+
+import "os"
+`,
+	},
+	{
+		Name: "import.2",
+		Fn:   addImportFn("os"),
+		In: `package main
+
+// Comment
+import "C"
+`,
+		Out: `package main
+
+// Comment
+import "C"
+import "os"
+`,
+	},
+	{
+		Name: "import.3",
+		Fn:   addImportFn("os"),
+		In: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"utf8"
+)
+`,
+		Out: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+	},
+	{
+		Name: "import.4",
+		Fn:   deleteImportFn("os"),
+		In: `package main
+
+import (
+	"os"
+)
+`,
+		Out: `package main
+`,
+	},
+	{
+		Name: "import.5",
+		Fn:   deleteImportFn("os"),
+		In: `package main
+
+// Comment
+import "C"
+import "os"
+`,
+		Out: `package main
+
+// Comment
+import "C"
+`,
+	},
+	{
+		Name: "import.6",
+		Fn:   deleteImportFn("os"),
+		In: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		Out: `package main
+
+// Comment
+import "C"
+
+import (
+	"io"
+	"utf8"
+)
+`,
+	},
+	{
+		Name: "import.7",
+		Fn:   deleteImportFn("io"),
+		In: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		Out: `package main
+
+import (
+	// a
+	"os"   // b
+	"utf8" // c
+)
+`,
+	},
+	{
+		Name: "import.8",
+		Fn:   deleteImportFn("os"),
+		In: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		Out: `package main
+
+import (
+	"io" // a
+	// b
+	"utf8" // c
+)
+`,
+	},
+	{
+		Name: "import.9",
+		Fn:   deleteImportFn("utf8"),
+		In: `package main
+
+import (
+	"io"   // a
+	"os"   // b
+	"utf8" // c
+)
+`,
+		Out: `package main
+
+import (
+	"io" // a
+	"os" // b
+	// c
+)
+`,
+	},
+	{
+		Name: "import.10",
+		Fn:   deleteImportFn("io"),
+		In: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		Out: `package main
+
+import (
+	"os"
+	"utf8"
+)
+`,
+	},
+	{
+		Name: "import.11",
+		Fn:   deleteImportFn("os"),
+		In: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		Out: `package main
+
+import (
+	"io"
+	"utf8"
+)
+`,
+	},
+	{
+		Name: "import.12",
+		Fn:   deleteImportFn("utf8"),
+		In: `package main
+
+import (
+	"io"
+	"os"
+	"utf8"
+)
+`,
+		Out: `package main
+
+import (
+	"io"
+	"os"
+)
+`,
+	},
+	{
+		Name: "import.13",
+		Fn:   rewriteImportFn("utf8", "encoding/utf8"),
+		In: `package main
+
+import (
+	"io"
+	"os"
+	"utf8" // thanks ken
+)
+`,
+		Out: `package main
+
+import (
+	"encoding/utf8" // thanks ken
+	"io"
+	"os"
+)
+`,
+	},
+	{
+		Name: "import.14",
+		Fn:   rewriteImportFn("asn1", "encoding/asn1"),
+		In: `package main
+
+import (
+	"asn1"
+	"crypto"
+	"crypto/rsa"
+	_ "crypto/sha1"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"time"
+)
+
+var x = 1
+`,
+		Out: `package main
+
+import (
+	"crypto"
+	"crypto/rsa"
+	_ "crypto/sha1"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"time"
+)
+
+var x = 1
+`,
+	},
+	{
+		Name: "import.15",
+		Fn:   rewriteImportFn("url", "net/url"),
+		In: `package main
+
+import (
+	"bufio"
+	"net"
+	"path"
+	"url"
+)
+
+var x = 1 // comment on x, not on url
+`,
+		Out: `package main
+
+import (
+	"bufio"
+	"net"
+	"net/url"
+	"path"
+)
+
+var x = 1 // comment on x, not on url
+`,
+	},
+	{
+		Name: "import.16",
+		Fn:   rewriteImportFn("http", "net/http", "template", "text/template"),
+		In: `package main
+
+import (
+	"flag"
+	"http"
+	"log"
+	"template"
+)
+
+var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
+`,
+		Out: `package main
+
+import (
+	"flag"
+	"log"
+	"net/http"
+	"text/template"
+)
+
+var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
+`,
+	},
+	{
+		Name: "import.17",
+		Fn:   addImportFn("x/y/z", "x/a/c"),
+		In: `package main
+
+// Comment
+import "C"
+
+import (
+	"a"
+	"b"
+
+	"x/w"
+
+	"d/f"
+)
+`,
+		Out: `package main
+
+// Comment
+import "C"
+
+import (
+	"a"
+	"b"
+
+	"x/a/c"
+	"x/w"
+	"x/y/z"
+
+	"d/f"
+)
+`,
+	},
+	{
+		Name: "import.18",
+		Fn:   addDelImportFn("e", "o"),
+		In: `package main
+
+import (
+	"f"
+	"o"
+	"z"
+)
+`,
+		Out: `package main
+
+import (
+	"e"
+	"f"
+	"z"
+)
+`,
+	},
+}
+
+func addImportFn(path ...string) func(*ast.File) bool {
+	return func(f *ast.File) bool {
+		fixed := false
+		for _, p := range path {
+			if !imports(f, p) {
+				addImport(f, p)
+				fixed = true
+			}
+		}
+		return fixed
+	}
+}
+
+func deleteImportFn(path string) func(*ast.File) bool {
+	return func(f *ast.File) bool {
+		if imports(f, path) {
+			deleteImport(f, path)
+			return true
+		}
+		return false
+	}
+}
+
+func addDelImportFn(p1 string, p2 string) func(*ast.File) bool {
+	return func(f *ast.File) bool {
+		fixed := false
+		if !imports(f, p1) {
+			addImport(f, p1)
+			fixed = true
+		}
+		if imports(f, p2) {
+			deleteImport(f, p2)
+			fixed = true
+		}
+		return fixed
+	}
+}
+
+func rewriteImportFn(oldnew ...string) func(*ast.File) bool {
+	return func(f *ast.File) bool {
+		fixed := false
+		for i := 0; i < len(oldnew); i += 2 {
+			if imports(f, oldnew[i]) {
+				rewriteImport(f, oldnew[i], oldnew[i+1])
+				fixed = true
+			}
+		}
+		return fixed
+	}
+}
diff --git a/src/cmd/gofix/iocopyn.go b/src/cmd/gofix/iocopyn.go
new file mode 100644
index 0000000..720f3c6
--- /dev/null
+++ b/src/cmd/gofix/iocopyn.go
@@ -0,0 +1,41 @@
+// Copyright 2011 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 (
+	"go/ast"
+)
+
+func init() {
+	register(ioCopyNFix)
+}
+
+var ioCopyNFix = fix{
+	"iocopyn",
+	"2011-09-30",
+	ioCopyN,
+	`Rename io.Copyn to io.CopyN.
+
+http://codereview.appspot.com/5157045
+`,
+}
+
+func ioCopyN(f *ast.File) bool {
+	if !imports(f, "io") {
+		return false
+	}
+
+	fixed := false
+	walk(f, func(n interface{}) {
+		if expr, ok := n.(ast.Expr); ok {
+			if isPkgDot(expr, "io", "Copyn") {
+				expr.(*ast.SelectorExpr).Sel.Name = "CopyN"
+				fixed = true
+				return
+			}
+		}
+	})
+	return fixed
+}
diff --git a/src/cmd/gofix/iocopyn_test.go b/src/cmd/gofix/iocopyn_test.go
new file mode 100644
index 0000000..f86fad7
--- /dev/null
+++ b/src/cmd/gofix/iocopyn_test.go
@@ -0,0 +1,37 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(ioCopyNTests, ioCopyN)
+}
+
+var ioCopyNTests = []testCase{
+	{
+		Name: "io.CopyN.0",
+		In: `package main
+
+import (
+	"io"
+)
+
+func f() {
+	io.Copyn(dst, src)
+	foo.Copyn(dst, src)
+}
+`,
+		Out: `package main
+
+import (
+	"io"
+)
+
+func f() {
+	io.CopyN(dst, src)
+	foo.Copyn(dst, src)
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/main.go b/src/cmd/gofix/main.go
index e0709fc..ca7e1a0 100644
--- a/src/cmd/gofix/main.go
+++ b/src/cmd/gofix/main.go
@@ -6,15 +6,16 @@ package main
 
 import (
 	"bytes"
-	"exec"
 	"flag"
 	"fmt"
+	"go/ast"
 	"go/parser"
 	"go/printer"
 	"go/scanner"
 	"go/token"
 	"io/ioutil"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"sort"
 	"strings"
@@ -28,14 +29,21 @@ var (
 var allowedRewrites = flag.String("r", "",
 	"restrict the rewrites to this comma-separated list")
 
-var allowed map[string]bool
+var forceRewrites = flag.String("force", "",
+	"force these fixes to run even if the code looks updated")
+
+var allowed, force map[string]bool
 
 var doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files")
 
+// enable for debugging gofix failures
+const debug = false // display incorrectly reformatted source and exit
+
 func usage() {
-	fmt.Fprintf(os.Stderr, "usage: gofix [-diff] [-r fixname,...] [path ...]\n")
+	fmt.Fprintf(os.Stderr, "usage: gofix [-diff] [-r fixname,...] [-force fixname,...] [path ...]\n")
 	flag.PrintDefaults()
 	fmt.Fprintf(os.Stderr, "\nAvailable rewrites are:\n")
+	sort.Sort(byName(fixes))
 	for _, f := range fixes {
 		fmt.Fprintf(os.Stderr, "\n%s\n", f.name)
 		desc := strings.TrimSpace(f.desc)
@@ -46,11 +54,11 @@ func usage() {
 }
 
 func main() {
-	sort.Sort(fixes)
-
 	flag.Usage = usage
 	flag.Parse()
 
+	sort.Sort(byDate(fixes))
+
 	if *allowedRewrites != "" {
 		allowed = make(map[string]bool)
 		for _, f := range strings.Split(*allowedRewrites, ",") {
@@ -58,6 +66,13 @@ func main() {
 		}
 	}
 
+	if *forceRewrites != "" {
+		force = make(map[string]bool)
+		for _, f := range strings.Split(*forceRewrites, ",") {
+			force[f] = true
+		}
+	}
+
 	if flag.NArg() == 0 {
 		if err := processFile("standard input", true); err != nil {
 			report(err)
@@ -70,12 +85,12 @@ func main() {
 		switch dir, err := os.Stat(path); {
 		case err != nil:
 			report(err)
-		case dir.IsRegular():
+		case dir.IsDir():
+			walkDir(path)
+		default:
 			if err := processFile(path, false); err != nil {
 				report(err)
 			}
-		case dir.IsDirectory():
-			walkDir(path)
 		}
 	}
 
@@ -93,11 +108,21 @@ var printConfig = &printer.Config{
 	tabWidth,
 }
 
-func processFile(filename string, useStdin bool) os.Error {
+func gofmtFile(f *ast.File) ([]byte, error) {
+	var buf bytes.Buffer
+
+	ast.SortImports(fset, f)
+	err := printConfig.Fprint(&buf, fset, f)
+	if err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
+}
+
+func processFile(filename string, useStdin bool) error {
 	var f *os.File
-	var err os.Error
+	var err error
 	var fixlog bytes.Buffer
-	var buf bytes.Buffer
 
 	if useStdin {
 		f = os.Stdin
@@ -133,14 +158,17 @@ func processFile(filename string, useStdin bool) os.Error {
 			// AST changed.
 			// Print and parse, to update any missing scoping
 			// or position information for subsequent fixers.
-			buf.Reset()
-			_, err = printConfig.Fprint(&buf, fset, newFile)
+			newSrc, err := gofmtFile(newFile)
 			if err != nil {
 				return err
 			}
-			newSrc := buf.Bytes()
 			newFile, err = parser.ParseFile(fset, filename, newSrc, parserMode)
 			if err != nil {
+				if debug {
+					fmt.Printf("%s", newSrc)
+					report(err)
+					os.Exit(exitCode)
+				}
 				return err
 			}
 		}
@@ -156,12 +184,10 @@ func processFile(filename string, useStdin bool) os.Error {
 	// output of the printer run on a standard AST generated by the parser,
 	// but the source we generated inside the loop above is the
 	// output of the printer run on a mangled AST generated by a fixer.
-	buf.Reset()
-	_, err = printConfig.Fprint(&buf, fset, newFile)
+	newSrc, err := gofmtFile(newFile)
 	if err != nil {
 		return err
 	}
-	newSrc := buf.Bytes()
 
 	if *doDiff {
 		data, err := diff(src, newSrc)
@@ -185,14 +211,14 @@ var gofmtBuf bytes.Buffer
 
 func gofmt(n interface{}) string {
 	gofmtBuf.Reset()
-	_, err := printConfig.Fprint(&gofmtBuf, fset, n)
+	err := printConfig.Fprint(&gofmtBuf, fset, n)
 	if err != nil {
-		return "<" + err.String() + ">"
+		return "<" + err.Error() + ">"
 	}
 	return gofmtBuf.String()
 }
 
-func report(err os.Error) {
+func report(err error) {
 	scanner.PrintError(os.Stderr, err)
 	exitCode = 2
 }
@@ -201,7 +227,7 @@ func walkDir(path string) {
 	filepath.Walk(path, visitFile)
 }
 
-func visitFile(path string, f *os.FileInfo, err os.Error) os.Error {
+func visitFile(path string, f os.FileInfo, err error) error {
 	if err == nil && isGoFile(f) {
 		err = processFile(path, false)
 	}
@@ -211,12 +237,13 @@ func visitFile(path string, f *os.FileInfo, err os.Error) os.Error {
 	return nil
 }
 
-func isGoFile(f *os.FileInfo) bool {
+func isGoFile(f os.FileInfo) bool {
 	// ignore non-Go files
-	return f.IsRegular() && !strings.HasPrefix(f.Name, ".") && strings.HasSuffix(f.Name, ".go")
+	name := f.Name()
+	return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
 }
 
-func diff(b1, b2 []byte) (data []byte, err os.Error) {
+func diff(b1, b2 []byte) (data []byte, err error) {
 	f1, err := ioutil.TempFile("", "gofix")
 	if err != nil {
 		return nil, err
diff --git a/src/cmd/gofix/main_test.go b/src/cmd/gofix/main_test.go
index 275778e..2151bf2 100644
--- a/src/cmd/gofix/main_test.go
+++ b/src/cmd/gofix/main_test.go
@@ -5,10 +5,8 @@
 package main
 
 import (
-	"bytes"
 	"go/ast"
 	"go/parser"
-	"go/printer"
 	"strings"
 	"testing"
 )
@@ -22,27 +20,33 @@ type testCase struct {
 
 var testCases []testCase
 
-func addTestCases(t []testCase) {
+func addTestCases(t []testCase, fn func(*ast.File) bool) {
+	// Fill in fn to avoid repetition in definitions.
+	if fn != nil {
+		for i := range t {
+			if t[i].Fn == nil {
+				t[i].Fn = fn
+			}
+		}
+	}
 	testCases = append(testCases, t...)
 }
 
 func fnop(*ast.File) bool { return false }
 
-func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out string, fixed, ok bool) {
+func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string, mustBeGofmt bool) (out string, fixed, ok bool) {
 	file, err := parser.ParseFile(fset, desc, in, parserMode)
 	if err != nil {
 		t.Errorf("%s: parsing: %v", desc, err)
 		return
 	}
 
-	var buf bytes.Buffer
-	buf.Reset()
-	_, err = (&printer.Config{printerMode, tabWidth}).Fprint(&buf, fset, file)
+	outb, err := gofmtFile(file)
 	if err != nil {
 		t.Errorf("%s: printing: %v", desc, err)
 		return
 	}
-	if s := buf.String(); in != s && fn != fnop {
+	if s := string(outb); in != s && mustBeGofmt {
 		t.Errorf("%s: not gofmt-formatted.\n--- %s\n%s\n--- %s | gofmt\n%s",
 			desc, desc, in, desc, s)
 		tdiff(t, in, s)
@@ -59,26 +63,25 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out
 		fixed = fn(file)
 	}
 
-	buf.Reset()
-	_, err = (&printer.Config{printerMode, tabWidth}).Fprint(&buf, fset, file)
+	outb, err = gofmtFile(file)
 	if err != nil {
 		t.Errorf("%s: printing: %v", desc, err)
 		return
 	}
 
-	return buf.String(), fixed, true
+	return string(outb), fixed, true
 }
 
 func TestRewrite(t *testing.T) {
 	for _, tt := range testCases {
 		// Apply fix: should get tt.Out.
-		out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In)
+		out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In, true)
 		if !ok {
 			continue
 		}
 
 		// reformat to get printing right
-		out, _, ok = parseFixPrint(t, fnop, tt.Name, out)
+		out, _, ok = parseFixPrint(t, fnop, tt.Name, out, false)
 		if !ok {
 			continue
 		}
@@ -98,7 +101,7 @@ func TestRewrite(t *testing.T) {
 		}
 
 		// Should not change if run again.
-		out2, fixed2, ok := parseFixPrint(t, tt.Fn, tt.Name+" output", out)
+		out2, fixed2, ok := parseFixPrint(t, tt.Fn, tt.Name+" output", out, true)
 		if !ok {
 			continue
 		}
diff --git a/src/cmd/gofix/mapdelete.go b/src/cmd/gofix/mapdelete.go
new file mode 100644
index 0000000..db89c7b
--- /dev/null
+++ b/src/cmd/gofix/mapdelete.go
@@ -0,0 +1,89 @@
+// Copyright 2011 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 "go/ast"
+
+func init() {
+	register(mapdeleteFix)
+}
+
+var mapdeleteFix = fix{
+	"mapdelete",
+	"2011-10-18",
+	mapdelete,
+	`Use delete(m, k) instead of m[k] = 0, false.
+
+http://codereview.appspot.com/5272045
+`,
+}
+
+func mapdelete(f *ast.File) bool {
+	fixed := false
+	walk(f, func(n interface{}) {
+		stmt, ok := n.(*ast.Stmt)
+		if !ok {
+			return
+		}
+		as, ok := (*stmt).(*ast.AssignStmt)
+		if !ok || len(as.Lhs) != 1 || len(as.Rhs) != 2 {
+			return
+		}
+		ix, ok := as.Lhs[0].(*ast.IndexExpr)
+		if !ok {
+			return
+		}
+		if !isTopName(as.Rhs[1], "false") {
+			warn(as.Pos(), "two-element map assignment with non-false second value")
+			return
+		}
+		if !canDrop(as.Rhs[0]) {
+			warn(as.Pos(), "two-element map assignment with non-trivial first value")
+			return
+		}
+		*stmt = &ast.ExprStmt{
+			X: &ast.CallExpr{
+				Fun: &ast.Ident{
+					NamePos: as.Pos(),
+					Name:    "delete",
+				},
+				Args: []ast.Expr{ix.X, ix.Index},
+			},
+		}
+		fixed = true
+	})
+	return fixed
+}
+
+// canDrop reports whether it is safe to drop the
+// evaluation of n from the program.
+// It is very conservative.
+func canDrop(n ast.Expr) bool {
+	switch n := n.(type) {
+	case *ast.Ident, *ast.BasicLit:
+		return true
+	case *ast.ParenExpr:
+		return canDrop(n.X)
+	case *ast.SelectorExpr:
+		return canDrop(n.X)
+	case *ast.CompositeLit:
+		if !canDrop(n.Type) {
+			return false
+		}
+		for _, e := range n.Elts {
+			if !canDrop(e) {
+				return false
+			}
+		}
+		return true
+	case *ast.StarExpr:
+		// Dropping *x is questionable,
+		// but we have to be able to drop (*T)(nil).
+		return canDrop(n.X)
+	case *ast.ArrayType, *ast.ChanType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.StructType:
+		return true
+	}
+	return false
+}
diff --git a/src/cmd/gofix/mapdelete_test.go b/src/cmd/gofix/mapdelete_test.go
new file mode 100644
index 0000000..8ed5032
--- /dev/null
+++ b/src/cmd/gofix/mapdelete_test.go
@@ -0,0 +1,43 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(mapdeleteTests, mapdelete)
+}
+
+var mapdeleteTests = []testCase{
+	{
+		Name: "mapdelete.0",
+		In: `package main
+
+func f() {
+	m[x] = 0, false
+	m[x] = g(), false
+	m[x] = 1
+	delete(m, x)
+	m[x] = 0, b
+}
+
+func g(false bool) {
+	m[x] = 0, false
+}
+`,
+		Out: `package main
+
+func f() {
+	delete(m, x)
+	m[x] = g(), false
+	m[x] = 1
+	delete(m, x)
+	m[x] = 0, b
+}
+
+func g(false bool) {
+	m[x] = 0, false
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/math.go b/src/cmd/gofix/math.go
new file mode 100644
index 0000000..2ec837e
--- /dev/null
+++ b/src/cmd/gofix/math.go
@@ -0,0 +1,51 @@
+// Copyright 2011 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 "go/ast"
+
+func init() {
+	register(mathFix)
+}
+
+var mathFix = fix{
+	"math",
+	"2011-09-29",
+	math,
+	`Remove the leading F from math functions such as Fabs.
+
+http://codereview.appspot.com/5158043
+`,
+}
+
+var mathRenames = []struct{ in, out string }{
+	{"Fabs", "Abs"},
+	{"Fdim", "Dim"},
+	{"Fmax", "Max"},
+	{"Fmin", "Min"},
+	{"Fmod", "Mod"},
+}
+
+func math(f *ast.File) bool {
+	if !imports(f, "math") {
+		return false
+	}
+
+	fixed := false
+
+	walk(f, func(n interface{}) {
+		// Rename functions.
+		if expr, ok := n.(ast.Expr); ok {
+			for _, s := range mathRenames {
+				if isPkgDot(expr, "math", s.in) {
+					expr.(*ast.SelectorExpr).Sel.Name = s.out
+					fixed = true
+					return
+				}
+			}
+		}
+	})
+	return fixed
+}
diff --git a/src/cmd/gofix/math_test.go b/src/cmd/gofix/math_test.go
new file mode 100644
index 0000000..b8d69d2
--- /dev/null
+++ b/src/cmd/gofix/math_test.go
@@ -0,0 +1,47 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(mathTests, math)
+}
+
+var mathTests = []testCase{
+	{
+		Name: "math.0",
+		In: `package main
+
+import (
+	"math"
+)
+
+func f() {
+	math.Fabs(1)
+	math.Fdim(1)
+	math.Fmax(1)
+	math.Fmin(1)
+	math.Fmod(1)
+	math.Abs(1)
+	foo.Fabs(1)
+}
+`,
+		Out: `package main
+
+import (
+	"math"
+)
+
+func f() {
+	math.Abs(1)
+	math.Dim(1)
+	math.Max(1)
+	math.Min(1)
+	math.Mod(1)
+	math.Abs(1)
+	foo.Fabs(1)
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/netdial.go b/src/cmd/gofix/netdial.go
index afa9895..2de994c 100644
--- a/src/cmd/gofix/netdial.go
+++ b/src/cmd/gofix/netdial.go
@@ -8,8 +8,15 @@ import (
 	"go/ast"
 )
 
+func init() {
+	register(netdialFix)
+	register(tlsdialFix)
+	register(netlookupFix)
+}
+
 var netdialFix = fix{
 	"netdial",
+	"2011-03-28",
 	netdial,
 	`Adapt 3-argument calls of net.Dial to use 2-argument form.
 
@@ -19,6 +26,7 @@ http://codereview.appspot.com/4244055
 
 var tlsdialFix = fix{
 	"tlsdial",
+	"2011-03-28",
 	tlsdial,
 	`Adapt 4-argument calls of tls.Dial to use 3-argument form.
 
@@ -28,6 +36,7 @@ http://codereview.appspot.com/4244055
 
 var netlookupFix = fix{
 	"netlookup",
+	"2011-03-28",
 	netlookup,
 	`Adapt 3-result calls to net.LookupHost to use 2-result form.
 
@@ -35,12 +44,6 @@ http://codereview.appspot.com/4244055
 `,
 }
 
-func init() {
-	register(netdialFix)
-	register(tlsdialFix)
-	register(netlookupFix)
-}
-
 func netdial(f *ast.File) bool {
 	if !imports(f, "net") {
 		return false
diff --git a/src/cmd/gofix/netdial_test.go b/src/cmd/gofix/netdial_test.go
index 272aa52..fff00b4 100644
--- a/src/cmd/gofix/netdial_test.go
+++ b/src/cmd/gofix/netdial_test.go
@@ -1,12 +1,17 @@
+// Copyright 2011 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
 
 func init() {
-	addTestCases(netdialTests)
+	addTestCases(netdialTests, nil)
 }
 
 var netdialTests = []testCase{
 	{
 		Name: "netdial.0",
+		Fn:   netdial,
 		In: `package main
 
 import "net"
@@ -29,6 +34,7 @@ func f() {
 
 	{
 		Name: "netlookup.0",
+		Fn:   netlookup,
 		In: `package main
 
 import "net"
diff --git a/src/cmd/gofix/netudpgroup.go b/src/cmd/gofix/netudpgroup.go
index 347452d..b54beb0 100644
--- a/src/cmd/gofix/netudpgroup.go
+++ b/src/cmd/gofix/netudpgroup.go
@@ -8,8 +8,13 @@ import (
 	"go/ast"
 )
 
+func init() {
+	register(netudpgroupFix)
+}
+
 var netudpgroupFix = fix{
 	"netudpgroup",
+	"2011-08-18",
 	netudpgroup,
 	`Adapt 1-argument calls of net.(*UDPConn).JoinGroup, LeaveGroup to use 2-argument form.
 
@@ -17,10 +22,6 @@ http://codereview.appspot.com/4815074
 `,
 }
 
-func init() {
-	register(netudpgroupFix)
-}
-
 func netudpgroup(f *ast.File) bool {
 	if !imports(f, "net") {
 		return false
@@ -29,7 +30,7 @@ func netudpgroup(f *ast.File) bool {
 	fixed := false
 	for _, d := range f.Decls {
 		fd, ok := d.(*ast.FuncDecl)
-		if !ok {
+		if !ok || fd.Body == nil {
 			continue
 		}
 		walk(fd.Body, func(n interface{}) {
diff --git a/src/cmd/gofix/netudpgroup_test.go b/src/cmd/gofix/netudpgroup_test.go
index b3b5816..88c0e09 100644
--- a/src/cmd/gofix/netudpgroup_test.go
+++ b/src/cmd/gofix/netudpgroup_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(netudpgroupTests)
+	addTestCases(netudpgroupTests, netudpgroup)
 }
 
 var netudpgroupTests = []testCase{
@@ -30,4 +30,24 @@ func f() {
 }
 `,
 	},
+	// Innocent function with no body.
+	{
+		Name: "netudpgroup.1",
+		In: `package main
+
+import "net"
+
+func f()
+
+var _ net.IP
+`,
+		Out: `package main
+
+import "net"
+
+func f()
+
+var _ net.IP
+`,
+	},
 }
diff --git a/src/cmd/gofix/oserrorstring.go b/src/cmd/gofix/oserrorstring.go
index db39ee9..a75a2c1 100644
--- a/src/cmd/gofix/oserrorstring.go
+++ b/src/cmd/gofix/oserrorstring.go
@@ -8,8 +8,13 @@ import (
 	"go/ast"
 )
 
+func init() {
+	register(oserrorstringFix)
+}
+
 var oserrorstringFix = fix{
 	"oserrorstring",
+	"2011-06-22",
 	oserrorstring,
 	`Replace os.ErrorString() conversions with calls to os.NewError().
 
@@ -17,10 +22,6 @@ http://codereview.appspot.com/4607052
 `,
 }
 
-func init() {
-	register(oserrorstringFix)
-}
-
 func oserrorstring(f *ast.File) bool {
 	if !imports(f, "os") {
 		return false
diff --git a/src/cmd/gofix/oserrorstring_test.go b/src/cmd/gofix/oserrorstring_test.go
index 070d922..7555148 100644
--- a/src/cmd/gofix/oserrorstring_test.go
+++ b/src/cmd/gofix/oserrorstring_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(oserrorstringTests)
+	addTestCases(oserrorstringTests, oserrorstring)
 }
 
 var oserrorstringTests = []testCase{
diff --git a/src/cmd/gofix/osopen.go b/src/cmd/gofix/osopen.go
index 19c19b5..af2796a 100644
--- a/src/cmd/gofix/osopen.go
+++ b/src/cmd/gofix/osopen.go
@@ -8,8 +8,13 @@ import (
 	"go/ast"
 )
 
+func init() {
+	register(osopenFix)
+}
+
 var osopenFix = fix{
 	"osopen",
+	"2011-04-04",
 	osopen,
 	`Adapt os.Open calls to new, easier API and rename O_CREAT O_CREATE.
 
@@ -17,10 +22,6 @@ http://codereview.appspot.com/4357052
 `,
 }
 
-func init() {
-	register(osopenFix)
-}
-
 func osopen(f *ast.File) bool {
 	if !imports(f, "os") {
 		return false
diff --git a/src/cmd/gofix/osopen_test.go b/src/cmd/gofix/osopen_test.go
index a33bcd4..5797adb 100644
--- a/src/cmd/gofix/osopen_test.go
+++ b/src/cmd/gofix/osopen_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(osopenTests)
+	addTestCases(osopenTests, osopen)
 }
 
 var osopenTests = []testCase{
diff --git a/src/cmd/gofix/procattr.go b/src/cmd/gofix/procattr.go
index 0e2190b..ea375ec 100644
--- a/src/cmd/gofix/procattr.go
+++ b/src/cmd/gofix/procattr.go
@@ -9,8 +9,13 @@ import (
 	"go/token"
 )
 
+func init() {
+	register(procattrFix)
+}
+
 var procattrFix = fix{
 	"procattr",
+	"2011-03-15",
 	procattr,
 	`Adapt calls to os.StartProcess to use new ProcAttr type.
 
@@ -18,10 +23,6 @@ http://codereview.appspot.com/4253052
 `,
 }
 
-func init() {
-	register(procattrFix)
-}
-
 func procattr(f *ast.File) bool {
 	if !imports(f, "os") && !imports(f, "syscall") {
 		return false
diff --git a/src/cmd/gofix/procattr_test.go b/src/cmd/gofix/procattr_test.go
index b973b96..9e2b86e 100644
--- a/src/cmd/gofix/procattr_test.go
+++ b/src/cmd/gofix/procattr_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(procattrTests)
+	addTestCases(procattrTests, procattr)
 }
 
 var procattrTests = []testCase{
diff --git a/src/cmd/gofix/reflect.go b/src/cmd/gofix/reflect.go
index 3c8beca..4665d15 100644
--- a/src/cmd/gofix/reflect.go
+++ b/src/cmd/gofix/reflect.go
@@ -15,8 +15,13 @@ import (
 	"strings"
 )
 
+func init() {
+	register(reflectFix)
+}
+
 var reflectFix = fix{
 	"reflect",
+	"2011-04-08",
 	reflectFn,
 	`Adapt code to new reflect API.
 
@@ -25,10 +30,6 @@ http://codereview.appspot.com/4433066
 `,
 }
 
-func init() {
-	register(reflectFix)
-}
-
 // The reflect API change dropped the concrete types *reflect.ArrayType etc.
 // Any type assertions prior to method calls can be deleted:
 //	x.(*reflect.ArrayType).Len() -> x.Len()
@@ -99,7 +100,7 @@ func reflectFn(f *ast.File) bool {
 
 	// Rewrite names in method calls.
 	// Needs basic type information (see above).
-	typeof := typecheck(reflectTypeConfig, f)
+	typeof, _ := typecheck(reflectTypeConfig, f)
 	walk(f, func(n interface{}) {
 		switch n := n.(type) {
 		case *ast.SelectorExpr:
@@ -616,75 +617,75 @@ func reflectFixAssert(n interface{}) bool {
 // which implements Type.)
 var reflectTypeConfig = &TypeConfig{
 	Type: map[string]*Type{
-		"reflect.ArrayOrSliceType":  &Type{Embed: []string{"reflect.Type"}},
-		"reflect.ArrayOrSliceValue": &Type{Embed: []string{"reflect.Value"}},
-		"reflect.ArrayType":         &Type{Embed: []string{"reflect.Type"}},
-		"reflect.ArrayValue":        &Type{Embed: []string{"reflect.Value"}},
-		"reflect.BoolType":          &Type{Embed: []string{"reflect.Type"}},
-		"reflect.BoolValue":         &Type{Embed: []string{"reflect.Value"}},
-		"reflect.ChanType":          &Type{Embed: []string{"reflect.Type"}},
-		"reflect.ChanValue": &Type{
+		"reflect.ArrayOrSliceType":  {Embed: []string{"reflect.Type"}},
+		"reflect.ArrayOrSliceValue": {Embed: []string{"reflect.Value"}},
+		"reflect.ArrayType":         {Embed: []string{"reflect.Type"}},
+		"reflect.ArrayValue":        {Embed: []string{"reflect.Value"}},
+		"reflect.BoolType":          {Embed: []string{"reflect.Type"}},
+		"reflect.BoolValue":         {Embed: []string{"reflect.Value"}},
+		"reflect.ChanType":          {Embed: []string{"reflect.Type"}},
+		"reflect.ChanValue": {
 			Method: map[string]string{
 				"Recv":    "func() (reflect.Value, bool)",
 				"TryRecv": "func() (reflect.Value, bool)",
 			},
 			Embed: []string{"reflect.Value"},
 		},
-		"reflect.ComplexType":  &Type{Embed: []string{"reflect.Type"}},
-		"reflect.ComplexValue": &Type{Embed: []string{"reflect.Value"}},
-		"reflect.FloatType":    &Type{Embed: []string{"reflect.Type"}},
-		"reflect.FloatValue":   &Type{Embed: []string{"reflect.Value"}},
-		"reflect.FuncType": &Type{
+		"reflect.ComplexType":  {Embed: []string{"reflect.Type"}},
+		"reflect.ComplexValue": {Embed: []string{"reflect.Value"}},
+		"reflect.FloatType":    {Embed: []string{"reflect.Type"}},
+		"reflect.FloatValue":   {Embed: []string{"reflect.Value"}},
+		"reflect.FuncType": {
 			Method: map[string]string{
 				"In":  "func(int) reflect.Type",
 				"Out": "func(int) reflect.Type",
 			},
 			Embed: []string{"reflect.Type"},
 		},
-		"reflect.FuncValue": &Type{
+		"reflect.FuncValue": {
 			Method: map[string]string{
 				"Call": "func([]reflect.Value) []reflect.Value",
 			},
 		},
-		"reflect.IntType":        &Type{Embed: []string{"reflect.Type"}},
-		"reflect.IntValue":       &Type{Embed: []string{"reflect.Value"}},
-		"reflect.InterfaceType":  &Type{Embed: []string{"reflect.Type"}},
-		"reflect.InterfaceValue": &Type{Embed: []string{"reflect.Value"}},
-		"reflect.MapType": &Type{
+		"reflect.IntType":        {Embed: []string{"reflect.Type"}},
+		"reflect.IntValue":       {Embed: []string{"reflect.Value"}},
+		"reflect.InterfaceType":  {Embed: []string{"reflect.Type"}},
+		"reflect.InterfaceValue": {Embed: []string{"reflect.Value"}},
+		"reflect.MapType": {
 			Method: map[string]string{
 				"Key": "func() reflect.Type",
 			},
 			Embed: []string{"reflect.Type"},
 		},
-		"reflect.MapValue": &Type{
+		"reflect.MapValue": {
 			Method: map[string]string{
 				"Keys": "func() []reflect.Value",
 			},
 			Embed: []string{"reflect.Value"},
 		},
-		"reflect.Method": &Type{
+		"reflect.Method": {
 			Field: map[string]string{
 				"Type": "*reflect.FuncType",
 				"Func": "*reflect.FuncValue",
 			},
 		},
-		"reflect.PtrType":   &Type{Embed: []string{"reflect.Type"}},
-		"reflect.PtrValue":  &Type{Embed: []string{"reflect.Value"}},
-		"reflect.SliceType": &Type{Embed: []string{"reflect.Type"}},
-		"reflect.SliceValue": &Type{
+		"reflect.PtrType":   {Embed: []string{"reflect.Type"}},
+		"reflect.PtrValue":  {Embed: []string{"reflect.Value"}},
+		"reflect.SliceType": {Embed: []string{"reflect.Type"}},
+		"reflect.SliceValue": {
 			Method: map[string]string{
 				"Slice": "func(int, int) *reflect.SliceValue",
 			},
 			Embed: []string{"reflect.Value"},
 		},
-		"reflect.StringType":  &Type{Embed: []string{"reflect.Type"}},
-		"reflect.StringValue": &Type{Embed: []string{"reflect.Value"}},
-		"reflect.StructField": &Type{
+		"reflect.StringType":  {Embed: []string{"reflect.Type"}},
+		"reflect.StringValue": {Embed: []string{"reflect.Value"}},
+		"reflect.StructField": {
 			Field: map[string]string{
 				"Type": "reflect.Type",
 			},
 		},
-		"reflect.StructType": &Type{
+		"reflect.StructType": {
 			Method: map[string]string{
 				"Field":           "func() reflect.StructField",
 				"FieldByIndex":    "func() reflect.StructField",
@@ -693,7 +694,7 @@ var reflectTypeConfig = &TypeConfig{
 			},
 			Embed: []string{"reflect.Type"},
 		},
-		"reflect.StructValue": &Type{
+		"reflect.StructValue": {
 			Method: map[string]string{
 				"Field":           "func() reflect.Value",
 				"FieldByIndex":    "func() reflect.Value",
@@ -702,17 +703,17 @@ var reflectTypeConfig = &TypeConfig{
 			},
 			Embed: []string{"reflect.Value"},
 		},
-		"reflect.Type": &Type{
+		"reflect.Type": {
 			Method: map[string]string{
 				"Elem":   "func() reflect.Type",
 				"Method": "func() reflect.Method",
 			},
 		},
-		"reflect.UintType":           &Type{Embed: []string{"reflect.Type"}},
-		"reflect.UintValue":          &Type{Embed: []string{"reflect.Value"}},
-		"reflect.UnsafePointerType":  &Type{Embed: []string{"reflect.Type"}},
-		"reflect.UnsafePointerValue": &Type{Embed: []string{"reflect.Value"}},
-		"reflect.Value": &Type{
+		"reflect.UintType":           {Embed: []string{"reflect.Type"}},
+		"reflect.UintValue":          {Embed: []string{"reflect.Value"}},
+		"reflect.UnsafePointerType":  {Embed: []string{"reflect.Type"}},
+		"reflect.UnsafePointerValue": {Embed: []string{"reflect.Value"}},
+		"reflect.Value": {
 			Method: map[string]string{
 				"Addr":     "func() *reflect.PtrValue",
 				"Elem":     "func() reflect.Value",
diff --git a/src/cmd/gofix/reflect_test.go b/src/cmd/gofix/reflect_test.go
index 00edf30..032cbc7 100644
--- a/src/cmd/gofix/reflect_test.go
+++ b/src/cmd/gofix/reflect_test.go
@@ -1,3 +1,7 @@
+// Copyright 2011 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 (
@@ -7,7 +11,7 @@ import (
 )
 
 func init() {
-	addTestCases(reflectTests())
+	addTestCases(reflectTests(), reflectFn)
 }
 
 func reflectTests() []testCase {
diff --git a/src/cmd/gofix/signal.go b/src/cmd/gofix/signal.go
index 53c3388..5a583d4 100644
--- a/src/cmd/gofix/signal.go
+++ b/src/cmd/gofix/signal.go
@@ -10,14 +10,17 @@ import (
 )
 
 func init() {
-	register(fix{
-		"signal",
-		signal,
-		`Adapt code to types moved from os/signal to signal.
+	register(signalFix)
+}
+
+var signalFix = fix{
+	"signal",
+	"2011-06-29",
+	signal,
+	`Adapt code to types moved from os/signal to signal.
 
 http://codereview.appspot.com/4437091
 `,
-	})
 }
 
 func signal(f *ast.File) (fixed bool) {
@@ -34,16 +37,14 @@ func signal(f *ast.File) (fixed bool) {
 
 		sel := s.Sel.String()
 		if sel == "Signal" || sel == "UnixSignal" || strings.HasPrefix(sel, "SIG") {
+			addImport(f, "os")
 			s.X = &ast.Ident{Name: "os"}
 			fixed = true
 		}
 	})
 
-	if fixed {
-		addImport(f, "os")
-		if !usesImport(f, "os/signal") {
-			deleteImport(f, "os/signal")
-		}
+	if fixed && !usesImport(f, "os/signal") {
+		deleteImport(f, "os/signal")
 	}
 	return
 }
diff --git a/src/cmd/gofix/signal_test.go b/src/cmd/gofix/signal_test.go
index 4abba35..7bca7d5 100644
--- a/src/cmd/gofix/signal_test.go
+++ b/src/cmd/gofix/signal_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(signalTests)
+	addTestCases(signalTests, signal)
 }
 
 var signalTests = []testCase{
diff --git a/src/cmd/gofix/sorthelpers.go b/src/cmd/gofix/sorthelpers.go
index 4e89fa8..fa54931 100644
--- a/src/cmd/gofix/sorthelpers.go
+++ b/src/cmd/gofix/sorthelpers.go
@@ -9,12 +9,15 @@ import (
 )
 
 func init() {
-	register(fix{
-		"sorthelpers",
-		sorthelpers,
-		`Adapt code from sort.Sort[Ints|Float64s|Strings] to sort.[Ints|Float64s|Strings].
+	register(sorthelpersFix)
+}
+
+var sorthelpersFix = fix{
+	"sorthelpers",
+	"2011-07-08",
+	sorthelpers,
+	`Adapt code from sort.Sort[Ints|Float64s|Strings] to sort.[Ints|Float64s|Strings].
 `,
-	})
 }
 
 func sorthelpers(f *ast.File) (fixed bool) {
diff --git a/src/cmd/gofix/sorthelpers_test.go b/src/cmd/gofix/sorthelpers_test.go
index 6c37858..dd6b58e 100644
--- a/src/cmd/gofix/sorthelpers_test.go
+++ b/src/cmd/gofix/sorthelpers_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(sorthelpersTests)
+	addTestCases(sorthelpersTests, sorthelpers)
 }
 
 var sorthelpersTests = []testCase{
diff --git a/src/cmd/gofix/sortslice.go b/src/cmd/gofix/sortslice.go
index 7cfa169..89267b8 100644
--- a/src/cmd/gofix/sortslice.go
+++ b/src/cmd/gofix/sortslice.go
@@ -9,15 +9,18 @@ import (
 )
 
 func init() {
-	register(fix{
-		"sortslice",
-		sortslice,
-		`Adapt code from sort.[Float64|Int|String]Array to  sort.[Float64|Int|String]Slice.
+	register(sortsliceFix)
+}
+
+var sortsliceFix = fix{
+	"sortslice",
+	"2011-06-26",
+	sortslice,
+	`Adapt code from sort.[Float64|Int|String]Array to  sort.[Float64|Int|String]Slice.
 		
 http://codereview.appspot.com/4602054
 http://codereview.appspot.com/4639041
 `,
-	})
 }
 
 func sortslice(f *ast.File) (fixed bool) {
diff --git a/src/cmd/gofix/sortslice_test.go b/src/cmd/gofix/sortslice_test.go
index 404feb2..7b745a2 100644
--- a/src/cmd/gofix/sortslice_test.go
+++ b/src/cmd/gofix/sortslice_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(sortsliceTests)
+	addTestCases(sortsliceTests, sortslice)
 }
 
 var sortsliceTests = []testCase{
diff --git a/src/cmd/gofix/strconv.go b/src/cmd/gofix/strconv.go
new file mode 100644
index 0000000..6cd6902
--- /dev/null
+++ b/src/cmd/gofix/strconv.go
@@ -0,0 +1,127 @@
+// Copyright 2011 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 "go/ast"
+
+func init() {
+	register(strconvFix)
+}
+
+var strconvFix = fix{
+	"strconv",
+	"2011-12-01",
+	strconvFn,
+	`Convert to new strconv API.
+
+http://codereview.appspot.com/5434095
+http://codereview.appspot.com/5434069
+`,
+}
+
+func strconvFn(f *ast.File) bool {
+	if !imports(f, "strconv") {
+		return false
+	}
+
+	fixed := false
+
+	walk(f, func(n interface{}) {
+		// Rename functions.
+		call, ok := n.(*ast.CallExpr)
+		if !ok || len(call.Args) < 1 {
+			return
+		}
+		sel, ok := call.Fun.(*ast.SelectorExpr)
+		if !ok || !isTopName(sel.X, "strconv") {
+			return
+		}
+		change := func(name string) {
+			fixed = true
+			sel.Sel.Name = name
+		}
+		add := func(s string) {
+			call.Args = append(call.Args, expr(s))
+		}
+		switch sel.Sel.Name {
+		case "Atob":
+			change("ParseBool")
+		case "Atof32":
+			change("ParseFloat")
+			add("32") // bitSize
+			warn(call.Pos(), "rewrote strconv.Atof32(_) to strconv.ParseFloat(_, 32) but return value must be converted to float32")
+		case "Atof64":
+			change("ParseFloat")
+			add("64") // bitSize
+		case "AtofN":
+			change("ParseFloat")
+		case "Atoi":
+			// Atoi stayed as a convenience wrapper.
+		case "Atoi64":
+			change("ParseInt")
+			add("10") // base
+			add("64") // bitSize
+		case "Atoui":
+			change("ParseUint")
+			add("10") // base
+			add("0")  // bitSize
+			warn(call.Pos(), "rewrote strconv.Atoui(_) to strconv.ParseUint(_, 10, 0) but return value must be converted to uint")
+		case "Atoui64":
+			change("ParseUint")
+			add("10") // base
+			add("64") // bitSize
+		case "Btoa":
+			change("FormatBool")
+		case "Btoi64":
+			change("ParseInt")
+			add("64") // bitSize
+		case "Btoui64":
+			change("ParseUint")
+			add("64") // bitSize
+		case "Ftoa32":
+			change("FormatFloat")
+			call.Args[0] = strconvRewrite("float32", "float64", call.Args[0])
+			add("32") // bitSize
+		case "Ftoa64":
+			change("FormatFloat")
+			add("64") // bitSize
+		case "FtoaN":
+			change("FormatFloat")
+		case "Itoa":
+			// Itoa stayed as a convenience wrapper.
+		case "Itoa64":
+			change("FormatInt")
+			add("10") // base
+		case "Itob":
+			change("FormatInt")
+			call.Args[0] = strconvRewrite("int", "int64", call.Args[0])
+		case "Itob64":
+			change("FormatInt")
+		case "Uitoa":
+			change("FormatUint")
+			call.Args[0] = strconvRewrite("uint", "uint64", call.Args[0])
+			add("10") // base
+		case "Uitoa64":
+			change("FormatUint")
+			add("10") // base
+		case "Uitob":
+			change("FormatUint")
+			call.Args[0] = strconvRewrite("uint", "uint64", call.Args[0])
+		case "Uitob64":
+			change("FormatUint")
+		}
+	})
+	return fixed
+}
+
+// rewrite from type t1 to type t2
+// If the expression x is of the form t1(_), use t2(_).  Otherwise use t2(x).
+func strconvRewrite(t1, t2 string, x ast.Expr) ast.Expr {
+	if call, ok := x.(*ast.CallExpr); ok && isTopName(call.Fun, t1) {
+		call.Fun.(*ast.Ident).Name = t2
+		return x
+	}
+	return &ast.CallExpr{Fun: ast.NewIdent(t2), Args: []ast.Expr{x}}
+}
diff --git a/src/cmd/gofix/strconv_test.go b/src/cmd/gofix/strconv_test.go
new file mode 100644
index 0000000..7fbd4e4
--- /dev/null
+++ b/src/cmd/gofix/strconv_test.go
@@ -0,0 +1,93 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(strconvTests, strconvFn)
+}
+
+var strconvTests = []testCase{
+	{
+		Name: "strconv.0",
+		In: `package main
+
+import "strconv"
+
+func f() {
+	foo.Atob("abc")
+
+	strconv.Atob("true")
+	strconv.Btoa(false)
+
+	strconv.Atof32("1.2")
+	strconv.Atof64("1.2")
+	strconv.AtofN("1.2", 64)
+	strconv.Ftoa32(1.2, 'g', 17)
+	strconv.Ftoa64(1.2, 'g', 17)
+	strconv.FtoaN(1.2, 'g', 17, 64)
+
+	strconv.Atoi("3")
+	strconv.Atoi64("3")
+	strconv.Btoi64("1234", 5)
+
+	strconv.Atoui("3")
+	strconv.Atoui64("3")
+	strconv.Btoui64("1234", 5)
+
+	strconv.Itoa(123)
+	strconv.Itoa64(1234)
+	strconv.Itob(123, 5)
+	strconv.Itob64(1234, 5)
+
+	strconv.Uitoa(123)
+	strconv.Uitoa64(1234)
+	strconv.Uitob(123, 5)
+	strconv.Uitob64(1234, 5)
+
+	strconv.Uitoa(uint(x))
+	strconv.Uitoa(f(x))
+}
+`,
+		Out: `package main
+
+import "strconv"
+
+func f() {
+	foo.Atob("abc")
+
+	strconv.ParseBool("true")
+	strconv.FormatBool(false)
+
+	strconv.ParseFloat("1.2", 32)
+	strconv.ParseFloat("1.2", 64)
+	strconv.ParseFloat("1.2", 64)
+	strconv.FormatFloat(float64(1.2), 'g', 17, 32)
+	strconv.FormatFloat(1.2, 'g', 17, 64)
+	strconv.FormatFloat(1.2, 'g', 17, 64)
+
+	strconv.Atoi("3")
+	strconv.ParseInt("3", 10, 64)
+	strconv.ParseInt("1234", 5, 64)
+
+	strconv.ParseUint("3", 10, 0)
+	strconv.ParseUint("3", 10, 64)
+	strconv.ParseUint("1234", 5, 64)
+
+	strconv.Itoa(123)
+	strconv.FormatInt(1234, 10)
+	strconv.FormatInt(int64(123), 5)
+	strconv.FormatInt(1234, 5)
+
+	strconv.FormatUint(uint64(123), 10)
+	strconv.FormatUint(1234, 10)
+	strconv.FormatUint(uint64(123), 5)
+	strconv.FormatUint(1234, 5)
+
+	strconv.FormatUint(uint64(x), 10)
+	strconv.FormatUint(uint64(f(x)), 10)
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/stringssplit.go b/src/cmd/gofix/stringssplit.go
index 4a1fe93..d89ecf0 100644
--- a/src/cmd/gofix/stringssplit.go
+++ b/src/cmd/gofix/stringssplit.go
@@ -9,8 +9,13 @@ import (
 	"go/token"
 )
 
+func init() {
+	register(stringssplitFix)
+}
+
 var stringssplitFix = fix{
 	"stringssplit",
+	"2011-06-28",
 	stringssplit,
 	`Restore strings.Split to its original meaning and add strings.SplitN. Bytes too.
 
@@ -18,10 +23,6 @@ http://codereview.appspot.com/4661051
 `,
 }
 
-func init() {
-	register(stringssplitFix)
-}
-
 func stringssplit(f *ast.File) bool {
 	if !imports(f, "bytes") && !imports(f, "strings") {
 		return false
diff --git a/src/cmd/gofix/stringssplit_test.go b/src/cmd/gofix/stringssplit_test.go
index b925722..fa42b1b 100644
--- a/src/cmd/gofix/stringssplit_test.go
+++ b/src/cmd/gofix/stringssplit_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(stringssplitTests)
+	addTestCases(stringssplitTests, stringssplit)
 }
 
 var stringssplitTests = []testCase{
diff --git a/src/cmd/gofix/template.go b/src/cmd/gofix/template.go
new file mode 100644
index 0000000..a3dd144
--- /dev/null
+++ b/src/cmd/gofix/template.go
@@ -0,0 +1,111 @@
+// Copyright 2011 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 (
+	"go/ast"
+)
+
+func init() {
+	register(templateFix)
+}
+
+var templateFix = fix{
+	"template",
+	"2011-11-22",
+	template,
+	`Rewrite calls to template.ParseFile to template.ParseFiles
+
+http://codereview.appspot.com/5433048
+`,
+}
+
+var templateSetGlobals = []string{
+	"ParseSetFiles",
+	"ParseSetGlob",
+	"ParseTemplateFiles",
+	"ParseTemplateGlob",
+	"Set",
+	"SetMust",
+}
+
+var templateSetMethods = []string{
+	"ParseSetFiles",
+	"ParseSetGlob",
+	"ParseTemplateFiles",
+	"ParseTemplateGlob",
+}
+
+var templateTypeConfig = &TypeConfig{
+	Type: map[string]*Type{
+		"template.Template": {
+			Method: map[string]string{
+				"Funcs":      "func() *template.Template",
+				"Delims":     "func() *template.Template",
+				"Parse":      "func() (*template.Template, error)",
+				"ParseFile":  "func() (*template.Template, error)",
+				"ParseInSet": "func() (*template.Template, error)",
+			},
+		},
+		"template.Set": {
+			Method: map[string]string{
+				"ParseSetFiles":      "func() (*template.Set, error)",
+				"ParseSetGlob":       "func() (*template.Set, error)",
+				"ParseTemplateFiles": "func() (*template.Set, error)",
+				"ParseTemplateGlob":  "func() (*template.Set, error)",
+			},
+		},
+	},
+
+	Func: map[string]string{
+		"template.New":     "*template.Template",
+		"template.Must":    "(*template.Template, error)",
+		"template.SetMust": "(*template.Set, error)",
+	},
+}
+
+func template(f *ast.File) bool {
+	if !imports(f, "text/template") && !imports(f, "html/template") {
+		return false
+	}
+
+	fixed := false
+
+	typeof, _ := typecheck(templateTypeConfig, f)
+
+	// Now update the names used by importers.
+	walk(f, func(n interface{}) {
+		if sel, ok := n.(*ast.SelectorExpr); ok {
+			// Reference to top-level function ParseFile.
+			if isPkgDot(sel, "template", "ParseFile") {
+				sel.Sel.Name = "ParseFiles"
+				fixed = true
+				return
+			}
+			// Reference to ParseFiles method.
+			if typeof[sel.X] == "*template.Template" && sel.Sel.Name == "ParseFile" {
+				sel.Sel.Name = "ParseFiles"
+				fixed = true
+				return
+			}
+			// The Set type and its functions are now gone.
+			for _, name := range templateSetGlobals {
+				if isPkgDot(sel, "template", name) {
+					warn(sel.Pos(), "reference to template.%s must be fixed manually", name)
+					return
+				}
+			}
+			// The methods of Set are now gone.
+			for _, name := range templateSetMethods {
+				if typeof[sel.X] == "*template.Set" && sel.Sel.Name == name {
+					warn(sel.Pos(), "reference to template.*Set.%s must be fixed manually", name)
+					return
+				}
+			}
+		}
+	})
+
+	return fixed
+}
diff --git a/src/cmd/gofix/template_test.go b/src/cmd/gofix/template_test.go
new file mode 100644
index 0000000..f713a29
--- /dev/null
+++ b/src/cmd/gofix/template_test.go
@@ -0,0 +1,55 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(templateTests, template)
+}
+
+var templateTests = []testCase{
+	{
+		Name: "template.0",
+		In: `package main
+
+import (
+	"text/template"
+)
+
+func f() {
+	template.ParseFile(a)
+	var t template.Template
+	x, y := template.ParseFile()
+	template.New("x").Funcs(m).ParseFile(a) // chained method
+	// Output should complain about these as functions or methods.
+	var s *template.Set
+	s.ParseSetFiles(a)
+	template.ParseSetGlob(a)
+	s.ParseTemplateFiles(a)
+	template.ParseTemplateGlob(a)
+	x := template.SetMust(a())
+}
+`,
+		Out: `package main
+
+import (
+	"text/template"
+)
+
+func f() {
+	template.ParseFiles(a)
+	var t template.Template
+	x, y := template.ParseFiles()
+	template.New("x").Funcs(m).ParseFiles(a) // chained method
+	// Output should complain about these as functions or methods.
+	var s *template.Set
+	s.ParseSetFiles(a)
+	template.ParseSetGlob(a)
+	s.ParseTemplateFiles(a)
+	template.ParseTemplateGlob(a)
+	x := template.SetMust(a())
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/testdata/reflect.decoder.go.in b/src/cmd/gofix/testdata/reflect.decoder.go.in
index 3436416..0ce9b06 100644
--- a/src/cmd/gofix/testdata/reflect.decoder.go.in
+++ b/src/cmd/gofix/testdata/reflect.decoder.go.in
@@ -44,7 +44,7 @@ func NewDecoder(r io.Reader) *Decoder {
 func (dec *Decoder) recvType(id typeId) {
 	// Have we already seen this type?  That's an error
 	if id < firstUserId || dec.wireType[id] != nil {
-		dec.err = os.ErrorString("gob: duplicate type received")
+		dec.err = os.NewError("gob: duplicate type received")
 		return
 	}
 
@@ -143,7 +143,7 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
 		// will be absorbed by recvMessage.)
 		if dec.buf.Len() > 0 {
 			if !isInterface {
-				dec.err = os.ErrorString("extra data in buffer")
+				dec.err = os.NewError("extra data in buffer")
 				break
 			}
 			dec.nextUint()
@@ -165,7 +165,7 @@ func (dec *Decoder) Decode(e interface{}) os.Error {
 	// If e represents a value as opposed to a pointer, the answer won't
 	// get back to the caller.  Make sure it's a pointer.
 	if value.Type().Kind() != reflect.Ptr {
-		dec.err = os.ErrorString("gob: attempt to decode into a non-pointer")
+		dec.err = os.NewError("gob: attempt to decode into a non-pointer")
 		return dec.err
 	}
 	return dec.DecodeValue(value)
diff --git a/src/cmd/gofix/testdata/reflect.encoder.go.in b/src/cmd/gofix/testdata/reflect.encoder.go.in
index e52a4de..0202d79 100644
--- a/src/cmd/gofix/testdata/reflect.encoder.go.in
+++ b/src/cmd/gofix/testdata/reflect.encoder.go.in
@@ -50,7 +50,7 @@ func (enc *Encoder) popWriter() {
 }
 
 func (enc *Encoder) badType(rt reflect.Type) {
-	enc.setError(os.ErrorString("gob: can't encode type " + rt.String()))
+	enc.setError(os.NewError("gob: can't encode type " + rt.String()))
 }
 
 func (enc *Encoder) setError(err os.Error) {
diff --git a/src/cmd/gofix/testdata/reflect.export.go.in b/src/cmd/gofix/testdata/reflect.export.go.in
index e91e777..ce7940b 100644
--- a/src/cmd/gofix/testdata/reflect.export.go.in
+++ b/src/cmd/gofix/testdata/reflect.export.go.in
@@ -22,8 +22,8 @@ package netchan
 // BUG: can't use range clause to receive when using ImportNValues to limit the count.
 
 import (
-	"log"
 	"io"
+	"log"
 	"net"
 	"os"
 	"reflect"
@@ -343,20 +343,20 @@ func (exp *Exporter) Sync(timeout int64) os.Error {
 func checkChan(chT interface{}, dir Dir) (*reflect.ChanValue, os.Error) {
 	chanType, ok := reflect.Typeof(chT).(*reflect.ChanType)
 	if !ok {
-		return nil, os.ErrorString("not a channel")
+		return nil, os.NewError("not a channel")
 	}
 	if dir != Send && dir != Recv {
-		return nil, os.ErrorString("unknown channel direction")
+		return nil, os.NewError("unknown channel direction")
 	}
 	switch chanType.Dir() {
 	case reflect.BothDir:
 	case reflect.SendDir:
 		if dir != Recv {
-			return nil, os.ErrorString("to import/export with Send, must provide <-chan")
+			return nil, os.NewError("to import/export with Send, must provide <-chan")
 		}
 	case reflect.RecvDir:
 		if dir != Send {
-			return nil, os.ErrorString("to import/export with Recv, must provide chan<-")
+			return nil, os.NewError("to import/export with Recv, must provide chan<-")
 		}
 	}
 	return reflect.NewValue(chT).(*reflect.ChanValue), nil
@@ -376,7 +376,7 @@ func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error {
 	defer exp.mu.Unlock()
 	_, present := exp.names[name]
 	if present {
-		return os.ErrorString("channel name already being exported:" + name)
+		return os.NewError("channel name already being exported:" + name)
 	}
 	exp.names[name] = &chanDir{ch, dir}
 	return nil
@@ -393,7 +393,7 @@ func (exp *Exporter) Hangup(name string) os.Error {
 	// TODO drop all instances of channel from client sets
 	exp.mu.Unlock()
 	if !ok {
-		return os.ErrorString("netchan export: hangup: no such channel: " + name)
+		return os.NewError("netchan export: hangup: no such channel: " + name)
 	}
 	chDir.ch.Close()
 	return nil
diff --git a/src/cmd/gofix/testdata/reflect.export.go.out b/src/cmd/gofix/testdata/reflect.export.go.out
index 460edb4..7bd73c5 100644
--- a/src/cmd/gofix/testdata/reflect.export.go.out
+++ b/src/cmd/gofix/testdata/reflect.export.go.out
@@ -22,8 +22,8 @@ package netchan
 // BUG: can't use range clause to receive when using ImportNValues to limit the count.
 
 import (
-	"log"
 	"io"
+	"log"
 	"net"
 	"os"
 	"reflect"
diff --git a/src/cmd/gofix/testdata/reflect.print.go.in b/src/cmd/gofix/testdata/reflect.print.go.in
index cba1df2..6c9b8e4 100644
--- a/src/cmd/gofix/testdata/reflect.print.go.in
+++ b/src/cmd/gofix/testdata/reflect.print.go.in
@@ -185,7 +185,7 @@ func Sprintf(format string, a ...interface{}) string {
 // Errorf formats according to a format specifier and returns the string 
 // converted to an os.ErrorString, which satisfies the os.Error interface.
 func Errorf(format string, a ...interface{}) os.Error {
-	return os.ErrorString(Sprintf(format, a...))
+	return os.NewError(Sprintf(format, a...))
 }
 
 // These routines do not take a format string
diff --git a/src/cmd/gofix/testdata/reflect.read.go.in b/src/cmd/gofix/testdata/reflect.read.go.in
index 9ae3bb8..487994a 100644
--- a/src/cmd/gofix/testdata/reflect.read.go.in
+++ b/src/cmd/gofix/testdata/reflect.read.go.in
@@ -244,7 +244,7 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
 
 	switch v := val.(type) {
 	default:
-		return os.ErrorString("unknown type " + v.Type().String())
+		return os.NewError("unknown type " + v.Type().String())
 
 	case *reflect.SliceValue:
 		typ := v.Type().(*reflect.SliceType)
@@ -483,7 +483,7 @@ Loop:
 	case nil:
 		// Probably a comment, handled below
 	default:
-		return os.ErrorString("cannot happen: unknown type " + t.Type().String())
+		return os.NewError("cannot happen: unknown type " + t.Type().String())
 	case *reflect.IntValue:
 		if !getInt64() {
 			return err
diff --git a/src/cmd/gofix/testdata/reflect.scan.go.in b/src/cmd/gofix/testdata/reflect.scan.go.in
index 83650e6..5189818 100644
--- a/src/cmd/gofix/testdata/reflect.scan.go.in
+++ b/src/cmd/gofix/testdata/reflect.scan.go.in
@@ -167,7 +167,7 @@ type ssave struct {
 // satisfies io.Reader. It will never be called when used as
 // intended, so there is no need to make it actually work.
 func (s *ss) Read(buf []byte) (n int, err os.Error) {
-	return 0, os.ErrorString("ScanState's Read should not be called. Use ReadRune")
+	return 0, os.NewError("ScanState's Read should not be called. Use ReadRune")
 }
 
 func (s *ss) ReadRune() (rune int, size int, err os.Error) {
@@ -240,7 +240,7 @@ func (s *ss) error(err os.Error) {
 }
 
 func (s *ss) errorString(err string) {
-	panic(scanError{os.ErrorString(err)})
+	panic(scanError{os.NewError(err)})
 }
 
 func (s *ss) Token(skipSpace bool, f func(int) bool) (tok []byte, err os.Error) {
@@ -424,8 +424,8 @@ func (s *ss) typeError(field interface{}, expected string) {
 	s.errorString("expected field of type pointer to " + expected + "; found " + reflect.Typeof(field).String())
 }
 
-var complexError = os.ErrorString("syntax error scanning complex number")
-var boolError = os.ErrorString("syntax error scanning boolean")
+var complexError = os.NewError("syntax error scanning complex number")
+var boolError = os.NewError("syntax error scanning boolean")
 
 // consume reads the next rune in the input and reports whether it is in the ok string.
 // If accept is true, it puts the character into the input token.
diff --git a/src/cmd/gofix/testdata/reflect.type.go.in b/src/cmd/gofix/testdata/reflect.type.go.in
index 305d419..34963be 100644
--- a/src/cmd/gofix/testdata/reflect.type.go.in
+++ b/src/cmd/gofix/testdata/reflect.type.go.in
@@ -67,7 +67,7 @@ func validUserType(rt reflect.Type) (ut *userTypeInfo, err os.Error) {
 		ut.base = pt.Elem()
 		if ut.base == slowpoke { // ut.base lapped slowpoke
 			// recursive pointer type.
-			return nil, os.ErrorString("can't represent recursive pointer type " + ut.base.String())
+			return nil, os.NewError("can't represent recursive pointer type " + ut.base.String())
 		}
 		if ut.indir%2 == 0 {
 			slowpoke = slowpoke.(*reflect.PtrType).Elem()
@@ -150,6 +150,7 @@ func userType(rt reflect.Type) *userTypeInfo {
 	}
 	return ut
 }
+
 // A typeId represents a gob Type as an integer that can be passed on the wire.
 // Internally, typeIds are used as keys to a map to recover the underlying type info.
 type typeId int32
@@ -524,7 +525,7 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.
 		return st, nil
 
 	default:
-		return nil, os.ErrorString("gob NewTypeObject can't handle type: " + rt.String())
+		return nil, os.NewError("gob NewTypeObject can't handle type: " + rt.String())
 	}
 	return nil, nil
 }
diff --git a/src/cmd/gofix/testdata/reflect.type.go.out b/src/cmd/gofix/testdata/reflect.type.go.out
index 9cd7829..d729ea4 100644
--- a/src/cmd/gofix/testdata/reflect.type.go.out
+++ b/src/cmd/gofix/testdata/reflect.type.go.out
@@ -150,6 +150,7 @@ func userType(rt reflect.Type) *userTypeInfo {
 	}
 	return ut
 }
+
 // A typeId represents a gob Type as an integer that can be passed on the wire.
 // Internally, typeIds are used as keys to a map to recover the underlying type info.
 type typeId int32
diff --git a/src/cmd/gofix/timefileinfo.go b/src/cmd/gofix/timefileinfo.go
new file mode 100644
index 0000000..b2ea23d
--- /dev/null
+++ b/src/cmd/gofix/timefileinfo.go
@@ -0,0 +1,298 @@
+// Copyright 2011 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 (
+	"go/ast"
+	"go/token"
+	"strings"
+)
+
+func init() {
+	register(timefileinfoFix)
+}
+
+var timefileinfoFix = fix{
+	"time+fileinfo",
+	"2011-11-29",
+	timefileinfo,
+	`Rewrite for new time and os.FileInfo APIs.
+
+This fix applies some of the more mechanical changes,
+but most code will still need manual cleanup.
+
+http://codereview.appspot.com/5392041
+http://codereview.appspot.com/5416060
+`,
+}
+
+var timefileinfoTypeConfig = &TypeConfig{
+	Type: map[string]*Type{
+		"os.File": {
+			Method: map[string]string{
+				"Readdir": "func() []*os.FileInfo",
+				"Stat":    "func() (*os.FileInfo, error)",
+			},
+		},
+		"time.Time": {
+			Method: map[string]string{
+				"Seconds":     "time.raw",
+				"Nanoseconds": "time.raw",
+			},
+		},
+	},
+	Func: map[string]string{
+		"ioutil.ReadDir":              "([]*os.FileInfo, error)",
+		"os.Stat":                     "(*os.FileInfo, error)",
+		"os.Lstat":                    "(*os.FileInfo, error)",
+		"time.LocalTime":              "*time.Time",
+		"time.UTC":                    "*time.Time",
+		"time.SecondsToLocalTime":     "*time.Time",
+		"time.SecondsToUTC":           "*time.Time",
+		"time.NanosecondsToLocalTime": "*time.Time",
+		"time.NanosecondsToUTC":       "*time.Time",
+		"time.Parse":                  "(*time.Time, error)",
+		"time.Nanoseconds":            "time.raw",
+		"time.Seconds":                "time.raw",
+	},
+}
+
+// timefileinfoIsOld reports whether f has evidence of being
+// "old code", from before the API changes.  Evidence means:
+//
+//	a mention of *os.FileInfo (the pointer)
+//	a mention of *time.Time (the pointer)
+//	a mention of old functions from package time
+//	an attempt to call time.UTC
+//
+func timefileinfoIsOld(f *ast.File, typeof map[interface{}]string) bool {
+	old := false
+
+	// called records the expressions that appear as
+	// the function part of a function call, so that
+	// we can distinguish a ref to the possibly new time.UTC
+	// from the definitely old time.UTC() function call.
+	called := make(map[interface{}]bool)
+
+	before := func(n interface{}) {
+		if old {
+			return
+		}
+		if star, ok := n.(*ast.StarExpr); ok {
+			if isPkgDot(star.X, "os", "FileInfo") || isPkgDot(star.X, "time", "Time") {
+				old = true
+				return
+			}
+		}
+		if sel, ok := n.(*ast.SelectorExpr); ok {
+			if isTopName(sel.X, "time") {
+				if timefileinfoOldTimeFunc[sel.Sel.Name] {
+					old = true
+					return
+				}
+			}
+			if typeof[sel.X] == "os.FileInfo" || typeof[sel.X] == "*os.FileInfo" {
+				switch sel.Sel.Name {
+				case "Mtime_ns", "IsDirectory", "IsRegular":
+					old = true
+					return
+				case "Name", "Mode", "Size":
+					if !called[sel] {
+						old = true
+						return
+					}
+				}
+			}
+		}
+		call, ok := n.(*ast.CallExpr)
+		if ok && isPkgDot(call.Fun, "time", "UTC") {
+			old = true
+			return
+		}
+		if ok {
+			called[call.Fun] = true
+		}
+	}
+	walkBeforeAfter(f, before, nop)
+	return old
+}
+
+var timefileinfoOldTimeFunc = map[string]bool{
+	"LocalTime":              true,
+	"SecondsToLocalTime":     true,
+	"SecondsToUTC":           true,
+	"NanosecondsToLocalTime": true,
+	"NanosecondsToUTC":       true,
+	"Seconds":                true,
+	"Nanoseconds":            true,
+}
+
+var isTimeNow = map[string]bool{
+	"LocalTime":   true,
+	"UTC":         true,
+	"Seconds":     true,
+	"Nanoseconds": true,
+}
+
+func timefileinfo(f *ast.File) bool {
+	if !imports(f, "os") && !imports(f, "time") && !imports(f, "io/ioutil") {
+		return false
+	}
+
+	typeof, _ := typecheck(timefileinfoTypeConfig, f)
+
+	if !timefileinfoIsOld(f, typeof) {
+		return false
+	}
+
+	fixed := false
+	walk(f, func(n interface{}) {
+		p, ok := n.(*ast.Expr)
+		if !ok {
+			return
+		}
+		nn := *p
+
+		// Rewrite *os.FileInfo and *time.Time to drop the pointer.
+		if star, ok := nn.(*ast.StarExpr); ok {
+			if isPkgDot(star.X, "os", "FileInfo") || isPkgDot(star.X, "time", "Time") {
+				fixed = true
+				*p = star.X
+				return
+			}
+		}
+
+		// Rewrite old time API calls to new calls.
+		// The code will still not compile after this edit,
+		// but the compiler will catch that, and the replacement
+		// code will be the correct functions to use in the new API.
+		if sel, ok := nn.(*ast.SelectorExpr); ok && isTopName(sel.X, "time") {
+			fn := sel.Sel.Name
+			if fn == "LocalTime" || fn == "Seconds" || fn == "Nanoseconds" {
+				fixed = true
+				sel.Sel.Name = "Now"
+				return
+			}
+		}
+
+		if call, ok := nn.(*ast.CallExpr); ok {
+			if sel, ok := call.Fun.(*ast.SelectorExpr); ok {
+				// Rewrite time.UTC but only when called (there's a new time.UTC var now).
+				if isPkgDot(sel, "time", "UTC") {
+					fixed = true
+					sel.Sel.Name = "Now"
+					// rewrite time.Now() into time.Now().UTC()
+					*p = &ast.CallExpr{
+						Fun: &ast.SelectorExpr{
+							X:   call,
+							Sel: ast.NewIdent("UTC"),
+						},
+					}
+					return
+				}
+
+				// Rewrite conversions.
+				if ok && isTopName(sel.X, "time") && len(call.Args) == 1 {
+					fn := sel.Sel.Name
+					switch fn {
+					case "SecondsToLocalTime", "SecondsToUTC",
+						"NanosecondsToLocalTime", "NanosecondsToUTC":
+						fixed = true
+						sel.Sel.Name = "Unix"
+						call.Args = append(call.Args, nil)
+						if strings.HasPrefix(fn, "Seconds") {
+							// Unix(sec, 0)
+							call.Args[1] = ast.NewIdent("0")
+						} else {
+							// Unix(0, nsec)
+							call.Args[1] = call.Args[0]
+							call.Args[0] = ast.NewIdent("0")
+						}
+						if strings.HasSuffix(fn, "ToUTC") {
+							// rewrite call into call.UTC()
+							*p = &ast.CallExpr{
+								Fun: &ast.SelectorExpr{
+									X:   call,
+									Sel: ast.NewIdent("UTC"),
+								},
+							}
+						}
+						return
+					}
+				}
+
+				// Rewrite method calls.
+				switch typeof[sel.X] {
+				case "*time.Time", "time.Time":
+					switch sel.Sel.Name {
+					case "Seconds":
+						fixed = true
+						sel.Sel.Name = "Unix"
+						return
+					case "Nanoseconds":
+						fixed = true
+						sel.Sel.Name = "UnixNano"
+						return
+					}
+
+				case "*os.FileInfo", "os.FileInfo":
+					switch sel.Sel.Name {
+					case "IsDirectory":
+						fixed = true
+						sel.Sel.Name = "IsDir"
+						return
+					case "IsRegular":
+						fixed = true
+						sel.Sel.Name = "IsDir"
+						*p = &ast.UnaryExpr{
+							Op: token.NOT,
+							X:  call,
+						}
+						return
+					}
+				}
+			}
+		}
+
+		// Rewrite subtraction of two times.
+		// Cannot handle +=/-=.
+		if bin, ok := nn.(*ast.BinaryExpr); ok &&
+			bin.Op == token.SUB &&
+			(typeof[bin.X] == "time.raw" || typeof[bin.Y] == "time.raw") {
+			fixed = true
+			*p = &ast.CallExpr{
+				Fun: &ast.SelectorExpr{
+					X:   bin.X,
+					Sel: ast.NewIdent("Sub"),
+				},
+				Args: []ast.Expr{bin.Y},
+			}
+		}
+
+		// Rewrite field references for os.FileInfo.
+		if sel, ok := nn.(*ast.SelectorExpr); ok {
+			if typ := typeof[sel.X]; typ == "*os.FileInfo" || typ == "os.FileInfo" {
+				addCall := false
+				switch sel.Sel.Name {
+				case "Name", "Size", "Mode":
+					fixed = true
+					addCall = true
+				case "Mtime_ns":
+					fixed = true
+					sel.Sel.Name = "ModTime"
+					addCall = true
+				}
+				if addCall {
+					*p = &ast.CallExpr{
+						Fun: sel,
+					}
+					return
+				}
+			}
+		}
+	})
+
+	return true
+}
diff --git a/src/cmd/gofix/timefileinfo_test.go b/src/cmd/gofix/timefileinfo_test.go
new file mode 100644
index 0000000..76d5c1f
--- /dev/null
+++ b/src/cmd/gofix/timefileinfo_test.go
@@ -0,0 +1,161 @@
+// Copyright 2011 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
+
+func init() {
+	addTestCases(timefileinfoTests, timefileinfo)
+}
+
+var timefileinfoTests = []testCase{
+	{
+		Name: "timefileinfo.0",
+		In: `package main
+
+import "os"
+
+func main() {
+	st, _ := os.Stat("/etc/passwd")
+	_ = st.Name
+}
+`,
+		Out: `package main
+
+import "os"
+
+func main() {
+	st, _ := os.Stat("/etc/passwd")
+	_ = st.Name()
+}
+`,
+	},
+	{
+		Name: "timefileinfo.1",
+		In: `package main
+
+import "os"
+
+func main() {
+	st, _ := os.Stat("/etc/passwd")
+	_ = st.Size
+	_ = st.Mode
+	_ = st.Mtime_ns
+	_ = st.IsDirectory()
+	_ = st.IsRegular()
+}
+`,
+		Out: `package main
+
+import "os"
+
+func main() {
+	st, _ := os.Stat("/etc/passwd")
+	_ = st.Size()
+	_ = st.Mode()
+	_ = st.ModTime()
+	_ = st.IsDir()
+	_ = !st.IsDir()
+}
+`,
+	},
+	{
+		Name: "timefileinfo.2",
+		In: `package main
+
+import "os"
+
+func f(st *os.FileInfo) {
+	_ = st.Name
+	_ = st.Size
+	_ = st.Mode
+	_ = st.Mtime_ns
+	_ = st.IsDirectory()
+	_ = st.IsRegular()
+}
+`,
+		Out: `package main
+
+import "os"
+
+func f(st os.FileInfo) {
+	_ = st.Name()
+	_ = st.Size()
+	_ = st.Mode()
+	_ = st.ModTime()
+	_ = st.IsDir()
+	_ = !st.IsDir()
+}
+`,
+	},
+	{
+		Name: "timefileinfo.3",
+		In: `package main
+
+import "time"
+
+func main() {
+	_ = time.Seconds()
+	_ = time.Nanoseconds()
+	_ = time.LocalTime()
+	_ = time.UTC()
+	_ = time.SecondsToLocalTime(sec)
+	_ = time.SecondsToUTC(sec)
+	_ = time.NanosecondsToLocalTime(nsec)
+	_ = time.NanosecondsToUTC(nsec)
+}
+`,
+		Out: `package main
+
+import "time"
+
+func main() {
+	_ = time.Now()
+	_ = time.Now()
+	_ = time.Now()
+	_ = time.Now().UTC()
+	_ = time.Unix(sec, 0)
+	_ = time.Unix(sec, 0).UTC()
+	_ = time.Unix(0, nsec)
+	_ = time.Unix(0, nsec).UTC()
+}
+`,
+	},
+	{
+		Name: "timefileinfo.4",
+		In: `package main
+
+import "time"
+
+func f(*time.Time)
+
+func main() {
+	t := time.LocalTime()
+	_ = t.Seconds()
+	_ = t.Nanoseconds()
+
+	t1 := time.Nanoseconds()
+	f(nil)
+	t2 := time.Nanoseconds()
+	dt := t2 - t1
+}
+`,
+		Out: `package main
+
+import "time"
+
+func f(time.Time)
+
+func main() {
+	t := time.Now()
+	_ = t.Unix()
+	_ = t.UnixNano()
+
+	t1 := time.Now()
+	f(nil)
+	t2 := time.Now()
+	dt := t2.Sub(t1)
+}
+`,
+	},
+}
diff --git a/src/cmd/gofix/typecheck.go b/src/cmd/gofix/typecheck.go
index 2d81b97..8e54314 100644
--- a/src/cmd/gofix/typecheck.go
+++ b/src/cmd/gofix/typecheck.go
@@ -97,8 +97,9 @@ func (cfg *TypeConfig) typeof(name string) string {
 // looked for in the Embed list.
 type Type struct {
 	Field  map[string]string // map field name to type
-	Method map[string]string // map method name to comma-separated return types
+	Method map[string]string // map method name to comma-separated return types (should start with "func ")
 	Embed  []string          // list of types this type embeds (for extra methods)
+	Def    string            // definition of named type
 }
 
 // dot returns the type of "typ.name", making its decision
@@ -128,9 +129,16 @@ func (typ *Type) dot(cfg *TypeConfig, name string) string {
 }
 
 // typecheck type checks the AST f assuming the information in cfg.
-// It returns a map from AST nodes to type information in gofmt string form.
-func typecheck(cfg *TypeConfig, f *ast.File) map[interface{}]string {
-	typeof := make(map[interface{}]string)
+// It returns two maps with type information:
+// typeof maps AST nodes to type information in gofmt string form.
+// assign maps type strings to lists of expressions that were assigned
+// to values of another type that were assigned to that type.
+func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, assign map[string][]interface{}) {
+	typeof = make(map[interface{}]string)
+	assign = make(map[string][]interface{})
+	cfg1 := &TypeConfig{}
+	*cfg1 = *cfg // make copy so we can add locally
+	copied := false
 
 	// gather function declarations
 	for _, decl := range f.Decls {
@@ -138,7 +146,7 @@ func typecheck(cfg *TypeConfig, f *ast.File) map[interface{}]string {
 		if !ok {
 			continue
 		}
-		typecheck1(cfg, fn.Type, typeof)
+		typecheck1(cfg, fn.Type, typeof, assign)
 		t := typeof[fn.Type]
 		if fn.Recv != nil {
 			// The receiver must be a type.
@@ -168,8 +176,43 @@ func typecheck(cfg *TypeConfig, f *ast.File) map[interface{}]string {
 		}
 	}
 
-	typecheck1(cfg, f, typeof)
-	return typeof
+	// gather struct declarations
+	for _, decl := range f.Decls {
+		d, ok := decl.(*ast.GenDecl)
+		if ok {
+			for _, s := range d.Specs {
+				switch s := s.(type) {
+				case *ast.TypeSpec:
+					if cfg1.Type[s.Name.Name] != nil {
+						break
+					}
+					if !copied {
+						copied = true
+						// Copy map lazily: it's time.
+						cfg1.Type = make(map[string]*Type)
+						for k, v := range cfg.Type {
+							cfg1.Type[k] = v
+						}
+					}
+					t := &Type{Field: map[string]string{}}
+					cfg1.Type[s.Name.Name] = t
+					switch st := s.Type.(type) {
+					case *ast.StructType:
+						for _, f := range st.Fields.List {
+							for _, n := range f.Names {
+								t.Field[n.Name] = gofmt(f.Type)
+							}
+						}
+					case *ast.ArrayType, *ast.StarExpr, *ast.MapType:
+						t.Def = gofmt(st)
+					}
+				}
+			}
+		}
+	}
+
+	typecheck1(cfg1, f, typeof, assign)
+	return typeof, assign
 }
 
 func makeExprList(a []*ast.Ident) []ast.Expr {
@@ -183,11 +226,14 @@ func makeExprList(a []*ast.Ident) []ast.Expr {
 // Typecheck1 is the recursive form of typecheck.
 // It is like typecheck but adds to the information in typeof
 // instead of allocating a new map.
-func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
+func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, assign map[string][]interface{}) {
 	// set sets the type of n to typ.
 	// If isDecl is true, n is being declared.
 	set := func(n ast.Expr, typ string, isDecl bool) {
 		if typeof[n] != "" || typ == "" {
+			if typeof[n] != typ {
+				assign[typ] = append(assign[typ], n)
+			}
 			return
 		}
 		typeof[n] = typ
@@ -236,6 +282,14 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 		}
 	}
 
+	expand := func(s string) string {
+		typ := cfg.Type[s]
+		if typ != nil && typ.Def != "" {
+			return typ.Def
+		}
+		return s
+	}
+
 	// The main type check is a recursive algorithm implemented
 	// by walkBeforeAfter(n, before, after).
 	// Most of it is bottom-up, but in a few places we need
@@ -263,7 +317,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 			defer func() {
 				if t := typeof[n]; t != "" {
 					pos := fset.Position(n.(ast.Node).Pos())
-					fmt.Fprintf(os.Stderr, "%s: typeof[%s] = %s\n", pos.String(), gofmt(n), t)
+					fmt.Fprintf(os.Stderr, "%s: typeof[%s] = %s\n", pos, gofmt(n), t)
 				}
 			}()
 		}
@@ -405,6 +459,8 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 			// x.(T) has type T.
 			if t := typeof[n.Type]; isType(t) {
 				typeof[n] = getType(t)
+			} else {
+				typeof[n] = gofmt(n.Type)
 			}
 
 		case *ast.SliceExpr:
@@ -413,7 +469,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 
 		case *ast.IndexExpr:
 			// x[i] has key type of x's type.
-			t := typeof[n.X]
+			t := expand(typeof[n.X])
 			if strings.HasPrefix(t, "[") || strings.HasPrefix(t, "map[") {
 				// Lazy: assume there are no nested [] in the array
 				// length or map key type.
@@ -426,7 +482,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 			// *x for x of type *T has type T when x is an expr.
 			// We don't use the result when *x is a type, but
 			// compute it anyway.
-			t := typeof[n.X]
+			t := expand(typeof[n.X])
 			if isType(t) {
 				typeof[n] = "type *" + getType(t)
 			} else if strings.HasPrefix(t, "*") {
@@ -437,7 +493,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 			// &x for x of type T has type *T.
 			t := typeof[n.X]
 			if t != "" && n.Op == token.AND {
-				typeof[n] = "&" + t
+				typeof[n] = "*" + t
 			}
 
 		case *ast.CompositeLit:
@@ -448,6 +504,39 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 			// (x) has type of x.
 			typeof[n] = typeof[n.X]
 
+		case *ast.RangeStmt:
+			t := expand(typeof[n.X])
+			if t == "" {
+				return
+			}
+			var key, value string
+			if t == "string" {
+				key, value = "int", "rune"
+			} else if strings.HasPrefix(t, "[") {
+				key = "int"
+				if i := strings.Index(t, "]"); i >= 0 {
+					value = t[i+1:]
+				}
+			} else if strings.HasPrefix(t, "map[") {
+				if i := strings.Index(t, "]"); i >= 0 {
+					key, value = t[4:i], t[i+1:]
+				}
+			}
+			changed := false
+			if n.Key != nil && key != "" {
+				changed = true
+				set(n.Key, key, n.Tok == token.DEFINE)
+			}
+			if n.Value != nil && value != "" {
+				changed = true
+				set(n.Value, value, n.Tok == token.DEFINE)
+			}
+			// Ugly failure of vision: already type-checked body.
+			// Do it again now that we have that type info.
+			if changed {
+				typecheck1(cfg, n.Body, typeof, assign)
+			}
+
 		case *ast.TypeSwitchStmt:
 			// Type of variable changes for each case in type switch,
 			// but go/parser generates just one variable.
@@ -471,7 +560,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string) {
 						tt = getType(tt)
 						typeof[varx] = tt
 						typeof[varx.Obj] = tt
-						typecheck1(cfg, cas.Body, typeof)
+						typecheck1(cfg, cas.Body, typeof, assign)
 					}
 				}
 			}
diff --git a/src/cmd/gofix/url.go b/src/cmd/gofix/url.go
index 7135d8e..49aac73 100644
--- a/src/cmd/gofix/url.go
+++ b/src/cmd/gofix/url.go
@@ -4,17 +4,15 @@
 
 package main
 
-import (
-	"fmt"
-	"os"
-	"go/ast"
-)
+import "go/ast"
 
-var _ fmt.Stringer
-var _ os.Error
+func init() {
+	register(urlFix)
+}
 
 var urlFix = fix{
 	"url",
+	"2011-08-17",
 	url,
 	`Move the URL pieces of package http into a new package, url.
 
@@ -22,10 +20,6 @@ http://codereview.appspot.com/4893043
 `,
 }
 
-func init() {
-	register(urlFix)
-}
-
 var urlRenames = []struct{ in, out string }{
 	{"URL", "URL"},
 	{"ParseURL", "Parse"},
@@ -46,12 +40,7 @@ func url(f *ast.File) bool {
 	fixed := false
 
 	// Update URL code.
-	var skip interface{}
 	urlWalk := func(n interface{}) {
-		if n == skip {
-			skip = nil
-			return
-		}
 		// Is it an identifier?
 		if ident, ok := n.(*ast.Ident); ok && ident.Name == "url" {
 			ident.Name = "url_"
@@ -62,12 +51,6 @@ func url(f *ast.File) bool {
 			fixed = urlDoFields(fn.Params) || fixed
 			fixed = urlDoFields(fn.Results) || fixed
 		}
-		// U{url: ...} is likely a struct field.
-		if kv, ok := n.(*ast.KeyValueExpr); ok {
-			if ident, ok := kv.Key.(*ast.Ident); ok && ident.Name == "url" {
-				skip = ident
-			}
-		}
 	}
 
 	// Fix up URL code and add import, at most once.
@@ -75,8 +58,8 @@ func url(f *ast.File) bool {
 		if fixed {
 			return
 		}
-		walkBeforeAfter(f, urlWalk, nop)
 		addImport(f, "url")
+		walkBeforeAfter(f, urlWalk, nop)
 		fixed = true
 	}
 
diff --git a/src/cmd/gofix/url_test.go b/src/cmd/gofix/url_test.go
index 8d9542c..39827f7 100644
--- a/src/cmd/gofix/url_test.go
+++ b/src/cmd/gofix/url_test.go
@@ -5,7 +5,7 @@
 package main
 
 func init() {
-	addTestCases(urlTests)
+	addTestCases(urlTests, url)
 }
 
 var urlTests = []testCase{
@@ -103,14 +103,14 @@ func h() (url string) {
 
 import "url"
 
-type U struct{ url int }
+type U struct{ url_ int }
 type M map[int]int
 
 func f() {
 	url.Parse(a)
 	var url_ = 23
 	url_, x := 45, y
-	_ = U{url: url_}
+	_ = U{url_: url_}
 	_ = M{url_ + 1: url_}
 }
 
diff --git a/src/cmd/gofix/xmlapi.go b/src/cmd/gofix/xmlapi.go
new file mode 100644
index 0000000..e744259
--- /dev/null
+++ b/src/cmd/gofix/xmlapi.go
@@ -0,0 +1,111 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"go/ast"
+)
+
+func init() {
+	register(xmlapiFix)
+}
+
+var xmlapiFix = fix{
+	"xmlapi",
+	"2012-01-23",
+	xmlapi,
+	`
+	Make encoding/xml's API look more like the rest of the encoding packages.
+
+http://codereview.appspot.com/5574053
+`,
+}
+
+var xmlapiTypeConfig = &TypeConfig{
+	Func: map[string]string{
+		"xml.NewParser":         "*xml.Parser",
+		"os.Open":               "*os.File",
+		"os.OpenFile":           "*os.File",
+		"bytes.NewBuffer":       "*bytes.Buffer",
+		"bytes.NewBufferString": "*bytes.Buffer",
+		"bufio.NewReader":       "*bufio.Reader",
+		"bufio.NewReadWriter":   "*bufio.ReadWriter",
+	},
+}
+
+var isReader = map[string]bool{
+	"*os.File":          true,
+	"*bytes.Buffer":     true,
+	"*bufio.Reader":     true,
+	"*bufio.ReadWriter": true,
+	"io.Reader":         true,
+}
+
+func xmlapi(f *ast.File) bool {
+	if !imports(f, "encoding/xml") {
+		return false
+	}
+
+	typeof, _ := typecheck(xmlapiTypeConfig, f)
+
+	fixed := false
+	walk(f, func(n interface{}) {
+		s, ok := n.(*ast.SelectorExpr)
+		if ok && typeof[s.X] == "*xml.Parser" && s.Sel.Name == "Unmarshal" {
+			s.Sel.Name = "DecodeElement"
+			fixed = true
+			return
+		}
+		if ok && isPkgDot(s, "xml", "Parser") {
+			s.Sel.Name = "Decoder"
+			fixed = true
+			return
+		}
+
+		call, ok := n.(*ast.CallExpr)
+		if !ok {
+			return
+		}
+		switch {
+		case len(call.Args) == 2 && isPkgDot(call.Fun, "xml", "Marshal"):
+			*call = xmlMarshal(call.Args)
+			fixed = true
+		case len(call.Args) == 2 && isPkgDot(call.Fun, "xml", "Unmarshal"):
+			if isReader[typeof[call.Args[0]]] {
+				*call = xmlUnmarshal(call.Args)
+				fixed = true
+			}
+		case len(call.Args) == 1 && isPkgDot(call.Fun, "xml", "NewParser"):
+			sel := call.Fun.(*ast.SelectorExpr).Sel
+			sel.Name = "NewDecoder"
+			fixed = true
+		}
+	})
+	return fixed
+}
+
+func xmlMarshal(args []ast.Expr) ast.CallExpr {
+	return xmlCallChain("NewEncoder", "Encode", args)
+}
+
+func xmlUnmarshal(args []ast.Expr) ast.CallExpr {
+	return xmlCallChain("NewDecoder", "Decode", args)
+}
+
+func xmlCallChain(first, second string, args []ast.Expr) ast.CallExpr {
+	return ast.CallExpr{
+		Fun: &ast.SelectorExpr{
+			X: &ast.CallExpr{
+				Fun: &ast.SelectorExpr{
+					X:   ast.NewIdent("xml"),
+					Sel: ast.NewIdent(first),
+				},
+				Args: args[:1],
+			},
+			Sel: ast.NewIdent(second),
+		},
+		Args: args[1:2],
+	}
+}
diff --git a/src/cmd/gofix/xmlapi_test.go b/src/cmd/gofix/xmlapi_test.go
new file mode 100644
index 0000000..6486c81
--- /dev/null
+++ b/src/cmd/gofix/xmlapi_test.go
@@ -0,0 +1,85 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func init() {
+	addTestCases(xmlapiTests, xmlapi)
+}
+
+var xmlapiTests = []testCase{
+	{
+		Name: "xmlapi.0",
+		In: `package main
+
+import "encoding/xml"
+
+func f() {
+	xml.Marshal(a, b)
+	xml.Unmarshal(a, b)
+
+	var buf1 bytes.Buffer
+	buf2 := &bytes.Buffer{}
+	buf3 := bytes.NewBuffer(data)
+	buf4 := bytes.NewBufferString(data)
+	buf5 := bufio.NewReader(r)
+	xml.Unmarshal(&buf1, v)
+	xml.Unmarshal(buf2, v)
+	xml.Unmarshal(buf3, v)
+	xml.Unmarshal(buf4, v)
+	xml.Unmarshal(buf5, v)
+
+	f := os.Open("foo.xml")
+	xml.Unmarshal(f, v)
+
+	p1 := xml.NewParser(stream)
+	p1.Unmarshal(v, start)
+
+	var p2 *xml.Parser
+	p2.Unmarshal(v, start)
+}
+
+func g(r io.Reader, f *os.File, b []byte) {
+	xml.Unmarshal(r, v)
+	xml.Unmarshal(f, v)
+	xml.Unmarshal(b, v)
+}
+`,
+		Out: `package main
+
+import "encoding/xml"
+
+func f() {
+	xml.NewEncoder(a).Encode(b)
+	xml.Unmarshal(a, b)
+
+	var buf1 bytes.Buffer
+	buf2 := &bytes.Buffer{}
+	buf3 := bytes.NewBuffer(data)
+	buf4 := bytes.NewBufferString(data)
+	buf5 := bufio.NewReader(r)
+	xml.NewDecoder(&buf1).Decode(v)
+	xml.NewDecoder(buf2).Decode(v)
+	xml.NewDecoder(buf3).Decode(v)
+	xml.NewDecoder(buf4).Decode(v)
+	xml.NewDecoder(buf5).Decode(v)
+
+	f := os.Open("foo.xml")
+	xml.NewDecoder(f).Decode(v)
+
+	p1 := xml.NewDecoder(stream)
+	p1.DecodeElement(v, start)
+
+	var p2 *xml.Decoder
+	p2.DecodeElement(v, start)
+}
+
+func g(r io.Reader, f *os.File, b []byte) {
+	xml.NewDecoder(r).Decode(v)
+	xml.NewDecoder(f).Decode(v)
+	xml.Unmarshal(b, v)
+}
+`,
+	},
+}
diff --git a/src/cmd/gofmt/doc.go b/src/cmd/gofmt/doc.go
index 3a20c21..65842a3 100644
--- a/src/cmd/gofmt/doc.go
+++ b/src/cmd/gofmt/doc.go
@@ -36,10 +36,8 @@ The flags are:
 Formatting control flags:
 	-comments=true
 		Print comments; if false, all comments are elided from the output.
-	-spaces
-		Align with spaces instead of tabs.
-	-tabindent
-		Indent with tabs independent of -spaces.
+	-tabs=true
+		Indent with tabs; if false, spaces are used instead.
 	-tabwidth=8
 		Tab width in spaces.
 
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 1c0efb6..6d610ad 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -6,7 +6,6 @@ package main
 
 import (
 	"bytes"
-	"exec"
 	"flag"
 	"fmt"
 	"go/ast"
@@ -17,6 +16,7 @@ import (
 	"io"
 	"io/ioutil"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"runtime/pprof"
 	"strings"
@@ -34,8 +34,7 @@ var (
 	// layout control
 	comments  = flag.Bool("comments", true, "print comments")
 	tabWidth  = flag.Int("tabwidth", 8, "tab width")
-	tabIndent = flag.Bool("tabindent", true, "indent with tabs independent of -spaces")
-	useSpaces = flag.Bool("spaces", true, "align with spaces instead of tabs")
+	tabIndent = flag.Bool("tabs", true, "indent with tabs")
 
 	// debugging
 	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
@@ -45,11 +44,11 @@ var (
 	fset        = token.NewFileSet()
 	exitCode    = 0
 	rewrite     func(*ast.File) *ast.File
-	parserMode  uint
+	parserMode  parser.Mode
 	printerMode uint
 )
 
-func report(err os.Error) {
+func report(err error) {
 	scanner.PrintError(os.Stderr, err)
 	exitCode = 2
 }
@@ -61,7 +60,7 @@ func usage() {
 }
 
 func initParserMode() {
-	parserMode = uint(0)
+	parserMode = parser.Mode(0)
 	if *comments {
 		parserMode |= parser.ParseComments
 	}
@@ -71,22 +70,20 @@ func initParserMode() {
 }
 
 func initPrinterMode() {
-	printerMode = uint(0)
+	printerMode = printer.UseSpaces
 	if *tabIndent {
 		printerMode |= printer.TabIndent
 	}
-	if *useSpaces {
-		printerMode |= printer.UseSpaces
-	}
 }
 
-func isGoFile(f *os.FileInfo) bool {
+func isGoFile(f os.FileInfo) bool {
 	// ignore non-Go files
-	return f.IsRegular() && !strings.HasPrefix(f.Name, ".") && strings.HasSuffix(f.Name, ".go")
+	name := f.Name()
+	return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
 }
 
 // If in == nil, the source is the contents of the file with the given filename.
-func processFile(filename string, in io.Reader, out io.Writer, stdin bool) os.Error {
+func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error {
 	if in == nil {
 		f, err := os.Open(filename)
 		if err != nil {
@@ -107,19 +104,28 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) os.Er
 	}
 
 	if rewrite != nil {
-		file = rewrite(file)
+		if adjust == nil {
+			file = rewrite(file)
+		} else {
+			fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n")
+		}
 	}
 
+	ast.SortImports(fset, file)
+
 	if *simplifyAST {
 		simplify(file)
 	}
 
 	var buf bytes.Buffer
-	_, err = (&printer.Config{printerMode, *tabWidth}).Fprint(&buf, fset, file)
+	err = (&printer.Config{printerMode, *tabWidth}).Fprint(&buf, fset, file)
 	if err != nil {
 		return err
 	}
-	res := adjust(src, buf.Bytes())
+	res := buf.Bytes()
+	if adjust != nil {
+		res = adjust(src, res)
+	}
 
 	if !bytes.Equal(src, res) {
 		// formatting has changed
@@ -149,7 +155,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) os.Er
 	return err
 }
 
-func visitFile(path string, f *os.FileInfo, err os.Error) os.Error {
+func visitFile(path string, f os.FileInfo, err error) error {
 	if err == nil && isGoFile(f) {
 		err = processFile(path, nil, os.Stdout, false)
 	}
@@ -208,17 +214,17 @@ func gofmtMain() {
 		switch dir, err := os.Stat(path); {
 		case err != nil:
 			report(err)
-		case dir.IsRegular():
+		case dir.IsDir():
+			walkDir(path)
+		default:
 			if err := processFile(path, nil, os.Stdout, false); err != nil {
 				report(err)
 			}
-		case dir.IsDirectory():
-			walkDir(path)
 		}
 	}
 }
 
-func diff(b1, b2 []byte) (data []byte, err os.Error) {
+func diff(b1, b2 []byte) (data []byte, err error) {
 	f1, err := ioutil.TempFile("", "gofmt")
 	if err != nil {
 		return
@@ -248,17 +254,16 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) {
 
 // parse parses src, which was read from filename,
 // as a Go source file or statement list.
-func parse(filename string, src []byte, stdin bool) (*ast.File, func(orig, src []byte) []byte, os.Error) {
+func parse(filename string, src []byte, stdin bool) (*ast.File, func(orig, src []byte) []byte, error) {
 	// Try as whole source file.
 	file, err := parser.ParseFile(fset, filename, src, parserMode)
 	if err == nil {
-		adjust := func(orig, src []byte) []byte { return src }
-		return file, adjust, nil
+		return file, nil, nil
 	}
 	// If the error is that the source file didn't begin with a
 	// package line and this is standard input, fall through to
 	// try as a source fragment.  Stop and return on any other error.
-	if !stdin || !strings.Contains(err.String(), "expected 'package'") {
+	if !stdin || !strings.Contains(err.Error(), "expected 'package'") {
 		return nil, nil, err
 	}
 
@@ -280,7 +285,7 @@ func parse(filename string, src []byte, stdin bool) (*ast.File, func(orig, src [
 	// If the error is that the source file didn't begin with a
 	// declaration, fall through to try as a statement list.
 	// Stop and return on any other error.
-	if !strings.Contains(err.String(), "expected declaration") {
+	if !strings.Contains(err.Error(), "expected declaration") {
 		return nil, nil, err
 	}
 
@@ -318,7 +323,10 @@ func cutSpace(b []byte) (before, middle, after []byte) {
 	for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') {
 		j--
 	}
-	return b[:i], b[i:j], b[j:]
+	if i <= j {
+		return b[:i], b[i:j], b[j:]
+	}
+	return nil, nil, b[j:]
 }
 
 // matchSpace reformats src to use the same space context as orig.
diff --git a/src/cmd/gofmt/gofmt_test.go b/src/cmd/gofmt/gofmt_test.go
index 87b02da..303c4f1 100644
--- a/src/cmd/gofmt/gofmt_test.go
+++ b/src/cmd/gofmt/gofmt_test.go
@@ -76,7 +76,10 @@ var tests = []struct {
 	{"testdata/old.input", ""},
 	{"testdata/rewrite1.input", "-r=Foo->Bar"},
 	{"testdata/rewrite2.input", "-r=int->bool"},
+	{"testdata/rewrite3.input", "-r=x->x"},
 	{"testdata/stdin*.input", "-stdin"},
+	{"testdata/comments.input", ""},
+	{"testdata/import.input", ""},
 }
 
 func TestRewrite(t *testing.T) {
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index 3d74dea..3c7861f 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -13,7 +13,7 @@ import (
 	"reflect"
 	"strings"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 func initRewrite() {
@@ -36,7 +36,7 @@ func initRewrite() {
 // but there are problems with preserving formatting and also
 // with what a wildcard for a statement looks like.
 func parseExpr(s string, what string) ast.Expr {
-	x, err := parser.ParseExpr(fset, "input", s)
+	x, err := parser.ParseExpr(s)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err)
 		os.Exit(2)
@@ -65,7 +65,7 @@ func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
 			return reflect.Value{}
 		}
 		for k := range m {
-			m[k] = reflect.Value{}, false
+			delete(m, k)
 		}
 		val = apply(f, val)
 		if match(m, pat, val) {
@@ -85,7 +85,8 @@ func setValue(x, y reflect.Value) {
 	}
 	defer func() {
 		if x := recover(); x != nil {
-			if s, ok := x.(string); ok && strings.HasPrefix(s, "type mismatch") {
+			if s, ok := x.(string); ok &&
+				(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
 				// x cannot be set to y - ignore this rewrite
 				return
 			}
@@ -158,8 +159,8 @@ func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
 	if m != nil && pattern.IsValid() && pattern.Type() == identType {
 		name := pattern.Interface().(*ast.Ident).Name
 		if isWildcard(name) && val.IsValid() {
-			// wildcards only match expressions
-			if _, ok := val.Interface().(ast.Expr); ok {
+			// wildcards only match valid (non-nil) expressions.
+			if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() {
 				if old, ok := m[name]; ok {
 					return match(nil, old, val)
 				}
diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go
index d9afc0e..470c006 100644
--- a/src/cmd/gofmt/simplify.go
+++ b/src/cmd/gofmt/simplify.go
@@ -6,6 +6,7 @@ package main
 
 import (
 	"go/ast"
+	"go/token"
 	"reflect"
 )
 
@@ -26,10 +27,12 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
 
 		if eltType != nil {
 			typ := reflect.ValueOf(eltType)
-			for _, x := range outer.Elts {
+			for i, x := range outer.Elts {
+				px := &outer.Elts[i]
 				// look at value of indexed/named elements
 				if t, ok := x.(*ast.KeyValueExpr); ok {
 					x = t.Value
+					px = &t.Value
 				}
 				simplify(x)
 				// if the element is a composite literal and its literal type
@@ -40,6 +43,19 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor {
 						inner.Type = nil
 					}
 				}
+				// if the outer literal's element type is a pointer type *T
+				// and the element is & of a composite literal of type T,
+				// the inner &T may be omitted.
+				if ptr, ok := eltType.(*ast.StarExpr); ok {
+					if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND {
+						if inner, ok := addr.X.(*ast.CompositeLit); ok {
+							if match(nil, reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) {
+								inner.Type = nil // drop T
+								*px = inner      // drop &
+							}
+						}
+					}
+				}
 			}
 
 			// node was simplified - stop walk (there are no subnodes to simplify)
diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh
index 063a072..c18987f 100755
--- a/src/cmd/gofmt/test.sh
+++ b/src/cmd/gofmt/test.sh
@@ -14,6 +14,7 @@ TMP1=test_tmp1.go
 TMP2=test_tmp2.go
 TMP3=test_tmp3.go
 COUNT=0
+rm -f _failed
 
 count() {
 	#echo $1
@@ -27,10 +28,9 @@ count() {
 
 error() {
 	echo $1
-	exit 1
+	touch _failed
 }
 
-
 # apply to one file
 apply1() {
 	# the following files are skipped because they are test cases
@@ -43,7 +43,8 @@ apply1() {
 	bug226.go | bug228.go | bug248.go | bug274.go | bug280.go | \
 	bug282.go | bug287.go | bug298.go | bug299.go | bug300.go | \
 	bug302.go | bug306.go | bug322.go | bug324.go | bug335.go | \
-	bug340.go | bug349.go | bug351.go | bug358.go ) return ;;
+	bug340.go | bug349.go | bug351.go | bug358.go | bug367.go | \
+	bug388.go | bug394.go ) return ;;
 	esac
 	# the following directories are skipped because they contain test
 	# cases for syntax errors and thus won't parse in the first place:
@@ -157,6 +158,11 @@ runtests() {
 runtests "$@"
 cleanup
 
+if [ -f _failed ]; then
+	rm _failed
+	exit 1
+fi
+
 # done
 echo
 echo "PASSED ($COUNT tests)"
diff --git a/src/cmd/gofmt/testdata/comments.golden b/src/cmd/gofmt/testdata/comments.golden
new file mode 100644
index 0000000..ad6bcaf
--- /dev/null
+++ b/src/cmd/gofmt/testdata/comments.golden
@@ -0,0 +1,9 @@
+package main
+
+func main() {}
+
+// comment here
+
+func f() {}
+
+//line foo.go:1
diff --git a/src/cmd/gofmt/testdata/comments.input b/src/cmd/gofmt/testdata/comments.input
new file mode 100644
index 0000000..ad6bcaf
--- /dev/null
+++ b/src/cmd/gofmt/testdata/comments.input
@@ -0,0 +1,9 @@
+package main
+
+func main() {}
+
+// comment here
+
+func f() {}
+
+//line foo.go:1
diff --git a/src/cmd/gofmt/testdata/composites.golden b/src/cmd/gofmt/testdata/composites.golden
index 1fd5847..b2825e7 100644
--- a/src/cmd/gofmt/testdata/composites.golden
+++ b/src/cmd/gofmt/testdata/composites.golden
@@ -102,3 +102,101 @@ var pieces4 = []Piece{
 	{2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
 	{3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
 }
+
+var _ = [42]*T{
+	{},
+	{1, 2},
+	{3, 4},
+}
+
+var _ = [...]*T{
+	{},
+	{1, 2},
+	{3, 4},
+}
+
+var _ = []*T{
+	{},
+	{1, 2},
+	{3, 4},
+}
+
+var _ = []*T{
+	{},
+	10: {1, 2},
+	20: {3, 4},
+}
+
+var _ = []*struct {
+	x, y int
+}{
+	{},
+	10: {1, 2},
+	20: {3, 4},
+}
+
+var _ = []interface{}{
+	&T{},
+	10: &T{1, 2},
+	20: &T{3, 4},
+}
+
+var _ = []*[]int{
+	{},
+	{1, 2},
+	{3, 4},
+}
+
+var _ = []*[]int{
+	(&[]int{}),
+	(&[]int{1, 2}),
+	{3, 4},
+}
+
+var _ = []*[]*[]int{
+	{},
+	{
+		{},
+		{0, 1, 2, 3},
+		{4, 5},
+	},
+}
+
+var _ = map[string]*T{
+	"foo": {},
+	"bar": {1, 2},
+	"bal": {3, 4},
+}
+
+var _ = map[string]*struct {
+	x, y int
+}{
+	"foo": {},
+	"bar": {1, 2},
+	"bal": {3, 4},
+}
+
+var _ = map[string]interface{}{
+	"foo": &T{},
+	"bar": &T{1, 2},
+	"bal": &T{3, 4},
+}
+
+var _ = map[string]*[]int{
+	"foo": {},
+	"bar": {1, 2},
+	"bal": {3, 4},
+}
+
+var _ = map[string]*[]int{
+	"foo": (&[]int{}),
+	"bar": (&[]int{1, 2}),
+	"bal": {3, 4},
+}
+
+var pieces4 = []*Piece{
+	{0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
+	{1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
+	{2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
+	{3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
+}
diff --git a/src/cmd/gofmt/testdata/composites.input b/src/cmd/gofmt/testdata/composites.input
index 15afd9e..7210daf 100644
--- a/src/cmd/gofmt/testdata/composites.input
+++ b/src/cmd/gofmt/testdata/composites.input
@@ -102,3 +102,101 @@ var pieces4 = []Piece{
 	Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
 	Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
 }
+
+var _ = [42]*T{
+	&T{},
+	&T{1, 2},
+	&T{3, 4},
+}
+
+var _ = [...]*T{
+	&T{},
+	&T{1, 2},
+	&T{3, 4},
+}
+
+var _ = []*T{
+	&T{},
+	&T{1, 2},
+	&T{3, 4},
+}
+
+var _ = []*T{
+	&T{},
+	10: &T{1, 2},
+	20: &T{3, 4},
+}
+
+var _ = []*struct {
+	x, y int
+}{
+	&struct{ x, y int }{},
+	10: &struct{ x, y int }{1, 2},
+	20: &struct{ x, y int }{3, 4},
+}
+
+var _ = []interface{}{
+	&T{},
+	10: &T{1, 2},
+	20: &T{3, 4},
+}
+
+var _ = []*[]int{
+	&[]int{},
+	&[]int{1, 2},
+	&[]int{3, 4},
+}
+
+var _ = []*[]int{
+	(&[]int{}),
+	(&[]int{1, 2}),
+	&[]int{3, 4},
+}
+
+var _ = []*[]*[]int{
+	&[]*[]int{},
+	&[]*[]int{
+		&[]int{},
+		&[]int{0, 1, 2, 3},
+		&[]int{4, 5},
+	},
+}
+
+var _ = map[string]*T{
+	"foo": &T{},
+	"bar": &T{1, 2},
+	"bal": &T{3, 4},
+}
+
+var _ = map[string]*struct {
+	x, y int
+}{
+	"foo": &struct{ x, y int }{},
+	"bar": &struct{ x, y int }{1, 2},
+	"bal": &struct{ x, y int }{3, 4},
+}
+
+var _ = map[string]interface{}{
+	"foo": &T{},
+	"bar": &T{1, 2},
+	"bal": &T{3, 4},
+}
+
+var _ = map[string]*[]int{
+	"foo": &[]int{},
+	"bar": &[]int{1, 2},
+	"bal": &[]int{3, 4},
+}
+
+var _ = map[string]*[]int{
+	"foo": (&[]int{}),
+	"bar": (&[]int{1, 2}),
+	"bal": &[]int{3, 4},
+}
+
+var pieces4 = []*Piece{
+	&Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
+	&Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
+	&Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
+	&Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
+}
diff --git a/src/cmd/gofmt/testdata/import.golden b/src/cmd/gofmt/testdata/import.golden
new file mode 100644
index 0000000..e8ee449
--- /dev/null
+++ b/src/cmd/gofmt/testdata/import.golden
@@ -0,0 +1,108 @@
+package main
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"math"
+)
+
+import (
+	"fmt"
+
+	"math"
+
+	"log"
+
+	"errors"
+
+	"io"
+)
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"math"
+
+	"fmt"
+
+	"math"
+
+	"log"
+
+	"errors"
+
+	"io"
+)
+
+import (
+	// a block with comments
+	"errors"
+	"fmt" // for Printf
+	"io"  // for Reader
+	"log" // for Fatal
+	"math"
+)
+
+import (
+	"fmt" // for Printf
+
+	"math"
+
+	"log" // for Fatal
+
+	"errors"
+
+	"io" // for Reader
+)
+
+import (
+	// for Printf
+	"fmt"
+
+	"math"
+
+	// for Fatal
+	"log"
+
+	"errors"
+
+	// for Reader
+	"io"
+)
+
+import (
+	"errors"
+	"fmt" // for Printf
+	"io"  // for Reader
+	"log" // for Fatal
+	"math"
+
+	"fmt" // for Printf
+
+	"math"
+
+	"log" // for Fatal
+
+	"errors"
+
+	"io" // for Reader
+)
+
+import (
+	"fmt" // for Printf
+
+	"errors"
+	"io"  // for Reader
+	"log" // for Fatal
+	"math"
+
+	"errors"
+	"fmt" // for Printf
+	"io"  // for Reader
+	"log" // for Fatal
+	"math"
+)
diff --git a/src/cmd/gofmt/testdata/import.input b/src/cmd/gofmt/testdata/import.input
new file mode 100644
index 0000000..cc36c3e
--- /dev/null
+++ b/src/cmd/gofmt/testdata/import.input
@@ -0,0 +1,108 @@
+package main
+
+import (
+	"fmt"
+	"math"
+	"log"
+	"errors"
+	"io"
+)
+
+import (
+	"fmt"
+
+	"math"
+
+	"log"
+
+	"errors"
+
+	"io"
+)
+
+import (
+	"fmt"
+	"math"
+	"log"
+	"errors"
+	"io"
+
+	"fmt"
+
+	"math"
+
+	"log"
+
+	"errors"
+
+	"io"
+)
+
+import (
+	// a block with comments
+	"fmt" // for Printf
+	"math"
+	"log" // for Fatal
+	"errors"
+	"io" // for Reader
+)
+
+import (
+	"fmt" // for Printf
+
+	"math"
+
+	"log" // for Fatal
+
+	"errors"
+
+	"io" // for Reader
+)
+
+import (
+	// for Printf
+	"fmt"
+
+	"math"
+
+	// for Fatal
+	"log"
+
+	"errors"
+
+	// for Reader
+	"io"
+)
+
+import (
+	"fmt" // for Printf
+	"math"
+	"log" // for Fatal
+	"errors"
+	"io" // for Reader
+
+	"fmt" // for Printf
+
+	"math"
+
+	"log" // for Fatal
+
+	"errors"
+
+	"io" // for Reader
+)
+
+import (
+	"fmt" // for Printf
+
+	"math"
+	"log" // for Fatal
+	"errors"
+	"io" // for Reader
+
+	"fmt" // for Printf
+	"math"
+	"log" // for Fatal
+	"errors"
+	"io" // for Reader
+)
diff --git a/src/cmd/gofmt/testdata/rewrite3.golden b/src/cmd/gofmt/testdata/rewrite3.golden
new file mode 100644
index 0000000..0d16d16
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite3.golden
@@ -0,0 +1,12 @@
+// Copyright 2011 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
+
+// Field tags are *ast.BasicLit nodes that are nil when the tag is
+// absent. These nil nodes must not be mistaken for expressions,
+// the rewriter should not try to dereference them. Was issue 2410.
+type Foo struct {
+	Field int
+}
diff --git a/src/cmd/gofmt/testdata/rewrite3.input b/src/cmd/gofmt/testdata/rewrite3.input
new file mode 100644
index 0000000..0d16d16
--- /dev/null
+++ b/src/cmd/gofmt/testdata/rewrite3.input
@@ -0,0 +1,12 @@
+// Copyright 2011 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
+
+// Field tags are *ast.BasicLit nodes that are nil when the tag is
+// absent. These nil nodes must not be mistaken for expressions,
+// the rewriter should not try to dereference them. Was issue 2410.
+type Foo struct {
+	Field int
+}
diff --git a/src/cmd/goinstall/doc.go b/src/cmd/goinstall/doc.go
index 47c6153..368e170 100644
--- a/src/cmd/goinstall/doc.go
+++ b/src/cmd/goinstall/doc.go
@@ -58,7 +58,7 @@ download the code if necessary.
 
 Goinstall recognizes packages from a few common code hosting sites:
 
-	BitBucket (Mercurial)
+	BitBucket (Git, Mercurial)
 
 		import "bitbucket.org/user/project"
 		import "bitbucket.org/user/project/sub/directory"
@@ -79,6 +79,10 @@ Goinstall recognizes packages from a few common code hosting sites:
 		import "project.googlecode.com/svn/trunk"
 		import "project.googlecode.com/svn/trunk/sub/directory"
 
+	Google Code Project Hosting sub-repositories:
+
+		import "code.google.com/p/project.subrepo/sub/directory
+
 	Launchpad (Bazaar)
 
 		import "launchpad.net/project"
diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go
index cc87315..8e6cb4b 100644
--- a/src/cmd/goinstall/download.go
+++ b/src/cmd/goinstall/download.go
@@ -8,10 +8,13 @@ package main
 
 import (
 	"bytes"
-	"exec"
+	"encoding/json"
+	"errors"
 	"fmt"
-	"http"
+	"io/ioutil"
+	"net/http"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"regexp"
 	"runtime"
@@ -53,207 +56,422 @@ type vcs struct {
 	check         string
 	protocols     []string
 	suffix        string
-	defaultHosts  []host
 }
 
-type host struct {
-	pattern  *regexp.Regexp
-	protocol string
-	suffix   string
+func (v *vcs) String() string {
+	return v.name
 }
 
-var hg = vcs{
-	name:      "Mercurial",
-	cmd:       "hg",
-	metadir:   ".hg",
-	checkout:  "checkout",
-	clone:     "clone",
-	update:    "update",
-	pull:      "pull",
-	tagList:   "tags",
-	tagListRe: regexp.MustCompile("([^ ]+)[^\n]+\n"),
-	check:     "identify",
-	protocols: []string{"https", "http"},
-	suffix:    ".hg",
-	defaultHosts: []host{
-		{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/hg)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
-		{regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ""},
+var vcsMap = map[string]*vcs{
+	"hg": {
+		name:      "Mercurial",
+		cmd:       "hg",
+		metadir:   ".hg",
+		checkout:  "checkout",
+		clone:     "clone",
+		update:    "update",
+		pull:      "pull",
+		tagList:   "tags",
+		tagListRe: regexp.MustCompile("([^ ]+)[^\n]+\n"),
+		check:     "identify",
+		protocols: []string{"https", "http"},
+		suffix:    ".hg",
 	},
-}
 
-var git = vcs{
-	name:      "Git",
-	cmd:       "git",
-	metadir:   ".git",
-	checkout:  "checkout",
-	clone:     "clone",
-	update:    "pull",
-	pull:      "fetch",
-	tagList:   "tag",
-	tagListRe: regexp.MustCompile("([^\n]+)\n"),
-	check:     "ls-remote",
-	protocols: []string{"git", "https", "http"},
-	suffix:    ".git",
-	defaultHosts: []host{
-		{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/git)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
-		{regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), "http", ".git"},
+	"git": {
+		name:      "Git",
+		cmd:       "git",
+		metadir:   ".git",
+		checkout:  "checkout",
+		clone:     "clone",
+		update:    "pull",
+		pull:      "fetch",
+		tagList:   "tag",
+		tagListRe: regexp.MustCompile("([^\n]+)\n"),
+		check:     "ls-remote",
+		protocols: []string{"git", "https", "http"},
+		suffix:    ".git",
+	},
+
+	"svn": {
+		name:      "Subversion",
+		cmd:       "svn",
+		metadir:   ".svn",
+		checkout:  "checkout",
+		clone:     "checkout",
+		update:    "update",
+		check:     "info",
+		protocols: []string{"https", "http", "svn"},
+		suffix:    ".svn",
 	},
-}
 
-var svn = vcs{
-	name:      "Subversion",
-	cmd:       "svn",
-	metadir:   ".svn",
-	checkout:  "checkout",
-	clone:     "checkout",
-	update:    "update",
-	check:     "info",
-	protocols: []string{"https", "http", "svn"},
-	suffix:    ".svn",
-	defaultHosts: []host{
-		{regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/svn)(/[a-z0-9A-Z_.\-/]*)?$`), "https", ""},
+	"bzr": {
+		name:          "Bazaar",
+		cmd:           "bzr",
+		metadir:       ".bzr",
+		checkout:      "update",
+		clone:         "branch",
+		update:        "update",
+		updateRevFlag: "-r",
+		pull:          "pull",
+		pullForceFlag: "--overwrite",
+		tagList:       "tags",
+		tagListRe:     regexp.MustCompile("([^ ]+)[^\n]+\n"),
+		check:         "info",
+		protocols:     []string{"https", "http", "bzr"},
+		suffix:        ".bzr",
 	},
 }
 
-var bzr = vcs{
-	name:          "Bazaar",
-	cmd:           "bzr",
-	metadir:       ".bzr",
-	checkout:      "update",
-	clone:         "branch",
-	update:        "update",
-	updateRevFlag: "-r",
-	pull:          "pull",
-	pullForceFlag: "--overwrite",
-	tagList:       "tags",
-	tagListRe:     regexp.MustCompile("([^ ]+)[^\n]+\n"),
-	check:         "info",
-	protocols:     []string{"https", "http", "bzr"},
-	suffix:        ".bzr",
-	defaultHosts: []host{
-		{regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`), "https", ""},
+type RemoteRepo interface {
+	// IsCheckedOut returns whether this repository is checked
+	// out inside the given srcDir (eg, $GOPATH/src).
+	IsCheckedOut(srcDir string) bool
+
+	// Repo returns the information about this repository: its url,
+	// the part of the import path that forms the repository root,
+	// and the version control system it uses. It may discover this
+	// information by using the supplied client to make HTTP requests.
+	Repo(*http.Client) (url, root string, vcs *vcs, err error)
+}
+
+type host struct {
+	pattern *regexp.Regexp
+	repo    func(repo string) (RemoteRepo, error)
+}
+
+var knownHosts = []host{
+	{
+		regexp.MustCompile(`^code\.google\.com/p/([a-z0-9\-]+(\.[a-z0-9\-]+)?)(/[a-z0-9A-Z_.\-/]+)?$`),
+		matchGoogleRepo,
+	},
+	{
+		regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]+)?$`),
+		matchGithubRepo,
+	},
+	{
+		regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]+)?$`),
+		matchBitbucketRepo,
+	},
+	{
+		regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`),
+		matchLaunchpadRepo,
 	},
 }
 
-var vcsList = []*vcs{&git, &hg, &bzr, &svn}
+// baseRepo is the base implementation of RemoteRepo.
+type baseRepo struct {
+	url, root string
+	vcs       *vcs
+}
 
-type vcsMatch struct {
-	*vcs
-	prefix, repo string
+func (r *baseRepo) Repo(*http.Client) (url, root string, vcs *vcs, err error) {
+	return r.url, r.root, r.vcs, nil
 }
 
-// findPublicRepo checks whether pkg is located at one of
-// the supported code hosting sites and, if so, returns a match.
-func findPublicRepo(pkg string) (*vcsMatch, os.Error) {
-	for _, v := range vcsList {
-		for _, host := range v.defaultHosts {
-			if hm := host.pattern.FindStringSubmatch(pkg); hm != nil {
-				if host.suffix != "" && strings.HasSuffix(hm[1], host.suffix) {
-					return nil, os.NewError("repository " + pkg + " should not have " + v.suffix + " suffix")
-				}
-				repo := host.protocol + "://" + hm[1] + host.suffix
-				return &vcsMatch{v, hm[1], repo}, nil
+// IsCheckedOut reports whether the repo root inside srcDir contains a
+// repository metadir. It updates the baseRepo's vcs field if necessary.
+func (r *baseRepo) IsCheckedOut(srcDir string) bool {
+	pkgPath := filepath.Join(srcDir, r.root)
+	if r.vcs == nil {
+		for _, vcs := range vcsMap {
+			if isDir(filepath.Join(pkgPath, vcs.metadir)) {
+				r.vcs = vcs
+				return true
 			}
 		}
+		return false
+	}
+	return isDir(filepath.Join(pkgPath, r.vcs.metadir))
+}
+
+// matchGithubRepo handles matches for github.com repositories.
+func matchGithubRepo(root string) (RemoteRepo, error) {
+	if strings.HasSuffix(root, ".git") {
+		return nil, errors.New("path must not include .git suffix")
+	}
+	return &baseRepo{"http://" + root + ".git", root, vcsMap["git"]}, nil
+}
+
+// matchLaunchpadRepo handles matches for launchpad.net repositories.
+func matchLaunchpadRepo(root string) (RemoteRepo, error) {
+	return &baseRepo{"https://" + root, root, vcsMap["bzr"]}, nil
+}
+
+// matchGoogleRepo matches repos like "code.google.com/p/repo.subrepo/path".
+func matchGoogleRepo(id string) (RemoteRepo, error) {
+	root := "code.google.com/p/" + id
+	return &googleRepo{baseRepo{"https://" + root, root, nil}}, nil
+}
+
+// googleRepo implements a RemoteRepo that discovers a Google Code
+// repository's VCS type by scraping the code.google.com source checkout page.
+type googleRepo struct{ baseRepo }
+
+var googleRepoRe = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
+
+func (r *googleRepo) Repo(client *http.Client) (url, root string, vcs *vcs, err error) {
+	if r.vcs != nil {
+		return r.url, r.root, r.vcs, nil
+	}
+
+	// Use the code.google.com source checkout page to find the VCS type.
+	const prefix = "code.google.com/p/"
+	p := strings.SplitN(r.root[len(prefix):], ".", 2)
+	u := fmt.Sprintf("https://%s%s/source/checkout", prefix, p[0])
+	if len(p) == 2 {
+		u += fmt.Sprintf("?repo=%s", p[1])
+	}
+	resp, err := client.Get(u)
+	if err != nil {
+		return "", "", nil, err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != 200 {
+		return "", "", nil, fmt.Errorf("fetching %s: %v", u, resp.Status)
+	}
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return "", "", nil, fmt.Errorf("fetching %s: %v", u, err)
+	}
+
+	// Scrape result for vcs details.
+	if m := googleRepoRe.FindSubmatch(b); len(m) == 2 {
+		s := string(m[1])
+		if v := vcsMap[s]; v != nil {
+			if s == "svn" {
+				// Subversion still uses the old-style URL.
+				r.url = fmt.Sprintf("http://%s.googlecode.com/svn", p[0])
+			}
+			r.vcs = v
+			return r.url, r.root, r.vcs, nil
+		}
+	}
+
+	return "", "", nil, errors.New("could not detect googlecode vcs")
+}
+
+// matchBitbucketRepo handles matches for all bitbucket.org repositories.
+func matchBitbucketRepo(root string) (RemoteRepo, error) {
+	if strings.HasSuffix(root, ".git") {
+		return nil, errors.New("path must not include .git suffix")
+	}
+	return &bitbucketRepo{baseRepo{root: root}}, nil
+}
+
+// bitbucketRepo implements a RemoteRepo that uses the BitBucket API to
+// discover the repository's VCS type.
+type bitbucketRepo struct{ baseRepo }
+
+func (r *bitbucketRepo) Repo(client *http.Client) (url, root string, vcs *vcs, err error) {
+	if r.vcs != nil && r.url != "" {
+		return r.url, r.root, r.vcs, nil
+	}
+
+	// Use the BitBucket API to find which kind of repository this is.
+	const apiUrl = "https://api.bitbucket.org/1.0/repositories/"
+	resp, err := client.Get(apiUrl + strings.SplitN(r.root, "/", 2)[1])
+	if err != nil {
+		return "", "", nil, fmt.Errorf("BitBucket API: %v", err)
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != 200 {
+		return "", "", nil, fmt.Errorf("BitBucket API: %v", resp.Status)
+	}
+	var response struct {
+		Vcs string `json:"scm"`
+	}
+	err = json.NewDecoder(resp.Body).Decode(&response)
+	if err != nil {
+		return "", "", nil, fmt.Errorf("BitBucket API: %v", err)
+	}
+	switch response.Vcs {
+	case "git":
+		r.url = "http://" + r.root + ".git"
+	case "hg":
+		r.url = "http://" + r.root
+	default:
+		return "", "", nil, errors.New("unsupported bitbucket vcs: " + response.Vcs)
+	}
+	if r.vcs = vcsMap[response.Vcs]; r.vcs == nil {
+		panic("vcs is nil when it should not be")
+	}
+	return r.url, r.root, r.vcs, nil
+}
+
+// findPublicRepo checks whether importPath is a well-formed path for one of
+// the supported code hosting sites and, if so, returns a RemoteRepo.
+func findPublicRepo(importPath string) (RemoteRepo, error) {
+	for _, host := range knownHosts {
+		if hm := host.pattern.FindStringSubmatch(importPath); hm != nil {
+			return host.repo(hm[1])
+		}
 	}
 	return nil, nil
 }
 
-// findAnyRepo looks for a vcs suffix in pkg (.git, etc) and returns a match.
-func findAnyRepo(pkg string) (*vcsMatch, os.Error) {
-	for _, v := range vcsList {
-		i := strings.Index(pkg+"/", v.suffix+"/")
+// findAnyRepo matches import paths with a repo suffix (.git, etc).
+func findAnyRepo(importPath string) RemoteRepo {
+	for _, v := range vcsMap {
+		i := strings.Index(importPath+"/", v.suffix+"/")
 		if i < 0 {
 			continue
 		}
-		if !strings.Contains(pkg[:i], "/") {
+		if !strings.Contains(importPath[:i], "/") {
 			continue // don't match vcs suffix in the host name
 		}
-		if m := v.find(pkg[:i]); m != nil {
-			return m, nil
+		return &anyRepo{
+			baseRepo{
+				root: importPath[:i] + v.suffix,
+				vcs:  v,
+			},
+			importPath[:i],
 		}
-		return nil, fmt.Errorf("couldn't find %s repository", v.name)
 	}
-	return nil, nil
+	return nil
+}
+
+// anyRepo implements an discoverable remote repo with a suffix (.git, etc).
+type anyRepo struct {
+	baseRepo
+	rootWithoutSuffix string
+}
+
+func (r *anyRepo) Repo(*http.Client) (url, root string, vcs *vcs, err error) {
+	if r.url != "" {
+		return r.url, r.root, r.vcs, nil
+	}
+	url, err = r.vcs.findURL(r.rootWithoutSuffix)
+	if url == "" && err == nil {
+		err = fmt.Errorf("couldn't find %s repository", r.vcs.name)
+	}
+	if err != nil {
+		return "", "", nil, err
+	}
+	r.url = url
+	return r.url, r.root, r.vcs, nil
 }
 
-func (v *vcs) find(pkg string) *vcsMatch {
+// findURL finds the URL for a given repo root by trying each combination of
+// protocol and suffix in series.
+func (v *vcs) findURL(root string) (string, error) {
 	for _, proto := range v.protocols {
 		for _, suffix := range []string{"", v.suffix} {
-			repo := proto + "://" + pkg + suffix
-			out, err := exec.Command(v.cmd, v.check, repo).CombinedOutput()
+			url := proto + "://" + root + suffix
+			out, err := exec.Command(v.cmd, v.check, url).CombinedOutput()
 			if err == nil {
-				printf("find %s: found %s\n", pkg, repo)
-				return &vcsMatch{v, pkg + v.suffix, repo}
+				printf("find %s: found %s\n", root, url)
+				return url, nil
 			}
-			printf("find %s: %s %s %s: %v\n%s\n", pkg, v.cmd, v.check, repo, err, out)
+			printf("findURL(%s): %s %s %s: %v\n%s\n", root, v.cmd, v.check, url, err, out)
 		}
 	}
-	return nil
+	return "", nil
 }
 
-// isRemote returns true if the first part of the package name looks like a
-// hostname - i.e. contains at least one '.' and the last part is at least 2
-// characters.
-func isRemote(pkg string) bool {
-	parts := strings.SplitN(pkg, "/", 2)
-	if len(parts) != 2 {
-		return false
-	}
-	parts = strings.Split(parts[0], ".")
-	if len(parts) < 2 || len(parts[len(parts)-1]) < 2 {
-		return false
-	}
-	return true
+var oldGoogleRepo = regexp.MustCompile(`^([a-z0-9\-]+)\.googlecode\.com/(svn|git|hg)(/[a-z0-9A-Z_.\-/]+)?$`)
+
+type errOldGoogleRepo struct {
+	fixedPath string
+}
+
+func (e *errOldGoogleRepo) Error() string {
+	return fmt.Sprintf("unsupported import path; should be %q", e.fixedPath)
 }
 
-// download checks out or updates pkg from the remote server.
-func download(pkg, srcDir string) (public bool, err os.Error) {
-	if strings.Contains(pkg, "..") {
-		err = os.NewError("invalid path (contains ..)")
+// download checks out or updates the specified package from the remote server.
+func download(importPath, srcDir string) (public bool, err error) {
+	if strings.Contains(importPath, "..") {
+		err = errors.New("invalid path (contains ..)")
 		return
 	}
-	m, err := findPublicRepo(pkg)
-	if err != nil {
+
+	if m := oldGoogleRepo.FindStringSubmatch(importPath); m != nil {
+		fixedPath := "code.google.com/p/" + m[1] + m[3]
+		err = &errOldGoogleRepo{fixedPath}
 		return
 	}
-	if m != nil {
+
+	repo, err := findPublicRepo(importPath)
+	if err != nil {
+		return false, err
+	}
+	if repo != nil {
 		public = true
 	} else {
-		m, err = findAnyRepo(pkg)
-		if err != nil {
-			return
-		}
+		repo = findAnyRepo(importPath)
 	}
-	if m == nil {
-		err = os.NewError("cannot download: " + pkg)
+	if repo == nil {
+		err = errors.New("cannot download: " + importPath)
 		return
 	}
-	err = m.checkoutRepo(srcDir, m.prefix, m.repo)
+	err = checkoutRepo(srcDir, repo)
 	return
 }
 
+// checkoutRepo checks out repo into srcDir (if it's not checked out already)
+// and, if the -u flag is set, updates the repository.
+func checkoutRepo(srcDir string, repo RemoteRepo) error {
+	if !repo.IsCheckedOut(srcDir) {
+		// do checkout
+		url, root, vcs, err := repo.Repo(http.DefaultClient)
+		if err != nil {
+			return err
+		}
+		repoPath := filepath.Join(srcDir, root)
+		parent, _ := filepath.Split(repoPath)
+		if err = os.MkdirAll(parent, 0777); err != nil {
+			return err
+		}
+		if err = run(string(filepath.Separator), nil, vcs.cmd, vcs.clone, url, repoPath); err != nil {
+			return err
+		}
+		return vcs.updateRepo(repoPath)
+	}
+	if *update {
+		// do update
+		_, root, vcs, err := repo.Repo(http.DefaultClient)
+		if err != nil {
+			return err
+		}
+		repoPath := filepath.Join(srcDir, root)
+		// Retrieve new revisions from the remote branch, if the VCS
+		// supports this operation independently (e.g. svn doesn't)
+		if vcs.pull != "" {
+			if vcs.pullForceFlag != "" {
+				if err = run(repoPath, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil {
+					return err
+				}
+			} else if err = run(repoPath, nil, vcs.cmd, vcs.pull); err != nil {
+				return err
+			}
+		}
+		// Update to release or latest revision
+		return vcs.updateRepo(repoPath)
+	}
+	return nil
+}
+
 // updateRepo gets a list of tags in the repository and
 // checks out the tag closest to the current runtime.Version.
 // If no matching tag is found, it just updates to tip.
-func (v *vcs) updateRepo(dst string) os.Error {
+func (v *vcs) updateRepo(repoPath string) error {
 	if v.tagList == "" || v.tagListRe == nil {
 		// TODO(adg): fix for svn
-		return run(dst, nil, v.cmd, v.update)
+		return run(repoPath, nil, v.cmd, v.update)
 	}
 
 	// Get tag list.
 	stderr := new(bytes.Buffer)
 	cmd := exec.Command(v.cmd, v.tagList)
-	cmd.Dir = dst
+	cmd.Dir = repoPath
 	cmd.Stderr = stderr
-	b, err := cmd.Output()
+	out, err := cmd.Output()
 	if err != nil {
-		errorf("%s %s: %s\n", v.cmd, v.tagList, stderr)
-		return err
+		return &RunError{strings.Join(cmd.Args, " "), repoPath, out, err}
 	}
 	var tags []string
-	for _, m := range v.tagListRe.FindAllStringSubmatch(string(b), -1) {
+	for _, m := range v.tagListRe.FindAllStringSubmatch(string(out), -1) {
 		tags = append(tags, m[1])
 	}
 
@@ -263,12 +481,12 @@ func (v *vcs) updateRepo(dst string) os.Error {
 	// Select tag.
 	if tag := selectTag(ver, tags); tag != "" {
 		printf("selecting revision %q\n", tag)
-		return run(dst, nil, v.cmd, v.checkout, v.updateRevFlag+tag)
+		return run(repoPath, nil, v.cmd, v.checkout, v.updateRevFlag+tag)
 	}
 
 	// No matching tag found, make default selection.
 	printf("selecting tip\n")
-	return run(dst, nil, v.cmd, v.update)
+	return run(repoPath, nil, v.cmd, v.update)
 }
 
 // selectTag returns the closest matching tag for a given version.
@@ -279,7 +497,7 @@ func selectTag(goVersion string, tags []string) (match string) {
 	const rPrefix = "release.r"
 	if strings.HasPrefix(goVersion, rPrefix) {
 		p := "go.r"
-		v, err := strconv.Atof64(goVersion[len(rPrefix):])
+		v, err := strconv.ParseFloat(goVersion[len(rPrefix):], 64)
 		if err != nil {
 			return ""
 		}
@@ -288,7 +506,7 @@ func selectTag(goVersion string, tags []string) (match string) {
 			if !strings.HasPrefix(t, p) {
 				continue
 			}
-			tf, err := strconv.Atof64(t[len(p):])
+			tf, err := strconv.ParseFloat(t[len(p):], 64)
 			if err != nil {
 				continue
 			}
@@ -313,41 +531,7 @@ func selectTag(goVersion string, tags []string) (match string) {
 	return match
 }
 
-// checkoutRepo checks out repo into dst using vcs.
-// It tries to check out (or update, if the dst already
-// exists and -u was specified on the command line)
-// the repository at tag/branch "release".  If there is no
-// such tag or branch, it falls back to the repository tip.
-func (vcs *vcs) checkoutRepo(srcDir, pkgprefix, repo string) os.Error {
-	dst := filepath.Join(srcDir, filepath.FromSlash(pkgprefix))
-	dir, err := os.Stat(filepath.Join(dst, vcs.metadir))
-	if err == nil && !dir.IsDirectory() {
-		return os.NewError("not a directory: " + dst)
-	}
-	if err != nil {
-		parent, _ := filepath.Split(dst)
-		if err = os.MkdirAll(parent, 0777); err != nil {
-			return err
-		}
-		if err = run(string(filepath.Separator), nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
-			return err
-		}
-		return vcs.updateRepo(dst)
-	}
-	if *update {
-		// Retrieve new revisions from the remote branch, if the VCS
-		// supports this operation independently (e.g. svn doesn't)
-		if vcs.pull != "" {
-			if vcs.pullForceFlag != "" {
-				if err = run(dst, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil {
-					return err
-				}
-			} else if err = run(dst, nil, vcs.cmd, vcs.pull); err != nil {
-				return err
-			}
-		}
-		// Update to release or latest revision
-		return vcs.updateRepo(dst)
-	}
-	return nil
+func isDir(dir string) bool {
+	fi, err := os.Stat(dir)
+	return err == nil && fi.IsDir()
 }
diff --git a/src/cmd/goinstall/download_test.go b/src/cmd/goinstall/download_test.go
new file mode 100644
index 0000000..2aa6f61
--- /dev/null
+++ b/src/cmd/goinstall/download_test.go
@@ -0,0 +1,149 @@
+// Copyright 2011 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 (
+	"bytes"
+	"errors"
+	"io/ioutil"
+	"net/http"
+	"testing"
+)
+
+var FindPublicRepoTests = []struct {
+	pkg            string
+	vcs, root, url string
+	transport      *testTransport
+}{
+	{
+		"code.google.com/p/repo/path/foo",
+		"hg",
+		"code.google.com/p/repo",
+		"https://code.google.com/p/repo",
+		&testTransport{
+			"https://code.google.com/p/repo/source/checkout",
+			`<tt id="checkoutcmd">hg clone https://...`,
+		},
+	},
+	{
+		"code.google.com/p/repo/path/foo",
+		"svn",
+		"code.google.com/p/repo",
+		"http://repo.googlecode.com/svn",
+		&testTransport{
+			"https://code.google.com/p/repo/source/checkout",
+			`<tt id="checkoutcmd">svn checkout https://...`,
+		},
+	},
+	{
+		"code.google.com/p/repo/path/foo",
+		"git",
+		"code.google.com/p/repo",
+		"https://code.google.com/p/repo",
+		&testTransport{
+			"https://code.google.com/p/repo/source/checkout",
+			`<tt id="checkoutcmd">git clone https://...`,
+		},
+	},
+	{
+		"code.google.com/p/repo.sub/path",
+		"hg",
+		"code.google.com/p/repo.sub",
+		"https://code.google.com/p/repo.sub",
+		&testTransport{
+			"https://code.google.com/p/repo/source/checkout?repo=sub",
+			`<tt id="checkoutcmd">hg clone https://...`,
+		},
+	},
+	{
+		"bitbucket.org/user/repo/path/foo",
+		"hg",
+		"bitbucket.org/user/repo",
+		"http://bitbucket.org/user/repo",
+		&testTransport{
+			"https://api.bitbucket.org/1.0/repositories/user/repo",
+			`{"scm": "hg"}`,
+		},
+	},
+	{
+		"bitbucket.org/user/repo/path/foo",
+		"git",
+		"bitbucket.org/user/repo",
+		"http://bitbucket.org/user/repo.git",
+		&testTransport{
+			"https://api.bitbucket.org/1.0/repositories/user/repo",
+			`{"scm": "git"}`,
+		},
+	},
+	{
+		"github.com/user/repo/path/foo",
+		"git",
+		"github.com/user/repo",
+		"http://github.com/user/repo.git",
+		nil,
+	},
+	{
+		"launchpad.net/project/series/path",
+		"bzr",
+		"launchpad.net/project/series",
+		"https://launchpad.net/project/series",
+		nil,
+	},
+	{
+		"launchpad.net/~user/project/branch/path",
+		"bzr",
+		"launchpad.net/~user/project/branch",
+		"https://launchpad.net/~user/project/branch",
+		nil,
+	},
+}
+
+func TestFindPublicRepo(t *testing.T) {
+	for _, test := range FindPublicRepoTests {
+		client := http.DefaultClient
+		if test.transport != nil {
+			client = &http.Client{Transport: test.transport}
+		}
+		repo, err := findPublicRepo(test.pkg)
+		if err != nil {
+			t.Errorf("findPublicRepo(%s): error: %v", test.pkg, err)
+			continue
+		}
+		if repo == nil {
+			t.Errorf("%s: got nil match", test.pkg)
+			continue
+		}
+		url, root, vcs, err := repo.Repo(client)
+		if err != nil {
+			t.Errorf("%s: repo.Repo error: %v", test.pkg, err)
+			continue
+		}
+		if v := vcsMap[test.vcs]; vcs != v {
+			t.Errorf("%s: got vcs=%v, want %v", test.pkg, vcs, v)
+		}
+		if root != test.root {
+			t.Errorf("%s: got root=%v, want %v", test.pkg, root, test.root)
+		}
+		if url != test.url {
+			t.Errorf("%s: got url=%v, want %v", test.pkg, url, test.url)
+		}
+	}
+}
+
+type testTransport struct {
+	expectURL    string
+	responseBody string
+}
+
+func (t *testTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+	if g, e := req.URL.String(), t.expectURL; g != e {
+		return nil, errors.New("want " + e)
+	}
+	body := ioutil.NopCloser(bytes.NewBufferString(t.responseBody))
+	return &http.Response{
+		StatusCode: http.StatusOK,
+		Body:       body,
+	}, nil
+}
diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go
index 4782663..bbc4b6b 100644
--- a/src/cmd/goinstall/main.go
+++ b/src/cmd/goinstall/main.go
@@ -6,13 +6,14 @@ package main
 
 import (
 	"bytes"
-	"exec"
+	"errors"
 	"flag"
 	"fmt"
 	"go/build"
 	"go/token"
 	"io/ioutil"
 	"os"
+	"os/exec"
 	"path/filepath" // use for file system paths
 	"regexp"
 	"runtime"
@@ -31,7 +32,6 @@ const logfile = "goinstall.log"
 var (
 	fset          = token.NewFileSet()
 	argv0         = os.Args[0]
-	errors        = false
 	parents       = make(map[string]string)
 	visit         = make(map[string]status)
 	installedPkgs = make(map[string]map[string]bool)
@@ -40,10 +40,11 @@ var (
 	allpkg            = flag.Bool("a", false, "install all previously installed packages")
 	reportToDashboard = flag.Bool("dashboard", true, "report public packages at "+dashboardURL)
 	update            = flag.Bool("u", false, "update already-downloaded packages")
+	doGofix           = flag.Bool("fix", false, "gofix each package before building it")
 	doInstall         = flag.Bool("install", true, "build and install")
 	clean             = flag.Bool("clean", false, "clean the package directory before installing")
 	nuke              = flag.Bool("nuke", false, "clean the package directory and target before installing")
-	useMake           = flag.Bool("make", true, "use make to build and install")
+	useMake           = flag.Bool("make", true, "use make to build and install (obsolete, always true)")
 	verbose           = flag.Bool("v", false, "verbose")
 )
 
@@ -54,6 +55,51 @@ const (
 	done
 )
 
+type PackageError struct {
+	pkg string
+	err error
+}
+
+func (e *PackageError) Error() string {
+	return fmt.Sprintf("%s: %v", e.pkg, e.err)
+}
+
+type DownloadError struct {
+	pkg    string
+	goroot bool
+	err    error
+}
+
+func (e *DownloadError) Error() string {
+	s := fmt.Sprintf("%s: download failed: %v", e.pkg, e.err)
+	if e.goroot && os.Getenv("GOPATH") == "" {
+		s += " ($GOPATH is not set)"
+	}
+	return s
+}
+
+type DependencyError PackageError
+
+func (e *DependencyError) Error() string {
+	return fmt.Sprintf("%s: depends on failing packages:\n\t%v", e.pkg, e.err)
+}
+
+type BuildError PackageError
+
+func (e *BuildError) Error() string {
+	return fmt.Sprintf("%s: build failed: %v", e.pkg, e.err)
+}
+
+type RunError struct {
+	cmd, dir string
+	out      []byte
+	err      error
+}
+
+func (e *RunError) Error() string {
+	return fmt.Sprintf("%v\ncd %q && %q\n%s", e.err, e.dir, e.cmd, e.out)
+}
+
 func logf(format string, args ...interface{}) {
 	format = "%s: " + format
 	args = append([]interface{}{argv0}, args...)
@@ -66,18 +112,6 @@ func printf(format string, args ...interface{}) {
 	}
 }
 
-func errorf(format string, args ...interface{}) {
-	errors = true
-	logf(format, args...)
-}
-
-func terrorf(tree *build.Tree, format string, args ...interface{}) {
-	if tree != nil && tree.Goroot && os.Getenv("GOPATH") == "" {
-		format = strings.TrimRight(format, "\n") + " ($GOPATH not set)\n"
-	}
-	errorf(format, args...)
-}
-
 func main() {
 	flag.Usage = usage
 	flag.Parse()
@@ -111,15 +145,14 @@ func main() {
 	if len(args) == 0 {
 		usage()
 	}
+	errs := false
 	for _, path := range args {
-		if s := schemeRe.FindString(path); s != "" {
-			errorf("%q used in import path, try %q\n", s, path[len(s):])
-			continue
+		if err := install(path, ""); err != nil {
+			errs = true
+			fmt.Fprintln(os.Stderr, err)
 		}
-
-		install(path, "")
 	}
-	if errors {
+	if errs {
 		os.Exit(1)
 	}
 }
@@ -136,7 +169,7 @@ func printDeps(pkg string) {
 }
 
 // readPackageList reads the list of installed packages from the
-// goinstall.log files in GOROOT and the GOPATHs and initalizes
+// goinstall.log files in GOROOT and the GOPATHs and initializes
 // the installedPkgs variable.
 func readPackageList() {
 	for _, t := range build.Path {
@@ -163,7 +196,7 @@ func logPackage(pkg string, tree *build.Tree) (logged bool) {
 	name := filepath.Join(tree.Path, logfile)
 	fout, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
 	if err != nil {
-		terrorf(tree, "package log: %s\n", err)
+		printf("package log: %s\n", err)
 		return false
 	}
 	fmt.Fprintf(fout, "%s\n", pkg)
@@ -172,11 +205,19 @@ func logPackage(pkg string, tree *build.Tree) (logged bool) {
 }
 
 // install installs the package named by path, which is needed by parent.
-func install(pkg, parent string) {
+func install(pkg, parent string) error {
+	// Basic validation of import path string.
+	if s := schemeRe.FindString(pkg); s != "" {
+		return fmt.Errorf("%q used in import path, try %q\n", s, pkg[len(s):])
+	}
+	if strings.HasSuffix(pkg, "/") {
+		return fmt.Errorf("%q should not have trailing '/'\n", pkg)
+	}
+
 	// Make sure we're not already trying to install pkg.
 	switch visit[pkg] {
 	case done:
-		return
+		return nil
 	case visiting:
 		fmt.Fprintf(os.Stderr, "%s: package dependency cycle\n", argv0)
 		printDeps(parent)
@@ -189,24 +230,17 @@ func install(pkg, parent string) {
 		visit[pkg] = done
 	}()
 
-	// Don't allow trailing '/'
-	if strings.HasSuffix(pkg, "/") {
-		errorf("%s should not have trailing '/'\n", pkg)
-		return
-	}
-
 	// Check whether package is local or remote.
 	// If remote, download or update it.
 	tree, pkg, err := build.FindTree(pkg)
 	// Don't build the standard library.
 	if err == nil && tree.Goroot && isStandardPath(pkg) {
 		if parent == "" {
-			errorf("%s: can not goinstall the standard library\n", pkg)
-		} else {
-			printf("%s: skipping standard library\n", pkg)
+			return &PackageError{pkg, errors.New("cannot goinstall the standard library")}
 		}
-		return
+		return nil
 	}
+
 	// Download remote packages if not found or forced with -u flag.
 	remote, public := isRemote(pkg), false
 	if remote {
@@ -214,85 +248,118 @@ func install(pkg, parent string) {
 			// Download remote package.
 			printf("%s: download\n", pkg)
 			public, err = download(pkg, tree.SrcDir())
+			if err != nil {
+				// only suggest -fix if the bad import was not on the command line
+				if e, ok := err.(*errOldGoogleRepo); ok && parent != "" {
+					err = fmt.Errorf("%v\nRun goinstall with -fix to gofix the code.", e)
+				}
+				return &DownloadError{pkg, tree.Goroot, err}
+			}
 		} else {
 			// Test if this is a public repository
 			// (for reporting to dashboard).
-			m, _ := findPublicRepo(pkg)
-			public = m != nil
+			repo, e := findPublicRepo(pkg)
+			public = repo != nil
+			err = e
 		}
 	}
 	if err != nil {
-		terrorf(tree, "%s: %v\n", pkg, err)
-		return
+		return &PackageError{pkg, err}
 	}
-	dir := filepath.Join(tree.SrcDir(), filepath.FromSlash(pkg))
 
-	// Install prerequisites.
+	// Install the package and its dependencies.
+	if err := installPackage(pkg, parent, tree, false); err != nil {
+		return err
+	}
+
+	if remote {
+		// mark package as installed in goinstall.log
+		logged := logPackage(pkg, tree)
+
+		// report installation to the dashboard if this is the first
+		// install from a public repository.
+		if logged && public {
+			maybeReportToDashboard(pkg)
+		}
+	}
+
+	return nil
+}
+
+// installPackage installs the specified package and its dependencies.
+func installPackage(pkg, parent string, tree *build.Tree, retry bool) (installErr error) {
+	printf("%s: install\n", pkg)
+
+	// Read package information.
+	dir := filepath.Join(tree.SrcDir(), filepath.FromSlash(pkg))
 	dirInfo, err := build.ScanDir(dir)
 	if err != nil {
-		terrorf(tree, "%s: %v\n", pkg, err)
-		return
+		return &PackageError{pkg, err}
 	}
+
 	// We reserve package main to identify commands.
 	if parent != "" && dirInfo.Package == "main" {
-		terrorf(tree, "%s: found only package main in %s; cannot import", pkg, dir)
-		return
-	}
-	for _, p := range dirInfo.Imports {
-		if p != "C" {
-			install(p, pkg)
-		}
-	}
-	if errors {
-		return
+		return &PackageError{pkg, fmt.Errorf("found only package main in %s; cannot import", dir)}
 	}
 
-	// Install this package.
-	if *useMake {
-		err := domake(dir, pkg, tree, dirInfo.IsCommand())
-		if err != nil {
-			terrorf(tree, "%s: install: %v\n", pkg, err)
+	// Run gofix if we fail to build and -fix is set.
+	defer func() {
+		if retry || installErr == nil || !*doGofix {
 			return
 		}
-	} else {
-		script, err := build.Build(tree, pkg, dirInfo)
-		if err != nil {
-			terrorf(tree, "%s: install: %v\n", pkg, err)
-			return
+		if e, ok := (installErr).(*DependencyError); ok {
+			// If this package failed to build due to a
+			// DependencyError, only attempt to gofix it if its
+			// dependency failed for some reason other than a
+			// DependencyError or BuildError.
+			// (If a dep or one of its deps doesn't build there's
+			// no way that gofixing this package can help.)
+			switch e.err.(type) {
+			case *DependencyError:
+				return
+			case *BuildError:
+				return
+			}
 		}
-		if *nuke {
-			printf("%s: nuke\n", pkg)
-			script.Nuke()
-		} else if *clean {
-			printf("%s: clean\n", pkg)
-			script.Clean()
+		gofix(pkg, dir, dirInfo)
+		installErr = installPackage(pkg, parent, tree, true) // retry
+	}()
+
+	// Install prerequisites.
+	for _, p := range dirInfo.Imports {
+		if p == "C" {
+			continue
 		}
-		if *doInstall {
-			if script.Stale() {
-				printf("%s: install\n", pkg)
-				if err := script.Run(); err != nil {
-					terrorf(tree, "%s: install: %v\n", pkg, err)
-					return
-				}
-			} else {
-				printf("%s: up-to-date\n", pkg)
-			}
+		if err := install(p, pkg); err != nil {
+			return &DependencyError{pkg, err}
 		}
 	}
 
-	if remote {
-		// mark package as installed in goinstall.log
-		logged := logPackage(pkg, tree)
+	// Install this package.
+	err = domake(dir, pkg, tree, dirInfo.IsCommand())
+	if err != nil {
+		return &BuildError{pkg, err}
+	}
+	return nil
+}
 
-		// report installation to the dashboard if this is the first
-		// install from a public repository.
-		if logged && public {
-			maybeReportToDashboard(pkg)
-		}
+// gofix runs gofix against the GoFiles and CgoFiles of dirInfo in dir.
+func gofix(pkg, dir string, dirInfo *build.DirInfo) {
+	printf("%s: gofix\n", pkg)
+	files := append([]string{}, dirInfo.GoFiles...)
+	files = append(files, dirInfo.CgoFiles...)
+	for i, file := range files {
+		files[i] = filepath.Join(dir, file)
+	}
+	cmd := exec.Command("gofix", files...)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		logf("%s: gofix: %v", pkg, err)
 	}
 }
 
-// Is this a standard package path?  strings container/vector etc.
+// Is this a standard package path?  strings container/list etc.
 // Assume that if the first element has a dot, it's a domain name
 // and is not the standard package path.
 func isStandardPath(s string) bool {
@@ -302,34 +369,32 @@ func isStandardPath(s string) bool {
 }
 
 // run runs the command cmd in directory dir with standard input stdin.
-// If the command fails, run prints the command and output on standard error
-// in addition to returning a non-nil os.Error.
-func run(dir string, stdin []byte, cmd ...string) os.Error {
-	return genRun(dir, stdin, cmd, false)
-}
-
-// quietRun is like run but prints nothing on failure unless -v is used.
-func quietRun(dir string, stdin []byte, cmd ...string) os.Error {
-	return genRun(dir, stdin, cmd, true)
-}
-
-// genRun implements run and quietRun.
-func genRun(dir string, stdin []byte, arg []string, quiet bool) os.Error {
+// If verbose is set and the command fails it prints the output to stderr.
+func run(dir string, stdin []byte, arg ...string) error {
 	cmd := exec.Command(arg[0], arg[1:]...)
 	cmd.Stdin = bytes.NewBuffer(stdin)
 	cmd.Dir = dir
-	printf("%s: %s %s\n", dir, cmd.Path, strings.Join(arg[1:], " "))
-	out, err := cmd.CombinedOutput()
-	if err != nil {
-		if !quiet || *verbose {
-			if dir != "" {
-				dir = "cd " + dir + "; "
-			}
-			fmt.Fprintf(os.Stderr, "%s: === %s%s\n", cmd.Path, dir, strings.Join(cmd.Args, " "))
-			os.Stderr.Write(out)
-			fmt.Fprintf(os.Stderr, "--- %s\n", err)
+	printf("cd %s && %s %s\n", dir, cmd.Path, strings.Join(arg[1:], " "))
+	if out, err := cmd.CombinedOutput(); err != nil {
+		if *verbose {
+			fmt.Fprintf(os.Stderr, "%v\n%s\n", err, out)
 		}
-		return os.NewError("running " + arg[0] + ": " + err.String())
+		return &RunError{strings.Join(arg, " "), dir, out, err}
 	}
 	return nil
 }
+
+// isRemote returns true if the first part of the package name looks like a
+// hostname - i.e. contains at least one '.' and the last part is at least 2
+// characters.
+func isRemote(pkg string) bool {
+	parts := strings.SplitN(pkg, "/", 2)
+	if len(parts) != 2 {
+		return false
+	}
+	parts = strings.Split(parts[0], ".")
+	if len(parts) < 2 || len(parts[len(parts)-1]) < 2 {
+		return false
+	}
+	return true
+}
diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go
index 7f41a91..1e40d6e 100644
--- a/src/cmd/goinstall/make.go
+++ b/src/cmd/goinstall/make.go
@@ -8,17 +8,17 @@ package main
 
 import (
 	"bytes"
+	"errors"
 	"go/build"
-	"os"
 	"path" // use for import paths
 	"strings"
-	"template"
+	"text/template"
 )
 
 // domake builds the package in dir.
 // domake generates a standard Makefile and passes it
 // to make on standard input.
-func domake(dir, pkg string, tree *build.Tree, isCmd bool) (err os.Error) {
+func domake(dir, pkg string, tree *build.Tree, isCmd bool) (err error) {
 	makefile, err := makeMakefile(dir, pkg, tree, isCmd)
 	if err != nil {
 		return err
@@ -29,16 +29,21 @@ func domake(dir, pkg string, tree *build.Tree, isCmd bool) (err os.Error) {
 	} else if *clean {
 		cmd = append(cmd, "clean")
 	}
-	cmd = append(cmd, "install")
+	if *doInstall {
+		cmd = append(cmd, "install")
+	}
+	if len(cmd) <= 3 { // nothing to do
+		return nil
+	}
 	return run(dir, makefile, cmd...)
 }
 
 // makeMakefile computes the standard Makefile for the directory dir
 // installing as package pkg.  It includes all *.go files in the directory
 // except those in package main and those ending in _test.go.
-func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Error) {
+func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, error) {
 	if !safeName(pkg) {
-		return nil, os.NewError("unsafe name: " + pkg)
+		return nil, errors.New("unsafe name: " + pkg)
 	}
 	targ := pkg
 	targDir := tree.PkgDir()
@@ -56,7 +61,7 @@ func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err
 	isCgo := make(map[string]bool, len(cgoFiles))
 	for _, file := range cgoFiles {
 		if !safeName(file) {
-			return nil, os.NewError("bad name: " + file)
+			return nil, errors.New("bad name: " + file)
 		}
 		isCgo[file] = true
 	}
@@ -64,7 +69,7 @@ func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err
 	goFiles := make([]string, 0, len(dirInfo.GoFiles))
 	for _, file := range dirInfo.GoFiles {
 		if !safeName(file) {
-			return nil, os.NewError("unsafe name: " + file)
+			return nil, errors.New("unsafe name: " + file)
 		}
 		if !isCgo[file] {
 			goFiles = append(goFiles, file)
@@ -75,7 +80,7 @@ func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err
 	cgoOFiles := make([]string, 0, len(dirInfo.CFiles))
 	for _, file := range dirInfo.CFiles {
 		if !safeName(file) {
-			return nil, os.NewError("unsafe name: " + file)
+			return nil, errors.New("unsafe name: " + file)
 		}
 		// When cgo is in use, C files are compiled with gcc,
 		// otherwise they're compiled with gc.
@@ -88,7 +93,7 @@ func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err
 
 	for _, file := range dirInfo.SFiles {
 		if !safeName(file) {
-			return nil, os.NewError("unsafe name: " + file)
+			return nil, errors.New("unsafe name: " + file)
 		}
 		oFiles = append(oFiles, file[:len(file)-2]+".$O")
 	}
@@ -109,7 +114,7 @@ func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err
 	return buf.Bytes(), nil
 }
 
-var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+var safeBytes = []byte("+-~./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
 
 func safeName(s string) bool {
 	if s == "" {
@@ -118,6 +123,9 @@ func safeName(s string) bool {
 	if strings.Contains(s, "..") {
 		return false
 	}
+	if s[0] == '~' {
+		return false
+	}
 	for i := 0; i < len(s); i++ {
 		if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
 			return false
diff --git a/src/cmd/gopack/ar.c b/src/cmd/gopack/ar.c
index 96f3660..40c99f6 100644
--- a/src/cmd/gopack/ar.c
+++ b/src/cmd/gopack/ar.c
@@ -37,7 +37,6 @@
 #define rcmd your_rcmd
 
 #include <u.h>
-#include <time.h>
 #include <libc.h>
 #include <bio.h>
 #include <mach.h>
@@ -612,12 +611,49 @@ qcmd(char *arname, int count, char **files)
 }
 
 /*
+ *	does the object header line p match the last one we saw?
+ *	update *lastp if it gets more specific.
+ */
+int
+matchhdr(char *p, char **lastp)
+{
+	int n;
+	char *last;
+	
+	// no information?
+	last = *lastp;
+	if(last == nil) {
+		*lastp = strdup(p);
+		return 1;
+	}
+
+	// identical match?
+	if(strcmp(last, p) == 0)
+		return 1;
+
+	// last has extra fields
+	n = strlen(p);
+	if(n < strlen(last) && last[n] == ' ')
+		return 1;
+
+	// p has extra fields - save in last
+	n = strlen(last);
+	if(n < strlen(p) && p[n] == ' ') {
+		free(last);
+		*lastp = strdup(p);
+		return 1;
+	}
+	
+	return 0;
+}	
+
+/*
  *	extract the symbol references from an object file
  */
 void
 scanobj(Biobuf *b, Arfile *ap, long size)
 {
-	int obj;
+	int obj, goobject;
 	vlong offset, offset1;
 	Dir *d;
 	static int lastobj = -1;
@@ -658,9 +694,19 @@ scanobj(Biobuf *b, Arfile *ap, long size)
 		return;
 	}
 
+	goobject = 1;
 	offset1 = Boffset(b);
 	Bseek(b, offset, 0);
 	p = Brdstr(b, '\n', 1);
+	
+	// After the go object header comes the Go metadata,
+	// followed by ! on a line by itself.  If this is not a Go object,
+	// the ! comes immediately.  Catch that so we can avoid
+	// the call to scanpkg below, since scanpkg assumes that the
+	// Go metadata is present.
+	if(Bgetc(b) == '!')
+		goobject = 0;
+
 	Bseek(b, offset1, 0);
 	if(p == nil || strncmp(p, "go object ", 10) != 0) {
 		fprint(2, "gopack: malformed object file %s\n", file);
@@ -670,18 +716,23 @@ scanobj(Biobuf *b, Arfile *ap, long size)
 		return;
 	}
 	
-	if ((lastobj >= 0 && obj != lastobj) || (objhdr != nil && strcmp(p, objhdr) != 0)) {
-		fprint(2, "gopack: inconsistent object file %s\n", file);
+	if (!matchhdr(p, &objhdr)) {
+		fprint(2, "gopack: inconsistent object file %s: [%s] vs [%s]\n", file, p, objhdr);
 		errors++;
 		allobj = 0;
 		free(p);
 		return;
 	}
+	free(p);
+
+	// Old check.  Should be impossible since objhdrs match, but keep the check anyway.
+	if (lastobj >= 0 && obj != lastobj) {
+		fprint(2, "gopack: inconsistent object file %s\n", file);
+		errors++;
+		allobj = 0;
+		return;
+	}
 	lastobj = obj;
-	if(objhdr == nil)
-		objhdr = p;
-	else
-		free(p);
 		
 	if (!readar(b, obj, offset+size, 0)) {
 		fprint(2, "gopack: invalid symbol reference in file %s\n", file);
@@ -692,7 +743,7 @@ scanobj(Biobuf *b, Arfile *ap, long size)
 	}
 	Bseek(b, offset, 0);
 	objtraverse(objsym, ap);
-	if (gflag) {
+	if (gflag && goobject) {
 		scanpkg(b, size);
 		Bseek(b, offset, 0);
 	}
@@ -786,7 +837,6 @@ foundstart:
 			goto bad;
 
 	/* how big is it? */
-	pkg = nil;
 	first = 1;
 	start = end = 0;
 	for (n=0; n<size; n+=Blinelen(b)) {
@@ -1050,7 +1100,7 @@ armove(Biobuf *b, Arfile *ap, Armember *bp)
 	for (cp = strchr(bp->hdr.name, 0);		/* blank pad on right */
 		cp < bp->hdr.name+sizeof(bp->hdr.name); cp++)
 			*cp = ' ';
-	sprint(bp->hdr.date, "%-12ld", 0);  // was d->mtime but removed for idempotent builds
+	sprint(bp->hdr.date, "%-12ld", 0L);  // was d->mtime but removed for idempotent builds
 	sprint(bp->hdr.uid, "%-6d", 0);
 	sprint(bp->hdr.gid, "%-6d", 0);
 	sprint(bp->hdr.mode, "%-8lo", d->mode);
@@ -1184,7 +1234,7 @@ rl(int fd)
 	len = symdefsize;
 	if(len&01)
 		len++;
-	sprint(a.date, "%-12ld", 0);  // time(0)
+	sprint(a.date, "%-12ld", 0L);  // time(0)
 	sprint(a.uid, "%-6d", 0);
 	sprint(a.gid, "%-6d", 0);
 	sprint(a.mode, "%-8lo", 0644L);
@@ -1221,7 +1271,7 @@ rl(int fd)
 
 	if (gflag) {
 		len = pkgdefsize;
-		sprint(a.date, "%-12ld", 0);  // time(0)
+		sprint(a.date, "%-12ld", 0L);  // time(0)
 		sprint(a.uid, "%-6d", 0);
 		sprint(a.gid, "%-6d", 0);
 		sprint(a.mode, "%-8lo", 0644L);
@@ -1368,15 +1418,12 @@ void
 longt(Armember *bp)
 {
 	char *cp;
-	time_t date;
 
 	pmode(strtoul(bp->hdr.mode, 0, 8));
 	Bprint(&bout, "%3ld/%1ld", strtol(bp->hdr.uid, 0, 0), strtol(bp->hdr.gid, 0, 0));
 	Bprint(&bout, "%7ld", bp->size);
-	date = bp->date;
-	cp = ctime(&date);
-	/* using unix ctime, not plan 9 time, so cp+20 for year, not cp+24 */
-	Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+20);
+	cp = ctime(bp->date);
+	Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24);
 }
 
 int	m1[] = { 1, ROWN, 'r', '-' };
diff --git a/src/cmd/gotest/doc.go b/src/cmd/gotest/doc.go
index 5be06f8..8d729f0 100644
--- a/src/cmd/gotest/doc.go
+++ b/src/cmd/gotest/doc.go
@@ -26,6 +26,26 @@ signature,
 
 	func BenchmarkXXX(b *testing.B) { ... }
 
+Example functions may also be written. They are similar to test functions but,
+instead of using *testing.T to report success or failure, their output to
+os.Stdout and os.Stderr is compared against their doc comment.
+
+	// The output of this example function.
+	func ExampleXXX() {
+		fmt.Println("The output of this example function.")
+	}
+
+The following naming conventions are used to declare examples for a function F, 
+a type T and method M on type T:
+	 func ExampleF() { ... }     and    func ExampleF_suffix() { ... } 
+	 func ExampleT() { ... }     and    func ExampleT_suffix() { ... }
+	 func ExampleT_M() { ... }   and    func ExampleT_M_suffix() { ... }
+
+Multiple example functions may be provided by appending a distinct suffix
+to the name.  The suffix must start with a lowercase letter.
+
+Example functions without doc comments are compiled but not executed.
+
 See the documentation of the testing package for more information.
 
 By default, gotest needs no arguments.  It compiles all the .go files
@@ -54,7 +74,8 @@ Usage:
 	6.out [-test.v] [-test.run pattern] [-test.bench pattern] \
 		[-test.cpuprofile=cpu.out] \
 		[-test.memprofile=mem.out] [-test.memprofilerate=1] \
-		[-test.timeout=10] [-test.short] \
+		[-test.parallel=$GOMAXPROCS] \
+		[-test.timeout=10s] [-test.short] \
 		[-test.benchtime=3] [-test.cpu=1,2,3,4]
 
 The -test.v flag causes the tests to be logged as they run.  The
@@ -86,12 +107,17 @@ collection.
 Use -test.run or -test.bench to limit profiling to a particular test
 or benchmark.
 
+The -test.parallel flag allows parallel execution of Test functions
+that call test.Parallel.  The value of the flag is the maximum
+number of tests to run simultaneously; by default, it is set to the
+value of GOMAXPROCS.
+
 The -test.short flag tells long-running tests to shorten their run
 time.  It is off by default but set by all.bash so installations of
 the Go tree can do a sanity check but not spend time running
 exhaustive tests.
 
-The -test.timeout flag sets a timeout for the test in seconds.  If the
+The -test.timeout flag sets a timeout for the test.  If the
 test runs for longer than that, it will panic, dumping a stack trace
 of all existing goroutines.
 
diff --git a/src/cmd/gotest/flag.go b/src/cmd/gotest/flag.go
index c3a28f9..b0b0cae 100644
--- a/src/cmd/gotest/flag.go
+++ b/src/cmd/gotest/flag.go
@@ -28,6 +28,7 @@ var usageMessage = `Usage of %s:
   -cpuprofile="": passes -test.cpuprofile to test
   -memprofile="": passes -test.memprofile to test
   -memprofilerate=0: passes -test.memprofilerate to test
+  -parallel=0: passes -test.parallel to test
   -run="": passes -test.run to test
   -short=false: passes -test.short to test
   -timeout=0: passes -test.timeout to test
@@ -52,21 +53,22 @@ type flagSpec struct {
 // flagDefn is the set of flags we process.
 var flagDefn = []*flagSpec{
 	// gotest-local.
-	&flagSpec{name: "c", isBool: true},
-	&flagSpec{name: "file", multiOK: true},
-	&flagSpec{name: "x", isBool: true},
+	{name: "c", isBool: true},
+	{name: "file", multiOK: true},
+	{name: "x", isBool: true},
 
 	// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
-	&flagSpec{name: "bench", passToTest: true},
-	&flagSpec{name: "benchtime", passToTest: true},
-	&flagSpec{name: "cpu", passToTest: true},
-	&flagSpec{name: "cpuprofile", passToTest: true},
-	&flagSpec{name: "memprofile", passToTest: true},
-	&flagSpec{name: "memprofilerate", passToTest: true},
-	&flagSpec{name: "run", passToTest: true},
-	&flagSpec{name: "short", isBool: true, passToTest: true},
-	&flagSpec{name: "timeout", passToTest: true},
-	&flagSpec{name: "v", isBool: true, passToTest: true},
+	{name: "bench", passToTest: true},
+	{name: "benchtime", passToTest: true},
+	{name: "cpu", passToTest: true},
+	{name: "cpuprofile", passToTest: true},
+	{name: "memprofile", passToTest: true},
+	{name: "memprofilerate", passToTest: true},
+	{name: "parallel", passToTest: true},
+	{name: "run", passToTest: true},
+	{name: "short", isBool: true, passToTest: true},
+	{name: "timeout", passToTest: true},
+	{name: "v", isBool: true, passToTest: true},
 }
 
 // flags processes the command line, grabbing -x and -c, rewriting known flags
@@ -105,6 +107,10 @@ func flag(i int) (f *flagSpec, value string, extra bool) {
 	if strings.HasPrefix(arg, "--") { // reduce two minuses to one
 		arg = arg[1:]
 	}
+	switch arg {
+	case "-?", "-h", "-help":
+		usage()
+	}
 	if arg == "" || arg[0] != '-' {
 		return
 	}
@@ -150,7 +156,7 @@ func flag(i int) (f *flagSpec, value string, extra bool) {
 
 // setBoolFlag sets the addressed boolean to the value.
 func setBoolFlag(flag *bool, value string) {
-	x, err := strconv.Atob(value)
+	x, err := strconv.ParseBool(value)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "gotest: illegal bool flag value %s\n", value)
 		usage()
diff --git a/src/cmd/gotest/gotest.go b/src/cmd/gotest/gotest.go
index 88c746c..6697aeb 100644
--- a/src/cmd/gotest/gotest.go
+++ b/src/cmd/gotest/gotest.go
@@ -6,7 +6,6 @@ package main
 
 import (
 	"bufio"
-	"exec"
 	"fmt"
 	"go/ast"
 	"go/build"
@@ -14,12 +13,13 @@ import (
 	"go/token"
 	"io/ioutil"
 	"os"
+	"os/exec"
 	"runtime"
 	"sort"
 	"strings"
 	"time"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 // Environment for commands.
@@ -55,10 +55,10 @@ var (
 
 // elapsed returns the number of seconds since gotest started.
 func elapsed() float64 {
-	return float64(time.Nanoseconds()-start) / 1e9
+	return time.Now().Sub(start).Seconds()
 }
 
-var start = time.Nanoseconds()
+var start = time.Now()
 
 // File represents a file that contains tests.
 type File struct {
@@ -68,6 +68,12 @@ type File struct {
 	astFile    *ast.File
 	tests      []string // The names of the TestXXXs.
 	benchmarks []string // The names of the BenchmarkXXXs.
+	examples   []example
+}
+
+type example struct {
+	name   string // The name of the example function (ExampleXXX).
+	output string // The expected output (stdout/stderr) of the function.
 }
 
 func main() {
@@ -107,13 +113,6 @@ func Fatalf(s string, args ...interface{}) {
 	os.Exit(2)
 }
 
-// theChar is the map from architecture to object character.
-var theChar = map[string]string{
-	"arm":   "5",
-	"amd64": "6",
-	"386":   "8",
-}
-
 // addEnv adds a name=value pair to the environment passed to subcommands.
 // If the item is already in the environment, addEnv replaces the value.
 func addEnv(name, value string) {
@@ -131,14 +130,12 @@ func setEnvironment() {
 	// Basic environment.
 	GOROOT = runtime.GOROOT()
 	addEnv("GOROOT", GOROOT)
-	GOARCH = os.Getenv("GOARCH")
-	if GOARCH == "" {
-		GOARCH = runtime.GOARCH
-	}
+	GOARCH = build.DefaultContext.GOARCH
 	addEnv("GOARCH", GOARCH)
-	O = theChar[GOARCH]
-	if O == "" {
-		Fatalf("unknown architecture %s", GOARCH)
+	var err error
+	O, err = build.ArchChar(GOARCH)
+	if err != nil {
+		Fatalf("unknown architecture: %s", err)
 	}
 
 	// Commands and their flags.
@@ -146,8 +143,12 @@ func setEnvironment() {
 	if gc == "" {
 		gc = O + "g"
 	}
-	XGC = []string{gc, "-I", "_test", "-o", "_xtest_." + O}
-	GC = []string{gc, "-I", "_test", "_testmain.go"}
+	var gcflags []string
+	if gf := strings.TrimSpace(os.Getenv("GCFLAGS")); gf != "" {
+		gcflags = strings.Fields(gf)
+	}
+	XGC = append([]string{gc, "-I", "_test", "-o", "_xtest_." + O}, gcflags...)
+	GC = append(append([]string{gc, "-I", "_test"}, gcflags...), "_testmain.go")
 	gl := os.Getenv("GL")
 	if gl == "" {
 		gl = O + "l"
@@ -190,7 +191,7 @@ func parseFiles() {
 	fileSet := token.NewFileSet()
 	for _, f := range files {
 		// Report declaration errors so we can abort if the files are incorrect Go.
-		file, err := parser.ParseFile(fileSet, f.name, nil, parser.DeclarationErrors)
+		file, err := parser.ParseFile(fileSet, f.name, nil, parser.DeclarationErrors|parser.ParseComments)
 		if err != nil {
 			Fatalf("parse error: %s", err)
 		}
@@ -219,10 +220,20 @@ func getTestNames() {
 				f.tests = append(f.tests, name)
 			} else if isTest(name, "Benchmark") {
 				f.benchmarks = append(f.benchmarks, name)
+			} else if isTest(name, "Example") {
+				output := n.Doc.Text()
+				if output == "" {
+					// Don't run examples with no output.
+					continue
+				}
+				f.examples = append(f.examples, example{
+					name:   name,
+					output: output,
+				})
 			}
 			// TODO: worth checking the signature? Probably not.
 		}
-		if strings.HasSuffix(f.pkg, "_test") {
+		if isOutsideTest(f.pkg) {
 			outsideFileNames = append(outsideFileNames, f.name)
 		} else {
 			insideFileNames = append(insideFileNames, f.name)
@@ -272,10 +283,10 @@ func runTestWithArgs(binary string) {
 func doRun(argv []string, returnStdout bool) string {
 	if xFlag {
 		fmt.Printf("gotest %.2fs: %s\n", elapsed(), strings.Join(argv, " "))
-		t := -time.Nanoseconds()
+		start := time.Now()
 		defer func() {
-			t += time.Nanoseconds()
-			fmt.Printf(" [+%.2fs]\n", float64(t)/1e9)
+			t := time.Now().Sub(start)
+			fmt.Printf(" [+%.2fs]\n", t.Seconds())
 		}()
 	}
 	command := argv[0]
@@ -291,7 +302,7 @@ func doRun(argv []string, returnStdout bool) string {
 		command = "bash"
 		argv = []string{"bash", "-c", cmd}
 	}
-	var err os.Error
+	var err error
 	argv[0], err = exec.LookPath(argv[0])
 	if err != nil {
 		Fatalf("can't find %s: %s", command, err)
@@ -356,51 +367,62 @@ func writeTestmainGo() {
 	insideTests := false
 	for _, f := range files {
 		//println(f.name, f.pkg)
-		if len(f.tests) == 0 && len(f.benchmarks) == 0 {
+		if len(f.tests) == 0 && len(f.benchmarks) == 0 && len(f.examples) == 0 {
 			continue
 		}
-		if strings.HasSuffix(f.pkg, "_test") {
+		if isOutsideTest(f.pkg) {
 			outsideTests = true
 		} else {
 			insideTests = true
 		}
 	}
+	// Rename the imports for the system under test,
+	// in case the tested package has the same name
+	// as any of the other imports, variables or methods.
 	if insideTests {
 		switch importPath {
 		case "testing":
 		case "main":
 			// Import path main is reserved, so import with
 			// explicit reference to ./_test/main instead.
-			// Also, the file we are writing defines a function named main,
-			// so rename this import to __main__ to avoid name conflict.
-			fmt.Fprintf(b, "import __main__ %q\n", "./_test/main")
+			fmt.Fprintf(b, "import target %q\n", "./_test/main")
 		default:
-			fmt.Fprintf(b, "import %q\n", importPath)
+			fmt.Fprintf(b, "import target %q\n", importPath)
 		}
 	}
 	if outsideTests {
-		fmt.Fprintf(b, "import %q\n", "./_xtest_")
+		// It is possible to have both inside and outside tests
+		// at the same time, so a different import name is needed.
+		fmt.Fprintf(b, "import target_test %q\n", "./_xtest_")
 	}
 	fmt.Fprintf(b, "import %q\n", "testing")
-	fmt.Fprintf(b, "import __os__ %q\n", "os")         // rename in case tested package is called os
-	fmt.Fprintf(b, "import __regexp__ %q\n", "regexp") // rename in case tested package is called regexp
-	fmt.Fprintln(b)                                    // for gofmt
+	fmt.Fprintf(b, "import %q\n", "regexp")
+	fmt.Fprintln(b) // for gofmt
 
 	// Tests.
-	fmt.Fprintln(b, "var tests = []testing.InternalTest{")
+	fmt.Fprintf(b, "var tests = []testing.InternalTest{\n")
 	for _, f := range files {
 		for _, t := range f.tests {
-			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, t, notMain(f.pkg), t)
+			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, t, renamedPackage(f.pkg), t)
 		}
 	}
 	fmt.Fprintln(b, "}")
 	fmt.Fprintln(b)
 
 	// Benchmarks.
-	fmt.Fprintf(b, "var benchmarks = []testing.InternalBenchmark{")
+	fmt.Fprintf(b, "var benchmarks = []testing.InternalBenchmark{\n")
 	for _, f := range files {
 		for _, bm := range f.benchmarks {
-			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, bm, notMain(f.pkg), bm)
+			fmt.Fprintf(b, "\t{\"%s.%s\", %s.%s},\n", f.pkg, bm, renamedPackage(f.pkg), bm)
+		}
+	}
+	fmt.Fprintln(b, "}")
+
+	// Examples.
+	fmt.Fprintf(b, "var examples = []testing.InternalExample{")
+	for _, f := range files {
+		for _, eg := range f.examples {
+			fmt.Fprintf(b, "\t{%q, %s.%s, %q},\n", eg.name, renamedPackage(f.pkg), eg.name, eg.output)
 		}
 	}
 	fmt.Fprintln(b, "}")
@@ -409,23 +431,27 @@ func writeTestmainGo() {
 	fmt.Fprintln(b, testBody)
 }
 
-// notMain returns the package, renaming as appropriate if it's "main".
-func notMain(pkg string) string {
-	if pkg == "main" {
-		return "__main__"
+// renamedPackage returns the name under which the test package was imported.
+func renamedPackage(pkg string) string {
+	if isOutsideTest(pkg) {
+		return "target_test"
 	}
-	return pkg
+	return "target"
+}
+
+func isOutsideTest(pkg string) bool {
+	return strings.HasSuffix(pkg, "_test")
 }
 
 // testBody is just copied to the output. It's the code that runs the tests.
 var testBody = `
 var matchPat string
-var matchRe *__regexp__.Regexp
+var matchRe *regexp.Regexp
 
-func matchString(pat, str string) (result bool, err __os__.Error) {
+func matchString(pat, str string) (result bool, err error) {
 	if matchRe == nil || matchPat != pat {
 		matchPat = pat
-		matchRe, err = __regexp__.Compile(matchPat)
+		matchRe, err = regexp.Compile(matchPat)
 		if err != nil {
 			return
 		}
@@ -434,5 +460,5 @@ func matchString(pat, str string) (result bool, err __os__.Error) {
 }
 
 func main() {
-	testing.Main(matchString, tests, benchmarks)
+	testing.Main(matchString, tests, benchmarks, examples)
 }`
diff --git a/src/cmd/gotry/Makefile b/src/cmd/gotry/Makefile
deleted file mode 100644
index 6a32bbf..0000000
--- a/src/cmd/gotry/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=install
-
-clean:
-	@true
-
-install: install-gotry
-
-install-%: %
-	! test -f "$(GOBIN)"/$* || chmod u+w "$(GOBIN)"/$*
-	sed 's`@@GOROOT@@`$(GOROOT_FINAL)`' $* >"$(GOBIN)"/$*
-	chmod +x "$(GOBIN)"/$*
-
diff --git a/src/cmd/gotry/gotry b/src/cmd/gotry/gotry
deleted file mode 100755
index c81b6c7..0000000
--- a/src/cmd/gotry/gotry
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2010 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.
-
-# Using all the non-test *.go files in the named directory, write
-# out a file /tmp/$USER.try.go to evaluate the expressions on the
-# command line, perhaps to discover a function or method that
-# gives the desired results.  See usage message.
-# Compile the program and run it.
-
-# Makes egrep,grep work better in general if we put them
-# in ordinary C mode instead of what the current language is.
-unset LANG
-export LC_ALL=C
-export LC_CTYPE=C
-
-export GOROOT=${GOROOT:-"@@GOROOT@@"}
-eval $(gomake -j1 --no-print-directory -f "$GOROOT"/src/Make.inc go-env)
-if [ -z "$O" ]; then
-	echo 'missing $O - maybe no Make.$GOARCH?' 1>&2
-	exit 2
-fi
-
-# Allow overrides
-GC="${_GC:-$GC} -I _test"
-GL="${GL:-$LD} -L _test"
-AS="$AS"
-CC="$CC"
-LD="$LD"
-export GC GL O AS CC LD
-
-# Macros for tab and quotes for easier readability.
-T='	'
-BQ='`'
-SQ="'"
-DQ='"'
-SD="$SQ$DQ"
-DS="$DQ$SQ"
-
-usage="usage: gotry [packagedirectory] expression ...
-Given one expression, gotry attempts to evaluate that expression.
-Given multiple expressions, gotry treats them as a list of arguments
-and result values and attempts to find a function in the package
-that, given the first few expressions as arguments, evaluates to
-the remaining expressions as results.  If the first expression has
-methods, it will also search for applicable methods.
-
-If there are multiple expressions, a package directory must be
-specified. If there is a package argument, the expressions are
-evaluated in an environment that includes
-	import . ${DQ}packagedirectory${DQ}
-
-Examples:
-	gotry 3+4
-		# evaluates to 7
-	gotry strings ${SD}abc${DS} ${SD}c${DS} 7-5
-		# finds strings.Index etc.
-	gotry regexp ${SQ}MustCompile(${DQ}^[0-9]+${DQ})${SQ} ${SD}12345${DS} true
-		# finds Regexp.MatchString
-
-"
-
-function fail() {
-	echo 2>&1 "$@"
-	exit 2
-}
-
-case $# in
-	0)
-		fail "$usage"
-		;;
-	*)
-		case "$1" in
-		-*help|-*'?'|'?')
-			fail "$usage"
-		esac
-		if test -d "$GOROOT/src/pkg/$1"
-		then
-			pkg=$(basename $1)
-			dir=$GOROOT/src/pkg/$1
-			importdir=$1
-			shift
-			case "$pkg" in
-			os|syscall)
-				fail "gotry: cannot try packages os or syscall; they are too dangerous"
-			esac
-		fi
-		;;
-esac
-
-spaces='[ 	][ 	]*'
-
-function getFunctions() {
-	if [ "$pkg" = "" ]
-	then
-		return
-	fi
-	for file in $dir/*.go
-	do
-		case $file in
-		*_test*)
-			continue
-		esac
-		grep "func$spaces[A-Z]" $file | # TODO: should be Unicode upper case
-			sed "s/func$spaces//;s/(.*//"
-	done | sort -u
-}
-
-# Generate list of public functions.
-functions=$(getFunctions)
-
-# Write file to compile
-file="/tmp/$USER.try"
-rm -f "$file.go"
-(
-cat <<'!'
-package main
-
-import (
-	"os"
-	"try"
-!
-
-if [ "$pkg" != "" ]
-then
-	echo "$T" . '"'$importdir'"'
-fi
-
-cat <<!
-)
-func main() {
-	try.Main("$pkg", firstArg, functions, args)
-}
-var functions = map[string] interface{}{
-!
-
-for i in $functions
-do
-	echo "$T"'"'$i'": '$i','
-done
-echo "}"
-
-echo 'var args = []interface{}{'
-
-if [ $# = 1 ]
-then
-	echo "${T}toSlice($1)",
-else
-for i
-	do
-		echo "$T$i",
-	done
-fi
-echo "}"
-
-cat <<!
-var firstArg = $BQ$1$BQ
-var _ os.Error
-func toSlice(a ...interface{}) []interface{} { return a }
-!
-
-)>"$file.go"
-
-$GC -o "$file.$O" "$file.go" &&
-$GL -o "$file" "$file.$O" &&
-"$file" "_$@"
-rm -f "$file" "$file.go" "$file.$O"
diff --git a/src/cmd/gotype/Makefile b/src/cmd/gotype/Makefile
deleted file mode 100644
index 1817194..0000000
--- a/src/cmd/gotype/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=gotype
-GOFILES=\
-	gotype.go\
-
-include ../../Make.cmd
-
-test:
-	gotest
-
-testshort:
-	gotest -test.short
diff --git a/src/cmd/gotype/gotype.go b/src/cmd/gotype/gotype.go
deleted file mode 100644
index e5e9417..0000000
--- a/src/cmd/gotype/gotype.go
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2011 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 (
-	"flag"
-	"fmt"
-	"go/ast"
-	"go/parser"
-	"go/scanner"
-	"go/token"
-	"go/types"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"strings"
-)
-
-var (
-	// main operation modes
-	pkgName   = flag.String("p", "", "process only those files in package pkgName")
-	recursive = flag.Bool("r", false, "recursively process subdirectories")
-	verbose   = flag.Bool("v", false, "verbose mode")
-	allErrors = flag.Bool("e", false, "print all (including spurious) errors")
-
-	// debugging support
-	printTrace = flag.Bool("trace", false, "print parse trace")
-	printAST   = flag.Bool("ast", false, "print AST")
-)
-
-var exitCode = 0
-
-func usage() {
-	fmt.Fprintf(os.Stderr, "usage: gotype [flags] [path ...]\n")
-	flag.PrintDefaults()
-	os.Exit(2)
-}
-
-func report(err os.Error) {
-	scanner.PrintError(os.Stderr, err)
-	exitCode = 2
-}
-
-// parse returns the AST for the Go source src.
-// The filename is for error reporting only.
-// The result is nil if there were errors or if
-// the file does not belong to the -p package.
-func parse(fset *token.FileSet, filename string, src []byte) *ast.File {
-	if *verbose {
-		fmt.Println(filename)
-	}
-
-	// ignore files with different package name
-	if *pkgName != "" {
-		file, err := parser.ParseFile(fset, filename, src, parser.PackageClauseOnly)
-		if err != nil {
-			report(err)
-			return nil
-		}
-		if file.Name.Name != *pkgName {
-			if *verbose {
-				fmt.Printf("\tignored (package %s)\n", file.Name.Name)
-			}
-			return nil
-		}
-	}
-
-	// parse entire file
-	mode := parser.DeclarationErrors
-	if *allErrors {
-		mode |= parser.SpuriousErrors
-	}
-	if *printTrace {
-		mode |= parser.Trace
-	}
-	file, err := parser.ParseFile(fset, filename, src, mode)
-	if err != nil {
-		report(err)
-		return nil
-	}
-	if *printAST {
-		ast.Print(fset, file)
-	}
-
-	return file
-}
-
-func parseStdin(fset *token.FileSet) (files map[string]*ast.File) {
-	files = make(map[string]*ast.File)
-	src, err := ioutil.ReadAll(os.Stdin)
-	if err != nil {
-		report(err)
-		return
-	}
-	const filename = "<standard input>"
-	if file := parse(fset, filename, src); file != nil {
-		files[filename] = file
-	}
-	return
-}
-
-func parseFiles(fset *token.FileSet, filenames []string) (files map[string]*ast.File) {
-	files = make(map[string]*ast.File)
-	for _, filename := range filenames {
-		src, err := ioutil.ReadFile(filename)
-		if err != nil {
-			report(err)
-			continue
-		}
-		if file := parse(fset, filename, src); file != nil {
-			if files[filename] != nil {
-				report(os.NewError(fmt.Sprintf("%q: duplicate file", filename)))
-				continue
-			}
-			files[filename] = file
-		}
-	}
-	return
-}
-
-func isGoFilename(filename string) bool {
-	// ignore non-Go files
-	return !strings.HasPrefix(filename, ".") && strings.HasSuffix(filename, ".go")
-}
-
-func processDirectory(dirname string) {
-	f, err := os.Open(dirname)
-	if err != nil {
-		report(err)
-		return
-	}
-	filenames, err := f.Readdirnames(-1)
-	f.Close()
-	if err != nil {
-		report(err)
-		// continue since filenames may not be empty
-	}
-	for i, filename := range filenames {
-		filenames[i] = filepath.Join(dirname, filename)
-	}
-	processFiles(filenames, false)
-}
-
-func processFiles(filenames []string, allFiles bool) {
-	i := 0
-	for _, filename := range filenames {
-		switch info, err := os.Stat(filename); {
-		case err != nil:
-			report(err)
-		case info.IsRegular():
-			if allFiles || isGoFilename(info.Name) {
-				filenames[i] = filename
-				i++
-			}
-		case info.IsDirectory():
-			if allFiles || *recursive {
-				processDirectory(filename)
-			}
-		}
-	}
-	fset := token.NewFileSet()
-	processPackage(fset, parseFiles(fset, filenames[0:i]))
-}
-
-func processPackage(fset *token.FileSet, files map[string]*ast.File) {
-	// make a package (resolve all identifiers)
-	pkg, err := ast.NewPackage(fset, files, types.GcImporter, types.Universe)
-	if err != nil {
-		report(err)
-		return
-	}
-	_, err = types.Check(fset, pkg)
-	if err != nil {
-		report(err)
-	}
-}
-
-func main() {
-	flag.Usage = usage
-	flag.Parse()
-
-	if flag.NArg() == 0 {
-		fset := token.NewFileSet()
-		processPackage(fset, parseStdin(fset))
-	} else {
-		processFiles(flag.Args(), true)
-	}
-
-	os.Exit(exitCode)
-}
diff --git a/src/cmd/gotype/gotype_test.go b/src/cmd/gotype/gotype_test.go
deleted file mode 100644
index ad0bc89..0000000
--- a/src/cmd/gotype/gotype_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2011 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 (
-	"path/filepath"
-	"runtime"
-	"testing"
-)
-
-func runTest(t *testing.T, path, pkg string) {
-	exitCode = 0
-	*pkgName = pkg
-	*recursive = false
-
-	if pkg == "" {
-		processFiles([]string{path}, true)
-	} else {
-		processDirectory(path)
-	}
-
-	if exitCode != 0 {
-		t.Errorf("processing %s failed: exitCode = %d", path, exitCode)
-	}
-}
-
-var tests = []struct {
-	path string
-	pkg  string
-}{
-	// individual files
-	{"testdata/test1.go", ""},
-
-	// directories
-	{filepath.Join(runtime.GOROOT(), "src/pkg/go/ast"), "ast"},
-	{filepath.Join(runtime.GOROOT(), "src/pkg/go/doc"), "doc"},
-	{filepath.Join(runtime.GOROOT(), "src/pkg/go/token"), "scanner"},
-	{filepath.Join(runtime.GOROOT(), "src/pkg/go/scanner"), "scanner"},
-	{filepath.Join(runtime.GOROOT(), "src/pkg/go/parser"), "parser"},
-	{filepath.Join(runtime.GOROOT(), "src/pkg/go/types"), "types"},
-}
-
-func Test(t *testing.T) {
-	for _, test := range tests {
-		runTest(t, test.path, test.pkg)
-	}
-}
diff --git a/src/cmd/gotype/testdata/test1.go b/src/cmd/gotype/testdata/test1.go
deleted file mode 100644
index a3298e6..0000000
--- a/src/cmd/gotype/testdata/test1.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package p
-
-func _() {
-	// the scope of a local type declaration starts immediately after the type name
-	type T struct{ _ *T }
-}
-
-func _(x interface{}) {
-	// the variable defined by a TypeSwitchGuard is declared in each TypeCaseClause
-	switch t := x.(type) {
-	case int:
-		_ = t
-	case float32:
-		_ = t
-	default:
-		_ = t
-	}
-
-	// the variable defined by a TypeSwitchGuard must not conflict with other
-	// variables declared in the initial simple statement
-	switch t := 0; t := x.(type) {
-	}
-}
diff --git a/src/cmd/govet/Makefile b/src/cmd/govet/Makefile
index f565b78..dae3ae5 100644
--- a/src/cmd/govet/Makefile
+++ b/src/cmd/govet/Makefile
@@ -7,8 +7,11 @@ include ../../Make.inc
 TARG=govet
 GOFILES=\
 	govet.go\
+	method.go\
+	print.go\
+	structtag.go\
 
 include ../../Make.cmd
 
 test testshort: $(TARG)
-	../../../test/errchk $(TARG) -printfuncs='Warn:1,Warnf:1' govet.go
+	../../../test/errchk $(TARG) -printfuncs='Warn:1,Warnf:1' print.go
diff --git a/src/cmd/govet/govet.go b/src/cmd/govet/govet.go
index 9aa97e3..283f161 100644
--- a/src/cmd/govet/govet.go
+++ b/src/cmd/govet/govet.go
@@ -7,22 +7,20 @@
 package main
 
 import (
+	"bytes"
 	"flag"
 	"fmt"
-	"io"
 	"go/ast"
 	"go/parser"
 	"go/token"
+	"io"
 	"os"
 	"path/filepath"
-	"reflect"
 	"strconv"
 	"strings"
-	"utf8"
 )
 
 var verbose = flag.Bool("v", false, "verbose")
-var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")
 var exitCode = 0
 
 // setExit sets the value for os.Exit when it is called, later.  It
@@ -43,7 +41,9 @@ func Usage() {
 // File is a wrapper for the state of a file used in the parser.
 // The parse tree walkers are all methods of this type.
 type File struct {
-	file *token.File
+	fset *token.FileSet
+	file *ast.File
+	b    bytes.Buffer // for use by methods
 }
 
 func main() {
@@ -57,7 +57,7 @@ func main() {
 			}
 			skip := 0
 			if colon := strings.LastIndex(name, ":"); colon > 0 {
-				var err os.Error
+				var err error
 				skip, err = strconv.Atoi(name[colon+1:])
 				if err != nil {
 					errorf(`illegal format for "Func:N" argument %q; %s`, name, err)
@@ -78,7 +78,7 @@ func main() {
 	} else {
 		for _, name := range flag.Args() {
 			// Is it a directory?
-			if fi, err := os.Stat(name); err == nil && fi.IsDirectory() {
+			if fi, err := os.Stat(name); err == nil && fi.IsDir() {
 				walkDir(name)
 			} else {
 				doFile(name, nil)
@@ -97,16 +97,16 @@ func doFile(name string, reader io.Reader) {
 		errorf("%s: %s", name, err)
 		return
 	}
-	file := &File{fs.File(parsedFile.Pos())}
-	file.checkFile(name, parsedFile)
+	file := &File{fset: fs, file: parsedFile}
+	file.walkFile(name, parsedFile)
 }
 
-func visit(path string, f *os.FileInfo, err os.Error) os.Error {
+func visit(path string, f os.FileInfo, err error) error {
 	if err != nil {
 		errorf("walk error: %s", err)
 		return nil
 	}
-	if f.IsRegular() && strings.HasSuffix(path, ".go") {
+	if !f.IsDir() && strings.HasSuffix(path, ".go") {
 		doFile(path, nil)
 	}
 	return nil
@@ -154,18 +154,18 @@ func (f *File) Badf(pos token.Pos, format string, args ...interface{}) {
 
 // Warn reports an error but does not set the exit code.
 func (f *File) Warn(pos token.Pos, args ...interface{}) {
-	loc := f.file.Position(pos).String() + ": "
+	loc := f.fset.Position(pos).String() + ": "
 	fmt.Fprint(os.Stderr, loc+fmt.Sprintln(args...))
 }
 
 // Warnf reports a formatted error but does not set the exit code.
 func (f *File) Warnf(pos token.Pos, format string, args ...interface{}) {
-	loc := f.file.Position(pos).String() + ": "
+	loc := f.fset.Position(pos).String() + ": "
 	fmt.Fprintf(os.Stderr, loc+format+"\n", args...)
 }
 
-// checkFile checks all the top-level declarations in a file.
-func (f *File) checkFile(name string, file *ast.File) {
+// walkFile walks the file's tree.
+func (f *File) walkFile(name string, file *ast.File) {
 	Println("Checking file", name)
 	ast.Walk(f, file)
 }
@@ -174,217 +174,59 @@ func (f *File) checkFile(name string, file *ast.File) {
 func (f *File) Visit(node ast.Node) ast.Visitor {
 	switch n := node.(type) {
 	case *ast.CallExpr:
-		f.checkCallExpr(n)
+		f.walkCallExpr(n)
 	case *ast.Field:
-		f.checkFieldTag(n)
+		f.walkFieldTag(n)
+	case *ast.FuncDecl:
+		f.walkMethodDecl(n)
+	case *ast.InterfaceType:
+		f.walkInterfaceType(n)
 	}
 	return f
 }
 
-// checkField checks a struct field tag.
-func (f *File) checkFieldTag(field *ast.Field) {
-	if field.Tag == nil {
-		return
-	}
-
-	tag, err := strconv.Unquote(field.Tag.Value)
-	if err != nil {
-		f.Warnf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
-		return
-	}
-
-	// Check tag for validity by appending
-	// new key:value to end and checking that
-	// the tag parsing code can find it.
-	if reflect.StructTag(tag+` _gofix:"_magic"`).Get("_gofix") != "_magic" {
-		f.Warnf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get", field.Tag.Value)
-		return
-	}
+// walkCall walks a call expression.
+func (f *File) walkCall(call *ast.CallExpr, name string) {
+	f.checkFmtPrintfCall(call, name)
 }
 
-// checkCallExpr checks a call expression.
-func (f *File) checkCallExpr(call *ast.CallExpr) {
-	switch x := call.Fun.(type) {
-	case *ast.Ident:
-		f.checkCall(call, x.Name)
-	case *ast.SelectorExpr:
-		f.checkCall(call, x.Sel.Name)
+// walkFieldTag walks a struct field tag.
+func (f *File) walkFieldTag(field *ast.Field) {
+	if field.Tag == nil {
+		return
 	}
+	f.checkCanonicalFieldTag(field)
 }
 
-// printfList records the formatted-print functions. The value is the location
-// of the format parameter. Names are lower-cased so the lookup is
-// case insensitive.
-var printfList = map[string]int{
-	"errorf":  0,
-	"fatalf":  0,
-	"fprintf": 1,
-	"panicf":  0,
-	"printf":  0,
-	"sprintf": 0,
+// walkMethodDecl walks the method's signature.
+func (f *File) walkMethod(id *ast.Ident, t *ast.FuncType) {
+	f.checkCanonicalMethod(id, t)
 }
 
-// printList records the unformatted-print functions. The value is the location
-// of the first parameter to be printed.  Names are lower-cased so the lookup is
-// case insensitive.
-var printList = map[string]int{
-	"error":  0,
-	"fatal":  0,
-	"fprint": 1, "fprintln": 1,
-	"panic": 0, "panicln": 0,
-	"print": 0, "println": 0,
-	"sprint": 0, "sprintln": 0,
-}
-
-// checkCall triggers the print-specific checks if the call invokes a print function.
-func (f *File) checkCall(call *ast.CallExpr, Name string) {
-	name := strings.ToLower(Name)
-	if skip, ok := printfList[name]; ok {
-		f.checkPrintf(call, Name, skip)
-		return
-	}
-	if skip, ok := printList[name]; ok {
-		f.checkPrint(call, Name, skip)
+// walkMethodDecl walks the method signature in the declaration.
+func (f *File) walkMethodDecl(d *ast.FuncDecl) {
+	if d.Recv == nil {
+		// not a method
 		return
 	}
+	f.walkMethod(d.Name, d.Type)
 }
 
-// checkPrintf checks a call to a formatted print routine such as Printf.
-// The skip argument records how many arguments to ignore; that is,
-// call.Args[skip] is (well, should be) the format argument.
-func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) {
-	if len(call.Args) <= skip {
-		return
-	}
-	// Common case: literal is first argument.
-	arg := call.Args[skip]
-	lit, ok := arg.(*ast.BasicLit)
-	if !ok {
-		// Too hard to check.
-		if *verbose {
-			f.Warn(call.Pos(), "can't check args for call to", name)
+// walkInterfaceType walks the method signatures of an interface.
+func (f *File) walkInterfaceType(t *ast.InterfaceType) {
+	for _, field := range t.Methods.List {
+		for _, id := range field.Names {
+			f.walkMethod(id, field.Type.(*ast.FuncType))
 		}
-		return
 	}
-	if lit.Kind == token.STRING {
-		if !strings.Contains(lit.Value, "%") {
-			if len(call.Args) > skip+1 {
-				f.Badf(call.Pos(), "no formatting directive in %s call", name)
-			}
-			return
-		}
-	}
-	// Hard part: check formats against args.
-	// Trivial but useful test: count.
-	numArgs := 0
-	for i, w := 0, 0; i < len(lit.Value); i += w {
-		w = 1
-		if lit.Value[i] == '%' {
-			nbytes, nargs := parsePrintfVerb(lit.Value[i:])
-			w = nbytes
-			numArgs += nargs
-		}
-	}
-	expect := len(call.Args) - (skip + 1)
-	if numArgs != expect {
-		f.Badf(call.Pos(), "wrong number of args in %s call: %d needed but %d args", name, numArgs, expect)
-	}
-}
-
-// parsePrintfVerb returns the number of bytes and number of arguments
-// consumed by the Printf directive that begins s, including its percent sign
-// and verb.
-func parsePrintfVerb(s string) (nbytes, nargs int) {
-	// There's guaranteed a percent sign.
-	nbytes = 1
-	end := len(s)
-	// There may be flags.
-FlagLoop:
-	for nbytes < end {
-		switch s[nbytes] {
-		case '#', '0', '+', '-', ' ':
-			nbytes++
-		default:
-			break FlagLoop
-		}
-	}
-	getNum := func() {
-		if nbytes < end && s[nbytes] == '*' {
-			nbytes++
-			nargs++
-		} else {
-			for nbytes < end && '0' <= s[nbytes] && s[nbytes] <= '9' {
-				nbytes++
-			}
-		}
-	}
-	// There may be a width.
-	getNum()
-	// If there's a period, there may be a precision.
-	if nbytes < end && s[nbytes] == '.' {
-		nbytes++
-		getNum()
-	}
-	// Now a verb.
-	c, w := utf8.DecodeRuneInString(s[nbytes:])
-	nbytes += w
-	if c != '%' {
-		nargs++
-	}
-	return
 }
 
-// checkPrint checks a call to an unformatted print routine such as Println.
-// The skip argument records how many arguments to ignore; that is,
-// call.Args[skip] is the first argument to be printed.
-func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
-	isLn := strings.HasSuffix(name, "ln")
-	args := call.Args
-	if len(args) <= skip {
-		if *verbose && !isLn {
-			f.Badf(call.Pos(), "no args in %s call", name)
-		}
-		return
-	}
-	arg := args[skip]
-	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
-		if strings.Contains(lit.Value, "%") {
-			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
-		}
-	}
-	if isLn {
-		// The last item, if a string, should not have a newline.
-		arg = args[len(call.Args)-1]
-		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
-			if strings.HasSuffix(lit.Value, `\n"`) {
-				f.Badf(call.Pos(), "%s call ends with newline", name)
-			}
-		}
+// walkCallExpr walks a call expression.
+func (f *File) walkCallExpr(call *ast.CallExpr) {
+	switch x := call.Fun.(type) {
+	case *ast.Ident:
+		f.walkCall(call, x.Name)
+	case *ast.SelectorExpr:
+		f.walkCall(call, x.Sel.Name)
 	}
 }
-
-// This function never executes, but it serves as a simple test for the program.
-// Test with make test.
-func BadFunctionUsedInTests() {
-	fmt.Println()                      // not an error
-	fmt.Println("%s", "hi")            // ERROR "possible formatting directive in Println call"
-	fmt.Printf("%s", "hi", 3)          // ERROR "wrong number of args in Printf call"
-	fmt.Printf("%s%%%d", "hi", 3)      // correct
-	fmt.Printf("%.*d", 3, 3)           // correct
-	fmt.Printf("%.*d", 3, 3, 3)        // ERROR "wrong number of args in Printf call"
-	printf("now is the time", "buddy") // ERROR "no formatting directive"
-	Printf("now is the time", "buddy") // ERROR "no formatting directive"
-	Printf("hi")                       // ok
-	f := new(File)
-	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
-	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
-}
-
-type BadTypeUsedInTests struct {
-	X int "hello" // ERROR "struct field tag"
-}
-
-// printf is used by the test.
-func printf(format string, args ...interface{}) {
-	panic("don't call - testing only")
-}
diff --git a/src/cmd/govet/method.go b/src/cmd/govet/method.go
new file mode 100644
index 0000000..55bf11d
--- /dev/null
+++ b/src/cmd/govet/method.go
@@ -0,0 +1,161 @@
+// Copyright 2010 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 file contains the code to check canonical methods.
+
+package main
+
+import (
+	"fmt"
+	"go/ast"
+	"go/printer"
+	"strings"
+)
+
+type MethodSig struct {
+	args    []string
+	results []string
+}
+
+// canonicalMethods lists the input and output types for Go methods
+// that are checked using dynamic interface checks.  Because the
+// checks are dynamic, such methods would not cause a compile error
+// if they have the wrong signature: instead the dynamic check would
+// fail, sometimes mysteriously.  If a method is found with a name listed
+// here but not the input/output types listed here, govet complains.
+//
+// A few of the canonical methods have very common names.
+// For example, a type might implement a Scan method that
+// has nothing to do with fmt.Scanner, but we still want to check
+// the methods that are intended to implement fmt.Scanner.
+// To do that, the arguments that have a + prefix are treated as
+// signals that the canonical meaning is intended: if a Scan
+// method doesn't have a fmt.ScanState as its first argument,
+// we let it go.  But if it does have a fmt.ScanState, then the
+// rest has to match.
+var canonicalMethods = map[string]MethodSig{
+	// "Flush": {{}, {"error"}}, // http.Flusher and jpeg.writer conflict
+	"Format":        {[]string{"=fmt.State", "rune"}, []string{}},            // fmt.Formatter
+	"GobDecode":     {[]string{"[]byte"}, []string{"error"}},                 // gob.GobDecoder
+	"GobEncode":     {[]string{}, []string{"[]byte", "error"}},               // gob.GobEncoder
+	"MarshalJSON":   {[]string{}, []string{"[]byte", "error"}},               // json.Marshaler
+	"MarshalXML":    {[]string{}, []string{"[]byte", "error"}},               // xml.Marshaler
+	"Peek":          {[]string{"=int"}, []string{"[]byte", "error"}},         // image.reader (matching bufio.Reader)
+	"ReadByte":      {[]string{}, []string{"byte", "error"}},                 // io.ByteReader
+	"ReadFrom":      {[]string{"=io.Reader"}, []string{"int64", "error"}},    // io.ReaderFrom
+	"ReadRune":      {[]string{}, []string{"rune", "int", "error"}},          // io.RuneReader
+	"Scan":          {[]string{"=fmt.ScanState", "rune"}, []string{"error"}}, // fmt.Scanner
+	"Seek":          {[]string{"=int64", "int"}, []string{"int64", "error"}}, // io.Seeker
+	"UnmarshalJSON": {[]string{"[]byte"}, []string{"error"}},                 // json.Unmarshaler
+	"UnreadByte":    {[]string{}, []string{"error"}},
+	"UnreadRune":    {[]string{}, []string{"error"}},
+	"WriteByte":     {[]string{"byte"}, []string{"error"}},                // jpeg.writer (matching bufio.Writer)
+	"WriteTo":       {[]string{"=io.Writer"}, []string{"int64", "error"}}, // io.WriterTo
+}
+
+func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
+	// Expected input/output.
+	expect, ok := canonicalMethods[id.Name]
+	if !ok {
+		return
+	}
+
+	// Actual input/output
+	args := typeFlatten(t.Params.List)
+	var results []ast.Expr
+	if t.Results != nil {
+		results = typeFlatten(t.Results.List)
+	}
+
+	// Do the =s (if any) all match?
+	if !f.matchParams(expect.args, args, "=") || !f.matchParams(expect.results, results, "=") {
+		return
+	}
+
+	// Everything must match.
+	if !f.matchParams(expect.args, args, "") || !f.matchParams(expect.results, results, "") {
+		expectFmt := id.Name + "(" + argjoin(expect.args) + ")"
+		if len(expect.results) == 1 {
+			expectFmt += " " + argjoin(expect.results)
+		} else if len(expect.results) > 1 {
+			expectFmt += " (" + argjoin(expect.results) + ")"
+		}
+
+		f.b.Reset()
+		if err := printer.Fprint(&f.b, f.fset, t); err != nil {
+			fmt.Fprintf(&f.b, "<%s>", err)
+		}
+		actual := f.b.String()
+		if strings.HasPrefix(actual, "func(") {
+			actual = actual[4:]
+		}
+		actual = id.Name + actual
+
+		f.Warnf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
+	}
+}
+
+func argjoin(x []string) string {
+	y := make([]string, len(x))
+	for i, s := range x {
+		if s[0] == '=' {
+			s = s[1:]
+		}
+		y[i] = s
+	}
+	return strings.Join(y, ", ")
+}
+
+// Turn parameter list into slice of types
+// (in the ast, types are Exprs).
+// Have to handle f(int, bool) and f(x, y, z int)
+// so not a simple 1-to-1 conversion.
+func typeFlatten(l []*ast.Field) []ast.Expr {
+	var t []ast.Expr
+	for _, f := range l {
+		if len(f.Names) == 0 {
+			t = append(t, f.Type)
+			continue
+		}
+		for _ = range f.Names {
+			t = append(t, f.Type)
+		}
+	}
+	return t
+}
+
+// Does each type in expect with the given prefix match the corresponding type in actual?
+func (f *File) matchParams(expect []string, actual []ast.Expr, prefix string) bool {
+	for i, x := range expect {
+		if !strings.HasPrefix(x, prefix) {
+			continue
+		}
+		if i >= len(actual) {
+			return false
+		}
+		if !f.matchParamType(x, actual[i]) {
+			return false
+		}
+	}
+	if prefix == "" && len(actual) > len(expect) {
+		return false
+	}
+	return true
+}
+
+// Does this one type match?
+func (f *File) matchParamType(expect string, actual ast.Expr) bool {
+	if strings.HasPrefix(expect, "=") {
+		expect = expect[1:]
+	}
+	// Strip package name if we're in that package.
+	if n := len(f.file.Name.Name); len(expect) > n && expect[:n] == f.file.Name.Name && expect[n] == '.' {
+		expect = expect[n+1:]
+	}
+
+	// Overkill but easy.
+	f.b.Reset()
+	printer.Fprint(&f.b, f.fset, actual)
+	return f.b.String() == expect
+}
diff --git a/src/cmd/govet/print.go b/src/cmd/govet/print.go
new file mode 100644
index 0000000..861a337
--- /dev/null
+++ b/src/cmd/govet/print.go
@@ -0,0 +1,267 @@
+// Copyright 2010 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 file contains the printf-checker.
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"strings"
+	"unicode/utf8"
+)
+
+var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")
+
+// printfList records the formatted-print functions. The value is the location
+// of the format parameter. Names are lower-cased so the lookup is
+// case insensitive.
+var printfList = map[string]int{
+	"errorf":  0,
+	"fatalf":  0,
+	"fprintf": 1,
+	"panicf":  0,
+	"printf":  0,
+	"sprintf": 0,
+}
+
+// printList records the unformatted-print functions. The value is the location
+// of the first parameter to be printed.  Names are lower-cased so the lookup is
+// case insensitive.
+var printList = map[string]int{
+	"error":  0,
+	"fatal":  0,
+	"fprint": 1, "fprintln": 1,
+	"panic": 0, "panicln": 0,
+	"print": 0, "println": 0,
+	"sprint": 0, "sprintln": 0,
+}
+
+// checkCall triggers the print-specific checks if the call invokes a print function.
+func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
+	name := strings.ToLower(Name)
+	if skip, ok := printfList[name]; ok {
+		f.checkPrintf(call, Name, skip)
+		return
+	}
+	if skip, ok := printList[name]; ok {
+		f.checkPrint(call, Name, skip)
+		return
+	}
+}
+
+// checkPrintf checks a call to a formatted print routine such as Printf.
+// The skip argument records how many arguments to ignore; that is,
+// call.Args[skip] is (well, should be) the format argument.
+func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) {
+	if len(call.Args) <= skip {
+		return
+	}
+	// Common case: literal is first argument.
+	arg := call.Args[skip]
+	lit, ok := arg.(*ast.BasicLit)
+	if !ok {
+		// Too hard to check.
+		if *verbose {
+			f.Warn(call.Pos(), "can't check non-literal format in call to", name)
+		}
+		return
+	}
+	if lit.Kind == token.STRING {
+		if !strings.Contains(lit.Value, "%") {
+			if len(call.Args) > skip+1 {
+				f.Badf(call.Pos(), "no formatting directive in %s call", name)
+			}
+			return
+		}
+	}
+	// Hard part: check formats against args.
+	// Trivial but useful test: count.
+	numArgs := 0
+	for i, w := 0, 0; i < len(lit.Value); i += w {
+		w = 1
+		if lit.Value[i] == '%' {
+			nbytes, nargs := f.parsePrintfVerb(call, lit.Value[i:])
+			w = nbytes
+			numArgs += nargs
+		}
+	}
+	expect := len(call.Args) - (skip + 1)
+	if numArgs != expect {
+		f.Badf(call.Pos(), "wrong number of args in %s call: %d needed but %d args", name, numArgs, expect)
+	}
+}
+
+// parsePrintfVerb returns the number of bytes and number of arguments
+// consumed by the Printf directive that begins s, including its percent sign
+// and verb.
+func (f *File) parsePrintfVerb(call *ast.CallExpr, s string) (nbytes, nargs int) {
+	// There's guaranteed a percent sign.
+	flags := make([]byte, 0, 5)
+	nbytes = 1
+	end := len(s)
+	// There may be flags.
+FlagLoop:
+	for nbytes < end {
+		switch s[nbytes] {
+		case '#', '0', '+', '-', ' ':
+			flags = append(flags, s[nbytes])
+			nbytes++
+		default:
+			break FlagLoop
+		}
+	}
+	getNum := func() {
+		if nbytes < end && s[nbytes] == '*' {
+			nbytes++
+			nargs++
+		} else {
+			for nbytes < end && '0' <= s[nbytes] && s[nbytes] <= '9' {
+				nbytes++
+			}
+		}
+	}
+	// There may be a width.
+	getNum()
+	// If there's a period, there may be a precision.
+	if nbytes < end && s[nbytes] == '.' {
+		flags = append(flags, '.') // Treat precision as a flag.
+		nbytes++
+		getNum()
+	}
+	// Now a verb.
+	c, w := utf8.DecodeRuneInString(s[nbytes:])
+	nbytes += w
+	if c != '%' {
+		nargs++
+		f.checkPrintfVerb(call, c, flags)
+	}
+	return
+}
+
+type printVerb struct {
+	verb  rune
+	flags string // known flags are all ASCII
+}
+
+// Common flag sets for printf verbs.
+const (
+	numFlag      = " -+.0"
+	sharpNumFlag = " -+.0#"
+	allFlags     = " -+.0#"
+)
+
+// printVerbs identifies which flags are known to printf for each verb.
+// TODO: A type that implements Formatter may do what it wants, and govet
+// will complain incorrectly.
+var printVerbs = []printVerb{
+	// '-' is a width modifier, always valid.
+	// '.' is a precision for float, max width for strings.
+	// '+' is required sign for numbers, Go format for %v.
+	// '#' is alternate format for several verbs.
+	// ' ' is spacer for numbers
+	{'b', numFlag},
+	{'c', "-"},
+	{'d', numFlag},
+	{'e', "-."},
+	{'E', numFlag},
+	{'f', numFlag},
+	{'F', numFlag},
+	{'g', numFlag},
+	{'G', numFlag},
+	{'o', sharpNumFlag},
+	{'p', "-#"},
+	{'q', "-+#."},
+	{'s', "-."},
+	{'t', "-"},
+	{'T', "-"},
+	{'U', "-#"},
+	{'v', allFlags},
+	{'x', sharpNumFlag},
+	{'X', sharpNumFlag},
+}
+
+const printfVerbs = "bcdeEfFgGopqstTvxUX"
+
+func (f *File) checkPrintfVerb(call *ast.CallExpr, verb rune, flags []byte) {
+	// Linear scan is fast enough for a small list.
+	for _, v := range printVerbs {
+		if v.verb == verb {
+			for _, flag := range flags {
+				if !strings.ContainsRune(v.flags, rune(flag)) {
+					f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", verb, flag)
+				}
+			}
+			return
+		}
+	}
+	f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
+}
+
+// checkPrint checks a call to an unformatted print routine such as Println.
+// The skip argument records how many arguments to ignore; that is,
+// call.Args[skip] is the first argument to be printed.
+func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
+	isLn := strings.HasSuffix(name, "ln")
+	args := call.Args
+	if len(args) <= skip {
+		if *verbose && !isLn {
+			f.Badf(call.Pos(), "no args in %s call", name)
+		}
+		return
+	}
+	arg := args[skip]
+	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
+		if strings.Contains(lit.Value, "%") {
+			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
+		}
+	}
+	if isLn {
+		// The last item, if a string, should not have a newline.
+		arg = args[len(call.Args)-1]
+		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
+			if strings.HasSuffix(lit.Value, `\n"`) {
+				f.Badf(call.Pos(), "%s call ends with newline", name)
+			}
+		}
+	}
+}
+
+// This function never executes, but it serves as a simple test for the program.
+// Test with make test.
+func BadFunctionUsedInTests() {
+	fmt.Println()                      // not an error
+	fmt.Println("%s", "hi")            // ERROR "possible formatting directive in Println call"
+	fmt.Printf("%s", "hi", 3)          // ERROR "wrong number of args in Printf call"
+	fmt.Printf("%s%%%d", "hi", 3)      // correct
+	fmt.Printf("%.*d", 3, 3)           // correct
+	fmt.Printf("%.*d", 3, 3, 3)        // ERROR "wrong number of args in Printf call"
+	printf("now is the time", "buddy") // ERROR "no formatting directive"
+	Printf("now is the time", "buddy") // ERROR "no formatting directive"
+	Printf("hi")                       // ok
+	f := new(File)
+	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
+	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
+	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
+	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
+}
+
+type BadTypeUsedInTests struct {
+	X int "hello" // ERROR "struct field tag"
+}
+
+func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
+}
+
+type BadInterfaceUsedInTests interface {
+	ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
+}
+
+// printf is used by the test.
+func printf(format string, args ...interface{}) {
+	panic("don't call - testing only")
+}
diff --git a/src/cmd/govet/structtag.go b/src/cmd/govet/structtag.go
new file mode 100644
index 0000000..ea2a9d8
--- /dev/null
+++ b/src/cmd/govet/structtag.go
@@ -0,0 +1,34 @@
+// Copyright 2010 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 file contains the test for canonical struct tags.
+
+package main
+
+import (
+	"go/ast"
+	"reflect"
+	"strconv"
+)
+
+// checkField checks a struct field tag.
+func (f *File) checkCanonicalFieldTag(field *ast.Field) {
+	if field.Tag == nil {
+		return
+	}
+
+	tag, err := strconv.Unquote(field.Tag.Value)
+	if err != nil {
+		f.Warnf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
+		return
+	}
+
+	// Check tag for validity by appending
+	// new key:value to end and checking that
+	// the tag parsing code can find it.
+	if reflect.StructTag(tag+` _gofix:"_magic"`).Get("_gofix") != "_magic" {
+		f.Warnf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get", field.Tag.Value)
+		return
+	}
+}
diff --git a/src/cmd/goyacc/Makefile b/src/cmd/goyacc/Makefile
index ac0f427..a616e85 100644
--- a/src/cmd/goyacc/Makefile
+++ b/src/cmd/goyacc/Makefile
@@ -12,6 +12,7 @@ include ../../Make.cmd
 
 units: goyacc units.y
 	./goyacc -p units_ units.y
-	$(GC) y.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) y.go
 	$(LD) -o units y.$O
 
+CLEANFILES += units y.go y.output
diff --git a/src/cmd/goyacc/goyacc.go b/src/cmd/goyacc/goyacc.go
index 4815401..e1b99be 100644
--- a/src/cmd/goyacc/goyacc.go
+++ b/src/cmd/goyacc/goyacc.go
@@ -45,12 +45,12 @@ package main
 //
 
 import (
+	"bufio"
+	"bytes"
 	"flag"
 	"fmt"
-	"bufio"
 	"os"
 	"strings"
-	"bytes"
 )
 
 // the following are adjustable
@@ -506,19 +506,20 @@ outer:
 		// non-literals
 		c := tokset[i].name[0]
 		if c != ' ' && c != '$' {
-			fmt.Fprintf(ftable, "const\t%v\t= %v\n", tokset[i].name, tokset[i].value)
+			fmt.Fprintf(ftable, "const %v = %v\n", tokset[i].name, tokset[i].value)
 		}
 	}
 
 	// put out names of token names
-	fmt.Fprintf(ftable, "var\t%sToknames\t =[]string {\n", prefix)
+	ftable.WriteRune('\n')
+	fmt.Fprintf(ftable, "var %sToknames = []string{\n", prefix)
 	for i := TOKSTART; i <= ntokens; i++ {
 		fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name)
 	}
 	fmt.Fprintf(ftable, "}\n")
 
 	// put out names of state names
-	fmt.Fprintf(ftable, "var\t%sStatenames\t =[]string {\n", prefix)
+	fmt.Fprintf(ftable, "var %sStatenames = []string{", prefix)
 	//	for i:=TOKSTART; i<=ntokens; i++ {
 	//		fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name);
 	//	}
@@ -595,7 +596,7 @@ outer:
 				break
 			}
 			levprd[nprod] |= ACTFLAG
-			fmt.Fprintf(fcode, "\ncase %v:", nprod)
+			fmt.Fprintf(fcode, "\n\tcase %v:", nprod)
 			cpyact(curprod, mem)
 
 			// action within rule...
@@ -652,8 +653,8 @@ outer:
 			if tempty != nontrst[curprod[0]-NTBASE].value {
 				errorf("default action causes potential type clash")
 			}
-			fmt.Fprintf(fcode, "\ncase %v:", nprod)
-			fmt.Fprintf(fcode, "\n\t%sVAL.%v = %sS[%spt-0].%v;",
+			fmt.Fprintf(fcode, "\n\tcase %v:", nprod)
+			fmt.Fprintf(fcode, "\n\t\t%sVAL.%v = %sS[%spt-0].%v",
 				prefix, typeset[tempty], prefix, prefix, typeset[tempty])
 		}
 		moreprod()
@@ -671,9 +672,10 @@ outer:
 
 	fmt.Fprintf(fcode, "\n\t}")
 
-	fmt.Fprintf(ftable, "const	%sEofCode	= 1\n", prefix)
-	fmt.Fprintf(ftable, "const	%sErrCode	= 2\n", prefix)
-	fmt.Fprintf(ftable, "const	%sMaxDepth	= %v\n", prefix, stacksize)
+	ftable.WriteRune('\n')
+	fmt.Fprintf(ftable, "const %sEofCode = 1\n", prefix)
+	fmt.Fprintf(ftable, "const %sErrCode = 2\n", prefix)
+	fmt.Fprintf(ftable, "const %sMaxDepth = %v\n", prefix, stacksize)
 
 	//
 	// copy any postfix code
@@ -811,7 +813,8 @@ func defin(nt int, s string) int {
 var peekline = 0
 
 func gettok() int {
-	var i, match, c int
+	var i int
+	var match, c rune
 
 	tokname = ""
 	for {
@@ -917,25 +920,25 @@ func gettok() int {
 
 		getword(c)
 		// find a reserved word
-		for c = 0; c < len(resrv); c++ {
-			if tokname == resrv[c].name {
+		for i := range resrv {
+			if tokname == resrv[i].name {
 				if tokflag {
 					fmt.Printf(">>> %%%v %v %v\n", tokname,
-						resrv[c].value-PRIVATE, lineno)
+						resrv[i].value-PRIVATE, lineno)
 				}
-				return resrv[c].value
+				return resrv[i].value
 			}
 		}
 		errorf("invalid escape, or illegal reserved word: %v", tokname)
 
 	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
-		numbval = c - '0'
+		numbval = int(c - '0')
 		for {
 			c = getrune(finput)
 			if !isdigit(c) {
 				break
 			}
-			numbval = numbval*10 + c - '0'
+			numbval = numbval*10 + int(c-'0')
 		}
 		ungetrune(finput, c)
 		if tokflag {
@@ -951,7 +954,7 @@ func gettok() int {
 		if tokflag {
 			fmt.Printf(">>> OPERATOR %v %v\n", string(c), lineno)
 		}
-		return c
+		return int(c)
 	}
 
 	// look ahead to distinguish IDENTIFIER from IDENTCOLON
@@ -980,7 +983,7 @@ func gettok() int {
 	return IDENTIFIER
 }
 
-func getword(c int) {
+func getword(c rune) {
 	tokname = ""
 	for isword(c) || isdigit(c) || c == '_' || c == '.' || c == '$' {
 		tokname += string(c)
@@ -1039,7 +1042,7 @@ func cpyunion() {
 	if !lflag {
 		fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
 	}
-	fmt.Fprintf(ftable, "type\t%sSymType\tstruct", prefix)
+	fmt.Fprintf(ftable, "type %sSymType struct", prefix)
 
 	level := 0
 
@@ -1055,7 +1058,7 @@ out:
 			lineno++
 		case '{':
 			if level == 0 {
-				fmt.Fprintf(ftable, "\n\tyys\tint;")
+				fmt.Fprintf(ftable, "\n\tyys int")
 			}
 			level++
 		case '}':
@@ -1065,7 +1068,7 @@ out:
 			}
 		}
 	}
-	fmt.Fprintf(ftable, "\n")
+	fmt.Fprintf(ftable, "\n\n")
 }
 
 //
@@ -1105,7 +1108,7 @@ func cpycode() {
 // skipcom is called after reading a '/'
 //
 func skipcom() int {
-	var c int
+	var c rune
 
 	c = getrune(finput)
 	if c == '/' {
@@ -1163,7 +1166,7 @@ func dumpprod(curprod []int, max int) {
 func cpyact(curprod []int, max int) {
 
 	if !lflag {
-		fmt.Fprintf(fcode, "\n//line %v:%v\n", infile, lineno)
+		fmt.Fprintf(fcode, "\n\t\t//line %v:%v\n\t\t", infile, lineno)
 	}
 
 	lno := lineno
@@ -1177,14 +1180,13 @@ loop:
 		switch c {
 		case ';':
 			if brac == 0 {
-				ftable.WriteRune(c)
+				fcode.WriteRune(c)
 				return
 			}
 
 		case '{':
 			if brac == 0 {
 			}
-			ftable.WriteRune('\t')
 			brac++
 
 		case '$':
@@ -1220,7 +1222,7 @@ loop:
 			j := 0
 			if isdigit(c) {
 				for isdigit(c) {
-					j = j*10 + c - '0'
+					j = j*10 + int(c-'0')
 					c = getrune(finput)
 				}
 				ungetrune(finput, c)
@@ -1345,7 +1347,9 @@ loop:
 			errorf("action does not terminate")
 
 		case '\n':
+			fmt.Fprint(fcode, "\n\t")
 			lineno++
+			continue loop
 		}
 
 		fcode.WriteRune(c)
@@ -2072,7 +2076,7 @@ func output() {
 	var c, u, v int
 
 	fmt.Fprintf(ftable, "\n//line yacctab:1\n")
-	fmt.Fprintf(ftable, "var\t%sExca = []int {\n", prefix)
+	fmt.Fprintf(ftable, "var %sExca = []int{\n", prefix)
 
 	noset := mkset()
 
@@ -2145,10 +2149,12 @@ func output() {
 	}
 
 	fmt.Fprintf(ftable, "}\n")
-	fmt.Fprintf(ftable, "const\t%sNprod\t= %v\n", prefix, nprod)
-	fmt.Fprintf(ftable, "const\t%sPrivate\t= %v\n", prefix, PRIVATE)
-	fmt.Fprintf(ftable, "var\t%sTokenNames []string\n", prefix)
-	fmt.Fprintf(ftable, "var\t%sStates []string\n", prefix)
+	ftable.WriteRune('\n')
+	fmt.Fprintf(ftable, "const %sNprod = %v\n", prefix, nprod)
+	fmt.Fprintf(ftable, "const %sPrivate = %v\n", prefix, PRIVATE)
+	ftable.WriteRune('\n')
+	fmt.Fprintf(ftable, "var %sTokenNames []string\n", prefix)
+	fmt.Fprintf(ftable, "var %sStates []string\n", prefix)
 }
 
 //
@@ -2264,7 +2270,7 @@ func wract(i int) {
 				continue
 			}
 			if flag == 0 {
-				fmt.Fprintf(ftable, "-1, %v,\n", i)
+				fmt.Fprintf(ftable, "\t-1, %v,\n", i)
 			}
 			flag++
 			fmt.Fprintf(ftable, "\t%v, %v,\n", p, p1)
@@ -2723,7 +2729,8 @@ nextn:
 // write out the optimized parser
 //
 func aoutput() {
-	fmt.Fprintf(ftable, "const\t%sLast\t= %v\n", prefix, maxa+1)
+	ftable.WriteRune('\n')
+	fmt.Fprintf(ftable, "const %sLast = %v\n\n", prefix, maxa+1)
 	arout("Act", amem, maxa+1)
 	arout("Pact", indgo, nstate)
 	arout("Pgo", pgo, nnonter+1)
@@ -2805,7 +2812,7 @@ func others() {
 	arout("Tok2", temp1, c+1)
 
 	// table 3 has everything else
-	fmt.Fprintf(ftable, "var\t%sTok3\t= []int {\n", prefix)
+	fmt.Fprintf(ftable, "var %sTok3 = []int{\n\t", prefix)
 	c = 0
 	for i = 1; i <= ntokens; i++ {
 		j = tokset[i].value
@@ -2816,19 +2823,25 @@ func others() {
 			continue
 		}
 
-		fmt.Fprintf(ftable, "%4d,%4d,", j, i)
+		if c%5 != 0 {
+			ftable.WriteRune(' ')
+		}
+		fmt.Fprintf(ftable, "%d, %d,", j, i)
 		c++
 		if c%5 == 0 {
-			ftable.WriteRune('\n')
+			fmt.Fprint(ftable, "\n\t")
 		}
 	}
-	fmt.Fprintf(ftable, "%4d,\n };\n", 0)
+	if c%5 != 0 {
+		ftable.WriteRune(' ')
+	}
+	fmt.Fprintf(ftable, "%d,\n}\n", 0)
 
 	// copy parser text
-	c = getrune(finput)
-	for c != EOF {
-		ftable.WriteRune(c)
-		c = getrune(finput)
+	ch := getrune(finput)
+	for ch != EOF {
+		ftable.WriteRune(ch)
+		ch = getrune(finput)
 	}
 
 	// copy yaccpar
@@ -2842,15 +2855,16 @@ func others() {
 
 func arout(s string, v []int, n int) {
 	s = prefix + s
-	fmt.Fprintf(ftable, "var\t%v\t= []int {\n", s)
+	fmt.Fprintf(ftable, "var %v = []int{\n", s)
 	for i := 0; i < n; i++ {
 		if i%10 == 0 {
-			ftable.WriteRune('\n')
+			fmt.Fprintf(ftable, "\n\t")
+		} else {
+			ftable.WriteRune(' ')
 		}
-		fmt.Fprintf(ftable, "%4d", v[i])
-		ftable.WriteRune(',')
+		fmt.Fprintf(ftable, "%d,", v[i])
 	}
-	fmt.Fprintf(ftable, "\n};\n")
+	fmt.Fprintf(ftable, "\n}\n")
 }
 
 //
@@ -2963,11 +2977,11 @@ func prlook(p Lkset) {
 //
 // utility routines
 //
-var peekrune int
+var peekrune rune
 
-func isdigit(c int) bool { return c >= '0' && c <= '9' }
+func isdigit(c rune) bool { return c >= '0' && c <= '9' }
 
-func isword(c int) bool {
+func isword(c rune) bool {
 	return c >= 0xa0 || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
 }
 
@@ -2997,8 +3011,8 @@ func putrune(f *bufio.Writer, c int) {
 	}
 }
 
-func getrune(f *bufio.Reader) int {
-	var r int
+func getrune(f *bufio.Reader) rune {
+	var r rune
 
 	if peekrune != 0 {
 		if peekrune == EOF {
@@ -3020,7 +3034,7 @@ func getrune(f *bufio.Reader) int {
 	return c
 }
 
-func ungetrune(f *bufio.Reader, c int) {
+func ungetrune(f *bufio.Reader, c rune) {
 	if f != finput {
 		panic("ungetc - not finput")
 	}
@@ -3257,10 +3271,9 @@ $$default:
 					}
 				}
 
-				/* the current p has no shift onn "error", pop stack */
+				/* the current p has no shift on "error", pop stack */
 				if $$Debug >= 2 {
-					fmt.Printf("error recovery pops state %d, uncovers %d\n",
-						$$S[$$p].yys, $$S[$$p-1].yys)
+					fmt.Printf("error recovery pops state %d\n", $$S[$$p].yys)
 				}
 				$$p--
 			}
@@ -3286,7 +3299,7 @@ $$default:
 
 	$$nt := $$n
 	$$pt := $$p
-	_ = $$pt		// guard against "declared and not used"
+	_ = $$pt // guard against "declared and not used"
 
 	$$p -= $$R2[$$n]
 	$$VAL = $$S[$$p+1]
diff --git a/src/cmd/goyacc/units.y b/src/cmd/goyacc/units.y
index d9ef663..3833486 100644
--- a/src/cmd/goyacc/units.y
+++ b/src/cmd/goyacc/units.y
@@ -14,7 +14,7 @@
 // units.y
 // example of a goyacc program
 // usage is
-//	goyacc units.y (produces y.go)
+//	goyacc -p "units_" units.y (produces y.go)
 //	6g y.go
 //	6l y.6
 //	./6.out $GOROOT/src/cmd/goyacc/units
@@ -33,7 +33,7 @@ import (
 	"os"
 	"math"
 	"strconv"
-	"utf8"
+	"unicode/utf8"
 )
 
 const (
@@ -58,21 +58,19 @@ var lineno int       // current input line number
 var linep int        // index to next rune in unput
 var nerrors int      // error count
 var one Node         // constant one
-var peekrune int     // backup runt from input
+var peekrune rune    // backup runt from input
 var retnode1 Node
 var retnode2 Node
 var retnode Node
 var sym string
 var vflag bool
-
 %}
 
-%union
-{
-	node	Node
-	vvar	*Var
-	numb	int
-	vval	float64
+%union {
+	node Node
+	vvar *Var
+	numb int
+	vval float64
 }
 
 %type	<node>	prog expr expr0 expr1 expr2 expr3 expr4
@@ -85,7 +83,6 @@ prog:
 	':' VAR expr
 	{
 		var f int
-
 		f = int($2.node.dim[0])
 		$2.node = $3
 		$2.node.dim[0] = 1
@@ -98,26 +95,23 @@ prog:
 |	':' VAR '#'
 	{
 		var f, i int
-
-		for i=1; i<Ndim; i++ {
+		for i = 1; i < Ndim; i++ {
 			if fund[i] == nil {
 				break
 			}
 		}
 		if i >= Ndim {
 			Error("too many dimensions")
-			i = Ndim-1
+			i = Ndim - 1
 		}
 		fund[i] = $2
-
 		f = int($2.node.dim[0])
 		$2.node = one
 		$2.node.dim[0] = 1
 		$2.node.dim[i] = 1
 		if f != 0 {
 			Errorf("redefinition of %v", $2.name)
-		} else
-		if vflag {
+		} else if vflag {
 			fmt.Printf("%v\t#\n", $2.name)
 		}
 	}
@@ -171,8 +165,7 @@ expr2:
 |	expr2 '^' expr1
 	{
 		var i int
-
-		for i=1; i<Ndim; i++ {
+		for i = 1; i < Ndim; i++ {
 			if $3.dim[i] != 0 {
 				Error("exponent has units")
 				$$ = $1
@@ -219,7 +212,8 @@ expr0:
 type UnitsLex int
 
 func (UnitsLex) Lex(yylval *units_SymType) int {
-	var c, i int
+	var c rune
+	var i int
 
 	c = peekrune
 	peekrune = ' '
@@ -249,7 +243,7 @@ loop:
 		yylval.numb = 3
 		return SUP
 	}
-	return c
+	return int(c)
 
 alpha:
 	sym = ""
@@ -274,7 +268,7 @@ numb:
 		}
 	}
 	peekrune = c
-	f, err := strconv.Atof64(sym)
+	f, err := strconv.ParseFloat(sym, 64)
 	if err != nil {
 		fmt.Printf("error converting %v\n", sym)
 		f = 0
@@ -369,7 +363,7 @@ func main() {
  * all characters that have some
  * meaning. rest are usable as names
  */
-func ralpha(c int) bool {
+func ralpha(c rune) bool {
 	switch c {
 	case 0, '+', '-', '*', '/', '[', ']', '(', ')',
 		'^', ':', '?', ' ', '\t', '.', '|', '#',
@@ -382,7 +376,7 @@ func ralpha(c int) bool {
 /*
  * number forming character
  */
-func rdigit(c int) bool {
+func rdigit(c rune) bool {
 	switch c {
 	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 		'.', 'e', '+', '-':
@@ -584,8 +578,9 @@ func readline() bool {
 	return false
 }
 
-func getrune() int {
-	var c, n int
+func getrune() rune {
+	var c rune
+	var n int
 
 	if linep >= len(line) {
 		return 0
@@ -690,7 +685,6 @@ func pname() float64 {
 	return 0
 }
 
-
 // careful multiplication
 // exponents (log) are checked before multiply
 func fmul(a, b float64) float64 {
diff --git a/src/cmd/hgpatch/Makefile b/src/cmd/hgpatch/Makefile
deleted file mode 100644
index 1ef98d7..0000000
--- a/src/cmd/hgpatch/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=hgpatch
-GOFILES=\
-	main.go\
-
-include ../../Make.cmd
diff --git a/src/cmd/hgpatch/doc.go b/src/cmd/hgpatch/doc.go
deleted file mode 100644
index 1e0f1da..0000000
--- a/src/cmd/hgpatch/doc.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-
-Hgpatch applies a patch to the local Mercurial repository.
-The patch should have been been generated by
-a version control system like CVS, Git, Mercurial, or Subversion.
-If successful, hgpatch writes a list of affected files to standard output.
-
-Hgpatch is meant to be used by the Mercurial codereview extension.
-
-Usage:
-	hgpatch [patchfile]
-
-*/
-package documentation
diff --git a/src/cmd/hgpatch/main.go b/src/cmd/hgpatch/main.go
deleted file mode 100644
index d4169ae..0000000
--- a/src/cmd/hgpatch/main.go
+++ /dev/null
@@ -1,359 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-	"bytes"
-	"exec"
-	"flag"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"patch"
-	"path/filepath"
-	"sort"
-	"strings"
-)
-
-var checkSync = flag.Bool("checksync", true, "check whether repository is out of sync")
-
-func usage() {
-	fmt.Fprintf(os.Stderr, "usage: hgpatch [options] [patchfile]\n")
-	flag.PrintDefaults()
-	os.Exit(2)
-}
-
-func main() {
-	flag.Usage = usage
-	flag.Parse()
-
-	args := flag.Args()
-	var data []byte
-	var err os.Error
-	switch len(args) {
-	case 0:
-		data, err = ioutil.ReadAll(os.Stdin)
-	case 1:
-		data, err = ioutil.ReadFile(args[0])
-	default:
-		usage()
-	}
-	chk(err)
-
-	pset, err := patch.Parse(data)
-	chk(err)
-
-	// Change to hg root directory, because
-	// patch paths are relative to root.
-	root, err := hgRoot()
-	chk(err)
-	chk(os.Chdir(root))
-
-	// Make sure there are no pending changes on the server.
-	if *checkSync && hgIncoming() {
-		fmt.Fprintf(os.Stderr, "incoming changes waiting; run hg sync first\n")
-		os.Exit(2)
-	}
-
-	// Make sure we won't be editing files with local pending changes.
-	dirtylist, err := hgModified()
-	chk(err)
-	dirty := make(map[string]bool)
-	for _, f := range dirtylist {
-		dirty[f] = true
-	}
-	conflict := make(map[string]bool)
-	for _, f := range pset.File {
-		if f.Verb == patch.Delete || f.Verb == patch.Rename {
-			if dirty[f.Src] {
-				conflict[f.Src] = true
-			}
-		}
-		if f.Verb != patch.Delete {
-			if dirty[f.Dst] {
-				conflict[f.Dst] = true
-			}
-		}
-	}
-	if len(conflict) > 0 {
-		fmt.Fprintf(os.Stderr, "cannot apply patch to locally modified files:\n")
-		for name := range conflict {
-			fmt.Fprintf(os.Stderr, "\t%s\n", name)
-		}
-		os.Exit(2)
-	}
-
-	// Apply changes in memory.
-	op, err := pset.Apply(ioutil.ReadFile)
-	chk(err)
-
-	// Write changes to disk copy: order of commands matters.
-	// Accumulate undo log as we go, in case there is an error.
-	// Also accumulate list of modified files to print at end.
-	changed := make(map[string]int)
-
-	// Copy, Rename create the destination file, so they
-	// must happen before we write the data out.
-	// A single patch may have a Copy and a Rename
-	// with the same source, so we have to run all the
-	// Copy in one pass, then all the Rename.
-	for i := range op {
-		o := &op[i]
-		if o.Verb == patch.Copy {
-			makeParent(o.Dst)
-			chk(hgCopy(o.Dst, o.Src))
-			undoRevert(o.Dst)
-			changed[o.Dst] = 1
-		}
-	}
-	for i := range op {
-		o := &op[i]
-		if o.Verb == patch.Rename {
-			makeParent(o.Dst)
-			chk(hgRename(o.Dst, o.Src))
-			undoRevert(o.Dst)
-			undoRevert(o.Src)
-			changed[o.Src] = 1
-			changed[o.Dst] = 1
-		}
-	}
-
-	// Run Delete before writing to files in case one of the
-	// deleted paths is becoming a directory.
-	for i := range op {
-		o := &op[i]
-		if o.Verb == patch.Delete {
-			chk(hgRemove(o.Src))
-			undoRevert(o.Src)
-			changed[o.Src] = 1
-		}
-	}
-
-	// Write files.
-	for i := range op {
-		o := &op[i]
-		if o.Verb == patch.Delete {
-			continue
-		}
-		if o.Verb == patch.Add {
-			makeParent(o.Dst)
-			changed[o.Dst] = 1
-		}
-		if o.Data != nil {
-			chk(ioutil.WriteFile(o.Dst, o.Data, 0644))
-			if o.Verb == patch.Add {
-				undoRm(o.Dst)
-			} else {
-				undoRevert(o.Dst)
-			}
-			changed[o.Dst] = 1
-		}
-		if o.Mode != 0 {
-			chk(os.Chmod(o.Dst, uint32(o.Mode&0755)))
-			undoRevert(o.Dst)
-			changed[o.Dst] = 1
-		}
-	}
-
-	// hg add looks at the destination file, so it must happen
-	// after we write the data out.
-	for i := range op {
-		o := &op[i]
-		if o.Verb == patch.Add {
-			chk(hgAdd(o.Dst))
-			undoRevert(o.Dst)
-			changed[o.Dst] = 1
-		}
-	}
-
-	// Finished editing files.  Write the list of changed files to stdout.
-	list := make([]string, len(changed))
-	i := 0
-	for f := range changed {
-		list[i] = f
-		i++
-	}
-	sort.Strings(list)
-	for _, f := range list {
-		fmt.Printf("%s\n", f)
-	}
-}
-
-// make parent directory for name, if necessary
-func makeParent(name string) {
-	parent, _ := filepath.Split(name)
-	chk(mkdirAll(parent, 0755))
-}
-
-// Copy of os.MkdirAll but adds to undo log after
-// creating a directory.
-func mkdirAll(path string, perm uint32) os.Error {
-	dir, err := os.Lstat(path)
-	if err == nil {
-		if dir.IsDirectory() {
-			return nil
-		}
-		return &os.PathError{"mkdir", path, os.ENOTDIR}
-	}
-
-	i := len(path)
-	for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
-		i--
-	}
-
-	j := i
-	for j > 0 && path[j-1] != '/' { // Scan backward over element.
-		j--
-	}
-
-	if j > 0 {
-		err = mkdirAll(path[0:j-1], perm)
-		if err != nil {
-			return err
-		}
-	}
-
-	err = os.Mkdir(path, perm)
-	if err != nil {
-		// Handle arguments like "foo/." by
-		// double-checking that directory doesn't exist.
-		dir, err1 := os.Lstat(path)
-		if err1 == nil && dir.IsDirectory() {
-			return nil
-		}
-		return err
-	}
-	undoRm(path)
-	return nil
-}
-
-// If err != nil, process the undo log and exit.
-func chk(err os.Error) {
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "%s\n", err)
-		runUndo()
-		os.Exit(2)
-	}
-}
-
-// Undo log
-type undo func() os.Error
-
-var undoLog []undo
-
-func undoRevert(name string) {
-	undoLog = append(undoLog, undo(func() os.Error { return hgRevert(name) }))
-}
-
-func undoRm(name string) { undoLog = append(undoLog, undo(func() os.Error { return os.Remove(name) })) }
-
-func runUndo() {
-	for i := len(undoLog) - 1; i >= 0; i-- {
-		if err := undoLog[i](); err != nil {
-			fmt.Fprintf(os.Stderr, "%s\n", err)
-		}
-	}
-}
-
-// hgRoot returns the root directory of the repository.
-func hgRoot() (string, os.Error) {
-	out, err := run([]string{"hg", "root"}, nil)
-	if err != nil {
-		return "", err
-	}
-	return strings.TrimSpace(out), nil
-}
-
-// hgIncoming returns true if hg sync will pull in changes.
-func hgIncoming() bool {
-	// hg -q incoming exits 0 when there is nothing incoming, 1 otherwise.
-	_, err := run([]string{"hg", "-q", "incoming"}, nil)
-	return err == nil
-}
-
-// hgModified returns a list of the modified files in the
-// repository.
-func hgModified() ([]string, os.Error) {
-	out, err := run([]string{"hg", "status", "-n"}, nil)
-	if err != nil {
-		return nil, err
-	}
-	return strings.Split(strings.TrimSpace(out), "\n"), nil
-}
-
-// hgAdd adds name to the repository.
-func hgAdd(name string) os.Error {
-	_, err := run([]string{"hg", "add", name}, nil)
-	return err
-}
-
-// hgRemove removes name from the repository.
-func hgRemove(name string) os.Error {
-	_, err := run([]string{"hg", "rm", name}, nil)
-	return err
-}
-
-// hgRevert reverts name.
-func hgRevert(name string) os.Error {
-	_, err := run([]string{"hg", "revert", name}, nil)
-	return err
-}
-
-// hgCopy copies src to dst in the repository.
-// Note that the argument order matches io.Copy, not "hg cp".
-func hgCopy(dst, src string) os.Error {
-	_, err := run([]string{"hg", "cp", src, dst}, nil)
-	return err
-}
-
-// hgRename renames src to dst in the repository.
-// Note that the argument order matches io.Copy, not "hg mv".
-func hgRename(dst, src string) os.Error {
-	_, err := run([]string{"hg", "mv", src, dst}, nil)
-	return err
-}
-
-func dup(a []string) []string {
-	b := make([]string, len(a))
-	copy(b, a)
-	return b
-}
-
-var lookPathCache = make(map[string]string)
-
-// run runs the command argv, resolving argv[0] if necessary by searching $PATH.
-// It provides input on standard input to the command.
-func run(argv []string, input []byte) (out string, err os.Error) {
-	if len(argv) < 1 {
-		return "", &runError{dup(argv), os.EINVAL}
-	}
-
-	prog, ok := lookPathCache[argv[0]]
-	if !ok {
-		prog, err = exec.LookPath(argv[0])
-		if err != nil {
-			return "", &runError{dup(argv), err}
-		}
-		lookPathCache[argv[0]] = prog
-	}
-
-	cmd := exec.Command(prog, argv[1:]...)
-	if len(input) > 0 {
-		cmd.Stdin = bytes.NewBuffer(input)
-	}
-	bs, err := cmd.CombinedOutput()
-	if err != nil {
-		return "", &runError{dup(argv), err}
-	}
-	return string(bs), nil
-}
-
-// A runError represents an error that occurred while running a command.
-type runError struct {
-	cmd []string
-	err os.Error
-}
-
-func (e *runError) String() string { return strings.Join(e.cmd, " ") + ": " + e.err.String() }
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index a7f61c9..d34d23c 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -824,6 +824,8 @@ dodata(void)
 	datsize = 0;
 	s = datap;
 	for(; s != nil && s->type < SSYMTAB; s = s->next) {
+		if(s->align != 0)
+			datsize = rnd(datsize, s->align);
 		s->type = SRODATA;
 		s->value = datsize;
 		datsize += rnd(s->size, PtrSize);
@@ -855,6 +857,8 @@ dodata(void)
 	/* read-only ELF sections */
 	for(; s != nil && s->type < SELFSECT; s = s->next) {
 		sect = addsection(&segtext, s->name, 04);
+		if(s->align != 0)
+			datsize = rnd(datsize, s->align);
 		sect->vaddr = datsize;
 		s->type = SRODATA;
 		s->value = datsize;
@@ -866,6 +870,8 @@ dodata(void)
 	datsize = 0;
 	for(; s != nil && s->type < SDATA; s = s->next) {
 		sect = addsection(&segdata, s->name, 06);
+		if(s->align != 0)
+			datsize = rnd(datsize, s->align);
 		sect->vaddr = datsize;
 		s->type = SDATA;
 		s->value = datsize;
@@ -887,7 +893,9 @@ dodata(void)
 			t = rnd(t, PtrSize);
 		else if(t > 2)
 			t = rnd(t, 4);
-		if(t & 1) {
+		if(s->align != 0)
+			datsize = rnd(datsize, s->align);
+		else if(t & 1) {
 			;
 		} else if(t & 2)
 			datsize = rnd(datsize, 2);
@@ -913,7 +921,9 @@ dodata(void)
 			t = rnd(t, PtrSize);
 		else if(t > 2)
 			t = rnd(t, 4);
-		if(t & 1) {
+		if(s->align != 0)
+			datsize = rnd(datsize, s->align);
+		else if(t & 1) {
 			;
 		} else if(t & 2)
 			datsize = rnd(datsize, 2);
@@ -947,6 +957,8 @@ textaddress(void)
 	for(sym = textp; sym != nil; sym = sym->next) {
 		if(sym->type & SSUB)
 			continue;
+		if(sym->align != 0)
+			va = rnd(va, sym->align);
 		sym->value = 0;
 		for(sub = sym; sub != S; sub = sub->sub) {
 			sub->value += va;
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index 7753601..d0ecabf 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -775,7 +775,7 @@ enum {
 	KindNoPointers = 1<<7,
 
 	// size of Type interface header + CommonType structure.
-	CommonSize = 2*PtrSize+ 4*PtrSize + 8,
+	CommonSize = 2*PtrSize+ 5*PtrSize + 8,
 };
 
 static Reloc*
@@ -1356,7 +1356,7 @@ synthesizemaptypes(DWDie *die)
 				getattr(keytype, DW_AT_name)->data,
 				getattr(valtype, DW_AT_name)->data));
 		copychildren(dwhs, hash_subtable);
-		substitutetype(dwhs, "end", defptrto(dwhe));
+		substitutetype(dwhs, "last", defptrto(dwhe));
 		substitutetype(dwhs, "entry", dwhe);  // todo: []hash_entry with dynamic size
 		newattr(dwhs, DW_AT_byte_size, DW_CLS_CONSTANT,
 			getattr(hash_subtable, DW_AT_byte_size)->value, nil);
@@ -1439,7 +1439,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
 	if (strncmp(s, "go.string.", 10) == 0)
 		return;
 
-	if (strncmp(s, "type.", 5) == 0 && strcmp(s, "type.*") != 0) {
+	if (strncmp(s, "type.", 5) == 0 && strcmp(s, "type.*") != 0 && strncmp(s, "type..", 6) != 0) {
 		defgotype(sym);
 		return;
 	}
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 00cfc8c..de9e6b8 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -318,29 +318,77 @@ elfwritedynentsymsize(Sym *s, int tag, Sym *t)
 }
 
 int
-elfwriteinterp(void)
+elfinterp(ElfShdr *sh, uint64 startva, uint64 resoff, char *p)
 {
 	int n;
 
-	if(interp == nil)
-		return 0;
-
+	interp = p;
 	n = strlen(interp)+1;
-	cseek(ELFRESERVE-n);
-	cwrite(interp, n);
+	sh->addr = startva + resoff - n;
+	sh->off = resoff - n;
+	sh->size = n;
+
 	return n;
 }
 
-void
-elfinterp(ElfShdr *sh, uint64 startva, char *p)
+int
+elfwriteinterp(vlong stridx)
+{
+	ElfShdr *sh = nil;
+	int i;
+
+	for(i = 0; i < hdr.shnum; i++)
+		if(shdr[i]->name == stridx)
+			sh = shdr[i];
+	if(sh == nil || interp == nil)
+		return 0;
+
+	cseek(sh->off);
+	cwrite(interp, sh->size);
+	return sh->size;
+}
+
+// Defined in NetBSD's sys/exec_elf.h
+#define ELF_NOTE_TYPE_NETBSD_TAG	1
+#define ELF_NOTE_NETBSD_NAMESZ		7
+#define ELF_NOTE_NETBSD_DESCSZ		4
+#define ELF_NOTE_NETBSD_NAME		"NetBSD\0\0"
+#define ELF_NOTE_NETBSD_VERSION		599000000	/* NetBSD 5.99 */
+
+int
+elfnetbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
 {
 	int n;
 
-	interp = p;
-	n = strlen(interp)+1;
-	sh->addr = startva + ELFRESERVE - n;
-	sh->off = ELFRESERVE - n;
+	n = sizeof(Elf_Note) + ELF_NOTE_NETBSD_NAMESZ + ELF_NOTE_NETBSD_DESCSZ + 1;
+	n += resoff % 4;
+	sh->addr = startva + resoff - n;
+	sh->off = resoff - n;
 	sh->size = n;
+
+	return n;
+}
+
+int
+elfwritenetbsdsig(vlong stridx) {
+	ElfShdr *sh = nil;
+	int i;
+
+	for(i = 0; i < hdr.shnum; i++)
+		if(shdr[i]->name == stridx)
+			sh = shdr[i];
+	if(sh == nil)
+		return 0;
+
+	// Write Elf_Note header followed by NetBSD string.
+	cseek(sh->off);
+	LPUT(ELF_NOTE_NETBSD_NAMESZ);
+	LPUT(ELF_NOTE_NETBSD_DESCSZ);
+	LPUT(ELF_NOTE_TYPE_NETBSD_TAG);
+	cwrite(ELF_NOTE_NETBSD_NAME, 8);
+	LPUT(ELF_NOTE_NETBSD_VERSION);
+
+	return sh->size;
 }
 
 extern int nelfsym;
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index c63df22..690ade9 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -968,8 +968,10 @@ extern	int	numelfphdr;
 extern	int	numelfshdr;
 extern	int	iself;
 extern	int	elfverneed;
-int	elfwriteinterp(void);
-void	elfinterp(ElfShdr*, uint64, char*);
+int	elfinterp(ElfShdr*, uint64, uint64, char*);
+int	elfwriteinterp(vlong);
+int	elfnetbsdsig(ElfShdr*, uint64, uint64);
+int	elfwritenetbsdsig(vlong);
 void	elfdynhash(void);
 ElfPhdr* elfphload(Segment*);
 ElfShdr* elfshbits(Section*);
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index fd7278a..2bda628 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -235,7 +235,7 @@ loadpkgdata(char *file, char *pkg, char *data, int len)
 		x = ilookup(name);
 		if(x->prefix == nil) {
 			x->prefix = prefix;
-			x->def = def;
+			x->def = strdup(def);
 			x->file = file;
 		} else if(strcmp(x->prefix, prefix) != 0) {
 			fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
@@ -248,7 +248,10 @@ loadpkgdata(char *file, char *pkg, char *data, int len)
 			fprint(2, "%s:\t%s %s %s\n", file, prefix, name, def);
 			nerrors++;
 		}
+		free(name);
+		free(def);
 	}
+	free(file);
 }
 
 // replace all "". with pkg.
@@ -264,7 +267,7 @@ expandpkg(char *t0, char *pkg)
 		n++;
 
 	if(n == 0)
-		return t0;
+		return strdup(t0);
 
 	// use malloc, not mal, so that caller can free
 	w0 = malloc(strlen(t0) + strlen(pkg)*n);
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index 9246878..bd4f3e7 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -538,6 +538,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
 			s->np = sect->size;
 		}
 		s->size = sect->size;
+		s->align = sect->align;
 		if(s->type == STEXT) {
 			if(etextp)
 				etextp->next = s;
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index 6805570..feb8620 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -282,8 +282,10 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 					diag("%s: unknown relocation type %d;", pn, type);
 				case IMAGE_REL_I386_REL32:
 				case IMAGE_REL_AMD64_REL32:
+				case IMAGE_REL_AMD64_ADDR32: // R_X86_64_PC32
+				case IMAGE_REL_AMD64_ADDR32NB:
 					rp->type = D_PCREL;
-					rp->add = 0;
+					rp->add = le32(rsect->base+rp->off);
 					break;
 				case IMAGE_REL_I386_DIR32NB:
 				case IMAGE_REL_I386_DIR32:
@@ -291,10 +293,6 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
 					// load addend from image
 					rp->add = le32(rsect->base+rp->off);
 					break;
-				case IMAGE_REL_AMD64_ADDR32: // R_X86_64_PC32
-					rp->type = D_PCREL;
-					rp->add += 4;
-					break;
 				case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64
 					rp->siz = 8;
 					rp->type = D_ADDR;
@@ -408,13 +406,15 @@ readsym(PeObj *obj, int i, PeSym **y)
 	sym = &obj->pesym[i];
 	*y = sym;
 	
-	name = sym->name;
-	if(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0) // section
+	if(sym->name[0] == '.') // .section
 		name = obj->sect[sym->sectnum-1].sym->name;
-	if(strncmp(sym->name, "__imp__", 7) == 0)
-		name = &sym->name[7]; // __imp__Name => Name
-	else if(sym->name[0] == '_') 
-		name = &sym->name[1]; // _Name => Name
+	else {
+		name = sym->name;
+		if(strncmp(name, "__imp_", 6) == 0)
+			name = &name[6]; // __imp_Name => Name
+		if(thechar == '8' && name[0] == '_')
+			name = &name[1]; // _Name => Name
+	}
 	// remove last @XXX
 	p = strchr(name, '@');
 	if(p)
@@ -443,8 +443,8 @@ readsym(PeObj *obj, int i, PeSym **y)
 
 	if(s != nil && s->type == 0 && !(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0))
 		s->type = SXREF;
-	if(strncmp(sym->name, "__imp__", 7) == 0)
-		s->got = -2; // flag for __imp__
+	if(strncmp(sym->name, "__imp_", 6) == 0)
+		s->got = -2; // flag for __imp_
 	sym->sym = s;
 
 	return 0;
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 37379e1..34440b8 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -46,6 +46,7 @@ static int	cout = -1;
 char*	goroot;
 char*	goarch;
 char*	goos;
+char*	theline;
 
 void
 Lflag(char *arg)
@@ -70,7 +71,12 @@ libinit(void)
 	// add goroot to the end of the libdir list.
 	libdir[nlibdir++] = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
 
+	// Unix doesn't like it when we write to a running (or, sometimes,
+	// recently run) binary, so remove the output file before writing it.
+	// On Windows 7, remove() can force the following create() to fail.
+#ifndef _WIN32
 	remove(outfile);
+#endif
 	cout = create(outfile, 1, 0775);
 	if(cout < 0) {
 		diag("cannot create %s", outfile);
@@ -109,7 +115,7 @@ addlib(char *src, char *obj)
 		sprint(name, "");
 		i = 1;
 	} else
-	if(isalpha(histfrog[0]->name[1]) && histfrog[0]->name[2] == ':') {
+	if(isalpha((uchar)histfrog[0]->name[1]) && histfrog[0]->name[2] == ':') {
 		strcpy(name, histfrog[0]->name+1);
 		i = 1;
 	} else
@@ -268,6 +274,7 @@ loadlib(void)
 	for(i=0; i<libraryp; i++) {
 		if(debug['v'])
 			Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i].file, library[i].objref);
+		iscgo |= strcmp(library[i].pkg, "runtime/cgo") == 0;
 		objfile(library[i].file, library[i].pkg);
 	}
 	
@@ -307,15 +314,9 @@ nextar(Biobuf *bp, int off, struct ar_hdr *a)
 			return 0;
 		return -1;
 	}
-	if(r == SAR_HDR) {
-		memmove(a, buf, SAR_HDR);
-	} else if (r == SAR_HDR-SARNAME+16) {	// old Plan 9
-		memset(a->name, ' ', sizeof a->name);
-		memmove(a, buf, 16);
-		memmove((char*)a+SARNAME, buf+16, SAR_HDR-SARNAME);
-	} else {	// unexpected
+	if(r != SAR_HDR)
 		return -1;
-	}
+	memmove(a, buf, SAR_HDR);
 	if(strncmp(a->fmag, ARFMAG, sizeof a->fmag))
 		return -1;
 	arsize = strtol(a->size, 0, 0);
@@ -350,6 +351,7 @@ objfile(char *file, char *pkg)
 		Bseek(f, 0L, 0);
 		ldobj(f, pkg, l, file, FileObj);
 		Bterm(f);
+		free(pkg);
 		return;
 	}
 	
@@ -411,6 +413,7 @@ objfile(char *file, char *pkg)
 
 out:
 	Bterm(f);
+	free(pkg);
 }
 
 void
@@ -438,14 +441,17 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
 	magic = c1<<24 | c2<<16 | c3<<8 | c4;
 	if(magic == 0x7f454c46) {	// \x7F E L F
 		ldelf(f, pkg, len, pn);
+		free(pn);
 		return;
 	}
 	if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
 		ldmacho(f, pkg, len, pn);
+		free(pn);
 		return;
 	}
 	if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
 		ldpe(f, pkg, len, pn);
+		free(pn);
 		return;
 	}
 
@@ -471,14 +477,36 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
 			return;
 		}
 		diag("%s: not an object file", pn);
+		free(pn);
 		return;
 	}
-	t = smprint("%s %s %s", getgoos(), thestring, getgoversion());
-	if(strcmp(line+10, t) != 0 && !debug['f']) {
+	
+	// First, check that the basic goos, string, and version match.
+	t = smprint("%s %s %s ", goos, thestring, getgoversion());
+	line[n] = ' ';
+	if(strncmp(line+10, t, strlen(t)) != 0 && !debug['f']) {
+		line[n] = '\0';
 		diag("%s: object is [%s] expected [%s]", pn, line+10, t);
 		free(t);
+		free(pn);
 		return;
 	}
+	
+	// Second, check that longer lines match each other exactly,
+	// so that the Go compiler and write additional information
+	// that must be the same from run to run.
+	line[n] = '\0';
+	if(n-10 > strlen(t)) {
+		if(theline == nil)
+			theline = strdup(line+10);
+		else if(strcmp(theline, line+10) != 0) {
+			line[n] = '\0';
+			diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
+			free(t);
+			free(pn);
+			return;
+		}
+	}
 	free(t);
 	line[n] = '\n';
 
@@ -501,10 +529,12 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
 	Bseek(f, import1, 0);
 
 	ldobj1(f, pkg, eof - Boffset(f), pn);
+	free(pn);
 	return;
 
 eof:
 	diag("truncated object file: %s", pn);
+	free(pn);
 }
 
 static Sym*
@@ -884,18 +914,26 @@ unmal(void *v, uint32 n)
  * Convert raw string to the prefix that will be used in the symbol table.
  * Invalid bytes turn into %xx.	 Right now the only bytes that need
  * escaping are %, ., and ", but we escape all control characters too.
+ *
+ * Must be same as ../gc/subr.c:/^pathtoprefix.
  */
 static char*
 pathtoprefix(char *s)
 {
 	static char hex[] = "0123456789abcdef";
-	char *p, *r, *w;
+	char *p, *r, *w, *l;
 	int n;
 
+	// find first character past the last slash, if any.
+	l = s;
+	for(r=s; *r; r++)
+		if(*r == '/')
+			l = r+1;
+
 	// check for chars that need escaping
 	n = 0;
 	for(r=s; *r; r++)
-		if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"')
+		if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f)
 			n++;
 
 	// quick exit
@@ -905,7 +943,7 @@ pathtoprefix(char *s)
 	// escape
 	p = mal((r-s)+1+2*n);
 	for(r=s, w=p; *r; r++) {
-		if(*r <= ' ' || *r == '.' || *r == '%' || *r == '"') {
+		if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f) {
 			*w++ = '%';
 			*w++ = hex[(*r>>4)&0xF];
 			*w++ = hex[*r&0xF];
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index d13eea3..bbaa52d 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -125,10 +125,12 @@ EXTERN	int32	nsymbol;
 EXTERN	char*	thestring;
 EXTERN	int	ndynexp;
 EXTERN	int	havedynamic;
+EXTERN	int	iscgo;
 
 EXTERN	Segment	segtext;
 EXTERN	Segment	segdata;
 EXTERN	Segment	segsym;
+EXTERN	Segment segdwarf;
 
 void	addlib(char *src, char *obj);
 void	addlibpath(char *srcref, char *objref, char *file, char *pkg);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 70133d6..6781c25 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -413,9 +413,9 @@ asmbmacho(void)
 
 		// must match domacholink below
 		s1 = lookup(".dynsym", 0);
-		s2 = lookup(".dynstr", 0);
-		s3 = lookup(".linkedit.plt", 0);
-		s4 = lookup(".linkedit.got", 0);
+		s2 = lookup(".linkedit.plt", 0);
+		s3 = lookup(".linkedit.got", 0);
+		s4 = lookup(".dynstr", 0);
 
 		ms = newMachoSeg("__LINKEDIT", 0);
 		ms->vaddr = va+v+rnd(segdata.len, INITRND);
@@ -428,8 +428,8 @@ asmbmacho(void)
 		ml = newMachoLoad(2, 4);	/* LC_SYMTAB */
 		ml->data[0] = linkoff;	/* symoff */
 		ml->data[1] = s1->size / (macho64 ? 16 : 12);	/* nsyms */
-		ml->data[2] = linkoff + s1->size;	/* stroff */
-		ml->data[3] = s2->size;	/* strsize */
+		ml->data[2] = linkoff + s1->size + s2->size + s3->size;	/* stroff */
+		ml->data[3] = s4->size;	/* strsize */
 
 		ml = newMachoLoad(11, 18);	/* LC_DYSYMTAB */
 		ml->data[0] = 0;	/* ilocalsym */
@@ -444,8 +444,8 @@ asmbmacho(void)
 		ml->data[9] = 0;	/* nmodtab */
 		ml->data[10] = 0;	/* extrefsymoff */
 		ml->data[11] = 0;	/* nextrefsyms */
-		ml->data[12] = linkoff + s1->size + s2->size;	/* indirectsymoff */
-		ml->data[13] = (s3->size + s4->size) / 4;	/* nindirectsyms */
+		ml->data[12] = linkoff + s1->size;	/* indirectsymoff */
+		ml->data[13] = (s2->size + s3->size) / 4;	/* nindirectsyms */
 		ml->data[14] = 0;	/* extreloff */
 		ml->data[15] = 0;	/* nextrel */
 		ml->data[16] = 0;	/* locreloff */
@@ -495,17 +495,34 @@ domacholink(void)
 	// write data that will be linkedit section
 	s1 = lookup(".dynsym", 0);
 	relocsym(s1);
-	s2 = lookup(".dynstr", 0);
-	s3 = lookup(".linkedit.plt", 0);
-	s4 = lookup(".linkedit.got", 0);
-
-	while(s2->size%4)
-		adduint8(s2, 0);
+	s2 = lookup(".linkedit.plt", 0);
+	s3 = lookup(".linkedit.got", 0);
+	s4 = lookup(".dynstr", 0);
+
+	// Force the linkedit section to end on a 16-byte
+	// boundary.  This allows pure (non-cgo) Go binaries
+	// to be code signed correctly.
+	//
+	// Apple's codesign_allocate (a helper utility for
+	// the codesign utility) can do this fine itself if
+	// it is run on a dynamic Mach-O binary.  However,
+	// when it is run on a pure (non-cgo) Go binary, where
+	// the linkedit section is mostly empty, it fails to
+	// account for the extra padding that it itself adds
+	// when adding the LC_CODE_SIGNATURE load command
+	// (which must be aligned on a 16-byte boundary).
+	//
+	// By forcing the linkedit section to end on a 16-byte
+	// boundary, codesign_allocate will not need to apply
+	// any alignment padding itself, working around the
+	// issue.
+	while(s4->size%16)
+		adduint8(s4, 0);
 	
 	size = s1->size + s2->size + s3->size + s4->size;
 
 	if(size > 0) {
-		linkoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND);
+		linkoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND) + rnd(segdwarf.filelen, INITRND);
 		cseek(linkoff);
 
 		cwrite(s1->p, s1->size);
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index df6c959..1d70b48 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -620,7 +620,7 @@ asmbpe(void)
 		set(Magic, 0x10b);	// PE32
 		oh.BaseOfData = d->VirtualAddress;
 	}
-	set(MajorLinkerVersion, 1);
+	set(MajorLinkerVersion, 3);
 	set(MinorLinkerVersion, 0);
 	set(SizeOfCode, t->SizeOfRawData);
 	set(SizeOfInitializedData, d->SizeOfRawData);
@@ -650,8 +650,21 @@ asmbpe(void)
 	// Commit size must be strictly less than reserve
 	// size otherwise reserve will be rounded up to a
 	// larger size, as verified with VMMap.
-	set(SizeOfStackReserve, 0x00010000);
-	set(SizeOfStackCommit, 0x0000ffff);
+
+	// Go code would be OK with 64k stacks, but we need larger stacks for cgo.
+	// That default stack reserve size affects only the main thread,
+	// for other threads we specify stack size in runtime explicitly
+	// (runtime knows whether cgo is enabled or not).
+	// If you change stack reserve sizes here,
+	// change them in runtime/cgo/windows_386/amd64.c as well.
+	if(!iscgo) {
+		set(SizeOfStackReserve, 0x00010000);
+		set(SizeOfStackCommit, 0x0000ffff);
+	} else {
+		set(SizeOfStackReserve, pe64 ? 0x00200000 : 0x00100000);
+		// account for 2 guard pages
+		set(SizeOfStackCommit, (pe64 ? 0x00200000 : 0x00100000) - 0x2000);
+	}
 	set(SizeOfHeapReserve, 0x00100000);
 	set(SizeOfHeapCommit, 0x00001000);
 	set(NumberOfRvaAndSizes, 16);
diff --git a/src/cmd/prof/Makefile b/src/cmd/prof/Makefile
index 6cefceb..292a648 100644
--- a/src/cmd/prof/Makefile
+++ b/src/cmd/prof/Makefile
@@ -25,6 +25,7 @@ endif
 install: install-$(NAME) install-pprof
 install-linux: install-default
 install-freebsd: install-default
+install-netbsd: install-default
 install-openbsd: install-default
 install-windows: install-default
 
diff --git a/src/cmd/prof/gopprof b/src/cmd/prof/gopprof
index 83438b7..49052ac 100755
--- a/src/cmd/prof/gopprof
+++ b/src/cmd/prof/gopprof
@@ -2615,7 +2615,6 @@ sub RemoveUninterestingFrames {
                       'mal',
                       'runtime.new',
                       'makeslice1',
-                      'runtime.gostringsize',
                       'runtime.malloc',
                       'unsafe.New',
                       'runtime.mallocgc',
diff --git a/src/env.bash b/src/env.bash
index de446bf..9f9f039 100644
--- a/src/env.bash
+++ b/src/env.bash
@@ -3,6 +3,10 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
+# Set to false if something breaks, to revert back to Makefiles.
+# TODO: This variable will go away when the Makefiles do.
+USE_GO_TOOL=${USE_GO_TOOL:-true}
+
 # If set to a Windows-style path convert to an MSYS-Unix 
 # one using the built-in shell commands.   
 if [[ "$GOROOT" == *:* ]]; then
@@ -59,6 +63,7 @@ PROGS="
 	gcc
 	grep
 	ls
+	$MAKE
 	mkdir
 	mv
 	pwd
@@ -95,7 +100,7 @@ set +o noclobber
 
 # Tried to use . <($MAKE ...) here, but it cannot set environment
 # variables in the version of bash that ships with OS X.  Amazing.
-eval $($MAKE --no-print-directory -f Make.inc go-env | egrep 'GOARCH|GOOS|GOHOSTARCH|GOHOSTOS|GO_ENV')
+eval $($MAKE --no-print-directory -f Make.inc go-env | egrep 'GOARCH|GOOS|GOHOSTARCH|GOHOSTOS|GO_ENV|CGO_ENABLED')
 
 # Shell doesn't tell us whether make succeeded,
 # so Make.inc generates a fake variable name.
diff --git a/src/lib9/Makefile b/src/lib9/Makefile
index 28c97c9..31f22c4 100644
--- a/src/lib9/Makefile
+++ b/src/lib9/Makefile
@@ -57,6 +57,7 @@ LIB9OFILES=\
 	atoi.$O\
 	cleanname.$O\
 	create.$O\
+	ctime.$O\
 	dirfstat.$O\
 	dirfwstat.$O\
 	dirstat.$O\
diff --git a/src/lib9/ctime.c b/src/lib9/ctime.c
new file mode 100644
index 0000000..1bc29fb
--- /dev/null
+++ b/src/lib9/ctime.c
@@ -0,0 +1,28 @@
+// Copyright 2011 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.
+
+#define NOPLAN9DEFINES
+#include <u.h>
+#include <libc.h>
+
+char*
+p9ctime(long t)
+{
+	static char buf[100];
+	time_t tt;
+	struct tm *tm;
+	
+	tt = t;
+	tm = localtime(&tt);
+	snprint(buf, sizeof buf, "%3.3s %3.3s %02d %02d:%02d:%02d %3.3s %d\n",
+		"SunMonTueWedThuFriSat"+(tm->tm_wday*3),
+		"JanFebMarAprMayJunJulAugSepOctNovDec"+(tm->tm_mon*3),
+		tm->tm_mday,
+		tm->tm_hour,
+		tm->tm_min,
+		tm->tm_sec,
+		"XXX",  // tm_zone is unavailable on windows, and no one cares
+		tm->tm_year + 1900);
+	return buf;
+}
diff --git a/src/lib9/fmt/fmtprint.c b/src/lib9/fmt/fmtprint.c
index 8a29e6f..6848ab4 100644
--- a/src/lib9/fmt/fmtprint.c
+++ b/src/lib9/fmt/fmtprint.c
@@ -21,31 +21,19 @@
 #include "fmtdef.h"
 
 /*
- * format a string into the output buffer
- * designed for formats which themselves call fmt,
- * but ignore any width flags
+ * Format a string into the output buffer.
+ * Designed for formats which themselves call fmt.
+ * Flags, precision and width are preserved.
  */
 int
 fmtprint(Fmt *f, char *fmt, ...)
 {
-	va_list va;
 	int n;
+	va_list va;
 
-	f->flags = 0;
-	f->width = 0;
-	f->prec = 0;
-	VA_COPY(va, f->args);
-	VA_END(f->args);
-	va_start(f->args, fmt);
-	n = dofmt(f, fmt);
-	va_end(f->args);
-	f->flags = 0;
-	f->width = 0;
-	f->prec = 0;
-	VA_COPY(f->args,va);
-	VA_END(va);
-	if(n >= 0)
-		return 0;
+	va_start(va, fmt);
+	n = fmtvprint(f, fmt, va);
+	va_end(va);
 	return n;
 }
 
diff --git a/src/lib9/fmt/fmtvprint.c b/src/lib9/fmt/fmtvprint.c
index 6acd37a..f18d27b 100644
--- a/src/lib9/fmt/fmtvprint.c
+++ b/src/lib9/fmt/fmtvprint.c
@@ -22,31 +22,31 @@
 
 
 /*
- * format a string into the output buffer
- * designed for formats which themselves call fmt,
- * but ignore any width flags
+ * Format a string into the output buffer.
+ * Designed for formats which themselves call fmt.
+ * Flags, precision and width are preserved.
  */
 int
 fmtvprint(Fmt *f, char *fmt, va_list args)
 {
 	va_list va;
-	int n;
+	int n, w, p;
+	unsigned long fl;
 
-	f->flags = 0;
-	f->width = 0;
-	f->prec = 0;
-	VA_COPY(va,f->args);
+	w = f->width;
+	p = f->prec;
+	fl = f->flags;
+	VA_COPY(va, f->args);
 	VA_END(f->args);
-	VA_COPY(f->args,args);
+	VA_COPY(f->args, args);
 	n = dofmt(f, fmt);
-	f->flags = 0;
-	f->width = 0;
-	f->prec = 0;
 	VA_END(f->args);
-	VA_COPY(f->args,va);
+	VA_COPY(f->args, va);
 	VA_END(va);
+	f->width = w;
+	f->prec = p;
+	f->flags = fl;
 	if(n >= 0)
 		return 0;
 	return n;
 }
-
diff --git a/src/libmach/5db.c b/src/libmach/5db.c
index aea391e..ae71dd9 100644
--- a/src/libmach/5db.c
+++ b/src/libmach/5db.c
@@ -307,7 +307,7 @@ gsymoff(char *buf, int n, long v, int space)
 	if (!delta)
 		return snprint(buf, n, "%s", s.name);
 	if (s.type != 't' && s.type != 'T')
-		return snprint(buf, n, "%s+%lux", s.name, v-s.value);
+		return snprint(buf, n, "%s+%llux", s.name, v-s.value);
 	else
 		return snprint(buf, n, "#%lux", v);
 }
diff --git a/src/libmach/8db.c b/src/libmach/8db.c
index 5b3de69..a5d147a 100644
--- a/src/libmach/8db.c
+++ b/src/libmach/8db.c
@@ -125,7 +125,7 @@ i386excep(Map *map, Rgetter rget)
 			if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
 				return "breakpoint";
 		}
-		snprint(buf, sizeof(buf), "exception %ld", c);
+		snprint(buf, sizeof(buf), "exception %d", c);
 		return buf;
 	} else
 		return excname[c];
@@ -1971,7 +1971,7 @@ plocal(Instr *ip)
 
 	offset = ip->disp;
 	if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) {
-		bprint(ip, "%lux(SP)", offset);
+		bprint(ip, "%ux(SP)", offset);
 		return;
 	}
 
@@ -1987,7 +1987,7 @@ plocal(Instr *ip)
 		bprint(ip, "%s+", s.name);
 	else
 		offset = ip->disp;
-	bprint(ip, "%lux%s", offset, reg);
+	bprint(ip, "%ux%s", offset, reg);
 }
 
 static int
@@ -2061,7 +2061,7 @@ immediate(Instr *ip, vlong val)
 			w = -w;
 		if (issymref(ip, &s, w, val)) {
 			if (w)
-				bprint(ip, "%s+%#lux(SB)", s.name, w);
+				bprint(ip, "%s+%#ux(SB)", s.name, w);
 			else
 				bprint(ip, "%s(SB)", s.name);
 			return;
@@ -2104,7 +2104,7 @@ pea(Instr *ip)
 		if (ip->base < 0)
 			immediate(ip, ip->disp);
 		else {
-			bprint(ip, "%lux", ip->disp);
+			bprint(ip, "%ux", ip->disp);
 			if(ip->rip)
 				bprint(ip, "(RIP)");
 			bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
@@ -2197,7 +2197,7 @@ prinstr(Instr *ip, char *fmt)
 				bprint(ip, "CBW");
 			break;
 		case 'd':
-			bprint(ip,"%ux:%lux",ip->seg,ip->disp);
+			bprint(ip,"%ux:%ux", ip->seg, ip->disp);
 			break;
 		case 'm':
 			if (ip->mod == 3 && ip->osize != 'B') {
diff --git a/src/libmach/Makefile b/src/libmach/Makefile
index 2a53749..7473204 100644
--- a/src/libmach/Makefile
+++ b/src/libmach/Makefile
@@ -49,13 +49,13 @@ OFILES=\
 	6obj.$O\
 	8obj.$O\
 
-ifneq ($(GOHOSTOS),windows)
+ifneq ($(GOHOSTOS),)
 OFILES+=\
-	$(shell uname | tr A-Z a-z).$O\
+	$(GOHOSTOS).$O\
 
 else
 OFILES+=\
-	windows.$O\
+	$(shell uname | tr A-Z a-z).$O\
 
 endif
 
diff --git a/src/libmach/executable.c b/src/libmach/executable.c
index 9d45323..3db3e7d 100644
--- a/src/libmach/executable.c
+++ b/src/libmach/executable.c
@@ -677,7 +677,7 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
 	uint32 (*swal)(uint32);
 	ushort (*swab)(ushort);
 	Ehdr64 *ep;
-	Phdr64 *ph;
+	Phdr64 *ph, *pph;
 	Shdr64 *sh;
 	int i, it, id, is, phsz, shsz;
 
@@ -797,7 +797,8 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp)
 	}
 
 	settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
-	setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz);
+	pph = ph + id;
+	setdata(fp, pph->vaddr, pph->filesz, pph->offset, pph->memsz - pph->filesz);
 	if(is != -1)
 		setsym(fp, ph[is].offset, ph[is].filesz, 0, 0, 0, ph[is].memsz);
 	else if(sh != 0){
@@ -1049,7 +1050,6 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
 	mp->sizeofcmds = swal(mp->sizeofcmds);
 	mp->flags = swal(mp->flags);
 	mp->reserved = swal(mp->reserved);
-	hdrsize = 0;
 
 	switch(mp->magic) {
 	case 0xFEEDFACE:	// 32-bit mach
@@ -1104,7 +1104,9 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
 	datava = 0;
 	symtab = 0;
 	pclntab = 0;
-	textsize = datasize = bsssize = 0;
+	textsize = 0;
+	datasize = 0;
+	bsssize = 0;
 	for (i = 0; i < mp->ncmds; i++) {
 		MachCmd *c;
 
@@ -1379,7 +1381,8 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
 	}
 
 	seek(fd, start+sizeof(magic)+sizeof(fh)+leswab(fh.SizeOfOptionalHeader), 0);
-	fp->txtaddr = fp->dataddr = 0;
+	fp->txtaddr = 0;
+	fp->dataddr = 0;
 	for (i=0; i<leswab(fh.NumberOfSections); i++) {
 		if (readn(fd, &sh, sizeof(sh)) != sizeof(sh)) {
 			werrstr("could not read Section Header %d", i+1);
@@ -1398,7 +1401,7 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
 	seek(fd, leswal(fh.PointerToSymbolTable), 0);
 	symtab = esymtab = 0;
 	for (i=0; i<leswal(fh.NumberOfSymbols); i++) {
-		if (readn(fd, &sym, sizeof(sym)) != sizeof(sym)) {
+		if (readn(fd, sym, sizeof(sym)) != sizeof(sym)) {
 			werrstr("crippled COFF symbol %d", i);
 			return 0;
 		}
@@ -1452,7 +1455,6 @@ setsym(Fhdr *fp, vlong symoff, int32 symsz, vlong sppcoff, int32 sppcsz, vlong l
 	fp->lnpcsz = lnpcsz;
 }
 
-
 static uvlong
 _round(uvlong a, uint32 b)
 {
diff --git a/src/libmach/machdata.c b/src/libmach/machdata.c
index 425a921..66c19f9 100644
--- a/src/libmach/machdata.c
+++ b/src/libmach/machdata.c
@@ -113,7 +113,7 @@ symoff(char *buf, int n, uvlong v, int space)
 	if (s.type != 't' && s.type != 'T' && delta >= 4096)
 		return snprint(buf, n, "%llux", v);
 	else if (delta)
-		return snprint(buf, n, "%s+%#lux", s.name, delta);
+		return snprint(buf, n, "%s+%#ux", s.name, delta);
 	else
 		return snprint(buf, n, "%s", s.name);
 }
@@ -139,7 +139,7 @@ fpformat(Map *map, Reglist *rp, char *buf, int n, int modif)
 	case 'X':
 		if (get4(map, rp->roffs, &r) < 0)
 			return -1;
-		snprint(buf, n, "%lux", r);
+		snprint(buf, n, "%ux", r);
 		break;
 	case 'F':	/* first reg of double reg pair */
 		if (modif == 'F')
@@ -219,12 +219,12 @@ ieeedftos(char *buf, int n, uint32 h, uint32 l)
 		return snprint(buf, n, "0.");
 	exp = (h>>20) & ((1L<<11)-1L);
 	if(exp == 0)
-		return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
+		return snprint(buf, n, "DeN(%.8ux%.8ux)", h, l);
 	if(exp == ((1L<<11)-1L)){
 		if(l==0 && (h&((1L<<20)-1L)) == 0)
 			return snprint(buf, n, "Inf");
 		else
-			return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
+			return snprint(buf, n, "NaN(%.8ux%.8ux)", h&((1<<20)-1), l);
 	}
 	exp -= (1L<<10) - 2L;
 	fr = l & ((1L<<16)-1L);
@@ -256,7 +256,7 @@ ieeesftos(char *buf, int n, uint32 h)
 		return snprint(buf, n, "0.");
 	exp = (h>>23) & ((1L<<8)-1L);
 	if(exp == 0)
-		return snprint(buf, n, "DeN(%.8lux)", h);
+		return snprint(buf, n, "DeN(%.8ux)", h);
 	if(exp == ((1L<<8)-1L)){
 		if((h&((1L<<23)-1L)) == 0)
 			return snprint(buf, n, "Inf");
diff --git a/src/libmach/netbsd.c b/src/libmach/netbsd.c
new file mode 100644
index 0000000..03e08d9
--- /dev/null
+++ b/src/libmach/netbsd.c
@@ -0,0 +1,46 @@
+// This is stubbed out for the moment. Will revisit when the time comes.
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mach.h>
+
+int
+ctlproc(int pid, char *msg)
+{
+	sysfatal("ctlproc unimplemented in NetBSD");
+	return -1;
+}
+
+char*
+proctextfile(int pid)
+{
+	sysfatal("proctextfile unimplemented in NetBSD");
+	return nil;
+}
+
+char*
+procstatus(int pid)
+{
+	sysfatal("procstatus unimplemented in NetBSD");
+	return nil;
+}
+
+Map*
+attachproc(int pid, Fhdr *fp)
+{
+	sysfatal("attachproc unimplemented in NetBSD");
+	return nil;
+}
+
+void
+detachproc(Map *m)
+{
+	sysfatal("detachproc unimplemented in NetBSD");
+}
+
+int
+procthreadpids(int pid, int *p, int np)
+{
+	sysfatal("procthreadpids unimplemented in NetBSD");
+	return -1;
+}
diff --git a/src/libmach/sym.c b/src/libmach/sym.c
index 5e4fdd8..1512d7a 100644
--- a/src/libmach/sym.c
+++ b/src/libmach/sym.c
@@ -124,7 +124,7 @@ syminit(int fd, Fhdr *fp)
 		/* minimum symbol record size = 4+1+2 bytes */
 	symbols = malloc((fp->symsz/(4+1+2)+1)*sizeof(Sym));
 	if(symbols == 0) {
-		werrstr("can't malloc %ld bytes", fp->symsz);
+		werrstr("can't malloc %d bytes", fp->symsz);
 		return -1;
 	}
 	Binit(&b, fd, OREAD);
@@ -203,11 +203,11 @@ syminit(int fd, Fhdr *fp)
 		}
 	}
 	if (debug)
-		print("NG: %ld NT: %d NF: %d\n", nglob, ntxt, fmaxi);
+		print("NG: %d NT: %d NF: %d\n", nglob, ntxt, fmaxi);
 	if (fp->sppcsz) {			/* pc-sp offset table */
 		spoff = (uchar *)malloc(fp->sppcsz);
 		if(spoff == 0) {
-			werrstr("can't malloc %ld bytes", fp->sppcsz);
+			werrstr("can't malloc %d bytes", fp->sppcsz);
 			return -1;
 		}
 		Bseek(&b, fp->sppcoff, 0);
@@ -220,7 +220,7 @@ syminit(int fd, Fhdr *fp)
 	if (fp->lnpcsz) {			/* pc-line number table */
 		pcline = (uchar *)malloc(fp->lnpcsz);
 		if(pcline == 0) {
-			werrstr("can't malloc %ld bytes", fp->lnpcsz);
+			werrstr("can't malloc %d bytes", fp->lnpcsz);
 			return -1;
 		}
 		Bseek(&b, fp->lnpcoff, 0);
@@ -280,12 +280,12 @@ decodename(Biobuf *bp, Sym *p)
 		n = Bseek(bp, 0, 1)-o;
 		p->name = malloc(n);
 		if(p->name == 0) {
-			werrstr("can't malloc %ld bytes", n);
+			werrstr("can't malloc %d bytes", n);
 			return -1;
 		}
 		Bseek(bp, -n, 1);
 		if(Bread(bp, p->name, n) != n) {
-			werrstr("can't read %ld bytes of symbol name", n);
+			werrstr("can't read %d bytes of symbol name", n);
 			return -1;
 		}
 	} else {
@@ -297,7 +297,7 @@ decodename(Biobuf *bp, Sym *p)
 		n = Blinelen(bp);
 		p->name = malloc(n);
 		if(p->name == 0) {
-			werrstr("can't malloc %ld bytes", n);
+			werrstr("can't malloc %d bytes", n);
 			return -1;
 		}
 		strcpy(p->name, cp);
@@ -913,7 +913,7 @@ file2pc(char *file, int32 line)
 			break;
 	free(name);
 	if(i >= nfiles) {
-		werrstr("line %ld in file %s not found", line, file);
+		werrstr("line %d in file %s not found", line, file);
 		return ~0;
 	}
 	start = fp->addr;		/* first text addr this file */
@@ -926,10 +926,10 @@ file2pc(char *file, int32 line)
 	 * run the state machine to locate the pc closest to that value.
 	 */
 	if(debug)
-		print("find pc for %ld - between: %llux and %llux\n", line, start, end);
+		print("find pc for %d - between: %llux and %llux\n", line, start, end);
 	pc = line2addr(line, start, end);
 	if(pc == ~0) {
-		werrstr("line %ld not in file %s", line, file);
+		werrstr("line %d not in file %s", line, file);
 		return ~0;
 	}
 	return pc;
@@ -1146,7 +1146,7 @@ fline(char *str, int n, int32 line, Hist *base, Hist **ret)
 	else {
 		k = fileelem(fnames, (uchar*)start->name, str, n);
 		if(k+8 < n)
-			sprint(str+k, ":%ld", line);
+			sprint(str+k, ":%d", line);
 	}
 /**********Remove comments for complete back-trace of include sequence
  *	if(start != base) {
@@ -1404,7 +1404,7 @@ printhist(char *msg, Hist *hp, int count)
 	while(hp->name) {
 		if(count && ++i > count)
 			break;
-		print("%s Line: %lx (%ld)  Offset: %lx (%ld)  Name: ", msg,
+		print("%s Line: %x (%d)  Offset: %x (%d)  Name: ", msg,
 			hp->line, hp->line, hp->offset, hp->offset);
 		for(cp = (uchar *)hp->name+1; (*cp<<8)|cp[1]; cp += 2) {
 			if (cp != (uchar *)hp->name+1)
diff --git a/src/make.bash b/src/make.bash
index 84b9908..34708b5 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -10,7 +10,7 @@ if [ ! -f env.bash ]; then
 fi
 . ./env.bash
 
-if ld --version 2>&1 | grep 'gold.*2\.20' >/dev/null; then
+if ld --version 2>&1 | grep 'gold.* 2\.20' >/dev/null; then
 	echo 'ERROR: Your system has gold 2.20 installed.'
 	echo 'This version is shipped by Ubuntu even though'
 	echo 'it is known not to work on Ubuntu.'
@@ -47,38 +47,71 @@ rm -f "$GOBIN"/gomake
 ) >"$GOBIN"/gomake
 chmod +x "$GOBIN"/gomake
 
-# TODO(brainman): delete this after 01/01/2012.
-rm -f "$GOBIN"/gotest	# remove old bash version of gotest on Windows
-
-if [ -d /selinux -a -f /selinux/booleans/allow_execstack -a -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
-	if ! cat /selinux/booleans/allow_execstack | grep -c '^1 1$' >> /dev/null ; then
-		echo "WARNING: the default SELinux policy on, at least, Fedora 12 breaks "
-		echo "Go. You can enable the features that Go needs via the following "
-		echo "command (as root):"
-		echo "  # setsebool -P allow_execstack 1"
-		echo
-		echo "Note that this affects your system globally! "
-		echo
-		echo "The build will continue in five seconds in case we "
-		echo "misdiagnosed the issue..."
+# on Fedora 16 the selinux filesystem is mounted at /sys/fs/selinux,
+# so loop through the possible selinux mount points
+for se_mount in /selinux /sys/fs/selinux
+do
+	if [ -d $se_mount -a -f $se_mount/booleans/allow_execstack -a -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
+		if ! cat $se_mount/booleans/allow_execstack | grep -c '^1 1$' >> /dev/null ; then
+			echo "WARNING: the default SELinux policy on, at least, Fedora 12 breaks "
+			echo "Go. You can enable the features that Go needs via the following "
+			echo "command (as root):"
+			echo "  # setsebool -P allow_execstack 1"
+			echo
+			echo "Note that this affects your system globally! "
+			echo
+			echo "The build will continue in five seconds in case we "
+			echo "misdiagnosed the issue..."
 
-		sleep 5
+			sleep 5
+		fi
 	fi
-fi
+done
 
+$USE_GO_TOOL ||
 (
 	cd "$GOROOT"/src/pkg;
 	bash deps.bash	# do this here so clean.bash will work in the pkg directory
-)
+) || exit 1
 bash "$GOROOT"/src/clean.bash
 
-# pkg builds libcgo and the Go programs in cmd.
-for i in lib9 libbio libmach cmd pkg
+# pkg builds runtime/cgo and the Go programs in cmd.
+for i in lib9 libbio libmach cmd
 do
 	echo; echo; echo %%%% making $i %%%%; echo
 	gomake -C $i install
 done
 
+echo; echo; echo %%%% making runtime generated files %%%%; echo
+
+(
+	cd "$GOROOT"/src/pkg/runtime
+	./autogen.sh
+	gomake install; gomake clean # copy runtime.h to pkg directory
+) || exit 1
+
+if $USE_GO_TOOL; then
+	echo
+	echo '# Building go_bootstrap command from bootstrap script.'
+	if ! ./buildscript/${GOOS}_$GOARCH.sh; then
+		echo '# Bootstrap script failed.'
+		if [ ! -x "$GOBIN/go" ]; then
+			exit 1
+		fi
+		echo '# Regenerating bootstrap script using pre-existing go binary.'
+		./buildscript.sh
+		./buildscript/${GOOS}_$GOARCH.sh
+	fi
+
+	echo '# Building Go code.'
+	go_bootstrap install -a -v std
+	rm -f "$GOBIN/go_bootstrap"
+
+else
+	echo; echo; echo %%%% making pkg %%%%; echo
+	gomake -C pkg install
+fi
+
 # Print post-install messages.
 # Implemented as a function so that all.bash can repeat the output
 # after run.bash finishes running all the tests.
diff --git a/src/pkg/Makefile b/src/pkg/Makefile
index 85c5031..4638558 100644
--- a/src/pkg/Makefile
+++ b/src/pkg/Makefile
@@ -16,11 +16,8 @@ all: install
 DIRS=\
 	archive/tar\
 	archive/zip\
-	asn1\
-	big\
 	bufio\
 	bytes\
-	cmath\
 	compress/bzip2\
 	compress/flate\
 	compress/gzip\
@@ -29,62 +26,51 @@ DIRS=\
 	container/heap\
 	container/list\
 	container/ring\
-	container/vector\
 	crypto\
 	crypto/aes\
-	crypto/blowfish\
-	crypto/bcrypt\
-	crypto/cast5\
 	crypto/cipher\
 	crypto/des\
 	crypto/dsa\
 	crypto/ecdsa\
 	crypto/elliptic\
 	crypto/hmac\
-	crypto/md4\
 	crypto/md5\
-	crypto/ocsp\
-	crypto/openpgp\
-	crypto/openpgp/armor\
-	crypto/openpgp/elgamal\
-	crypto/openpgp/error\
-	crypto/openpgp/packet\
-	crypto/openpgp/s2k\
 	crypto/rand\
 	crypto/rc4\
-	crypto/ripemd160\
 	crypto/rsa\
 	crypto/sha1\
 	crypto/sha256\
 	crypto/sha512\
 	crypto/subtle\
 	crypto/tls\
-	crypto/twofish\
 	crypto/x509\
 	crypto/x509/pkix\
-	crypto/xtea\
-	csv\
+	database/sql\
+	database/sql/driver\
 	debug/dwarf\
 	debug/macho\
 	debug/elf\
 	debug/gosym\
 	debug/pe\
-	ebnf\
 	encoding/ascii85\
+	encoding/asn1\
 	encoding/base32\
 	encoding/base64\
 	encoding/binary\
-	encoding/git85\
+	encoding/csv\
+	encoding/gob\
 	encoding/hex\
+	encoding/json\
 	encoding/pem\
-	exec\
-	exp/datafmt\
-	exp/gui\
-	exp/gui/x11\
+	encoding/xml\
+	errors\
+	exp/ebnf\
+	exp/ebnflint\
+	exp/gotype\
+	exp/html\
 	exp/norm\
-	exp/regexp\
-	exp/regexp/syntax\
-	exp/template/html\
+	exp/terminal\
+	exp/types\
 	expvar\
 	flag\
 	fmt\
@@ -95,97 +81,91 @@ DIRS=\
 	go/printer\
 	go/scanner\
 	go/token\
-	go/typechecker\
-	go/types\
-	gob\
 	hash\
 	hash/adler32\
 	hash/crc32\
 	hash/crc64\
 	hash/fnv\
 	html\
-	http\
-	http/cgi\
-	http/fcgi\
-	http/pprof\
-	http/httptest\
-	http/spdy\
+	html/template\
 	image\
 	image/bmp\
+	image/color\
 	image/draw\
 	image/gif\
 	image/jpeg\
 	image/png\
 	image/tiff\
-	image/ycbcr\
 	index/suffixarray\
 	io\
 	io/ioutil\
-	json\
 	log\
-	mail\
+	log/syslog\
 	math\
+	math/big\
+	math/cmplx\
+	math/rand\
 	mime\
 	mime/multipart\
 	net\
-	net/dict\
+	net/http\
+	net/http/cgi\
+	net/http/fcgi\
+	net/http/pprof\
+	net/http/httptest\
+	net/http/httputil\
+	net/mail\
+	net/rpc\
+	net/rpc/jsonrpc\
+	net/smtp\
 	net/textproto\
-	netchan\
+	net/url\
+	old/netchan\
+	old/regexp\
 	old/template\
 	os\
+	os/exec\
 	os/signal\
 	os/user\
-	patch\
 	path\
 	path/filepath\
-	rand\
 	reflect\
 	regexp\
-	rpc\
-	rpc/jsonrpc\
+	regexp/syntax\
 	runtime\
 	runtime/cgo\
 	runtime/debug\
 	runtime/pprof\
-	scanner\
-	smtp\
 	sort\
 	strconv\
 	strings\
 	sync\
 	sync/atomic\
 	syscall\
-	syslog\
-	tabwriter\
-	template\
-	template/parse\
 	testing\
 	testing/iotest\
 	testing/quick\
 	testing/script\
+	text/scanner\
+	text/tabwriter\
+	text/template\
+	text/template/parse\
 	time\
-	try\
 	unicode\
-	url\
-	utf16\
-	utf8\
-	websocket\
-	xml\
+	unicode/utf16\
+	unicode/utf8\
 	../cmd/cgo\
-	../cmd/ebnflint\
 	../cmd/godoc\
 	../cmd/gofix\
 	../cmd/gofmt\
 	../cmd/goinstall\
 	../cmd/gotest\
-	../cmd/gotype\
 	../cmd/govet\
 	../cmd/goyacc\
-	../cmd/hgpatch\
 
 ifeq ($(GOOS),linux)
 DIRS+=\
-	os/inotify\
+	exp/inotify\
 
 endif
 
@@ -198,34 +178,25 @@ endif
 
 NOTEST+=\
 	crypto\
-	crypto/openpgp/error\
+	crypto/openpgp/errors\
 	crypto/x509/pkix\
-	exp/gui\
-	exp/gui/x11\
-	go/ast\
+	exp/ebnflint\
 	go/doc\
-	go/token\
 	hash\
-	http/pprof\
-	http/httptest\
 	image/bmp\
 	image/gif\
-	net/dict\
-	rand\
+	net/http/pprof\
+	net/http/httptest\
 	runtime/cgo\
 	syscall\
 	testing\
 	testing/iotest\
-	try\
 	../cmd/cgo\
-	../cmd/ebnflint\
 	../cmd/godoc\
 	../cmd/gotest\
 	../cmd/goyacc\
-	../cmd/hgpatch\
 
 NOBENCH+=\
-	container/vector\
 
 # Disable tests that windows cannot run yet.
 ifeq ($(GOOS),windows)
@@ -239,6 +210,9 @@ TEST=\
 BENCH=\
 	$(filter-out $(NOBENCH),$(TEST))
 
+CRAP:
+	echo $(DIRS)
+
 clean.dirs: $(addsuffix .clean, $(DIRS))
 install.dirs: $(addsuffix .install, $(DIRS))
 nuke.dirs: $(addsuffix .nuke, $(DIRS))
diff --git a/src/pkg/archive/tar/common.go b/src/pkg/archive/tar/common.go
index 6735508..fc7a409 100644
--- a/src/pkg/archive/tar/common.go
+++ b/src/pkg/archive/tar/common.go
@@ -11,41 +11,42 @@
 //   http://www.gnu.org/software/tar/manual/html_node/Standard.html
 package tar
 
+import "time"
+
 const (
 	blockSize = 512
 
 	// Types
-	TypeReg           = '0'    // regular file.
-	TypeRegA          = '\x00' // regular file.
-	TypeLink          = '1'    // hard link.
-	TypeSymlink       = '2'    // symbolic link.
-	TypeChar          = '3'    // character device node.
-	TypeBlock         = '4'    // block device node.
-	TypeDir           = '5'    // directory.
-	TypeFifo          = '6'    // fifo node.
-	TypeCont          = '7'    // reserved.
-	TypeXHeader       = 'x'    // extended header.
-	TypeXGlobalHeader = 'g'    // global extended header.
+	TypeReg           = '0'    // regular file
+	TypeRegA          = '\x00' // regular file
+	TypeLink          = '1'    // hard link
+	TypeSymlink       = '2'    // symbolic link
+	TypeChar          = '3'    // character device node
+	TypeBlock         = '4'    // block device node
+	TypeDir           = '5'    // directory
+	TypeFifo          = '6'    // fifo node
+	TypeCont          = '7'    // reserved
+	TypeXHeader       = 'x'    // extended header
+	TypeXGlobalHeader = 'g'    // global extended header
 )
 
 // A Header represents a single header in a tar archive.
 // Some fields may not be populated.
 type Header struct {
-	Name     string // name of header file entry.
-	Mode     int64  // permission and mode bits.
-	Uid      int    // user id of owner.
-	Gid      int    // group id of owner.
-	Size     int64  // length in bytes.
-	Mtime    int64  // modified time; seconds since epoch.
-	Typeflag byte   // type of header entry.
-	Linkname string // target name of link.
-	Uname    string // user name of owner.
-	Gname    string // group name of owner.
-	Devmajor int64  // major number of character or block device.
-	Devminor int64  // minor number of character or block device.
-	Atime    int64  // access time; seconds since epoch.
-	Ctime    int64  // status change time; seconds since epoch.
-
+	Name       string    // name of header file entry
+	Mode       int64     // permission and mode bits
+	Uid        int       // user id of owner
+	Gid        int       // group id of owner
+	Size       int64     // length in bytes
+	ModTime    time.Time // modified time
+	Typeflag   byte      // type of header entry
+	Linkname   string    // target name of link
+	Uname      string    // user name of owner
+	Gname      string    // group name of owner
+	Devmajor   int64     // major number of character or block device
+	Devminor   int64     // minor number of character or block device
+	AccessTime time.Time // access time
+	ChangeTime time.Time // status change time
 }
 
 var zeroBlock = make([]byte, blockSize)
diff --git a/src/pkg/archive/tar/reader.go b/src/pkg/archive/tar/reader.go
index 45d95c3..755a730 100644
--- a/src/pkg/archive/tar/reader.go
+++ b/src/pkg/archive/tar/reader.go
@@ -9,14 +9,16 @@ package tar
 
 import (
 	"bytes"
+	"errors"
 	"io"
 	"io/ioutil"
 	"os"
 	"strconv"
+	"time"
 )
 
 var (
-	HeaderError = os.NewError("invalid tar header")
+	ErrHeader = errors.New("invalid tar header")
 )
 
 // A Reader provides sequential access to the contents of a tar archive.
@@ -28,7 +30,7 @@ var (
 //	tr := tar.NewReader(r)
 //	for {
 //		hdr, err := tr.Next()
-//		if err == os.EOF {
+//		if err == io.EOF {
 //			// end of tar archive
 //			break
 //		}
@@ -39,7 +41,7 @@ var (
 //	}
 type Reader struct {
 	r   io.Reader
-	err os.Error
+	err error
 	nb  int64 // number of unread bytes for current file entry
 	pad int64 // amount of padding (ignored) after current file entry
 }
@@ -48,7 +50,7 @@ type Reader struct {
 func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
 
 // Next advances to the next entry in the tar archive.
-func (tr *Reader) Next() (*Header, os.Error) {
+func (tr *Reader) Next() (*Header, error) {
 	var hdr *Header
 	if tr.err == nil {
 		tr.skipUnread()
@@ -78,7 +80,7 @@ func (tr *Reader) octal(b []byte) int64 {
 	for len(b) > 0 && (b[len(b)-1] == ' ' || b[len(b)-1] == '\x00') {
 		b = b[0 : len(b)-1]
 	}
-	x, err := strconv.Btoui64(cString(b), 8)
+	x, err := strconv.ParseUint(cString(b), 8, 64)
 	if err != nil {
 		tr.err = err
 	}
@@ -94,7 +96,7 @@ func (tr *Reader) skipUnread() {
 			return
 		}
 	}
-	_, tr.err = io.Copyn(ioutil.Discard, tr.r, nr)
+	_, tr.err = io.CopyN(ioutil.Discard, tr.r, nr)
 }
 
 func (tr *Reader) verifyChecksum(header []byte) bool {
@@ -119,15 +121,15 @@ func (tr *Reader) readHeader() *Header {
 			return nil
 		}
 		if bytes.Equal(header, zeroBlock[0:blockSize]) {
-			tr.err = os.EOF
+			tr.err = io.EOF
 		} else {
-			tr.err = HeaderError // zero block and then non-zero block
+			tr.err = ErrHeader // zero block and then non-zero block
 		}
 		return nil
 	}
 
 	if !tr.verifyChecksum(header) {
-		tr.err = HeaderError
+		tr.err = ErrHeader
 		return nil
 	}
 
@@ -140,7 +142,7 @@ func (tr *Reader) readHeader() *Header {
 	hdr.Uid = int(tr.octal(s.next(8)))
 	hdr.Gid = int(tr.octal(s.next(8)))
 	hdr.Size = tr.octal(s.next(12))
-	hdr.Mtime = tr.octal(s.next(12))
+	hdr.ModTime = time.Unix(tr.octal(s.next(12)), 0)
 	s.next(8) // chksum
 	hdr.Typeflag = s.next(1)[0]
 	hdr.Linkname = cString(s.next(100))
@@ -177,8 +179,8 @@ func (tr *Reader) readHeader() *Header {
 			prefix = cString(s.next(155))
 		case "star":
 			prefix = cString(s.next(131))
-			hdr.Atime = tr.octal(s.next(12))
-			hdr.Ctime = tr.octal(s.next(12))
+			hdr.AccessTime = time.Unix(tr.octal(s.next(12)), 0)
+			hdr.ChangeTime = time.Unix(tr.octal(s.next(12)), 0)
 		}
 		if len(prefix) > 0 {
 			hdr.Name = prefix + "/" + hdr.Name
@@ -186,7 +188,7 @@ func (tr *Reader) readHeader() *Header {
 	}
 
 	if tr.err != nil {
-		tr.err = HeaderError
+		tr.err = ErrHeader
 		return nil
 	}
 
@@ -199,12 +201,12 @@ func (tr *Reader) readHeader() *Header {
 }
 
 // Read reads from the current entry in the tar archive.
-// It returns 0, os.EOF when it reaches the end of that entry,
+// It returns 0, io.EOF when it reaches the end of that entry,
 // until Next is called to advance to the next entry.
-func (tr *Reader) Read(b []byte) (n int, err os.Error) {
+func (tr *Reader) Read(b []byte) (n int, err error) {
 	if tr.nb == 0 {
 		// file consumed
-		return 0, os.EOF
+		return 0, io.EOF
 	}
 
 	if int64(len(b)) > tr.nb {
@@ -213,7 +215,7 @@ func (tr *Reader) Read(b []byte) (n int, err os.Error) {
 	n, err = tr.r.Read(b)
 	tr.nb -= int64(n)
 
-	if err == os.EOF && tr.nb > 0 {
+	if err == io.EOF && tr.nb > 0 {
 		err = io.ErrUnexpectedEOF
 	}
 	tr.err = err
diff --git a/src/pkg/archive/tar/reader_test.go b/src/pkg/archive/tar/reader_test.go
index f473c90..0a8646c 100644
--- a/src/pkg/archive/tar/reader_test.go
+++ b/src/pkg/archive/tar/reader_test.go
@@ -10,8 +10,8 @@ import (
 	"fmt"
 	"io"
 	"os"
-	"reflect"
 	"testing"
+	"time"
 )
 
 type untarTest struct {
@@ -23,24 +23,24 @@ type untarTest struct {
 var gnuTarTest = &untarTest{
 	file: "testdata/gnu.tar",
 	headers: []*Header{
-		&Header{
+		{
 			Name:     "small.txt",
 			Mode:     0640,
 			Uid:      73025,
 			Gid:      5000,
 			Size:     5,
-			Mtime:    1244428340,
+			ModTime:  time.Unix(1244428340, 0),
 			Typeflag: '0',
 			Uname:    "dsymonds",
 			Gname:    "eng",
 		},
-		&Header{
+		{
 			Name:     "small2.txt",
 			Mode:     0640,
 			Uid:      73025,
 			Gid:      5000,
 			Size:     11,
-			Mtime:    1244436044,
+			ModTime:  time.Unix(1244436044, 0),
 			Typeflag: '0',
 			Uname:    "dsymonds",
 			Gname:    "eng",
@@ -54,56 +54,56 @@ var gnuTarTest = &untarTest{
 
 var untarTests = []*untarTest{
 	gnuTarTest,
-	&untarTest{
+	{
 		file: "testdata/star.tar",
 		headers: []*Header{
-			&Header{
-				Name:     "small.txt",
-				Mode:     0640,
-				Uid:      73025,
-				Gid:      5000,
-				Size:     5,
-				Mtime:    1244592783,
-				Typeflag: '0',
-				Uname:    "dsymonds",
-				Gname:    "eng",
-				Atime:    1244592783,
-				Ctime:    1244592783,
+			{
+				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),
 			},
-			&Header{
-				Name:     "small2.txt",
-				Mode:     0640,
-				Uid:      73025,
-				Gid:      5000,
-				Size:     11,
-				Mtime:    1244592783,
-				Typeflag: '0',
-				Uname:    "dsymonds",
-				Gname:    "eng",
-				Atime:    1244592783,
-				Ctime:    1244592783,
+			{
+				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),
 			},
 		},
 	},
-	&untarTest{
+	{
 		file: "testdata/v7.tar",
 		headers: []*Header{
-			&Header{
+			{
 				Name:     "small.txt",
 				Mode:     0444,
 				Uid:      73025,
 				Gid:      5000,
 				Size:     5,
-				Mtime:    1244593104,
+				ModTime:  time.Unix(1244593104, 0),
 				Typeflag: '\x00',
 			},
-			&Header{
+			{
 				Name:     "small2.txt",
 				Mode:     0444,
 				Uid:      73025,
 				Gid:      5000,
 				Size:     11,
-				Mtime:    1244593104,
+				ModTime:  time.Unix(1244593104, 0),
 				Typeflag: '\x00',
 			},
 		},
@@ -126,13 +126,13 @@ testLoop:
 				f.Close()
 				continue testLoop
 			}
-			if !reflect.DeepEqual(hdr, header) {
+			if *hdr != *header {
 				t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v",
 					i, j, *hdr, *header)
 			}
 		}
 		hdr, err := tr.Next()
-		if err == os.EOF {
+		if err == io.EOF {
 			break
 		}
 		if hdr != nil || err != nil {
@@ -195,12 +195,12 @@ func TestIncrementalRead(t *testing.T) {
 	// loop over all files
 	for ; ; nread++ {
 		hdr, err := tr.Next()
-		if hdr == nil || err == os.EOF {
+		if hdr == nil || err == io.EOF {
 			break
 		}
 
 		// check the header
-		if !reflect.DeepEqual(hdr, headers[nread]) {
+		if *hdr != *headers[nread] {
 			t.Errorf("Incorrect header:\nhave %+v\nwant %+v",
 				*hdr, headers[nread])
 		}
@@ -211,7 +211,7 @@ func TestIncrementalRead(t *testing.T) {
 		rdbuf := make([]uint8, 8)
 		for {
 			nr, err := tr.Read(rdbuf)
-			if err == os.EOF {
+			if err == io.EOF {
 				break
 			}
 			if err != nil {
@@ -221,7 +221,7 @@ func TestIncrementalRead(t *testing.T) {
 			h.Write(rdbuf[0:nr])
 		}
 		// verify checksum
-		have := fmt.Sprintf("%x", h.Sum())
+		have := fmt.Sprintf("%x", h.Sum(nil))
 		want := cksums[nread]
 		if want != have {
 			t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want)
@@ -240,31 +240,20 @@ func TestNonSeekable(t *testing.T) {
 	}
 	defer f.Close()
 
-	// pipe the data in
-	r, w, err := os.Pipe()
-	if err != nil {
-		t.Fatalf("Unexpected error %s", err)
+	type readerOnly struct {
+		io.Reader
 	}
-	go func() {
-		rdbuf := make([]uint8, 1<<16)
-		for {
-			nr, err := f.Read(rdbuf)
-			w.Write(rdbuf[0:nr])
-			if err == os.EOF {
-				break
-			}
-		}
-		w.Close()
-	}()
-
-	tr := NewReader(r)
+	tr := NewReader(readerOnly{f})
 	nread := 0
 
 	for ; ; nread++ {
-		hdr, err := tr.Next()
-		if hdr == nil || err == os.EOF {
+		_, err := tr.Next()
+		if err == io.EOF {
 			break
 		}
+		if err != nil {
+			t.Fatalf("Unexpected error: %v", err)
+		}
 	}
 
 	if nread != len(test.headers) {
diff --git a/src/pkg/archive/tar/writer.go b/src/pkg/archive/tar/writer.go
index c6ce224..d35726b 100644
--- a/src/pkg/archive/tar/writer.go
+++ b/src/pkg/archive/tar/writer.go
@@ -8,15 +8,15 @@ package tar
 // - catch more errors (no first header, write after close, etc.)
 
 import (
+	"errors"
 	"io"
-	"os"
 	"strconv"
 )
 
 var (
-	ErrWriteTooLong    = os.NewError("write too long")
-	ErrFieldTooLong    = os.NewError("header field too long")
-	ErrWriteAfterClose = os.NewError("write after close")
+	ErrWriteTooLong    = errors.New("write too long")
+	ErrFieldTooLong    = errors.New("header field too long")
+	ErrWriteAfterClose = errors.New("write after close")
 )
 
 // A Writer provides sequential writing of a tar archive in POSIX.1 format.
@@ -36,7 +36,7 @@ var (
 //	tw.Close()
 type Writer struct {
 	w          io.Writer
-	err        os.Error
+	err        error
 	nb         int64 // number of unwritten bytes for current file entry
 	pad        int64 // amount of padding to write after current file entry
 	closed     bool
@@ -47,7 +47,7 @@ type Writer struct {
 func NewWriter(w io.Writer) *Writer { return &Writer{w: w} }
 
 // Flush finishes writing the current file (optional).
-func (tw *Writer) Flush() os.Error {
+func (tw *Writer) Flush() error {
 	n := tw.nb + tw.pad
 	for n > 0 && tw.err == nil {
 		nr := n
@@ -79,7 +79,7 @@ func (tw *Writer) cString(b []byte, s string) {
 
 // Encode x as an octal ASCII string and write it into b with leading zeros.
 func (tw *Writer) octal(b []byte, x int64) {
-	s := strconv.Itob64(x, 8)
+	s := strconv.FormatInt(x, 8)
 	// leading zeros, but leave room for a NUL.
 	for len(s)+1 < len(b) {
 		s = "0" + s
@@ -90,7 +90,7 @@ func (tw *Writer) octal(b []byte, x int64) {
 // Write x into b, either as octal or as binary (GNUtar/star extension).
 func (tw *Writer) numeric(b []byte, x int64) {
 	// Try octal first.
-	s := strconv.Itob64(x, 8)
+	s := strconv.FormatInt(x, 8)
 	if len(s) < len(b) {
 		tw.octal(b, x)
 		return
@@ -107,7 +107,7 @@ func (tw *Writer) numeric(b []byte, x int64) {
 // WriteHeader writes hdr and prepares to accept the file's contents.
 // WriteHeader calls Flush if it is not the first header.
 // Calling after a Close will return ErrWriteAfterClose.
-func (tw *Writer) WriteHeader(hdr *Header) os.Error {
+func (tw *Writer) WriteHeader(hdr *Header) error {
 	if tw.closed {
 		return ErrWriteAfterClose
 	}
@@ -127,19 +127,19 @@ func (tw *Writer) WriteHeader(hdr *Header) os.Error {
 	// TODO(dsymonds): handle names longer than 100 chars
 	copy(s.next(100), []byte(hdr.Name))
 
-	tw.octal(s.next(8), hdr.Mode)          // 100:108
-	tw.numeric(s.next(8), int64(hdr.Uid))  // 108:116
-	tw.numeric(s.next(8), int64(hdr.Gid))  // 116:124
-	tw.numeric(s.next(12), hdr.Size)       // 124:136
-	tw.numeric(s.next(12), hdr.Mtime)      // 136:148
-	s.next(8)                              // chksum (148:156)
-	s.next(1)[0] = hdr.Typeflag            // 156:157
-	tw.cString(s.next(100), hdr.Linkname)  // linkname (157:257)
-	copy(s.next(8), []byte("ustar\x0000")) // 257:265
-	tw.cString(s.next(32), hdr.Uname)      // 265:297
-	tw.cString(s.next(32), hdr.Gname)      // 297:329
-	tw.numeric(s.next(8), hdr.Devmajor)    // 329:337
-	tw.numeric(s.next(8), hdr.Devminor)    // 337:345
+	tw.octal(s.next(8), hdr.Mode)              // 100:108
+	tw.numeric(s.next(8), int64(hdr.Uid))      // 108:116
+	tw.numeric(s.next(8), int64(hdr.Gid))      // 116:124
+	tw.numeric(s.next(12), hdr.Size)           // 124:136
+	tw.numeric(s.next(12), hdr.ModTime.Unix()) // 136:148
+	s.next(8)                                  // chksum (148:156)
+	s.next(1)[0] = hdr.Typeflag                // 156:157
+	tw.cString(s.next(100), hdr.Linkname)      // linkname (157:257)
+	copy(s.next(8), []byte("ustar\x0000"))     // 257:265
+	tw.cString(s.next(32), hdr.Uname)          // 265:297
+	tw.cString(s.next(32), hdr.Gname)          // 297:329
+	tw.numeric(s.next(8), hdr.Devmajor)        // 329:337
+	tw.numeric(s.next(8), hdr.Devminor)        // 337:345
 
 	// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
 	if tw.usedBinary {
@@ -165,7 +165,7 @@ func (tw *Writer) WriteHeader(hdr *Header) os.Error {
 // 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.
-func (tw *Writer) Write(b []byte) (n int, err os.Error) {
+func (tw *Writer) Write(b []byte) (n int, err error) {
 	if tw.closed {
 		err = ErrWriteTooLong
 		return
@@ -187,7 +187,7 @@ func (tw *Writer) Write(b []byte) (n int, err os.Error) {
 
 // Close closes the tar archive, flushing any unwritten
 // data to the underlying writer.
-func (tw *Writer) Close() os.Error {
+func (tw *Writer) Close() error {
 	if tw.err != nil || tw.closed {
 		return tw.err
 	}
diff --git a/src/pkg/archive/tar/writer_test.go b/src/pkg/archive/tar/writer_test.go
index 6cc9386..0b41372 100644
--- a/src/pkg/archive/tar/writer_test.go
+++ b/src/pkg/archive/tar/writer_test.go
@@ -11,6 +11,7 @@ import (
 	"io/ioutil"
 	"testing"
 	"testing/iotest"
+	"time"
 )
 
 type writerTestEntry struct {
@@ -28,45 +29,45 @@ var writerTests = []*writerTest{
 	// 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
-	&writerTest{
+	{
 		file: "testdata/writer.tar",
 		entries: []*writerTestEntry{
-			&writerTestEntry{
+			{
 				header: &Header{
 					Name:     "small.txt",
 					Mode:     0640,
 					Uid:      73025,
 					Gid:      5000,
 					Size:     5,
-					Mtime:    1246508266,
+					ModTime:  time.Unix(1246508266, 0),
 					Typeflag: '0',
 					Uname:    "dsymonds",
 					Gname:    "eng",
 				},
 				contents: "Kilts",
 			},
-			&writerTestEntry{
+			{
 				header: &Header{
 					Name:     "small2.txt",
 					Mode:     0640,
 					Uid:      73025,
 					Gid:      5000,
 					Size:     11,
-					Mtime:    1245217492,
+					ModTime:  time.Unix(1245217492, 0),
 					Typeflag: '0',
 					Uname:    "dsymonds",
 					Gname:    "eng",
 				},
 				contents: "Google.com\n",
 			},
-			&writerTestEntry{
+			{
 				header: &Header{
 					Name:     "link.txt",
 					Mode:     0777,
 					Uid:      1000,
 					Gid:      1000,
 					Size:     0,
-					Mtime:    1314603082,
+					ModTime:  time.Unix(1314603082, 0),
 					Typeflag: '2',
 					Linkname: "small.txt",
 					Uname:    "strings",
@@ -79,17 +80,17 @@ var writerTests = []*writerTest{
 	// 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
-	&writerTest{
+	{
 		file: "testdata/writer-big.tar",
 		entries: []*writerTestEntry{
-			&writerTestEntry{
+			{
 				header: &Header{
 					Name:     "tmp/16gig.txt",
 					Mode:     0640,
 					Uid:      73025,
 					Gid:      5000,
 					Size:     16 << 30,
-					Mtime:    1254699560,
+					ModTime:  time.Unix(1254699560, 0),
 					Typeflag: '0',
 					Uname:    "dsymonds",
 					Gname:    "eng",
diff --git a/src/pkg/archive/zip/reader.go b/src/pkg/archive/zip/reader.go
index f92f929..4dd0f4f 100644
--- a/src/pkg/archive/zip/reader.go
+++ b/src/pkg/archive/zip/reader.go
@@ -7,18 +7,19 @@ package zip
 import (
 	"bufio"
 	"compress/flate"
+	"encoding/binary"
+	"errors"
 	"hash"
 	"hash/crc32"
-	"encoding/binary"
 	"io"
 	"io/ioutil"
 	"os"
 )
 
 var (
-	FormatError       = os.NewError("zip: not a valid zip file")
-	UnsupportedMethod = os.NewError("zip: unsupported compression algorithm")
-	ChecksumError     = os.NewError("zip: checksum error")
+	ErrFormat    = errors.New("zip: not a valid zip file")
+	ErrAlgorithm = errors.New("zip: unsupported compression algorithm")
+	ErrChecksum  = errors.New("zip: checksum error")
 )
 
 type Reader struct {
@@ -44,7 +45,7 @@ func (f *File) hasDataDescriptor() bool {
 }
 
 // OpenReader will open the Zip file specified by name and return a ReadCloser.
-func OpenReader(name string) (*ReadCloser, os.Error) {
+func OpenReader(name string) (*ReadCloser, error) {
 	f, err := os.Open(name)
 	if err != nil {
 		return nil, err
@@ -55,16 +56,17 @@ func OpenReader(name string) (*ReadCloser, os.Error) {
 		return nil, err
 	}
 	r := new(ReadCloser)
-	if err := r.init(f, fi.Size); err != nil {
+	if err := r.init(f, fi.Size()); err != nil {
 		f.Close()
 		return nil, err
 	}
+	r.f = f
 	return r, nil
 }
 
 // NewReader returns a new Reader reading from r, which is assumed to
 // have the given size in bytes.
-func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) {
+func NewReader(r io.ReaderAt, size int64) (*Reader, error) {
 	zr := new(Reader)
 	if err := zr.init(r, size); err != nil {
 		return nil, err
@@ -72,7 +74,7 @@ func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) {
 	return zr, nil
 }
 
-func (z *Reader) init(r io.ReaderAt, size int64) os.Error {
+func (z *Reader) init(r io.ReaderAt, size int64) error {
 	end, err := readDirectoryEnd(r, size)
 	if err != nil {
 		return err
@@ -88,12 +90,12 @@ func (z *Reader) init(r io.ReaderAt, size int64) os.Error {
 
 	// The count of files inside a zip is truncated to fit in a uint16.
 	// Gloss over this by reading headers until we encounter
-	// a bad one, and then only report a FormatError or UnexpectedEOF if
+	// a bad one, and then only report a ErrFormat or UnexpectedEOF if
 	// the file count modulo 65536 is incorrect.
 	for {
 		f := &File{zipr: r, zipsize: size}
 		err = readDirectoryHeader(f, buf)
-		if err == FormatError || err == io.ErrUnexpectedEOF {
+		if err == ErrFormat || err == io.ErrUnexpectedEOF {
 			break
 		}
 		if err != nil {
@@ -110,13 +112,13 @@ func (z *Reader) init(r io.ReaderAt, size int64) os.Error {
 }
 
 // Close closes the Zip file, rendering it unusable for I/O.
-func (rc *ReadCloser) Close() os.Error {
+func (rc *ReadCloser) Close() error {
 	return rc.f.Close()
 }
 
 // Open returns a ReadCloser that provides access to the File's contents.
 // It is safe to Open and Read from files concurrently.
-func (f *File) Open() (rc io.ReadCloser, err os.Error) {
+func (f *File) Open() (rc io.ReadCloser, err error) {
 	bodyOffset, err := f.findBodyOffset()
 	if err != nil {
 		return
@@ -133,7 +135,7 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
 	case Deflate:
 		rc = flate.NewReader(r)
 	default:
-		err = UnsupportedMethod
+		err = ErrAlgorithm
 	}
 	if rc != nil {
 		rc = &checksumReader{rc, crc32.NewIEEE(), f, r}
@@ -148,10 +150,10 @@ type checksumReader struct {
 	zipr io.Reader // for reading the data descriptor
 }
 
-func (r *checksumReader) Read(b []byte) (n int, err os.Error) {
+func (r *checksumReader) Read(b []byte) (n int, err error) {
 	n, err = r.rc.Read(b)
 	r.hash.Write(b[:n])
-	if err != os.EOF {
+	if err != io.EOF {
 		return
 	}
 	if r.f.hasDataDescriptor() {
@@ -160,21 +162,21 @@ func (r *checksumReader) Read(b []byte) (n int, err os.Error) {
 		}
 	}
 	if r.hash.Sum32() != r.f.CRC32 {
-		err = ChecksumError
+		err = ErrChecksum
 	}
 	return
 }
 
-func (r *checksumReader) Close() os.Error { return r.rc.Close() }
+func (r *checksumReader) Close() error { return r.rc.Close() }
 
-func readFileHeader(f *File, r io.Reader) os.Error {
+func readFileHeader(f *File, r io.Reader) error {
 	var b [fileHeaderLen]byte
 	if _, err := io.ReadFull(r, b[:]); err != nil {
 		return err
 	}
 	c := binary.LittleEndian
 	if sig := c.Uint32(b[:4]); sig != fileHeaderSignature {
-		return FormatError
+		return ErrFormat
 	}
 	f.ReaderVersion = c.Uint16(b[4:6])
 	f.Flags = c.Uint16(b[6:8])
@@ -197,7 +199,7 @@ func readFileHeader(f *File, r io.Reader) os.Error {
 
 // findBodyOffset does the minimum work to verify the file has a header
 // and returns the file body offset.
-func (f *File) findBodyOffset() (int64, os.Error) {
+func (f *File) findBodyOffset() (int64, error) {
 	r := io.NewSectionReader(f.zipr, f.headerOffset, f.zipsize-f.headerOffset)
 	var b [fileHeaderLen]byte
 	if _, err := io.ReadFull(r, b[:]); err != nil {
@@ -205,7 +207,7 @@ func (f *File) findBodyOffset() (int64, os.Error) {
 	}
 	c := binary.LittleEndian
 	if sig := c.Uint32(b[:4]); sig != fileHeaderSignature {
-		return 0, FormatError
+		return 0, ErrFormat
 	}
 	filenameLen := int(c.Uint16(b[26:28]))
 	extraLen := int(c.Uint16(b[28:30]))
@@ -214,15 +216,15 @@ func (f *File) findBodyOffset() (int64, os.Error) {
 
 // readDirectoryHeader attempts to read a directory header from r.
 // It returns io.ErrUnexpectedEOF if it cannot read a complete header,
-// and FormatError if it doesn't find a valid header signature.
-func readDirectoryHeader(f *File, r io.Reader) os.Error {
+// and ErrFormat if it doesn't find a valid header signature.
+func readDirectoryHeader(f *File, r io.Reader) error {
 	var b [directoryHeaderLen]byte
 	if _, err := io.ReadFull(r, b[:]); err != nil {
 		return err
 	}
 	c := binary.LittleEndian
 	if sig := c.Uint32(b[:4]); sig != directoryHeaderSignature {
-		return FormatError
+		return ErrFormat
 	}
 	f.CreatorVersion = c.Uint16(b[4:6])
 	f.ReaderVersion = c.Uint16(b[6:8])
@@ -238,7 +240,7 @@ func readDirectoryHeader(f *File, r io.Reader) os.Error {
 	commentLen := int(c.Uint16(b[32:34]))
 	// startDiskNumber := c.Uint16(b[34:36])    // Unused
 	// internalAttributes := c.Uint16(b[36:38]) // Unused
-	// externalAttributes := c.Uint32(b[38:42]) // Unused
+	f.ExternalAttrs = c.Uint32(b[38:42])
 	f.headerOffset = int64(c.Uint32(b[42:46]))
 	d := make([]byte, filenameLen+extraLen+commentLen)
 	if _, err := io.ReadFull(r, d); err != nil {
@@ -250,7 +252,7 @@ func readDirectoryHeader(f *File, r io.Reader) os.Error {
 	return nil
 }
 
-func readDataDescriptor(r io.Reader, f *File) os.Error {
+func readDataDescriptor(r io.Reader, f *File) error {
 	var b [dataDescriptorLen]byte
 	if _, err := io.ReadFull(r, b[:]); err != nil {
 		return err
@@ -262,7 +264,7 @@ func readDataDescriptor(r io.Reader, f *File) os.Error {
 	return nil
 }
 
-func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err os.Error) {
+func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
 	// look for directoryEndSignature in the last 1k, then in the last 65k
 	var b []byte
 	for i, bLen := range []int64{1024, 65 * 1024} {
@@ -270,7 +272,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err os.Erro
 			bLen = size
 		}
 		b = make([]byte, int(bLen))
-		if _, err := r.ReadAt(b, size-bLen); err != nil && err != os.EOF {
+		if _, err := r.ReadAt(b, size-bLen); err != nil && err != io.EOF {
 			return nil, err
 		}
 		if p := findSignatureInBlock(b); p >= 0 {
@@ -278,7 +280,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err os.Erro
 			break
 		}
 		if i == 1 || bLen == size {
-			return nil, FormatError
+			return nil, ErrFormat
 		}
 	}
 
diff --git a/src/pkg/archive/zip/reader_test.go b/src/pkg/archive/zip/reader_test.go
index fd5fed2..9407e35 100644
--- a/src/pkg/archive/zip/reader_test.go
+++ b/src/pkg/archive/zip/reader_test.go
@@ -18,7 +18,7 @@ type ZipTest struct {
 	Name    string
 	Comment string
 	File    []ZipTestFile
-	Error   os.Error // the error that Opening this file should return
+	Error   error // the error that Opening this file should return
 }
 
 type ZipTestFile struct {
@@ -26,6 +26,7 @@ type ZipTestFile struct {
 	Content []byte // if blank, will attempt to compare against File
 	File    string // name of file to compare to (relative to testdata/)
 	Mtime   string // modified time in format "mm-dd-yy hh:mm:ss"
+	Mode    os.FileMode
 }
 
 // Caution: The Mtime values found for the test files should correspond to
@@ -47,11 +48,13 @@ var tests = []ZipTest{
 				Name:    "test.txt",
 				Content: []byte("This is a test text file.\n"),
 				Mtime:   "09-05-10 12:12:02",
+				Mode:    0644,
 			},
 			{
 				Name:  "gophercolor16x16.png",
 				File:  "gophercolor16x16.png",
 				Mtime: "09-05-10 15:52:58",
+				Mode:  0644,
 			},
 		},
 	},
@@ -62,11 +65,12 @@ var tests = []ZipTest{
 				Name:  "r/r.zip",
 				File:  "r.zip",
 				Mtime: "03-04-10 00:24:16",
+				Mode:  0666,
 			},
 		},
 	},
 	{Name: "readme.zip"},
-	{Name: "readme.notzip", Error: FormatError},
+	{Name: "readme.notzip", Error: ErrFormat},
 	{
 		Name: "dd.zip",
 		File: []ZipTestFile{
@@ -74,9 +78,43 @@ var tests = []ZipTest{
 				Name:    "filename",
 				Content: []byte("This is a test textfile.\n"),
 				Mtime:   "02-02-11 13:06:20",
+				Mode:    0666,
 			},
 		},
 	},
+	{
+		// created in windows XP file manager.
+		Name: "winxp.zip",
+		File: crossPlatform,
+	},
+	{
+		// created by Zip 3.0 under Linux
+		Name: "unix.zip",
+		File: crossPlatform,
+	},
+}
+
+var crossPlatform = []ZipTestFile{
+	{
+		Name:    "hello",
+		Content: []byte("world \r\n"),
+		Mode:    0666,
+	},
+	{
+		Name:    "dir/bar",
+		Content: []byte("foo \r\n"),
+		Mode:    0666,
+	},
+	{
+		Name:    "dir/empty/",
+		Content: []byte{},
+		Mode:    os.ModeDir | 0777,
+	},
+	{
+		Name:    "readonly",
+		Content: []byte("important \r\n"),
+		Mode:    0444,
+	},
 }
 
 func TestReader(t *testing.T) {
@@ -93,10 +131,14 @@ func readTestZip(t *testing.T, zt ZipTest) {
 	}
 
 	// bail if file is not zip
-	if err == FormatError {
+	if err == ErrFormat {
 		return
 	}
-	defer z.Close()
+	defer func() {
+		if err := z.Close(); err != nil {
+			t.Errorf("error %q when closing zip file", err)
+		}
+	}()
 
 	// bail here if no Files expected to be tested
 	// (there may actually be files in the zip, but we don't care)
@@ -121,10 +163,10 @@ func readTestZip(t *testing.T, zt ZipTest) {
 	done := make(chan bool)
 	for i := 0; i < 5; i++ {
 		for j, ft := range zt.File {
-			go func() {
+			go func(j int, ft ZipTestFile) {
 				readTestFile(t, ft, z.File[j])
 				done <- true
-			}()
+			}(j, ft)
 			n++
 		}
 	}
@@ -142,8 +184,8 @@ func readTestZip(t *testing.T, zt ZipTest) {
 		}
 		var b bytes.Buffer
 		_, err = io.Copy(&b, r)
-		if err != ChecksumError {
-			t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError)
+		if err != ErrChecksum {
+			t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ErrChecksum)
 		}
 	}
 }
@@ -153,15 +195,19 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
 		t.Errorf("name=%q, want %q", f.Name, ft.Name)
 	}
 
-	mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime)
-	if err != nil {
-		t.Error(err)
-		return
-	}
-	if got, want := f.Mtime_ns()/1e9, mtime.Seconds(); got != want {
-		t.Errorf("%s: mtime=%s (%d); want %s (%d)", f.Name, time.SecondsToUTC(got), got, mtime, want)
+	if ft.Mtime != "" {
+		mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		if ft := f.ModTime(); !ft.Equal(mtime) {
+			t.Errorf("%s: mtime=%s, want %s", f.Name, ft, mtime)
+		}
 	}
 
+	testFileMode(t, f, ft.Mode)
+
 	size0 := f.UncompressedSize
 
 	var b bytes.Buffer
@@ -183,7 +229,7 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
 	r.Close()
 
 	var c []byte
-	if len(ft.Content) != 0 {
+	if ft.Content != nil {
 		c = ft.Content
 	} else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil {
 		t.Error(err)
@@ -203,14 +249,23 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
 	}
 }
 
+func testFileMode(t *testing.T, f *File, want os.FileMode) {
+	mode := f.Mode()
+	if want == 0 {
+		t.Errorf("%s mode: got %v, want none", f.Name, mode)
+	} else if mode != want {
+		t.Errorf("%s mode: want %v, got %v", f.Name, want, mode)
+	}
+}
+
 func TestInvalidFiles(t *testing.T) {
 	const size = 1024 * 70 // 70kb
 	b := make([]byte, size)
 
 	// zeroes
 	_, err := NewReader(sliceReaderAt(b), size)
-	if err != FormatError {
-		t.Errorf("zeroes: error=%v, want %v", err, FormatError)
+	if err != ErrFormat {
+		t.Errorf("zeroes: error=%v, want %v", err, ErrFormat)
 	}
 
 	// repeated directoryEndSignatures
@@ -220,14 +275,14 @@ func TestInvalidFiles(t *testing.T) {
 		copy(b[i:i+4], sig)
 	}
 	_, err = NewReader(sliceReaderAt(b), size)
-	if err != FormatError {
-		t.Errorf("sigs: error=%v, want %v", err, FormatError)
+	if err != ErrFormat {
+		t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
 	}
 }
 
 type sliceReaderAt []byte
 
-func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, os.Error) {
+func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, error) {
 	copy(b, r[int(off):int(off)+len(b)])
 	return len(b), nil
 }
diff --git a/src/pkg/archive/zip/struct.go b/src/pkg/archive/zip/struct.go
index 1d6e70f..67e9658 100644
--- a/src/pkg/archive/zip/struct.go
+++ b/src/pkg/archive/zip/struct.go
@@ -11,8 +11,11 @@ This package does not support ZIP64 or disk spanning.
 */
 package zip
 
-import "os"
-import "time"
+import (
+	"errors"
+	"os"
+	"time"
+)
 
 // Compression methods.
 const (
@@ -28,6 +31,13 @@ const (
 	directoryHeaderLen       = 46 // + filename + extra + comment
 	directoryEndLen          = 22 // + comment
 	dataDescriptorLen        = 12
+
+	// Constants for the first byte in CreatorVersion
+	creatorFAT    = 0
+	creatorUnix   = 3
+	creatorNTFS   = 11
+	creatorVFAT   = 14
+	creatorMacOSX = 19
 )
 
 type FileHeader struct {
@@ -42,9 +52,42 @@ type FileHeader struct {
 	CompressedSize   uint32
 	UncompressedSize uint32
 	Extra            []byte
+	ExternalAttrs    uint32 // Meaning depends on CreatorVersion
 	Comment          string
 }
 
+// FileInfo returns an os.FileInfo for the FileHeader.
+func (fh *FileHeader) FileInfo() os.FileInfo {
+	return headerFileInfo{fh}
+}
+
+// headerFileInfo implements os.FileInfo.
+type headerFileInfo struct {
+	fh *FileHeader
+}
+
+func (fi headerFileInfo) Name() string       { return fi.fh.Name }
+func (fi headerFileInfo) Size() int64        { return int64(fi.fh.UncompressedSize) }
+func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
+func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
+func (fi headerFileInfo) Mode() os.FileMode  { return fi.fh.Mode() }
+
+// FileInfoHeader creates a partially-populated FileHeader from an
+// os.FileInfo.
+func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
+	size := fi.Size()
+	if size > (1<<32 - 1) {
+		return nil, errors.New("zip: file over 4GB")
+	}
+	fh := &FileHeader{
+		Name:             fi.Name(),
+		UncompressedSize: uint32(size),
+	}
+	fh.SetModTime(fi.ModTime())
+	fh.SetMode(fi.Mode())
+	return fh, nil
+}
+
 type directoryEnd struct {
 	diskNbr            uint16 // unused
 	dirDiskNbr         uint16 // unused
@@ -56,10 +99,10 @@ type directoryEnd struct {
 	comment            string
 }
 
-func recoverError(err *os.Error) {
+func recoverError(errp *error) {
 	if e := recover(); e != nil {
-		if osErr, ok := e.(os.Error); ok {
-			*err = osErr
+		if err, ok := e.(error); ok {
+			*errp = err
 			return
 		}
 		panic(e)
@@ -70,22 +113,122 @@ func recoverError(err *os.Error) {
 // The resolution is 2s.
 // See: http://msdn.microsoft.com/en-us/library/ms724247(v=VS.85).aspx
 func msDosTimeToTime(dosDate, dosTime uint16) time.Time {
-	return time.Time{
+	return time.Date(
 		// date bits 0-4: day of month; 5-8: month; 9-15: years since 1980
-		Year:  int64(dosDate>>9 + 1980),
-		Month: int(dosDate >> 5 & 0xf),
-		Day:   int(dosDate & 0x1f),
+		int(dosDate>>9+1980),
+		time.Month(dosDate>>5&0xf),
+		int(dosDate&0x1f),
 
 		// time bits 0-4: second/2; 5-10: minute; 11-15: hour
-		Hour:   int(dosTime >> 11),
-		Minute: int(dosTime >> 5 & 0x3f),
-		Second: int(dosTime & 0x1f * 2),
-	}
+		int(dosTime>>11),
+		int(dosTime>>5&0x3f),
+		int(dosTime&0x1f*2),
+		0, // nanoseconds
+
+		time.UTC,
+	)
+}
+
+// timeToMsDosTime converts a time.Time to an MS-DOS date and time.
+// The resolution is 2s.
+// See: http://msdn.microsoft.com/en-us/library/ms724274(v=VS.85).aspx
+func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) {
+	t = t.In(time.UTC)
+	fDate = uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9)
+	fTime = uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11)
+	return
 }
 
-// Mtime_ns returns the modified time in ns since epoch.
+// ModTime returns the modification time.
 // The resolution is 2s.
-func (h *FileHeader) Mtime_ns() int64 {
-	t := msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
-	return t.Seconds() * 1e9
+func (h *FileHeader) ModTime() time.Time {
+	return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
+}
+
+// SetModTime sets the ModifiedTime and ModifiedDate fields to the given time.
+// The resolution is 2s.
+func (h *FileHeader) SetModTime(t time.Time) {
+	h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t)
+}
+
+// traditional names for Unix constants
+const (
+	s_IFMT  = 0xf000
+	s_IFDIR = 0x4000
+	s_IFREG = 0x8000
+	s_ISUID = 0x800
+	s_ISGID = 0x400
+
+	msdosDir      = 0x10
+	msdosReadOnly = 0x01
+)
+
+// Mode returns the permission and mode bits for the FileHeader.
+func (h *FileHeader) Mode() (mode os.FileMode) {
+	switch h.CreatorVersion >> 8 {
+	case creatorUnix, creatorMacOSX:
+		mode = unixModeToFileMode(h.ExternalAttrs >> 16)
+	case creatorNTFS, creatorVFAT, creatorFAT:
+		mode = msdosModeToFileMode(h.ExternalAttrs)
+	}
+	if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
+		mode |= os.ModeDir
+	}
+	return mode
+}
+
+// SetMode changes the permission and mode bits for the FileHeader.
+func (h *FileHeader) SetMode(mode os.FileMode) {
+	h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
+	h.ExternalAttrs = fileModeToUnixMode(mode) << 16
+
+	// set MSDOS attributes too, as the original zip does.
+	if mode&os.ModeDir != 0 {
+		h.ExternalAttrs |= msdosDir
+	}
+	if mode&0200 == 0 {
+		h.ExternalAttrs |= msdosReadOnly
+	}
+}
+
+func msdosModeToFileMode(m uint32) (mode os.FileMode) {
+	if m&msdosDir != 0 {
+		mode = os.ModeDir | 0777
+	} else {
+		mode = 0666
+	}
+	if m&msdosReadOnly != 0 {
+		mode &^= 0222
+	}
+	return mode
+}
+
+func fileModeToUnixMode(mode os.FileMode) uint32 {
+	var m uint32
+	if mode&os.ModeDir != 0 {
+		m = s_IFDIR
+	} else {
+		m = s_IFREG
+	}
+	if mode&os.ModeSetuid != 0 {
+		m |= s_ISUID
+	}
+	if mode&os.ModeSetgid != 0 {
+		m |= s_ISGID
+	}
+	return m | uint32(mode&0777)
+}
+
+func unixModeToFileMode(m uint32) os.FileMode {
+	var mode os.FileMode
+	if m&s_IFMT == s_IFDIR {
+		mode |= os.ModeDir
+	}
+	if m&s_ISGID != 0 {
+		mode |= os.ModeSetgid
+	}
+	if m&s_ISUID != 0 {
+		mode |= os.ModeSetuid
+	}
+	return mode | os.FileMode(m&0777)
 }
diff --git a/src/pkg/archive/zip/testdata/unix.zip b/src/pkg/archive/zip/testdata/unix.zip
new file mode 100644
index 0000000..ce1a981
Binary files /dev/null and b/src/pkg/archive/zip/testdata/unix.zip differ
diff --git a/src/pkg/archive/zip/testdata/winxp.zip b/src/pkg/archive/zip/testdata/winxp.zip
new file mode 100644
index 0000000..3919322
Binary files /dev/null and b/src/pkg/archive/zip/testdata/winxp.zip differ
diff --git a/src/pkg/archive/zip/writer.go b/src/pkg/archive/zip/writer.go
index 2065b06..b1b128e 100644
--- a/src/pkg/archive/zip/writer.go
+++ b/src/pkg/archive/zip/writer.go
@@ -8,10 +8,10 @@ import (
 	"bufio"
 	"compress/flate"
 	"encoding/binary"
+	"errors"
 	"hash"
 	"hash/crc32"
 	"io"
-	"os"
 )
 
 // TODO(adg): support zip file comments
@@ -37,7 +37,7 @@ func NewWriter(w io.Writer) *Writer {
 
 // Close finishes writing the zip file by writing the central directory.
 // It does not (and can not) close the underlying writer.
-func (w *Writer) Close() (err os.Error) {
+func (w *Writer) Close() (err error) {
 	if w.last != nil && !w.last.closed {
 		if err = w.last.close(); err != nil {
 			return
@@ -45,7 +45,7 @@ func (w *Writer) Close() (err os.Error) {
 		w.last = nil
 	}
 	if w.closed {
-		return os.NewError("zip: writer closed twice")
+		return errors.New("zip: writer closed twice")
 	}
 	w.closed = true
 
@@ -69,7 +69,7 @@ func (w *Writer) Close() (err os.Error) {
 		write(w, uint16(len(h.Comment)))
 		write(w, uint16(0)) // disk number start
 		write(w, uint16(0)) // internal file attributes
-		write(w, uint32(0)) // external file attributes
+		write(w, h.ExternalAttrs)
 		write(w, h.offset)
 		writeBytes(w, []byte(h.Name))
 		writeBytes(w, h.Extra)
@@ -94,7 +94,7 @@ func (w *Writer) Close() (err os.Error) {
 // It returns a Writer to which the file contents should be written.
 // The file's contents must be written to the io.Writer before the next
 // call to Create, CreateHeader, or Close.
-func (w *Writer) Create(name string) (io.Writer, os.Error) {
+func (w *Writer) Create(name string) (io.Writer, error) {
 	header := &FileHeader{
 		Name:   name,
 		Method: Deflate,
@@ -107,7 +107,7 @@ func (w *Writer) Create(name string) (io.Writer, os.Error) {
 // It returns a Writer to which the file contents should be written.
 // The file's contents must be written to the io.Writer before the next
 // call to Create, CreateHeader, or Close.
-func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, os.Error) {
+func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
 	if w.last != nil && !w.last.closed {
 		if err := w.last.close(); err != nil {
 			return nil, err
@@ -115,7 +115,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, os.Error) {
 	}
 
 	fh.Flags |= 0x8 // we will write a data descriptor
-	fh.CreatorVersion = 0x14
+	fh.CreatorVersion = fh.CreatorVersion&0xff00 | 0x14
 	fh.ReaderVersion = 0x14
 
 	fw := &fileWriter{
@@ -129,7 +129,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, os.Error) {
 	case Deflate:
 		fw.comp = flate.NewWriter(fw.compCount, 5)
 	default:
-		return nil, UnsupportedMethod
+		return nil, ErrAlgorithm
 	}
 	fw.rawCount = &countWriter{w: fw.comp}
 
@@ -148,7 +148,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, os.Error) {
 	return fw, nil
 }
 
-func writeHeader(w io.Writer, h *FileHeader) (err os.Error) {
+func writeHeader(w io.Writer, h *FileHeader) (err error) {
 	defer recoverError(&err)
 	write(w, uint32(fileHeaderSignature))
 	write(w, h.ReaderVersion)
@@ -176,17 +176,17 @@ type fileWriter struct {
 	closed    bool
 }
 
-func (w *fileWriter) Write(p []byte) (int, os.Error) {
+func (w *fileWriter) Write(p []byte) (int, error) {
 	if w.closed {
-		return 0, os.NewError("zip: write to closed file")
+		return 0, errors.New("zip: write to closed file")
 	}
 	w.crc32.Write(p)
 	return w.rawCount.Write(p)
 }
 
-func (w *fileWriter) close() (err os.Error) {
+func (w *fileWriter) close() (err error) {
 	if w.closed {
-		return os.NewError("zip: file closed twice")
+		return errors.New("zip: file closed twice")
 	}
 	w.closed = true
 	if err = w.comp.Close(); err != nil {
@@ -213,7 +213,7 @@ type countWriter struct {
 	count int64
 }
 
-func (w *countWriter) Write(p []byte) (int, os.Error) {
+func (w *countWriter) Write(p []byte) (int, error) {
 	n, err := w.w.Write(p)
 	w.count += int64(n)
 	return n, err
@@ -223,7 +223,7 @@ type nopCloser struct {
 	io.Writer
 }
 
-func (w nopCloser) Close() os.Error {
+func (w nopCloser) Close() error {
 	return nil
 }
 
diff --git a/src/pkg/archive/zip/writer_test.go b/src/pkg/archive/zip/writer_test.go
index eb2a80c..5a576b1 100644
--- a/src/pkg/archive/zip/writer_test.go
+++ b/src/pkg/archive/zip/writer_test.go
@@ -7,25 +7,71 @@ package zip
 import (
 	"bytes"
 	"io/ioutil"
-	"rand"
+	"math/rand"
+	"os"
 	"testing"
 )
 
 // TODO(adg): a more sophisticated test suite
 
-const testString = "Rabbits, guinea pigs, gophers, marsupial rats, and quolls."
+type WriteTest struct {
+	Name   string
+	Data   []byte
+	Method uint16
+	Mode   os.FileMode
+}
+
+var writeTests = []WriteTest{
+	{
+		Name:   "foo",
+		Data:   []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."),
+		Method: Store,
+		Mode:   0666,
+	},
+	{
+		Name:   "bar",
+		Data:   nil, // large data set in the test
+		Method: Deflate,
+		Mode:   0644,
+	},
+	{
+		Name:   "setuid",
+		Data:   []byte("setuid file"),
+		Method: Deflate,
+		Mode:   0755 | os.ModeSetuid,
+	},
+	{
+		Name:   "setgid",
+		Data:   []byte("setgid file"),
+		Method: Deflate,
+		Mode:   0755 | os.ModeSetgid,
+	},
+	{
+		Name:   "setgid",
+		Data:   []byte("setgid file"),
+		Method: Deflate,
+		Mode:   0755 | os.ModeSetgid,
+	},
+}
 
 func TestWriter(t *testing.T) {
 	largeData := make([]byte, 1<<17)
 	for i := range largeData {
 		largeData[i] = byte(rand.Int())
 	}
+	writeTests[1].Data = largeData
+	defer func() {
+		writeTests[1].Data = nil
+	}()
 
 	// write a zip file
 	buf := new(bytes.Buffer)
 	w := NewWriter(buf)
-	testCreate(t, w, "foo", []byte(testString), Store)
-	testCreate(t, w, "bar", largeData, Deflate)
+
+	for _, wt := range writeTests {
+		testCreate(t, w, &wt)
+	}
+
 	if err := w.Close(); err != nil {
 		t.Fatal(err)
 	}
@@ -35,26 +81,34 @@ func TestWriter(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	testReadFile(t, r.File[0], []byte(testString))
-	testReadFile(t, r.File[1], largeData)
+	for i, wt := range writeTests {
+		testReadFile(t, r.File[i], &wt)
+	}
 }
 
-func testCreate(t *testing.T, w *Writer, name string, data []byte, method uint16) {
+func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
 	header := &FileHeader{
-		Name:   name,
-		Method: method,
+		Name:   wt.Name,
+		Method: wt.Method,
+	}
+	if wt.Mode != 0 {
+		header.SetMode(wt.Mode)
 	}
 	f, err := w.CreateHeader(header)
 	if err != nil {
 		t.Fatal(err)
 	}
-	_, err = f.Write(data)
+	_, err = f.Write(wt.Data)
 	if err != nil {
 		t.Fatal(err)
 	}
 }
 
-func testReadFile(t *testing.T, f *File, data []byte) {
+func testReadFile(t *testing.T, f *File, wt *WriteTest) {
+	if f.Name != wt.Name {
+		t.Fatalf("File name: got %q, want %q", f.Name, wt.Name)
+	}
+	testFileMode(t, f, wt.Mode)
 	rc, err := f.Open()
 	if err != nil {
 		t.Fatal("opening:", err)
@@ -67,7 +121,7 @@ func testReadFile(t *testing.T, f *File, data []byte) {
 	if err != nil {
 		t.Fatal("closing:", err)
 	}
-	if !bytes.Equal(b, data) {
-		t.Errorf("File contents %q, want %q", b, data)
+	if !bytes.Equal(b, wt.Data) {
+		t.Errorf("File contents %q, want %q", b, wt.Data)
 	}
 }
diff --git a/src/pkg/archive/zip/zip_test.go b/src/pkg/archive/zip/zip_test.go
index 0f71fdf..acd3d93 100644
--- a/src/pkg/archive/zip/zip_test.go
+++ b/src/pkg/archive/zip/zip_test.go
@@ -9,15 +9,17 @@ package zip
 import (
 	"bytes"
 	"fmt"
-	"os"
+	"io"
+	"reflect"
 	"testing"
+	"time"
 )
 
 type stringReaderAt string
 
-func (s stringReaderAt) ReadAt(p []byte, off int64) (n int, err os.Error) {
+func (s stringReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
 	if off >= int64(len(s)) {
-		return 0, os.EOF
+		return 0, io.EOF
 	}
 	n = copy(p, s[off:])
 	return
@@ -55,3 +57,32 @@ func TestOver65kFiles(t *testing.T) {
 		}
 	}
 }
+
+func TestModTime(t *testing.T) {
+	var testTime = time.Date(2009, time.November, 10, 23, 45, 58, 0, time.UTC)
+	fh := new(FileHeader)
+	fh.SetModTime(testTime)
+	outTime := fh.ModTime()
+	if !outTime.Equal(testTime) {
+		t.Errorf("times don't match: got %s, want %s", outTime, testTime)
+	}
+}
+
+func TestFileHeaderRoundTrip(t *testing.T) {
+	fh := &FileHeader{
+		Name:             "foo.txt",
+		UncompressedSize: 987654321,
+		ModifiedTime:     1234,
+		ModifiedDate:     5678,
+	}
+	fi := fh.FileInfo()
+	fh2, err := FileInfoHeader(fi)
+
+	// Ignore these fields:
+	fh2.CreatorVersion = 0
+	fh2.ExternalAttrs = 0
+
+	if !reflect.DeepEqual(fh, fh2) {
+		t.Errorf("mismatch\n input=%#v\noutput=%#v\nerr=%v", fh, fh2, err)
+	}
+}
diff --git a/src/pkg/asn1/Makefile b/src/pkg/asn1/Makefile
deleted file mode 100644
index 6b7770e..0000000
--- a/src/pkg/asn1/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=asn1
-GOFILES=\
-	asn1.go\
-	common.go\
-	marshal.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/asn1/asn1.go b/src/pkg/asn1/asn1.go
deleted file mode 100644
index 39b676b..0000000
--- a/src/pkg/asn1/asn1.go
+++ /dev/null
@@ -1,840 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package asn1 implements parsing of DER-encoded ASN.1 data structures,
-// as defined in ITU-T Rec X.690.
-//
-// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,''
-// http://luca.ntop.org/Teaching/Appunti/asn1.html.
-package asn1
-
-// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc
-// are different encoding formats for those objects. Here, we'll be dealing
-// with DER, the Distinguished Encoding Rules. DER is used in X.509 because
-// it's fast to parse and, unlike BER, has a unique encoding for every object.
-// When calculating hashes over objects, it's important that the resulting
-// bytes be the same at both ends and DER removes this margin of error.
-//
-// ASN.1 is very complex and this package doesn't attempt to implement
-// everything by any means.
-
-import (
-	"big"
-	"fmt"
-	"os"
-	"reflect"
-	"time"
-)
-
-// A StructuralError suggests that the ASN.1 data is valid, but the Go type
-// which is receiving it doesn't match.
-type StructuralError struct {
-	Msg string
-}
-
-func (e StructuralError) String() string { return "ASN.1 structure error: " + e.Msg }
-
-// A SyntaxError suggests that the ASN.1 data is invalid.
-type SyntaxError struct {
-	Msg string
-}
-
-func (e SyntaxError) String() string { return "ASN.1 syntax error: " + e.Msg }
-
-// We start by dealing with each of the primitive types in turn.
-
-// BOOLEAN
-
-func parseBool(bytes []byte) (ret bool, err os.Error) {
-	if len(bytes) != 1 {
-		err = SyntaxError{"invalid boolean"}
-		return
-	}
-
-	return bytes[0] != 0, nil
-}
-
-// INTEGER
-
-// parseInt64 treats the given bytes as a big-endian, signed integer and
-// returns the result.
-func parseInt64(bytes []byte) (ret int64, err os.Error) {
-	if len(bytes) > 8 {
-		// We'll overflow an int64 in this case.
-		err = StructuralError{"integer too large"}
-		return
-	}
-	for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
-		ret <<= 8
-		ret |= int64(bytes[bytesRead])
-	}
-
-	// Shift up and down in order to sign extend the result.
-	ret <<= 64 - uint8(len(bytes))*8
-	ret >>= 64 - uint8(len(bytes))*8
-	return
-}
-
-// parseInt treats the given bytes as a big-endian, signed integer and returns
-// the result.
-func parseInt(bytes []byte) (int, os.Error) {
-	ret64, err := parseInt64(bytes)
-	if err != nil {
-		return 0, err
-	}
-	if ret64 != int64(int(ret64)) {
-		return 0, StructuralError{"integer too large"}
-	}
-	return int(ret64), nil
-}
-
-var bigOne = big.NewInt(1)
-
-// parseBigInt treats the given bytes as a big-endian, signed integer and returns
-// the result.
-func parseBigInt(bytes []byte) *big.Int {
-	ret := new(big.Int)
-	if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
-		// This is a negative number.
-		notBytes := make([]byte, len(bytes))
-		for i := range notBytes {
-			notBytes[i] = ^bytes[i]
-		}
-		ret.SetBytes(notBytes)
-		ret.Add(ret, bigOne)
-		ret.Neg(ret)
-		return ret
-	}
-	ret.SetBytes(bytes)
-	return ret
-}
-
-// BIT STRING
-
-// BitString is the structure to use when you want an ASN.1 BIT STRING type. A
-// bit string is padded up to the nearest byte in memory and the number of
-// valid bits is recorded. Padding bits will be zero.
-type BitString struct {
-	Bytes     []byte // bits packed into bytes.
-	BitLength int    // length in bits.
-}
-
-// At returns the bit at the given index. If the index is out of range it
-// returns false.
-func (b BitString) At(i int) int {
-	if i < 0 || i >= b.BitLength {
-		return 0
-	}
-	x := i / 8
-	y := 7 - uint(i%8)
-	return int(b.Bytes[x]>>y) & 1
-}
-
-// RightAlign returns a slice where the padding bits are at the beginning. The
-// slice may share memory with the BitString.
-func (b BitString) RightAlign() []byte {
-	shift := uint(8 - (b.BitLength % 8))
-	if shift == 8 || len(b.Bytes) == 0 {
-		return b.Bytes
-	}
-
-	a := make([]byte, len(b.Bytes))
-	a[0] = b.Bytes[0] >> shift
-	for i := 1; i < len(b.Bytes); i++ {
-		a[i] = b.Bytes[i-1] << (8 - shift)
-		a[i] |= b.Bytes[i] >> shift
-	}
-
-	return a
-}
-
-// parseBitString parses an ASN.1 bit string from the given byte slice and returns it.
-func parseBitString(bytes []byte) (ret BitString, err os.Error) {
-	if len(bytes) == 0 {
-		err = SyntaxError{"zero length BIT STRING"}
-		return
-	}
-	paddingBits := int(bytes[0])
-	if paddingBits > 7 ||
-		len(bytes) == 1 && paddingBits > 0 ||
-		bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {
-		err = SyntaxError{"invalid padding bits in BIT STRING"}
-		return
-	}
-	ret.BitLength = (len(bytes)-1)*8 - paddingBits
-	ret.Bytes = bytes[1:]
-	return
-}
-
-// OBJECT IDENTIFIER
-
-// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER.
-type ObjectIdentifier []int
-
-// Equal returns true iff oi and other represent the same identifier.
-func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
-	if len(oi) != len(other) {
-		return false
-	}
-	for i := 0; i < len(oi); i++ {
-		if oi[i] != other[i] {
-			return false
-		}
-	}
-
-	return true
-}
-
-// parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and
-// returns it. An object identifier is a sequence of variable length integers
-// that are assigned in a hierarchy.
-func parseObjectIdentifier(bytes []byte) (s []int, err os.Error) {
-	if len(bytes) == 0 {
-		err = SyntaxError{"zero length OBJECT IDENTIFIER"}
-		return
-	}
-
-	// In the worst case, we get two elements from the first byte (which is
-	// encoded differently) and then every varint is a single byte long.
-	s = make([]int, len(bytes)+1)
-
-	// The first byte is 40*value1 + value2:
-	s[0] = int(bytes[0]) / 40
-	s[1] = int(bytes[0]) % 40
-	i := 2
-	for offset := 1; offset < len(bytes); i++ {
-		var v int
-		v, offset, err = parseBase128Int(bytes, offset)
-		if err != nil {
-			return
-		}
-		s[i] = v
-	}
-	s = s[0:i]
-	return
-}
-
-// ENUMERATED
-
-// An Enumerated is represented as a plain int.
-type Enumerated int
-
-// FLAG
-
-// A Flag accepts any data and is set to true if present.
-type Flag bool
-
-// parseBase128Int parses a base-128 encoded int from the given offset in the
-// given byte slice. It returns the value and the new offset.
-func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err os.Error) {
-	offset = initOffset
-	for shifted := 0; offset < len(bytes); shifted++ {
-		if shifted > 4 {
-			err = StructuralError{"base 128 integer too large"}
-			return
-		}
-		ret <<= 7
-		b := bytes[offset]
-		ret |= int(b & 0x7f)
-		offset++
-		if b&0x80 == 0 {
-			return
-		}
-	}
-	err = SyntaxError{"truncated base 128 integer"}
-	return
-}
-
-// UTCTime
-
-func parseUTCTime(bytes []byte) (ret *time.Time, err os.Error) {
-	s := string(bytes)
-	ret, err = time.Parse("0601021504Z0700", s)
-	if err == nil {
-		return
-	}
-	ret, err = time.Parse("060102150405Z0700", s)
-	return
-}
-
-// parseGeneralizedTime parses the GeneralizedTime from the given byte slice
-// and returns the resulting time.
-func parseGeneralizedTime(bytes []byte) (ret *time.Time, err os.Error) {
-	return time.Parse("20060102150405Z0700", string(bytes))
-}
-
-// PrintableString
-
-// parsePrintableString parses a ASN.1 PrintableString from the given byte
-// array and returns it.
-func parsePrintableString(bytes []byte) (ret string, err os.Error) {
-	for _, b := range bytes {
-		if !isPrintable(b) {
-			err = SyntaxError{"PrintableString contains invalid character"}
-			return
-		}
-	}
-	ret = string(bytes)
-	return
-}
-
-// isPrintable returns true iff the given b is in the ASN.1 PrintableString set.
-func isPrintable(b byte) bool {
-	return 'a' <= b && b <= 'z' ||
-		'A' <= b && b <= 'Z' ||
-		'0' <= b && b <= '9' ||
-		'\'' <= b && b <= ')' ||
-		'+' <= b && b <= '/' ||
-		b == ' ' ||
-		b == ':' ||
-		b == '=' ||
-		b == '?' ||
-		// This is technically not allowed in a PrintableString.
-		// However, x509 certificates with wildcard strings don't
-		// always use the correct string type so we permit it.
-		b == '*'
-}
-
-// IA5String
-
-// parseIA5String parses a ASN.1 IA5String (ASCII string) from the given
-// byte slice and returns it.
-func parseIA5String(bytes []byte) (ret string, err os.Error) {
-	for _, b := range bytes {
-		if b >= 0x80 {
-			err = SyntaxError{"IA5String contains invalid character"}
-			return
-		}
-	}
-	ret = string(bytes)
-	return
-}
-
-// T61String
-
-// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given
-// byte slice and returns it.
-func parseT61String(bytes []byte) (ret string, err os.Error) {
-	return string(bytes), nil
-}
-
-// UTF8String
-
-// parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte
-// array and returns it.
-func parseUTF8String(bytes []byte) (ret string, err os.Error) {
-	return string(bytes), nil
-}
-
-// A RawValue represents an undecoded ASN.1 object.
-type RawValue struct {
-	Class, Tag int
-	IsCompound bool
-	Bytes      []byte
-	FullBytes  []byte // includes the tag and length
-}
-
-// RawContent is used to signal that the undecoded, DER data needs to be
-// preserved for a struct. To use it, the first field of the struct must have
-// this type. It's an error for any of the other fields to have this type.
-type RawContent []byte
-
-// Tagging
-
-// parseTagAndLength parses an ASN.1 tag and length pair from the given offset
-// into a byte slice. It returns the parsed data and the new offset. SET and
-// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we
-// don't distinguish between ordered and unordered objects in this code.
-func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err os.Error) {
-	offset = initOffset
-	b := bytes[offset]
-	offset++
-	ret.class = int(b >> 6)
-	ret.isCompound = b&0x20 == 0x20
-	ret.tag = int(b & 0x1f)
-
-	// If the bottom five bits are set, then the tag number is actually base 128
-	// encoded afterwards
-	if ret.tag == 0x1f {
-		ret.tag, offset, err = parseBase128Int(bytes, offset)
-		if err != nil {
-			return
-		}
-	}
-	if offset >= len(bytes) {
-		err = SyntaxError{"truncated tag or length"}
-		return
-	}
-	b = bytes[offset]
-	offset++
-	if b&0x80 == 0 {
-		// The length is encoded in the bottom 7 bits.
-		ret.length = int(b & 0x7f)
-	} else {
-		// Bottom 7 bits give the number of length bytes to follow.
-		numBytes := int(b & 0x7f)
-		// We risk overflowing a signed 32-bit number if we accept more than 3 bytes.
-		if numBytes > 3 {
-			err = StructuralError{"length too large"}
-			return
-		}
-		if numBytes == 0 {
-			err = SyntaxError{"indefinite length found (not DER)"}
-			return
-		}
-		ret.length = 0
-		for i := 0; i < numBytes; i++ {
-			if offset >= len(bytes) {
-				err = SyntaxError{"truncated tag or length"}
-				return
-			}
-			b = bytes[offset]
-			offset++
-			ret.length <<= 8
-			ret.length |= int(b)
-		}
-	}
-
-	return
-}
-
-// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse
-// a number of ASN.1 values from the given byte slice and returns them as a
-// slice of Go values of the given type.
-func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err os.Error) {
-	expectedTag, compoundType, ok := getUniversalType(elemType)
-	if !ok {
-		err = StructuralError{"unknown Go type for slice"}
-		return
-	}
-
-	// First we iterate over the input and count the number of elements,
-	// checking that the types are correct in each case.
-	numElements := 0
-	for offset := 0; offset < len(bytes); {
-		var t tagAndLength
-		t, offset, err = parseTagAndLength(bytes, offset)
-		if err != nil {
-			return
-		}
-		// We pretend that GENERAL STRINGs are PRINTABLE STRINGs so
-		// that a sequence of them can be parsed into a []string.
-		if t.tag == tagGeneralString {
-			t.tag = tagPrintableString
-		}
-		if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag {
-			err = StructuralError{"sequence tag mismatch"}
-			return
-		}
-		if invalidLength(offset, t.length, len(bytes)) {
-			err = SyntaxError{"truncated sequence"}
-			return
-		}
-		offset += t.length
-		numElements++
-	}
-	ret = reflect.MakeSlice(sliceType, numElements, numElements)
-	params := fieldParameters{}
-	offset := 0
-	for i := 0; i < numElements; i++ {
-		offset, err = parseField(ret.Index(i), bytes, offset, params)
-		if err != nil {
-			return
-		}
-	}
-	return
-}
-
-var (
-	bitStringType        = reflect.TypeOf(BitString{})
-	objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
-	enumeratedType       = reflect.TypeOf(Enumerated(0))
-	flagType             = reflect.TypeOf(Flag(false))
-	timeType             = reflect.TypeOf(&time.Time{})
-	rawValueType         = reflect.TypeOf(RawValue{})
-	rawContentsType      = reflect.TypeOf(RawContent(nil))
-	bigIntType           = reflect.TypeOf(new(big.Int))
-)
-
-// invalidLength returns true iff offset + length > sliceLength, or if the
-// addition would overflow.
-func invalidLength(offset, length, sliceLength int) bool {
-	return offset+length < offset || offset+length > sliceLength
-}
-
-// parseField is the main parsing function. Given a byte slice and an offset
-// into the array, it will try to parse a suitable ASN.1 value out and store it
-// in the given Value.
-func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err os.Error) {
-	offset = initOffset
-	fieldType := v.Type()
-
-	// If we have run out of data, it may be that there are optional elements at the end.
-	if offset == len(bytes) {
-		if !setDefaultValue(v, params) {
-			err = SyntaxError{"sequence truncated"}
-		}
-		return
-	}
-
-	// Deal with raw values.
-	if fieldType == rawValueType {
-		var t tagAndLength
-		t, offset, err = parseTagAndLength(bytes, offset)
-		if err != nil {
-			return
-		}
-		if invalidLength(offset, t.length, len(bytes)) {
-			err = SyntaxError{"data truncated"}
-			return
-		}
-		result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]}
-		offset += t.length
-		v.Set(reflect.ValueOf(result))
-		return
-	}
-
-	// Deal with the ANY type.
-	if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 {
-		var t tagAndLength
-		t, offset, err = parseTagAndLength(bytes, offset)
-		if err != nil {
-			return
-		}
-		if invalidLength(offset, t.length, len(bytes)) {
-			err = SyntaxError{"data truncated"}
-			return
-		}
-		var result interface{}
-		if !t.isCompound && t.class == classUniversal {
-			innerBytes := bytes[offset : offset+t.length]
-			switch t.tag {
-			case tagPrintableString:
-				result, err = parsePrintableString(innerBytes)
-			case tagIA5String:
-				result, err = parseIA5String(innerBytes)
-			case tagT61String:
-				result, err = parseT61String(innerBytes)
-			case tagInteger:
-				result, err = parseInt64(innerBytes)
-			case tagBitString:
-				result, err = parseBitString(innerBytes)
-			case tagOID:
-				result, err = parseObjectIdentifier(innerBytes)
-			case tagUTCTime:
-				result, err = parseUTCTime(innerBytes)
-			case tagOctetString:
-				result = innerBytes
-			default:
-				// If we don't know how to handle the type, we just leave Value as nil.
-			}
-		}
-		offset += t.length
-		if err != nil {
-			return
-		}
-		if result != nil {
-			v.Set(reflect.ValueOf(result))
-		}
-		return
-	}
-	universalTag, compoundType, ok1 := getUniversalType(fieldType)
-	if !ok1 {
-		err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)}
-		return
-	}
-
-	t, offset, err := parseTagAndLength(bytes, offset)
-	if err != nil {
-		return
-	}
-	if params.explicit {
-		expectedClass := classContextSpecific
-		if params.application {
-			expectedClass = classApplication
-		}
-		if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
-			if t.length > 0 {
-				t, offset, err = parseTagAndLength(bytes, offset)
-				if err != nil {
-					return
-				}
-			} else {
-				if fieldType != flagType {
-					err = StructuralError{"Zero length explicit tag was not an asn1.Flag"}
-					return
-				}
-				v.SetBool(true)
-				return
-			}
-		} else {
-			// The tags didn't match, it might be an optional element.
-			ok := setDefaultValue(v, params)
-			if ok {
-				offset = initOffset
-			} else {
-				err = StructuralError{"explicitly tagged member didn't match"}
-			}
-			return
-		}
-	}
-
-	// Special case for strings: all the ASN.1 string types map to the Go
-	// type string. getUniversalType returns the tag for PrintableString
-	// when it sees a string, so if we see a different string type on the
-	// wire, we change the universal type to match.
-	if universalTag == tagPrintableString {
-		switch t.tag {
-		case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
-			universalTag = t.tag
-		}
-	}
-
-	// Special case for time: UTCTime and GeneralizedTime both map to the
-	// Go type time.Time.
-	if universalTag == tagUTCTime && t.tag == tagGeneralizedTime {
-		universalTag = tagGeneralizedTime
-	}
-
-	expectedClass := classUniversal
-	expectedTag := universalTag
-
-	if !params.explicit && params.tag != nil {
-		expectedClass = classContextSpecific
-		expectedTag = *params.tag
-	}
-
-	if !params.explicit && params.application && params.tag != nil {
-		expectedClass = classApplication
-		expectedTag = *params.tag
-	}
-
-	// We have unwrapped any explicit tagging at this point.
-	if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType {
-		// Tags don't match. Again, it could be an optional element.
-		ok := setDefaultValue(v, params)
-		if ok {
-			offset = initOffset
-		} else {
-			err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)}
-		}
-		return
-	}
-	if invalidLength(offset, t.length, len(bytes)) {
-		err = SyntaxError{"data truncated"}
-		return
-	}
-	innerBytes := bytes[offset : offset+t.length]
-	offset += t.length
-
-	// We deal with the structures defined in this package first.
-	switch fieldType {
-	case objectIdentifierType:
-		newSlice, err1 := parseObjectIdentifier(innerBytes)
-		v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice)))
-		if err1 == nil {
-			reflect.Copy(v, reflect.ValueOf(newSlice))
-		}
-		err = err1
-		return
-	case bitStringType:
-		bs, err1 := parseBitString(innerBytes)
-		if err1 == nil {
-			v.Set(reflect.ValueOf(bs))
-		}
-		err = err1
-		return
-	case timeType:
-		var time *time.Time
-		var err1 os.Error
-		if universalTag == tagUTCTime {
-			time, err1 = parseUTCTime(innerBytes)
-		} else {
-			time, err1 = parseGeneralizedTime(innerBytes)
-		}
-		if err1 == nil {
-			v.Set(reflect.ValueOf(time))
-		}
-		err = err1
-		return
-	case enumeratedType:
-		parsedInt, err1 := parseInt(innerBytes)
-		if err1 == nil {
-			v.SetInt(int64(parsedInt))
-		}
-		err = err1
-		return
-	case flagType:
-		v.SetBool(true)
-		return
-	case bigIntType:
-		parsedInt := parseBigInt(innerBytes)
-		v.Set(reflect.ValueOf(parsedInt))
-		return
-	}
-	switch val := v; val.Kind() {
-	case reflect.Bool:
-		parsedBool, err1 := parseBool(innerBytes)
-		if err1 == nil {
-			val.SetBool(parsedBool)
-		}
-		err = err1
-		return
-	case reflect.Int, reflect.Int32:
-		parsedInt, err1 := parseInt(innerBytes)
-		if err1 == nil {
-			val.SetInt(int64(parsedInt))
-		}
-		err = err1
-		return
-	case reflect.Int64:
-		parsedInt, err1 := parseInt64(innerBytes)
-		if err1 == nil {
-			val.SetInt(parsedInt)
-		}
-		err = err1
-		return
-	// TODO(dfc) Add support for the remaining integer types
-	case reflect.Struct:
-		structType := fieldType
-
-		if structType.NumField() > 0 &&
-			structType.Field(0).Type == rawContentsType {
-			bytes := bytes[initOffset:offset]
-			val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
-		}
-
-		innerOffset := 0
-		for i := 0; i < structType.NumField(); i++ {
-			field := structType.Field(i)
-			if i == 0 && field.Type == rawContentsType {
-				continue
-			}
-			innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1")))
-			if err != nil {
-				return
-			}
-		}
-		// We allow extra bytes at the end of the SEQUENCE because
-		// adding elements to the end has been used in X.509 as the
-		// version numbers have increased.
-		return
-	case reflect.Slice:
-		sliceType := fieldType
-		if sliceType.Elem().Kind() == reflect.Uint8 {
-			val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
-			reflect.Copy(val, reflect.ValueOf(innerBytes))
-			return
-		}
-		newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
-		if err1 == nil {
-			val.Set(newSlice)
-		}
-		err = err1
-		return
-	case reflect.String:
-		var v string
-		switch universalTag {
-		case tagPrintableString:
-			v, err = parsePrintableString(innerBytes)
-		case tagIA5String:
-			v, err = parseIA5String(innerBytes)
-		case tagT61String:
-			v, err = parseT61String(innerBytes)
-		case tagUTF8String:
-			v, err = parseUTF8String(innerBytes)
-		case tagGeneralString:
-			// GeneralString is specified in ISO-2022/ECMA-35,
-			// A brief review suggests that it includes structures
-			// that allow the encoding to change midstring and
-			// such. We give up and pass it as an 8-bit string.
-			v, err = parseT61String(innerBytes)
-		default:
-			err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
-		}
-		if err == nil {
-			val.SetString(v)
-		}
-		return
-	}
-	err = StructuralError{"unsupported: " + v.Type().String()}
-	return
-}
-
-// setDefaultValue is used to install a default value, from a tag string, into
-// a Value. It is successful is the field was optional, even if a default value
-// wasn't provided or it failed to install it into the Value.
-func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
-	if !params.optional {
-		return
-	}
-	ok = true
-	if params.defaultValue == nil {
-		return
-	}
-	switch val := v; val.Kind() {
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		val.SetInt(*params.defaultValue)
-	}
-	return
-}
-
-// Unmarshal parses the DER-encoded ASN.1 data structure b
-// and uses the reflect package to fill in an arbitrary value pointed at by val.
-// Because Unmarshal uses the reflect package, the structs
-// being written to must use upper case field names.
-//
-// An ASN.1 INTEGER can be written to an int, int32 or int64.
-// If the encoded value does not fit in the Go type,
-// Unmarshal returns a parse error.
-//
-// An ASN.1 BIT STRING can be written to a BitString.
-//
-// An ASN.1 OCTET STRING can be written to a []byte.
-//
-// An ASN.1 OBJECT IDENTIFIER can be written to an
-// ObjectIdentifier.
-//
-// An ASN.1 ENUMERATED can be written to an Enumerated.
-//
-// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a *time.Time.
-//
-// An ASN.1 PrintableString or IA5String can be written to a string.
-//
-// Any of the above ASN.1 values can be written to an interface{}.
-// The value stored in the interface has the corresponding Go type.
-// For integers, that type is int64.
-//
-// An ASN.1 SEQUENCE OF x or SET OF x can be written
-// to a slice if an x can be written to the slice's element type.
-//
-// An ASN.1 SEQUENCE or SET can be written to a struct
-// if each of the elements in the sequence can be
-// written to the corresponding element in the struct.
-//
-// The following tags on struct fields have special meaning to Unmarshal:
-//
-//	optional		marks the field as ASN.1 OPTIONAL
-//	[explicit] tag:x	specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC
-//	default:x		sets the default value for optional integer fields
-//
-// If the type of the first field of a structure is RawContent then the raw
-// ASN1 contents of the struct will be stored in it.
-//
-// Other ASN.1 types are not supported; if it encounters them,
-// Unmarshal returns a parse error.
-func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) {
-	return UnmarshalWithParams(b, val, "")
-}
-
-// UnmarshalWithParams allows field parameters to be specified for the
-// top-level element. The form of the params is the same as the field tags.
-func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) {
-	v := reflect.ValueOf(val).Elem()
-	offset, err := parseField(v, b, 0, parseFieldParameters(params))
-	if err != nil {
-		return nil, err
-	}
-	return b[offset:], nil
-}
diff --git a/src/pkg/asn1/asn1_test.go b/src/pkg/asn1/asn1_test.go
deleted file mode 100644
index 1c529bd..0000000
--- a/src/pkg/asn1/asn1_test.go
+++ /dev/null
@@ -1,689 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package asn1
-
-import (
-	"bytes"
-	"reflect"
-	"testing"
-	"time"
-)
-
-type int64Test struct {
-	in  []byte
-	ok  bool
-	out int64
-}
-
-var int64TestData = []int64Test{
-	{[]byte{0x00}, true, 0},
-	{[]byte{0x7f}, true, 127},
-	{[]byte{0x00, 0x80}, true, 128},
-	{[]byte{0x01, 0x00}, true, 256},
-	{[]byte{0x80}, true, -128},
-	{[]byte{0xff, 0x7f}, true, -129},
-	{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, true, -1},
-	{[]byte{0xff}, true, -1},
-	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808},
-	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0},
-}
-
-func TestParseInt64(t *testing.T) {
-	for i, test := range int64TestData {
-		ret, err := parseInt64(test.in)
-		if (err == nil) != test.ok {
-			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
-		}
-		if test.ok && ret != test.out {
-			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
-		}
-	}
-}
-
-type int32Test struct {
-	in  []byte
-	ok  bool
-	out int32
-}
-
-var int32TestData = []int32Test{
-	{[]byte{0x00}, true, 0},
-	{[]byte{0x7f}, true, 127},
-	{[]byte{0x00, 0x80}, true, 128},
-	{[]byte{0x01, 0x00}, true, 256},
-	{[]byte{0x80}, true, -128},
-	{[]byte{0xff, 0x7f}, true, -129},
-	{[]byte{0xff, 0xff, 0xff, 0xff}, true, -1},
-	{[]byte{0xff}, true, -1},
-	{[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648},
-	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0},
-}
-
-func TestParseInt32(t *testing.T) {
-	for i, test := range int32TestData {
-		ret, err := parseInt(test.in)
-		if (err == nil) != test.ok {
-			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
-		}
-		if test.ok && int32(ret) != test.out {
-			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
-		}
-	}
-}
-
-var bigIntTests = []struct {
-	in     []byte
-	base10 string
-}{
-	{[]byte{0xff}, "-1"},
-	{[]byte{0x00}, "0"},
-	{[]byte{0x01}, "1"},
-	{[]byte{0x00, 0xff}, "255"},
-	{[]byte{0xff, 0x00}, "-256"},
-	{[]byte{0x01, 0x00}, "256"},
-}
-
-func TestParseBigInt(t *testing.T) {
-	for i, test := range bigIntTests {
-		ret := parseBigInt(test.in)
-		if ret.String() != test.base10 {
-			t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10)
-		}
-		fw := newForkableWriter()
-		marshalBigInt(fw, ret)
-		result := fw.Bytes()
-		if !bytes.Equal(result, test.in) {
-			t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in)
-		}
-	}
-}
-
-type bitStringTest struct {
-	in        []byte
-	ok        bool
-	out       []byte
-	bitLength int
-}
-
-var bitStringTestData = []bitStringTest{
-	{[]byte{}, false, []byte{}, 0},
-	{[]byte{0x00}, true, []byte{}, 0},
-	{[]byte{0x07, 0x00}, true, []byte{0x00}, 1},
-	{[]byte{0x07, 0x01}, false, []byte{}, 0},
-	{[]byte{0x07, 0x40}, false, []byte{}, 0},
-	{[]byte{0x08, 0x00}, false, []byte{}, 0},
-}
-
-func TestBitString(t *testing.T) {
-	for i, test := range bitStringTestData {
-		ret, err := parseBitString(test.in)
-		if (err == nil) != test.ok {
-			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
-		}
-		if err == nil {
-			if test.bitLength != ret.BitLength || bytes.Compare(ret.Bytes, test.out) != 0 {
-				t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength)
-			}
-		}
-	}
-}
-
-func TestBitStringAt(t *testing.T) {
-	bs := BitString{[]byte{0x82, 0x40}, 16}
-	if bs.At(0) != 1 {
-		t.Error("#1: Failed")
-	}
-	if bs.At(1) != 0 {
-		t.Error("#2: Failed")
-	}
-	if bs.At(6) != 1 {
-		t.Error("#3: Failed")
-	}
-	if bs.At(9) != 1 {
-		t.Error("#4: Failed")
-	}
-}
-
-type bitStringRightAlignTest struct {
-	in    []byte
-	inlen int
-	out   []byte
-}
-
-var bitStringRightAlignTests = []bitStringRightAlignTest{
-	{[]byte{0x80}, 1, []byte{0x01}},
-	{[]byte{0x80, 0x80}, 9, []byte{0x01, 0x01}},
-	{[]byte{}, 0, []byte{}},
-	{[]byte{0xce}, 8, []byte{0xce}},
-	{[]byte{0xce, 0x47}, 16, []byte{0xce, 0x47}},
-	{[]byte{0x34, 0x50}, 12, []byte{0x03, 0x45}},
-}
-
-func TestBitStringRightAlign(t *testing.T) {
-	for i, test := range bitStringRightAlignTests {
-		bs := BitString{test.in, test.inlen}
-		out := bs.RightAlign()
-		if bytes.Compare(out, test.out) != 0 {
-			t.Errorf("#%d got: %x want: %x", i, out, test.out)
-		}
-	}
-}
-
-type objectIdentifierTest struct {
-	in  []byte
-	ok  bool
-	out []int
-}
-
-var objectIdentifierTestData = []objectIdentifierTest{
-	{[]byte{}, false, []int{}},
-	{[]byte{85}, true, []int{2, 5}},
-	{[]byte{85, 0x02}, true, []int{2, 5, 2}},
-	{[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
-	{[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
-}
-
-func TestObjectIdentifier(t *testing.T) {
-	for i, test := range objectIdentifierTestData {
-		ret, err := parseObjectIdentifier(test.in)
-		if (err == nil) != test.ok {
-			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
-		}
-		if err == nil {
-			if !reflect.DeepEqual(test.out, ret) {
-				t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
-			}
-		}
-	}
-}
-
-type timeTest struct {
-	in  string
-	ok  bool
-	out *time.Time
-}
-
-var utcTestData = []timeTest{
-	{"910506164540-0700", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, -7 * 60 * 60, ""}},
-	{"910506164540+0730", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 7*60*60 + 30*60, ""}},
-	{"910506234540Z", true, &time.Time{1991, 05, 06, 23, 45, 40, 0, 0, "UTC"}},
-	{"9105062345Z", true, &time.Time{1991, 05, 06, 23, 45, 0, 0, 0, "UTC"}},
-	{"a10506234540Z", false, nil},
-	{"91a506234540Z", false, nil},
-	{"9105a6234540Z", false, nil},
-	{"910506a34540Z", false, nil},
-	{"910506334a40Z", false, nil},
-	{"91050633444aZ", false, nil},
-	{"910506334461Z", false, nil},
-	{"910506334400Za", false, nil},
-}
-
-func TestUTCTime(t *testing.T) {
-	for i, test := range utcTestData {
-		ret, err := parseUTCTime([]byte(test.in))
-		if (err == nil) != test.ok {
-			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
-		}
-		if err == nil {
-			if !reflect.DeepEqual(test.out, ret) {
-				t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
-			}
-		}
-	}
-}
-
-var generalizedTimeTestData = []timeTest{
-	{"20100102030405Z", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, "UTC"}},
-	{"20100102030405", false, nil},
-	{"20100102030405+0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 6*60*60 + 7*60, ""}},
-	{"20100102030405-0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, -6*60*60 - 7*60, ""}},
-}
-
-func TestGeneralizedTime(t *testing.T) {
-	for i, test := range generalizedTimeTestData {
-		ret, err := parseGeneralizedTime([]byte(test.in))
-		if (err == nil) != test.ok {
-			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
-		}
-		if err == nil {
-			if !reflect.DeepEqual(test.out, ret) {
-				t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
-			}
-		}
-	}
-}
-
-type tagAndLengthTest struct {
-	in  []byte
-	ok  bool
-	out tagAndLength
-}
-
-var tagAndLengthData = []tagAndLengthTest{
-	{[]byte{0x80, 0x01}, true, tagAndLength{2, 0, 1, false}},
-	{[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}},
-	{[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}},
-	{[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}},
-	{[]byte{0x1f, 0x01, 0x00}, true, tagAndLength{0, 1, 0, false}},
-	{[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}},
-	{[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}},
-	{[]byte{0x00, 0x81, 0x01}, true, tagAndLength{0, 0, 1, false}},
-	{[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}},
-	{[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}},
-	{[]byte{0x1f, 0x85}, false, tagAndLength{}},
-	{[]byte{0x30, 0x80}, false, tagAndLength{}},
-}
-
-func TestParseTagAndLength(t *testing.T) {
-	for i, test := range tagAndLengthData {
-		tagAndLength, _, err := parseTagAndLength(test.in, 0)
-		if (err == nil) != test.ok {
-			t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok)
-		}
-		if err == nil && !reflect.DeepEqual(test.out, tagAndLength) {
-			t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out)
-		}
-	}
-}
-
-type parseFieldParametersTest struct {
-	in  string
-	out fieldParameters
-}
-
-func newInt(n int) *int { return &n }
-
-func newInt64(n int64) *int64 { return &n }
-
-func newString(s string) *string { return &s }
-
-func newBool(b bool) *bool { return &b }
-
-var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{
-	{"", fieldParameters{}},
-	{"ia5", fieldParameters{stringType: tagIA5String}},
-	{"printable", fieldParameters{stringType: tagPrintableString}},
-	{"optional", fieldParameters{optional: true}},
-	{"explicit", fieldParameters{explicit: true, tag: new(int)}},
-	{"application", fieldParameters{application: true, tag: new(int)}},
-	{"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}},
-	{"default:42", fieldParameters{defaultValue: newInt64(42)}},
-	{"tag:17", fieldParameters{tag: newInt(17)}},
-	{"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}},
-	{"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, false}},
-	{"set", fieldParameters{set: true}},
-}
-
-func TestParseFieldParameters(t *testing.T) {
-	for i, test := range parseFieldParametersTestData {
-		f := parseFieldParameters(test.in)
-		if !reflect.DeepEqual(f, test.out) {
-			t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out)
-		}
-	}
-}
-
-type TestObjectIdentifierStruct struct {
-	OID ObjectIdentifier
-}
-
-type TestContextSpecificTags struct {
-	A int `asn1:"tag:1"`
-}
-
-type TestContextSpecificTags2 struct {
-	A int `asn1:"explicit,tag:1"`
-	B int
-}
-
-type TestElementsAfterString struct {
-	S    string
-	A, B int
-}
-
-var unmarshalTestData = []struct {
-	in  []byte
-	out interface{}
-}{
-	{[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
-	{[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
-	{[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
-	{[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}},
-	{[]byte{0x02, 0x01, 0x10}, newInt(16)},
-	{[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")},
-	{[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")},
-	{[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}},
-	{[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}},
-	{[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}},
-	{[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}},
-	{[]byte{0x01, 0x01, 0x00}, newBool(false)},
-	{[]byte{0x01, 0x01, 0x01}, newBool(true)},
-	{[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
-}
-
-func TestUnmarshal(t *testing.T) {
-	for i, test := range unmarshalTestData {
-		pv := reflect.New(reflect.TypeOf(test.out).Elem())
-		val := pv.Interface()
-		_, err := Unmarshal(test.in, val)
-		if err != nil {
-			t.Errorf("Unmarshal failed at index %d %v", i, err)
-		}
-		if !reflect.DeepEqual(val, test.out) {
-			t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out)
-		}
-	}
-}
-
-type Certificate struct {
-	TBSCertificate     TBSCertificate
-	SignatureAlgorithm AlgorithmIdentifier
-	SignatureValue     BitString
-}
-
-type TBSCertificate struct {
-	Version            int `asn1:"optional,explicit,default:0,tag:0"`
-	SerialNumber       RawValue
-	SignatureAlgorithm AlgorithmIdentifier
-	Issuer             RDNSequence
-	Validity           Validity
-	Subject            RDNSequence
-	PublicKey          PublicKeyInfo
-}
-
-type AlgorithmIdentifier struct {
-	Algorithm ObjectIdentifier
-}
-
-type RDNSequence []RelativeDistinguishedNameSET
-
-type RelativeDistinguishedNameSET []AttributeTypeAndValue
-
-type AttributeTypeAndValue struct {
-	Type  ObjectIdentifier
-	Value interface{}
-}
-
-type Validity struct {
-	NotBefore, NotAfter *time.Time
-}
-
-type PublicKeyInfo struct {
-	Algorithm AlgorithmIdentifier
-	PublicKey BitString
-}
-
-func TestCertificate(t *testing.T) {
-	// This is a minimal, self-signed certificate that should parse correctly.
-	var cert Certificate
-	if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil {
-		t.Errorf("Unmarshal failed: %v", err)
-	}
-	if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) {
-		t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert)
-	}
-}
-
-func TestCertificateWithNUL(t *testing.T) {
-	// This is the paypal NUL-hack certificate. It should fail to parse because
-	// NUL isn't a permitted character in a PrintableString.
-
-	var cert Certificate
-	if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil {
-		t.Error("Unmarshal succeeded, should not have")
-	}
-}
-
-type rawStructTest struct {
-	Raw RawContent
-	A   int
-}
-
-func TestRawStructs(t *testing.T) {
-	var s rawStructTest
-	input := []byte{0x30, 0x03, 0x02, 0x01, 0x50}
-
-	rest, err := Unmarshal(input, &s)
-	if len(rest) != 0 {
-		t.Errorf("incomplete parse: %x", rest)
-		return
-	}
-	if err != nil {
-		t.Error(err)
-		return
-	}
-	if s.A != 0x50 {
-		t.Errorf("bad value for A: got %d want %d", s.A, 0x50)
-	}
-	if bytes.Compare([]byte(s.Raw), input) != 0 {
-		t.Errorf("bad value for Raw: got %x want %x", s.Raw, input)
-	}
-}
-
-var derEncodedSelfSignedCert = Certificate{
-	TBSCertificate: TBSCertificate{
-		Version:            0,
-		SerialNumber:       RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}},
-		SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
-		Issuer: RDNSequence{
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false at example.com"}},
-		},
-		Validity: Validity{NotBefore: &time.Time{Year: 2009, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}, NotAfter: &time.Time{Year: 2010, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}},
-		Subject: RDNSequence{
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
-			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false at example.com"}},
-		},
-		PublicKey: PublicKeyInfo{
-			Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}},
-			PublicKey: BitString{
-				Bytes: []uint8{
-					0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7,
-					0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42,
-					0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4,
-					0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2,
-					0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f,
-					0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec,
-					0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1,
-				},
-				BitLength: 592,
-			},
-		},
-	},
-	SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
-	SignatureValue: BitString{
-		Bytes: []uint8{
-			0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce,
-			0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c,
-			0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b,
-			0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8,
-			0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa,
-			0xfa, 0x88, 0x21, 0x49, 0x4, 0x35,
-		},
-		BitLength: 512,
-	},
-}
-
-var derEncodedSelfSignedCertBytes = []byte{
-	0x30, 0x82, 0x02, 0x18, 0x30,
-	0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c,
-	0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
-	0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-	0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
-	0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
-	0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43,
-	0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
-	0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
-	0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31,
-	0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c,
-	0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
-	0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-	0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78,
-	0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
-	0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a,
-	0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35,
-	0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
-	0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
-	0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
-	0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69,
-	0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
-	0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
-	0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a,
-	0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73,
-	0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
-	0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-	0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61,
-	0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06,
-	0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
-	0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78,
-	0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c,
-	0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea,
-	0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88,
-	0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45,
-	0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d,
-	0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
-	0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4,
-	0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd,
-	0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4,
-	0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14,
-	0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49,
-	0x04, 0x35,
-}
-
-var derEncodedPaypalNULCertBytes = []byte{
-	0x30, 0x82, 0x06, 0x44, 0x30,
-	0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b,
-	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
-	0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-	0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
-	0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61,
-	0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61,
-	0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03,
-	0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74,
-	0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74,
-	0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e,
-	0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65,
-	0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d,
-	0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36,
-	0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03,
-	0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c,
-	0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
-	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
-	0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
-	0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
-	0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
-	0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
-	0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
-	0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70,
-	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39,
-	0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d,
-	0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a,
-	0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
-	0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
-	0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
-	0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20,
-	0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f,
-	0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
-	0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
-	0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f,
-	0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e,
-	0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73,
-	0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d,
-	0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
-	0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69,
-	0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19,
-	0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e,
-	0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29,
-	0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41,
-	0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce,
-	0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96,
-	0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2,
-	0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10,
-	0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49,
-	0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00,
-	0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03,
-	0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86,
-	0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40,
-	0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8,
-	0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08,
-	0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55,
-	0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14,
-	0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e,
-	0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
-	0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8,
-	0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
-	0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04,
-	0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40,
-	0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63,
-	0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
-	0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e,
-	0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e,
-	0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76,
-	0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
-	0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68,
-	0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
-	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60,
-	0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68,
-	0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
-	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
-	0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
-	0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70,
-	0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61,
-	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30,
-	0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c,
-	0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37,
-	0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
-	0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
-	0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74,
-	0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
-	0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
-	0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63,
-	0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f,
-	0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
-	0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86,
-	0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74,
-	0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73,
-	0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32,
-	0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41,
-	0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06,
-	0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0,
-	0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
-	0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70,
-	0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
-	0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63,
-	0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74,
-	0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69,
-	0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
-	0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30,
-	0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c,
-	0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
-	0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
-	0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63,
-	0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
-	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
-	0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b,
-	0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa,
-	0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e,
-	0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d,
-	0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7,
-	0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1,
-	0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5,
-	0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07,
-	0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e,
-	0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43,
-	0x96, 0x07, 0xa8, 0xbb,
-}
diff --git a/src/pkg/asn1/common.go b/src/pkg/asn1/common.go
deleted file mode 100644
index 01f4f7b..0000000
--- a/src/pkg/asn1/common.go
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package asn1
-
-import (
-	"reflect"
-	"strconv"
-	"strings"
-)
-
-// ASN.1 objects have metadata preceding them:
-//   the tag: the type of the object
-//   a flag denoting if this object is compound or not
-//   the class type: the namespace of the tag
-//   the length of the object, in bytes
-
-// Here are some standard tags and classes
-
-const (
-	tagBoolean         = 1
-	tagInteger         = 2
-	tagBitString       = 3
-	tagOctetString     = 4
-	tagOID             = 6
-	tagEnum            = 10
-	tagUTF8String      = 12
-	tagSequence        = 16
-	tagSet             = 17
-	tagPrintableString = 19
-	tagT61String       = 20
-	tagIA5String       = 22
-	tagUTCTime         = 23
-	tagGeneralizedTime = 24
-	tagGeneralString   = 27
-)
-
-const (
-	classUniversal       = 0
-	classApplication     = 1
-	classContextSpecific = 2
-	classPrivate         = 3
-)
-
-type tagAndLength struct {
-	class, tag, length int
-	isCompound         bool
-}
-
-// ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead
-// of" and "in addition to". When not specified, every primitive type has a
-// default tag in the UNIVERSAL class.
-//
-// For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1
-// doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT
-// CONTEXT-SPECIFIC 42], that means that the tag is replaced by another.
-//
-// On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an
-// /additional/ tag would wrap the default tag. This explicit tag will have the
-// compound flag set.
-//
-// (This is used in order to remove ambiguity with optional elements.)
-//
-// You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we
-// don't support that here. We support a single layer of EXPLICIT or IMPLICIT
-// tagging with tag strings on the fields of a structure.
-
-// fieldParameters is the parsed representation of tag string from a structure field.
-type fieldParameters struct {
-	optional     bool   // true iff the field is OPTIONAL
-	explicit     bool   // true iff an EXPLICIT tag is in use.
-	application  bool   // true iff an APPLICATION tag is in use.
-	defaultValue *int64 // a default value for INTEGER typed fields (maybe nil).
-	tag          *int   // the EXPLICIT or IMPLICIT tag (maybe nil).
-	stringType   int    // the string tag to use when marshaling.
-	set          bool   // true iff this should be encoded as a SET
-
-	// Invariants:
-	//   if explicit is set, tag is non-nil.
-}
-
-// Given a tag string with the format specified in the package comment,
-// parseFieldParameters will parse it into a fieldParameters structure,
-// ignoring unknown parts of the string.
-func parseFieldParameters(str string) (ret fieldParameters) {
-	for _, part := range strings.Split(str, ",") {
-		switch {
-		case part == "optional":
-			ret.optional = true
-		case part == "explicit":
-			ret.explicit = true
-			if ret.tag == nil {
-				ret.tag = new(int)
-			}
-		case part == "ia5":
-			ret.stringType = tagIA5String
-		case part == "printable":
-			ret.stringType = tagPrintableString
-		case strings.HasPrefix(part, "default:"):
-			i, err := strconv.Atoi64(part[8:])
-			if err == nil {
-				ret.defaultValue = new(int64)
-				*ret.defaultValue = i
-			}
-		case strings.HasPrefix(part, "tag:"):
-			i, err := strconv.Atoi(part[4:])
-			if err == nil {
-				ret.tag = new(int)
-				*ret.tag = i
-			}
-		case part == "set":
-			ret.set = true
-		case part == "application":
-			ret.application = true
-			if ret.tag == nil {
-				ret.tag = new(int)
-			}
-		}
-	}
-	return
-}
-
-// Given a reflected Go type, getUniversalType returns the default tag number
-// and expected compound flag.
-func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
-	switch t {
-	case objectIdentifierType:
-		return tagOID, false, true
-	case bitStringType:
-		return tagBitString, false, true
-	case timeType:
-		return tagUTCTime, false, true
-	case enumeratedType:
-		return tagEnum, false, true
-	case bigIntType:
-		return tagInteger, false, true
-	}
-	switch t.Kind() {
-	case reflect.Bool:
-		return tagBoolean, false, true
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return tagInteger, false, true
-	case reflect.Struct:
-		return tagSequence, true, true
-	case reflect.Slice:
-		if t.Elem().Kind() == reflect.Uint8 {
-			return tagOctetString, false, true
-		}
-		if strings.HasSuffix(t.Name(), "SET") {
-			return tagSet, true, true
-		}
-		return tagSequence, true, true
-	case reflect.String:
-		return tagPrintableString, false, true
-	}
-	return 0, false, false
-}
diff --git a/src/pkg/asn1/marshal.go b/src/pkg/asn1/marshal.go
deleted file mode 100644
index d7eb63b..0000000
--- a/src/pkg/asn1/marshal.go
+++ /dev/null
@@ -1,544 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package asn1
-
-import (
-	"big"
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"reflect"
-	"time"
-)
-
-// A forkableWriter is an in-memory buffer that can be
-// 'forked' to create new forkableWriters that bracket the
-// original.  After
-//    pre, post := w.fork();
-// the overall sequence of bytes represented is logically w+pre+post.
-type forkableWriter struct {
-	*bytes.Buffer
-	pre, post *forkableWriter
-}
-
-func newForkableWriter() *forkableWriter {
-	return &forkableWriter{bytes.NewBuffer(nil), nil, nil}
-}
-
-func (f *forkableWriter) fork() (pre, post *forkableWriter) {
-	if f.pre != nil || f.post != nil {
-		panic("have already forked")
-	}
-	f.pre = newForkableWriter()
-	f.post = newForkableWriter()
-	return f.pre, f.post
-}
-
-func (f *forkableWriter) Len() (l int) {
-	l += f.Buffer.Len()
-	if f.pre != nil {
-		l += f.pre.Len()
-	}
-	if f.post != nil {
-		l += f.post.Len()
-	}
-	return
-}
-
-func (f *forkableWriter) writeTo(out io.Writer) (n int, err os.Error) {
-	n, err = out.Write(f.Bytes())
-	if err != nil {
-		return
-	}
-
-	var nn int
-
-	if f.pre != nil {
-		nn, err = f.pre.writeTo(out)
-		n += nn
-		if err != nil {
-			return
-		}
-	}
-
-	if f.post != nil {
-		nn, err = f.post.writeTo(out)
-		n += nn
-	}
-	return
-}
-
-func marshalBase128Int(out *forkableWriter, n int64) (err os.Error) {
-	if n == 0 {
-		err = out.WriteByte(0)
-		return
-	}
-
-	l := 0
-	for i := n; i > 0; i >>= 7 {
-		l++
-	}
-
-	for i := l - 1; i >= 0; i-- {
-		o := byte(n >> uint(i*7))
-		o &= 0x7f
-		if i != 0 {
-			o |= 0x80
-		}
-		err = out.WriteByte(o)
-		if err != nil {
-			return
-		}
-	}
-
-	return nil
-}
-
-func marshalInt64(out *forkableWriter, i int64) (err os.Error) {
-	n := int64Length(i)
-
-	for ; n > 0; n-- {
-		err = out.WriteByte(byte(i >> uint((n-1)*8)))
-		if err != nil {
-			return
-		}
-	}
-
-	return nil
-}
-
-func int64Length(i int64) (numBytes int) {
-	numBytes = 1
-
-	for i > 127 {
-		numBytes++
-		i >>= 8
-	}
-
-	for i < -128 {
-		numBytes++
-		i >>= 8
-	}
-
-	return
-}
-
-func marshalBigInt(out *forkableWriter, n *big.Int) (err os.Error) {
-	if n.Sign() < 0 {
-		// A negative number has to be converted to two's-complement
-		// form. So we'll subtract 1 and invert. If the
-		// most-significant-bit isn't set then we'll need to pad the
-		// beginning with 0xff in order to keep the number negative.
-		nMinus1 := new(big.Int).Neg(n)
-		nMinus1.Sub(nMinus1, bigOne)
-		bytes := nMinus1.Bytes()
-		for i := range bytes {
-			bytes[i] ^= 0xff
-		}
-		if len(bytes) == 0 || bytes[0]&0x80 == 0 {
-			err = out.WriteByte(0xff)
-			if err != nil {
-				return
-			}
-		}
-		_, err = out.Write(bytes)
-	} else if n.Sign() == 0 {
-		// Zero is written as a single 0 zero rather than no bytes.
-		err = out.WriteByte(0x00)
-	} else {
-		bytes := n.Bytes()
-		if len(bytes) > 0 && bytes[0]&0x80 != 0 {
-			// We'll have to pad this with 0x00 in order to stop it
-			// looking like a negative number.
-			err = out.WriteByte(0)
-			if err != nil {
-				return
-			}
-		}
-		_, err = out.Write(bytes)
-	}
-	return
-}
-
-func marshalLength(out *forkableWriter, i int) (err os.Error) {
-	n := lengthLength(i)
-
-	for ; n > 0; n-- {
-		err = out.WriteByte(byte(i >> uint((n-1)*8)))
-		if err != nil {
-			return
-		}
-	}
-
-	return nil
-}
-
-func lengthLength(i int) (numBytes int) {
-	numBytes = 1
-	for i > 255 {
-		numBytes++
-		i >>= 8
-	}
-	return
-}
-
-func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err os.Error) {
-	b := uint8(t.class) << 6
-	if t.isCompound {
-		b |= 0x20
-	}
-	if t.tag >= 31 {
-		b |= 0x1f
-		err = out.WriteByte(b)
-		if err != nil {
-			return
-		}
-		err = marshalBase128Int(out, int64(t.tag))
-		if err != nil {
-			return
-		}
-	} else {
-		b |= uint8(t.tag)
-		err = out.WriteByte(b)
-		if err != nil {
-			return
-		}
-	}
-
-	if t.length >= 128 {
-		l := lengthLength(t.length)
-		err = out.WriteByte(0x80 | byte(l))
-		if err != nil {
-			return
-		}
-		err = marshalLength(out, t.length)
-		if err != nil {
-			return
-		}
-	} else {
-		err = out.WriteByte(byte(t.length))
-		if err != nil {
-			return
-		}
-	}
-
-	return nil
-}
-
-func marshalBitString(out *forkableWriter, b BitString) (err os.Error) {
-	paddingBits := byte((8 - b.BitLength%8) % 8)
-	err = out.WriteByte(paddingBits)
-	if err != nil {
-		return
-	}
-	_, err = out.Write(b.Bytes)
-	return
-}
-
-func marshalObjectIdentifier(out *forkableWriter, oid []int) (err os.Error) {
-	if len(oid) < 2 || oid[0] > 6 || oid[1] >= 40 {
-		return StructuralError{"invalid object identifier"}
-	}
-
-	err = out.WriteByte(byte(oid[0]*40 + oid[1]))
-	if err != nil {
-		return
-	}
-	for i := 2; i < len(oid); i++ {
-		err = marshalBase128Int(out, int64(oid[i]))
-		if err != nil {
-			return
-		}
-	}
-
-	return
-}
-
-func marshalPrintableString(out *forkableWriter, s string) (err os.Error) {
-	b := []byte(s)
-	for _, c := range b {
-		if !isPrintable(c) {
-			return StructuralError{"PrintableString contains invalid character"}
-		}
-	}
-
-	_, err = out.Write(b)
-	return
-}
-
-func marshalIA5String(out *forkableWriter, s string) (err os.Error) {
-	b := []byte(s)
-	for _, c := range b {
-		if c > 127 {
-			return StructuralError{"IA5String contains invalid character"}
-		}
-	}
-
-	_, err = out.Write(b)
-	return
-}
-
-func marshalTwoDigits(out *forkableWriter, v int) (err os.Error) {
-	err = out.WriteByte(byte('0' + (v/10)%10))
-	if err != nil {
-		return
-	}
-	return out.WriteByte(byte('0' + v%10))
-}
-
-func marshalUTCTime(out *forkableWriter, t *time.Time) (err os.Error) {
-	switch {
-	case 1950 <= t.Year && t.Year < 2000:
-		err = marshalTwoDigits(out, int(t.Year-1900))
-	case 2000 <= t.Year && t.Year < 2050:
-		err = marshalTwoDigits(out, int(t.Year-2000))
-	default:
-		return StructuralError{"Cannot represent time as UTCTime"}
-	}
-
-	if err != nil {
-		return
-	}
-
-	err = marshalTwoDigits(out, t.Month)
-	if err != nil {
-		return
-	}
-
-	err = marshalTwoDigits(out, t.Day)
-	if err != nil {
-		return
-	}
-
-	err = marshalTwoDigits(out, t.Hour)
-	if err != nil {
-		return
-	}
-
-	err = marshalTwoDigits(out, t.Minute)
-	if err != nil {
-		return
-	}
-
-	err = marshalTwoDigits(out, t.Second)
-	if err != nil {
-		return
-	}
-
-	switch {
-	case t.ZoneOffset/60 == 0:
-		err = out.WriteByte('Z')
-		return
-	case t.ZoneOffset > 0:
-		err = out.WriteByte('+')
-	case t.ZoneOffset < 0:
-		err = out.WriteByte('-')
-	}
-
-	if err != nil {
-		return
-	}
-
-	offsetMinutes := t.ZoneOffset / 60
-	if offsetMinutes < 0 {
-		offsetMinutes = -offsetMinutes
-	}
-
-	err = marshalTwoDigits(out, offsetMinutes/60)
-	if err != nil {
-		return
-	}
-
-	err = marshalTwoDigits(out, offsetMinutes%60)
-	return
-}
-
-func stripTagAndLength(in []byte) []byte {
-	_, offset, err := parseTagAndLength(in, 0)
-	if err != nil {
-		return in
-	}
-	return in[offset:]
-}
-
-func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err os.Error) {
-	switch value.Type() {
-	case timeType:
-		return marshalUTCTime(out, value.Interface().(*time.Time))
-	case bitStringType:
-		return marshalBitString(out, value.Interface().(BitString))
-	case objectIdentifierType:
-		return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
-	case bigIntType:
-		return marshalBigInt(out, value.Interface().(*big.Int))
-	}
-
-	switch v := value; v.Kind() {
-	case reflect.Bool:
-		if v.Bool() {
-			return out.WriteByte(255)
-		} else {
-			return out.WriteByte(0)
-		}
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return marshalInt64(out, int64(v.Int()))
-	case reflect.Struct:
-		t := v.Type()
-
-		startingField := 0
-
-		// If the first element of the structure is a non-empty
-		// RawContents, then we don't bother serializing the rest.
-		if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
-			s := v.Field(0)
-			if s.Len() > 0 {
-				bytes := make([]byte, s.Len())
-				for i := 0; i < s.Len(); i++ {
-					bytes[i] = uint8(s.Index(i).Uint())
-				}
-				/* The RawContents will contain the tag and
-				 * length fields but we'll also be writing
-				 * those ourselves, so we strip them out of
-				 * bytes */
-				_, err = out.Write(stripTagAndLength(bytes))
-				return
-			} else {
-				startingField = 1
-			}
-		}
-
-		for i := startingField; i < t.NumField(); i++ {
-			var pre *forkableWriter
-			pre, out = out.fork()
-			err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
-			if err != nil {
-				return
-			}
-		}
-		return
-	case reflect.Slice:
-		sliceType := v.Type()
-		if sliceType.Elem().Kind() == reflect.Uint8 {
-			bytes := make([]byte, v.Len())
-			for i := 0; i < v.Len(); i++ {
-				bytes[i] = uint8(v.Index(i).Uint())
-			}
-			_, err = out.Write(bytes)
-			return
-		}
-
-		var params fieldParameters
-		for i := 0; i < v.Len(); i++ {
-			var pre *forkableWriter
-			pre, out = out.fork()
-			err = marshalField(pre, v.Index(i), params)
-			if err != nil {
-				return
-			}
-		}
-		return
-	case reflect.String:
-		if params.stringType == tagIA5String {
-			return marshalIA5String(out, v.String())
-		} else {
-			return marshalPrintableString(out, v.String())
-		}
-		return
-	}
-
-	return StructuralError{"unknown Go type"}
-}
-
-func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err os.Error) {
-	// If the field is an interface{} then recurse into it.
-	if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
-		return marshalField(out, v.Elem(), params)
-	}
-
-	if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
-		return
-	}
-
-	if v.Type() == rawValueType {
-		rv := v.Interface().(RawValue)
-		err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
-		if err != nil {
-			return
-		}
-		_, err = out.Write(rv.Bytes)
-		return
-	}
-
-	tag, isCompound, ok := getUniversalType(v.Type())
-	if !ok {
-		err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
-		return
-	}
-	class := classUniversal
-
-	if params.stringType != 0 {
-		if tag != tagPrintableString {
-			return StructuralError{"Explicit string type given to non-string member"}
-		}
-		tag = params.stringType
-	}
-
-	if params.set {
-		if tag != tagSequence {
-			return StructuralError{"Non sequence tagged as set"}
-		}
-		tag = tagSet
-	}
-
-	tags, body := out.fork()
-
-	err = marshalBody(body, v, params)
-	if err != nil {
-		return
-	}
-
-	bodyLen := body.Len()
-
-	var explicitTag *forkableWriter
-	if params.explicit {
-		explicitTag, tags = tags.fork()
-	}
-
-	if !params.explicit && params.tag != nil {
-		// implicit tag.
-		tag = *params.tag
-		class = classContextSpecific
-	}
-
-	err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
-	if err != nil {
-		return
-	}
-
-	if params.explicit {
-		err = marshalTagAndLength(explicitTag, tagAndLength{
-			class:      classContextSpecific,
-			tag:        *params.tag,
-			length:     bodyLen + tags.Len(),
-			isCompound: true,
-		})
-	}
-
-	return nil
-}
-
-// Marshal returns the ASN.1 encoding of val.
-func Marshal(val interface{}) ([]byte, os.Error) {
-	var out bytes.Buffer
-	v := reflect.ValueOf(val)
-	f := newForkableWriter()
-	err := marshalField(f, v, fieldParameters{})
-	if err != nil {
-		return nil, err
-	}
-	_, err = f.writeTo(&out)
-	return out.Bytes(), nil
-}
diff --git a/src/pkg/asn1/marshal_test.go b/src/pkg/asn1/marshal_test.go
deleted file mode 100644
index 03df5f1..0000000
--- a/src/pkg/asn1/marshal_test.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package asn1
-
-import (
-	"bytes"
-	"encoding/hex"
-	"testing"
-	"time"
-)
-
-type intStruct struct {
-	A int
-}
-
-type twoIntStruct struct {
-	A int
-	B int
-}
-
-type nestedStruct struct {
-	A intStruct
-}
-
-type rawContentsStruct struct {
-	Raw RawContent
-	A   int
-}
-
-type implicitTagTest struct {
-	A int `asn1:"implicit,tag:5"`
-}
-
-type explicitTagTest struct {
-	A int `asn1:"explicit,tag:5"`
-}
-
-type ia5StringTest struct {
-	A string `asn1:"ia5"`
-}
-
-type printableStringTest struct {
-	A string `asn1:"printable"`
-}
-
-type optionalRawValueTest struct {
-	A RawValue `asn1:"optional"`
-}
-
-type testSET []int
-
-func setPST(t *time.Time) *time.Time {
-	t.ZoneOffset = -28800
-	return t
-}
-
-type marshalTest struct {
-	in  interface{}
-	out string // hex encoded
-}
-
-var marshalTests = []marshalTest{
-	{10, "02010a"},
-	{127, "02017f"},
-	{128, "02020080"},
-	{-128, "020180"},
-	{-129, "0202ff7f"},
-	{intStruct{64}, "3003020140"},
-	{twoIntStruct{64, 65}, "3006020140020141"},
-	{nestedStruct{intStruct{127}}, "3005300302017f"},
-	{[]byte{1, 2, 3}, "0403010203"},
-	{implicitTagTest{64}, "3003850140"},
-	{explicitTagTest{64}, "3005a503020140"},
-	{time.SecondsToUTC(0), "170d3730303130313030303030305a"},
-	{time.SecondsToUTC(1258325776), "170d3039313131353232353631365a"},
-	{setPST(time.SecondsToUTC(1258325776)), "17113039313131353232353631362d30383030"},
-	{BitString{[]byte{0x80}, 1}, "03020780"},
-	{BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"},
-	{ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"},
-	{ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"},
-	{"test", "130474657374"},
-	{
-		"" +
-			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
-			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
-			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
-			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 127 times 'x'
-		"137f" +
-			"7878787878787878787878787878787878787878787878787878787878787878" +
-			"7878787878787878787878787878787878787878787878787878787878787878" +
-			"7878787878787878787878787878787878787878787878787878787878787878" +
-			"78787878787878787878787878787878787878787878787878787878787878",
-	},
-	{
-		"" +
-			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
-			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
-			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
-			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 128 times 'x'
-		"138180" +
-			"7878787878787878787878787878787878787878787878787878787878787878" +
-			"7878787878787878787878787878787878787878787878787878787878787878" +
-			"7878787878787878787878787878787878787878787878787878787878787878" +
-			"7878787878787878787878787878787878787878787878787878787878787878",
-	},
-	{ia5StringTest{"test"}, "3006160474657374"},
-	{optionalRawValueTest{}, "3000"},
-	{printableStringTest{"test"}, "3006130474657374"},
-	{printableStringTest{"test*"}, "30071305746573742a"},
-	{rawContentsStruct{nil, 64}, "3003020140"},
-	{rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"},
-	{RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"},
-	{testSET([]int{10}), "310302010a"},
-}
-
-func TestMarshal(t *testing.T) {
-	for i, test := range marshalTests {
-		data, err := Marshal(test.in)
-		if err != nil {
-			t.Errorf("#%d failed: %s", i, err)
-		}
-		out, _ := hex.DecodeString(test.out)
-		if bytes.Compare(out, data) != 0 {
-			t.Errorf("#%d got: %x want %x", i, data, out)
-		}
-	}
-}
diff --git a/src/pkg/big/Makefile b/src/pkg/big/Makefile
deleted file mode 100644
index 3d4b56d..0000000
--- a/src/pkg/big/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=big
-GOFILES=\
-	arith.go\
-	arith_decl.go\
-	int.go\
-	nat.go\
-	rat.go\
-
-OFILES=\
-	arith_$(GOARCH).$O\
-
-include ../../Make.pkg
diff --git a/src/pkg/big/arith.go b/src/pkg/big/arith.go
deleted file mode 100644
index 0a02a4e..0000000
--- a/src/pkg/big/arith.go
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file provides Go implementations of elementary multi-precision
-// arithmetic operations on word vectors. Needed for platforms without
-// assembly implementations of these routines.
-
-package big
-
-// TODO(gri) Decide if Word needs to remain exported.
-
-type Word uintptr
-
-const (
-	// Compute the size _S of a Word in bytes.
-	_m    = ^Word(0)
-	_logS = _m>>8&1 + _m>>16&1 + _m>>32&1
-	_S    = 1 << _logS
-
-	_W = _S << 3 // word size in bits
-	_B = 1 << _W // digit base
-	_M = _B - 1  // digit mask
-
-	_W2 = _W / 2   // half word size in bits
-	_B2 = 1 << _W2 // half digit base
-	_M2 = _B2 - 1  // half digit mask
-)
-
-// ----------------------------------------------------------------------------
-// Elementary operations on words
-//
-// These operations are used by the vector operations below.
-
-// z1<<_W + z0 = x+y+c, with c == 0 or 1
-func addWW_g(x, y, c Word) (z1, z0 Word) {
-	yc := y + c
-	z0 = x + yc
-	if z0 < x || yc < y {
-		z1 = 1
-	}
-	return
-}
-
-// z1<<_W + z0 = x-y-c, with c == 0 or 1
-func subWW_g(x, y, c Word) (z1, z0 Word) {
-	yc := y + c
-	z0 = x - yc
-	if z0 > x || yc < y {
-		z1 = 1
-	}
-	return
-}
-
-// z1<<_W + z0 = x*y
-// Adapted from Warren, Hacker's Delight, p. 132.
-func mulWW_g(x, y Word) (z1, z0 Word) {
-	x0 := x & _M2
-	x1 := x >> _W2
-	y0 := y & _M2
-	y1 := y >> _W2
-	w0 := x0 * y0
-	t := x1*y0 + w0>>_W2
-	w1 := t & _M2
-	w2 := t >> _W2
-	w1 += x0 * y1
-	z1 = x1*y1 + w2 + w1>>_W2
-	z0 = x * y
-	return
-}
-
-// z1<<_W + z0 = x*y + c
-func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
-	z1, zz0 := mulWW(x, y)
-	if z0 = zz0 + c; z0 < zz0 {
-		z1++
-	}
-	return
-}
-
-// Length of x in bits.
-func bitLen(x Word) (n int) {
-	for ; x >= 0x100; x >>= 8 {
-		n += 8
-	}
-	for ; x > 0; x >>= 1 {
-		n++
-	}
-	return
-}
-
-// log2 computes the integer binary logarithm of x.
-// The result is the integer n for which 2^n <= x < 2^(n+1).
-// If x == 0, the result is -1.
-func log2(x Word) int {
-	return bitLen(x) - 1
-}
-
-// Number of leading zeros in x.
-func leadingZeros(x Word) uint {
-	return uint(_W - bitLen(x))
-}
-
-// q = (u1<<_W + u0 - r)/y
-// Adapted from Warren, Hacker's Delight, p. 152.
-func divWW_g(u1, u0, v Word) (q, r Word) {
-	if u1 >= v {
-		return 1<<_W - 1, 1<<_W - 1
-	}
-
-	s := leadingZeros(v)
-	v <<= s
-
-	vn1 := v >> _W2
-	vn0 := v & _M2
-	un32 := u1<<s | u0>>(_W-s)
-	un10 := u0 << s
-	un1 := un10 >> _W2
-	un0 := un10 & _M2
-	q1 := un32 / vn1
-	rhat := un32 - q1*vn1
-
-again1:
-	if q1 >= _B2 || q1*vn0 > _B2*rhat+un1 {
-		q1--
-		rhat += vn1
-		if rhat < _B2 {
-			goto again1
-		}
-	}
-
-	un21 := un32*_B2 + un1 - q1*v
-	q0 := un21 / vn1
-	rhat = un21 - q0*vn1
-
-again2:
-	if q0 >= _B2 || q0*vn0 > _B2*rhat+un0 {
-		q0--
-		rhat += vn1
-		if rhat < _B2 {
-			goto again2
-		}
-	}
-
-	return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s
-}
-
-func addVV_g(z, x, y []Word) (c Word) {
-	for i := range z {
-		c, z[i] = addWW_g(x[i], y[i], c)
-	}
-	return
-}
-
-func subVV_g(z, x, y []Word) (c Word) {
-	for i := range z {
-		c, z[i] = subWW_g(x[i], y[i], c)
-	}
-	return
-}
-
-func addVW_g(z, x []Word, y Word) (c Word) {
-	c = y
-	for i := range z {
-		c, z[i] = addWW_g(x[i], c, 0)
-	}
-	return
-}
-
-func subVW_g(z, x []Word, y Word) (c Word) {
-	c = y
-	for i := range z {
-		c, z[i] = subWW_g(x[i], c, 0)
-	}
-	return
-}
-
-func shlVU_g(z, x []Word, s uint) (c Word) {
-	if n := len(z); n > 0 {
-		ŝ := _W - s
-		w1 := x[n-1]
-		c = w1 >> ŝ
-		for i := n - 1; i > 0; i-- {
-			w := w1
-			w1 = x[i-1]
-			z[i] = w<<s | w1>>ŝ
-		}
-		z[0] = w1 << s
-	}
-	return
-}
-
-func shrVU_g(z, x []Word, s uint) (c Word) {
-	if n := len(z); n > 0 {
-		ŝ := _W - s
-		w1 := x[0]
-		c = w1 << ŝ
-		for i := 0; i < n-1; i++ {
-			w := w1
-			w1 = x[i+1]
-			z[i] = w>>s | w1<<ŝ
-		}
-		z[n-1] = w1 >> s
-	}
-	return
-}
-
-func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
-	c = r
-	for i := range z {
-		c, z[i] = mulAddWWW_g(x[i], y, c)
-	}
-	return
-}
-
-func addMulVVW_g(z, x []Word, y Word) (c Word) {
-	for i := range z {
-		z1, z0 := mulAddWWW_g(x[i], y, z[i])
-		c, z[i] = addWW_g(z0, c, 0)
-		c += z1
-	}
-	return
-}
-
-func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) {
-	r = xn
-	for i := len(z) - 1; i >= 0; i-- {
-		z[i], r = divWW_g(r, x[i], y)
-	}
-	return
-}
diff --git a/src/pkg/big/arith_386.s b/src/pkg/big/arith_386.s
deleted file mode 100644
index 07c07b0..0000000
--- a/src/pkg/big/arith_386.s
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file provides fast assembly versions for the elementary
-// arithmetic operations on vectors implemented in arith.go.
-
-// func mulWW(x, y Word) (z1, z0 Word)
-TEXT ·mulWW(SB),7,$0
-	MOVL x+0(FP), AX
-	MULL y+4(FP)
-	MOVL DX, z1+8(FP)
-	MOVL AX, z0+12(FP)
-	RET
-
-
-// func divWW(x1, x0, y Word) (q, r Word)
-TEXT ·divWW(SB),7,$0
-	MOVL x1+0(FP), DX
-	MOVL x0+4(FP), AX
-	DIVL y+8(FP)
-	MOVL AX, q+12(FP)
-	MOVL DX, r+16(FP)
-	RET
-
-
-// func addVV(z, x, y []Word) (c Word)
-TEXT ·addVV(SB),7,$0
-	MOVL z+0(FP), DI
-	MOVL x+12(FP), SI
-	MOVL y+24(FP), CX
-	MOVL n+4(FP), BP
-	MOVL $0, BX		// i = 0
-	MOVL $0, DX		// c = 0
-	JMP E1
-
-L1:	MOVL (SI)(BX*4), AX
-	RCRL $1, DX
-	ADCL (CX)(BX*4), AX
-	RCLL $1, DX
-	MOVL AX, (DI)(BX*4)
-	ADDL $1, BX		// i++
-
-E1:	CMPL BX, BP		// i < n
-	JL L1
-
-	MOVL DX, c+36(FP)
-	RET
-
-
-// func subVV(z, x, y []Word) (c Word)
-// (same as addVV except for SBBL instead of ADCL and label names)
-TEXT ·subVV(SB),7,$0
-	MOVL z+0(FP), DI
-	MOVL x+12(FP), SI
-	MOVL y+24(FP), CX
-	MOVL n+4(FP), BP
-	MOVL $0, BX		// i = 0
-	MOVL $0, DX		// c = 0
-	JMP E2
-
-L2:	MOVL (SI)(BX*4), AX
-	RCRL $1, DX
-	SBBL (CX)(BX*4), AX
-	RCLL $1, DX
-	MOVL AX, (DI)(BX*4)
-	ADDL $1, BX		// i++
-
-E2:	CMPL BX, BP		// i < n
-	JL L2
-
-	MOVL DX, c+36(FP)
-	RET
-
-
-// func addVW(z, x []Word, y Word) (c Word)
-TEXT ·addVW(SB),7,$0
-	MOVL z+0(FP), DI
-	MOVL x+12(FP), SI
-	MOVL y+24(FP), AX	// c = y
-	MOVL n+4(FP), BP
-	MOVL $0, BX		// i = 0
-	JMP E3
-
-L3:	ADDL (SI)(BX*4), AX
-	MOVL AX, (DI)(BX*4)
-	RCLL $1, AX
-	ANDL $1, AX
-	ADDL $1, BX		// i++
-
-E3:	CMPL BX, BP		// i < n
-	JL L3
-
-	MOVL AX, c+28(FP)
-	RET
-
-
-// func subVW(z, x []Word, y Word) (c Word)
-TEXT ·subVW(SB),7,$0
-	MOVL z+0(FP), DI
-	MOVL x+12(FP), SI
-	MOVL y+24(FP), AX	// c = y
-	MOVL n+4(FP), BP
-	MOVL $0, BX		// i = 0
-	JMP E4
-
-L4:	MOVL (SI)(BX*4), DX	// TODO(gri) is there a reverse SUBL?
-	SUBL AX, DX
-	MOVL DX, (DI)(BX*4)
-	RCLL $1, AX
-	ANDL $1, AX
-	ADDL $1, BX		// i++
-
-E4:	CMPL BX, BP		// i < n
-	JL L4
-
-	MOVL AX, c+28(FP)
-	RET
-
-
-// func shlVU(z, x []Word, s uint) (c Word)
-TEXT ·shlVU(SB),7,$0
-	MOVL n+4(FP), BX	// i = n
-	SUBL $1, BX		// i--
-	JL X8b			// i < 0	(n <= 0)
-
-	// n > 0
-	MOVL z+0(FP), DI
-	MOVL x+12(FP), SI
-	MOVL s+24(FP), CX
-	MOVL (SI)(BX*4), AX	// w1 = x[n-1]
-	MOVL $0, DX
-	SHLL CX, DX:AX		// w1>>ŝ
-	MOVL DX, c+28(FP)
-
-	CMPL BX, $0
-	JLE X8a			// i <= 0
-
-	// i > 0
-L8:	MOVL AX, DX		// w = w1
-	MOVL -4(SI)(BX*4), AX	// w1 = x[i-1]
-	SHLL CX, DX:AX		// w<<s | w1>>ŝ
-	MOVL DX, (DI)(BX*4)	// z[i] = w<<s | w1>>ŝ
-	SUBL $1, BX		// i--
-	JG L8			// i > 0
-
-	// i <= 0
-X8a:	SHLL CX, AX		// w1<<s
-	MOVL AX, (DI)		// z[0] = w1<<s
-	RET
-
-X8b:	MOVL $0, c+28(FP)
-	RET
-
-
-// func shrVU(z, x []Word, s uint) (c Word)
-TEXT ·shrVU(SB),7,$0
-	MOVL n+4(FP), BP
-	SUBL $1, BP		// n--
-	JL X9b			// n < 0	(n <= 0)
-
-	// n > 0
-	MOVL z+0(FP), DI
-	MOVL x+12(FP), SI
-	MOVL s+24(FP), CX
-	MOVL (SI), AX		// w1 = x[0]
-	MOVL $0, DX
-	SHRL CX, DX:AX		// w1<<ŝ
-	MOVL DX, c+28(FP)
-
-	MOVL $0, BX		// i = 0
-	JMP E9
-
-	// i < n-1
-L9:	MOVL AX, DX		// w = w1
-	MOVL 4(SI)(BX*4), AX	// w1 = x[i+1]
-	SHRL CX, DX:AX		// w>>s | w1<<ŝ
-	MOVL DX, (DI)(BX*4)	// z[i] = w>>s | w1<<ŝ
-	ADDL $1, BX		// i++
-	
-E9:	CMPL BX, BP
-	JL L9			// i < n-1
-
-	// i >= n-1
-X9a:	SHRL CX, AX		// w1>>s
-	MOVL AX, (DI)(BP*4)	// z[n-1] = w1>>s
-	RET
-
-X9b:	MOVL $0, c+28(FP)
-	RET
-
-
-// func mulAddVWW(z, x []Word, y, r Word) (c Word)
-TEXT ·mulAddVWW(SB),7,$0
-	MOVL z+0(FP), DI
-	MOVL x+12(FP), SI
-	MOVL y+24(FP), BP
-	MOVL r+28(FP), CX	// c = r
-	MOVL n+4(FP), BX
-	LEAL (DI)(BX*4), DI
-	LEAL (SI)(BX*4), SI
-	NEGL BX			// i = -n
-	JMP E5
-
-L5:	MOVL (SI)(BX*4), AX
-	MULL BP
-	ADDL CX, AX
-	ADCL $0, DX
-	MOVL AX, (DI)(BX*4)
-	MOVL DX, CX
-	ADDL $1, BX		// i++
-
-E5:	CMPL BX, $0		// i < 0
-	JL L5
-
-	MOVL CX, c+32(FP)
-	RET
-
-
-// func addMulVVW(z, x []Word, y Word) (c Word)
-TEXT ·addMulVVW(SB),7,$0
-	MOVL z+0(FP), DI
-	MOVL x+12(FP), SI
-	MOVL y+24(FP), BP
-	MOVL n+4(FP), BX
-	LEAL (DI)(BX*4), DI
-	LEAL (SI)(BX*4), SI
-	NEGL BX			// i = -n
-	MOVL $0, CX		// c = 0
-	JMP E6
-
-L6:	MOVL (SI)(BX*4), AX
-	MULL BP
-	ADDL CX, AX
-	ADCL $0, DX
-	ADDL AX, (DI)(BX*4)
-	ADCL $0, DX
-	MOVL DX, CX
-	ADDL $1, BX		// i++
-
-E6:	CMPL BX, $0		// i < 0
-	JL L6
-
-	MOVL CX, c+28(FP)
-	RET
-
-
-// divWVW(z* Word, xn Word, x []Word, y Word) (r Word)
-TEXT ·divWVW(SB),7,$0
-	MOVL z+0(FP), DI
-	MOVL xn+12(FP), DX	// r = xn
-	MOVL x+16(FP), SI
-	MOVL y+28(FP), CX
-	MOVL n+4(FP), BX	// i = n
-	JMP E7
-
-L7:	MOVL (SI)(BX*4), AX
-	DIVL CX
-	MOVL AX, (DI)(BX*4)
-
-E7:	SUBL $1, BX		// i--
-	JGE L7			// i >= 0
-
-	MOVL DX, r+32(FP)
-	RET
diff --git a/src/pkg/big/arith_amd64.s b/src/pkg/big/arith_amd64.s
deleted file mode 100644
index 89b65f3..0000000
--- a/src/pkg/big/arith_amd64.s
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file provides fast assembly versions for the elementary
-// arithmetic operations on vectors implemented in arith.go.
-
-// TODO(gri) - experiment with unrolled loops for faster execution
-
-// func mulWW(x, y Word) (z1, z0 Word)
-TEXT ·mulWW(SB),7,$0
-	MOVQ x+0(FP), AX
-	MULQ y+8(FP)
-	MOVQ DX, z1+16(FP)
-	MOVQ AX, z0+24(FP)
-	RET
-
-
-// func divWW(x1, x0, y Word) (q, r Word)
-TEXT ·divWW(SB),7,$0
-	MOVQ x1+0(FP), DX
-	MOVQ x0+8(FP), AX
-	DIVQ y+16(FP)
-	MOVQ AX, q+24(FP)
-	MOVQ DX, r+32(FP)
-	RET
-
-
-// func addVV(z, x, y []Word) (c Word)
-TEXT ·addVV(SB),7,$0
-	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), R9
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	MOVQ $0, DX		// c = 0
-	JMP E1
-
-L1:	MOVQ (R8)(BX*8), AX
-	RCRQ $1, DX
-	ADCQ (R9)(BX*8), AX
-	RCLQ $1, DX
-	MOVQ AX, (R10)(BX*8)
-	ADDL $1, BX		// i++
-
-E1:	CMPQ BX, R11		// i < n
-	JL L1
-
-	MOVQ DX, c+48(FP)
-	RET
-
-
-// func subVV(z, x, y []Word) (c Word)
-// (same as addVV_s except for SBBQ instead of ADCQ and label names)
-TEXT ·subVV(SB),7,$0
-	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), R9
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	MOVQ $0, DX		// c = 0
-	JMP E2
-
-L2:	MOVQ (R8)(BX*8), AX
-	RCRQ $1, DX
-	SBBQ (R9)(BX*8), AX
-	RCLQ $1, DX
-	MOVQ AX, (R10)(BX*8)
-	ADDL $1, BX		// i++
-
-E2:	CMPQ BX, R11		// i < n
-	JL L2
-
-	MOVQ DX, c+48(FP)
-	RET
-
-
-// func addVW(z, x []Word, y Word) (c Word)
-TEXT ·addVW(SB),7,$0
-	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), AX	// c = y
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	JMP E3
-
-L3:	ADDQ (R8)(BX*8), AX
-	MOVQ AX, (R10)(BX*8)
-	RCLQ $1, AX
-	ANDQ $1, AX
-	ADDL $1, BX		// i++
-
-E3:	CMPQ BX, R11		// i < n
-	JL L3
-
-	MOVQ AX, c+40(FP)
-	RET
-
-
-// func subVW(z, x []Word, y Word) (c Word)
-TEXT ·subVW(SB),7,$0
-	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), AX	// c = y
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	JMP E4
-
-L4:	MOVQ (R8)(BX*8), DX	// TODO(gri) is there a reverse SUBQ?
-	SUBQ AX, DX
-	MOVQ DX, (R10)(BX*8)
-	RCLQ $1, AX
-	ANDQ $1, AX
-	ADDL $1, BX		// i++
-
-E4:	CMPQ BX, R11		// i < n
-	JL L4
-
-	MOVQ AX, c+40(FP)
-	RET
-
-
-// func shlVU(z, x []Word, s uint) (c Word)
-TEXT ·shlVU(SB),7,$0
-	MOVL n+8(FP), BX	// i = n
-	SUBL $1, BX		// i--
-	JL X8b			// i < 0	(n <= 0)
-
-	// n > 0
-	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVL s+32(FP), CX
-	MOVQ (R8)(BX*8), AX	// w1 = x[n-1]
-	MOVQ $0, DX
-	SHLQ CX, DX:AX		// w1>>ŝ
-	MOVQ DX, c+40(FP)
-
-	CMPL BX, $0
-	JLE X8a			// i <= 0
-
-	// i > 0
-L8:	MOVQ AX, DX		// w = w1
-	MOVQ -8(R8)(BX*8), AX	// w1 = x[i-1]
-	SHLQ CX, DX:AX		// w<<s | w1>>ŝ
-	MOVQ DX, (R10)(BX*8)	// z[i] = w<<s | w1>>ŝ
-	SUBL $1, BX		// i--
-	JG L8			// i > 0
-
-	// i <= 0
-X8a:	SHLQ CX, AX		// w1<<s
-	MOVQ AX, (R10)		// z[0] = w1<<s
-	RET
-
-X8b:	MOVQ $0, c+40(FP)
-	RET
-
-
-// func shrVU(z, x []Word, s uint) (c Word)
-TEXT ·shrVU(SB),7,$0
-	MOVL n+8(FP), R11
-	SUBL $1, R11		// n--
-	JL X9b			// n < 0	(n <= 0)
-
-	// n > 0
-	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVL s+32(FP), CX
-	MOVQ (R8), AX		// w1 = x[0]
-	MOVQ $0, DX
-	SHRQ CX, DX:AX		// w1<<ŝ
-	MOVQ DX, c+40(FP)
-
-	MOVQ $0, BX		// i = 0
-	JMP E9
-
-	// i < n-1
-L9:	MOVQ AX, DX		// w = w1
-	MOVQ 8(R8)(BX*8), AX	// w1 = x[i+1]
-	SHRQ CX, DX:AX		// w>>s | w1<<ŝ
-	MOVQ DX, (R10)(BX*8)	// z[i] = w>>s | w1<<ŝ
-	ADDL $1, BX		// i++
-	
-E9:	CMPQ BX, R11
-	JL L9			// i < n-1
-
-	// i >= n-1
-X9a:	SHRQ CX, AX		// w1>>s
-	MOVQ AX, (R10)(R11*8)	// z[n-1] = w1>>s
-	RET
-
-X9b:	MOVQ $0, c+40(FP)
-	RET
-
-
-// func mulAddVWW(z, x []Word, y, r Word) (c Word)
-TEXT ·mulAddVWW(SB),7,$0
-	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), R9
-	MOVQ r+40(FP), CX	// c = r
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	JMP E5
-
-L5:	MOVQ (R8)(BX*8), AX
-	MULQ R9
-	ADDQ CX, AX
-	ADCQ $0, DX
-	MOVQ AX, (R10)(BX*8)
-	MOVQ DX, CX
-	ADDL $1, BX		// i++
-
-E5:	CMPQ BX, R11		// i < n
-	JL L5
-
-	MOVQ CX, c+48(FP)
-	RET
-
-
-// func addMulVVW(z, x []Word, y Word) (c Word)
-TEXT ·addMulVVW(SB),7,$0
-	MOVQ z+0(FP), R10
-	MOVQ x+16(FP), R8
-	MOVQ y+32(FP), R9
-	MOVL n+8(FP), R11
-	MOVQ $0, BX		// i = 0
-	MOVQ $0, CX		// c = 0
-	JMP E6
-
-L6:	MOVQ (R8)(BX*8), AX
-	MULQ R9
-	ADDQ CX, AX
-	ADCQ $0, DX
-	ADDQ AX, (R10)(BX*8)
-	ADCQ $0, DX
-	MOVQ DX, CX
-	ADDL $1, BX		// i++
-
-E6:	CMPQ BX, R11		// i < n
-	JL L6
-
-	MOVQ CX, c+40(FP)
-	RET
-
-
-// divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
-TEXT ·divWVW(SB),7,$0
-	MOVQ z+0(FP), R10
-	MOVQ xn+16(FP), DX	// r = xn
-	MOVQ x+24(FP), R8
-	MOVQ y+40(FP), R9
-	MOVL n+8(FP), BX	// i = n
-	JMP E7
-
-L7:	MOVQ (R8)(BX*8), AX
-	DIVQ R9
-	MOVQ AX, (R10)(BX*8)
-
-E7:	SUBL $1, BX		// i--
-	JGE L7			// i >= 0
-
-	MOVQ DX, r+48(FP)
-	RET
diff --git a/src/pkg/big/arith_arm.s b/src/pkg/big/arith_arm.s
deleted file mode 100644
index 60abe6e..0000000
--- a/src/pkg/big/arith_arm.s
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file provides fast assembly versions for the elementary
-// arithmetic operations on vectors implemented in arith.go.
-
-#define CFLAG 29	// bit position of carry flag
-
-// func addVV(z, x, y []Word) (c Word)
-TEXT ·addVV(SB),7,$0
-	MOVW	$0, R0
-	MOVW	z+0(FP), R1
-	MOVW	x+12(FP), R2
-	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R4
-	MOVW	R4<<2, R4
-	ADD	R1, R4
-	B E1
-L1:
-	MOVW.P	4(R2), R5
-	MOVW.P	4(R3), R6
-	MOVW	R0, CPSR
-	ADC.S	R6, R5
-	MOVW.P	R5, 4(R1)
-	MOVW	CPSR, R0
-E1:
-	CMP	R1, R4
-	BNE L1
-
-	MOVW	R0>>CFLAG, R0
-	AND	$1, R0
-	MOVW	R0, c+36(FP)
-	RET
-
-
-// func subVV(z, x, y []Word) (c Word)
-// (same as addVV except for SBC instead of ADC and label names)
-TEXT ·subVV(SB),7,$0
-	MOVW	$(1<<CFLAG), R0
-	MOVW	z+0(FP), R1
-	MOVW	x+12(FP), R2
-	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R4
-	MOVW	R4<<2, R4
-	ADD	R1, R4
-	B E2
-L2:
-	MOVW.P	4(R2), R5
-	MOVW.P	4(R3), R6
-	MOVW	R0, CPSR
-	SBC.S	R6, R5
-	MOVW.P	R5, 4(R1)
-	MOVW	CPSR, R0
-E2:
-	CMP	R1, R4
-	BNE L2
-
-	MOVW	R0>>CFLAG, R0
-	AND	$1, R0
-	EOR	$1, R0
-	MOVW	R0, c+36(FP)
-	RET
-
-
-// func addVW(z, x []Word, y Word) (c Word)
-TEXT ·addVW(SB),7,$0
-	MOVW	z+0(FP), R1
-	MOVW	x+12(FP), R2
-	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R4
-	MOVW	R4<<2, R4
-	ADD	R1, R4
-	CMP	R1, R4
-	BNE L3a
-	MOVW	R3, c+28(FP)
-	RET
-L3a:
-	MOVW.P	4(R2), R5
-	ADD.S	R3, R5
-	MOVW.P	R5, 4(R1)
-	MOVW	CPSR, R0
-	B	E3
-L3:
-	MOVW.P	4(R2), R5
-	MOVW	R0, CPSR
-	ADC.S	$0, R5
-	MOVW.P	R5, 4(R1)
-	MOVW	CPSR, R0
-E3:
-	CMP	R1, R4
-	BNE	L3
-
-	MOVW	R0>>CFLAG, R0
-	AND	$1, R0
-	MOVW	R0, c+28(FP)
-	RET
-
-
-// func subVW(z, x []Word, y Word) (c Word)
-TEXT ·subVW(SB),7,$0
-	MOVW	z+0(FP), R1
-	MOVW	x+12(FP), R2
-	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R4
-	MOVW	R4<<2, R4
-	ADD	R1, R4
-	CMP	R1, R4
-	BNE L4a
-	MOVW	R3, c+28(FP)
-	RET
-L4a:
-	MOVW.P	4(R2), R5
-	SUB.S	R3, R5
-	MOVW.P	R5, 4(R1)
-	MOVW	CPSR, R0
-	B	E4
-L4:
-	MOVW.P	4(R2), R5
-	MOVW	R0, CPSR
-	SBC.S	$0, R5
-	MOVW.P	R5, 4(R1)
-	MOVW	CPSR, R0
-E4:
-	CMP	R1, R4
-	BNE	L4
-
-	MOVW	R0>>CFLAG, R0
-	AND	$1, R0
-	EOR	$1, R0
-	MOVW	R0, c+28(FP)
-	RET
-
-
-// func shlVU(z, x []Word, s uint) (c Word)
-TEXT ·shlVU(SB),7,$0
-	MOVW	n+4(FP), R5
-	CMP	$0, R5
-	BEQ	X7
-	
-	MOVW	z+0(FP), R1
-	MOVW	x+12(FP), R2
-	MOVW	R5<<2, R5
-	ADD	R5, R2
-	ADD	R1, R5
-	MOVW	s+24(FP), R3
-	CMP	$0, R3	// shift 0 is special
-	BEQ	Y7
-	ADD	$4, R1	// stop one word early
-	MOVW	$32, R4
-	SUB	R3, R4
-	MOVW	$0, R7
-	
-	MOVW.W	-4(R2), R6
-	MOVW	R6<<R3, R7
-	MOVW	R6>>R4, R6
-	MOVW	R6, c+28(FP)
-	B E7
-
-L7:
-	MOVW.W	-4(R2), R6
-	ORR	R6>>R4, R7
-	MOVW.W	R7, -4(R5)
-	MOVW	R6<<R3, R7
-E7:
-	CMP	R1, R5
-	BNE	L7
-
-	MOVW	R7, -4(R5)
-	RET
-
-Y7:	// copy loop, because shift 0 == shift 32
-	MOVW.W	-4(R2), R6
-	MOVW.W	R6, -4(R5)
-	CMP	R1, R5
-	BNE Y7
-
-X7:
-	MOVW	$0, R1
-	MOVW	R1, c+28(FP)
-	RET
-
-
-// func shrVU(z, x []Word, s uint) (c Word)
-TEXT ·shrVU(SB),7,$0
-	MOVW	n+4(FP), R5
-	CMP	$0, R5
-	BEQ	X6
-
-	MOVW	z+0(FP), R1
-	MOVW	x+12(FP), R2
-	MOVW	R5<<2, R5
-	ADD	R1, R5
-	MOVW	s+24(FP), R3
-	CMP	$0, R3	// shift 0 is special
-	BEQ Y6
-	SUB	$4, R5	// stop one word early
-	MOVW	$32, R4
-	SUB	R3, R4
-	MOVW	$0, R7
-
-	// first word
-	MOVW.P	4(R2), R6
-	MOVW	R6>>R3, R7
-	MOVW	R6<<R4, R6
-	MOVW	R6, c+28(FP)
-	B E6
-
-	// word loop
-L6:
-	MOVW.P	4(R2), R6
-	ORR	R6<<R4, R7
-	MOVW.P	R7, 4(R1)
-	MOVW	R6>>R3, R7
-E6:
-	CMP	R1, R5
-	BNE	L6
-
-	MOVW	R7, 0(R1)
-	RET
-
-Y6:	// copy loop, because shift 0 == shift 32
-	MOVW.P	4(R2), R6
-	MOVW.P	R6, 4(R1)
-	CMP R1, R5
-	BNE Y6
-
-X6:
-	MOVW	$0, R1
-	MOVW	R1, c+28(FP)
-	RET
-
-
-// func mulAddVWW(z, x []Word, y, r Word) (c Word)
-TEXT ·mulAddVWW(SB),7,$0
-	MOVW	$0, R0
-	MOVW	z+0(FP), R1
-	MOVW	x+12(FP), R2
-	MOVW	y+24(FP), R3
-	MOVW	r+28(FP), R4
-	MOVW	n+4(FP), R5
-	MOVW	R5<<2, R5
-	ADD	R1, R5
-	B E8
-
-	// word loop
-L8:
-	MOVW.P	4(R2), R6
-	MULLU	R6, R3, (R7, R6)
-	ADD.S	R4, R6
-	ADC	R0, R7
-	MOVW.P	R6, 4(R1)
-	MOVW	R7, R4
-E8:
-	CMP	R1, R5
-	BNE	L8
-
-	MOVW	R4, c+32(FP)
-	RET
-
-
-// func addMulVVW(z, x []Word, y Word) (c Word)
-TEXT ·addMulVVW(SB),7,$0
-	MOVW	$0, R0
-	MOVW	z+0(FP), R1
-	MOVW	x+12(FP), R2
-	MOVW	y+24(FP), R3
-	MOVW	n+4(FP), R5
-	MOVW	R5<<2, R5
-	ADD	R1, R5
-	MOVW	$0, R4
-	B E9
-
-	// word loop
-L9:
-	MOVW.P	4(R2), R6
-	MULLU	R6, R3, (R7, R6)
-	ADD.S	R4, R6
-	ADC	R0, R7
-	MOVW	0(R1), R4
-	ADD.S	R4, R6
-	ADC	R0, R7
-	MOVW.P	R6, 4(R1)
-	MOVW	R7, R4
-E9:
-	CMP	R1, R5
-	BNE	L9
-
-	MOVW	R4, c+28(FP)
-	RET
-
-
-// divWVW(z* Word, xn Word, x []Word, y Word) (r Word)
-TEXT ·divWVW(SB),7,$0
-	// ARM has no multiword division, so use portable code.
-	B ·divWVW_g(SB)
-
-
-// func divWW(x1, x0, y Word) (q, r Word)
-TEXT ·divWW(SB),7,$0
-	// ARM has no multiword division, so use portable code.
-	B ·divWW_g(SB)
-
-
-// func mulWW(x, y Word) (z1, z0 Word)
-TEXT ·mulWW(SB),7,$0
-	MOVW	x+0(FP), R1
-	MOVW	y+4(FP), R2
-	MULLU	R1, R2, (R4, R3)
-	MOVW	R4, z1+8(FP)
-	MOVW	R3, z0+12(FP)
-	RET
diff --git a/src/pkg/big/arith_decl.go b/src/pkg/big/arith_decl.go
deleted file mode 100644
index 95fcd8b..0000000
--- a/src/pkg/big/arith_decl.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2010 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 big
-
-// implemented in arith_$GOARCH.s
-func mulWW(x, y Word) (z1, z0 Word)
-func divWW(x1, x0, y Word) (q, r Word)
-func addVV(z, x, y []Word) (c Word)
-func subVV(z, x, y []Word) (c Word)
-func addVW(z, x []Word, y Word) (c Word)
-func subVW(z, x []Word, y Word) (c Word)
-func shlVU(z, x []Word, s uint) (c Word)
-func shrVU(z, x []Word, s uint) (c Word)
-func mulAddVWW(z, x []Word, y, r Word) (c Word)
-func addMulVVW(z, x []Word, y Word) (c Word)
-func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
diff --git a/src/pkg/big/arith_test.go b/src/pkg/big/arith_test.go
deleted file mode 100644
index b6c56c3..0000000
--- a/src/pkg/big/arith_test.go
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package big
-
-import "testing"
-
-type funWW func(x, y, c Word) (z1, z0 Word)
-type argWW struct {
-	x, y, c, z1, z0 Word
-}
-
-var sumWW = []argWW{
-	{0, 0, 0, 0, 0},
-	{0, 1, 0, 0, 1},
-	{0, 0, 1, 0, 1},
-	{0, 1, 1, 0, 2},
-	{12345, 67890, 0, 0, 80235},
-	{12345, 67890, 1, 0, 80236},
-	{_M, 1, 0, 1, 0},
-	{_M, 0, 1, 1, 0},
-	{_M, 1, 1, 1, 1},
-	{_M, _M, 0, 1, _M - 1},
-	{_M, _M, 1, 1, _M},
-}
-
-func testFunWW(t *testing.T, msg string, f funWW, a argWW) {
-	z1, z0 := f(a.x, a.y, a.c)
-	if z1 != a.z1 || z0 != a.z0 {
-		t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0)
-	}
-}
-
-func TestFunWW(t *testing.T) {
-	for _, a := range sumWW {
-		arg := a
-		testFunWW(t, "addWW_g", addWW_g, arg)
-
-		arg = argWW{a.y, a.x, a.c, a.z1, a.z0}
-		testFunWW(t, "addWW_g symmetric", addWW_g, arg)
-
-		arg = argWW{a.z0, a.x, a.c, a.z1, a.y}
-		testFunWW(t, "subWW_g", subWW_g, arg)
-
-		arg = argWW{a.z0, a.y, a.c, a.z1, a.x}
-		testFunWW(t, "subWW_g symmetric", subWW_g, arg)
-	}
-}
-
-type funVV func(z, x, y []Word) (c Word)
-type argVV struct {
-	z, x, y nat
-	c       Word
-}
-
-var sumVV = []argVV{
-	{},
-	{nat{0}, nat{0}, nat{0}, 0},
-	{nat{1}, nat{1}, nat{0}, 0},
-	{nat{0}, nat{_M}, nat{1}, 1},
-	{nat{80235}, nat{12345}, nat{67890}, 0},
-	{nat{_M - 1}, nat{_M}, nat{_M}, 1},
-	{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, nat{1, 0, 0, 0}, 1},
-	{nat{0, 0, 0, _M}, nat{_M, _M, _M, _M - 1}, nat{1, 0, 0, 0}, 0},
-	{nat{0, 0, 0, 0}, nat{_M, 0, _M, 0}, nat{1, _M, 0, _M}, 1},
-}
-
-func testFunVV(t *testing.T, msg string, f funVV, a argVV) {
-	z := make(nat, len(a.z))
-	c := f(z, a.x, a.y)
-	for i, zi := range z {
-		if zi != a.z[i] {
-			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
-			break
-		}
-	}
-	if c != a.c {
-		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
-	}
-}
-
-func TestFunVV(t *testing.T) {
-	for _, a := range sumVV {
-		arg := a
-		testFunVV(t, "addVV_g", addVV_g, arg)
-		testFunVV(t, "addVV", addVV, arg)
-
-		arg = argVV{a.z, a.y, a.x, a.c}
-		testFunVV(t, "addVV_g symmetric", addVV_g, arg)
-		testFunVV(t, "addVV symmetric", addVV, arg)
-
-		arg = argVV{a.x, a.z, a.y, a.c}
-		testFunVV(t, "subVV_g", subVV_g, arg)
-		testFunVV(t, "subVV", subVV, arg)
-
-		arg = argVV{a.y, a.z, a.x, a.c}
-		testFunVV(t, "subVV_g symmetric", subVV_g, arg)
-		testFunVV(t, "subVV symmetric", subVV, arg)
-	}
-}
-
-type funVW func(z, x []Word, y Word) (c Word)
-type argVW struct {
-	z, x nat
-	y    Word
-	c    Word
-}
-
-var sumVW = []argVW{
-	{},
-	{nil, nil, 2, 2},
-	{nat{0}, nat{0}, 0, 0},
-	{nat{1}, nat{0}, 1, 0},
-	{nat{1}, nat{1}, 0, 0},
-	{nat{0}, nat{_M}, 1, 1},
-	{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1},
-}
-
-var prodVW = []argVW{
-	{},
-	{nat{0}, nat{0}, 0, 0},
-	{nat{0}, nat{_M}, 0, 0},
-	{nat{0}, nat{0}, _M, 0},
-	{nat{1}, nat{1}, 1, 0},
-	{nat{22793}, nat{991}, 23, 0},
-	{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0},
-	{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0},
-	{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0},
-	{nat{_M << 1 & _M}, nat{_M}, 1 << 1, _M >> (_W - 1)},
-	{nat{_M << 7 & _M}, nat{_M}, 1 << 7, _M >> (_W - 7)},
-	{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, _M >> (_W - 7)},
-}
-
-var lshVW = []argVW{
-	{},
-	{nat{0}, nat{0}, 0, 0},
-	{nat{0}, nat{0}, 1, 0},
-	{nat{0}, nat{0}, 20, 0},
-
-	{nat{_M}, nat{_M}, 0, 0},
-	{nat{_M << 1 & _M}, nat{_M}, 1, 1},
-	{nat{_M << 20 & _M}, nat{_M}, 20, _M >> (_W - 20)},
-
-	{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
-	{nat{_M << 1 & _M, _M, _M}, nat{_M, _M, _M}, 1, 1},
-	{nat{_M << 20 & _M, _M, _M}, nat{_M, _M, _M}, 20, _M >> (_W - 20)},
-}
-
-var rshVW = []argVW{
-	{},
-	{nat{0}, nat{0}, 0, 0},
-	{nat{0}, nat{0}, 1, 0},
-	{nat{0}, nat{0}, 20, 0},
-
-	{nat{_M}, nat{_M}, 0, 0},
-	{nat{_M >> 1}, nat{_M}, 1, _M << (_W - 1) & _M},
-	{nat{_M >> 20}, nat{_M}, 20, _M << (_W - 20) & _M},
-
-	{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
-	{nat{_M, _M, _M >> 1}, nat{_M, _M, _M}, 1, _M << (_W - 1) & _M},
-	{nat{_M, _M, _M >> 20}, nat{_M, _M, _M}, 20, _M << (_W - 20) & _M},
-}
-
-func testFunVW(t *testing.T, msg string, f funVW, a argVW) {
-	z := make(nat, len(a.z))
-	c := f(z, a.x, a.y)
-	for i, zi := range z {
-		if zi != a.z[i] {
-			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
-			break
-		}
-	}
-	if c != a.c {
-		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
-	}
-}
-
-func makeFunVW(f func(z, x []Word, s uint) (c Word)) funVW {
-	return func(z, x []Word, s Word) (c Word) {
-		return f(z, x, uint(s))
-	}
-}
-
-func TestFunVW(t *testing.T) {
-	for _, a := range sumVW {
-		arg := a
-		testFunVW(t, "addVW_g", addVW_g, arg)
-		testFunVW(t, "addVW", addVW, arg)
-
-		arg = argVW{a.x, a.z, a.y, a.c}
-		testFunVW(t, "subVW_g", subVW_g, arg)
-		testFunVW(t, "subVW", subVW, arg)
-	}
-
-	shlVW_g := makeFunVW(shlVU_g)
-	shlVW := makeFunVW(shlVU)
-	for _, a := range lshVW {
-		arg := a
-		testFunVW(t, "shlVU_g", shlVW_g, arg)
-		testFunVW(t, "shlVU", shlVW, arg)
-	}
-
-	shrVW_g := makeFunVW(shrVU_g)
-	shrVW := makeFunVW(shrVU)
-	for _, a := range rshVW {
-		arg := a
-		testFunVW(t, "shrVU_g", shrVW_g, arg)
-		testFunVW(t, "shrVU", shrVW, arg)
-	}
-}
-
-type funVWW func(z, x []Word, y, r Word) (c Word)
-type argVWW struct {
-	z, x nat
-	y, r Word
-	c    Word
-}
-
-var prodVWW = []argVWW{
-	{},
-	{nat{0}, nat{0}, 0, 0, 0},
-	{nat{991}, nat{0}, 0, 991, 0},
-	{nat{0}, nat{_M}, 0, 0, 0},
-	{nat{991}, nat{_M}, 0, 991, 0},
-	{nat{0}, nat{0}, _M, 0, 0},
-	{nat{991}, nat{0}, _M, 991, 0},
-	{nat{1}, nat{1}, 1, 0, 0},
-	{nat{992}, nat{1}, 1, 991, 0},
-	{nat{22793}, nat{991}, 23, 0, 0},
-	{nat{22800}, nat{991}, 23, 7, 0},
-	{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0, 0},
-	{nat{7, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 7, 0},
-	{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0, 0},
-	{nat{991, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 991, 0},
-	{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0, 0},
-	{nat{991, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 991, 0},
-	{nat{_M << 1 & _M}, nat{_M}, 1 << 1, 0, _M >> (_W - 1)},
-	{nat{_M<<1&_M + 1}, nat{_M}, 1 << 1, 1, _M >> (_W - 1)},
-	{nat{_M << 7 & _M}, nat{_M}, 1 << 7, 0, _M >> (_W - 7)},
-	{nat{_M<<7&_M + 1<<6}, nat{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
-	{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)},
-	{nat{_M<<7&_M + 1<<6, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
-}
-
-func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) {
-	z := make(nat, len(a.z))
-	c := f(z, a.x, a.y, a.r)
-	for i, zi := range z {
-		if zi != a.z[i] {
-			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
-			break
-		}
-	}
-	if c != a.c {
-		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
-	}
-}
-
-// TODO(gri) mulAddVWW and divWVW are symmetric operations but
-//           their signature is not symmetric. Try to unify.
-
-type funWVW func(z []Word, xn Word, x []Word, y Word) (r Word)
-type argWVW struct {
-	z  nat
-	xn Word
-	x  nat
-	y  Word
-	r  Word
-}
-
-func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) {
-	z := make(nat, len(a.z))
-	r := f(z, a.xn, a.x, a.y)
-	for i, zi := range z {
-		if zi != a.z[i] {
-			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
-			break
-		}
-	}
-	if r != a.r {
-		t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r)
-	}
-}
-
-func TestFunVWW(t *testing.T) {
-	for _, a := range prodVWW {
-		arg := a
-		testFunVWW(t, "mulAddVWW_g", mulAddVWW_g, arg)
-		testFunVWW(t, "mulAddVWW", mulAddVWW, arg)
-
-		if a.y != 0 && a.r < a.y {
-			arg := argWVW{a.x, a.c, a.z, a.y, a.r}
-			testFunWVW(t, "divWVW_g", divWVW_g, arg)
-			testFunWVW(t, "divWVW", divWVW, arg)
-		}
-	}
-}
-
-var mulWWTests = []struct {
-	x, y Word
-	q, r Word
-}{
-	{_M, _M, _M - 1, 1},
-	// 32 bit only: {0xc47dfa8c, 50911, 0x98a4, 0x998587f4},
-}
-
-func TestMulWW(t *testing.T) {
-	for i, test := range mulWWTests {
-		q, r := mulWW_g(test.x, test.y)
-		if q != test.q || r != test.r {
-			t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
-		}
-	}
-}
-
-var mulAddWWWTests = []struct {
-	x, y, c Word
-	q, r    Word
-}{
-	// TODO(agl): These will only work on 64-bit platforms.
-	// {15064310297182388543, 0xe7df04d2d35d5d80, 13537600649892366549, 13644450054494335067, 10832252001440893781},
-	// {15064310297182388543, 0xdab2f18048baa68d, 13644450054494335067, 12869334219691522700, 14233854684711418382},
-	{_M, _M, 0, _M - 1, 1},
-	{_M, _M, _M, _M, 0},
-}
-
-func TestMulAddWWW(t *testing.T) {
-	for i, test := range mulAddWWWTests {
-		q, r := mulAddWWW_g(test.x, test.y, test.c)
-		if q != test.q || r != test.r {
-			t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
-		}
-	}
-}
diff --git a/src/pkg/big/calibrate_test.go b/src/pkg/big/calibrate_test.go
deleted file mode 100644
index 1cd93b1..0000000
--- a/src/pkg/big/calibrate_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file prints execution times for the Mul benchmark
-// given different Karatsuba thresholds. The result may be
-// used to manually fine-tune the threshold constant. The
-// results are somewhat fragile; use repeated runs to get
-// a clear picture.
-
-// Usage: gotest -calibrate
-
-package big
-
-import (
-	"flag"
-	"fmt"
-	"testing"
-	"time"
-)
-
-var calibrate = flag.Bool("calibrate", false, "run calibration test")
-
-// measure returns the time to run f
-func measure(f func()) int64 {
-	const N = 100
-	start := time.Nanoseconds()
-	for i := N; i > 0; i-- {
-		f()
-	}
-	stop := time.Nanoseconds()
-	return (stop - start) / N
-}
-
-func computeThresholds() {
-	fmt.Printf("Multiplication times for varying Karatsuba thresholds\n")
-	fmt.Printf("(run repeatedly for good results)\n")
-
-	// determine Tk, the work load execution time using basic multiplication
-	karatsubaThreshold = 1e9 // disable karatsuba
-	Tb := measure(benchmarkMulLoad)
-	fmt.Printf("Tb = %dns\n", Tb)
-
-	// thresholds
-	n := 8 // any lower values for the threshold lead to very slow multiplies
-	th1 := -1
-	th2 := -1
-
-	var deltaOld int64
-	for count := -1; count != 0; count-- {
-		// determine Tk, the work load execution time using Karatsuba multiplication
-		karatsubaThreshold = n // enable karatsuba
-		Tk := measure(benchmarkMulLoad)
-
-		// improvement over Tb
-		delta := (Tb - Tk) * 100 / Tb
-
-		fmt.Printf("n = %3d  Tk = %8dns  %4d%%", n, Tk, delta)
-
-		// determine break-even point
-		if Tk < Tb && th1 < 0 {
-			th1 = n
-			fmt.Print("  break-even point")
-		}
-
-		// determine diminishing return
-		if 0 < delta && delta < deltaOld && th2 < 0 {
-			th2 = n
-			fmt.Print("  diminishing return")
-		}
-		deltaOld = delta
-
-		fmt.Println()
-
-		// trigger counter
-		if th1 >= 0 && th2 >= 0 && count < 0 {
-			count = 20 // this many extra measurements after we got both thresholds
-		}
-
-		n++
-	}
-}
-
-func TestCalibrate(t *testing.T) {
-	if *calibrate {
-		computeThresholds()
-	}
-}
diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go
deleted file mode 100644
index 701b697..0000000
--- a/src/pkg/big/int.go
+++ /dev/null
@@ -1,868 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file implements signed multi-precision integers.
-
-package big
-
-import (
-	"fmt"
-	"io"
-	"os"
-	"rand"
-	"strings"
-)
-
-// An Int represents a signed multi-precision integer.
-// The zero value for an Int represents the value 0.
-type Int struct {
-	neg bool // sign
-	abs nat  // absolute value of the integer
-}
-
-var intOne = &Int{false, natOne}
-
-// Sign returns:
-//
-//	-1 if x <  0
-//	 0 if x == 0
-//	+1 if x >  0
-//
-func (x *Int) Sign() int {
-	if len(x.abs) == 0 {
-		return 0
-	}
-	if x.neg {
-		return -1
-	}
-	return 1
-}
-
-// SetInt64 sets z to x and returns z.
-func (z *Int) SetInt64(x int64) *Int {
-	neg := false
-	if x < 0 {
-		neg = true
-		x = -x
-	}
-	z.abs = z.abs.setUint64(uint64(x))
-	z.neg = neg
-	return z
-}
-
-// NewInt allocates and returns a new Int set to x.
-func NewInt(x int64) *Int {
-	return new(Int).SetInt64(x)
-}
-
-// Set sets z to x and returns z.
-func (z *Int) Set(x *Int) *Int {
-	z.abs = z.abs.set(x.abs)
-	z.neg = x.neg
-	return z
-}
-
-// Abs sets z to |x| (the absolute value of x) and returns z.
-func (z *Int) Abs(x *Int) *Int {
-	z.abs = z.abs.set(x.abs)
-	z.neg = false
-	return z
-}
-
-// Neg sets z to -x and returns z.
-func (z *Int) Neg(x *Int) *Int {
-	z.abs = z.abs.set(x.abs)
-	z.neg = len(z.abs) > 0 && !x.neg // 0 has no sign
-	return z
-}
-
-// Add sets z to the sum x+y and returns z.
-func (z *Int) Add(x, y *Int) *Int {
-	neg := x.neg
-	if x.neg == y.neg {
-		// x + y == x + y
-		// (-x) + (-y) == -(x + y)
-		z.abs = z.abs.add(x.abs, y.abs)
-	} else {
-		// x + (-y) == x - y == -(y - x)
-		// (-x) + y == y - x == -(x - y)
-		if x.abs.cmp(y.abs) >= 0 {
-			z.abs = z.abs.sub(x.abs, y.abs)
-		} else {
-			neg = !neg
-			z.abs = z.abs.sub(y.abs, x.abs)
-		}
-	}
-	z.neg = len(z.abs) > 0 && neg // 0 has no sign
-	return z
-}
-
-// Sub sets z to the difference x-y and returns z.
-func (z *Int) Sub(x, y *Int) *Int {
-	neg := x.neg
-	if x.neg != y.neg {
-		// x - (-y) == x + y
-		// (-x) - y == -(x + y)
-		z.abs = z.abs.add(x.abs, y.abs)
-	} else {
-		// x - y == x - y == -(y - x)
-		// (-x) - (-y) == y - x == -(x - y)
-		if x.abs.cmp(y.abs) >= 0 {
-			z.abs = z.abs.sub(x.abs, y.abs)
-		} else {
-			neg = !neg
-			z.abs = z.abs.sub(y.abs, x.abs)
-		}
-	}
-	z.neg = len(z.abs) > 0 && neg // 0 has no sign
-	return z
-}
-
-// Mul sets z to the product x*y and returns z.
-func (z *Int) Mul(x, y *Int) *Int {
-	// x * y == x * y
-	// x * (-y) == -(x * y)
-	// (-x) * y == -(x * y)
-	// (-x) * (-y) == x * y
-	z.abs = z.abs.mul(x.abs, y.abs)
-	z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
-	return z
-}
-
-// MulRange sets z to the product of all integers
-// in the range [a, b] inclusively and returns z.
-// If a > b (empty range), the result is 1.
-func (z *Int) MulRange(a, b int64) *Int {
-	switch {
-	case a > b:
-		return z.SetInt64(1) // empty range
-	case a <= 0 && b >= 0:
-		return z.SetInt64(0) // range includes 0
-	}
-	// a <= b && (b < 0 || a > 0)
-
-	neg := false
-	if a < 0 {
-		neg = (b-a)&1 == 0
-		a, b = -b, -a
-	}
-
-	z.abs = z.abs.mulRange(uint64(a), uint64(b))
-	z.neg = neg
-	return z
-}
-
-// Binomial sets z to the binomial coefficient of (n, k) and returns z.
-func (z *Int) Binomial(n, k int64) *Int {
-	var a, b Int
-	a.MulRange(n-k+1, n)
-	b.MulRange(1, k)
-	return z.Quo(&a, &b)
-}
-
-// Quo sets z to the quotient x/y for y != 0 and returns z.
-// If y == 0, a division-by-zero run-time panic occurs.
-// See QuoRem for more details.
-func (z *Int) Quo(x, y *Int) *Int {
-	z.abs, _ = z.abs.div(nil, x.abs, y.abs)
-	z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
-	return z
-}
-
-// Rem sets z to the remainder x%y for y != 0 and returns z.
-// If y == 0, a division-by-zero run-time panic occurs.
-// See QuoRem for more details.
-func (z *Int) Rem(x, y *Int) *Int {
-	_, z.abs = nat(nil).div(z.abs, x.abs, y.abs)
-	z.neg = len(z.abs) > 0 && x.neg // 0 has no sign
-	return z
-}
-
-// QuoRem sets z to the quotient x/y and r to the remainder x%y
-// and returns the pair (z, r) for y != 0.
-// If y == 0, a division-by-zero run-time panic occurs.
-//
-// QuoRem implements T-division and modulus (like Go):
-//
-//	q = x/y      with the result truncated to zero
-//	r = x - y*q
-//
-// (See Daan Leijen, ``Division and Modulus for Computer Scientists''.)
-//
-func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) {
-	z.abs, r.abs = z.abs.div(r.abs, x.abs, y.abs)
-	z.neg, r.neg = len(z.abs) > 0 && x.neg != y.neg, len(r.abs) > 0 && x.neg // 0 has no sign
-	return z, r
-}
-
-// Div sets z to the quotient x/y for y != 0 and returns z.
-// If y == 0, a division-by-zero run-time panic occurs.
-// See DivMod for more details.
-func (z *Int) Div(x, y *Int) *Int {
-	y_neg := y.neg // z may be an alias for y
-	var r Int
-	z.QuoRem(x, y, &r)
-	if r.neg {
-		if y_neg {
-			z.Add(z, intOne)
-		} else {
-			z.Sub(z, intOne)
-		}
-	}
-	return z
-}
-
-// Mod sets z to the modulus x%y for y != 0 and returns z.
-// If y == 0, a division-by-zero run-time panic occurs.
-// See DivMod for more details.
-func (z *Int) Mod(x, y *Int) *Int {
-	y0 := y // save y
-	if z == y || alias(z.abs, y.abs) {
-		y0 = new(Int).Set(y)
-	}
-	var q Int
-	q.QuoRem(x, y, z)
-	if z.neg {
-		if y0.neg {
-			z.Sub(z, y0)
-		} else {
-			z.Add(z, y0)
-		}
-	}
-	return z
-}
-
-// DivMod sets z to the quotient x div y and m to the modulus x mod y
-// and returns the pair (z, m) for y != 0.
-// If y == 0, a division-by-zero run-time panic occurs.
-//
-// DivMod implements Euclidean division and modulus (unlike Go):
-//
-//	q = x div y  such that
-//	m = x - y*q  with 0 <= m < |q|
-//
-// (See Raymond T. Boute, ``The Euclidean definition of the functions
-// div and mod''. ACM Transactions on Programming Languages and
-// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992.
-// ACM press.)
-//
-func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) {
-	y0 := y // save y
-	if z == y || alias(z.abs, y.abs) {
-		y0 = new(Int).Set(y)
-	}
-	z.QuoRem(x, y, m)
-	if m.neg {
-		if y0.neg {
-			z.Add(z, intOne)
-			m.Sub(m, y0)
-		} else {
-			z.Sub(z, intOne)
-			m.Add(m, y0)
-		}
-	}
-	return z, m
-}
-
-// Cmp compares x and y and returns:
-//
-//   -1 if x <  y
-//    0 if x == y
-//   +1 if x >  y
-//
-func (x *Int) Cmp(y *Int) (r int) {
-	// x cmp y == x cmp y
-	// x cmp (-y) == x
-	// (-x) cmp y == y
-	// (-x) cmp (-y) == -(x cmp y)
-	switch {
-	case x.neg == y.neg:
-		r = x.abs.cmp(y.abs)
-		if x.neg {
-			r = -r
-		}
-	case x.neg:
-		r = -1
-	default:
-		r = 1
-	}
-	return
-}
-
-func (x *Int) String() string {
-	switch {
-	case x == nil:
-		return "<nil>"
-	case x.neg:
-		return "-" + x.abs.decimalString()
-	}
-	return x.abs.decimalString()
-}
-
-func charset(ch int) string {
-	switch ch {
-	case 'b':
-		return lowercaseDigits[0:2]
-	case 'o':
-		return lowercaseDigits[0:8]
-	case 'd', 's', 'v':
-		return lowercaseDigits[0:10]
-	case 'x':
-		return lowercaseDigits[0:16]
-	case 'X':
-		return uppercaseDigits[0:16]
-	}
-	return "" // unknown format
-}
-
-// write count copies of text to s
-func writeMultiple(s fmt.State, text string, count int) {
-	if len(text) > 0 {
-		b := []byte(text)
-		for ; count > 0; count-- {
-			s.Write(b)
-		}
-	}
-}
-
-// Format is a support routine for fmt.Formatter. It accepts
-// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
-// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
-// Also supported are the full suite of package fmt's format
-// verbs for integral types, including '+', '-', and ' '
-// for sign control, '#' for leading zero in octal and for
-// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
-// respectively, specification of minimum digits precision,
-// output field width, space or zero padding, and left or
-// right justification.
-//
-func (x *Int) Format(s fmt.State, ch int) {
-	cs := charset(ch)
-
-	// special cases
-	switch {
-	case cs == "":
-		// unknown format
-		fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
-		return
-	case x == nil:
-		fmt.Fprint(s, "<nil>")
-		return
-	}
-
-	// determine sign character
-	sign := ""
-	switch {
-	case x.neg:
-		sign = "-"
-	case s.Flag('+'): // supersedes ' ' when both specified
-		sign = "+"
-	case s.Flag(' '):
-		sign = " "
-	}
-
-	// determine prefix characters for indicating output base
-	prefix := ""
-	if s.Flag('#') {
-		switch ch {
-		case 'o': // octal
-			prefix = "0"
-		case 'x': // hexadecimal
-			prefix = "0x"
-		case 'X':
-			prefix = "0X"
-		}
-	}
-
-	// determine digits with base set by len(cs) and digit characters from cs
-	digits := x.abs.string(cs)
-
-	// number of characters for the three classes of number padding
-	var left int   // space characters to left of digits for right justification ("%8d")
-	var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
-	var right int  // space characters to right of digits for left justification ("%-8d")
-
-	// determine number padding from precision: the least number of digits to output
-	precision, precisionSet := s.Precision()
-	if precisionSet {
-		switch {
-		case len(digits) < precision:
-			zeroes = precision - len(digits) // count of zero padding 
-		case digits == "0" && precision == 0:
-			return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
-		}
-	}
-
-	// determine field pad from width: the least number of characters to output
-	length := len(sign) + len(prefix) + zeroes + len(digits)
-	if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
-		switch d := width - length; {
-		case s.Flag('-'):
-			// pad on the right with spaces; supersedes '0' when both specified
-			right = d
-		case s.Flag('0') && !precisionSet:
-			// pad with zeroes unless precision also specified
-			zeroes = d
-		default:
-			// pad on the left with spaces
-			left = d
-		}
-	}
-
-	// print number as [left pad][sign][prefix][zero pad][digits][right pad]
-	writeMultiple(s, " ", left)
-	writeMultiple(s, sign, 1)
-	writeMultiple(s, prefix, 1)
-	writeMultiple(s, "0", zeroes)
-	writeMultiple(s, digits, 1)
-	writeMultiple(s, " ", right)
-}
-
-// scan sets z to the integer value corresponding to the longest possible prefix
-// read from r representing a signed integer number in a given conversion base.
-// It returns z, the actual conversion base used, and an error, if any. In the
-// error case, the value of z is undefined. The syntax follows the syntax of
-// integer literals in Go.
-//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
-// is 0, the string prefix determines the actual conversion base. A prefix of
-// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
-// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
-//
-func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, os.Error) {
-	// determine sign
-	ch, _, err := r.ReadRune()
-	if err != nil {
-		return z, 0, err
-	}
-	neg := false
-	switch ch {
-	case '-':
-		neg = true
-	case '+': // nothing to do
-	default:
-		r.UnreadRune()
-	}
-
-	// determine mantissa
-	z.abs, base, err = z.abs.scan(r, base)
-	if err != nil {
-		return z, base, err
-	}
-	z.neg = len(z.abs) > 0 && neg // 0 has no sign
-
-	return z, base, nil
-}
-
-// Scan is a support routine for fmt.Scanner; it sets z to the value of
-// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
-// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
-func (z *Int) Scan(s fmt.ScanState, ch int) os.Error {
-	s.SkipSpace() // skip leading space characters
-	base := 0
-	switch ch {
-	case 'b':
-		base = 2
-	case 'o':
-		base = 8
-	case 'd':
-		base = 10
-	case 'x', 'X':
-		base = 16
-	case 's', 'v':
-		// let scan determine the base
-	default:
-		return os.NewError("Int.Scan: invalid verb")
-	}
-	_, _, err := z.scan(s, base)
-	return err
-}
-
-// Int64 returns the int64 representation of x.
-// If x cannot be represented in an int64, the result is undefined.
-func (x *Int) Int64() int64 {
-	if len(x.abs) == 0 {
-		return 0
-	}
-	v := int64(x.abs[0])
-	if _W == 32 && len(x.abs) > 1 {
-		v |= int64(x.abs[1]) << 32
-	}
-	if x.neg {
-		v = -v
-	}
-	return v
-}
-
-// SetString sets z to the value of s, interpreted in the given base,
-// and returns z and a boolean indicating success. If SetString fails,
-// the value of z is undefined.
-//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
-// is 0, the string prefix determines the actual conversion base. A prefix of
-// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
-// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
-//
-func (z *Int) SetString(s string, base int) (*Int, bool) {
-	r := strings.NewReader(s)
-	_, _, err := z.scan(r, base)
-	if err != nil {
-		return z, false
-	}
-	_, _, err = r.ReadRune()
-	return z, err == os.EOF // err == os.EOF => scan consumed all of s
-}
-
-// SetBytes interprets buf as the bytes of a big-endian unsigned
-// integer, sets z to that value, and returns z.
-func (z *Int) SetBytes(buf []byte) *Int {
-	z.abs = z.abs.setBytes(buf)
-	z.neg = false
-	return z
-}
-
-// Bytes returns the absolute value of z as a big-endian byte slice.
-func (z *Int) Bytes() []byte {
-	buf := make([]byte, len(z.abs)*_S)
-	return buf[z.abs.bytes(buf):]
-}
-
-// BitLen returns the length of the absolute value of z in bits.
-// The bit length of 0 is 0.
-func (z *Int) BitLen() int {
-	return z.abs.bitLen()
-}
-
-// Exp sets z = x**y mod m. If m is nil, z = x**y.
-// See Knuth, volume 2, section 4.6.3.
-func (z *Int) Exp(x, y, m *Int) *Int {
-	if y.neg || len(y.abs) == 0 {
-		neg := x.neg
-		z.SetInt64(1)
-		z.neg = neg
-		return z
-	}
-
-	var mWords nat
-	if m != nil {
-		mWords = m.abs
-	}
-
-	z.abs = z.abs.expNN(x.abs, y.abs, mWords)
-	z.neg = len(z.abs) > 0 && x.neg && y.abs[0]&1 == 1 // 0 has no sign
-	return z
-}
-
-// GcdInt sets d to the greatest common divisor of a and b, which must be
-// positive numbers.
-// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
-// If either a or b is not positive, GcdInt sets d = x = y = 0.
-func GcdInt(d, x, y, a, b *Int) {
-	if a.neg || b.neg {
-		d.SetInt64(0)
-		if x != nil {
-			x.SetInt64(0)
-		}
-		if y != nil {
-			y.SetInt64(0)
-		}
-		return
-	}
-
-	A := new(Int).Set(a)
-	B := new(Int).Set(b)
-
-	X := new(Int)
-	Y := new(Int).SetInt64(1)
-
-	lastX := new(Int).SetInt64(1)
-	lastY := new(Int)
-
-	q := new(Int)
-	temp := new(Int)
-
-	for len(B.abs) > 0 {
-		r := new(Int)
-		q, r = q.QuoRem(A, B, r)
-
-		A, B = B, r
-
-		temp.Set(X)
-		X.Mul(X, q)
-		X.neg = !X.neg
-		X.Add(X, lastX)
-		lastX.Set(temp)
-
-		temp.Set(Y)
-		Y.Mul(Y, q)
-		Y.neg = !Y.neg
-		Y.Add(Y, lastY)
-		lastY.Set(temp)
-	}
-
-	if x != nil {
-		*x = *lastX
-	}
-
-	if y != nil {
-		*y = *lastY
-	}
-
-	*d = *A
-}
-
-// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
-// If it returns true, z is prime with probability 1 - 1/4^n.
-// If it returns false, z is not prime.
-func ProbablyPrime(z *Int, n int) bool {
-	return !z.neg && z.abs.probablyPrime(n)
-}
-
-// Rand sets z to a pseudo-random number in [0, n) and returns z.
-func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
-	z.neg = false
-	if n.neg == true || len(n.abs) == 0 {
-		z.abs = nil
-		return z
-	}
-	z.abs = z.abs.random(rnd, n.abs, n.abs.bitLen())
-	return z
-}
-
-// ModInverse sets z to the multiplicative inverse of g in the group ℤ/pℤ (where
-// p is a prime) and returns z.
-func (z *Int) ModInverse(g, p *Int) *Int {
-	var d Int
-	GcdInt(&d, z, nil, g, p)
-	// x and y are such that g*x + p*y = d. Since p is prime, d = 1. Taking
-	// that modulo p results in g*x = 1, therefore x is the inverse element.
-	if z.neg {
-		z.Add(z, p)
-	}
-	return z
-}
-
-// Lsh sets z = x << n and returns z.
-func (z *Int) Lsh(x *Int, n uint) *Int {
-	z.abs = z.abs.shl(x.abs, n)
-	z.neg = x.neg
-	return z
-}
-
-// Rsh sets z = x >> n and returns z.
-func (z *Int) Rsh(x *Int, n uint) *Int {
-	if x.neg {
-		// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)
-		t := z.abs.sub(x.abs, natOne) // no underflow because |x| > 0
-		t = t.shr(t, n)
-		z.abs = t.add(t, natOne)
-		z.neg = true // z cannot be zero if x is negative
-		return z
-	}
-
-	z.abs = z.abs.shr(x.abs, n)
-	z.neg = false
-	return z
-}
-
-// Bit returns the value of the i'th bit of z. That is, it
-// returns (z>>i)&1. The bit index i must be >= 0.
-func (z *Int) Bit(i int) uint {
-	if i < 0 {
-		panic("negative bit index")
-	}
-	if z.neg {
-		t := nat{}.sub(z.abs, natOne)
-		return t.bit(uint(i)) ^ 1
-	}
-
-	return z.abs.bit(uint(i))
-}
-
-// SetBit sets the i'th bit of z to bit and returns z.
-// That is, if bit is 1 SetBit sets z = x | (1 << i);
-// if bit is 0 it sets z = x &^ (1 << i). If bit is not 0 or 1,
-// SetBit will panic.
-func (z *Int) SetBit(x *Int, i int, b uint) *Int {
-	if i < 0 {
-		panic("negative bit index")
-	}
-	if x.neg {
-		t := z.abs.sub(x.abs, natOne)
-		t = t.setBit(t, uint(i), b^1)
-		z.abs = t.add(t, natOne)
-		z.neg = len(z.abs) > 0
-		return z
-	}
-	z.abs = z.abs.setBit(x.abs, uint(i), b)
-	z.neg = false
-	return z
-}
-
-// And sets z = x & y and returns z.
-func (z *Int) And(x, y *Int) *Int {
-	if x.neg == y.neg {
-		if x.neg {
-			// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
-			x1 := nat{}.sub(x.abs, natOne)
-			y1 := nat{}.sub(y.abs, natOne)
-			z.abs = z.abs.add(z.abs.or(x1, y1), natOne)
-			z.neg = true // z cannot be zero if x and y are negative
-			return z
-		}
-
-		// x & y == x & y
-		z.abs = z.abs.and(x.abs, y.abs)
-		z.neg = false
-		return z
-	}
-
-	// x.neg != y.neg
-	if x.neg {
-		x, y = y, x // & is symmetric
-	}
-
-	// x & (-y) == x & ^(y-1) == x &^ (y-1)
-	y1 := nat{}.sub(y.abs, natOne)
-	z.abs = z.abs.andNot(x.abs, y1)
-	z.neg = false
-	return z
-}
-
-// AndNot sets z = x &^ y and returns z.
-func (z *Int) AndNot(x, y *Int) *Int {
-	if x.neg == y.neg {
-		if x.neg {
-			// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
-			x1 := nat{}.sub(x.abs, natOne)
-			y1 := nat{}.sub(y.abs, natOne)
-			z.abs = z.abs.andNot(y1, x1)
-			z.neg = false
-			return z
-		}
-
-		// x &^ y == x &^ y
-		z.abs = z.abs.andNot(x.abs, y.abs)
-		z.neg = false
-		return z
-	}
-
-	if x.neg {
-		// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
-		x1 := nat{}.sub(x.abs, natOne)
-		z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne)
-		z.neg = true // z cannot be zero if x is negative and y is positive
-		return z
-	}
-
-	// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
-	y1 := nat{}.add(y.abs, natOne)
-	z.abs = z.abs.and(x.abs, y1)
-	z.neg = false
-	return z
-}
-
-// Or sets z = x | y and returns z.
-func (z *Int) Or(x, y *Int) *Int {
-	if x.neg == y.neg {
-		if x.neg {
-			// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
-			x1 := nat{}.sub(x.abs, natOne)
-			y1 := nat{}.sub(y.abs, natOne)
-			z.abs = z.abs.add(z.abs.and(x1, y1), natOne)
-			z.neg = true // z cannot be zero if x and y are negative
-			return z
-		}
-
-		// x | y == x | y
-		z.abs = z.abs.or(x.abs, y.abs)
-		z.neg = false
-		return z
-	}
-
-	// x.neg != y.neg
-	if x.neg {
-		x, y = y, x // | is symmetric
-	}
-
-	// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
-	y1 := nat{}.sub(y.abs, natOne)
-	z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne)
-	z.neg = true // z cannot be zero if one of x or y is negative
-	return z
-}
-
-// Xor sets z = x ^ y and returns z.
-func (z *Int) Xor(x, y *Int) *Int {
-	if x.neg == y.neg {
-		if x.neg {
-			// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
-			x1 := nat{}.sub(x.abs, natOne)
-			y1 := nat{}.sub(y.abs, natOne)
-			z.abs = z.abs.xor(x1, y1)
-			z.neg = false
-			return z
-		}
-
-		// x ^ y == x ^ y
-		z.abs = z.abs.xor(x.abs, y.abs)
-		z.neg = false
-		return z
-	}
-
-	// x.neg != y.neg
-	if x.neg {
-		x, y = y, x // ^ is symmetric
-	}
-
-	// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
-	y1 := nat{}.sub(y.abs, natOne)
-	z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne)
-	z.neg = true // z cannot be zero if only one of x or y is negative
-	return z
-}
-
-// Not sets z = ^x and returns z.
-func (z *Int) Not(x *Int) *Int {
-	if x.neg {
-		// ^(-x) == ^(^(x-1)) == x-1
-		z.abs = z.abs.sub(x.abs, natOne)
-		z.neg = false
-		return z
-	}
-
-	// ^x == -x-1 == -(x+1)
-	z.abs = z.abs.add(x.abs, natOne)
-	z.neg = true // z cannot be zero if x is positive
-	return z
-}
-
-// Gob codec version. Permits backward-compatible changes to the encoding.
-const intGobVersion byte = 1
-
-// GobEncode implements the gob.GobEncoder interface.
-func (z *Int) GobEncode() ([]byte, os.Error) {
-	buf := make([]byte, 1+len(z.abs)*_S) // extra byte for version and sign bit
-	i := z.abs.bytes(buf) - 1            // i >= 0
-	b := intGobVersion << 1              // make space for sign bit
-	if z.neg {
-		b |= 1
-	}
-	buf[i] = b
-	return buf[i:], nil
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (z *Int) GobDecode(buf []byte) os.Error {
-	if len(buf) == 0 {
-		return os.NewError("Int.GobDecode: no data")
-	}
-	b := buf[0]
-	if b>>1 != intGobVersion {
-		return os.NewError(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1))
-	}
-	z.neg = b&1 != 0
-	z.abs = z.abs.setBytes(buf[1:])
-	return nil
-}
diff --git a/src/pkg/big/int_test.go b/src/pkg/big/int_test.go
deleted file mode 100644
index b2e1692..0000000
--- a/src/pkg/big/int_test.go
+++ /dev/null
@@ -1,1394 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package big
-
-import (
-	"bytes"
-	"encoding/hex"
-	"fmt"
-	"gob"
-	"testing"
-	"testing/quick"
-)
-
-func isNormalized(x *Int) bool {
-	if len(x.abs) == 0 {
-		return !x.neg
-	}
-	// len(x.abs) > 0
-	return x.abs[len(x.abs)-1] != 0
-}
-
-type funZZ func(z, x, y *Int) *Int
-type argZZ struct {
-	z, x, y *Int
-}
-
-var sumZZ = []argZZ{
-	{NewInt(0), NewInt(0), NewInt(0)},
-	{NewInt(1), NewInt(1), NewInt(0)},
-	{NewInt(1111111110), NewInt(123456789), NewInt(987654321)},
-	{NewInt(-1), NewInt(-1), NewInt(0)},
-	{NewInt(864197532), NewInt(-123456789), NewInt(987654321)},
-	{NewInt(-1111111110), NewInt(-123456789), NewInt(-987654321)},
-}
-
-var prodZZ = []argZZ{
-	{NewInt(0), NewInt(0), NewInt(0)},
-	{NewInt(0), NewInt(1), NewInt(0)},
-	{NewInt(1), NewInt(1), NewInt(1)},
-	{NewInt(-991 * 991), NewInt(991), NewInt(-991)},
-	// TODO(gri) add larger products
-}
-
-func TestSignZ(t *testing.T) {
-	var zero Int
-	for _, a := range sumZZ {
-		s := a.z.Sign()
-		e := a.z.Cmp(&zero)
-		if s != e {
-			t.Errorf("got %d; want %d for z = %v", s, e, a.z)
-		}
-	}
-}
-
-func TestSetZ(t *testing.T) {
-	for _, a := range sumZZ {
-		var z Int
-		z.Set(a.z)
-		if !isNormalized(&z) {
-			t.Errorf("%v is not normalized", z)
-		}
-		if (&z).Cmp(a.z) != 0 {
-			t.Errorf("got z = %v; want %v", z, a.z)
-		}
-	}
-}
-
-func TestAbsZ(t *testing.T) {
-	var zero Int
-	for _, a := range sumZZ {
-		var z Int
-		z.Abs(a.z)
-		var e Int
-		e.Set(a.z)
-		if e.Cmp(&zero) < 0 {
-			e.Sub(&zero, &e)
-		}
-		if z.Cmp(&e) != 0 {
-			t.Errorf("got z = %v; want %v", z, e)
-		}
-	}
-}
-
-func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
-	var z Int
-	f(&z, a.x, a.y)
-	if !isNormalized(&z) {
-		t.Errorf("%s%v is not normalized", z, msg)
-	}
-	if (&z).Cmp(a.z) != 0 {
-		t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
-	}
-}
-
-func TestSumZZ(t *testing.T) {
-	AddZZ := func(z, x, y *Int) *Int { return z.Add(x, y) }
-	SubZZ := func(z, x, y *Int) *Int { return z.Sub(x, y) }
-	for _, a := range sumZZ {
-		arg := a
-		testFunZZ(t, "AddZZ", AddZZ, arg)
-
-		arg = argZZ{a.z, a.y, a.x}
-		testFunZZ(t, "AddZZ symmetric", AddZZ, arg)
-
-		arg = argZZ{a.x, a.z, a.y}
-		testFunZZ(t, "SubZZ", SubZZ, arg)
-
-		arg = argZZ{a.y, a.z, a.x}
-		testFunZZ(t, "SubZZ symmetric", SubZZ, arg)
-	}
-}
-
-func TestProdZZ(t *testing.T) {
-	MulZZ := func(z, x, y *Int) *Int { return z.Mul(x, y) }
-	for _, a := range prodZZ {
-		arg := a
-		testFunZZ(t, "MulZZ", MulZZ, arg)
-
-		arg = argZZ{a.z, a.y, a.x}
-		testFunZZ(t, "MulZZ symmetric", MulZZ, arg)
-	}
-}
-
-// mulBytes returns x*y via grade school multiplication. Both inputs
-// and the result are assumed to be in big-endian representation (to
-// match the semantics of Int.Bytes and Int.SetBytes).
-func mulBytes(x, y []byte) []byte {
-	z := make([]byte, len(x)+len(y))
-
-	// multiply
-	k0 := len(z) - 1
-	for j := len(y) - 1; j >= 0; j-- {
-		d := int(y[j])
-		if d != 0 {
-			k := k0
-			carry := 0
-			for i := len(x) - 1; i >= 0; i-- {
-				t := int(z[k]) + int(x[i])*d + carry
-				z[k], carry = byte(t), t>>8
-				k--
-			}
-			z[k] = byte(carry)
-		}
-		k0--
-	}
-
-	// normalize (remove leading 0's)
-	i := 0
-	for i < len(z) && z[i] == 0 {
-		i++
-	}
-
-	return z[i:]
-}
-
-func checkMul(a, b []byte) bool {
-	var x, y, z1 Int
-	x.SetBytes(a)
-	y.SetBytes(b)
-	z1.Mul(&x, &y)
-
-	var z2 Int
-	z2.SetBytes(mulBytes(a, b))
-
-	return z1.Cmp(&z2) == 0
-}
-
-func TestMul(t *testing.T) {
-	if err := quick.Check(checkMul, nil); err != nil {
-		t.Error(err)
-	}
-}
-
-var mulRangesZ = []struct {
-	a, b int64
-	prod string
-}{
-	// entirely positive ranges are covered by mulRangesN
-	{-1, 1, "0"},
-	{-2, -1, "2"},
-	{-3, -2, "6"},
-	{-3, -1, "-6"},
-	{1, 3, "6"},
-	{-10, -10, "-10"},
-	{0, -1, "1"},                      // empty range
-	{-1, -100, "1"},                   // empty range
-	{-1, 1, "0"},                      // range includes 0
-	{-1e9, 0, "0"},                    // range includes 0
-	{-1e9, 1e9, "0"},                  // range includes 0
-	{-10, -1, "3628800"},              // 10!
-	{-20, -2, "-2432902008176640000"}, // -20!
-	{-99, -1,
-		"-933262154439441526816992388562667004907159682643816214685929" +
-			"638952175999932299156089414639761565182862536979208272237582" +
-			"511852109168640000000000000000000000", // -99!
-	},
-}
-
-func TestMulRangeZ(t *testing.T) {
-	var tmp Int
-	// test entirely positive ranges
-	for i, r := range mulRangesN {
-		prod := tmp.MulRange(int64(r.a), int64(r.b)).String()
-		if prod != r.prod {
-			t.Errorf("#%da: got %s; want %s", i, prod, r.prod)
-		}
-	}
-	// test other ranges
-	for i, r := range mulRangesZ {
-		prod := tmp.MulRange(r.a, r.b).String()
-		if prod != r.prod {
-			t.Errorf("#%db: got %s; want %s", i, prod, r.prod)
-		}
-	}
-}
-
-var stringTests = []struct {
-	in   string
-	out  string
-	base int
-	val  int64
-	ok   bool
-}{
-	{in: "", ok: false},
-	{in: "a", ok: false},
-	{in: "z", ok: false},
-	{in: "+", ok: false},
-	{in: "-", ok: false},
-	{in: "0b", ok: false},
-	{in: "0x", ok: false},
-	{in: "2", base: 2, ok: false},
-	{in: "0b2", base: 0, ok: false},
-	{in: "08", ok: false},
-	{in: "8", base: 8, ok: false},
-	{in: "0xg", base: 0, ok: false},
-	{in: "g", base: 16, ok: false},
-	{"0", "0", 0, 0, true},
-	{"0", "0", 10, 0, true},
-	{"0", "0", 16, 0, true},
-	{"+0", "0", 0, 0, true},
-	{"-0", "0", 0, 0, true},
-	{"10", "10", 0, 10, true},
-	{"10", "10", 10, 10, true},
-	{"10", "10", 16, 16, true},
-	{"-10", "-10", 16, -16, true},
-	{"+10", "10", 16, 16, true},
-	{"0x10", "16", 0, 16, true},
-	{in: "0x10", base: 16, ok: false},
-	{"-0x10", "-16", 0, -16, true},
-	{"+0x10", "16", 0, 16, true},
-	{"00", "0", 0, 0, true},
-	{"0", "0", 8, 0, true},
-	{"07", "7", 0, 7, true},
-	{"7", "7", 8, 7, true},
-	{"023", "19", 0, 19, true},
-	{"23", "23", 8, 19, true},
-	{"cafebabe", "cafebabe", 16, 0xcafebabe, true},
-	{"0b0", "0", 0, 0, true},
-	{"-111", "-111", 2, -7, true},
-	{"-0b111", "-7", 0, -7, true},
-	{"0b1001010111", "599", 0, 0x257, true},
-	{"1001010111", "1001010111", 2, 0x257, true},
-}
-
-func format(base int) string {
-	switch base {
-	case 2:
-		return "%b"
-	case 8:
-		return "%o"
-	case 16:
-		return "%x"
-	}
-	return "%d"
-}
-
-func TestGetString(t *testing.T) {
-	z := new(Int)
-	for i, test := range stringTests {
-		if !test.ok {
-			continue
-		}
-		z.SetInt64(test.val)
-
-		if test.base == 10 {
-			s := z.String()
-			if s != test.out {
-				t.Errorf("#%da got %s; want %s", i, s, test.out)
-			}
-		}
-
-		s := fmt.Sprintf(format(test.base), z)
-		if s != test.out {
-			t.Errorf("#%db got %s; want %s", i, s, test.out)
-		}
-	}
-}
-
-func TestSetString(t *testing.T) {
-	tmp := new(Int)
-	for i, test := range stringTests {
-		// initialize to a non-zero value so that issues with parsing
-		// 0 are detected
-		tmp.SetInt64(1234567890)
-		n1, ok1 := new(Int).SetString(test.in, test.base)
-		n2, ok2 := tmp.SetString(test.in, test.base)
-		expected := NewInt(test.val)
-		if ok1 != test.ok || ok2 != test.ok {
-			t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
-			continue
-		}
-		if !ok1 || !ok2 {
-			continue
-		}
-
-		if ok1 && !isNormalized(n1) {
-			t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
-		}
-		if ok2 && !isNormalized(n2) {
-			t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
-		}
-
-		if n1.Cmp(expected) != 0 {
-			t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
-		}
-		if n2.Cmp(expected) != 0 {
-			t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
-		}
-	}
-}
-
-var formatTests = []struct {
-	input  string
-	format string
-	output string
-}{
-	{"<nil>", "%x", "<nil>"},
-	{"<nil>", "%#x", "<nil>"},
-	{"<nil>", "%#y", "%!y(big.Int=<nil>)"},
-
-	{"10", "%b", "1010"},
-	{"10", "%o", "12"},
-	{"10", "%d", "10"},
-	{"10", "%v", "10"},
-	{"10", "%x", "a"},
-	{"10", "%X", "A"},
-	{"-10", "%X", "-A"},
-	{"10", "%y", "%!y(big.Int=10)"},
-	{"-10", "%y", "%!y(big.Int=-10)"},
-
-	{"10", "%#b", "1010"},
-	{"10", "%#o", "012"},
-	{"10", "%#d", "10"},
-	{"10", "%#v", "10"},
-	{"10", "%#x", "0xa"},
-	{"10", "%#X", "0XA"},
-	{"-10", "%#X", "-0XA"},
-	{"10", "%#y", "%!y(big.Int=10)"},
-	{"-10", "%#y", "%!y(big.Int=-10)"},
-
-	{"1234", "%d", "1234"},
-	{"1234", "%3d", "1234"},
-	{"1234", "%4d", "1234"},
-	{"-1234", "%d", "-1234"},
-	{"1234", "% 5d", " 1234"},
-	{"1234", "%+5d", "+1234"},
-	{"1234", "%-5d", "1234 "},
-	{"1234", "%x", "4d2"},
-	{"1234", "%X", "4D2"},
-	{"-1234", "%3x", "-4d2"},
-	{"-1234", "%4x", "-4d2"},
-	{"-1234", "%5x", " -4d2"},
-	{"-1234", "%-5x", "-4d2 "},
-	{"1234", "%03d", "1234"},
-	{"1234", "%04d", "1234"},
-	{"1234", "%05d", "01234"},
-	{"1234", "%06d", "001234"},
-	{"-1234", "%06d", "-01234"},
-	{"1234", "%+06d", "+01234"},
-	{"1234", "% 06d", " 01234"},
-	{"1234", "%-6d", "1234  "},
-	{"1234", "%-06d", "1234  "},
-	{"-1234", "%-06d", "-1234 "},
-
-	{"1234", "%.3d", "1234"},
-	{"1234", "%.4d", "1234"},
-	{"1234", "%.5d", "01234"},
-	{"1234", "%.6d", "001234"},
-	{"-1234", "%.3d", "-1234"},
-	{"-1234", "%.4d", "-1234"},
-	{"-1234", "%.5d", "-01234"},
-	{"-1234", "%.6d", "-001234"},
-
-	{"1234", "%8.3d", "    1234"},
-	{"1234", "%8.4d", "    1234"},
-	{"1234", "%8.5d", "   01234"},
-	{"1234", "%8.6d", "  001234"},
-	{"-1234", "%8.3d", "   -1234"},
-	{"-1234", "%8.4d", "   -1234"},
-	{"-1234", "%8.5d", "  -01234"},
-	{"-1234", "%8.6d", " -001234"},
-
-	{"1234", "%+8.3d", "   +1234"},
-	{"1234", "%+8.4d", "   +1234"},
-	{"1234", "%+8.5d", "  +01234"},
-	{"1234", "%+8.6d", " +001234"},
-	{"-1234", "%+8.3d", "   -1234"},
-	{"-1234", "%+8.4d", "   -1234"},
-	{"-1234", "%+8.5d", "  -01234"},
-	{"-1234", "%+8.6d", " -001234"},
-
-	{"1234", "% 8.3d", "    1234"},
-	{"1234", "% 8.4d", "    1234"},
-	{"1234", "% 8.5d", "   01234"},
-	{"1234", "% 8.6d", "  001234"},
-	{"-1234", "% 8.3d", "   -1234"},
-	{"-1234", "% 8.4d", "   -1234"},
-	{"-1234", "% 8.5d", "  -01234"},
-	{"-1234", "% 8.6d", " -001234"},
-
-	{"1234", "%.3x", "4d2"},
-	{"1234", "%.4x", "04d2"},
-	{"1234", "%.5x", "004d2"},
-	{"1234", "%.6x", "0004d2"},
-	{"-1234", "%.3x", "-4d2"},
-	{"-1234", "%.4x", "-04d2"},
-	{"-1234", "%.5x", "-004d2"},
-	{"-1234", "%.6x", "-0004d2"},
-
-	{"1234", "%8.3x", "     4d2"},
-	{"1234", "%8.4x", "    04d2"},
-	{"1234", "%8.5x", "   004d2"},
-	{"1234", "%8.6x", "  0004d2"},
-	{"-1234", "%8.3x", "    -4d2"},
-	{"-1234", "%8.4x", "   -04d2"},
-	{"-1234", "%8.5x", "  -004d2"},
-	{"-1234", "%8.6x", " -0004d2"},
-
-	{"1234", "%+8.3x", "    +4d2"},
-	{"1234", "%+8.4x", "   +04d2"},
-	{"1234", "%+8.5x", "  +004d2"},
-	{"1234", "%+8.6x", " +0004d2"},
-	{"-1234", "%+8.3x", "    -4d2"},
-	{"-1234", "%+8.4x", "   -04d2"},
-	{"-1234", "%+8.5x", "  -004d2"},
-	{"-1234", "%+8.6x", " -0004d2"},
-
-	{"1234", "% 8.3x", "     4d2"},
-	{"1234", "% 8.4x", "    04d2"},
-	{"1234", "% 8.5x", "   004d2"},
-	{"1234", "% 8.6x", "  0004d2"},
-	{"1234", "% 8.7x", " 00004d2"},
-	{"1234", "% 8.8x", " 000004d2"},
-	{"-1234", "% 8.3x", "    -4d2"},
-	{"-1234", "% 8.4x", "   -04d2"},
-	{"-1234", "% 8.5x", "  -004d2"},
-	{"-1234", "% 8.6x", " -0004d2"},
-	{"-1234", "% 8.7x", "-00004d2"},
-	{"-1234", "% 8.8x", "-000004d2"},
-
-	{"1234", "%-8.3d", "1234    "},
-	{"1234", "%-8.4d", "1234    "},
-	{"1234", "%-8.5d", "01234   "},
-	{"1234", "%-8.6d", "001234  "},
-	{"1234", "%-8.7d", "0001234 "},
-	{"1234", "%-8.8d", "00001234"},
-	{"-1234", "%-8.3d", "-1234   "},
-	{"-1234", "%-8.4d", "-1234   "},
-	{"-1234", "%-8.5d", "-01234  "},
-	{"-1234", "%-8.6d", "-001234 "},
-	{"-1234", "%-8.7d", "-0001234"},
-	{"-1234", "%-8.8d", "-00001234"},
-
-	{"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
-
-	{"0", "%.d", ""},
-	{"0", "%.0d", ""},
-	{"0", "%3.d", ""},
-}
-
-func TestFormat(t *testing.T) {
-	for i, test := range formatTests {
-		var x *Int
-		if test.input != "<nil>" {
-			var ok bool
-			x, ok = new(Int).SetString(test.input, 0)
-			if !ok {
-				t.Errorf("#%d failed reading input %s", i, test.input)
-			}
-		}
-		output := fmt.Sprintf(test.format, x)
-		if output != test.output {
-			t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
-		}
-	}
-}
-
-var scanTests = []struct {
-	input     string
-	format    string
-	output    string
-	remaining int
-}{
-	{"1010", "%b", "10", 0},
-	{"0b1010", "%v", "10", 0},
-	{"12", "%o", "10", 0},
-	{"012", "%v", "10", 0},
-	{"10", "%d", "10", 0},
-	{"10", "%v", "10", 0},
-	{"a", "%x", "10", 0},
-	{"0xa", "%v", "10", 0},
-	{"A", "%X", "10", 0},
-	{"-A", "%X", "-10", 0},
-	{"+0b1011001", "%v", "89", 0},
-	{"0xA", "%v", "10", 0},
-	{"0 ", "%v", "0", 1},
-	{"2+3", "%v", "2", 2},
-	{"0XABC 12", "%v", "2748", 3},
-}
-
-func TestScan(t *testing.T) {
-	var buf bytes.Buffer
-	for i, test := range scanTests {
-		x := new(Int)
-		buf.Reset()
-		buf.WriteString(test.input)
-		if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
-			t.Errorf("#%d error: %s", i, err.String())
-		}
-		if x.String() != test.output {
-			t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
-		}
-		if buf.Len() != test.remaining {
-			t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
-		}
-	}
-}
-
-// Examples from the Go Language Spec, section "Arithmetic operators"
-var divisionSignsTests = []struct {
-	x, y int64
-	q, r int64 // T-division
-	d, m int64 // Euclidian division
-}{
-	{5, 3, 1, 2, 1, 2},
-	{-5, 3, -1, -2, -2, 1},
-	{5, -3, -1, 2, -1, 2},
-	{-5, -3, 1, -2, 2, 1},
-	{1, 2, 0, 1, 0, 1},
-	{8, 4, 2, 0, 2, 0},
-}
-
-func TestDivisionSigns(t *testing.T) {
-	for i, test := range divisionSignsTests {
-		x := NewInt(test.x)
-		y := NewInt(test.y)
-		q := NewInt(test.q)
-		r := NewInt(test.r)
-		d := NewInt(test.d)
-		m := NewInt(test.m)
-
-		q1 := new(Int).Quo(x, y)
-		r1 := new(Int).Rem(x, y)
-		if !isNormalized(q1) {
-			t.Errorf("#%d Quo: %v is not normalized", i, *q1)
-		}
-		if !isNormalized(r1) {
-			t.Errorf("#%d Rem: %v is not normalized", i, *r1)
-		}
-		if q1.Cmp(q) != 0 || r1.Cmp(r) != 0 {
-			t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q1, r1, q, r)
-		}
-
-		q2, r2 := new(Int).QuoRem(x, y, new(Int))
-		if !isNormalized(q2) {
-			t.Errorf("#%d Quo: %v is not normalized", i, *q2)
-		}
-		if !isNormalized(r2) {
-			t.Errorf("#%d Rem: %v is not normalized", i, *r2)
-		}
-		if q2.Cmp(q) != 0 || r2.Cmp(r) != 0 {
-			t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q2, r2, q, r)
-		}
-
-		d1 := new(Int).Div(x, y)
-		m1 := new(Int).Mod(x, y)
-		if !isNormalized(d1) {
-			t.Errorf("#%d Div: %v is not normalized", i, *d1)
-		}
-		if !isNormalized(m1) {
-			t.Errorf("#%d Mod: %v is not normalized", i, *m1)
-		}
-		if d1.Cmp(d) != 0 || m1.Cmp(m) != 0 {
-			t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d1, m1, d, m)
-		}
-
-		d2, m2 := new(Int).DivMod(x, y, new(Int))
-		if !isNormalized(d2) {
-			t.Errorf("#%d Div: %v is not normalized", i, *d2)
-		}
-		if !isNormalized(m2) {
-			t.Errorf("#%d Mod: %v is not normalized", i, *m2)
-		}
-		if d2.Cmp(d) != 0 || m2.Cmp(m) != 0 {
-			t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d2, m2, d, m)
-		}
-	}
-}
-
-func checkSetBytes(b []byte) bool {
-	hex1 := hex.EncodeToString(new(Int).SetBytes(b).Bytes())
-	hex2 := hex.EncodeToString(b)
-
-	for len(hex1) < len(hex2) {
-		hex1 = "0" + hex1
-	}
-
-	for len(hex1) > len(hex2) {
-		hex2 = "0" + hex2
-	}
-
-	return hex1 == hex2
-}
-
-func TestSetBytes(t *testing.T) {
-	if err := quick.Check(checkSetBytes, nil); err != nil {
-		t.Error(err)
-	}
-}
-
-func checkBytes(b []byte) bool {
-	b2 := new(Int).SetBytes(b).Bytes()
-	return bytes.Compare(b, b2) == 0
-}
-
-func TestBytes(t *testing.T) {
-	if err := quick.Check(checkSetBytes, nil); err != nil {
-		t.Error(err)
-	}
-}
-
-func checkQuo(x, y []byte) bool {
-	u := new(Int).SetBytes(x)
-	v := new(Int).SetBytes(y)
-
-	if len(v.abs) == 0 {
-		return true
-	}
-
-	r := new(Int)
-	q, r := new(Int).QuoRem(u, v, r)
-
-	if r.Cmp(v) >= 0 {
-		return false
-	}
-
-	uprime := new(Int).Set(q)
-	uprime.Mul(uprime, v)
-	uprime.Add(uprime, r)
-
-	return uprime.Cmp(u) == 0
-}
-
-var quoTests = []struct {
-	x, y string
-	q, r string
-}{
-	{
-		"476217953993950760840509444250624797097991362735329973741718102894495832294430498335824897858659711275234906400899559094370964723884706254265559534144986498357",
-		"9353930466774385905609975137998169297361893554149986716853295022578535724979483772383667534691121982974895531435241089241440253066816724367338287092081996",
-		"50911",
-		"1",
-	},
-	{
-		"11510768301994997771168",
-		"1328165573307167369775",
-		"8",
-		"885443715537658812968",
-	},
-}
-
-func TestQuo(t *testing.T) {
-	if err := quick.Check(checkQuo, nil); err != nil {
-		t.Error(err)
-	}
-
-	for i, test := range quoTests {
-		x, _ := new(Int).SetString(test.x, 10)
-		y, _ := new(Int).SetString(test.y, 10)
-		expectedQ, _ := new(Int).SetString(test.q, 10)
-		expectedR, _ := new(Int).SetString(test.r, 10)
-
-		r := new(Int)
-		q, r := new(Int).QuoRem(x, y, r)
-
-		if q.Cmp(expectedQ) != 0 || r.Cmp(expectedR) != 0 {
-			t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR)
-		}
-	}
-}
-
-func TestQuoStepD6(t *testing.T) {
-	// See Knuth, Volume 2, section 4.3.1, exercise 21. This code exercises
-	// a code path which only triggers 1 in 10^{-19} cases.
-
-	u := &Int{false, nat{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}}
-	v := &Int{false, nat{5, 2 + 1<<(_W-1), 1 << (_W - 1)}}
-
-	r := new(Int)
-	q, r := new(Int).QuoRem(u, v, r)
-	const expectedQ64 = "18446744073709551613"
-	const expectedR64 = "3138550867693340382088035895064302439801311770021610913807"
-	const expectedQ32 = "4294967293"
-	const expectedR32 = "39614081266355540837921718287"
-	if q.String() != expectedQ64 && q.String() != expectedQ32 ||
-		r.String() != expectedR64 && r.String() != expectedR32 {
-		t.Errorf("got (%s, %s) want (%s, %s) or (%s, %s)", q, r, expectedQ64, expectedR64, expectedQ32, expectedR32)
-	}
-}
-
-var bitLenTests = []struct {
-	in  string
-	out int
-}{
-	{"-1", 1},
-	{"0", 0},
-	{"1", 1},
-	{"2", 2},
-	{"4", 3},
-	{"0xabc", 12},
-	{"0x8000", 16},
-	{"0x80000000", 32},
-	{"0x800000000000", 48},
-	{"0x8000000000000000", 64},
-	{"0x80000000000000000000", 80},
-	{"-0x4000000000000000000000", 87},
-}
-
-func TestBitLen(t *testing.T) {
-	for i, test := range bitLenTests {
-		x, ok := new(Int).SetString(test.in, 0)
-		if !ok {
-			t.Errorf("#%d test input invalid: %s", i, test.in)
-			continue
-		}
-
-		if n := x.BitLen(); n != test.out {
-			t.Errorf("#%d got %d want %d", i, n, test.out)
-		}
-	}
-}
-
-var expTests = []struct {
-	x, y, m string
-	out     string
-}{
-	{"5", "0", "", "1"},
-	{"-5", "0", "", "-1"},
-	{"5", "1", "", "5"},
-	{"-5", "1", "", "-5"},
-	{"-2", "3", "2", "0"},
-	{"5", "2", "", "25"},
-	{"1", "65537", "2", "1"},
-	{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
-	{"0x8000000000000000", "2", "6719", "4944"},
-	{"0x8000000000000000", "3", "6719", "5447"},
-	{"0x8000000000000000", "1000", "6719", "1603"},
-	{"0x8000000000000000", "1000000", "6719", "3199"},
-	{
-		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
-		"298472983472983471903246121093472394872319615612417471234712061",
-		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
-		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
-	},
-}
-
-func TestExp(t *testing.T) {
-	for i, test := range expTests {
-		x, ok1 := new(Int).SetString(test.x, 0)
-		y, ok2 := new(Int).SetString(test.y, 0)
-		out, ok3 := new(Int).SetString(test.out, 0)
-
-		var ok4 bool
-		var m *Int
-
-		if len(test.m) == 0 {
-			m, ok4 = nil, true
-		} else {
-			m, ok4 = new(Int).SetString(test.m, 0)
-		}
-
-		if !ok1 || !ok2 || !ok3 || !ok4 {
-			t.Errorf("#%d: error in input", i)
-			continue
-		}
-
-		z := y.Exp(x, y, m)
-		if !isNormalized(z) {
-			t.Errorf("#%d: %v is not normalized", i, *z)
-		}
-		if z.Cmp(out) != 0 {
-			t.Errorf("#%d: got %s want %s", i, z, out)
-		}
-	}
-}
-
-func checkGcd(aBytes, bBytes []byte) bool {
-	a := new(Int).SetBytes(aBytes)
-	b := new(Int).SetBytes(bBytes)
-
-	x := new(Int)
-	y := new(Int)
-	d := new(Int)
-
-	GcdInt(d, x, y, a, b)
-	x.Mul(x, a)
-	y.Mul(y, b)
-	x.Add(x, y)
-
-	return x.Cmp(d) == 0
-}
-
-var gcdTests = []struct {
-	a, b    int64
-	d, x, y int64
-}{
-	{120, 23, 1, -9, 47},
-}
-
-func TestGcd(t *testing.T) {
-	for i, test := range gcdTests {
-		a := NewInt(test.a)
-		b := NewInt(test.b)
-
-		x := new(Int)
-		y := new(Int)
-		d := new(Int)
-
-		expectedX := NewInt(test.x)
-		expectedY := NewInt(test.y)
-		expectedD := NewInt(test.d)
-
-		GcdInt(d, x, y, a, b)
-
-		if expectedX.Cmp(x) != 0 ||
-			expectedY.Cmp(y) != 0 ||
-			expectedD.Cmp(d) != 0 {
-			t.Errorf("#%d got (%s %s %s) want (%s %s %s)", i, x, y, d, expectedX, expectedY, expectedD)
-		}
-	}
-
-	quick.Check(checkGcd, nil)
-}
-
-var primes = []string{
-	"2",
-	"3",
-	"5",
-	"7",
-	"11",
-
-	"13756265695458089029",
-	"13496181268022124907",
-	"10953742525620032441",
-	"17908251027575790097",
-
-	// http://code.google.com/p/go/issues/detail?id=638
-	"18699199384836356663",
-
-	"98920366548084643601728869055592650835572950932266967461790948584315647051443",
-	"94560208308847015747498523884063394671606671904944666360068158221458669711639",
-
-	// http://primes.utm.edu/lists/small/small3.html
-	"449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163",
-	"230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593",
-	"5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993",
-	"203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123",
-}
-
-var composites = []string{
-	"21284175091214687912771199898307297748211672914763848041968395774954376176754",
-	"6084766654921918907427900243509372380954290099172559290432744450051395395951",
-	"84594350493221918389213352992032324280367711247940675652888030554255915464401",
-	"82793403787388584738507275144194252681",
-}
-
-func TestProbablyPrime(t *testing.T) {
-	nreps := 20
-	if testing.Short() {
-		nreps = 1
-	}
-	for i, s := range primes {
-		p, _ := new(Int).SetString(s, 10)
-		if !ProbablyPrime(p, nreps) {
-			t.Errorf("#%d prime found to be non-prime (%s)", i, s)
-		}
-	}
-
-	for i, s := range composites {
-		c, _ := new(Int).SetString(s, 10)
-		if ProbablyPrime(c, nreps) {
-			t.Errorf("#%d composite found to be prime (%s)", i, s)
-		}
-		if testing.Short() {
-			break
-		}
-	}
-}
-
-type intShiftTest struct {
-	in    string
-	shift uint
-	out   string
-}
-
-var rshTests = []intShiftTest{
-	{"0", 0, "0"},
-	{"-0", 0, "0"},
-	{"0", 1, "0"},
-	{"0", 2, "0"},
-	{"1", 0, "1"},
-	{"1", 1, "0"},
-	{"1", 2, "0"},
-	{"2", 0, "2"},
-	{"2", 1, "1"},
-	{"-1", 0, "-1"},
-	{"-1", 1, "-1"},
-	{"-1", 10, "-1"},
-	{"-100", 2, "-25"},
-	{"-100", 3, "-13"},
-	{"-100", 100, "-1"},
-	{"4294967296", 0, "4294967296"},
-	{"4294967296", 1, "2147483648"},
-	{"4294967296", 2, "1073741824"},
-	{"18446744073709551616", 0, "18446744073709551616"},
-	{"18446744073709551616", 1, "9223372036854775808"},
-	{"18446744073709551616", 2, "4611686018427387904"},
-	{"18446744073709551616", 64, "1"},
-	{"340282366920938463463374607431768211456", 64, "18446744073709551616"},
-	{"340282366920938463463374607431768211456", 128, "1"},
-}
-
-func TestRsh(t *testing.T) {
-	for i, test := range rshTests {
-		in, _ := new(Int).SetString(test.in, 10)
-		expected, _ := new(Int).SetString(test.out, 10)
-		out := new(Int).Rsh(in, test.shift)
-
-		if !isNormalized(out) {
-			t.Errorf("#%d: %v is not normalized", i, *out)
-		}
-		if out.Cmp(expected) != 0 {
-			t.Errorf("#%d: got %s want %s", i, out, expected)
-		}
-	}
-}
-
-func TestRshSelf(t *testing.T) {
-	for i, test := range rshTests {
-		z, _ := new(Int).SetString(test.in, 10)
-		expected, _ := new(Int).SetString(test.out, 10)
-		z.Rsh(z, test.shift)
-
-		if !isNormalized(z) {
-			t.Errorf("#%d: %v is not normalized", i, *z)
-		}
-		if z.Cmp(expected) != 0 {
-			t.Errorf("#%d: got %s want %s", i, z, expected)
-		}
-	}
-}
-
-var lshTests = []intShiftTest{
-	{"0", 0, "0"},
-	{"0", 1, "0"},
-	{"0", 2, "0"},
-	{"1", 0, "1"},
-	{"1", 1, "2"},
-	{"1", 2, "4"},
-	{"2", 0, "2"},
-	{"2", 1, "4"},
-	{"2", 2, "8"},
-	{"-87", 1, "-174"},
-	{"4294967296", 0, "4294967296"},
-	{"4294967296", 1, "8589934592"},
-	{"4294967296", 2, "17179869184"},
-	{"18446744073709551616", 0, "18446744073709551616"},
-	{"9223372036854775808", 1, "18446744073709551616"},
-	{"4611686018427387904", 2, "18446744073709551616"},
-	{"1", 64, "18446744073709551616"},
-	{"18446744073709551616", 64, "340282366920938463463374607431768211456"},
-	{"1", 128, "340282366920938463463374607431768211456"},
-}
-
-func TestLsh(t *testing.T) {
-	for i, test := range lshTests {
-		in, _ := new(Int).SetString(test.in, 10)
-		expected, _ := new(Int).SetString(test.out, 10)
-		out := new(Int).Lsh(in, test.shift)
-
-		if !isNormalized(out) {
-			t.Errorf("#%d: %v is not normalized", i, *out)
-		}
-		if out.Cmp(expected) != 0 {
-			t.Errorf("#%d: got %s want %s", i, out, expected)
-		}
-	}
-}
-
-func TestLshSelf(t *testing.T) {
-	for i, test := range lshTests {
-		z, _ := new(Int).SetString(test.in, 10)
-		expected, _ := new(Int).SetString(test.out, 10)
-		z.Lsh(z, test.shift)
-
-		if !isNormalized(z) {
-			t.Errorf("#%d: %v is not normalized", i, *z)
-		}
-		if z.Cmp(expected) != 0 {
-			t.Errorf("#%d: got %s want %s", i, z, expected)
-		}
-	}
-}
-
-func TestLshRsh(t *testing.T) {
-	for i, test := range rshTests {
-		in, _ := new(Int).SetString(test.in, 10)
-		out := new(Int).Lsh(in, test.shift)
-		out = out.Rsh(out, test.shift)
-
-		if !isNormalized(out) {
-			t.Errorf("#%d: %v is not normalized", i, *out)
-		}
-		if in.Cmp(out) != 0 {
-			t.Errorf("#%d: got %s want %s", i, out, in)
-		}
-	}
-	for i, test := range lshTests {
-		in, _ := new(Int).SetString(test.in, 10)
-		out := new(Int).Lsh(in, test.shift)
-		out.Rsh(out, test.shift)
-
-		if !isNormalized(out) {
-			t.Errorf("#%d: %v is not normalized", i, *out)
-		}
-		if in.Cmp(out) != 0 {
-			t.Errorf("#%d: got %s want %s", i, out, in)
-		}
-	}
-}
-
-var int64Tests = []int64{
-	0,
-	1,
-	-1,
-	4294967295,
-	-4294967295,
-	4294967296,
-	-4294967296,
-	9223372036854775807,
-	-9223372036854775807,
-	-9223372036854775808,
-}
-
-func TestInt64(t *testing.T) {
-	for i, testVal := range int64Tests {
-		in := NewInt(testVal)
-		out := in.Int64()
-
-		if out != testVal {
-			t.Errorf("#%d got %d want %d", i, out, testVal)
-		}
-	}
-}
-
-var bitwiseTests = []struct {
-	x, y                 string
-	and, or, xor, andNot string
-}{
-	{"0x00", "0x00", "0x00", "0x00", "0x00", "0x00"},
-	{"0x00", "0x01", "0x00", "0x01", "0x01", "0x00"},
-	{"0x01", "0x00", "0x00", "0x01", "0x01", "0x01"},
-	{"-0x01", "0x00", "0x00", "-0x01", "-0x01", "-0x01"},
-	{"-0xaf", "-0x50", "-0xf0", "-0x0f", "0xe1", "0x41"},
-	{"0x00", "-0x01", "0x00", "-0x01", "-0x01", "0x00"},
-	{"0x01", "0x01", "0x01", "0x01", "0x00", "0x00"},
-	{"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"},
-	{"0x07", "0x08", "0x00", "0x0f", "0x0f", "0x07"},
-	{"0x05", "0x0f", "0x05", "0x0f", "0x0a", "0x00"},
-	{"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8", "0x0125b0"},
-	{"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc", "-0x01c000"},
-	{"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8", "0x8008"},
-	{
-		"0x1000009dc6e3d9822cba04129bcbe3401",
-		"0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
-		"0x1000001186210100001000009048c2001",
-		"0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
-		"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
-		"0x8c40c2d8822caa04120b8321400",
-	},
-	{
-		"0x1000009dc6e3d9822cba04129bcbe3401",
-		"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
-		"0x8c40c2d8822caa04120b8321401",
-		"-0xb9bd7d543685789d57ca918e82229142459020483cd2014001fd",
-		"-0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fe",
-		"0x1000001186210100001000009048c2000",
-	},
-	{
-		"-0x1000009dc6e3d9822cba04129bcbe3401",
-		"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
-		"-0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
-		"-0x1000001186210100001000009048c2001",
-		"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
-		"0xb9bd7d543685789d57ca918e82229142459020483cd2014001fc",
-	},
-}
-
-type bitFun func(z, x, y *Int) *Int
-
-func testBitFun(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
-	expected := new(Int)
-	expected.SetString(exp, 0)
-
-	out := f(new(Int), x, y)
-	if out.Cmp(expected) != 0 {
-		t.Errorf("%s: got %s want %s", msg, out, expected)
-	}
-}
-
-func testBitFunSelf(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
-	self := new(Int)
-	self.Set(x)
-	expected := new(Int)
-	expected.SetString(exp, 0)
-
-	self = f(self, self, y)
-	if self.Cmp(expected) != 0 {
-		t.Errorf("%s: got %s want %s", msg, self, expected)
-	}
-}
-
-func altBit(x *Int, i int) uint {
-	z := new(Int).Rsh(x, uint(i))
-	z = z.And(z, NewInt(1))
-	if z.Cmp(new(Int)) != 0 {
-		return 1
-	}
-	return 0
-}
-
-func altSetBit(z *Int, x *Int, i int, b uint) *Int {
-	one := NewInt(1)
-	m := one.Lsh(one, uint(i))
-	switch b {
-	case 1:
-		return z.Or(x, m)
-	case 0:
-		return z.AndNot(x, m)
-	}
-	panic("set bit is not 0 or 1")
-}
-
-func testBitset(t *testing.T, x *Int) {
-	n := x.BitLen()
-	z := new(Int).Set(x)
-	z1 := new(Int).Set(x)
-	for i := 0; i < n+10; i++ {
-		old := z.Bit(i)
-		old1 := altBit(z1, i)
-		if old != old1 {
-			t.Errorf("bitset: inconsistent value for Bit(%s, %d), got %v want %v", z1, i, old, old1)
-		}
-		z := new(Int).SetBit(z, i, 1)
-		z1 := altSetBit(new(Int), z1, i, 1)
-		if z.Bit(i) == 0 {
-			t.Errorf("bitset: bit %d of %s got 0 want 1", i, x)
-		}
-		if z.Cmp(z1) != 0 {
-			t.Errorf("bitset: inconsistent value after SetBit 1, got %s want %s", z, z1)
-		}
-		z.SetBit(z, i, 0)
-		altSetBit(z1, z1, i, 0)
-		if z.Bit(i) != 0 {
-			t.Errorf("bitset: bit %d of %s got 1 want 0", i, x)
-		}
-		if z.Cmp(z1) != 0 {
-			t.Errorf("bitset: inconsistent value after SetBit 0, got %s want %s", z, z1)
-		}
-		altSetBit(z1, z1, i, old)
-		z.SetBit(z, i, old)
-		if z.Cmp(z1) != 0 {
-			t.Errorf("bitset: inconsistent value after SetBit old, got %s want %s", z, z1)
-		}
-	}
-	if z.Cmp(x) != 0 {
-		t.Errorf("bitset: got %s want %s", z, x)
-	}
-}
-
-var bitsetTests = []struct {
-	x string
-	i int
-	b uint
-}{
-	{"0", 0, 0},
-	{"0", 200, 0},
-	{"1", 0, 1},
-	{"1", 1, 0},
-	{"-1", 0, 1},
-	{"-1", 200, 1},
-	{"0x2000000000000000000000000000", 108, 0},
-	{"0x2000000000000000000000000000", 109, 1},
-	{"0x2000000000000000000000000000", 110, 0},
-	{"-0x2000000000000000000000000001", 108, 1},
-	{"-0x2000000000000000000000000001", 109, 0},
-	{"-0x2000000000000000000000000001", 110, 1},
-}
-
-func TestBitSet(t *testing.T) {
-	for _, test := range bitwiseTests {
-		x := new(Int)
-		x.SetString(test.x, 0)
-		testBitset(t, x)
-		x = new(Int)
-		x.SetString(test.y, 0)
-		testBitset(t, x)
-	}
-	for i, test := range bitsetTests {
-		x := new(Int)
-		x.SetString(test.x, 0)
-		b := x.Bit(test.i)
-		if b != test.b {
-
-			t.Errorf("#%d want %v got %v", i, test.b, b)
-		}
-	}
-}
-
-func BenchmarkBitset(b *testing.B) {
-	z := new(Int)
-	z.SetBit(z, 512, 1)
-	b.ResetTimer()
-	b.StartTimer()
-	for i := b.N - 1; i >= 0; i-- {
-		z.SetBit(z, i&512, 1)
-	}
-}
-
-func BenchmarkBitsetNeg(b *testing.B) {
-	z := NewInt(-1)
-	z.SetBit(z, 512, 0)
-	b.ResetTimer()
-	b.StartTimer()
-	for i := b.N - 1; i >= 0; i-- {
-		z.SetBit(z, i&512, 0)
-	}
-}
-
-func BenchmarkBitsetOrig(b *testing.B) {
-	z := new(Int)
-	altSetBit(z, z, 512, 1)
-	b.ResetTimer()
-	b.StartTimer()
-	for i := b.N - 1; i >= 0; i-- {
-		altSetBit(z, z, i&512, 1)
-	}
-}
-
-func BenchmarkBitsetNegOrig(b *testing.B) {
-	z := NewInt(-1)
-	altSetBit(z, z, 512, 0)
-	b.ResetTimer()
-	b.StartTimer()
-	for i := b.N - 1; i >= 0; i-- {
-		altSetBit(z, z, i&512, 0)
-	}
-}
-
-func TestBitwise(t *testing.T) {
-	x := new(Int)
-	y := new(Int)
-	for _, test := range bitwiseTests {
-		x.SetString(test.x, 0)
-		y.SetString(test.y, 0)
-
-		testBitFun(t, "and", (*Int).And, x, y, test.and)
-		testBitFunSelf(t, "and", (*Int).And, x, y, test.and)
-		testBitFun(t, "andNot", (*Int).AndNot, x, y, test.andNot)
-		testBitFunSelf(t, "andNot", (*Int).AndNot, x, y, test.andNot)
-		testBitFun(t, "or", (*Int).Or, x, y, test.or)
-		testBitFunSelf(t, "or", (*Int).Or, x, y, test.or)
-		testBitFun(t, "xor", (*Int).Xor, x, y, test.xor)
-		testBitFunSelf(t, "xor", (*Int).Xor, x, y, test.xor)
-	}
-}
-
-var notTests = []struct {
-	in  string
-	out string
-}{
-	{"0", "-1"},
-	{"1", "-2"},
-	{"7", "-8"},
-	{"0", "-1"},
-	{"-81910", "81909"},
-	{
-		"298472983472983471903246121093472394872319615612417471234712061",
-		"-298472983472983471903246121093472394872319615612417471234712062",
-	},
-}
-
-func TestNot(t *testing.T) {
-	in := new(Int)
-	out := new(Int)
-	expected := new(Int)
-	for i, test := range notTests {
-		in.SetString(test.in, 10)
-		expected.SetString(test.out, 10)
-		out = out.Not(in)
-		if out.Cmp(expected) != 0 {
-			t.Errorf("#%d: got %s want %s", i, out, expected)
-		}
-		out = out.Not(out)
-		if out.Cmp(in) != 0 {
-			t.Errorf("#%d: got %s want %s", i, out, in)
-		}
-	}
-}
-
-var modInverseTests = []struct {
-	element string
-	prime   string
-}{
-	{"1", "7"},
-	{"1", "13"},
-	{"239487239847", "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"},
-}
-
-func TestModInverse(t *testing.T) {
-	var element, prime Int
-	one := NewInt(1)
-	for i, test := range modInverseTests {
-		(&element).SetString(test.element, 10)
-		(&prime).SetString(test.prime, 10)
-		inverse := new(Int).ModInverse(&element, &prime)
-		inverse.Mul(inverse, &element)
-		inverse.Mod(inverse, &prime)
-		if inverse.Cmp(one) != 0 {
-			t.Errorf("#%d: failed (e·e^(-1)=%s)", i, inverse)
-		}
-	}
-}
-
-// used by TestIntGobEncoding and TestRatGobEncoding
-var gobEncodingTests = []string{
-	"0",
-	"1",
-	"2",
-	"10",
-	"42",
-	"1234567890",
-	"298472983472983471903246121093472394872319615612417471234712061",
-}
-
-func TestIntGobEncoding(t *testing.T) {
-	var medium bytes.Buffer
-	enc := gob.NewEncoder(&medium)
-	dec := gob.NewDecoder(&medium)
-	for i, test := range gobEncodingTests {
-		for j := 0; j < 2; j++ {
-			medium.Reset() // empty buffer for each test case (in case of failures)
-			stest := test
-			if j != 0 {
-				// negative numbers
-				stest = "-" + test
-			}
-			var tx Int
-			tx.SetString(stest, 10)
-			if err := enc.Encode(&tx); err != nil {
-				t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
-			}
-			var rx Int
-			if err := dec.Decode(&rx); err != nil {
-				t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
-			}
-			if rx.Cmp(&tx) != 0 {
-				t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
-			}
-		}
-	}
-}
diff --git a/src/pkg/big/nat.go b/src/pkg/big/nat.go
deleted file mode 100644
index 33d6bb1..0000000
--- a/src/pkg/big/nat.go
+++ /dev/null
@@ -1,1272 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package big implements multi-precision arithmetic (big numbers).
-// The following numeric types are supported:
-//
-//	- Int	signed integers
-//	- Rat	rational numbers
-//
-// All methods on Int take the result as the receiver; if it is one
-// of the operands it may be overwritten (and its memory reused).
-// To enable chaining of operations, the result is also returned.
-//
-package big
-
-// This file contains operations on unsigned multi-precision integers.
-// These are the building blocks for the operations on signed integers
-// and rationals.
-
-import (
-	"io"
-	"os"
-	"rand"
-)
-
-// An unsigned integer x of the form
-//
-//   x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0]
-//
-// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n,
-// with the digits x[i] as the slice elements.
-//
-// A number is normalized if the slice contains no leading 0 digits.
-// During arithmetic operations, denormalized values may occur but are
-// always normalized before returning the final result. The normalized
-// representation of 0 is the empty or nil slice (length = 0).
-
-type nat []Word
-
-var (
-	natOne = nat{1}
-	natTwo = nat{2}
-	natTen = nat{10}
-)
-
-func (z nat) clear() {
-	for i := range z {
-		z[i] = 0
-	}
-}
-
-func (z nat) norm() nat {
-	i := len(z)
-	for i > 0 && z[i-1] == 0 {
-		i--
-	}
-	return z[0:i]
-}
-
-func (z nat) make(n int) nat {
-	if n <= cap(z) {
-		return z[0:n] // reuse z
-	}
-	// Choosing a good value for e has significant performance impact
-	// because it increases the chance that a value can be reused.
-	const e = 4 // extra capacity
-	return make(nat, n, n+e)
-}
-
-func (z nat) setWord(x Word) nat {
-	if x == 0 {
-		return z.make(0)
-	}
-	z = z.make(1)
-	z[0] = x
-	return z
-}
-
-func (z nat) setUint64(x uint64) nat {
-	// single-digit values
-	if w := Word(x); uint64(w) == x {
-		return z.setWord(w)
-	}
-
-	// compute number of words n required to represent x
-	n := 0
-	for t := x; t > 0; t >>= _W {
-		n++
-	}
-
-	// split x into n words
-	z = z.make(n)
-	for i := range z {
-		z[i] = Word(x & _M)
-		x >>= _W
-	}
-
-	return z
-}
-
-func (z nat) set(x nat) nat {
-	z = z.make(len(x))
-	copy(z, x)
-	return z
-}
-
-func (z nat) add(x, y nat) nat {
-	m := len(x)
-	n := len(y)
-
-	switch {
-	case m < n:
-		return z.add(y, x)
-	case m == 0:
-		// n == 0 because m >= n; result is 0
-		return z.make(0)
-	case n == 0:
-		// result is x
-		return z.set(x)
-	}
-	// m > 0
-
-	z = z.make(m + 1)
-	c := addVV(z[0:n], x, y)
-	if m > n {
-		c = addVW(z[n:m], x[n:], c)
-	}
-	z[m] = c
-
-	return z.norm()
-}
-
-func (z nat) sub(x, y nat) nat {
-	m := len(x)
-	n := len(y)
-
-	switch {
-	case m < n:
-		panic("underflow")
-	case m == 0:
-		// n == 0 because m >= n; result is 0
-		return z.make(0)
-	case n == 0:
-		// result is x
-		return z.set(x)
-	}
-	// m > 0
-
-	z = z.make(m)
-	c := subVV(z[0:n], x, y)
-	if m > n {
-		c = subVW(z[n:], x[n:], c)
-	}
-	if c != 0 {
-		panic("underflow")
-	}
-
-	return z.norm()
-}
-
-func (x nat) cmp(y nat) (r int) {
-	m := len(x)
-	n := len(y)
-	if m != n || m == 0 {
-		switch {
-		case m < n:
-			r = -1
-		case m > n:
-			r = 1
-		}
-		return
-	}
-
-	i := m - 1
-	for i > 0 && x[i] == y[i] {
-		i--
-	}
-
-	switch {
-	case x[i] < y[i]:
-		r = -1
-	case x[i] > y[i]:
-		r = 1
-	}
-	return
-}
-
-func (z nat) mulAddWW(x nat, y, r Word) nat {
-	m := len(x)
-	if m == 0 || y == 0 {
-		return z.setWord(r) // result is r
-	}
-	// m > 0
-
-	z = z.make(m + 1)
-	z[m] = mulAddVWW(z[0:m], x, y, r)
-
-	return z.norm()
-}
-
-// basicMul multiplies x and y and leaves the result in z.
-// The (non-normalized) result is placed in z[0 : len(x) + len(y)].
-func basicMul(z, x, y nat) {
-	z[0 : len(x)+len(y)].clear() // initialize z
-	for i, d := range y {
-		if d != 0 {
-			z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d)
-		}
-	}
-}
-
-// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks.
-// Factored out for readability - do not use outside karatsuba.
-func karatsubaAdd(z, x nat, n int) {
-	if c := addVV(z[0:n], z, x); c != 0 {
-		addVW(z[n:n+n>>1], z[n:], c)
-	}
-}
-
-// Like karatsubaAdd, but does subtract.
-func karatsubaSub(z, x nat, n int) {
-	if c := subVV(z[0:n], z, x); c != 0 {
-		subVW(z[n:n+n>>1], z[n:], c)
-	}
-}
-
-// Operands that are shorter than karatsubaThreshold are multiplied using
-// "grade school" multiplication; for longer operands the Karatsuba algorithm
-// is used.
-var karatsubaThreshold int = 32 // computed by calibrate.go
-
-// karatsuba multiplies x and y and leaves the result in z.
-// Both x and y must have the same length n and n must be a
-// power of 2. The result vector z must have len(z) >= 6*n.
-// The (non-normalized) result is placed in z[0 : 2*n].
-func karatsuba(z, x, y nat) {
-	n := len(y)
-
-	// Switch to basic multiplication if numbers are odd or small.
-	// (n is always even if karatsubaThreshold is even, but be
-	// conservative)
-	if n&1 != 0 || n < karatsubaThreshold || n < 2 {
-		basicMul(z, x, y)
-		return
-	}
-	// n&1 == 0 && n >= karatsubaThreshold && n >= 2
-
-	// Karatsuba multiplication is based on the observation that
-	// for two numbers x and y with:
-	//
-	//   x = x1*b + x0
-	//   y = y1*b + y0
-	//
-	// the product x*y can be obtained with 3 products z2, z1, z0
-	// instead of 4:
-	//
-	//   x*y = x1*y1*b*b + (x1*y0 + x0*y1)*b + x0*y0
-	//       =    z2*b*b +              z1*b +    z0
-	//
-	// with:
-	//
-	//   xd = x1 - x0
-	//   yd = y0 - y1
-	//
-	//   z1 =      xd*yd                    + z1 + z0
-	//      = (x1-x0)*(y0 - y1)             + z1 + z0
-	//      = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z1 + z0
-	//      = x1*y0 -    z1 -    z0 + x0*y1 + z1 + z0
-	//      = x1*y0                 + x0*y1
-
-	// split x, y into "digits"
-	n2 := n >> 1              // n2 >= 1
-	x1, x0 := x[n2:], x[0:n2] // x = x1*b + y0
-	y1, y0 := y[n2:], y[0:n2] // y = y1*b + y0
-
-	// z is used for the result and temporary storage:
-	//
-	//   6*n     5*n     4*n     3*n     2*n     1*n     0*n
-	// z = [z2 copy|z0 copy| xd*yd | yd:xd | x1*y1 | x0*y0 ]
-	//
-	// For each recursive call of karatsuba, an unused slice of
-	// z is passed in that has (at least) half the length of the
-	// caller's z.
-
-	// compute z0 and z2 with the result "in place" in z
-	karatsuba(z, x0, y0)     // z0 = x0*y0
-	karatsuba(z[n:], x1, y1) // z2 = x1*y1
-
-	// compute xd (or the negative value if underflow occurs)
-	s := 1 // sign of product xd*yd
-	xd := z[2*n : 2*n+n2]
-	if subVV(xd, x1, x0) != 0 { // x1-x0
-		s = -s
-		subVV(xd, x0, x1) // x0-x1
-	}
-
-	// compute yd (or the negative value if underflow occurs)
-	yd := z[2*n+n2 : 3*n]
-	if subVV(yd, y0, y1) != 0 { // y0-y1
-		s = -s
-		subVV(yd, y1, y0) // y1-y0
-	}
-
-	// p = (x1-x0)*(y0-y1) == x1*y0 - x1*y1 - x0*y0 + x0*y1 for s > 0
-	// p = (x0-x1)*(y0-y1) == x0*y0 - x0*y1 - x1*y0 + x1*y1 for s < 0
-	p := z[n*3:]
-	karatsuba(p, xd, yd)
-
-	// save original z2:z0
-	// (ok to use upper half of z since we're done recursing)
-	r := z[n*4:]
-	copy(r, z)
-
-	// add up all partial products
-	//
-	//   2*n     n     0
-	// z = [ z2  | z0  ]
-	//   +    [ z0  ]
-	//   +    [ z2  ]
-	//   +    [  p  ]
-	//
-	karatsubaAdd(z[n2:], r, n)
-	karatsubaAdd(z[n2:], r[n:], n)
-	if s > 0 {
-		karatsubaAdd(z[n2:], p, n)
-	} else {
-		karatsubaSub(z[n2:], p, n)
-	}
-}
-
-// alias returns true if x and y share the same base array.
-func alias(x, y nat) bool {
-	return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
-}
-
-// addAt implements z += x*(1<<(_W*i)); z must be long enough.
-// (we don't use nat.add because we need z to stay the same
-// slice, and we don't need to normalize z after each addition)
-func addAt(z, x nat, i int) {
-	if n := len(x); n > 0 {
-		if c := addVV(z[i:i+n], z[i:], x); c != 0 {
-			j := i + n
-			if j < len(z) {
-				addVW(z[j:], z[j:], c)
-			}
-		}
-	}
-}
-
-func max(x, y int) int {
-	if x > y {
-		return x
-	}
-	return y
-}
-
-// karatsubaLen computes an approximation to the maximum k <= n such that
-// k = p<<i for a number p <= karatsubaThreshold and an i >= 0. Thus, the
-// result is the largest number that can be divided repeatedly by 2 before
-// becoming about the value of karatsubaThreshold.
-func karatsubaLen(n int) int {
-	i := uint(0)
-	for n > karatsubaThreshold {
-		n >>= 1
-		i++
-	}
-	return n << i
-}
-
-func (z nat) mul(x, y nat) nat {
-	m := len(x)
-	n := len(y)
-
-	switch {
-	case m < n:
-		return z.mul(y, x)
-	case m == 0 || n == 0:
-		return z.make(0)
-	case n == 1:
-		return z.mulAddWW(x, y[0], 0)
-	}
-	// m >= n > 1
-
-	// determine if z can be reused
-	if alias(z, x) || alias(z, y) {
-		z = nil // z is an alias for x or y - cannot reuse
-	}
-
-	// use basic multiplication if the numbers are small
-	if n < karatsubaThreshold || n < 2 {
-		z = z.make(m + n)
-		basicMul(z, x, y)
-		return z.norm()
-	}
-	// m >= n && n >= karatsubaThreshold && n >= 2
-
-	// determine Karatsuba length k such that
-	//
-	//   x = x1*b + x0
-	//   y = y1*b + y0  (and k <= len(y), which implies k <= len(x))
-	//   b = 1<<(_W*k)  ("base" of digits xi, yi)
-	//
-	k := karatsubaLen(n)
-	// k <= n
-
-	// multiply x0 and y0 via Karatsuba
-	x0 := x[0:k]              // x0 is not normalized
-	y0 := y[0:k]              // y0 is not normalized
-	z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y
-	karatsuba(z, x0, y0)
-	z = z[0 : m+n] // z has final length but may be incomplete, upper portion is garbage
-
-	// If x1 and/or y1 are not 0, add missing terms to z explicitly:
-	//
-	//     m+n       2*k       0
-	//   z = [   ...   | x0*y0 ]
-	//     +   [ x1*y1 ]
-	//     +   [ x1*y0 ]
-	//     +   [ x0*y1 ]
-	//
-	if k < n || m != n {
-		x1 := x[k:] // x1 is normalized because x is
-		y1 := y[k:] // y1 is normalized because y is
-		var t nat
-		t = t.mul(x1, y1)
-		copy(z[2*k:], t)
-		z[2*k+len(t):].clear() // upper portion of z is garbage
-		t = t.mul(x1, y0.norm())
-		addAt(z, t, k)
-		t = t.mul(x0.norm(), y1)
-		addAt(z, t, k)
-	}
-
-	return z.norm()
-}
-
-// mulRange computes the product of all the unsigned integers in the
-// range [a, b] inclusively. If a > b (empty range), the result is 1.
-func (z nat) mulRange(a, b uint64) nat {
-	switch {
-	case a == 0:
-		// cut long ranges short (optimization)
-		return z.setUint64(0)
-	case a > b:
-		return z.setUint64(1)
-	case a == b:
-		return z.setUint64(a)
-	case a+1 == b:
-		return z.mul(nat(nil).setUint64(a), nat(nil).setUint64(b))
-	}
-	m := (a + b) / 2
-	return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b))
-}
-
-// q = (x-r)/y, with 0 <= r < y
-func (z nat) divW(x nat, y Word) (q nat, r Word) {
-	m := len(x)
-	switch {
-	case y == 0:
-		panic("division by zero")
-	case y == 1:
-		q = z.set(x) // result is x
-		return
-	case m == 0:
-		q = z.make(0) // result is 0
-		return
-	}
-	// m > 0
-	z = z.make(m)
-	r = divWVW(z, 0, x, y)
-	q = z.norm()
-	return
-}
-
-func (z nat) div(z2, u, v nat) (q, r nat) {
-	if len(v) == 0 {
-		panic("division by zero")
-	}
-
-	if u.cmp(v) < 0 {
-		q = z.make(0)
-		r = z2.set(u)
-		return
-	}
-
-	if len(v) == 1 {
-		var rprime Word
-		q, rprime = z.divW(u, v[0])
-		if rprime > 0 {
-			r = z2.make(1)
-			r[0] = rprime
-		} else {
-			r = z2.make(0)
-		}
-		return
-	}
-
-	q, r = z.divLarge(z2, u, v)
-	return
-}
-
-// q = (uIn-r)/v, with 0 <= r < y
-// Uses z as storage for q, and u as storage for r if possible.
-// See Knuth, Volume 2, section 4.3.1, Algorithm D.
-// Preconditions:
-//    len(v) >= 2
-//    len(uIn) >= len(v)
-func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
-	n := len(v)
-	m := len(uIn) - n
-
-	// determine if z can be reused
-	// TODO(gri) should find a better solution - this if statement
-	//           is very costly (see e.g. time pidigits -s -n 10000)
-	if alias(z, uIn) || alias(z, v) {
-		z = nil // z is an alias for uIn or v - cannot reuse
-	}
-	q = z.make(m + 1)
-
-	qhatv := make(nat, n+1)
-	if alias(u, uIn) || alias(u, v) {
-		u = nil // u is an alias for uIn or v - cannot reuse
-	}
-	u = u.make(len(uIn) + 1)
-	u.clear()
-
-	// D1.
-	shift := leadingZeros(v[n-1])
-	if shift > 0 {
-		// do not modify v, it may be used by another goroutine simultaneously
-		v1 := make(nat, n)
-		shlVU(v1, v, shift)
-		v = v1
-	}
-	u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift)
-
-	// D2.
-	for j := m; j >= 0; j-- {
-		// D3.
-		qhat := Word(_M)
-		if u[j+n] != v[n-1] {
-			var rhat Word
-			qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1])
-
-			// x1 | x2 = q̂v_{n-2}
-			x1, x2 := mulWW(qhat, v[n-2])
-			// test if q̂v_{n-2} > br̂ + u_{j+n-2}
-			for greaterThan(x1, x2, rhat, u[j+n-2]) {
-				qhat--
-				prevRhat := rhat
-				rhat += v[n-1]
-				// v[n-1] >= 0, so this tests for overflow.
-				if rhat < prevRhat {
-					break
-				}
-				x1, x2 = mulWW(qhat, v[n-2])
-			}
-		}
-
-		// D4.
-		qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0)
-
-		c := subVV(u[j:j+len(qhatv)], u[j:], qhatv)
-		if c != 0 {
-			c := addVV(u[j:j+n], u[j:], v)
-			u[j+n] += c
-			qhat--
-		}
-
-		q[j] = qhat
-	}
-
-	q = q.norm()
-	shrVU(u, u, shift)
-	r = u.norm()
-
-	return q, r
-}
-
-// Length of x in bits. x must be normalized.
-func (x nat) bitLen() int {
-	if i := len(x) - 1; i >= 0 {
-		return i*_W + bitLen(x[i])
-	}
-	return 0
-}
-
-// MaxBase is the largest number base accepted for string conversions.
-const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1
-
-
-func hexValue(ch int) Word {
-	d := MaxBase + 1 // illegal base
-	switch {
-	case '0' <= ch && ch <= '9':
-		d = ch - '0'
-	case 'a' <= ch && ch <= 'z':
-		d = ch - 'a' + 10
-	case 'A' <= ch && ch <= 'Z':
-		d = ch - 'A' + 10
-	}
-	return Word(d)
-}
-
-// scan sets z to the natural number corresponding to the longest possible prefix
-// read from r representing an unsigned integer in a given conversion base.
-// It returns z, the actual conversion base used, and an error, if any. In the
-// error case, the value of z is undefined. The syntax follows the syntax of
-// unsigned integer literals in Go.
-//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
-// is 0, the string prefix determines the actual conversion base. A prefix of
-// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
-// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
-//
-func (z nat) scan(r io.RuneScanner, base int) (nat, int, os.Error) {
-	// reject illegal bases
-	if base < 0 || base == 1 || MaxBase < base {
-		return z, 0, os.NewError("illegal number base")
-	}
-
-	// one char look-ahead
-	ch, _, err := r.ReadRune()
-	if err != nil {
-		return z, 0, err
-	}
-
-	// determine base if necessary
-	b := Word(base)
-	if base == 0 {
-		b = 10
-		if ch == '0' {
-			switch ch, _, err = r.ReadRune(); err {
-			case nil:
-				b = 8
-				switch ch {
-				case 'x', 'X':
-					b = 16
-				case 'b', 'B':
-					b = 2
-				}
-				if b == 2 || b == 16 {
-					if ch, _, err = r.ReadRune(); err != nil {
-						return z, 0, err
-					}
-				}
-			case os.EOF:
-				return z.make(0), 10, nil
-			default:
-				return z, 10, err
-			}
-		}
-	}
-
-	// convert string
-	// - group as many digits d as possible together into a "super-digit" dd with "super-base" bb
-	// - only when bb does not fit into a word anymore, do a full number mulAddWW using bb and dd
-	z = z.make(0)
-	bb := Word(1)
-	dd := Word(0)
-	for max := _M / b; ; {
-		d := hexValue(ch)
-		if d >= b {
-			r.UnreadRune() // ch does not belong to number anymore
-			break
-		}
-
-		if bb <= max {
-			bb *= b
-			dd = dd*b + d
-		} else {
-			// bb * b would overflow
-			z = z.mulAddWW(z, bb, dd)
-			bb = b
-			dd = d
-		}
-
-		if ch, _, err = r.ReadRune(); err != nil {
-			if err != os.EOF {
-				return z, int(b), err
-			}
-			break
-		}
-	}
-
-	switch {
-	case bb > 1:
-		// there was at least one mantissa digit
-		z = z.mulAddWW(z, bb, dd)
-	case base == 0 && b == 8:
-		// there was only the octal prefix 0 (possibly followed by digits > 7);
-		// return base 10, not 8
-		return z, 10, nil
-	case base != 0 || b != 8:
-		// there was neither a mantissa digit nor the octal prefix 0
-		return z, int(b), os.NewError("syntax error scanning number")
-	}
-
-	return z.norm(), int(b), nil
-}
-
-// Character sets for string conversion.
-const (
-	lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
-	uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-)
-
-// decimalString returns a decimal representation of x.
-// It calls x.string with the charset "0123456789".
-func (x nat) decimalString() string {
-	return x.string(lowercaseDigits[0:10])
-}
-
-// string converts x to a string using digits from a charset; a digit with
-// value d is represented by charset[d]. The conversion base is determined
-// by len(charset), which must be >= 2.
-func (x nat) string(charset string) string {
-	b := Word(len(charset))
-
-	// special cases
-	switch {
-	case b < 2 || b > 256:
-		panic("illegal base")
-	case len(x) == 0:
-		return string(charset[0])
-	}
-
-	// allocate buffer for conversion
-	i := x.bitLen()/log2(b) + 1 // +1: round up
-	s := make([]byte, i)
-
-	// special case: power of two bases can avoid divisions completely
-	if b == b&-b {
-		// shift is base-b digit size in bits
-		shift := uint(trailingZeroBits(b)) // shift > 0 because b >= 2
-		mask := Word(1)<<shift - 1
-		w := x[0]
-		nbits := uint(_W) // number of unprocessed bits in w
-
-		// convert less-significant words
-		for k := 1; k < len(x); k++ {
-			// convert full digits
-			for nbits >= shift {
-				i--
-				s[i] = charset[w&mask]
-				w >>= shift
-				nbits -= shift
-			}
-
-			// convert any partial leading digit and advance to next word
-			if nbits == 0 {
-				// no partial digit remaining, just advance
-				w = x[k]
-				nbits = _W
-			} else {
-				// partial digit in current (k-1) and next (k) word
-				w |= x[k] << nbits
-				i--
-				s[i] = charset[w&mask]
-
-				// advance
-				w = x[k] >> (shift - nbits)
-				nbits = _W - (shift - nbits)
-			}
-		}
-
-		// convert digits of most-significant word (omit leading zeros)
-		for nbits >= 0 && w != 0 {
-			i--
-			s[i] = charset[w&mask]
-			w >>= shift
-			nbits -= shift
-		}
-
-		return string(s[i:])
-	}
-
-	// general case: extract groups of digits by multiprecision division
-
-	// maximize ndigits where b**ndigits < 2^_W; bb (big base) is b**ndigits
-	bb := Word(1)
-	ndigits := 0
-	for max := Word(_M / b); bb <= max; bb *= b {
-		ndigits++
-	}
-
-	// preserve x, create local copy for use in repeated divisions
-	q := nat(nil).set(x)
-	var r Word
-
-	// convert
-	if b == 10 { // hard-coding for 10 here speeds this up by 1.25x
-		for len(q) > 0 {
-			// extract least significant, base bb "digit"
-			q, r = q.divW(q, bb) // N.B. >82% of time is here. Optimize divW
-			if len(q) == 0 {
-				// skip leading zeros in most-significant group of digits
-				for j := 0; j < ndigits && r != 0; j++ {
-					i--
-					s[i] = charset[r%10]
-					r /= 10
-				}
-			} else {
-				for j := 0; j < ndigits; j++ {
-					i--
-					s[i] = charset[r%10]
-					r /= 10
-				}
-			}
-		}
-	} else {
-		for len(q) > 0 {
-			// extract least significant group of digits
-			q, r = q.divW(q, bb) // N.B. >82% of time is here. Optimize divW
-			if len(q) == 0 {
-				// skip leading zeros in most-significant group of digits
-				for j := 0; j < ndigits && r != 0; j++ {
-					i--
-					s[i] = charset[r%b]
-					r /= b
-				}
-			} else {
-				for j := 0; j < ndigits; j++ {
-					i--
-					s[i] = charset[r%b]
-					r /= b
-				}
-			}
-		}
-	}
-
-	return string(s[i:])
-}
-
-const deBruijn32 = 0x077CB531
-
-var deBruijn32Lookup = []byte{
-	0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
-	31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
-}
-
-const deBruijn64 = 0x03f79d71b4ca8b09
-
-var deBruijn64Lookup = []byte{
-	0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
-	62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
-	63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
-	54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
-}
-
-// trailingZeroBits returns the number of consecutive zero bits on the right
-// side of the given Word.
-// See Knuth, volume 4, section 7.3.1
-func trailingZeroBits(x Word) int {
-	// x & -x leaves only the right-most bit set in the word. Let k be the
-	// index of that bit. Since only a single bit is set, the value is two
-	// to the power of k. Multiplying by a power of two is equivalent to
-	// left shifting, in this case by k bits.  The de Bruijn constant is
-	// such that all six bit, consecutive substrings are distinct.
-	// Therefore, if we have a left shifted version of this constant we can
-	// find by how many bits it was shifted by looking at which six bit
-	// substring ended up at the top of the word.
-	switch _W {
-	case 32:
-		return int(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
-	case 64:
-		return int(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
-	default:
-		panic("Unknown word size")
-	}
-
-	return 0
-}
-
-// z = x << s
-func (z nat) shl(x nat, s uint) nat {
-	m := len(x)
-	if m == 0 {
-		return z.make(0)
-	}
-	// m > 0
-
-	n := m + int(s/_W)
-	z = z.make(n + 1)
-	z[n] = shlVU(z[n-m:n], x, s%_W)
-	z[0 : n-m].clear()
-
-	return z.norm()
-}
-
-// z = x >> s
-func (z nat) shr(x nat, s uint) nat {
-	m := len(x)
-	n := m - int(s/_W)
-	if n <= 0 {
-		return z.make(0)
-	}
-	// n > 0
-
-	z = z.make(n)
-	shrVU(z, x[m-n:], s%_W)
-
-	return z.norm()
-}
-
-func (z nat) setBit(x nat, i uint, b uint) nat {
-	j := int(i / _W)
-	m := Word(1) << (i % _W)
-	n := len(x)
-	switch b {
-	case 0:
-		z = z.make(n)
-		copy(z, x)
-		if j >= n {
-			// no need to grow
-			return z
-		}
-		z[j] &^= m
-		return z.norm()
-	case 1:
-		if j >= n {
-			n = j + 1
-		}
-		z = z.make(n)
-		copy(z, x)
-		z[j] |= m
-		// no need to normalize
-		return z
-	}
-	panic("set bit is not 0 or 1")
-}
-
-func (z nat) bit(i uint) uint {
-	j := int(i / _W)
-	if j >= len(z) {
-		return 0
-	}
-	return uint(z[j] >> (i % _W) & 1)
-}
-
-func (z nat) and(x, y nat) nat {
-	m := len(x)
-	n := len(y)
-	if m > n {
-		m = n
-	}
-	// m <= n
-
-	z = z.make(m)
-	for i := 0; i < m; i++ {
-		z[i] = x[i] & y[i]
-	}
-
-	return z.norm()
-}
-
-func (z nat) andNot(x, y nat) nat {
-	m := len(x)
-	n := len(y)
-	if n > m {
-		n = m
-	}
-	// m >= n
-
-	z = z.make(m)
-	for i := 0; i < n; i++ {
-		z[i] = x[i] &^ y[i]
-	}
-	copy(z[n:m], x[n:m])
-
-	return z.norm()
-}
-
-func (z nat) or(x, y nat) nat {
-	m := len(x)
-	n := len(y)
-	s := x
-	if m < n {
-		n, m = m, n
-		s = y
-	}
-	// m >= n
-
-	z = z.make(m)
-	for i := 0; i < n; i++ {
-		z[i] = x[i] | y[i]
-	}
-	copy(z[n:m], s[n:m])
-
-	return z.norm()
-}
-
-func (z nat) xor(x, y nat) nat {
-	m := len(x)
-	n := len(y)
-	s := x
-	if m < n {
-		n, m = m, n
-		s = y
-	}
-	// m >= n
-
-	z = z.make(m)
-	for i := 0; i < n; i++ {
-		z[i] = x[i] ^ y[i]
-	}
-	copy(z[n:m], s[n:m])
-
-	return z.norm()
-}
-
-// greaterThan returns true iff (x1<<_W + x2) > (y1<<_W + y2)
-func greaterThan(x1, x2, y1, y2 Word) bool {
-	return x1 > y1 || x1 == y1 && x2 > y2
-}
-
-// modW returns x % d.
-func (x nat) modW(d Word) (r Word) {
-	// TODO(agl): we don't actually need to store the q value.
-	var q nat
-	q = q.make(len(x))
-	return divWVW(q, 0, x, d)
-}
-
-// powersOfTwoDecompose finds q and k with x = q * 1<<k and q is odd, or q and k are 0.
-func (x nat) powersOfTwoDecompose() (q nat, k int) {
-	if len(x) == 0 {
-		return x, 0
-	}
-
-	// One of the words must be non-zero by definition,
-	// so this loop will terminate with i < len(x), and
-	// i is the number of 0 words.
-	i := 0
-	for x[i] == 0 {
-		i++
-	}
-	n := trailingZeroBits(x[i]) // x[i] != 0
-
-	q = make(nat, len(x)-i)
-	shrVU(q, x[i:], uint(n))
-
-	q = q.norm()
-	k = i*_W + n
-	return
-}
-
-// random creates a random integer in [0..limit), using the space in z if
-// possible. n is the bit length of limit.
-func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
-	bitLengthOfMSW := uint(n % _W)
-	if bitLengthOfMSW == 0 {
-		bitLengthOfMSW = _W
-	}
-	mask := Word((1 << bitLengthOfMSW) - 1)
-	z = z.make(len(limit))
-
-	for {
-		for i := range z {
-			switch _W {
-			case 32:
-				z[i] = Word(rand.Uint32())
-			case 64:
-				z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32
-			}
-		}
-
-		z[len(limit)-1] &= mask
-
-		if z.cmp(limit) < 0 {
-			break
-		}
-	}
-
-	return z.norm()
-}
-
-// If m != nil, expNN calculates x**y mod m. Otherwise it calculates x**y. It
-// reuses the storage of z if possible.
-func (z nat) expNN(x, y, m nat) nat {
-	if alias(z, x) || alias(z, y) {
-		// We cannot allow in place modification of x or y.
-		z = nil
-	}
-
-	if len(y) == 0 {
-		z = z.make(1)
-		z[0] = 1
-		return z
-	}
-
-	if m != nil {
-		// We likely end up being as long as the modulus.
-		z = z.make(len(m))
-	}
-	z = z.set(x)
-	v := y[len(y)-1]
-	// It's invalid for the most significant word to be zero, therefore we
-	// will find a one bit.
-	shift := leadingZeros(v) + 1
-	v <<= shift
-	var q nat
-
-	const mask = 1 << (_W - 1)
-
-	// We walk through the bits of the exponent one by one. Each time we
-	// see a bit, we square, thus doubling the power. If the bit is a one,
-	// we also multiply by x, thus adding one to the power.
-
-	w := _W - int(shift)
-	for j := 0; j < w; j++ {
-		z = z.mul(z, z)
-
-		if v&mask != 0 {
-			z = z.mul(z, x)
-		}
-
-		if m != nil {
-			q, z = q.div(z, z, m)
-		}
-
-		v <<= 1
-	}
-
-	for i := len(y) - 2; i >= 0; i-- {
-		v = y[i]
-
-		for j := 0; j < _W; j++ {
-			z = z.mul(z, z)
-
-			if v&mask != 0 {
-				z = z.mul(z, x)
-			}
-
-			if m != nil {
-				q, z = q.div(z, z, m)
-			}
-
-			v <<= 1
-		}
-	}
-
-	return z
-}
-
-// probablyPrime performs reps Miller-Rabin tests to check whether n is prime.
-// If it returns true, n is prime with probability 1 - 1/4^reps.
-// If it returns false, n is not prime.
-func (n nat) probablyPrime(reps int) bool {
-	if len(n) == 0 {
-		return false
-	}
-
-	if len(n) == 1 {
-		if n[0] < 2 {
-			return false
-		}
-
-		if n[0]%2 == 0 {
-			return n[0] == 2
-		}
-
-		// We have to exclude these cases because we reject all
-		// multiples of these numbers below.
-		switch n[0] {
-		case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53:
-			return true
-		}
-	}
-
-	const primesProduct32 = 0xC0CFD797         // Π {p ∈ primes, 2 < p <= 29}
-	const primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53}
-
-	var r Word
-	switch _W {
-	case 32:
-		r = n.modW(primesProduct32)
-	case 64:
-		r = n.modW(primesProduct64 & _M)
-	default:
-		panic("Unknown word size")
-	}
-
-	if r%3 == 0 || r%5 == 0 || r%7 == 0 || r%11 == 0 ||
-		r%13 == 0 || r%17 == 0 || r%19 == 0 || r%23 == 0 || r%29 == 0 {
-		return false
-	}
-
-	if _W == 64 && (r%31 == 0 || r%37 == 0 || r%41 == 0 ||
-		r%43 == 0 || r%47 == 0 || r%53 == 0) {
-		return false
-	}
-
-	nm1 := nat(nil).sub(n, natOne)
-	// 1<<k * q = nm1;
-	q, k := nm1.powersOfTwoDecompose()
-
-	nm3 := nat(nil).sub(nm1, natTwo)
-	rand := rand.New(rand.NewSource(int64(n[0])))
-
-	var x, y, quotient nat
-	nm3Len := nm3.bitLen()
-
-NextRandom:
-	for i := 0; i < reps; i++ {
-		x = x.random(rand, nm3, nm3Len)
-		x = x.add(x, natTwo)
-		y = y.expNN(x, q, n)
-		if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
-			continue
-		}
-		for j := 1; j < k; j++ {
-			y = y.mul(y, y)
-			quotient, y = quotient.div(y, y, n)
-			if y.cmp(nm1) == 0 {
-				continue NextRandom
-			}
-			if y.cmp(natOne) == 0 {
-				return false
-			}
-		}
-		return false
-	}
-
-	return true
-}
-
-// bytes writes the value of z into buf using big-endian encoding.
-// len(buf) must be >= len(z)*_S. The value of z is encoded in the
-// slice buf[i:]. The number i of unused bytes at the beginning of
-// buf is returned as result.
-func (z nat) bytes(buf []byte) (i int) {
-	i = len(buf)
-	for _, d := range z {
-		for j := 0; j < _S; j++ {
-			i--
-			buf[i] = byte(d)
-			d >>= 8
-		}
-	}
-
-	for i < len(buf) && buf[i] == 0 {
-		i++
-	}
-
-	return
-}
-
-// setBytes interprets buf as the bytes of a big-endian unsigned
-// integer, sets z to that value, and returns z.
-func (z nat) setBytes(buf []byte) nat {
-	z = z.make((len(buf) + _S - 1) / _S)
-
-	k := 0
-	s := uint(0)
-	var d Word
-	for i := len(buf); i > 0; i-- {
-		d |= Word(buf[i-1]) << s
-		if s += 8; s == _S*8 {
-			z[k] = d
-			k++
-			s = 0
-			d = 0
-		}
-	}
-	if k < len(z) {
-		z[k] = d
-	}
-
-	return z.norm()
-}
diff --git a/src/pkg/big/nat_test.go b/src/pkg/big/nat_test.go
deleted file mode 100644
index 71d0860..0000000
--- a/src/pkg/big/nat_test.go
+++ /dev/null
@@ -1,669 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package big
-
-import (
-	"fmt"
-	"os"
-	"strings"
-	"testing"
-)
-
-var cmpTests = []struct {
-	x, y nat
-	r    int
-}{
-	{nil, nil, 0},
-	{nil, nat{}, 0},
-	{nat{}, nil, 0},
-	{nat{}, nat{}, 0},
-	{nat{0}, nat{0}, 0},
-	{nat{0}, nat{1}, -1},
-	{nat{1}, nat{0}, 1},
-	{nat{1}, nat{1}, 0},
-	{nat{0, _M}, nat{1}, 1},
-	{nat{1}, nat{0, _M}, -1},
-	{nat{1, _M}, nat{0, _M}, 1},
-	{nat{0, _M}, nat{1, _M}, -1},
-	{nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1},
-	{nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1},
-}
-
-func TestCmp(t *testing.T) {
-	for i, a := range cmpTests {
-		r := a.x.cmp(a.y)
-		if r != a.r {
-			t.Errorf("#%d got r = %v; want %v", i, r, a.r)
-		}
-	}
-}
-
-type funNN func(z, x, y nat) nat
-type argNN struct {
-	z, x, y nat
-}
-
-var sumNN = []argNN{
-	{},
-	{nat{1}, nil, nat{1}},
-	{nat{1111111110}, nat{123456789}, nat{987654321}},
-	{nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}},
-	{nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}},
-	{nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}},
-}
-
-var prodNN = []argNN{
-	{},
-	{nil, nil, nil},
-	{nil, nat{991}, nil},
-	{nat{991}, nat{991}, nat{1}},
-	{nat{991 * 991}, nat{991}, nat{991}},
-	{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}},
-	{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}},
-	{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}},
-}
-
-func TestSet(t *testing.T) {
-	for _, a := range sumNN {
-		z := nat(nil).set(a.z)
-		if z.cmp(a.z) != 0 {
-			t.Errorf("got z = %v; want %v", z, a.z)
-		}
-	}
-}
-
-func testFunNN(t *testing.T, msg string, f funNN, a argNN) {
-	z := f(nil, a.x, a.y)
-	if z.cmp(a.z) != 0 {
-		t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z)
-	}
-}
-
-func TestFunNN(t *testing.T) {
-	for _, a := range sumNN {
-		arg := a
-		testFunNN(t, "add", nat.add, arg)
-
-		arg = argNN{a.z, a.y, a.x}
-		testFunNN(t, "add symmetric", nat.add, arg)
-
-		arg = argNN{a.x, a.z, a.y}
-		testFunNN(t, "sub", nat.sub, arg)
-
-		arg = argNN{a.y, a.z, a.x}
-		testFunNN(t, "sub symmetric", nat.sub, arg)
-	}
-
-	for _, a := range prodNN {
-		arg := a
-		testFunNN(t, "mul", nat.mul, arg)
-
-		arg = argNN{a.z, a.y, a.x}
-		testFunNN(t, "mul symmetric", nat.mul, arg)
-	}
-}
-
-var mulRangesN = []struct {
-	a, b uint64
-	prod string
-}{
-	{0, 0, "0"},
-	{1, 1, "1"},
-	{1, 2, "2"},
-	{1, 3, "6"},
-	{10, 10, "10"},
-	{0, 100, "0"},
-	{0, 1e9, "0"},
-	{1, 0, "1"},                    // empty range
-	{100, 1, "1"},                  // empty range
-	{1, 10, "3628800"},             // 10!
-	{1, 20, "2432902008176640000"}, // 20!
-	{1, 100,
-		"933262154439441526816992388562667004907159682643816214685929" +
-			"638952175999932299156089414639761565182862536979208272237582" +
-			"51185210916864000000000000000000000000", // 100!
-	},
-}
-
-func TestMulRangeN(t *testing.T) {
-	for i, r := range mulRangesN {
-		prod := nat(nil).mulRange(r.a, r.b).decimalString()
-		if prod != r.prod {
-			t.Errorf("#%d: got %s; want %s", i, prod, r.prod)
-		}
-	}
-}
-
-var mulArg, mulTmp nat
-
-func init() {
-	const n = 1000
-	mulArg = make(nat, n)
-	for i := 0; i < n; i++ {
-		mulArg[i] = _M
-	}
-}
-
-func benchmarkMulLoad() {
-	for j := 1; j <= 10; j++ {
-		x := mulArg[0 : j*100]
-		mulTmp.mul(x, x)
-	}
-}
-
-func BenchmarkMul(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		benchmarkMulLoad()
-	}
-}
-
-func toString(x nat, charset string) string {
-	base := len(charset)
-
-	// special cases
-	switch {
-	case base < 2:
-		panic("illegal base")
-	case len(x) == 0:
-		return string(charset[0])
-	}
-
-	// allocate buffer for conversion
-	i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
-	s := make([]byte, i)
-
-	// don't destroy x
-	q := nat(nil).set(x)
-
-	// convert
-	for len(q) > 0 {
-		i--
-		var r Word
-		q, r = q.divW(q, Word(base))
-		s[i] = charset[r]
-	}
-
-	return string(s[i:])
-}
-
-var strTests = []struct {
-	x nat    // nat value to be converted
-	c string // conversion charset
-	s string // expected result
-}{
-	{nil, "01", "0"},
-	{nat{1}, "01", "1"},
-	{nat{0xc5}, "01", "11000101"},
-	{nat{03271}, lowercaseDigits[0:8], "3271"},
-	{nat{10}, lowercaseDigits[0:10], "10"},
-	{nat{1234567890}, uppercaseDigits[0:10], "1234567890"},
-	{nat{0xdeadbeef}, lowercaseDigits[0:16], "deadbeef"},
-	{nat{0xdeadbeef}, uppercaseDigits[0:16], "DEADBEEF"},
-	{nat{0x229be7}, lowercaseDigits[0:17], "1a2b3c"},
-	{nat{0x309663e6}, uppercaseDigits[0:32], "O9COV6"},
-}
-
-func TestString(t *testing.T) {
-	for _, a := range strTests {
-		s := a.x.string(a.c)
-		if s != a.s {
-			t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
-		}
-
-		x, b, err := nat(nil).scan(strings.NewReader(a.s), len(a.c))
-		if x.cmp(a.x) != 0 {
-			t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
-		}
-		if b != len(a.c) {
-			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
-		}
-		if err != nil {
-			t.Errorf("scan%+v\n\tgot error = %s", a, err)
-		}
-	}
-}
-
-var natScanTests = []struct {
-	s    string // string to be scanned
-	base int    // input base
-	x    nat    // expected nat
-	b    int    // expected base
-	ok   bool   // expected success
-	next int    // next character (or 0, if at EOF)
-}{
-	// error: illegal base
-	{base: -1},
-	{base: 1},
-	{base: 37},
-
-	// error: no mantissa
-	{},
-	{s: "?"},
-	{base: 10},
-	{base: 36},
-	{s: "?", base: 10},
-	{s: "0x"},
-	{s: "345", base: 2},
-
-	// no errors
-	{"0", 0, nil, 10, true, 0},
-	{"0", 10, nil, 10, true, 0},
-	{"0", 36, nil, 36, true, 0},
-	{"1", 0, nat{1}, 10, true, 0},
-	{"1", 10, nat{1}, 10, true, 0},
-	{"0 ", 0, nil, 10, true, ' '},
-	{"08", 0, nil, 10, true, '8'},
-	{"018", 0, nat{1}, 8, true, '8'},
-	{"0b1", 0, nat{1}, 2, true, 0},
-	{"0b11000101", 0, nat{0xc5}, 2, true, 0},
-	{"03271", 0, nat{03271}, 8, true, 0},
-	{"10ab", 0, nat{10}, 10, true, 'a'},
-	{"1234567890", 0, nat{1234567890}, 10, true, 0},
-	{"xyz", 36, nat{(33*36+34)*36 + 35}, 36, true, 0},
-	{"xyz?", 36, nat{(33*36+34)*36 + 35}, 36, true, '?'},
-	{"0x", 16, nil, 16, true, 'x'},
-	{"0xdeadbeef", 0, nat{0xdeadbeef}, 16, true, 0},
-	{"0XDEADBEEF", 0, nat{0xdeadbeef}, 16, true, 0},
-}
-
-func TestScanBase(t *testing.T) {
-	for _, a := range natScanTests {
-		r := strings.NewReader(a.s)
-		x, b, err := nat(nil).scan(r, a.base)
-		if err == nil && !a.ok {
-			t.Errorf("scan%+v\n\texpected error", a)
-		}
-		if err != nil {
-			if a.ok {
-				t.Errorf("scan%+v\n\tgot error = %s", a, err)
-			}
-			continue
-		}
-		if x.cmp(a.x) != 0 {
-			t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
-		}
-		if b != a.b {
-			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
-		}
-		next, _, err := r.ReadRune()
-		if err == os.EOF {
-			next = 0
-			err = nil
-		}
-		if err == nil && next != a.next {
-			t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
-		}
-	}
-}
-
-var pi = "3" +
-	"14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
-	"32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
-	"28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
-	"96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
-	"31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
-	"60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
-	"22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
-	"29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
-	"81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
-	"21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
-	"55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
-	"63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
-	"75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
-	"45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
-	"34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
-	"16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
-	"04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
-	"26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
-	"99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
-	"53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
-	"68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
-	"13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
-	"88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
-	"79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
-	"68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
-	"21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
-	"06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
-	"14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
-	"21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
-	"05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
-	"23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
-	"90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
-	"31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
-	"20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
-	"97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
-	"44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
-	"44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
-	"85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
-	"58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
-	"27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
-	"09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
-	"79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
-	"06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
-	"91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
-	"94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
-	"78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
-	"24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
-	"59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
-	"34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
-	"88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
-	"94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
-
-// Test case for BenchmarkScanPi.
-func TestScanPi(t *testing.T) {
-	var x nat
-	z, _, err := x.scan(strings.NewReader(pi), 10)
-	if err != nil {
-		t.Errorf("scanning pi: %s", err)
-	}
-	if s := z.decimalString(); s != pi {
-		t.Errorf("scanning pi: got %s", s)
-	}
-}
-
-func BenchmarkScanPi(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		var x nat
-		x.scan(strings.NewReader(pi), 10)
-	}
-}
-
-const (
-	// 314**271
-	// base  2: 2249 digits
-	// base  8:  751 digits
-	// base 10:  678 digits
-	// base 16:  563 digits
-	shortBase     = 314
-	shortExponent = 271
-
-	// 3141**2178
-	// base  2: 31577 digits
-	// base  8: 10527 digits
-	// base 10:  9507 digits
-	// base 16:  7895 digits
-	mediumBase     = 3141
-	mediumExponent = 2718
-
-	// 3141**2178
-	// base  2: 406078 digits
-	// base  8: 135360 digits
-	// base 10: 122243 digits
-	// base 16: 101521 digits
-	longBase     = 31415
-	longExponent = 27182
-)
-
-func BenchmarkScanShort2(b *testing.B) {
-	ScanHelper(b, 2, shortBase, shortExponent)
-}
-
-func BenchmarkScanShort8(b *testing.B) {
-	ScanHelper(b, 8, shortBase, shortExponent)
-}
-
-func BenchmarkScanSort10(b *testing.B) {
-	ScanHelper(b, 10, shortBase, shortExponent)
-}
-
-func BenchmarkScanShort16(b *testing.B) {
-	ScanHelper(b, 16, shortBase, shortExponent)
-}
-
-func BenchmarkScanMedium2(b *testing.B) {
-	ScanHelper(b, 2, mediumBase, mediumExponent)
-}
-
-func BenchmarkScanMedium8(b *testing.B) {
-	ScanHelper(b, 8, mediumBase, mediumExponent)
-}
-
-func BenchmarkScanMedium10(b *testing.B) {
-	ScanHelper(b, 10, mediumBase, mediumExponent)
-}
-
-func BenchmarkScanMedium16(b *testing.B) {
-	ScanHelper(b, 16, mediumBase, mediumExponent)
-}
-
-func BenchmarkScanLong2(b *testing.B) {
-	ScanHelper(b, 2, longBase, longExponent)
-}
-
-func BenchmarkScanLong8(b *testing.B) {
-	ScanHelper(b, 8, longBase, longExponent)
-}
-
-func BenchmarkScanLong10(b *testing.B) {
-	ScanHelper(b, 10, longBase, longExponent)
-}
-
-func BenchmarkScanLong16(b *testing.B) {
-	ScanHelper(b, 16, longBase, longExponent)
-}
-
-func ScanHelper(b *testing.B, base int, xv, yv Word) {
-	b.StopTimer()
-	var x, y, z nat
-	x = x.setWord(xv)
-	y = y.setWord(yv)
-	z = z.expNN(x, y, nil)
-
-	var s string
-	s = z.string(lowercaseDigits[0:base])
-	if t := toString(z, lowercaseDigits[0:base]); t != s {
-		panic(fmt.Sprintf("scanning: got %s; want %s", s, t))
-	}
-	b.StartTimer()
-
-	for i := 0; i < b.N; i++ {
-		x.scan(strings.NewReader(s), base)
-	}
-}
-
-func BenchmarkStringShort2(b *testing.B) {
-	StringHelper(b, 2, shortBase, shortExponent)
-}
-
-func BenchmarkStringShort8(b *testing.B) {
-	StringHelper(b, 8, shortBase, shortExponent)
-}
-
-func BenchmarkStringShort10(b *testing.B) {
-	StringHelper(b, 10, shortBase, shortExponent)
-}
-
-func BenchmarkStringShort16(b *testing.B) {
-	StringHelper(b, 16, shortBase, shortExponent)
-}
-
-func BenchmarkStringMedium2(b *testing.B) {
-	StringHelper(b, 2, mediumBase, mediumExponent)
-}
-
-func BenchmarkStringMedium8(b *testing.B) {
-	StringHelper(b, 8, mediumBase, mediumExponent)
-}
-
-func BenchmarkStringMedium10(b *testing.B) {
-	StringHelper(b, 10, mediumBase, mediumExponent)
-}
-
-func BenchmarkStringMedium16(b *testing.B) {
-	StringHelper(b, 16, mediumBase, mediumExponent)
-}
-
-func BenchmarkStringLong2(b *testing.B) {
-	StringHelper(b, 2, longBase, longExponent)
-}
-
-func BenchmarkStringLong8(b *testing.B) {
-	StringHelper(b, 8, longBase, longExponent)
-}
-
-func BenchmarkStringLong10(b *testing.B) {
-	StringHelper(b, 10, longBase, longExponent)
-}
-
-func BenchmarkStringLong16(b *testing.B) {
-	StringHelper(b, 16, longBase, longExponent)
-}
-
-func StringHelper(b *testing.B, base int, xv, yv Word) {
-	b.StopTimer()
-	var x, y, z nat
-	x = x.setWord(xv)
-	y = y.setWord(yv)
-	z = z.expNN(x, y, nil)
-	b.StartTimer()
-
-	for i := 0; i < b.N; i++ {
-		z.string(lowercaseDigits[0:base])
-	}
-}
-
-func TestLeadingZeros(t *testing.T) {
-	var x Word = _B >> 1
-	for i := 0; i <= _W; i++ {
-		if int(leadingZeros(x)) != i {
-			t.Errorf("failed at %x: got %d want %d", x, leadingZeros(x), i)
-		}
-		x >>= 1
-	}
-}
-
-type shiftTest struct {
-	in    nat
-	shift uint
-	out   nat
-}
-
-var leftShiftTests = []shiftTest{
-	{nil, 0, nil},
-	{nil, 1, nil},
-	{natOne, 0, natOne},
-	{natOne, 1, natTwo},
-	{nat{1 << (_W - 1)}, 1, nat{0}},
-	{nat{1 << (_W - 1), 0}, 1, nat{0, 1}},
-}
-
-func TestShiftLeft(t *testing.T) {
-	for i, test := range leftShiftTests {
-		var z nat
-		z = z.shl(test.in, test.shift)
-		for j, d := range test.out {
-			if j >= len(z) || z[j] != d {
-				t.Errorf("#%d: got: %v want: %v", i, z, test.out)
-				break
-			}
-		}
-	}
-}
-
-var rightShiftTests = []shiftTest{
-	{nil, 0, nil},
-	{nil, 1, nil},
-	{natOne, 0, natOne},
-	{natOne, 1, nil},
-	{natTwo, 1, natOne},
-	{nat{0, 1}, 1, nat{1 << (_W - 1)}},
-	{nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1)}},
-}
-
-func TestShiftRight(t *testing.T) {
-	for i, test := range rightShiftTests {
-		var z nat
-		z = z.shr(test.in, test.shift)
-		for j, d := range test.out {
-			if j >= len(z) || z[j] != d {
-				t.Errorf("#%d: got: %v want: %v", i, z, test.out)
-				break
-			}
-		}
-	}
-}
-
-type modWTest struct {
-	in       string
-	dividend string
-	out      string
-}
-
-var modWTests32 = []modWTest{
-	{"23492635982634928349238759823742", "252341", "220170"},
-}
-
-var modWTests64 = []modWTest{
-	{"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"},
-}
-
-func runModWTests(t *testing.T, tests []modWTest) {
-	for i, test := range tests {
-		in, _ := new(Int).SetString(test.in, 10)
-		d, _ := new(Int).SetString(test.dividend, 10)
-		out, _ := new(Int).SetString(test.out, 10)
-
-		r := in.abs.modW(d.abs[0])
-		if r != out.abs[0] {
-			t.Errorf("#%d failed: got %s want %s", i, r, out)
-		}
-	}
-}
-
-func TestModW(t *testing.T) {
-	if _W >= 32 {
-		runModWTests(t, modWTests32)
-	}
-	if _W >= 64 {
-		runModWTests(t, modWTests64)
-	}
-}
-
-func TestTrailingZeroBits(t *testing.T) {
-	var x Word
-	x--
-	for i := 0; i < _W; i++ {
-		if trailingZeroBits(x) != i {
-			t.Errorf("Failed at step %d: x: %x got: %d", i, x, trailingZeroBits(x))
-		}
-		x <<= 1
-	}
-}
-
-var expNNTests = []struct {
-	x, y, m string
-	out     string
-}{
-	{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
-	{"0x8000000000000000", "2", "6719", "4944"},
-	{"0x8000000000000000", "3", "6719", "5447"},
-	{"0x8000000000000000", "1000", "6719", "1603"},
-	{"0x8000000000000000", "1000000", "6719", "3199"},
-	{
-		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
-		"298472983472983471903246121093472394872319615612417471234712061",
-		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
-		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
-	},
-}
-
-func TestExpNN(t *testing.T) {
-	for i, test := range expNNTests {
-		x, _, _ := nat(nil).scan(strings.NewReader(test.x), 0)
-		y, _, _ := nat(nil).scan(strings.NewReader(test.y), 0)
-		out, _, _ := nat(nil).scan(strings.NewReader(test.out), 0)
-
-		var m nat
-
-		if len(test.m) > 0 {
-			m, _, _ = nat(nil).scan(strings.NewReader(test.m), 0)
-		}
-
-		z := nat(nil).expNN(x, y, m)
-		if z.cmp(out) != 0 {
-			t.Errorf("#%d got %v want %v", i, z, out)
-		}
-	}
-}
diff --git a/src/pkg/big/rat.go b/src/pkg/big/rat.go
deleted file mode 100644
index 327b9bd..0000000
--- a/src/pkg/big/rat.go
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2010 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 file implements multi-precision rational numbers.
-
-package big
-
-import (
-	"encoding/binary"
-	"fmt"
-	"os"
-	"strings"
-)
-
-// A Rat represents a quotient a/b of arbitrary precision. The zero value for
-// a Rat, 0/0, is not a legal Rat.
-type Rat struct {
-	a Int
-	b nat
-}
-
-// NewRat creates a new Rat with numerator a and denominator b.
-func NewRat(a, b int64) *Rat {
-	return new(Rat).SetFrac64(a, b)
-}
-
-// SetFrac sets z to a/b and returns z.
-func (z *Rat) SetFrac(a, b *Int) *Rat {
-	z.a.Set(a)
-	z.a.neg = a.neg != b.neg
-	z.b = z.b.set(b.abs)
-	return z.norm()
-}
-
-// SetFrac64 sets z to a/b and returns z.
-func (z *Rat) SetFrac64(a, b int64) *Rat {
-	z.a.SetInt64(a)
-	if b < 0 {
-		b = -b
-		z.a.neg = !z.a.neg
-	}
-	z.b = z.b.setUint64(uint64(b))
-	return z.norm()
-}
-
-// SetInt sets z to x (by making a copy of x) and returns z.
-func (z *Rat) SetInt(x *Int) *Rat {
-	z.a.Set(x)
-	z.b = z.b.setWord(1)
-	return z
-}
-
-// SetInt64 sets z to x and returns z.
-func (z *Rat) SetInt64(x int64) *Rat {
-	z.a.SetInt64(x)
-	z.b = z.b.setWord(1)
-	return z
-}
-
-// Sign returns:
-//
-//	-1 if x <  0
-//	 0 if x == 0
-//	+1 if x >  0
-//
-func (x *Rat) Sign() int {
-	return x.a.Sign()
-}
-
-// IsInt returns true if the denominator of x is 1.
-func (x *Rat) IsInt() bool {
-	return len(x.b) == 1 && x.b[0] == 1
-}
-
-// Num returns the numerator of z; it may be <= 0.
-// The result is a reference to z's numerator; it
-// may change if a new value is assigned to z.
-func (z *Rat) Num() *Int {
-	return &z.a
-}
-
-// Denom returns the denominator of z; it is always > 0.
-// The result is a reference to z's denominator; it
-// may change if a new value is assigned to z.
-func (z *Rat) Denom() *Int {
-	return &Int{false, z.b}
-}
-
-func gcd(x, y nat) nat {
-	// Euclidean algorithm.
-	var a, b nat
-	a = a.set(x)
-	b = b.set(y)
-	for len(b) != 0 {
-		var q, r nat
-		_, r = q.div(r, a, b)
-		a = b
-		b = r
-	}
-	return a
-}
-
-func (z *Rat) norm() *Rat {
-	f := gcd(z.a.abs, z.b)
-	if len(z.a.abs) == 0 {
-		// z == 0
-		z.a.neg = false // normalize sign
-		z.b = z.b.setWord(1)
-		return z
-	}
-	if f.cmp(natOne) != 0 {
-		z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f)
-		z.b, _ = z.b.div(nil, z.b, f)
-	}
-	return z
-}
-
-func mulNat(x *Int, y nat) *Int {
-	var z Int
-	z.abs = z.abs.mul(x.abs, y)
-	z.neg = len(z.abs) > 0 && x.neg
-	return &z
-}
-
-// Cmp compares x and y and returns:
-//
-//   -1 if x <  y
-//    0 if x == y
-//   +1 if x >  y
-//
-func (x *Rat) Cmp(y *Rat) (r int) {
-	return mulNat(&x.a, y.b).Cmp(mulNat(&y.a, x.b))
-}
-
-// Abs sets z to |x| (the absolute value of x) and returns z.
-func (z *Rat) Abs(x *Rat) *Rat {
-	z.a.Abs(&x.a)
-	z.b = z.b.set(x.b)
-	return z
-}
-
-// Add sets z to the sum x+y and returns z.
-func (z *Rat) Add(x, y *Rat) *Rat {
-	a1 := mulNat(&x.a, y.b)
-	a2 := mulNat(&y.a, x.b)
-	z.a.Add(a1, a2)
-	z.b = z.b.mul(x.b, y.b)
-	return z.norm()
-}
-
-// Sub sets z to the difference x-y and returns z.
-func (z *Rat) Sub(x, y *Rat) *Rat {
-	a1 := mulNat(&x.a, y.b)
-	a2 := mulNat(&y.a, x.b)
-	z.a.Sub(a1, a2)
-	z.b = z.b.mul(x.b, y.b)
-	return z.norm()
-}
-
-// Mul sets z to the product x*y and returns z.
-func (z *Rat) Mul(x, y *Rat) *Rat {
-	z.a.Mul(&x.a, &y.a)
-	z.b = z.b.mul(x.b, y.b)
-	return z.norm()
-}
-
-// Quo sets z to the quotient x/y and returns z.
-// If y == 0, a division-by-zero run-time panic occurs.
-func (z *Rat) Quo(x, y *Rat) *Rat {
-	if len(y.a.abs) == 0 {
-		panic("division by zero")
-	}
-	a := mulNat(&x.a, y.b)
-	b := mulNat(&y.a, x.b)
-	z.a.abs = a.abs
-	z.b = b.abs
-	z.a.neg = a.neg != b.neg
-	return z.norm()
-}
-
-// Neg sets z to -x (by making a copy of x if necessary) and returns z.
-func (z *Rat) Neg(x *Rat) *Rat {
-	z.a.Neg(&x.a)
-	z.b = z.b.set(x.b)
-	return z
-}
-
-// Set sets z to x (by making a copy of x if necessary) and returns z.
-func (z *Rat) Set(x *Rat) *Rat {
-	z.a.Set(&x.a)
-	z.b = z.b.set(x.b)
-	return z
-}
-
-func ratTok(ch int) bool {
-	return strings.IndexRune("+-/0123456789.eE", ch) >= 0
-}
-
-// Scan is a support routine for fmt.Scanner. It accepts the formats
-// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
-func (z *Rat) Scan(s fmt.ScanState, ch int) os.Error {
-	tok, err := s.Token(true, ratTok)
-	if err != nil {
-		return err
-	}
-	if strings.IndexRune("efgEFGv", ch) < 0 {
-		return os.NewError("Rat.Scan: invalid verb")
-	}
-	if _, ok := z.SetString(string(tok)); !ok {
-		return os.NewError("Rat.Scan: invalid syntax")
-	}
-	return nil
-}
-
-// SetString sets z to the value of s and returns z and a boolean indicating
-// success. s can be given as a fraction "a/b" or as a floating-point number
-// optionally followed by an exponent. If the operation failed, the value of z
-// is undefined.
-func (z *Rat) SetString(s string) (*Rat, bool) {
-	if len(s) == 0 {
-		return z, false
-	}
-
-	// check for a quotient
-	sep := strings.Index(s, "/")
-	if sep >= 0 {
-		if _, ok := z.a.SetString(s[0:sep], 10); !ok {
-			return z, false
-		}
-		s = s[sep+1:]
-		var err os.Error
-		if z.b, _, err = z.b.scan(strings.NewReader(s), 10); err != nil {
-			return z, false
-		}
-		return z.norm(), true
-	}
-
-	// check for a decimal point
-	sep = strings.Index(s, ".")
-	// check for an exponent
-	e := strings.IndexAny(s, "eE")
-	var exp Int
-	if e >= 0 {
-		if e < sep {
-			// The E must come after the decimal point.
-			return z, false
-		}
-		if _, ok := exp.SetString(s[e+1:], 10); !ok {
-			return z, false
-		}
-		s = s[0:e]
-	}
-	if sep >= 0 {
-		s = s[0:sep] + s[sep+1:]
-		exp.Sub(&exp, NewInt(int64(len(s)-sep)))
-	}
-
-	if _, ok := z.a.SetString(s, 10); !ok {
-		return z, false
-	}
-	powTen := nat{}.expNN(natTen, exp.abs, nil)
-	if exp.neg {
-		z.b = powTen
-		z.norm()
-	} else {
-		z.a.abs = z.a.abs.mul(z.a.abs, powTen)
-		z.b = z.b.setWord(1)
-	}
-
-	return z, true
-}
-
-// String returns a string representation of z in the form "a/b" (even if b == 1).
-func (z *Rat) String() string {
-	return z.a.String() + "/" + z.b.decimalString()
-}
-
-// RatString returns a string representation of z in the form "a/b" if b != 1,
-// and in the form "a" if b == 1.
-func (z *Rat) RatString() string {
-	if z.IsInt() {
-		return z.a.String()
-	}
-	return z.String()
-}
-
-// FloatString returns a string representation of z in decimal form with prec
-// digits of precision after the decimal point and the last digit rounded.
-func (z *Rat) FloatString(prec int) string {
-	if z.IsInt() {
-		s := z.a.String()
-		if prec > 0 {
-			s += "." + strings.Repeat("0", prec)
-		}
-		return s
-	}
-
-	q, r := nat{}.div(nat{}, z.a.abs, z.b)
-
-	p := natOne
-	if prec > 0 {
-		p = nat{}.expNN(natTen, nat{}.setUint64(uint64(prec)), nil)
-	}
-
-	r = r.mul(r, p)
-	r, r2 := r.div(nat{}, r, z.b)
-
-	// see if we need to round up
-	r2 = r2.add(r2, r2)
-	if z.b.cmp(r2) <= 0 {
-		r = r.add(r, natOne)
-		if r.cmp(p) >= 0 {
-			q = nat{}.add(q, natOne)
-			r = nat{}.sub(r, p)
-		}
-	}
-
-	s := q.decimalString()
-	if z.a.neg {
-		s = "-" + s
-	}
-
-	if prec > 0 {
-		rs := r.decimalString()
-		leadingZeros := prec - len(rs)
-		s += "." + strings.Repeat("0", leadingZeros) + rs
-	}
-
-	return s
-}
-
-// Gob codec version. Permits backward-compatible changes to the encoding.
-const ratGobVersion byte = 1
-
-// GobEncode implements the gob.GobEncoder interface.
-func (z *Rat) GobEncode() ([]byte, os.Error) {
-	buf := make([]byte, 1+4+(len(z.a.abs)+len(z.b))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
-	i := z.b.bytes(buf)
-	j := z.a.abs.bytes(buf[0:i])
-	n := i - j
-	if int(uint32(n)) != n {
-		// this should never happen
-		return nil, os.NewError("Rat.GobEncode: numerator too large")
-	}
-	binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
-	j -= 1 + 4
-	b := ratGobVersion << 1 // make space for sign bit
-	if z.a.neg {
-		b |= 1
-	}
-	buf[j] = b
-	return buf[j:], nil
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (z *Rat) GobDecode(buf []byte) os.Error {
-	if len(buf) == 0 {
-		return os.NewError("Rat.GobDecode: no data")
-	}
-	b := buf[0]
-	if b>>1 != ratGobVersion {
-		return os.NewError(fmt.Sprintf("Rat.GobDecode: encoding version %d not supported", b>>1))
-	}
-	const j = 1 + 4
-	i := j + binary.BigEndian.Uint32(buf[j-4:j])
-	z.a.neg = b&1 != 0
-	z.a.abs = z.a.abs.setBytes(buf[j:i])
-	z.b = z.b.setBytes(buf[i:])
-	return nil
-}
diff --git a/src/pkg/big/rat_test.go b/src/pkg/big/rat_test.go
deleted file mode 100644
index dbc5bb6..0000000
--- a/src/pkg/big/rat_test.go
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright 2010 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 big
-
-import (
-	"bytes"
-	"fmt"
-	"gob"
-	"testing"
-)
-
-var setStringTests = []struct {
-	in, out string
-	ok      bool
-}{
-	{"0", "0", true},
-	{"-0", "0", true},
-	{"1", "1", true},
-	{"-1", "-1", true},
-	{"1.", "1", true},
-	{"1e0", "1", true},
-	{"1.e1", "10", true},
-	{in: "1e", ok: false},
-	{in: "1.e", ok: false},
-	{in: "1e+14e-5", ok: false},
-	{in: "1e4.5", ok: false},
-	{in: "r", ok: false},
-	{in: "a/b", ok: false},
-	{in: "a.b", ok: false},
-	{"-0.1", "-1/10", true},
-	{"-.1", "-1/10", true},
-	{"2/4", "1/2", true},
-	{".25", "1/4", true},
-	{"-1/5", "-1/5", true},
-	{"8129567.7690E14", "812956776900000000000", true},
-	{"78189e+4", "781890000", true},
-	{"553019.8935e+8", "55301989350000", true},
-	{"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
-	{"9877861857500000E-7", "3951144743/4", true},
-	{"2169378.417e-3", "2169378417/1000000", true},
-	{"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
-	{"53/70893980658822810696", "53/70893980658822810696", true},
-	{"106/141787961317645621392", "53/70893980658822810696", true},
-	{"204211327800791583.81095", "4084226556015831676219/20000", true},
-}
-
-func TestRatSetString(t *testing.T) {
-	for i, test := range setStringTests {
-		x, ok := new(Rat).SetString(test.in)
-
-		if ok != test.ok || ok && x.RatString() != test.out {
-			t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
-		}
-	}
-}
-
-func TestRatScan(t *testing.T) {
-	var buf bytes.Buffer
-	for i, test := range setStringTests {
-		x := new(Rat)
-		buf.Reset()
-		buf.WriteString(test.in)
-
-		_, err := fmt.Fscanf(&buf, "%v", x)
-		if err == nil != test.ok {
-			if test.ok {
-				t.Errorf("#%d error: %s", i, err.String())
-			} else {
-				t.Errorf("#%d expected error", i)
-			}
-			continue
-		}
-		if err == nil && x.RatString() != test.out {
-			t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
-		}
-	}
-}
-
-var floatStringTests = []struct {
-	in   string
-	prec int
-	out  string
-}{
-	{"0", 0, "0"},
-	{"0", 4, "0.0000"},
-	{"1", 0, "1"},
-	{"1", 2, "1.00"},
-	{"-1", 0, "-1"},
-	{".25", 2, "0.25"},
-	{".25", 1, "0.3"},
-	{".25", 3, "0.250"},
-	{"-1/3", 3, "-0.333"},
-	{"-2/3", 4, "-0.6667"},
-	{"0.96", 1, "1.0"},
-	{"0.999", 2, "1.00"},
-	{"0.9", 0, "1"},
-	{".25", -1, "0"},
-	{".55", -1, "1"},
-}
-
-func TestFloatString(t *testing.T) {
-	for i, test := range floatStringTests {
-		x, _ := new(Rat).SetString(test.in)
-
-		if x.FloatString(test.prec) != test.out {
-			t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
-		}
-	}
-}
-
-func TestRatSign(t *testing.T) {
-	zero := NewRat(0, 1)
-	for _, a := range setStringTests {
-		var x Rat
-		x.SetString(a.in)
-		s := x.Sign()
-		e := x.Cmp(zero)
-		if s != e {
-			t.Errorf("got %d; want %d for z = %v", s, e, &x)
-		}
-	}
-}
-
-var ratCmpTests = []struct {
-	rat1, rat2 string
-	out        int
-}{
-	{"0", "0/1", 0},
-	{"1/1", "1", 0},
-	{"-1", "-2/2", 0},
-	{"1", "0", 1},
-	{"0/1", "1/1", -1},
-	{"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
-	{"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
-	{"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
-	{"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
-}
-
-func TestRatCmp(t *testing.T) {
-	for i, test := range ratCmpTests {
-		x, _ := new(Rat).SetString(test.rat1)
-		y, _ := new(Rat).SetString(test.rat2)
-
-		out := x.Cmp(y)
-		if out != test.out {
-			t.Errorf("#%d got out = %v; want %v", i, out, test.out)
-		}
-	}
-}
-
-func TestIsInt(t *testing.T) {
-	one := NewInt(1)
-	for _, a := range setStringTests {
-		var x Rat
-		x.SetString(a.in)
-		i := x.IsInt()
-		e := x.Denom().Cmp(one) == 0
-		if i != e {
-			t.Errorf("got %v; want %v for z = %v", i, e, &x)
-		}
-	}
-}
-
-func TestRatAbs(t *testing.T) {
-	zero := NewRat(0, 1)
-	for _, a := range setStringTests {
-		var z Rat
-		z.SetString(a.in)
-		var e Rat
-		e.Set(&z)
-		if e.Cmp(zero) < 0 {
-			e.Sub(zero, &e)
-		}
-		z.Abs(&z)
-		if z.Cmp(&e) != 0 {
-			t.Errorf("got z = %v; want %v", &z, &e)
-		}
-	}
-}
-
-type ratBinFun func(z, x, y *Rat) *Rat
-type ratBinArg struct {
-	x, y, z string
-}
-
-func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) {
-	x, _ := NewRat(0, 1).SetString(a.x)
-	y, _ := NewRat(0, 1).SetString(a.y)
-	z, _ := NewRat(0, 1).SetString(a.z)
-	out := f(NewRat(0, 1), x, y)
-
-	if out.Cmp(z) != 0 {
-		t.Errorf("%s #%d got %s want %s", name, i, out, z)
-	}
-}
-
-var ratBinTests = []struct {
-	x, y      string
-	sum, prod string
-}{
-	{"0", "0", "0", "0"},
-	{"0", "1", "1", "0"},
-	{"-1", "0", "-1", "0"},
-	{"-1", "1", "0", "-1"},
-	{"1", "1", "2", "1"},
-	{"1/2", "1/2", "1", "1/4"},
-	{"1/4", "1/3", "7/12", "1/12"},
-	{"2/5", "-14/3", "-64/15", "-28/15"},
-	{"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"},
-	{"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"},
-	{"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"},
-	{"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"},
-	{"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"},
-	{"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"},
-	{"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"},
-	{"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"},
-	{"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"},
-	{"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"},
-}
-
-func TestRatBin(t *testing.T) {
-	for i, test := range ratBinTests {
-		arg := ratBinArg{test.x, test.y, test.sum}
-		testRatBin(t, i, "Add", (*Rat).Add, arg)
-
-		arg = ratBinArg{test.y, test.x, test.sum}
-		testRatBin(t, i, "Add symmetric", (*Rat).Add, arg)
-
-		arg = ratBinArg{test.sum, test.x, test.y}
-		testRatBin(t, i, "Sub", (*Rat).Sub, arg)
-
-		arg = ratBinArg{test.sum, test.y, test.x}
-		testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg)
-
-		arg = ratBinArg{test.x, test.y, test.prod}
-		testRatBin(t, i, "Mul", (*Rat).Mul, arg)
-
-		arg = ratBinArg{test.y, test.x, test.prod}
-		testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg)
-
-		if test.x != "0" {
-			arg = ratBinArg{test.prod, test.x, test.y}
-			testRatBin(t, i, "Quo", (*Rat).Quo, arg)
-		}
-
-		if test.y != "0" {
-			arg = ratBinArg{test.prod, test.y, test.x}
-			testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg)
-		}
-	}
-}
-
-func TestIssue820(t *testing.T) {
-	x := NewRat(3, 1)
-	y := NewRat(2, 1)
-	z := y.Quo(x, y)
-	q := NewRat(3, 2)
-	if z.Cmp(q) != 0 {
-		t.Errorf("got %s want %s", z, q)
-	}
-
-	y = NewRat(3, 1)
-	x = NewRat(2, 1)
-	z = y.Quo(x, y)
-	q = NewRat(2, 3)
-	if z.Cmp(q) != 0 {
-		t.Errorf("got %s want %s", z, q)
-	}
-
-	x = NewRat(3, 1)
-	z = x.Quo(x, x)
-	q = NewRat(3, 3)
-	if z.Cmp(q) != 0 {
-		t.Errorf("got %s want %s", z, q)
-	}
-}
-
-var setFrac64Tests = []struct {
-	a, b int64
-	out  string
-}{
-	{0, 1, "0"},
-	{0, -1, "0"},
-	{1, 1, "1"},
-	{-1, 1, "-1"},
-	{1, -1, "-1"},
-	{-1, -1, "1"},
-	{-9223372036854775808, -9223372036854775808, "1"},
-}
-
-func TestRatSetFrac64Rat(t *testing.T) {
-	for i, test := range setFrac64Tests {
-		x := new(Rat).SetFrac64(test.a, test.b)
-		if x.RatString() != test.out {
-			t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
-		}
-	}
-}
-
-func TestRatGobEncoding(t *testing.T) {
-	var medium bytes.Buffer
-	enc := gob.NewEncoder(&medium)
-	dec := gob.NewDecoder(&medium)
-	for i, test := range gobEncodingTests {
-		for j := 0; j < 4; j++ {
-			medium.Reset() // empty buffer for each test case (in case of failures)
-			stest := test
-			if j&1 != 0 {
-				// negative numbers
-				stest = "-" + test
-			}
-			if j%2 != 0 {
-				// fractions
-				stest = stest + "." + test
-			}
-			var tx Rat
-			tx.SetString(stest)
-			if err := enc.Encode(&tx); err != nil {
-				t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
-			}
-			var rx Rat
-			if err := dec.Decode(&rx); err != nil {
-				t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
-			}
-			if rx.Cmp(&tx) != 0 {
-				t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
-			}
-		}
-	}
-}
diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go
index 2ea7af3..907a9dc 100644
--- a/src/pkg/bufio/bufio.go
+++ b/src/pkg/bufio/bufio.go
@@ -10,9 +10,8 @@ package bufio
 import (
 	"bytes"
 	"io"
-	"os"
 	"strconv"
-	"utf8"
+	"unicode/utf8"
 )
 
 const (
@@ -24,20 +23,20 @@ type Error struct {
 	ErrorString string
 }
 
-func (err *Error) String() string { return err.ErrorString }
+func (err *Error) Error() string { return err.ErrorString }
 
 var (
-	ErrInvalidUnreadByte os.Error = &Error{"bufio: invalid use of UnreadByte"}
-	ErrInvalidUnreadRune os.Error = &Error{"bufio: invalid use of UnreadRune"}
-	ErrBufferFull        os.Error = &Error{"bufio: buffer full"}
-	ErrNegativeCount     os.Error = &Error{"bufio: negative count"}
-	errInternal          os.Error = &Error{"bufio: internal error"}
+	ErrInvalidUnreadByte error = &Error{"bufio: invalid use of UnreadByte"}
+	ErrInvalidUnreadRune error = &Error{"bufio: invalid use of UnreadRune"}
+	ErrBufferFull        error = &Error{"bufio: buffer full"}
+	ErrNegativeCount     error = &Error{"bufio: negative count"}
+	errInternal          error = &Error{"bufio: internal error"}
 )
 
 // BufSizeError is the error representing an invalid buffer size.
 type BufSizeError int
 
-func (b BufSizeError) String() string {
+func (b BufSizeError) Error() string {
 	return "bufio: bad buffer size " + strconv.Itoa(int(b))
 }
 
@@ -48,17 +47,19 @@ type Reader struct {
 	buf          []byte
 	rd           io.Reader
 	r, w         int
-	err          os.Error
+	err          error
 	lastByte     int
 	lastRuneSize int
 }
 
+const minReadBufferSize = 16
+
 // NewReaderSize creates a new Reader whose buffer has the specified size,
-// which must be greater than one.  If the argument io.Reader is already a
+// which must be at least 16 bytes.  If the argument io.Reader is already a
 // Reader with large enough size, it returns the underlying Reader.
 // It returns the Reader and any error.
-func NewReaderSize(rd io.Reader, size int) (*Reader, os.Error) {
-	if size <= 1 {
+func NewReaderSize(rd io.Reader, size int) (*Reader, error) {
+	if size < minReadBufferSize {
 		return nil, BufSizeError(size)
 	}
 	// Is it already a Reader?
@@ -101,7 +102,7 @@ func (b *Reader) fill() {
 	}
 }
 
-func (b *Reader) readErr() os.Error {
+func (b *Reader) readErr() error {
 	err := b.err
 	b.err = nil
 	return err
@@ -111,7 +112,7 @@ func (b *Reader) readErr() os.Error {
 // being valid at the next read call. If Peek returns fewer than n bytes, it
 // also returns an error explaining why the read is short. The error is
 // ErrBufferFull if n is larger than b's buffer size.
-func (b *Reader) Peek(n int) ([]byte, os.Error) {
+func (b *Reader) Peek(n int) ([]byte, error) {
 	if n < 0 {
 		return nil, ErrNegativeCount
 	}
@@ -136,8 +137,8 @@ func (b *Reader) Peek(n int) ([]byte, os.Error) {
 // It returns the number of bytes read into p.
 // It calls Read at most once on the underlying Reader,
 // hence n may be less than len(p).
-// At EOF, the count will be zero and err will be os.EOF.
-func (b *Reader) Read(p []byte) (n int, err os.Error) {
+// At EOF, the count will be zero and err will be io.EOF.
+func (b *Reader) Read(p []byte) (n int, err error) {
 	n = len(p)
 	if n == 0 {
 		return 0, b.readErr()
@@ -174,7 +175,7 @@ func (b *Reader) Read(p []byte) (n int, err os.Error) {
 
 // ReadByte reads and returns a single byte.
 // If no byte is available, returns an error.
-func (b *Reader) ReadByte() (c byte, err os.Error) {
+func (b *Reader) ReadByte() (c byte, err error) {
 	b.lastRuneSize = -1
 	for b.w == b.r {
 		if b.err != nil {
@@ -189,7 +190,7 @@ func (b *Reader) ReadByte() (c byte, err os.Error) {
 }
 
 // UnreadByte unreads the last byte.  Only the most recently read byte can be unread.
-func (b *Reader) UnreadByte() os.Error {
+func (b *Reader) UnreadByte() error {
 	b.lastRuneSize = -1
 	if b.r == b.w && b.lastByte >= 0 {
 		b.w = 1
@@ -208,7 +209,7 @@ func (b *Reader) UnreadByte() os.Error {
 
 // ReadRune reads a single UTF-8 encoded Unicode character and returns the
 // rune and its size in bytes.
-func (b *Reader) ReadRune() (rune int, size int, err os.Error) {
+func (b *Reader) ReadRune() (r rune, size int, err error) {
 	for b.r+utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) && b.err == nil {
 		b.fill()
 	}
@@ -216,21 +217,21 @@ func (b *Reader) ReadRune() (rune int, size int, err os.Error) {
 	if b.r == b.w {
 		return 0, 0, b.readErr()
 	}
-	rune, size = int(b.buf[b.r]), 1
-	if rune >= 0x80 {
-		rune, size = utf8.DecodeRune(b.buf[b.r:b.w])
+	r, size = rune(b.buf[b.r]), 1
+	if r >= 0x80 {
+		r, size = utf8.DecodeRune(b.buf[b.r:b.w])
 	}
 	b.r += size
 	b.lastByte = int(b.buf[b.r-1])
 	b.lastRuneSize = size
-	return rune, size, nil
+	return r, size, nil
 }
 
 // UnreadRune unreads the last rune.  If the most recent read operation on
 // the buffer was not a ReadRune, UnreadRune returns an error.  (In this
 // regard it is stricter than UnreadByte, which will unread the last byte
 // from any read operation.)
-func (b *Reader) UnreadRune() os.Error {
+func (b *Reader) UnreadRune() error {
 	if b.lastRuneSize < 0 || b.r == 0 {
 		return ErrInvalidUnreadRune
 	}
@@ -247,13 +248,13 @@ func (b *Reader) Buffered() int { return b.w - b.r }
 // returning a slice pointing at the bytes in the buffer.
 // The bytes stop being valid at the next read call.
 // If ReadSlice encounters an error before finding a delimiter,
-// it returns all the data in the buffer and the error itself (often os.EOF).
+// it returns all the data in the buffer and the error itself (often io.EOF).
 // ReadSlice fails with error ErrBufferFull if the buffer fills without a delim.
 // Because the data returned from ReadSlice will be overwritten
 // by the next I/O operation, most clients should use
 // ReadBytes or ReadString instead.
 // ReadSlice returns err != nil if and only if line does not end in delim.
-func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) {
+func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
 	// Look in buffer.
 	if i := bytes.IndexByte(b.buf[b.r:b.w], delim); i >= 0 {
 		line1 := b.buf[b.r : b.r+i+1]
@@ -295,7 +296,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) {
 // of the line. The returned buffer is only valid until the next call to
 // ReadLine. ReadLine either returns a non-nil line or it returns an error,
 // never both.
-func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
+func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) {
 	line, err = b.ReadSlice('\n')
 	if err == ErrBufferFull {
 		// Handle the case where "\r\n" straddles the buffer.
@@ -313,6 +314,9 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
 	}
 
 	if len(line) == 0 {
+		if err != nil {
+			line = nil
+		}
 		return
 	}
 	err = nil
@@ -330,10 +334,10 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
 // ReadBytes reads until the first occurrence of delim in the input,
 // returning a slice containing the data up to and including the delimiter.
 // If ReadBytes encounters an error before finding a delimiter,
-// it returns the data read before the error and the error itself (often os.EOF).
+// it returns the data read before the error and the error itself (often io.EOF).
 // ReadBytes returns err != nil if and only if the returned data does not end in
 // delim.
-func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
+func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
 	// Use ReadSlice to look for array,
 	// accumulating full buffers.
 	var frag []byte
@@ -341,7 +345,7 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
 	err = nil
 
 	for {
-		var e os.Error
+		var e error
 		frag, e = b.ReadSlice(delim)
 		if e == nil { // got final fragment
 			break
@@ -377,10 +381,10 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
 // ReadString reads until the first occurrence of delim in the input,
 // returning a string containing the data up to and including the delimiter.
 // If ReadString encounters an error before finding a delimiter,
-// it returns the data read before the error and the error itself (often os.EOF).
+// it returns the data read before the error and the error itself (often io.EOF).
 // ReadString returns err != nil if and only if the returned data does not end in
 // delim.
-func (b *Reader) ReadString(delim byte) (line string, err os.Error) {
+func (b *Reader) ReadString(delim byte) (line string, err error) {
 	bytes, e := b.ReadBytes(delim)
 	return string(bytes), e
 }
@@ -389,7 +393,7 @@ func (b *Reader) ReadString(delim byte) (line string, err os.Error) {
 
 // Writer implements buffering for an io.Writer object.
 type Writer struct {
-	err os.Error
+	err error
 	buf []byte
 	n   int
 	wr  io.Writer
@@ -399,7 +403,7 @@ type Writer struct {
 // which must be greater than zero. If the argument io.Writer is already a
 // Writer with large enough size, it returns the underlying Writer.
 // It returns the Writer and any error.
-func NewWriterSize(wr io.Writer, size int) (*Writer, os.Error) {
+func NewWriterSize(wr io.Writer, size int) (*Writer, error) {
 	if size <= 0 {
 		return nil, BufSizeError(size)
 	}
@@ -425,7 +429,7 @@ func NewWriter(wr io.Writer) *Writer {
 }
 
 // Flush writes any buffered data to the underlying io.Writer.
-func (b *Writer) Flush() os.Error {
+func (b *Writer) Flush() error {
 	if b.err != nil {
 		return b.err
 	}
@@ -458,7 +462,7 @@ func (b *Writer) Buffered() int { return b.n }
 // It returns the number of bytes written.
 // If nn < len(p), it also returns an error explaining
 // why the write is short.
-func (b *Writer) Write(p []byte) (nn int, err os.Error) {
+func (b *Writer) Write(p []byte) (nn int, err error) {
 	for len(p) > b.Available() && b.err == nil {
 		var n int
 		if b.Buffered() == 0 {
@@ -483,7 +487,7 @@ func (b *Writer) Write(p []byte) (nn int, err os.Error) {
 }
 
 // WriteByte writes a single byte.
-func (b *Writer) WriteByte(c byte) os.Error {
+func (b *Writer) WriteByte(c byte) error {
 	if b.err != nil {
 		return b.err
 	}
@@ -497,9 +501,9 @@ func (b *Writer) WriteByte(c byte) os.Error {
 
 // WriteRune writes a single Unicode code point, returning
 // the number of bytes written and any error.
-func (b *Writer) WriteRune(rune int) (size int, err os.Error) {
-	if rune < utf8.RuneSelf {
-		err = b.WriteByte(byte(rune))
+func (b *Writer) WriteRune(r rune) (size int, err error) {
+	if r < utf8.RuneSelf {
+		err = b.WriteByte(byte(r))
 		if err != nil {
 			return 0, err
 		}
@@ -516,10 +520,10 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) {
 		n = b.Available()
 		if n < utf8.UTFMax {
 			// Can only happen if buffer is silly small.
-			return b.WriteString(string(rune))
+			return b.WriteString(string(r))
 		}
 	}
-	size = utf8.EncodeRune(b.buf[b.n:], rune)
+	size = utf8.EncodeRune(b.buf[b.n:], r)
 	b.n += size
 	return size, nil
 }
@@ -528,7 +532,7 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) {
 // It returns the number of bytes written.
 // If the count is less than len(s), it also returns an error explaining
 // why the write is short.
-func (b *Writer) WriteString(s string) (int, os.Error) {
+func (b *Writer) WriteString(s string) (int, error) {
 	nn := 0
 	for len(s) > b.Available() && b.err == nil {
 		n := copy(b.buf[b.n:], s)
diff --git a/src/pkg/bufio/bufio_test.go b/src/pkg/bufio/bufio_test.go
index 38213ff..6463bbb 100644
--- a/src/pkg/bufio/bufio_test.go
+++ b/src/pkg/bufio/bufio_test.go
@@ -10,11 +10,10 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
-	"os"
 	"strings"
 	"testing"
 	"testing/iotest"
-	"utf8"
+	"unicode/utf8"
 )
 
 // Reads from a reader and rot13s the result.
@@ -28,7 +27,7 @@ func newRot13Reader(r io.Reader) *rot13Reader {
 	return r13
 }
 
-func (r13 *rot13Reader) Read(p []byte) (int, os.Error) {
+func (r13 *rot13Reader) Read(p []byte) (int, error) {
 	n, e := r13.r.Read(p)
 	if e != nil {
 		return n, e
@@ -50,14 +49,14 @@ func readBytes(buf *Reader) string {
 	nb := 0
 	for {
 		c, e := buf.ReadByte()
-		if e == os.EOF {
+		if e == io.EOF {
 			break
 		}
 		if e == nil {
 			b[nb] = c
 			nb++
 		} else if e != iotest.ErrTimeout {
-			panic("Data: " + e.String())
+			panic("Data: " + e.Error())
 		}
 	}
 	return string(b[0:nb])
@@ -95,11 +94,11 @@ func readLines(b *Reader) string {
 	s := ""
 	for {
 		s1, e := b.ReadString('\n')
-		if e == os.EOF {
+		if e == io.EOF {
 			break
 		}
 		if e != nil && e != iotest.ErrTimeout {
-			panic("GetLines: " + e.String())
+			panic("GetLines: " + e.Error())
 		}
 		s += s1
 	}
@@ -113,7 +112,7 @@ func reads(buf *Reader, m int) string {
 	for {
 		n, e := buf.Read(b[nb : nb+m])
 		nb += n
-		if e == os.EOF {
+		if e == io.EOF {
 			break
 		}
 	}
@@ -136,9 +135,10 @@ var bufreaders = []bufReader{
 	{"lines", readLines},
 }
 
+const minReadBufferSize = 16
+
 var bufsizes = []int{
-	2, 3, 4, 5, 6, 7, 8, 9, 10,
-	23, 32, 46, 64, 93, 128, 1024, 4096,
+	minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096,
 }
 
 func TestReader(t *testing.T) {
@@ -179,13 +179,13 @@ type StringReader struct {
 	step int
 }
 
-func (r *StringReader) Read(p []byte) (n int, err os.Error) {
+func (r *StringReader) Read(p []byte) (n int, err error) {
 	if r.step < len(r.data) {
 		s := r.data[r.step]
 		n = copy(p, s)
 		r.step++
 	} else {
-		err = os.EOF
+		err = io.EOF
 	}
 	return
 }
@@ -195,14 +195,14 @@ func readRuneSegments(t *testing.T, segments []string) {
 	want := strings.Join(segments, "")
 	r := NewReader(&StringReader{data: segments})
 	for {
-		rune, _, err := r.ReadRune()
+		r, _, err := r.ReadRune()
 		if err != nil {
-			if err != os.EOF {
+			if err != io.EOF {
 				return
 			}
 			break
 		}
-		got += string(rune)
+		got += string(r)
 	}
 	if got != want {
 		t.Errorf("segments=%v got=%s want=%s", segments, got, want)
@@ -233,24 +233,24 @@ func TestUnreadRune(t *testing.T) {
 	r := NewReader(&StringReader{data: segments})
 	// Normal execution.
 	for {
-		rune, _, err := r.ReadRune()
+		r1, _, err := r.ReadRune()
 		if err != nil {
-			if err != os.EOF {
+			if err != io.EOF {
 				t.Error("unexpected EOF")
 			}
 			break
 		}
-		got += string(rune)
+		got += string(r1)
 		// Put it back and read it again
 		if err = r.UnreadRune(); err != nil {
 			t.Error("unexpected error on UnreadRune:", err)
 		}
-		rune1, _, err := r.ReadRune()
+		r2, _, err := r.ReadRune()
 		if err != nil {
 			t.Error("unexpected error reading after unreading:", err)
 		}
-		if rune != rune1 {
-			t.Errorf("incorrect rune after unread: got %c wanted %c", rune1, rune)
+		if r1 != r2 {
+			t.Errorf("incorrect rune after unread: got %c wanted %c", r1, r2)
 		}
 	}
 	if got != data {
@@ -328,7 +328,7 @@ func TestUnreadRuneAtEOF(t *testing.T) {
 	_, _, err := r.ReadRune()
 	if err == nil {
 		t.Error("expected error at EOF")
-	} else if err != os.EOF {
+	} else if err != io.EOF {
 		t.Error("expected EOF; got", err)
 	}
 }
@@ -339,25 +339,25 @@ func TestReadWriteRune(t *testing.T) {
 	w := NewWriter(byteBuf)
 	// Write the runes out using WriteRune
 	buf := make([]byte, utf8.UTFMax)
-	for rune := 0; rune < NRune; rune++ {
-		size := utf8.EncodeRune(buf, rune)
-		nbytes, err := w.WriteRune(rune)
+	for r := rune(0); r < NRune; r++ {
+		size := utf8.EncodeRune(buf, r)
+		nbytes, err := w.WriteRune(r)
 		if err != nil {
-			t.Fatalf("WriteRune(0x%x) error: %s", rune, err)
+			t.Fatalf("WriteRune(0x%x) error: %s", r, err)
 		}
 		if nbytes != size {
-			t.Fatalf("WriteRune(0x%x) expected %d, got %d", rune, size, nbytes)
+			t.Fatalf("WriteRune(0x%x) expected %d, got %d", r, size, nbytes)
 		}
 	}
 	w.Flush()
 
 	r := NewReader(byteBuf)
 	// Read them back with ReadRune
-	for rune := 0; rune < NRune; rune++ {
-		size := utf8.EncodeRune(buf, rune)
+	for r1 := rune(0); r1 < NRune; r1++ {
+		size := utf8.EncodeRune(buf, r1)
 		nr, nbytes, err := r.ReadRune()
-		if nr != rune || nbytes != size || err != nil {
-			t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r, nr, nbytes, r, size, err)
+		if nr != r1 || nbytes != size || err != nil {
+			t.Fatalf("ReadRune(0x%x) got 0x%x,%d not 0x%x,%d (err=%s)", r1, nr, nbytes, r1, size, err)
 		}
 	}
 }
@@ -413,11 +413,11 @@ func TestWriter(t *testing.T) {
 
 type errorWriterTest struct {
 	n, m   int
-	err    os.Error
-	expect os.Error
+	err    error
+	expect error
 }
 
-func (w errorWriterTest) Write(p []byte) (int, os.Error) {
+func (w errorWriterTest) Write(p []byte) (int, error) {
 	return len(p) * w.n / w.m, w.err
 }
 
@@ -425,9 +425,9 @@ var errorWriterTests = []errorWriterTest{
 	{0, 1, nil, io.ErrShortWrite},
 	{1, 2, nil, io.ErrShortWrite},
 	{1, 1, nil, nil},
-	{0, 1, os.EPIPE, os.EPIPE},
-	{1, 2, os.EPIPE, os.EPIPE},
-	{1, 1, os.EPIPE, os.EPIPE},
+	{0, 1, io.ErrClosedPipe, io.ErrClosedPipe},
+	{1, 2, io.ErrClosedPipe, io.ErrClosedPipe},
+	{1, 1, io.ErrClosedPipe, io.ErrClosedPipe},
 }
 
 func TestWriteErrors(t *testing.T) {
@@ -515,27 +515,32 @@ func TestWriteString(t *testing.T) {
 }
 
 func TestBufferFull(t *testing.T) {
-	buf, _ := NewReaderSize(strings.NewReader("hello, world"), 5)
-	line, err := buf.ReadSlice(',')
-	if string(line) != "hello" || err != ErrBufferFull {
+	const longString = "And now, hello, world! It is the time for all good men to come to the aid of their party"
+	buf, err := NewReaderSize(strings.NewReader(longString), minReadBufferSize)
+	if err != nil {
+		t.Fatal("NewReaderSize:", err)
+	}
+	line, err := buf.ReadSlice('!')
+	if string(line) != "And now, hello, " || err != ErrBufferFull {
 		t.Errorf("first ReadSlice(,) = %q, %v", line, err)
 	}
-	line, err = buf.ReadSlice(',')
-	if string(line) != "," || err != nil {
+	line, err = buf.ReadSlice('!')
+	if string(line) != "world!" || err != nil {
 		t.Errorf("second ReadSlice(,) = %q, %v", line, err)
 	}
 }
 
 func TestPeek(t *testing.T) {
 	p := make([]byte, 10)
-	buf, _ := NewReaderSize(strings.NewReader("abcdefghij"), 4)
+	// string is 16 (minReadBufferSize) long.
+	buf, _ := NewReaderSize(strings.NewReader("abcdefghijklmnop"), minReadBufferSize)
 	if s, err := buf.Peek(1); string(s) != "a" || err != nil {
 		t.Fatalf("want %q got %q, err=%v", "a", string(s), err)
 	}
 	if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
 		t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err)
 	}
-	if _, err := buf.Peek(5); err != ErrBufferFull {
+	if _, err := buf.Peek(32); err != ErrBufferFull {
 		t.Fatalf("want ErrBufFull got %v", err)
 	}
 	if _, err := buf.Read(p[0:3]); string(p[0:3]) != "abc" || err != nil {
@@ -553,13 +558,13 @@ func TestPeek(t *testing.T) {
 	if s, err := buf.Peek(4); string(s) != "ghij" || err != nil {
 		t.Fatalf("want %q got %q, err=%v", "ghij", string(s), err)
 	}
-	if _, err := buf.Read(p[0:4]); string(p[0:4]) != "ghij" || err != nil {
-		t.Fatalf("want %q got %q, err=%v", "ghij", string(p[0:3]), err)
+	if _, err := buf.Read(p[0:]); string(p[0:]) != "ghijklmnop" || err != nil {
+		t.Fatalf("want %q got %q, err=%v", "ghijklmnop", string(p[0:minReadBufferSize]), err)
 	}
 	if s, err := buf.Peek(0); string(s) != "" || err != nil {
 		t.Fatalf("want %q got %q, err=%v", "", string(s), err)
 	}
-	if _, err := buf.Peek(1); err != os.EOF {
+	if _, err := buf.Peek(1); err != io.EOF {
 		t.Fatalf("want EOF got %v", err)
 	}
 }
@@ -583,7 +588,7 @@ type testReader struct {
 	stride int
 }
 
-func (t *testReader) Read(buf []byte) (n int, err os.Error) {
+func (t *testReader) Read(buf []byte) (n int, err error) {
 	n = t.stride
 	if n > len(t.data) {
 		n = len(t.data)
@@ -594,7 +599,7 @@ func (t *testReader) Read(buf []byte) (n int, err os.Error) {
 	copy(buf, t.data)
 	t.data = t.data[n:]
 	if len(t.data) == 0 {
-		err = os.EOF
+		err = io.EOF
 	}
 	return
 }
@@ -614,7 +619,7 @@ func testReadLine(t *testing.T, input []byte) {
 				t.Errorf("ReadLine returned prefix")
 			}
 			if err != nil {
-				if err != os.EOF {
+				if err != io.EOF {
 					t.Fatalf("Got unknown error: %s", err)
 				}
 				break
@@ -636,19 +641,25 @@ func TestReadLine(t *testing.T) {
 }
 
 func TestLineTooLong(t *testing.T) {
-	buf := bytes.NewBuffer([]byte("aaabbbcc\n"))
-	l, _ := NewReaderSize(buf, 3)
+	data := make([]byte, 0)
+	for i := 0; i < minReadBufferSize*5/2; i++ {
+		data = append(data, '0'+byte(i%10))
+	}
+	buf := bytes.NewBuffer(data)
+	l, _ := NewReaderSize(buf, minReadBufferSize)
 	line, isPrefix, err := l.ReadLine()
-	if !isPrefix || !bytes.Equal(line, []byte("aaa")) || err != nil {
-		t.Errorf("bad result for first line: %x %s", line, err)
+	if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
+		t.Errorf("bad result for first line: got %q want %q %v", line, data[:minReadBufferSize], err)
 	}
+	data = data[len(line):]
 	line, isPrefix, err = l.ReadLine()
-	if !isPrefix || !bytes.Equal(line, []byte("bbb")) || err != nil {
-		t.Errorf("bad result for second line: %x", line)
+	if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil {
+		t.Errorf("bad result for second line: got %q want %q %v", line, data[:minReadBufferSize], err)
 	}
+	data = data[len(line):]
 	line, isPrefix, err = l.ReadLine()
-	if isPrefix || !bytes.Equal(line, []byte("cc")) || err != nil {
-		t.Errorf("bad result for third line: %x", line)
+	if isPrefix || !bytes.Equal(line, data[:minReadBufferSize/2]) || err != nil {
+		t.Errorf("bad result for third line: got %q want %q %v", line, data[:minReadBufferSize/2], err)
 	}
 	line, isPrefix, err = l.ReadLine()
 	if isPrefix || err == nil {
@@ -657,8 +668,8 @@ func TestLineTooLong(t *testing.T) {
 }
 
 func TestReadAfterLines(t *testing.T) {
-	line1 := "line1"
-	restData := "line2\nline 3\n"
+	line1 := "this is line1"
+	restData := "this is line2\nthis is line 3\n"
 	inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData))
 	outbuf := new(bytes.Buffer)
 	maxLineLength := len(line1) + len(restData)/2
@@ -677,15 +688,15 @@ func TestReadAfterLines(t *testing.T) {
 }
 
 func TestReadEmptyBuffer(t *testing.T) {
-	l, _ := NewReaderSize(bytes.NewBuffer(nil), 10)
+	l, _ := NewReaderSize(bytes.NewBuffer(nil), minReadBufferSize)
 	line, isPrefix, err := l.ReadLine()
-	if err != os.EOF {
+	if err != io.EOF {
 		t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
 	}
 }
 
 func TestLinesAfterRead(t *testing.T) {
-	l, _ := NewReaderSize(bytes.NewBuffer([]byte("foo")), 10)
+	l, _ := NewReaderSize(bytes.NewBuffer([]byte("foo")), minReadBufferSize)
 	_, err := ioutil.ReadAll(l)
 	if err != nil {
 		t.Error(err)
@@ -693,59 +704,55 @@ func TestLinesAfterRead(t *testing.T) {
 	}
 
 	line, isPrefix, err := l.ReadLine()
-	if err != os.EOF {
+	if err != io.EOF {
 		t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
 	}
 }
 
+func TestReadLineNonNilLineOrError(t *testing.T) {
+	r := NewReader(strings.NewReader("line 1\n"))
+	for i := 0; i < 2; i++ {
+		l, _, err := r.ReadLine()
+		if l != nil && err != nil {
+			t.Fatalf("on line %d/2; ReadLine=%#v, %v; want non-nil line or Error, but not both",
+				i+1, l, err)
+		}
+	}
+}
+
 type readLineResult struct {
 	line     []byte
 	isPrefix bool
-	err      os.Error
+	err      error
 }
 
 var readLineNewlinesTests = []struct {
-	input   string
-	bufSize int
-	expect  []readLineResult
+	input  string
+	expect []readLineResult
 }{
-	{"h\r\nb\r\n", 2, []readLineResult{
-		{[]byte("h"), true, nil},
-		{nil, false, nil},
-		{[]byte("b"), true, nil},
-		{nil, false, nil},
-		{nil, false, os.EOF},
-	}},
-	{"hello\r\nworld\r\n", 6, []readLineResult{
-		{[]byte("hello"), true, nil},
+	{"012345678901234\r\n012345678901234\r\n", []readLineResult{
+		{[]byte("012345678901234"), true, nil},
 		{nil, false, nil},
-		{[]byte("world"), true, nil},
+		{[]byte("012345678901234"), true, nil},
 		{nil, false, nil},
-		{nil, false, os.EOF},
+		{nil, false, io.EOF},
 	}},
-	{"hello\rworld\r", 6, []readLineResult{
-		{[]byte("hello"), true, nil},
-		{[]byte("\rworld"), true, nil},
-		{[]byte("\r"), false, nil},
-		{nil, false, os.EOF},
-	}},
-	{"h\ri\r\n\r", 2, []readLineResult{
-		{[]byte("h"), true, nil},
-		{[]byte("\ri"), true, nil},
-		{nil, false, nil},
+	{"0123456789012345\r012345678901234\r", []readLineResult{
+		{[]byte("0123456789012345"), true, nil},
+		{[]byte("\r012345678901234"), true, nil},
 		{[]byte("\r"), false, nil},
-		{nil, false, os.EOF},
+		{nil, false, io.EOF},
 	}},
 }
 
 func TestReadLineNewlines(t *testing.T) {
 	for _, e := range readLineNewlinesTests {
-		testReadLineNewlines(t, e.input, e.bufSize, e.expect)
+		testReadLineNewlines(t, e.input, e.expect)
 	}
 }
 
-func testReadLineNewlines(t *testing.T, input string, bufSize int, expect []readLineResult) {
-	b, err := NewReaderSize(strings.NewReader(input), bufSize)
+func testReadLineNewlines(t *testing.T, input string, expect []readLineResult) {
+	b, err := NewReaderSize(strings.NewReader(input), minReadBufferSize)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/src/pkg/builtin/builtin.go b/src/pkg/builtin/builtin.go
index 07acce4..e81616c 100644
--- a/src/pkg/builtin/builtin.go
+++ b/src/pkg/builtin/builtin.go
@@ -3,29 +3,110 @@
 // license that can be found in the LICENSE file.
 
 /*
-	Package builtin provides documentation for Go's built-in functions.
-	The functions documented here are not actually in package builtin
+	Package builtin provides documentation for Go's predeclared identifiers.
+	The items documented here are not actually in package builtin
 	but their descriptions here allow godoc to present documentation
-	for the language's special functions.
+	for the language's special identifiers.
 */
 package builtin
 
+// bool is the set of boolean values, true and false.
+type bool bool
+
+// uint8 is the set of all unsigned 8-bit integers.
+// Range: 0 through 255.
+type uint8 uint8
+
+// uint16 is the set of all unsigned 16-bit integers.
+// Range: 0 through 65535.
+type uint16 uint16
+
+// uint32 is the set of all unsigned 32-bit integers.
+// Range: 0 through 4294967295.
+type uint32 uint32
+
+// uint64 is the set of all unsigned 64-bit integers.
+// Range: 0 through 18446744073709551615.
+type uint64 uint64
+
+// int8 is the set of all signed 8-bit integers.
+// Range: -128 through 127.
+type int8 int8
+
+// int16 is the set of all signed 16-bit integers.
+// Range: -32768 through 32767.
+type int16 int16
+
+// int32 is the set of all signed 32-bit integers.
+// Range: -2147483648 through 2147483647.
+type int32 int32
+
+// int64 is the set of all signed 64-bit integers.
+// Range: -9223372036854775808 through 9223372036854775807.
+type int64 int64
+
+// float32 is the set of all IEEE-754 32-bit floating-point numbers.
+type float32 float32
+
+// float64 is the set of all IEEE-754 64-bit floating-point numbers.
+type float64 float64
+
+// complex64 is the set of all complex numbers with float32 real and
+// imaginary parts.
+type complex64 complex64
+
+// complex128 is the set of all complex numbers with float64 real and
+// imaginary parts.
+type complex128 complex128
+
+// string is the set of all strings of 8-bit bytes, conventionally but not
+// necessarily representing UTF-8-encoded text. A string may be empty, but
+// not nil. Values of string type are immutable.
+type string string
+
+// int is a signed integer type that is at least 32 bits in size. It is a
+// distinct type, however, and not an alias for, say, int32.
+type int int
+
+// uint is an unsigned integer type that is at least 32 bits in size. It is a
+// distinct type, however, and not an alias for, say, uint32.
+type uint uint
+
+// uintptr is an integer type that is large enough to hold the bit pattern of
+// any pointer.
+type uintptr uintptr
+
+// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
+// used, by convention, to distinguish byte values from 8-bit unsigned
+// integer values.
+type byte byte
+
+// rune is an alias for int and is equivalent to int in all ways. It is
+// used, by convention, to distinguish character values from integer values.
+// In a future version of Go, it will change to an alias of int32.
+type rune rune
+
 // Type is here for the purposes of documentation only. It is a stand-in
 // for any Go type, but represents the same type for any given function
 // invocation.
 type Type int
 
+// Type1 is here for the purposes of documentation only. It is a stand-in
+// for any Go type, but represents the same type for any given function
+// invocation.
+type Type1 int
+
 // IntegerType is here for the purposes of documentation only. It is a stand-in
 // for any integer type: int, uint, int8 etc.
 type IntegerType int
 
 // FloatType is here for the purposes of documentation only. It is a stand-in
 // for either float type: float32 or float64.
-type FloatType int
+type FloatType float32
 
 // ComplexType is here for the purposes of documentation only. It is a
 // stand-in for either complex type: complex64 or complex128.
-type ComplexType int
+type ComplexType complex64
 
 // The append built-in function appends elements to the end of a slice. If
 // it has sufficient capacity, the destination is resliced to accommodate the
@@ -43,6 +124,11 @@ func append(slice []Type, elems ...Type) []Type
 // len(src) and len(dst).
 func copy(dst, src []Type) int
 
+// The delete built-in function deletes the element with the specified key
+// (m[key]) from the map. If there is no such element, delete is a no-op.
+// If m is nil, delete panics.
+func delete(m map[Type]Type1, key Type)
+
 // The len built-in function returns the length of v, according to its type:
 //	Array: the number of elements in v.
 //	Pointer to array: the number of elements in *v (even if v is nil).
@@ -95,7 +181,7 @@ func complex(r, i FloatType) ComplexType
 // The return value will be floating point type corresponding to the type of c.
 func real(c ComplexType) FloatType
 
-// The imaginary built-in function returns the imaginary part of the complex
+// The imag built-in function returns the imaginary part of the complex
 // number c. The return value will be floating point type corresponding to
 // the type of c.
 func imag(c ComplexType) FloatType
@@ -133,3 +219,9 @@ func panic(v interface{})
 // nil. Thus the return value from recover reports whether the goroutine is
 // panicking.
 func recover() interface{}
+
+// The error built-in interface type is the conventional interface for
+// representing an error condition, with the nil value representing no error.
+type error interface {
+	Error() string
+}
diff --git a/src/pkg/bytes/asm_386.s b/src/pkg/bytes/asm_386.s
index f339174..e7833de 100644
--- a/src/pkg/bytes/asm_386.s
+++ b/src/pkg/bytes/asm_386.s
@@ -15,3 +15,19 @@ TEXT ·IndexByte(SB),7,$0
 	SUBL	$1, DI
 	MOVL	DI, ret+16(FP)
 	RET
+
+TEXT ·Equal(SB),7,$0
+	MOVL	len+4(FP), BX
+	MOVL	len1+16(FP), CX
+	MOVL	$0, AX
+	CMPL	BX, CX
+	JNE	eqret
+	MOVL	p+0(FP), SI
+	MOVL	q+12(FP), DI
+	CLD
+	REP; CMPSB
+	JNE eqret
+	MOVL	$1, AX
+eqret:
+	MOVB	AX, ret+24(FP)
+	RET
diff --git a/src/pkg/bytes/asm_amd64.s b/src/pkg/bytes/asm_amd64.s
index c6793cb..5caea5c 100644
--- a/src/pkg/bytes/asm_amd64.s
+++ b/src/pkg/bytes/asm_amd64.s
@@ -90,3 +90,19 @@ success:
 	MOVL DI, ret+24(FP)
 	RET
 
+TEXT ·Equal(SB),7,$0
+	MOVL	len+8(FP), BX
+	MOVL	len1+24(FP), CX
+	MOVL	$0, AX
+	CMPL	BX, CX
+	JNE	eqret
+	MOVQ	p+0(FP), SI
+	MOVQ	q+16(FP), DI
+	CLD
+	REP; CMPSB
+	MOVL	$1, DX
+	CMOVLEQ	DX, AX
+eqret:
+	MOVB	AX, ret+32(FP)
+	RET
+
diff --git a/src/pkg/bytes/asm_arm.s b/src/pkg/bytes/asm_arm.s
index f32fca1..4ed0c15 100644
--- a/src/pkg/bytes/asm_arm.s
+++ b/src/pkg/bytes/asm_arm.s
@@ -6,3 +6,6 @@
 TEXT ·IndexByte(SB),7,$0
 	B	·indexBytePortable(SB)
 
+// no memcmp implementation on arm yet
+TEXT ·Equal(SB),7,$0
+	B	·equalPortable(SB)
diff --git a/src/pkg/bytes/buffer.go b/src/pkg/bytes/buffer.go
index 975031b..2c3eb6a 100644
--- a/src/pkg/bytes/buffer.go
+++ b/src/pkg/bytes/buffer.go
@@ -7,9 +7,9 @@ package bytes
 // Simple byte buffer for marshaling data.
 
 import (
+	"errors"
 	"io"
-	"os"
-	"utf8"
+	"unicode/utf8"
 )
 
 // A Buffer is a variable-sized buffer of bytes with Read and Write methods.
@@ -33,6 +33,9 @@ const (
 	opRead                   // Any other read operation.
 )
 
+// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
+var ErrTooLarge = errors.New("bytes.Buffer: too large")
+
 // Bytes returns a slice of the contents of the unread portion of the buffer;
 // len(b.Bytes()) == b.Len().  If the caller changes the contents of the
 // returned slice, the contents of the buffer will change provided there
@@ -68,8 +71,9 @@ func (b *Buffer) Truncate(n int) {
 // b.Reset() is the same as b.Truncate(0).
 func (b *Buffer) Reset() { b.Truncate(0) }
 
-// Grow buffer to guarantee space for n more bytes.
-// Return index where bytes should be written.
+// grow grows the buffer to guarantee space for n more bytes.
+// It returns the index where bytes should be written.
+// If the buffer can't grow it will panic with ErrTooLarge.
 func (b *Buffer) grow(n int) int {
 	m := b.Len()
 	// If buffer is empty, reset to recover space.
@@ -82,7 +86,7 @@ func (b *Buffer) grow(n int) int {
 			buf = b.bootstrap[0:]
 		} else {
 			// not enough space anywhere
-			buf = make([]byte, 2*cap(b.buf)+n)
+			buf = makeSlice(2*cap(b.buf) + n)
 			copy(buf, b.buf[b.off:])
 		}
 		b.buf = buf
@@ -94,16 +98,19 @@ func (b *Buffer) grow(n int) int {
 
 // Write appends the contents of p to the buffer.  The return
 // value n is the length of p; err is always nil.
-func (b *Buffer) Write(p []byte) (n int, err os.Error) {
+// If the buffer becomes too large, Write will panic with
+// ErrTooLarge.
+func (b *Buffer) Write(p []byte) (n int, err error) {
 	b.lastRead = opInvalid
 	m := b.grow(len(p))
-	copy(b.buf[m:], p)
-	return len(p), nil
+	return copy(b.buf[m:], p), nil
 }
 
 // WriteString appends the contents of s to the buffer.  The return
 // value n is the length of s; err is always nil.
-func (b *Buffer) WriteString(s string) (n int, err os.Error) {
+// If the buffer becomes too large, WriteString will panic with
+// ErrTooLarge.
+func (b *Buffer) WriteString(s string) (n int, err error) {
 	b.lastRead = opInvalid
 	m := b.grow(len(s))
 	return copy(b.buf[m:], s), nil
@@ -117,33 +124,33 @@ const MinRead = 512
 
 // ReadFrom reads data from r until EOF and appends it to the buffer.
 // The return value n is the number of bytes read.
-// Any error except os.EOF encountered during the read
+// Any error except io.EOF encountered during the read
 // is also returned.
-func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
+// If the buffer becomes too large, ReadFrom will panic with
+// ErrTooLarge.
+func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
 	b.lastRead = opInvalid
 	// If buffer is empty, reset to recover space.
 	if b.off >= len(b.buf) {
 		b.Truncate(0)
 	}
 	for {
-		if cap(b.buf)-len(b.buf) < MinRead {
-			var newBuf []byte
-			// can we get space without allocation?
-			if b.off+cap(b.buf)-len(b.buf) >= MinRead {
-				// reuse beginning of buffer
-				newBuf = b.buf[0 : len(b.buf)-b.off]
-			} else {
-				// not enough space at end; put space on end
-				newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead)
+		if free := cap(b.buf) - len(b.buf); free < MinRead {
+			// not enough space at end
+			newBuf := b.buf
+			if b.off+free < MinRead {
+				// not enough space using beginning of buffer;
+				// double buffer capacity
+				newBuf = makeSlice(2*cap(b.buf) + MinRead)
 			}
 			copy(newBuf, b.buf[b.off:])
-			b.buf = newBuf
+			b.buf = newBuf[:len(b.buf)-b.off]
 			b.off = 0
 		}
 		m, e := r.Read(b.buf[len(b.buf):cap(b.buf)])
 		b.buf = b.buf[0 : len(b.buf)+m]
 		n += int64(m)
-		if e == os.EOF {
+		if e == io.EOF {
 			break
 		}
 		if e != nil {
@@ -153,11 +160,23 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
 	return n, nil // err is EOF, so return nil explicitly
 }
 
+// makeSlice allocates a slice of size n. If the allocation fails, it panics
+// with ErrTooLarge.
+func makeSlice(n int) []byte {
+	// If the make fails, give a known error.
+	defer func() {
+		if recover() != nil {
+			panic(ErrTooLarge)
+		}
+	}()
+	return make([]byte, n)
+}
+
 // WriteTo writes data to w until the buffer is drained or an error
 // occurs. The return value n is the number of bytes written; it always
 // fits into an int, but it is int64 to match the io.WriterTo interface.
 // Any error encountered during the write is also returned.
-func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
+func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
 	b.lastRead = opInvalid
 	if b.off < len(b.buf) {
 		m, e := w.Write(b.buf[b.off:])
@@ -177,7 +196,9 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
 // WriteByte appends the byte c to the buffer.
 // The returned error is always nil, but is included
 // to match bufio.Writer's WriteByte.
-func (b *Buffer) WriteByte(c byte) os.Error {
+// If the buffer becomes too large, WriteByte will panic with
+// ErrTooLarge.
+func (b *Buffer) WriteByte(c byte) error {
 	b.lastRead = opInvalid
 	m := b.grow(1)
 	b.buf[m] = c
@@ -188,7 +209,9 @@ func (b *Buffer) WriteByte(c byte) os.Error {
 // code point r to the buffer, returning its length and
 // an error, which is always nil but is included
 // to match bufio.Writer's WriteRune.
-func (b *Buffer) WriteRune(r int) (n int, err os.Error) {
+// If the buffer becomes too large, WriteRune will panic with
+// ErrTooLarge.
+func (b *Buffer) WriteRune(r rune) (n int, err error) {
 	if r < utf8.RuneSelf {
 		b.WriteByte(byte(r))
 		return 1, nil
@@ -200,14 +223,17 @@ func (b *Buffer) WriteRune(r int) (n int, err os.Error) {
 
 // Read reads the next len(p) bytes from the buffer or until the buffer
 // is drained.  The return value n is the number of bytes read.  If the
-// buffer has no data to return, err is os.EOF even if len(p) is zero;
+// buffer has no data to return, err is io.EOF (unless len(p) is zero);
 // otherwise it is nil.
-func (b *Buffer) Read(p []byte) (n int, err os.Error) {
+func (b *Buffer) Read(p []byte) (n int, err error) {
 	b.lastRead = opInvalid
 	if b.off >= len(b.buf) {
 		// Buffer is empty, reset to recover space.
 		b.Truncate(0)
-		return 0, os.EOF
+		if len(p) == 0 {
+			return
+		}
+		return 0, io.EOF
 	}
 	n = copy(p, b.buf[b.off:])
 	b.off += n
@@ -236,13 +262,13 @@ func (b *Buffer) Next(n int) []byte {
 }
 
 // ReadByte reads and returns the next byte from the buffer.
-// If no byte is available, it returns error os.EOF.
-func (b *Buffer) ReadByte() (c byte, err os.Error) {
+// If no byte is available, it returns error io.EOF.
+func (b *Buffer) ReadByte() (c byte, err error) {
 	b.lastRead = opInvalid
 	if b.off >= len(b.buf) {
 		// Buffer is empty, reset to recover space.
 		b.Truncate(0)
-		return 0, os.EOF
+		return 0, io.EOF
 	}
 	c = b.buf[b.off]
 	b.off++
@@ -252,21 +278,21 @@ func (b *Buffer) ReadByte() (c byte, err os.Error) {
 
 // ReadRune reads and returns the next UTF-8-encoded
 // Unicode code point from the buffer.
-// If no bytes are available, the error returned is os.EOF.
+// If no bytes are available, the error returned is io.EOF.
 // If the bytes are an erroneous UTF-8 encoding, it
 // consumes one byte and returns U+FFFD, 1.
-func (b *Buffer) ReadRune() (r int, size int, err os.Error) {
+func (b *Buffer) ReadRune() (r rune, size int, err error) {
 	b.lastRead = opInvalid
 	if b.off >= len(b.buf) {
 		// Buffer is empty, reset to recover space.
 		b.Truncate(0)
-		return 0, 0, os.EOF
+		return 0, 0, io.EOF
 	}
 	b.lastRead = opReadRune
 	c := b.buf[b.off]
 	if c < utf8.RuneSelf {
 		b.off++
-		return int(c), 1, nil
+		return rune(c), 1, nil
 	}
 	r, n := utf8.DecodeRune(b.buf[b.off:])
 	b.off += n
@@ -278,9 +304,9 @@ func (b *Buffer) ReadRune() (r int, size int, err os.Error) {
 // not a ReadRune, UnreadRune returns an error.  (In this regard
 // it is stricter than UnreadByte, which will unread the last byte
 // from any read operation.)
-func (b *Buffer) UnreadRune() os.Error {
+func (b *Buffer) UnreadRune() error {
 	if b.lastRead != opReadRune {
-		return os.NewError("bytes.Buffer: UnreadRune: previous operation was not ReadRune")
+		return errors.New("bytes.Buffer: UnreadRune: previous operation was not ReadRune")
 	}
 	b.lastRead = opInvalid
 	if b.off > 0 {
@@ -293,9 +319,9 @@ func (b *Buffer) UnreadRune() os.Error {
 // UnreadByte unreads the last byte returned by the most recent
 // read operation.  If write has happened since the last read, UnreadByte
 // returns an error.
-func (b *Buffer) UnreadByte() os.Error {
+func (b *Buffer) UnreadByte() error {
 	if b.lastRead != opReadRune && b.lastRead != opRead {
-		return os.NewError("bytes.Buffer: UnreadByte: previous operation was not a read")
+		return errors.New("bytes.Buffer: UnreadByte: previous operation was not a read")
 	}
 	b.lastRead = opInvalid
 	if b.off > 0 {
@@ -307,15 +333,15 @@ func (b *Buffer) UnreadByte() os.Error {
 // ReadBytes reads until the first occurrence of delim in the input,
 // returning a slice containing the data up to and including the delimiter.
 // If ReadBytes encounters an error before finding a delimiter,
-// it returns the data read before the error and the error itself (often os.EOF).
+// it returns the data read before the error and the error itself (often io.EOF).
 // ReadBytes returns err != nil if and only if the returned data does not end in
 // delim.
-func (b *Buffer) ReadBytes(delim byte) (line []byte, err os.Error) {
+func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
 	i := IndexByte(b.buf[b.off:], delim)
 	size := i + 1
 	if i < 0 {
 		size = len(b.buf) - b.off
-		err = os.EOF
+		err = io.EOF
 	}
 	line = make([]byte, size)
 	copy(line, b.buf[b.off:])
@@ -326,10 +352,10 @@ func (b *Buffer) ReadBytes(delim byte) (line []byte, err os.Error) {
 // ReadString reads until the first occurrence of delim in the input,
 // returning a string containing the data up to and including the delimiter.
 // If ReadString encounters an error before finding a delimiter,
-// it returns the data read before the error and the error itself (often os.EOF).
+// it returns the data read before the error and the error itself (often io.EOF).
 // ReadString returns err != nil if and only if the returned data does not end
 // in delim.
-func (b *Buffer) ReadString(delim byte) (line string, err os.Error) {
+func (b *Buffer) ReadString(delim byte) (line string, err error) {
 	bytes, err := b.ReadBytes(delim)
 	return string(bytes), err
 }
diff --git a/src/pkg/bytes/buffer_test.go b/src/pkg/bytes/buffer_test.go
index 06d2a65..d0af11f 100644
--- a/src/pkg/bytes/buffer_test.go
+++ b/src/pkg/bytes/buffer_test.go
@@ -6,17 +6,16 @@ package bytes_test
 
 import (
 	. "bytes"
-	"os"
-	"rand"
+	"io"
+	"math/rand"
 	"testing"
-	"utf8"
+	"unicode/utf8"
 )
 
 const N = 10000  // make this bigger for a larger (and slower) test
 var data string  // test data for write tests
 var bytes []byte // test data; same as data but as a slice.
 
-
 func init() {
 	bytes = make([]byte, N)
 	for i := 0; i < N; i++ {
@@ -264,7 +263,7 @@ func TestRuneIO(t *testing.T) {
 	b := make([]byte, utf8.UTFMax*NRune)
 	var buf Buffer
 	n := 0
-	for r := 0; r < NRune; r++ {
+	for r := rune(0); r < NRune; r++ {
 		size := utf8.EncodeRune(b[n:], r)
 		nbytes, err := buf.WriteRune(r)
 		if err != nil {
@@ -284,7 +283,7 @@ func TestRuneIO(t *testing.T) {
 
 	p := make([]byte, utf8.UTFMax)
 	// Read it back with ReadRune
-	for r := 0; r < NRune; r++ {
+	for r := rune(0); r < NRune; r++ {
 		size := utf8.EncodeRune(p, r)
 		nr, nbytes, err := buf.ReadRune()
 		if nr != r || nbytes != size || err != nil {
@@ -295,7 +294,7 @@ func TestRuneIO(t *testing.T) {
 	// Check that UnreadRune works
 	buf.Reset()
 	buf.Write(b)
-	for r := 0; r < NRune; r++ {
+	for r := rune(0); r < NRune; r++ {
 		r1, size, _ := buf.ReadRune()
 		if err := buf.UnreadRune(); err != nil {
 			t.Fatalf("UnreadRune(%U) got error %q", r, err)
@@ -344,21 +343,21 @@ var readBytesTests = []struct {
 	buffer   string
 	delim    byte
 	expected []string
-	err      os.Error
+	err      error
 }{
-	{"", 0, []string{""}, os.EOF},
+	{"", 0, []string{""}, io.EOF},
 	{"a\x00", 0, []string{"a\x00"}, nil},
 	{"abbbaaaba", 'b', []string{"ab", "b", "b", "aaab"}, nil},
 	{"hello\x01world", 1, []string{"hello\x01"}, nil},
-	{"foo\nbar", 0, []string{"foo\nbar"}, os.EOF},
+	{"foo\nbar", 0, []string{"foo\nbar"}, io.EOF},
 	{"alpha\nbeta\ngamma\n", '\n', []string{"alpha\n", "beta\n", "gamma\n"}, nil},
-	{"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, os.EOF},
+	{"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, io.EOF},
 }
 
 func TestReadBytes(t *testing.T) {
 	for _, test := range readBytesTests {
 		buf := NewBufferString(test.buffer)
-		var err os.Error
+		var err error
 		for _, expected := range test.expected {
 			var bytes []byte
 			bytes, err = buf.ReadBytes(test.delim)
@@ -374,3 +373,16 @@ func TestReadBytes(t *testing.T) {
 		}
 	}
 }
+
+// Was a bug: used to give EOF reading empty slice at EOF.
+func TestReadEmptyAtEOF(t *testing.T) {
+	b := new(Buffer)
+	slice := make([]byte, 0)
+	n, err := b.Read(slice)
+	if err != nil {
+		t.Errorf("read error: %v", err)
+	}
+	if n != 0 {
+		t.Errorf("wrong count; got %d want 0", n)
+	}
+}
diff --git a/src/pkg/bytes/bytes.go b/src/pkg/bytes/bytes.go
index ea6bf5e..e94a0ec 100644
--- a/src/pkg/bytes/bytes.go
+++ b/src/pkg/bytes/bytes.go
@@ -8,7 +8,7 @@ package bytes
 
 import (
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 // Compare returns an integer comparing the two byte arrays lexicographically.
@@ -37,7 +37,9 @@ func Compare(a, b []byte) int {
 }
 
 // Equal returns a boolean reporting whether a == b.
-func Equal(a, b []byte) bool {
+func Equal(a, b []byte) bool
+
+func equalPortable(a, b []byte) bool {
 	if len(a) != len(b) {
 		return false
 	}
@@ -74,18 +76,38 @@ func explode(s []byte, n int) [][]byte {
 
 // Count counts the number of non-overlapping instances of sep in s.
 func Count(s, sep []byte) int {
-	if len(sep) == 0 {
+	n := len(sep)
+	if n == 0 {
 		return utf8.RuneCount(s) + 1
 	}
+	if n > len(s) {
+		return 0
+	}
+	count := 0
 	c := sep[0]
-	n := 0
-	for i := 0; i+len(sep) <= len(s); i++ {
-		if s[i] == c && (len(sep) == 1 || Equal(s[i:i+len(sep)], sep)) {
-			n++
-			i += len(sep) - 1
+	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 n == 1 || Equal(s[i:i+n], sep) {
+			count++
+			i += n
+			continue
+		}
+		i++
 	}
-	return n
+	return count
+}
+
+// Contains returns whether subslice is within b.
+func Contains(b, subslice []byte) bool {
+	return Index(b, subslice) != -1
 }
 
 // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
@@ -94,11 +116,27 @@ func Index(s, sep []byte) int {
 	if n == 0 {
 		return 0
 	}
+	if n > len(s) {
+		return -1
+	}
 	c := sep[0]
-	for i := 0; i+n <= len(s); i++ {
-		if s[i] == c && (n == 1 || Equal(s[i:i+n], sep)) {
+	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
 }
@@ -130,10 +168,10 @@ func LastIndex(s, sep []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.
-func IndexRune(s []byte, rune int) int {
+func IndexRune(s []byte, r rune) int {
 	for i := 0; i < len(s); {
-		r, size := utf8.DecodeRune(s[i:])
-		if r == rune {
+		r1, size := utf8.DecodeRune(s[i:])
+		if r == r1 {
 			return i
 		}
 		i += size
@@ -147,16 +185,17 @@ func IndexRune(s []byte, rune int) int {
 // point in common.
 func IndexAny(s []byte, chars string) int {
 	if len(chars) > 0 {
-		var rune, width int
+		var r rune
+		var width int
 		for i := 0; i < len(s); i += width {
-			rune = int(s[i])
-			if rune < utf8.RuneSelf {
+			r = rune(s[i])
+			if r < utf8.RuneSelf {
 				width = 1
 			} else {
-				rune, width = utf8.DecodeRune(s[i:])
+				r, width = utf8.DecodeRune(s[i:])
 			}
-			for _, r := range chars {
-				if rune == r {
+			for _, ch := range chars {
+				if r == ch {
 					return i
 				}
 			}
@@ -172,10 +211,10 @@ func IndexAny(s []byte, chars string) int {
 func LastIndexAny(s []byte, chars string) int {
 	if len(chars) > 0 {
 		for i := len(s); i > 0; {
-			rune, size := utf8.DecodeLastRune(s[0:i])
+			r, size := utf8.DecodeLastRune(s[0:i])
 			i -= size
-			for _, m := range chars {
-				if rune == m {
+			for _, ch := range chars {
+				if r == ch {
 					return i
 				}
 			}
@@ -256,13 +295,13 @@ func Fields(s []byte) [][]byte {
 // It splits the array s at each run of code points c satisfying f(c) and
 // returns a slice of subarrays of s.  If no code points in s satisfy f(c), an
 // empty slice is returned.
-func FieldsFunc(s []byte, f func(int) bool) [][]byte {
+func FieldsFunc(s []byte, f func(rune) bool) [][]byte {
 	n := 0
 	inField := false
 	for i := 0; i < len(s); {
-		rune, size := utf8.DecodeRune(s[i:])
+		r, size := utf8.DecodeRune(s[i:])
 		wasInField := inField
-		inField = !f(rune)
+		inField = !f(r)
 		if inField && !wasInField {
 			n++
 		}
@@ -273,13 +312,13 @@ func FieldsFunc(s []byte, f func(int) bool) [][]byte {
 	na := 0
 	fieldStart := -1
 	for i := 0; i <= len(s) && na < n; {
-		rune, size := utf8.DecodeRune(s[i:])
-		if fieldStart < 0 && size > 0 && !f(rune) {
+		r, size := utf8.DecodeRune(s[i:])
+		if fieldStart < 0 && size > 0 && !f(r) {
 			fieldStart = i
 			i += size
 			continue
 		}
-		if fieldStart >= 0 && (size == 0 || f(rune)) {
+		if fieldStart >= 0 && (size == 0 || f(r)) {
 			a[na] = s[fieldStart:i]
 			na++
 			fieldStart = -1
@@ -329,7 +368,7 @@ func HasSuffix(s, suffix []byte) bool {
 // according to the mapping function. If mapping returns a negative value, the character is
 // dropped from the string with no replacement.  The characters in s and the
 // output are interpreted as UTF-8-encoded Unicode code points.
-func Map(mapping func(rune int) int, s []byte) []byte {
+func Map(mapping func(r rune) rune, s []byte) []byte {
 	// In the worst case, the array can grow when mapped, making
 	// things unpleasant.  But it's so rare we barge in assuming it's
 	// fine.  It could also shrink but that falls out naturally.
@@ -338,20 +377,20 @@ func Map(mapping func(rune int) int, s []byte) []byte {
 	b := make([]byte, maxbytes)
 	for i := 0; i < len(s); {
 		wid := 1
-		rune := int(s[i])
-		if rune >= utf8.RuneSelf {
-			rune, wid = utf8.DecodeRune(s[i:])
+		r := rune(s[i])
+		if r >= utf8.RuneSelf {
+			r, wid = utf8.DecodeRune(s[i:])
 		}
-		rune = mapping(rune)
-		if rune >= 0 {
-			if nbytes+utf8.RuneLen(rune) > maxbytes {
+		r = mapping(r)
+		if r >= 0 {
+			if nbytes+utf8.RuneLen(r) > maxbytes {
 				// Grow the buffer.
 				maxbytes = maxbytes*2 + utf8.UTFMax
 				nb := make([]byte, maxbytes)
 				copy(nb, b[0:nbytes])
 				b = nb
 			}
-			nbytes += utf8.EncodeRune(b[nbytes:maxbytes], rune)
+			nbytes += utf8.EncodeRune(b[nbytes:maxbytes], r)
 		}
 		i += wid
 	}
@@ -383,44 +422,44 @@ func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
 // ToUpperSpecial returns a copy of the byte array s with all Unicode letters mapped to their
 // upper case, giving priority to the special casing rules.
 func ToUpperSpecial(_case unicode.SpecialCase, s []byte) []byte {
-	return Map(func(r int) int { return _case.ToUpper(r) }, s)
+	return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
 }
 
 // ToLowerSpecial returns a copy of the byte array s with all Unicode letters mapped to their
 // lower case, giving priority to the special casing rules.
 func ToLowerSpecial(_case unicode.SpecialCase, s []byte) []byte {
-	return Map(func(r int) int { return _case.ToLower(r) }, s)
+	return Map(func(r rune) rune { return _case.ToLower(r) }, s)
 }
 
 // ToTitleSpecial returns a copy of the byte array s with all Unicode letters mapped to their
 // title case, giving priority to the special casing rules.
 func ToTitleSpecial(_case unicode.SpecialCase, s []byte) []byte {
-	return Map(func(r int) int { return _case.ToTitle(r) }, s)
+	return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
 }
 
 // isSeparator reports whether the rune could mark a word boundary.
 // TODO: update when package unicode captures more of the properties.
-func isSeparator(rune int) bool {
+func isSeparator(r rune) bool {
 	// ASCII alphanumerics and underscore are not separators
-	if rune <= 0x7F {
+	if r <= 0x7F {
 		switch {
-		case '0' <= rune && rune <= '9':
+		case '0' <= r && r <= '9':
 			return false
-		case 'a' <= rune && rune <= 'z':
+		case 'a' <= r && r <= 'z':
 			return false
-		case 'A' <= rune && rune <= 'Z':
+		case 'A' <= r && r <= 'Z':
 			return false
-		case rune == '_':
+		case r == '_':
 			return false
 		}
 		return true
 	}
 	// Letters and digits are not separators
-	if unicode.IsLetter(rune) || unicode.IsDigit(rune) {
+	if unicode.IsLetter(r) || unicode.IsDigit(r) {
 		return false
 	}
 	// Otherwise, all we can do for now is treat spaces as separators.
-	return unicode.IsSpace(rune)
+	return unicode.IsSpace(r)
 }
 
 // BUG(r): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
@@ -433,7 +472,7 @@ func Title(s []byte) []byte {
 	// the closure once per rune.
 	prev := ' '
 	return Map(
-		func(r int) int {
+		func(r rune) rune {
 			if isSeparator(prev) {
 				prev = r
 				return unicode.ToTitle(r)
@@ -446,7 +485,7 @@ func Title(s []byte) []byte {
 
 // TrimLeftFunc returns a subslice of s by slicing off all leading UTF-8-encoded
 // Unicode code points c that satisfy f(c).
-func TrimLeftFunc(s []byte, f func(r int) bool) []byte {
+func TrimLeftFunc(s []byte, f func(r rune) bool) []byte {
 	i := indexFunc(s, f, false)
 	if i == -1 {
 		return nil
@@ -456,7 +495,7 @@ func TrimLeftFunc(s []byte, f func(r int) bool) []byte {
 
 // TrimRightFunc returns a subslice of s by slicing off all trailing UTF-8
 // encoded Unicode code points c that satisfy f(c).
-func TrimRightFunc(s []byte, f func(r int) bool) []byte {
+func TrimRightFunc(s []byte, f func(r rune) bool) []byte {
 	i := lastIndexFunc(s, f, false)
 	if i >= 0 && s[i] >= utf8.RuneSelf {
 		_, wid := utf8.DecodeRune(s[i:])
@@ -469,36 +508,36 @@ func TrimRightFunc(s []byte, f func(r int) bool) []byte {
 
 // TrimFunc returns a subslice of s by slicing off all leading and trailing
 // UTF-8-encoded Unicode code points c that satisfy f(c).
-func TrimFunc(s []byte, f func(r int) bool) []byte {
+func TrimFunc(s []byte, f func(r rune) bool) []byte {
 	return TrimRightFunc(TrimLeftFunc(s, f), f)
 }
 
 // IndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
 // It returns the byte index in s of the first Unicode
 // code point satisfying f(c), or -1 if none do.
-func IndexFunc(s []byte, f func(r int) bool) int {
+func IndexFunc(s []byte, f func(r rune) bool) int {
 	return indexFunc(s, f, true)
 }
 
 // LastIndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
 // It returns the byte index in s of the last Unicode
 // code point satisfying f(c), or -1 if none do.
-func LastIndexFunc(s []byte, f func(r int) bool) int {
+func LastIndexFunc(s []byte, f func(r rune) bool) int {
 	return lastIndexFunc(s, f, true)
 }
 
 // indexFunc is the same as IndexFunc except that if
 // truth==false, the sense of the predicate function is
 // inverted.
-func indexFunc(s []byte, f func(r int) bool, truth bool) int {
+func indexFunc(s []byte, f func(r rune) bool, truth bool) int {
 	start := 0
 	for start < len(s) {
 		wid := 1
-		rune := int(s[start])
-		if rune >= utf8.RuneSelf {
-			rune, wid = utf8.DecodeRune(s[start:])
+		r := rune(s[start])
+		if r >= utf8.RuneSelf {
+			r, wid = utf8.DecodeRune(s[start:])
 		}
-		if f(rune) == truth {
+		if f(r) == truth {
 			return start
 		}
 		start += wid
@@ -509,21 +548,21 @@ func indexFunc(s []byte, f func(r int) bool, truth bool) int {
 // lastIndexFunc is the same as LastIndexFunc except that if
 // truth==false, the sense of the predicate function is
 // inverted.
-func lastIndexFunc(s []byte, f func(r int) bool, truth bool) int {
+func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int {
 	for i := len(s); i > 0; {
-		rune, size := utf8.DecodeLastRune(s[0:i])
+		r, size := utf8.DecodeLastRune(s[0:i])
 		i -= size
-		if f(rune) == truth {
+		if f(r) == truth {
 			return i
 		}
 	}
 	return -1
 }
 
-func makeCutsetFunc(cutset string) func(rune int) bool {
-	return func(rune int) bool {
+func makeCutsetFunc(cutset string) func(r rune) bool {
+	return func(r rune) bool {
 		for _, c := range cutset {
-			if c == rune {
+			if c == r {
 				return true
 			}
 		}
@@ -556,8 +595,8 @@ func TrimSpace(s []byte) []byte {
 }
 
 // Runes returns a slice of runes (Unicode code points) equivalent to s.
-func Runes(s []byte) []int {
-	t := make([]int, utf8.RuneCount(s))
+func Runes(s []byte) []rune {
+	t := make([]rune, utf8.RuneCount(s))
 	i := 0
 	for len(s) > 0 {
 		r, l := utf8.DecodeRune(s)
@@ -608,3 +647,58 @@ func Replace(s, old, new []byte, n int) []byte {
 	w += copy(t[w:], s[start:])
 	return t[0:w]
 }
+
+// EqualFold reports whether s and t, interpreted as UTF-8 strings,
+// are equal under Unicode case-folding.
+func EqualFold(s, t []byte) bool {
+	for len(s) != 0 && len(t) != 0 {
+		// Extract first rune from each.
+		var sr, tr rune
+		if s[0] < utf8.RuneSelf {
+			sr, s = rune(s[0]), s[1:]
+		} else {
+			r, size := utf8.DecodeRune(s)
+			sr, s = r, s[size:]
+		}
+		if t[0] < utf8.RuneSelf {
+			tr, t = rune(t[0]), t[1:]
+		} else {
+			r, size := utf8.DecodeRune(t)
+			tr, t = r, t[size:]
+		}
+
+		// If they match, keep going; if not, return false.
+
+		// Easy case.
+		if tr == sr {
+			continue
+		}
+
+		// Make sr < tr to simplify what follows.
+		if tr < sr {
+			tr, sr = sr, tr
+		}
+		// Fast check for ASCII.
+		if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
+			// ASCII, and sr is upper case.  tr must be lower case.
+			if tr == sr+'a'-'A' {
+				continue
+			}
+			return false
+		}
+
+		// General case.  SimpleFold(x) returns the next equivalent rune > x
+		// or wraps around to smaller values.
+		r := unicode.SimpleFold(sr)
+		for r != sr && r < tr {
+			r = unicode.SimpleFold(r)
+		}
+		if r == tr {
+			continue
+		}
+		return false
+	}
+
+	// One string is empty.  Are both?
+	return len(s) == len(t)
+}
diff --git a/src/pkg/bytes/bytes_test.go b/src/pkg/bytes/bytes_test.go
index 1679279..2a1d41b 100644
--- a/src/pkg/bytes/bytes_test.go
+++ b/src/pkg/bytes/bytes_test.go
@@ -9,7 +9,7 @@ import (
 	"reflect"
 	"testing"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 func eq(a, b []string) bool {
@@ -64,13 +64,17 @@ func TestCompare(t *testing.T) {
 		a := []byte(tt.a)
 		b := []byte(tt.b)
 		cmp := Compare(a, b)
-		eql := Equal(a, b)
 		if cmp != tt.i {
 			t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
 		}
+		eql := Equal(a, b)
 		if eql != (tt.i == 0) {
 			t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
 		}
+		eql = EqualPortable(a, b)
+		if eql != (tt.i == 0) {
+			t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql)
+		}
 	}
 }
 
@@ -264,27 +268,111 @@ func TestIndexRune(t *testing.T) {
 	}
 }
 
-func BenchmarkIndexByte4K(b *testing.B) { bmIndex(b, IndexByte, 4<<10) }
+var bmbuf []byte
 
-func BenchmarkIndexByte4M(b *testing.B) { bmIndex(b, IndexByte, 4<<20) }
+func BenchmarkIndexByte32(b *testing.B)          { bmIndexByte(b, IndexByte, 32) }
+func BenchmarkIndexByte4K(b *testing.B)          { bmIndexByte(b, IndexByte, 4<<10) }
+func BenchmarkIndexByte4M(b *testing.B)          { bmIndexByte(b, IndexByte, 4<<20) }
+func BenchmarkIndexByte64M(b *testing.B)         { bmIndexByte(b, IndexByte, 64<<20) }
+func BenchmarkIndexBytePortable32(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 32) }
+func BenchmarkIndexBytePortable4K(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 4<<10) }
+func BenchmarkIndexBytePortable4M(b *testing.B)  { bmIndexByte(b, IndexBytePortable, 4<<20) }
+func BenchmarkIndexBytePortable64M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 64<<20) }
 
-func BenchmarkIndexByte64M(b *testing.B) { bmIndex(b, IndexByte, 64<<20) }
+func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	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 BenchmarkIndexBytePortable4K(b *testing.B) {
-	bmIndex(b, IndexBytePortable, 4<<10)
+func BenchmarkEqual32(b *testing.B)          { bmEqual(b, Equal, 32) }
+func BenchmarkEqual4K(b *testing.B)          { bmEqual(b, Equal, 4<<10) }
+func BenchmarkEqual4M(b *testing.B)          { bmEqual(b, Equal, 4<<20) }
+func BenchmarkEqual64M(b *testing.B)         { bmEqual(b, Equal, 64<<20) }
+func BenchmarkEqualPort32(b *testing.B)      { bmEqual(b, EqualPortable, 32) }
+func BenchmarkEqualPort4K(b *testing.B)      { bmEqual(b, EqualPortable, 4<<10) }
+func BenchmarkEqualPortable4M(b *testing.B)  { bmEqual(b, EqualPortable, 4<<20) }
+func BenchmarkEqualPortable64M(b *testing.B) { bmEqual(b, EqualPortable, 64<<20) }
+
+func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) {
+	if len(bmbuf) < 2*n {
+		bmbuf = make([]byte, 2*n)
+	}
+	b.SetBytes(int64(n))
+	buf1 := bmbuf[0:n]
+	buf2 := bmbuf[n : 2*n]
+	buf1[n-1] = 'x'
+	buf2[n-1] = 'x'
+	for i := 0; i < b.N; i++ {
+		eq := equal(buf1, buf2)
+		if !eq {
+			b.Fatal("bad equal")
+		}
+	}
+	buf1[n-1] = '\x00'
+	buf2[n-1] = '\x00'
 }
 
-func BenchmarkIndexBytePortable4M(b *testing.B) {
-	bmIndex(b, IndexBytePortable, 4<<20)
+func BenchmarkIndex32(b *testing.B)  { bmIndex(b, Index, 32) }
+func BenchmarkIndex4K(b *testing.B)  { bmIndex(b, Index, 4<<10) }
+func BenchmarkIndex4M(b *testing.B)  { bmIndex(b, Index, 4<<20) }
+func BenchmarkIndex64M(b *testing.B) { bmIndex(b, Index, 64<<20) }
+
+func bmIndex(b *testing.B, index func([]byte, []byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	buf := bmbuf[0:n]
+	buf[n-1] = 'x'
+	for i := 0; i < b.N; i++ {
+		j := index(buf, buf[n-7:])
+		if j != n-7 {
+			b.Fatal("bad index", j)
+		}
+	}
+	buf[n-1] = '\x00'
 }
 
-func BenchmarkIndexBytePortable64M(b *testing.B) {
-	bmIndex(b, IndexBytePortable, 64<<20)
+func BenchmarkIndexEasy32(b *testing.B)  { bmIndexEasy(b, Index, 32) }
+func BenchmarkIndexEasy4K(b *testing.B)  { bmIndexEasy(b, Index, 4<<10) }
+func BenchmarkIndexEasy4M(b *testing.B)  { bmIndexEasy(b, Index, 4<<20) }
+func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) }
+
+func bmIndexEasy(b *testing.B, index func([]byte, []byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	buf := bmbuf[0:n]
+	buf[n-1] = 'x'
+	buf[n-7] = 'x'
+	for i := 0; i < b.N; i++ {
+		j := index(buf, buf[n-7:])
+		if j != n-7 {
+			b.Fatal("bad index", j)
+		}
+	}
+	buf[n-1] = '\x00'
+	buf[n-7] = '\x00'
 }
 
-var bmbuf []byte
+func BenchmarkCount32(b *testing.B)  { bmCount(b, Count, 32) }
+func BenchmarkCount4K(b *testing.B)  { bmCount(b, Count, 4<<10) }
+func BenchmarkCount4M(b *testing.B)  { bmCount(b, Count, 4<<20) }
+func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) }
 
-func bmIndex(b *testing.B, index func([]byte, byte) int, n int) {
+func bmCount(b *testing.B, count func([]byte, []byte) int, n int) {
 	if len(bmbuf) < n {
 		bmbuf = make([]byte, n)
 	}
@@ -292,13 +380,35 @@ func bmIndex(b *testing.B, index func([]byte, byte) int, 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 {
-			println("bad index", j)
-			panic("bad index")
+		j := count(buf, buf[n-7:])
+		if j != 1 {
+			b.Fatal("bad count", j)
+		}
+	}
+	buf[n-1] = '\x00'
+}
+
+func BenchmarkCountEasy32(b *testing.B)  { bmCountEasy(b, Count, 32) }
+func BenchmarkCountEasy4K(b *testing.B)  { bmCountEasy(b, Count, 4<<10) }
+func BenchmarkCountEasy4M(b *testing.B)  { bmCountEasy(b, Count, 4<<20) }
+func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) }
+
+func bmCountEasy(b *testing.B, count func([]byte, []byte) int, n int) {
+	if len(bmbuf) < n {
+		bmbuf = make([]byte, n)
+	}
+	b.SetBytes(int64(n))
+	buf := bmbuf[0:n]
+	buf[n-1] = 'x'
+	buf[n-7] = 'x'
+	for i := 0; i < b.N; i++ {
+		j := count(buf, buf[n-7:])
+		if j != 1 {
+			b.Fatal("bad count", j)
 		}
 	}
-	buf[n-1] = '0'
+	buf[n-1] = '\x00'
+	buf[n-7] = '\x00'
 }
 
 type ExplodeTest struct {
@@ -444,7 +554,7 @@ func TestFields(t *testing.T) {
 }
 
 func TestFieldsFunc(t *testing.T) {
-	pred := func(c int) bool { return c == 'X' }
+	pred := func(c rune) bool { return c == 'X' }
 	var fieldsFuncTests = []FieldsTest{
 		{"", []string{}},
 		{"XX", []string{}},
@@ -514,24 +624,24 @@ func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCa
 	}
 }
 
-func tenRunes(rune int) string {
-	r := make([]int, 10)
-	for i := range r {
-		r[i] = rune
+func tenRunes(r rune) string {
+	runes := make([]rune, 10)
+	for i := range runes {
+		runes[i] = r
 	}
-	return string(r)
+	return string(runes)
 }
 
 // User-defined self-inverse mapping function
-func rot13(rune int) int {
-	step := 13
-	if rune >= 'a' && rune <= 'z' {
-		return ((rune - 'a' + step) % 26) + 'a'
+func rot13(r rune) rune {
+	const step = 13
+	if r >= 'a' && r <= 'z' {
+		return ((r - 'a' + step) % 26) + 'a'
 	}
-	if rune >= 'A' && rune <= 'Z' {
-		return ((rune - 'A' + step) % 26) + 'A'
+	if r >= 'A' && r <= 'Z' {
+		return ((r - 'A' + step) % 26) + 'A'
 	}
-	return rune
+	return r
 }
 
 func TestMap(t *testing.T) {
@@ -539,7 +649,7 @@ func TestMap(t *testing.T) {
 	a := tenRunes('a')
 
 	// 1.  Grow.  This triggers two reallocations in Map.
-	maxRune := func(rune int) int { return unicode.MaxRune }
+	maxRune := func(r rune) rune { return unicode.MaxRune }
 	m := Map(maxRune, []byte(a))
 	expect := tenRunes(unicode.MaxRune)
 	if string(m) != expect {
@@ -547,7 +657,7 @@ func TestMap(t *testing.T) {
 	}
 
 	// 2. Shrink
-	minRune := func(rune int) int { return 'a' }
+	minRune := func(r rune) rune { return 'a' }
 	m = Map(minRune, []byte(tenRunes(unicode.MaxRune)))
 	expect = a
 	if string(m) != expect {
@@ -569,9 +679,9 @@ func TestMap(t *testing.T) {
 	}
 
 	// 5. Drop
-	dropNotLatin := func(rune int) int {
-		if unicode.Is(unicode.Latin, rune) {
-			return rune
+	dropNotLatin := func(r rune) rune {
+		if unicode.Is(unicode.Latin, r) {
+			return r
 		}
 		return -1
 	}
@@ -615,7 +725,7 @@ func TestRepeat(t *testing.T) {
 	}
 }
 
-func runesEqual(a, b []int) bool {
+func runesEqual(a, b []rune) bool {
 	if len(a) != len(b) {
 		return false
 	}
@@ -629,18 +739,18 @@ func runesEqual(a, b []int) bool {
 
 type RunesTest struct {
 	in    string
-	out   []int
+	out   []rune
 	lossy bool
 }
 
 var RunesTests = []RunesTest{
-	{"", []int{}, false},
-	{" ", []int{32}, false},
-	{"ABC", []int{65, 66, 67}, false},
-	{"abc", []int{97, 98, 99}, false},
-	{"\u65e5\u672c\u8a9e", []int{26085, 26412, 35486}, false},
-	{"ab\x80c", []int{97, 98, 0xFFFD, 99}, true},
-	{"ab\xc0c", []int{97, 98, 0xFFFD, 99}, true},
+	{"", []rune{}, false},
+	{" ", []rune{32}, false},
+	{"ABC", []rune{65, 66, 67}, false},
+	{"abc", []rune{97, 98, 99}, false},
+	{"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false},
+	{"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true},
+	{"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true},
 }
 
 func TestRunes(t *testing.T) {
@@ -662,48 +772,49 @@ func TestRunes(t *testing.T) {
 }
 
 type TrimTest struct {
-	f               func([]byte, string) []byte
+	f               string
 	in, cutset, out string
 }
 
 var trimTests = []TrimTest{
-	{Trim, "abba", "a", "bb"},
-	{Trim, "abba", "ab", ""},
-	{TrimLeft, "abba", "ab", ""},
-	{TrimRight, "abba", "ab", ""},
-	{TrimLeft, "abba", "a", "bba"},
-	{TrimRight, "abba", "a", "abb"},
-	{Trim, "<tag>", "<>", "tag"},
-	{Trim, "* listitem", " *", "listitem"},
-	{Trim, `"quote"`, `"`, "quote"},
-	{Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
+	{"Trim", "abba", "a", "bb"},
+	{"Trim", "abba", "ab", ""},
+	{"TrimLeft", "abba", "ab", ""},
+	{"TrimRight", "abba", "ab", ""},
+	{"TrimLeft", "abba", "a", "bba"},
+	{"TrimRight", "abba", "a", "abb"},
+	{"Trim", "<tag>", "<>", "tag"},
+	{"Trim", "* listitem", " *", "listitem"},
+	{"Trim", `"quote"`, `"`, "quote"},
+	{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
 	//empty string tests
-	{Trim, "abba", "", "abba"},
-	{Trim, "", "123", ""},
-	{Trim, "", "", ""},
-	{TrimLeft, "abba", "", "abba"},
-	{TrimLeft, "", "123", ""},
-	{TrimLeft, "", "", ""},
-	{TrimRight, "abba", "", "abba"},
-	{TrimRight, "", "123", ""},
-	{TrimRight, "", "", ""},
-	{TrimRight, "☺\xc0", "☺", "☺\xc0"},
+	{"Trim", "abba", "", "abba"},
+	{"Trim", "", "123", ""},
+	{"Trim", "", "", ""},
+	{"TrimLeft", "abba", "", "abba"},
+	{"TrimLeft", "", "123", ""},
+	{"TrimLeft", "", "", ""},
+	{"TrimRight", "abba", "", "abba"},
+	{"TrimRight", "", "123", ""},
+	{"TrimRight", "", "", ""},
+	{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
 }
 
 func TestTrim(t *testing.T) {
 	for _, tc := range trimTests {
-		actual := string(tc.f([]byte(tc.in), tc.cutset))
-		var name string
-		switch tc.f {
-		case Trim:
-			name = "Trim"
-		case TrimLeft:
-			name = "TrimLeft"
-		case TrimRight:
-			name = "TrimRight"
+		name := tc.f
+		var f func([]byte, string) []byte
+		switch name {
+		case "Trim":
+			f = Trim
+		case "TrimLeft":
+			f = TrimLeft
+		case "TrimRight":
+			f = TrimRight
 		default:
-			t.Error("Undefined trim function")
+			t.Errorf("Undefined trim function %s", name)
 		}
+		actual := string(f([]byte(tc.in), tc.cutset))
 		if actual != tc.out {
 			t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
 		}
@@ -711,7 +822,7 @@ func TestTrim(t *testing.T) {
 }
 
 type predicate struct {
-	f    func(r int) bool
+	f    func(r rune) bool
 	name string
 }
 
@@ -719,7 +830,7 @@ var isSpace = predicate{unicode.IsSpace, "IsSpace"}
 var isDigit = predicate{unicode.IsDigit, "IsDigit"}
 var isUpper = predicate{unicode.IsUpper, "IsUpper"}
 var isValidRune = predicate{
-	func(r int) bool {
+	func(r rune) bool {
 		return r != utf8.RuneError
 	},
 	"IsValidRune",
@@ -732,7 +843,7 @@ type TrimFuncTest struct {
 
 func not(p predicate) predicate {
 	return predicate{
-		func(r int) bool {
+		func(r rune) bool {
 			return !p.f(r)
 		},
 		"not " + p.name,
@@ -829,7 +940,7 @@ var ReplaceTests = []ReplaceTest{
 
 func TestReplace(t *testing.T) {
 	for _, tt := range ReplaceTests {
-		in := append([]byte(tt.in), []byte("<spare>")...)
+		in := append([]byte(tt.in), "<spare>"...)
 		in = in[:len(tt.in)]
 		out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n)
 		if s := string(out); s != tt.out {
@@ -862,3 +973,31 @@ func TestTitle(t *testing.T) {
 		}
 	}
 }
+
+var EqualFoldTests = []struct {
+	s, t string
+	out  bool
+}{
+	{"abc", "abc", true},
+	{"ABcd", "ABcd", true},
+	{"123abc", "123ABC", true},
+	{"αβδ", "ΑΒΔ", true},
+	{"abc", "xyz", false},
+	{"abc", "XYZ", false},
+	{"abcdefghijk", "abcdefghijX", false},
+	{"abcdefghijk", "abcdefghij\u212A", true},
+	{"abcdefghijK", "abcdefghij\u212A", true},
+	{"abcdefghijkz", "abcdefghij\u212Ay", false},
+	{"abcdefghijKz", "abcdefghij\u212Ay", false},
+}
+
+func TestEqualFold(t *testing.T) {
+	for _, tt := range EqualFoldTests {
+		if out := EqualFold([]byte(tt.s), []byte(tt.t)); out != tt.out {
+			t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out)
+		}
+		if out := EqualFold([]byte(tt.t), []byte(tt.s)); out != tt.out {
+			t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out)
+		}
+	}
+}
diff --git a/src/pkg/bytes/example_test.go b/src/pkg/bytes/example_test.go
new file mode 100644
index 0000000..0234a01
--- /dev/null
+++ b/src/pkg/bytes/example_test.go
@@ -0,0 +1,28 @@
+// Copyright 2011 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_test
+
+import (
+	. "bytes"
+	"encoding/base64"
+	"io"
+	"os"
+)
+
+// Hello world!
+func ExampleBuffer() {
+	var b Buffer // A Buffer needs no initialization.
+	b.Write([]byte("Hello "))
+	b.Write([]byte("world!"))
+	b.WriteTo(os.Stdout)
+}
+
+// Gophers rule!
+func ExampleBuffer_reader() {
+	// A Buffer can turn a string or a []byte into an io.Reader.
+	buf := NewBufferString("R29waGVycyBydWxlIQ==")
+	dec := base64.NewDecoder(base64.StdEncoding, buf)
+	io.Copy(os.Stdout, dec)
+}
diff --git a/src/pkg/bytes/export_test.go b/src/pkg/bytes/export_test.go
index b65428d..f61523e 100644
--- a/src/pkg/bytes/export_test.go
+++ b/src/pkg/bytes/export_test.go
@@ -6,3 +6,4 @@ package bytes
 
 // Export func for testing
 var IndexBytePortable = indexBytePortable
+var EqualPortable = equalPortable
diff --git a/src/pkg/cmath/Makefile b/src/pkg/cmath/Makefile
deleted file mode 100644
index 486caac..0000000
--- a/src/pkg/cmath/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=cmath
-
-GOFILES=\
-	abs.go\
-	asin.go\
-	conj.go\
-	exp.go\
-	isinf.go\
-	isnan.go\
-	log.go\
-	phase.go\
-	polar.go\
-	pow.go\
-	rect.go\
-	sin.go\
-	sqrt.go\
-	tan.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/cmath/abs.go b/src/pkg/cmath/abs.go
deleted file mode 100644
index f3199ca..0000000
--- a/src/pkg/cmath/abs.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2010 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 cmath provides basic constants and mathematical functions for
-// complex numbers.
-package cmath
-
-import "math"
-
-// Abs returns the absolute value (also called the modulus) of x.
-func Abs(x complex128) float64 { return math.Hypot(real(x), imag(x)) }
diff --git a/src/pkg/cmath/asin.go b/src/pkg/cmath/asin.go
deleted file mode 100644
index d6a3ca4..0000000
--- a/src/pkg/cmath/asin.go
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// The original C code, the long comment, and the constants
-// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
-// The go code is a simplified version of the original C.
-//
-// Cephes Math Library Release 2.8:  June, 2000
-// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
-//
-// The readme file at http://netlib.sandia.gov/cephes/ says:
-//    Some software in this archive may be from the book _Methods and
-// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
-// International, 1989) or from the Cephes Mathematical Library, a
-// commercial product. In either event, it is copyrighted by the author.
-// What you see here may be used freely but it comes with no support or
-// guarantee.
-//
-//   The two known misprints in the book are repaired here in the
-// source listings for the gamma function and the incomplete beta
-// integral.
-//
-//   Stephen L. Moshier
-//   moshier at na-net.ornl.gov
-
-// Complex circular arc sine
-//
-// DESCRIPTION:
-//
-// Inverse complex sine:
-//                               2
-// w = -i clog( iz + csqrt( 1 - z ) ).
-//
-// casin(z) = -i casinh(iz)
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10     10100       2.1e-15     3.4e-16
-//    IEEE      -10,+10     30000       2.2e-14     2.7e-15
-// Larger relative error can be observed for z near zero.
-// Also tested by csin(casin(z)) = z.
-
-// Asin returns the inverse sine of x.
-func Asin(x complex128) complex128 {
-	if imag(x) == 0 {
-		if math.Fabs(real(x)) > 1 {
-			return complex(math.Pi/2, 0) // DOMAIN error
-		}
-		return complex(math.Asin(real(x)), 0)
-	}
-	ct := complex(-imag(x), real(x)) // i * x
-	xx := x * x
-	x1 := complex(1-real(xx), -imag(xx)) // 1 - x*x
-	x2 := Sqrt(x1)                       // x2 = sqrt(1 - x*x)
-	w := Log(ct + x2)
-	return complex(imag(w), -real(w)) // -i * w
-}
-
-// Asinh returns the inverse hyperbolic sine of x.
-func Asinh(x complex128) complex128 {
-	// TODO check range
-	if imag(x) == 0 {
-		if math.Fabs(real(x)) > 1 {
-			return complex(math.Pi/2, 0) // DOMAIN error
-		}
-		return complex(math.Asinh(real(x)), 0)
-	}
-	xx := x * x
-	x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
-	return Log(x + Sqrt(x1))            // log(x + sqrt(1 + x*x))
-}
-
-// Complex circular arc cosine
-//
-// DESCRIPTION:
-//
-// w = arccos z  =  PI/2 - arcsin z.
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10      5200      1.6e-15      2.8e-16
-//    IEEE      -10,+10     30000      1.8e-14      2.2e-15
-
-// Acos returns the inverse cosine of x.
-func Acos(x complex128) complex128 {
-	w := Asin(x)
-	return complex(math.Pi/2-real(w), -imag(w))
-}
-
-// Acosh returns the inverse hyperbolic cosine of x.
-func Acosh(x complex128) complex128 {
-	w := Acos(x)
-	if imag(w) <= 0 {
-		return complex(-imag(w), real(w)) // i * w
-	}
-	return complex(imag(w), -real(w)) // -i * w
-}
-
-// Complex circular arc tangent
-//
-// DESCRIPTION:
-//
-// If
-//     z = x + iy,
-//
-// then
-//          1       (    2x     )
-// Re w  =  - arctan(-----------)  +  k PI
-//          2       (     2    2)
-//                  (1 - x  - y )
-//
-//               ( 2         2)
-//          1    (x  +  (y+1) )
-// Im w  =  - log(------------)
-//          4    ( 2         2)
-//               (x  +  (y-1) )
-//
-// Where k is an arbitrary integer.
-//
-// catan(z) = -i catanh(iz).
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10      5900       1.3e-16     7.8e-18
-//    IEEE      -10,+10     30000       2.3e-15     8.5e-17
-// The check catan( ctan(z) )  =  z, with |x| and |y| < PI/2,
-// had peak relative error 1.5e-16, rms relative error
-// 2.9e-17.  See also clog().
-
-// Atan returns the inverse tangent of x.
-func Atan(x complex128) complex128 {
-	if real(x) == 0 && imag(x) > 1 {
-		return NaN()
-	}
-
-	x2 := real(x) * real(x)
-	a := 1 - x2 - imag(x)*imag(x)
-	if a == 0 {
-		return NaN()
-	}
-	t := 0.5 * math.Atan2(2*real(x), a)
-	w := reducePi(t)
-
-	t = imag(x) - 1
-	b := x2 + t*t
-	if b == 0 {
-		return NaN()
-	}
-	t = imag(x) + 1
-	c := (x2 + t*t) / b
-	return complex(w, 0.25*math.Log(c))
-}
-
-// Atanh returns the inverse hyperbolic tangent of x.
-func Atanh(x complex128) complex128 {
-	z := complex(-imag(x), real(x)) // z = i * x
-	z = Atan(z)
-	return complex(imag(z), -real(z)) // z = -i * z
-}
diff --git a/src/pkg/cmath/cmath_test.go b/src/pkg/cmath/cmath_test.go
deleted file mode 100644
index 6a595b0..0000000
--- a/src/pkg/cmath/cmath_test.go
+++ /dev/null
@@ -1,853 +0,0 @@
-// Copyright 2010 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 cmath
-
-import (
-	"math"
-	"testing"
-)
-
-var vc26 = []complex128{
-	(4.97901192488367350108546816 + 7.73887247457810456552351752i),
-	(7.73887247457810456552351752 - 0.27688005719200159404635997i),
-	(-0.27688005719200159404635997 - 5.01060361827107492160848778i),
-	(-5.01060361827107492160848778 + 9.63629370719841737980004837i),
-	(9.63629370719841737980004837 + 2.92637723924396464525443662i),
-	(2.92637723924396464525443662 + 5.22908343145930665230025625i),
-	(5.22908343145930665230025625 + 2.72793991043601025126008608i),
-	(2.72793991043601025126008608 + 1.82530809168085506044576505i),
-	(1.82530809168085506044576505 - 8.68592476857560136238589621i),
-	(-8.68592476857560136238589621 + 4.97901192488367350108546816i),
-}
-var vc = []complex128{
-	(4.9790119248836735e+00 + 7.7388724745781045e+00i),
-	(7.7388724745781045e+00 - 2.7688005719200159e-01i),
-	(-2.7688005719200159e-01 - 5.0106036182710749e+00i),
-	(-5.0106036182710749e+00 + 9.6362937071984173e+00i),
-	(9.6362937071984173e+00 + 2.9263772392439646e+00i),
-	(2.9263772392439646e+00 + 5.2290834314593066e+00i),
-	(5.2290834314593066e+00 + 2.7279399104360102e+00i),
-	(2.7279399104360102e+00 + 1.8253080916808550e+00i),
-	(1.8253080916808550e+00 - 8.6859247685756013e+00i),
-	(-8.6859247685756013e+00 + 4.9790119248836735e+00i),
-}
-
-// The expected results below were computed by the high precision calculators
-// at http://keisan.casio.com/.  More exact input values (array vc[], above)
-// were obtained by printing them with "%.26f".  The answers were calculated
-// to 26 digits (by using the "Digit number" drop-down control of each
-// calculator).
-
-var abs = []float64{
-	9.2022120669932650313380972e+00,
-	7.7438239742296106616261394e+00,
-	5.0182478202557746902556648e+00,
-	1.0861137372799545160704002e+01,
-	1.0070841084922199607011905e+01,
-	5.9922447613166942183705192e+00,
-	5.8978784056736762299945176e+00,
-	3.2822866700678709020367184e+00,
-	8.8756430028990417290744307e+00,
-	1.0011785496777731986390856e+01,
-}
-
-var acos = []complex128{
-	(1.0017679804707456328694569 - 2.9138232718554953784519807i),
-	(0.03606427612041407369636057 + 2.7358584434576260925091256i),
-	(1.6249365462333796703711823 + 2.3159537454335901187730929i),
-	(2.0485650849650740120660391 - 3.0795576791204117911123886i),
-	(0.29621132089073067282488147 - 3.0007392508200622519398814i),
-	(1.0664555914934156601503632 - 2.4872865024796011364747111i),
-	(0.48681307452231387690013905 - 2.463655912283054555225301i),
-	(0.6116977071277574248407752 - 1.8734458851737055262693056i),
-	(1.3649311280370181331184214 + 2.8793528632328795424123832i),
-	(2.6189310485682988308904501 - 2.9956543302898767795858704i),
-}
-var acosh = []complex128{
-	(2.9138232718554953784519807 + 1.0017679804707456328694569i),
-	(2.7358584434576260925091256 - 0.03606427612041407369636057i),
-	(2.3159537454335901187730929 - 1.6249365462333796703711823i),
-	(3.0795576791204117911123886 + 2.0485650849650740120660391i),
-	(3.0007392508200622519398814 + 0.29621132089073067282488147i),
-	(2.4872865024796011364747111 + 1.0664555914934156601503632i),
-	(2.463655912283054555225301 + 0.48681307452231387690013905i),
-	(1.8734458851737055262693056 + 0.6116977071277574248407752i),
-	(2.8793528632328795424123832 - 1.3649311280370181331184214i),
-	(2.9956543302898767795858704 + 2.6189310485682988308904501i),
-}
-var asin = []complex128{
-	(0.56902834632415098636186476 + 2.9138232718554953784519807i),
-	(1.5347320506744825455349611 - 2.7358584434576260925091256i),
-	(-0.054140219438483051139860579 - 2.3159537454335901187730929i),
-	(-0.47776875817017739283471738 + 3.0795576791204117911123886i),
-	(1.2745850059041659464064402 + 3.0007392508200622519398814i),
-	(0.50434073530148095908095852 + 2.4872865024796011364747111i),
-	(1.0839832522725827423311826 + 2.463655912283054555225301i),
-	(0.9590986196671391943905465 + 1.8734458851737055262693056i),
-	(0.20586519875787848611290031 - 2.8793528632328795424123832i),
-	(-1.0481347217734022116591284 + 2.9956543302898767795858704i),
-}
-var asinh = []complex128{
-	(2.9113760469415295679342185 + 0.99639459545704326759805893i),
-	(2.7441755423994259061579029 - 0.035468308789000500601119392i),
-	(-2.2962136462520690506126678 - 1.5144663565690151885726707i),
-	(-3.0771233459295725965402455 + 1.0895577967194013849422294i),
-	(3.0048366100923647417557027 + 0.29346979169819220036454168i),
-	(2.4800059370795363157364643 + 1.0545868606049165710424232i),
-	(2.4718773838309585611141821 + 0.47502344364250803363708842i),
-	(1.8910743588080159144378396 + 0.56882925572563602341139174i),
-	(2.8735426423367341878069406 - 1.362376149648891420997548i),
-	(-2.9981750586172477217567878 + 0.5183571985225367505624207i),
-}
-var atan = []complex128{
-	(1.5115747079332741358607654 + 0.091324403603954494382276776i),
-	(1.4424504323482602560806727 - 0.0045416132642803911503770933i),
-	(-1.5593488703630532674484026 - 0.20163295409248362456446431i),
-	(-1.5280619472445889867794105 + 0.081721556230672003746956324i),
-	(1.4759909163240799678221039 + 0.028602969320691644358773586i),
-	(1.4877353772046548932715555 + 0.14566877153207281663773599i),
-	(1.4206983927779191889826 + 0.076830486127880702249439993i),
-	(1.3162236060498933364869556 + 0.16031313000467530644933363i),
-	(1.5473450684303703578810093 - 0.11064907507939082484935782i),
-	(-1.4841462340185253987375812 + 0.049341850305024399493142411i),
-}
-var atanh = []complex128{
-	(0.058375027938968509064640438 + 1.4793488495105334458167782i),
-	(0.12977343497790381229915667 - 1.5661009410463561327262499i),
-	(-0.010576456067347252072200088 - 1.3743698658402284549750563i),
-	(-0.042218595678688358882784918 + 1.4891433968166405606692604i),
-	(0.095218997991316722061828397 + 1.5416884098777110330499698i),
-	(0.079965459366890323857556487 + 1.4252510353873192700350435i),
-	(0.15051245471980726221708301 + 1.4907432533016303804884461i),
-	(0.25082072933993987714470373 + 1.392057665392187516442986i),
-	(0.022896108815797135846276662 - 1.4609224989282864208963021i),
-	(-0.08665624101841876130537396 + 1.5207902036935093480142159i),
-}
-var conj = []complex128{
-	(4.9790119248836735e+00 - 7.7388724745781045e+00i),
-	(7.7388724745781045e+00 + 2.7688005719200159e-01i),
-	(-2.7688005719200159e-01 + 5.0106036182710749e+00i),
-	(-5.0106036182710749e+00 - 9.6362937071984173e+00i),
-	(9.6362937071984173e+00 - 2.9263772392439646e+00i),
-	(2.9263772392439646e+00 - 5.2290834314593066e+00i),
-	(5.2290834314593066e+00 - 2.7279399104360102e+00i),
-	(2.7279399104360102e+00 - 1.8253080916808550e+00i),
-	(1.8253080916808550e+00 + 8.6859247685756013e+00i),
-	(-8.6859247685756013e+00 - 4.9790119248836735e+00i),
-}
-var cos = []complex128{
-	(3.024540920601483938336569e+02 + 1.1073797572517071650045357e+03i),
-	(1.192858682649064973252758e-01 + 2.7857554122333065540970207e-01i),
-	(7.2144394304528306603857962e+01 - 2.0500129667076044169954205e+01i),
-	(2.24921952538403984190541e+03 - 7.317363745602773587049329e+03i),
-	(-9.148222970032421760015498e+00 + 1.953124661113563541862227e+00i),
-	(-9.116081175857732248227078e+01 - 1.992669213569952232487371e+01i),
-	(3.795639179042704640002918e+00 + 6.623513350981458399309662e+00i),
-	(-2.9144840732498869560679084e+00 - 1.214620271628002917638748e+00i),
-	(-7.45123482501299743872481e+02 + 2.8641692314488080814066734e+03i),
-	(-5.371977967039319076416747e+01 + 4.893348341339375830564624e+01i),
-}
-var cosh = []complex128{
-	(8.34638383523018249366948e+00 + 7.2181057886425846415112064e+01i),
-	(1.10421967379919366952251e+03 - 3.1379638689277575379469861e+02i),
-	(3.051485206773701584738512e-01 - 2.6805384730105297848044485e-01i),
-	(-7.33294728684187933370938e+01 + 1.574445942284918251038144e+01i),
-	(-7.478643293945957535757355e+03 + 1.6348382209913353929473321e+03i),
-	(4.622316522966235701630926e+00 - 8.088695185566375256093098e+00i),
-	(-8.544333183278877406197712e+01 + 3.7505836120128166455231717e+01i),
-	(-1.934457815021493925115198e+00 + 7.3725859611767228178358673e+00i),
-	(-2.352958770061749348353548e+00 - 2.034982010440878358915409e+00i),
-	(7.79756457532134748165069e+02 + 2.8549350716819176560377717e+03i),
-}
-var exp = []complex128{
-	(1.669197736864670815125146e+01 + 1.4436895109507663689174096e+02i),
-	(2.2084389286252583447276212e+03 - 6.2759289284909211238261917e+02i),
-	(2.227538273122775173434327e-01 + 7.2468284028334191250470034e-01i),
-	(-6.5182985958153548997881627e-03 - 1.39965837915193860879044e-03i),
-	(-1.4957286524084015746110777e+04 + 3.269676455931135688988042e+03i),
-	(9.218158701983105935659273e+00 - 1.6223985291084956009304582e+01i),
-	(-1.7088175716853040841444505e+02 + 7.501382609870410713795546e+01i),
-	(-3.852461315830959613132505e+00 + 1.4808420423156073221970892e+01i),
-	(-4.586775503301407379786695e+00 - 4.178501081246873415144744e+00i),
-	(4.451337963005453491095747e-05 - 1.62977574205442915935263e-04i),
-}
-var log = []complex128{
-	(2.2194438972179194425697051e+00 + 9.9909115046919291062461269e-01i),
-	(2.0468956191154167256337289e+00 - 3.5762575021856971295156489e-02i),
-	(1.6130808329853860438751244e+00 - 1.6259990074019058442232221e+00i),
-	(2.3851910394823008710032651e+00 + 2.0502936359659111755031062e+00i),
-	(2.3096442270679923004800651e+00 + 2.9483213155446756211881774e-01i),
-	(1.7904660933974656106951860e+00 + 1.0605860367252556281902109e+00i),
-	(1.7745926939841751666177512e+00 + 4.8084556083358307819310911e-01i),
-	(1.1885403350045342425648780e+00 + 5.8969634164776659423195222e-01i),
-	(2.1833107837679082586772505e+00 - 1.3636647724582455028314573e+00i),
-	(2.3037629487273259170991671e+00 + 2.6210913895386013290915234e+00i),
-}
-var log10 = []complex128{
-	(9.6389223745559042474184943e-01 + 4.338997735671419492599631e-01i),
-	(8.8895547241376579493490892e-01 - 1.5531488990643548254864806e-02i),
-	(7.0055210462945412305244578e-01 - 7.0616239649481243222248404e-01i),
-	(1.0358753067322445311676952e+00 + 8.9043121238134980156490909e-01i),
-	(1.003065742975330237172029e+00 + 1.2804396782187887479857811e-01i),
-	(7.7758954439739162532085157e-01 + 4.6060666333341810869055108e-01i),
-	(7.7069581462315327037689152e-01 + 2.0882857371769952195512475e-01i),
-	(5.1617650901191156135137239e-01 + 2.5610186717615977620363299e-01i),
-	(9.4819982567026639742663212e-01 - 5.9223208584446952284914289e-01i),
-	(1.0005115362454417135973429e+00 + 1.1383255270407412817250921e+00i),
-}
-
-type ff struct {
-	r, theta float64
-}
-
-var polar = []ff{
-	{9.2022120669932650313380972e+00, 9.9909115046919291062461269e-01},
-	{7.7438239742296106616261394e+00, -3.5762575021856971295156489e-02},
-	{5.0182478202557746902556648e+00, -1.6259990074019058442232221e+00},
-	{1.0861137372799545160704002e+01, 2.0502936359659111755031062e+00},
-	{1.0070841084922199607011905e+01, 2.9483213155446756211881774e-01},
-	{5.9922447613166942183705192e+00, 1.0605860367252556281902109e+00},
-	{5.8978784056736762299945176e+00, 4.8084556083358307819310911e-01},
-	{3.2822866700678709020367184e+00, 5.8969634164776659423195222e-01},
-	{8.8756430028990417290744307e+00, -1.3636647724582455028314573e+00},
-	{1.0011785496777731986390856e+01, 2.6210913895386013290915234e+00},
-}
-var pow = []complex128{
-	(-2.499956739197529585028819e+00 + 1.759751724335650228957144e+00i),
-	(7.357094338218116311191939e+04 - 5.089973412479151648145882e+04i),
-	(1.320777296067768517259592e+01 - 3.165621914333901498921986e+01i),
-	(-3.123287828297300934072149e-07 - 1.9849567521490553032502223E-7i),
-	(8.0622651468477229614813e+04 - 7.80028727944573092944363e+04i),
-	(-1.0268824572103165858577141e+00 - 4.716844738244989776610672e-01i),
-	(-4.35953819012244175753187e+01 + 2.2036445974645306917648585e+02i),
-	(8.3556092283250594950239e-01 - 1.2261571947167240272593282e+01i),
-	(1.582292972120769306069625e+03 + 1.273564263524278244782512e+04i),
-	(6.592208301642122149025369e-08 + 2.584887236651661903526389e-08i),
-}
-var sin = []complex128{
-	(-1.1073801774240233539648544e+03 + 3.024539773002502192425231e+02i),
-	(1.0317037521400759359744682e+00 - 3.2208979799929570242818e-02i),
-	(-2.0501952097271429804261058e+01 - 7.2137981348240798841800967e+01i),
-	(7.3173638080346338642193078e+03 + 2.249219506193664342566248e+03i),
-	(-1.964375633631808177565226e+00 - 9.0958264713870404464159683e+00i),
-	(1.992783647158514838337674e+01 - 9.11555769410191350416942e+01i),
-	(-6.680335650741921444300349e+00 + 3.763353833142432513086117e+00i),
-	(1.2794028166657459148245993e+00 - 2.7669092099795781155109602e+00i),
-	(2.8641693949535259594188879e+03 + 7.451234399649871202841615e+02i),
-	(-4.893811726244659135553033e+01 - 5.371469305562194635957655e+01i),
-}
-var sinh = []complex128{
-	(8.34559353341652565758198e+00 + 7.2187893208650790476628899e+01i),
-	(1.1042192548260646752051112e+03 - 3.1379650595631635858792056e+02i),
-	(-8.239469336509264113041849e-02 + 9.9273668758439489098514519e-01i),
-	(7.332295456982297798219401e+01 - 1.574585908122833444899023e+01i),
-	(-7.4786432301380582103534216e+03 + 1.63483823493980029604071e+03i),
-	(4.595842179016870234028347e+00 - 8.135290105518580753211484e+00i),
-	(-8.543842533574163435246793e+01 + 3.750798997857594068272375e+01i),
-	(-1.918003500809465688017307e+00 + 7.4358344619793504041350251e+00i),
-	(-2.233816733239658031433147e+00 - 2.143519070805995056229335e+00i),
-	(-7.797564130187551181105341e+02 - 2.8549352346594918614806877e+03i),
-}
-var sqrt = []complex128{
-	(2.6628203086086130543813948e+00 + 1.4531345674282185229796902e+00i),
-	(2.7823278427251986247149295e+00 - 4.9756907317005224529115567e-02i),
-	(1.5397025302089642757361015e+00 - 1.6271336573016637535695727e+00i),
-	(1.7103411581506875260277898e+00 + 2.8170677122737589676157029e+00i),
-	(3.1390392472953103383607947e+00 + 4.6612625849858653248980849e-01i),
-	(2.1117080764822417640789287e+00 + 1.2381170223514273234967850e+00i),
-	(2.3587032281672256703926939e+00 + 5.7827111903257349935720172e-01i),
-	(1.7335262588873410476661577e+00 + 5.2647258220721269141550382e-01i),
-	(2.3131094974708716531499282e+00 - 1.8775429304303785570775490e+00i),
-	(8.1420535745048086240947359e-01 + 3.0575897587277248522656113e+00i),
-}
-var tan = []complex128{
-	(-1.928757919086441129134525e-07 + 1.0000003267499169073251826e+00i),
-	(1.242412685364183792138948e+00 - 3.17149693883133370106696e+00i),
-	(-4.6745126251587795225571826e-05 - 9.9992439225263959286114298e-01i),
-	(4.792363401193648192887116e-09 + 1.0000000070589333451557723e+00i),
-	(2.345740824080089140287315e-03 + 9.947733046570988661022763e-01i),
-	(-2.396030789494815566088809e-05 + 9.9994781345418591429826779e-01i),
-	(-7.370204836644931340905303e-03 + 1.0043553413417138987717748e+00i),
-	(-3.691803847992048527007457e-02 + 9.6475071993469548066328894e-01i),
-	(-2.781955256713729368401878e-08 - 1.000000049848910609006646e+00i),
-	(9.4281590064030478879791249e-05 + 9.9999119340863718183758545e-01i),
-}
-var tanh = []complex128{
-	(1.0000921981225144748819918e+00 + 2.160986245871518020231507e-05i),
-	(9.9999967727531993209562591e-01 - 1.9953763222959658873657676e-07i),
-	(-1.765485739548037260789686e+00 + 1.7024216325552852445168471e+00i),
-	(-9.999189442732736452807108e-01 + 3.64906070494473701938098e-05i),
-	(9.9999999224622333738729767e-01 - 3.560088949517914774813046e-09i),
-	(1.0029324933367326862499343e+00 - 4.948790309797102353137528e-03i),
-	(9.9996113064788012488693567e-01 - 4.226995742097032481451259e-05i),
-	(1.0074784189316340029873945e+00 - 4.194050814891697808029407e-03i),
-	(9.9385534229718327109131502e-01 + 5.144217985914355502713437e-02i),
-	(-1.0000000491604982429364892e+00 - 2.901873195374433112227349e-08i),
-}
-
-// special cases
-var vcAbsSC = []complex128{
-	NaN(),
-}
-var absSC = []float64{
-	math.NaN(),
-}
-var vcAcosSC = []complex128{
-	NaN(),
-}
-var acosSC = []complex128{
-	NaN(),
-}
-var vcAcoshSC = []complex128{
-	NaN(),
-}
-var acoshSC = []complex128{
-	NaN(),
-}
-var vcAsinSC = []complex128{
-	NaN(),
-}
-var asinSC = []complex128{
-	NaN(),
-}
-var vcAsinhSC = []complex128{
-	NaN(),
-}
-var asinhSC = []complex128{
-	NaN(),
-}
-var vcAtanSC = []complex128{
-	NaN(),
-}
-var atanSC = []complex128{
-	NaN(),
-}
-var vcAtanhSC = []complex128{
-	NaN(),
-}
-var atanhSC = []complex128{
-	NaN(),
-}
-var vcConjSC = []complex128{
-	NaN(),
-}
-var conjSC = []complex128{
-	NaN(),
-}
-var vcCosSC = []complex128{
-	NaN(),
-}
-var cosSC = []complex128{
-	NaN(),
-}
-var vcCoshSC = []complex128{
-	NaN(),
-}
-var coshSC = []complex128{
-	NaN(),
-}
-var vcExpSC = []complex128{
-	NaN(),
-}
-var expSC = []complex128{
-	NaN(),
-}
-var vcIsNaNSC = []complex128{
-	complex(math.Inf(-1), math.Inf(-1)),
-	complex(math.Inf(-1), math.NaN()),
-	complex(math.NaN(), math.Inf(-1)),
-	complex(0, math.NaN()),
-	complex(math.NaN(), 0),
-	complex(math.Inf(1), math.Inf(1)),
-	complex(math.Inf(1), math.NaN()),
-	complex(math.NaN(), math.Inf(1)),
-	complex(math.NaN(), math.NaN()),
-}
-var isNaNSC = []bool{
-	false,
-	false,
-	false,
-	true,
-	true,
-	false,
-	false,
-	false,
-	true,
-}
-var vcLogSC = []complex128{
-	NaN(),
-}
-var logSC = []complex128{
-	NaN(),
-}
-var vcLog10SC = []complex128{
-	NaN(),
-}
-var log10SC = []complex128{
-	NaN(),
-}
-var vcPolarSC = []complex128{
-	NaN(),
-}
-var polarSC = []ff{
-	{math.NaN(), math.NaN()},
-}
-var vcPowSC = [][2]complex128{
-	{NaN(), NaN()},
-}
-var powSC = []complex128{
-	NaN(),
-}
-var vcSinSC = []complex128{
-	NaN(),
-}
-var sinSC = []complex128{
-	NaN(),
-}
-var vcSinhSC = []complex128{
-	NaN(),
-}
-var sinhSC = []complex128{
-	NaN(),
-}
-var vcSqrtSC = []complex128{
-	NaN(),
-}
-var sqrtSC = []complex128{
-	NaN(),
-}
-var vcTanSC = []complex128{
-	NaN(),
-}
-var tanSC = []complex128{
-	NaN(),
-}
-var vcTanhSC = []complex128{
-	NaN(),
-}
-var tanhSC = []complex128{
-	NaN(),
-}
-
-// functions borrowed from pkg/math/all_test.go
-func tolerance(a, b, e float64) bool {
-	d := a - b
-	if d < 0 {
-		d = -d
-	}
-
-	if a != 0 {
-		e = e * a
-		if e < 0 {
-			e = -e
-		}
-	}
-	return d < e
-}
-func soclose(a, b, e float64) bool { return tolerance(a, b, e) }
-func veryclose(a, b float64) bool  { return tolerance(a, b, 4e-16) }
-func alike(a, b float64) bool {
-	switch {
-	case a != a && b != b: // math.IsNaN(a) && math.IsNaN(b):
-		return true
-	case a == b:
-		return math.Signbit(a) == math.Signbit(b)
-	}
-	return false
-}
-
-func cTolerance(a, b complex128, e float64) bool {
-	d := Abs(a - b)
-	if a != 0 {
-		e = e * Abs(a)
-		if e < 0 {
-			e = -e
-		}
-	}
-	return d < e
-}
-func cSoclose(a, b complex128, e float64) bool { return cTolerance(a, b, e) }
-func cVeryclose(a, b complex128) bool          { return cTolerance(a, b, 4e-16) }
-func cAlike(a, b complex128) bool {
-	switch {
-	case IsNaN(a) && IsNaN(b):
-		return true
-	case a == b:
-		return math.Signbit(real(a)) == math.Signbit(real(b)) && math.Signbit(imag(a)) == math.Signbit(imag(b))
-	}
-	return false
-}
-
-func TestAbs(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Abs(vc[i]); !veryclose(abs[i], f) {
-			t.Errorf("Abs(%g) = %g, want %g", vc[i], f, abs[i])
-		}
-	}
-	for i := 0; i < len(vcAbsSC); i++ {
-		if f := Abs(vcAbsSC[i]); !alike(absSC[i], f) {
-			t.Errorf("Abs(%g) = %g, want %g", vcAbsSC[i], f, absSC[i])
-		}
-	}
-}
-func TestAcos(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Acos(vc[i]); !cSoclose(acos[i], f, 1e-14) {
-			t.Errorf("Acos(%g) = %g, want %g", vc[i], f, acos[i])
-		}
-	}
-	for i := 0; i < len(vcAcosSC); i++ {
-		if f := Acos(vcAcosSC[i]); !cAlike(acosSC[i], f) {
-			t.Errorf("Acos(%g) = %g, want %g", vcAcosSC[i], f, acosSC[i])
-		}
-	}
-}
-func TestAcosh(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Acosh(vc[i]); !cSoclose(acosh[i], f, 1e-14) {
-			t.Errorf("Acosh(%g) = %g, want %g", vc[i], f, acosh[i])
-		}
-	}
-	for i := 0; i < len(vcAcoshSC); i++ {
-		if f := Acosh(vcAcoshSC[i]); !cAlike(acoshSC[i], f) {
-			t.Errorf("Acosh(%g) = %g, want %g", vcAcoshSC[i], f, acoshSC[i])
-		}
-	}
-}
-func TestAsin(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Asin(vc[i]); !cSoclose(asin[i], f, 1e-14) {
-			t.Errorf("Asin(%g) = %g, want %g", vc[i], f, asin[i])
-		}
-	}
-	for i := 0; i < len(vcAsinSC); i++ {
-		if f := Asin(vcAsinSC[i]); !cAlike(asinSC[i], f) {
-			t.Errorf("Asin(%g) = %g, want %g", vcAsinSC[i], f, asinSC[i])
-		}
-	}
-}
-func TestAsinh(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Asinh(vc[i]); !cSoclose(asinh[i], f, 4e-15) {
-			t.Errorf("Asinh(%g) = %g, want %g", vc[i], f, asinh[i])
-		}
-	}
-	for i := 0; i < len(vcAsinhSC); i++ {
-		if f := Asinh(vcAsinhSC[i]); !cAlike(asinhSC[i], f) {
-			t.Errorf("Asinh(%g) = %g, want %g", vcAsinhSC[i], f, asinhSC[i])
-		}
-	}
-}
-func TestAtan(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Atan(vc[i]); !cVeryclose(atan[i], f) {
-			t.Errorf("Atan(%g) = %g, want %g", vc[i], f, atan[i])
-		}
-	}
-	for i := 0; i < len(vcAtanSC); i++ {
-		if f := Atan(vcAtanSC[i]); !cAlike(atanSC[i], f) {
-			t.Errorf("Atan(%g) = %g, want %g", vcAtanSC[i], f, atanSC[i])
-		}
-	}
-}
-func TestAtanh(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Atanh(vc[i]); !cVeryclose(atanh[i], f) {
-			t.Errorf("Atanh(%g) = %g, want %g", vc[i], f, atanh[i])
-		}
-	}
-	for i := 0; i < len(vcAtanhSC); i++ {
-		if f := Atanh(vcAtanhSC[i]); !cAlike(atanhSC[i], f) {
-			t.Errorf("Atanh(%g) = %g, want %g", vcAtanhSC[i], f, atanhSC[i])
-		}
-	}
-}
-func TestConj(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Conj(vc[i]); !cVeryclose(conj[i], f) {
-			t.Errorf("Conj(%g) = %g, want %g", vc[i], f, conj[i])
-		}
-	}
-	for i := 0; i < len(vcConjSC); i++ {
-		if f := Conj(vcConjSC[i]); !cAlike(conjSC[i], f) {
-			t.Errorf("Conj(%g) = %g, want %g", vcConjSC[i], f, conjSC[i])
-		}
-	}
-}
-func TestCos(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Cos(vc[i]); !cSoclose(cos[i], f, 3e-15) {
-			t.Errorf("Cos(%g) = %g, want %g", vc[i], f, cos[i])
-		}
-	}
-	for i := 0; i < len(vcCosSC); i++ {
-		if f := Cos(vcCosSC[i]); !cAlike(cosSC[i], f) {
-			t.Errorf("Cos(%g) = %g, want %g", vcCosSC[i], f, cosSC[i])
-		}
-	}
-}
-func TestCosh(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Cosh(vc[i]); !cSoclose(cosh[i], f, 2e-15) {
-			t.Errorf("Cosh(%g) = %g, want %g", vc[i], f, cosh[i])
-		}
-	}
-	for i := 0; i < len(vcCoshSC); i++ {
-		if f := Cosh(vcCoshSC[i]); !cAlike(coshSC[i], f) {
-			t.Errorf("Cosh(%g) = %g, want %g", vcCoshSC[i], f, coshSC[i])
-		}
-	}
-}
-func TestExp(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Exp(vc[i]); !cSoclose(exp[i], f, 1e-15) {
-			t.Errorf("Exp(%g) = %g, want %g", vc[i], f, exp[i])
-		}
-	}
-	for i := 0; i < len(vcExpSC); i++ {
-		if f := Exp(vcExpSC[i]); !cAlike(expSC[i], f) {
-			t.Errorf("Exp(%g) = %g, want %g", vcExpSC[i], f, expSC[i])
-		}
-	}
-}
-func TestIsNaN(t *testing.T) {
-	for i := 0; i < len(vcIsNaNSC); i++ {
-		if f := IsNaN(vcIsNaNSC[i]); isNaNSC[i] != f {
-			t.Errorf("IsNaN(%v) = %v, want %v", vcIsNaNSC[i], f, isNaNSC[i])
-		}
-	}
-}
-func TestLog(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Log(vc[i]); !cVeryclose(log[i], f) {
-			t.Errorf("Log(%g) = %g, want %g", vc[i], f, log[i])
-		}
-	}
-	for i := 0; i < len(vcLogSC); i++ {
-		if f := Log(vcLogSC[i]); !cAlike(logSC[i], f) {
-			t.Errorf("Log(%g) = %g, want %g", vcLogSC[i], f, logSC[i])
-		}
-	}
-}
-func TestLog10(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Log10(vc[i]); !cVeryclose(log10[i], f) {
-			t.Errorf("Log10(%g) = %g, want %g", vc[i], f, log10[i])
-		}
-	}
-	for i := 0; i < len(vcLog10SC); i++ {
-		if f := Log10(vcLog10SC[i]); !cAlike(log10SC[i], f) {
-			t.Errorf("Log10(%g) = %g, want %g", vcLog10SC[i], f, log10SC[i])
-		}
-	}
-}
-func TestPolar(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if r, theta := Polar(vc[i]); !veryclose(polar[i].r, r) && !veryclose(polar[i].theta, theta) {
-			t.Errorf("Polar(%g) = %g, %g want %g, %g", vc[i], r, theta, polar[i].r, polar[i].theta)
-		}
-	}
-	for i := 0; i < len(vcPolarSC); i++ {
-		if r, theta := Polar(vcPolarSC[i]); !alike(polarSC[i].r, r) && !alike(polarSC[i].theta, theta) {
-			t.Errorf("Polar(%g) = %g, %g, want %g, %g", vcPolarSC[i], r, theta, polarSC[i].r, polarSC[i].theta)
-		}
-	}
-}
-func TestPow(t *testing.T) {
-	var a = complex(3.0, 3.0)
-	for i := 0; i < len(vc); i++ {
-		if f := Pow(a, vc[i]); !cSoclose(pow[i], f, 4e-15) {
-			t.Errorf("Pow(%g, %g) = %g, want %g", a, vc[i], f, pow[i])
-		}
-	}
-	for i := 0; i < len(vcPowSC); i++ {
-		if f := Pow(vcPowSC[i][0], vcPowSC[i][0]); !cAlike(powSC[i], f) {
-			t.Errorf("Pow(%g, %g) = %g, want %g", vcPowSC[i][0], vcPowSC[i][0], f, powSC[i])
-		}
-	}
-}
-func TestRect(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Rect(polar[i].r, polar[i].theta); !cVeryclose(vc[i], f) {
-			t.Errorf("Rect(%g, %g) = %g want %g", polar[i].r, polar[i].theta, f, vc[i])
-		}
-	}
-	for i := 0; i < len(vcPolarSC); i++ {
-		if f := Rect(polarSC[i].r, polarSC[i].theta); !cAlike(vcPolarSC[i], f) {
-			t.Errorf("Rect(%g, %g) = %g, want %g", polarSC[i].r, polarSC[i].theta, f, vcPolarSC[i])
-		}
-	}
-}
-func TestSin(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Sin(vc[i]); !cSoclose(sin[i], f, 2e-15) {
-			t.Errorf("Sin(%g) = %g, want %g", vc[i], f, sin[i])
-		}
-	}
-	for i := 0; i < len(vcSinSC); i++ {
-		if f := Sin(vcSinSC[i]); !cAlike(sinSC[i], f) {
-			t.Errorf("Sin(%g) = %g, want %g", vcSinSC[i], f, sinSC[i])
-		}
-	}
-}
-func TestSinh(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Sinh(vc[i]); !cSoclose(sinh[i], f, 2e-15) {
-			t.Errorf("Sinh(%g) = %g, want %g", vc[i], f, sinh[i])
-		}
-	}
-	for i := 0; i < len(vcSinhSC); i++ {
-		if f := Sinh(vcSinhSC[i]); !cAlike(sinhSC[i], f) {
-			t.Errorf("Sinh(%g) = %g, want %g", vcSinhSC[i], f, sinhSC[i])
-		}
-	}
-}
-func TestSqrt(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Sqrt(vc[i]); !cVeryclose(sqrt[i], f) {
-			t.Errorf("Sqrt(%g) = %g, want %g", vc[i], f, sqrt[i])
-		}
-	}
-	for i := 0; i < len(vcSqrtSC); i++ {
-		if f := Sqrt(vcSqrtSC[i]); !cAlike(sqrtSC[i], f) {
-			t.Errorf("Sqrt(%g) = %g, want %g", vcSqrtSC[i], f, sqrtSC[i])
-		}
-	}
-}
-func TestTan(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Tan(vc[i]); !cSoclose(tan[i], f, 3e-15) {
-			t.Errorf("Tan(%g) = %g, want %g", vc[i], f, tan[i])
-		}
-	}
-	for i := 0; i < len(vcTanSC); i++ {
-		if f := Tan(vcTanSC[i]); !cAlike(tanSC[i], f) {
-			t.Errorf("Tan(%g) = %g, want %g", vcTanSC[i], f, tanSC[i])
-		}
-	}
-}
-func TestTanh(t *testing.T) {
-	for i := 0; i < len(vc); i++ {
-		if f := Tanh(vc[i]); !cSoclose(tanh[i], f, 2e-15) {
-			t.Errorf("Tanh(%g) = %g, want %g", vc[i], f, tanh[i])
-		}
-	}
-	for i := 0; i < len(vcTanhSC); i++ {
-		if f := Tanh(vcTanhSC[i]); !cAlike(tanhSC[i], f) {
-			t.Errorf("Tanh(%g) = %g, want %g", vcTanhSC[i], f, tanhSC[i])
-		}
-	}
-}
-
-func BenchmarkAbs(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Abs(complex(2.5, 3.5))
-	}
-}
-func BenchmarkAcos(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Acos(complex(2.5, 3.5))
-	}
-}
-func BenchmarkAcosh(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Acosh(complex(2.5, 3.5))
-	}
-}
-func BenchmarkAsin(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Asin(complex(2.5, 3.5))
-	}
-}
-func BenchmarkAsinh(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Asinh(complex(2.5, 3.5))
-	}
-}
-func BenchmarkAtan(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Atan(complex(2.5, 3.5))
-	}
-}
-func BenchmarkAtanh(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Atanh(complex(2.5, 3.5))
-	}
-}
-func BenchmarkConj(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Conj(complex(2.5, 3.5))
-	}
-}
-func BenchmarkCos(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Cos(complex(2.5, 3.5))
-	}
-}
-func BenchmarkCosh(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Cosh(complex(2.5, 3.5))
-	}
-}
-func BenchmarkExp(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Exp(complex(2.5, 3.5))
-	}
-}
-func BenchmarkLog(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Log(complex(2.5, 3.5))
-	}
-}
-func BenchmarkLog10(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Log10(complex(2.5, 3.5))
-	}
-}
-func BenchmarkPhase(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Phase(complex(2.5, 3.5))
-	}
-}
-func BenchmarkPolar(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Polar(complex(2.5, 3.5))
-	}
-}
-func BenchmarkPow(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Pow(complex(2.5, 3.5), complex(2.5, 3.5))
-	}
-}
-func BenchmarkRect(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Rect(2.5, 1.5)
-	}
-}
-func BenchmarkSin(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Sin(complex(2.5, 3.5))
-	}
-}
-func BenchmarkSinh(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Sinh(complex(2.5, 3.5))
-	}
-}
-func BenchmarkSqrt(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Sqrt(complex(2.5, 3.5))
-	}
-}
-func BenchmarkTan(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Tan(complex(2.5, 3.5))
-	}
-}
-func BenchmarkTanh(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Tanh(complex(2.5, 3.5))
-	}
-}
diff --git a/src/pkg/cmath/conj.go b/src/pkg/cmath/conj.go
deleted file mode 100644
index 776b57d..0000000
--- a/src/pkg/cmath/conj.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2010 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 cmath
-
-// Conj returns the complex conjugate of x.
-func Conj(x complex128) complex128 { return complex(real(x), -imag(x)) }
diff --git a/src/pkg/cmath/exp.go b/src/pkg/cmath/exp.go
deleted file mode 100644
index 64c1ef4..0000000
--- a/src/pkg/cmath/exp.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// The original C code, the long comment, and the constants
-// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
-// The go code is a simplified version of the original C.
-//
-// Cephes Math Library Release 2.8:  June, 2000
-// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
-//
-// The readme file at http://netlib.sandia.gov/cephes/ says:
-//    Some software in this archive may be from the book _Methods and
-// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
-// International, 1989) or from the Cephes Mathematical Library, a
-// commercial product. In either event, it is copyrighted by the author.
-// What you see here may be used freely but it comes with no support or
-// guarantee.
-//
-//   The two known misprints in the book are repaired here in the
-// source listings for the gamma function and the incomplete beta
-// integral.
-//
-//   Stephen L. Moshier
-//   moshier at na-net.ornl.gov
-
-// Complex exponential function
-//
-// DESCRIPTION:
-//
-// Returns the complex exponential of the complex argument z.
-//
-// If
-//     z = x + iy,
-//     r = exp(x),
-// then
-//     w = r cos y + i r sin y.
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10      8700       3.7e-17     1.1e-17
-//    IEEE      -10,+10     30000       3.0e-16     8.7e-17
-
-// Exp returns e**x, the base-e exponential of x.
-func Exp(x complex128) complex128 {
-	r := math.Exp(real(x))
-	s, c := math.Sincos(imag(x))
-	return complex(r*c, r*s)
-}
diff --git a/src/pkg/cmath/isinf.go b/src/pkg/cmath/isinf.go
deleted file mode 100644
index f23d2de..0000000
--- a/src/pkg/cmath/isinf.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// IsInf returns true if either real(x) or imag(x) is an infinity.
-func IsInf(x complex128) bool {
-	if math.IsInf(real(x), 0) || math.IsInf(imag(x), 0) {
-		return true
-	}
-	return false
-}
-
-// Inf returns a complex infinity, complex(+Inf, +Inf).
-func Inf() complex128 {
-	inf := math.Inf(1)
-	return complex(inf, inf)
-}
diff --git a/src/pkg/cmath/isnan.go b/src/pkg/cmath/isnan.go
deleted file mode 100644
index 2063bb8..0000000
--- a/src/pkg/cmath/isnan.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// IsNaN returns true if either real(x) or imag(x) is NaN
-// and neither is an infinity.
-func IsNaN(x complex128) bool {
-	switch {
-	case math.IsInf(real(x), 0) || math.IsInf(imag(x), 0):
-		return false
-	case math.IsNaN(real(x)) || math.IsNaN(imag(x)):
-		return true
-	}
-	return false
-}
-
-// NaN returns a complex ``not-a-number'' value.
-func NaN() complex128 {
-	nan := math.NaN()
-	return complex(nan, nan)
-}
diff --git a/src/pkg/cmath/log.go b/src/pkg/cmath/log.go
deleted file mode 100644
index 8e6964f..0000000
--- a/src/pkg/cmath/log.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// The original C code, the long comment, and the constants
-// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
-// The go code is a simplified version of the original C.
-//
-// Cephes Math Library Release 2.8:  June, 2000
-// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
-//
-// The readme file at http://netlib.sandia.gov/cephes/ says:
-//    Some software in this archive may be from the book _Methods and
-// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
-// International, 1989) or from the Cephes Mathematical Library, a
-// commercial product. In either event, it is copyrighted by the author.
-// What you see here may be used freely but it comes with no support or
-// guarantee.
-//
-//   The two known misprints in the book are repaired here in the
-// source listings for the gamma function and the incomplete beta
-// integral.
-//
-//   Stephen L. Moshier
-//   moshier at na-net.ornl.gov
-
-// Complex natural logarithm
-//
-// DESCRIPTION:
-//
-// Returns complex logarithm to the base e (2.718...) of
-// the complex argument z.
-//
-// If
-//       z = x + iy, r = sqrt( x**2 + y**2 ),
-// then
-//       w = log(r) + i arctan(y/x).
-//
-// The arctangent ranges from -PI to +PI.
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10      7000       8.5e-17     1.9e-17
-//    IEEE      -10,+10     30000       5.0e-15     1.1e-16
-//
-// Larger relative error can be observed for z near 1 +i0.
-// In IEEE arithmetic the peak absolute error is 5.2e-16, rms
-// absolute error 1.0e-16.
-
-// Log returns the natural logarithm of x.
-func Log(x complex128) complex128 {
-	return complex(math.Log(Abs(x)), Phase(x))
-}
-
-// Log10 returns the decimal logarithm of x.
-func Log10(x complex128) complex128 {
-	return math.Log10E * Log(x)
-}
diff --git a/src/pkg/cmath/phase.go b/src/pkg/cmath/phase.go
deleted file mode 100644
index 2d67aa3..0000000
--- a/src/pkg/cmath/phase.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// Phase returns the phase (also called the argument) of x.
-// The returned value is in the range [-Pi, Pi].
-func Phase(x complex128) float64 { return math.Atan2(imag(x), real(x)) }
diff --git a/src/pkg/cmath/polar.go b/src/pkg/cmath/polar.go
deleted file mode 100644
index 033676a..0000000
--- a/src/pkg/cmath/polar.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2010 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 cmath
-
-// Polar returns the absolute value r and phase θ of x,
-// such that x = r * e**θi.
-// The phase is in the range [-Pi, Pi].
-func Polar(x complex128) (r, θ float64) {
-	return Abs(x), Phase(x)
-}
diff --git a/src/pkg/cmath/pow.go b/src/pkg/cmath/pow.go
deleted file mode 100644
index 68e1207..0000000
--- a/src/pkg/cmath/pow.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// The original C code, the long comment, and the constants
-// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
-// The go code is a simplified version of the original C.
-//
-// Cephes Math Library Release 2.8:  June, 2000
-// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
-//
-// The readme file at http://netlib.sandia.gov/cephes/ says:
-//    Some software in this archive may be from the book _Methods and
-// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
-// International, 1989) or from the Cephes Mathematical Library, a
-// commercial product. In either event, it is copyrighted by the author.
-// What you see here may be used freely but it comes with no support or
-// guarantee.
-//
-//   The two known misprints in the book are repaired here in the
-// source listings for the gamma function and the incomplete beta
-// integral.
-//
-//   Stephen L. Moshier
-//   moshier at na-net.ornl.gov
-
-// Complex power function
-//
-// DESCRIPTION:
-//
-// Raises complex A to the complex Zth power.
-// Definition is per AMS55 # 4.2.8,
-// analytically equivalent to cpow(a,z) = cexp(z clog(a)).
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    IEEE      -10,+10     30000       9.4e-15     1.5e-15
-
-// Pow returns x**y, the base-x exponential of y.
-func Pow(x, y complex128) complex128 {
-	modulus := Abs(x)
-	if modulus == 0 {
-		return complex(0, 0)
-	}
-	r := math.Pow(modulus, real(y))
-	arg := Phase(x)
-	theta := real(y) * arg
-	if imag(y) != 0 {
-		r *= math.Exp(-imag(y) * arg)
-		theta += imag(y) * math.Log(modulus)
-	}
-	s, c := math.Sincos(theta)
-	return complex(r*c, r*s)
-}
diff --git a/src/pkg/cmath/rect.go b/src/pkg/cmath/rect.go
deleted file mode 100644
index b955f0b..0000000
--- a/src/pkg/cmath/rect.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// Rect returns the complex number x with polar coordinates r, θ.
-func Rect(r, θ float64) complex128 {
-	s, c := math.Sincos(θ)
-	return complex(r*c, r*s)
-}
diff --git a/src/pkg/cmath/sin.go b/src/pkg/cmath/sin.go
deleted file mode 100644
index 8900ecd..0000000
--- a/src/pkg/cmath/sin.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// The original C code, the long comment, and the constants
-// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
-// The go code is a simplified version of the original C.
-//
-// Cephes Math Library Release 2.8:  June, 2000
-// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
-//
-// The readme file at http://netlib.sandia.gov/cephes/ says:
-//    Some software in this archive may be from the book _Methods and
-// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
-// International, 1989) or from the Cephes Mathematical Library, a
-// commercial product. In either event, it is copyrighted by the author.
-// What you see here may be used freely but it comes with no support or
-// guarantee.
-//
-//   The two known misprints in the book are repaired here in the
-// source listings for the gamma function and the incomplete beta
-// integral.
-//
-//   Stephen L. Moshier
-//   moshier at na-net.ornl.gov
-
-// Complex circular sine
-//
-// DESCRIPTION:
-//
-// If
-//     z = x + iy,
-//
-// then
-//
-//     w = sin x  cosh y  +  i cos x sinh y.
-//
-// csin(z) = -i csinh(iz).
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10      8400       5.3e-17     1.3e-17
-//    IEEE      -10,+10     30000       3.8e-16     1.0e-16
-// Also tested by csin(casin(z)) = z.
-
-// Sin returns the sine of x.
-func Sin(x complex128) complex128 {
-	s, c := math.Sincos(real(x))
-	sh, ch := sinhcosh(imag(x))
-	return complex(s*ch, c*sh)
-}
-
-// Complex hyperbolic sine
-//
-// DESCRIPTION:
-//
-// csinh z = (cexp(z) - cexp(-z))/2
-//         = sinh x * cos y  +  i cosh x * sin y .
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    IEEE      -10,+10     30000       3.1e-16     8.2e-17
-
-// Sinh returns the hyperbolic sine of x.
-func Sinh(x complex128) complex128 {
-	s, c := math.Sincos(imag(x))
-	sh, ch := sinhcosh(real(x))
-	return complex(c*sh, s*ch)
-}
-
-// Complex circular cosine
-//
-// DESCRIPTION:
-//
-// If
-//     z = x + iy,
-//
-// then
-//
-//     w = cos x  cosh y  -  i sin x sinh y.
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10      8400       4.5e-17     1.3e-17
-//    IEEE      -10,+10     30000       3.8e-16     1.0e-16
-
-// Cos returns the cosine of x.
-func Cos(x complex128) complex128 {
-	s, c := math.Sincos(real(x))
-	sh, ch := sinhcosh(imag(x))
-	return complex(c*ch, -s*sh)
-}
-
-// Complex hyperbolic cosine
-//
-// DESCRIPTION:
-//
-// ccosh(z) = cosh x  cos y + i sinh x sin y .
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    IEEE      -10,+10     30000       2.9e-16     8.1e-17
-
-// Cosh returns the hyperbolic cosine of x.
-func Cosh(x complex128) complex128 {
-	s, c := math.Sincos(imag(x))
-	sh, ch := sinhcosh(real(x))
-	return complex(c*ch, s*sh)
-}
-
-// calculate sinh and cosh
-func sinhcosh(x float64) (sh, ch float64) {
-	if math.Fabs(x) <= 0.5 {
-		return math.Sinh(x), math.Cosh(x)
-	}
-	e := math.Exp(x)
-	ei := 0.5 / e
-	e *= 0.5
-	return e - ei, e + ei
-}
diff --git a/src/pkg/cmath/sqrt.go b/src/pkg/cmath/sqrt.go
deleted file mode 100644
index e77a9b9..0000000
--- a/src/pkg/cmath/sqrt.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// The original C code, the long comment, and the constants
-// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
-// The go code is a simplified version of the original C.
-//
-// Cephes Math Library Release 2.8:  June, 2000
-// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
-//
-// The readme file at http://netlib.sandia.gov/cephes/ says:
-//    Some software in this archive may be from the book _Methods and
-// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
-// International, 1989) or from the Cephes Mathematical Library, a
-// commercial product. In either event, it is copyrighted by the author.
-// What you see here may be used freely but it comes with no support or
-// guarantee.
-//
-//   The two known misprints in the book are repaired here in the
-// source listings for the gamma function and the incomplete beta
-// integral.
-//
-//   Stephen L. Moshier
-//   moshier at na-net.ornl.gov
-
-// Complex square root
-//
-// DESCRIPTION:
-//
-// If z = x + iy,  r = |z|, then
-//
-//                       1/2
-// Re w  =  [ (r + x)/2 ]   ,
-//
-//                       1/2
-// Im w  =  [ (r - x)/2 ]   .
-//
-// Cancellation error in r-x or r+x is avoided by using the
-// identity  2 Re w Im w  =  y.
-//
-// Note that -w is also a square root of z.  The root chosen
-// is always in the right half plane and Im w has the same sign as y.
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10     25000       3.2e-17     9.6e-18
-//    IEEE      -10,+10   1,000,000     2.9e-16     6.1e-17
-
-// Sqrt returns the square root of x.
-func Sqrt(x complex128) complex128 {
-	if imag(x) == 0 {
-		if real(x) == 0 {
-			return complex(0, 0)
-		}
-		if real(x) < 0 {
-			return complex(0, math.Sqrt(-real(x)))
-		}
-		return complex(math.Sqrt(real(x)), 0)
-	}
-	if real(x) == 0 {
-		if imag(x) < 0 {
-			r := math.Sqrt(-0.5 * imag(x))
-			return complex(r, -r)
-		}
-		r := math.Sqrt(0.5 * imag(x))
-		return complex(r, r)
-	}
-	a := real(x)
-	b := imag(x)
-	var scale float64
-	// Rescale to avoid internal overflow or underflow.
-	if math.Fabs(a) > 4 || math.Fabs(b) > 4 {
-		a *= 0.25
-		b *= 0.25
-		scale = 2
-	} else {
-		a *= 1.8014398509481984e16 // 2**54
-		b *= 1.8014398509481984e16
-		scale = 7.450580596923828125e-9 // 2**-27
-	}
-	r := math.Hypot(a, b)
-	var t float64
-	if a > 0 {
-		t = math.Sqrt(0.5*r + 0.5*a)
-		r = scale * math.Fabs((0.5*b)/t)
-		t *= scale
-	} else {
-		r = math.Sqrt(0.5*r - 0.5*a)
-		t = scale * math.Fabs((0.5*b)/r)
-		r *= scale
-	}
-	if b < 0 {
-		return complex(t, -r)
-	}
-	return complex(t, r)
-}
diff --git a/src/pkg/cmath/tan.go b/src/pkg/cmath/tan.go
deleted file mode 100644
index 94b5175..0000000
--- a/src/pkg/cmath/tan.go
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright 2010 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 cmath
-
-import "math"
-
-// The original C code, the long comment, and the constants
-// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
-// The go code is a simplified version of the original C.
-//
-// Cephes Math Library Release 2.8:  June, 2000
-// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
-//
-// The readme file at http://netlib.sandia.gov/cephes/ says:
-//    Some software in this archive may be from the book _Methods and
-// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
-// International, 1989) or from the Cephes Mathematical Library, a
-// commercial product. In either event, it is copyrighted by the author.
-// What you see here may be used freely but it comes with no support or
-// guarantee.
-//
-//   The two known misprints in the book are repaired here in the
-// source listings for the gamma function and the incomplete beta
-// integral.
-//
-//   Stephen L. Moshier
-//   moshier at na-net.ornl.gov
-
-// Complex circular tangent
-//
-// DESCRIPTION:
-//
-// If
-//     z = x + iy,
-//
-// then
-//
-//           sin 2x  +  i sinh 2y
-//     w  =  --------------------.
-//            cos 2x  +  cosh 2y
-//
-// On the real axis the denominator is zero at odd multiples
-// of PI/2.  The denominator is evaluated by its Taylor
-// series near these points.
-//
-// ctan(z) = -i ctanh(iz).
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10      5200       7.1e-17     1.6e-17
-//    IEEE      -10,+10     30000       7.2e-16     1.2e-16
-// Also tested by ctan * ccot = 1 and catan(ctan(z))  =  z.
-
-// Tan returns the tangent of x.
-func Tan(x complex128) complex128 {
-	d := math.Cos(2*real(x)) + math.Cosh(2*imag(x))
-	if math.Fabs(d) < 0.25 {
-		d = tanSeries(x)
-	}
-	if d == 0 {
-		return Inf()
-	}
-	return complex(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d)
-}
-
-// Complex hyperbolic tangent
-//
-// DESCRIPTION:
-//
-// tanh z = (sinh 2x  +  i sin 2y) / (cosh 2x + cos 2y) .
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    IEEE      -10,+10     30000       1.7e-14     2.4e-16
-
-// Tanh returns the hyperbolic tangent of x.
-func Tanh(x complex128) complex128 {
-	d := math.Cosh(2*real(x)) + math.Cos(2*imag(x))
-	if d == 0 {
-		return Inf()
-	}
-	return complex(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d)
-}
-
-// Program to subtract nearest integer multiple of PI
-func reducePi(x float64) float64 {
-	const (
-		// extended precision value of PI:
-		DP1 = 3.14159265160560607910E0   // ?? 0x400921fb54000000
-		DP2 = 1.98418714791870343106E-9  // ?? 0x3e210b4610000000
-		DP3 = 1.14423774522196636802E-17 // ?? 0x3c6a62633145c06e
-	)
-	t := x / math.Pi
-	if t >= 0 {
-		t += 0.5
-	} else {
-		t -= 0.5
-	}
-	t = float64(int64(t)) // int64(t) = the multiple
-	return ((x - t*DP1) - t*DP2) - t*DP3
-}
-
-// Taylor series expansion for cosh(2y) - cos(2x)
-func tanSeries(z complex128) float64 {
-	const MACHEP = 1.0 / (1 << 53)
-	x := math.Fabs(2 * real(z))
-	y := math.Fabs(2 * imag(z))
-	x = reducePi(x)
-	x = x * x
-	y = y * y
-	x2 := 1.0
-	y2 := 1.0
-	f := 1.0
-	rn := 0.0
-	d := 0.0
-	for {
-		rn += 1
-		f *= rn
-		rn += 1
-		f *= rn
-		x2 *= x
-		y2 *= y
-		t := y2 + x2
-		t /= f
-		d += t
-
-		rn += 1
-		f *= rn
-		rn += 1
-		f *= rn
-		x2 *= x
-		y2 *= y
-		t = y2 - x2
-		t /= f
-		d += t
-		if math.Fabs(t/d) <= MACHEP {
-			break
-		}
-	}
-	return d
-}
-
-// Complex circular cotangent
-//
-// DESCRIPTION:
-//
-// If
-//     z = x + iy,
-//
-// then
-//
-//           sin 2x  -  i sinh 2y
-//     w  =  --------------------.
-//            cosh 2y  -  cos 2x
-//
-// On the real axis, the denominator has zeros at even
-// multiples of PI/2.  Near these points it is evaluated
-// by a Taylor series.
-//
-// ACCURACY:
-//
-//                      Relative error:
-// arithmetic   domain     # trials      peak         rms
-//    DEC       -10,+10      3000       6.5e-17     1.6e-17
-//    IEEE      -10,+10     30000       9.2e-16     1.2e-16
-// Also tested by ctan * ccot = 1 + i0.
-
-// Cot returns the cotangent of x.
-func Cot(x complex128) complex128 {
-	d := math.Cosh(2*imag(x)) - math.Cos(2*real(x))
-	if math.Fabs(d) < 0.25 {
-		d = tanSeries(x)
-	}
-	if d == 0 {
-		return Inf()
-	}
-	return complex(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d)
-}
diff --git a/src/pkg/compress/bzip2/bit_reader.go b/src/pkg/compress/bzip2/bit_reader.go
index 50f0ec8..b35c69a 100644
--- a/src/pkg/compress/bzip2/bit_reader.go
+++ b/src/pkg/compress/bzip2/bit_reader.go
@@ -7,25 +7,24 @@ package bzip2
 import (
 	"bufio"
 	"io"
-	"os"
 )
 
 // bitReader wraps an io.Reader and provides the ability to read values,
-// bit-by-bit, from it. Its Read* methods don't return the usual os.Error
+// bit-by-bit, from it. Its Read* methods don't return the usual error
 // because the error handling was verbose. Instead, any error is kept and can
 // be checked afterwards.
 type bitReader struct {
 	r    byteReader
 	n    uint64
 	bits uint
-	err  os.Error
+	err  error
 }
 
-// bitReader needs to read bytes from an io.Reader. We attempt to cast the
+// bitReader needs to read bytes from an io.Reader. We attempt to convert the
 // given io.Reader to this interface and, if it doesn't already fit, we wrap in
 // a bufio.Reader.
 type byteReader interface {
-	ReadByte() (byte, os.Error)
+	ReadByte() (byte, error)
 }
 
 func newBitReader(r io.Reader) bitReader {
@@ -38,11 +37,11 @@ func newBitReader(r io.Reader) bitReader {
 
 // ReadBits64 reads the given number of bits and returns them in the
 // least-significant part of a uint64. In the event of an error, it returns 0
-// and the error can be obtained by calling Error().
+// and the error can be obtained by calling Err().
 func (br *bitReader) ReadBits64(bits uint) (n uint64) {
 	for bits > br.bits {
 		b, err := br.r.ReadByte()
-		if err == os.EOF {
+		if err == io.EOF {
 			err = io.ErrUnexpectedEOF
 		}
 		if err != nil {
@@ -83,6 +82,6 @@ func (br *bitReader) ReadBit() bool {
 	return n != 0
 }
 
-func (br *bitReader) Error() os.Error {
+func (br *bitReader) Err() error {
 	return br.err
 }
diff --git a/src/pkg/compress/bzip2/bzip2.go b/src/pkg/compress/bzip2/bzip2.go
index 8b45723..3dc8c62 100644
--- a/src/pkg/compress/bzip2/bzip2.go
+++ b/src/pkg/compress/bzip2/bzip2.go
@@ -5,10 +5,7 @@
 // Package bzip2 implements bzip2 decompression.
 package bzip2
 
-import (
-	"io"
-	"os"
-)
+import "io"
 
 // There's no RFC for bzip2. I used the Wikipedia page for reference and a lot
 // of guessing: http://en.wikipedia.org/wiki/Bzip2
@@ -19,7 +16,7 @@ import (
 // syntactically invalid.
 type StructuralError string
 
-func (s StructuralError) String() string {
+func (s StructuralError) Error() string {
 	return "bzip2 data invalid: " + string(s)
 }
 
@@ -53,7 +50,7 @@ const bzip2BlockMagic = 0x314159265359
 const bzip2FinalMagic = 0x177245385090
 
 // setup parses the bzip2 header.
-func (bz2 *reader) setup() os.Error {
+func (bz2 *reader) setup() error {
 	br := &bz2.br
 
 	magic := br.ReadBits(16)
@@ -76,14 +73,14 @@ func (bz2 *reader) setup() os.Error {
 	return nil
 }
 
-func (bz2 *reader) Read(buf []byte) (n int, err os.Error) {
+func (bz2 *reader) Read(buf []byte) (n int, err error) {
 	if bz2.eof {
-		return 0, os.EOF
+		return 0, io.EOF
 	}
 
 	if !bz2.setupDone {
 		err = bz2.setup()
-		brErr := bz2.br.Error()
+		brErr := bz2.br.Err()
 		if brErr != nil {
 			err = brErr
 		}
@@ -94,14 +91,14 @@ func (bz2 *reader) Read(buf []byte) (n int, err os.Error) {
 	}
 
 	n, err = bz2.read(buf)
-	brErr := bz2.br.Error()
+	brErr := bz2.br.Err()
 	if brErr != nil {
 		err = brErr
 	}
 	return
 }
 
-func (bz2 *reader) read(buf []byte) (n int, err os.Error) {
+func (bz2 *reader) read(buf []byte) (n int, err error) {
 	// bzip2 is a block based compressor, except that it has a run-length
 	// preprocessing step. The block based nature means that we can
 	// preallocate fixed-size buffers and reuse them. However, the RLE
@@ -162,7 +159,7 @@ func (bz2 *reader) read(buf []byte) (n int, err os.Error) {
 	if magic == bzip2FinalMagic {
 		br.ReadBits64(32) // ignored CRC
 		bz2.eof = true
-		return 0, os.EOF
+		return 0, io.EOF
 	} else if magic != bzip2BlockMagic {
 		return 0, StructuralError("bad magic value found")
 	}
@@ -176,7 +173,7 @@ func (bz2 *reader) read(buf []byte) (n int, err os.Error) {
 }
 
 // readBlock reads a bzip2 block. The magic number should already have been consumed.
-func (bz2 *reader) readBlock() (err os.Error) {
+func (bz2 *reader) readBlock() (err error) {
 	br := &bz2.br
 	br.ReadBits64(32) // skip checksum. TODO: check it if we can figure out what it is.
 	randomized := br.ReadBits(1)
diff --git a/src/pkg/compress/bzip2/bzip2_test.go b/src/pkg/compress/bzip2/bzip2_test.go
index 156eea8..7b227ac 100644
--- a/src/pkg/compress/bzip2/bzip2_test.go
+++ b/src/pkg/compress/bzip2/bzip2_test.go
@@ -9,7 +9,6 @@ import (
 	"encoding/hex"
 	"io"
 	"io/ioutil"
-	"os"
 	"testing"
 )
 
@@ -46,7 +45,7 @@ func readerFromHex(s string) io.Reader {
 	return bytes.NewBuffer(data)
 }
 
-func decompressHex(s string) (out []byte, err os.Error) {
+func decompressHex(s string) (out []byte, err error) {
 	r := NewReader(readerFromHex(s))
 	return ioutil.ReadAll(r)
 }
diff --git a/src/pkg/compress/bzip2/huffman.go b/src/pkg/compress/bzip2/huffman.go
index dc05739..078c1cb 100644
--- a/src/pkg/compress/bzip2/huffman.go
+++ b/src/pkg/compress/bzip2/huffman.go
@@ -4,10 +4,7 @@
 
 package bzip2
 
-import (
-	"os"
-	"sort"
-)
+import "sort"
 
 // A huffmanTree is a binary tree which is navigated, bit-by-bit to reach a
 // symbol.
@@ -63,7 +60,7 @@ func (t huffmanTree) Decode(br *bitReader) (v uint16) {
 
 // newHuffmanTree builds a Huffman tree from a slice containing the code
 // lengths of each symbol. The maximum code length is 32 bits.
-func newHuffmanTree(lengths []uint8) (huffmanTree, os.Error) {
+func newHuffmanTree(lengths []uint8) (huffmanTree, error) {
 	// There are many possible trees that assign the same code length to
 	// each symbol (consider reflecting a tree down the middle, for
 	// example). Since the code length assignments determine the
@@ -176,7 +173,7 @@ func (n huffmanCodes) Swap(i, j int) {
 // buildHuffmanNode takes a slice of sorted huffmanCodes and builds a node in
 // the Huffman tree at the given level. It returns the index of the newly
 // constructed node.
-func buildHuffmanNode(t *huffmanTree, codes []huffmanCode, level uint32) (nodeIndex uint16, err os.Error) {
+func buildHuffmanNode(t *huffmanTree, codes []huffmanCode, level uint32) (nodeIndex uint16, err error) {
 	test := uint32(1) << (31 - level)
 
 	// We have to search the list of codes to find the divide between the left and right sides.
diff --git a/src/pkg/compress/flate/Makefile b/src/pkg/compress/flate/Makefile
index 197828a..04fcb6b 100644
--- a/src/pkg/compress/flate/Makefile
+++ b/src/pkg/compress/flate/Makefile
@@ -12,6 +12,5 @@ GOFILES=\
 	inflate.go\
 	reverse_bits.go\
 	token.go\
-	util.go\
 
 include ../../../Make.pkg
diff --git a/src/pkg/compress/flate/deflate.go b/src/pkg/compress/flate/deflate.go
index b1cee0b..1e72589 100644
--- a/src/pkg/compress/flate/deflate.go
+++ b/src/pkg/compress/flate/deflate.go
@@ -7,7 +7,6 @@ package flate
 import (
 	"io"
 	"math"
-	"os"
 )
 
 const (
@@ -28,10 +27,12 @@ const (
 	// stop things from getting too large.
 	maxFlateBlockTokens = 1 << 14
 	maxStoreBlockSize   = 65535
-	hashBits            = 15
+	hashBits            = 17
 	hashSize            = 1 << hashBits
 	hashMask            = (1 << hashBits) - 1
 	hashShift           = (hashBits + minMatchLength - 1) / minMatchLength
+
+	skipNever = math.MaxInt32
 )
 
 type compressionLevel struct {
@@ -46,12 +47,12 @@ var levels = []compressionLevel{
 	{3, 0, 32, 32, 6},
 	// Levels 4-9 use increasingly more lazy matching
 	// and increasingly stringent conditions for "good enough".
-	{4, 4, 16, 16, math.MaxInt32},
-	{8, 16, 32, 32, math.MaxInt32},
-	{8, 16, 128, 128, math.MaxInt32},
-	{8, 32, 128, 256, math.MaxInt32},
-	{32, 128, 258, 1024, math.MaxInt32},
-	{32, 258, 258, 4096, math.MaxInt32},
+	{4, 4, 16, 16, skipNever},
+	{8, 16, 32, 32, skipNever},
+	{8, 16, 128, 128, skipNever},
+	{8, 32, 128, 256, skipNever},
+	{32, 128, 258, 1024, skipNever},
+	{32, 258, 258, 4096, skipNever},
 }
 
 type compressor struct {
@@ -69,9 +70,10 @@ type compressor struct {
 	// If hashHead[hashValue] is within the current window, then
 	// hashPrev[hashHead[hashValue] & windowMask] contains the previous index
 	// with the same hash value.
-	chainHead int
-	hashHead  []int
-	hashPrev  []int
+	chainHead  int
+	hashHead   []int
+	hashPrev   []int
+	hashOffset int
 
 	// input window: unprocessed data is window[index:windowEnd]
 	index         int
@@ -80,16 +82,15 @@ type compressor struct {
 	blockStart    int  // window index where current tokens start
 	byteAvailable bool // if true, still need to process window[index-1].
 
-	// queued output tokens: tokens[:ti]
+	// queued output tokens
 	tokens []token
-	ti     int
 
 	// deflate state
 	length         int
 	offset         int
 	hash           int
 	maxInsertIndex int
-	err            os.Error
+	err            error
 }
 
 func (d *compressor) fillDeflate(b []byte) int {
@@ -101,29 +102,16 @@ func (d *compressor) fillDeflate(b []byte) int {
 		if d.blockStart >= windowSize {
 			d.blockStart -= windowSize
 		} else {
-			d.blockStart = math.MaxInt32
-		}
-		for i, h := range d.hashHead {
-			v := h - windowSize
-			if v < -1 {
-				v = -1
-			}
-			d.hashHead[i] = v
-		}
-		for i, h := range d.hashPrev {
-			v := -h - windowSize
-			if v < -1 {
-				v = -1
-			}
-			d.hashPrev[i] = v
+			d.blockStart = skipNever
 		}
+		d.hashOffset += windowSize
 	}
 	n := copy(d.window[d.windowEnd:], b)
 	d.windowEnd += n
 	return n
 }
 
-func (d *compressor) writeBlock(tokens []token, index int, eof bool) os.Error {
+func (d *compressor) writeBlock(tokens []token, index int, eof bool) error {
 	if index > 0 || eof {
 		var window []byte
 		if d.blockStart <= index {
@@ -187,14 +175,14 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead
 			// hashPrev[i & windowMask] has already been overwritten, so stop now.
 			break
 		}
-		if i = d.hashPrev[i&windowMask]; i < minIndex || i < 0 {
+		if i = d.hashPrev[i&windowMask] - d.hashOffset; i < minIndex || i < 0 {
 			break
 		}
 	}
 	return
 }
 
-func (d *compressor) writeStoredBlock(buf []byte) os.Error {
+func (d *compressor) writeStoredBlock(buf []byte) error {
 	if d.w.writeStoredHeader(len(buf), false); d.w.err != nil {
 		return d.w.err
 	}
@@ -206,13 +194,12 @@ func (d *compressor) initDeflate() {
 	d.hashHead = make([]int, hashSize)
 	d.hashPrev = make([]int, windowSize)
 	d.window = make([]byte, 2*windowSize)
-	fillInts(d.hashHead, -1)
-	d.tokens = make([]token, maxFlateBlockTokens, maxFlateBlockTokens+1)
+	d.hashOffset = 1
+	d.tokens = make([]token, 0, maxFlateBlockTokens+1)
 	d.length = minMatchLength - 1
 	d.offset = 0
 	d.byteAvailable = false
 	d.index = 0
-	d.ti = 0
 	d.hash = 0
 	d.chainHead = -1
 }
@@ -244,15 +231,14 @@ Loop:
 				// Flush current output block if any.
 				if d.byteAvailable {
 					// There is still one pending token that needs to be flushed
-					d.tokens[d.ti] = literalToken(uint32(d.window[d.index-1]))
-					d.ti++
+					d.tokens = append(d.tokens, literalToken(uint32(d.window[d.index-1])))
 					d.byteAvailable = false
 				}
-				if d.ti > 0 {
-					if d.err = d.writeBlock(d.tokens[0:d.ti], d.index, false); d.err != nil {
+				if len(d.tokens) > 0 {
+					if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
 						return
 					}
-					d.ti = 0
+					d.tokens = d.tokens[:0]
 				}
 				break Loop
 			}
@@ -262,7 +248,7 @@ Loop:
 			d.hash = (d.hash<<hashShift + int(d.window[d.index+2])) & hashMask
 			d.chainHead = d.hashHead[d.hash]
 			d.hashPrev[d.index&windowMask] = d.chainHead
-			d.hashHead[d.hash] = d.index
+			d.hashHead[d.hash] = d.index + d.hashOffset
 		}
 		prevLength := d.length
 		prevOffset := d.offset
@@ -273,34 +259,33 @@ Loop:
 			minIndex = 0
 		}
 
-		if d.chainHead >= minIndex &&
-			(d.fastSkipHashing != 0 && lookahead > minMatchLength-1 ||
-				d.fastSkipHashing == 0 && lookahead > prevLength && prevLength < d.lazy) {
-			if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead, minMatchLength-1, lookahead); ok {
+		if d.chainHead-d.hashOffset >= minIndex &&
+			(d.fastSkipHashing != skipNever && lookahead > minMatchLength-1 ||
+				d.fastSkipHashing == skipNever && lookahead > prevLength && prevLength < d.lazy) {
+			if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
 				d.length = newLength
 				d.offset = newOffset
 			}
 		}
-		if d.fastSkipHashing != 0 && d.length >= minMatchLength ||
-			d.fastSkipHashing == 0 && prevLength >= minMatchLength && d.length <= prevLength {
+		if d.fastSkipHashing != skipNever && d.length >= minMatchLength ||
+			d.fastSkipHashing == skipNever && prevLength >= minMatchLength && d.length <= prevLength {
 			// There was a match at the previous step, and the current match is
 			// not better. Output the previous match.
-			if d.fastSkipHashing != 0 {
-				d.tokens[d.ti] = matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize))
+			if d.fastSkipHashing != skipNever {
+				d.tokens = append(d.tokens, matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize)))
 			} else {
-				d.tokens[d.ti] = matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize))
+				d.tokens = append(d.tokens, matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize)))
 			}
-			d.ti++
 			// Insert in the hash table all strings up to the end of the match.
 			// index and index-1 are already inserted. If there is not enough
 			// lookahead, the last two strings are not inserted into the hash
 			// table.
 			if d.length <= d.fastSkipHashing {
 				var newIndex int
-				if d.fastSkipHashing != 0 {
+				if d.fastSkipHashing != skipNever {
 					newIndex = d.index + d.length
 				} else {
-					newIndex = prevLength - 1
+					newIndex = d.index + prevLength - 1
 				}
 				for d.index++; d.index < newIndex; d.index++ {
 					if d.index < d.maxInsertIndex {
@@ -309,10 +294,10 @@ Loop:
 						// Our chain should point to the previous value.
 						d.hashPrev[d.index&windowMask] = d.hashHead[d.hash]
 						// Set the head of the hash chain to us.
-						d.hashHead[d.hash] = d.index
+						d.hashHead[d.hash] = d.index + d.hashOffset
 					}
 				}
-				if d.fastSkipHashing == 0 {
+				if d.fastSkipHashing == skipNever {
 					d.byteAvailable = false
 					d.length = minMatchLength - 1
 				}
@@ -320,32 +305,33 @@ Loop:
 				// For matches this long, we don't bother inserting each individual
 				// item into the table.
 				d.index += d.length
-				d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1]))
+				if d.index < d.maxInsertIndex {
+					d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1]))
+				}
 			}
-			if d.ti == maxFlateBlockTokens {
+			if len(d.tokens) == maxFlateBlockTokens {
 				// The block includes the current character
 				if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
 					return
 				}
-				d.ti = 0
+				d.tokens = d.tokens[:0]
 			}
 		} else {
-			if d.fastSkipHashing != 0 || d.byteAvailable {
+			if d.fastSkipHashing != skipNever || d.byteAvailable {
 				i := d.index - 1
-				if d.fastSkipHashing != 0 {
+				if d.fastSkipHashing != skipNever {
 					i = d.index
 				}
-				d.tokens[d.ti] = literalToken(uint32(d.window[i]))
-				d.ti++
-				if d.ti == maxFlateBlockTokens {
+				d.tokens = append(d.tokens, literalToken(uint32(d.window[i])))
+				if len(d.tokens) == maxFlateBlockTokens {
 					if d.err = d.writeBlock(d.tokens, i+1, false); d.err != nil {
 						return
 					}
-					d.ti = 0
+					d.tokens = d.tokens[:0]
 				}
 			}
 			d.index++
-			if d.fastSkipHashing == 0 {
+			if d.fastSkipHashing == skipNever {
 				d.byteAvailable = true
 			}
 		}
@@ -365,7 +351,7 @@ func (d *compressor) store() {
 	d.windowEnd = 0
 }
 
-func (d *compressor) write(b []byte) (n int, err os.Error) {
+func (d *compressor) write(b []byte) (n int, err error) {
 	n = len(b)
 	b = b[d.fill(d, b):]
 	for len(b) > 0 {
@@ -375,7 +361,7 @@ func (d *compressor) write(b []byte) (n int, err os.Error) {
 	return n, d.err
 }
 
-func (d *compressor) syncFlush() os.Error {
+func (d *compressor) syncFlush() error {
 	d.sync = true
 	d.step(d)
 	if d.err == nil {
@@ -387,7 +373,7 @@ func (d *compressor) syncFlush() os.Error {
 	return d.err
 }
 
-func (d *compressor) init(w io.Writer, level int) (err os.Error) {
+func (d *compressor) init(w io.Writer, level int) (err error) {
 	d.w = newHuffmanBitWriter(w)
 
 	switch {
@@ -409,7 +395,7 @@ func (d *compressor) init(w io.Writer, level int) (err os.Error) {
 	return nil
 }
 
-func (d *compressor) close() os.Error {
+func (d *compressor) close() error {
 	d.sync = true
 	d.step(d)
 	if d.err != nil {
@@ -455,7 +441,7 @@ type dictWriter struct {
 	enabled bool
 }
 
-func (w *dictWriter) Write(b []byte) (n int, err os.Error) {
+func (w *dictWriter) Write(b []byte) (n int, err error) {
 	if w.enabled {
 		return w.w.Write(b)
 	}
@@ -470,7 +456,7 @@ type Writer struct {
 
 // Write writes data to w, which will eventually write the
 // compressed form of data to its underlying writer.
-func (w *Writer) Write(data []byte) (n int, err os.Error) {
+func (w *Writer) Write(data []byte) (n int, err error) {
 	return w.d.write(data)
 }
 
@@ -481,13 +467,13 @@ func (w *Writer) Write(data []byte) (n int, err os.Error) {
 // If the underlying writer returns an error, Flush returns that error.
 //
 // In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
-func (w *Writer) Flush() os.Error {
+func (w *Writer) Flush() error {
 	// For more about flushing:
 	// http://www.bolet.org/~pornin/deflate-flush.html
 	return w.d.syncFlush()
 }
 
 // Close flushes and closes the writer.
-func (w *Writer) Close() os.Error {
+func (w *Writer) Close() error {
 	return w.d.close()
 }
diff --git a/src/pkg/compress/flate/deflate_test.go b/src/pkg/compress/flate/deflate_test.go
index 9308236..24881d3 100644
--- a/src/pkg/compress/flate/deflate_test.go
+++ b/src/pkg/compress/flate/deflate_test.go
@@ -9,7 +9,6 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
-	"os"
 	"sync"
 	"testing"
 )
@@ -31,44 +30,44 @@ type reverseBitsTest struct {
 }
 
 var deflateTests = []*deflateTest{
-	&deflateTest{[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
-
-	&deflateTest{[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
+	{[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
+	{[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
+	{[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
+	{[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
+
+	{[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
 		[]byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255},
 	},
-	&deflateTest{[]byte{}, 1, []byte{1, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
-	&deflateTest{[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
-	&deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
+	{[]byte{}, 1, []byte{1, 0, 0, 255, 255}},
+	{[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
+	{[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
+	{[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
+	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
 }
 
 var deflateInflateTests = []*deflateInflateTest{
-	&deflateInflateTest{[]byte{}},
-	&deflateInflateTest{[]byte{0x11}},
-	&deflateInflateTest{[]byte{0x11, 0x12}},
-	&deflateInflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
-	&deflateInflateTest{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
-	&deflateInflateTest{largeDataChunk()},
+	{[]byte{}},
+	{[]byte{0x11}},
+	{[]byte{0x11, 0x12}},
+	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
+	{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
+	{largeDataChunk()},
 }
 
 var reverseBitsTests = []*reverseBitsTest{
-	&reverseBitsTest{1, 1, 1},
-	&reverseBitsTest{1, 2, 2},
-	&reverseBitsTest{1, 3, 4},
-	&reverseBitsTest{1, 4, 8},
-	&reverseBitsTest{1, 5, 16},
-	&reverseBitsTest{17, 5, 17},
-	&reverseBitsTest{257, 9, 257},
-	&reverseBitsTest{29, 5, 23},
+	{1, 1, 1},
+	{1, 2, 2},
+	{1, 3, 4},
+	{1, 4, 8},
+	{1, 5, 16},
+	{17, 5, 17},
+	{257, 9, 257},
+	{29, 5, 23},
 }
 
 func largeDataChunk() []byte {
@@ -102,7 +101,7 @@ func newSyncBuffer() *syncBuffer {
 	return &syncBuffer{ready: make(chan bool, 1)}
 }
 
-func (b *syncBuffer) Read(p []byte) (n int, err os.Error) {
+func (b *syncBuffer) Read(p []byte) (n int, err error) {
 	for {
 		b.mu.RLock()
 		n, err = b.buf.Read(p)
@@ -122,7 +121,7 @@ func (b *syncBuffer) signal() {
 	}
 }
 
-func (b *syncBuffer) Write(p []byte) (n int, err os.Error) {
+func (b *syncBuffer) Write(p []byte) (n int, err error) {
 	n, err = b.buf.Write(p)
 	b.signal()
 	return
@@ -137,7 +136,7 @@ func (b *syncBuffer) ReadMode() {
 	b.signal()
 }
 
-func (b *syncBuffer) Close() os.Error {
+func (b *syncBuffer) Close() error {
 	b.closed = true
 	b.signal()
 	return nil
@@ -204,7 +203,7 @@ func testSync(t *testing.T, level int, input []byte, name string) {
 	}
 	buf.ReadMode()
 	out := make([]byte, 10)
-	if n, err := r.Read(out); n > 0 || err != os.EOF {
+	if n, err := r.Read(out); n > 0 || err != io.EOF {
 		t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n])
 	}
 	if buf.buf.Len() != 0 {
@@ -225,11 +224,18 @@ func testSync(t *testing.T, level int, input []byte, name string) {
 	}
 }
 
-func testToFromWithLevel(t *testing.T, level int, input []byte, name string) os.Error {
+func testToFromWithLevel(t *testing.T, level int, input []byte, name string) error {
+	return testToFromWithLevelAndLimit(t, level, input, name, -1)
+}
+
+func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) error {
 	buffer := bytes.NewBuffer(nil)
 	w := NewWriter(buffer, level)
 	w.Write(input)
 	w.Close()
+	if limit > 0 && buffer.Len() > limit {
+		t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
+	}
 	r := NewReader(buffer)
 	out, err := ioutil.ReadAll(r)
 	if err != nil {
@@ -245,12 +251,16 @@ func testToFromWithLevel(t *testing.T, level int, input []byte, name string) os.
 	return nil
 }
 
-func testToFrom(t *testing.T, input []byte, name string) {
+func testToFromWithLimit(t *testing.T, input []byte, name string, limit [10]int) {
 	for i := 0; i < 10; i++ {
-		testToFromWithLevel(t, i, input, name)
+		testToFromWithLevelAndLimit(t, i, input, name, limit[i])
 	}
 }
 
+func testToFrom(t *testing.T, input []byte, name string) {
+	testToFromWithLimit(t, input, name, [10]int{})
+}
+
 func TestDeflateInflate(t *testing.T) {
 	for i, h := range deflateInflateTests {
 		testToFrom(t, h.in, fmt.Sprintf("#%d", i))
@@ -266,12 +276,33 @@ func TestReverseBits(t *testing.T) {
 	}
 }
 
+type deflateInflateStringTest struct {
+	filename string
+	label    string
+	limit    [10]int
+}
+
+var deflateInflateStringTests = []deflateInflateStringTest{
+	{
+		"../testdata/e.txt",
+		"2.718281828...",
+		[...]int{10013, 5065, 5096, 5115, 5093, 5079, 5079, 5079, 5079, 5079},
+	},
+	{
+		"../testdata/Mark.Twain-Tom.Sawyer.txt",
+		"Mark.Twain-Tom.Sawyer",
+		[...]int{407330, 187598, 180361, 172974, 169160, 163476, 160936, 160506, 160295, 160295},
+	},
+}
+
 func TestDeflateInflateString(t *testing.T) {
-	gold, err := ioutil.ReadFile("../testdata/e.txt")
-	if err != nil {
-		t.Error(err)
+	for _, test := range deflateInflateStringTests {
+		gold, err := ioutil.ReadFile(test.filename)
+		if err != nil {
+			t.Error(err)
+		}
+		testToFromWithLimit(t, gold, test.label, test.limit)
 	}
-	testToFromWithLevel(t, 1, gold, "2.718281828...")
 }
 
 func TestReaderDict(t *testing.T) {
@@ -319,3 +350,15 @@ func TestWriterDict(t *testing.T) {
 		t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
 	}
 }
+
+// See http://code.google.com/p/go/issues/detail?id=2508
+func TestRegression2508(t *testing.T) {
+	w := NewWriter(ioutil.Discard, 1)
+	buf := make([]byte, 1024)
+	for i := 0; i < 131072; i++ {
+		if _, err := w.Write(buf); err != nil {
+			t.Fatalf("writer failed: %v", err)
+		}
+	}
+	w.Close()
+}
diff --git a/src/pkg/compress/flate/flate_test.go b/src/pkg/compress/flate/flate_test.go
index bfd3b83..94efc90 100644
--- a/src/pkg/compress/flate/flate_test.go
+++ b/src/pkg/compress/flate/flate_test.go
@@ -52,7 +52,7 @@ type InitDecoderTest struct {
 
 var initDecoderTests = []*InitDecoderTest{
 	// Example from Connell 1973,
-	&InitDecoderTest{
+	{
 		[]int{3, 5, 2, 4, 3, 5, 5, 4, 4, 3, 4, 5},
 		huffmanDecoder{
 			2, 5,
@@ -68,7 +68,7 @@ var initDecoderTests = []*InitDecoderTest{
 	},
 
 	// Example from RFC 1951 section 3.2.2
-	&InitDecoderTest{
+	{
 		[]int{2, 1, 3, 3},
 		huffmanDecoder{
 			1, 3,
@@ -80,7 +80,7 @@ var initDecoderTests = []*InitDecoderTest{
 	},
 
 	// Second example from RFC 1951 section 3.2.2
-	&InitDecoderTest{
+	{
 		[]int{3, 3, 3, 3, 3, 2, 4, 4},
 		huffmanDecoder{
 			2, 4,
@@ -92,21 +92,21 @@ var initDecoderTests = []*InitDecoderTest{
 	},
 
 	// Static Huffman codes (RFC 1951 section 3.2.6)
-	&InitDecoderTest{
+	{
 		fixedHuffmanBits[0:],
 		fixedHuffmanDecoder,
 		true,
 	},
 
 	// Illegal input.
-	&InitDecoderTest{
+	{
 		[]int{},
 		huffmanDecoder{},
 		false,
 	},
 
 	// Illegal input.
-	&InitDecoderTest{
+	{
 		[]int{0, 0, 0, 0, 0, 0, 0},
 		huffmanDecoder{},
 		false,
diff --git a/src/pkg/compress/flate/huffman_bit_writer.go b/src/pkg/compress/flate/huffman_bit_writer.go
index 3981df5..57b56b5 100644
--- a/src/pkg/compress/flate/huffman_bit_writer.go
+++ b/src/pkg/compress/flate/huffman_bit_writer.go
@@ -7,7 +7,6 @@ package flate
 import (
 	"io"
 	"math"
-	"os"
 	"strconv"
 )
 
@@ -83,7 +82,7 @@ type huffmanBitWriter struct {
 	literalEncoding *huffmanEncoder
 	offsetEncoding  *huffmanEncoder
 	codegenEncoding *huffmanEncoder
-	err             os.Error
+	err             error
 }
 
 type WrongValueError struct {
@@ -106,9 +105,9 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
 	}
 }
 
-func (err WrongValueError) String() string {
-	return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.Itoa64(int64(err.from)) + ";" +
-		strconv.Itoa64(int64(err.to)) + "] but actual value is " + strconv.Itoa64(int64(err.value))
+func (err WrongValueError) Error() string {
+	return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.FormatInt(int64(err.from), 10) + ";" +
+		strconv.FormatInt(int64(err.to), 10) + "] but actual value is " + strconv.FormatInt(int64(err.value), 10)
 }
 
 func (w *huffmanBitWriter) flushBits() {
@@ -194,15 +193,17 @@ func (w *huffmanBitWriter) writeBytes(bytes []byte) {
 //  numLiterals      The number of literals in literalEncoding
 //  numOffsets       The number of offsets in offsetEncoding
 func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
-	fillInt32s(w.codegenFreq, 0)
+	for i := range w.codegenFreq {
+		w.codegenFreq[i] = 0
+	}
 	// Note that we are using codegen both as a temporary variable for holding
 	// a copy of the frequencies, and as the place where we put the result.
 	// This is fine because the output is always shorter than the input used
 	// so far.
 	codegen := w.codegen // cache
 	// Copy the concatenated code sizes to codegen.  Put a marker at the end.
-	copyUint8s(codegen[0:numLiterals], w.literalEncoding.codeBits)
-	copyUint8s(codegen[numLiterals:numLiterals+numOffsets], w.offsetEncoding.codeBits)
+	copy(codegen[0:numLiterals], w.literalEncoding.codeBits)
+	copy(codegen[numLiterals:numLiterals+numOffsets], w.offsetEncoding.codeBits)
 	codegen[numLiterals+numOffsets] = badCode
 
 	size := codegen[0]
@@ -223,7 +224,10 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
 			w.codegenFreq[size]++
 			count--
 			for count >= 3 {
-				n := min(count, 6)
+				n := 6
+				if n > count {
+					n = count
+				}
 				codegen[outIndex] = 16
 				outIndex++
 				codegen[outIndex] = uint8(n - 3)
@@ -233,7 +237,10 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
 			}
 		} else {
 			for count >= 11 {
-				n := min(count, 138)
+				n := 138
+				if n > count {
+					n = count
+				}
 				codegen[outIndex] = 18
 				outIndex++
 				codegen[outIndex] = uint8(n - 11)
@@ -352,8 +359,12 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
 	if w.err != nil {
 		return
 	}
-	fillInt32s(w.literalFreq, 0)
-	fillInt32s(w.offsetFreq, 0)
+	for i := range w.literalFreq {
+		w.literalFreq[i] = 0
+	}
+	for i := range w.offsetFreq {
+		w.offsetFreq[i] = 0
+	}
 
 	n := len(tokens)
 	tokens = tokens[0 : n+1]
diff --git a/src/pkg/compress/flate/huffman_code.go b/src/pkg/compress/flate/huffman_code.go
index 7ed603a..4873b0f 100644
--- a/src/pkg/compress/flate/huffman_code.go
+++ b/src/pkg/compress/flate/huffman_code.go
@@ -195,7 +195,9 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
 
 	// The tree can't have greater depth than n - 1, no matter what.  This
 	// saves a little bit of work in some small cases
-	maxBits = minInt32(maxBits, n-1)
+	if maxBits > n-1 {
+		maxBits = n - 1
+	}
 
 	// Create information about each of the levels.
 	// A bogus "Level 0" whose sole purpose is so that
diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go
index 3845f12..3f2042b 100644
--- a/src/pkg/compress/flate/inflate.go
+++ b/src/pkg/compress/flate/inflate.go
@@ -10,7 +10,6 @@ package flate
 import (
 	"bufio"
 	"io"
-	"os"
 	"strconv"
 )
 
@@ -25,33 +24,33 @@ const (
 // A CorruptInputError reports the presence of corrupt input at a given offset.
 type CorruptInputError int64
 
-func (e CorruptInputError) String() string {
-	return "flate: corrupt input before offset " + strconv.Itoa64(int64(e))
+func (e CorruptInputError) Error() string {
+	return "flate: corrupt input before offset " + strconv.FormatInt(int64(e), 10)
 }
 
 // An InternalError reports an error in the flate code itself.
 type InternalError string
 
-func (e InternalError) String() string { return "flate: internal error: " + string(e) }
+func (e InternalError) Error() string { return "flate: internal error: " + string(e) }
 
 // A ReadError reports an error encountered while reading input.
 type ReadError struct {
-	Offset int64    // byte offset where error occurred
-	Error  os.Error // error returned by underlying Read
+	Offset int64 // byte offset where error occurred
+	Err    error // error returned by underlying Read
 }
 
-func (e *ReadError) String() string {
-	return "flate: read error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Error.String()
+func (e *ReadError) Error() string {
+	return "flate: read error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
 }
 
 // A WriteError reports an error encountered while writing output.
 type WriteError struct {
-	Offset int64    // byte offset where error occurred
-	Error  os.Error // error returned by underlying Write
+	Offset int64 // byte offset where error occurred
+	Err    error // error returned by underlying Write
 }
 
-func (e *WriteError) String() string {
-	return "flate: write error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Error.String()
+func (e *WriteError) Error() string {
+	return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
 }
 
 // Huffman decoder is based on
@@ -190,7 +189,7 @@ var fixedHuffmanDecoder = huffmanDecoder{
 // the NewReader will introduce its own buffering.
 type Reader interface {
 	io.Reader
-	ReadByte() (c byte, err os.Error)
+	ReadByte() (c byte, err error)
 }
 
 // Decompress state.
@@ -224,7 +223,7 @@ type decompressor struct {
 	// and decompression state.
 	step     func(*decompressor)
 	final    bool
-	err      os.Error
+	err      error
 	toRead   []byte
 	hl, hd   *huffmanDecoder
 	copyLen  int
@@ -237,7 +236,7 @@ func (f *decompressor) nextBlock() {
 			f.flush((*decompressor).nextBlock)
 			return
 		}
-		f.err = os.EOF
+		f.err = io.EOF
 		return
 	}
 	for f.nb < 1+2 {
@@ -272,7 +271,7 @@ func (f *decompressor) nextBlock() {
 	}
 }
 
-func (f *decompressor) Read(b []byte) (int, os.Error) {
+func (f *decompressor) Read(b []byte) (int, error) {
 	for {
 		if len(f.toRead) > 0 {
 			n := copy(b, f.toRead)
@@ -287,8 +286,8 @@ func (f *decompressor) Read(b []byte) (int, os.Error) {
 	panic("unreachable")
 }
 
-func (f *decompressor) Close() os.Error {
-	if f.err == os.EOF {
+func (f *decompressor) Close() error {
+	if f.err == io.EOF {
 		return nil
 	}
 	return f.err
@@ -299,7 +298,7 @@ func (f *decompressor) Close() os.Error {
 
 var codeOrder = [...]int{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
 
-func (f *decompressor) readHuffman() os.Error {
+func (f *decompressor) readHuffman() error {
 	// HLIT[5], HDIST[5], HCLEN[4].
 	for f.nb < 5+5+4 {
 		if err := f.moreBits(); err != nil {
@@ -625,10 +624,10 @@ func (f *decompressor) setDict(dict []byte) {
 	f.hw = f.hp
 }
 
-func (f *decompressor) moreBits() os.Error {
+func (f *decompressor) moreBits() error {
 	c, err := f.r.ReadByte()
 	if err != nil {
-		if err == os.EOF {
+		if err == io.EOF {
 			err = io.ErrUnexpectedEOF
 		}
 		return err
@@ -640,7 +639,7 @@ func (f *decompressor) moreBits() os.Error {
 }
 
 // Read the next Huffman-encoded symbol from f according to h.
-func (f *decompressor) huffSym(h *huffmanDecoder) (int, os.Error) {
+func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) {
 	for n := uint(h.min); n <= uint(h.max); n++ {
 		lim := h.limit[n]
 		if lim == -1 {
diff --git a/src/pkg/compress/flate/util.go b/src/pkg/compress/flate/util.go
deleted file mode 100644
index aca5c78..0000000
--- a/src/pkg/compress/flate/util.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package flate
-
-func min(left int, right int) int {
-	if left < right {
-		return left
-	}
-	return right
-}
-
-func minInt32(left int32, right int32) int32 {
-	if left < right {
-		return left
-	}
-	return right
-}
-
-func max(left int, right int) int {
-	if left > right {
-		return left
-	}
-	return right
-}
-
-func fillInts(a []int, value int) {
-	for i := range a {
-		a[i] = value
-	}
-}
-
-func fillInt32s(a []int32, value int32) {
-	for i := range a {
-		a[i] = value
-	}
-}
-
-func fillBytes(a []byte, value byte) {
-	for i := range a {
-		a[i] = value
-	}
-}
-
-func fillInt8s(a []int8, value int8) {
-	for i := range a {
-		a[i] = value
-	}
-}
-
-func fillUint8s(a []uint8, value uint8) {
-	for i := range a {
-		a[i] = value
-	}
-}
-
-func copyInt8s(dst []int8, src []int8) int {
-	cnt := min(len(dst), len(src))
-	for i := 0; i < cnt; i++ {
-		dst[i] = src[i]
-	}
-	return cnt
-}
-
-func copyUint8s(dst []uint8, src []uint8) int {
-	cnt := min(len(dst), len(src))
-	for i := 0; i < cnt; i++ {
-		dst[i] = src[i]
-	}
-	return cnt
-}
diff --git a/src/pkg/compress/gzip/gunzip.go b/src/pkg/compress/gzip/gunzip.go
index 6ac9293..d374310 100644
--- a/src/pkg/compress/gzip/gunzip.go
+++ b/src/pkg/compress/gzip/gunzip.go
@@ -9,10 +9,11 @@ package gzip
 import (
 	"bufio"
 	"compress/flate"
+	"errors"
 	"hash"
 	"hash/crc32"
 	"io"
-	"os"
+	"time"
 )
 
 // BUG(nigeltao): Comments and Names don't properly map UTF-8 character codes outside of
@@ -36,17 +37,17 @@ func makeReader(r io.Reader) flate.Reader {
 	return bufio.NewReader(r)
 }
 
-var HeaderError = os.NewError("invalid gzip header")
-var ChecksumError = os.NewError("gzip checksum error")
+var ErrHeader = errors.New("invalid gzip header")
+var ErrChecksum = errors.New("gzip checksum error")
 
 // The gzip file stores a header giving metadata about the compressed file.
 // That header is exposed as the fields of the Compressor and Decompressor structs.
 type Header struct {
-	Comment string // comment
-	Extra   []byte // "extra data"
-	Mtime   uint32 // modification time (seconds since January 1, 1970)
-	Name    string // file name
-	OS      byte   // operating system type
+	Comment string    // comment
+	Extra   []byte    // "extra data"
+	ModTime time.Time // modification time
+	Name    string    // file name
+	OS      byte      // operating system type
 }
 
 // An Decompressor is an io.Reader that can be read to retrieve
@@ -58,7 +59,7 @@ type Header struct {
 // Only the first header is recorded in the Decompressor fields.
 //
 // Gzip files store a length and checksum of the uncompressed data.
-// The Decompressor will return a ChecksumError when Read
+// The Decompressor will return a ErrChecksum when Read
 // reaches the end of the uncompressed data if it does not
 // have the expected length or checksum.  Clients should treat data
 // returned by Read as tentative until they receive the successful
@@ -71,13 +72,13 @@ type Decompressor struct {
 	size         uint32
 	flg          byte
 	buf          [512]byte
-	err          os.Error
+	err          error
 }
 
 // NewReader creates a new Decompressor reading the given reader.
 // The implementation buffers input and may read more data than necessary from r.
 // It is the caller's responsibility to call Close on the Decompressor when done.
-func NewReader(r io.Reader) (*Decompressor, os.Error) {
+func NewReader(r io.Reader) (*Decompressor, error) {
 	z := new(Decompressor)
 	z.r = makeReader(r)
 	z.digest = crc32.NewIEEE()
@@ -93,26 +94,36 @@ func get4(p []byte) uint32 {
 	return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
 }
 
-func (z *Decompressor) readString() (string, os.Error) {
-	var err os.Error
+func (z *Decompressor) readString() (string, error) {
+	var err error
+	needconv := false
 	for i := 0; ; i++ {
 		if i >= len(z.buf) {
-			return "", HeaderError
+			return "", ErrHeader
 		}
 		z.buf[i], err = z.r.ReadByte()
 		if err != nil {
 			return "", err
 		}
+		if z.buf[i] > 0x7f {
+			needconv = true
+		}
 		if z.buf[i] == 0 {
 			// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
-			// TODO(nigeltao): Convert from ISO 8859-1 (Latin-1) to UTF-8.
+			if needconv {
+				s := make([]rune, 0, i)
+				for _, v := range z.buf[0:i] {
+					s = append(s, rune(v))
+				}
+				return string(s), nil
+			}
 			return string(z.buf[0:i]), nil
 		}
 	}
 	panic("not reached")
 }
 
-func (z *Decompressor) read2() (uint32, os.Error) {
+func (z *Decompressor) read2() (uint32, error) {
 	_, err := io.ReadFull(z.r, z.buf[0:2])
 	if err != nil {
 		return 0, err
@@ -120,17 +131,17 @@ func (z *Decompressor) read2() (uint32, os.Error) {
 	return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil
 }
 
-func (z *Decompressor) readHeader(save bool) os.Error {
+func (z *Decompressor) readHeader(save bool) error {
 	_, err := io.ReadFull(z.r, z.buf[0:10])
 	if err != nil {
 		return err
 	}
 	if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
-		return HeaderError
+		return ErrHeader
 	}
 	z.flg = z.buf[3]
 	if save {
-		z.Mtime = get4(z.buf[4:8])
+		z.ModTime = time.Unix(int64(get4(z.buf[4:8])), 0)
 		// z.buf[8] is xfl, ignored
 		z.OS = z.buf[9]
 	}
@@ -177,7 +188,7 @@ func (z *Decompressor) readHeader(save bool) os.Error {
 		}
 		sum := z.digest.Sum32() & 0xFFFF
 		if n != sum {
-			return HeaderError
+			return ErrHeader
 		}
 	}
 
@@ -186,7 +197,7 @@ func (z *Decompressor) readHeader(save bool) os.Error {
 	return nil
 }
 
-func (z *Decompressor) Read(p []byte) (n int, err os.Error) {
+func (z *Decompressor) Read(p []byte) (n int, err error) {
 	if z.err != nil {
 		return 0, z.err
 	}
@@ -197,7 +208,7 @@ func (z *Decompressor) Read(p []byte) (n int, err os.Error) {
 	n, err = z.decompressor.Read(p)
 	z.digest.Write(p[0:n])
 	z.size += uint32(n)
-	if n != 0 || err != os.EOF {
+	if n != 0 || err != io.EOF {
 		z.err = err
 		return
 	}
@@ -210,7 +221,7 @@ func (z *Decompressor) Read(p []byte) (n int, err os.Error) {
 	crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8])
 	sum := z.digest.Sum32()
 	if sum != crc32 || isize != z.size {
-		z.err = ChecksumError
+		z.err = ErrChecksum
 		return 0, z.err
 	}
 
@@ -227,4 +238,4 @@ func (z *Decompressor) Read(p []byte) (n int, err os.Error) {
 }
 
 // Calling Close does not close the wrapped io.Reader originally passed to NewReader.
-func (z *Decompressor) Close() os.Error { return z.decompressor.Close() }
+func (z *Decompressor) Close() error { return z.decompressor.Close() }
diff --git a/src/pkg/compress/gzip/gunzip_test.go b/src/pkg/compress/gzip/gunzip_test.go
index 1c08c73..a133358 100644
--- a/src/pkg/compress/gzip/gunzip_test.go
+++ b/src/pkg/compress/gzip/gunzip_test.go
@@ -7,7 +7,6 @@ package gzip
 import (
 	"bytes"
 	"io"
-	"os"
 	"testing"
 )
 
@@ -16,7 +15,7 @@ type gunzipTest struct {
 	desc string
 	raw  string
 	gzip []byte
-	err  os.Error
+	err  error
 }
 
 var gunzipTests = []gunzipTest{
@@ -233,7 +232,7 @@ var gunzipTests = []gunzipTest{
 			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
 			0x00, 0x00, 'g', 'a', 'r', 'b', 'a', 'g', 'e', '!', '!', '!',
 		},
-		HeaderError,
+		ErrHeader,
 	},
 	{ // has 1 non-empty fixed huffman block not enough header
 		"hello.txt",
@@ -261,7 +260,7 @@ var gunzipTests = []gunzipTest{
 			0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x00,
 			0x00, 0x00,
 		},
-		ChecksumError,
+		ErrChecksum,
 	},
 	{ // has 1 non-empty fixed huffman block but corrupt size
 		"hello.txt",
@@ -275,7 +274,7 @@ var gunzipTests = []gunzipTest{
 			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0xff, 0x00,
 			0x00, 0x00,
 		},
-		ChecksumError,
+		ErrChecksum,
 	},
 }
 
diff --git a/src/pkg/compress/gzip/gzip.go b/src/pkg/compress/gzip/gzip.go
index 8860d10..f2639a6 100644
--- a/src/pkg/compress/gzip/gzip.go
+++ b/src/pkg/compress/gzip/gzip.go
@@ -6,10 +6,10 @@ package gzip
 
 import (
 	"compress/flate"
+	"errors"
 	"hash"
 	"hash/crc32"
 	"io"
-	"os"
 )
 
 // These constants are copied from the flate package, so that code that imports
@@ -32,11 +32,11 @@ type Compressor struct {
 	size       uint32
 	closed     bool
 	buf        [10]byte
-	err        os.Error
+	err        error
 }
 
 // NewWriter calls NewWriterLevel with the default compression level.
-func NewWriter(w io.Writer) (*Compressor, os.Error) {
+func NewWriter(w io.Writer) (*Compressor, error) {
 	return NewWriterLevel(w, DefaultCompression)
 }
 
@@ -47,7 +47,7 @@ func NewWriter(w io.Writer) (*Compressor, os.Error) {
 // It is the caller's responsibility to call Close on the WriteCloser when done.
 // level is the compression level, which can be DefaultCompression, NoCompression,
 // or any integer value between BestSpeed and BestCompression (inclusive).
-func NewWriterLevel(w io.Writer, level int) (*Compressor, os.Error) {
+func NewWriterLevel(w io.Writer, level int) (*Compressor, error) {
 	z := new(Compressor)
 	z.OS = 255 // unknown
 	z.w = w
@@ -70,9 +70,9 @@ func put4(p []byte, v uint32) {
 }
 
 // writeBytes writes a length-prefixed byte slice to z.w.
-func (z *Compressor) writeBytes(b []byte) os.Error {
+func (z *Compressor) writeBytes(b []byte) error {
 	if len(b) > 0xffff {
-		return os.NewError("gzip.Write: Extra data is too large")
+		return errors.New("gzip.Write: Extra data is too large")
 	}
 	put2(z.buf[0:2], uint16(len(b)))
 	_, err := z.w.Write(z.buf[0:2])
@@ -84,15 +84,27 @@ func (z *Compressor) writeBytes(b []byte) os.Error {
 }
 
 // writeString writes a string (in ISO 8859-1 (Latin-1) format) to z.w.
-func (z *Compressor) writeString(s string) os.Error {
+func (z *Compressor) writeString(s string) error {
 	// GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
-	// TODO(nigeltao): Convert from UTF-8 to ISO 8859-1 (Latin-1).
+	var err error
+	needconv := false
 	for _, v := range s {
-		if v == 0 || v > 0x7f {
-			return os.NewError("gzip.Write: non-ASCII header string")
+		if v == 0 || v > 0xff {
+			return errors.New("gzip.Write: non-Latin-1 header string")
 		}
+		if v > 0x7f {
+			needconv = true
+		}
+	}
+	if needconv {
+		b := make([]byte, 0, len(s))
+		for _, v := range s {
+			b = append(b, byte(v))
+		}
+		_, err = z.w.Write(b)
+	} else {
+		_, err = io.WriteString(z.w, s)
 	}
-	_, err := io.WriteString(z.w, s)
 	if err != nil {
 		return err
 	}
@@ -102,7 +114,7 @@ func (z *Compressor) writeString(s string) os.Error {
 	return err
 }
 
-func (z *Compressor) Write(p []byte) (int, os.Error) {
+func (z *Compressor) Write(p []byte) (int, error) {
 	if z.err != nil {
 		return 0, z.err
 	}
@@ -122,7 +134,7 @@ func (z *Compressor) Write(p []byte) (int, os.Error) {
 		if z.Comment != "" {
 			z.buf[3] |= 0x10
 		}
-		put4(z.buf[4:8], z.Mtime)
+		put4(z.buf[4:8], uint32(z.ModTime.Unix()))
 		if z.level == BestCompression {
 			z.buf[8] = 2
 		} else if z.level == BestSpeed {
@@ -162,7 +174,7 @@ func (z *Compressor) Write(p []byte) (int, os.Error) {
 }
 
 // Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
-func (z *Compressor) Close() os.Error {
+func (z *Compressor) Close() error {
 	if z.err != nil {
 		return z.err
 	}
diff --git a/src/pkg/compress/gzip/gzip_test.go b/src/pkg/compress/gzip/gzip_test.go
index 121e627..eb7a7ec 100644
--- a/src/pkg/compress/gzip/gzip_test.go
+++ b/src/pkg/compress/gzip/gzip_test.go
@@ -5,9 +5,12 @@
 package gzip
 
 import (
+	"bufio"
+	"bytes"
 	"io"
 	"io/ioutil"
 	"testing"
+	"time"
 )
 
 // pipe creates two ends of a pipe that gzip and gunzip, and runs dfunc at the
@@ -51,9 +54,10 @@ func TestEmpty(t *testing.T) {
 func TestWriter(t *testing.T) {
 	pipe(t,
 		func(compressor *Compressor) {
-			compressor.Comment = "comment"
+			compressor.Comment = "Äußerung"
+			//compressor.Comment = "comment"
 			compressor.Extra = []byte("extra")
-			compressor.Mtime = 1e8
+			compressor.ModTime = time.Unix(1e8, 0)
 			compressor.Name = "name"
 			_, err := compressor.Write([]byte("payload"))
 			if err != nil {
@@ -68,17 +72,43 @@ func TestWriter(t *testing.T) {
 			if string(b) != "payload" {
 				t.Fatalf("payload is %q, want %q", string(b), "payload")
 			}
-			if decompressor.Comment != "comment" {
-				t.Fatalf("comment is %q, want %q", decompressor.Comment, "comment")
+			if decompressor.Comment != "Äußerung" {
+				t.Fatalf("comment is %q, want %q", decompressor.Comment, "Äußerung")
 			}
 			if string(decompressor.Extra) != "extra" {
 				t.Fatalf("extra is %q, want %q", decompressor.Extra, "extra")
 			}
-			if decompressor.Mtime != 1e8 {
-				t.Fatalf("mtime is %d, want %d", decompressor.Mtime, uint32(1e8))
+			if decompressor.ModTime.Unix() != 1e8 {
+				t.Fatalf("mtime is %d, want %d", decompressor.ModTime.Unix(), uint32(1e8))
 			}
 			if decompressor.Name != "name" {
 				t.Fatalf("name is %q, want %q", decompressor.Name, "name")
 			}
 		})
 }
+
+func TestLatin1(t *testing.T) {
+	latin1 := []byte{0xc4, 'u', 0xdf, 'e', 'r', 'u', 'n', 'g', 0}
+	utf8 := "Äußerung"
+	z := Decompressor{r: bufio.NewReader(bytes.NewBuffer(latin1))}
+	s, err := z.readString()
+	if err != nil {
+		t.Fatalf("%v", err)
+	}
+	if s != utf8 {
+		t.Fatalf("string is %q, want %q", s, utf8)
+	}
+
+	buf := bytes.NewBuffer(make([]byte, 0, len(latin1)))
+	c := Compressor{w: buf}
+	if err = c.writeString(utf8); err != nil {
+		t.Fatalf("%v", err)
+	}
+	s = buf.String()
+	if s != string(latin1) {
+		t.Fatalf("string is %v, want %v", s, latin1)
+	}
+	//if s, err = buf.ReadString(0); err != nil {
+	//t.Fatalf("%v", err)
+	//}
+}
diff --git a/src/pkg/compress/lzw/reader.go b/src/pkg/compress/lzw/reader.go
index 21231c8..0ed742c 100644
--- a/src/pkg/compress/lzw/reader.go
+++ b/src/pkg/compress/lzw/reader.go
@@ -16,9 +16,9 @@ package lzw
 
 import (
 	"bufio"
+	"errors"
 	"fmt"
 	"io"
-	"os"
 )
 
 // Order specifies the bit ordering in an LZW data stream.
@@ -45,9 +45,9 @@ type decoder struct {
 	bits     uint32
 	nBits    uint
 	width    uint
-	read     func(*decoder) (uint16, os.Error) // readLSB or readMSB
-	litWidth int                               // width in bits of literal codes
-	err      os.Error
+	read     func(*decoder) (uint16, error) // readLSB or readMSB
+	litWidth int                            // width in bits of literal codes
+	err      error
 
 	// The first 1<<litWidth codes are literal codes.
 	// The next two codes mean clear and EOF.
@@ -78,7 +78,7 @@ type decoder struct {
 }
 
 // readLSB returns the next code for "Least Significant Bits first" data.
-func (d *decoder) readLSB() (uint16, os.Error) {
+func (d *decoder) readLSB() (uint16, error) {
 	for d.nBits < d.width {
 		x, err := d.r.ReadByte()
 		if err != nil {
@@ -94,7 +94,7 @@ func (d *decoder) readLSB() (uint16, os.Error) {
 }
 
 // readMSB returns the next code for "Most Significant Bits first" data.
-func (d *decoder) readMSB() (uint16, os.Error) {
+func (d *decoder) readMSB() (uint16, error) {
 	for d.nBits < d.width {
 		x, err := d.r.ReadByte()
 		if err != nil {
@@ -109,7 +109,7 @@ func (d *decoder) readMSB() (uint16, os.Error) {
 	return code, nil
 }
 
-func (d *decoder) Read(b []byte) (int, os.Error) {
+func (d *decoder) Read(b []byte) (int, error) {
 	for {
 		if len(d.toRead) > 0 {
 			n := copy(b, d.toRead)
@@ -132,7 +132,7 @@ func (d *decoder) decode() {
 	for {
 		code, err := d.read(d)
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				err = io.ErrUnexpectedEOF
 			}
 			d.err = err
@@ -156,7 +156,7 @@ func (d *decoder) decode() {
 			continue
 		case code == d.eof:
 			d.flush()
-			d.err = os.EOF
+			d.err = io.EOF
 			return
 		case code <= d.hi:
 			c, i := code, len(d.output)-1
@@ -186,7 +186,7 @@ func (d *decoder) decode() {
 				d.prefix[d.hi] = d.last
 			}
 		default:
-			d.err = os.NewError("lzw: invalid code")
+			d.err = errors.New("lzw: invalid code")
 			return
 		}
 		d.last, d.hi = code, d.hi+1
@@ -211,8 +211,10 @@ func (d *decoder) flush() {
 	d.o = 0
 }
 
-func (d *decoder) Close() os.Error {
-	d.err = os.EINVAL // in case any Reads come along
+var errClosed = errors.New("compress/lzw: reader/writer is closed")
+
+func (d *decoder) Close() error {
+	d.err = errClosed // in case any Reads come along
 	return nil
 }
 
@@ -230,7 +232,7 @@ func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser {
 	case MSB:
 		d.read = (*decoder).readMSB
 	default:
-		d.err = os.NewError("lzw: unknown order")
+		d.err = errors.New("lzw: unknown order")
 		return d
 	}
 	if litWidth < 2 || 8 < litWidth {
diff --git a/src/pkg/compress/lzw/reader_test.go b/src/pkg/compress/lzw/reader_test.go
index f8042b0..0982157 100644
--- a/src/pkg/compress/lzw/reader_test.go
+++ b/src/pkg/compress/lzw/reader_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"io"
 	"io/ioutil"
-	"os"
 	"runtime"
 	"strconv"
 	"strings"
@@ -19,7 +18,7 @@ type lzwTest struct {
 	desc       string
 	raw        string
 	compressed string
-	err        os.Error
+	err        error
 }
 
 var lzwTests = []lzwTest{
diff --git a/src/pkg/compress/lzw/writer.go b/src/pkg/compress/lzw/writer.go
index 87143b7..488ba64 100644
--- a/src/pkg/compress/lzw/writer.go
+++ b/src/pkg/compress/lzw/writer.go
@@ -6,27 +6,27 @@ package lzw
 
 import (
 	"bufio"
+	"errors"
 	"fmt"
 	"io"
-	"os"
 )
 
 // A writer is a buffered, flushable writer.
 type writer interface {
-	WriteByte(byte) os.Error
-	Flush() os.Error
+	WriteByte(byte) error
+	Flush() error
 }
 
 // An errWriteCloser is an io.WriteCloser that always returns a given error.
 type errWriteCloser struct {
-	err os.Error
+	err error
 }
 
-func (e *errWriteCloser) Write([]byte) (int, os.Error) {
+func (e *errWriteCloser) Write([]byte) (int, error) {
 	return 0, e.err
 }
 
-func (e *errWriteCloser) Close() os.Error {
+func (e *errWriteCloser) Close() error {
 	return e.err
 }
 
@@ -48,9 +48,10 @@ const (
 type encoder struct {
 	// w is the writer that compressed bytes are written to.
 	w writer
-	// write, bits, nBits and width are the state for converting a code stream
-	// into a byte stream.
-	write func(*encoder, uint32) os.Error
+	// order, write, bits, nBits and width are the state for
+	// converting a code stream into a byte stream.
+	order Order
+	write func(*encoder, uint32) error
 	bits  uint32
 	nBits uint
 	width uint
@@ -63,8 +64,8 @@ type encoder struct {
 	// call. It is equal to invalidCode if there was no such call.
 	savedCode uint32
 	// err is the first error encountered during writing. Closing the encoder
-	// will make any future Write calls return os.EINVAL.
-	err os.Error
+	// will make any future Write calls return errClosed
+	err error
 	// table is the hash table from 20-bit keys to 12-bit values. Each table
 	// entry contains key<<12|val and collisions resolve by linear probing.
 	// The keys consist of a 12-bit code prefix and an 8-bit byte suffix.
@@ -73,7 +74,7 @@ type encoder struct {
 }
 
 // writeLSB writes the code c for "Least Significant Bits first" data.
-func (e *encoder) writeLSB(c uint32) os.Error {
+func (e *encoder) writeLSB(c uint32) error {
 	e.bits |= c << e.nBits
 	e.nBits += e.width
 	for e.nBits >= 8 {
@@ -87,7 +88,7 @@ func (e *encoder) writeLSB(c uint32) os.Error {
 }
 
 // writeMSB writes the code c for "Most Significant Bits first" data.
-func (e *encoder) writeMSB(c uint32) os.Error {
+func (e *encoder) writeMSB(c uint32) error {
 	e.bits |= c << (32 - e.width - e.nBits)
 	e.nBits += e.width
 	for e.nBits >= 8 {
@@ -102,12 +103,12 @@ func (e *encoder) writeMSB(c uint32) os.Error {
 
 // errOutOfCodes is an internal error that means that the encoder has run out
 // of unused codes and a clear code needs to be sent next.
-var errOutOfCodes = os.NewError("lzw: out of codes")
+var errOutOfCodes = errors.New("lzw: out of codes")
 
 // incHi increments e.hi and checks for both overflow and running out of
 // unused codes. In the latter case, incHi sends a clear code, resets the
 // encoder state and returns errOutOfCodes.
-func (e *encoder) incHi() os.Error {
+func (e *encoder) incHi() error {
 	e.hi++
 	if e.hi == e.overflow {
 		e.width++
@@ -130,7 +131,7 @@ func (e *encoder) incHi() os.Error {
 }
 
 // Write writes a compressed representation of p to e's underlying writer.
-func (e *encoder) Write(p []byte) (int, os.Error) {
+func (e *encoder) Write(p []byte) (int, error) {
 	if e.err != nil {
 		return 0, e.err
 	}
@@ -188,15 +189,15 @@ loop:
 
 // Close closes the encoder, flushing any pending output. It does not close or
 // flush e's underlying writer.
-func (e *encoder) Close() os.Error {
+func (e *encoder) Close() error {
 	if e.err != nil {
-		if e.err == os.EINVAL {
+		if e.err == errClosed {
 			return nil
 		}
 		return e.err
 	}
-	// Make any future calls to Write return os.EINVAL.
-	e.err = os.EINVAL
+	// Make any future calls to Write return errClosed.
+	e.err = errClosed
 	// Write the savedCode if valid.
 	if e.savedCode != invalidCode {
 		if err := e.write(e, e.savedCode); err != nil {
@@ -213,7 +214,7 @@ func (e *encoder) Close() os.Error {
 	}
 	// Write the final bits.
 	if e.nBits > 0 {
-		if e.write == (*encoder).writeMSB {
+		if e.order == MSB {
 			e.bits >>= 24
 		}
 		if err := e.w.WriteByte(uint8(e.bits)); err != nil {
@@ -230,14 +231,14 @@ func (e *encoder) Close() os.Error {
 // The number of bits to use for literal codes, litWidth, must be in the
 // range [2,8] and is typically 8.
 func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser {
-	var write func(*encoder, uint32) os.Error
+	var write func(*encoder, uint32) error
 	switch order {
 	case LSB:
 		write = (*encoder).writeLSB
 	case MSB:
 		write = (*encoder).writeMSB
 	default:
-		return &errWriteCloser{os.NewError("lzw: unknown order")}
+		return &errWriteCloser{errors.New("lzw: unknown order")}
 	}
 	if litWidth < 2 || 8 < litWidth {
 		return &errWriteCloser{fmt.Errorf("lzw: litWidth %d out of range", litWidth)}
@@ -249,6 +250,7 @@ func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser {
 	lw := uint(litWidth)
 	return &encoder{
 		w:         bw,
+		order:     order,
 		write:     write,
 		width:     1 + lw,
 		litWidth:  lw,
diff --git a/src/pkg/compress/lzw/writer_test.go b/src/pkg/compress/lzw/writer_test.go
index 4c5e522..d249a09 100644
--- a/src/pkg/compress/lzw/writer_test.go
+++ b/src/pkg/compress/lzw/writer_test.go
@@ -45,20 +45,16 @@ func testFile(t *testing.T, fn string, order Order, litWidth int) {
 		var b [4096]byte
 		for {
 			n, err0 := raw.Read(b[:])
-			if err0 != nil && err0 != os.EOF {
+			if err0 != nil && err0 != io.EOF {
 				t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
 				return
 			}
 			_, err1 := lzww.Write(b[:n])
-			if err1 == os.EPIPE {
-				// Fail, but do not report the error, as some other (presumably reportable) error broke the pipe.
-				return
-			}
 			if err1 != nil {
 				t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
 				return
 			}
-			if err0 == os.EOF {
+			if err0 == io.EOF {
 				break
 			}
 		}
diff --git a/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt
new file mode 100644
index 0000000..8d0ff4e
--- /dev/null
+++ b/src/pkg/compress/testdata/Mark.Twain-Tom.Sawyer.txt
@@ -0,0 +1,8858 @@
+The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+by Mark Twain (Samuel Clemens)
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever.  You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.net
+
+
+Title: The Adventures of Tom Sawyer, Complete
+
+Author: Mark Twain (Samuel Clemens)
+
+Release Date: August 20, 2006 [EBook #74]
+[Last updated: May 3, 2011]
+
+Language: English
+
+
+*** START OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
+
+
+
+
+Produced by David Widger. The previous edition was updated by Jose
+Menendez.
+
+
+
+
+
+                   THE ADVENTURES OF TOM SAWYER
+                                BY
+                            MARK TWAIN
+                     (Samuel Langhorne Clemens)
+
+
+
+
+                           P R E F A C E
+
+MOST of the adventures recorded in this book really occurred; one or
+two were experiences of my own, the rest those of boys who were
+schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
+not from an individual--he is a combination of the characteristics of
+three boys whom I knew, and therefore belongs to the composite order of
+architecture.
+
+The odd superstitions touched upon were all prevalent among children
+and slaves in the West at the period of this story--that is to say,
+thirty or forty years ago.
+
+Although my book is intended mainly for the entertainment of boys and
+girls, I hope it will not be shunned by men and women on that account,
+for part of my plan has been to try to pleasantly remind adults of what
+they once were themselves, and of how they felt and thought and talked,
+and what queer enterprises they sometimes engaged in.
+
+                                                            THE AUTHOR.
+
+HARTFORD, 1876.
+
+
+
+                          T O M   S A W Y E R
+
+
+
+CHAPTER I
+
+"TOM!"
+
+No answer.
+
+"TOM!"
+
+No answer.
+
+"What's gone with that boy,  I wonder? You TOM!"
+
+No answer.
+
+The old lady pulled her spectacles down and looked over them about the
+room; then she put them up and looked out under them. She seldom or
+never looked THROUGH them for so small a thing as a boy; they were her
+state pair, the pride of her heart, and were built for "style," not
+service--she could have seen through a pair of stove-lids just as well.
+She looked perplexed for a moment, and then said, not fiercely, but
+still loud enough for the furniture to hear:
+
+"Well, I lay if I get hold of you I'll--"
+
+She did not finish, for by this time she was bending down and punching
+under the bed with the broom, and so she needed breath to punctuate the
+punches with. She resurrected nothing but the cat.
+
+"I never did see the beat of that boy!"
+
+She went to the open door and stood in it and looked out among the
+tomato vines and "jimpson" weeds that constituted the garden. No Tom.
+So she lifted up her voice at an angle calculated for distance and
+shouted:
+
+"Y-o-u-u TOM!"
+
+There was a slight noise behind her and she turned just in time to
+seize a small boy by the slack of his roundabout and arrest his flight.
+
+"There! I might 'a' thought of that closet. What you been doing in
+there?"
+
+"Nothing."
+
+"Nothing! Look at your hands. And look at your mouth. What IS that
+truck?"
+
+"I don't know, aunt."
+
+"Well, I know. It's jam--that's what it is. Forty times I've said if
+you didn't let that jam alone I'd skin you. Hand me that switch."
+
+The switch hovered in the air--the peril was desperate--
+
+"My! Look behind you, aunt!"
+
+The old lady whirled round, and snatched her skirts out of danger. The
+lad fled on the instant, scrambled up the high board-fence, and
+disappeared over it.
+
+His aunt Polly stood surprised a moment, and then broke into a gentle
+laugh.
+
+"Hang the boy, can't I never learn anything? Ain't he played me tricks
+enough like that for me to be looking out for him by this time? But old
+fools is the biggest fools there is. Can't learn an old dog new tricks,
+as the saying is. But my goodness, he never plays them alike, two days,
+and how is a body to know what's coming? He 'pears to know just how
+long he can torment me before I get my dander up, and he knows if he
+can make out to put me off for a minute or make me laugh, it's all down
+again and I can't hit him a lick. I ain't doing my duty by that boy,
+and that's the Lord's truth, goodness knows. Spare the rod and spile
+the child, as the Good Book says. I'm a laying up sin and suffering for
+us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
+own dead sister's boy, poor thing, and I ain't got the heart to lash
+him, somehow. Every time I let him off, my conscience does hurt me so,
+and every time I hit him my old heart most breaks. Well-a-well, man
+that is born of woman is of few days and full of trouble, as the
+Scripture says, and I reckon it's so. He'll play hookey this evening, *
+and [* Southwestern for "afternoon"] I'll just be obleeged to make him
+work, to-morrow, to punish him. It's mighty hard to make him work
+Saturdays, when all the boys is having holiday, but he hates work more
+than he hates anything else, and I've GOT to do some of my duty by him,
+or I'll be the ruination of the child."
+
+Tom did play hookey, and he had a very good time. He got back home
+barely in season to help Jim, the small colored boy, saw next-day's
+wood and split the kindlings before supper--at least he was there in
+time to tell his adventures to Jim while Jim did three-fourths of the
+work. Tom's younger brother (or rather half-brother) Sid was already
+through with his part of the work (picking up chips), for he was a
+quiet boy, and had no adventurous, troublesome ways.
+
+While Tom was eating his supper, and stealing sugar as opportunity
+offered, Aunt Polly asked him questions that were full of guile, and
+very deep--for she wanted to trap him into damaging revealments. Like
+many other simple-hearted souls, it was her pet vanity to believe she
+was endowed with a talent for dark and mysterious diplomacy, and she
+loved to contemplate her most transparent devices as marvels of low
+cunning. Said she:
+
+"Tom, it was middling warm in school, warn't it?"
+
+"Yes'm."
+
+"Powerful warm, warn't it?"
+
+"Yes'm."
+
+"Didn't you want to go in a-swimming, Tom?"
+
+A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
+He searched Aunt Polly's face, but it told him nothing. So he said:
+
+"No'm--well, not very much."
+
+The old lady reached out her hand and felt Tom's shirt, and said:
+
+"But you ain't too warm now, though." And it flattered her to reflect
+that she had discovered that the shirt was dry without anybody knowing
+that that was what she had in her mind. But in spite of her, Tom knew
+where the wind lay, now. So he forestalled what might be the next move:
+
+"Some of us pumped on our heads--mine's damp yet. See?"
+
+Aunt Polly was vexed to think she had overlooked that bit of
+circumstantial evidence, and missed a trick. Then she had a new
+inspiration:
+
+"Tom, you didn't have to undo your shirt collar where I sewed it, to
+pump on your head, did you? Unbutton your jacket!"
+
+The trouble vanished out of Tom's face. He opened his jacket. His
+shirt collar was securely sewed.
+
+"Bother! Well, go 'long with you. I'd made sure you'd played hookey
+and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
+singed cat, as the saying is--better'n you look. THIS time."
+
+She was half sorry her sagacity had miscarried, and half glad that Tom
+had stumbled into obedient conduct for once.
+
+But Sidney said:
+
+"Well, now, if I didn't think you sewed his collar with white thread,
+but it's black."
+
+"Why, I did sew it with white! Tom!"
+
+But Tom did not wait for the rest. As he went out at the door he said:
+
+"Siddy, I'll lick you for that."
+
+In a safe place Tom examined two large needles which were thrust into
+the lapels of his jacket, and had thread bound about them--one needle
+carried white thread and the other black. He said:
+
+"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
+she sews it with white, and sometimes she sews it with black. I wish to
+geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
+I bet you I'll lam Sid for that. I'll learn him!"
+
+He was not the Model Boy of the village. He knew the model boy very
+well though--and loathed him.
+
+Within two minutes, or even less, he had forgotten all his troubles.
+Not because his troubles were one whit less heavy and bitter to him
+than a man's are to a man, but because a new and powerful interest bore
+them down and drove them out of his mind for the time--just as men's
+misfortunes are forgotten in the excitement of new enterprises. This
+new interest was a valued novelty in whistling, which he had just
+acquired from a negro, and he was suffering to practise it undisturbed.
+It consisted in a peculiar bird-like turn, a sort of liquid warble,
+produced by touching the tongue to the roof of the mouth at short
+intervals in the midst of the music--the reader probably remembers how
+to do it, if he has ever been a boy. Diligence and attention soon gave
+him the knack of it, and he strode down the street with his mouth full
+of harmony and his soul full of gratitude. He felt much as an
+astronomer feels who has discovered a new planet--no doubt, as far as
+strong, deep, unalloyed pleasure is concerned, the advantage was with
+the boy, not the astronomer.
+
+The summer evenings were long. It was not dark, yet. Presently Tom
+checked his whistle. A stranger was before him--a boy a shade larger
+than himself. A new-comer of any age or either sex was an impressive
+curiosity in the poor little shabby village of St. Petersburg. This boy
+was well dressed, too--well dressed on a week-day. This was simply
+astounding. His cap was a dainty thing, his close-buttoned blue cloth
+roundabout was new and natty, and so were his pantaloons. He had shoes
+on--and it was only Friday. He even wore a necktie, a bright bit of
+ribbon. He had a citified air about him that ate into Tom's vitals. The
+more Tom stared at the splendid marvel, the higher he turned up his
+nose at his finery and the shabbier and shabbier his own outfit seemed
+to him to grow. Neither boy spoke. If one moved, the other moved--but
+only sidewise, in a circle; they kept face to face and eye to eye all
+the time. Finally Tom said:
+
+"I can lick you!"
+
+"I'd like to see you try it."
+
+"Well, I can do it."
+
+"No you can't, either."
+
+"Yes I can."
+
+"No you can't."
+
+"I can."
+
+"You can't."
+
+"Can!"
+
+"Can't!"
+
+An uncomfortable pause. Then Tom said:
+
+"What's your name?"
+
+"'Tisn't any of your business, maybe."
+
+"Well I 'low I'll MAKE it my business."
+
+"Well why don't you?"
+
+"If you say much, I will."
+
+"Much--much--MUCH. There now."
+
+"Oh, you think you're mighty smart, DON'T you? I could lick you with
+one hand tied behind me, if I wanted to."
+
+"Well why don't you DO it? You SAY you can do it."
+
+"Well I WILL, if you fool with me."
+
+"Oh yes--I've seen whole families in the same fix."
+
+"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
+
+"You can lump that hat if you don't like it. I dare you to knock it
+off--and anybody that'll take a dare will suck eggs."
+
+"You're a liar!"
+
+"You're another."
+
+"You're a fighting liar and dasn't take it up."
+
+"Aw--take a walk!"
+
+"Say--if you give me much more of your sass I'll take and bounce a
+rock off'n your head."
+
+"Oh, of COURSE you will."
+
+"Well I WILL."
+
+"Well why don't you DO it then? What do you keep SAYING you will for?
+Why don't you DO it? It's because you're afraid."
+
+"I AIN'T afraid."
+
+"You are."
+
+"I ain't."
+
+"You are."
+
+Another pause, and more eying and sidling around each other. Presently
+they were shoulder to shoulder. Tom said:
+
+"Get away from here!"
+
+"Go away yourself!"
+
+"I won't."
+
+"I won't either."
+
+So they stood, each with a foot placed at an angle as a brace, and
+both shoving with might and main, and glowering at each other with
+hate. But neither could get an advantage. After struggling till both
+were hot and flushed, each relaxed his strain with watchful caution,
+and Tom said:
+
+"You're a coward and a pup. I'll tell my big brother on you, and he
+can thrash you with his little finger, and I'll make him do it, too."
+
+"What do I care for your big brother? I've got a brother that's bigger
+than he is--and what's more, he can throw him over that fence, too."
+[Both brothers were imaginary.]
+
+"That's a lie."
+
+"YOUR saying so don't make it so."
+
+Tom drew a line in the dust with his big toe, and said:
+
+"I dare you to step over that, and I'll lick you till you can't stand
+up. Anybody that'll take a dare will steal sheep."
+
+The new boy stepped over promptly, and said:
+
+"Now you said you'd do it, now let's see you do it."
+
+"Don't you crowd me now; you better look out."
+
+"Well, you SAID you'd do it--why don't you do it?"
+
+"By jingo! for two cents I WILL do it."
+
+The new boy took two broad coppers out of his pocket and held them out
+with derision. Tom struck them to the ground. In an instant both boys
+were rolling and tumbling in the dirt, gripped together like cats; and
+for the space of a minute they tugged and tore at each other's hair and
+clothes, punched and scratched each other's nose, and covered
+themselves with dust and glory. Presently the confusion took form, and
+through the fog of battle Tom appeared, seated astride the new boy, and
+pounding him with his fists. "Holler 'nuff!" said he.
+
+The boy only struggled to free himself. He was crying--mainly from rage.
+
+"Holler 'nuff!"--and the pounding went on.
+
+At last the stranger got out a smothered "'Nuff!" and Tom let him up
+and said:
+
+"Now that'll learn you. Better look out who you're fooling with next
+time."
+
+The new boy went off brushing the dust from his clothes, sobbing,
+snuffling, and occasionally looking back and shaking his head and
+threatening what he would do to Tom the "next time he caught him out."
+To which Tom responded with jeers, and started off in high feather, and
+as soon as his back was turned the new boy snatched up a stone, threw
+it and hit him between the shoulders and then turned tail and ran like
+an antelope. Tom chased the traitor home, and thus found out where he
+lived. He then held a position at the gate for some time, daring the
+enemy to come outside, but the enemy only made faces at him through the
+window and declined. At last the enemy's mother appeared, and called
+Tom a bad, vicious, vulgar child, and ordered him away. So he went
+away; but he said he "'lowed" to "lay" for that boy.
+
+He got home pretty late that night, and when he climbed cautiously in
+at the window, he uncovered an ambuscade, in the person of his aunt;
+and when she saw the state his clothes were in her resolution to turn
+his Saturday holiday into captivity at hard labor became adamantine in
+its firmness.
+
+
+
+CHAPTER II
+
+SATURDAY morning was come, and all the summer world was bright and
+fresh, and brimming with life. There was a song in every heart; and if
+the heart was young the music issued at the lips. There was cheer in
+every face and a spring in every step. The locust-trees were in bloom
+and the fragrance of the blossoms filled the air. Cardiff Hill, beyond
+the village and above it, was green with vegetation and it lay just far
+enough away to seem a Delectable Land, dreamy, reposeful, and inviting.
+
+Tom appeared on the sidewalk with a bucket of whitewash and a
+long-handled brush. He surveyed the fence, and all gladness left him and
+a deep melancholy settled down upon his spirit. Thirty yards of board
+fence nine feet high. Life to him seemed hollow, and existence but a
+burden. Sighing, he dipped his brush and passed it along the topmost
+plank; repeated the operation; did it again; compared the insignificant
+whitewashed streak with the far-reaching continent of unwhitewashed
+fence, and sat down on a tree-box discouraged. Jim came skipping out at
+the gate with a tin pail, and singing Buffalo Gals. Bringing water from
+the town pump had always been hateful work in Tom's eyes, before, but
+now it did not strike him so. He remembered that there was company at
+the pump. White, mulatto, and negro boys and girls were always there
+waiting their turns, resting, trading playthings, quarrelling,
+fighting, skylarking. And he remembered that although the pump was only
+a hundred and fifty yards off, Jim never got back with a bucket of
+water under an hour--and even then somebody generally had to go after
+him. Tom said:
+
+"Say, Jim, I'll fetch the water if you'll whitewash some."
+
+Jim shook his head and said:
+
+"Can't, Mars Tom. Ole missis, she tole me I got to go an' git dis
+water an' not stop foolin' roun' wid anybody. She say she spec' Mars
+Tom gwine to ax me to whitewash, an' so she tole me go 'long an' 'tend
+to my own business--she 'lowed SHE'D 'tend to de whitewashin'."
+
+"Oh, never you mind what she said, Jim. That's the way she always
+talks. Gimme the bucket--I won't be gone only a a minute. SHE won't
+ever know."
+
+"Oh, I dasn't, Mars Tom. Ole missis she'd take an' tar de head off'n
+me. 'Deed she would."
+
+"SHE! She never licks anybody--whacks 'em over the head with her
+thimble--and who cares for that, I'd like to know. She talks awful, but
+talk don't hurt--anyways it don't if she don't cry. Jim, I'll give you
+a marvel. I'll give you a white alley!"
+
+Jim began to waver.
+
+"White alley, Jim! And it's a bully taw."
+
+"My! Dat's a mighty gay marvel, I tell you! But Mars Tom I's powerful
+'fraid ole missis--"
+
+"And besides, if you will I'll show you my sore toe."
+
+Jim was only human--this attraction was too much for him. He put down
+his pail, took the white alley, and bent over the toe with absorbing
+interest while the bandage was being unwound. In another moment he was
+flying down the street with his pail and a tingling rear, Tom was
+whitewashing with vigor, and Aunt Polly was retiring from the field
+with a slipper in her hand and triumph in her eye.
+
+But Tom's energy did not last. He began to think of the fun he had
+planned for this day, and his sorrows multiplied. Soon the free boys
+would come tripping along on all sorts of delicious expeditions, and
+they would make a world of fun of him for having to work--the very
+thought of it burnt him like fire. He got out his worldly wealth and
+examined it--bits of toys, marbles, and trash; enough to buy an
+exchange of WORK, maybe, but not half enough to buy so much as half an
+hour of pure freedom. So he returned his straitened means to his
+pocket, and gave up the idea of trying to buy the boys. At this dark
+and hopeless moment an inspiration burst upon him! Nothing less than a
+great, magnificent inspiration.
+
+He took up his brush and went tranquilly to work. Ben Rogers hove in
+sight presently--the very boy, of all boys, whose ridicule he had been
+dreading. Ben's gait was the hop-skip-and-jump--proof enough that his
+heart was light and his anticipations high. He was eating an apple, and
+giving a long, melodious whoop, at intervals, followed by a deep-toned
+ding-dong-dong, ding-dong-dong, for he was personating a steamboat. As
+he drew near, he slackened speed, took the middle of the street, leaned
+far over to starboard and rounded to ponderously and with laborious
+pomp and circumstance--for he was personating the Big Missouri, and
+considered himself to be drawing nine feet of water. He was boat and
+captain and engine-bells combined, so he had to imagine himself
+standing on his own hurricane-deck giving the orders and executing them:
+
+"Stop her, sir! Ting-a-ling-ling!" The headway ran almost out, and he
+drew up slowly toward the sidewalk.
+
+"Ship up to back! Ting-a-ling-ling!" His arms straightened and
+stiffened down his sides.
+
+"Set her back on the stabboard! Ting-a-ling-ling! Chow! ch-chow-wow!
+Chow!" His right hand, meantime, describing stately circles--for it was
+representing a forty-foot wheel.
+
+"Let her go back on the labboard! Ting-a-lingling! Chow-ch-chow-chow!"
+The left hand began to describe circles.
+
+"Stop the stabboard! Ting-a-ling-ling! Stop the labboard! Come ahead
+on the stabboard! Stop her! Let your outside turn over slow!
+Ting-a-ling-ling! Chow-ow-ow! Get out that head-line! LIVELY now!
+Come--out with your spring-line--what're you about there! Take a turn
+round that stump with the bight of it! Stand by that stage, now--let her
+go! Done with the engines, sir! Ting-a-ling-ling! SH'T! S'H'T! SH'T!"
+(trying the gauge-cocks).
+
+Tom went on whitewashing--paid no attention to the steamboat. Ben
+stared a moment and then said: "Hi-YI! YOU'RE up a stump, ain't you!"
+
+No answer. Tom surveyed his last touch with the eye of an artist, then
+he gave his brush another gentle sweep and surveyed the result, as
+before. Ben ranged up alongside of him. Tom's mouth watered for the
+apple, but he stuck to his work. Ben said:
+
+"Hello, old chap, you got to work, hey?"
+
+Tom wheeled suddenly and said:
+
+"Why, it's you, Ben! I warn't noticing."
+
+"Say--I'm going in a-swimming, I am. Don't you wish you could? But of
+course you'd druther WORK--wouldn't you? Course you would!"
+
+Tom contemplated the boy a bit, and said:
+
+"What do you call work?"
+
+"Why, ain't THAT work?"
+
+Tom resumed his whitewashing, and answered carelessly:
+
+"Well, maybe it is, and maybe it ain't. All I know, is, it suits Tom
+Sawyer."
+
+"Oh come, now, you don't mean to let on that you LIKE it?"
+
+The brush continued to move.
+
+"Like it? Well, I don't see why I oughtn't to like it. Does a boy get
+a chance to whitewash a fence every day?"
+
+That put the thing in a new light. Ben stopped nibbling his apple. Tom
+swept his brush daintily back and forth--stepped back to note the
+effect--added a touch here and there--criticised the effect again--Ben
+watching every move and getting more and more interested, more and more
+absorbed. Presently he said:
+
+"Say, Tom, let ME whitewash a little."
+
+Tom considered, was about to consent; but he altered his mind:
+
+"No--no--I reckon it wouldn't hardly do, Ben. You see, Aunt Polly's
+awful particular about this fence--right here on the street, you know
+--but if it was the back fence I wouldn't mind and SHE wouldn't. Yes,
+she's awful particular about this fence; it's got to be done very
+careful; I reckon there ain't one boy in a thousand, maybe two
+thousand, that can do it the way it's got to be done."
+
+"No--is that so? Oh come, now--lemme just try. Only just a little--I'd
+let YOU, if you was me, Tom."
+
+"Ben, I'd like to, honest injun; but Aunt Polly--well, Jim wanted to
+do it, but she wouldn't let him; Sid wanted to do it, and she wouldn't
+let Sid. Now don't you see how I'm fixed? If you was to tackle this
+fence and anything was to happen to it--"
+
+"Oh, shucks, I'll be just as careful. Now lemme try. Say--I'll give
+you the core of my apple."
+
+"Well, here--No, Ben, now don't. I'm afeard--"
+
+"I'll give you ALL of it!"
+
+Tom gave up the brush with reluctance in his face, but alacrity in his
+heart. And while the late steamer Big Missouri worked and sweated in
+the sun, the retired artist sat on a barrel in the shade close by,
+dangled his legs, munched his apple, and planned the slaughter of more
+innocents. There was no lack of material; boys happened along every
+little while; they came to jeer, but remained to whitewash. By the time
+Ben was fagged out, Tom had traded the next chance to Billy Fisher for
+a kite, in good repair; and when he played out, Johnny Miller bought in
+for a dead rat and a string to swing it with--and so on, and so on,
+hour after hour. And when the middle of the afternoon came, from being
+a poor poverty-stricken boy in the morning, Tom was literally rolling
+in wealth. He had besides the things before mentioned, twelve marbles,
+part of a jews-harp, a piece of blue bottle-glass to look through, a
+spool cannon, a key that wouldn't unlock anything, a fragment of chalk,
+a glass stopper of a decanter, a tin soldier, a couple of tadpoles, six
+fire-crackers, a kitten with only one eye, a brass doorknob, a
+dog-collar--but no dog--the handle of a knife, four pieces of
+orange-peel, and a dilapidated old window sash.
+
+He had had a nice, good, idle time all the while--plenty of company
+--and the fence had three coats of whitewash on it! If he hadn't run out
+of whitewash he would have bankrupted every boy in the village.
+
+Tom said to himself that it was not such a hollow world, after all. He
+had discovered a great law of human action, without knowing it--namely,
+that in order to make a man or a boy covet a thing, it is only
+necessary to make the thing difficult to attain. If he had been a great
+and wise philosopher, like the writer of this book, he would now have
+comprehended that Work consists of whatever a body is OBLIGED to do,
+and that Play consists of whatever a body is not obliged to do. And
+this would help him to understand why constructing artificial flowers
+or performing on a tread-mill is work, while rolling ten-pins or
+climbing Mont Blanc is only amusement. There are wealthy gentlemen in
+England who drive four-horse passenger-coaches twenty or thirty miles
+on a daily line, in the summer, because the privilege costs them
+considerable money; but if they were offered wages for the service,
+that would turn it into work and then they would resign.
+
+The boy mused awhile over the substantial change which had taken place
+in his worldly circumstances, and then wended toward headquarters to
+report.
+
+
+
+CHAPTER III
+
+TOM presented himself before Aunt Polly, who was sitting by an open
+window in a pleasant rearward apartment, which was bedroom,
+breakfast-room, dining-room, and library, combined. The balmy summer
+air, the restful quiet, the odor of the flowers, and the drowsing murmur
+of the bees had had their effect, and she was nodding over her knitting
+--for she had no company but the cat, and it was asleep in her lap. Her
+spectacles were propped up on her gray head for safety. She had thought
+that of course Tom had deserted long ago, and she wondered at seeing him
+place himself in her power again in this intrepid way. He said: "Mayn't
+I go and play now, aunt?"
+
+"What, a'ready? How much have you done?"
+
+"It's all done, aunt."
+
+"Tom, don't lie to me--I can't bear it."
+
+"I ain't, aunt; it IS all done."
+
+Aunt Polly placed small trust in such evidence. She went out to see
+for herself; and she would have been content to find twenty per cent.
+of Tom's statement true. When she found the entire fence whitewashed,
+and not only whitewashed but elaborately coated and recoated, and even
+a streak added to the ground, her astonishment was almost unspeakable.
+She said:
+
+"Well, I never! There's no getting round it, you can work when you're
+a mind to, Tom." And then she diluted the compliment by adding, "But
+it's powerful seldom you're a mind to, I'm bound to say. Well, go 'long
+and play; but mind you get back some time in a week, or I'll tan you."
+
+She was so overcome by the splendor of his achievement that she took
+him into the closet and selected a choice apple and delivered it to
+him, along with an improving lecture upon the added value and flavor a
+treat took to itself when it came without sin through virtuous effort.
+And while she closed with a happy Scriptural flourish, he "hooked" a
+doughnut.
+
+Then he skipped out, and saw Sid just starting up the outside stairway
+that led to the back rooms on the second floor. Clods were handy and
+the air was full of them in a twinkling. They raged around Sid like a
+hail-storm; and before Aunt Polly could collect her surprised faculties
+and sally to the rescue, six or seven clods had taken personal effect,
+and Tom was over the fence and gone. There was a gate, but as a general
+thing he was too crowded for time to make use of it. His soul was at
+peace, now that he had settled with Sid for calling attention to his
+black thread and getting him into trouble.
+
+Tom skirted the block, and came round into a muddy alley that led by
+the back of his aunt's cow-stable. He presently got safely beyond the
+reach of capture and punishment, and hastened toward the public square
+of the village, where two "military" companies of boys had met for
+conflict, according to previous appointment. Tom was General of one of
+these armies, Joe Harper (a bosom friend) General of the other. These
+two great commanders did not condescend to fight in person--that being
+better suited to the still smaller fry--but sat together on an eminence
+and conducted the field operations by orders delivered through
+aides-de-camp. Tom's army won a great victory, after a long and
+hard-fought battle. Then the dead were counted, prisoners exchanged,
+the terms of the next disagreement agreed upon, and the day for the
+necessary battle appointed; after which the armies fell into line and
+marched away, and Tom turned homeward alone.
+
+As he was passing by the house where Jeff Thatcher lived, he saw a new
+girl in the garden--a lovely little blue-eyed creature with yellow hair
+plaited into two long-tails, white summer frock and embroidered
+pantalettes. The fresh-crowned hero fell without firing a shot. A
+certain Amy Lawrence vanished out of his heart and left not even a
+memory of herself behind. He had thought he loved her to distraction;
+he had regarded his passion as adoration; and behold it was only a poor
+little evanescent partiality. He had been months winning her; she had
+confessed hardly a week ago; he had been the happiest and the proudest
+boy in the world only seven short days, and here in one instant of time
+she had gone out of his heart like a casual stranger whose visit is
+done.
+
+He worshipped this new angel with furtive eye, till he saw that she
+had discovered him; then he pretended he did not know she was present,
+and began to "show off" in all sorts of absurd boyish ways, in order to
+win her admiration. He kept up this grotesque foolishness for some
+time; but by-and-by, while he was in the midst of some dangerous
+gymnastic performances, he glanced aside and saw that the little girl
+was wending her way toward the house. Tom came up to the fence and
+leaned on it, grieving, and hoping she would tarry yet awhile longer.
+She halted a moment on the steps and then moved toward the door. Tom
+heaved a great sigh as she put her foot on the threshold. But his face
+lit up, right away, for she tossed a pansy over the fence a moment
+before she disappeared.
+
+The boy ran around and stopped within a foot or two of the flower, and
+then shaded his eyes with his hand and began to look down street as if
+he had discovered something of interest going on in that direction.
+Presently he picked up a straw and began trying to balance it on his
+nose, with his head tilted far back; and as he moved from side to side,
+in his efforts, he edged nearer and nearer toward the pansy; finally
+his bare foot rested upon it, his pliant toes closed upon it, and he
+hopped away with the treasure and disappeared round the corner. But
+only for a minute--only while he could button the flower inside his
+jacket, next his heart--or next his stomach, possibly, for he was not
+much posted in anatomy, and not hypercritical, anyway.
+
+He returned, now, and hung about the fence till nightfall, "showing
+off," as before; but the girl never exhibited herself again, though Tom
+comforted himself a little with the hope that she had been near some
+window, meantime, and been aware of his attentions. Finally he strode
+home reluctantly, with his poor head full of visions.
+
+All through supper his spirits were so high that his aunt wondered
+"what had got into the child." He took a good scolding about clodding
+Sid, and did not seem to mind it in the least. He tried to steal sugar
+under his aunt's very nose, and got his knuckles rapped for it. He said:
+
+"Aunt, you don't whack Sid when he takes it."
+
+"Well, Sid don't torment a body the way you do. You'd be always into
+that sugar if I warn't watching you."
+
+Presently she stepped into the kitchen, and Sid, happy in his
+immunity, reached for the sugar-bowl--a sort of glorying over Tom which
+was wellnigh unbearable. But Sid's fingers slipped and the bowl dropped
+and broke. Tom was in ecstasies. In such ecstasies that he even
+controlled his tongue and was silent. He said to himself that he would
+not speak a word, even when his aunt came in, but would sit perfectly
+still till she asked who did the mischief; and then he would tell, and
+there would be nothing so good in the world as to see that pet model
+"catch it." He was so brimful of exultation that he could hardly hold
+himself when the old lady came back and stood above the wreck
+discharging lightnings of wrath from over her spectacles. He said to
+himself, "Now it's coming!" And the next instant he was sprawling on
+the floor! The potent palm was uplifted to strike again when Tom cried
+out:
+
+"Hold on, now, what 'er you belting ME for?--Sid broke it!"
+
+Aunt Polly paused, perplexed, and Tom looked for healing pity. But
+when she got her tongue again, she only said:
+
+"Umf! Well, you didn't get a lick amiss, I reckon. You been into some
+other audacious mischief when I wasn't around, like enough."
+
+Then her conscience reproached her, and she yearned to say something
+kind and loving; but she judged that this would be construed into a
+confession that she had been in the wrong, and discipline forbade that.
+So she kept silence, and went about her affairs with a troubled heart.
+Tom sulked in a corner and exalted his woes. He knew that in her heart
+his aunt was on her knees to him, and he was morosely gratified by the
+consciousness of it. He would hang out no signals, he would take notice
+of none. He knew that a yearning glance fell upon him, now and then,
+through a film of tears, but he refused recognition of it. He pictured
+himself lying sick unto death and his aunt bending over him beseeching
+one little forgiving word, but he would turn his face to the wall, and
+die with that word unsaid. Ah, how would she feel then? And he pictured
+himself brought home from the river, dead, with his curls all wet, and
+his sore heart at rest. How she would throw herself upon him, and how
+her tears would fall like rain, and her lips pray God to give her back
+her boy and she would never, never abuse him any more! But he would lie
+there cold and white and make no sign--a poor little sufferer, whose
+griefs were at an end. He so worked upon his feelings with the pathos
+of these dreams, that he had to keep swallowing, he was so like to
+choke; and his eyes swam in a blur of water, which overflowed when he
+winked, and ran down and trickled from the end of his nose. And such a
+luxury to him was this petting of his sorrows, that he could not bear
+to have any worldly cheeriness or any grating delight intrude upon it;
+it was too sacred for such contact; and so, presently, when his cousin
+Mary danced in, all alive with the joy of seeing home again after an
+age-long visit of one week to the country, he got up and moved in
+clouds and darkness out at one door as she brought song and sunshine in
+at the other.
+
+He wandered far from the accustomed haunts of boys, and sought
+desolate places that were in harmony with his spirit. A log raft in the
+river invited him, and he seated himself on its outer edge and
+contemplated the dreary vastness of the stream, wishing, the while,
+that he could only be drowned, all at once and unconsciously, without
+undergoing the uncomfortable routine devised by nature. Then he thought
+of his flower. He got it out, rumpled and wilted, and it mightily
+increased his dismal felicity. He wondered if she would pity him if she
+knew? Would she cry, and wish that she had a right to put her arms
+around his neck and comfort him? Or would she turn coldly away like all
+the hollow world? This picture brought such an agony of pleasurable
+suffering that he worked it over and over again in his mind and set it
+up in new and varied lights, till he wore it threadbare. At last he
+rose up sighing and departed in the darkness.
+
+About half-past nine or ten o'clock he came along the deserted street
+to where the Adored Unknown lived; he paused a moment; no sound fell
+upon his listening ear; a candle was casting a dull glow upon the
+curtain of a second-story window. Was the sacred presence there? He
+climbed the fence, threaded his stealthy way through the plants, till
+he stood under that window; he looked up at it long, and with emotion;
+then he laid him down on the ground under it, disposing himself upon
+his back, with his hands clasped upon his breast and holding his poor
+wilted flower. And thus he would die--out in the cold world, with no
+shelter over his homeless head, no friendly hand to wipe the
+death-damps from his brow, no loving face to bend pityingly over him
+when the great agony came. And thus SHE would see him when she looked
+out upon the glad morning, and oh! would she drop one little tear upon
+his poor, lifeless form, would she heave one little sigh to see a bright
+young life so rudely blighted, so untimely cut down?
+
+The window went up, a maid-servant's discordant voice profaned the
+holy calm, and a deluge of water drenched the prone martyr's remains!
+
+The strangling hero sprang up with a relieving snort. There was a whiz
+as of a missile in the air, mingled with the murmur of a curse, a sound
+as of shivering glass followed, and a small, vague form went over the
+fence and shot away in the gloom.
+
+Not long after, as Tom, all undressed for bed, was surveying his
+drenched garments by the light of a tallow dip, Sid woke up; but if he
+had any dim idea of making any "references to allusions," he thought
+better of it and held his peace, for there was danger in Tom's eye.
+
+Tom turned in without the added vexation of prayers, and Sid made
+mental note of the omission.
+
+
+
+CHAPTER IV
+
+THE sun rose upon a tranquil world, and beamed down upon the peaceful
+village like a benediction. Breakfast over, Aunt Polly had family
+worship: it began with a prayer built from the ground up of solid
+courses of Scriptural quotations, welded together with a thin mortar of
+originality; and from the summit of this she delivered a grim chapter
+of the Mosaic Law, as from Sinai.
+
+Then Tom girded up his loins, so to speak, and went to work to "get
+his verses." Sid had learned his lesson days before. Tom bent all his
+energies to the memorizing of five verses, and he chose part of the
+Sermon on the Mount, because he could find no verses that were shorter.
+At the end of half an hour Tom had a vague general idea of his lesson,
+but no more, for his mind was traversing the whole field of human
+thought, and his hands were busy with distracting recreations. Mary
+took his book to hear him recite, and he tried to find his way through
+the fog:
+
+"Blessed are the--a--a--"
+
+"Poor"--
+
+"Yes--poor; blessed are the poor--a--a--"
+
+"In spirit--"
+
+"In spirit; blessed are the poor in spirit, for they--they--"
+
+"THEIRS--"
+
+"For THEIRS. Blessed are the poor in spirit, for theirs is the kingdom
+of heaven. Blessed are they that mourn, for they--they--"
+
+"Sh--"
+
+"For they--a--"
+
+"S, H, A--"
+
+"For they S, H--Oh, I don't know what it is!"
+
+"SHALL!"
+
+"Oh, SHALL! for they shall--for they shall--a--a--shall mourn--a--a--
+blessed are they that shall--they that--a--they that shall mourn, for
+they shall--a--shall WHAT? Why don't you tell me, Mary?--what do you
+want to be so mean for?"
+
+"Oh, Tom, you poor thick-headed thing, I'm not teasing you. I wouldn't
+do that. You must go and learn it again. Don't you be discouraged, Tom,
+you'll manage it--and if you do, I'll give you something ever so nice.
+There, now, that's a good boy."
+
+"All right! What is it, Mary, tell me what it is."
+
+"Never you mind, Tom. You know if I say it's nice, it is nice."
+
+"You bet you that's so, Mary. All right, I'll tackle it again."
+
+And he did "tackle it again"--and under the double pressure of
+curiosity and prospective gain he did it with such spirit that he
+accomplished a shining success. Mary gave him a brand-new "Barlow"
+knife worth twelve and a half cents; and the convulsion of delight that
+swept his system shook him to his foundations. True, the knife would
+not cut anything, but it was a "sure-enough" Barlow, and there was
+inconceivable grandeur in that--though where the Western boys ever got
+the idea that such a weapon could possibly be counterfeited to its
+injury is an imposing mystery and will always remain so, perhaps. Tom
+contrived to scarify the cupboard with it, and was arranging to begin
+on the bureau, when he was called off to dress for Sunday-school.
+
+Mary gave him a tin basin of water and a piece of soap, and he went
+outside the door and set the basin on a little bench there; then he
+dipped the soap in the water and laid it down; turned up his sleeves;
+poured out the water on the ground, gently, and then entered the
+kitchen and began to wipe his face diligently on the towel behind the
+door. But Mary removed the towel and said:
+
+"Now ain't you ashamed, Tom. You mustn't be so bad. Water won't hurt
+you."
+
+Tom was a trifle disconcerted. The basin was refilled, and this time
+he stood over it a little while, gathering resolution; took in a big
+breath and began. When he entered the kitchen presently, with both eyes
+shut and groping for the towel with his hands, an honorable testimony
+of suds and water was dripping from his face. But when he emerged from
+the towel, he was not yet satisfactory, for the clean territory stopped
+short at his chin and his jaws, like a mask; below and beyond this line
+there was a dark expanse of unirrigated soil that spread downward in
+front and backward around his neck. Mary took him in hand, and when she
+was done with him he was a man and a brother, without distinction of
+color, and his saturated hair was neatly brushed, and its short curls
+wrought into a dainty and symmetrical general effect. [He privately
+smoothed out the curls, with labor and difficulty, and plastered his
+hair close down to his head; for he held curls to be effeminate, and
+his own filled his life with bitterness.] Then Mary got out a suit of
+his clothing that had been used only on Sundays during two years--they
+were simply called his "other clothes"--and so by that we know the
+size of his wardrobe. The girl "put him to rights" after he had dressed
+himself; she buttoned his neat roundabout up to his chin, turned his
+vast shirt collar down over his shoulders, brushed him off and crowned
+him with his speckled straw hat. He now looked exceedingly improved and
+uncomfortable. He was fully as uncomfortable as he looked; for there
+was a restraint about whole clothes and cleanliness that galled him. He
+hoped that Mary would forget his shoes, but the hope was blighted; she
+coated them thoroughly with tallow, as was the custom, and brought them
+out. He lost his temper and said he was always being made to do
+everything he didn't want to do. But Mary said, persuasively:
+
+"Please, Tom--that's a good boy."
+
+So he got into the shoes snarling. Mary was soon ready, and the three
+children set out for Sunday-school--a place that Tom hated with his
+whole heart; but Sid and Mary were fond of it.
+
+Sabbath-school hours were from nine to half-past ten; and then church
+service. Two of the children always remained for the sermon
+voluntarily, and the other always remained too--for stronger reasons.
+The church's high-backed, uncushioned pews would seat about three
+hundred persons; the edifice was but a small, plain affair, with a sort
+of pine board tree-box on top of it for a steeple. At the door Tom
+dropped back a step and accosted a Sunday-dressed comrade:
+
+"Say, Billy, got a yaller ticket?"
+
+"Yes."
+
+"What'll you take for her?"
+
+"What'll you give?"
+
+"Piece of lickrish and a fish-hook."
+
+"Less see 'em."
+
+Tom exhibited. They were satisfactory, and the property changed hands.
+Then Tom traded a couple of white alleys for three red tickets, and
+some small trifle or other for a couple of blue ones. He waylaid other
+boys as they came, and went on buying tickets of various colors ten or
+fifteen minutes longer. He entered the church, now, with a swarm of
+clean and noisy boys and girls, proceeded to his seat and started a
+quarrel with the first boy that came handy. The teacher, a grave,
+elderly man, interfered; then turned his back a moment and Tom pulled a
+boy's hair in the next bench, and was absorbed in his book when the boy
+turned around; stuck a pin in another boy, presently, in order to hear
+him say "Ouch!" and got a new reprimand from his teacher. Tom's whole
+class were of a pattern--restless, noisy, and troublesome. When they
+came to recite their lessons, not one of them knew his verses
+perfectly, but had to be prompted all along. However, they worried
+through, and each got his reward--in small blue tickets, each with a
+passage of Scripture on it; each blue ticket was pay for two verses of
+the recitation. Ten blue tickets equalled a red one, and could be
+exchanged for it; ten red tickets equalled a yellow one; for ten yellow
+tickets the superintendent gave a very plainly bound Bible (worth forty
+cents in those easy times) to the pupil. How many of my readers would
+have the industry and application to memorize two thousand verses, even
+for a Dore Bible? And yet Mary had acquired two Bibles in this way--it
+was the patient work of two years--and a boy of German parentage had
+won four or five. He once recited three thousand verses without
+stopping; but the strain upon his mental faculties was too great, and
+he was little better than an idiot from that day forth--a grievous
+misfortune for the school, for on great occasions, before company, the
+superintendent (as Tom expressed it) had always made this boy come out
+and "spread himself." Only the older pupils managed to keep their
+tickets and stick to their tedious work long enough to get a Bible, and
+so the delivery of one of these prizes was a rare and noteworthy
+circumstance; the successful pupil was so great and conspicuous for
+that day that on the spot every scholar's heart was fired with a fresh
+ambition that often lasted a couple of weeks. It is possible that Tom's
+mental stomach had never really hungered for one of those prizes, but
+unquestionably his entire being had for many a day longed for the glory
+and the eclat that came with it.
+
+In due course the superintendent stood up in front of the pulpit, with
+a closed hymn-book in his hand and his forefinger inserted between its
+leaves, and commanded attention. When a Sunday-school superintendent
+makes his customary little speech, a hymn-book in the hand is as
+necessary as is the inevitable sheet of music in the hand of a singer
+who stands forward on the platform and sings a solo at a concert
+--though why, is a mystery: for neither the hymn-book nor the sheet of
+music is ever referred to by the sufferer. This superintendent was a
+slim creature of thirty-five, with a sandy goatee and short sandy hair;
+he wore a stiff standing-collar whose upper edge almost reached his
+ears and whose sharp points curved forward abreast the corners of his
+mouth--a fence that compelled a straight lookout ahead, and a turning
+of the whole body when a side view was required; his chin was propped
+on a spreading cravat which was as broad and as long as a bank-note,
+and had fringed ends; his boot toes were turned sharply up, in the
+fashion of the day, like sleigh-runners--an effect patiently and
+laboriously produced by the young men by sitting with their toes
+pressed against a wall for hours together. Mr. Walters was very earnest
+of mien, and very sincere and honest at heart; and he held sacred
+things and places in such reverence, and so separated them from worldly
+matters, that unconsciously to himself his Sunday-school voice had
+acquired a peculiar intonation which was wholly absent on week-days. He
+began after this fashion:
+
+"Now, children, I want you all to sit up just as straight and pretty
+as you can and give me all your attention for a minute or two. There
+--that is it. That is the way good little boys and girls should do. I see
+one little girl who is looking out of the window--I am afraid she
+thinks I am out there somewhere--perhaps up in one of the trees making
+a speech to the little birds. [Applausive titter.] I want to tell you
+how good it makes me feel to see so many bright, clean little faces
+assembled in a place like this, learning to do right and be good." And
+so forth and so on. It is not necessary to set down the rest of the
+oration. It was of a pattern which does not vary, and so it is familiar
+to us all.
+
+The latter third of the speech was marred by the resumption of fights
+and other recreations among certain of the bad boys, and by fidgetings
+and whisperings that extended far and wide, washing even to the bases
+of isolated and incorruptible rocks like Sid and Mary. But now every
+sound ceased suddenly, with the subsidence of Mr. Walters' voice, and
+the conclusion of the speech was received with a burst of silent
+gratitude.
+
+A good part of the whispering had been occasioned by an event which
+was more or less rare--the entrance of visitors: lawyer Thatcher,
+accompanied by a very feeble and aged man; a fine, portly, middle-aged
+gentleman with iron-gray hair; and a dignified lady who was doubtless
+the latter's wife. The lady was leading a child. Tom had been restless
+and full of chafings and repinings; conscience-smitten, too--he could
+not meet Amy Lawrence's eye, he could not brook her loving gaze. But
+when he saw this small new-comer his soul was all ablaze with bliss in
+a moment. The next moment he was "showing off" with all his might
+--cuffing boys, pulling hair, making faces--in a word, using every art
+that seemed likely to fascinate a girl and win her applause. His
+exaltation had but one alloy--the memory of his humiliation in this
+angel's garden--and that record in sand was fast washing out, under
+the waves of happiness that were sweeping over it now.
+
+The visitors were given the highest seat of honor, and as soon as Mr.
+Walters' speech was finished, he introduced them to the school. The
+middle-aged man turned out to be a prodigious personage--no less a one
+than the county judge--altogether the most august creation these
+children had ever looked upon--and they wondered what kind of material
+he was made of--and they half wanted to hear him roar, and were half
+afraid he might, too. He was from Constantinople, twelve miles away--so
+he had travelled, and seen the world--these very eyes had looked upon
+the county court-house--which was said to have a tin roof. The awe
+which these reflections inspired was attested by the impressive silence
+and the ranks of staring eyes. This was the great Judge Thatcher,
+brother of their own lawyer. Jeff Thatcher immediately went forward, to
+be familiar with the great man and be envied by the school. It would
+have been music to his soul to hear the whisperings:
+
+"Look at him, Jim! He's a going up there. Say--look! he's a going to
+shake hands with him--he IS shaking hands with him! By jings, don't you
+wish you was Jeff?"
+
+Mr. Walters fell to "showing off," with all sorts of official
+bustlings and activities, giving orders, delivering judgments,
+discharging directions here, there, everywhere that he could find a
+target. The librarian "showed off"--running hither and thither with his
+arms full of books and making a deal of the splutter and fuss that
+insect authority delights in. The young lady teachers "showed off"
+--bending sweetly over pupils that were lately being boxed, lifting
+pretty warning fingers at bad little boys and patting good ones
+lovingly. The young gentlemen teachers "showed off" with small
+scoldings and other little displays of authority and fine attention to
+discipline--and most of the teachers, of both sexes, found business up
+at the library, by the pulpit; and it was business that frequently had
+to be done over again two or three times (with much seeming vexation).
+The little girls "showed off" in various ways, and the little boys
+"showed off" with such diligence that the air was thick with paper wads
+and the murmur of scufflings. And above it all the great man sat and
+beamed a majestic judicial smile upon all the house, and warmed himself
+in the sun of his own grandeur--for he was "showing off," too.
+
+There was only one thing wanting to make Mr. Walters' ecstasy
+complete, and that was a chance to deliver a Bible-prize and exhibit a
+prodigy. Several pupils had a few yellow tickets, but none had enough
+--he had been around among the star pupils inquiring. He would have given
+worlds, now, to have that German lad back again with a sound mind.
+
+And now at this moment, when hope was dead, Tom Sawyer came forward
+with nine yellow tickets, nine red tickets, and ten blue ones, and
+demanded a Bible. This was a thunderbolt out of a clear sky. Walters
+was not expecting an application from this source for the next ten
+years. But there was no getting around it--here were the certified
+checks, and they were good for their face. Tom was therefore elevated
+to a place with the Judge and the other elect, and the great news was
+announced from headquarters. It was the most stunning surprise of the
+decade, and so profound was the sensation that it lifted the new hero
+up to the judicial one's altitude, and the school had two marvels to
+gaze upon in place of one. The boys were all eaten up with envy--but
+those that suffered the bitterest pangs were those who perceived too
+late that they themselves had contributed to this hated splendor by
+trading tickets to Tom for the wealth he had amassed in selling
+whitewashing privileges. These despised themselves, as being the dupes
+of a wily fraud, a guileful snake in the grass.
+
+The prize was delivered to Tom with as much effusion as the
+superintendent could pump up under the circumstances; but it lacked
+somewhat of the true gush, for the poor fellow's instinct taught him
+that there was a mystery here that could not well bear the light,
+perhaps; it was simply preposterous that this boy had warehoused two
+thousand sheaves of Scriptural wisdom on his premises--a dozen would
+strain his capacity, without a doubt.
+
+Amy Lawrence was proud and glad, and she tried to make Tom see it in
+her face--but he wouldn't look. She wondered; then she was just a grain
+troubled; next a dim suspicion came and went--came again; she watched;
+a furtive glance told her worlds--and then her heart broke, and she was
+jealous, and angry, and the tears came and she hated everybody. Tom
+most of all (she thought).
+
+Tom was introduced to the Judge; but his tongue was tied, his breath
+would hardly come, his heart quaked--partly because of the awful
+greatness of the man, but mainly because he was her parent. He would
+have liked to fall down and worship him, if it were in the dark. The
+Judge put his hand on Tom's head and called him a fine little man, and
+asked him what his name was. The boy stammered, gasped, and got it out:
+
+"Tom."
+
+"Oh, no, not Tom--it is--"
+
+"Thomas."
+
+"Ah, that's it. I thought there was more to it, maybe. That's very
+well. But you've another one I daresay, and you'll tell it to me, won't
+you?"
+
+"Tell the gentleman your other name, Thomas," said Walters, "and say
+sir. You mustn't forget your manners."
+
+"Thomas Sawyer--sir."
+
+"That's it! That's a good boy. Fine boy. Fine, manly little fellow.
+Two thousand verses is a great many--very, very great many. And you
+never can be sorry for the trouble you took to learn them; for
+knowledge is worth more than anything there is in the world; it's what
+makes great men and good men; you'll be a great man and a good man
+yourself, some day, Thomas, and then you'll look back and say, It's all
+owing to the precious Sunday-school privileges of my boyhood--it's all
+owing to my dear teachers that taught me to learn--it's all owing to
+the good superintendent, who encouraged me, and watched over me, and
+gave me a beautiful Bible--a splendid elegant Bible--to keep and have
+it all for my own, always--it's all owing to right bringing up! That is
+what you will say, Thomas--and you wouldn't take any money for those
+two thousand verses--no indeed you wouldn't. And now you wouldn't mind
+telling me and this lady some of the things you've learned--no, I know
+you wouldn't--for we are proud of little boys that learn. Now, no
+doubt you know the names of all the twelve disciples. Won't you tell us
+the names of the first two that were appointed?"
+
+Tom was tugging at a button-hole and looking sheepish. He blushed,
+now, and his eyes fell. Mr. Walters' heart sank within him. He said to
+himself, it is not possible that the boy can answer the simplest
+question--why DID the Judge ask him? Yet he felt obliged to speak up
+and say:
+
+"Answer the gentleman, Thomas--don't be afraid."
+
+Tom still hung fire.
+
+"Now I know you'll tell me," said the lady. "The names of the first
+two disciples were--"
+
+"DAVID AND GOLIAH!"
+
+Let us draw the curtain of charity over the rest of the scene.
+
+
+
+CHAPTER V
+
+ABOUT half-past ten the cracked bell of the small church began to
+ring, and presently the people began to gather for the morning sermon.
+The Sunday-school children distributed themselves about the house and
+occupied pews with their parents, so as to be under supervision. Aunt
+Polly came, and Tom and Sid and Mary sat with her--Tom being placed
+next the aisle, in order that he might be as far away from the open
+window and the seductive outside summer scenes as possible. The crowd
+filed up the aisles: the aged and needy postmaster, who had seen better
+days; the mayor and his wife--for they had a mayor there, among other
+unnecessaries; the justice of the peace; the widow Douglass, fair,
+smart, and forty, a generous, good-hearted soul and well-to-do, her
+hill mansion the only palace in the town, and the most hospitable and
+much the most lavish in the matter of festivities that St. Petersburg
+could boast; the bent and venerable Major and Mrs. Ward; lawyer
+Riverson, the new notable from a distance; next the belle of the
+village, followed by a troop of lawn-clad and ribbon-decked young
+heart-breakers; then all the young clerks in town in a body--for they
+had stood in the vestibule sucking their cane-heads, a circling wall of
+oiled and simpering admirers, till the last girl had run their gantlet;
+and last of all came the Model Boy, Willie Mufferson, taking as heedful
+care of his mother as if she were cut glass. He always brought his
+mother to church, and was the pride of all the matrons. The boys all
+hated him, he was so good. And besides, he had been "thrown up to them"
+so much. His white handkerchief was hanging out of his pocket behind, as
+usual on Sundays--accidentally. Tom had no handkerchief, and he looked
+upon boys who had as snobs.
+
+The congregation being fully assembled, now, the bell rang once more,
+to warn laggards and stragglers, and then a solemn hush fell upon the
+church which was only broken by the tittering and whispering of the
+choir in the gallery. The choir always tittered and whispered all
+through service. There was once a church choir that was not ill-bred,
+but I have forgotten where it was, now. It was a great many years ago,
+and I can scarcely remember anything about it, but I think it was in
+some foreign country.
+
+The minister gave out the hymn, and read it through with a relish, in
+a peculiar style which was much admired in that part of the country.
+His voice began on a medium key and climbed steadily up till it reached
+a certain point, where it bore with strong emphasis upon the topmost
+word and then plunged down as if from a spring-board:
+
+  Shall I be car-ri-ed toe the skies, on flow'ry BEDS of ease,
+
+  Whilst others fight to win the prize, and sail thro' BLOODY seas?
+
+He was regarded as a wonderful reader. At church "sociables" he was
+always called upon to read poetry; and when he was through, the ladies
+would lift up their hands and let them fall helplessly in their laps,
+and "wall" their eyes, and shake their heads, as much as to say, "Words
+cannot express it; it is too beautiful, TOO beautiful for this mortal
+earth."
+
+After the hymn had been sung, the Rev. Mr. Sprague turned himself into
+a bulletin-board, and read off "notices" of meetings and societies and
+things till it seemed that the list would stretch out to the crack of
+doom--a queer custom which is still kept up in America, even in cities,
+away here in this age of abundant newspapers. Often, the less there is
+to justify a traditional custom, the harder it is to get rid of it.
+
+And now the minister prayed. A good, generous prayer it was, and went
+into details: it pleaded for the church, and the little children of the
+church; for the other churches of the village; for the village itself;
+for the county; for the State; for the State officers; for the United
+States; for the churches of the United States; for Congress; for the
+President; for the officers of the Government; for poor sailors, tossed
+by stormy seas; for the oppressed millions groaning under the heel of
+European monarchies and Oriental despotisms; for such as have the light
+and the good tidings, and yet have not eyes to see nor ears to hear
+withal; for the heathen in the far islands of the sea; and closed with
+a supplication that the words he was about to speak might find grace
+and favor, and be as seed sown in fertile ground, yielding in time a
+grateful harvest of good. Amen.
+
+There was a rustling of dresses, and the standing congregation sat
+down. The boy whose history this book relates did not enjoy the prayer,
+he only endured it--if he even did that much. He was restive all
+through it; he kept tally of the details of the prayer, unconsciously
+--for he was not listening, but he knew the ground of old, and the
+clergyman's regular route over it--and when a little trifle of new
+matter was interlarded, his ear detected it and his whole nature
+resented it; he considered additions unfair, and scoundrelly. In the
+midst of the prayer a fly had lit on the back of the pew in front of
+him and tortured his spirit by calmly rubbing its hands together,
+embracing its head with its arms, and polishing it so vigorously that
+it seemed to almost part company with the body, and the slender thread
+of a neck was exposed to view; scraping its wings with its hind legs
+and smoothing them to its body as if they had been coat-tails; going
+through its whole toilet as tranquilly as if it knew it was perfectly
+safe. As indeed it was; for as sorely as Tom's hands itched to grab for
+it they did not dare--he believed his soul would be instantly destroyed
+if he did such a thing while the prayer was going on. But with the
+closing sentence his hand began to curve and steal forward; and the
+instant the "Amen" was out the fly was a prisoner of war. His aunt
+detected the act and made him let it go.
+
+The minister gave out his text and droned along monotonously through
+an argument that was so prosy that many a head by and by began to nod
+--and yet it was an argument that dealt in limitless fire and brimstone
+and thinned the predestined elect down to a company so small as to be
+hardly worth the saving. Tom counted the pages of the sermon; after
+church he always knew how many pages there had been, but he seldom knew
+anything else about the discourse. However, this time he was really
+interested for a little while. The minister made a grand and moving
+picture of the assembling together of the world's hosts at the
+millennium when the lion and the lamb should lie down together and a
+little child should lead them. But the pathos, the lesson, the moral of
+the great spectacle were lost upon the boy; he only thought of the
+conspicuousness of the principal character before the on-looking
+nations; his face lit with the thought, and he said to himself that he
+wished he could be that child, if it was a tame lion.
+
+Now he lapsed into suffering again, as the dry argument was resumed.
+Presently he bethought him of a treasure he had and got it out. It was
+a large black beetle with formidable jaws--a "pinchbug," he called it.
+It was in a percussion-cap box. The first thing the beetle did was to
+take him by the finger. A natural fillip followed, the beetle went
+floundering into the aisle and lit on its back, and the hurt finger
+went into the boy's mouth. The beetle lay there working its helpless
+legs, unable to turn over. Tom eyed it, and longed for it; but it was
+safe out of his reach. Other people uninterested in the sermon found
+relief in the beetle, and they eyed it too. Presently a vagrant poodle
+dog came idling along, sad at heart, lazy with the summer softness and
+the quiet, weary of captivity, sighing for change. He spied the beetle;
+the drooping tail lifted and wagged. He surveyed the prize; walked
+around it; smelt at it from a safe distance; walked around it again;
+grew bolder, and took a closer smell; then lifted his lip and made a
+gingerly snatch at it, just missing it; made another, and another;
+began to enjoy the diversion; subsided to his stomach with the beetle
+between his paws, and continued his experiments; grew weary at last,
+and then indifferent and absent-minded. His head nodded, and little by
+little his chin descended and touched the enemy, who seized it. There
+was a sharp yelp, a flirt of the poodle's head, and the beetle fell a
+couple of yards away, and lit on its back once more. The neighboring
+spectators shook with a gentle inward joy, several faces went behind
+fans and handkerchiefs, and Tom was entirely happy. The dog looked
+foolish, and probably felt so; but there was resentment in his heart,
+too, and a craving for revenge. So he went to the beetle and began a
+wary attack on it again; jumping at it from every point of a circle,
+lighting with his fore-paws within an inch of the creature, making even
+closer snatches at it with his teeth, and jerking his head till his
+ears flapped again. But he grew tired once more, after a while; tried
+to amuse himself with a fly but found no relief; followed an ant
+around, with his nose close to the floor, and quickly wearied of that;
+yawned, sighed, forgot the beetle entirely, and sat down on it. Then
+there was a wild yelp of agony and the poodle went sailing up the
+aisle; the yelps continued, and so did the dog; he crossed the house in
+front of the altar; he flew down the other aisle; he crossed before the
+doors; he clamored up the home-stretch; his anguish grew with his
+progress, till presently he was but a woolly comet moving in its orbit
+with the gleam and the speed of light. At last the frantic sufferer
+sheered from its course, and sprang into its master's lap; he flung it
+out of the window, and the voice of distress quickly thinned away and
+died in the distance.
+
+By this time the whole church was red-faced and suffocating with
+suppressed laughter, and the sermon had come to a dead standstill. The
+discourse was resumed presently, but it went lame and halting, all
+possibility of impressiveness being at an end; for even the gravest
+sentiments were constantly being received with a smothered burst of
+unholy mirth, under cover of some remote pew-back, as if the poor
+parson had said a rarely facetious thing. It was a genuine relief to
+the whole congregation when the ordeal was over and the benediction
+pronounced.
+
+Tom Sawyer went home quite cheerful, thinking to himself that there
+was some satisfaction about divine service when there was a bit of
+variety in it. He had but one marring thought; he was willing that the
+dog should play with his pinchbug, but he did not think it was upright
+in him to carry it off.
+
+
+
+CHAPTER VI
+
+MONDAY morning found Tom Sawyer miserable. Monday morning always found
+him so--because it began another week's slow suffering in school. He
+generally began that day with wishing he had had no intervening
+holiday, it made the going into captivity and fetters again so much
+more odious.
+
+Tom lay thinking. Presently it occurred to him that he wished he was
+sick; then he could stay home from school. Here was a vague
+possibility. He canvassed his system. No ailment was found, and he
+investigated again. This time he thought he could detect colicky
+symptoms, and he began to encourage them with considerable hope. But
+they soon grew feeble, and presently died wholly away. He reflected
+further. Suddenly he discovered something. One of his upper front teeth
+was loose. This was lucky; he was about to begin to groan, as a
+"starter," as he called it, when it occurred to him that if he came
+into court with that argument, his aunt would pull it out, and that
+would hurt. So he thought he would hold the tooth in reserve for the
+present, and seek further. Nothing offered for some little time, and
+then he remembered hearing the doctor tell about a certain thing that
+laid up a patient for two or three weeks and threatened to make him
+lose a finger. So the boy eagerly drew his sore toe from under the
+sheet and held it up for inspection. But now he did not know the
+necessary symptoms. However, it seemed well worth while to chance it,
+so he fell to groaning with considerable spirit.
+
+But Sid slept on unconscious.
+
+Tom groaned louder, and fancied that he began to feel pain in the toe.
+
+No result from Sid.
+
+Tom was panting with his exertions by this time. He took a rest and
+then swelled himself up and fetched a succession of admirable groans.
+
+Sid snored on.
+
+Tom was aggravated. He said, "Sid, Sid!" and shook him. This course
+worked well, and Tom began to groan again. Sid yawned, stretched, then
+brought himself up on his elbow with a snort, and began to stare at
+Tom. Tom went on groaning. Sid said:
+
+"Tom! Say, Tom!" [No response.] "Here, Tom! TOM! What is the matter,
+Tom?" And he shook him and looked in his face anxiously.
+
+Tom moaned out:
+
+"Oh, don't, Sid. Don't joggle me."
+
+"Why, what's the matter, Tom? I must call auntie."
+
+"No--never mind. It'll be over by and by, maybe. Don't call anybody."
+
+"But I must! DON'T groan so, Tom, it's awful. How long you been this
+way?"
+
+"Hours. Ouch! Oh, don't stir so, Sid, you'll kill me."
+
+"Tom, why didn't you wake me sooner? Oh, Tom, DON'T! It makes my
+flesh crawl to hear you. Tom, what is the matter?"
+
+"I forgive you everything, Sid. [Groan.] Everything you've ever done
+to me. When I'm gone--"
+
+"Oh, Tom, you ain't dying, are you? Don't, Tom--oh, don't. Maybe--"
+
+"I forgive everybody, Sid. [Groan.] Tell 'em so, Sid. And Sid, you
+give my window-sash and my cat with one eye to that new girl that's
+come to town, and tell her--"
+
+But Sid had snatched his clothes and gone. Tom was suffering in
+reality, now, so handsomely was his imagination working, and so his
+groans had gathered quite a genuine tone.
+
+Sid flew down-stairs and said:
+
+"Oh, Aunt Polly, come! Tom's dying!"
+
+"Dying!"
+
+"Yes'm. Don't wait--come quick!"
+
+"Rubbage! I don't believe it!"
+
+But she fled up-stairs, nevertheless, with Sid and Mary at her heels.
+And her face grew white, too, and her lip trembled. When she reached
+the bedside she gasped out:
+
+"You, Tom! Tom, what's the matter with you?"
+
+"Oh, auntie, I'm--"
+
+"What's the matter with you--what is the matter with you, child?"
+
+"Oh, auntie, my sore toe's mortified!"
+
+The old lady sank down into a chair and laughed a little, then cried a
+little, then did both together. This restored her and she said:
+
+"Tom, what a turn you did give me. Now you shut up that nonsense and
+climb out of this."
+
+The groans ceased and the pain vanished from the toe. The boy felt a
+little foolish, and he said:
+
+"Aunt Polly, it SEEMED mortified, and it hurt so I never minded my
+tooth at all."
+
+"Your tooth, indeed! What's the matter with your tooth?"
+
+"One of them's loose, and it aches perfectly awful."
+
+"There, there, now, don't begin that groaning again. Open your mouth.
+Well--your tooth IS loose, but you're not going to die about that.
+Mary, get me a silk thread, and a chunk of fire out of the kitchen."
+
+Tom said:
+
+"Oh, please, auntie, don't pull it out. It don't hurt any more. I wish
+I may never stir if it does. Please don't, auntie. I don't want to stay
+home from school."
+
+"Oh, you don't, don't you? So all this row was because you thought
+you'd get to stay home from school and go a-fishing? Tom, Tom, I love
+you so, and you seem to try every way you can to break my old heart
+with your outrageousness." By this time the dental instruments were
+ready. The old lady made one end of the silk thread fast to Tom's tooth
+with a loop and tied the other to the bedpost. Then she seized the
+chunk of fire and suddenly thrust it almost into the boy's face. The
+tooth hung dangling by the bedpost, now.
+
+But all trials bring their compensations. As Tom wended to school
+after breakfast, he was the envy of every boy he met because the gap in
+his upper row of teeth enabled him to expectorate in a new and
+admirable way. He gathered quite a following of lads interested in the
+exhibition; and one that had cut his finger and had been a centre of
+fascination and homage up to this time, now found himself suddenly
+without an adherent, and shorn of his glory. His heart was heavy, and
+he said with a disdain which he did not feel that it wasn't anything to
+spit like Tom Sawyer; but another boy said, "Sour grapes!" and he
+wandered away a dismantled hero.
+
+Shortly Tom came upon the juvenile pariah of the village, Huckleberry
+Finn, son of the town drunkard. Huckleberry was cordially hated and
+dreaded by all the mothers of the town, because he was idle and lawless
+and vulgar and bad--and because all their children admired him so, and
+delighted in his forbidden society, and wished they dared to be like
+him. Tom was like the rest of the respectable boys, in that he envied
+Huckleberry his gaudy outcast condition, and was under strict orders
+not to play with him. So he played with him every time he got a chance.
+Huckleberry was always dressed in the cast-off clothes of full-grown
+men, and they were in perennial bloom and fluttering with rags. His hat
+was a vast ruin with a wide crescent lopped out of its brim; his coat,
+when he wore one, hung nearly to his heels and had the rearward buttons
+far down the back; but one suspender supported his trousers; the seat
+of the trousers bagged low and contained nothing, the fringed legs
+dragged in the dirt when not rolled up.
+
+Huckleberry came and went, at his own free will. He slept on doorsteps
+in fine weather and in empty hogsheads in wet; he did not have to go to
+school or to church, or call any being master or obey anybody; he could
+go fishing or swimming when and where he chose, and stay as long as it
+suited him; nobody forbade him to fight; he could sit up as late as he
+pleased; he was always the first boy that went barefoot in the spring
+and the last to resume leather in the fall; he never had to wash, nor
+put on clean clothes; he could swear wonderfully. In a word, everything
+that goes to make life precious that boy had. So thought every
+harassed, hampered, respectable boy in St. Petersburg.
+
+Tom hailed the romantic outcast:
+
+"Hello, Huckleberry!"
+
+"Hello yourself, and see how you like it."
+
+"What's that you got?"
+
+"Dead cat."
+
+"Lemme see him, Huck. My, he's pretty stiff. Where'd you get him?"
+
+"Bought him off'n a boy."
+
+"What did you give?"
+
+"I give a blue ticket and a bladder that I got at the slaughter-house."
+
+"Where'd you get the blue ticket?"
+
+"Bought it off'n Ben Rogers two weeks ago for a hoop-stick."
+
+"Say--what is dead cats good for, Huck?"
+
+"Good for? Cure warts with."
+
+"No! Is that so? I know something that's better."
+
+"I bet you don't. What is it?"
+
+"Why, spunk-water."
+
+"Spunk-water! I wouldn't give a dern for spunk-water."
+
+"You wouldn't, wouldn't you? D'you ever try it?"
+
+"No, I hain't. But Bob Tanner did."
+
+"Who told you so!"
+
+"Why, he told Jeff Thatcher, and Jeff told Johnny Baker, and Johnny
+told Jim Hollis, and Jim told Ben Rogers, and Ben told a nigger, and
+the nigger told me. There now!"
+
+"Well, what of it? They'll all lie. Leastways all but the nigger. I
+don't know HIM. But I never see a nigger that WOULDN'T lie. Shucks! Now
+you tell me how Bob Tanner done it, Huck."
+
+"Why, he took and dipped his hand in a rotten stump where the
+rain-water was."
+
+"In the daytime?"
+
+"Certainly."
+
+"With his face to the stump?"
+
+"Yes. Least I reckon so."
+
+"Did he say anything?"
+
+"I don't reckon he did. I don't know."
+
+"Aha! Talk about trying to cure warts with spunk-water such a blame
+fool way as that! Why, that ain't a-going to do any good. You got to go
+all by yourself, to the middle of the woods, where you know there's a
+spunk-water stump, and just as it's midnight you back up against the
+stump and jam your hand in and say:
+
+  'Barley-corn, barley-corn, injun-meal shorts,
+   Spunk-water, spunk-water, swaller these warts,'
+
+and then walk away quick, eleven steps, with your eyes shut, and then
+turn around three times and walk home without speaking to anybody.
+Because if you speak the charm's busted."
+
+"Well, that sounds like a good way; but that ain't the way Bob Tanner
+done."
+
+"No, sir, you can bet he didn't, becuz he's the wartiest boy in this
+town; and he wouldn't have a wart on him if he'd knowed how to work
+spunk-water. I've took off thousands of warts off of my hands that way,
+Huck. I play with frogs so much that I've always got considerable many
+warts. Sometimes I take 'em off with a bean."
+
+"Yes, bean's good. I've done that."
+
+"Have you? What's your way?"
+
+"You take and split the bean, and cut the wart so as to get some
+blood, and then you put the blood on one piece of the bean and take and
+dig a hole and bury it 'bout midnight at the crossroads in the dark of
+the moon, and then you burn up the rest of the bean. You see that piece
+that's got the blood on it will keep drawing and drawing, trying to
+fetch the other piece to it, and so that helps the blood to draw the
+wart, and pretty soon off she comes."
+
+"Yes, that's it, Huck--that's it; though when you're burying it if you
+say 'Down bean; off wart; come no more to bother me!' it's better.
+That's the way Joe Harper does, and he's been nearly to Coonville and
+most everywheres. But say--how do you cure 'em with dead cats?"
+
+"Why, you take your cat and go and get in the graveyard 'long about
+midnight when somebody that was wicked has been buried; and when it's
+midnight a devil will come, or maybe two or three, but you can't see
+'em, you can only hear something like the wind, or maybe hear 'em talk;
+and when they're taking that feller away, you heave your cat after 'em
+and say, 'Devil follow corpse, cat follow devil, warts follow cat, I'm
+done with ye!' That'll fetch ANY wart."
+
+"Sounds right. D'you ever try it, Huck?"
+
+"No, but old Mother Hopkins told me."
+
+"Well, I reckon it's so, then. Becuz they say she's a witch."
+
+"Say! Why, Tom, I KNOW she is. She witched pap. Pap says so his own
+self. He come along one day, and he see she was a-witching him, so he
+took up a rock, and if she hadn't dodged, he'd a got her. Well, that
+very night he rolled off'n a shed wher' he was a layin drunk, and broke
+his arm."
+
+"Why, that's awful. How did he know she was a-witching him?"
+
+"Lord, pap can tell, easy. Pap says when they keep looking at you
+right stiddy, they're a-witching you. Specially if they mumble. Becuz
+when they mumble they're saying the Lord's Prayer backards."
+
+"Say, Hucky, when you going to try the cat?"
+
+"To-night. I reckon they'll come after old Hoss Williams to-night."
+
+"But they buried him Saturday. Didn't they get him Saturday night?"
+
+"Why, how you talk! How could their charms work till midnight?--and
+THEN it's Sunday. Devils don't slosh around much of a Sunday, I don't
+reckon."
+
+"I never thought of that. That's so. Lemme go with you?"
+
+"Of course--if you ain't afeard."
+
+"Afeard! 'Tain't likely. Will you meow?"
+
+"Yes--and you meow back, if you get a chance. Last time, you kep' me
+a-meowing around till old Hays went to throwing rocks at me and says
+'Dern that cat!' and so I hove a brick through his window--but don't
+you tell."
+
+"I won't. I couldn't meow that night, becuz auntie was watching me,
+but I'll meow this time. Say--what's that?"
+
+"Nothing but a tick."
+
+"Where'd you get him?"
+
+"Out in the woods."
+
+"What'll you take for him?"
+
+"I don't know. I don't want to sell him."
+
+"All right. It's a mighty small tick, anyway."
+
+"Oh, anybody can run a tick down that don't belong to them. I'm
+satisfied with it. It's a good enough tick for me."
+
+"Sho, there's ticks a plenty. I could have a thousand of 'em if I
+wanted to."
+
+"Well, why don't you? Becuz you know mighty well you can't. This is a
+pretty early tick, I reckon. It's the first one I've seen this year."
+
+"Say, Huck--I'll give you my tooth for him."
+
+"Less see it."
+
+Tom got out a bit of paper and carefully unrolled it. Huckleberry
+viewed it wistfully. The temptation was very strong. At last he said:
+
+"Is it genuwyne?"
+
+Tom lifted his lip and showed the vacancy.
+
+"Well, all right," said Huckleberry, "it's a trade."
+
+Tom enclosed the tick in the percussion-cap box that had lately been
+the pinchbug's prison, and the boys separated, each feeling wealthier
+than before.
+
+When Tom reached the little isolated frame schoolhouse, he strode in
+briskly, with the manner of one who had come with all honest speed.
+He hung his hat on a peg and flung himself into his seat with
+business-like alacrity. The master, throned on high in his great
+splint-bottom arm-chair, was dozing, lulled by the drowsy hum of study.
+The interruption roused him.
+
+"Thomas Sawyer!"
+
+Tom knew that when his name was pronounced in full, it meant trouble.
+
+"Sir!"
+
+"Come up here. Now, sir, why are you late again, as usual?"
+
+Tom was about to take refuge in a lie, when he saw two long tails of
+yellow hair hanging down a back that he recognized by the electric
+sympathy of love; and by that form was THE ONLY VACANT PLACE on the
+girls' side of the schoolhouse. He instantly said:
+
+"I STOPPED TO TALK WITH HUCKLEBERRY FINN!"
+
+The master's pulse stood still, and he stared helplessly. The buzz of
+study ceased. The pupils wondered if this foolhardy boy had lost his
+mind. The master said:
+
+"You--you did what?"
+
+"Stopped to talk with Huckleberry Finn."
+
+There was no mistaking the words.
+
+"Thomas Sawyer, this is the most astounding confession I have ever
+listened to. No mere ferule will answer for this offence. Take off your
+jacket."
+
+The master's arm performed until it was tired and the stock of
+switches notably diminished. Then the order followed:
+
+"Now, sir, go and sit with the girls! And let this be a warning to you."
+
+The titter that rippled around the room appeared to abash the boy, but
+in reality that result was caused rather more by his worshipful awe of
+his unknown idol and the dread pleasure that lay in his high good
+fortune. He sat down upon the end of the pine bench and the girl
+hitched herself away from him with a toss of her head. Nudges and winks
+and whispers traversed the room, but Tom sat still, with his arms upon
+the long, low desk before him, and seemed to study his book.
+
+By and by attention ceased from him, and the accustomed school murmur
+rose upon the dull air once more. Presently the boy began to steal
+furtive glances at the girl. She observed it, "made a mouth" at him and
+gave him the back of her head for the space of a minute. When she
+cautiously faced around again, a peach lay before her. She thrust it
+away. Tom gently put it back. She thrust it away again, but with less
+animosity. Tom patiently returned it to its place. Then she let it
+remain. Tom scrawled on his slate, "Please take it--I got more." The
+girl glanced at the words, but made no sign. Now the boy began to draw
+something on the slate, hiding his work with his left hand. For a time
+the girl refused to notice; but her human curiosity presently began to
+manifest itself by hardly perceptible signs. The boy worked on,
+apparently unconscious. The girl made a sort of noncommittal attempt to
+see, but the boy did not betray that he was aware of it. At last she
+gave in and hesitatingly whispered:
+
+"Let me see it."
+
+Tom partly uncovered a dismal caricature of a house with two gable
+ends to it and a corkscrew of smoke issuing from the chimney. Then the
+girl's interest began to fasten itself upon the work and she forgot
+everything else. When it was finished, she gazed a moment, then
+whispered:
+
+"It's nice--make a man."
+
+The artist erected a man in the front yard, that resembled a derrick.
+He could have stepped over the house; but the girl was not
+hypercritical; she was satisfied with the monster, and whispered:
+
+"It's a beautiful man--now make me coming along."
+
+Tom drew an hour-glass with a full moon and straw limbs to it and
+armed the spreading fingers with a portentous fan. The girl said:
+
+"It's ever so nice--I wish I could draw."
+
+"It's easy," whispered Tom, "I'll learn you."
+
+"Oh, will you? When?"
+
+"At noon. Do you go home to dinner?"
+
+"I'll stay if you will."
+
+"Good--that's a whack. What's your name?"
+
+"Becky Thatcher. What's yours? Oh, I know. It's Thomas Sawyer."
+
+"That's the name they lick me by. I'm Tom when I'm good. You call me
+Tom, will you?"
+
+"Yes."
+
+Now Tom began to scrawl something on the slate, hiding the words from
+the girl. But she was not backward this time. She begged to see. Tom
+said:
+
+"Oh, it ain't anything."
+
+"Yes it is."
+
+"No it ain't. You don't want to see."
+
+"Yes I do, indeed I do. Please let me."
+
+"You'll tell."
+
+"No I won't--deed and deed and double deed won't."
+
+"You won't tell anybody at all? Ever, as long as you live?"
+
+"No, I won't ever tell ANYbody. Now let me."
+
+"Oh, YOU don't want to see!"
+
+"Now that you treat me so, I WILL see." And she put her small hand
+upon his and a little scuffle ensued, Tom pretending to resist in
+earnest but letting his hand slip by degrees till these words were
+revealed: "I LOVE YOU."
+
+"Oh, you bad thing!" And she hit his hand a smart rap, but reddened
+and looked pleased, nevertheless.
+
+Just at this juncture the boy felt a slow, fateful grip closing on his
+ear, and a steady lifting impulse. In that wise he was borne across the
+house and deposited in his own seat, under a peppering fire of giggles
+from the whole school. Then the master stood over him during a few
+awful moments, and finally moved away to his throne without saying a
+word. But although Tom's ear tingled, his heart was jubilant.
+
+As the school quieted down Tom made an honest effort to study, but the
+turmoil within him was too great. In turn he took his place in the
+reading class and made a botch of it; then in the geography class and
+turned lakes into mountains, mountains into rivers, and rivers into
+continents, till chaos was come again; then in the spelling class, and
+got "turned down," by a succession of mere baby words, till he brought
+up at the foot and yielded up the pewter medal which he had worn with
+ostentation for months.
+
+
+
+CHAPTER VII
+
+THE harder Tom tried to fasten his mind on his book, the more his
+ideas wandered. So at last, with a sigh and a yawn, he gave it up. It
+seemed to him that the noon recess would never come. The air was
+utterly dead. There was not a breath stirring. It was the sleepiest of
+sleepy days. The drowsing murmur of the five and twenty studying
+scholars soothed the soul like the spell that is in the murmur of bees.
+Away off in the flaming sunshine, Cardiff Hill lifted its soft green
+sides through a shimmering veil of heat, tinted with the purple of
+distance; a few birds floated on lazy wing high in the air; no other
+living thing was visible but some cows, and they were asleep. Tom's
+heart ached to be free, or else to have something of interest to do to
+pass the dreary time. His hand wandered into his pocket and his face
+lit up with a glow of gratitude that was prayer, though he did not know
+it. Then furtively the percussion-cap box came out. He released the
+tick and put him on the long flat desk. The creature probably glowed
+with a gratitude that amounted to prayer, too, at this moment, but it
+was premature: for when he started thankfully to travel off, Tom turned
+him aside with a pin and made him take a new direction.
+
+Tom's bosom friend sat next him, suffering just as Tom had been, and
+now he was deeply and gratefully interested in this entertainment in an
+instant. This bosom friend was Joe Harper. The two boys were sworn
+friends all the week, and embattled enemies on Saturdays. Joe took a
+pin out of his lapel and began to assist in exercising the prisoner.
+The sport grew in interest momently. Soon Tom said that they were
+interfering with each other, and neither getting the fullest benefit of
+the tick. So he put Joe's slate on the desk and drew a line down the
+middle of it from top to bottom.
+
+"Now," said he, "as long as he is on your side you can stir him up and
+I'll let him alone; but if you let him get away and get on my side,
+you're to leave him alone as long as I can keep him from crossing over."
+
+"All right, go ahead; start him up."
+
+The tick escaped from Tom, presently, and crossed the equator. Joe
+harassed him awhile, and then he got away and crossed back again. This
+change of base occurred often. While one boy was worrying the tick with
+absorbing interest, the other would look on with interest as strong,
+the two heads bowed together over the slate, and the two souls dead to
+all things else. At last luck seemed to settle and abide with Joe. The
+tick tried this, that, and the other course, and got as excited and as
+anxious as the boys themselves, but time and again just as he would
+have victory in his very grasp, so to speak, and Tom's fingers would be
+twitching to begin, Joe's pin would deftly head him off, and keep
+possession. At last Tom could stand it no longer. The temptation was
+too strong. So he reached out and lent a hand with his pin. Joe was
+angry in a moment. Said he:
+
+"Tom, you let him alone."
+
+"I only just want to stir him up a little, Joe."
+
+"No, sir, it ain't fair; you just let him alone."
+
+"Blame it, I ain't going to stir him much."
+
+"Let him alone, I tell you."
+
+"I won't!"
+
+"You shall--he's on my side of the line."
+
+"Look here, Joe Harper, whose is that tick?"
+
+"I don't care whose tick he is--he's on my side of the line, and you
+sha'n't touch him."
+
+"Well, I'll just bet I will, though. He's my tick and I'll do what I
+blame please with him, or die!"
+
+A tremendous whack came down on Tom's shoulders, and its duplicate on
+Joe's; and for the space of two minutes the dust continued to fly from
+the two jackets and the whole school to enjoy it. The boys had been too
+absorbed to notice the hush that had stolen upon the school awhile
+before when the master came tiptoeing down the room and stood over
+them. He had contemplated a good part of the performance before he
+contributed his bit of variety to it.
+
+When school broke up at noon, Tom flew to Becky Thatcher, and
+whispered in her ear:
+
+"Put on your bonnet and let on you're going home; and when you get to
+the corner, give the rest of 'em the slip, and turn down through the
+lane and come back. I'll go the other way and come it over 'em the same
+way."
+
+So the one went off with one group of scholars, and the other with
+another. In a little while the two met at the bottom of the lane, and
+when they reached the school they had it all to themselves. Then they
+sat together, with a slate before them, and Tom gave Becky the pencil
+and held her hand in his, guiding it, and so created another surprising
+house. When the interest in art began to wane, the two fell to talking.
+Tom was swimming in bliss. He said:
+
+"Do you love rats?"
+
+"No! I hate them!"
+
+"Well, I do, too--LIVE ones. But I mean dead ones, to swing round your
+head with a string."
+
+"No, I don't care for rats much, anyway. What I like is chewing-gum."
+
+"Oh, I should say so! I wish I had some now."
+
+"Do you? I've got some. I'll let you chew it awhile, but you must give
+it back to me."
+
+That was agreeable, so they chewed it turn about, and dangled their
+legs against the bench in excess of contentment.
+
+"Was you ever at a circus?" said Tom.
+
+"Yes, and my pa's going to take me again some time, if I'm good."
+
+"I been to the circus three or four times--lots of times. Church ain't
+shucks to a circus. There's things going on at a circus all the time.
+I'm going to be a clown in a circus when I grow up."
+
+"Oh, are you! That will be nice. They're so lovely, all spotted up."
+
+"Yes, that's so. And they get slathers of money--most a dollar a day,
+Ben Rogers says. Say, Becky, was you ever engaged?"
+
+"What's that?"
+
+"Why, engaged to be married."
+
+"No."
+
+"Would you like to?"
+
+"I reckon so. I don't know. What is it like?"
+
+"Like? Why it ain't like anything. You only just tell a boy you won't
+ever have anybody but him, ever ever ever, and then you kiss and that's
+all. Anybody can do it."
+
+"Kiss? What do you kiss for?"
+
+"Why, that, you know, is to--well, they always do that."
+
+"Everybody?"
+
+"Why, yes, everybody that's in love with each other. Do you remember
+what I wrote on the slate?"
+
+"Ye--yes."
+
+"What was it?"
+
+"I sha'n't tell you."
+
+"Shall I tell YOU?"
+
+"Ye--yes--but some other time."
+
+"No, now."
+
+"No, not now--to-morrow."
+
+"Oh, no, NOW. Please, Becky--I'll whisper it, I'll whisper it ever so
+easy."
+
+Becky hesitating, Tom took silence for consent, and passed his arm
+about her waist and whispered the tale ever so softly, with his mouth
+close to her ear. And then he added:
+
+"Now you whisper it to me--just the same."
+
+She resisted, for a while, and then said:
+
+"You turn your face away so you can't see, and then I will. But you
+mustn't ever tell anybody--WILL you, Tom? Now you won't, WILL you?"
+
+"No, indeed, indeed I won't. Now, Becky."
+
+He turned his face away. She bent timidly around till her breath
+stirred his curls and whispered, "I--love--you!"
+
+Then she sprang away and ran around and around the desks and benches,
+with Tom after her, and took refuge in a corner at last, with her
+little white apron to her face. Tom clasped her about her neck and
+pleaded:
+
+"Now, Becky, it's all done--all over but the kiss. Don't you be afraid
+of that--it ain't anything at all. Please, Becky." And he tugged at her
+apron and the hands.
+
+By and by she gave up, and let her hands drop; her face, all glowing
+with the struggle, came up and submitted. Tom kissed the red lips and
+said:
+
+"Now it's all done, Becky. And always after this, you know, you ain't
+ever to love anybody but me, and you ain't ever to marry anybody but
+me, ever never and forever. Will you?"
+
+"No, I'll never love anybody but you, Tom, and I'll never marry
+anybody but you--and you ain't to ever marry anybody but me, either."
+
+"Certainly. Of course. That's PART of it. And always coming to school
+or when we're going home, you're to walk with me, when there ain't
+anybody looking--and you choose me and I choose you at parties, because
+that's the way you do when you're engaged."
+
+"It's so nice. I never heard of it before."
+
+"Oh, it's ever so gay! Why, me and Amy Lawrence--"
+
+The big eyes told Tom his blunder and he stopped, confused.
+
+"Oh, Tom! Then I ain't the first you've ever been engaged to!"
+
+The child began to cry. Tom said:
+
+"Oh, don't cry, Becky, I don't care for her any more."
+
+"Yes, you do, Tom--you know you do."
+
+Tom tried to put his arm about her neck, but she pushed him away and
+turned her face to the wall, and went on crying. Tom tried again, with
+soothing words in his mouth, and was repulsed again. Then his pride was
+up, and he strode away and went outside. He stood about, restless and
+uneasy, for a while, glancing at the door, every now and then, hoping
+she would repent and come to find him. But she did not. Then he began
+to feel badly and fear that he was in the wrong. It was a hard struggle
+with him to make new advances, now, but he nerved himself to it and
+entered. She was still standing back there in the corner, sobbing, with
+her face to the wall. Tom's heart smote him. He went to her and stood a
+moment, not knowing exactly how to proceed. Then he said hesitatingly:
+
+"Becky, I--I don't care for anybody but you."
+
+No reply--but sobs.
+
+"Becky"--pleadingly. "Becky, won't you say something?"
+
+More sobs.
+
+Tom got out his chiefest jewel, a brass knob from the top of an
+andiron, and passed it around her so that she could see it, and said:
+
+"Please, Becky, won't you take it?"
+
+She struck it to the floor. Then Tom marched out of the house and over
+the hills and far away, to return to school no more that day. Presently
+Becky began to suspect. She ran to the door; he was not in sight; she
+flew around to the play-yard; he was not there. Then she called:
+
+"Tom! Come back, Tom!"
+
+She listened intently, but there was no answer. She had no companions
+but silence and loneliness. So she sat down to cry again and upbraid
+herself; and by this time the scholars began to gather again, and she
+had to hide her griefs and still her broken heart and take up the cross
+of a long, dreary, aching afternoon, with none among the strangers
+about her to exchange sorrows with.
+
+
+
+CHAPTER VIII
+
+TOM dodged hither and thither through lanes until he was well out of
+the track of returning scholars, and then fell into a moody jog. He
+crossed a small "branch" two or three times, because of a prevailing
+juvenile superstition that to cross water baffled pursuit. Half an hour
+later he was disappearing behind the Douglas mansion on the summit of
+Cardiff Hill, and the schoolhouse was hardly distinguishable away off
+in the valley behind him. He entered a dense wood, picked his pathless
+way to the centre of it, and sat down on a mossy spot under a spreading
+oak. There was not even a zephyr stirring; the dead noonday heat had
+even stilled the songs of the birds; nature lay in a trance that was
+broken by no sound but the occasional far-off hammering of a
+woodpecker, and this seemed to render the pervading silence and sense
+of loneliness the more profound. The boy's soul was steeped in
+melancholy; his feelings were in happy accord with his surroundings. He
+sat long with his elbows on his knees and his chin in his hands,
+meditating. It seemed to him that life was but a trouble, at best, and
+he more than half envied Jimmy Hodges, so lately released; it must be
+very peaceful, he thought, to lie and slumber and dream forever and
+ever, with the wind whispering through the trees and caressing the
+grass and the flowers over the grave, and nothing to bother and grieve
+about, ever any more. If he only had a clean Sunday-school record he
+could be willing to go, and be done with it all. Now as to this girl.
+What had he done? Nothing. He had meant the best in the world, and been
+treated like a dog--like a very dog. She would be sorry some day--maybe
+when it was too late. Ah, if he could only die TEMPORARILY!
+
+But the elastic heart of youth cannot be compressed into one
+constrained shape long at a time. Tom presently began to drift
+insensibly back into the concerns of this life again. What if he turned
+his back, now, and disappeared mysteriously? What if he went away--ever
+so far away, into unknown countries beyond the seas--and never came
+back any more! How would she feel then! The idea of being a clown
+recurred to him now, only to fill him with disgust. For frivolity and
+jokes and spotted tights were an offense, when they intruded themselves
+upon a spirit that was exalted into the vague august realm of the
+romantic. No, he would be a soldier, and return after long years, all
+war-worn and illustrious. No--better still, he would join the Indians,
+and hunt buffaloes and go on the warpath in the mountain ranges and the
+trackless great plains of the Far West, and away in the future come
+back a great chief, bristling with feathers, hideous with paint, and
+prance into Sunday-school, some drowsy summer morning, with a
+bloodcurdling war-whoop, and sear the eyeballs of all his companions
+with unappeasable envy. But no, there was something gaudier even than
+this. He would be a pirate! That was it! NOW his future lay plain
+before him, and glowing with unimaginable splendor. How his name would
+fill the world, and make people shudder! How gloriously he would go
+plowing the dancing seas, in his long, low, black-hulled racer, the
+Spirit of the Storm, with his grisly flag flying at the fore! And at
+the zenith of his fame, how he would suddenly appear at the old village
+and stalk into church, brown and weather-beaten, in his black velvet
+doublet and trunks, his great jack-boots, his crimson sash, his belt
+bristling with horse-pistols, his crime-rusted cutlass at his side, his
+slouch hat with waving plumes, his black flag unfurled, with the skull
+and crossbones on it, and hear with swelling ecstasy the whisperings,
+"It's Tom Sawyer the Pirate!--the Black Avenger of the Spanish Main!"
+
+Yes, it was settled; his career was determined. He would run away from
+home and enter upon it. He would start the very next morning. Therefore
+he must now begin to get ready. He would collect his resources
+together. He went to a rotten log near at hand and began to dig under
+one end of it with his Barlow knife. He soon struck wood that sounded
+hollow. He put his hand there and uttered this incantation impressively:
+
+"What hasn't come here, come! What's here, stay here!"
+
+Then he scraped away the dirt, and exposed a pine shingle. He took it
+up and disclosed a shapely little treasure-house whose bottom and sides
+were of shingles. In it lay a marble. Tom's astonishment was boundless!
+He scratched his head with a perplexed air, and said:
+
+"Well, that beats anything!"
+
+Then he tossed the marble away pettishly, and stood cogitating. The
+truth was, that a superstition of his had failed, here, which he and
+all his comrades had always looked upon as infallible. If you buried a
+marble with certain necessary incantations, and left it alone a
+fortnight, and then opened the place with the incantation he had just
+used, you would find that all the marbles you had ever lost had
+gathered themselves together there, meantime, no matter how widely they
+had been separated. But now, this thing had actually and unquestionably
+failed. Tom's whole structure of faith was shaken to its foundations.
+He had many a time heard of this thing succeeding but never of its
+failing before. It did not occur to him that he had tried it several
+times before, himself, but could never find the hiding-places
+afterward. He puzzled over the matter some time, and finally decided
+that some witch had interfered and broken the charm. He thought he
+would satisfy himself on that point; so he searched around till he
+found a small sandy spot with a little funnel-shaped depression in it.
+He laid himself down and put his mouth close to this depression and
+called--
+
+"Doodle-bug, doodle-bug, tell me what I want to know! Doodle-bug,
+doodle-bug, tell me what I want to know!"
+
+The sand began to work, and presently a small black bug appeared for a
+second and then darted under again in a fright.
+
+"He dasn't tell! So it WAS a witch that done it. I just knowed it."
+
+He well knew the futility of trying to contend against witches, so he
+gave up discouraged. But it occurred to him that he might as well have
+the marble he had just thrown away, and therefore he went and made a
+patient search for it. But he could not find it. Now he went back to
+his treasure-house and carefully placed himself just as he had been
+standing when he tossed the marble away; then he took another marble
+from his pocket and tossed it in the same way, saying:
+
+"Brother, go find your brother!"
+
+He watched where it stopped, and went there and looked. But it must
+have fallen short or gone too far; so he tried twice more. The last
+repetition was successful. The two marbles lay within a foot of each
+other.
+
+Just here the blast of a toy tin trumpet came faintly down the green
+aisles of the forest. Tom flung off his jacket and trousers, turned a
+suspender into a belt, raked away some brush behind the rotten log,
+disclosing a rude bow and arrow, a lath sword and a tin trumpet, and in
+a moment had seized these things and bounded away, barelegged, with
+fluttering shirt. He presently halted under a great elm, blew an
+answering blast, and then began to tiptoe and look warily out, this way
+and that. He said cautiously--to an imaginary company:
+
+"Hold, my merry men! Keep hid till I blow."
+
+Now appeared Joe Harper, as airily clad and elaborately armed as Tom.
+Tom called:
+
+"Hold! Who comes here into Sherwood Forest without my pass?"
+
+"Guy of Guisborne wants no man's pass. Who art thou that--that--"
+
+"Dares to hold such language," said Tom, prompting--for they talked
+"by the book," from memory.
+
+"Who art thou that dares to hold such language?"
+
+"I, indeed! I am Robin Hood, as thy caitiff carcase soon shall know."
+
+"Then art thou indeed that famous outlaw? Right gladly will I dispute
+with thee the passes of the merry wood. Have at thee!"
+
+They took their lath swords, dumped their other traps on the ground,
+struck a fencing attitude, foot to foot, and began a grave, careful
+combat, "two up and two down." Presently Tom said:
+
+"Now, if you've got the hang, go it lively!"
+
+So they "went it lively," panting and perspiring with the work. By and
+by Tom shouted:
+
+"Fall! fall! Why don't you fall?"
+
+"I sha'n't! Why don't you fall yourself? You're getting the worst of
+it."
+
+"Why, that ain't anything. I can't fall; that ain't the way it is in
+the book. The book says, 'Then with one back-handed stroke he slew poor
+Guy of Guisborne.' You're to turn around and let me hit you in the
+back."
+
+There was no getting around the authorities, so Joe turned, received
+the whack and fell.
+
+"Now," said Joe, getting up, "you got to let me kill YOU. That's fair."
+
+"Why, I can't do that, it ain't in the book."
+
+"Well, it's blamed mean--that's all."
+
+"Well, say, Joe, you can be Friar Tuck or Much the miller's son, and
+lam me with a quarter-staff; or I'll be the Sheriff of Nottingham and
+you be Robin Hood a little while and kill me."
+
+This was satisfactory, and so these adventures were carried out. Then
+Tom became Robin Hood again, and was allowed by the treacherous nun to
+bleed his strength away through his neglected wound. And at last Joe,
+representing a whole tribe of weeping outlaws, dragged him sadly forth,
+gave his bow into his feeble hands, and Tom said, "Where this arrow
+falls, there bury poor Robin Hood under the greenwood tree." Then he
+shot the arrow and fell back and would have died, but he lit on a
+nettle and sprang up too gaily for a corpse.
+
+The boys dressed themselves, hid their accoutrements, and went off
+grieving that there were no outlaws any more, and wondering what modern
+civilization could claim to have done to compensate for their loss.
+They said they would rather be outlaws a year in Sherwood Forest than
+President of the United States forever.
+
+
+
+CHAPTER IX
+
+AT half-past nine, that night, Tom and Sid were sent to bed, as usual.
+They said their prayers, and Sid was soon asleep. Tom lay awake and
+waited, in restless impatience. When it seemed to him that it must be
+nearly daylight, he heard the clock strike ten! This was despair. He
+would have tossed and fidgeted, as his nerves demanded, but he was
+afraid he might wake Sid. So he lay still, and stared up into the dark.
+Everything was dismally still. By and by, out of the stillness, little,
+scarcely perceptible noises began to emphasize themselves. The ticking
+of the clock began to bring itself into notice. Old beams began to
+crack mysteriously. The stairs creaked faintly. Evidently spirits were
+abroad. A measured, muffled snore issued from Aunt Polly's chamber. And
+now the tiresome chirping of a cricket that no human ingenuity could
+locate, began. Next the ghastly ticking of a deathwatch in the wall at
+the bed's head made Tom shudder--it meant that somebody's days were
+numbered. Then the howl of a far-off dog rose on the night air, and was
+answered by a fainter howl from a remoter distance. Tom was in an
+agony. At last he was satisfied that time had ceased and eternity
+begun; he began to doze, in spite of himself; the clock chimed eleven,
+but he did not hear it. And then there came, mingling with his
+half-formed dreams, a most melancholy caterwauling. The raising of a
+neighboring window disturbed him. A cry of "Scat! you devil!" and the
+crash of an empty bottle against the back of his aunt's woodshed
+brought him wide awake, and a single minute later he was dressed and
+out of the window and creeping along the roof of the "ell" on all
+fours. He "meow'd" with caution once or twice, as he went; then jumped
+to the roof of the woodshed and thence to the ground. Huckleberry Finn
+was there, with his dead cat. The boys moved off and disappeared in the
+gloom. At the end of half an hour they were wading through the tall
+grass of the graveyard.
+
+It was a graveyard of the old-fashioned Western kind. It was on a
+hill, about a mile and a half from the village. It had a crazy board
+fence around it, which leaned inward in places, and outward the rest of
+the time, but stood upright nowhere. Grass and weeds grew rank over the
+whole cemetery. All the old graves were sunken in, there was not a
+tombstone on the place; round-topped, worm-eaten boards staggered over
+the graves, leaning for support and finding none. "Sacred to the memory
+of" So-and-So had been painted on them once, but it could no longer
+have been read, on the most of them, now, even if there had been light.
+
+A faint wind moaned through the trees, and Tom feared it might be the
+spirits of the dead, complaining at being disturbed. The boys talked
+little, and only under their breath, for the time and the place and the
+pervading solemnity and silence oppressed their spirits. They found the
+sharp new heap they were seeking, and ensconced themselves within the
+protection of three great elms that grew in a bunch within a few feet
+of the grave.
+
+Then they waited in silence for what seemed a long time. The hooting
+of a distant owl was all the sound that troubled the dead stillness.
+Tom's reflections grew oppressive. He must force some talk. So he said
+in a whisper:
+
+"Hucky, do you believe the dead people like it for us to be here?"
+
+Huckleberry whispered:
+
+"I wisht I knowed. It's awful solemn like, AIN'T it?"
+
+"I bet it is."
+
+There was a considerable pause, while the boys canvassed this matter
+inwardly. Then Tom whispered:
+
+"Say, Hucky--do you reckon Hoss Williams hears us talking?"
+
+"O' course he does. Least his sperrit does."
+
+Tom, after a pause:
+
+"I wish I'd said Mister Williams. But I never meant any harm.
+Everybody calls him Hoss."
+
+"A body can't be too partic'lar how they talk 'bout these-yer dead
+people, Tom."
+
+This was a damper, and conversation died again.
+
+Presently Tom seized his comrade's arm and said:
+
+"Sh!"
+
+"What is it, Tom?" And the two clung together with beating hearts.
+
+"Sh! There 'tis again! Didn't you hear it?"
+
+"I--"
+
+"There! Now you hear it."
+
+"Lord, Tom, they're coming! They're coming, sure. What'll we do?"
+
+"I dono. Think they'll see us?"
+
+"Oh, Tom, they can see in the dark, same as cats. I wisht I hadn't
+come."
+
+"Oh, don't be afeard. I don't believe they'll bother us. We ain't
+doing any harm. If we keep perfectly still, maybe they won't notice us
+at all."
+
+"I'll try to, Tom, but, Lord, I'm all of a shiver."
+
+"Listen!"
+
+The boys bent their heads together and scarcely breathed. A muffled
+sound of voices floated up from the far end of the graveyard.
+
+"Look! See there!" whispered Tom. "What is it?"
+
+"It's devil-fire. Oh, Tom, this is awful."
+
+Some vague figures approached through the gloom, swinging an
+old-fashioned tin lantern that freckled the ground with innumerable
+little spangles of light. Presently Huckleberry whispered with a
+shudder:
+
+"It's the devils sure enough. Three of 'em! Lordy, Tom, we're goners!
+Can you pray?"
+
+"I'll try, but don't you be afeard. They ain't going to hurt us. 'Now
+I lay me down to sleep, I--'"
+
+"Sh!"
+
+"What is it, Huck?"
+
+"They're HUMANS! One of 'em is, anyway. One of 'em's old Muff Potter's
+voice."
+
+"No--'tain't so, is it?"
+
+"I bet I know it. Don't you stir nor budge. He ain't sharp enough to
+notice us. Drunk, the same as usual, likely--blamed old rip!"
+
+"All right, I'll keep still. Now they're stuck. Can't find it. Here
+they come again. Now they're hot. Cold again. Hot again. Red hot!
+They're p'inted right, this time. Say, Huck, I know another o' them
+voices; it's Injun Joe."
+
+"That's so--that murderin' half-breed! I'd druther they was devils a
+dern sight. What kin they be up to?"
+
+The whisper died wholly out, now, for the three men had reached the
+grave and stood within a few feet of the boys' hiding-place.
+
+"Here it is," said the third voice; and the owner of it held the
+lantern up and revealed the face of young Doctor Robinson.
+
+Potter and Injun Joe were carrying a handbarrow with a rope and a
+couple of shovels on it. They cast down their load and began to open
+the grave. The doctor put the lantern at the head of the grave and came
+and sat down with his back against one of the elm trees. He was so
+close the boys could have touched him.
+
+"Hurry, men!" he said, in a low voice; "the moon might come out at any
+moment."
+
+They growled a response and went on digging. For some time there was
+no noise but the grating sound of the spades discharging their freight
+of mould and gravel. It was very monotonous. Finally a spade struck
+upon the coffin with a dull woody accent, and within another minute or
+two the men had hoisted it out on the ground. They pried off the lid
+with their shovels, got out the body and dumped it rudely on the
+ground. The moon drifted from behind the clouds and exposed the pallid
+face. The barrow was got ready and the corpse placed on it, covered
+with a blanket, and bound to its place with the rope. Potter took out a
+large spring-knife and cut off the dangling end of the rope and then
+said:
+
+"Now the cussed thing's ready, Sawbones, and you'll just out with
+another five, or here she stays."
+
+"That's the talk!" said Injun Joe.
+
+"Look here, what does this mean?" said the doctor. "You required your
+pay in advance, and I've paid you."
+
+"Yes, and you done more than that," said Injun Joe, approaching the
+doctor, who was now standing. "Five years ago you drove me away from
+your father's kitchen one night, when I come to ask for something to
+eat, and you said I warn't there for any good; and when I swore I'd get
+even with you if it took a hundred years, your father had me jailed for
+a vagrant. Did you think I'd forget? The Injun blood ain't in me for
+nothing. And now I've GOT you, and you got to SETTLE, you know!"
+
+He was threatening the doctor, with his fist in his face, by this
+time. The doctor struck out suddenly and stretched the ruffian on the
+ground. Potter dropped his knife, and exclaimed:
+
+"Here, now, don't you hit my pard!" and the next moment he had
+grappled with the doctor and the two were struggling with might and
+main, trampling the grass and tearing the ground with their heels.
+Injun Joe sprang to his feet, his eyes flaming with passion, snatched
+up Potter's knife, and went creeping, catlike and stooping, round and
+round about the combatants, seeking an opportunity. All at once the
+doctor flung himself free, seized the heavy headboard of Williams'
+grave and felled Potter to the earth with it--and in the same instant
+the half-breed saw his chance and drove the knife to the hilt in the
+young man's breast. He reeled and fell partly upon Potter, flooding him
+with his blood, and in the same moment the clouds blotted out the
+dreadful spectacle and the two frightened boys went speeding away in
+the dark.
+
+Presently, when the moon emerged again, Injun Joe was standing over
+the two forms, contemplating them. The doctor murmured inarticulately,
+gave a long gasp or two and was still. The half-breed muttered:
+
+"THAT score is settled--damn you."
+
+Then he robbed the body. After which he put the fatal knife in
+Potter's open right hand, and sat down on the dismantled coffin. Three
+--four--five minutes passed, and then Potter began to stir and moan. His
+hand closed upon the knife; he raised it, glanced at it, and let it
+fall, with a shudder. Then he sat up, pushing the body from him, and
+gazed at it, and then around him, confusedly. His eyes met Joe's.
+
+"Lord, how is this, Joe?" he said.
+
+"It's a dirty business," said Joe, without moving.
+
+"What did you do it for?"
+
+"I! I never done it!"
+
+"Look here! That kind of talk won't wash."
+
+Potter trembled and grew white.
+
+"I thought I'd got sober. I'd no business to drink to-night. But it's
+in my head yet--worse'n when we started here. I'm all in a muddle;
+can't recollect anything of it, hardly. Tell me, Joe--HONEST, now, old
+feller--did I do it? Joe, I never meant to--'pon my soul and honor, I
+never meant to, Joe. Tell me how it was, Joe. Oh, it's awful--and him
+so young and promising."
+
+"Why, you two was scuffling, and he fetched you one with the headboard
+and you fell flat; and then up you come, all reeling and staggering
+like, and snatched the knife and jammed it into him, just as he fetched
+you another awful clip--and here you've laid, as dead as a wedge til
+now."
+
+"Oh, I didn't know what I was a-doing. I wish I may die this minute if
+I did. It was all on account of the whiskey and the excitement, I
+reckon. I never used a weepon in my life before, Joe. I've fought, but
+never with weepons. They'll all say that. Joe, don't tell! Say you
+won't tell, Joe--that's a good feller. I always liked you, Joe, and
+stood up for you, too. Don't you remember? You WON'T tell, WILL you,
+Joe?" And the poor creature dropped on his knees before the stolid
+murderer, and clasped his appealing hands.
+
+"No, you've always been fair and square with me, Muff Potter, and I
+won't go back on you. There, now, that's as fair as a man can say."
+
+"Oh, Joe, you're an angel. I'll bless you for this the longest day I
+live." And Potter began to cry.
+
+"Come, now, that's enough of that. This ain't any time for blubbering.
+You be off yonder way and I'll go this. Move, now, and don't leave any
+tracks behind you."
+
+Potter started on a trot that quickly increased to a run. The
+half-breed stood looking after him. He muttered:
+
+"If he's as much stunned with the lick and fuddled with the rum as he
+had the look of being, he won't think of the knife till he's gone so
+far he'll be afraid to come back after it to such a place by himself
+--chicken-heart!"
+
+Two or three minutes later the murdered man, the blanketed corpse, the
+lidless coffin, and the open grave were under no inspection but the
+moon's. The stillness was complete again, too.
+
+
+
+CHAPTER X
+
+THE two boys flew on and on, toward the village, speechless with
+horror. They glanced backward over their shoulders from time to time,
+apprehensively, as if they feared they might be followed. Every stump
+that started up in their path seemed a man and an enemy, and made them
+catch their breath; and as they sped by some outlying cottages that lay
+near the village, the barking of the aroused watch-dogs seemed to give
+wings to their feet.
+
+"If we can only get to the old tannery before we break down!"
+whispered Tom, in short catches between breaths. "I can't stand it much
+longer."
+
+Huckleberry's hard pantings were his only reply, and the boys fixed
+their eyes on the goal of their hopes and bent to their work to win it.
+They gained steadily on it, and at last, breast to breast, they burst
+through the open door and fell grateful and exhausted in the sheltering
+shadows beyond. By and by their pulses slowed down, and Tom whispered:
+
+"Huckleberry, what do you reckon'll come of this?"
+
+"If Doctor Robinson dies, I reckon hanging'll come of it."
+
+"Do you though?"
+
+"Why, I KNOW it, Tom."
+
+Tom thought a while, then he said:
+
+"Who'll tell? We?"
+
+"What are you talking about? S'pose something happened and Injun Joe
+DIDN'T hang? Why, he'd kill us some time or other, just as dead sure as
+we're a laying here."
+
+"That's just what I was thinking to myself, Huck."
+
+"If anybody tells, let Muff Potter do it, if he's fool enough. He's
+generally drunk enough."
+
+Tom said nothing--went on thinking. Presently he whispered:
+
+"Huck, Muff Potter don't know it. How can he tell?"
+
+"What's the reason he don't know it?"
+
+"Because he'd just got that whack when Injun Joe done it. D'you reckon
+he could see anything? D'you reckon he knowed anything?"
+
+"By hokey, that's so, Tom!"
+
+"And besides, look-a-here--maybe that whack done for HIM!"
+
+"No, 'taint likely, Tom. He had liquor in him; I could see that; and
+besides, he always has. Well, when pap's full, you might take and belt
+him over the head with a church and you couldn't phase him. He says so,
+his own self. So it's the same with Muff Potter, of course. But if a
+man was dead sober, I reckon maybe that whack might fetch him; I dono."
+
+After another reflective silence, Tom said:
+
+"Hucky, you sure you can keep mum?"
+
+"Tom, we GOT to keep mum. You know that. That Injun devil wouldn't
+make any more of drownding us than a couple of cats, if we was to
+squeak 'bout this and they didn't hang him. Now, look-a-here, Tom, less
+take and swear to one another--that's what we got to do--swear to keep
+mum."
+
+"I'm agreed. It's the best thing. Would you just hold hands and swear
+that we--"
+
+"Oh no, that wouldn't do for this. That's good enough for little
+rubbishy common things--specially with gals, cuz THEY go back on you
+anyway, and blab if they get in a huff--but there orter be writing
+'bout a big thing like this. And blood."
+
+Tom's whole being applauded this idea. It was deep, and dark, and
+awful; the hour, the circumstances, the surroundings, were in keeping
+with it. He picked up a clean pine shingle that lay in the moonlight,
+took a little fragment of "red keel" out of his pocket, got the moon on
+his work, and painfully scrawled these lines, emphasizing each slow
+down-stroke by clamping his tongue between his teeth, and letting up
+the pressure on the up-strokes. [See next page.]
+
+   "Huck Finn and
+    Tom Sawyer swears
+    they will keep mum
+    about This and They
+    wish They may Drop
+    down dead in Their
+    Tracks if They ever
+    Tell and Rot."
+
+Huckleberry was filled with admiration of Tom's facility in writing,
+and the sublimity of his language. He at once took a pin from his lapel
+and was going to prick his flesh, but Tom said:
+
+"Hold on! Don't do that. A pin's brass. It might have verdigrease on
+it."
+
+"What's verdigrease?"
+
+"It's p'ison. That's what it is. You just swaller some of it once
+--you'll see."
+
+So Tom unwound the thread from one of his needles, and each boy
+pricked the ball of his thumb and squeezed out a drop of blood. In
+time, after many squeezes, Tom managed to sign his initials, using the
+ball of his little finger for a pen. Then he showed Huckleberry how to
+make an H and an F, and the oath was complete. They buried the shingle
+close to the wall, with some dismal ceremonies and incantations, and
+the fetters that bound their tongues were considered to be locked and
+the key thrown away.
+
+A figure crept stealthily through a break in the other end of the
+ruined building, now, but they did not notice it.
+
+"Tom," whispered Huckleberry, "does this keep us from EVER telling
+--ALWAYS?"
+
+"Of course it does. It don't make any difference WHAT happens, we got
+to keep mum. We'd drop down dead--don't YOU know that?"
+
+"Yes, I reckon that's so."
+
+They continued to whisper for some little time. Presently a dog set up
+a long, lugubrious howl just outside--within ten feet of them. The boys
+clasped each other suddenly, in an agony of fright.
+
+"Which of us does he mean?" gasped Huckleberry.
+
+"I dono--peep through the crack. Quick!"
+
+"No, YOU, Tom!"
+
+"I can't--I can't DO it, Huck!"
+
+"Please, Tom. There 'tis again!"
+
+"Oh, lordy, I'm thankful!" whispered Tom. "I know his voice. It's Bull
+Harbison." *
+
+[* If Mr. Harbison owned a slave named Bull, Tom would have spoken of
+him as "Harbison's Bull," but a son or a dog of that name was "Bull
+Harbison."]
+
+"Oh, that's good--I tell you, Tom, I was most scared to death; I'd a
+bet anything it was a STRAY dog."
+
+The dog howled again. The boys' hearts sank once more.
+
+"Oh, my! that ain't no Bull Harbison!" whispered Huckleberry. "DO, Tom!"
+
+Tom, quaking with fear, yielded, and put his eye to the crack. His
+whisper was hardly audible when he said:
+
+"Oh, Huck, IT S A STRAY DOG!"
+
+"Quick, Tom, quick! Who does he mean?"
+
+"Huck, he must mean us both--we're right together."
+
+"Oh, Tom, I reckon we're goners. I reckon there ain't no mistake 'bout
+where I'LL go to. I been so wicked."
+
+"Dad fetch it! This comes of playing hookey and doing everything a
+feller's told NOT to do. I might a been good, like Sid, if I'd a tried
+--but no, I wouldn't, of course. But if ever I get off this time, I lay
+I'll just WALLER in Sunday-schools!" And Tom began to snuffle a little.
+
+"YOU bad!" and Huckleberry began to snuffle too. "Consound it, Tom
+Sawyer, you're just old pie, 'longside o' what I am. Oh, LORDY, lordy,
+lordy, I wisht I only had half your chance."
+
+Tom choked off and whispered:
+
+"Look, Hucky, look! He's got his BACK to us!"
+
+Hucky looked, with joy in his heart.
+
+"Well, he has, by jingoes! Did he before?"
+
+"Yes, he did. But I, like a fool, never thought. Oh, this is bully,
+you know. NOW who can he mean?"
+
+The howling stopped. Tom pricked up his ears.
+
+"Sh! What's that?" he whispered.
+
+"Sounds like--like hogs grunting. No--it's somebody snoring, Tom."
+
+"That IS it! Where 'bouts is it, Huck?"
+
+"I bleeve it's down at 'tother end. Sounds so, anyway. Pap used to
+sleep there, sometimes, 'long with the hogs, but laws bless you, he
+just lifts things when HE snores. Besides, I reckon he ain't ever
+coming back to this town any more."
+
+The spirit of adventure rose in the boys' souls once more.
+
+"Hucky, do you das't to go if I lead?"
+
+"I don't like to, much. Tom, s'pose it's Injun Joe!"
+
+Tom quailed. But presently the temptation rose up strong again and the
+boys agreed to try, with the understanding that they would take to
+their heels if the snoring stopped. So they went tiptoeing stealthily
+down, the one behind the other. When they had got to within five steps
+of the snorer, Tom stepped on a stick, and it broke with a sharp snap.
+The man moaned, writhed a little, and his face came into the moonlight.
+It was Muff Potter. The boys' hearts had stood still, and their hopes
+too, when the man moved, but their fears passed away now. They tiptoed
+out, through the broken weather-boarding, and stopped at a little
+distance to exchange a parting word. That long, lugubrious howl rose on
+the night air again! They turned and saw the strange dog standing
+within a few feet of where Potter was lying, and FACING Potter, with
+his nose pointing heavenward.
+
+"Oh, geeminy, it's HIM!" exclaimed both boys, in a breath.
+
+"Say, Tom--they say a stray dog come howling around Johnny Miller's
+house, 'bout midnight, as much as two weeks ago; and a whippoorwill
+come in and lit on the banisters and sung, the very same evening; and
+there ain't anybody dead there yet."
+
+"Well, I know that. And suppose there ain't. Didn't Gracie Miller fall
+in the kitchen fire and burn herself terrible the very next Saturday?"
+
+"Yes, but she ain't DEAD. And what's more, she's getting better, too."
+
+"All right, you wait and see. She's a goner, just as dead sure as Muff
+Potter's a goner. That's what the niggers say, and they know all about
+these kind of things, Huck."
+
+Then they separated, cogitating. When Tom crept in at his bedroom
+window the night was almost spent. He undressed with excessive caution,
+and fell asleep congratulating himself that nobody knew of his
+escapade. He was not aware that the gently-snoring Sid was awake, and
+had been so for an hour.
+
+When Tom awoke, Sid was dressed and gone. There was a late look in the
+light, a late sense in the atmosphere. He was startled. Why had he not
+been called--persecuted till he was up, as usual? The thought filled
+him with bodings. Within five minutes he was dressed and down-stairs,
+feeling sore and drowsy. The family were still at table, but they had
+finished breakfast. There was no voice of rebuke; but there were
+averted eyes; there was a silence and an air of solemnity that struck a
+chill to the culprit's heart. He sat down and tried to seem gay, but it
+was up-hill work; it roused no smile, no response, and he lapsed into
+silence and let his heart sink down to the depths.
+
+After breakfast his aunt took him aside, and Tom almost brightened in
+the hope that he was going to be flogged; but it was not so. His aunt
+wept over him and asked him how he could go and break her old heart so;
+and finally told him to go on, and ruin himself and bring her gray
+hairs with sorrow to the grave, for it was no use for her to try any
+more. This was worse than a thousand whippings, and Tom's heart was
+sorer now than his body. He cried, he pleaded for forgiveness, promised
+to reform over and over again, and then received his dismissal, feeling
+that he had won but an imperfect forgiveness and established but a
+feeble confidence.
+
+He left the presence too miserable to even feel revengeful toward Sid;
+and so the latter's prompt retreat through the back gate was
+unnecessary. He moped to school gloomy and sad, and took his flogging,
+along with Joe Harper, for playing hookey the day before, with the air
+of one whose heart was busy with heavier woes and wholly dead to
+trifles. Then he betook himself to his seat, rested his elbows on his
+desk and his jaws in his hands, and stared at the wall with the stony
+stare of suffering that has reached the limit and can no further go.
+His elbow was pressing against some hard substance. After a long time
+he slowly and sadly changed his position, and took up this object with
+a sigh. It was in a paper. He unrolled it. A long, lingering, colossal
+sigh followed, and his heart broke. It was his brass andiron knob!
+
+This final feather broke the camel's back.
+
+
+
+CHAPTER XI
+
+CLOSE upon the hour of noon the whole village was suddenly electrified
+with the ghastly news. No need of the as yet undreamed-of telegraph;
+the tale flew from man to man, from group to group, from house to
+house, with little less than telegraphic speed. Of course the
+schoolmaster gave holiday for that afternoon; the town would have
+thought strangely of him if he had not.
+
+A gory knife had been found close to the murdered man, and it had been
+recognized by somebody as belonging to Muff Potter--so the story ran.
+And it was said that a belated citizen had come upon Potter washing
+himself in the "branch" about one or two o'clock in the morning, and
+that Potter had at once sneaked off--suspicious circumstances,
+especially the washing which was not a habit with Potter. It was also
+said that the town had been ransacked for this "murderer" (the public
+are not slow in the matter of sifting evidence and arriving at a
+verdict), but that he could not be found. Horsemen had departed down
+all the roads in every direction, and the Sheriff "was confident" that
+he would be captured before night.
+
+All the town was drifting toward the graveyard. Tom's heartbreak
+vanished and he joined the procession, not because he would not a
+thousand times rather go anywhere else, but because an awful,
+unaccountable fascination drew him on. Arrived at the dreadful place,
+he wormed his small body through the crowd and saw the dismal
+spectacle. It seemed to him an age since he was there before. Somebody
+pinched his arm. He turned, and his eyes met Huckleberry's. Then both
+looked elsewhere at once, and wondered if anybody had noticed anything
+in their mutual glance. But everybody was talking, and intent upon the
+grisly spectacle before them.
+
+"Poor fellow!" "Poor young fellow!" "This ought to be a lesson to
+grave robbers!" "Muff Potter'll hang for this if they catch him!" This
+was the drift of remark; and the minister said, "It was a judgment; His
+hand is here."
+
+Now Tom shivered from head to heel; for his eye fell upon the stolid
+face of Injun Joe. At this moment the crowd began to sway and struggle,
+and voices shouted, "It's him! it's him! he's coming himself!"
+
+"Who? Who?" from twenty voices.
+
+"Muff Potter!"
+
+"Hallo, he's stopped!--Look out, he's turning! Don't let him get away!"
+
+People in the branches of the trees over Tom's head said he wasn't
+trying to get away--he only looked doubtful and perplexed.
+
+"Infernal impudence!" said a bystander; "wanted to come and take a
+quiet look at his work, I reckon--didn't expect any company."
+
+The crowd fell apart, now, and the Sheriff came through,
+ostentatiously leading Potter by the arm. The poor fellow's face was
+haggard, and his eyes showed the fear that was upon him. When he stood
+before the murdered man, he shook as with a palsy, and he put his face
+in his hands and burst into tears.
+
+"I didn't do it, friends," he sobbed; "'pon my word and honor I never
+done it."
+
+"Who's accused you?" shouted a voice.
+
+This shot seemed to carry home. Potter lifted his face and looked
+around him with a pathetic hopelessness in his eyes. He saw Injun Joe,
+and exclaimed:
+
+"Oh, Injun Joe, you promised me you'd never--"
+
+"Is that your knife?" and it was thrust before him by the Sheriff.
+
+Potter would have fallen if they had not caught him and eased him to
+the ground. Then he said:
+
+"Something told me 't if I didn't come back and get--" He shuddered;
+then waved his nerveless hand with a vanquished gesture and said, "Tell
+'em, Joe, tell 'em--it ain't any use any more."
+
+Then Huckleberry and Tom stood dumb and staring, and heard the
+stony-hearted liar reel off his serene statement, they expecting every
+moment that the clear sky would deliver God's lightnings upon his head,
+and wondering to see how long the stroke was delayed. And when he had
+finished and still stood alive and whole, their wavering impulse to
+break their oath and save the poor betrayed prisoner's life faded and
+vanished away, for plainly this miscreant had sold himself to Satan and
+it would be fatal to meddle with the property of such a power as that.
+
+"Why didn't you leave? What did you want to come here for?" somebody
+said.
+
+"I couldn't help it--I couldn't help it," Potter moaned. "I wanted to
+run away, but I couldn't seem to come anywhere but here." And he fell
+to sobbing again.
+
+Injun Joe repeated his statement, just as calmly, a few minutes
+afterward on the inquest, under oath; and the boys, seeing that the
+lightnings were still withheld, were confirmed in their belief that Joe
+had sold himself to the devil. He was now become, to them, the most
+balefully interesting object they had ever looked upon, and they could
+not take their fascinated eyes from his face.
+
+They inwardly resolved to watch him nights, when opportunity should
+offer, in the hope of getting a glimpse of his dread master.
+
+Injun Joe helped to raise the body of the murdered man and put it in a
+wagon for removal; and it was whispered through the shuddering crowd
+that the wound bled a little! The boys thought that this happy
+circumstance would turn suspicion in the right direction; but they were
+disappointed, for more than one villager remarked:
+
+"It was within three feet of Muff Potter when it done it."
+
+Tom's fearful secret and gnawing conscience disturbed his sleep for as
+much as a week after this; and at breakfast one morning Sid said:
+
+"Tom, you pitch around and talk in your sleep so much that you keep me
+awake half the time."
+
+Tom blanched and dropped his eyes.
+
+"It's a bad sign," said Aunt Polly, gravely. "What you got on your
+mind, Tom?"
+
+"Nothing. Nothing 't I know of." But the boy's hand shook so that he
+spilled his coffee.
+
+"And you do talk such stuff," Sid said. "Last night you said, 'It's
+blood, it's blood, that's what it is!' You said that over and over. And
+you said, 'Don't torment me so--I'll tell!' Tell WHAT? What is it
+you'll tell?"
+
+Everything was swimming before Tom. There is no telling what might
+have happened, now, but luckily the concern passed out of Aunt Polly's
+face and she came to Tom's relief without knowing it. She said:
+
+"Sho! It's that dreadful murder. I dream about it most every night
+myself. Sometimes I dream it's me that done it."
+
+Mary said she had been affected much the same way. Sid seemed
+satisfied. Tom got out of the presence as quick as he plausibly could,
+and after that he complained of toothache for a week, and tied up his
+jaws every night. He never knew that Sid lay nightly watching, and
+frequently slipped the bandage free and then leaned on his elbow
+listening a good while at a time, and afterward slipped the bandage
+back to its place again. Tom's distress of mind wore off gradually and
+the toothache grew irksome and was discarded. If Sid really managed to
+make anything out of Tom's disjointed mutterings, he kept it to himself.
+
+It seemed to Tom that his schoolmates never would get done holding
+inquests on dead cats, and thus keeping his trouble present to his
+mind. Sid noticed that Tom never was coroner at one of these inquiries,
+though it had been his habit to take the lead in all new enterprises;
+he noticed, too, that Tom never acted as a witness--and that was
+strange; and Sid did not overlook the fact that Tom even showed a
+marked aversion to these inquests, and always avoided them when he
+could. Sid marvelled, but said nothing. However, even inquests went out
+of vogue at last, and ceased to torture Tom's conscience.
+
+Every day or two, during this time of sorrow, Tom watched his
+opportunity and went to the little grated jail-window and smuggled such
+small comforts through to the "murderer" as he could get hold of. The
+jail was a trifling little brick den that stood in a marsh at the edge
+of the village, and no guards were afforded for it; indeed, it was
+seldom occupied. These offerings greatly helped to ease Tom's
+conscience.
+
+The villagers had a strong desire to tar-and-feather Injun Joe and
+ride him on a rail, for body-snatching, but so formidable was his
+character that nobody could be found who was willing to take the lead
+in the matter, so it was dropped. He had been careful to begin both of
+his inquest-statements with the fight, without confessing the
+grave-robbery that preceded it; therefore it was deemed wisest not
+to try the case in the courts at present.
+
+
+
+CHAPTER XII
+
+ONE of the reasons why Tom's mind had drifted away from its secret
+troubles was, that it had found a new and weighty matter to interest
+itself about. Becky Thatcher had stopped coming to school. Tom had
+struggled with his pride a few days, and tried to "whistle her down the
+wind," but failed. He began to find himself hanging around her father's
+house, nights, and feeling very miserable. She was ill. What if she
+should die! There was distraction in the thought. He no longer took an
+interest in war, nor even in piracy. The charm of life was gone; there
+was nothing but dreariness left. He put his hoop away, and his bat;
+there was no joy in them any more. His aunt was concerned. She began to
+try all manner of remedies on him. She was one of those people who are
+infatuated with patent medicines and all new-fangled methods of
+producing health or mending it. She was an inveterate experimenter in
+these things. When something fresh in this line came out she was in a
+fever, right away, to try it; not on herself, for she was never ailing,
+but on anybody else that came handy. She was a subscriber for all the
+"Health" periodicals and phrenological frauds; and the solemn ignorance
+they were inflated with was breath to her nostrils. All the "rot" they
+contained about ventilation, and how to go to bed, and how to get up,
+and what to eat, and what to drink, and how much exercise to take, and
+what frame of mind to keep one's self in, and what sort of clothing to
+wear, was all gospel to her, and she never observed that her
+health-journals of the current month customarily upset everything they
+had recommended the month before. She was as simple-hearted and honest
+as the day was long, and so she was an easy victim. She gathered
+together her quack periodicals and her quack medicines, and thus armed
+with death, went about on her pale horse, metaphorically speaking, with
+"hell following after." But she never suspected that she was not an
+angel of healing and the balm of Gilead in disguise, to the suffering
+neighbors.
+
+The water treatment was new, now, and Tom's low condition was a
+windfall to her. She had him out at daylight every morning, stood him
+up in the woodshed and drowned him with a deluge of cold water; then
+she scrubbed him down with a towel like a file, and so brought him to;
+then she rolled him up in a wet sheet and put him away under blankets
+till she sweated his soul clean and "the yellow stains of it came
+through his pores"--as Tom said.
+
+Yet notwithstanding all this, the boy grew more and more melancholy
+and pale and dejected. She added hot baths, sitz baths, shower baths,
+and plunges. The boy remained as dismal as a hearse. She began to
+assist the water with a slim oatmeal diet and blister-plasters. She
+calculated his capacity as she would a jug's, and filled him up every
+day with quack cure-alls.
+
+Tom had become indifferent to persecution by this time. This phase
+filled the old lady's heart with consternation. This indifference must
+be broken up at any cost. Now she heard of Pain-killer for the first
+time. She ordered a lot at once. She tasted it and was filled with
+gratitude. It was simply fire in a liquid form. She dropped the water
+treatment and everything else, and pinned her faith to Pain-killer. She
+gave Tom a teaspoonful and watched with the deepest anxiety for the
+result. Her troubles were instantly at rest, her soul at peace again;
+for the "indifference" was broken up. The boy could not have shown a
+wilder, heartier interest, if she had built a fire under him.
+
+Tom felt that it was time to wake up; this sort of life might be
+romantic enough, in his blighted condition, but it was getting to have
+too little sentiment and too much distracting variety about it. So he
+thought over various plans for relief, and finally hit pon that of
+professing to be fond of Pain-killer. He asked for it so often that he
+became a nuisance, and his aunt ended by telling him to help himself
+and quit bothering her. If it had been Sid, she would have had no
+misgivings to alloy her delight; but since it was Tom, she watched the
+bottle clandestinely. She found that the medicine did really diminish,
+but it did not occur to her that the boy was mending the health of a
+crack in the sitting-room floor with it.
+
+One day Tom was in the act of dosing the crack when his aunt's yellow
+cat came along, purring, eying the teaspoon avariciously, and begging
+for a taste. Tom said:
+
+"Don't ask for it unless you want it, Peter."
+
+But Peter signified that he did want it.
+
+"You better make sure."
+
+Peter was sure.
+
+"Now you've asked for it, and I'll give it to you, because there ain't
+anything mean about me; but if you find you don't like it, you mustn't
+blame anybody but your own self."
+
+Peter was agreeable. So Tom pried his mouth open and poured down the
+Pain-killer. Peter sprang a couple of yards in the air, and then
+delivered a war-whoop and set off round and round the room, banging
+against furniture, upsetting flower-pots, and making general havoc.
+Next he rose on his hind feet and pranced around, in a frenzy of
+enjoyment, with his head over his shoulder and his voice proclaiming
+his unappeasable happiness. Then he went tearing around the house again
+spreading chaos and destruction in his path. Aunt Polly entered in time
+to see him throw a few double summersets, deliver a final mighty
+hurrah, and sail through the open window, carrying the rest of the
+flower-pots with him. The old lady stood petrified with astonishment,
+peering over her glasses; Tom lay on the floor expiring with laughter.
+
+"Tom, what on earth ails that cat?"
+
+"I don't know, aunt," gasped the boy.
+
+"Why, I never see anything like it. What did make him act so?"
+
+"Deed I don't know, Aunt Polly; cats always act so when they're having
+a good time."
+
+"They do, do they?" There was something in the tone that made Tom
+apprehensive.
+
+"Yes'm. That is, I believe they do."
+
+"You DO?"
+
+"Yes'm."
+
+The old lady was bending down, Tom watching, with interest emphasized
+by anxiety. Too late he divined her "drift." The handle of the telltale
+teaspoon was visible under the bed-valance. Aunt Polly took it, held it
+up. Tom winced, and dropped his eyes. Aunt Polly raised him by the
+usual handle--his ear--and cracked his head soundly with her thimble.
+
+"Now, sir, what did you want to treat that poor dumb beast so, for?"
+
+"I done it out of pity for him--because he hadn't any aunt."
+
+"Hadn't any aunt!--you numskull. What has that got to do with it?"
+
+"Heaps. Because if he'd had one she'd a burnt him out herself! She'd a
+roasted his bowels out of him 'thout any more feeling than if he was a
+human!"
+
+Aunt Polly felt a sudden pang of remorse. This was putting the thing
+in a new light; what was cruelty to a cat MIGHT be cruelty to a boy,
+too. She began to soften; she felt sorry. Her eyes watered a little,
+and she put her hand on Tom's head and said gently:
+
+"I was meaning for the best, Tom. And, Tom, it DID do you good."
+
+Tom looked up in her face with just a perceptible twinkle peeping
+through his gravity.
+
+"I know you was meaning for the best, aunty, and so was I with Peter.
+It done HIM good, too. I never see him get around so since--"
+
+"Oh, go 'long with you, Tom, before you aggravate me again. And you
+try and see if you can't be a good boy, for once, and you needn't take
+any more medicine."
+
+Tom reached school ahead of time. It was noticed that this strange
+thing had been occurring every day latterly. And now, as usual of late,
+he hung about the gate of the schoolyard instead of playing with his
+comrades. He was sick, he said, and he looked it. He tried to seem to
+be looking everywhere but whither he really was looking--down the road.
+Presently Jeff Thatcher hove in sight, and Tom's face lighted; he gazed
+a moment, and then turned sorrowfully away. When Jeff arrived, Tom
+accosted him; and "led up" warily to opportunities for remark about
+Becky, but the giddy lad never could see the bait. Tom watched and
+watched, hoping whenever a frisking frock came in sight, and hating the
+owner of it as soon as he saw she was not the right one. At last frocks
+ceased to appear, and he dropped hopelessly into the dumps; he entered
+the empty schoolhouse and sat down to suffer. Then one more frock
+passed in at the gate, and Tom's heart gave a great bound. The next
+instant he was out, and "going on" like an Indian; yelling, laughing,
+chasing boys, jumping over the fence at risk of life and limb, throwing
+handsprings, standing on his head--doing all the heroic things he could
+conceive of, and keeping a furtive eye out, all the while, to see if
+Becky Thatcher was noticing. But she seemed to be unconscious of it
+all; she never looked. Could it be possible that she was not aware that
+he was there? He carried his exploits to her immediate vicinity; came
+war-whooping around, snatched a boy's cap, hurled it to the roof of the
+schoolhouse, broke through a group of boys, tumbling them in every
+direction, and fell sprawling, himself, under Becky's nose, almost
+upsetting her--and she turned, with her nose in the air, and he heard
+her say: "Mf! some people think they're mighty smart--always showing
+off!"
+
+Tom's cheeks burned. He gathered himself up and sneaked off, crushed
+and crestfallen.
+
+
+
+CHAPTER XIII
+
+TOM'S mind was made up now. He was gloomy and desperate. He was a
+forsaken, friendless boy, he said; nobody loved him; when they found
+out what they had driven him to, perhaps they would be sorry; he had
+tried to do right and get along, but they would not let him; since
+nothing would do them but to be rid of him, let it be so; and let them
+blame HIM for the consequences--why shouldn't they? What right had the
+friendless to complain? Yes, they had forced him to it at last: he
+would lead a life of crime. There was no choice.
+
+By this time he was far down Meadow Lane, and the bell for school to
+"take up" tinkled faintly upon his ear. He sobbed, now, to think he
+should never, never hear that old familiar sound any more--it was very
+hard, but it was forced on him; since he was driven out into the cold
+world, he must submit--but he forgave them. Then the sobs came thick
+and fast.
+
+Just at this point he met his soul's sworn comrade, Joe Harper
+--hard-eyed, and with evidently a great and dismal purpose in his heart.
+Plainly here were "two souls with but a single thought." Tom, wiping
+his eyes with his sleeve, began to blubber out something about a
+resolution to escape from hard usage and lack of sympathy at home by
+roaming abroad into the great world never to return; and ended by
+hoping that Joe would not forget him.
+
+But it transpired that this was a request which Joe had just been
+going to make of Tom, and had come to hunt him up for that purpose. His
+mother had whipped him for drinking some cream which he had never
+tasted and knew nothing about; it was plain that she was tired of him
+and wished him to go; if she felt that way, there was nothing for him
+to do but succumb; he hoped she would be happy, and never regret having
+driven her poor boy out into the unfeeling world to suffer and die.
+
+As the two boys walked sorrowing along, they made a new compact to
+stand by each other and be brothers and never separate till death
+relieved them of their troubles. Then they began to lay their plans.
+Joe was for being a hermit, and living on crusts in a remote cave, and
+dying, some time, of cold and want and grief; but after listening to
+Tom, he conceded that there were some conspicuous advantages about a
+life of crime, and so he consented to be a pirate.
+
+Three miles below St. Petersburg, at a point where the Mississippi
+River was a trifle over a mile wide, there was a long, narrow, wooded
+island, with a shallow bar at the head of it, and this offered well as
+a rendezvous. It was not inhabited; it lay far over toward the further
+shore, abreast a dense and almost wholly unpeopled forest. So Jackson's
+Island was chosen. Who were to be the subjects of their piracies was a
+matter that did not occur to them. Then they hunted up Huckleberry
+Finn, and he joined them promptly, for all careers were one to him; he
+was indifferent. They presently separated to meet at a lonely spot on
+the river-bank two miles above the village at the favorite hour--which
+was midnight. There was a small log raft there which they meant to
+capture. Each would bring hooks and lines, and such provision as he
+could steal in the most dark and mysterious way--as became outlaws. And
+before the afternoon was done, they had all managed to enjoy the sweet
+glory of spreading the fact that pretty soon the town would "hear
+something." All who got this vague hint were cautioned to "be mum and
+wait."
+
+About midnight Tom arrived with a boiled ham and a few trifles,
+and stopped in a dense undergrowth on a small bluff overlooking the
+meeting-place. It was starlight, and very still. The mighty river lay
+like an ocean at rest. Tom listened a moment, but no sound disturbed the
+quiet. Then he gave a low, distinct whistle. It was answered from under
+the bluff. Tom whistled twice more; these signals were answered in the
+same way. Then a guarded voice said:
+
+"Who goes there?"
+
+"Tom Sawyer, the Black Avenger of the Spanish Main. Name your names."
+
+"Huck Finn the Red-Handed, and Joe Harper the Terror of the Seas." Tom
+had furnished these titles, from his favorite literature.
+
+"'Tis well. Give the countersign."
+
+Two hoarse whispers delivered the same awful word simultaneously to
+the brooding night:
+
+"BLOOD!"
+
+Then Tom tumbled his ham over the bluff and let himself down after it,
+tearing both skin and clothes to some extent in the effort. There was
+an easy, comfortable path along the shore under the bluff, but it
+lacked the advantages of difficulty and danger so valued by a pirate.
+
+The Terror of the Seas had brought a side of bacon, and had about worn
+himself out with getting it there. Finn the Red-Handed had stolen a
+skillet and a quantity of half-cured leaf tobacco, and had also brought
+a few corn-cobs to make pipes with. But none of the pirates smoked or
+"chewed" but himself. The Black Avenger of the Spanish Main said it
+would never do to start without some fire. That was a wise thought;
+matches were hardly known there in that day. They saw a fire
+smouldering upon a great raft a hundred yards above, and they went
+stealthily thither and helped themselves to a chunk. They made an
+imposing adventure of it, saying, "Hist!" every now and then, and
+suddenly halting with finger on lip; moving with hands on imaginary
+dagger-hilts; and giving orders in dismal whispers that if "the foe"
+stirred, to "let him have it to the hilt," because "dead men tell no
+tales." They knew well enough that the raftsmen were all down at the
+village laying in stores or having a spree, but still that was no
+excuse for their conducting this thing in an unpiratical way.
+
+They shoved off, presently, Tom in command, Huck at the after oar and
+Joe at the forward. Tom stood amidships, gloomy-browed, and with folded
+arms, and gave his orders in a low, stern whisper:
+
+"Luff, and bring her to the wind!"
+
+"Aye-aye, sir!"
+
+"Steady, steady-y-y-y!"
+
+"Steady it is, sir!"
+
+"Let her go off a point!"
+
+"Point it is, sir!"
+
+As the boys steadily and monotonously drove the raft toward mid-stream
+it was no doubt understood that these orders were given only for
+"style," and were not intended to mean anything in particular.
+
+"What sail's she carrying?"
+
+"Courses, tops'ls, and flying-jib, sir."
+
+"Send the r'yals up! Lay out aloft, there, half a dozen of ye
+--foretopmaststuns'l! Lively, now!"
+
+"Aye-aye, sir!"
+
+"Shake out that maintogalans'l! Sheets and braces! NOW my hearties!"
+
+"Aye-aye, sir!"
+
+"Hellum-a-lee--hard a port! Stand by to meet her when she comes! Port,
+port! NOW, men! With a will! Stead-y-y-y!"
+
+"Steady it is, sir!"
+
+The raft drew beyond the middle of the river; the boys pointed her
+head right, and then lay on their oars. The river was not high, so
+there was not more than a two or three mile current. Hardly a word was
+said during the next three-quarters of an hour. Now the raft was
+passing before the distant town. Two or three glimmering lights showed
+where it lay, peacefully sleeping, beyond the vague vast sweep of
+star-gemmed water, unconscious of the tremendous event that was happening.
+The Black Avenger stood still with folded arms, "looking his last" upon
+the scene of his former joys and his later sufferings, and wishing
+"she" could see him now, abroad on the wild sea, facing peril and death
+with dauntless heart, going to his doom with a grim smile on his lips.
+It was but a small strain on his imagination to remove Jackson's Island
+beyond eyeshot of the village, and so he "looked his last" with a
+broken and satisfied heart. The other pirates were looking their last,
+too; and they all looked so long that they came near letting the
+current drift them out of the range of the island. But they discovered
+the danger in time, and made shift to avert it. About two o'clock in
+the morning the raft grounded on the bar two hundred yards above the
+head of the island, and they waded back and forth until they had landed
+their freight. Part of the little raft's belongings consisted of an old
+sail, and this they spread over a nook in the bushes for a tent to
+shelter their provisions; but they themselves would sleep in the open
+air in good weather, as became outlaws.
+
+They built a fire against the side of a great log twenty or thirty
+steps within the sombre depths of the forest, and then cooked some
+bacon in the frying-pan for supper, and used up half of the corn "pone"
+stock they had brought. It seemed glorious sport to be feasting in that
+wild, free way in the virgin forest of an unexplored and uninhabited
+island, far from the haunts of men, and they said they never would
+return to civilization. The climbing fire lit up their faces and threw
+its ruddy glare upon the pillared tree-trunks of their forest temple,
+and upon the varnished foliage and festooning vines.
+
+When the last crisp slice of bacon was gone, and the last allowance of
+corn pone devoured, the boys stretched themselves out on the grass,
+filled with contentment. They could have found a cooler place, but they
+would not deny themselves such a romantic feature as the roasting
+camp-fire.
+
+"AIN'T it gay?" said Joe.
+
+"It's NUTS!" said Tom. "What would the boys say if they could see us?"
+
+"Say? Well, they'd just die to be here--hey, Hucky!"
+
+"I reckon so," said Huckleberry; "anyways, I'm suited. I don't want
+nothing better'n this. I don't ever get enough to eat, gen'ally--and
+here they can't come and pick at a feller and bullyrag him so."
+
+"It's just the life for me," said Tom. "You don't have to get up,
+mornings, and you don't have to go to school, and wash, and all that
+blame foolishness. You see a pirate don't have to do ANYTHING, Joe,
+when he's ashore, but a hermit HE has to be praying considerable, and
+then he don't have any fun, anyway, all by himself that way."
+
+"Oh yes, that's so," said Joe, "but I hadn't thought much about it,
+you know. I'd a good deal rather be a pirate, now that I've tried it."
+
+"You see," said Tom, "people don't go much on hermits, nowadays, like
+they used to in old times, but a pirate's always respected. And a
+hermit's got to sleep on the hardest place he can find, and put
+sackcloth and ashes on his head, and stand out in the rain, and--"
+
+"What does he put sackcloth and ashes on his head for?" inquired Huck.
+
+"I dono. But they've GOT to do it. Hermits always do. You'd have to do
+that if you was a hermit."
+
+"Dern'd if I would," said Huck.
+
+"Well, what would you do?"
+
+"I dono. But I wouldn't do that."
+
+"Why, Huck, you'd HAVE to. How'd you get around it?"
+
+"Why, I just wouldn't stand it. I'd run away."
+
+"Run away! Well, you WOULD be a nice old slouch of a hermit. You'd be
+a disgrace."
+
+The Red-Handed made no response, being better employed. He had
+finished gouging out a cob, and now he fitted a weed stem to it, loaded
+it with tobacco, and was pressing a coal to the charge and blowing a
+cloud of fragrant smoke--he was in the full bloom of luxurious
+contentment. The other pirates envied him this majestic vice, and
+secretly resolved to acquire it shortly. Presently Huck said:
+
+"What does pirates have to do?"
+
+Tom said:
+
+"Oh, they have just a bully time--take ships and burn them, and get
+the money and bury it in awful places in their island where there's
+ghosts and things to watch it, and kill everybody in the ships--make
+'em walk a plank."
+
+"And they carry the women to the island," said Joe; "they don't kill
+the women."
+
+"No," assented Tom, "they don't kill the women--they're too noble. And
+the women's always beautiful, too.
+
+"And don't they wear the bulliest clothes! Oh no! All gold and silver
+and di'monds," said Joe, with enthusiasm.
+
+"Who?" said Huck.
+
+"Why, the pirates."
+
+Huck scanned his own clothing forlornly.
+
+"I reckon I ain't dressed fitten for a pirate," said he, with a
+regretful pathos in his voice; "but I ain't got none but these."
+
+But the other boys told him the fine clothes would come fast enough,
+after they should have begun their adventures. They made him understand
+that his poor rags would do to begin with, though it was customary for
+wealthy pirates to start with a proper wardrobe.
+
+Gradually their talk died out and drowsiness began to steal upon the
+eyelids of the little waifs. The pipe dropped from the fingers of the
+Red-Handed, and he slept the sleep of the conscience-free and the
+weary. The Terror of the Seas and the Black Avenger of the Spanish Main
+had more difficulty in getting to sleep. They said their prayers
+inwardly, and lying down, since there was nobody there with authority
+to make them kneel and recite aloud; in truth, they had a mind not to
+say them at all, but they were afraid to proceed to such lengths as
+that, lest they might call down a sudden and special thunderbolt from
+heaven. Then at once they reached and hovered upon the imminent verge
+of sleep--but an intruder came, now, that would not "down." It was
+conscience. They began to feel a vague fear that they had been doing
+wrong to run away; and next they thought of the stolen meat, and then
+the real torture came. They tried to argue it away by reminding
+conscience that they had purloined sweetmeats and apples scores of
+times; but conscience was not to be appeased by such thin
+plausibilities; it seemed to them, in the end, that there was no
+getting around the stubborn fact that taking sweetmeats was only
+"hooking," while taking bacon and hams and such valuables was plain
+simple stealing--and there was a command against that in the Bible. So
+they inwardly resolved that so long as they remained in the business,
+their piracies should not again be sullied with the crime of stealing.
+Then conscience granted a truce, and these curiously inconsistent
+pirates fell peacefully to sleep.
+
+
+
+CHAPTER XIV
+
+WHEN Tom awoke in the morning, he wondered where he was. He sat up and
+rubbed his eyes and looked around. Then he comprehended. It was the
+cool gray dawn, and there was a delicious sense of repose and peace in
+the deep pervading calm and silence of the woods. Not a leaf stirred;
+not a sound obtruded upon great Nature's meditation. Beaded dewdrops
+stood upon the leaves and grasses. A white layer of ashes covered the
+fire, and a thin blue breath of smoke rose straight into the air. Joe
+and Huck still slept.
+
+Now, far away in the woods a bird called; another answered; presently
+the hammering of a woodpecker was heard. Gradually the cool dim gray of
+the morning whitened, and as gradually sounds multiplied and life
+manifested itself. The marvel of Nature shaking off sleep and going to
+work unfolded itself to the musing boy. A little green worm came
+crawling over a dewy leaf, lifting two-thirds of his body into the air
+from time to time and "sniffing around," then proceeding again--for he
+was measuring, Tom said; and when the worm approached him, of its own
+accord, he sat as still as a stone, with his hopes rising and falling,
+by turns, as the creature still came toward him or seemed inclined to
+go elsewhere; and when at last it considered a painful moment with its
+curved body in the air and then came decisively down upon Tom's leg and
+began a journey over him, his whole heart was glad--for that meant that
+he was going to have a new suit of clothes--without the shadow of a
+doubt a gaudy piratical uniform. Now a procession of ants appeared,
+from nowhere in particular, and went about their labors; one struggled
+manfully by with a dead spider five times as big as itself in its arms,
+and lugged it straight up a tree-trunk. A brown spotted lady-bug
+climbed the dizzy height of a grass blade, and Tom bent down close to
+it and said, "Lady-bug, lady-bug, fly away home, your house is on fire,
+your children's alone," and she took wing and went off to see about it
+--which did not surprise the boy, for he knew of old that this insect was
+credulous about conflagrations, and he had practised upon its
+simplicity more than once. A tumblebug came next, heaving sturdily at
+its ball, and Tom touched the creature, to see it shut its legs against
+its body and pretend to be dead. The birds were fairly rioting by this
+time. A catbird, the Northern mocker, lit in a tree over Tom's head,
+and trilled out her imitations of her neighbors in a rapture of
+enjoyment; then a shrill jay swept down, a flash of blue flame, and
+stopped on a twig almost within the boy's reach, cocked his head to one
+side and eyed the strangers with a consuming curiosity; a gray squirrel
+and a big fellow of the "fox" kind came skurrying along, sitting up at
+intervals to inspect and chatter at the boys, for the wild things had
+probably never seen a human being before and scarcely knew whether to
+be afraid or not. All Nature was wide awake and stirring, now; long
+lances of sunlight pierced down through the dense foliage far and near,
+and a few butterflies came fluttering upon the scene.
+
+Tom stirred up the other pirates and they all clattered away with a
+shout, and in a minute or two were stripped and chasing after and
+tumbling over each other in the shallow limpid water of the white
+sandbar. They felt no longing for the little village sleeping in the
+distance beyond the majestic waste of water. A vagrant current or a
+slight rise in the river had carried off their raft, but this only
+gratified them, since its going was something like burning the bridge
+between them and civilization.
+
+They came back to camp wonderfully refreshed, glad-hearted, and
+ravenous; and they soon had the camp-fire blazing up again. Huck found
+a spring of clear cold water close by, and the boys made cups of broad
+oak or hickory leaves, and felt that water, sweetened with such a
+wildwood charm as that, would be a good enough substitute for coffee.
+While Joe was slicing bacon for breakfast, Tom and Huck asked him to
+hold on a minute; they stepped to a promising nook in the river-bank
+and threw in their lines; almost immediately they had reward. Joe had
+not had time to get impatient before they were back again with some
+handsome bass, a couple of sun-perch and a small catfish--provisions
+enough for quite a family. They fried the fish with the bacon, and were
+astonished; for no fish had ever seemed so delicious before. They did
+not know that the quicker a fresh-water fish is on the fire after he is
+caught the better he is; and they reflected little upon what a sauce
+open-air sleeping, open-air exercise, bathing, and a large ingredient
+of hunger make, too.
+
+They lay around in the shade, after breakfast, while Huck had a smoke,
+and then went off through the woods on an exploring expedition. They
+tramped gayly along, over decaying logs, through tangled underbrush,
+among solemn monarchs of the forest, hung from their crowns to the
+ground with a drooping regalia of grape-vines. Now and then they came
+upon snug nooks carpeted with grass and jeweled with flowers.
+
+They found plenty of things to be delighted with, but nothing to be
+astonished at. They discovered that the island was about three miles
+long and a quarter of a mile wide, and that the shore it lay closest to
+was only separated from it by a narrow channel hardly two hundred yards
+wide. They took a swim about every hour, so it was close upon the
+middle of the afternoon when they got back to camp. They were too
+hungry to stop to fish, but they fared sumptuously upon cold ham, and
+then threw themselves down in the shade to talk. But the talk soon
+began to drag, and then died. The stillness, the solemnity that brooded
+in the woods, and the sense of loneliness, began to tell upon the
+spirits of the boys. They fell to thinking. A sort of undefined longing
+crept upon them. This took dim shape, presently--it was budding
+homesickness. Even Finn the Red-Handed was dreaming of his doorsteps
+and empty hogsheads. But they were all ashamed of their weakness, and
+none was brave enough to speak his thought.
+
+For some time, now, the boys had been dully conscious of a peculiar
+sound in the distance, just as one sometimes is of the ticking of a
+clock which he takes no distinct note of. But now this mysterious sound
+became more pronounced, and forced a recognition. The boys started,
+glanced at each other, and then each assumed a listening attitude.
+There was a long silence, profound and unbroken; then a deep, sullen
+boom came floating down out of the distance.
+
+"What is it!" exclaimed Joe, under his breath.
+
+"I wonder," said Tom in a whisper.
+
+"'Tain't thunder," said Huckleberry, in an awed tone, "becuz thunder--"
+
+"Hark!" said Tom. "Listen--don't talk."
+
+They waited a time that seemed an age, and then the same muffled boom
+troubled the solemn hush.
+
+"Let's go and see."
+
+They sprang to their feet and hurried to the shore toward the town.
+They parted the bushes on the bank and peered out over the water. The
+little steam ferryboat was about a mile below the village, drifting
+with the current. Her broad deck seemed crowded with people. There were
+a great many skiffs rowing about or floating with the stream in the
+neighborhood of the ferryboat, but the boys could not determine what
+the men in them were doing. Presently a great jet of white smoke burst
+from the ferryboat's side, and as it expanded and rose in a lazy cloud,
+that same dull throb of sound was borne to the listeners again.
+
+"I know now!" exclaimed Tom; "somebody's drownded!"
+
+"That's it!" said Huck; "they done that last summer, when Bill Turner
+got drownded; they shoot a cannon over the water, and that makes him
+come up to the top. Yes, and they take loaves of bread and put
+quicksilver in 'em and set 'em afloat, and wherever there's anybody
+that's drownded, they'll float right there and stop."
+
+"Yes, I've heard about that," said Joe. "I wonder what makes the bread
+do that."
+
+"Oh, it ain't the bread, so much," said Tom; "I reckon it's mostly
+what they SAY over it before they start it out."
+
+"But they don't say anything over it," said Huck. "I've seen 'em and
+they don't."
+
+"Well, that's funny," said Tom. "But maybe they say it to themselves.
+Of COURSE they do. Anybody might know that."
+
+The other boys agreed that there was reason in what Tom said, because
+an ignorant lump of bread, uninstructed by an incantation, could not be
+expected to act very intelligently when set upon an errand of such
+gravity.
+
+"By jings, I wish I was over there, now," said Joe.
+
+"I do too" said Huck "I'd give heaps to know who it is."
+
+The boys still listened and watched. Presently a revealing thought
+flashed through Tom's mind, and he exclaimed:
+
+"Boys, I know who's drownded--it's us!"
+
+They felt like heroes in an instant. Here was a gorgeous triumph; they
+were missed; they were mourned; hearts were breaking on their account;
+tears were being shed; accusing memories of unkindness to these poor
+lost lads were rising up, and unavailing regrets and remorse were being
+indulged; and best of all, the departed were the talk of the whole
+town, and the envy of all the boys, as far as this dazzling notoriety
+was concerned. This was fine. It was worth while to be a pirate, after
+all.
+
+As twilight drew on, the ferryboat went back to her accustomed
+business and the skiffs disappeared. The pirates returned to camp. They
+were jubilant with vanity over their new grandeur and the illustrious
+trouble they were making. They caught fish, cooked supper and ate it,
+and then fell to guessing at what the village was thinking and saying
+about them; and the pictures they drew of the public distress on their
+account were gratifying to look upon--from their point of view. But
+when the shadows of night closed them in, they gradually ceased to
+talk, and sat gazing into the fire, with their minds evidently
+wandering elsewhere. The excitement was gone, now, and Tom and Joe
+could not keep back thoughts of certain persons at home who were not
+enjoying this fine frolic as much as they were. Misgivings came; they
+grew troubled and unhappy; a sigh or two escaped, unawares. By and by
+Joe timidly ventured upon a roundabout "feeler" as to how the others
+might look upon a return to civilization--not right now, but--
+
+Tom withered him with derision! Huck, being uncommitted as yet, joined
+in with Tom, and the waverer quickly "explained," and was glad to get
+out of the scrape with as little taint of chicken-hearted homesickness
+clinging to his garments as he could. Mutiny was effectually laid to
+rest for the moment.
+
+As the night deepened, Huck began to nod, and presently to snore. Joe
+followed next. Tom lay upon his elbow motionless, for some time,
+watching the two intently. At last he got up cautiously, on his knees,
+and went searching among the grass and the flickering reflections flung
+by the camp-fire. He picked up and inspected several large
+semi-cylinders of the thin white bark of a sycamore, and finally chose
+two which seemed to suit him. Then he knelt by the fire and painfully
+wrote something upon each of these with his "red keel"; one he rolled up
+and put in his jacket pocket, and the other he put in Joe's hat and
+removed it to a little distance from the owner. And he also put into the
+hat certain schoolboy treasures of almost inestimable value--among them
+a lump of chalk, an India-rubber ball, three fishhooks, and one of that
+kind of marbles known as a "sure 'nough crystal." Then he tiptoed his
+way cautiously among the trees till he felt that he was out of hearing,
+and straightway broke into a keen run in the direction of the sandbar.
+
+
+
+CHAPTER XV
+
+A FEW minutes later Tom was in the shoal water of the bar, wading
+toward the Illinois shore. Before the depth reached his middle he was
+half-way over; the current would permit no more wading, now, so he
+struck out confidently to swim the remaining hundred yards. He swam
+quartering upstream, but still was swept downward rather faster than he
+had expected. However, he reached the shore finally, and drifted along
+till he found a low place and drew himself out. He put his hand on his
+jacket pocket, found his piece of bark safe, and then struck through
+the woods, following the shore, with streaming garments. Shortly before
+ten o'clock he came out into an open place opposite the village, and
+saw the ferryboat lying in the shadow of the trees and the high bank.
+Everything was quiet under the blinking stars. He crept down the bank,
+watching with all his eyes, slipped into the water, swam three or four
+strokes and climbed into the skiff that did "yawl" duty at the boat's
+stern. He laid himself down under the thwarts and waited, panting.
+
+Presently the cracked bell tapped and a voice gave the order to "cast
+off." A minute or two later the skiff's head was standing high up,
+against the boat's swell, and the voyage was begun. Tom felt happy in
+his success, for he knew it was the boat's last trip for the night. At
+the end of a long twelve or fifteen minutes the wheels stopped, and Tom
+slipped overboard and swam ashore in the dusk, landing fifty yards
+downstream, out of danger of possible stragglers.
+
+He flew along unfrequented alleys, and shortly found himself at his
+aunt's back fence. He climbed over, approached the "ell," and looked in
+at the sitting-room window, for a light was burning there. There sat
+Aunt Polly, Sid, Mary, and Joe Harper's mother, grouped together,
+talking. They were by the bed, and the bed was between them and the
+door. Tom went to the door and began to softly lift the latch; then he
+pressed gently and the door yielded a crack; he continued pushing
+cautiously, and quaking every time it creaked, till he judged he might
+squeeze through on his knees; so he put his head through and began,
+warily.
+
+"What makes the candle blow so?" said Aunt Polly. Tom hurried up.
+"Why, that door's open, I believe. Why, of course it is. No end of
+strange things now. Go 'long and shut it, Sid."
+
+Tom disappeared under the bed just in time. He lay and "breathed"
+himself for a time, and then crept to where he could almost touch his
+aunt's foot.
+
+"But as I was saying," said Aunt Polly, "he warn't BAD, so to say
+--only mischEEvous. Only just giddy, and harum-scarum, you know. He
+warn't any more responsible than a colt. HE never meant any harm, and
+he was the best-hearted boy that ever was"--and she began to cry.
+
+"It was just so with my Joe--always full of his devilment, and up to
+every kind of mischief, but he was just as unselfish and kind as he
+could be--and laws bless me, to think I went and whipped him for taking
+that cream, never once recollecting that I throwed it out myself
+because it was sour, and I never to see him again in this world, never,
+never, never, poor abused boy!" And Mrs. Harper sobbed as if her heart
+would break.
+
+"I hope Tom's better off where he is," said Sid, "but if he'd been
+better in some ways--"
+
+"SID!" Tom felt the glare of the old lady's eye, though he could not
+see it. "Not a word against my Tom, now that he's gone! God'll take
+care of HIM--never you trouble YOURself, sir! Oh, Mrs. Harper, I don't
+know how to give him up! I don't know how to give him up! He was such a
+comfort to me, although he tormented my old heart out of me, 'most."
+
+"The Lord giveth and the Lord hath taken away--Blessed be the name of
+the Lord! But it's so hard--Oh, it's so hard! Only last Saturday my
+Joe busted a firecracker right under my nose and I knocked him
+sprawling. Little did I know then, how soon--Oh, if it was to do over
+again I'd hug him and bless him for it."
+
+"Yes, yes, yes, I know just how you feel, Mrs. Harper, I know just
+exactly how you feel. No longer ago than yesterday noon, my Tom took
+and filled the cat full of Pain-killer, and I did think the cretur
+would tear the house down. And God forgive me, I cracked Tom's head
+with my thimble, poor boy, poor dead boy. But he's out of all his
+troubles now. And the last words I ever heard him say was to reproach--"
+
+But this memory was too much for the old lady, and she broke entirely
+down. Tom was snuffling, now, himself--and more in pity of himself than
+anybody else. He could hear Mary crying, and putting in a kindly word
+for him from time to time. He began to have a nobler opinion of himself
+than ever before. Still, he was sufficiently touched by his aunt's
+grief to long to rush out from under the bed and overwhelm her with
+joy--and the theatrical gorgeousness of the thing appealed strongly to
+his nature, too, but he resisted and lay still.
+
+He went on listening, and gathered by odds and ends that it was
+conjectured at first that the boys had got drowned while taking a swim;
+then the small raft had been missed; next, certain boys said the
+missing lads had promised that the village should "hear something"
+soon; the wise-heads had "put this and that together" and decided that
+the lads had gone off on that raft and would turn up at the next town
+below, presently; but toward noon the raft had been found, lodged
+against the Missouri shore some five or six miles below the village
+--and then hope perished; they must be drowned, else hunger would have
+driven them home by nightfall if not sooner. It was believed that the
+search for the bodies had been a fruitless effort merely because the
+drowning must have occurred in mid-channel, since the boys, being good
+swimmers, would otherwise have escaped to shore. This was Wednesday
+night. If the bodies continued missing until Sunday, all hope would be
+given over, and the funerals would be preached on that morning. Tom
+shuddered.
+
+Mrs. Harper gave a sobbing good-night and turned to go. Then with a
+mutual impulse the two bereaved women flung themselves into each
+other's arms and had a good, consoling cry, and then parted. Aunt Polly
+was tender far beyond her wont, in her good-night to Sid and Mary. Sid
+snuffled a bit and Mary went off crying with all her heart.
+
+Aunt Polly knelt down and prayed for Tom so touchingly, so
+appealingly, and with such measureless love in her words and her old
+trembling voice, that he was weltering in tears again, long before she
+was through.
+
+He had to keep still long after she went to bed, for she kept making
+broken-hearted ejaculations from time to time, tossing unrestfully, and
+turning over. But at last she was still, only moaning a little in her
+sleep. Now the boy stole out, rose gradually by the bedside, shaded the
+candle-light with his hand, and stood regarding her. His heart was full
+of pity for her. He took out his sycamore scroll and placed it by the
+candle. But something occurred to him, and he lingered considering. His
+face lighted with a happy solution of his thought; he put the bark
+hastily in his pocket. Then he bent over and kissed the faded lips, and
+straightway made his stealthy exit, latching the door behind him.
+
+He threaded his way back to the ferry landing, found nobody at large
+there, and walked boldly on board the boat, for he knew she was
+tenantless except that there was a watchman, who always turned in and
+slept like a graven image. He untied the skiff at the stern, slipped
+into it, and was soon rowing cautiously upstream. When he had pulled a
+mile above the village, he started quartering across and bent himself
+stoutly to his work. He hit the landing on the other side neatly, for
+this was a familiar bit of work to him. He was moved to capture the
+skiff, arguing that it might be considered a ship and therefore
+legitimate prey for a pirate, but he knew a thorough search would be
+made for it and that might end in revelations. So he stepped ashore and
+entered the woods.
+
+He sat down and took a long rest, torturing himself meanwhile to keep
+awake, and then started warily down the home-stretch. The night was far
+spent. It was broad daylight before he found himself fairly abreast the
+island bar. He rested again until the sun was well up and gilding the
+great river with its splendor, and then he plunged into the stream. A
+little later he paused, dripping, upon the threshold of the camp, and
+heard Joe say:
+
+"No, Tom's true-blue, Huck, and he'll come back. He won't desert. He
+knows that would be a disgrace to a pirate, and Tom's too proud for
+that sort of thing. He's up to something or other. Now I wonder what?"
+
+"Well, the things is ours, anyway, ain't they?"
+
+"Pretty near, but not yet, Huck. The writing says they are if he ain't
+back here to breakfast."
+
+"Which he is!" exclaimed Tom, with fine dramatic effect, stepping
+grandly into camp.
+
+A sumptuous breakfast of bacon and fish was shortly provided, and as
+the boys set to work upon it, Tom recounted (and adorned) his
+adventures. They were a vain and boastful company of heroes when the
+tale was done. Then Tom hid himself away in a shady nook to sleep till
+noon, and the other pirates got ready to fish and explore.
+
+
+
+CHAPTER XVI
+
+AFTER dinner all the gang turned out to hunt for turtle eggs on the
+bar. They went about poking sticks into the sand, and when they found a
+soft place they went down on their knees and dug with their hands.
+Sometimes they would take fifty or sixty eggs out of one hole. They
+were perfectly round white things a trifle smaller than an English
+walnut. They had a famous fried-egg feast that night, and another on
+Friday morning.
+
+After breakfast they went whooping and prancing out on the bar, and
+chased each other round and round, shedding clothes as they went, until
+they were naked, and then continued the frolic far away up the shoal
+water of the bar, against the stiff current, which latter tripped their
+legs from under them from time to time and greatly increased the fun.
+And now and then they stooped in a group and splashed water in each
+other's faces with their palms, gradually approaching each other, with
+averted faces to avoid the strangling sprays, and finally gripping and
+struggling till the best man ducked his neighbor, and then they all
+went under in a tangle of white legs and arms and came up blowing,
+sputtering, laughing, and gasping for breath at one and the same time.
+
+When they were well exhausted, they would run out and sprawl on the
+dry, hot sand, and lie there and cover themselves up with it, and by
+and by break for the water again and go through the original
+performance once more. Finally it occurred to them that their naked
+skin represented flesh-colored "tights" very fairly; so they drew a
+ring in the sand and had a circus--with three clowns in it, for none
+would yield this proudest post to his neighbor.
+
+Next they got their marbles and played "knucks" and "ring-taw" and
+"keeps" till that amusement grew stale. Then Joe and Huck had another
+swim, but Tom would not venture, because he found that in kicking off
+his trousers he had kicked his string of rattlesnake rattles off his
+ankle, and he wondered how he had escaped cramp so long without the
+protection of this mysterious charm. He did not venture again until he
+had found it, and by that time the other boys were tired and ready to
+rest. They gradually wandered apart, dropped into the "dumps," and fell
+to gazing longingly across the wide river to where the village lay
+drowsing in the sun. Tom found himself writing "BECKY" in the sand with
+his big toe; he scratched it out, and was angry with himself for his
+weakness. But he wrote it again, nevertheless; he could not help it. He
+erased it once more and then took himself out of temptation by driving
+the other boys together and joining them.
+
+But Joe's spirits had gone down almost beyond resurrection. He was so
+homesick that he could hardly endure the misery of it. The tears lay
+very near the surface. Huck was melancholy, too. Tom was downhearted,
+but tried hard not to show it. He had a secret which he was not ready
+to tell, yet, but if this mutinous depression was not broken up soon,
+he would have to bring it out. He said, with a great show of
+cheerfulness:
+
+"I bet there's been pirates on this island before, boys. We'll explore
+it again. They've hid treasures here somewhere. How'd you feel to light
+on a rotten chest full of gold and silver--hey?"
+
+But it roused only faint enthusiasm, which faded out, with no reply.
+Tom tried one or two other seductions; but they failed, too. It was
+discouraging work. Joe sat poking up the sand with a stick and looking
+very gloomy. Finally he said:
+
+"Oh, boys, let's give it up. I want to go home. It's so lonesome."
+
+"Oh no, Joe, you'll feel better by and by," said Tom. "Just think of
+the fishing that's here."
+
+"I don't care for fishing. I want to go home."
+
+"But, Joe, there ain't such another swimming-place anywhere."
+
+"Swimming's no good. I don't seem to care for it, somehow, when there
+ain't anybody to say I sha'n't go in. I mean to go home."
+
+"Oh, shucks! Baby! You want to see your mother, I reckon."
+
+"Yes, I DO want to see my mother--and you would, too, if you had one.
+I ain't any more baby than you are." And Joe snuffled a little.
+
+"Well, we'll let the cry-baby go home to his mother, won't we, Huck?
+Poor thing--does it want to see its mother? And so it shall. You like
+it here, don't you, Huck? We'll stay, won't we?"
+
+Huck said, "Y-e-s"--without any heart in it.
+
+"I'll never speak to you again as long as I live," said Joe, rising.
+"There now!" And he moved moodily away and began to dress himself.
+
+"Who cares!" said Tom. "Nobody wants you to. Go 'long home and get
+laughed at. Oh, you're a nice pirate. Huck and me ain't cry-babies.
+We'll stay, won't we, Huck? Let him go if he wants to. I reckon we can
+get along without him, per'aps."
+
+But Tom was uneasy, nevertheless, and was alarmed to see Joe go
+sullenly on with his dressing. And then it was discomforting to see
+Huck eying Joe's preparations so wistfully, and keeping up such an
+ominous silence. Presently, without a parting word, Joe began to wade
+off toward the Illinois shore. Tom's heart began to sink. He glanced at
+Huck. Huck could not bear the look, and dropped his eyes. Then he said:
+
+"I want to go, too, Tom. It was getting so lonesome anyway, and now
+it'll be worse. Let's us go, too, Tom."
+
+"I won't! You can all go, if you want to. I mean to stay."
+
+"Tom, I better go."
+
+"Well, go 'long--who's hendering you."
+
+Huck began to pick up his scattered clothes. He said:
+
+"Tom, I wisht you'd come, too. Now you think it over. We'll wait for
+you when we get to shore."
+
+"Well, you'll wait a blame long time, that's all."
+
+Huck started sorrowfully away, and Tom stood looking after him, with a
+strong desire tugging at his heart to yield his pride and go along too.
+He hoped the boys would stop, but they still waded slowly on. It
+suddenly dawned on Tom that it was become very lonely and still. He
+made one final struggle with his pride, and then darted after his
+comrades, yelling:
+
+"Wait! Wait! I want to tell you something!"
+
+They presently stopped and turned around. When he got to where they
+were, he began unfolding his secret, and they listened moodily till at
+last they saw the "point" he was driving at, and then they set up a
+war-whoop of applause and said it was "splendid!" and said if he had
+told them at first, they wouldn't have started away. He made a plausible
+excuse; but his real reason had been the fear that not even the secret
+would keep them with him any very great length of time, and so he had
+meant to hold it in reserve as a last seduction.
+
+The lads came gayly back and went at their sports again with a will,
+chattering all the time about Tom's stupendous plan and admiring the
+genius of it. After a dainty egg and fish dinner, Tom said he wanted to
+learn to smoke, now. Joe caught at the idea and said he would like to
+try, too. So Huck made pipes and filled them. These novices had never
+smoked anything before but cigars made of grape-vine, and they "bit"
+the tongue, and were not considered manly anyway.
+
+Now they stretched themselves out on their elbows and began to puff,
+charily, and with slender confidence. The smoke had an unpleasant
+taste, and they gagged a little, but Tom said:
+
+"Why, it's just as easy! If I'd a knowed this was all, I'd a learnt
+long ago."
+
+"So would I," said Joe. "It's just nothing."
+
+"Why, many a time I've looked at people smoking, and thought well I
+wish I could do that; but I never thought I could," said Tom.
+
+"That's just the way with me, hain't it, Huck? You've heard me talk
+just that way--haven't you, Huck? I'll leave it to Huck if I haven't."
+
+"Yes--heaps of times," said Huck.
+
+"Well, I have too," said Tom; "oh, hundreds of times. Once down by the
+slaughter-house. Don't you remember, Huck? Bob Tanner was there, and
+Johnny Miller, and Jeff Thatcher, when I said it. Don't you remember,
+Huck, 'bout me saying that?"
+
+"Yes, that's so," said Huck. "That was the day after I lost a white
+alley. No, 'twas the day before."
+
+"There--I told you so," said Tom. "Huck recollects it."
+
+"I bleeve I could smoke this pipe all day," said Joe. "I don't feel
+sick."
+
+"Neither do I," said Tom. "I could smoke it all day. But I bet you
+Jeff Thatcher couldn't."
+
+"Jeff Thatcher! Why, he'd keel over just with two draws. Just let him
+try it once. HE'D see!"
+
+"I bet he would. And Johnny Miller--I wish could see Johnny Miller
+tackle it once."
+
+"Oh, don't I!" said Joe. "Why, I bet you Johnny Miller couldn't any
+more do this than nothing. Just one little snifter would fetch HIM."
+
+"'Deed it would, Joe. Say--I wish the boys could see us now."
+
+"So do I."
+
+"Say--boys, don't say anything about it, and some time when they're
+around, I'll come up to you and say, 'Joe, got a pipe? I want a smoke.'
+And you'll say, kind of careless like, as if it warn't anything, you'll
+say, 'Yes, I got my OLD pipe, and another one, but my tobacker ain't
+very good.' And I'll say, 'Oh, that's all right, if it's STRONG
+enough.' And then you'll out with the pipes, and we'll light up just as
+ca'm, and then just see 'em look!"
+
+"By jings, that'll be gay, Tom! I wish it was NOW!"
+
+"So do I! And when we tell 'em we learned when we was off pirating,
+won't they wish they'd been along?"
+
+"Oh, I reckon not! I'll just BET they will!"
+
+So the talk ran on. But presently it began to flag a trifle, and grow
+disjointed. The silences widened; the expectoration marvellously
+increased. Every pore inside the boys' cheeks became a spouting
+fountain; they could scarcely bail out the cellars under their tongues
+fast enough to prevent an inundation; little overflowings down their
+throats occurred in spite of all they could do, and sudden retchings
+followed every time. Both boys were looking very pale and miserable,
+now. Joe's pipe dropped from his nerveless fingers. Tom's followed.
+Both fountains were going furiously and both pumps bailing with might
+and main. Joe said feebly:
+
+"I've lost my knife. I reckon I better go and find it."
+
+Tom said, with quivering lips and halting utterance:
+
+"I'll help you. You go over that way and I'll hunt around by the
+spring. No, you needn't come, Huck--we can find it."
+
+So Huck sat down again, and waited an hour. Then he found it lonesome,
+and went to find his comrades. They were wide apart in the woods, both
+very pale, both fast asleep. But something informed him that if they
+had had any trouble they had got rid of it.
+
+They were not talkative at supper that night. They had a humble look,
+and when Huck prepared his pipe after the meal and was going to prepare
+theirs, they said no, they were not feeling very well--something they
+ate at dinner had disagreed with them.
+
+About midnight Joe awoke, and called the boys. There was a brooding
+oppressiveness in the air that seemed to bode something. The boys
+huddled themselves together and sought the friendly companionship of
+the fire, though the dull dead heat of the breathless atmosphere was
+stifling. They sat still, intent and waiting. The solemn hush
+continued. Beyond the light of the fire everything was swallowed up in
+the blackness of darkness. Presently there came a quivering glow that
+vaguely revealed the foliage for a moment and then vanished. By and by
+another came, a little stronger. Then another. Then a faint moan came
+sighing through the branches of the forest and the boys felt a fleeting
+breath upon their cheeks, and shuddered with the fancy that the Spirit
+of the Night had gone by. There was a pause. Now a weird flash turned
+night into day and showed every little grass-blade, separate and
+distinct, that grew about their feet. And it showed three white,
+startled faces, too. A deep peal of thunder went rolling and tumbling
+down the heavens and lost itself in sullen rumblings in the distance. A
+sweep of chilly air passed by, rustling all the leaves and snowing the
+flaky ashes broadcast about the fire. Another fierce glare lit up the
+forest and an instant crash followed that seemed to rend the tree-tops
+right over the boys' heads. They clung together in terror, in the thick
+gloom that followed. A few big rain-drops fell pattering upon the
+leaves.
+
+"Quick! boys, go for the tent!" exclaimed Tom.
+
+They sprang away, stumbling over roots and among vines in the dark, no
+two plunging in the same direction. A furious blast roared through the
+trees, making everything sing as it went. One blinding flash after
+another came, and peal on peal of deafening thunder. And now a
+drenching rain poured down and the rising hurricane drove it in sheets
+along the ground. The boys cried out to each other, but the roaring
+wind and the booming thunder-blasts drowned their voices utterly.
+However, one by one they straggled in at last and took shelter under
+the tent, cold, scared, and streaming with water; but to have company
+in misery seemed something to be grateful for. They could not talk, the
+old sail flapped so furiously, even if the other noises would have
+allowed them. The tempest rose higher and higher, and presently the
+sail tore loose from its fastenings and went winging away on the blast.
+The boys seized each others' hands and fled, with many tumblings and
+bruises, to the shelter of a great oak that stood upon the river-bank.
+Now the battle was at its highest. Under the ceaseless conflagration of
+lightning that flamed in the skies, everything below stood out in
+clean-cut and shadowless distinctness: the bending trees, the billowy
+river, white with foam, the driving spray of spume-flakes, the dim
+outlines of the high bluffs on the other side, glimpsed through the
+drifting cloud-rack and the slanting veil of rain. Every little while
+some giant tree yielded the fight and fell crashing through the younger
+growth; and the unflagging thunder-peals came now in ear-splitting
+explosive bursts, keen and sharp, and unspeakably appalling. The storm
+culminated in one matchless effort that seemed likely to tear the island
+to pieces, burn it up, drown it to the tree-tops, blow it away, and
+deafen every creature in it, all at one and the same moment. It was a
+wild night for homeless young heads to be out in.
+
+But at last the battle was done, and the forces retired with weaker
+and weaker threatenings and grumblings, and peace resumed her sway. The
+boys went back to camp, a good deal awed; but they found there was
+still something to be thankful for, because the great sycamore, the
+shelter of their beds, was a ruin, now, blasted by the lightnings, and
+they were not under it when the catastrophe happened.
+
+Everything in camp was drenched, the camp-fire as well; for they were
+but heedless lads, like their generation, and had made no provision
+against rain. Here was matter for dismay, for they were soaked through
+and chilled. They were eloquent in their distress; but they presently
+discovered that the fire had eaten so far up under the great log it had
+been built against (where it curved upward and separated itself from
+the ground), that a handbreadth or so of it had escaped wetting; so
+they patiently wrought until, with shreds and bark gathered from the
+under sides of sheltered logs, they coaxed the fire to burn again. Then
+they piled on great dead boughs till they had a roaring furnace, and
+were glad-hearted once more. They dried their boiled ham and had a
+feast, and after that they sat by the fire and expanded and glorified
+their midnight adventure until morning, for there was not a dry spot to
+sleep on, anywhere around.
+
+As the sun began to steal in upon the boys, drowsiness came over them,
+and they went out on the sandbar and lay down to sleep. They got
+scorched out by and by, and drearily set about getting breakfast. After
+the meal they felt rusty, and stiff-jointed, and a little homesick once
+more. Tom saw the signs, and fell to cheering up the pirates as well as
+he could. But they cared nothing for marbles, or circus, or swimming,
+or anything. He reminded them of the imposing secret, and raised a ray
+of cheer. While it lasted, he got them interested in a new device. This
+was to knock off being pirates, for a while, and be Indians for a
+change. They were attracted by this idea; so it was not long before
+they were stripped, and striped from head to heel with black mud, like
+so many zebras--all of them chiefs, of course--and then they went
+tearing through the woods to attack an English settlement.
+
+By and by they separated into three hostile tribes, and darted upon
+each other from ambush with dreadful war-whoops, and killed and scalped
+each other by thousands. It was a gory day. Consequently it was an
+extremely satisfactory one.
+
+They assembled in camp toward supper-time, hungry and happy; but now a
+difficulty arose--hostile Indians could not break the bread of
+hospitality together without first making peace, and this was a simple
+impossibility without smoking a pipe of peace. There was no other
+process that ever they had heard of. Two of the savages almost wished
+they had remained pirates. However, there was no other way; so with
+such show of cheerfulness as they could muster they called for the pipe
+and took their whiff as it passed, in due form.
+
+And behold, they were glad they had gone into savagery, for they had
+gained something; they found that they could now smoke a little without
+having to go and hunt for a lost knife; they did not get sick enough to
+be seriously uncomfortable. They were not likely to fool away this high
+promise for lack of effort. No, they practised cautiously, after
+supper, with right fair success, and so they spent a jubilant evening.
+They were prouder and happier in their new acquirement than they would
+have been in the scalping and skinning of the Six Nations. We will
+leave them to smoke and chatter and brag, since we have no further use
+for them at present.
+
+
+
+CHAPTER XVII
+
+BUT there was no hilarity in the little town that same tranquil
+Saturday afternoon. The Harpers, and Aunt Polly's family, were being
+put into mourning, with great grief and many tears. An unusual quiet
+possessed the village, although it was ordinarily quiet enough, in all
+conscience. The villagers conducted their concerns with an absent air,
+and talked little; but they sighed often. The Saturday holiday seemed a
+burden to the children. They had no heart in their sports, and
+gradually gave them up.
+
+In the afternoon Becky Thatcher found herself moping about the
+deserted schoolhouse yard, and feeling very melancholy. But she found
+nothing there to comfort her. She soliloquized:
+
+"Oh, if I only had a brass andiron-knob again! But I haven't got
+anything now to remember him by." And she choked back a little sob.
+
+Presently she stopped, and said to herself:
+
+"It was right here. Oh, if it was to do over again, I wouldn't say
+that--I wouldn't say it for the whole world. But he's gone now; I'll
+never, never, never see him any more."
+
+This thought broke her down, and she wandered away, with tears rolling
+down her cheeks. Then quite a group of boys and girls--playmates of
+Tom's and Joe's--came by, and stood looking over the paling fence and
+talking in reverent tones of how Tom did so-and-so the last time they
+saw him, and how Joe said this and that small trifle (pregnant with
+awful prophecy, as they could easily see now!)--and each speaker
+pointed out the exact spot where the lost lads stood at the time, and
+then added something like "and I was a-standing just so--just as I am
+now, and as if you was him--I was as close as that--and he smiled, just
+this way--and then something seemed to go all over me, like--awful, you
+know--and I never thought what it meant, of course, but I can see now!"
+
+Then there was a dispute about who saw the dead boys last in life, and
+many claimed that dismal distinction, and offered evidences, more or
+less tampered with by the witness; and when it was ultimately decided
+who DID see the departed last, and exchanged the last words with them,
+the lucky parties took upon themselves a sort of sacred importance, and
+were gaped at and envied by all the rest. One poor chap, who had no
+other grandeur to offer, said with tolerably manifest pride in the
+remembrance:
+
+"Well, Tom Sawyer he licked me once."
+
+But that bid for glory was a failure. Most of the boys could say that,
+and so that cheapened the distinction too much. The group loitered
+away, still recalling memories of the lost heroes, in awed voices.
+
+When the Sunday-school hour was finished, the next morning, the bell
+began to toll, instead of ringing in the usual way. It was a very still
+Sabbath, and the mournful sound seemed in keeping with the musing hush
+that lay upon nature. The villagers began to gather, loitering a moment
+in the vestibule to converse in whispers about the sad event. But there
+was no whispering in the house; only the funereal rustling of dresses
+as the women gathered to their seats disturbed the silence there. None
+could remember when the little church had been so full before. There
+was finally a waiting pause, an expectant dumbness, and then Aunt Polly
+entered, followed by Sid and Mary, and they by the Harper family, all
+in deep black, and the whole congregation, the old minister as well,
+rose reverently and stood until the mourners were seated in the front
+pew. There was another communing silence, broken at intervals by
+muffled sobs, and then the minister spread his hands abroad and prayed.
+A moving hymn was sung, and the text followed: "I am the Resurrection
+and the Life."
+
+As the service proceeded, the clergyman drew such pictures of the
+graces, the winning ways, and the rare promise of the lost lads that
+every soul there, thinking he recognized these pictures, felt a pang in
+remembering that he had persistently blinded himself to them always
+before, and had as persistently seen only faults and flaws in the poor
+boys. The minister related many a touching incident in the lives of the
+departed, too, which illustrated their sweet, generous natures, and the
+people could easily see, now, how noble and beautiful those episodes
+were, and remembered with grief that at the time they occurred they had
+seemed rank rascalities, well deserving of the cowhide. The
+congregation became more and more moved, as the pathetic tale went on,
+till at last the whole company broke down and joined the weeping
+mourners in a chorus of anguished sobs, the preacher himself giving way
+to his feelings, and crying in the pulpit.
+
+There was a rustle in the gallery, which nobody noticed; a moment
+later the church door creaked; the minister raised his streaming eyes
+above his handkerchief, and stood transfixed! First one and then
+another pair of eyes followed the minister's, and then almost with one
+impulse the congregation rose and stared while the three dead boys came
+marching up the aisle, Tom in the lead, Joe next, and Huck, a ruin of
+drooping rags, sneaking sheepishly in the rear! They had been hid in
+the unused gallery listening to their own funeral sermon!
+
+Aunt Polly, Mary, and the Harpers threw themselves upon their restored
+ones, smothered them with kisses and poured out thanksgivings, while
+poor Huck stood abashed and uncomfortable, not knowing exactly what to
+do or where to hide from so many unwelcoming eyes. He wavered, and
+started to slink away, but Tom seized him and said:
+
+"Aunt Polly, it ain't fair. Somebody's got to be glad to see Huck."
+
+"And so they shall. I'm glad to see him, poor motherless thing!" And
+the loving attentions Aunt Polly lavished upon him were the one thing
+capable of making him more uncomfortable than he was before.
+
+Suddenly the minister shouted at the top of his voice: "Praise God
+from whom all blessings flow--SING!--and put your hearts in it!"
+
+And they did. Old Hundred swelled up with a triumphant burst, and
+while it shook the rafters Tom Sawyer the Pirate looked around upon the
+envying juveniles about him and confessed in his heart that this was
+the proudest moment of his life.
+
+As the "sold" congregation trooped out they said they would almost be
+willing to be made ridiculous again to hear Old Hundred sung like that
+once more.
+
+Tom got more cuffs and kisses that day--according to Aunt Polly's
+varying moods--than he had earned before in a year; and he hardly knew
+which expressed the most gratefulness to God and affection for himself.
+
+
+
+CHAPTER XVIII
+
+THAT was Tom's great secret--the scheme to return home with his
+brother pirates and attend their own funerals. They had paddled over to
+the Missouri shore on a log, at dusk on Saturday, landing five or six
+miles below the village; they had slept in the woods at the edge of the
+town till nearly daylight, and had then crept through back lanes and
+alleys and finished their sleep in the gallery of the church among a
+chaos of invalided benches.
+
+At breakfast, Monday morning, Aunt Polly and Mary were very loving to
+Tom, and very attentive to his wants. There was an unusual amount of
+talk. In the course of it Aunt Polly said:
+
+"Well, I don't say it wasn't a fine joke, Tom, to keep everybody
+suffering 'most a week so you boys had a good time, but it is a pity
+you could be so hard-hearted as to let me suffer so. If you could come
+over on a log to go to your funeral, you could have come over and give
+me a hint some way that you warn't dead, but only run off."
+
+"Yes, you could have done that, Tom," said Mary; "and I believe you
+would if you had thought of it."
+
+"Would you, Tom?" said Aunt Polly, her face lighting wistfully. "Say,
+now, would you, if you'd thought of it?"
+
+"I--well, I don't know. 'Twould 'a' spoiled everything."
+
+"Tom, I hoped you loved me that much," said Aunt Polly, with a grieved
+tone that discomforted the boy. "It would have been something if you'd
+cared enough to THINK of it, even if you didn't DO it."
+
+"Now, auntie, that ain't any harm," pleaded Mary; "it's only Tom's
+giddy way--he is always in such a rush that he never thinks of
+anything."
+
+"More's the pity. Sid would have thought. And Sid would have come and
+DONE it, too. Tom, you'll look back, some day, when it's too late, and
+wish you'd cared a little more for me when it would have cost you so
+little."
+
+"Now, auntie, you know I do care for you," said Tom.
+
+"I'd know it better if you acted more like it."
+
+"I wish now I'd thought," said Tom, with a repentant tone; "but I
+dreamt about you, anyway. That's something, ain't it?"
+
+"It ain't much--a cat does that much--but it's better than nothing.
+What did you dream?"
+
+"Why, Wednesday night I dreamt that you was sitting over there by the
+bed, and Sid was sitting by the woodbox, and Mary next to him."
+
+"Well, so we did. So we always do. I'm glad your dreams could take
+even that much trouble about us."
+
+"And I dreamt that Joe Harper's mother was here."
+
+"Why, she was here! Did you dream any more?"
+
+"Oh, lots. But it's so dim, now."
+
+"Well, try to recollect--can't you?"
+
+"Somehow it seems to me that the wind--the wind blowed the--the--"
+
+"Try harder, Tom! The wind did blow something. Come!"
+
+Tom pressed his fingers on his forehead an anxious minute, and then
+said:
+
+"I've got it now! I've got it now! It blowed the candle!"
+
+"Mercy on us! Go on, Tom--go on!"
+
+"And it seems to me that you said, 'Why, I believe that that door--'"
+
+"Go ON, Tom!"
+
+"Just let me study a moment--just a moment. Oh, yes--you said you
+believed the door was open."
+
+"As I'm sitting here, I did! Didn't I, Mary! Go on!"
+
+"And then--and then--well I won't be certain, but it seems like as if
+you made Sid go and--and--"
+
+"Well? Well? What did I make him do, Tom? What did I make him do?"
+
+"You made him--you--Oh, you made him shut it."
+
+"Well, for the land's sake! I never heard the beat of that in all my
+days! Don't tell ME there ain't anything in dreams, any more. Sereny
+Harper shall know of this before I'm an hour older. I'd like to see her
+get around THIS with her rubbage 'bout superstition. Go on, Tom!"
+
+"Oh, it's all getting just as bright as day, now. Next you said I
+warn't BAD, only mischeevous and harum-scarum, and not any more
+responsible than--than--I think it was a colt, or something."
+
+"And so it was! Well, goodness gracious! Go on, Tom!"
+
+"And then you began to cry."
+
+"So I did. So I did. Not the first time, neither. And then--"
+
+"Then Mrs. Harper she began to cry, and said Joe was just the same,
+and she wished she hadn't whipped him for taking cream when she'd
+throwed it out her own self--"
+
+"Tom! The sperrit was upon you! You was a prophesying--that's what you
+was doing! Land alive, go on, Tom!"
+
+"Then Sid he said--he said--"
+
+"I don't think I said anything," said Sid.
+
+"Yes you did, Sid," said Mary.
+
+"Shut your heads and let Tom go on! What did he say, Tom?"
+
+"He said--I THINK he said he hoped I was better off where I was gone
+to, but if I'd been better sometimes--"
+
+"THERE, d'you hear that! It was his very words!"
+
+"And you shut him up sharp."
+
+"I lay I did! There must 'a' been an angel there. There WAS an angel
+there, somewheres!"
+
+"And Mrs. Harper told about Joe scaring her with a firecracker, and
+you told about Peter and the Painkiller--"
+
+"Just as true as I live!"
+
+"And then there was a whole lot of talk 'bout dragging the river for
+us, and 'bout having the funeral Sunday, and then you and old Miss
+Harper hugged and cried, and she went."
+
+"It happened just so! It happened just so, as sure as I'm a-sitting in
+these very tracks. Tom, you couldn't told it more like if you'd 'a'
+seen it! And then what? Go on, Tom!"
+
+"Then I thought you prayed for me--and I could see you and hear every
+word you said. And you went to bed, and I was so sorry that I took and
+wrote on a piece of sycamore bark, 'We ain't dead--we are only off
+being pirates,' and put it on the table by the candle; and then you
+looked so good, laying there asleep, that I thought I went and leaned
+over and kissed you on the lips."
+
+"Did you, Tom, DID you! I just forgive you everything for that!" And
+she seized the boy in a crushing embrace that made him feel like the
+guiltiest of villains.
+
+"It was very kind, even though it was only a--dream," Sid soliloquized
+just audibly.
+
+"Shut up, Sid! A body does just the same in a dream as he'd do if he
+was awake. Here's a big Milum apple I've been saving for you, Tom, if
+you was ever found again--now go 'long to school. I'm thankful to the
+good God and Father of us all I've got you back, that's long-suffering
+and merciful to them that believe on Him and keep His word, though
+goodness knows I'm unworthy of it, but if only the worthy ones got His
+blessings and had His hand to help them over the rough places, there's
+few enough would smile here or ever enter into His rest when the long
+night comes. Go 'long Sid, Mary, Tom--take yourselves off--you've
+hendered me long enough."
+
+The children left for school, and the old lady to call on Mrs. Harper
+and vanquish her realism with Tom's marvellous dream. Sid had better
+judgment than to utter the thought that was in his mind as he left the
+house. It was this: "Pretty thin--as long a dream as that, without any
+mistakes in it!"
+
+What a hero Tom was become, now! He did not go skipping and prancing,
+but moved with a dignified swagger as became a pirate who felt that the
+public eye was on him. And indeed it was; he tried not to seem to see
+the looks or hear the remarks as he passed along, but they were food
+and drink to him. Smaller boys than himself flocked at his heels, as
+proud to be seen with him, and tolerated by him, as if he had been the
+drummer at the head of a procession or the elephant leading a menagerie
+into town. Boys of his own size pretended not to know he had been away
+at all; but they were consuming with envy, nevertheless. They would
+have given anything to have that swarthy suntanned skin of his, and his
+glittering notoriety; and Tom would not have parted with either for a
+circus.
+
+At school the children made so much of him and of Joe, and delivered
+such eloquent admiration from their eyes, that the two heroes were not
+long in becoming insufferably "stuck-up." They began to tell their
+adventures to hungry listeners--but they only began; it was not a thing
+likely to have an end, with imaginations like theirs to furnish
+material. And finally, when they got out their pipes and went serenely
+puffing around, the very summit of glory was reached.
+
+Tom decided that he could be independent of Becky Thatcher now. Glory
+was sufficient. He would live for glory. Now that he was distinguished,
+maybe she would be wanting to "make up." Well, let her--she should see
+that he could be as indifferent as some other people. Presently she
+arrived. Tom pretended not to see her. He moved away and joined a group
+of boys and girls and began to talk. Soon he observed that she was
+tripping gayly back and forth with flushed face and dancing eyes,
+pretending to be busy chasing schoolmates, and screaming with laughter
+when she made a capture; but he noticed that she always made her
+captures in his vicinity, and that she seemed to cast a conscious eye
+in his direction at such times, too. It gratified all the vicious
+vanity that was in him; and so, instead of winning him, it only "set
+him up" the more and made him the more diligent to avoid betraying that
+he knew she was about. Presently she gave over skylarking, and moved
+irresolutely about, sighing once or twice and glancing furtively and
+wistfully toward Tom. Then she observed that now Tom was talking more
+particularly to Amy Lawrence than to any one else. She felt a sharp
+pang and grew disturbed and uneasy at once. She tried to go away, but
+her feet were treacherous, and carried her to the group instead. She
+said to a girl almost at Tom's elbow--with sham vivacity:
+
+"Why, Mary Austin! you bad girl, why didn't you come to Sunday-school?"
+
+"I did come--didn't you see me?"
+
+"Why, no! Did you? Where did you sit?"
+
+"I was in Miss Peters' class, where I always go. I saw YOU."
+
+"Did you? Why, it's funny I didn't see you. I wanted to tell you about
+the picnic."
+
+"Oh, that's jolly. Who's going to give it?"
+
+"My ma's going to let me have one."
+
+"Oh, goody; I hope she'll let ME come."
+
+"Well, she will. The picnic's for me. She'll let anybody come that I
+want, and I want you."
+
+"That's ever so nice. When is it going to be?"
+
+"By and by. Maybe about vacation."
+
+"Oh, won't it be fun! You going to have all the girls and boys?"
+
+"Yes, every one that's friends to me--or wants to be"; and she glanced
+ever so furtively at Tom, but he talked right along to Amy Lawrence
+about the terrible storm on the island, and how the lightning tore the
+great sycamore tree "all to flinders" while he was "standing within
+three feet of it."
+
+"Oh, may I come?" said Grace Miller.
+
+"Yes."
+
+"And me?" said Sally Rogers.
+
+"Yes."
+
+"And me, too?" said Susy Harper. "And Joe?"
+
+"Yes."
+
+And so on, with clapping of joyful hands till all the group had begged
+for invitations but Tom and Amy. Then Tom turned coolly away, still
+talking, and took Amy with him. Becky's lips trembled and the tears
+came to her eyes; she hid these signs with a forced gayety and went on
+chattering, but the life had gone out of the picnic, now, and out of
+everything else; she got away as soon as she could and hid herself and
+had what her sex call "a good cry." Then she sat moody, with wounded
+pride, till the bell rang. She roused up, now, with a vindictive cast
+in her eye, and gave her plaited tails a shake and said she knew what
+SHE'D do.
+
+At recess Tom continued his flirtation with Amy with jubilant
+self-satisfaction. And he kept drifting about to find Becky and lacerate
+her with the performance. At last he spied her, but there was a sudden
+falling of his mercury. She was sitting cosily on a little bench behind
+the schoolhouse looking at a picture-book with Alfred Temple--and so
+absorbed were they, and their heads so close together over the book,
+that they did not seem to be conscious of anything in the world besides.
+Jealousy ran red-hot through Tom's veins. He began to hate himself for
+throwing away the chance Becky had offered for a reconciliation. He
+called himself a fool, and all the hard names he could think of. He
+wanted to cry with vexation. Amy chatted happily along, as they walked,
+for her heart was singing, but Tom's tongue had lost its function. He
+did not hear what Amy was saying, and whenever she paused expectantly he
+could only stammer an awkward assent, which was as often misplaced as
+otherwise. He kept drifting to the rear of the schoolhouse, again and
+again, to sear his eyeballs with the hateful spectacle there. He could
+not help it. And it maddened him to see, as he thought he saw, that
+Becky Thatcher never once suspected that he was even in the land of the
+living. But she did see, nevertheless; and she knew she was winning her
+fight, too, and was glad to see him suffer as she had suffered.
+
+Amy's happy prattle became intolerable. Tom hinted at things he had to
+attend to; things that must be done; and time was fleeting. But in
+vain--the girl chirped on. Tom thought, "Oh, hang her, ain't I ever
+going to get rid of her?" At last he must be attending to those
+things--and she said artlessly that she would be "around" when school
+let out. And he hastened away, hating her for it.
+
+"Any other boy!" Tom thought, grating his teeth. "Any boy in the whole
+town but that Saint Louis smarty that thinks he dresses so fine and is
+aristocracy! Oh, all right, I licked you the first day you ever saw
+this town, mister, and I'll lick you again! You just wait till I catch
+you out! I'll just take and--"
+
+And he went through the motions of thrashing an imaginary boy
+--pummelling the air, and kicking and gouging. "Oh, you do, do you? You
+holler 'nough, do you? Now, then, let that learn you!" And so the
+imaginary flogging was finished to his satisfaction.
+
+Tom fled home at noon. His conscience could not endure any more of
+Amy's grateful happiness, and his jealousy could bear no more of the
+other distress. Becky resumed her picture inspections with Alfred, but
+as the minutes dragged along and no Tom came to suffer, her triumph
+began to cloud and she lost interest; gravity and absent-mindedness
+followed, and then melancholy; two or three times she pricked up her
+ear at a footstep, but it was a false hope; no Tom came. At last she
+grew entirely miserable and wished she hadn't carried it so far. When
+poor Alfred, seeing that he was losing her, he did not know how, kept
+exclaiming: "Oh, here's a jolly one! look at this!" she lost patience
+at last, and said, "Oh, don't bother me! I don't care for them!" and
+burst into tears, and got up and walked away.
+
+Alfred dropped alongside and was going to try to comfort her, but she
+said:
+
+"Go away and leave me alone, can't you! I hate you!"
+
+So the boy halted, wondering what he could have done--for she had said
+she would look at pictures all through the nooning--and she walked on,
+crying. Then Alfred went musing into the deserted schoolhouse. He was
+humiliated and angry. He easily guessed his way to the truth--the girl
+had simply made a convenience of him to vent her spite upon Tom Sawyer.
+He was far from hating Tom the less when this thought occurred to him.
+He wished there was some way to get that boy into trouble without much
+risk to himself. Tom's spelling-book fell under his eye. Here was his
+opportunity. He gratefully opened to the lesson for the afternoon and
+poured ink upon the page.
+
+Becky, glancing in at a window behind him at the moment, saw the act,
+and moved on, without discovering herself. She started homeward, now,
+intending to find Tom and tell him; Tom would be thankful and their
+troubles would be healed. Before she was half way home, however, she
+had changed her mind. The thought of Tom's treatment of her when she
+was talking about her picnic came scorching back and filled her with
+shame. She resolved to let him get whipped on the damaged
+spelling-book's account, and to hate him forever, into the bargain.
+
+
+
+CHAPTER XIX
+
+TOM arrived at home in a dreary mood, and the first thing his aunt
+said to him showed him that he had brought his sorrows to an
+unpromising market:
+
+"Tom, I've a notion to skin you alive!"
+
+"Auntie, what have I done?"
+
+"Well, you've done enough. Here I go over to Sereny Harper, like an
+old softy, expecting I'm going to make her believe all that rubbage
+about that dream, when lo and behold you she'd found out from Joe that
+you was over here and heard all the talk we had that night. Tom, I
+don't know what is to become of a boy that will act like that. It makes
+me feel so bad to think you could let me go to Sereny Harper and make
+such a fool of myself and never say a word."
+
+This was a new aspect of the thing. His smartness of the morning had
+seemed to Tom a good joke before, and very ingenious. It merely looked
+mean and shabby now. He hung his head and could not think of anything
+to say for a moment. Then he said:
+
+"Auntie, I wish I hadn't done it--but I didn't think."
+
+"Oh, child, you never think. You never think of anything but your own
+selfishness. You could think to come all the way over here from
+Jackson's Island in the night to laugh at our troubles, and you could
+think to fool me with a lie about a dream; but you couldn't ever think
+to pity us and save us from sorrow."
+
+"Auntie, I know now it was mean, but I didn't mean to be mean. I
+didn't, honest. And besides, I didn't come over here to laugh at you
+that night."
+
+"What did you come for, then?"
+
+"It was to tell you not to be uneasy about us, because we hadn't got
+drownded."
+
+"Tom, Tom, I would be the thankfullest soul in this world if I could
+believe you ever had as good a thought as that, but you know you never
+did--and I know it, Tom."
+
+"Indeed and 'deed I did, auntie--I wish I may never stir if I didn't."
+
+"Oh, Tom, don't lie--don't do it. It only makes things a hundred times
+worse."
+
+"It ain't a lie, auntie; it's the truth. I wanted to keep you from
+grieving--that was all that made me come."
+
+"I'd give the whole world to believe that--it would cover up a power
+of sins, Tom. I'd 'most be glad you'd run off and acted so bad. But it
+ain't reasonable; because, why didn't you tell me, child?"
+
+"Why, you see, when you got to talking about the funeral, I just got
+all full of the idea of our coming and hiding in the church, and I
+couldn't somehow bear to spoil it. So I just put the bark back in my
+pocket and kept mum."
+
+"What bark?"
+
+"The bark I had wrote on to tell you we'd gone pirating. I wish, now,
+you'd waked up when I kissed you--I do, honest."
+
+The hard lines in his aunt's face relaxed and a sudden tenderness
+dawned in her eyes.
+
+"DID you kiss me, Tom?"
+
+"Why, yes, I did."
+
+"Are you sure you did, Tom?"
+
+"Why, yes, I did, auntie--certain sure."
+
+"What did you kiss me for, Tom?"
+
+"Because I loved you so, and you laid there moaning and I was so sorry."
+
+The words sounded like truth. The old lady could not hide a tremor in
+her voice when she said:
+
+"Kiss me again, Tom!--and be off with you to school, now, and don't
+bother me any more."
+
+The moment he was gone, she ran to a closet and got out the ruin of a
+jacket which Tom had gone pirating in. Then she stopped, with it in her
+hand, and said to herself:
+
+"No, I don't dare. Poor boy, I reckon he's lied about it--but it's a
+blessed, blessed lie, there's such a comfort come from it. I hope the
+Lord--I KNOW the Lord will forgive him, because it was such
+goodheartedness in him to tell it. But I don't want to find out it's a
+lie. I won't look."
+
+She put the jacket away, and stood by musing a minute. Twice she put
+out her hand to take the garment again, and twice she refrained. Once
+more she ventured, and this time she fortified herself with the
+thought: "It's a good lie--it's a good lie--I won't let it grieve me."
+So she sought the jacket pocket. A moment later she was reading Tom's
+piece of bark through flowing tears and saying: "I could forgive the
+boy, now, if he'd committed a million sins!"
+
+
+
+CHAPTER XX
+
+THERE was something about Aunt Polly's manner, when she kissed Tom,
+that swept away his low spirits and made him lighthearted and happy
+again. He started to school and had the luck of coming upon Becky
+Thatcher at the head of Meadow Lane. His mood always determined his
+manner. Without a moment's hesitation he ran to her and said:
+
+"I acted mighty mean to-day, Becky, and I'm so sorry. I won't ever,
+ever do that way again, as long as ever I live--please make up, won't
+you?"
+
+The girl stopped and looked him scornfully in the face:
+
+"I'll thank you to keep yourself TO yourself, Mr. Thomas Sawyer. I'll
+never speak to you again."
+
+She tossed her head and passed on. Tom was so stunned that he had not
+even presence of mind enough to say "Who cares, Miss Smarty?" until the
+right time to say it had gone by. So he said nothing. But he was in a
+fine rage, nevertheless. He moped into the schoolyard wishing she were
+a boy, and imagining how he would trounce her if she were. He presently
+encountered her and delivered a stinging remark as he passed. She
+hurled one in return, and the angry breach was complete. It seemed to
+Becky, in her hot resentment, that she could hardly wait for school to
+"take in," she was so impatient to see Tom flogged for the injured
+spelling-book. If she had had any lingering notion of exposing Alfred
+Temple, Tom's offensive fling had driven it entirely away.
+
+Poor girl, she did not know how fast she was nearing trouble herself.
+The master, Mr. Dobbins, had reached middle age with an unsatisfied
+ambition. The darling of his desires was, to be a doctor, but poverty
+had decreed that he should be nothing higher than a village
+schoolmaster. Every day he took a mysterious book out of his desk and
+absorbed himself in it at times when no classes were reciting. He kept
+that book under lock and key. There was not an urchin in school but was
+perishing to have a glimpse of it, but the chance never came. Every boy
+and girl had a theory about the nature of that book; but no two
+theories were alike, and there was no way of getting at the facts in
+the case. Now, as Becky was passing by the desk, which stood near the
+door, she noticed that the key was in the lock! It was a precious
+moment. She glanced around; found herself alone, and the next instant
+she had the book in her hands. The title-page--Professor Somebody's
+ANATOMY--carried no information to her mind; so she began to turn the
+leaves. She came at once upon a handsomely engraved and colored
+frontispiece--a human figure, stark naked. At that moment a shadow fell
+on the page and Tom Sawyer stepped in at the door and caught a glimpse
+of the picture. Becky snatched at the book to close it, and had the
+hard luck to tear the pictured page half down the middle. She thrust
+the volume into the desk, turned the key, and burst out crying with
+shame and vexation.
+
+"Tom Sawyer, you are just as mean as you can be, to sneak up on a
+person and look at what they're looking at."
+
+"How could I know you was looking at anything?"
+
+"You ought to be ashamed of yourself, Tom Sawyer; you know you're
+going to tell on me, and oh, what shall I do, what shall I do! I'll be
+whipped, and I never was whipped in school."
+
+Then she stamped her little foot and said:
+
+"BE so mean if you want to! I know something that's going to happen.
+You just wait and you'll see! Hateful, hateful, hateful!"--and she
+flung out of the house with a new explosion of crying.
+
+Tom stood still, rather flustered by this onslaught. Presently he said
+to himself:
+
+"What a curious kind of a fool a girl is! Never been licked in school!
+Shucks! What's a licking! That's just like a girl--they're so
+thin-skinned and chicken-hearted. Well, of course I ain't going to tell
+old Dobbins on this little fool, because there's other ways of getting
+even on her, that ain't so mean; but what of it? Old Dobbins will ask
+who it was tore his book. Nobody'll answer. Then he'll do just the way
+he always does--ask first one and then t'other, and when he comes to the
+right girl he'll know it, without any telling. Girls' faces always tell
+on them. They ain't got any backbone. She'll get licked. Well, it's a
+kind of a tight place for Becky Thatcher, because there ain't any way
+out of it." Tom conned the thing a moment longer, and then added: "All
+right, though; she'd like to see me in just such a fix--let her sweat it
+out!"
+
+Tom joined the mob of skylarking scholars outside. In a few moments
+the master arrived and school "took in." Tom did not feel a strong
+interest in his studies. Every time he stole a glance at the girls'
+side of the room Becky's face troubled him. Considering all things, he
+did not want to pity her, and yet it was all he could do to help it. He
+could get up no exultation that was really worthy the name. Presently
+the spelling-book discovery was made, and Tom's mind was entirely full
+of his own matters for a while after that. Becky roused up from her
+lethargy of distress and showed good interest in the proceedings. She
+did not expect that Tom could get out of his trouble by denying that he
+spilt the ink on the book himself; and she was right. The denial only
+seemed to make the thing worse for Tom. Becky supposed she would be
+glad of that, and she tried to believe she was glad of it, but she
+found she was not certain. When the worst came to the worst, she had an
+impulse to get up and tell on Alfred Temple, but she made an effort and
+forced herself to keep still--because, said she to herself, "he'll tell
+about me tearing the picture sure. I wouldn't say a word, not to save
+his life!"
+
+Tom took his whipping and went back to his seat not at all
+broken-hearted, for he thought it was possible that he had unknowingly
+upset the ink on the spelling-book himself, in some skylarking bout--he
+had denied it for form's sake and because it was custom, and had stuck
+to the denial from principle.
+
+A whole hour drifted by, the master sat nodding in his throne, the air
+was drowsy with the hum of study. By and by, Mr. Dobbins straightened
+himself up, yawned, then unlocked his desk, and reached for his book,
+but seemed undecided whether to take it out or leave it. Most of the
+pupils glanced up languidly, but there were two among them that watched
+his movements with intent eyes. Mr. Dobbins fingered his book absently
+for a while, then took it out and settled himself in his chair to read!
+Tom shot a glance at Becky. He had seen a hunted and helpless rabbit
+look as she did, with a gun levelled at its head. Instantly he forgot
+his quarrel with her. Quick--something must be done! done in a flash,
+too! But the very imminence of the emergency paralyzed his invention.
+Good!--he had an inspiration! He would run and snatch the book, spring
+through the door and fly. But his resolution shook for one little
+instant, and the chance was lost--the master opened the volume. If Tom
+only had the wasted opportunity back again! Too late. There was no help
+for Becky now, he said. The next moment the master faced the school.
+Every eye sank under his gaze. There was that in it which smote even
+the innocent with fear. There was silence while one might count ten
+--the master was gathering his wrath. Then he spoke: "Who tore this book?"
+
+There was not a sound. One could have heard a pin drop. The stillness
+continued; the master searched face after face for signs of guilt.
+
+"Benjamin Rogers, did you tear this book?"
+
+A denial. Another pause.
+
+"Joseph Harper, did you?"
+
+Another denial. Tom's uneasiness grew more and more intense under the
+slow torture of these proceedings. The master scanned the ranks of
+boys--considered a while, then turned to the girls:
+
+"Amy Lawrence?"
+
+A shake of the head.
+
+"Gracie Miller?"
+
+The same sign.
+
+"Susan Harper, did you do this?"
+
+Another negative. The next girl was Becky Thatcher. Tom was trembling
+from head to foot with excitement and a sense of the hopelessness of
+the situation.
+
+"Rebecca Thatcher" [Tom glanced at her face--it was white with terror]
+--"did you tear--no, look me in the face" [her hands rose in appeal]
+--"did you tear this book?"
+
+A thought shot like lightning through Tom's brain. He sprang to his
+feet and shouted--"I done it!"
+
+The school stared in perplexity at this incredible folly. Tom stood a
+moment, to gather his dismembered faculties; and when he stepped
+forward to go to his punishment the surprise, the gratitude, the
+adoration that shone upon him out of poor Becky's eyes seemed pay
+enough for a hundred floggings. Inspired by the splendor of his own
+act, he took without an outcry the most merciless flaying that even Mr.
+Dobbins had ever administered; and also received with indifference the
+added cruelty of a command to remain two hours after school should be
+dismissed--for he knew who would wait for him outside till his
+captivity was done, and not count the tedious time as loss, either.
+
+Tom went to bed that night planning vengeance against Alfred Temple;
+for with shame and repentance Becky had told him all, not forgetting
+her own treachery; but even the longing for vengeance had to give way,
+soon, to pleasanter musings, and he fell asleep at last with Becky's
+latest words lingering dreamily in his ear--
+
+"Tom, how COULD you be so noble!"
+
+
+
+CHAPTER XXI
+
+VACATION was approaching. The schoolmaster, always severe, grew
+severer and more exacting than ever, for he wanted the school to make a
+good showing on "Examination" day. His rod and his ferule were seldom
+idle now--at least among the smaller pupils. Only the biggest boys, and
+young ladies of eighteen and twenty, escaped lashing. Mr. Dobbins'
+lashings were very vigorous ones, too; for although he carried, under
+his wig, a perfectly bald and shiny head, he had only reached middle
+age, and there was no sign of feebleness in his muscle. As the great
+day approached, all the tyranny that was in him came to the surface; he
+seemed to take a vindictive pleasure in punishing the least
+shortcomings. The consequence was, that the smaller boys spent their
+days in terror and suffering and their nights in plotting revenge. They
+threw away no opportunity to do the master a mischief. But he kept
+ahead all the time. The retribution that followed every vengeful
+success was so sweeping and majestic that the boys always retired from
+the field badly worsted. At last they conspired together and hit upon a
+plan that promised a dazzling victory. They swore in the sign-painter's
+boy, told him the scheme, and asked his help. He had his own reasons
+for being delighted, for the master boarded in his father's family and
+had given the boy ample cause to hate him. The master's wife would go
+on a visit to the country in a few days, and there would be nothing to
+interfere with the plan; the master always prepared himself for great
+occasions by getting pretty well fuddled, and the sign-painter's boy
+said that when the dominie had reached the proper condition on
+Examination Evening he would "manage the thing" while he napped in his
+chair; then he would have him awakened at the right time and hurried
+away to school.
+
+In the fulness of time the interesting occasion arrived. At eight in
+the evening the schoolhouse was brilliantly lighted, and adorned with
+wreaths and festoons of foliage and flowers. The master sat throned in
+his great chair upon a raised platform, with his blackboard behind him.
+He was looking tolerably mellow. Three rows of benches on each side and
+six rows in front of him were occupied by the dignitaries of the town
+and by the parents of the pupils. To his left, back of the rows of
+citizens, was a spacious temporary platform upon which were seated the
+scholars who were to take part in the exercises of the evening; rows of
+small boys, washed and dressed to an intolerable state of discomfort;
+rows of gawky big boys; snowbanks of girls and young ladies clad in
+lawn and muslin and conspicuously conscious of their bare arms, their
+grandmothers' ancient trinkets, their bits of pink and blue ribbon and
+the flowers in their hair. All the rest of the house was filled with
+non-participating scholars.
+
+The exercises began. A very little boy stood up and sheepishly
+recited, "You'd scarce expect one of my age to speak in public on the
+stage," etc.--accompanying himself with the painfully exact and
+spasmodic gestures which a machine might have used--supposing the
+machine to be a trifle out of order. But he got through safely, though
+cruelly scared, and got a fine round of applause when he made his
+manufactured bow and retired.
+
+A little shamefaced girl lisped, "Mary had a little lamb," etc.,
+performed a compassion-inspiring curtsy, got her meed of applause, and
+sat down flushed and happy.
+
+Tom Sawyer stepped forward with conceited confidence and soared into
+the unquenchable and indestructible "Give me liberty or give me death"
+speech, with fine fury and frantic gesticulation, and broke down in the
+middle of it. A ghastly stage-fright seized him, his legs quaked under
+him and he was like to choke. True, he had the manifest sympathy of the
+house but he had the house's silence, too, which was even worse than
+its sympathy. The master frowned, and this completed the disaster. Tom
+struggled awhile and then retired, utterly defeated. There was a weak
+attempt at applause, but it died early.
+
+"The Boy Stood on the Burning Deck" followed; also "The Assyrian Came
+Down," and other declamatory gems. Then there were reading exercises,
+and a spelling fight. The meagre Latin class recited with honor. The
+prime feature of the evening was in order, now--original "compositions"
+by the young ladies. Each in her turn stepped forward to the edge of
+the platform, cleared her throat, held up her manuscript (tied with
+dainty ribbon), and proceeded to read, with labored attention to
+"expression" and punctuation. The themes were the same that had been
+illuminated upon similar occasions by their mothers before them, their
+grandmothers, and doubtless all their ancestors in the female line
+clear back to the Crusades. "Friendship" was one; "Memories of Other
+Days"; "Religion in History"; "Dream Land"; "The Advantages of
+Culture"; "Forms of Political Government Compared and Contrasted";
+"Melancholy"; "Filial Love"; "Heart Longings," etc., etc.
+
+A prevalent feature in these compositions was a nursed and petted
+melancholy; another was a wasteful and opulent gush of "fine language";
+another was a tendency to lug in by the ears particularly prized words
+and phrases until they were worn entirely out; and a peculiarity that
+conspicuously marked and marred them was the inveterate and intolerable
+sermon that wagged its crippled tail at the end of each and every one
+of them. No matter what the subject might be, a brain-racking effort
+was made to squirm it into some aspect or other that the moral and
+religious mind could contemplate with edification. The glaring
+insincerity of these sermons was not sufficient to compass the
+banishment of the fashion from the schools, and it is not sufficient
+to-day; it never will be sufficient while the world stands, perhaps.
+There is no school in all our land where the young ladies do not feel
+obliged to close their compositions with a sermon; and you will find
+that the sermon of the most frivolous and the least religious girl in
+the school is always the longest and the most relentlessly pious. But
+enough of this. Homely truth is unpalatable.
+
+Let us return to the "Examination." The first composition that was
+read was one entitled "Is this, then, Life?" Perhaps the reader can
+endure an extract from it:
+
+  "In the common walks of life, with what delightful
+   emotions does the youthful mind look forward to some
+   anticipated scene of festivity! Imagination is busy
+   sketching rose-tinted pictures of joy. In fancy, the
+   voluptuous votary of fashion sees herself amid the
+   festive throng, 'the observed of all observers.' Her
+   graceful form, arrayed in snowy robes, is whirling
+   through the mazes of the joyous dance; her eye is
+   brightest, her step is lightest in the gay assembly.
+
+  "In such delicious fancies time quickly glides by,
+   and the welcome hour arrives for her entrance into
+   the Elysian world, of which she has had such bright
+   dreams. How fairy-like does everything appear to
+   her enchanted vision! Each new scene is more charming
+   than the last. But after a while she finds that
+   beneath this goodly exterior, all is vanity, the
+   flattery which once charmed her soul, now grates
+   harshly upon her ear; the ball-room has lost its
+   charms; and with wasted health and imbittered heart,
+   she turns away with the conviction that earthly
+   pleasures cannot satisfy the longings of the soul!"
+
+And so forth and so on. There was a buzz of gratification from time to
+time during the reading, accompanied by whispered ejaculations of "How
+sweet!" "How eloquent!" "So true!" etc., and after the thing had closed
+with a peculiarly afflicting sermon the applause was enthusiastic.
+
+Then arose a slim, melancholy girl, whose face had the "interesting"
+paleness that comes of pills and indigestion, and read a "poem." Two
+stanzas of it will do:
+
+   "A MISSOURI MAIDEN'S FAREWELL TO ALABAMA
+
+   "Alabama, good-bye! I love thee well!
+      But yet for a while do I leave thee now!
+    Sad, yes, sad thoughts of thee my heart doth swell,
+      And burning recollections throng my brow!
+    For I have wandered through thy flowery woods;
+      Have roamed and read near Tallapoosa's stream;
+    Have listened to Tallassee's warring floods,
+      And wooed on Coosa's side Aurora's beam.
+
+   "Yet shame I not to bear an o'er-full heart,
+      Nor blush to turn behind my tearful eyes;
+    'Tis from no stranger land I now must part,
+      'Tis to no strangers left I yield these sighs.
+    Welcome and home were mine within this State,
+      Whose vales I leave--whose spires fade fast from me
+    And cold must be mine eyes, and heart, and tete,
+      When, dear Alabama! they turn cold on thee!"
+
+There were very few there who knew what "tete" meant, but the poem was
+very satisfactory, nevertheless.
+
+Next appeared a dark-complexioned, black-eyed, black-haired young
+lady, who paused an impressive moment, assumed a tragic expression, and
+began to read in a measured, solemn tone:
+
+  "A VISION
+
+   "Dark and tempestuous was night. Around the
+   throne on high not a single star quivered; but
+   the deep intonations of the heavy thunder
+   constantly vibrated upon the ear; whilst the
+   terrific lightning revelled in angry mood
+   through the cloudy chambers of heaven, seeming
+   to scorn the power exerted over its terror by
+   the illustrious Franklin! Even the boisterous
+   winds unanimously came forth from their mystic
+   homes, and blustered about as if to enhance by
+   their aid the wildness of the scene.
+
+   "At such a time, so dark, so dreary, for human
+   sympathy my very spirit sighed; but instead thereof,
+
+   "'My dearest friend, my counsellor, my comforter
+   and guide--My joy in grief, my second bliss
+   in joy,' came to my side. She moved like one of
+   those bright beings pictured in the sunny walks
+   of fancy's Eden by the romantic and young, a
+   queen of beauty unadorned save by her own
+   transcendent loveliness. So soft was her step, it
+   failed to make even a sound, and but for the
+   magical thrill imparted by her genial touch, as
+   other unobtrusive beauties, she would have glided
+   away un-perceived--unsought. A strange sadness
+   rested upon her features, like icy tears upon
+   the robe of December, as she pointed to the
+   contending elements without, and bade me contemplate
+   the two beings presented."
+
+This nightmare occupied some ten pages of manuscript and wound up with
+a sermon so destructive of all hope to non-Presbyterians that it took
+the first prize. This composition was considered to be the very finest
+effort of the evening. The mayor of the village, in delivering the
+prize to the author of it, made a warm speech in which he said that it
+was by far the most "eloquent" thing he had ever listened to, and that
+Daniel Webster himself might well be proud of it.
+
+It may be remarked, in passing, that the number of compositions in
+which the word "beauteous" was over-fondled, and human experience
+referred to as "life's page," was up to the usual average.
+
+Now the master, mellow almost to the verge of geniality, put his chair
+aside, turned his back to the audience, and began to draw a map of
+America on the blackboard, to exercise the geography class upon. But he
+made a sad business of it with his unsteady hand, and a smothered
+titter rippled over the house. He knew what the matter was, and set
+himself to right it. He sponged out lines and remade them; but he only
+distorted them more than ever, and the tittering was more pronounced.
+He threw his entire attention upon his work, now, as if determined not
+to be put down by the mirth. He felt that all eyes were fastened upon
+him; he imagined he was succeeding, and yet the tittering continued; it
+even manifestly increased. And well it might. There was a garret above,
+pierced with a scuttle over his head; and down through this scuttle
+came a cat, suspended around the haunches by a string; she had a rag
+tied about her head and jaws to keep her from mewing; as she slowly
+descended she curved upward and clawed at the string, she swung
+downward and clawed at the intangible air. The tittering rose higher
+and higher--the cat was within six inches of the absorbed teacher's
+head--down, down, a little lower, and she grabbed his wig with her
+desperate claws, clung to it, and was snatched up into the garret in an
+instant with her trophy still in her possession! And how the light did
+blaze abroad from the master's bald pate--for the sign-painter's boy
+had GILDED it!
+
+That broke up the meeting. The boys were avenged. Vacation had come.
+
+   NOTE:--The pretended "compositions" quoted in
+   this chapter are taken without alteration from a
+   volume entitled "Prose and Poetry, by a Western
+   Lady"--but they are exactly and precisely after
+   the schoolgirl pattern, and hence are much
+   happier than any mere imitations could be.
+
+
+
+CHAPTER XXII
+
+TOM joined the new order of Cadets of Temperance, being attracted by
+the showy character of their "regalia." He promised to abstain from
+smoking, chewing, and profanity as long as he remained a member. Now he
+found out a new thing--namely, that to promise not to do a thing is the
+surest way in the world to make a body want to go and do that very
+thing. Tom soon found himself tormented with a desire to drink and
+swear; the desire grew to be so intense that nothing but the hope of a
+chance to display himself in his red sash kept him from withdrawing
+from the order. Fourth of July was coming; but he soon gave that up
+--gave it up before he had worn his shackles over forty-eight hours--and
+fixed his hopes upon old Judge Frazer, justice of the peace, who was
+apparently on his deathbed and would have a big public funeral, since
+he was so high an official. During three days Tom was deeply concerned
+about the Judge's condition and hungry for news of it. Sometimes his
+hopes ran high--so high that he would venture to get out his regalia
+and practise before the looking-glass. But the Judge had a most
+discouraging way of fluctuating. At last he was pronounced upon the
+mend--and then convalescent. Tom was disgusted; and felt a sense of
+injury, too. He handed in his resignation at once--and that night the
+Judge suffered a relapse and died. Tom resolved that he would never
+trust a man like that again.
+
+The funeral was a fine thing. The Cadets paraded in a style calculated
+to kill the late member with envy. Tom was a free boy again, however
+--there was something in that. He could drink and swear, now--but found
+to his surprise that he did not want to. The simple fact that he could,
+took the desire away, and the charm of it.
+
+Tom presently wondered to find that his coveted vacation was beginning
+to hang a little heavily on his hands.
+
+He attempted a diary--but nothing happened during three days, and so
+he abandoned it.
+
+The first of all the negro minstrel shows came to town, and made a
+sensation. Tom and Joe Harper got up a band of performers and were
+happy for two days.
+
+Even the Glorious Fourth was in some sense a failure, for it rained
+hard, there was no procession in consequence, and the greatest man in
+the world (as Tom supposed), Mr. Benton, an actual United States
+Senator, proved an overwhelming disappointment--for he was not
+twenty-five feet high, nor even anywhere in the neighborhood of it.
+
+A circus came. The boys played circus for three days afterward in
+tents made of rag carpeting--admission, three pins for boys, two for
+girls--and then circusing was abandoned.
+
+A phrenologist and a mesmerizer came--and went again and left the
+village duller and drearier than ever.
+
+There were some boys-and-girls' parties, but they were so few and so
+delightful that they only made the aching voids between ache the harder.
+
+Becky Thatcher was gone to her Constantinople home to stay with her
+parents during vacation--so there was no bright side to life anywhere.
+
+The dreadful secret of the murder was a chronic misery. It was a very
+cancer for permanency and pain.
+
+Then came the measles.
+
+During two long weeks Tom lay a prisoner, dead to the world and its
+happenings. He was very ill, he was interested in nothing. When he got
+upon his feet at last and moved feebly down-town, a melancholy change
+had come over everything and every creature. There had been a
+"revival," and everybody had "got religion," not only the adults, but
+even the boys and girls. Tom went about, hoping against hope for the
+sight of one blessed sinful face, but disappointment crossed him
+everywhere. He found Joe Harper studying a Testament, and turned sadly
+away from the depressing spectacle. He sought Ben Rogers, and found him
+visiting the poor with a basket of tracts. He hunted up Jim Hollis, who
+called his attention to the precious blessing of his late measles as a
+warning. Every boy he encountered added another ton to his depression;
+and when, in desperation, he flew for refuge at last to the bosom of
+Huckleberry Finn and was received with a Scriptural quotation, his
+heart broke and he crept home and to bed realizing that he alone of all
+the town was lost, forever and forever.
+
+And that night there came on a terrific storm, with driving rain,
+awful claps of thunder and blinding sheets of lightning. He covered his
+head with the bedclothes and waited in a horror of suspense for his
+doom; for he had not the shadow of a doubt that all this hubbub was
+about him. He believed he had taxed the forbearance of the powers above
+to the extremity of endurance and that this was the result. It might
+have seemed to him a waste of pomp and ammunition to kill a bug with a
+battery of artillery, but there seemed nothing incongruous about the
+getting up such an expensive thunderstorm as this to knock the turf
+from under an insect like himself.
+
+By and by the tempest spent itself and died without accomplishing its
+object. The boy's first impulse was to be grateful, and reform. His
+second was to wait--for there might not be any more storms.
+
+The next day the doctors were back; Tom had relapsed. The three weeks
+he spent on his back this time seemed an entire age. When he got abroad
+at last he was hardly grateful that he had been spared, remembering how
+lonely was his estate, how companionless and forlorn he was. He drifted
+listlessly down the street and found Jim Hollis acting as judge in a
+juvenile court that was trying a cat for murder, in the presence of her
+victim, a bird. He found Joe Harper and Huck Finn up an alley eating a
+stolen melon. Poor lads! they--like Tom--had suffered a relapse.
+
+
+
+CHAPTER XXIII
+
+AT last the sleepy atmosphere was stirred--and vigorously: the murder
+trial came on in the court. It became the absorbing topic of village
+talk immediately. Tom could not get away from it. Every reference to
+the murder sent a shudder to his heart, for his troubled conscience and
+fears almost persuaded him that these remarks were put forth in his
+hearing as "feelers"; he did not see how he could be suspected of
+knowing anything about the murder, but still he could not be
+comfortable in the midst of this gossip. It kept him in a cold shiver
+all the time. He took Huck to a lonely place to have a talk with him.
+It would be some relief to unseal his tongue for a little while; to
+divide his burden of distress with another sufferer. Moreover, he
+wanted to assure himself that Huck had remained discreet.
+
+"Huck, have you ever told anybody about--that?"
+
+"'Bout what?"
+
+"You know what."
+
+"Oh--'course I haven't."
+
+"Never a word?"
+
+"Never a solitary word, so help me. What makes you ask?"
+
+"Well, I was afeard."
+
+"Why, Tom Sawyer, we wouldn't be alive two days if that got found out.
+YOU know that."
+
+Tom felt more comfortable. After a pause:
+
+"Huck, they couldn't anybody get you to tell, could they?"
+
+"Get me to tell? Why, if I wanted that half-breed devil to drownd me
+they could get me to tell. They ain't no different way."
+
+"Well, that's all right, then. I reckon we're safe as long as we keep
+mum. But let's swear again, anyway. It's more surer."
+
+"I'm agreed."
+
+So they swore again with dread solemnities.
+
+"What is the talk around, Huck? I've heard a power of it."
+
+"Talk? Well, it's just Muff Potter, Muff Potter, Muff Potter all the
+time. It keeps me in a sweat, constant, so's I want to hide som'ers."
+
+"That's just the same way they go on round me. I reckon he's a goner.
+Don't you feel sorry for him, sometimes?"
+
+"Most always--most always. He ain't no account; but then he hain't
+ever done anything to hurt anybody. Just fishes a little, to get money
+to get drunk on--and loafs around considerable; but lord, we all do
+that--leastways most of us--preachers and such like. But he's kind of
+good--he give me half a fish, once, when there warn't enough for two;
+and lots of times he's kind of stood by me when I was out of luck."
+
+"Well, he's mended kites for me, Huck, and knitted hooks on to my
+line. I wish we could get him out of there."
+
+"My! we couldn't get him out, Tom. And besides, 'twouldn't do any
+good; they'd ketch him again."
+
+"Yes--so they would. But I hate to hear 'em abuse him so like the
+dickens when he never done--that."
+
+"I do too, Tom. Lord, I hear 'em say he's the bloodiest looking
+villain in this country, and they wonder he wasn't ever hung before."
+
+"Yes, they talk like that, all the time. I've heard 'em say that if he
+was to get free they'd lynch him."
+
+"And they'd do it, too."
+
+The boys had a long talk, but it brought them little comfort. As the
+twilight drew on, they found themselves hanging about the neighborhood
+of the little isolated jail, perhaps with an undefined hope that
+something would happen that might clear away their difficulties. But
+nothing happened; there seemed to be no angels or fairies interested in
+this luckless captive.
+
+The boys did as they had often done before--went to the cell grating
+and gave Potter some tobacco and matches. He was on the ground floor
+and there were no guards.
+
+His gratitude for their gifts had always smote their consciences
+before--it cut deeper than ever, this time. They felt cowardly and
+treacherous to the last degree when Potter said:
+
+"You've been mighty good to me, boys--better'n anybody else in this
+town. And I don't forget it, I don't. Often I says to myself, says I,
+'I used to mend all the boys' kites and things, and show 'em where the
+good fishin' places was, and befriend 'em what I could, and now they've
+all forgot old Muff when he's in trouble; but Tom don't, and Huck
+don't--THEY don't forget him, says I, 'and I don't forget them.' Well,
+boys, I done an awful thing--drunk and crazy at the time--that's the
+only way I account for it--and now I got to swing for it, and it's
+right. Right, and BEST, too, I reckon--hope so, anyway. Well, we won't
+talk about that. I don't want to make YOU feel bad; you've befriended
+me. But what I want to say, is, don't YOU ever get drunk--then you won't
+ever get here. Stand a litter furder west--so--that's it; it's a prime
+comfort to see faces that's friendly when a body's in such a muck of
+trouble, and there don't none come here but yourn. Good friendly
+faces--good friendly faces. Git up on one another's backs and let me
+touch 'em. That's it. Shake hands--yourn'll come through the bars, but
+mine's too big. Little hands, and weak--but they've helped Muff Potter
+a power, and they'd help him more if they could."
+
+Tom went home miserable, and his dreams that night were full of
+horrors. The next day and the day after, he hung about the court-room,
+drawn by an almost irresistible impulse to go in, but forcing himself
+to stay out. Huck was having the same experience. They studiously
+avoided each other. Each wandered away, from time to time, but the same
+dismal fascination always brought them back presently. Tom kept his
+ears open when idlers sauntered out of the court-room, but invariably
+heard distressing news--the toils were closing more and more
+relentlessly around poor Potter. At the end of the second day the
+village talk was to the effect that Injun Joe's evidence stood firm and
+unshaken, and that there was not the slightest question as to what the
+jury's verdict would be.
+
+Tom was out late, that night, and came to bed through the window. He
+was in a tremendous state of excitement. It was hours before he got to
+sleep. All the village flocked to the court-house the next morning, for
+this was to be the great day. Both sexes were about equally represented
+in the packed audience. After a long wait the jury filed in and took
+their places; shortly afterward, Potter, pale and haggard, timid and
+hopeless, was brought in, with chains upon him, and seated where all
+the curious eyes could stare at him; no less conspicuous was Injun Joe,
+stolid as ever. There was another pause, and then the judge arrived and
+the sheriff proclaimed the opening of the court. The usual whisperings
+among the lawyers and gathering together of papers followed. These
+details and accompanying delays worked up an atmosphere of preparation
+that was as impressive as it was fascinating.
+
+Now a witness was called who testified that he found Muff Potter
+washing in the brook, at an early hour of the morning that the murder
+was discovered, and that he immediately sneaked away. After some
+further questioning, counsel for the prosecution said:
+
+"Take the witness."
+
+The prisoner raised his eyes for a moment, but dropped them again when
+his own counsel said:
+
+"I have no questions to ask him."
+
+The next witness proved the finding of the knife near the corpse.
+Counsel for the prosecution said:
+
+"Take the witness."
+
+"I have no questions to ask him," Potter's lawyer replied.
+
+A third witness swore he had often seen the knife in Potter's
+possession.
+
+"Take the witness."
+
+Counsel for Potter declined to question him. The faces of the audience
+began to betray annoyance. Did this attorney mean to throw away his
+client's life without an effort?
+
+Several witnesses deposed concerning Potter's guilty behavior when
+brought to the scene of the murder. They were allowed to leave the
+stand without being cross-questioned.
+
+Every detail of the damaging circumstances that occurred in the
+graveyard upon that morning which all present remembered so well was
+brought out by credible witnesses, but none of them were cross-examined
+by Potter's lawyer. The perplexity and dissatisfaction of the house
+expressed itself in murmurs and provoked a reproof from the bench.
+Counsel for the prosecution now said:
+
+"By the oaths of citizens whose simple word is above suspicion, we
+have fastened this awful crime, beyond all possibility of question,
+upon the unhappy prisoner at the bar. We rest our case here."
+
+A groan escaped from poor Potter, and he put his face in his hands and
+rocked his body softly to and fro, while a painful silence reigned in
+the court-room. Many men were moved, and many women's compassion
+testified itself in tears. Counsel for the defence rose and said:
+
+"Your honor, in our remarks at the opening of this trial, we
+foreshadowed our purpose to prove that our client did this fearful deed
+while under the influence of a blind and irresponsible delirium
+produced by drink. We have changed our mind. We shall not offer that
+plea." [Then to the clerk:] "Call Thomas Sawyer!"
+
+A puzzled amazement awoke in every face in the house, not even
+excepting Potter's. Every eye fastened itself with wondering interest
+upon Tom as he rose and took his place upon the stand. The boy looked
+wild enough, for he was badly scared. The oath was administered.
+
+"Thomas Sawyer, where were you on the seventeenth of June, about the
+hour of midnight?"
+
+Tom glanced at Injun Joe's iron face and his tongue failed him. The
+audience listened breathless, but the words refused to come. After a
+few moments, however, the boy got a little of his strength back, and
+managed to put enough of it into his voice to make part of the house
+hear:
+
+"In the graveyard!"
+
+"A little bit louder, please. Don't be afraid. You were--"
+
+"In the graveyard."
+
+A contemptuous smile flitted across Injun Joe's face.
+
+"Were you anywhere near Horse Williams' grave?"
+
+"Yes, sir."
+
+"Speak up--just a trifle louder. How near were you?"
+
+"Near as I am to you."
+
+"Were you hidden, or not?"
+
+"I was hid."
+
+"Where?"
+
+"Behind the elms that's on the edge of the grave."
+
+Injun Joe gave a barely perceptible start.
+
+"Any one with you?"
+
+"Yes, sir. I went there with--"
+
+"Wait--wait a moment. Never mind mentioning your companion's name. We
+will produce him at the proper time. Did you carry anything there with
+you."
+
+Tom hesitated and looked confused.
+
+"Speak out, my boy--don't be diffident. The truth is always
+respectable. What did you take there?"
+
+"Only a--a--dead cat."
+
+There was a ripple of mirth, which the court checked.
+
+"We will produce the skeleton of that cat. Now, my boy, tell us
+everything that occurred--tell it in your own way--don't skip anything,
+and don't be afraid."
+
+Tom began--hesitatingly at first, but as he warmed to his subject his
+words flowed more and more easily; in a little while every sound ceased
+but his own voice; every eye fixed itself upon him; with parted lips
+and bated breath the audience hung upon his words, taking no note of
+time, rapt in the ghastly fascinations of the tale. The strain upon
+pent emotion reached its climax when the boy said:
+
+"--and as the doctor fetched the board around and Muff Potter fell,
+Injun Joe jumped with the knife and--"
+
+Crash! Quick as lightning the half-breed sprang for a window, tore his
+way through all opposers, and was gone!
+
+
+
+CHAPTER XXIV
+
+TOM was a glittering hero once more--the pet of the old, the envy of
+the young. His name even went into immortal print, for the village
+paper magnified him. There were some that believed he would be
+President, yet, if he escaped hanging.
+
+As usual, the fickle, unreasoning world took Muff Potter to its bosom
+and fondled him as lavishly as it had abused him before. But that sort
+of conduct is to the world's credit; therefore it is not well to find
+fault with it.
+
+Tom's days were days of splendor and exultation to him, but his nights
+were seasons of horror. Injun Joe infested all his dreams, and always
+with doom in his eye. Hardly any temptation could persuade the boy to
+stir abroad after nightfall. Poor Huck was in the same state of
+wretchedness and terror, for Tom had told the whole story to the lawyer
+the night before the great day of the trial, and Huck was sore afraid
+that his share in the business might leak out, yet, notwithstanding
+Injun Joe's flight had saved him the suffering of testifying in court.
+The poor fellow had got the attorney to promise secrecy, but what of
+that? Since Tom's harassed conscience had managed to drive him to the
+lawyer's house by night and wring a dread tale from lips that had been
+sealed with the dismalest and most formidable of oaths, Huck's
+confidence in the human race was well-nigh obliterated.
+
+Daily Muff Potter's gratitude made Tom glad he had spoken; but nightly
+he wished he had sealed up his tongue.
+
+Half the time Tom was afraid Injun Joe would never be captured; the
+other half he was afraid he would be. He felt sure he never could draw
+a safe breath again until that man was dead and he had seen the corpse.
+
+Rewards had been offered, the country had been scoured, but no Injun
+Joe was found. One of those omniscient and awe-inspiring marvels, a
+detective, came up from St. Louis, moused around, shook his head,
+looked wise, and made that sort of astounding success which members of
+that craft usually achieve. That is to say, he "found a clew." But you
+can't hang a "clew" for murder, and so after that detective had got
+through and gone home, Tom felt just as insecure as he was before.
+
+The slow days drifted on, and each left behind it a slightly lightened
+weight of apprehension.
+
+
+
+CHAPTER XXV
+
+THERE comes a time in every rightly-constructed boy's life when he has
+a raging desire to go somewhere and dig for hidden treasure. This
+desire suddenly came upon Tom one day. He sallied out to find Joe
+Harper, but failed of success. Next he sought Ben Rogers; he had gone
+fishing. Presently he stumbled upon Huck Finn the Red-Handed. Huck
+would answer. Tom took him to a private place and opened the matter to
+him confidentially. Huck was willing. Huck was always willing to take a
+hand in any enterprise that offered entertainment and required no
+capital, for he had a troublesome superabundance of that sort of time
+which is not money. "Where'll we dig?" said Huck.
+
+"Oh, most anywhere."
+
+"Why, is it hid all around?"
+
+"No, indeed it ain't. It's hid in mighty particular places, Huck
+--sometimes on islands, sometimes in rotten chests under the end of a
+limb of an old dead tree, just where the shadow falls at midnight; but
+mostly under the floor in ha'nted houses."
+
+"Who hides it?"
+
+"Why, robbers, of course--who'd you reckon? Sunday-school
+sup'rintendents?"
+
+"I don't know. If 'twas mine I wouldn't hide it; I'd spend it and have
+a good time."
+
+"So would I. But robbers don't do that way. They always hide it and
+leave it there."
+
+"Don't they come after it any more?"
+
+"No, they think they will, but they generally forget the marks, or
+else they die. Anyway, it lays there a long time and gets rusty; and by
+and by somebody finds an old yellow paper that tells how to find the
+marks--a paper that's got to be ciphered over about a week because it's
+mostly signs and hy'roglyphics."
+
+"Hyro--which?"
+
+"Hy'roglyphics--pictures and things, you know, that don't seem to mean
+anything."
+
+"Have you got one of them papers, Tom?"
+
+"No."
+
+"Well then, how you going to find the marks?"
+
+"I don't want any marks. They always bury it under a ha'nted house or
+on an island, or under a dead tree that's got one limb sticking out.
+Well, we've tried Jackson's Island a little, and we can try it again
+some time; and there's the old ha'nted house up the Still-House branch,
+and there's lots of dead-limb trees--dead loads of 'em."
+
+"Is it under all of them?"
+
+"How you talk! No!"
+
+"Then how you going to know which one to go for?"
+
+"Go for all of 'em!"
+
+"Why, Tom, it'll take all summer."
+
+"Well, what of that? Suppose you find a brass pot with a hundred
+dollars in it, all rusty and gray, or rotten chest full of di'monds.
+How's that?"
+
+Huck's eyes glowed.
+
+"That's bully. Plenty bully enough for me. Just you gimme the hundred
+dollars and I don't want no di'monds."
+
+"All right. But I bet you I ain't going to throw off on di'monds. Some
+of 'em's worth twenty dollars apiece--there ain't any, hardly, but's
+worth six bits or a dollar."
+
+"No! Is that so?"
+
+"Cert'nly--anybody'll tell you so. Hain't you ever seen one, Huck?"
+
+"Not as I remember."
+
+"Oh, kings have slathers of them."
+
+"Well, I don' know no kings, Tom."
+
+"I reckon you don't. But if you was to go to Europe you'd see a raft
+of 'em hopping around."
+
+"Do they hop?"
+
+"Hop?--your granny! No!"
+
+"Well, what did you say they did, for?"
+
+"Shucks, I only meant you'd SEE 'em--not hopping, of course--what do
+they want to hop for?--but I mean you'd just see 'em--scattered around,
+you know, in a kind of a general way. Like that old humpbacked Richard."
+
+"Richard? What's his other name?"
+
+"He didn't have any other name. Kings don't have any but a given name."
+
+"No?"
+
+"But they don't."
+
+"Well, if they like it, Tom, all right; but I don't want to be a king
+and have only just a given name, like a nigger. But say--where you
+going to dig first?"
+
+"Well, I don't know. S'pose we tackle that old dead-limb tree on the
+hill t'other side of Still-House branch?"
+
+"I'm agreed."
+
+So they got a crippled pick and a shovel, and set out on their
+three-mile tramp. They arrived hot and panting, and threw themselves
+down in the shade of a neighboring elm to rest and have a smoke.
+
+"I like this," said Tom.
+
+"So do I."
+
+"Say, Huck, if we find a treasure here, what you going to do with your
+share?"
+
+"Well, I'll have pie and a glass of soda every day, and I'll go to
+every circus that comes along. I bet I'll have a gay time."
+
+"Well, ain't you going to save any of it?"
+
+"Save it? What for?"
+
+"Why, so as to have something to live on, by and by."
+
+"Oh, that ain't any use. Pap would come back to thish-yer town some
+day and get his claws on it if I didn't hurry up, and I tell you he'd
+clean it out pretty quick. What you going to do with yourn, Tom?"
+
+"I'm going to buy a new drum, and a sure-'nough sword, and a red
+necktie and a bull pup, and get married."
+
+"Married!"
+
+"That's it."
+
+"Tom, you--why, you ain't in your right mind."
+
+"Wait--you'll see."
+
+"Well, that's the foolishest thing you could do. Look at pap and my
+mother. Fight! Why, they used to fight all the time. I remember, mighty
+well."
+
+"That ain't anything. The girl I'm going to marry won't fight."
+
+"Tom, I reckon they're all alike. They'll all comb a body. Now you
+better think 'bout this awhile. I tell you you better. What's the name
+of the gal?"
+
+"It ain't a gal at all--it's a girl."
+
+"It's all the same, I reckon; some says gal, some says girl--both's
+right, like enough. Anyway, what's her name, Tom?"
+
+"I'll tell you some time--not now."
+
+"All right--that'll do. Only if you get married I'll be more lonesomer
+than ever."
+
+"No you won't. You'll come and live with me. Now stir out of this and
+we'll go to digging."
+
+They worked and sweated for half an hour. No result. They toiled
+another half-hour. Still no result. Huck said:
+
+"Do they always bury it as deep as this?"
+
+"Sometimes--not always. Not generally. I reckon we haven't got the
+right place."
+
+So they chose a new spot and began again. The labor dragged a little,
+but still they made progress. They pegged away in silence for some
+time. Finally Huck leaned on his shovel, swabbed the beaded drops from
+his brow with his sleeve, and said:
+
+"Where you going to dig next, after we get this one?"
+
+"I reckon maybe we'll tackle the old tree that's over yonder on
+Cardiff Hill back of the widow's."
+
+"I reckon that'll be a good one. But won't the widow take it away from
+us, Tom? It's on her land."
+
+"SHE take it away! Maybe she'd like to try it once. Whoever finds one
+of these hid treasures, it belongs to him. It don't make any difference
+whose land it's on."
+
+That was satisfactory. The work went on. By and by Huck said:
+
+"Blame it, we must be in the wrong place again. What do you think?"
+
+"It is mighty curious, Huck. I don't understand it. Sometimes witches
+interfere. I reckon maybe that's what's the trouble now."
+
+"Shucks! Witches ain't got no power in the daytime."
+
+"Well, that's so. I didn't think of that. Oh, I know what the matter
+is! What a blamed lot of fools we are! You got to find out where the
+shadow of the limb falls at midnight, and that's where you dig!"
+
+"Then consound it, we've fooled away all this work for nothing. Now
+hang it all, we got to come back in the night. It's an awful long way.
+Can you get out?"
+
+"I bet I will. We've got to do it to-night, too, because if somebody
+sees these holes they'll know in a minute what's here and they'll go
+for it."
+
+"Well, I'll come around and maow to-night."
+
+"All right. Let's hide the tools in the bushes."
+
+The boys were there that night, about the appointed time. They sat in
+the shadow waiting. It was a lonely place, and an hour made solemn by
+old traditions. Spirits whispered in the rustling leaves, ghosts lurked
+in the murky nooks, the deep baying of a hound floated up out of the
+distance, an owl answered with his sepulchral note. The boys were
+subdued by these solemnities, and talked little. By and by they judged
+that twelve had come; they marked where the shadow fell, and began to
+dig. Their hopes commenced to rise. Their interest grew stronger, and
+their industry kept pace with it. The hole deepened and still deepened,
+but every time their hearts jumped to hear the pick strike upon
+something, they only suffered a new disappointment. It was only a stone
+or a chunk. At last Tom said:
+
+"It ain't any use, Huck, we're wrong again."
+
+"Well, but we CAN'T be wrong. We spotted the shadder to a dot."
+
+"I know it, but then there's another thing."
+
+"What's that?".
+
+"Why, we only guessed at the time. Like enough it was too late or too
+early."
+
+Huck dropped his shovel.
+
+"That's it," said he. "That's the very trouble. We got to give this
+one up. We can't ever tell the right time, and besides this kind of
+thing's too awful, here this time of night with witches and ghosts
+a-fluttering around so. I feel as if something's behind me all the time;
+and I'm afeard to turn around, becuz maybe there's others in front
+a-waiting for a chance. I been creeping all over, ever since I got here."
+
+"Well, I've been pretty much so, too, Huck. They most always put in a
+dead man when they bury a treasure under a tree, to look out for it."
+
+"Lordy!"
+
+"Yes, they do. I've always heard that."
+
+"Tom, I don't like to fool around much where there's dead people. A
+body's bound to get into trouble with 'em, sure."
+
+"I don't like to stir 'em up, either. S'pose this one here was to
+stick his skull out and say something!"
+
+"Don't Tom! It's awful."
+
+"Well, it just is. Huck, I don't feel comfortable a bit."
+
+"Say, Tom, let's give this place up, and try somewheres else."
+
+"All right, I reckon we better."
+
+"What'll it be?"
+
+Tom considered awhile; and then said:
+
+"The ha'nted house. That's it!"
+
+"Blame it, I don't like ha'nted houses, Tom. Why, they're a dern sight
+worse'n dead people. Dead people might talk, maybe, but they don't come
+sliding around in a shroud, when you ain't noticing, and peep over your
+shoulder all of a sudden and grit their teeth, the way a ghost does. I
+couldn't stand such a thing as that, Tom--nobody could."
+
+"Yes, but, Huck, ghosts don't travel around only at night. They won't
+hender us from digging there in the daytime."
+
+"Well, that's so. But you know mighty well people don't go about that
+ha'nted house in the day nor the night."
+
+"Well, that's mostly because they don't like to go where a man's been
+murdered, anyway--but nothing's ever been seen around that house except
+in the night--just some blue lights slipping by the windows--no regular
+ghosts."
+
+"Well, where you see one of them blue lights flickering around, Tom,
+you can bet there's a ghost mighty close behind it. It stands to
+reason. Becuz you know that they don't anybody but ghosts use 'em."
+
+"Yes, that's so. But anyway they don't come around in the daytime, so
+what's the use of our being afeard?"
+
+"Well, all right. We'll tackle the ha'nted house if you say so--but I
+reckon it's taking chances."
+
+They had started down the hill by this time. There in the middle of
+the moonlit valley below them stood the "ha'nted" house, utterly
+isolated, its fences gone long ago, rank weeds smothering the very
+doorsteps, the chimney crumbled to ruin, the window-sashes vacant, a
+corner of the roof caved in. The boys gazed awhile, half expecting to
+see a blue light flit past a window; then talking in a low tone, as
+befitted the time and the circumstances, they struck far off to the
+right, to give the haunted house a wide berth, and took their way
+homeward through the woods that adorned the rearward side of Cardiff
+Hill.
+
+
+
+CHAPTER XXVI
+
+ABOUT noon the next day the boys arrived at the dead tree; they had
+come for their tools. Tom was impatient to go to the haunted house;
+Huck was measurably so, also--but suddenly said:
+
+"Lookyhere, Tom, do you know what day it is?"
+
+Tom mentally ran over the days of the week, and then quickly lifted
+his eyes with a startled look in them--
+
+"My! I never once thought of it, Huck!"
+
+"Well, I didn't neither, but all at once it popped onto me that it was
+Friday."
+
+"Blame it, a body can't be too careful, Huck. We might 'a' got into an
+awful scrape, tackling such a thing on a Friday."
+
+"MIGHT! Better say we WOULD! There's some lucky days, maybe, but
+Friday ain't."
+
+"Any fool knows that. I don't reckon YOU was the first that found it
+out, Huck."
+
+"Well, I never said I was, did I? And Friday ain't all, neither. I had
+a rotten bad dream last night--dreampt about rats."
+
+"No! Sure sign of trouble. Did they fight?"
+
+"No."
+
+"Well, that's good, Huck. When they don't fight it's only a sign that
+there's trouble around, you know. All we got to do is to look mighty
+sharp and keep out of it. We'll drop this thing for to-day, and play.
+Do you know Robin Hood, Huck?"
+
+"No. Who's Robin Hood?"
+
+"Why, he was one of the greatest men that was ever in England--and the
+best. He was a robber."
+
+"Cracky, I wisht I was. Who did he rob?"
+
+"Only sheriffs and bishops and rich people and kings, and such like.
+But he never bothered the poor. He loved 'em. He always divided up with
+'em perfectly square."
+
+"Well, he must 'a' been a brick."
+
+"I bet you he was, Huck. Oh, he was the noblest man that ever was.
+They ain't any such men now, I can tell you. He could lick any man in
+England, with one hand tied behind him; and he could take his yew bow
+and plug a ten-cent piece every time, a mile and a half."
+
+"What's a YEW bow?"
+
+"I don't know. It's some kind of a bow, of course. And if he hit that
+dime only on the edge he would set down and cry--and curse. But we'll
+play Robin Hood--it's nobby fun. I'll learn you."
+
+"I'm agreed."
+
+So they played Robin Hood all the afternoon, now and then casting a
+yearning eye down upon the haunted house and passing a remark about the
+morrow's prospects and possibilities there. As the sun began to sink
+into the west they took their way homeward athwart the long shadows of
+the trees and soon were buried from sight in the forests of Cardiff
+Hill.
+
+On Saturday, shortly after noon, the boys were at the dead tree again.
+They had a smoke and a chat in the shade, and then dug a little in
+their last hole, not with great hope, but merely because Tom said there
+were so many cases where people had given up a treasure after getting
+down within six inches of it, and then somebody else had come along and
+turned it up with a single thrust of a shovel. The thing failed this
+time, however, so the boys shouldered their tools and went away feeling
+that they had not trifled with fortune, but had fulfilled all the
+requirements that belong to the business of treasure-hunting.
+
+When they reached the haunted house there was something so weird and
+grisly about the dead silence that reigned there under the baking sun,
+and something so depressing about the loneliness and desolation of the
+place, that they were afraid, for a moment, to venture in. Then they
+crept to the door and took a trembling peep. They saw a weed-grown,
+floorless room, unplastered, an ancient fireplace, vacant windows, a
+ruinous staircase; and here, there, and everywhere hung ragged and
+abandoned cobwebs. They presently entered, softly, with quickened
+pulses, talking in whispers, ears alert to catch the slightest sound,
+and muscles tense and ready for instant retreat.
+
+In a little while familiarity modified their fears and they gave the
+place a critical and interested examination, rather admiring their own
+boldness, and wondering at it, too. Next they wanted to look up-stairs.
+This was something like cutting off retreat, but they got to daring
+each other, and of course there could be but one result--they threw
+their tools into a corner and made the ascent. Up there were the same
+signs of decay. In one corner they found a closet that promised
+mystery, but the promise was a fraud--there was nothing in it. Their
+courage was up now and well in hand. They were about to go down and
+begin work when--
+
+"Sh!" said Tom.
+
+"What is it?" whispered Huck, blanching with fright.
+
+"Sh!... There!... Hear it?"
+
+"Yes!... Oh, my! Let's run!"
+
+"Keep still! Don't you budge! They're coming right toward the door."
+
+The boys stretched themselves upon the floor with their eyes to
+knot-holes in the planking, and lay waiting, in a misery of fear.
+
+"They've stopped.... No--coming.... Here they are. Don't whisper
+another word, Huck. My goodness, I wish I was out of this!"
+
+Two men entered. Each boy said to himself: "There's the old deaf and
+dumb Spaniard that's been about town once or twice lately--never saw
+t'other man before."
+
+"T'other" was a ragged, unkempt creature, with nothing very pleasant
+in his face. The Spaniard was wrapped in a serape; he had bushy white
+whiskers; long white hair flowed from under his sombrero, and he wore
+green goggles. When they came in, "t'other" was talking in a low voice;
+they sat down on the ground, facing the door, with their backs to the
+wall, and the speaker continued his remarks. His manner became less
+guarded and his words more distinct as he proceeded:
+
+"No," said he, "I've thought it all over, and I don't like it. It's
+dangerous."
+
+"Dangerous!" grunted the "deaf and dumb" Spaniard--to the vast
+surprise of the boys. "Milksop!"
+
+This voice made the boys gasp and quake. It was Injun Joe's! There was
+silence for some time. Then Joe said:
+
+"What's any more dangerous than that job up yonder--but nothing's come
+of it."
+
+"That's different. Away up the river so, and not another house about.
+'Twon't ever be known that we tried, anyway, long as we didn't succeed."
+
+"Well, what's more dangerous than coming here in the daytime!--anybody
+would suspicion us that saw us."
+
+"I know that. But there warn't any other place as handy after that
+fool of a job. I want to quit this shanty. I wanted to yesterday, only
+it warn't any use trying to stir out of here, with those infernal boys
+playing over there on the hill right in full view."
+
+"Those infernal boys" quaked again under the inspiration of this
+remark, and thought how lucky it was that they had remembered it was
+Friday and concluded to wait a day. They wished in their hearts they
+had waited a year.
+
+The two men got out some food and made a luncheon. After a long and
+thoughtful silence, Injun Joe said:
+
+"Look here, lad--you go back up the river where you belong. Wait there
+till you hear from me. I'll take the chances on dropping into this town
+just once more, for a look. We'll do that 'dangerous' job after I've
+spied around a little and think things look well for it. Then for
+Texas! We'll leg it together!"
+
+This was satisfactory. Both men presently fell to yawning, and Injun
+Joe said:
+
+"I'm dead for sleep! It's your turn to watch."
+
+He curled down in the weeds and soon began to snore. His comrade
+stirred him once or twice and he became quiet. Presently the watcher
+began to nod; his head drooped lower and lower, both men began to snore
+now.
+
+The boys drew a long, grateful breath. Tom whispered:
+
+"Now's our chance--come!"
+
+Huck said:
+
+"I can't--I'd die if they was to wake."
+
+Tom urged--Huck held back. At last Tom rose slowly and softly, and
+started alone. But the first step he made wrung such a hideous creak
+from the crazy floor that he sank down almost dead with fright. He
+never made a second attempt. The boys lay there counting the dragging
+moments till it seemed to them that time must be done and eternity
+growing gray; and then they were grateful to note that at last the sun
+was setting.
+
+Now one snore ceased. Injun Joe sat up, stared around--smiled grimly
+upon his comrade, whose head was drooping upon his knees--stirred him
+up with his foot and said:
+
+"Here! YOU'RE a watchman, ain't you! All right, though--nothing's
+happened."
+
+"My! have I been asleep?"
+
+"Oh, partly, partly. Nearly time for us to be moving, pard. What'll we
+do with what little swag we've got left?"
+
+"I don't know--leave it here as we've always done, I reckon. No use to
+take it away till we start south. Six hundred and fifty in silver's
+something to carry."
+
+"Well--all right--it won't matter to come here once more."
+
+"No--but I'd say come in the night as we used to do--it's better."
+
+"Yes: but look here; it may be a good while before I get the right
+chance at that job; accidents might happen; 'tain't in such a very good
+place; we'll just regularly bury it--and bury it deep."
+
+"Good idea," said the comrade, who walked across the room, knelt down,
+raised one of the rearward hearth-stones and took out a bag that
+jingled pleasantly. He subtracted from it twenty or thirty dollars for
+himself and as much for Injun Joe, and passed the bag to the latter,
+who was on his knees in the corner, now, digging with his bowie-knife.
+
+The boys forgot all their fears, all their miseries in an instant.
+With gloating eyes they watched every movement. Luck!--the splendor of
+it was beyond all imagination! Six hundred dollars was money enough to
+make half a dozen boys rich! Here was treasure-hunting under the
+happiest auspices--there would not be any bothersome uncertainty as to
+where to dig. They nudged each other every moment--eloquent nudges and
+easily understood, for they simply meant--"Oh, but ain't you glad NOW
+we're here!"
+
+Joe's knife struck upon something.
+
+"Hello!" said he.
+
+"What is it?" said his comrade.
+
+"Half-rotten plank--no, it's a box, I believe. Here--bear a hand and
+we'll see what it's here for. Never mind, I've broke a hole."
+
+He reached his hand in and drew it out--
+
+"Man, it's money!"
+
+The two men examined the handful of coins. They were gold. The boys
+above were as excited as themselves, and as delighted.
+
+Joe's comrade said:
+
+"We'll make quick work of this. There's an old rusty pick over amongst
+the weeds in the corner the other side of the fireplace--I saw it a
+minute ago."
+
+He ran and brought the boys' pick and shovel. Injun Joe took the pick,
+looked it over critically, shook his head, muttered something to
+himself, and then began to use it. The box was soon unearthed. It was
+not very large; it was iron bound and had been very strong before the
+slow years had injured it. The men contemplated the treasure awhile in
+blissful silence.
+
+"Pard, there's thousands of dollars here," said Injun Joe.
+
+"'Twas always said that Murrel's gang used to be around here one
+summer," the stranger observed.
+
+"I know it," said Injun Joe; "and this looks like it, I should say."
+
+"Now you won't need to do that job."
+
+The half-breed frowned. Said he:
+
+"You don't know me. Least you don't know all about that thing. 'Tain't
+robbery altogether--it's REVENGE!" and a wicked light flamed in his
+eyes. "I'll need your help in it. When it's finished--then Texas. Go
+home to your Nance and your kids, and stand by till you hear from me."
+
+"Well--if you say so; what'll we do with this--bury it again?"
+
+"Yes. [Ravishing delight overhead.] NO! by the great Sachem, no!
+[Profound distress overhead.] I'd nearly forgot. That pick had fresh
+earth on it! [The boys were sick with terror in a moment.] What
+business has a pick and a shovel here? What business with fresh earth
+on them? Who brought them here--and where are they gone? Have you heard
+anybody?--seen anybody? What! bury it again and leave them to come and
+see the ground disturbed? Not exactly--not exactly. We'll take it to my
+den."
+
+"Why, of course! Might have thought of that before. You mean Number
+One?"
+
+"No--Number Two--under the cross. The other place is bad--too common."
+
+"All right. It's nearly dark enough to start."
+
+Injun Joe got up and went about from window to window cautiously
+peeping out. Presently he said:
+
+"Who could have brought those tools here? Do you reckon they can be
+up-stairs?"
+
+The boys' breath forsook them. Injun Joe put his hand on his knife,
+halted a moment, undecided, and then turned toward the stairway. The
+boys thought of the closet, but their strength was gone. The steps came
+creaking up the stairs--the intolerable distress of the situation woke
+the stricken resolution of the lads--they were about to spring for the
+closet, when there was a crash of rotten timbers and Injun Joe landed
+on the ground amid the debris of the ruined stairway. He gathered
+himself up cursing, and his comrade said:
+
+"Now what's the use of all that? If it's anybody, and they're up
+there, let them STAY there--who cares? If they want to jump down, now,
+and get into trouble, who objects? It will be dark in fifteen minutes
+--and then let them follow us if they want to. I'm willing. In my
+opinion, whoever hove those things in here caught a sight of us and
+took us for ghosts or devils or something. I'll bet they're running
+yet."
+
+Joe grumbled awhile; then he agreed with his friend that what daylight
+was left ought to be economized in getting things ready for leaving.
+Shortly afterward they slipped out of the house in the deepening
+twilight, and moved toward the river with their precious box.
+
+Tom and Huck rose up, weak but vastly relieved, and stared after them
+through the chinks between the logs of the house. Follow? Not they.
+They were content to reach ground again without broken necks, and take
+the townward track over the hill. They did not talk much. They were too
+much absorbed in hating themselves--hating the ill luck that made them
+take the spade and the pick there. But for that, Injun Joe never would
+have suspected. He would have hidden the silver with the gold to wait
+there till his "revenge" was satisfied, and then he would have had the
+misfortune to find that money turn up missing. Bitter, bitter luck that
+the tools were ever brought there!
+
+They resolved to keep a lookout for that Spaniard when he should come
+to town spying out for chances to do his revengeful job, and follow him
+to "Number Two," wherever that might be. Then a ghastly thought
+occurred to Tom.
+
+"Revenge? What if he means US, Huck!"
+
+"Oh, don't!" said Huck, nearly fainting.
+
+They talked it all over, and as they entered town they agreed to
+believe that he might possibly mean somebody else--at least that he
+might at least mean nobody but Tom, since only Tom had testified.
+
+Very, very small comfort it was to Tom to be alone in danger! Company
+would be a palpable improvement, he thought.
+
+
+
+CHAPTER XXVII
+
+THE adventure of the day mightily tormented Tom's dreams that night.
+Four times he had his hands on that rich treasure and four times it
+wasted to nothingness in his fingers as sleep forsook him and
+wakefulness brought back the hard reality of his misfortune. As he lay
+in the early morning recalling the incidents of his great adventure, he
+noticed that they seemed curiously subdued and far away--somewhat as if
+they had happened in another world, or in a time long gone by. Then it
+occurred to him that the great adventure itself must be a dream! There
+was one very strong argument in favor of this idea--namely, that the
+quantity of coin he had seen was too vast to be real. He had never seen
+as much as fifty dollars in one mass before, and he was like all boys
+of his age and station in life, in that he imagined that all references
+to "hundreds" and "thousands" were mere fanciful forms of speech, and
+that no such sums really existed in the world. He never had supposed
+for a moment that so large a sum as a hundred dollars was to be found
+in actual money in any one's possession. If his notions of hidden
+treasure had been analyzed, they would have been found to consist of a
+handful of real dimes and a bushel of vague, splendid, ungraspable
+dollars.
+
+But the incidents of his adventure grew sensibly sharper and clearer
+under the attrition of thinking them over, and so he presently found
+himself leaning to the impression that the thing might not have been a
+dream, after all. This uncertainty must be swept away. He would snatch
+a hurried breakfast and go and find Huck. Huck was sitting on the
+gunwale of a flatboat, listlessly dangling his feet in the water and
+looking very melancholy. Tom concluded to let Huck lead up to the
+subject. If he did not do it, then the adventure would be proved to
+have been only a dream.
+
+"Hello, Huck!"
+
+"Hello, yourself."
+
+Silence, for a minute.
+
+"Tom, if we'd 'a' left the blame tools at the dead tree, we'd 'a' got
+the money. Oh, ain't it awful!"
+
+"'Tain't a dream, then, 'tain't a dream! Somehow I most wish it was.
+Dog'd if I don't, Huck."
+
+"What ain't a dream?"
+
+"Oh, that thing yesterday. I been half thinking it was."
+
+"Dream! If them stairs hadn't broke down you'd 'a' seen how much dream
+it was! I've had dreams enough all night--with that patch-eyed Spanish
+devil going for me all through 'em--rot him!"
+
+"No, not rot him. FIND him! Track the money!"
+
+"Tom, we'll never find him. A feller don't have only one chance for
+such a pile--and that one's lost. I'd feel mighty shaky if I was to see
+him, anyway."
+
+"Well, so'd I; but I'd like to see him, anyway--and track him out--to
+his Number Two."
+
+"Number Two--yes, that's it. I been thinking 'bout that. But I can't
+make nothing out of it. What do you reckon it is?"
+
+"I dono. It's too deep. Say, Huck--maybe it's the number of a house!"
+
+"Goody!... No, Tom, that ain't it. If it is, it ain't in this
+one-horse town. They ain't no numbers here."
+
+"Well, that's so. Lemme think a minute. Here--it's the number of a
+room--in a tavern, you know!"
+
+"Oh, that's the trick! They ain't only two taverns. We can find out
+quick."
+
+"You stay here, Huck, till I come."
+
+Tom was off at once. He did not care to have Huck's company in public
+places. He was gone half an hour. He found that in the best tavern, No.
+2 had long been occupied by a young lawyer, and was still so occupied.
+In the less ostentatious house, No. 2 was a mystery. The
+tavern-keeper's young son said it was kept locked all the time, and he
+never saw anybody go into it or come out of it except at night; he did
+not know any particular reason for this state of things; had had some
+little curiosity, but it was rather feeble; had made the most of the
+mystery by entertaining himself with the idea that that room was
+"ha'nted"; had noticed that there was a light in there the night before.
+
+"That's what I've found out, Huck. I reckon that's the very No. 2
+we're after."
+
+"I reckon it is, Tom. Now what you going to do?"
+
+"Lemme think."
+
+Tom thought a long time. Then he said:
+
+"I'll tell you. The back door of that No. 2 is the door that comes out
+into that little close alley between the tavern and the old rattle trap
+of a brick store. Now you get hold of all the door-keys you can find,
+and I'll nip all of auntie's, and the first dark night we'll go there
+and try 'em. And mind you, keep a lookout for Injun Joe, because he
+said he was going to drop into town and spy around once more for a
+chance to get his revenge. If you see him, you just follow him; and if
+he don't go to that No. 2, that ain't the place."
+
+"Lordy, I don't want to foller him by myself!"
+
+"Why, it'll be night, sure. He mightn't ever see you--and if he did,
+maybe he'd never think anything."
+
+"Well, if it's pretty dark I reckon I'll track him. I dono--I dono.
+I'll try."
+
+"You bet I'll follow him, if it's dark, Huck. Why, he might 'a' found
+out he couldn't get his revenge, and be going right after that money."
+
+"It's so, Tom, it's so. I'll foller him; I will, by jingoes!"
+
+"Now you're TALKING! Don't you ever weaken, Huck, and I won't."
+
+
+
+CHAPTER XXVIII
+
+THAT night Tom and Huck were ready for their adventure. They hung
+about the neighborhood of the tavern until after nine, one watching the
+alley at a distance and the other the tavern door. Nobody entered the
+alley or left it; nobody resembling the Spaniard entered or left the
+tavern door. The night promised to be a fair one; so Tom went home with
+the understanding that if a considerable degree of darkness came on,
+Huck was to come and "maow," whereupon he would slip out and try the
+keys. But the night remained clear, and Huck closed his watch and
+retired to bed in an empty sugar hogshead about twelve.
+
+Tuesday the boys had the same ill luck. Also Wednesday. But Thursday
+night promised better. Tom slipped out in good season with his aunt's
+old tin lantern, and a large towel to blindfold it with. He hid the
+lantern in Huck's sugar hogshead and the watch began. An hour before
+midnight the tavern closed up and its lights (the only ones
+thereabouts) were put out. No Spaniard had been seen. Nobody had
+entered or left the alley. Everything was auspicious. The blackness of
+darkness reigned, the perfect stillness was interrupted only by
+occasional mutterings of distant thunder.
+
+Tom got his lantern, lit it in the hogshead, wrapped it closely in the
+towel, and the two adventurers crept in the gloom toward the tavern.
+Huck stood sentry and Tom felt his way into the alley. Then there was a
+season of waiting anxiety that weighed upon Huck's spirits like a
+mountain. He began to wish he could see a flash from the lantern--it
+would frighten him, but it would at least tell him that Tom was alive
+yet. It seemed hours since Tom had disappeared. Surely he must have
+fainted; maybe he was dead; maybe his heart had burst under terror and
+excitement. In his uneasiness Huck found himself drawing closer and
+closer to the alley; fearing all sorts of dreadful things, and
+momentarily expecting some catastrophe to happen that would take away
+his breath. There was not much to take away, for he seemed only able to
+inhale it by thimblefuls, and his heart would soon wear itself out, the
+way it was beating. Suddenly there was a flash of light and Tom came
+tearing by him: "Run!" said he; "run, for your life!"
+
+He needn't have repeated it; once was enough; Huck was making thirty
+or forty miles an hour before the repetition was uttered. The boys
+never stopped till they reached the shed of a deserted slaughter-house
+at the lower end of the village. Just as they got within its shelter
+the storm burst and the rain poured down. As soon as Tom got his breath
+he said:
+
+"Huck, it was awful! I tried two of the keys, just as soft as I could;
+but they seemed to make such a power of racket that I couldn't hardly
+get my breath I was so scared. They wouldn't turn in the lock, either.
+Well, without noticing what I was doing, I took hold of the knob, and
+open comes the door! It warn't locked! I hopped in, and shook off the
+towel, and, GREAT CAESAR'S GHOST!"
+
+"What!--what'd you see, Tom?"
+
+"Huck, I most stepped onto Injun Joe's hand!"
+
+"No!"
+
+"Yes! He was lying there, sound asleep on the floor, with his old
+patch on his eye and his arms spread out."
+
+"Lordy, what did you do? Did he wake up?"
+
+"No, never budged. Drunk, I reckon. I just grabbed that towel and
+started!"
+
+"I'd never 'a' thought of the towel, I bet!"
+
+"Well, I would. My aunt would make me mighty sick if I lost it."
+
+"Say, Tom, did you see that box?"
+
+"Huck, I didn't wait to look around. I didn't see the box, I didn't
+see the cross. I didn't see anything but a bottle and a tin cup on the
+floor by Injun Joe; yes, I saw two barrels and lots more bottles in the
+room. Don't you see, now, what's the matter with that ha'nted room?"
+
+"How?"
+
+"Why, it's ha'nted with whiskey! Maybe ALL the Temperance Taverns have
+got a ha'nted room, hey, Huck?"
+
+"Well, I reckon maybe that's so. Who'd 'a' thought such a thing? But
+say, Tom, now's a mighty good time to get that box, if Injun Joe's
+drunk."
+
+"It is, that! You try it!"
+
+Huck shuddered.
+
+"Well, no--I reckon not."
+
+"And I reckon not, Huck. Only one bottle alongside of Injun Joe ain't
+enough. If there'd been three, he'd be drunk enough and I'd do it."
+
+There was a long pause for reflection, and then Tom said:
+
+"Lookyhere, Huck, less not try that thing any more till we know Injun
+Joe's not in there. It's too scary. Now, if we watch every night, we'll
+be dead sure to see him go out, some time or other, and then we'll
+snatch that box quicker'n lightning."
+
+"Well, I'm agreed. I'll watch the whole night long, and I'll do it
+every night, too, if you'll do the other part of the job."
+
+"All right, I will. All you got to do is to trot up Hooper Street a
+block and maow--and if I'm asleep, you throw some gravel at the window
+and that'll fetch me."
+
+"Agreed, and good as wheat!"
+
+"Now, Huck, the storm's over, and I'll go home. It'll begin to be
+daylight in a couple of hours. You go back and watch that long, will
+you?"
+
+"I said I would, Tom, and I will. I'll ha'nt that tavern every night
+for a year! I'll sleep all day and I'll stand watch all night."
+
+"That's all right. Now, where you going to sleep?"
+
+"In Ben Rogers' hayloft. He lets me, and so does his pap's nigger man,
+Uncle Jake. I tote water for Uncle Jake whenever he wants me to, and
+any time I ask him he gives me a little something to eat if he can
+spare it. That's a mighty good nigger, Tom. He likes me, becuz I don't
+ever act as if I was above him. Sometime I've set right down and eat
+WITH him. But you needn't tell that. A body's got to do things when
+he's awful hungry he wouldn't want to do as a steady thing."
+
+"Well, if I don't want you in the daytime, I'll let you sleep. I won't
+come bothering around. Any time you see something's up, in the night,
+just skip right around and maow."
+
+
+
+CHAPTER XXIX
+
+THE first thing Tom heard on Friday morning was a glad piece of news
+--Judge Thatcher's family had come back to town the night before. Both
+Injun Joe and the treasure sunk into secondary importance for a moment,
+and Becky took the chief place in the boy's interest. He saw her and
+they had an exhausting good time playing "hi-spy" and "gully-keeper"
+with a crowd of their school-mates. The day was completed and crowned
+in a peculiarly satisfactory way: Becky teased her mother to appoint
+the next day for the long-promised and long-delayed picnic, and she
+consented. The child's delight was boundless; and Tom's not more
+moderate. The invitations were sent out before sunset, and straightway
+the young folks of the village were thrown into a fever of preparation
+and pleasurable anticipation. Tom's excitement enabled him to keep
+awake until a pretty late hour, and he had good hopes of hearing Huck's
+"maow," and of having his treasure to astonish Becky and the picnickers
+with, next day; but he was disappointed. No signal came that night.
+
+Morning came, eventually, and by ten or eleven o'clock a giddy and
+rollicking company were gathered at Judge Thatcher's, and everything
+was ready for a start. It was not the custom for elderly people to mar
+the picnics with their presence. The children were considered safe
+enough under the wings of a few young ladies of eighteen and a few
+young gentlemen of twenty-three or thereabouts. The old steam ferryboat
+was chartered for the occasion; presently the gay throng filed up the
+main street laden with provision-baskets. Sid was sick and had to miss
+the fun; Mary remained at home to entertain him. The last thing Mrs.
+Thatcher said to Becky, was:
+
+"You'll not get back till late. Perhaps you'd better stay all night
+with some of the girls that live near the ferry-landing, child."
+
+"Then I'll stay with Susy Harper, mamma."
+
+"Very well. And mind and behave yourself and don't be any trouble."
+
+Presently, as they tripped along, Tom said to Becky:
+
+"Say--I'll tell you what we'll do. 'Stead of going to Joe Harper's
+we'll climb right up the hill and stop at the Widow Douglas'. She'll
+have ice-cream! She has it most every day--dead loads of it. And she'll
+be awful glad to have us."
+
+"Oh, that will be fun!"
+
+Then Becky reflected a moment and said:
+
+"But what will mamma say?"
+
+"How'll she ever know?"
+
+The girl turned the idea over in her mind, and said reluctantly:
+
+"I reckon it's wrong--but--"
+
+"But shucks! Your mother won't know, and so what's the harm? All she
+wants is that you'll be safe; and I bet you she'd 'a' said go there if
+she'd 'a' thought of it. I know she would!"
+
+The Widow Douglas' splendid hospitality was a tempting bait. It and
+Tom's persuasions presently carried the day. So it was decided to say
+nothing anybody about the night's programme. Presently it occurred to
+Tom that maybe Huck might come this very night and give the signal. The
+thought took a deal of the spirit out of his anticipations. Still he
+could not bear to give up the fun at Widow Douglas'. And why should he
+give it up, he reasoned--the signal did not come the night before, so
+why should it be any more likely to come to-night? The sure fun of the
+evening outweighed the uncertain treasure; and, boy-like, he determined
+to yield to the stronger inclination and not allow himself to think of
+the box of money another time that day.
+
+Three miles below town the ferryboat stopped at the mouth of a woody
+hollow and tied up. The crowd swarmed ashore and soon the forest
+distances and craggy heights echoed far and near with shoutings and
+laughter. All the different ways of getting hot and tired were gone
+through with, and by-and-by the rovers straggled back to camp fortified
+with responsible appetites, and then the destruction of the good things
+began. After the feast there was a refreshing season of rest and chat
+in the shade of spreading oaks. By-and-by somebody shouted:
+
+"Who's ready for the cave?"
+
+Everybody was. Bundles of candles were procured, and straightway there
+was a general scamper up the hill. The mouth of the cave was up the
+hillside--an opening shaped like a letter A. Its massive oaken door
+stood unbarred. Within was a small chamber, chilly as an ice-house, and
+walled by Nature with solid limestone that was dewy with a cold sweat.
+It was romantic and mysterious to stand here in the deep gloom and look
+out upon the green valley shining in the sun. But the impressiveness of
+the situation quickly wore off, and the romping began again. The moment
+a candle was lighted there was a general rush upon the owner of it; a
+struggle and a gallant defence followed, but the candle was soon
+knocked down or blown out, and then there was a glad clamor of laughter
+and a new chase. But all things have an end. By-and-by the procession
+went filing down the steep descent of the main avenue, the flickering
+rank of lights dimly revealing the lofty walls of rock almost to their
+point of junction sixty feet overhead. This main avenue was not more
+than eight or ten feet wide. Every few steps other lofty and still
+narrower crevices branched from it on either hand--for McDougal's cave
+was but a vast labyrinth of crooked aisles that ran into each other and
+out again and led nowhere. It was said that one might wander days and
+nights together through its intricate tangle of rifts and chasms, and
+never find the end of the cave; and that he might go down, and down,
+and still down, into the earth, and it was just the same--labyrinth
+under labyrinth, and no end to any of them. No man "knew" the cave.
+That was an impossible thing. Most of the young men knew a portion of
+it, and it was not customary to venture much beyond this known portion.
+Tom Sawyer knew as much of the cave as any one.
+
+The procession moved along the main avenue some three-quarters of a
+mile, and then groups and couples began to slip aside into branch
+avenues, fly along the dismal corridors, and take each other by
+surprise at points where the corridors joined again. Parties were able
+to elude each other for the space of half an hour without going beyond
+the "known" ground.
+
+By-and-by, one group after another came straggling back to the mouth
+of the cave, panting, hilarious, smeared from head to foot with tallow
+drippings, daubed with clay, and entirely delighted with the success of
+the day. Then they were astonished to find that they had been taking no
+note of time and that night was about at hand. The clanging bell had
+been calling for half an hour. However, this sort of close to the day's
+adventures was romantic and therefore satisfactory. When the ferryboat
+with her wild freight pushed into the stream, nobody cared sixpence for
+the wasted time but the captain of the craft.
+
+Huck was already upon his watch when the ferryboat's lights went
+glinting past the wharf. He heard no noise on board, for the young
+people were as subdued and still as people usually are who are nearly
+tired to death. He wondered what boat it was, and why she did not stop
+at the wharf--and then he dropped her out of his mind and put his
+attention upon his business. The night was growing cloudy and dark. Ten
+o'clock came, and the noise of vehicles ceased, scattered lights began
+to wink out, all straggling foot-passengers disappeared, the village
+betook itself to its slumbers and left the small watcher alone with the
+silence and the ghosts. Eleven o'clock came, and the tavern lights were
+put out; darkness everywhere, now. Huck waited what seemed a weary long
+time, but nothing happened. His faith was weakening. Was there any use?
+Was there really any use? Why not give it up and turn in?
+
+A noise fell upon his ear. He was all attention in an instant. The
+alley door closed softly. He sprang to the corner of the brick store.
+The next moment two men brushed by him, and one seemed to have
+something under his arm. It must be that box! So they were going to
+remove the treasure. Why call Tom now? It would be absurd--the men
+would get away with the box and never be found again. No, he would
+stick to their wake and follow them; he would trust to the darkness for
+security from discovery. So communing with himself, Huck stepped out
+and glided along behind the men, cat-like, with bare feet, allowing
+them to keep just far enough ahead not to be invisible.
+
+They moved up the river street three blocks, then turned to the left
+up a cross-street. They went straight ahead, then, until they came to
+the path that led up Cardiff Hill; this they took. They passed by the
+old Welshman's house, half-way up the hill, without hesitating, and
+still climbed upward. Good, thought Huck, they will bury it in the old
+quarry. But they never stopped at the quarry. They passed on, up the
+summit. They plunged into the narrow path between the tall sumach
+bushes, and were at once hidden in the gloom. Huck closed up and
+shortened his distance, now, for they would never be able to see him.
+He trotted along awhile; then slackened his pace, fearing he was
+gaining too fast; moved on a piece, then stopped altogether; listened;
+no sound; none, save that he seemed to hear the beating of his own
+heart. The hooting of an owl came over the hill--ominous sound! But no
+footsteps. Heavens, was everything lost! He was about to spring with
+winged feet, when a man cleared his throat not four feet from him!
+Huck's heart shot into his throat, but he swallowed it again; and then
+he stood there shaking as if a dozen agues had taken charge of him at
+once, and so weak that he thought he must surely fall to the ground. He
+knew where he was. He knew he was within five steps of the stile
+leading into Widow Douglas' grounds. Very well, he thought, let them
+bury it there; it won't be hard to find.
+
+Now there was a voice--a very low voice--Injun Joe's:
+
+"Damn her, maybe she's got company--there's lights, late as it is."
+
+"I can't see any."
+
+This was that stranger's voice--the stranger of the haunted house. A
+deadly chill went to Huck's heart--this, then, was the "revenge" job!
+His thought was, to fly. Then he remembered that the Widow Douglas had
+been kind to him more than once, and maybe these men were going to
+murder her. He wished he dared venture to warn her; but he knew he
+didn't dare--they might come and catch him. He thought all this and
+more in the moment that elapsed between the stranger's remark and Injun
+Joe's next--which was--
+
+"Because the bush is in your way. Now--this way--now you see, don't
+you?"
+
+"Yes. Well, there IS company there, I reckon. Better give it up."
+
+"Give it up, and I just leaving this country forever! Give it up and
+maybe never have another chance. I tell you again, as I've told you
+before, I don't care for her swag--you may have it. But her husband was
+rough on me--many times he was rough on me--and mainly he was the
+justice of the peace that jugged me for a vagrant. And that ain't all.
+It ain't a millionth part of it! He had me HORSEWHIPPED!--horsewhipped
+in front of the jail, like a nigger!--with all the town looking on!
+HORSEWHIPPED!--do you understand? He took advantage of me and died. But
+I'll take it out of HER."
+
+"Oh, don't kill her! Don't do that!"
+
+"Kill? Who said anything about killing? I would kill HIM if he was
+here; but not her. When you want to get revenge on a woman you don't
+kill her--bosh! you go for her looks. You slit her nostrils--you notch
+her ears like a sow!"
+
+"By God, that's--"
+
+"Keep your opinion to yourself! It will be safest for you. I'll tie
+her to the bed. If she bleeds to death, is that my fault? I'll not cry,
+if she does. My friend, you'll help me in this thing--for MY sake
+--that's why you're here--I mightn't be able alone. If you flinch, I'll
+kill you. Do you understand that? And if I have to kill you, I'll kill
+her--and then I reckon nobody'll ever know much about who done this
+business."
+
+"Well, if it's got to be done, let's get at it. The quicker the
+better--I'm all in a shiver."
+
+"Do it NOW? And company there? Look here--I'll get suspicious of you,
+first thing you know. No--we'll wait till the lights are out--there's
+no hurry."
+
+Huck felt that a silence was going to ensue--a thing still more awful
+than any amount of murderous talk; so he held his breath and stepped
+gingerly back; planted his foot carefully and firmly, after balancing,
+one-legged, in a precarious way and almost toppling over, first on one
+side and then on the other. He took another step back, with the same
+elaboration and the same risks; then another and another, and--a twig
+snapped under his foot! His breath stopped and he listened. There was
+no sound--the stillness was perfect. His gratitude was measureless. Now
+he turned in his tracks, between the walls of sumach bushes--turned
+himself as carefully as if he were a ship--and then stepped quickly but
+cautiously along. When he emerged at the quarry he felt secure, and so
+he picked up his nimble heels and flew. Down, down he sped, till he
+reached the Welshman's. He banged at the door, and presently the heads
+of the old man and his two stalwart sons were thrust from windows.
+
+"What's the row there? Who's banging? What do you want?"
+
+"Let me in--quick! I'll tell everything."
+
+"Why, who are you?"
+
+"Huckleberry Finn--quick, let me in!"
+
+"Huckleberry Finn, indeed! It ain't a name to open many doors, I
+judge! But let him in, lads, and let's see what's the trouble."
+
+"Please don't ever tell I told you," were Huck's first words when he
+got in. "Please don't--I'd be killed, sure--but the widow's been good
+friends to me sometimes, and I want to tell--I WILL tell if you'll
+promise you won't ever say it was me."
+
+"By George, he HAS got something to tell, or he wouldn't act so!"
+exclaimed the old man; "out with it and nobody here'll ever tell, lad."
+
+Three minutes later the old man and his sons, well armed, were up the
+hill, and just entering the sumach path on tiptoe, their weapons in
+their hands. Huck accompanied them no further. He hid behind a great
+bowlder and fell to listening. There was a lagging, anxious silence,
+and then all of a sudden there was an explosion of firearms and a cry.
+
+Huck waited for no particulars. He sprang away and sped down the hill
+as fast as his legs could carry him.
+
+
+
+CHAPTER XXX
+
+AS the earliest suspicion of dawn appeared on Sunday morning, Huck
+came groping up the hill and rapped gently at the old Welshman's door.
+The inmates were asleep, but it was a sleep that was set on a
+hair-trigger, on account of the exciting episode of the night. A call
+came from a window:
+
+"Who's there!"
+
+Huck's scared voice answered in a low tone:
+
+"Please let me in! It's only Huck Finn!"
+
+"It's a name that can open this door night or day, lad!--and welcome!"
+
+These were strange words to the vagabond boy's ears, and the
+pleasantest he had ever heard. He could not recollect that the closing
+word had ever been applied in his case before. The door was quickly
+unlocked, and he entered. Huck was given a seat and the old man and his
+brace of tall sons speedily dressed themselves.
+
+"Now, my boy, I hope you're good and hungry, because breakfast will be
+ready as soon as the sun's up, and we'll have a piping hot one, too
+--make yourself easy about that! I and the boys hoped you'd turn up and
+stop here last night."
+
+"I was awful scared," said Huck, "and I run. I took out when the
+pistols went off, and I didn't stop for three mile. I've come now becuz
+I wanted to know about it, you know; and I come before daylight becuz I
+didn't want to run across them devils, even if they was dead."
+
+"Well, poor chap, you do look as if you'd had a hard night of it--but
+there's a bed here for you when you've had your breakfast. No, they
+ain't dead, lad--we are sorry enough for that. You see we knew right
+where to put our hands on them, by your description; so we crept along
+on tiptoe till we got within fifteen feet of them--dark as a cellar
+that sumach path was--and just then I found I was going to sneeze. It
+was the meanest kind of luck! I tried to keep it back, but no use
+--'twas bound to come, and it did come! I was in the lead with my pistol
+raised, and when the sneeze started those scoundrels a-rustling to get
+out of the path, I sung out, 'Fire boys!' and blazed away at the place
+where the rustling was. So did the boys. But they were off in a jiffy,
+those villains, and we after them, down through the woods. I judge we
+never touched them. They fired a shot apiece as they started, but their
+bullets whizzed by and didn't do us any harm. As soon as we lost the
+sound of their feet we quit chasing, and went down and stirred up the
+constables. They got a posse together, and went off to guard the river
+bank, and as soon as it is light the sheriff and a gang are going to
+beat up the woods. My boys will be with them presently. I wish we had
+some sort of description of those rascals--'twould help a good deal.
+But you couldn't see what they were like, in the dark, lad, I suppose?"
+
+"Oh yes; I saw them down-town and follered them."
+
+"Splendid! Describe them--describe them, my boy!"
+
+"One's the old deaf and dumb Spaniard that's ben around here once or
+twice, and t'other's a mean-looking, ragged--"
+
+"That's enough, lad, we know the men! Happened on them in the woods
+back of the widow's one day, and they slunk away. Off with you, boys,
+and tell the sheriff--get your breakfast to-morrow morning!"
+
+The Welshman's sons departed at once. As they were leaving the room
+Huck sprang up and exclaimed:
+
+"Oh, please don't tell ANYbody it was me that blowed on them! Oh,
+please!"
+
+"All right if you say it, Huck, but you ought to have the credit of
+what you did."
+
+"Oh no, no! Please don't tell!"
+
+When the young men were gone, the old Welshman said:
+
+"They won't tell--and I won't. But why don't you want it known?"
+
+Huck would not explain, further than to say that he already knew too
+much about one of those men and would not have the man know that he
+knew anything against him for the whole world--he would be killed for
+knowing it, sure.
+
+The old man promised secrecy once more, and said:
+
+"How did you come to follow these fellows, lad? Were they looking
+suspicious?"
+
+Huck was silent while he framed a duly cautious reply. Then he said:
+
+"Well, you see, I'm a kind of a hard lot,--least everybody says so,
+and I don't see nothing agin it--and sometimes I can't sleep much, on
+account of thinking about it and sort of trying to strike out a new way
+of doing. That was the way of it last night. I couldn't sleep, and so I
+come along up-street 'bout midnight, a-turning it all over, and when I
+got to that old shackly brick store by the Temperance Tavern, I backed
+up agin the wall to have another think. Well, just then along comes
+these two chaps slipping along close by me, with something under their
+arm, and I reckoned they'd stole it. One was a-smoking, and t'other one
+wanted a light; so they stopped right before me and the cigars lit up
+their faces and I see that the big one was the deaf and dumb Spaniard,
+by his white whiskers and the patch on his eye, and t'other one was a
+rusty, ragged-looking devil."
+
+"Could you see the rags by the light of the cigars?"
+
+This staggered Huck for a moment. Then he said:
+
+"Well, I don't know--but somehow it seems as if I did."
+
+"Then they went on, and you--"
+
+"Follered 'em--yes. That was it. I wanted to see what was up--they
+sneaked along so. I dogged 'em to the widder's stile, and stood in the
+dark and heard the ragged one beg for the widder, and the Spaniard
+swear he'd spile her looks just as I told you and your two--"
+
+"What! The DEAF AND DUMB man said all that!"
+
+Huck had made another terrible mistake! He was trying his best to keep
+the old man from getting the faintest hint of who the Spaniard might
+be, and yet his tongue seemed determined to get him into trouble in
+spite of all he could do. He made several efforts to creep out of his
+scrape, but the old man's eye was upon him and he made blunder after
+blunder. Presently the Welshman said:
+
+"My boy, don't be afraid of me. I wouldn't hurt a hair of your head
+for all the world. No--I'd protect you--I'd protect you. This Spaniard
+is not deaf and dumb; you've let that slip without intending it; you
+can't cover that up now. You know something about that Spaniard that
+you want to keep dark. Now trust me--tell me what it is, and trust me
+--I won't betray you."
+
+Huck looked into the old man's honest eyes a moment, then bent over
+and whispered in his ear:
+
+"'Tain't a Spaniard--it's Injun Joe!"
+
+The Welshman almost jumped out of his chair. In a moment he said:
+
+"It's all plain enough, now. When you talked about notching ears and
+slitting noses I judged that that was your own embellishment, because
+white men don't take that sort of revenge. But an Injun! That's a
+different matter altogether."
+
+During breakfast the talk went on, and in the course of it the old man
+said that the last thing which he and his sons had done, before going
+to bed, was to get a lantern and examine the stile and its vicinity for
+marks of blood. They found none, but captured a bulky bundle of--
+
+"Of WHAT?"
+
+If the words had been lightning they could not have leaped with a more
+stunning suddenness from Huck's blanched lips. His eyes were staring
+wide, now, and his breath suspended--waiting for the answer. The
+Welshman started--stared in return--three seconds--five seconds--ten
+--then replied:
+
+"Of burglar's tools. Why, what's the MATTER with you?"
+
+Huck sank back, panting gently, but deeply, unutterably grateful. The
+Welshman eyed him gravely, curiously--and presently said:
+
+"Yes, burglar's tools. That appears to relieve you a good deal. But
+what did give you that turn? What were YOU expecting we'd found?"
+
+Huck was in a close place--the inquiring eye was upon him--he would
+have given anything for material for a plausible answer--nothing
+suggested itself--the inquiring eye was boring deeper and deeper--a
+senseless reply offered--there was no time to weigh it, so at a venture
+he uttered it--feebly:
+
+"Sunday-school books, maybe."
+
+Poor Huck was too distressed to smile, but the old man laughed loud
+and joyously, shook up the details of his anatomy from head to foot,
+and ended by saying that such a laugh was money in a-man's pocket,
+because it cut down the doctor's bill like everything. Then he added:
+
+"Poor old chap, you're white and jaded--you ain't well a bit--no
+wonder you're a little flighty and off your balance. But you'll come
+out of it. Rest and sleep will fetch you out all right, I hope."
+
+Huck was irritated to think he had been such a goose and betrayed such
+a suspicious excitement, for he had dropped the idea that the parcel
+brought from the tavern was the treasure, as soon as he had heard the
+talk at the widow's stile. He had only thought it was not the treasure,
+however--he had not known that it wasn't--and so the suggestion of a
+captured bundle was too much for his self-possession. But on the whole
+he felt glad the little episode had happened, for now he knew beyond
+all question that that bundle was not THE bundle, and so his mind was
+at rest and exceedingly comfortable. In fact, everything seemed to be
+drifting just in the right direction, now; the treasure must be still
+in No. 2, the men would be captured and jailed that day, and he and Tom
+could seize the gold that night without any trouble or any fear of
+interruption.
+
+Just as breakfast was completed there was a knock at the door. Huck
+jumped for a hiding-place, for he had no mind to be connected even
+remotely with the late event. The Welshman admitted several ladies and
+gentlemen, among them the Widow Douglas, and noticed that groups of
+citizens were climbing up the hill--to stare at the stile. So the news
+had spread. The Welshman had to tell the story of the night to the
+visitors. The widow's gratitude for her preservation was outspoken.
+
+"Don't say a word about it, madam. There's another that you're more
+beholden to than you are to me and my boys, maybe, but he don't allow
+me to tell his name. We wouldn't have been there but for him."
+
+Of course this excited a curiosity so vast that it almost belittled
+the main matter--but the Welshman allowed it to eat into the vitals of
+his visitors, and through them be transmitted to the whole town, for he
+refused to part with his secret. When all else had been learned, the
+widow said:
+
+"I went to sleep reading in bed and slept straight through all that
+noise. Why didn't you come and wake me?"
+
+"We judged it warn't worth while. Those fellows warn't likely to come
+again--they hadn't any tools left to work with, and what was the use of
+waking you up and scaring you to death? My three negro men stood guard
+at your house all the rest of the night. They've just come back."
+
+More visitors came, and the story had to be told and retold for a
+couple of hours more.
+
+There was no Sabbath-school during day-school vacation, but everybody
+was early at church. The stirring event was well canvassed. News came
+that not a sign of the two villains had been yet discovered. When the
+sermon was finished, Judge Thatcher's wife dropped alongside of Mrs.
+Harper as she moved down the aisle with the crowd and said:
+
+"Is my Becky going to sleep all day? I just expected she would be
+tired to death."
+
+"Your Becky?"
+
+"Yes," with a startled look--"didn't she stay with you last night?"
+
+"Why, no."
+
+Mrs. Thatcher turned pale, and sank into a pew, just as Aunt Polly,
+talking briskly with a friend, passed by. Aunt Polly said:
+
+"Good-morning, Mrs. Thatcher. Good-morning, Mrs. Harper. I've got a
+boy that's turned up missing. I reckon my Tom stayed at your house last
+night--one of you. And now he's afraid to come to church. I've got to
+settle with him."
+
+Mrs. Thatcher shook her head feebly and turned paler than ever.
+
+"He didn't stay with us," said Mrs. Harper, beginning to look uneasy.
+A marked anxiety came into Aunt Polly's face.
+
+"Joe Harper, have you seen my Tom this morning?"
+
+"No'm."
+
+"When did you see him last?"
+
+Joe tried to remember, but was not sure he could say. The people had
+stopped moving out of church. Whispers passed along, and a boding
+uneasiness took possession of every countenance. Children were
+anxiously questioned, and young teachers. They all said they had not
+noticed whether Tom and Becky were on board the ferryboat on the
+homeward trip; it was dark; no one thought of inquiring if any one was
+missing. One young man finally blurted out his fear that they were
+still in the cave! Mrs. Thatcher swooned away. Aunt Polly fell to
+crying and wringing her hands.
+
+The alarm swept from lip to lip, from group to group, from street to
+street, and within five minutes the bells were wildly clanging and the
+whole town was up! The Cardiff Hill episode sank into instant
+insignificance, the burglars were forgotten, horses were saddled,
+skiffs were manned, the ferryboat ordered out, and before the horror
+was half an hour old, two hundred men were pouring down highroad and
+river toward the cave.
+
+All the long afternoon the village seemed empty and dead. Many women
+visited Aunt Polly and Mrs. Thatcher and tried to comfort them. They
+cried with them, too, and that was still better than words. All the
+tedious night the town waited for news; but when the morning dawned at
+last, all the word that came was, "Send more candles--and send food."
+Mrs. Thatcher was almost crazed; and Aunt Polly, also. Judge Thatcher
+sent messages of hope and encouragement from the cave, but they
+conveyed no real cheer.
+
+The old Welshman came home toward daylight, spattered with
+candle-grease, smeared with clay, and almost worn out. He found Huck
+still in the bed that had been provided for him, and delirious with
+fever. The physicians were all at the cave, so the Widow Douglas came
+and took charge of the patient. She said she would do her best by him,
+because, whether he was good, bad, or indifferent, he was the Lord's,
+and nothing that was the Lord's was a thing to be neglected. The
+Welshman said Huck had good spots in him, and the widow said:
+
+"You can depend on it. That's the Lord's mark. He don't leave it off.
+He never does. Puts it somewhere on every creature that comes from his
+hands."
+
+Early in the forenoon parties of jaded men began to straggle into the
+village, but the strongest of the citizens continued searching. All the
+news that could be gained was that remotenesses of the cavern were
+being ransacked that had never been visited before; that every corner
+and crevice was going to be thoroughly searched; that wherever one
+wandered through the maze of passages, lights were to be seen flitting
+hither and thither in the distance, and shoutings and pistol-shots sent
+their hollow reverberations to the ear down the sombre aisles. In one
+place, far from the section usually traversed by tourists, the names
+"BECKY & TOM" had been found traced upon the rocky wall with
+candle-smoke, and near at hand a grease-soiled bit of ribbon. Mrs.
+Thatcher recognized the ribbon and cried over it. She said it was the
+last relic she should ever have of her child; and that no other memorial
+of her could ever be so precious, because this one parted latest from
+the living body before the awful death came. Some said that now and
+then, in the cave, a far-away speck of light would glimmer, and then a
+glorious shout would burst forth and a score of men go trooping down the
+echoing aisle--and then a sickening disappointment always followed; the
+children were not there; it was only a searcher's light.
+
+Three dreadful days and nights dragged their tedious hours along, and
+the village sank into a hopeless stupor. No one had heart for anything.
+The accidental discovery, just made, that the proprietor of the
+Temperance Tavern kept liquor on his premises, scarcely fluttered the
+public pulse, tremendous as the fact was. In a lucid interval, Huck
+feebly led up to the subject of taverns, and finally asked--dimly
+dreading the worst--if anything had been discovered at the Temperance
+Tavern since he had been ill.
+
+"Yes," said the widow.
+
+Huck started up in bed, wild-eyed:
+
+"What? What was it?"
+
+"Liquor!--and the place has been shut up. Lie down, child--what a turn
+you did give me!"
+
+"Only tell me just one thing--only just one--please! Was it Tom Sawyer
+that found it?"
+
+The widow burst into tears. "Hush, hush, child, hush! I've told you
+before, you must NOT talk. You are very, very sick!"
+
+Then nothing but liquor had been found; there would have been a great
+powwow if it had been the gold. So the treasure was gone forever--gone
+forever! But what could she be crying about? Curious that she should
+cry.
+
+These thoughts worked their dim way through Huck's mind, and under the
+weariness they gave him he fell asleep. The widow said to herself:
+
+"There--he's asleep, poor wreck. Tom Sawyer find it! Pity but somebody
+could find Tom Sawyer! Ah, there ain't many left, now, that's got hope
+enough, or strength enough, either, to go on searching."
+
+
+
+CHAPTER XXXI
+
+NOW to return to Tom and Becky's share in the picnic. They tripped
+along the murky aisles with the rest of the company, visiting the
+familiar wonders of the cave--wonders dubbed with rather
+over-descriptive names, such as "The Drawing-Room," "The Cathedral,"
+"Aladdin's Palace," and so on. Presently the hide-and-seek frolicking
+began, and Tom and Becky engaged in it with zeal until the exertion
+began to grow a trifle wearisome; then they wandered down a sinuous
+avenue holding their candles aloft and reading the tangled web-work of
+names, dates, post-office addresses, and mottoes with which the rocky
+walls had been frescoed (in candle-smoke). Still drifting along and
+talking, they scarcely noticed that they were now in a part of the cave
+whose walls were not frescoed. They smoked their own names under an
+overhanging shelf and moved on. Presently they came to a place where a
+little stream of water, trickling over a ledge and carrying a limestone
+sediment with it, had, in the slow-dragging ages, formed a laced and
+ruffled Niagara in gleaming and imperishable stone. Tom squeezed his
+small body behind it in order to illuminate it for Becky's
+gratification. He found that it curtained a sort of steep natural
+stairway which was enclosed between narrow walls, and at once the
+ambition to be a discoverer seized him. Becky responded to his call,
+and they made a smoke-mark for future guidance, and started upon their
+quest. They wound this way and that, far down into the secret depths of
+the cave, made another mark, and branched off in search of novelties to
+tell the upper world about. In one place they found a spacious cavern,
+from whose ceiling depended a multitude of shining stalactites of the
+length and circumference of a man's leg; they walked all about it,
+wondering and admiring, and presently left it by one of the numerous
+passages that opened into it. This shortly brought them to a bewitching
+spring, whose basin was incrusted with a frostwork of glittering
+crystals; it was in the midst of a cavern whose walls were supported by
+many fantastic pillars which had been formed by the joining of great
+stalactites and stalagmites together, the result of the ceaseless
+water-drip of centuries. Under the roof vast knots of bats had packed
+themselves together, thousands in a bunch; the lights disturbed the
+creatures and they came flocking down by hundreds, squeaking and
+darting furiously at the candles. Tom knew their ways and the danger of
+this sort of conduct. He seized Becky's hand and hurried her into the
+first corridor that offered; and none too soon, for a bat struck
+Becky's light out with its wing while she was passing out of the
+cavern. The bats chased the children a good distance; but the fugitives
+plunged into every new passage that offered, and at last got rid of the
+perilous things. Tom found a subterranean lake, shortly, which
+stretched its dim length away until its shape was lost in the shadows.
+He wanted to explore its borders, but concluded that it would be best
+to sit down and rest awhile, first. Now, for the first time, the deep
+stillness of the place laid a clammy hand upon the spirits of the
+children. Becky said:
+
+"Why, I didn't notice, but it seems ever so long since I heard any of
+the others."
+
+"Come to think, Becky, we are away down below them--and I don't know
+how far away north, or south, or east, or whichever it is. We couldn't
+hear them here."
+
+Becky grew apprehensive.
+
+"I wonder how long we've been down here, Tom? We better start back."
+
+"Yes, I reckon we better. P'raps we better."
+
+"Can you find the way, Tom? It's all a mixed-up crookedness to me."
+
+"I reckon I could find it--but then the bats. If they put our candles
+out it will be an awful fix. Let's try some other way, so as not to go
+through there."
+
+"Well. But I hope we won't get lost. It would be so awful!" and the
+girl shuddered at the thought of the dreadful possibilities.
+
+They started through a corridor, and traversed it in silence a long
+way, glancing at each new opening, to see if there was anything
+familiar about the look of it; but they were all strange. Every time
+Tom made an examination, Becky would watch his face for an encouraging
+sign, and he would say cheerily:
+
+"Oh, it's all right. This ain't the one, but we'll come to it right
+away!"
+
+But he felt less and less hopeful with each failure, and presently
+began to turn off into diverging avenues at sheer random, in desperate
+hope of finding the one that was wanted. He still said it was "all
+right," but there was such a leaden dread at his heart that the words
+had lost their ring and sounded just as if he had said, "All is lost!"
+Becky clung to his side in an anguish of fear, and tried hard to keep
+back the tears, but they would come. At last she said:
+
+"Oh, Tom, never mind the bats, let's go back that way! We seem to get
+worse and worse off all the time."
+
+"Listen!" said he.
+
+Profound silence; silence so deep that even their breathings were
+conspicuous in the hush. Tom shouted. The call went echoing down the
+empty aisles and died out in the distance in a faint sound that
+resembled a ripple of mocking laughter.
+
+"Oh, don't do it again, Tom, it is too horrid," said Becky.
+
+"It is horrid, but I better, Becky; they might hear us, you know," and
+he shouted again.
+
+The "might" was even a chillier horror than the ghostly laughter, it
+so confessed a perishing hope. The children stood still and listened;
+but there was no result. Tom turned upon the back track at once, and
+hurried his steps. It was but a little while before a certain
+indecision in his manner revealed another fearful fact to Becky--he
+could not find his way back!
+
+"Oh, Tom, you didn't make any marks!"
+
+"Becky, I was such a fool! Such a fool! I never thought we might want
+to come back! No--I can't find the way. It's all mixed up."
+
+"Tom, Tom, we're lost! we're lost! We never can get out of this awful
+place! Oh, why DID we ever leave the others!"
+
+She sank to the ground and burst into such a frenzy of crying that Tom
+was appalled with the idea that she might die, or lose her reason. He
+sat down by her and put his arms around her; she buried her face in his
+bosom, she clung to him, she poured out her terrors, her unavailing
+regrets, and the far echoes turned them all to jeering laughter. Tom
+begged her to pluck up hope again, and she said she could not. He fell
+to blaming and abusing himself for getting her into this miserable
+situation; this had a better effect. She said she would try to hope
+again, she would get up and follow wherever he might lead if only he
+would not talk like that any more. For he was no more to blame than
+she, she said.
+
+So they moved on again--aimlessly--simply at random--all they could do
+was to move, keep moving. For a little while, hope made a show of
+reviving--not with any reason to back it, but only because it is its
+nature to revive when the spring has not been taken out of it by age
+and familiarity with failure.
+
+By-and-by Tom took Becky's candle and blew it out. This economy meant
+so much! Words were not needed. Becky understood, and her hope died
+again. She knew that Tom had a whole candle and three or four pieces in
+his pockets--yet he must economize.
+
+By-and-by, fatigue began to assert its claims; the children tried to
+pay attention, for it was dreadful to think of sitting down when time
+was grown to be so precious, moving, in some direction, in any
+direction, was at least progress and might bear fruit; but to sit down
+was to invite death and shorten its pursuit.
+
+At last Becky's frail limbs refused to carry her farther. She sat
+down. Tom rested with her, and they talked of home, and the friends
+there, and the comfortable beds and, above all, the light! Becky cried,
+and Tom tried to think of some way of comforting her, but all his
+encouragements were grown threadbare with use, and sounded like
+sarcasms. Fatigue bore so heavily upon Becky that she drowsed off to
+sleep. Tom was grateful. He sat looking into her drawn face and saw it
+grow smooth and natural under the influence of pleasant dreams; and
+by-and-by a smile dawned and rested there. The peaceful face reflected
+somewhat of peace and healing into his own spirit, and his thoughts
+wandered away to bygone times and dreamy memories. While he was deep in
+his musings, Becky woke up with a breezy little laugh--but it was
+stricken dead upon her lips, and a groan followed it.
+
+"Oh, how COULD I sleep! I wish I never, never had waked! No! No, I
+don't, Tom! Don't look so! I won't say it again."
+
+"I'm glad you've slept, Becky; you'll feel rested, now, and we'll find
+the way out."
+
+"We can try, Tom; but I've seen such a beautiful country in my dream.
+I reckon we are going there."
+
+"Maybe not, maybe not. Cheer up, Becky, and let's go on trying."
+
+They rose up and wandered along, hand in hand and hopeless. They tried
+to estimate how long they had been in the cave, but all they knew was
+that it seemed days and weeks, and yet it was plain that this could not
+be, for their candles were not gone yet. A long time after this--they
+could not tell how long--Tom said they must go softly and listen for
+dripping water--they must find a spring. They found one presently, and
+Tom said it was time to rest again. Both were cruelly tired, yet Becky
+said she thought she could go a little farther. She was surprised to
+hear Tom dissent. She could not understand it. They sat down, and Tom
+fastened his candle to the wall in front of them with some clay.
+Thought was soon busy; nothing was said for some time. Then Becky broke
+the silence:
+
+"Tom, I am so hungry!"
+
+Tom took something out of his pocket.
+
+"Do you remember this?" said he.
+
+Becky almost smiled.
+
+"It's our wedding-cake, Tom."
+
+"Yes--I wish it was as big as a barrel, for it's all we've got."
+
+"I saved it from the picnic for us to dream on, Tom, the way grown-up
+people do with wedding-cake--but it'll be our--"
+
+She dropped the sentence where it was. Tom divided the cake and Becky
+ate with good appetite, while Tom nibbled at his moiety. There was
+abundance of cold water to finish the feast with. By-and-by Becky
+suggested that they move on again. Tom was silent a moment. Then he
+said:
+
+"Becky, can you bear it if I tell you something?"
+
+Becky's face paled, but she thought she could.
+
+"Well, then, Becky, we must stay here, where there's water to drink.
+That little piece is our last candle!"
+
+Becky gave loose to tears and wailings. Tom did what he could to
+comfort her, but with little effect. At length Becky said:
+
+"Tom!"
+
+"Well, Becky?"
+
+"They'll miss us and hunt for us!"
+
+"Yes, they will! Certainly they will!"
+
+"Maybe they're hunting for us now, Tom."
+
+"Why, I reckon maybe they are. I hope they are."
+
+"When would they miss us, Tom?"
+
+"When they get back to the boat, I reckon."
+
+"Tom, it might be dark then--would they notice we hadn't come?"
+
+"I don't know. But anyway, your mother would miss you as soon as they
+got home."
+
+A frightened look in Becky's face brought Tom to his senses and he saw
+that he had made a blunder. Becky was not to have gone home that night!
+The children became silent and thoughtful. In a moment a new burst of
+grief from Becky showed Tom that the thing in his mind had struck hers
+also--that the Sabbath morning might be half spent before Mrs. Thatcher
+discovered that Becky was not at Mrs. Harper's.
+
+The children fastened their eyes upon their bit of candle and watched
+it melt slowly and pitilessly away; saw the half inch of wick stand
+alone at last; saw the feeble flame rise and fall, climb the thin
+column of smoke, linger at its top a moment, and then--the horror of
+utter darkness reigned!
+
+How long afterward it was that Becky came to a slow consciousness that
+she was crying in Tom's arms, neither could tell. All that they knew
+was, that after what seemed a mighty stretch of time, both awoke out of
+a dead stupor of sleep and resumed their miseries once more. Tom said
+it might be Sunday, now--maybe Monday. He tried to get Becky to talk,
+but her sorrows were too oppressive, all her hopes were gone. Tom said
+that they must have been missed long ago, and no doubt the search was
+going on. He would shout and maybe some one would come. He tried it;
+but in the darkness the distant echoes sounded so hideously that he
+tried it no more.
+
+The hours wasted away, and hunger came to torment the captives again.
+A portion of Tom's half of the cake was left; they divided and ate it.
+But they seemed hungrier than before. The poor morsel of food only
+whetted desire.
+
+By-and-by Tom said:
+
+"SH! Did you hear that?"
+
+Both held their breath and listened. There was a sound like the
+faintest, far-off shout. Instantly Tom answered it, and leading Becky
+by the hand, started groping down the corridor in its direction.
+Presently he listened again; again the sound was heard, and apparently
+a little nearer.
+
+"It's them!" said Tom; "they're coming! Come along, Becky--we're all
+right now!"
+
+The joy of the prisoners was almost overwhelming. Their speed was
+slow, however, because pitfalls were somewhat common, and had to be
+guarded against. They shortly came to one and had to stop. It might be
+three feet deep, it might be a hundred--there was no passing it at any
+rate. Tom got down on his breast and reached as far down as he could.
+No bottom. They must stay there and wait until the searchers came. They
+listened; evidently the distant shoutings were growing more distant! a
+moment or two more and they had gone altogether. The heart-sinking
+misery of it! Tom whooped until he was hoarse, but it was of no use. He
+talked hopefully to Becky; but an age of anxious waiting passed and no
+sounds came again.
+
+The children groped their way back to the spring. The weary time
+dragged on; they slept again, and awoke famished and woe-stricken. Tom
+believed it must be Tuesday by this time.
+
+Now an idea struck him. There were some side passages near at hand. It
+would be better to explore some of these than bear the weight of the
+heavy time in idleness. He took a kite-line from his pocket, tied it to
+a projection, and he and Becky started, Tom in the lead, unwinding the
+line as he groped along. At the end of twenty steps the corridor ended
+in a "jumping-off place." Tom got down on his knees and felt below, and
+then as far around the corner as he could reach with his hands
+conveniently; he made an effort to stretch yet a little farther to the
+right, and at that moment, not twenty yards away, a human hand, holding
+a candle, appeared from behind a rock! Tom lifted up a glorious shout,
+and instantly that hand was followed by the body it belonged to--Injun
+Joe's! Tom was paralyzed; he could not move. He was vastly gratified
+the next moment, to see the "Spaniard" take to his heels and get
+himself out of sight. Tom wondered that Joe had not recognized his
+voice and come over and killed him for testifying in court. But the
+echoes must have disguised the voice. Without doubt, that was it, he
+reasoned. Tom's fright weakened every muscle in his body. He said to
+himself that if he had strength enough to get back to the spring he
+would stay there, and nothing should tempt him to run the risk of
+meeting Injun Joe again. He was careful to keep from Becky what it was
+he had seen. He told her he had only shouted "for luck."
+
+But hunger and wretchedness rise superior to fears in the long run.
+Another tedious wait at the spring and another long sleep brought
+changes. The children awoke tortured with a raging hunger. Tom believed
+that it must be Wednesday or Thursday or even Friday or Saturday, now,
+and that the search had been given over. He proposed to explore another
+passage. He felt willing to risk Injun Joe and all other terrors. But
+Becky was very weak. She had sunk into a dreary apathy and would not be
+roused. She said she would wait, now, where she was, and die--it would
+not be long. She told Tom to go with the kite-line and explore if he
+chose; but she implored him to come back every little while and speak
+to her; and she made him promise that when the awful time came, he
+would stay by her and hold her hand until all was over.
+
+Tom kissed her, with a choking sensation in his throat, and made a
+show of being confident of finding the searchers or an escape from the
+cave; then he took the kite-line in his hand and went groping down one
+of the passages on his hands and knees, distressed with hunger and sick
+with bodings of coming doom.
+
+
+
+CHAPTER XXXII
+
+TUESDAY afternoon came, and waned to the twilight. The village of St.
+Petersburg still mourned. The lost children had not been found. Public
+prayers had been offered up for them, and many and many a private
+prayer that had the petitioner's whole heart in it; but still no good
+news came from the cave. The majority of the searchers had given up the
+quest and gone back to their daily avocations, saying that it was plain
+the children could never be found. Mrs. Thatcher was very ill, and a
+great part of the time delirious. People said it was heartbreaking to
+hear her call her child, and raise her head and listen a whole minute
+at a time, then lay it wearily down again with a moan. Aunt Polly had
+drooped into a settled melancholy, and her gray hair had grown almost
+white. The village went to its rest on Tuesday night, sad and forlorn.
+
+Away in the middle of the night a wild peal burst from the village
+bells, and in a moment the streets were swarming with frantic half-clad
+people, who shouted, "Turn out! turn out! they're found! they're
+found!" Tin pans and horns were added to the din, the population massed
+itself and moved toward the river, met the children coming in an open
+carriage drawn by shouting citizens, thronged around it, joined its
+homeward march, and swept magnificently up the main street roaring
+huzzah after huzzah!
+
+The village was illuminated; nobody went to bed again; it was the
+greatest night the little town had ever seen. During the first half-hour
+a procession of villagers filed through Judge Thatcher's house, seized
+the saved ones and kissed them, squeezed Mrs. Thatcher's hand, tried to
+speak but couldn't--and drifted out raining tears all over the place.
+
+Aunt Polly's happiness was complete, and Mrs. Thatcher's nearly so. It
+would be complete, however, as soon as the messenger dispatched with
+the great news to the cave should get the word to her husband. Tom lay
+upon a sofa with an eager auditory about him and told the history of
+the wonderful adventure, putting in many striking additions to adorn it
+withal; and closed with a description of how he left Becky and went on
+an exploring expedition; how he followed two avenues as far as his
+kite-line would reach; how he followed a third to the fullest stretch of
+the kite-line, and was about to turn back when he glimpsed a far-off
+speck that looked like daylight; dropped the line and groped toward it,
+pushed his head and shoulders through a small hole, and saw the broad
+Mississippi rolling by! And if it had only happened to be night he would
+not have seen that speck of daylight and would not have explored that
+passage any more! He told how he went back for Becky and broke the good
+news and she told him not to fret her with such stuff, for she was
+tired, and knew she was going to die, and wanted to. He described how he
+labored with her and convinced her; and how she almost died for joy when
+she had groped to where she actually saw the blue speck of daylight; how
+he pushed his way out at the hole and then helped her out; how they sat
+there and cried for gladness; how some men came along in a skiff and Tom
+hailed them and told them their situation and their famished condition;
+how the men didn't believe the wild tale at first, "because," said they,
+"you are five miles down the river below the valley the cave is in"
+--then took them aboard, rowed to a house, gave them supper, made them
+rest till two or three hours after dark and then brought them home.
+
+Before day-dawn, Judge Thatcher and the handful of searchers with him
+were tracked out, in the cave, by the twine clews they had strung
+behind them, and informed of the great news.
+
+Three days and nights of toil and hunger in the cave were not to be
+shaken off at once, as Tom and Becky soon discovered. They were
+bedridden all of Wednesday and Thursday, and seemed to grow more and
+more tired and worn, all the time. Tom got about, a little, on
+Thursday, was down-town Friday, and nearly as whole as ever Saturday;
+but Becky did not leave her room until Sunday, and then she looked as
+if she had passed through a wasting illness.
+
+Tom learned of Huck's sickness and went to see him on Friday, but
+could not be admitted to the bedroom; neither could he on Saturday or
+Sunday. He was admitted daily after that, but was warned to keep still
+about his adventure and introduce no exciting topic. The Widow Douglas
+stayed by to see that he obeyed. At home Tom learned of the Cardiff
+Hill event; also that the "ragged man's" body had eventually been found
+in the river near the ferry-landing; he had been drowned while trying
+to escape, perhaps.
+
+About a fortnight after Tom's rescue from the cave, he started off to
+visit Huck, who had grown plenty strong enough, now, to hear exciting
+talk, and Tom had some that would interest him, he thought. Judge
+Thatcher's house was on Tom's way, and he stopped to see Becky. The
+Judge and some friends set Tom to talking, and some one asked him
+ironically if he wouldn't like to go to the cave again. Tom said he
+thought he wouldn't mind it. The Judge said:
+
+"Well, there are others just like you, Tom, I've not the least doubt.
+But we have taken care of that. Nobody will get lost in that cave any
+more."
+
+"Why?"
+
+"Because I had its big door sheathed with boiler iron two weeks ago,
+and triple-locked--and I've got the keys."
+
+Tom turned as white as a sheet.
+
+"What's the matter, boy! Here, run, somebody! Fetch a glass of water!"
+
+The water was brought and thrown into Tom's face.
+
+"Ah, now you're all right. What was the matter with you, Tom?"
+
+"Oh, Judge, Injun Joe's in the cave!"
+
+
+
+CHAPTER XXXIII
+
+WITHIN a few minutes the news had spread, and a dozen skiff-loads of
+men were on their way to McDougal's cave, and the ferryboat, well
+filled with passengers, soon followed. Tom Sawyer was in the skiff that
+bore Judge Thatcher.
+
+When the cave door was unlocked, a sorrowful sight presented itself in
+the dim twilight of the place. Injun Joe lay stretched upon the ground,
+dead, with his face close to the crack of the door, as if his longing
+eyes had been fixed, to the latest moment, upon the light and the cheer
+of the free world outside. Tom was touched, for he knew by his own
+experience how this wretch had suffered. His pity was moved, but
+nevertheless he felt an abounding sense of relief and security, now,
+which revealed to him in a degree which he had not fully appreciated
+before how vast a weight of dread had been lying upon him since the day
+he lifted his voice against this bloody-minded outcast.
+
+Injun Joe's bowie-knife lay close by, its blade broken in two. The
+great foundation-beam of the door had been chipped and hacked through,
+with tedious labor; useless labor, too, it was, for the native rock
+formed a sill outside it, and upon that stubborn material the knife had
+wrought no effect; the only damage done was to the knife itself. But if
+there had been no stony obstruction there the labor would have been
+useless still, for if the beam had been wholly cut away Injun Joe could
+not have squeezed his body under the door, and he knew it. So he had
+only hacked that place in order to be doing something--in order to pass
+the weary time--in order to employ his tortured faculties. Ordinarily
+one could find half a dozen bits of candle stuck around in the crevices
+of this vestibule, left there by tourists; but there were none now. The
+prisoner had searched them out and eaten them. He had also contrived to
+catch a few bats, and these, also, he had eaten, leaving only their
+claws. The poor unfortunate had starved to death. In one place, near at
+hand, a stalagmite had been slowly growing up from the ground for ages,
+builded by the water-drip from a stalactite overhead. The captive had
+broken off the stalagmite, and upon the stump had placed a stone,
+wherein he had scooped a shallow hollow to catch the precious drop
+that fell once in every three minutes with the dreary regularity of a
+clock-tick--a dessertspoonful once in four and twenty hours. That drop
+was falling when the Pyramids were new; when Troy fell; when the
+foundations of Rome were laid; when Christ was crucified; when the
+Conqueror created the British empire; when Columbus sailed; when the
+massacre at Lexington was "news." It is falling now; it will still be
+falling when all these things shall have sunk down the afternoon of
+history, and the twilight of tradition, and been swallowed up in the
+thick night of oblivion. Has everything a purpose and a mission? Did
+this drop fall patiently during five thousand years to be ready for
+this flitting human insect's need? and has it another important object
+to accomplish ten thousand years to come? No matter. It is many and
+many a year since the hapless half-breed scooped out the stone to catch
+the priceless drops, but to this day the tourist stares longest at that
+pathetic stone and that slow-dropping water when he comes to see the
+wonders of McDougal's cave. Injun Joe's cup stands first in the list of
+the cavern's marvels; even "Aladdin's Palace" cannot rival it.
+
+Injun Joe was buried near the mouth of the cave; and people flocked
+there in boats and wagons from the towns and from all the farms and
+hamlets for seven miles around; they brought their children, and all
+sorts of provisions, and confessed that they had had almost as
+satisfactory a time at the funeral as they could have had at the
+hanging.
+
+This funeral stopped the further growth of one thing--the petition to
+the governor for Injun Joe's pardon. The petition had been largely
+signed; many tearful and eloquent meetings had been held, and a
+committee of sappy women been appointed to go in deep mourning and wail
+around the governor, and implore him to be a merciful ass and trample
+his duty under foot. Injun Joe was believed to have killed five
+citizens of the village, but what of that? If he had been Satan himself
+there would have been plenty of weaklings ready to scribble their names
+to a pardon-petition, and drip a tear on it from their permanently
+impaired and leaky water-works.
+
+The morning after the funeral Tom took Huck to a private place to have
+an important talk. Huck had learned all about Tom's adventure from the
+Welshman and the Widow Douglas, by this time, but Tom said he reckoned
+there was one thing they had not told him; that thing was what he
+wanted to talk about now. Huck's face saddened. He said:
+
+"I know what it is. You got into No. 2 and never found anything but
+whiskey. Nobody told me it was you; but I just knowed it must 'a' ben
+you, soon as I heard 'bout that whiskey business; and I knowed you
+hadn't got the money becuz you'd 'a' got at me some way or other and
+told me even if you was mum to everybody else. Tom, something's always
+told me we'd never get holt of that swag."
+
+"Why, Huck, I never told on that tavern-keeper. YOU know his tavern
+was all right the Saturday I went to the picnic. Don't you remember you
+was to watch there that night?"
+
+"Oh yes! Why, it seems 'bout a year ago. It was that very night that I
+follered Injun Joe to the widder's."
+
+"YOU followed him?"
+
+"Yes--but you keep mum. I reckon Injun Joe's left friends behind him,
+and I don't want 'em souring on me and doing me mean tricks. If it
+hadn't ben for me he'd be down in Texas now, all right."
+
+Then Huck told his entire adventure in confidence to Tom, who had only
+heard of the Welshman's part of it before.
+
+"Well," said Huck, presently, coming back to the main question,
+"whoever nipped the whiskey in No. 2, nipped the money, too, I reckon
+--anyways it's a goner for us, Tom."
+
+"Huck, that money wasn't ever in No. 2!"
+
+"What!" Huck searched his comrade's face keenly. "Tom, have you got on
+the track of that money again?"
+
+"Huck, it's in the cave!"
+
+Huck's eyes blazed.
+
+"Say it again, Tom."
+
+"The money's in the cave!"
+
+"Tom--honest injun, now--is it fun, or earnest?"
+
+"Earnest, Huck--just as earnest as ever I was in my life. Will you go
+in there with me and help get it out?"
+
+"I bet I will! I will if it's where we can blaze our way to it and not
+get lost."
+
+"Huck, we can do that without the least little bit of trouble in the
+world."
+
+"Good as wheat! What makes you think the money's--"
+
+"Huck, you just wait till we get in there. If we don't find it I'll
+agree to give you my drum and every thing I've got in the world. I
+will, by jings."
+
+"All right--it's a whiz. When do you say?"
+
+"Right now, if you say it. Are you strong enough?"
+
+"Is it far in the cave? I ben on my pins a little, three or four days,
+now, but I can't walk more'n a mile, Tom--least I don't think I could."
+
+"It's about five mile into there the way anybody but me would go,
+Huck, but there's a mighty short cut that they don't anybody but me
+know about. Huck, I'll take you right to it in a skiff. I'll float the
+skiff down there, and I'll pull it back again all by myself. You
+needn't ever turn your hand over."
+
+"Less start right off, Tom."
+
+"All right. We want some bread and meat, and our pipes, and a little
+bag or two, and two or three kite-strings, and some of these
+new-fangled things they call lucifer matches. I tell you, many's
+the time I wished I had some when I was in there before."
+
+A trifle after noon the boys borrowed a small skiff from a citizen who
+was absent, and got under way at once. When they were several miles
+below "Cave Hollow," Tom said:
+
+"Now you see this bluff here looks all alike all the way down from the
+cave hollow--no houses, no wood-yards, bushes all alike. But do you see
+that white place up yonder where there's been a landslide? Well, that's
+one of my marks. We'll get ashore, now."
+
+They landed.
+
+"Now, Huck, where we're a-standing you could touch that hole I got out
+of with a fishing-pole. See if you can find it."
+
+Huck searched all the place about, and found nothing. Tom proudly
+marched into a thick clump of sumach bushes and said:
+
+"Here you are! Look at it, Huck; it's the snuggest hole in this
+country. You just keep mum about it. All along I've been wanting to be
+a robber, but I knew I'd got to have a thing like this, and where to
+run across it was the bother. We've got it now, and we'll keep it
+quiet, only we'll let Joe Harper and Ben Rogers in--because of course
+there's got to be a Gang, or else there wouldn't be any style about it.
+Tom Sawyer's Gang--it sounds splendid, don't it, Huck?"
+
+"Well, it just does, Tom. And who'll we rob?"
+
+"Oh, most anybody. Waylay people--that's mostly the way."
+
+"And kill them?"
+
+"No, not always. Hive them in the cave till they raise a ransom."
+
+"What's a ransom?"
+
+"Money. You make them raise all they can, off'n their friends; and
+after you've kept them a year, if it ain't raised then you kill them.
+That's the general way. Only you don't kill the women. You shut up the
+women, but you don't kill them. They're always beautiful and rich, and
+awfully scared. You take their watches and things, but you always take
+your hat off and talk polite. They ain't anybody as polite as robbers
+--you'll see that in any book. Well, the women get to loving you, and
+after they've been in the cave a week or two weeks they stop crying and
+after that you couldn't get them to leave. If you drove them out they'd
+turn right around and come back. It's so in all the books."
+
+"Why, it's real bully, Tom. I believe it's better'n to be a pirate."
+
+"Yes, it's better in some ways, because it's close to home and
+circuses and all that."
+
+By this time everything was ready and the boys entered the hole, Tom
+in the lead. They toiled their way to the farther end of the tunnel,
+then made their spliced kite-strings fast and moved on. A few steps
+brought them to the spring, and Tom felt a shudder quiver all through
+him. He showed Huck the fragment of candle-wick perched on a lump of
+clay against the wall, and described how he and Becky had watched the
+flame struggle and expire.
+
+The boys began to quiet down to whispers, now, for the stillness and
+gloom of the place oppressed their spirits. They went on, and presently
+entered and followed Tom's other corridor until they reached the
+"jumping-off place." The candles revealed the fact that it was not
+really a precipice, but only a steep clay hill twenty or thirty feet
+high. Tom whispered:
+
+"Now I'll show you something, Huck."
+
+He held his candle aloft and said:
+
+"Look as far around the corner as you can. Do you see that? There--on
+the big rock over yonder--done with candle-smoke."
+
+"Tom, it's a CROSS!"
+
+"NOW where's your Number Two? 'UNDER THE CROSS,' hey? Right yonder's
+where I saw Injun Joe poke up his candle, Huck!"
+
+Huck stared at the mystic sign awhile, and then said with a shaky voice:
+
+"Tom, less git out of here!"
+
+"What! and leave the treasure?"
+
+"Yes--leave it. Injun Joe's ghost is round about there, certain."
+
+"No it ain't, Huck, no it ain't. It would ha'nt the place where he
+died--away out at the mouth of the cave--five mile from here."
+
+"No, Tom, it wouldn't. It would hang round the money. I know the ways
+of ghosts, and so do you."
+
+Tom began to fear that Huck was right. Misgivings gathered in his
+mind. But presently an idea occurred to him--
+
+"Lookyhere, Huck, what fools we're making of ourselves! Injun Joe's
+ghost ain't a going to come around where there's a cross!"
+
+The point was well taken. It had its effect.
+
+"Tom, I didn't think of that. But that's so. It's luck for us, that
+cross is. I reckon we'll climb down there and have a hunt for that box."
+
+Tom went first, cutting rude steps in the clay hill as he descended.
+Huck followed. Four avenues opened out of the small cavern which the
+great rock stood in. The boys examined three of them with no result.
+They found a small recess in the one nearest the base of the rock, with
+a pallet of blankets spread down in it; also an old suspender, some
+bacon rind, and the well-gnawed bones of two or three fowls. But there
+was no money-box. The lads searched and researched this place, but in
+vain. Tom said:
+
+"He said UNDER the cross. Well, this comes nearest to being under the
+cross. It can't be under the rock itself, because that sets solid on
+the ground."
+
+They searched everywhere once more, and then sat down discouraged.
+Huck could suggest nothing. By-and-by Tom said:
+
+"Lookyhere, Huck, there's footprints and some candle-grease on the
+clay about one side of this rock, but not on the other sides. Now,
+what's that for? I bet you the money IS under the rock. I'm going to
+dig in the clay."
+
+"That ain't no bad notion, Tom!" said Huck with animation.
+
+Tom's "real Barlow" was out at once, and he had not dug four inches
+before he struck wood.
+
+"Hey, Huck!--you hear that?"
+
+Huck began to dig and scratch now. Some boards were soon uncovered and
+removed. They had concealed a natural chasm which led under the rock.
+Tom got into this and held his candle as far under the rock as he
+could, but said he could not see to the end of the rift. He proposed to
+explore. He stooped and passed under; the narrow way descended
+gradually. He followed its winding course, first to the right, then to
+the left, Huck at his heels. Tom turned a short curve, by-and-by, and
+exclaimed:
+
+"My goodness, Huck, lookyhere!"
+
+It was the treasure-box, sure enough, occupying a snug little cavern,
+along with an empty powder-keg, a couple of guns in leather cases, two
+or three pairs of old moccasins, a leather belt, and some other rubbish
+well soaked with the water-drip.
+
+"Got it at last!" said Huck, ploughing among the tarnished coins with
+his hand. "My, but we're rich, Tom!"
+
+"Huck, I always reckoned we'd get it. It's just too good to believe,
+but we HAVE got it, sure! Say--let's not fool around here. Let's snake
+it out. Lemme see if I can lift the box."
+
+It weighed about fifty pounds. Tom could lift it, after an awkward
+fashion, but could not carry it conveniently.
+
+"I thought so," he said; "THEY carried it like it was heavy, that day
+at the ha'nted house. I noticed that. I reckon I was right to think of
+fetching the little bags along."
+
+The money was soon in the bags and the boys took it up to the cross
+rock.
+
+"Now less fetch the guns and things," said Huck.
+
+"No, Huck--leave them there. They're just the tricks to have when we
+go to robbing. We'll keep them there all the time, and we'll hold our
+orgies there, too. It's an awful snug place for orgies."
+
+"What orgies?"
+
+"I dono. But robbers always have orgies, and of course we've got to
+have them, too. Come along, Huck, we've been in here a long time. It's
+getting late, I reckon. I'm hungry, too. We'll eat and smoke when we
+get to the skiff."
+
+They presently emerged into the clump of sumach bushes, looked warily
+out, found the coast clear, and were soon lunching and smoking in the
+skiff. As the sun dipped toward the horizon they pushed out and got
+under way. Tom skimmed up the shore through the long twilight, chatting
+cheerily with Huck, and landed shortly after dark.
+
+"Now, Huck," said Tom, "we'll hide the money in the loft of the
+widow's woodshed, and I'll come up in the morning and we'll count it
+and divide, and then we'll hunt up a place out in the woods for it
+where it will be safe. Just you lay quiet here and watch the stuff till
+I run and hook Benny Taylor's little wagon; I won't be gone a minute."
+
+He disappeared, and presently returned with the wagon, put the two
+small sacks into it, threw some old rags on top of them, and started
+off, dragging his cargo behind him. When the boys reached the
+Welshman's house, they stopped to rest. Just as they were about to move
+on, the Welshman stepped out and said:
+
+"Hallo, who's that?"
+
+"Huck and Tom Sawyer."
+
+"Good! Come along with me, boys, you are keeping everybody waiting.
+Here--hurry up, trot ahead--I'll haul the wagon for you. Why, it's not
+as light as it might be. Got bricks in it?--or old metal?"
+
+"Old metal," said Tom.
+
+"I judged so; the boys in this town will take more trouble and fool
+away more time hunting up six bits' worth of old iron to sell to the
+foundry than they would to make twice the money at regular work. But
+that's human nature--hurry along, hurry along!"
+
+The boys wanted to know what the hurry was about.
+
+"Never mind; you'll see, when we get to the Widow Douglas'."
+
+Huck said with some apprehension--for he was long used to being
+falsely accused:
+
+"Mr. Jones, we haven't been doing nothing."
+
+The Welshman laughed.
+
+"Well, I don't know, Huck, my boy. I don't know about that. Ain't you
+and the widow good friends?"
+
+"Yes. Well, she's ben good friends to me, anyway."
+
+"All right, then. What do you want to be afraid for?"
+
+This question was not entirely answered in Huck's slow mind before he
+found himself pushed, along with Tom, into Mrs. Douglas' drawing-room.
+Mr. Jones left the wagon near the door and followed.
+
+The place was grandly lighted, and everybody that was of any
+consequence in the village was there. The Thatchers were there, the
+Harpers, the Rogerses, Aunt Polly, Sid, Mary, the minister, the editor,
+and a great many more, and all dressed in their best. The widow
+received the boys as heartily as any one could well receive two such
+looking beings. They were covered with clay and candle-grease. Aunt
+Polly blushed crimson with humiliation, and frowned and shook her head
+at Tom. Nobody suffered half as much as the two boys did, however. Mr.
+Jones said:
+
+"Tom wasn't at home, yet, so I gave him up; but I stumbled on him and
+Huck right at my door, and so I just brought them along in a hurry."
+
+"And you did just right," said the widow. "Come with me, boys."
+
+She took them to a bedchamber and said:
+
+"Now wash and dress yourselves. Here are two new suits of clothes
+--shirts, socks, everything complete. They're Huck's--no, no thanks,
+Huck--Mr. Jones bought one and I the other. But they'll fit both of you.
+Get into them. We'll wait--come down when you are slicked up enough."
+
+Then she left.
+
+
+
+CHAPTER XXXIV
+
+HUCK said: "Tom, we can slope, if we can find a rope. The window ain't
+high from the ground."
+
+"Shucks! what do you want to slope for?"
+
+"Well, I ain't used to that kind of a crowd. I can't stand it. I ain't
+going down there, Tom."
+
+"Oh, bother! It ain't anything. I don't mind it a bit. I'll take care
+of you."
+
+Sid appeared.
+
+"Tom," said he, "auntie has been waiting for you all the afternoon.
+Mary got your Sunday clothes ready, and everybody's been fretting about
+you. Say--ain't this grease and clay, on your clothes?"
+
+"Now, Mr. Siddy, you jist 'tend to your own business. What's all this
+blow-out about, anyway?"
+
+"It's one of the widow's parties that she's always having. This time
+it's for the Welshman and his sons, on account of that scrape they
+helped her out of the other night. And say--I can tell you something,
+if you want to know."
+
+"Well, what?"
+
+"Why, old Mr. Jones is going to try to spring something on the people
+here to-night, but I overheard him tell auntie to-day about it, as a
+secret, but I reckon it's not much of a secret now. Everybody knows
+--the widow, too, for all she tries to let on she don't. Mr. Jones was
+bound Huck should be here--couldn't get along with his grand secret
+without Huck, you know!"
+
+"Secret about what, Sid?"
+
+"About Huck tracking the robbers to the widow's. I reckon Mr. Jones
+was going to make a grand time over his surprise, but I bet you it will
+drop pretty flat."
+
+Sid chuckled in a very contented and satisfied way.
+
+"Sid, was it you that told?"
+
+"Oh, never mind who it was. SOMEBODY told--that's enough."
+
+"Sid, there's only one person in this town mean enough to do that, and
+that's you. If you had been in Huck's place you'd 'a' sneaked down the
+hill and never told anybody on the robbers. You can't do any but mean
+things, and you can't bear to see anybody praised for doing good ones.
+There--no thanks, as the widow says"--and Tom cuffed Sid's ears and
+helped him to the door with several kicks. "Now go and tell auntie if
+you dare--and to-morrow you'll catch it!"
+
+Some minutes later the widow's guests were at the supper-table, and a
+dozen children were propped up at little side-tables in the same room,
+after the fashion of that country and that day. At the proper time Mr.
+Jones made his little speech, in which he thanked the widow for the
+honor she was doing himself and his sons, but said that there was
+another person whose modesty--
+
+And so forth and so on. He sprung his secret about Huck's share in the
+adventure in the finest dramatic manner he was master of, but the
+surprise it occasioned was largely counterfeit and not as clamorous and
+effusive as it might have been under happier circumstances. However,
+the widow made a pretty fair show of astonishment, and heaped so many
+compliments and so much gratitude upon Huck that he almost forgot the
+nearly intolerable discomfort of his new clothes in the entirely
+intolerable discomfort of being set up as a target for everybody's gaze
+and everybody's laudations.
+
+The widow said she meant to give Huck a home under her roof and have
+him educated; and that when she could spare the money she would start
+him in business in a modest way. Tom's chance was come. He said:
+
+"Huck don't need it. Huck's rich."
+
+Nothing but a heavy strain upon the good manners of the company kept
+back the due and proper complimentary laugh at this pleasant joke. But
+the silence was a little awkward. Tom broke it:
+
+"Huck's got money. Maybe you don't believe it, but he's got lots of
+it. Oh, you needn't smile--I reckon I can show you. You just wait a
+minute."
+
+Tom ran out of doors. The company looked at each other with a
+perplexed interest--and inquiringly at Huck, who was tongue-tied.
+
+"Sid, what ails Tom?" said Aunt Polly. "He--well, there ain't ever any
+making of that boy out. I never--"
+
+Tom entered, struggling with the weight of his sacks, and Aunt Polly
+did not finish her sentence. Tom poured the mass of yellow coin upon
+the table and said:
+
+"There--what did I tell you? Half of it's Huck's and half of it's mine!"
+
+The spectacle took the general breath away. All gazed, nobody spoke
+for a moment. Then there was a unanimous call for an explanation. Tom
+said he could furnish it, and he did. The tale was long, but brimful of
+interest. There was scarcely an interruption from any one to break the
+charm of its flow. When he had finished, Mr. Jones said:
+
+"I thought I had fixed up a little surprise for this occasion, but it
+don't amount to anything now. This one makes it sing mighty small, I'm
+willing to allow."
+
+The money was counted. The sum amounted to a little over twelve
+thousand dollars. It was more than any one present had ever seen at one
+time before, though several persons were there who were worth
+considerably more than that in property.
+
+
+
+CHAPTER XXXV
+
+THE reader may rest satisfied that Tom's and Huck's windfall made a
+mighty stir in the poor little village of St. Petersburg. So vast a
+sum, all in actual cash, seemed next to incredible. It was talked
+about, gloated over, glorified, until the reason of many of the
+citizens tottered under the strain of the unhealthy excitement. Every
+"haunted" house in St. Petersburg and the neighboring villages was
+dissected, plank by plank, and its foundations dug up and ransacked for
+hidden treasure--and not by boys, but men--pretty grave, unromantic
+men, too, some of them. Wherever Tom and Huck appeared they were
+courted, admired, stared at. The boys were not able to remember that
+their remarks had possessed weight before; but now their sayings were
+treasured and repeated; everything they did seemed somehow to be
+regarded as remarkable; they had evidently lost the power of doing and
+saying commonplace things; moreover, their past history was raked up
+and discovered to bear marks of conspicuous originality. The village
+paper published biographical sketches of the boys.
+
+The Widow Douglas put Huck's money out at six per cent., and Judge
+Thatcher did the same with Tom's at Aunt Polly's request. Each lad had
+an income, now, that was simply prodigious--a dollar for every week-day
+in the year and half of the Sundays. It was just what the minister got
+--no, it was what he was promised--he generally couldn't collect it. A
+dollar and a quarter a week would board, lodge, and school a boy in
+those old simple days--and clothe him and wash him, too, for that
+matter.
+
+Judge Thatcher had conceived a great opinion of Tom. He said that no
+commonplace boy would ever have got his daughter out of the cave. When
+Becky told her father, in strict confidence, how Tom had taken her
+whipping at school, the Judge was visibly moved; and when she pleaded
+grace for the mighty lie which Tom had told in order to shift that
+whipping from her shoulders to his own, the Judge said with a fine
+outburst that it was a noble, a generous, a magnanimous lie--a lie that
+was worthy to hold up its head and march down through history breast to
+breast with George Washington's lauded Truth about the hatchet! Becky
+thought her father had never looked so tall and so superb as when he
+walked the floor and stamped his foot and said that. She went straight
+off and told Tom about it.
+
+Judge Thatcher hoped to see Tom a great lawyer or a great soldier some
+day. He said he meant to look to it that Tom should be admitted to the
+National Military Academy and afterward trained in the best law school
+in the country, in order that he might be ready for either career or
+both.
+
+Huck Finn's wealth and the fact that he was now under the Widow
+Douglas' protection introduced him into society--no, dragged him into
+it, hurled him into it--and his sufferings were almost more than he
+could bear. The widow's servants kept him clean and neat, combed and
+brushed, and they bedded him nightly in unsympathetic sheets that had
+not one little spot or stain which he could press to his heart and know
+for a friend. He had to eat with a knife and fork; he had to use
+napkin, cup, and plate; he had to learn his book, he had to go to
+church; he had to talk so properly that speech was become insipid in
+his mouth; whithersoever he turned, the bars and shackles of
+civilization shut him in and bound him hand and foot.
+
+He bravely bore his miseries three weeks, and then one day turned up
+missing. For forty-eight hours the widow hunted for him everywhere in
+great distress. The public were profoundly concerned; they searched
+high and low, they dragged the river for his body. Early the third
+morning Tom Sawyer wisely went poking among some old empty hogsheads
+down behind the abandoned slaughter-house, and in one of them he found
+the refugee. Huck had slept there; he had just breakfasted upon some
+stolen odds and ends of food, and was lying off, now, in comfort, with
+his pipe. He was unkempt, uncombed, and clad in the same old ruin of
+rags that had made him picturesque in the days when he was free and
+happy. Tom routed him out, told him the trouble he had been causing,
+and urged him to go home. Huck's face lost its tranquil content, and
+took a melancholy cast. He said:
+
+"Don't talk about it, Tom. I've tried it, and it don't work; it don't
+work, Tom. It ain't for me; I ain't used to it. The widder's good to
+me, and friendly; but I can't stand them ways. She makes me get up just
+at the same time every morning; she makes me wash, they comb me all to
+thunder; she won't let me sleep in the woodshed; I got to wear them
+blamed clothes that just smothers me, Tom; they don't seem to any air
+git through 'em, somehow; and they're so rotten nice that I can't set
+down, nor lay down, nor roll around anywher's; I hain't slid on a
+cellar-door for--well, it 'pears to be years; I got to go to church and
+sweat and sweat--I hate them ornery sermons! I can't ketch a fly in
+there, I can't chaw. I got to wear shoes all Sunday. The widder eats by
+a bell; she goes to bed by a bell; she gits up by a bell--everything's
+so awful reg'lar a body can't stand it."
+
+"Well, everybody does that way, Huck."
+
+"Tom, it don't make no difference. I ain't everybody, and I can't
+STAND it. It's awful to be tied up so. And grub comes too easy--I don't
+take no interest in vittles, that way. I got to ask to go a-fishing; I
+got to ask to go in a-swimming--dern'd if I hain't got to ask to do
+everything. Well, I'd got to talk so nice it wasn't no comfort--I'd got
+to go up in the attic and rip out awhile, every day, to git a taste in
+my mouth, or I'd a died, Tom. The widder wouldn't let me smoke; she
+wouldn't let me yell, she wouldn't let me gape, nor stretch, nor
+scratch, before folks--" [Then with a spasm of special irritation and
+injury]--"And dad fetch it, she prayed all the time! I never see such a
+woman! I HAD to shove, Tom--I just had to. And besides, that school's
+going to open, and I'd a had to go to it--well, I wouldn't stand THAT,
+Tom. Looky here, Tom, being rich ain't what it's cracked up to be. It's
+just worry and worry, and sweat and sweat, and a-wishing you was dead
+all the time. Now these clothes suits me, and this bar'l suits me, and
+I ain't ever going to shake 'em any more. Tom, I wouldn't ever got into
+all this trouble if it hadn't 'a' ben for that money; now you just take
+my sheer of it along with your'n, and gimme a ten-center sometimes--not
+many times, becuz I don't give a dern for a thing 'thout it's tollable
+hard to git--and you go and beg off for me with the widder."
+
+"Oh, Huck, you know I can't do that. 'Tain't fair; and besides if
+you'll try this thing just a while longer you'll come to like it."
+
+"Like it! Yes--the way I'd like a hot stove if I was to set on it long
+enough. No, Tom, I won't be rich, and I won't live in them cussed
+smothery houses. I like the woods, and the river, and hogsheads, and
+I'll stick to 'em, too. Blame it all! just as we'd got guns, and a
+cave, and all just fixed to rob, here this dern foolishness has got to
+come up and spile it all!"
+
+Tom saw his opportunity--
+
+"Lookyhere, Huck, being rich ain't going to keep me back from turning
+robber."
+
+"No! Oh, good-licks; are you in real dead-wood earnest, Tom?"
+
+"Just as dead earnest as I'm sitting here. But Huck, we can't let you
+into the gang if you ain't respectable, you know."
+
+Huck's joy was quenched.
+
+"Can't let me in, Tom? Didn't you let me go for a pirate?"
+
+"Yes, but that's different. A robber is more high-toned than what a
+pirate is--as a general thing. In most countries they're awful high up
+in the nobility--dukes and such."
+
+"Now, Tom, hain't you always ben friendly to me? You wouldn't shet me
+out, would you, Tom? You wouldn't do that, now, WOULD you, Tom?"
+
+"Huck, I wouldn't want to, and I DON'T want to--but what would people
+say? Why, they'd say, 'Mph! Tom Sawyer's Gang! pretty low characters in
+it!' They'd mean you, Huck. You wouldn't like that, and I wouldn't."
+
+Huck was silent for some time, engaged in a mental struggle. Finally
+he said:
+
+"Well, I'll go back to the widder for a month and tackle it and see if
+I can come to stand it, if you'll let me b'long to the gang, Tom."
+
+"All right, Huck, it's a whiz! Come along, old chap, and I'll ask the
+widow to let up on you a little, Huck."
+
+"Will you, Tom--now will you? That's good. If she'll let up on some of
+the roughest things, I'll smoke private and cuss private, and crowd
+through or bust. When you going to start the gang and turn robbers?"
+
+"Oh, right off. We'll get the boys together and have the initiation
+to-night, maybe."
+
+"Have the which?"
+
+"Have the initiation."
+
+"What's that?"
+
+"It's to swear to stand by one another, and never tell the gang's
+secrets, even if you're chopped all to flinders, and kill anybody and
+all his family that hurts one of the gang."
+
+"That's gay--that's mighty gay, Tom, I tell you."
+
+"Well, I bet it is. And all that swearing's got to be done at
+midnight, in the lonesomest, awfulest place you can find--a ha'nted
+house is the best, but they're all ripped up now."
+
+"Well, midnight's good, anyway, Tom."
+
+"Yes, so it is. And you've got to swear on a coffin, and sign it with
+blood."
+
+"Now, that's something LIKE! Why, it's a million times bullier than
+pirating. I'll stick to the widder till I rot, Tom; and if I git to be
+a reg'lar ripper of a robber, and everybody talking 'bout it, I reckon
+she'll be proud she snaked me in out of the wet."
+
+
+
+CONCLUSION
+
+SO endeth this chronicle. It being strictly a history of a BOY, it
+must stop here; the story could not go much further without becoming
+the history of a MAN. When one writes a novel about grown people, he
+knows exactly where to stop--that is, with a marriage; but when he
+writes of juveniles, he must stop where he best can.
+
+Most of the characters that perform in this book still live, and are
+prosperous and happy. Some day it may seem worth while to take up the
+story of the younger ones again and see what sort of men and women they
+turned out to be; therefore it will be wisest not to reveal any of that
+part of their lives at present.
+
+
+
+
+
+End of the Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+by Mark Twain (Samuel Clemens)
+
+*** END OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
+
+***** This file should be named 74.txt or 74.zip *****
+This and all associated files of various formats will be found in:
+        http://www.gutenberg.net/7/74/
+
+Produced by David Widger. The previous edition was update by Jose
+Menendez.
+
+
+Updated editions will replace the previous one--the old editions
+will be renamed.
+
+Creating the works from public domain print editions means that no
+one owns a United States copyright in these works, so the Foundation
+(and you!) can copy and distribute it in the United States without
+permission and without paying copyright royalties.  Special rules,
+set forth in the General Terms of Use part of this license, apply to
+copying and distributing Project Gutenberg-tm electronic works to
+protect the PROJECT GUTENBERG-tm concept and trademark.  Project
+Gutenberg is a registered trademark, and may not be used if you
+charge for the eBooks, unless you receive specific permission.  If you
+do not charge anything for copies of this eBook, complying with the
+rules is very easy.  You may use this eBook for nearly any purpose
+such as creation of derivative works, reports, performances and
+research.  They may be modified and printed and given away--you may do
+practically ANYTHING with public domain eBooks.  Redistribution is
+subject to the trademark license, especially commercial
+redistribution.
+
+
+
+*** START: FULL LICENSE ***
+
+THE FULL PROJECT GUTENBERG LICENSE
+PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
+
+To protect the Project Gutenberg-tm mission of promoting the free
+distribution of electronic works, by using or distributing this work
+(or any other work associated in any way with the phrase "Project
+Gutenberg"), you agree to comply with all the terms of the Full Project
+Gutenberg-tm License (available with this file or online at
+http://gutenberg.net/license).
+
+
+Section 1.  General Terms of Use and Redistributing Project Gutenberg-tm
+electronic works
+
+1.A.  By reading or using any part of this Project Gutenberg-tm
+electronic work, you indicate that you have read, understand, agree to
+and accept all the terms of this license and intellectual property
+(trademark/copyright) agreement.  If you do not agree to abide by all
+the terms of this agreement, you must cease using and return or destroy
+all copies of Project Gutenberg-tm electronic works in your possession.
+If you paid a fee for obtaining a copy of or access to a Project
+Gutenberg-tm electronic work and you do not agree to be bound by the
+terms of this agreement, you may obtain a refund from the person or
+entity to whom you paid the fee as set forth in paragraph 1.E.8.
+
+1.B.  "Project Gutenberg" is a registered trademark.  It may only be
+used on or associated in any way with an electronic work by people who
+agree to be bound by the terms of this agreement.  There are a few
+things that you can do with most Project Gutenberg-tm electronic works
+even without complying with the full terms of this agreement.  See
+paragraph 1.C below.  There are a lot of things you can do with Project
+Gutenberg-tm electronic works if you follow the terms of this agreement
+and help preserve free future access to Project Gutenberg-tm electronic
+works.  See paragraph 1.E below.
+
+1.C.  The Project Gutenberg Literary Archive Foundation ("the Foundation"
+or PGLAF), owns a compilation copyright in the collection of Project
+Gutenberg-tm electronic works.  Nearly all the individual works in the
+collection are in the public domain in the United States.  If an
+individual work is in the public domain in the United States and you are
+located in the United States, we do not claim a right to prevent you from
+copying, distributing, performing, displaying or creating derivative
+works based on the work as long as all references to Project Gutenberg
+are removed.  Of course, we hope that you will support the Project
+Gutenberg-tm mission of promoting free access to electronic works by
+freely sharing Project Gutenberg-tm works in compliance with the terms of
+this agreement for keeping the Project Gutenberg-tm name associated with
+the work.  You can easily comply with the terms of this agreement by
+keeping this work in the same format with its attached full Project
+Gutenberg-tm License when you share it without charge with others.
+
+1.D.  The copyright laws of the place where you are located also govern
+what you can do with this work.  Copyright laws in most countries are in
+a constant state of change.  If you are outside the United States, check
+the laws of your country in addition to the terms of this agreement
+before downloading, copying, displaying, performing, distributing or
+creating derivative works based on this work or any other Project
+Gutenberg-tm work.  The Foundation makes no representations concerning
+the copyright status of any work in any country outside the United
+States.
+
+1.E.  Unless you have removed all references to Project Gutenberg:
+
+1.E.1.  The following sentence, with active links to, or other immediate
+access to, the full Project Gutenberg-tm License must appear prominently
+whenever any copy of a Project Gutenberg-tm work (any work on which the
+phrase "Project Gutenberg" appears, or with which the phrase "Project
+Gutenberg" is associated) is accessed, displayed, performed, viewed,
+copied or distributed:
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever.  You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.net
+
+1.E.2.  If an individual Project Gutenberg-tm electronic work is derived
+from the public domain (does not contain a notice indicating that it is
+posted with permission of the copyright holder), the work can be copied
+and distributed to anyone in the United States without paying any fees
+or charges.  If you are redistributing or providing access to a work
+with the phrase "Project Gutenberg" associated with or appearing on the
+work, you must comply either with the requirements of paragraphs 1.E.1
+through 1.E.7 or obtain permission for the use of the work and the
+Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or
+1.E.9.
+
+1.E.3.  If an individual Project Gutenberg-tm electronic work is posted
+with the permission of the copyright holder, your use and distribution
+must comply with both paragraphs 1.E.1 through 1.E.7 and any additional
+terms imposed by the copyright holder.  Additional terms will be linked
+to the Project Gutenberg-tm License for all works posted with the
+permission of the copyright holder found at the beginning of this work.
+
+1.E.4.  Do not unlink or detach or remove the full Project Gutenberg-tm
+License terms from this work, or any files containing a part of this
+work or any other work associated with Project Gutenberg-tm.
+
+1.E.5.  Do not copy, display, perform, distribute or redistribute this
+electronic work, or any part of this electronic work, without
+prominently displaying the sentence set forth in paragraph 1.E.1 with
+active links or immediate access to the full terms of the Project
+Gutenberg-tm License.
+
+1.E.6.  You may convert to and distribute this work in any binary,
+compressed, marked up, nonproprietary or proprietary form, including any
+word processing or hypertext form.  However, if you provide access to or
+distribute copies of a Project Gutenberg-tm work in a format other than
+"Plain Vanilla ASCII" or other format used in the official version
+posted on the official Project Gutenberg-tm web site (www.gutenberg.net),
+you must, at no additional cost, fee or expense to the user, provide a
+copy, a means of exporting a copy, or a means of obtaining a copy upon
+request, of the work in its original "Plain Vanilla ASCII" or other
+form.  Any alternate format must include the full Project Gutenberg-tm
+License as specified in paragraph 1.E.1.
+
+1.E.7.  Do not charge a fee for access to, viewing, displaying,
+performing, copying or distributing any Project Gutenberg-tm works
+unless you comply with paragraph 1.E.8 or 1.E.9.
+
+1.E.8.  You may charge a reasonable fee for copies of or providing
+access to or distributing Project Gutenberg-tm electronic works provided
+that
+
+- You pay a royalty fee of 20% of the gross profits you derive from
+     the use of Project Gutenberg-tm works calculated using the method
+     you already use to calculate your applicable taxes.  The fee is
+     owed to the owner of the Project Gutenberg-tm trademark, but he
+     has agreed to donate royalties under this paragraph to the
+     Project Gutenberg Literary Archive Foundation.  Royalty payments
+     must be paid within 60 days following each date on which you
+     prepare (or are legally required to prepare) your periodic tax
+     returns.  Royalty payments should be clearly marked as such and
+     sent to the Project Gutenberg Literary Archive Foundation at the
+     address specified in Section 4, "Information about donations to
+     the Project Gutenberg Literary Archive Foundation."
+
+- You provide a full refund of any money paid by a user who notifies
+     you in writing (or by e-mail) within 30 days of receipt that s/he
+     does not agree to the terms of the full Project Gutenberg-tm
+     License.  You must require such a user to return or
+     destroy all copies of the works possessed in a physical medium
+     and discontinue all use of and all access to other copies of
+     Project Gutenberg-tm works.
+
+- You provide, in accordance with paragraph 1.F.3, a full refund of any
+     money paid for a work or a replacement copy, if a defect in the
+     electronic work is discovered and reported to you within 90 days
+     of receipt of the work.
+
+- You comply with all other terms of this agreement for free
+     distribution of Project Gutenberg-tm works.
+
+1.E.9.  If you wish to charge a fee or distribute a Project Gutenberg-tm
+electronic work or group of works on different terms than are set
+forth in this agreement, you must obtain permission in writing from
+both the Project Gutenberg Literary Archive Foundation and Michael
+Hart, the owner of the Project Gutenberg-tm trademark.  Contact the
+Foundation as set forth in Section 3 below.
+
+1.F.
+
+1.F.1.  Project Gutenberg volunteers and employees expend considerable
+effort to identify, do copyright research on, transcribe and proofread
+public domain works in creating the Project Gutenberg-tm
+collection.  Despite these efforts, Project Gutenberg-tm electronic
+works, and the medium on which they may be stored, may contain
+"Defects," such as, but not limited to, incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other intellectual
+property infringement, a defective or damaged disk or other medium, a
+computer virus, or computer codes that damage or cannot be read by
+your equipment.
+
+1.F.2.  LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right
+of Replacement or Refund" described in paragraph 1.F.3, the Project
+Gutenberg Literary Archive Foundation, the owner of the Project
+Gutenberg-tm trademark, and any other party distributing a Project
+Gutenberg-tm electronic work under this agreement, disclaim all
+liability to you for damages, costs and expenses, including legal
+fees.  YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
+LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE
+PROVIDED IN PARAGRAPH F3.  YOU AGREE THAT THE FOUNDATION, THE
+TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE
+LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
+INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+1.F.3.  LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a
+defect in this electronic work within 90 days of receiving it, you can
+receive a refund of the money (if any) you paid for it by sending a
+written explanation to the person you received the work from.  If you
+received the work on a physical medium, you must return the medium with
+your written explanation.  The person or entity that provided you with
+the defective work may elect to provide a replacement copy in lieu of a
+refund.  If you received the work electronically, the person or entity
+providing it to you may choose to give you a second opportunity to
+receive the work electronically in lieu of a refund.  If the second copy
+is also defective, you may demand a refund in writing without further
+opportunities to fix the problem.
+
+1.F.4.  Except for the limited right of replacement or refund set forth
+in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE.
+
+1.F.5.  Some states do not allow disclaimers of certain implied
+warranties or the exclusion or limitation of certain types of damages.
+If any disclaimer or limitation set forth in this agreement violates the
+law of the state applicable to this agreement, the agreement shall be
+interpreted to make the maximum disclaimer or limitation permitted by
+the applicable state law.  The invalidity or unenforceability of any
+provision of this agreement shall not void the remaining provisions.
+
+1.F.6.  INDEMNITY - You agree to indemnify and hold the Foundation, the
+trademark owner, any agent or employee of the Foundation, anyone
+providing copies of Project Gutenberg-tm electronic works in accordance
+with this agreement, and any volunteers associated with the production,
+promotion and distribution of Project Gutenberg-tm electronic works,
+harmless from all liability, costs and expenses, including legal fees,
+that arise directly or indirectly from any of the following which you do
+or cause to occur: (a) distribution of this or any Project Gutenberg-tm
+work, (b) alteration, modification, or additions or deletions to any
+Project Gutenberg-tm work, and (c) any Defect you cause.
+
+
+Section  2.  Information about the Mission of Project Gutenberg-tm
+
+Project Gutenberg-tm is synonymous with the free distribution of
+electronic works in formats readable by the widest variety of computers
+including obsolete, old, middle-aged and new computers.  It exists
+because of the efforts of hundreds of volunteers and donations from
+people in all walks of life.
+
+Volunteers and financial support to provide volunteers with the
+assistance they need, is critical to reaching Project Gutenberg-tm's
+goals and ensuring that the Project Gutenberg-tm collection will
+remain freely available for generations to come.  In 2001, the Project
+Gutenberg Literary Archive Foundation was created to provide a secure
+and permanent future for Project Gutenberg-tm and future generations.
+To learn more about the Project Gutenberg Literary Archive Foundation
+and how your efforts and donations can help, see Sections 3 and 4
+and the Foundation web page at http://www.pglaf.org.
+
+
+Section 3.  Information about the Project Gutenberg Literary Archive
+Foundation
+
+The Project Gutenberg Literary Archive Foundation is a non profit
+501(c)(3) educational corporation organized under the laws of the
+state of Mississippi and granted tax exempt status by the Internal
+Revenue Service.  The Foundation's EIN or federal tax identification
+number is 64-6221541.  Its 501(c)(3) letter is posted at
+http://pglaf.org/fundraising.  Contributions to the Project Gutenberg
+Literary Archive Foundation are tax deductible to the full extent
+permitted by U.S. federal laws and your state's laws.
+
+The Foundation's principal office is located at 4557 Melan Dr. S.
+Fairbanks, AK, 99712., but its volunteers and employees are scattered
+throughout numerous locations.  Its business office is located at
+809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email
+business at pglaf.org.  Email contact links and up to date contact
+information can be found at the Foundation's web site and official
+page at http://pglaf.org
+
+For additional contact information:
+     Dr. Gregory B. Newby
+     Chief Executive and Director
+     gbnewby at pglaf.org
+
+
+Section 4.  Information about Donations to the Project Gutenberg
+Literary Archive Foundation
+
+Project Gutenberg-tm depends upon and cannot survive without wide
+spread public support and donations to carry out its mission of
+increasing the number of public domain and licensed works that can be
+freely distributed in machine readable form accessible by the widest
+array of equipment including outdated equipment.  Many small donations
+($1 to $5,000) are particularly important to maintaining tax exempt
+status with the IRS.
+
+The Foundation is committed to complying with the laws regulating
+charities and charitable donations in all 50 states of the United
+States.  Compliance requirements are not uniform and it takes a
+considerable effort, much paperwork and many fees to meet and keep up
+with these requirements.  We do not solicit donations in locations
+where we have not received written confirmation of compliance.  To
+SEND DONATIONS or determine the status of compliance for any
+particular state visit http://pglaf.org
+
+While we cannot and do not solicit contributions from states where we
+have not met the solicitation requirements, we know of no prohibition
+against accepting unsolicited donations from donors in such states who
+approach us with offers to donate.
+
+International donations are gratefully accepted, but we cannot make
+any statements concerning tax treatment of donations received from
+outside the United States.  U.S. laws alone swamp our small staff.
+
+Please check the Project Gutenberg Web pages for current donation
+methods and addresses.  Donations are accepted in a number of other
+ways including including checks, online payments and credit card
+donations.  To donate, please visit: http://pglaf.org/donate
+
+
+Section 5.  General Information About Project Gutenberg-tm electronic
+works.
+
+Professor Michael S. Hart is the originator of the Project Gutenberg-tm
+concept of a library of electronic works that could be freely shared
+with anyone.  For thirty years, he produced and distributed Project
+Gutenberg-tm eBooks with only a loose network of volunteer support.
+
+
+Project Gutenberg-tm eBooks are often created from several printed
+editions, all of which are confirmed as Public Domain in the U.S.
+unless a copyright notice is included.  Thus, we do not necessarily
+keep eBooks in compliance with any particular paper edition.
+
+
+Most people start at our Web site which has the main PG search facility:
+
+     http://www.gutenberg.net
+
+This Web site includes information about Project Gutenberg-tm,
+including how to make donations to the Project Gutenberg Literary
+Archive Foundation, how to help produce our new eBooks, and how to
+subscribe to our email newsletter to hear about new eBooks.
diff --git a/src/pkg/compress/zlib/reader.go b/src/pkg/compress/zlib/reader.go
index 78dabdf..4638a65 100644
--- a/src/pkg/compress/zlib/reader.go
+++ b/src/pkg/compress/zlib/reader.go
@@ -26,36 +26,36 @@ package zlib
 import (
 	"bufio"
 	"compress/flate"
+	"errors"
 	"hash"
 	"hash/adler32"
 	"io"
-	"os"
 )
 
 const zlibDeflate = 8
 
-var ChecksumError = os.NewError("zlib checksum error")
-var HeaderError = os.NewError("invalid zlib header")
-var DictionaryError = os.NewError("invalid zlib dictionary")
+var ErrChecksum = errors.New("zlib checksum error")
+var ErrHeader = errors.New("invalid zlib header")
+var ErrDictionary = errors.New("invalid zlib dictionary")
 
 type reader struct {
 	r            flate.Reader
 	decompressor io.ReadCloser
 	digest       hash.Hash32
-	err          os.Error
+	err          error
 	scratch      [4]byte
 }
 
 // NewReader creates a new io.ReadCloser that satisfies reads by decompressing data read from r.
 // The implementation buffers input and may read more data than necessary from r.
 // It is the caller's responsibility to call Close on the ReadCloser when done.
-func NewReader(r io.Reader) (io.ReadCloser, os.Error) {
+func NewReader(r io.Reader) (io.ReadCloser, error) {
 	return NewReaderDict(r, nil)
 }
 
 // NewReaderDict is like NewReader but uses a preset dictionary.
 // NewReaderDict ignores the dictionary if the compressed data does not refer to it.
-func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, os.Error) {
+func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
 	z := new(reader)
 	if fr, ok := r.(flate.Reader); ok {
 		z.r = fr
@@ -68,7 +68,7 @@ func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, os.Error) {
 	}
 	h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
 	if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
-		return nil, HeaderError
+		return nil, ErrHeader
 	}
 	if z.scratch[1]&0x20 != 0 {
 		_, err = io.ReadFull(z.r, z.scratch[0:4])
@@ -77,7 +77,7 @@ func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, os.Error) {
 		}
 		checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
 		if checksum != adler32.Checksum(dict) {
-			return nil, DictionaryError
+			return nil, ErrDictionary
 		}
 		z.decompressor = flate.NewReaderDict(z.r, dict)
 	} else {
@@ -87,7 +87,7 @@ func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, os.Error) {
 	return z, nil
 }
 
-func (z *reader) Read(p []byte) (n int, err os.Error) {
+func (z *reader) Read(p []byte) (n int, err error) {
 	if z.err != nil {
 		return 0, z.err
 	}
@@ -97,7 +97,7 @@ func (z *reader) Read(p []byte) (n int, err os.Error) {
 
 	n, err = z.decompressor.Read(p)
 	z.digest.Write(p[0:n])
-	if n != 0 || err != os.EOF {
+	if n != 0 || err != io.EOF {
 		z.err = err
 		return
 	}
@@ -110,14 +110,14 @@ func (z *reader) Read(p []byte) (n int, err os.Error) {
 	// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
 	checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
 	if checksum != z.digest.Sum32() {
-		z.err = ChecksumError
+		z.err = ErrChecksum
 		return 0, z.err
 	}
 	return
 }
 
 // Calling Close does not close the wrapped io.Reader originally passed to NewReader.
-func (z *reader) Close() os.Error {
+func (z *reader) Close() error {
 	if z.err != nil {
 		return z.err
 	}
diff --git a/src/pkg/compress/zlib/reader_test.go b/src/pkg/compress/zlib/reader_test.go
index 195db44..3b02a08 100644
--- a/src/pkg/compress/zlib/reader_test.go
+++ b/src/pkg/compress/zlib/reader_test.go
@@ -7,7 +7,6 @@ package zlib
 import (
 	"bytes"
 	"io"
-	"os"
 	"testing"
 )
 
@@ -16,7 +15,7 @@ type zlibTest struct {
 	raw        string
 	compressed []byte
 	dict       []byte
-	err        os.Error
+	err        error
 }
 
 // Compare-to-golden test data was generated by the ZLIB example program at
@@ -46,14 +45,14 @@ var zlibTests = []zlibTest{
 		"",
 		[]byte{0x78, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
 		nil,
-		HeaderError,
+		ErrHeader,
 	},
 	{
 		"bad checksum",
 		"",
 		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff},
 		nil,
-		ChecksumError,
+		ErrChecksum,
 	},
 	{
 		"not enough data",
@@ -96,7 +95,7 @@ var zlibTests = []zlibTest{
 		[]byte{
 			0x48, 0x65, 0x6c, 0x6c,
 		},
-		DictionaryError,
+		ErrDictionary,
 	},
 }
 
diff --git a/src/pkg/compress/zlib/writer.go b/src/pkg/compress/zlib/writer.go
index 8f86e9c..bbff637 100644
--- a/src/pkg/compress/zlib/writer.go
+++ b/src/pkg/compress/zlib/writer.go
@@ -6,10 +6,10 @@ package zlib
 
 import (
 	"compress/flate"
+	"errors"
 	"hash"
 	"hash/adler32"
 	"io"
-	"os"
 )
 
 // These constants are copied from the flate package, so that code that imports
@@ -27,17 +27,17 @@ type Writer struct {
 	w          io.Writer
 	compressor *flate.Writer
 	digest     hash.Hash32
-	err        os.Error
+	err        error
 	scratch    [4]byte
 }
 
 // NewWriter calls NewWriterLevel with the default compression level.
-func NewWriter(w io.Writer) (*Writer, os.Error) {
+func NewWriter(w io.Writer) (*Writer, error) {
 	return NewWriterLevel(w, DefaultCompression)
 }
 
 // NewWriterLevel calls NewWriterDict with no dictionary.
-func NewWriterLevel(w io.Writer, level int) (*Writer, os.Error) {
+func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
 	return NewWriterDict(w, level, nil)
 }
 
@@ -46,7 +46,7 @@ func NewWriterLevel(w io.Writer, level int) (*Writer, os.Error) {
 // level is the compression level, which can be DefaultCompression, NoCompression,
 // or any integer value between BestSpeed and BestCompression (inclusive).
 // dict is the preset dictionary to compress with, or nil to use no dictionary.
-func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, os.Error) {
+func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
 	z := new(Writer)
 	// ZLIB has a two-byte header (as documented in RFC 1950).
 	// The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
@@ -66,7 +66,7 @@ func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, os.Error) {
 	case 7, 8, 9:
 		z.scratch[1] = 3 << 6
 	default:
-		return nil, os.NewError("level out of range")
+		return nil, errors.New("level out of range")
 	}
 	if dict != nil {
 		z.scratch[1] |= 1 << 5
@@ -94,7 +94,7 @@ func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, os.Error) {
 	return z, nil
 }
 
-func (z *Writer) Write(p []byte) (n int, err os.Error) {
+func (z *Writer) Write(p []byte) (n int, err error) {
 	if z.err != nil {
 		return 0, z.err
 	}
@@ -111,7 +111,7 @@ func (z *Writer) Write(p []byte) (n int, err os.Error) {
 }
 
 // Flush flushes the underlying compressor.
-func (z *Writer) Flush() os.Error {
+func (z *Writer) Flush() error {
 	if z.err != nil {
 		return z.err
 	}
@@ -120,7 +120,7 @@ func (z *Writer) Flush() os.Error {
 }
 
 // Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
-func (z *Writer) Close() os.Error {
+func (z *Writer) Close() error {
 	if z.err != nil {
 		return z.err
 	}
diff --git a/src/pkg/compress/zlib/writer_test.go b/src/pkg/compress/zlib/writer_test.go
index 32f05ab..a71894d 100644
--- a/src/pkg/compress/zlib/writer_test.go
+++ b/src/pkg/compress/zlib/writer_test.go
@@ -59,10 +59,6 @@ func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
 		}
 		defer zlibw.Close()
 		_, err = zlibw.Write(b0)
-		if err == os.EPIPE {
-			// Fail, but do not report the error, as some other (presumably reported) error broke the pipe.
-			return
-		}
 		if err != nil {
 			t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
 			return
diff --git a/src/pkg/container/heap/heap.go b/src/pkg/container/heap/heap.go
index 2dfe5b4..7af636b 100644
--- a/src/pkg/container/heap/heap.go
+++ b/src/pkg/container/heap/heap.go
@@ -3,7 +3,13 @@
 // license that can be found in the LICENSE file.
 
 // Package heap provides heap operations for any type that implements
-// heap.Interface.
+// heap.Interface. A heap is a tree with the property that each node is the
+// highest-valued node in its subtree.
+//
+// A heap is a common way to impement a priority queue. To build a priority
+// queue, implement the Heap interface with the (negative) priority as the
+// ordering for the Less method, so Push adds items while Pop removes the
+// highest-priority item from the queue.
 //
 package heap
 
@@ -11,14 +17,17 @@ import "sort"
 
 // Any type that implements heap.Interface may be used as a
 // min-heap with the following invariants (established after
-// Init has been called):
+// Init has been called or if the data is empty or sorted):
 //
 //	!h.Less(j, i) for 0 <= i < h.Len() and j = 2*i+1 or 2*i+2 and j < h.Len()
 //
+// Note that Push and Pop in this interface are for package heap's
+// implementation to call.  To add and remove things from the heap,
+// use heap.Push and heap.Pop.
 type Interface interface {
 	sort.Interface
-	Push(x interface{})
-	Pop() interface{}
+	Push(x interface{}) // add x as element Len()
+	Pop() interface{}   // remove and return element Len() - 1.
 }
 
 // A heap must be initialized before any of the heap operations
diff --git a/src/pkg/container/heap/heap_test.go b/src/pkg/container/heap/heap_test.go
index 6625e3a..cb31ef6 100644
--- a/src/pkg/container/heap/heap_test.go
+++ b/src/pkg/container/heap/heap_test.go
@@ -5,8 +5,8 @@
 package heap_test
 
 import (
-	"testing"
 	. "container/heap"
+	"testing"
 )
 
 type myHeap []int
diff --git a/src/pkg/container/vector/Makefile b/src/pkg/container/vector/Makefile
deleted file mode 100644
index f6b5015..0000000
--- a/src/pkg/container/vector/Makefile
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=container/vector
-GOFILES=\
-	defs.go\
-	intvector.go\
-	stringvector.go\
-	vector.go\
-
-include ../../../Make.pkg
-
-generate: vector.go vector_test.go
-	< vector.go cat\
-	| gofmt -r='Vector -> IntVector'\
-	| gofmt -r='interface{} -> int'\
-	> intvector.go\
-	
-	< vector.go cat\
-	| gofmt -r='Vector -> StringVector'\
-	| gofmt -r='interface{} -> string'\
-	> stringvector.go\
-	
-	< vector_test.go cat\
-	| gofmt -r='Vector -> IntVector'\
-	| gofmt -r='zero -> intzero'\
-	| gofmt -r='elem2Value -> elem2IntValue'\
-	| gofmt -r='intf2Value -> intf2IntValue'\
-	| gofmt -r='int2Value -> int2IntValue'\
-	| gofmt -r='TestZeroLen -> TestIntZeroLen'\
-	| gofmt -r='TestResize -> TestIntResize'\
-	| gofmt -r='TestResize2 -> TestIntResize2'\
-	| gofmt -r='checkZero -> checkIntZero'\
-	| gofmt -r='TestTrailingElements -> TestIntTrailingElements'\
-	| gofmt -r='TestAccess -> TestIntAccess'\
-	| gofmt -r='TestInsertDeleteClear -> TestIntInsertDeleteClear'\
-	| gofmt -r='verify_slice -> verify_sliceInt'\
-	| gofmt -r='verify_pattern -> verify_patternInt'\
-	| gofmt -r='make_vector -> make_vectorInt'\
-	| gofmt -r='TestInsertVector -> TestIntInsertVector'\
-	| gofmt -r='TestDo -> TestIntDo'\
-	| gofmt -r='TestVectorCopy -> TestIntVectorCopy'\
-	| gofmt -r='interface{} -> int'\
-	> intvector_test.go\
-	
-	< vector_test.go cat\
-	| gofmt -r='Vector -> StringVector'\
-	| gofmt -r='zero -> strzero'\
-	| gofmt -r='int2Value -> int2StrValue'\
-	| gofmt -r='intf2Value -> intf2StrValue'\
-	| gofmt -r='elem2Value -> elem2StrValue'\
-	| gofmt -r='TestZeroLen -> TestStrZeroLen'\
-	| gofmt -r='TestResize -> TestStrResize'\
-	| gofmt -r='TestResize2 -> TestStrResize2'\
-	| gofmt -r='checkZero -> checkStrZero'\
-	| gofmt -r='TestTrailingElements -> TestStrTrailingElements'\
-	| gofmt -r='TestAccess -> TestStrAccess'\
-	| gofmt -r='TestInsertDeleteClear -> TestStrInsertDeleteClear'\
-	| gofmt -r='verify_slice -> verify_sliceStr'\
-	| gofmt -r='verify_pattern -> verify_patternStr'\
-	| gofmt -r='make_vector -> make_vectorStr'\
-	| gofmt -r='TestInsertVector -> TestStrInsertVector'\
-	| gofmt -r='TestDo -> TestStrDo'\
-	| gofmt -r='TestVectorCopy -> TestStrVectorCopy'\
-	| gofmt -r='interface{} -> string'\
-	> stringvector_test.go
diff --git a/src/pkg/container/vector/defs.go b/src/pkg/container/vector/defs.go
deleted file mode 100644
index 6d6b2ac..0000000
--- a/src/pkg/container/vector/defs.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package vector implements containers for managing sequences of elements.
-// Vectors grow and shrink dynamically as necessary.
-package vector
-
-// Vector is a container for numbered sequences of elements of type interface{}.
-// A vector's length and capacity adjusts automatically as necessary.
-// The zero value for Vector is an empty vector ready to use.
-type Vector []interface{}
-
-// IntVector is a container for numbered sequences of elements of type int.
-// A vector's length and capacity adjusts automatically as necessary.
-// The zero value for IntVector is an empty vector ready to use.
-type IntVector []int
-
-// StringVector is a container for numbered sequences of elements of type string.
-// A vector's length and capacity adjusts automatically as necessary.
-// The zero value for StringVector is an empty vector ready to use.
-type StringVector []string
-
-// Initial underlying array size
-const initialSize = 8
-
-// Partial sort.Interface support
-
-// LessInterface provides partial support of the sort.Interface.
-type LessInterface interface {
-	Less(y interface{}) bool
-}
-
-// Less returns a boolean denoting whether the i'th element is less than the j'th element.
-func (p *Vector) Less(i, j int) bool { return (*p)[i].(LessInterface).Less((*p)[j]) }
-
-// sort.Interface support
-
-// Less returns a boolean denoting whether the i'th element is less than the j'th element.
-func (p *IntVector) Less(i, j int) bool { return (*p)[i] < (*p)[j] }
-
-// Less returns a boolean denoting whether the i'th element is less than the j'th element.
-func (p *StringVector) Less(i, j int) bool { return (*p)[i] < (*p)[j] }
diff --git a/src/pkg/container/vector/intvector.go b/src/pkg/container/vector/intvector.go
deleted file mode 100644
index aa88cfe..0000000
--- a/src/pkg/container/vector/intvector.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector.go, it was generated
-// automatically from vector.go - DO NOT EDIT in that case!
-
-package vector
-
-func (p *IntVector) realloc(length, capacity int) (b []int) {
-	if capacity < initialSize {
-		capacity = initialSize
-	}
-	if capacity < length {
-		capacity = length
-	}
-	b = make(IntVector, length, capacity)
-	copy(b, *p)
-	*p = b
-	return
-}
-
-// Insert n elements at position i.
-func (p *IntVector) Expand(i, n int) {
-	a := *p
-
-	// make sure we have enough space
-	len0 := len(a)
-	len1 := len0 + n
-	if len1 <= cap(a) {
-		// enough space - just expand
-		a = a[0:len1]
-	} else {
-		// not enough space - double capacity
-		capb := cap(a) * 2
-		if capb < len1 {
-			// still not enough - use required length
-			capb = len1
-		}
-		// capb >= len1
-		a = p.realloc(len1, capb)
-	}
-
-	// make a hole
-	for j := len0 - 1; j >= i; j-- {
-		a[j+n] = a[j]
-	}
-
-	*p = a
-}
-
-// Insert n elements at the end of a vector.
-func (p *IntVector) Extend(n int) { p.Expand(len(*p), n) }
-
-// Resize changes the length and capacity of a vector.
-// If the new length is shorter than the current length, Resize discards
-// trailing elements. If the new length is longer than the current length,
-// Resize adds the respective zero values for the additional elements. The capacity
-// parameter is ignored unless the new length or capacity is longer than the current
-// capacity. The resized vector's capacity may be larger than the requested capacity.
-func (p *IntVector) Resize(length, capacity int) *IntVector {
-	a := *p
-
-	if length > cap(a) || capacity > cap(a) {
-		// not enough space or larger capacity requested explicitly
-		a = p.realloc(length, capacity)
-	} else if length < len(a) {
-		// clear trailing elements
-		for i := range a[length:] {
-			var zero int
-			a[length+i] = zero
-		}
-	}
-
-	*p = a[0:length]
-	return p
-}
-
-// Len returns the number of elements in the vector.
-// Same as len(*p).
-func (p *IntVector) Len() int { return len(*p) }
-
-// Cap returns the capacity of the vector; that is, the
-// maximum length the vector can grow without resizing.
-// Same as cap(*p).
-func (p *IntVector) Cap() int { return cap(*p) }
-
-// At returns the i'th element of the vector.
-func (p *IntVector) At(i int) int { return (*p)[i] }
-
-// Set sets the i'th element of the vector to value x.
-func (p *IntVector) Set(i int, x int) { (*p)[i] = x }
-
-// Last returns the element in the vector of highest index.
-func (p *IntVector) Last() int { return (*p)[len(*p)-1] }
-
-// Copy makes a copy of the vector and returns it.
-func (p *IntVector) Copy() IntVector {
-	arr := make(IntVector, len(*p))
-	copy(arr, *p)
-	return arr
-}
-
-// Insert inserts into the vector an element of value x before
-// the current element at index i.
-func (p *IntVector) Insert(i int, x int) {
-	p.Expand(i, 1)
-	(*p)[i] = x
-}
-
-// Delete deletes the i'th element of the vector.  The gap is closed so the old
-// element at index i+1 has index i afterwards.
-func (p *IntVector) Delete(i int) {
-	a := *p
-	n := len(a)
-
-	copy(a[i:n-1], a[i+1:n])
-	var zero int
-	a[n-1] = zero // support GC, zero out entry
-	*p = a[0 : n-1]
-}
-
-// InsertVector inserts into the vector the contents of the vector
-// x such that the 0th element of x appears at index i after insertion.
-func (p *IntVector) InsertVector(i int, x *IntVector) {
-	b := *x
-
-	p.Expand(i, len(b))
-	copy((*p)[i:i+len(b)], b)
-}
-
-// Cut deletes elements i through j-1, inclusive.
-func (p *IntVector) Cut(i, j int) {
-	a := *p
-	n := len(a)
-	m := n - (j - i)
-
-	copy(a[i:m], a[j:n])
-	for k := m; k < n; k++ { //TODO(bflm) don't zero out the elements unless it's a Vector.
-		var zero int
-		a[k] = zero // support GC, zero out entries
-	}
-
-	*p = a[0:m]
-}
-
-// Slice returns a new sub-vector by slicing the old one to extract slice [i:j].
-// The elements are copied. The original vector is unchanged.
-func (p *IntVector) Slice(i, j int) *IntVector {
-	var s IntVector
-	s.realloc(j-i, 0) // will fail in Init() if j < i
-	copy(s, (*p)[i:j])
-	return &s
-}
-
-// Convenience wrappers
-
-// Push appends x to the end of the vector.
-func (p *IntVector) Push(x int) { p.Insert(len(*p), x) }
-
-// Pop deletes the last element of the vector.
-func (p *IntVector) Pop() int {
-	a := *p
-
-	i := len(a) - 1
-	x := a[i]
-	var zero int
-	a[i] = zero // support GC, zero out entry
-	*p = a[0:i]
-	return x
-}
-
-// AppendVector appends the entire vector x to the end of this vector.
-func (p *IntVector) AppendVector(x *IntVector) { p.InsertVector(len(*p), x) }
-
-// Swap exchanges the elements at indexes i and j.
-func (p *IntVector) Swap(i, j int) {
-	a := *p
-	a[i], a[j] = a[j], a[i]
-}
-
-// Do calls function f for each element of the vector, in order.
-// The behavior of Do is undefined if f changes *p.
-func (p *IntVector) Do(f func(elem int)) {
-	for _, e := range *p {
-		f(e)
-	}
-}
diff --git a/src/pkg/container/vector/intvector_test.go b/src/pkg/container/vector/intvector_test.go
deleted file mode 100644
index b825af9..0000000
--- a/src/pkg/container/vector/intvector_test.go
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector_test.go, it was generated
-// automatically from vector_test.go - DO NOT EDIT in that case!
-
-package vector
-
-import "testing"
-
-func TestIntZeroLen(t *testing.T) {
-	a := new(IntVector)
-	if a.Len() != 0 {
-		t.Errorf("%T: B1) expected 0, got %d", a, a.Len())
-	}
-	if len(*a) != 0 {
-		t.Errorf("%T: B2) expected 0, got %d", a, len(*a))
-	}
-	var b IntVector
-	if b.Len() != 0 {
-		t.Errorf("%T: B3) expected 0, got %d", b, b.Len())
-	}
-	if len(b) != 0 {
-		t.Errorf("%T: B4) expected 0, got %d", b, len(b))
-	}
-}
-
-func TestIntResize(t *testing.T) {
-	var a IntVector
-	checkSize(t, &a, 0, 0)
-	checkSize(t, a.Resize(0, 5), 0, 5)
-	checkSize(t, a.Resize(1, 0), 1, 5)
-	checkSize(t, a.Resize(10, 0), 10, 10)
-	checkSize(t, a.Resize(5, 0), 5, 10)
-	checkSize(t, a.Resize(3, 8), 3, 10)
-	checkSize(t, a.Resize(0, 100), 0, 100)
-	checkSize(t, a.Resize(11, 100), 11, 100)
-}
-
-func TestIntResize2(t *testing.T) {
-	var a IntVector
-	checkSize(t, &a, 0, 0)
-	a.Push(int2IntValue(1))
-	a.Push(int2IntValue(2))
-	a.Push(int2IntValue(3))
-	a.Push(int2IntValue(4))
-	checkSize(t, &a, 4, 4)
-	checkSize(t, a.Resize(10, 0), 10, 10)
-	for i := 4; i < a.Len(); i++ {
-		if a.At(i) != intzero {
-			t.Errorf("%T: expected a.At(%d) == %v; found %v!", a, i, intzero, a.At(i))
-		}
-	}
-	for i := 4; i < len(a); i++ {
-		if a[i] != intzero {
-			t.Errorf("%T: expected a[%d] == %v; found %v", a, i, intzero, a[i])
-		}
-	}
-}
-
-func checkIntZero(t *testing.T, a *IntVector, i int) {
-	for j := 0; j < i; j++ {
-		if a.At(j) == intzero {
-			t.Errorf("%T: 1 expected a.At(%d) == %d; found %v", a, j, j, a.At(j))
-		}
-		if (*a)[j] == intzero {
-			t.Errorf("%T: 2 expected (*a)[%d] == %d; found %v", a, j, j, (*a)[j])
-		}
-	}
-	for ; i < a.Len(); i++ {
-		if a.At(i) != intzero {
-			t.Errorf("%T: 3 expected a.At(%d) == %v; found %v", a, i, intzero, a.At(i))
-		}
-		if (*a)[i] != intzero {
-			t.Errorf("%T: 4 expected (*a)[%d] == %v; found %v", a, i, intzero, (*a)[i])
-		}
-	}
-}
-
-func TestIntTrailingElements(t *testing.T) {
-	var a IntVector
-	for i := 0; i < 10; i++ {
-		a.Push(int2IntValue(i + 1))
-	}
-	checkIntZero(t, &a, 10)
-	checkSize(t, &a, 10, 16)
-	checkSize(t, a.Resize(5, 0), 5, 16)
-	checkSize(t, a.Resize(10, 0), 10, 16)
-	checkIntZero(t, &a, 5)
-}
-
-func TestIntAccess(t *testing.T) {
-	const n = 100
-	var a IntVector
-	a.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		a.Set(i, int2IntValue(val(i)))
-	}
-	for i := 0; i < n; i++ {
-		if elem2IntValue(a.At(i)) != int2IntValue(val(i)) {
-			t.Error(i)
-		}
-	}
-	var b IntVector
-	b.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		b[i] = int2IntValue(val(i))
-	}
-	for i := 0; i < n; i++ {
-		if elem2IntValue(b[i]) != int2IntValue(val(i)) {
-			t.Error(i)
-		}
-	}
-}
-
-func TestIntInsertDeleteClear(t *testing.T) {
-	const n = 100
-	var a IntVector
-
-	for i := 0; i < n; i++ {
-		if a.Len() != i {
-			t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
-		}
-		if len(a) != i {
-			t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
-		}
-		a.Insert(0, int2IntValue(val(i)))
-		if elem2IntValue(a.Last()) != int2IntValue(val(0)) {
-			t.Errorf("%T: B", a)
-		}
-	}
-	for i := n - 1; i >= 0; i-- {
-		if elem2IntValue(a.Last()) != int2IntValue(val(0)) {
-			t.Errorf("%T: C", a)
-		}
-		if elem2IntValue(a.At(0)) != int2IntValue(val(i)) {
-			t.Errorf("%T: D", a)
-		}
-		if elem2IntValue(a[0]) != int2IntValue(val(i)) {
-			t.Errorf("%T: D2", a)
-		}
-		a.Delete(0)
-		if a.Len() != i {
-			t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
-		}
-		if len(a) != i {
-			t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
-		}
-	}
-
-	if a.Len() != 0 {
-		t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
-	}
-	if len(a) != 0 {
-		t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
-	}
-	for i := 0; i < n; i++ {
-		a.Push(int2IntValue(val(i)))
-		if a.Len() != i+1 {
-			t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
-		}
-		if len(a) != i+1 {
-			t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
-		}
-		if elem2IntValue(a.Last()) != int2IntValue(val(i)) {
-			t.Errorf("%T: H", a)
-		}
-	}
-	a.Resize(0, 0)
-	if a.Len() != 0 {
-		t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
-	}
-	if len(a) != 0 {
-		t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
-	}
-
-	const m = 5
-	for j := 0; j < m; j++ {
-		a.Push(int2IntValue(j))
-		for i := 0; i < n; i++ {
-			x := val(i)
-			a.Push(int2IntValue(x))
-			if elem2IntValue(a.Pop()) != int2IntValue(x) {
-				t.Errorf("%T: J", a)
-			}
-			if a.Len() != j+1 {
-				t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
-			}
-			if len(a) != j+1 {
-				t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
-			}
-		}
-	}
-	if a.Len() != m {
-		t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
-	}
-	if len(a) != m {
-		t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
-	}
-}
-
-func verify_sliceInt(t *testing.T, x *IntVector, elt, i, j int) {
-	for k := i; k < j; k++ {
-		if elem2IntValue(x.At(k)) != int2IntValue(elt) {
-			t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2IntValue(x.At(k)), int2IntValue(elt))
-		}
-	}
-
-	s := x.Slice(i, j)
-	for k, n := 0, j-i; k < n; k++ {
-		if elem2IntValue(s.At(k)) != int2IntValue(elt) {
-			t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2IntValue(x.At(k)), int2IntValue(elt))
-		}
-	}
-}
-
-func verify_patternInt(t *testing.T, x *IntVector, a, b, c int) {
-	n := a + b + c
-	if x.Len() != n {
-		t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
-	}
-	if len(*x) != n {
-		t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
-	}
-	verify_sliceInt(t, x, 0, 0, a)
-	verify_sliceInt(t, x, 1, a, a+b)
-	verify_sliceInt(t, x, 0, a+b, n)
-}
-
-func make_vectorInt(elt, len int) *IntVector {
-	x := new(IntVector).Resize(len, 0)
-	for i := 0; i < len; i++ {
-		x.Set(i, int2IntValue(elt))
-	}
-	return x
-}
-
-func TestIntInsertVector(t *testing.T) {
-	// 1
-	a := make_vectorInt(0, 0)
-	b := make_vectorInt(1, 10)
-	a.InsertVector(0, b)
-	verify_patternInt(t, a, 0, 10, 0)
-	// 2
-	a = make_vectorInt(0, 10)
-	b = make_vectorInt(1, 0)
-	a.InsertVector(5, b)
-	verify_patternInt(t, a, 5, 0, 5)
-	// 3
-	a = make_vectorInt(0, 10)
-	b = make_vectorInt(1, 3)
-	a.InsertVector(3, b)
-	verify_patternInt(t, a, 3, 3, 7)
-	// 4
-	a = make_vectorInt(0, 10)
-	b = make_vectorInt(1, 1000)
-	a.InsertVector(8, b)
-	verify_patternInt(t, a, 8, 1000, 2)
-}
-
-func TestIntDo(t *testing.T) {
-	const n = 25
-	const salt = 17
-	a := new(IntVector).Resize(n, 0)
-	for i := 0; i < n; i++ {
-		a.Set(i, int2IntValue(salt*i))
-	}
-	count := 0
-	a.Do(func(e int) {
-		i := intf2IntValue(e)
-		if i != int2IntValue(count*salt) {
-			t.Error(tname(a), "value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(a), "should visit", n, "values; did visit", count)
-	}
-
-	b := new(IntVector).Resize(n, 0)
-	for i := 0; i < n; i++ {
-		(*b)[i] = int2IntValue(salt * i)
-	}
-	count = 0
-	b.Do(func(e int) {
-		i := intf2IntValue(e)
-		if i != int2IntValue(count*salt) {
-			t.Error(tname(b), "b) value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(b), "b) should visit", n, "values; did visit", count)
-	}
-
-	var c IntVector
-	c.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		c[i] = int2IntValue(salt * i)
-	}
-	count = 0
-	c.Do(func(e int) {
-		i := intf2IntValue(e)
-		if i != int2IntValue(count*salt) {
-			t.Error(tname(c), "c) value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(c), "c) should visit", n, "values; did visit", count)
-	}
-
-}
-
-func TestIntVectorCopy(t *testing.T) {
-	// verify Copy() returns a copy, not simply a slice of the original vector
-	const Len = 10
-	var src IntVector
-	for i := 0; i < Len; i++ {
-		src.Push(int2IntValue(i * i))
-	}
-	dest := src.Copy()
-	for i := 0; i < Len; i++ {
-		src[i] = int2IntValue(-1)
-		v := elem2IntValue(dest[i])
-		if v != int2IntValue(i*i) {
-			t.Error(tname(src), "expected", i*i, "got", v)
-		}
-	}
-}
diff --git a/src/pkg/container/vector/nogen_test.go b/src/pkg/container/vector/nogen_test.go
deleted file mode 100644
index 7b6a259..0000000
--- a/src/pkg/container/vector/nogen_test.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vector
-
-import (
-	"fmt"
-	"sort"
-	"testing"
-)
-
-var (
-	zero    interface{}
-	intzero int
-	strzero string
-)
-
-func int2Value(x int) int       { return x }
-func int2IntValue(x int) int    { return x }
-func int2StrValue(x int) string { return string(x) }
-
-func elem2Value(x interface{}) int  { return x.(int) }
-func elem2IntValue(x int) int       { return x }
-func elem2StrValue(x string) string { return x }
-
-func intf2Value(x interface{}) int       { return x.(int) }
-func intf2IntValue(x interface{}) int    { return x.(int) }
-func intf2StrValue(x interface{}) string { return x.(string) }
-
-type VectorInterface interface {
-	Len() int
-	Cap() int
-}
-
-func checkSize(t *testing.T, v VectorInterface, len, cap int) {
-	if v.Len() != len {
-		t.Errorf("%T expected len = %d; found %d", v, len, v.Len())
-	}
-	if v.Cap() < cap {
-		t.Errorf("%T expected cap >= %d; found %d", v, cap, v.Cap())
-	}
-}
-
-func val(i int) int { return i*991 - 1234 }
-
-func TestSorting(t *testing.T) {
-	const n = 100
-
-	a := new(IntVector).Resize(n, 0)
-	for i := n - 1; i >= 0; i-- {
-		a.Set(i, n-1-i)
-	}
-	if sort.IsSorted(a) {
-		t.Error("int vector not sorted")
-	}
-
-	b := new(StringVector).Resize(n, 0)
-	for i := n - 1; i >= 0; i-- {
-		b.Set(i, fmt.Sprint(n-1-i))
-	}
-	if sort.IsSorted(b) {
-		t.Error("string vector not sorted")
-	}
-}
-
-func tname(x interface{}) string { return fmt.Sprintf("%T: ", x) }
diff --git a/src/pkg/container/vector/numbers_test.go b/src/pkg/container/vector/numbers_test.go
deleted file mode 100644
index abe01a8..0000000
--- a/src/pkg/container/vector/numbers_test.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vector
-
-import (
-	"fmt"
-	"runtime"
-	"strings"
-	"testing"
-)
-
-const memTestN = 1000000
-
-func s(n uint64) string {
-	str := fmt.Sprintf("%d", n)
-	lens := len(str)
-	a := make([]string, (lens+2)/3)
-	start := lens
-	for i := range a {
-		start -= 3
-		if start < 0 {
-			start = 0
-		}
-		a[len(a)-i-1] = str[start:lens]
-		lens -= 3
-	}
-	return strings.Join(a, " ")
-}
-
-func TestVectorNums(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-	var v Vector
-	c := int(0)
-	runtime.GC()
-	m0 := runtime.MemStats
-	v.Resize(memTestN, memTestN)
-	for i := 0; i < memTestN; i++ {
-		v.Set(i, c)
-	}
-	runtime.GC()
-	m := runtime.MemStats
-	v.Resize(0, 0)
-	runtime.GC()
-	n := m.Alloc - m0.Alloc
-	t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
-}
-
-func TestIntVectorNums(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-	var v IntVector
-	c := int(0)
-	runtime.GC()
-	m0 := runtime.MemStats
-	v.Resize(memTestN, memTestN)
-	for i := 0; i < memTestN; i++ {
-		v.Set(i, c)
-	}
-	runtime.GC()
-	m := runtime.MemStats
-	v.Resize(0, 0)
-	runtime.GC()
-	n := m.Alloc - m0.Alloc
-	t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
-}
-
-func TestStringVectorNums(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-	var v StringVector
-	c := ""
-	runtime.GC()
-	m0 := runtime.MemStats
-	v.Resize(memTestN, memTestN)
-	for i := 0; i < memTestN; i++ {
-		v.Set(i, c)
-	}
-	runtime.GC()
-	m := runtime.MemStats
-	v.Resize(0, 0)
-	runtime.GC()
-	n := m.Alloc - m0.Alloc
-	t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
-}
-
-func BenchmarkVectorNums(b *testing.B) {
-	c := int(0)
-	var v Vector
-	b.StopTimer()
-	runtime.GC()
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		v.Push(c)
-	}
-}
-
-func BenchmarkIntVectorNums(b *testing.B) {
-	c := int(0)
-	var v IntVector
-	b.StopTimer()
-	runtime.GC()
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		v.Push(c)
-	}
-}
-
-func BenchmarkStringVectorNums(b *testing.B) {
-	c := ""
-	var v StringVector
-	b.StopTimer()
-	runtime.GC()
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		v.Push(c)
-	}
-}
diff --git a/src/pkg/container/vector/stringvector.go b/src/pkg/container/vector/stringvector.go
deleted file mode 100644
index dc81f06..0000000
--- a/src/pkg/container/vector/stringvector.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector.go, it was generated
-// automatically from vector.go - DO NOT EDIT in that case!
-
-package vector
-
-func (p *StringVector) realloc(length, capacity int) (b []string) {
-	if capacity < initialSize {
-		capacity = initialSize
-	}
-	if capacity < length {
-		capacity = length
-	}
-	b = make(StringVector, length, capacity)
-	copy(b, *p)
-	*p = b
-	return
-}
-
-// Insert n elements at position i.
-func (p *StringVector) Expand(i, n int) {
-	a := *p
-
-	// make sure we have enough space
-	len0 := len(a)
-	len1 := len0 + n
-	if len1 <= cap(a) {
-		// enough space - just expand
-		a = a[0:len1]
-	} else {
-		// not enough space - double capacity
-		capb := cap(a) * 2
-		if capb < len1 {
-			// still not enough - use required length
-			capb = len1
-		}
-		// capb >= len1
-		a = p.realloc(len1, capb)
-	}
-
-	// make a hole
-	for j := len0 - 1; j >= i; j-- {
-		a[j+n] = a[j]
-	}
-
-	*p = a
-}
-
-// Insert n elements at the end of a vector.
-func (p *StringVector) Extend(n int) { p.Expand(len(*p), n) }
-
-// Resize changes the length and capacity of a vector.
-// If the new length is shorter than the current length, Resize discards
-// trailing elements. If the new length is longer than the current length,
-// Resize adds the respective zero values for the additional elements. The capacity
-// parameter is ignored unless the new length or capacity is longer than the current
-// capacity. The resized vector's capacity may be larger than the requested capacity.
-func (p *StringVector) Resize(length, capacity int) *StringVector {
-	a := *p
-
-	if length > cap(a) || capacity > cap(a) {
-		// not enough space or larger capacity requested explicitly
-		a = p.realloc(length, capacity)
-	} else if length < len(a) {
-		// clear trailing elements
-		for i := range a[length:] {
-			var zero string
-			a[length+i] = zero
-		}
-	}
-
-	*p = a[0:length]
-	return p
-}
-
-// Len returns the number of elements in the vector.
-// Same as len(*p).
-func (p *StringVector) Len() int { return len(*p) }
-
-// Cap returns the capacity of the vector; that is, the
-// maximum length the vector can grow without resizing.
-// Same as cap(*p).
-func (p *StringVector) Cap() int { return cap(*p) }
-
-// At returns the i'th element of the vector.
-func (p *StringVector) At(i int) string { return (*p)[i] }
-
-// Set sets the i'th element of the vector to value x.
-func (p *StringVector) Set(i int, x string) { (*p)[i] = x }
-
-// Last returns the element in the vector of highest index.
-func (p *StringVector) Last() string { return (*p)[len(*p)-1] }
-
-// Copy makes a copy of the vector and returns it.
-func (p *StringVector) Copy() StringVector {
-	arr := make(StringVector, len(*p))
-	copy(arr, *p)
-	return arr
-}
-
-// Insert inserts into the vector an element of value x before
-// the current element at index i.
-func (p *StringVector) Insert(i int, x string) {
-	p.Expand(i, 1)
-	(*p)[i] = x
-}
-
-// Delete deletes the i'th element of the vector.  The gap is closed so the old
-// element at index i+1 has index i afterwards.
-func (p *StringVector) Delete(i int) {
-	a := *p
-	n := len(a)
-
-	copy(a[i:n-1], a[i+1:n])
-	var zero string
-	a[n-1] = zero // support GC, zero out entry
-	*p = a[0 : n-1]
-}
-
-// InsertVector inserts into the vector the contents of the vector
-// x such that the 0th element of x appears at index i after insertion.
-func (p *StringVector) InsertVector(i int, x *StringVector) {
-	b := *x
-
-	p.Expand(i, len(b))
-	copy((*p)[i:i+len(b)], b)
-}
-
-// Cut deletes elements i through j-1, inclusive.
-func (p *StringVector) Cut(i, j int) {
-	a := *p
-	n := len(a)
-	m := n - (j - i)
-
-	copy(a[i:m], a[j:n])
-	for k := m; k < n; k++ { //TODO(bflm) don't zero out the elements unless it's a Vector.
-		var zero string
-		a[k] = zero // support GC, zero out entries
-	}
-
-	*p = a[0:m]
-}
-
-// Slice returns a new sub-vector by slicing the old one to extract slice [i:j].
-// The elements are copied. The original vector is unchanged.
-func (p *StringVector) Slice(i, j int) *StringVector {
-	var s StringVector
-	s.realloc(j-i, 0) // will fail in Init() if j < i
-	copy(s, (*p)[i:j])
-	return &s
-}
-
-// Convenience wrappers
-
-// Push appends x to the end of the vector.
-func (p *StringVector) Push(x string) { p.Insert(len(*p), x) }
-
-// Pop deletes the last element of the vector.
-func (p *StringVector) Pop() string {
-	a := *p
-
-	i := len(a) - 1
-	x := a[i]
-	var zero string
-	a[i] = zero // support GC, zero out entry
-	*p = a[0:i]
-	return x
-}
-
-// AppendVector appends the entire vector x to the end of this vector.
-func (p *StringVector) AppendVector(x *StringVector) { p.InsertVector(len(*p), x) }
-
-// Swap exchanges the elements at indexes i and j.
-func (p *StringVector) Swap(i, j int) {
-	a := *p
-	a[i], a[j] = a[j], a[i]
-}
-
-// Do calls function f for each element of the vector, in order.
-// The behavior of Do is undefined if f changes *p.
-func (p *StringVector) Do(f func(elem string)) {
-	for _, e := range *p {
-		f(e)
-	}
-}
diff --git a/src/pkg/container/vector/stringvector_test.go b/src/pkg/container/vector/stringvector_test.go
deleted file mode 100644
index c75676f..0000000
--- a/src/pkg/container/vector/stringvector_test.go
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector_test.go, it was generated
-// automatically from vector_test.go - DO NOT EDIT in that case!
-
-package vector
-
-import "testing"
-
-func TestStrZeroLen(t *testing.T) {
-	a := new(StringVector)
-	if a.Len() != 0 {
-		t.Errorf("%T: B1) expected 0, got %d", a, a.Len())
-	}
-	if len(*a) != 0 {
-		t.Errorf("%T: B2) expected 0, got %d", a, len(*a))
-	}
-	var b StringVector
-	if b.Len() != 0 {
-		t.Errorf("%T: B3) expected 0, got %d", b, b.Len())
-	}
-	if len(b) != 0 {
-		t.Errorf("%T: B4) expected 0, got %d", b, len(b))
-	}
-}
-
-func TestStrResize(t *testing.T) {
-	var a StringVector
-	checkSize(t, &a, 0, 0)
-	checkSize(t, a.Resize(0, 5), 0, 5)
-	checkSize(t, a.Resize(1, 0), 1, 5)
-	checkSize(t, a.Resize(10, 0), 10, 10)
-	checkSize(t, a.Resize(5, 0), 5, 10)
-	checkSize(t, a.Resize(3, 8), 3, 10)
-	checkSize(t, a.Resize(0, 100), 0, 100)
-	checkSize(t, a.Resize(11, 100), 11, 100)
-}
-
-func TestStrResize2(t *testing.T) {
-	var a StringVector
-	checkSize(t, &a, 0, 0)
-	a.Push(int2StrValue(1))
-	a.Push(int2StrValue(2))
-	a.Push(int2StrValue(3))
-	a.Push(int2StrValue(4))
-	checkSize(t, &a, 4, 4)
-	checkSize(t, a.Resize(10, 0), 10, 10)
-	for i := 4; i < a.Len(); i++ {
-		if a.At(i) != strzero {
-			t.Errorf("%T: expected a.At(%d) == %v; found %v!", a, i, strzero, a.At(i))
-		}
-	}
-	for i := 4; i < len(a); i++ {
-		if a[i] != strzero {
-			t.Errorf("%T: expected a[%d] == %v; found %v", a, i, strzero, a[i])
-		}
-	}
-}
-
-func checkStrZero(t *testing.T, a *StringVector, i int) {
-	for j := 0; j < i; j++ {
-		if a.At(j) == strzero {
-			t.Errorf("%T: 1 expected a.At(%d) == %d; found %v", a, j, j, a.At(j))
-		}
-		if (*a)[j] == strzero {
-			t.Errorf("%T: 2 expected (*a)[%d] == %d; found %v", a, j, j, (*a)[j])
-		}
-	}
-	for ; i < a.Len(); i++ {
-		if a.At(i) != strzero {
-			t.Errorf("%T: 3 expected a.At(%d) == %v; found %v", a, i, strzero, a.At(i))
-		}
-		if (*a)[i] != strzero {
-			t.Errorf("%T: 4 expected (*a)[%d] == %v; found %v", a, i, strzero, (*a)[i])
-		}
-	}
-}
-
-func TestStrTrailingElements(t *testing.T) {
-	var a StringVector
-	for i := 0; i < 10; i++ {
-		a.Push(int2StrValue(i + 1))
-	}
-	checkStrZero(t, &a, 10)
-	checkSize(t, &a, 10, 16)
-	checkSize(t, a.Resize(5, 0), 5, 16)
-	checkSize(t, a.Resize(10, 0), 10, 16)
-	checkStrZero(t, &a, 5)
-}
-
-func TestStrAccess(t *testing.T) {
-	const n = 100
-	var a StringVector
-	a.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		a.Set(i, int2StrValue(val(i)))
-	}
-	for i := 0; i < n; i++ {
-		if elem2StrValue(a.At(i)) != int2StrValue(val(i)) {
-			t.Error(i)
-		}
-	}
-	var b StringVector
-	b.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		b[i] = int2StrValue(val(i))
-	}
-	for i := 0; i < n; i++ {
-		if elem2StrValue(b[i]) != int2StrValue(val(i)) {
-			t.Error(i)
-		}
-	}
-}
-
-func TestStrInsertDeleteClear(t *testing.T) {
-	const n = 100
-	var a StringVector
-
-	for i := 0; i < n; i++ {
-		if a.Len() != i {
-			t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
-		}
-		if len(a) != i {
-			t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
-		}
-		a.Insert(0, int2StrValue(val(i)))
-		if elem2StrValue(a.Last()) != int2StrValue(val(0)) {
-			t.Errorf("%T: B", a)
-		}
-	}
-	for i := n - 1; i >= 0; i-- {
-		if elem2StrValue(a.Last()) != int2StrValue(val(0)) {
-			t.Errorf("%T: C", a)
-		}
-		if elem2StrValue(a.At(0)) != int2StrValue(val(i)) {
-			t.Errorf("%T: D", a)
-		}
-		if elem2StrValue(a[0]) != int2StrValue(val(i)) {
-			t.Errorf("%T: D2", a)
-		}
-		a.Delete(0)
-		if a.Len() != i {
-			t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
-		}
-		if len(a) != i {
-			t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
-		}
-	}
-
-	if a.Len() != 0 {
-		t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
-	}
-	if len(a) != 0 {
-		t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
-	}
-	for i := 0; i < n; i++ {
-		a.Push(int2StrValue(val(i)))
-		if a.Len() != i+1 {
-			t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
-		}
-		if len(a) != i+1 {
-			t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
-		}
-		if elem2StrValue(a.Last()) != int2StrValue(val(i)) {
-			t.Errorf("%T: H", a)
-		}
-	}
-	a.Resize(0, 0)
-	if a.Len() != 0 {
-		t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
-	}
-	if len(a) != 0 {
-		t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
-	}
-
-	const m = 5
-	for j := 0; j < m; j++ {
-		a.Push(int2StrValue(j))
-		for i := 0; i < n; i++ {
-			x := val(i)
-			a.Push(int2StrValue(x))
-			if elem2StrValue(a.Pop()) != int2StrValue(x) {
-				t.Errorf("%T: J", a)
-			}
-			if a.Len() != j+1 {
-				t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
-			}
-			if len(a) != j+1 {
-				t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
-			}
-		}
-	}
-	if a.Len() != m {
-		t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
-	}
-	if len(a) != m {
-		t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
-	}
-}
-
-func verify_sliceStr(t *testing.T, x *StringVector, elt, i, j int) {
-	for k := i; k < j; k++ {
-		if elem2StrValue(x.At(k)) != int2StrValue(elt) {
-			t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2StrValue(x.At(k)), int2StrValue(elt))
-		}
-	}
-
-	s := x.Slice(i, j)
-	for k, n := 0, j-i; k < n; k++ {
-		if elem2StrValue(s.At(k)) != int2StrValue(elt) {
-			t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2StrValue(x.At(k)), int2StrValue(elt))
-		}
-	}
-}
-
-func verify_patternStr(t *testing.T, x *StringVector, a, b, c int) {
-	n := a + b + c
-	if x.Len() != n {
-		t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
-	}
-	if len(*x) != n {
-		t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
-	}
-	verify_sliceStr(t, x, 0, 0, a)
-	verify_sliceStr(t, x, 1, a, a+b)
-	verify_sliceStr(t, x, 0, a+b, n)
-}
-
-func make_vectorStr(elt, len int) *StringVector {
-	x := new(StringVector).Resize(len, 0)
-	for i := 0; i < len; i++ {
-		x.Set(i, int2StrValue(elt))
-	}
-	return x
-}
-
-func TestStrInsertVector(t *testing.T) {
-	// 1
-	a := make_vectorStr(0, 0)
-	b := make_vectorStr(1, 10)
-	a.InsertVector(0, b)
-	verify_patternStr(t, a, 0, 10, 0)
-	// 2
-	a = make_vectorStr(0, 10)
-	b = make_vectorStr(1, 0)
-	a.InsertVector(5, b)
-	verify_patternStr(t, a, 5, 0, 5)
-	// 3
-	a = make_vectorStr(0, 10)
-	b = make_vectorStr(1, 3)
-	a.InsertVector(3, b)
-	verify_patternStr(t, a, 3, 3, 7)
-	// 4
-	a = make_vectorStr(0, 10)
-	b = make_vectorStr(1, 1000)
-	a.InsertVector(8, b)
-	verify_patternStr(t, a, 8, 1000, 2)
-}
-
-func TestStrDo(t *testing.T) {
-	const n = 25
-	const salt = 17
-	a := new(StringVector).Resize(n, 0)
-	for i := 0; i < n; i++ {
-		a.Set(i, int2StrValue(salt*i))
-	}
-	count := 0
-	a.Do(func(e string) {
-		i := intf2StrValue(e)
-		if i != int2StrValue(count*salt) {
-			t.Error(tname(a), "value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(a), "should visit", n, "values; did visit", count)
-	}
-
-	b := new(StringVector).Resize(n, 0)
-	for i := 0; i < n; i++ {
-		(*b)[i] = int2StrValue(salt * i)
-	}
-	count = 0
-	b.Do(func(e string) {
-		i := intf2StrValue(e)
-		if i != int2StrValue(count*salt) {
-			t.Error(tname(b), "b) value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(b), "b) should visit", n, "values; did visit", count)
-	}
-
-	var c StringVector
-	c.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		c[i] = int2StrValue(salt * i)
-	}
-	count = 0
-	c.Do(func(e string) {
-		i := intf2StrValue(e)
-		if i != int2StrValue(count*salt) {
-			t.Error(tname(c), "c) value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(c), "c) should visit", n, "values; did visit", count)
-	}
-
-}
-
-func TestStrVectorCopy(t *testing.T) {
-	// verify Copy() returns a copy, not simply a slice of the original vector
-	const Len = 10
-	var src StringVector
-	for i := 0; i < Len; i++ {
-		src.Push(int2StrValue(i * i))
-	}
-	dest := src.Copy()
-	for i := 0; i < Len; i++ {
-		src[i] = int2StrValue(-1)
-		v := elem2StrValue(dest[i])
-		if v != int2StrValue(i*i) {
-			t.Error(tname(src), "expected", i*i, "got", v)
-		}
-	}
-}
diff --git a/src/pkg/container/vector/vector.go b/src/pkg/container/vector/vector.go
deleted file mode 100644
index 8470ec0..0000000
--- a/src/pkg/container/vector/vector.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector.go, it was generated
-// automatically from vector.go - DO NOT EDIT in that case!
-
-package vector
-
-func (p *Vector) realloc(length, capacity int) (b []interface{}) {
-	if capacity < initialSize {
-		capacity = initialSize
-	}
-	if capacity < length {
-		capacity = length
-	}
-	b = make(Vector, length, capacity)
-	copy(b, *p)
-	*p = b
-	return
-}
-
-// Insert n elements at position i.
-func (p *Vector) Expand(i, n int) {
-	a := *p
-
-	// make sure we have enough space
-	len0 := len(a)
-	len1 := len0 + n
-	if len1 <= cap(a) {
-		// enough space - just expand
-		a = a[0:len1]
-	} else {
-		// not enough space - double capacity
-		capb := cap(a) * 2
-		if capb < len1 {
-			// still not enough - use required length
-			capb = len1
-		}
-		// capb >= len1
-		a = p.realloc(len1, capb)
-	}
-
-	// make a hole
-	for j := len0 - 1; j >= i; j-- {
-		a[j+n] = a[j]
-	}
-
-	*p = a
-}
-
-// Insert n elements at the end of a vector.
-func (p *Vector) Extend(n int) { p.Expand(len(*p), n) }
-
-// Resize changes the length and capacity of a vector.
-// If the new length is shorter than the current length, Resize discards
-// trailing elements. If the new length is longer than the current length,
-// Resize adds the respective zero values for the additional elements. The capacity
-// parameter is ignored unless the new length or capacity is longer than the current
-// capacity. The resized vector's capacity may be larger than the requested capacity.
-func (p *Vector) Resize(length, capacity int) *Vector {
-	a := *p
-
-	if length > cap(a) || capacity > cap(a) {
-		// not enough space or larger capacity requested explicitly
-		a = p.realloc(length, capacity)
-	} else if length < len(a) {
-		// clear trailing elements
-		for i := range a[length:] {
-			var zero interface{}
-			a[length+i] = zero
-		}
-	}
-
-	*p = a[0:length]
-	return p
-}
-
-// Len returns the number of elements in the vector.
-// Same as len(*p).
-func (p *Vector) Len() int { return len(*p) }
-
-// Cap returns the capacity of the vector; that is, the
-// maximum length the vector can grow without resizing.
-// Same as cap(*p).
-func (p *Vector) Cap() int { return cap(*p) }
-
-// At returns the i'th element of the vector.
-func (p *Vector) At(i int) interface{} { return (*p)[i] }
-
-// Set sets the i'th element of the vector to value x.
-func (p *Vector) Set(i int, x interface{}) { (*p)[i] = x }
-
-// Last returns the element in the vector of highest index.
-func (p *Vector) Last() interface{} { return (*p)[len(*p)-1] }
-
-// Copy makes a copy of the vector and returns it.
-func (p *Vector) Copy() Vector {
-	arr := make(Vector, len(*p))
-	copy(arr, *p)
-	return arr
-}
-
-// Insert inserts into the vector an element of value x before
-// the current element at index i.
-func (p *Vector) Insert(i int, x interface{}) {
-	p.Expand(i, 1)
-	(*p)[i] = x
-}
-
-// Delete deletes the i'th element of the vector.  The gap is closed so the old
-// element at index i+1 has index i afterwards.
-func (p *Vector) Delete(i int) {
-	a := *p
-	n := len(a)
-
-	copy(a[i:n-1], a[i+1:n])
-	var zero interface{}
-	a[n-1] = zero // support GC, zero out entry
-	*p = a[0 : n-1]
-}
-
-// InsertVector inserts into the vector the contents of the vector
-// x such that the 0th element of x appears at index i after insertion.
-func (p *Vector) InsertVector(i int, x *Vector) {
-	b := *x
-
-	p.Expand(i, len(b))
-	copy((*p)[i:i+len(b)], b)
-}
-
-// Cut deletes elements i through j-1, inclusive.
-func (p *Vector) Cut(i, j int) {
-	a := *p
-	n := len(a)
-	m := n - (j - i)
-
-	copy(a[i:m], a[j:n])
-	for k := m; k < n; k++ { //TODO(bflm) don't zero out the elements unless it's a Vector.
-		var zero interface{}
-		a[k] = zero // support GC, zero out entries
-	}
-
-	*p = a[0:m]
-}
-
-// Slice returns a new sub-vector by slicing the old one to extract slice [i:j].
-// The elements are copied. The original vector is unchanged.
-func (p *Vector) Slice(i, j int) *Vector {
-	var s Vector
-	s.realloc(j-i, 0) // will fail in Init() if j < i
-	copy(s, (*p)[i:j])
-	return &s
-}
-
-// Convenience wrappers
-
-// Push appends x to the end of the vector.
-func (p *Vector) Push(x interface{}) { p.Insert(len(*p), x) }
-
-// Pop deletes the last element of the vector.
-func (p *Vector) Pop() interface{} {
-	a := *p
-
-	i := len(a) - 1
-	x := a[i]
-	var zero interface{}
-	a[i] = zero // support GC, zero out entry
-	*p = a[0:i]
-	return x
-}
-
-// AppendVector appends the entire vector x to the end of this vector.
-func (p *Vector) AppendVector(x *Vector) { p.InsertVector(len(*p), x) }
-
-// Swap exchanges the elements at indexes i and j.
-func (p *Vector) Swap(i, j int) {
-	a := *p
-	a[i], a[j] = a[j], a[i]
-}
-
-// Do calls function f for each element of the vector, in order.
-// The behavior of Do is undefined if f changes *p.
-func (p *Vector) Do(f func(elem interface{})) {
-	for _, e := range *p {
-		f(e)
-	}
-}
diff --git a/src/pkg/container/vector/vector_test.go b/src/pkg/container/vector/vector_test.go
deleted file mode 100644
index a7f47b8..0000000
--- a/src/pkg/container/vector/vector_test.go
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector_test.go, it was generated
-// automatically from vector_test.go - DO NOT EDIT in that case!
-
-package vector
-
-import "testing"
-
-func TestZeroLen(t *testing.T) {
-	a := new(Vector)
-	if a.Len() != 0 {
-		t.Errorf("%T: B1) expected 0, got %d", a, a.Len())
-	}
-	if len(*a) != 0 {
-		t.Errorf("%T: B2) expected 0, got %d", a, len(*a))
-	}
-	var b Vector
-	if b.Len() != 0 {
-		t.Errorf("%T: B3) expected 0, got %d", b, b.Len())
-	}
-	if len(b) != 0 {
-		t.Errorf("%T: B4) expected 0, got %d", b, len(b))
-	}
-}
-
-func TestResize(t *testing.T) {
-	var a Vector
-	checkSize(t, &a, 0, 0)
-	checkSize(t, a.Resize(0, 5), 0, 5)
-	checkSize(t, a.Resize(1, 0), 1, 5)
-	checkSize(t, a.Resize(10, 0), 10, 10)
-	checkSize(t, a.Resize(5, 0), 5, 10)
-	checkSize(t, a.Resize(3, 8), 3, 10)
-	checkSize(t, a.Resize(0, 100), 0, 100)
-	checkSize(t, a.Resize(11, 100), 11, 100)
-}
-
-func TestResize2(t *testing.T) {
-	var a Vector
-	checkSize(t, &a, 0, 0)
-	a.Push(int2Value(1))
-	a.Push(int2Value(2))
-	a.Push(int2Value(3))
-	a.Push(int2Value(4))
-	checkSize(t, &a, 4, 4)
-	checkSize(t, a.Resize(10, 0), 10, 10)
-	for i := 4; i < a.Len(); i++ {
-		if a.At(i) != zero {
-			t.Errorf("%T: expected a.At(%d) == %v; found %v!", a, i, zero, a.At(i))
-		}
-	}
-	for i := 4; i < len(a); i++ {
-		if a[i] != zero {
-			t.Errorf("%T: expected a[%d] == %v; found %v", a, i, zero, a[i])
-		}
-	}
-}
-
-func checkZero(t *testing.T, a *Vector, i int) {
-	for j := 0; j < i; j++ {
-		if a.At(j) == zero {
-			t.Errorf("%T: 1 expected a.At(%d) == %d; found %v", a, j, j, a.At(j))
-		}
-		if (*a)[j] == zero {
-			t.Errorf("%T: 2 expected (*a)[%d] == %d; found %v", a, j, j, (*a)[j])
-		}
-	}
-	for ; i < a.Len(); i++ {
-		if a.At(i) != zero {
-			t.Errorf("%T: 3 expected a.At(%d) == %v; found %v", a, i, zero, a.At(i))
-		}
-		if (*a)[i] != zero {
-			t.Errorf("%T: 4 expected (*a)[%d] == %v; found %v", a, i, zero, (*a)[i])
-		}
-	}
-}
-
-func TestTrailingElements(t *testing.T) {
-	var a Vector
-	for i := 0; i < 10; i++ {
-		a.Push(int2Value(i + 1))
-	}
-	checkZero(t, &a, 10)
-	checkSize(t, &a, 10, 16)
-	checkSize(t, a.Resize(5, 0), 5, 16)
-	checkSize(t, a.Resize(10, 0), 10, 16)
-	checkZero(t, &a, 5)
-}
-
-func TestAccess(t *testing.T) {
-	const n = 100
-	var a Vector
-	a.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		a.Set(i, int2Value(val(i)))
-	}
-	for i := 0; i < n; i++ {
-		if elem2Value(a.At(i)) != int2Value(val(i)) {
-			t.Error(i)
-		}
-	}
-	var b Vector
-	b.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		b[i] = int2Value(val(i))
-	}
-	for i := 0; i < n; i++ {
-		if elem2Value(b[i]) != int2Value(val(i)) {
-			t.Error(i)
-		}
-	}
-}
-
-func TestInsertDeleteClear(t *testing.T) {
-	const n = 100
-	var a Vector
-
-	for i := 0; i < n; i++ {
-		if a.Len() != i {
-			t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
-		}
-		if len(a) != i {
-			t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
-		}
-		a.Insert(0, int2Value(val(i)))
-		if elem2Value(a.Last()) != int2Value(val(0)) {
-			t.Errorf("%T: B", a)
-		}
-	}
-	for i := n - 1; i >= 0; i-- {
-		if elem2Value(a.Last()) != int2Value(val(0)) {
-			t.Errorf("%T: C", a)
-		}
-		if elem2Value(a.At(0)) != int2Value(val(i)) {
-			t.Errorf("%T: D", a)
-		}
-		if elem2Value(a[0]) != int2Value(val(i)) {
-			t.Errorf("%T: D2", a)
-		}
-		a.Delete(0)
-		if a.Len() != i {
-			t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
-		}
-		if len(a) != i {
-			t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
-		}
-	}
-
-	if a.Len() != 0 {
-		t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
-	}
-	if len(a) != 0 {
-		t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
-	}
-	for i := 0; i < n; i++ {
-		a.Push(int2Value(val(i)))
-		if a.Len() != i+1 {
-			t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
-		}
-		if len(a) != i+1 {
-			t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
-		}
-		if elem2Value(a.Last()) != int2Value(val(i)) {
-			t.Errorf("%T: H", a)
-		}
-	}
-	a.Resize(0, 0)
-	if a.Len() != 0 {
-		t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
-	}
-	if len(a) != 0 {
-		t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
-	}
-
-	const m = 5
-	for j := 0; j < m; j++ {
-		a.Push(int2Value(j))
-		for i := 0; i < n; i++ {
-			x := val(i)
-			a.Push(int2Value(x))
-			if elem2Value(a.Pop()) != int2Value(x) {
-				t.Errorf("%T: J", a)
-			}
-			if a.Len() != j+1 {
-				t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
-			}
-			if len(a) != j+1 {
-				t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
-			}
-		}
-	}
-	if a.Len() != m {
-		t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
-	}
-	if len(a) != m {
-		t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
-	}
-}
-
-func verify_slice(t *testing.T, x *Vector, elt, i, j int) {
-	for k := i; k < j; k++ {
-		if elem2Value(x.At(k)) != int2Value(elt) {
-			t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2Value(x.At(k)), int2Value(elt))
-		}
-	}
-
-	s := x.Slice(i, j)
-	for k, n := 0, j-i; k < n; k++ {
-		if elem2Value(s.At(k)) != int2Value(elt) {
-			t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2Value(x.At(k)), int2Value(elt))
-		}
-	}
-}
-
-func verify_pattern(t *testing.T, x *Vector, a, b, c int) {
-	n := a + b + c
-	if x.Len() != n {
-		t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
-	}
-	if len(*x) != n {
-		t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
-	}
-	verify_slice(t, x, 0, 0, a)
-	verify_slice(t, x, 1, a, a+b)
-	verify_slice(t, x, 0, a+b, n)
-}
-
-func make_vector(elt, len int) *Vector {
-	x := new(Vector).Resize(len, 0)
-	for i := 0; i < len; i++ {
-		x.Set(i, int2Value(elt))
-	}
-	return x
-}
-
-func TestInsertVector(t *testing.T) {
-	// 1
-	a := make_vector(0, 0)
-	b := make_vector(1, 10)
-	a.InsertVector(0, b)
-	verify_pattern(t, a, 0, 10, 0)
-	// 2
-	a = make_vector(0, 10)
-	b = make_vector(1, 0)
-	a.InsertVector(5, b)
-	verify_pattern(t, a, 5, 0, 5)
-	// 3
-	a = make_vector(0, 10)
-	b = make_vector(1, 3)
-	a.InsertVector(3, b)
-	verify_pattern(t, a, 3, 3, 7)
-	// 4
-	a = make_vector(0, 10)
-	b = make_vector(1, 1000)
-	a.InsertVector(8, b)
-	verify_pattern(t, a, 8, 1000, 2)
-}
-
-func TestDo(t *testing.T) {
-	const n = 25
-	const salt = 17
-	a := new(Vector).Resize(n, 0)
-	for i := 0; i < n; i++ {
-		a.Set(i, int2Value(salt*i))
-	}
-	count := 0
-	a.Do(func(e interface{}) {
-		i := intf2Value(e)
-		if i != int2Value(count*salt) {
-			t.Error(tname(a), "value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(a), "should visit", n, "values; did visit", count)
-	}
-
-	b := new(Vector).Resize(n, 0)
-	for i := 0; i < n; i++ {
-		(*b)[i] = int2Value(salt * i)
-	}
-	count = 0
-	b.Do(func(e interface{}) {
-		i := intf2Value(e)
-		if i != int2Value(count*salt) {
-			t.Error(tname(b), "b) value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(b), "b) should visit", n, "values; did visit", count)
-	}
-
-	var c Vector
-	c.Resize(n, 0)
-	for i := 0; i < n; i++ {
-		c[i] = int2Value(salt * i)
-	}
-	count = 0
-	c.Do(func(e interface{}) {
-		i := intf2Value(e)
-		if i != int2Value(count*salt) {
-			t.Error(tname(c), "c) value at", count, "should be", count*salt, "not", i)
-		}
-		count++
-	})
-	if count != n {
-		t.Error(tname(c), "c) should visit", n, "values; did visit", count)
-	}
-
-}
-
-func TestVectorCopy(t *testing.T) {
-	// verify Copy() returns a copy, not simply a slice of the original vector
-	const Len = 10
-	var src Vector
-	for i := 0; i < Len; i++ {
-		src.Push(int2Value(i * i))
-	}
-	dest := src.Copy()
-	for i := 0; i < Len; i++ {
-		src[i] = int2Value(-1)
-		v := elem2Value(dest[i])
-		if v != int2Value(i*i) {
-			t.Error(tname(src), "expected", i*i, "got", v)
-		}
-	}
-}
diff --git a/src/pkg/crypto/aes/aes_test.go b/src/pkg/crypto/aes/aes_test.go
index 2136d44..e500c66 100644
--- a/src/pkg/crypto/aes/aes_test.go
+++ b/src/pkg/crypto/aes/aes_test.go
@@ -91,6 +91,7 @@ func TestTe(t *testing.T) {
 		s2 := mul(s, 2)
 		s3 := mul(s, 3)
 		w := s2<<24 | s<<16 | s<<8 | s3
+		te := [][256]uint32{te0, te1, te2, te3}
 		for j := 0; j < 4; j++ {
 			if x := te[j][i]; x != w {
 				t.Fatalf("te[%d][%d] = %#x, want %#x", j, i, x, w)
@@ -110,6 +111,7 @@ func TestTd(t *testing.T) {
 		sd := mul(s, 0xd)
 		se := mul(s, 0xe)
 		w := se<<24 | s9<<16 | sd<<8 | sb
+		td := [][256]uint32{td0, td1, td2, td3}
 		for j := 0; j < 4; j++ {
 			if x := td[j][i]; x != w {
 				t.Fatalf("td[%d][%d] = %#x, want %#x", j, i, x, w)
@@ -348,3 +350,17 @@ func TestCipherDecrypt(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkEncrypt(b *testing.B) {
+	b.StopTimer()
+	tt := encryptTests[0]
+	c, err := NewCipher(tt.key)
+	if err != nil {
+		b.Fatal("NewCipher:", err)
+	}
+	out := make([]byte, len(tt.in))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		c.Encrypt(out, tt.in)
+	}
+}
diff --git a/src/pkg/crypto/aes/block.go b/src/pkg/crypto/aes/block.go
index 130cd01..b930787 100644
--- a/src/pkg/crypto/aes/block.go
+++ b/src/pkg/crypto/aes/block.go
@@ -56,10 +56,10 @@ func encryptBlock(xk []uint32, dst, src []byte) {
 	nr := len(xk)/4 - 2 // - 2: one above, one more below
 	k := 4
 	for r := 0; r < nr; r++ {
-		t0 = xk[k+0] ^ te[0][s0>>24] ^ te[1][s1>>16&0xff] ^ te[2][s2>>8&0xff] ^ te[3][s3&0xff]
-		t1 = xk[k+1] ^ te[0][s1>>24] ^ te[1][s2>>16&0xff] ^ te[2][s3>>8&0xff] ^ te[3][s0&0xff]
-		t2 = xk[k+2] ^ te[0][s2>>24] ^ te[1][s3>>16&0xff] ^ te[2][s0>>8&0xff] ^ te[3][s1&0xff]
-		t3 = xk[k+3] ^ te[0][s3>>24] ^ te[1][s0>>16&0xff] ^ te[2][s1>>8&0xff] ^ te[3][s2&0xff]
+		t0 = xk[k+0] ^ te0[uint8(s0>>24)] ^ te1[uint8(s1>>16)] ^ te2[uint8(s2>>8)] ^ te3[uint8(s3)]
+		t1 = xk[k+1] ^ te0[uint8(s1>>24)] ^ te1[uint8(s2>>16)] ^ te2[uint8(s3>>8)] ^ te3[uint8(s0)]
+		t2 = xk[k+2] ^ te0[uint8(s2>>24)] ^ te1[uint8(s3>>16)] ^ te2[uint8(s0>>8)] ^ te3[uint8(s1)]
+		t3 = xk[k+3] ^ te0[uint8(s3>>24)] ^ te1[uint8(s0>>16)] ^ te2[uint8(s1>>8)] ^ te3[uint8(s2)]
 		k += 4
 		s0, s1, s2, s3 = t0, t1, t2, t3
 	}
@@ -101,10 +101,10 @@ func decryptBlock(xk []uint32, dst, src []byte) {
 	nr := len(xk)/4 - 2 // - 2: one above, one more below
 	k := 4
 	for r := 0; r < nr; r++ {
-		t0 = xk[k+0] ^ td[0][s0>>24] ^ td[1][s3>>16&0xff] ^ td[2][s2>>8&0xff] ^ td[3][s1&0xff]
-		t1 = xk[k+1] ^ td[0][s1>>24] ^ td[1][s0>>16&0xff] ^ td[2][s3>>8&0xff] ^ td[3][s2&0xff]
-		t2 = xk[k+2] ^ td[0][s2>>24] ^ td[1][s1>>16&0xff] ^ td[2][s0>>8&0xff] ^ td[3][s3&0xff]
-		t3 = xk[k+3] ^ td[0][s3>>24] ^ td[1][s2>>16&0xff] ^ td[2][s1>>8&0xff] ^ td[3][s0&0xff]
+		t0 = xk[k+0] ^ td0[uint8(s0>>24)] ^ td1[uint8(s3>>16)] ^ td2[uint8(s2>>8)] ^ td3[uint8(s1)]
+		t1 = xk[k+1] ^ td0[uint8(s1>>24)] ^ td1[uint8(s0>>16)] ^ td2[uint8(s3>>8)] ^ td3[uint8(s2)]
+		t2 = xk[k+2] ^ td0[uint8(s2>>24)] ^ td1[uint8(s1>>16)] ^ td2[uint8(s0>>8)] ^ td3[uint8(s3)]
+		t3 = xk[k+3] ^ td0[uint8(s3>>24)] ^ td1[uint8(s2>>16)] ^ td2[uint8(s1>>8)] ^ td3[uint8(s0)]
 		k += 4
 		s0, s1, s2, s3 = t0, t1, t2, t3
 	}
@@ -168,7 +168,7 @@ func expandKey(key []byte, enc, dec []uint32) {
 		for j := 0; j < 4; j++ {
 			x := enc[ei+j]
 			if i > 0 && i+4 < n {
-				x = td[0][sbox0[x>>24]] ^ td[1][sbox0[x>>16&0xff]] ^ td[2][sbox0[x>>8&0xff]] ^ td[3][sbox0[x&0xff]]
+				x = td0[sbox0[x>>24]] ^ td1[sbox0[x>>16&0xff]] ^ td2[sbox0[x>>8&0xff]] ^ td3[sbox0[x&0xff]]
 			}
 			dec[i+j] = x
 		}
diff --git a/src/pkg/crypto/aes/cipher.go b/src/pkg/crypto/aes/cipher.go
index 7322353..28752e7 100644
--- a/src/pkg/crypto/aes/cipher.go
+++ b/src/pkg/crypto/aes/cipher.go
@@ -4,10 +4,7 @@
 
 package aes
 
-import (
-	"os"
-	"strconv"
-)
+import "strconv"
 
 // The AES block size in bytes.
 const BlockSize = 16
@@ -20,7 +17,7 @@ type Cipher struct {
 
 type KeySizeError int
 
-func (k KeySizeError) String() string {
+func (k KeySizeError) Error() string {
 	return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
 }
 
@@ -28,7 +25,7 @@ func (k KeySizeError) String() string {
 // The key argument should be the AES key,
 // either 16, 24, or 32 bytes to select
 // AES-128, AES-192, or AES-256.
-func NewCipher(key []byte) (*Cipher, os.Error) {
+func NewCipher(key []byte) (*Cipher, error) {
 	k := len(key)
 	switch k {
 	default:
@@ -44,7 +41,7 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
 }
 
 // BlockSize returns the AES block size, 16 bytes.
-// It is necessary to satisfy the Cipher interface in the
+// It is necessary to satisfy the Block interface in the
 // package "crypto/cipher".
 func (c *Cipher) BlockSize() int { return BlockSize }
 
diff --git a/src/pkg/crypto/aes/const.go b/src/pkg/crypto/aes/const.go
index 25acd0d..f0b4eab 100644
--- a/src/pkg/crypto/aes/const.go
+++ b/src/pkg/crypto/aes/const.go
@@ -80,283 +80,279 @@ var sbox1 = [256]byte{
 // Lookup tables for encryption.
 // These can be recomputed by adapting the tests in aes_test.go.
 
-var te = [4][256]uint32{
-	{
-		0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554,
-		0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a,
-		0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,
-		0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
-		0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f,
-		0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
-		0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5,
-		0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
-		0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
-		0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497,
-		0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed,
-		0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
-		0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594,
-		0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3,
-		0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,
-		0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
-		0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739,
-		0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
-		0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883,
-		0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76,
-		0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,
-		0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b,
-		0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0,
-		0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
-		0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651,
-		0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
-		0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
-		0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9,
-		0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7,
-		0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
-		0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8,
-		0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a,
-	},
-	{
-		0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5,
-		0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676,
-		0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0,
-		0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0,
-		0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc,
-		0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515,
-		0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a,
-		0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575,
-		0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0,
-		0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484,
-		0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b,
-		0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf,
-		0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585,
-		0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8,
-		0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5,
-		0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2,
-		0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717,
-		0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373,
-		0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888,
-		0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb,
-		0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c,
-		0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979,
-		0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9,
-		0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808,
-		0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6,
-		0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a,
-		0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e,
-		0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e,
-		0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494,
-		0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf,
-		0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868,
-		0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616,
-	},
-	{
-		0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5,
-		0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76,
-		0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0,
-		0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0,
-		0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc,
-		0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15,
-		0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a,
-		0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75,
-		0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0,
-		0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384,
-		0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b,
-		0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf,
-		0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185,
-		0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8,
-		0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5,
-		0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2,
-		0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17,
-		0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673,
-		0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88,
-		0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb,
-		0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c,
-		0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279,
-		0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9,
-		0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008,
-		0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6,
-		0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a,
-		0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e,
-		0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e,
-		0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394,
-		0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df,
-		0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068,
-		0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16,
-	},
-	{
-		0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491,
-		0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec,
-		0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb,
-		0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b,
-		0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83,
-		0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a,
-		0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f,
-		0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea,
-		0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b,
-		0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713,
-		0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6,
-		0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85,
-		0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411,
-		0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b,
-		0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1,
-		0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf,
-		0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e,
-		0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6,
-		0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b,
-		0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad,
-		0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8,
-		0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2,
-		0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049,
-		0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810,
-		0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197,
-		0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f,
-		0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c,
-		0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927,
-		0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733,
-		0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5,
-		0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0,
-		0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
-	},
+var te0 = [256]uint32{
+	0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554,
+	0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a,
+	0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,
+	0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
+	0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f,
+	0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
+	0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5,
+	0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
+	0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
+	0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497,
+	0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed,
+	0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
+	0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594,
+	0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3,
+	0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,
+	0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
+	0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739,
+	0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
+	0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883,
+	0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76,
+	0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,
+	0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b,
+	0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0,
+	0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
+	0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651,
+	0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
+	0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
+	0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9,
+	0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7,
+	0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
+	0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8,
+	0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a,
+}
+var te1 = [256]uint32{
+	0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5,
+	0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676,
+	0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0,
+	0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0,
+	0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc,
+	0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515,
+	0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a,
+	0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575,
+	0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0,
+	0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484,
+	0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b,
+	0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf,
+	0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585,
+	0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8,
+	0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5,
+	0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2,
+	0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717,
+	0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373,
+	0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888,
+	0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb,
+	0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c,
+	0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979,
+	0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9,
+	0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808,
+	0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6,
+	0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a,
+	0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e,
+	0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e,
+	0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494,
+	0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf,
+	0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868,
+	0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616,
+}
+var te2 = [256]uint32{
+	0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5,
+	0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76,
+	0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0,
+	0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0,
+	0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc,
+	0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15,
+	0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a,
+	0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75,
+	0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0,
+	0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384,
+	0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b,
+	0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf,
+	0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185,
+	0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8,
+	0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5,
+	0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2,
+	0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17,
+	0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673,
+	0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88,
+	0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb,
+	0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c,
+	0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279,
+	0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9,
+	0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008,
+	0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6,
+	0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a,
+	0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e,
+	0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e,
+	0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394,
+	0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df,
+	0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068,
+	0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16,
+}
+var te3 = [256]uint32{
+	0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491,
+	0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec,
+	0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb,
+	0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b,
+	0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83,
+	0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a,
+	0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f,
+	0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea,
+	0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b,
+	0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713,
+	0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6,
+	0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85,
+	0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411,
+	0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b,
+	0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1,
+	0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf,
+	0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e,
+	0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6,
+	0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b,
+	0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad,
+	0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8,
+	0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2,
+	0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049,
+	0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810,
+	0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197,
+	0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f,
+	0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c,
+	0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927,
+	0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733,
+	0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5,
+	0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0,
+	0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
 }
 
 // Lookup tables for decryption.
 // These can be recomputed by adapting the tests in aes_test.go.
 
-var td = [4][256]uint32{
-	{
-		0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393,
-		0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f,
-		0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6,
-		0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
-		0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4,
-		0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94,
-		0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a,
-		0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
-		0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a,
-		0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051,
-		0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff,
-		0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb,
-		0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e,
-		0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a,
-		0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16,
-		0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
-		0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34,
-		0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
-		0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0,
-		0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef,
-		0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4,
-		0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5,
-		0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b,
-		0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
-		0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0,
-		0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
-		0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f,
-		0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713,
-		0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c,
-		0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86,
-		0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541,
-		0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742,
-	},
-	{
-		0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303,
-		0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3,
-		0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9,
-		0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8,
-		0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a,
-		0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b,
-		0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab,
-		0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682,
-		0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe,
-		0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10,
-		0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015,
-		0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee,
-		0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72,
-		0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e,
-		0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a,
-		0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9,
-		0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e,
-		0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611,
-		0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3,
-		0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390,
-		0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf,
-		0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af,
-		0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb,
-		0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8,
-		0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266,
-		0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6,
-		0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551,
-		0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647,
-		0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1,
-		0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db,
-		0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95,
-		0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857,
-	},
-	{
-		0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3,
-		0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562,
-		0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3,
-		0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9,
-		0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce,
-		0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908,
-		0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655,
-		0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16,
-		0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6,
-		0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e,
-		0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050,
-		0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8,
-		0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a,
-		0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436,
-		0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12,
-		0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e,
-		0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb,
-		0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6,
-		0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1,
-		0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233,
-		0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad,
-		0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3,
-		0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b,
-		0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15,
-		0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2,
-		0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791,
-		0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665,
-		0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6,
-		0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47,
-		0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844,
-		0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d,
-		0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8,
-	},
-	{
-		0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b,
-		0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5,
-		0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b,
-		0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e,
-		0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d,
-		0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9,
-		0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66,
-		0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced,
-		0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4,
-		0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd,
-		0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60,
-		0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79,
-		0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c,
-		0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24,
-		0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c,
-		0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814,
-		0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b,
-		0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084,
-		0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077,
-		0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22,
-		0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f,
-		0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582,
-		0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb,
-		0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef,
-		0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035,
-		0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17,
-		0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46,
-		0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d,
-		0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a,
-		0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678,
-		0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff,
-		0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0,
-	},
+var td0 = [256]uint32{
+	0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393,
+	0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f,
+	0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6,
+	0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
+	0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4,
+	0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94,
+	0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a,
+	0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
+	0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a,
+	0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051,
+	0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff,
+	0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb,
+	0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e,
+	0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a,
+	0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16,
+	0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
+	0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34,
+	0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
+	0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0,
+	0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef,
+	0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4,
+	0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5,
+	0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b,
+	0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
+	0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0,
+	0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
+	0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f,
+	0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713,
+	0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c,
+	0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86,
+	0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541,
+	0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742,
+}
+var td1 = [256]uint32{
+	0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303,
+	0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3,
+	0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9,
+	0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8,
+	0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a,
+	0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b,
+	0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab,
+	0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682,
+	0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe,
+	0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10,
+	0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015,
+	0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee,
+	0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72,
+	0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e,
+	0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a,
+	0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9,
+	0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e,
+	0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611,
+	0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3,
+	0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390,
+	0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf,
+	0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af,
+	0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb,
+	0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8,
+	0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266,
+	0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6,
+	0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551,
+	0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647,
+	0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1,
+	0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db,
+	0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95,
+	0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857,
+}
+var td2 = [256]uint32{
+	0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3,
+	0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562,
+	0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3,
+	0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9,
+	0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce,
+	0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908,
+	0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655,
+	0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16,
+	0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6,
+	0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e,
+	0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050,
+	0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8,
+	0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a,
+	0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436,
+	0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12,
+	0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e,
+	0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb,
+	0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6,
+	0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1,
+	0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233,
+	0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad,
+	0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3,
+	0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b,
+	0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15,
+	0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2,
+	0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791,
+	0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665,
+	0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6,
+	0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47,
+	0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844,
+	0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d,
+	0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8,
+}
+var td3 = [256]uint32{
+	0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b,
+	0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5,
+	0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b,
+	0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e,
+	0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d,
+	0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9,
+	0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66,
+	0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced,
+	0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4,
+	0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd,
+	0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60,
+	0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79,
+	0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c,
+	0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24,
+	0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c,
+	0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814,
+	0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b,
+	0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084,
+	0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077,
+	0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22,
+	0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f,
+	0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582,
+	0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb,
+	0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef,
+	0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035,
+	0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17,
+	0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46,
+	0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d,
+	0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a,
+	0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678,
+	0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff,
+	0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0,
 }
diff --git a/src/pkg/crypto/bcrypt/Makefile b/src/pkg/crypto/bcrypt/Makefile
deleted file mode 100644
index 3c83d9c..0000000
--- a/src/pkg/crypto/bcrypt/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/bcrypt
-GOFILES=\
-	base64.go \
-	bcrypt.go
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/bcrypt/base64.go b/src/pkg/crypto/bcrypt/base64.go
deleted file mode 100644
index ed6cea7..0000000
--- a/src/pkg/crypto/bcrypt/base64.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2011 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 bcrypt
-
-import (
-	"encoding/base64"
-	"os"
-)
-
-const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-
-var bcEncoding = base64.NewEncoding(alphabet)
-
-func base64Encode(src []byte) []byte {
-	n := bcEncoding.EncodedLen(len(src))
-	dst := make([]byte, n)
-	bcEncoding.Encode(dst, src)
-	for dst[n-1] == '=' {
-		n--
-	}
-	return dst[:n]
-}
-
-func base64Decode(src []byte) ([]byte, os.Error) {
-	numOfEquals := 4 - (len(src) % 4)
-	for i := 0; i < numOfEquals; i++ {
-		src = append(src, '=')
-	}
-
-	dst := make([]byte, bcEncoding.DecodedLen(len(src)))
-	n, err := bcEncoding.Decode(dst, src)
-	if err != nil {
-		return nil, err
-	}
-	return dst[:n], nil
-}
diff --git a/src/pkg/crypto/bcrypt/bcrypt.go b/src/pkg/crypto/bcrypt/bcrypt.go
deleted file mode 100644
index 1e8ccfa..0000000
--- a/src/pkg/crypto/bcrypt/bcrypt.go
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2011 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 bcrypt implements Provos and Mazières's bcrypt adapative hashing
-// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
-package bcrypt
-
-// The code is a port of Provos and Mazières's C implementation. 
-import (
-	"crypto/blowfish"
-	"crypto/rand"
-	"crypto/subtle"
-	"fmt"
-	"io"
-	"os"
-	"strconv"
-)
-
-const (
-	MinCost     int = 4  // the minimum allowable cost as passed in to GenerateFromPassword
-	MaxCost     int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
-	DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
-)
-
-// The error returned from CompareHashAndPassword when a password and hash do
-// not match.
-var MismatchedHashAndPasswordError = os.NewError("crypto/bcrypt: hashedPassword is not the hash of the given password")
-
-// The error returned from CompareHashAndPassword when a hash is too short to
-// be a bcrypt hash.
-var HashTooShortError = os.NewError("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
-
-// The error returned from CompareHashAndPassword when a hash was created with
-// a bcrypt algorithm newer than this implementation.
-type HashVersionTooNewError byte
-
-func (hv HashVersionTooNewError) String() string {
-	return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
-}
-
-// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
-type InvalidHashPrefixError byte
-
-func (ih InvalidHashPrefixError) String() string {
-	return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
-}
-
-type InvalidCostError int
-
-func (ic InvalidCostError) String() string {
-	return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
-}
-
-const (
-	majorVersion       = '2'
-	minorVersion       = 'a'
-	maxSaltSize        = 16
-	maxCryptedHashSize = 23
-	encodedSaltSize    = 22
-	encodedHashSize    = 31
-	minHashSize        = 59
-)
-
-// magicCipherData is an IV for the 64 Blowfish encryption calls in
-// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
-var magicCipherData = []byte{
-	0x4f, 0x72, 0x70, 0x68,
-	0x65, 0x61, 0x6e, 0x42,
-	0x65, 0x68, 0x6f, 0x6c,
-	0x64, 0x65, 0x72, 0x53,
-	0x63, 0x72, 0x79, 0x44,
-	0x6f, 0x75, 0x62, 0x74,
-}
-
-type hashed struct {
-	hash  []byte
-	salt  []byte
-	cost  uint32 // allowed range is MinCost to MaxCost
-	major byte
-	minor byte
-}
-
-// GenerateFromPassword returns the bcrypt hash of the password at the given
-// cost. If the cost given is less than MinCost, the cost will be set to
-// MinCost, instead. Use CompareHashAndPassword, as defined in this package,
-// to compare the returned hashed password with its cleartext version.
-func GenerateFromPassword(password []byte, cost int) ([]byte, os.Error) {
-	p, err := newFromPassword(password, cost)
-	if err != nil {
-		return nil, err
-	}
-	return p.Hash(), nil
-}
-
-// CompareHashAndPassword compares a bcrypt hashed password with its possible
-// plaintext equivalent. Note: Using bytes.Equal for this job is
-// insecure. Returns nil on success, or an error on failure.
-func CompareHashAndPassword(hashedPassword, password []byte) os.Error {
-	p, err := newFromHash(hashedPassword)
-	if err != nil {
-		return err
-	}
-
-	otherHash, err := bcrypt(password, p.cost, p.salt)
-	if err != nil {
-		return err
-	}
-
-	otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
-	if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
-		return nil
-	}
-
-	return MismatchedHashAndPasswordError
-}
-
-func newFromPassword(password []byte, cost int) (*hashed, os.Error) {
-	if cost < MinCost {
-		cost = DefaultCost
-	}
-	p := new(hashed)
-	p.major = majorVersion
-	p.minor = minorVersion
-
-	err := checkCost(cost)
-	if err != nil {
-		return nil, err
-	}
-	p.cost = uint32(cost)
-
-	unencodedSalt := make([]byte, maxSaltSize)
-	_, err = io.ReadFull(rand.Reader, unencodedSalt)
-	if err != nil {
-		return nil, err
-	}
-
-	p.salt = base64Encode(unencodedSalt)
-	hash, err := bcrypt(password, p.cost, p.salt)
-	if err != nil {
-		return nil, err
-	}
-	p.hash = hash
-	return p, err
-}
-
-func newFromHash(hashedSecret []byte) (*hashed, os.Error) {
-	if len(hashedSecret) < minHashSize {
-		return nil, HashTooShortError
-	}
-	p := new(hashed)
-	n, err := p.decodeVersion(hashedSecret)
-	if err != nil {
-		return nil, err
-	}
-	hashedSecret = hashedSecret[n:]
-	n, err = p.decodeCost(hashedSecret)
-	if err != nil {
-		return nil, err
-	}
-	hashedSecret = hashedSecret[n:]
-
-	// The "+2" is here because we'll have to append at most 2 '=' to the salt
-	// when base64 decoding it in expensiveBlowfishSetup().
-	p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
-	copy(p.salt, hashedSecret[:encodedSaltSize])
-
-	hashedSecret = hashedSecret[encodedSaltSize:]
-	p.hash = make([]byte, len(hashedSecret))
-	copy(p.hash, hashedSecret)
-
-	return p, nil
-}
-
-func bcrypt(password []byte, cost uint32, salt []byte) ([]byte, os.Error) {
-	cipherData := make([]byte, len(magicCipherData))
-	copy(cipherData, magicCipherData)
-
-	c, err := expensiveBlowfishSetup(password, cost, salt)
-	if err != nil {
-		return nil, err
-	}
-
-	for i := 0; i < 24; i += 8 {
-		for j := 0; j < 64; j++ {
-			c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
-		}
-	}
-
-	// Bug compatibility with C bcrypt implementations. We only encode 23 of
-	// the 24 bytes encrypted.
-	hsh := base64Encode(cipherData[:maxCryptedHashSize])
-	return hsh, nil
-}
-
-func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, os.Error) {
-
-	csalt, err := base64Decode(salt)
-	if err != nil {
-		return nil, err
-	}
-
-	// Bug compatibility with C bcrypt implementations. They use the trailing
-	// NULL in the key string during expansion.
-	ckey := append(key, 0)
-
-	c, err := blowfish.NewSaltedCipher(ckey, csalt)
-	if err != nil {
-		return nil, err
-	}
-
-	rounds := 1 << cost
-	for i := 0; i < rounds; i++ {
-		blowfish.ExpandKey(ckey, c)
-		blowfish.ExpandKey(csalt, c)
-	}
-
-	return c, nil
-}
-
-func (p *hashed) Hash() []byte {
-	arr := make([]byte, 60)
-	arr[0] = '$'
-	arr[1] = p.major
-	n := 2
-	if p.minor != 0 {
-		arr[2] = p.minor
-		n = 3
-	}
-	arr[n] = '$'
-	n += 1
-	copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
-	n += 2
-	arr[n] = '$'
-	n += 1
-	copy(arr[n:], p.salt)
-	n += encodedSaltSize
-	copy(arr[n:], p.hash)
-	n += encodedHashSize
-	return arr[:n]
-}
-
-func (p *hashed) decodeVersion(sbytes []byte) (int, os.Error) {
-	if sbytes[0] != '$' {
-		return -1, InvalidHashPrefixError(sbytes[0])
-	}
-	if sbytes[1] > majorVersion {
-		return -1, HashVersionTooNewError(sbytes[1])
-	}
-	p.major = sbytes[1]
-	n := 3
-	if sbytes[2] != '$' {
-		p.minor = sbytes[2]
-		n++
-	}
-	return n, nil
-}
-
-// sbytes should begin where decodeVersion left off.
-func (p *hashed) decodeCost(sbytes []byte) (int, os.Error) {
-	cost, err := strconv.Atoi(string(sbytes[0:2]))
-	if err != nil {
-		return -1, err
-	}
-	err = checkCost(cost)
-	if err != nil {
-		return -1, err
-	}
-	p.cost = uint32(cost)
-	return 3, nil
-}
-
-func (p *hashed) String() string {
-	return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
-}
-
-func checkCost(cost int) os.Error {
-	if cost < MinCost || cost > MaxCost {
-		return InvalidCostError(cost)
-	}
-	return nil
-}
diff --git a/src/pkg/crypto/bcrypt/bcrypt_test.go b/src/pkg/crypto/bcrypt/bcrypt_test.go
deleted file mode 100644
index 89eca0a..0000000
--- a/src/pkg/crypto/bcrypt/bcrypt_test.go
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2011 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 bcrypt
-
-import (
-	"bytes"
-	"os"
-	"testing"
-)
-
-func TestBcryptingIsEasy(t *testing.T) {
-	pass := []byte("mypassword")
-	hp, err := GenerateFromPassword(pass, 0)
-	if err != nil {
-		t.Fatalf("GenerateFromPassword error: %s", err)
-	}
-
-	if CompareHashAndPassword(hp, pass) != nil {
-		t.Errorf("%v should hash %s correctly", hp, pass)
-	}
-
-	notPass := "notthepass"
-	err = CompareHashAndPassword(hp, []byte(notPass))
-	if err != MismatchedHashAndPasswordError {
-		t.Errorf("%v and %s should be mismatched", hp, notPass)
-	}
-}
-
-func TestBcryptingIsCorrect(t *testing.T) {
-	pass := []byte("allmine")
-	salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
-	expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
-
-	hash, err := bcrypt(pass, 10, salt)
-	if err != nil {
-		t.Fatalf("bcrypt blew up: %v", err)
-	}
-	if !bytes.HasSuffix(expectedHash, hash) {
-		t.Errorf("%v should be the suffix of %v", hash, expectedHash)
-	}
-
-	h, err := newFromHash(expectedHash)
-	if err != nil {
-		t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
-	}
-
-	// This is not the safe way to compare these hashes. We do this only for
-	// testing clarity. Use bcrypt.CompareHashAndPassword()
-	if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
-		t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
-	}
-}
-
-func TestTooLongPasswordsWork(t *testing.T) {
-	salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
-	// One byte over the usual 56 byte limit that blowfish has
-	tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
-	tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
-	hash, err := bcrypt(tooLongPass, 10, salt)
-	if err != nil {
-		t.Fatalf("bcrypt blew up on long password: %v", err)
-	}
-	if !bytes.HasSuffix(tooLongExpected, hash) {
-		t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
-	}
-}
-
-type InvalidHashTest struct {
-	err  os.Error
-	hash []byte
-}
-
-var invalidTests = []InvalidHashTest{
-	{HashTooShortError, []byte("$2a$10$fooo")},
-	{HashTooShortError, []byte("$2a")},
-	{HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
-	{InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
-	{InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
-}
-
-func TestInvalidHashErrors(t *testing.T) {
-	check := func(name string, expected, err os.Error) {
-		if err == nil {
-			t.Errorf("%s: Should have returned an error", name)
-		}
-		if err != nil && err != expected {
-			t.Errorf("%s gave err %v but should have given %v", name, err.String(), expected.String())
-		}
-	}
-	for _, iht := range invalidTests {
-		_, err := newFromHash(iht.hash)
-		check("newFromHash", iht.err, err)
-		err = CompareHashAndPassword(iht.hash, []byte("anything"))
-		check("CompareHashAndPassword", iht.err, err)
-	}
-}
-
-func TestUnpaddedBase64Encoding(t *testing.T) {
-	original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
-	encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
-
-	encoded := base64Encode(original)
-
-	if !bytes.Equal(encodedOriginal, encoded) {
-		t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
-	}
-
-	decoded, err := base64Decode(encodedOriginal)
-	if err != nil {
-		t.Fatalf("base64Decode blew up: %s", err)
-	}
-
-	if !bytes.Equal(decoded, original) {
-		t.Errorf("Decoded %v should have equaled %v", decoded, original)
-	}
-}
-
-func TestCost(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	pass := []byte("mypassword")
-
-	for c := 0; c < MinCost; c++ {
-		p, _ := newFromPassword(pass, c)
-		if p.cost != uint32(DefaultCost) {
-			t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
-		}
-	}
-
-	p, _ := newFromPassword(pass, 14)
-	if p.cost != 14 {
-		t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
-	}
-
-	hp, _ := newFromHash(p.Hash())
-	if p.cost != hp.cost {
-		t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
-	}
-
-	_, err := newFromPassword(pass, 32)
-	if err == nil {
-		t.Fatalf("newFromPassword: should return a cost error")
-	}
-	if err != InvalidCostError(32) {
-		t.Errorf("newFromPassword: should return cost error, got %#v", err)
-	}
-}
-
-func TestCostReturnsWithLeadingZeroes(t *testing.T) {
-	hp, _ := newFromPassword([]byte("abcdefgh"), 7)
-	cost := hp.Hash()[4:7]
-	expected := []byte("07$")
-
-	if !bytes.Equal(expected, cost) {
-		t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
-	}
-}
-
-func TestMinorNotRequired(t *testing.T) {
-	noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
-	h, err := newFromHash(noMinorHash)
-	if err != nil {
-		t.Fatalf("No minor hash blew up: %s", err)
-	}
-	if h.minor != 0 {
-		t.Errorf("Should leave minor version at 0, but was %d", h.minor)
-	}
-
-	if !bytes.Equal(noMinorHash, h.Hash()) {
-		t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
-	}
-}
-
-func BenchmarkEqual(b *testing.B) {
-	b.StopTimer()
-	passwd := []byte("somepasswordyoulike")
-	hash, _ := GenerateFromPassword(passwd, 10)
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		CompareHashAndPassword(hash, passwd)
-	}
-}
-
-func BenchmarkGeneration(b *testing.B) {
-	b.StopTimer()
-	passwd := []byte("mylongpassword1234")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		GenerateFromPassword(passwd, 10)
-	}
-}
diff --git a/src/pkg/crypto/blowfish/Makefile b/src/pkg/crypto/blowfish/Makefile
deleted file mode 100644
index f370ab2..0000000
--- a/src/pkg/crypto/blowfish/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/blowfish
-GOFILES=\
-	block.go\
-	cipher.go\
-	const.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/blowfish/block.go b/src/pkg/crypto/blowfish/block.go
deleted file mode 100644
index 326292d..0000000
--- a/src/pkg/crypto/blowfish/block.go
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2010 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 blowfish
-
-// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
-// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
-// pi and substitution tables for calls to Encrypt. This is used, primarily,
-// by the bcrypt package to reuse the Blowfish key schedule during its
-// set up. It's unlikely that you need to use this directly.
-func ExpandKey(key []byte, c *Cipher) {
-	j := 0
-	for i := 0; i < 18; i++ {
-		var d uint32
-		for k := 0; k < 4; k++ {
-			d = d<<8 | uint32(key[j])&0x000000FF
-			j++
-			if j >= len(key) {
-				j = 0
-			}
-		}
-		c.p[i] ^= d
-	}
-
-	var l, r uint32
-	for i := 0; i < 18; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.p[i], c.p[i+1] = l, r
-	}
-
-	for i := 0; i < 256; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.s0[i], c.s0[i+1] = l, r
-	}
-	for i := 0; i < 256; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.s1[i], c.s1[i+1] = l, r
-	}
-	for i := 0; i < 256; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.s2[i], c.s2[i+1] = l, r
-	}
-	for i := 0; i < 256; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.s3[i], c.s3[i+1] = l, r
-	}
-}
-
-// This is similar to ExpandKey, but folds the salt during the key
-// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
-// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
-// and specializing it here is useful.
-func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
-	j := 0
-	expandedKey := make([]uint32, 18)
-	for i := 0; i < 18; i++ {
-		var d uint32
-		for k := 0; k < 4; k++ {
-			d = d<<8 | uint32(key[j])&0x000000FF
-			j++
-			if j >= len(key) {
-				j = 0
-			}
-		}
-		expandedKey[i] = d
-		c.p[i] ^= d
-	}
-
-	j = 0
-	expandedSalt := make([]uint32, 18)
-	for i := 0; i < 18; i++ {
-		var d uint32
-		for k := 0; k < 4; k++ {
-			d = d<<8 | uint32(salt[j])&0x000000FF
-			j++
-			if j >= len(salt) {
-				j = 0
-			}
-		}
-		expandedSalt[i] = d
-	}
-
-	var l, r uint32
-	for i := 0; i < 18; i += 2 {
-		l ^= expandedSalt[i&2]
-		r ^= expandedSalt[(i&2)+1]
-		l, r = encryptBlock(l, r, c)
-		c.p[i], c.p[i+1] = l, r
-	}
-
-	for i := 0; i < 256; i += 4 {
-		l ^= expandedSalt[2]
-		r ^= expandedSalt[3]
-		l, r = encryptBlock(l, r, c)
-		c.s0[i], c.s0[i+1] = l, r
-
-		l ^= expandedSalt[0]
-		r ^= expandedSalt[1]
-		l, r = encryptBlock(l, r, c)
-		c.s0[i+2], c.s0[i+3] = l, r
-
-	}
-
-	for i := 0; i < 256; i += 4 {
-		l ^= expandedSalt[2]
-		r ^= expandedSalt[3]
-		l, r = encryptBlock(l, r, c)
-		c.s1[i], c.s1[i+1] = l, r
-
-		l ^= expandedSalt[0]
-		r ^= expandedSalt[1]
-		l, r = encryptBlock(l, r, c)
-		c.s1[i+2], c.s1[i+3] = l, r
-	}
-
-	for i := 0; i < 256; i += 4 {
-		l ^= expandedSalt[2]
-		r ^= expandedSalt[3]
-		l, r = encryptBlock(l, r, c)
-		c.s2[i], c.s2[i+1] = l, r
-
-		l ^= expandedSalt[0]
-		r ^= expandedSalt[1]
-		l, r = encryptBlock(l, r, c)
-		c.s2[i+2], c.s2[i+3] = l, r
-	}
-
-	for i := 0; i < 256; i += 4 {
-		l ^= expandedSalt[2]
-		r ^= expandedSalt[3]
-		l, r = encryptBlock(l, r, c)
-		c.s3[i], c.s3[i+1] = l, r
-
-		l ^= expandedSalt[0]
-		r ^= expandedSalt[1]
-		l, r = encryptBlock(l, r, c)
-		c.s3[i+2], c.s3[i+3] = l, r
-	}
-}
-
-func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
-	xl, xr := l, r
-	xl ^= c.p[0]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
-	xr ^= c.p[17]
-	return xr, xl
-}
-
-func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
-	xl, xr := l, r
-	xl ^= c.p[17]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
-	xr ^= c.p[0]
-	return xr, xl
-}
-
-func zero(x []uint32) {
-	for i := range x {
-		x[i] = 0
-	}
-}
diff --git a/src/pkg/crypto/blowfish/blowfish_test.go b/src/pkg/crypto/blowfish/blowfish_test.go
deleted file mode 100644
index 1038d2e..0000000
--- a/src/pkg/crypto/blowfish/blowfish_test.go
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2010 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 blowfish
-
-import (
-	"testing"
-)
-
-type CryptTest struct {
-	key []byte
-	in  []byte
-	out []byte
-}
-
-// Test vector values are from http://www.schneier.com/code/vectors.txt.
-var encryptTests = []CryptTest{
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
-	{
-		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-		[]byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
-	{
-		[]byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
-		[]byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
-	{
-		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
-		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
-		[]byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
-
-	{
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
-		[]byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
-	{
-		[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-		[]byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
-	{
-		[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-		[]byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
-	{
-		[]byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
-		[]byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
-		[]byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
-	{
-		[]byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
-		[]byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
-		[]byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
-	{
-		[]byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
-		[]byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
-		[]byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
-	{
-		[]byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
-		[]byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
-		[]byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
-	{
-		[]byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
-		[]byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
-		[]byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
-	{
-		[]byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
-		[]byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
-		[]byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
-	{
-		[]byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
-		[]byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
-		[]byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
-	{
-		[]byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
-		[]byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
-		[]byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
-	{
-		[]byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
-		[]byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
-		[]byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
-	{
-		[]byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
-		[]byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
-		[]byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
-	{
-		[]byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
-		[]byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
-		[]byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
-	{
-		[]byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
-		[]byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
-		[]byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
-	{
-		[]byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
-		[]byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
-		[]byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
-	{
-		[]byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
-		[]byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
-		[]byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
-	{
-		[]byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
-		[]byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
-		[]byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
-	{
-		[]byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
-		[]byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
-		[]byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
-	{
-		[]byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
-		[]byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
-		[]byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
-	{
-		[]byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
-		[]byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
-		[]byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
-	{
-		[]byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
-		[]byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
-		[]byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
-	{
-		[]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-		[]byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
-	{
-		[]byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-		[]byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
-	{
-		[]byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-		[]byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-		[]byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
-	{
-		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
-	{
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
-	{
-		[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
-		[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-		[]byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
-}
-
-func TestCipherEncrypt(t *testing.T) {
-	for i, tt := range encryptTests {
-		c, err := NewCipher(tt.key)
-		if err != nil {
-			t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
-			continue
-		}
-		ct := make([]byte, len(tt.out))
-		c.Encrypt(ct, tt.in)
-		for j, v := range ct {
-			if v != tt.out[j] {
-				t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
-				break
-			}
-		}
-	}
-}
-
-func TestCipherDecrypt(t *testing.T) {
-	for i, tt := range encryptTests {
-		c, err := NewCipher(tt.key)
-		if err != nil {
-			t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
-			continue
-		}
-		pt := make([]byte, len(tt.in))
-		c.Decrypt(pt, tt.out)
-		for j, v := range pt {
-			if v != tt.in[j] {
-				t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
-				break
-			}
-		}
-	}
-}
-
-func TestSaltedCipherKeyLength(t *testing.T) {
-	var key []byte
-	for i := 0; i < 4; i++ {
-		_, err := NewSaltedCipher(key, []byte{'a'})
-		if err != KeySizeError(i) {
-			t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(i))
-		}
-		key = append(key, 'a')
-	}
-
-	// A 57-byte key. One over the typical blowfish restriction.
-	key = []byte("012345678901234567890123456789012345678901234567890123456")
-	_, err := NewSaltedCipher(key, []byte{'a'})
-	if err != nil {
-		t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
-	}
-}
diff --git a/src/pkg/crypto/blowfish/cipher.go b/src/pkg/crypto/blowfish/cipher.go
deleted file mode 100644
index 3439825..0000000
--- a/src/pkg/crypto/blowfish/cipher.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2010 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 blowfish implements Bruce Schneier's Blowfish encryption algorithm.
-package blowfish
-
-// The code is a port of Bruce Schneier's C implementation.
-// See http://www.schneier.com/blowfish.html.
-
-import (
-	"os"
-	"strconv"
-)
-
-// The Blowfish block size in bytes.
-const BlockSize = 8
-
-// A Cipher is an instance of Blowfish encryption using a particular key.
-type Cipher struct {
-	p              [18]uint32
-	s0, s1, s2, s3 [256]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) String() string {
-	return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a Cipher.
-// The key argument should be the Blowfish key, 4 to 56 bytes.
-func NewCipher(key []byte) (*Cipher, os.Error) {
-	var result Cipher
-	k := len(key)
-	if k < 4 || k > 56 {
-		return nil, KeySizeError(k)
-	}
-	initCipher(key, &result)
-	ExpandKey(key, &result)
-	return &result, nil
-}
-
-// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
-// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
-// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
-// bytes.
-func NewSaltedCipher(key, salt []byte) (*Cipher, os.Error) {
-	var result Cipher
-	k := len(key)
-	if k < 4 {
-		return nil, KeySizeError(k)
-	}
-	initCipher(key, &result)
-	expandKeyWithSalt(key, salt, &result)
-	return &result, nil
-}
-
-// BlockSize returns the Blowfish block size, 8 bytes.
-// It is necessary to satisfy the Cipher interface in the
-// package "crypto/cipher".
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// Encrypt encrypts the 8-byte buffer src using the key k
-// and stores the result in dst.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) {
-	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-	l, r = encryptBlock(l, r, c)
-	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
-	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
-}
-
-// Decrypt decrypts the 8-byte buffer src using the key k
-// and stores the result in dst.
-func (c *Cipher) Decrypt(dst, src []byte) {
-	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-	l, r = decryptBlock(l, r, c)
-	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
-	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
-}
-
-// Reset zeros the key data, so that it will no longer
-// appear in the process's memory.
-func (c *Cipher) Reset() {
-	zero(c.p[0:])
-	zero(c.s0[0:])
-	zero(c.s1[0:])
-	zero(c.s2[0:])
-	zero(c.s3[0:])
-}
-
-func initCipher(key []byte, c *Cipher) {
-	copy(c.p[0:], p[0:])
-	copy(c.s0[0:], s0[0:])
-	copy(c.s1[0:], s1[0:])
-	copy(c.s2[0:], s2[0:])
-	copy(c.s3[0:], s3[0:])
-}
diff --git a/src/pkg/crypto/blowfish/const.go b/src/pkg/crypto/blowfish/const.go
deleted file mode 100644
index 8c5ee4c..0000000
--- a/src/pkg/crypto/blowfish/const.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2010 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.
-
-// The startup permutation array and substitution boxes.
-// They are the hexadecimal digits of PI; see:
-// http://www.schneier.com/code/constants.txt.
-
-package blowfish
-
-var s0 = [256]uint32{
-	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
-	0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
-	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
-	0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
-	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
-	0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
-	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
-	0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
-	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
-	0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
-	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
-	0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
-	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
-	0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
-	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
-	0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
-	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
-	0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
-	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
-	0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
-	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
-	0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
-	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
-	0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
-	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
-	0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
-	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
-	0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
-	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
-	0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
-	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
-	0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
-	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
-	0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
-	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
-	0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
-	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
-	0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
-	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
-	0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
-	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
-	0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
-	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
-}
-
-var s1 = [256]uint32{
-	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
-	0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
-	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
-	0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
-	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
-	0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
-	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
-	0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
-	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
-	0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
-	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
-	0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
-	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
-	0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
-	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
-	0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
-	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
-	0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
-	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
-	0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
-	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
-	0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
-	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
-	0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
-	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
-	0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
-	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
-	0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
-	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
-	0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
-	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
-	0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
-	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
-	0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
-	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
-	0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
-	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
-	0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
-	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
-	0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
-	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
-	0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
-	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
-}
-
-var s2 = [256]uint32{
-	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
-	0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
-	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
-	0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
-	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
-	0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
-	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
-	0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
-	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
-	0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
-	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
-	0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
-	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
-	0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
-	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
-	0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
-	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
-	0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
-	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
-	0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
-	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
-	0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
-	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
-	0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
-	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
-	0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
-	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
-	0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
-	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
-	0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
-	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
-	0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
-	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
-	0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
-	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
-	0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
-	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
-	0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
-	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
-	0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
-	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
-	0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
-	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
-}
-
-var s3 = [256]uint32{
-	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
-	0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
-	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
-	0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
-	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
-	0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
-	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
-	0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
-	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
-	0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
-	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
-	0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
-	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
-	0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
-	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
-	0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
-	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
-	0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
-	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
-	0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
-	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
-	0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
-	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
-	0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
-	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
-	0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
-	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
-	0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
-	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
-	0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
-	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
-	0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
-	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
-	0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
-	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
-	0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
-	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
-	0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
-	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
-	0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
-	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
-	0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
-	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
-}
-
-var p = [18]uint32{
-	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
-	0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
-	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
-}
diff --git a/src/pkg/crypto/cast5/Makefile b/src/pkg/crypto/cast5/Makefile
deleted file mode 100644
index 346fadd..0000000
--- a/src/pkg/crypto/cast5/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/cast5
-GOFILES=\
-	cast5.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/cast5/cast5.go b/src/pkg/crypto/cast5/cast5.go
deleted file mode 100644
index e9d4a24..0000000
--- a/src/pkg/crypto/cast5/cast5.go
+++ /dev/null
@@ -1,536 +0,0 @@
-// Copyright 2010 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 cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
-// OpenPGP cipher.
-package cast5
-
-import (
-	"os"
-)
-
-const BlockSize = 8
-const KeySize = 16
-
-type Cipher struct {
-	masking [16]uint32
-	rotate  [16]uint8
-}
-
-func NewCipher(key []byte) (c *Cipher, err os.Error) {
-	if len(key) != KeySize {
-		return nil, os.NewError("CAST5: keys must be 16 bytes")
-	}
-
-	c = new(Cipher)
-	c.keySchedule(key)
-	return
-}
-
-func (c *Cipher) BlockSize() int {
-	return BlockSize
-}
-
-// Reset zeros the key material in memory.
-func (c *Cipher) Reset() {
-	for i := 0; i < 16; i++ {
-		c.masking[i] = 0
-		c.rotate[i] = 0
-	}
-}
-
-func (c *Cipher) Encrypt(dst, src []byte) {
-	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-
-	l, r = r, l^f1(r, c.masking[0], c.rotate[0])
-	l, r = r, l^f2(r, c.masking[1], c.rotate[1])
-	l, r = r, l^f3(r, c.masking[2], c.rotate[2])
-	l, r = r, l^f1(r, c.masking[3], c.rotate[3])
-
-	l, r = r, l^f2(r, c.masking[4], c.rotate[4])
-	l, r = r, l^f3(r, c.masking[5], c.rotate[5])
-	l, r = r, l^f1(r, c.masking[6], c.rotate[6])
-	l, r = r, l^f2(r, c.masking[7], c.rotate[7])
-
-	l, r = r, l^f3(r, c.masking[8], c.rotate[8])
-	l, r = r, l^f1(r, c.masking[9], c.rotate[9])
-	l, r = r, l^f2(r, c.masking[10], c.rotate[10])
-	l, r = r, l^f3(r, c.masking[11], c.rotate[11])
-
-	l, r = r, l^f1(r, c.masking[12], c.rotate[12])
-	l, r = r, l^f2(r, c.masking[13], c.rotate[13])
-	l, r = r, l^f3(r, c.masking[14], c.rotate[14])
-	l, r = r, l^f1(r, c.masking[15], c.rotate[15])
-
-	dst[0] = uint8(r >> 24)
-	dst[1] = uint8(r >> 16)
-	dst[2] = uint8(r >> 8)
-	dst[3] = uint8(r)
-	dst[4] = uint8(l >> 24)
-	dst[5] = uint8(l >> 16)
-	dst[6] = uint8(l >> 8)
-	dst[7] = uint8(l)
-}
-
-func (c *Cipher) Decrypt(dst, src []byte) {
-	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-
-	l, r = r, l^f1(r, c.masking[15], c.rotate[15])
-	l, r = r, l^f3(r, c.masking[14], c.rotate[14])
-	l, r = r, l^f2(r, c.masking[13], c.rotate[13])
-	l, r = r, l^f1(r, c.masking[12], c.rotate[12])
-
-	l, r = r, l^f3(r, c.masking[11], c.rotate[11])
-	l, r = r, l^f2(r, c.masking[10], c.rotate[10])
-	l, r = r, l^f1(r, c.masking[9], c.rotate[9])
-	l, r = r, l^f3(r, c.masking[8], c.rotate[8])
-
-	l, r = r, l^f2(r, c.masking[7], c.rotate[7])
-	l, r = r, l^f1(r, c.masking[6], c.rotate[6])
-	l, r = r, l^f3(r, c.masking[5], c.rotate[5])
-	l, r = r, l^f2(r, c.masking[4], c.rotate[4])
-
-	l, r = r, l^f1(r, c.masking[3], c.rotate[3])
-	l, r = r, l^f3(r, c.masking[2], c.rotate[2])
-	l, r = r, l^f2(r, c.masking[1], c.rotate[1])
-	l, r = r, l^f1(r, c.masking[0], c.rotate[0])
-
-	dst[0] = uint8(r >> 24)
-	dst[1] = uint8(r >> 16)
-	dst[2] = uint8(r >> 8)
-	dst[3] = uint8(r)
-	dst[4] = uint8(l >> 24)
-	dst[5] = uint8(l >> 16)
-	dst[6] = uint8(l >> 8)
-	dst[7] = uint8(l)
-}
-
-type keyScheduleA [4][7]uint8
-type keyScheduleB [4][5]uint8
-
-// keyScheduleRound contains the magic values for a round of the key schedule.
-// The keyScheduleA deals with the lines like:
-//   z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
-// Conceptually, both x and z are in the same array, x first. The first
-// element describes which word of this array gets written to and the
-// second, which word gets read. So, for the line above, it's "4, 0", because
-// it's writing to the first word of z, which, being after x, is word 4, and
-// reading from the first word of x: word 0.
-//
-// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
-// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
-// that it's z that we're indexing.
-//
-// keyScheduleB deals with lines like:
-//   K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
-// "K1" is ignored because key words are always written in order. So the five
-// elements are the S-box indexes. They use the same form as in keyScheduleA,
-// above.
-
-type keyScheduleRound struct{}
-type keySchedule []keyScheduleRound
-
-var schedule = []struct {
-	a keyScheduleA
-	b keyScheduleB
-}{
-	{
-		keyScheduleA{
-			{4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
-			{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
-			{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
-			{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
-		},
-		keyScheduleB{
-			{16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
-			{16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
-			{16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
-			{16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
-		},
-	},
-	{
-		keyScheduleA{
-			{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
-			{1, 4, 0, 2, 1, 3, 16 + 2},
-			{2, 5, 7, 6, 5, 4, 16 + 1},
-			{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
-		},
-		keyScheduleB{
-			{3, 2, 0xc, 0xd, 8},
-			{1, 0, 0xe, 0xf, 0xd},
-			{7, 6, 8, 9, 3},
-			{5, 4, 0xa, 0xb, 7},
-		},
-	},
-	{
-		keyScheduleA{
-			{4, 0, 0xd, 0xf, 0xc, 0xe, 8},
-			{5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
-			{6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
-			{7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
-		},
-		keyScheduleB{
-			{16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
-			{16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
-			{16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
-			{16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
-		},
-	},
-	{
-		keyScheduleA{
-			{0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
-			{1, 4, 0, 2, 1, 3, 16 + 2},
-			{2, 5, 7, 6, 5, 4, 16 + 1},
-			{3, 7, 0xa, 9, 0xb, 8, 16 + 3},
-		},
-		keyScheduleB{
-			{8, 9, 7, 6, 3},
-			{0xa, 0xb, 5, 4, 7},
-			{0xc, 0xd, 3, 2, 8},
-			{0xe, 0xf, 1, 0, 0xd},
-		},
-	},
-}
-
-func (c *Cipher) keySchedule(in []byte) {
-	var t [8]uint32
-	var k [32]uint32
-
-	for i := 0; i < 4; i++ {
-		j := i * 4
-		t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
-	}
-
-	x := []byte{6, 7, 4, 5}
-	ki := 0
-
-	for half := 0; half < 2; half++ {
-		for _, round := range schedule {
-			for j := 0; j < 4; j++ {
-				var a [7]uint8
-				copy(a[:], round.a[j][:])
-				w := t[a[1]]
-				w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
-				w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
-				w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
-				w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
-				w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
-				t[a[0]] = w
-			}
-
-			for j := 0; j < 4; j++ {
-				var b [5]uint8
-				copy(b[:], round.b[j][:])
-				w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
-				w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
-				w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
-				w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
-				w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
-				k[ki] = w
-				ki++
-			}
-		}
-	}
-
-	for i := 0; i < 16; i++ {
-		c.masking[i] = k[i]
-		c.rotate[i] = uint8(k[16+i] & 0x1f)
-	}
-}
-
-// These are the three 'f' functions. See RFC 2144, section 2.2.
-func f1(d, m uint32, r uint8) uint32 {
-	t := m + d
-	I := (t << r) | (t >> (32 - r))
-	return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
-}
-
-func f2(d, m uint32, r uint8) uint32 {
-	t := m ^ d
-	I := (t << r) | (t >> (32 - r))
-	return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
-}
-
-func f3(d, m uint32, r uint8) uint32 {
-	t := m - d
-	I := (t << r) | (t >> (32 - r))
-	return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
-}
-
-var sBox = [8][256]uint32{
-	{
-		0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
-		0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
-		0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
-		0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
-		0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
-		0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
-		0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
-		0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
-		0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
-		0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
-		0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
-		0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
-		0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
-		0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
-		0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
-		0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
-		0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
-		0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
-		0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
-		0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
-		0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
-		0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
-		0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
-		0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
-		0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
-		0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
-		0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
-		0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
-		0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
-		0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
-		0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
-		0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
-	},
-	{
-		0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
-		0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
-		0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
-		0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
-		0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
-		0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
-		0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
-		0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
-		0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
-		0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
-		0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
-		0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
-		0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
-		0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
-		0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
-		0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
-		0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
-		0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
-		0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
-		0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
-		0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
-		0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
-		0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
-		0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
-		0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
-		0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
-		0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
-		0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
-		0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
-		0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
-		0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
-		0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
-	},
-	{
-		0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
-		0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
-		0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
-		0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
-		0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
-		0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
-		0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
-		0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
-		0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
-		0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
-		0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
-		0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
-		0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
-		0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
-		0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
-		0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
-		0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
-		0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
-		0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
-		0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
-		0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
-		0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
-		0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
-		0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
-		0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
-		0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
-		0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
-		0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
-		0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
-		0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
-		0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
-		0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
-	},
-	{
-		0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
-		0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
-		0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
-		0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
-		0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
-		0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
-		0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
-		0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
-		0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
-		0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
-		0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
-		0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
-		0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
-		0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
-		0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
-		0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
-		0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
-		0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
-		0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
-		0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
-		0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
-		0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
-		0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
-		0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
-		0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
-		0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
-		0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
-		0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
-		0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
-		0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
-		0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
-		0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
-	},
-	{
-		0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
-		0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
-		0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
-		0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
-		0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
-		0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
-		0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
-		0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
-		0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
-		0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
-		0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
-		0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
-		0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
-		0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
-		0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
-		0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
-		0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
-		0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
-		0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
-		0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
-		0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
-		0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
-		0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
-		0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
-		0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
-		0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
-		0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
-		0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
-		0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
-		0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
-		0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
-		0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
-	},
-	{
-		0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
-		0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
-		0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
-		0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
-		0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
-		0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
-		0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
-		0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
-		0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
-		0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
-		0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
-		0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
-		0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
-		0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
-		0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
-		0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
-		0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
-		0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
-		0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
-		0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
-		0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
-		0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
-		0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
-		0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
-		0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
-		0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
-		0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
-		0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
-		0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
-		0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
-		0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
-		0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
-	},
-	{
-		0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
-		0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
-		0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
-		0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
-		0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
-		0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
-		0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
-		0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
-		0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
-		0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
-		0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
-		0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
-		0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
-		0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
-		0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
-		0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
-		0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
-		0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
-		0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
-		0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
-		0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
-		0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
-		0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
-		0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
-		0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
-		0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
-		0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
-		0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
-		0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
-		0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
-		0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
-		0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
-	},
-	{
-		0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
-		0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
-		0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
-		0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
-		0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
-		0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
-		0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
-		0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
-		0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
-		0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
-		0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
-		0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
-		0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
-		0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
-		0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
-		0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
-		0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
-		0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
-		0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
-		0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
-		0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
-		0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
-		0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
-		0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
-		0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
-		0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
-		0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
-		0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
-		0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
-		0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
-		0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
-		0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
-	},
-}
diff --git a/src/pkg/crypto/cast5/cast5_test.go b/src/pkg/crypto/cast5/cast5_test.go
deleted file mode 100644
index 5f7025f..0000000
--- a/src/pkg/crypto/cast5/cast5_test.go
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2010 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 cast5
-
-import (
-	"bytes"
-	"encoding/hex"
-	"testing"
-)
-
-// This test vector is taken from RFC 2144, App B.1.
-// Since the other two test vectors are for reduced-round variants, we can't
-// use them.
-var basicTests = []struct {
-	key, plainText, cipherText string
-}{
-	{
-		"0123456712345678234567893456789a",
-		"0123456789abcdef",
-		"238b4fe5847e44b2",
-	},
-}
-
-func TestBasic(t *testing.T) {
-	for i, test := range basicTests {
-		key, _ := hex.DecodeString(test.key)
-		plainText, _ := hex.DecodeString(test.plainText)
-		expected, _ := hex.DecodeString(test.cipherText)
-
-		c, err := NewCipher(key)
-		if err != nil {
-			t.Errorf("#%d: failed to create Cipher: %s", i, err)
-			continue
-		}
-		var cipherText [BlockSize]byte
-		c.Encrypt(cipherText[:], plainText)
-		if !bytes.Equal(cipherText[:], expected) {
-			t.Errorf("#%d: got:%x want:%x", i, cipherText, expected)
-		}
-
-		var plainTextAgain [BlockSize]byte
-		c.Decrypt(plainTextAgain[:], cipherText[:])
-		if !bytes.Equal(plainTextAgain[:], plainText) {
-			t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText)
-		}
-	}
-}
-
-// TestFull performs the test specified in RFC 2144, App B.2.
-// However, due to the length of time taken, it's disabled here and a more
-// limited version is included, below.
-func TestFull(t *testing.T) {
-	// This is too slow for normal testing
-	return
-
-	a, b := iterate(1000000)
-
-	const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92"
-	const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e"
-
-	if hex.EncodeToString(a) != expectedA {
-		t.Errorf("a: got:%x want:%s", a, expectedA)
-	}
-	if hex.EncodeToString(b) != expectedB {
-		t.Errorf("b: got:%x want:%s", b, expectedB)
-	}
-}
-
-func iterate(iterations int) ([]byte, []byte) {
-	const initValueHex = "0123456712345678234567893456789a"
-
-	initValue, _ := hex.DecodeString(initValueHex)
-
-	var a, b [16]byte
-	copy(a[:], initValue)
-	copy(b[:], initValue)
-
-	for i := 0; i < iterations; i++ {
-		c, _ := NewCipher(b[:])
-		c.Encrypt(a[:8], a[:8])
-		c.Encrypt(a[8:], a[8:])
-		c, _ = NewCipher(a[:])
-		c.Encrypt(b[:8], b[:8])
-		c.Encrypt(b[8:], b[8:])
-	}
-
-	return a[:], b[:]
-}
-
-func TestLimited(t *testing.T) {
-	a, b := iterate(1000)
-
-	const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d"
-	const expectedB = "e5bf37eff14c456a40b21ce369370a9f"
-
-	if hex.EncodeToString(a) != expectedA {
-		t.Errorf("a: got:%x want:%s", a, expectedA)
-	}
-	if hex.EncodeToString(b) != expectedB {
-		t.Errorf("b: got:%x want:%s", b, expectedB)
-	}
-}
diff --git a/src/pkg/crypto/cipher/io.go b/src/pkg/crypto/cipher/io.go
index 97f40b8..9888c98 100644
--- a/src/pkg/crypto/cipher/io.go
+++ b/src/pkg/crypto/cipher/io.go
@@ -4,10 +4,7 @@
 
 package cipher
 
-import (
-	"os"
-	"io"
-)
+import "io"
 
 // The Stream* objects are so simple that all their members are public. Users
 // can create them themselves.
@@ -19,7 +16,7 @@ type StreamReader struct {
 	R io.Reader
 }
 
-func (r StreamReader) Read(dst []byte) (n int, err os.Error) {
+func (r StreamReader) Read(dst []byte) (n int, err error) {
 	n, err = r.R.Read(dst)
 	r.S.XORKeyStream(dst[:n], dst[:n])
 	return
@@ -31,10 +28,10 @@ func (r StreamReader) Read(dst []byte) (n int, err os.Error) {
 type StreamWriter struct {
 	S   Stream
 	W   io.Writer
-	Err os.Error
+	Err error
 }
 
-func (w StreamWriter) Write(src []byte) (n int, err os.Error) {
+func (w StreamWriter) Write(src []byte) (n int, err error) {
 	if w.Err != nil {
 		return 0, w.Err
 	}
@@ -50,7 +47,7 @@ func (w StreamWriter) Write(src []byte) (n int, err os.Error) {
 	return
 }
 
-func (w StreamWriter) Close() os.Error {
+func (w StreamWriter) Close() error {
 	// This saves us from either requiring a WriteCloser or having a
 	// StreamWriterCloser.
 	return w.W.(io.Closer).Close()
diff --git a/src/pkg/crypto/crypto.go b/src/pkg/crypto/crypto.go
index 53672a4..c913494 100644
--- a/src/pkg/crypto/crypto.go
+++ b/src/pkg/crypto/crypto.go
@@ -71,3 +71,6 @@ func RegisterHash(h Hash, f func() hash.Hash) {
 	}
 	hashes[h] = f
 }
+
+// PrivateKey represents a private key using an unspecified algorithm.
+type PrivateKey interface{}
diff --git a/src/pkg/crypto/des/cipher.go b/src/pkg/crypto/des/cipher.go
index d17a1a7..fc252c8 100644
--- a/src/pkg/crypto/des/cipher.go
+++ b/src/pkg/crypto/des/cipher.go
@@ -4,17 +4,14 @@
 
 package des
 
-import (
-	"os"
-	"strconv"
-)
+import "strconv"
 
 // The DES block size in bytes.
 const BlockSize = 8
 
 type KeySizeError int
 
-func (k KeySizeError) String() string {
+func (k KeySizeError) Error() string {
 	return "crypto/des: invalid key size " + strconv.Itoa(int(k))
 }
 
@@ -24,7 +21,7 @@ type Cipher struct {
 }
 
 // NewCipher creates and returns a new Cipher.
-func NewCipher(key []byte) (*Cipher, os.Error) {
+func NewCipher(key []byte) (*Cipher, error) {
 	if len(key) != 8 {
 		return nil, KeySizeError(len(key))
 	}
@@ -60,7 +57,7 @@ type TripleDESCipher struct {
 }
 
 // NewCipher creates and returns a new Cipher.
-func NewTripleDESCipher(key []byte) (*TripleDESCipher, os.Error) {
+func NewTripleDESCipher(key []byte) (*TripleDESCipher, error) {
 	if len(key) != 24 {
 		return nil, KeySizeError(len(key))
 	}
diff --git a/src/pkg/crypto/dsa/dsa.go b/src/pkg/crypto/dsa/dsa.go
index a5f96fe..7aaad1c 100644
--- a/src/pkg/crypto/dsa/dsa.go
+++ b/src/pkg/crypto/dsa/dsa.go
@@ -6,9 +6,9 @@
 package dsa
 
 import (
-	"big"
+	"errors"
 	"io"
-	"os"
+	"math/big"
 )
 
 // Parameters represents the domain parameters for a key. These parameters can
@@ -31,15 +31,15 @@ type PrivateKey struct {
 
 type invalidPublicKeyError int
 
-func (invalidPublicKeyError) String() string {
+func (invalidPublicKeyError) Error() string {
 	return "crypto/dsa: invalid public key"
 }
 
-// InvalidPublicKeyError results when a public key is not usable by this code.
+// ErrInvalidPublicKey results when a public key is not usable by this code.
 // FIPS is quite strict about the format of DSA keys, but other code may be
 // less so. Thus, when using keys which may have been generated by other code,
 // this error must be handled.
-var InvalidPublicKeyError = invalidPublicKeyError(0)
+var ErrInvalidPublicKey error = invalidPublicKeyError(0)
 
 // ParameterSizes is a enumeration of the acceptable bit lengths of the primes
 // in a set of DSA parameters. See FIPS 186-3, section 4.2.
@@ -58,7 +58,7 @@ const numMRTests = 64
 
 // GenerateParameters puts a random, valid set of DSA parameters into params.
 // This function takes many seconds, even on fast machines.
-func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err os.Error) {
+func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err error) {
 	// This function doesn't follow FIPS 186-3 exactly in that it doesn't
 	// use a verification seed to generate the primes. The verification
 	// seed doesn't appear to be exported or used by other code and
@@ -79,7 +79,7 @@ func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes
 		L = 3072
 		N = 256
 	default:
-		return os.NewError("crypto/dsa: invalid ParameterSizes")
+		return errors.New("crypto/dsa: invalid ParameterSizes")
 	}
 
 	qBytes := make([]byte, N/8)
@@ -156,9 +156,9 @@ GeneratePrimes:
 
 // GenerateKey generates a public&private key pair. The Parameters of the
 // PrivateKey must already be valid (see GenerateParameters).
-func GenerateKey(priv *PrivateKey, rand io.Reader) os.Error {
+func GenerateKey(priv *PrivateKey, rand io.Reader) error {
 	if priv.P == nil || priv.Q == nil || priv.G == nil {
-		return os.NewError("crypto/dsa: parameters not set up before generating key")
+		return errors.New("crypto/dsa: parameters not set up before generating key")
 	}
 
 	x := new(big.Int)
@@ -185,12 +185,16 @@ func GenerateKey(priv *PrivateKey, rand io.Reader) os.Error {
 // larger message) using the private key, priv. It returns the signature as a
 // pair of integers. The security of the private key depends on the entropy of
 // rand.
-func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.Error) {
+//
+// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
+// to the byte-length of the subgroup. This function does not perform that
+// truncation itself.
+func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
 	// FIPS 186-3, section 4.6
 
 	n := priv.Q.BitLen()
 	if n&7 != 0 {
-		err = InvalidPublicKeyError
+		err = ErrInvalidPublicKey
 		return
 	}
 	n >>= 3
@@ -218,10 +222,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.
 			continue
 		}
 
-		if n > len(hash) {
-			n = len(hash)
-		}
-		z := k.SetBytes(hash[:n])
+		z := k.SetBytes(hash)
 
 		s = new(big.Int).Mul(priv.X, r)
 		s.Add(s, z)
@@ -238,7 +239,11 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.
 }
 
 // Verify verifies the signature in r, s of hash using the public key, pub. It
-// returns true iff the signature is valid.
+// reports whether the signature is valid.
+//
+// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
+// to the byte-length of the subgroup. This function does not perform that
+// truncation itself.
 func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
 	// FIPS 186-3, section 4.7
 
@@ -255,12 +260,7 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
 	if n&7 != 0 {
 		return false
 	}
-	n >>= 3
-
-	if n > len(hash) {
-		n = len(hash)
-	}
-	z := new(big.Int).SetBytes(hash[:n])
+	z := new(big.Int).SetBytes(hash)
 
 	u1 := new(big.Int).Mul(z, w)
 	u1.Mod(u1, pub.Q)
diff --git a/src/pkg/crypto/dsa/dsa_test.go b/src/pkg/crypto/dsa/dsa_test.go
index deec08d..177aa44 100644
--- a/src/pkg/crypto/dsa/dsa_test.go
+++ b/src/pkg/crypto/dsa/dsa_test.go
@@ -5,8 +5,8 @@
 package dsa
 
 import (
-	"big"
 	"crypto/rand"
+	"math/big"
 	"testing"
 )
 
diff --git a/src/pkg/crypto/ecdsa/ecdsa.go b/src/pkg/crypto/ecdsa/ecdsa.go
index 7bce1bc..d2f7d8f 100644
--- a/src/pkg/crypto/ecdsa/ecdsa.go
+++ b/src/pkg/crypto/ecdsa/ecdsa.go
@@ -13,15 +13,14 @@ package ecdsa
 //     http://www.secg.org/download/aid-780/sec1-v2.pdf
 
 import (
-	"big"
 	"crypto/elliptic"
 	"io"
-	"os"
+	"math/big"
 )
 
 // PublicKey represents an ECDSA public key.
 type PublicKey struct {
-	*elliptic.Curve
+	elliptic.Curve
 	X, Y *big.Int
 }
 
@@ -35,22 +34,23 @@ var one = new(big.Int).SetInt64(1)
 
 // randFieldElement returns a random element of the field underlying the given
 // curve using the procedure given in [NSA] A.2.1.
-func randFieldElement(c *elliptic.Curve, rand io.Reader) (k *big.Int, err os.Error) {
-	b := make([]byte, c.BitSize/8+8)
+func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
+	params := c.Params()
+	b := make([]byte, params.BitSize/8+8)
 	_, err = io.ReadFull(rand, b)
 	if err != nil {
 		return
 	}
 
 	k = new(big.Int).SetBytes(b)
-	n := new(big.Int).Sub(c.N, one)
+	n := new(big.Int).Sub(params.N, one)
 	k.Mod(k, n)
 	k.Add(k, one)
 	return
 }
 
 // GenerateKey generates a public&private key pair.
-func GenerateKey(c *elliptic.Curve, rand io.Reader) (priv *PrivateKey, err os.Error) {
+func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error) {
 	k, err := randFieldElement(c, rand)
 	if err != nil {
 		return
@@ -67,8 +67,8 @@ func GenerateKey(c *elliptic.Curve, rand io.Reader) (priv *PrivateKey, err os.Er
 // about how this is done. [NSA] suggests that this is done in the obvious
 // manner, but [SECG] truncates the hash to the bit-length of the curve order
 // first. We follow [SECG] because that's what OpenSSL does.
-func hashToInt(hash []byte, c *elliptic.Curve) *big.Int {
-	orderBits := c.N.BitLen()
+func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
+	orderBits := c.Params().N.BitLen()
 	orderBytes := (orderBits + 7) / 8
 	if len(hash) > orderBytes {
 		hash = hash[:orderBytes]
@@ -86,9 +86,10 @@ func hashToInt(hash []byte, c *elliptic.Curve) *big.Int {
 // larger message) using the private key, priv. It returns the signature as a
 // pair of integers. The security of the private key depends on the entropy of
 // rand.
-func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.Error) {
+func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
 	// See [NSA] 3.4.1
 	c := priv.PublicKey.Curve
+	N := c.Params().N
 
 	var k, kInv *big.Int
 	for {
@@ -99,9 +100,9 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.
 				return
 			}
 
-			kInv = new(big.Int).ModInverse(k, c.N)
+			kInv = new(big.Int).ModInverse(k, N)
 			r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
-			r.Mod(r, priv.Curve.N)
+			r.Mod(r, N)
 			if r.Sign() != 0 {
 				break
 			}
@@ -111,7 +112,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.
 		s = new(big.Int).Mul(priv.D, r)
 		s.Add(s, e)
 		s.Mul(s, kInv)
-		s.Mod(s, priv.PublicKey.Curve.N)
+		s.Mod(s, N)
 		if s.Sign() != 0 {
 			break
 		}
@@ -125,15 +126,16 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.
 func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
 	// See [NSA] 3.4.2
 	c := pub.Curve
+	N := c.Params().N
 
 	if r.Sign() == 0 || s.Sign() == 0 {
 		return false
 	}
-	if r.Cmp(c.N) >= 0 || s.Cmp(c.N) >= 0 {
+	if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 {
 		return false
 	}
 	e := hashToInt(hash, c)
-	w := new(big.Int).ModInverse(s, c.N)
+	w := new(big.Int).ModInverse(s, N)
 
 	u1 := e.Mul(e, w)
 	u2 := w.Mul(r, w)
@@ -144,6 +146,6 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
 		return false
 	}
 	x, _ := c.Add(x1, y1, x2, y2)
-	x.Mod(x, c.N)
+	x.Mod(x, N)
 	return x.Cmp(r) == 0
 }
diff --git a/src/pkg/crypto/ecdsa/ecdsa_test.go b/src/pkg/crypto/ecdsa/ecdsa_test.go
index d6b4039..3a2b3ef 100644
--- a/src/pkg/crypto/ecdsa/ecdsa_test.go
+++ b/src/pkg/crypto/ecdsa/ecdsa_test.go
@@ -5,15 +5,15 @@
 package ecdsa
 
 import (
-	"big"
 	"crypto/elliptic"
-	"crypto/sha1"
 	"crypto/rand"
+	"crypto/sha1"
 	"encoding/hex"
+	"math/big"
 	"testing"
 )
 
-func testKeyGeneration(t *testing.T, c *elliptic.Curve, tag string) {
+func testKeyGeneration(t *testing.T, c elliptic.Curve, tag string) {
 	priv, err := GenerateKey(c, rand.Reader)
 	if err != nil {
 		t.Errorf("%s: error: %s", tag, err)
@@ -34,7 +34,7 @@ func TestKeyGeneration(t *testing.T) {
 	testKeyGeneration(t, elliptic.P521(), "p521")
 }
 
-func testSignAndVerify(t *testing.T, c *elliptic.Curve, tag string) {
+func testSignAndVerify(t *testing.T, c elliptic.Curve, tag string) {
 	priv, _ := GenerateKey(c, rand.Reader)
 
 	hashed := []byte("testing")
@@ -214,7 +214,7 @@ func TestVectors(t *testing.T) {
 		msg, _ := hex.DecodeString(test.msg)
 		sha.Reset()
 		sha.Write(msg)
-		hashed := sha.Sum()
+		hashed := sha.Sum(nil)
 		r := fromHex(test.r)
 		s := fromHex(test.s)
 		if Verify(&pub, hashed, r, s) != test.ok {
diff --git a/src/pkg/crypto/elliptic/Makefile b/src/pkg/crypto/elliptic/Makefile
index 4db5d7d..b38af4d 100644
--- a/src/pkg/crypto/elliptic/Makefile
+++ b/src/pkg/crypto/elliptic/Makefile
@@ -7,5 +7,6 @@ include ../../../Make.inc
 TARG=crypto/elliptic
 GOFILES=\
 	elliptic.go\
+	p224.go\
 
 include ../../../Make.pkg
diff --git a/src/pkg/crypto/elliptic/elliptic.go b/src/pkg/crypto/elliptic/elliptic.go
index 41835f1..30835a9 100644
--- a/src/pkg/crypto/elliptic/elliptic.go
+++ b/src/pkg/crypto/elliptic/elliptic.go
@@ -14,15 +14,32 @@ package elliptic
 // reverse the transform than to operate in affine coordinates.
 
 import (
-	"big"
 	"io"
-	"os"
+	"math/big"
 	"sync"
 )
 
 // A Curve represents a short-form Weierstrass curve with a=-3.
 // See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
-type Curve struct {
+type Curve interface {
+	// Params returns the parameters for the curve.
+	Params() *CurveParams
+	// IsOnCurve returns true if the given (x,y) lies on the curve.
+	IsOnCurve(x, y *big.Int) bool
+	// Add returns the sum of (x1,y1) and (x2,y2)
+	Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int)
+	// Double returns 2*(x,y)
+	Double(x1, y1 *big.Int) (x, y *big.Int)
+	// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
+	ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int)
+	// ScalarBaseMult returns k*G, where G is the base point of the group and k
+	// is an integer in big-endian form.
+	ScalarBaseMult(scalar []byte) (x, y *big.Int)
+}
+
+// CurveParams contains the parameters of an elliptic curve and also provides
+// a generic, non-constant time implementation of Curve.
+type CurveParams struct {
 	P       *big.Int // the order of the underlying field
 	N       *big.Int // the order of the base point
 	B       *big.Int // the constant of the curve equation
@@ -30,8 +47,11 @@ type Curve struct {
 	BitSize int      // the size of the underlying field
 }
 
-// IsOnCurve returns true if the given (x,y) lies on the curve.
-func (curve *Curve) IsOnCurve(x, y *big.Int) bool {
+func (curve *CurveParams) Params() *CurveParams {
+	return curve
+}
+
+func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
 	// y² = x³ - 3x + b
 	y2 := new(big.Int).Mul(y, y)
 	y2.Mod(y2, curve.P)
@@ -51,7 +71,7 @@ func (curve *Curve) IsOnCurve(x, y *big.Int) bool {
 
 // affineFromJacobian reverses the Jacobian transform. See the comment at the
 // top of the file.
-func (curve *Curve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
+func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
 	zinv := new(big.Int).ModInverse(z, curve.P)
 	zinvsq := new(big.Int).Mul(zinv, zinv)
 
@@ -63,15 +83,14 @@ func (curve *Curve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
 	return
 }
 
-// Add returns the sum of (x1,y1) and (x2,y2)
-func (curve *Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
 	z := new(big.Int).SetInt64(1)
 	return curve.affineFromJacobian(curve.addJacobian(x1, y1, z, x2, y2, z))
 }
 
 // addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
 // (x2, y2, z2) and returns their sum, also in Jacobian form.
-func (curve *Curve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
+func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
 	// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
 	z1z1 := new(big.Int).Mul(z1, z1)
 	z1z1.Mod(z1z1, curve.P)
@@ -134,15 +153,14 @@ func (curve *Curve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big
 	return x3, y3, z3
 }
 
-// Double returns 2*(x,y)
-func (curve *Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
 	z1 := new(big.Int).SetInt64(1)
 	return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
 }
 
 // doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
 // returns its double, also in Jacobian form.
-func (curve *Curve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
+func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
 	// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
 	delta := new(big.Int).Mul(z, z)
 	delta.Mod(delta, curve.P)
@@ -200,8 +218,7 @@ func (curve *Curve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.I
 	return x3, y3, z3
 }
 
-// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
-func (curve *Curve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
+func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
 	// We have a slight problem in that the identity of the group (the
 	// point at infinity) cannot be represented in (x, y) form on a finite
 	// machine. Thus the standard add/double algorithm has to be tweaked
@@ -239,18 +256,17 @@ func (curve *Curve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
 	return curve.affineFromJacobian(x, y, z)
 }
 
-// ScalarBaseMult returns k*G, where G is the base point of the group and k is
-// an integer in big-endian form.
-func (curve *Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
 	return curve.ScalarMult(curve.Gx, curve.Gy, k)
 }
 
 var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
 
-// GenerateKey returns a public/private key pair. The private key is generated
-// using the given reader, which must return random data.
-func (curve *Curve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err os.Error) {
-	byteLen := (curve.BitSize + 7) >> 3
+// GenerateKey returns a public/private key pair. The private key is
+// generated using the given reader, which must return random data.
+func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) {
+	bitSize := curve.Params().BitSize
+	byteLen := (bitSize + 7) >> 3
 	priv = make([]byte, byteLen)
 
 	for x == nil {
@@ -260,7 +276,7 @@ func (curve *Curve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err
 		}
 		// We have to mask off any excess bits in the case that the size of the
 		// underlying field is not a whole number of bytes.
-		priv[0] &= mask[curve.BitSize%8]
+		priv[0] &= mask[bitSize%8]
 		// This is because, in tests, rand will return all zeros and we don't
 		// want to get the point at infinity and loop forever.
 		priv[1] ^= 0x42
@@ -269,10 +285,9 @@ func (curve *Curve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err
 	return
 }
 
-// Marshal converts a point into the form specified in section 4.3.6 of ANSI
-// X9.62.
-func (curve *Curve) Marshal(x, y *big.Int) []byte {
-	byteLen := (curve.BitSize + 7) >> 3
+// Marshal converts a point into the form specified in section 4.3.6 of ANSI X9.62.
+func Marshal(curve Curve, x, y *big.Int) []byte {
+	byteLen := (curve.Params().BitSize + 7) >> 3
 
 	ret := make([]byte, 1+2*byteLen)
 	ret[0] = 4 // uncompressed point
@@ -284,10 +299,9 @@ func (curve *Curve) Marshal(x, y *big.Int) []byte {
 	return ret
 }
 
-// Unmarshal converts a point, serialized by Marshal, into an x, y pair. On
-// error, x = nil.
-func (curve *Curve) Unmarshal(data []byte) (x, y *big.Int) {
-	byteLen := (curve.BitSize + 7) >> 3
+// Unmarshal converts a point, serialized by Marshal, into an x, y pair. On error, x = nil.
+func Unmarshal(curve Curve, data []byte) (x, y *big.Int) {
+	byteLen := (curve.Params().BitSize + 7) >> 3
 	if len(data) != 1+2*byteLen {
 		return
 	}
@@ -300,10 +314,9 @@ func (curve *Curve) Unmarshal(data []byte) (x, y *big.Int) {
 }
 
 var initonce sync.Once
-var p224 *Curve
-var p256 *Curve
-var p384 *Curve
-var p521 *Curve
+var p256 *CurveParams
+var p384 *CurveParams
+var p521 *CurveParams
 
 func initAll() {
 	initP224()
@@ -312,20 +325,9 @@ func initAll() {
 	initP521()
 }
 
-func initP224() {
-	// See FIPS 186-3, section D.2.2
-	p224 = new(Curve)
-	p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10)
-	p224.N, _ = new(big.Int).SetString("26959946667150639794667015087019625940457807714424391721682722368061", 10)
-	p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16)
-	p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16)
-	p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16)
-	p224.BitSize = 224
-}
-
 func initP256() {
 	// See FIPS 186-3, section D.2.3
-	p256 = new(Curve)
+	p256 = new(CurveParams)
 	p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
 	p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
 	p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
@@ -336,7 +338,7 @@ func initP256() {
 
 func initP384() {
 	// See FIPS 186-3, section D.2.4
-	p384 = new(Curve)
+	p384 = new(CurveParams)
 	p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10)
 	p384.N, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10)
 	p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16)
@@ -347,7 +349,7 @@ func initP384() {
 
 func initP521() {
 	// See FIPS 186-3, section D.2.5
-	p521 = new(Curve)
+	p521 = new(CurveParams)
 	p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10)
 	p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10)
 	p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
@@ -356,26 +358,20 @@ func initP521() {
 	p521.BitSize = 521
 }
 
-// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2)
-func P224() *Curve {
-	initonce.Do(initAll)
-	return p224
-}
-
 // P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3)
-func P256() *Curve {
+func P256() Curve {
 	initonce.Do(initAll)
 	return p256
 }
 
 // P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4)
-func P384() *Curve {
+func P384() Curve {
 	initonce.Do(initAll)
 	return p384
 }
 
 // P256 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
-func P521() *Curve {
+func P521() Curve {
 	initonce.Do(initAll)
 	return p521
 }
diff --git a/src/pkg/crypto/elliptic/elliptic_test.go b/src/pkg/crypto/elliptic/elliptic_test.go
index b7e7f03..c23af75 100644
--- a/src/pkg/crypto/elliptic/elliptic_test.go
+++ b/src/pkg/crypto/elliptic/elliptic_test.go
@@ -5,15 +5,15 @@
 package elliptic
 
 import (
-	"big"
 	"crypto/rand"
 	"fmt"
+	"math/big"
 	"testing"
 )
 
 func TestOnCurve(t *testing.T) {
 	p224 := P224()
-	if !p224.IsOnCurve(p224.Gx, p224.Gy) {
+	if !p224.IsOnCurve(p224.Params().Gx, p224.Params().Gy) {
 		t.Errorf("FAIL")
 	}
 }
@@ -295,7 +295,25 @@ func TestBaseMult(t *testing.T) {
 		}
 		x, y := p224.ScalarBaseMult(k.Bytes())
 		if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
-			t.Errorf("%d: bad output for k=%s: got (%x, %s), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+			t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+		}
+		if testing.Short() && i > 5 {
+			break
+		}
+	}
+}
+
+func TestGenericBaseMult(t *testing.T) {
+	// We use the P224 CurveParams directly in order to test the generic implementation.
+	p224 := P224().Params()
+	for i, e := range p224BaseMultTests {
+		k, ok := new(big.Int).SetString(e.k, 10)
+		if !ok {
+			t.Errorf("%d: bad value for k: %s", i, e.k)
+		}
+		x, y := p224.ScalarBaseMult(k.Bytes())
+		if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
+			t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y)
 		}
 		if testing.Short() && i > 5 {
 			break
@@ -316,13 +334,13 @@ func BenchmarkBaseMult(b *testing.B) {
 
 func TestMarshal(t *testing.T) {
 	p224 := P224()
-	_, x, y, err := p224.GenerateKey(rand.Reader)
+	_, x, y, err := GenerateKey(p224, rand.Reader)
 	if err != nil {
 		t.Error(err)
 		return
 	}
-	serialized := p224.Marshal(x, y)
-	xx, yy := p224.Unmarshal(serialized)
+	serialized := Marshal(p224, x, y)
+	xx, yy := Unmarshal(p224, serialized)
 	if xx == nil {
 		t.Error("failed to unmarshal")
 		return
diff --git a/src/pkg/crypto/elliptic/p224.go b/src/pkg/crypto/elliptic/p224.go
new file mode 100644
index 0000000..08db5bc
--- /dev/null
+++ b/src/pkg/crypto/elliptic/p224.go
@@ -0,0 +1,685 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elliptic
+
+// This is a constant-time, 32-bit implementation of P224. See FIPS 186-3,
+// section D.2.2.
+//
+// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
+
+import (
+	"math/big"
+)
+
+var p224 p224Curve
+
+type p224Curve struct {
+	*CurveParams
+	gx, gy, b p224FieldElement
+}
+
+func initP224() {
+	// See FIPS 186-3, section D.2.2
+	p224.CurveParams = new(CurveParams)
+	p224.P, _ = new(big.Int).SetString("26959946667150639794667015087019630673557916260026308143510066298881", 10)
+	p224.N, _ = new(big.Int).SetString("26959946667150639794667015087019625940457807714424391721682722368061", 10)
+	p224.B, _ = new(big.Int).SetString("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16)
+	p224.Gx, _ = new(big.Int).SetString("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16)
+	p224.Gy, _ = new(big.Int).SetString("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16)
+	p224.BitSize = 224
+
+	p224FromBig(&p224.gx, p224.Gx)
+	p224FromBig(&p224.gy, p224.Gy)
+	p224FromBig(&p224.b, p224.B)
+}
+
+// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2)
+func P224() Curve {
+	initonce.Do(initAll)
+	return p224
+}
+
+func (curve p224Curve) Params() *CurveParams {
+	return curve.CurveParams
+}
+
+func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
+	var x, y p224FieldElement
+	p224FromBig(&x, bigX)
+	p224FromBig(&y, bigY)
+
+	// y² = x³ - 3x + b
+	var tmp p224LargeFieldElement
+	var x3 p224FieldElement
+	p224Square(&x3, &x, &tmp)
+	p224Mul(&x3, &x3, &x, &tmp)
+
+	for i := 0; i < 8; i++ {
+		x[i] *= 3
+	}
+	p224Sub(&x3, &x3, &x)
+	p224Reduce(&x3)
+	p224Add(&x3, &x3, &curve.b)
+	p224Contract(&x3, &x3)
+
+	p224Square(&y, &y, &tmp)
+	p224Contract(&y, &y)
+
+	for i := 0; i < 8; i++ {
+		if y[i] != x3[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (p224Curve) Add(bigX1, bigY1, bigX2, bigY2 *big.Int) (x, y *big.Int) {
+	var x1, y1, z1, x2, y2, z2, x3, y3, z3 p224FieldElement
+
+	p224FromBig(&x1, bigX1)
+	p224FromBig(&y1, bigY1)
+	z1[0] = 1
+	p224FromBig(&x2, bigX2)
+	p224FromBig(&y2, bigY2)
+	z2[0] = 1
+
+	p224AddJacobian(&x3, &y3, &z3, &x1, &y1, &z1, &x2, &y2, &z2)
+	return p224ToAffine(&x3, &y3, &z3)
+}
+
+func (p224Curve) Double(bigX1, bigY1 *big.Int) (x, y *big.Int) {
+	var x1, y1, z1, x2, y2, z2 p224FieldElement
+
+	p224FromBig(&x1, bigX1)
+	p224FromBig(&y1, bigY1)
+	z1[0] = 1
+
+	p224DoubleJacobian(&x2, &y2, &z2, &x1, &y1, &z1)
+	return p224ToAffine(&x2, &y2, &z2)
+}
+
+func (p224Curve) ScalarMult(bigX1, bigY1 *big.Int, scalar []byte) (x, y *big.Int) {
+	var x1, y1, z1, x2, y2, z2 p224FieldElement
+
+	p224FromBig(&x1, bigX1)
+	p224FromBig(&y1, bigY1)
+	z1[0] = 1
+
+	p224ScalarMult(&x2, &y2, &z2, &x1, &y1, &z1, scalar)
+	return p224ToAffine(&x2, &y2, &z2)
+}
+
+func (curve p224Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
+	var z1, x2, y2, z2 p224FieldElement
+
+	z1[0] = 1
+	p224ScalarMult(&x2, &y2, &z2, &curve.gx, &curve.gy, &z1, scalar)
+	return p224ToAffine(&x2, &y2, &z2)
+}
+
+// Field element functions.
+//
+// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1.
+//
+// Field elements are represented by a FieldElement, which is a typedef to an
+// array of 8 uint32's. The value of a FieldElement, a, is:
+//   a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7]
+//
+// Using 28-bit limbs means that there's only 4 bits of headroom, which is less
+// than we would really like. But it has the useful feature that we hit 2**224
+// exactly, making the reflections during a reduce much nicer.
+type p224FieldElement [8]uint32
+
+// p224Add computes *out = a+b
+//
+// a[i] + b[i] < 2**32
+func p224Add(out, a, b *p224FieldElement) {
+	for i := 0; i < 8; i++ {
+		out[i] = a[i] + b[i]
+	}
+}
+
+const two31p3 = 1<<31 + 1<<3
+const two31m3 = 1<<31 - 1<<3
+const two31m15m3 = 1<<31 - 1<<15 - 1<<3
+
+// p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can
+// subtract smaller amounts without underflow. See the section "Subtraction" in
+// [1] for reasoning.
+var p224ZeroModP31 = []uint32{two31p3, two31m3, two31m3, two31m15m3, two31m3, two31m3, two31m3, two31m3}
+
+// p224Sub computes *out = a-b
+//
+// a[i], b[i] < 2**30
+// out[i] < 2**32
+func p224Sub(out, a, b *p224FieldElement) {
+	for i := 0; i < 8; i++ {
+		out[i] = a[i] + p224ZeroModP31[i] - b[i]
+	}
+}
+
+// LargeFieldElement also represents an element of the field. The limbs are
+// still spaced 28-bits apart and in little-endian order. So the limbs are at
+// 0, 28, 56, ..., 392 bits, each 64-bits wide.
+type p224LargeFieldElement [15]uint64
+
+const two63p35 = 1<<63 + 1<<35
+const two63m35 = 1<<63 - 1<<35
+const two63m35m19 = 1<<63 - 1<<35 - 1<<19
+
+// p224ZeroModP63 is 0 mod p where bit 63 is set in all limbs. See the section
+// "Subtraction" in [1] for why.
+var p224ZeroModP63 = [8]uint64{two63p35, two63m35, two63m35, two63m35, two63m35m19, two63m35, two63m35, two63m35}
+
+const bottom12Bits = 0xfff
+const bottom28Bits = 0xfffffff
+
+// p224Mul computes *out = a*b
+//
+// a[i] < 2**29, b[i] < 2**30 (or vice versa)
+// out[i] < 2**29
+func p224Mul(out, a, b *p224FieldElement, tmp *p224LargeFieldElement) {
+	for i := 0; i < 15; i++ {
+		tmp[i] = 0
+	}
+
+	for i := 0; i < 8; i++ {
+		for j := 0; j < 8; j++ {
+			tmp[i+j] += uint64(a[i]) * uint64(b[j])
+		}
+	}
+
+	p224ReduceLarge(out, tmp)
+}
+
+// Square computes *out = a*a
+//
+// a[i] < 2**29
+// out[i] < 2**29
+func p224Square(out, a *p224FieldElement, tmp *p224LargeFieldElement) {
+	for i := 0; i < 15; i++ {
+		tmp[i] = 0
+	}
+
+	for i := 0; i < 8; i++ {
+		for j := 0; j <= i; j++ {
+			r := uint64(a[i]) * uint64(a[j])
+			if i == j {
+				tmp[i+j] += r
+			} else {
+				tmp[i+j] += r << 1
+			}
+		}
+	}
+
+	p224ReduceLarge(out, tmp)
+}
+
+// ReduceLarge converts a p224LargeFieldElement to a p224FieldElement.
+//
+// in[i] < 2**62
+func p224ReduceLarge(out *p224FieldElement, in *p224LargeFieldElement) {
+	for i := 0; i < 8; i++ {
+		in[i] += p224ZeroModP63[i]
+	}
+
+	// Elimintate the coefficients at 2**224 and greater.
+	for i := 14; i >= 8; i-- {
+		in[i-8] -= in[i]
+		in[i-5] += (in[i] & 0xffff) << 12
+		in[i-4] += in[i] >> 16
+	}
+	in[8] = 0
+	// in[0..8] < 2**64
+
+	// As the values become small enough, we start to store them in |out|
+	// and use 32-bit operations.
+	for i := 1; i < 8; i++ {
+		in[i+1] += in[i] >> 28
+		out[i] = uint32(in[i] & bottom28Bits)
+	}
+	in[0] -= in[8]
+	out[3] += uint32(in[8]&0xffff) << 12
+	out[4] += uint32(in[8] >> 16)
+	// in[0] < 2**64
+	// out[3] < 2**29
+	// out[4] < 2**29
+	// out[1,2,5..7] < 2**28
+
+	out[0] = uint32(in[0] & bottom28Bits)
+	out[1] += uint32((in[0] >> 28) & bottom28Bits)
+	out[2] += uint32(in[0] >> 56)
+	// out[0] < 2**28
+	// out[1..4] < 2**29
+	// out[5..7] < 2**28
+}
+
+// Reduce reduces the coefficients of a to smaller bounds.
+//
+// On entry: a[i] < 2**31 + 2**30
+// On exit: a[i] < 2**29
+func p224Reduce(a *p224FieldElement) {
+	for i := 0; i < 7; i++ {
+		a[i+1] += a[i] >> 28
+		a[i] &= bottom28Bits
+	}
+	top := a[7] >> 28
+	a[7] &= bottom28Bits
+
+	// top < 2**4
+	mask := top
+	mask |= mask >> 2
+	mask |= mask >> 1
+	mask <<= 31
+	mask = uint32(int32(mask) >> 31)
+	// Mask is all ones if top != 0, all zero otherwise
+
+	a[0] -= top
+	a[3] += top << 12
+
+	// We may have just made a[0] negative but, if we did, then we must
+	// have added something to a[3], this it's > 2**12. Therefore we can
+	// carry down to a[0].
+	a[3] -= 1 & mask
+	a[2] += mask & (1<<28 - 1)
+	a[1] += mask & (1<<28 - 1)
+	a[0] += mask & (1 << 28)
+}
+
+// p224Invert calcuates *out = in**-1 by computing in**(2**224 - 2**96 - 1),
+// i.e. Fermat's little theorem.
+func p224Invert(out, in *p224FieldElement) {
+	var f1, f2, f3, f4 p224FieldElement
+	var c p224LargeFieldElement
+
+	p224Square(&f1, in, &c)    // 2
+	p224Mul(&f1, &f1, in, &c)  // 2**2 - 1
+	p224Square(&f1, &f1, &c)   // 2**3 - 2
+	p224Mul(&f1, &f1, in, &c)  // 2**3 - 1
+	p224Square(&f2, &f1, &c)   // 2**4 - 2
+	p224Square(&f2, &f2, &c)   // 2**5 - 4
+	p224Square(&f2, &f2, &c)   // 2**6 - 8
+	p224Mul(&f1, &f1, &f2, &c) // 2**6 - 1
+	p224Square(&f2, &f1, &c)   // 2**7 - 2
+	for i := 0; i < 5; i++ {   // 2**12 - 2**6
+		p224Square(&f2, &f2, &c)
+	}
+	p224Mul(&f2, &f2, &f1, &c) // 2**12 - 1
+	p224Square(&f3, &f2, &c)   // 2**13 - 2
+	for i := 0; i < 11; i++ {  // 2**24 - 2**12
+		p224Square(&f3, &f3, &c)
+	}
+	p224Mul(&f2, &f3, &f2, &c) // 2**24 - 1
+	p224Square(&f3, &f2, &c)   // 2**25 - 2
+	for i := 0; i < 23; i++ {  // 2**48 - 2**24
+		p224Square(&f3, &f3, &c)
+	}
+	p224Mul(&f3, &f3, &f2, &c) // 2**48 - 1
+	p224Square(&f4, &f3, &c)   // 2**49 - 2
+	for i := 0; i < 47; i++ {  // 2**96 - 2**48
+		p224Square(&f4, &f4, &c)
+	}
+	p224Mul(&f3, &f3, &f4, &c) // 2**96 - 1
+	p224Square(&f4, &f3, &c)   // 2**97 - 2
+	for i := 0; i < 23; i++ {  // 2**120 - 2**24
+		p224Square(&f4, &f4, &c)
+	}
+	p224Mul(&f2, &f4, &f2, &c) // 2**120 - 1
+	for i := 0; i < 6; i++ {   // 2**126 - 2**6
+		p224Square(&f2, &f2, &c)
+	}
+	p224Mul(&f1, &f1, &f2, &c) // 2**126 - 1
+	p224Square(&f1, &f1, &c)   // 2**127 - 2
+	p224Mul(&f1, &f1, in, &c)  // 2**127 - 1
+	for i := 0; i < 97; i++ {  // 2**224 - 2**97
+		p224Square(&f1, &f1, &c)
+	}
+	p224Mul(out, &f1, &f3, &c) // 2**224 - 2**96 - 1
+}
+
+// p224Contract converts a FieldElement to its unique, minimal form.
+//
+// On entry, in[i] < 2**32
+// On exit, in[i] < 2**28
+func p224Contract(out, in *p224FieldElement) {
+	copy(out[:], in[:])
+
+	for i := 0; i < 7; i++ {
+		out[i+1] += out[i] >> 28
+		out[i] &= bottom28Bits
+	}
+	top := out[7] >> 28
+	out[7] &= bottom28Bits
+
+	out[0] -= top
+	out[3] += top << 12
+
+	// We may just have made out[i] negative. So we carry down. If we made
+	// out[0] negative then we know that out[3] is sufficiently positive
+	// because we just added to it.
+	for i := 0; i < 3; i++ {
+		mask := uint32(int32(out[i]) >> 31)
+		out[i] += (1 << 28) & mask
+		out[i+1] -= 1 & mask
+	}
+
+	// Now we see if the value is >= p and, if so, subtract p.
+
+	// First we build a mask from the top four limbs, which must all be
+	// equal to bottom28Bits if the whole value is >= p. If top4AllOnes
+	// ends up with any zero bits in the bottom 28 bits, then this wasn't
+	// true.
+	top4AllOnes := uint32(0xffffffff)
+	for i := 4; i < 8; i++ {
+		top4AllOnes &= (out[i] & bottom28Bits) - 1
+	}
+	top4AllOnes |= 0xf0000000
+	// Now we replicate any zero bits to all the bits in top4AllOnes.
+	top4AllOnes &= top4AllOnes >> 16
+	top4AllOnes &= top4AllOnes >> 8
+	top4AllOnes &= top4AllOnes >> 4
+	top4AllOnes &= top4AllOnes >> 2
+	top4AllOnes &= top4AllOnes >> 1
+	top4AllOnes = uint32(int32(top4AllOnes<<31) >> 31)
+
+	// Now we test whether the bottom three limbs are non-zero.
+	bottom3NonZero := out[0] | out[1] | out[2]
+	bottom3NonZero |= bottom3NonZero >> 16
+	bottom3NonZero |= bottom3NonZero >> 8
+	bottom3NonZero |= bottom3NonZero >> 4
+	bottom3NonZero |= bottom3NonZero >> 2
+	bottom3NonZero |= bottom3NonZero >> 1
+	bottom3NonZero = uint32(int32(bottom3NonZero<<31) >> 31)
+
+	// Everything depends on the value of out[3].
+	//    If it's > 0xffff000 and top4AllOnes != 0 then the whole value is >= p
+	//    If it's = 0xffff000 and top4AllOnes != 0 and bottom3NonZero != 0,
+	//      then the whole value is >= p
+	//    If it's < 0xffff000, then the whole value is < p
+	n := out[3] - 0xffff000
+	out3Equal := n
+	out3Equal |= out3Equal >> 16
+	out3Equal |= out3Equal >> 8
+	out3Equal |= out3Equal >> 4
+	out3Equal |= out3Equal >> 2
+	out3Equal |= out3Equal >> 1
+	out3Equal = ^uint32(int32(out3Equal<<31) >> 31)
+
+	// If out[3] > 0xffff000 then n's MSB will be zero.
+	out3GT := ^uint32(int32(n<<31) >> 31)
+
+	mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT)
+	out[0] -= 1 & mask
+	out[3] -= 0xffff000 & mask
+	out[4] -= 0xfffffff & mask
+	out[5] -= 0xfffffff & mask
+	out[6] -= 0xfffffff & mask
+	out[7] -= 0xfffffff & mask
+}
+
+// Group element functions.
+//
+// These functions deal with group elements. The group is an elliptic curve
+// group with a = -3 defined in FIPS 186-3, section D.2.2.
+
+// p224AddJacobian computes *out = a+b where a != b.
+func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) {
+	// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl
+	var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement
+	var c p224LargeFieldElement
+
+	// Z1Z1 = Z1²
+	p224Square(&z1z1, z1, &c)
+	// Z2Z2 = Z2²
+	p224Square(&z2z2, z2, &c)
+	// U1 = X1*Z2Z2
+	p224Mul(&u1, x1, &z2z2, &c)
+	// U2 = X2*Z1Z1
+	p224Mul(&u2, x2, &z1z1, &c)
+	// S1 = Y1*Z2*Z2Z2
+	p224Mul(&s1, z2, &z2z2, &c)
+	p224Mul(&s1, y1, &s1, &c)
+	// S2 = Y2*Z1*Z1Z1
+	p224Mul(&s2, z1, &z1z1, &c)
+	p224Mul(&s2, y2, &s2, &c)
+	// H = U2-U1
+	p224Sub(&h, &u2, &u1)
+	p224Reduce(&h)
+	// I = (2*H)²
+	for j := 0; j < 8; j++ {
+		i[j] = h[j] << 1
+	}
+	p224Reduce(&i)
+	p224Square(&i, &i, &c)
+	// J = H*I
+	p224Mul(&j, &h, &i, &c)
+	// r = 2*(S2-S1)
+	p224Sub(&r, &s2, &s1)
+	p224Reduce(&r)
+	for i := 0; i < 8; i++ {
+		r[i] <<= 1
+	}
+	p224Reduce(&r)
+	// V = U1*I
+	p224Mul(&v, &u1, &i, &c)
+	// Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H
+	p224Add(&z1z1, &z1z1, &z2z2)
+	p224Add(&z2z2, z1, z2)
+	p224Reduce(&z2z2)
+	p224Square(&z2z2, &z2z2, &c)
+	p224Sub(z3, &z2z2, &z1z1)
+	p224Reduce(z3)
+	p224Mul(z3, z3, &h, &c)
+	// X3 = r²-J-2*V
+	for i := 0; i < 8; i++ {
+		z1z1[i] = v[i] << 1
+	}
+	p224Add(&z1z1, &j, &z1z1)
+	p224Reduce(&z1z1)
+	p224Square(x3, &r, &c)
+	p224Sub(x3, x3, &z1z1)
+	p224Reduce(x3)
+	// Y3 = r*(V-X3)-2*S1*J
+	for i := 0; i < 8; i++ {
+		s1[i] <<= 1
+	}
+	p224Mul(&s1, &s1, &j, &c)
+	p224Sub(&z1z1, &v, x3)
+	p224Reduce(&z1z1)
+	p224Mul(&z1z1, &z1z1, &r, &c)
+	p224Sub(y3, &z1z1, &s1)
+	p224Reduce(y3)
+}
+
+// p224DoubleJacobian computes *out = a+a.
+func p224DoubleJacobian(x3, y3, z3, x1, y1, z1 *p224FieldElement) {
+	var delta, gamma, beta, alpha, t p224FieldElement
+	var c p224LargeFieldElement
+
+	p224Square(&delta, z1, &c)
+	p224Square(&gamma, y1, &c)
+	p224Mul(&beta, x1, &gamma, &c)
+
+	// alpha = 3*(X1-delta)*(X1+delta)
+	p224Add(&t, x1, &delta)
+	for i := 0; i < 8; i++ {
+		t[i] += t[i] << 1
+	}
+	p224Reduce(&t)
+	p224Sub(&alpha, x1, &delta)
+	p224Reduce(&alpha)
+	p224Mul(&alpha, &alpha, &t, &c)
+
+	// Z3 = (Y1+Z1)²-gamma-delta
+	p224Add(z3, y1, z1)
+	p224Reduce(z3)
+	p224Square(z3, z3, &c)
+	p224Sub(z3, z3, &gamma)
+	p224Reduce(z3)
+	p224Sub(z3, z3, &delta)
+	p224Reduce(z3)
+
+	// X3 = alpha²-8*beta
+	for i := 0; i < 8; i++ {
+		delta[i] = beta[i] << 3
+	}
+	p224Reduce(&delta)
+	p224Square(x3, &alpha, &c)
+	p224Sub(x3, x3, &delta)
+	p224Reduce(x3)
+
+	// Y3 = alpha*(4*beta-X3)-8*gamma²
+	for i := 0; i < 8; i++ {
+		beta[i] <<= 2
+	}
+	p224Sub(&beta, &beta, x3)
+	p224Reduce(&beta)
+	p224Square(&gamma, &gamma, &c)
+	for i := 0; i < 8; i++ {
+		gamma[i] <<= 3
+	}
+	p224Reduce(&gamma)
+	p224Mul(y3, &alpha, &beta, &c)
+	p224Sub(y3, y3, &gamma)
+	p224Reduce(y3)
+}
+
+// p224CopyConditional sets *out = *in iff the least-significant-bit of control
+// is true, and it runs in constant time.
+func p224CopyConditional(out, in *p224FieldElement, control uint32) {
+	control <<= 31
+	control = uint32(int32(control) >> 31)
+
+	for i := 0; i < 8; i++ {
+		out[i] ^= (out[i] ^ in[i]) & control
+	}
+}
+
+func p224ScalarMult(outX, outY, outZ, inX, inY, inZ *p224FieldElement, scalar []byte) {
+	var xx, yy, zz p224FieldElement
+	for i := 0; i < 8; i++ {
+		outZ[i] = 0
+	}
+
+	firstBit := uint32(1)
+	for _, byte := range scalar {
+		for bitNum := uint(0); bitNum < 8; bitNum++ {
+			p224DoubleJacobian(outX, outY, outZ, outX, outY, outZ)
+			bit := uint32((byte >> (7 - bitNum)) & 1)
+			p224AddJacobian(&xx, &yy, &zz, inX, inY, inZ, outX, outY, outZ)
+			p224CopyConditional(outX, inX, firstBit&bit)
+			p224CopyConditional(outY, inY, firstBit&bit)
+			p224CopyConditional(outZ, inZ, firstBit&bit)
+			p224CopyConditional(outX, &xx, ^firstBit&bit)
+			p224CopyConditional(outY, &yy, ^firstBit&bit)
+			p224CopyConditional(outZ, &zz, ^firstBit&bit)
+			firstBit = firstBit & ^bit
+		}
+	}
+}
+
+// p224ToAffine converts from Jacobian to affine form.
+func p224ToAffine(x, y, z *p224FieldElement) (*big.Int, *big.Int) {
+	var zinv, zinvsq, outx, outy p224FieldElement
+	var tmp p224LargeFieldElement
+
+	isPointAtInfinity := true
+	for i := 0; i < 8; i++ {
+		if z[i] != 0 {
+			isPointAtInfinity = false
+			break
+		}
+	}
+
+	if isPointAtInfinity {
+		return nil, nil
+	}
+
+	p224Invert(&zinv, z)
+	p224Square(&zinvsq, &zinv, &tmp)
+	p224Mul(x, x, &zinvsq, &tmp)
+	p224Mul(&zinvsq, &zinvsq, &zinv, &tmp)
+	p224Mul(y, y, &zinvsq, &tmp)
+
+	p224Contract(&outx, x)
+	p224Contract(&outy, y)
+	return p224ToBig(&outx), p224ToBig(&outy)
+}
+
+// get28BitsFromEnd returns the least-significant 28 bits from buf>>shift,
+// where buf is interpreted as a big-endian number.
+func get28BitsFromEnd(buf []byte, shift uint) (uint32, []byte) {
+	var ret uint32
+
+	for i := uint(0); i < 4; i++ {
+		var b byte
+		if l := len(buf); l > 0 {
+			b = buf[l-1]
+			// We don't remove the byte if we're about to return and we're not
+			// reading all of it.
+			if i != 3 || shift == 4 {
+				buf = buf[:l-1]
+			}
+		}
+		ret |= uint32(b) << (8 * i) >> shift
+	}
+	ret &= bottom28Bits
+	return ret, buf
+}
+
+// p224FromBig sets *out = *in.
+func p224FromBig(out *p224FieldElement, in *big.Int) {
+	bytes := in.Bytes()
+	out[0], bytes = get28BitsFromEnd(bytes, 0)
+	out[1], bytes = get28BitsFromEnd(bytes, 4)
+	out[2], bytes = get28BitsFromEnd(bytes, 0)
+	out[3], bytes = get28BitsFromEnd(bytes, 4)
+	out[4], bytes = get28BitsFromEnd(bytes, 0)
+	out[5], bytes = get28BitsFromEnd(bytes, 4)
+	out[6], bytes = get28BitsFromEnd(bytes, 0)
+	out[7], bytes = get28BitsFromEnd(bytes, 4)
+}
+
+// p224ToBig returns in as a big.Int.
+func p224ToBig(in *p224FieldElement) *big.Int {
+	var buf [28]byte
+	buf[27] = byte(in[0])
+	buf[26] = byte(in[0] >> 8)
+	buf[25] = byte(in[0] >> 16)
+	buf[24] = byte(((in[0] >> 24) & 0x0f) | (in[1]<<4)&0xf0)
+
+	buf[23] = byte(in[1] >> 4)
+	buf[22] = byte(in[1] >> 12)
+	buf[21] = byte(in[1] >> 20)
+
+	buf[20] = byte(in[2])
+	buf[19] = byte(in[2] >> 8)
+	buf[18] = byte(in[2] >> 16)
+	buf[17] = byte(((in[2] >> 24) & 0x0f) | (in[3]<<4)&0xf0)
+
+	buf[16] = byte(in[3] >> 4)
+	buf[15] = byte(in[3] >> 12)
+	buf[14] = byte(in[3] >> 20)
+
+	buf[13] = byte(in[4])
+	buf[12] = byte(in[4] >> 8)
+	buf[11] = byte(in[4] >> 16)
+	buf[10] = byte(((in[4] >> 24) & 0x0f) | (in[5]<<4)&0xf0)
+
+	buf[9] = byte(in[5] >> 4)
+	buf[8] = byte(in[5] >> 12)
+	buf[7] = byte(in[5] >> 20)
+
+	buf[6] = byte(in[6])
+	buf[5] = byte(in[6] >> 8)
+	buf[4] = byte(in[6] >> 16)
+	buf[3] = byte(((in[6] >> 24) & 0x0f) | (in[7]<<4)&0xf0)
+
+	buf[2] = byte(in[7] >> 4)
+	buf[1] = byte(in[7] >> 12)
+	buf[0] = byte(in[7] >> 20)
+
+	return new(big.Int).SetBytes(buf[:])
+}
diff --git a/src/pkg/crypto/elliptic/p224_test.go b/src/pkg/crypto/elliptic/p224_test.go
new file mode 100644
index 0000000..4b26d16
--- /dev/null
+++ b/src/pkg/crypto/elliptic/p224_test.go
@@ -0,0 +1,47 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elliptic
+
+import (
+	"math/big"
+	"testing"
+)
+
+var toFromBigTests = []string{
+	"0",
+	"1",
+	"23",
+	"b70e0cb46bb4bf7f321390b94a03c1d356c01122343280d6105c1d21",
+	"706a46d476dcb76798e6046d89474788d164c18032d268fd10704fa6",
+}
+
+func p224AlternativeToBig(in *p224FieldElement) *big.Int {
+	ret := new(big.Int)
+	tmp := new(big.Int)
+
+	for i := uint(0); i < 8; i++ {
+		tmp.SetInt64(int64(in[i]))
+		tmp.Lsh(tmp, 28*i)
+		ret.Add(ret, tmp)
+	}
+	ret.Mod(ret, p224.P)
+	return ret
+}
+
+func TestToFromBig(t *testing.T) {
+	for i, test := range toFromBigTests {
+		n, _ := new(big.Int).SetString(test, 16)
+		var x p224FieldElement
+		p224FromBig(&x, n)
+		m := p224ToBig(&x)
+		if n.Cmp(m) != 0 {
+			t.Errorf("#%d: %x != %x", i, n, m)
+		}
+		q := p224AlternativeToBig(&x)
+		if n.Cmp(q) != 0 {
+			t.Errorf("#%d: %x != %x (alternative)", i, n, m)
+		}
+	}
+}
diff --git a/src/pkg/crypto/hmac/hmac.go b/src/pkg/crypto/hmac/hmac.go
index 04ec86e..a97ce09 100644
--- a/src/pkg/crypto/hmac/hmac.go
+++ b/src/pkg/crypto/hmac/hmac.go
@@ -9,33 +9,20 @@
 package hmac
 
 import (
-	"crypto/md5"
-	"crypto/sha1"
-	"crypto/sha256"
 	"hash"
-	"os"
 )
 
 // FIPS 198:
 // http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
 
-// key is zero padded to 64 bytes
-// ipad = 0x36 byte repeated to 64 bytes
-// opad = 0x5c byte repeated to 64 bytes
+// key is zero padded to the block size of the hash function
+// ipad = 0x36 byte repeated for key length
+// opad = 0x5c byte repeated for key length
 // hmac = H([key ^ opad] H([key ^ ipad] text))
 
-const (
-	// NOTE(rsc): This constant is actually the
-	// underlying hash function's block size.
-	// HMAC is only conventionally used with
-	// MD5 and SHA1, and both use 64-byte blocks.
-	// The hash.Hash interface doesn't provide a
-	// way to find out the block size.
-	padSize = 64
-)
-
 type hmac struct {
 	size         int
+	blocksize    int
 	key, tmp     []byte
 	outer, inner hash.Hash
 }
@@ -44,57 +31,50 @@ func (h *hmac) tmpPad(xor byte) {
 	for i, k := range h.key {
 		h.tmp[i] = xor ^ k
 	}
-	for i := len(h.key); i < padSize; i++ {
+	for i := len(h.key); i < h.blocksize; i++ {
 		h.tmp[i] = xor
 	}
 }
 
-func (h *hmac) Sum() []byte {
-	sum := h.inner.Sum()
+func (h *hmac) Sum(in []byte) []byte {
+	origLen := len(in)
+	in = h.inner.Sum(in)
 	h.tmpPad(0x5c)
-	for i, b := range sum {
-		h.tmp[padSize+i] = b
-	}
+	copy(h.tmp[h.blocksize:], in[origLen:])
 	h.outer.Reset()
 	h.outer.Write(h.tmp)
-	return h.outer.Sum()
+	return h.outer.Sum(in[:origLen])
 }
 
-func (h *hmac) Write(p []byte) (n int, err os.Error) {
+func (h *hmac) Write(p []byte) (n int, err error) {
 	return h.inner.Write(p)
 }
 
 func (h *hmac) Size() int { return h.size }
 
+func (h *hmac) BlockSize() int { return h.blocksize }
+
 func (h *hmac) Reset() {
 	h.inner.Reset()
 	h.tmpPad(0x36)
-	h.inner.Write(h.tmp[0:padSize])
+	h.inner.Write(h.tmp[0:h.blocksize])
 }
 
-// New returns a new HMAC hash using the given hash generator and key.
+// New returns a new HMAC hash using the given hash.Hash type and key.
 func New(h func() hash.Hash, key []byte) hash.Hash {
 	hm := new(hmac)
 	hm.outer = h()
 	hm.inner = h()
 	hm.size = hm.inner.Size()
-	hm.tmp = make([]byte, padSize+hm.size)
-	if len(key) > padSize {
+	hm.blocksize = hm.inner.BlockSize()
+	hm.tmp = make([]byte, hm.blocksize+hm.size)
+	if len(key) > hm.blocksize {
 		// If key is too big, hash it.
 		hm.outer.Write(key)
-		key = hm.outer.Sum()
+		key = hm.outer.Sum(nil)
 	}
 	hm.key = make([]byte, len(key))
 	copy(hm.key, key)
 	hm.Reset()
 	return hm
 }
-
-// NewMD5 returns a new HMAC-MD5 hash using the given key.
-func NewMD5(key []byte) hash.Hash { return New(md5.New, key) }
-
-// NewSHA1 returns a new HMAC-SHA1 hash using the given key.
-func NewSHA1(key []byte) hash.Hash { return New(sha1.New, key) }
-
-// NewSHA256 returns a new HMAC-SHA256 hash using the given key.
-func NewSHA256(key []byte) hash.Hash { return New(sha256.New, key) }
diff --git a/src/pkg/crypto/hmac/hmac_test.go b/src/pkg/crypto/hmac/hmac_test.go
index bcae63b..0795741 100644
--- a/src/pkg/crypto/hmac/hmac_test.go
+++ b/src/pkg/crypto/hmac/hmac_test.go
@@ -5,13 +5,17 @@
 package hmac
 
 import (
-	"hash"
+	"crypto/md5"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/sha512"
 	"fmt"
+	"hash"
 	"testing"
 )
 
 type hmacTest struct {
-	hash func([]byte) hash.Hash
+	hash func() hash.Hash
 	key  []byte
 	in   []byte
 	out  string
@@ -21,7 +25,7 @@ var hmacTests = []hmacTest{
 	// Tests from US FIPS 198
 	// http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
 	{
-		NewSHA1,
+		sha1.New,
 		[]byte{
 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
@@ -36,7 +40,7 @@ var hmacTests = []hmacTest{
 		"4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a",
 	},
 	{
-		NewSHA1,
+		sha1.New,
 		[]byte{
 			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
 			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
@@ -46,7 +50,7 @@ var hmacTests = []hmacTest{
 		"0922d3405faa3d194f82a45830737d5cc6c75d24",
 	},
 	{
-		NewSHA1,
+		sha1.New,
 		[]byte{
 			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
 			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
@@ -68,7 +72,7 @@ var hmacTests = []hmacTest{
 
 	// Test from Plan 9.
 	{
-		NewMD5,
+		md5.New,
 		[]byte("Jefe"),
 		[]byte("what do ya want for nothing?"),
 		"750c783e6ab0b503eaa86e310a5db738",
@@ -76,7 +80,7 @@ var hmacTests = []hmacTest{
 
 	// Tests from RFC 4231
 	{
-		NewSHA256,
+		sha256.New,
 		[]byte{
 			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
 			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
@@ -86,13 +90,13 @@ var hmacTests = []hmacTest{
 		"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
 	},
 	{
-		NewSHA256,
+		sha256.New,
 		[]byte("Jefe"),
 		[]byte("what do ya want for nothing?"),
 		"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
 	},
 	{
-		NewSHA256,
+		sha256.New,
 		[]byte{
 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
@@ -110,7 +114,7 @@ var hmacTests = []hmacTest{
 		"773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
 	},
 	{
-		NewSHA256,
+		sha256.New,
 		[]byte{
 			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
 			0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
@@ -129,7 +133,7 @@ var hmacTests = []hmacTest{
 		"82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
 	},
 	{
-		NewSHA256,
+		sha256.New,
 		[]byte{
 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
@@ -153,7 +157,7 @@ var hmacTests = []hmacTest{
 		"60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
 	},
 	{
-		NewSHA256,
+		sha256.New,
 		[]byte{
 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
 			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
@@ -178,11 +182,295 @@ var hmacTests = []hmacTest{
 			"be hashed before being used by the HMAC algorithm."),
 		"9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
 	},
+
+	// Tests from http://csrc.nist.gov/groups/ST/toolkit/examples.html
+	// (truncated tag tests are left out)
+	{
+		sha1.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"5fd596ee78d5553c8ff4e72d266dfd192366da29",
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"4c99ff0cb1b31bd33f8431dbaf4d17fcd356a807",
+	},
+	{
+		sha1.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"2d51b2f7750e410584662e38f133435f4c4fd42a",
+	},
+	{
+		sha256.New224,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"c7405e3ae058e8cd30b08b4140248581ed174cb34e1224bcc1efc81b",
+	},
+	{
+		sha256.New224,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"e3d249a8cfb67ef8b7a169e9a0a599714a2cecba65999a51beb8fbbe",
+	},
+	{
+		sha256.New224,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"91c52509e5af8531601ae6230099d90bef88aaefb961f4080abc014d",
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"8bb9a1db9806f20df7f77b82138c7914d174d59e13dc4d0169c9057b133e1d62",
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"a28cf43130ee696a98f14a37678b56bcfcbdd9e5cf69717fecf5480f0ebdf790",
+	},
+	{
+		sha256.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"bdccb6c72ddeadb500ae768386cb38cc41c63dbb0878ddb9c7a38a431b78378d",
+	},
+	{
+		sha512.New384,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"63c5daa5e651847ca897c95814ab830bededc7d25e83eef9195cd45857a37f448947858f5af50cc2b1b730ddf29671a9",
+	},
+	{
+		sha512.New384,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"6eb242bdbb582ca17bebfa481b1e23211464d2b7f8c20b9ff2201637b93646af5ae9ac316e98db45d9cae773675eeed0",
+	},
+	{
+		sha512.New384,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"5b664436df69b0ca22551231a3f0a3d5b4f97991713cfa84bff4d0792eff96c27dccbbb6f79b65d548b40e8564cef594",
+	},
+	{
+		sha512.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"fc25e240658ca785b7a811a8d3f7b4ca" +
+			"48cfa26a8a366bf2cd1f836b05fcb024bd36853081811d6c" +
+			"ea4216ebad79da1cfcb95ea4586b8a0ce356596a55fb1347",
+	},
+	{
+		sha512.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		},
+		[]byte("Sample message for keylen<blocklen"),
+		"fd44c18bda0bb0a6ce0e82b031bf2818" +
+			"f6539bd56ec00bdc10a8a2d730b3634de2545d639b0f2cf7" +
+			"10d0692c72a1896f1f211c2b922d1a96c392e07e7ea9fedc",
+	},
+	{
+		sha512.New,
+		[]byte{
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+		},
+		[]byte("Sample message for keylen=blocklen"),
+		"d93ec8d2de1ad2a9957cb9b83f14e76a" +
+			"d6b5e0cce285079a127d3b14bccb7aa7286d4ac0d4ce6421" +
+			"5f2bc9e6870b33d97438be4aaa20cda5c5a912b48b8e27f3",
+	},
 }
 
 func TestHMAC(t *testing.T) {
 	for i, tt := range hmacTests {
-		h := tt.hash(tt.key)
+		h := New(tt.hash, tt.key)
 		for j := 0; j < 2; j++ {
 			n, err := h.Write(tt.in)
 			if n != len(tt.in) || err != nil {
@@ -192,7 +480,7 @@ func TestHMAC(t *testing.T) {
 
 			// Repetitive Sum() calls should return the same value
 			for k := 0; k < 2; k++ {
-				sum := fmt.Sprintf("%x", h.Sum())
+				sum := fmt.Sprintf("%x", h.Sum(nil))
 				if sum != tt.out {
 					t.Errorf("test %d.%d.%d: have %s want %s\n", i, j, k, sum, tt.out)
 				}
diff --git a/src/pkg/crypto/md4/Makefile b/src/pkg/crypto/md4/Makefile
deleted file mode 100644
index eef05ab..0000000
--- a/src/pkg/crypto/md4/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/md4
-GOFILES=\
-	md4.go\
-	md4block.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/md4/md4.go b/src/pkg/crypto/md4/md4.go
deleted file mode 100644
index 848d955..0000000
--- a/src/pkg/crypto/md4/md4.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
-package md4
-
-import (
-	"crypto"
-	"hash"
-	"os"
-)
-
-func init() {
-	crypto.RegisterHash(crypto.MD4, New)
-}
-
-// The size of an MD4 checksum in bytes.
-const Size = 16
-
-const (
-	_Chunk = 64
-	_Init0 = 0x67452301
-	_Init1 = 0xEFCDAB89
-	_Init2 = 0x98BADCFE
-	_Init3 = 0x10325476
-)
-
-// digest represents the partial evaluation of a checksum.
-type digest struct {
-	s   [4]uint32
-	x   [_Chunk]byte
-	nx  int
-	len uint64
-}
-
-func (d *digest) Reset() {
-	d.s[0] = _Init0
-	d.s[1] = _Init1
-	d.s[2] = _Init2
-	d.s[3] = _Init3
-	d.nx = 0
-	d.len = 0
-}
-
-// New returns a new hash.Hash computing the MD4 checksum.
-func New() hash.Hash {
-	d := new(digest)
-	d.Reset()
-	return d
-}
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) Write(p []byte) (nn int, err os.Error) {
-	nn = len(p)
-	d.len += uint64(nn)
-	if d.nx > 0 {
-		n := len(p)
-		if n > _Chunk-d.nx {
-			n = _Chunk - d.nx
-		}
-		for i := 0; i < n; i++ {
-			d.x[d.nx+i] = p[i]
-		}
-		d.nx += n
-		if d.nx == _Chunk {
-			_Block(d, d.x[0:])
-			d.nx = 0
-		}
-		p = p[n:]
-	}
-	n := _Block(d, p)
-	p = p[n:]
-	if len(p) > 0 {
-		d.nx = copy(d.x[:], p)
-	}
-	return
-}
-
-func (d0 *digest) Sum() []byte {
-	// Make a copy of d0, so that caller can keep writing and summing.
-	d := new(digest)
-	*d = *d0
-
-	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
-	len := d.len
-	var tmp [64]byte
-	tmp[0] = 0x80
-	if len%64 < 56 {
-		d.Write(tmp[0 : 56-len%64])
-	} else {
-		d.Write(tmp[0 : 64+56-len%64])
-	}
-
-	// Length in bits.
-	len <<= 3
-	for i := uint(0); i < 8; i++ {
-		tmp[i] = byte(len >> (8 * i))
-	}
-	d.Write(tmp[0:8])
-
-	if d.nx != 0 {
-		panic("d.nx != 0")
-	}
-
-	p := make([]byte, 16)
-	j := 0
-	for _, s := range d.s {
-		p[j+0] = byte(s >> 0)
-		p[j+1] = byte(s >> 8)
-		p[j+2] = byte(s >> 16)
-		p[j+3] = byte(s >> 24)
-		j += 4
-	}
-	return p
-}
diff --git a/src/pkg/crypto/md4/md4_test.go b/src/pkg/crypto/md4/md4_test.go
deleted file mode 100644
index 721bd4c..0000000
--- a/src/pkg/crypto/md4/md4_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package md4
-
-import (
-	"fmt"
-	"io"
-	"testing"
-)
-
-type md4Test struct {
-	out string
-	in  string
-}
-
-var golden = []md4Test{
-	{"31d6cfe0d16ae931b73c59d7e0c089c0", ""},
-	{"bde52cb31de33e46245e05fbdbd6fb24", "a"},
-	{"ec388dd78999dfc7cf4632465693b6bf", "ab"},
-	{"a448017aaf21d8525fc10ae87aa6729d", "abc"},
-	{"41decd8f579255c5200f86a4bb3ba740", "abcd"},
-	{"9803f4a34e8eb14f96adba49064a0c41", "abcde"},
-	{"804e7f1c2586e50b49ac65db5b645131", "abcdef"},
-	{"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"},
-	{"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"},
-	{"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"},
-	{"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"},
-	{"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."},
-	{"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."},
-	{"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."},
-	{"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
-	{"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered.  -Tom Stoppard"},
-	{"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."},
-	{"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."},
-	{"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."},
-	{"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
-	{"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
-	{"9ddc753e7a4ccee6081cd1b45b23a834", "size:  a.out:  bad magic"},
-	{"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail.  -Mark Horton"},
-	{"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
-	{"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."},
-	{"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."},
-	{"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."},
-	{"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"},
-	{"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
-	{"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
-	{"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++?  -Paul Glick"},
-}
-
-func TestGolden(t *testing.T) {
-	for i := 0; i < len(golden); i++ {
-		g := golden[i]
-		c := New()
-		for j := 0; j < 3; j++ {
-			if j < 2 {
-				io.WriteString(c, g.in)
-			} else {
-				io.WriteString(c, g.in[0:len(g.in)/2])
-				c.Sum()
-				io.WriteString(c, g.in[len(g.in)/2:])
-			}
-			s := fmt.Sprintf("%x", c.Sum())
-			if s != g.out {
-				t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out)
-			}
-			c.Reset()
-		}
-	}
-}
diff --git a/src/pkg/crypto/md4/md4block.go b/src/pkg/crypto/md4/md4block.go
deleted file mode 100644
index 3fed475..0000000
--- a/src/pkg/crypto/md4/md4block.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// MD4 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
-
-package md4
-
-var shift1 = []uint{3, 7, 11, 19}
-var shift2 = []uint{3, 5, 9, 13}
-var shift3 = []uint{3, 9, 11, 15}
-
-var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}
-var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}
-
-func _Block(dig *digest, p []byte) int {
-	a := dig.s[0]
-	b := dig.s[1]
-	c := dig.s[2]
-	d := dig.s[3]
-	n := 0
-	var X [16]uint32
-	for len(p) >= _Chunk {
-		aa, bb, cc, dd := a, b, c, d
-
-		j := 0
-		for i := 0; i < 16; i++ {
-			X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
-			j += 4
-		}
-
-		// If this needs to be made faster in the future,
-		// the usual trick is to unroll each of these
-		// loops by a factor of 4; that lets you replace
-		// the shift[] lookups with constants and,
-		// with suitable variable renaming in each
-		// unrolled body, delete the a, b, c, d = d, a, b, c
-		// (or you can let the optimizer do the renaming).
-		//
-		// The index variables are uint so that % by a power
-		// of two can be optimized easily by a compiler.
-
-		// Round 1.
-		for i := uint(0); i < 16; i++ {
-			x := i
-			s := shift1[i%4]
-			f := ((c ^ d) & b) ^ d
-			a += f + X[x]
-			a = a<<s | a>>(32-s)
-			a, b, c, d = d, a, b, c
-		}
-
-		// Round 2.
-		for i := uint(0); i < 16; i++ {
-			x := xIndex2[i]
-			s := shift2[i%4]
-			g := (b & c) | (b & d) | (c & d)
-			a += g + X[x] + 0x5a827999
-			a = a<<s | a>>(32-s)
-			a, b, c, d = d, a, b, c
-		}
-
-		// Round 3.
-		for i := uint(0); i < 16; i++ {
-			x := xIndex3[i]
-			s := shift3[i%4]
-			h := b ^ c ^ d
-			a += h + X[x] + 0x6ed9eba1
-			a = a<<s | a>>(32-s)
-			a, b, c, d = d, a, b, c
-		}
-
-		a += aa
-		b += bb
-		c += cc
-		d += dd
-
-		p = p[_Chunk:]
-		n += _Chunk
-	}
-
-	dig.s[0] = a
-	dig.s[1] = b
-	dig.s[2] = c
-	dig.s[3] = d
-	return n
-}
diff --git a/src/pkg/crypto/md5/md5.go b/src/pkg/crypto/md5/md5.go
index 378faa6..cfb728c 100644
--- a/src/pkg/crypto/md5/md5.go
+++ b/src/pkg/crypto/md5/md5.go
@@ -8,7 +8,6 @@ package md5
 import (
 	"crypto"
 	"hash"
-	"os"
 )
 
 func init() {
@@ -18,6 +17,9 @@ func init() {
 // The size of an MD5 checksum in bytes.
 const Size = 16
 
+// The blocksize of MD5 in bytes.
+const BlockSize = 64
+
 const (
 	_Chunk = 64
 	_Init0 = 0x67452301
@@ -52,7 +54,9 @@ func New() hash.Hash {
 
 func (d *digest) Size() int { return Size }
 
-func (d *digest) Write(p []byte) (nn int, err os.Error) {
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
 	nn = len(p)
 	d.len += uint64(nn)
 	if d.nx > 0 {
@@ -78,10 +82,9 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) {
 	return
 }
 
-func (d0 *digest) Sum() []byte {
+func (d0 *digest) Sum(in []byte) []byte {
 	// Make a copy of d0 so that caller can keep writing and summing.
-	d := new(digest)
-	*d = *d0
+	d := *d0
 
 	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
 	len := d.len
@@ -104,14 +107,13 @@ func (d0 *digest) Sum() []byte {
 		panic("d.nx != 0")
 	}
 
-	p := make([]byte, 16)
-	j := 0
-	for _, s := range d.s {
-		p[j+0] = byte(s >> 0)
-		p[j+1] = byte(s >> 8)
-		p[j+2] = byte(s >> 16)
-		p[j+3] = byte(s >> 24)
-		j += 4
+	var digest [Size]byte
+	for i, s := range d.s {
+		digest[i*4] = byte(s)
+		digest[i*4+1] = byte(s >> 8)
+		digest[i*4+2] = byte(s >> 16)
+		digest[i*4+3] = byte(s >> 24)
 	}
-	return p
+
+	return append(in, digest[:]...)
 }
diff --git a/src/pkg/crypto/md5/md5_test.go b/src/pkg/crypto/md5/md5_test.go
index 857002b..b15e466 100644
--- a/src/pkg/crypto/md5/md5_test.go
+++ b/src/pkg/crypto/md5/md5_test.go
@@ -58,10 +58,10 @@ func TestGolden(t *testing.T) {
 				io.WriteString(c, g.in)
 			} else {
 				io.WriteString(c, g.in[0:len(g.in)/2])
-				c.Sum()
+				c.Sum(nil)
 				io.WriteString(c, g.in[len(g.in)/2:])
 			}
-			s := fmt.Sprintf("%x", c.Sum())
+			s := fmt.Sprintf("%x", c.Sum(nil))
 			if s != g.out {
 				t.Fatalf("md5[%d](%s) = %s want %s", j, g.in, s, g.out)
 			}
diff --git a/src/pkg/crypto/ocsp/Makefile b/src/pkg/crypto/ocsp/Makefile
deleted file mode 100644
index 6e132ff..0000000
--- a/src/pkg/crypto/ocsp/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/ocsp
-GOFILES=\
-	ocsp.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/ocsp/ocsp.go b/src/pkg/crypto/ocsp/ocsp.go
deleted file mode 100644
index 7ea7a1e..0000000
--- a/src/pkg/crypto/ocsp/ocsp.go
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2010 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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
-// are signed messages attesting to the validity of a certificate for a small
-// period of time. This is used to manage revocation for X.509 certificates.
-package ocsp
-
-import (
-	"asn1"
-	"crypto"
-	"crypto/rsa"
-	_ "crypto/sha1"
-	"crypto/x509"
-	"crypto/x509/pkix"
-	"os"
-	"time"
-)
-
-var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
-var idSHA1WithRSA = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 1, 5})
-
-// These are internal structures that reflect the ASN.1 structure of an OCSP
-// response. See RFC 2560, section 4.2.
-
-const (
-	ocspSuccess       = 0
-	ocspMalformed     = 1
-	ocspInternalError = 2
-	ocspTryLater      = 3
-	ocspSigRequired   = 4
-	ocspUnauthorized  = 5
-)
-
-type certID struct {
-	HashAlgorithm pkix.AlgorithmIdentifier
-	NameHash      []byte
-	IssuerKeyHash []byte
-	SerialNumber  asn1.RawValue
-}
-
-type responseASN1 struct {
-	Status   asn1.Enumerated
-	Response responseBytes `asn1:"explicit,tag:0"`
-}
-
-type responseBytes struct {
-	ResponseType asn1.ObjectIdentifier
-	Response     []byte
-}
-
-type basicResponse struct {
-	TBSResponseData    responseData
-	SignatureAlgorithm pkix.AlgorithmIdentifier
-	Signature          asn1.BitString
-	Certificates       []asn1.RawValue `asn1:"explicit,tag:0,optional"`
-}
-
-type responseData struct {
-	Raw           asn1.RawContent
-	Version       int              `asn1:"optional,default:1,explicit,tag:0"`
-	RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"`
-	KeyHash       []byte           `asn1:"optional,explicit,tag:2"`
-	ProducedAt    *time.Time
-	Responses     []singleResponse
-}
-
-type singleResponse struct {
-	CertID     certID
-	Good       asn1.Flag   `asn1:"explicit,tag:0,optional"`
-	Revoked    revokedInfo `asn1:"explicit,tag:1,optional"`
-	Unknown    asn1.Flag   `asn1:"explicit,tag:2,optional"`
-	ThisUpdate *time.Time
-	NextUpdate *time.Time `asn1:"explicit,tag:0,optional"`
-}
-
-type revokedInfo struct {
-	RevocationTime *time.Time
-	Reason         int `asn1:"explicit,tag:0,optional"`
-}
-
-// This is the exposed reflection of the internal OCSP structures.
-
-const (
-	// Good means that the certificate is valid.
-	Good = iota
-	// Revoked means that the certificate has been deliberately revoked.
-	Revoked = iota
-	// Unknown means that the OCSP responder doesn't know about the certificate.
-	Unknown = iota
-	// ServerFailed means that the OCSP responder failed to process the request.
-	ServerFailed = iota
-)
-
-// Response represents an OCSP response. See RFC 2560.
-type Response struct {
-	// Status is one of {Good, Revoked, Unknown, ServerFailed}
-	Status                                        int
-	SerialNumber                                  []byte
-	ProducedAt, ThisUpdate, NextUpdate, RevokedAt *time.Time
-	RevocationReason                              int
-	Certificate                                   *x509.Certificate
-}
-
-// ParseError results from an invalid OCSP response.
-type ParseError string
-
-func (p ParseError) String() string {
-	return string(p)
-}
-
-// ParseResponse parses an OCSP response in DER form. It only supports
-// responses for a single certificate and only those using RSA signatures.
-// Non-RSA responses will result in an x509.UnsupportedAlgorithmError.
-// Signature errors or parse failures will result in a ParseError.
-func ParseResponse(bytes []byte) (*Response, os.Error) {
-	var resp responseASN1
-	rest, err := asn1.Unmarshal(bytes, &resp)
-	if err != nil {
-		return nil, err
-	}
-	if len(rest) > 0 {
-		return nil, ParseError("trailing data in OCSP response")
-	}
-
-	ret := new(Response)
-	if resp.Status != ocspSuccess {
-		ret.Status = ServerFailed
-		return ret, nil
-	}
-
-	if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
-		return nil, ParseError("bad OCSP response type")
-	}
-
-	var basicResp basicResponse
-	rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
-	if err != nil {
-		return nil, err
-	}
-
-	if len(basicResp.Certificates) != 1 {
-		return nil, ParseError("OCSP response contains bad number of certificates")
-	}
-
-	if len(basicResp.TBSResponseData.Responses) != 1 {
-		return nil, ParseError("OCSP response contains bad number of responses")
-	}
-
-	ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
-	if err != nil {
-		return nil, err
-	}
-
-	if ret.Certificate.PublicKeyAlgorithm != x509.RSA || !basicResp.SignatureAlgorithm.Algorithm.Equal(idSHA1WithRSA) {
-		return nil, x509.UnsupportedAlgorithmError{}
-	}
-
-	hashType := crypto.SHA1
-	h := hashType.New()
-
-	pub := ret.Certificate.PublicKey.(*rsa.PublicKey)
-	h.Write(basicResp.TBSResponseData.Raw)
-	digest := h.Sum()
-	signature := basicResp.Signature.RightAlign()
-
-	if rsa.VerifyPKCS1v15(pub, hashType, digest, signature) != nil {
-		return nil, ParseError("bad OCSP signature")
-	}
-
-	r := basicResp.TBSResponseData.Responses[0]
-
-	ret.SerialNumber = r.CertID.SerialNumber.Bytes
-
-	switch {
-	case bool(r.Good):
-		ret.Status = Good
-	case bool(r.Unknown):
-		ret.Status = Unknown
-	default:
-		ret.Status = Revoked
-		ret.RevokedAt = r.Revoked.RevocationTime
-		ret.RevocationReason = r.Revoked.Reason
-	}
-
-	ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
-	ret.ThisUpdate = r.ThisUpdate
-	ret.NextUpdate = r.NextUpdate
-
-	return ret, nil
-}
diff --git a/src/pkg/crypto/ocsp/ocsp_test.go b/src/pkg/crypto/ocsp/ocsp_test.go
deleted file mode 100644
index 7be3721..0000000
--- a/src/pkg/crypto/ocsp/ocsp_test.go
+++ /dev/null
@@ -1,97 +0,0 @@
-package ocsp
-
-import (
-	"bytes"
-	"encoding/hex"
-	"reflect"
-	"testing"
-	"time"
-)
-
-func TestOCSPDecode(t *testing.T) {
-	responseBytes, _ := hex.DecodeString(ocspResponseHex)
-	resp, err := ParseResponse(responseBytes)
-	if err != nil {
-		t.Error(err)
-	}
-
-	expected := Response{Status: 0, SerialNumber: []byte{0x1, 0xd0, 0xfa}, RevocationReason: 0, ThisUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 15, Minute: 1, Second: 5, ZoneOffset: 0, Zone: "UTC"}, NextUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 18, Minute: 35, Second: 17, ZoneOffset: 0, Zone: "UTC"}}
-
-	if !reflect.DeepEqual(resp.ThisUpdate, resp.ThisUpdate) {
-		t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate)
-	}
-
-	if !reflect.DeepEqual(resp.NextUpdate, resp.NextUpdate) {
-		t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate)
-	}
-
-	if resp.Status != expected.Status {
-		t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status)
-	}
-
-	if !bytes.Equal(resp.SerialNumber, expected.SerialNumber) {
-		t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber)
-	}
-
-	if resp.RevocationReason != expected.RevocationReason {
-		t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason)
-	}
-}
-
-// This OCSP response was taken from Thawte's public OCSP responder.
-// To recreate:
-//   $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443
-// Copy and paste the first certificate into /tmp/cert.crt and the second into
-// /tmp/intermediate.crt
-//   $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der
-// Then hex encode the result:
-//   $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")'
-
-const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" +
-	"c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" +
-	"6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" +
-	"5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" +
-	"2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" +
-	"b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" +
-	"30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" +
-	"000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" +
-	"fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" +
-	"467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" +
-	"4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" +
-	"672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" +
-	"d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" +
-	"17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" +
-	"e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" +
-	"06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" +
-	"040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" +
-	"69676974616c204365727469666963617465205369676e696e6731383036060355040313" +
-	"2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" +
-	"746520536572766572204341301e170d3037313032353030323330365a170d3132313032" +
-	"333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" +
-	"617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" +
-	"2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" +
-	"0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" +
-	"7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" +
-	"a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" +
-	"fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" +
-	"4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" +
-	"ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" +
-	"3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" +
-	"29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" +
-	"01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" +
-	"0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" +
-	"bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" +
-	"6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" +
-	"55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" +
-	"4469676974616c204365727469666963617465205369676e696e67312930270603550403" +
-	"13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" +
-	"0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" +
-	"6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" +
-	"6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" +
-	"8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" +
-	"2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" +
-	"1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" +
-	"c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" +
-	"f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" +
-	"a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" +
-	"6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42"
diff --git a/src/pkg/crypto/openpgp/Makefile b/src/pkg/crypto/openpgp/Makefile
deleted file mode 100644
index b46ac2b..0000000
--- a/src/pkg/crypto/openpgp/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/openpgp
-GOFILES=\
-	canonical_text.go\
-	keys.go\
-	read.go\
-	write.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/openpgp/armor/Makefile b/src/pkg/crypto/openpgp/armor/Makefile
deleted file mode 100644
index 138e314..0000000
--- a/src/pkg/crypto/openpgp/armor/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../../Make.inc
-
-TARG=crypto/openpgp/armor
-GOFILES=\
-	armor.go\
-	encode.go\
-
-include ../../../../Make.pkg
diff --git a/src/pkg/crypto/openpgp/armor/armor.go b/src/pkg/crypto/openpgp/armor/armor.go
deleted file mode 100644
index 9c4180d..0000000
--- a/src/pkg/crypto/openpgp/armor/armor.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2010 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 armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
-// very similar to PEM except that it has an additional CRC checksum.
-package armor
-
-import (
-	"bufio"
-	"bytes"
-	"crypto/openpgp/error"
-	"encoding/base64"
-	"io"
-	"os"
-)
-
-// A Block represents an OpenPGP armored structure.
-//
-// The encoded form is:
-//    -----BEGIN Type-----
-//    Headers
-//
-//    base64-encoded Bytes
-//    '=' base64 encoded checksum
-//    -----END Type-----
-// where Headers is a possibly empty sequence of Key: Value lines.
-//
-// Since the armored data can be very large, this package presents a streaming
-// interface.
-type Block struct {
-	Type    string            // The type, taken from the preamble (i.e. "PGP SIGNATURE").
-	Header  map[string]string // Optional headers.
-	Body    io.Reader         // A Reader from which the contents can be read
-	lReader lineReader
-	oReader openpgpReader
-}
-
-var ArmorCorrupt os.Error = error.StructuralError("armor invalid")
-
-const crc24Init = 0xb704ce
-const crc24Poly = 0x1864cfb
-const crc24Mask = 0xffffff
-
-// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
-func crc24(crc uint32, d []byte) uint32 {
-	for _, b := range d {
-		crc ^= uint32(b) << 16
-		for i := 0; i < 8; i++ {
-			crc <<= 1
-			if crc&0x1000000 != 0 {
-				crc ^= crc24Poly
-			}
-		}
-	}
-	return crc
-}
-
-var armorStart = []byte("-----BEGIN ")
-var armorEnd = []byte("-----END ")
-var armorEndOfLine = []byte("-----")
-
-// lineReader wraps a line based reader. It watches for the end of an armor
-// block and records the expected CRC value.
-type lineReader struct {
-	in  *bufio.Reader
-	buf []byte
-	eof bool
-	crc uint32
-}
-
-func (l *lineReader) Read(p []byte) (n int, err os.Error) {
-	if l.eof {
-		return 0, os.EOF
-	}
-
-	if len(l.buf) > 0 {
-		n = copy(p, l.buf)
-		l.buf = l.buf[n:]
-		return
-	}
-
-	line, isPrefix, err := l.in.ReadLine()
-	if err != nil {
-		return
-	}
-	if isPrefix {
-		return 0, ArmorCorrupt
-	}
-
-	if len(line) == 5 && line[0] == '=' {
-		// This is the checksum line
-		var expectedBytes [3]byte
-		var m int
-		m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
-		if m != 3 || err != nil {
-			return
-		}
-		l.crc = uint32(expectedBytes[0])<<16 |
-			uint32(expectedBytes[1])<<8 |
-			uint32(expectedBytes[2])
-
-		line, _, err = l.in.ReadLine()
-		if err != nil && err != os.EOF {
-			return
-		}
-		if !bytes.HasPrefix(line, armorEnd) {
-			return 0, ArmorCorrupt
-		}
-
-		l.eof = true
-		return 0, os.EOF
-	}
-
-	if len(line) > 64 {
-		return 0, ArmorCorrupt
-	}
-
-	n = copy(p, line)
-	bytesToSave := len(line) - n
-	if bytesToSave > 0 {
-		if cap(l.buf) < bytesToSave {
-			l.buf = make([]byte, 0, bytesToSave)
-		}
-		l.buf = l.buf[0:bytesToSave]
-		copy(l.buf, line[n:])
-	}
-
-	return
-}
-
-// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
-// a running CRC of the resulting data and checks the CRC against the value
-// found by the lineReader at EOF.
-type openpgpReader struct {
-	lReader    *lineReader
-	b64Reader  io.Reader
-	currentCRC uint32
-}
-
-func (r *openpgpReader) Read(p []byte) (n int, err os.Error) {
-	n, err = r.b64Reader.Read(p)
-	r.currentCRC = crc24(r.currentCRC, p[:n])
-
-	if err == os.EOF {
-		if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
-			return 0, ArmorCorrupt
-		}
-	}
-
-	return
-}
-
-// Decode reads a PGP armored block from the given Reader. It will ignore
-// leading garbage. If it doesn't find a block, it will return nil, os.EOF. The
-// given Reader is not usable after calling this function: an arbitrary amount
-// of data may have been read past the end of the block.
-func Decode(in io.Reader) (p *Block, err os.Error) {
-	r, _ := bufio.NewReaderSize(in, 100)
-	var line []byte
-	ignoreNext := false
-
-TryNextBlock:
-	p = nil
-
-	// Skip leading garbage
-	for {
-		ignoreThis := ignoreNext
-		line, ignoreNext, err = r.ReadLine()
-		if err != nil {
-			return
-		}
-		if ignoreNext || ignoreThis {
-			continue
-		}
-		line = bytes.TrimSpace(line)
-		if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
-			break
-		}
-	}
-
-	p = new(Block)
-	p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
-	p.Header = make(map[string]string)
-	nextIsContinuation := false
-	var lastKey string
-
-	// Read headers
-	for {
-		isContinuation := nextIsContinuation
-		line, nextIsContinuation, err = r.ReadLine()
-		if err != nil {
-			p = nil
-			return
-		}
-		if isContinuation {
-			p.Header[lastKey] += string(line)
-			continue
-		}
-		line = bytes.TrimSpace(line)
-		if len(line) == 0 {
-			break
-		}
-
-		i := bytes.Index(line, []byte(": "))
-		if i == -1 {
-			goto TryNextBlock
-		}
-		lastKey = string(line[:i])
-		p.Header[lastKey] = string(line[i+2:])
-	}
-
-	p.lReader.in = r
-	p.oReader.currentCRC = crc24Init
-	p.oReader.lReader = &p.lReader
-	p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
-	p.Body = &p.oReader
-
-	return
-}
diff --git a/src/pkg/crypto/openpgp/armor/armor_test.go b/src/pkg/crypto/openpgp/armor/armor_test.go
deleted file mode 100644
index 9334e94..0000000
--- a/src/pkg/crypto/openpgp/armor/armor_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2010 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 armor
-
-import (
-	"bytes"
-	"hash/adler32"
-	"io/ioutil"
-	"testing"
-)
-
-func TestDecodeEncode(t *testing.T) {
-	buf := bytes.NewBuffer([]byte(armorExample1))
-	result, err := Decode(buf)
-	if err != nil {
-		t.Error(err)
-	}
-	expectedType := "PGP SIGNATURE"
-	if result.Type != expectedType {
-		t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
-	}
-	if len(result.Header) != 1 {
-		t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
-	}
-	v, ok := result.Header["Version"]
-	if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
-		t.Errorf("result.Header: got:%#v", result.Header)
-	}
-
-	contents, err := ioutil.ReadAll(result.Body)
-	if err != nil {
-		t.Error(err)
-	}
-
-	if adler32.Checksum(contents) != 0x27b144be {
-		t.Errorf("contents: got: %x", contents)
-	}
-
-	buf = bytes.NewBuffer(nil)
-	w, err := Encode(buf, result.Type, result.Header)
-	if err != nil {
-		t.Error(err)
-	}
-	_, err = w.Write(contents)
-	if err != nil {
-		t.Error(err)
-	}
-	w.Close()
-
-	if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
-		t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
-	}
-}
-
-func TestLongHeader(t *testing.T) {
-	buf := bytes.NewBuffer([]byte(armorLongLine))
-	result, err := Decode(buf)
-	if err != nil {
-		t.Error(err)
-		return
-	}
-	value, ok := result.Header["Version"]
-	if !ok {
-		t.Errorf("missing Version header")
-	}
-	if value != longValueExpected {
-		t.Errorf("got: %s want: %s", value, longValueExpected)
-	}
-}
-
-const armorExample1 = `-----BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.10 (GNU/Linux)
-
-iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm
-4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt
-p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW
-TxRjs+fJCIFuo71xb1g=
-=/teI
------END PGP SIGNATURE-----`
-
-const armorLongLine = `-----BEGIN PGP SIGNATURE-----
-Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
-
-iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
-kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
-cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
-byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
-WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
-okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
-=wfQG
------END PGP SIGNATURE-----`
-
-const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
diff --git a/src/pkg/crypto/openpgp/armor/encode.go b/src/pkg/crypto/openpgp/armor/encode.go
deleted file mode 100644
index 99dee37..0000000
--- a/src/pkg/crypto/openpgp/armor/encode.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2010 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 armor
-
-import (
-	"encoding/base64"
-	"io"
-	"os"
-)
-
-var armorHeaderSep = []byte(": ")
-var blockEnd = []byte("\n=")
-var newline = []byte("\n")
-var armorEndOfLineOut = []byte("-----\n")
-
-// writeSlices writes its arguments to the given Writer.
-func writeSlices(out io.Writer, slices ...[]byte) (err os.Error) {
-	for _, s := range slices {
-		_, err = out.Write(s)
-		if err != nil {
-			return err
-		}
-	}
-	return
-}
-
-// lineBreaker breaks data across several lines, all of the same byte length
-// (except possibly the last). Lines are broken with a single '\n'.
-type lineBreaker struct {
-	lineLength  int
-	line        []byte
-	used        int
-	out         io.Writer
-	haveWritten bool
-}
-
-func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
-	return &lineBreaker{
-		lineLength: lineLength,
-		line:       make([]byte, lineLength),
-		used:       0,
-		out:        out,
-	}
-}
-
-func (l *lineBreaker) Write(b []byte) (n int, err os.Error) {
-	n = len(b)
-
-	if n == 0 {
-		return
-	}
-
-	if l.used == 0 && l.haveWritten {
-		_, err = l.out.Write([]byte{'\n'})
-		if err != nil {
-			return
-		}
-	}
-
-	if l.used+len(b) < l.lineLength {
-		l.used += copy(l.line[l.used:], b)
-		return
-	}
-
-	l.haveWritten = true
-	_, err = l.out.Write(l.line[0:l.used])
-	if err != nil {
-		return
-	}
-	excess := l.lineLength - l.used
-	l.used = 0
-
-	_, err = l.out.Write(b[0:excess])
-	if err != nil {
-		return
-	}
-
-	_, err = l.Write(b[excess:])
-	return
-}
-
-func (l *lineBreaker) Close() (err os.Error) {
-	if l.used > 0 {
-		_, err = l.out.Write(l.line[0:l.used])
-		if err != nil {
-			return
-		}
-	}
-
-	return
-}
-
-// encoding keeps track of a running CRC24 over the data which has been written
-// to it and outputs a OpenPGP checksum when closed, followed by an armor
-// trailer.
-//
-// It's built into a stack of io.Writers:
-//    encoding -> base64 encoder -> lineBreaker -> out
-type encoding struct {
-	out       io.Writer
-	breaker   *lineBreaker
-	b64       io.WriteCloser
-	crc       uint32
-	blockType []byte
-}
-
-func (e *encoding) Write(data []byte) (n int, err os.Error) {
-	e.crc = crc24(e.crc, data)
-	return e.b64.Write(data)
-}
-
-func (e *encoding) Close() (err os.Error) {
-	err = e.b64.Close()
-	if err != nil {
-		return
-	}
-	e.breaker.Close()
-
-	var checksumBytes [3]byte
-	checksumBytes[0] = byte(e.crc >> 16)
-	checksumBytes[1] = byte(e.crc >> 8)
-	checksumBytes[2] = byte(e.crc)
-
-	var b64ChecksumBytes [4]byte
-	base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
-
-	return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
-}
-
-// Encode returns a WriteCloser which will encode the data written to it in
-// OpenPGP armor.
-func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err os.Error) {
-	bType := []byte(blockType)
-	err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
-	if err != nil {
-		return
-	}
-
-	for k, v := range headers {
-		err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
-		if err != nil {
-			return
-		}
-	}
-
-	_, err = out.Write(newline)
-	if err != nil {
-		return
-	}
-
-	e := &encoding{
-		out:       out,
-		breaker:   newLineBreaker(out, 64),
-		crc:       crc24Init,
-		blockType: bType,
-	}
-	e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
-	return e, nil
-}
diff --git a/src/pkg/crypto/openpgp/canonical_text.go b/src/pkg/crypto/openpgp/canonical_text.go
deleted file mode 100644
index 293eff3..0000000
--- a/src/pkg/crypto/openpgp/canonical_text.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2011 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 openpgp
-
-import (
-	"hash"
-	"os"
-)
-
-// NewCanonicalTextHash reformats text written to it into the canonical
-// form and then applies the hash h.  See RFC 4880, section 5.2.1.
-func NewCanonicalTextHash(h hash.Hash) hash.Hash {
-	return &canonicalTextHash{h, 0}
-}
-
-type canonicalTextHash struct {
-	h hash.Hash
-	s int
-}
-
-var newline = []byte{'\r', '\n'}
-
-func (cth *canonicalTextHash) Write(buf []byte) (int, os.Error) {
-	start := 0
-
-	for i, c := range buf {
-		switch cth.s {
-		case 0:
-			if c == '\r' {
-				cth.s = 1
-			} else if c == '\n' {
-				cth.h.Write(buf[start:i])
-				cth.h.Write(newline)
-				start = i + 1
-			}
-		case 1:
-			cth.s = 0
-		}
-	}
-
-	cth.h.Write(buf[start:])
-	return len(buf), nil
-}
-
-func (cth *canonicalTextHash) Sum() []byte {
-	return cth.h.Sum()
-}
-
-func (cth *canonicalTextHash) Reset() {
-	cth.h.Reset()
-	cth.s = 0
-}
-
-func (cth *canonicalTextHash) Size() int {
-	return cth.h.Size()
-}
diff --git a/src/pkg/crypto/openpgp/canonical_text_test.go b/src/pkg/crypto/openpgp/canonical_text_test.go
deleted file mode 100644
index ccf2910..0000000
--- a/src/pkg/crypto/openpgp/canonical_text_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2011 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 openpgp
-
-import (
-	"bytes"
-	"os"
-	"testing"
-)
-
-type recordingHash struct {
-	buf *bytes.Buffer
-}
-
-func (r recordingHash) Write(b []byte) (n int, err os.Error) {
-	return r.buf.Write(b)
-}
-
-func (r recordingHash) Sum() []byte {
-	return r.buf.Bytes()
-}
-
-func (r recordingHash) Reset() {
-	panic("shouldn't be called")
-}
-
-func (r recordingHash) Size() int {
-	panic("shouldn't be called")
-}
-
-func testCanonicalText(t *testing.T, input, expected string) {
-	r := recordingHash{bytes.NewBuffer(nil)}
-	c := NewCanonicalTextHash(r)
-	c.Write([]byte(input))
-	result := c.Sum()
-	if expected != string(result) {
-		t.Errorf("input: %x got: %x want: %x", input, result, expected)
-	}
-}
-
-func TestCanonicalText(t *testing.T) {
-	testCanonicalText(t, "foo\n", "foo\r\n")
-	testCanonicalText(t, "foo", "foo")
-	testCanonicalText(t, "foo\r\n", "foo\r\n")
-	testCanonicalText(t, "foo\r\nbar", "foo\r\nbar")
-	testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n")
-}
diff --git a/src/pkg/crypto/openpgp/elgamal/Makefile b/src/pkg/crypto/openpgp/elgamal/Makefile
deleted file mode 100644
index f730255..0000000
--- a/src/pkg/crypto/openpgp/elgamal/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../../Make.inc
-
-TARG=crypto/openpgp/elgamal
-GOFILES=\
-	elgamal.go\
-
-include ../../../../Make.pkg
diff --git a/src/pkg/crypto/openpgp/elgamal/elgamal.go b/src/pkg/crypto/openpgp/elgamal/elgamal.go
deleted file mode 100644
index 99a6e3e..0000000
--- a/src/pkg/crypto/openpgp/elgamal/elgamal.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2011 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 elgamal implements ElGamal encryption, suitable for OpenPGP,
-// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
-// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
-// n. 4, 1985, pp. 469-472.
-//
-// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
-// unsuitable for other protocols. RSA should be used in preference in any
-// case.
-package elgamal
-
-import (
-	"big"
-	"crypto/rand"
-	"crypto/subtle"
-	"io"
-	"os"
-)
-
-// PublicKey represents an ElGamal public key.
-type PublicKey struct {
-	G, P, Y *big.Int
-}
-
-// PrivateKey represents an ElGamal private key.
-type PrivateKey struct {
-	PublicKey
-	X *big.Int
-}
-
-// Encrypt encrypts the given message to the given public key. The result is a
-// pair of integers. Errors can result from reading random, or because msg is
-// too large to be encrypted to the public key.
-func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err os.Error) {
-	pLen := (pub.P.BitLen() + 7) / 8
-	if len(msg) > pLen-11 {
-		err = os.NewError("elgamal: message too long")
-		return
-	}
-
-	// EM = 0x02 || PS || 0x00 || M
-	em := make([]byte, pLen-1)
-	em[0] = 2
-	ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
-	err = nonZeroRandomBytes(ps, random)
-	if err != nil {
-		return
-	}
-	em[len(em)-len(msg)-1] = 0
-	copy(mm, msg)
-
-	m := new(big.Int).SetBytes(em)
-
-	k, err := rand.Int(random, pub.P)
-	if err != nil {
-		return
-	}
-
-	c1 = new(big.Int).Exp(pub.G, k, pub.P)
-	s := new(big.Int).Exp(pub.Y, k, pub.P)
-	c2 = s.Mul(s, m)
-	c2.Mod(c2, pub.P)
-
-	return
-}
-
-// Decrypt takes two integers, resulting from an ElGamal encryption, and
-// returns the plaintext of the message. An error can result only if the
-// ciphertext is invalid. Users should keep in mind that this is a padding
-// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
-// be used to break the cryptosystem.  See ``Chosen Ciphertext Attacks
-// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
-// Bleichenbacher, Advances in Cryptology (Crypto '98),
-func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err os.Error) {
-	s := new(big.Int).Exp(c1, priv.X, priv.P)
-	s.ModInverse(s, priv.P)
-	s.Mul(s, c2)
-	s.Mod(s, priv.P)
-	em := s.Bytes()
-
-	firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
-
-	// The remainder of the plaintext must be a string of non-zero random
-	// octets, followed by a 0, followed by the message.
-	//   lookingForIndex: 1 iff we are still looking for the zero.
-	//   index: the offset of the first zero byte.
-	var lookingForIndex, index int
-	lookingForIndex = 1
-
-	for i := 1; i < len(em); i++ {
-		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
-		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
-		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
-	}
-
-	if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
-		return nil, os.NewError("elgamal: decryption error")
-	}
-	return em[index+1:], nil
-}
-
-// nonZeroRandomBytes fills the given slice with non-zero random octets.
-func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
-	_, err = io.ReadFull(rand, s)
-	if err != nil {
-		return
-	}
-
-	for i := 0; i < len(s); i++ {
-		for s[i] == 0 {
-			_, err = io.ReadFull(rand, s[i:i+1])
-			if err != nil {
-				return
-			}
-		}
-	}
-
-	return
-}
diff --git a/src/pkg/crypto/openpgp/elgamal/elgamal_test.go b/src/pkg/crypto/openpgp/elgamal/elgamal_test.go
deleted file mode 100644
index 101121a..0000000
--- a/src/pkg/crypto/openpgp/elgamal/elgamal_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2011 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 elgamal
-
-import (
-	"big"
-	"bytes"
-	"crypto/rand"
-	"testing"
-)
-
-// This is the 1024-bit MODP group from RFC 5114, section 2.1:
-const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371"
-
-const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5"
-
-func fromHex(hex string) *big.Int {
-	n, ok := new(big.Int).SetString(hex, 16)
-	if !ok {
-		panic("failed to parse hex number")
-	}
-	return n
-}
-
-func TestEncryptDecrypt(t *testing.T) {
-	priv := &PrivateKey{
-		PublicKey: PublicKey{
-			G: fromHex(generatorHex),
-			P: fromHex(primeHex),
-		},
-		X: fromHex("42"),
-	}
-	priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P)
-
-	message := []byte("hello world")
-	c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message)
-	if err != nil {
-		t.Errorf("error encrypting: %s", err)
-	}
-	message2, err := Decrypt(priv, c1, c2)
-	if err != nil {
-		t.Errorf("error decrypting: %s", err)
-	}
-	if !bytes.Equal(message2, message) {
-		t.Errorf("decryption failed, got: %x, want: %x", message2, message)
-	}
-}
diff --git a/src/pkg/crypto/openpgp/error/Makefile b/src/pkg/crypto/openpgp/error/Makefile
deleted file mode 100644
index 8c370a0..0000000
--- a/src/pkg/crypto/openpgp/error/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../../Make.inc
-
-TARG=crypto/openpgp/error
-GOFILES=\
-	error.go\
-
-include ../../../../Make.pkg
diff --git a/src/pkg/crypto/openpgp/error/error.go b/src/pkg/crypto/openpgp/error/error.go
deleted file mode 100644
index 3759ce1..0000000
--- a/src/pkg/crypto/openpgp/error/error.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2010 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 error contains common error types for the OpenPGP packages.
-package error
-
-import (
-	"strconv"
-)
-
-// A StructuralError is returned when OpenPGP data is found to be syntactically
-// invalid.
-type StructuralError string
-
-func (s StructuralError) String() string {
-	return "OpenPGP data invalid: " + string(s)
-}
-
-// UnsupportedError indicates that, although the OpenPGP data is valid, it
-// makes use of currently unimplemented features.
-type UnsupportedError string
-
-func (s UnsupportedError) String() string {
-	return "OpenPGP feature unsupported: " + string(s)
-}
-
-// InvalidArgumentError indicates that the caller is in error and passed an
-// incorrect value.
-type InvalidArgumentError string
-
-func (i InvalidArgumentError) String() string {
-	return "OpenPGP argument invalid: " + string(i)
-}
-
-// SignatureError indicates that a syntactically valid signature failed to
-// validate.
-type SignatureError string
-
-func (b SignatureError) String() string {
-	return "OpenPGP signature invalid: " + string(b)
-}
-
-type keyIncorrect int
-
-func (ki keyIncorrect) String() string {
-	return "the given key was incorrect"
-}
-
-var KeyIncorrectError = keyIncorrect(0)
-
-type unknownIssuer int
-
-func (unknownIssuer) String() string {
-	return "signature make by unknown entity"
-}
-
-var UnknownIssuerError = unknownIssuer(0)
-
-type UnknownPacketTypeError uint8
-
-func (upte UnknownPacketTypeError) String() string {
-	return "unknown OpenPGP packet type: " + strconv.Itoa(int(upte))
-}
diff --git a/src/pkg/crypto/openpgp/keys.go b/src/pkg/crypto/openpgp/keys.go
deleted file mode 100644
index c70fb79..0000000
--- a/src/pkg/crypto/openpgp/keys.go
+++ /dev/null
@@ -1,545 +0,0 @@
-// Copyright 2011 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 openpgp
-
-import (
-	"crypto"
-	"crypto/openpgp/armor"
-	"crypto/openpgp/error"
-	"crypto/openpgp/packet"
-	"crypto/rsa"
-	"io"
-	"os"
-	"time"
-)
-
-// PublicKeyType is the armor type for a PGP public key.
-var PublicKeyType = "PGP PUBLIC KEY BLOCK"
-// PrivateKeyType is the armor type for a PGP private key.
-var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
-
-// An Entity represents the components of an OpenPGP key: a primary public key
-// (which must be a signing key), one or more identities claimed by that key,
-// and zero or more subkeys, which may be encryption keys.
-type Entity struct {
-	PrimaryKey *packet.PublicKey
-	PrivateKey *packet.PrivateKey
-	Identities map[string]*Identity // indexed by Identity.Name
-	Subkeys    []Subkey
-}
-
-// An Identity represents an identity claimed by an Entity and zero or more
-// assertions by other entities about that claim.
-type Identity struct {
-	Name          string // by convention, has the form "Full Name (comment) <email at example.com>"
-	UserId        *packet.UserId
-	SelfSignature *packet.Signature
-	Signatures    []*packet.Signature
-}
-
-// A Subkey is an additional public key in an Entity. Subkeys can be used for
-// encryption.
-type Subkey struct {
-	PublicKey  *packet.PublicKey
-	PrivateKey *packet.PrivateKey
-	Sig        *packet.Signature
-}
-
-// A Key identifies a specific public key in an Entity. This is either the
-// Entity's primary key or a subkey.
-type Key struct {
-	Entity        *Entity
-	PublicKey     *packet.PublicKey
-	PrivateKey    *packet.PrivateKey
-	SelfSignature *packet.Signature
-}
-
-// A KeyRing provides access to public and private keys.
-type KeyRing interface {
-	// KeysById returns the set of keys that have the given key id.
-	KeysById(id uint64) []Key
-	// DecryptionKeys returns all private keys that are valid for
-	// decryption.
-	DecryptionKeys() []Key
-}
-
-// primaryIdentity returns the Identity marked as primary or the first identity
-// if none are so marked.
-func (e *Entity) primaryIdentity() *Identity {
-	var firstIdentity *Identity
-	for _, ident := range e.Identities {
-		if firstIdentity == nil {
-			firstIdentity = ident
-		}
-		if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
-			return ident
-		}
-	}
-	return firstIdentity
-}
-
-// encryptionKey returns the best candidate Key for encrypting a message to the
-// given Entity.
-func (e *Entity) encryptionKey() Key {
-	candidateSubkey := -1
-
-	for i, subkey := range e.Subkeys {
-		if subkey.Sig.FlagsValid && subkey.Sig.FlagEncryptCommunications && subkey.PublicKey.PubKeyAlgo.CanEncrypt() {
-			candidateSubkey = i
-			break
-		}
-	}
-
-	i := e.primaryIdentity()
-
-	if e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
-		// If we don't have any candidate subkeys for encryption and
-		// the primary key doesn't have any usage metadata then we
-		// assume that the primary key is ok. Or, if the primary key is
-		// marked as ok to encrypt to, then we can obviously use it.
-		if candidateSubkey == -1 && !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && i.SelfSignature.FlagsValid {
-			return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}
-		}
-	}
-
-	if candidateSubkey != -1 {
-		subkey := e.Subkeys[candidateSubkey]
-		return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}
-	}
-
-	// This Entity appears to be signing only.
-	return Key{}
-}
-
-// signingKey return the best candidate Key for signing a message with this
-// Entity.
-func (e *Entity) signingKey() Key {
-	candidateSubkey := -1
-
-	for i, subkey := range e.Subkeys {
-		if subkey.Sig.FlagsValid && subkey.Sig.FlagSign && subkey.PublicKey.PubKeyAlgo.CanSign() {
-			candidateSubkey = i
-			break
-		}
-	}
-
-	i := e.primaryIdentity()
-
-	// If we have no candidate subkey then we assume that it's ok to sign
-	// with the primary key.
-	if candidateSubkey == -1 || i.SelfSignature.FlagsValid && i.SelfSignature.FlagSign {
-		return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}
-	}
-
-	subkey := e.Subkeys[candidateSubkey]
-	return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}
-}
-
-// An EntityList contains one or more Entities.
-type EntityList []*Entity
-
-// KeysById returns the set of keys that have the given key id.
-func (el EntityList) KeysById(id uint64) (keys []Key) {
-	for _, e := range el {
-		if e.PrimaryKey.KeyId == id {
-			var selfSig *packet.Signature
-			for _, ident := range e.Identities {
-				if selfSig == nil {
-					selfSig = ident.SelfSignature
-				} else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
-					selfSig = ident.SelfSignature
-					break
-				}
-			}
-			keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
-		}
-
-		for _, subKey := range e.Subkeys {
-			if subKey.PublicKey.KeyId == id {
-				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
-			}
-		}
-	}
-	return
-}
-
-// DecryptionKeys returns all private keys that are valid for decryption.
-func (el EntityList) DecryptionKeys() (keys []Key) {
-	for _, e := range el {
-		for _, subKey := range e.Subkeys {
-			if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
-				keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
-			}
-		}
-	}
-	return
-}
-
-// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
-func ReadArmoredKeyRing(r io.Reader) (EntityList, os.Error) {
-	block, err := armor.Decode(r)
-	if err == os.EOF {
-		return nil, error.InvalidArgumentError("no armored data found")
-	}
-	if err != nil {
-		return nil, err
-	}
-	if block.Type != PublicKeyType && block.Type != PrivateKeyType {
-		return nil, error.InvalidArgumentError("expected public or private key block, got: " + block.Type)
-	}
-
-	return ReadKeyRing(block.Body)
-}
-
-// ReadKeyRing reads one or more public/private keys. Unsupported keys are
-// ignored as long as at least a single valid key is found.
-func ReadKeyRing(r io.Reader) (el EntityList, err os.Error) {
-	packets := packet.NewReader(r)
-	var lastUnsupportedError os.Error
-
-	for {
-		var e *Entity
-		e, err = readEntity(packets)
-		if err != nil {
-			if _, ok := err.(error.UnsupportedError); ok {
-				lastUnsupportedError = err
-				err = readToNextPublicKey(packets)
-			}
-			if err == os.EOF {
-				err = nil
-				break
-			}
-			if err != nil {
-				el = nil
-				break
-			}
-		} else {
-			el = append(el, e)
-		}
-	}
-
-	if len(el) == 0 && err == nil {
-		err = lastUnsupportedError
-	}
-	return
-}
-
-// readToNextPublicKey reads packets until the start of the entity and leaves
-// the first packet of the new entity in the Reader.
-func readToNextPublicKey(packets *packet.Reader) (err os.Error) {
-	var p packet.Packet
-	for {
-		p, err = packets.Next()
-		if err == os.EOF {
-			return
-		} else if err != nil {
-			if _, ok := err.(error.UnsupportedError); ok {
-				err = nil
-				continue
-			}
-			return
-		}
-
-		if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
-			packets.Unread(p)
-			return
-		}
-	}
-
-	panic("unreachable")
-}
-
-// readEntity reads an entity (public key, identities, subkeys etc) from the
-// given Reader.
-func readEntity(packets *packet.Reader) (*Entity, os.Error) {
-	e := new(Entity)
-	e.Identities = make(map[string]*Identity)
-
-	p, err := packets.Next()
-	if err != nil {
-		return nil, err
-	}
-
-	var ok bool
-	if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
-		if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
-			packets.Unread(p)
-			return nil, error.StructuralError("first packet was not a public/private key")
-		} else {
-			e.PrimaryKey = &e.PrivateKey.PublicKey
-		}
-	}
-
-	if !e.PrimaryKey.PubKeyAlgo.CanSign() {
-		return nil, error.StructuralError("primary key cannot be used for signatures")
-	}
-
-	var current *Identity
-EachPacket:
-	for {
-		p, err := packets.Next()
-		if err == os.EOF {
-			break
-		} else if err != nil {
-			return nil, err
-		}
-
-		switch pkt := p.(type) {
-		case *packet.UserId:
-			current = new(Identity)
-			current.Name = pkt.Id
-			current.UserId = pkt
-			e.Identities[pkt.Id] = current
-
-			for {
-				p, err = packets.Next()
-				if err == os.EOF {
-					return nil, io.ErrUnexpectedEOF
-				} else if err != nil {
-					return nil, err
-				}
-
-				sig, ok := p.(*packet.Signature)
-				if !ok {
-					return nil, error.StructuralError("user ID packet not followed by self-signature")
-				}
-
-				if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
-					if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil {
-						return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
-					}
-					current.SelfSignature = sig
-					break
-				}
-				current.Signatures = append(current.Signatures, sig)
-			}
-		case *packet.Signature:
-			if current == nil {
-				return nil, error.StructuralError("signature packet found before user id packet")
-			}
-			current.Signatures = append(current.Signatures, pkt)
-		case *packet.PrivateKey:
-			if pkt.IsSubkey == false {
-				packets.Unread(p)
-				break EachPacket
-			}
-			err = addSubkey(e, packets, &pkt.PublicKey, pkt)
-			if err != nil {
-				return nil, err
-			}
-		case *packet.PublicKey:
-			if pkt.IsSubkey == false {
-				packets.Unread(p)
-				break EachPacket
-			}
-			err = addSubkey(e, packets, pkt, nil)
-			if err != nil {
-				return nil, err
-			}
-		default:
-			// we ignore unknown packets
-		}
-	}
-
-	if len(e.Identities) == 0 {
-		return nil, error.StructuralError("entity without any identities")
-	}
-
-	return e, nil
-}
-
-func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) os.Error {
-	var subKey Subkey
-	subKey.PublicKey = pub
-	subKey.PrivateKey = priv
-	p, err := packets.Next()
-	if err == os.EOF {
-		return io.ErrUnexpectedEOF
-	}
-	if err != nil {
-		return error.StructuralError("subkey signature invalid: " + err.String())
-	}
-	var ok bool
-	subKey.Sig, ok = p.(*packet.Signature)
-	if !ok {
-		return error.StructuralError("subkey packet not followed by signature")
-	}
-	if subKey.Sig.SigType != packet.SigTypeSubkeyBinding {
-		return error.StructuralError("subkey signature with wrong type")
-	}
-	err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
-	if err != nil {
-		return error.StructuralError("subkey signature invalid: " + err.String())
-	}
-	e.Subkeys = append(e.Subkeys, subKey)
-	return nil
-}
-
-const defaultRSAKeyBits = 2048
-
-// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
-// single identity composed of the given full name, comment and email, any of
-// which may be empty but must not contain any of "()<>\x00".
-func NewEntity(rand io.Reader, currentTimeSecs int64, name, comment, email string) (*Entity, os.Error) {
-	uid := packet.NewUserId(name, comment, email)
-	if uid == nil {
-		return nil, error.InvalidArgumentError("user id field contained invalid characters")
-	}
-	signingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
-	if err != nil {
-		return nil, err
-	}
-	encryptingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
-	if err != nil {
-		return nil, err
-	}
-
-	t := uint32(currentTimeSecs)
-
-	e := &Entity{
-		PrimaryKey: packet.NewRSAPublicKey(t, &signingPriv.PublicKey, false /* not a subkey */ ),
-		PrivateKey: packet.NewRSAPrivateKey(t, signingPriv, false /* not a subkey */ ),
-		Identities: make(map[string]*Identity),
-	}
-	isPrimaryId := true
-	e.Identities[uid.Id] = &Identity{
-		Name:   uid.Name,
-		UserId: uid,
-		SelfSignature: &packet.Signature{
-			CreationTime: t,
-			SigType:      packet.SigTypePositiveCert,
-			PubKeyAlgo:   packet.PubKeyAlgoRSA,
-			Hash:         crypto.SHA256,
-			IsPrimaryId:  &isPrimaryId,
-			FlagsValid:   true,
-			FlagSign:     true,
-			FlagCertify:  true,
-			IssuerKeyId:  &e.PrimaryKey.KeyId,
-		},
-	}
-
-	e.Subkeys = make([]Subkey, 1)
-	e.Subkeys[0] = Subkey{
-		PublicKey:  packet.NewRSAPublicKey(t, &encryptingPriv.PublicKey, true /* is a subkey */ ),
-		PrivateKey: packet.NewRSAPrivateKey(t, encryptingPriv, true /* is a subkey */ ),
-		Sig: &packet.Signature{
-			CreationTime:              t,
-			SigType:                   packet.SigTypeSubkeyBinding,
-			PubKeyAlgo:                packet.PubKeyAlgoRSA,
-			Hash:                      crypto.SHA256,
-			FlagsValid:                true,
-			FlagEncryptStorage:        true,
-			FlagEncryptCommunications: true,
-			IssuerKeyId:               &e.PrimaryKey.KeyId,
-		},
-	}
-
-	return e, nil
-}
-
-// SerializePrivate serializes an Entity, including private key material, to
-// the given Writer. For now, it must only be used on an Entity returned from
-// NewEntity.
-func (e *Entity) SerializePrivate(w io.Writer) (err os.Error) {
-	err = e.PrivateKey.Serialize(w)
-	if err != nil {
-		return
-	}
-	for _, ident := range e.Identities {
-		err = ident.UserId.Serialize(w)
-		if err != nil {
-			return
-		}
-		err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey)
-		if err != nil {
-			return
-		}
-		err = ident.SelfSignature.Serialize(w)
-		if err != nil {
-			return
-		}
-	}
-	for _, subkey := range e.Subkeys {
-		err = subkey.PrivateKey.Serialize(w)
-		if err != nil {
-			return
-		}
-		err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey)
-		if err != nil {
-			return
-		}
-		err = subkey.Sig.Serialize(w)
-		if err != nil {
-			return
-		}
-	}
-	return nil
-}
-
-// Serialize writes the public part of the given Entity to w. (No private
-// key material will be output).
-func (e *Entity) Serialize(w io.Writer) os.Error {
-	err := e.PrimaryKey.Serialize(w)
-	if err != nil {
-		return err
-	}
-	for _, ident := range e.Identities {
-		err = ident.UserId.Serialize(w)
-		if err != nil {
-			return err
-		}
-		err = ident.SelfSignature.Serialize(w)
-		if err != nil {
-			return err
-		}
-		for _, sig := range ident.Signatures {
-			err = sig.Serialize(w)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	for _, subkey := range e.Subkeys {
-		err = subkey.PublicKey.Serialize(w)
-		if err != nil {
-			return err
-		}
-		err = subkey.Sig.Serialize(w)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// SignIdentity adds a signature to e, from signer, attesting that identity is
-// associated with e. The provided identity must already be an element of
-// e.Identities and the private key of signer must have been decrypted if
-// necessary.
-func (e *Entity) SignIdentity(identity string, signer *Entity) os.Error {
-	if signer.PrivateKey == nil {
-		return error.InvalidArgumentError("signing Entity must have a private key")
-	}
-	if signer.PrivateKey.Encrypted {
-		return error.InvalidArgumentError("signing Entity's private key must be decrypted")
-	}
-	ident, ok := e.Identities[identity]
-	if !ok {
-		return error.InvalidArgumentError("given identity string not found in Entity")
-	}
-
-	sig := &packet.Signature{
-		SigType:      packet.SigTypeGenericCert,
-		PubKeyAlgo:   signer.PrivateKey.PubKeyAlgo,
-		Hash:         crypto.SHA256,
-		CreationTime: uint32(time.Seconds()),
-		IssuerKeyId:  &signer.PrivateKey.KeyId,
-	}
-	if err := sig.SignKey(e.PrimaryKey, signer.PrivateKey); err != nil {
-		return err
-	}
-	ident.Signatures = append(ident.Signatures, sig)
-	return nil
-}
diff --git a/src/pkg/crypto/openpgp/packet/Makefile b/src/pkg/crypto/openpgp/packet/Makefile
deleted file mode 100644
index 0f0d94e..0000000
--- a/src/pkg/crypto/openpgp/packet/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../../Make.inc
-
-TARG=crypto/openpgp/packet
-GOFILES=\
-	compressed.go\
-	encrypted_key.go\
-	literal.go\
-	one_pass_signature.go\
-	packet.go\
-	private_key.go\
-	public_key.go\
-	reader.go\
-	signature.go\
-	symmetrically_encrypted.go\
-	symmetric_key_encrypted.go\
-	userid.go\
-
-include ../../../../Make.pkg
diff --git a/src/pkg/crypto/openpgp/packet/compressed.go b/src/pkg/crypto/openpgp/packet/compressed.go
deleted file mode 100644
index 1c15c24..0000000
--- a/src/pkg/crypto/openpgp/packet/compressed.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"compress/flate"
-	"compress/zlib"
-	"crypto/openpgp/error"
-	"io"
-	"os"
-	"strconv"
-)
-
-// Compressed represents a compressed OpenPGP packet. The decompressed contents
-// will contain more OpenPGP packets. See RFC 4880, section 5.6.
-type Compressed struct {
-	Body io.Reader
-}
-
-func (c *Compressed) parse(r io.Reader) os.Error {
-	var buf [1]byte
-	_, err := readFull(r, buf[:])
-	if err != nil {
-		return err
-	}
-
-	switch buf[0] {
-	case 1:
-		c.Body = flate.NewReader(r)
-	case 2:
-		c.Body, err = zlib.NewReader(r)
-	default:
-		err = error.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
-	}
-
-	return err
-}
diff --git a/src/pkg/crypto/openpgp/packet/compressed_test.go b/src/pkg/crypto/openpgp/packet/compressed_test.go
deleted file mode 100644
index 24fe501..0000000
--- a/src/pkg/crypto/openpgp/packet/compressed_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"bytes"
-	"encoding/hex"
-	"os"
-	"io/ioutil"
-	"testing"
-)
-
-func TestCompressed(t *testing.T) {
-	packet, err := Read(readerFromHex(compressedHex))
-	if err != nil {
-		t.Errorf("failed to read Compressed: %s", err)
-		return
-	}
-
-	c, ok := packet.(*Compressed)
-	if !ok {
-		t.Error("didn't find Compressed packet")
-		return
-	}
-
-	contents, err := ioutil.ReadAll(c.Body)
-	if err != nil && err != os.EOF {
-		t.Error(err)
-		return
-	}
-
-	expected, _ := hex.DecodeString(compressedExpectedHex)
-	if !bytes.Equal(expected, contents) {
-		t.Errorf("got:%x want:%x", contents, expected)
-	}
-}
-
-const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700"
-const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a"
diff --git a/src/pkg/crypto/openpgp/packet/encrypted_key.go b/src/pkg/crypto/openpgp/packet/encrypted_key.go
deleted file mode 100644
index b4730cb..0000000
--- a/src/pkg/crypto/openpgp/packet/encrypted_key.go
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"big"
-	"crypto/openpgp/elgamal"
-	"crypto/openpgp/error"
-	"crypto/rand"
-	"crypto/rsa"
-	"encoding/binary"
-	"io"
-	"os"
-	"strconv"
-)
-
-const encryptedKeyVersion = 3
-
-// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
-// section 5.1.
-type EncryptedKey struct {
-	KeyId      uint64
-	Algo       PublicKeyAlgorithm
-	CipherFunc CipherFunction // only valid after a successful Decrypt
-	Key        []byte         // only valid after a successful Decrypt
-
-	encryptedMPI1, encryptedMPI2 []byte
-}
-
-func (e *EncryptedKey) parse(r io.Reader) (err os.Error) {
-	var buf [10]byte
-	_, err = readFull(r, buf[:])
-	if err != nil {
-		return
-	}
-	if buf[0] != encryptedKeyVersion {
-		return error.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
-	}
-	e.KeyId = binary.BigEndian.Uint64(buf[1:9])
-	e.Algo = PublicKeyAlgorithm(buf[9])
-	switch e.Algo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
-		e.encryptedMPI1, _, err = readMPI(r)
-	case PubKeyAlgoElGamal:
-		e.encryptedMPI1, _, err = readMPI(r)
-		if err != nil {
-			return
-		}
-		e.encryptedMPI2, _, err = readMPI(r)
-	}
-	_, err = consumeAll(r)
-	return
-}
-
-func checksumKeyMaterial(key []byte) uint16 {
-	var checksum uint16
-	for _, v := range key {
-		checksum += uint16(v)
-	}
-	return checksum
-}
-
-// Decrypt decrypts an encrypted session key with the given private key. The
-// private key must have been decrypted first.
-func (e *EncryptedKey) Decrypt(priv *PrivateKey) os.Error {
-	var err os.Error
-	var b []byte
-
-	// TODO(agl): use session key decryption routines here to avoid
-	// padding oracle attacks.
-	switch priv.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
-		b, err = rsa.DecryptPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1)
-	case PubKeyAlgoElGamal:
-		c1 := new(big.Int).SetBytes(e.encryptedMPI1)
-		c2 := new(big.Int).SetBytes(e.encryptedMPI2)
-		b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
-	default:
-		err = error.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
-	}
-
-	if err != nil {
-		return err
-	}
-
-	e.CipherFunc = CipherFunction(b[0])
-	e.Key = b[1 : len(b)-2]
-	expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
-	checksum := checksumKeyMaterial(e.Key)
-	if checksum != expectedChecksum {
-		return error.StructuralError("EncryptedKey checksum incorrect")
-	}
-
-	return nil
-}
-
-// SerializeEncryptedKey serializes an encrypted key packet to w that contains
-// key, encrypted to pub.
-func SerializeEncryptedKey(w io.Writer, rand io.Reader, pub *PublicKey, cipherFunc CipherFunction, key []byte) os.Error {
-	var buf [10]byte
-	buf[0] = encryptedKeyVersion
-	binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
-	buf[9] = byte(pub.PubKeyAlgo)
-
-	keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */ )
-	keyBlock[0] = byte(cipherFunc)
-	copy(keyBlock[1:], key)
-	checksum := checksumKeyMaterial(key)
-	keyBlock[1+len(key)] = byte(checksum >> 8)
-	keyBlock[1+len(key)+1] = byte(checksum)
-
-	switch pub.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
-		return serializeEncryptedKeyRSA(w, rand, buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
-	case PubKeyAlgoElGamal:
-		return serializeEncryptedKeyElGamal(w, rand, buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
-	case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
-		return error.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
-	}
-
-	return error.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
-}
-
-func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) os.Error {
-	cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
-	if err != nil {
-		return error.InvalidArgumentError("RSA encryption failed: " + err.String())
-	}
-
-	packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
-
-	err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
-	if err != nil {
-		return err
-	}
-	_, err = w.Write(header[:])
-	if err != nil {
-		return err
-	}
-	return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
-}
-
-func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) os.Error {
-	c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
-	if err != nil {
-		return error.InvalidArgumentError("ElGamal encryption failed: " + err.String())
-	}
-
-	packetLen := 10 /* header length */
-	packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
-	packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
-
-	err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
-	if err != nil {
-		return err
-	}
-	_, err = w.Write(header[:])
-	if err != nil {
-		return err
-	}
-	err = writeBig(w, c1)
-	if err != nil {
-		return err
-	}
-	return writeBig(w, c2)
-}
diff --git a/src/pkg/crypto/openpgp/packet/encrypted_key_test.go b/src/pkg/crypto/openpgp/packet/encrypted_key_test.go
deleted file mode 100644
index b402245..0000000
--- a/src/pkg/crypto/openpgp/packet/encrypted_key_test.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"big"
-	"bytes"
-	"crypto/rand"
-	"crypto/rsa"
-	"fmt"
-	"testing"
-)
-
-func bigFromBase10(s string) *big.Int {
-	b, ok := new(big.Int).SetString(s, 10)
-	if !ok {
-		panic("bigFromBase10 failed")
-	}
-	return b
-}
-
-var encryptedKeyPub = rsa.PublicKey{
-	E: 65537,
-	N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"),
-}
-
-var encryptedKeyRSAPriv = &rsa.PrivateKey{
-	PublicKey: encryptedKeyPub,
-	D:         bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"),
-}
-
-var encryptedKeyPriv = &PrivateKey{
-	PublicKey: PublicKey{
-		PubKeyAlgo: PubKeyAlgoRSA,
-	},
-	PrivateKey: encryptedKeyRSAPriv,
-}
-
-func TestDecryptingEncryptedKey(t *testing.T) {
-	const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
-	const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b"
-
-	p, err := Read(readerFromHex(encryptedKeyHex))
-	if err != nil {
-		t.Errorf("error from Read: %s", err)
-		return
-	}
-	ek, ok := p.(*EncryptedKey)
-	if !ok {
-		t.Errorf("didn't parse an EncryptedKey, got %#v", p)
-		return
-	}
-
-	if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA {
-		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
-		return
-	}
-
-	err = ek.Decrypt(encryptedKeyPriv)
-	if err != nil {
-		t.Errorf("error from Decrypt: %s", err)
-		return
-	}
-
-	if ek.CipherFunc != CipherAES256 {
-		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
-		return
-	}
-
-	keyHex := fmt.Sprintf("%x", ek.Key)
-	if keyHex != expectedKeyHex {
-		t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
-	}
-}
-
-func TestEncryptingEncryptedKey(t *testing.T) {
-	key := []byte{1, 2, 3, 4}
-	const expectedKeyHex = "01020304"
-	const keyId = 42
-
-	pub := &PublicKey{
-		PublicKey:  &encryptedKeyPub,
-		KeyId:      keyId,
-		PubKeyAlgo: PubKeyAlgoRSAEncryptOnly,
-	}
-
-	buf := new(bytes.Buffer)
-	err := SerializeEncryptedKey(buf, rand.Reader, pub, CipherAES128, key)
-	if err != nil {
-		t.Errorf("error writing encrypted key packet: %s", err)
-	}
-
-	p, err := Read(buf)
-	if err != nil {
-		t.Errorf("error from Read: %s", err)
-		return
-	}
-	ek, ok := p.(*EncryptedKey)
-	if !ok {
-		t.Errorf("didn't parse an EncryptedKey, got %#v", p)
-		return
-	}
-
-	if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly {
-		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
-		return
-	}
-
-	err = ek.Decrypt(encryptedKeyPriv)
-	if err != nil {
-		t.Errorf("error from Decrypt: %s", err)
-		return
-	}
-
-	if ek.CipherFunc != CipherAES128 {
-		t.Errorf("unexpected EncryptedKey contents: %#v", ek)
-		return
-	}
-
-	keyHex := fmt.Sprintf("%x", ek.Key)
-	if keyHex != expectedKeyHex {
-		t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
-	}
-}
diff --git a/src/pkg/crypto/openpgp/packet/literal.go b/src/pkg/crypto/openpgp/packet/literal.go
deleted file mode 100644
index 9411572..0000000
--- a/src/pkg/crypto/openpgp/packet/literal.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"encoding/binary"
-	"io"
-	"os"
-)
-
-// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
-type LiteralData struct {
-	IsBinary bool
-	FileName string
-	Time     uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
-	Body     io.Reader
-}
-
-// ForEyesOnly returns whether the contents of the LiteralData have been marked
-// as especially sensitive.
-func (l *LiteralData) ForEyesOnly() bool {
-	return l.FileName == "_CONSOLE"
-}
-
-func (l *LiteralData) parse(r io.Reader) (err os.Error) {
-	var buf [256]byte
-
-	_, err = readFull(r, buf[:2])
-	if err != nil {
-		return
-	}
-
-	l.IsBinary = buf[0] == 'b'
-	fileNameLen := int(buf[1])
-
-	_, err = readFull(r, buf[:fileNameLen])
-	if err != nil {
-		return
-	}
-
-	l.FileName = string(buf[:fileNameLen])
-
-	_, err = readFull(r, buf[:4])
-	if err != nil {
-		return
-	}
-
-	l.Time = binary.BigEndian.Uint32(buf[:4])
-	l.Body = r
-	return
-}
-
-// SerializeLiteral serializes a literal data packet to w and returns a
-// WriteCloser to which the data itself can be written and which MUST be closed
-// on completion. The fileName is truncated to 255 bytes.
-func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err os.Error) {
-	var buf [4]byte
-	buf[0] = 't'
-	if isBinary {
-		buf[0] = 'b'
-	}
-	if len(fileName) > 255 {
-		fileName = fileName[:255]
-	}
-	buf[1] = byte(len(fileName))
-
-	inner, err := serializeStreamHeader(w, packetTypeLiteralData)
-	if err != nil {
-		return
-	}
-
-	_, err = inner.Write(buf[:2])
-	if err != nil {
-		return
-	}
-	_, err = inner.Write([]byte(fileName))
-	if err != nil {
-		return
-	}
-	binary.BigEndian.PutUint32(buf[:], time)
-	_, err = inner.Write(buf[:])
-	if err != nil {
-		return
-	}
-
-	plaintext = inner
-	return
-}
diff --git a/src/pkg/crypto/openpgp/packet/one_pass_signature.go b/src/pkg/crypto/openpgp/packet/one_pass_signature.go
deleted file mode 100644
index ca826e4..0000000
--- a/src/pkg/crypto/openpgp/packet/one_pass_signature.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"crypto"
-	"crypto/openpgp/error"
-	"crypto/openpgp/s2k"
-	"encoding/binary"
-	"io"
-	"os"
-	"strconv"
-)
-
-// OnePassSignature represents a one-pass signature packet. See RFC 4880,
-// section 5.4.
-type OnePassSignature struct {
-	SigType    SignatureType
-	Hash       crypto.Hash
-	PubKeyAlgo PublicKeyAlgorithm
-	KeyId      uint64
-	IsLast     bool
-}
-
-const onePassSignatureVersion = 3
-
-func (ops *OnePassSignature) parse(r io.Reader) (err os.Error) {
-	var buf [13]byte
-
-	_, err = readFull(r, buf[:])
-	if err != nil {
-		return
-	}
-	if buf[0] != onePassSignatureVersion {
-		err = error.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
-	}
-
-	var ok bool
-	ops.Hash, ok = s2k.HashIdToHash(buf[2])
-	if !ok {
-		return error.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
-	}
-
-	ops.SigType = SignatureType(buf[1])
-	ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
-	ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
-	ops.IsLast = buf[12] != 0
-	return
-}
-
-// Serialize marshals the given OnePassSignature to w.
-func (ops *OnePassSignature) Serialize(w io.Writer) os.Error {
-	var buf [13]byte
-	buf[0] = onePassSignatureVersion
-	buf[1] = uint8(ops.SigType)
-	var ok bool
-	buf[2], ok = s2k.HashToHashId(ops.Hash)
-	if !ok {
-		return error.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
-	}
-	buf[3] = uint8(ops.PubKeyAlgo)
-	binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
-	if ops.IsLast {
-		buf[12] = 1
-	}
-
-	if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
-		return err
-	}
-	_, err := w.Write(buf[:])
-	return err
-}
diff --git a/src/pkg/crypto/openpgp/packet/packet.go b/src/pkg/crypto/openpgp/packet/packet.go
deleted file mode 100644
index 1d7297e..0000000
--- a/src/pkg/crypto/openpgp/packet/packet.go
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright 2011 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 packet implements parsing and serialization of OpenPGP packets, as
-// specified in RFC 4880.
-package packet
-
-import (
-	"big"
-	"crypto/aes"
-	"crypto/cast5"
-	"crypto/cipher"
-	"crypto/openpgp/error"
-	"io"
-	"os"
-)
-
-// readFull is the same as io.ReadFull except that reading zero bytes returns
-// ErrUnexpectedEOF rather than EOF.
-func readFull(r io.Reader, buf []byte) (n int, err os.Error) {
-	n, err = io.ReadFull(r, buf)
-	if err == os.EOF {
-		err = io.ErrUnexpectedEOF
-	}
-	return
-}
-
-// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
-func readLength(r io.Reader) (length int64, isPartial bool, err os.Error) {
-	var buf [4]byte
-	_, err = readFull(r, buf[:1])
-	if err != nil {
-		return
-	}
-	switch {
-	case buf[0] < 192:
-		length = int64(buf[0])
-	case buf[0] < 224:
-		length = int64(buf[0]-192) << 8
-		_, err = readFull(r, buf[0:1])
-		if err != nil {
-			return
-		}
-		length += int64(buf[0]) + 192
-	case buf[0] < 255:
-		length = int64(1) << (buf[0] & 0x1f)
-		isPartial = true
-	default:
-		_, err = readFull(r, buf[0:4])
-		if err != nil {
-			return
-		}
-		length = int64(buf[0])<<24 |
-			int64(buf[1])<<16 |
-			int64(buf[2])<<8 |
-			int64(buf[3])
-	}
-	return
-}
-
-// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
-// The continuation lengths are parsed and removed from the stream and EOF is
-// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
-type partialLengthReader struct {
-	r         io.Reader
-	remaining int64
-	isPartial bool
-}
-
-func (r *partialLengthReader) Read(p []byte) (n int, err os.Error) {
-	for r.remaining == 0 {
-		if !r.isPartial {
-			return 0, os.EOF
-		}
-		r.remaining, r.isPartial, err = readLength(r.r)
-		if err != nil {
-			return 0, err
-		}
-	}
-
-	toRead := int64(len(p))
-	if toRead > r.remaining {
-		toRead = r.remaining
-	}
-
-	n, err = r.r.Read(p[:int(toRead)])
-	r.remaining -= int64(n)
-	if n < int(toRead) && err == os.EOF {
-		err = io.ErrUnexpectedEOF
-	}
-	return
-}
-
-// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
-// See RFC 4880, section 4.2.2.4.
-type partialLengthWriter struct {
-	w          io.WriteCloser
-	lengthByte [1]byte
-}
-
-func (w *partialLengthWriter) Write(p []byte) (n int, err os.Error) {
-	for len(p) > 0 {
-		for power := uint(14); power < 32; power-- {
-			l := 1 << power
-			if len(p) >= l {
-				w.lengthByte[0] = 224 + uint8(power)
-				_, err = w.w.Write(w.lengthByte[:])
-				if err != nil {
-					return
-				}
-				var m int
-				m, err = w.w.Write(p[:l])
-				n += m
-				if err != nil {
-					return
-				}
-				p = p[l:]
-				break
-			}
-		}
-	}
-	return
-}
-
-func (w *partialLengthWriter) Close() os.Error {
-	w.lengthByte[0] = 0
-	_, err := w.w.Write(w.lengthByte[:])
-	if err != nil {
-		return err
-	}
-	return w.w.Close()
-}
-
-// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
-// underlying Reader returns EOF before the limit has been reached.
-type spanReader struct {
-	r io.Reader
-	n int64
-}
-
-func (l *spanReader) Read(p []byte) (n int, err os.Error) {
-	if l.n <= 0 {
-		return 0, os.EOF
-	}
-	if int64(len(p)) > l.n {
-		p = p[0:l.n]
-	}
-	n, err = l.r.Read(p)
-	l.n -= int64(n)
-	if l.n > 0 && err == os.EOF {
-		err = io.ErrUnexpectedEOF
-	}
-	return
-}
-
-// readHeader parses a packet header and returns an io.Reader which will return
-// the contents of the packet. See RFC 4880, section 4.2.
-func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err os.Error) {
-	var buf [4]byte
-	_, err = io.ReadFull(r, buf[:1])
-	if err != nil {
-		return
-	}
-	if buf[0]&0x80 == 0 {
-		err = error.StructuralError("tag byte does not have MSB set")
-		return
-	}
-	if buf[0]&0x40 == 0 {
-		// Old format packet
-		tag = packetType((buf[0] & 0x3f) >> 2)
-		lengthType := buf[0] & 3
-		if lengthType == 3 {
-			length = -1
-			contents = r
-			return
-		}
-		lengthBytes := 1 << lengthType
-		_, err = readFull(r, buf[0:lengthBytes])
-		if err != nil {
-			return
-		}
-		for i := 0; i < lengthBytes; i++ {
-			length <<= 8
-			length |= int64(buf[i])
-		}
-		contents = &spanReader{r, length}
-		return
-	}
-
-	// New format packet
-	tag = packetType(buf[0] & 0x3f)
-	length, isPartial, err := readLength(r)
-	if err != nil {
-		return
-	}
-	if isPartial {
-		contents = &partialLengthReader{
-			remaining: length,
-			isPartial: true,
-			r:         r,
-		}
-		length = -1
-	} else {
-		contents = &spanReader{r, length}
-	}
-	return
-}
-
-// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
-// 4.2.
-func serializeHeader(w io.Writer, ptype packetType, length int) (err os.Error) {
-	var buf [6]byte
-	var n int
-
-	buf[0] = 0x80 | 0x40 | byte(ptype)
-	if length < 192 {
-		buf[1] = byte(length)
-		n = 2
-	} else if length < 8384 {
-		length -= 192
-		buf[1] = 192 + byte(length>>8)
-		buf[2] = byte(length)
-		n = 3
-	} else {
-		buf[1] = 255
-		buf[2] = byte(length >> 24)
-		buf[3] = byte(length >> 16)
-		buf[4] = byte(length >> 8)
-		buf[5] = byte(length)
-		n = 6
-	}
-
-	_, err = w.Write(buf[:n])
-	return
-}
-
-// serializeStreamHeader writes an OpenPGP packet header to w where the
-// length of the packet is unknown. It returns a io.WriteCloser which can be
-// used to write the contents of the packet. See RFC 4880, section 4.2.
-func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err os.Error) {
-	var buf [1]byte
-	buf[0] = 0x80 | 0x40 | byte(ptype)
-	_, err = w.Write(buf[:])
-	if err != nil {
-		return
-	}
-	out = &partialLengthWriter{w: w}
-	return
-}
-
-// Packet represents an OpenPGP packet. Users are expected to try casting
-// instances of this interface to specific packet types.
-type Packet interface {
-	parse(io.Reader) os.Error
-}
-
-// consumeAll reads from the given Reader until error, returning the number of
-// bytes read.
-func consumeAll(r io.Reader) (n int64, err os.Error) {
-	var m int
-	var buf [1024]byte
-
-	for {
-		m, err = r.Read(buf[:])
-		n += int64(m)
-		if err == os.EOF {
-			err = nil
-			return
-		}
-		if err != nil {
-			return
-		}
-	}
-
-	panic("unreachable")
-}
-
-// packetType represents the numeric ids of the different OpenPGP packet types. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
-type packetType uint8
-
-const (
-	packetTypeEncryptedKey              packetType = 1
-	packetTypeSignature                 packetType = 2
-	packetTypeSymmetricKeyEncrypted     packetType = 3
-	packetTypeOnePassSignature          packetType = 4
-	packetTypePrivateKey                packetType = 5
-	packetTypePublicKey                 packetType = 6
-	packetTypePrivateSubkey             packetType = 7
-	packetTypeCompressed                packetType = 8
-	packetTypeSymmetricallyEncrypted    packetType = 9
-	packetTypeLiteralData               packetType = 11
-	packetTypeUserId                    packetType = 13
-	packetTypePublicSubkey              packetType = 14
-	packetTypeSymmetricallyEncryptedMDC packetType = 18
-)
-
-// Read reads a single OpenPGP packet from the given io.Reader. If there is an
-// error parsing a packet, the whole packet is consumed from the input.
-func Read(r io.Reader) (p Packet, err os.Error) {
-	tag, _, contents, err := readHeader(r)
-	if err != nil {
-		return
-	}
-
-	switch tag {
-	case packetTypeEncryptedKey:
-		p = new(EncryptedKey)
-	case packetTypeSignature:
-		p = new(Signature)
-	case packetTypeSymmetricKeyEncrypted:
-		p = new(SymmetricKeyEncrypted)
-	case packetTypeOnePassSignature:
-		p = new(OnePassSignature)
-	case packetTypePrivateKey, packetTypePrivateSubkey:
-		pk := new(PrivateKey)
-		if tag == packetTypePrivateSubkey {
-			pk.IsSubkey = true
-		}
-		p = pk
-	case packetTypePublicKey, packetTypePublicSubkey:
-		pk := new(PublicKey)
-		if tag == packetTypePublicSubkey {
-			pk.IsSubkey = true
-		}
-		p = pk
-	case packetTypeCompressed:
-		p = new(Compressed)
-	case packetTypeSymmetricallyEncrypted:
-		p = new(SymmetricallyEncrypted)
-	case packetTypeLiteralData:
-		p = new(LiteralData)
-	case packetTypeUserId:
-		p = new(UserId)
-	case packetTypeSymmetricallyEncryptedMDC:
-		se := new(SymmetricallyEncrypted)
-		se.MDC = true
-		p = se
-	default:
-		err = error.UnknownPacketTypeError(tag)
-	}
-	if p != nil {
-		err = p.parse(contents)
-	}
-	if err != nil {
-		consumeAll(contents)
-	}
-	return
-}
-
-// SignatureType represents the different semantic meanings of an OpenPGP
-// signature. See RFC 4880, section 5.2.1.
-type SignatureType uint8
-
-const (
-	SigTypeBinary        SignatureType = 0
-	SigTypeText                        = 1
-	SigTypeGenericCert                 = 0x10
-	SigTypePersonaCert                 = 0x11
-	SigTypeCasualCert                  = 0x12
-	SigTypePositiveCert                = 0x13
-	SigTypeSubkeyBinding               = 0x18
-)
-
-// PublicKeyAlgorithm represents the different public key system specified for
-// OpenPGP. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
-type PublicKeyAlgorithm uint8
-
-const (
-	PubKeyAlgoRSA            PublicKeyAlgorithm = 1
-	PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
-	PubKeyAlgoRSASignOnly    PublicKeyAlgorithm = 3
-	PubKeyAlgoElGamal        PublicKeyAlgorithm = 16
-	PubKeyAlgoDSA            PublicKeyAlgorithm = 17
-)
-
-// CanEncrypt returns true if it's possible to encrypt a message to a public
-// key of the given type.
-func (pka PublicKeyAlgorithm) CanEncrypt() bool {
-	switch pka {
-	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
-		return true
-	}
-	return false
-}
-
-// CanSign returns true if it's possible for a public key of the given type to
-// sign a message.
-func (pka PublicKeyAlgorithm) CanSign() bool {
-	switch pka {
-	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
-		return true
-	}
-	return false
-}
-
-// CipherFunction represents the different block ciphers specified for OpenPGP. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
-type CipherFunction uint8
-
-const (
-	CipherCAST5  CipherFunction = 3
-	CipherAES128 CipherFunction = 7
-	CipherAES192 CipherFunction = 8
-	CipherAES256 CipherFunction = 9
-)
-
-// KeySize returns the key size, in bytes, of cipher.
-func (cipher CipherFunction) KeySize() int {
-	switch cipher {
-	case CipherCAST5:
-		return cast5.KeySize
-	case CipherAES128:
-		return 16
-	case CipherAES192:
-		return 24
-	case CipherAES256:
-		return 32
-	}
-	return 0
-}
-
-// blockSize returns the block size, in bytes, of cipher.
-func (cipher CipherFunction) blockSize() int {
-	switch cipher {
-	case CipherCAST5:
-		return 8
-	case CipherAES128, CipherAES192, CipherAES256:
-		return 16
-	}
-	return 0
-}
-
-// new returns a fresh instance of the given cipher.
-func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
-	switch cipher {
-	case CipherCAST5:
-		block, _ = cast5.NewCipher(key)
-	case CipherAES128, CipherAES192, CipherAES256:
-		block, _ = aes.NewCipher(key)
-	}
-	return
-}
-
-// readMPI reads a big integer from r. The bit length returned is the bit
-// length that was specified in r. This is preserved so that the integer can be
-// reserialized exactly.
-func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err os.Error) {
-	var buf [2]byte
-	_, err = readFull(r, buf[0:])
-	if err != nil {
-		return
-	}
-	bitLength = uint16(buf[0])<<8 | uint16(buf[1])
-	numBytes := (int(bitLength) + 7) / 8
-	mpi = make([]byte, numBytes)
-	_, err = readFull(r, mpi)
-	return
-}
-
-// mpiLength returns the length of the given *big.Int when serialized as an
-// MPI.
-func mpiLength(n *big.Int) (mpiLengthInBytes int) {
-	mpiLengthInBytes = 2 /* MPI length */
-	mpiLengthInBytes += (n.BitLen() + 7) / 8
-	return
-}
-
-// writeMPI serializes a big integer to w.
-func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err os.Error) {
-	_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
-	if err == nil {
-		_, err = w.Write(mpiBytes)
-	}
-	return
-}
-
-// writeBig serializes a *big.Int to w.
-func writeBig(w io.Writer, i *big.Int) os.Error {
-	return writeMPI(w, uint16(i.BitLen()), i.Bytes())
-}
diff --git a/src/pkg/crypto/openpgp/packet/packet_test.go b/src/pkg/crypto/openpgp/packet/packet_test.go
deleted file mode 100644
index 23d9978..0000000
--- a/src/pkg/crypto/openpgp/packet/packet_test.go
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"bytes"
-	"crypto/openpgp/error"
-	"encoding/hex"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"testing"
-)
-
-func TestReadFull(t *testing.T) {
-	var out [4]byte
-
-	b := bytes.NewBufferString("foo")
-	n, err := readFull(b, out[:3])
-	if n != 3 || err != nil {
-		t.Errorf("full read failed n:%d err:%s", n, err)
-	}
-
-	b = bytes.NewBufferString("foo")
-	n, err = readFull(b, out[:4])
-	if n != 3 || err != io.ErrUnexpectedEOF {
-		t.Errorf("partial read failed n:%d err:%s", n, err)
-	}
-
-	b = bytes.NewBuffer(nil)
-	n, err = readFull(b, out[:3])
-	if n != 0 || err != io.ErrUnexpectedEOF {
-		t.Errorf("empty read failed n:%d err:%s", n, err)
-	}
-}
-
-func readerFromHex(s string) io.Reader {
-	data, err := hex.DecodeString(s)
-	if err != nil {
-		panic("readerFromHex: bad input")
-	}
-	return bytes.NewBuffer(data)
-}
-
-var readLengthTests = []struct {
-	hexInput  string
-	length    int64
-	isPartial bool
-	err       os.Error
-}{
-	{"", 0, false, io.ErrUnexpectedEOF},
-	{"1f", 31, false, nil},
-	{"c0", 0, false, io.ErrUnexpectedEOF},
-	{"c101", 256 + 1 + 192, false, nil},
-	{"e0", 1, true, nil},
-	{"e1", 2, true, nil},
-	{"e2", 4, true, nil},
-	{"ff", 0, false, io.ErrUnexpectedEOF},
-	{"ff00", 0, false, io.ErrUnexpectedEOF},
-	{"ff0000", 0, false, io.ErrUnexpectedEOF},
-	{"ff000000", 0, false, io.ErrUnexpectedEOF},
-	{"ff00000000", 0, false, nil},
-	{"ff01020304", 16909060, false, nil},
-}
-
-func TestReadLength(t *testing.T) {
-	for i, test := range readLengthTests {
-		length, isPartial, err := readLength(readerFromHex(test.hexInput))
-		if test.err != nil {
-			if err != test.err {
-				t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
-			}
-			continue
-		}
-		if err != nil {
-			t.Errorf("%d: unexpected error: %s", i, err)
-			continue
-		}
-		if length != test.length || isPartial != test.isPartial {
-			t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial)
-		}
-	}
-}
-
-var partialLengthReaderTests = []struct {
-	hexInput  string
-	err       os.Error
-	hexOutput string
-}{
-	{"e0", io.ErrUnexpectedEOF, ""},
-	{"e001", io.ErrUnexpectedEOF, ""},
-	{"e0010102", nil, "0102"},
-	{"ff00000000", nil, ""},
-	{"e10102e1030400", nil, "01020304"},
-	{"e101", io.ErrUnexpectedEOF, ""},
-}
-
-func TestPartialLengthReader(t *testing.T) {
-	for i, test := range partialLengthReaderTests {
-		r := &partialLengthReader{readerFromHex(test.hexInput), 0, true}
-		out, err := ioutil.ReadAll(r)
-		if test.err != nil {
-			if err != test.err {
-				t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
-			}
-			continue
-		}
-		if err != nil {
-			t.Errorf("%d: unexpected error: %s", i, err)
-			continue
-		}
-
-		got := fmt.Sprintf("%x", out)
-		if got != test.hexOutput {
-			t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got)
-		}
-	}
-}
-
-var readHeaderTests = []struct {
-	hexInput        string
-	structuralError bool
-	unexpectedEOF   bool
-	tag             int
-	length          int64
-	hexOutput       string
-}{
-	{"", false, false, 0, 0, ""},
-	{"7f", true, false, 0, 0, ""},
-
-	// Old format headers
-	{"80", false, true, 0, 0, ""},
-	{"8001", false, true, 0, 1, ""},
-	{"800102", false, false, 0, 1, "02"},
-	{"81000102", false, false, 0, 1, "02"},
-	{"820000000102", false, false, 0, 1, "02"},
-	{"860000000102", false, false, 1, 1, "02"},
-	{"83010203", false, false, 0, -1, "010203"},
-
-	// New format headers
-	{"c0", false, true, 0, 0, ""},
-	{"c000", false, false, 0, 0, ""},
-	{"c00102", false, false, 0, 1, "02"},
-	{"c0020203", false, false, 0, 2, "0203"},
-	{"c00202", false, true, 0, 2, ""},
-	{"c3020203", false, false, 3, 2, "0203"},
-}
-
-func TestReadHeader(t *testing.T) {
-	for i, test := range readHeaderTests {
-		tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
-		if test.structuralError {
-			if _, ok := err.(error.StructuralError); ok {
-				continue
-			}
-			t.Errorf("%d: expected StructuralError, got:%s", i, err)
-			continue
-		}
-		if err != nil {
-			if len(test.hexInput) == 0 && err == os.EOF {
-				continue
-			}
-			if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
-				t.Errorf("%d: unexpected error from readHeader: %s", i, err)
-			}
-			continue
-		}
-		if int(tag) != test.tag || length != test.length {
-			t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length)
-			continue
-		}
-
-		body, err := ioutil.ReadAll(contents)
-		if err != nil {
-			if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
-				t.Errorf("%d: unexpected error from contents: %s", i, err)
-			}
-			continue
-		}
-		if test.unexpectedEOF {
-			t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i)
-			continue
-		}
-		got := fmt.Sprintf("%x", body)
-		if got != test.hexOutput {
-			t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput)
-		}
-	}
-}
-
-func TestSerializeHeader(t *testing.T) {
-	tag := packetTypePublicKey
-	lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000}
-
-	for _, length := range lengths {
-		buf := bytes.NewBuffer(nil)
-		serializeHeader(buf, tag, length)
-		tag2, length2, _, err := readHeader(buf)
-		if err != nil {
-			t.Errorf("length %d, err: %s", length, err)
-		}
-		if tag2 != tag {
-			t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag)
-		}
-		if int(length2) != length {
-			t.Errorf("length %d, length incorrect (got %d)", length, length2)
-		}
-	}
-}
-
-func TestPartialLengths(t *testing.T) {
-	buf := bytes.NewBuffer(nil)
-	w := new(partialLengthWriter)
-	w.w = noOpCloser{buf}
-
-	const maxChunkSize = 64
-
-	var b [maxChunkSize]byte
-	var n uint8
-	for l := 1; l <= maxChunkSize; l++ {
-		for i := 0; i < l; i++ {
-			b[i] = n
-			n++
-		}
-		m, err := w.Write(b[:l])
-		if m != l {
-			t.Errorf("short write got: %d want: %d", m, l)
-		}
-		if err != nil {
-			t.Errorf("error from write: %s", err)
-		}
-	}
-	w.Close()
-
-	want := (maxChunkSize * (maxChunkSize + 1)) / 2
-	copyBuf := bytes.NewBuffer(nil)
-	r := &partialLengthReader{buf, 0, true}
-	m, err := io.Copy(copyBuf, r)
-	if m != int64(want) {
-		t.Errorf("short copy got: %d want: %d", m, want)
-	}
-	if err != nil {
-		t.Errorf("error from copy: %s", err)
-	}
-
-	copyBytes := copyBuf.Bytes()
-	for i := 0; i < want; i++ {
-		if copyBytes[i] != uint8(i) {
-			t.Errorf("bad pattern in copy at %d", i)
-			break
-		}
-	}
-}
diff --git a/src/pkg/crypto/openpgp/packet/private_key.go b/src/pkg/crypto/openpgp/packet/private_key.go
deleted file mode 100644
index 6f8133d..0000000
--- a/src/pkg/crypto/openpgp/packet/private_key.go
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"big"
-	"bytes"
-	"crypto/cipher"
-	"crypto/dsa"
-	"crypto/openpgp/elgamal"
-	"crypto/openpgp/error"
-	"crypto/openpgp/s2k"
-	"crypto/rsa"
-	"crypto/sha1"
-	"io"
-	"io/ioutil"
-	"os"
-	"strconv"
-)
-
-// PrivateKey represents a possibly encrypted private key. See RFC 4880,
-// section 5.5.3.
-type PrivateKey struct {
-	PublicKey
-	Encrypted     bool // if true then the private key is unavailable until Decrypt has been called.
-	encryptedData []byte
-	cipher        CipherFunction
-	s2k           func(out, in []byte)
-	PrivateKey    interface{} // An *rsa.PrivateKey.
-	sha1Checksum  bool
-	iv            []byte
-}
-
-func NewRSAPrivateKey(currentTimeSecs uint32, priv *rsa.PrivateKey, isSubkey bool) *PrivateKey {
-	pk := new(PrivateKey)
-	pk.PublicKey = *NewRSAPublicKey(currentTimeSecs, &priv.PublicKey, isSubkey)
-	pk.PrivateKey = priv
-	return pk
-}
-
-func (pk *PrivateKey) parse(r io.Reader) (err os.Error) {
-	err = (&pk.PublicKey).parse(r)
-	if err != nil {
-		return
-	}
-	var buf [1]byte
-	_, err = readFull(r, buf[:])
-	if err != nil {
-		return
-	}
-
-	s2kType := buf[0]
-
-	switch s2kType {
-	case 0:
-		pk.s2k = nil
-		pk.Encrypted = false
-	case 254, 255:
-		_, err = readFull(r, buf[:])
-		if err != nil {
-			return
-		}
-		pk.cipher = CipherFunction(buf[0])
-		pk.Encrypted = true
-		pk.s2k, err = s2k.Parse(r)
-		if err != nil {
-			return
-		}
-		if s2kType == 254 {
-			pk.sha1Checksum = true
-		}
-	default:
-		return error.UnsupportedError("deprecated s2k function in private key")
-	}
-
-	if pk.Encrypted {
-		blockSize := pk.cipher.blockSize()
-		if blockSize == 0 {
-			return error.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
-		}
-		pk.iv = make([]byte, blockSize)
-		_, err = readFull(r, pk.iv)
-		if err != nil {
-			return
-		}
-	}
-
-	pk.encryptedData, err = ioutil.ReadAll(r)
-	if err != nil {
-		return
-	}
-
-	if !pk.Encrypted {
-		return pk.parsePrivateKey(pk.encryptedData)
-	}
-
-	return
-}
-
-func mod64kHash(d []byte) uint16 {
-	h := uint16(0)
-	for i := 0; i < len(d); i += 2 {
-		v := uint16(d[i]) << 8
-		if i+1 < len(d) {
-			v += uint16(d[i+1])
-		}
-		h += v
-	}
-	return h
-}
-
-func (pk *PrivateKey) Serialize(w io.Writer) (err os.Error) {
-	// TODO(agl): support encrypted private keys
-	buf := bytes.NewBuffer(nil)
-	err = pk.PublicKey.serializeWithoutHeaders(buf)
-	if err != nil {
-		return
-	}
-	buf.WriteByte(0 /* no encryption */ )
-
-	privateKeyBuf := bytes.NewBuffer(nil)
-
-	switch priv := pk.PrivateKey.(type) {
-	case *rsa.PrivateKey:
-		err = serializeRSAPrivateKey(privateKeyBuf, priv)
-	default:
-		err = error.InvalidArgumentError("non-RSA private key")
-	}
-	if err != nil {
-		return
-	}
-
-	ptype := packetTypePrivateKey
-	contents := buf.Bytes()
-	privateKeyBytes := privateKeyBuf.Bytes()
-	if pk.IsSubkey {
-		ptype = packetTypePrivateSubkey
-	}
-	err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
-	if err != nil {
-		return
-	}
-	_, err = w.Write(contents)
-	if err != nil {
-		return
-	}
-	_, err = w.Write(privateKeyBytes)
-	if err != nil {
-		return
-	}
-
-	checksum := mod64kHash(privateKeyBytes)
-	var checksumBytes [2]byte
-	checksumBytes[0] = byte(checksum >> 8)
-	checksumBytes[1] = byte(checksum)
-	_, err = w.Write(checksumBytes[:])
-
-	return
-}
-
-func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) os.Error {
-	err := writeBig(w, priv.D)
-	if err != nil {
-		return err
-	}
-	err = writeBig(w, priv.Primes[1])
-	if err != nil {
-		return err
-	}
-	err = writeBig(w, priv.Primes[0])
-	if err != nil {
-		return err
-	}
-	return writeBig(w, priv.Precomputed.Qinv)
-}
-
-// Decrypt decrypts an encrypted private key using a passphrase.
-func (pk *PrivateKey) Decrypt(passphrase []byte) os.Error {
-	if !pk.Encrypted {
-		return nil
-	}
-
-	key := make([]byte, pk.cipher.KeySize())
-	pk.s2k(key, passphrase)
-	block := pk.cipher.new(key)
-	cfb := cipher.NewCFBDecrypter(block, pk.iv)
-
-	data := pk.encryptedData
-	cfb.XORKeyStream(data, data)
-
-	if pk.sha1Checksum {
-		if len(data) < sha1.Size {
-			return error.StructuralError("truncated private key data")
-		}
-		h := sha1.New()
-		h.Write(data[:len(data)-sha1.Size])
-		sum := h.Sum()
-		if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
-			return error.StructuralError("private key checksum failure")
-		}
-		data = data[:len(data)-sha1.Size]
-	} else {
-		if len(data) < 2 {
-			return error.StructuralError("truncated private key data")
-		}
-		var sum uint16
-		for i := 0; i < len(data)-2; i++ {
-			sum += uint16(data[i])
-		}
-		if data[len(data)-2] != uint8(sum>>8) ||
-			data[len(data)-1] != uint8(sum) {
-			return error.StructuralError("private key checksum failure")
-		}
-		data = data[:len(data)-2]
-	}
-
-	return pk.parsePrivateKey(data)
-}
-
-func (pk *PrivateKey) parsePrivateKey(data []byte) (err os.Error) {
-	switch pk.PublicKey.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
-		return pk.parseRSAPrivateKey(data)
-	case PubKeyAlgoDSA:
-		return pk.parseDSAPrivateKey(data)
-	case PubKeyAlgoElGamal:
-		return pk.parseElGamalPrivateKey(data)
-	}
-	panic("impossible")
-}
-
-func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err os.Error) {
-	rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
-	rsaPriv := new(rsa.PrivateKey)
-	rsaPriv.PublicKey = *rsaPub
-
-	buf := bytes.NewBuffer(data)
-	d, _, err := readMPI(buf)
-	if err != nil {
-		return
-	}
-	p, _, err := readMPI(buf)
-	if err != nil {
-		return
-	}
-	q, _, err := readMPI(buf)
-	if err != nil {
-		return
-	}
-
-	rsaPriv.D = new(big.Int).SetBytes(d)
-	rsaPriv.Primes = make([]*big.Int, 2)
-	rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
-	rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
-	rsaPriv.Precompute()
-	pk.PrivateKey = rsaPriv
-	pk.Encrypted = false
-	pk.encryptedData = nil
-
-	return nil
-}
-
-func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err os.Error) {
-	dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
-	dsaPriv := new(dsa.PrivateKey)
-	dsaPriv.PublicKey = *dsaPub
-
-	buf := bytes.NewBuffer(data)
-	x, _, err := readMPI(buf)
-	if err != nil {
-		return
-	}
-
-	dsaPriv.X = new(big.Int).SetBytes(x)
-	pk.PrivateKey = dsaPriv
-	pk.Encrypted = false
-	pk.encryptedData = nil
-
-	return nil
-}
-
-func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err os.Error) {
-	pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
-	priv := new(elgamal.PrivateKey)
-	priv.PublicKey = *pub
-
-	buf := bytes.NewBuffer(data)
-	x, _, err := readMPI(buf)
-	if err != nil {
-		return
-	}
-
-	priv.X = new(big.Int).SetBytes(x)
-	pk.PrivateKey = priv
-	pk.Encrypted = false
-	pk.encryptedData = nil
-
-	return nil
-}
diff --git a/src/pkg/crypto/openpgp/packet/private_key_test.go b/src/pkg/crypto/openpgp/packet/private_key_test.go
deleted file mode 100644
index 60eebaa..0000000
--- a/src/pkg/crypto/openpgp/packet/private_key_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"testing"
-)
-
-var privateKeyTests = []struct {
-	privateKeyHex string
-	creationTime  uint32
-}{
-	{
-		privKeyRSAHex,
-		0x4cc349a8,
-	},
-	{
-		privKeyElGamalHex,
-		0x4df9ee1a,
-	},
-}
-
-func TestPrivateKeyRead(t *testing.T) {
-	for i, test := range privateKeyTests {
-		packet, err := Read(readerFromHex(test.privateKeyHex))
-		if err != nil {
-			t.Errorf("#%d: failed to parse: %s", i, err)
-			continue
-		}
-
-		privKey := packet.(*PrivateKey)
-
-		if !privKey.Encrypted {
-			t.Errorf("#%d: private key isn't encrypted", i)
-			continue
-		}
-
-		err = privKey.Decrypt([]byte("testing"))
-		if err != nil {
-			t.Errorf("#%d: failed to decrypt: %s", i, err)
-			continue
-		}
-
-		if privKey.CreationTime != test.creationTime || privKey.Encrypted {
-			t.Errorf("#%d: bad result, got: %#v", i, privKey)
-		}
-	}
-}
-
-// Generated with `gpg --export-secret-keys "Test Key 2"`
-const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
-
-// Generated by `gpg --export-secret-keys` followed by a manual extraction of
-// the ElGamal subkey from the packets.
-const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"
diff --git a/src/pkg/crypto/openpgp/packet/public_key.go b/src/pkg/crypto/openpgp/packet/public_key.go
deleted file mode 100644
index e6b0ae5..0000000
--- a/src/pkg/crypto/openpgp/packet/public_key.go
+++ /dev/null
@@ -1,393 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"big"
-	"crypto/dsa"
-	"crypto/openpgp/elgamal"
-	"crypto/openpgp/error"
-	"crypto/rsa"
-	"crypto/sha1"
-	"encoding/binary"
-	"fmt"
-	"hash"
-	"io"
-	"os"
-	"strconv"
-)
-
-// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
-type PublicKey struct {
-	CreationTime uint32 // seconds since the epoch
-	PubKeyAlgo   PublicKeyAlgorithm
-	PublicKey    interface{} // Either a *rsa.PublicKey or *dsa.PublicKey
-	Fingerprint  [20]byte
-	KeyId        uint64
-	IsSubkey     bool
-
-	n, e, p, q, g, y parsedMPI
-}
-
-func fromBig(n *big.Int) parsedMPI {
-	return parsedMPI{
-		bytes:     n.Bytes(),
-		bitLength: uint16(n.BitLen()),
-	}
-}
-
-// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
-func NewRSAPublicKey(creationTimeSecs uint32, pub *rsa.PublicKey, isSubkey bool) *PublicKey {
-	pk := &PublicKey{
-		CreationTime: creationTimeSecs,
-		PubKeyAlgo:   PubKeyAlgoRSA,
-		PublicKey:    pub,
-		IsSubkey:     isSubkey,
-		n:            fromBig(pub.N),
-		e:            fromBig(big.NewInt(int64(pub.E))),
-	}
-
-	pk.setFingerPrintAndKeyId()
-	return pk
-}
-
-func (pk *PublicKey) parse(r io.Reader) (err os.Error) {
-	// RFC 4880, section 5.5.2
-	var buf [6]byte
-	_, err = readFull(r, buf[:])
-	if err != nil {
-		return
-	}
-	if buf[0] != 4 {
-		return error.UnsupportedError("public key version")
-	}
-	pk.CreationTime = uint32(buf[1])<<24 | uint32(buf[2])<<16 | uint32(buf[3])<<8 | uint32(buf[4])
-	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
-	switch pk.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
-		err = pk.parseRSA(r)
-	case PubKeyAlgoDSA:
-		err = pk.parseDSA(r)
-	case PubKeyAlgoElGamal:
-		err = pk.parseElGamal(r)
-	default:
-		err = error.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
-	}
-	if err != nil {
-		return
-	}
-
-	pk.setFingerPrintAndKeyId()
-	return
-}
-
-func (pk *PublicKey) setFingerPrintAndKeyId() {
-	// RFC 4880, section 12.2
-	fingerPrint := sha1.New()
-	pk.SerializeSignaturePrefix(fingerPrint)
-	pk.serializeWithoutHeaders(fingerPrint)
-	copy(pk.Fingerprint[:], fingerPrint.Sum())
-	pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
-}
-
-// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
-// section 5.5.2.
-func (pk *PublicKey) parseRSA(r io.Reader) (err os.Error) {
-	pk.n.bytes, pk.n.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-	pk.e.bytes, pk.e.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-
-	if len(pk.e.bytes) > 3 {
-		err = error.UnsupportedError("large public exponent")
-		return
-	}
-	rsa := &rsa.PublicKey{
-		N: new(big.Int).SetBytes(pk.n.bytes),
-		E: 0,
-	}
-	for i := 0; i < len(pk.e.bytes); i++ {
-		rsa.E <<= 8
-		rsa.E |= int(pk.e.bytes[i])
-	}
-	pk.PublicKey = rsa
-	return
-}
-
-// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
-// section 5.5.2.
-func (pk *PublicKey) parseDSA(r io.Reader) (err os.Error) {
-	pk.p.bytes, pk.p.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-	pk.q.bytes, pk.q.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-	pk.g.bytes, pk.g.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-	pk.y.bytes, pk.y.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-
-	dsa := new(dsa.PublicKey)
-	dsa.P = new(big.Int).SetBytes(pk.p.bytes)
-	dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
-	dsa.G = new(big.Int).SetBytes(pk.g.bytes)
-	dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
-	pk.PublicKey = dsa
-	return
-}
-
-// parseElGamal parses ElGamal public key material from the given Reader. See
-// RFC 4880, section 5.5.2.
-func (pk *PublicKey) parseElGamal(r io.Reader) (err os.Error) {
-	pk.p.bytes, pk.p.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-	pk.g.bytes, pk.g.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-	pk.y.bytes, pk.y.bitLength, err = readMPI(r)
-	if err != nil {
-		return
-	}
-
-	elgamal := new(elgamal.PublicKey)
-	elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
-	elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
-	elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
-	pk.PublicKey = elgamal
-	return
-}
-
-// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
-// The prefix is used when calculating a signature over this public key. See
-// RFC 4880, section 5.2.4.
-func (pk *PublicKey) SerializeSignaturePrefix(h hash.Hash) {
-	var pLength uint16
-	switch pk.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
-		pLength += 2 + uint16(len(pk.n.bytes))
-		pLength += 2 + uint16(len(pk.e.bytes))
-	case PubKeyAlgoDSA:
-		pLength += 2 + uint16(len(pk.p.bytes))
-		pLength += 2 + uint16(len(pk.q.bytes))
-		pLength += 2 + uint16(len(pk.g.bytes))
-		pLength += 2 + uint16(len(pk.y.bytes))
-	case PubKeyAlgoElGamal:
-		pLength += 2 + uint16(len(pk.p.bytes))
-		pLength += 2 + uint16(len(pk.g.bytes))
-		pLength += 2 + uint16(len(pk.y.bytes))
-	default:
-		panic("unknown public key algorithm")
-	}
-	pLength += 6
-	h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
-	return
-}
-
-func (pk *PublicKey) Serialize(w io.Writer) (err os.Error) {
-	length := 6 // 6 byte header
-
-	switch pk.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
-		length += 2 + len(pk.n.bytes)
-		length += 2 + len(pk.e.bytes)
-	case PubKeyAlgoDSA:
-		length += 2 + len(pk.p.bytes)
-		length += 2 + len(pk.q.bytes)
-		length += 2 + len(pk.g.bytes)
-		length += 2 + len(pk.y.bytes)
-	case PubKeyAlgoElGamal:
-		length += 2 + len(pk.p.bytes)
-		length += 2 + len(pk.g.bytes)
-		length += 2 + len(pk.y.bytes)
-	default:
-		panic("unknown public key algorithm")
-	}
-
-	packetType := packetTypePublicKey
-	if pk.IsSubkey {
-		packetType = packetTypePublicSubkey
-	}
-	err = serializeHeader(w, packetType, length)
-	if err != nil {
-		return
-	}
-	return pk.serializeWithoutHeaders(w)
-}
-
-// serializeWithoutHeaders marshals the PublicKey to w in the form of an
-// OpenPGP public key packet, not including the packet header.
-func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err os.Error) {
-	var buf [6]byte
-	buf[0] = 4
-	buf[1] = byte(pk.CreationTime >> 24)
-	buf[2] = byte(pk.CreationTime >> 16)
-	buf[3] = byte(pk.CreationTime >> 8)
-	buf[4] = byte(pk.CreationTime)
-	buf[5] = byte(pk.PubKeyAlgo)
-
-	_, err = w.Write(buf[:])
-	if err != nil {
-		return
-	}
-
-	switch pk.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
-		return writeMPIs(w, pk.n, pk.e)
-	case PubKeyAlgoDSA:
-		return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
-	case PubKeyAlgoElGamal:
-		return writeMPIs(w, pk.p, pk.g, pk.y)
-	}
-	return error.InvalidArgumentError("bad public-key algorithm")
-}
-
-// CanSign returns true iff this public key can generate signatures
-func (pk *PublicKey) CanSign() bool {
-	return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
-}
-
-// VerifySignature returns nil iff sig is a valid signature, made by this
-// public key, of the data hashed into signed. signed is mutated by this call.
-func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err os.Error) {
-	if !pk.CanSign() {
-		return error.InvalidArgumentError("public key cannot generate signatures")
-	}
-
-	signed.Write(sig.HashSuffix)
-	hashBytes := signed.Sum()
-
-	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
-		return error.SignatureError("hash tag doesn't match")
-	}
-
-	if pk.PubKeyAlgo != sig.PubKeyAlgo {
-		return error.InvalidArgumentError("public key and signature use different algorithms")
-	}
-
-	switch pk.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-		rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
-		err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
-		if err != nil {
-			return error.SignatureError("RSA verification failure")
-		}
-		return nil
-	case PubKeyAlgoDSA:
-		dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
-		if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
-			return error.SignatureError("DSA verification failure")
-		}
-		return nil
-	default:
-		panic("shouldn't happen")
-	}
-	panic("unreachable")
-}
-
-// keySignatureHash returns a Hash of the message that needs to be signed for
-// pk to assert a subkey relationship to signed.
-func keySignatureHash(pk, signed *PublicKey, sig *Signature) (h hash.Hash, err os.Error) {
-	h = sig.Hash.New()
-	if h == nil {
-		return nil, error.UnsupportedError("hash function")
-	}
-
-	// RFC 4880, section 5.2.4
-	pk.SerializeSignaturePrefix(h)
-	pk.serializeWithoutHeaders(h)
-	signed.SerializeSignaturePrefix(h)
-	signed.serializeWithoutHeaders(h)
-	return
-}
-
-// VerifyKeySignature returns nil iff sig is a valid signature, made by this
-// public key, of signed.
-func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err os.Error) {
-	h, err := keySignatureHash(pk, signed, sig)
-	if err != nil {
-		return err
-	}
-	return pk.VerifySignature(h, sig)
-}
-
-// userIdSignatureHash returns a Hash of the message that needs to be signed
-// to assert that pk is a valid key for id.
-func userIdSignatureHash(id string, pk *PublicKey, sig *Signature) (h hash.Hash, err os.Error) {
-	h = sig.Hash.New()
-	if h == nil {
-		return nil, error.UnsupportedError("hash function")
-	}
-
-	// RFC 4880, section 5.2.4
-	pk.SerializeSignaturePrefix(h)
-	pk.serializeWithoutHeaders(h)
-
-	var buf [5]byte
-	buf[0] = 0xb4
-	buf[1] = byte(len(id) >> 24)
-	buf[2] = byte(len(id) >> 16)
-	buf[3] = byte(len(id) >> 8)
-	buf[4] = byte(len(id))
-	h.Write(buf[:])
-	h.Write([]byte(id))
-
-	return
-}
-
-// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
-// public key, of id.
-func (pk *PublicKey) VerifyUserIdSignature(id string, sig *Signature) (err os.Error) {
-	h, err := userIdSignatureHash(id, pk, sig)
-	if err != nil {
-		return err
-	}
-	return pk.VerifySignature(h, sig)
-}
-
-// KeyIdString returns the public key's fingerprint in capital hex
-// (e.g. "6C7EE1B8621CC013").
-func (pk *PublicKey) KeyIdString() string {
-	return fmt.Sprintf("%X", pk.Fingerprint[12:20])
-}
-
-// KeyIdShortString returns the short form of public key's fingerprint
-// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
-func (pk *PublicKey) KeyIdShortString() string {
-	return fmt.Sprintf("%X", pk.Fingerprint[16:20])
-}
-
-// A parsedMPI is used to store the contents of a big integer, along with the
-// bit length that was specified in the original input. This allows the MPI to
-// be reserialized exactly.
-type parsedMPI struct {
-	bytes     []byte
-	bitLength uint16
-}
-
-// writeMPIs is a utility function for serializing several big integers to the
-// given Writer.
-func writeMPIs(w io.Writer, mpis ...parsedMPI) (err os.Error) {
-	for _, mpi := range mpis {
-		err = writeMPI(w, mpi.bitLength, mpi.bytes)
-		if err != nil {
-			return
-		}
-	}
-	return
-}
diff --git a/src/pkg/crypto/openpgp/packet/public_key_test.go b/src/pkg/crypto/openpgp/packet/public_key_test.go
deleted file mode 100644
index 6e8bfbc..0000000
--- a/src/pkg/crypto/openpgp/packet/public_key_test.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"bytes"
-	"encoding/hex"
-	"testing"
-)
-
-var pubKeyTests = []struct {
-	hexData        string
-	hexFingerprint string
-	creationTime   uint32
-	pubKeyAlgo     PublicKeyAlgorithm
-	keyId          uint64
-	keyIdString    string
-	keyIdShort     string
-}{
-	{rsaPkDataHex, rsaFingerprintHex, 0x4d3c5c10, PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"},
-	{dsaPkDataHex, dsaFingerprintHex, 0x4d432f89, PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"},
-}
-
-func TestPublicKeyRead(t *testing.T) {
-	for i, test := range pubKeyTests {
-		packet, err := Read(readerFromHex(test.hexData))
-		if err != nil {
-			t.Errorf("#%d: Read error: %s", i, err)
-			continue
-		}
-		pk, ok := packet.(*PublicKey)
-		if !ok {
-			t.Errorf("#%d: failed to parse, got: %#v", i, packet)
-			continue
-		}
-		if pk.PubKeyAlgo != test.pubKeyAlgo {
-			t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
-		}
-		if pk.CreationTime != test.creationTime {
-			t.Errorf("#%d: bad creation time got:%x want:%x", i, pk.CreationTime, test.creationTime)
-		}
-		expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
-		if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
-			t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
-		}
-		if pk.KeyId != test.keyId {
-			t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
-		}
-		if g, e := pk.KeyIdString(), test.keyIdString; g != e {
-			t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
-		}
-		if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
-			t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
-		}
-	}
-}
-
-func TestPublicKeySerialize(t *testing.T) {
-	for i, test := range pubKeyTests {
-		packet, err := Read(readerFromHex(test.hexData))
-		if err != nil {
-			t.Errorf("#%d: Read error: %s", i, err)
-			continue
-		}
-		pk, ok := packet.(*PublicKey)
-		if !ok {
-			t.Errorf("#%d: failed to parse, got: %#v", i, packet)
-			continue
-		}
-		serializeBuf := bytes.NewBuffer(nil)
-		err = pk.Serialize(serializeBuf)
-		if err != nil {
-			t.Errorf("#%d: failed to serialize: %s", i, err)
-			continue
-		}
-
-		packet, err = Read(serializeBuf)
-		if err != nil {
-			t.Errorf("#%d: Read error (from serialized data): %s", i, err)
-			continue
-		}
-		pk, ok = packet.(*PublicKey)
-		if !ok {
-			t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet)
-			continue
-		}
-	}
-}
-
-const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
-
-const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
-
-const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
-
-const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
diff --git a/src/pkg/crypto/openpgp/packet/reader.go b/src/pkg/crypto/openpgp/packet/reader.go
deleted file mode 100644
index 5febc3b..0000000
--- a/src/pkg/crypto/openpgp/packet/reader.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"crypto/openpgp/error"
-	"io"
-	"os"
-)
-
-// Reader reads packets from an io.Reader and allows packets to be 'unread' so
-// that they result from the next call to Next.
-type Reader struct {
-	q       []Packet
-	readers []io.Reader
-}
-
-// Next returns the most recently unread Packet, or reads another packet from
-// the top-most io.Reader. Unknown packet types are skipped.
-func (r *Reader) Next() (p Packet, err os.Error) {
-	if len(r.q) > 0 {
-		p = r.q[len(r.q)-1]
-		r.q = r.q[:len(r.q)-1]
-		return
-	}
-
-	for len(r.readers) > 0 {
-		p, err = Read(r.readers[len(r.readers)-1])
-		if err == nil {
-			return
-		}
-		if err == os.EOF {
-			r.readers = r.readers[:len(r.readers)-1]
-			continue
-		}
-		if _, ok := err.(error.UnknownPacketTypeError); !ok {
-			return nil, err
-		}
-	}
-
-	return nil, os.EOF
-}
-
-// Push causes the Reader to start reading from a new io.Reader. When an EOF
-// error is seen from the new io.Reader, it is popped and the Reader continues
-// to read from the next most recent io.Reader.
-func (r *Reader) Push(reader io.Reader) {
-	r.readers = append(r.readers, reader)
-}
-
-// Unread causes the given Packet to be returned from the next call to Next.
-func (r *Reader) Unread(p Packet) {
-	r.q = append(r.q, p)
-}
-
-func NewReader(r io.Reader) *Reader {
-	return &Reader{
-		q:       nil,
-		readers: []io.Reader{r},
-	}
-}
diff --git a/src/pkg/crypto/openpgp/packet/signature.go b/src/pkg/crypto/openpgp/packet/signature.go
deleted file mode 100644
index 7577e28..0000000
--- a/src/pkg/crypto/openpgp/packet/signature.go
+++ /dev/null
@@ -1,558 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"crypto"
-	"crypto/dsa"
-	"crypto/openpgp/error"
-	"crypto/openpgp/s2k"
-	"crypto/rand"
-	"crypto/rsa"
-	"encoding/binary"
-	"hash"
-	"io"
-	"os"
-	"strconv"
-)
-
-// Signature represents a signature. See RFC 4880, section 5.2.
-type Signature struct {
-	SigType    SignatureType
-	PubKeyAlgo PublicKeyAlgorithm
-	Hash       crypto.Hash
-
-	// HashSuffix is extra data that is hashed in after the signed data.
-	HashSuffix []byte
-	// HashTag contains the first two bytes of the hash for fast rejection
-	// of bad signed data.
-	HashTag      [2]byte
-	CreationTime uint32 // Unix epoch time
-
-	RSASignature     parsedMPI
-	DSASigR, DSASigS parsedMPI
-
-	// rawSubpackets contains the unparsed subpackets, in order.
-	rawSubpackets []outputSubpacket
-
-	// The following are optional so are nil when not included in the
-	// signature.
-
-	SigLifetimeSecs, KeyLifetimeSecs                        *uint32
-	PreferredSymmetric, PreferredHash, PreferredCompression []uint8
-	IssuerKeyId                                             *uint64
-	IsPrimaryId                                             *bool
-
-	// FlagsValid is set if any flags were given. See RFC 4880, section
-	// 5.2.3.21 for details.
-	FlagsValid                                                           bool
-	FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
-
-	outSubpackets []outputSubpacket
-}
-
-func (sig *Signature) parse(r io.Reader) (err os.Error) {
-	// RFC 4880, section 5.2.3
-	var buf [5]byte
-	_, err = readFull(r, buf[:1])
-	if err != nil {
-		return
-	}
-	if buf[0] != 4 {
-		err = error.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
-		return
-	}
-
-	_, err = readFull(r, buf[:5])
-	if err != nil {
-		return
-	}
-	sig.SigType = SignatureType(buf[0])
-	sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
-	switch sig.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
-	default:
-		err = error.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
-		return
-	}
-
-	var ok bool
-	sig.Hash, ok = s2k.HashIdToHash(buf[2])
-	if !ok {
-		return error.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
-	}
-
-	hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
-	l := 6 + hashedSubpacketsLength
-	sig.HashSuffix = make([]byte, l+6)
-	sig.HashSuffix[0] = 4
-	copy(sig.HashSuffix[1:], buf[:5])
-	hashedSubpackets := sig.HashSuffix[6:l]
-	_, err = readFull(r, hashedSubpackets)
-	if err != nil {
-		return
-	}
-	// See RFC 4880, section 5.2.4
-	trailer := sig.HashSuffix[l:]
-	trailer[0] = 4
-	trailer[1] = 0xff
-	trailer[2] = uint8(l >> 24)
-	trailer[3] = uint8(l >> 16)
-	trailer[4] = uint8(l >> 8)
-	trailer[5] = uint8(l)
-
-	err = parseSignatureSubpackets(sig, hashedSubpackets, true)
-	if err != nil {
-		return
-	}
-
-	_, err = readFull(r, buf[:2])
-	if err != nil {
-		return
-	}
-	unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
-	unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
-	_, err = readFull(r, unhashedSubpackets)
-	if err != nil {
-		return
-	}
-	err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
-	if err != nil {
-		return
-	}
-
-	_, err = readFull(r, sig.HashTag[:2])
-	if err != nil {
-		return
-	}
-
-	switch sig.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-		sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
-	case PubKeyAlgoDSA:
-		sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
-		if err == nil {
-			sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
-		}
-	default:
-		panic("unreachable")
-	}
-	return
-}
-
-// parseSignatureSubpackets parses subpackets of the main signature packet. See
-// RFC 4880, section 5.2.3.1.
-func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err os.Error) {
-	for len(subpackets) > 0 {
-		subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
-		if err != nil {
-			return
-		}
-	}
-
-	if sig.CreationTime == 0 {
-		err = error.StructuralError("no creation time in signature")
-	}
-
-	return
-}
-
-type signatureSubpacketType uint8
-
-const (
-	creationTimeSubpacket        signatureSubpacketType = 2
-	signatureExpirationSubpacket signatureSubpacketType = 3
-	keyExpirySubpacket           signatureSubpacketType = 9
-	prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
-	issuerSubpacket              signatureSubpacketType = 16
-	prefHashAlgosSubpacket       signatureSubpacketType = 21
-	prefCompressionSubpacket     signatureSubpacketType = 22
-	primaryUserIdSubpacket       signatureSubpacketType = 25
-	keyFlagsSubpacket            signatureSubpacketType = 27
-)
-
-// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
-func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err os.Error) {
-	// RFC 4880, section 5.2.3.1
-	var (
-		length     uint32
-		packetType signatureSubpacketType
-		isCritical bool
-	)
-	switch {
-	case subpacket[0] < 192:
-		length = uint32(subpacket[0])
-		subpacket = subpacket[1:]
-	case subpacket[0] < 255:
-		if len(subpacket) < 2 {
-			goto Truncated
-		}
-		length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
-		subpacket = subpacket[2:]
-	default:
-		if len(subpacket) < 5 {
-			goto Truncated
-		}
-		length = uint32(subpacket[1])<<24 |
-			uint32(subpacket[2])<<16 |
-			uint32(subpacket[3])<<8 |
-			uint32(subpacket[4])
-		subpacket = subpacket[5:]
-	}
-	if length > uint32(len(subpacket)) {
-		goto Truncated
-	}
-	rest = subpacket[length:]
-	subpacket = subpacket[:length]
-	if len(subpacket) == 0 {
-		err = error.StructuralError("zero length signature subpacket")
-		return
-	}
-	packetType = signatureSubpacketType(subpacket[0] & 0x7f)
-	isCritical = subpacket[0]&0x80 == 0x80
-	subpacket = subpacket[1:]
-	sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
-	switch packetType {
-	case creationTimeSubpacket:
-		if !isHashed {
-			err = error.StructuralError("signature creation time in non-hashed area")
-			return
-		}
-		if len(subpacket) != 4 {
-			err = error.StructuralError("signature creation time not four bytes")
-			return
-		}
-		sig.CreationTime = binary.BigEndian.Uint32(subpacket)
-	case signatureExpirationSubpacket:
-		// Signature expiration time, section 5.2.3.10
-		if !isHashed {
-			return
-		}
-		if len(subpacket) != 4 {
-			err = error.StructuralError("expiration subpacket with bad length")
-			return
-		}
-		sig.SigLifetimeSecs = new(uint32)
-		*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
-	case keyExpirySubpacket:
-		// Key expiration time, section 5.2.3.6
-		if !isHashed {
-			return
-		}
-		if len(subpacket) != 4 {
-			err = error.StructuralError("key expiration subpacket with bad length")
-			return
-		}
-		sig.KeyLifetimeSecs = new(uint32)
-		*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
-	case prefSymmetricAlgosSubpacket:
-		// Preferred symmetric algorithms, section 5.2.3.7
-		if !isHashed {
-			return
-		}
-		sig.PreferredSymmetric = make([]byte, len(subpacket))
-		copy(sig.PreferredSymmetric, subpacket)
-	case issuerSubpacket:
-		// Issuer, section 5.2.3.5
-		if len(subpacket) != 8 {
-			err = error.StructuralError("issuer subpacket with bad length")
-			return
-		}
-		sig.IssuerKeyId = new(uint64)
-		*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
-	case prefHashAlgosSubpacket:
-		// Preferred hash algorithms, section 5.2.3.8
-		if !isHashed {
-			return
-		}
-		sig.PreferredHash = make([]byte, len(subpacket))
-		copy(sig.PreferredHash, subpacket)
-	case prefCompressionSubpacket:
-		// Preferred compression algorithms, section 5.2.3.9
-		if !isHashed {
-			return
-		}
-		sig.PreferredCompression = make([]byte, len(subpacket))
-		copy(sig.PreferredCompression, subpacket)
-	case primaryUserIdSubpacket:
-		// Primary User ID, section 5.2.3.19
-		if !isHashed {
-			return
-		}
-		if len(subpacket) != 1 {
-			err = error.StructuralError("primary user id subpacket with bad length")
-			return
-		}
-		sig.IsPrimaryId = new(bool)
-		if subpacket[0] > 0 {
-			*sig.IsPrimaryId = true
-		}
-	case keyFlagsSubpacket:
-		// Key flags, section 5.2.3.21
-		if !isHashed {
-			return
-		}
-		if len(subpacket) == 0 {
-			err = error.StructuralError("empty key flags subpacket")
-			return
-		}
-		sig.FlagsValid = true
-		if subpacket[0]&1 != 0 {
-			sig.FlagCertify = true
-		}
-		if subpacket[0]&2 != 0 {
-			sig.FlagSign = true
-		}
-		if subpacket[0]&4 != 0 {
-			sig.FlagEncryptCommunications = true
-		}
-		if subpacket[0]&8 != 0 {
-			sig.FlagEncryptStorage = true
-		}
-
-	default:
-		if isCritical {
-			err = error.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
-			return
-		}
-	}
-	return
-
-Truncated:
-	err = error.StructuralError("signature subpacket truncated")
-	return
-}
-
-// subpacketLengthLength returns the length, in bytes, of an encoded length value.
-func subpacketLengthLength(length int) int {
-	if length < 192 {
-		return 1
-	}
-	if length < 16320 {
-		return 2
-	}
-	return 5
-}
-
-// serializeSubpacketLength marshals the given length into to.
-func serializeSubpacketLength(to []byte, length int) int {
-	if length < 192 {
-		to[0] = byte(length)
-		return 1
-	}
-	if length < 16320 {
-		length -= 192
-		to[0] = byte(length >> 8)
-		to[1] = byte(length)
-		return 2
-	}
-	to[0] = 255
-	to[1] = byte(length >> 24)
-	to[2] = byte(length >> 16)
-	to[3] = byte(length >> 8)
-	to[4] = byte(length)
-	return 5
-}
-
-// subpacketsLength returns the serialized length, in bytes, of the given
-// subpackets.
-func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
-	for _, subpacket := range subpackets {
-		if subpacket.hashed == hashed {
-			length += subpacketLengthLength(len(subpacket.contents) + 1)
-			length += 1 // type byte
-			length += len(subpacket.contents)
-		}
-	}
-	return
-}
-
-// serializeSubpackets marshals the given subpackets into to.
-func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
-	for _, subpacket := range subpackets {
-		if subpacket.hashed == hashed {
-			n := serializeSubpacketLength(to, len(subpacket.contents)+1)
-			to[n] = byte(subpacket.subpacketType)
-			to = to[1+n:]
-			n = copy(to, subpacket.contents)
-			to = to[n:]
-		}
-	}
-	return
-}
-
-// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
-func (sig *Signature) buildHashSuffix() (err os.Error) {
-	hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
-
-	var ok bool
-	l := 6 + hashedSubpacketsLen
-	sig.HashSuffix = make([]byte, l+6)
-	sig.HashSuffix[0] = 4
-	sig.HashSuffix[1] = uint8(sig.SigType)
-	sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
-	sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
-	if !ok {
-		sig.HashSuffix = nil
-		return error.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
-	}
-	sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
-	sig.HashSuffix[5] = byte(hashedSubpacketsLen)
-	serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
-	trailer := sig.HashSuffix[l:]
-	trailer[0] = 4
-	trailer[1] = 0xff
-	trailer[2] = byte(l >> 24)
-	trailer[3] = byte(l >> 16)
-	trailer[4] = byte(l >> 8)
-	trailer[5] = byte(l)
-	return
-}
-
-func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err os.Error) {
-	err = sig.buildHashSuffix()
-	if err != nil {
-		return
-	}
-
-	h.Write(sig.HashSuffix)
-	digest = h.Sum()
-	copy(sig.HashTag[:], digest)
-	return
-}
-
-// Sign signs a message with a private key. The hash, h, must contain
-// the hash of the message to be signed and will be mutated by this function.
-// On success, the signature is stored in sig. Call Serialize to write it out.
-func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err os.Error) {
-	sig.outSubpackets = sig.buildSubpackets()
-	digest, err := sig.signPrepareHash(h)
-	if err != nil {
-		return
-	}
-
-	switch priv.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-		sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
-		sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
-	case PubKeyAlgoDSA:
-		r, s, err := dsa.Sign(rand.Reader, priv.PrivateKey.(*dsa.PrivateKey), digest)
-		if err == nil {
-			sig.DSASigR.bytes = r.Bytes()
-			sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
-			sig.DSASigS.bytes = s.Bytes()
-			sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
-		}
-	default:
-		err = error.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
-	}
-
-	return
-}
-
-// SignUserId computes a signature from priv, asserting that pub is a valid
-// key for the identity id.  On success, the signature is stored in sig. Call
-// Serialize to write it out.
-func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey) os.Error {
-	h, err := userIdSignatureHash(id, pub, sig)
-	if err != nil {
-		return nil
-	}
-	return sig.Sign(h, priv)
-}
-
-// SignKey computes a signature from priv, asserting that pub is a subkey.  On
-// success, the signature is stored in sig. Call Serialize to write it out.
-func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey) os.Error {
-	h, err := keySignatureHash(&priv.PublicKey, pub, sig)
-	if err != nil {
-		return err
-	}
-	return sig.Sign(h, priv)
-}
-
-// Serialize marshals sig to w. SignRSA or SignDSA must have been called first.
-func (sig *Signature) Serialize(w io.Writer) (err os.Error) {
-	if len(sig.outSubpackets) == 0 {
-		sig.outSubpackets = sig.rawSubpackets
-	}
-	if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
-		return error.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize")
-	}
-
-	sigLength := 0
-	switch sig.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-		sigLength = 2 + len(sig.RSASignature.bytes)
-	case PubKeyAlgoDSA:
-		sigLength = 2 + len(sig.DSASigR.bytes)
-		sigLength += 2 + len(sig.DSASigS.bytes)
-	default:
-		panic("impossible")
-	}
-
-	unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
-	length := len(sig.HashSuffix) - 6 /* trailer not included */ +
-		2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
-		2 /* hash tag */ + sigLength
-	err = serializeHeader(w, packetTypeSignature, length)
-	if err != nil {
-		return
-	}
-
-	_, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
-	if err != nil {
-		return
-	}
-
-	unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
-	unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
-	unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
-	serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
-
-	_, err = w.Write(unhashedSubpackets)
-	if err != nil {
-		return
-	}
-	_, err = w.Write(sig.HashTag[:])
-	if err != nil {
-		return
-	}
-
-	switch sig.PubKeyAlgo {
-	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-		err = writeMPIs(w, sig.RSASignature)
-	case PubKeyAlgoDSA:
-		err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
-	default:
-		panic("impossible")
-	}
-	return
-}
-
-// outputSubpacket represents a subpacket to be marshaled.
-type outputSubpacket struct {
-	hashed        bool // true if this subpacket is in the hashed area.
-	subpacketType signatureSubpacketType
-	isCritical    bool
-	contents      []byte
-}
-
-func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
-	creationTime := make([]byte, 4)
-	creationTime[0] = byte(sig.CreationTime >> 24)
-	creationTime[1] = byte(sig.CreationTime >> 16)
-	creationTime[2] = byte(sig.CreationTime >> 8)
-	creationTime[3] = byte(sig.CreationTime)
-	subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
-
-	if sig.IssuerKeyId != nil {
-		keyId := make([]byte, 8)
-		binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
-		subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
-	}
-
-	return
-}
diff --git a/src/pkg/crypto/openpgp/packet/signature_test.go b/src/pkg/crypto/openpgp/packet/signature_test.go
deleted file mode 100644
index c1bbde8..0000000
--- a/src/pkg/crypto/openpgp/packet/signature_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"bytes"
-	"crypto"
-	"encoding/hex"
-	"testing"
-)
-
-func TestSignatureRead(t *testing.T) {
-	packet, err := Read(readerFromHex(signatureDataHex))
-	if err != nil {
-		t.Error(err)
-		return
-	}
-	sig, ok := packet.(*Signature)
-	if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 {
-		t.Errorf("failed to parse, got: %#v", packet)
-	}
-}
-
-func TestSignatureReserialize(t *testing.T) {
-	packet, _ := Read(readerFromHex(signatureDataHex))
-	sig := packet.(*Signature)
-	out := new(bytes.Buffer)
-	err := sig.Serialize(out)
-	if err != nil {
-		t.Errorf("error reserializing: %s", err)
-		return
-	}
-
-	expected, _ := hex.DecodeString(signatureDataHex)
-	if !bytes.Equal(expected, out.Bytes()) {
-		t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
-	}
-}
-
-const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"
diff --git a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go
deleted file mode 100644
index ad4f1d6..0000000
--- a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"bytes"
-	"crypto/cipher"
-	"crypto/openpgp/error"
-	"crypto/openpgp/s2k"
-	"io"
-	"os"
-	"strconv"
-)
-
-// This is the largest session key that we'll support. Since no 512-bit cipher
-// has even been seriously used, this is comfortably large.
-const maxSessionKeySizeInBytes = 64
-
-// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
-// 4880, section 5.3.
-type SymmetricKeyEncrypted struct {
-	CipherFunc   CipherFunction
-	Encrypted    bool
-	Key          []byte // Empty unless Encrypted is false.
-	s2k          func(out, in []byte)
-	encryptedKey []byte
-}
-
-const symmetricKeyEncryptedVersion = 4
-
-func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err os.Error) {
-	// RFC 4880, section 5.3.
-	var buf [2]byte
-	_, err = readFull(r, buf[:])
-	if err != nil {
-		return
-	}
-	if buf[0] != symmetricKeyEncryptedVersion {
-		return error.UnsupportedError("SymmetricKeyEncrypted version")
-	}
-	ske.CipherFunc = CipherFunction(buf[1])
-
-	if ske.CipherFunc.KeySize() == 0 {
-		return error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
-	}
-
-	ske.s2k, err = s2k.Parse(r)
-	if err != nil {
-		return
-	}
-
-	encryptedKey := make([]byte, maxSessionKeySizeInBytes)
-	// The session key may follow. We just have to try and read to find
-	// out. If it exists then we limit it to maxSessionKeySizeInBytes.
-	n, err := readFull(r, encryptedKey)
-	if err != nil && err != io.ErrUnexpectedEOF {
-		return
-	}
-	err = nil
-	if n != 0 {
-		if n == maxSessionKeySizeInBytes {
-			return error.UnsupportedError("oversized encrypted session key")
-		}
-		ske.encryptedKey = encryptedKey[:n]
-	}
-
-	ske.Encrypted = true
-
-	return
-}
-
-// Decrypt attempts to decrypt an encrypted session key. If it returns nil,
-// ske.Key will contain the session key.
-func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) os.Error {
-	if !ske.Encrypted {
-		return nil
-	}
-
-	key := make([]byte, ske.CipherFunc.KeySize())
-	ske.s2k(key, passphrase)
-
-	if len(ske.encryptedKey) == 0 {
-		ske.Key = key
-	} else {
-		// the IV is all zeros
-		iv := make([]byte, ske.CipherFunc.blockSize())
-		c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
-		c.XORKeyStream(ske.encryptedKey, ske.encryptedKey)
-		ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
-		if ske.CipherFunc.blockSize() == 0 {
-			return error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
-		}
-		ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
-		ske.Key = ske.encryptedKey[1:]
-		if len(ske.Key)%ske.CipherFunc.blockSize() != 0 {
-			ske.Key = nil
-			return error.StructuralError("length of decrypted key not a multiple of block size")
-		}
-	}
-
-	ske.Encrypted = false
-	return nil
-}
-
-// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
-// packet contains a random session key, encrypted by a key derived from the
-// given passphrase. The session key is returned and must be passed to
-// SerializeSymmetricallyEncrypted.
-func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []byte, cipherFunc CipherFunction) (key []byte, err os.Error) {
-	keySize := cipherFunc.KeySize()
-	if keySize == 0 {
-		return nil, error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
-	}
-
-	s2kBuf := new(bytes.Buffer)
-	keyEncryptingKey := make([]byte, keySize)
-	// s2k.Serialize salts and stretches the passphrase, and writes the
-	// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
-	err = s2k.Serialize(s2kBuf, keyEncryptingKey, rand, passphrase)
-	if err != nil {
-		return
-	}
-	s2kBytes := s2kBuf.Bytes()
-
-	packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
-	err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
-	if err != nil {
-		return
-	}
-
-	var buf [2]byte
-	buf[0] = symmetricKeyEncryptedVersion
-	buf[1] = byte(cipherFunc)
-	_, err = w.Write(buf[:])
-	if err != nil {
-		return
-	}
-	_, err = w.Write(s2kBytes)
-	if err != nil {
-		return
-	}
-
-	sessionKey := make([]byte, keySize)
-	_, err = io.ReadFull(rand, sessionKey)
-	if err != nil {
-		return
-	}
-	iv := make([]byte, cipherFunc.blockSize())
-	c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
-	encryptedCipherAndKey := make([]byte, keySize+1)
-	c.XORKeyStream(encryptedCipherAndKey, buf[1:])
-	c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
-	_, err = w.Write(encryptedCipherAndKey)
-	if err != nil {
-		return
-	}
-
-	key = sessionKey
-	return
-}
diff --git a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go
deleted file mode 100644
index 823ec40..0000000
--- a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"bytes"
-	"crypto/rand"
-	"encoding/hex"
-	"io/ioutil"
-	"os"
-	"testing"
-)
-
-func TestSymmetricKeyEncrypted(t *testing.T) {
-	buf := readerFromHex(symmetricallyEncryptedHex)
-	packet, err := Read(buf)
-	if err != nil {
-		t.Errorf("failed to read SymmetricKeyEncrypted: %s", err)
-		return
-	}
-	ske, ok := packet.(*SymmetricKeyEncrypted)
-	if !ok {
-		t.Error("didn't find SymmetricKeyEncrypted packet")
-		return
-	}
-	err = ske.Decrypt([]byte("password"))
-	if err != nil {
-		t.Error(err)
-		return
-	}
-
-	packet, err = Read(buf)
-	if err != nil {
-		t.Errorf("failed to read SymmetricallyEncrypted: %s", err)
-		return
-	}
-	se, ok := packet.(*SymmetricallyEncrypted)
-	if !ok {
-		t.Error("didn't find SymmetricallyEncrypted packet")
-		return
-	}
-	r, err := se.Decrypt(ske.CipherFunc, ske.Key)
-	if err != nil {
-		t.Error(err)
-		return
-	}
-
-	contents, err := ioutil.ReadAll(r)
-	if err != nil && err != os.EOF {
-		t.Error(err)
-		return
-	}
-
-	expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex)
-	if !bytes.Equal(expectedContents, contents) {
-		t.Errorf("bad contents got:%x want:%x", contents, expectedContents)
-	}
-}
-
-const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf"
-const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"
-
-func TestSerializeSymmetricKeyEncrypted(t *testing.T) {
-	buf := bytes.NewBuffer(nil)
-	passphrase := []byte("testing")
-	cipherFunc := CipherAES128
-
-	key, err := SerializeSymmetricKeyEncrypted(buf, rand.Reader, passphrase, cipherFunc)
-	if err != nil {
-		t.Errorf("failed to serialize: %s", err)
-		return
-	}
-
-	p, err := Read(buf)
-	if err != nil {
-		t.Errorf("failed to reparse: %s", err)
-		return
-	}
-	ske, ok := p.(*SymmetricKeyEncrypted)
-	if !ok {
-		t.Errorf("parsed a different packet type: %#v", p)
-		return
-	}
-
-	if !ske.Encrypted {
-		t.Errorf("SKE not encrypted but should be")
-	}
-	if ske.CipherFunc != cipherFunc {
-		t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, cipherFunc)
-	}
-	err = ske.Decrypt(passphrase)
-	if err != nil {
-		t.Errorf("failed to decrypt reparsed SKE: %s", err)
-		return
-	}
-	if !bytes.Equal(key, ske.Key) {
-		t.Errorf("keys don't match after Decrpyt: %x (original) vs %x (parsed)", key, ske.Key)
-	}
-}
diff --git a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go b/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go
deleted file mode 100644
index e33c9f3..0000000
--- a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"crypto/cipher"
-	"crypto/openpgp/error"
-	"crypto/rand"
-	"crypto/sha1"
-	"crypto/subtle"
-	"hash"
-	"io"
-	"os"
-	"strconv"
-)
-
-// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
-// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
-// sections 5.7 and 5.13.
-type SymmetricallyEncrypted struct {
-	MDC      bool // true iff this is a type 18 packet and thus has an embedded MAC.
-	contents io.Reader
-	prefix   []byte
-}
-
-const symmetricallyEncryptedVersion = 1
-
-func (se *SymmetricallyEncrypted) parse(r io.Reader) os.Error {
-	if se.MDC {
-		// See RFC 4880, section 5.13.
-		var buf [1]byte
-		_, err := readFull(r, buf[:])
-		if err != nil {
-			return err
-		}
-		if buf[0] != symmetricallyEncryptedVersion {
-			return error.UnsupportedError("unknown SymmetricallyEncrypted version")
-		}
-	}
-	se.contents = r
-	return nil
-}
-
-// Decrypt returns a ReadCloser, from which the decrypted contents of the
-// packet can be read. An incorrect key can, with high probability, be detected
-// immediately and this will result in a KeyIncorrect error being returned.
-func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, os.Error) {
-	keySize := c.KeySize()
-	if keySize == 0 {
-		return nil, error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
-	}
-	if len(key) != keySize {
-		return nil, error.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
-	}
-
-	if se.prefix == nil {
-		se.prefix = make([]byte, c.blockSize()+2)
-		_, err := readFull(se.contents, se.prefix)
-		if err != nil {
-			return nil, err
-		}
-	} else if len(se.prefix) != c.blockSize()+2 {
-		return nil, error.InvalidArgumentError("can't try ciphers with different block lengths")
-	}
-
-	ocfbResync := cipher.OCFBResync
-	if se.MDC {
-		// MDC packets use a different form of OCFB mode.
-		ocfbResync = cipher.OCFBNoResync
-	}
-
-	s := cipher.NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
-	if s == nil {
-		return nil, error.KeyIncorrectError
-	}
-
-	plaintext := cipher.StreamReader{S: s, R: se.contents}
-
-	if se.MDC {
-		// MDC packets have an embedded hash that we need to check.
-		h := sha1.New()
-		h.Write(se.prefix)
-		return &seMDCReader{in: plaintext, h: h}, nil
-	}
-
-	// Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
-	return seReader{plaintext}, nil
-}
-
-// seReader wraps an io.Reader with a no-op Close method.
-type seReader struct {
-	in io.Reader
-}
-
-func (ser seReader) Read(buf []byte) (int, os.Error) {
-	return ser.in.Read(buf)
-}
-
-func (ser seReader) Close() os.Error {
-	return nil
-}
-
-const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
-
-// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
-// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
-// MDC packet containing a hash of the previous contents which is checked
-// against the running hash. See RFC 4880, section 5.13.
-type seMDCReader struct {
-	in          io.Reader
-	h           hash.Hash
-	trailer     [mdcTrailerSize]byte
-	scratch     [mdcTrailerSize]byte
-	trailerUsed int
-	error       bool
-	eof         bool
-}
-
-func (ser *seMDCReader) Read(buf []byte) (n int, err os.Error) {
-	if ser.error {
-		err = io.ErrUnexpectedEOF
-		return
-	}
-	if ser.eof {
-		err = os.EOF
-		return
-	}
-
-	// If we haven't yet filled the trailer buffer then we must do that
-	// first.
-	for ser.trailerUsed < mdcTrailerSize {
-		n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
-		ser.trailerUsed += n
-		if err == os.EOF {
-			if ser.trailerUsed != mdcTrailerSize {
-				n = 0
-				err = io.ErrUnexpectedEOF
-				ser.error = true
-				return
-			}
-			ser.eof = true
-			n = 0
-			return
-		}
-
-		if err != nil {
-			n = 0
-			return
-		}
-	}
-
-	// If it's a short read then we read into a temporary buffer and shift
-	// the data into the caller's buffer.
-	if len(buf) <= mdcTrailerSize {
-		n, err = readFull(ser.in, ser.scratch[:len(buf)])
-		copy(buf, ser.trailer[:n])
-		ser.h.Write(buf[:n])
-		copy(ser.trailer[:], ser.trailer[n:])
-		copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
-		if n < len(buf) {
-			ser.eof = true
-			err = os.EOF
-		}
-		return
-	}
-
-	n, err = ser.in.Read(buf[mdcTrailerSize:])
-	copy(buf, ser.trailer[:])
-	ser.h.Write(buf[:n])
-	copy(ser.trailer[:], buf[n:])
-
-	if err == os.EOF {
-		ser.eof = true
-	}
-	return
-}
-
-// This is a new-format packet tag byte for a type 19 (MDC) packet.
-const mdcPacketTagByte = byte(0x80) | 0x40 | 19
-
-func (ser *seMDCReader) Close() os.Error {
-	if ser.error {
-		return error.SignatureError("error during reading")
-	}
-
-	for !ser.eof {
-		// We haven't seen EOF so we need to read to the end
-		var buf [1024]byte
-		_, err := ser.Read(buf[:])
-		if err == os.EOF {
-			break
-		}
-		if err != nil {
-			return error.SignatureError("error during reading")
-		}
-	}
-
-	if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
-		return error.SignatureError("MDC packet not found")
-	}
-	ser.h.Write(ser.trailer[:2])
-
-	final := ser.h.Sum()
-	if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
-		return error.SignatureError("hash mismatch")
-	}
-	return nil
-}
-
-// An seMDCWriter writes through to an io.WriteCloser while maintains a running
-// hash of the data written. On close, it emits an MDC packet containing the
-// running hash.
-type seMDCWriter struct {
-	w io.WriteCloser
-	h hash.Hash
-}
-
-func (w *seMDCWriter) Write(buf []byte) (n int, err os.Error) {
-	w.h.Write(buf)
-	return w.w.Write(buf)
-}
-
-func (w *seMDCWriter) Close() (err os.Error) {
-	var buf [mdcTrailerSize]byte
-
-	buf[0] = mdcPacketTagByte
-	buf[1] = sha1.Size
-	w.h.Write(buf[:2])
-	digest := w.h.Sum()
-	copy(buf[2:], digest)
-
-	_, err = w.w.Write(buf[:])
-	if err != nil {
-		return
-	}
-	return w.w.Close()
-}
-
-// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
-type noOpCloser struct {
-	w io.Writer
-}
-
-func (c noOpCloser) Write(data []byte) (n int, err os.Error) {
-	return c.w.Write(data)
-}
-
-func (c noOpCloser) Close() os.Error {
-	return nil
-}
-
-// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
-// to w and returns a WriteCloser to which the to-be-encrypted packets can be
-// written.
-func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte) (contents io.WriteCloser, err os.Error) {
-	if c.KeySize() != len(key) {
-		return nil, error.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
-	}
-	writeCloser := noOpCloser{w}
-	ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
-	if err != nil {
-		return
-	}
-
-	_, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion})
-	if err != nil {
-		return
-	}
-
-	block := c.new(key)
-	blockSize := block.BlockSize()
-	iv := make([]byte, blockSize)
-	_, err = rand.Reader.Read(iv)
-	if err != nil {
-		return
-	}
-	s, prefix := cipher.NewOCFBEncrypter(block, iv, cipher.OCFBNoResync)
-	_, err = ciphertext.Write(prefix)
-	if err != nil {
-		return
-	}
-	plaintext := cipher.StreamWriter{S: s, W: ciphertext}
-
-	h := sha1.New()
-	h.Write(iv)
-	h.Write(iv[blockSize-2:])
-	contents = &seMDCWriter{w: plaintext, h: h}
-	return
-}
diff --git a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go b/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go
deleted file mode 100644
index 1054fc2..0000000
--- a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"bytes"
-	"crypto/openpgp/error"
-	"crypto/sha1"
-	"encoding/hex"
-	"io"
-	"io/ioutil"
-	"os"
-	"testing"
-)
-
-// TestReader wraps a []byte and returns reads of a specific length.
-type testReader struct {
-	data   []byte
-	stride int
-}
-
-func (t *testReader) Read(buf []byte) (n int, err os.Error) {
-	n = t.stride
-	if n > len(t.data) {
-		n = len(t.data)
-	}
-	if n > len(buf) {
-		n = len(buf)
-	}
-	copy(buf, t.data)
-	t.data = t.data[n:]
-	if len(t.data) == 0 {
-		err = os.EOF
-	}
-	return
-}
-
-func testMDCReader(t *testing.T) {
-	mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex)
-
-	for stride := 1; stride < len(mdcPlaintext)/2; stride++ {
-		r := &testReader{data: mdcPlaintext, stride: stride}
-		mdcReader := &seMDCReader{in: r, h: sha1.New()}
-		body, err := ioutil.ReadAll(mdcReader)
-		if err != nil {
-			t.Errorf("stride: %d, error: %s", stride, err)
-			continue
-		}
-		if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) {
-			t.Errorf("stride: %d: bad contents %x", stride, body)
-			continue
-		}
-
-		err = mdcReader.Close()
-		if err != nil {
-			t.Errorf("stride: %d, error on Close: %s", stride, err)
-		}
-	}
-
-	mdcPlaintext[15] ^= 80
-
-	r := &testReader{data: mdcPlaintext, stride: 2}
-	mdcReader := &seMDCReader{in: r, h: sha1.New()}
-	_, err := ioutil.ReadAll(mdcReader)
-	if err != nil {
-		t.Errorf("corruption test, error: %s", err)
-		return
-	}
-	err = mdcReader.Close()
-	if err == nil {
-		t.Error("corruption: no error")
-	} else if _, ok := err.(*error.SignatureError); !ok {
-		t.Errorf("corruption: expected SignatureError, got: %s", err)
-	}
-}
-
-const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980"
-
-func TestSerialize(t *testing.T) {
-	buf := bytes.NewBuffer(nil)
-	c := CipherAES128
-	key := make([]byte, c.KeySize())
-
-	w, err := SerializeSymmetricallyEncrypted(buf, c, key)
-	if err != nil {
-		t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
-		return
-	}
-
-	contents := []byte("hello world\n")
-
-	w.Write(contents)
-	w.Close()
-
-	p, err := Read(buf)
-	if err != nil {
-		t.Errorf("error from Read: %s", err)
-		return
-	}
-
-	se, ok := p.(*SymmetricallyEncrypted)
-	if !ok {
-		t.Errorf("didn't read a *SymmetricallyEncrypted")
-		return
-	}
-
-	r, err := se.Decrypt(c, key)
-	if err != nil {
-		t.Errorf("error from Decrypt: %s", err)
-		return
-	}
-
-	contentsCopy := bytes.NewBuffer(nil)
-	_, err = io.Copy(contentsCopy, r)
-	if err != nil {
-		t.Errorf("error from io.Copy: %s", err)
-		return
-	}
-	if !bytes.Equal(contentsCopy.Bytes(), contents) {
-		t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents)
-	}
-}
diff --git a/src/pkg/crypto/openpgp/packet/userid.go b/src/pkg/crypto/openpgp/packet/userid.go
deleted file mode 100644
index 0580ba3..0000000
--- a/src/pkg/crypto/openpgp/packet/userid.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"io"
-	"io/ioutil"
-	"os"
-	"strings"
-)
-
-// UserId contains text that is intended to represent the name and email
-// address of the key holder. See RFC 4880, section 5.11. By convention, this
-// takes the form "Full Name (Comment) <email at example.com>"
-type UserId struct {
-	Id string // By convention, this takes the form "Full Name (Comment) <email at example.com>" which is split out in the fields below.
-
-	Name, Comment, Email string
-}
-
-func hasInvalidCharacters(s string) bool {
-	for _, c := range s {
-		switch c {
-		case '(', ')', '<', '>', 0:
-			return true
-		}
-	}
-	return false
-}
-
-// NewUserId returns a UserId or nil if any of the arguments contain invalid
-// characters. The invalid characters are '\x00', '(', ')', '<' and '>'
-func NewUserId(name, comment, email string) *UserId {
-	// RFC 4880 doesn't deal with the structure of userid strings; the
-	// name, comment and email form is just a convention. However, there's
-	// no convention about escaping the metacharacters and GPG just refuses
-	// to create user ids where, say, the name contains a '('. We mirror
-	// this behaviour.
-
-	if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
-		return nil
-	}
-
-	uid := new(UserId)
-	uid.Name, uid.Comment, uid.Email = name, comment, email
-	uid.Id = name
-	if len(comment) > 0 {
-		if len(uid.Id) > 0 {
-			uid.Id += " "
-		}
-		uid.Id += "("
-		uid.Id += comment
-		uid.Id += ")"
-	}
-	if len(email) > 0 {
-		if len(uid.Id) > 0 {
-			uid.Id += " "
-		}
-		uid.Id += "<"
-		uid.Id += email
-		uid.Id += ">"
-	}
-	return uid
-}
-
-func (uid *UserId) parse(r io.Reader) (err os.Error) {
-	// RFC 4880, section 5.11
-	b, err := ioutil.ReadAll(r)
-	if err != nil {
-		return
-	}
-	uid.Id = string(b)
-	uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
-	return
-}
-
-// Serialize marshals uid to w in the form of an OpenPGP packet, including
-// header.
-func (uid *UserId) Serialize(w io.Writer) os.Error {
-	err := serializeHeader(w, packetTypeUserId, len(uid.Id))
-	if err != nil {
-		return err
-	}
-	_, err = w.Write([]byte(uid.Id))
-	return err
-}
-
-// parseUserId extracts the name, comment and email from a user id string that
-// is formatted as "Full Name (Comment) <email at example.com>".
-func parseUserId(id string) (name, comment, email string) {
-	var n, c, e struct {
-		start, end int
-	}
-	var state int
-
-	for offset, rune := range id {
-		switch state {
-		case 0:
-			// Entering name
-			n.start = offset
-			state = 1
-			fallthrough
-		case 1:
-			// In name
-			if rune == '(' {
-				state = 2
-				n.end = offset
-			} else if rune == '<' {
-				state = 5
-				n.end = offset
-			}
-		case 2:
-			// Entering comment
-			c.start = offset
-			state = 3
-			fallthrough
-		case 3:
-			// In comment
-			if rune == ')' {
-				state = 4
-				c.end = offset
-			}
-		case 4:
-			// Between comment and email
-			if rune == '<' {
-				state = 5
-			}
-		case 5:
-			// Entering email
-			e.start = offset
-			state = 6
-			fallthrough
-		case 6:
-			// In email
-			if rune == '>' {
-				state = 7
-				e.end = offset
-			}
-		default:
-			// After email
-		}
-	}
-	switch state {
-	case 1:
-		// ended in the name
-		n.end = len(id)
-	case 3:
-		// ended in comment
-		c.end = len(id)
-	case 6:
-		// ended in email
-		e.end = len(id)
-	}
-
-	name = strings.TrimSpace(id[n.start:n.end])
-	comment = strings.TrimSpace(id[c.start:c.end])
-	email = strings.TrimSpace(id[e.start:e.end])
-	return
-}
diff --git a/src/pkg/crypto/openpgp/packet/userid_test.go b/src/pkg/crypto/openpgp/packet/userid_test.go
deleted file mode 100644
index 2968193..0000000
--- a/src/pkg/crypto/openpgp/packet/userid_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2011 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 packet
-
-import (
-	"testing"
-)
-
-var userIdTests = []struct {
-	id                   string
-	name, comment, email string
-}{
-	{"", "", "", ""},
-	{"John Smith", "John Smith", "", ""},
-	{"John Smith ()", "John Smith", "", ""},
-	{"John Smith () <>", "John Smith", "", ""},
-	{"(comment", "", "comment", ""},
-	{"(comment)", "", "comment", ""},
-	{"<email", "", "", "email"},
-	{"<email>   sdfk", "", "", "email"},
-	{"  John Smith  (  Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"},
-	{"  John Smith  < email > lksdfj", "John Smith", "", "email"},
-	{"(<foo", "", "<foo", ""},
-	{"René Descartes (العربي)", "René Descartes", "العربي", ""},
-}
-
-func TestParseUserId(t *testing.T) {
-	for i, test := range userIdTests {
-		name, comment, email := parseUserId(test.id)
-		if name != test.name {
-			t.Errorf("%d: name mismatch got:%s want:%s", i, name, test.name)
-		}
-		if comment != test.comment {
-			t.Errorf("%d: comment mismatch got:%s want:%s", i, comment, test.comment)
-		}
-		if email != test.email {
-			t.Errorf("%d: email mismatch got:%s want:%s", i, email, test.email)
-		}
-	}
-}
-
-var newUserIdTests = []struct {
-	name, comment, email, id string
-}{
-	{"foo", "", "", "foo"},
-	{"", "bar", "", "(bar)"},
-	{"", "", "baz", "<baz>"},
-	{"foo", "bar", "", "foo (bar)"},
-	{"foo", "", "baz", "foo <baz>"},
-	{"", "bar", "baz", "(bar) <baz>"},
-	{"foo", "bar", "baz", "foo (bar) <baz>"},
-}
-
-func TestNewUserId(t *testing.T) {
-	for i, test := range newUserIdTests {
-		uid := NewUserId(test.name, test.comment, test.email)
-		if uid == nil {
-			t.Errorf("#%d: returned nil", i)
-			continue
-		}
-		if uid.Id != test.id {
-			t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id)
-		}
-	}
-}
-
-var invalidNewUserIdTests = []struct {
-	name, comment, email string
-}{
-	{"foo(", "", ""},
-	{"foo<", "", ""},
-	{"", "bar)", ""},
-	{"", "bar<", ""},
-	{"", "", "baz>"},
-	{"", "", "baz)"},
-	{"", "", "baz\x00"},
-}
-
-func TestNewUserIdWithInvalidInput(t *testing.T) {
-	for i, test := range invalidNewUserIdTests {
-		if uid := NewUserId(test.name, test.comment, test.email); uid != nil {
-			t.Errorf("#%d: returned non-nil value: %#v", i, uid)
-		}
-	}
-}
diff --git a/src/pkg/crypto/openpgp/read.go b/src/pkg/crypto/openpgp/read.go
deleted file mode 100644
index d95f613..0000000
--- a/src/pkg/crypto/openpgp/read.go
+++ /dev/null
@@ -1,415 +0,0 @@
-// Copyright 2011 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 openpgp implements high level operations on OpenPGP messages.
-package openpgp
-
-import (
-	"crypto"
-	"crypto/openpgp/armor"
-	"crypto/openpgp/error"
-	"crypto/openpgp/packet"
-	_ "crypto/sha256"
-	"hash"
-	"io"
-	"os"
-	"strconv"
-)
-
-// SignatureType is the armor type for a PGP signature.
-var SignatureType = "PGP SIGNATURE"
-
-// readArmored reads an armored block with the given type.
-func readArmored(r io.Reader, expectedType string) (body io.Reader, err os.Error) {
-	block, err := armor.Decode(r)
-	if err != nil {
-		return
-	}
-
-	if block.Type != expectedType {
-		return nil, error.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
-	}
-
-	return block.Body, nil
-}
-
-// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
-// signed message.
-type MessageDetails struct {
-	IsEncrypted              bool                // true if the message was encrypted.
-	EncryptedToKeyIds        []uint64            // the list of recipient key ids.
-	IsSymmetricallyEncrypted bool                // true if a passphrase could have decrypted the message.
-	DecryptedWith            Key                 // the private key used to decrypt the message, if any.
-	IsSigned                 bool                // true if the message is signed.
-	SignedByKeyId            uint64              // the key id of the signer, if any.
-	SignedBy                 *Key                // the key of the signer, if available.
-	LiteralData              *packet.LiteralData // the metadata of the contents
-	UnverifiedBody           io.Reader           // the contents of the message.
-
-	// If IsSigned is true and SignedBy is non-zero then the signature will
-	// be verified as UnverifiedBody is read. The signature cannot be
-	// checked until the whole of UnverifiedBody is read so UnverifiedBody
-	// must be consumed until EOF before the data can trusted. Even if a
-	// message isn't signed (or the signer is unknown) the data may contain
-	// an authentication code that is only checked once UnverifiedBody has
-	// been consumed. Once EOF has been seen, the following fields are
-	// valid. (An authentication code failure is reported as a
-	// SignatureError error when reading from UnverifiedBody.)
-	SignatureError os.Error          // nil if the signature is good.
-	Signature      *packet.Signature // the signature packet itself.
-
-	decrypted io.ReadCloser
-}
-
-// A PromptFunction is used as a callback by functions that may need to decrypt
-// a private key, or prompt for a passphrase. It is called with a list of
-// acceptable, encrypted private keys and a boolean that indicates whether a
-// passphrase is usable. It should either decrypt a private key or return a
-// passphrase to try. If the decrypted private key or given passphrase isn't
-// correct, the function will be called again, forever. Any error returned will
-// be passed up.
-type PromptFunction func(keys []Key, symmetric bool) ([]byte, os.Error)
-
-// A keyEnvelopePair is used to store a private key with the envelope that
-// contains a symmetric key, encrypted with that key.
-type keyEnvelopePair struct {
-	key          Key
-	encryptedKey *packet.EncryptedKey
-}
-
-// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
-// The given KeyRing should contain both public keys (for signature
-// verification) and, possibly encrypted, private keys for decrypting.
-func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction) (md *MessageDetails, err os.Error) {
-	var p packet.Packet
-
-	var symKeys []*packet.SymmetricKeyEncrypted
-	var pubKeys []keyEnvelopePair
-	var se *packet.SymmetricallyEncrypted
-
-	packets := packet.NewReader(r)
-	md = new(MessageDetails)
-	md.IsEncrypted = true
-
-	// The message, if encrypted, starts with a number of packets
-	// containing an encrypted decryption key. The decryption key is either
-	// encrypted to a public key, or with a passphrase. This loop
-	// collects these packets.
-ParsePackets:
-	for {
-		p, err = packets.Next()
-		if err != nil {
-			return nil, err
-		}
-		switch p := p.(type) {
-		case *packet.SymmetricKeyEncrypted:
-			// This packet contains the decryption key encrypted with a passphrase.
-			md.IsSymmetricallyEncrypted = true
-			symKeys = append(symKeys, p)
-		case *packet.EncryptedKey:
-			// This packet contains the decryption key encrypted to a public key.
-			md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
-			switch p.Algo {
-			case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
-				break
-			default:
-				continue
-			}
-			var keys []Key
-			if p.KeyId == 0 {
-				keys = keyring.DecryptionKeys()
-			} else {
-				keys = keyring.KeysById(p.KeyId)
-			}
-			for _, k := range keys {
-				pubKeys = append(pubKeys, keyEnvelopePair{k, p})
-			}
-		case *packet.SymmetricallyEncrypted:
-			se = p
-			break ParsePackets
-		case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
-			// This message isn't encrypted.
-			if len(symKeys) != 0 || len(pubKeys) != 0 {
-				return nil, error.StructuralError("key material not followed by encrypted message")
-			}
-			packets.Unread(p)
-			return readSignedMessage(packets, nil, keyring)
-		}
-	}
-
-	var candidates []Key
-	var decrypted io.ReadCloser
-
-	// Now that we have the list of encrypted keys we need to decrypt at
-	// least one of them or, if we cannot, we need to call the prompt
-	// function so that it can decrypt a key or give us a passphrase.
-FindKey:
-	for {
-		// See if any of the keys already have a private key available
-		candidates = candidates[:0]
-		candidateFingerprints := make(map[string]bool)
-
-		for _, pk := range pubKeys {
-			if pk.key.PrivateKey == nil {
-				continue
-			}
-			if !pk.key.PrivateKey.Encrypted {
-				if len(pk.encryptedKey.Key) == 0 {
-					pk.encryptedKey.Decrypt(pk.key.PrivateKey)
-				}
-				if len(pk.encryptedKey.Key) == 0 {
-					continue
-				}
-				decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
-				if err != nil && err != error.KeyIncorrectError {
-					return nil, err
-				}
-				if decrypted != nil {
-					md.DecryptedWith = pk.key
-					break FindKey
-				}
-			} else {
-				fpr := string(pk.key.PublicKey.Fingerprint[:])
-				if v := candidateFingerprints[fpr]; v {
-					continue
-				}
-				candidates = append(candidates, pk.key)
-				candidateFingerprints[fpr] = true
-			}
-		}
-
-		if len(candidates) == 0 && len(symKeys) == 0 {
-			return nil, error.KeyIncorrectError
-		}
-
-		if prompt == nil {
-			return nil, error.KeyIncorrectError
-		}
-
-		passphrase, err := prompt(candidates, len(symKeys) != 0)
-		if err != nil {
-			return nil, err
-		}
-
-		// Try the symmetric passphrase first
-		if len(symKeys) != 0 && passphrase != nil {
-			for _, s := range symKeys {
-				err = s.Decrypt(passphrase)
-				if err == nil && !s.Encrypted {
-					decrypted, err = se.Decrypt(s.CipherFunc, s.Key)
-					if err != nil && err != error.KeyIncorrectError {
-						return nil, err
-					}
-					if decrypted != nil {
-						break FindKey
-					}
-				}
-
-			}
-		}
-	}
-
-	md.decrypted = decrypted
-	packets.Push(decrypted)
-	return readSignedMessage(packets, md, keyring)
-}
-
-// readSignedMessage reads a possibly signed message if mdin is non-zero then
-// that structure is updated and returned. Otherwise a fresh MessageDetails is
-// used.
-func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err os.Error) {
-	if mdin == nil {
-		mdin = new(MessageDetails)
-	}
-	md = mdin
-
-	var p packet.Packet
-	var h hash.Hash
-	var wrappedHash hash.Hash
-FindLiteralData:
-	for {
-		p, err = packets.Next()
-		if err != nil {
-			return nil, err
-		}
-		switch p := p.(type) {
-		case *packet.Compressed:
-			packets.Push(p.Body)
-		case *packet.OnePassSignature:
-			if !p.IsLast {
-				return nil, error.UnsupportedError("nested signatures")
-			}
-
-			h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
-			if err != nil {
-				md = nil
-				return
-			}
-
-			md.IsSigned = true
-			md.SignedByKeyId = p.KeyId
-			keys := keyring.KeysById(p.KeyId)
-			for i, key := range keys {
-				if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
-					continue
-				}
-				md.SignedBy = &keys[i]
-				break
-			}
-		case *packet.LiteralData:
-			md.LiteralData = p
-			break FindLiteralData
-		}
-	}
-
-	if md.SignedBy != nil {
-		md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
-	} else if md.decrypted != nil {
-		md.UnverifiedBody = checkReader{md}
-	} else {
-		md.UnverifiedBody = md.LiteralData.Body
-	}
-
-	return md, nil
-}
-
-// hashForSignature returns a pair of hashes that can be used to verify a
-// signature. The signature may specify that the contents of the signed message
-// should be preprocessed (i.e. to normalize line endings). Thus this function
-// returns two hashes. The second should be used to hash the message itself and
-// performs any needed preprocessing.
-func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, os.Error) {
-	h := hashId.New()
-	if h == nil {
-		return nil, nil, error.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
-	}
-
-	switch sigType {
-	case packet.SigTypeBinary:
-		return h, h, nil
-	case packet.SigTypeText:
-		return h, NewCanonicalTextHash(h), nil
-	}
-
-	return nil, nil, error.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
-}
-
-// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
-// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
-// MDC checks.
-type checkReader struct {
-	md *MessageDetails
-}
-
-func (cr checkReader) Read(buf []byte) (n int, err os.Error) {
-	n, err = cr.md.LiteralData.Body.Read(buf)
-	if err == os.EOF {
-		mdcErr := cr.md.decrypted.Close()
-		if mdcErr != nil {
-			err = mdcErr
-		}
-	}
-	return
-}
-
-// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
-// the data as it is read. When it sees an EOF from the underlying io.Reader
-// it parses and checks a trailing Signature packet and triggers any MDC checks.
-type signatureCheckReader struct {
-	packets        *packet.Reader
-	h, wrappedHash hash.Hash
-	md             *MessageDetails
-}
-
-func (scr *signatureCheckReader) Read(buf []byte) (n int, err os.Error) {
-	n, err = scr.md.LiteralData.Body.Read(buf)
-	scr.wrappedHash.Write(buf[:n])
-	if err == os.EOF {
-		var p packet.Packet
-		p, scr.md.SignatureError = scr.packets.Next()
-		if scr.md.SignatureError != nil {
-			return
-		}
-
-		var ok bool
-		if scr.md.Signature, ok = p.(*packet.Signature); !ok {
-			scr.md.SignatureError = error.StructuralError("LiteralData not followed by Signature")
-			return
-		}
-
-		scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
-
-		// The SymmetricallyEncrypted packet, if any, might have an
-		// unsigned hash of its own. In order to check this we need to
-		// close that Reader.
-		if scr.md.decrypted != nil {
-			mdcErr := scr.md.decrypted.Close()
-			if mdcErr != nil {
-				err = mdcErr
-			}
-		}
-	}
-	return
-}
-
-// CheckDetachedSignature takes a signed file and a detached signature and
-// returns the signer if the signature is valid. If the signer isn't know,
-// UnknownIssuerError is returned.
-func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err os.Error) {
-	p, err := packet.Read(signature)
-	if err != nil {
-		return
-	}
-
-	sig, ok := p.(*packet.Signature)
-	if !ok {
-		return nil, error.StructuralError("non signature packet found")
-	}
-
-	if sig.IssuerKeyId == nil {
-		return nil, error.StructuralError("signature doesn't have an issuer")
-	}
-
-	keys := keyring.KeysById(*sig.IssuerKeyId)
-	if len(keys) == 0 {
-		return nil, error.UnknownIssuerError
-	}
-
-	h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
-	if err != nil {
-		return
-	}
-
-	_, err = io.Copy(wrappedHash, signed)
-	if err != nil && err != os.EOF {
-		return
-	}
-
-	for _, key := range keys {
-		if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
-			continue
-		}
-		err = key.PublicKey.VerifySignature(h, sig)
-		if err == nil {
-			return key.Entity, nil
-		}
-	}
-
-	if err != nil {
-		return
-	}
-
-	return nil, error.UnknownIssuerError
-}
-
-// CheckArmoredDetachedSignature performs the same actions as
-// CheckDetachedSignature but expects the signature to be armored.
-func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err os.Error) {
-	body, err := readArmored(signature, SignatureType)
-	if err != nil {
-		return
-	}
-
-	return CheckDetachedSignature(keyring, signed, body)
-}
diff --git a/src/pkg/crypto/openpgp/read_test.go b/src/pkg/crypto/openpgp/read_test.go
deleted file mode 100644
index 4dc290e..0000000
--- a/src/pkg/crypto/openpgp/read_test.go
+++ /dev/null
@@ -1,361 +0,0 @@
-// Copyright 2011 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 openpgp
-
-import (
-	"bytes"
-	"crypto/openpgp/error"
-	"encoding/hex"
-	"io"
-	"io/ioutil"
-	"os"
-	"testing"
-)
-
-func readerFromHex(s string) io.Reader {
-	data, err := hex.DecodeString(s)
-	if err != nil {
-		panic("readerFromHex: bad input")
-	}
-	return bytes.NewBuffer(data)
-}
-
-func TestReadKeyRing(t *testing.T) {
-	kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-	if err != nil {
-		t.Error(err)
-		return
-	}
-	if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B {
-		t.Errorf("bad keyring: %#v", kring)
-	}
-}
-
-func TestRereadKeyRing(t *testing.T) {
-	kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-	if err != nil {
-		t.Errorf("error in initial parse: %s", err)
-		return
-	}
-	out := new(bytes.Buffer)
-	err = kring[0].Serialize(out)
-	if err != nil {
-		t.Errorf("error in serialization: %s", err)
-		return
-	}
-	kring, err = ReadKeyRing(out)
-	if err != nil {
-		t.Errorf("error in second parse: %s", err)
-		return
-	}
-
-	if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB {
-		t.Errorf("bad keyring: %#v", kring)
-	}
-}
-
-func TestReadPrivateKeyRing(t *testing.T) {
-	kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-	if err != nil {
-		t.Error(err)
-		return
-	}
-	if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil {
-		t.Errorf("bad keyring: %#v", kring)
-	}
-}
-
-func TestReadDSAKey(t *testing.T) {
-	kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex))
-	if err != nil {
-		t.Error(err)
-		return
-	}
-	if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 {
-		t.Errorf("bad parse: %#v", kring)
-	}
-}
-
-func TestGetKeyById(t *testing.T) {
-	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-
-	keys := kring.KeysById(0xa34d7e18c20c31bb)
-	if len(keys) != 1 || keys[0].Entity != kring[0] {
-		t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
-	}
-
-	keys = kring.KeysById(0xfd94408d4543314f)
-	if len(keys) != 1 || keys[0].Entity != kring[0] {
-		t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
-	}
-}
-
-func checkSignedMessage(t *testing.T, signedHex, expected string) {
-	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-
-	md, err := ReadMessage(readerFromHex(signedHex), kring, nil)
-	if err != nil {
-		t.Error(err)
-		return
-	}
-
-	if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted {
-		t.Errorf("bad MessageDetails: %#v", md)
-	}
-
-	contents, err := ioutil.ReadAll(md.UnverifiedBody)
-	if err != nil {
-		t.Errorf("error reading UnverifiedBody: %s", err)
-	}
-	if string(contents) != expected {
-		t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
-	}
-	if md.SignatureError != nil || md.Signature == nil {
-		t.Errorf("failed to validate: %s", md.SignatureError)
-	}
-}
-
-func TestSignedMessage(t *testing.T) {
-	checkSignedMessage(t, signedMessageHex, signedInput)
-}
-
-func TestTextSignedMessage(t *testing.T) {
-	checkSignedMessage(t, signedTextMessageHex, signedTextInput)
-}
-
-var signedEncryptedMessageTests = []struct {
-	keyRingHex       string
-	messageHex       string
-	signedByKeyId    uint64
-	encryptedToKeyId uint64
-}{
-	{
-		testKeys1And2PrivateHex,
-		signedEncryptedMessageHex,
-		0xa34d7e18c20c31bb,
-		0x2a67d68660df41c7,
-	},
-	{
-		dsaElGamalTestKeysHex,
-		signedEncryptedMessage2Hex,
-		0x33af447ccd759b09,
-		0xcf6a7abcd43e3673,
-	},
-}
-
-func TestSignedEncryptedMessage(t *testing.T) {
-	for i, test := range signedEncryptedMessageTests {
-		expected := "Signed and encrypted message\n"
-		kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
-		prompt := func(keys []Key, symmetric bool) ([]byte, os.Error) {
-			if symmetric {
-				t.Errorf("prompt: message was marked as symmetrically encrypted")
-				return nil, error.KeyIncorrectError
-			}
-
-			if len(keys) == 0 {
-				t.Error("prompt: no keys requested")
-				return nil, error.KeyIncorrectError
-			}
-
-			err := keys[0].PrivateKey.Decrypt([]byte("passphrase"))
-			if err != nil {
-				t.Errorf("prompt: error decrypting key: %s", err)
-				return nil, error.KeyIncorrectError
-			}
-
-			return nil, nil
-		}
-
-		md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt)
-		if err != nil {
-			t.Errorf("#%d: error reading message: %s", i, err)
-			return
-		}
-
-		if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId {
-			t.Errorf("#%d: bad MessageDetails: %#v", i, md)
-		}
-
-		contents, err := ioutil.ReadAll(md.UnverifiedBody)
-		if err != nil {
-			t.Errorf("#%d: error reading UnverifiedBody: %s", i, err)
-		}
-		if string(contents) != expected {
-			t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected)
-		}
-
-		if md.SignatureError != nil || md.Signature == nil {
-			t.Errorf("#%d: failed to validate: %s", i, md.SignatureError)
-		}
-	}
-}
-
-func TestUnspecifiedRecipient(t *testing.T) {
-	expected := "Recipient unspecified\n"
-	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-
-	md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil)
-	if err != nil {
-		t.Errorf("error reading message: %s", err)
-		return
-	}
-
-	contents, err := ioutil.ReadAll(md.UnverifiedBody)
-	if err != nil {
-		t.Errorf("error reading UnverifiedBody: %s", err)
-	}
-	if string(contents) != expected {
-		t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
-	}
-}
-
-func TestSymmetricallyEncrypted(t *testing.T) {
-	expected := "Symmetrically encrypted.\n"
-
-	prompt := func(keys []Key, symmetric bool) ([]byte, os.Error) {
-		if len(keys) != 0 {
-			t.Errorf("prompt: len(keys) = %d (want 0)", len(keys))
-		}
-
-		if !symmetric {
-			t.Errorf("symmetric is not set")
-		}
-
-		return []byte("password"), nil
-	}
-
-	md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt)
-	if err != nil {
-		t.Errorf("ReadMessage: %s", err)
-		return
-	}
-
-	contents, err := ioutil.ReadAll(md.UnverifiedBody)
-	if err != nil {
-		t.Errorf("ReadAll: %s", err)
-	}
-
-	expectedCreationTime := uint32(1295992998)
-	if md.LiteralData.Time != expectedCreationTime {
-		t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime)
-	}
-
-	if string(contents) != expected {
-		t.Errorf("contents got: %s want: %s", string(contents), expected)
-	}
-}
-
-func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) {
-	signed := bytes.NewBufferString(sigInput)
-	signer, err := CheckDetachedSignature(kring, signed, signature)
-	if err != nil {
-		t.Errorf("%s: signature error: %s", tag, err)
-		return
-	}
-	if signer == nil {
-		t.Errorf("%s: signer is nil", tag)
-		return
-	}
-	if signer.PrimaryKey.KeyId != expectedSignerKeyId {
-		t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId)
-	}
-}
-
-func TestDetachedSignature(t *testing.T) {
-	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-	testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId)
-	testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId)
-}
-
-func TestDetachedSignatureDSA(t *testing.T) {
-	kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex))
-	testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
-}
-
-func TestReadingArmoredPrivateKey(t *testing.T) {
-	el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock))
-	if err != nil {
-		t.Error(err)
-	}
-	if len(el) != 1 {
-		t.Errorf("got %d entities, wanted 1\n", len(el))
-	}
-}
-
-func TestNoArmoredData(t *testing.T) {
-	_, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
-	if _, ok := err.(error.InvalidArgumentError); !ok {
-		t.Errorf("error was not an InvalidArgumentError: %s", err)
-	}
-}
-
-const testKey1KeyId = 0xA34D7E18C20C31BB
-const testKey3KeyId = 0x338934250CCC0360
-
-const signedInput = "Signed message\nline 2\nline 3\n"
-const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n"
-
-const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b"
-
-const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77"
-
-const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39"
-
-const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83"
-
-const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003"
-
-const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000"
-
-const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
-
-const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
-
-const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
-
-const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d"
-
-const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3"
-
-const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6"
-
-const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
-
-const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
-
-const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
-Version: GnuPG v1.4.10 (GNU/Linux)
-
-lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
-idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
-vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
-AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
-0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
-IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
-VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
-gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
-TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
-q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
-dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
-CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
-ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
-eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
-AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
-bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
-/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
-A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
-TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
-lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
-rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
-oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
-QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
-nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
-AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
-BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
-AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
-VrM0m72/jnpKo04=
-=zNCn
------END PGP PRIVATE KEY BLOCK-----`
diff --git a/src/pkg/crypto/openpgp/s2k/Makefile b/src/pkg/crypto/openpgp/s2k/Makefile
deleted file mode 100644
index 731d534..0000000
--- a/src/pkg/crypto/openpgp/s2k/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../../Make.inc
-
-TARG=crypto/openpgp/s2k
-GOFILES=\
-	s2k.go\
-
-include ../../../../Make.pkg
diff --git a/src/pkg/crypto/openpgp/s2k/s2k.go b/src/pkg/crypto/openpgp/s2k/s2k.go
deleted file mode 100644
index da926a7..0000000
--- a/src/pkg/crypto/openpgp/s2k/s2k.go
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2011 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 s2k implements the various OpenPGP string-to-key transforms as
-// specified in RFC 4800 section 3.7.1.
-package s2k
-
-import (
-	"crypto"
-	"crypto/openpgp/error"
-	"hash"
-	"io"
-	"os"
-	"strconv"
-)
-
-// Simple writes to out the result of computing the Simple S2K function (RFC
-// 4880, section 3.7.1.1) using the given hash and input passphrase.
-func Simple(out []byte, h hash.Hash, in []byte) {
-	Salted(out, h, in, nil)
-}
-
-var zero [1]byte
-
-// Salted writes to out the result of computing the Salted S2K function (RFC
-// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
-func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
-	done := 0
-
-	for i := 0; done < len(out); i++ {
-		h.Reset()
-		for j := 0; j < i; j++ {
-			h.Write(zero[:])
-		}
-		h.Write(salt)
-		h.Write(in)
-		n := copy(out[done:], h.Sum())
-		done += n
-	}
-}
-
-// Iterated writes to out the result of computing the Iterated and Salted S2K
-// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
-// salt and iteration count.
-func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
-	combined := make([]byte, len(in)+len(salt))
-	copy(combined, salt)
-	copy(combined[len(salt):], in)
-
-	if count < len(combined) {
-		count = len(combined)
-	}
-
-	done := 0
-	for i := 0; done < len(out); i++ {
-		h.Reset()
-		for j := 0; j < i; j++ {
-			h.Write(zero[:])
-		}
-		written := 0
-		for written < count {
-			if written+len(combined) > count {
-				todo := count - written
-				h.Write(combined[:todo])
-				written = count
-			} else {
-				h.Write(combined)
-				written += len(combined)
-			}
-		}
-		n := copy(out[done:], h.Sum())
-		done += n
-	}
-}
-
-// Parse reads a binary specification for a string-to-key transformation from r
-// and returns a function which performs that transform.
-func Parse(r io.Reader) (f func(out, in []byte), err os.Error) {
-	var buf [9]byte
-
-	_, err = io.ReadFull(r, buf[:2])
-	if err != nil {
-		return
-	}
-
-	hash, ok := HashIdToHash(buf[1])
-	if !ok {
-		return nil, error.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
-	}
-	h := hash.New()
-	if h == nil {
-		return nil, error.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
-	}
-
-	switch buf[0] {
-	case 1:
-		f := func(out, in []byte) {
-			Simple(out, h, in)
-		}
-		return f, nil
-	case 2:
-		_, err := io.ReadFull(r, buf[:8])
-		if err != nil {
-			return
-		}
-		f := func(out, in []byte) {
-			Salted(out, h, in, buf[:8])
-		}
-		return f, nil
-	case 3:
-		_, err := io.ReadFull(r, buf[:9])
-		if err != nil {
-			return
-		}
-		count := (16 + int(buf[8]&15)) << (uint32(buf[8]>>4) + 6)
-		f := func(out, in []byte) {
-			Iterated(out, h, in, buf[:8], count)
-		}
-		return f, nil
-	}
-
-	return nil, error.UnsupportedError("S2K function")
-}
-
-// Serialize salts and stretches the given passphrase and writes the resulting
-// key into key. It also serializes an S2K descriptor to w.
-func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte) os.Error {
-	var buf [11]byte
-	buf[0] = 3 /* iterated and salted */
-	buf[1], _ = HashToHashId(crypto.SHA1)
-	salt := buf[2:10]
-	if _, err := io.ReadFull(rand, salt); err != nil {
-		return err
-	}
-	const count = 65536 // this is the default in gpg
-	buf[10] = 96        // 65536 iterations
-	if _, err := w.Write(buf[:]); err != nil {
-		return err
-	}
-
-	Iterated(key, crypto.SHA1.New(), passphrase, salt, count)
-	return nil
-}
-
-// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
-// Go's crypto.Hash type. See RFC 4880, section 9.4.
-var hashToHashIdMapping = []struct {
-	id   byte
-	hash crypto.Hash
-}{
-	{1, crypto.MD5},
-	{2, crypto.SHA1},
-	{3, crypto.RIPEMD160},
-	{8, crypto.SHA256},
-	{9, crypto.SHA384},
-	{10, crypto.SHA512},
-	{11, crypto.SHA224},
-}
-
-// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
-// hash id.
-func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
-	for _, m := range hashToHashIdMapping {
-		if m.id == id {
-			return m.hash, true
-		}
-	}
-	return 0, false
-}
-
-// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
-func HashToHashId(h crypto.Hash) (id byte, ok bool) {
-	for _, m := range hashToHashIdMapping {
-		if m.hash == h {
-			return m.id, true
-		}
-	}
-	return 0, false
-}
diff --git a/src/pkg/crypto/openpgp/s2k/s2k_test.go b/src/pkg/crypto/openpgp/s2k/s2k_test.go
deleted file mode 100644
index ec4012c..0000000
--- a/src/pkg/crypto/openpgp/s2k/s2k_test.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2011 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 s2k
-
-import (
-	"bytes"
-	"crypto/sha1"
-	"crypto/rand"
-	"encoding/hex"
-	"testing"
-)
-
-var saltedTests = []struct {
-	in, out string
-}{
-	{"hello", "10295ac1"},
-	{"world", "ac587a5e"},
-	{"foo", "4dda8077"},
-	{"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
-	{"x", "f1d3f289"},
-	{"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
-}
-
-func TestSalted(t *testing.T) {
-	h := sha1.New()
-	salt := [4]byte{1, 2, 3, 4}
-
-	for i, test := range saltedTests {
-		expected, _ := hex.DecodeString(test.out)
-		out := make([]byte, len(expected))
-		Salted(out, h, []byte(test.in), salt[:])
-		if !bytes.Equal(expected, out) {
-			t.Errorf("#%d, got: %x want: %x", i, out, expected)
-		}
-	}
-}
-
-var iteratedTests = []struct {
-	in, out string
-}{
-	{"hello", "83126105"},
-	{"world", "6fa317f9"},
-	{"foo", "8fbc35b9"},
-	{"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
-	{"x", "5a684dfe"},
-	{"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
-}
-
-func TestIterated(t *testing.T) {
-	h := sha1.New()
-	salt := [4]byte{4, 3, 2, 1}
-
-	for i, test := range iteratedTests {
-		expected, _ := hex.DecodeString(test.out)
-		out := make([]byte, len(expected))
-		Iterated(out, h, []byte(test.in), salt[:], 31)
-		if !bytes.Equal(expected, out) {
-			t.Errorf("#%d, got: %x want: %x", i, out, expected)
-		}
-	}
-}
-
-var parseTests = []struct {
-	spec, in, out string
-}{
-	/* Simple with SHA1 */
-	{"0102", "hello", "aaf4c61d"},
-	/* Salted with SHA1 */
-	{"02020102030405060708", "hello", "f4f7d67e"},
-	/* Iterated with SHA1 */
-	{"03020102030405060708f1", "hello", "f2a57b7c"},
-}
-
-func TestParse(t *testing.T) {
-	for i, test := range parseTests {
-		spec, _ := hex.DecodeString(test.spec)
-		buf := bytes.NewBuffer(spec)
-		f, err := Parse(buf)
-		if err != nil {
-			t.Errorf("%d: Parse returned error: %s", i, err)
-			continue
-		}
-
-		expected, _ := hex.DecodeString(test.out)
-		out := make([]byte, len(expected))
-		f(out, []byte(test.in))
-		if !bytes.Equal(out, expected) {
-			t.Errorf("%d: output got: %x want: %x", i, out, expected)
-		}
-		if testing.Short() {
-			break
-		}
-	}
-}
-
-func TestSerialize(t *testing.T) {
-	buf := bytes.NewBuffer(nil)
-	key := make([]byte, 16)
-	passphrase := []byte("testing")
-	err := Serialize(buf, key, rand.Reader, passphrase)
-	if err != nil {
-		t.Errorf("failed to serialize: %s", err)
-		return
-	}
-
-	f, err := Parse(buf)
-	if err != nil {
-		t.Errorf("failed to reparse: %s", err)
-		return
-	}
-	key2 := make([]byte, len(key))
-	f(key2, passphrase)
-	if !bytes.Equal(key2, key) {
-		t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2)
-	}
-}
diff --git a/src/pkg/crypto/openpgp/write.go b/src/pkg/crypto/openpgp/write.go
deleted file mode 100644
index 9884472..0000000
--- a/src/pkg/crypto/openpgp/write.go
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright 2011 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 openpgp
-
-import (
-	"crypto"
-	"crypto/openpgp/armor"
-	"crypto/openpgp/error"
-	"crypto/openpgp/packet"
-	"crypto/openpgp/s2k"
-	"crypto/rand"
-	_ "crypto/sha256"
-	"hash"
-	"io"
-	"os"
-	"strconv"
-	"time"
-)
-
-// DetachSign signs message with the private key from signer (which must
-// already have been decrypted) and writes the signature to w.
-func DetachSign(w io.Writer, signer *Entity, message io.Reader) os.Error {
-	return detachSign(w, signer, message, packet.SigTypeBinary)
-}
-
-// ArmoredDetachSign signs message with the private key from signer (which
-// must already have been decrypted) and writes an armored signature to w.
-func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader) (err os.Error) {
-	return armoredDetachSign(w, signer, message, packet.SigTypeBinary)
-}
-
-// DetachSignText signs message (after canonicalising the line endings) with
-// the private key from signer (which must already have been decrypted) and
-// writes the signature to w.
-func DetachSignText(w io.Writer, signer *Entity, message io.Reader) os.Error {
-	return detachSign(w, signer, message, packet.SigTypeText)
-}
-
-// ArmoredDetachSignText signs message (after canonicalising the line endings)
-// with the private key from signer (which must already have been decrypted)
-// and writes an armored signature to w.
-func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader) os.Error {
-	return armoredDetachSign(w, signer, message, packet.SigTypeText)
-}
-
-func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err os.Error) {
-	out, err := armor.Encode(w, SignatureType, nil)
-	if err != nil {
-		return
-	}
-	err = detachSign(out, signer, message, sigType)
-	if err != nil {
-		return
-	}
-	return out.Close()
-}
-
-func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err os.Error) {
-	if signer.PrivateKey == nil {
-		return error.InvalidArgumentError("signing key doesn't have a private key")
-	}
-	if signer.PrivateKey.Encrypted {
-		return error.InvalidArgumentError("signing key is encrypted")
-	}
-
-	sig := new(packet.Signature)
-	sig.SigType = sigType
-	sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
-	sig.Hash = crypto.SHA256
-	sig.CreationTime = uint32(time.Seconds())
-	sig.IssuerKeyId = &signer.PrivateKey.KeyId
-
-	h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
-	if err != nil {
-		return
-	}
-	io.Copy(wrappedHash, message)
-
-	err = sig.Sign(h, signer.PrivateKey)
-	if err != nil {
-		return
-	}
-
-	return sig.Serialize(w)
-}
-
-// FileHints contains metadata about encrypted files. This metadata is, itself,
-// encrypted.
-type FileHints struct {
-	// IsBinary can be set to hint that the contents are binary data.
-	IsBinary bool
-	// FileName hints at the name of the file that should be written. It's
-	// truncated to 255 bytes if longer. It may be empty to suggest that the
-	// file should not be written to disk. It may be equal to "_CONSOLE" to
-	// suggest the data should not be written to disk.
-	FileName string
-	// EpochSeconds contains the modification time of the file, or 0 if not applicable.
-	EpochSeconds uint32
-}
-
-// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase.
-// The resulting WriteCloser must be closed after the contents of the file have
-// been written.
-func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints) (plaintext io.WriteCloser, err os.Error) {
-	if hints == nil {
-		hints = &FileHints{}
-	}
-
-	key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, rand.Reader, passphrase, packet.CipherAES128)
-	if err != nil {
-		return
-	}
-	w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, packet.CipherAES128, key)
-	if err != nil {
-		return
-	}
-	return packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, hints.EpochSeconds)
-}
-
-// intersectPreferences mutates and returns a prefix of a that contains only
-// the values in the intersection of a and b. The order of a is preserved.
-func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
-	var j int
-	for _, v := range a {
-		for _, v2 := range b {
-			if v == v2 {
-				a[j] = v
-				j++
-				break
-			}
-		}
-	}
-
-	return a[:j]
-}
-
-func hashToHashId(h crypto.Hash) uint8 {
-	v, ok := s2k.HashToHashId(h)
-	if !ok {
-		panic("tried to convert unknown hash")
-	}
-	return v
-}
-
-// Encrypt encrypts a message to a number of recipients and, optionally, signs
-// it. hints contains optional information, that is also encrypted, that aids
-// the recipients in processing the message. The resulting WriteCloser must
-// be closed after the contents of the file have been written.
-func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints) (plaintext io.WriteCloser, err os.Error) {
-	var signer *packet.PrivateKey
-	if signed != nil {
-		signer = signed.signingKey().PrivateKey
-		if signer == nil || signer.Encrypted {
-			return nil, error.InvalidArgumentError("signing key must be decrypted")
-		}
-	}
-
-	// These are the possible ciphers that we'll use for the message.
-	candidateCiphers := []uint8{
-		uint8(packet.CipherAES128),
-		uint8(packet.CipherAES256),
-		uint8(packet.CipherCAST5),
-	}
-	// These are the possible hash functions that we'll use for the signature.
-	candidateHashes := []uint8{
-		hashToHashId(crypto.SHA256),
-		hashToHashId(crypto.SHA512),
-		hashToHashId(crypto.SHA1),
-		hashToHashId(crypto.RIPEMD160),
-	}
-	// In the event that a recipient doesn't specify any supported ciphers
-	// or hash functions, these are the ones that we assume that every
-	// implementation supports.
-	defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
-	defaultHashes := candidateHashes[len(candidateHashes)-1:]
-
-	encryptKeys := make([]Key, len(to))
-	for i := range to {
-		encryptKeys[i] = to[i].encryptionKey()
-		if encryptKeys[i].PublicKey == nil {
-			return nil, error.InvalidArgumentError("cannot encrypt a message to key id " + strconv.Uitob64(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
-		}
-
-		sig := to[i].primaryIdentity().SelfSignature
-
-		preferredSymmetric := sig.PreferredSymmetric
-		if len(preferredSymmetric) == 0 {
-			preferredSymmetric = defaultCiphers
-		}
-		preferredHashes := sig.PreferredHash
-		if len(preferredHashes) == 0 {
-			preferredHashes = defaultHashes
-		}
-		candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
-		candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
-	}
-
-	if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
-		return nil, error.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
-	}
-
-	cipher := packet.CipherFunction(candidateCiphers[0])
-	hash, _ := s2k.HashIdToHash(candidateHashes[0])
-	symKey := make([]byte, cipher.KeySize())
-	if _, err := io.ReadFull(rand.Reader, symKey); err != nil {
-		return nil, err
-	}
-
-	for _, key := range encryptKeys {
-		if err := packet.SerializeEncryptedKey(ciphertext, rand.Reader, key.PublicKey, cipher, symKey); err != nil {
-			return nil, err
-		}
-	}
-
-	encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey)
-	if err != nil {
-		return
-	}
-
-	if signer != nil {
-		ops := &packet.OnePassSignature{
-			SigType:    packet.SigTypeBinary,
-			Hash:       hash,
-			PubKeyAlgo: signer.PubKeyAlgo,
-			KeyId:      signer.KeyId,
-			IsLast:     true,
-		}
-		if err := ops.Serialize(encryptedData); err != nil {
-			return nil, err
-		}
-	}
-
-	if hints == nil {
-		hints = &FileHints{}
-	}
-
-	w := encryptedData
-	if signer != nil {
-		// If we need to write a signature packet after the literal
-		// data then we need to stop literalData from closing
-		// encryptedData.
-		w = noOpCloser{encryptedData}
-
-	}
-	literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, hints.EpochSeconds)
-	if err != nil {
-		return nil, err
-	}
-
-	if signer != nil {
-		return signatureWriter{encryptedData, literalData, hash, hash.New(), signer}, nil
-	}
-	return literalData, nil
-}
-
-// signatureWriter hashes the contents of a message while passing it along to
-// literalData. When closed, it closes literalData, writes a signature packet
-// to encryptedData and then also closes encryptedData.
-type signatureWriter struct {
-	encryptedData io.WriteCloser
-	literalData   io.WriteCloser
-	hashType      crypto.Hash
-	h             hash.Hash
-	signer        *packet.PrivateKey
-}
-
-func (s signatureWriter) Write(data []byte) (int, os.Error) {
-	s.h.Write(data)
-	return s.literalData.Write(data)
-}
-
-func (s signatureWriter) Close() os.Error {
-	sig := &packet.Signature{
-		SigType:      packet.SigTypeBinary,
-		PubKeyAlgo:   s.signer.PubKeyAlgo,
-		Hash:         s.hashType,
-		CreationTime: uint32(time.Seconds()),
-		IssuerKeyId:  &s.signer.KeyId,
-	}
-
-	if err := sig.Sign(s.h, s.signer); err != nil {
-		return err
-	}
-	if err := s.literalData.Close(); err != nil {
-		return err
-	}
-	if err := sig.Serialize(s.encryptedData); err != nil {
-		return err
-	}
-	return s.encryptedData.Close()
-}
-
-// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
-// TODO: we have two of these in OpenPGP packages alone. This probably needs
-// to be promoted somewhere more common.
-type noOpCloser struct {
-	w io.Writer
-}
-
-func (c noOpCloser) Write(data []byte) (n int, err os.Error) {
-	return c.w.Write(data)
-}
-
-func (c noOpCloser) Close() os.Error {
-	return nil
-}
diff --git a/src/pkg/crypto/openpgp/write_test.go b/src/pkg/crypto/openpgp/write_test.go
deleted file mode 100644
index c542dfa..0000000
--- a/src/pkg/crypto/openpgp/write_test.go
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright 2011 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 openpgp
-
-import (
-	"bytes"
-	"crypto/rand"
-	"os"
-	"io"
-	"io/ioutil"
-	"testing"
-	"time"
-)
-
-func TestSignDetached(t *testing.T) {
-	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-	out := bytes.NewBuffer(nil)
-	message := bytes.NewBufferString(signedInput)
-	err := DetachSign(out, kring[0], message)
-	if err != nil {
-		t.Error(err)
-	}
-
-	testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
-}
-
-func TestSignTextDetached(t *testing.T) {
-	kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-	out := bytes.NewBuffer(nil)
-	message := bytes.NewBufferString(signedInput)
-	err := DetachSignText(out, kring[0], message)
-	if err != nil {
-		t.Error(err)
-	}
-
-	testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
-}
-
-func TestSignDetachedDSA(t *testing.T) {
-	kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex))
-	out := bytes.NewBuffer(nil)
-	message := bytes.NewBufferString(signedInput)
-	err := DetachSign(out, kring[0], message)
-	if err != nil {
-		t.Error(err)
-	}
-
-	testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId)
-}
-
-func TestNewEntity(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-
-	e, err := NewEntity(rand.Reader, time.Seconds(), "Test User", "test", "test at example.com")
-	if err != nil {
-		t.Errorf("failed to create entity: %s", err)
-		return
-	}
-
-	w := bytes.NewBuffer(nil)
-	if err := e.SerializePrivate(w); err != nil {
-		t.Errorf("failed to serialize entity: %s", err)
-		return
-	}
-	serialized := w.Bytes()
-
-	el, err := ReadKeyRing(w)
-	if err != nil {
-		t.Errorf("failed to reparse entity: %s", err)
-		return
-	}
-
-	if len(el) != 1 {
-		t.Errorf("wrong number of entities found, got %d, want 1", len(el))
-	}
-
-	w = bytes.NewBuffer(nil)
-	if err := e.SerializePrivate(w); err != nil {
-		t.Errorf("failed to serialize entity second time: %s", err)
-		return
-	}
-
-	if !bytes.Equal(w.Bytes(), serialized) {
-		t.Errorf("results differed")
-	}
-}
-
-func TestSymmetricEncryption(t *testing.T) {
-	buf := new(bytes.Buffer)
-	plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil)
-	if err != nil {
-		t.Errorf("error writing headers: %s", err)
-		return
-	}
-	message := []byte("hello world\n")
-	_, err = plaintext.Write(message)
-	if err != nil {
-		t.Errorf("error writing to plaintext writer: %s", err)
-	}
-	err = plaintext.Close()
-	if err != nil {
-		t.Errorf("error closing plaintext writer: %s", err)
-	}
-
-	md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, os.Error) {
-		return []byte("testing"), nil
-	})
-	if err != nil {
-		t.Errorf("error rereading message: %s", err)
-	}
-	messageBuf := bytes.NewBuffer(nil)
-	_, err = io.Copy(messageBuf, md.UnverifiedBody)
-	if err != nil {
-		t.Errorf("error rereading message: %s", err)
-	}
-	if !bytes.Equal(message, messageBuf.Bytes()) {
-		t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message)
-	}
-}
-
-var testEncryptionTests = []struct {
-	keyRingHex string
-	isSigned   bool
-}{
-	{
-		testKeys1And2PrivateHex,
-		false,
-	},
-	{
-		testKeys1And2PrivateHex,
-		true,
-	},
-	{
-		dsaElGamalTestKeysHex,
-		false,
-	},
-	{
-		dsaElGamalTestKeysHex,
-		true,
-	},
-}
-
-func TestEncryption(t *testing.T) {
-	for i, test := range testEncryptionTests {
-		kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
-
-		passphrase := []byte("passphrase")
-		for _, entity := range kring {
-			if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
-				err := entity.PrivateKey.Decrypt(passphrase)
-				if err != nil {
-					t.Errorf("#%d: failed to decrypt key", i)
-				}
-			}
-			for _, subkey := range entity.Subkeys {
-				if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted {
-					err := subkey.PrivateKey.Decrypt(passphrase)
-					if err != nil {
-						t.Errorf("#%d: failed to decrypt subkey", i)
-					}
-				}
-			}
-		}
-
-		var signed *Entity
-		if test.isSigned {
-			signed = kring[0]
-		}
-
-		buf := new(bytes.Buffer)
-		w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */ )
-		if err != nil {
-			t.Errorf("#%d: error in Encrypt: %s", i, err)
-			continue
-		}
-
-		const message = "testing"
-		_, err = w.Write([]byte(message))
-		if err != nil {
-			t.Errorf("#%d: error writing plaintext: %s", i, err)
-			continue
-		}
-		err = w.Close()
-		if err != nil {
-			t.Errorf("#%d: error closing WriteCloser: %s", i, err)
-			continue
-		}
-
-		md, err := ReadMessage(buf, kring, nil /* no prompt */ )
-		if err != nil {
-			t.Errorf("#%d: error reading message: %s", i, err)
-			continue
-		}
-
-		if test.isSigned {
-			expectedKeyId := kring[0].signingKey().PublicKey.KeyId
-			if md.SignedByKeyId != expectedKeyId {
-				t.Errorf("#%d: message signed by wrong key id, got: %d, want: %d", i, *md.SignedBy, expectedKeyId)
-			}
-			if md.SignedBy == nil {
-				t.Errorf("#%d: failed to find the signing Entity", i)
-			}
-		}
-
-		plaintext, err := ioutil.ReadAll(md.UnverifiedBody)
-		if err != nil {
-			t.Errorf("#%d: error reading encrypted contents: %s", i, err)
-			continue
-		}
-
-		expectedKeyId := kring[0].encryptionKey().PublicKey.KeyId
-		if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId {
-			t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds)
-		}
-
-		if string(plaintext) != message {
-			t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message)
-		}
-
-		if test.isSigned {
-			if md.SignatureError != nil {
-				t.Errorf("#%d: signature error: %s", i, err)
-			}
-			if md.Signature == nil {
-				t.Error("signature missing")
-			}
-		}
-	}
-}
diff --git a/src/pkg/crypto/rand/rand.go b/src/pkg/crypto/rand/rand.go
index 42d9da0..5975903 100644
--- a/src/pkg/crypto/rand/rand.go
+++ b/src/pkg/crypto/rand/rand.go
@@ -6,10 +6,7 @@
 // pseudorandom number generator.
 package rand
 
-import (
-	"io"
-	"os"
-)
+import "io"
 
 // Reader is a global, shared instance of a cryptographically
 // strong pseudo-random generator.
@@ -18,4 +15,4 @@ import (
 var Reader io.Reader
 
 // Read is a helper function that calls Reader.Read.
-func Read(b []byte) (n int, err os.Error) { return Reader.Read(b) }
+func Read(b []byte) (n int, err error) { return Reader.Read(b) }
diff --git a/src/pkg/crypto/rand/rand_unix.go b/src/pkg/crypto/rand/rand_unix.go
index 76a7365..5d4fc81 100644
--- a/src/pkg/crypto/rand/rand_unix.go
+++ b/src/pkg/crypto/rand/rand_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 // Unix cryptographically secure pseudorandom number
 // generator.
@@ -30,7 +30,7 @@ type devReader struct {
 	mu   sync.Mutex
 }
 
-func (r *devReader) Read(b []byte) (n int, err os.Error) {
+func (r *devReader) Read(b []byte) (n int, err error) {
 	r.mu.Lock()
 	defer r.mu.Unlock()
 	if r.f == nil {
@@ -71,7 +71,7 @@ type reader struct {
 	time, seed, dst, key [aes.BlockSize]byte
 }
 
-func (r *reader) Read(b []byte) (n int, err os.Error) {
+func (r *reader) Read(b []byte) (n int, err error) {
 	r.mu.Lock()
 	defer r.mu.Unlock()
 	n = len(b)
@@ -100,7 +100,7 @@ func (r *reader) Read(b []byte) (n int, err os.Error) {
 		// t = encrypt(time)
 		// dst = encrypt(t^seed)
 		// seed = encrypt(t^dst)
-		ns := time.Nanoseconds()
+		ns := time.Now().UnixNano()
 		r.time[0] = byte(ns >> 56)
 		r.time[1] = byte(ns >> 48)
 		r.time[2] = byte(ns >> 40)
diff --git a/src/pkg/crypto/rand/rand_windows.go b/src/pkg/crypto/rand/rand_windows.go
index 0eab6b2..2b2bd4b 100644
--- a/src/pkg/crypto/rand/rand_windows.go
+++ b/src/pkg/crypto/rand/rand_windows.go
@@ -23,21 +23,21 @@ type rngReader struct {
 	mu   sync.Mutex
 }
 
-func (r *rngReader) Read(b []byte) (n int, err os.Error) {
+func (r *rngReader) Read(b []byte) (n int, err error) {
 	r.mu.Lock()
 	if r.prov == 0 {
 		const provType = syscall.PROV_RSA_FULL
 		const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
-		errno := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
-		if errno != 0 {
+		err := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
+		if err != nil {
 			r.mu.Unlock()
-			return 0, os.NewSyscallError("CryptAcquireContext", errno)
+			return 0, os.NewSyscallError("CryptAcquireContext", err)
 		}
 	}
 	r.mu.Unlock()
-	errno := syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
-	if errno != 0 {
-		return 0, os.NewSyscallError("CryptGenRandom", errno)
+	err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
+	if err != nil {
+		return 0, os.NewSyscallError("CryptGenRandom", err)
 	}
 	return len(b), nil
 }
diff --git a/src/pkg/crypto/rand/util.go b/src/pkg/crypto/rand/util.go
index 7702847..fc5fe6c 100644
--- a/src/pkg/crypto/rand/util.go
+++ b/src/pkg/crypto/rand/util.go
@@ -5,16 +5,16 @@
 package rand
 
 import (
-	"big"
+	"errors"
 	"io"
-	"os"
+	"math/big"
 )
 
 // Prime returns a number, p, of the given size, such that p is prime
 // with high probability.
-func Prime(rand io.Reader, bits int) (p *big.Int, err os.Error) {
+func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
 	if bits < 1 {
-		err = os.EINVAL
+		err = errors.New("crypto/rand: prime size must be positive")
 	}
 
 	b := uint(bits % 8)
@@ -48,7 +48,7 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err os.Error) {
 }
 
 // Int returns a uniform random value in [0, max).
-func Int(rand io.Reader, max *big.Int) (n *big.Int, err os.Error) {
+func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {
 	k := (max.BitLen() + 7) / 8
 
 	// b is the number of bits in the most significant byte of max.
diff --git a/src/pkg/crypto/rc4/rc4.go b/src/pkg/crypto/rc4/rc4.go
index 7ee4710..1bb278f 100644
--- a/src/pkg/crypto/rc4/rc4.go
+++ b/src/pkg/crypto/rc4/rc4.go
@@ -9,10 +9,7 @@ package rc4
 // BUG(agl): RC4 is in common use but has design weaknesses that make
 // it a poor choice for new protocols.
 
-import (
-	"os"
-	"strconv"
-)
+import "strconv"
 
 // A Cipher is an instance of RC4 using a particular key.
 type Cipher struct {
@@ -22,13 +19,13 @@ type Cipher struct {
 
 type KeySizeError int
 
-func (k KeySizeError) String() string {
+func (k KeySizeError) Error() string {
 	return "crypto/rc4: invalid key size " + strconv.Itoa(int(k))
 }
 
 // NewCipher creates and returns a new Cipher.  The key argument should be the
 // RC4 key, at least 1 byte and at most 256 bytes.
-func NewCipher(key []byte) (*Cipher, os.Error) {
+func NewCipher(key []byte) (*Cipher, error) {
 	k := len(key)
 	if k < 1 || k > 256 {
 		return nil, KeySizeError(k)
diff --git a/src/pkg/crypto/ripemd160/Makefile b/src/pkg/crypto/ripemd160/Makefile
deleted file mode 100644
index 7e52945..0000000
--- a/src/pkg/crypto/ripemd160/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/ripemd160
-GOFILES=\
-	ripemd160.go\
-	ripemd160block.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/ripemd160/ripemd160.go b/src/pkg/crypto/ripemd160/ripemd160.go
deleted file mode 100644
index 5aaca59..0000000
--- a/src/pkg/crypto/ripemd160/ripemd160.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2010 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 ripemd160 implements the RIPEMD-160 hash algorithm.
-package ripemd160
-
-// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
-// Preneel with specifications available at:
-// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf.
-
-import (
-	"crypto"
-	"hash"
-	"os"
-)
-
-func init() {
-	crypto.RegisterHash(crypto.RIPEMD160, New)
-}
-
-// The size of the checksum in bytes.
-const Size = 20
-
-// The block size of the hash algorithm in bytes.
-const BlockSize = 64
-
-const (
-	_s0 = 0x67452301
-	_s1 = 0xefcdab89
-	_s2 = 0x98badcfe
-	_s3 = 0x10325476
-	_s4 = 0xc3d2e1f0
-)
-
-// digest represents the partial evaluation of a checksum.
-type digest struct {
-	s  [5]uint32       // running context
-	x  [BlockSize]byte // temporary buffer
-	nx int             // index into x
-	tc uint64          // total count of bytes processed
-}
-
-func (d *digest) Reset() {
-	d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4
-	d.nx = 0
-	d.tc = 0
-}
-
-// New returns a new hash.Hash computing the checksum.
-func New() hash.Hash {
-	result := new(digest)
-	result.Reset()
-	return result
-}
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) Write(p []byte) (nn int, err os.Error) {
-	nn = len(p)
-	d.tc += uint64(nn)
-	if d.nx > 0 {
-		n := len(p)
-		if n > BlockSize-d.nx {
-			n = BlockSize - d.nx
-		}
-		for i := 0; i < n; i++ {
-			d.x[d.nx+i] = p[i]
-		}
-		d.nx += n
-		if d.nx == BlockSize {
-			_Block(d, d.x[0:])
-			d.nx = 0
-		}
-		p = p[n:]
-	}
-	n := _Block(d, p)
-	p = p[n:]
-	if len(p) > 0 {
-		d.nx = copy(d.x[:], p)
-	}
-	return
-}
-
-func (d0 *digest) Sum() []byte {
-	// Make a copy of d0 so that caller can keep writing and summing.
-	d := new(digest)
-	*d = *d0
-
-	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
-	tc := d.tc
-	var tmp [64]byte
-	tmp[0] = 0x80
-	if tc%64 < 56 {
-		d.Write(tmp[0 : 56-tc%64])
-	} else {
-		d.Write(tmp[0 : 64+56-tc%64])
-	}
-
-	// Length in bits.
-	tc <<= 3
-	for i := uint(0); i < 8; i++ {
-		tmp[i] = byte(tc >> (8 * i))
-	}
-	d.Write(tmp[0:8])
-
-	if d.nx != 0 {
-		panic("d.nx != 0")
-	}
-
-	p := make([]byte, 20)
-	j := 0
-	for _, s := range d.s {
-		p[j], p[j+1], p[j+2], p[j+3] = byte(s), byte(s>>8), byte(s>>16), byte(s>>24)
-		j += 4
-	}
-	return p
-}
diff --git a/src/pkg/crypto/ripemd160/ripemd160_test.go b/src/pkg/crypto/ripemd160/ripemd160_test.go
deleted file mode 100644
index f4135f5..0000000
--- a/src/pkg/crypto/ripemd160/ripemd160_test.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2010 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 ripemd160
-
-// Test vectors are from:
-// http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
-
-import (
-	"fmt"
-	"io"
-	"testing"
-)
-
-type mdTest struct {
-	out string
-	in  string
-}
-
-var vectors = [...]mdTest{
-	{"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""},
-	{"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"},
-	{"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"},
-	{"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"},
-	{"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"},
-	{"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
-	{"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
-	{"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
-}
-
-func TestVectors(t *testing.T) {
-	for i := 0; i < len(vectors); i++ {
-		tv := vectors[i]
-		md := New()
-		for j := 0; j < 3; j++ {
-			if j < 2 {
-				io.WriteString(md, tv.in)
-			} else {
-				io.WriteString(md, tv.in[0:len(tv.in)/2])
-				md.Sum()
-				io.WriteString(md, tv.in[len(tv.in)/2:])
-			}
-			s := fmt.Sprintf("%x", md.Sum())
-			if s != tv.out {
-				t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out)
-			}
-			md.Reset()
-		}
-	}
-}
-
-func TestMillionA(t *testing.T) {
-	md := New()
-	for i := 0; i < 100000; i++ {
-		io.WriteString(md, "aaaaaaaaaa")
-	}
-	out := "52783243c1697bdbe16d37f97f68f08325dc1528"
-	s := fmt.Sprintf("%x", md.Sum())
-	if s != out {
-		t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out)
-	}
-	md.Reset()
-}
diff --git a/src/pkg/crypto/ripemd160/ripemd160block.go b/src/pkg/crypto/ripemd160/ripemd160block.go
deleted file mode 100644
index 7bc8e6c..0000000
--- a/src/pkg/crypto/ripemd160/ripemd160block.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2010 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.
-
-// RIPEMD-160 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
-
-package ripemd160
-
-// work buffer indices and roll amounts for one line
-var _n = [80]uint{
-	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-	7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
-	3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
-	1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
-	4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13,
-}
-
-var _r = [80]uint{
-	11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
-	7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
-	11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
-	11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
-	9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6,
-}
-
-// same for the other parallel one
-var n_ = [80]uint{
-	5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
-	6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
-	15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
-	8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
-	12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11,
-}
-
-var r_ = [80]uint{
-	8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
-	9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
-	9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
-	15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
-	8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11,
-}
-
-func _Block(md *digest, p []byte) int {
-	n := 0
-	var x [16]uint32
-	var alpha, beta uint32
-	for len(p) >= BlockSize {
-		a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4]
-		aa, bb, cc, dd, ee := a, b, c, d, e
-		j := 0
-		for i := 0; i < 16; i++ {
-			x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
-			j += 4
-		}
-
-		// round 1
-		i := 0
-		for i < 16 {
-			alpha = a + (b ^ c ^ d) + x[_n[i]]
-			s := _r[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + e
-			beta = c<<10 | c>>22
-			a, b, c, d, e = e, alpha, b, beta, d
-
-			// parallel line
-			alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6
-			s = r_[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + ee
-			beta = cc<<10 | cc>>22
-			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-			i++
-		}
-
-		// round 2
-		for i < 32 {
-			alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999
-			s := _r[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + e
-			beta = c<<10 | c>>22
-			a, b, c, d, e = e, alpha, b, beta, d
-
-			// parallel line
-			alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124
-			s = r_[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + ee
-			beta = cc<<10 | cc>>22
-			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-			i++
-		}
-
-		// round 3
-		for i < 48 {
-			alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1
-			s := _r[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + e
-			beta = c<<10 | c>>22
-			a, b, c, d, e = e, alpha, b, beta, d
-
-			// parallel line
-			alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3
-			s = r_[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + ee
-			beta = cc<<10 | cc>>22
-			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-			i++
-		}
-
-		// round 4
-		for i < 64 {
-			alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc
-			s := _r[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + e
-			beta = c<<10 | c>>22
-			a, b, c, d, e = e, alpha, b, beta, d
-
-			// parallel line
-			alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9
-			s = r_[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + ee
-			beta = cc<<10 | cc>>22
-			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-			i++
-		}
-
-		// round 5
-		for i < 80 {
-			alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e
-			s := _r[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + e
-			beta = c<<10 | c>>22
-			a, b, c, d, e = e, alpha, b, beta, d
-
-			// parallel line
-			alpha = aa + (bb ^ cc ^ dd) + x[n_[i]]
-			s = r_[i]
-			alpha = (alpha<<s | alpha>>(32-s)) + ee
-			beta = cc<<10 | cc>>22
-			aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-			i++
-		}
-
-		// combine results
-		dd += c + md.s[1]
-		md.s[1] = md.s[2] + d + ee
-		md.s[2] = md.s[3] + e + aa
-		md.s[3] = md.s[4] + a + bb
-		md.s[4] = md.s[0] + b + cc
-		md.s[0] = dd
-
-		p = p[BlockSize:]
-		n += BlockSize
-	}
-	return n
-}
diff --git a/src/pkg/crypto/rsa/pkcs1v15.go b/src/pkg/crypto/rsa/pkcs1v15.go
index 6006231..d7b053f 100644
--- a/src/pkg/crypto/rsa/pkcs1v15.go
+++ b/src/pkg/crypto/rsa/pkcs1v15.go
@@ -5,11 +5,11 @@
 package rsa
 
 import (
-	"big"
 	"crypto"
 	"crypto/subtle"
+	"errors"
 	"io"
-	"os"
+	"math/big"
 )
 
 // This file implements encryption and decryption using PKCS#1 v1.5 padding.
@@ -18,7 +18,7 @@ import (
 // The message must be no longer than the length of the public modulus minus 11 bytes.
 // WARNING: use of this function to encrypt plaintexts other than session keys
 // is dangerous. Use RSA OAEP in new protocols.
-func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err os.Error) {
+func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
 	k := (pub.N.BitLen() + 7) / 8
 	if len(msg) > k-11 {
 		err = MessageTooLongError{}
@@ -44,7 +44,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
 
 // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
-func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err os.Error) {
+func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
 	valid, out, err := decryptPKCS1v15(rand, priv, ciphertext)
 	if err == nil && valid == 0 {
 		err = DecryptionError{}
@@ -66,7 +66,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [
 // See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
 // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
 // (Crypto '98),
-func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err os.Error) {
+func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
 	k := (priv.N.BitLen() + 7) / 8
 	if k-(len(key)+3+8) < 0 {
 		err = DecryptionError{}
@@ -83,7 +83,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
 	return
 }
 
-func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err os.Error) {
+func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err error) {
 	k := (priv.N.BitLen() + 7) / 8
 	if k < 11 {
 		err = DecryptionError{}
@@ -119,7 +119,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
 }
 
 // nonZeroRandomBytes fills the given slice with non-zero random octets.
-func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
+func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
 	_, err = io.ReadFull(rand, s)
 	if err != nil {
 		return
@@ -161,7 +161,7 @@ var hashPrefixes = map[crypto.Hash][]byte{
 // SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5.
 // Note that hashed must be the result of hashing the input message using the
 // given hash function.
-func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err os.Error) {
+func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) {
 	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
 	if err != nil {
 		return
@@ -194,7 +194,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
 // hashed is the result of hashing the input message using the given hash
 // function and sig is the signature. A valid signature is indicated by
 // returning a nil error.
-func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err os.Error) {
+func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error) {
 	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
 	if err != nil {
 		return
@@ -229,14 +229,14 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
 	return nil
 }
 
-func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err os.Error) {
+func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
 	hashLen = hash.Size()
 	if inLen != hashLen {
-		return 0, nil, os.NewError("input must be hashed message")
+		return 0, nil, errors.New("input must be hashed message")
 	}
 	prefix, ok := hashPrefixes[hash]
 	if !ok {
-		return 0, nil, os.NewError("unsupported hash function")
+		return 0, nil, errors.New("unsupported hash function")
 	}
 	return
 }
diff --git a/src/pkg/crypto/rsa/pkcs1v15_test.go b/src/pkg/crypto/rsa/pkcs1v15_test.go
index d69bacf..58d5fda 100644
--- a/src/pkg/crypto/rsa/pkcs1v15_test.go
+++ b/src/pkg/crypto/rsa/pkcs1v15_test.go
@@ -5,7 +5,6 @@
 package rsa
 
 import (
-	"big"
 	"bytes"
 	"crypto"
 	"crypto/rand"
@@ -13,6 +12,7 @@ import (
 	"encoding/base64"
 	"encoding/hex"
 	"io"
+	"math/big"
 	"testing"
 	"testing/quick"
 )
@@ -168,7 +168,7 @@ func TestSignPKCS1v15(t *testing.T) {
 	for i, test := range signPKCS1v15Tests {
 		h := sha1.New()
 		h.Write([]byte(test.in))
-		digest := h.Sum()
+		digest := h.Sum(nil)
 
 		s, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA1, digest)
 		if err != nil {
@@ -186,7 +186,7 @@ func TestVerifyPKCS1v15(t *testing.T) {
 	for i, test := range signPKCS1v15Tests {
 		h := sha1.New()
 		h.Write([]byte(test.in))
-		digest := h.Sum()
+		digest := h.Sum(nil)
 
 		sig, _ := hex.DecodeString(test.out)
 
diff --git a/src/pkg/crypto/rsa/rsa.go b/src/pkg/crypto/rsa/rsa.go
index 6957659..c07e8f9 100644
--- a/src/pkg/crypto/rsa/rsa.go
+++ b/src/pkg/crypto/rsa/rsa.go
@@ -8,12 +8,12 @@ package rsa
 // TODO(agl): Add support for PSS padding.
 
 import (
-	"big"
 	"crypto/rand"
 	"crypto/subtle"
+	"errors"
 	"hash"
 	"io"
-	"os"
+	"math/big"
 )
 
 var bigZero = big.NewInt(0)
@@ -55,16 +55,15 @@ type CRTValue struct {
 }
 
 // Validate performs basic sanity checks on the key.
-// It returns nil if the key is valid, or else an os.Error describing a problem.
-
-func (priv *PrivateKey) Validate() os.Error {
+// It returns nil if the key is valid, or else an error describing a problem.
+func (priv *PrivateKey) Validate() error {
 	// Check that the prime factors are actually prime. Note that this is
 	// just a sanity check. Since the random witnesses chosen by
 	// ProbablyPrime are deterministic, given the candidate number, it's
 	// easy for an attack to generate composites that pass this test.
 	for _, prime := range priv.Primes {
 		if !big.ProbablyPrime(prime, 20) {
-			return os.NewError("prime factor is composite")
+			return errors.New("prime factor is composite")
 		}
 	}
 
@@ -74,7 +73,7 @@ func (priv *PrivateKey) Validate() os.Error {
 		modulus.Mul(modulus, prime)
 	}
 	if modulus.Cmp(priv.N) != 0 {
-		return os.NewError("invalid modulus")
+		return errors.New("invalid modulus")
 	}
 	// Check that e and totient(Πprimes) are coprime.
 	totient := new(big.Int).Set(bigOne)
@@ -88,19 +87,19 @@ func (priv *PrivateKey) Validate() os.Error {
 	y := new(big.Int)
 	big.GcdInt(gcd, x, y, totient, e)
 	if gcd.Cmp(bigOne) != 0 {
-		return os.NewError("invalid public exponent E")
+		return errors.New("invalid public exponent E")
 	}
 	// Check that de ≡ 1 (mod totient(Πprimes))
 	de := new(big.Int).Mul(priv.D, e)
 	de.Mod(de, totient)
 	if de.Cmp(bigOne) != 0 {
-		return os.NewError("invalid private exponent D")
+		return errors.New("invalid private exponent D")
 	}
 	return nil
 }
 
 // GenerateKey generates an RSA keypair of the given bit size.
-func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err os.Error) {
+func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error) {
 	return GenerateMultiPrimeKey(random, 2, bits)
 }
 
@@ -114,20 +113,12 @@ func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err os.Error) {
 //
 // [1] US patent 4405829 (1972, expired)
 // [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
-func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *PrivateKey, err os.Error) {
+func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *PrivateKey, err error) {
 	priv = new(PrivateKey)
-	// Smaller public exponents lead to faster public key
-	// operations. Since the exponent must be coprime to
-	// (p-1)(q-1), the smallest possible value is 3. Some have
-	// suggested that a larger exponent (often 2**16+1) be used
-	// since previous implementation bugs[1] were avoided when this
-	// was the case. However, there are no current reasons not to use
-	// small exponents.
-	// [1] http://marc.info/?l=cryptography&m=115694833312008&w=2
-	priv.E = 3
+	priv.E = 65537
 
 	if nprimes < 2 {
-		return nil, os.NewError("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
+		return nil, errors.New("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
 	}
 
 	primes := make([]*big.Int, nprimes)
@@ -198,12 +189,13 @@ func incCounter(c *[4]byte) {
 // specified in PKCS#1 v2.1.
 func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
 	var counter [4]byte
+	var digest []byte
 
 	done := 0
 	for done < len(out) {
 		hash.Write(seed)
 		hash.Write(counter[0:4])
-		digest := hash.Sum()
+		digest = hash.Sum(digest[:0])
 		hash.Reset()
 
 		for i := 0; i < len(digest) && done < len(out); i++ {
@@ -218,7 +210,7 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
 // is too large for the size of the public key.
 type MessageTooLongError struct{}
 
-func (MessageTooLongError) String() string {
+func (MessageTooLongError) Error() string {
 	return "message too long for RSA public key size"
 }
 
@@ -231,7 +223,7 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
 // EncryptOAEP encrypts the given message with RSA-OAEP.
 // The message must be no longer than the length of the public modulus less
 // twice the hash length plus 2.
-func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err os.Error) {
+func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) {
 	hash.Reset()
 	k := (pub.N.BitLen() + 7) / 8
 	if len(msg) > k-2*hash.Size()-2 {
@@ -240,7 +232,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
 	}
 
 	hash.Write(label)
-	lHash := hash.Sum()
+	lHash := hash.Sum(nil)
 	hash.Reset()
 
 	em := make([]byte, k)
@@ -278,13 +270,13 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
 // It is deliberately vague to avoid adaptive attacks.
 type DecryptionError struct{}
 
-func (DecryptionError) String() string { return "RSA decryption error" }
+func (DecryptionError) Error() string { return "RSA decryption error" }
 
 // A VerificationError represents a failure to verify a signature.
 // It is deliberately vague to avoid adaptive attacks.
 type VerificationError struct{}
 
-func (VerificationError) String() string { return "RSA verification error" }
+func (VerificationError) Error() string { return "RSA verification error" }
 
 // modInverse returns ia, the inverse of a in the multiplicative group of prime
 // order n. It requires that a be a member of the group (i.e. less than n).
@@ -343,7 +335,7 @@ func (priv *PrivateKey) Precompute() {
 
 // decrypt performs an RSA decryption, resulting in a plaintext integer. If a
 // random source is given, RSA blinding is used.
-func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.Error) {
+func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
 	// TODO(agl): can we get away with reusing blinds?
 	if c.Cmp(priv.N) > 0 {
 		err = DecryptionError{}
@@ -421,7 +413,7 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os
 
 // DecryptOAEP decrypts ciphertext using RSA-OAEP.
 // If rand != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
-func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err os.Error) {
+func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
 	k := (priv.N.BitLen() + 7) / 8
 	if len(ciphertext) > k ||
 		k < hash.Size()*2+2 {
@@ -437,7 +429,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
 	}
 
 	hash.Write(label)
-	lHash := hash.Sum()
+	lHash := hash.Sum(nil)
 	hash.Reset()
 
 	// Converting the plaintext number to bytes will strip any
diff --git a/src/pkg/crypto/rsa/rsa_test.go b/src/pkg/crypto/rsa/rsa_test.go
index c36bca1..0fb9875 100644
--- a/src/pkg/crypto/rsa/rsa_test.go
+++ b/src/pkg/crypto/rsa/rsa_test.go
@@ -5,10 +5,10 @@
 package rsa
 
 import (
-	"big"
 	"bytes"
 	"crypto/rand"
 	"crypto/sha1"
+	"math/big"
 	"testing"
 )
 
diff --git a/src/pkg/crypto/sha1/sha1.go b/src/pkg/crypto/sha1/sha1.go
index 788d1ff..876e799 100644
--- a/src/pkg/crypto/sha1/sha1.go
+++ b/src/pkg/crypto/sha1/sha1.go
@@ -8,7 +8,6 @@ package sha1
 import (
 	"crypto"
 	"hash"
-	"os"
 )
 
 func init() {
@@ -18,6 +17,9 @@ func init() {
 // The size of a SHA1 checksum in bytes.
 const Size = 20
 
+// The blocksize of SHA1 in bytes.
+const BlockSize = 64
+
 const (
 	_Chunk = 64
 	_Init0 = 0x67452301
@@ -54,7 +56,9 @@ func New() hash.Hash {
 
 func (d *digest) Size() int { return Size }
 
-func (d *digest) Write(p []byte) (nn int, err os.Error) {
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
 	nn = len(p)
 	d.len += uint64(nn)
 	if d.nx > 0 {
@@ -80,10 +84,9 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) {
 	return
 }
 
-func (d0 *digest) Sum() []byte {
+func (d0 *digest) Sum(in []byte) []byte {
 	// Make a copy of d0 so that caller can keep writing and summing.
-	d := new(digest)
-	*d = *d0
+	d := *d0
 
 	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
 	len := d.len
@@ -106,14 +109,13 @@ func (d0 *digest) Sum() []byte {
 		panic("d.nx != 0")
 	}
 
-	p := make([]byte, 20)
-	j := 0
-	for _, s := range d.h {
-		p[j+0] = byte(s >> 24)
-		p[j+1] = byte(s >> 16)
-		p[j+2] = byte(s >> 8)
-		p[j+3] = byte(s >> 0)
-		j += 4
+	var digest [Size]byte
+	for i, s := range d.h {
+		digest[i*4] = byte(s >> 24)
+		digest[i*4+1] = byte(s >> 16)
+		digest[i*4+2] = byte(s >> 8)
+		digest[i*4+3] = byte(s)
 	}
-	return p
+
+	return append(in, digest[:]...)
 }
diff --git a/src/pkg/crypto/sha1/sha1_test.go b/src/pkg/crypto/sha1/sha1_test.go
index 2712fe3..c23df6c 100644
--- a/src/pkg/crypto/sha1/sha1_test.go
+++ b/src/pkg/crypto/sha1/sha1_test.go
@@ -60,10 +60,10 @@ func TestGolden(t *testing.T) {
 				io.WriteString(c, g.in)
 			} else {
 				io.WriteString(c, g.in[0:len(g.in)/2])
-				c.Sum()
+				c.Sum(nil)
 				io.WriteString(c, g.in[len(g.in)/2:])
 			}
-			s := fmt.Sprintf("%x", c.Sum())
+			s := fmt.Sprintf("%x", c.Sum(nil))
 			if s != g.out {
 				t.Fatalf("sha1[%d](%s) = %s want %s", j, g.in, s, g.out)
 			}
diff --git a/src/pkg/crypto/sha256/sha256.go b/src/pkg/crypto/sha256/sha256.go
index a2c058d..a61e30b 100644
--- a/src/pkg/crypto/sha256/sha256.go
+++ b/src/pkg/crypto/sha256/sha256.go
@@ -9,7 +9,6 @@ package sha256
 import (
 	"crypto"
 	"hash"
-	"os"
 )
 
 func init() {
@@ -23,6 +22,9 @@ const Size = 32
 // The size of a SHA224 checksum in bytes.
 const Size224 = 28
 
+// The blocksize of SHA256 and SHA224 in bytes.
+const BlockSize = 64
+
 const (
 	_Chunk     = 64
 	_Init0     = 0x6A09E667
@@ -98,7 +100,9 @@ func (d *digest) Size() int {
 	return Size224
 }
 
-func (d *digest) Write(p []byte) (nn int, err os.Error) {
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
 	nn = len(p)
 	d.len += uint64(nn)
 	if d.nx > 0 {
@@ -124,10 +128,9 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) {
 	return
 }
 
-func (d0 *digest) Sum() []byte {
+func (d0 *digest) Sum(in []byte) []byte {
 	// Make a copy of d0 so that caller can keep writing and summing.
-	d := new(digest)
-	*d = *d0
+	d := *d0
 
 	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
 	len := d.len
@@ -150,17 +153,20 @@ func (d0 *digest) Sum() []byte {
 		panic("d.nx != 0")
 	}
 
-	p := make([]byte, 32)
-	j := 0
-	for _, s := range d.h {
-		p[j+0] = byte(s >> 24)
-		p[j+1] = byte(s >> 16)
-		p[j+2] = byte(s >> 8)
-		p[j+3] = byte(s >> 0)
-		j += 4
-	}
+	h := d.h[:]
+	size := Size
 	if d.is224 {
-		return p[0:28]
+		h = d.h[:7]
+		size = Size224
 	}
-	return p
+
+	var digest [Size]byte
+	for i, s := range h {
+		digest[i*4] = byte(s >> 24)
+		digest[i*4+1] = byte(s >> 16)
+		digest[i*4+2] = byte(s >> 8)
+		digest[i*4+3] = byte(s)
+	}
+
+	return append(in, digest[:size]...)
 }
diff --git a/src/pkg/crypto/sha256/sha256_test.go b/src/pkg/crypto/sha256/sha256_test.go
index 42a3fa7..a6efb37 100644
--- a/src/pkg/crypto/sha256/sha256_test.go
+++ b/src/pkg/crypto/sha256/sha256_test.go
@@ -94,10 +94,10 @@ func TestGolden(t *testing.T) {
 				io.WriteString(c, g.in)
 			} else {
 				io.WriteString(c, g.in[0:len(g.in)/2])
-				c.Sum()
+				c.Sum(nil)
 				io.WriteString(c, g.in[len(g.in)/2:])
 			}
-			s := fmt.Sprintf("%x", c.Sum())
+			s := fmt.Sprintf("%x", c.Sum(nil))
 			if s != g.out {
 				t.Fatalf("sha256[%d](%s) = %s want %s", j, g.in, s, g.out)
 			}
@@ -112,10 +112,10 @@ func TestGolden(t *testing.T) {
 				io.WriteString(c, g.in)
 			} else {
 				io.WriteString(c, g.in[0:len(g.in)/2])
-				c.Sum()
+				c.Sum(nil)
 				io.WriteString(c, g.in[len(g.in)/2:])
 			}
-			s := fmt.Sprintf("%x", c.Sum())
+			s := fmt.Sprintf("%x", c.Sum(nil))
 			if s != g.out {
 				t.Fatalf("sha224[%d](%s) = %s want %s", j, g.in, s, g.out)
 			}
diff --git a/src/pkg/crypto/sha512/sha512.go b/src/pkg/crypto/sha512/sha512.go
index 78f5fe2..a245fd6 100644
--- a/src/pkg/crypto/sha512/sha512.go
+++ b/src/pkg/crypto/sha512/sha512.go
@@ -9,7 +9,6 @@ package sha512
 import (
 	"crypto"
 	"hash"
-	"os"
 )
 
 func init() {
@@ -23,6 +22,9 @@ const Size = 64
 // The size of a SHA384 checksum in bytes.
 const Size384 = 48
 
+// The blocksize of SHA512 and SHA384 in bytes.
+const BlockSize = 128
+
 const (
 	_Chunk     = 128
 	_Init0     = 0x6a09e667f3bcc908
@@ -98,7 +100,9 @@ func (d *digest) Size() int {
 	return Size384
 }
 
-func (d *digest) Write(p []byte) (nn int, err os.Error) {
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
 	nn = len(p)
 	d.len += uint64(nn)
 	if d.nx > 0 {
@@ -124,7 +128,7 @@ func (d *digest) Write(p []byte) (nn int, err os.Error) {
 	return
 }
 
-func (d0 *digest) Sum() []byte {
+func (d0 *digest) Sum(in []byte) []byte {
 	// Make a copy of d0 so that caller can keep writing and summing.
 	d := new(digest)
 	*d = *d0
@@ -150,21 +154,24 @@ func (d0 *digest) Sum() []byte {
 		panic("d.nx != 0")
 	}
 
-	p := make([]byte, 64)
-	j := 0
-	for _, s := range d.h {
-		p[j+0] = byte(s >> 56)
-		p[j+1] = byte(s >> 48)
-		p[j+2] = byte(s >> 40)
-		p[j+3] = byte(s >> 32)
-		p[j+4] = byte(s >> 24)
-		p[j+5] = byte(s >> 16)
-		p[j+6] = byte(s >> 8)
-		p[j+7] = byte(s >> 0)
-		j += 8
-	}
+	h := d.h[:]
+	size := Size
 	if d.is384 {
-		return p[0:48]
+		h = d.h[:6]
+		size = Size384
 	}
-	return p
+
+	var digest [Size]byte
+	for i, s := range h {
+		digest[i*8] = byte(s >> 56)
+		digest[i*8+1] = byte(s >> 48)
+		digest[i*8+2] = byte(s >> 40)
+		digest[i*8+3] = byte(s >> 32)
+		digest[i*8+4] = byte(s >> 24)
+		digest[i*8+5] = byte(s >> 16)
+		digest[i*8+6] = byte(s >> 8)
+		digest[i*8+7] = byte(s)
+	}
+
+	return append(in, digest[:size]...)
 }
diff --git a/src/pkg/crypto/sha512/sha512_test.go b/src/pkg/crypto/sha512/sha512_test.go
index dd116dc..a70f7c5 100644
--- a/src/pkg/crypto/sha512/sha512_test.go
+++ b/src/pkg/crypto/sha512/sha512_test.go
@@ -94,10 +94,10 @@ func TestGolden(t *testing.T) {
 				io.WriteString(c, g.in)
 			} else {
 				io.WriteString(c, g.in[0:len(g.in)/2])
-				c.Sum()
+				c.Sum(nil)
 				io.WriteString(c, g.in[len(g.in)/2:])
 			}
-			s := fmt.Sprintf("%x", c.Sum())
+			s := fmt.Sprintf("%x", c.Sum(nil))
 			if s != g.out {
 				t.Fatalf("sha512[%d](%s) = %s want %s", j, g.in, s, g.out)
 			}
@@ -112,10 +112,10 @@ func TestGolden(t *testing.T) {
 				io.WriteString(c, g.in)
 			} else {
 				io.WriteString(c, g.in[0:len(g.in)/2])
-				c.Sum()
+				c.Sum(nil)
 				io.WriteString(c, g.in[len(g.in)/2:])
 			}
-			s := fmt.Sprintf("%x", c.Sum())
+			s := fmt.Sprintf("%x", c.Sum(nil))
 			if s != g.out {
 				t.Fatalf("sha384[%d](%s) = %s want %s", j, g.in, s, g.out)
 			}
diff --git a/src/pkg/crypto/tls/Makefile b/src/pkg/crypto/tls/Makefile
index 000314b..5cda149 100644
--- a/src/pkg/crypto/tls/Makefile
+++ b/src/pkg/crypto/tls/Makefile
@@ -17,4 +17,23 @@ GOFILES=\
 	prf.go\
 	tls.go\
 
+ifeq ($(CGO_ENABLED),1)
+CGOFILES_darwin=\
+	root_darwin.go
+else
+GOFILES_darwin+=root_stub.go
+endif
+
+GOFILES_freebsd+=root_unix.go
+GOFILES_linux+=root_unix.go
+GOFILES_netbsd+=root_unix.go
+GOFILES_openbsd+=root_unix.go
+GOFILES_plan9+=root_stub.go
+GOFILES_windows+=root_windows.go
+
+GOFILES+=$(GOFILES_$(GOOS))
+ifneq ($(CGOFILES_$(GOOS)),)
+CGOFILES+=$(CGOFILES_$(GOOS))
+endif
+
 include ../../../Make.pkg
diff --git a/src/pkg/crypto/tls/alert.go b/src/pkg/crypto/tls/alert.go
index 3b9e0e2..0856311 100644
--- a/src/pkg/crypto/tls/alert.go
+++ b/src/pkg/crypto/tls/alert.go
@@ -71,3 +71,7 @@ func (e alert) String() string {
 	}
 	return "alert(" + strconv.Itoa(int(e)) + ")"
 }
+
+func (e alert) Error() string {
+	return e.String()
+}
diff --git a/src/pkg/crypto/tls/cipher_suites.go b/src/pkg/crypto/tls/cipher_suites.go
index 77e712d..00695e7 100644
--- a/src/pkg/crypto/tls/cipher_suites.go
+++ b/src/pkg/crypto/tls/cipher_suites.go
@@ -7,12 +7,12 @@ package tls
 import (
 	"crypto/aes"
 	"crypto/cipher"
+	"crypto/des"
 	"crypto/hmac"
 	"crypto/rc4"
 	"crypto/sha1"
 	"crypto/x509"
 	"hash"
-	"os"
 )
 
 // a keyAgreement implements the client and server side of a TLS key agreement
@@ -23,20 +23,21 @@ type keyAgreement interface {
 	// In the case that the key agreement protocol doesn't use a
 	// ServerKeyExchange message, generateServerKeyExchange can return nil,
 	// nil.
-	generateServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, os.Error)
-	processClientKeyExchange(*Config, *clientKeyExchangeMsg, uint16) ([]byte, os.Error)
+	generateServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
+	processClientKeyExchange(*Config, *clientKeyExchangeMsg, uint16) ([]byte, error)
 
 	// On the client side, the next two methods are called in order.
 
 	// This method may not be called if the server doesn't send a
 	// ServerKeyExchange message.
-	processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) os.Error
-	generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error)
+	processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
+	generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
 }
 
 // A cipherSuite is a specific combination of key agreement, cipher and MAC
 // function. All cipher suites currently assume RSA key agreement.
 type cipherSuite struct {
+	id uint16
 	// the lengths, in bytes, of the key material needed for each component.
 	keyLen int
 	macLen int
@@ -50,11 +51,13 @@ type cipherSuite struct {
 	mac      func(version uint16, macKey []byte) macFunction
 }
 
-var cipherSuites = map[uint16]*cipherSuite{
-	TLS_RSA_WITH_RC4_128_SHA:           &cipherSuite{16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
-	TLS_RSA_WITH_AES_128_CBC_SHA:       &cipherSuite{16, 20, 16, rsaKA, false, cipherAES, macSHA1},
-	TLS_ECDHE_RSA_WITH_RC4_128_SHA:     &cipherSuite{16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
-	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
+var cipherSuites = []*cipherSuite{
+	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
+	{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
+	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
+	{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
+	{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
+	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
 }
 
 func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -62,6 +65,14 @@ func cipherRC4(key, iv []byte, isRead bool) interface{} {
 	return cipher
 }
 
+func cipher3DES(key, iv []byte, isRead bool) interface{} {
+	block, _ := des.NewTripleDESCipher(key)
+	if isRead {
+		return cipher.NewCBCDecrypter(block, iv)
+	}
+	return cipher.NewCBCEncrypter(block, iv)
+}
+
 func cipherAES(key, iv []byte, isRead bool) interface{} {
 	block, _ := aes.NewCipher(key)
 	if isRead {
@@ -80,12 +91,12 @@ func macSHA1(version uint16, key []byte) macFunction {
 		copy(mac.key, key)
 		return mac
 	}
-	return tls10MAC{hmac.NewSHA1(key)}
+	return tls10MAC{hmac.New(sha1.New, key)}
 }
 
 type macFunction interface {
 	Size() int
-	MAC(seq, data []byte) []byte
+	MAC(digestBuf, seq, data []byte) []byte
 }
 
 // ssl30MAC implements the SSLv3 MAC function, as defined in
@@ -103,7 +114,7 @@ var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0
 
 var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
 
-func (s ssl30MAC) MAC(seq, record []byte) []byte {
+func (s ssl30MAC) MAC(digestBuf, seq, record []byte) []byte {
 	padLength := 48
 	if s.h.Size() == 20 {
 		padLength = 40
@@ -116,13 +127,13 @@ func (s ssl30MAC) MAC(seq, record []byte) []byte {
 	s.h.Write(record[:1])
 	s.h.Write(record[3:5])
 	s.h.Write(record[recordHeaderLen:])
-	digest := s.h.Sum()
+	digestBuf = s.h.Sum(digestBuf[:0])
 
 	s.h.Reset()
 	s.h.Write(s.key)
 	s.h.Write(ssl30Pad2[:padLength])
-	s.h.Write(digest)
-	return s.h.Sum()
+	s.h.Write(digestBuf)
+	return s.h.Sum(digestBuf[:0])
 }
 
 // tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
@@ -134,11 +145,11 @@ func (s tls10MAC) Size() int {
 	return s.h.Size()
 }
 
-func (s tls10MAC) MAC(seq, record []byte) []byte {
+func (s tls10MAC) MAC(digestBuf, seq, record []byte) []byte {
 	s.h.Reset()
 	s.h.Write(seq)
 	s.h.Write(record)
-	return s.h.Sum()
+	return s.h.Sum(digestBuf[:0])
 }
 
 func rsaKA() keyAgreement {
@@ -149,22 +160,29 @@ func ecdheRSAKA() keyAgreement {
 	return new(ecdheRSAKeyAgreement)
 }
 
-// mutualCipherSuite returns a cipherSuite and its id given a list of supported
+// mutualCipherSuite returns a cipherSuite given a list of supported
 // ciphersuites and the id requested by the peer.
-func mutualCipherSuite(have []uint16, want uint16) (suite *cipherSuite, id uint16) {
+func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
 	for _, id := range have {
 		if id == want {
-			return cipherSuites[id], id
+			for _, suite := range cipherSuites {
+				if suite.id == want {
+					return suite
+				}
+			}
+			return nil
 		}
 	}
-	return
+	return nil
 }
 
 // A list of the possible cipher suite ids. Taken from
 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
 const (
-	TLS_RSA_WITH_RC4_128_SHA           uint16 = 0x0005
-	TLS_RSA_WITH_AES_128_CBC_SHA       uint16 = 0x002f
-	TLS_ECDHE_RSA_WITH_RC4_128_SHA     uint16 = 0xc011
-	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
+	TLS_RSA_WITH_RC4_128_SHA            uint16 = 0x0005
+	TLS_RSA_WITH_3DES_EDE_CBC_SHA       uint16 = 0x000a
+	TLS_RSA_WITH_AES_128_CBC_SHA        uint16 = 0x002f
+	TLS_ECDHE_RSA_WITH_RC4_128_SHA      uint16 = 0xc011
+	TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
+	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA  uint16 = 0xc013
 )
diff --git a/src/pkg/crypto/tls/common.go b/src/pkg/crypto/tls/common.go
index 8fb1a88..25f7a92 100644
--- a/src/pkg/crypto/tls/common.go
+++ b/src/pkg/crypto/tls/common.go
@@ -5,11 +5,11 @@
 package tls
 
 import (
+	"crypto"
 	"crypto/rand"
-	"crypto/rsa"
 	"crypto/x509"
 	"io"
-	"io/ioutil"
+	"strings"
 	"sync"
 	"time"
 )
@@ -101,12 +101,28 @@ type ConnectionState struct {
 	NegotiatedProtocol         string
 	NegotiatedProtocolIsMutual bool
 
+	// ServerName contains the server name indicated by the client, if any.
+	// (Only valid for server connections.)
+	ServerName string
+
 	// the certificate chain that was presented by the other side
 	PeerCertificates []*x509.Certificate
 	// the verified certificate chains built from PeerCertificates.
 	VerifiedChains [][]*x509.Certificate
 }
 
+// ClientAuthType declares the policy the server will follow for
+// TLS Client Authentication.
+type ClientAuthType int
+
+const (
+	NoClientCert ClientAuthType = iota
+	RequestClientCert
+	RequireAnyClientCert
+	VerifyClientCertIfGiven
+	RequireAndVerifyClientCert
+)
+
 // A Config structure is used to configure a TLS client or server. After one
 // has been passed to a TLS function it must not be modified.
 type Config struct {
@@ -116,14 +132,22 @@ type Config struct {
 	Rand io.Reader
 
 	// Time returns the current time as the number of seconds since the epoch.
-	// If Time is nil, TLS uses the system time.Seconds.
-	Time func() int64
+	// If Time is nil, TLS uses time.Now.
+	Time func() time.Time
 
 	// Certificates contains one or more certificate chains
 	// to present to the other side of the connection.
 	// Server configurations must include at least one certificate.
 	Certificates []Certificate
 
+	// NameToCertificate maps from a certificate name to an element of
+	// Certificates. Note that a certificate name can be of the form
+	// '*.example.com' and so doesn't have to be a domain name as such.
+	// See Config.BuildNameToCertificate
+	// The nil value causes the first element of Certificates to be used
+	// for all connections.
+	NameToCertificate map[string]*Certificate
+
 	// RootCAs defines the set of root certificate authorities
 	// that clients use when verifying server certificates.
 	// If RootCAs is nil, TLS uses the host's root CA set.
@@ -136,11 +160,22 @@ type Config struct {
 	// hosting.
 	ServerName string
 
-	// AuthenticateClient controls whether a server will request a certificate
-	// from the client. It does not require that the client send a
-	// certificate nor does it require that the certificate sent be
-	// anything more than self-signed.
-	AuthenticateClient bool
+	// ClientAuth determines the server's policy for
+	// TLS Client Authentication. The default is NoClientCert.
+	ClientAuth ClientAuthType
+
+	// ClientCAs defines the set of root certificate authorities
+	// that servers use if required to verify a client certificate
+	// by the policy in ClientAuth.
+	ClientCAs *x509.CertPool
+
+	// InsecureSkipVerify controls whether a client verifies the
+	// server's certificate chain and host name.
+	// If InsecureSkipVerify is true, TLS accepts any certificate
+	// presented by the server and any host name in that certificate.
+	// In this mode, TLS is susceptible to man-in-the-middle attacks.
+	// This should be used only for testing.
+	InsecureSkipVerify bool
 
 	// CipherSuites is a list of supported cipher suites. If CipherSuites
 	// is nil, TLS uses a list of suites supported by the implementation.
@@ -155,10 +190,10 @@ func (c *Config) rand() io.Reader {
 	return r
 }
 
-func (c *Config) time() int64 {
+func (c *Config) time() time.Time {
 	t := c.Time
 	if t == nil {
-		t = time.Seconds
+		t = time.Now
 	}
 	return t()
 }
@@ -179,13 +214,71 @@ func (c *Config) cipherSuites() []uint16 {
 	return s
 }
 
+// getCertificateForName returns the best certificate for the given name,
+// defaulting to the first element of c.Certificates if there are no good
+// options.
+func (c *Config) getCertificateForName(name string) *Certificate {
+	if len(c.Certificates) == 1 || c.NameToCertificate == nil {
+		// There's only one choice, so no point doing any work.
+		return &c.Certificates[0]
+	}
+
+	name = strings.ToLower(name)
+	for len(name) > 0 && name[len(name)-1] == '.' {
+		name = name[:len(name)-1]
+	}
+
+	if cert, ok := c.NameToCertificate[name]; ok {
+		return cert
+	}
+
+	// try replacing labels in the name with wildcards until we get a
+	// match.
+	labels := strings.Split(name, ".")
+	for i := range labels {
+		labels[i] = "*"
+		candidate := strings.Join(labels, ".")
+		if cert, ok := c.NameToCertificate[candidate]; ok {
+			return cert
+		}
+	}
+
+	// If nothing matches, return the first certificate.
+	return &c.Certificates[0]
+}
+
+// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
+// from the CommonName and SubjectAlternateName fields of each of the leaf
+// certificates.
+func (c *Config) BuildNameToCertificate() {
+	c.NameToCertificate = make(map[string]*Certificate)
+	for i := range c.Certificates {
+		cert := &c.Certificates[i]
+		x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
+		if err != nil {
+			continue
+		}
+		if len(x509Cert.Subject.CommonName) > 0 {
+			c.NameToCertificate[x509Cert.Subject.CommonName] = cert
+		}
+		for _, san := range x509Cert.DNSNames {
+			c.NameToCertificate[san] = cert
+		}
+	}
+}
+
 // A Certificate is a chain of one or more certificates, leaf first.
 type Certificate struct {
 	Certificate [][]byte
-	PrivateKey  *rsa.PrivateKey
+	PrivateKey  crypto.PrivateKey // supported types: *rsa.PrivateKey
 	// OCSPStaple contains an optional OCSP response which will be served
 	// to clients that request it.
 	OCSPStaple []byte
+	// Leaf is the parsed form of the leaf certificate, which may be
+	// initialized using x509.ParseCertificate to reduce per-handshake
+	// processing for TLS clients doing client authentication. If nil, the
+	// leaf certificate will be parsed as needed.
+	Leaf *x509.Certificate
 }
 
 // A TLS record.
@@ -218,15 +311,6 @@ func defaultConfig() *Config {
 	return &emptyConfig
 }
 
-// Possible certificate files; stop after finding one.
-// On OS X we should really be using the Directory Services keychain
-// but that requires a lot of Mach goo to get at.  Instead we use
-// the same root set that curl uses.
-var certFiles = []string{
-	"/etc/ssl/certs/ca-certificates.crt", // Linux etc
-	"/usr/share/curl/curl-ca-bundle.crt", // OS X
-}
-
 var once sync.Once
 
 func defaultRoots() *x509.CertPool {
@@ -244,27 +328,14 @@ func initDefaults() {
 	initDefaultCipherSuites()
 }
 
-var varDefaultRoots *x509.CertPool
-
-func initDefaultRoots() {
-	roots := x509.NewCertPool()
-	for _, file := range certFiles {
-		data, err := ioutil.ReadFile(file)
-		if err == nil {
-			roots.AppendCertsFromPEM(data)
-			break
-		}
-	}
-	varDefaultRoots = roots
-}
-
-var varDefaultCipherSuites []uint16
+var (
+	varDefaultRoots        *x509.CertPool
+	varDefaultCipherSuites []uint16
+)
 
 func initDefaultCipherSuites() {
 	varDefaultCipherSuites = make([]uint16, len(cipherSuites))
-	i := 0
-	for id := range cipherSuites {
-		varDefaultCipherSuites[i] = id
-		i++
+	for i, suite := range cipherSuites {
+		varDefaultCipherSuites[i] = suite.id
 	}
 }
diff --git a/src/pkg/crypto/tls/conn.go b/src/pkg/crypto/tls/conn.go
index 0719951..e6cee12 100644
--- a/src/pkg/crypto/tls/conn.go
+++ b/src/pkg/crypto/tls/conn.go
@@ -11,10 +11,11 @@ import (
 	"crypto/cipher"
 	"crypto/subtle"
 	"crypto/x509"
+	"errors"
 	"io"
 	"net"
-	"os"
 	"sync"
+	"time"
 )
 
 // A Conn represents a secured connection.
@@ -36,13 +37,15 @@ type Conn struct {
 	// verifiedChains contains the certificate chains that we built, as
 	// opposed to the ones presented by the server.
 	verifiedChains [][]*x509.Certificate
+	// serverName contains the server name indicated by the client, if any.
+	serverName string
 
 	clientProtocol         string
 	clientProtocolFallback bool
 
 	// first permanent error
 	errMutex sync.Mutex
-	err      os.Error
+	err      error
 
 	// input/output
 	in, out  halfConn     // in.Mutex < out.Mutex
@@ -53,7 +56,7 @@ type Conn struct {
 	tmp [16]byte
 }
 
-func (c *Conn) setError(err os.Error) os.Error {
+func (c *Conn) setError(err error) error {
 	c.errMutex.Lock()
 	defer c.errMutex.Unlock()
 
@@ -63,7 +66,7 @@ func (c *Conn) setError(err os.Error) os.Error {
 	return err
 }
 
-func (c *Conn) error() os.Error {
+func (c *Conn) error() error {
 	c.errMutex.Lock()
 	defer c.errMutex.Unlock()
 
@@ -84,23 +87,23 @@ func (c *Conn) RemoteAddr() net.Addr {
 	return c.conn.RemoteAddr()
 }
 
-// SetTimeout sets the read deadline associated with the connection.
+// SetDeadline sets the read deadline associated with the connection.
 // There is no write deadline.
-func (c *Conn) SetTimeout(nsec int64) os.Error {
-	return c.conn.SetTimeout(nsec)
+// A zero value for t means Read will not time out.
+func (c *Conn) SetDeadline(t time.Time) error {
+	return c.conn.SetDeadline(t)
 }
 
-// SetReadTimeout sets the time (in nanoseconds) that
-// Read will wait for data before returning os.EAGAIN.
-// Setting nsec == 0 (the default) disables the deadline.
-func (c *Conn) SetReadTimeout(nsec int64) os.Error {
-	return c.conn.SetReadTimeout(nsec)
+// SetReadDeadline sets the read deadline on the underlying connection.
+// A zero value for t means Read will not time out.
+func (c *Conn) SetReadDeadline(t time.Time) error {
+	return c.conn.SetReadDeadline(t)
 }
 
-// SetWriteTimeout exists to satisfy the net.Conn interface
+// SetWriteDeadline exists to satisfy the net.Conn interface
 // but is not implemented by TLS.  It always returns an error.
-func (c *Conn) SetWriteTimeout(nsec int64) os.Error {
-	return os.NewError("TLS does not support SetWriteTimeout")
+func (c *Conn) SetWriteDeadline(t time.Time) error {
+	return errors.New("TLS does not support SetWriteDeadline")
 }
 
 // A halfConn represents one direction of the record layer
@@ -115,6 +118,9 @@ type halfConn struct {
 
 	nextCipher interface{} // next encryption state
 	nextMac    macFunction // next MAC algorithm
+
+	// used to save allocating a new buffer for each MAC.
+	inDigestBuf, outDigestBuf []byte
 }
 
 // prepareCipherSpec sets the encryption and MAC states
@@ -127,7 +133,7 @@ func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac ma
 
 // changeCipherSpec changes the encryption and MAC states
 // to the ones previously passed to prepareCipherSpec.
-func (hc *halfConn) changeCipherSpec() os.Error {
+func (hc *halfConn) changeCipherSpec() error {
 	if hc.nextCipher == nil {
 		return alertInternalError
 	}
@@ -277,12 +283,13 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
 		b.data[4] = byte(n)
 		b.resize(recordHeaderLen + n)
 		remoteMAC := payload[n:]
-		localMAC := hc.mac.MAC(hc.seq[0:], b.data)
+		localMAC := hc.mac.MAC(hc.inDigestBuf, hc.seq[0:], b.data)
 		hc.incSeq()
 
 		if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
 			return false, alertBadRecordMAC
 		}
+		hc.inDigestBuf = localMAC
 	}
 
 	return true, 0
@@ -309,12 +316,13 @@ func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
 func (hc *halfConn) encrypt(b *block) (bool, alert) {
 	// mac
 	if hc.mac != nil {
-		mac := hc.mac.MAC(hc.seq[0:], b.data)
+		mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data)
 		hc.incSeq()
 
 		n := len(b.data)
 		b.resize(n + len(mac))
 		copy(b.data[n:], mac)
+		hc.outDigestBuf = mac
 	}
 
 	payload := b.data[recordHeaderLen:]
@@ -376,7 +384,7 @@ func (b *block) reserve(n int) {
 
 // readFromUntil reads from r into b until b contains at least n bytes
 // or else returns an error.
-func (b *block) readFromUntil(r io.Reader, n int) os.Error {
+func (b *block) readFromUntil(r io.Reader, n int) error {
 	// quick case
 	if len(b.data) >= n {
 		return nil
@@ -397,7 +405,7 @@ func (b *block) readFromUntil(r io.Reader, n int) os.Error {
 	return nil
 }
 
-func (b *block) Read(p []byte) (n int, err os.Error) {
+func (b *block) Read(p []byte) (n int, err error) {
 	n = copy(p, b.data[b.off:])
 	b.off += n
 	return
@@ -441,7 +449,7 @@ func (hc *halfConn) splitBlock(b *block, n int) (*block, *block) {
 // readRecord reads the next TLS record from the connection
 // and updates the record layer state.
 // c.in.Mutex <= L; c.input == nil.
-func (c *Conn) readRecord(want recordType) os.Error {
+func (c *Conn) readRecord(want recordType) error {
 	// Caller must be in sync with connection:
 	// handshake data if handshake not yet completed,
 	// else application data.  (We don't support renegotiation.)
@@ -469,7 +477,7 @@ Again:
 		// RFC suggests that EOF without an alertCloseNotify is
 		// an error, but popular web sites seem to do this,
 		// so we can't make it an error.
-		// if err == os.EOF {
+		// if err == io.EOF {
 		// 	err = io.ErrUnexpectedEOF
 		// }
 		if e, ok := err.(net.Error); !ok || !e.Temporary() {
@@ -500,7 +508,7 @@ Again:
 		}
 	}
 	if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil {
-		if err == os.EOF {
+		if err == io.EOF {
 			err = io.ErrUnexpectedEOF
 		}
 		if e, ok := err.(net.Error); !ok || !e.Temporary() {
@@ -532,7 +540,7 @@ Again:
 			break
 		}
 		if alert(data[1]) == alertCloseNotify {
-			c.setError(os.EOF)
+			c.setError(io.EOF)
 			break
 		}
 		switch data[0] {
@@ -541,7 +549,7 @@ Again:
 			c.in.freeBlock(b)
 			goto Again
 		case alertLevelError:
-			c.setError(&net.OpError{Op: "remote error", Error: alert(data[1])})
+			c.setError(&net.OpError{Op: "remote error", Err: alert(data[1])})
 		default:
 			c.sendAlert(alertUnexpectedMessage)
 		}
@@ -580,7 +588,7 @@ Again:
 
 // sendAlert sends a TLS alert message.
 // c.out.Mutex <= L.
-func (c *Conn) sendAlertLocked(err alert) os.Error {
+func (c *Conn) sendAlertLocked(err alert) error {
 	c.tmp[0] = alertLevelError
 	if err == alertNoRenegotiation {
 		c.tmp[0] = alertLevelWarning
@@ -589,14 +597,14 @@ func (c *Conn) sendAlertLocked(err alert) os.Error {
 	c.writeRecord(recordTypeAlert, c.tmp[0:2])
 	// closeNotify is a special case in that it isn't an error:
 	if err != alertCloseNotify {
-		return c.setError(&net.OpError{Op: "local error", Error: err})
+		return c.setError(&net.OpError{Op: "local error", Err: err})
 	}
 	return nil
 }
 
 // sendAlert sends a TLS alert message.
 // L < c.out.Mutex.
-func (c *Conn) sendAlert(err alert) os.Error {
+func (c *Conn) sendAlert(err alert) error {
 	c.out.Lock()
 	defer c.out.Unlock()
 	return c.sendAlertLocked(err)
@@ -605,7 +613,7 @@ func (c *Conn) sendAlert(err alert) os.Error {
 // writeRecord writes a TLS record with the given type and payload
 // to the connection and updates the record layer state.
 // c.out.Mutex <= L.
-func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err os.Error) {
+func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
 	b := c.out.newBlock()
 	for len(data) > 0 {
 		m := len(data)
@@ -641,7 +649,7 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err os.Error) {
 			c.tmp[0] = alertLevelError
 			c.tmp[1] = byte(err.(alert))
 			c.writeRecord(recordTypeAlert, c.tmp[0:2])
-			c.err = &net.OpError{Op: "local error", Error: err}
+			c.err = &net.OpError{Op: "local error", Err: err}
 			return n, c.err
 		}
 	}
@@ -651,12 +659,14 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err os.Error) {
 // readHandshake reads the next handshake message from
 // the record layer.
 // c.in.Mutex < L; c.out.Mutex < L.
-func (c *Conn) readHandshake() (interface{}, os.Error) {
+func (c *Conn) readHandshake() (interface{}, error) {
 	for c.hand.Len() < 4 {
 		if c.err != nil {
 			return nil, c.err
 		}
-		c.readRecord(recordTypeHandshake)
+		if err := c.readRecord(recordTypeHandshake); err != nil {
+			return nil, err
+		}
 	}
 
 	data := c.hand.Bytes()
@@ -669,7 +679,9 @@ func (c *Conn) readHandshake() (interface{}, os.Error) {
 		if c.err != nil {
 			return nil, c.err
 		}
-		c.readRecord(recordTypeHandshake)
+		if err := c.readRecord(recordTypeHandshake); err != nil {
+			return nil, err
+		}
 	}
 	data = c.hand.Next(4 + n)
 	var m handshakeMessage
@@ -714,7 +726,7 @@ func (c *Conn) readHandshake() (interface{}, os.Error) {
 }
 
 // Write writes data to the connection.
-func (c *Conn) Write(b []byte) (n int, err os.Error) {
+func (c *Conn) Write(b []byte) (n int, err error) {
 	if err = c.Handshake(); err != nil {
 		return
 	}
@@ -731,9 +743,9 @@ func (c *Conn) Write(b []byte) (n int, err os.Error) {
 	return c.writeRecord(recordTypeApplicationData, b)
 }
 
-// Read can be made to time out and return err == os.EAGAIN
-// after a fixed time limit; see SetTimeout and SetReadTimeout.
-func (c *Conn) Read(b []byte) (n int, err os.Error) {
+// Read can be made to time out and return a net.Error with Timeout() == true
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
+func (c *Conn) Read(b []byte) (n int, err error) {
 	if err = c.Handshake(); err != nil {
 		return
 	}
@@ -759,18 +771,26 @@ func (c *Conn) Read(b []byte) (n int, err os.Error) {
 }
 
 // Close closes the connection.
-func (c *Conn) Close() os.Error {
-	if err := c.Handshake(); err != nil {
+func (c *Conn) Close() error {
+	var alertErr error
+
+	c.handshakeMutex.Lock()
+	defer c.handshakeMutex.Unlock()
+	if c.handshakeComplete {
+		alertErr = c.sendAlert(alertCloseNotify)
+	}
+
+	if err := c.conn.Close(); err != nil {
 		return err
 	}
-	return c.sendAlert(alertCloseNotify)
+	return alertErr
 }
 
 // Handshake runs the client or server handshake
 // protocol if it has not yet been run.
 // Most uses of this package need not call Handshake
 // explicitly: the first Read or Write will call it automatically.
-func (c *Conn) Handshake() os.Error {
+func (c *Conn) Handshake() error {
 	c.handshakeMutex.Lock()
 	defer c.handshakeMutex.Unlock()
 	if err := c.error(); err != nil {
@@ -798,6 +818,7 @@ func (c *Conn) ConnectionState() ConnectionState {
 		state.CipherSuite = c.cipherSuite
 		state.PeerCertificates = c.peerCertificates
 		state.VerifiedChains = c.verifiedChains
+		state.ServerName = c.serverName
 	}
 
 	return state
@@ -813,16 +834,16 @@ func (c *Conn) OCSPResponse() []byte {
 }
 
 // VerifyHostname checks that the peer certificate chain is valid for
-// connecting to host.  If so, it returns nil; if not, it returns an os.Error
+// connecting to host.  If so, it returns nil; if not, it returns an error
 // describing the problem.
-func (c *Conn) VerifyHostname(host string) os.Error {
+func (c *Conn) VerifyHostname(host string) error {
 	c.handshakeMutex.Lock()
 	defer c.handshakeMutex.Unlock()
 	if !c.isClient {
-		return os.NewError("VerifyHostname called on TLS server connection")
+		return errors.New("VerifyHostname called on TLS server connection")
 	}
 	if !c.handshakeComplete {
-		return os.NewError("TLS handshake has not yet been performed")
+		return errors.New("TLS handshake has not yet been performed")
 	}
 	return c.peerCertificates[0].VerifyHostname(host)
 }
diff --git a/src/pkg/crypto/tls/conn_test.go b/src/pkg/crypto/tls/conn_test.go
index f44a50b..5c55514 100644
--- a/src/pkg/crypto/tls/conn_test.go
+++ b/src/pkg/crypto/tls/conn_test.go
@@ -50,3 +50,57 @@ func TestRemovePadding(t *testing.T) {
 		}
 	}
 }
+
+var certExampleCom = `308201403081eda003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313138353835325a170d3132303933303138353835325a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31a301830160603551d11040f300d820b6578616d706c652e636f6d300b06092a864886f70d0101050341001a0b419d2c74474c6450654e5f10b32bf426ffdf55cad1c52602e7a9151513a3424c70f5960dcd682db0c33769cc1daa3fcdd3db10809d2392ed4a1bf50ced18`
+
+var certWildcardExampleCom = `308201423081efa003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303034365a170d3132303933303139303034365a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31c301a30180603551d110411300f820d2a2e6578616d706c652e636f6d300b06092a864886f70d0101050341001676f0c9e7c33c1b656ed5a6476c4e2ee9ec8e62df7407accb1875272b2edd0a22096cb2c22598d11604104d604f810eb4b5987ca6bb319c7e6ce48725c54059`
+
+var certFooExampleCom = `308201443081f1a003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303131345a170d3132303933303139303131345a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31e301c301a0603551d1104133011820f666f6f2e6578616d706c652e636f6d300b06092a864886f70d010105034100646a2a51f2aa2477add854b462cf5207ba16d3213ffb5d3d0eed473fbf09935019192d1d5b8ca6a2407b424cf04d97c4cd9197c83ecf81f0eab9464a1109d09f`
+
+var certDoubleWildcardExampleCom = `308201443081f1a003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303134315a170d3132303933303139303134315a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31e301c301a0603551d1104133011820f2a2e2a2e6578616d706c652e636f6d300b06092a864886f70d0101050341001c3de267975f56ef57771c6218ef95ecc65102e57bd1defe6f7efea90d9b26cf40de5bd7ad75e46201c7f2a92aaa3e907451e9409f65e28ddb6db80d726290f6`
+
+func TestCertificateSelection(t *testing.T) {
+	config := Config{
+		Certificates: []Certificate{
+			{
+				Certificate: [][]byte{fromHex(certExampleCom)},
+			},
+			{
+				Certificate: [][]byte{fromHex(certWildcardExampleCom)},
+			},
+			{
+				Certificate: [][]byte{fromHex(certFooExampleCom)},
+			},
+			{
+				Certificate: [][]byte{fromHex(certDoubleWildcardExampleCom)},
+			},
+		},
+	}
+
+	config.BuildNameToCertificate()
+
+	pointerToIndex := func(c *Certificate) int {
+		for i := range config.Certificates {
+			if c == &config.Certificates[i] {
+				return i
+			}
+		}
+		return -1
+	}
+
+	if n := pointerToIndex(config.getCertificateForName("example.com")); n != 0 {
+		t.Errorf("example.com returned certificate %d, not 0", n)
+	}
+	if n := pointerToIndex(config.getCertificateForName("bar.example.com")); n != 1 {
+		t.Errorf("bar.example.com returned certificate %d, not 1", n)
+	}
+	if n := pointerToIndex(config.getCertificateForName("foo.example.com")); n != 2 {
+		t.Errorf("foo.example.com returned certificate %d, not 2", n)
+	}
+	if n := pointerToIndex(config.getCertificateForName("foo.bar.example.com")); n != 3 {
+		t.Errorf("foo.bar.example.com returned certificate %d, not 3", n)
+	}
+	if n := pointerToIndex(config.getCertificateForName("foo.bar.baz.example.com")); n != 0 {
+		t.Errorf("foo.bar.baz.example.com returned certificate %d, not 0", n)
+	}
+}
diff --git a/src/pkg/crypto/tls/generate_cert.go b/src/pkg/crypto/tls/generate_cert.go
index 41206e2..7c0718b 100644
--- a/src/pkg/crypto/tls/generate_cert.go
+++ b/src/pkg/crypto/tls/generate_cert.go
@@ -8,14 +8,14 @@
 package main
 
 import (
-	"big"
-	"crypto/x509/pkix"
 	"crypto/rand"
 	"crypto/rsa"
 	"crypto/x509"
+	"crypto/x509/pkix"
 	"encoding/pem"
 	"flag"
 	"log"
+	"math/big"
 	"os"
 	"time"
 )
@@ -31,7 +31,7 @@ func main() {
 		return
 	}
 
-	now := time.Seconds()
+	now := time.Now()
 
 	template := x509.Certificate{
 		SerialNumber: new(big.Int).SetInt64(0),
@@ -39,8 +39,8 @@ func main() {
 			CommonName:   *hostName,
 			Organization: []string{"Acme Co"},
 		},
-		NotBefore: time.SecondsToUTC(now - 300),
-		NotAfter:  time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.
+		NotBefore: now.Add(-5 * time.Minute).UTC(),
+		NotAfter:  now.AddDate(1, 0, 0).UTC(), // valid for 1 year.
 
 		SubjectKeyId: []byte{1, 2, 3, 4},
 		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
diff --git a/src/pkg/crypto/tls/handshake_client.go b/src/pkg/crypto/tls/handshake_client.go
index 0badc39..632ceea 100644
--- a/src/pkg/crypto/tls/handshake_client.go
+++ b/src/pkg/crypto/tls/handshake_client.go
@@ -5,15 +5,17 @@
 package tls
 
 import (
+	"bytes"
 	"crypto"
 	"crypto/rsa"
 	"crypto/subtle"
 	"crypto/x509"
+	"errors"
 	"io"
-	"os"
+	"strconv"
 )
 
-func (c *Conn) clientHandshake() os.Error {
+func (c *Conn) clientHandshake() error {
 	finishedHash := newFinishedHash(versionTLS10)
 
 	if c.config == nil {
@@ -32,7 +34,7 @@ func (c *Conn) clientHandshake() os.Error {
 		nextProtoNeg:       len(c.config.NextProtos) > 0,
 	}
 
-	t := uint32(c.config.time())
+	t := uint32(c.config.time().Unix())
 	hello.random[0] = byte(t >> 24)
 	hello.random[1] = byte(t >> 16)
 	hello.random[2] = byte(t >> 8)
@@ -40,7 +42,7 @@ func (c *Conn) clientHandshake() os.Error {
 	_, err := io.ReadFull(c.config.rand(), hello.random[4:])
 	if err != nil {
 		c.sendAlert(alertInternalError)
-		return os.NewError("short read from Rand")
+		return errors.New("short read from Rand")
 	}
 
 	finishedHash.Write(hello.marshal())
@@ -69,10 +71,10 @@ func (c *Conn) clientHandshake() os.Error {
 
 	if !hello.nextProtoNeg && serverHello.nextProtoNeg {
 		c.sendAlert(alertHandshakeFailure)
-		return os.NewError("server advertised unrequested NPN")
+		return errors.New("server advertised unrequested NPN")
 	}
 
-	suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
+	suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
 	if suite == nil {
 		return c.sendAlert(alertHandshakeFailure)
 	}
@@ -92,16 +94,14 @@ func (c *Conn) clientHandshake() os.Error {
 		cert, err := x509.ParseCertificate(asn1Data)
 		if err != nil {
 			c.sendAlert(alertBadCertificate)
-			return os.NewError("failed to parse certificate from server: " + err.String())
+			return errors.New("failed to parse certificate from server: " + err.Error())
 		}
 		certs[i] = cert
 	}
 
-	// If we don't have a root CA set configured then anything is accepted.
-	// TODO(rsc): Find certificates for OS X 10.6.
-	if c.config.RootCAs != nil {
+	if !c.config.InsecureSkipVerify {
 		opts := x509.VerifyOptions{
-			Roots:         c.config.RootCAs,
+			Roots:         c.config.rootCAs(),
 			CurrentTime:   c.config.time(),
 			DNSName:       c.config.ServerName,
 			Intermediates: x509.NewCertPool(),
@@ -164,10 +164,23 @@ func (c *Conn) clientHandshake() os.Error {
 		}
 	}
 
-	transmitCert := false
+	var certToSend *Certificate
 	certReq, ok := msg.(*certificateRequestMsg)
 	if ok {
-		// We only accept certificates with RSA keys.
+		// RFC 4346 on the certificateAuthorities field:
+		// A list of the distinguished names of acceptable certificate
+		// authorities. These distinguished names may specify a desired
+		// distinguished name for a root CA or for a subordinate CA;
+		// thus, this message can be used to describe both known roots
+		// and a desired authorization space. If the
+		// certificate_authorities list is empty then the client MAY
+		// send any certificate of the appropriate
+		// ClientCertificateType, unless there is some external
+		// arrangement to the contrary.
+
+		finishedHash.Write(certReq.marshal())
+
+		// For now, we only know how to sign challenges with RSA
 		rsaAvail := false
 		for _, certType := range certReq.certificateTypes {
 			if certType == certTypeRSASign {
@@ -176,23 +189,41 @@ func (c *Conn) clientHandshake() os.Error {
 			}
 		}
 
-		// For now, only send a certificate back if the server gives us an
-		// empty list of certificateAuthorities.
-		//
-		// RFC 4346 on the certificateAuthorities field:
-		// A list of the distinguished names of acceptable certificate
-		// authorities.  These distinguished names may specify a desired
-		// distinguished name for a root CA or for a subordinate CA; thus,
-		// this message can be used to describe both known roots and a
-		// desired authorization space.  If the certificate_authorities
-		// list is empty then the client MAY send any certificate of the
-		// appropriate ClientCertificateType, unless there is some
-		// external arrangement to the contrary.
-		if rsaAvail && len(certReq.certificateAuthorities) == 0 {
-			transmitCert = true
-		}
+		// We need to search our list of client certs for one
+		// where SignatureAlgorithm is RSA and the Issuer is in
+		// certReq.certificateAuthorities
+	findCert:
+		for i, cert := range c.config.Certificates {
+			if !rsaAvail {
+				continue
+			}
 
-		finishedHash.Write(certReq.marshal())
+			leaf := cert.Leaf
+			if leaf == nil {
+				if leaf, err = x509.ParseCertificate(cert.Certificate[0]); err != nil {
+					c.sendAlert(alertInternalError)
+					return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+				}
+			}
+
+			if leaf.PublicKeyAlgorithm != x509.RSA {
+				continue
+			}
+
+			if len(certReq.certificateAuthorities) == 0 {
+				// they gave us an empty list, so just take the
+				// first RSA cert from c.config.Certificates
+				certToSend = &cert
+				break
+			}
+
+			for _, ca := range certReq.certificateAuthorities {
+				if bytes.Equal(leaf.RawIssuer, ca) {
+					certToSend = &cert
+					break findCert
+				}
+			}
+		}
 
 		msg, err = c.readHandshake()
 		if err != nil {
@@ -206,17 +237,9 @@ func (c *Conn) clientHandshake() os.Error {
 	}
 	finishedHash.Write(shd.marshal())
 
-	var cert *x509.Certificate
-	if transmitCert {
+	if certToSend != nil {
 		certMsg = new(certificateMsg)
-		if len(c.config.Certificates) > 0 {
-			cert, err = x509.ParseCertificate(c.config.Certificates[0].Certificate[0])
-			if err == nil && cert.PublicKeyAlgorithm == x509.RSA {
-				certMsg.certificates = c.config.Certificates[0].Certificate
-			} else {
-				cert = nil
-			}
-		}
+		certMsg.certificates = certToSend.Certificate
 		finishedHash.Write(certMsg.marshal())
 		c.writeRecord(recordTypeHandshake, certMsg.marshal())
 	}
@@ -231,12 +254,12 @@ func (c *Conn) clientHandshake() os.Error {
 		c.writeRecord(recordTypeHandshake, ckx.marshal())
 	}
 
-	if cert != nil {
+	if certToSend != nil {
 		certVerify := new(certificateVerifyMsg)
-		var digest [36]byte
-		copy(digest[0:16], finishedHash.serverMD5.Sum())
-		copy(digest[16:36], finishedHash.serverSHA1.Sum())
-		signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest[0:])
+		digest := make([]byte, 0, 36)
+		digest = finishedHash.serverMD5.Sum(digest)
+		digest = finishedHash.serverSHA1.Sum(digest)
+		signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, digest)
 		if err != nil {
 			return c.sendAlert(alertInternalError)
 		}
@@ -294,7 +317,7 @@ func (c *Conn) clientHandshake() os.Error {
 	}
 
 	c.handshakeComplete = true
-	c.cipherSuite = suiteId
+	c.cipherSuite = suite.id
 	return nil
 }
 
diff --git a/src/pkg/crypto/tls/handshake_messages.go b/src/pkg/crypto/tls/handshake_messages.go
index f11232d..e1517cc 100644
--- a/src/pkg/crypto/tls/handshake_messages.go
+++ b/src/pkg/crypto/tls/handshake_messages.go
@@ -4,6 +4,8 @@
 
 package tls
 
+import "bytes"
+
 type clientHelloMsg struct {
 	raw                []byte
 	vers               uint16
@@ -18,6 +20,25 @@ type clientHelloMsg struct {
 	supportedPoints    []uint8
 }
 
+func (m *clientHelloMsg) equal(i interface{}) bool {
+	m1, ok := i.(*clientHelloMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.vers == m1.vers &&
+		bytes.Equal(m.random, m1.random) &&
+		bytes.Equal(m.sessionId, m1.sessionId) &&
+		eqUint16s(m.cipherSuites, m1.cipherSuites) &&
+		bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
+		m.nextProtoNeg == m1.nextProtoNeg &&
+		m.serverName == m1.serverName &&
+		m.ocspStapling == m1.ocspStapling &&
+		eqUint16s(m.supportedCurves, m1.supportedCurves) &&
+		bytes.Equal(m.supportedPoints, m1.supportedPoints)
+}
+
 func (m *clientHelloMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
@@ -309,6 +330,23 @@ type serverHelloMsg struct {
 	ocspStapling      bool
 }
 
+func (m *serverHelloMsg) equal(i interface{}) bool {
+	m1, ok := i.(*serverHelloMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.vers == m1.vers &&
+		bytes.Equal(m.random, m1.random) &&
+		bytes.Equal(m.sessionId, m1.sessionId) &&
+		m.cipherSuite == m1.cipherSuite &&
+		m.compressionMethod == m1.compressionMethod &&
+		m.nextProtoNeg == m1.nextProtoNeg &&
+		eqStrings(m.nextProtos, m1.nextProtos) &&
+		m.ocspStapling == m1.ocspStapling
+}
+
 func (m *serverHelloMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
@@ -463,6 +501,16 @@ type certificateMsg struct {
 	certificates [][]byte
 }
 
+func (m *certificateMsg) equal(i interface{}) bool {
+	m1, ok := i.(*certificateMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		eqByteSlices(m.certificates, m1.certificates)
+}
+
 func (m *certificateMsg) marshal() (x []byte) {
 	if m.raw != nil {
 		return m.raw
@@ -540,6 +588,16 @@ type serverKeyExchangeMsg struct {
 	key []byte
 }
 
+func (m *serverKeyExchangeMsg) equal(i interface{}) bool {
+	m1, ok := i.(*serverKeyExchangeMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.key, m1.key)
+}
+
 func (m *serverKeyExchangeMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
@@ -571,6 +629,17 @@ type certificateStatusMsg struct {
 	response   []byte
 }
 
+func (m *certificateStatusMsg) equal(i interface{}) bool {
+	m1, ok := i.(*certificateStatusMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.statusType == m1.statusType &&
+		bytes.Equal(m.response, m1.response)
+}
+
 func (m *certificateStatusMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
@@ -622,6 +691,11 @@ func (m *certificateStatusMsg) unmarshal(data []byte) bool {
 
 type serverHelloDoneMsg struct{}
 
+func (m *serverHelloDoneMsg) equal(i interface{}) bool {
+	_, ok := i.(*serverHelloDoneMsg)
+	return ok
+}
+
 func (m *serverHelloDoneMsg) marshal() []byte {
 	x := make([]byte, 4)
 	x[0] = typeServerHelloDone
@@ -637,6 +711,16 @@ type clientKeyExchangeMsg struct {
 	ciphertext []byte
 }
 
+func (m *clientKeyExchangeMsg) equal(i interface{}) bool {
+	m1, ok := i.(*clientKeyExchangeMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.ciphertext, m1.ciphertext)
+}
+
 func (m *clientKeyExchangeMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
@@ -671,6 +755,16 @@ type finishedMsg struct {
 	verifyData []byte
 }
 
+func (m *finishedMsg) equal(i interface{}) bool {
+	m1, ok := i.(*finishedMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.verifyData, m1.verifyData)
+}
+
 func (m *finishedMsg) marshal() (x []byte) {
 	if m.raw != nil {
 		return m.raw
@@ -698,6 +792,16 @@ type nextProtoMsg struct {
 	proto string
 }
 
+func (m *nextProtoMsg) equal(i interface{}) bool {
+	m1, ok := i.(*nextProtoMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		m.proto == m1.proto
+}
+
 func (m *nextProtoMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
@@ -759,6 +863,17 @@ type certificateRequestMsg struct {
 	certificateAuthorities [][]byte
 }
 
+func (m *certificateRequestMsg) equal(i interface{}) bool {
+	m1, ok := i.(*certificateRequestMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.certificateTypes, m1.certificateTypes) &&
+		eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities)
+}
+
 func (m *certificateRequestMsg) marshal() (x []byte) {
 	if m.raw != nil {
 		return m.raw
@@ -766,9 +881,11 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
 
 	// See http://tools.ietf.org/html/rfc4346#section-7.4.4
 	length := 1 + len(m.certificateTypes) + 2
+	casLength := 0
 	for _, ca := range m.certificateAuthorities {
-		length += 2 + len(ca)
+		casLength += 2 + len(ca)
 	}
+	length += casLength
 
 	x = make([]byte, 4+length)
 	x[0] = typeCertificateRequest
@@ -780,10 +897,8 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
 
 	copy(x[5:], m.certificateTypes)
 	y := x[5+len(m.certificateTypes):]
-
-	numCA := len(m.certificateAuthorities)
-	y[0] = uint8(numCA >> 8)
-	y[1] = uint8(numCA)
+	y[0] = uint8(casLength >> 8)
+	y[1] = uint8(casLength)
 	y = y[2:]
 	for _, ca := range m.certificateAuthorities {
 		y[0] = uint8(len(ca) >> 8)
@@ -794,7 +909,6 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
 	}
 
 	m.raw = x
-
 	return
 }
 
@@ -822,31 +936,34 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
 	}
 
 	data = data[numCertTypes:]
+
 	if len(data) < 2 {
 		return false
 	}
-
-	numCAs := uint16(data[0])<<16 | uint16(data[1])
+	casLength := uint16(data[0])<<8 | uint16(data[1])
 	data = data[2:]
+	if len(data) < int(casLength) {
+		return false
+	}
+	cas := make([]byte, casLength)
+	copy(cas, data)
+	data = data[casLength:]
 
-	m.certificateAuthorities = make([][]byte, numCAs)
-	for i := uint16(0); i < numCAs; i++ {
-		if len(data) < 2 {
+	m.certificateAuthorities = nil
+	for len(cas) > 0 {
+		if len(cas) < 2 {
 			return false
 		}
-		caLen := uint16(data[0])<<16 | uint16(data[1])
+		caLen := uint16(cas[0])<<8 | uint16(cas[1])
+		cas = cas[2:]
 
-		data = data[2:]
-		if len(data) < int(caLen) {
+		if len(cas) < int(caLen) {
 			return false
 		}
 
-		ca := make([]byte, caLen)
-		copy(ca, data)
-		m.certificateAuthorities[i] = ca
-		data = data[caLen:]
+		m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
+		cas = cas[caLen:]
 	}
-
 	if len(data) > 0 {
 		return false
 	}
@@ -859,6 +976,16 @@ type certificateVerifyMsg struct {
 	signature []byte
 }
 
+func (m *certificateVerifyMsg) equal(i interface{}) bool {
+	m1, ok := i.(*certificateVerifyMsg)
+	if !ok {
+		return false
+	}
+
+	return bytes.Equal(m.raw, m1.raw) &&
+		bytes.Equal(m.signature, m1.signature)
+}
+
 func (m *certificateVerifyMsg) marshal() (x []byte) {
 	if m.raw != nil {
 		return m.raw
@@ -902,3 +1029,39 @@ func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
 
 	return true
 }
+
+func eqUint16s(x, y []uint16) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if y[i] != v {
+			return false
+		}
+	}
+	return true
+}
+
+func eqStrings(x, y []string) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if y[i] != v {
+			return false
+		}
+	}
+	return true
+}
+
+func eqByteSlices(x, y [][]byte) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if !bytes.Equal(v, y[i]) {
+			return false
+		}
+	}
+	return true
+}
diff --git a/src/pkg/crypto/tls/handshake_messages_test.go b/src/pkg/crypto/tls/handshake_messages_test.go
index dc68a12..e62a9d5 100644
--- a/src/pkg/crypto/tls/handshake_messages_test.go
+++ b/src/pkg/crypto/tls/handshake_messages_test.go
@@ -5,7 +5,7 @@
 package tls
 
 import (
-	"rand"
+	"math/rand"
 	"reflect"
 	"testing"
 	"testing/quick"
@@ -27,10 +27,12 @@ var tests = []interface{}{
 type testMessage interface {
 	marshal() []byte
 	unmarshal([]byte) bool
+	equal(interface{}) bool
 }
 
 func TestMarshalUnmarshal(t *testing.T) {
 	rand := rand.New(rand.NewSource(0))
+
 	for i, iface := range tests {
 		ty := reflect.ValueOf(iface).Type()
 
@@ -54,7 +56,7 @@ func TestMarshalUnmarshal(t *testing.T) {
 			}
 			m2.marshal() // to fill any marshal cache in the message
 
-			if !reflect.DeepEqual(m1, m2) {
+			if !m1.equal(m2) {
 				t.Errorf("#%d got:%#v want:%#v %x", i, m2, m1, marshaled)
 				break
 			}
diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/pkg/crypto/tls/handshake_server.go
index f083a87..fb53767 100644
--- a/src/pkg/crypto/tls/handshake_server.go
+++ b/src/pkg/crypto/tls/handshake_server.go
@@ -9,11 +9,11 @@ import (
 	"crypto/rsa"
 	"crypto/subtle"
 	"crypto/x509"
+	"errors"
 	"io"
-	"os"
 )
 
-func (c *Conn) serverHandshake() os.Error {
+func (c *Conn) serverHandshake() error {
 	config := c.config
 	msg, err := c.readHandshake()
 	if err != nil {
@@ -56,18 +56,25 @@ Curves:
 	ellipticOk := supportedCurve && supportedPointFormat
 
 	var suite *cipherSuite
-	var suiteId uint16
 FindCipherSuite:
 	for _, id := range clientHello.cipherSuites {
 		for _, supported := range config.cipherSuites() {
 			if id == supported {
-				suite = cipherSuites[id]
+				suite = nil
+				for _, s := range cipherSuites {
+					if s.id == id {
+						suite = s
+						break
+					}
+				}
+				if suite == nil {
+					continue
+				}
 				// Don't select a ciphersuite which we can't
 				// support for this client.
 				if suite.elliptic && !ellipticOk {
 					continue
 				}
-				suiteId = id
 				break FindCipherSuite
 			}
 		}
@@ -87,8 +94,8 @@ FindCipherSuite:
 	}
 
 	hello.vers = vers
-	hello.cipherSuite = suiteId
-	t := uint32(config.time())
+	hello.cipherSuite = suite.id
+	t := uint32(config.time().Unix())
 	hello.random = make([]byte, 32)
 	hello.random[0] = byte(t >> 24)
 	hello.random[1] = byte(t >> 16)
@@ -115,7 +122,12 @@ FindCipherSuite:
 	}
 
 	certMsg := new(certificateMsg)
-	certMsg.certificates = config.Certificates[0].Certificate
+	if len(clientHello.serverName) > 0 {
+		c.serverName = clientHello.serverName
+		certMsg.certificates = config.getCertificateForName(clientHello.serverName).Certificate
+	} else {
+		certMsg.certificates = config.Certificates[0].Certificate
+	}
 	finishedHash.Write(certMsg.marshal())
 	c.writeRecord(recordTypeHandshake, certMsg.marshal())
 
@@ -138,14 +150,19 @@ FindCipherSuite:
 		c.writeRecord(recordTypeHandshake, skx.marshal())
 	}
 
-	if config.AuthenticateClient {
+	if config.ClientAuth >= RequestClientCert {
 		// Request a client certificate
 		certReq := new(certificateRequestMsg)
 		certReq.certificateTypes = []byte{certTypeRSASign}
+
 		// An empty list of certificateAuthorities signals to
 		// the client that it may send any certificate in response
-		// to our request.
-
+		// to our request. When we know the CAs we trust, then
+		// we can send them down, so that the client can choose
+		// an appropriate certificate to give to us.
+		if config.ClientCAs != nil {
+			certReq.certificateAuthorities = config.ClientCAs.Subjects()
+		}
 		finishedHash.Write(certReq.marshal())
 		c.writeRecord(recordTypeHandshake, certReq.marshal())
 	}
@@ -154,52 +171,87 @@ FindCipherSuite:
 	finishedHash.Write(helloDone.marshal())
 	c.writeRecord(recordTypeHandshake, helloDone.marshal())
 
-	var pub *rsa.PublicKey
-	if config.AuthenticateClient {
-		// Get client certificate
-		msg, err = c.readHandshake()
-		if err != nil {
-			return err
-		}
-		certMsg, ok = msg.(*certificateMsg)
-		if !ok {
-			return c.sendAlert(alertUnexpectedMessage)
+	var pub *rsa.PublicKey // public key for client auth, if any
+
+	msg, err = c.readHandshake()
+	if err != nil {
+		return err
+	}
+
+	// If we requested a client certificate, then the client must send a
+	// certificate message, even if it's empty.
+	if config.ClientAuth >= RequestClientCert {
+		if certMsg, ok = msg.(*certificateMsg); !ok {
+			return c.sendAlert(alertHandshakeFailure)
 		}
 		finishedHash.Write(certMsg.marshal())
 
+		if len(certMsg.certificates) == 0 {
+			// The client didn't actually send a certificate
+			switch config.ClientAuth {
+			case RequireAnyClientCert, RequireAndVerifyClientCert:
+				c.sendAlert(alertBadCertificate)
+				return errors.New("tls: client didn't provide a certificate")
+			}
+		}
+
 		certs := make([]*x509.Certificate, len(certMsg.certificates))
 		for i, asn1Data := range certMsg.certificates {
-			cert, err := x509.ParseCertificate(asn1Data)
-			if err != nil {
+			if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
 				c.sendAlert(alertBadCertificate)
-				return os.NewError("could not parse client's certificate: " + err.String())
+				return errors.New("tls: failed to parse client certificate: " + err.Error())
 			}
-			certs[i] = cert
 		}
 
-		// TODO(agl): do better validation of certs: max path length, name restrictions etc.
-		for i := 1; i < len(certs); i++ {
-			if err := certs[i-1].CheckSignatureFrom(certs[i]); err != nil {
+		if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
+			opts := x509.VerifyOptions{
+				Roots:         c.config.ClientCAs,
+				CurrentTime:   c.config.time(),
+				Intermediates: x509.NewCertPool(),
+			}
+
+			for i, cert := range certs {
+				if i == 0 {
+					continue
+				}
+				opts.Intermediates.AddCert(cert)
+			}
+
+			chains, err := certs[0].Verify(opts)
+			if err != nil {
 				c.sendAlert(alertBadCertificate)
-				return os.NewError("could not validate certificate signature: " + err.String())
+				return errors.New("tls: failed to verify client's certificate: " + err.Error())
+			}
+
+			ok := false
+			for _, ku := range certs[0].ExtKeyUsage {
+				if ku == x509.ExtKeyUsageClientAuth {
+					ok = true
+					break
+				}
+			}
+			if !ok {
+				c.sendAlert(alertHandshakeFailure)
+				return errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
 			}
+
+			c.verifiedChains = chains
 		}
 
 		if len(certs) > 0 {
-			key, ok := certs[0].PublicKey.(*rsa.PublicKey)
-			if !ok {
+			if pub, ok = certs[0].PublicKey.(*rsa.PublicKey); !ok {
 				return c.sendAlert(alertUnsupportedCertificate)
 			}
-			pub = key
 			c.peerCertificates = certs
 		}
+
+		msg, err = c.readHandshake()
+		if err != nil {
+			return err
+		}
 	}
 
 	// Get client key exchange
-	msg, err = c.readHandshake()
-	if err != nil {
-		return err
-	}
 	ckx, ok := msg.(*clientKeyExchangeMsg)
 	if !ok {
 		return c.sendAlert(alertUnexpectedMessage)
@@ -222,13 +274,13 @@ FindCipherSuite:
 			return c.sendAlert(alertUnexpectedMessage)
 		}
 
-		digest := make([]byte, 36)
-		copy(digest[0:16], finishedHash.serverMD5.Sum())
-		copy(digest[16:36], finishedHash.serverSHA1.Sum())
+		digest := make([]byte, 0, 36)
+		digest = finishedHash.serverMD5.Sum(digest)
+		digest = finishedHash.serverSHA1.Sum(digest)
 		err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
 		if err != nil {
 			c.sendAlert(alertBadCertificate)
-			return os.NewError("could not validate signature of connection nonces: " + err.String())
+			return errors.New("could not validate signature of connection nonces: " + err.Error())
 		}
 
 		finishedHash.Write(certVerify.marshal())
@@ -291,7 +343,7 @@ FindCipherSuite:
 	c.writeRecord(recordTypeHandshake, finished.marshal())
 
 	c.handshakeComplete = true
-	c.cipherSuite = suiteId
+	c.cipherSuite = suite.id
 
 	return nil
 }
diff --git a/src/pkg/crypto/tls/handshake_server_test.go b/src/pkg/crypto/tls/handshake_server_test.go
index d910ead..4bff532 100644
--- a/src/pkg/crypto/tls/handshake_server_test.go
+++ b/src/pkg/crypto/tls/handshake_server_test.go
@@ -5,20 +5,25 @@
 package tls
 
 import (
-	"big"
 	"bytes"
 	"crypto/rsa"
+	"crypto/x509"
 	"encoding/hex"
+	"encoding/pem"
 	"flag"
 	"io"
+	"log"
+	"math/big"
 	"net"
-	"os"
+	"strconv"
+	"strings"
 	"testing"
+	"time"
 )
 
 type zeroSource struct{}
 
-func (zeroSource) Read(b []byte) (n int, err os.Error) {
+func (zeroSource) Read(b []byte) (n int, err error) {
 	for i := range b {
 		b[i] = 0
 	}
@@ -30,15 +35,16 @@ var testConfig *Config
 
 func init() {
 	testConfig = new(Config)
-	testConfig.Time = func() int64 { return 0 }
+	testConfig.Time = func() time.Time { return time.Unix(0, 0) }
 	testConfig.Rand = zeroSource{}
 	testConfig.Certificates = make([]Certificate, 1)
 	testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
 	testConfig.Certificates[0].PrivateKey = testPrivateKey
 	testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
+	testConfig.InsecureSkipVerify = true
 }
 
-func testClientHelloFailure(t *testing.T, m handshakeMessage, expected os.Error) {
+func testClientHelloFailure(t *testing.T, m handshakeMessage, expected error) {
 	// Create in-memory network connection,
 	// send message to server.  Should return
 	// expected error.
@@ -53,7 +59,7 @@ func testClientHelloFailure(t *testing.T, m handshakeMessage, expected os.Error)
 	}()
 	err := Server(s, testConfig).Handshake()
 	s.Close()
-	if e, ok := err.(*net.OpError); !ok || e.Error != expected {
+	if e, ok := err.(*net.OpError); !ok || e.Err != expected {
 		t.Errorf("Got error: %s; expected: %s", err, expected)
 	}
 }
@@ -90,7 +96,7 @@ func TestAlertForwarding(t *testing.T) {
 
 	err := Server(s, testConfig).Handshake()
 	s.Close()
-	if e, ok := err.(*net.OpError); !ok || e.Error != os.Error(alertUnknownCA) {
+	if e, ok := err.(*net.OpError); !ok || e.Err != error(alertUnknownCA) {
 		t.Errorf("Got error: %s; expected: %s", err, alertUnknownCA)
 	}
 }
@@ -101,21 +107,23 @@ func TestClose(t *testing.T) {
 
 	err := Server(s, testConfig).Handshake()
 	s.Close()
-	if err != os.EOF {
-		t.Errorf("Got error: %s; expected: %s", err, os.EOF)
+	if err != io.EOF {
+		t.Errorf("Got error: %s; expected: %s", err, io.EOF)
 	}
 }
 
-func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config) {
+func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config, peers []*x509.Certificate) {
 	c, s := net.Pipe()
 	srv := Server(s, config)
+	pchan := make(chan []*x509.Certificate, 1)
 	go func() {
 		srv.Write([]byte("hello, world\n"))
 		srv.Close()
 		s.Close()
+		st := srv.ConnectionState()
+		pchan <- st.PeerCertificates
 	}()
 
-	defer c.Close()
 	for i, b := range serverScript {
 		if i%2 == 0 {
 			c.Write(b)
@@ -130,30 +138,84 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config *
 			t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
 		}
 	}
+	c.Close()
+
+	if peers != nil {
+		gotpeers := <-pchan
+		if len(peers) == len(gotpeers) {
+			for i, _ := range peers {
+				if !peers[i].Equal(gotpeers[i]) {
+					t.Fatalf("%s: mismatch on peer cert %d", name, i)
+				}
+			}
+		} else {
+			t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", name, len(peers), len(gotpeers))
+		}
+	}
 }
 
 func TestHandshakeServerRC4(t *testing.T) {
-	testServerScript(t, "RC4", rc4ServerScript, testConfig)
+	testServerScript(t, "RC4", rc4ServerScript, testConfig, nil)
+}
+
+func TestHandshakeServer3DES(t *testing.T) {
+	des3Config := new(Config)
+	*des3Config = *testConfig
+	des3Config.CipherSuites = []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA}
+	testServerScript(t, "3DES", des3ServerScript, des3Config, nil)
 }
 
 func TestHandshakeServerAES(t *testing.T) {
 	aesConfig := new(Config)
 	*aesConfig = *testConfig
 	aesConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}
-	testServerScript(t, "AES", aesServerScript, aesConfig)
+	testServerScript(t, "AES", aesServerScript, aesConfig, nil)
 }
 
 func TestHandshakeServerSSLv3(t *testing.T) {
-	testServerScript(t, "SSLv3", sslv3ServerScript, testConfig)
+	testServerScript(t, "SSLv3", sslv3ServerScript, testConfig, nil)
+}
+
+type clientauthTest struct {
+	name       string
+	clientauth ClientAuthType
+	peers      []*x509.Certificate
+	script     [][]byte
+}
+
+func TestClientAuth(t *testing.T) {
+	for _, cat := range clientauthTests {
+		t.Log("running", cat.name)
+		cfg := new(Config)
+		*cfg = *testConfig
+		cfg.ClientAuth = cat.clientauth
+		testServerScript(t, cat.name, cat.script, cfg, cat.peers)
+	}
 }
 
 var serve = flag.Bool("serve", false, "run a TLS server on :10443")
+var testCipherSuites = flag.String("ciphersuites",
+	"0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
+	"cipher suites to accept in serving mode")
+var testClientAuth = flag.Int("clientauth", 0, "value for tls.Config.ClientAuth")
 
 func TestRunServer(t *testing.T) {
 	if !*serve {
 		return
 	}
 
+	suites := strings.Split(*testCipherSuites, ",")
+	testConfig.CipherSuites = make([]uint16, len(suites))
+	for i := range suites {
+		suite, err := strconv.ParseUint(suites[i], 0, 64)
+		if err != nil {
+			panic(err)
+		}
+		testConfig.CipherSuites[i] = uint16(suite)
+	}
+
+	testConfig.ClientAuth = ClientAuthType(*testClientAuth)
+
 	l, err := Listen("tcp", ":10443", testConfig)
 	if err != nil {
 		t.Fatal(err)
@@ -162,13 +224,23 @@ func TestRunServer(t *testing.T) {
 	for {
 		c, err := l.Accept()
 		if err != nil {
+			log.Printf("error from TLS handshake: %s", err)
 			break
 		}
+
 		_, err = c.Write([]byte("hello, world\n"))
 		if err != nil {
-			t.Errorf("error from TLS: %s", err)
-			break
+			log.Printf("error from TLS: %s", err)
+			continue
 		}
+
+		st := c.(*Conn).ConnectionState()
+		if len(st.PeerCertificates) > 0 {
+			log.Print("Handling request from client ", st.PeerCertificates[0].Subject.CommonName)
+		} else {
+			log.Print("Handling request from anon client")
+		}
+
 		c.Close()
 	}
 }
@@ -198,6 +270,18 @@ var testPrivateKey = &rsa.PrivateKey{
 	},
 }
 
+func loadPEMCert(in string) *x509.Certificate {
+	block, _ := pem.Decode([]byte(in))
+	if block.Type == "CERTIFICATE" && len(block.Headers) == 0 {
+		cert, err := x509.ParseCertificate(block.Bytes)
+		if err == nil {
+			return cert
+		}
+		panic("error parsing cert")
+	}
+	panic("error parsing PEM")
+}
+
 // Script of interaction with gnutls implementation.
 // The values for this test are obtained by building and running in server mode:
 //   % gotest -test.run "TestRunServer" -serve
@@ -206,23 +290,22 @@ var testPrivateKey = &rsa.PrivateKey{
 //   % python parse-gnutls-cli-debug-log.py < /tmp/log
 var rc4ServerScript = [][]byte{
 	{
-		0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
-		0x7b, 0x03, 0x02, 0x4d, 0x08, 0x1f, 0x5a, 0x7a,
-		0x0a, 0x92, 0x2f, 0xf0, 0x73, 0x16, 0x3a, 0x88,
-		0x14, 0x85, 0x4c, 0x98, 0x15, 0x7b, 0x65, 0xe0,
-		0x78, 0xd0, 0xed, 0xd0, 0xf3, 0x65, 0x20, 0xeb,
-		0x80, 0xd1, 0x0b, 0x00, 0x00, 0x34, 0x00, 0x33,
+		0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+		0x76, 0x03, 0x02, 0x4e, 0xdd, 0xe6, 0xa5, 0xf7,
+		0x00, 0x36, 0xf7, 0x83, 0xec, 0x93, 0x7c, 0xd2,
+		0x4d, 0xe7, 0x7b, 0xf5, 0x4c, 0xf7, 0xe3, 0x86,
+		0xe8, 0xec, 0x3b, 0xbd, 0x2c, 0x9a, 0x3f, 0x57,
+		0xf0, 0xa4, 0xd4, 0x00, 0x00, 0x34, 0x00, 0x33,
 		0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
 		0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
 		0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
 		0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
 		0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
 		0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-		0x00, 0x8a, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x09,
+		0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
 		0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
 		0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-		0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0xff,
-		0x01, 0x00, 0x01, 0x00,
+		0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
 	},
 
 	{
@@ -326,38 +409,219 @@ var rc4ServerScript = [][]byte{
 
 	{
 		0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-		0x82, 0x00, 0x80, 0x3c, 0x13, 0xd7, 0x12, 0xc1,
-		0x6a, 0xf0, 0x3f, 0x8c, 0xa1, 0x35, 0x5d, 0xc5,
-		0x89, 0x1e, 0x9e, 0xcd, 0x32, 0xc7, 0x9e, 0xe6,
-		0xae, 0xd5, 0xf1, 0xbf, 0x70, 0xd7, 0xa9, 0xef,
-		0x2c, 0x4c, 0xf4, 0x22, 0xbc, 0x17, 0x17, 0xaa,
-		0x05, 0xf3, 0x9f, 0x80, 0xf2, 0xe9, 0x82, 0x2f,
-		0x2a, 0x15, 0x54, 0x0d, 0x16, 0x0e, 0x77, 0x4c,
-		0x28, 0x3c, 0x03, 0x2d, 0x2d, 0xd7, 0xc8, 0x64,
-		0xd9, 0x59, 0x4b, 0x1c, 0xf4, 0xde, 0xff, 0x2f,
-		0xbc, 0x94, 0xaf, 0x18, 0x26, 0x37, 0xce, 0x4f,
-		0x84, 0x74, 0x2e, 0x45, 0x66, 0x7c, 0x0c, 0x54,
-		0x46, 0x36, 0x5f, 0x65, 0x21, 0x7b, 0x83, 0x8c,
-		0x6d, 0x76, 0xcd, 0x0d, 0x9f, 0xda, 0x1c, 0xa4,
-		0x6e, 0xfe, 0xb1, 0xf7, 0x09, 0x0d, 0xfb, 0x74,
-		0x66, 0x34, 0x99, 0x89, 0x7f, 0x5f, 0x77, 0x87,
-		0x4a, 0x66, 0x4b, 0xa9, 0x59, 0x57, 0xe3, 0x56,
-		0x0d, 0xdd, 0xd8, 0x14, 0x03, 0x01, 0x00, 0x01,
-		0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc0, 0x4e,
-		0xd3, 0x0f, 0xb5, 0xc0, 0x57, 0xa6, 0x18, 0x80,
-		0x80, 0x6b, 0x49, 0xfe, 0xbd, 0x3a, 0x7a, 0x2c,
-		0xef, 0x70, 0xb5, 0x1c, 0xd2, 0xdf, 0x5f, 0x78,
-		0x5a, 0xd8, 0x4f, 0xa0, 0x95, 0xb4, 0xb3, 0xb5,
-		0xaa, 0x3b,
+		0x82, 0x00, 0x80, 0x39, 0xe2, 0x0f, 0x49, 0xa0,
+		0xe6, 0xe4, 0x3b, 0x0c, 0x5f, 0xce, 0x39, 0x97,
+		0x6c, 0xb6, 0x41, 0xd9, 0xe1, 0x52, 0x8f, 0x43,
+		0xb3, 0xc6, 0x4f, 0x9a, 0xe2, 0x1e, 0xb9, 0x3b,
+		0xe3, 0x72, 0x17, 0x68, 0xb2, 0x0d, 0x7b, 0x71,
+		0x33, 0x96, 0x5c, 0xf9, 0xfe, 0x18, 0x8f, 0x2f,
+		0x2b, 0x82, 0xec, 0x03, 0xf2, 0x16, 0xa8, 0xf8,
+		0x39, 0xf9, 0xbb, 0x5a, 0xd3, 0x0c, 0xc1, 0x2a,
+		0x52, 0xa1, 0x90, 0x20, 0x6b, 0x24, 0xc9, 0x55,
+		0xee, 0x05, 0xd8, 0xb3, 0x43, 0x58, 0xf6, 0x7f,
+		0x68, 0x2d, 0xb3, 0xd1, 0x1b, 0x30, 0xaa, 0xdf,
+		0xfc, 0x85, 0xf1, 0xab, 0x14, 0x51, 0x91, 0x78,
+		0x29, 0x35, 0x65, 0xe0, 0x9c, 0xf6, 0xb7, 0x35,
+		0x33, 0xdb, 0x28, 0x93, 0x4d, 0x86, 0xbc, 0xfe,
+		0xaa, 0xd1, 0xc0, 0x2e, 0x4d, 0xec, 0xa2, 0x98,
+		0xca, 0x08, 0xb2, 0x91, 0x14, 0xde, 0x97, 0x3a,
+		0xc4, 0x6b, 0x49, 0x14, 0x03, 0x01, 0x00, 0x01,
+		0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x7a, 0xcb,
+		0x3b, 0x0e, 0xbb, 0x7a, 0x56, 0x39, 0xaf, 0x83,
+		0xae, 0xfd, 0x25, 0xfd, 0x64, 0xb4, 0x0c, 0x0c,
+		0x17, 0x46, 0x54, 0x2c, 0x6a, 0x07, 0x83, 0xc6,
+		0x46, 0x08, 0x0b, 0xcd, 0x15, 0x53, 0xef, 0x40,
+		0x4e, 0x56,
 	},
 
 	{
 		0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-		0x01, 0x00, 0x24, 0x9d, 0xc9, 0xda, 0xdf, 0xeb,
-		0xc8, 0xdb, 0xf8, 0x94, 0xa5, 0xef, 0xd5, 0xfc,
-		0x89, 0x01, 0x64, 0x30, 0x77, 0x5a, 0x18, 0x4b,
-		0x16, 0x79, 0x9c, 0xf6, 0xf5, 0x09, 0x22, 0x12,
-		0x4c, 0x3e, 0xa8, 0x8e, 0x91, 0xa5, 0x24,
+		0x01, 0x00, 0x24, 0xd3, 0x72, 0xeb, 0x29, 0xb9,
+		0x15, 0x29, 0xb5, 0xe5, 0xb7, 0xef, 0x5c, 0xb2,
+		0x9d, 0xf6, 0xc8, 0x47, 0xd6, 0xa0, 0x84, 0xf0,
+		0x8c, 0xcb, 0xe6, 0xbe, 0xbc, 0xfb, 0x38, 0x90,
+		0x89, 0x60, 0xa2, 0xe8, 0xaa, 0xb3, 0x12, 0x17,
+		0x03, 0x01, 0x00, 0x21, 0x67, 0x4a, 0x3d, 0x31,
+		0x6c, 0x5a, 0x1c, 0xf9, 0x6e, 0xf1, 0xd8, 0x12,
+		0x0e, 0xb9, 0xfd, 0xfc, 0x66, 0x91, 0xd1, 0x1d,
+		0x6e, 0xe4, 0x55, 0xdd, 0x11, 0xb9, 0xb8, 0xa2,
+		0x65, 0xa1, 0x95, 0x64, 0x1c, 0x15, 0x03, 0x01,
+		0x00, 0x16, 0x9b, 0xa0, 0x24, 0xe3, 0xcb, 0xae,
+		0xad, 0x51, 0xb3, 0x63, 0x59, 0x78, 0x49, 0x24,
+		0x06, 0x6e, 0xee, 0x7a, 0xd7, 0x74, 0x53, 0x04,
+	},
+}
+
+var des3ServerScript = [][]byte{
+	{
+		0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+		0x76, 0x03, 0x02, 0x4e, 0x84, 0xf4, 0x3c, 0xe4,
+		0xb8, 0xc7, 0xa0, 0x30, 0x55, 0x2a, 0xbc, 0xb7,
+		0x04, 0x6b, 0x6f, 0x87, 0x93, 0x96, 0xbd, 0x1a,
+		0x7a, 0x1e, 0xce, 0xd2, 0x0d, 0xf3, 0x01, 0x03,
+		0xbe, 0x7b, 0x17, 0x00, 0x00, 0x34, 0x00, 0x33,
+		0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+		0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+		0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+		0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+		0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+		0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+		0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+		0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+		0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+		0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+	},
+
+	{
+		0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+		0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x16,
+		0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+		0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+		0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+		0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+		0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+		0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+		0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+		0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+		0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+		0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+		0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+		0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+		0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+		0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+		0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+		0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+		0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+		0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+		0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+		0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+		0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+		0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+		0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+		0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+		0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+		0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+		0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+		0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+		0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+		0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+		0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+		0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+		0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+		0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+		0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+		0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+		0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+		0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+		0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+		0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+		0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+		0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+		0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+		0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+		0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+		0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+		0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+		0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+		0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+		0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+		0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+		0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+		0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+		0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+		0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+		0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+		0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+		0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+		0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+		0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+		0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+		0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+		0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+		0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+		0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+		0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+		0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+		0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+		0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+		0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+		0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+		0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+		0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+		0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+		0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+		0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+		0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+		0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+		0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+		0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+		0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+		0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+		0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+		0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+		0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+		0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+		0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+		0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
+		0x00, 0x00, 0x00,
+	},
+
+	{
+		0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+		0x82, 0x00, 0x80, 0xae, 0xcf, 0x4f, 0x70, 0x0e,
+		0xe5, 0xe7, 0xba, 0xef, 0x0c, 0x66, 0xe9, 0xae,
+		0x76, 0xf4, 0xe0, 0xbc, 0x1c, 0x22, 0x5b, 0x72,
+		0xc9, 0x68, 0x63, 0x44, 0xec, 0x72, 0xc2, 0xca,
+		0xac, 0xc2, 0xf5, 0x5c, 0x28, 0xa1, 0xaf, 0xd0,
+		0xc2, 0xf7, 0x79, 0x71, 0x32, 0x73, 0x86, 0xea,
+		0x39, 0xf6, 0x04, 0x26, 0x19, 0x84, 0x1d, 0x7d,
+		0xa1, 0x21, 0xa6, 0x88, 0xbf, 0x33, 0x5a, 0x64,
+		0xb0, 0xc2, 0xcc, 0x19, 0x7a, 0x8b, 0x6e, 0x94,
+		0x9e, 0x2e, 0x20, 0xbe, 0xdc, 0xe9, 0x8e, 0xae,
+		0x5c, 0x39, 0xc8, 0xcd, 0x0e, 0x19, 0x9a, 0xa2,
+		0xfc, 0x3f, 0x61, 0x9a, 0xca, 0x58, 0x69, 0x0d,
+		0xa8, 0x7b, 0xbe, 0x98, 0x8f, 0xb9, 0x9d, 0x8b,
+		0x68, 0x65, 0xa9, 0x74, 0xcc, 0x8d, 0x0c, 0xb2,
+		0xc4, 0x0f, 0xdc, 0x56, 0x3e, 0x44, 0x61, 0x0a,
+		0x26, 0x93, 0x99, 0xef, 0x67, 0xff, 0x6e, 0x73,
+		0x01, 0xa1, 0x90, 0x14, 0x03, 0x01, 0x00, 0x01,
+		0x01, 0x16, 0x03, 0x01, 0x00, 0x60, 0x49, 0x36,
+		0xc8, 0x38, 0x95, 0xe4, 0x5d, 0x8e, 0x80, 0x10,
+		0x26, 0x9f, 0x87, 0x7d, 0xcd, 0xb9, 0x32, 0x6c,
+		0xff, 0xaa, 0xe0, 0x07, 0xec, 0x33, 0xe2, 0x36,
+		0x9d, 0xd5, 0x83, 0x2c, 0xf0, 0x0a, 0xa0, 0xa8,
+		0x12, 0x9f, 0xca, 0x72, 0xda, 0x70, 0x7d, 0x76,
+		0x80, 0x12, 0x88, 0x07, 0xaa, 0x27, 0x62, 0x33,
+		0xab, 0x55, 0xad, 0x3c, 0x2b, 0x54, 0xc4, 0x1c,
+		0x91, 0xfd, 0x8f, 0x9c, 0xa7, 0x8b, 0x75, 0x10,
+		0xa8, 0x6e, 0xfc, 0x30, 0x52, 0x8a, 0x61, 0x02,
+		0xdb, 0x9c, 0x6f, 0xc8, 0x19, 0x93, 0x5d, 0x41,
+		0x1d, 0x36, 0x68, 0x0b, 0xec, 0x30, 0xae, 0xfb,
+		0x90, 0xdb, 0x6d, 0x83, 0xb0, 0xf2,
+	},
+
+	{
+		0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+		0x01, 0x00, 0x28, 0x07, 0xf3, 0x33, 0x84, 0xb1,
+		0x5d, 0x2b, 0x52, 0xa4, 0x63, 0x3c, 0x32, 0xe0,
+		0x0d, 0x22, 0xf5, 0x23, 0xec, 0xf9, 0xa6, 0xec,
+		0xc0, 0x12, 0x69, 0x88, 0xf6, 0x7d, 0x37, 0xcd,
+		0xc2, 0x74, 0x2f, 0xef, 0xf6, 0x49, 0x15, 0xea,
+		0x88, 0x3f, 0x55, 0x17, 0x03, 0x01, 0x00, 0x28,
+		0xaf, 0x00, 0x84, 0xff, 0x11, 0x01, 0x6d, 0xba,
+		0x39, 0x5e, 0x45, 0xe1, 0x52, 0x5e, 0xc1, 0xab,
+		0xde, 0x5b, 0x16, 0xdd, 0xd6, 0x61, 0x57, 0xb8,
+		0x66, 0x8b, 0x2d, 0xde, 0x51, 0x41, 0xc5, 0x09,
+		0xb3, 0x6a, 0x06, 0x43, 0xb4, 0x73, 0x5c, 0xf1,
+		0x15, 0x03, 0x01, 0x00, 0x18, 0xbd, 0x65, 0xb2,
+		0xce, 0x77, 0x2e, 0xf9, 0x11, 0xc4, 0x80, 0x43,
+		0x5a, 0x73, 0x8b, 0x73, 0xdd, 0xf0, 0x54, 0x44,
+		0x7c, 0x56, 0x19, 0x54, 0xda,
 	},
 }
 
@@ -682,3 +946,625 @@ var sslv3ServerScript = [][]byte{
 		0xaf, 0xd3, 0xb7, 0xa3, 0xcc, 0x4a, 0x1d, 0x2e,
 	},
 }
+
+var clientauthTests = []clientauthTest{
+	// Server doesn't asks for cert
+	// gotest -test.run "TestRunServer" -serve -clientauth 0
+	// gnutls-cli --insecure --debug 100 -p 10443 localhost 2>&1 |
+	//   python parse-gnutls-cli-debug-log.py
+	{"NoClientCert", NoClientCert, nil,
+		[][]byte{{
+			0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+			0x76, 0x03, 0x02, 0x4e, 0xe0, 0x92, 0x5d, 0xcd,
+			0xfe, 0x0c, 0x69, 0xd4, 0x7d, 0x8e, 0xa6, 0x88,
+			0xde, 0x72, 0x04, 0x29, 0x6a, 0x4a, 0x16, 0x23,
+			0xd7, 0x8f, 0xbc, 0xfa, 0x80, 0x73, 0x2e, 0x12,
+			0xb7, 0x0b, 0x39, 0x00, 0x00, 0x34, 0x00, 0x33,
+			0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+			0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+			0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+			0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+			0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+			0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+			0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+			0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+			0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+			0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+		},
+
+			{
+				0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+				0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+				0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+				0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+				0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+				0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+				0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+				0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+				0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+				0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+				0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+				0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+				0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+				0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+				0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+				0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+				0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+				0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+				0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+				0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+				0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+				0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+				0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+				0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+				0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+				0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+				0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+				0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+				0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+				0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+				0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+				0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+				0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+				0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+				0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+				0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+				0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+				0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+				0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+				0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+				0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+				0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+				0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+				0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+				0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+				0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+				0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+				0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+				0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+				0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+				0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+				0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+				0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+				0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+				0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+				0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+				0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+				0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+				0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+				0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+				0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+				0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+				0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+				0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+				0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+				0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+				0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+				0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+				0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+				0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+				0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+				0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+				0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+				0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+				0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+				0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+				0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+				0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+				0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+				0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+				0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+				0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+				0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+				0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+				0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+				0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+				0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+				0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+				0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
+				0x00, 0x00, 0x00,
+			},
+
+			{
+				0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+				0x82, 0x00, 0x80, 0x10, 0xe1, 0x00, 0x3d, 0x0a,
+				0x6b, 0x02, 0x7f, 0x97, 0xde, 0xfb, 0x65, 0x46,
+				0x1a, 0x50, 0x4e, 0x34, 0x9a, 0xae, 0x14, 0x7e,
+				0xec, 0xef, 0x85, 0x15, 0x3b, 0x39, 0xc2, 0x45,
+				0x04, 0x40, 0x92, 0x71, 0xd6, 0x7e, 0xf6, 0xfd,
+				0x4d, 0x84, 0xf7, 0xc4, 0x77, 0x99, 0x3d, 0xe2,
+				0xc3, 0x8d, 0xb0, 0x4c, 0x74, 0xc8, 0x51, 0xec,
+				0xb2, 0xe8, 0x6b, 0xa1, 0xd2, 0x4d, 0xd8, 0x61,
+				0x92, 0x7a, 0x24, 0x57, 0x44, 0x4f, 0xa2, 0x1e,
+				0x74, 0x0b, 0x06, 0x4b, 0x80, 0x34, 0x8b, 0xfe,
+				0xc2, 0x0e, 0xc1, 0xcd, 0xab, 0x0c, 0x3f, 0x54,
+				0xe2, 0x44, 0xe9, 0x6c, 0x2b, 0xba, 0x7b, 0x64,
+				0xf1, 0x93, 0x65, 0x75, 0xf2, 0x35, 0xff, 0x27,
+				0x03, 0xd5, 0x64, 0xe6, 0x8e, 0xe7, 0x7b, 0x56,
+				0xb6, 0x61, 0x73, 0xeb, 0xa2, 0xdc, 0xa4, 0x6e,
+				0x52, 0xac, 0xbc, 0xba, 0x11, 0xa3, 0xd2, 0x61,
+				0x4a, 0xe0, 0xbb, 0x14, 0x03, 0x01, 0x00, 0x01,
+				0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xd2, 0x5a,
+				0x0c, 0x2a, 0x27, 0x96, 0xba, 0xa9, 0x67, 0xd2,
+				0x51, 0x68, 0x32, 0x68, 0x22, 0x1f, 0xb9, 0x27,
+				0x79, 0x59, 0x28, 0xdf, 0x38, 0x1f, 0x92, 0x21,
+				0x5d, 0x0f, 0xf4, 0xc0, 0xee, 0xb7, 0x10, 0x5a,
+				0xa9, 0x45,
+			},
+
+			{
+				0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+				0x01, 0x00, 0x24, 0x13, 0x6f, 0x6c, 0x71, 0x83,
+				0x59, 0xcf, 0x32, 0x72, 0xe9, 0xce, 0xcc, 0x7a,
+				0x6c, 0xf0, 0x72, 0x39, 0x16, 0xae, 0x40, 0x61,
+				0xfa, 0x92, 0x4c, 0xe7, 0xf2, 0x1a, 0xd7, 0x0c,
+				0x84, 0x76, 0x6c, 0xe9, 0x11, 0x43, 0x19, 0x17,
+				0x03, 0x01, 0x00, 0x21, 0xc0, 0xa2, 0x13, 0x28,
+				0x94, 0x8c, 0x5c, 0xd6, 0x79, 0xb9, 0xfe, 0xae,
+				0x45, 0x4b, 0xc0, 0x7c, 0xae, 0x2d, 0xb4, 0x0d,
+				0x31, 0xc4, 0xad, 0x22, 0xd7, 0x1e, 0x99, 0x1c,
+				0x4c, 0x69, 0xab, 0x42, 0x61, 0x15, 0x03, 0x01,
+				0x00, 0x16, 0xe1, 0x0c, 0x67, 0xf3, 0xf4, 0xb9,
+				0x8e, 0x81, 0x8e, 0x01, 0xb8, 0xa0, 0x69, 0x8c,
+				0x03, 0x11, 0x43, 0x3e, 0xee, 0xb7, 0x4d, 0x69,
+			}}},
+	// Server asks for cert with empty CA list, client doesn't give it.
+	// gotest -test.run "TestRunServer" -serve -clientauth 1
+	// gnutls-cli --insecure --debug 100 -p 10443 localhost
+	{"RequestClientCert, none given", RequestClientCert, nil,
+		[][]byte{{
+			0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+			0x76, 0x03, 0x02, 0x4e, 0xe0, 0x93, 0xe2, 0x47,
+			0x06, 0xa0, 0x61, 0x0c, 0x51, 0xdd, 0xf0, 0xef,
+			0xf4, 0x30, 0x72, 0xe1, 0xa6, 0x50, 0x68, 0x82,
+			0x3c, 0xfb, 0xcb, 0x72, 0x5e, 0x73, 0x9d, 0xda,
+			0x27, 0x35, 0x72, 0x00, 0x00, 0x34, 0x00, 0x33,
+			0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+			0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+			0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+			0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+			0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+			0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+			0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+			0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+			0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+			0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+		},
+
+			{
+				0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+				0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+				0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+				0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+				0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+				0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+				0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+				0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+				0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+				0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+				0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+				0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+				0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+				0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+				0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+				0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+				0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+				0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+				0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+				0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+				0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+				0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+				0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+				0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+				0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+				0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+				0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+				0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+				0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+				0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+				0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+				0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+				0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+				0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+				0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+				0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+				0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+				0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+				0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+				0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+				0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+				0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+				0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+				0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+				0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+				0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+				0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+				0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+				0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+				0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+				0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+				0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+				0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+				0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+				0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+				0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+				0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+				0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+				0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+				0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+				0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+				0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+				0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+				0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+				0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+				0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+				0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+				0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+				0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+				0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+				0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+				0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+				0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+				0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+				0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+				0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+				0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+				0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+				0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+				0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+				0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+				0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+				0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+				0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+				0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+				0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+				0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+				0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+				0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+				0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+				0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+			},
+
+			{
+				0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00,
+				0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00,
+				0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x64,
+				0x28, 0xb9, 0x3f, 0x48, 0xaf, 0x06, 0x22, 0x39,
+				0x56, 0xd8, 0x6f, 0x63, 0x5d, 0x03, 0x48, 0x63,
+				0x01, 0x13, 0xa2, 0xd6, 0x76, 0xc0, 0xab, 0xda,
+				0x25, 0x30, 0x75, 0x6c, 0xaa, 0xb4, 0xdc, 0x35,
+				0x72, 0xdc, 0xf2, 0x43, 0xe4, 0x1d, 0x82, 0xfb,
+				0x6c, 0x64, 0xe2, 0xa7, 0x8f, 0x32, 0x67, 0x6b,
+				0xcd, 0xd2, 0xb2, 0x36, 0x94, 0xbc, 0x6f, 0x46,
+				0x79, 0x29, 0x42, 0xe3, 0x1a, 0xbf, 0xfb, 0x41,
+				0xd5, 0xe3, 0xb4, 0x2a, 0xf6, 0x95, 0x6f, 0x0c,
+				0x87, 0xb9, 0x03, 0x18, 0xa1, 0xea, 0x4a, 0xe2,
+				0x2e, 0x0f, 0x50, 0x00, 0xc1, 0xe8, 0x8c, 0xc8,
+				0xa2, 0xf6, 0xa4, 0x05, 0xf4, 0x38, 0x3e, 0xd9,
+				0x6e, 0x63, 0x96, 0x0c, 0x34, 0x73, 0x90, 0x03,
+				0x55, 0xa6, 0x34, 0xb0, 0x5e, 0x8c, 0x48, 0x40,
+				0x25, 0x45, 0x84, 0xa6, 0x21, 0x3f, 0x81, 0x97,
+				0xa7, 0x11, 0x09, 0x14, 0x95, 0xa5, 0xe5, 0x14,
+				0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+				0x00, 0x24, 0x16, 0xaa, 0x01, 0x2c, 0xa8, 0xc1,
+				0x28, 0xaf, 0x35, 0xc1, 0xc1, 0xf3, 0x0a, 0x25,
+				0x66, 0x6e, 0x27, 0x11, 0xa3, 0xa4, 0xd9, 0xe9,
+				0xea, 0x15, 0x09, 0x9d, 0x28, 0xe3, 0x5b, 0x2b,
+				0xa6, 0x25, 0xa7, 0x14, 0x24, 0x3a,
+			},
+
+			{
+				0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+				0x01, 0x00, 0x24, 0x9a, 0xa8, 0xd6, 0x77, 0x46,
+				0x45, 0x68, 0x9d, 0x5d, 0xa9, 0x68, 0x03, 0xe5,
+				0xaf, 0xe8, 0xc8, 0x21, 0xc5, 0xc6, 0xc1, 0x50,
+				0xe0, 0xd8, 0x52, 0xce, 0xa3, 0x4f, 0x2d, 0xf4,
+				0xe3, 0xa7, 0x7d, 0x35, 0x80, 0x84, 0x12, 0x17,
+				0x03, 0x01, 0x00, 0x21, 0x8a, 0x82, 0x0c, 0x54,
+				0x1b, 0xeb, 0x77, 0x90, 0x2c, 0x3e, 0xbc, 0xf0,
+				0x23, 0xcc, 0xa8, 0x9f, 0x25, 0x08, 0x12, 0xed,
+				0x43, 0xf1, 0xf9, 0x06, 0xad, 0xa9, 0x4b, 0x97,
+				0x82, 0xb7, 0xc4, 0x0b, 0x4c, 0x15, 0x03, 0x01,
+				0x00, 0x16, 0x05, 0x2d, 0x9d, 0x45, 0x03, 0xb7,
+				0xc2, 0xd1, 0xb5, 0x1a, 0x43, 0xcf, 0x1a, 0x37,
+				0xf4, 0x70, 0xcc, 0xb4, 0xed, 0x07, 0x76, 0x3a,
+			}}},
+	// Server asks for cert with empty CA list, client gives one
+	// gotest -test.run "TestRunServer" -serve -clientauth 1
+	// gnutls-cli --insecure --debug 100 -p 10443 localhost
+	{"RequestClientCert, client gives it", RequestClientCert,
+		[]*x509.Certificate{clicert},
+		[][]byte{{
+			0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+			0x76, 0x03, 0x02, 0x4e, 0xe7, 0x44, 0xda, 0x58,
+			0x7d, 0x46, 0x4a, 0x48, 0x97, 0x9f, 0xe5, 0x91,
+			0x11, 0x64, 0xa7, 0x1e, 0x4d, 0xb7, 0xfe, 0x9b,
+			0xc6, 0x63, 0xf8, 0xa4, 0xb5, 0x0b, 0x18, 0xb5,
+			0xbd, 0x19, 0xb3, 0x00, 0x00, 0x34, 0x00, 0x33,
+			0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+			0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+			0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+			0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+			0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+			0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+			0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+			0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+			0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+			0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+		},
+
+			{
+				0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+				0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+				0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+				0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+				0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+				0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+				0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+				0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+				0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+				0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+				0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+				0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+				0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+				0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+				0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+				0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+				0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+				0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+				0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+				0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+				0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+				0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+				0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+				0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+				0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+				0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+				0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+				0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+				0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+				0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+				0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+				0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+				0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+				0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+				0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+				0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+				0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+				0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+				0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+				0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+				0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+				0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+				0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+				0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+				0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+				0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+				0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+				0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+				0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+				0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+				0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+				0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+				0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+				0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+				0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+				0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+				0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+				0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+				0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+				0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+				0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+				0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+				0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+				0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+				0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+				0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+				0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+				0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+				0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+				0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+				0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+				0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+				0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+				0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+				0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+				0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+				0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+				0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+				0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+				0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+				0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+				0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+				0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+				0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+				0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+				0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+				0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+				0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+				0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+				0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+				0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+				0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+			},
+
+			{
+				0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01,
+				0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30,
+				0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0,
+				0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30,
+				0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+				0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10,
+				0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+				0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+				0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+				0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+				0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d,
+				0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37,
+				0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31,
+				0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30,
+				0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10,
+				0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+				0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+				0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+				0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+				0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30,
+				0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+				0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00,
+				0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0,
+				0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0,
+				0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33,
+				0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84,
+				0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d,
+				0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5,
+				0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c,
+				0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87,
+				0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec,
+				0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01,
+				0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab,
+				0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e,
+				0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b,
+				0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec,
+				0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c,
+				0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13,
+				0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03,
+				0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30,
+				0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+				0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30,
+				0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06,
+				0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f,
+				0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30,
+				0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30,
+				0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+				0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00,
+				0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e,
+				0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7,
+				0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85,
+				0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32,
+				0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9,
+				0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15,
+				0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9,
+				0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84,
+				0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd,
+				0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6,
+				0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0,
+				0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c,
+				0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96,
+				0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18,
+				0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
+				0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
+				0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+				0x82, 0x00, 0x80, 0xa7, 0x2f, 0xed, 0xfa, 0xc2,
+				0xbd, 0x46, 0xa1, 0xf2, 0x69, 0xc5, 0x1d, 0xa1,
+				0x34, 0xd6, 0xd0, 0x84, 0xf5, 0x5d, 0x8c, 0x82,
+				0x8d, 0x98, 0x82, 0x9c, 0xd9, 0x07, 0xe0, 0xf7,
+				0x55, 0x49, 0x4d, 0xa1, 0x48, 0x59, 0x02, 0xd3,
+				0x84, 0x37, 0xaf, 0x01, 0xb3, 0x3a, 0xf4, 0xed,
+				0x99, 0xbe, 0x67, 0x36, 0x19, 0x55, 0xf3, 0xf9,
+				0xcb, 0x94, 0xe5, 0x7b, 0x8b, 0x77, 0xf2, 0x5f,
+				0x4c, 0xfe, 0x01, 0x1f, 0x7b, 0xd7, 0x23, 0x49,
+				0x0c, 0xcb, 0x6c, 0xb0, 0xe7, 0x77, 0xd6, 0xcf,
+				0xa8, 0x7d, 0xdb, 0xa7, 0x14, 0xe2, 0xf5, 0xf3,
+				0xff, 0xba, 0x23, 0xd2, 0x9a, 0x36, 0x14, 0x60,
+				0x2a, 0x91, 0x5d, 0x2b, 0x35, 0x3b, 0xb6, 0xdd,
+				0xcb, 0x6b, 0xdc, 0x18, 0xdc, 0x33, 0xb8, 0xb3,
+				0xc7, 0x27, 0x7e, 0xfc, 0xd2, 0xf7, 0x97, 0x90,
+				0x5e, 0x17, 0xac, 0x14, 0x8e, 0x0f, 0xca, 0xb5,
+				0x6f, 0xc9, 0x2d, 0x16, 0x03, 0x01, 0x00, 0x86,
+				0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x44, 0x7f,
+				0xa2, 0x59, 0x60, 0x0b, 0x5a, 0xc4, 0xaf, 0x1e,
+				0x60, 0xa5, 0x24, 0xea, 0xc1, 0xc3, 0x22, 0x21,
+				0x6b, 0x22, 0x8b, 0x2a, 0x11, 0x82, 0x68, 0x7d,
+				0xb9, 0xdd, 0x9c, 0x27, 0x4c, 0xc2, 0xc8, 0xa2,
+				0x8b, 0x6b, 0x77, 0x8d, 0x3a, 0x2b, 0x8d, 0x2f,
+				0x6a, 0x2b, 0x43, 0xd2, 0xd1, 0xc6, 0x41, 0x79,
+				0xa2, 0x4f, 0x2b, 0xc2, 0xf7, 0xb2, 0x10, 0xad,
+				0xa6, 0x01, 0x51, 0x51, 0x25, 0xe7, 0x58, 0x7a,
+				0xcf, 0x3b, 0xc4, 0x29, 0xb5, 0xe5, 0xa7, 0x83,
+				0xe6, 0xcb, 0x1e, 0xf3, 0x02, 0x0f, 0x53, 0x3b,
+				0xb5, 0x39, 0xef, 0x9c, 0x42, 0xe0, 0xa6, 0x9b,
+				0x2b, 0xdd, 0x60, 0xae, 0x0a, 0x73, 0x35, 0xbe,
+				0x26, 0x10, 0x1b, 0xe9, 0xe9, 0x61, 0xab, 0x20,
+				0xa5, 0x48, 0xc6, 0x60, 0xa6, 0x50, 0x3c, 0xfb,
+				0xa7, 0xca, 0xb0, 0x80, 0x95, 0x1e, 0xce, 0xc7,
+				0xbb, 0x68, 0x44, 0xdc, 0x0e, 0x0e, 0x14, 0x03,
+				0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
+				0x24, 0xb6, 0xcd, 0x0c, 0x78, 0xfd, 0xd6, 0xff,
+				0xbe, 0x97, 0xd5, 0x0a, 0x7d, 0x4f, 0xa1, 0x03,
+				0x78, 0xc8, 0x61, 0x6f, 0xf2, 0x4b, 0xa8, 0x56,
+				0x4f, 0x3c, 0xa2, 0xd9, 0xd0, 0x20, 0x13, 0x1b,
+				0x8b, 0x36, 0xb7, 0x33, 0x9c,
+			},
+
+			{
+				0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+				0x01, 0x00, 0x24, 0xa3, 0x43, 0x94, 0xe7, 0xdf,
+				0xb6, 0xc3, 0x03, 0x9f, 0xc1, 0x59, 0x0c, 0xc3,
+				0x13, 0xae, 0xed, 0xcf, 0xff, 0xf1, 0x80, 0xf3,
+				0x13, 0x63, 0x1c, 0xf0, 0xca, 0xad, 0x9e, 0x71,
+				0x46, 0x5f, 0x6b, 0xeb, 0x10, 0x3f, 0xe3, 0x17,
+				0x03, 0x01, 0x00, 0x21, 0xe9, 0x80, 0x95, 0x6e,
+				0x05, 0x55, 0x2f, 0xed, 0x4d, 0xde, 0x17, 0x3a,
+				0x32, 0x9b, 0x2a, 0x74, 0x30, 0x4f, 0xe0, 0x9f,
+				0x4e, 0xd3, 0x06, 0xbd, 0x3a, 0x43, 0x75, 0x8b,
+				0x5b, 0x9a, 0xd8, 0x2e, 0x56, 0x15, 0x03, 0x01,
+				0x00, 0x16, 0x53, 0xf5, 0xff, 0xe0, 0xa1, 0x6c,
+				0x33, 0xf4, 0x4e, 0x89, 0x68, 0xe1, 0xf7, 0x61,
+				0x13, 0xb3, 0x12, 0xa1, 0x8e, 0x5a, 0x7a, 0x02,
+			}}},
+}
+
+// cert.pem and key.pem were generated with generate_cert.go
+// Thus, they have no ExtKeyUsage fields and trigger an error
+// when verification is turned on.
+
+var clicert = loadPEMCert(`
+-----BEGIN CERTIFICATE-----
+MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
+bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
+MDAxMlowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGc
+MAsGCSqGSIb3DQEBAQOBjAAwgYgCgYBO0Hsx44Jk2VnAwoekXh6LczPHY1PfZpIG
+hPZk1Y/kNqcdK+izIDZFI7Xjla7t4PUgnI2V339aEu+H5Fto5OkOdOwEin/ekyfE
+ARl6vfLcPRSr0FTKIQzQTW6HLlzF0rtNS0/Otiz3fojsfNcCkXSmHgwa2uNKWi7e
+E5xMQIhZkwIDAQABozIwMDAOBgNVHQ8BAf8EBAMCAKAwDQYDVR0OBAYEBAECAwQw
+DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A
+p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4
+hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE
+GFGNEH5PlGffo05wc46QkYU=
+-----END CERTIFICATE-----
+`)
+
+/* corresponding key.pem for cert.pem is:
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
+NkUjteOVru3g9SCcjZXff1oS74fkW2jk6Q507ASKf96TJ8QBGXq98tw9FKvQVMoh
+DNBNbocuXMXSu01LT862LPd+iOx81wKRdKYeDBra40paLt4TnExAiFmTAgMBAAEC
+gYBxvXd8yNteFTns8A/2yomEMC4yeosJJSpp1CsN3BJ7g8/qTnrVPxBy+RU+qr63
+t2WquaOu/cr5P8iEsa6lk20tf8pjKLNXeX0b1RTzK8rJLbS7nGzP3tvOhL096VtQ
+dAo4ROEaro0TzYpHmpciSvxVIeEIAAdFDObDJPKqcJAxyQJBAJizfYgK8Gzx9fsx
+hxp+VteCbVPg2euASH5Yv3K5LukRdKoSzHE2grUVQgN/LafC0eZibRanxHegYSr7
+7qaswKUCQQCEIWor/X4XTMdVj3Oj+vpiw75y/S9gh682+myZL+d/02IEkwnB098P
+RkKVpenBHyrGg0oeN5La7URILWKj7CPXAkBKo6F+d+phNjwIFoN1Xb/RA32w/D1I
+saG9sF+UEhRt9AxUfW/U/tIQ9V0ZHHcSg1XaCM5Nvp934brdKdvTOKnJAkBD5h/3
+Rybatlvg/fzBEaJFyq09zhngkxlZOUtBVTqzl17RVvY2orgH02U4HbCHy4phxOn7
+qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN
+1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvAMAA=
+-----END RSA PRIVATE KEY-----
+*/
diff --git a/src/pkg/crypto/tls/key_agreement.go b/src/pkg/crypto/tls/key_agreement.go
index e347528..75f5c73 100644
--- a/src/pkg/crypto/tls/key_agreement.go
+++ b/src/pkg/crypto/tls/key_agreement.go
@@ -5,26 +5,26 @@
 package tls
 
 import (
-	"big"
 	"crypto"
 	"crypto/elliptic"
 	"crypto/md5"
 	"crypto/rsa"
 	"crypto/sha1"
 	"crypto/x509"
+	"errors"
 	"io"
-	"os"
+	"math/big"
 )
 
 // rsaKeyAgreement implements the standard TLS key agreement where the client
 // encrypts the pre-master secret to the server's public key.
 type rsaKeyAgreement struct{}
 
-func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
+func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
 	return nil, nil
 }
 
-func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, os.Error) {
+func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
 	preMasterSecret := make([]byte, 48)
 	_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
 	if err != nil {
@@ -32,19 +32,19 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKe
 	}
 
 	if len(ckx.ciphertext) < 2 {
-		return nil, os.NewError("bad ClientKeyExchange")
+		return nil, errors.New("bad ClientKeyExchange")
 	}
 
 	ciphertext := ckx.ciphertext
 	if version != versionSSL30 {
 		ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
 		if ciphertextLen != len(ckx.ciphertext)-2 {
-			return nil, os.NewError("bad ClientKeyExchange")
+			return nil, errors.New("bad ClientKeyExchange")
 		}
 		ciphertext = ckx.ciphertext[2:]
 	}
 
-	err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey, ciphertext, preMasterSecret)
+	err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
 	if err != nil {
 		return nil, err
 	}
@@ -57,11 +57,11 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKe
 	return preMasterSecret, nil
 }
 
-func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) os.Error {
-	return os.NewError("unexpected ServerKeyExchange")
+func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+	return errors.New("unexpected ServerKeyExchange")
 }
 
-func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error) {
+func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
 	preMasterSecret := make([]byte, 48)
 	preMasterSecret[0] = byte(clientHello.vers >> 8)
 	preMasterSecret[1] = byte(clientHello.vers)
@@ -90,13 +90,13 @@ func md5SHA1Hash(slices ...[]byte) []byte {
 	for _, slice := range slices {
 		hmd5.Write(slice)
 	}
-	copy(md5sha1, hmd5.Sum())
+	copy(md5sha1, hmd5.Sum(nil))
 
 	hsha1 := sha1.New()
 	for _, slice := range slices {
 		hsha1.Write(slice)
 	}
-	copy(md5sha1[md5.Size:], hsha1.Sum())
+	copy(md5sha1[md5.Size:], hsha1.Sum(nil))
 	return md5sha1
 }
 
@@ -105,11 +105,11 @@ func md5SHA1Hash(slices ...[]byte) []byte {
 // pre-master secret is then calculated using ECDH.
 type ecdheRSAKeyAgreement struct {
 	privateKey []byte
-	curve      *elliptic.Curve
+	curve      elliptic.Curve
 	x, y       *big.Int
 }
 
-func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, os.Error) {
+func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
 	var curveid uint16
 
 Curve:
@@ -131,12 +131,12 @@ Curve:
 	}
 
 	var x, y *big.Int
-	var err os.Error
-	ka.privateKey, x, y, err = ka.curve.GenerateKey(config.rand())
+	var err error
+	ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
 	if err != nil {
 		return nil, err
 	}
-	ecdhePublic := ka.curve.Marshal(x, y)
+	ecdhePublic := elliptic.Marshal(ka.curve, x, y)
 
 	// http://tools.ietf.org/html/rfc4492#section-5.4
 	serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
@@ -147,9 +147,9 @@ Curve:
 	copy(serverECDHParams[4:], ecdhePublic)
 
 	md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
-	sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey, crypto.MD5SHA1, md5sha1)
+	sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
 	if err != nil {
-		return nil, os.NewError("failed to sign ECDHE parameters: " + err.String())
+		return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
 	}
 
 	skx := new(serverKeyExchangeMsg)
@@ -163,30 +163,30 @@ Curve:
 	return skx, nil
 }
 
-func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, os.Error) {
+func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
 	if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
-		return nil, os.NewError("bad ClientKeyExchange")
+		return nil, errors.New("bad ClientKeyExchange")
 	}
-	x, y := ka.curve.Unmarshal(ckx.ciphertext[1:])
+	x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
 	if x == nil {
-		return nil, os.NewError("bad ClientKeyExchange")
+		return nil, errors.New("bad ClientKeyExchange")
 	}
 	x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
-	preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
+	preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
 	xBytes := x.Bytes()
 	copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
 
 	return preMasterSecret, nil
 }
 
-var errServerKeyExchange = os.NewError("invalid ServerKeyExchange")
+var errServerKeyExchange = errors.New("invalid ServerKeyExchange")
 
-func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) os.Error {
+func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
 	if len(skx.key) < 4 {
 		return errServerKeyExchange
 	}
 	if skx.key[0] != 3 { // named curve
-		return os.NewError("server selected unsupported curve")
+		return errors.New("server selected unsupported curve")
 	}
 	curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2])
 
@@ -198,14 +198,14 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH
 	case curveP521:
 		ka.curve = elliptic.P521()
 	default:
-		return os.NewError("server selected unsupported curve")
+		return errors.New("server selected unsupported curve")
 	}
 
 	publicLen := int(skx.key[3])
 	if publicLen+4 > len(skx.key) {
 		return errServerKeyExchange
 	}
-	ka.x, ka.y = ka.curve.Unmarshal(skx.key[4 : 4+publicLen])
+	ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
 	if ka.x == nil {
 		return errServerKeyExchange
 	}
@@ -225,20 +225,20 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH
 	return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig)
 }
 
-func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, os.Error) {
+func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
 	if ka.curve == nil {
-		return nil, nil, os.NewError("missing ServerKeyExchange message")
+		return nil, nil, errors.New("missing ServerKeyExchange message")
 	}
-	priv, mx, my, err := ka.curve.GenerateKey(config.rand())
+	priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
 	if err != nil {
 		return nil, nil, err
 	}
 	x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
-	preMasterSecret := make([]byte, (ka.curve.BitSize+7)>>3)
+	preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
 	xBytes := x.Bytes()
 	copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
 
-	serialized := ka.curve.Marshal(mx, my)
+	serialized := elliptic.Marshal(ka.curve, mx, my)
 
 	ckx := new(clientKeyExchangeMsg)
 	ckx.ciphertext = make([]byte, 1+len(serialized))
diff --git a/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py b/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py
index c03eaa6..5692bd3 100644
--- a/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py
+++ b/src/pkg/crypto/tls/parse-gnutls-cli-debug-log.py
@@ -35,6 +35,8 @@ for line in sys.stdin.readlines():
                 bs = line.split()
                 for b in bs:
                         currentBlock.append(int(b, 16))
+	elif line.startswith("|<7>| RB-PEEK: Read 1 bytes"):
+		currentBlock = currentBlock[:-1]
 
 if len(currentBlock) > 0:
         blocks.append(currentBlock)
diff --git a/src/pkg/crypto/tls/prf.go b/src/pkg/crypto/tls/prf.go
index 2d58dc5..637ef03 100644
--- a/src/pkg/crypto/tls/prf.go
+++ b/src/pkg/crypto/tls/prf.go
@@ -9,7 +9,6 @@ import (
 	"crypto/md5"
 	"crypto/sha1"
 	"hash"
-	"os"
 )
 
 // Split a premaster secret in two as specified in RFC 4346, section 5.
@@ -23,14 +22,14 @@ func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
 func pHash(result, secret, seed []byte, hash func() hash.Hash) {
 	h := hmac.New(hash, secret)
 	h.Write(seed)
-	a := h.Sum()
+	a := h.Sum(nil)
 
 	j := 0
 	for j < len(result) {
 		h.Reset()
 		h.Write(a)
 		h.Write(seed)
-		b := h.Sum()
+		b := h.Sum(nil)
 		todo := len(b)
 		if j+todo > len(result) {
 			todo = len(result) - j
@@ -40,7 +39,7 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) {
 
 		h.Reset()
 		h.Write(a)
-		a = h.Sum()
+		a = h.Sum(nil)
 	}
 }
 
@@ -85,13 +84,13 @@ func pRF30(result, secret, label, seed []byte) {
 		hashSHA1.Write(b[:i+1])
 		hashSHA1.Write(secret)
 		hashSHA1.Write(seed)
-		digest := hashSHA1.Sum()
+		digest := hashSHA1.Sum(nil)
 
 		hashMD5.Reset()
 		hashMD5.Write(secret)
 		hashMD5.Write(digest)
 
-		done += copy(result[done:], hashMD5.Sum())
+		done += copy(result[done:], hashMD5.Sum(nil))
 		i++
 	}
 }
@@ -156,7 +155,7 @@ type finishedHash struct {
 	version    uint16
 }
 
-func (h finishedHash) Write(msg []byte) (n int, err os.Error) {
+func (h finishedHash) Write(msg []byte) (n int, err error) {
 	h.clientMD5.Write(msg)
 	h.clientSHA1.Write(msg)
 	h.serverMD5.Write(msg)
@@ -183,24 +182,24 @@ func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []by
 	md5.Write(magic[:])
 	md5.Write(masterSecret)
 	md5.Write(ssl30Pad1[:])
-	md5Digest := md5.Sum()
+	md5Digest := md5.Sum(nil)
 
 	md5.Reset()
 	md5.Write(masterSecret)
 	md5.Write(ssl30Pad2[:])
 	md5.Write(md5Digest)
-	md5Digest = md5.Sum()
+	md5Digest = md5.Sum(nil)
 
 	sha1.Write(magic[:])
 	sha1.Write(masterSecret)
 	sha1.Write(ssl30Pad1[:40])
-	sha1Digest := sha1.Sum()
+	sha1Digest := sha1.Sum(nil)
 
 	sha1.Reset()
 	sha1.Write(masterSecret)
 	sha1.Write(ssl30Pad2[:40])
 	sha1.Write(sha1Digest)
-	sha1Digest = sha1.Sum()
+	sha1Digest = sha1.Sum(nil)
 
 	ret := make([]byte, len(md5Digest)+len(sha1Digest))
 	copy(ret, md5Digest)
@@ -218,8 +217,8 @@ func (h finishedHash) clientSum(masterSecret []byte) []byte {
 		return finishedSum30(h.clientMD5, h.clientSHA1, masterSecret, ssl3ClientFinishedMagic)
 	}
 
-	md5 := h.clientMD5.Sum()
-	sha1 := h.clientSHA1.Sum()
+	md5 := h.clientMD5.Sum(nil)
+	sha1 := h.clientSHA1.Sum(nil)
 	return finishedSum10(md5, sha1, clientFinishedLabel, masterSecret)
 }
 
@@ -230,7 +229,7 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte {
 		return finishedSum30(h.serverMD5, h.serverSHA1, masterSecret, ssl3ServerFinishedMagic)
 	}
 
-	md5 := h.serverMD5.Sum()
-	sha1 := h.serverSHA1.Sum()
+	md5 := h.serverMD5.Sum(nil)
+	sha1 := h.serverSHA1.Sum(nil)
 	return finishedSum10(md5, sha1, serverFinishedLabel, masterSecret)
 }
diff --git a/src/pkg/crypto/tls/root_darwin.go b/src/pkg/crypto/tls/root_darwin.go
new file mode 100644
index 0000000..db1b18b
--- /dev/null
+++ b/src/pkg/crypto/tls/root_darwin.go
@@ -0,0 +1,95 @@
+// Copyright 2011 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 tls
+
+/*
+// Note: We disable -Werror here because the code in this file uses a deprecated API to stay
+// compatible with both Mac OS X 10.6 and 10.7. Using a deprecated function on Darwin generates
+// a warning.
+#cgo CFLAGS: -Wno-error -Wno-deprecated-declarations
+#cgo LDFLAGS: -framework CoreFoundation -framework Security
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+
+// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
+//
+// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
+// certificates of the system. On failure, the function returns -1.
+//
+// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
+// we've consumed its content.
+int FetchPEMRoots(CFDataRef *pemRoots) {
+	if (pemRoots == NULL) {
+		return -1;
+	}
+
+	CFArrayRef certs = NULL;
+	OSStatus err = SecTrustCopyAnchorCertificates(&certs);
+	if (err != noErr) {
+		return -1;
+	}
+
+	CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
+	int i, ncerts = CFArrayGetCount(certs);
+	for (i = 0; i < ncerts; i++) {
+		CFDataRef data = NULL;
+		SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
+		if (cert == NULL) {
+			continue;
+		}
+
+		// SecKeychainImportExport is deprecated in >= OS X 10.7, and has been replaced by
+		// SecItemExport.  If we're built on a host with a Lion SDK, this code gets conditionally
+		// included in the output, also for binaries meant for 10.6.
+		//
+		// To make sure that we run on both Mac OS X 10.6 and 10.7 we use weak linking
+		// and check whether SecItemExport is available before we attempt to call it. On
+		// 10.6, this won't be the case, and we'll fall back to calling SecKeychainItemExport.
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+		if (SecItemExport) {
+			err = SecItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
+			if (err != noErr) {
+				continue;
+			}
+		} else
+#endif
+		if (data == NULL) {
+			err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
+			if (err != noErr) {
+				continue;
+			}
+		}
+
+		if (data != NULL) {
+			CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
+			CFRelease(data);
+		}
+	}
+
+	CFRelease(certs);
+
+	*pemRoots = combinedData;
+	return 0;
+}
+*/
+import "C"
+import (
+	"crypto/x509"
+	"unsafe"
+)
+
+func initDefaultRoots() {
+	roots := x509.NewCertPool()
+
+	var data C.CFDataRef = nil
+	err := C.FetchPEMRoots(&data)
+	if err != -1 {
+		defer C.CFRelease(C.CFTypeRef(data))
+		buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
+		roots.AppendCertsFromPEM(buf)
+	}
+
+	varDefaultRoots = roots
+}
diff --git a/src/pkg/crypto/tls/root_stub.go b/src/pkg/crypto/tls/root_stub.go
new file mode 100644
index 0000000..ee2c3e0
--- /dev/null
+++ b/src/pkg/crypto/tls/root_stub.go
@@ -0,0 +1,10 @@
+// Copyright 2011 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 plan9 darwin,!cgo
+
+package tls
+
+func initDefaultRoots() {
+}
diff --git a/src/pkg/crypto/tls/root_test.go b/src/pkg/crypto/tls/root_test.go
new file mode 100644
index 0000000..95a89d8
--- /dev/null
+++ b/src/pkg/crypto/tls/root_test.go
@@ -0,0 +1,36 @@
+// Copyright 2011 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 tls
+
+import (
+	"testing"
+)
+
+var tlsServers = []string{
+	"google.com:443",
+	"github.com:443",
+	"twitter.com:443",
+}
+
+func TestOSCertBundles(t *testing.T) {
+	defaultRoots()
+
+	if testing.Short() {
+		t.Logf("skipping certificate tests in short mode")
+		return
+	}
+
+	for _, addr := range tlsServers {
+		conn, err := Dial("tcp", addr, nil)
+		if err != nil {
+			t.Errorf("unable to verify %v: %v", addr, err)
+			continue
+		}
+		err = conn.Close()
+		if err != nil {
+			t.Error(err)
+		}
+	}
+}
diff --git a/src/pkg/crypto/tls/root_unix.go b/src/pkg/crypto/tls/root_unix.go
new file mode 100644
index 0000000..acaf3dd
--- /dev/null
+++ b/src/pkg/crypto/tls/root_unix.go
@@ -0,0 +1,33 @@
+// Copyright 2011 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 freebsd linux openbsd netbsd
+
+package tls
+
+import (
+	"crypto/x509"
+	"io/ioutil"
+)
+
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+	"/etc/ssl/certs/ca-certificates.crt",     // Linux etc
+	"/etc/pki/tls/certs/ca-bundle.crt",       // Fedora/RHEL
+	"/etc/ssl/ca-bundle.pem",                 // OpenSUSE
+	"/etc/ssl/cert.pem",                      // OpenBSD
+	"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD
+}
+
+func initDefaultRoots() {
+	roots := x509.NewCertPool()
+	for _, file := range certFiles {
+		data, err := ioutil.ReadFile(file)
+		if err == nil {
+			roots.AppendCertsFromPEM(data)
+			break
+		}
+	}
+	varDefaultRoots = roots
+}
diff --git a/src/pkg/crypto/tls/root_windows.go b/src/pkg/crypto/tls/root_windows.go
new file mode 100644
index 0000000..319309a
--- /dev/null
+++ b/src/pkg/crypto/tls/root_windows.go
@@ -0,0 +1,47 @@
+// Copyright 2011 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 tls
+
+import (
+	"crypto/x509"
+	"syscall"
+	"unsafe"
+)
+
+func loadStore(roots *x509.CertPool, name string) {
+	store, err := syscall.CertOpenSystemStore(syscall.InvalidHandle, syscall.StringToUTF16Ptr(name))
+	if err != nil {
+		return
+	}
+	defer syscall.CertCloseStore(store, 0)
+
+	var cert *syscall.CertContext
+	for {
+		cert, err = syscall.CertEnumCertificatesInStore(store, cert)
+		if err != nil {
+			return
+		}
+
+		buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
+		// ParseCertificate requires its own copy of certificate data to keep.
+		buf2 := make([]byte, cert.Length)
+		copy(buf2, buf)
+		if c, err := x509.ParseCertificate(buf2); err == nil {
+			roots.AddCert(c)
+		}
+	}
+}
+
+func initDefaultRoots() {
+	roots := x509.NewCertPool()
+
+	// Roots
+	loadStore(roots, "ROOT")
+
+	// Intermediates
+	loadStore(roots, "CA")
+
+	varDefaultRoots = roots
+}
diff --git a/src/pkg/crypto/tls/tls.go b/src/pkg/crypto/tls/tls.go
index 4f0859f..28e93a0 100644
--- a/src/pkg/crypto/tls/tls.go
+++ b/src/pkg/crypto/tls/tls.go
@@ -10,9 +10,9 @@ import (
 	"crypto/rsa"
 	"crypto/x509"
 	"encoding/pem"
+	"errors"
 	"io/ioutil"
 	"net"
-	"os"
 	"strings"
 )
 
@@ -41,7 +41,7 @@ type Listener struct {
 
 // Accept waits for and returns the next incoming TLS connection.
 // The returned connection c is a *tls.Conn.
-func (l *Listener) Accept() (c net.Conn, err os.Error) {
+func (l *Listener) Accept() (c net.Conn, err error) {
 	c, err = l.listener.Accept()
 	if err != nil {
 		return
@@ -51,7 +51,7 @@ func (l *Listener) Accept() (c net.Conn, err os.Error) {
 }
 
 // Close closes the listener.
-func (l *Listener) Close() os.Error { return l.listener.Close() }
+func (l *Listener) Close() error { return l.listener.Close() }
 
 // Addr returns the listener's network address.
 func (l *Listener) Addr() net.Addr { return l.listener.Addr() }
@@ -71,9 +71,9 @@ func NewListener(listener net.Listener, config *Config) (l *Listener) {
 // given network address using net.Listen.
 // The configuration config must be non-nil and must have
 // at least one certificate.
-func Listen(network, laddr string, config *Config) (*Listener, os.Error) {
+func Listen(network, laddr string, config *Config) (*Listener, error) {
 	if config == nil || len(config.Certificates) == 0 {
-		return nil, os.NewError("tls.Listen: no certificates in configuration")
+		return nil, errors.New("tls.Listen: no certificates in configuration")
 	}
 	l, err := net.Listen(network, laddr)
 	if err != nil {
@@ -88,7 +88,7 @@ func Listen(network, laddr string, config *Config) (*Listener, os.Error) {
 // Dial interprets a nil configuration as equivalent to
 // the zero configuration; see the documentation of Config
 // for the defaults.
-func Dial(network, addr string, config *Config) (*Conn, os.Error) {
+func Dial(network, addr string, config *Config) (*Conn, error) {
 	raddr := addr
 	c, err := net.Dial(network, raddr)
 	if err != nil {
@@ -120,7 +120,7 @@ func Dial(network, addr string, config *Config) (*Conn, os.Error) {
 
 // LoadX509KeyPair reads and parses a public/private key pair from a pair of
 // files. The files must contain PEM encoded data.
-func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.Error) {
+func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) {
 	certPEMBlock, err := ioutil.ReadFile(certFile)
 	if err != nil {
 		return
@@ -134,7 +134,7 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.
 
 // X509KeyPair parses a public/private key pair from a pair of
 // PEM encoded data.
-func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err os.Error) {
+func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error) {
 	var certDERBlock *pem.Block
 	for {
 		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
@@ -147,20 +147,31 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err os.Err
 	}
 
 	if len(cert.Certificate) == 0 {
-		err = os.NewError("crypto/tls: failed to parse certificate PEM data")
+		err = errors.New("crypto/tls: failed to parse certificate PEM data")
 		return
 	}
 
 	keyDERBlock, _ := pem.Decode(keyPEMBlock)
 	if keyDERBlock == nil {
-		err = os.NewError("crypto/tls: failed to parse key PEM data")
+		err = errors.New("crypto/tls: failed to parse key PEM data")
 		return
 	}
 
-	key, err := x509.ParsePKCS1PrivateKey(keyDERBlock.Bytes)
-	if err != nil {
-		err = os.NewError("crypto/tls: failed to parse key: " + err.String())
-		return
+	// OpenSSL 0.9.8 generates PKCS#1 private keys by default, while
+	// OpenSSL 1.0.0 generates PKCS#8 keys. We try both.
+	var key *rsa.PrivateKey
+	if key, err = x509.ParsePKCS1PrivateKey(keyDERBlock.Bytes); err != nil {
+		var privKey interface{}
+		if privKey, err = x509.ParsePKCS8PrivateKey(keyDERBlock.Bytes); err != nil {
+			err = errors.New("crypto/tls: failed to parse key: " + err.Error())
+			return
+		}
+
+		var ok bool
+		if key, ok = privKey.(*rsa.PrivateKey); !ok {
+			err = errors.New("crypto/tls: found non-RSA private key in PKCS#8 wrapping")
+			return
+		}
 	}
 
 	cert.PrivateKey = key
@@ -173,7 +184,7 @@ func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err os.Err
 	}
 
 	if x509Cert.PublicKeyAlgorithm != x509.RSA || x509Cert.PublicKey.(*rsa.PublicKey).N.Cmp(key.PublicKey.N) != 0 {
-		err = os.NewError("crypto/tls: private key does not match public key")
+		err = errors.New("crypto/tls: private key does not match public key")
 		return
 	}
 
diff --git a/src/pkg/crypto/twofish/Makefile b/src/pkg/crypto/twofish/Makefile
deleted file mode 100644
index aec6165..0000000
--- a/src/pkg/crypto/twofish/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/twofish
-GOFILES=\
-	twofish.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/twofish/twofish.go b/src/pkg/crypto/twofish/twofish.go
deleted file mode 100644
index 2e537c6..0000000
--- a/src/pkg/crypto/twofish/twofish.go
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright 2011 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 twofish implements Bruce Schneier's Twofish encryption algorithm.
-package twofish
-
-// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
-
-// This code is a port of the LibTom C implementation.
-// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt.
-// LibTomCrypt is free for all purposes under the public domain.
-// It was heavily inspired by the go blowfish package.
-
-import (
-	"os"
-	"strconv"
-)
-
-// BlockSize is the constant block size of Twofish.
-const BlockSize = 16
-
-const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
-const rsPolynomial = 0x14d  // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3
-
-// A Cipher is an instance of Twofish encryption using a particular key.
-type Cipher struct {
-	s [4][256]uint32
-	k [40]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) String() string {
-	return "crypto/twofish: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a Cipher.
-// The key argument should be the Twofish key, 16, 24 or 32 bytes.
-func NewCipher(key []byte) (*Cipher, os.Error) {
-	keylen := len(key)
-
-	if keylen != 16 && keylen != 24 && keylen != 32 {
-		return nil, KeySizeError(keylen)
-	}
-
-	// k is the number of 64 bit words in key
-	k := keylen / 8
-
-	// Create the S[..] words
-	var S [4 * 4]byte
-	for i := 0; i < k; i++ {
-		// Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7]
-		for j, rsRow := range rs {
-			for k, rsVal := range rsRow {
-				S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial)
-			}
-		}
-	}
-
-	// Calculate subkeys
-	c := new(Cipher)
-	var tmp [4]byte
-	for i := byte(0); i < 20; i++ {
-		// A = h(p * 2x, Me)
-		for j := range tmp {
-			tmp[j] = 2 * i
-		}
-		A := h(tmp[:], key, 0)
-
-		// B = rolc(h(p * (2x + 1), Mo), 8)
-		for j := range tmp {
-			tmp[j] = 2*i + 1
-		}
-		B := h(tmp[:], key, 1)
-		B = rol(B, 8)
-
-		c.k[2*i] = A + B
-
-		// K[2i+1] = (A + 2B) <<< 9
-		c.k[2*i+1] = rol(2*B+A, 9)
-	}
-
-	// Calculate sboxes
-	switch k {
-	case 2:
-		for i := range c.s[0] {
-			c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0)
-			c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1)
-			c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2)
-			c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3)
-		}
-	case 3:
-		for i := range c.s[0] {
-			c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0)
-			c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1)
-			c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2)
-			c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3)
-		}
-	default:
-		for i := range c.s[0] {
-			c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0)
-			c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1)
-			c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2)
-			c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3)
-		}
-	}
-
-	return c, nil
-}
-
-// Reset zeros the key data, so that it will no longer appear in the process's
-// memory.
-func (c *Cipher) Reset() {
-	for i := range c.k {
-		c.k[i] = 0
-	}
-	for i := range c.s {
-		for j := 0; j < 256; j++ {
-			c.s[i][j] = 0
-		}
-	}
-}
-
-// BlockSize returns the Twofish block size, 16 bytes.
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// store32l stores src in dst in little-endian form.
-func store32l(dst []byte, src uint32) {
-	dst[0] = byte(src)
-	dst[1] = byte(src >> 8)
-	dst[2] = byte(src >> 16)
-	dst[3] = byte(src >> 24)
-	return
-}
-
-// load32l reads a little-endian uint32 from src.
-func load32l(src []byte) uint32 {
-	return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24
-}
-
-// rol returns x after a left circular rotation of y bits.
-func rol(x, y uint32) uint32 {
-	return (x << (y & 31)) | (x >> (32 - (y & 31)))
-}
-
-// ror returns x after a right circular rotation of y bits.
-func ror(x, y uint32) uint32 {
-	return (x >> (y & 31)) | (x << (32 - (y & 31)))
-}
-
-// The RS matrix. See [TWOFISH] 4.3
-var rs = [4][8]byte{
-	{0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E},
-	{0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5},
-	{0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19},
-	{0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03},
-}
-
-// sbox tables
-var sbox = [2][256]byte{
-	{
-		0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38,
-		0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48,
-		0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82,
-		0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61,
-		0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
-		0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7,
-		0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71,
-		0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7,
-		0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90,
-		0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
-		0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64,
-		0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a,
-		0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d,
-		0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
-		0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
-		0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0,
-	},
-	{
-		0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b,
-		0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f,
-		0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5,
-		0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51,
-		0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
-		0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8,
-		0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2,
-		0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17,
-		0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e,
-		0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
-		0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48,
-		0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64,
-		0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69,
-		0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc,
-		0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
-		0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91,
-	},
-}
-
-// gfMult returns a·b in GF(2^8)/p
-func gfMult(a, b byte, p uint32) byte {
-	B := [2]uint32{0, uint32(b)}
-	P := [2]uint32{0, p}
-	var result uint32
-
-	// branchless GF multiplier
-	for i := 0; i < 7; i++ {
-		result ^= B[a&1]
-		a >>= 1
-		B[1] = P[B[1]>>7] ^ (B[1] << 1)
-	}
-	result ^= B[a&1]
-	return byte(result)
-}
-
-// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0]
-func mdsColumnMult(in byte, col int) uint32 {
-	mul01 := in
-	mul5B := gfMult(in, 0x5B, mdsPolynomial)
-	mulEF := gfMult(in, 0xEF, mdsPolynomial)
-
-	switch col {
-	case 0:
-		return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24
-	case 1:
-		return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24
-	case 2:
-		return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24
-	case 3:
-		return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24
-	}
-
-	panic("unreachable")
-}
-
-// h implements the S-box generation function. See [TWOFISH] 4.3.5
-func h(in, key []byte, offset int) uint32 {
-	var y [4]byte
-	for x := range y {
-		y[x] = in[x]
-	}
-	switch len(key) / 8 {
-	case 4:
-		y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0]
-		y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1]
-		y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2]
-		y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3]
-		fallthrough
-	case 3:
-		y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0]
-		y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1]
-		y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2]
-		y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3]
-		fallthrough
-	case 2:
-		y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]]
-		y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]]
-		y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]]
-		y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]]
-	}
-	// [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3]
-	var mdsMult uint32
-	for i := range y {
-		mdsMult ^= mdsColumnMult(y[i], i)
-	}
-	return mdsMult
-}
-
-// Encrypt encrypts a 16-byte block from src to dst, which may overlap.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) {
-	S1 := c.s[0]
-	S2 := c.s[1]
-	S3 := c.s[2]
-	S4 := c.s[3]
-
-	// Load input
-	ia := load32l(src[0:4])
-	ib := load32l(src[4:8])
-	ic := load32l(src[8:12])
-	id := load32l(src[12:16])
-
-	// Pre-whitening
-	ia ^= c.k[0]
-	ib ^= c.k[1]
-	ic ^= c.k[2]
-	id ^= c.k[3]
-
-	for i := 0; i < 8; i++ {
-		k := c.k[8+i*4 : 12+i*4]
-		t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
-		t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
-		ic = ror(ic^(t1+k[0]), 1)
-		id = rol(id, 1) ^ (t2 + t1 + k[1])
-
-		t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
-		t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
-		ia = ror(ia^(t1+k[2]), 1)
-		ib = rol(ib, 1) ^ (t2 + t1 + k[3])
-	}
-
-	// Output with "undo last swap"
-	ta := ic ^ c.k[4]
-	tb := id ^ c.k[5]
-	tc := ia ^ c.k[6]
-	td := ib ^ c.k[7]
-
-	store32l(dst[0:4], ta)
-	store32l(dst[4:8], tb)
-	store32l(dst[8:12], tc)
-	store32l(dst[12:16], td)
-}
-
-// Decrypt decrypts a 16-byte block from src to dst, which may overlap.
-func (c *Cipher) Decrypt(dst, src []byte) {
-	S1 := c.s[0]
-	S2 := c.s[1]
-	S3 := c.s[2]
-	S4 := c.s[3]
-
-	// Load input
-	ta := load32l(src[0:4])
-	tb := load32l(src[4:8])
-	tc := load32l(src[8:12])
-	td := load32l(src[12:16])
-
-	// Undo undo final swap
-	ia := tc ^ c.k[6]
-	ib := td ^ c.k[7]
-	ic := ta ^ c.k[4]
-	id := tb ^ c.k[5]
-
-	for i := 8; i > 0; i-- {
-		k := c.k[4+i*4 : 8+i*4]
-		t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
-		t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
-		ia = rol(ia, 1) ^ (t1 + k[2])
-		ib = ror(ib^(t2+t1+k[3]), 1)
-
-		t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
-		t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
-		ic = rol(ic, 1) ^ (t1 + k[0])
-		id = ror(id^(t2+t1+k[1]), 1)
-	}
-
-	// Undo pre-whitening
-	ia ^= c.k[0]
-	ib ^= c.k[1]
-	ic ^= c.k[2]
-	id ^= c.k[3]
-
-	store32l(dst[0:4], ia)
-	store32l(dst[4:8], ib)
-	store32l(dst[8:12], ic)
-	store32l(dst[12:16], id)
-}
diff --git a/src/pkg/crypto/twofish/twofish_test.go b/src/pkg/crypto/twofish/twofish_test.go
deleted file mode 100644
index 303081f..0000000
--- a/src/pkg/crypto/twofish/twofish_test.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2011 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 twofish
-
-import (
-	"bytes"
-	"testing"
-)
-
-var qbox = [2][4][16]byte{
-	{
-		{0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4},
-		{0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD},
-		{0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1},
-		{0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA},
-	},
-	{
-		{0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5},
-		{0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8},
-		{0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF},
-		{0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA},
-	},
-}
-
-// genSbox generates the variable sbox
-func genSbox(qi int, x byte) byte {
-	a0, b0 := x/16, x%16
-	for i := 0; i < 2; i++ {
-		a1 := a0 ^ b0
-		b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15
-		a0 = qbox[qi][2*i][a1]
-		b0 = qbox[qi][2*i+1][b1]
-	}
-	return (b0 << 4) + a0
-}
-
-func TestSbox(t *testing.T) {
-	for n := range sbox {
-		for m := range sbox[n] {
-			if genSbox(n, byte(m)) != sbox[n][m] {
-				t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m)))
-			}
-		}
-	}
-}
-
-var testVectors = []struct {
-	key []byte
-	dec []byte
-	enc []byte
-}{
-	// These tests are extracted from LibTom
-	{
-		[]byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
-		[]byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19},
-		[]byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3},
-	},
-	{
-		[]byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
-			0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44},
-		[]byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2},
-		[]byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65},
-	},
-	{
-		[]byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
-			0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F},
-		[]byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6},
-		[]byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA},
-	},
-	// These test are derived from http://www.schneier.com/code/ecb_ival.txt
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
-	},
-	{
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-		},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48},
-	},
-	{
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
-		},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20},
-	},
-}
-
-func TestCipher(t *testing.T) {
-	for n, tt := range testVectors {
-		// Test if the plaintext (dec) is encrypts to the given
-		// ciphertext (enc) using the given key. Test also if enc can
-		// be decrypted again into dec.
-		c, err := NewCipher(tt.key)
-		if err != nil {
-			t.Errorf("#%d: NewCipher: %v", n, err)
-			return
-		}
-
-		buf := make([]byte, 16)
-		c.Encrypt(buf, tt.dec)
-		if !bytes.Equal(buf, tt.enc) {
-			t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc)
-		}
-		c.Decrypt(buf, tt.enc)
-		if !bytes.Equal(buf, tt.dec) {
-			t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec)
-		}
-
-		// Test that 16 zero bytes, encrypted 1000 times then decrypted
-		// 1000 times results in zero bytes again.
-		zero := make([]byte, 16)
-		buf = make([]byte, 16)
-		for i := 0; i < 1000; i++ {
-			c.Encrypt(buf, buf)
-		}
-		for i := 0; i < 1000; i++ {
-			c.Decrypt(buf, buf)
-		}
-		if !bytes.Equal(buf, zero) {
-			t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero)
-		}
-	}
-}
diff --git a/src/pkg/crypto/x509/Makefile b/src/pkg/crypto/x509/Makefile
index 14ffd09..91d1052 100644
--- a/src/pkg/crypto/x509/Makefile
+++ b/src/pkg/crypto/x509/Makefile
@@ -7,6 +7,8 @@ include ../../../Make.inc
 TARG=crypto/x509
 GOFILES=\
 	cert_pool.go\
+	pkcs1.go\
+	pkcs8.go\
 	verify.go\
 	x509.go\
 
diff --git a/src/pkg/crypto/x509/cert_pool.go b/src/pkg/crypto/x509/cert_pool.go
index 16cd92e..616a0b3 100644
--- a/src/pkg/crypto/x509/cert_pool.go
+++ b/src/pkg/crypto/x509/cert_pool.go
@@ -5,12 +5,10 @@
 package x509
 
 import (
-	"crypto/x509/pkix"
 	"encoding/pem"
-	"strings"
 )
 
-// Roots is a set of certificates.
+// CertPool is a set of certificates.
 type CertPool struct {
 	bySubjectKeyId map[string][]int
 	byName         map[string][]int
@@ -26,21 +24,20 @@ func NewCertPool() *CertPool {
 	}
 }
 
-func nameToKey(name *pkix.Name) string {
-	return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
-}
-
 // findVerifiedParents attempts to find certificates in s which have signed the
 // given certificate. If no such certificate can be found or the signature
 // doesn't match, it returns nil.
 func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
+	if s == nil {
+		return
+	}
 	var candidates []int
 
 	if len(cert.AuthorityKeyId) > 0 {
 		candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
 	}
 	if len(candidates) == 0 {
-		candidates = s.byName[nameToKey(&cert.Issuer)]
+		candidates = s.byName[string(cert.RawIssuer)]
 	}
 
 	for _, c := range candidates {
@@ -72,15 +69,15 @@ func (s *CertPool) AddCert(cert *Certificate) {
 		keyId := string(cert.SubjectKeyId)
 		s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
 	}
-	name := nameToKey(&cert.Subject)
+	name := string(cert.RawSubject)
 	s.byName[name] = append(s.byName[name], n)
 }
 
-// AppendCertsFromPEM attempts to parse a series of PEM encoded root
-// certificates. It appends any certificates found to s and returns true if any
-// certificates were successfully parsed.
+// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
+// It appends any certificates found to s and returns true if any certificates
+// were successfully parsed.
 //
-// On many Linux systems, /etc/ssl/cert.pem will contains the system wide set
+// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
 // of root CAs in a format suitable for this function.
 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
 	for len(pemCerts) > 0 {
@@ -104,3 +101,13 @@ func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
 
 	return
 }
+
+// Subjects returns a list of the DER-encoded subjects of
+// all of the certificates in the pool. 
+func (s *CertPool) Subjects() (res [][]byte) {
+	res = make([][]byte, len(s.certs))
+	for i, c := range s.certs {
+		res[i] = c.RawSubject
+	}
+	return
+}
diff --git a/src/pkg/crypto/x509/pkcs1.go b/src/pkg/crypto/x509/pkcs1.go
new file mode 100644
index 0000000..31d0dd0
--- /dev/null
+++ b/src/pkg/crypto/x509/pkcs1.go
@@ -0,0 +1,122 @@
+// Copyright 2011 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 x509
+
+import (
+	"crypto/rsa"
+	"encoding/asn1"
+	"errors"
+	"math/big"
+)
+
+// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
+type pkcs1PrivateKey struct {
+	Version int
+	N       *big.Int
+	E       int
+	D       *big.Int
+	P       *big.Int
+	Q       *big.Int
+	// We ignore these values, if present, because rsa will calculate them.
+	Dp   *big.Int `asn1:"optional"`
+	Dq   *big.Int `asn1:"optional"`
+	Qinv *big.Int `asn1:"optional"`
+
+	AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional"`
+}
+
+type pkcs1AdditionalRSAPrime struct {
+	Prime *big.Int
+
+	// We ignore these values because rsa will calculate them.
+	Exp   *big.Int
+	Coeff *big.Int
+}
+
+// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
+func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) {
+	var priv pkcs1PrivateKey
+	rest, err := asn1.Unmarshal(der, &priv)
+	if len(rest) > 0 {
+		err = asn1.SyntaxError{"trailing data"}
+		return
+	}
+	if err != nil {
+		return
+	}
+
+	if priv.Version > 1 {
+		return nil, errors.New("x509: unsupported private key version")
+	}
+
+	if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
+		return nil, errors.New("private key contains zero or negative value")
+	}
+
+	key = new(rsa.PrivateKey)
+	key.PublicKey = rsa.PublicKey{
+		E: priv.E,
+		N: priv.N,
+	}
+
+	key.D = priv.D
+	key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
+	key.Primes[0] = priv.P
+	key.Primes[1] = priv.Q
+	for i, a := range priv.AdditionalPrimes {
+		if a.Prime.Sign() <= 0 {
+			return nil, errors.New("private key contains zero or negative prime")
+		}
+		key.Primes[i+2] = a.Prime
+		// We ignore the other two values because rsa will calculate
+		// them as needed.
+	}
+
+	err = key.Validate()
+	if err != nil {
+		return nil, err
+	}
+	key.Precompute()
+
+	return
+}
+
+// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
+func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
+	key.Precompute()
+
+	version := 0
+	if len(key.Primes) > 2 {
+		version = 1
+	}
+
+	priv := pkcs1PrivateKey{
+		Version: version,
+		N:       key.N,
+		E:       key.PublicKey.E,
+		D:       key.D,
+		P:       key.Primes[0],
+		Q:       key.Primes[1],
+		Dp:      key.Precomputed.Dp,
+		Dq:      key.Precomputed.Dq,
+		Qinv:    key.Precomputed.Qinv,
+	}
+
+	priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
+	for i, values := range key.Precomputed.CRTValues {
+		priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
+		priv.AdditionalPrimes[i].Exp = values.Exp
+		priv.AdditionalPrimes[i].Coeff = values.Coeff
+	}
+
+	b, _ := asn1.Marshal(priv)
+	return b
+}
+
+// rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
+type rsaPublicKey struct {
+	N *big.Int
+	E int
+}
diff --git a/src/pkg/crypto/x509/pkcs8.go b/src/pkg/crypto/x509/pkcs8.go
new file mode 100644
index 0000000..4d8e051
--- /dev/null
+++ b/src/pkg/crypto/x509/pkcs8.go
@@ -0,0 +1,42 @@
+// Copyright 2011 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 x509
+
+import (
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"errors"
+	"fmt"
+)
+
+// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See 
+// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn.
+type pkcs8 struct {
+	Version    int
+	Algo       pkix.AlgorithmIdentifier
+	PrivateKey []byte
+	// optional attributes omitted.
+}
+
+// ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key. See
+// http://www.rsa.com/rsalabs/node.asp?id=2130
+func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
+	var privKey pkcs8
+	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
+		return nil, err
+	}
+	switch {
+	case privKey.Algo.Algorithm.Equal(oidRSA):
+		key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
+		if err != nil {
+			return nil, errors.New("crypto/x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
+		}
+		return key, nil
+	default:
+		return nil, fmt.Errorf("crypto/x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
+	}
+
+	panic("unreachable")
+}
diff --git a/src/pkg/crypto/x509/pkcs8_test.go b/src/pkg/crypto/x509/pkcs8_test.go
new file mode 100644
index 0000000..372005f
--- /dev/null
+++ b/src/pkg/crypto/x509/pkcs8_test.go
@@ -0,0 +1,20 @@
+// Copyright 2011 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 x509
+
+import (
+	"encoding/hex"
+	"testing"
+)
+
+var pkcs8PrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031`
+
+func TestPKCS8(t *testing.T) {
+	derBytes, _ := hex.DecodeString(pkcs8PrivateKeyHex)
+	_, err := ParsePKCS8PrivateKey(derBytes)
+	if err != nil {
+		t.Errorf("failed to decode PKCS8 key: %s", err)
+	}
+}
diff --git a/src/pkg/crypto/x509/pkix/pkix.go b/src/pkg/crypto/x509/pkix/pkix.go
index 266fd55..8eced55 100644
--- a/src/pkg/crypto/x509/pkix/pkix.go
+++ b/src/pkg/crypto/x509/pkix/pkix.go
@@ -7,8 +7,8 @@
 package pkix
 
 import (
-	"asn1"
-	"big"
+	"encoding/asn1"
+	"math/big"
 	"time"
 )
 
@@ -43,6 +43,8 @@ type Name struct {
 	Locality, Province                        []string
 	StreetAddress, PostalCode                 []string
 	SerialNumber, CommonName                  string
+
+	Names []AttributeTypeAndValue
 }
 
 func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
@@ -51,6 +53,7 @@ func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
 			continue
 		}
 		atv := rdn[0]
+		n.Names = append(n.Names, atv)
 		value, ok := atv.Value.(string)
 		if !ok {
 			continue
@@ -139,10 +142,9 @@ type CertificateList struct {
 	SignatureValue     asn1.BitString
 }
 
-// HasExpired returns true iff currentTimeSeconds is past the expiry time of
-// certList.
-func (certList *CertificateList) HasExpired(currentTimeSeconds int64) bool {
-	return certList.TBSCertList.NextUpdate.Seconds() <= currentTimeSeconds
+// HasExpired returns true iff now is past the expiry time of certList.
+func (certList *CertificateList) HasExpired(now time.Time) bool {
+	return now.After(certList.TBSCertList.NextUpdate)
 }
 
 // TBSCertificateList represents the ASN.1 structure of the same name. See RFC
@@ -152,8 +154,8 @@ type TBSCertificateList struct {
 	Version             int `asn1:"optional,default:2"`
 	Signature           AlgorithmIdentifier
 	Issuer              RDNSequence
-	ThisUpdate          *time.Time
-	NextUpdate          *time.Time
+	ThisUpdate          time.Time
+	NextUpdate          time.Time
 	RevokedCertificates []RevokedCertificate `asn1:"optional"`
 	Extensions          []Extension          `asn1:"tag:0,optional,explicit"`
 }
@@ -162,6 +164,6 @@ type TBSCertificateList struct {
 // 5280, section 5.1.
 type RevokedCertificate struct {
 	SerialNumber   *big.Int
-	RevocationTime *time.Time
+	RevocationTime time.Time
 	Extensions     []Extension `asn1:"optional"`
 }
diff --git a/src/pkg/crypto/x509/verify.go b/src/pkg/crypto/x509/verify.go
index 4c0fecc..50a3b66 100644
--- a/src/pkg/crypto/x509/verify.go
+++ b/src/pkg/crypto/x509/verify.go
@@ -5,7 +5,6 @@
 package x509
 
 import (
-	"os"
 	"strings"
 	"time"
 )
@@ -32,7 +31,7 @@ type CertificateInvalidError struct {
 	Reason InvalidReason
 }
 
-func (e CertificateInvalidError) String() string {
+func (e CertificateInvalidError) Error() string {
 	switch e.Reason {
 	case NotAuthorizedToSign:
 		return "x509: certificate is not authorized to sign other other certificates"
@@ -51,7 +50,7 @@ type HostnameError struct {
 	Host        string
 }
 
-func (h HostnameError) String() string {
+func (h HostnameError) Error() string {
 	var valid string
 	c := h.Certificate
 	if len(c.DNSNames) > 0 {
@@ -67,7 +66,7 @@ type UnknownAuthorityError struct {
 	cert *Certificate
 }
 
-func (e UnknownAuthorityError) String() string {
+func (e UnknownAuthorityError) Error() string {
 	return "x509: certificate signed by unknown authority"
 }
 
@@ -77,7 +76,7 @@ type VerifyOptions struct {
 	DNSName       string
 	Intermediates *CertPool
 	Roots         *CertPool
-	CurrentTime   int64 // if 0, the current system time is used.
+	CurrentTime   time.Time // if zero, the current time is used
 }
 
 const (
@@ -87,9 +86,12 @@ const (
 )
 
 // isValid performs validity checks on the c.
-func (c *Certificate) isValid(certType int, opts *VerifyOptions) os.Error {
-	if opts.CurrentTime < c.NotBefore.Seconds() ||
-		opts.CurrentTime > c.NotAfter.Seconds() {
+func (c *Certificate) isValid(certType int, opts *VerifyOptions) error {
+	now := opts.CurrentTime
+	if now.IsZero() {
+		now = time.Now()
+	}
+	if now.Before(c.NotBefore) || now.After(c.NotAfter) {
 		return CertificateInvalidError{c, Expired}
 	}
 
@@ -136,10 +138,7 @@ func (c *Certificate) isValid(certType int, opts *VerifyOptions) os.Error {
 // the chain is c and the last element is from opts.Roots.
 //
 // WARNING: this doesn't do any revocation checking.
-func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err os.Error) {
-	if opts.CurrentTime == 0 {
-		opts.CurrentTime = time.Seconds()
-	}
+func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
 	err = c.isValid(leafCertificate, &opts)
 	if err != nil {
 		return
@@ -160,7 +159,7 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate
 	return n
 }
 
-func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err os.Error) {
+func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
 	for _, rootNum := range opts.Roots.findVerifiedParents(c) {
 		root := opts.Roots.certs[rootNum]
 		err = root.isValid(rootCertificate, opts)
@@ -227,8 +226,8 @@ func matchHostnames(pattern, host string) bool {
 }
 
 // VerifyHostname returns nil if c is a valid certificate for the named host.
-// Otherwise it returns an os.Error describing the mismatch.
-func (c *Certificate) VerifyHostname(h string) os.Error {
+// Otherwise it returns an error describing the mismatch.
+func (c *Certificate) VerifyHostname(h string) error {
 	if len(c.DNSNames) > 0 {
 		for _, match := range c.DNSNames {
 			if matchHostnames(match, h) {
diff --git a/src/pkg/crypto/x509/verify_test.go b/src/pkg/crypto/x509/verify_test.go
index ecff7ff..2016858 100644
--- a/src/pkg/crypto/x509/verify_test.go
+++ b/src/pkg/crypto/x509/verify_test.go
@@ -5,10 +5,12 @@
 package x509
 
 import (
+	"crypto/x509/pkix"
 	"encoding/pem"
-	"os"
+	"errors"
 	"strings"
 	"testing"
+	"time"
 )
 
 type verifyTest struct {
@@ -17,8 +19,9 @@ type verifyTest struct {
 	roots         []string
 	currentTime   int64
 	dnsName       string
+	nilRoots      bool
 
-	errorCallback  func(*testing.T, int, os.Error) bool
+	errorCallback  func(*testing.T, int, error) bool
 	expectedChains [][]string
 }
 
@@ -46,6 +49,14 @@ var verifyTests = []verifyTest{
 	{
 		leaf:          googleLeaf,
 		intermediates: []string{thawteIntermediate},
+		nilRoots:      true, // verifies that we don't crash
+		currentTime:   1302726541,
+		dnsName:       "www.google.com",
+		errorCallback: expectAuthorityUnknown,
+	},
+	{
+		leaf:          googleLeaf,
+		intermediates: []string{thawteIntermediate},
 		roots:         []string{verisignRoot},
 		currentTime:   1,
 		dnsName:       "www.example.com",
@@ -94,7 +105,7 @@ var verifyTests = []verifyTest{
 	},
 }
 
-func expectHostnameError(t *testing.T, i int, err os.Error) (ok bool) {
+func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
 	if _, ok := err.(HostnameError); !ok {
 		t.Errorf("#%d: error was not a HostnameError: %s", i, err)
 		return false
@@ -102,7 +113,7 @@ func expectHostnameError(t *testing.T, i int, err os.Error) (ok bool) {
 	return true
 }
 
-func expectExpired(t *testing.T, i int, err os.Error) (ok bool) {
+func expectExpired(t *testing.T, i int, err error) (ok bool) {
 	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired {
 		t.Errorf("#%d: error was not Expired: %s", i, err)
 		return false
@@ -110,7 +121,7 @@ func expectExpired(t *testing.T, i int, err os.Error) (ok bool) {
 	return true
 }
 
-func expectAuthorityUnknown(t *testing.T, i int, err os.Error) (ok bool) {
+func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
 	if _, ok := err.(UnknownAuthorityError); !ok {
 		t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
 		return false
@@ -118,10 +129,10 @@ func expectAuthorityUnknown(t *testing.T, i int, err os.Error) (ok bool) {
 	return true
 }
 
-func certificateFromPEM(pemBytes string) (*Certificate, os.Error) {
+func certificateFromPEM(pemBytes string) (*Certificate, error) {
 	block, _ := pem.Decode([]byte(pemBytes))
 	if block == nil {
-		return nil, os.NewError("failed to decode PEM")
+		return nil, errors.New("failed to decode PEM")
 	}
 	return ParseCertificate(block.Bytes)
 }
@@ -132,7 +143,10 @@ func TestVerify(t *testing.T) {
 			Roots:         NewCertPool(),
 			Intermediates: NewCertPool(),
 			DNSName:       test.dnsName,
-			CurrentTime:   test.currentTime,
+			CurrentTime:   time.Unix(test.currentTime, 0),
+		}
+		if test.nilRoots {
+			opts.Roots = nil
 		}
 
 		for j, root := range test.roots {
@@ -211,6 +225,10 @@ func chainToDebugString(chain []*Certificate) string {
 	return chainStr
 }
 
+func nameToKey(name *pkix.Name) string {
+	return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
+}
+
 const verisignRoot = `-----BEGIN CERTIFICATE-----
 MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
 A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
diff --git a/src/pkg/crypto/x509/x509.go b/src/pkg/crypto/x509/x509.go
index 8fda471..bf39c5d 100644
--- a/src/pkg/crypto/x509/x509.go
+++ b/src/pkg/crypto/x509/x509.go
@@ -6,122 +6,73 @@
 package x509
 
 import (
-	"asn1"
-	"big"
 	"bytes"
 	"crypto"
 	"crypto/dsa"
 	"crypto/rsa"
 	"crypto/sha1"
 	"crypto/x509/pkix"
+	"encoding/asn1"
 	"encoding/pem"
+	"errors"
 	"io"
-	"os"
+	"math/big"
 	"time"
 )
 
-// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
-type pkcs1PrivateKey struct {
-	Version int
-	N       *big.Int
-	E       int
-	D       *big.Int
-	P       *big.Int
-	Q       *big.Int
-	// We ignore these values, if present, because rsa will calculate them.
-	Dp   *big.Int `asn1:"optional"`
-	Dq   *big.Int `asn1:"optional"`
-	Qinv *big.Int `asn1:"optional"`
-
-	AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional"`
+// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo
+// in RFC 3280.
+type pkixPublicKey struct {
+	Algo      pkix.AlgorithmIdentifier
+	BitString asn1.BitString
 }
 
-type pkcs1AdditionalRSAPrime struct {
-	Prime *big.Int
-
-	// We ignore these values because rsa will calculate them.
-	Exp   *big.Int
-	Coeff *big.Int
-}
-
-// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
-func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
-	var priv pkcs1PrivateKey
-	rest, err := asn1.Unmarshal(der, &priv)
-	if len(rest) > 0 {
-		err = asn1.SyntaxError{"trailing data"}
+// ParsePKIXPublicKey parses a DER encoded public key. These values are
+// typically found in PEM blocks with "BEGIN PUBLIC KEY".
+func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) {
+	var pki publicKeyInfo
+	if _, err = asn1.Unmarshal(derBytes, &pki); err != nil {
 		return
 	}
-	if err != nil {
-		return
-	}
-
-	if priv.Version > 1 {
-		return nil, os.NewError("x509: unsupported private key version")
-	}
-
-	if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
-		return nil, os.NewError("private key contains zero or negative value")
-	}
-
-	key = new(rsa.PrivateKey)
-	key.PublicKey = rsa.PublicKey{
-		E: priv.E,
-		N: priv.N,
-	}
-
-	key.D = priv.D
-	key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
-	key.Primes[0] = priv.P
-	key.Primes[1] = priv.Q
-	for i, a := range priv.AdditionalPrimes {
-		if a.Prime.Sign() <= 0 {
-			return nil, os.NewError("private key contains zero or negative prime")
-		}
-		key.Primes[i+2] = a.Prime
-		// We ignore the other two values because rsa will calculate
-		// them as needed.
+	algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm)
+	if algo == UnknownPublicKeyAlgorithm {
+		return nil, errors.New("ParsePKIXPublicKey: unknown public key algorithm")
 	}
-
-	err = key.Validate()
-	if err != nil {
-		return nil, err
-	}
-	key.Precompute()
-
-	return
+	return parsePublicKey(algo, &pki)
 }
 
-// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
-func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
-	key.Precompute()
-
-	version := 0
-	if len(key.Primes) > 2 {
-		version = 1
-	}
+// MarshalPKIXPublicKey serialises a public key to DER-encoded PKIX format.
+func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) {
+	var pubBytes []byte
 
-	priv := pkcs1PrivateKey{
-		Version: version,
-		N:       key.N,
-		E:       key.PublicKey.E,
-		D:       key.D,
-		P:       key.Primes[0],
-		Q:       key.Primes[1],
-		Dp:      key.Precomputed.Dp,
-		Dq:      key.Precomputed.Dq,
-		Qinv:    key.Precomputed.Qinv,
+	switch pub := pub.(type) {
+	case *rsa.PublicKey:
+		pubBytes, _ = asn1.Marshal(rsaPublicKey{
+			N: pub.N,
+			E: pub.E,
+		})
+	default:
+		return nil, errors.New("MarshalPKIXPublicKey: unknown public key type")
 	}
 
-	priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
-	for i, values := range key.Precomputed.CRTValues {
-		priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
-		priv.AdditionalPrimes[i].Exp = values.Exp
-		priv.AdditionalPrimes[i].Coeff = values.Coeff
+	pkix := pkixPublicKey{
+		Algo: pkix.AlgorithmIdentifier{
+			Algorithm: []int{1, 2, 840, 113549, 1, 1, 1},
+			// This is a NULL parameters value which is technically
+			// superfluous, but most other code includes it and, by
+			// doing this, we match their public key hashes.
+			Parameters: asn1.RawValue{
+				Tag: 5,
+			},
+		},
+		BitString: asn1.BitString{
+			Bytes:     pubBytes,
+			BitLength: 8 * len(pubBytes),
+		},
 	}
 
-	b, _ := asn1.Marshal(priv)
-	return b
+	ret, _ := asn1.Marshal(pkix)
+	return ret, nil
 }
 
 // These structures reflect the ASN.1 structure of X.509 certificates.:
@@ -138,9 +89,9 @@ type tbsCertificate struct {
 	Version            int `asn1:"optional,explicit,default:1,tag:0"`
 	SerialNumber       *big.Int
 	SignatureAlgorithm pkix.AlgorithmIdentifier
-	Issuer             pkix.RDNSequence
+	Issuer             asn1.RawValue
 	Validity           validity
-	Subject            pkix.RDNSequence
+	Subject            asn1.RawValue
 	PublicKey          publicKeyInfo
 	UniqueId           asn1.BitString   `asn1:"optional,tag:1"`
 	SubjectUniqueId    asn1.BitString   `asn1:"optional,tag:2"`
@@ -156,7 +107,7 @@ type dsaSignature struct {
 }
 
 type validity struct {
-	NotBefore, NotAfter *time.Time
+	NotBefore, NotAfter time.Time
 }
 
 type publicKeyInfo struct {
@@ -339,6 +290,8 @@ type Certificate struct {
 	Raw                     []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
 	RawTBSCertificate       []byte // Certificate part of raw ASN.1 DER content.
 	RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
+	RawSubject              []byte // DER encoded Subject
+	RawIssuer               []byte // DER encoded Issuer
 
 	Signature          []byte
 	SignatureAlgorithm SignatureAlgorithm
@@ -350,7 +303,7 @@ type Certificate struct {
 	SerialNumber        *big.Int
 	Issuer              pkix.Name
 	Subject             pkix.Name
-	NotBefore, NotAfter *time.Time // Validity bounds.
+	NotBefore, NotAfter time.Time // Validity bounds.
 	KeyUsage            KeyUsage
 
 	ExtKeyUsage        []ExtKeyUsage           // Sequence of extended key usages.
@@ -378,7 +331,7 @@ type Certificate struct {
 // that involves algorithms that are not currently implemented.
 type UnsupportedAlgorithmError struct{}
 
-func (UnsupportedAlgorithmError) String() string {
+func (UnsupportedAlgorithmError) Error() string {
 	return "cannot verify signature: algorithm unimplemented"
 }
 
@@ -387,7 +340,7 @@ func (UnsupportedAlgorithmError) String() string {
 // certificate signing key.
 type ConstraintViolationError struct{}
 
-func (ConstraintViolationError) String() string {
+func (ConstraintViolationError) Error() string {
 	return "invalid signature: parent certificate cannot sign this kind of certificate"
 }
 
@@ -397,7 +350,7 @@ func (c *Certificate) Equal(other *Certificate) bool {
 
 // CheckSignatureFrom verifies that the signature on c is a valid signature
 // from parent.
-func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
+func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
 	// RFC 5280, 4.2.1.9:
 	// "If the basic constraints extension is not present in a version 3
 	// certificate, or the extension is present but the cA boolean is not
@@ -423,7 +376,7 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
 
 // CheckSignature verifies that signature is a valid signature over signed from
 // c's public key.
-func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) (err os.Error) {
+func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) (err error) {
 	var hashType crypto.Hash
 
 	switch algo {
@@ -445,7 +398,7 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
 	}
 
 	h.Write(signed)
-	digest := h.Sum()
+	digest := h.Sum(nil)
 
 	switch pub := c.PublicKey.(type) {
 	case *rsa.PublicKey:
@@ -456,10 +409,10 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
 			return err
 		}
 		if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 {
-			return os.NewError("DSA signature contained zero or negative values")
+			return errors.New("DSA signature contained zero or negative values")
 		}
 		if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) {
-			return os.NewError("DSA verification failure")
+			return errors.New("DSA verification failure")
 		}
 		return
 	}
@@ -467,14 +420,14 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
 }
 
 // CheckCRLSignature checks that the signature in crl is from c.
-func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) (err os.Error) {
+func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) (err error) {
 	algo := getSignatureAlgorithmFromOID(crl.SignatureAlgorithm.Algorithm)
 	return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign())
 }
 
 type UnhandledCriticalExtension struct{}
 
-func (h UnhandledCriticalExtension) String() string {
+func (h UnhandledCriticalExtension) Error() string {
 	return "unhandled critical extension"
 }
 
@@ -483,11 +436,6 @@ type basicConstraints struct {
 	MaxPathLen int  `asn1:"optional"`
 }
 
-type rsaPublicKey struct {
-	N *big.Int
-	E int
-}
-
 // RFC 5280 4.2.1.4
 type policyInformation struct {
 	Policy asn1.ObjectIdentifier
@@ -506,7 +454,7 @@ type generalSubtree struct {
 	Max  int    `asn1:"optional,tag:1"`
 }
 
-func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, os.Error) {
+func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
 	asn1Data := keyData.PublicKey.RightAlign()
 	switch algo {
 	case RSA:
@@ -534,7 +482,7 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
 			return nil, err
 		}
 		if p.Sign() <= 0 || params.P.Sign() <= 0 || params.Q.Sign() <= 0 || params.G.Sign() <= 0 {
-			return nil, os.NewError("zero or negative DSA parameter")
+			return nil, errors.New("zero or negative DSA parameter")
 		}
 		pub := &dsa.PublicKey{
 			Parameters: dsa.Parameters{
@@ -551,11 +499,13 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
 	panic("unreachable")
 }
 
-func parseCertificate(in *certificate) (*Certificate, os.Error) {
+func parseCertificate(in *certificate) (*Certificate, error) {
 	out := new(Certificate)
 	out.Raw = in.Raw
 	out.RawTBSCertificate = in.TBSCertificate.Raw
 	out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw
+	out.RawSubject = in.TBSCertificate.Subject.FullBytes
+	out.RawIssuer = in.TBSCertificate.Issuer.FullBytes
 
 	out.Signature = in.SignatureValue.RightAlign()
 	out.SignatureAlgorithm =
@@ -563,20 +513,30 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
 
 	out.PublicKeyAlgorithm =
 		getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm)
-	var err os.Error
+	var err error
 	out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCertificate.PublicKey)
 	if err != nil {
 		return nil, err
 	}
 
 	if in.TBSCertificate.SerialNumber.Sign() < 0 {
-		return nil, os.NewError("negative serial number")
+		return nil, errors.New("negative serial number")
 	}
 
 	out.Version = in.TBSCertificate.Version + 1
 	out.SerialNumber = in.TBSCertificate.SerialNumber
-	out.Issuer.FillFromRDNSequence(&in.TBSCertificate.Issuer)
-	out.Subject.FillFromRDNSequence(&in.TBSCertificate.Subject)
+
+	var issuer, subject pkix.RDNSequence
+	if _, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil {
+		return nil, err
+	}
+	if _, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil {
+		return nil, err
+	}
+
+	out.Issuer.FillFromRDNSequence(&issuer)
+	out.Subject.FillFromRDNSequence(&subject)
+
 	out.NotBefore = in.TBSCertificate.Validity.NotBefore
 	out.NotAfter = in.TBSCertificate.Validity.NotAfter
 
@@ -777,7 +737,7 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
 }
 
 // ParseCertificate parses a single certificate from the given ASN.1 DER data.
-func ParseCertificate(asn1Data []byte) (*Certificate, os.Error) {
+func ParseCertificate(asn1Data []byte) (*Certificate, error) {
 	var cert certificate
 	rest, err := asn1.Unmarshal(asn1Data, &cert)
 	if err != nil {
@@ -792,12 +752,12 @@ func ParseCertificate(asn1Data []byte) (*Certificate, os.Error) {
 
 // ParseCertificates parses one or more certificates from the given ASN.1 DER
 // data. The certificates must be concatenated with no intermediate padding.
-func ParseCertificates(asn1Data []byte) ([]*Certificate, os.Error) {
+func ParseCertificates(asn1Data []byte) ([]*Certificate, error) {
 	var v []*certificate
 
 	for len(asn1Data) > 0 {
 		cert := new(certificate)
-		var err os.Error
+		var err error
 		asn1Data, err = asn1.Unmarshal(asn1Data, cert)
 		if err != nil {
 			return nil, err
@@ -834,7 +794,7 @@ var (
 	oidExtensionNameConstraints     = []int{2, 5, 29, 30}
 )
 
-func buildExtensions(template *Certificate) (ret []pkix.Extension, err os.Error) {
+func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
 	ret = make([]pkix.Extension, 7 /* maximum number of elements. */ )
 	n := 0
 
@@ -939,21 +899,41 @@ var (
 	oidRSA         = []int{1, 2, 840, 113549, 1, 1, 1}
 )
 
-// CreateSelfSignedCertificate creates a new certificate based on
-// a template. The following members of template are used: SerialNumber,
-// Subject, NotBefore, NotAfter, KeyUsage, BasicConstraintsValid, IsCA,
-// MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
-// PermittedDNSDomains.
+func subjectBytes(cert *Certificate) ([]byte, error) {
+	if len(cert.RawSubject) > 0 {
+		return cert.RawSubject, nil
+	}
+
+	return asn1.Marshal(cert.Subject.ToRDNSequence())
+}
+
+// CreateCertificate creates a new certificate based on a template. The
+// following members of template are used: SerialNumber, Subject, NotBefore,
+// NotAfter, KeyUsage, BasicConstraintsValid, IsCA, MaxPathLen, SubjectKeyId,
+// DNSNames, PermittedDNSDomainsCritical, PermittedDNSDomains.
 //
 // The certificate is signed by parent. If parent is equal to template then the
 // certificate is self-signed. The parameter pub is the public key of the
 // signee and priv is the private key of the signer.
 //
 // The returned slice is the certificate in DER encoding.
-func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.PublicKey, priv *rsa.PrivateKey) (cert []byte, err os.Error) {
+//
+// The only supported key type is RSA (*rsa.PublicKey for pub, *rsa.PrivateKey
+// for priv).
+func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) {
+	rsaPub, ok := pub.(*rsa.PublicKey)
+	if !ok {
+		return nil, errors.New("x509: non-RSA public keys not supported")
+	}
+
+	rsaPriv, ok := priv.(*rsa.PrivateKey)
+	if !ok {
+		return nil, errors.New("x509: non-RSA private keys not supported")
+	}
+
 	asn1PublicKey, err := asn1.Marshal(rsaPublicKey{
-		N: pub.N,
-		E: pub.E,
+		N: rsaPub.N,
+		E: rsaPub.E,
 	})
 	if err != nil {
 		return
@@ -968,14 +948,24 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
 		return
 	}
 
+	asn1Issuer, err := subjectBytes(parent)
+	if err != nil {
+		return
+	}
+
+	asn1Subject, err := subjectBytes(template)
+	if err != nil {
+		return
+	}
+
 	encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
 	c := tbsCertificate{
 		Version:            2,
 		SerialNumber:       template.SerialNumber,
 		SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
-		Issuer:             parent.Subject.ToRDNSequence(),
+		Issuer:             asn1.RawValue{FullBytes: asn1Issuer},
 		Validity:           validity{template.NotBefore, template.NotAfter},
-		Subject:            template.Subject.ToRDNSequence(),
+		Subject:            asn1.RawValue{FullBytes: asn1Subject},
 		PublicKey:          publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey},
 		Extensions:         extensions,
 	}
@@ -989,9 +979,9 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
 
 	h := sha1.New()
 	h.Write(tbsCertContents)
-	digest := h.Sum()
+	digest := h.Sum(nil)
 
-	signature, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, digest)
+	signature, err := rsa.SignPKCS1v15(rand, rsaPriv, crypto.SHA1, digest)
 	if err != nil {
 		return
 	}
@@ -1008,6 +998,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
 // pemCRLPrefix is the magic string that indicates that we have a PEM encoded
 // CRL.
 var pemCRLPrefix = []byte("-----BEGIN X509 CRL")
+
 // pemType is the type of a PEM encoded CRL.
 var pemType = "X509 CRL"
 
@@ -1015,7 +1006,7 @@ var pemType = "X509 CRL"
 // encoded CRLs will appear where they should be DER encoded, so this function
 // will transparently handle PEM encoding as long as there isn't any leading
 // garbage.
-func ParseCRL(crlBytes []byte) (certList *pkix.CertificateList, err os.Error) {
+func ParseCRL(crlBytes []byte) (certList *pkix.CertificateList, err error) {
 	if bytes.HasPrefix(crlBytes, pemCRLPrefix) {
 		block, _ := pem.Decode(crlBytes)
 		if block != nil && block.Type == pemType {
@@ -1026,7 +1017,7 @@ func ParseCRL(crlBytes []byte) (certList *pkix.CertificateList, err os.Error) {
 }
 
 // ParseDERCRL parses a DER encoded CRL from the given bytes.
-func ParseDERCRL(derBytes []byte) (certList *pkix.CertificateList, err os.Error) {
+func ParseDERCRL(derBytes []byte) (certList *pkix.CertificateList, err error) {
 	certList = new(pkix.CertificateList)
 	_, err = asn1.Unmarshal(derBytes, certList)
 	if err != nil {
@@ -1037,7 +1028,13 @@ func ParseDERCRL(derBytes []byte) (certList *pkix.CertificateList, err os.Error)
 
 // CreateCRL returns a DER encoded CRL, signed by this Certificate, that
 // contains the given list of revoked certificates.
-func (c *Certificate) CreateCRL(rand io.Reader, priv *rsa.PrivateKey, revokedCerts []pkix.RevokedCertificate, now, expiry *time.Time) (crlBytes []byte, err os.Error) {
+//
+// The only supported key type is RSA (*rsa.PrivateKey for priv).
+func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) {
+	rsaPriv, ok := priv.(*rsa.PrivateKey)
+	if !ok {
+		return nil, errors.New("x509: non-RSA private keys not supported")
+	}
 	tbsCertList := pkix.TBSCertificateList{
 		Version: 2,
 		Signature: pkix.AlgorithmIdentifier{
@@ -1056,9 +1053,9 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv *rsa.PrivateKey, revokedCer
 
 	h := sha1.New()
 	h.Write(tbsCertListContents)
-	digest := h.Sum()
+	digest := h.Sum(nil)
 
-	signature, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, digest)
+	signature, err := rsa.SignPKCS1v15(rand, rsaPriv, crypto.SHA1, digest)
 	if err != nil {
 		return
 	}
diff --git a/src/pkg/crypto/x509/x509_test.go b/src/pkg/crypto/x509/x509_test.go
index dc21650..f0327b0 100644
--- a/src/pkg/crypto/x509/x509_test.go
+++ b/src/pkg/crypto/x509/x509_test.go
@@ -5,15 +5,16 @@
 package x509
 
 import (
-	"asn1"
-	"big"
+	"bytes"
 	"crypto/dsa"
 	"crypto/rand"
 	"crypto/rsa"
 	"crypto/x509/pkix"
+	"encoding/asn1"
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/pem"
+	"math/big"
 	"testing"
 	"time"
 )
@@ -34,6 +35,40 @@ func TestParsePKCS1PrivateKey(t *testing.T) {
 	}
 }
 
+func TestParsePKIXPublicKey(t *testing.T) {
+	block, _ := pem.Decode([]byte(pemPublicKey))
+	pub, err := ParsePKIXPublicKey(block.Bytes)
+	if err != nil {
+		t.Errorf("Failed to parse RSA public key: %s", err)
+		return
+	}
+	rsaPub, ok := pub.(*rsa.PublicKey)
+	if !ok {
+		t.Errorf("Value returned from ParsePKIXPublicKey was not an RSA public key")
+		return
+	}
+
+	pubBytes2, err := MarshalPKIXPublicKey(rsaPub)
+	if err != nil {
+		t.Errorf("Failed to marshal RSA public key for the second time: %s", err)
+		return
+	}
+	if !bytes.Equal(pubBytes2, block.Bytes) {
+		t.Errorf("Reserialization of public key didn't match. got %x, want %x", pubBytes2, block.Bytes)
+	}
+}
+
+var pemPublicKey = `-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3VoPN9PKUjKFLMwOge6+
+wnDi8sbETGIx2FKXGgqtAKpzmem53kRGEQg8WeqRmp12wgp74TGpkEXsGae7RS1k
+enJCnma4fii+noGH7R0qKgHvPrI2Bwa9hzsH8tHxpyM3qrXslOmD45EH9SxIDUBJ
+FehNdaPbLP1gFyahKMsdfxFJLUvbUycuZSJ2ZnIgeVxwm4qbSvZInL9Iu4FzuPtg
+fINKcbbovy1qq4KvPIrXzhbY3PWDc6btxCf3SE0JdE1MCPThntB62/bLMSQ7xdDR
+FF53oIpvxe/SCOymfWq/LW849Ytv3Xwod0+wzAP8STXG4HSELS4UedPYeHJJJYcZ
++QIDAQAB
+-----END PUBLIC KEY-----
+`
+
 var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
 MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
 fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
@@ -208,14 +243,15 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
 		return
 	}
 
+	commonName := "test.example.com"
 	template := Certificate{
 		SerialNumber: big.NewInt(1),
 		Subject: pkix.Name{
-			CommonName:   "test.example.com",
+			CommonName:   commonName,
 			Organization: []string{"Acme Co"},
 		},
-		NotBefore: time.SecondsToUTC(1000),
-		NotAfter:  time.SecondsToUTC(100000),
+		NotBefore: time.Unix(1000, 0),
+		NotAfter:  time.Unix(100000, 0),
 
 		SubjectKeyId: []byte{1, 2, 3, 4},
 		KeyUsage:     KeyUsageCertSign,
@@ -248,6 +284,14 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
 		t.Errorf("Failed to parse name constraints: %#v", cert.PermittedDNSDomains)
 	}
 
+	if cert.Subject.CommonName != commonName {
+		t.Errorf("Subject wasn't correctly copied from the template. Got %s, want %s", cert.Subject.CommonName, commonName)
+	}
+
+	if cert.Issuer.CommonName != commonName {
+		t.Errorf("Issuer wasn't correctly copied from the template. Got %s, want %s", cert.Issuer.CommonName, commonName)
+	}
+
 	err = cert.CheckSignatureFrom(cert)
 	if err != nil {
 		t.Errorf("Signature verification failed: %s", err)
@@ -352,8 +396,8 @@ func TestCRLCreation(t *testing.T) {
 	block, _ = pem.Decode([]byte(pemCertificate))
 	cert, _ := ParseCertificate(block.Bytes)
 
-	now := time.SecondsToUTC(1000)
-	expiry := time.SecondsToUTC(10000)
+	now := time.Unix(1000, 0)
+	expiry := time.Unix(10000, 0)
 
 	revokedCerts := []pkix.RevokedCertificate{
 		{
@@ -399,7 +443,7 @@ func TestParseDERCRL(t *testing.T) {
 		t.Errorf("bad number of revoked certificates. got: %d want: %d", numCerts, expected)
 	}
 
-	if certList.HasExpired(1302517272) {
+	if certList.HasExpired(time.Unix(1302517272, 0)) {
 		t.Errorf("CRL has expired (but shouldn't have)")
 	}
 
@@ -419,7 +463,7 @@ func TestParsePEMCRL(t *testing.T) {
 		t.Errorf("bad number of revoked certificates. got: %d want: %d", numCerts, expected)
 	}
 
-	if certList.HasExpired(1302517272) {
+	if certList.HasExpired(time.Unix(1302517272, 0)) {
 		t.Errorf("CRL has expired (but shouldn't have)")
 	}
 
diff --git a/src/pkg/crypto/xtea/Makefile b/src/pkg/crypto/xtea/Makefile
deleted file mode 100644
index 3016211..0000000
--- a/src/pkg/crypto/xtea/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=crypto/xtea
-GOFILES=\
-	cipher.go\
-	block.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/crypto/xtea/block.go b/src/pkg/crypto/xtea/block.go
deleted file mode 100644
index bf5d245..0000000
--- a/src/pkg/crypto/xtea/block.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-	Implementation adapted from Needham and Wheeler's paper:
-	http://www.cix.co.uk/~klockstone/xtea.pdf
-
-	A precalculated look up table is used during encryption/decryption for values that are based purely on the key.
-*/
-
-package xtea
-
-// XTEA is based on 64 rounds.
-const numRounds = 64
-
-// blockToUint32 reads an 8 byte slice into two uint32s.
-// The block is treated as big endian.
-func blockToUint32(src []byte) (uint32, uint32) {
-	r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-	r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-	return r0, r1
-}
-
-// uint32ToBlock writes two uint32s into an 8 byte data block.
-// Values are written as big endian.
-func uint32ToBlock(v0, v1 uint32, dst []byte) {
-	dst[0] = byte(v0 >> 24)
-	dst[1] = byte(v0 >> 16)
-	dst[2] = byte(v0 >> 8)
-	dst[3] = byte(v0)
-	dst[4] = byte(v1 >> 24)
-	dst[5] = byte(v1 >> 16)
-	dst[6] = byte(v1 >> 8)
-	dst[7] = byte(v1 >> 0)
-}
-
-// encryptBlock encrypts a single 8 byte block using XTEA.
-func encryptBlock(c *Cipher, dst, src []byte) {
-	v0, v1 := blockToUint32(src)
-
-	// Two rounds of XTEA applied per loop
-	for i := 0; i < numRounds; {
-		v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
-		i++
-		v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
-		i++
-	}
-
-	uint32ToBlock(v0, v1, dst)
-}
-
-// decryptBlock decrypt a single 8 byte block using XTEA.
-func decryptBlock(c *Cipher, dst, src []byte) {
-	v0, v1 := blockToUint32(src)
-
-	// Two rounds of XTEA applied per loop
-	for i := numRounds; i > 0; {
-		i--
-		v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
-		i--
-		v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
-	}
-
-	uint32ToBlock(v0, v1, dst)
-}
diff --git a/src/pkg/crypto/xtea/cipher.go b/src/pkg/crypto/xtea/cipher.go
deleted file mode 100644
index b3fba3c..0000000
--- a/src/pkg/crypto/xtea/cipher.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's
-// 1997 technical report, "Tea extensions."
-package xtea
-
-// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf
-
-import (
-	"os"
-	"strconv"
-)
-
-// The XTEA block size in bytes.
-const BlockSize = 8
-
-// A Cipher is an instance of an XTEA cipher using a particular key.
-// table contains a series of precalculated values that are used each round.
-type Cipher struct {
-	table [64]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) String() string {
-	return "crypto/xtea: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a new Cipher.
-// The key argument should be the XTEA key.
-// XTEA only supports 128 bit (16 byte) keys.
-func NewCipher(key []byte) (*Cipher, os.Error) {
-	k := len(key)
-	switch k {
-	default:
-		return nil, KeySizeError(k)
-	case 16:
-		break
-	}
-
-	c := new(Cipher)
-	initCipher(c, key)
-
-	return c, nil
-}
-
-// BlockSize returns the XTEA block size, 8 bytes.
-// It is necessary to satisfy the Cipher interface in the
-// package "crypto/cipher".
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) }
-
-// Decrypt decrypts the 8 byte buffer src using the key k and stores the result in dst.
-func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) }
-
-// Reset zeros the table, so that it will no longer appear in the process's memory.
-func (c *Cipher) Reset() {
-	for i := 0; i < len(c.table); i++ {
-		c.table[i] = 0
-	}
-}
-
-// initCipher initializes the cipher context by creating a look up table
-// of precalculated values that are based on the key.
-func initCipher(c *Cipher, key []byte) {
-	// Load the key into four uint32s
-	var k [4]uint32
-	for i := 0; i < len(k); i++ {
-		j := i << 2 // Multiply by 4
-		k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3])
-	}
-
-	// Precalculate the table
-	const delta = 0x9E3779B9
-	var sum uint32 = 0
-
-	// Two rounds of XTEA applied per loop
-	for i := 0; i < numRounds; {
-		c.table[i] = sum + k[sum&3]
-		i++
-		sum += delta
-		c.table[i] = sum + k[(sum>>11)&3]
-		i++
-	}
-}
diff --git a/src/pkg/crypto/xtea/xtea_test.go b/src/pkg/crypto/xtea/xtea_test.go
deleted file mode 100644
index 217d96a..0000000
--- a/src/pkg/crypto/xtea/xtea_test.go
+++ /dev/null
@@ -1,246 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package xtea
-
-import (
-	"testing"
-)
-
-// A sample test key for when we just want to initialize a cipher
-var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}
-
-// Test that the block size for XTEA is correct
-func TestBlocksize(t *testing.T) {
-	if BlockSize != 8 {
-		t.Errorf("BlockSize constant - expected 8, got %d", BlockSize)
-		return
-	}
-
-	c, err := NewCipher(testKey)
-	if err != nil {
-		t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
-		return
-	}
-
-	result := c.BlockSize()
-	if result != 8 {
-		t.Errorf("BlockSize function - expected 8, got %d", result)
-		return
-	}
-}
-
-// A series of test values to confirm that the Cipher.table array was initialized correctly
-var testTable = []uint32{
-	0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917,
-	0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F,
-	0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67,
-	0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F,
-	0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7,
-	0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF,
-	0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7,
-	0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB,
-}
-
-// Test that the cipher context is initialized correctly
-func TestCipherInit(t *testing.T) {
-	c, err := NewCipher(testKey)
-	if err != nil {
-		t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
-		return
-	}
-
-	for i := 0; i < len(c.table); i++ {
-		if c.table[i] != testTable[i] {
-			t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i])
-			break
-		}
-	}
-}
-
-// Test that invalid key sizes return an error
-func TestInvalidKeySize(t *testing.T) {
-	// Test a long key
-	key := []byte{
-		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
-		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
-	}
-
-	_, err := NewCipher(key)
-	if err == nil {
-		t.Errorf("Invalid key size %d didn't result in an error.", len(key))
-	}
-
-	// Test a short key
-	key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}
-
-	_, err = NewCipher(key)
-	if err == nil {
-		t.Errorf("Invalid key size %d didn't result in an error.", len(key))
-	}
-}
-
-// Test that we can correctly decode some bytes we have encoded
-func TestEncodeDecode(t *testing.T) {
-	original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}
-	input := original
-	output := make([]byte, BlockSize)
-
-	c, err := NewCipher(testKey)
-	if err != nil {
-		t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
-		return
-	}
-
-	// Encrypt the input block
-	c.Encrypt(output, input)
-
-	// Check that the output does not match the input
-	differs := false
-	for i := 0; i < len(input); i++ {
-		if output[i] != input[i] {
-			differs = true
-			break
-		}
-	}
-	if differs == false {
-		t.Error("Cipher.Encrypt: Failed to encrypt the input block.")
-		return
-	}
-
-	// Decrypt the block we just encrypted
-	input = output
-	output = make([]byte, BlockSize)
-	c.Decrypt(output, input)
-
-	// Check that the output from decrypt matches our initial input
-	for i := 0; i < len(input); i++ {
-		if output[i] != original[i] {
-			t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i])
-			return
-		}
-	}
-}
-
-// Test Vectors
-type CryptTest struct {
-	key        []byte
-	plainText  []byte
-	cipherText []byte
-}
-
-var CryptTests = []CryptTest{
-	// These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors
-	{
-		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
-		[]byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
-		[]byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5},
-	},
-	{
-		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
-		[]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
-		[]byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8},
-	},
-	{
-		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
-		[]byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f},
-		[]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
-	},
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
-		[]byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5},
-	},
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
-		[]byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d},
-	},
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55},
-		[]byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
-	},
-
-	// These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9},
-	},
-	{
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
-		[]byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16},
-	},
-	{
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
-		[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-		[]byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64},
-	},
-	{
-		[]byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
-		[]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
-		[]byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD},
-	},
-}
-
-// Test encryption
-func TestCipherEncrypt(t *testing.T) {
-	for i, tt := range CryptTests {
-		c, err := NewCipher(tt.key)
-		if err != nil {
-			t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
-			continue
-		}
-
-		out := make([]byte, len(tt.plainText))
-		c.Encrypt(out, tt.plainText)
-
-		for j := 0; j < len(out); j++ {
-			if out[j] != tt.cipherText[j] {
-				t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j])
-				break
-			}
-		}
-	}
-}
-
-// Test decryption
-func TestCipherDecrypt(t *testing.T) {
-	for i, tt := range CryptTests {
-		c, err := NewCipher(tt.key)
-		if err != nil {
-			t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
-			continue
-		}
-
-		out := make([]byte, len(tt.cipherText))
-		c.Decrypt(out, tt.cipherText)
-
-		for j := 0; j < len(out); j++ {
-			if out[j] != tt.plainText[j] {
-				t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j])
-				break
-			}
-		}
-	}
-}
-
-// Test resetting the cipher context
-func TestReset(t *testing.T) {
-	c, err := NewCipher(testKey)
-	if err != nil {
-		t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
-		return
-	}
-
-	c.Reset()
-	for i := 0; i < len(c.table); i++ {
-		if c.table[i] != 0 {
-			t.Errorf("Cipher.Reset: Failed to clear Cipher.table[%d]. expected 0, got %08X", i, c.table[i])
-			return
-		}
-	}
-}
diff --git a/src/pkg/csv/Makefile b/src/pkg/csv/Makefile
deleted file mode 100644
index e364d51..0000000
--- a/src/pkg/csv/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=csv
-GOFILES=\
-	reader.go\
-	writer.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/csv/reader.go b/src/pkg/csv/reader.go
deleted file mode 100644
index ea2c266..0000000
--- a/src/pkg/csv/reader.go
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright 2011 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 csv reads and writes comma-separated values (CSV) files.
-//
-// A csv file contains zero or more records of one or more fields per record.
-// Each record is separated by the newline character. The final record may
-// optionally be followed by a newline character.
-//
-//	field1,field2,field3
-//
-// White space is considered part of a field.
-//
-// Carriage returns before newline characters are silently removed.
-//
-// Blank lines are ignored.  A line with only whitespace characters (excluding
-// the ending newline character) is not considered a blank line.
-//
-// Fields which start and stop with the quote character " are called
-// quoted-fields.  The beginning and ending quote are not part of the
-// field.
-//
-// The source:
-//
-//	normal string,"quoted-field"
-//
-// results in the fields
-//
-//	{`normal string`, `quoted-field`}
-//
-// Within a quoted-field a quote character followed by a second quote
-// character is considered a single quote.
-//
-//	"the ""word"" is true","a ""quoted-field"""
-//
-// results in
-//
-//	{`the "word" is true`, `a "quoted-field"`}
-//
-// Newlines and commas may be included in a quoted-field
-//
-//	"Multi-line
-//	field","comma is ,"
-//
-// results in
-//
-//	{`Multi-line
-//	field`, `comma is ,`}
-package csv
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"unicode"
-)
-
-// A ParseError is returned for parsing errors.
-// The first line is 1.  The first column is 0.
-type ParseError struct {
-	Line   int      // Line where the error occurred
-	Column int      // Column (rune index) where the error occurred
-	Error  os.Error // The actual error
-}
-
-func (e *ParseError) String() string {
-	return fmt.Sprintf("line %d, column %d: %s", e.Line, e.Column, e.Error)
-}
-
-// These are the errors that can be returned in ParseError.Error
-var (
-	ErrTrailingComma = os.NewError("extra delimiter at end of line")
-	ErrBareQuote     = os.NewError("bare \" in non-quoted-field")
-	ErrQuote         = os.NewError("extraneous \" in field")
-	ErrFieldCount    = os.NewError("wrong number of fields in line")
-)
-
-// A Reader reads records from a CSV-encoded file.
-//
-// As returned by NewReader, a Reader expects input conforming to RFC 4180.
-// The exported fields can be changed to customize the details before the
-// first call to Read or ReadAll.
-//
-// Comma is the field delimiter.  It defaults to ','.
-//
-// Comment, if not 0, is the comment character. Lines beginning with the
-// Comment character are ignored.
-//
-// If FieldsPerRecord is positive, Read requires each record to
-// have the given number of fields.  If FieldsPerRecord is 0, Read sets it to
-// the number of fields in the first record, so that future records must
-// have the same field count.
-//
-// If LazyQuotes is true, a quote may appear in an unquoted field and a
-// non-doubled quote may appear in a quoted field.
-//
-// If TrailingComma is true, the last field may be an unquoted empty field.
-//
-// If TrimLeadingSpace is true, leading white space in a field is ignored.
-type Reader struct {
-	Comma            int  // Field delimiter (set to ',' by NewReader)
-	Comment          int  // Comment character for start of line
-	FieldsPerRecord  int  // Number of expected fields per record
-	LazyQuotes       bool // Allow lazy quotes
-	TrailingComma    bool // Allow trailing comma
-	TrimLeadingSpace bool // Trim leading space
-	line             int
-	column           int
-	r                *bufio.Reader
-	field            bytes.Buffer
-}
-
-// NewReader returns a new Reader that reads from r.
-func NewReader(r io.Reader) *Reader {
-	return &Reader{
-		Comma: ',',
-		r:     bufio.NewReader(r),
-	}
-}
-
-// error creates a new ParseError based on err.
-func (r *Reader) error(err os.Error) os.Error {
-	return &ParseError{
-		Line:   r.line,
-		Column: r.column,
-		Error:  err,
-	}
-}
-
-// Read reads one record from r.  The record is a slice of strings with each
-// string representing one field.
-func (r *Reader) Read() (record []string, err os.Error) {
-	for {
-		record, err = r.parseRecord()
-		if record != nil {
-			break
-		}
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	if r.FieldsPerRecord > 0 {
-		if len(record) != r.FieldsPerRecord {
-			r.column = 0 // report at start of record
-			return record, r.error(ErrFieldCount)
-		}
-	} else if r.FieldsPerRecord == 0 {
-		r.FieldsPerRecord = len(record)
-	}
-	return record, nil
-}
-
-// ReadAll reads all the remaining records from r.
-// Each record is a slice of fields.
-func (r *Reader) ReadAll() (records [][]string, err os.Error) {
-	for {
-		record, err := r.Read()
-		if err == os.EOF {
-			return records, nil
-		}
-		if err != nil {
-			return nil, err
-		}
-		records = append(records, record)
-	}
-	panic("unreachable")
-}
-
-// readRune reads one rune from r, folding \r\n to \n and keeping track
-// of how far into the line we have read.  r.column will point to the start
-// of this rune, not the end of this rune.
-func (r *Reader) readRune() (int, os.Error) {
-	rune, _, err := r.r.ReadRune()
-
-	// Handle \r\n here.  We make the simplifying assumption that
-	// anytime \r is followed by \n that it can be folded to \n.
-	// We will not detect files which contain both \r\n and bare \n.
-	if rune == '\r' {
-		rune, _, err = r.r.ReadRune()
-		if err == nil {
-			if rune != '\n' {
-				r.r.UnreadRune()
-				rune = '\r'
-			}
-		}
-	}
-	r.column++
-	return rune, err
-}
-
-// unreadRune puts the last rune read from r back.
-func (r *Reader) unreadRune() {
-	r.r.UnreadRune()
-	r.column--
-}
-
-// skip reads runes up to and including the rune delim or until error.
-func (r *Reader) skip(delim int) os.Error {
-	for {
-		rune, err := r.readRune()
-		if err != nil {
-			return err
-		}
-		if rune == delim {
-			return nil
-		}
-	}
-	panic("unreachable")
-}
-
-// parseRecord reads and parses a single csv record from r.
-func (r *Reader) parseRecord() (fields []string, err os.Error) {
-	// Each record starts on a new line.  We increment our line
-	// number (lines start at 1, not 0) and set column to -1
-	// so as we increment in readRune it points to the character we read.
-	r.line++
-	r.column = -1
-
-	// Peek at the first rune.  If it is an error we are done.
-	// If we are support comments and it is the comment character
-	// then skip to the end of line.
-
-	rune, _, err := r.r.ReadRune()
-	if err != nil {
-		return nil, err
-	}
-
-	if r.Comment != 0 && rune == r.Comment {
-		return nil, r.skip('\n')
-	}
-	r.r.UnreadRune()
-
-	// At this point we have at least one field.
-	for {
-		haveField, delim, err := r.parseField()
-		if haveField {
-			fields = append(fields, r.field.String())
-		}
-		if delim == '\n' || err == os.EOF {
-			return fields, err
-		} else if err != nil {
-			return nil, err
-		}
-	}
-	panic("unreachable")
-}
-
-// parseField parses the next field in the record.  The read field is
-// located in r.field.  Delim is the first character not part of the field
-// (r.Comma or '\n').
-func (r *Reader) parseField() (haveField bool, delim int, err os.Error) {
-	r.field.Reset()
-
-	rune, err := r.readRune()
-	if err != nil {
-		// If we have EOF and are not at the start of a line
-		// then we return the empty field.  We have already
-		// checked for trailing commas if needed.
-		if err == os.EOF && r.column != 0 {
-			return true, 0, err
-		}
-		return false, 0, err
-	}
-
-	if r.TrimLeadingSpace {
-		for unicode.IsSpace(rune) {
-			rune, err = r.readRune()
-			if err != nil {
-				return false, 0, err
-			}
-		}
-	}
-
-	switch rune {
-	case r.Comma:
-		// will check below
-
-	case '\n':
-		// We are a trailing empty field or a blank line
-		if r.column == 0 {
-			return false, rune, nil
-		}
-		return true, rune, nil
-
-	case '"':
-		// quoted field
-	Quoted:
-		for {
-			rune, err = r.readRune()
-			if err != nil {
-				if err == os.EOF {
-					if r.LazyQuotes {
-						return true, 0, err
-					}
-					return false, 0, r.error(ErrQuote)
-				}
-				return false, 0, err
-			}
-			switch rune {
-			case '"':
-				rune, err = r.readRune()
-				if err != nil || rune == r.Comma {
-					break Quoted
-				}
-				if rune == '\n' {
-					return true, rune, nil
-				}
-				if rune != '"' {
-					if !r.LazyQuotes {
-						r.column--
-						return false, 0, r.error(ErrQuote)
-					}
-					// accept the bare quote
-					r.field.WriteRune('"')
-				}
-			case '\n':
-				r.line++
-				r.column = -1
-			}
-			r.field.WriteRune(rune)
-		}
-
-	default:
-		// unquoted field
-		for {
-			r.field.WriteRune(rune)
-			rune, err = r.readRune()
-			if err != nil || rune == r.Comma {
-				break
-			}
-			if rune == '\n' {
-				return true, rune, nil
-			}
-			if !r.LazyQuotes && rune == '"' {
-				return false, 0, r.error(ErrBareQuote)
-			}
-		}
-	}
-
-	if err != nil {
-		if err == os.EOF {
-			return true, 0, err
-		}
-		return false, 0, err
-	}
-
-	if !r.TrailingComma {
-		// We don't allow trailing commas.  See if we
-		// are at the end of the line (being mindful
-		// of trimming spaces).
-		c := r.column
-		rune, err = r.readRune()
-		if r.TrimLeadingSpace {
-			for unicode.IsSpace(rune) {
-				rune, err = r.readRune()
-				if err != nil {
-					break
-				}
-			}
-		}
-		if err == os.EOF || rune == '\n' {
-			r.column = c // report the comma
-			return false, 0, r.error(ErrTrailingComma)
-		}
-		r.unreadRune()
-	}
-	return true, rune, nil
-}
diff --git a/src/pkg/csv/reader_test.go b/src/pkg/csv/reader_test.go
deleted file mode 100644
index 0068bad..0000000
--- a/src/pkg/csv/reader_test.go
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2011 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 csv
-
-import (
-	"reflect"
-	"strings"
-	"testing"
-)
-
-var readTests = []struct {
-	Name               string
-	Input              string
-	Output             [][]string
-	UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1
-
-	// These fields are copied into the Reader
-	Comma            int
-	Comment          int
-	FieldsPerRecord  int
-	LazyQuotes       bool
-	TrailingComma    bool
-	TrimLeadingSpace bool
-
-	Error  string
-	Line   int // Expected error line if != 0
-	Column int // Expected error column if line != 0
-}{
-	{
-		Name:   "Simple",
-		Input:  "a,b,c\n",
-		Output: [][]string{{"a", "b", "c"}},
-	},
-	{
-		Name:   "CRLF",
-		Input:  "a,b\r\nc,d\r\n",
-		Output: [][]string{{"a", "b"}, {"c", "d"}},
-	},
-	{
-		Name:   "BareCR",
-		Input:  "a,b\rc,d\r\n",
-		Output: [][]string{{"a", "b\rc", "d"}},
-	},
-	{
-		Name:               "RFC4180test",
-		UseFieldsPerRecord: true,
-		Input: `#field1,field2,field3
-"aaa","bb
-b","ccc"
-"a,a","b""bb","ccc"
-zzz,yyy,xxx
-`,
-		Output: [][]string{
-			{"#field1", "field2", "field3"},
-			{"aaa", "bb\nb", "ccc"},
-			{"a,a", `b"bb`, "ccc"},
-			{"zzz", "yyy", "xxx"},
-		},
-	},
-	{
-		Name:   "NoEOLTest",
-		Input:  "a,b,c",
-		Output: [][]string{{"a", "b", "c"}},
-	},
-	{
-		Name:   "Semicolon",
-		Comma:  ';',
-		Input:  "a;b;c\n",
-		Output: [][]string{{"a", "b", "c"}},
-	},
-	{
-		Name: "MultiLine",
-		Input: `"two
-line","one line","three
-line
-field"`,
-		Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}},
-	},
-	{
-		Name:  "BlankLine",
-		Input: "a,b,c\n\nd,e,f\n\n",
-		Output: [][]string{
-			{"a", "b", "c"},
-			{"d", "e", "f"},
-		},
-	},
-	{
-		Name:             "TrimSpace",
-		Input:            " a,  b,   c\n",
-		TrimLeadingSpace: true,
-		Output:           [][]string{{"a", "b", "c"}},
-	},
-	{
-		Name:   "LeadingSpace",
-		Input:  " a,  b,   c\n",
-		Output: [][]string{{" a", "  b", "   c"}},
-	},
-	{
-		Name:    "Comment",
-		Comment: '#',
-		Input:   "#1,2,3\na,b,c\n#comment",
-		Output:  [][]string{{"a", "b", "c"}},
-	},
-	{
-		Name:   "NoComment",
-		Input:  "#1,2,3\na,b,c",
-		Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}},
-	},
-	{
-		Name:       "LazyQuotes",
-		LazyQuotes: true,
-		Input:      `a "word","1"2",a","b`,
-		Output:     [][]string{{`a "word"`, `1"2`, `a"`, `b`}},
-	},
-	{
-		Name:       "BareQuotes",
-		LazyQuotes: true,
-		Input:      `a "word","1"2",a"`,
-		Output:     [][]string{{`a "word"`, `1"2`, `a"`}},
-	},
-	{
-		Name:       "BareDoubleQuotes",
-		LazyQuotes: true,
-		Input:      `a""b,c`,
-		Output:     [][]string{{`a""b`, `c`}},
-	},
-	{
-		Name:   "BadDoubleQuotes",
-		Input:  `a""b,c`,
-		Output: [][]string{{`a""b`, `c`}},
-		Error:  `bare " in non-quoted-field`, Line: 1, Column: 1,
-	},
-	{
-		Name:             "TrimQuote",
-		Input:            ` "a"," b",c`,
-		TrimLeadingSpace: true,
-		Output:           [][]string{{"a", " b", "c"}},
-	},
-	{
-		Name:  "BadBareQuote",
-		Input: `a "word","b"`,
-		Error: `bare " in non-quoted-field`, Line: 1, Column: 2,
-	},
-	{
-		Name:  "BadTrailingQuote",
-		Input: `"a word",b"`,
-		Error: `bare " in non-quoted-field`, Line: 1, Column: 10,
-	},
-	{
-		Name:  "ExtraneousQuote",
-		Input: `"a "word","b"`,
-		Error: `extraneous " in field`, Line: 1, Column: 3,
-	},
-	{
-		Name:               "BadFieldCount",
-		UseFieldsPerRecord: true,
-		Input:              "a,b,c\nd,e",
-		Error:              "wrong number of fields", Line: 2,
-	},
-	{
-		Name:               "BadFieldCount1",
-		UseFieldsPerRecord: true,
-		FieldsPerRecord:    2,
-		Input:              `a,b,c`,
-		Error:              "wrong number of fields", Line: 1,
-	},
-	{
-		Name:   "FieldCount",
-		Input:  "a,b,c\nd,e",
-		Output: [][]string{{"a", "b", "c"}, {"d", "e"}},
-	},
-	{
-		Name:  "BadTrailingCommaEOF",
-		Input: "a,b,c,",
-		Error: "extra delimiter at end of line", Line: 1, Column: 5,
-	},
-	{
-		Name:  "BadTrailingCommaEOL",
-		Input: "a,b,c,\n",
-		Error: "extra delimiter at end of line", Line: 1, Column: 5,
-	},
-	{
-		Name:             "BadTrailingCommaSpaceEOF",
-		TrimLeadingSpace: true,
-		Input:            "a,b,c, ",
-		Error:            "extra delimiter at end of line", Line: 1, Column: 5,
-	},
-	{
-		Name:             "BadTrailingCommaSpaceEOL",
-		TrimLeadingSpace: true,
-		Input:            "a,b,c, \n",
-		Error:            "extra delimiter at end of line", Line: 1, Column: 5,
-	},
-	{
-		Name:             "BadTrailingCommaLine3",
-		TrimLeadingSpace: true,
-		Input:            "a,b,c\nd,e,f\ng,hi,",
-		Error:            "extra delimiter at end of line", Line: 3, Column: 4,
-	},
-	{
-		Name:   "NotTrailingComma3",
-		Input:  "a,b,c, \n",
-		Output: [][]string{{"a", "b", "c", " "}},
-	},
-	{
-		Name:          "CommaFieldTest",
-		TrailingComma: true,
-		Input: `x,y,z,w
-x,y,z,
-x,y,,
-x,,,
-,,,
-"x","y","z","w"
-"x","y","z",""
-"x","y","",""
-"x","","",""
-"","","",""
-`,
-		Output: [][]string{
-			{"x", "y", "z", "w"},
-			{"x", "y", "z", ""},
-			{"x", "y", "", ""},
-			{"x", "", "", ""},
-			{"", "", "", ""},
-			{"x", "y", "z", "w"},
-			{"x", "y", "z", ""},
-			{"x", "y", "", ""},
-			{"x", "", "", ""},
-			{"", "", "", ""},
-		},
-	},
-}
-
-func TestRead(t *testing.T) {
-	for _, tt := range readTests {
-		r := NewReader(strings.NewReader(tt.Input))
-		r.Comment = tt.Comment
-		if tt.UseFieldsPerRecord {
-			r.FieldsPerRecord = tt.FieldsPerRecord
-		} else {
-			r.FieldsPerRecord = -1
-		}
-		r.LazyQuotes = tt.LazyQuotes
-		r.TrailingComma = tt.TrailingComma
-		r.TrimLeadingSpace = tt.TrimLeadingSpace
-		if tt.Comma != 0 {
-			r.Comma = tt.Comma
-		}
-		out, err := r.ReadAll()
-		perr, _ := err.(*ParseError)
-		if tt.Error != "" {
-			if err == nil || !strings.Contains(err.String(), tt.Error) {
-				t.Errorf("%s: error %v, want error %q", tt.Name, err, tt.Error)
-			} else if tt.Line != 0 && (tt.Line != perr.Line || tt.Column != perr.Column) {
-				t.Errorf("%s: error at %d:%d expected %d:%d", tt.Name, perr.Line, perr.Column, tt.Line, tt.Column)
-			}
-		} else if err != nil {
-			t.Errorf("%s: unexpected error %v", tt.Name, err)
-		} else if !reflect.DeepEqual(out, tt.Output) {
-			t.Errorf("%s: out=%q want %q", tt.Name, out, tt.Output)
-		}
-	}
-}
diff --git a/src/pkg/csv/writer.go b/src/pkg/csv/writer.go
deleted file mode 100644
index ccf703f..0000000
--- a/src/pkg/csv/writer.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2011 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 csv
-
-import (
-	"bufio"
-	"io"
-	"os"
-	"strings"
-	"unicode"
-	"utf8"
-)
-
-// A Writer writes records to a CSV encoded file.
-//
-// As returned by NewWriter, a Writer writes records terminated by a
-// newline and uses ',' as the field delimiter.  The exported fields can be
-// changed to customize the details before the first call to Write or WriteAll.
-//
-// Comma is the field delimiter.
-//
-// If UseCRLF is true, the Writer ends each record with \r\n instead of \n.
-type Writer struct {
-	Comma   int  // Field delimiter (set to to ',' by NewWriter)
-	UseCRLF bool // True to use \r\n as the line terminator
-	w       *bufio.Writer
-}
-
-// NewWriter returns a new Writer that writes to w.
-func NewWriter(w io.Writer) *Writer {
-	return &Writer{
-		Comma: ',',
-		w:     bufio.NewWriter(w),
-	}
-}
-
-// Writer writes a single CSV record to w along with any necessary quoting.
-// A record is a slice of strings with each string being one field.
-func (w *Writer) Write(record []string) (err os.Error) {
-	for n, field := range record {
-		if n > 0 {
-			if _, err = w.w.WriteRune(w.Comma); err != nil {
-				return
-			}
-		}
-
-		// If we don't have to have a quoted field then just
-		// write out the field and continue to the next field.
-		if !w.fieldNeedsQuotes(field) {
-			if _, err = w.w.WriteString(field); err != nil {
-				return
-			}
-			continue
-		}
-		if err = w.w.WriteByte('"'); err != nil {
-			return
-		}
-
-		for _, rune := range field {
-			switch rune {
-			case '"':
-				_, err = w.w.WriteString(`""`)
-			case '\r':
-				if !w.UseCRLF {
-					err = w.w.WriteByte('\r')
-				}
-			case '\n':
-				if w.UseCRLF {
-					_, err = w.w.WriteString("\r\n")
-				} else {
-					err = w.w.WriteByte('\n')
-				}
-			default:
-				_, err = w.w.WriteRune(rune)
-			}
-			if err != nil {
-				return
-			}
-		}
-
-		if err = w.w.WriteByte('"'); err != nil {
-			return
-		}
-	}
-	if w.UseCRLF {
-		_, err = w.w.WriteString("\r\n")
-	} else {
-		err = w.w.WriteByte('\n')
-	}
-	return
-}
-
-// Flush writes any buffered data to the underlying io.Writer.
-func (w *Writer) Flush() {
-	w.w.Flush()
-}
-
-// WriteAll writes multiple CSV records to w using Write and then calls Flush.
-func (w *Writer) WriteAll(records [][]string) (err os.Error) {
-	for _, record := range records {
-		err = w.Write(record)
-		if err != nil {
-			break
-		}
-	}
-	w.Flush()
-	return nil
-}
-
-// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
-// Empty fields, files with a Comma, fields with a quote or newline, and
-// fields which start with a space must be enclosed in quotes.
-func (w *Writer) fieldNeedsQuotes(field string) bool {
-	if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
-		return true
-	}
-
-	rune, _ := utf8.DecodeRuneInString(field)
-	return unicode.IsSpace(rune)
-}
diff --git a/src/pkg/database/sql/Makefile b/src/pkg/database/sql/Makefile
new file mode 100644
index 0000000..b8dd59a
--- /dev/null
+++ b/src/pkg/database/sql/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=database/sql
+GOFILES=\
+	convert.go\
+	sql.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/database/sql/convert.go b/src/pkg/database/sql/convert.go
new file mode 100644
index 0000000..e80420e
--- /dev/null
+++ b/src/pkg/database/sql/convert.go
@@ -0,0 +1,142 @@
+// Copyright 2011 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.
+
+// Type conversions for Scan.
+
+package sql
+
+import (
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"reflect"
+	"strconv"
+)
+
+// subsetTypeArgs takes a slice of arguments from callers of the sql
+// package and converts them into a slice of the driver package's
+// "subset types".
+func subsetTypeArgs(args []interface{}) ([]interface{}, error) {
+	out := make([]interface{}, len(args))
+	for n, arg := range args {
+		var err error
+		out[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+		if err != nil {
+			return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n+1, err)
+		}
+	}
+	return out, nil
+}
+
+// convertAssign copies to dest the value in src, converting it if possible.
+// An error is returned if the copy would result in loss of information.
+// dest should be a pointer type.
+func convertAssign(dest, src interface{}) error {
+	// Common cases, without reflect.  Fall through.
+	switch s := src.(type) {
+	case string:
+		switch d := dest.(type) {
+		case *string:
+			*d = s
+			return nil
+		case *[]byte:
+			*d = []byte(s)
+			return nil
+		}
+	case []byte:
+		switch d := dest.(type) {
+		case *string:
+			*d = string(s)
+			return nil
+		case *[]byte:
+			*d = s
+			return nil
+		}
+	case nil:
+		switch d := dest.(type) {
+		case *[]byte:
+			*d = nil
+			return nil
+		}
+	}
+
+	var sv reflect.Value
+
+	switch d := dest.(type) {
+	case *string:
+		sv = reflect.ValueOf(src)
+		switch sv.Kind() {
+		case reflect.Bool,
+			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+			reflect.Float32, reflect.Float64:
+			*d = fmt.Sprintf("%v", src)
+			return nil
+		}
+	case *bool:
+		bv, err := driver.Bool.ConvertValue(src)
+		if err == nil {
+			*d = bv.(bool)
+		}
+		return err
+	}
+
+	if scanner, ok := dest.(ScannerInto); ok {
+		return scanner.ScanInto(src)
+	}
+
+	dpv := reflect.ValueOf(dest)
+	if dpv.Kind() != reflect.Ptr {
+		return errors.New("destination not a pointer")
+	}
+
+	if !sv.IsValid() {
+		sv = reflect.ValueOf(src)
+	}
+
+	dv := reflect.Indirect(dpv)
+	if dv.Kind() == sv.Kind() {
+		dv.Set(sv)
+		return nil
+	}
+
+	switch dv.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		s := asString(src)
+		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
+		if err != nil {
+			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+		}
+		dv.SetInt(i64)
+		return nil
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		s := asString(src)
+		u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
+		if err != nil {
+			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+		}
+		dv.SetUint(u64)
+		return nil
+	case reflect.Float32, reflect.Float64:
+		s := asString(src)
+		f64, err := strconv.ParseFloat(s, dv.Type().Bits())
+		if err != nil {
+			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+		}
+		dv.SetFloat(f64)
+		return nil
+	}
+
+	return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
+}
+
+func asString(src interface{}) string {
+	switch v := src.(type) {
+	case string:
+		return v
+	case []byte:
+		return string(v)
+	}
+	return fmt.Sprintf("%v", src)
+}
diff --git a/src/pkg/database/sql/convert_test.go b/src/pkg/database/sql/convert_test.go
new file mode 100644
index 0000000..b188864
--- /dev/null
+++ b/src/pkg/database/sql/convert_test.go
@@ -0,0 +1,206 @@
+// Copyright 2011 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 sql
+
+import (
+	"database/sql/driver"
+	"fmt"
+	"reflect"
+	"testing"
+	"time"
+)
+
+var someTime = time.Unix(123, 0)
+
+type conversionTest struct {
+	s, d interface{} // source and destination
+
+	// following are used if they're non-zero
+	wantint  int64
+	wantuint uint64
+	wantstr  string
+	wantf32  float32
+	wantf64  float64
+	wanttime time.Time
+	wantbool bool // used if d is of type *bool
+	wanterr  string
+}
+
+// Target variables for scanning into.
+var (
+	scanstr    string
+	scanint    int
+	scanint8   int8
+	scanint16  int16
+	scanint32  int32
+	scanuint8  uint8
+	scanuint16 uint16
+	scanbool   bool
+	scanf32    float32
+	scanf64    float64
+	scantime   time.Time
+)
+
+var conversionTests = []conversionTest{
+	// Exact conversions (destination pointer type matches source type)
+	{s: "foo", d: &scanstr, wantstr: "foo"},
+	{s: 123, d: &scanint, wantint: 123},
+	{s: someTime, d: &scantime, wanttime: someTime},
+
+	// To strings
+	{s: []byte("byteslice"), d: &scanstr, wantstr: "byteslice"},
+	{s: 123, d: &scanstr, wantstr: "123"},
+	{s: int8(123), d: &scanstr, wantstr: "123"},
+	{s: int64(123), d: &scanstr, wantstr: "123"},
+	{s: uint8(123), d: &scanstr, wantstr: "123"},
+	{s: uint16(123), d: &scanstr, wantstr: "123"},
+	{s: uint32(123), d: &scanstr, wantstr: "123"},
+	{s: uint64(123), d: &scanstr, wantstr: "123"},
+	{s: 1.5, d: &scanstr, wantstr: "1.5"},
+
+	// Strings to integers
+	{s: "255", d: &scanuint8, wantuint: 255},
+	{s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
+	{s: "256", d: &scanuint16, wantuint: 256},
+	{s: "-1", d: &scanint, wantint: -1},
+	{s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`},
+
+	// True bools
+	{s: true, d: &scanbool, wantbool: true},
+	{s: "True", d: &scanbool, wantbool: true},
+	{s: "TRUE", d: &scanbool, wantbool: true},
+	{s: "1", d: &scanbool, wantbool: true},
+	{s: 1, d: &scanbool, wantbool: true},
+	{s: int64(1), d: &scanbool, wantbool: true},
+	{s: uint16(1), d: &scanbool, wantbool: true},
+
+	// False bools
+	{s: false, d: &scanbool, wantbool: false},
+	{s: "false", d: &scanbool, wantbool: false},
+	{s: "FALSE", d: &scanbool, wantbool: false},
+	{s: "0", d: &scanbool, wantbool: false},
+	{s: 0, d: &scanbool, wantbool: false},
+	{s: int64(0), d: &scanbool, wantbool: false},
+	{s: uint16(0), d: &scanbool, wantbool: false},
+
+	// Not bools
+	{s: "yup", d: &scanbool, wanterr: `sql/driver: couldn't convert "yup" into type bool`},
+	{s: 2, d: &scanbool, wanterr: `sql/driver: couldn't convert 2 into type bool`},
+
+	// Floats
+	{s: float64(1.5), d: &scanf64, wantf64: float64(1.5)},
+	{s: int64(1), d: &scanf64, wantf64: float64(1)},
+	{s: float64(1.5), d: &scanf32, wantf32: float32(1.5)},
+	{s: "1.5", d: &scanf32, wantf32: float32(1.5)},
+	{s: "1.5", d: &scanf64, wantf64: float64(1.5)},
+}
+
+func intValue(intptr interface{}) int64 {
+	return reflect.Indirect(reflect.ValueOf(intptr)).Int()
+}
+
+func uintValue(intptr interface{}) uint64 {
+	return reflect.Indirect(reflect.ValueOf(intptr)).Uint()
+}
+
+func float64Value(ptr interface{}) float64 {
+	return *(ptr.(*float64))
+}
+
+func float32Value(ptr interface{}) float32 {
+	return *(ptr.(*float32))
+}
+
+func timeValue(ptr interface{}) time.Time {
+	return *(ptr.(*time.Time))
+}
+
+func TestConversions(t *testing.T) {
+	for n, ct := range conversionTests {
+		err := convertAssign(ct.d, ct.s)
+		errstr := ""
+		if err != nil {
+			errstr = err.Error()
+		}
+		errf := func(format string, args ...interface{}) {
+			base := fmt.Sprintf("convertAssign #%d: for %v (%T) -> %T, ", n, ct.s, ct.s, ct.d)
+			t.Errorf(base+format, args...)
+		}
+		if errstr != ct.wanterr {
+			errf("got error %q, want error %q", errstr, ct.wanterr)
+		}
+		if ct.wantstr != "" && ct.wantstr != scanstr {
+			errf("want string %q, got %q", ct.wantstr, scanstr)
+		}
+		if ct.wantint != 0 && ct.wantint != intValue(ct.d) {
+			errf("want int %d, got %d", ct.wantint, intValue(ct.d))
+		}
+		if ct.wantuint != 0 && ct.wantuint != uintValue(ct.d) {
+			errf("want uint %d, got %d", ct.wantuint, uintValue(ct.d))
+		}
+		if ct.wantf32 != 0 && ct.wantf32 != float32Value(ct.d) {
+			errf("want float32 %v, got %v", ct.wantf32, float32Value(ct.d))
+		}
+		if ct.wantf64 != 0 && ct.wantf64 != float64Value(ct.d) {
+			errf("want float32 %v, got %v", ct.wantf64, float64Value(ct.d))
+		}
+		if bp, boolTest := ct.d.(*bool); boolTest && *bp != ct.wantbool && ct.wanterr == "" {
+			errf("want bool %v, got %v", ct.wantbool, *bp)
+		}
+		if !ct.wanttime.IsZero() && !ct.wanttime.Equal(timeValue(ct.d)) {
+			errf("want time %v, got %v", ct.wanttime, timeValue(ct.d))
+		}
+	}
+}
+
+func TestNullString(t *testing.T) {
+	var ns NullString
+	convertAssign(&ns, []byte("foo"))
+	if !ns.Valid {
+		t.Errorf("expecting not null")
+	}
+	if ns.String != "foo" {
+		t.Errorf("expecting foo; got %q", ns.String)
+	}
+	convertAssign(&ns, nil)
+	if ns.Valid {
+		t.Errorf("expecting null on nil")
+	}
+	if ns.String != "" {
+		t.Errorf("expecting blank on nil; got %q", ns.String)
+	}
+}
+
+type valueConverterTest struct {
+	c       driver.ValueConverter
+	in, out interface{}
+	err     string
+}
+
+var valueConverterTests = []valueConverterTest{
+	{driver.DefaultParameterConverter, NullString{"hi", true}, "hi", ""},
+	{driver.DefaultParameterConverter, NullString{"", false}, nil, ""},
+}
+
+func TestValueConverters(t *testing.T) {
+	for i, tt := range valueConverterTests {
+		out, err := tt.c.ConvertValue(tt.in)
+		goterr := ""
+		if err != nil {
+			goterr = err.Error()
+		}
+		if goterr != tt.err {
+			t.Errorf("test %d: %s(%T(%v)) error = %q; want error = %q",
+				i, tt.c, tt.in, tt.in, goterr, tt.err)
+		}
+		if tt.err != "" {
+			continue
+		}
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("test %d: %s(%T(%v)) = %v (%T); want %v (%T)",
+				i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out)
+		}
+	}
+}
diff --git a/src/pkg/database/sql/doc.txt b/src/pkg/database/sql/doc.txt
new file mode 100644
index 0000000..fb16595
--- /dev/null
+++ b/src/pkg/database/sql/doc.txt
@@ -0,0 +1,46 @@
+Goals of the sql and sql/driver packages:
+
+* Provide a generic database API for a variety of SQL or SQL-like
+  databases.  There currently exist Go libraries for SQLite, MySQL,
+  and Postgres, but all with a very different feel, and often
+  a non-Go-like feel.
+
+* Feel like Go.
+
+* Care mostly about the common cases. Common SQL should be portable.
+  SQL edge cases or db-specific extensions can be detected and
+  conditionally used by the application.  It is a non-goal to care
+  about every particular db's extension or quirk.
+
+* Separate out the basic implementation of a database driver
+  (implementing the sql/driver interfaces) vs the implementation
+  of all the user-level types and convenience methods.
+  In a nutshell:
+
+  User Code ---> sql package (concrete types) ---> sql/driver (interfaces)
+  Database Driver -> sql (to register) + sql/driver (implement interfaces)
+
+* Make type casting/conversions consistent between all drivers. To
+  achieve this, most of the conversions are done in the db package,
+  not in each driver. The drivers then only have to deal with a
+  smaller set of types.
+
+* Be flexible with type conversions, but be paranoid about silent
+  truncation or other loss of precision.
+
+* Handle concurrency well.  Users shouldn't need to care about the
+  database's per-connection thread safety issues (or lack thereof),
+  and shouldn't have to maintain their own free pools of connections.
+  The 'db' package should deal with that bookkeeping as needed.  Given
+  an *sql.DB, it should be possible to share that instance between
+  multiple goroutines, without any extra synchronization.
+
+* Push complexity, where necessary, down into the sql+driver packages,
+  rather than exposing it to users. Said otherwise, the sql package
+  should expose an ideal database that's not finnicky about how it's
+  accessed, even if that's not true.
+
+* Provide optional interfaces in sql/driver for drivers to implement
+  for special cases or fastpaths.  But the only party that knows about
+  those is the sql package.  To user code, some stuff just might start
+  working or start working slightly faster.
diff --git a/src/pkg/database/sql/driver/Makefile b/src/pkg/database/sql/driver/Makefile
new file mode 100644
index 0000000..564aaa6
--- /dev/null
+++ b/src/pkg/database/sql/driver/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../../Make.inc
+
+TARG=database/sql/driver
+GOFILES=\
+	driver.go\
+	types.go\
+
+include ../../../../Make.pkg
diff --git a/src/pkg/database/sql/driver/driver.go b/src/pkg/database/sql/driver/driver.go
new file mode 100644
index 0000000..0cd2562
--- /dev/null
+++ b/src/pkg/database/sql/driver/driver.go
@@ -0,0 +1,207 @@
+// Copyright 2011 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 driver defines interfaces to be implemented by database
+// drivers as used by package sql.
+//
+// Code simply using databases should use package sql.
+//
+// Drivers only need to be aware of a subset of Go's types.  The sql package
+// will convert all types into one of the following:
+//
+//   int64
+//   float64
+//   bool
+//   nil
+//   []byte
+//   string   [*] everywhere except from Rows.Next.
+//   time.Time
+//
+package driver
+
+import "errors"
+
+// Driver is the interface that must be implemented by a database
+// driver.
+type Driver interface {
+	// Open returns a new connection to the database.
+	// The name is a string in a driver-specific format.
+	//
+	// Open may return a cached connection (one previously
+	// closed), but doing so is unnecessary; the sql package
+	// maintains a pool of idle connections for efficient re-use.
+	//
+	// The returned connection is only used by one goroutine at a
+	// time.
+	Open(name string) (Conn, error)
+}
+
+// ErrSkip may be returned by some optional interfaces' methods to
+// indicate at runtime that the fast path is unavailable and the sql
+// package should continue as if the optional interface was not
+// implemented. ErrSkip is only supported where explicitly
+// documented.
+var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")
+
+// Execer is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement Execer, the db package's DB.Exec will
+// first prepare a query, execute the statement, and then close the
+// statement.
+//
+// All arguments are of a subset type as defined in the package docs.
+//
+// Exec may return ErrSkip.
+type Execer interface {
+	Exec(query string, args []interface{}) (Result, error)
+}
+
+// Conn is a connection to a database. It is not used concurrently
+// by multiple goroutines.
+//
+// Conn is assumed to be stateful.
+type Conn interface {
+	// Prepare returns a prepared statement, bound to this connection.
+	Prepare(query string) (Stmt, error)
+
+	// Close invalidates and potentially stops any current
+	// prepared statements and transactions, marking this
+	// connection as no longer in use.
+	//
+	// Because the sql package maintains a free pool of
+	// connections and only calls Close when there's a surplus of
+	// idle connections, it shouldn't be necessary for drivers to
+	// do their own connection caching.
+	Close() error
+
+	// Begin starts and returns a new transaction.
+	Begin() (Tx, error)
+}
+
+// Result is the result of a query execution.
+type Result interface {
+	// LastInsertId returns the database's auto-generated ID
+	// after, for example, an INSERT into a table with primary
+	// key.
+	LastInsertId() (int64, error)
+
+	// RowsAffected returns the number of rows affected by the
+	// query.
+	RowsAffected() (int64, error)
+}
+
+// Stmt is a prepared statement. It is bound to a Conn and not
+// used by multiple goroutines concurrently.
+type Stmt interface {
+	// Close closes the statement.
+	//
+	// Closing a statement should not interrupt any outstanding
+	// query created from that statement. That is, the following
+	// order of operations is valid:
+	//
+	//  * create a driver statement
+	//  * call Query on statement, returning Rows
+	//  * close the statement
+	//  * read from Rows
+	//
+	// If closing a statement invalidates currently-running
+	// queries, the final step above will incorrectly fail.
+	//
+	// TODO(bradfitz): possibly remove the restriction above, if
+	// enough driver authors object and find it complicates their
+	// code too much. The sql package could be smarter about
+	// refcounting the statement and closing it at the appropriate
+	// time.
+	Close() error
+
+	// NumInput returns the number of placeholder parameters.
+	//
+	// If NumInput returns >= 0, the sql package will sanity check
+	// argument counts from callers and return errors to the caller
+	// before the statement's Exec or Query methods are called.
+	//
+	// NumInput may also return -1, if the driver doesn't know
+	// its number of placeholders. In that case, the sql package
+	// will not sanity check Exec or Query argument counts.
+	NumInput() int
+
+	// Exec executes a query that doesn't return rows, such
+	// as an INSERT or UPDATE.  The args are all of a subset
+	// type as defined above.
+	Exec(args []interface{}) (Result, error)
+
+	// Exec executes a query that may return rows, such as a
+	// SELECT.  The args of all of a subset type as defined above.
+	Query(args []interface{}) (Rows, error)
+}
+
+// ColumnConverter may be optionally implemented by Stmt if the
+// the statement is aware of its own columns' types and can
+// convert from any type to a driver subset type.
+type ColumnConverter interface {
+	// ColumnConverter returns a ValueConverter for the provided
+	// column index.  If the type of a specific column isn't known
+	// or shouldn't be handled specially, DefaultValueConverter
+	// can be returned.
+	ColumnConverter(idx int) ValueConverter
+}
+
+// Rows is an iterator over an executed query's results.
+type Rows interface {
+	// Columns returns the names of the columns. The number of
+	// columns of the result is inferred from the length of the
+	// slice.  If a particular column name isn't known, an empty
+	// string should be returned for that entry.
+	Columns() []string
+
+	// Close closes the rows iterator.
+	Close() error
+
+	// Next is called to populate the next row of data into
+	// the provided slice. The provided slice will be the same
+	// size as the Columns() are wide.
+	//
+	// The dest slice may be populated with only with values
+	// of subset types defined above, but excluding string.
+	// All string values must be converted to []byte.
+	//
+	// Next should return io.EOF when there are no more rows.
+	Next(dest []interface{}) error
+}
+
+// Tx is a transaction.
+type Tx interface {
+	Commit() error
+	Rollback() error
+}
+
+// RowsAffected implements Result for an INSERT or UPDATE operation
+// which mutates a number of rows.
+type RowsAffected int64
+
+var _ Result = RowsAffected(0)
+
+func (RowsAffected) LastInsertId() (int64, error) {
+	return 0, errors.New("no LastInsertId available")
+}
+
+func (v RowsAffected) RowsAffected() (int64, error) {
+	return int64(v), nil
+}
+
+// DDLSuccess is a pre-defined Result for drivers to return when a DDL
+// command succeeds.
+var DDLSuccess ddlSuccess
+
+type ddlSuccess struct{}
+
+var _ Result = ddlSuccess{}
+
+func (ddlSuccess) LastInsertId() (int64, error) {
+	return 0, errors.New("no LastInsertId available after DDL statement")
+}
+
+func (ddlSuccess) RowsAffected() (int64, error) {
+	return 0, errors.New("no RowsAffected available after DDL statement")
+}
diff --git a/src/pkg/database/sql/driver/types.go b/src/pkg/database/sql/driver/types.go
new file mode 100644
index 0000000..f383885
--- /dev/null
+++ b/src/pkg/database/sql/driver/types.go
@@ -0,0 +1,265 @@
+// Copyright 2011 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 driver
+
+import (
+	"fmt"
+	"reflect"
+	"strconv"
+	"time"
+)
+
+// ValueConverter is the interface providing the ConvertValue method.
+//
+// Various implementations of ValueConverter are provided by the
+// driver package to provide consistent implementations of conversions
+// between drivers.  The ValueConverters have several uses:
+//
+//  * converting from the subset types as provided by the sql package
+//    into a database table's specific column type and making sure it
+//    fits, such as making sure a particular int64 fits in a
+//    table's uint16 column.
+//
+//  * converting a value as given from the database into one of the
+//    subset types.
+//
+//  * by the sql package, for converting from a driver's subset type
+//    to a user's type in a scan.
+type ValueConverter interface {
+	// ConvertValue converts a value to a restricted subset type.
+	ConvertValue(v interface{}) (interface{}, error)
+}
+
+// SubsetValuer is the interface providing the SubsetValue method.
+//
+// Types implementing SubsetValuer interface are able to convert
+// themselves to one of the driver's allowed subset values.
+type SubsetValuer interface {
+	// SubsetValue returns a driver parameter subset value.
+	SubsetValue() (interface{}, error)
+}
+
+// Bool is a ValueConverter that converts input values to bools.
+//
+// The conversion rules are:
+//  - booleans are returned unchanged
+//  - for integer types,
+//       1 is true
+//       0 is false,
+//       other integers are an error
+//  - for strings and []byte, same rules as strconv.ParseBool
+//  - all other types are an error
+var Bool boolType
+
+type boolType struct{}
+
+var _ ValueConverter = boolType{}
+
+func (boolType) String() string { return "Bool" }
+
+func (boolType) ConvertValue(src interface{}) (interface{}, error) {
+	switch s := src.(type) {
+	case bool:
+		return s, nil
+	case string:
+		b, err := strconv.ParseBool(s)
+		if err != nil {
+			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
+		}
+		return b, nil
+	case []byte:
+		b, err := strconv.ParseBool(string(s))
+		if err != nil {
+			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
+		}
+		return b, nil
+	}
+
+	sv := reflect.ValueOf(src)
+	switch sv.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		iv := sv.Int()
+		if iv == 1 || iv == 0 {
+			return iv == 1, nil
+		}
+		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		uv := sv.Uint()
+		if uv == 1 || uv == 0 {
+			return uv == 1, nil
+		}
+		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv)
+	}
+
+	return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src)
+}
+
+// Int32 is a ValueConverter that converts input values to int64,
+// respecting the limits of an int32 value.
+var Int32 int32Type
+
+type int32Type struct{}
+
+var _ ValueConverter = int32Type{}
+
+func (int32Type) ConvertValue(v interface{}) (interface{}, error) {
+	rv := reflect.ValueOf(v)
+	switch rv.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		i64 := rv.Int()
+		if i64 > (1<<31)-1 || i64 < -(1<<31) {
+			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
+		}
+		return i64, nil
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		u64 := rv.Uint()
+		if u64 > (1<<31)-1 {
+			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
+		}
+		return int64(u64), nil
+	case reflect.String:
+		i, err := strconv.Atoi(rv.String())
+		if err != nil {
+			return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v)
+		}
+		return int64(i), nil
+	}
+	return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v)
+}
+
+// String is a ValueConverter that converts its input to a string.
+// If the value is already a string or []byte, it's unchanged.
+// If the value is of another type, conversion to string is done
+// with fmt.Sprintf("%v", v).
+var String stringType
+
+type stringType struct{}
+
+func (stringType) ConvertValue(v interface{}) (interface{}, error) {
+	switch v.(type) {
+	case string, []byte:
+		return v, nil
+	}
+	return fmt.Sprintf("%v", v), nil
+}
+
+// Null is a type that implements ValueConverter by allowing nil
+// values but otherwise delegating to another ValueConverter.
+type Null struct {
+	Converter ValueConverter
+}
+
+func (n Null) ConvertValue(v interface{}) (interface{}, error) {
+	if v == nil {
+		return nil, nil
+	}
+	return n.Converter.ConvertValue(v)
+}
+
+// NotNull is a type that implements ValueConverter by disallowing nil
+// values but otherwise delegating to another ValueConverter.
+type NotNull struct {
+	Converter ValueConverter
+}
+
+func (n NotNull) ConvertValue(v interface{}) (interface{}, error) {
+	if v == nil {
+		return nil, fmt.Errorf("nil value not allowed")
+	}
+	return n.Converter.ConvertValue(v)
+}
+
+// IsParameterSubsetType reports whether v is of a valid type for a
+// parameter. These types are:
+//
+//   int64
+//   float64
+//   bool
+//   nil
+//   []byte
+//   time.Time
+//   string
+//
+// This is the same list as IsScanSubsetType, with the addition of
+// string.
+func IsParameterSubsetType(v interface{}) bool {
+	if IsScanSubsetType(v) {
+		return true
+	}
+	if _, ok := v.(string); ok {
+		return true
+	}
+	return false
+}
+
+// IsScanSubsetType reports whether v is of a valid type for a
+// value populated by Rows.Next. These types are:
+//
+//   int64
+//   float64
+//   bool
+//   nil
+//   []byte
+//   time.Time
+//
+// This is the same list as IsParameterSubsetType, without string.
+func IsScanSubsetType(v interface{}) bool {
+	if v == nil {
+		return true
+	}
+	switch v.(type) {
+	case int64, float64, []byte, bool, time.Time:
+		return true
+	}
+	return false
+}
+
+// DefaultParameterConverter is the default implementation of
+// ValueConverter that's used when a Stmt doesn't implement
+// ColumnConverter.
+//
+// DefaultParameterConverter returns the given value directly if
+// IsSubsetType(value).  Otherwise integer type are converted to
+// int64, floats to float64, and strings to []byte.  Other types are
+// an error.
+var DefaultParameterConverter defaultConverter
+
+type defaultConverter struct{}
+
+var _ ValueConverter = defaultConverter{}
+
+func (defaultConverter) ConvertValue(v interface{}) (interface{}, error) {
+	if IsParameterSubsetType(v) {
+		return v, nil
+	}
+
+	if svi, ok := v.(SubsetValuer); ok {
+		sv, err := svi.SubsetValue()
+		if err != nil {
+			return nil, err
+		}
+		if !IsParameterSubsetType(sv) {
+			return nil, fmt.Errorf("non-subset type %T returned from SubsetValue", sv)
+		}
+		return sv, nil
+	}
+
+	rv := reflect.ValueOf(v)
+	switch rv.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return rv.Int(), nil
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
+		return int64(rv.Uint()), nil
+	case reflect.Uint64:
+		u64 := rv.Uint()
+		if u64 >= 1<<63 {
+			return nil, fmt.Errorf("uint64 values with high bit set are not supported")
+		}
+		return int64(u64), nil
+	case reflect.Float32, reflect.Float64:
+		return rv.Float(), nil
+	}
+	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
+}
diff --git a/src/pkg/database/sql/driver/types_test.go b/src/pkg/database/sql/driver/types_test.go
new file mode 100644
index 0000000..966bc6b
--- /dev/null
+++ b/src/pkg/database/sql/driver/types_test.go
@@ -0,0 +1,61 @@
+// Copyright 2011 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 driver
+
+import (
+	"reflect"
+	"testing"
+	"time"
+)
+
+type valueConverterTest struct {
+	c   ValueConverter
+	in  interface{}
+	out interface{}
+	err string
+}
+
+var now = time.Now()
+
+var valueConverterTests = []valueConverterTest{
+	{Bool, "true", true, ""},
+	{Bool, "True", true, ""},
+	{Bool, []byte("t"), true, ""},
+	{Bool, true, true, ""},
+	{Bool, "1", true, ""},
+	{Bool, 1, true, ""},
+	{Bool, int64(1), true, ""},
+	{Bool, uint16(1), true, ""},
+	{Bool, "false", false, ""},
+	{Bool, false, false, ""},
+	{Bool, "0", false, ""},
+	{Bool, 0, false, ""},
+	{Bool, int64(0), false, ""},
+	{Bool, uint16(0), false, ""},
+	{c: Bool, in: "foo", err: "sql/driver: couldn't convert \"foo\" into type bool"},
+	{c: Bool, in: 2, err: "sql/driver: couldn't convert 2 into type bool"},
+	{DefaultParameterConverter, now, now, ""},
+}
+
+func TestValueConverters(t *testing.T) {
+	for i, tt := range valueConverterTests {
+		out, err := tt.c.ConvertValue(tt.in)
+		goterr := ""
+		if err != nil {
+			goterr = err.Error()
+		}
+		if goterr != tt.err {
+			t.Errorf("test %d: %s(%T(%v)) error = %q; want error = %q",
+				i, tt.c, tt.in, tt.in, goterr, tt.err)
+		}
+		if tt.err != "" {
+			continue
+		}
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("test %d: %s(%T(%v)) = %v (%T); want %v (%T)",
+				i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out)
+		}
+	}
+}
diff --git a/src/pkg/database/sql/fakedb_test.go b/src/pkg/database/sql/fakedb_test.go
new file mode 100644
index 0000000..df25023
--- /dev/null
+++ b/src/pkg/database/sql/fakedb_test.go
@@ -0,0 +1,612 @@
+// Copyright 2011 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 sql
+
+import (
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+var _ = log.Printf
+
+// fakeDriver is a fake database that implements Go's driver.Driver
+// interface, just for testing.
+//
+// It speaks a query language that's semantically similar to but
+// syntantically different and simpler than SQL.  The syntax is as
+// follows:
+//
+//   WIPE
+//   CREATE|<tablename>|<col>=<type>,<col>=<type>,...
+//     where types are: "string", [u]int{8,16,32,64}, "bool"
+//   INSERT|<tablename>|col=val,col2=val2,col3=?
+//   SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
+//
+// When opening a a fakeDriver's database, it starts empty with no
+// tables.  All tables and data are stored in memory only.
+type fakeDriver struct {
+	mu        sync.Mutex
+	openCount int
+	dbs       map[string]*fakeDB
+}
+
+type fakeDB struct {
+	name string
+
+	mu     sync.Mutex
+	free   []*fakeConn
+	tables map[string]*table
+}
+
+type table struct {
+	mu      sync.Mutex
+	colname []string
+	coltype []string
+	rows    []*row
+}
+
+func (t *table) columnIndex(name string) int {
+	for n, nname := range t.colname {
+		if name == nname {
+			return n
+		}
+	}
+	return -1
+}
+
+type row struct {
+	cols []interface{} // must be same size as its table colname + coltype
+}
+
+func (r *row) clone() *row {
+	nrow := &row{cols: make([]interface{}, len(r.cols))}
+	copy(nrow.cols, r.cols)
+	return nrow
+}
+
+type fakeConn struct {
+	db *fakeDB // where to return ourselves to
+
+	currTx *fakeTx
+
+	// Stats for tests:
+	mu          sync.Mutex
+	stmtsMade   int
+	stmtsClosed int
+}
+
+func (c *fakeConn) incrStat(v *int) {
+	c.mu.Lock()
+	*v++
+	c.mu.Unlock()
+}
+
+type fakeTx struct {
+	c *fakeConn
+}
+
+type fakeStmt struct {
+	c *fakeConn
+	q string // just for debugging
+
+	cmd   string
+	table string
+
+	closed bool
+
+	colName      []string      // used by CREATE, INSERT, SELECT (selected columns)
+	colType      []string      // used by CREATE
+	colValue     []interface{} // used by INSERT (mix of strings and "?" for bound params)
+	placeholders int           // used by INSERT/SELECT: number of ? params
+
+	whereCol []string // used by SELECT (all placeholders)
+
+	placeholderConverter []driver.ValueConverter // used by INSERT
+}
+
+var fdriver driver.Driver = &fakeDriver{}
+
+func init() {
+	Register("test", fdriver)
+}
+
+// Supports dsn forms:
+//    <dbname>
+//    <dbname>;<opts>  (no currently supported options)
+func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
+	parts := strings.Split(dsn, ";")
+	if len(parts) < 1 {
+		return nil, errors.New("fakedb: no database name")
+	}
+	name := parts[0]
+
+	db := d.getDB(name)
+
+	d.mu.Lock()
+	d.openCount++
+	d.mu.Unlock()
+	return &fakeConn{db: db}, nil
+}
+
+func (d *fakeDriver) getDB(name string) *fakeDB {
+	d.mu.Lock()
+	defer d.mu.Unlock()
+	if d.dbs == nil {
+		d.dbs = make(map[string]*fakeDB)
+	}
+	db, ok := d.dbs[name]
+	if !ok {
+		db = &fakeDB{name: name}
+		d.dbs[name] = db
+	}
+	return db
+}
+
+func (db *fakeDB) wipe() {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	db.tables = nil
+}
+
+func (db *fakeDB) createTable(name string, columnNames, columnTypes []string) error {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	if db.tables == nil {
+		db.tables = make(map[string]*table)
+	}
+	if _, exist := db.tables[name]; exist {
+		return fmt.Errorf("table %q already exists", name)
+	}
+	if len(columnNames) != len(columnTypes) {
+		return fmt.Errorf("create table of %q len(names) != len(types): %d vs %d",
+			name, len(columnNames), len(columnTypes))
+	}
+	db.tables[name] = &table{colname: columnNames, coltype: columnTypes}
+	return nil
+}
+
+// must be called with db.mu lock held
+func (db *fakeDB) table(table string) (*table, bool) {
+	if db.tables == nil {
+		return nil, false
+	}
+	t, ok := db.tables[table]
+	return t, ok
+}
+
+func (db *fakeDB) columnType(table, column string) (typ string, ok bool) {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	t, ok := db.table(table)
+	if !ok {
+		return
+	}
+	for n, cname := range t.colname {
+		if cname == column {
+			return t.coltype[n], true
+		}
+	}
+	return "", false
+}
+
+func (c *fakeConn) Begin() (driver.Tx, error) {
+	if c.currTx != nil {
+		return nil, errors.New("already in a transaction")
+	}
+	c.currTx = &fakeTx{c: c}
+	return c.currTx, nil
+}
+
+func (c *fakeConn) Close() error {
+	if c.currTx != nil {
+		return errors.New("can't close; in a Transaction")
+	}
+	if c.db == nil {
+		return errors.New("can't close; already closed")
+	}
+	c.db = nil
+	return nil
+}
+
+func checkSubsetTypes(args []interface{}) error {
+	for n, arg := range args {
+		switch arg.(type) {
+		case int64, float64, bool, nil, []byte, string, time.Time:
+		default:
+			return fmt.Errorf("fakedb_test: invalid argument #%d: %v, type %T", n+1, arg, arg)
+		}
+	}
+	return nil
+}
+
+func (c *fakeConn) Exec(query string, args []interface{}) (driver.Result, error) {
+	// This is an optional interface, but it's implemented here
+	// just to check that all the args of of the proper types.
+	// ErrSkip is returned so the caller acts as if we didn't
+	// implement this at all.
+	err := checkSubsetTypes(args)
+	if err != nil {
+		return nil, err
+	}
+	return nil, driver.ErrSkip
+}
+
+func errf(msg string, args ...interface{}) error {
+	return errors.New("fakedb: " + fmt.Sprintf(msg, args...))
+}
+
+// parts are table|selectCol1,selectCol2|whereCol=?,whereCol2=?
+// (note that where where columns must always contain ? marks,
+//  just a limitation for fakedb)
+func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+	if len(parts) != 3 {
+		return nil, errf("invalid SELECT syntax with %d parts; want 3", len(parts))
+	}
+	stmt.table = parts[0]
+	stmt.colName = strings.Split(parts[1], ",")
+	for n, colspec := range strings.Split(parts[2], ",") {
+		if colspec == "" {
+			continue
+		}
+		nameVal := strings.Split(colspec, "=")
+		if len(nameVal) != 2 {
+			return nil, errf("SELECT on table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+		}
+		column, value := nameVal[0], nameVal[1]
+		_, ok := c.db.columnType(stmt.table, column)
+		if !ok {
+			return nil, errf("SELECT on table %q references non-existent column %q", stmt.table, column)
+		}
+		if value != "?" {
+			return nil, errf("SELECT on table %q has pre-bound value for where column %q; need a question mark",
+				stmt.table, column)
+		}
+		stmt.whereCol = append(stmt.whereCol, column)
+		stmt.placeholders++
+	}
+	return stmt, nil
+}
+
+// parts are table|col=type,col2=type2
+func (c *fakeConn) prepareCreate(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+	if len(parts) != 2 {
+		return nil, errf("invalid CREATE syntax with %d parts; want 2", len(parts))
+	}
+	stmt.table = parts[0]
+	for n, colspec := range strings.Split(parts[1], ",") {
+		nameType := strings.Split(colspec, "=")
+		if len(nameType) != 2 {
+			return nil, errf("CREATE table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+		}
+		stmt.colName = append(stmt.colName, nameType[0])
+		stmt.colType = append(stmt.colType, nameType[1])
+	}
+	return stmt, nil
+}
+
+// parts are table|col=?,col2=val
+func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+	if len(parts) != 2 {
+		return nil, errf("invalid INSERT syntax with %d parts; want 2", len(parts))
+	}
+	stmt.table = parts[0]
+	for n, colspec := range strings.Split(parts[1], ",") {
+		nameVal := strings.Split(colspec, "=")
+		if len(nameVal) != 2 {
+			return nil, errf("INSERT table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+		}
+		column, value := nameVal[0], nameVal[1]
+		ctype, ok := c.db.columnType(stmt.table, column)
+		if !ok {
+			return nil, errf("INSERT table %q references non-existent column %q", stmt.table, column)
+		}
+		stmt.colName = append(stmt.colName, column)
+
+		if value != "?" {
+			var subsetVal interface{}
+			// Convert to driver subset type
+			switch ctype {
+			case "string":
+				subsetVal = []byte(value)
+			case "blob":
+				subsetVal = []byte(value)
+			case "int32":
+				i, err := strconv.Atoi(value)
+				if err != nil {
+					return nil, errf("invalid conversion to int32 from %q", value)
+				}
+				subsetVal = int64(i) // int64 is a subset type, but not int32
+			default:
+				return nil, errf("unsupported conversion for pre-bound parameter %q to type %q", value, ctype)
+			}
+			stmt.colValue = append(stmt.colValue, subsetVal)
+		} else {
+			stmt.placeholders++
+			stmt.placeholderConverter = append(stmt.placeholderConverter, converterForType(ctype))
+			stmt.colValue = append(stmt.colValue, "?")
+		}
+	}
+	return stmt, nil
+}
+
+func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
+	if c.db == nil {
+		panic("nil c.db; conn = " + fmt.Sprintf("%#v", c))
+	}
+	parts := strings.Split(query, "|")
+	if len(parts) < 1 {
+		return nil, errf("empty query")
+	}
+	cmd := parts[0]
+	parts = parts[1:]
+	stmt := &fakeStmt{q: query, c: c, cmd: cmd}
+	c.incrStat(&c.stmtsMade)
+	switch cmd {
+	case "WIPE":
+		// Nothing
+	case "SELECT":
+		return c.prepareSelect(stmt, parts)
+	case "CREATE":
+		return c.prepareCreate(stmt, parts)
+	case "INSERT":
+		return c.prepareInsert(stmt, parts)
+	default:
+		return nil, errf("unsupported command type %q", cmd)
+	}
+	return stmt, nil
+}
+
+func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
+	return s.placeholderConverter[idx]
+}
+
+func (s *fakeStmt) Close() error {
+	if !s.closed {
+		s.c.incrStat(&s.c.stmtsClosed)
+		s.closed = true
+	}
+	return nil
+}
+
+var errClosed = errors.New("fakedb: statement has been closed")
+
+func (s *fakeStmt) Exec(args []interface{}) (driver.Result, error) {
+	if s.closed {
+		return nil, errClosed
+	}
+	err := checkSubsetTypes(args)
+	if err != nil {
+		return nil, err
+	}
+
+	db := s.c.db
+	switch s.cmd {
+	case "WIPE":
+		db.wipe()
+		return driver.DDLSuccess, nil
+	case "CREATE":
+		if err := db.createTable(s.table, s.colName, s.colType); err != nil {
+			return nil, err
+		}
+		return driver.DDLSuccess, nil
+	case "INSERT":
+		return s.execInsert(args)
+	}
+	fmt.Printf("EXEC statement, cmd=%q: %#v\n", s.cmd, s)
+	return nil, fmt.Errorf("unimplemented statement Exec command type of %q", s.cmd)
+}
+
+func (s *fakeStmt) execInsert(args []interface{}) (driver.Result, error) {
+	db := s.c.db
+	if len(args) != s.placeholders {
+		panic("error in pkg db; should only get here if size is correct")
+	}
+	db.mu.Lock()
+	t, ok := db.table(s.table)
+	db.mu.Unlock()
+	if !ok {
+		return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
+	}
+
+	t.mu.Lock()
+	defer t.mu.Unlock()
+
+	cols := make([]interface{}, len(t.colname))
+	argPos := 0
+	for n, colname := range s.colName {
+		colidx := t.columnIndex(colname)
+		if colidx == -1 {
+			return nil, fmt.Errorf("fakedb: column %q doesn't exist or dropped since prepared statement was created", colname)
+		}
+		var val interface{}
+		if strvalue, ok := s.colValue[n].(string); ok && strvalue == "?" {
+			val = args[argPos]
+			argPos++
+		} else {
+			val = s.colValue[n]
+		}
+		cols[colidx] = val
+	}
+
+	t.rows = append(t.rows, &row{cols: cols})
+	return driver.RowsAffected(1), nil
+}
+
+func (s *fakeStmt) Query(args []interface{}) (driver.Rows, error) {
+	if s.closed {
+		return nil, errClosed
+	}
+	err := checkSubsetTypes(args)
+	if err != nil {
+		return nil, err
+	}
+
+	db := s.c.db
+	if len(args) != s.placeholders {
+		panic("error in pkg db; should only get here if size is correct")
+	}
+
+	db.mu.Lock()
+	t, ok := db.table(s.table)
+	db.mu.Unlock()
+	if !ok {
+		return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
+	}
+	t.mu.Lock()
+	defer t.mu.Unlock()
+
+	colIdx := make(map[string]int) // select column name -> column index in table
+	for _, name := range s.colName {
+		idx := t.columnIndex(name)
+		if idx == -1 {
+			return nil, fmt.Errorf("fakedb: unknown column name %q", name)
+		}
+		colIdx[name] = idx
+	}
+
+	mrows := []*row{}
+rows:
+	for _, trow := range t.rows {
+		// Process the where clause, skipping non-match rows. This is lazy
+		// and just uses fmt.Sprintf("%v") to test equality.  Good enough
+		// for test code.
+		for widx, wcol := range s.whereCol {
+			idx := t.columnIndex(wcol)
+			if idx == -1 {
+				return nil, fmt.Errorf("db: invalid where clause column %q", wcol)
+			}
+			tcol := trow.cols[idx]
+			if bs, ok := tcol.([]byte); ok {
+				// lazy hack to avoid sprintf %v on a []byte
+				tcol = string(bs)
+			}
+			if fmt.Sprintf("%v", tcol) != fmt.Sprintf("%v", args[widx]) {
+				continue rows
+			}
+		}
+		mrow := &row{cols: make([]interface{}, len(s.colName))}
+		for seli, name := range s.colName {
+			mrow.cols[seli] = trow.cols[colIdx[name]]
+		}
+		mrows = append(mrows, mrow)
+	}
+
+	cursor := &rowsCursor{
+		pos:  -1,
+		rows: mrows,
+		cols: s.colName,
+	}
+	return cursor, nil
+}
+
+func (s *fakeStmt) NumInput() int {
+	return s.placeholders
+}
+
+func (tx *fakeTx) Commit() error {
+	tx.c.currTx = nil
+	return nil
+}
+
+func (tx *fakeTx) Rollback() error {
+	tx.c.currTx = nil
+	return nil
+}
+
+type rowsCursor struct {
+	cols   []string
+	pos    int
+	rows   []*row
+	closed bool
+
+	// a clone of slices to give out to clients, indexed by the
+	// the original slice's first byte address.  we clone them
+	// just so we're able to corrupt them on close.
+	bytesClone map[*byte][]byte
+}
+
+func (rc *rowsCursor) Close() error {
+	if !rc.closed {
+		for _, bs := range rc.bytesClone {
+			bs[0] = 255 // first byte corrupted
+		}
+	}
+	rc.closed = true
+	return nil
+}
+
+func (rc *rowsCursor) Columns() []string {
+	return rc.cols
+}
+
+func (rc *rowsCursor) Next(dest []interface{}) error {
+	if rc.closed {
+		return errors.New("fakedb: cursor is closed")
+	}
+	rc.pos++
+	if rc.pos >= len(rc.rows) {
+		return io.EOF // per interface spec
+	}
+	for i, v := range rc.rows[rc.pos].cols {
+		// TODO(bradfitz): convert to subset types? naah, I
+		// think the subset types should only be input to
+		// driver, but the sql package should be able to handle
+		// a wider range of types coming out of drivers. all
+		// for ease of drivers, and to prevent drivers from
+		// messing up conversions or doing them differently.
+		dest[i] = v
+
+		if bs, ok := v.([]byte); ok {
+			if rc.bytesClone == nil {
+				rc.bytesClone = make(map[*byte][]byte)
+			}
+			clone, ok := rc.bytesClone[&bs[0]]
+			if !ok {
+				clone = make([]byte, len(bs))
+				copy(clone, bs)
+				rc.bytesClone[&bs[0]] = clone
+			}
+			dest[i] = clone
+		}
+	}
+	return nil
+}
+
+func converterForType(typ string) driver.ValueConverter {
+	switch typ {
+	case "bool":
+		return driver.Bool
+	case "nullbool":
+		return driver.Null{driver.Bool}
+	case "int32":
+		return driver.Int32
+	case "string":
+		return driver.NotNull{driver.String}
+	case "nullstring":
+		return driver.Null{driver.String}
+	case "int64":
+		// TODO(coopernurse): add type-specific converter
+		return driver.NotNull{driver.DefaultParameterConverter}
+	case "nullint64":
+		// TODO(coopernurse): add type-specific converter
+		return driver.Null{driver.DefaultParameterConverter}
+	case "float64":
+		// TODO(coopernurse): add type-specific converter
+		return driver.NotNull{driver.DefaultParameterConverter}
+	case "nullfloat64":
+		// TODO(coopernurse): add type-specific converter
+		return driver.Null{driver.DefaultParameterConverter}
+	case "datetime":
+		return driver.DefaultParameterConverter
+	}
+	panic("invalid fakedb column type of " + typ)
+}
diff --git a/src/pkg/database/sql/sql.go b/src/pkg/database/sql/sql.go
new file mode 100644
index 0000000..34a7652
--- /dev/null
+++ b/src/pkg/database/sql/sql.go
@@ -0,0 +1,994 @@
+// Copyright 2011 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 sql provides a generic interface around SQL (or SQL-like)
+// databases.
+package sql
+
+import (
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"io"
+	"sync"
+)
+
+var drivers = make(map[string]driver.Driver)
+
+// Register makes a database driver available by the provided name.
+// If Register is called twice with the same name or if driver is nil,
+// it panics.
+func Register(name string, driver driver.Driver) {
+	if driver == nil {
+		panic("sql: Register driver is nil")
+	}
+	if _, dup := drivers[name]; dup {
+		panic("sql: Register called twice for driver " + name)
+	}
+	drivers[name] = driver
+}
+
+// RawBytes is a byte slice that holds a reference to memory owned by
+// the database itself. After a Scan into a RawBytes, the slice is only
+// valid until the next call to Next, Scan, or Close.
+type RawBytes []byte
+
+// NullString represents a string that may be null.
+// NullString implements the ScannerInto interface so
+// it can be used as a scan destination:
+//
+//  var s NullString
+//  err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s)
+//  ...
+//  if s.Valid {
+//     // use s.String
+//  } else {
+//     // NULL value
+//  }
+//
+type NullString struct {
+	String string
+	Valid  bool // Valid is true if String is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (ns *NullString) ScanInto(value interface{}) error {
+	if value == nil {
+		ns.String, ns.Valid = "", false
+		return nil
+	}
+	ns.Valid = true
+	return convertAssign(&ns.String, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (ns NullString) SubsetValue() (interface{}, error) {
+	if !ns.Valid {
+		return nil, nil
+	}
+	return ns.String, nil
+}
+
+// NullInt64 represents an int64 that may be null.
+// NullInt64 implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullInt64 struct {
+	Int64 int64
+	Valid bool // Valid is true if Int64 is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullInt64) ScanInto(value interface{}) error {
+	if value == nil {
+		n.Int64, n.Valid = 0, false
+		return nil
+	}
+	n.Valid = true
+	return convertAssign(&n.Int64, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullInt64) SubsetValue() (interface{}, error) {
+	if !n.Valid {
+		return nil, nil
+	}
+	return n.Int64, nil
+}
+
+// NullFloat64 represents a float64 that may be null.
+// NullFloat64 implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullFloat64 struct {
+	Float64 float64
+	Valid   bool // Valid is true if Float64 is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullFloat64) ScanInto(value interface{}) error {
+	if value == nil {
+		n.Float64, n.Valid = 0, false
+		return nil
+	}
+	n.Valid = true
+	return convertAssign(&n.Float64, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullFloat64) SubsetValue() (interface{}, error) {
+	if !n.Valid {
+		return nil, nil
+	}
+	return n.Float64, nil
+}
+
+// NullBool represents a bool that may be null.
+// NullBool implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullBool struct {
+	Bool  bool
+	Valid bool // Valid is true if Bool is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullBool) ScanInto(value interface{}) error {
+	if value == nil {
+		n.Bool, n.Valid = false, false
+		return nil
+	}
+	n.Valid = true
+	return convertAssign(&n.Bool, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullBool) SubsetValue() (interface{}, error) {
+	if !n.Valid {
+		return nil, nil
+	}
+	return n.Bool, nil
+}
+
+// ScannerInto is an interface used by Scan.
+type ScannerInto interface {
+	// ScanInto assigns a value from a database driver.
+	//
+	// The value will be of one of the following restricted
+	// set of types:
+	//
+	//    int64
+	//    float64
+	//    bool
+	//    []byte
+	//    nil - for NULL values
+	//
+	// An error should be returned if the value can not be stored
+	// without loss of information.
+	ScanInto(value interface{}) error
+}
+
+// ErrNoRows is returned by Scan when QueryRow doesn't return a
+// row. In such a case, QueryRow returns a placeholder *Row value that
+// defers this error until a Scan.
+var ErrNoRows = errors.New("sql: no rows in result set")
+
+// DB is a database handle. It's safe for concurrent use by multiple
+// goroutines.
+type DB struct {
+	driver driver.Driver
+	dsn    string
+
+	mu       sync.Mutex // protects freeConn and closed
+	freeConn []driver.Conn
+	closed   bool
+}
+
+// Open opens a database specified by its database driver name and a
+// driver-specific data source name, usually consisting of at least a
+// database name and connection information.
+//
+// Most users will open a database via a driver-specific connection
+// helper function that returns a *DB.
+func Open(driverName, dataSourceName string) (*DB, error) {
+	driver, ok := drivers[driverName]
+	if !ok {
+		return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
+	}
+	return &DB{driver: driver, dsn: dataSourceName}, nil
+}
+
+// Close closes the database, releasing any open resources.
+func (db *DB) Close() error {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	var err error
+	for _, c := range db.freeConn {
+		err1 := c.Close()
+		if err1 != nil {
+			err = err1
+		}
+	}
+	db.freeConn = nil
+	db.closed = true
+	return err
+}
+
+func (db *DB) maxIdleConns() int {
+	const defaultMaxIdleConns = 2
+	// TODO(bradfitz): ask driver, if supported, for its default preference
+	// TODO(bradfitz): let users override?
+	return defaultMaxIdleConns
+}
+
+// conn returns a newly-opened or cached driver.Conn
+func (db *DB) conn() (driver.Conn, error) {
+	db.mu.Lock()
+	if db.closed {
+		db.mu.Unlock()
+		return nil, errors.New("sql: database is closed")
+	}
+	if n := len(db.freeConn); n > 0 {
+		conn := db.freeConn[n-1]
+		db.freeConn = db.freeConn[:n-1]
+		db.mu.Unlock()
+		return conn, nil
+	}
+	db.mu.Unlock()
+	return db.driver.Open(db.dsn)
+}
+
+func (db *DB) connIfFree(wanted driver.Conn) (conn driver.Conn, ok bool) {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	for n, conn := range db.freeConn {
+		if conn == wanted {
+			db.freeConn[n] = db.freeConn[len(db.freeConn)-1]
+			db.freeConn = db.freeConn[:len(db.freeConn)-1]
+			return wanted, true
+		}
+	}
+	return nil, false
+}
+
+func (db *DB) putConn(c driver.Conn) {
+	db.mu.Lock()
+	defer db.mu.Unlock()
+	if n := len(db.freeConn); !db.closed && n < db.maxIdleConns() {
+		db.freeConn = append(db.freeConn, c)
+		return
+	}
+	db.closeConn(c) // TODO(bradfitz): release lock before calling this?
+}
+
+func (db *DB) closeConn(c driver.Conn) {
+	// TODO: check to see if we need this Conn for any prepared statements
+	// that are active.
+	c.Close()
+}
+
+// Prepare creates a prepared statement for later execution.
+func (db *DB) Prepare(query string) (*Stmt, error) {
+	// TODO: check if db.driver supports an optional
+	// driver.Preparer interface and call that instead, if so,
+	// otherwise we make a prepared statement that's bound
+	// to a connection, and to execute this prepared statement
+	// we either need to use this connection (if it's free), else
+	// get a new connection + re-prepare + execute on that one.
+	ci, err := db.conn()
+	if err != nil {
+		return nil, err
+	}
+	defer db.putConn(ci)
+	si, err := ci.Prepare(query)
+	if err != nil {
+		return nil, err
+	}
+	stmt := &Stmt{
+		db:    db,
+		query: query,
+		css:   []connStmt{{ci, si}},
+	}
+	return stmt, nil
+}
+
+// Exec executes a query without returning any rows.
+func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
+	sargs, err := subsetTypeArgs(args)
+	if err != nil {
+		return nil, err
+	}
+
+	ci, err := db.conn()
+	if err != nil {
+		return nil, err
+	}
+	defer db.putConn(ci)
+
+	if execer, ok := ci.(driver.Execer); ok {
+		resi, err := execer.Exec(query, sargs)
+		if err != driver.ErrSkip {
+			if err != nil {
+				return nil, err
+			}
+			return result{resi}, nil
+		}
+	}
+
+	sti, err := ci.Prepare(query)
+	if err != nil {
+		return nil, err
+	}
+	defer sti.Close()
+
+	resi, err := sti.Exec(sargs)
+	if err != nil {
+		return nil, err
+	}
+	return result{resi}, nil
+}
+
+// Query executes a query that returns rows, typically a SELECT.
+func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
+	stmt, err := db.Prepare(query)
+	if err != nil {
+		return nil, err
+	}
+	rows, err := stmt.Query(args...)
+	if err != nil {
+		stmt.Close()
+		return nil, err
+	}
+	rows.closeStmt = stmt
+	return rows, nil
+}
+
+// QueryRow executes a query that is expected to return at most one row.
+// QueryRow always return a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+func (db *DB) QueryRow(query string, args ...interface{}) *Row {
+	rows, err := db.Query(query, args...)
+	return &Row{rows: rows, err: err}
+}
+
+// Begin starts a transaction. The isolation level is dependent on
+// the driver.
+func (db *DB) Begin() (*Tx, error) {
+	ci, err := db.conn()
+	if err != nil {
+		return nil, err
+	}
+	txi, err := ci.Begin()
+	if err != nil {
+		db.putConn(ci)
+		return nil, fmt.Errorf("sql: failed to Begin transaction: %v", err)
+	}
+	return &Tx{
+		db:  db,
+		ci:  ci,
+		txi: txi,
+	}, nil
+}
+
+// DriverDatabase returns the database's underlying driver.
+func (db *DB) Driver() driver.Driver {
+	return db.driver
+}
+
+// Tx is an in-progress database transaction.
+//
+// A transaction must end with a call to Commit or Rollback.
+//
+// After a call to Commit or Rollback, all operations on the
+// transaction fail with ErrTransactionFinished.
+type Tx struct {
+	db *DB
+
+	// ci is owned exclusively until Commit or Rollback, at which point
+	// it's returned with putConn.
+	ci  driver.Conn
+	txi driver.Tx
+
+	// cimu is held while somebody is using ci (between grabConn
+	// and releaseConn)
+	cimu sync.Mutex
+
+	// done transitions from false to true exactly once, on Commit
+	// or Rollback. once done, all operations fail with
+	// ErrTransactionFinished.
+	done bool
+}
+
+var ErrTransactionFinished = errors.New("sql: Transaction has already been committed or rolled back")
+
+func (tx *Tx) close() {
+	if tx.done {
+		panic("double close") // internal error
+	}
+	tx.done = true
+	tx.db.putConn(tx.ci)
+	tx.ci = nil
+	tx.txi = nil
+}
+
+func (tx *Tx) grabConn() (driver.Conn, error) {
+	if tx.done {
+		return nil, ErrTransactionFinished
+	}
+	tx.cimu.Lock()
+	return tx.ci, nil
+}
+
+func (tx *Tx) releaseConn() {
+	tx.cimu.Unlock()
+}
+
+// Commit commits the transaction.
+func (tx *Tx) Commit() error {
+	if tx.done {
+		return ErrTransactionFinished
+	}
+	defer tx.close()
+	return tx.txi.Commit()
+}
+
+// Rollback aborts the transaction.
+func (tx *Tx) Rollback() error {
+	if tx.done {
+		return ErrTransactionFinished
+	}
+	defer tx.close()
+	return tx.txi.Rollback()
+}
+
+// Prepare creates a prepared statement for use within a transaction.
+//
+// The returned statement operates within the transaction and can no longer
+// be used once the transaction has been committed or rolled back.
+//
+// To use an existing prepared statement on this transaction, see Tx.Stmt.
+func (tx *Tx) Prepare(query string) (*Stmt, error) {
+	// TODO(bradfitz): We could be more efficient here and either
+	// provide a method to take an existing Stmt (created on
+	// perhaps a different Conn), and re-create it on this Conn if
+	// necessary. Or, better: keep a map in DB of query string to
+	// Stmts, and have Stmt.Execute do the right thing and
+	// re-prepare if the Conn in use doesn't have that prepared
+	// statement.  But we'll want to avoid caching the statement
+	// in the case where we only call conn.Prepare implicitly
+	// (such as in db.Exec or tx.Exec), but the caller package
+	// can't be holding a reference to the returned statement.
+	// Perhaps just looking at the reference count (by noting
+	// Stmt.Close) would be enough. We might also want a finalizer
+	// on Stmt to drop the reference count.
+	ci, err := tx.grabConn()
+	if err != nil {
+		return nil, err
+	}
+	defer tx.releaseConn()
+
+	si, err := ci.Prepare(query)
+	if err != nil {
+		return nil, err
+	}
+
+	stmt := &Stmt{
+		db:    tx.db,
+		tx:    tx,
+		txsi:  si,
+		query: query,
+	}
+	return stmt, nil
+}
+
+// Stmt returns a transaction-specific prepared statement from
+// an existing statement.
+//
+// Example:
+//  updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?")
+//  ...
+//  tx, err := db.Begin()
+//  ...
+//  res, err := tx.Stmt(updateMoney).Exec(123.45, 98293203)
+func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
+	// TODO(bradfitz): optimize this. Currently this re-prepares
+	// each time.  This is fine for now to illustrate the API but
+	// we should really cache already-prepared statements
+	// per-Conn. See also the big comment in Tx.Prepare.
+
+	if tx.db != stmt.db {
+		return &Stmt{stickyErr: errors.New("sql: Tx.Stmt: statement from different database used")}
+	}
+	ci, err := tx.grabConn()
+	if err != nil {
+		return &Stmt{stickyErr: err}
+	}
+	defer tx.releaseConn()
+	si, err := ci.Prepare(stmt.query)
+	return &Stmt{
+		db:        tx.db,
+		tx:        tx,
+		txsi:      si,
+		query:     stmt.query,
+		stickyErr: err,
+	}
+}
+
+// Exec executes a query that doesn't return rows.
+// For example: an INSERT and UPDATE.
+func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
+	ci, err := tx.grabConn()
+	if err != nil {
+		return nil, err
+	}
+	defer tx.releaseConn()
+
+	if execer, ok := ci.(driver.Execer); ok {
+		resi, err := execer.Exec(query, args)
+		if err != nil {
+			return nil, err
+		}
+		return result{resi}, nil
+	}
+
+	sti, err := ci.Prepare(query)
+	if err != nil {
+		return nil, err
+	}
+	defer sti.Close()
+
+	sargs, err := subsetTypeArgs(args)
+	if err != nil {
+		return nil, err
+	}
+
+	resi, err := sti.Exec(sargs)
+	if err != nil {
+		return nil, err
+	}
+	return result{resi}, nil
+}
+
+// Query executes a query that returns rows, typically a SELECT.
+func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
+	if tx.done {
+		return nil, ErrTransactionFinished
+	}
+	stmt, err := tx.Prepare(query)
+	if err != nil {
+		return nil, err
+	}
+	rows, err := stmt.Query(args...)
+	if err == nil {
+		rows.closeStmt = stmt
+	}
+	return rows, err
+}
+
+// QueryRow executes a query that is expected to return at most one row.
+// QueryRow always return a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
+	rows, err := tx.Query(query, args...)
+	return &Row{rows: rows, err: err}
+}
+
+// connStmt is a prepared statement on a particular connection.
+type connStmt struct {
+	ci driver.Conn
+	si driver.Stmt
+}
+
+// Stmt is a prepared statement. Stmt is safe for concurrent use by multiple goroutines.
+type Stmt struct {
+	// Immutable:
+	db        *DB    // where we came from
+	query     string // that created the Stmt
+	stickyErr error  // if non-nil, this error is returned for all operations
+
+	// If in a transaction, else both nil:
+	tx   *Tx
+	txsi driver.Stmt
+
+	mu     sync.Mutex // protects the rest of the fields
+	closed bool
+
+	// css is a list of underlying driver statement interfaces
+	// that are valid on particular connections.  This is only
+	// used if tx == nil and one is found that has idle
+	// connections.  If tx != nil, txsi is always used.
+	css []connStmt
+}
+
+// Exec executes a prepared statement with the given arguments and
+// returns a Result summarizing the effect of the statement.
+func (s *Stmt) Exec(args ...interface{}) (Result, error) {
+	_, releaseConn, si, err := s.connStmt()
+	if err != nil {
+		return nil, err
+	}
+	defer releaseConn()
+
+	// -1 means the driver doesn't know how to count the number of
+	// placeholders, so we won't sanity check input here and instead let the
+	// driver deal with errors.
+	if want := si.NumInput(); want != -1 && len(args) != want {
+		return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(args))
+	}
+
+	// Convert args to subset types.
+	if cc, ok := si.(driver.ColumnConverter); ok {
+		for n, arg := range args {
+			// First, see if the value itself knows how to convert
+			// itself to a driver type.  For example, a NullString
+			// struct changing into a string or nil.
+			if svi, ok := arg.(driver.SubsetValuer); ok {
+				sv, err := svi.SubsetValue()
+				if err != nil {
+					return nil, fmt.Errorf("sql: argument index %d from SubsetValue: %v", n, err)
+				}
+				if !driver.IsParameterSubsetType(sv) {
+					return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from SubsetValue", n, sv)
+				}
+				arg = sv
+			}
+
+			// Second, ask the column to sanity check itself. For
+			// example, drivers might use this to make sure that
+			// an int64 values being inserted into a 16-bit
+			// integer field is in range (before getting
+			// truncated), or that a nil can't go into a NOT NULL
+			// column before going across the network to get the
+			// same error.
+			args[n], err = cc.ColumnConverter(n).ConvertValue(arg)
+			if err != nil {
+				return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
+			}
+			if !driver.IsParameterSubsetType(args[n]) {
+				return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
+					arg, args[n])
+			}
+		}
+	} else {
+		for n, arg := range args {
+			args[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+			if err != nil {
+				return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
+			}
+		}
+	}
+
+	resi, err := si.Exec(args)
+	if err != nil {
+		return nil, err
+	}
+	return result{resi}, nil
+}
+
+// connStmt returns a free driver connection on which to execute the
+// statement, a function to call to release the connection, and a
+// statement bound to that connection.
+func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(), si driver.Stmt, err error) {
+	if err = s.stickyErr; err != nil {
+		return
+	}
+	s.mu.Lock()
+	if s.closed {
+		s.mu.Unlock()
+		err = errors.New("sql: statement is closed")
+		return
+	}
+
+	// In a transaction, we always use the connection that the
+	// transaction was created on.
+	if s.tx != nil {
+		s.mu.Unlock()
+		ci, err = s.tx.grabConn() // blocks, waiting for the connection.
+		if err != nil {
+			return
+		}
+		releaseConn = func() { s.tx.releaseConn() }
+		return ci, releaseConn, s.txsi, nil
+	}
+
+	var cs connStmt
+	match := false
+	for _, v := range s.css {
+		// TODO(bradfitz): lazily clean up entries in this
+		// list with dead conns while enumerating
+		if _, match = s.db.connIfFree(cs.ci); match {
+			cs = v
+			break
+		}
+	}
+	s.mu.Unlock()
+
+	// Make a new conn if all are busy.
+	// TODO(bradfitz): or wait for one? make configurable later?
+	if !match {
+		ci, err := s.db.conn()
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		si, err := ci.Prepare(s.query)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+		s.mu.Lock()
+		cs = connStmt{ci, si}
+		s.css = append(s.css, cs)
+		s.mu.Unlock()
+	}
+
+	conn := cs.ci
+	releaseConn = func() { s.db.putConn(conn) }
+	return conn, releaseConn, cs.si, nil
+}
+
+// Query executes a prepared query statement with the given arguments
+// and returns the query results as a *Rows.
+func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
+	ci, releaseConn, si, err := s.connStmt()
+	if err != nil {
+		return nil, err
+	}
+
+	// -1 means the driver doesn't know how to count the number of
+	// placeholders, so we won't sanity check input here and instead let the
+	// driver deal with errors.
+	if want := si.NumInput(); want != -1 && len(args) != want {
+		return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", si.NumInput(), len(args))
+	}
+	sargs, err := subsetTypeArgs(args)
+	if err != nil {
+		return nil, err
+	}
+	rowsi, err := si.Query(sargs)
+	if err != nil {
+		s.db.putConn(ci)
+		return nil, err
+	}
+	// Note: ownership of ci passes to the *Rows, to be freed
+	// with releaseConn.
+	rows := &Rows{
+		db:          s.db,
+		ci:          ci,
+		releaseConn: releaseConn,
+		rowsi:       rowsi,
+	}
+	return rows, nil
+}
+
+// QueryRow executes a prepared query statement with the given arguments.
+// If an error occurs during the execution of the statement, that error will
+// be returned by a call to Scan on the returned *Row, which is always non-nil.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
+//
+// Example usage:
+//
+//  var name string
+//  err := nameByUseridStmt.QueryRow(id).Scan(&s)
+func (s *Stmt) QueryRow(args ...interface{}) *Row {
+	rows, err := s.Query(args...)
+	if err != nil {
+		return &Row{err: err}
+	}
+	return &Row{rows: rows}
+}
+
+// Close closes the statement.
+func (s *Stmt) Close() error {
+	if s.stickyErr != nil {
+		return s.stickyErr
+	}
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	if s.closed {
+		return nil
+	}
+	s.closed = true
+
+	if s.tx != nil {
+		s.txsi.Close()
+	} else {
+		for _, v := range s.css {
+			if ci, match := s.db.connIfFree(v.ci); match {
+				v.si.Close()
+				s.db.putConn(ci)
+			} else {
+				// TODO(bradfitz): care that we can't close
+				// this statement because the statement's
+				// connection is in use?
+			}
+		}
+	}
+	return nil
+}
+
+// Rows is the result of a query. Its cursor starts before the first row
+// of the result set. Use Next to advance through the rows:
+//
+//     rows, err := db.Query("SELECT ...")
+//     ...
+//     for rows.Next() {
+//         var id int
+//         var name string
+//         err = rows.Scan(&id, &name)
+//         ...
+//     }
+//     err = rows.Err() // get any error encountered during iteration
+//     ...
+type Rows struct {
+	db          *DB
+	ci          driver.Conn // owned; must call putconn when closed to release
+	releaseConn func()
+	rowsi       driver.Rows
+
+	closed    bool
+	lastcols  []interface{}
+	lasterr   error
+	closeStmt *Stmt // if non-nil, statement to Close on close
+}
+
+// Next prepares the next result row for reading with the Scan method.
+// It returns true on success, false if there is no next result row.
+// Every call to Scan, even the first one, must be preceded by a call
+// to Next.
+func (rs *Rows) Next() bool {
+	if rs.closed {
+		return false
+	}
+	if rs.lasterr != nil {
+		return false
+	}
+	if rs.lastcols == nil {
+		rs.lastcols = make([]interface{}, len(rs.rowsi.Columns()))
+	}
+	rs.lasterr = rs.rowsi.Next(rs.lastcols)
+	if rs.lasterr == io.EOF {
+		rs.Close()
+	}
+	return rs.lasterr == nil
+}
+
+// Err returns the error, if any, that was encountered during iteration.
+func (rs *Rows) Err() error {
+	if rs.lasterr == io.EOF {
+		return nil
+	}
+	return rs.lasterr
+}
+
+// Columns returns the column names.
+// Columns returns an error if the rows are closed, or if the rows
+// are from QueryRow and there was a deferred error.
+func (rs *Rows) Columns() ([]string, error) {
+	if rs.closed {
+		return nil, errors.New("sql: Rows are closed")
+	}
+	if rs.rowsi == nil {
+		return nil, errors.New("sql: no Rows available")
+	}
+	return rs.rowsi.Columns(), nil
+}
+
+// Scan copies the columns in the current row into the values pointed
+// at by dest.
+//
+// If an argument has type *[]byte, Scan saves in that argument a copy
+// of the corresponding data. The copy is owned by the caller and can
+// be modified and held indefinitely. The copy can be avoided by using
+// an argument of type *RawBytes instead; see the documentation for
+// RawBytes for restrictions on its use.
+func (rs *Rows) Scan(dest ...interface{}) error {
+	if rs.closed {
+		return errors.New("sql: Rows closed")
+	}
+	if rs.lasterr != nil {
+		return rs.lasterr
+	}
+	if rs.lastcols == nil {
+		return errors.New("sql: Scan called without calling Next")
+	}
+	if len(dest) != len(rs.lastcols) {
+		return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
+	}
+	for i, sv := range rs.lastcols {
+		err := convertAssign(dest[i], sv)
+		if err != nil {
+			return fmt.Errorf("sql: Scan error on column index %d: %v", i, err)
+		}
+	}
+	for _, dp := range dest {
+		b, ok := dp.(*[]byte)
+		if !ok {
+			continue
+		}
+		if *b == nil {
+			// If the []byte is now nil (for a NULL value),
+			// don't fall through to below which would
+			// turn it into a non-nil 0-length byte slice
+			continue
+		}
+		if _, ok = dp.(*RawBytes); ok {
+			continue
+		}
+		clone := make([]byte, len(*b))
+		copy(clone, *b)
+		*b = clone
+	}
+	return nil
+}
+
+// Close closes the Rows, preventing further enumeration. If the
+// end is encountered, the Rows are closed automatically. Close
+// is idempotent.
+func (rs *Rows) Close() error {
+	if rs.closed {
+		return nil
+	}
+	rs.closed = true
+	err := rs.rowsi.Close()
+	rs.releaseConn()
+	if rs.closeStmt != nil {
+		rs.closeStmt.Close()
+	}
+	return err
+}
+
+// Row is the result of calling QueryRow to select a single row.
+type Row struct {
+	// One of these two will be non-nil:
+	err  error // deferred error for easy chaining
+	rows *Rows
+}
+
+// Scan copies the columns from the matched row into the values
+// pointed at by dest.  If more than one row matches the query,
+// Scan uses the first row and discards the rest.  If no row matches
+// the query, Scan returns ErrNoRows.
+func (r *Row) Scan(dest ...interface{}) error {
+	if r.err != nil {
+		return r.err
+	}
+
+	// TODO(bradfitz): for now we need to defensively clone all
+	// []byte that the driver returned (not permitting 
+	// *RawBytes in Rows.Scan), since we're about to close
+	// the Rows in our defer, when we return from this function.
+	// the contract with the driver.Next(...) interface is that it
+	// can return slices into read-only temporary memory that's
+	// only valid until the next Scan/Close.  But the TODO is that
+	// for a lot of drivers, this copy will be unnecessary.  We
+	// should provide an optional interface for drivers to
+	// implement to say, "don't worry, the []bytes that I return
+	// from Next will not be modified again." (for instance, if
+	// they were obtained from the network anyway) But for now we
+	// don't care.
+	for _, dp := range dest {
+		if _, ok := dp.(*RawBytes); ok {
+			return errors.New("sql: RawBytes isn't allowed on Row.Scan")
+		}
+	}
+
+	defer r.rows.Close()
+	if !r.rows.Next() {
+		return ErrNoRows
+	}
+	err := r.rows.Scan(dest...)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// A Result summarizes an executed SQL command.
+type Result interface {
+	LastInsertId() (int64, error)
+	RowsAffected() (int64, error)
+}
+
+type result struct {
+	driver.Result
+}
diff --git a/src/pkg/database/sql/sql_test.go b/src/pkg/database/sql/sql_test.go
new file mode 100644
index 0000000..c5cadad
--- /dev/null
+++ b/src/pkg/database/sql/sql_test.go
@@ -0,0 +1,519 @@
+// Copyright 2011 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 sql
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+)
+
+const fakeDBName = "foo"
+
+var chrisBirthday = time.Unix(123456789, 0)
+
+func newTestDB(t *testing.T, name string) *DB {
+	db, err := Open("test", fakeDBName)
+	if err != nil {
+		t.Fatalf("Open: %v", err)
+	}
+	if _, err := db.Exec("WIPE"); err != nil {
+		t.Fatalf("exec wipe: %v", err)
+	}
+	if name == "people" {
+		exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime")
+		exec(t, db, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1)
+		exec(t, db, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2)
+		exec(t, db, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
+	}
+	return db
+}
+
+func exec(t *testing.T, db *DB, query string, args ...interface{}) {
+	_, err := db.Exec(query, args...)
+	if err != nil {
+		t.Fatalf("Exec of %q: %v", query, err)
+	}
+}
+
+func closeDB(t *testing.T, db *DB) {
+	err := db.Close()
+	if err != nil {
+		t.Fatalf("error closing DB: %v", err)
+	}
+}
+
+func TestQuery(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	rows, err := db.Query("SELECT|people|age,name|")
+	if err != nil {
+		t.Fatalf("Query: %v", err)
+	}
+	type row struct {
+		age  int
+		name string
+	}
+	got := []row{}
+	for rows.Next() {
+		var r row
+		err = rows.Scan(&r.age, &r.name)
+		if err != nil {
+			t.Fatalf("Scan: %v", err)
+		}
+		got = append(got, r)
+	}
+	err = rows.Err()
+	if err != nil {
+		t.Fatalf("Err: %v", err)
+	}
+	want := []row{
+		{age: 1, name: "Alice"},
+		{age: 2, name: "Bob"},
+		{age: 3, name: "Chris"},
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
+	}
+
+	// And verify that the final rows.Next() call, which hit EOF,
+	// also closed the rows connection.
+	if n := len(db.freeConn); n != 1 {
+		t.Errorf("free conns after query hitting EOF = %d; want 1", n)
+	}
+}
+
+func TestByteOwnership(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	rows, err := db.Query("SELECT|people|name,photo|")
+	if err != nil {
+		t.Fatalf("Query: %v", err)
+	}
+	type row struct {
+		name  []byte
+		photo RawBytes
+	}
+	got := []row{}
+	for rows.Next() {
+		var r row
+		err = rows.Scan(&r.name, &r.photo)
+		if err != nil {
+			t.Fatalf("Scan: %v", err)
+		}
+		got = append(got, r)
+	}
+	corruptMemory := []byte("\xffPHOTO")
+	want := []row{
+		{name: []byte("Alice"), photo: corruptMemory},
+		{name: []byte("Bob"), photo: corruptMemory},
+		{name: []byte("Chris"), photo: corruptMemory},
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
+	}
+
+	var photo RawBytes
+	err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo)
+	if err == nil {
+		t.Error("want error scanning into RawBytes from QueryRow")
+	}
+}
+
+func TestRowsColumns(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	rows, err := db.Query("SELECT|people|age,name|")
+	if err != nil {
+		t.Fatalf("Query: %v", err)
+	}
+	cols, err := rows.Columns()
+	if err != nil {
+		t.Fatalf("Columns: %v", err)
+	}
+	want := []string{"age", "name"}
+	if !reflect.DeepEqual(cols, want) {
+		t.Errorf("got %#v; want %#v", cols, want)
+	}
+}
+
+func TestQueryRow(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	var name string
+	var age int
+	var birthday time.Time
+
+	err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age)
+	if err == nil || !strings.Contains(err.Error(), "expected 2 destination arguments") {
+		t.Errorf("expected error from wrong number of arguments; actually got: %v", err)
+	}
+
+	err = db.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday)
+	if err != nil || !birthday.Equal(chrisBirthday) {
+		t.Errorf("chris birthday = %v, err = %v; want %v", birthday, err, chrisBirthday)
+	}
+
+	err = db.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age, &name)
+	if err != nil {
+		t.Fatalf("age QueryRow+Scan: %v", err)
+	}
+	if name != "Bob" {
+		t.Errorf("expected name Bob, got %q", name)
+	}
+	if age != 2 {
+		t.Errorf("expected age 2, got %d", age)
+	}
+
+	err = db.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age, &name)
+	if err != nil {
+		t.Fatalf("name QueryRow+Scan: %v", err)
+	}
+	if name != "Alice" {
+		t.Errorf("expected name Alice, got %q", name)
+	}
+	if age != 1 {
+		t.Errorf("expected age 1, got %d", age)
+	}
+
+	var photo []byte
+	err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo)
+	if err != nil {
+		t.Fatalf("photo QueryRow+Scan: %v", err)
+	}
+	want := []byte("APHOTO")
+	if !reflect.DeepEqual(photo, want) {
+		t.Errorf("photo = %q; want %q", photo, want)
+	}
+}
+
+func TestStatementErrorAfterClose(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	stmt, err := db.Prepare("SELECT|people|age|name=?")
+	if err != nil {
+		t.Fatalf("Prepare: %v", err)
+	}
+	err = stmt.Close()
+	if err != nil {
+		t.Fatalf("Close: %v", err)
+	}
+	var name string
+	err = stmt.QueryRow("foo").Scan(&name)
+	if err == nil {
+		t.Errorf("expected error from QueryRow.Scan after Stmt.Close")
+	}
+}
+
+func TestStatementQueryRow(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	stmt, err := db.Prepare("SELECT|people|age|name=?")
+	if err != nil {
+		t.Fatalf("Prepare: %v", err)
+	}
+	var age int
+	for n, tt := range []struct {
+		name string
+		want int
+	}{
+		{"Alice", 1},
+		{"Bob", 2},
+		{"Chris", 3},
+	} {
+		if err := stmt.QueryRow(tt.name).Scan(&age); err != nil {
+			t.Errorf("%d: on %q, QueryRow/Scan: %v", n, tt.name, err)
+		} else if age != tt.want {
+			t.Errorf("%d: age=%d, want %d", n, age, tt.want)
+		}
+	}
+
+}
+
+// just a test of fakedb itself
+func TestBogusPreboundParameters(t *testing.T) {
+	db := newTestDB(t, "foo")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	_, err := db.Prepare("INSERT|t1|name=?,age=bogusconversion")
+	if err == nil {
+		t.Fatalf("expected error")
+	}
+	if err.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` {
+		t.Errorf("unexpected error: %v", err)
+	}
+}
+
+func TestExec(t *testing.T) {
+	db := newTestDB(t, "foo")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+	if err != nil {
+		t.Errorf("Stmt, err = %v, %v", stmt, err)
+	}
+
+	type execTest struct {
+		args    []interface{}
+		wantErr string
+	}
+	execTests := []execTest{
+		// Okay:
+		{[]interface{}{"Brad", 31}, ""},
+		{[]interface{}{"Brad", int64(31)}, ""},
+		{[]interface{}{"Bob", "32"}, ""},
+		{[]interface{}{7, 9}, ""},
+
+		// Invalid conversions:
+		{[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting Exec argument #1's type: sql/driver: value 4294967295 overflows int32"},
+		{[]interface{}{"Brad", "strconv fail"}, "sql: converting Exec argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
+
+		// Wrong number of args:
+		{[]interface{}{}, "sql: expected 2 arguments, got 0"},
+		{[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"},
+	}
+	for n, et := range execTests {
+		_, err := stmt.Exec(et.args...)
+		errStr := ""
+		if err != nil {
+			errStr = err.Error()
+		}
+		if errStr != et.wantErr {
+			t.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q",
+				n, et.args, errStr, et.wantErr)
+		}
+	}
+}
+
+func TestTxStmt(t *testing.T) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+	if err != nil {
+		t.Fatalf("Stmt, err = %v, %v", stmt, err)
+	}
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatalf("Begin = %v", err)
+	}
+	_, err = tx.Stmt(stmt).Exec("Bobby", 7)
+	if err != nil {
+		t.Fatalf("Exec = %v", err)
+	}
+	err = tx.Commit()
+	if err != nil {
+		t.Fatalf("Commit = %v", err)
+	}
+}
+
+// Issue: http://golang.org/issue/2784
+// This test didn't fail before because we got luckly with the fakedb driver.
+// It was failing, and now not, in github.com/bradfitz/go-sql-test
+func TestTxQuery(t *testing.T) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	exec(t, db, "INSERT|t1|name=Alice")
+
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer tx.Rollback()
+
+	r, err := tx.Query("SELECT|t1|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !r.Next() {
+		if r.Err() != nil {
+			t.Fatal(r.Err())
+		}
+		t.Fatal("expected one row")
+	}
+
+	var x string
+	err = r.Scan(&x)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// Tests fix for issue 2542, that we release a lock when querying on
+// a closed connection.
+func TestIssue2542Deadlock(t *testing.T) {
+	db := newTestDB(t, "people")
+	closeDB(t, db)
+	for i := 0; i < 2; i++ {
+		_, err := db.Query("SELECT|people|age,name|")
+		if err == nil {
+			t.Fatalf("expected error")
+		}
+	}
+}
+
+// Tests fix for issue 2788, that we bind nil to a []byte if the
+// value in the column is sql null
+func TestNullByteSlice(t *testing.T) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, "CREATE|t|id=int32,name=nullstring")
+	exec(t, db, "INSERT|t|id=10,name=?", nil)
+
+	var name []byte
+
+	err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if name != nil {
+		t.Fatalf("name []byte should be nil for null column value, got: %#v", name)
+	}
+
+	exec(t, db, "INSERT|t|id=11,name=?", "bob")
+	err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(name) != "bob" {
+		t.Fatalf("name []byte should be bob, got: %q", string(name))
+	}
+}
+
+func TestQueryRowClosingStmt(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	var name string
+	var age int
+	err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age, &name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(db.freeConn) != 1 {
+		t.Fatalf("expected 1 free conn")
+	}
+	fakeConn := db.freeConn[0].(*fakeConn)
+	if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed {
+		t.Errorf("statement close mismatch: made %d, closed %d", made, closed)
+	}
+}
+
+type nullTestRow struct {
+	nullParam    interface{}
+	notNullParam interface{}
+	scanNullVal  interface{}
+}
+
+type nullTestSpec struct {
+	nullType    string
+	notNullType string
+	rows        [6]nullTestRow
+}
+
+func TestNullStringParam(t *testing.T) {
+	spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
+		nullTestRow{NullString{"aqua", true}, "", NullString{"aqua", true}},
+		nullTestRow{NullString{"brown", false}, "", NullString{"", false}},
+		nullTestRow{"chartreuse", "", NullString{"chartreuse", true}},
+		nullTestRow{NullString{"darkred", true}, "", NullString{"darkred", true}},
+		nullTestRow{NullString{"eel", false}, "", NullString{"", false}},
+		nullTestRow{"foo", NullString{"black", false}, nil},
+	}}
+	nullTestRun(t, spec)
+}
+
+func TestNullInt64Param(t *testing.T) {
+	spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{
+		nullTestRow{NullInt64{31, true}, 1, NullInt64{31, true}},
+		nullTestRow{NullInt64{-22, false}, 1, NullInt64{0, false}},
+		nullTestRow{22, 1, NullInt64{22, true}},
+		nullTestRow{NullInt64{33, true}, 1, NullInt64{33, true}},
+		nullTestRow{NullInt64{222, false}, 1, NullInt64{0, false}},
+		nullTestRow{0, NullInt64{31, false}, nil},
+	}}
+	nullTestRun(t, spec)
+}
+
+func TestNullFloat64Param(t *testing.T) {
+	spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{
+		nullTestRow{NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}},
+		nullTestRow{NullFloat64{13.1, false}, 1, NullFloat64{0, false}},
+		nullTestRow{-22.9, 1, NullFloat64{-22.9, true}},
+		nullTestRow{NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}},
+		nullTestRow{NullFloat64{222, false}, 1, NullFloat64{0, false}},
+		nullTestRow{10, NullFloat64{31.2, false}, nil},
+	}}
+	nullTestRun(t, spec)
+}
+
+func TestNullBoolParam(t *testing.T) {
+	spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{
+		nullTestRow{NullBool{false, true}, true, NullBool{false, true}},
+		nullTestRow{NullBool{true, false}, false, NullBool{false, false}},
+		nullTestRow{true, true, NullBool{true, true}},
+		nullTestRow{NullBool{true, true}, false, NullBool{true, true}},
+		nullTestRow{NullBool{true, false}, true, NullBool{false, false}},
+		nullTestRow{true, NullBool{true, false}, nil},
+	}}
+	nullTestRun(t, spec)
+}
+
+func nullTestRun(t *testing.T, spec nullTestSpec) {
+	db := newTestDB(t, "")
+	defer closeDB(t, db)
+	exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType))
+
+	// Inserts with db.Exec:
+	exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam)
+	exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam)
+
+	// Inserts with a prepared statement:
+	stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?")
+	if err != nil {
+		t.Fatalf("prepare: %v", err)
+	}
+	if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil {
+		t.Errorf("exec insert chris: %v", err)
+	}
+	if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil {
+		t.Errorf("exec insert dave: %v", err)
+	}
+	if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil {
+		t.Errorf("exec insert eleanor: %v", err)
+	}
+
+	// Can't put null val into non-null col
+	if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil {
+		t.Errorf("expected error inserting nil val with prepared statement Exec")
+	}
+
+	_, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil)
+	if err == nil {
+		// TODO: this test fails, but it's just because
+		// fakeConn implements the optional Execer interface,
+		// so arguably this is the correct behavior.  But
+		// maybe I should flesh out the fakeConn.Exec
+		// implementation so this properly fails.
+		// t.Errorf("expected error inserting nil name with Exec")
+	}
+
+	paramtype := reflect.TypeOf(spec.rows[0].nullParam)
+	bindVal := reflect.New(paramtype).Interface()
+
+	for i := 0; i < 5; i++ {
+		id := i + 1
+		if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil {
+			t.Errorf("id=%d Scan: %v", id, err)
+		}
+		bindValDeref := reflect.ValueOf(bindVal).Elem().Interface()
+		if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) {
+			t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal)
+		}
+	}
+}
diff --git a/src/pkg/debug/dwarf/buf.go b/src/pkg/debug/dwarf/buf.go
index 2d29ceb..6dc28d2 100644
--- a/src/pkg/debug/dwarf/buf.go
+++ b/src/pkg/debug/dwarf/buf.go
@@ -8,7 +8,6 @@ package dwarf
 
 import (
 	"encoding/binary"
-	"os"
 	"strconv"
 )
 
@@ -20,7 +19,7 @@ type buf struct {
 	off      Offset
 	data     []byte
 	addrsize int
-	err      os.Error
+	err      error
 }
 
 func makeBuf(d *Data, name string, off Offset, data []byte, addrsize int) buf {
@@ -146,9 +145,9 @@ func (b *buf) error(s string) {
 type DecodeError struct {
 	Name   string
 	Offset Offset
-	Error  string
+	Err    string
 }
 
-func (e DecodeError) String() string {
-	return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.Itob64(int64(e.Offset), 16) + ": " + e.Error
+func (e DecodeError) Error() string {
+	return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err
 }
diff --git a/src/pkg/debug/dwarf/const.go b/src/pkg/debug/dwarf/const.go
index 1a3fec1..918b153 100644
--- a/src/pkg/debug/dwarf/const.go
+++ b/src/pkg/debug/dwarf/const.go
@@ -178,7 +178,7 @@ func (a Attr) GoString() string {
 			return "dwarf.Attr" + s
 		}
 	}
-	return "dwarf.Attr(" + strconv.Itoa64(int64(a)) + ")"
+	return "dwarf.Attr(" + strconv.FormatInt(int64(a), 10) + ")"
 }
 
 // A format is a DWARF data encoding format.
@@ -347,7 +347,7 @@ func (t Tag) GoString() string {
 			return "dwarf.Tag" + s
 		}
 	}
-	return "dwarf.Tag(" + strconv.Itoa64(int64(t)) + ")"
+	return "dwarf.Tag(" + strconv.FormatInt(int64(t), 10) + ")"
 }
 
 // Location expression operators.
diff --git a/src/pkg/debug/dwarf/entry.go b/src/pkg/debug/dwarf/entry.go
index 549e5c2..2885d8f 100644
--- a/src/pkg/debug/dwarf/entry.go
+++ b/src/pkg/debug/dwarf/entry.go
@@ -10,7 +10,7 @@
 
 package dwarf
 
-import "os"
+import "errors"
 
 // a single entry's description: a sequence of attributes
 type abbrev struct {
@@ -29,7 +29,7 @@ type abbrevTable map[uint32]abbrev
 
 // ParseAbbrev returns the abbreviation table that starts at byte off
 // in the .debug_abbrev section.
-func (d *Data) parseAbbrev(off uint32) (abbrevTable, os.Error) {
+func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) {
 	if m, ok := d.abbrevCache[off]; ok {
 		return m, nil
 	}
@@ -232,7 +232,7 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
 type Reader struct {
 	b            buf
 	d            *Data
-	err          os.Error
+	err          error
 	unit         int
 	lastChildren bool   // .Children of last entry returned by Next
 	lastSibling  Offset // .Val(AttrSibling) of last entry returned by Next
@@ -273,7 +273,7 @@ func (r *Reader) Seek(off Offset) {
 			return
 		}
 	}
-	r.err = os.NewError("offset out of range")
+	r.err = errors.New("offset out of range")
 }
 
 // maybeNextUnit advances to the next unit if this one is finished.
@@ -289,7 +289,7 @@ func (r *Reader) maybeNextUnit() {
 // It returns nil, nil when it reaches the end of the section.
 // It returns an error if the current offset is invalid or the data at the
 // offset cannot be decoded as a valid Entry.
-func (r *Reader) Next() (*Entry, os.Error) {
+func (r *Reader) Next() (*Entry, error) {
 	if r.err != nil {
 		return nil, r.err
 	}
diff --git a/src/pkg/debug/dwarf/open.go b/src/pkg/debug/dwarf/open.go
index d9525f7..9543297 100644
--- a/src/pkg/debug/dwarf/open.go
+++ b/src/pkg/debug/dwarf/open.go
@@ -7,10 +7,7 @@
 // http://dwarfstd.org/doc/dwarf-2.0.0.pdf
 package dwarf
 
-import (
-	"encoding/binary"
-	"os"
-)
+import "encoding/binary"
 
 // Data represents the DWARF debugging information
 // loaded from an executable file (for example, an ELF or Mach-O executable).
@@ -40,7 +37,7 @@ type Data struct {
 // The []byte arguments are the data from the corresponding debug section
 // in the object file; for example, for an ELF object, abbrev is the contents of
 // the ".debug_abbrev" section.
-func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, os.Error) {
+func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Data, error) {
 	d := &Data{
 		abbrev:      abbrev,
 		aranges:     aranges,
diff --git a/src/pkg/debug/dwarf/type.go b/src/pkg/debug/dwarf/type.go
index f35365e..9be6665 100644
--- a/src/pkg/debug/dwarf/type.go
+++ b/src/pkg/debug/dwarf/type.go
@@ -8,10 +8,7 @@
 
 package dwarf
 
-import (
-	"os"
-	"strconv"
-)
+import "strconv"
 
 // A Type conventionally represents a pointer to any of the
 // specific Type structures (CharType, StructType, etc.).
@@ -113,7 +110,7 @@ type ArrayType struct {
 }
 
 func (t *ArrayType) String() string {
-	return "[" + strconv.Itoa64(t.Count) + "]" + t.Type.String()
+	return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String()
 }
 
 func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() }
@@ -174,10 +171,10 @@ func (t *StructType) Defn() string {
 			s += "; "
 		}
 		s += f.Name + " " + f.Type.String()
-		s += "@" + strconv.Itoa64(f.ByteOffset)
+		s += "@" + strconv.FormatInt(f.ByteOffset, 10)
 		if f.BitSize > 0 {
-			s += " : " + strconv.Itoa64(f.BitSize)
-			s += "@" + strconv.Itoa64(f.BitOffset)
+			s += " : " + strconv.FormatInt(f.BitSize, 10)
+			s += "@" + strconv.FormatInt(f.BitOffset, 10)
 		}
 	}
 	s += "}"
@@ -209,7 +206,7 @@ func (t *EnumType) String() string {
 		if i > 0 {
 			s += "; "
 		}
-		s += v.Name + "=" + strconv.Itoa64(v.Val)
+		s += v.Name + "=" + strconv.FormatInt(v.Val, 10)
 	}
 	s += "}"
 	return s
@@ -254,7 +251,7 @@ func (t *TypedefType) String() string { return t.Name }
 
 func (t *TypedefType) Size() int64 { return t.Type.Size() }
 
-func (d *Data) Type(off Offset) (Type, os.Error) {
+func (d *Data) Type(off Offset) (Type, error) {
 	if t, ok := d.typeCache[off]; ok {
 		return t, nil
 	}
@@ -579,6 +576,6 @@ Error:
 	// If the parse fails, take the type out of the cache
 	// so that the next call with this offset doesn't hit
 	// the cache and return success.
-	d.typeCache[off] = nil, false
+	delete(d.typeCache, off)
 	return nil, err
 }
diff --git a/src/pkg/debug/dwarf/unit.go b/src/pkg/debug/dwarf/unit.go
index 02cb363..c10d75d 100644
--- a/src/pkg/debug/dwarf/unit.go
+++ b/src/pkg/debug/dwarf/unit.go
@@ -4,10 +4,7 @@
 
 package dwarf
 
-import (
-	"os"
-	"strconv"
-)
+import "strconv"
 
 // DWARF debug info is split into a sequence of compilation units.
 // Each unit has its own abbreviation table and address size.
@@ -20,7 +17,7 @@ type unit struct {
 	addrsize int
 }
 
-func (d *Data) parseUnits() ([]unit, os.Error) {
+func (d *Data) parseUnits() ([]unit, error) {
 	// Count units.
 	nunit := 0
 	b := makeBuf(d, "info", 0, d.info, 0)
diff --git a/src/pkg/debug/elf/elf.go b/src/pkg/debug/elf/elf.go
index c71b230..03e42b0 100644
--- a/src/pkg/debug/elf/elf.go
+++ b/src/pkg/debug/elf/elf.go
@@ -1490,11 +1490,11 @@ func stringName(i uint32, names []intName, goSyntax bool) string {
 			if goSyntax {
 				s = "elf." + s
 			}
-			return s + "+" + strconv.Uitoa64(uint64(i-n.i))
+			return s + "+" + strconv.FormatUint(uint64(i-n.i), 10)
 		}
 	}
 
-	return strconv.Uitoa64(uint64(i))
+	return strconv.FormatUint(uint64(i), 10)
 }
 
 func flagName(i uint32, names []intName, goSyntax bool) string {
@@ -1512,10 +1512,10 @@ func flagName(i uint32, names []intName, goSyntax bool) string {
 		}
 	}
 	if len(s) == 0 {
-		return "0x" + strconv.Uitob64(uint64(i), 16)
+		return "0x" + strconv.FormatUint(uint64(i), 16)
 	}
 	if i != 0 {
-		s += "+0x" + strconv.Uitob64(uint64(i), 16)
+		s += "+0x" + strconv.FormatUint(uint64(i), 16)
 	}
 	return s
 }
diff --git a/src/pkg/debug/elf/file.go b/src/pkg/debug/elf/file.go
index a0ddb1f..184ca83 100644
--- a/src/pkg/debug/elf/file.go
+++ b/src/pkg/debug/elf/file.go
@@ -9,6 +9,7 @@ import (
 	"bytes"
 	"debug/dwarf"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"io"
 	"os"
@@ -71,7 +72,7 @@ type Section struct {
 }
 
 // Data reads and returns the contents of the ELF section.
-func (s *Section) Data() ([]byte, os.Error) {
+func (s *Section) Data() ([]byte, error) {
 	dat := make([]byte, s.sr.Size())
 	n, err := s.sr.ReadAt(dat, 0)
 	return dat[0:n], err
@@ -79,9 +80,9 @@ func (s *Section) Data() ([]byte, os.Error) {
 
 // stringTable reads and returns the string table given by the
 // specified link value.
-func (f *File) stringTable(link uint32) ([]byte, os.Error) {
+func (f *File) stringTable(link uint32) ([]byte, error) {
 	if link <= 0 || link >= uint32(len(f.Sections)) {
-		return nil, os.NewError("section has invalid string table link")
+		return nil, errors.New("section has invalid string table link")
 	}
 	return f.Sections[link].Data()
 }
@@ -136,7 +137,7 @@ type FormatError struct {
 	val interface{}
 }
 
-func (e *FormatError) String() string {
+func (e *FormatError) Error() string {
 	msg := e.msg
 	if e.val != nil {
 		msg += fmt.Sprintf(" '%v' ", e.val)
@@ -146,7 +147,7 @@ func (e *FormatError) String() string {
 }
 
 // Open opens the named file using os.Open and prepares it for use as an ELF binary.
-func Open(name string) (*File, os.Error) {
+func Open(name string) (*File, error) {
 	f, err := os.Open(name)
 	if err != nil {
 		return nil, err
@@ -163,8 +164,8 @@ func Open(name string) (*File, os.Error) {
 // Close closes the File.
 // If the File was created using NewFile directly instead of Open,
 // Close has no effect.
-func (f *File) Close() os.Error {
-	var err os.Error
+func (f *File) Close() error {
+	var err error
 	if f.closer != nil {
 		err = f.closer.Close()
 		f.closer = nil
@@ -185,7 +186,7 @@ func (f *File) SectionByType(typ SectionType) *Section {
 
 // NewFile creates a new File for accessing an ELF binary in an underlying reader.
 // The ELF binary is expected to start at position 0 in the ReaderAt.
-func NewFile(r io.ReaderAt) (*File, os.Error) {
+func NewFile(r io.ReaderAt) (*File, error) {
 	sr := io.NewSectionReader(r, 0, 1<<63-1)
 	// Read and decode ELF identifier
 	var ident [16]uint8
@@ -381,7 +382,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
 
 // getSymbols returns a slice of Symbols from parsing the symbol table
 // with the given type, along with the associated string table.
-func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, os.Error) {
+func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) {
 	switch f.Class {
 	case ELFCLASS64:
 		return f.getSymbols64(typ)
@@ -390,27 +391,27 @@ func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, os.Error) {
 		return f.getSymbols32(typ)
 	}
 
-	return nil, nil, os.NewError("not implemented")
+	return nil, nil, errors.New("not implemented")
 }
 
-func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, os.Error) {
+func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
 	symtabSection := f.SectionByType(typ)
 	if symtabSection == nil {
-		return nil, nil, os.NewError("no symbol section")
+		return nil, nil, errors.New("no symbol section")
 	}
 
 	data, err := symtabSection.Data()
 	if err != nil {
-		return nil, nil, os.NewError("cannot load symbol section")
+		return nil, nil, errors.New("cannot load symbol section")
 	}
 	symtab := bytes.NewBuffer(data)
 	if symtab.Len()%Sym32Size != 0 {
-		return nil, nil, os.NewError("length of symbol section is not a multiple of SymSize")
+		return nil, nil, errors.New("length of symbol section is not a multiple of SymSize")
 	}
 
 	strdata, err := f.stringTable(symtabSection.Link)
 	if err != nil {
-		return nil, nil, os.NewError("cannot load string table section")
+		return nil, nil, errors.New("cannot load string table section")
 	}
 
 	// The first entry is all zeros.
@@ -436,24 +437,24 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, os.Error) {
 	return symbols, strdata, nil
 }
 
-func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, os.Error) {
+func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
 	symtabSection := f.SectionByType(typ)
 	if symtabSection == nil {
-		return nil, nil, os.NewError("no symbol section")
+		return nil, nil, errors.New("no symbol section")
 	}
 
 	data, err := symtabSection.Data()
 	if err != nil {
-		return nil, nil, os.NewError("cannot load symbol section")
+		return nil, nil, errors.New("cannot load symbol section")
 	}
 	symtab := bytes.NewBuffer(data)
 	if symtab.Len()%Sym64Size != 0 {
-		return nil, nil, os.NewError("length of symbol section is not a multiple of Sym64Size")
+		return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size")
 	}
 
 	strdata, err := f.stringTable(symtabSection.Link)
 	if err != nil {
-		return nil, nil, os.NewError("cannot load string table section")
+		return nil, nil, errors.New("cannot load string table section")
 	}
 
 	// The first entry is all zeros.
@@ -506,17 +507,17 @@ func (f *File) Section(name string) *Section {
 
 // applyRelocations applies relocations to dst. rels is a relocations section
 // in RELA format.
-func (f *File) applyRelocations(dst []byte, rels []byte) os.Error {
+func (f *File) applyRelocations(dst []byte, rels []byte) error {
 	if f.Class == ELFCLASS64 && f.Machine == EM_X86_64 {
 		return f.applyRelocationsAMD64(dst, rels)
 	}
 
-	return os.NewError("not implemented")
+	return errors.New("not implemented")
 }
 
-func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) os.Error {
+func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
 	if len(rels)%Sym64Size != 0 {
-		return os.NewError("length of relocation section is not a multiple of Sym64Size")
+		return errors.New("length of relocation section is not a multiple of Sym64Size")
 	}
 
 	symbols, _, err := f.getSymbols(SHT_SYMTAB)
@@ -558,7 +559,7 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) os.Error {
 	return nil
 }
 
-func (f *File) DWARF() (*dwarf.Data, os.Error) {
+func (f *File) DWARF() (*dwarf.Data, error) {
 	// There are many other DWARF sections, but these
 	// are the required ones, and the debug/dwarf package
 	// does not use the others, so don't bother loading them.
@@ -596,7 +597,7 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
 }
 
 // Symbols returns the symbol table for f.
-func (f *File) Symbols() ([]Symbol, os.Error) {
+func (f *File) Symbols() ([]Symbol, error) {
 	sym, _, err := f.getSymbols(SHT_SYMTAB)
 	return sym, err
 }
@@ -611,7 +612,7 @@ type ImportedSymbol struct {
 // referred to by the binary f that are expected to be
 // satisfied by other libraries at dynamic load time.
 // It does not return weak symbols.
-func (f *File) ImportedSymbols() ([]ImportedSymbol, os.Error) {
+func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
 	sym, str, err := f.getSymbols(SHT_DYNSYM)
 	if err != nil {
 		return nil, err
@@ -721,7 +722,7 @@ func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
 // ImportedLibraries returns the names of all libraries
 // referred to by the binary f that are expected to be
 // linked with the binary at dynamic link time.
-func (f *File) ImportedLibraries() ([]string, os.Error) {
+func (f *File) ImportedLibraries() ([]string, error) {
 	ds := f.SectionByType(SHT_DYNAMIC)
 	if ds == nil {
 		// not dynamic, so no libraries
diff --git a/src/pkg/debug/gosym/pclinetest.h b/src/pkg/debug/gosym/pclinetest.h
index a6c40e7..156c0b8 100644
--- a/src/pkg/debug/gosym/pclinetest.h
+++ b/src/pkg/debug/gosym/pclinetest.h
@@ -1,3 +1,5 @@
+// +build ignore
+
 // Empty include file to generate z symbols
 
 
diff --git a/src/pkg/debug/gosym/pclinetest.s b/src/pkg/debug/gosym/pclinetest.s
index 6305435..c1d4818 100644
--- a/src/pkg/debug/gosym/pclinetest.s
+++ b/src/pkg/debug/gosym/pclinetest.s
@@ -1,3 +1,5 @@
+// +build ignore
+
 TEXT linefrompc(SB),7,$0	// Each byte stores its line delta
 BYTE $2;
 BYTE $1;
diff --git a/src/pkg/debug/gosym/pclntab_test.go b/src/pkg/debug/gosym/pclntab_test.go
index c83e64e..b90181b 100644
--- a/src/pkg/debug/gosym/pclntab_test.go
+++ b/src/pkg/debug/gosym/pclntab_test.go
@@ -7,13 +7,14 @@ package gosym
 import (
 	"debug/elf"
 	"os"
+	"runtime"
 	"testing"
-	"syscall"
 )
 
 func dotest() bool {
 	// For now, only works on ELF platforms.
-	return syscall.OS == "linux" && os.Getenv("GOARCH") == "amd64"
+	// TODO: convert to work with new go tool
+	return false && runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
 }
 
 func getTable(t *testing.T) *Table {
diff --git a/src/pkg/debug/gosym/symtab.go b/src/pkg/debug/gosym/symtab.go
index dea460d..52d7d55 100644
--- a/src/pkg/debug/gosym/symtab.go
+++ b/src/pkg/debug/gosym/symtab.go
@@ -15,7 +15,6 @@ package gosym
 import (
 	"encoding/binary"
 	"fmt"
-	"os"
 	"strconv"
 	"strings"
 )
@@ -105,7 +104,7 @@ type sym struct {
 	name   []byte
 }
 
-func walksymtab(data []byte, fn func(sym) os.Error) os.Error {
+func walksymtab(data []byte, fn func(sym) error) error {
 	var s sym
 	p := data
 	for len(p) >= 6 {
@@ -149,9 +148,9 @@ func walksymtab(data []byte, fn func(sym) os.Error) os.Error {
 
 // NewTable decodes the Go symbol table in data,
 // returning an in-memory representation.
-func NewTable(symtab []byte, pcln *LineTable) (*Table, os.Error) {
+func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
 	var n int
-	err := walksymtab(symtab, func(s sym) os.Error {
+	err := walksymtab(symtab, func(s sym) error {
 		n++
 		return nil
 	})
@@ -165,7 +164,7 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, os.Error) {
 	nf := 0
 	nz := 0
 	lasttyp := uint8(0)
-	err = walksymtab(symtab, func(s sym) os.Error {
+	err = walksymtab(symtab, func(s sym) error {
 		n := len(t.Syms)
 		t.Syms = t.Syms[0 : n+1]
 		ts := &t.Syms[n]
@@ -355,7 +354,7 @@ func (t *Table) PCToLine(pc uint64) (file string, line int, fn *Func) {
 // LineToPC looks up the first program counter on the given line in
 // the named file.  Returns UnknownPathError or UnknownLineError if
 // there is an error looking up this line.
-func (t *Table) LineToPC(file string, line int) (pc uint64, fn *Func, err os.Error) {
+func (t *Table) LineToPC(file string, line int) (pc uint64, fn *Func, err error) {
 	obj, ok := t.Files[file]
 	if !ok {
 		return 0, nil, UnknownFileError(file)
@@ -466,7 +465,7 @@ pathloop:
 	return tos.path, aline - tos.start - tos.offset + 1
 }
 
-func (o *Obj) alineFromLine(path string, line int) (int, os.Error) {
+func (o *Obj) alineFromLine(path string, line int) (int, error) {
 	if line < 1 {
 		return 0, &UnknownLineError{path, line}
 	}
@@ -516,7 +515,7 @@ func (o *Obj) alineFromLine(path string, line int) (int, os.Error) {
 // the symbol table.
 type UnknownFileError string
 
-func (e UnknownFileError) String() string { return "unknown file: " + string(e) }
+func (e UnknownFileError) Error() string { return "unknown file: " + string(e) }
 
 // UnknownLineError represents a failure to map a line to a program
 // counter, either because the line is beyond the bounds of the file
@@ -526,7 +525,7 @@ type UnknownLineError struct {
 	Line int
 }
 
-func (e *UnknownLineError) String() string {
+func (e *UnknownLineError) Error() string {
 	return "no code at " + e.File + ":" + strconv.Itoa(e.Line)
 }
 
@@ -538,7 +537,7 @@ type DecodingError struct {
 	val interface{}
 }
 
-func (e *DecodingError) String() string {
+func (e *DecodingError) Error() string {
 	msg := e.msg
 	if e.val != nil {
 		msg += fmt.Sprintf(" '%v'", e.val)
diff --git a/src/pkg/debug/macho/file.go b/src/pkg/debug/macho/file.go
index 721a4c4..c7cb905 100644
--- a/src/pkg/debug/macho/file.go
+++ b/src/pkg/debug/macho/file.go
@@ -12,6 +12,7 @@ import (
 	"bytes"
 	"debug/dwarf"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"io"
 	"os"
@@ -71,7 +72,7 @@ type Segment struct {
 }
 
 // Data reads and returns the contents of the segment.
-func (s *Segment) Data() ([]byte, os.Error) {
+func (s *Segment) Data() ([]byte, error) {
 	dat := make([]byte, s.sr.Size())
 	n, err := s.sr.ReadAt(dat, 0)
 	return dat[0:n], err
@@ -106,7 +107,7 @@ type Section struct {
 }
 
 // Data reads and returns the contents of the Mach-O section.
-func (s *Section) Data() ([]byte, os.Error) {
+func (s *Section) Data() ([]byte, error) {
 	dat := make([]byte, s.sr.Size())
 	n, err := s.sr.ReadAt(dat, 0)
 	return dat[0:n], err
@@ -148,7 +149,7 @@ type FormatError struct {
 	val interface{}
 }
 
-func (e *FormatError) String() string {
+func (e *FormatError) Error() string {
 	msg := e.msg
 	if e.val != nil {
 		msg += fmt.Sprintf(" '%v'", e.val)
@@ -158,7 +159,7 @@ func (e *FormatError) String() string {
 }
 
 // Open opens the named file using os.Open and prepares it for use as a Mach-O binary.
-func Open(name string) (*File, os.Error) {
+func Open(name string) (*File, error) {
 	f, err := os.Open(name)
 	if err != nil {
 		return nil, err
@@ -175,8 +176,8 @@ func Open(name string) (*File, os.Error) {
 // Close closes the File.
 // If the File was created using NewFile directly instead of Open,
 // Close has no effect.
-func (f *File) Close() os.Error {
-	var err os.Error
+func (f *File) Close() error {
+	var err error
 	if f.closer != nil {
 		err = f.closer.Close()
 		f.closer = nil
@@ -186,7 +187,7 @@ func (f *File) Close() os.Error {
 
 // NewFile creates a new File for accessing a Mach-O binary in an underlying reader.
 // The Mach-O binary is expected to start at position 0 in the ReaderAt.
-func NewFile(r io.ReaderAt) (*File, os.Error) {
+func NewFile(r io.ReaderAt) (*File, error) {
 	f := new(File)
 	sr := io.NewSectionReader(r, 0, 1<<63-1)
 
@@ -391,7 +392,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
 	return f, nil
 }
 
-func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, os.Error) {
+func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, error) {
 	bo := f.ByteOrder
 	symtab := make([]Symbol, hdr.Nsyms)
 	b := bytes.NewBuffer(symdat)
@@ -463,7 +464,7 @@ func (f *File) Section(name string) *Section {
 }
 
 // DWARF returns the DWARF debug information for the Mach-O file.
-func (f *File) DWARF() (*dwarf.Data, os.Error) {
+func (f *File) DWARF() (*dwarf.Data, error) {
 	// There are many other DWARF sections, but these
 	// are the required ones, and the debug/dwarf package
 	// does not use the others, so don't bother loading them.
@@ -473,7 +474,7 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
 		name = "__debug_" + name
 		s := f.Section(name)
 		if s == nil {
-			return nil, os.NewError("missing Mach-O section " + name)
+			return nil, errors.New("missing Mach-O section " + name)
 		}
 		b, err := s.Data()
 		if err != nil && uint64(len(b)) < s.Size {
@@ -489,7 +490,7 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
 // ImportedSymbols returns the names of all symbols
 // referred to by the binary f that are expected to be
 // satisfied by other libraries at dynamic load time.
-func (f *File) ImportedSymbols() ([]string, os.Error) {
+func (f *File) ImportedSymbols() ([]string, error) {
 	if f.Dysymtab == nil || f.Symtab == nil {
 		return nil, &FormatError{0, "missing symbol table", nil}
 	}
@@ -506,7 +507,7 @@ func (f *File) ImportedSymbols() ([]string, os.Error) {
 // ImportedLibraries returns the paths of all libraries
 // referred to by the binary f that are expected to be
 // linked with the binary at dynamic link time.
-func (f *File) ImportedLibraries() ([]string, os.Error) {
+func (f *File) ImportedLibraries() ([]string, error) {
 	var all []string
 	for _, l := range f.Loads {
 		if lib, ok := l.(*Dylib); ok {
diff --git a/src/pkg/debug/macho/file_test.go b/src/pkg/debug/macho/file_test.go
index 56d8a20..640225b 100644
--- a/src/pkg/debug/macho/file_test.go
+++ b/src/pkg/debug/macho/file_test.go
@@ -21,11 +21,11 @@ var fileTests = []fileTest{
 		"testdata/gcc-386-darwin-exec",
 		FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85},
 		[]*SegmentHeader{
-			&SegmentHeader{LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
-			&SegmentHeader{LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0},
-			&SegmentHeader{LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0},
-			&SegmentHeader{LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0},
-			&SegmentHeader{LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0},
+			{LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0},
+			{LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0},
+			{LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0},
+			{LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0},
 			nil,
 			nil,
 			nil,
@@ -35,21 +35,21 @@ var fileTests = []fileTest{
 			nil,
 		},
 		[]*SectionHeader{
-			&SectionHeader{"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400},
-			&SectionHeader{"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2},
-			&SectionHeader{"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0},
-			&SectionHeader{"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0},
-			&SectionHeader{"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008},
+			{"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400},
+			{"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2},
+			{"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0},
+			{"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0},
+			{"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008},
 		},
 	},
 	{
 		"testdata/gcc-amd64-darwin-exec",
 		FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85},
 		[]*SegmentHeader{
-			&SegmentHeader{LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
-			&SegmentHeader{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0},
-			&SegmentHeader{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0},
-			&SegmentHeader{LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0},
+			{LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0},
+			{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0},
+			{LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0},
 			nil,
 			nil,
 			nil,
@@ -59,14 +59,14 @@ var fileTests = []fileTest{
 			nil,
 		},
 		[]*SectionHeader{
-			&SectionHeader{"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400},
-			&SectionHeader{"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408},
-			&SectionHeader{"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0},
-			&SectionHeader{"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2},
-			&SectionHeader{"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b},
-			&SectionHeader{"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0},
-			&SectionHeader{"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0},
-			&SectionHeader{"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7},
+			{"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400},
+			{"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408},
+			{"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0},
+			{"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2},
+			{"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b},
+			{"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0},
+			{"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0},
+			{"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7},
 		},
 	},
 	{
@@ -74,26 +74,26 @@ var fileTests = []fileTest{
 		FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0},
 		[]*SegmentHeader{
 			nil,
-			&SegmentHeader{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0},
-			&SegmentHeader{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0},
-			&SegmentHeader{LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0},
+			{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0},
+			{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0},
+			{LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0},
 		},
 		[]*SectionHeader{
-			&SectionHeader{"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400},
-			&SectionHeader{"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408},
-			&SectionHeader{"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0},
-			&SectionHeader{"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
-			&SectionHeader{"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b},
-			&SectionHeader{"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
-			&SectionHeader{"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
-			&SectionHeader{"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7},
-			&SectionHeader{"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0},
-			&SectionHeader{"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0},
-			&SectionHeader{"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0},
-			&SectionHeader{"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0},
-			&SectionHeader{"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0},
-			&SectionHeader{"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0},
-			&SectionHeader{"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
+			{"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400},
+			{"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408},
+			{"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0},
+			{"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
+			{"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b},
+			{"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
+			{"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
+			{"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7},
+			{"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0},
+			{"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
 		},
 	},
 }
diff --git a/src/pkg/debug/macho/macho.go b/src/pkg/debug/macho/macho.go
index 1386f5a..bc14226 100644
--- a/src/pkg/debug/macho/macho.go
+++ b/src/pkg/debug/macho/macho.go
@@ -278,7 +278,7 @@ func stringName(i uint32, names []intName, goSyntax bool) string {
 			return n.s
 		}
 	}
-	return strconv.Uitoa64(uint64(i))
+	return strconv.FormatUint(uint64(i), 10)
 }
 
 func flagName(i uint32, names []intName, goSyntax bool) string {
@@ -296,10 +296,10 @@ func flagName(i uint32, names []intName, goSyntax bool) string {
 		}
 	}
 	if len(s) == 0 {
-		return "0x" + strconv.Uitob64(uint64(i), 16)
+		return "0x" + strconv.FormatUint(uint64(i), 16)
 	}
 	if i != 0 {
-		s += "+0x" + strconv.Uitob64(uint64(i), 16)
+		s += "+0x" + strconv.FormatUint(uint64(i), 16)
 	}
 	return s
 }
diff --git a/src/pkg/debug/pe/file.go b/src/pkg/debug/pe/file.go
index d86d916..6b98a5f 100644
--- a/src/pkg/debug/pe/file.go
+++ b/src/pkg/debug/pe/file.go
@@ -8,6 +8,7 @@ package pe
 import (
 	"debug/dwarf"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"io"
 	"os"
@@ -59,7 +60,7 @@ type ImportDirectory struct {
 }
 
 // Data reads and returns the contents of the PE section.
-func (s *Section) Data() ([]byte, os.Error) {
+func (s *Section) Data() ([]byte, error) {
 	dat := make([]byte, s.sr.Size())
 	n, err := s.sr.ReadAt(dat, 0)
 	return dat[0:n], err
@@ -74,7 +75,7 @@ type FormatError struct {
 	val interface{}
 }
 
-func (e *FormatError) String() string {
+func (e *FormatError) Error() string {
 	msg := e.msg
 	if e.val != nil {
 		msg += fmt.Sprintf(" '%v'", e.val)
@@ -84,7 +85,7 @@ func (e *FormatError) String() string {
 }
 
 // Open opens the named file using os.Open and prepares it for use as a PE binary.
-func Open(name string) (*File, os.Error) {
+func Open(name string) (*File, error) {
 	f, err := os.Open(name)
 	if err != nil {
 		return nil, err
@@ -101,8 +102,8 @@ func Open(name string) (*File, os.Error) {
 // Close closes the File.
 // If the File was created using NewFile directly instead of Open,
 // Close has no effect.
-func (f *File) Close() os.Error {
-	var err os.Error
+func (f *File) Close() error {
+	var err error
 	if f.closer != nil {
 		err = f.closer.Close()
 		f.closer = nil
@@ -111,7 +112,7 @@ func (f *File) Close() os.Error {
 }
 
 // NewFile creates a new File for accessing a PE binary in an underlying reader.
-func NewFile(r io.ReaderAt) (*File, os.Error) {
+func NewFile(r io.ReaderAt) (*File, error) {
 	f := new(File)
 	sr := io.NewSectionReader(r, 0, 1<<63-1)
 
@@ -124,7 +125,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
 		var sign [4]byte
 		r.ReadAt(sign[0:], int64(dosheader[0x3c]))
 		if !(sign[0] == 'P' && sign[1] == 'E' && sign[2] == 0 && sign[3] == 0) {
-			return nil, os.NewError("Invalid PE File Format.")
+			return nil, errors.New("Invalid PE File Format.")
 		}
 		base = int64(dosheader[0x3c]) + 4
 	} else {
@@ -135,7 +136,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
 		return nil, err
 	}
 	if f.FileHeader.Machine != IMAGE_FILE_MACHINE_UNKNOWN && f.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 && f.FileHeader.Machine != IMAGE_FILE_MACHINE_I386 {
-		return nil, os.NewError("Invalid PE File Format.")
+		return nil, errors.New("Invalid PE File Format.")
 	}
 	// get symbol string table
 	sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
@@ -215,7 +216,7 @@ func (f *File) Section(name string) *Section {
 	return nil
 }
 
-func (f *File) DWARF() (*dwarf.Data, os.Error) {
+func (f *File) DWARF() (*dwarf.Data, error) {
 	// There are many other DWARF sections, but these
 	// are the required ones, and the debug/dwarf package
 	// does not use the others, so don't bother loading them.
@@ -242,7 +243,7 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
 // referred to by the binary f that are expected to be
 // satisfied by other libraries at dynamic load time.
 // It does not return weak symbols.
-func (f *File) ImportedSymbols() ([]string, os.Error) {
+func (f *File) ImportedSymbols() ([]string, error) {
 	pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64
 	ds := f.Section(".idata")
 	if ds == nil {
@@ -308,7 +309,7 @@ func (f *File) ImportedSymbols() ([]string, os.Error) {
 // ImportedLibraries returns the names of all libraries
 // referred to by the binary f that are expected to be
 // linked with the binary at dynamic link time.
-func (f *File) ImportedLibraries() ([]string, os.Error) {
+func (f *File) ImportedLibraries() ([]string, error) {
 	// TODO
 	// cgo -dynimport don't use this for windows PE, so just return.
 	return nil, nil
diff --git a/src/pkg/debug/pe/file_test.go b/src/pkg/debug/pe/file_test.go
index 2c5c25b..2815d72 100644
--- a/src/pkg/debug/pe/file_test.go
+++ b/src/pkg/debug/pe/file_test.go
@@ -20,39 +20,39 @@ var fileTests = []fileTest{
 		"testdata/gcc-386-mingw-obj",
 		FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
 		[]*SectionHeader{
-			&SectionHeader{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
-			&SectionHeader{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
-			&SectionHeader{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
-			&SectionHeader{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
-			&SectionHeader{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
-			&SectionHeader{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
-			&SectionHeader{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
-			&SectionHeader{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
-			&SectionHeader{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
-			&SectionHeader{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
-			&SectionHeader{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
-			&SectionHeader{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
+			{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
+			{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
+			{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
+			{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
+			{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
+			{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
+			{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
+			{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
+			{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
+			{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
+			{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
+			{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
 		},
 	},
 	{
 		"testdata/gcc-386-mingw-exec",
 		FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
 		[]*SectionHeader{
-			&SectionHeader{Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060},
-			&SectionHeader{Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
-			&SectionHeader{Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040},
-			&SectionHeader{Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080},
-			&SectionHeader{Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
-			&SectionHeader{Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
-			&SectionHeader{Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
-			&SectionHeader{Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-			&SectionHeader{Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-			&SectionHeader{Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-			&SectionHeader{Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-			&SectionHeader{Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-			&SectionHeader{Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-			&SectionHeader{Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
-			&SectionHeader{Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+			{Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060},
+			{Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
+			{Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040},
+			{Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080},
+			{Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
+			{Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
+			{Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
+			{Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+			{Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+			{Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+			{Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+			{Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+			{Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+			{Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
+			{Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
 		},
 	},
 }
diff --git a/src/pkg/deps.bash b/src/pkg/deps.bash
index 2095ec1..c4c44f6 100755
--- a/src/pkg/deps.bash
+++ b/src/pkg/deps.bash
@@ -24,7 +24,7 @@ dirpat=$(echo $dirs C | awk '{
 }')
 
 for dir in $dirs; do (
-	cd $dir || exit 1
+	cd $dir >/dev/null || exit 1
 
 	sources=$(sed -n 's/^[ 	]*\([^ 	]*\.go\)[ 	]*\\*[ 	]*$/\1/p' Makefile)
 	sources=$(echo $sources | sed 's/\$(GOOS)/'$GOOS'/g')
@@ -47,3 +47,8 @@ for dir in $dirs; do (
 ) done > $TMP
 
 mv $TMP $OUT
+
+if (egrep -v '^(exp|old)/' $OUT | egrep -q " (exp|old)/"); then
+	echo "$0: $OUT contains dependencies to exp or old packages"
+        exit 1
+fi
diff --git a/src/pkg/ebnf/Makefile b/src/pkg/ebnf/Makefile
deleted file mode 100644
index f5555d2..0000000
--- a/src/pkg/ebnf/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=ebnf
-GOFILES=\
-	ebnf.go\
-	parser.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/ebnf/ebnf.go b/src/pkg/ebnf/ebnf.go
deleted file mode 100644
index 69da117..0000000
--- a/src/pkg/ebnf/ebnf.go
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package ebnf is a library for EBNF grammars. The input is text ([]byte)
-// satisfying the following grammar (represented itself in EBNF):
-//
-//	Production  = name "=" [ Expression ] "." .
-//	Expression  = Alternative { "|" Alternative } .
-//	Alternative = Term { Term } .
-//	Term        = name | token [ "…" token ] | Group | Option | Repetition .
-//	Group       = "(" Expression ")" .
-//	Option      = "[" Expression "]" .
-//	Repetition  = "{" Expression "}" .
-//
-// A name is a Go identifier, a token is a Go string, and comments
-// and white space follow the same rules as for the Go language.
-// Production names starting with an uppercase Unicode letter denote
-// non-terminal productions (i.e., productions which allow white-space
-// and comments between tokens); all other production names denote
-// lexical productions.
-//
-package ebnf
-
-import (
-	"go/scanner"
-	"go/token"
-	"os"
-	"unicode"
-	"utf8"
-)
-
-// ----------------------------------------------------------------------------
-// Internal representation
-
-type (
-	// An Expression node represents a production expression.
-	Expression interface {
-		// Pos is the position of the first character of the syntactic construct
-		Pos() token.Pos
-	}
-
-	// An Alternative node represents a non-empty list of alternative expressions.
-	Alternative []Expression // x | y | z
-
-	// A Sequence node represents a non-empty list of sequential expressions.
-	Sequence []Expression // x y z
-
-	// A Name node represents a production name.
-	Name struct {
-		StringPos token.Pos
-		String    string
-	}
-
-	// A Token node represents a literal.
-	Token struct {
-		StringPos token.Pos
-		String    string
-	}
-
-	// A List node represents a range of characters.
-	Range struct {
-		Begin, End *Token // begin ... end
-	}
-
-	// A Group node represents a grouped expression.
-	Group struct {
-		Lparen token.Pos
-		Body   Expression // (body)
-	}
-
-	// An Option node represents an optional expression.
-	Option struct {
-		Lbrack token.Pos
-		Body   Expression // [body]
-	}
-
-	// A Repetition node represents a repeated expression.
-	Repetition struct {
-		Lbrace token.Pos
-		Body   Expression // {body}
-	}
-
-	// A Bad node stands for pieces of source code that lead to a parse error.
-	Bad struct {
-		TokPos token.Pos
-		Error  string // parser error message
-	}
-
-	// A Production node represents an EBNF production.
-	Production struct {
-		Name *Name
-		Expr Expression
-	}
-
-	// A Grammar is a set of EBNF productions. The map
-	// is indexed by production name.
-	//
-	Grammar map[string]*Production
-)
-
-func (x Alternative) Pos() token.Pos { return x[0].Pos() } // the parser always generates non-empty Alternative
-func (x Sequence) Pos() token.Pos    { return x[0].Pos() } // the parser always generates non-empty Sequences
-func (x *Name) Pos() token.Pos       { return x.StringPos }
-func (x *Token) Pos() token.Pos      { return x.StringPos }
-func (x *Range) Pos() token.Pos      { return x.Begin.Pos() }
-func (x *Group) Pos() token.Pos      { return x.Lparen }
-func (x *Option) Pos() token.Pos     { return x.Lbrack }
-func (x *Repetition) Pos() token.Pos { return x.Lbrace }
-func (x *Bad) Pos() token.Pos        { return x.TokPos }
-func (x *Production) Pos() token.Pos { return x.Name.Pos() }
-
-// ----------------------------------------------------------------------------
-// Grammar verification
-
-func isLexical(name string) bool {
-	ch, _ := utf8.DecodeRuneInString(name)
-	return !unicode.IsUpper(ch)
-}
-
-type verifier struct {
-	fset *token.FileSet
-	scanner.ErrorVector
-	worklist []*Production
-	reached  Grammar // set of productions reached from (and including) the root production
-	grammar  Grammar
-}
-
-func (v *verifier) error(pos token.Pos, msg string) {
-	v.Error(v.fset.Position(pos), msg)
-}
-
-func (v *verifier) push(prod *Production) {
-	name := prod.Name.String
-	if _, found := v.reached[name]; !found {
-		v.worklist = append(v.worklist, prod)
-		v.reached[name] = prod
-	}
-}
-
-func (v *verifier) verifyChar(x *Token) int {
-	s := x.String
-	if utf8.RuneCountInString(s) != 1 {
-		v.error(x.Pos(), "single char expected, found "+s)
-		return 0
-	}
-	ch, _ := utf8.DecodeRuneInString(s)
-	return ch
-}
-
-func (v *verifier) verifyExpr(expr Expression, lexical bool) {
-	switch x := expr.(type) {
-	case nil:
-		// empty expression
-	case Alternative:
-		for _, e := range x {
-			v.verifyExpr(e, lexical)
-		}
-	case Sequence:
-		for _, e := range x {
-			v.verifyExpr(e, lexical)
-		}
-	case *Name:
-		// a production with this name must exist;
-		// add it to the worklist if not yet processed
-		if prod, found := v.grammar[x.String]; found {
-			v.push(prod)
-		} else {
-			v.error(x.Pos(), "missing production "+x.String)
-		}
-		// within a lexical production references
-		// to non-lexical productions are invalid
-		if lexical && !isLexical(x.String) {
-			v.error(x.Pos(), "reference to non-lexical production "+x.String)
-		}
-	case *Token:
-		// nothing to do for now
-	case *Range:
-		i := v.verifyChar(x.Begin)
-		j := v.verifyChar(x.End)
-		if i >= j {
-			v.error(x.Pos(), "decreasing character range")
-		}
-	case *Group:
-		v.verifyExpr(x.Body, lexical)
-	case *Option:
-		v.verifyExpr(x.Body, lexical)
-	case *Repetition:
-		v.verifyExpr(x.Body, lexical)
-	default:
-		panic("unreachable")
-	}
-}
-
-func (v *verifier) verify(fset *token.FileSet, grammar Grammar, start string) {
-	// find root production
-	root, found := grammar[start]
-	if !found {
-		// token.NoPos doesn't require a file set;
-		// ok to set v.fset only afterwards
-		v.error(token.NoPos, "no start production "+start)
-		return
-	}
-
-	// initialize verifier
-	v.fset = fset
-	v.ErrorVector.Reset()
-	v.worklist = v.worklist[0:0]
-	v.reached = make(Grammar)
-	v.grammar = grammar
-
-	// work through the worklist
-	v.push(root)
-	for {
-		n := len(v.worklist) - 1
-		if n < 0 {
-			break
-		}
-		prod := v.worklist[n]
-		v.worklist = v.worklist[0:n]
-		v.verifyExpr(prod.Expr, isLexical(prod.Name.String))
-	}
-
-	// check if all productions were reached
-	if len(v.reached) < len(v.grammar) {
-		for name, prod := range v.grammar {
-			if _, found := v.reached[name]; !found {
-				v.error(prod.Pos(), name+" is unreachable")
-			}
-		}
-	}
-}
-
-// Verify checks that:
-//	- all productions used are defined
-//	- all productions defined are used when beginning at start
-//	- lexical productions refer only to other lexical productions
-//
-// Position information is interpreted relative to the file set fset.
-//
-func Verify(fset *token.FileSet, grammar Grammar, start string) os.Error {
-	var v verifier
-	v.verify(fset, grammar, start)
-	return v.GetError(scanner.Sorted)
-}
diff --git a/src/pkg/ebnf/ebnf_test.go b/src/pkg/ebnf/ebnf_test.go
deleted file mode 100644
index b086fac..0000000
--- a/src/pkg/ebnf/ebnf_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ebnf
-
-import (
-	"go/token"
-	"io/ioutil"
-	"testing"
-)
-
-var fset = token.NewFileSet()
-
-var goodGrammars = []string{
-	`Program = .`,
-
-	`Program = foo .
-	 foo = "foo" .`,
-
-	`Program = "a" | "b" "c" .`,
-
-	`Program = "a" … "z" .`,
-
-	`Program = Song .
-	 Song = { Note } .
-	 Note = Do | (Re | Mi | Fa | So | La) | Ti .
-	 Do = "c" .
-	 Re = "d" .
-	 Mi = "e" .
-	 Fa = "f" .
-	 So = "g" .
-	 La = "a" .
-	 Ti = ti .
-	 ti = "b" .`,
-}
-
-var badGrammars = []string{
-	`Program = | .`,
-	`Program = | b .`,
-	`Program = a … b .`,
-	`Program = "a" … .`,
-	`Program = … "b" .`,
-	`Program = () .`,
-	`Program = [] .`,
-	`Program = {} .`,
-}
-
-func checkGood(t *testing.T, filename string, src []byte) {
-	grammar, err := Parse(fset, filename, src)
-	if err != nil {
-		t.Errorf("Parse(%s) failed: %v", src, err)
-	}
-	if err = Verify(fset, grammar, "Program"); err != nil {
-		t.Errorf("Verify(%s) failed: %v", src, err)
-	}
-}
-
-func checkBad(t *testing.T, filename string, src []byte) {
-	_, err := Parse(fset, filename, src)
-	if err == nil {
-		t.Errorf("Parse(%s) should have failed", src)
-	}
-}
-
-func TestGrammars(t *testing.T) {
-	for _, src := range goodGrammars {
-		checkGood(t, "", []byte(src))
-	}
-	for _, src := range badGrammars {
-		checkBad(t, "", []byte(src))
-	}
-}
-
-var files = []string{
-// TODO(gri) add some test files
-}
-
-func TestFiles(t *testing.T) {
-	for _, filename := range files {
-		src, err := ioutil.ReadFile(filename)
-		if err != nil {
-			t.Fatal(err)
-		}
-		checkGood(t, filename, src)
-	}
-}
diff --git a/src/pkg/ebnf/parser.go b/src/pkg/ebnf/parser.go
deleted file mode 100644
index ef2fac0..0000000
--- a/src/pkg/ebnf/parser.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ebnf
-
-import (
-	"go/scanner"
-	"go/token"
-	"os"
-	"strconv"
-)
-
-type parser struct {
-	fset *token.FileSet
-	scanner.ErrorVector
-	scanner scanner.Scanner
-	pos     token.Pos   // token position
-	tok     token.Token // one token look-ahead
-	lit     string      // token literal
-}
-
-func (p *parser) next() {
-	p.pos, p.tok, p.lit = p.scanner.Scan()
-	if p.tok.IsKeyword() {
-		// TODO Should keyword mapping always happen outside scanner?
-		//      Or should there be a flag to scanner to enable keyword mapping?
-		p.tok = token.IDENT
-	}
-}
-
-func (p *parser) error(pos token.Pos, msg string) {
-	p.Error(p.fset.Position(pos), msg)
-}
-
-func (p *parser) errorExpected(pos token.Pos, msg string) {
-	msg = "expected " + msg
-	if pos == p.pos {
-		// the error happened at the current position;
-		// make the error message more specific
-		msg += ", found '" + p.tok.String() + "'"
-		if p.tok.IsLiteral() {
-			msg += " " + p.lit
-		}
-	}
-	p.error(pos, msg)
-}
-
-func (p *parser) expect(tok token.Token) token.Pos {
-	pos := p.pos
-	if p.tok != tok {
-		p.errorExpected(pos, "'"+tok.String()+"'")
-	}
-	p.next() // make progress in any case
-	return pos
-}
-
-func (p *parser) parseIdentifier() *Name {
-	pos := p.pos
-	name := p.lit
-	p.expect(token.IDENT)
-	return &Name{pos, name}
-}
-
-func (p *parser) parseToken() *Token {
-	pos := p.pos
-	value := ""
-	if p.tok == token.STRING {
-		value, _ = strconv.Unquote(p.lit)
-		// Unquote may fail with an error, but only if the scanner found
-		// an illegal string in the first place. In this case the error
-		// has already been reported.
-		p.next()
-	} else {
-		p.expect(token.STRING)
-	}
-	return &Token{pos, value}
-}
-
-// ParseTerm returns nil if no term was found.
-func (p *parser) parseTerm() (x Expression) {
-	pos := p.pos
-
-	switch p.tok {
-	case token.IDENT:
-		x = p.parseIdentifier()
-
-	case token.STRING:
-		tok := p.parseToken()
-		x = tok
-		const ellipsis = "…" // U+2026, the horizontal ellipsis character
-		if p.tok == token.ILLEGAL && p.lit == ellipsis {
-			p.next()
-			x = &Range{tok, p.parseToken()}
-		}
-
-	case token.LPAREN:
-		p.next()
-		x = &Group{pos, p.parseExpression()}
-		p.expect(token.RPAREN)
-
-	case token.LBRACK:
-		p.next()
-		x = &Option{pos, p.parseExpression()}
-		p.expect(token.RBRACK)
-
-	case token.LBRACE:
-		p.next()
-		x = &Repetition{pos, p.parseExpression()}
-		p.expect(token.RBRACE)
-	}
-
-	return x
-}
-
-func (p *parser) parseSequence() Expression {
-	var list Sequence
-
-	for x := p.parseTerm(); x != nil; x = p.parseTerm() {
-		list = append(list, x)
-	}
-
-	// no need for a sequence if list.Len() < 2
-	switch len(list) {
-	case 0:
-		p.errorExpected(p.pos, "term")
-		return &Bad{p.pos, "term expected"}
-	case 1:
-		return list[0]
-	}
-
-	return list
-}
-
-func (p *parser) parseExpression() Expression {
-	var list Alternative
-
-	for {
-		list = append(list, p.parseSequence())
-		if p.tok != token.OR {
-			break
-		}
-		p.next()
-	}
-	// len(list) > 0
-
-	// no need for an Alternative node if list.Len() < 2
-	if len(list) == 1 {
-		return list[0]
-	}
-
-	return list
-}
-
-func (p *parser) parseProduction() *Production {
-	name := p.parseIdentifier()
-	p.expect(token.ASSIGN)
-	var expr Expression
-	if p.tok != token.PERIOD {
-		expr = p.parseExpression()
-	}
-	p.expect(token.PERIOD)
-	return &Production{name, expr}
-}
-
-func (p *parser) parse(fset *token.FileSet, filename string, src []byte) Grammar {
-	// initialize parser
-	p.fset = fset
-	p.ErrorVector.Reset()
-	p.scanner.Init(fset.AddFile(filename, fset.Base(), len(src)), src, p, scanner.AllowIllegalChars)
-	p.next() // initializes pos, tok, lit
-
-	grammar := make(Grammar)
-	for p.tok != token.EOF {
-		prod := p.parseProduction()
-		name := prod.Name.String
-		if _, found := grammar[name]; !found {
-			grammar[name] = prod
-		} else {
-			p.error(prod.Pos(), name+" declared already")
-		}
-	}
-
-	return grammar
-}
-
-// Parse parses a set of EBNF productions from source src.
-// It returns a set of productions. Errors are reported
-// for incorrect syntax and if a production is declared
-// more than once. Position information is recorded relative
-// to the file set fset.
-//
-func Parse(fset *token.FileSet, filename string, src []byte) (Grammar, os.Error) {
-	var p parser
-	grammar := p.parse(fset, filename, src)
-	return grammar, p.GetError(scanner.Sorted)
-}
diff --git a/src/pkg/encoding/ascii85/ascii85.go b/src/pkg/encoding/ascii85/ascii85.go
index ead0c24..7d004b5 100644
--- a/src/pkg/encoding/ascii85/ascii85.go
+++ b/src/pkg/encoding/ascii85/ascii85.go
@@ -8,7 +8,6 @@ package ascii85
 
 import (
 	"io"
-	"os"
 	"strconv"
 )
 
@@ -93,14 +92,14 @@ func MaxEncodedLen(n int) int { return (n + 3) / 4 * 5 }
 func NewEncoder(w io.Writer) io.WriteCloser { return &encoder{w: w} }
 
 type encoder struct {
-	err  os.Error
+	err  error
 	w    io.Writer
 	buf  [4]byte    // buffered data waiting to be encoded
 	nbuf int        // number of bytes in buf
 	out  [1024]byte // output buffer
 }
 
-func (e *encoder) Write(p []byte) (n int, err os.Error) {
+func (e *encoder) Write(p []byte) (n int, err error) {
 	if e.err != nil {
 		return 0, e.err
 	}
@@ -152,7 +151,7 @@ func (e *encoder) Write(p []byte) (n int, err os.Error) {
 
 // Close flushes any pending output from the encoder.
 // It is an error to call Write after calling Close.
-func (e *encoder) Close() os.Error {
+func (e *encoder) Close() error {
 	// If there's anything left in the buffer, flush it out
 	if e.err == nil && e.nbuf > 0 {
 		nout := Encode(e.out[0:], e.buf[0:e.nbuf])
@@ -168,8 +167,8 @@ func (e *encoder) Close() os.Error {
 
 type CorruptInputError int64
 
-func (e CorruptInputError) String() string {
-	return "illegal ascii85 data at input byte " + strconv.Itoa64(int64(e))
+func (e CorruptInputError) Error() string {
+	return "illegal ascii85 data at input byte " + strconv.FormatInt(int64(e), 10)
 }
 
 // Decode decodes src into dst, returning both the number
@@ -186,7 +185,7 @@ func (e CorruptInputError) String() string {
 //
 // NewDecoder wraps an io.Reader interface around Decode.
 //
-func Decode(dst, src []byte, flush bool) (ndst, nsrc int, err os.Error) {
+func Decode(dst, src []byte, flush bool) (ndst, nsrc int, err error) {
 	var v uint32
 	var nb int
 	for i, b := range src {
@@ -246,8 +245,8 @@ func Decode(dst, src []byte, flush bool) (ndst, nsrc int, err os.Error) {
 func NewDecoder(r io.Reader) io.Reader { return &decoder{r: r} }
 
 type decoder struct {
-	err     os.Error
-	readErr os.Error
+	err     error
+	readErr error
 	r       io.Reader
 	end     bool       // saw end of message
 	buf     [1024]byte // leftover input
@@ -256,7 +255,7 @@ type decoder struct {
 	outbuf  [1024]byte
 }
 
-func (d *decoder) Read(p []byte) (n int, err os.Error) {
+func (d *decoder) Read(p []byte) (n int, err error) {
 	if len(p) == 0 {
 		return 0, nil
 	}
diff --git a/src/pkg/encoding/ascii85/ascii85_test.go b/src/pkg/encoding/ascii85/ascii85_test.go
index fdfeb88..70e67d8 100644
--- a/src/pkg/encoding/ascii85/ascii85_test.go
+++ b/src/pkg/encoding/ascii85/ascii85_test.go
@@ -6,8 +6,8 @@ package ascii85
 
 import (
 	"bytes"
+	"io"
 	"io/ioutil"
-	"os"
 	"testing"
 )
 
@@ -83,11 +83,11 @@ func TestEncoderBuffering(t *testing.T) {
 				end = len(input)
 			}
 			n, err := encoder.Write(input[pos:end])
-			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, os.Error(nil))
+			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
 			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
 		}
 		err := encoder.Close()
-		testEqual(t, "Close gave error %v, want %v", err, os.Error(nil))
+		testEqual(t, "Close gave error %v, want %v", err, error(nil))
 		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, strip85(bb.String()), strip85(bigtest.encoded))
 	}
 }
@@ -96,7 +96,7 @@ func TestDecode(t *testing.T) {
 	for _, p := range pairs {
 		dbuf := make([]byte, 4*len(p.encoded))
 		ndst, nsrc, err := Decode(dbuf, []byte(p.encoded), true)
-		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, os.Error(nil))
+		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
 		testEqual(t, "Decode(%q) = nsrc %v, want %v", p.encoded, nsrc, len(p.encoded))
 		testEqual(t, "Decode(%q) = ndst %v, want %v", p.encoded, ndst, len(p.decoded))
 		testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:ndst]), p.decoded)
@@ -113,7 +113,7 @@ func TestDecoder(t *testing.T) {
 		testEqual(t, "Read from %q = length %v, want %v", p.encoded, len(dbuf), len(p.decoded))
 		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf), p.decoded)
 		if err != nil {
-			testEqual(t, "Read from %q = %v, want %v", p.encoded, err, os.EOF)
+			testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
 		}
 	}
 }
@@ -125,7 +125,7 @@ func TestDecoderBuffering(t *testing.T) {
 		var total int
 		for total = 0; total < len(bigtest.decoded); {
 			n, err := decoder.Read(buf[total : total+bs])
-			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, os.Error(nil))
+			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil))
 			total += n
 		}
 		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
diff --git a/src/pkg/encoding/asn1/Makefile b/src/pkg/encoding/asn1/Makefile
new file mode 100644
index 0000000..1c046dc
--- /dev/null
+++ b/src/pkg/encoding/asn1/Makefile
@@ -0,0 +1,13 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=encoding/asn1
+GOFILES=\
+	asn1.go\
+	common.go\
+	marshal.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/encoding/asn1/asn1.go b/src/pkg/encoding/asn1/asn1.go
new file mode 100644
index 0000000..4d1ae38
--- /dev/null
+++ b/src/pkg/encoding/asn1/asn1.go
@@ -0,0 +1,842 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package asn1 implements parsing of DER-encoded ASN.1 data structures,
+// as defined in ITU-T Rec X.690.
+//
+// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,''
+// http://luca.ntop.org/Teaching/Appunti/asn1.html.
+package asn1
+
+// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc
+// are different encoding formats for those objects. Here, we'll be dealing
+// with DER, the Distinguished Encoding Rules. DER is used in X.509 because
+// it's fast to parse and, unlike BER, has a unique encoding for every object.
+// When calculating hashes over objects, it's important that the resulting
+// bytes be the same at both ends and DER removes this margin of error.
+//
+// ASN.1 is very complex and this package doesn't attempt to implement
+// everything by any means.
+
+import (
+	"fmt"
+	"math/big"
+	"reflect"
+	"time"
+)
+
+// A StructuralError suggests that the ASN.1 data is valid, but the Go type
+// which is receiving it doesn't match.
+type StructuralError struct {
+	Msg string
+}
+
+func (e StructuralError) Error() string { return "ASN.1 structure error: " + e.Msg }
+
+// A SyntaxError suggests that the ASN.1 data is invalid.
+type SyntaxError struct {
+	Msg string
+}
+
+func (e SyntaxError) Error() string { return "ASN.1 syntax error: " + e.Msg }
+
+// We start by dealing with each of the primitive types in turn.
+
+// BOOLEAN
+
+func parseBool(bytes []byte) (ret bool, err error) {
+	if len(bytes) != 1 {
+		err = SyntaxError{"invalid boolean"}
+		return
+	}
+
+	return bytes[0] != 0, nil
+}
+
+// INTEGER
+
+// parseInt64 treats the given bytes as a big-endian, signed integer and
+// returns the result.
+func parseInt64(bytes []byte) (ret int64, err error) {
+	if len(bytes) > 8 {
+		// We'll overflow an int64 in this case.
+		err = StructuralError{"integer too large"}
+		return
+	}
+	for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
+		ret <<= 8
+		ret |= int64(bytes[bytesRead])
+	}
+
+	// Shift up and down in order to sign extend the result.
+	ret <<= 64 - uint8(len(bytes))*8
+	ret >>= 64 - uint8(len(bytes))*8
+	return
+}
+
+// parseInt treats the given bytes as a big-endian, signed integer and returns
+// the result.
+func parseInt(bytes []byte) (int, error) {
+	ret64, err := parseInt64(bytes)
+	if err != nil {
+		return 0, err
+	}
+	if ret64 != int64(int(ret64)) {
+		return 0, StructuralError{"integer too large"}
+	}
+	return int(ret64), nil
+}
+
+var bigOne = big.NewInt(1)
+
+// parseBigInt treats the given bytes as a big-endian, signed integer and returns
+// the result.
+func parseBigInt(bytes []byte) *big.Int {
+	ret := new(big.Int)
+	if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
+		// This is a negative number.
+		notBytes := make([]byte, len(bytes))
+		for i := range notBytes {
+			notBytes[i] = ^bytes[i]
+		}
+		ret.SetBytes(notBytes)
+		ret.Add(ret, bigOne)
+		ret.Neg(ret)
+		return ret
+	}
+	ret.SetBytes(bytes)
+	return ret
+}
+
+// BIT STRING
+
+// BitString is the structure to use when you want an ASN.1 BIT STRING type. A
+// bit string is padded up to the nearest byte in memory and the number of
+// valid bits is recorded. Padding bits will be zero.
+type BitString struct {
+	Bytes     []byte // bits packed into bytes.
+	BitLength int    // length in bits.
+}
+
+// At returns the bit at the given index. If the index is out of range it
+// returns false.
+func (b BitString) At(i int) int {
+	if i < 0 || i >= b.BitLength {
+		return 0
+	}
+	x := i / 8
+	y := 7 - uint(i%8)
+	return int(b.Bytes[x]>>y) & 1
+}
+
+// RightAlign returns a slice where the padding bits are at the beginning. The
+// slice may share memory with the BitString.
+func (b BitString) RightAlign() []byte {
+	shift := uint(8 - (b.BitLength % 8))
+	if shift == 8 || len(b.Bytes) == 0 {
+		return b.Bytes
+	}
+
+	a := make([]byte, len(b.Bytes))
+	a[0] = b.Bytes[0] >> shift
+	for i := 1; i < len(b.Bytes); i++ {
+		a[i] = b.Bytes[i-1] << (8 - shift)
+		a[i] |= b.Bytes[i] >> shift
+	}
+
+	return a
+}
+
+// parseBitString parses an ASN.1 bit string from the given byte slice and returns it.
+func parseBitString(bytes []byte) (ret BitString, err error) {
+	if len(bytes) == 0 {
+		err = SyntaxError{"zero length BIT STRING"}
+		return
+	}
+	paddingBits := int(bytes[0])
+	if paddingBits > 7 ||
+		len(bytes) == 1 && paddingBits > 0 ||
+		bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {
+		err = SyntaxError{"invalid padding bits in BIT STRING"}
+		return
+	}
+	ret.BitLength = (len(bytes)-1)*8 - paddingBits
+	ret.Bytes = bytes[1:]
+	return
+}
+
+// OBJECT IDENTIFIER
+
+// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER.
+type ObjectIdentifier []int
+
+// Equal returns true iff oi and other represent the same identifier.
+func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
+	if len(oi) != len(other) {
+		return false
+	}
+	for i := 0; i < len(oi); i++ {
+		if oi[i] != other[i] {
+			return false
+		}
+	}
+
+	return true
+}
+
+// parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and
+// returns it. An object identifier is a sequence of variable length integers
+// that are assigned in a hierarchy.
+func parseObjectIdentifier(bytes []byte) (s []int, err error) {
+	if len(bytes) == 0 {
+		err = SyntaxError{"zero length OBJECT IDENTIFIER"}
+		return
+	}
+
+	// In the worst case, we get two elements from the first byte (which is
+	// encoded differently) and then every varint is a single byte long.
+	s = make([]int, len(bytes)+1)
+
+	// The first byte is 40*value1 + value2:
+	s[0] = int(bytes[0]) / 40
+	s[1] = int(bytes[0]) % 40
+	i := 2
+	for offset := 1; offset < len(bytes); i++ {
+		var v int
+		v, offset, err = parseBase128Int(bytes, offset)
+		if err != nil {
+			return
+		}
+		s[i] = v
+	}
+	s = s[0:i]
+	return
+}
+
+// ENUMERATED
+
+// An Enumerated is represented as a plain int.
+type Enumerated int
+
+// FLAG
+
+// A Flag accepts any data and is set to true if present.
+type Flag bool
+
+// parseBase128Int parses a base-128 encoded int from the given offset in the
+// given byte slice. It returns the value and the new offset.
+func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
+	offset = initOffset
+	for shifted := 0; offset < len(bytes); shifted++ {
+		if shifted > 4 {
+			err = StructuralError{"base 128 integer too large"}
+			return
+		}
+		ret <<= 7
+		b := bytes[offset]
+		ret |= int(b & 0x7f)
+		offset++
+		if b&0x80 == 0 {
+			return
+		}
+	}
+	err = SyntaxError{"truncated base 128 integer"}
+	return
+}
+
+// UTCTime
+
+func parseUTCTime(bytes []byte) (ret time.Time, err error) {
+	s := string(bytes)
+	ret, err = time.Parse("0601021504Z0700", s)
+	if err == nil {
+		return
+	}
+	ret, err = time.Parse("060102150405Z0700", s)
+	return
+}
+
+// parseGeneralizedTime parses the GeneralizedTime from the given byte slice
+// and returns the resulting time.
+func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
+	return time.Parse("20060102150405Z0700", string(bytes))
+}
+
+// PrintableString
+
+// parsePrintableString parses a ASN.1 PrintableString from the given byte
+// array and returns it.
+func parsePrintableString(bytes []byte) (ret string, err error) {
+	for _, b := range bytes {
+		if !isPrintable(b) {
+			err = SyntaxError{"PrintableString contains invalid character"}
+			return
+		}
+	}
+	ret = string(bytes)
+	return
+}
+
+// isPrintable returns true iff the given b is in the ASN.1 PrintableString set.
+func isPrintable(b byte) bool {
+	return 'a' <= b && b <= 'z' ||
+		'A' <= b && b <= 'Z' ||
+		'0' <= b && b <= '9' ||
+		'\'' <= b && b <= ')' ||
+		'+' <= b && b <= '/' ||
+		b == ' ' ||
+		b == ':' ||
+		b == '=' ||
+		b == '?' ||
+		// This is technically not allowed in a PrintableString.
+		// However, x509 certificates with wildcard strings don't
+		// always use the correct string type so we permit it.
+		b == '*'
+}
+
+// IA5String
+
+// parseIA5String parses a ASN.1 IA5String (ASCII string) from the given
+// byte slice and returns it.
+func parseIA5String(bytes []byte) (ret string, err error) {
+	for _, b := range bytes {
+		if b >= 0x80 {
+			err = SyntaxError{"IA5String contains invalid character"}
+			return
+		}
+	}
+	ret = string(bytes)
+	return
+}
+
+// T61String
+
+// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given
+// byte slice and returns it.
+func parseT61String(bytes []byte) (ret string, err error) {
+	return string(bytes), nil
+}
+
+// UTF8String
+
+// parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte
+// array and returns it.
+func parseUTF8String(bytes []byte) (ret string, err error) {
+	return string(bytes), nil
+}
+
+// A RawValue represents an undecoded ASN.1 object.
+type RawValue struct {
+	Class, Tag int
+	IsCompound bool
+	Bytes      []byte
+	FullBytes  []byte // includes the tag and length
+}
+
+// RawContent is used to signal that the undecoded, DER data needs to be
+// preserved for a struct. To use it, the first field of the struct must have
+// this type. It's an error for any of the other fields to have this type.
+type RawContent []byte
+
+// Tagging
+
+// parseTagAndLength parses an ASN.1 tag and length pair from the given offset
+// into a byte slice. It returns the parsed data and the new offset. SET and
+// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we
+// don't distinguish between ordered and unordered objects in this code.
+func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) {
+	offset = initOffset
+	b := bytes[offset]
+	offset++
+	ret.class = int(b >> 6)
+	ret.isCompound = b&0x20 == 0x20
+	ret.tag = int(b & 0x1f)
+
+	// If the bottom five bits are set, then the tag number is actually base 128
+	// encoded afterwards
+	if ret.tag == 0x1f {
+		ret.tag, offset, err = parseBase128Int(bytes, offset)
+		if err != nil {
+			return
+		}
+	}
+	if offset >= len(bytes) {
+		err = SyntaxError{"truncated tag or length"}
+		return
+	}
+	b = bytes[offset]
+	offset++
+	if b&0x80 == 0 {
+		// The length is encoded in the bottom 7 bits.
+		ret.length = int(b & 0x7f)
+	} else {
+		// Bottom 7 bits give the number of length bytes to follow.
+		numBytes := int(b & 0x7f)
+		// We risk overflowing a signed 32-bit number if we accept more than 3 bytes.
+		if numBytes > 3 {
+			err = StructuralError{"length too large"}
+			return
+		}
+		if numBytes == 0 {
+			err = SyntaxError{"indefinite length found (not DER)"}
+			return
+		}
+		ret.length = 0
+		for i := 0; i < numBytes; i++ {
+			if offset >= len(bytes) {
+				err = SyntaxError{"truncated tag or length"}
+				return
+			}
+			b = bytes[offset]
+			offset++
+			ret.length <<= 8
+			ret.length |= int(b)
+		}
+	}
+
+	return
+}
+
+// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse
+// a number of ASN.1 values from the given byte slice and returns them as a
+// slice of Go values of the given type.
+func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) {
+	expectedTag, compoundType, ok := getUniversalType(elemType)
+	if !ok {
+		err = StructuralError{"unknown Go type for slice"}
+		return
+	}
+
+	// First we iterate over the input and count the number of elements,
+	// checking that the types are correct in each case.
+	numElements := 0
+	for offset := 0; offset < len(bytes); {
+		var t tagAndLength
+		t, offset, err = parseTagAndLength(bytes, offset)
+		if err != nil {
+			return
+		}
+		// We pretend that GENERAL STRINGs are PRINTABLE STRINGs so
+		// that a sequence of them can be parsed into a []string.
+		if t.tag == tagGeneralString {
+			t.tag = tagPrintableString
+		}
+		if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag {
+			err = StructuralError{"sequence tag mismatch"}
+			return
+		}
+		if invalidLength(offset, t.length, len(bytes)) {
+			err = SyntaxError{"truncated sequence"}
+			return
+		}
+		offset += t.length
+		numElements++
+	}
+	ret = reflect.MakeSlice(sliceType, numElements, numElements)
+	params := fieldParameters{}
+	offset := 0
+	for i := 0; i < numElements; i++ {
+		offset, err = parseField(ret.Index(i), bytes, offset, params)
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+var (
+	bitStringType        = reflect.TypeOf(BitString{})
+	objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
+	enumeratedType       = reflect.TypeOf(Enumerated(0))
+	flagType             = reflect.TypeOf(Flag(false))
+	timeType             = reflect.TypeOf(time.Time{})
+	rawValueType         = reflect.TypeOf(RawValue{})
+	rawContentsType      = reflect.TypeOf(RawContent(nil))
+	bigIntType           = reflect.TypeOf(new(big.Int))
+)
+
+// invalidLength returns true iff offset + length > sliceLength, or if the
+// addition would overflow.
+func invalidLength(offset, length, sliceLength int) bool {
+	return offset+length < offset || offset+length > sliceLength
+}
+
+// parseField is the main parsing function. Given a byte slice and an offset
+// into the array, it will try to parse a suitable ASN.1 value out and store it
+// in the given Value.
+func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) {
+	offset = initOffset
+	fieldType := v.Type()
+
+	// If we have run out of data, it may be that there are optional elements at the end.
+	if offset == len(bytes) {
+		if !setDefaultValue(v, params) {
+			err = SyntaxError{"sequence truncated"}
+		}
+		return
+	}
+
+	// Deal with raw values.
+	if fieldType == rawValueType {
+		var t tagAndLength
+		t, offset, err = parseTagAndLength(bytes, offset)
+		if err != nil {
+			return
+		}
+		if invalidLength(offset, t.length, len(bytes)) {
+			err = SyntaxError{"data truncated"}
+			return
+		}
+		result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]}
+		offset += t.length
+		v.Set(reflect.ValueOf(result))
+		return
+	}
+
+	// Deal with the ANY type.
+	if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 {
+		var t tagAndLength
+		t, offset, err = parseTagAndLength(bytes, offset)
+		if err != nil {
+			return
+		}
+		if invalidLength(offset, t.length, len(bytes)) {
+			err = SyntaxError{"data truncated"}
+			return
+		}
+		var result interface{}
+		if !t.isCompound && t.class == classUniversal {
+			innerBytes := bytes[offset : offset+t.length]
+			switch t.tag {
+			case tagPrintableString:
+				result, err = parsePrintableString(innerBytes)
+			case tagIA5String:
+				result, err = parseIA5String(innerBytes)
+			case tagT61String:
+				result, err = parseT61String(innerBytes)
+			case tagUTF8String:
+				result, err = parseUTF8String(innerBytes)
+			case tagInteger:
+				result, err = parseInt64(innerBytes)
+			case tagBitString:
+				result, err = parseBitString(innerBytes)
+			case tagOID:
+				result, err = parseObjectIdentifier(innerBytes)
+			case tagUTCTime:
+				result, err = parseUTCTime(innerBytes)
+			case tagOctetString:
+				result = innerBytes
+			default:
+				// If we don't know how to handle the type, we just leave Value as nil.
+			}
+		}
+		offset += t.length
+		if err != nil {
+			return
+		}
+		if result != nil {
+			v.Set(reflect.ValueOf(result))
+		}
+		return
+	}
+	universalTag, compoundType, ok1 := getUniversalType(fieldType)
+	if !ok1 {
+		err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)}
+		return
+	}
+
+	t, offset, err := parseTagAndLength(bytes, offset)
+	if err != nil {
+		return
+	}
+	if params.explicit {
+		expectedClass := classContextSpecific
+		if params.application {
+			expectedClass = classApplication
+		}
+		if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
+			if t.length > 0 {
+				t, offset, err = parseTagAndLength(bytes, offset)
+				if err != nil {
+					return
+				}
+			} else {
+				if fieldType != flagType {
+					err = StructuralError{"Zero length explicit tag was not an asn1.Flag"}
+					return
+				}
+				v.SetBool(true)
+				return
+			}
+		} else {
+			// The tags didn't match, it might be an optional element.
+			ok := setDefaultValue(v, params)
+			if ok {
+				offset = initOffset
+			} else {
+				err = StructuralError{"explicitly tagged member didn't match"}
+			}
+			return
+		}
+	}
+
+	// Special case for strings: all the ASN.1 string types map to the Go
+	// type string. getUniversalType returns the tag for PrintableString
+	// when it sees a string, so if we see a different string type on the
+	// wire, we change the universal type to match.
+	if universalTag == tagPrintableString {
+		switch t.tag {
+		case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
+			universalTag = t.tag
+		}
+	}
+
+	// Special case for time: UTCTime and GeneralizedTime both map to the
+	// Go type time.Time.
+	if universalTag == tagUTCTime && t.tag == tagGeneralizedTime {
+		universalTag = tagGeneralizedTime
+	}
+
+	expectedClass := classUniversal
+	expectedTag := universalTag
+
+	if !params.explicit && params.tag != nil {
+		expectedClass = classContextSpecific
+		expectedTag = *params.tag
+	}
+
+	if !params.explicit && params.application && params.tag != nil {
+		expectedClass = classApplication
+		expectedTag = *params.tag
+	}
+
+	// We have unwrapped any explicit tagging at this point.
+	if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType {
+		// Tags don't match. Again, it could be an optional element.
+		ok := setDefaultValue(v, params)
+		if ok {
+			offset = initOffset
+		} else {
+			err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)}
+		}
+		return
+	}
+	if invalidLength(offset, t.length, len(bytes)) {
+		err = SyntaxError{"data truncated"}
+		return
+	}
+	innerBytes := bytes[offset : offset+t.length]
+	offset += t.length
+
+	// We deal with the structures defined in this package first.
+	switch fieldType {
+	case objectIdentifierType:
+		newSlice, err1 := parseObjectIdentifier(innerBytes)
+		v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice)))
+		if err1 == nil {
+			reflect.Copy(v, reflect.ValueOf(newSlice))
+		}
+		err = err1
+		return
+	case bitStringType:
+		bs, err1 := parseBitString(innerBytes)
+		if err1 == nil {
+			v.Set(reflect.ValueOf(bs))
+		}
+		err = err1
+		return
+	case timeType:
+		var time time.Time
+		var err1 error
+		if universalTag == tagUTCTime {
+			time, err1 = parseUTCTime(innerBytes)
+		} else {
+			time, err1 = parseGeneralizedTime(innerBytes)
+		}
+		if err1 == nil {
+			v.Set(reflect.ValueOf(time))
+		}
+		err = err1
+		return
+	case enumeratedType:
+		parsedInt, err1 := parseInt(innerBytes)
+		if err1 == nil {
+			v.SetInt(int64(parsedInt))
+		}
+		err = err1
+		return
+	case flagType:
+		v.SetBool(true)
+		return
+	case bigIntType:
+		parsedInt := parseBigInt(innerBytes)
+		v.Set(reflect.ValueOf(parsedInt))
+		return
+	}
+	switch val := v; val.Kind() {
+	case reflect.Bool:
+		parsedBool, err1 := parseBool(innerBytes)
+		if err1 == nil {
+			val.SetBool(parsedBool)
+		}
+		err = err1
+		return
+	case reflect.Int, reflect.Int32:
+		parsedInt, err1 := parseInt(innerBytes)
+		if err1 == nil {
+			val.SetInt(int64(parsedInt))
+		}
+		err = err1
+		return
+	case reflect.Int64:
+		parsedInt, err1 := parseInt64(innerBytes)
+		if err1 == nil {
+			val.SetInt(parsedInt)
+		}
+		err = err1
+		return
+	// TODO(dfc) Add support for the remaining integer types
+	case reflect.Struct:
+		structType := fieldType
+
+		if structType.NumField() > 0 &&
+			structType.Field(0).Type == rawContentsType {
+			bytes := bytes[initOffset:offset]
+			val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
+		}
+
+		innerOffset := 0
+		for i := 0; i < structType.NumField(); i++ {
+			field := structType.Field(i)
+			if i == 0 && field.Type == rawContentsType {
+				continue
+			}
+			innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1")))
+			if err != nil {
+				return
+			}
+		}
+		// We allow extra bytes at the end of the SEQUENCE because
+		// adding elements to the end has been used in X.509 as the
+		// version numbers have increased.
+		return
+	case reflect.Slice:
+		sliceType := fieldType
+		if sliceType.Elem().Kind() == reflect.Uint8 {
+			val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
+			reflect.Copy(val, reflect.ValueOf(innerBytes))
+			return
+		}
+		newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
+		if err1 == nil {
+			val.Set(newSlice)
+		}
+		err = err1
+		return
+	case reflect.String:
+		var v string
+		switch universalTag {
+		case tagPrintableString:
+			v, err = parsePrintableString(innerBytes)
+		case tagIA5String:
+			v, err = parseIA5String(innerBytes)
+		case tagT61String:
+			v, err = parseT61String(innerBytes)
+		case tagUTF8String:
+			v, err = parseUTF8String(innerBytes)
+		case tagGeneralString:
+			// GeneralString is specified in ISO-2022/ECMA-35,
+			// A brief review suggests that it includes structures
+			// that allow the encoding to change midstring and
+			// such. We give up and pass it as an 8-bit string.
+			v, err = parseT61String(innerBytes)
+		default:
+			err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
+		}
+		if err == nil {
+			val.SetString(v)
+		}
+		return
+	}
+	err = StructuralError{"unsupported: " + v.Type().String()}
+	return
+}
+
+// setDefaultValue is used to install a default value, from a tag string, into
+// a Value. It is successful is the field was optional, even if a default value
+// wasn't provided or it failed to install it into the Value.
+func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
+	if !params.optional {
+		return
+	}
+	ok = true
+	if params.defaultValue == nil {
+		return
+	}
+	switch val := v; val.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		val.SetInt(*params.defaultValue)
+	}
+	return
+}
+
+// Unmarshal parses the DER-encoded ASN.1 data structure b
+// and uses the reflect package to fill in an arbitrary value pointed at by val.
+// Because Unmarshal uses the reflect package, the structs
+// being written to must use upper case field names.
+//
+// An ASN.1 INTEGER can be written to an int, int32, int64,
+// or *big.Int (from the math/big package).
+// If the encoded value does not fit in the Go type,
+// Unmarshal returns a parse error.
+//
+// An ASN.1 BIT STRING can be written to a BitString.
+//
+// An ASN.1 OCTET STRING can be written to a []byte.
+//
+// An ASN.1 OBJECT IDENTIFIER can be written to an
+// ObjectIdentifier.
+//
+// An ASN.1 ENUMERATED can be written to an Enumerated.
+//
+// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a time.Time.
+//
+// An ASN.1 PrintableString or IA5String can be written to a string.
+//
+// Any of the above ASN.1 values can be written to an interface{}.
+// The value stored in the interface has the corresponding Go type.
+// For integers, that type is int64.
+//
+// An ASN.1 SEQUENCE OF x or SET OF x can be written
+// to a slice if an x can be written to the slice's element type.
+//
+// An ASN.1 SEQUENCE or SET can be written to a struct
+// if each of the elements in the sequence can be
+// written to the corresponding element in the struct.
+//
+// The following tags on struct fields have special meaning to Unmarshal:
+//
+//	optional		marks the field as ASN.1 OPTIONAL
+//	[explicit] tag:x	specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC
+//	default:x		sets the default value for optional integer fields
+//
+// If the type of the first field of a structure is RawContent then the raw
+// ASN1 contents of the struct will be stored in it.
+//
+// Other ASN.1 types are not supported; if it encounters them,
+// Unmarshal returns a parse error.
+func Unmarshal(b []byte, val interface{}) (rest []byte, err error) {
+	return UnmarshalWithParams(b, val, "")
+}
+
+// UnmarshalWithParams allows field parameters to be specified for the
+// top-level element. The form of the params is the same as the field tags.
+func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) {
+	v := reflect.ValueOf(val).Elem()
+	offset, err := parseField(v, b, 0, parseFieldParameters(params))
+	if err != nil {
+		return nil, err
+	}
+	return b[offset:], nil
+}
diff --git a/src/pkg/encoding/asn1/asn1_test.go b/src/pkg/encoding/asn1/asn1_test.go
new file mode 100644
index 0000000..92c9eb6
--- /dev/null
+++ b/src/pkg/encoding/asn1/asn1_test.go
@@ -0,0 +1,706 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package asn1
+
+import (
+	"bytes"
+	"math/big"
+	"reflect"
+	"testing"
+	"time"
+)
+
+type int64Test struct {
+	in  []byte
+	ok  bool
+	out int64
+}
+
+var int64TestData = []int64Test{
+	{[]byte{0x00}, true, 0},
+	{[]byte{0x7f}, true, 127},
+	{[]byte{0x00, 0x80}, true, 128},
+	{[]byte{0x01, 0x00}, true, 256},
+	{[]byte{0x80}, true, -128},
+	{[]byte{0xff, 0x7f}, true, -129},
+	{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, true, -1},
+	{[]byte{0xff}, true, -1},
+	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808},
+	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0},
+}
+
+func TestParseInt64(t *testing.T) {
+	for i, test := range int64TestData {
+		ret, err := parseInt64(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if test.ok && ret != test.out {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+		}
+	}
+}
+
+type int32Test struct {
+	in  []byte
+	ok  bool
+	out int32
+}
+
+var int32TestData = []int32Test{
+	{[]byte{0x00}, true, 0},
+	{[]byte{0x7f}, true, 127},
+	{[]byte{0x00, 0x80}, true, 128},
+	{[]byte{0x01, 0x00}, true, 256},
+	{[]byte{0x80}, true, -128},
+	{[]byte{0xff, 0x7f}, true, -129},
+	{[]byte{0xff, 0xff, 0xff, 0xff}, true, -1},
+	{[]byte{0xff}, true, -1},
+	{[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648},
+	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0},
+}
+
+func TestParseInt32(t *testing.T) {
+	for i, test := range int32TestData {
+		ret, err := parseInt(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if test.ok && int32(ret) != test.out {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+		}
+	}
+}
+
+var bigIntTests = []struct {
+	in     []byte
+	base10 string
+}{
+	{[]byte{0xff}, "-1"},
+	{[]byte{0x00}, "0"},
+	{[]byte{0x01}, "1"},
+	{[]byte{0x00, 0xff}, "255"},
+	{[]byte{0xff, 0x00}, "-256"},
+	{[]byte{0x01, 0x00}, "256"},
+}
+
+func TestParseBigInt(t *testing.T) {
+	for i, test := range bigIntTests {
+		ret := parseBigInt(test.in)
+		if ret.String() != test.base10 {
+			t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10)
+		}
+		fw := newForkableWriter()
+		marshalBigInt(fw, ret)
+		result := fw.Bytes()
+		if !bytes.Equal(result, test.in) {
+			t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in)
+		}
+	}
+}
+
+type bitStringTest struct {
+	in        []byte
+	ok        bool
+	out       []byte
+	bitLength int
+}
+
+var bitStringTestData = []bitStringTest{
+	{[]byte{}, false, []byte{}, 0},
+	{[]byte{0x00}, true, []byte{}, 0},
+	{[]byte{0x07, 0x00}, true, []byte{0x00}, 1},
+	{[]byte{0x07, 0x01}, false, []byte{}, 0},
+	{[]byte{0x07, 0x40}, false, []byte{}, 0},
+	{[]byte{0x08, 0x00}, false, []byte{}, 0},
+}
+
+func TestBitString(t *testing.T) {
+	for i, test := range bitStringTestData {
+		ret, err := parseBitString(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if err == nil {
+			if test.bitLength != ret.BitLength || bytes.Compare(ret.Bytes, test.out) != 0 {
+				t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength)
+			}
+		}
+	}
+}
+
+func TestBitStringAt(t *testing.T) {
+	bs := BitString{[]byte{0x82, 0x40}, 16}
+	if bs.At(0) != 1 {
+		t.Error("#1: Failed")
+	}
+	if bs.At(1) != 0 {
+		t.Error("#2: Failed")
+	}
+	if bs.At(6) != 1 {
+		t.Error("#3: Failed")
+	}
+	if bs.At(9) != 1 {
+		t.Error("#4: Failed")
+	}
+}
+
+type bitStringRightAlignTest struct {
+	in    []byte
+	inlen int
+	out   []byte
+}
+
+var bitStringRightAlignTests = []bitStringRightAlignTest{
+	{[]byte{0x80}, 1, []byte{0x01}},
+	{[]byte{0x80, 0x80}, 9, []byte{0x01, 0x01}},
+	{[]byte{}, 0, []byte{}},
+	{[]byte{0xce}, 8, []byte{0xce}},
+	{[]byte{0xce, 0x47}, 16, []byte{0xce, 0x47}},
+	{[]byte{0x34, 0x50}, 12, []byte{0x03, 0x45}},
+}
+
+func TestBitStringRightAlign(t *testing.T) {
+	for i, test := range bitStringRightAlignTests {
+		bs := BitString{test.in, test.inlen}
+		out := bs.RightAlign()
+		if bytes.Compare(out, test.out) != 0 {
+			t.Errorf("#%d got: %x want: %x", i, out, test.out)
+		}
+	}
+}
+
+type objectIdentifierTest struct {
+	in  []byte
+	ok  bool
+	out []int
+}
+
+var objectIdentifierTestData = []objectIdentifierTest{
+	{[]byte{}, false, []int{}},
+	{[]byte{85}, true, []int{2, 5}},
+	{[]byte{85, 0x02}, true, []int{2, 5, 2}},
+	{[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
+	{[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
+}
+
+func TestObjectIdentifier(t *testing.T) {
+	for i, test := range objectIdentifierTestData {
+		ret, err := parseObjectIdentifier(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if err == nil {
+			if !reflect.DeepEqual(test.out, ret) {
+				t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+			}
+		}
+	}
+}
+
+type timeTest struct {
+	in  string
+	ok  bool
+	out time.Time
+}
+
+var utcTestData = []timeTest{
+	{"910506164540-0700", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", -7*60*60))},
+	{"910506164540+0730", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", 7*60*60+30*60))},
+	{"910506234540Z", true, time.Date(1991, 05, 06, 23, 45, 40, 0, time.UTC)},
+	{"9105062345Z", true, time.Date(1991, 05, 06, 23, 45, 0, 0, time.UTC)},
+	{"a10506234540Z", false, time.Time{}},
+	{"91a506234540Z", false, time.Time{}},
+	{"9105a6234540Z", false, time.Time{}},
+	{"910506a34540Z", false, time.Time{}},
+	{"910506334a40Z", false, time.Time{}},
+	{"91050633444aZ", false, time.Time{}},
+	{"910506334461Z", false, time.Time{}},
+	{"910506334400Za", false, time.Time{}},
+}
+
+func TestUTCTime(t *testing.T) {
+	for i, test := range utcTestData {
+		ret, err := parseUTCTime([]byte(test.in))
+		if err != nil {
+			if test.ok {
+				t.Errorf("#%d: parseUTCTime(%q) = error %v", i, test.in, err)
+			}
+			continue
+		}
+		if !test.ok {
+			t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i, test.in)
+			continue
+		}
+		const format = "Jan _2 15:04:05 -0700 2006" // ignore zone name, just offset
+		have := ret.Format(format)
+		want := test.out.Format(format)
+		if have != want {
+			t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", i, test.in, have, want)
+		}
+	}
+}
+
+var generalizedTimeTestData = []timeTest{
+	{"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)},
+	{"20100102030405", false, time.Time{}},
+	{"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
+	{"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
+}
+
+func TestGeneralizedTime(t *testing.T) {
+	for i, test := range generalizedTimeTestData {
+		ret, err := parseGeneralizedTime([]byte(test.in))
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if err == nil {
+			if !reflect.DeepEqual(test.out, ret) {
+				t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+			}
+		}
+	}
+}
+
+type tagAndLengthTest struct {
+	in  []byte
+	ok  bool
+	out tagAndLength
+}
+
+var tagAndLengthData = []tagAndLengthTest{
+	{[]byte{0x80, 0x01}, true, tagAndLength{2, 0, 1, false}},
+	{[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}},
+	{[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}},
+	{[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}},
+	{[]byte{0x1f, 0x01, 0x00}, true, tagAndLength{0, 1, 0, false}},
+	{[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}},
+	{[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}},
+	{[]byte{0x00, 0x81, 0x01}, true, tagAndLength{0, 0, 1, false}},
+	{[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}},
+	{[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}},
+	{[]byte{0x1f, 0x85}, false, tagAndLength{}},
+	{[]byte{0x30, 0x80}, false, tagAndLength{}},
+}
+
+func TestParseTagAndLength(t *testing.T) {
+	for i, test := range tagAndLengthData {
+		tagAndLength, _, err := parseTagAndLength(test.in, 0)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok)
+		}
+		if err == nil && !reflect.DeepEqual(test.out, tagAndLength) {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out)
+		}
+	}
+}
+
+type parseFieldParametersTest struct {
+	in  string
+	out fieldParameters
+}
+
+func newInt(n int) *int { return &n }
+
+func newInt64(n int64) *int64 { return &n }
+
+func newString(s string) *string { return &s }
+
+func newBool(b bool) *bool { return &b }
+
+var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{
+	{"", fieldParameters{}},
+	{"ia5", fieldParameters{stringType: tagIA5String}},
+	{"printable", fieldParameters{stringType: tagPrintableString}},
+	{"optional", fieldParameters{optional: true}},
+	{"explicit", fieldParameters{explicit: true, tag: new(int)}},
+	{"application", fieldParameters{application: true, tag: new(int)}},
+	{"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}},
+	{"default:42", fieldParameters{defaultValue: newInt64(42)}},
+	{"tag:17", fieldParameters{tag: newInt(17)}},
+	{"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}},
+	{"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, false}},
+	{"set", fieldParameters{set: true}},
+}
+
+func TestParseFieldParameters(t *testing.T) {
+	for i, test := range parseFieldParametersTestData {
+		f := parseFieldParameters(test.in)
+		if !reflect.DeepEqual(f, test.out) {
+			t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out)
+		}
+	}
+}
+
+type TestObjectIdentifierStruct struct {
+	OID ObjectIdentifier
+}
+
+type TestContextSpecificTags struct {
+	A int `asn1:"tag:1"`
+}
+
+type TestContextSpecificTags2 struct {
+	A int `asn1:"explicit,tag:1"`
+	B int
+}
+
+type TestElementsAfterString struct {
+	S    string
+	A, B int
+}
+
+type TestBigInt struct {
+	X *big.Int
+}
+
+var unmarshalTestData = []struct {
+	in  []byte
+	out interface{}
+}{
+	{[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
+	{[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
+	{[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
+	{[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}},
+	{[]byte{0x02, 0x01, 0x10}, newInt(16)},
+	{[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")},
+	{[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")},
+	{[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}},
+	{[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}},
+	{[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}},
+	{[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}},
+	{[]byte{0x01, 0x01, 0x00}, newBool(false)},
+	{[]byte{0x01, 0x01, 0x01}, newBool(true)},
+	{[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
+	{[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}},
+}
+
+func TestUnmarshal(t *testing.T) {
+	for i, test := range unmarshalTestData {
+		pv := reflect.New(reflect.TypeOf(test.out).Elem())
+		val := pv.Interface()
+		_, err := Unmarshal(test.in, val)
+		if err != nil {
+			t.Errorf("Unmarshal failed at index %d %v", i, err)
+		}
+		if !reflect.DeepEqual(val, test.out) {
+			t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out)
+		}
+	}
+}
+
+type Certificate struct {
+	TBSCertificate     TBSCertificate
+	SignatureAlgorithm AlgorithmIdentifier
+	SignatureValue     BitString
+}
+
+type TBSCertificate struct {
+	Version            int `asn1:"optional,explicit,default:0,tag:0"`
+	SerialNumber       RawValue
+	SignatureAlgorithm AlgorithmIdentifier
+	Issuer             RDNSequence
+	Validity           Validity
+	Subject            RDNSequence
+	PublicKey          PublicKeyInfo
+}
+
+type AlgorithmIdentifier struct {
+	Algorithm ObjectIdentifier
+}
+
+type RDNSequence []RelativeDistinguishedNameSET
+
+type RelativeDistinguishedNameSET []AttributeTypeAndValue
+
+type AttributeTypeAndValue struct {
+	Type  ObjectIdentifier
+	Value interface{}
+}
+
+type Validity struct {
+	NotBefore, NotAfter time.Time
+}
+
+type PublicKeyInfo struct {
+	Algorithm AlgorithmIdentifier
+	PublicKey BitString
+}
+
+func TestCertificate(t *testing.T) {
+	// This is a minimal, self-signed certificate that should parse correctly.
+	var cert Certificate
+	if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil {
+		t.Errorf("Unmarshal failed: %v", err)
+	}
+	if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) {
+		t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert)
+	}
+}
+
+func TestCertificateWithNUL(t *testing.T) {
+	// This is the paypal NUL-hack certificate. It should fail to parse because
+	// NUL isn't a permitted character in a PrintableString.
+
+	var cert Certificate
+	if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil {
+		t.Error("Unmarshal succeeded, should not have")
+	}
+}
+
+type rawStructTest struct {
+	Raw RawContent
+	A   int
+}
+
+func TestRawStructs(t *testing.T) {
+	var s rawStructTest
+	input := []byte{0x30, 0x03, 0x02, 0x01, 0x50}
+
+	rest, err := Unmarshal(input, &s)
+	if len(rest) != 0 {
+		t.Errorf("incomplete parse: %x", rest)
+		return
+	}
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	if s.A != 0x50 {
+		t.Errorf("bad value for A: got %d want %d", s.A, 0x50)
+	}
+	if bytes.Compare([]byte(s.Raw), input) != 0 {
+		t.Errorf("bad value for Raw: got %x want %x", s.Raw, input)
+	}
+}
+
+var derEncodedSelfSignedCert = Certificate{
+	TBSCertificate: TBSCertificate{
+		Version:            0,
+		SerialNumber:       RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}},
+		SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
+		Issuer: RDNSequence{
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false at example.com"}},
+		},
+		Validity: Validity{
+			NotBefore: time.Date(2009, 10, 8, 00, 25, 53, 0, time.UTC),
+			NotAfter:  time.Date(2010, 10, 8, 00, 25, 53, 0, time.UTC),
+		},
+		Subject: RDNSequence{
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
+			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false at example.com"}},
+		},
+		PublicKey: PublicKeyInfo{
+			Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}},
+			PublicKey: BitString{
+				Bytes: []uint8{
+					0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7,
+					0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42,
+					0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4,
+					0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2,
+					0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f,
+					0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec,
+					0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1,
+				},
+				BitLength: 592,
+			},
+		},
+	},
+	SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
+	SignatureValue: BitString{
+		Bytes: []uint8{
+			0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce,
+			0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c,
+			0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b,
+			0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8,
+			0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa,
+			0xfa, 0x88, 0x21, 0x49, 0x4, 0x35,
+		},
+		BitLength: 512,
+	},
+}
+
+var derEncodedSelfSignedCertBytes = []byte{
+	0x30, 0x82, 0x02, 0x18, 0x30,
+	0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c,
+	0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+	0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+	0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+	0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+	0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43,
+	0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+	0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+	0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31,
+	0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c,
+	0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+	0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+	0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78,
+	0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
+	0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a,
+	0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35,
+	0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+	0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+	0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+	0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69,
+	0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
+	0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+	0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a,
+	0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73,
+	0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
+	0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+	0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61,
+	0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06,
+	0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+	0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78,
+	0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c,
+	0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea,
+	0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88,
+	0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45,
+	0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d,
+	0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+	0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4,
+	0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd,
+	0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4,
+	0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14,
+	0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49,
+	0x04, 0x35,
+}
+
+var derEncodedPaypalNULCertBytes = []byte{
+	0x30, 0x82, 0x06, 0x44, 0x30,
+	0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b,
+	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+	0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+	0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+	0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61,
+	0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61,
+	0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03,
+	0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74,
+	0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74,
+	0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e,
+	0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65,
+	0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d,
+	0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36,
+	0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03,
+	0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c,
+	0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
+	0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+	0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
+	0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
+	0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
+	0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70,
+	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39,
+	0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d,
+	0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a,
+	0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+	0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+	0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
+	0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20,
+	0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f,
+	0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
+	0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
+	0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f,
+	0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e,
+	0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73,
+	0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
+	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+	0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+	0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69,
+	0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19,
+	0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e,
+	0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29,
+	0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41,
+	0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce,
+	0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96,
+	0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2,
+	0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10,
+	0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49,
+	0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00,
+	0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03,
+	0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86,
+	0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40,
+	0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8,
+	0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08,
+	0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55,
+	0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14,
+	0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e,
+	0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+	0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8,
+	0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
+	0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04,
+	0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40,
+	0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63,
+	0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+	0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e,
+	0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e,
+	0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76,
+	0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+	0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68,
+	0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
+	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60,
+	0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68,
+	0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
+	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
+	0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+	0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70,
+	0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61,
+	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30,
+	0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c,
+	0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37,
+	0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
+	0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
+	0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74,
+	0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
+	0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
+	0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63,
+	0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f,
+	0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
+	0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86,
+	0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74,
+	0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73,
+	0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32,
+	0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41,
+	0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06,
+	0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0,
+	0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
+	0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70,
+	0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
+	0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63,
+	0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74,
+	0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69,
+	0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
+	0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30,
+	0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c,
+	0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
+	0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+	0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63,
+	0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
+	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+	0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b,
+	0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa,
+	0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e,
+	0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d,
+	0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7,
+	0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1,
+	0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5,
+	0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07,
+	0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e,
+	0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43,
+	0x96, 0x07, 0xa8, 0xbb,
+}
diff --git a/src/pkg/encoding/asn1/common.go b/src/pkg/encoding/asn1/common.go
new file mode 100644
index 0000000..f7cb3ac
--- /dev/null
+++ b/src/pkg/encoding/asn1/common.go
@@ -0,0 +1,158 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package asn1
+
+import (
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// ASN.1 objects have metadata preceding them:
+//   the tag: the type of the object
+//   a flag denoting if this object is compound or not
+//   the class type: the namespace of the tag
+//   the length of the object, in bytes
+
+// Here are some standard tags and classes
+
+const (
+	tagBoolean         = 1
+	tagInteger         = 2
+	tagBitString       = 3
+	tagOctetString     = 4
+	tagOID             = 6
+	tagEnum            = 10
+	tagUTF8String      = 12
+	tagSequence        = 16
+	tagSet             = 17
+	tagPrintableString = 19
+	tagT61String       = 20
+	tagIA5String       = 22
+	tagUTCTime         = 23
+	tagGeneralizedTime = 24
+	tagGeneralString   = 27
+)
+
+const (
+	classUniversal       = 0
+	classApplication     = 1
+	classContextSpecific = 2
+	classPrivate         = 3
+)
+
+type tagAndLength struct {
+	class, tag, length int
+	isCompound         bool
+}
+
+// ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead
+// of" and "in addition to". When not specified, every primitive type has a
+// default tag in the UNIVERSAL class.
+//
+// For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1
+// doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT
+// CONTEXT-SPECIFIC 42], that means that the tag is replaced by another.
+//
+// On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an
+// /additional/ tag would wrap the default tag. This explicit tag will have the
+// compound flag set.
+//
+// (This is used in order to remove ambiguity with optional elements.)
+//
+// You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we
+// don't support that here. We support a single layer of EXPLICIT or IMPLICIT
+// tagging with tag strings on the fields of a structure.
+
+// fieldParameters is the parsed representation of tag string from a structure field.
+type fieldParameters struct {
+	optional     bool   // true iff the field is OPTIONAL
+	explicit     bool   // true iff an EXPLICIT tag is in use.
+	application  bool   // true iff an APPLICATION tag is in use.
+	defaultValue *int64 // a default value for INTEGER typed fields (maybe nil).
+	tag          *int   // the EXPLICIT or IMPLICIT tag (maybe nil).
+	stringType   int    // the string tag to use when marshaling.
+	set          bool   // true iff this should be encoded as a SET
+
+	// Invariants:
+	//   if explicit is set, tag is non-nil.
+}
+
+// Given a tag string with the format specified in the package comment,
+// parseFieldParameters will parse it into a fieldParameters structure,
+// ignoring unknown parts of the string.
+func parseFieldParameters(str string) (ret fieldParameters) {
+	for _, part := range strings.Split(str, ",") {
+		switch {
+		case part == "optional":
+			ret.optional = true
+		case part == "explicit":
+			ret.explicit = true
+			if ret.tag == nil {
+				ret.tag = new(int)
+			}
+		case part == "ia5":
+			ret.stringType = tagIA5String
+		case part == "printable":
+			ret.stringType = tagPrintableString
+		case strings.HasPrefix(part, "default:"):
+			i, err := strconv.ParseInt(part[8:], 10, 64)
+			if err == nil {
+				ret.defaultValue = new(int64)
+				*ret.defaultValue = i
+			}
+		case strings.HasPrefix(part, "tag:"):
+			i, err := strconv.Atoi(part[4:])
+			if err == nil {
+				ret.tag = new(int)
+				*ret.tag = i
+			}
+		case part == "set":
+			ret.set = true
+		case part == "application":
+			ret.application = true
+			if ret.tag == nil {
+				ret.tag = new(int)
+			}
+		}
+	}
+	return
+}
+
+// Given a reflected Go type, getUniversalType returns the default tag number
+// and expected compound flag.
+func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
+	switch t {
+	case objectIdentifierType:
+		return tagOID, false, true
+	case bitStringType:
+		return tagBitString, false, true
+	case timeType:
+		return tagUTCTime, false, true
+	case enumeratedType:
+		return tagEnum, false, true
+	case bigIntType:
+		return tagInteger, false, true
+	}
+	switch t.Kind() {
+	case reflect.Bool:
+		return tagBoolean, false, true
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return tagInteger, false, true
+	case reflect.Struct:
+		return tagSequence, true, true
+	case reflect.Slice:
+		if t.Elem().Kind() == reflect.Uint8 {
+			return tagOctetString, false, true
+		}
+		if strings.HasSuffix(t.Name(), "SET") {
+			return tagSet, true, true
+		}
+		return tagSequence, true, true
+	case reflect.String:
+		return tagPrintableString, false, true
+	}
+	return 0, false, false
+}
diff --git a/src/pkg/encoding/asn1/marshal.go b/src/pkg/encoding/asn1/marshal.go
new file mode 100644
index 0000000..c181e43
--- /dev/null
+++ b/src/pkg/encoding/asn1/marshal.go
@@ -0,0 +1,553 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package asn1
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"math/big"
+	"reflect"
+	"time"
+)
+
+// A forkableWriter is an in-memory buffer that can be
+// 'forked' to create new forkableWriters that bracket the
+// original.  After
+//    pre, post := w.fork();
+// the overall sequence of bytes represented is logically w+pre+post.
+type forkableWriter struct {
+	*bytes.Buffer
+	pre, post *forkableWriter
+}
+
+func newForkableWriter() *forkableWriter {
+	return &forkableWriter{bytes.NewBuffer(nil), nil, nil}
+}
+
+func (f *forkableWriter) fork() (pre, post *forkableWriter) {
+	if f.pre != nil || f.post != nil {
+		panic("have already forked")
+	}
+	f.pre = newForkableWriter()
+	f.post = newForkableWriter()
+	return f.pre, f.post
+}
+
+func (f *forkableWriter) Len() (l int) {
+	l += f.Buffer.Len()
+	if f.pre != nil {
+		l += f.pre.Len()
+	}
+	if f.post != nil {
+		l += f.post.Len()
+	}
+	return
+}
+
+func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) {
+	n, err = out.Write(f.Bytes())
+	if err != nil {
+		return
+	}
+
+	var nn int
+
+	if f.pre != nil {
+		nn, err = f.pre.writeTo(out)
+		n += nn
+		if err != nil {
+			return
+		}
+	}
+
+	if f.post != nil {
+		nn, err = f.post.writeTo(out)
+		n += nn
+	}
+	return
+}
+
+func marshalBase128Int(out *forkableWriter, n int64) (err error) {
+	if n == 0 {
+		err = out.WriteByte(0)
+		return
+	}
+
+	l := 0
+	for i := n; i > 0; i >>= 7 {
+		l++
+	}
+
+	for i := l - 1; i >= 0; i-- {
+		o := byte(n >> uint(i*7))
+		o &= 0x7f
+		if i != 0 {
+			o |= 0x80
+		}
+		err = out.WriteByte(o)
+		if err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func marshalInt64(out *forkableWriter, i int64) (err error) {
+	n := int64Length(i)
+
+	for ; n > 0; n-- {
+		err = out.WriteByte(byte(i >> uint((n-1)*8)))
+		if err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func int64Length(i int64) (numBytes int) {
+	numBytes = 1
+
+	for i > 127 {
+		numBytes++
+		i >>= 8
+	}
+
+	for i < -128 {
+		numBytes++
+		i >>= 8
+	}
+
+	return
+}
+
+func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
+	if n.Sign() < 0 {
+		// A negative number has to be converted to two's-complement
+		// form. So we'll subtract 1 and invert. If the
+		// most-significant-bit isn't set then we'll need to pad the
+		// beginning with 0xff in order to keep the number negative.
+		nMinus1 := new(big.Int).Neg(n)
+		nMinus1.Sub(nMinus1, bigOne)
+		bytes := nMinus1.Bytes()
+		for i := range bytes {
+			bytes[i] ^= 0xff
+		}
+		if len(bytes) == 0 || bytes[0]&0x80 == 0 {
+			err = out.WriteByte(0xff)
+			if err != nil {
+				return
+			}
+		}
+		_, err = out.Write(bytes)
+	} else if n.Sign() == 0 {
+		// Zero is written as a single 0 zero rather than no bytes.
+		err = out.WriteByte(0x00)
+	} else {
+		bytes := n.Bytes()
+		if len(bytes) > 0 && bytes[0]&0x80 != 0 {
+			// We'll have to pad this with 0x00 in order to stop it
+			// looking like a negative number.
+			err = out.WriteByte(0)
+			if err != nil {
+				return
+			}
+		}
+		_, err = out.Write(bytes)
+	}
+	return
+}
+
+func marshalLength(out *forkableWriter, i int) (err error) {
+	n := lengthLength(i)
+
+	for ; n > 0; n-- {
+		err = out.WriteByte(byte(i >> uint((n-1)*8)))
+		if err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func lengthLength(i int) (numBytes int) {
+	numBytes = 1
+	for i > 255 {
+		numBytes++
+		i >>= 8
+	}
+	return
+}
+
+func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
+	b := uint8(t.class) << 6
+	if t.isCompound {
+		b |= 0x20
+	}
+	if t.tag >= 31 {
+		b |= 0x1f
+		err = out.WriteByte(b)
+		if err != nil {
+			return
+		}
+		err = marshalBase128Int(out, int64(t.tag))
+		if err != nil {
+			return
+		}
+	} else {
+		b |= uint8(t.tag)
+		err = out.WriteByte(b)
+		if err != nil {
+			return
+		}
+	}
+
+	if t.length >= 128 {
+		l := lengthLength(t.length)
+		err = out.WriteByte(0x80 | byte(l))
+		if err != nil {
+			return
+		}
+		err = marshalLength(out, t.length)
+		if err != nil {
+			return
+		}
+	} else {
+		err = out.WriteByte(byte(t.length))
+		if err != nil {
+			return
+		}
+	}
+
+	return nil
+}
+
+func marshalBitString(out *forkableWriter, b BitString) (err error) {
+	paddingBits := byte((8 - b.BitLength%8) % 8)
+	err = out.WriteByte(paddingBits)
+	if err != nil {
+		return
+	}
+	_, err = out.Write(b.Bytes)
+	return
+}
+
+func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
+	if len(oid) < 2 || oid[0] > 6 || oid[1] >= 40 {
+		return StructuralError{"invalid object identifier"}
+	}
+
+	err = out.WriteByte(byte(oid[0]*40 + oid[1]))
+	if err != nil {
+		return
+	}
+	for i := 2; i < len(oid); i++ {
+		err = marshalBase128Int(out, int64(oid[i]))
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
+
+func marshalPrintableString(out *forkableWriter, s string) (err error) {
+	b := []byte(s)
+	for _, c := range b {
+		if !isPrintable(c) {
+			return StructuralError{"PrintableString contains invalid character"}
+		}
+	}
+
+	_, err = out.Write(b)
+	return
+}
+
+func marshalIA5String(out *forkableWriter, s string) (err error) {
+	b := []byte(s)
+	for _, c := range b {
+		if c > 127 {
+			return StructuralError{"IA5String contains invalid character"}
+		}
+	}
+
+	_, err = out.Write(b)
+	return
+}
+
+func marshalTwoDigits(out *forkableWriter, v int) (err error) {
+	err = out.WriteByte(byte('0' + (v/10)%10))
+	if err != nil {
+		return
+	}
+	return out.WriteByte(byte('0' + v%10))
+}
+
+func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
+	utc := t.UTC()
+	year, month, day := utc.Date()
+
+	switch {
+	case 1950 <= year && year < 2000:
+		err = marshalTwoDigits(out, int(year-1900))
+	case 2000 <= year && year < 2050:
+		err = marshalTwoDigits(out, int(year-2000))
+	default:
+		return StructuralError{"Cannot represent time as UTCTime"}
+	}
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, int(month))
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, day)
+	if err != nil {
+		return
+	}
+
+	hour, min, sec := utc.Clock()
+
+	err = marshalTwoDigits(out, hour)
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, min)
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, sec)
+	if err != nil {
+		return
+	}
+
+	_, offset := t.Zone()
+
+	switch {
+	case offset/60 == 0:
+		err = out.WriteByte('Z')
+		return
+	case offset > 0:
+		err = out.WriteByte('+')
+	case offset < 0:
+		err = out.WriteByte('-')
+	}
+
+	if err != nil {
+		return
+	}
+
+	offsetMinutes := offset / 60
+	if offsetMinutes < 0 {
+		offsetMinutes = -offsetMinutes
+	}
+
+	err = marshalTwoDigits(out, offsetMinutes/60)
+	if err != nil {
+		return
+	}
+
+	err = marshalTwoDigits(out, offsetMinutes%60)
+	return
+}
+
+func stripTagAndLength(in []byte) []byte {
+	_, offset, err := parseTagAndLength(in, 0)
+	if err != nil {
+		return in
+	}
+	return in[offset:]
+}
+
+func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
+	switch value.Type() {
+	case timeType:
+		return marshalUTCTime(out, value.Interface().(time.Time))
+	case bitStringType:
+		return marshalBitString(out, value.Interface().(BitString))
+	case objectIdentifierType:
+		return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
+	case bigIntType:
+		return marshalBigInt(out, value.Interface().(*big.Int))
+	}
+
+	switch v := value; v.Kind() {
+	case reflect.Bool:
+		if v.Bool() {
+			return out.WriteByte(255)
+		} else {
+			return out.WriteByte(0)
+		}
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return marshalInt64(out, int64(v.Int()))
+	case reflect.Struct:
+		t := v.Type()
+
+		startingField := 0
+
+		// If the first element of the structure is a non-empty
+		// RawContents, then we don't bother serializing the rest.
+		if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
+			s := v.Field(0)
+			if s.Len() > 0 {
+				bytes := make([]byte, s.Len())
+				for i := 0; i < s.Len(); i++ {
+					bytes[i] = uint8(s.Index(i).Uint())
+				}
+				/* The RawContents will contain the tag and
+				 * length fields but we'll also be writing
+				 * those ourselves, so we strip them out of
+				 * bytes */
+				_, err = out.Write(stripTagAndLength(bytes))
+				return
+			} else {
+				startingField = 1
+			}
+		}
+
+		for i := startingField; i < t.NumField(); i++ {
+			var pre *forkableWriter
+			pre, out = out.fork()
+			err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
+			if err != nil {
+				return
+			}
+		}
+		return
+	case reflect.Slice:
+		sliceType := v.Type()
+		if sliceType.Elem().Kind() == reflect.Uint8 {
+			bytes := make([]byte, v.Len())
+			for i := 0; i < v.Len(); i++ {
+				bytes[i] = uint8(v.Index(i).Uint())
+			}
+			_, err = out.Write(bytes)
+			return
+		}
+
+		var params fieldParameters
+		for i := 0; i < v.Len(); i++ {
+			var pre *forkableWriter
+			pre, out = out.fork()
+			err = marshalField(pre, v.Index(i), params)
+			if err != nil {
+				return
+			}
+		}
+		return
+	case reflect.String:
+		if params.stringType == tagIA5String {
+			return marshalIA5String(out, v.String())
+		} else {
+			return marshalPrintableString(out, v.String())
+		}
+		return
+	}
+
+	return StructuralError{"unknown Go type"}
+}
+
+func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
+	// If the field is an interface{} then recurse into it.
+	if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
+		return marshalField(out, v.Elem(), params)
+	}
+
+	if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
+		return
+	}
+
+	if v.Type() == rawValueType {
+		rv := v.Interface().(RawValue)
+		if len(rv.FullBytes) != 0 {
+			_, err = out.Write(rv.FullBytes)
+		} else {
+			err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
+			if err != nil {
+				return
+			}
+			_, err = out.Write(rv.Bytes)
+		}
+		return
+	}
+
+	tag, isCompound, ok := getUniversalType(v.Type())
+	if !ok {
+		err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
+		return
+	}
+	class := classUniversal
+
+	if params.stringType != 0 {
+		if tag != tagPrintableString {
+			return StructuralError{"Explicit string type given to non-string member"}
+		}
+		tag = params.stringType
+	}
+
+	if params.set {
+		if tag != tagSequence {
+			return StructuralError{"Non sequence tagged as set"}
+		}
+		tag = tagSet
+	}
+
+	tags, body := out.fork()
+
+	err = marshalBody(body, v, params)
+	if err != nil {
+		return
+	}
+
+	bodyLen := body.Len()
+
+	var explicitTag *forkableWriter
+	if params.explicit {
+		explicitTag, tags = tags.fork()
+	}
+
+	if !params.explicit && params.tag != nil {
+		// implicit tag.
+		tag = *params.tag
+		class = classContextSpecific
+	}
+
+	err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
+	if err != nil {
+		return
+	}
+
+	if params.explicit {
+		err = marshalTagAndLength(explicitTag, tagAndLength{
+			class:      classContextSpecific,
+			tag:        *params.tag,
+			length:     bodyLen + tags.Len(),
+			isCompound: true,
+		})
+	}
+
+	return nil
+}
+
+// Marshal returns the ASN.1 encoding of val.
+func Marshal(val interface{}) ([]byte, error) {
+	var out bytes.Buffer
+	v := reflect.ValueOf(val)
+	f := newForkableWriter()
+	err := marshalField(f, v, fieldParameters{})
+	if err != nil {
+		return nil, err
+	}
+	_, err = f.writeTo(&out)
+	return out.Bytes(), nil
+}
diff --git a/src/pkg/encoding/asn1/marshal_test.go b/src/pkg/encoding/asn1/marshal_test.go
new file mode 100644
index 0000000..a7447f9
--- /dev/null
+++ b/src/pkg/encoding/asn1/marshal_test.go
@@ -0,0 +1,133 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package asn1
+
+import (
+	"bytes"
+	"encoding/hex"
+	"math/big"
+	"testing"
+	"time"
+)
+
+type intStruct struct {
+	A int
+}
+
+type twoIntStruct struct {
+	A int
+	B int
+}
+
+type bigIntStruct struct {
+	A *big.Int
+}
+
+type nestedStruct struct {
+	A intStruct
+}
+
+type rawContentsStruct struct {
+	Raw RawContent
+	A   int
+}
+
+type implicitTagTest struct {
+	A int `asn1:"implicit,tag:5"`
+}
+
+type explicitTagTest struct {
+	A int `asn1:"explicit,tag:5"`
+}
+
+type ia5StringTest struct {
+	A string `asn1:"ia5"`
+}
+
+type printableStringTest struct {
+	A string `asn1:"printable"`
+}
+
+type optionalRawValueTest struct {
+	A RawValue `asn1:"optional"`
+}
+
+type testSET []int
+
+var PST = time.FixedZone("PST", -8*60*60)
+
+type marshalTest struct {
+	in  interface{}
+	out string // hex encoded
+}
+
+var marshalTests = []marshalTest{
+	{10, "02010a"},
+	{127, "02017f"},
+	{128, "02020080"},
+	{-128, "020180"},
+	{-129, "0202ff7f"},
+	{intStruct{64}, "3003020140"},
+	{bigIntStruct{big.NewInt(0x123456)}, "30050203123456"},
+	{twoIntStruct{64, 65}, "3006020140020141"},
+	{nestedStruct{intStruct{127}}, "3005300302017f"},
+	{[]byte{1, 2, 3}, "0403010203"},
+	{implicitTagTest{64}, "3003850140"},
+	{explicitTagTest{64}, "3005a503020140"},
+	{time.Unix(0, 0).UTC(), "170d3730303130313030303030305a"},
+	{time.Unix(1258325776, 0).UTC(), "170d3039313131353232353631365a"},
+	{time.Unix(1258325776, 0).In(PST), "17113039313131353232353631362d30383030"},
+	{BitString{[]byte{0x80}, 1}, "03020780"},
+	{BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"},
+	{ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"},
+	{ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"},
+	{"test", "130474657374"},
+	{
+		"" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 127 times 'x'
+		"137f" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"78787878787878787878787878787878787878787878787878787878787878",
+	},
+	{
+		"" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+			"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 128 times 'x'
+		"138180" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878" +
+			"7878787878787878787878787878787878787878787878787878787878787878",
+	},
+	{ia5StringTest{"test"}, "3006160474657374"},
+	{optionalRawValueTest{}, "3000"},
+	{printableStringTest{"test"}, "3006130474657374"},
+	{printableStringTest{"test*"}, "30071305746573742a"},
+	{rawContentsStruct{nil, 64}, "3003020140"},
+	{rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"},
+	{RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"},
+	{testSET([]int{10}), "310302010a"},
+}
+
+func TestMarshal(t *testing.T) {
+	for i, test := range marshalTests {
+		data, err := Marshal(test.in)
+		if err != nil {
+			t.Errorf("#%d failed: %s", i, err)
+		}
+		out, _ := hex.DecodeString(test.out)
+		if bytes.Compare(out, data) != 0 {
+			t.Errorf("#%d got: %x want %x\n\t%q\n\t%q", i, data, out, data, out)
+
+		}
+	}
+}
diff --git a/src/pkg/encoding/base32/base32.go b/src/pkg/encoding/base32/base32.go
index acace30..c75c7c1 100644
--- a/src/pkg/encoding/base32/base32.go
+++ b/src/pkg/encoding/base32/base32.go
@@ -7,7 +7,6 @@ package base32
 
 import (
 	"io"
-	"os"
 	"strconv"
 )
 
@@ -127,7 +126,7 @@ func (enc *Encoding) Encode(dst, src []byte) {
 }
 
 type encoder struct {
-	err  os.Error
+	err  error
 	enc  *Encoding
 	w    io.Writer
 	buf  [5]byte    // buffered data waiting to be encoded
@@ -135,7 +134,7 @@ type encoder struct {
 	out  [1024]byte // output buffer
 }
 
-func (e *encoder) Write(p []byte) (n int, err os.Error) {
+func (e *encoder) Write(p []byte) (n int, err error) {
 	if e.err != nil {
 		return 0, e.err
 	}
@@ -187,7 +186,7 @@ func (e *encoder) Write(p []byte) (n int, err os.Error) {
 
 // Close flushes any pending output from the encoder.
 // It is an error to call Write after calling Close.
-func (e *encoder) Close() os.Error {
+func (e *encoder) Close() error {
 	// If there's anything left in the buffer, flush it out
 	if e.err == nil && e.nbuf > 0 {
 		e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
@@ -216,15 +215,15 @@ func (enc *Encoding) EncodedLen(n int) int { return (n + 4) / 5 * 8 }
 
 type CorruptInputError int64
 
-func (e CorruptInputError) String() string {
-	return "illegal base32 data at input byte " + strconv.Itoa64(int64(e))
+func (e CorruptInputError) Error() string {
+	return "illegal base32 data at input byte " + strconv.FormatInt(int64(e), 10)
 }
 
 // decode is like Decode but returns an additional 'end' value, which
 // indicates if end-of-message padding was encountered and thus any
 // additional data is an error.  decode also assumes len(src)%8==0,
 // since it is meant for internal use.
-func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err os.Error) {
+func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
 	for i := 0; i < len(src)/8 && !end; i++ {
 		// Decode quantum using the base32 alphabet
 		var dbuf [8]byte
@@ -290,7 +289,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err os.Error) {
 // DecodedLen(len(src)) bytes to dst and returns the number of bytes
 // written.  If src contains invalid base32 data, it will return the
 // number of bytes successfully written and CorruptInputError.
-func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) {
+func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
 	if len(src)%8 != 0 {
 		return 0, CorruptInputError(len(src) / 8 * 8)
 	}
@@ -300,7 +299,7 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) {
 }
 
 type decoder struct {
-	err    os.Error
+	err    error
 	enc    *Encoding
 	r      io.Reader
 	end    bool       // saw end of message
@@ -310,7 +309,7 @@ type decoder struct {
 	outbuf [1024 / 8 * 5]byte
 }
 
-func (d *decoder) Read(p []byte) (n int, err os.Error) {
+func (d *decoder) Read(p []byte) (n int, err error) {
 	if d.err != nil {
 		return 0, d.err
 	}
diff --git a/src/pkg/encoding/base32/base32_test.go b/src/pkg/encoding/base32/base32_test.go
index 3fa1c2b..facf5d0 100644
--- a/src/pkg/encoding/base32/base32_test.go
+++ b/src/pkg/encoding/base32/base32_test.go
@@ -6,8 +6,8 @@ package base32
 
 import (
 	"bytes"
+	"io"
 	"io/ioutil"
-	"os"
 	"testing"
 )
 
@@ -78,11 +78,11 @@ func TestEncoderBuffering(t *testing.T) {
 				end = len(input)
 			}
 			n, err := encoder.Write(input[pos:end])
-			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, os.Error(nil))
+			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
 			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
 		}
 		err := encoder.Close()
-		testEqual(t, "Close gave error %v, want %v", err, os.Error(nil))
+		testEqual(t, "Close gave error %v, want %v", err, error(nil))
 		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded)
 	}
 }
@@ -91,7 +91,7 @@ func TestDecode(t *testing.T) {
 	for _, p := range pairs {
 		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
 		count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded))
-		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, os.Error(nil))
+		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
 		testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded))
 		if len(p.encoded) > 0 {
 			testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
@@ -107,15 +107,15 @@ func TestDecoder(t *testing.T) {
 		decoder := NewDecoder(StdEncoding, bytes.NewBufferString(p.encoded))
 		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
 		count, err := decoder.Read(dbuf)
-		if err != nil && err != os.EOF {
+		if err != nil && err != io.EOF {
 			t.Fatal("Read failed", err)
 		}
 		testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded))
 		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
-		if err != os.EOF {
+		if err != io.EOF {
 			count, err = decoder.Read(dbuf)
 		}
-		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, os.EOF)
+		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
 	}
 }
 
@@ -126,7 +126,7 @@ func TestDecoderBuffering(t *testing.T) {
 		var total int
 		for total = 0; total < len(bigtest.decoded); {
 			n, err := decoder.Read(buf[total : total+bs])
-			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, os.Error(nil))
+			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil))
 			total += n
 		}
 		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
diff --git a/src/pkg/encoding/base64/base64.go b/src/pkg/encoding/base64/base64.go
index c6b2a13..889b565 100644
--- a/src/pkg/encoding/base64/base64.go
+++ b/src/pkg/encoding/base64/base64.go
@@ -7,7 +7,6 @@ package base64
 
 import (
 	"io"
-	"os"
 	"strconv"
 )
 
@@ -114,7 +113,7 @@ func (enc *Encoding) EncodeToString(src []byte) string {
 }
 
 type encoder struct {
-	err  os.Error
+	err  error
 	enc  *Encoding
 	w    io.Writer
 	buf  [3]byte    // buffered data waiting to be encoded
@@ -122,7 +121,7 @@ type encoder struct {
 	out  [1024]byte // output buffer
 }
 
-func (e *encoder) Write(p []byte) (n int, err os.Error) {
+func (e *encoder) Write(p []byte) (n int, err error) {
 	if e.err != nil {
 		return 0, e.err
 	}
@@ -174,7 +173,7 @@ func (e *encoder) Write(p []byte) (n int, err os.Error) {
 
 // Close flushes any pending output from the encoder.
 // It is an error to call Write after calling Close.
-func (e *encoder) Close() os.Error {
+func (e *encoder) Close() error {
 	// If there's anything left in the buffer, flush it out
 	if e.err == nil && e.nbuf > 0 {
 		e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
@@ -203,15 +202,15 @@ func (enc *Encoding) EncodedLen(n int) int { return (n + 2) / 3 * 4 }
 
 type CorruptInputError int64
 
-func (e CorruptInputError) String() string {
-	return "illegal base64 data at input byte " + strconv.Itoa64(int64(e))
+func (e CorruptInputError) Error() string {
+	return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
 }
 
 // decode is like Decode but returns an additional 'end' value, which
 // indicates if end-of-message padding was encountered and thus any
 // additional data is an error.  decode also assumes len(src)%4==0,
 // since it is meant for internal use.
-func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err os.Error) {
+func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
 	for i := 0; i < len(src)/4 && !end; i++ {
 		// Decode quantum using the base64 alphabet
 		var dbuf [4]byte
@@ -258,7 +257,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err os.Error) {
 // DecodedLen(len(src)) bytes to dst and returns the number of bytes
 // written.  If src contains invalid base64 data, it will return the
 // number of bytes successfully written and CorruptInputError.
-func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) {
+func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
 	if len(src)%4 != 0 {
 		return 0, CorruptInputError(len(src) / 4 * 4)
 	}
@@ -268,14 +267,14 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) {
 }
 
 // DecodeString returns the bytes represented by the base64 string s.
-func (enc *Encoding) DecodeString(s string) ([]byte, os.Error) {
+func (enc *Encoding) DecodeString(s string) ([]byte, error) {
 	dbuf := make([]byte, enc.DecodedLen(len(s)))
 	n, err := enc.Decode(dbuf, []byte(s))
 	return dbuf[:n], err
 }
 
 type decoder struct {
-	err    os.Error
+	err    error
 	enc    *Encoding
 	r      io.Reader
 	end    bool       // saw end of message
@@ -285,7 +284,7 @@ type decoder struct {
 	outbuf [1024 / 4 * 3]byte
 }
 
-func (d *decoder) Read(p []byte) (n int, err os.Error) {
+func (d *decoder) Read(p []byte) (n int, err error) {
 	if d.err != nil {
 		return 0, d.err
 	}
diff --git a/src/pkg/encoding/base64/base64_test.go b/src/pkg/encoding/base64/base64_test.go
index c163dae..8310d8a 100644
--- a/src/pkg/encoding/base64/base64_test.go
+++ b/src/pkg/encoding/base64/base64_test.go
@@ -6,8 +6,8 @@ package base64
 
 import (
 	"bytes"
+	"io"
 	"io/ioutil"
-	"os"
 	"testing"
 )
 
@@ -82,11 +82,11 @@ func TestEncoderBuffering(t *testing.T) {
 				end = len(input)
 			}
 			n, err := encoder.Write(input[pos:end])
-			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, os.Error(nil))
+			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
 			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
 		}
 		err := encoder.Close()
-		testEqual(t, "Close gave error %v, want %v", err, os.Error(nil))
+		testEqual(t, "Close gave error %v, want %v", err, error(nil))
 		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded)
 	}
 }
@@ -95,7 +95,7 @@ func TestDecode(t *testing.T) {
 	for _, p := range pairs {
 		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
 		count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded))
-		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, os.Error(nil))
+		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
 		testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded))
 		if len(p.encoded) > 0 {
 			testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
@@ -103,7 +103,7 @@ func TestDecode(t *testing.T) {
 		testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
 
 		dbuf, err = StdEncoding.DecodeString(p.encoded)
-		testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, os.Error(nil))
+		testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, error(nil))
 		testEqual(t, "DecodeString(%q) = %q, want %q", string(dbuf), p.decoded)
 	}
 }
@@ -113,15 +113,15 @@ func TestDecoder(t *testing.T) {
 		decoder := NewDecoder(StdEncoding, bytes.NewBufferString(p.encoded))
 		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
 		count, err := decoder.Read(dbuf)
-		if err != nil && err != os.EOF {
+		if err != nil && err != io.EOF {
 			t.Fatal("Read failed", err)
 		}
 		testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded))
 		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
-		if err != os.EOF {
+		if err != io.EOF {
 			count, err = decoder.Read(dbuf)
 		}
-		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, os.EOF)
+		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
 	}
 }
 
@@ -132,7 +132,7 @@ func TestDecoderBuffering(t *testing.T) {
 		var total int
 		for total = 0; total < len(bigtest.decoded); {
 			n, err := decoder.Read(buf[total : total+bs])
-			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, os.Error(nil))
+			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil))
 			total += n
 		}
 		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
diff --git a/src/pkg/encoding/binary/Makefile b/src/pkg/encoding/binary/Makefile
index dc46abe..3246f5a 100644
--- a/src/pkg/encoding/binary/Makefile
+++ b/src/pkg/encoding/binary/Makefile
@@ -7,5 +7,6 @@ include ../../../Make.inc
 TARG=encoding/binary
 GOFILES=\
 	binary.go\
+        varint.go\
 
 include ../../../Make.pkg
diff --git a/src/pkg/encoding/binary/binary.go b/src/pkg/encoding/binary/binary.go
index 8e55cb2..d2f8b1e 100644
--- a/src/pkg/encoding/binary/binary.go
+++ b/src/pkg/encoding/binary/binary.go
@@ -8,18 +8,18 @@
 package binary
 
 import (
-	"math"
+	"errors"
 	"io"
-	"os"
+	"math"
 	"reflect"
 )
 
 // A ByteOrder specifies how to convert byte sequences into
 // 16-, 32-, or 64-bit unsigned integers.
 type ByteOrder interface {
-	Uint16(b []byte) uint16
-	Uint32(b []byte) uint32
-	Uint64(b []byte) uint64
+	Uint16([]byte) uint16
+	Uint32([]byte) uint32
+	Uint64([]byte) uint64
 	PutUint16([]byte, uint16)
 	PutUint32([]byte, uint32)
 	PutUint64([]byte, uint64)
@@ -124,7 +124,7 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
 // or an array or struct containing only fixed-size values.
 // Bytes read from r are decoded using the specified byte order
 // and written to successive fields of the data.
-func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
+func Read(r io.Reader, order ByteOrder, data interface{}) error {
 	// Fast path for basic types.
 	if n := intDestSize(data); n != 0 {
 		var b [8]byte
@@ -161,11 +161,11 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
 	case reflect.Slice:
 		v = d
 	default:
-		return os.NewError("binary.Read: invalid type " + d.Type().String())
+		return errors.New("binary.Read: invalid type " + d.Type().String())
 	}
 	size := TotalSize(v)
 	if size < 0 {
-		return os.NewError("binary.Read: invalid type " + v.Type().String())
+		return errors.New("binary.Read: invalid type " + v.Type().String())
 	}
 	d := &decoder{order: order, buf: make([]byte, size)}
 	if _, err := io.ReadFull(r, d.buf); err != nil {
@@ -183,7 +183,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
 // or an array or struct containing only fixed-size values.
 // Bytes written to w are encoded using the specified byte order
 // and read from successive fields of the data.
-func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
+func Write(w io.Writer, order ByteOrder, data interface{}) error {
 	// Fast path for basic types.
 	var b [8]byte
 	var bs []byte
@@ -244,7 +244,7 @@ func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
 	v := reflect.Indirect(reflect.ValueOf(data))
 	size := TotalSize(v)
 	if size < 0 {
-		return os.NewError("binary.Write: invalid type " + v.Type().String())
+		return errors.New("binary.Write: invalid type " + v.Type().String())
 	}
 	buf := make([]byte, size)
 	e := &encoder{order: order, buf: buf}
diff --git a/src/pkg/encoding/binary/binary_test.go b/src/pkg/encoding/binary/binary_test.go
index b266996..3e7057e 100644
--- a/src/pkg/encoding/binary/binary_test.go
+++ b/src/pkg/encoding/binary/binary_test.go
@@ -5,9 +5,8 @@
 package binary
 
 import (
-	"io"
-	"os"
 	"bytes"
+	"io"
 	"math"
 	"reflect"
 	"testing"
@@ -99,7 +98,7 @@ var little = []byte{
 var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
 var res = []int32{0x01020304, 0x05060708}
 
-func checkResult(t *testing.T, dir string, order, err os.Error, have, want interface{}) {
+func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want interface{}) {
 	if err != nil {
 		t.Errorf("%v %v: %v", dir, order, err)
 		return
@@ -166,17 +165,48 @@ type byteSliceReader struct {
 	remain []byte
 }
 
-func (br *byteSliceReader) Read(p []byte) (int, os.Error) {
+func (br *byteSliceReader) Read(p []byte) (int, error) {
 	n := copy(p, br.remain)
 	br.remain = br.remain[n:]
 	return n, nil
 }
 
-func BenchmarkRead(b *testing.B) {
+func BenchmarkReadSlice1000Int32s(b *testing.B) {
+	bsr := &byteSliceReader{}
+	slice := make([]int32, 1000)
+	buf := make([]byte, len(slice)*4)
+	b.SetBytes(int64(len(buf)))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bsr.remain = buf
+		Read(bsr, BigEndian, slice)
+	}
+}
+
+func BenchmarkReadStruct(b *testing.B) {
+	bsr := &byteSliceReader{}
+	var buf bytes.Buffer
+	Write(&buf, BigEndian, &s)
+	n := TotalSize(reflect.ValueOf(s))
+	b.SetBytes(int64(n))
+	t := s
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bsr.remain = buf.Bytes()
+		Read(bsr, BigEndian, &t)
+	}
+	b.StopTimer()
+	if !reflect.DeepEqual(s, t) {
+		b.Fatal("no match")
+	}
+}
+
+func BenchmarkReadInts(b *testing.B) {
 	var ls Struct
 	bsr := &byteSliceReader{}
 	var r io.Reader = bsr
-
+	b.SetBytes(2 * (1 + 2 + 4 + 8))
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		bsr.remain = big
 		Read(r, BigEndian, &ls.Int8)
@@ -197,25 +227,19 @@ func BenchmarkRead(b *testing.B) {
 	for i := range want.Array {
 		want.Array[i] = 0
 	}
+	b.StopTimer()
 	if !reflect.DeepEqual(ls, want) {
 		panic("no match")
 	}
 }
 
-func BenchmarkWrite(b *testing.B) {
+func BenchmarkWriteInts(b *testing.B) {
 	buf := new(bytes.Buffer)
 	var w io.Writer = buf
-
+	b.SetBytes(2 * (1 + 2 + 4 + 8))
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		buf.Reset()
-		Write(w, BigEndian, &s.Int8)
-		Write(w, BigEndian, &s.Int16)
-		Write(w, BigEndian, &s.Int32)
-		Write(w, BigEndian, &s.Int64)
-		Write(w, BigEndian, &s.Uint8)
-		Write(w, BigEndian, &s.Uint16)
-		Write(w, BigEndian, &s.Uint32)
-		Write(w, BigEndian, &s.Uint64)
 		Write(w, BigEndian, s.Int8)
 		Write(w, BigEndian, s.Int16)
 		Write(w, BigEndian, s.Int32)
@@ -225,11 +249,8 @@ func BenchmarkWrite(b *testing.B) {
 		Write(w, BigEndian, s.Uint32)
 		Write(w, BigEndian, s.Uint64)
 	}
-
-	if !bytes.Equal(buf.Bytes()[:30], big[:30]) {
-		panic("first half doesn't match")
-	}
-	if !bytes.Equal(buf.Bytes()[30:], big[:30]) {
-		panic("second half doesn't match")
+	b.StopTimer()
+	if !bytes.Equal(buf.Bytes(), big[:30]) {
+		b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
 	}
 }
diff --git a/src/pkg/encoding/binary/example_test.go b/src/pkg/encoding/binary/example_test.go
new file mode 100644
index 0000000..297d6c1
--- /dev/null
+++ b/src/pkg/encoding/binary/example_test.go
@@ -0,0 +1,52 @@
+// Copyright 2011 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 binary_test
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"math"
+)
+
+// 18 2d 44 54 fb 21 09 40
+func ExampleWrite() {
+	buf := new(bytes.Buffer)
+	var pi float64 = math.Pi
+	err := binary.Write(buf, binary.LittleEndian, pi)
+	if err != nil {
+		fmt.Println("binary.Write failed:", err)
+	}
+	fmt.Printf("% x", buf.Bytes())
+}
+
+// cafebabe
+func ExampleWrite_multi() {
+	buf := new(bytes.Buffer)
+	var data = []interface{}{
+		int8(-54),
+		uint8(254),
+		uint16(48826),
+	}
+	for _, v := range data {
+		err := binary.Write(buf, binary.LittleEndian, v)
+		if err != nil {
+			fmt.Println("binary.Write failed:", err)
+		}
+	}
+	fmt.Printf("%x", buf.Bytes())
+}
+
+// 3.141592653589793
+func ExampleRead() {
+	var pi float64
+	b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
+	buf := bytes.NewBuffer(b)
+	err := binary.Read(buf, binary.LittleEndian, &pi)
+	if err != nil {
+		fmt.Println("binary.Read failed:", err)
+	}
+	fmt.Print(pi)
+}
diff --git a/src/pkg/encoding/binary/varint.go b/src/pkg/encoding/binary/varint.go
new file mode 100644
index 0000000..b756afd
--- /dev/null
+++ b/src/pkg/encoding/binary/varint.go
@@ -0,0 +1,134 @@
+// Copyright 2011 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 binary
+
+// This file implements "varint" encoding of 64-bit integers.
+// The encoding is:
+// - unsigned integers are serialized 7 bits at a time, starting with the
+//   least significant bits
+// - the most significant bit (msb) in each output byte indicates if there
+//   is a continuation byte (msb = 1)
+// - signed integers are mapped to unsigned integers using "zig-zag"
+//   encoding: Positive values x are written as 2*x + 0, negative values
+//   are written as 2*(^x) + 1; that is, negative numbers are complemented
+//   and whether to complement is encoded in bit 0.
+//
+// Design note:
+// At most 10 bytes are needed for 64-bit values. The encoding could
+// be more dense: a full 64-bit value needs an extra byte just to hold bit 63.
+// Instead, the msb of the previous byte could be used to hold bit 63 since we
+// know there can't be more than 64 bits. This is a trivial improvement and
+// would reduce the maximum encoding length to 9 bytes. However, it breaks the
+// invariant that the msb is always the "continuation bit" and thus makes the
+// format incompatible with a varint encoding for larger numbers (say 128-bit).
+
+import (
+	"errors"
+	"io"
+)
+
+// MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.
+const (
+	MaxVarintLen16 = 3
+	MaxVarintLen32 = 5
+	MaxVarintLen64 = 10
+)
+
+// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
+// If the buffer is too small, PutUvarint will panic.
+func PutUvarint(buf []byte, x uint64) int {
+	i := 0
+	for x >= 0x80 {
+		buf[i] = byte(x) | 0x80
+		x >>= 7
+		i++
+	}
+	buf[i] = byte(x)
+	return i + 1
+}
+
+// Uvarint decodes a uint64 from buf and returns that value and the
+// number of bytes read (> 0). If an error occurred, the value is 0
+// and the number of bytes n is <= 0 meaning:
+//
+//	n == 0: buf too small
+//	n  < 0: value larger than 64 bits (overflow)
+//              and -n is the number of bytes read
+//
+func Uvarint(buf []byte) (uint64, int) {
+	var x uint64
+	var s uint
+	for i, b := range buf {
+		if b < 0x80 {
+			if i > 9 || i == 9 && b > 1 {
+				return 0, -(i + 1) // overflow
+			}
+			return x | uint64(b)<<s, i + 1
+		}
+		x |= uint64(b&0x7f) << s
+		s += 7
+	}
+	return 0, 0
+}
+
+// PutVarint encodes an int64 into buf and returns the number of bytes written.
+// If the buffer is too small, PutVarint will panic.
+func PutVarint(buf []byte, x int64) int {
+	ux := uint64(x) << 1
+	if x < 0 {
+		ux = ^ux
+	}
+	return PutUvarint(buf, ux)
+}
+
+// Varint decodes an int64 from buf and returns that value and the
+// number of bytes read (> 0). If an error occurred, the value is 0
+// and the number of bytes n is <= 0 with the following meaning:
+//
+//	n == 0: buf too small
+//	n  < 0: value larger than 64 bits (overflow)
+//              and -n is the number of bytes read
+//
+func Varint(buf []byte) (int64, int) {
+	ux, n := Uvarint(buf) // ok to continue in presence of error
+	x := int64(ux >> 1)
+	if ux&1 != 0 {
+		x = ^x
+	}
+	return x, n
+}
+
+var overflow = errors.New("binary: varint overflows a 64-bit integer")
+
+// ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
+func ReadUvarint(r io.ByteReader) (uint64, error) {
+	var x uint64
+	var s uint
+	for i := 0; ; i++ {
+		b, err := r.ReadByte()
+		if err != nil {
+			return x, err
+		}
+		if b < 0x80 {
+			if i > 9 || i == 9 && b > 1 {
+				return x, overflow
+			}
+			return x | uint64(b)<<s, nil
+		}
+		x |= uint64(b&0x7f) << s
+		s += 7
+	}
+	panic("unreachable")
+}
+
+// ReadVarint reads an encoded unsigned integer from r and returns it as a uint64.
+func ReadVarint(r io.ByteReader) (int64, error) {
+	ux, err := ReadUvarint(r) // ok to continue in presence of error
+	x := int64(ux >> 1)
+	if ux&1 != 0 {
+		x = ^x
+	}
+	return x, err
+}
diff --git a/src/pkg/encoding/binary/varint_test.go b/src/pkg/encoding/binary/varint_test.go
new file mode 100644
index 0000000..9476bd5
--- /dev/null
+++ b/src/pkg/encoding/binary/varint_test.go
@@ -0,0 +1,168 @@
+// Copyright 2011 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 binary
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+func testConstant(t *testing.T, w uint, max int) {
+	buf := make([]byte, MaxVarintLen64)
+	n := PutUvarint(buf, 1<<w-1)
+	if n != max {
+		t.Errorf("MaxVarintLen%d = %d; want %d", w, max, n)
+	}
+}
+
+func TestConstants(t *testing.T) {
+	testConstant(t, 16, MaxVarintLen16)
+	testConstant(t, 32, MaxVarintLen32)
+	testConstant(t, 64, MaxVarintLen64)
+}
+
+func testVarint(t *testing.T, x int64) {
+	buf := make([]byte, MaxVarintLen64)
+	n := PutVarint(buf, x)
+	y, m := Varint(buf[0:n])
+	if x != y {
+		t.Errorf("Varint(%d): got %d", x, y)
+	}
+	if n != m {
+		t.Errorf("Varint(%d): got n = %d; want %d", x, m, n)
+	}
+
+	y, err := ReadVarint(bytes.NewBuffer(buf))
+	if err != nil {
+		t.Errorf("ReadVarint(%d): %s", x, err)
+	}
+	if x != y {
+		t.Errorf("ReadVarint(%d): got %d", x, y)
+	}
+}
+
+func testUvarint(t *testing.T, x uint64) {
+	buf := make([]byte, MaxVarintLen64)
+	n := PutUvarint(buf, x)
+	y, m := Uvarint(buf[0:n])
+	if x != y {
+		t.Errorf("Uvarint(%d): got %d", x, y)
+	}
+	if n != m {
+		t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n)
+	}
+
+	y, err := ReadUvarint(bytes.NewBuffer(buf))
+	if err != nil {
+		t.Errorf("ReadUvarint(%d): %s", x, err)
+	}
+	if x != y {
+		t.Errorf("ReadUvarint(%d): got %d", x, y)
+	}
+}
+
+var tests = []int64{
+	-1 << 63,
+	-1<<63 + 1,
+	-1,
+	0,
+	1,
+	2,
+	10,
+	20,
+	63,
+	64,
+	65,
+	127,
+	128,
+	129,
+	255,
+	256,
+	257,
+	1<<63 - 1,
+}
+
+func TestVarint(t *testing.T) {
+	for _, x := range tests {
+		testVarint(t, x)
+		testVarint(t, -x)
+	}
+	for x := int64(0x7); x != 0; x <<= 1 {
+		testVarint(t, x)
+		testVarint(t, -x)
+	}
+}
+
+func TestUvarint(t *testing.T) {
+	for _, x := range tests {
+		testUvarint(t, uint64(x))
+	}
+	for x := uint64(0x7); x != 0; x <<= 1 {
+		testUvarint(t, x)
+	}
+}
+
+func TestBufferTooSmall(t *testing.T) {
+	buf := []byte{0x80, 0x80, 0x80, 0x80}
+	for i := 0; i <= len(buf); i++ {
+		buf := buf[0:i]
+		x, n := Uvarint(buf)
+		if x != 0 || n != 0 {
+			t.Errorf("Uvarint(%v): got x = %d, n = %d", buf, x, n)
+		}
+
+		x, err := ReadUvarint(bytes.NewBuffer(buf))
+		if x != 0 || err != io.EOF {
+			t.Errorf("ReadUvarint(%v): got x = %d, err = %s", buf, x, err)
+		}
+	}
+}
+
+func testOverflow(t *testing.T, buf []byte, n0 int, err0 error) {
+	x, n := Uvarint(buf)
+	if x != 0 || n != n0 {
+		t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, %d", buf, x, n, n0)
+	}
+
+	x, err := ReadUvarint(bytes.NewBuffer(buf))
+	if x != 0 || err != err0 {
+		t.Errorf("ReadUvarint(%v): got x = %d, err = %s; want 0, %s", buf, x, err, err0)
+	}
+}
+
+func TestOverflow(t *testing.T) {
+	testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, -10, overflow)
+	testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, -13, overflow)
+}
+
+func TestNonCanonicalZero(t *testing.T) {
+	buf := []byte{0x80, 0x80, 0x80, 0}
+	x, n := Uvarint(buf)
+	if x != 0 || n != 4 {
+		t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, 4", buf, x, n)
+
+	}
+}
+
+func BenchmarkPutUvarint32(b *testing.B) {
+	buf := make([]byte, MaxVarintLen32)
+	b.SetBytes(4)
+	for i := 0; i < b.N; i++ {
+		for j := uint(0); j < MaxVarintLen32; j++ {
+			PutUvarint(buf, 1<<(j*7))
+		}
+	}
+}
+
+func BenchmarkPutUvarint64(b *testing.B) {
+	buf := make([]byte, MaxVarintLen64)
+	b.SetBytes(8)
+	for i := 0; i < b.N; i++ {
+		for j := uint(0); j < MaxVarintLen64; j++ {
+			PutUvarint(buf, 1<<(j*7))
+		}
+	}
+}
diff --git a/src/pkg/encoding/csv/Makefile b/src/pkg/encoding/csv/Makefile
new file mode 100644
index 0000000..9e04c5b
--- /dev/null
+++ b/src/pkg/encoding/csv/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=encoding/csv
+GOFILES=\
+	reader.go\
+	writer.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/encoding/csv/reader.go b/src/pkg/encoding/csv/reader.go
new file mode 100644
index 0000000..ae0f567
--- /dev/null
+++ b/src/pkg/encoding/csv/reader.go
@@ -0,0 +1,372 @@
+// Copyright 2011 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 csv reads and writes comma-separated values (CSV) files.
+//
+// A csv file contains zero or more records of one or more fields per record.
+// Each record is separated by the newline character. The final record may
+// optionally be followed by a newline character.
+//
+//	field1,field2,field3
+//
+// White space is considered part of a field.
+//
+// Carriage returns before newline characters are silently removed.
+//
+// Blank lines are ignored.  A line with only whitespace characters (excluding
+// the ending newline character) is not considered a blank line.
+//
+// Fields which start and stop with the quote character " are called
+// quoted-fields.  The beginning and ending quote are not part of the
+// field.
+//
+// The source:
+//
+//	normal string,"quoted-field"
+//
+// results in the fields
+//
+//	{`normal string`, `quoted-field`}
+//
+// Within a quoted-field a quote character followed by a second quote
+// character is considered a single quote.
+//
+//	"the ""word"" is true","a ""quoted-field"""
+//
+// results in
+//
+//	{`the "word" is true`, `a "quoted-field"`}
+//
+// Newlines and commas may be included in a quoted-field
+//
+//	"Multi-line
+//	field","comma is ,"
+//
+// results in
+//
+//	{`Multi-line
+//	field`, `comma is ,`}
+package csv
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"unicode"
+)
+
+// A ParseError is returned for parsing errors.
+// The first line is 1.  The first column is 0.
+type ParseError struct {
+	Line   int   // Line where the error occurred
+	Column int   // Column (rune index) where the error occurred
+	Err    error // The actual error
+}
+
+func (e *ParseError) Error() string {
+	return fmt.Sprintf("line %d, column %d: %s", e.Line, e.Column, e.Err)
+}
+
+// These are the errors that can be returned in ParseError.Error
+var (
+	ErrTrailingComma = errors.New("extra delimiter at end of line")
+	ErrBareQuote     = errors.New("bare \" in non-quoted-field")
+	ErrQuote         = errors.New("extraneous \" in field")
+	ErrFieldCount    = errors.New("wrong number of fields in line")
+)
+
+// A Reader reads records from a CSV-encoded file.
+//
+// As returned by NewReader, a Reader expects input conforming to RFC 4180.
+// The exported fields can be changed to customize the details before the
+// first call to Read or ReadAll.
+//
+// Comma is the field delimiter.  It defaults to ','.
+//
+// Comment, if not 0, is the comment character. Lines beginning with the
+// Comment character are ignored.
+//
+// If FieldsPerRecord is positive, Read requires each record to
+// have the given number of fields.  If FieldsPerRecord is 0, Read sets it to
+// the number of fields in the first record, so that future records must
+// have the same field count.
+//
+// If LazyQuotes is true, a quote may appear in an unquoted field and a
+// non-doubled quote may appear in a quoted field.
+//
+// If TrailingComma is true, the last field may be an unquoted empty field.
+//
+// If TrimLeadingSpace is true, leading white space in a field is ignored.
+type Reader struct {
+	Comma            rune // Field delimiter (set to ',' by NewReader)
+	Comment          rune // Comment character for start of line
+	FieldsPerRecord  int  // Number of expected fields per record
+	LazyQuotes       bool // Allow lazy quotes
+	TrailingComma    bool // Allow trailing comma
+	TrimLeadingSpace bool // Trim leading space
+	line             int
+	column           int
+	r                *bufio.Reader
+	field            bytes.Buffer
+}
+
+// NewReader returns a new Reader that reads from r.
+func NewReader(r io.Reader) *Reader {
+	return &Reader{
+		Comma: ',',
+		r:     bufio.NewReader(r),
+	}
+}
+
+// error creates a new ParseError based on err.
+func (r *Reader) error(err error) error {
+	return &ParseError{
+		Line:   r.line,
+		Column: r.column,
+		Err:    err,
+	}
+}
+
+// Read reads one record from r.  The record is a slice of strings with each
+// string representing one field.
+func (r *Reader) Read() (record []string, err error) {
+	for {
+		record, err = r.parseRecord()
+		if record != nil {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if r.FieldsPerRecord > 0 {
+		if len(record) != r.FieldsPerRecord {
+			r.column = 0 // report at start of record
+			return record, r.error(ErrFieldCount)
+		}
+	} else if r.FieldsPerRecord == 0 {
+		r.FieldsPerRecord = len(record)
+	}
+	return record, nil
+}
+
+// ReadAll reads all the remaining records from r.
+// Each record is a slice of fields.
+func (r *Reader) ReadAll() (records [][]string, err error) {
+	for {
+		record, err := r.Read()
+		if err == io.EOF {
+			return records, nil
+		}
+		if err != nil {
+			return nil, err
+		}
+		records = append(records, record)
+	}
+	panic("unreachable")
+}
+
+// readRune reads one rune from r, folding \r\n to \n and keeping track
+// of how far into the line we have read.  r.column will point to the start
+// of this rune, not the end of this rune.
+func (r *Reader) readRune() (rune, error) {
+	r1, _, err := r.r.ReadRune()
+
+	// Handle \r\n here.  We make the simplifying assumption that
+	// anytime \r is followed by \n that it can be folded to \n.
+	// We will not detect files which contain both \r\n and bare \n.
+	if r1 == '\r' {
+		r1, _, err = r.r.ReadRune()
+		if err == nil {
+			if r1 != '\n' {
+				r.r.UnreadRune()
+				r1 = '\r'
+			}
+		}
+	}
+	r.column++
+	return r1, err
+}
+
+// unreadRune puts the last rune read from r back.
+func (r *Reader) unreadRune() {
+	r.r.UnreadRune()
+	r.column--
+}
+
+// skip reads runes up to and including the rune delim or until error.
+func (r *Reader) skip(delim rune) error {
+	for {
+		r1, err := r.readRune()
+		if err != nil {
+			return err
+		}
+		if r1 == delim {
+			return nil
+		}
+	}
+	panic("unreachable")
+}
+
+// parseRecord reads and parses a single csv record from r.
+func (r *Reader) parseRecord() (fields []string, err error) {
+	// Each record starts on a new line.  We increment our line
+	// number (lines start at 1, not 0) and set column to -1
+	// so as we increment in readRune it points to the character we read.
+	r.line++
+	r.column = -1
+
+	// Peek at the first rune.  If it is an error we are done.
+	// If we are support comments and it is the comment character
+	// then skip to the end of line.
+
+	r1, _, err := r.r.ReadRune()
+	if err != nil {
+		return nil, err
+	}
+
+	if r.Comment != 0 && r1 == r.Comment {
+		return nil, r.skip('\n')
+	}
+	r.r.UnreadRune()
+
+	// At this point we have at least one field.
+	for {
+		haveField, delim, err := r.parseField()
+		if haveField {
+			fields = append(fields, r.field.String())
+		}
+		if delim == '\n' || err == io.EOF {
+			return fields, err
+		} else if err != nil {
+			return nil, err
+		}
+	}
+	panic("unreachable")
+}
+
+// parseField parses the next field in the record.  The read field is
+// located in r.field.  Delim is the first character not part of the field
+// (r.Comma or '\n').
+func (r *Reader) parseField() (haveField bool, delim rune, err error) {
+	r.field.Reset()
+
+	r1, err := r.readRune()
+	if err != nil {
+		// If we have EOF and are not at the start of a line
+		// then we return the empty field.  We have already
+		// checked for trailing commas if needed.
+		if err == io.EOF && r.column != 0 {
+			return true, 0, err
+		}
+		return false, 0, err
+	}
+
+	if r.TrimLeadingSpace {
+		for r1 != '\n' && unicode.IsSpace(r1) {
+			r1, err = r.readRune()
+			if err != nil {
+				return false, 0, err
+			}
+		}
+	}
+
+	switch r1 {
+	case r.Comma:
+		// will check below
+
+	case '\n':
+		// We are a trailing empty field or a blank line
+		if r.column == 0 {
+			return false, r1, nil
+		}
+		return true, r1, nil
+
+	case '"':
+		// quoted field
+	Quoted:
+		for {
+			r1, err = r.readRune()
+			if err != nil {
+				if err == io.EOF {
+					if r.LazyQuotes {
+						return true, 0, err
+					}
+					return false, 0, r.error(ErrQuote)
+				}
+				return false, 0, err
+			}
+			switch r1 {
+			case '"':
+				r1, err = r.readRune()
+				if err != nil || r1 == r.Comma {
+					break Quoted
+				}
+				if r1 == '\n' {
+					return true, r1, nil
+				}
+				if r1 != '"' {
+					if !r.LazyQuotes {
+						r.column--
+						return false, 0, r.error(ErrQuote)
+					}
+					// accept the bare quote
+					r.field.WriteRune('"')
+				}
+			case '\n':
+				r.line++
+				r.column = -1
+			}
+			r.field.WriteRune(r1)
+		}
+
+	default:
+		// unquoted field
+		for {
+			r.field.WriteRune(r1)
+			r1, err = r.readRune()
+			if err != nil || r1 == r.Comma {
+				break
+			}
+			if r1 == '\n' {
+				return true, r1, nil
+			}
+			if !r.LazyQuotes && r1 == '"' {
+				return false, 0, r.error(ErrBareQuote)
+			}
+		}
+	}
+
+	if err != nil {
+		if err == io.EOF {
+			return true, 0, err
+		}
+		return false, 0, err
+	}
+
+	if !r.TrailingComma {
+		// We don't allow trailing commas.  See if we
+		// are at the end of the line (being mindful
+		// of trimming spaces).
+		c := r.column
+		r1, err = r.readRune()
+		if r.TrimLeadingSpace {
+			for r1 != '\n' && unicode.IsSpace(r1) {
+				r1, err = r.readRune()
+				if err != nil {
+					break
+				}
+			}
+		}
+		if err == io.EOF || r1 == '\n' {
+			r.column = c // report the comma
+			return false, 0, r.error(ErrTrailingComma)
+		}
+		r.unreadRune()
+	}
+	return true, r1, nil
+}
diff --git a/src/pkg/encoding/csv/reader_test.go b/src/pkg/encoding/csv/reader_test.go
new file mode 100644
index 0000000..5fd84a7
--- /dev/null
+++ b/src/pkg/encoding/csv/reader_test.go
@@ -0,0 +1,281 @@
+// Copyright 2011 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 csv
+
+import (
+	"reflect"
+	"strings"
+	"testing"
+)
+
+var readTests = []struct {
+	Name               string
+	Input              string
+	Output             [][]string
+	UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1
+
+	// These fields are copied into the Reader
+	Comma            rune
+	Comment          rune
+	FieldsPerRecord  int
+	LazyQuotes       bool
+	TrailingComma    bool
+	TrimLeadingSpace bool
+
+	Error  string
+	Line   int // Expected error line if != 0
+	Column int // Expected error column if line != 0
+}{
+	{
+		Name:   "Simple",
+		Input:  "a,b,c\n",
+		Output: [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name:   "CRLF",
+		Input:  "a,b\r\nc,d\r\n",
+		Output: [][]string{{"a", "b"}, {"c", "d"}},
+	},
+	{
+		Name:   "BareCR",
+		Input:  "a,b\rc,d\r\n",
+		Output: [][]string{{"a", "b\rc", "d"}},
+	},
+	{
+		Name:               "RFC4180test",
+		UseFieldsPerRecord: true,
+		Input: `#field1,field2,field3
+"aaa","bb
+b","ccc"
+"a,a","b""bb","ccc"
+zzz,yyy,xxx
+`,
+		Output: [][]string{
+			{"#field1", "field2", "field3"},
+			{"aaa", "bb\nb", "ccc"},
+			{"a,a", `b"bb`, "ccc"},
+			{"zzz", "yyy", "xxx"},
+		},
+	},
+	{
+		Name:   "NoEOLTest",
+		Input:  "a,b,c",
+		Output: [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name:   "Semicolon",
+		Comma:  ';',
+		Input:  "a;b;c\n",
+		Output: [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name: "MultiLine",
+		Input: `"two
+line","one line","three
+line
+field"`,
+		Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}},
+	},
+	{
+		Name:  "BlankLine",
+		Input: "a,b,c\n\nd,e,f\n\n",
+		Output: [][]string{
+			{"a", "b", "c"},
+			{"d", "e", "f"},
+		},
+	},
+	{
+		Name:             "TrimSpace",
+		Input:            " a,  b,   c\n",
+		TrimLeadingSpace: true,
+		Output:           [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name:   "LeadingSpace",
+		Input:  " a,  b,   c\n",
+		Output: [][]string{{" a", "  b", "   c"}},
+	},
+	{
+		Name:    "Comment",
+		Comment: '#',
+		Input:   "#1,2,3\na,b,c\n#comment",
+		Output:  [][]string{{"a", "b", "c"}},
+	},
+	{
+		Name:   "NoComment",
+		Input:  "#1,2,3\na,b,c",
+		Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}},
+	},
+	{
+		Name:       "LazyQuotes",
+		LazyQuotes: true,
+		Input:      `a "word","1"2",a","b`,
+		Output:     [][]string{{`a "word"`, `1"2`, `a"`, `b`}},
+	},
+	{
+		Name:       "BareQuotes",
+		LazyQuotes: true,
+		Input:      `a "word","1"2",a"`,
+		Output:     [][]string{{`a "word"`, `1"2`, `a"`}},
+	},
+	{
+		Name:       "BareDoubleQuotes",
+		LazyQuotes: true,
+		Input:      `a""b,c`,
+		Output:     [][]string{{`a""b`, `c`}},
+	},
+	{
+		Name:  "BadDoubleQuotes",
+		Input: `a""b,c`,
+		Error: `bare " in non-quoted-field`, Line: 1, Column: 1,
+	},
+	{
+		Name:             "TrimQuote",
+		Input:            ` "a"," b",c`,
+		TrimLeadingSpace: true,
+		Output:           [][]string{{"a", " b", "c"}},
+	},
+	{
+		Name:  "BadBareQuote",
+		Input: `a "word","b"`,
+		Error: `bare " in non-quoted-field`, Line: 1, Column: 2,
+	},
+	{
+		Name:  "BadTrailingQuote",
+		Input: `"a word",b"`,
+		Error: `bare " in non-quoted-field`, Line: 1, Column: 10,
+	},
+	{
+		Name:  "ExtraneousQuote",
+		Input: `"a "word","b"`,
+		Error: `extraneous " in field`, Line: 1, Column: 3,
+	},
+	{
+		Name:               "BadFieldCount",
+		UseFieldsPerRecord: true,
+		Input:              "a,b,c\nd,e",
+		Error:              "wrong number of fields", Line: 2,
+	},
+	{
+		Name:               "BadFieldCount1",
+		UseFieldsPerRecord: true,
+		FieldsPerRecord:    2,
+		Input:              `a,b,c`,
+		Error:              "wrong number of fields", Line: 1,
+	},
+	{
+		Name:   "FieldCount",
+		Input:  "a,b,c\nd,e",
+		Output: [][]string{{"a", "b", "c"}, {"d", "e"}},
+	},
+	{
+		Name:  "BadTrailingCommaEOF",
+		Input: "a,b,c,",
+		Error: "extra delimiter at end of line", Line: 1, Column: 5,
+	},
+	{
+		Name:  "BadTrailingCommaEOL",
+		Input: "a,b,c,\n",
+		Error: "extra delimiter at end of line", Line: 1, Column: 5,
+	},
+	{
+		Name:             "BadTrailingCommaSpaceEOF",
+		TrimLeadingSpace: true,
+		Input:            "a,b,c, ",
+		Error:            "extra delimiter at end of line", Line: 1, Column: 5,
+	},
+	{
+		Name:             "BadTrailingCommaSpaceEOL",
+		TrimLeadingSpace: true,
+		Input:            "a,b,c, \n",
+		Error:            "extra delimiter at end of line", Line: 1, Column: 5,
+	},
+	{
+		Name:             "BadTrailingCommaLine3",
+		TrimLeadingSpace: true,
+		Input:            "a,b,c\nd,e,f\ng,hi,",
+		Error:            "extra delimiter at end of line", Line: 3, Column: 4,
+	},
+	{
+		Name:   "NotTrailingComma3",
+		Input:  "a,b,c, \n",
+		Output: [][]string{{"a", "b", "c", " "}},
+	},
+	{
+		Name:          "CommaFieldTest",
+		TrailingComma: true,
+		Input: `x,y,z,w
+x,y,z,
+x,y,,
+x,,,
+,,,
+"x","y","z","w"
+"x","y","z",""
+"x","y","",""
+"x","","",""
+"","","",""
+`,
+		Output: [][]string{
+			{"x", "y", "z", "w"},
+			{"x", "y", "z", ""},
+			{"x", "y", "", ""},
+			{"x", "", "", ""},
+			{"", "", "", ""},
+			{"x", "y", "z", "w"},
+			{"x", "y", "z", ""},
+			{"x", "y", "", ""},
+			{"x", "", "", ""},
+			{"", "", "", ""},
+		},
+	},
+	{
+		Name:             "Issue 2366",
+		TrailingComma:    true,
+		TrimLeadingSpace: true,
+		Input:            "a,b,\nc,d,e",
+		Output: [][]string{
+			{"a", "b", ""},
+			{"c", "d", "e"},
+		},
+	},
+	{
+		Name:             "Issue 2366a",
+		TrailingComma:    false,
+		TrimLeadingSpace: true,
+		Input:            "a,b,\nc,d,e",
+		Error:            "extra delimiter at end of line",
+	},
+}
+
+func TestRead(t *testing.T) {
+	for _, tt := range readTests {
+		r := NewReader(strings.NewReader(tt.Input))
+		r.Comment = tt.Comment
+		if tt.UseFieldsPerRecord {
+			r.FieldsPerRecord = tt.FieldsPerRecord
+		} else {
+			r.FieldsPerRecord = -1
+		}
+		r.LazyQuotes = tt.LazyQuotes
+		r.TrailingComma = tt.TrailingComma
+		r.TrimLeadingSpace = tt.TrimLeadingSpace
+		if tt.Comma != 0 {
+			r.Comma = tt.Comma
+		}
+		out, err := r.ReadAll()
+		perr, _ := err.(*ParseError)
+		if tt.Error != "" {
+			if err == nil || !strings.Contains(err.Error(), tt.Error) {
+				t.Errorf("%s: error %v, want error %q", tt.Name, err, tt.Error)
+			} else if tt.Line != 0 && (tt.Line != perr.Line || tt.Column != perr.Column) {
+				t.Errorf("%s: error at %d:%d expected %d:%d", tt.Name, perr.Line, perr.Column, tt.Line, tt.Column)
+			}
+		} else if err != nil {
+			t.Errorf("%s: unexpected error %v", tt.Name, err)
+		} else if !reflect.DeepEqual(out, tt.Output) {
+			t.Errorf("%s: out=%q want %q", tt.Name, out, tt.Output)
+		}
+	}
+}
diff --git a/src/pkg/encoding/csv/writer.go b/src/pkg/encoding/csv/writer.go
new file mode 100644
index 0000000..c4dcba5
--- /dev/null
+++ b/src/pkg/encoding/csv/writer.go
@@ -0,0 +1,121 @@
+// Copyright 2011 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 csv
+
+import (
+	"bufio"
+	"io"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// A Writer writes records to a CSV encoded file.
+//
+// As returned by NewWriter, a Writer writes records terminated by a
+// newline and uses ',' as the field delimiter.  The exported fields can be
+// changed to customize the details before the first call to Write or WriteAll.
+//
+// Comma is the field delimiter.
+//
+// If UseCRLF is true, the Writer ends each record with \r\n instead of \n.
+type Writer struct {
+	Comma   rune // Field delimiter (set to to ',' by NewWriter)
+	UseCRLF bool // True to use \r\n as the line terminator
+	w       *bufio.Writer
+}
+
+// NewWriter returns a new Writer that writes to w.
+func NewWriter(w io.Writer) *Writer {
+	return &Writer{
+		Comma: ',',
+		w:     bufio.NewWriter(w),
+	}
+}
+
+// Writer writes a single CSV record to w along with any necessary quoting.
+// A record is a slice of strings with each string being one field.
+func (w *Writer) Write(record []string) (err error) {
+	for n, field := range record {
+		if n > 0 {
+			if _, err = w.w.WriteRune(w.Comma); err != nil {
+				return
+			}
+		}
+
+		// If we don't have to have a quoted field then just
+		// write out the field and continue to the next field.
+		if !w.fieldNeedsQuotes(field) {
+			if _, err = w.w.WriteString(field); err != nil {
+				return
+			}
+			continue
+		}
+		if err = w.w.WriteByte('"'); err != nil {
+			return
+		}
+
+		for _, r1 := range field {
+			switch r1 {
+			case '"':
+				_, err = w.w.WriteString(`""`)
+			case '\r':
+				if !w.UseCRLF {
+					err = w.w.WriteByte('\r')
+				}
+			case '\n':
+				if w.UseCRLF {
+					_, err = w.w.WriteString("\r\n")
+				} else {
+					err = w.w.WriteByte('\n')
+				}
+			default:
+				_, err = w.w.WriteRune(r1)
+			}
+			if err != nil {
+				return
+			}
+		}
+
+		if err = w.w.WriteByte('"'); err != nil {
+			return
+		}
+	}
+	if w.UseCRLF {
+		_, err = w.w.WriteString("\r\n")
+	} else {
+		err = w.w.WriteByte('\n')
+	}
+	return
+}
+
+// Flush writes any buffered data to the underlying io.Writer.
+func (w *Writer) Flush() {
+	w.w.Flush()
+}
+
+// WriteAll writes multiple CSV records to w using Write and then calls Flush.
+func (w *Writer) WriteAll(records [][]string) (err error) {
+	for _, record := range records {
+		err = w.Write(record)
+		if err != nil {
+			break
+		}
+	}
+	w.Flush()
+	return nil
+}
+
+// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
+// Empty fields, files with a Comma, fields with a quote or newline, and
+// fields which start with a space must be enclosed in quotes.
+func (w *Writer) fieldNeedsQuotes(field string) bool {
+	if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
+		return true
+	}
+
+	r1, _ := utf8.DecodeRuneInString(field)
+	return unicode.IsSpace(r1)
+}
diff --git a/src/pkg/csv/writer_test.go b/src/pkg/encoding/csv/writer_test.go
similarity index 100%
rename from src/pkg/csv/writer_test.go
rename to src/pkg/encoding/csv/writer_test.go
diff --git a/src/pkg/encoding/git85/Makefile b/src/pkg/encoding/git85/Makefile
deleted file mode 100644
index fbd0034..0000000
--- a/src/pkg/encoding/git85/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=encoding/git85
-GOFILES=\
-	git.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/encoding/git85/git.go b/src/pkg/encoding/git85/git.go
deleted file mode 100644
index 6bb74f4..0000000
--- a/src/pkg/encoding/git85/git.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package git85 implements the radix 85 data encoding
-// used in the Git version control system.
-package git85
-
-import (
-	"bytes"
-	"io"
-	"os"
-	"strconv"
-)
-
-type CorruptInputError int64
-
-func (e CorruptInputError) String() string {
-	return "illegal git85 data at input byte " + strconv.Itoa64(int64(e))
-}
-
-const encode = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"
-
-// The decodings are 1+ the actual value, so that the
-// default zero value can be used to mean "not valid".
-var decode = [256]uint8{
-	'0': 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
-	'A': 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,
-	'a': 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
-	50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
-	'!': 63,
-	'#': 64, 65, 66, 67,
-	'(': 68, 69, 70, 71,
-	'-': 72,
-	';': 73,
-	'<': 74, 75, 76, 77,
-	'@': 78,
-	'^': 79, 80, 81,
-	'{': 82, 83, 84, 85,
-}
-
-// Encode encodes src into EncodedLen(len(src))
-// bytes of dst.  As a convenience, it returns the number
-// of bytes written to dst, but this value is always EncodedLen(len(src)).
-// Encode implements the radix 85 encoding used in the
-// Git version control tool.
-//
-// The encoding splits src into chunks of at most 52 bytes
-// and encodes each chunk on its own line.
-func Encode(dst, src []byte) int {
-	ndst := 0
-	for len(src) > 0 {
-		n := len(src)
-		if n > 52 {
-			n = 52
-		}
-		if n <= 27 {
-			dst[ndst] = byte('A' + n - 1)
-		} else {
-			dst[ndst] = byte('a' + n - 26 - 1)
-		}
-		ndst++
-		for i := 0; i < n; i += 4 {
-			var v uint32
-			for j := 0; j < 4 && i+j < n; j++ {
-				v |= uint32(src[i+j]) << uint(24-j*8)
-			}
-			for j := 4; j >= 0; j-- {
-				dst[ndst+j] = encode[v%85]
-				v /= 85
-			}
-			ndst += 5
-		}
-		dst[ndst] = '\n'
-		ndst++
-		src = src[n:]
-	}
-	return ndst
-}
-
-// EncodedLen returns the length of an encoding of n source bytes.
-func EncodedLen(n int) int {
-	if n == 0 {
-		return 0
-	}
-	// 5 bytes per 4 bytes of input, rounded up.
-	// 2 extra bytes for each line of 52 src bytes, rounded up.
-	return (n+3)/4*5 + (n+51)/52*2
-}
-
-var newline = []byte{'\n'}
-
-// Decode decodes src into at most MaxDecodedLen(len(src))
-// bytes, returning the actual number of bytes written to dst.
-//
-// If Decode encounters invalid input, it returns a CorruptInputError.
-//
-func Decode(dst, src []byte) (n int, err os.Error) {
-	ndst := 0
-	nsrc := 0
-	for nsrc < len(src) {
-		var l int
-		switch ch := int(src[nsrc]); {
-		case 'A' <= ch && ch <= 'Z':
-			l = ch - 'A' + 1
-		case 'a' <= ch && ch <= 'z':
-			l = ch - 'a' + 26 + 1
-		default:
-			return ndst, CorruptInputError(nsrc)
-		}
-		if nsrc+1+l > len(src) {
-			return ndst, CorruptInputError(nsrc)
-		}
-		el := (l + 3) / 4 * 5 // encoded len
-		if nsrc+1+el+1 > len(src) || src[nsrc+1+el] != '\n' {
-			return ndst, CorruptInputError(nsrc)
-		}
-		line := src[nsrc+1 : nsrc+1+el]
-		for i := 0; i < el; i += 5 {
-			var v uint32
-			for j := 0; j < 5; j++ {
-				ch := decode[line[i+j]]
-				if ch == 0 {
-					return ndst, CorruptInputError(nsrc + 1 + i + j)
-				}
-				v = v*85 + uint32(ch-1)
-			}
-			for j := 0; j < 4; j++ {
-				dst[ndst] = byte(v >> 24)
-				v <<= 8
-				ndst++
-			}
-		}
-		// Last fragment may have run too far (but there was room in dst).
-		// Back up.
-		if l%4 != 0 {
-			ndst -= 4 - l%4
-		}
-		nsrc += 1 + el + 1
-	}
-	return ndst, nil
-}
-
-func MaxDecodedLen(n int) int { return n / 5 * 4 }
-
-// NewEncoder returns a new Git base85 stream encoder.  Data written to
-// the returned writer will be encoded and then written to w.
-// The Git encoding operates on 52-byte blocks; when finished
-// writing, the caller must Close the returned encoder to flush any
-// partially written blocks.
-func NewEncoder(w io.Writer) io.WriteCloser { return &encoder{w: w} }
-
-type encoder struct {
-	w    io.Writer
-	err  os.Error
-	buf  [52]byte
-	nbuf int
-	out  [1024]byte
-	nout int
-}
-
-func (e *encoder) Write(p []byte) (n int, err os.Error) {
-	if e.err != nil {
-		return 0, e.err
-	}
-
-	// Leading fringe.
-	if e.nbuf > 0 {
-		var i int
-		for i = 0; i < len(p) && e.nbuf < 52; i++ {
-			e.buf[e.nbuf] = p[i]
-			e.nbuf++
-		}
-		n += i
-		p = p[i:]
-		if e.nbuf < 52 {
-			return
-		}
-		nout := Encode(e.out[0:], e.buf[0:])
-		if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
-			return n, e.err
-		}
-		e.nbuf = 0
-	}
-
-	// Large interior chunks.
-	for len(p) >= 52 {
-		nn := len(e.out) / (1 + 52/4*5 + 1) * 52
-		if nn > len(p) {
-			nn = len(p) / 52 * 52
-		}
-		if nn > 0 {
-			nout := Encode(e.out[0:], p[0:nn])
-			if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
-				return n, e.err
-			}
-		}
-		n += nn
-		p = p[nn:]
-	}
-
-	// Trailing fringe.
-	for i := 0; i < len(p); i++ {
-		e.buf[i] = p[i]
-	}
-	e.nbuf = len(p)
-	n += len(p)
-	return
-}
-
-func (e *encoder) Close() os.Error {
-	// If there's anything left in the buffer, flush it out
-	if e.err == nil && e.nbuf > 0 {
-		nout := Encode(e.out[0:], e.buf[0:e.nbuf])
-		e.nbuf = 0
-		_, e.err = e.w.Write(e.out[0:nout])
-	}
-	return e.err
-}
-
-// NewDecoder returns a new Git base85 stream decoder.
-func NewDecoder(r io.Reader) io.Reader { return &decoder{r: r} }
-
-type decoder struct {
-	r       io.Reader
-	err     os.Error
-	readErr os.Error
-	buf     [1024]byte
-	nbuf    int
-	out     []byte
-	outbuf  [1024]byte
-	off     int64
-}
-
-func (d *decoder) Read(p []byte) (n int, err os.Error) {
-	if len(p) == 0 {
-		return 0, nil
-	}
-
-	for {
-		// Copy leftover output from last decode.
-		if len(d.out) > 0 {
-			n = copy(p, d.out)
-			d.out = d.out[n:]
-			return
-		}
-
-		// Out of decoded output.  Check errors.
-		if d.err != nil {
-			return 0, d.err
-		}
-		if d.readErr != nil {
-			d.err = d.readErr
-			return 0, d.err
-		}
-
-		// Read and decode more input.
-		var nn int
-		nn, d.readErr = d.r.Read(d.buf[d.nbuf:])
-		d.nbuf += nn
-
-		// Send complete lines to Decode.
-		nl := bytes.LastIndex(d.buf[0:d.nbuf], newline)
-		if nl < 0 {
-			continue
-		}
-		nn, d.err = Decode(d.outbuf[0:], d.buf[0:nl+1])
-		if e, ok := d.err.(CorruptInputError); ok {
-			d.err = CorruptInputError(int64(e) + d.off)
-		}
-		d.out = d.outbuf[0:nn]
-		d.nbuf = copy(d.buf[0:], d.buf[nl+1:d.nbuf])
-		d.off += int64(nl + 1)
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/encoding/git85/git_test.go b/src/pkg/encoding/git85/git_test.go
deleted file mode 100644
index c76385c..0000000
--- a/src/pkg/encoding/git85/git_test.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package git85
-
-import (
-	"bytes"
-	"io/ioutil"
-	"os"
-	"testing"
-)
-
-type testpair struct {
-	decoded, encoded string
-}
-
-func testEqual(t *testing.T, msg string, args ...interface{}) bool {
-	if args[len(args)-2] != args[len(args)-1] {
-		t.Errorf(msg, args...)
-		return false
-	}
-	return true
-}
-
-func TestGitTable(t *testing.T) {
-	var saw [256]bool
-	for i, c := range encode {
-		if decode[c] != uint8(i+1) {
-			t.Errorf("decode['%c'] = %d, want %d", c, decode[c], i+1)
-		}
-		saw[c] = true
-	}
-	for i, b := range saw {
-		if !b && decode[i] != 0 {
-			t.Errorf("decode[%d] = %d, want 0", i, decode[i])
-		}
-	}
-}
-
-var gitPairs = []testpair{
-	// Wikipedia example, adapted.
-	{
-		"Man is distinguished, not only by his reason, but by this singular passion from " +
-			"other animals, which is a lust of the mind, that by a perseverance of delight in " +
-			"the continued and indefatigable generation of knowledge, exceeds the short " +
-			"vehemence of any carnal pleasure.",
-
-		"zO<`^zX>%ZCX>)XGZfA9Ab7*B`EFf-gbRchTY<VDJc_3(Mb0BhMVRLV8EFfZabRc4R\n" +
-			"zAarPHb0BkRZfA9DVR9gFVRLh7Z*CxFa&K)QZ**v7av))DX>DO_b1WctXlY|;AZc?T\n" +
-			"zVIXXEb95kYW*~HEWgu;7Ze%PVbZB98AYyqSVIXj2a&u*NWpZI|V`U(3W*}r`Y-wj`\n" +
-			"zbRcPNAarPDAY*TCbZKsNWn>^>Ze$>7Ze(R<VRUI{VPb4$AZKN6WpZJ3X>V>IZ)PBC\n" +
-			"zZf|#NWn^b%EFfigV`XJzb0BnRWgv5CZ*p`Xc4cT~ZDnp_Wgu^6AYpEKAY);2ZeeU7\n" +
-			"IaBO8^b9HiME&u=k\n",
-	},
-}
-
-var gitBigtest = gitPairs[len(gitPairs)-1]
-
-func TestEncode(t *testing.T) {
-	for _, p := range gitPairs {
-		buf := make([]byte, EncodedLen(len(p.decoded)))
-		n := Encode(buf, []byte(p.decoded))
-		if n != len(buf) {
-			t.Errorf("EncodedLen does not agree with Encode")
-		}
-		buf = buf[0:n]
-		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, string(buf), p.encoded)
-	}
-}
-
-func TestEncoder(t *testing.T) {
-	for _, p := range gitPairs {
-		bb := &bytes.Buffer{}
-		encoder := NewEncoder(bb)
-		encoder.Write([]byte(p.decoded))
-		encoder.Close()
-		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
-	}
-}
-
-func TestEncoderBuffering(t *testing.T) {
-	input := []byte(gitBigtest.decoded)
-	for bs := 1; bs <= 12; bs++ {
-		bb := &bytes.Buffer{}
-		encoder := NewEncoder(bb)
-		for pos := 0; pos < len(input); pos += bs {
-			end := pos + bs
-			if end > len(input) {
-				end = len(input)
-			}
-			n, err := encoder.Write(input[pos:end])
-			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, os.Error(nil))
-			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
-		}
-		err := encoder.Close()
-		testEqual(t, "Close gave error %v, want %v", err, os.Error(nil))
-		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, gitBigtest.decoded, bb.String(), gitBigtest.encoded)
-	}
-}
-
-func TestDecode(t *testing.T) {
-	for _, p := range gitPairs {
-		dbuf := make([]byte, 4*len(p.encoded))
-		ndst, err := Decode(dbuf, []byte(p.encoded))
-		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, os.Error(nil))
-		testEqual(t, "Decode(%q) = ndst %v, want %v", p.encoded, ndst, len(p.decoded))
-		testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:ndst]), p.decoded)
-	}
-}
-
-func TestDecoder(t *testing.T) {
-	for _, p := range gitPairs {
-		decoder := NewDecoder(bytes.NewBufferString(p.encoded))
-		dbuf, err := ioutil.ReadAll(decoder)
-		if err != nil {
-			t.Fatal("Read failed", err)
-		}
-		testEqual(t, "Read from %q = length %v, want %v", p.encoded, len(dbuf), len(p.decoded))
-		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf), p.decoded)
-		if err != nil {
-			testEqual(t, "Read from %q = %v, want %v", p.encoded, err, os.EOF)
-		}
-	}
-}
-
-func TestDecoderBuffering(t *testing.T) {
-	for bs := 1; bs <= 12; bs++ {
-		decoder := NewDecoder(bytes.NewBufferString(gitBigtest.encoded))
-		buf := make([]byte, len(gitBigtest.decoded)+12)
-		var total int
-		for total = 0; total < len(gitBigtest.decoded); {
-			n, err := decoder.Read(buf[total : total+bs])
-			testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", gitBigtest.encoded, total, n, err, os.Error(nil))
-			total += n
-		}
-		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, gitBigtest.encoded, string(buf[0:total]), gitBigtest.decoded)
-	}
-}
-
-func TestDecodeCorrupt(t *testing.T) {
-	type corrupt struct {
-		e string
-		p int
-	}
-	examples := []corrupt{
-		{"v", 0},
-		{"!z!!!!!!!!!", 0},
-	}
-
-	for _, e := range examples {
-		dbuf := make([]byte, 2*len(e.e))
-		_, err := Decode(dbuf, []byte(e.e))
-		switch err := err.(type) {
-		case CorruptInputError:
-			testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
-		default:
-			t.Error("Decoder failed to detect corruption in", e)
-		}
-	}
-}
-
-func TestGitBig(t *testing.T) {
-	n := 3*1000 + 1
-	raw := make([]byte, n)
-	const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
-	for i := 0; i < n; i++ {
-		raw[i] = alpha[i%len(alpha)]
-	}
-	encoded := new(bytes.Buffer)
-	w := NewEncoder(encoded)
-	nn, err := w.Write(raw)
-	if nn != n || err != nil {
-		t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
-	}
-	err = w.Close()
-	if err != nil {
-		t.Fatalf("Encoder.Close() = %v want nil", err)
-	}
-	decoded, err := ioutil.ReadAll(NewDecoder(encoded))
-	if err != nil {
-		t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
-	}
-
-	if !bytes.Equal(raw, decoded) {
-		var i int
-		for i = 0; i < len(decoded) && i < len(raw); i++ {
-			if decoded[i] != raw[i] {
-				break
-			}
-		}
-		t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
-	}
-}
diff --git a/src/pkg/encoding/gob/Makefile b/src/pkg/encoding/gob/Makefile
new file mode 100644
index 0000000..3847edb
--- /dev/null
+++ b/src/pkg/encoding/gob/Makefile
@@ -0,0 +1,25 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=encoding/gob
+GOFILES=\
+	decode.go\
+	decoder.go\
+	doc.go\
+	encode.go\
+	encoder.go\
+	error.go\
+	type.go\
+
+include ../../../Make.pkg
+
+# Help for debugging. Requires adding debug.go to the gob package as well.
+
+dump:	dump.$O
+	$(LD) -o dump $<
+
+dump.$O:	dump.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) $<
diff --git a/src/pkg/encoding/gob/codec_test.go b/src/pkg/encoding/gob/codec_test.go
new file mode 100644
index 0000000..73844b9
--- /dev/null
+++ b/src/pkg/encoding/gob/codec_test.go
@@ -0,0 +1,1409 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+	"bytes"
+	"errors"
+	"math"
+	"reflect"
+	"strings"
+	"testing"
+	"unsafe"
+)
+
+// Guarantee encoding format by comparing some encodings to hand-written values
+type EncodeT struct {
+	x uint64
+	b []byte
+}
+
+var encodeT = []EncodeT{
+	{0x00, []byte{0x00}},
+	{0x0F, []byte{0x0F}},
+	{0xFF, []byte{0xFF, 0xFF}},
+	{0xFFFF, []byte{0xFE, 0xFF, 0xFF}},
+	{0xFFFFFF, []byte{0xFD, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFF, []byte{0xFC, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFFFF, []byte{0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFFFFFF, []byte{0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFFFFFFFF, []byte{0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0xFFFFFFFFFFFFFFFF, []byte{0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
+	{0x1111, []byte{0xFE, 0x11, 0x11}},
+	{0x1111111111111111, []byte{0xF8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
+	{0x8888888888888888, []byte{0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}},
+	{1 << 63, []byte{0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+}
+
+// testError is meant to be used as a deferred function to turn a panic(gobError) into a
+// plain test.Error call.
+func testError(t *testing.T) {
+	if e := recover(); e != nil {
+		t.Error(e.(gobError).err) // Will re-panic if not one of our errors, such as a runtime error.
+	}
+	return
+}
+
+// Test basic encode/decode routines for unsigned integers
+func TestUintCodec(t *testing.T) {
+	defer testError(t)
+	b := new(bytes.Buffer)
+	encState := newEncoderState(b)
+	for _, tt := range encodeT {
+		b.Reset()
+		encState.encodeUint(tt.x)
+		if !bytes.Equal(tt.b, b.Bytes()) {
+			t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes())
+		}
+	}
+	decState := newDecodeState(b)
+	for u := uint64(0); ; u = (u + 1) * 7 {
+		b.Reset()
+		encState.encodeUint(u)
+		v := decState.decodeUint()
+		if u != v {
+			t.Errorf("Encode/Decode: sent %#x received %#x", u, v)
+		}
+		if u&(1<<63) != 0 {
+			break
+		}
+	}
+}
+
+func verifyInt(i int64, t *testing.T) {
+	defer testError(t)
+	var b = new(bytes.Buffer)
+	encState := newEncoderState(b)
+	encState.encodeInt(i)
+	decState := newDecodeState(b)
+	decState.buf = make([]byte, 8)
+	j := decState.decodeInt()
+	if i != j {
+		t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j))
+	}
+}
+
+// Test basic encode/decode routines for signed integers
+func TestIntCodec(t *testing.T) {
+	for u := uint64(0); ; u = (u + 1) * 7 {
+		// Do positive and negative values
+		i := int64(u)
+		verifyInt(i, t)
+		verifyInt(-i, t)
+		verifyInt(^i, t)
+		if u&(1<<63) != 0 {
+			break
+		}
+	}
+	verifyInt(-1<<63, t) // a tricky case
+}
+
+// The result of encoding a true boolean with field number 7
+var boolResult = []byte{0x07, 0x01}
+
+// The result of encoding a number 17 with field number 7
+var signedResult = []byte{0x07, 2 * 17}
+var unsignedResult = []byte{0x07, 17}
+var floatResult = []byte{0x07, 0xFE, 0x31, 0x40}
+
+// The result of encoding a number 17+19i with field number 7
+var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40}
+
+// The result of encoding "hello" with field number 7
+var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
+
+func newDecodeState(buf *bytes.Buffer) *decoderState {
+	d := new(decoderState)
+	d.b = buf
+	d.buf = make([]byte, uint64Size)
+	return d
+}
+
+func newEncoderState(b *bytes.Buffer) *encoderState {
+	b.Reset()
+	state := &encoderState{enc: nil, b: b}
+	state.fieldnum = -1
+	return state
+}
+
+// Test instruction execution for encoding.
+// Do not run the machine yet; instead do individual instructions crafted by hand.
+func TestScalarEncInstructions(t *testing.T) {
+	var b = new(bytes.Buffer)
+
+	// bool
+	{
+		data := struct{ a bool }{true}
+		instr := &encInstr{encBool, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(boolResult, b.Bytes()) {
+			t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes())
+		}
+	}
+
+	// int
+	{
+		b.Reset()
+		data := struct{ a int }{17}
+		instr := &encInstr{encInt, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint
+	{
+		b.Reset()
+		data := struct{ a uint }{17}
+		instr := &encInstr{encUint, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// int8
+	{
+		b.Reset()
+		data := struct{ a int8 }{17}
+		instr := &encInstr{encInt8, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint8
+	{
+		b.Reset()
+		data := struct{ a uint8 }{17}
+		instr := &encInstr{encUint8, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// int16
+	{
+		b.Reset()
+		data := struct{ a int16 }{17}
+		instr := &encInstr{encInt16, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint16
+	{
+		b.Reset()
+		data := struct{ a uint16 }{17}
+		instr := &encInstr{encUint16, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// int32
+	{
+		b.Reset()
+		data := struct{ a int32 }{17}
+		instr := &encInstr{encInt32, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint32
+	{
+		b.Reset()
+		data := struct{ a uint32 }{17}
+		instr := &encInstr{encUint32, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// int64
+	{
+		b.Reset()
+		data := struct{ a int64 }{17}
+		instr := &encInstr{encInt64, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(signedResult, b.Bytes()) {
+			t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes())
+		}
+	}
+
+	// uint64
+	{
+		b.Reset()
+		data := struct{ a uint64 }{17}
+		instr := &encInstr{encUint64, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(unsignedResult, b.Bytes()) {
+			t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
+		}
+	}
+
+	// float32
+	{
+		b.Reset()
+		data := struct{ a float32 }{17}
+		instr := &encInstr{encFloat32, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(floatResult, b.Bytes()) {
+			t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes())
+		}
+	}
+
+	// float64
+	{
+		b.Reset()
+		data := struct{ a float64 }{17}
+		instr := &encInstr{encFloat64, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(floatResult, b.Bytes()) {
+			t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes())
+		}
+	}
+
+	// bytes == []uint8
+	{
+		b.Reset()
+		data := struct{ a []byte }{[]byte("hello")}
+		instr := &encInstr{encUint8Array, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(bytesResult, b.Bytes()) {
+			t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes())
+		}
+	}
+
+	// string
+	{
+		b.Reset()
+		data := struct{ a string }{"hello"}
+		instr := &encInstr{encString, 6, 0, 0}
+		state := newEncoderState(b)
+		instr.op(instr, state, unsafe.Pointer(&data))
+		if !bytes.Equal(bytesResult, b.Bytes()) {
+			t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes())
+		}
+	}
+}
+
+func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, p unsafe.Pointer) {
+	defer testError(t)
+	v := int(state.decodeUint())
+	if v+state.fieldnum != 6 {
+		t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum)
+	}
+	instr.op(instr, state, decIndirect(p, instr.indir))
+	state.fieldnum = 6
+}
+
+func newDecodeStateFromData(data []byte) *decoderState {
+	b := bytes.NewBuffer(data)
+	state := newDecodeState(b)
+	state.fieldnum = -1
+	return state
+}
+
+// Test instruction execution for decoding.
+// Do not run the machine yet; instead do individual instructions crafted by hand.
+func TestScalarDecInstructions(t *testing.T) {
+	ovfl := errors.New("overflow")
+
+	// bool
+	{
+		var data struct {
+			a bool
+		}
+		instr := &decInstr{decBool, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(boolResult)
+		execDec("bool", instr, state, t, unsafe.Pointer(&data))
+		if data.a != true {
+			t.Errorf("bool a = %v not true", data.a)
+		}
+	}
+	// int
+	{
+		var data struct {
+			a int
+		}
+		instr := &decInstr{decOpTable[reflect.Int], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int a = %v not 17", data.a)
+		}
+	}
+
+	// uint
+	{
+		var data struct {
+			a uint
+		}
+		instr := &decInstr{decOpTable[reflect.Uint], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint a = %v not 17", data.a)
+		}
+	}
+
+	// int8
+	{
+		var data struct {
+			a int8
+		}
+		instr := &decInstr{decInt8, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int8", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int8 a = %v not 17", data.a)
+		}
+	}
+
+	// uint8
+	{
+		var data struct {
+			a uint8
+		}
+		instr := &decInstr{decUint8, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint8", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint8 a = %v not 17", data.a)
+		}
+	}
+
+	// int16
+	{
+		var data struct {
+			a int16
+		}
+		instr := &decInstr{decInt16, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int16", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int16 a = %v not 17", data.a)
+		}
+	}
+
+	// uint16
+	{
+		var data struct {
+			a uint16
+		}
+		instr := &decInstr{decUint16, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint16", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint16 a = %v not 17", data.a)
+		}
+	}
+
+	// int32
+	{
+		var data struct {
+			a int32
+		}
+		instr := &decInstr{decInt32, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int32", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int32 a = %v not 17", data.a)
+		}
+	}
+
+	// uint32
+	{
+		var data struct {
+			a uint32
+		}
+		instr := &decInstr{decUint32, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint32", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint32 a = %v not 17", data.a)
+		}
+	}
+
+	// uintptr
+	{
+		var data struct {
+			a uintptr
+		}
+		instr := &decInstr{decOpTable[reflect.Uintptr], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uintptr", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uintptr a = %v not 17", data.a)
+		}
+	}
+
+	// int64
+	{
+		var data struct {
+			a int64
+		}
+		instr := &decInstr{decInt64, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(signedResult)
+		execDec("int64", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("int64 a = %v not 17", data.a)
+		}
+	}
+
+	// uint64
+	{
+		var data struct {
+			a uint64
+		}
+		instr := &decInstr{decUint64, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(unsignedResult)
+		execDec("uint64", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("uint64 a = %v not 17", data.a)
+		}
+	}
+
+	// float32
+	{
+		var data struct {
+			a float32
+		}
+		instr := &decInstr{decFloat32, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(floatResult)
+		execDec("float32", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("float32 a = %v not 17", data.a)
+		}
+	}
+
+	// float64
+	{
+		var data struct {
+			a float64
+		}
+		instr := &decInstr{decFloat64, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(floatResult)
+		execDec("float64", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17 {
+			t.Errorf("float64 a = %v not 17", data.a)
+		}
+	}
+
+	// complex64
+	{
+		var data struct {
+			a complex64
+		}
+		instr := &decInstr{decOpTable[reflect.Complex64], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(complexResult)
+		execDec("complex", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17+19i {
+			t.Errorf("complex a = %v not 17+19i", data.a)
+		}
+	}
+
+	// complex128
+	{
+		var data struct {
+			a complex128
+		}
+		instr := &decInstr{decOpTable[reflect.Complex128], 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(complexResult)
+		execDec("complex", instr, state, t, unsafe.Pointer(&data))
+		if data.a != 17+19i {
+			t.Errorf("complex a = %v not 17+19i", data.a)
+		}
+	}
+
+	// bytes == []uint8
+	{
+		var data struct {
+			a []byte
+		}
+		instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(bytesResult)
+		execDec("bytes", instr, state, t, unsafe.Pointer(&data))
+		if string(data.a) != "hello" {
+			t.Errorf(`bytes a = %q not "hello"`, string(data.a))
+		}
+	}
+
+	// string
+	{
+		var data struct {
+			a string
+		}
+		instr := &decInstr{decString, 6, 0, 0, ovfl}
+		state := newDecodeStateFromData(bytesResult)
+		execDec("bytes", instr, state, t, unsafe.Pointer(&data))
+		if data.a != "hello" {
+			t.Errorf(`bytes a = %q not "hello"`, data.a)
+		}
+	}
+}
+
+func TestEndToEnd(t *testing.T) {
+	type T2 struct {
+		T string
+	}
+	s1 := "string1"
+	s2 := "string2"
+	type T1 struct {
+		A, B, C  int
+		M        map[string]*float64
+		EmptyMap map[string]int // to check that we receive a non-nil map.
+		N        *[3]float64
+		Strs     *[2]string
+		Int64s   *[]int64
+		RI       complex64
+		S        string
+		Y        []byte
+		T        *T2
+	}
+	pi := 3.14159
+	e := 2.71828
+	t1 := &T1{
+		A:        17,
+		B:        18,
+		C:        -5,
+		M:        map[string]*float64{"pi": &pi, "e": &e},
+		EmptyMap: make(map[string]int),
+		N:        &[3]float64{1.5, 2.5, 3.5},
+		Strs:     &[2]string{s1, s2},
+		Int64s:   &[]int64{77, 89, 123412342134},
+		RI:       17 - 23i,
+		S:        "Now is the time",
+		Y:        []byte("hello, sailor"),
+		T:        &T2{"this is T2"},
+	}
+	b := new(bytes.Buffer)
+	err := NewEncoder(b).Encode(t1)
+	if err != nil {
+		t.Error("encode:", err)
+	}
+	var _t1 T1
+	err = NewDecoder(b).Decode(&_t1)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(t1, &_t1) {
+		t.Errorf("encode expected %v got %v", *t1, _t1)
+	}
+	// Be absolutely sure the received map is non-nil.
+	if t1.EmptyMap == nil {
+		t.Errorf("nil map sent")
+	}
+	if _t1.EmptyMap == nil {
+		t.Errorf("nil map received")
+	}
+}
+
+func TestOverflow(t *testing.T) {
+	type inputT struct {
+		Maxi int64
+		Mini int64
+		Maxu uint64
+		Maxf float64
+		Minf float64
+		Maxc complex128
+		Minc complex128
+	}
+	var it inputT
+	var err error
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	dec := NewDecoder(b)
+
+	// int8
+	b.Reset()
+	it = inputT{
+		Maxi: math.MaxInt8 + 1,
+	}
+	type outi8 struct {
+		Maxi int8
+		Mini int8
+	}
+	var o1 outi8
+	enc.Encode(it)
+	err = dec.Decode(&o1)
+	if err == nil || err.Error() != `value for "Maxi" out of range` {
+		t.Error("wrong overflow error for int8:", err)
+	}
+	it = inputT{
+		Mini: math.MinInt8 - 1,
+	}
+	b.Reset()
+	enc.Encode(it)
+	err = dec.Decode(&o1)
+	if err == nil || err.Error() != `value for "Mini" out of range` {
+		t.Error("wrong underflow error for int8:", err)
+	}
+
+	// int16
+	b.Reset()
+	it = inputT{
+		Maxi: math.MaxInt16 + 1,
+	}
+	type outi16 struct {
+		Maxi int16
+		Mini int16
+	}
+	var o2 outi16
+	enc.Encode(it)
+	err = dec.Decode(&o2)
+	if err == nil || err.Error() != `value for "Maxi" out of range` {
+		t.Error("wrong overflow error for int16:", err)
+	}
+	it = inputT{
+		Mini: math.MinInt16 - 1,
+	}
+	b.Reset()
+	enc.Encode(it)
+	err = dec.Decode(&o2)
+	if err == nil || err.Error() != `value for "Mini" out of range` {
+		t.Error("wrong underflow error for int16:", err)
+	}
+
+	// int32
+	b.Reset()
+	it = inputT{
+		Maxi: math.MaxInt32 + 1,
+	}
+	type outi32 struct {
+		Maxi int32
+		Mini int32
+	}
+	var o3 outi32
+	enc.Encode(it)
+	err = dec.Decode(&o3)
+	if err == nil || err.Error() != `value for "Maxi" out of range` {
+		t.Error("wrong overflow error for int32:", err)
+	}
+	it = inputT{
+		Mini: math.MinInt32 - 1,
+	}
+	b.Reset()
+	enc.Encode(it)
+	err = dec.Decode(&o3)
+	if err == nil || err.Error() != `value for "Mini" out of range` {
+		t.Error("wrong underflow error for int32:", err)
+	}
+
+	// uint8
+	b.Reset()
+	it = inputT{
+		Maxu: math.MaxUint8 + 1,
+	}
+	type outu8 struct {
+		Maxu uint8
+	}
+	var o4 outu8
+	enc.Encode(it)
+	err = dec.Decode(&o4)
+	if err == nil || err.Error() != `value for "Maxu" out of range` {
+		t.Error("wrong overflow error for uint8:", err)
+	}
+
+	// uint16
+	b.Reset()
+	it = inputT{
+		Maxu: math.MaxUint16 + 1,
+	}
+	type outu16 struct {
+		Maxu uint16
+	}
+	var o5 outu16
+	enc.Encode(it)
+	err = dec.Decode(&o5)
+	if err == nil || err.Error() != `value for "Maxu" out of range` {
+		t.Error("wrong overflow error for uint16:", err)
+	}
+
+	// uint32
+	b.Reset()
+	it = inputT{
+		Maxu: math.MaxUint32 + 1,
+	}
+	type outu32 struct {
+		Maxu uint32
+	}
+	var o6 outu32
+	enc.Encode(it)
+	err = dec.Decode(&o6)
+	if err == nil || err.Error() != `value for "Maxu" out of range` {
+		t.Error("wrong overflow error for uint32:", err)
+	}
+
+	// float32
+	b.Reset()
+	it = inputT{
+		Maxf: math.MaxFloat32 * 2,
+	}
+	type outf32 struct {
+		Maxf float32
+		Minf float32
+	}
+	var o7 outf32
+	enc.Encode(it)
+	err = dec.Decode(&o7)
+	if err == nil || err.Error() != `value for "Maxf" out of range` {
+		t.Error("wrong overflow error for float32:", err)
+	}
+
+	// complex64
+	b.Reset()
+	it = inputT{
+		Maxc: complex(math.MaxFloat32*2, math.MaxFloat32*2),
+	}
+	type outc64 struct {
+		Maxc complex64
+		Minc complex64
+	}
+	var o8 outc64
+	enc.Encode(it)
+	err = dec.Decode(&o8)
+	if err == nil || err.Error() != `value for "Maxc" out of range` {
+		t.Error("wrong overflow error for complex64:", err)
+	}
+}
+
+func TestNesting(t *testing.T) {
+	type RT struct {
+		A    string
+		Next *RT
+	}
+	rt := new(RT)
+	rt.A = "level1"
+	rt.Next = new(RT)
+	rt.Next.A = "level2"
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(rt)
+	var drt RT
+	dec := NewDecoder(b)
+	err := dec.Decode(&drt)
+	if err != nil {
+		t.Fatal("decoder error:", err)
+	}
+	if drt.A != rt.A {
+		t.Errorf("nesting: encode expected %v got %v", *rt, drt)
+	}
+	if drt.Next == nil {
+		t.Errorf("nesting: recursion failed")
+	}
+	if drt.Next.A != rt.Next.A {
+		t.Errorf("nesting: encode expected %v got %v", *rt.Next, *drt.Next)
+	}
+}
+
+// These three structures have the same data with different indirections
+type T0 struct {
+	A int
+	B int
+	C int
+	D int
+}
+type T1 struct {
+	A int
+	B *int
+	C **int
+	D ***int
+}
+type T2 struct {
+	A ***int
+	B **int
+	C *int
+	D int
+}
+
+func TestAutoIndirection(t *testing.T) {
+	// First transfer t1 into t0
+	var t1 T1
+	t1.A = 17
+	t1.B = new(int)
+	*t1.B = 177
+	t1.C = new(*int)
+	*t1.C = new(int)
+	**t1.C = 1777
+	t1.D = new(**int)
+	*t1.D = new(*int)
+	**t1.D = new(int)
+	***t1.D = 17777
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	enc.Encode(t1)
+	dec := NewDecoder(b)
+	var t0 T0
+	dec.Decode(&t0)
+	if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
+		t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0)
+	}
+
+	// Now transfer t2 into t0
+	var t2 T2
+	t2.D = 17777
+	t2.C = new(int)
+	*t2.C = 1777
+	t2.B = new(*int)
+	*t2.B = new(int)
+	**t2.B = 177
+	t2.A = new(**int)
+	*t2.A = new(*int)
+	**t2.A = new(int)
+	***t2.A = 17
+	b.Reset()
+	enc.Encode(t2)
+	t0 = T0{}
+	dec.Decode(&t0)
+	if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
+		t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0)
+	}
+
+	// Now transfer t0 into t1
+	t0 = T0{17, 177, 1777, 17777}
+	b.Reset()
+	enc.Encode(t0)
+	t1 = T1{}
+	dec.Decode(&t1)
+	if t1.A != 17 || *t1.B != 177 || **t1.C != 1777 || ***t1.D != 17777 {
+		t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.A, *t1.B, **t1.C, ***t1.D)
+	}
+
+	// Now transfer t0 into t2
+	b.Reset()
+	enc.Encode(t0)
+	t2 = T2{}
+	dec.Decode(&t2)
+	if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
+		t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
+	}
+
+	// Now do t2 again but without pre-allocated pointers.
+	b.Reset()
+	enc.Encode(t0)
+	***t2.A = 0
+	**t2.B = 0
+	*t2.C = 0
+	t2.D = 0
+	dec.Decode(&t2)
+	if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
+		t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
+	}
+}
+
+type RT0 struct {
+	A int
+	B string
+	C float64
+}
+type RT1 struct {
+	C      float64
+	B      string
+	A      int
+	NotSet string
+}
+
+func TestReorderedFields(t *testing.T) {
+	var rt0 RT0
+	rt0.A = 17
+	rt0.B = "hello"
+	rt0.C = 3.14159
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(rt0)
+	dec := NewDecoder(b)
+	var rt1 RT1
+	// Wire type is RT0, local type is RT1.
+	err := dec.Decode(&rt1)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if rt0.A != rt1.A || rt0.B != rt1.B || rt0.C != rt1.C {
+		t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1)
+	}
+}
+
+// Like an RT0 but with fields we'll ignore on the decode side.
+type IT0 struct {
+	A        int64
+	B        string
+	Ignore_d []int
+	Ignore_e [3]float64
+	Ignore_f bool
+	Ignore_g string
+	Ignore_h []byte
+	Ignore_i *RT1
+	Ignore_m map[string]int
+	C        float64
+}
+
+func TestIgnoredFields(t *testing.T) {
+	var it0 IT0
+	it0.A = 17
+	it0.B = "hello"
+	it0.C = 3.14159
+	it0.Ignore_d = []int{1, 2, 3}
+	it0.Ignore_e[0] = 1.0
+	it0.Ignore_e[1] = 2.0
+	it0.Ignore_e[2] = 3.0
+	it0.Ignore_f = true
+	it0.Ignore_g = "pay no attention"
+	it0.Ignore_h = []byte("to the curtain")
+	it0.Ignore_i = &RT1{3.1, "hi", 7, "hello"}
+	it0.Ignore_m = map[string]int{"one": 1, "two": 2}
+
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(it0)
+	dec := NewDecoder(b)
+	var rt1 RT1
+	// Wire type is IT0, local type is RT1.
+	err := dec.Decode(&rt1)
+	if err != nil {
+		t.Error("error: ", err)
+	}
+	if int(it0.A) != rt1.A || it0.B != rt1.B || it0.C != rt1.C {
+		t.Errorf("rt0->rt1: expected %v; got %v", it0, rt1)
+	}
+}
+
+func TestBadRecursiveType(t *testing.T) {
+	type Rec ***Rec
+	var rec Rec
+	b := new(bytes.Buffer)
+	err := NewEncoder(b).Encode(&rec)
+	if err == nil {
+		t.Error("expected error; got none")
+	} else if strings.Index(err.Error(), "recursive") < 0 {
+		t.Error("expected recursive type error; got", err)
+	}
+	// Can't test decode easily because we can't encode one, so we can't pass one to a Decoder.
+}
+
+type Bad0 struct {
+	CH chan int
+	C  float64
+}
+
+func TestInvalidField(t *testing.T) {
+	var bad0 Bad0
+	bad0.CH = make(chan int)
+	b := new(bytes.Buffer)
+	dummyEncoder := new(Encoder) // sufficient for this purpose.
+	dummyEncoder.encode(b, reflect.ValueOf(&bad0), userType(reflect.TypeOf(&bad0)))
+	if err := dummyEncoder.err; err == nil {
+		t.Error("expected error; got none")
+	} else if strings.Index(err.Error(), "type") < 0 {
+		t.Error("expected type error; got", err)
+	}
+}
+
+type Indirect struct {
+	A ***[3]int
+	S ***[]int
+	M ****map[string]int
+}
+
+type Direct struct {
+	A [3]int
+	S []int
+	M map[string]int
+}
+
+func TestIndirectSliceMapArray(t *testing.T) {
+	// Marshal indirect, unmarshal to direct.
+	i := new(Indirect)
+	i.A = new(**[3]int)
+	*i.A = new(*[3]int)
+	**i.A = new([3]int)
+	***i.A = [3]int{1, 2, 3}
+	i.S = new(**[]int)
+	*i.S = new(*[]int)
+	**i.S = new([]int)
+	***i.S = []int{4, 5, 6}
+	i.M = new(***map[string]int)
+	*i.M = new(**map[string]int)
+	**i.M = new(*map[string]int)
+	***i.M = new(map[string]int)
+	****i.M = map[string]int{"one": 1, "two": 2, "three": 3}
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(i)
+	dec := NewDecoder(b)
+	var d Direct
+	err := dec.Decode(&d)
+	if err != nil {
+		t.Error("error: ", err)
+	}
+	if len(d.A) != 3 || d.A[0] != 1 || d.A[1] != 2 || d.A[2] != 3 {
+		t.Errorf("indirect to direct: d.A is %v not %v", d.A, ***i.A)
+	}
+	if len(d.S) != 3 || d.S[0] != 4 || d.S[1] != 5 || d.S[2] != 6 {
+		t.Errorf("indirect to direct: d.S is %v not %v", d.S, ***i.S)
+	}
+	if len(d.M) != 3 || d.M["one"] != 1 || d.M["two"] != 2 || d.M["three"] != 3 {
+		t.Errorf("indirect to direct: d.M is %v not %v", d.M, ***i.M)
+	}
+	// Marshal direct, unmarshal to indirect.
+	d.A = [3]int{11, 22, 33}
+	d.S = []int{44, 55, 66}
+	d.M = map[string]int{"four": 4, "five": 5, "six": 6}
+	i = new(Indirect)
+	b.Reset()
+	NewEncoder(b).Encode(d)
+	dec = NewDecoder(b)
+	err = dec.Decode(&i)
+	if err != nil {
+		t.Fatal("error: ", err)
+	}
+	if len(***i.A) != 3 || (***i.A)[0] != 11 || (***i.A)[1] != 22 || (***i.A)[2] != 33 {
+		t.Errorf("direct to indirect: ***i.A is %v not %v", ***i.A, d.A)
+	}
+	if len(***i.S) != 3 || (***i.S)[0] != 44 || (***i.S)[1] != 55 || (***i.S)[2] != 66 {
+		t.Errorf("direct to indirect: ***i.S is %v not %v", ***i.S, ***i.S)
+	}
+	if len(****i.M) != 3 || (****i.M)["four"] != 4 || (****i.M)["five"] != 5 || (****i.M)["six"] != 6 {
+		t.Errorf("direct to indirect: ****i.M is %v not %v", ****i.M, d.M)
+	}
+}
+
+// An interface with several implementations
+type Squarer interface {
+	Square() int
+}
+
+type Int int
+
+func (i Int) Square() int {
+	return int(i * i)
+}
+
+type Float float64
+
+func (f Float) Square() int {
+	return int(f * f)
+}
+
+type Vector []int
+
+func (v Vector) Square() int {
+	sum := 0
+	for _, x := range v {
+		sum += x * x
+	}
+	return sum
+}
+
+type Point struct {
+	X, Y int
+}
+
+func (p Point) Square() int {
+	return p.X*p.X + p.Y*p.Y
+}
+
+// A struct with interfaces in it.
+type InterfaceItem struct {
+	I             int
+	Sq1, Sq2, Sq3 Squarer
+	F             float64
+	Sq            []Squarer
+}
+
+// The same struct without interfaces
+type NoInterfaceItem struct {
+	I int
+	F float64
+}
+
+func TestInterface(t *testing.T) {
+	iVal := Int(3)
+	fVal := Float(5)
+	// Sending a Vector will require that the receiver define a type in the middle of
+	// receiving the value for item2.
+	vVal := Vector{1, 2, 3}
+	b := new(bytes.Buffer)
+	item1 := &InterfaceItem{1, iVal, fVal, vVal, 11.5, []Squarer{iVal, fVal, nil, vVal}}
+	// Register the types.
+	Register(Int(0))
+	Register(Float(0))
+	Register(Vector{})
+	err := NewEncoder(b).Encode(item1)
+	if err != nil {
+		t.Error("expected no encode error; got", err)
+	}
+
+	item2 := InterfaceItem{}
+	err = NewDecoder(b).Decode(&item2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if item2.I != item1.I {
+		t.Error("normal int did not decode correctly")
+	}
+	if item2.Sq1 == nil || item2.Sq1.Square() != iVal.Square() {
+		t.Error("Int did not decode correctly")
+	}
+	if item2.Sq2 == nil || item2.Sq2.Square() != fVal.Square() {
+		t.Error("Float did not decode correctly")
+	}
+	if item2.Sq3 == nil || item2.Sq3.Square() != vVal.Square() {
+		t.Error("Vector did not decode correctly")
+	}
+	if item2.F != item1.F {
+		t.Error("normal float did not decode correctly")
+	}
+	// Now check that we received a slice of Squarers correctly, including a nil element
+	if len(item1.Sq) != len(item2.Sq) {
+		t.Fatalf("[]Squarer length wrong: got %d; expected %d", len(item2.Sq), len(item1.Sq))
+	}
+	for i, v1 := range item1.Sq {
+		v2 := item2.Sq[i]
+		if v1 == nil || v2 == nil {
+			if v1 != nil || v2 != nil {
+				t.Errorf("item %d inconsistent nils", i)
+			}
+			continue
+			if v1.Square() != v2.Square() {
+				t.Errorf("item %d inconsistent values: %v %v", i, v1, v2)
+			}
+		}
+	}
+}
+
+// A struct with all basic types, stored in interfaces.
+type BasicInterfaceItem struct {
+	Int, Int8, Int16, Int32, Int64      interface{}
+	Uint, Uint8, Uint16, Uint32, Uint64 interface{}
+	Float32, Float64                    interface{}
+	Complex64, Complex128               interface{}
+	Bool                                interface{}
+	String                              interface{}
+	Bytes                               interface{}
+}
+
+func TestInterfaceBasic(t *testing.T) {
+	b := new(bytes.Buffer)
+	item1 := &BasicInterfaceItem{
+		int(1), int8(1), int16(1), int32(1), int64(1),
+		uint(1), uint8(1), uint16(1), uint32(1), uint64(1),
+		float32(1), 1.0,
+		complex64(1i), complex128(1i),
+		true,
+		"hello",
+		[]byte("sailor"),
+	}
+	err := NewEncoder(b).Encode(item1)
+	if err != nil {
+		t.Error("expected no encode error; got", err)
+	}
+
+	item2 := &BasicInterfaceItem{}
+	err = NewDecoder(b).Decode(&item2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(item1, item2) {
+		t.Errorf("encode expected %v got %v", item1, item2)
+	}
+	// Hand check a couple for correct types.
+	if v, ok := item2.Bool.(bool); !ok || !v {
+		t.Error("boolean should be true")
+	}
+	if v, ok := item2.String.(string); !ok || v != item1.String.(string) {
+		t.Errorf("string should be %v is %v", item1.String, v)
+	}
+}
+
+type String string
+
+type PtrInterfaceItem struct {
+	Str1 interface{} // basic
+	Str2 interface{} // derived
+}
+
+// We'll send pointers; should receive values.
+// Also check that we can register T but send *T.
+func TestInterfacePointer(t *testing.T) {
+	b := new(bytes.Buffer)
+	str1 := "howdy"
+	str2 := String("kiddo")
+	item1 := &PtrInterfaceItem{
+		&str1,
+		&str2,
+	}
+	// Register the type.
+	Register(str2)
+	err := NewEncoder(b).Encode(item1)
+	if err != nil {
+		t.Error("expected no encode error; got", err)
+	}
+
+	item2 := &PtrInterfaceItem{}
+	err = NewDecoder(b).Decode(&item2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	// Hand test for correct types and values.
+	if v, ok := item2.Str1.(string); !ok || v != str1 {
+		t.Errorf("basic string failed: %q should be %q", v, str1)
+	}
+	if v, ok := item2.Str2.(String); !ok || v != str2 {
+		t.Errorf("derived type String failed: %q should be %q", v, str2)
+	}
+}
+
+func TestIgnoreInterface(t *testing.T) {
+	iVal := Int(3)
+	fVal := Float(5)
+	// Sending a Point will require that the receiver define a type in the middle of
+	// receiving the value for item2.
+	pVal := Point{2, 3}
+	b := new(bytes.Buffer)
+	item1 := &InterfaceItem{1, iVal, fVal, pVal, 11.5, nil}
+	// Register the types.
+	Register(Int(0))
+	Register(Float(0))
+	Register(Point{})
+	err := NewEncoder(b).Encode(item1)
+	if err != nil {
+		t.Error("expected no encode error; got", err)
+	}
+
+	item2 := NoInterfaceItem{}
+	err = NewDecoder(b).Decode(&item2)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if item2.I != item1.I {
+		t.Error("normal int did not decode correctly")
+	}
+	if item2.F != item2.F {
+		t.Error("normal float did not decode correctly")
+	}
+}
+
+type U struct {
+	A int
+	B string
+	c float64
+	D uint
+}
+
+func TestUnexportedFields(t *testing.T) {
+	var u0 U
+	u0.A = 17
+	u0.B = "hello"
+	u0.c = 3.14159
+	u0.D = 23
+	b := new(bytes.Buffer)
+	NewEncoder(b).Encode(u0)
+	dec := NewDecoder(b)
+	var u1 U
+	u1.c = 1234.
+	err := dec.Decode(&u1)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D {
+		t.Errorf("u1->u0: expected %v; got %v", u0, u1)
+	}
+	if u1.c != 1234. {
+		t.Error("u1.c modified")
+	}
+}
+
+var singletons = []interface{}{
+	true,
+	7,
+	3.2,
+	"hello",
+	[3]int{11, 22, 33},
+	[]float32{0.5, 0.25, 0.125},
+	map[string]int{"one": 1, "two": 2},
+}
+
+func TestDebugSingleton(t *testing.T) {
+	if debugFunc == nil {
+		return
+	}
+	b := new(bytes.Buffer)
+	// Accumulate a number of values and print them out all at once.
+	for _, x := range singletons {
+		err := NewEncoder(b).Encode(x)
+		if err != nil {
+			t.Fatal("encode:", err)
+		}
+	}
+	debugFunc(b)
+}
+
+// A type that won't be defined in the gob until we send it in an interface value.
+type OnTheFly struct {
+	A int
+}
+
+type DT struct {
+	//	X OnTheFly
+	A     int
+	B     string
+	C     float64
+	I     interface{}
+	J     interface{}
+	I_nil interface{}
+	M     map[string]int
+	T     [3]int
+	S     []string
+}
+
+func TestDebugStruct(t *testing.T) {
+	if debugFunc == nil {
+		return
+	}
+	Register(OnTheFly{})
+	var dt DT
+	dt.A = 17
+	dt.B = "hello"
+	dt.C = 3.14159
+	dt.I = 271828
+	dt.J = OnTheFly{3}
+	dt.I_nil = nil
+	dt.M = map[string]int{"one": 1, "two": 2}
+	dt.T = [3]int{11, 22, 33}
+	dt.S = []string{"hi", "joe"}
+	b := new(bytes.Buffer)
+	err := NewEncoder(b).Encode(dt)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	debugBuffer := bytes.NewBuffer(b.Bytes())
+	dt2 := &DT{}
+	err = NewDecoder(b).Decode(&dt2)
+	if err != nil {
+		t.Error("decode:", err)
+	}
+	debugFunc(debugBuffer)
+}
diff --git a/src/pkg/encoding/gob/debug.go b/src/pkg/encoding/gob/debug.go
new file mode 100644
index 0000000..6dc7fc9
--- /dev/null
+++ b/src/pkg/encoding/gob/debug.go
@@ -0,0 +1,694 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Delete the next line to include this file in the gob package.
+// +build ignore
+
+package gob
+
+// This file is not normally included in the gob package.  Used only for debugging the package itself.
+// Add debug.go to the files listed in the Makefile to add Debug to the gob package.
+// Except for reading uints, it is an implementation of a reader that is independent of
+// the one implemented by Decoder.
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"sync"
+)
+
+var dumpBytes = false // If true, print the remaining bytes in the input buffer at each item.
+
+// Init installs the debugging facility. If this file is not compiled in the
+// package, the tests in codec_test.go are no-ops.
+func init() {
+	debugFunc = Debug
+}
+
+var (
+	blanks = bytes.Repeat([]byte{' '}, 3*10)
+	empty  = []byte(": <empty>\n")
+	tabs   = strings.Repeat("\t", 100)
+)
+
+// tab indents itself when printed.
+type tab int
+
+func (t tab) String() string {
+	n := int(t)
+	if n > len(tabs) {
+		n = len(tabs)
+	}
+	return tabs[0:n]
+}
+
+func (t tab) print() {
+	fmt.Fprint(os.Stderr, t)
+}
+
+// A peekReader wraps an io.Reader, allowing one to peek ahead to see
+// what's coming without stealing the data from the client of the Reader.
+type peekReader struct {
+	r    io.Reader
+	data []byte // read-ahead data
+}
+
+// newPeekReader returns a peekReader that wraps r.
+func newPeekReader(r io.Reader) *peekReader {
+	return &peekReader{r: r}
+}
+
+// Read is the usual method. It will first take data that has been read ahead.
+func (p *peekReader) Read(b []byte) (n int, err error) {
+	if len(p.data) == 0 {
+		return p.r.Read(b)
+	}
+	// Satisfy what's possible from the read-ahead data.
+	n = copy(b, p.data)
+	// Move data down to beginning of slice, to avoid endless growth
+	copy(p.data, p.data[n:])
+	p.data = p.data[:len(p.data)-n]
+	return
+}
+
+// peek returns as many bytes as possible from the unread
+// portion of the stream, up to the length of b.
+func (p *peekReader) peek(b []byte) (n int, err error) {
+	if len(p.data) > 0 {
+		n = copy(b, p.data)
+		if n == len(b) {
+			return
+		}
+		b = b[n:]
+	}
+	if len(b) == 0 {
+		return
+	}
+	m, e := io.ReadFull(p.r, b)
+	if m > 0 {
+		p.data = append(p.data, b[:m]...)
+	}
+	n += m
+	if e == io.ErrUnexpectedEOF {
+		// That means m > 0 but we reached EOF. If we got data
+		// we won't complain about not being able to peek enough.
+		if n > 0 {
+			e = nil
+		} else {
+			e = io.EOF
+		}
+	}
+	return n, e
+}
+
+type debugger struct {
+	mutex          sync.Mutex
+	remain         int  // the number of bytes known to remain in the input
+	remainingKnown bool // the value of 'remain' is valid
+	r              *peekReader
+	wireType       map[typeId]*wireType
+	tmp            []byte // scratch space for decoding uints.
+}
+
+// dump prints the next nBytes of the input.
+// It arranges to print the output aligned from call to
+// call, to make it easy to see what has been consumed.
+func (deb *debugger) dump(format string, args ...interface{}) {
+	if !dumpBytes {
+		return
+	}
+	fmt.Fprintf(os.Stderr, format+" ", args...)
+	if !deb.remainingKnown {
+		return
+	}
+	if deb.remain < 0 {
+		fmt.Fprintf(os.Stderr, "remaining byte count is negative! %d\n", deb.remain)
+		return
+	}
+	data := make([]byte, deb.remain)
+	n, _ := deb.r.peek(data)
+	if n == 0 {
+		os.Stderr.Write(empty)
+		return
+	}
+	b := new(bytes.Buffer)
+	fmt.Fprintf(b, "[%d]{\n", deb.remain)
+	// Blanks until first byte
+	lineLength := 0
+	if n := len(data); n%10 != 0 {
+		lineLength = 10 - n%10
+		fmt.Fprintf(b, "\t%s", blanks[:lineLength*3])
+	}
+	// 10 bytes per line
+	for len(data) > 0 {
+		if lineLength == 0 {
+			fmt.Fprint(b, "\t")
+		}
+		m := 10 - lineLength
+		lineLength = 0
+		if m > len(data) {
+			m = len(data)
+		}
+		fmt.Fprintf(b, "% x\n", data[:m])
+		data = data[m:]
+	}
+	fmt.Fprint(b, "}\n")
+	os.Stderr.Write(b.Bytes())
+}
+
+// Debug prints a human-readable representation of the gob data read from r.
+// It is a no-op unless debugging was enabled when the package was built.
+func Debug(r io.Reader) {
+	err := debug(r)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "gob debug: %s\n", err)
+	}
+}
+
+// debug implements Debug, but catches panics and returns
+// them as errors to be printed by Debug.
+func debug(r io.Reader) (err error) {
+	defer catchError(&err)
+	fmt.Fprintln(os.Stderr, "Start of debugging")
+	deb := &debugger{
+		r:        newPeekReader(r),
+		wireType: make(map[typeId]*wireType),
+		tmp:      make([]byte, 16),
+	}
+	if b, ok := r.(*bytes.Buffer); ok {
+		deb.remain = b.Len()
+		deb.remainingKnown = true
+	}
+	deb.gobStream()
+	return
+}
+
+// note that we've consumed some bytes
+func (deb *debugger) consumed(n int) {
+	if deb.remainingKnown {
+		deb.remain -= n
+	}
+}
+
+// int64 decodes and returns the next integer, which must be present.
+// Don't call this if you could be at EOF.
+func (deb *debugger) int64() int64 {
+	return toInt(deb.uint64())
+}
+
+// uint64 returns and decodes the next unsigned integer, which must be present.
+// Don't call this if you could be at EOF.
+// TODO: handle errors better.
+func (deb *debugger) uint64() uint64 {
+	n, w, err := decodeUintReader(deb.r, deb.tmp)
+	if err != nil {
+		errorf("debug: read error: %s", err)
+	}
+	deb.consumed(w)
+	return n
+}
+
+// GobStream:
+//	DelimitedMessage* (until EOF)
+func (deb *debugger) gobStream() {
+	// Make sure we're single-threaded through here.
+	deb.mutex.Lock()
+	defer deb.mutex.Unlock()
+
+	for deb.delimitedMessage(0) {
+	}
+}
+
+// DelimitedMessage:
+//	uint(lengthOfMessage) Message
+func (deb *debugger) delimitedMessage(indent tab) bool {
+	for {
+		n := deb.loadBlock(true)
+		if n < 0 {
+			return false
+		}
+		deb.dump("Delimited message of length %d", n)
+		deb.message(indent)
+	}
+	return true
+}
+
+// loadBlock preps us to read a message
+// of the length specified next in the input. It returns
+// the length of the block. The argument tells whether
+// an EOF is acceptable now.  If it is and one is found,
+// the return value is negative.
+func (deb *debugger) loadBlock(eofOK bool) int {
+	n64, w, err := decodeUintReader(deb.r, deb.tmp) // deb.uint64 will error at EOF
+	if err != nil {
+		if eofOK && err == io.EOF {
+			return -1
+		}
+		errorf("debug: unexpected error: %s", err)
+	}
+	deb.consumed(w)
+	n := int(n64)
+	if n < 0 {
+		errorf("huge value for message length: %d", n64)
+	}
+	return int(n)
+}
+
+// Message:
+//	TypeSequence TypedValue
+// TypeSequence
+//	(TypeDefinition DelimitedTypeDefinition*)?
+// DelimitedTypeDefinition:
+//	uint(lengthOfTypeDefinition) TypeDefinition
+// TypedValue:
+//	int(typeId) Value
+func (deb *debugger) message(indent tab) bool {
+	for {
+		// Convert the uint64 to a signed integer typeId
+		uid := deb.int64()
+		id := typeId(uid)
+		deb.dump("type id=%d", id)
+		if id < 0 {
+			deb.typeDefinition(indent, -id)
+			n := deb.loadBlock(false)
+			deb.dump("Message of length %d", n)
+			continue
+		} else {
+			deb.value(indent, id)
+			break
+		}
+	}
+	return true
+}
+
+// Helper methods to make it easy to scan a type descriptor.
+
+// common returns the CommonType at the input point.
+func (deb *debugger) common() CommonType {
+	fieldNum := -1
+	name := ""
+	id := typeId(0)
+	for {
+		delta := deb.delta(-1)
+		if delta == 0 {
+			break
+		}
+		fieldNum += delta
+		switch fieldNum {
+		case 0:
+			name = deb.string()
+		case 1:
+			// Id typeId
+			id = deb.typeId()
+		default:
+			errorf("corrupted CommonType")
+		}
+	}
+	return CommonType{name, id}
+}
+
+// uint returns the unsigned int at the input point, as a uint (not uint64).
+func (deb *debugger) uint() uint {
+	return uint(deb.uint64())
+}
+
+// int returns the signed int at the input point, as an int (not int64).
+func (deb *debugger) int() int {
+	return int(deb.int64())
+}
+
+// typeId returns the type id at the input point.
+func (deb *debugger) typeId() typeId {
+	return typeId(deb.int64())
+}
+
+// string returns the string at the input point.
+func (deb *debugger) string() string {
+	x := int(deb.uint64())
+	b := make([]byte, x)
+	nb, _ := deb.r.Read(b)
+	if nb != x {
+		errorf("corrupted type")
+	}
+	deb.consumed(nb)
+	return string(b)
+}
+
+// delta returns the field delta at the input point.  The expect argument,
+// if non-negative, identifies what the value should be.
+func (deb *debugger) delta(expect int) int {
+	delta := int(deb.uint64())
+	if delta < 0 || (expect >= 0 && delta != expect) {
+		errorf("decode: corrupted type: delta %d expected %d", delta, expect)
+	}
+	return delta
+}
+
+// TypeDefinition:
+//	[int(-typeId) (already read)] encodingOfWireType
+func (deb *debugger) typeDefinition(indent tab, id typeId) {
+	deb.dump("type definition for id %d", id)
+	// Encoding is of a wireType. Decode the structure as usual
+	fieldNum := -1
+	wire := new(wireType)
+	// A wireType defines a single field.
+	delta := deb.delta(-1)
+	fieldNum += delta
+	switch fieldNum {
+	case 0: // array type, one field of {{Common}, elem, length}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		// Field number 1 is type Id of elem
+		deb.delta(1)
+		id := deb.typeId()
+		// Field number 3 is length
+		deb.delta(1)
+		length := deb.int()
+		wire.ArrayT = &arrayType{com, id, length}
+
+	case 1: // slice type, one field of {{Common}, elem}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		// Field number 1 is type Id of elem
+		deb.delta(1)
+		id := deb.typeId()
+		wire.SliceT = &sliceType{com, id}
+
+	case 2: // struct type, one field of {{Common}, []fieldType}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		// Field number 1 is slice of FieldType
+		deb.delta(1)
+		numField := int(deb.uint())
+		field := make([]*fieldType, numField)
+		for i := 0; i < numField; i++ {
+			field[i] = new(fieldType)
+			deb.delta(1) // field 0 of fieldType: name
+			field[i].Name = deb.string()
+			deb.delta(1) // field 1 of fieldType: id
+			field[i].Id = deb.typeId()
+			deb.delta(0) // end of fieldType
+		}
+		wire.StructT = &structType{com, field}
+
+	case 3: // map type, one field of {{Common}, key, elem}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		// Field number 1 is type Id of key
+		deb.delta(1)
+		keyId := deb.typeId()
+		// Field number 2 is type Id of elem
+		deb.delta(1)
+		elemId := deb.typeId()
+		wire.MapT = &mapType{com, keyId, elemId}
+	case 4: // GobEncoder type, one field of {{Common}}
+		// Field number 0 is CommonType
+		deb.delta(1)
+		com := deb.common()
+		wire.GobEncoderT = &gobEncoderType{com}
+	default:
+		errorf("bad field in type %d", fieldNum)
+	}
+	deb.printWireType(indent, wire)
+	deb.delta(0) // end inner type (arrayType, etc.)
+	deb.delta(0) // end wireType
+	// Remember we've seen this type.
+	deb.wireType[id] = wire
+}
+
+// Value:
+//	SingletonValue | StructValue
+func (deb *debugger) value(indent tab, id typeId) {
+	wire, ok := deb.wireType[id]
+	if ok && wire.StructT != nil {
+		deb.structValue(indent, id)
+	} else {
+		deb.singletonValue(indent, id)
+	}
+}
+
+// SingletonValue:
+//	uint(0) FieldValue
+func (deb *debugger) singletonValue(indent tab, id typeId) {
+	deb.dump("Singleton value")
+	// is it a builtin type?
+	wire := deb.wireType[id]
+	_, ok := builtinIdToType[id]
+	if !ok && wire == nil {
+		errorf("type id %d not defined", id)
+	}
+	m := deb.uint64()
+	if m != 0 {
+		errorf("expected zero; got %d", m)
+	}
+	deb.fieldValue(indent, id)
+}
+
+// InterfaceValue:
+//	NilInterfaceValue | NonNilInterfaceValue
+func (deb *debugger) interfaceValue(indent tab) {
+	deb.dump("Start of interface value")
+	if nameLen := deb.uint64(); nameLen == 0 {
+		deb.nilInterfaceValue(indent)
+	} else {
+		deb.nonNilInterfaceValue(indent, int(nameLen))
+	}
+}
+
+// NilInterfaceValue:
+//	uint(0) [already read]
+func (deb *debugger) nilInterfaceValue(indent tab) int {
+	fmt.Fprintf(os.Stderr, "%snil interface\n", indent)
+	return 0
+}
+
+// NonNilInterfaceValue:
+//	ConcreteTypeName TypeSequence InterfaceContents
+// ConcreteTypeName:
+//	uint(lengthOfName) [already read=n] name
+// InterfaceContents:
+//	int(concreteTypeId) DelimitedValue
+// DelimitedValue:
+//	uint(length) Value
+func (deb *debugger) nonNilInterfaceValue(indent tab, nameLen int) {
+	// ConcreteTypeName
+	b := make([]byte, nameLen)
+	deb.r.Read(b) // TODO: CHECK THESE READS!!
+	deb.consumed(nameLen)
+	name := string(b)
+
+	for {
+		id := deb.typeId()
+		if id < 0 {
+			deb.typeDefinition(indent, -id)
+			n := deb.loadBlock(false)
+			deb.dump("Nested message of length %d", n)
+		} else {
+			// DelimitedValue
+			x := deb.uint64() // in case we want to ignore the value; we don't.
+			fmt.Fprintf(os.Stderr, "%sinterface value, type %q id=%d; valueLength %d\n", indent, name, id, x)
+			deb.value(indent, id)
+			break
+		}
+	}
+}
+
+// printCommonType prints a common type; used by printWireType.
+func (deb *debugger) printCommonType(indent tab, kind string, common *CommonType) {
+	indent.print()
+	fmt.Fprintf(os.Stderr, "%s %q id=%d\n", kind, common.Name, common.Id)
+}
+
+// printWireType prints the contents of a wireType.
+func (deb *debugger) printWireType(indent tab, wire *wireType) {
+	fmt.Fprintf(os.Stderr, "%stype definition {\n", indent)
+	indent++
+	switch {
+	case wire.ArrayT != nil:
+		deb.printCommonType(indent, "array", &wire.ArrayT.CommonType)
+		fmt.Fprintf(os.Stderr, "%slen %d\n", indent+1, wire.ArrayT.Len)
+		fmt.Fprintf(os.Stderr, "%selemid %d\n", indent+1, wire.ArrayT.Elem)
+	case wire.MapT != nil:
+		deb.printCommonType(indent, "map", &wire.MapT.CommonType)
+		fmt.Fprintf(os.Stderr, "%skey id=%d\n", indent+1, wire.MapT.Key)
+		fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.MapT.Elem)
+	case wire.SliceT != nil:
+		deb.printCommonType(indent, "slice", &wire.SliceT.CommonType)
+		fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.SliceT.Elem)
+	case wire.StructT != nil:
+		deb.printCommonType(indent, "struct", &wire.StructT.CommonType)
+		for i, field := range wire.StructT.Field {
+			fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id)
+		}
+	case wire.GobEncoderT != nil:
+		deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType)
+	}
+	indent--
+	fmt.Fprintf(os.Stderr, "%s}\n", indent)
+}
+
+// fieldValue prints a value of any type, such as a struct field.
+// FieldValue:
+//	builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue
+func (deb *debugger) fieldValue(indent tab, id typeId) {
+	_, ok := builtinIdToType[id]
+	if ok {
+		if id == tInterface {
+			deb.interfaceValue(indent)
+		} else {
+			deb.printBuiltin(indent, id)
+		}
+		return
+	}
+	wire, ok := deb.wireType[id]
+	if !ok {
+		errorf("type id %d not defined", id)
+	}
+	switch {
+	case wire.ArrayT != nil:
+		deb.arrayValue(indent, wire)
+	case wire.MapT != nil:
+		deb.mapValue(indent, wire)
+	case wire.SliceT != nil:
+		deb.sliceValue(indent, wire)
+	case wire.StructT != nil:
+		deb.structValue(indent, id)
+	case wire.GobEncoderT != nil:
+		deb.gobEncoderValue(indent, id)
+	default:
+		panic("bad wire type for field")
+	}
+}
+
+// printBuiltin prints a value not of a fundamental type, that is,
+// one whose type is known to gobs at bootstrap time.
+func (deb *debugger) printBuiltin(indent tab, id typeId) {
+	switch id {
+	case tBool:
+		x := deb.int64()
+		if x == 0 {
+			fmt.Fprintf(os.Stderr, "%sfalse\n", indent)
+		} else {
+			fmt.Fprintf(os.Stderr, "%strue\n", indent)
+		}
+	case tInt:
+		x := deb.int64()
+		fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
+	case tUint:
+		x := deb.int64()
+		fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
+	case tFloat:
+		x := deb.uint64()
+		fmt.Fprintf(os.Stderr, "%s%g\n", indent, floatFromBits(x))
+	case tComplex:
+		r := deb.uint64()
+		i := deb.uint64()
+		fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, floatFromBits(r), floatFromBits(i))
+	case tBytes:
+		x := int(deb.uint64())
+		b := make([]byte, x)
+		deb.r.Read(b)
+		deb.consumed(x)
+		fmt.Fprintf(os.Stderr, "%s{% x}=%q\n", indent, b, b)
+	case tString:
+		x := int(deb.uint64())
+		b := make([]byte, x)
+		deb.r.Read(b)
+		deb.consumed(x)
+		fmt.Fprintf(os.Stderr, "%s%q\n", indent, b)
+	default:
+		panic("unknown builtin")
+	}
+}
+
+// ArrayValue:
+//	uint(n) FieldValue*n
+func (deb *debugger) arrayValue(indent tab, wire *wireType) {
+	elemId := wire.ArrayT.Elem
+	u := deb.uint64()
+	length := int(u)
+	for i := 0; i < length; i++ {
+		deb.fieldValue(indent, elemId)
+	}
+	if length != wire.ArrayT.Len {
+		fmt.Fprintf(os.Stderr, "%s(wrong length for array: %d should be %d)\n", indent, length, wire.ArrayT.Len)
+	}
+}
+
+// MapValue:
+//	uint(n) (FieldValue FieldValue)*n  [n (key, value) pairs]
+func (deb *debugger) mapValue(indent tab, wire *wireType) {
+	keyId := wire.MapT.Key
+	elemId := wire.MapT.Elem
+	u := deb.uint64()
+	length := int(u)
+	for i := 0; i < length; i++ {
+		deb.fieldValue(indent+1, keyId)
+		deb.fieldValue(indent+1, elemId)
+	}
+}
+
+// SliceValue:
+//	uint(n) (n FieldValue)
+func (deb *debugger) sliceValue(indent tab, wire *wireType) {
+	elemId := wire.SliceT.Elem
+	u := deb.uint64()
+	length := int(u)
+	deb.dump("Start of slice of length %d", length)
+
+	for i := 0; i < length; i++ {
+		deb.fieldValue(indent, elemId)
+	}
+}
+
+// StructValue:
+//	(uint(fieldDelta) FieldValue)*
+func (deb *debugger) structValue(indent tab, id typeId) {
+	deb.dump("Start of struct value of %q id=%d\n<<\n", id.name(), id)
+	fmt.Fprintf(os.Stderr, "%s%s struct {\n", indent, id.name())
+	wire, ok := deb.wireType[id]
+	if !ok {
+		errorf("type id %d not defined", id)
+	}
+	strct := wire.StructT
+	fieldNum := -1
+	indent++
+	for {
+		delta := deb.uint64()
+		if delta == 0 { // struct terminator is zero delta fieldnum
+			break
+		}
+		fieldNum += int(delta)
+		if fieldNum < 0 || fieldNum >= len(strct.Field) {
+			deb.dump("field number out of range: prevField=%d delta=%d", fieldNum-int(delta), delta)
+			break
+		}
+		fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\n", indent, fieldNum, wire.StructT.Field[fieldNum].Name)
+		deb.fieldValue(indent+1, strct.Field[fieldNum].Id)
+	}
+	indent--
+	fmt.Fprintf(os.Stderr, "%s} // end %s struct\n", indent, id.name())
+	deb.dump(">> End of struct value of type %d %q", id, id.name())
+}
+
+// GobEncoderValue:
+//	uint(n) byte*n
+func (deb *debugger) gobEncoderValue(indent tab, id typeId) {
+	len := deb.uint64()
+	deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len)
+	fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name())
+	data := make([]byte, len)
+	_, err := deb.r.Read(data)
+	if err != nil {
+		errorf("gobEncoder data read: %s", err)
+	}
+	fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data)
+}
diff --git a/src/pkg/encoding/gob/decode.go b/src/pkg/encoding/gob/decode.go
new file mode 100644
index 0000000..4d1325d
--- /dev/null
+++ b/src/pkg/encoding/gob/decode.go
@@ -0,0 +1,1284 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+// TODO(rsc): When garbage collector changes, revisit
+// the allocations in this file that use unsafe.Pointer.
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"math"
+	"reflect"
+	"unsafe"
+)
+
+var (
+	errBadUint = errors.New("gob: encoded unsigned integer out of range")
+	errBadType = errors.New("gob: unknown type id or corrupted data")
+	errRange   = errors.New("gob: bad data: field numbers out of bounds")
+)
+
+// decoderState is the execution state of an instance of the decoder. A new state
+// is created for nested objects.
+type decoderState struct {
+	dec *Decoder
+	// The buffer is stored with an extra indirection because it may be replaced
+	// if we load a type during decode (when reading an interface value).
+	b        *bytes.Buffer
+	fieldnum int // the last field number read.
+	buf      []byte
+	next     *decoderState // for free list
+}
+
+// We pass the bytes.Buffer separately for easier testing of the infrastructure
+// without requiring a full Decoder.
+func (dec *Decoder) newDecoderState(buf *bytes.Buffer) *decoderState {
+	d := dec.freeList
+	if d == nil {
+		d = new(decoderState)
+		d.dec = dec
+		d.buf = make([]byte, uint64Size)
+	} else {
+		dec.freeList = d.next
+	}
+	d.b = buf
+	return d
+}
+
+func (dec *Decoder) freeDecoderState(d *decoderState) {
+	d.next = dec.freeList
+	dec.freeList = d
+}
+
+func overflow(name string) error {
+	return errors.New(`value for "` + name + `" out of range`)
+}
+
+// decodeUintReader reads an encoded unsigned integer from an io.Reader.
+// Used only by the Decoder to read the message length.
+func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err error) {
+	width = 1
+	_, err = r.Read(buf[0:width])
+	if err != nil {
+		return
+	}
+	b := buf[0]
+	if b <= 0x7f {
+		return uint64(b), width, nil
+	}
+	n := -int(int8(b))
+	if n > uint64Size {
+		err = errBadUint
+		return
+	}
+	width, err = io.ReadFull(r, buf[0:n])
+	if err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return
+	}
+	// Could check that the high byte is zero but it's not worth it.
+	for _, b := range buf[0:width] {
+		x = x<<8 | uint64(b)
+	}
+	width++ // +1 for length byte
+	return
+}
+
+// decodeUint reads an encoded unsigned integer from state.r.
+// Does not check for overflow.
+func (state *decoderState) decodeUint() (x uint64) {
+	b, err := state.b.ReadByte()
+	if err != nil {
+		error_(err)
+	}
+	if b <= 0x7f {
+		return uint64(b)
+	}
+	n := -int(int8(b))
+	if n > uint64Size {
+		error_(errBadUint)
+	}
+	width, err := state.b.Read(state.buf[0:n])
+	if err != nil {
+		error_(err)
+	}
+	// Don't need to check error; it's safe to loop regardless.
+	// Could check that the high byte is zero but it's not worth it.
+	for _, b := range state.buf[0:width] {
+		x = x<<8 | uint64(b)
+	}
+	return x
+}
+
+// decodeInt reads an encoded signed integer from state.r.
+// Does not check for overflow.
+func (state *decoderState) decodeInt() int64 {
+	x := state.decodeUint()
+	if x&1 != 0 {
+		return ^int64(x >> 1)
+	}
+	return int64(x >> 1)
+}
+
+// decOp is the signature of a decoding operator for a given type.
+type decOp func(i *decInstr, state *decoderState, p unsafe.Pointer)
+
+// The 'instructions' of the decoding machine
+type decInstr struct {
+	op     decOp
+	field  int     // field number of the wire type
+	indir  int     // how many pointer indirections to reach the value in the struct
+	offset uintptr // offset in the structure of the field to encode
+	ovfl   error   // error message for overflow/underflow (for arrays, of the elements)
+}
+
+// Since the encoder writes no zeros, if we arrive at a decoder we have
+// a value to extract and store.  The field number has already been read
+// (it's how we knew to call this decoder).
+// Each decoder is responsible for handling any indirections associated
+// with the data structure.  If any pointer so reached is nil, allocation must
+// be done.
+
+// Walk the pointer hierarchy, allocating if we find a nil.  Stop one before the end.
+func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
+	for ; indir > 1; indir-- {
+		if *(*unsafe.Pointer)(p) == nil {
+			// Allocation required
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	return p
+}
+
+// ignoreUint discards a uint value with no destination.
+func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	state.decodeUint()
+}
+
+// ignoreTwoUints discards a uint value with no destination. It's used to skip
+// complex values.
+func ignoreTwoUints(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	state.decodeUint()
+	state.decodeUint()
+}
+
+// decBool decodes a uint and stores it as a boolean through p.
+func decBool(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	*(*bool)(p) = state.decodeUint() != 0
+}
+
+// decInt8 decodes an integer and stores it as an int8 through p.
+func decInt8(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeInt()
+	if v < math.MinInt8 || math.MaxInt8 < v {
+		error_(i.ovfl)
+	} else {
+		*(*int8)(p) = int8(v)
+	}
+}
+
+// decUint8 decodes an unsigned integer and stores it as a uint8 through p.
+func decUint8(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeUint()
+	if math.MaxUint8 < v {
+		error_(i.ovfl)
+	} else {
+		*(*uint8)(p) = uint8(v)
+	}
+}
+
+// decInt16 decodes an integer and stores it as an int16 through p.
+func decInt16(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeInt()
+	if v < math.MinInt16 || math.MaxInt16 < v {
+		error_(i.ovfl)
+	} else {
+		*(*int16)(p) = int16(v)
+	}
+}
+
+// decUint16 decodes an unsigned integer and stores it as a uint16 through p.
+func decUint16(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeUint()
+	if math.MaxUint16 < v {
+		error_(i.ovfl)
+	} else {
+		*(*uint16)(p) = uint16(v)
+	}
+}
+
+// decInt32 decodes an integer and stores it as an int32 through p.
+func decInt32(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeInt()
+	if v < math.MinInt32 || math.MaxInt32 < v {
+		error_(i.ovfl)
+	} else {
+		*(*int32)(p) = int32(v)
+	}
+}
+
+// decUint32 decodes an unsigned integer and stores it as a uint32 through p.
+func decUint32(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	v := state.decodeUint()
+	if math.MaxUint32 < v {
+		error_(i.ovfl)
+	} else {
+		*(*uint32)(p) = uint32(v)
+	}
+}
+
+// decInt64 decodes an integer and stores it as an int64 through p.
+func decInt64(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	*(*int64)(p) = int64(state.decodeInt())
+}
+
+// decUint64 decodes an unsigned integer and stores it as a uint64 through p.
+func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	*(*uint64)(p) = uint64(state.decodeUint())
+}
+
+// Floating-point numbers are transmitted as uint64s holding the bits
+// of the underlying representation.  They are sent byte-reversed, with
+// the exponent end coming out first, so integer floating point numbers
+// (for example) transmit more compactly.  This routine does the
+// unswizzling.
+func floatFromBits(u uint64) float64 {
+	var v uint64
+	for i := 0; i < 8; i++ {
+		v <<= 8
+		v |= u & 0xFF
+		u >>= 8
+	}
+	return math.Float64frombits(v)
+}
+
+// storeFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
+// number, and stores it through p. It's a helper function for float32 and complex64.
+func storeFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	v := floatFromBits(state.decodeUint())
+	av := v
+	if av < 0 {
+		av = -av
+	}
+	// +Inf is OK in both 32- and 64-bit floats.  Underflow is always OK.
+	if math.MaxFloat32 < av && av <= math.MaxFloat64 {
+		error_(i.ovfl)
+	} else {
+		*(*float32)(p) = float32(v)
+	}
+}
+
+// decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
+// number, and stores it through p.
+func decFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	storeFloat32(i, state, p)
+}
+
+// decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point
+// number, and stores it through p.
+func decFloat64(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	*(*float64)(p) = floatFromBits(uint64(state.decodeUint()))
+}
+
+// decComplex64 decodes a pair of unsigned integers, treats them as a
+// pair of floating point numbers, and stores them as a complex64 through p.
+// The real part comes first.
+func decComplex64(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	storeFloat32(i, state, p)
+	storeFloat32(i, state, unsafe.Pointer(uintptr(p)+unsafe.Sizeof(float32(0))))
+}
+
+// decComplex128 decodes a pair of unsigned integers, treats them as a
+// pair of floating point numbers, and stores them as a complex128 through p.
+// The real part comes first.
+func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	real := floatFromBits(uint64(state.decodeUint()))
+	imag := floatFromBits(uint64(state.decodeUint()))
+	*(*complex128)(p) = complex(real, imag)
+}
+
+// decUint8Slice decodes a byte slice and stores through p a slice header
+// describing the data.
+// uint8 slices are encoded as an unsigned count followed by the raw bytes.
+func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	n := int(state.decodeUint())
+	if n < 0 {
+		errorf("negative length decoding []byte")
+	}
+	slice := (*[]uint8)(p)
+	if cap(*slice) < n {
+		*slice = make([]uint8, n)
+	} else {
+		*slice = (*slice)[0:n]
+	}
+	if _, err := state.b.Read(*slice); err != nil {
+		errorf("error decoding []byte: %s", err)
+	}
+}
+
+// decString decodes byte array and stores through p a string header
+// describing the data.
+// Strings are encoded as an unsigned count followed by the raw bytes.
+func decString(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	if i.indir > 0 {
+		if *(*unsafe.Pointer)(p) == nil {
+			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(string))
+		}
+		p = *(*unsafe.Pointer)(p)
+	}
+	b := make([]byte, state.decodeUint())
+	state.b.Read(b)
+	// It would be a shame to do the obvious thing here,
+	//	*(*string)(p) = string(b)
+	// because we've already allocated the storage and this would
+	// allocate again and copy.  So we do this ugly hack, which is even
+	// even more unsafe than it looks as it depends the memory
+	// representation of a string matching the beginning of the memory
+	// representation of a byte slice (a byte slice is longer).
+	*(*string)(p) = *(*string)(unsafe.Pointer(&b))
+}
+
+// ignoreUint8Array skips over the data for a byte slice value with no destination.
+func ignoreUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
+	b := make([]byte, state.decodeUint())
+	state.b.Read(b)
+}
+
+// Execution engine
+
+// The encoder engine is an array of instructions indexed by field number of the incoming
+// decoder.  It is executed with random access according to field number.
+type decEngine struct {
+	instr    []decInstr
+	numInstr int // the number of active instructions
+}
+
+// allocate makes sure storage is available for an object of underlying type rtyp
+// that is indir levels of indirection through p.
+func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
+	if indir == 0 {
+		return p
+	}
+	up := unsafe.Pointer(p)
+	if indir > 1 {
+		up = decIndirect(up, indir)
+	}
+	if *(*unsafe.Pointer)(up) == nil {
+		// Allocate object.
+		*(*unsafe.Pointer)(up) = unsafe.New(rtyp)
+	}
+	return *(*uintptr)(up)
+}
+
+// decodeSingle decodes a top-level value that is not a struct and stores it through p.
+// Such values are preceded by a zero, making them have the memory layout of a
+// struct field (although with an illegal field number).
+func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uintptr) (err error) {
+	state := dec.newDecoderState(&dec.buf)
+	state.fieldnum = singletonField
+	delta := int(state.decodeUint())
+	if delta != 0 {
+		errorf("decode: corrupted data: non-zero delta for singleton")
+	}
+	instr := &engine.instr[singletonField]
+	if instr.indir != ut.indir {
+		return errors.New("gob: internal error: inconsistent indirection")
+	}
+	ptr := unsafe.Pointer(basep) // offset will be zero
+	if instr.indir > 1 {
+		ptr = decIndirect(ptr, instr.indir)
+	}
+	instr.op(instr, state, ptr)
+	dec.freeDecoderState(state)
+	return nil
+}
+
+// decodeSingle decodes a top-level struct and stores it through p.
+// Indir is for the value, not the type.  At the time of the call it may
+// differ from ut.indir, which was computed when the engine was built.
+// This state cannot arise for decodeSingle, which is called directly
+// from the user's value, not from the innards of an engine.
+func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr, indir int) {
+	p = allocate(ut.base, p, indir)
+	state := dec.newDecoderState(&dec.buf)
+	state.fieldnum = -1
+	basep := p
+	for state.b.Len() > 0 {
+		delta := int(state.decodeUint())
+		if delta < 0 {
+			errorf("decode: corrupted data: negative delta")
+		}
+		if delta == 0 { // struct terminator is zero delta fieldnum
+			break
+		}
+		fieldnum := state.fieldnum + delta
+		if fieldnum >= len(engine.instr) {
+			error_(errRange)
+			break
+		}
+		instr := &engine.instr[fieldnum]
+		p := unsafe.Pointer(basep + instr.offset)
+		if instr.indir > 1 {
+			p = decIndirect(p, instr.indir)
+		}
+		instr.op(instr, state, p)
+		state.fieldnum = fieldnum
+	}
+	dec.freeDecoderState(state)
+}
+
+// ignoreStruct discards the data for a struct with no destination.
+func (dec *Decoder) ignoreStruct(engine *decEngine) {
+	state := dec.newDecoderState(&dec.buf)
+	state.fieldnum = -1
+	for state.b.Len() > 0 {
+		delta := int(state.decodeUint())
+		if delta < 0 {
+			errorf("ignore decode: corrupted data: negative delta")
+		}
+		if delta == 0 { // struct terminator is zero delta fieldnum
+			break
+		}
+		fieldnum := state.fieldnum + delta
+		if fieldnum >= len(engine.instr) {
+			error_(errRange)
+		}
+		instr := &engine.instr[fieldnum]
+		instr.op(instr, state, unsafe.Pointer(nil))
+		state.fieldnum = fieldnum
+	}
+	dec.freeDecoderState(state)
+}
+
+// ignoreSingle discards the data for a top-level non-struct value with no
+// destination. It's used when calling Decode with a nil value.
+func (dec *Decoder) ignoreSingle(engine *decEngine) {
+	state := dec.newDecoderState(&dec.buf)
+	state.fieldnum = singletonField
+	delta := int(state.decodeUint())
+	if delta != 0 {
+		errorf("decode: corrupted data: non-zero delta for singleton")
+	}
+	instr := &engine.instr[singletonField]
+	instr.op(instr, state, unsafe.Pointer(nil))
+	dec.freeDecoderState(state)
+}
+
+// decodeArrayHelper does the work for decoding arrays and slices.
+func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
+	instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
+	for i := 0; i < length; i++ {
+		up := unsafe.Pointer(p)
+		if elemIndir > 1 {
+			up = decIndirect(up, elemIndir)
+		}
+		elemOp(instr, state, up)
+		p += uintptr(elemWid)
+	}
+}
+
+// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
+// The length is an unsigned integer preceding the elements.  Even though the length is redundant
+// (it's part of the type), it's a useful check and is included in the encoding.
+func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
+	if indir > 0 {
+		p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
+	}
+	if n := state.decodeUint(); n != uint64(length) {
+		errorf("length mismatch in decodeArray")
+	}
+	dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
+}
+
+// decodeIntoValue is a helper for map decoding.  Since maps are decoded using reflection,
+// unlike the other items we can't use a pointer directly.
+func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value {
+	instr := &decInstr{op, 0, indir, 0, ovfl}
+	up := unsafe.Pointer(unsafeAddr(v))
+	if indir > 1 {
+		up = decIndirect(up, indir)
+	}
+	op(instr, state, up)
+	return v
+}
+
+// decodeMap decodes a map and stores its header through p.
+// Maps are encoded as a length followed by key:value pairs.
+// Because the internals of maps are not visible to us, we must
+// use reflection rather than pointer magic.
+func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
+	if indir > 0 {
+		p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
+	}
+	up := unsafe.Pointer(p)
+	if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime
+		// Allocate map.
+		*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Pointer())
+	}
+	// Maps cannot be accessed by moving addresses around the way
+	// that slices etc. can.  We must recover a full reflection value for
+	// the iteration.
+	v := reflect.ValueOf(unsafe.Unreflect(mtyp, unsafe.Pointer(p)))
+	n := int(state.decodeUint())
+	for i := 0; i < n; i++ {
+		key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
+		elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl)
+		v.SetMapIndex(key, elem)
+	}
+}
+
+// ignoreArrayHelper does the work for discarding arrays and slices.
+func (dec *Decoder) ignoreArrayHelper(state *decoderState, elemOp decOp, length int) {
+	instr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")}
+	for i := 0; i < length; i++ {
+		elemOp(instr, state, nil)
+	}
+}
+
+// ignoreArray discards the data for an array value with no destination.
+func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) {
+	if n := state.decodeUint(); n != uint64(length) {
+		errorf("length mismatch in ignoreArray")
+	}
+	dec.ignoreArrayHelper(state, elemOp, length)
+}
+
+// ignoreMap discards the data for a map value with no destination.
+func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
+	n := int(state.decodeUint())
+	keyInstr := &decInstr{keyOp, 0, 0, 0, errors.New("no error")}
+	elemInstr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")}
+	for i := 0; i < n; i++ {
+		keyOp(keyInstr, state, nil)
+		elemOp(elemInstr, state, nil)
+	}
+}
+
+// decodeSlice decodes a slice and stores the slice header through p.
+// Slices are encoded as an unsigned length followed by the elements.
+func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) {
+	n := int(uintptr(state.decodeUint()))
+	if indir > 0 {
+		up := unsafe.Pointer(p)
+		if *(*unsafe.Pointer)(up) == nil {
+			// Allocate the slice header.
+			*(*unsafe.Pointer)(up) = unsafe.Pointer(new([]unsafe.Pointer))
+		}
+		p = *(*uintptr)(up)
+	}
+	// Allocate storage for the slice elements, that is, the underlying array,
+	// if the existing slice does not have the capacity.
+	// Always write a header at p.
+	hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p))
+	if hdrp.Cap < n {
+		hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n))
+		hdrp.Cap = n
+	}
+	hdrp.Len = n
+	dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
+}
+
+// ignoreSlice skips over the data for a slice value with no destination.
+func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
+	dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
+}
+
+// setInterfaceValue sets an interface value to a concrete value,
+// but first it checks that the assignment will succeed.
+func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
+	if !value.Type().AssignableTo(ivalue.Type()) {
+		errorf("cannot assign value of type %s to %s", value.Type(), ivalue.Type())
+	}
+	ivalue.Set(value)
+}
+
+// decodeInterface decodes an interface value and stores it through p.
+// Interfaces are encoded as the name of a concrete type followed by a value.
+// If the name is empty, the value is nil and no value is sent.
+func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p uintptr, indir int) {
+	// Create a writable interface reflect.Value.  We need one even for the nil case.
+	ivalue := allocValue(ityp)
+	// Read the name of the concrete type.
+	b := make([]byte, state.decodeUint())
+	state.b.Read(b)
+	name := string(b)
+	if name == "" {
+		// Copy the representation of the nil interface value to the target.
+		// This is horribly unsafe and special.
+		*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
+		return
+	}
+	// The concrete type must be registered.
+	typ, ok := nameToConcreteType[name]
+	if !ok {
+		errorf("name not registered for interface: %q", name)
+	}
+	// Read the type id of the concrete value.
+	concreteId := dec.decodeTypeSequence(true)
+	if concreteId < 0 {
+		error_(dec.err)
+	}
+	// Byte count of value is next; we don't care what it is (it's there
+	// in case we want to ignore the value by skipping it completely).
+	state.decodeUint()
+	// Read the concrete value.
+	value := allocValue(typ)
+	dec.decodeValue(concreteId, value)
+	if dec.err != nil {
+		error_(dec.err)
+	}
+	// Allocate the destination interface value.
+	if indir > 0 {
+		p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
+	}
+	// Assign the concrete value to the interface.
+	// Tread carefully; it might not satisfy the interface.
+	setInterfaceValue(ivalue, value)
+	// Copy the representation of the interface value to the target.
+	// This is horribly unsafe and special.
+	*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
+}
+
+// ignoreInterface discards the data for an interface value with no destination.
+func (dec *Decoder) ignoreInterface(state *decoderState) {
+	// Read the name of the concrete type.
+	b := make([]byte, state.decodeUint())
+	_, err := state.b.Read(b)
+	if err != nil {
+		error_(err)
+	}
+	id := dec.decodeTypeSequence(true)
+	if id < 0 {
+		error_(dec.err)
+	}
+	// At this point, the decoder buffer contains a delimited value. Just toss it.
+	state.b.Next(int(state.decodeUint()))
+}
+
+// decodeGobDecoder decodes something implementing the GobDecoder interface.
+// The data is encoded as a byte slice.
+func (dec *Decoder) decodeGobDecoder(state *decoderState, v reflect.Value) {
+	// Read the bytes for the value.
+	b := make([]byte, state.decodeUint())
+	_, err := state.b.Read(b)
+	if err != nil {
+		error_(err)
+	}
+	// We know it's a GobDecoder, so just call the method directly.
+	err = v.Interface().(GobDecoder).GobDecode(b)
+	if err != nil {
+		error_(err)
+	}
+}
+
+// ignoreGobDecoder discards the data for a GobDecoder value with no destination.
+func (dec *Decoder) ignoreGobDecoder(state *decoderState) {
+	// Read the bytes for the value.
+	b := make([]byte, state.decodeUint())
+	_, err := state.b.Read(b)
+	if err != nil {
+		error_(err)
+	}
+}
+
+// Index by Go types.
+var decOpTable = [...]decOp{
+	reflect.Bool:       decBool,
+	reflect.Int8:       decInt8,
+	reflect.Int16:      decInt16,
+	reflect.Int32:      decInt32,
+	reflect.Int64:      decInt64,
+	reflect.Uint8:      decUint8,
+	reflect.Uint16:     decUint16,
+	reflect.Uint32:     decUint32,
+	reflect.Uint64:     decUint64,
+	reflect.Float32:    decFloat32,
+	reflect.Float64:    decFloat64,
+	reflect.Complex64:  decComplex64,
+	reflect.Complex128: decComplex128,
+	reflect.String:     decString,
+}
+
+// Indexed by gob types.  tComplex will be added during type.init().
+var decIgnoreOpMap = map[typeId]decOp{
+	tBool:    ignoreUint,
+	tInt:     ignoreUint,
+	tUint:    ignoreUint,
+	tFloat:   ignoreUint,
+	tBytes:   ignoreUint8Array,
+	tString:  ignoreUint8Array,
+	tComplex: ignoreTwoUints,
+}
+
+// decOpFor returns the decoding op for the base type under rt and
+// the indirection count to reach it.
+func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) {
+	ut := userType(rt)
+	// If the type implements GobEncoder, we handle it without further processing.
+	if ut.isGobDecoder {
+		return dec.gobDecodeOpFor(ut)
+	}
+	// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
+	// Return the pointer to the op we're already building.
+	if opPtr := inProgress[rt]; opPtr != nil {
+		return opPtr, ut.indir
+	}
+	typ := ut.base
+	indir := ut.indir
+	var op decOp
+	k := typ.Kind()
+	if int(k) < len(decOpTable) {
+		op = decOpTable[k]
+	}
+	if op == nil {
+		inProgress[rt] = &op
+		// Special cases
+		switch t := typ; t.Kind() {
+		case reflect.Array:
+			name = "element of " + name
+			elemId := dec.wireType[wireId].ArrayT.Elem
+			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+			ovfl := overflow(name)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.decodeArray(t, state, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
+			}
+
+		case reflect.Map:
+			name = "element of " + name
+			keyId := dec.wireType[wireId].MapT.Key
+			elemId := dec.wireType[wireId].MapT.Elem
+			keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name, inProgress)
+			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+			ovfl := overflow(name)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				up := unsafe.Pointer(p)
+				state.dec.decodeMap(t, state, uintptr(up), *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
+			}
+
+		case reflect.Slice:
+			name = "element of " + name
+			if t.Elem().Kind() == reflect.Uint8 {
+				op = decUint8Slice
+				break
+			}
+			var elemId typeId
+			if tt, ok := builtinIdToType[wireId]; ok {
+				elemId = tt.(*sliceType).Elem
+			} else {
+				elemId = dec.wireType[wireId].SliceT.Elem
+			}
+			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
+			ovfl := overflow(name)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.decodeSlice(t, state, uintptr(p), *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
+			}
+
+		case reflect.Struct:
+			// Generate a closure that calls out to the engine for the nested type.
+			enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ))
+			if err != nil {
+				error_(err)
+			}
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				// indirect through enginePtr to delay evaluation for recursive structs.
+				dec.decodeStruct(*enginePtr, userType(typ), uintptr(p), i.indir)
+			}
+		case reflect.Interface:
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.decodeInterface(t, state, uintptr(p), i.indir)
+			}
+		}
+	}
+	if op == nil {
+		errorf("decode can't handle type %s", rt)
+	}
+	return &op, indir
+}
+
+// decIgnoreOpFor returns the decoding op for a field that has no destination.
+func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
+	op, ok := decIgnoreOpMap[wireId]
+	if !ok {
+		if wireId == tInterface {
+			// Special case because it's a method: the ignored item might
+			// define types and we need to record their state in the decoder.
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreInterface(state)
+			}
+			return op
+		}
+		// Special cases
+		wire := dec.wireType[wireId]
+		switch {
+		case wire == nil:
+			errorf("bad data: undefined type %s", wireId.string())
+		case wire.ArrayT != nil:
+			elemId := wire.ArrayT.Elem
+			elemOp := dec.decIgnoreOpFor(elemId)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len)
+			}
+
+		case wire.MapT != nil:
+			keyId := dec.wireType[wireId].MapT.Key
+			elemId := dec.wireType[wireId].MapT.Elem
+			keyOp := dec.decIgnoreOpFor(keyId)
+			elemOp := dec.decIgnoreOpFor(elemId)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreMap(state, keyOp, elemOp)
+			}
+
+		case wire.SliceT != nil:
+			elemId := wire.SliceT.Elem
+			elemOp := dec.decIgnoreOpFor(elemId)
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreSlice(state, elemOp)
+			}
+
+		case wire.StructT != nil:
+			// Generate a closure that calls out to the engine for the nested type.
+			enginePtr, err := dec.getIgnoreEnginePtr(wireId)
+			if err != nil {
+				error_(err)
+			}
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				// indirect through enginePtr to delay evaluation for recursive structs
+				state.dec.ignoreStruct(*enginePtr)
+			}
+
+		case wire.GobEncoderT != nil:
+			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+				state.dec.ignoreGobDecoder(state)
+			}
+		}
+	}
+	if op == nil {
+		errorf("bad data: ignore can't handle type %s", wireId.string())
+	}
+	return op
+}
+
+// gobDecodeOpFor returns the op for a type that is known to implement
+// GobDecoder.
+func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
+	rcvrType := ut.user
+	if ut.decIndir == -1 {
+		rcvrType = reflect.PtrTo(rcvrType)
+	} else if ut.decIndir > 0 {
+		for i := int8(0); i < ut.decIndir; i++ {
+			rcvrType = rcvrType.Elem()
+		}
+	}
+	var op decOp
+	op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
+		// Caller has gotten us to within one indirection of our value.
+		if i.indir > 0 {
+			if *(*unsafe.Pointer)(p) == nil {
+				*(*unsafe.Pointer)(p) = unsafe.New(ut.base)
+			}
+		}
+		// Now p is a pointer to the base type.  Do we need to climb out to
+		// get to the receiver type?
+		var v reflect.Value
+		if ut.decIndir == -1 {
+			v = reflect.ValueOf(unsafe.Unreflect(rcvrType, unsafe.Pointer(&p)))
+		} else {
+			v = reflect.ValueOf(unsafe.Unreflect(rcvrType, p))
+		}
+		state.dec.decodeGobDecoder(state, v)
+	}
+	return &op, int(ut.indir)
+
+}
+
+// compatibleType asks: Are these two gob Types compatible?
+// Answers the question for basic types, arrays, maps and slices, plus
+// GobEncoder/Decoder pairs.
+// Structs are considered ok; fields will be checked later.
+func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[reflect.Type]typeId) bool {
+	if rhs, ok := inProgress[fr]; ok {
+		return rhs == fw
+	}
+	inProgress[fr] = fw
+	ut := userType(fr)
+	wire, ok := dec.wireType[fw]
+	// If fr is a GobDecoder, the wire type must be GobEncoder.
+	// And if fr is not a GobDecoder, the wire type must not be either.
+	if ut.isGobDecoder != (ok && wire.GobEncoderT != nil) { // the parentheses look odd but are correct.
+		return false
+	}
+	if ut.isGobDecoder { // This test trumps all others.
+		return true
+	}
+	switch t := ut.base; t.Kind() {
+	default:
+		// chan, etc: cannot handle.
+		return false
+	case reflect.Bool:
+		return fw == tBool
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return fw == tInt
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return fw == tUint
+	case reflect.Float32, reflect.Float64:
+		return fw == tFloat
+	case reflect.Complex64, reflect.Complex128:
+		return fw == tComplex
+	case reflect.String:
+		return fw == tString
+	case reflect.Interface:
+		return fw == tInterface
+	case reflect.Array:
+		if !ok || wire.ArrayT == nil {
+			return false
+		}
+		array := wire.ArrayT
+		return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem, inProgress)
+	case reflect.Map:
+		if !ok || wire.MapT == nil {
+			return false
+		}
+		MapType := wire.MapT
+		return dec.compatibleType(t.Key(), MapType.Key, inProgress) && dec.compatibleType(t.Elem(), MapType.Elem, inProgress)
+	case reflect.Slice:
+		// Is it an array of bytes?
+		if t.Elem().Kind() == reflect.Uint8 {
+			return fw == tBytes
+		}
+		// Extract and compare element types.
+		var sw *sliceType
+		if tt, ok := builtinIdToType[fw]; ok {
+			sw, _ = tt.(*sliceType)
+		} else if wire != nil {
+			sw = wire.SliceT
+		}
+		elem := userType(t.Elem()).base
+		return sw != nil && dec.compatibleType(elem, sw.Elem, inProgress)
+	case reflect.Struct:
+		return true
+	}
+	return true
+}
+
+// typeString returns a human-readable description of the type identified by remoteId.
+func (dec *Decoder) typeString(remoteId typeId) string {
+	if t := idToType[remoteId]; t != nil {
+		// globally known type.
+		return t.string()
+	}
+	return dec.wireType[remoteId].string()
+}
+
+// compileSingle compiles the decoder engine for a non-struct top-level value, including
+// GobDecoders.
+func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
+	rt := ut.user
+	engine = new(decEngine)
+	engine.instr = make([]decInstr, 1) // one item
+	name := rt.String()                // best we can do
+	if !dec.compatibleType(rt, remoteId, make(map[reflect.Type]typeId)) {
+		remoteType := dec.typeString(remoteId)
+		// Common confusing case: local interface type, remote concrete type.
+		if ut.base.Kind() == reflect.Interface && remoteId != tInterface {
+			return nil, errors.New("gob: local interface type " + name + " can only be decoded from remote interface type; received concrete type " + remoteType)
+		}
+		return nil, errors.New("gob: decoding into local type " + name + ", received remote type " + remoteType)
+	}
+	op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp))
+	ovfl := errors.New(`value for "` + name + `" out of range`)
+	engine.instr[singletonField] = decInstr{*op, singletonField, indir, 0, ovfl}
+	engine.numInstr = 1
+	return
+}
+
+// compileIgnoreSingle compiles the decoder engine for a non-struct top-level value that will be discarded.
+func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err error) {
+	engine = new(decEngine)
+	engine.instr = make([]decInstr, 1) // one item
+	op := dec.decIgnoreOpFor(remoteId)
+	ovfl := overflow(dec.typeString(remoteId))
+	engine.instr[0] = decInstr{op, 0, 0, 0, ovfl}
+	engine.numInstr = 1
+	return
+}
+
+// compileDec compiles the decoder engine for a value.  If the value is not a struct,
+// it calls out to compileSingle.
+func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
+	rt := ut.base
+	srt := rt
+	if srt.Kind() != reflect.Struct ||
+		ut.isGobDecoder {
+		return dec.compileSingle(remoteId, ut)
+	}
+	var wireStruct *structType
+	// Builtin types can come from global pool; the rest must be defined by the decoder.
+	// Also we know we're decoding a struct now, so the client must have sent one.
+	if t, ok := builtinIdToType[remoteId]; ok {
+		wireStruct, _ = t.(*structType)
+	} else {
+		wire := dec.wireType[remoteId]
+		if wire == nil {
+			error_(errBadType)
+		}
+		wireStruct = wire.StructT
+	}
+	if wireStruct == nil {
+		errorf("type mismatch in decoder: want struct type %s; got non-struct", rt)
+	}
+	engine = new(decEngine)
+	engine.instr = make([]decInstr, len(wireStruct.Field))
+	seen := make(map[reflect.Type]*decOp)
+	// Loop over the fields of the wire type.
+	for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ {
+		wireField := wireStruct.Field[fieldnum]
+		if wireField.Name == "" {
+			errorf("empty name for remote field of type %s", wireStruct.Name)
+		}
+		ovfl := overflow(wireField.Name)
+		// Find the field of the local type with the same name.
+		localField, present := srt.FieldByName(wireField.Name)
+		// TODO(r): anonymous names
+		if !present || !isExported(wireField.Name) {
+			op := dec.decIgnoreOpFor(wireField.Id)
+			engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl}
+			continue
+		}
+		if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) {
+			errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
+		}
+		op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen)
+		engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl}
+		engine.numInstr++
+	}
+	return
+}
+
+// getDecEnginePtr returns the engine for the specified type.
+func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err error) {
+	rt := ut.base
+	decoderMap, ok := dec.decoderCache[rt]
+	if !ok {
+		decoderMap = make(map[typeId]**decEngine)
+		dec.decoderCache[rt] = decoderMap
+	}
+	if enginePtr, ok = decoderMap[remoteId]; !ok {
+		// To handle recursive types, mark this engine as underway before compiling.
+		enginePtr = new(*decEngine)
+		decoderMap[remoteId] = enginePtr
+		*enginePtr, err = dec.compileDec(remoteId, ut)
+		if err != nil {
+			delete(decoderMap, remoteId)
+		}
+	}
+	return
+}
+
+// emptyStruct is the type we compile into when ignoring a struct value.
+type emptyStruct struct{}
+
+var emptyStructType = reflect.TypeOf(emptyStruct{})
+
+// getDecEnginePtr returns the engine for the specified type when the value is to be discarded.
+func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err error) {
+	var ok bool
+	if enginePtr, ok = dec.ignorerCache[wireId]; !ok {
+		// To handle recursive types, mark this engine as underway before compiling.
+		enginePtr = new(*decEngine)
+		dec.ignorerCache[wireId] = enginePtr
+		wire := dec.wireType[wireId]
+		if wire != nil && wire.StructT != nil {
+			*enginePtr, err = dec.compileDec(wireId, userType(emptyStructType))
+		} else {
+			*enginePtr, err = dec.compileIgnoreSingle(wireId)
+		}
+		if err != nil {
+			delete(dec.ignorerCache, wireId)
+		}
+	}
+	return
+}
+
+// decodeValue decodes the data stream representing a value and stores it in val.
+func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
+	defer catchError(&dec.err)
+	// If the value is nil, it means we should just ignore this item.
+	if !val.IsValid() {
+		dec.decodeIgnoredValue(wireId)
+		return
+	}
+	// Dereference down to the underlying type.
+	ut := userType(val.Type())
+	base := ut.base
+	var enginePtr **decEngine
+	enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut)
+	if dec.err != nil {
+		return
+	}
+	engine := *enginePtr
+	if st := base; st.Kind() == reflect.Struct && !ut.isGobDecoder {
+		if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
+			name := base.Name()
+			errorf("type mismatch: no fields matched compiling decoder for %s", name)
+		}
+		dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir)
+	} else {
+		dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val)))
+	}
+}
+
+// decodeIgnoredValue decodes the data stream representing a value of the specified type and discards it.
+func (dec *Decoder) decodeIgnoredValue(wireId typeId) {
+	var enginePtr **decEngine
+	enginePtr, dec.err = dec.getIgnoreEnginePtr(wireId)
+	if dec.err != nil {
+		return
+	}
+	wire := dec.wireType[wireId]
+	if wire != nil && wire.StructT != nil {
+		dec.ignoreStruct(*enginePtr)
+	} else {
+		dec.ignoreSingle(*enginePtr)
+	}
+}
+
+func init() {
+	var iop, uop decOp
+	switch reflect.TypeOf(int(0)).Bits() {
+	case 32:
+		iop = decInt32
+		uop = decUint32
+	case 64:
+		iop = decInt64
+		uop = decUint64
+	default:
+		panic("gob: unknown size of int/uint")
+	}
+	decOpTable[reflect.Int] = iop
+	decOpTable[reflect.Uint] = uop
+
+	// Finally uintptr
+	switch reflect.TypeOf(uintptr(0)).Bits() {
+	case 32:
+		uop = decUint32
+	case 64:
+		uop = decUint64
+	default:
+		panic("gob: unknown size of uintptr")
+	}
+	decOpTable[reflect.Uintptr] = uop
+}
+
+// Gob assumes it can call UnsafeAddr on any Value
+// in order to get a pointer it can copy data from.
+// Values that have just been created and do not point
+// into existing structs or slices cannot be addressed,
+// so simulate it by returning a pointer to a copy.
+// Each call allocates once.
+func unsafeAddr(v reflect.Value) uintptr {
+	if v.CanAddr() {
+		return v.UnsafeAddr()
+	}
+	x := reflect.New(v.Type()).Elem()
+	x.Set(v)
+	return x.UnsafeAddr()
+}
+
+// Gob depends on being able to take the address
+// of zeroed Values it creates, so use this wrapper instead
+// of the standard reflect.Zero.
+// Each call allocates once.
+func allocValue(t reflect.Type) reflect.Value {
+	return reflect.New(t).Elem()
+}
diff --git a/src/pkg/encoding/gob/decoder.go b/src/pkg/encoding/gob/decoder.go
new file mode 100644
index 0000000..fb28c8c
--- /dev/null
+++ b/src/pkg/encoding/gob/decoder.go
@@ -0,0 +1,216 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"io"
+	"reflect"
+	"sync"
+)
+
+// A Decoder manages the receipt of type and data information read from the
+// remote side of a connection.
+type Decoder struct {
+	mutex        sync.Mutex                              // each item must be received atomically
+	r            io.Reader                               // source of the data
+	buf          bytes.Buffer                            // buffer for more efficient i/o from r
+	wireType     map[typeId]*wireType                    // map from remote ID to local description
+	decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines
+	ignorerCache map[typeId]**decEngine                  // ditto for ignored objects
+	freeList     *decoderState                           // list of free decoderStates; avoids reallocation
+	countBuf     []byte                                  // used for decoding integers while parsing messages
+	tmp          []byte                                  // temporary storage for i/o; saves reallocating
+	err          error
+}
+
+// NewDecoder returns a new decoder that reads from the io.Reader.
+// If r does not also implement io.ByteReader, it will be wrapped in a
+// bufio.Reader.
+func NewDecoder(r io.Reader) *Decoder {
+	dec := new(Decoder)
+	// We use the ability to read bytes as a plausible surrogate for buffering.
+	if _, ok := r.(io.ByteReader); !ok {
+		r = bufio.NewReader(r)
+	}
+	dec.r = r
+	dec.wireType = make(map[typeId]*wireType)
+	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
+	dec.ignorerCache = make(map[typeId]**decEngine)
+	dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes
+
+	return dec
+}
+
+// recvType loads the definition of a type.
+func (dec *Decoder) recvType(id typeId) {
+	// Have we already seen this type?  That's an error
+	if id < firstUserId || dec.wireType[id] != nil {
+		dec.err = errors.New("gob: duplicate type received")
+		return
+	}
+
+	// Type:
+	wire := new(wireType)
+	dec.decodeValue(tWireType, reflect.ValueOf(wire))
+	if dec.err != nil {
+		return
+	}
+	// Remember we've seen this type.
+	dec.wireType[id] = wire
+}
+
+var errBadCount = errors.New("invalid message length")
+
+// recvMessage reads the next count-delimited item from the input. It is the converse
+// of Encoder.writeMessage. It returns false on EOF or other error reading the message.
+func (dec *Decoder) recvMessage() bool {
+	// Read a count.
+	nbytes, _, err := decodeUintReader(dec.r, dec.countBuf)
+	if err != nil {
+		dec.err = err
+		return false
+	}
+	// Upper limit of 1GB, allowing room to grow a little without overflow.
+	// TODO: We might want more control over this limit.
+	if nbytes >= 1<<30 {
+		dec.err = errBadCount
+		return false
+	}
+	dec.readMessage(int(nbytes))
+	return dec.err == nil
+}
+
+// readMessage reads the next nbytes bytes from the input.
+func (dec *Decoder) readMessage(nbytes int) {
+	// Allocate the buffer.
+	if cap(dec.tmp) < nbytes {
+		dec.tmp = make([]byte, nbytes+100) // room to grow
+	}
+	dec.tmp = dec.tmp[:nbytes]
+
+	// Read the data
+	_, dec.err = io.ReadFull(dec.r, dec.tmp)
+	if dec.err != nil {
+		if dec.err == io.EOF {
+			dec.err = io.ErrUnexpectedEOF
+		}
+		return
+	}
+	dec.buf.Write(dec.tmp)
+}
+
+// toInt turns an encoded uint64 into an int, according to the marshaling rules.
+func toInt(x uint64) int64 {
+	i := int64(x >> 1)
+	if x&1 != 0 {
+		i = ^i
+	}
+	return i
+}
+
+func (dec *Decoder) nextInt() int64 {
+	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
+	if err != nil {
+		dec.err = err
+	}
+	return toInt(n)
+}
+
+func (dec *Decoder) nextUint() uint64 {
+	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
+	if err != nil {
+		dec.err = err
+	}
+	return n
+}
+
+// decodeTypeSequence parses:
+// TypeSequence
+//	(TypeDefinition DelimitedTypeDefinition*)?
+// and returns the type id of the next value.  It returns -1 at
+// EOF.  Upon return, the remainder of dec.buf is the value to be
+// decoded.  If this is an interface value, it can be ignored by
+// simply resetting that buffer.
+func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
+	for dec.err == nil {
+		if dec.buf.Len() == 0 {
+			if !dec.recvMessage() {
+				break
+			}
+		}
+		// Receive a type id.
+		id := typeId(dec.nextInt())
+		if id >= 0 {
+			// Value follows.
+			return id
+		}
+		// Type definition for (-id) follows.
+		dec.recvType(-id)
+		// When decoding an interface, after a type there may be a
+		// DelimitedValue still in the buffer.  Skip its count.
+		// (Alternatively, the buffer is empty and the byte count
+		// will be absorbed by recvMessage.)
+		if dec.buf.Len() > 0 {
+			if !isInterface {
+				dec.err = errors.New("extra data in buffer")
+				break
+			}
+			dec.nextUint()
+		}
+	}
+	return -1
+}
+
+// Decode reads the next value from the connection and stores
+// it in the data represented by the empty interface value.
+// If e is nil, the value will be discarded. Otherwise,
+// the value underlying e must be a pointer to the
+// correct type for the next data item received.
+func (dec *Decoder) Decode(e interface{}) error {
+	if e == nil {
+		return dec.DecodeValue(reflect.Value{})
+	}
+	value := reflect.ValueOf(e)
+	// If e represents a value as opposed to a pointer, the answer won't
+	// get back to the caller.  Make sure it's a pointer.
+	if value.Type().Kind() != reflect.Ptr {
+		dec.err = errors.New("gob: attempt to decode into a non-pointer")
+		return dec.err
+	}
+	return dec.DecodeValue(value)
+}
+
+// DecodeValue reads the next value from the connection.
+// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
+// Otherwise, it stores the value into v.  In that case, v must represent
+// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
+func (dec *Decoder) DecodeValue(v reflect.Value) error {
+	if v.IsValid() {
+		if v.Kind() == reflect.Ptr && !v.IsNil() {
+			// That's okay, we'll store through the pointer.
+		} else if !v.CanSet() {
+			return errors.New("gob: DecodeValue of unassignable value")
+		}
+	}
+	// Make sure we're single-threaded through here.
+	dec.mutex.Lock()
+	defer dec.mutex.Unlock()
+
+	dec.buf.Reset() // In case data lingers from previous invocation.
+	dec.err = nil
+	id := dec.decodeTypeSequence(false)
+	if dec.err == nil {
+		dec.decodeValue(id, v)
+	}
+	return dec.err
+}
+
+// If debug.go is compiled into the program , debugFunc prints a human-readable
+// representation of the gob data read from r by calling that file's Debug function.
+// Otherwise it is nil.
+var debugFunc func(io.Reader)
diff --git a/src/pkg/gob/doc.go b/src/pkg/encoding/gob/doc.go
similarity index 100%
rename from src/pkg/gob/doc.go
rename to src/pkg/encoding/gob/doc.go
diff --git a/src/pkg/encoding/gob/dump.go b/src/pkg/encoding/gob/dump.go
new file mode 100644
index 0000000..f7d822c
--- /dev/null
+++ b/src/pkg/encoding/gob/dump.go
@@ -0,0 +1,26 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Need to compile package gob with debug.go to build this program.
+
+import (
+	"encoding/gob"
+	"fmt"
+	"os"
+)
+
+func main() {
+	var err error
+	file := os.Stdin
+	if len(os.Args) > 1 {
+		file, err = os.Open(os.Args[1])
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "dump: %s\n", err)
+			os.Exit(1)
+		}
+	}
+	gob.Debug(file)
+}
diff --git a/src/pkg/encoding/gob/encode.go b/src/pkg/encoding/gob/encode.go
new file mode 100644
index 0000000..f05b17c
--- /dev/null
+++ b/src/pkg/encoding/gob/encode.go
@@ -0,0 +1,731 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+	"bytes"
+	"math"
+	"reflect"
+	"unsafe"
+)
+
+const uint64Size = int(unsafe.Sizeof(uint64(0)))
+
+// encoderState is the global execution state of an instance of the encoder.
+// Field numbers are delta encoded and always increase. The field
+// number is initialized to -1 so 0 comes out as delta(1). A delta of
+// 0 terminates the structure.
+type encoderState struct {
+	enc      *Encoder
+	b        *bytes.Buffer
+	sendZero bool                 // encoding an array element or map key/value pair; send zero values
+	fieldnum int                  // the last field number written.
+	buf      [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation.
+	next     *encoderState        // for free list
+}
+
+func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState {
+	e := enc.freeList
+	if e == nil {
+		e = new(encoderState)
+		e.enc = enc
+	} else {
+		enc.freeList = e.next
+	}
+	e.sendZero = false
+	e.fieldnum = 0
+	e.b = b
+	return e
+}
+
+func (enc *Encoder) freeEncoderState(e *encoderState) {
+	e.next = enc.freeList
+	enc.freeList = e
+}
+
+// Unsigned integers have a two-state encoding.  If the number is less
+// than 128 (0 through 0x7F), its value is written directly.
+// Otherwise the value is written in big-endian byte order preceded
+// by the byte length, negated.
+
+// encodeUint writes an encoded unsigned integer to state.b.
+func (state *encoderState) encodeUint(x uint64) {
+	if x <= 0x7F {
+		err := state.b.WriteByte(uint8(x))
+		if err != nil {
+			error_(err)
+		}
+		return
+	}
+	i := uint64Size
+	for x > 0 {
+		state.buf[i] = uint8(x)
+		x >>= 8
+		i--
+	}
+	state.buf[i] = uint8(i - uint64Size) // = loop count, negated
+	_, err := state.b.Write(state.buf[i : uint64Size+1])
+	if err != nil {
+		error_(err)
+	}
+}
+
+// encodeInt writes an encoded signed integer to state.w.
+// The low bit of the encoding says whether to bit complement the (other bits of the)
+// uint to recover the int.
+func (state *encoderState) encodeInt(i int64) {
+	var x uint64
+	if i < 0 {
+		x = uint64(^i<<1) | 1
+	} else {
+		x = uint64(i << 1)
+	}
+	state.encodeUint(uint64(x))
+}
+
+// encOp is the signature of an encoding operator for a given type.
+type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer)
+
+// The 'instructions' of the encoding machine
+type encInstr struct {
+	op     encOp
+	field  int     // field number
+	indir  int     // how many pointer indirections to reach the value in the struct
+	offset uintptr // offset in the structure of the field to encode
+}
+
+// update emits a field number and updates the state to record its value for delta encoding.
+// If the instruction pointer is nil, it does nothing
+func (state *encoderState) update(instr *encInstr) {
+	if instr != nil {
+		state.encodeUint(uint64(instr.field - state.fieldnum))
+		state.fieldnum = instr.field
+	}
+}
+
+// Each encoder for a composite is responsible for handling any
+// indirections associated with the elements of the data structure.
+// If any pointer so reached is nil, no bytes are written.  If the
+// data item is zero, no bytes are written.  Single values - ints,
+// strings etc. - are indirected before calling their encoders.
+// Otherwise, the output (for a scalar) is the field number, as an
+// encoded integer, followed by the field data in its appropriate
+// format.
+
+// encIndirect dereferences p indir times and returns the result.
+func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
+	for ; indir > 0; indir-- {
+		p = *(*unsafe.Pointer)(p)
+		if p == nil {
+			return unsafe.Pointer(nil)
+		}
+	}
+	return p
+}
+
+// encBool encodes the bool with address p as an unsigned 0 or 1.
+func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	b := *(*bool)(p)
+	if b || state.sendZero {
+		state.update(i)
+		if b {
+			state.encodeUint(1)
+		} else {
+			state.encodeUint(0)
+		}
+	}
+}
+
+// encInt encodes the int with address p.
+func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := int64(*(*int)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encUint encodes the uint with address p.
+func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uint)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encInt8 encodes the int8 with address p.
+func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := int64(*(*int8)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encUint8 encodes the uint8 with address p.
+func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uint8)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encInt16 encodes the int16 with address p.
+func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := int64(*(*int16)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encUint16 encodes the uint16 with address p.
+func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uint16)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encInt32 encodes the int32 with address p.
+func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := int64(*(*int32)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encUint encodes the uint32 with address p.
+func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uint32)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encInt64 encodes the int64 with address p.
+func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := *(*int64)(p)
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeInt(v)
+	}
+}
+
+// encInt64 encodes the uint64 with address p.
+func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := *(*uint64)(p)
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encUintptr encodes the uintptr with address p.
+func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	v := uint64(*(*uintptr)(p))
+	if v != 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// floatBits returns a uint64 holding the bits of a floating-point number.
+// Floating-point numbers are transmitted as uint64s holding the bits
+// of the underlying representation.  They are sent byte-reversed, with
+// the exponent end coming out first, so integer floating point numbers
+// (for example) transmit more compactly.  This routine does the
+// swizzling.
+func floatBits(f float64) uint64 {
+	u := math.Float64bits(f)
+	var v uint64
+	for i := 0; i < 8; i++ {
+		v <<= 8
+		v |= u & 0xFF
+		u >>= 8
+	}
+	return v
+}
+
+// encFloat32 encodes the float32 with address p.
+func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	f := *(*float32)(p)
+	if f != 0 || state.sendZero {
+		v := floatBits(float64(f))
+		state.update(i)
+		state.encodeUint(v)
+	}
+}
+
+// encFloat64 encodes the float64 with address p.
+func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	f := *(*float64)(p)
+	if f != 0 || state.sendZero {
+		state.update(i)
+		v := floatBits(f)
+		state.encodeUint(v)
+	}
+}
+
+// encComplex64 encodes the complex64 with address p.
+// Complex numbers are just a pair of floating-point numbers, real part first.
+func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	c := *(*complex64)(p)
+	if c != 0+0i || state.sendZero {
+		rpart := floatBits(float64(real(c)))
+		ipart := floatBits(float64(imag(c)))
+		state.update(i)
+		state.encodeUint(rpart)
+		state.encodeUint(ipart)
+	}
+}
+
+// encComplex128 encodes the complex128 with address p.
+func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	c := *(*complex128)(p)
+	if c != 0+0i || state.sendZero {
+		rpart := floatBits(real(c))
+		ipart := floatBits(imag(c))
+		state.update(i)
+		state.encodeUint(rpart)
+		state.encodeUint(ipart)
+	}
+}
+
+// encUint8Array encodes the byte slice whose header has address p.
+// Byte arrays are encoded as an unsigned count followed by the raw bytes.
+func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	b := *(*[]byte)(p)
+	if len(b) > 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(uint64(len(b)))
+		state.b.Write(b)
+	}
+}
+
+// encString encodes the string whose header has address p.
+// Strings are encoded as an unsigned count followed by the raw bytes.
+func encString(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	s := *(*string)(p)
+	if len(s) > 0 || state.sendZero {
+		state.update(i)
+		state.encodeUint(uint64(len(s)))
+		state.b.WriteString(s)
+	}
+}
+
+// encStructTerminator encodes the end of an encoded struct
+// as delta field number of 0.
+func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) {
+	state.encodeUint(0)
+}
+
+// Execution engine
+
+// encEngine an array of instructions indexed by field number of the encoding
+// data, typically a struct.  It is executed top to bottom, walking the struct.
+type encEngine struct {
+	instr []encInstr
+}
+
+const singletonField = 0
+
+// encodeSingle encodes a single top-level non-struct value.
+func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = singletonField
+	// There is no surrounding struct to frame the transmission, so we must
+	// generate data even if the item is zero.  To do this, set sendZero.
+	state.sendZero = true
+	instr := &engine.instr[singletonField]
+	p := unsafe.Pointer(basep) // offset will be zero
+	if instr.indir > 0 {
+		if p = encIndirect(p, instr.indir); p == nil {
+			return
+		}
+	}
+	instr.op(instr, state, p)
+	enc.freeEncoderState(state)
+}
+
+// encodeStruct encodes a single struct value.
+func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	for i := 0; i < len(engine.instr); i++ {
+		instr := &engine.instr[i]
+		p := unsafe.Pointer(basep + instr.offset)
+		if instr.indir > 0 {
+			if p = encIndirect(p, instr.indir); p == nil {
+				continue
+			}
+		}
+		instr.op(instr, state, p)
+	}
+	enc.freeEncoderState(state)
+}
+
+// encodeArray encodes the array whose 0th element is at p.
+func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	state.sendZero = true
+	state.encodeUint(uint64(length))
+	for i := 0; i < length; i++ {
+		elemp := p
+		up := unsafe.Pointer(elemp)
+		if elemIndir > 0 {
+			if up = encIndirect(up, elemIndir); up == nil {
+				errorf("encodeArray: nil element")
+			}
+			elemp = uintptr(up)
+		}
+		op(nil, state, unsafe.Pointer(elemp))
+		p += uintptr(elemWid)
+	}
+	enc.freeEncoderState(state)
+}
+
+// encodeReflectValue is a helper for maps. It encodes the value v.
+func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) {
+	for i := 0; i < indir && v.IsValid(); i++ {
+		v = reflect.Indirect(v)
+	}
+	if !v.IsValid() {
+		errorf("encodeReflectValue: nil element")
+	}
+	op(nil, state, unsafe.Pointer(unsafeAddr(v)))
+}
+
+// encodeMap encodes a map as unsigned count followed by key:value pairs.
+// Because map internals are not exposed, we must use reflection rather than
+// addresses.
+func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	state.sendZero = true
+	keys := mv.MapKeys()
+	state.encodeUint(uint64(len(keys)))
+	for _, key := range keys {
+		encodeReflectValue(state, key, keyOp, keyIndir)
+		encodeReflectValue(state, mv.MapIndex(key), elemOp, elemIndir)
+	}
+	enc.freeEncoderState(state)
+}
+
+// encodeInterface encodes the interface value iv.
+// To send an interface, we send a string identifying the concrete type, followed
+// by the type identifier (which might require defining that type right now), followed
+// by the concrete value.  A nil value gets sent as the empty string for the name,
+// followed by no value.
+func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	state.sendZero = true
+	if iv.IsNil() {
+		state.encodeUint(0)
+		return
+	}
+
+	ut := userType(iv.Elem().Type())
+	name, ok := concreteTypeToName[ut.base]
+	if !ok {
+		errorf("type not registered for interface: %s", ut.base)
+	}
+	// Send the name.
+	state.encodeUint(uint64(len(name)))
+	_, err := state.b.WriteString(name)
+	if err != nil {
+		error_(err)
+	}
+	// Define the type id if necessary.
+	enc.sendTypeDescriptor(enc.writer(), state, ut)
+	// Send the type id.
+	enc.sendTypeId(state, ut)
+	// Encode the value into a new buffer.  Any nested type definitions
+	// should be written to b, before the encoded value.
+	enc.pushWriter(b)
+	data := new(bytes.Buffer)
+	data.Write(spaceForLength)
+	enc.encode(data, iv.Elem(), ut)
+	if enc.err != nil {
+		error_(enc.err)
+	}
+	enc.popWriter()
+	enc.writeMessage(b, data)
+	if enc.err != nil {
+		error_(err)
+	}
+	enc.freeEncoderState(state)
+}
+
+// isZero returns whether the value is the zero of its type.
+func isZero(val reflect.Value) bool {
+	switch val.Kind() {
+	case reflect.Array:
+		for i := 0; i < val.Len(); i++ {
+			if !isZero(val.Index(i)) {
+				return false
+			}
+		}
+		return true
+	case reflect.Map, reflect.Slice, reflect.String:
+		return val.Len() == 0
+	case reflect.Bool:
+		return !val.Bool()
+	case reflect.Complex64, reflect.Complex128:
+		return val.Complex() == 0
+	case reflect.Chan, reflect.Func, reflect.Ptr:
+		return val.IsNil()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return val.Int() == 0
+	case reflect.Float32, reflect.Float64:
+		return val.Float() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return val.Uint() == 0
+	case reflect.Struct:
+		for i := 0; i < val.NumField(); i++ {
+			if !isZero(val.Field(i)) {
+				return false
+			}
+		}
+		return true
+	}
+	panic("unknown type in isZero " + val.Type().String())
+}
+
+// encGobEncoder encodes a value that implements the GobEncoder interface.
+// The data is sent as a byte array.
+func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, v reflect.Value) {
+	// TODO: should we catch panics from the called method?
+	// We know it's a GobEncoder, so just call the method directly.
+	data, err := v.Interface().(GobEncoder).GobEncode()
+	if err != nil {
+		error_(err)
+	}
+	state := enc.newEncoderState(b)
+	state.fieldnum = -1
+	state.encodeUint(uint64(len(data)))
+	state.b.Write(data)
+	enc.freeEncoderState(state)
+}
+
+var encOpTable = [...]encOp{
+	reflect.Bool:       encBool,
+	reflect.Int:        encInt,
+	reflect.Int8:       encInt8,
+	reflect.Int16:      encInt16,
+	reflect.Int32:      encInt32,
+	reflect.Int64:      encInt64,
+	reflect.Uint:       encUint,
+	reflect.Uint8:      encUint8,
+	reflect.Uint16:     encUint16,
+	reflect.Uint32:     encUint32,
+	reflect.Uint64:     encUint64,
+	reflect.Uintptr:    encUintptr,
+	reflect.Float32:    encFloat32,
+	reflect.Float64:    encFloat64,
+	reflect.Complex64:  encComplex64,
+	reflect.Complex128: encComplex128,
+	reflect.String:     encString,
+}
+
+// encOpFor returns (a pointer to) the encoding op for the base type under rt and
+// the indirection count to reach it.
+func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) {
+	ut := userType(rt)
+	// If the type implements GobEncoder, we handle it without further processing.
+	if ut.isGobEncoder {
+		return enc.gobEncodeOpFor(ut)
+	}
+	// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
+	// Return the pointer to the op we're already building.
+	if opPtr := inProgress[rt]; opPtr != nil {
+		return opPtr, ut.indir
+	}
+	typ := ut.base
+	indir := ut.indir
+	k := typ.Kind()
+	var op encOp
+	if int(k) < len(encOpTable) {
+		op = encOpTable[k]
+	}
+	if op == nil {
+		inProgress[rt] = &op
+		// Special cases
+		switch t := typ; t.Kind() {
+		case reflect.Slice:
+			if t.Elem().Kind() == reflect.Uint8 {
+				op = encUint8Array
+				break
+			}
+			// Slices have a header; we decode it to find the underlying array.
+			elemOp, indir := enc.encOpFor(t.Elem(), inProgress)
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				slice := (*reflect.SliceHeader)(p)
+				if !state.sendZero && slice.Len == 0 {
+					return
+				}
+				state.update(i)
+				state.enc.encodeArray(state.b, slice.Data, *elemOp, t.Elem().Size(), indir, int(slice.Len))
+			}
+		case reflect.Array:
+			// True arrays have size in the type.
+			elemOp, indir := enc.encOpFor(t.Elem(), inProgress)
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				state.update(i)
+				state.enc.encodeArray(state.b, uintptr(p), *elemOp, t.Elem().Size(), indir, t.Len())
+			}
+		case reflect.Map:
+			keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress)
+			elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				// Maps cannot be accessed by moving addresses around the way
+				// that slices etc. can.  We must recover a full reflection value for
+				// the iteration.
+				v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p)))
+				mv := reflect.Indirect(v)
+				// We send zero-length (but non-nil) maps because the
+				// receiver might want to use the map.  (Maps don't use append.)
+				if !state.sendZero && mv.IsNil() {
+					return
+				}
+				state.update(i)
+				state.enc.encodeMap(state.b, mv, *keyOp, *elemOp, keyIndir, elemIndir)
+			}
+		case reflect.Struct:
+			// Generate a closure that calls out to the engine for the nested type.
+			enc.getEncEngine(userType(typ))
+			info := mustGetTypeInfo(typ)
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				state.update(i)
+				// indirect through info to delay evaluation for recursive structs
+				state.enc.encodeStruct(state.b, info.encoder, uintptr(p))
+			}
+		case reflect.Interface:
+			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+				// Interfaces transmit the name and contents of the concrete
+				// value they contain.
+				v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p)))
+				iv := reflect.Indirect(v)
+				if !state.sendZero && (!iv.IsValid() || iv.IsNil()) {
+					return
+				}
+				state.update(i)
+				state.enc.encodeInterface(state.b, iv)
+			}
+		}
+	}
+	if op == nil {
+		errorf("can't happen: encode type %s", rt)
+	}
+	return &op, indir
+}
+
+// gobEncodeOpFor returns the op for a type that is known to implement
+// GobEncoder.
+func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
+	rt := ut.user
+	if ut.encIndir == -1 {
+		rt = reflect.PtrTo(rt)
+	} else if ut.encIndir > 0 {
+		for i := int8(0); i < ut.encIndir; i++ {
+			rt = rt.Elem()
+		}
+	}
+	var op encOp
+	op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
+		var v reflect.Value
+		if ut.encIndir == -1 {
+			// Need to climb up one level to turn value into pointer.
+			v = reflect.ValueOf(unsafe.Unreflect(rt, unsafe.Pointer(&p)))
+		} else {
+			v = reflect.ValueOf(unsafe.Unreflect(rt, p))
+		}
+		if !state.sendZero && isZero(v) {
+			return
+		}
+		state.update(i)
+		state.enc.encodeGobEncoder(state.b, v)
+	}
+	return &op, int(ut.encIndir) // encIndir: op will get called with p == address of receiver.
+}
+
+// compileEnc returns the engine to compile the type.
+func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
+	srt := ut.base
+	engine := new(encEngine)
+	seen := make(map[reflect.Type]*encOp)
+	rt := ut.base
+	if ut.isGobEncoder {
+		rt = ut.user
+	}
+	if !ut.isGobEncoder &&
+		srt.Kind() == reflect.Struct {
+		for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ {
+			f := srt.Field(fieldNum)
+			if !isExported(f.Name) {
+				continue
+			}
+			op, indir := enc.encOpFor(f.Type, seen)
+			engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, indir, uintptr(f.Offset)})
+			wireFieldNum++
+		}
+		if srt.NumField() > 0 && len(engine.instr) == 0 {
+			errorf("type %s has no exported fields", rt)
+		}
+		engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, 0, 0})
+	} else {
+		engine.instr = make([]encInstr, 1)
+		op, indir := enc.encOpFor(rt, seen)
+		engine.instr[0] = encInstr{*op, singletonField, indir, 0} // offset is zero
+	}
+	return engine
+}
+
+// getEncEngine returns the engine to compile the type.
+// typeLock must be held (or we're in initialization and guaranteed single-threaded).
+func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine {
+	info, err1 := getTypeInfo(ut)
+	if err1 != nil {
+		error_(err1)
+	}
+	if info.encoder == nil {
+		// mark this engine as underway before compiling to handle recursive types.
+		info.encoder = new(encEngine)
+		info.encoder = enc.compileEnc(ut)
+	}
+	return info.encoder
+}
+
+// lockAndGetEncEngine is a function that locks and compiles.
+// This lets us hold the lock only while compiling, not when encoding.
+func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine {
+	typeLock.Lock()
+	defer typeLock.Unlock()
+	return enc.getEncEngine(ut)
+}
+
+func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) {
+	defer catchError(&enc.err)
+	engine := enc.lockAndGetEncEngine(ut)
+	indir := ut.indir
+	if ut.isGobEncoder {
+		indir = int(ut.encIndir)
+	}
+	for i := 0; i < indir; i++ {
+		value = reflect.Indirect(value)
+	}
+	if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct {
+		enc.encodeStruct(b, engine, unsafeAddr(value))
+	} else {
+		enc.encodeSingle(b, engine, unsafeAddr(value))
+	}
+}
diff --git a/src/pkg/encoding/gob/encoder.go b/src/pkg/encoding/gob/encoder.go
new file mode 100644
index 0000000..a15b5a1
--- /dev/null
+++ b/src/pkg/encoding/gob/encoder.go
@@ -0,0 +1,253 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"reflect"
+	"sync"
+)
+
+// An Encoder manages the transmission of type and data information to the
+// other side of a connection.
+type Encoder struct {
+	mutex      sync.Mutex              // each item must be sent atomically
+	w          []io.Writer             // where to send the data
+	sent       map[reflect.Type]typeId // which types we've already sent
+	countState *encoderState           // stage for writing counts
+	freeList   *encoderState           // list of free encoderStates; avoids reallocation
+	byteBuf    bytes.Buffer            // buffer for top-level encoderState
+	err        error
+}
+
+// Before we encode a message, we reserve space at the head of the
+// buffer in which to encode its length. This means we can use the
+// buffer to assemble the message without another allocation.
+const maxLength = 9 // Maximum size of an encoded length.
+var spaceForLength = make([]byte, maxLength)
+
+// NewEncoder returns a new encoder that will transmit on the io.Writer.
+func NewEncoder(w io.Writer) *Encoder {
+	enc := new(Encoder)
+	enc.w = []io.Writer{w}
+	enc.sent = make(map[reflect.Type]typeId)
+	enc.countState = enc.newEncoderState(new(bytes.Buffer))
+	return enc
+}
+
+// writer() returns the innermost writer the encoder is using
+func (enc *Encoder) writer() io.Writer {
+	return enc.w[len(enc.w)-1]
+}
+
+// pushWriter adds a writer to the encoder.
+func (enc *Encoder) pushWriter(w io.Writer) {
+	enc.w = append(enc.w, w)
+}
+
+// popWriter pops the innermost writer.
+func (enc *Encoder) popWriter() {
+	enc.w = enc.w[0 : len(enc.w)-1]
+}
+
+func (enc *Encoder) badType(rt reflect.Type) {
+	enc.setError(errors.New("gob: can't encode type " + rt.String()))
+}
+
+func (enc *Encoder) setError(err error) {
+	if enc.err == nil { // remember the first.
+		enc.err = err
+	}
+}
+
+// writeMessage sends the data item preceded by a unsigned count of its length.
+func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) {
+	// Space has been reserved for the length at the head of the message.
+	// This is a little dirty: we grab the slice from the bytes.Buffer and massage
+	// it by hand.
+	message := b.Bytes()
+	messageLen := len(message) - maxLength
+	// Encode the length.
+	enc.countState.b.Reset()
+	enc.countState.encodeUint(uint64(messageLen))
+	// Copy the length to be a prefix of the message.
+	offset := maxLength - enc.countState.b.Len()
+	copy(message[offset:], enc.countState.b.Bytes())
+	// Write the data.
+	_, err := w.Write(message[offset:])
+	// Drain the buffer and restore the space at the front for the count of the next message.
+	b.Reset()
+	b.Write(spaceForLength)
+	if err != nil {
+		enc.setError(err)
+	}
+}
+
+// sendActualType sends the requested type, without further investigation, unless
+// it's been sent before.
+func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) {
+	if _, alreadySent := enc.sent[actual]; alreadySent {
+		return false
+	}
+	typeLock.Lock()
+	info, err := getTypeInfo(ut)
+	typeLock.Unlock()
+	if err != nil {
+		enc.setError(err)
+		return
+	}
+	// Send the pair (-id, type)
+	// Id:
+	state.encodeInt(-int64(info.id))
+	// Type:
+	enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo)
+	enc.writeMessage(w, state.b)
+	if enc.err != nil {
+		return
+	}
+
+	// Remember we've sent this type, both what the user gave us and the base type.
+	enc.sent[ut.base] = info.id
+	if ut.user != ut.base {
+		enc.sent[ut.user] = info.id
+	}
+	// Now send the inner types
+	switch st := actual; st.Kind() {
+	case reflect.Struct:
+		for i := 0; i < st.NumField(); i++ {
+			if isExported(st.Field(i).Name) {
+				enc.sendType(w, state, st.Field(i).Type)
+			}
+		}
+	case reflect.Array, reflect.Slice:
+		enc.sendType(w, state, st.Elem())
+	case reflect.Map:
+		enc.sendType(w, state, st.Key())
+		enc.sendType(w, state, st.Elem())
+	}
+	return true
+}
+
+// sendType sends the type info to the other side, if necessary. 
+func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
+	ut := userType(origt)
+	if ut.isGobEncoder {
+		// The rules are different: regardless of the underlying type's representation,
+		// we need to tell the other side that this exact type is a GobEncoder.
+		return enc.sendActualType(w, state, ut, ut.user)
+	}
+
+	// It's a concrete value, so drill down to the base type.
+	switch rt := ut.base; rt.Kind() {
+	default:
+		// Basic types and interfaces do not need to be described.
+		return
+	case reflect.Slice:
+		// If it's []uint8, don't send; it's considered basic.
+		if rt.Elem().Kind() == reflect.Uint8 {
+			return
+		}
+		// Otherwise we do send.
+		break
+	case reflect.Array:
+		// arrays must be sent so we know their lengths and element types.
+		break
+	case reflect.Map:
+		// maps must be sent so we know their lengths and key/value types.
+		break
+	case reflect.Struct:
+		// structs must be sent so we know their fields.
+		break
+	case reflect.Chan, reflect.Func:
+		// Probably a bad field in a struct.
+		enc.badType(rt)
+		return
+	}
+
+	return enc.sendActualType(w, state, ut, ut.base)
+}
+
+// Encode transmits the data item represented by the empty interface value,
+// guaranteeing that all necessary type information has been transmitted first.
+func (enc *Encoder) Encode(e interface{}) error {
+	return enc.EncodeValue(reflect.ValueOf(e))
+}
+
+// sendTypeDescriptor makes sure the remote side knows about this type.
+// It will send a descriptor if this is the first time the type has been
+// sent.
+func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) {
+	// Make sure the type is known to the other side.
+	// First, have we already sent this type?
+	rt := ut.base
+	if ut.isGobEncoder {
+		rt = ut.user
+	}
+	if _, alreadySent := enc.sent[rt]; !alreadySent {
+		// No, so send it.
+		sent := enc.sendType(w, state, rt)
+		if enc.err != nil {
+			return
+		}
+		// If the type info has still not been transmitted, it means we have
+		// a singleton basic type (int, []byte etc.) at top level.  We don't
+		// need to send the type info but we do need to update enc.sent.
+		if !sent {
+			typeLock.Lock()
+			info, err := getTypeInfo(ut)
+			typeLock.Unlock()
+			if err != nil {
+				enc.setError(err)
+				return
+			}
+			enc.sent[rt] = info.id
+		}
+	}
+}
+
+// sendTypeId sends the id, which must have already been defined.
+func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
+	// Identify the type of this top-level value.
+	state.encodeInt(int64(enc.sent[ut.base]))
+}
+
+// EncodeValue transmits the data item represented by the reflection value,
+// guaranteeing that all necessary type information has been transmitted first.
+func (enc *Encoder) EncodeValue(value reflect.Value) error {
+	// Make sure we're single-threaded through here, so multiple
+	// goroutines can share an encoder.
+	enc.mutex.Lock()
+	defer enc.mutex.Unlock()
+
+	// Remove any nested writers remaining due to previous errors.
+	enc.w = enc.w[0:1]
+
+	ut, err := validUserType(value.Type())
+	if err != nil {
+		return err
+	}
+
+	enc.err = nil
+	enc.byteBuf.Reset()
+	enc.byteBuf.Write(spaceForLength)
+	state := enc.newEncoderState(&enc.byteBuf)
+
+	enc.sendTypeDescriptor(enc.writer(), state, ut)
+	enc.sendTypeId(state, ut)
+	if enc.err != nil {
+		return enc.err
+	}
+
+	// Encode the object.
+	enc.encode(state.b, value, ut)
+	if enc.err == nil {
+		enc.writeMessage(enc.writer(), state.b)
+	}
+
+	enc.freeEncoderState(state)
+	return enc.err
+}
diff --git a/src/pkg/encoding/gob/encoder_test.go b/src/pkg/encoding/gob/encoder_test.go
new file mode 100644
index 0000000..7a30f91
--- /dev/null
+++ b/src/pkg/encoding/gob/encoder_test.go
@@ -0,0 +1,688 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type ET2 struct {
+	X string
+}
+
+type ET1 struct {
+	A    int
+	Et2  *ET2
+	Next *ET1
+}
+
+// Like ET1 but with a different name for a field
+type ET3 struct {
+	A             int
+	Et2           *ET2
+	DifferentNext *ET1
+}
+
+// Like ET1 but with a different type for a field
+type ET4 struct {
+	A    int
+	Et2  float64
+	Next int
+}
+
+func TestEncoderDecoder(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	et1 := new(ET1)
+	et1.A = 7
+	et1.Et2 = new(ET2)
+	err := enc.Encode(et1)
+	if err != nil {
+		t.Error("encoder fail:", err)
+	}
+	dec := NewDecoder(b)
+	newEt1 := new(ET1)
+	err = dec.Decode(newEt1)
+	if err != nil {
+		t.Fatal("error decoding ET1:", err)
+	}
+
+	if !reflect.DeepEqual(et1, newEt1) {
+		t.Fatalf("invalid data for et1: expected %+v; got %+v", *et1, *newEt1)
+	}
+	if b.Len() != 0 {
+		t.Error("not at eof;", b.Len(), "bytes left")
+	}
+
+	enc.Encode(et1)
+	newEt1 = new(ET1)
+	err = dec.Decode(newEt1)
+	if err != nil {
+		t.Fatal("round 2: error decoding ET1:", err)
+	}
+	if !reflect.DeepEqual(et1, newEt1) {
+		t.Fatalf("round 2: invalid data for et1: expected %+v; got %+v", *et1, *newEt1)
+	}
+	if b.Len() != 0 {
+		t.Error("round 2: not at eof;", b.Len(), "bytes left")
+	}
+
+	// Now test with a running encoder/decoder pair that we recognize a type mismatch.
+	err = enc.Encode(et1)
+	if err != nil {
+		t.Error("round 3: encoder fail:", err)
+	}
+	newEt2 := new(ET2)
+	err = dec.Decode(newEt2)
+	if err == nil {
+		t.Fatal("round 3: expected `bad type' error decoding ET2")
+	}
+}
+
+// Run one value through the encoder/decoder, but use the wrong type.
+// Input is always an ET1; we compare it to whatever is under 'e'.
+func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	et1 := new(ET1)
+	et1.A = 7
+	et1.Et2 = new(ET2)
+	err := enc.Encode(et1)
+	if err != nil {
+		t.Error("encoder fail:", err)
+	}
+	dec := NewDecoder(b)
+	err = dec.Decode(e)
+	if shouldFail && err == nil {
+		t.Error("expected error for", msg)
+	}
+	if !shouldFail && err != nil {
+		t.Error("unexpected error for", msg, err)
+	}
+}
+
+// Test that we recognize a bad type the first time.
+func TestWrongTypeDecoder(t *testing.T) {
+	badTypeCheck(new(ET2), true, "no fields in common", t)
+	badTypeCheck(new(ET3), false, "different name of field", t)
+	badTypeCheck(new(ET4), true, "different type of field", t)
+}
+
+func corruptDataCheck(s string, err error, t *testing.T) {
+	b := bytes.NewBufferString(s)
+	dec := NewDecoder(b)
+	err1 := dec.Decode(new(ET2))
+	if err1 != err {
+		t.Errorf("from %q expected error %s; got %s", s, err, err1)
+	}
+}
+
+// Check that we survive bad data.
+func TestBadData(t *testing.T) {
+	corruptDataCheck("", io.EOF, t)
+	corruptDataCheck("\x7Fhi", io.ErrUnexpectedEOF, t)
+	corruptDataCheck("\x03now is the time for all good men", errBadType, t)
+}
+
+// Types not supported by the Encoder.
+var unsupportedValues = []interface{}{
+	make(chan int),
+	func(a int) bool { return true },
+}
+
+func TestUnsupported(t *testing.T) {
+	var b bytes.Buffer
+	enc := NewEncoder(&b)
+	for _, v := range unsupportedValues {
+		err := enc.Encode(v)
+		if err == nil {
+			t.Errorf("expected error for %T; got none", v)
+		}
+	}
+}
+
+func encAndDec(in, out interface{}) error {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(in)
+	if err != nil {
+		return err
+	}
+	dec := NewDecoder(b)
+	err = dec.Decode(out)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func TestTypeToPtrType(t *testing.T) {
+	// Encode a T, decode a *T
+	type Type0 struct {
+		A int
+	}
+	t0 := Type0{7}
+	t0p := new(Type0)
+	if err := encAndDec(t0, t0p); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestPtrTypeToType(t *testing.T) {
+	// Encode a *T, decode a T
+	type Type1 struct {
+		A uint
+	}
+	t1p := &Type1{17}
+	var t1 Type1
+	if err := encAndDec(t1, t1p); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestTypeToPtrPtrPtrPtrType(t *testing.T) {
+	type Type2 struct {
+		A ****float64
+	}
+	t2 := Type2{}
+	t2.A = new(***float64)
+	*t2.A = new(**float64)
+	**t2.A = new(*float64)
+	***t2.A = new(float64)
+	****t2.A = 27.4
+	t2pppp := new(***Type2)
+	if err := encAndDec(t2, t2pppp); err != nil {
+		t.Fatal(err)
+	}
+	if ****(****t2pppp).A != ****t2.A {
+		t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).A, ****t2.A)
+	}
+}
+
+func TestSlice(t *testing.T) {
+	type Type3 struct {
+		A []string
+	}
+	t3p := &Type3{[]string{"hello", "world"}}
+	var t3 Type3
+	if err := encAndDec(t3, t3p); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestValueError(t *testing.T) {
+	// Encode a *T, decode a T
+	type Type4 struct {
+		A int
+	}
+	t4p := &Type4{3}
+	var t4 Type4 // note: not a pointer.
+	if err := encAndDec(t4p, t4); err == nil || strings.Index(err.Error(), "pointer") < 0 {
+		t.Error("expected error about pointer; got", err)
+	}
+}
+
+func TestArray(t *testing.T) {
+	type Type5 struct {
+		A [3]string
+		B [3]byte
+	}
+	type Type6 struct {
+		A [2]string // can't hold t5.a
+	}
+	t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}}
+	var t5p Type5
+	if err := encAndDec(t5, &t5p); err != nil {
+		t.Error(err)
+	}
+	var t6 Type6
+	if err := encAndDec(t5, &t6); err == nil {
+		t.Error("should fail with mismatched array sizes")
+	}
+}
+
+func TestRecursiveMapType(t *testing.T) {
+	type recursiveMap map[string]recursiveMap
+	r1 := recursiveMap{"A": recursiveMap{"B": nil, "C": nil}, "D": nil}
+	r2 := make(recursiveMap)
+	if err := encAndDec(r1, &r2); err != nil {
+		t.Error(err)
+	}
+}
+
+func TestRecursiveSliceType(t *testing.T) {
+	type recursiveSlice []recursiveSlice
+	r1 := recursiveSlice{0: recursiveSlice{0: nil}, 1: nil}
+	r2 := make(recursiveSlice, 0)
+	if err := encAndDec(r1, &r2); err != nil {
+		t.Error(err)
+	}
+}
+
+// Regression test for bug: must send zero values inside arrays
+func TestDefaultsInArray(t *testing.T) {
+	type Type7 struct {
+		B []bool
+		I []int
+		S []string
+		F []float64
+	}
+	t7 := Type7{
+		[]bool{false, false, true},
+		[]int{0, 0, 1},
+		[]string{"hi", "", "there"},
+		[]float64{0, 0, 1},
+	}
+	var t7p Type7
+	if err := encAndDec(t7, &t7p); err != nil {
+		t.Error(err)
+	}
+}
+
+var testInt int
+var testFloat32 float32
+var testString string
+var testSlice []string
+var testMap map[string]int
+var testArray [7]int
+
+type SingleTest struct {
+	in  interface{}
+	out interface{}
+	err string
+}
+
+var singleTests = []SingleTest{
+	{17, &testInt, ""},
+	{float32(17.5), &testFloat32, ""},
+	{"bike shed", &testString, ""},
+	{[]string{"bike", "shed", "paint", "color"}, &testSlice, ""},
+	{map[string]int{"seven": 7, "twelve": 12}, &testMap, ""},
+	{[7]int{4, 55, 0, 0, 0, 0, 0}, &testArray, ""}, // case that once triggered a bug
+	{[7]int{4, 55, 1, 44, 22, 66, 1234}, &testArray, ""},
+
+	// Decode errors
+	{172, &testFloat32, "type"},
+}
+
+func TestSingletons(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	dec := NewDecoder(b)
+	for _, test := range singleTests {
+		b.Reset()
+		err := enc.Encode(test.in)
+		if err != nil {
+			t.Errorf("error encoding %v: %s", test.in, err)
+			continue
+		}
+		err = dec.Decode(test.out)
+		switch {
+		case err != nil && test.err == "":
+			t.Errorf("error decoding %v: %s", test.in, err)
+			continue
+		case err == nil && test.err != "":
+			t.Errorf("expected error decoding %v: %s", test.in, test.err)
+			continue
+		case err != nil && test.err != "":
+			if strings.Index(err.Error(), test.err) < 0 {
+				t.Errorf("wrong error decoding %v: wanted %s, got %v", test.in, test.err, err)
+			}
+			continue
+		}
+		// Get rid of the pointer in the rhs
+		val := reflect.ValueOf(test.out).Elem().Interface()
+		if !reflect.DeepEqual(test.in, val) {
+			t.Errorf("decoding singleton: expected %v got %v", test.in, val)
+		}
+	}
+}
+
+func TestStructNonStruct(t *testing.T) {
+	type Struct struct {
+		A string
+	}
+	type NonStruct string
+	s := Struct{"hello"}
+	var sp Struct
+	if err := encAndDec(s, &sp); err != nil {
+		t.Error(err)
+	}
+	var ns NonStruct
+	if err := encAndDec(s, &ns); err == nil {
+		t.Error("should get error for struct/non-struct")
+	} else if strings.Index(err.Error(), "type") < 0 {
+		t.Error("for struct/non-struct expected type error; got", err)
+	}
+	// Now try the other way
+	var nsp NonStruct
+	if err := encAndDec(ns, &nsp); err != nil {
+		t.Error(err)
+	}
+	if err := encAndDec(ns, &s); err == nil {
+		t.Error("should get error for non-struct/struct")
+	} else if strings.Index(err.Error(), "type") < 0 {
+		t.Error("for non-struct/struct expected type error; got", err)
+	}
+}
+
+type interfaceIndirectTestI interface {
+	F() bool
+}
+
+type interfaceIndirectTestT struct{}
+
+func (this *interfaceIndirectTestT) F() bool {
+	return true
+}
+
+// A version of a bug reported on golang-nuts.  Also tests top-level
+// slice of interfaces.  The issue was registering *T caused T to be
+// stored as the concrete type.
+func TestInterfaceIndirect(t *testing.T) {
+	Register(&interfaceIndirectTestT{})
+	b := new(bytes.Buffer)
+	w := []interfaceIndirectTestI{&interfaceIndirectTestT{}}
+	err := NewEncoder(b).Encode(w)
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+
+	var r []interfaceIndirectTestI
+	err = NewDecoder(b).Decode(&r)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+}
+
+// Now follow various tests that decode into things that can't represent the
+// encoded value, all of which should be legal.
+
+// Also, when the ignored object contains an interface value, it may define
+// types. Make sure that skipping the value still defines the types by using
+// the encoder/decoder pair to send a value afterwards.  If an interface
+// is sent, its type in the test is always NewType0, so this checks that the
+// encoder and decoder don't skew with respect to type definitions.
+
+type Struct0 struct {
+	I interface{}
+}
+
+type NewType0 struct {
+	S string
+}
+
+type ignoreTest struct {
+	in, out interface{}
+}
+
+var ignoreTests = []ignoreTest{
+	// Decode normal struct into an empty struct
+	{&struct{ A int }{23}, &struct{}{}},
+	// Decode normal struct into a nil.
+	{&struct{ A int }{23}, nil},
+	// Decode singleton string into a nil.
+	{"hello, world", nil},
+	// Decode singleton slice into a nil.
+	{[]int{1, 2, 3, 4}, nil},
+	// Decode struct containing an interface into a nil.
+	{&Struct0{&NewType0{"value0"}}, nil},
+	// Decode singleton slice of interfaces into a nil.
+	{[]interface{}{"hi", &NewType0{"value1"}, 23}, nil},
+}
+
+func TestDecodeIntoNothing(t *testing.T) {
+	Register(new(NewType0))
+	for i, test := range ignoreTests {
+		b := new(bytes.Buffer)
+		enc := NewEncoder(b)
+		err := enc.Encode(test.in)
+		if err != nil {
+			t.Errorf("%d: encode error %s:", i, err)
+			continue
+		}
+		dec := NewDecoder(b)
+		err = dec.Decode(test.out)
+		if err != nil {
+			t.Errorf("%d: decode error: %s", i, err)
+			continue
+		}
+		// Now see if the encoder and decoder are in a consistent state.
+		str := fmt.Sprintf("Value %d", i)
+		err = enc.Encode(&NewType0{str})
+		if err != nil {
+			t.Fatalf("%d: NewType0 encode error: %s", i, err)
+		}
+		ns := new(NewType0)
+		err = dec.Decode(ns)
+		if err != nil {
+			t.Fatalf("%d: NewType0 decode error: %s", i, err)
+		}
+		if ns.S != str {
+			t.Fatalf("%d: expected %q got %q", i, str, ns.S)
+		}
+	}
+}
+
+// Another bug from golang-nuts, involving nested interfaces.
+type Bug0Outer struct {
+	Bug0Field interface{}
+}
+
+type Bug0Inner struct {
+	A int
+}
+
+func TestNestedInterfaces(t *testing.T) {
+	var buf bytes.Buffer
+	e := NewEncoder(&buf)
+	d := NewDecoder(&buf)
+	Register(new(Bug0Outer))
+	Register(new(Bug0Inner))
+	f := &Bug0Outer{&Bug0Outer{&Bug0Inner{7}}}
+	var v interface{} = f
+	err := e.Encode(&v)
+	if err != nil {
+		t.Fatal("Encode:", err)
+	}
+	err = d.Decode(&v)
+	if err != nil {
+		t.Fatal("Decode:", err)
+	}
+	// Make sure it decoded correctly.
+	outer1, ok := v.(*Bug0Outer)
+	if !ok {
+		t.Fatalf("v not Bug0Outer: %T", v)
+	}
+	outer2, ok := outer1.Bug0Field.(*Bug0Outer)
+	if !ok {
+		t.Fatalf("v.Bug0Field not Bug0Outer: %T", outer1.Bug0Field)
+	}
+	inner, ok := outer2.Bug0Field.(*Bug0Inner)
+	if !ok {
+		t.Fatalf("v.Bug0Field.Bug0Field not Bug0Inner: %T", outer2.Bug0Field)
+	}
+	if inner.A != 7 {
+		t.Fatalf("final value %d; expected %d", inner.A, 7)
+	}
+}
+
+// The bugs keep coming. We forgot to send map subtypes before the map.
+
+type Bug1Elem struct {
+	Name string
+	Id   int
+}
+
+type Bug1StructMap map[string]Bug1Elem
+
+func bug1EncDec(in Bug1StructMap, out *Bug1StructMap) error {
+	return nil
+}
+
+func TestMapBug1(t *testing.T) {
+	in := make(Bug1StructMap)
+	in["val1"] = Bug1Elem{"elem1", 1}
+	in["val2"] = Bug1Elem{"elem2", 2}
+
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(in)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	dec := NewDecoder(b)
+	out := make(Bug1StructMap)
+	err = dec.Decode(&out)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if !reflect.DeepEqual(in, out) {
+		t.Errorf("mismatch: %v %v", in, out)
+	}
+}
+
+func TestGobMapInterfaceEncode(t *testing.T) {
+	m := map[string]interface{}{
+		"up": uintptr(0),
+		"i0": []int{-1},
+		"i1": []int8{-1},
+		"i2": []int16{-1},
+		"i3": []int32{-1},
+		"i4": []int64{-1},
+		"u0": []uint{1},
+		"u1": []uint8{1},
+		"u2": []uint16{1},
+		"u3": []uint32{1},
+		"u4": []uint64{1},
+		"f0": []float32{1},
+		"f1": []float64{1},
+		"c0": []complex64{complex(2, -2)},
+		"c1": []complex128{complex(2, float64(-2))},
+		"us": []uintptr{0},
+		"bo": []bool{false},
+		"st": []string{"s"},
+	}
+	buf := bytes.NewBuffer(nil)
+	enc := NewEncoder(buf)
+	err := enc.Encode(m)
+	if err != nil {
+		t.Errorf("encode map: %s", err)
+	}
+}
+
+func TestSliceReusesMemory(t *testing.T) {
+	buf := bytes.NewBuffer(nil)
+	// Bytes
+	{
+		x := []byte("abcd")
+		enc := NewEncoder(buf)
+		err := enc.Encode(x)
+		if err != nil {
+			t.Errorf("bytes: encode: %s", err)
+		}
+		// Decode into y, which is big enough.
+		y := []byte("ABCDE")
+		addr := &y[0]
+		dec := NewDecoder(buf)
+		err = dec.Decode(&y)
+		if err != nil {
+			t.Fatal("bytes: decode:", err)
+		}
+		if !bytes.Equal(x, y) {
+			t.Errorf("bytes: expected %q got %q\n", x, y)
+		}
+		if addr != &y[0] {
+			t.Errorf("bytes: unnecessary reallocation")
+		}
+	}
+	// general slice
+	{
+		x := []rune("abcd")
+		enc := NewEncoder(buf)
+		err := enc.Encode(x)
+		if err != nil {
+			t.Errorf("ints: encode: %s", err)
+		}
+		// Decode into y, which is big enough.
+		y := []rune("ABCDE")
+		addr := &y[0]
+		dec := NewDecoder(buf)
+		err = dec.Decode(&y)
+		if err != nil {
+			t.Fatal("ints: decode:", err)
+		}
+		if !reflect.DeepEqual(x, y) {
+			t.Errorf("ints: expected %q got %q\n", x, y)
+		}
+		if addr != &y[0] {
+			t.Errorf("ints: unnecessary reallocation")
+		}
+	}
+}
+
+// Used to crash: negative count in recvMessage.
+func TestBadCount(t *testing.T) {
+	b := []byte{0xfb, 0xa5, 0x82, 0x2f, 0xca, 0x1}
+	if err := NewDecoder(bytes.NewBuffer(b)).Decode(nil); err == nil {
+		t.Error("expected error from bad count")
+	} else if err.Error() != errBadCount.Error() {
+		t.Error("expected bad count error; got", err)
+	}
+}
+
+// Verify that sequential Decoders built on a single input will
+// succeed if the input implements ReadByte and there is no
+// type information in the stream.
+func TestSequentialDecoder(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	const count = 10
+	for i := 0; i < count; i++ {
+		s := fmt.Sprintf("%d", i)
+		if err := enc.Encode(s); err != nil {
+			t.Error("encoder fail:", err)
+		}
+	}
+	for i := 0; i < count; i++ {
+		dec := NewDecoder(b)
+		var s string
+		if err := dec.Decode(&s); err != nil {
+			t.Fatal("decoder fail:", err)
+		}
+		if s != fmt.Sprintf("%d", i) {
+			t.Fatalf("decode expected %d got %s", i, s)
+		}
+	}
+}
+
+// Should be able to have unrepresentable fields (chan, func) as long as they
+// are unexported.
+type Bug2 struct {
+	A int
+	b chan int
+}
+
+func TestUnexportedChan(t *testing.T) {
+	b := Bug2{23, make(chan int)}
+	var stream bytes.Buffer
+	enc := NewEncoder(&stream)
+	if err := enc.Encode(b); err != nil {
+		t.Fatalf("error encoding unexported channel: %s", err)
+	}
+}
+
+func TestSliceIncompatibility(t *testing.T) {
+	var in = []byte{1, 2, 3}
+	var out []int
+	if err := encAndDec(in, &out); err == nil {
+		t.Error("expected compatibility error")
+	}
+}
diff --git a/src/pkg/encoding/gob/error.go b/src/pkg/encoding/gob/error.go
new file mode 100644
index 0000000..fbae8b6
--- /dev/null
+++ b/src/pkg/encoding/gob/error.go
@@ -0,0 +1,39 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import "fmt"
+
+// Errors in decoding and encoding are handled using panic and recover.
+// Panics caused by user error (that is, everything except run-time panics
+// such as "index out of bounds" errors) do not leave the file that caused
+// them, but are instead turned into plain error returns.  Encoding and
+// decoding functions and methods that do not return an error either use
+// panic to report an error or are guaranteed error-free.
+
+// A gobError is used to distinguish errors (panics) generated in this package.
+type gobError struct {
+	err error
+}
+
+// errorf is like error_ but takes Printf-style arguments to construct an error.
+// It always prefixes the message with "gob: ".
+func errorf(format string, args ...interface{}) {
+	error_(fmt.Errorf("gob: "+format, args...))
+}
+
+// error wraps the argument error and uses it as the argument to panic.
+func error_(err error) {
+	panic(gobError{err})
+}
+
+// catchError is meant to be used as a deferred function to turn a panic(gobError) into a
+// plain error.  It overwrites the error return of the function that deferred its call.
+func catchError(err *error) {
+	if e := recover(); e != nil {
+		*err = e.(gobError).err // Will re-panic if not one of our errors, such as a runtime error.
+	}
+	return
+}
diff --git a/src/pkg/encoding/gob/gobencdec_test.go b/src/pkg/encoding/gob/gobencdec_test.go
new file mode 100644
index 0000000..83644c0
--- /dev/null
+++ b/src/pkg/encoding/gob/gobencdec_test.go
@@ -0,0 +1,575 @@
+// Copyright 20011 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 file contains tests of the GobEncoder/GobDecoder support.
+
+package gob
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"strings"
+	"testing"
+	"time"
+)
+
+// Types that implement the GobEncoder/Decoder interfaces.
+
+type ByteStruct struct {
+	a byte // not an exported field
+}
+
+type StringStruct struct {
+	s string // not an exported field
+}
+
+type ArrayStruct struct {
+	a [8192]byte // not an exported field
+}
+
+type Gobber int
+
+type ValueGobber string // encodes with a value, decodes with a pointer.
+
+// The relevant methods
+
+func (g *ByteStruct) GobEncode() ([]byte, error) {
+	b := make([]byte, 3)
+	b[0] = g.a
+	b[1] = g.a + 1
+	b[2] = g.a + 2
+	return b, nil
+}
+
+func (g *ByteStruct) GobDecode(data []byte) error {
+	if g == nil {
+		return errors.New("NIL RECEIVER")
+	}
+	// Expect N sequential-valued bytes.
+	if len(data) == 0 {
+		return io.EOF
+	}
+	g.a = data[0]
+	for i, c := range data {
+		if c != g.a+byte(i) {
+			return errors.New("invalid data sequence")
+		}
+	}
+	return nil
+}
+
+func (g *StringStruct) GobEncode() ([]byte, error) {
+	return []byte(g.s), nil
+}
+
+func (g *StringStruct) GobDecode(data []byte) error {
+	// Expect N sequential-valued bytes.
+	if len(data) == 0 {
+		return io.EOF
+	}
+	a := data[0]
+	for i, c := range data {
+		if c != a+byte(i) {
+			return errors.New("invalid data sequence")
+		}
+	}
+	g.s = string(data)
+	return nil
+}
+
+func (a *ArrayStruct) GobEncode() ([]byte, error) {
+	return a.a[:], nil
+}
+
+func (a *ArrayStruct) GobDecode(data []byte) error {
+	if len(data) != len(a.a) {
+		return errors.New("wrong length in array decode")
+	}
+	copy(a.a[:], data)
+	return nil
+}
+
+func (g *Gobber) GobEncode() ([]byte, error) {
+	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
+}
+
+func (g *Gobber) GobDecode(data []byte) error {
+	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
+	return err
+}
+
+func (v ValueGobber) GobEncode() ([]byte, error) {
+	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
+}
+
+func (v *ValueGobber) GobDecode(data []byte) error {
+	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
+	return err
+}
+
+// Structs that include GobEncodable fields.
+
+type GobTest0 struct {
+	X int // guarantee we have  something in common with GobTest*
+	G *ByteStruct
+}
+
+type GobTest1 struct {
+	X int // guarantee we have  something in common with GobTest*
+	G *StringStruct
+}
+
+type GobTest2 struct {
+	X int    // guarantee we have  something in common with GobTest*
+	G string // not a GobEncoder - should give us errors
+}
+
+type GobTest3 struct {
+	X int // guarantee we have  something in common with GobTest*
+	G *Gobber
+}
+
+type GobTest4 struct {
+	X int // guarantee we have  something in common with GobTest*
+	V ValueGobber
+}
+
+type GobTest5 struct {
+	X int // guarantee we have  something in common with GobTest*
+	V *ValueGobber
+}
+
+type GobTestIgnoreEncoder struct {
+	X int // guarantee we have  something in common with GobTest*
+}
+
+type GobTestValueEncDec struct {
+	X int          // guarantee we have  something in common with GobTest*
+	G StringStruct // not a pointer.
+}
+
+type GobTestIndirectEncDec struct {
+	X int             // guarantee we have  something in common with GobTest*
+	G ***StringStruct // indirections to the receiver.
+}
+
+type GobTestArrayEncDec struct {
+	X int         // guarantee we have  something in common with GobTest*
+	A ArrayStruct // not a pointer.
+}
+
+type GobTestIndirectArrayEncDec struct {
+	X int            // guarantee we have  something in common with GobTest*
+	A ***ArrayStruct // indirections to a large receiver.
+}
+
+func TestGobEncoderField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest0)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.G.a != 'A' {
+		t.Errorf("expected 'A' got %c", x.G.a)
+	}
+	// Now a field that's not a structure.
+	b.Reset()
+	gobber := Gobber(23)
+	err = enc.Encode(GobTest3{17, &gobber})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	y := new(GobTest3)
+	err = dec.Decode(y)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if *y.G != 23 {
+		t.Errorf("expected '23 got %d", *y.G)
+	}
+}
+
+// Even though the field is a value, we can still take its address
+// and should be able to call the methods.
+func TestGobEncoderValueField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestValueEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.G.s != "HIJKL" {
+		t.Errorf("expected `HIJKL` got %s", x.G.s)
+	}
+}
+
+// GobEncode/Decode should work even if the value is
+// more indirect than the receiver.
+func TestGobEncoderIndirectField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	s := &StringStruct{"HIJKL"}
+	sp := &s
+	err := enc.Encode(GobTestIndirectEncDec{17, &sp})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIndirectEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if (***x.G).s != "HIJKL" {
+		t.Errorf("expected `HIJKL` got %s", (***x.G).s)
+	}
+}
+
+// Test with a large field with methods.
+func TestGobEncoderArrayField(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	var a GobTestArrayEncDec
+	a.X = 17
+	for i := range a.A.a {
+		a.A.a[i] = byte(i)
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestArrayEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	for i, v := range x.A.a {
+		if v != byte(i) {
+			t.Errorf("expected %x got %x", byte(i), v)
+			break
+		}
+	}
+}
+
+// Test an indirection to a large field with methods.
+func TestGobEncoderIndirectArrayField(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	var a GobTestIndirectArrayEncDec
+	a.X = 17
+	var array ArrayStruct
+	ap := &array
+	app := &ap
+	a.A = &app
+	for i := range array.a {
+		array.a[i] = byte(i)
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIndirectArrayEncDec)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	for i, v := range (***x.A).a {
+		if v != byte(i) {
+			t.Errorf("expected %x got %x", byte(i), v)
+			break
+		}
+	}
+}
+
+// As long as the fields have the same name and implement the
+// interface, we can cross-connect them.  Not sure it's useful
+// and may even be bad but it works and it's hard to prevent
+// without exposing the contents of the object, which would
+// defeat the purpose.
+func TestGobEncoderFieldsOfDifferentType(t *testing.T) {
+	// first, string in field to byte in field
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest0)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.G.a != 'A' {
+		t.Errorf("expected 'A' got %c", x.G.a)
+	}
+	// now the other direction, byte in field to string in field
+	b.Reset()
+	err = enc.Encode(GobTest0{17, &ByteStruct{'X'}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	y := new(GobTest1)
+	err = dec.Decode(y)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if y.G.s != "XYZ" {
+		t.Fatalf("expected `XYZ` got %c", y.G.s)
+	}
+}
+
+// Test that we can encode a value and decode into a pointer.
+func TestGobEncoderValueEncoder(t *testing.T) {
+	// first, string in field to byte in field
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest4{17, ValueGobber("hello")})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest5)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if *x.V != "hello" {
+		t.Errorf("expected `hello` got %s", x.V)
+	}
+}
+
+func TestGobEncoderFieldTypeError(t *testing.T) {
+	// GobEncoder to non-decoder: error
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := &GobTest2{}
+	err = dec.Decode(x)
+	if err == nil {
+		t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
+	}
+	if strings.Index(err.Error(), "type") < 0 {
+		t.Fatal("expected type error; got", err)
+	}
+	// Non-encoder to GobDecoder: error
+	b.Reset()
+	err = enc.Encode(GobTest2{17, "ABC"})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	y := &GobTest1{}
+	err = dec.Decode(y)
+	if err == nil {
+		t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
+	}
+	if strings.Index(err.Error(), "type") < 0 {
+		t.Fatal("expected type error; got", err)
+	}
+}
+
+// Even though ByteStruct is a struct, it's treated as a singleton at the top level.
+func TestGobEncoderStructSingleton(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(&ByteStruct{'A'})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(ByteStruct)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.a != 'A' {
+		t.Errorf("expected 'A' got %c", x.a)
+	}
+}
+
+func TestGobEncoderNonStructSingleton(t *testing.T) {
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(Gobber(1234))
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	var x Gobber
+	err = dec.Decode(&x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x != 1234 {
+		t.Errorf("expected 1234 got %d", x)
+	}
+}
+
+func TestGobEncoderIgnoreStructField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIgnoreEncoder)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.X != 17 {
+		t.Errorf("expected 17 got %c", x.X)
+	}
+}
+
+func TestGobEncoderIgnoreNonStructField(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	gobber := Gobber(23)
+	err := enc.Encode(GobTest3{17, &gobber})
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTestIgnoreEncoder)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.X != 17 {
+		t.Errorf("expected 17 got %c", x.X)
+	}
+}
+
+func TestGobEncoderIgnoreNilEncoder(t *testing.T) {
+	b := new(bytes.Buffer)
+	// First a field that's a structure.
+	enc := NewEncoder(b)
+	err := enc.Encode(GobTest0{X: 18}) // G is nil
+	if err != nil {
+		t.Fatal("encode error:", err)
+	}
+	dec := NewDecoder(b)
+	x := new(GobTest0)
+	err = dec.Decode(x)
+	if err != nil {
+		t.Fatal("decode error:", err)
+	}
+	if x.X != 18 {
+		t.Errorf("expected x.X = 18, got %v", x.X)
+	}
+	if x.G != nil {
+		t.Errorf("expected x.G = nil, got %v", x.G)
+	}
+}
+
+type gobDecoderBug0 struct {
+	foo, bar string
+}
+
+func (br *gobDecoderBug0) String() string {
+	return br.foo + "-" + br.bar
+}
+
+func (br *gobDecoderBug0) GobEncode() ([]byte, error) {
+	return []byte(br.String()), nil
+}
+
+func (br *gobDecoderBug0) GobDecode(b []byte) error {
+	br.foo = "foo"
+	br.bar = "bar"
+	return nil
+}
+
+// This was a bug: the receiver has a different indirection level
+// than the variable.
+func TestGobEncoderExtraIndirect(t *testing.T) {
+	gdb := &gobDecoderBug0{"foo", "bar"}
+	buf := new(bytes.Buffer)
+	e := NewEncoder(buf)
+	if err := e.Encode(gdb); err != nil {
+		t.Fatalf("encode: %v", err)
+	}
+	d := NewDecoder(buf)
+	var got *gobDecoderBug0
+	if err := d.Decode(&got); err != nil {
+		t.Fatalf("decode: %v", err)
+	}
+	if got.foo != gdb.foo || got.bar != gdb.bar {
+		t.Errorf("got = %q, want %q", got, gdb)
+	}
+}
+
+// Another bug: this caused a crash with the new Go1 Time type.
+// We throw in a gob-encoding array, to test another case of isZero
+
+type isZeroBug struct {
+	T time.Time
+	S string
+	I int
+	A isZeroBugArray
+}
+
+type isZeroBugArray [2]uint8
+
+// Receiver is value, not pointer, to test isZero of array.
+func (a isZeroBugArray) GobEncode() (b []byte, e error) {
+	b = append(b, a[:]...)
+	return b, nil
+}
+
+func (a *isZeroBugArray) GobDecode(data []byte) error {
+	if len(data) != len(a) {
+		return io.EOF
+	}
+	a[0] = data[0]
+	a[1] = data[1]
+	return nil
+}
+
+func TestGobEncodeIsZero(t *testing.T) {
+	x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}}
+	b := new(bytes.Buffer)
+	enc := NewEncoder(b)
+	err := enc.Encode(x)
+	if err != nil {
+		t.Fatal("encode:", err)
+	}
+	var y isZeroBug
+	dec := NewDecoder(b)
+	err = dec.Decode(&y)
+	if err != nil {
+		t.Fatal("decode:", err)
+	}
+	if x != y {
+		t.Fatalf("%v != %v", x, y)
+	}
+}
diff --git a/src/pkg/encoding/gob/timing_test.go b/src/pkg/encoding/gob/timing_test.go
new file mode 100644
index 0000000..1017eb7
--- /dev/null
+++ b/src/pkg/encoding/gob/timing_test.go
@@ -0,0 +1,94 @@
+// Copyright 2011 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 gob
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"runtime"
+	"testing"
+)
+
+type Bench struct {
+	A int
+	B float64
+	C string
+	D []byte
+}
+
+func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) {
+	b.StopTimer()
+	enc := NewEncoder(w)
+	dec := NewDecoder(r)
+	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if enc.Encode(bench) != nil {
+			panic("encode error")
+		}
+		if dec.Decode(bench) != nil {
+			panic("decode error")
+		}
+	}
+}
+
+func BenchmarkEndToEndPipe(b *testing.B) {
+	r, w, err := os.Pipe()
+	if err != nil {
+		b.Fatal("can't get pipe:", err)
+	}
+	benchmarkEndToEnd(r, w, b)
+}
+
+func BenchmarkEndToEndByteBuffer(b *testing.B) {
+	var buf bytes.Buffer
+	benchmarkEndToEnd(&buf, &buf, b)
+}
+
+func TestCountEncodeMallocs(t *testing.T) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
+	runtime.UpdateMemStats()
+	mallocs := 0 - runtime.MemStats.Mallocs
+	const count = 1000
+	for i := 0; i < count; i++ {
+		err := enc.Encode(bench)
+		if err != nil {
+			t.Fatal("encode:", err)
+		}
+	}
+	runtime.UpdateMemStats()
+	mallocs += runtime.MemStats.Mallocs
+	fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count)
+}
+
+func TestCountDecodeMallocs(t *testing.T) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
+	const count = 1000
+	for i := 0; i < count; i++ {
+		err := enc.Encode(bench)
+		if err != nil {
+			t.Fatal("encode:", err)
+		}
+	}
+	dec := NewDecoder(&buf)
+	runtime.UpdateMemStats()
+	mallocs := 0 - runtime.MemStats.Mallocs
+	for i := 0; i < count; i++ {
+		*bench = Bench{}
+		err := dec.Decode(&bench)
+		if err != nil {
+			t.Fatal("decode:", err)
+		}
+	}
+	runtime.UpdateMemStats()
+	mallocs += runtime.MemStats.Mallocs
+	fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count)
+}
diff --git a/src/pkg/encoding/gob/type.go b/src/pkg/encoding/gob/type.go
new file mode 100644
index 0000000..71a28be
--- /dev/null
+++ b/src/pkg/encoding/gob/type.go
@@ -0,0 +1,789 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"reflect"
+	"sync"
+	"unicode"
+	"unicode/utf8"
+)
+
+// userTypeInfo stores the information associated with a type the user has handed
+// to the package.  It's computed once and stored in a map keyed by reflection
+// type.
+type userTypeInfo struct {
+	user         reflect.Type // the type the user handed us
+	base         reflect.Type // the base type after all indirections
+	indir        int          // number of indirections to reach the base type
+	isGobEncoder bool         // does the type implement GobEncoder?
+	isGobDecoder bool         // does the type implement GobDecoder?
+	encIndir     int8         // number of indirections to reach the receiver type; may be negative
+	decIndir     int8         // number of indirections to reach the receiver type; may be negative
+}
+
+var (
+	// Protected by an RWMutex because we read it a lot and write
+	// it only when we see a new type, typically when compiling.
+	userTypeLock  sync.RWMutex
+	userTypeCache = make(map[reflect.Type]*userTypeInfo)
+)
+
+// validType returns, and saves, the information associated with user-provided type rt.
+// If the user type is not valid, err will be non-nil.  To be used when the error handler
+// is not set up.
+func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) {
+	userTypeLock.RLock()
+	ut = userTypeCache[rt]
+	userTypeLock.RUnlock()
+	if ut != nil {
+		return
+	}
+	// Now set the value under the write lock.
+	userTypeLock.Lock()
+	defer userTypeLock.Unlock()
+	if ut = userTypeCache[rt]; ut != nil {
+		// Lost the race; not a problem.
+		return
+	}
+	ut = new(userTypeInfo)
+	ut.base = rt
+	ut.user = rt
+	// A type that is just a cycle of pointers (such as type T *T) cannot
+	// be represented in gobs, which need some concrete data.  We use a
+	// cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6,
+	// pp 539-540.  As we step through indirections, run another type at
+	// half speed. If they meet up, there's a cycle.
+	slowpoke := ut.base // walks half as fast as ut.base
+	for {
+		pt := ut.base
+		if pt.Kind() != reflect.Ptr {
+			break
+		}
+		ut.base = pt.Elem()
+		if ut.base == slowpoke { // ut.base lapped slowpoke
+			// recursive pointer type.
+			return nil, errors.New("can't represent recursive pointer type " + ut.base.String())
+		}
+		if ut.indir%2 == 0 {
+			slowpoke = slowpoke.Elem()
+		}
+		ut.indir++
+	}
+	ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType)
+	ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType)
+	userTypeCache[rt] = ut
+	return
+}
+
+var (
+	gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem()
+	gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem()
+)
+
+// implementsInterface reports whether the type implements the
+// gobEncoder/gobDecoder interface.
+// It also returns the number of indirections required to get to the
+// implementation.
+func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) {
+	if typ == nil {
+		return
+	}
+	rt := typ
+	// The type might be a pointer and we need to keep
+	// dereferencing to the base type until we find an implementation.
+	for {
+		if rt.Implements(gobEncDecType) {
+			return true, indir
+		}
+		if p := rt; p.Kind() == reflect.Ptr {
+			indir++
+			if indir > 100 { // insane number of indirections
+				return false, 0
+			}
+			rt = p.Elem()
+			continue
+		}
+		break
+	}
+	// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
+	if typ.Kind() != reflect.Ptr {
+		// Not a pointer, but does the pointer work?
+		if reflect.PtrTo(typ).Implements(gobEncDecType) {
+			return true, -1
+		}
+	}
+	return false, 0
+}
+
+// userType returns, and saves, the information associated with user-provided type rt.
+// If the user type is not valid, it calls error.
+func userType(rt reflect.Type) *userTypeInfo {
+	ut, err := validUserType(rt)
+	if err != nil {
+		error_(err)
+	}
+	return ut
+}
+
+// A typeId represents a gob Type as an integer that can be passed on the wire.
+// Internally, typeIds are used as keys to a map to recover the underlying type info.
+type typeId int32
+
+var nextId typeId       // incremented for each new type we build
+var typeLock sync.Mutex // set while building a type
+const firstUserId = 64  // lowest id number granted to user
+
+type gobType interface {
+	id() typeId
+	setId(id typeId)
+	name() string
+	string() string // not public; only for debugging
+	safeString(seen map[typeId]bool) string
+}
+
+var types = make(map[reflect.Type]gobType)
+var idToType = make(map[typeId]gobType)
+var builtinIdToType map[typeId]gobType // set in init() after builtins are established
+
+func setTypeId(typ gobType) {
+	nextId++
+	typ.setId(nextId)
+	idToType[nextId] = typ
+}
+
+func (t typeId) gobType() gobType {
+	if t == 0 {
+		return nil
+	}
+	return idToType[t]
+}
+
+// string returns the string representation of the type associated with the typeId.
+func (t typeId) string() string {
+	if t.gobType() == nil {
+		return "<nil>"
+	}
+	return t.gobType().string()
+}
+
+// Name returns the name of the type associated with the typeId.
+func (t typeId) name() string {
+	if t.gobType() == nil {
+		return "<nil>"
+	}
+	return t.gobType().name()
+}
+
+// Common elements of all types.
+type CommonType struct {
+	Name string
+	Id   typeId
+}
+
+func (t *CommonType) id() typeId { return t.Id }
+
+func (t *CommonType) setId(id typeId) { t.Id = id }
+
+func (t *CommonType) string() string { return t.Name }
+
+func (t *CommonType) safeString(seen map[typeId]bool) string {
+	return t.Name
+}
+
+func (t *CommonType) name() string { return t.Name }
+
+// Create and check predefined types
+// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
+
+var (
+	// Primordial types, needed during initialization.
+	// Always passed as pointers so the interface{} type
+	// goes through without losing its interfaceness.
+	tBool      = bootstrapType("bool", (*bool)(nil), 1)
+	tInt       = bootstrapType("int", (*int)(nil), 2)
+	tUint      = bootstrapType("uint", (*uint)(nil), 3)
+	tFloat     = bootstrapType("float", (*float64)(nil), 4)
+	tBytes     = bootstrapType("bytes", (*[]byte)(nil), 5)
+	tString    = bootstrapType("string", (*string)(nil), 6)
+	tComplex   = bootstrapType("complex", (*complex128)(nil), 7)
+	tInterface = bootstrapType("interface", (*interface{})(nil), 8)
+	// Reserve some Ids for compatible expansion
+	tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9)
+	tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10)
+	tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11)
+	tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12)
+	tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13)
+	tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14)
+	tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15)
+)
+
+// Predefined because it's needed by the Decoder
+var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
+var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType)
+
+func init() {
+	// Some magic numbers to make sure there are no surprises.
+	checkId(16, tWireType)
+	checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
+	checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
+	checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
+	checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
+	checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
+	checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)
+
+	builtinIdToType = make(map[typeId]gobType)
+	for k, v := range idToType {
+		builtinIdToType[k] = v
+	}
+
+	// Move the id space upwards to allow for growth in the predefined world
+	// without breaking existing files.
+	if nextId > firstUserId {
+		panic(fmt.Sprintln("nextId too large:", nextId))
+	}
+	nextId = firstUserId
+	registerBasics()
+	wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
+}
+
+// Array type
+type arrayType struct {
+	CommonType
+	Elem typeId
+	Len  int
+}
+
+func newArrayType(name string) *arrayType {
+	a := &arrayType{CommonType{Name: name}, 0, 0}
+	return a
+}
+
+func (a *arrayType) init(elem gobType, len int) {
+	// Set our type id before evaluating the element's, in case it's our own.
+	setTypeId(a)
+	a.Elem = elem.id()
+	a.Len = len
+}
+
+func (a *arrayType) safeString(seen map[typeId]bool) string {
+	if seen[a.Id] {
+		return a.Name
+	}
+	seen[a.Id] = true
+	return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen))
+}
+
+func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) }
+
+// GobEncoder type (something that implements the GobEncoder interface)
+type gobEncoderType struct {
+	CommonType
+}
+
+func newGobEncoderType(name string) *gobEncoderType {
+	g := &gobEncoderType{CommonType{Name: name}}
+	setTypeId(g)
+	return g
+}
+
+func (g *gobEncoderType) safeString(seen map[typeId]bool) string {
+	return g.Name
+}
+
+func (g *gobEncoderType) string() string { return g.Name }
+
+// Map type
+type mapType struct {
+	CommonType
+	Key  typeId
+	Elem typeId
+}
+
+func newMapType(name string) *mapType {
+	m := &mapType{CommonType{Name: name}, 0, 0}
+	return m
+}
+
+func (m *mapType) init(key, elem gobType) {
+	// Set our type id before evaluating the element's, in case it's our own.
+	setTypeId(m)
+	m.Key = key.id()
+	m.Elem = elem.id()
+}
+
+func (m *mapType) safeString(seen map[typeId]bool) string {
+	if seen[m.Id] {
+		return m.Name
+	}
+	seen[m.Id] = true
+	key := m.Key.gobType().safeString(seen)
+	elem := m.Elem.gobType().safeString(seen)
+	return fmt.Sprintf("map[%s]%s", key, elem)
+}
+
+func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) }
+
+// Slice type
+type sliceType struct {
+	CommonType
+	Elem typeId
+}
+
+func newSliceType(name string) *sliceType {
+	s := &sliceType{CommonType{Name: name}, 0}
+	return s
+}
+
+func (s *sliceType) init(elem gobType) {
+	// Set our type id before evaluating the element's, in case it's our own.
+	setTypeId(s)
+	s.Elem = elem.id()
+}
+
+func (s *sliceType) safeString(seen map[typeId]bool) string {
+	if seen[s.Id] {
+		return s.Name
+	}
+	seen[s.Id] = true
+	return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen))
+}
+
+func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) }
+
+// Struct type
+type fieldType struct {
+	Name string
+	Id   typeId
+}
+
+type structType struct {
+	CommonType
+	Field []*fieldType
+}
+
+func (s *structType) safeString(seen map[typeId]bool) string {
+	if s == nil {
+		return "<nil>"
+	}
+	if _, ok := seen[s.Id]; ok {
+		return s.Name
+	}
+	seen[s.Id] = true
+	str := s.Name + " = struct { "
+	for _, f := range s.Field {
+		str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
+	}
+	str += "}"
+	return str
+}
+
+func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }
+
+func newStructType(name string) *structType {
+	s := &structType{CommonType{Name: name}, nil}
+	// For historical reasons we set the id here rather than init.
+	// See the comment in newTypeObject for details.
+	setTypeId(s)
+	return s
+}
+
+// newTypeObject allocates a gobType for the reflection type rt.
+// Unless ut represents a GobEncoder, rt should be the base type
+// of ut.
+// This is only called from the encoding side. The decoding side
+// works through typeIds and userTypeInfos alone.
+func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
+	// Does this type implement GobEncoder?
+	if ut.isGobEncoder {
+		return newGobEncoderType(name), nil
+	}
+	var err error
+	var type0, type1 gobType
+	defer func() {
+		if err != nil {
+			delete(types, rt)
+		}
+	}()
+	// Install the top-level type before the subtypes (e.g. struct before
+	// fields) so recursive types can be constructed safely.
+	switch t := rt; t.Kind() {
+	// All basic types are easy: they are predefined.
+	case reflect.Bool:
+		return tBool.gobType(), nil
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return tInt.gobType(), nil
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return tUint.gobType(), nil
+
+	case reflect.Float32, reflect.Float64:
+		return tFloat.gobType(), nil
+
+	case reflect.Complex64, reflect.Complex128:
+		return tComplex.gobType(), nil
+
+	case reflect.String:
+		return tString.gobType(), nil
+
+	case reflect.Interface:
+		return tInterface.gobType(), nil
+
+	case reflect.Array:
+		at := newArrayType(name)
+		types[rt] = at
+		type0, err = getBaseType("", t.Elem())
+		if err != nil {
+			return nil, err
+		}
+		// Historical aside:
+		// For arrays, maps, and slices, we set the type id after the elements
+		// are constructed. This is to retain the order of type id allocation after
+		// a fix made to handle recursive types, which changed the order in
+		// which types are built.  Delaying the setting in this way preserves
+		// type ids while allowing recursive types to be described. Structs,
+		// done below, were already handling recursion correctly so they
+		// assign the top-level id before those of the field.
+		at.init(type0, t.Len())
+		return at, nil
+
+	case reflect.Map:
+		mt := newMapType(name)
+		types[rt] = mt
+		type0, err = getBaseType("", t.Key())
+		if err != nil {
+			return nil, err
+		}
+		type1, err = getBaseType("", t.Elem())
+		if err != nil {
+			return nil, err
+		}
+		mt.init(type0, type1)
+		return mt, nil
+
+	case reflect.Slice:
+		// []byte == []uint8 is a special case
+		if t.Elem().Kind() == reflect.Uint8 {
+			return tBytes.gobType(), nil
+		}
+		st := newSliceType(name)
+		types[rt] = st
+		type0, err = getBaseType(t.Elem().Name(), t.Elem())
+		if err != nil {
+			return nil, err
+		}
+		st.init(type0)
+		return st, nil
+
+	case reflect.Struct:
+		st := newStructType(name)
+		types[rt] = st
+		idToType[st.id()] = st
+		for i := 0; i < t.NumField(); i++ {
+			f := t.Field(i)
+			if !isExported(f.Name) {
+				continue
+			}
+			typ := userType(f.Type).base
+			tname := typ.Name()
+			if tname == "" {
+				t := userType(f.Type).base
+				tname = t.String()
+			}
+			gt, err := getBaseType(tname, f.Type)
+			if err != nil {
+				return nil, err
+			}
+			st.Field = append(st.Field, &fieldType{f.Name, gt.id()})
+		}
+		return st, nil
+
+	default:
+		return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String())
+	}
+	return nil, nil
+}
+
+// isExported reports whether this is an exported - upper case - name.
+func isExported(name string) bool {
+	rune, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(rune)
+}
+
+// getBaseType returns the Gob type describing the given reflect.Type's base type.
+// typeLock must be held.
+func getBaseType(name string, rt reflect.Type) (gobType, error) {
+	ut := userType(rt)
+	return getType(name, ut, ut.base)
+}
+
+// getType returns the Gob type describing the given reflect.Type.
+// Should be called only when handling GobEncoders/Decoders,
+// which may be pointers.  All other types are handled through the
+// base type, never a pointer.
+// typeLock must be held.
+func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
+	typ, present := types[rt]
+	if present {
+		return typ, nil
+	}
+	typ, err := newTypeObject(name, ut, rt)
+	if err == nil {
+		types[rt] = typ
+	}
+	return typ, err
+}
+
+func checkId(want, got typeId) {
+	if want != got {
+		fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want))
+		panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string())
+	}
+}
+
+// used for building the basic types; called only from init().  the incoming
+// interface always refers to a pointer.
+func bootstrapType(name string, e interface{}, expect typeId) typeId {
+	rt := reflect.TypeOf(e).Elem()
+	_, present := types[rt]
+	if present {
+		panic("bootstrap type already present: " + name + ", " + rt.String())
+	}
+	typ := &CommonType{Name: name}
+	types[rt] = typ
+	setTypeId(typ)
+	checkId(expect, nextId)
+	userType(rt) // might as well cache it now
+	return nextId
+}
+
+// Representation of the information we send and receive about this type.
+// Each value we send is preceded by its type definition: an encoded int.
+// However, the very first time we send the value, we first send the pair
+// (-id, wireType).
+// For bootstrapping purposes, we assume that the recipient knows how
+// to decode a wireType; it is exactly the wireType struct here, interpreted
+// using the gob rules for sending a structure, except that we assume the
+// ids for wireType and structType etc. are known.  The relevant pieces
+// are built in encode.go's init() function.
+// To maintain binary compatibility, if you extend this type, always put
+// the new fields last.
+type wireType struct {
+	ArrayT      *arrayType
+	SliceT      *sliceType
+	StructT     *structType
+	MapT        *mapType
+	GobEncoderT *gobEncoderType
+}
+
+func (w *wireType) string() string {
+	const unknown = "unknown type"
+	if w == nil {
+		return unknown
+	}
+	switch {
+	case w.ArrayT != nil:
+		return w.ArrayT.Name
+	case w.SliceT != nil:
+		return w.SliceT.Name
+	case w.StructT != nil:
+		return w.StructT.Name
+	case w.MapT != nil:
+		return w.MapT.Name
+	case w.GobEncoderT != nil:
+		return w.GobEncoderT.Name
+	}
+	return unknown
+}
+
+type typeInfo struct {
+	id      typeId
+	encoder *encEngine
+	wire    *wireType
+}
+
+var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock
+
+// typeLock must be held.
+func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
+	rt := ut.base
+	if ut.isGobEncoder {
+		// We want the user type, not the base type.
+		rt = ut.user
+	}
+	info, ok := typeInfoMap[rt]
+	if ok {
+		return info, nil
+	}
+	info = new(typeInfo)
+	gt, err := getBaseType(rt.Name(), rt)
+	if err != nil {
+		return nil, err
+	}
+	info.id = gt.id()
+
+	if ut.isGobEncoder {
+		userType, err := getType(rt.Name(), ut, rt)
+		if err != nil {
+			return nil, err
+		}
+		info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)}
+		typeInfoMap[ut.user] = info
+		return info, nil
+	}
+
+	t := info.id.gobType()
+	switch typ := rt; typ.Kind() {
+	case reflect.Array:
+		info.wire = &wireType{ArrayT: t.(*arrayType)}
+	case reflect.Map:
+		info.wire = &wireType{MapT: t.(*mapType)}
+	case reflect.Slice:
+		// []byte == []uint8 is a special case handled separately
+		if typ.Elem().Kind() != reflect.Uint8 {
+			info.wire = &wireType{SliceT: t.(*sliceType)}
+		}
+	case reflect.Struct:
+		info.wire = &wireType{StructT: t.(*structType)}
+	}
+	typeInfoMap[rt] = info
+	return info, nil
+}
+
+// Called only when a panic is acceptable and unexpected.
+func mustGetTypeInfo(rt reflect.Type) *typeInfo {
+	t, err := getTypeInfo(userType(rt))
+	if err != nil {
+		panic("getTypeInfo: " + err.Error())
+	}
+	return t
+}
+
+// GobEncoder is the interface describing data that provides its own
+// representation for encoding values for transmission to a GobDecoder.
+// A type that implements GobEncoder and GobDecoder has complete
+// control over the representation of its data and may therefore
+// contain things such as private fields, channels, and functions,
+// which are not usually transmissible in gob streams.
+//
+// Note: Since gobs can be stored permanently, It is good design
+// to guarantee the encoding used by a GobEncoder is stable as the
+// software evolves.  For instance, it might make sense for GobEncode
+// to include a version number in the encoding.
+type GobEncoder interface {
+	// GobEncode returns a byte slice representing the encoding of the
+	// receiver for transmission to a GobDecoder, usually of the same
+	// concrete type.
+	GobEncode() ([]byte, error)
+}
+
+// GobDecoder is the interface describing data that provides its own
+// routine for decoding transmitted values sent by a GobEncoder.
+type GobDecoder interface {
+	// GobDecode overwrites the receiver, which must be a pointer,
+	// with the value represented by the byte slice, which was written
+	// by GobEncode, usually for the same concrete type.
+	GobDecode([]byte) error
+}
+
+var (
+	nameToConcreteType = make(map[string]reflect.Type)
+	concreteTypeToName = make(map[reflect.Type]string)
+)
+
+// RegisterName is like Register but uses the provided name rather than the
+// type's default.
+func RegisterName(name string, value interface{}) {
+	if name == "" {
+		// reserved for nil
+		panic("attempt to register empty name")
+	}
+	ut := userType(reflect.TypeOf(value))
+	// Check for incompatible duplicates. The name must refer to the
+	// same user type, and vice versa.
+	if t, ok := nameToConcreteType[name]; ok && t != ut.user {
+		panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user))
+	}
+	if n, ok := concreteTypeToName[ut.base]; ok && n != name {
+		panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name))
+	}
+	// Store the name and type provided by the user....
+	nameToConcreteType[name] = reflect.TypeOf(value)
+	// but the flattened type in the type table, since that's what decode needs.
+	concreteTypeToName[ut.base] = name
+}
+
+// Register records a type, identified by a value for that type, under its
+// internal type name.  That name will identify the concrete type of a value
+// sent or received as an interface variable.  Only types that will be
+// transferred as implementations of interface values need to be registered.
+// Expecting to be used only during initialization, it panics if the mapping
+// between types and names is not a bijection.
+func Register(value interface{}) {
+	// Default to printed representation for unnamed types
+	rt := reflect.TypeOf(value)
+	name := rt.String()
+
+	// But for named types (or pointers to them), qualify with import path.
+	// Dereference one pointer looking for a named type.
+	star := ""
+	if rt.Name() == "" {
+		if pt := rt; pt.Kind() == reflect.Ptr {
+			star = "*"
+			rt = pt
+		}
+	}
+	if rt.Name() != "" {
+		if rt.PkgPath() == "" {
+			name = star + rt.Name()
+		} else {
+			name = star + rt.PkgPath() + "." + rt.Name()
+		}
+	}
+
+	RegisterName(name, value)
+}
+
+func registerBasics() {
+	Register(int(0))
+	Register(int8(0))
+	Register(int16(0))
+	Register(int32(0))
+	Register(int64(0))
+	Register(uint(0))
+	Register(uint8(0))
+	Register(uint16(0))
+	Register(uint32(0))
+	Register(uint64(0))
+	Register(float32(0))
+	Register(float64(0))
+	Register(complex64(0i))
+	Register(complex128(0i))
+	Register(uintptr(0))
+	Register(false)
+	Register("")
+	Register([]byte(nil))
+	Register([]int(nil))
+	Register([]int8(nil))
+	Register([]int16(nil))
+	Register([]int32(nil))
+	Register([]int64(nil))
+	Register([]uint(nil))
+	Register([]uint8(nil))
+	Register([]uint16(nil))
+	Register([]uint32(nil))
+	Register([]uint64(nil))
+	Register([]float32(nil))
+	Register([]float64(nil))
+	Register([]complex64(nil))
+	Register([]complex128(nil))
+	Register([]uintptr(nil))
+	Register([]bool(nil))
+	Register([]string(nil))
+}
diff --git a/src/pkg/encoding/gob/type_test.go b/src/pkg/encoding/gob/type_test.go
new file mode 100644
index 0000000..42bdb4c
--- /dev/null
+++ b/src/pkg/encoding/gob/type_test.go
@@ -0,0 +1,161 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob
+
+import (
+	"reflect"
+	"testing"
+)
+
+type typeT struct {
+	id  typeId
+	str string
+}
+
+var basicTypes = []typeT{
+	{tBool, "bool"},
+	{tInt, "int"},
+	{tUint, "uint"},
+	{tFloat, "float"},
+	{tBytes, "bytes"},
+	{tString, "string"},
+}
+
+func getTypeUnlocked(name string, rt reflect.Type) gobType {
+	typeLock.Lock()
+	defer typeLock.Unlock()
+	t, err := getBaseType(name, rt)
+	if err != nil {
+		panic("getTypeUnlocked: " + err.Error())
+	}
+	return t
+}
+
+// Sanity checks
+func TestBasic(t *testing.T) {
+	for _, tt := range basicTypes {
+		if tt.id.string() != tt.str {
+			t.Errorf("checkType: expected %q got %s", tt.str, tt.id.string())
+		}
+		if tt.id == 0 {
+			t.Errorf("id for %q is zero", tt.str)
+		}
+	}
+}
+
+// Reregister some basic types to check registration is idempotent.
+func TestReregistration(t *testing.T) {
+	newtyp := getTypeUnlocked("int", reflect.TypeOf(int(0)))
+	if newtyp != tInt.gobType() {
+		t.Errorf("reregistration of %s got new type", newtyp.string())
+	}
+	newtyp = getTypeUnlocked("uint", reflect.TypeOf(uint(0)))
+	if newtyp != tUint.gobType() {
+		t.Errorf("reregistration of %s got new type", newtyp.string())
+	}
+	newtyp = getTypeUnlocked("string", reflect.TypeOf("hello"))
+	if newtyp != tString.gobType() {
+		t.Errorf("reregistration of %s got new type", newtyp.string())
+	}
+}
+
+func TestArrayType(t *testing.T) {
+	var a3 [3]int
+	a3int := getTypeUnlocked("foo", reflect.TypeOf(a3))
+	newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3))
+	if a3int != newa3int {
+		t.Errorf("second registration of [3]int creates new type")
+	}
+	var a4 [4]int
+	a4int := getTypeUnlocked("goo", reflect.TypeOf(a4))
+	if a3int == a4int {
+		t.Errorf("registration of [3]int creates same type as [4]int")
+	}
+	var b3 [3]bool
+	a3bool := getTypeUnlocked("", reflect.TypeOf(b3))
+	if a3int == a3bool {
+		t.Errorf("registration of [3]bool creates same type as [3]int")
+	}
+	str := a3bool.string()
+	expected := "[3]bool"
+	if str != expected {
+		t.Errorf("array printed as %q; expected %q", str, expected)
+	}
+}
+
+func TestSliceType(t *testing.T) {
+	var s []int
+	sint := getTypeUnlocked("slice", reflect.TypeOf(s))
+	var news []int
+	newsint := getTypeUnlocked("slice1", reflect.TypeOf(news))
+	if sint != newsint {
+		t.Errorf("second registration of []int creates new type")
+	}
+	var b []bool
+	sbool := getTypeUnlocked("", reflect.TypeOf(b))
+	if sbool == sint {
+		t.Errorf("registration of []bool creates same type as []int")
+	}
+	str := sbool.string()
+	expected := "[]bool"
+	if str != expected {
+		t.Errorf("slice printed as %q; expected %q", str, expected)
+	}
+}
+
+func TestMapType(t *testing.T) {
+	var m map[string]int
+	mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m))
+	var newm map[string]int
+	newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm))
+	if mapStringInt != newMapStringInt {
+		t.Errorf("second registration of map[string]int creates new type")
+	}
+	var b map[string]bool
+	mapStringBool := getTypeUnlocked("", reflect.TypeOf(b))
+	if mapStringBool == mapStringInt {
+		t.Errorf("registration of map[string]bool creates same type as map[string]int")
+	}
+	str := mapStringBool.string()
+	expected := "map[string]bool"
+	if str != expected {
+		t.Errorf("map printed as %q; expected %q", str, expected)
+	}
+}
+
+type Bar struct {
+	X string
+}
+
+// This structure has pointers and refers to itself, making it a good test case.
+type Foo struct {
+	A int
+	B int32 // will become int
+	C string
+	D []byte
+	E *float64    // will become float64
+	F ****float64 // will become float64
+	G *Bar
+	H *Bar // should not interpolate the definition of Bar again
+	I *Foo // will not explode
+}
+
+func TestStructType(t *testing.T) {
+	sstruct := getTypeUnlocked("Foo", reflect.TypeOf(Foo{}))
+	str := sstruct.string()
+	// If we can print it correctly, we built it correctly.
+	expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }"
+	if str != expected {
+		t.Errorf("struct printed as %q; expected %q", str, expected)
+	}
+}
+
+// Should be OK to register the same type multiple times, as long as they're
+// at the same level of indirection.
+func TestRegistration(t *testing.T) {
+	type T struct{ a int }
+	Register(new(T))
+	Register(new(T))
+}
diff --git a/src/pkg/encoding/hex/hex.go b/src/pkg/encoding/hex/hex.go
index e7ea8b0..eb7e7ca 100644
--- a/src/pkg/encoding/hex/hex.go
+++ b/src/pkg/encoding/hex/hex.go
@@ -8,7 +8,6 @@ package hex
 import (
 	"bytes"
 	"io"
-	"os"
 	"strconv"
 )
 
@@ -33,12 +32,12 @@ func Encode(dst, src []byte) int {
 // OddLengthInputError results from decoding an odd length slice.
 type OddLengthInputError struct{}
 
-func (OddLengthInputError) String() string { return "odd length hex string" }
+func (OddLengthInputError) Error() string { return "odd length hex string" }
 
 // InvalidHexCharError results from finding an invalid character in a hex string.
 type InvalidHexCharError byte
 
-func (e InvalidHexCharError) String() string {
+func (e InvalidHexCharError) Error() string {
 	return "invalid hex char: " + strconv.Itoa(int(e))
 }
 
@@ -49,7 +48,7 @@ func DecodedLen(x int) int { return x / 2 }
 //
 // If Decode encounters invalid input, it returns an OddLengthInputError or an
 // InvalidHexCharError.
-func Decode(dst, src []byte) (int, os.Error) {
+func Decode(dst, src []byte) (int, error) {
 	if len(src)%2 == 1 {
 		return 0, OddLengthInputError{}
 	}
@@ -91,7 +90,7 @@ func EncodeToString(src []byte) string {
 }
 
 // DecodeString returns the bytes represented by the hexadecimal string s.
-func DecodeString(s string) ([]byte, os.Error) {
+func DecodeString(s string) ([]byte, error) {
 	src := []byte(s)
 	dst := make([]byte, DecodedLen(len(src)))
 	_, err := Decode(dst, src)
@@ -133,7 +132,7 @@ func toChar(b byte) byte {
 	return b
 }
 
-func (h *dumper) Write(data []byte) (n int, err os.Error) {
+func (h *dumper) Write(data []byte) (n int, err error) {
 	// Output lines look like:
 	// 00000010  2e 2f 30 31 32 33 34 35  36 37 38 39 3a 3b 3c 3d  |./0123456789:;<=|
 	// ^ offset                          ^ extra space              ^ ASCII of line.
@@ -185,7 +184,7 @@ func (h *dumper) Write(data []byte) (n int, err os.Error) {
 	return
 }
 
-func (h *dumper) Close() (err os.Error) {
+func (h *dumper) Close() (err error) {
 	// See the comments in Write() for the details of this format.
 	if h.used == 0 {
 		return
diff --git a/src/pkg/encoding/json/Makefile b/src/pkg/encoding/json/Makefile
new file mode 100644
index 0000000..37223e7
--- /dev/null
+++ b/src/pkg/encoding/json/Makefile
@@ -0,0 +1,16 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=encoding/json
+GOFILES=\
+	decode.go\
+	encode.go\
+	indent.go\
+	scanner.go\
+	stream.go\
+	tags.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/encoding/json/bench_test.go b/src/pkg/encoding/json/bench_test.go
new file mode 100644
index 0000000..333c1c0
--- /dev/null
+++ b/src/pkg/encoding/json/bench_test.go
@@ -0,0 +1,157 @@
+// Copyright 2011 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.
+
+// Large data benchmark.
+// The JSON data is a summary of agl's changes in the
+// go, webkit, and chromium open source projects.
+// We benchmark converting between the JSON form
+// and in-memory data structures.
+
+package json
+
+import (
+	"bytes"
+	"compress/gzip"
+	"io/ioutil"
+	"os"
+	"testing"
+)
+
+type codeResponse struct {
+	Tree     *codeNode `json:"tree"`
+	Username string    `json:"username"`
+}
+
+type codeNode struct {
+	Name     string      `json:"name"`
+	Kids     []*codeNode `json:"kids"`
+	CLWeight float64     `json:"cl_weight"`
+	Touches  int         `json:"touches"`
+	MinT     int64       `json:"min_t"`
+	MaxT     int64       `json:"max_t"`
+	MeanT    int64       `json:"mean_t"`
+}
+
+var codeJSON []byte
+var codeStruct codeResponse
+
+func codeInit() {
+	f, err := os.Open("testdata/code.json.gz")
+	if err != nil {
+		panic(err)
+	}
+	defer f.Close()
+	gz, err := gzip.NewReader(f)
+	if err != nil {
+		panic(err)
+	}
+	data, err := ioutil.ReadAll(gz)
+	if err != nil {
+		panic(err)
+	}
+
+	codeJSON = data
+
+	if err := Unmarshal(codeJSON, &codeStruct); err != nil {
+		panic("unmarshal code.json: " + err.Error())
+	}
+
+	if data, err = Marshal(&codeStruct); err != nil {
+		panic("marshal code.json: " + err.Error())
+	}
+
+	if !bytes.Equal(data, codeJSON) {
+		println("different lengths", len(data), len(codeJSON))
+		for i := 0; i < len(data) && i < len(codeJSON); i++ {
+			if data[i] != codeJSON[i] {
+				println("re-marshal: changed at byte", i)
+				println("orig: ", string(codeJSON[i-10:i+10]))
+				println("new: ", string(data[i-10:i+10]))
+				break
+			}
+		}
+		panic("re-marshal code.json: different result")
+	}
+}
+
+func BenchmarkCodeEncoder(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	enc := NewEncoder(ioutil.Discard)
+	for i := 0; i < b.N; i++ {
+		if err := enc.Encode(&codeStruct); err != nil {
+			b.Fatal("Encode:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeMarshal(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	for i := 0; i < b.N; i++ {
+		if _, err := Marshal(&codeStruct); err != nil {
+			b.Fatal("Marshal:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeDecoder(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	var buf bytes.Buffer
+	dec := NewDecoder(&buf)
+	var r codeResponse
+	for i := 0; i < b.N; i++ {
+		buf.Write(codeJSON)
+		// hide EOF
+		buf.WriteByte('\n')
+		buf.WriteByte('\n')
+		buf.WriteByte('\n')
+		if err := dec.Decode(&r); err != nil {
+			b.Fatal("Decode:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeUnmarshal(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	for i := 0; i < b.N; i++ {
+		var r codeResponse
+		if err := Unmarshal(codeJSON, &r); err != nil {
+			b.Fatal("Unmmarshal:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeUnmarshalReuse(b *testing.B) {
+	if codeJSON == nil {
+		b.StopTimer()
+		codeInit()
+		b.StartTimer()
+	}
+	var r codeResponse
+	for i := 0; i < b.N; i++ {
+		if err := Unmarshal(codeJSON, &r); err != nil {
+			b.Fatal("Unmmarshal:", err)
+		}
+	}
+	b.SetBytes(int64(len(codeJSON)))
+}
diff --git a/src/pkg/encoding/json/decode.go b/src/pkg/encoding/json/decode.go
new file mode 100644
index 0000000..87076b5
--- /dev/null
+++ b/src/pkg/encoding/json/decode.go
@@ -0,0 +1,965 @@
+// Copyright 2010 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.
+
+// Represents JSON data structure using native Go types: booleans, floats,
+// strings, arrays, and maps.
+
+package json
+
+import (
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"reflect"
+	"runtime"
+	"strconv"
+	"strings"
+	"unicode"
+	"unicode/utf16"
+	"unicode/utf8"
+)
+
+// Unmarshal parses the JSON-encoded data and stores the result
+// in the value pointed to by v.
+//
+// Unmarshal uses the inverse of the encodings that
+// Marshal uses, allocating maps, slices, and pointers as necessary,
+// with the following additional rules:
+//
+// To unmarshal JSON into a pointer, Unmarshal first handles the case of
+// the JSON being the JSON literal null.  In that case, Unmarshal sets
+// the pointer to nil.  Otherwise, Unmarshal unmarshals the JSON into
+// the value pointed at by the pointer.  If the pointer is nil, Unmarshal
+// allocates a new value for it to point to.
+//
+// To unmarshal JSON into an interface value, Unmarshal unmarshals
+// the JSON into the concrete value contained in the interface value.
+// If the interface value is nil, that is, has no concrete value stored in it,
+// Unmarshal stores one of these in the interface value:
+//
+//	bool, for JSON booleans
+//	float64, for JSON numbers
+//	string, for JSON strings
+//	[]interface{}, for JSON arrays
+//	map[string]interface{}, for JSON objects
+//	nil for JSON null
+//
+// If a JSON value is not appropriate for a given target type,
+// or if a JSON number overflows the target type, Unmarshal
+// skips that field and completes the unmarshalling as best it can.
+// If no more serious errors are encountered, Unmarshal returns
+// an UnmarshalTypeError describing the earliest such error.
+//
+func Unmarshal(data []byte, v interface{}) error {
+	d := new(decodeState).init(data)
+
+	// Quick check for well-formedness.
+	// Avoids filling out half a data structure
+	// before discovering a JSON syntax error.
+	err := checkValid(data, &d.scan)
+	if err != nil {
+		return err
+	}
+
+	return d.unmarshal(v)
+}
+
+// Unmarshaler is the interface implemented by objects
+// that can unmarshal a JSON description of themselves.
+// The input can be assumed to be a valid JSON object
+// encoding.  UnmarshalJSON must copy the JSON data
+// if it wishes to retain the data after returning.
+type Unmarshaler interface {
+	UnmarshalJSON([]byte) error
+}
+
+// An UnmarshalTypeError describes a JSON value that was
+// not appropriate for a value of a specific Go type.
+type UnmarshalTypeError struct {
+	Value string       // description of JSON value - "bool", "array", "number -5"
+	Type  reflect.Type // type of Go value it could not be assigned to
+}
+
+func (e *UnmarshalTypeError) Error() string {
+	return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
+}
+
+// An UnmarshalFieldError describes a JSON object key that
+// led to an unexported (and therefore unwritable) struct field.
+type UnmarshalFieldError struct {
+	Key   string
+	Type  reflect.Type
+	Field reflect.StructField
+}
+
+func (e *UnmarshalFieldError) Error() string {
+	return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
+}
+
+// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
+// (The argument to Unmarshal must be a non-nil pointer.)
+type InvalidUnmarshalError struct {
+	Type reflect.Type
+}
+
+func (e *InvalidUnmarshalError) Error() string {
+	if e.Type == nil {
+		return "json: Unmarshal(nil)"
+	}
+
+	if e.Type.Kind() != reflect.Ptr {
+		return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
+	}
+	return "json: Unmarshal(nil " + e.Type.String() + ")"
+}
+
+func (d *decodeState) unmarshal(v interface{}) (err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			if _, ok := r.(runtime.Error); ok {
+				panic(r)
+			}
+			err = r.(error)
+		}
+	}()
+
+	rv := reflect.ValueOf(v)
+	pv := rv
+	if pv.Kind() != reflect.Ptr || pv.IsNil() {
+		return &InvalidUnmarshalError{reflect.TypeOf(v)}
+	}
+
+	d.scan.reset()
+	// We decode rv not pv.Elem because the Unmarshaler interface
+	// test must be applied at the top level of the value.
+	d.value(rv)
+	return d.savedError
+}
+
+// decodeState represents the state while decoding a JSON value.
+type decodeState struct {
+	data       []byte
+	off        int // read offset in data
+	scan       scanner
+	nextscan   scanner // for calls to nextValue
+	savedError error
+	tempstr    string // scratch space to avoid some allocations
+}
+
+// errPhase is used for errors that should not happen unless
+// there is a bug in the JSON decoder or something is editing
+// the data slice while the decoder executes.
+var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?")
+
+func (d *decodeState) init(data []byte) *decodeState {
+	d.data = data
+	d.off = 0
+	d.savedError = nil
+	return d
+}
+
+// error aborts the decoding by panicking with err.
+func (d *decodeState) error(err error) {
+	panic(err)
+}
+
+// saveError saves the first err it is called with,
+// for reporting at the end of the unmarshal.
+func (d *decodeState) saveError(err error) {
+	if d.savedError == nil {
+		d.savedError = err
+	}
+}
+
+// next cuts off and returns the next full JSON value in d.data[d.off:].
+// The next value is known to be an object or array, not a literal.
+func (d *decodeState) next() []byte {
+	c := d.data[d.off]
+	item, rest, err := nextValue(d.data[d.off:], &d.nextscan)
+	if err != nil {
+		d.error(err)
+	}
+	d.off = len(d.data) - len(rest)
+
+	// Our scanner has seen the opening brace/bracket
+	// and thinks we're still in the middle of the object.
+	// invent a closing brace/bracket to get it out.
+	if c == '{' {
+		d.scan.step(&d.scan, '}')
+	} else {
+		d.scan.step(&d.scan, ']')
+	}
+
+	return item
+}
+
+// scanWhile processes bytes in d.data[d.off:] until it
+// receives a scan code not equal to op.
+// It updates d.off and returns the new scan code.
+func (d *decodeState) scanWhile(op int) int {
+	var newOp int
+	for {
+		if d.off >= len(d.data) {
+			newOp = d.scan.eof()
+			d.off = len(d.data) + 1 // mark processed EOF with len+1
+		} else {
+			c := int(d.data[d.off])
+			d.off++
+			newOp = d.scan.step(&d.scan, c)
+		}
+		if newOp != op {
+			break
+		}
+	}
+	return newOp
+}
+
+// value decodes a JSON value from d.data[d.off:] into the value.
+// it updates d.off to point past the decoded value.
+func (d *decodeState) value(v reflect.Value) {
+	if !v.IsValid() {
+		_, rest, err := nextValue(d.data[d.off:], &d.nextscan)
+		if err != nil {
+			d.error(err)
+		}
+		d.off = len(d.data) - len(rest)
+
+		// d.scan thinks we're still at the beginning of the item.
+		// Feed in an empty string - the shortest, simplest value -
+		// so that it knows we got to the end of the value.
+		if d.scan.redo {
+			// rewind.
+			d.scan.redo = false
+			d.scan.step = stateBeginValue
+		}
+		d.scan.step(&d.scan, '"')
+		d.scan.step(&d.scan, '"')
+		return
+	}
+
+	switch op := d.scanWhile(scanSkipSpace); op {
+	default:
+		d.error(errPhase)
+
+	case scanBeginArray:
+		d.array(v)
+
+	case scanBeginObject:
+		d.object(v)
+
+	case scanBeginLiteral:
+		d.literal(v)
+	}
+}
+
+// indirect walks down v allocating pointers as needed,
+// until it gets to a non-pointer.
+// if it encounters an Unmarshaler, indirect stops and returns that.
+// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
+func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) {
+	// If v is a named type and is addressable,
+	// start with its address, so that if the type has pointer methods,
+	// we find them.
+	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
+		v = v.Addr()
+	}
+	for {
+		var isUnmarshaler bool
+		if v.Type().NumMethod() > 0 {
+			// Remember that this is an unmarshaler,
+			// but wait to return it until after allocating
+			// the pointer (if necessary).
+			_, isUnmarshaler = v.Interface().(Unmarshaler)
+		}
+
+		if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() {
+			v = iv.Elem()
+			continue
+		}
+
+		pv := v
+		if pv.Kind() != reflect.Ptr {
+			break
+		}
+
+		if pv.Elem().Kind() != reflect.Ptr && decodingNull && pv.CanSet() {
+			return nil, pv
+		}
+		if pv.IsNil() {
+			pv.Set(reflect.New(pv.Type().Elem()))
+		}
+		if isUnmarshaler {
+			// Using v.Interface().(Unmarshaler)
+			// here means that we have to use a pointer
+			// as the struct field.  We cannot use a value inside
+			// a pointer to a struct, because in that case
+			// v.Interface() is the value (x.f) not the pointer (&x.f).
+			// This is an unfortunate consequence of reflect.
+			// An alternative would be to look up the
+			// UnmarshalJSON method and return a FuncValue.
+			return v.Interface().(Unmarshaler), reflect.Value{}
+		}
+		v = pv.Elem()
+	}
+	return nil, v
+}
+
+// array consumes an array from d.data[d.off-1:], decoding into the value v.
+// the first byte of the array ('[') has been read already.
+func (d *decodeState) array(v reflect.Value) {
+	// Check for unmarshaler.
+	unmarshaler, pv := d.indirect(v, false)
+	if unmarshaler != nil {
+		d.off--
+		err := unmarshaler.UnmarshalJSON(d.next())
+		if err != nil {
+			d.error(err)
+		}
+		return
+	}
+	v = pv
+
+	// Check type of target.
+	switch v.Kind() {
+	default:
+		d.saveError(&UnmarshalTypeError{"array", v.Type()})
+		d.off--
+		d.next()
+		return
+	case reflect.Interface:
+		// Decoding into nil interface?  Switch to non-reflect code.
+		v.Set(reflect.ValueOf(d.arrayInterface()))
+		return
+	case reflect.Array:
+	case reflect.Slice:
+		break
+	}
+
+	i := 0
+	for {
+		// Look ahead for ] - can only happen on first iteration.
+		op := d.scanWhile(scanSkipSpace)
+		if op == scanEndArray {
+			break
+		}
+
+		// Back up so d.value can have the byte we just read.
+		d.off--
+		d.scan.undo(op)
+
+		// Get element of array, growing if necessary.
+		if v.Kind() == reflect.Slice {
+			// Grow slice if necessary
+			if i >= v.Cap() {
+				newcap := v.Cap() + v.Cap()/2
+				if newcap < 4 {
+					newcap = 4
+				}
+				newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
+				reflect.Copy(newv, v)
+				v.Set(newv)
+			}
+			if i >= v.Len() {
+				v.SetLen(i + 1)
+			}
+		}
+
+		if i < v.Len() {
+			// Decode into element.
+			d.value(v.Index(i))
+		} else {
+			// Ran out of fixed array: skip.
+			d.value(reflect.Value{})
+		}
+		i++
+
+		// Next token must be , or ].
+		op = d.scanWhile(scanSkipSpace)
+		if op == scanEndArray {
+			break
+		}
+		if op != scanArrayValue {
+			d.error(errPhase)
+		}
+	}
+
+	if i < v.Len() {
+		if v.Kind() == reflect.Array {
+			// Array.  Zero the rest.
+			z := reflect.Zero(v.Type().Elem())
+			for ; i < v.Len(); i++ {
+				v.Index(i).Set(z)
+			}
+		} else {
+			v.SetLen(i)
+		}
+	}
+	if i == 0 && v.Kind() == reflect.Slice {
+		v.Set(reflect.MakeSlice(v.Type(), 0, 0))
+	}
+}
+
+// object consumes an object from d.data[d.off-1:], decoding into the value v.
+// the first byte of the object ('{') has been read already.
+func (d *decodeState) object(v reflect.Value) {
+	// Check for unmarshaler.
+	unmarshaler, pv := d.indirect(v, false)
+	if unmarshaler != nil {
+		d.off--
+		err := unmarshaler.UnmarshalJSON(d.next())
+		if err != nil {
+			d.error(err)
+		}
+		return
+	}
+	v = pv
+
+	// Decoding into nil interface?  Switch to non-reflect code.
+	iv := v
+	if iv.Kind() == reflect.Interface {
+		iv.Set(reflect.ValueOf(d.objectInterface()))
+		return
+	}
+
+	// Check type of target: struct or map[string]T
+	var (
+		mv reflect.Value
+		sv reflect.Value
+	)
+	switch v.Kind() {
+	case reflect.Map:
+		// map must have string type
+		t := v.Type()
+		if t.Key() != reflect.TypeOf("") {
+			d.saveError(&UnmarshalTypeError{"object", v.Type()})
+			break
+		}
+		mv = v
+		if mv.IsNil() {
+			mv.Set(reflect.MakeMap(t))
+		}
+	case reflect.Struct:
+		sv = v
+	default:
+		d.saveError(&UnmarshalTypeError{"object", v.Type()})
+	}
+
+	if !mv.IsValid() && !sv.IsValid() {
+		d.off--
+		d.next() // skip over { } in input
+		return
+	}
+
+	var mapElem reflect.Value
+
+	for {
+		// Read opening " of string key or closing }.
+		op := d.scanWhile(scanSkipSpace)
+		if op == scanEndObject {
+			// closing } - can only happen on first iteration.
+			break
+		}
+		if op != scanBeginLiteral {
+			d.error(errPhase)
+		}
+
+		// Read string key.
+		start := d.off - 1
+		op = d.scanWhile(scanContinue)
+		item := d.data[start : d.off-1]
+		key, ok := unquote(item)
+		if !ok {
+			d.error(errPhase)
+		}
+
+		// Figure out field corresponding to key.
+		var subv reflect.Value
+		destring := false // whether the value is wrapped in a string to be decoded first
+
+		if mv.IsValid() {
+			elemType := mv.Type().Elem()
+			if !mapElem.IsValid() {
+				mapElem = reflect.New(elemType).Elem()
+			} else {
+				mapElem.Set(reflect.Zero(elemType))
+			}
+			subv = mapElem
+		} else {
+			var f reflect.StructField
+			var ok bool
+			st := sv.Type()
+			for i := 0; i < sv.NumField(); i++ {
+				sf := st.Field(i)
+				tag := sf.Tag.Get("json")
+				if tag == "-" {
+					// Pretend this field doesn't exist.
+					continue
+				}
+				// First, tag match
+				tagName, _ := parseTag(tag)
+				if tagName == key {
+					f = sf
+					ok = true
+					break // no better match possible
+				}
+				// Second, exact field name match
+				if sf.Name == key {
+					f = sf
+					ok = true
+				}
+				// Third, case-insensitive field name match,
+				// but only if a better match hasn't already been seen
+				if !ok && strings.EqualFold(sf.Name, key) {
+					f = sf
+					ok = true
+				}
+			}
+
+			// Extract value; name must be exported.
+			if ok {
+				if f.PkgPath != "" {
+					d.saveError(&UnmarshalFieldError{key, st, f})
+				} else {
+					subv = sv.FieldByIndex(f.Index)
+				}
+				_, opts := parseTag(f.Tag.Get("json"))
+				destring = opts.Contains("string")
+			}
+		}
+
+		// Read : before value.
+		if op == scanSkipSpace {
+			op = d.scanWhile(scanSkipSpace)
+		}
+		if op != scanObjectKey {
+			d.error(errPhase)
+		}
+
+		// Read value.
+		if destring {
+			d.value(reflect.ValueOf(&d.tempstr))
+			d.literalStore([]byte(d.tempstr), subv, true)
+		} else {
+			d.value(subv)
+		}
+		// Write value back to map;
+		// if using struct, subv points into struct already.
+		if mv.IsValid() {
+			mv.SetMapIndex(reflect.ValueOf(key), subv)
+		}
+
+		// Next token must be , or }.
+		op = d.scanWhile(scanSkipSpace)
+		if op == scanEndObject {
+			break
+		}
+		if op != scanObjectValue {
+			d.error(errPhase)
+		}
+	}
+}
+
+// literal consumes a literal from d.data[d.off-1:], decoding into the value v.
+// The first byte of the literal has been read already
+// (that's how the caller knows it's a literal).
+func (d *decodeState) literal(v reflect.Value) {
+	// All bytes inside literal return scanContinue op code.
+	start := d.off - 1
+	op := d.scanWhile(scanContinue)
+
+	// Scan read one byte too far; back up.
+	d.off--
+	d.scan.undo(op)
+
+	d.literalStore(d.data[start:d.off], v, false)
+}
+
+// literalStore decodes a literal stored in item into v.
+//
+// fromQuoted indicates whether this literal came from unwrapping a
+// string from the ",string" struct tag option. this is used only to
+// produce more helpful error messages.
+func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) {
+	// Check for unmarshaler.
+	wantptr := item[0] == 'n' // null
+	unmarshaler, pv := d.indirect(v, wantptr)
+	if unmarshaler != nil {
+		err := unmarshaler.UnmarshalJSON(item)
+		if err != nil {
+			d.error(err)
+		}
+		return
+	}
+	v = pv
+
+	switch c := item[0]; c {
+	case 'n': // null
+		switch v.Kind() {
+		default:
+			d.saveError(&UnmarshalTypeError{"null", v.Type()})
+		case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+			v.Set(reflect.Zero(v.Type()))
+		}
+
+	case 't', 'f': // true, false
+		value := c == 't'
+		switch v.Kind() {
+		default:
+			if fromQuoted {
+				d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+			}
+		case reflect.Bool:
+			v.SetBool(value)
+		case reflect.Interface:
+			v.Set(reflect.ValueOf(value))
+		}
+
+	case '"': // string
+		s, ok := unquoteBytes(item)
+		if !ok {
+			if fromQuoted {
+				d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.error(errPhase)
+			}
+		}
+		switch v.Kind() {
+		default:
+			d.saveError(&UnmarshalTypeError{"string", v.Type()})
+		case reflect.Slice:
+			if v.Type() != byteSliceType {
+				d.saveError(&UnmarshalTypeError{"string", v.Type()})
+				break
+			}
+			b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
+			n, err := base64.StdEncoding.Decode(b, s)
+			if err != nil {
+				d.saveError(err)
+				break
+			}
+			v.Set(reflect.ValueOf(b[0:n]))
+		case reflect.String:
+			v.SetString(string(s))
+		case reflect.Interface:
+			v.Set(reflect.ValueOf(string(s)))
+		}
+
+	default: // number
+		if c != '-' && (c < '0' || c > '9') {
+			if fromQuoted {
+				d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.error(errPhase)
+			}
+		}
+		s := string(item)
+		switch v.Kind() {
+		default:
+			if fromQuoted {
+				d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+			} else {
+				d.error(&UnmarshalTypeError{"number", v.Type()})
+			}
+		case reflect.Interface:
+			n, err := strconv.ParseFloat(s, 64)
+			if err != nil {
+				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+				break
+			}
+			v.Set(reflect.ValueOf(n))
+
+		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+			n, err := strconv.ParseInt(s, 10, 64)
+			if err != nil || v.OverflowInt(n) {
+				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+				break
+			}
+			v.SetInt(n)
+
+		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+			n, err := strconv.ParseUint(s, 10, 64)
+			if err != nil || v.OverflowUint(n) {
+				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+				break
+			}
+			v.SetUint(n)
+
+		case reflect.Float32, reflect.Float64:
+			n, err := strconv.ParseFloat(s, v.Type().Bits())
+			if err != nil || v.OverflowFloat(n) {
+				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
+				break
+			}
+			v.SetFloat(n)
+		}
+	}
+}
+
+// The xxxInterface routines build up a value to be stored
+// in an empty interface.  They are not strictly necessary,
+// but they avoid the weight of reflection in this common case.
+
+// valueInterface is like value but returns interface{}
+func (d *decodeState) valueInterface() interface{} {
+	switch d.scanWhile(scanSkipSpace) {
+	default:
+		d.error(errPhase)
+	case scanBeginArray:
+		return d.arrayInterface()
+	case scanBeginObject:
+		return d.objectInterface()
+	case scanBeginLiteral:
+		return d.literalInterface()
+	}
+	panic("unreachable")
+}
+
+// arrayInterface is like array but returns []interface{}.
+func (d *decodeState) arrayInterface() []interface{} {
+	var v []interface{}
+	for {
+		// Look ahead for ] - can only happen on first iteration.
+		op := d.scanWhile(scanSkipSpace)
+		if op == scanEndArray {
+			break
+		}
+
+		// Back up so d.value can have the byte we just read.
+		d.off--
+		d.scan.undo(op)
+
+		v = append(v, d.valueInterface())
+
+		// Next token must be , or ].
+		op = d.scanWhile(scanSkipSpace)
+		if op == scanEndArray {
+			break
+		}
+		if op != scanArrayValue {
+			d.error(errPhase)
+		}
+	}
+	return v
+}
+
+// objectInterface is like object but returns map[string]interface{}.
+func (d *decodeState) objectInterface() map[string]interface{} {
+	m := make(map[string]interface{})
+	for {
+		// Read opening " of string key or closing }.
+		op := d.scanWhile(scanSkipSpace)
+		if op == scanEndObject {
+			// closing } - can only happen on first iteration.
+			break
+		}
+		if op != scanBeginLiteral {
+			d.error(errPhase)
+		}
+
+		// Read string key.
+		start := d.off - 1
+		op = d.scanWhile(scanContinue)
+		item := d.data[start : d.off-1]
+		key, ok := unquote(item)
+		if !ok {
+			d.error(errPhase)
+		}
+
+		// Read : before value.
+		if op == scanSkipSpace {
+			op = d.scanWhile(scanSkipSpace)
+		}
+		if op != scanObjectKey {
+			d.error(errPhase)
+		}
+
+		// Read value.
+		m[key] = d.valueInterface()
+
+		// Next token must be , or }.
+		op = d.scanWhile(scanSkipSpace)
+		if op == scanEndObject {
+			break
+		}
+		if op != scanObjectValue {
+			d.error(errPhase)
+		}
+	}
+	return m
+}
+
+// literalInterface is like literal but returns an interface value.
+func (d *decodeState) literalInterface() interface{} {
+	// All bytes inside literal return scanContinue op code.
+	start := d.off - 1
+	op := d.scanWhile(scanContinue)
+
+	// Scan read one byte too far; back up.
+	d.off--
+	d.scan.undo(op)
+	item := d.data[start:d.off]
+
+	switch c := item[0]; c {
+	case 'n': // null
+		return nil
+
+	case 't', 'f': // true, false
+		return c == 't'
+
+	case '"': // string
+		s, ok := unquote(item)
+		if !ok {
+			d.error(errPhase)
+		}
+		return s
+
+	default: // number
+		if c != '-' && (c < '0' || c > '9') {
+			d.error(errPhase)
+		}
+		n, err := strconv.ParseFloat(string(item), 64)
+		if err != nil {
+			d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
+		}
+		return n
+	}
+	panic("unreachable")
+}
+
+// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
+// or it returns -1.
+func getu4(s []byte) rune {
+	if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
+		return -1
+	}
+	r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
+	if err != nil {
+		return -1
+	}
+	return rune(r)
+}
+
+// unquote converts a quoted JSON string literal s into an actual string t.
+// The rules are different than for Go, so cannot use strconv.Unquote.
+func unquote(s []byte) (t string, ok bool) {
+	s, ok = unquoteBytes(s)
+	t = string(s)
+	return
+}
+
+func unquoteBytes(s []byte) (t []byte, ok bool) {
+	if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
+		return
+	}
+	s = s[1 : len(s)-1]
+
+	// Check for unusual characters. If there are none,
+	// then no unquoting is needed, so return a slice of the
+	// original bytes.
+	r := 0
+	for r < len(s) {
+		c := s[r]
+		if c == '\\' || c == '"' || c < ' ' {
+			break
+		}
+		if c < utf8.RuneSelf {
+			r++
+			continue
+		}
+		rr, size := utf8.DecodeRune(s[r:])
+		if rr == utf8.RuneError && size == 1 {
+			break
+		}
+		r += size
+	}
+	if r == len(s) {
+		return s, true
+	}
+
+	b := make([]byte, len(s)+2*utf8.UTFMax)
+	w := copy(b, s[0:r])
+	for r < len(s) {
+		// Out of room?  Can only happen if s is full of
+		// malformed UTF-8 and we're replacing each
+		// byte with RuneError.
+		if w >= len(b)-2*utf8.UTFMax {
+			nb := make([]byte, (len(b)+utf8.UTFMax)*2)
+			copy(nb, b[0:w])
+			b = nb
+		}
+		switch c := s[r]; {
+		case c == '\\':
+			r++
+			if r >= len(s) {
+				return
+			}
+			switch s[r] {
+			default:
+				return
+			case '"', '\\', '/', '\'':
+				b[w] = s[r]
+				r++
+				w++
+			case 'b':
+				b[w] = '\b'
+				r++
+				w++
+			case 'f':
+				b[w] = '\f'
+				r++
+				w++
+			case 'n':
+				b[w] = '\n'
+				r++
+				w++
+			case 'r':
+				b[w] = '\r'
+				r++
+				w++
+			case 't':
+				b[w] = '\t'
+				r++
+				w++
+			case 'u':
+				r--
+				rr := getu4(s[r:])
+				if rr < 0 {
+					return
+				}
+				r += 6
+				if utf16.IsSurrogate(rr) {
+					rr1 := getu4(s[r:])
+					if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
+						// A valid pair; consume.
+						r += 6
+						w += utf8.EncodeRune(b[w:], dec)
+						break
+					}
+					// Invalid surrogate; fall back to replacement rune.
+					rr = unicode.ReplacementChar
+				}
+				w += utf8.EncodeRune(b[w:], rr)
+			}
+
+		// Quote, control characters are invalid.
+		case c == '"', c < ' ':
+			return
+
+		// ASCII
+		case c < utf8.RuneSelf:
+			b[w] = c
+			r++
+			w++
+
+		// Coerce to well-formed UTF-8.
+		default:
+			rr, size := utf8.DecodeRune(s[r:])
+			r += size
+			w += utf8.EncodeRune(b[w:], rr)
+		}
+	}
+	return b[0:w], true
+}
diff --git a/src/pkg/encoding/json/decode_test.go b/src/pkg/encoding/json/decode_test.go
new file mode 100644
index 0000000..cc3103f
--- /dev/null
+++ b/src/pkg/encoding/json/decode_test.go
@@ -0,0 +1,600 @@
+// Copyright 2010 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 json
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+type T struct {
+	X string
+	Y int
+	Z int `json:"-"`
+}
+
+type tx struct {
+	x int
+}
+
+var txType = reflect.TypeOf((*tx)(nil)).Elem()
+
+// A type that can unmarshal itself.
+
+type unmarshaler struct {
+	T bool
+}
+
+func (u *unmarshaler) UnmarshalJSON(b []byte) error {
+	*u = unmarshaler{true} // All we need to see that UnmarshalJson is called.
+	return nil
+}
+
+type ustruct struct {
+	M unmarshaler
+}
+
+var (
+	um0, um1 unmarshaler // target2 of unmarshaling
+	ump      = &um1
+	umtrue   = unmarshaler{true}
+	umslice  = []unmarshaler{{true}}
+	umslicep = new([]unmarshaler)
+	umstruct = ustruct{unmarshaler{true}}
+)
+
+type unmarshalTest struct {
+	in  string
+	ptr interface{}
+	out interface{}
+	err error
+}
+
+var unmarshalTests = []unmarshalTest{
+	// basic types
+	{`true`, new(bool), true, nil},
+	{`1`, new(int), 1, nil},
+	{`1.2`, new(float64), 1.2, nil},
+	{`-5`, new(int16), int16(-5), nil},
+	{`"a\u1234"`, new(string), "a\u1234", nil},
+	{`"http:\/\/"`, new(string), "http://", nil},
+	{`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
+	{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
+	{"null", new(interface{}), nil, nil},
+	{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
+	{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
+
+	// Z has a "-" tag.
+	{`{"Y": 1, "Z": 2}`, new(T), T{Y: 1}, nil},
+
+	// syntax errors
+	{`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
+	{`[1, 2, 3+]`, nil, nil, &SyntaxError{"invalid character '+' after array element", 9}},
+
+	// array tests
+	{`[1, 2, 3]`, new([3]int), [3]int{1, 2, 3}, nil},
+	{`[1, 2, 3]`, new([1]int), [1]int{1}, nil},
+	{`[1, 2, 3]`, new([5]int), [5]int{1, 2, 3, 0, 0}, nil},
+
+	// composite tests
+	{allValueIndent, new(All), allValue, nil},
+	{allValueCompact, new(All), allValue, nil},
+	{allValueIndent, new(*All), &allValue, nil},
+	{allValueCompact, new(*All), &allValue, nil},
+	{pallValueIndent, new(All), pallValue, nil},
+	{pallValueCompact, new(All), pallValue, nil},
+	{pallValueIndent, new(*All), &pallValue, nil},
+	{pallValueCompact, new(*All), &pallValue, nil},
+
+	// unmarshal interface test
+	{`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called
+	{`{"T":false}`, &ump, &umtrue, nil},
+	{`[{"T":false}]`, &umslice, umslice, nil},
+	{`[{"T":false}]`, &umslicep, &umslice, nil},
+	{`{"M":{"T":false}}`, &umstruct, umstruct, nil},
+}
+
+func TestMarshal(t *testing.T) {
+	b, err := Marshal(allValue)
+	if err != nil {
+		t.Fatalf("Marshal allValue: %v", err)
+	}
+	if string(b) != allValueCompact {
+		t.Errorf("Marshal allValueCompact")
+		diff(t, b, []byte(allValueCompact))
+		return
+	}
+
+	b, err = Marshal(pallValue)
+	if err != nil {
+		t.Fatalf("Marshal pallValue: %v", err)
+	}
+	if string(b) != pallValueCompact {
+		t.Errorf("Marshal pallValueCompact")
+		diff(t, b, []byte(pallValueCompact))
+		return
+	}
+}
+
+func TestMarshalBadUTF8(t *testing.T) {
+	s := "hello\xffworld"
+	b, err := Marshal(s)
+	if err == nil {
+		t.Fatal("Marshal bad UTF8: no error")
+	}
+	if len(b) != 0 {
+		t.Fatal("Marshal returned data")
+	}
+	if _, ok := err.(*InvalidUTF8Error); !ok {
+		t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err)
+	}
+}
+
+func TestUnmarshal(t *testing.T) {
+	for i, tt := range unmarshalTests {
+		var scan scanner
+		in := []byte(tt.in)
+		if err := checkValid(in, &scan); err != nil {
+			if !reflect.DeepEqual(err, tt.err) {
+				t.Errorf("#%d: checkValid: %#v", i, err)
+				continue
+			}
+		}
+		if tt.ptr == nil {
+			continue
+		}
+		// v = new(right-type)
+		v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
+		if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
+			t.Errorf("#%d: %v want %v", i, err, tt.err)
+			continue
+		}
+		if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
+			t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
+			data, _ := Marshal(v.Elem().Interface())
+			println(string(data))
+			data, _ = Marshal(tt.out)
+			println(string(data))
+			continue
+		}
+	}
+}
+
+func TestUnmarshalMarshal(t *testing.T) {
+	initBig()
+	var v interface{}
+	if err := Unmarshal(jsonBig, &v); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	b, err := Marshal(v)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	if bytes.Compare(jsonBig, b) != 0 {
+		t.Errorf("Marshal jsonBig")
+		diff(t, b, jsonBig)
+		return
+	}
+}
+
+func TestLargeByteSlice(t *testing.T) {
+	s0 := make([]byte, 2000)
+	for i := range s0 {
+		s0[i] = byte(i)
+	}
+	b, err := Marshal(s0)
+	if err != nil {
+		t.Fatalf("Marshal: %v", err)
+	}
+	var s1 []byte
+	if err := Unmarshal(b, &s1); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if bytes.Compare(s0, s1) != 0 {
+		t.Errorf("Marshal large byte slice")
+		diff(t, s0, s1)
+	}
+}
+
+type Xint struct {
+	X int
+}
+
+func TestUnmarshalInterface(t *testing.T) {
+	var xint Xint
+	var i interface{} = &xint
+	if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if xint.X != 1 {
+		t.Fatalf("Did not write to xint")
+	}
+}
+
+func TestUnmarshalPtrPtr(t *testing.T) {
+	var xint Xint
+	pxint := &xint
+	if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
+		t.Fatalf("Unmarshal: %v", err)
+	}
+	if xint.X != 1 {
+		t.Fatalf("Did not write to xint")
+	}
+}
+
+func TestEscape(t *testing.T) {
+	const input = `"foobar"<html>`
+	const expected = `"\"foobar\"\u003chtml\u003e"`
+	b, err := Marshal(input)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+	if s := string(b); s != expected {
+		t.Errorf("Encoding of [%s] was [%s], want [%s]", input, s, expected)
+	}
+}
+
+func TestHTMLEscape(t *testing.T) {
+	b, err := MarshalForHTML("foobarbaz<>&quux")
+	if err != nil {
+		t.Fatalf("MarshalForHTML error: %v", err)
+	}
+	if !bytes.Equal(b, []byte(`"foobarbaz\u003c\u003e\u0026quux"`)) {
+		t.Fatalf("Unexpected encoding of \"<>&\": %s", b)
+	}
+}
+
+// WrongString is a struct that's misusing the ,string modifier.
+type WrongString struct {
+	Message string `json:"result,string"`
+}
+
+type wrongStringTest struct {
+	in, err string
+}
+
+var wrongStringTests = []wrongStringTest{
+	{`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`},
+	{`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`},
+	{`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`},
+}
+
+// If people misuse the ,string modifier, the error message should be
+// helpful, telling the user that they're doing it wrong.
+func TestErrorMessageFromMisusedString(t *testing.T) {
+	for n, tt := range wrongStringTests {
+		r := strings.NewReader(tt.in)
+		var s WrongString
+		err := NewDecoder(r).Decode(&s)
+		got := fmt.Sprintf("%v", err)
+		if got != tt.err {
+			t.Errorf("%d. got err = %q, want %q", n, got, tt.err)
+		}
+	}
+}
+
+func noSpace(c rune) rune {
+	if isSpace(c) {
+		return -1
+	}
+	return c
+}
+
+type All struct {
+	Bool    bool
+	Int     int
+	Int8    int8
+	Int16   int16
+	Int32   int32
+	Int64   int64
+	Uint    uint
+	Uint8   uint8
+	Uint16  uint16
+	Uint32  uint32
+	Uint64  uint64
+	Uintptr uintptr
+	Float32 float32
+	Float64 float64
+
+	Foo  string `json:"bar"`
+	Foo2 string `json:"bar2,dummyopt"`
+
+	IntStr int64 `json:",string"`
+
+	PBool    *bool
+	PInt     *int
+	PInt8    *int8
+	PInt16   *int16
+	PInt32   *int32
+	PInt64   *int64
+	PUint    *uint
+	PUint8   *uint8
+	PUint16  *uint16
+	PUint32  *uint32
+	PUint64  *uint64
+	PUintptr *uintptr
+	PFloat32 *float32
+	PFloat64 *float64
+
+	String  string
+	PString *string
+
+	Map   map[string]Small
+	MapP  map[string]*Small
+	PMap  *map[string]Small
+	PMapP *map[string]*Small
+
+	EmptyMap map[string]Small
+	NilMap   map[string]Small
+
+	Slice   []Small
+	SliceP  []*Small
+	PSlice  *[]Small
+	PSliceP *[]*Small
+
+	EmptySlice []Small
+	NilSlice   []Small
+
+	StringSlice []string
+	ByteSlice   []byte
+
+	Small   Small
+	PSmall  *Small
+	PPSmall **Small
+
+	Interface  interface{}
+	PInterface *interface{}
+
+	unexported int
+}
+
+type Small struct {
+	Tag string
+}
+
+var allValue = All{
+	Bool:    true,
+	Int:     2,
+	Int8:    3,
+	Int16:   4,
+	Int32:   5,
+	Int64:   6,
+	Uint:    7,
+	Uint8:   8,
+	Uint16:  9,
+	Uint32:  10,
+	Uint64:  11,
+	Uintptr: 12,
+	Float32: 14.1,
+	Float64: 15.1,
+	Foo:     "foo",
+	Foo2:    "foo2",
+	IntStr:  42,
+	String:  "16",
+	Map: map[string]Small{
+		"17": {Tag: "tag17"},
+		"18": {Tag: "tag18"},
+	},
+	MapP: map[string]*Small{
+		"19": {Tag: "tag19"},
+		"20": nil,
+	},
+	EmptyMap:    map[string]Small{},
+	Slice:       []Small{{Tag: "tag20"}, {Tag: "tag21"}},
+	SliceP:      []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
+	EmptySlice:  []Small{},
+	StringSlice: []string{"str24", "str25", "str26"},
+	ByteSlice:   []byte{27, 28, 29},
+	Small:       Small{Tag: "tag30"},
+	PSmall:      &Small{Tag: "tag31"},
+	Interface:   5.2,
+}
+
+var pallValue = All{
+	PBool:      &allValue.Bool,
+	PInt:       &allValue.Int,
+	PInt8:      &allValue.Int8,
+	PInt16:     &allValue.Int16,
+	PInt32:     &allValue.Int32,
+	PInt64:     &allValue.Int64,
+	PUint:      &allValue.Uint,
+	PUint8:     &allValue.Uint8,
+	PUint16:    &allValue.Uint16,
+	PUint32:    &allValue.Uint32,
+	PUint64:    &allValue.Uint64,
+	PUintptr:   &allValue.Uintptr,
+	PFloat32:   &allValue.Float32,
+	PFloat64:   &allValue.Float64,
+	PString:    &allValue.String,
+	PMap:       &allValue.Map,
+	PMapP:      &allValue.MapP,
+	PSlice:     &allValue.Slice,
+	PSliceP:    &allValue.SliceP,
+	PPSmall:    &allValue.PSmall,
+	PInterface: &allValue.Interface,
+}
+
+var allValueIndent = `{
+	"Bool": true,
+	"Int": 2,
+	"Int8": 3,
+	"Int16": 4,
+	"Int32": 5,
+	"Int64": 6,
+	"Uint": 7,
+	"Uint8": 8,
+	"Uint16": 9,
+	"Uint32": 10,
+	"Uint64": 11,
+	"Uintptr": 12,
+	"Float32": 14.1,
+	"Float64": 15.1,
+	"bar": "foo",
+	"bar2": "foo2",
+	"IntStr": "42",
+	"PBool": null,
+	"PInt": null,
+	"PInt8": null,
+	"PInt16": null,
+	"PInt32": null,
+	"PInt64": null,
+	"PUint": null,
+	"PUint8": null,
+	"PUint16": null,
+	"PUint32": null,
+	"PUint64": null,
+	"PUintptr": null,
+	"PFloat32": null,
+	"PFloat64": null,
+	"String": "16",
+	"PString": null,
+	"Map": {
+		"17": {
+			"Tag": "tag17"
+		},
+		"18": {
+			"Tag": "tag18"
+		}
+	},
+	"MapP": {
+		"19": {
+			"Tag": "tag19"
+		},
+		"20": null
+	},
+	"PMap": null,
+	"PMapP": null,
+	"EmptyMap": {},
+	"NilMap": null,
+	"Slice": [
+		{
+			"Tag": "tag20"
+		},
+		{
+			"Tag": "tag21"
+		}
+	],
+	"SliceP": [
+		{
+			"Tag": "tag22"
+		},
+		null,
+		{
+			"Tag": "tag23"
+		}
+	],
+	"PSlice": null,
+	"PSliceP": null,
+	"EmptySlice": [],
+	"NilSlice": null,
+	"StringSlice": [
+		"str24",
+		"str25",
+		"str26"
+	],
+	"ByteSlice": "Gxwd",
+	"Small": {
+		"Tag": "tag30"
+	},
+	"PSmall": {
+		"Tag": "tag31"
+	},
+	"PPSmall": null,
+	"Interface": 5.2,
+	"PInterface": null
+}`
+
+var allValueCompact = strings.Map(noSpace, allValueIndent)
+
+var pallValueIndent = `{
+	"Bool": false,
+	"Int": 0,
+	"Int8": 0,
+	"Int16": 0,
+	"Int32": 0,
+	"Int64": 0,
+	"Uint": 0,
+	"Uint8": 0,
+	"Uint16": 0,
+	"Uint32": 0,
+	"Uint64": 0,
+	"Uintptr": 0,
+	"Float32": 0,
+	"Float64": 0,
+	"bar": "",
+	"bar2": "",
+        "IntStr": "0",
+	"PBool": true,
+	"PInt": 2,
+	"PInt8": 3,
+	"PInt16": 4,
+	"PInt32": 5,
+	"PInt64": 6,
+	"PUint": 7,
+	"PUint8": 8,
+	"PUint16": 9,
+	"PUint32": 10,
+	"PUint64": 11,
+	"PUintptr": 12,
+	"PFloat32": 14.1,
+	"PFloat64": 15.1,
+	"String": "",
+	"PString": "16",
+	"Map": null,
+	"MapP": null,
+	"PMap": {
+		"17": {
+			"Tag": "tag17"
+		},
+		"18": {
+			"Tag": "tag18"
+		}
+	},
+	"PMapP": {
+		"19": {
+			"Tag": "tag19"
+		},
+		"20": null
+	},
+	"EmptyMap": null,
+	"NilMap": null,
+	"Slice": null,
+	"SliceP": null,
+	"PSlice": [
+		{
+			"Tag": "tag20"
+		},
+		{
+			"Tag": "tag21"
+		}
+	],
+	"PSliceP": [
+		{
+			"Tag": "tag22"
+		},
+		null,
+		{
+			"Tag": "tag23"
+		}
+	],
+	"EmptySlice": null,
+	"NilSlice": null,
+	"StringSlice": null,
+	"ByteSlice": null,
+	"Small": {
+		"Tag": ""
+	},
+	"PSmall": null,
+	"PPSmall": {
+		"Tag": "tag31"
+	},
+	"Interface": null,
+	"PInterface": 5.2
+}`
+
+var pallValueCompact = strings.Map(noSpace, pallValueIndent)
diff --git a/src/pkg/encoding/json/encode.go b/src/pkg/encoding/json/encode.go
new file mode 100644
index 0000000..eac14a4
--- /dev/null
+++ b/src/pkg/encoding/json/encode.go
@@ -0,0 +1,551 @@
+// Copyright 2010 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 json implements encoding and decoding of JSON objects as defined in
+// RFC 4627.
+//
+// See "JSON and Go" for an introduction to this package:
+// http://blog.golang.org/2011/01/json-and-go.html
+package json
+
+import (
+	"bytes"
+	"encoding/base64"
+	"math"
+	"reflect"
+	"runtime"
+	"sort"
+	"strconv"
+	"sync"
+	"unicode"
+	"unicode/utf8"
+)
+
+// Marshal returns the JSON encoding of v.
+//
+// Marshal traverses the value v recursively.
+// If an encountered value implements the Marshaler interface
+// and is not a nil pointer, Marshal calls its MarshalJSON method
+// to produce JSON.  The nil pointer exception is not strictly necessary
+// but mimics a similar, necessary exception in the behavior of
+// UnmarshalJSON.
+//
+// Otherwise, Marshal uses the following type-dependent default encodings:
+//
+// Boolean values encode as JSON booleans.
+//
+// Floating point and integer values encode as JSON numbers.
+//
+// String values encode as JSON strings, with each invalid UTF-8 sequence
+// replaced by the encoding of the Unicode replacement character U+FFFD.
+// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
+// to keep some browsers from misinterpreting JSON output as HTML.
+//
+// Array and slice values encode as JSON arrays, except that
+// []byte encodes as a base64-encoded string.
+//
+// Struct values encode as JSON objects. Each exported struct field
+// becomes a member of the object unless
+//   - the field's tag is "-", or
+//   - the field is empty and its tag specifies the "omitempty" option.
+// The empty values are false, 0, any
+// nil pointer or interface value, and any array, slice, map, or string of
+// length zero. The object's default key string is the struct field name
+// but can be specified in the struct field's tag value. The "json" key in
+// struct field's tag value is the key name, followed by an optional comma
+// and options. Examples:
+//
+//   // Field is ignored by this package.
+//   Field int `json:"-"`
+//
+//   // Field appears in JSON as key "myName".
+//   Field int `json:"myName"`
+//
+//   // Field appears in JSON as key "myName" and
+//   // the field is omitted from the object if its value is empty,
+//   // as defined above.
+//   Field int `json:"myName,omitempty"`
+//
+//   // Field appears in JSON as key "Field" (the default), but
+//   // the field is skipped if empty.
+//   // Note the leading comma.
+//   Field int `json:",omitempty"`
+//
+// The "string" option signals that a field is stored as JSON inside a
+// JSON-encoded string.  This extra level of encoding is sometimes
+// used when communicating with JavaScript programs:
+//
+//    Int64String int64 `json:",string"`
+//
+// The key name will be used if it's a non-empty string consisting of
+// only Unicode letters, digits, dollar signs, percent signs, hyphens,
+// underscores and slashes.
+//
+// Map values encode as JSON objects.
+// The map's key type must be string; the object keys are used directly
+// as map keys.
+//
+// Pointer values encode as the value pointed to.
+// A nil pointer encodes as the null JSON object.
+//
+// Interface values encode as the value contained in the interface.
+// A nil interface value encodes as the null JSON object.
+//
+// Channel, complex, and function values cannot be encoded in JSON.
+// Attempting to encode such a value causes Marshal to return
+// an InvalidTypeError.
+//
+// JSON cannot represent cyclic data structures and Marshal does not
+// handle them.  Passing cyclic structures to Marshal will result in
+// an infinite recursion.
+//
+func Marshal(v interface{}) ([]byte, error) {
+	e := &encodeState{}
+	err := e.marshal(v)
+	if err != nil {
+		return nil, err
+	}
+	return e.Bytes(), nil
+}
+
+// MarshalIndent is like Marshal but applies Indent to format the output.
+func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
+	b, err := Marshal(v)
+	if err != nil {
+		return nil, err
+	}
+	var buf bytes.Buffer
+	err = Indent(&buf, b, prefix, indent)
+	if err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
+}
+
+// MarshalForHTML is like Marshal but applies HTMLEscape to the output.
+func MarshalForHTML(v interface{}) ([]byte, error) {
+	b, err := Marshal(v)
+	if err != nil {
+		return nil, err
+	}
+	var buf bytes.Buffer
+	HTMLEscape(&buf, b)
+	return buf.Bytes(), nil
+}
+
+// HTMLEscape appends to dst the JSON-encoded src with <, >, and &
+// characters inside string literals changed to \u003c, \u003e, \u0026
+// so that the JSON will be safe to embed inside HTML <script> tags.
+// For historical reasons, web browsers don't honor standard HTML
+// escaping within <script> tags, so an alternative JSON encoding must
+// be used.
+func HTMLEscape(dst *bytes.Buffer, src []byte) {
+	// < > & can only appear in string literals,
+	// so just scan the string one byte at a time.
+	start := 0
+	for i, c := range src {
+		if c == '<' || c == '>' || c == '&' {
+			if start < i {
+				dst.Write(src[start:i])
+			}
+			dst.WriteString(`\u00`)
+			dst.WriteByte(hex[c>>4])
+			dst.WriteByte(hex[c&0xF])
+			start = i + 1
+		}
+	}
+	if start < len(src) {
+		dst.Write(src[start:])
+	}
+}
+
+// Marshaler is the interface implemented by objects that
+// can marshal themselves into valid JSON.
+type Marshaler interface {
+	MarshalJSON() ([]byte, error)
+}
+
+type UnsupportedTypeError struct {
+	Type reflect.Type
+}
+
+func (e *UnsupportedTypeError) Error() string {
+	return "json: unsupported type: " + e.Type.String()
+}
+
+type UnsupportedValueError struct {
+	Value reflect.Value
+	Str   string
+}
+
+func (e *UnsupportedValueError) Error() string {
+	return "json: unsupported value: " + e.Str
+}
+
+type InvalidUTF8Error struct {
+	S string
+}
+
+func (e *InvalidUTF8Error) Error() string {
+	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
+}
+
+type MarshalerError struct {
+	Type reflect.Type
+	Err  error
+}
+
+func (e *MarshalerError) Error() string {
+	return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Err.Error()
+}
+
+type interfaceOrPtrValue interface {
+	IsNil() bool
+	Elem() reflect.Value
+}
+
+var hex = "0123456789abcdef"
+
+// An encodeState encodes JSON into a bytes.Buffer.
+type encodeState struct {
+	bytes.Buffer // accumulated output
+	scratch      [64]byte
+}
+
+func (e *encodeState) marshal(v interface{}) (err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			if _, ok := r.(runtime.Error); ok {
+				panic(r)
+			}
+			err = r.(error)
+		}
+	}()
+	e.reflectValue(reflect.ValueOf(v))
+	return nil
+}
+
+func (e *encodeState) error(err error) {
+	panic(err)
+}
+
+var byteSliceType = reflect.TypeOf([]byte(nil))
+
+func isEmptyValue(v reflect.Value) bool {
+	switch v.Kind() {
+	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len() == 0
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	}
+	return false
+}
+
+func (e *encodeState) reflectValue(v reflect.Value) {
+	e.reflectValueQuoted(v, false)
+}
+
+// reflectValueQuoted writes the value in v to the output.
+// If quoted is true, the serialization is wrapped in a JSON string.
+func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
+	if !v.IsValid() {
+		e.WriteString("null")
+		return
+	}
+
+	if j, ok := v.Interface().(Marshaler); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
+		b, err := j.MarshalJSON()
+		if err == nil {
+			// copy JSON into buffer, checking validity.
+			err = Compact(&e.Buffer, b)
+		}
+		if err != nil {
+			e.error(&MarshalerError{v.Type(), err})
+		}
+		return
+	}
+
+	writeString := (*encodeState).WriteString
+	if quoted {
+		writeString = (*encodeState).string
+	}
+
+	switch v.Kind() {
+	case reflect.Bool:
+		x := v.Bool()
+		if x {
+			writeString(e, "true")
+		} else {
+			writeString(e, "false")
+		}
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
+		if quoted {
+			writeString(e, string(b))
+		} else {
+			e.Write(b)
+		}
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
+		if quoted {
+			writeString(e, string(b))
+		} else {
+			e.Write(b)
+		}
+	case reflect.Float32, reflect.Float64:
+		f := v.Float()
+		if math.IsInf(f, 0) || math.IsNaN(f) {
+			e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, v.Type().Bits())})
+		}
+		b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, v.Type().Bits())
+		if quoted {
+			writeString(e, string(b))
+		} else {
+			e.Write(b)
+		}
+	case reflect.String:
+		if quoted {
+			sb, err := Marshal(v.String())
+			if err != nil {
+				e.error(err)
+			}
+			e.string(string(sb))
+		} else {
+			e.string(v.String())
+		}
+
+	case reflect.Struct:
+		e.WriteByte('{')
+		first := true
+		for _, ef := range encodeFields(v.Type()) {
+			fieldValue := v.Field(ef.i)
+			if ef.omitEmpty && isEmptyValue(fieldValue) {
+				continue
+			}
+			if first {
+				first = false
+			} else {
+				e.WriteByte(',')
+			}
+			e.string(ef.tag)
+			e.WriteByte(':')
+			e.reflectValueQuoted(fieldValue, ef.quoted)
+		}
+		e.WriteByte('}')
+
+	case reflect.Map:
+		if v.Type().Key().Kind() != reflect.String {
+			e.error(&UnsupportedTypeError{v.Type()})
+		}
+		if v.IsNil() {
+			e.WriteString("null")
+			break
+		}
+		e.WriteByte('{')
+		var sv stringValues = v.MapKeys()
+		sort.Sort(sv)
+		for i, k := range sv {
+			if i > 0 {
+				e.WriteByte(',')
+			}
+			e.string(k.String())
+			e.WriteByte(':')
+			e.reflectValue(v.MapIndex(k))
+		}
+		e.WriteByte('}')
+
+	case reflect.Slice:
+		if v.IsNil() {
+			e.WriteString("null")
+			break
+		}
+		if v.Type().Elem().Kind() == reflect.Uint8 {
+			// Byte slices get special treatment; arrays don't.
+			s := v.Bytes()
+			e.WriteByte('"')
+			if len(s) < 1024 {
+				// for small buffers, using Encode directly is much faster.
+				dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
+				base64.StdEncoding.Encode(dst, s)
+				e.Write(dst)
+			} else {
+				// for large buffers, avoid unnecessary extra temporary
+				// buffer space.
+				enc := base64.NewEncoder(base64.StdEncoding, e)
+				enc.Write(s)
+				enc.Close()
+			}
+			e.WriteByte('"')
+			break
+		}
+		// Slices can be marshalled as nil, but otherwise are handled
+		// as arrays.
+		fallthrough
+	case reflect.Array:
+		e.WriteByte('[')
+		n := v.Len()
+		for i := 0; i < n; i++ {
+			if i > 0 {
+				e.WriteByte(',')
+			}
+			e.reflectValue(v.Index(i))
+		}
+		e.WriteByte(']')
+
+	case reflect.Interface, reflect.Ptr:
+		if v.IsNil() {
+			e.WriteString("null")
+			return
+		}
+		e.reflectValue(v.Elem())
+
+	default:
+		e.error(&UnsupportedTypeError{v.Type()})
+	}
+	return
+}
+
+func isValidTag(s string) bool {
+	if s == "" {
+		return false
+	}
+	for _, c := range s {
+		switch c {
+		case '$', '-', '_', '/', '%':
+			// Acceptable
+		default:
+			if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+// stringValues is a slice of reflect.Value holding *reflect.StringValue.
+// It implements the methods to sort by string.
+type stringValues []reflect.Value
+
+func (sv stringValues) Len() int           { return len(sv) }
+func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
+func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
+func (sv stringValues) get(i int) string   { return sv[i].String() }
+
+func (e *encodeState) string(s string) (int, error) {
+	len0 := e.Len()
+	e.WriteByte('"')
+	start := 0
+	for i := 0; i < len(s); {
+		if b := s[i]; b < utf8.RuneSelf {
+			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' {
+				i++
+				continue
+			}
+			if start < i {
+				e.WriteString(s[start:i])
+			}
+			switch b {
+			case '\\', '"':
+				e.WriteByte('\\')
+				e.WriteByte(b)
+			case '\n':
+				e.WriteByte('\\')
+				e.WriteByte('n')
+			case '\r':
+				e.WriteByte('\\')
+				e.WriteByte('r')
+			default:
+				// This encodes bytes < 0x20 except for \n and \r,
+				// as well as < and >. The latter are escaped because they
+				// can lead to security holes when user-controlled strings
+				// are rendered into JSON and served to some browsers.
+				e.WriteString(`\u00`)
+				e.WriteByte(hex[b>>4])
+				e.WriteByte(hex[b&0xF])
+			}
+			i++
+			start = i
+			continue
+		}
+		c, size := utf8.DecodeRuneInString(s[i:])
+		if c == utf8.RuneError && size == 1 {
+			e.error(&InvalidUTF8Error{s})
+		}
+		i += size
+	}
+	if start < len(s) {
+		e.WriteString(s[start:])
+	}
+	e.WriteByte('"')
+	return e.Len() - len0, nil
+}
+
+// encodeField contains information about how to encode a field of a
+// struct.
+type encodeField struct {
+	i         int // field index in struct
+	tag       string
+	quoted    bool
+	omitEmpty bool
+}
+
+var (
+	typeCacheLock     sync.RWMutex
+	encodeFieldsCache = make(map[reflect.Type][]encodeField)
+)
+
+// encodeFields returns a slice of encodeField for a given
+// struct type.
+func encodeFields(t reflect.Type) []encodeField {
+	typeCacheLock.RLock()
+	fs, ok := encodeFieldsCache[t]
+	typeCacheLock.RUnlock()
+	if ok {
+		return fs
+	}
+
+	typeCacheLock.Lock()
+	defer typeCacheLock.Unlock()
+	fs, ok = encodeFieldsCache[t]
+	if ok {
+		return fs
+	}
+
+	v := reflect.Zero(t)
+	n := v.NumField()
+	for i := 0; i < n; i++ {
+		f := t.Field(i)
+		if f.PkgPath != "" {
+			continue
+		}
+		var ef encodeField
+		ef.i = i
+		ef.tag = f.Name
+
+		tv := f.Tag.Get("json")
+		if tv != "" {
+			if tv == "-" {
+				continue
+			}
+			name, opts := parseTag(tv)
+			if isValidTag(name) {
+				ef.tag = name
+			}
+			ef.omitEmpty = opts.Contains("omitempty")
+			ef.quoted = opts.Contains("string")
+		}
+		fs = append(fs, ef)
+	}
+	encodeFieldsCache[t] = fs
+	return fs
+}
diff --git a/src/pkg/encoding/json/encode_test.go b/src/pkg/encoding/json/encode_test.go
new file mode 100644
index 0000000..0e39559
--- /dev/null
+++ b/src/pkg/encoding/json/encode_test.go
@@ -0,0 +1,128 @@
+// Copyright 2011 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 json
+
+import (
+	"bytes"
+	"math"
+	"reflect"
+	"testing"
+)
+
+type Optionals struct {
+	Sr string `json:"sr"`
+	So string `json:"so,omitempty"`
+	Sw string `json:"-"`
+
+	Ir int `json:"omitempty"` // actually named omitempty, not an option
+	Io int `json:"io,omitempty"`
+
+	Slr []string `json:"slr,random"`
+	Slo []string `json:"slo,omitempty"`
+
+	Mr map[string]interface{} `json:"mr"`
+	Mo map[string]interface{} `json:",omitempty"`
+}
+
+var optionalsExpected = `{
+ "sr": "",
+ "omitempty": 0,
+ "slr": null,
+ "mr": {}
+}`
+
+func TestOmitEmpty(t *testing.T) {
+	var o Optionals
+	o.Sw = "something"
+	o.Mr = map[string]interface{}{}
+	o.Mo = map[string]interface{}{}
+
+	got, err := MarshalIndent(&o, "", " ")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got := string(got); got != optionalsExpected {
+		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
+	}
+}
+
+type StringTag struct {
+	BoolStr bool   `json:",string"`
+	IntStr  int64  `json:",string"`
+	StrStr  string `json:",string"`
+}
+
+var stringTagExpected = `{
+ "BoolStr": "true",
+ "IntStr": "42",
+ "StrStr": "\"xzbit\""
+}`
+
+func TestStringTag(t *testing.T) {
+	var s StringTag
+	s.BoolStr = true
+	s.IntStr = 42
+	s.StrStr = "xzbit"
+	got, err := MarshalIndent(&s, "", " ")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got := string(got); got != stringTagExpected {
+		t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
+	}
+
+	// Verify that it round-trips.
+	var s2 StringTag
+	err = NewDecoder(bytes.NewBuffer(got)).Decode(&s2)
+	if err != nil {
+		t.Fatalf("Decode: %v", err)
+	}
+	if !reflect.DeepEqual(s, s2) {
+		t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
+	}
+}
+
+// byte slices are special even if they're renamed types.
+type renamedByte byte
+type renamedByteSlice []byte
+type renamedRenamedByteSlice []renamedByte
+
+func TestEncodeRenamedByteSlice(t *testing.T) {
+	s := renamedByteSlice("abc")
+	result, err := Marshal(s)
+	if err != nil {
+		t.Fatal(err)
+	}
+	expect := `"YWJj"`
+	if string(result) != expect {
+		t.Errorf(" got %s want %s", result, expect)
+	}
+	r := renamedRenamedByteSlice("abc")
+	result, err = Marshal(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(result) != expect {
+		t.Errorf(" got %s want %s", result, expect)
+	}
+}
+
+var unsupportedValues = []interface{}{
+	math.NaN(),
+	math.Inf(-1),
+	math.Inf(1),
+}
+
+func TestUnsupportedValues(t *testing.T) {
+	for _, v := range unsupportedValues {
+		if _, err := Marshal(v); err != nil {
+			if _, ok := err.(*UnsupportedValueError); !ok {
+				t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
+			}
+		} else {
+			t.Errorf("for %v, expected error", v)
+		}
+	}
+}
diff --git a/src/pkg/encoding/json/example_test.go b/src/pkg/encoding/json/example_test.go
new file mode 100644
index 0000000..7f4a78c
--- /dev/null
+++ b/src/pkg/encoding/json/example_test.go
@@ -0,0 +1,48 @@
+// Copyright 2011 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 json_test
+
+import (
+	"encoding/json"
+	"fmt"
+	"os"
+)
+
+// {"ID":1,"Name":"Reds","Colors":["Crimson","Red","Ruby","Maroon"]}
+func ExampleMarshal() {
+	type ColorGroup struct {
+		ID     int
+		Name   string
+		Colors []string
+	}
+	group := ColorGroup{
+		ID:     1,
+		Name:   "Reds",
+		Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
+	}
+	b, err := json.Marshal(group)
+	if err != nil {
+		fmt.Println("error:", err)
+	}
+	os.Stdout.Write(b)
+}
+
+// [{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]
+func ExampleUnmarshal() {
+	var jsonBlob = []byte(`[
+		{"Name": "Platypus", "Order": "Monotremata"},
+		{"Name": "Quoll",    "Order": "Dasyuromorphia"}
+	]`)
+	type Animal struct {
+		Name  string
+		Order string
+	}
+	var animals []Animal
+	err := json.Unmarshal(jsonBlob, &animals)
+	if err != nil {
+		fmt.Println("error:", err)
+	}
+	fmt.Printf("%+v", animals)
+}
diff --git a/src/pkg/encoding/json/indent.go b/src/pkg/encoding/json/indent.go
new file mode 100644
index 0000000..5ba19b0
--- /dev/null
+++ b/src/pkg/encoding/json/indent.go
@@ -0,0 +1,114 @@
+// Copyright 2010 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 json
+
+import "bytes"
+
+// Compact appends to dst the JSON-encoded src with
+// insignificant space characters elided.
+func Compact(dst *bytes.Buffer, src []byte) error {
+	origLen := dst.Len()
+	var scan scanner
+	scan.reset()
+	start := 0
+	for i, c := range src {
+		v := scan.step(&scan, int(c))
+		if v >= scanSkipSpace {
+			if v == scanError {
+				break
+			}
+			if start < i {
+				dst.Write(src[start:i])
+			}
+			start = i + 1
+		}
+	}
+	if scan.eof() == scanError {
+		dst.Truncate(origLen)
+		return scan.err
+	}
+	if start < len(src) {
+		dst.Write(src[start:])
+	}
+	return nil
+}
+
+func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
+	dst.WriteByte('\n')
+	dst.WriteString(prefix)
+	for i := 0; i < depth; i++ {
+		dst.WriteString(indent)
+	}
+}
+
+// Indent appends to dst an indented form of the JSON-encoded src.
+// Each element in a JSON object or array begins on a new,
+// indented line beginning with prefix followed by one or more
+// copies of indent according to the indentation nesting.
+// The data appended to dst has no trailing newline, to make it easier
+// to embed inside other formatted JSON data.
+func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
+	origLen := dst.Len()
+	var scan scanner
+	scan.reset()
+	needIndent := false
+	depth := 0
+	for _, c := range src {
+		scan.bytes++
+		v := scan.step(&scan, int(c))
+		if v == scanSkipSpace {
+			continue
+		}
+		if v == scanError {
+			break
+		}
+		if needIndent && v != scanEndObject && v != scanEndArray {
+			needIndent = false
+			depth++
+			newline(dst, prefix, indent, depth)
+		}
+
+		// Emit semantically uninteresting bytes
+		// (in particular, punctuation in strings) unmodified.
+		if v == scanContinue {
+			dst.WriteByte(c)
+			continue
+		}
+
+		// Add spacing around real punctuation.
+		switch c {
+		case '{', '[':
+			// delay indent so that empty object and array are formatted as {} and [].
+			needIndent = true
+			dst.WriteByte(c)
+
+		case ',':
+			dst.WriteByte(c)
+			newline(dst, prefix, indent, depth)
+
+		case ':':
+			dst.WriteByte(c)
+			dst.WriteByte(' ')
+
+		case '}', ']':
+			if needIndent {
+				// suppress indent in empty object/array
+				needIndent = false
+			} else {
+				depth--
+				newline(dst, prefix, indent, depth)
+			}
+			dst.WriteByte(c)
+
+		default:
+			dst.WriteByte(c)
+		}
+	}
+	if scan.eof() == scanError {
+		dst.Truncate(origLen)
+		return scan.err
+	}
+	return nil
+}
diff --git a/src/pkg/encoding/json/scanner.go b/src/pkg/encoding/json/scanner.go
new file mode 100644
index 0000000..2661f41
--- /dev/null
+++ b/src/pkg/encoding/json/scanner.go
@@ -0,0 +1,632 @@
+// Copyright 2010 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 json
+
+// JSON value parser state machine.
+// Just about at the limit of what is reasonable to write by hand.
+// Some parts are a bit tedious, but overall it nicely factors out the
+// otherwise common code from the multiple scanning functions
+// in this package (Compact, Indent, checkValid, nextValue, etc).
+//
+// This file starts with two simple examples using the scanner
+// before diving into the scanner itself.
+
+import "strconv"
+
+// checkValid verifies that data is valid JSON-encoded data.
+// scan is passed in for use by checkValid to avoid an allocation.
+func checkValid(data []byte, scan *scanner) error {
+	scan.reset()
+	for _, c := range data {
+		scan.bytes++
+		if scan.step(scan, int(c)) == scanError {
+			return scan.err
+		}
+	}
+	if scan.eof() == scanError {
+		return scan.err
+	}
+	return nil
+}
+
+// nextValue splits data after the next whole JSON value,
+// returning that value and the bytes that follow it as separate slices.
+// scan is passed in for use by nextValue to avoid an allocation.
+func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) {
+	scan.reset()
+	for i, c := range data {
+		v := scan.step(scan, int(c))
+		if v >= scanEnd {
+			switch v {
+			case scanError:
+				return nil, nil, scan.err
+			case scanEnd:
+				return data[0:i], data[i:], nil
+			}
+		}
+	}
+	if scan.eof() == scanError {
+		return nil, nil, scan.err
+	}
+	return data, nil, nil
+}
+
+// A SyntaxError is a description of a JSON syntax error.
+type SyntaxError struct {
+	msg    string // description of error
+	Offset int64  // error occurred after reading Offset bytes
+}
+
+func (e *SyntaxError) Error() string { return e.msg }
+
+// A scanner is a JSON scanning state machine.
+// Callers call scan.reset() and then pass bytes in one at a time
+// by calling scan.step(&scan, c) for each byte.
+// The return value, referred to as an opcode, tells the
+// caller about significant parsing events like beginning
+// and ending literals, objects, and arrays, so that the
+// caller can follow along if it wishes.
+// The return value scanEnd indicates that a single top-level
+// JSON value has been completed, *before* the byte that
+// just got passed in.  (The indication must be delayed in order
+// to recognize the end of numbers: is 123 a whole value or
+// the beginning of 12345e+6?).
+type scanner struct {
+	// The step is a func to be called to execute the next transition.
+	// Also tried using an integer constant and a single func
+	// with a switch, but using the func directly was 10% faster
+	// on a 64-bit Mac Mini, and it's nicer to read.
+	step func(*scanner, int) int
+
+	// Reached end of top-level value.
+	endTop bool
+
+	// Stack of what we're in the middle of - array values, object keys, object values.
+	parseState []int
+
+	// Error that happened, if any.
+	err error
+
+	// 1-byte redo (see undo method)
+	redo      bool
+	redoCode  int
+	redoState func(*scanner, int) int
+
+	// total bytes consumed, updated by decoder.Decode
+	bytes int64
+}
+
+// These values are returned by the state transition functions
+// assigned to scanner.state and the method scanner.eof.
+// They give details about the current state of the scan that
+// callers might be interested to know about.
+// It is okay to ignore the return value of any particular
+// call to scanner.state: if one call returns scanError,
+// every subsequent call will return scanError too.
+const (
+	// Continue.
+	scanContinue     = iota // uninteresting byte
+	scanBeginLiteral        // end implied by next result != scanContinue
+	scanBeginObject         // begin object
+	scanObjectKey           // just finished object key (string)
+	scanObjectValue         // just finished non-last object value
+	scanEndObject           // end object (implies scanObjectValue if possible)
+	scanBeginArray          // begin array
+	scanArrayValue          // just finished array value
+	scanEndArray            // end array (implies scanArrayValue if possible)
+	scanSkipSpace           // space byte; can skip; known to be last "continue" result
+
+	// Stop.
+	scanEnd   // top-level value ended *before* this byte; known to be first "stop" result
+	scanError // hit an error, scanner.err.
+)
+
+// These values are stored in the parseState stack.
+// They give the current state of a composite value
+// being scanned.  If the parser is inside a nested value
+// the parseState describes the nested state, outermost at entry 0.
+const (
+	parseObjectKey   = iota // parsing object key (before colon)
+	parseObjectValue        // parsing object value (after colon)
+	parseArrayValue         // parsing array value
+)
+
+// reset prepares the scanner for use.
+// It must be called before calling s.step.
+func (s *scanner) reset() {
+	s.step = stateBeginValue
+	s.parseState = s.parseState[0:0]
+	s.err = nil
+	s.redo = false
+	s.endTop = false
+}
+
+// eof tells the scanner that the end of input has been reached.
+// It returns a scan status just as s.step does.
+func (s *scanner) eof() int {
+	if s.err != nil {
+		return scanError
+	}
+	if s.endTop {
+		return scanEnd
+	}
+	s.step(s, ' ')
+	if s.endTop {
+		return scanEnd
+	}
+	if s.err == nil {
+		s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
+	}
+	return scanError
+}
+
+// pushParseState pushes a new parse state p onto the parse stack.
+func (s *scanner) pushParseState(p int) {
+	s.parseState = append(s.parseState, p)
+}
+
+// popParseState pops a parse state (already obtained) off the stack
+// and updates s.step accordingly.
+func (s *scanner) popParseState() {
+	n := len(s.parseState) - 1
+	s.parseState = s.parseState[0:n]
+	s.redo = false
+	if n == 0 {
+		s.step = stateEndTop
+		s.endTop = true
+	} else {
+		s.step = stateEndValue
+	}
+}
+
+func isSpace(c rune) bool {
+	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
+}
+
+// NOTE(rsc): The various instances of
+//
+//	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+//
+// below should all be if c <= ' ' && isSpace(c), but inlining
+// the checks makes a significant difference (>10%) in tight loops
+// such as nextValue.  These should be rewritten with the clearer
+// function call once 6g knows to inline the call.
+
+// stateBeginValueOrEmpty is the state after reading `[`.
+func stateBeginValueOrEmpty(s *scanner, c int) int {
+	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+		return scanSkipSpace
+	}
+	if c == ']' {
+		return stateEndValue(s, c)
+	}
+	return stateBeginValue(s, c)
+}
+
+// stateBeginValue is the state at the beginning of the input.
+func stateBeginValue(s *scanner, c int) int {
+	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+		return scanSkipSpace
+	}
+	switch c {
+	case '{':
+		s.step = stateBeginStringOrEmpty
+		s.pushParseState(parseObjectKey)
+		return scanBeginObject
+	case '[':
+		s.step = stateBeginValueOrEmpty
+		s.pushParseState(parseArrayValue)
+		return scanBeginArray
+	case '"':
+		s.step = stateInString
+		return scanBeginLiteral
+	case '-':
+		s.step = stateNeg
+		return scanBeginLiteral
+	case '0': // beginning of 0.123
+		s.step = state0
+		return scanBeginLiteral
+	case 't': // beginning of true
+		s.step = stateT
+		return scanBeginLiteral
+	case 'f': // beginning of false
+		s.step = stateF
+		return scanBeginLiteral
+	case 'n': // beginning of null
+		s.step = stateN
+		return scanBeginLiteral
+	}
+	if '1' <= c && c <= '9' { // beginning of 1234.5
+		s.step = state1
+		return scanBeginLiteral
+	}
+	return s.error(c, "looking for beginning of value")
+}
+
+// stateBeginStringOrEmpty is the state after reading `{`.
+func stateBeginStringOrEmpty(s *scanner, c int) int {
+	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+		return scanSkipSpace
+	}
+	if c == '}' {
+		n := len(s.parseState)
+		s.parseState[n-1] = parseObjectValue
+		return stateEndValue(s, c)
+	}
+	return stateBeginString(s, c)
+}
+
+// stateBeginString is the state after reading `{"key": value,`.
+func stateBeginString(s *scanner, c int) int {
+	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+		return scanSkipSpace
+	}
+	if c == '"' {
+		s.step = stateInString
+		return scanBeginLiteral
+	}
+	return s.error(c, "looking for beginning of object key string")
+}
+
+// stateEndValue is the state after completing a value,
+// such as after reading `{}` or `true` or `["x"`.
+func stateEndValue(s *scanner, c int) int {
+	n := len(s.parseState)
+	if n == 0 {
+		// Completed top-level before the current byte.
+		s.step = stateEndTop
+		s.endTop = true
+		return stateEndTop(s, c)
+	}
+	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+		s.step = stateEndValue
+		return scanSkipSpace
+	}
+	ps := s.parseState[n-1]
+	switch ps {
+	case parseObjectKey:
+		if c == ':' {
+			s.parseState[n-1] = parseObjectValue
+			s.step = stateBeginValue
+			return scanObjectKey
+		}
+		return s.error(c, "after object key")
+	case parseObjectValue:
+		if c == ',' {
+			s.parseState[n-1] = parseObjectKey
+			s.step = stateBeginString
+			return scanObjectValue
+		}
+		if c == '}' {
+			s.popParseState()
+			return scanEndObject
+		}
+		return s.error(c, "after object key:value pair")
+	case parseArrayValue:
+		if c == ',' {
+			s.step = stateBeginValue
+			return scanArrayValue
+		}
+		if c == ']' {
+			s.popParseState()
+			return scanEndArray
+		}
+		return s.error(c, "after array element")
+	}
+	return s.error(c, "")
+}
+
+// stateEndTop is the state after finishing the top-level value,
+// such as after reading `{}` or `[1,2,3]`.
+// Only space characters should be seen now.
+func stateEndTop(s *scanner, c int) int {
+	if c != ' ' && c != '\t' && c != '\r' && c != '\n' {
+		// Complain about non-space byte on next call.
+		s.error(c, "after top-level value")
+	}
+	return scanEnd
+}
+
+// stateInString is the state after reading `"`.
+func stateInString(s *scanner, c int) int {
+	if c == '"' {
+		s.step = stateEndValue
+		return scanContinue
+	}
+	if c == '\\' {
+		s.step = stateInStringEsc
+		return scanContinue
+	}
+	if c < 0x20 {
+		return s.error(c, "in string literal")
+	}
+	return scanContinue
+}
+
+// stateInStringEsc is the state after reading `"\` during a quoted string.
+func stateInStringEsc(s *scanner, c int) int {
+	switch c {
+	case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
+		s.step = stateInString
+		return scanContinue
+	}
+	if c == 'u' {
+		s.step = stateInStringEscU
+		return scanContinue
+	}
+	return s.error(c, "in string escape code")
+}
+
+// stateInStringEscU is the state after reading `"\u` during a quoted string.
+func stateInStringEscU(s *scanner, c int) int {
+	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+		s.step = stateInStringEscU1
+		return scanContinue
+	}
+	// numbers
+	return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
+func stateInStringEscU1(s *scanner, c int) int {
+	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+		s.step = stateInStringEscU12
+		return scanContinue
+	}
+	// numbers
+	return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
+func stateInStringEscU12(s *scanner, c int) int {
+	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+		s.step = stateInStringEscU123
+		return scanContinue
+	}
+	// numbers
+	return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
+func stateInStringEscU123(s *scanner, c int) int {
+	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+		s.step = stateInString
+		return scanContinue
+	}
+	// numbers
+	return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU123 is the state after reading `-` during a number.
+func stateNeg(s *scanner, c int) int {
+	if c == '0' {
+		s.step = state0
+		return scanContinue
+	}
+	if '1' <= c && c <= '9' {
+		s.step = state1
+		return scanContinue
+	}
+	return s.error(c, "in numeric literal")
+}
+
+// state1 is the state after reading a non-zero integer during a number,
+// such as after reading `1` or `100` but not `0`.
+func state1(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = state1
+		return scanContinue
+	}
+	return state0(s, c)
+}
+
+// state0 is the state after reading `0` during a number.
+func state0(s *scanner, c int) int {
+	if c == '.' {
+		s.step = stateDot
+		return scanContinue
+	}
+	if c == 'e' || c == 'E' {
+		s.step = stateE
+		return scanContinue
+	}
+	return stateEndValue(s, c)
+}
+
+// stateDot is the state after reading the integer and decimal point in a number,
+// such as after reading `1.`.
+func stateDot(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = stateDot0
+		return scanContinue
+	}
+	return s.error(c, "after decimal point in numeric literal")
+}
+
+// stateDot0 is the state after reading the integer, decimal point, and subsequent
+// digits of a number, such as after reading `3.14`.
+func stateDot0(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = stateDot0
+		return scanContinue
+	}
+	if c == 'e' || c == 'E' {
+		s.step = stateE
+		return scanContinue
+	}
+	return stateEndValue(s, c)
+}
+
+// stateE is the state after reading the mantissa and e in a number,
+// such as after reading `314e` or `0.314e`.
+func stateE(s *scanner, c int) int {
+	if c == '+' {
+		s.step = stateESign
+		return scanContinue
+	}
+	if c == '-' {
+		s.step = stateESign
+		return scanContinue
+	}
+	return stateESign(s, c)
+}
+
+// stateESign is the state after reading the mantissa, e, and sign in a number,
+// such as after reading `314e-` or `0.314e+`.
+func stateESign(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = stateE0
+		return scanContinue
+	}
+	return s.error(c, "in exponent of numeric literal")
+}
+
+// stateE0 is the state after reading the mantissa, e, optional sign,
+// and at least one digit of the exponent in a number,
+// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
+func stateE0(s *scanner, c int) int {
+	if '0' <= c && c <= '9' {
+		s.step = stateE0
+		return scanContinue
+	}
+	return stateEndValue(s, c)
+}
+
+// stateT is the state after reading `t`.
+func stateT(s *scanner, c int) int {
+	if c == 'r' {
+		s.step = stateTr
+		return scanContinue
+	}
+	return s.error(c, "in literal true (expecting 'r')")
+}
+
+// stateTr is the state after reading `tr`.
+func stateTr(s *scanner, c int) int {
+	if c == 'u' {
+		s.step = stateTru
+		return scanContinue
+	}
+	return s.error(c, "in literal true (expecting 'u')")
+}
+
+// stateTru is the state after reading `tru`.
+func stateTru(s *scanner, c int) int {
+	if c == 'e' {
+		s.step = stateEndValue
+		return scanContinue
+	}
+	return s.error(c, "in literal true (expecting 'e')")
+}
+
+// stateF is the state after reading `f`.
+func stateF(s *scanner, c int) int {
+	if c == 'a' {
+		s.step = stateFa
+		return scanContinue
+	}
+	return s.error(c, "in literal false (expecting 'a')")
+}
+
+// stateFa is the state after reading `fa`.
+func stateFa(s *scanner, c int) int {
+	if c == 'l' {
+		s.step = stateFal
+		return scanContinue
+	}
+	return s.error(c, "in literal false (expecting 'l')")
+}
+
+// stateFal is the state after reading `fal`.
+func stateFal(s *scanner, c int) int {
+	if c == 's' {
+		s.step = stateFals
+		return scanContinue
+	}
+	return s.error(c, "in literal false (expecting 's')")
+}
+
+// stateFals is the state after reading `fals`.
+func stateFals(s *scanner, c int) int {
+	if c == 'e' {
+		s.step = stateEndValue
+		return scanContinue
+	}
+	return s.error(c, "in literal false (expecting 'e')")
+}
+
+// stateN is the state after reading `n`.
+func stateN(s *scanner, c int) int {
+	if c == 'u' {
+		s.step = stateNu
+		return scanContinue
+	}
+	return s.error(c, "in literal null (expecting 'u')")
+}
+
+// stateNu is the state after reading `nu`.
+func stateNu(s *scanner, c int) int {
+	if c == 'l' {
+		s.step = stateNul
+		return scanContinue
+	}
+	return s.error(c, "in literal null (expecting 'l')")
+}
+
+// stateNul is the state after reading `nul`.
+func stateNul(s *scanner, c int) int {
+	if c == 'l' {
+		s.step = stateEndValue
+		return scanContinue
+	}
+	return s.error(c, "in literal null (expecting 'l')")
+}
+
+// stateError is the state after reaching a syntax error,
+// such as after reading `[1}` or `5.1.2`.
+func stateError(s *scanner, c int) int {
+	return scanError
+}
+
+// error records an error and switches to the error state.
+func (s *scanner) error(c int, context string) int {
+	s.step = stateError
+	s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
+	return scanError
+}
+
+// quoteChar formats c as a quoted character literal
+func quoteChar(c int) string {
+	// special cases - different from quoted strings
+	if c == '\'' {
+		return `'\''`
+	}
+	if c == '"' {
+		return `'"'`
+	}
+
+	// use quoted string with different quotation marks
+	s := strconv.Quote(string(c))
+	return "'" + s[1:len(s)-1] + "'"
+}
+
+// undo causes the scanner to return scanCode from the next state transition.
+// This gives callers a simple 1-byte undo mechanism.
+func (s *scanner) undo(scanCode int) {
+	if s.redo {
+		panic("json: invalid use of scanner")
+	}
+	s.redoCode = scanCode
+	s.redoState = s.step
+	s.step = stateRedo
+	s.redo = true
+}
+
+// stateRedo helps implement the scanner's 1-byte undo.
+func stateRedo(s *scanner, c int) int {
+	s.redo = false
+	s.step = s.redoState
+	return s.redoCode
+}
diff --git a/src/pkg/encoding/json/scanner_test.go b/src/pkg/encoding/json/scanner_test.go
new file mode 100644
index 0000000..14d8508
--- /dev/null
+++ b/src/pkg/encoding/json/scanner_test.go
@@ -0,0 +1,303 @@
+// Copyright 2010 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 json
+
+import (
+	"bytes"
+	"math"
+	"math/rand"
+	"reflect"
+	"testing"
+)
+
+// Tests of simple examples.
+
+type example struct {
+	compact string
+	indent  string
+}
+
+var examples = []example{
+	{`1`, `1`},
+	{`{}`, `{}`},
+	{`[]`, `[]`},
+	{`{"":2}`, "{\n\t\"\": 2\n}"},
+	{`[3]`, "[\n\t3\n]"},
+	{`[1,2,3]`, "[\n\t1,\n\t2,\n\t3\n]"},
+	{`{"x":1}`, "{\n\t\"x\": 1\n}"},
+	{ex1, ex1i},
+}
+
+var ex1 = `[true,false,null,"x",1,1.5,0,-5e+2]`
+
+var ex1i = `[
+	true,
+	false,
+	null,
+	"x",
+	1,
+	1.5,
+	0,
+	-5e+2
+]`
+
+func TestCompact(t *testing.T) {
+	var buf bytes.Buffer
+	for _, tt := range examples {
+		buf.Reset()
+		if err := Compact(&buf, []byte(tt.compact)); err != nil {
+			t.Errorf("Compact(%#q): %v", tt.compact, err)
+		} else if s := buf.String(); s != tt.compact {
+			t.Errorf("Compact(%#q) = %#q, want original", tt.compact, s)
+		}
+
+		buf.Reset()
+		if err := Compact(&buf, []byte(tt.indent)); err != nil {
+			t.Errorf("Compact(%#q): %v", tt.indent, err)
+			continue
+		} else if s := buf.String(); s != tt.compact {
+			t.Errorf("Compact(%#q) = %#q, want %#q", tt.indent, s, tt.compact)
+		}
+	}
+}
+
+func TestIndent(t *testing.T) {
+	var buf bytes.Buffer
+	for _, tt := range examples {
+		buf.Reset()
+		if err := Indent(&buf, []byte(tt.indent), "", "\t"); err != nil {
+			t.Errorf("Indent(%#q): %v", tt.indent, err)
+		} else if s := buf.String(); s != tt.indent {
+			t.Errorf("Indent(%#q) = %#q, want original", tt.indent, s)
+		}
+
+		buf.Reset()
+		if err := Indent(&buf, []byte(tt.compact), "", "\t"); err != nil {
+			t.Errorf("Indent(%#q): %v", tt.compact, err)
+			continue
+		} else if s := buf.String(); s != tt.indent {
+			t.Errorf("Indent(%#q) = %#q, want %#q", tt.compact, s, tt.indent)
+		}
+	}
+}
+
+// Tests of a large random structure.
+
+func TestCompactBig(t *testing.T) {
+	initBig()
+	var buf bytes.Buffer
+	if err := Compact(&buf, jsonBig); err != nil {
+		t.Fatalf("Compact: %v", err)
+	}
+	b := buf.Bytes()
+	if bytes.Compare(b, jsonBig) != 0 {
+		t.Error("Compact(jsonBig) != jsonBig")
+		diff(t, b, jsonBig)
+		return
+	}
+}
+
+func TestIndentBig(t *testing.T) {
+	initBig()
+	var buf bytes.Buffer
+	if err := Indent(&buf, jsonBig, "", "\t"); err != nil {
+		t.Fatalf("Indent1: %v", err)
+	}
+	b := buf.Bytes()
+	if len(b) == len(jsonBig) {
+		// jsonBig is compact (no unnecessary spaces);
+		// indenting should make it bigger
+		t.Fatalf("Indent(jsonBig) did not get bigger")
+	}
+
+	// should be idempotent
+	var buf1 bytes.Buffer
+	if err := Indent(&buf1, b, "", "\t"); err != nil {
+		t.Fatalf("Indent2: %v", err)
+	}
+	b1 := buf1.Bytes()
+	if bytes.Compare(b1, b) != 0 {
+		t.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
+		diff(t, b1, b)
+		return
+	}
+
+	// should get back to original
+	buf1.Reset()
+	if err := Compact(&buf1, b); err != nil {
+		t.Fatalf("Compact: %v", err)
+	}
+	b1 = buf1.Bytes()
+	if bytes.Compare(b1, jsonBig) != 0 {
+		t.Error("Compact(Indent(jsonBig)) != jsonBig")
+		diff(t, b1, jsonBig)
+		return
+	}
+}
+
+type indentErrorTest struct {
+	in  string
+	err error
+}
+
+var indentErrorTests = []indentErrorTest{
+	{`{"X": "foo", "Y"}`, &SyntaxError{"invalid character '}' after object key", 17}},
+	{`{"X": "foo" "Y": "bar"}`, &SyntaxError{"invalid character '\"' after object key:value pair", 13}},
+}
+
+func TestIndentErrors(t *testing.T) {
+	for i, tt := range indentErrorTests {
+		slice := make([]uint8, 0)
+		buf := bytes.NewBuffer(slice)
+		if err := Indent(buf, []uint8(tt.in), "", ""); err != nil {
+			if !reflect.DeepEqual(err, tt.err) {
+				t.Errorf("#%d: Indent: %#v", i, err)
+				continue
+			}
+		}
+	}
+}
+
+func TestNextValueBig(t *testing.T) {
+	initBig()
+	var scan scanner
+	item, rest, err := nextValue(jsonBig, &scan)
+	if err != nil {
+		t.Fatalf("nextValue: %s", err)
+	}
+	if len(item) != len(jsonBig) || &item[0] != &jsonBig[0] {
+		t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
+	}
+	if len(rest) != 0 {
+		t.Errorf("invalid rest: %d", len(rest))
+	}
+
+	item, rest, err = nextValue(append(jsonBig, "HELLO WORLD"...), &scan)
+	if err != nil {
+		t.Fatalf("nextValue extra: %s", err)
+	}
+	if len(item) != len(jsonBig) {
+		t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
+	}
+	if string(rest) != "HELLO WORLD" {
+		t.Errorf("invalid rest: %d", len(rest))
+	}
+}
+
+var benchScan scanner
+
+func BenchmarkSkipValue(b *testing.B) {
+	initBig()
+	for i := 0; i < b.N; i++ {
+		nextValue(jsonBig, &benchScan)
+	}
+	b.SetBytes(int64(len(jsonBig)))
+}
+
+func diff(t *testing.T, a, b []byte) {
+	for i := 0; ; i++ {
+		if i >= len(a) || i >= len(b) || a[i] != b[i] {
+			j := i - 10
+			if j < 0 {
+				j = 0
+			}
+			t.Errorf("diverge at %d: «%s» vs «%s»", i, trim(a[j:]), trim(b[j:]))
+			return
+		}
+	}
+}
+
+func trim(b []byte) []byte {
+	if len(b) > 20 {
+		return b[0:20]
+	}
+	return b
+}
+
+// Generate a random JSON object.
+
+var jsonBig []byte
+
+const (
+	big   = 10000
+	small = 100
+)
+
+func initBig() {
+	n := big
+	if testing.Short() {
+		n = small
+	}
+	if len(jsonBig) != n {
+		b, err := Marshal(genValue(n))
+		if err != nil {
+			panic(err)
+		}
+		jsonBig = b
+	}
+}
+
+func genValue(n int) interface{} {
+	if n > 1 {
+		switch rand.Intn(2) {
+		case 0:
+			return genArray(n)
+		case 1:
+			return genMap(n)
+		}
+	}
+	switch rand.Intn(3) {
+	case 0:
+		return rand.Intn(2) == 0
+	case 1:
+		return rand.NormFloat64()
+	case 2:
+		return genString(30)
+	}
+	panic("unreachable")
+}
+
+func genString(stddev float64) string {
+	n := int(math.Abs(rand.NormFloat64()*stddev + stddev/2))
+	c := make([]rune, n)
+	for i := range c {
+		f := math.Abs(rand.NormFloat64()*64 + 32)
+		if f > 0x10ffff {
+			f = 0x10ffff
+		}
+		c[i] = rune(f)
+	}
+	return string(c)
+}
+
+func genArray(n int) []interface{} {
+	f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
+	if f > n {
+		f = n
+	}
+	if n > 0 && f == 0 {
+		f = 1
+	}
+	x := make([]interface{}, f)
+	for i := range x {
+		x[i] = genValue(((i+1)*n)/f - (i*n)/f)
+	}
+	return x
+}
+
+func genMap(n int) map[string]interface{} {
+	f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
+	if f > n {
+		f = n
+	}
+	if n > 0 && f == 0 {
+		f = 1
+	}
+	x := make(map[string]interface{})
+	for i := 0; i < f; i++ {
+		x[genString(10)] = genValue(((i+1)*n)/f - (i*n)/f)
+	}
+	return x
+}
diff --git a/src/pkg/encoding/json/stream.go b/src/pkg/encoding/json/stream.go
new file mode 100644
index 0000000..f247639
--- /dev/null
+++ b/src/pkg/encoding/json/stream.go
@@ -0,0 +1,185 @@
+// Copyright 2010 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 json
+
+import (
+	"errors"
+	"io"
+)
+
+// A Decoder reads and decodes JSON objects from an input stream.
+type Decoder struct {
+	r    io.Reader
+	buf  []byte
+	d    decodeState
+	scan scanner
+	err  error
+}
+
+// NewDecoder returns a new decoder that reads from r.
+func NewDecoder(r io.Reader) *Decoder {
+	return &Decoder{r: r}
+}
+
+// Decode reads the next JSON-encoded value from its
+// input and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about
+// the conversion of JSON into a Go value.
+func (dec *Decoder) Decode(v interface{}) error {
+	if dec.err != nil {
+		return dec.err
+	}
+
+	n, err := dec.readValue()
+	if err != nil {
+		return err
+	}
+
+	// Don't save err from unmarshal into dec.err:
+	// the connection is still usable since we read a complete JSON
+	// object from it before the error happened.
+	dec.d.init(dec.buf[0:n])
+	err = dec.d.unmarshal(v)
+
+	// Slide rest of data down.
+	rest := copy(dec.buf, dec.buf[n:])
+	dec.buf = dec.buf[0:rest]
+
+	return err
+}
+
+// readValue reads a JSON value into dec.buf.
+// It returns the length of the encoding.
+func (dec *Decoder) readValue() (int, error) {
+	dec.scan.reset()
+
+	scanp := 0
+	var err error
+Input:
+	for {
+		// Look in the buffer for a new value.
+		for i, c := range dec.buf[scanp:] {
+			dec.scan.bytes++
+			v := dec.scan.step(&dec.scan, int(c))
+			if v == scanEnd {
+				scanp += i
+				break Input
+			}
+			// scanEnd is delayed one byte.
+			// We might block trying to get that byte from src,
+			// so instead invent a space byte.
+			if v == scanEndObject && dec.scan.step(&dec.scan, ' ') == scanEnd {
+				scanp += i + 1
+				break Input
+			}
+			if v == scanError {
+				dec.err = dec.scan.err
+				return 0, dec.scan.err
+			}
+		}
+		scanp = len(dec.buf)
+
+		// Did the last read have an error?
+		// Delayed until now to allow buffer scan.
+		if err != nil {
+			if err == io.EOF {
+				if dec.scan.step(&dec.scan, ' ') == scanEnd {
+					break Input
+				}
+				if nonSpace(dec.buf) {
+					err = io.ErrUnexpectedEOF
+				}
+			}
+			dec.err = err
+			return 0, err
+		}
+
+		// Make room to read more into the buffer.
+		const minRead = 512
+		if cap(dec.buf)-len(dec.buf) < minRead {
+			newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
+			copy(newBuf, dec.buf)
+			dec.buf = newBuf
+		}
+
+		// Read.  Delay error for next iteration (after scan).
+		var n int
+		n, err = dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
+		dec.buf = dec.buf[0 : len(dec.buf)+n]
+	}
+	return scanp, nil
+}
+
+func nonSpace(b []byte) bool {
+	for _, c := range b {
+		if !isSpace(rune(c)) {
+			return true
+		}
+	}
+	return false
+}
+
+// An Encoder writes JSON objects to an output stream.
+type Encoder struct {
+	w   io.Writer
+	e   encodeState
+	err error
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+	return &Encoder{w: w}
+}
+
+// Encode writes the JSON encoding of v to the connection.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values to JSON.
+func (enc *Encoder) Encode(v interface{}) error {
+	if enc.err != nil {
+		return enc.err
+	}
+	enc.e.Reset()
+	err := enc.e.marshal(v)
+	if err != nil {
+		return err
+	}
+
+	// Terminate each value with a newline.
+	// This makes the output look a little nicer
+	// when debugging, and some kind of space
+	// is required if the encoded value was a number,
+	// so that the reader knows there aren't more
+	// digits coming.
+	enc.e.WriteByte('\n')
+
+	if _, err = enc.w.Write(enc.e.Bytes()); err != nil {
+		enc.err = err
+	}
+	return err
+}
+
+// RawMessage is a raw encoded JSON object.
+// It implements Marshaler and Unmarshaler and can
+// be used to delay JSON decoding or precompute a JSON encoding.
+type RawMessage []byte
+
+// MarshalJSON returns *m as the JSON encoding of m.
+func (m *RawMessage) MarshalJSON() ([]byte, error) {
+	return *m, nil
+}
+
+// UnmarshalJSON sets *m to a copy of data.
+func (m *RawMessage) UnmarshalJSON(data []byte) error {
+	if m == nil {
+		return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
+	}
+	*m = append((*m)[0:0], data...)
+	return nil
+}
+
+var _ Marshaler = (*RawMessage)(nil)
+var _ Unmarshaler = (*RawMessage)(nil)
diff --git a/src/pkg/json/stream_test.go b/src/pkg/encoding/json/stream_test.go
similarity index 100%
rename from src/pkg/json/stream_test.go
rename to src/pkg/encoding/json/stream_test.go
diff --git a/src/pkg/encoding/json/tagkey_test.go b/src/pkg/encoding/json/tagkey_test.go
new file mode 100644
index 0000000..bba5730
--- /dev/null
+++ b/src/pkg/encoding/json/tagkey_test.go
@@ -0,0 +1,100 @@
+// Copyright 2011 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 json
+
+import (
+	"testing"
+)
+
+type basicLatin2xTag struct {
+	V string `json:"$%-/"`
+}
+
+type basicLatin3xTag struct {
+	V string `json:"0123456789"`
+}
+
+type basicLatin4xTag struct {
+	V string `json:"ABCDEFGHIJKLMO"`
+}
+
+type basicLatin5xTag struct {
+	V string `json:"PQRSTUVWXYZ_"`
+}
+
+type basicLatin6xTag struct {
+	V string `json:"abcdefghijklmno"`
+}
+
+type basicLatin7xTag struct {
+	V string `json:"pqrstuvwxyz"`
+}
+
+type miscPlaneTag struct {
+	V string `json:"色は匂へど"`
+}
+
+type percentSlashTag struct {
+	V string `json:"text/html%"` // http://golang.org/issue/2718
+}
+
+type emptyTag struct {
+	W string
+}
+
+type misnamedTag struct {
+	X string `jsom:"Misnamed"`
+}
+
+type badFormatTag struct {
+	Y string `:"BadFormat"`
+}
+
+type badCodeTag struct {
+	Z string `json:" !\"#&'()*+,."`
+}
+
+var structTagObjectKeyTests = []struct {
+	raw   interface{}
+	value string
+	key   string
+}{
+	{basicLatin2xTag{"2x"}, "2x", "$%-/"},
+	{basicLatin3xTag{"3x"}, "3x", "0123456789"},
+	{basicLatin4xTag{"4x"}, "4x", "ABCDEFGHIJKLMO"},
+	{basicLatin5xTag{"5x"}, "5x", "PQRSTUVWXYZ_"},
+	{basicLatin6xTag{"6x"}, "6x", "abcdefghijklmno"},
+	{basicLatin7xTag{"7x"}, "7x", "pqrstuvwxyz"},
+	{miscPlaneTag{"いろはにほへと"}, "いろはにほへと", "色は匂へど"},
+	{emptyTag{"Pour Moi"}, "Pour Moi", "W"},
+	{misnamedTag{"Animal Kingdom"}, "Animal Kingdom", "X"},
+	{badFormatTag{"Orfevre"}, "Orfevre", "Y"},
+	{badCodeTag{"Reliable Man"}, "Reliable Man", "Z"},
+	{percentSlashTag{"brut"}, "brut", "text/html%"},
+}
+
+func TestStructTagObjectKey(t *testing.T) {
+	for _, tt := range structTagObjectKeyTests {
+		b, err := Marshal(tt.raw)
+		if err != nil {
+			t.Fatalf("Marshal(%#q) failed: %v", tt.raw, err)
+		}
+		var f interface{}
+		err = Unmarshal(b, &f)
+		if err != nil {
+			t.Fatalf("Unmarshal(%#q) failed: %v", b, err)
+		}
+		for i, v := range f.(map[string]interface{}) {
+			switch i {
+			case tt.key:
+				if s, ok := v.(string); !ok || s != tt.value {
+					t.Fatalf("Unexpected value: %#q, want %v", s, tt.value)
+				}
+			default:
+				t.Fatalf("Unexpected key: %#q, from %#q", i, b)
+			}
+		}
+	}
+}
diff --git a/src/pkg/json/tags.go b/src/pkg/encoding/json/tags.go
similarity index 100%
rename from src/pkg/json/tags.go
rename to src/pkg/encoding/json/tags.go
diff --git a/src/pkg/json/tags_test.go b/src/pkg/encoding/json/tags_test.go
similarity index 100%
rename from src/pkg/json/tags_test.go
rename to src/pkg/encoding/json/tags_test.go
diff --git a/src/pkg/encoding/json/testdata/code.json.gz b/src/pkg/encoding/json/testdata/code.json.gz
new file mode 100644
index 0000000..0e2895b
Binary files /dev/null and b/src/pkg/encoding/json/testdata/code.json.gz differ
diff --git a/src/pkg/encoding/pem/pem.go b/src/pkg/encoding/pem/pem.go
index 12689b5..3eb7c9f 100644
--- a/src/pkg/encoding/pem/pem.go
+++ b/src/pkg/encoding/pem/pem.go
@@ -11,7 +11,6 @@ import (
 	"bytes"
 	"encoding/base64"
 	"io"
-	"os"
 )
 
 // A Block represents a PEM encoded structure.
@@ -170,7 +169,7 @@ type lineBreaker struct {
 	out  io.Writer
 }
 
-func (l *lineBreaker) Write(b []byte) (n int, err os.Error) {
+func (l *lineBreaker) Write(b []byte) (n int, err error) {
 	if l.used+len(b) < pemLineLength {
 		copy(l.line[l.used:], b)
 		l.used += len(b)
@@ -197,7 +196,7 @@ func (l *lineBreaker) Write(b []byte) (n int, err os.Error) {
 	return l.Write(b[excess:])
 }
 
-func (l *lineBreaker) Close() (err os.Error) {
+func (l *lineBreaker) Close() (err error) {
 	if l.used > 0 {
 		_, err = l.out.Write(l.line[0:l.used])
 		if err != nil {
@@ -209,7 +208,7 @@ func (l *lineBreaker) Close() (err os.Error) {
 	return
 }
 
-func Encode(out io.Writer, b *Block) (err os.Error) {
+func Encode(out io.Writer, b *Block) (err error) {
 	_, err = out.Write(pemStart[1:])
 	if err != nil {
 		return
diff --git a/src/pkg/encoding/xml/Makefile b/src/pkg/encoding/xml/Makefile
new file mode 100644
index 0000000..ca84c21
--- /dev/null
+++ b/src/pkg/encoding/xml/Makefile
@@ -0,0 +1,15 @@
+# Copyright 2009 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=encoding/xml
+
+GOFILES=\
+	marshal.go\
+	read.go\
+	typeinfo.go\
+	xml.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/encoding/xml/atom_test.go b/src/pkg/encoding/xml/atom_test.go
new file mode 100644
index 0000000..8d003aa
--- /dev/null
+++ b/src/pkg/encoding/xml/atom_test.go
@@ -0,0 +1,51 @@
+// Copyright 2011 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 xml
+
+var atomValue = &Feed{
+	XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
+	Title:   "Example Feed",
+	Link:    []Link{{Href: "http://example.org/"}},
+	Updated: ParseTime("2003-12-13T18:30:02Z"),
+	Author:  Person{Name: "John Doe"},
+	Id:      "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6",
+
+	Entry: []Entry{
+		{
+			Title:   "Atom-Powered Robots Run Amok",
+			Link:    []Link{{Href: "http://example.org/2003/12/13/atom03"}},
+			Id:      "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
+			Updated: ParseTime("2003-12-13T18:30:02Z"),
+			Summary: NewText("Some text."),
+		},
+	},
+}
+
+var atomXml = `` +
+	`<feed xmlns="http://www.w3.org/2005/Atom">` +
+	`<title>Example Feed</title>` +
+	`<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>` +
+	`<link href="http://example.org/"></link>` +
+	`<updated>2003-12-13T18:30:02Z</updated>` +
+	`<author><name>John Doe</name><uri></uri><email></email></author>` +
+	`<entry>` +
+	`<title>Atom-Powered Robots Run Amok</title>` +
+	`<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>` +
+	`<link href="http://example.org/2003/12/13/atom03"></link>` +
+	`<updated>2003-12-13T18:30:02Z</updated>` +
+	`<author><name></name><uri></uri><email></email></author>` +
+	`<summary>Some text.</summary>` +
+	`</entry>` +
+	`</feed>`
+
+func ParseTime(str string) Time {
+	return Time(str)
+}
+
+func NewText(text string) Text {
+	return Text{
+		Body: text,
+	}
+}
diff --git a/src/pkg/encoding/xml/marshal.go b/src/pkg/encoding/xml/marshal.go
new file mode 100644
index 0000000..7a05a1b
--- /dev/null
+++ b/src/pkg/encoding/xml/marshal.go
@@ -0,0 +1,380 @@
+// Copyright 2011 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 xml
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+const (
+	// A generic XML header suitable for use with the output of Marshal.
+	// This is not automatically added to any output of this package,
+	// it is provided as a convenience.
+	Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
+)
+
+// Marshal returns the XML encoding of v.
+//
+// Marshal handles an array or slice by marshalling each of the elements.
+// Marshal handles a pointer by marshalling the value it points at or, if the
+// pointer is nil, by writing nothing.  Marshal handles an interface value by
+// marshalling the value it contains or, if the interface value is nil, by
+// writing nothing.  Marshal handles all other data by writing one or more XML
+// elements containing the data.
+//
+// The name for the XML elements is taken from, in order of preference:
+//     - the tag on the XMLName field, if the data is a struct
+//     - the value of the XMLName field of type xml.Name
+//     - the tag of the struct field used to obtain the data
+//     - the name of the struct field used to obtain the data
+//     - the name of the marshalled type
+//
+// The XML element for a struct contains marshalled elements for each of the
+// exported fields of the struct, with these exceptions:
+//     - the XMLName field, described above, is omitted.
+//     - a field with tag "-" is omitted.
+//     - a field with tag "name,attr" becomes an attribute with
+//       the given name in the XML element.
+//     - a field with tag ",attr" becomes an attribute with the
+//       field name in the in the XML element.
+//     - a field with tag ",chardata" is written as character data,
+//       not as an XML element.
+//     - a field with tag ",innerxml" is written verbatim, not subject
+//       to the usual marshalling procedure.
+//     - a field with tag ",comment" is written as an XML comment, not
+//       subject to the usual marshalling procedure. It must not contain
+//       the "--" string within it.
+//
+// If a field uses a tag "a>b>c", then the element c will be nested inside
+// parent elements a and b.  Fields that appear next to each other that name
+// the same parent will be enclosed in one XML element.  For example:
+//
+//	type Result struct {
+//		XMLName   xml.Name `xml:"result"`
+//		Id        int      `xml:"id,attr"`
+//		FirstName string   `xml:"person>name>first"`
+//		LastName  string   `xml:"person>name>last"`
+//		Age       int      `xml:"person>age"`
+//	}
+//
+//	xml.Marshal(&Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42})
+//
+// would be marshalled as:
+//
+//	<result>
+//		<person id="13">
+//			<name>
+//				<first>John</first>
+//				<last>Doe</last>
+//			</name>
+//			<age>42</age>
+//		</person>
+//	</result>
+//
+// Marshal will return an error if asked to marshal a channel, function, or map.
+func Marshal(v interface{}) ([]byte, error) {
+	var b bytes.Buffer
+	if err := NewEncoder(&b).Encode(v); err != nil {
+		return nil, err
+	}
+	return b.Bytes(), nil
+}
+
+// An Encoder writes XML data to an output stream.
+type Encoder struct {
+	printer
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+	return &Encoder{printer{bufio.NewWriter(w)}}
+}
+
+// Encode writes the XML encoding of v to the stream.
+//
+// See the documentation for Marshal for details about the conversion
+// of Go values to XML.
+func (enc *Encoder) Encode(v interface{}) error {
+	err := enc.marshalValue(reflect.ValueOf(v), nil)
+	enc.Flush()
+	return err
+}
+
+type printer struct {
+	*bufio.Writer
+}
+
+func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
+	if !val.IsValid() {
+		return nil
+	}
+
+	kind := val.Kind()
+	typ := val.Type()
+
+	// Drill into pointers/interfaces
+	if kind == reflect.Ptr || kind == reflect.Interface {
+		if val.IsNil() {
+			return nil
+		}
+		return p.marshalValue(val.Elem(), finfo)
+	}
+
+	// Slices and arrays iterate over the elements. They do not have an enclosing tag.
+	if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
+		for i, n := 0, val.Len(); i < n; i++ {
+			if err := p.marshalValue(val.Index(i), finfo); err != nil {
+				return err
+			}
+		}
+		return nil
+	}
+
+	tinfo, err := getTypeInfo(typ)
+	if err != nil {
+		return err
+	}
+
+	// Precedence for the XML element name is:
+	// 1. XMLName field in underlying struct;
+	// 2. field name/tag in the struct field; and
+	// 3. type name
+	var xmlns, name string
+	if tinfo.xmlname != nil {
+		xmlname := tinfo.xmlname
+		if xmlname.name != "" {
+			xmlns, name = xmlname.xmlns, xmlname.name
+		} else if v, ok := val.FieldByIndex(xmlname.idx).Interface().(Name); ok && v.Local != "" {
+			xmlns, name = v.Space, v.Local
+		}
+	}
+	if name == "" && finfo != nil {
+		xmlns, name = finfo.xmlns, finfo.name
+	}
+	if name == "" {
+		name = typ.Name()
+		if name == "" {
+			return &UnsupportedTypeError{typ}
+		}
+	}
+
+	p.WriteByte('<')
+	p.WriteString(name)
+
+	if xmlns != "" {
+		p.WriteString(` xmlns="`)
+		// TODO: EscapeString, to avoid the allocation.
+		Escape(p, []byte(xmlns))
+		p.WriteByte('"')
+	}
+
+	// Attributes
+	for i := range tinfo.fields {
+		finfo := &tinfo.fields[i]
+		if finfo.flags&fAttr == 0 {
+			continue
+		}
+		fv := val.FieldByIndex(finfo.idx)
+		switch fv.Kind() {
+		case reflect.String, reflect.Array, reflect.Slice:
+			// TODO: Should we really do this once ,omitempty is in?
+			if fv.Len() == 0 {
+				continue
+			}
+		}
+		p.WriteByte(' ')
+		p.WriteString(finfo.name)
+		p.WriteString(`="`)
+		if err := p.marshalSimple(fv.Type(), fv); err != nil {
+			return err
+		}
+		p.WriteByte('"')
+	}
+	p.WriteByte('>')
+
+	if val.Kind() == reflect.Struct {
+		err = p.marshalStruct(tinfo, val)
+	} else {
+		err = p.marshalSimple(typ, val)
+	}
+	if err != nil {
+		return err
+	}
+
+	p.WriteByte('<')
+	p.WriteByte('/')
+	p.WriteString(name)
+	p.WriteByte('>')
+
+	return nil
+}
+
+func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
+	switch val.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p.WriteString(strconv.FormatInt(val.Int(), 10))
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p.WriteString(strconv.FormatUint(val.Uint(), 10))
+	case reflect.Float32, reflect.Float64:
+		p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, 64))
+	case reflect.String:
+		// TODO: Add EscapeString.
+		Escape(p, []byte(val.String()))
+	case reflect.Bool:
+		p.WriteString(strconv.FormatBool(val.Bool()))
+	case reflect.Array:
+		// will be [...]byte
+		bytes := make([]byte, val.Len())
+		for i := range bytes {
+			bytes[i] = val.Index(i).Interface().(byte)
+		}
+		Escape(p, bytes)
+	case reflect.Slice:
+		// will be []byte
+		Escape(p, val.Bytes())
+	default:
+		return &UnsupportedTypeError{typ}
+	}
+	return nil
+}
+
+var ddBytes = []byte("--")
+
+func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
+	s := parentStack{printer: p}
+	for i := range tinfo.fields {
+		finfo := &tinfo.fields[i]
+		if finfo.flags&(fAttr|fAny) != 0 {
+			continue
+		}
+		vf := val.FieldByIndex(finfo.idx)
+		switch finfo.flags & fMode {
+		case fCharData:
+			switch vf.Kind() {
+			case reflect.String:
+				Escape(p, []byte(vf.String()))
+			case reflect.Slice:
+				if elem, ok := vf.Interface().([]byte); ok {
+					Escape(p, elem)
+				}
+			}
+			continue
+
+		case fComment:
+			k := vf.Kind()
+			if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
+				return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
+			}
+			if vf.Len() == 0 {
+				continue
+			}
+			p.WriteString("<!--")
+			dashDash := false
+			dashLast := false
+			switch k {
+			case reflect.String:
+				s := vf.String()
+				dashDash = strings.Index(s, "--") >= 0
+				dashLast = s[len(s)-1] == '-'
+				if !dashDash {
+					p.WriteString(s)
+				}
+			case reflect.Slice:
+				b := vf.Bytes()
+				dashDash = bytes.Index(b, ddBytes) >= 0
+				dashLast = b[len(b)-1] == '-'
+				if !dashDash {
+					p.Write(b)
+				}
+			default:
+				panic("can't happen")
+			}
+			if dashDash {
+				return fmt.Errorf(`xml: comments must not contain "--"`)
+			}
+			if dashLast {
+				// "--->" is invalid grammar. Make it "- -->"
+				p.WriteByte(' ')
+			}
+			p.WriteString("-->")
+			continue
+
+		case fInnerXml:
+			iface := vf.Interface()
+			switch raw := iface.(type) {
+			case []byte:
+				p.Write(raw)
+				continue
+			case string:
+				p.WriteString(raw)
+				continue
+			}
+
+		case fElement:
+			s.trim(finfo.parents)
+			if len(finfo.parents) > len(s.stack) {
+				if vf.Kind() != reflect.Ptr && vf.Kind() != reflect.Interface || !vf.IsNil() {
+					s.push(finfo.parents[len(s.stack):])
+				}
+			}
+		}
+		if err := p.marshalValue(vf, finfo); err != nil {
+			return err
+		}
+	}
+	s.trim(nil)
+	return nil
+}
+
+type parentStack struct {
+	*printer
+	stack []string
+}
+
+// trim updates the XML context to match the longest common prefix of the stack
+// and the given parents.  A closing tag will be written for every parent
+// popped.  Passing a zero slice or nil will close all the elements.
+func (s *parentStack) trim(parents []string) {
+	split := 0
+	for ; split < len(parents) && split < len(s.stack); split++ {
+		if parents[split] != s.stack[split] {
+			break
+		}
+	}
+
+	for i := len(s.stack) - 1; i >= split; i-- {
+		s.WriteString("</")
+		s.WriteString(s.stack[i])
+		s.WriteByte('>')
+	}
+
+	s.stack = parents[:split]
+}
+
+// push adds parent elements to the stack and writes open tags.
+func (s *parentStack) push(parents []string) {
+	for i := 0; i < len(parents); i++ {
+		s.WriteString("<")
+		s.WriteString(parents[i])
+		s.WriteByte('>')
+	}
+	s.stack = append(s.stack, parents...)
+}
+
+// A MarshalXMLError is returned when Marshal encounters a type
+// that cannot be converted into XML.
+type UnsupportedTypeError struct {
+	Type reflect.Type
+}
+
+func (e *UnsupportedTypeError) Error() string {
+	return "xml: unsupported type: " + e.Type.String()
+}
diff --git a/src/pkg/encoding/xml/marshal_test.go b/src/pkg/encoding/xml/marshal_test.go
new file mode 100644
index 0000000..e0be332
--- /dev/null
+++ b/src/pkg/encoding/xml/marshal_test.go
@@ -0,0 +1,707 @@
+// Copyright 2011 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 xml
+
+import (
+	"reflect"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+type DriveType int
+
+const (
+	HyperDrive DriveType = iota
+	ImprobabilityDrive
+)
+
+type Passenger struct {
+	Name   []string `xml:"name"`
+	Weight float32  `xml:"weight"`
+}
+
+type Ship struct {
+	XMLName struct{} `xml:"spaceship"`
+
+	Name      string       `xml:"name,attr"`
+	Pilot     string       `xml:"pilot,attr"`
+	Drive     DriveType    `xml:"drive"`
+	Age       uint         `xml:"age"`
+	Passenger []*Passenger `xml:"passenger"`
+	secret    string
+}
+
+type NamedType string
+
+type Port struct {
+	XMLName struct{} `xml:"port"`
+	Type    string   `xml:"type,attr"`
+	Comment string   `xml:",comment"`
+	Number  string   `xml:",chardata"`
+}
+
+type Domain struct {
+	XMLName struct{} `xml:"domain"`
+	Country string   `xml:",attr"`
+	Name    []byte   `xml:",chardata"`
+	Comment []byte   `xml:",comment"`
+}
+
+type Book struct {
+	XMLName struct{} `xml:"book"`
+	Title   string   `xml:",chardata"`
+}
+
+type SecretAgent struct {
+	XMLName   struct{} `xml:"agent"`
+	Handle    string   `xml:"handle,attr"`
+	Identity  string
+	Obfuscate string `xml:",innerxml"`
+}
+
+type NestedItems struct {
+	XMLName struct{} `xml:"result"`
+	Items   []string `xml:">item"`
+	Item1   []string `xml:"Items>item1"`
+}
+
+type NestedOrder struct {
+	XMLName struct{} `xml:"result"`
+	Field1  string   `xml:"parent>c"`
+	Field2  string   `xml:"parent>b"`
+	Field3  string   `xml:"parent>a"`
+}
+
+type MixedNested struct {
+	XMLName struct{} `xml:"result"`
+	A       string   `xml:"parent1>a"`
+	B       string   `xml:"b"`
+	C       string   `xml:"parent1>parent2>c"`
+	D       string   `xml:"parent1>d"`
+}
+
+type NilTest struct {
+	A interface{} `xml:"parent1>parent2>a"`
+	B interface{} `xml:"parent1>b"`
+	C interface{} `xml:"parent1>parent2>c"`
+}
+
+type Service struct {
+	XMLName struct{} `xml:"service"`
+	Domain  *Domain  `xml:"host>domain"`
+	Port    *Port    `xml:"host>port"`
+	Extra1  interface{}
+	Extra2  interface{} `xml:"host>extra2"`
+}
+
+var nilStruct *Ship
+
+type EmbedA struct {
+	EmbedC
+	EmbedB EmbedB
+	FieldA string
+}
+
+type EmbedB struct {
+	FieldB string
+	EmbedC
+}
+
+type EmbedC struct {
+	FieldA1 string `xml:"FieldA>A1"`
+	FieldA2 string `xml:"FieldA>A2"`
+	FieldB  string
+	FieldC  string
+}
+
+type NameCasing struct {
+	XMLName struct{} `xml:"casing"`
+	Xy      string
+	XY      string
+	XyA     string `xml:"Xy,attr"`
+	XYA     string `xml:"XY,attr"`
+}
+
+type NamePrecedence struct {
+	XMLName     Name              `xml:"Parent"`
+	FromTag     XMLNameWithoutTag `xml:"InTag"`
+	FromNameVal XMLNameWithoutTag
+	FromNameTag XMLNameWithTag
+	InFieldName string
+}
+
+type XMLNameWithTag struct {
+	XMLName Name   `xml:"InXMLNameTag"`
+	Value   string ",chardata"
+}
+
+type XMLNameWithoutTag struct {
+	XMLName Name
+	Value   string ",chardata"
+}
+
+type NameInField struct {
+	Foo Name `xml:"ns foo"`
+}
+
+type AttrTest struct {
+	Int   int     `xml:",attr"`
+	Lower int     `xml:"int,attr"`
+	Float float64 `xml:",attr"`
+	Uint8 uint8   `xml:",attr"`
+	Bool  bool    `xml:",attr"`
+	Str   string  `xml:",attr"`
+}
+
+type AnyTest struct {
+	XMLName  struct{}  `xml:"a"`
+	Nested   string    `xml:"nested>value"`
+	AnyField AnyHolder `xml:",any"`
+}
+
+type AnyHolder struct {
+	XMLName Name
+	XML     string `xml:",innerxml"`
+}
+
+type RecurseA struct {
+	A string
+	B *RecurseB
+}
+
+type RecurseB struct {
+	A *RecurseA
+	B string
+}
+
+type PresenceTest struct {
+	Exists *struct{}
+}
+
+type IgnoreTest struct {
+	PublicSecret string `xml:"-"`
+}
+
+type MyBytes []byte
+
+type Data struct {
+	Bytes  []byte
+	Attr   []byte `xml:",attr"`
+	Custom MyBytes
+}
+
+type Plain struct {
+	V interface{}
+}
+
+// Unless explicitly stated as such (or *Plain), all of the
+// tests below are two-way tests. When introducing new tests,
+// please try to make them two-way as well to ensure that
+// marshalling and unmarshalling are as symmetrical as feasible.
+var marshalTests = []struct {
+	Value         interface{}
+	ExpectXML     string
+	MarshalOnly   bool
+	UnmarshalOnly bool
+}{
+	// Test nil marshals to nothing
+	{Value: nil, ExpectXML: ``, MarshalOnly: true},
+	{Value: nilStruct, ExpectXML: ``, MarshalOnly: true},
+
+	// Test value types
+	{Value: &Plain{true}, ExpectXML: `<Plain><V>true</V></Plain>`},
+	{Value: &Plain{false}, ExpectXML: `<Plain><V>false</V></Plain>`},
+	{Value: &Plain{int(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{int8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{int16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{int32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{uint(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{uint8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{uint16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{uint32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+	{Value: &Plain{float32(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
+	{Value: &Plain{float64(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
+	{Value: &Plain{uintptr(0xFFDD)}, ExpectXML: `<Plain><V>65501</V></Plain>`},
+	{Value: &Plain{"gopher"}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
+	{Value: &Plain{[]byte("gopher")}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
+	{Value: &Plain{"</>"}, ExpectXML: `<Plain><V></></V></Plain>`},
+	{Value: &Plain{[]byte("</>")}, ExpectXML: `<Plain><V></></V></Plain>`},
+	{Value: &Plain{[3]byte{'<', '/', '>'}}, ExpectXML: `<Plain><V></></V></Plain>`},
+	{Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},
+	{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+	{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+
+	// A pointer to struct{} may be used to test for an element's presence.
+	{
+		Value:     &PresenceTest{new(struct{})},
+		ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+	},
+	{
+		Value:     &PresenceTest{},
+		ExpectXML: `<PresenceTest></PresenceTest>`,
+	},
+
+	// A pointer to struct{} may be used to test for an element's presence.
+	{
+		Value:     &PresenceTest{new(struct{})},
+		ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+	},
+	{
+		Value:     &PresenceTest{},
+		ExpectXML: `<PresenceTest></PresenceTest>`,
+	},
+
+	// A []byte field is only nil if the element was not found.
+	{
+		Value:         &Data{},
+		ExpectXML:     `<Data></Data>`,
+		UnmarshalOnly: true,
+	},
+	{
+		Value:         &Data{Bytes: []byte{}, Custom: MyBytes{}, Attr: []byte{}},
+		ExpectXML:     `<Data Attr=""><Bytes></Bytes><Custom></Custom></Data>`,
+		UnmarshalOnly: true,
+	},
+
+	// Check that []byte works, including named []byte types.
+	{
+		Value:     &Data{Bytes: []byte("ab"), Custom: MyBytes("cd"), Attr: []byte{'v'}},
+		ExpectXML: `<Data Attr="v"><Bytes>ab</Bytes><Custom>cd</Custom></Data>`,
+	},
+
+	// Test innerxml
+	{
+		Value: &SecretAgent{
+			Handle:    "007",
+			Identity:  "James Bond",
+			Obfuscate: "<redacted/>",
+		},
+		ExpectXML:   `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+		MarshalOnly: true,
+	},
+	{
+		Value: &SecretAgent{
+			Handle:    "007",
+			Identity:  "James Bond",
+			Obfuscate: "<Identity>James Bond</Identity><redacted/>",
+		},
+		ExpectXML:     `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+		UnmarshalOnly: true,
+	},
+
+	// Test structs
+	{Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
+	{Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
+	{Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="<unix>"></port>`},
+	{Value: &Port{Number: "443", Comment: "https"}, ExpectXML: `<port><!--https-->443</port>`},
+	{Value: &Port{Number: "443", Comment: "add space-"}, ExpectXML: `<port><!--add space- -->443</port>`, MarshalOnly: true},
+	{Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&friends</domain>`},
+	{Value: &Domain{Name: []byte("google.com"), Comment: []byte(" &friends ")}, ExpectXML: `<domain>google.com<!-- &friends --></domain>`},
+	{Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride & Prejudice</book>`},
+	{Value: atomValue, ExpectXML: atomXml},
+	{
+		Value: &Ship{
+			Name:  "Heart of Gold",
+			Pilot: "Computer",
+			Age:   1,
+			Drive: ImprobabilityDrive,
+			Passenger: []*Passenger{
+				{
+					Name:   []string{"Zaphod", "Beeblebrox"},
+					Weight: 7.25,
+				},
+				{
+					Name:   []string{"Trisha", "McMillen"},
+					Weight: 5.5,
+				},
+				{
+					Name:   []string{"Ford", "Prefect"},
+					Weight: 7,
+				},
+				{
+					Name:   []string{"Arthur", "Dent"},
+					Weight: 6.75,
+				},
+			},
+		},
+		ExpectXML: `<spaceship name="Heart of Gold" pilot="Computer">` +
+			`<drive>` + strconv.Itoa(int(ImprobabilityDrive)) + `</drive>` +
+			`<age>1</age>` +
+			`<passenger>` +
+			`<name>Zaphod</name>` +
+			`<name>Beeblebrox</name>` +
+			`<weight>7.25</weight>` +
+			`</passenger>` +
+			`<passenger>` +
+			`<name>Trisha</name>` +
+			`<name>McMillen</name>` +
+			`<weight>5.5</weight>` +
+			`</passenger>` +
+			`<passenger>` +
+			`<name>Ford</name>` +
+			`<name>Prefect</name>` +
+			`<weight>7</weight>` +
+			`</passenger>` +
+			`<passenger>` +
+			`<name>Arthur</name>` +
+			`<name>Dent</name>` +
+			`<weight>6.75</weight>` +
+			`</passenger>` +
+			`</spaceship>`,
+	},
+
+	// Test a>b
+	{
+		Value: &NestedItems{Items: nil, Item1: nil},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`</Items>` +
+			`</result>`,
+	},
+	{
+		Value: &NestedItems{Items: []string{}, Item1: []string{}},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`</Items>` +
+			`</result>`,
+		MarshalOnly: true,
+	},
+	{
+		Value: &NestedItems{Items: nil, Item1: []string{"A"}},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`<item1>A</item1>` +
+			`</Items>` +
+			`</result>`,
+	},
+	{
+		Value: &NestedItems{Items: []string{"A", "B"}, Item1: nil},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`<item>A</item>` +
+			`<item>B</item>` +
+			`</Items>` +
+			`</result>`,
+	},
+	{
+		Value: &NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},
+		ExpectXML: `<result>` +
+			`<Items>` +
+			`<item>A</item>` +
+			`<item>B</item>` +
+			`<item1>C</item1>` +
+			`</Items>` +
+			`</result>`,
+	},
+	{
+		Value: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
+		ExpectXML: `<result>` +
+			`<parent>` +
+			`<c>C</c>` +
+			`<b>B</b>` +
+			`<a>A</a>` +
+			`</parent>` +
+			`</result>`,
+	},
+	{
+		Value: &NilTest{A: "A", B: nil, C: "C"},
+		ExpectXML: `<NilTest>` +
+			`<parent1>` +
+			`<parent2><a>A</a></parent2>` +
+			`<parent2><c>C</c></parent2>` +
+			`</parent1>` +
+			`</NilTest>`,
+		MarshalOnly: true, // Uses interface{}
+	},
+	{
+		Value: &MixedNested{A: "A", B: "B", C: "C", D: "D"},
+		ExpectXML: `<result>` +
+			`<parent1><a>A</a></parent1>` +
+			`<b>B</b>` +
+			`<parent1>` +
+			`<parent2><c>C</c></parent2>` +
+			`<d>D</d>` +
+			`</parent1>` +
+			`</result>`,
+	},
+	{
+		Value:     &Service{Port: &Port{Number: "80"}},
+		ExpectXML: `<service><host><port>80</port></host></service>`,
+	},
+	{
+		Value:     &Service{},
+		ExpectXML: `<service></service>`,
+	},
+	{
+		Value: &Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},
+		ExpectXML: `<service>` +
+			`<host><port>80</port></host>` +
+			`<Extra1>A</Extra1>` +
+			`<host><extra2>B</extra2></host>` +
+			`</service>`,
+		MarshalOnly: true,
+	},
+	{
+		Value: &Service{Port: &Port{Number: "80"}, Extra2: "example"},
+		ExpectXML: `<service>` +
+			`<host><port>80</port></host>` +
+			`<host><extra2>example</extra2></host>` +
+			`</service>`,
+		MarshalOnly: true,
+	},
+
+	// Test struct embedding
+	{
+		Value: &EmbedA{
+			EmbedC: EmbedC{
+				FieldA1: "", // Shadowed by A.A
+				FieldA2: "", // Shadowed by A.A
+				FieldB:  "A.C.B",
+				FieldC:  "A.C.C",
+			},
+			EmbedB: EmbedB{
+				FieldB: "A.B.B",
+				EmbedC: EmbedC{
+					FieldA1: "A.B.C.A1",
+					FieldA2: "A.B.C.A2",
+					FieldB:  "", // Shadowed by A.B.B
+					FieldC:  "A.B.C.C",
+				},
+			},
+			FieldA: "A.A",
+		},
+		ExpectXML: `<EmbedA>` +
+			`<FieldB>A.C.B</FieldB>` +
+			`<FieldC>A.C.C</FieldC>` +
+			`<EmbedB>` +
+			`<FieldB>A.B.B</FieldB>` +
+			`<FieldA>` +
+			`<A1>A.B.C.A1</A1>` +
+			`<A2>A.B.C.A2</A2>` +
+			`</FieldA>` +
+			`<FieldC>A.B.C.C</FieldC>` +
+			`</EmbedB>` +
+			`<FieldA>A.A</FieldA>` +
+			`</EmbedA>`,
+	},
+
+	// Test that name casing matters
+	{
+		Value:     &NameCasing{Xy: "mixed", XY: "upper", XyA: "mixedA", XYA: "upperA"},
+		ExpectXML: `<casing Xy="mixedA" XY="upperA"><Xy>mixed</Xy><XY>upper</XY></casing>`,
+	},
+
+	// Test the order in which the XML element name is chosen
+	{
+		Value: &NamePrecedence{
+			FromTag:     XMLNameWithoutTag{Value: "A"},
+			FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "InXMLName"}, Value: "B"},
+			FromNameTag: XMLNameWithTag{Value: "C"},
+			InFieldName: "D",
+		},
+		ExpectXML: `<Parent>` +
+			`<InTag><Value>A</Value></InTag>` +
+			`<InXMLName><Value>B</Value></InXMLName>` +
+			`<InXMLNameTag><Value>C</Value></InXMLNameTag>` +
+			`<InFieldName>D</InFieldName>` +
+			`</Parent>`,
+		MarshalOnly: true,
+	},
+	{
+		Value: &NamePrecedence{
+			XMLName:     Name{Local: "Parent"},
+			FromTag:     XMLNameWithoutTag{XMLName: Name{Local: "InTag"}, Value: "A"},
+			FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "FromNameVal"}, Value: "B"},
+			FromNameTag: XMLNameWithTag{XMLName: Name{Local: "InXMLNameTag"}, Value: "C"},
+			InFieldName: "D",
+		},
+		ExpectXML: `<Parent>` +
+			`<InTag><Value>A</Value></InTag>` +
+			`<FromNameVal><Value>B</Value></FromNameVal>` +
+			`<InXMLNameTag><Value>C</Value></InXMLNameTag>` +
+			`<InFieldName>D</InFieldName>` +
+			`</Parent>`,
+		UnmarshalOnly: true,
+	},
+
+	// xml.Name works in a plain field as well.
+	{
+		Value:     &NameInField{Name{Space: "ns", Local: "foo"}},
+		ExpectXML: `<NameInField><foo xmlns="ns"></foo></NameInField>`,
+	},
+
+	// Marshaling zero xml.Name uses the tag or field name.
+	{
+		Value:       &NameInField{},
+		ExpectXML:   `<NameInField><foo xmlns="ns"></foo></NameInField>`,
+		MarshalOnly: true,
+	},
+
+	// Test attributes
+	{
+		Value: &AttrTest{
+			Int:   8,
+			Lower: 9,
+			Float: 23.5,
+			Uint8: 255,
+			Bool:  true,
+			Str:   "s",
+		},
+		ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="s"></AttrTest>`,
+	},
+
+	// Test ",any"
+	{
+		ExpectXML: `<a><nested><value>known</value></nested><other><sub>unknown</sub></other></a>`,
+		Value: &AnyTest{
+			Nested: "known",
+			AnyField: AnyHolder{
+				XMLName: Name{Local: "other"},
+				XML:     "<sub>unknown</sub>",
+			},
+		},
+		UnmarshalOnly: true,
+	},
+	{
+		Value:       &AnyTest{Nested: "known", AnyField: AnyHolder{XML: "<unknown/>"}},
+		ExpectXML:   `<a><nested><value>known</value></nested></a>`,
+		MarshalOnly: true,
+	},
+
+	// Test recursive types.
+	{
+		Value: &RecurseA{
+			A: "a1",
+			B: &RecurseB{
+				A: &RecurseA{"a2", nil},
+				B: "b1",
+			},
+		},
+		ExpectXML: `<RecurseA><A>a1</A><B><A><A>a2</A></A><B>b1</B></B></RecurseA>`,
+	},
+
+	// Test ignoring fields via "-" tag
+	{
+		ExpectXML: `<IgnoreTest></IgnoreTest>`,
+		Value:     &IgnoreTest{},
+	},
+	{
+		ExpectXML:   `<IgnoreTest></IgnoreTest>`,
+		Value:       &IgnoreTest{PublicSecret: "can't tell"},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IgnoreTest><PublicSecret>ignore me</PublicSecret></IgnoreTest>`,
+		Value:         &IgnoreTest{},
+		UnmarshalOnly: true,
+	},
+}
+
+func TestMarshal(t *testing.T) {
+	for idx, test := range marshalTests {
+		if test.UnmarshalOnly {
+			continue
+		}
+		data, err := Marshal(test.Value)
+		if err != nil {
+			t.Errorf("#%d: Error: %s", idx, err)
+			continue
+		}
+		if got, want := string(data), test.ExpectXML; got != want {
+			if strings.Contains(want, "\n") {
+				t.Errorf("#%d: marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", idx, test.Value, got, want)
+			} else {
+				t.Errorf("#%d: marshal(%#v):\nhave %#q\nwant %#q", idx, test.Value, got, want)
+			}
+		}
+	}
+}
+
+var marshalErrorTests = []struct {
+	Value interface{}
+	Err   string
+	Kind  reflect.Kind
+}{
+	{
+		Value: make(chan bool),
+		Err:   "xml: unsupported type: chan bool",
+		Kind:  reflect.Chan,
+	},
+	{
+		Value: map[string]string{
+			"question": "What do you get when you multiply six by nine?",
+			"answer":   "42",
+		},
+		Err:  "xml: unsupported type: map[string]string",
+		Kind: reflect.Map,
+	},
+	{
+		Value: map[*Ship]bool{nil: false},
+		Err:   "xml: unsupported type: map[*xml.Ship]bool",
+		Kind:  reflect.Map,
+	},
+	{
+		Value: &Domain{Comment: []byte("f--bar")},
+		Err:   `xml: comments must not contain "--"`,
+	},
+}
+
+func TestMarshalErrors(t *testing.T) {
+	for idx, test := range marshalErrorTests {
+		_, err := Marshal(test.Value)
+		if err == nil || err.Error() != test.Err {
+			t.Errorf("#%d: marshal(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)
+		}
+		if test.Kind != reflect.Invalid {
+			if kind := err.(*UnsupportedTypeError).Type.Kind(); kind != test.Kind {
+				t.Errorf("#%d: marshal(%#v) = [error kind] %s, want %s", idx, test.Value, kind, test.Kind)
+			}
+		}
+	}
+}
+
+// Do invertibility testing on the various structures that we test
+func TestUnmarshal(t *testing.T) {
+	for i, test := range marshalTests {
+		if test.MarshalOnly {
+			continue
+		}
+		if _, ok := test.Value.(*Plain); ok {
+			continue
+		}
+
+		vt := reflect.TypeOf(test.Value)
+		dest := reflect.New(vt.Elem()).Interface()
+		err := Unmarshal([]byte(test.ExpectXML), dest)
+
+		switch fix := dest.(type) {
+		case *Feed:
+			fix.Author.InnerXML = ""
+			for i := range fix.Entry {
+				fix.Entry[i].Author.InnerXML = ""
+			}
+		}
+
+		if err != nil {
+			t.Errorf("#%d: unexpected error: %#v", i, err)
+		} else if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
+			t.Errorf("#%d: unmarshal(%q):\nhave %#v\nwant %#v", i, test.ExpectXML, got, want)
+		}
+	}
+}
+
+func BenchmarkMarshal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Marshal(atomValue)
+	}
+}
+
+func BenchmarkUnmarshal(b *testing.B) {
+	xml := []byte(atomXml)
+	for i := 0; i < b.N; i++ {
+		Unmarshal(xml, &Feed{})
+	}
+}
diff --git a/src/pkg/encoding/xml/read.go b/src/pkg/encoding/xml/read.go
new file mode 100644
index 0000000..871fe05
--- /dev/null
+++ b/src/pkg/encoding/xml/read.go
@@ -0,0 +1,564 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xml
+
+import (
+	"bytes"
+	"errors"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
+// an XML element is an order-dependent collection of anonymous
+// values, while a data structure is an order-independent collection
+// of named values.
+// See package json for a textual representation more suitable
+// to data structures.
+
+// Unmarshal parses the XML-encoded data and stores the result in
+// the value pointed to by v, which must be an arbitrary struct,
+// slice, or string. Well-formed data that does not fit into v is
+// discarded.
+//
+// For example, given these definitions:
+//
+//	type Email struct {
+//		Where string `xml:",attr"`
+//		Addr  string
+//	}
+//
+//	type Result struct {
+//		XMLName xml.Name `xml:"result"`
+//		Name	string
+//		Phone	string
+//		Email	[]Email
+//		Groups  []string `xml:"group>value"`
+//	}
+//
+//	result := Result{Name: "name", Phone: "phone", Email: nil}
+//
+// unmarshalling the XML input
+//
+//	<result>
+//		<email where="home">
+//			<addr>gre at example.com</addr>
+//		</email>
+//		<email where='work'>
+//			<addr>gre at work.com</addr>
+//		</email>
+//		<name>Grace R. Emlin</name>
+// 		<group>
+// 			<value>Friends</value>
+// 			<value>Squash</value>
+// 		</group>
+//		<address>123 Main Street</address>
+//	</result>
+//
+// via Unmarshal(data, &result) is equivalent to assigning
+//
+//	r = Result{
+//		xml.Name{Local: "result"},
+//		"Grace R. Emlin", // name
+//		"phone",	  // no phone given
+//		[]Email{
+//			Email{"home", "gre at example.com"},
+//			Email{"work", "gre at work.com"},
+//		},
+//		[]string{"Friends", "Squash"},
+//	}
+//
+// Note that the field r.Phone has not been modified and
+// that the XML <address> element was discarded. Also, the field
+// Groups was assigned considering the element path provided in the
+// field tag.
+//
+// Because Unmarshal uses the reflect package, it can only assign
+// to exported (upper case) fields.  Unmarshal uses a case-sensitive
+// comparison to match XML element names to tag values and struct
+// field names.
+//
+// Unmarshal maps an XML element to a struct using the following rules.
+// In the rules, the tag of a field refers to the value associated with the
+// key 'xml' in the struct field's tag (see the example above).
+//
+//   * If the struct has a field of type []byte or string with tag
+//      ",innerxml", Unmarshal accumulates the raw XML nested inside the
+//      element in that field.  The rest of the rules still apply.
+//
+//   * If the struct has a field named XMLName of type xml.Name,
+//      Unmarshal records the element name in that field.
+//
+//   * If the XMLName field has an associated tag of the form
+//      "name" or "namespace-URL name", the XML element must have
+//      the given name (and, optionally, name space) or else Unmarshal
+//      returns an error.
+//
+//   * If the XML element has an attribute whose name matches a
+//      struct field name with an associated tag containing ",attr" or
+//      the explicit name in a struct field tag of the form "name,attr",
+//      Unmarshal records the attribute value in that field.
+//
+//   * If the XML element contains character data, that data is
+//      accumulated in the first struct field that has tag "chardata".
+//      The struct field may have type []byte or string.
+//      If there is no such field, the character data is discarded.
+//
+//   * If the XML element contains comments, they are accumulated in
+//      the first struct field that has tag ",comments".  The struct
+//      field may have type []byte or string.  If there is no such
+//      field, the comments are discarded.
+//
+//   * If the XML element contains a sub-element whose name matches
+//      the prefix of a tag formatted as "a" or "a>b>c", unmarshal
+//      will descend into the XML structure looking for elements with the
+//      given names, and will map the innermost elements to that struct
+//      field. A tag starting with ">" is equivalent to one starting
+//      with the field name followed by ">".
+//
+//   * If the XML element contains a sub-element whose name matches
+//      a struct field's XMLName tag and the struct field has no
+//      explicit name tag as per the previous rule, unmarshal maps
+//      the sub-element to that struct field.
+//
+//   * If the XML element contains a sub-element whose name matches a
+//      field without any mode flags (",attr", ",chardata", etc), Unmarshal
+//      maps the sub-element to that struct field.
+//
+//   * If the XML element contains a sub-element that hasn't matched any
+//      of the above rules and the struct has a field with tag ",any",
+//      unmarshal maps the sub-element to that struct field.
+//
+//   * A struct field with tag "-" is never unmarshalled into.
+//
+// Unmarshal maps an XML element to a string or []byte by saving the
+// concatenation of that element's character data in the string or
+// []byte. The saved []byte is never nil.
+//
+// Unmarshal maps an attribute value to a string or []byte by saving
+// the value in the string or slice.
+//
+// Unmarshal maps an XML element to a slice by extending the length of
+// the slice and mapping the element to the newly created value.
+//
+// Unmarshal maps an XML element or attribute value to a bool by
+// setting it to the boolean value represented by the string.
+//
+// Unmarshal maps an XML element or attribute value to an integer or
+// floating-point field by setting the field to the result of
+// interpreting the string value in decimal.  There is no check for
+// overflow.
+//
+// Unmarshal maps an XML element to an xml.Name by recording the
+// element name.
+//
+// Unmarshal maps an XML element to a pointer by setting the pointer
+// to a freshly allocated value and then mapping the element to that value.
+//
+func Unmarshal(data []byte, v interface{}) error {
+	return NewDecoder(bytes.NewBuffer(data)).Decode(v)
+}
+
+// Decode works like xml.Unmarshal, except it reads the decoder
+// stream to find the start element.
+func (d *Decoder) Decode(v interface{}) error {
+	return d.DecodeElement(v, nil)
+}
+
+// DecodeElement works like xml.Unmarshal except that it takes
+// a pointer to the start XML element to decode into v.
+// It is useful when a client reads some raw XML tokens itself
+// but also wants to defer to Unmarshal for some elements.
+func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
+	val := reflect.ValueOf(v)
+	if val.Kind() != reflect.Ptr {
+		return errors.New("non-pointer passed to Unmarshal")
+	}
+	return d.unmarshal(val.Elem(), start)
+}
+
+// An UnmarshalError represents an error in the unmarshalling process.
+type UnmarshalError string
+
+func (e UnmarshalError) Error() string { return string(e) }
+
+// Unmarshal a single XML element into val.
+func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
+	// Find start element if we need it.
+	if start == nil {
+		for {
+			tok, err := p.Token()
+			if err != nil {
+				return err
+			}
+			if t, ok := tok.(StartElement); ok {
+				start = &t
+				break
+			}
+		}
+	}
+
+	if pv := val; pv.Kind() == reflect.Ptr {
+		if pv.IsNil() {
+			pv.Set(reflect.New(pv.Type().Elem()))
+		}
+		val = pv.Elem()
+	}
+
+	var (
+		data         []byte
+		saveData     reflect.Value
+		comment      []byte
+		saveComment  reflect.Value
+		saveXML      reflect.Value
+		saveXMLIndex int
+		saveXMLData  []byte
+		saveAny      reflect.Value
+		sv           reflect.Value
+		tinfo        *typeInfo
+		err          error
+	)
+
+	switch v := val; v.Kind() {
+	default:
+		return errors.New("unknown type " + v.Type().String())
+
+	case reflect.Interface:
+		// TODO: For now, simply ignore the field. In the near
+		//       future we may choose to unmarshal the start
+		//       element on it, if not nil.
+		return p.Skip()
+
+	case reflect.Slice:
+		typ := v.Type()
+		if typ.Elem().Kind() == reflect.Uint8 {
+			// []byte
+			saveData = v
+			break
+		}
+
+		// Slice of element values.
+		// Grow slice.
+		n := v.Len()
+		if n >= v.Cap() {
+			ncap := 2 * n
+			if ncap < 4 {
+				ncap = 4
+			}
+			new := reflect.MakeSlice(typ, n, ncap)
+			reflect.Copy(new, v)
+			v.Set(new)
+		}
+		v.SetLen(n + 1)
+
+		// Recur to read element into slice.
+		if err := p.unmarshal(v.Index(n), start); err != nil {
+			v.SetLen(n)
+			return err
+		}
+		return nil
+
+	case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String:
+		saveData = v
+
+	case reflect.Struct:
+		sv = v
+		typ := sv.Type()
+		if typ == nameType {
+			v.Set(reflect.ValueOf(start.Name))
+			break
+		}
+		tinfo, err = getTypeInfo(typ)
+		if err != nil {
+			return err
+		}
+
+		// Validate and assign element name.
+		if tinfo.xmlname != nil {
+			finfo := tinfo.xmlname
+			if finfo.name != "" && finfo.name != start.Name.Local {
+				return UnmarshalError("expected element type <" + finfo.name + "> but have <" + start.Name.Local + ">")
+			}
+			if finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
+				e := "expected element <" + finfo.name + "> in name space " + finfo.xmlns + " but have "
+				if start.Name.Space == "" {
+					e += "no name space"
+				} else {
+					e += start.Name.Space
+				}
+				return UnmarshalError(e)
+			}
+			fv := sv.FieldByIndex(finfo.idx)
+			if _, ok := fv.Interface().(Name); ok {
+				fv.Set(reflect.ValueOf(start.Name))
+			}
+		}
+
+		// Assign attributes.
+		// Also, determine whether we need to save character data or comments.
+		for i := range tinfo.fields {
+			finfo := &tinfo.fields[i]
+			switch finfo.flags & fMode {
+			case fAttr:
+				strv := sv.FieldByIndex(finfo.idx)
+				// Look for attribute.
+				for _, a := range start.Attr {
+					if a.Name.Local == finfo.name {
+						copyValue(strv, []byte(a.Value))
+						break
+					}
+				}
+
+			case fCharData:
+				if !saveData.IsValid() {
+					saveData = sv.FieldByIndex(finfo.idx)
+				}
+
+			case fComment:
+				if !saveComment.IsValid() {
+					saveComment = sv.FieldByIndex(finfo.idx)
+				}
+
+			case fAny:
+				if !saveAny.IsValid() {
+					saveAny = sv.FieldByIndex(finfo.idx)
+				}
+
+			case fInnerXml:
+				if !saveXML.IsValid() {
+					saveXML = sv.FieldByIndex(finfo.idx)
+					if p.saved == nil {
+						saveXMLIndex = 0
+						p.saved = new(bytes.Buffer)
+					} else {
+						saveXMLIndex = p.savedOffset()
+					}
+				}
+			}
+		}
+	}
+
+	// Find end element.
+	// Process sub-elements along the way.
+Loop:
+	for {
+		var savedOffset int
+		if saveXML.IsValid() {
+			savedOffset = p.savedOffset()
+		}
+		tok, err := p.Token()
+		if err != nil {
+			return err
+		}
+		switch t := tok.(type) {
+		case StartElement:
+			consumed := false
+			if sv.IsValid() {
+				consumed, err = p.unmarshalPath(tinfo, sv, nil, &t)
+				if err != nil {
+					return err
+				}
+				if !consumed && saveAny.IsValid() {
+					consumed = true
+					if err := p.unmarshal(saveAny, &t); err != nil {
+						return err
+					}
+				}
+			}
+			if !consumed {
+				if err := p.Skip(); err != nil {
+					return err
+				}
+			}
+
+		case EndElement:
+			if saveXML.IsValid() {
+				saveXMLData = p.saved.Bytes()[saveXMLIndex:savedOffset]
+				if saveXMLIndex == 0 {
+					p.saved = nil
+				}
+			}
+			break Loop
+
+		case CharData:
+			if saveData.IsValid() {
+				data = append(data, t...)
+			}
+
+		case Comment:
+			if saveComment.IsValid() {
+				comment = append(comment, t...)
+			}
+		}
+	}
+
+	if err := copyValue(saveData, data); err != nil {
+		return err
+	}
+
+	switch t := saveComment; t.Kind() {
+	case reflect.String:
+		t.SetString(string(comment))
+	case reflect.Slice:
+		t.Set(reflect.ValueOf(comment))
+	}
+
+	switch t := saveXML; t.Kind() {
+	case reflect.String:
+		t.SetString(string(saveXMLData))
+	case reflect.Slice:
+		t.Set(reflect.ValueOf(saveXMLData))
+	}
+
+	return nil
+}
+
+func copyValue(dst reflect.Value, src []byte) (err error) {
+	// Helper functions for integer and unsigned integer conversions
+	var itmp int64
+	getInt64 := func() bool {
+		itmp, err = strconv.ParseInt(string(src), 10, 64)
+		// TODO: should check sizes
+		return err == nil
+	}
+	var utmp uint64
+	getUint64 := func() bool {
+		utmp, err = strconv.ParseUint(string(src), 10, 64)
+		// TODO: check for overflow?
+		return err == nil
+	}
+	var ftmp float64
+	getFloat64 := func() bool {
+		ftmp, err = strconv.ParseFloat(string(src), 64)
+		// TODO: check for overflow?
+		return err == nil
+	}
+
+	// Save accumulated data.
+	switch t := dst; t.Kind() {
+	case reflect.Invalid:
+		// Probably a comment.
+	default:
+		return errors.New("cannot happen: unknown type " + t.Type().String())
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		if !getInt64() {
+			return err
+		}
+		t.SetInt(itmp)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		if !getUint64() {
+			return err
+		}
+		t.SetUint(utmp)
+	case reflect.Float32, reflect.Float64:
+		if !getFloat64() {
+			return err
+		}
+		t.SetFloat(ftmp)
+	case reflect.Bool:
+		value, err := strconv.ParseBool(strings.TrimSpace(string(src)))
+		if err != nil {
+			return err
+		}
+		t.SetBool(value)
+	case reflect.String:
+		t.SetString(string(src))
+	case reflect.Slice:
+		if len(src) == 0 {
+			// non-nil to flag presence
+			src = []byte{}
+		}
+		t.SetBytes(src)
+	}
+	return nil
+}
+
+// unmarshalPath walks down an XML structure looking for wanted
+// paths, and calls unmarshal on them.
+// The consumed result tells whether XML elements have been consumed
+// from the Decoder until start's matching end element, or if it's
+// still untouched because start is uninteresting for sv's fields.
+func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
+	recurse := false
+Loop:
+	for i := range tinfo.fields {
+		finfo := &tinfo.fields[i]
+		if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) {
+			continue
+		}
+		for j := range parents {
+			if parents[j] != finfo.parents[j] {
+				continue Loop
+			}
+		}
+		if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
+			// It's a perfect match, unmarshal the field.
+			return true, p.unmarshal(sv.FieldByIndex(finfo.idx), start)
+		}
+		if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
+			// It's a prefix for the field. Break and recurse
+			// since it's not ok for one field path to be itself
+			// the prefix for another field path.
+			recurse = true
+
+			// We can reuse the same slice as long as we
+			// don't try to append to it.
+			parents = finfo.parents[:len(parents)+1]
+			break
+		}
+	}
+	if !recurse {
+		// We have no business with this element.
+		return false, nil
+	}
+	// The element is not a perfect match for any field, but one
+	// or more fields have the path to this element as a parent
+	// prefix. Recurse and attempt to match these.
+	for {
+		var tok Token
+		tok, err = p.Token()
+		if err != nil {
+			return true, err
+		}
+		switch t := tok.(type) {
+		case StartElement:
+			consumed2, err := p.unmarshalPath(tinfo, sv, parents, &t)
+			if err != nil {
+				return true, err
+			}
+			if !consumed2 {
+				if err := p.Skip(); err != nil {
+					return true, err
+				}
+			}
+		case EndElement:
+			return true, nil
+		}
+	}
+	panic("unreachable")
+}
+
+// Have already read a start element.
+// Read tokens until we find the end element.
+// Token is taking care of making sure the
+// end element matches the start element we saw.
+func (p *Decoder) Skip() error {
+	for {
+		tok, err := p.Token()
+		if err != nil {
+			return err
+		}
+		switch tok.(type) {
+		case StartElement:
+			if err := p.Skip(); err != nil {
+				return err
+			}
+		case EndElement:
+			return nil
+		}
+	}
+	panic("unreachable")
+}
diff --git a/src/pkg/encoding/xml/read_test.go b/src/pkg/encoding/xml/read_test.go
new file mode 100644
index 0000000..833eafc
--- /dev/null
+++ b/src/pkg/encoding/xml/read_test.go
@@ -0,0 +1,358 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xml
+
+import (
+	"reflect"
+	"testing"
+)
+
+// Stripped down Atom feed data structures.
+
+func TestUnmarshalFeed(t *testing.T) {
+	var f Feed
+	if err := Unmarshal([]byte(atomFeedString), &f); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if !reflect.DeepEqual(f, atomFeed) {
+		t.Fatalf("have %#v\nwant %#v", f, atomFeed)
+	}
+}
+
+// hget http://codereview.appspot.com/rss/mine/rsc
+const atomFeedString = `
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><link href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></link><id>http://codereview.appspot.com/</id><updated>2009-10-04T01:35:58+00:00</updated><author><name>rietveld<></name></author><entry><title>rietveld: an attempt at pubsubhubbub
+</title><link href="http://codereview.appspot.com/126085" rel="alternate"></link><updated>2009-10-04T01:35:58+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:134d9179c41f806be79b3a5f7877d19a</id><summary type="html">
+  An attempt at adding pubsubhubbub support to Rietveld.
+http://code.google.com/p/pubsubhubbub
+http://code.google.com/p/rietveld/issues/detail?id=155
+
+The server side of the protocol is trivial:
+  1. add a &lt;link rel=&quot;hub&quot; href=&quot;hub-server&quot;&gt; tag to all
+     feeds that will be pubsubhubbubbed.
+  2. every time one of those feeds changes, tell the hub
+     with a simple POST request.
+
+I have tested this by adding debug prints to a local hub
+server and checking that the server got the right publish
+requests.
+
+I can&#39;t quite get the server to work, but I think the bug
+is not in my code.  I think that the server expects to be
+able to grab the feed and see the feed&#39;s actual URL in
+the link rel=&quot;self&quot;, but the default value for that drops
+the :port from the URL, and I cannot for the life of me
+figure out how to get the Atom generator deep inside
+django not to do that, or even where it is doing that,
+or even what code is running to generate the Atom feed.
+(I thought I knew but I added some assert False statements
+and it kept running!)
+
+Ignoring that particular problem, I would appreciate
+feedback on the right way to get the two values at
+the top of feeds.py marked NOTE(rsc).
+
+
+</summary></entry><entry><title>rietveld: correct tab handling
+</title><link href="http://codereview.appspot.com/124106" rel="alternate"></link><updated>2009-10-03T23:02:17+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:0a2a4f19bb815101f0ba2904aed7c35a</id><summary type="html">
+  This fixes the buggy tab rendering that can be seen at
+http://codereview.appspot.com/116075/diff/1/2
+
+The fundamental problem was that the tab code was
+not being told what column the text began in, so it
+didn&#39;t know where to put the tab stops.  Another problem
+was that some of the code assumed that string byte
+offsets were the same as column offsets, which is only
+true if there are no tabs.
+
+In the process of fixing this, I cleaned up the arguments
+to Fold and ExpandTabs and renamed them Break and
+_ExpandTabs so that I could be sure that I found all the
+call sites.  I also wanted to verify that ExpandTabs was
+not being used from outside intra_region_diff.py.
+
+
+</summary></entry></feed> 	   `
+
+type Feed struct {
+	XMLName Name    `xml:"http://www.w3.org/2005/Atom feed"`
+	Title   string  `xml:"title"`
+	Id      string  `xml:"id"`
+	Link    []Link  `xml:"link"`
+	Updated Time    `xml:"updated"`
+	Author  Person  `xml:"author"`
+	Entry   []Entry `xml:"entry"`
+}
+
+type Entry struct {
+	Title   string `xml:"title"`
+	Id      string `xml:"id"`
+	Link    []Link `xml:"link"`
+	Updated Time   `xml:"updated"`
+	Author  Person `xml:"author"`
+	Summary Text   `xml:"summary"`
+}
+
+type Link struct {
+	Rel  string `xml:"rel,attr"`
+	Href string `xml:"href,attr"`
+}
+
+type Person struct {
+	Name     string `xml:"name"`
+	URI      string `xml:"uri"`
+	Email    string `xml:"email"`
+	InnerXML string `xml:",innerxml"`
+}
+
+type Text struct {
+	Type string `xml:"type,attr"`
+	Body string `xml:",chardata"`
+}
+
+type Time string
+
+var atomFeed = Feed{
+	XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
+	Title:   "Code Review - My issues",
+	Link: []Link{
+		{Rel: "alternate", Href: "http://codereview.appspot.com/"},
+		{Rel: "self", Href: "http://codereview.appspot.com/rss/mine/rsc"},
+	},
+	Id:      "http://codereview.appspot.com/",
+	Updated: "2009-10-04T01:35:58+00:00",
+	Author: Person{
+		Name:     "rietveld<>",
+		InnerXML: "<name>rietveld<></name>",
+	},
+	Entry: []Entry{
+		{
+			Title: "rietveld: an attempt at pubsubhubbub\n",
+			Link: []Link{
+				{Rel: "alternate", Href: "http://codereview.appspot.com/126085"},
+			},
+			Updated: "2009-10-04T01:35:58+00:00",
+			Author: Person{
+				Name:     "email-address-removed",
+				InnerXML: "<name>email-address-removed</name>",
+			},
+			Id: "urn:md5:134d9179c41f806be79b3a5f7877d19a",
+			Summary: Text{
+				Type: "html",
+				Body: `
+  An attempt at adding pubsubhubbub support to Rietveld.
+http://code.google.com/p/pubsubhubbub
+http://code.google.com/p/rietveld/issues/detail?id=155
+
+The server side of the protocol is trivial:
+  1. add a <link rel="hub" href="hub-server"> tag to all
+     feeds that will be pubsubhubbubbed.
+  2. every time one of those feeds changes, tell the hub
+     with a simple POST request.
+
+I have tested this by adding debug prints to a local hub
+server and checking that the server got the right publish
+requests.
+
+I can't quite get the server to work, but I think the bug
+is not in my code.  I think that the server expects to be
+able to grab the feed and see the feed's actual URL in
+the link rel="self", but the default value for that drops
+the :port from the URL, and I cannot for the life of me
+figure out how to get the Atom generator deep inside
+django not to do that, or even where it is doing that,
+or even what code is running to generate the Atom feed.
+(I thought I knew but I added some assert False statements
+and it kept running!)
+
+Ignoring that particular problem, I would appreciate
+feedback on the right way to get the two values at
+the top of feeds.py marked NOTE(rsc).
+
+
+`,
+			},
+		},
+		{
+			Title: "rietveld: correct tab handling\n",
+			Link: []Link{
+				{Rel: "alternate", Href: "http://codereview.appspot.com/124106"},
+			},
+			Updated: "2009-10-03T23:02:17+00:00",
+			Author: Person{
+				Name:     "email-address-removed",
+				InnerXML: "<name>email-address-removed</name>",
+			},
+			Id: "urn:md5:0a2a4f19bb815101f0ba2904aed7c35a",
+			Summary: Text{
+				Type: "html",
+				Body: `
+  This fixes the buggy tab rendering that can be seen at
+http://codereview.appspot.com/116075/diff/1/2
+
+The fundamental problem was that the tab code was
+not being told what column the text began in, so it
+didn't know where to put the tab stops.  Another problem
+was that some of the code assumed that string byte
+offsets were the same as column offsets, which is only
+true if there are no tabs.
+
+In the process of fixing this, I cleaned up the arguments
+to Fold and ExpandTabs and renamed them Break and
+_ExpandTabs so that I could be sure that I found all the
+call sites.  I also wanted to verify that ExpandTabs was
+not being used from outside intra_region_diff.py.
+
+
+`,
+			},
+		},
+	},
+}
+
+const pathTestString = `
+<Result>
+    <Before>1</Before>
+    <Items>
+        <Item1>
+            <Value>A</Value>
+        </Item1>
+        <Item2>
+            <Value>B</Value>
+        </Item2>
+        <Item1>
+            <Value>C</Value>
+            <Value>D</Value>
+        </Item1>
+        <_>
+            <Value>E</Value>
+        </_>
+    </Items>
+    <After>2</After>
+</Result>
+`
+
+type PathTestItem struct {
+	Value string
+}
+
+type PathTestA struct {
+	Items         []PathTestItem `xml:">Item1"`
+	Before, After string
+}
+
+type PathTestB struct {
+	Other         []PathTestItem `xml:"Items>Item1"`
+	Before, After string
+}
+
+type PathTestC struct {
+	Values1       []string `xml:"Items>Item1>Value"`
+	Values2       []string `xml:"Items>Item2>Value"`
+	Before, After string
+}
+
+type PathTestSet struct {
+	Item1 []PathTestItem
+}
+
+type PathTestD struct {
+	Other         PathTestSet `xml:"Items"`
+	Before, After string
+}
+
+type PathTestE struct {
+	Underline     string `xml:"Items>_>Value"`
+	Before, After string
+}
+
+var pathTests = []interface{}{
+	&PathTestA{Items: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
+	&PathTestB{Other: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
+	&PathTestC{Values1: []string{"A", "C", "D"}, Values2: []string{"B"}, Before: "1", After: "2"},
+	&PathTestD{Other: PathTestSet{Item1: []PathTestItem{{"A"}, {"D"}}}, Before: "1", After: "2"},
+	&PathTestE{Underline: "E", Before: "1", After: "2"},
+}
+
+func TestUnmarshalPaths(t *testing.T) {
+	for _, pt := range pathTests {
+		v := reflect.New(reflect.TypeOf(pt).Elem()).Interface()
+		if err := Unmarshal([]byte(pathTestString), v); err != nil {
+			t.Fatalf("Unmarshal: %s", err)
+		}
+		if !reflect.DeepEqual(v, pt) {
+			t.Fatalf("have %#v\nwant %#v", v, pt)
+		}
+	}
+}
+
+type BadPathTestA struct {
+	First  string `xml:"items>item1"`
+	Other  string `xml:"items>item2"`
+	Second string `xml:"items"`
+}
+
+type BadPathTestB struct {
+	Other  string `xml:"items>item2>value"`
+	First  string `xml:"items>item1"`
+	Second string `xml:"items>item1>value"`
+}
+
+type BadPathTestC struct {
+	First  string
+	Second string `xml:"First"`
+}
+
+type BadPathTestD struct {
+	BadPathEmbeddedA
+	BadPathEmbeddedB
+}
+
+type BadPathEmbeddedA struct {
+	First string
+}
+
+type BadPathEmbeddedB struct {
+	Second string `xml:"First"`
+}
+
+var badPathTests = []struct {
+	v, e interface{}
+}{
+	{&BadPathTestA{}, &TagPathError{reflect.TypeOf(BadPathTestA{}), "First", "items>item1", "Second", "items"}},
+	{&BadPathTestB{}, &TagPathError{reflect.TypeOf(BadPathTestB{}), "First", "items>item1", "Second", "items>item1>value"}},
+	{&BadPathTestC{}, &TagPathError{reflect.TypeOf(BadPathTestC{}), "First", "", "Second", "First"}},
+	{&BadPathTestD{}, &TagPathError{reflect.TypeOf(BadPathTestD{}), "First", "", "Second", "First"}},
+}
+
+func TestUnmarshalBadPaths(t *testing.T) {
+	for _, tt := range badPathTests {
+		err := Unmarshal([]byte(pathTestString), tt.v)
+		if !reflect.DeepEqual(err, tt.e) {
+			t.Fatalf("Unmarshal with %#v didn't fail properly:\nhave %#v,\nwant %#v", tt.v, err, tt.e)
+		}
+	}
+}
+
+const OK = "OK"
+const withoutNameTypeData = `
+<?xml version="1.0" charset="utf-8"?>
+<Test3 Attr="OK" />`
+
+type TestThree struct {
+	XMLName Name   `xml:"Test3"`
+	Attr    string `xml:",attr"`
+}
+
+func TestUnmarshalWithoutNameType(t *testing.T) {
+	var x TestThree
+	if err := Unmarshal([]byte(withoutNameTypeData), &x); err != nil {
+		t.Fatalf("Unmarshal: %s", err)
+	}
+	if x.Attr != OK {
+		t.Fatalf("have %v\nwant %v", x.Attr, OK)
+	}
+}
diff --git a/src/pkg/encoding/xml/typeinfo.go b/src/pkg/encoding/xml/typeinfo.go
new file mode 100644
index 0000000..2bf2c6b
--- /dev/null
+++ b/src/pkg/encoding/xml/typeinfo.go
@@ -0,0 +1,322 @@
+// Copyright 2011 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 xml
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+	"sync"
+)
+
+// typeInfo holds details for the xml representation of a type.
+type typeInfo struct {
+	xmlname *fieldInfo
+	fields  []fieldInfo
+}
+
+// fieldInfo holds details for the xml representation of a single field.
+type fieldInfo struct {
+	idx     []int
+	name    string
+	xmlns   string
+	flags   fieldFlags
+	parents []string
+}
+
+type fieldFlags int
+
+const (
+	fElement fieldFlags = 1 << iota
+	fAttr
+	fCharData
+	fInnerXml
+	fComment
+	fAny
+
+	// TODO:
+	//fOmitEmpty
+
+	fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
+)
+
+var tinfoMap = make(map[reflect.Type]*typeInfo)
+var tinfoLock sync.RWMutex
+
+var nameType = reflect.TypeOf(Name{})
+
+// getTypeInfo returns the typeInfo structure with details necessary
+// for marshalling and unmarshalling typ.
+func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
+	tinfoLock.RLock()
+	tinfo, ok := tinfoMap[typ]
+	tinfoLock.RUnlock()
+	if ok {
+		return tinfo, nil
+	}
+	tinfo = &typeInfo{}
+	if typ.Kind() == reflect.Struct && typ != nameType {
+		n := typ.NumField()
+		for i := 0; i < n; i++ {
+			f := typ.Field(i)
+			if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
+				continue // Private field
+			}
+
+			// For embedded structs, embed its fields.
+			if f.Anonymous {
+				if f.Type.Kind() != reflect.Struct {
+					continue
+				}
+				inner, err := getTypeInfo(f.Type)
+				if err != nil {
+					return nil, err
+				}
+				for _, finfo := range inner.fields {
+					finfo.idx = append([]int{i}, finfo.idx...)
+					if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
+						return nil, err
+					}
+				}
+				continue
+			}
+
+			finfo, err := structFieldInfo(typ, &f)
+			if err != nil {
+				return nil, err
+			}
+
+			if f.Name == "XMLName" {
+				tinfo.xmlname = finfo
+				continue
+			}
+
+			// Add the field if it doesn't conflict with other fields.
+			if err := addFieldInfo(typ, tinfo, finfo); err != nil {
+				return nil, err
+			}
+		}
+	}
+	tinfoLock.Lock()
+	tinfoMap[typ] = tinfo
+	tinfoLock.Unlock()
+	return tinfo, nil
+}
+
+// structFieldInfo builds and returns a fieldInfo for f.
+func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, error) {
+	finfo := &fieldInfo{idx: f.Index}
+
+	// Split the tag from the xml namespace if necessary.
+	tag := f.Tag.Get("xml")
+	if i := strings.Index(tag, " "); i >= 0 {
+		finfo.xmlns, tag = tag[:i], tag[i+1:]
+	}
+
+	// Parse flags.
+	tokens := strings.Split(tag, ",")
+	if len(tokens) == 1 {
+		finfo.flags = fElement
+	} else {
+		tag = tokens[0]
+		for _, flag := range tokens[1:] {
+			switch flag {
+			case "attr":
+				finfo.flags |= fAttr
+			case "chardata":
+				finfo.flags |= fCharData
+			case "innerxml":
+				finfo.flags |= fInnerXml
+			case "comment":
+				finfo.flags |= fComment
+			case "any":
+				finfo.flags |= fAny
+			}
+		}
+
+		// Validate the flags used.
+		switch mode := finfo.flags & fMode; mode {
+		case 0:
+			finfo.flags |= fElement
+		case fAttr, fCharData, fInnerXml, fComment, fAny:
+			if f.Name != "XMLName" && (tag == "" || mode == fAttr) {
+				break
+			}
+			fallthrough
+		default:
+			// This will also catch multiple modes in a single field.
+			return nil, fmt.Errorf("xml: invalid tag in field %s of type %s: %q",
+				f.Name, typ, f.Tag.Get("xml"))
+		}
+	}
+
+	// Use of xmlns without a name is not allowed.
+	if finfo.xmlns != "" && tag == "" {
+		return nil, fmt.Errorf("xml: namespace without name in field %s of type %s: %q",
+			f.Name, typ, f.Tag.Get("xml"))
+	}
+
+	if f.Name == "XMLName" {
+		// The XMLName field records the XML element name. Don't
+		// process it as usual because its name should default to
+		// empty rather than to the field name.
+		finfo.name = tag
+		return finfo, nil
+	}
+
+	if tag == "" {
+		// If the name part of the tag is completely empty, get
+		// default from XMLName of underlying struct if feasible,
+		// or field name otherwise.
+		if xmlname := lookupXMLName(f.Type); xmlname != nil {
+			finfo.xmlns, finfo.name = xmlname.xmlns, xmlname.name
+		} else {
+			finfo.name = f.Name
+		}
+		return finfo, nil
+	}
+
+	// Prepare field name and parents.
+	tokens = strings.Split(tag, ">")
+	if tokens[0] == "" {
+		tokens[0] = f.Name
+	}
+	if tokens[len(tokens)-1] == "" {
+		return nil, fmt.Errorf("xml: trailing '>' in field %s of type %s", f.Name, typ)
+	}
+	finfo.name = tokens[len(tokens)-1]
+	if len(tokens) > 1 {
+		finfo.parents = tokens[:len(tokens)-1]
+	}
+
+	// If the field type has an XMLName field, the names must match
+	// so that the behavior of both marshalling and unmarshalling
+	// is straighforward and unambiguous.
+	if finfo.flags&fElement != 0 {
+		ftyp := f.Type
+		xmlname := lookupXMLName(ftyp)
+		if xmlname != nil && xmlname.name != finfo.name {
+			return nil, fmt.Errorf("xml: name %q in tag of %s.%s conflicts with name %q in %s.XMLName",
+				finfo.name, typ, f.Name, xmlname.name, ftyp)
+		}
+	}
+	return finfo, nil
+}
+
+// lookupXMLName returns the fieldInfo for typ's XMLName field
+// in case it exists and has a valid xml field tag, otherwise
+// it returns nil.
+func lookupXMLName(typ reflect.Type) (xmlname *fieldInfo) {
+	for typ.Kind() == reflect.Ptr {
+		typ = typ.Elem()
+	}
+	if typ.Kind() != reflect.Struct {
+		return nil
+	}
+	for i, n := 0, typ.NumField(); i < n; i++ {
+		f := typ.Field(i)
+		if f.Name != "XMLName" {
+			continue
+		}
+		finfo, err := structFieldInfo(typ, &f)
+		if finfo.name != "" && err == nil {
+			return finfo
+		}
+		// Also consider errors as a non-existent field tag
+		// and let getTypeInfo itself report the error.
+		break
+	}
+	return nil
+}
+
+func min(a, b int) int {
+	if a <= b {
+		return a
+	}
+	return b
+}
+
+// addFieldInfo adds finfo to tinfo.fields if there are no
+// conflicts, or if conflicts arise from previous fields that were
+// obtained from deeper embedded structures than finfo. In the latter
+// case, the conflicting entries are dropped.
+// A conflict occurs when the path (parent + name) to a field is
+// itself a prefix of another path, or when two paths match exactly.
+// It is okay for field paths to share a common, shorter prefix.
+func addFieldInfo(typ reflect.Type, tinfo *typeInfo, newf *fieldInfo) error {
+	var conflicts []int
+Loop:
+	// First, figure all conflicts. Most working code will have none.
+	for i := range tinfo.fields {
+		oldf := &tinfo.fields[i]
+		if oldf.flags&fMode != newf.flags&fMode {
+			continue
+		}
+		minl := min(len(newf.parents), len(oldf.parents))
+		for p := 0; p < minl; p++ {
+			if oldf.parents[p] != newf.parents[p] {
+				continue Loop
+			}
+		}
+		if len(oldf.parents) > len(newf.parents) {
+			if oldf.parents[len(newf.parents)] == newf.name {
+				conflicts = append(conflicts, i)
+			}
+		} else if len(oldf.parents) < len(newf.parents) {
+			if newf.parents[len(oldf.parents)] == oldf.name {
+				conflicts = append(conflicts, i)
+			}
+		} else {
+			if newf.name == oldf.name {
+				conflicts = append(conflicts, i)
+			}
+		}
+	}
+	// Without conflicts, add the new field and return.
+	if conflicts == nil {
+		tinfo.fields = append(tinfo.fields, *newf)
+		return nil
+	}
+
+	// If any conflict is shallower, ignore the new field.
+	// This matches the Go field resolution on embedding.
+	for _, i := range conflicts {
+		if len(tinfo.fields[i].idx) < len(newf.idx) {
+			return nil
+		}
+	}
+
+	// Otherwise, if any of them is at the same depth level, it's an error.
+	for _, i := range conflicts {
+		oldf := &tinfo.fields[i]
+		if len(oldf.idx) == len(newf.idx) {
+			f1 := typ.FieldByIndex(oldf.idx)
+			f2 := typ.FieldByIndex(newf.idx)
+			return &TagPathError{typ, f1.Name, f1.Tag.Get("xml"), f2.Name, f2.Tag.Get("xml")}
+		}
+	}
+
+	// Otherwise, the new field is shallower, and thus takes precedence,
+	// so drop the conflicting fields from tinfo and append the new one.
+	for c := len(conflicts) - 1; c >= 0; c-- {
+		i := conflicts[c]
+		copy(tinfo.fields[i:], tinfo.fields[i+1:])
+		tinfo.fields = tinfo.fields[:len(tinfo.fields)-1]
+	}
+	tinfo.fields = append(tinfo.fields, *newf)
+	return nil
+}
+
+// A TagPathError represents an error in the unmarshalling process
+// caused by the use of field tags with conflicting paths.
+type TagPathError struct {
+	Struct       reflect.Type
+	Field1, Tag1 string
+	Field2, Tag2 string
+}
+
+func (e *TagPathError) Error() string {
+	return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2)
+}
diff --git a/src/pkg/encoding/xml/xml.go b/src/pkg/encoding/xml/xml.go
new file mode 100644
index 0000000..5066f5c
--- /dev/null
+++ b/src/pkg/encoding/xml/xml.go
@@ -0,0 +1,1697 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package xml implements a simple XML 1.0 parser that
+// understands XML name spaces.
+package xml
+
+// References:
+//    Annotated XML spec: http://www.xml.com/axml/testaxml.htm
+//    XML name spaces: http://www.w3.org/TR/REC-xml-names/
+
+// TODO(rsc):
+//	Test error handling.
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// A SyntaxError represents a syntax error in the XML input stream.
+type SyntaxError struct {
+	Msg  string
+	Line int
+}
+
+func (e *SyntaxError) Error() string {
+	return "XML syntax error on line " + strconv.Itoa(e.Line) + ": " + e.Msg
+}
+
+// A Name represents an XML name (Local) annotated
+// with a name space identifier (Space).
+// In tokens returned by Decoder.Token, the Space identifier
+// is given as a canonical URL, not the short prefix used
+// in the document being parsed.
+type Name struct {
+	Space, Local string
+}
+
+// An Attr represents an attribute in an XML element (Name=Value).
+type Attr struct {
+	Name  Name
+	Value string
+}
+
+// A Token is an interface holding one of the token types:
+// StartElement, EndElement, CharData, Comment, ProcInst, or Directive.
+type Token interface{}
+
+// A StartElement represents an XML start element.
+type StartElement struct {
+	Name Name
+	Attr []Attr
+}
+
+func (e StartElement) Copy() StartElement {
+	attrs := make([]Attr, len(e.Attr))
+	copy(attrs, e.Attr)
+	e.Attr = attrs
+	return e
+}
+
+// An EndElement represents an XML end element.
+type EndElement struct {
+	Name Name
+}
+
+// A CharData represents XML character data (raw text),
+// in which XML escape sequences have been replaced by
+// the characters they represent.
+type CharData []byte
+
+func makeCopy(b []byte) []byte {
+	b1 := make([]byte, len(b))
+	copy(b1, b)
+	return b1
+}
+
+func (c CharData) Copy() CharData { return CharData(makeCopy(c)) }
+
+// A Comment represents an XML comment of the form <!--comment-->.
+// The bytes do not include the <!-- and --> comment markers.
+type Comment []byte
+
+func (c Comment) Copy() Comment { return Comment(makeCopy(c)) }
+
+// A ProcInst represents an XML processing instruction of the form <?target inst?>
+type ProcInst struct {
+	Target string
+	Inst   []byte
+}
+
+func (p ProcInst) Copy() ProcInst {
+	p.Inst = makeCopy(p.Inst)
+	return p
+}
+
+// A Directive represents an XML directive of the form <!text>.
+// The bytes do not include the <! and > markers.
+type Directive []byte
+
+func (d Directive) Copy() Directive { return Directive(makeCopy(d)) }
+
+// CopyToken returns a copy of a Token.
+func CopyToken(t Token) Token {
+	switch v := t.(type) {
+	case CharData:
+		return v.Copy()
+	case Comment:
+		return v.Copy()
+	case Directive:
+		return v.Copy()
+	case ProcInst:
+		return v.Copy()
+	case StartElement:
+		return v.Copy()
+	}
+	return t
+}
+
+// A Decoder represents an XML parser reading a particular input stream.
+// The parser assumes that its input is encoded in UTF-8.
+type Decoder struct {
+	// Strict defaults to true, enforcing the requirements
+	// of the XML specification.
+	// If set to false, the parser allows input containing common
+	// mistakes:
+	//	* If an element is missing an end tag, the parser invents
+	//	  end tags as necessary to keep the return values from Token
+	//	  properly balanced.
+	//	* In attribute values and character data, unknown or malformed
+	//	  character entities (sequences beginning with &) are left alone.
+	//
+	// Setting:
+	//
+	//	d.Strict = false;
+	//	d.AutoClose = HTMLAutoClose;
+	//	d.Entity = HTMLEntity
+	//
+	// creates a parser that can handle typical HTML.
+	Strict bool
+
+	// When Strict == false, AutoClose indicates a set of elements to
+	// consider closed immediately after they are opened, regardless
+	// of whether an end element is present.
+	AutoClose []string
+
+	// Entity can be used to map non-standard entity names to string replacements.
+	// The parser behaves as if these standard mappings are present in the map,
+	// regardless of the actual map content:
+	//
+	//	"lt": "<",
+	//	"gt": ">",
+	//	"amp": "&",
+	//	"apos": "'",
+	//	"quot": `"`,
+	Entity map[string]string
+
+	// CharsetReader, if non-nil, defines a function to generate
+	// charset-conversion readers, converting from the provided
+	// non-UTF-8 charset into UTF-8. If CharsetReader is nil or
+	// returns an error, parsing stops with an error. One of the
+	// the CharsetReader's result values must be non-nil.
+	CharsetReader func(charset string, input io.Reader) (io.Reader, error)
+
+	r         io.ByteReader
+	buf       bytes.Buffer
+	saved     *bytes.Buffer
+	stk       *stack
+	free      *stack
+	needClose bool
+	toClose   Name
+	nextToken Token
+	nextByte  int
+	ns        map[string]string
+	err       error
+	line      int
+	tmp       [32]byte
+}
+
+// NewDecoder creates a new XML parser reading from r.
+func NewDecoder(r io.Reader) *Decoder {
+	d := &Decoder{
+		ns:       make(map[string]string),
+		nextByte: -1,
+		line:     1,
+		Strict:   true,
+	}
+	d.switchToReader(r)
+	return d
+}
+
+// Token returns the next XML token in the input stream.
+// At the end of the input stream, Token returns nil, io.EOF.
+//
+// Slices of bytes in the returned token data refer to the
+// parser's internal buffer and remain valid only until the next
+// call to Token.  To acquire a copy of the bytes, call CopyToken
+// or the token's Copy method.
+//
+// Token expands self-closing elements such as <br/>
+// into separate start and end elements returned by successive calls.
+//
+// Token guarantees that the StartElement and EndElement
+// tokens it returns are properly nested and matched:
+// if Token encounters an unexpected end element,
+// it will return an error.
+//
+// Token implements XML name spaces as described by
+// http://www.w3.org/TR/REC-xml-names/.  Each of the
+// Name structures contained in the Token has the Space
+// set to the URL identifying its name space when known.
+// If Token encounters an unrecognized name space prefix,
+// it uses the prefix as the Space rather than report an error.
+func (d *Decoder) Token() (t Token, err error) {
+	if d.nextToken != nil {
+		t = d.nextToken
+		d.nextToken = nil
+	} else if t, err = d.RawToken(); err != nil {
+		return
+	}
+
+	if !d.Strict {
+		if t1, ok := d.autoClose(t); ok {
+			d.nextToken = t
+			t = t1
+		}
+	}
+	switch t1 := t.(type) {
+	case StartElement:
+		// In XML name spaces, the translations listed in the
+		// attributes apply to the element name and
+		// to the other attribute names, so process
+		// the translations first.
+		for _, a := range t1.Attr {
+			if a.Name.Space == "xmlns" {
+				v, ok := d.ns[a.Name.Local]
+				d.pushNs(a.Name.Local, v, ok)
+				d.ns[a.Name.Local] = a.Value
+			}
+			if a.Name.Space == "" && a.Name.Local == "xmlns" {
+				// Default space for untagged names
+				v, ok := d.ns[""]
+				d.pushNs("", v, ok)
+				d.ns[""] = a.Value
+			}
+		}
+
+		d.translate(&t1.Name, true)
+		for i := range t1.Attr {
+			d.translate(&t1.Attr[i].Name, false)
+		}
+		d.pushElement(t1.Name)
+		t = t1
+
+	case EndElement:
+		d.translate(&t1.Name, true)
+		if !d.popElement(&t1) {
+			return nil, d.err
+		}
+		t = t1
+	}
+	return
+}
+
+// Apply name space translation to name n.
+// The default name space (for Space=="")
+// applies only to element names, not to attribute names.
+func (d *Decoder) translate(n *Name, isElementName bool) {
+	switch {
+	case n.Space == "xmlns":
+		return
+	case n.Space == "" && !isElementName:
+		return
+	case n.Space == "" && n.Local == "xmlns":
+		return
+	}
+	if v, ok := d.ns[n.Space]; ok {
+		n.Space = v
+	}
+}
+
+func (d *Decoder) switchToReader(r io.Reader) {
+	// Get efficient byte at a time reader.
+	// Assume that if reader has its own
+	// ReadByte, it's efficient enough.
+	// Otherwise, use bufio.
+	if rb, ok := r.(io.ByteReader); ok {
+		d.r = rb
+	} else {
+		d.r = bufio.NewReader(r)
+	}
+}
+
+// Parsing state - stack holds old name space translations
+// and the current set of open elements.  The translations to pop when
+// ending a given tag are *below* it on the stack, which is
+// more work but forced on us by XML.
+type stack struct {
+	next *stack
+	kind int
+	name Name
+	ok   bool
+}
+
+const (
+	stkStart = iota
+	stkNs
+)
+
+func (d *Decoder) push(kind int) *stack {
+	s := d.free
+	if s != nil {
+		d.free = s.next
+	} else {
+		s = new(stack)
+	}
+	s.next = d.stk
+	s.kind = kind
+	d.stk = s
+	return s
+}
+
+func (d *Decoder) pop() *stack {
+	s := d.stk
+	if s != nil {
+		d.stk = s.next
+		s.next = d.free
+		d.free = s
+	}
+	return s
+}
+
+// Record that we are starting an element with the given name.
+func (d *Decoder) pushElement(name Name) {
+	s := d.push(stkStart)
+	s.name = name
+}
+
+// Record that we are changing the value of ns[local].
+// The old value is url, ok.
+func (d *Decoder) pushNs(local string, url string, ok bool) {
+	s := d.push(stkNs)
+	s.name.Local = local
+	s.name.Space = url
+	s.ok = ok
+}
+
+// Creates a SyntaxError with the current line number.
+func (d *Decoder) syntaxError(msg string) error {
+	return &SyntaxError{Msg: msg, Line: d.line}
+}
+
+// Record that we are ending an element with the given name.
+// The name must match the record at the top of the stack,
+// which must be a pushElement record.
+// After popping the element, apply any undo records from
+// the stack to restore the name translations that existed
+// before we saw this element.
+func (d *Decoder) popElement(t *EndElement) bool {
+	s := d.pop()
+	name := t.Name
+	switch {
+	case s == nil || s.kind != stkStart:
+		d.err = d.syntaxError("unexpected end element </" + name.Local + ">")
+		return false
+	case s.name.Local != name.Local:
+		if !d.Strict {
+			d.needClose = true
+			d.toClose = t.Name
+			t.Name = s.name
+			return true
+		}
+		d.err = d.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
+		return false
+	case s.name.Space != name.Space:
+		d.err = d.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
+			"closed by </" + name.Local + "> in space " + name.Space)
+		return false
+	}
+
+	// Pop stack until a Start is on the top, undoing the
+	// translations that were associated with the element we just closed.
+	for d.stk != nil && d.stk.kind != stkStart {
+		s := d.pop()
+		if s.ok {
+			d.ns[s.name.Local] = s.name.Space
+		} else {
+			delete(d.ns, s.name.Local)
+		}
+	}
+
+	return true
+}
+
+// If the top element on the stack is autoclosing and
+// t is not the end tag, invent the end tag.
+func (d *Decoder) autoClose(t Token) (Token, bool) {
+	if d.stk == nil || d.stk.kind != stkStart {
+		return nil, false
+	}
+	name := strings.ToLower(d.stk.name.Local)
+	for _, s := range d.AutoClose {
+		if strings.ToLower(s) == name {
+			// This one should be auto closed if t doesn't close it.
+			et, ok := t.(EndElement)
+			if !ok || et.Name.Local != name {
+				return EndElement{d.stk.name}, true
+			}
+			break
+		}
+	}
+	return nil, false
+}
+
+// RawToken is like Token but does not verify that
+// start and end elements match and does not translate
+// name space prefixes to their corresponding URLs.
+func (d *Decoder) RawToken() (Token, error) {
+	if d.err != nil {
+		return nil, d.err
+	}
+	if d.needClose {
+		// The last element we read was self-closing and
+		// we returned just the StartElement half.
+		// Return the EndElement half now.
+		d.needClose = false
+		return EndElement{d.toClose}, nil
+	}
+
+	b, ok := d.getc()
+	if !ok {
+		return nil, d.err
+	}
+
+	if b != '<' {
+		// Text section.
+		d.ungetc(b)
+		data := d.text(-1, false)
+		if data == nil {
+			return nil, d.err
+		}
+		return CharData(data), nil
+	}
+
+	if b, ok = d.mustgetc(); !ok {
+		return nil, d.err
+	}
+	switch b {
+	case '/':
+		// </: End element
+		var name Name
+		if name, ok = d.nsname(); !ok {
+			if d.err == nil {
+				d.err = d.syntaxError("expected element name after </")
+			}
+			return nil, d.err
+		}
+		d.space()
+		if b, ok = d.mustgetc(); !ok {
+			return nil, d.err
+		}
+		if b != '>' {
+			d.err = d.syntaxError("invalid characters between </" + name.Local + " and >")
+			return nil, d.err
+		}
+		return EndElement{name}, nil
+
+	case '?':
+		// <?: Processing instruction.
+		// TODO(rsc): Should parse the <?xml declaration to make sure
+		// the version is 1.0 and the encoding is UTF-8.
+		var target string
+		if target, ok = d.name(); !ok {
+			if d.err == nil {
+				d.err = d.syntaxError("expected target name after <?")
+			}
+			return nil, d.err
+		}
+		d.space()
+		d.buf.Reset()
+		var b0 byte
+		for {
+			if b, ok = d.mustgetc(); !ok {
+				return nil, d.err
+			}
+			d.buf.WriteByte(b)
+			if b0 == '?' && b == '>' {
+				break
+			}
+			b0 = b
+		}
+		data := d.buf.Bytes()
+		data = data[0 : len(data)-2] // chop ?>
+
+		if target == "xml" {
+			enc := procInstEncoding(string(data))
+			if enc != "" && enc != "utf-8" && enc != "UTF-8" {
+				if d.CharsetReader == nil {
+					d.err = fmt.Errorf("xml: encoding %q declared but Decoder.CharsetReader is nil", enc)
+					return nil, d.err
+				}
+				newr, err := d.CharsetReader(enc, d.r.(io.Reader))
+				if err != nil {
+					d.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
+					return nil, d.err
+				}
+				if newr == nil {
+					panic("CharsetReader returned a nil Reader for charset " + enc)
+				}
+				d.switchToReader(newr)
+			}
+		}
+		return ProcInst{target, data}, nil
+
+	case '!':
+		// <!: Maybe comment, maybe CDATA.
+		if b, ok = d.mustgetc(); !ok {
+			return nil, d.err
+		}
+		switch b {
+		case '-': // <!-
+			// Probably <!-- for a comment.
+			if b, ok = d.mustgetc(); !ok {
+				return nil, d.err
+			}
+			if b != '-' {
+				d.err = d.syntaxError("invalid sequence <!- not part of <!--")
+				return nil, d.err
+			}
+			// Look for terminator.
+			d.buf.Reset()
+			var b0, b1 byte
+			for {
+				if b, ok = d.mustgetc(); !ok {
+					return nil, d.err
+				}
+				d.buf.WriteByte(b)
+				if b0 == '-' && b1 == '-' && b == '>' {
+					break
+				}
+				b0, b1 = b1, b
+			}
+			data := d.buf.Bytes()
+			data = data[0 : len(data)-3] // chop -->
+			return Comment(data), nil
+
+		case '[': // <![
+			// Probably <![CDATA[.
+			for i := 0; i < 6; i++ {
+				if b, ok = d.mustgetc(); !ok {
+					return nil, d.err
+				}
+				if b != "CDATA["[i] {
+					d.err = d.syntaxError("invalid <![ sequence")
+					return nil, d.err
+				}
+			}
+			// Have <![CDATA[.  Read text until ]]>.
+			data := d.text(-1, true)
+			if data == nil {
+				return nil, d.err
+			}
+			return CharData(data), nil
+		}
+
+		// Probably a directive: <!DOCTYPE ...>, <!ENTITY ...>, etc.
+		// We don't care, but accumulate for caller. Quoted angle
+		// brackets do not count for nesting.
+		d.buf.Reset()
+		d.buf.WriteByte(b)
+		inquote := uint8(0)
+		depth := 0
+		for {
+			if b, ok = d.mustgetc(); !ok {
+				return nil, d.err
+			}
+			if inquote == 0 && b == '>' && depth == 0 {
+				break
+			}
+			d.buf.WriteByte(b)
+			switch {
+			case b == inquote:
+				inquote = 0
+
+			case inquote != 0:
+				// in quotes, no special action
+
+			case b == '\'' || b == '"':
+				inquote = b
+
+			case b == '>' && inquote == 0:
+				depth--
+
+			case b == '<' && inquote == 0:
+				depth++
+			}
+		}
+		return Directive(d.buf.Bytes()), nil
+	}
+
+	// Must be an open element like <a href="foo">
+	d.ungetc(b)
+
+	var (
+		name  Name
+		empty bool
+		attr  []Attr
+	)
+	if name, ok = d.nsname(); !ok {
+		if d.err == nil {
+			d.err = d.syntaxError("expected element name after <")
+		}
+		return nil, d.err
+	}
+
+	attr = make([]Attr, 0, 4)
+	for {
+		d.space()
+		if b, ok = d.mustgetc(); !ok {
+			return nil, d.err
+		}
+		if b == '/' {
+			empty = true
+			if b, ok = d.mustgetc(); !ok {
+				return nil, d.err
+			}
+			if b != '>' {
+				d.err = d.syntaxError("expected /> in element")
+				return nil, d.err
+			}
+			break
+		}
+		if b == '>' {
+			break
+		}
+		d.ungetc(b)
+
+		n := len(attr)
+		if n >= cap(attr) {
+			nattr := make([]Attr, n, 2*cap(attr))
+			copy(nattr, attr)
+			attr = nattr
+		}
+		attr = attr[0 : n+1]
+		a := &attr[n]
+		if a.Name, ok = d.nsname(); !ok {
+			if d.err == nil {
+				d.err = d.syntaxError("expected attribute name in element")
+			}
+			return nil, d.err
+		}
+		d.space()
+		if b, ok = d.mustgetc(); !ok {
+			return nil, d.err
+		}
+		if b != '=' {
+			if d.Strict {
+				d.err = d.syntaxError("attribute name without = in element")
+				return nil, d.err
+			} else {
+				d.ungetc(b)
+				a.Value = a.Name.Local
+			}
+		} else {
+			d.space()
+			data := d.attrval()
+			if data == nil {
+				return nil, d.err
+			}
+			a.Value = string(data)
+		}
+	}
+	if empty {
+		d.needClose = true
+		d.toClose = name
+	}
+	return StartElement{name, attr}, nil
+}
+
+func (d *Decoder) attrval() []byte {
+	b, ok := d.mustgetc()
+	if !ok {
+		return nil
+	}
+	// Handle quoted attribute values
+	if b == '"' || b == '\'' {
+		return d.text(int(b), false)
+	}
+	// Handle unquoted attribute values for strict parsers
+	if d.Strict {
+		d.err = d.syntaxError("unquoted or missing attribute value in element")
+		return nil
+	}
+	// Handle unquoted attribute values for unstrict parsers
+	d.ungetc(b)
+	d.buf.Reset()
+	for {
+		b, ok = d.mustgetc()
+		if !ok {
+			return nil
+		}
+		// http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
+		if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' ||
+			'0' <= b && b <= '9' || b == '_' || b == ':' || b == '-' {
+			d.buf.WriteByte(b)
+		} else {
+			d.ungetc(b)
+			break
+		}
+	}
+	return d.buf.Bytes()
+}
+
+// Skip spaces if any
+func (d *Decoder) space() {
+	for {
+		b, ok := d.getc()
+		if !ok {
+			return
+		}
+		switch b {
+		case ' ', '\r', '\n', '\t':
+		default:
+			d.ungetc(b)
+			return
+		}
+	}
+}
+
+// Read a single byte.
+// If there is no byte to read, return ok==false
+// and leave the error in d.err.
+// Maintain line number.
+func (d *Decoder) getc() (b byte, ok bool) {
+	if d.err != nil {
+		return 0, false
+	}
+	if d.nextByte >= 0 {
+		b = byte(d.nextByte)
+		d.nextByte = -1
+	} else {
+		b, d.err = d.r.ReadByte()
+		if d.err != nil {
+			return 0, false
+		}
+		if d.saved != nil {
+			d.saved.WriteByte(b)
+		}
+	}
+	if b == '\n' {
+		d.line++
+	}
+	return b, true
+}
+
+// Return saved offset.
+// If we did ungetc (nextByte >= 0), have to back up one.
+func (d *Decoder) savedOffset() int {
+	n := d.saved.Len()
+	if d.nextByte >= 0 {
+		n--
+	}
+	return n
+}
+
+// Must read a single byte.
+// If there is no byte to read,
+// set d.err to SyntaxError("unexpected EOF")
+// and return ok==false
+func (d *Decoder) mustgetc() (b byte, ok bool) {
+	if b, ok = d.getc(); !ok {
+		if d.err == io.EOF {
+			d.err = d.syntaxError("unexpected EOF")
+		}
+	}
+	return
+}
+
+// Unread a single byte.
+func (d *Decoder) ungetc(b byte) {
+	if b == '\n' {
+		d.line--
+	}
+	d.nextByte = int(b)
+}
+
+var entity = map[string]int{
+	"lt":   '<',
+	"gt":   '>',
+	"amp":  '&',
+	"apos": '\'',
+	"quot": '"',
+}
+
+// Read plain text section (XML calls it character data).
+// If quote >= 0, we are in a quoted string and need to find the matching quote.
+// If cdata == true, we are in a <![CDATA[ section and need to find ]]>.
+// On failure return nil and leave the error in d.err.
+func (d *Decoder) text(quote int, cdata bool) []byte {
+	var b0, b1 byte
+	var trunc int
+	d.buf.Reset()
+Input:
+	for {
+		b, ok := d.getc()
+		if !ok {
+			if cdata {
+				if d.err == io.EOF {
+					d.err = d.syntaxError("unexpected EOF in CDATA section")
+				}
+				return nil
+			}
+			break Input
+		}
+
+		// <![CDATA[ section ends with ]]>.
+		// It is an error for ]]> to appear in ordinary text.
+		if b0 == ']' && b1 == ']' && b == '>' {
+			if cdata {
+				trunc = 2
+				break Input
+			}
+			d.err = d.syntaxError("unescaped ]]> not in CDATA section")
+			return nil
+		}
+
+		// Stop reading text if we see a <.
+		if b == '<' && !cdata {
+			if quote >= 0 {
+				d.err = d.syntaxError("unescaped < inside quoted string")
+				return nil
+			}
+			d.ungetc('<')
+			break Input
+		}
+		if quote >= 0 && b == byte(quote) {
+			break Input
+		}
+		if b == '&' && !cdata {
+			// Read escaped character expression up to semicolon.
+			// XML in all its glory allows a document to define and use
+			// its own character names with <!ENTITY ...> directives.
+			// Parsers are required to recognize lt, gt, amp, apos, and quot
+			// even if they have not been declared.  That's all we allow.
+			var i int
+			for i = 0; i < len(d.tmp); i++ {
+				var ok bool
+				d.tmp[i], ok = d.getc()
+				if !ok {
+					if d.err == io.EOF {
+						d.err = d.syntaxError("unexpected EOF")
+					}
+					return nil
+				}
+				c := d.tmp[i]
+				if c == ';' {
+					break
+				}
+				if 'a' <= c && c <= 'z' ||
+					'A' <= c && c <= 'Z' ||
+					'0' <= c && c <= '9' ||
+					c == '_' || c == '#' {
+					continue
+				}
+				d.ungetc(c)
+				break
+			}
+			s := string(d.tmp[0:i])
+			if i >= len(d.tmp) {
+				if !d.Strict {
+					b0, b1 = 0, 0
+					d.buf.WriteByte('&')
+					d.buf.Write(d.tmp[0:i])
+					continue Input
+				}
+				d.err = d.syntaxError("character entity expression &" + s + "... too long")
+				return nil
+			}
+			var haveText bool
+			var text string
+			if i >= 2 && s[0] == '#' {
+				var n uint64
+				var err error
+				if i >= 3 && s[1] == 'x' {
+					n, err = strconv.ParseUint(s[2:], 16, 64)
+				} else {
+					n, err = strconv.ParseUint(s[1:], 10, 64)
+				}
+				if err == nil && n <= unicode.MaxRune {
+					text = string(n)
+					haveText = true
+				}
+			} else {
+				if r, ok := entity[s]; ok {
+					text = string(r)
+					haveText = true
+				} else if d.Entity != nil {
+					text, haveText = d.Entity[s]
+				}
+			}
+			if !haveText {
+				if !d.Strict {
+					b0, b1 = 0, 0
+					d.buf.WriteByte('&')
+					d.buf.Write(d.tmp[0:i])
+					continue Input
+				}
+				d.err = d.syntaxError("invalid character entity &" + s + ";")
+				return nil
+			}
+			d.buf.Write([]byte(text))
+			b0, b1 = 0, 0
+			continue Input
+		}
+		d.buf.WriteByte(b)
+		b0, b1 = b1, b
+	}
+	data := d.buf.Bytes()
+	data = data[0 : len(data)-trunc]
+
+	// Inspect each rune for being a disallowed character.
+	buf := data
+	for len(buf) > 0 {
+		r, size := utf8.DecodeRune(buf)
+		if r == utf8.RuneError && size == 1 {
+			d.err = d.syntaxError("invalid UTF-8")
+			return nil
+		}
+		buf = buf[size:]
+		if !isInCharacterRange(r) {
+			d.err = d.syntaxError(fmt.Sprintf("illegal character code %U", r))
+			return nil
+		}
+	}
+
+	// Must rewrite \r and \r\n into \n.
+	w := 0
+	for r := 0; r < len(data); r++ {
+		b := data[r]
+		if b == '\r' {
+			if r+1 < len(data) && data[r+1] == '\n' {
+				continue
+			}
+			b = '\n'
+		}
+		data[w] = b
+		w++
+	}
+	return data[0:w]
+}
+
+// Decide whether the given rune is in the XML Character Range, per
+// the Char production of http://www.xml.com/axml/testaxml.htm,
+// Section 2.2 Characters.
+func isInCharacterRange(r rune) (inrange bool) {
+	return r == 0x09 ||
+		r == 0x0A ||
+		r == 0x0D ||
+		r >= 0x20 && r <= 0xDF77 ||
+		r >= 0xE000 && r <= 0xFFFD ||
+		r >= 0x10000 && r <= 0x10FFFF
+}
+
+// Get name space name: name with a : stuck in the middle.
+// The part before the : is the name space identifier.
+func (d *Decoder) nsname() (name Name, ok bool) {
+	s, ok := d.name()
+	if !ok {
+		return
+	}
+	i := strings.Index(s, ":")
+	if i < 0 {
+		name.Local = s
+	} else {
+		name.Space = s[0:i]
+		name.Local = s[i+1:]
+	}
+	return name, true
+}
+
+// Get name: /first(first|second)*/
+// Do not set d.err if the name is missing (unless unexpected EOF is received):
+// let the caller provide better context.
+func (d *Decoder) name() (s string, ok bool) {
+	var b byte
+	if b, ok = d.mustgetc(); !ok {
+		return
+	}
+
+	// As a first approximation, we gather the bytes [A-Za-z_:.-\x80-\xFF]*
+	if b < utf8.RuneSelf && !isNameByte(b) {
+		d.ungetc(b)
+		return "", false
+	}
+	d.buf.Reset()
+	d.buf.WriteByte(b)
+	for {
+		if b, ok = d.mustgetc(); !ok {
+			return
+		}
+		if b < utf8.RuneSelf && !isNameByte(b) {
+			d.ungetc(b)
+			break
+		}
+		d.buf.WriteByte(b)
+	}
+
+	// Then we check the characters.
+	s = d.buf.String()
+	for i, c := range s {
+		if !unicode.Is(first, c) && (i == 0 || !unicode.Is(second, c)) {
+			d.err = d.syntaxError("invalid XML name: " + s)
+			return "", false
+		}
+	}
+	return s, true
+}
+
+func isNameByte(c byte) bool {
+	return 'A' <= c && c <= 'Z' ||
+		'a' <= c && c <= 'z' ||
+		'0' <= c && c <= '9' ||
+		c == '_' || c == ':' || c == '.' || c == '-'
+}
+
+// These tables were generated by cut and paste from Appendix B of
+// the XML spec at http://www.xml.com/axml/testaxml.htm
+// and then reformatting.  First corresponds to (Letter | '_' | ':')
+// and second corresponds to NameChar.
+
+var first = &unicode.RangeTable{
+	R16: []unicode.Range16{
+		{0x003A, 0x003A, 1},
+		{0x0041, 0x005A, 1},
+		{0x005F, 0x005F, 1},
+		{0x0061, 0x007A, 1},
+		{0x00C0, 0x00D6, 1},
+		{0x00D8, 0x00F6, 1},
+		{0x00F8, 0x00FF, 1},
+		{0x0100, 0x0131, 1},
+		{0x0134, 0x013E, 1},
+		{0x0141, 0x0148, 1},
+		{0x014A, 0x017E, 1},
+		{0x0180, 0x01C3, 1},
+		{0x01CD, 0x01F0, 1},
+		{0x01F4, 0x01F5, 1},
+		{0x01FA, 0x0217, 1},
+		{0x0250, 0x02A8, 1},
+		{0x02BB, 0x02C1, 1},
+		{0x0386, 0x0386, 1},
+		{0x0388, 0x038A, 1},
+		{0x038C, 0x038C, 1},
+		{0x038E, 0x03A1, 1},
+		{0x03A3, 0x03CE, 1},
+		{0x03D0, 0x03D6, 1},
+		{0x03DA, 0x03E0, 2},
+		{0x03E2, 0x03F3, 1},
+		{0x0401, 0x040C, 1},
+		{0x040E, 0x044F, 1},
+		{0x0451, 0x045C, 1},
+		{0x045E, 0x0481, 1},
+		{0x0490, 0x04C4, 1},
+		{0x04C7, 0x04C8, 1},
+		{0x04CB, 0x04CC, 1},
+		{0x04D0, 0x04EB, 1},
+		{0x04EE, 0x04F5, 1},
+		{0x04F8, 0x04F9, 1},
+		{0x0531, 0x0556, 1},
+		{0x0559, 0x0559, 1},
+		{0x0561, 0x0586, 1},
+		{0x05D0, 0x05EA, 1},
+		{0x05F0, 0x05F2, 1},
+		{0x0621, 0x063A, 1},
+		{0x0641, 0x064A, 1},
+		{0x0671, 0x06B7, 1},
+		{0x06BA, 0x06BE, 1},
+		{0x06C0, 0x06CE, 1},
+		{0x06D0, 0x06D3, 1},
+		{0x06D5, 0x06D5, 1},
+		{0x06E5, 0x06E6, 1},
+		{0x0905, 0x0939, 1},
+		{0x093D, 0x093D, 1},
+		{0x0958, 0x0961, 1},
+		{0x0985, 0x098C, 1},
+		{0x098F, 0x0990, 1},
+		{0x0993, 0x09A8, 1},
+		{0x09AA, 0x09B0, 1},
+		{0x09B2, 0x09B2, 1},
+		{0x09B6, 0x09B9, 1},
+		{0x09DC, 0x09DD, 1},
+		{0x09DF, 0x09E1, 1},
+		{0x09F0, 0x09F1, 1},
+		{0x0A05, 0x0A0A, 1},
+		{0x0A0F, 0x0A10, 1},
+		{0x0A13, 0x0A28, 1},
+		{0x0A2A, 0x0A30, 1},
+		{0x0A32, 0x0A33, 1},
+		{0x0A35, 0x0A36, 1},
+		{0x0A38, 0x0A39, 1},
+		{0x0A59, 0x0A5C, 1},
+		{0x0A5E, 0x0A5E, 1},
+		{0x0A72, 0x0A74, 1},
+		{0x0A85, 0x0A8B, 1},
+		{0x0A8D, 0x0A8D, 1},
+		{0x0A8F, 0x0A91, 1},
+		{0x0A93, 0x0AA8, 1},
+		{0x0AAA, 0x0AB0, 1},
+		{0x0AB2, 0x0AB3, 1},
+		{0x0AB5, 0x0AB9, 1},
+		{0x0ABD, 0x0AE0, 0x23},
+		{0x0B05, 0x0B0C, 1},
+		{0x0B0F, 0x0B10, 1},
+		{0x0B13, 0x0B28, 1},
+		{0x0B2A, 0x0B30, 1},
+		{0x0B32, 0x0B33, 1},
+		{0x0B36, 0x0B39, 1},
+		{0x0B3D, 0x0B3D, 1},
+		{0x0B5C, 0x0B5D, 1},
+		{0x0B5F, 0x0B61, 1},
+		{0x0B85, 0x0B8A, 1},
+		{0x0B8E, 0x0B90, 1},
+		{0x0B92, 0x0B95, 1},
+		{0x0B99, 0x0B9A, 1},
+		{0x0B9C, 0x0B9C, 1},
+		{0x0B9E, 0x0B9F, 1},
+		{0x0BA3, 0x0BA4, 1},
+		{0x0BA8, 0x0BAA, 1},
+		{0x0BAE, 0x0BB5, 1},
+		{0x0BB7, 0x0BB9, 1},
+		{0x0C05, 0x0C0C, 1},
+		{0x0C0E, 0x0C10, 1},
+		{0x0C12, 0x0C28, 1},
+		{0x0C2A, 0x0C33, 1},
+		{0x0C35, 0x0C39, 1},
+		{0x0C60, 0x0C61, 1},
+		{0x0C85, 0x0C8C, 1},
+		{0x0C8E, 0x0C90, 1},
+		{0x0C92, 0x0CA8, 1},
+		{0x0CAA, 0x0CB3, 1},
+		{0x0CB5, 0x0CB9, 1},
+		{0x0CDE, 0x0CDE, 1},
+		{0x0CE0, 0x0CE1, 1},
+		{0x0D05, 0x0D0C, 1},
+		{0x0D0E, 0x0D10, 1},
+		{0x0D12, 0x0D28, 1},
+		{0x0D2A, 0x0D39, 1},
+		{0x0D60, 0x0D61, 1},
+		{0x0E01, 0x0E2E, 1},
+		{0x0E30, 0x0E30, 1},
+		{0x0E32, 0x0E33, 1},
+		{0x0E40, 0x0E45, 1},
+		{0x0E81, 0x0E82, 1},
+		{0x0E84, 0x0E84, 1},
+		{0x0E87, 0x0E88, 1},
+		{0x0E8A, 0x0E8D, 3},
+		{0x0E94, 0x0E97, 1},
+		{0x0E99, 0x0E9F, 1},
+		{0x0EA1, 0x0EA3, 1},
+		{0x0EA5, 0x0EA7, 2},
+		{0x0EAA, 0x0EAB, 1},
+		{0x0EAD, 0x0EAE, 1},
+		{0x0EB0, 0x0EB0, 1},
+		{0x0EB2, 0x0EB3, 1},
+		{0x0EBD, 0x0EBD, 1},
+		{0x0EC0, 0x0EC4, 1},
+		{0x0F40, 0x0F47, 1},
+		{0x0F49, 0x0F69, 1},
+		{0x10A0, 0x10C5, 1},
+		{0x10D0, 0x10F6, 1},
+		{0x1100, 0x1100, 1},
+		{0x1102, 0x1103, 1},
+		{0x1105, 0x1107, 1},
+		{0x1109, 0x1109, 1},
+		{0x110B, 0x110C, 1},
+		{0x110E, 0x1112, 1},
+		{0x113C, 0x1140, 2},
+		{0x114C, 0x1150, 2},
+		{0x1154, 0x1155, 1},
+		{0x1159, 0x1159, 1},
+		{0x115F, 0x1161, 1},
+		{0x1163, 0x1169, 2},
+		{0x116D, 0x116E, 1},
+		{0x1172, 0x1173, 1},
+		{0x1175, 0x119E, 0x119E - 0x1175},
+		{0x11A8, 0x11AB, 0x11AB - 0x11A8},
+		{0x11AE, 0x11AF, 1},
+		{0x11B7, 0x11B8, 1},
+		{0x11BA, 0x11BA, 1},
+		{0x11BC, 0x11C2, 1},
+		{0x11EB, 0x11F0, 0x11F0 - 0x11EB},
+		{0x11F9, 0x11F9, 1},
+		{0x1E00, 0x1E9B, 1},
+		{0x1EA0, 0x1EF9, 1},
+		{0x1F00, 0x1F15, 1},
+		{0x1F18, 0x1F1D, 1},
+		{0x1F20, 0x1F45, 1},
+		{0x1F48, 0x1F4D, 1},
+		{0x1F50, 0x1F57, 1},
+		{0x1F59, 0x1F5B, 0x1F5B - 0x1F59},
+		{0x1F5D, 0x1F5D, 1},
+		{0x1F5F, 0x1F7D, 1},
+		{0x1F80, 0x1FB4, 1},
+		{0x1FB6, 0x1FBC, 1},
+		{0x1FBE, 0x1FBE, 1},
+		{0x1FC2, 0x1FC4, 1},
+		{0x1FC6, 0x1FCC, 1},
+		{0x1FD0, 0x1FD3, 1},
+		{0x1FD6, 0x1FDB, 1},
+		{0x1FE0, 0x1FEC, 1},
+		{0x1FF2, 0x1FF4, 1},
+		{0x1FF6, 0x1FFC, 1},
+		{0x2126, 0x2126, 1},
+		{0x212A, 0x212B, 1},
+		{0x212E, 0x212E, 1},
+		{0x2180, 0x2182, 1},
+		{0x3007, 0x3007, 1},
+		{0x3021, 0x3029, 1},
+		{0x3041, 0x3094, 1},
+		{0x30A1, 0x30FA, 1},
+		{0x3105, 0x312C, 1},
+		{0x4E00, 0x9FA5, 1},
+		{0xAC00, 0xD7A3, 1},
+	},
+}
+
+var second = &unicode.RangeTable{
+	R16: []unicode.Range16{
+		{0x002D, 0x002E, 1},
+		{0x0030, 0x0039, 1},
+		{0x00B7, 0x00B7, 1},
+		{0x02D0, 0x02D1, 1},
+		{0x0300, 0x0345, 1},
+		{0x0360, 0x0361, 1},
+		{0x0387, 0x0387, 1},
+		{0x0483, 0x0486, 1},
+		{0x0591, 0x05A1, 1},
+		{0x05A3, 0x05B9, 1},
+		{0x05BB, 0x05BD, 1},
+		{0x05BF, 0x05BF, 1},
+		{0x05C1, 0x05C2, 1},
+		{0x05C4, 0x0640, 0x0640 - 0x05C4},
+		{0x064B, 0x0652, 1},
+		{0x0660, 0x0669, 1},
+		{0x0670, 0x0670, 1},
+		{0x06D6, 0x06DC, 1},
+		{0x06DD, 0x06DF, 1},
+		{0x06E0, 0x06E4, 1},
+		{0x06E7, 0x06E8, 1},
+		{0x06EA, 0x06ED, 1},
+		{0x06F0, 0x06F9, 1},
+		{0x0901, 0x0903, 1},
+		{0x093C, 0x093C, 1},
+		{0x093E, 0x094C, 1},
+		{0x094D, 0x094D, 1},
+		{0x0951, 0x0954, 1},
+		{0x0962, 0x0963, 1},
+		{0x0966, 0x096F, 1},
+		{0x0981, 0x0983, 1},
+		{0x09BC, 0x09BC, 1},
+		{0x09BE, 0x09BF, 1},
+		{0x09C0, 0x09C4, 1},
+		{0x09C7, 0x09C8, 1},
+		{0x09CB, 0x09CD, 1},
+		{0x09D7, 0x09D7, 1},
+		{0x09E2, 0x09E3, 1},
+		{0x09E6, 0x09EF, 1},
+		{0x0A02, 0x0A3C, 0x3A},
+		{0x0A3E, 0x0A3F, 1},
+		{0x0A40, 0x0A42, 1},
+		{0x0A47, 0x0A48, 1},
+		{0x0A4B, 0x0A4D, 1},
+		{0x0A66, 0x0A6F, 1},
+		{0x0A70, 0x0A71, 1},
+		{0x0A81, 0x0A83, 1},
+		{0x0ABC, 0x0ABC, 1},
+		{0x0ABE, 0x0AC5, 1},
+		{0x0AC7, 0x0AC9, 1},
+		{0x0ACB, 0x0ACD, 1},
+		{0x0AE6, 0x0AEF, 1},
+		{0x0B01, 0x0B03, 1},
+		{0x0B3C, 0x0B3C, 1},
+		{0x0B3E, 0x0B43, 1},
+		{0x0B47, 0x0B48, 1},
+		{0x0B4B, 0x0B4D, 1},
+		{0x0B56, 0x0B57, 1},
+		{0x0B66, 0x0B6F, 1},
+		{0x0B82, 0x0B83, 1},
+		{0x0BBE, 0x0BC2, 1},
+		{0x0BC6, 0x0BC8, 1},
+		{0x0BCA, 0x0BCD, 1},
+		{0x0BD7, 0x0BD7, 1},
+		{0x0BE7, 0x0BEF, 1},
+		{0x0C01, 0x0C03, 1},
+		{0x0C3E, 0x0C44, 1},
+		{0x0C46, 0x0C48, 1},
+		{0x0C4A, 0x0C4D, 1},
+		{0x0C55, 0x0C56, 1},
+		{0x0C66, 0x0C6F, 1},
+		{0x0C82, 0x0C83, 1},
+		{0x0CBE, 0x0CC4, 1},
+		{0x0CC6, 0x0CC8, 1},
+		{0x0CCA, 0x0CCD, 1},
+		{0x0CD5, 0x0CD6, 1},
+		{0x0CE6, 0x0CEF, 1},
+		{0x0D02, 0x0D03, 1},
+		{0x0D3E, 0x0D43, 1},
+		{0x0D46, 0x0D48, 1},
+		{0x0D4A, 0x0D4D, 1},
+		{0x0D57, 0x0D57, 1},
+		{0x0D66, 0x0D6F, 1},
+		{0x0E31, 0x0E31, 1},
+		{0x0E34, 0x0E3A, 1},
+		{0x0E46, 0x0E46, 1},
+		{0x0E47, 0x0E4E, 1},
+		{0x0E50, 0x0E59, 1},
+		{0x0EB1, 0x0EB1, 1},
+		{0x0EB4, 0x0EB9, 1},
+		{0x0EBB, 0x0EBC, 1},
+		{0x0EC6, 0x0EC6, 1},
+		{0x0EC8, 0x0ECD, 1},
+		{0x0ED0, 0x0ED9, 1},
+		{0x0F18, 0x0F19, 1},
+		{0x0F20, 0x0F29, 1},
+		{0x0F35, 0x0F39, 2},
+		{0x0F3E, 0x0F3F, 1},
+		{0x0F71, 0x0F84, 1},
+		{0x0F86, 0x0F8B, 1},
+		{0x0F90, 0x0F95, 1},
+		{0x0F97, 0x0F97, 1},
+		{0x0F99, 0x0FAD, 1},
+		{0x0FB1, 0x0FB7, 1},
+		{0x0FB9, 0x0FB9, 1},
+		{0x20D0, 0x20DC, 1},
+		{0x20E1, 0x3005, 0x3005 - 0x20E1},
+		{0x302A, 0x302F, 1},
+		{0x3031, 0x3035, 1},
+		{0x3099, 0x309A, 1},
+		{0x309D, 0x309E, 1},
+		{0x30FC, 0x30FE, 1},
+	},
+}
+
+// HTMLEntity is an entity map containing translations for the
+// standard HTML entity characters.
+var HTMLEntity = htmlEntity
+
+var htmlEntity = map[string]string{
+	/*
+		hget http://www.w3.org/TR/html4/sgml/entities.html |
+		ssam '
+			,y /\>/ x/\<(.|\n)+/ s/\n/ /g
+			,x v/^\<!ENTITY/d
+			,s/\<!ENTITY ([^ ]+) .*U\+([0-9A-F][0-9A-F][0-9A-F][0-9A-F]) .+/	"\1": "\\u\2",/g
+		'
+	*/
+	"nbsp":     "\u00A0",
+	"iexcl":    "\u00A1",
+	"cent":     "\u00A2",
+	"pound":    "\u00A3",
+	"curren":   "\u00A4",
+	"yen":      "\u00A5",
+	"brvbar":   "\u00A6",
+	"sect":     "\u00A7",
+	"uml":      "\u00A8",
+	"copy":     "\u00A9",
+	"ordf":     "\u00AA",
+	"laquo":    "\u00AB",
+	"not":      "\u00AC",
+	"shy":      "\u00AD",
+	"reg":      "\u00AE",
+	"macr":     "\u00AF",
+	"deg":      "\u00B0",
+	"plusmn":   "\u00B1",
+	"sup2":     "\u00B2",
+	"sup3":     "\u00B3",
+	"acute":    "\u00B4",
+	"micro":    "\u00B5",
+	"para":     "\u00B6",
+	"middot":   "\u00B7",
+	"cedil":    "\u00B8",
+	"sup1":     "\u00B9",
+	"ordm":     "\u00BA",
+	"raquo":    "\u00BB",
+	"frac14":   "\u00BC",
+	"frac12":   "\u00BD",
+	"frac34":   "\u00BE",
+	"iquest":   "\u00BF",
+	"Agrave":   "\u00C0",
+	"Aacute":   "\u00C1",
+	"Acirc":    "\u00C2",
+	"Atilde":   "\u00C3",
+	"Auml":     "\u00C4",
+	"Aring":    "\u00C5",
+	"AElig":    "\u00C6",
+	"Ccedil":   "\u00C7",
+	"Egrave":   "\u00C8",
+	"Eacute":   "\u00C9",
+	"Ecirc":    "\u00CA",
+	"Euml":     "\u00CB",
+	"Igrave":   "\u00CC",
+	"Iacute":   "\u00CD",
+	"Icirc":    "\u00CE",
+	"Iuml":     "\u00CF",
+	"ETH":      "\u00D0",
+	"Ntilde":   "\u00D1",
+	"Ograve":   "\u00D2",
+	"Oacute":   "\u00D3",
+	"Ocirc":    "\u00D4",
+	"Otilde":   "\u00D5",
+	"Ouml":     "\u00D6",
+	"times":    "\u00D7",
+	"Oslash":   "\u00D8",
+	"Ugrave":   "\u00D9",
+	"Uacute":   "\u00DA",
+	"Ucirc":    "\u00DB",
+	"Uuml":     "\u00DC",
+	"Yacute":   "\u00DD",
+	"THORN":    "\u00DE",
+	"szlig":    "\u00DF",
+	"agrave":   "\u00E0",
+	"aacute":   "\u00E1",
+	"acirc":    "\u00E2",
+	"atilde":   "\u00E3",
+	"auml":     "\u00E4",
+	"aring":    "\u00E5",
+	"aelig":    "\u00E6",
+	"ccedil":   "\u00E7",
+	"egrave":   "\u00E8",
+	"eacute":   "\u00E9",
+	"ecirc":    "\u00EA",
+	"euml":     "\u00EB",
+	"igrave":   "\u00EC",
+	"iacute":   "\u00ED",
+	"icirc":    "\u00EE",
+	"iuml":     "\u00EF",
+	"eth":      "\u00F0",
+	"ntilde":   "\u00F1",
+	"ograve":   "\u00F2",
+	"oacute":   "\u00F3",
+	"ocirc":    "\u00F4",
+	"otilde":   "\u00F5",
+	"ouml":     "\u00F6",
+	"divide":   "\u00F7",
+	"oslash":   "\u00F8",
+	"ugrave":   "\u00F9",
+	"uacute":   "\u00FA",
+	"ucirc":    "\u00FB",
+	"uuml":     "\u00FC",
+	"yacute":   "\u00FD",
+	"thorn":    "\u00FE",
+	"yuml":     "\u00FF",
+	"fnof":     "\u0192",
+	"Alpha":    "\u0391",
+	"Beta":     "\u0392",
+	"Gamma":    "\u0393",
+	"Delta":    "\u0394",
+	"Epsilon":  "\u0395",
+	"Zeta":     "\u0396",
+	"Eta":      "\u0397",
+	"Theta":    "\u0398",
+	"Iota":     "\u0399",
+	"Kappa":    "\u039A",
+	"Lambda":   "\u039B",
+	"Mu":       "\u039C",
+	"Nu":       "\u039D",
+	"Xi":       "\u039E",
+	"Omicron":  "\u039F",
+	"Pi":       "\u03A0",
+	"Rho":      "\u03A1",
+	"Sigma":    "\u03A3",
+	"Tau":      "\u03A4",
+	"Upsilon":  "\u03A5",
+	"Phi":      "\u03A6",
+	"Chi":      "\u03A7",
+	"Psi":      "\u03A8",
+	"Omega":    "\u03A9",
+	"alpha":    "\u03B1",
+	"beta":     "\u03B2",
+	"gamma":    "\u03B3",
+	"delta":    "\u03B4",
+	"epsilon":  "\u03B5",
+	"zeta":     "\u03B6",
+	"eta":      "\u03B7",
+	"theta":    "\u03B8",
+	"iota":     "\u03B9",
+	"kappa":    "\u03BA",
+	"lambda":   "\u03BB",
+	"mu":       "\u03BC",
+	"nu":       "\u03BD",
+	"xi":       "\u03BE",
+	"omicron":  "\u03BF",
+	"pi":       "\u03C0",
+	"rho":      "\u03C1",
+	"sigmaf":   "\u03C2",
+	"sigma":    "\u03C3",
+	"tau":      "\u03C4",
+	"upsilon":  "\u03C5",
+	"phi":      "\u03C6",
+	"chi":      "\u03C7",
+	"psi":      "\u03C8",
+	"omega":    "\u03C9",
+	"thetasym": "\u03D1",
+	"upsih":    "\u03D2",
+	"piv":      "\u03D6",
+	"bull":     "\u2022",
+	"hellip":   "\u2026",
+	"prime":    "\u2032",
+	"Prime":    "\u2033",
+	"oline":    "\u203E",
+	"frasl":    "\u2044",
+	"weierp":   "\u2118",
+	"image":    "\u2111",
+	"real":     "\u211C",
+	"trade":    "\u2122",
+	"alefsym":  "\u2135",
+	"larr":     "\u2190",
+	"uarr":     "\u2191",
+	"rarr":     "\u2192",
+	"darr":     "\u2193",
+	"harr":     "\u2194",
+	"crarr":    "\u21B5",
+	"lArr":     "\u21D0",
+	"uArr":     "\u21D1",
+	"rArr":     "\u21D2",
+	"dArr":     "\u21D3",
+	"hArr":     "\u21D4",
+	"forall":   "\u2200",
+	"part":     "\u2202",
+	"exist":    "\u2203",
+	"empty":    "\u2205",
+	"nabla":    "\u2207",
+	"isin":     "\u2208",
+	"notin":    "\u2209",
+	"ni":       "\u220B",
+	"prod":     "\u220F",
+	"sum":      "\u2211",
+	"minus":    "\u2212",
+	"lowast":   "\u2217",
+	"radic":    "\u221A",
+	"prop":     "\u221D",
+	"infin":    "\u221E",
+	"ang":      "\u2220",
+	"and":      "\u2227",
+	"or":       "\u2228",
+	"cap":      "\u2229",
+	"cup":      "\u222A",
+	"int":      "\u222B",
+	"there4":   "\u2234",
+	"sim":      "\u223C",
+	"cong":     "\u2245",
+	"asymp":    "\u2248",
+	"ne":       "\u2260",
+	"equiv":    "\u2261",
+	"le":       "\u2264",
+	"ge":       "\u2265",
+	"sub":      "\u2282",
+	"sup":      "\u2283",
+	"nsub":     "\u2284",
+	"sube":     "\u2286",
+	"supe":     "\u2287",
+	"oplus":    "\u2295",
+	"otimes":   "\u2297",
+	"perp":     "\u22A5",
+	"sdot":     "\u22C5",
+	"lceil":    "\u2308",
+	"rceil":    "\u2309",
+	"lfloor":   "\u230A",
+	"rfloor":   "\u230B",
+	"lang":     "\u2329",
+	"rang":     "\u232A",
+	"loz":      "\u25CA",
+	"spades":   "\u2660",
+	"clubs":    "\u2663",
+	"hearts":   "\u2665",
+	"diams":    "\u2666",
+	"quot":     "\u0022",
+	"amp":      "\u0026",
+	"lt":       "\u003C",
+	"gt":       "\u003E",
+	"OElig":    "\u0152",
+	"oelig":    "\u0153",
+	"Scaron":   "\u0160",
+	"scaron":   "\u0161",
+	"Yuml":     "\u0178",
+	"circ":     "\u02C6",
+	"tilde":    "\u02DC",
+	"ensp":     "\u2002",
+	"emsp":     "\u2003",
+	"thinsp":   "\u2009",
+	"zwnj":     "\u200C",
+	"zwj":      "\u200D",
+	"lrm":      "\u200E",
+	"rlm":      "\u200F",
+	"ndash":    "\u2013",
+	"mdash":    "\u2014",
+	"lsquo":    "\u2018",
+	"rsquo":    "\u2019",
+	"sbquo":    "\u201A",
+	"ldquo":    "\u201C",
+	"rdquo":    "\u201D",
+	"bdquo":    "\u201E",
+	"dagger":   "\u2020",
+	"Dagger":   "\u2021",
+	"permil":   "\u2030",
+	"lsaquo":   "\u2039",
+	"rsaquo":   "\u203A",
+	"euro":     "\u20AC",
+}
+
+// HTMLAutoClose is the set of HTML elements that
+// should be considered to close automatically.
+var HTMLAutoClose = htmlAutoClose
+
+var htmlAutoClose = []string{
+	/*
+		hget http://www.w3.org/TR/html4/loose.dtd |
+		9 sed -n 's/<!ELEMENT (.*) - O EMPTY.+/	"\1",/p' | tr A-Z a-z
+	*/
+	"basefont",
+	"br",
+	"area",
+	"link",
+	"img",
+	"param",
+	"hr",
+	"input",
+	"col     ",
+	"frame",
+	"isindex",
+	"base",
+	"meta",
+}
+
+var (
+	esc_quot = []byte(""") // shorter than """
+	esc_apos = []byte("'") // shorter than "'"
+	esc_amp  = []byte("&")
+	esc_lt   = []byte("<")
+	esc_gt   = []byte(">")
+)
+
+// Escape writes to w the properly escaped XML equivalent
+// of the plain text data s.
+func Escape(w io.Writer, s []byte) {
+	var esc []byte
+	last := 0
+	for i, c := range s {
+		switch c {
+		case '"':
+			esc = esc_quot
+		case '\'':
+			esc = esc_apos
+		case '&':
+			esc = esc_amp
+		case '<':
+			esc = esc_lt
+		case '>':
+			esc = esc_gt
+		default:
+			continue
+		}
+		w.Write(s[last:i])
+		w.Write(esc)
+		last = i + 1
+	}
+	w.Write(s[last:])
+}
+
+// procInstEncoding parses the `encoding="..."` or `encoding='...'`
+// value out of the provided string, returning "" if not found.
+func procInstEncoding(s string) string {
+	// TODO: this parsing is somewhat lame and not exact.
+	// It works for all actual cases, though.
+	idx := strings.Index(s, "encoding=")
+	if idx == -1 {
+		return ""
+	}
+	v := s[idx+len("encoding="):]
+	if v == "" {
+		return ""
+	}
+	if v[0] != '\'' && v[0] != '"' {
+		return ""
+	}
+	idx = strings.IndexRune(v[1:], rune(v[0]))
+	if idx == -1 {
+		return ""
+	}
+	return v[1 : idx+1]
+}
diff --git a/src/pkg/encoding/xml/xml_test.go b/src/pkg/encoding/xml/xml_test.go
new file mode 100644
index 0000000..1d0696c
--- /dev/null
+++ b/src/pkg/encoding/xml/xml_test.go
@@ -0,0 +1,578 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xml
+
+import (
+	"io"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+const testInput = `
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<body xmlns:foo="ns1" xmlns="ns2" xmlns:tag="ns3" ` +
+	"\r\n\t" + `  >
+  <hello lang="en">World <>'" &#x767d;鵬ç¿”</hello>
+  <goodbye />
+  <outer foo:attr="value" xmlns:tag="ns4">
+    <inner/>
+  </outer>
+  <tag:name>
+    <![CDATA[Some text here.]]>
+  </tag:name>
+</body><!-- missing final newline -->`
+
+var rawTokens = []Token{
+	CharData("\n"),
+	ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
+	CharData("\n"),
+	Directive(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`),
+	CharData("\n"),
+	StartElement{Name{"", "body"}, []Attr{{Name{"xmlns", "foo"}, "ns1"}, {Name{"", "xmlns"}, "ns2"}, {Name{"xmlns", "tag"}, "ns3"}}},
+	CharData("\n  "),
+	StartElement{Name{"", "hello"}, []Attr{{Name{"", "lang"}, "en"}}},
+	CharData("World <>'\" 白鵬翔"),
+	EndElement{Name{"", "hello"}},
+	CharData("\n  "),
+	StartElement{Name{"", "goodbye"}, []Attr{}},
+	EndElement{Name{"", "goodbye"}},
+	CharData("\n  "),
+	StartElement{Name{"", "outer"}, []Attr{{Name{"foo", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
+	CharData("\n    "),
+	StartElement{Name{"", "inner"}, []Attr{}},
+	EndElement{Name{"", "inner"}},
+	CharData("\n  "),
+	EndElement{Name{"", "outer"}},
+	CharData("\n  "),
+	StartElement{Name{"tag", "name"}, []Attr{}},
+	CharData("\n    "),
+	CharData("Some text here."),
+	CharData("\n  "),
+	EndElement{Name{"tag", "name"}},
+	CharData("\n"),
+	EndElement{Name{"", "body"}},
+	Comment(" missing final newline "),
+}
+
+var cookedTokens = []Token{
+	CharData("\n"),
+	ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
+	CharData("\n"),
+	Directive(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`),
+	CharData("\n"),
+	StartElement{Name{"ns2", "body"}, []Attr{{Name{"xmlns", "foo"}, "ns1"}, {Name{"", "xmlns"}, "ns2"}, {Name{"xmlns", "tag"}, "ns3"}}},
+	CharData("\n  "),
+	StartElement{Name{"ns2", "hello"}, []Attr{{Name{"", "lang"}, "en"}}},
+	CharData("World <>'\" 白鵬翔"),
+	EndElement{Name{"ns2", "hello"}},
+	CharData("\n  "),
+	StartElement{Name{"ns2", "goodbye"}, []Attr{}},
+	EndElement{Name{"ns2", "goodbye"}},
+	CharData("\n  "),
+	StartElement{Name{"ns2", "outer"}, []Attr{{Name{"ns1", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
+	CharData("\n    "),
+	StartElement{Name{"ns2", "inner"}, []Attr{}},
+	EndElement{Name{"ns2", "inner"}},
+	CharData("\n  "),
+	EndElement{Name{"ns2", "outer"}},
+	CharData("\n  "),
+	StartElement{Name{"ns3", "name"}, []Attr{}},
+	CharData("\n    "),
+	CharData("Some text here."),
+	CharData("\n  "),
+	EndElement{Name{"ns3", "name"}},
+	CharData("\n"),
+	EndElement{Name{"ns2", "body"}},
+	Comment(" missing final newline "),
+}
+
+const testInputAltEncoding = `
+<?xml version="1.0" encoding="x-testing-uppercase"?>
+<TAG>VALUE</TAG>`
+
+var rawTokensAltEncoding = []Token{
+	CharData("\n"),
+	ProcInst{"xml", []byte(`version="1.0" encoding="x-testing-uppercase"`)},
+	CharData("\n"),
+	StartElement{Name{"", "tag"}, []Attr{}},
+	CharData("value"),
+	EndElement{Name{"", "tag"}},
+}
+
+var xmlInput = []string{
+	// unexpected EOF cases
+	"<",
+	"<t",
+	"<t ",
+	"<t/",
+	"<!",
+	"<!-",
+	"<!--",
+	"<!--c-",
+	"<!--c--",
+	"<!d",
+	"<t></",
+	"<t></t",
+	"<?",
+	"<?p",
+	"<t a",
+	"<t a=",
+	"<t a='",
+	"<t a=''",
+	"<t/><![",
+	"<t/><![C",
+	"<t/><![CDATA[d",
+	"<t/><![CDATA[d]",
+	"<t/><![CDATA[d]]",
+
+	// other Syntax errors
+	"<>",
+	"<t/a",
+	"<0 />",
+	"<?0 >",
+	//	"<!0 >",	// let the Token() caller handle
+	"</0>",
+	"<t 0=''>",
+	"<t a='&'>",
+	"<t a='<'>",
+	"<t> c;</t>",
+	"<t a>",
+	"<t a=>",
+	"<t a=v>",
+	//	"<![CDATA[d]]>",	// let the Token() caller handle
+	"<t></e>",
+	"<t></>",
+	"<t></t!",
+	"<t>cdata]]></t>",
+}
+
+func TestRawToken(t *testing.T) {
+	d := NewDecoder(strings.NewReader(testInput))
+	testRawToken(t, d, rawTokens)
+}
+
+type downCaser struct {
+	t *testing.T
+	r io.ByteReader
+}
+
+func (d *downCaser) ReadByte() (c byte, err error) {
+	c, err = d.r.ReadByte()
+	if c >= 'A' && c <= 'Z' {
+		c += 'a' - 'A'
+	}
+	return
+}
+
+func (d *downCaser) Read(p []byte) (int, error) {
+	d.t.Fatalf("unexpected Read call on downCaser reader")
+	panic("unreachable")
+}
+
+func TestRawTokenAltEncoding(t *testing.T) {
+	sawEncoding := ""
+	d := NewDecoder(strings.NewReader(testInputAltEncoding))
+	d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
+		sawEncoding = charset
+		if charset != "x-testing-uppercase" {
+			t.Fatalf("unexpected charset %q", charset)
+		}
+		return &downCaser{t, input.(io.ByteReader)}, nil
+	}
+	testRawToken(t, d, rawTokensAltEncoding)
+}
+
+func TestRawTokenAltEncodingNoConverter(t *testing.T) {
+	d := NewDecoder(strings.NewReader(testInputAltEncoding))
+	token, err := d.RawToken()
+	if token == nil {
+		t.Fatalf("expected a token on first RawToken call")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	token, err = d.RawToken()
+	if token != nil {
+		t.Errorf("expected a nil token; got %#v", token)
+	}
+	if err == nil {
+		t.Fatalf("expected an error on second RawToken call")
+	}
+	const encoding = "x-testing-uppercase"
+	if !strings.Contains(err.Error(), encoding) {
+		t.Errorf("expected error to contain %q; got error: %v",
+			encoding, err)
+	}
+}
+
+func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) {
+	for i, want := range rawTokens {
+		have, err := d.RawToken()
+		if err != nil {
+			t.Fatalf("token %d: unexpected error: %s", i, err)
+		}
+		if !reflect.DeepEqual(have, want) {
+			t.Errorf("token %d = %#v want %#v", i, have, want)
+		}
+	}
+}
+
+// Ensure that directives (specifically !DOCTYPE) include the complete
+// text of any nested directives, noting that < and > do not change
+// nesting depth if they are in single or double quotes.
+
+var nestedDirectivesInput = `
+<!DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]>
+<!DOCTYPE [<!ENTITY xlt ">">]>
+<!DOCTYPE [<!ENTITY xlt "<">]>
+<!DOCTYPE [<!ENTITY xlt '>'>]>
+<!DOCTYPE [<!ENTITY xlt '<'>]>
+<!DOCTYPE [<!ENTITY xlt '">'>]>
+<!DOCTYPE [<!ENTITY xlt "'<">]>
+`
+
+var nestedDirectivesTokens = []Token{
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt ">">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt "<">]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt '>'>]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt '<'>]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt '">'>]`),
+	CharData("\n"),
+	Directive(`DOCTYPE [<!ENTITY xlt "'<">]`),
+	CharData("\n"),
+}
+
+func TestNestedDirectives(t *testing.T) {
+	d := NewDecoder(strings.NewReader(nestedDirectivesInput))
+
+	for i, want := range nestedDirectivesTokens {
+		have, err := d.Token()
+		if err != nil {
+			t.Fatalf("token %d: unexpected error: %s", i, err)
+		}
+		if !reflect.DeepEqual(have, want) {
+			t.Errorf("token %d = %#v want %#v", i, have, want)
+		}
+	}
+}
+
+func TestToken(t *testing.T) {
+	d := NewDecoder(strings.NewReader(testInput))
+
+	for i, want := range cookedTokens {
+		have, err := d.Token()
+		if err != nil {
+			t.Fatalf("token %d: unexpected error: %s", i, err)
+		}
+		if !reflect.DeepEqual(have, want) {
+			t.Errorf("token %d = %#v want %#v", i, have, want)
+		}
+	}
+}
+
+func TestSyntax(t *testing.T) {
+	for i := range xmlInput {
+		d := NewDecoder(strings.NewReader(xmlInput[i]))
+		var err error
+		for _, err = d.Token(); err == nil; _, err = d.Token() {
+		}
+		if _, ok := err.(*SyntaxError); !ok {
+			t.Fatalf(`xmlInput "%s": expected SyntaxError not received`, xmlInput[i])
+		}
+	}
+}
+
+type allScalars struct {
+	True1     bool
+	True2     bool
+	False1    bool
+	False2    bool
+	Int       int
+	Int8      int8
+	Int16     int16
+	Int32     int32
+	Int64     int64
+	Uint      int
+	Uint8     uint8
+	Uint16    uint16
+	Uint32    uint32
+	Uint64    uint64
+	Uintptr   uintptr
+	Float32   float32
+	Float64   float64
+	String    string
+	PtrString *string
+}
+
+var all = allScalars{
+	True1:     true,
+	True2:     true,
+	False1:    false,
+	False2:    false,
+	Int:       1,
+	Int8:      -2,
+	Int16:     3,
+	Int32:     -4,
+	Int64:     5,
+	Uint:      6,
+	Uint8:     7,
+	Uint16:    8,
+	Uint32:    9,
+	Uint64:    10,
+	Uintptr:   11,
+	Float32:   13.0,
+	Float64:   14.0,
+	String:    "15",
+	PtrString: &sixteen,
+}
+
+var sixteen = "16"
+
+const testScalarsInput = `<allscalars>
+	<True1>true</True1>
+	<True2>1</True2>
+	<False1>false</False1>
+	<False2>0</False2>
+	<Int>1</Int>
+	<Int8>-2</Int8>
+	<Int16>3</Int16>
+	<Int32>-4</Int32>
+	<Int64>5</Int64>
+	<Uint>6</Uint>
+	<Uint8>7</Uint8>
+	<Uint16>8</Uint16>
+	<Uint32>9</Uint32>
+	<Uint64>10</Uint64>
+	<Uintptr>11</Uintptr>
+	<Float>12.0</Float>
+	<Float32>13.0</Float32>
+	<Float64>14.0</Float64>
+	<String>15</String>
+	<PtrString>16</PtrString>
+</allscalars>`
+
+func TestAllScalars(t *testing.T) {
+	var a allScalars
+	err := Unmarshal([]byte(testScalarsInput), &a)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !reflect.DeepEqual(a, all) {
+		t.Errorf("have %+v want %+v", a, all)
+	}
+}
+
+type item struct {
+	Field_a string
+}
+
+func TestIssue569(t *testing.T) {
+	data := `<item><Field_a>abcd</Field_a></item>`
+	var i item
+	err := Unmarshal([]byte(data), &i)
+
+	if err != nil || i.Field_a != "abcd" {
+		t.Fatal("Expecting abcd")
+	}
+}
+
+func TestUnquotedAttrs(t *testing.T) {
+	data := "<tag attr=azAZ09:-_\t>"
+	d := NewDecoder(strings.NewReader(data))
+	d.Strict = false
+	token, err := d.Token()
+	if _, ok := err.(*SyntaxError); ok {
+		t.Errorf("Unexpected error: %v", err)
+	}
+	if token.(StartElement).Name.Local != "tag" {
+		t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
+	}
+	attr := token.(StartElement).Attr[0]
+	if attr.Value != "azAZ09:-_" {
+		t.Errorf("Unexpected attribute value: %v", attr.Value)
+	}
+	if attr.Name.Local != "attr" {
+		t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
+	}
+}
+
+func TestValuelessAttrs(t *testing.T) {
+	tests := [][3]string{
+		{"<p nowrap>", "p", "nowrap"},
+		{"<p nowrap >", "p", "nowrap"},
+		{"<input checked/>", "input", "checked"},
+		{"<input checked />", "input", "checked"},
+	}
+	for _, test := range tests {
+		d := NewDecoder(strings.NewReader(test[0]))
+		d.Strict = false
+		token, err := d.Token()
+		if _, ok := err.(*SyntaxError); ok {
+			t.Errorf("Unexpected error: %v", err)
+		}
+		if token.(StartElement).Name.Local != test[1] {
+			t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
+		}
+		attr := token.(StartElement).Attr[0]
+		if attr.Value != test[2] {
+			t.Errorf("Unexpected attribute value: %v", attr.Value)
+		}
+		if attr.Name.Local != test[2] {
+			t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
+		}
+	}
+}
+
+func TestCopyTokenCharData(t *testing.T) {
+	data := []byte("same data")
+	var tok1 Token = CharData(data)
+	tok2 := CopyToken(tok1)
+	if !reflect.DeepEqual(tok1, tok2) {
+		t.Error("CopyToken(CharData) != CharData")
+	}
+	data[1] = 'o'
+	if reflect.DeepEqual(tok1, tok2) {
+		t.Error("CopyToken(CharData) uses same buffer.")
+	}
+}
+
+func TestCopyTokenStartElement(t *testing.T) {
+	elt := StartElement{Name{"", "hello"}, []Attr{{Name{"", "lang"}, "en"}}}
+	var tok1 Token = elt
+	tok2 := CopyToken(tok1)
+	if tok1.(StartElement).Attr[0].Value != "en" {
+		t.Error("CopyToken overwrote Attr[0]")
+	}
+	if !reflect.DeepEqual(tok1, tok2) {
+		t.Error("CopyToken(StartElement) != StartElement")
+	}
+	tok1.(StartElement).Attr[0] = Attr{Name{"", "lang"}, "de"}
+	if reflect.DeepEqual(tok1, tok2) {
+		t.Error("CopyToken(CharData) uses same buffer.")
+	}
+}
+
+func TestSyntaxErrorLineNum(t *testing.T) {
+	testInput := "<P>Foo<P>\n\n<P>Bar</>\n"
+	d := NewDecoder(strings.NewReader(testInput))
+	var err error
+	for _, err = d.Token(); err == nil; _, err = d.Token() {
+	}
+	synerr, ok := err.(*SyntaxError)
+	if !ok {
+		t.Error("Expected SyntaxError.")
+	}
+	if synerr.Line != 3 {
+		t.Error("SyntaxError didn't have correct line number.")
+	}
+}
+
+func TestTrailingRawToken(t *testing.T) {
+	input := `<FOO></FOO>  `
+	d := NewDecoder(strings.NewReader(input))
+	var err error
+	for _, err = d.RawToken(); err == nil; _, err = d.RawToken() {
+	}
+	if err != io.EOF {
+		t.Fatalf("d.RawToken() = _, %v, want _, io.EOF", err)
+	}
+}
+
+func TestTrailingToken(t *testing.T) {
+	input := `<FOO></FOO>  `
+	d := NewDecoder(strings.NewReader(input))
+	var err error
+	for _, err = d.Token(); err == nil; _, err = d.Token() {
+	}
+	if err != io.EOF {
+		t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
+	}
+}
+
+func TestEntityInsideCDATA(t *testing.T) {
+	input := `<test><![CDATA[ &val=foo ]]></test>`
+	d := NewDecoder(strings.NewReader(input))
+	var err error
+	for _, err = d.Token(); err == nil; _, err = d.Token() {
+	}
+	if err != io.EOF {
+		t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
+	}
+}
+
+// The last three tests (respectively one for characters in attribute
+// names and two for character entities) pass not because of code
+// changed for issue 1259, but instead pass with the given messages
+// from other parts of xml.Decoder.  I provide these to note the
+// current behavior of situations where one might think that character
+// range checking would detect the error, but it does not in fact.
+
+var characterTests = []struct {
+	in  string
+	err string
+}{
+	{"\x12<doc/>", "illegal character code U+0012"},
+	{"<?xml version=\"1.0\"?>\x0b<doc/>", "illegal character code U+000B"},
+	{"\xef\xbf\xbe<doc/>", "illegal character code U+FFFE"},
+	{"<?xml version=\"1.0\"?><doc>\r\n<hiya/>\x07<toots/></doc>", "illegal character code U+0007"},
+	{"<?xml version=\"1.0\"?><doc \x12='value'>what's up</doc>", "expected attribute name in element"},
+	{"<doc>&\x01;</doc>", "invalid character entity &;"},
+	{"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &;"},
+}
+
+func TestDisallowedCharacters(t *testing.T) {
+
+	for i, tt := range characterTests {
+		d := NewDecoder(strings.NewReader(tt.in))
+		var err error
+
+		for err == nil {
+			_, err = d.Token()
+		}
+		synerr, ok := err.(*SyntaxError)
+		if !ok {
+			t.Fatalf("input %d d.Token() = _, %v, want _, *SyntaxError", i, err)
+		}
+		if synerr.Msg != tt.err {
+			t.Fatalf("input %d synerr.Msg wrong: want '%s', got '%s'", i, tt.err, synerr.Msg)
+		}
+	}
+}
+
+type procInstEncodingTest struct {
+	expect, got string
+}
+
+var procInstTests = []struct {
+	input, expect string
+}{
+	{`version="1.0" encoding="utf-8"`, "utf-8"},
+	{`version="1.0" encoding='utf-8'`, "utf-8"},
+	{`version="1.0" encoding='utf-8' `, "utf-8"},
+	{`version="1.0" encoding=utf-8`, ""},
+	{`encoding="FOO" `, "FOO"},
+}
+
+func TestProcInstEncoding(t *testing.T) {
+	for _, test := range procInstTests {
+		got := procInstEncoding(test.input)
+		if got != test.expect {
+			t.Errorf("procInstEncoding(%q) = %q; want %q", test.input, got, test.expect)
+		}
+	}
+}
diff --git a/src/pkg/errors/Makefile b/src/pkg/errors/Makefile
new file mode 100644
index 0000000..05b4de5
--- /dev/null
+++ b/src/pkg/errors/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../Make.inc
+
+TARG=errors
+GOFILES=\
+	errors.go\
+
+include ../../Make.pkg
diff --git a/src/pkg/errors/errors.go b/src/pkg/errors/errors.go
new file mode 100644
index 0000000..3085a79
--- /dev/null
+++ b/src/pkg/errors/errors.go
@@ -0,0 +1,20 @@
+// Copyright 2011 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 errors implements functions to manipulate errors.
+package errors
+
+// New returns an error that formats as the given text.
+func New(text string) error {
+	return &errorString{text}
+}
+
+// errorString is a trivial implementation of error.
+type errorString struct {
+	s string
+}
+
+func (e *errorString) Error() string {
+	return e.s
+}
diff --git a/src/pkg/errors/errors_test.go b/src/pkg/errors/errors_test.go
new file mode 100644
index 0000000..c537eeb
--- /dev/null
+++ b/src/pkg/errors/errors_test.go
@@ -0,0 +1,33 @@
+// Copyright 2011 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 errors_test
+
+import (
+	. "errors"
+	"testing"
+)
+
+func TestNewEqual(t *testing.T) {
+	// Different allocations should not be equal.
+	if New("abc") == New("abc") {
+		t.Errorf(`New("abc") == New("abc")`)
+	}
+	if New("abc") == New("xyz") {
+		t.Errorf(`New("abc") == New("xyz")`)
+	}
+
+	// Same allocation should be equal to itself (not crash).
+	err := New("jkl")
+	if err != err {
+		t.Errorf(`err != err`)
+	}
+}
+
+func TestErrorMethod(t *testing.T) {
+	err := New("abc")
+	if err.Error() != "abc" {
+		t.Errorf(`New("abc").Error() = %q, want %q`, err.Error(), "abc")
+	}
+}
diff --git a/src/pkg/exec/Makefile b/src/pkg/exec/Makefile
deleted file mode 100644
index ba19d0e..0000000
--- a/src/pkg/exec/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=exec
-GOFILES=\
-	exec.go\
-
-GOFILES_freebsd=\
-	lp_unix.go\
-
-GOFILES_darwin=\
-	lp_unix.go\
-
-GOFILES_linux=\
-	lp_unix.go\
-
-GOFILES_openbsd=\
-	lp_unix.go\
-
-GOFILES_windows=\
-	lp_windows.go\
-
-GOFILES_plan9=\
-	lp_plan9.go\
-
-GOFILES+=$(GOFILES_$(GOOS))
-
-include ../../Make.pkg
diff --git a/src/pkg/exec/exec.go b/src/pkg/exec/exec.go
deleted file mode 100644
index 3b20f20..0000000
--- a/src/pkg/exec/exec.go
+++ /dev/null
@@ -1,377 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package exec runs external commands. It wraps os.StartProcess to make it
-// easier to remap stdin and stdout, connect I/O with pipes, and do other
-// adjustments.
-package exec
-
-import (
-	"bytes"
-	"io"
-	"os"
-	"strconv"
-	"syscall"
-)
-
-// Error records the name of a binary that failed to be be executed
-// and the reason it failed.
-type Error struct {
-	Name  string
-	Error os.Error
-}
-
-func (e *Error) String() string {
-	return "exec: " + strconv.Quote(e.Name) + ": " + e.Error.String()
-}
-
-// Cmd represents an external command being prepared or run.
-type Cmd struct {
-	// Path is the path of the command to run.
-	//
-	// This is the only field that must be set to a non-zero
-	// value.
-	Path string
-
-	// Args holds command line arguments, including the command as Args[0].
-	// If the Args field is empty or nil, Run uses {Path}.
-	// 
-	// In typical use, both Path and Args are set by calling Command.
-	Args []string
-
-	// Env specifies the environment of the process.
-	// If Env is nil, Run uses the current process's environment.
-	Env []string
-
-	// Dir specifies the working directory of the command.
-	// If Dir is the empty string, Run runs the command in the
-	// calling process's current directory.
-	Dir string
-
-	// Stdin specifies the process's standard input.
-	// If Stdin is nil, the process reads from DevNull.
-	Stdin io.Reader
-
-	// Stdout and Stderr specify the process's standard output and error.
-	//
-	// If either is nil, Run connects the
-	// corresponding file descriptor to /dev/null.
-	//
-	// If Stdout and Stderr are are the same writer, at most one
-	// goroutine at a time will call Write.
-	Stdout io.Writer
-	Stderr io.Writer
-
-	// SysProcAttr holds optional, operating system-specific attributes.
-	// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
-	SysProcAttr *syscall.SysProcAttr
-
-	// Process is the underlying process, once started.
-	Process *os.Process
-
-	err             os.Error // last error (from LookPath, stdin, stdout, stderr)
-	finished        bool     // when Wait was called
-	childFiles      []*os.File
-	closeAfterStart []io.Closer
-	closeAfterWait  []io.Closer
-	goroutine       []func() os.Error
-	errch           chan os.Error // one send per goroutine
-}
-
-// Command returns the Cmd struct to execute the named program with
-// the given arguments.
-//
-// It sets Path and Args in the returned structure and zeroes the
-// other fields.
-//
-// If name contains no path separators, Command uses LookPath to
-// resolve the path to a complete name if possible. Otherwise it uses
-// name directly.
-//
-// The returned Cmd's Args field is constructed from the command name
-// followed by the elements of arg, so arg should not include the
-// command name itself. For example, Command("echo", "hello")
-func Command(name string, arg ...string) *Cmd {
-	aname, err := LookPath(name)
-	if err != nil {
-		aname = name
-	}
-	return &Cmd{
-		Path: aname,
-		Args: append([]string{name}, arg...),
-		err:  err,
-	}
-}
-
-// interfaceEqual protects against panics from doing equality tests on
-// two interfaces with non-comparable underlying types
-func interfaceEqual(a, b interface{}) bool {
-	defer func() {
-		recover()
-	}()
-	return a == b
-}
-
-func (c *Cmd) envv() []string {
-	if c.Env != nil {
-		return c.Env
-	}
-	return os.Environ()
-}
-
-func (c *Cmd) argv() []string {
-	if len(c.Args) > 0 {
-		return c.Args
-	}
-	return []string{c.Path}
-}
-
-func (c *Cmd) stdin() (f *os.File, err os.Error) {
-	if c.Stdin == nil {
-		f, err = os.Open(os.DevNull)
-		c.closeAfterStart = append(c.closeAfterStart, f)
-		return
-	}
-
-	if f, ok := c.Stdin.(*os.File); ok {
-		return f, nil
-	}
-
-	pr, pw, err := os.Pipe()
-	if err != nil {
-		return
-	}
-
-	c.closeAfterStart = append(c.closeAfterStart, pr)
-	c.closeAfterWait = append(c.closeAfterWait, pw)
-	c.goroutine = append(c.goroutine, func() os.Error {
-		_, err := io.Copy(pw, c.Stdin)
-		if err1 := pw.Close(); err == nil {
-			err = err1
-		}
-		return err
-	})
-	return pr, nil
-}
-
-func (c *Cmd) stdout() (f *os.File, err os.Error) {
-	return c.writerDescriptor(c.Stdout)
-}
-
-func (c *Cmd) stderr() (f *os.File, err os.Error) {
-	if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
-		return c.childFiles[1], nil
-	}
-	return c.writerDescriptor(c.Stderr)
-}
-
-func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) {
-	if w == nil {
-		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
-		c.closeAfterStart = append(c.closeAfterStart, f)
-		return
-	}
-
-	if f, ok := w.(*os.File); ok {
-		return f, nil
-	}
-
-	pr, pw, err := os.Pipe()
-	if err != nil {
-		return
-	}
-
-	c.closeAfterStart = append(c.closeAfterStart, pw)
-	c.closeAfterWait = append(c.closeAfterWait, pr)
-	c.goroutine = append(c.goroutine, func() os.Error {
-		_, err := io.Copy(w, pr)
-		return err
-	})
-	return pw, nil
-}
-
-// Run starts the specified command and waits for it to complete.
-//
-// The returned error is nil if the command runs, has no problems
-// copying stdin, stdout, and stderr, and exits with a zero exit
-// status.
-//
-// If the command fails to run or doesn't complete successfully, the
-// error is of type *os.Waitmsg. Other error types may be
-// returned for I/O problems.
-func (c *Cmd) Run() os.Error {
-	if err := c.Start(); err != nil {
-		return err
-	}
-	return c.Wait()
-}
-
-// Start starts the specified command but does not wait for it to complete.
-func (c *Cmd) Start() os.Error {
-	if c.err != nil {
-		return c.err
-	}
-	if c.Process != nil {
-		return os.NewError("exec: already started")
-	}
-
-	type F func(*Cmd) (*os.File, os.Error)
-	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
-		fd, err := setupFd(c)
-		if err != nil {
-			return err
-		}
-		c.childFiles = append(c.childFiles, fd)
-	}
-
-	var err os.Error
-	c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
-		Dir:   c.Dir,
-		Files: c.childFiles,
-		Env:   c.envv(),
-		Sys:   c.SysProcAttr,
-	})
-	if err != nil {
-		return err
-	}
-
-	for _, fd := range c.closeAfterStart {
-		fd.Close()
-	}
-
-	c.errch = make(chan os.Error, len(c.goroutine))
-	for _, fn := range c.goroutine {
-		go func(fn func() os.Error) {
-			c.errch <- fn()
-		}(fn)
-	}
-
-	return nil
-}
-
-// Wait waits for the command to exit.
-// It must have been started by Start.
-//
-// The returned error is nil if the command runs, has no problems
-// copying stdin, stdout, and stderr, and exits with a zero exit
-// status.
-//
-// If the command fails to run or doesn't complete successfully, the
-// error is of type *os.Waitmsg. Other error types may be
-// returned for I/O problems.
-func (c *Cmd) Wait() os.Error {
-	if c.Process == nil {
-		return os.NewError("exec: not started")
-	}
-	if c.finished {
-		return os.NewError("exec: Wait was already called")
-	}
-	c.finished = true
-	msg, err := c.Process.Wait(0)
-
-	var copyError os.Error
-	for _ = range c.goroutine {
-		if err := <-c.errch; err != nil && copyError == nil {
-			copyError = err
-		}
-	}
-
-	for _, fd := range c.closeAfterWait {
-		fd.Close()
-	}
-
-	if err != nil {
-		return err
-	} else if !msg.Exited() || msg.ExitStatus() != 0 {
-		return msg
-	}
-
-	return copyError
-}
-
-// Output runs the command and returns its standard output.
-func (c *Cmd) Output() ([]byte, os.Error) {
-	if c.Stdout != nil {
-		return nil, os.NewError("exec: Stdout already set")
-	}
-	var b bytes.Buffer
-	c.Stdout = &b
-	err := c.Run()
-	return b.Bytes(), err
-}
-
-// CombinedOutput runs the command and returns its combined standard
-// output and standard error.
-func (c *Cmd) CombinedOutput() ([]byte, os.Error) {
-	if c.Stdout != nil {
-		return nil, os.NewError("exec: Stdout already set")
-	}
-	if c.Stderr != nil {
-		return nil, os.NewError("exec: Stderr already set")
-	}
-	var b bytes.Buffer
-	c.Stdout = &b
-	c.Stderr = &b
-	err := c.Run()
-	return b.Bytes(), err
-}
-
-// StdinPipe returns a pipe that will be connected to the command's
-// standard input when the command starts.
-func (c *Cmd) StdinPipe() (io.WriteCloser, os.Error) {
-	if c.Stdin != nil {
-		return nil, os.NewError("exec: Stdin already set")
-	}
-	if c.Process != nil {
-		return nil, os.NewError("exec: StdinPipe after process started")
-	}
-	pr, pw, err := os.Pipe()
-	if err != nil {
-		return nil, err
-	}
-	c.Stdin = pr
-	c.closeAfterStart = append(c.closeAfterStart, pr)
-	c.closeAfterWait = append(c.closeAfterWait, pw)
-	return pw, nil
-}
-
-// StdoutPipe returns a pipe that will be connected to the command's
-// standard output when the command starts.
-// The pipe will be closed automatically after Wait sees the command exit.
-func (c *Cmd) StdoutPipe() (io.ReadCloser, os.Error) {
-	if c.Stdout != nil {
-		return nil, os.NewError("exec: Stdout already set")
-	}
-	if c.Process != nil {
-		return nil, os.NewError("exec: StdoutPipe after process started")
-	}
-	pr, pw, err := os.Pipe()
-	if err != nil {
-		return nil, err
-	}
-	c.Stdout = pw
-	c.closeAfterStart = append(c.closeAfterStart, pw)
-	c.closeAfterWait = append(c.closeAfterWait, pr)
-	return pr, nil
-}
-
-// StderrPipe returns a pipe that will be connected to the command's
-// standard error when the command starts.
-// The pipe will be closed automatically after Wait sees the command exit.
-func (c *Cmd) StderrPipe() (io.ReadCloser, os.Error) {
-	if c.Stderr != nil {
-		return nil, os.NewError("exec: Stderr already set")
-	}
-	if c.Process != nil {
-		return nil, os.NewError("exec: StderrPipe after process started")
-	}
-	pr, pw, err := os.Pipe()
-	if err != nil {
-		return nil, err
-	}
-	c.Stderr = pw
-	c.closeAfterStart = append(c.closeAfterStart, pw)
-	c.closeAfterWait = append(c.closeAfterWait, pr)
-	return pr, nil
-}
diff --git a/src/pkg/exec/exec_test.go b/src/pkg/exec/exec_test.go
deleted file mode 100644
index 242120f..0000000
--- a/src/pkg/exec/exec_test.go
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package exec
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"testing"
-	"os"
-	"strconv"
-	"strings"
-)
-
-func helperCommand(s ...string) *Cmd {
-	cs := []string{"-test.run=exec.TestHelperProcess", "--"}
-	cs = append(cs, s...)
-	cmd := Command(os.Args[0], cs...)
-	cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
-	return cmd
-}
-
-func TestEcho(t *testing.T) {
-	bs, err := helperCommand("echo", "foo bar", "baz").Output()
-	if err != nil {
-		t.Errorf("echo: %v", err)
-	}
-	if g, e := string(bs), "foo bar baz\n"; g != e {
-		t.Errorf("echo: want %q, got %q", e, g)
-	}
-}
-
-func TestCatStdin(t *testing.T) {
-	// Cat, testing stdin and stdout.
-	input := "Input string\nLine 2"
-	p := helperCommand("cat")
-	p.Stdin = strings.NewReader(input)
-	bs, err := p.Output()
-	if err != nil {
-		t.Errorf("cat: %v", err)
-	}
-	s := string(bs)
-	if s != input {
-		t.Errorf("cat: want %q, got %q", input, s)
-	}
-}
-
-func TestCatGoodAndBadFile(t *testing.T) {
-	// Testing combined output and error values.
-	bs, err := helperCommand("cat", "/bogus/file.foo", "exec_test.go").CombinedOutput()
-	if _, ok := err.(*os.Waitmsg); !ok {
-		t.Errorf("expected Waitmsg from cat combined; got %T: %v", err, err)
-	}
-	s := string(bs)
-	sp := strings.SplitN(s, "\n", 2)
-	if len(sp) != 2 {
-		t.Fatalf("expected two lines from cat; got %q", s)
-	}
-	errLine, body := sp[0], sp[1]
-	if !strings.HasPrefix(errLine, "Error: open /bogus/file.foo") {
-		t.Errorf("expected stderr to complain about file; got %q", errLine)
-	}
-	if !strings.Contains(body, "func TestHelperProcess(t *testing.T)") {
-		t.Errorf("expected test code; got %q (len %d)", body, len(body))
-	}
-}
-
-func TestNoExistBinary(t *testing.T) {
-	// Can't run a non-existent binary
-	err := Command("/no-exist-binary").Run()
-	if err == nil {
-		t.Error("expected error from /no-exist-binary")
-	}
-}
-
-func TestExitStatus(t *testing.T) {
-	// Test that exit values are returned correctly
-	err := helperCommand("exit", "42").Run()
-	if werr, ok := err.(*os.Waitmsg); ok {
-		if s, e := werr.String(), "exit status 42"; s != e {
-			t.Errorf("from exit 42 got exit %q, want %q", s, e)
-		}
-	} else {
-		t.Fatalf("expected Waitmsg from exit 42; got %T: %v", err, err)
-	}
-}
-
-func TestPipes(t *testing.T) {
-	check := func(what string, err os.Error) {
-		if err != nil {
-			t.Fatalf("%s: %v", what, err)
-		}
-	}
-	// Cat, testing stdin and stdout.
-	c := helperCommand("pipetest")
-	stdin, err := c.StdinPipe()
-	check("StdinPipe", err)
-	stdout, err := c.StdoutPipe()
-	check("StdoutPipe", err)
-	stderr, err := c.StderrPipe()
-	check("StderrPipe", err)
-
-	outbr := bufio.NewReader(stdout)
-	errbr := bufio.NewReader(stderr)
-	line := func(what string, br *bufio.Reader) string {
-		line, _, err := br.ReadLine()
-		if err != nil {
-			t.Fatalf("%s: %v", what, err)
-		}
-		return string(line)
-	}
-
-	err = c.Start()
-	check("Start", err)
-
-	_, err = stdin.Write([]byte("O:I am output\n"))
-	check("first stdin Write", err)
-	if g, e := line("first output line", outbr), "O:I am output"; g != e {
-		t.Errorf("got %q, want %q", g, e)
-	}
-
-	_, err = stdin.Write([]byte("E:I am error\n"))
-	check("second stdin Write", err)
-	if g, e := line("first error line", errbr), "E:I am error"; g != e {
-		t.Errorf("got %q, want %q", g, e)
-	}
-
-	_, err = stdin.Write([]byte("O:I am output2\n"))
-	check("third stdin Write 3", err)
-	if g, e := line("second output line", outbr), "O:I am output2"; g != e {
-		t.Errorf("got %q, want %q", g, e)
-	}
-
-	stdin.Close()
-	err = c.Wait()
-	check("Wait", err)
-}
-
-// TestHelperProcess isn't a real test. It's used as a helper process
-// for TestParameterRun.
-func TestHelperProcess(*testing.T) {
-	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
-		return
-	}
-	defer os.Exit(0)
-
-	args := os.Args
-	for len(args) > 0 {
-		if args[0] == "--" {
-			args = args[1:]
-			break
-		}
-		args = args[1:]
-	}
-	if len(args) == 0 {
-		fmt.Fprintf(os.Stderr, "No command\n")
-		os.Exit(2)
-	}
-
-	cmd, args := args[0], args[1:]
-	switch cmd {
-	case "echo":
-		iargs := []interface{}{}
-		for _, s := range args {
-			iargs = append(iargs, s)
-		}
-		fmt.Println(iargs...)
-	case "cat":
-		if len(args) == 0 {
-			io.Copy(os.Stdout, os.Stdin)
-			return
-		}
-		exit := 0
-		for _, fn := range args {
-			f, err := os.Open(fn)
-			if err != nil {
-				fmt.Fprintf(os.Stderr, "Error: %v\n", err)
-				exit = 2
-			} else {
-				defer f.Close()
-				io.Copy(os.Stdout, f)
-			}
-		}
-		os.Exit(exit)
-	case "pipetest":
-		bufr := bufio.NewReader(os.Stdin)
-		for {
-			line, _, err := bufr.ReadLine()
-			if err == os.EOF {
-				break
-			} else if err != nil {
-				os.Exit(1)
-			}
-			if bytes.HasPrefix(line, []byte("O:")) {
-				os.Stdout.Write(line)
-				os.Stdout.Write([]byte{'\n'})
-			} else if bytes.HasPrefix(line, []byte("E:")) {
-				os.Stderr.Write(line)
-				os.Stderr.Write([]byte{'\n'})
-			} else {
-				os.Exit(1)
-			}
-		}
-	case "exit":
-		n, _ := strconv.Atoi(args[0])
-		os.Exit(n)
-	default:
-		fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
-		os.Exit(2)
-	}
-}
diff --git a/src/pkg/exec/lp_plan9.go b/src/pkg/exec/lp_plan9.go
deleted file mode 100644
index e4751a4..0000000
--- a/src/pkg/exec/lp_plan9.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2011 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 exec
-
-import (
-	"os"
-	"strings"
-)
-
-// ErrNotFound is the error resulting if a path search failed to find an executable file.
-var ErrNotFound = os.NewError("executable file not found in $path")
-
-func findExecutable(file string) os.Error {
-	d, err := os.Stat(file)
-	if err != nil {
-		return err
-	}
-	if d.IsRegular() && d.Permission()&0111 != 0 {
-		return nil
-	}
-	return os.EPERM
-}
-
-// LookPath searches for an executable binary named file
-// in the directories named by the path environment variable.
-// If file begins with "/", "#", "./", or "../", it is tried
-// directly and the path is not consulted.
-func LookPath(file string) (string, os.Error) {
-	// skip the path lookup for these prefixes
-	skip := []string{"/", "#", "./", "../"}
-
-	for _, p := range skip {
-		if strings.HasPrefix(file, p) {
-			err := findExecutable(file)
-			if err == nil {
-				return file, nil
-			}
-			return "", &Error{file, err}
-		}
-	}
-
-	path := os.Getenv("path")
-	for _, dir := range strings.Split(path, "\000") {
-		if err := findExecutable(dir + "/" + file); err == nil {
-			return dir + "/" + file, nil
-		}
-	}
-	return "", &Error{file, ErrNotFound}
-}
diff --git a/src/pkg/exec/lp_unix.go b/src/pkg/exec/lp_unix.go
deleted file mode 100644
index 0cd19e7..0000000
--- a/src/pkg/exec/lp_unix.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2010 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 darwin freebsd linux openbsd
-
-package exec
-
-import (
-	"os"
-	"strings"
-)
-
-// ErrNotFound is the error resulting if a path search failed to find an executable file.
-var ErrNotFound = os.NewError("executable file not found in $PATH")
-
-func findExecutable(file string) os.Error {
-	d, err := os.Stat(file)
-	if err != nil {
-		return err
-	}
-	if d.IsRegular() && d.Permission()&0111 != 0 {
-		return nil
-	}
-	return os.EPERM
-}
-
-// LookPath searches for an executable binary named file
-// in the directories named by the PATH environment variable.
-// If file contains a slash, it is tried directly and the PATH is not consulted.
-func LookPath(file string) (string, os.Error) {
-	// NOTE(rsc): I wish we could use the Plan 9 behavior here
-	// (only bypass the path if file begins with / or ./ or ../)
-	// but that would not match all the Unix shells.
-
-	if strings.Contains(file, "/") {
-		err := findExecutable(file)
-		if err == nil {
-			return file, nil
-		}
-		return "", &Error{file, err}
-	}
-	pathenv := os.Getenv("PATH")
-	for _, dir := range strings.Split(pathenv, ":") {
-		if dir == "" {
-			// Unix shell semantics: path element "" means "."
-			dir = "."
-		}
-		if err := findExecutable(dir + "/" + file); err == nil {
-			return dir + "/" + file, nil
-		}
-	}
-	return "", &Error{file, ErrNotFound}
-}
diff --git a/src/pkg/exec/lp_windows.go b/src/pkg/exec/lp_windows.go
deleted file mode 100644
index 7581088..0000000
--- a/src/pkg/exec/lp_windows.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2010 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 exec
-
-import (
-	"os"
-	"strings"
-)
-
-// ErrNotFound is the error resulting if a path search failed to find an executable file.
-var ErrNotFound = os.NewError("executable file not found in %PATH%")
-
-func chkStat(file string) os.Error {
-	d, err := os.Stat(file)
-	if err != nil {
-		return err
-	}
-	if d.IsRegular() {
-		return nil
-	}
-	return os.EPERM
-}
-
-func findExecutable(file string, exts []string) (string, os.Error) {
-	if len(exts) == 0 {
-		return file, chkStat(file)
-	}
-	f := strings.ToLower(file)
-	for _, e := range exts {
-		if strings.HasSuffix(f, e) {
-			return file, chkStat(file)
-		}
-	}
-	for _, e := range exts {
-		if f := file + e; chkStat(f) == nil {
-			return f, nil
-		}
-	}
-	return ``, os.ENOENT
-}
-
-func LookPath(file string) (f string, err os.Error) {
-	x := os.Getenv(`PATHEXT`)
-	if x == `` {
-		x = `.COM;.EXE;.BAT;.CMD`
-	}
-	exts := []string{}
-	for _, e := range strings.Split(strings.ToLower(x), `;`) {
-		if e == "" {
-			continue
-		}
-		if e[0] != '.' {
-			e = "." + e
-		}
-		exts = append(exts, e)
-	}
-	if strings.IndexAny(file, `:\/`) != -1 {
-		if f, err = findExecutable(file, exts); err == nil {
-			return
-		}
-		return ``, &Error{file, err}
-	}
-	if pathenv := os.Getenv(`PATH`); pathenv == `` {
-		if f, err = findExecutable(`.\`+file, exts); err == nil {
-			return
-		}
-	} else {
-		for _, dir := range strings.Split(pathenv, `;`) {
-			if f, err = findExecutable(dir+`\`+file, exts); err == nil {
-				return
-			}
-		}
-	}
-	return ``, &Error{file, ErrNotFound}
-}
diff --git a/src/pkg/exp/datafmt/Makefile b/src/pkg/exp/datafmt/Makefile
deleted file mode 100644
index aa94538..0000000
--- a/src/pkg/exp/datafmt/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=exp/datafmt
-GOFILES=\
-	datafmt.go\
-	parser.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/exp/datafmt/datafmt.go b/src/pkg/exp/datafmt/datafmt.go
deleted file mode 100644
index 6d7e764..0000000
--- a/src/pkg/exp/datafmt/datafmt.go
+++ /dev/null
@@ -1,710 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*	Package datafmt implements syntax-directed, type-driven formatting
-	of arbitrary data structures. Formatting a data structure consists of
-	two phases: first, a parser reads a format specification and builds a
-	"compiled" format. Then, the format can be applied repeatedly to
-	arbitrary values. Applying a format to a value evaluates to a []byte
-	containing the formatted value bytes, or nil.
-
-	A format specification is a set of package declarations and format rules:
-
-		Format      = [ Entry { ";" Entry } [ ";" ] ] .
-		Entry       = PackageDecl | FormatRule .
-
-	(The syntax of a format specification is presented in the same EBNF
-	notation as used in the Go language specification. The syntax of white
-	space, comments, identifiers, and string literals is the same as in Go.)
-
-	A package declaration binds a package name (such as 'ast') to a
-	package import path (such as '"go/ast"'). Each package used (in
-	a type name, see below) must be declared once before use.
-
-		PackageDecl = PackageName ImportPath .
-		PackageName = identifier .
-		ImportPath  = string .
-
-	A format rule binds a rule name to a format expression. A rule name
-	may be a type name or one of the special names 'default' or '/'.
-	A type name may be the name of a predeclared type (for example, 'int',
-	'float32', etc.), the package-qualified name of a user-defined type
-	(for example, 'ast.MapType'), or an identifier indicating the structure
-	of unnamed composite types ('array', 'chan', 'func', 'interface', 'map',
-	or 'ptr'). Each rule must have a unique name; rules can be declared in
-	any order.
-
-		FormatRule  = RuleName "=" Expression .
-		RuleName    = TypeName | "default" | "/" .
-		TypeName    = [ PackageName "." ] identifier .
-
-	To format a value, the value's type name is used to select the format rule
-	(there is an override mechanism, see below). The format expression of the
-	selected rule specifies how the value is formatted. Each format expression,
-	when applied to a value, evaluates to a byte sequence or nil.
-
-	In its most general form, a format expression is a list of alternatives,
-	each of which is a sequence of operands:
-
-		Expression  = [ Sequence ] { "|" [ Sequence ] } .
-		Sequence    = Operand { Operand } .
-
-	The formatted result produced by an expression is the result of the first
-	alternative sequence that evaluates to a non-nil result; if there is no
-	such alternative, the expression evaluates to nil. The result produced by
-	an operand sequence is the concatenation of the results of its operands.
-	If any operand in the sequence evaluates to nil, the entire sequence
-	evaluates to nil.
-
-	There are five kinds of operands:
-
-		Operand     = Literal | Field | Group | Option | Repetition .
-
-	Literals evaluate to themselves, with two substitutions. First,
-	%-formats expand in the manner of fmt.Printf, with the current value
-	passed as the parameter. Second, the current indentation (see below)
-	is inserted after every newline or form feed character.
-
-		Literal     = string .
-
-	This table shows string literals applied to the value 42 and the
-	corresponding formatted result:
-
-		"foo"       foo
-		"%x"        2a
-		"x = %d"    x = 42
-		"%#x = %d"  0x2a = 42
-
-	A field operand is a field name optionally followed by an alternate
-	rule name. The field name may be an identifier or one of the special
-	names @ or *.
-
-		Field       = FieldName [ ":" RuleName ] .
-		FieldName   = identifier | "@" | "*" .
-
-	If the field name is an identifier, the current value must be a struct,
-	and there must be a field with that name in the struct. The same lookup
-	rules apply as in the Go language (for instance, the name of an anonymous
-	field is the unqualified type name). The field name denotes the field
-	value in the struct. If the field is not found, formatting is aborted
-	and an error message is returned. (TODO consider changing the semantics
-	such that if a field is not found, it evaluates to nil).
-
-	The special name '@' denotes the current value.
-
-	The meaning of the special name '*' depends on the type of the current
-	value:
-
-		array, slice types   array, slice element (inside {} only, see below)
-		interfaces           value stored in interface
-		pointers             value pointed to by pointer
-
-	(Implementation restriction: channel, function and map types are not
-	supported due to missing reflection support).
-
-	Fields are evaluated as follows: If the field value is nil, or an array
-	or slice element does not exist, the result is nil (see below for details
-	on array/slice elements). If the value is not nil the field value is
-	formatted (recursively) using the rule corresponding to its type name,
-	or the alternate rule name, if given.
-
-	The following example shows a complete format specification for a
-	struct 'myPackage.Point'. Assume the package
-
-		package myPackage  // in directory myDir/myPackage
-		type Point struct {
-			name string;
-			x, y int;
-		}
-
-	Applying the format specification
-
-		myPackage "myDir/myPackage";
-		int = "%d";
-		hexInt = "0x%x";
-		string = "---%s---";
-		myPackage.Point = name "{" x ", " y:hexInt "}";
-
-	to the value myPackage.Point{"foo", 3, 15} results in
-
-		---foo---{3, 0xf}
-
-	Finally, an operand may be a grouped, optional, or repeated expression.
-	A grouped expression ("group") groups a more complex expression (body)
-	so that it can be used in place of a single operand:
-
-		Group       = "(" [ Indentation ">>" ] Body ")" .
-		Indentation = Expression .
-		Body        = Expression .
-
-	A group body may be prefixed by an indentation expression followed by '>>'.
-	The indentation expression is applied to the current value like any other
-	expression and the result, if not nil, is appended to the current indentation
-	during the evaluation of the body (see also formatting state, below).
-
-	An optional expression ("option") is enclosed in '[]' brackets.
-
-		Option      = "[" Body "]" .
-
-	An option evaluates to its body, except that if the body evaluates to nil,
-	the option expression evaluates to an empty []byte. Thus an option's purpose
-	is to protect the expression containing the option from a nil operand.
-
-	A repeated expression ("repetition") is enclosed in '{}' braces.
-
-		Repetition  = "{" Body [ "/" Separator ] "}" .
-		Separator   = Expression .
-
-	A repeated expression is evaluated as follows: The body is evaluated
-	repeatedly and its results are concatenated until the body evaluates
-	to nil. The result of the repetition is the (possibly empty) concatenation,
-	but it is never nil. An implicit index is supplied for the evaluation of
-	the body: that index is used to address elements of arrays or slices. If
-	the corresponding elements do not exist, the field denoting the element
-	evaluates to nil (which in turn may terminate the repetition).
-
-	The body of a repetition may be followed by a '/' and a "separator"
-	expression. If the separator is present, it is invoked between repetitions
-	of the body.
-
-	The following example shows a complete format specification for formatting
-	a slice of unnamed type. Applying the specification
-
-		int = "%b";
-		array = { * / ", " };  // array is the type name for an unnamed slice
-
-	to the value '[]int{2, 3, 5, 7}' results in
-
-		10, 11, 101, 111
-
-	Default rule: If a format rule named 'default' is present, it is used for
-	formatting a value if no other rule was found. A common default rule is
-
-		default = "%v"
-
-	to provide default formatting for basic types without having to specify
-	a specific rule for each basic type.
-
-	Global separator rule: If a format rule named '/' is present, it is
-	invoked with the current value between literals. If the separator
-	expression evaluates to nil, it is ignored.
-
-	For instance, a global separator rule may be used to punctuate a sequence
-	of values with commas. The rules:
-
-		default = "%v";
-		/ = ", ";
-
-	will format an argument list by printing each one in its default format,
-	separated by a comma and a space.
-*/
-package datafmt
-
-import (
-	"bytes"
-	"fmt"
-	"go/token"
-	"io"
-	"os"
-	"reflect"
-	"runtime"
-)
-
-// ----------------------------------------------------------------------------
-// Format representation
-
-// Custom formatters implement the Formatter function type.
-// A formatter is invoked with the current formatting state, the
-// value to format, and the rule name under which the formatter
-// was installed (the same formatter function may be installed
-// under different names). The formatter may access the current state
-// to guide formatting and use State.Write to append to the state's
-// output.
-//
-// A formatter must return a boolean value indicating if it evaluated
-// to a non-nil value (true), or a nil value (false).
-//
-type Formatter func(state *State, value interface{}, ruleName string) bool
-
-// A FormatterMap is a set of custom formatters.
-// It maps a rule name to a formatter function.
-//
-type FormatterMap map[string]Formatter
-
-// A parsed format expression is built from the following nodes.
-//
-type (
-	expr interface{}
-
-	alternatives []expr // x | y | z
-
-	sequence []expr // x y z
-
-	literal [][]byte // a list of string segments, possibly starting with '%'
-
-	field struct {
-		fieldName string // including "@", "*"
-		ruleName  string // "" if no rule name specified
-	}
-
-	group struct {
-		indent, body expr // (indent >> body)
-	}
-
-	option struct {
-		body expr // [body]
-	}
-
-	repetition struct {
-		body, separator expr // {body / separator}
-	}
-
-	custom struct {
-		ruleName string
-		fun      Formatter
-	}
-)
-
-// A Format is the result of parsing a format specification.
-// The format may be applied repeatedly to format values.
-//
-type Format map[string]expr
-
-// ----------------------------------------------------------------------------
-// Formatting
-
-// An application-specific environment may be provided to Format.Apply;
-// the environment is available inside custom formatters via State.Env().
-// Environments must implement copying; the Copy method must return an
-// complete copy of the receiver. This is necessary so that the formatter
-// can save and restore an environment (in case of an absent expression).
-//
-// If the Environment doesn't change during formatting (this is under
-// control of the custom formatters), the Copy function can simply return
-// the receiver, and thus can be very light-weight.
-//
-type Environment interface {
-	Copy() Environment
-}
-
-// State represents the current formatting state.
-// It is provided as argument to custom formatters.
-//
-type State struct {
-	fmt       Format         // format in use
-	env       Environment    // user-supplied environment
-	errors    chan os.Error  // not chan *Error (errors <- nil would be wrong!)
-	hasOutput bool           // true after the first literal has been written
-	indent    bytes.Buffer   // current indentation
-	output    bytes.Buffer   // format output
-	linePos   token.Position // position of line beginning (Column == 0)
-	default_  expr           // possibly nil
-	separator expr           // possibly nil
-}
-
-func newState(fmt Format, env Environment, errors chan os.Error) *State {
-	s := new(State)
-	s.fmt = fmt
-	s.env = env
-	s.errors = errors
-	s.linePos = token.Position{Line: 1}
-
-	// if we have a default rule, cache its expression for fast access
-	if x, found := fmt["default"]; found {
-		s.default_ = x
-	}
-
-	// if we have a global separator rule, cache its expression for fast access
-	if x, found := fmt["/"]; found {
-		s.separator = x
-	}
-
-	return s
-}
-
-// Env returns the environment passed to Format.Apply.
-func (s *State) Env() interface{} { return s.env }
-
-// LinePos returns the position of the current line beginning
-// in the state's output buffer. Line numbers start at 1.
-//
-func (s *State) LinePos() token.Position { return s.linePos }
-
-// Pos returns the position of the next byte to be written to the
-// output buffer. Line numbers start at 1.
-//
-func (s *State) Pos() token.Position {
-	offs := s.output.Len()
-	return token.Position{Line: s.linePos.Line, Column: offs - s.linePos.Offset, Offset: offs}
-}
-
-// Write writes data to the output buffer, inserting the indentation
-// string after each newline or form feed character. It cannot return an error.
-//
-func (s *State) Write(data []byte) (int, os.Error) {
-	n := 0
-	i0 := 0
-	for i, ch := range data {
-		if ch == '\n' || ch == '\f' {
-			// write text segment and indentation
-			n1, _ := s.output.Write(data[i0 : i+1])
-			n2, _ := s.output.Write(s.indent.Bytes())
-			n += n1 + n2
-			i0 = i + 1
-			s.linePos.Offset = s.output.Len()
-			s.linePos.Line++
-		}
-	}
-	n3, _ := s.output.Write(data[i0:])
-	return n + n3, nil
-}
-
-type checkpoint struct {
-	env       Environment
-	hasOutput bool
-	outputLen int
-	linePos   token.Position
-}
-
-func (s *State) save() checkpoint {
-	saved := checkpoint{nil, s.hasOutput, s.output.Len(), s.linePos}
-	if s.env != nil {
-		saved.env = s.env.Copy()
-	}
-	return saved
-}
-
-func (s *State) restore(m checkpoint) {
-	s.env = m.env
-	s.output.Truncate(m.outputLen)
-}
-
-func (s *State) error(msg string) {
-	s.errors <- os.NewError(msg)
-	runtime.Goexit()
-}
-
-// TODO At the moment, unnamed types are simply mapped to the default
-//      names below. For instance, all unnamed arrays are mapped to
-//      'array' which is not really sufficient. Eventually one may want
-//      to be able to specify rules for say an unnamed slice of T.
-//
-
-func typename(typ reflect.Type) string {
-	switch typ.Kind() {
-	case reflect.Array:
-		return "array"
-	case reflect.Slice:
-		return "array"
-	case reflect.Chan:
-		return "chan"
-	case reflect.Func:
-		return "func"
-	case reflect.Interface:
-		return "interface"
-	case reflect.Map:
-		return "map"
-	case reflect.Ptr:
-		return "ptr"
-	}
-	return typ.String()
-}
-
-func (s *State) getFormat(name string) expr {
-	if fexpr, found := s.fmt[name]; found {
-		return fexpr
-	}
-
-	if s.default_ != nil {
-		return s.default_
-	}
-
-	s.error(fmt.Sprintf("no format rule for type: '%s'", name))
-	return nil
-}
-
-// eval applies a format expression fexpr to a value. If the expression
-// evaluates internally to a non-nil []byte, that slice is appended to
-// the state's output buffer and eval returns true. Otherwise, eval
-// returns false and the state remains unchanged.
-//
-func (s *State) eval(fexpr expr, value reflect.Value, index int) bool {
-	// an empty format expression always evaluates
-	// to a non-nil (but empty) []byte
-	if fexpr == nil {
-		return true
-	}
-
-	switch t := fexpr.(type) {
-	case alternatives:
-		// append the result of the first alternative that evaluates to
-		// a non-nil []byte to the state's output
-		mark := s.save()
-		for _, x := range t {
-			if s.eval(x, value, index) {
-				return true
-			}
-			s.restore(mark)
-		}
-		return false
-
-	case sequence:
-		// append the result of all operands to the state's output
-		// unless a nil result is encountered
-		mark := s.save()
-		for _, x := range t {
-			if !s.eval(x, value, index) {
-				s.restore(mark)
-				return false
-			}
-		}
-		return true
-
-	case literal:
-		// write separator, if any
-		if s.hasOutput {
-			// not the first literal
-			if s.separator != nil {
-				sep := s.separator // save current separator
-				s.separator = nil  // and disable it (avoid recursion)
-				mark := s.save()
-				if !s.eval(sep, value, index) {
-					s.restore(mark)
-				}
-				s.separator = sep // enable it again
-			}
-		}
-		s.hasOutput = true
-		// write literal segments
-		for _, lit := range t {
-			if len(lit) > 1 && lit[0] == '%' {
-				// segment contains a %-format at the beginning
-				if lit[1] == '%' {
-					// "%%" is printed as a single "%"
-					s.Write(lit[1:])
-				} else {
-					// use s instead of s.output to get indentation right
-					fmt.Fprintf(s, string(lit), value.Interface())
-				}
-			} else {
-				// segment contains no %-formats
-				s.Write(lit)
-			}
-		}
-		return true // a literal never evaluates to nil
-
-	case *field:
-		// determine field value
-		switch t.fieldName {
-		case "@":
-			// field value is current value
-
-		case "*":
-			// indirection: operation is type-specific
-			switch v := value; v.Kind() {
-			case reflect.Array:
-				if v.Len() <= index {
-					return false
-				}
-				value = v.Index(index)
-
-			case reflect.Slice:
-				if v.IsNil() || v.Len() <= index {
-					return false
-				}
-				value = v.Index(index)
-
-			case reflect.Map:
-				s.error("reflection support for maps incomplete")
-
-			case reflect.Ptr:
-				if v.IsNil() {
-					return false
-				}
-				value = v.Elem()
-
-			case reflect.Interface:
-				if v.IsNil() {
-					return false
-				}
-				value = v.Elem()
-
-			case reflect.Chan:
-				s.error("reflection support for chans incomplete")
-
-			case reflect.Func:
-				s.error("reflection support for funcs incomplete")
-
-			default:
-				s.error(fmt.Sprintf("error: * does not apply to `%s`", value.Type()))
-			}
-
-		default:
-			// value is value of named field
-			var field reflect.Value
-			if sval := value; sval.Kind() == reflect.Struct {
-				field = sval.FieldByName(t.fieldName)
-				if !field.IsValid() {
-					// TODO consider just returning false in this case
-					s.error(fmt.Sprintf("error: no field `%s` in `%s`", t.fieldName, value.Type()))
-				}
-			}
-			value = field
-		}
-
-		// determine rule
-		ruleName := t.ruleName
-		if ruleName == "" {
-			// no alternate rule name, value type determines rule
-			ruleName = typename(value.Type())
-		}
-		fexpr = s.getFormat(ruleName)
-
-		mark := s.save()
-		if !s.eval(fexpr, value, index) {
-			s.restore(mark)
-			return false
-		}
-		return true
-
-	case *group:
-		// remember current indentation
-		indentLen := s.indent.Len()
-
-		// update current indentation
-		mark := s.save()
-		s.eval(t.indent, value, index)
-		// if the indentation evaluates to nil, the state's output buffer
-		// didn't change - either way it's ok to append the difference to
-		// the current indentation
-		s.indent.Write(s.output.Bytes()[mark.outputLen:s.output.Len()])
-		s.restore(mark)
-
-		// format group body
-		mark = s.save()
-		b := true
-		if !s.eval(t.body, value, index) {
-			s.restore(mark)
-			b = false
-		}
-
-		// reset indentation
-		s.indent.Truncate(indentLen)
-		return b
-
-	case *option:
-		// evaluate the body and append the result to the state's output
-		// buffer unless the result is nil
-		mark := s.save()
-		if !s.eval(t.body, value, 0) { // TODO is 0 index correct?
-			s.restore(mark)
-		}
-		return true // an option never evaluates to nil
-
-	case *repetition:
-		// evaluate the body and append the result to the state's output
-		// buffer until a result is nil
-		for i := 0; ; i++ {
-			mark := s.save()
-			// write separator, if any
-			if i > 0 && t.separator != nil {
-				// nil result from separator is ignored
-				mark := s.save()
-				if !s.eval(t.separator, value, i) {
-					s.restore(mark)
-				}
-			}
-			if !s.eval(t.body, value, i) {
-				s.restore(mark)
-				break
-			}
-		}
-		return true // a repetition never evaluates to nil
-
-	case *custom:
-		// invoke the custom formatter to obtain the result
-		mark := s.save()
-		if !t.fun(s, value.Interface(), t.ruleName) {
-			s.restore(mark)
-			return false
-		}
-		return true
-	}
-
-	panic("unreachable")
-	return false
-}
-
-// Eval formats each argument according to the format
-// f and returns the resulting []byte and os.Error. If
-// an error occurred, the []byte contains the partially
-// formatted result. An environment env may be passed
-// in which is available in custom formatters through
-// the state parameter.
-//
-func (f Format) Eval(env Environment, args ...interface{}) ([]byte, os.Error) {
-	if f == nil {
-		return nil, os.NewError("format is nil")
-	}
-
-	errors := make(chan os.Error)
-	s := newState(f, env, errors)
-
-	go func() {
-		for _, v := range args {
-			fld := reflect.ValueOf(v)
-			if !fld.IsValid() {
-				errors <- os.NewError("nil argument")
-				return
-			}
-			mark := s.save()
-			if !s.eval(s.getFormat(typename(fld.Type())), fld, 0) { // TODO is 0 index correct?
-				s.restore(mark)
-			}
-		}
-		errors <- nil // no errors
-	}()
-
-	err := <-errors
-	return s.output.Bytes(), err
-}
-
-// ----------------------------------------------------------------------------
-// Convenience functions
-
-// Fprint formats each argument according to the format f
-// and writes to w. The result is the total number of bytes
-// written and an os.Error, if any.
-//
-func (f Format) Fprint(w io.Writer, env Environment, args ...interface{}) (int, os.Error) {
-	data, err := f.Eval(env, args...)
-	if err != nil {
-		// TODO should we print partial result in case of error?
-		return 0, err
-	}
-	return w.Write(data)
-}
-
-// Print formats each argument according to the format f
-// and writes to standard output. The result is the total
-// number of bytes written and an os.Error, if any.
-//
-func (f Format) Print(args ...interface{}) (int, os.Error) {
-	return f.Fprint(os.Stdout, nil, args...)
-}
-
-// Sprint formats each argument according to the format f
-// and returns the resulting string. If an error occurs
-// during formatting, the result string contains the
-// partially formatted result followed by an error message.
-//
-func (f Format) Sprint(args ...interface{}) string {
-	var buf bytes.Buffer
-	_, err := f.Fprint(&buf, nil, args...)
-	if err != nil {
-		var i interface{} = args
-		fmt.Fprintf(&buf, "--- Sprint(%s) failed: %v", fmt.Sprint(i), err)
-	}
-	return buf.String()
-}
diff --git a/src/pkg/exp/datafmt/datafmt_test.go b/src/pkg/exp/datafmt/datafmt_test.go
deleted file mode 100644
index 87d0716..0000000
--- a/src/pkg/exp/datafmt/datafmt_test.go
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package datafmt
-
-import (
-	"fmt"
-	"testing"
-	"go/token"
-)
-
-var fset = token.NewFileSet()
-
-func parse(t *testing.T, form string, fmap FormatterMap) Format {
-	f, err := Parse(fset, "", []byte(form), fmap)
-	if err != nil {
-		t.Errorf("Parse(%s): %v", form, err)
-		return nil
-	}
-	return f
-}
-
-func verify(t *testing.T, f Format, expected string, args ...interface{}) {
-	if f == nil {
-		return // allow other tests to run
-	}
-	result := f.Sprint(args...)
-	if result != expected {
-		t.Errorf(
-			"result  : `%s`\nexpected: `%s`\n\n",
-			result, expected)
-	}
-}
-
-func formatter(s *State, value interface{}, rule_name string) bool {
-	switch rule_name {
-	case "/":
-		fmt.Fprintf(s, "%d %d %d", s.Pos().Line, s.LinePos().Column, s.Pos().Column)
-		return true
-	case "blank":
-		s.Write([]byte{' '})
-		return true
-	case "int":
-		if value.(int)&1 == 0 {
-			fmt.Fprint(s, "even ")
-		} else {
-			fmt.Fprint(s, "odd ")
-		}
-		return true
-	case "nil":
-		return false
-	case "testing.T":
-		s.Write([]byte("testing.T"))
-		return true
-	}
-	panic("unreachable")
-	return false
-}
-
-func TestCustomFormatters(t *testing.T) {
-	fmap0 := FormatterMap{"/": formatter}
-	fmap1 := FormatterMap{"int": formatter, "blank": formatter, "nil": formatter}
-	fmap2 := FormatterMap{"testing.T": formatter}
-
-	f := parse(t, `int=`, fmap0)
-	verify(t, f, ``, 1, 2, 3)
-
-	f = parse(t, `int="#"`, nil)
-	verify(t, f, `###`, 1, 2, 3)
-
-	f = parse(t, `int="#";string="%s"`, fmap0)
-	verify(t, f, "#1 0 1#1 0 7#1 0 13\n2 0 0foo2 0 8\n", 1, 2, 3, "\n", "foo", "\n")
-
-	f = parse(t, ``, fmap1)
-	verify(t, f, `even odd even odd `, 0, 1, 2, 3)
-
-	f = parse(t, `/ =@:blank; float64="#"`, fmap1)
-	verify(t, f, `# # #`, 0.0, 1.0, 2.0)
-
-	f = parse(t, `float64=@:nil`, fmap1)
-	verify(t, f, ``, 0.0, 1.0, 2.0)
-
-	f = parse(t, `testing "testing"; ptr=*`, fmap2)
-	verify(t, f, `testing.T`, t)
-
-	// TODO needs more tests
-}
-
-// ----------------------------------------------------------------------------
-// Formatting of basic and simple composite types
-
-func check(t *testing.T, form, expected string, args ...interface{}) {
-	f := parse(t, form, nil)
-	if f == nil {
-		return // allow other tests to run
-	}
-	result := f.Sprint(args...)
-	if result != expected {
-		t.Errorf(
-			"format  : %s\nresult  : `%s`\nexpected: `%s`\n\n",
-			form, result, expected)
-	}
-}
-
-func TestBasicTypes(t *testing.T) {
-	check(t, ``, ``)
-	check(t, `bool=":%v"`, `:true:false`, true, false)
-	check(t, `int="%b %d %o 0x%x"`, `101010 42 52 0x2a`, 42)
-
-	check(t, `int="%"`, `%`, 42)
-	check(t, `int="%%"`, `%`, 42)
-	check(t, `int="**%%**"`, `**%**`, 42)
-	check(t, `int="%%%%%%"`, `%%%`, 42)
-	check(t, `int="%%%d%%"`, `%42%`, 42)
-
-	const i = -42
-	const is = `-42`
-	check(t, `int  ="%d"`, is, i)
-	check(t, `int8 ="%d"`, is, int8(i))
-	check(t, `int16="%d"`, is, int16(i))
-	check(t, `int32="%d"`, is, int32(i))
-	check(t, `int64="%d"`, is, int64(i))
-
-	const u = 42
-	const us = `42`
-	check(t, `uint  ="%d"`, us, uint(u))
-	check(t, `uint8 ="%d"`, us, uint8(u))
-	check(t, `uint16="%d"`, us, uint16(u))
-	check(t, `uint32="%d"`, us, uint32(u))
-	check(t, `uint64="%d"`, us, uint64(u))
-
-	const f = 3.141592
-	const fs = `3.141592`
-	check(t, `float64="%g"`, fs, f)
-	check(t, `float32="%g"`, fs, float32(f))
-	check(t, `float64="%g"`, fs, float64(f))
-}
-
-func TestArrayTypes(t *testing.T) {
-	var a0 [10]int
-	check(t, `array="array";`, `array`, a0)
-
-	a1 := [...]int{1, 2, 3}
-	check(t, `array="array";`, `array`, a1)
-	check(t, `array={*}; int="%d";`, `123`, a1)
-	check(t, `array={* / ", "}; int="%d";`, `1, 2, 3`, a1)
-	check(t, `array={* / *}; int="%d";`, `12233`, a1)
-
-	a2 := []interface{}{42, "foo", 3.14}
-	check(t, `array={* / ", "}; interface=*; string="bar"; default="%v";`, `42, bar, 3.14`, a2)
-}
-
-func TestChanTypes(t *testing.T) {
-	var c0 chan int
-	check(t, `chan="chan"`, `chan`, c0)
-
-	c1 := make(chan int)
-	go func() { c1 <- 42 }()
-	check(t, `chan="chan"`, `chan`, c1)
-	// check(t, `chan=*`, `42`, c1);  // reflection support for chans incomplete
-}
-
-func TestFuncTypes(t *testing.T) {
-	var f0 func() int
-	check(t, `func="func"`, `func`, f0)
-
-	f1 := func() int { return 42 }
-	check(t, `func="func"`, `func`, f1)
-	// check(t, `func=*`, `42`, f1);  // reflection support for funcs incomplete
-}
-
-func TestMapTypes(t *testing.T) {
-	var m0 map[string]int
-	check(t, `map="map"`, `map`, m0)
-
-	m1 := map[string]int{}
-	check(t, `map="map"`, `map`, m1)
-	// check(t, `map=*`, ``, m1);  // reflection support for maps incomplete
-}
-
-func TestPointerTypes(t *testing.T) {
-	var p0 *int
-	check(t, `ptr="ptr"`, `ptr`, p0)
-	check(t, `ptr=*`, ``, p0)
-	check(t, `ptr=*|"nil"`, `nil`, p0)
-
-	x := 99991
-	p1 := &x
-	check(t, `ptr="ptr"`, `ptr`, p1)
-	check(t, `ptr=*; int="%d"`, `99991`, p1)
-}
-
-func TestDefaultRule(t *testing.T) {
-	check(t, `default="%v"`, `42foo3.14`, 42, "foo", 3.14)
-	check(t, `default="%v"; int="%x"`, `abcdef`, 10, 11, 12, 13, 14, 15)
-	check(t, `default="%v"; int="%x"`, `ab**ef`, 10, 11, "**", 14, 15)
-	check(t, `default="%x"; int=@:default`, `abcdef`, 10, 11, 12, 13, 14, 15)
-}
-
-func TestGlobalSeparatorRule(t *testing.T) {
-	check(t, `int="%d"; / ="-"`, `1-2-3-4`, 1, 2, 3, 4)
-	check(t, `int="%x%x"; / ="*"`, `aa*aa`, 10, 10)
-}
-
-// ----------------------------------------------------------------------------
-// Formatting of a struct
-
-type T1 struct {
-	a int
-}
-
-const F1 = `datafmt "datafmt";` +
-	`int = "%d";` +
-	`datafmt.T1 = "<" a ">";`
-
-func TestStruct1(t *testing.T) { check(t, F1, "<42>", T1{42}) }
-
-// ----------------------------------------------------------------------------
-// Formatting of a struct with an optional field (ptr)
-
-type T2 struct {
-	s string
-	p *T1
-}
-
-const F2a = F1 +
-	`string = "%s";` +
-	`ptr = *;` +
-	`datafmt.T2 = s ["-" p "-"];`
-
-const F2b = F1 +
-	`string = "%s";` +
-	`ptr = *;` +
-	`datafmt.T2 = s ("-" p "-" | "empty");`
-
-func TestStruct2(t *testing.T) {
-	check(t, F2a, "foo", T2{"foo", nil})
-	check(t, F2a, "bar-<17>-", T2{"bar", &T1{17}})
-	check(t, F2b, "fooempty", T2{"foo", nil})
-}
-
-// ----------------------------------------------------------------------------
-// Formatting of a struct with a repetitive field (slice)
-
-type T3 struct {
-	s string
-	a []int
-}
-
-const F3a = `datafmt "datafmt";` +
-	`default = "%v";` +
-	`array = *;` +
-	`datafmt.T3 = s  {" " a a / ","};`
-
-const F3b = `datafmt "datafmt";` +
-	`int = "%d";` +
-	`string = "%s";` +
-	`array = *;` +
-	`nil = ;` +
-	`empty = *:nil;` +
-	`datafmt.T3 = s [a:empty ": " {a / "-"}]`
-
-func TestStruct3(t *testing.T) {
-	check(t, F3a, "foo", T3{"foo", nil})
-	check(t, F3a, "foo 00, 11, 22", T3{"foo", []int{0, 1, 2}})
-	check(t, F3b, "bar", T3{"bar", nil})
-	check(t, F3b, "bal: 2-3-5", T3{"bal", []int{2, 3, 5}})
-}
-
-// ----------------------------------------------------------------------------
-// Formatting of a struct with alternative field
-
-type T4 struct {
-	x *int
-	a []int
-}
-
-const F4a = `datafmt "datafmt";` +
-	`int = "%d";` +
-	`ptr = *;` +
-	`array = *;` +
-	`nil = ;` +
-	`empty = *:nil;` +
-	`datafmt.T4 = "<" (x:empty x | "-") ">" `
-
-const F4b = `datafmt "datafmt";` +
-	`int = "%d";` +
-	`ptr = *;` +
-	`array = *;` +
-	`nil = ;` +
-	`empty = *:nil;` +
-	`datafmt.T4 = "<" (a:empty {a / ", "} | "-") ">" `
-
-func TestStruct4(t *testing.T) {
-	x := 7
-	check(t, F4a, "<->", T4{nil, nil})
-	check(t, F4a, "<7>", T4{&x, nil})
-	check(t, F4b, "<->", T4{nil, nil})
-	check(t, F4b, "<2, 3, 7>", T4{nil, []int{2, 3, 7}})
-}
-
-// ----------------------------------------------------------------------------
-// Formatting a struct (documentation example)
-
-type Point struct {
-	name string
-	x, y int
-}
-
-const FPoint = `datafmt "datafmt";` +
-	`int = "%d";` +
-	`hexInt = "0x%x";` +
-	`string = "---%s---";` +
-	`datafmt.Point = name "{" x ", " y:hexInt "}";`
-
-func TestStructPoint(t *testing.T) {
-	p := Point{"foo", 3, 15}
-	check(t, FPoint, "---foo---{3, 0xf}", p)
-}
-
-// ----------------------------------------------------------------------------
-// Formatting a slice (documentation example)
-
-const FSlice = `int = "%b";` +
-	`array = { * / ", " }`
-
-func TestSlice(t *testing.T) { check(t, FSlice, "10, 11, 101, 111", []int{2, 3, 5, 7}) }
-
-// TODO add more tests
diff --git a/src/pkg/exp/datafmt/parser.go b/src/pkg/exp/datafmt/parser.go
deleted file mode 100644
index a2ddd38..0000000
--- a/src/pkg/exp/datafmt/parser.go
+++ /dev/null
@@ -1,368 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package datafmt
-
-import (
-	"go/scanner"
-	"go/token"
-	"os"
-	"strconv"
-	"strings"
-)
-
-// ----------------------------------------------------------------------------
-// Parsing
-
-type parser struct {
-	scanner.ErrorVector
-	scanner scanner.Scanner
-	file    *token.File
-	pos     token.Pos   // token position
-	tok     token.Token // one token look-ahead
-	lit     string      // token literal
-
-	packs map[string]string // PackageName -> ImportPath
-	rules map[string]expr   // RuleName -> Expression
-}
-
-func (p *parser) next() {
-	p.pos, p.tok, p.lit = p.scanner.Scan()
-	switch p.tok {
-	case token.CHAN, token.FUNC, token.INTERFACE, token.MAP, token.STRUCT:
-		// Go keywords for composite types are type names
-		// returned by reflect. Accept them as identifiers.
-		p.tok = token.IDENT // p.lit is already set correctly
-	}
-}
-
-func (p *parser) init(fset *token.FileSet, filename string, src []byte) {
-	p.ErrorVector.Reset()
-	p.file = fset.AddFile(filename, fset.Base(), len(src))
-	p.scanner.Init(p.file, src, p, scanner.AllowIllegalChars) // return '@' as token.ILLEGAL w/o error message
-	p.next()                                                  // initializes pos, tok, lit
-	p.packs = make(map[string]string)
-	p.rules = make(map[string]expr)
-}
-
-func (p *parser) error(pos token.Pos, msg string) {
-	p.Error(p.file.Position(pos), msg)
-}
-
-func (p *parser) errorExpected(pos token.Pos, msg string) {
-	msg = "expected " + msg
-	if pos == p.pos {
-		// the error happened at the current position;
-		// make the error message more specific
-		msg += ", found '" + p.tok.String() + "'"
-		if p.tok.IsLiteral() {
-			msg += " " + p.lit
-		}
-	}
-	p.error(pos, msg)
-}
-
-func (p *parser) expect(tok token.Token) token.Pos {
-	pos := p.pos
-	if p.tok != tok {
-		p.errorExpected(pos, "'"+tok.String()+"'")
-	}
-	p.next() // make progress in any case
-	return pos
-}
-
-func (p *parser) parseIdentifier() string {
-	name := p.lit
-	p.expect(token.IDENT)
-	return name
-}
-
-func (p *parser) parseTypeName() (string, bool) {
-	pos := p.pos
-	name, isIdent := p.parseIdentifier(), true
-	if p.tok == token.PERIOD {
-		// got a package name, lookup package
-		if importPath, found := p.packs[name]; found {
-			name = importPath
-		} else {
-			p.error(pos, "package not declared: "+name)
-		}
-		p.next()
-		name, isIdent = name+"."+p.parseIdentifier(), false
-	}
-	return name, isIdent
-}
-
-// Parses a rule name and returns it. If the rule name is
-// a package-qualified type name, the package name is resolved.
-// The 2nd result value is true iff the rule name consists of a
-// single identifier only (and thus could be a package name).
-//
-func (p *parser) parseRuleName() (string, bool) {
-	name, isIdent := "", false
-	switch p.tok {
-	case token.IDENT:
-		name, isIdent = p.parseTypeName()
-	case token.DEFAULT:
-		name = "default"
-		p.next()
-	case token.QUO:
-		name = "/"
-		p.next()
-	default:
-		p.errorExpected(p.pos, "rule name")
-		p.next() // make progress in any case
-	}
-	return name, isIdent
-}
-
-func (p *parser) parseString() string {
-	s := ""
-	if p.tok == token.STRING {
-		s, _ = strconv.Unquote(p.lit)
-		// Unquote may fail with an error, but only if the scanner found
-		// an illegal string in the first place. In this case the error
-		// has already been reported.
-		p.next()
-		return s
-	} else {
-		p.expect(token.STRING)
-	}
-	return s
-}
-
-func (p *parser) parseLiteral() literal {
-	s := []byte(p.parseString())
-
-	// A string literal may contain %-format specifiers. To simplify
-	// and speed up printing of the literal, split it into segments
-	// that start with "%" possibly followed by a last segment that
-	// starts with some other character.
-	var list []interface{}
-	i0 := 0
-	for i := 0; i < len(s); i++ {
-		if s[i] == '%' && i+1 < len(s) {
-			// the next segment starts with a % format
-			if i0 < i {
-				// the current segment is not empty, split it off
-				list = append(list, s[i0:i])
-				i0 = i
-			}
-			i++ // skip %; let loop skip over char after %
-		}
-	}
-	// the final segment may start with any character
-	// (it is empty iff the string is empty)
-	list = append(list, s[i0:])
-
-	// convert list into a literal
-	lit := make(literal, len(list))
-	for i := 0; i < len(list); i++ {
-		lit[i] = list[i].([]byte)
-	}
-
-	return lit
-}
-
-func (p *parser) parseField() expr {
-	var fname string
-	switch p.tok {
-	case token.ILLEGAL:
-		if p.lit != "@" {
-			return nil
-		}
-		fname = "@"
-		p.next()
-	case token.MUL:
-		fname = "*"
-		p.next()
-	case token.IDENT:
-		fname = p.parseIdentifier()
-	default:
-		return nil
-	}
-
-	var ruleName string
-	if p.tok == token.COLON {
-		p.next()
-		ruleName, _ = p.parseRuleName()
-	}
-
-	return &field{fname, ruleName}
-}
-
-func (p *parser) parseOperand() (x expr) {
-	switch p.tok {
-	case token.STRING:
-		x = p.parseLiteral()
-
-	case token.LPAREN:
-		p.next()
-		x = p.parseExpression()
-		if p.tok == token.SHR {
-			p.next()
-			x = &group{x, p.parseExpression()}
-		}
-		p.expect(token.RPAREN)
-
-	case token.LBRACK:
-		p.next()
-		x = &option{p.parseExpression()}
-		p.expect(token.RBRACK)
-
-	case token.LBRACE:
-		p.next()
-		x = p.parseExpression()
-		var div expr
-		if p.tok == token.QUO {
-			p.next()
-			div = p.parseExpression()
-		}
-		x = &repetition{x, div}
-		p.expect(token.RBRACE)
-
-	default:
-		x = p.parseField() // may be nil
-	}
-
-	return x
-}
-
-func (p *parser) parseSequence() expr {
-	var list []interface{}
-
-	for x := p.parseOperand(); x != nil; x = p.parseOperand() {
-		list = append(list, x)
-	}
-
-	// no need for a sequence if list.Len() < 2
-	switch len(list) {
-	case 0:
-		return nil
-	case 1:
-		return list[0].(expr)
-	}
-
-	// convert list into a sequence
-	seq := make(sequence, len(list))
-	for i := 0; i < len(list); i++ {
-		seq[i] = list[i].(expr)
-	}
-	return seq
-}
-
-func (p *parser) parseExpression() expr {
-	var list []interface{}
-
-	for {
-		x := p.parseSequence()
-		if x != nil {
-			list = append(list, x)
-		}
-		if p.tok != token.OR {
-			break
-		}
-		p.next()
-	}
-
-	// no need for an alternatives if list.Len() < 2
-	switch len(list) {
-	case 0:
-		return nil
-	case 1:
-		return list[0].(expr)
-	}
-
-	// convert list into a alternatives
-	alt := make(alternatives, len(list))
-	for i := 0; i < len(list); i++ {
-		alt[i] = list[i].(expr)
-	}
-	return alt
-}
-
-func (p *parser) parseFormat() {
-	for p.tok != token.EOF {
-		pos := p.pos
-
-		name, isIdent := p.parseRuleName()
-		switch p.tok {
-		case token.STRING:
-			// package declaration
-			importPath := p.parseString()
-
-			// add package declaration
-			if !isIdent {
-				p.error(pos, "illegal package name: "+name)
-			} else if _, found := p.packs[name]; !found {
-				p.packs[name] = importPath
-			} else {
-				p.error(pos, "package already declared: "+name)
-			}
-
-		case token.ASSIGN:
-			// format rule
-			p.next()
-			x := p.parseExpression()
-
-			// add rule
-			if _, found := p.rules[name]; !found {
-				p.rules[name] = x
-			} else {
-				p.error(pos, "format rule already declared: "+name)
-			}
-
-		default:
-			p.errorExpected(p.pos, "package declaration or format rule")
-			p.next() // make progress in any case
-		}
-
-		if p.tok == token.SEMICOLON {
-			p.next()
-		} else {
-			break
-		}
-	}
-	p.expect(token.EOF)
-}
-
-func remap(p *parser, name string) string {
-	i := strings.Index(name, ".")
-	if i >= 0 {
-		packageName, suffix := name[0:i], name[i:]
-		// lookup package
-		if importPath, found := p.packs[packageName]; found {
-			name = importPath + suffix
-		} else {
-			var invalidPos token.Position
-			p.Error(invalidPos, "package not declared: "+packageName)
-		}
-	}
-	return name
-}
-
-// Parse parses a set of format productions from source src. Custom
-// formatters may be provided via a map of formatter functions. If
-// there are no errors, the result is a Format and the error is nil.
-// Otherwise the format is nil and a non-empty ErrorList is returned.
-//
-func Parse(fset *token.FileSet, filename string, src []byte, fmap FormatterMap) (Format, os.Error) {
-	// parse source
-	var p parser
-	p.init(fset, filename, src)
-	p.parseFormat()
-
-	// add custom formatters, if any
-	for name, form := range fmap {
-		name = remap(&p, name)
-		if _, found := p.rules[name]; !found {
-			p.rules[name] = &custom{name, form}
-		} else {
-			var invalidPos token.Position
-			p.Error(invalidPos, "formatter already declared: "+name)
-		}
-	}
-
-	return p.rules, p.GetError(scanner.NoMultiples)
-}
diff --git a/src/pkg/exp/ebnf/Makefile b/src/pkg/exp/ebnf/Makefile
new file mode 100644
index 0000000..844de67
--- /dev/null
+++ b/src/pkg/exp/ebnf/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=exp/ebnf
+GOFILES=\
+	ebnf.go\
+	parser.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/exp/ebnf/ebnf.go b/src/pkg/exp/ebnf/ebnf.go
new file mode 100644
index 0000000..cd8c83c
--- /dev/null
+++ b/src/pkg/exp/ebnf/ebnf.go
@@ -0,0 +1,269 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ebnf is a library for EBNF grammars. The input is text ([]byte)
+// satisfying the following grammar (represented itself in EBNF):
+//
+//	Production  = name "=" [ Expression ] "." .
+//	Expression  = Alternative { "|" Alternative } .
+//	Alternative = Term { Term } .
+//	Term        = name | token [ "…" token ] | Group | Option | Repetition .
+//	Group       = "(" Expression ")" .
+//	Option      = "[" Expression "]" .
+//	Repetition  = "{" Expression "}" .
+//
+// A name is a Go identifier, a token is a Go string, and comments
+// and white space follow the same rules as for the Go language.
+// Production names starting with an uppercase Unicode letter denote
+// non-terminal productions (i.e., productions which allow white-space
+// and comments between tokens); all other production names denote
+// lexical productions.
+//
+package ebnf
+
+import (
+	"errors"
+	"fmt"
+	"text/scanner"
+	"unicode"
+	"unicode/utf8"
+)
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+type errorList []error
+
+func (list errorList) Err() error {
+	if len(list) == 0 {
+		return nil
+	}
+	return list
+}
+
+func (list errorList) Error() string {
+	switch len(list) {
+	case 0:
+		return "no errors"
+	case 1:
+		return list[0].Error()
+	}
+	return fmt.Sprintf("%s (and %d more errors)", list[0], len(list)-1)
+}
+
+func newError(pos scanner.Position, msg string) error {
+	return errors.New(fmt.Sprintf("%s: %s", pos, msg))
+}
+
+// ----------------------------------------------------------------------------
+// Internal representation
+
+type (
+	// An Expression node represents a production expression.
+	Expression interface {
+		// Pos is the position of the first character of the syntactic construct
+		Pos() scanner.Position
+	}
+
+	// An Alternative node represents a non-empty list of alternative expressions.
+	Alternative []Expression // x | y | z
+
+	// A Sequence node represents a non-empty list of sequential expressions.
+	Sequence []Expression // x y z
+
+	// A Name node represents a production name.
+	Name struct {
+		StringPos scanner.Position
+		String    string
+	}
+
+	// A Token node represents a literal.
+	Token struct {
+		StringPos scanner.Position
+		String    string
+	}
+
+	// A List node represents a range of characters.
+	Range struct {
+		Begin, End *Token // begin ... end
+	}
+
+	// A Group node represents a grouped expression.
+	Group struct {
+		Lparen scanner.Position
+		Body   Expression // (body)
+	}
+
+	// An Option node represents an optional expression.
+	Option struct {
+		Lbrack scanner.Position
+		Body   Expression // [body]
+	}
+
+	// A Repetition node represents a repeated expression.
+	Repetition struct {
+		Lbrace scanner.Position
+		Body   Expression // {body}
+	}
+
+	// A Production node represents an EBNF production.
+	Production struct {
+		Name *Name
+		Expr Expression
+	}
+
+	// A Bad node stands for pieces of source code that lead to a parse error.
+	Bad struct {
+		TokPos scanner.Position
+		Error  string // parser error message
+	}
+
+	// A Grammar is a set of EBNF productions. The map
+	// is indexed by production name.
+	//
+	Grammar map[string]*Production
+)
+
+func (x Alternative) Pos() scanner.Position { return x[0].Pos() } // the parser always generates non-empty Alternative
+func (x Sequence) Pos() scanner.Position    { return x[0].Pos() } // the parser always generates non-empty Sequences
+func (x *Name) Pos() scanner.Position       { return x.StringPos }
+func (x *Token) Pos() scanner.Position      { return x.StringPos }
+func (x *Range) Pos() scanner.Position      { return x.Begin.Pos() }
+func (x *Group) Pos() scanner.Position      { return x.Lparen }
+func (x *Option) Pos() scanner.Position     { return x.Lbrack }
+func (x *Repetition) Pos() scanner.Position { return x.Lbrace }
+func (x *Production) Pos() scanner.Position { return x.Name.Pos() }
+func (x *Bad) Pos() scanner.Position        { return x.TokPos }
+
+// ----------------------------------------------------------------------------
+// Grammar verification
+
+func isLexical(name string) bool {
+	ch, _ := utf8.DecodeRuneInString(name)
+	return !unicode.IsUpper(ch)
+}
+
+type verifier struct {
+	errors   errorList
+	worklist []*Production
+	reached  Grammar // set of productions reached from (and including) the root production
+	grammar  Grammar
+}
+
+func (v *verifier) error(pos scanner.Position, msg string) {
+	v.errors = append(v.errors, newError(pos, msg))
+}
+
+func (v *verifier) push(prod *Production) {
+	name := prod.Name.String
+	if _, found := v.reached[name]; !found {
+		v.worklist = append(v.worklist, prod)
+		v.reached[name] = prod
+	}
+}
+
+func (v *verifier) verifyChar(x *Token) rune {
+	s := x.String
+	if utf8.RuneCountInString(s) != 1 {
+		v.error(x.Pos(), "single char expected, found "+s)
+		return 0
+	}
+	ch, _ := utf8.DecodeRuneInString(s)
+	return ch
+}
+
+func (v *verifier) verifyExpr(expr Expression, lexical bool) {
+	switch x := expr.(type) {
+	case nil:
+		// empty expression
+	case Alternative:
+		for _, e := range x {
+			v.verifyExpr(e, lexical)
+		}
+	case Sequence:
+		for _, e := range x {
+			v.verifyExpr(e, lexical)
+		}
+	case *Name:
+		// a production with this name must exist;
+		// add it to the worklist if not yet processed
+		if prod, found := v.grammar[x.String]; found {
+			v.push(prod)
+		} else {
+			v.error(x.Pos(), "missing production "+x.String)
+		}
+		// within a lexical production references
+		// to non-lexical productions are invalid
+		if lexical && !isLexical(x.String) {
+			v.error(x.Pos(), "reference to non-lexical production "+x.String)
+		}
+	case *Token:
+		// nothing to do for now
+	case *Range:
+		i := v.verifyChar(x.Begin)
+		j := v.verifyChar(x.End)
+		if i >= j {
+			v.error(x.Pos(), "decreasing character range")
+		}
+	case *Group:
+		v.verifyExpr(x.Body, lexical)
+	case *Option:
+		v.verifyExpr(x.Body, lexical)
+	case *Repetition:
+		v.verifyExpr(x.Body, lexical)
+	case *Bad:
+		v.error(x.Pos(), x.Error)
+	default:
+		panic(fmt.Sprintf("internal error: unexpected type %T", expr))
+	}
+}
+
+func (v *verifier) verify(grammar Grammar, start string) {
+	// find root production
+	root, found := grammar[start]
+	if !found {
+		var noPos scanner.Position
+		v.error(noPos, "no start production "+start)
+		return
+	}
+
+	// initialize verifier
+	v.worklist = v.worklist[0:0]
+	v.reached = make(Grammar)
+	v.grammar = grammar
+
+	// work through the worklist
+	v.push(root)
+	for {
+		n := len(v.worklist) - 1
+		if n < 0 {
+			break
+		}
+		prod := v.worklist[n]
+		v.worklist = v.worklist[0:n]
+		v.verifyExpr(prod.Expr, isLexical(prod.Name.String))
+	}
+
+	// check if all productions were reached
+	if len(v.reached) < len(v.grammar) {
+		for name, prod := range v.grammar {
+			if _, found := v.reached[name]; !found {
+				v.error(prod.Pos(), name+" is unreachable")
+			}
+		}
+	}
+}
+
+// Verify checks that:
+//	- all productions used are defined
+//	- all productions defined are used when beginning at start
+//	- lexical productions refer only to other lexical productions
+//
+// Position information is interpreted relative to the file set fset.
+//
+func Verify(grammar Grammar, start string) error {
+	var v verifier
+	v.verify(grammar, start)
+	return v.errors.Err()
+}
diff --git a/src/pkg/exp/ebnf/ebnf_test.go b/src/pkg/exp/ebnf/ebnf_test.go
new file mode 100644
index 0000000..8cfd6b9
--- /dev/null
+++ b/src/pkg/exp/ebnf/ebnf_test.go
@@ -0,0 +1,71 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ebnf
+
+import (
+	"bytes"
+	"testing"
+)
+
+var goodGrammars = []string{
+	`Program = .`,
+
+	`Program = foo .
+	 foo = "foo" .`,
+
+	`Program = "a" | "b" "c" .`,
+
+	`Program = "a" … "z" .`,
+
+	`Program = Song .
+	 Song = { Note } .
+	 Note = Do | (Re | Mi | Fa | So | La) | Ti .
+	 Do = "c" .
+	 Re = "d" .
+	 Mi = "e" .
+	 Fa = "f" .
+	 So = "g" .
+	 La = "a" .
+	 Ti = ti .
+	 ti = "b" .`,
+}
+
+var badGrammars = []string{
+	`Program = | .`,
+	`Program = | b .`,
+	`Program = a … b .`,
+	`Program = "a" … .`,
+	`Program = … "b" .`,
+	`Program = () .`,
+	`Program = [] .`,
+	`Program = {} .`,
+}
+
+func checkGood(t *testing.T, src string) {
+	grammar, err := Parse("", bytes.NewBuffer([]byte(src)))
+	if err != nil {
+		t.Errorf("Parse(%s) failed: %v", src, err)
+		return
+	}
+	if err = Verify(grammar, "Program"); err != nil {
+		t.Errorf("Verify(%s) failed: %v", src, err)
+	}
+}
+
+func checkBad(t *testing.T, src string) {
+	_, err := Parse("", bytes.NewBuffer([]byte(src)))
+	if err == nil {
+		t.Errorf("Parse(%s) should have failed", src)
+	}
+}
+
+func TestGrammars(t *testing.T) {
+	for _, src := range goodGrammars {
+		checkGood(t, src)
+	}
+	for _, src := range badGrammars {
+		checkBad(t, src)
+	}
+}
diff --git a/src/pkg/exp/ebnf/parser.go b/src/pkg/exp/ebnf/parser.go
new file mode 100644
index 0000000..7a7e3cc
--- /dev/null
+++ b/src/pkg/exp/ebnf/parser.go
@@ -0,0 +1,190 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ebnf
+
+import (
+	"io"
+	"strconv"
+	"text/scanner"
+)
+
+type parser struct {
+	errors  errorList
+	scanner scanner.Scanner
+	pos     scanner.Position // token position
+	tok     rune             // one token look-ahead
+	lit     string           // token literal
+}
+
+func (p *parser) next() {
+	p.tok = p.scanner.Scan()
+	p.pos = p.scanner.Position
+	p.lit = p.scanner.TokenText()
+}
+
+func (p *parser) error(pos scanner.Position, msg string) {
+	p.errors = append(p.errors, newError(pos, msg))
+}
+
+func (p *parser) errorExpected(pos scanner.Position, msg string) {
+	msg = `expected "` + msg + `"`
+	if pos.Offset == p.pos.Offset {
+		// the error happened at the current position;
+		// make the error message more specific
+		msg += ", found " + scanner.TokenString(p.tok)
+		if p.tok < 0 {
+			msg += " " + p.lit
+		}
+	}
+	p.error(pos, msg)
+}
+
+func (p *parser) expect(tok rune) scanner.Position {
+	pos := p.pos
+	if p.tok != tok {
+		p.errorExpected(pos, scanner.TokenString(tok))
+	}
+	p.next() // make progress in any case
+	return pos
+}
+
+func (p *parser) parseIdentifier() *Name {
+	pos := p.pos
+	name := p.lit
+	p.expect(scanner.Ident)
+	return &Name{pos, name}
+}
+
+func (p *parser) parseToken() *Token {
+	pos := p.pos
+	value := ""
+	if p.tok == scanner.String {
+		value, _ = strconv.Unquote(p.lit)
+		// Unquote may fail with an error, but only if the scanner found
+		// an illegal string in the first place. In this case the error
+		// has already been reported.
+		p.next()
+	} else {
+		p.expect(scanner.String)
+	}
+	return &Token{pos, value}
+}
+
+// ParseTerm returns nil if no term was found.
+func (p *parser) parseTerm() (x Expression) {
+	pos := p.pos
+
+	switch p.tok {
+	case scanner.Ident:
+		x = p.parseIdentifier()
+
+	case scanner.String:
+		tok := p.parseToken()
+		x = tok
+		const ellipsis = '…' // U+2026, the horizontal ellipsis character
+		if p.tok == ellipsis {
+			p.next()
+			x = &Range{tok, p.parseToken()}
+		}
+
+	case '(':
+		p.next()
+		x = &Group{pos, p.parseExpression()}
+		p.expect(')')
+
+	case '[':
+		p.next()
+		x = &Option{pos, p.parseExpression()}
+		p.expect(']')
+
+	case '{':
+		p.next()
+		x = &Repetition{pos, p.parseExpression()}
+		p.expect('}')
+	}
+
+	return x
+}
+
+func (p *parser) parseSequence() Expression {
+	var list Sequence
+
+	for x := p.parseTerm(); x != nil; x = p.parseTerm() {
+		list = append(list, x)
+	}
+
+	// no need for a sequence if list.Len() < 2
+	switch len(list) {
+	case 0:
+		p.errorExpected(p.pos, "term")
+		return &Bad{p.pos, "term expected"}
+	case 1:
+		return list[0]
+	}
+
+	return list
+}
+
+func (p *parser) parseExpression() Expression {
+	var list Alternative
+
+	for {
+		list = append(list, p.parseSequence())
+		if p.tok != '|' {
+			break
+		}
+		p.next()
+	}
+	// len(list) > 0
+
+	// no need for an Alternative node if list.Len() < 2
+	if len(list) == 1 {
+		return list[0]
+	}
+
+	return list
+}
+
+func (p *parser) parseProduction() *Production {
+	name := p.parseIdentifier()
+	p.expect('=')
+	var expr Expression
+	if p.tok != '.' {
+		expr = p.parseExpression()
+	}
+	p.expect('.')
+	return &Production{name, expr}
+}
+
+func (p *parser) parse(filename string, src io.Reader) Grammar {
+	p.scanner.Init(src)
+	p.scanner.Filename = filename
+	p.next() // initializes pos, tok, lit
+
+	grammar := make(Grammar)
+	for p.tok != scanner.EOF {
+		prod := p.parseProduction()
+		name := prod.Name.String
+		if _, found := grammar[name]; !found {
+			grammar[name] = prod
+		} else {
+			p.error(prod.Pos(), name+" declared already")
+		}
+	}
+
+	return grammar
+}
+
+// Parse parses a set of EBNF productions from source src.
+// It returns a set of productions. Errors are reported
+// for incorrect syntax and if a production is declared
+// more than once; the filename is used only for error
+// positions.
+//
+func Parse(filename string, src io.Reader) (Grammar, error) {
+	var p parser
+	grammar := p.parse(filename, src)
+	return grammar, p.errors.Err()
+}
diff --git a/src/pkg/exp/ebnflint/Makefile b/src/pkg/exp/ebnflint/Makefile
new file mode 100644
index 0000000..2057b07
--- /dev/null
+++ b/src/pkg/exp/ebnflint/Makefile
@@ -0,0 +1,15 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=ebnflint
+GOFILES=\
+	ebnflint.go\
+
+include ../../../Make.cmd
+
+test: $(TARG)
+	$(TARG) -start="SourceFile" "$(GOROOT)"/doc/go_spec.html
+
diff --git a/src/cmd/ebnflint/doc.go b/src/pkg/exp/ebnflint/doc.go
similarity index 100%
rename from src/cmd/ebnflint/doc.go
rename to src/pkg/exp/ebnflint/doc.go
diff --git a/src/pkg/exp/ebnflint/ebnflint.go b/src/pkg/exp/ebnflint/ebnflint.go
new file mode 100644
index 0000000..2cb5aa6
--- /dev/null
+++ b/src/pkg/exp/ebnflint/ebnflint.go
@@ -0,0 +1,122 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"exp/ebnf"
+	"flag"
+	"fmt"
+	"go/scanner"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+)
+
+var fset = token.NewFileSet()
+var start = flag.String("start", "Start", "name of start production")
+
+func usage() {
+	fmt.Fprintf(os.Stderr, "usage: ebnflint [flags] [filename]\n")
+	flag.PrintDefaults()
+	os.Exit(1)
+}
+
+// Markers around EBNF sections in .html files
+var (
+	open  = []byte(`<pre class="ebnf">`)
+	close = []byte(`</pre>`)
+)
+
+func report(err error) {
+	scanner.PrintError(os.Stderr, err)
+	os.Exit(1)
+}
+
+func extractEBNF(src []byte) []byte {
+	var buf bytes.Buffer
+
+	for {
+		// i = beginning of EBNF text
+		i := bytes.Index(src, open)
+		if i < 0 {
+			break // no EBNF found - we are done
+		}
+		i += len(open)
+
+		// write as many newlines as found in the excluded text
+		// to maintain correct line numbers in error messages
+		for _, ch := range src[0:i] {
+			if ch == '\n' {
+				buf.WriteByte('\n')
+			}
+		}
+
+		// j = end of EBNF text (or end of source)
+		j := bytes.Index(src[i:], close) // close marker
+		if j < 0 {
+			j = len(src) - i
+		}
+		j += i
+
+		// copy EBNF text
+		buf.Write(src[i:j])
+
+		// advance
+		src = src[j:]
+	}
+
+	return buf.Bytes()
+}
+
+func main() {
+	flag.Parse()
+
+	var (
+		name string
+		r    io.Reader
+	)
+	switch flag.NArg() {
+	case 0:
+		name, r = "<stdin>", os.Stdin
+	case 1:
+		name = flag.Arg(0)
+	default:
+		usage()
+	}
+
+	if err := verify(name, *start, r); err != nil {
+		report(err)
+	}
+}
+
+func verify(name, start string, r io.Reader) error {
+	if r == nil {
+		f, err := os.Open(name)
+		if err != nil {
+			return err
+		}
+		defer f.Close()
+		r = f
+	}
+
+	src, err := ioutil.ReadAll(r)
+	if err != nil {
+		return err
+	}
+
+	if filepath.Ext(name) == ".html" || bytes.Index(src, open) >= 0 {
+		src = extractEBNF(src)
+	}
+
+	grammar, err := ebnf.Parse(name, bytes.NewBuffer(src))
+	if err != nil {
+		return err
+	}
+
+	return ebnf.Verify(grammar, start)
+}
diff --git a/src/pkg/exp/ebnflint/ebnflint_test.go b/src/pkg/exp/ebnflint/ebnflint_test.go
new file mode 100644
index 0000000..875dbc1
--- /dev/null
+++ b/src/pkg/exp/ebnflint/ebnflint_test.go
@@ -0,0 +1,16 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"runtime"
+	"testing"
+)
+
+func TestSpec(t *testing.T) {
+	if err := verify(runtime.GOROOT()+"/doc/go_spec.html", "SourceFile", nil); err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/src/pkg/exp/gotype/Makefile b/src/pkg/exp/gotype/Makefile
new file mode 100644
index 0000000..230242c
--- /dev/null
+++ b/src/pkg/exp/gotype/Makefile
@@ -0,0 +1,17 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=gotype
+GOFILES=\
+	gotype.go\
+
+include ../../../Make.cmd
+
+test:
+	gotest
+
+testshort:
+	gotest -test.short
diff --git a/src/cmd/gotype/doc.go b/src/pkg/exp/gotype/doc.go
similarity index 100%
rename from src/cmd/gotype/doc.go
rename to src/pkg/exp/gotype/doc.go
diff --git a/src/pkg/exp/gotype/gotype.go b/src/pkg/exp/gotype/gotype.go
new file mode 100644
index 0000000..a2a9361
--- /dev/null
+++ b/src/pkg/exp/gotype/gotype.go
@@ -0,0 +1,193 @@
+// Copyright 2011 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 (
+	"errors"
+	"exp/types"
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+var (
+	// main operation modes
+	pkgName   = flag.String("p", "", "process only those files in package pkgName")
+	recursive = flag.Bool("r", false, "recursively process subdirectories")
+	verbose   = flag.Bool("v", false, "verbose mode")
+	allErrors = flag.Bool("e", false, "print all (including spurious) errors")
+
+	// debugging support
+	printTrace = flag.Bool("trace", false, "print parse trace")
+	printAST   = flag.Bool("ast", false, "print AST")
+)
+
+var exitCode = 0
+
+func usage() {
+	fmt.Fprintf(os.Stderr, "usage: gotype [flags] [path ...]\n")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func report(err error) {
+	scanner.PrintError(os.Stderr, err)
+	exitCode = 2
+}
+
+// parse returns the AST for the Go source src.
+// The filename is for error reporting only.
+// The result is nil if there were errors or if
+// the file does not belong to the -p package.
+func parse(fset *token.FileSet, filename string, src []byte) *ast.File {
+	if *verbose {
+		fmt.Println(filename)
+	}
+
+	// ignore files with different package name
+	if *pkgName != "" {
+		file, err := parser.ParseFile(fset, filename, src, parser.PackageClauseOnly)
+		if err != nil {
+			report(err)
+			return nil
+		}
+		if file.Name.Name != *pkgName {
+			if *verbose {
+				fmt.Printf("\tignored (package %s)\n", file.Name.Name)
+			}
+			return nil
+		}
+	}
+
+	// parse entire file
+	mode := parser.DeclarationErrors
+	if *allErrors {
+		mode |= parser.SpuriousErrors
+	}
+	if *printTrace {
+		mode |= parser.Trace
+	}
+	file, err := parser.ParseFile(fset, filename, src, mode)
+	if err != nil {
+		report(err)
+		return nil
+	}
+	if *printAST {
+		ast.Print(fset, file)
+	}
+
+	return file
+}
+
+func parseStdin(fset *token.FileSet) (files map[string]*ast.File) {
+	files = make(map[string]*ast.File)
+	src, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		report(err)
+		return
+	}
+	const filename = "<standard input>"
+	if file := parse(fset, filename, src); file != nil {
+		files[filename] = file
+	}
+	return
+}
+
+func parseFiles(fset *token.FileSet, filenames []string) (files map[string]*ast.File) {
+	files = make(map[string]*ast.File)
+	for _, filename := range filenames {
+		src, err := ioutil.ReadFile(filename)
+		if err != nil {
+			report(err)
+			continue
+		}
+		if file := parse(fset, filename, src); file != nil {
+			if files[filename] != nil {
+				report(errors.New(fmt.Sprintf("%q: duplicate file", filename)))
+				continue
+			}
+			files[filename] = file
+		}
+	}
+	return
+}
+
+func isGoFilename(filename string) bool {
+	// ignore non-Go files
+	return !strings.HasPrefix(filename, ".") && strings.HasSuffix(filename, ".go")
+}
+
+func processDirectory(dirname string) {
+	f, err := os.Open(dirname)
+	if err != nil {
+		report(err)
+		return
+	}
+	filenames, err := f.Readdirnames(-1)
+	f.Close()
+	if err != nil {
+		report(err)
+		// continue since filenames may not be empty
+	}
+	for i, filename := range filenames {
+		filenames[i] = filepath.Join(dirname, filename)
+	}
+	processFiles(filenames, false)
+}
+
+func processFiles(filenames []string, allFiles bool) {
+	i := 0
+	for _, filename := range filenames {
+		switch info, err := os.Stat(filename); {
+		case err != nil:
+			report(err)
+		case info.IsDir():
+			if allFiles || *recursive {
+				processDirectory(filename)
+			}
+		default:
+			if allFiles || isGoFilename(info.Name()) {
+				filenames[i] = filename
+				i++
+			}
+		}
+	}
+	fset := token.NewFileSet()
+	processPackage(fset, parseFiles(fset, filenames[0:i]))
+}
+
+func processPackage(fset *token.FileSet, files map[string]*ast.File) {
+	// make a package (resolve all identifiers)
+	pkg, err := ast.NewPackage(fset, files, types.GcImporter, types.Universe)
+	if err != nil {
+		report(err)
+		return
+	}
+	_, err = types.Check(fset, pkg)
+	if err != nil {
+		report(err)
+	}
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+
+	if flag.NArg() == 0 {
+		fset := token.NewFileSet()
+		processPackage(fset, parseStdin(fset))
+	} else {
+		processFiles(flag.Args(), true)
+	}
+
+	os.Exit(exitCode)
+}
diff --git a/src/pkg/exp/gotype/gotype_test.go b/src/pkg/exp/gotype/gotype_test.go
new file mode 100644
index 0000000..8732d4c
--- /dev/null
+++ b/src/pkg/exp/gotype/gotype_test.go
@@ -0,0 +1,49 @@
+// Copyright 2011 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 (
+	"path/filepath"
+	"runtime"
+	"testing"
+)
+
+func runTest(t *testing.T, path, pkg string) {
+	exitCode = 0
+	*pkgName = pkg
+	*recursive = false
+
+	if pkg == "" {
+		processFiles([]string{path}, true)
+	} else {
+		processDirectory(path)
+	}
+
+	if exitCode != 0 {
+		t.Errorf("processing %s failed: exitCode = %d", path, exitCode)
+	}
+}
+
+var tests = []struct {
+	path string
+	pkg  string
+}{
+	// individual files
+	{"testdata/test1.go", ""},
+
+	// directories
+	{filepath.Join(runtime.GOROOT(), "src/pkg/go/ast"), "ast"},
+	{filepath.Join(runtime.GOROOT(), "src/pkg/go/doc"), "doc"},
+	{filepath.Join(runtime.GOROOT(), "src/pkg/go/token"), "scanner"},
+	{filepath.Join(runtime.GOROOT(), "src/pkg/go/scanner"), "scanner"},
+	{filepath.Join(runtime.GOROOT(), "src/pkg/go/parser"), "parser"},
+	{filepath.Join(runtime.GOROOT(), "src/pkg/exp/types"), "types"},
+}
+
+func Test(t *testing.T) {
+	for _, test := range tests {
+		runTest(t, test.path, test.pkg)
+	}
+}
diff --git a/src/pkg/exp/gotype/testdata/test1.go b/src/pkg/exp/gotype/testdata/test1.go
new file mode 100644
index 0000000..ba8a51f
--- /dev/null
+++ b/src/pkg/exp/gotype/testdata/test1.go
@@ -0,0 +1,27 @@
+// Copyright 2011 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 p
+
+func _() {
+	// the scope of a local type declaration starts immediately after the type name
+	type T struct{ _ *T }
+}
+
+func _(x interface{}) {
+	// the variable defined by a TypeSwitchGuard is declared in each TypeCaseClause
+	switch t := x.(type) {
+	case int:
+		_ = t
+	case float32:
+		_ = t
+	default:
+		_ = t
+	}
+
+	// the variable defined by a TypeSwitchGuard must not conflict with other
+	// variables declared in the initial simple statement
+	switch t := 0; t := x.(type) {
+	}
+}
diff --git a/src/pkg/exp/gui/Makefile b/src/pkg/exp/gui/Makefile
deleted file mode 100644
index af065e4..0000000
--- a/src/pkg/exp/gui/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=exp/gui
-GOFILES=\
-	gui.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/exp/gui/gui.go b/src/pkg/exp/gui/gui.go
deleted file mode 100644
index 1714991..0000000
--- a/src/pkg/exp/gui/gui.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package gui defines a basic graphical user interface programming model.
-package gui
-
-import (
-	"image"
-	"image/draw"
-	"os"
-)
-
-// A Window represents a single graphics window.
-type Window interface {
-	// Screen returns an editable Image for the window.
-	Screen() draw.Image
-	// FlushImage flushes changes made to Screen() back to screen.
-	FlushImage()
-	// EventChan returns a channel carrying UI events such as key presses,
-	// mouse movements and window resizes.
-	EventChan() <-chan interface{}
-	// Close closes the window.
-	Close() os.Error
-}
-
-// A KeyEvent is sent for a key press or release.
-type KeyEvent struct {
-	// The value k represents key k being pressed.
-	// The value -k represents key k being released.
-	// The specific set of key values is not specified,
-	// but ordinary characters represent themselves.
-	Key int
-}
-
-// A MouseEvent is sent for a button press or release or for a mouse movement.
-type MouseEvent struct {
-	// Buttons is a bit mask of buttons: 1<<0 is left, 1<<1 middle, 1<<2 right.
-	// It represents button state and not necessarily the state delta: bit 0
-	// being on means that the left mouse button is down, but does not imply
-	// that the same button was up in the previous MouseEvent.
-	Buttons int
-	// Loc is the location of the cursor.
-	Loc image.Point
-	// Nsec is the event's timestamp.
-	Nsec int64
-}
-
-// A ConfigEvent is sent each time the window's color model or size changes.
-// The client should respond by calling Window.Screen to obtain a new image.
-type ConfigEvent struct {
-	Config image.Config
-}
-
-// An ErrEvent is sent when an error occurs.
-type ErrEvent struct {
-	Err os.Error
-}
diff --git a/src/pkg/exp/gui/x11/Makefile b/src/pkg/exp/gui/x11/Makefile
deleted file mode 100644
index 88cc1e2..0000000
--- a/src/pkg/exp/gui/x11/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../../Make.inc
-
-TARG=exp/gui/x11
-GOFILES=\
-	auth.go\
-	conn.go\
-
-include ../../../../Make.pkg
diff --git a/src/pkg/exp/gui/x11/auth.go b/src/pkg/exp/gui/x11/auth.go
deleted file mode 100644
index d48936a..0000000
--- a/src/pkg/exp/gui/x11/auth.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package x11
-
-import (
-	"bufio"
-	"io"
-	"os"
-)
-
-// readU16BE reads a big-endian uint16 from r, using b as a scratch buffer.
-func readU16BE(r io.Reader, b []byte) (uint16, os.Error) {
-	_, err := io.ReadFull(r, b[0:2])
-	if err != nil {
-		return 0, err
-	}
-	return uint16(b[0])<<8 + uint16(b[1]), nil
-}
-
-// readStr reads a length-prefixed string from r, using b as a scratch buffer.
-func readStr(r io.Reader, b []byte) (string, os.Error) {
-	n, err := readU16BE(r, b)
-	if err != nil {
-		return "", err
-	}
-	if int(n) > len(b) {
-		return "", os.NewError("Xauthority entry too long for buffer")
-	}
-	_, err = io.ReadFull(r, b[0:n])
-	if err != nil {
-		return "", err
-	}
-	return string(b[0:n]), nil
-}
-
-// readAuth reads the X authority file and returns the name/data pair for the display.
-// displayStr is the "12" out of a $DISPLAY like ":12.0".
-func readAuth(displayStr string) (name, data string, err os.Error) {
-	// b is a scratch buffer to use and should be at least 256 bytes long
-	// (i.e. it should be able to hold a hostname).
-	var b [256]byte
-	// As per /usr/include/X11/Xauth.h.
-	const familyLocal = 256
-
-	fn := os.Getenv("XAUTHORITY")
-	if fn == "" {
-		home := os.Getenv("HOME")
-		if home == "" {
-			err = os.NewError("Xauthority not found: $XAUTHORITY, $HOME not set")
-			return
-		}
-		fn = home + "/.Xauthority"
-	}
-	r, err := os.Open(fn)
-	if err != nil {
-		return
-	}
-	defer r.Close()
-	br := bufio.NewReader(r)
-
-	hostname, err := os.Hostname()
-	if err != nil {
-		return
-	}
-	for {
-		family, err := readU16BE(br, b[0:2])
-		if err != nil {
-			return
-		}
-		addr, err := readStr(br, b[0:])
-		if err != nil {
-			return
-		}
-		disp, err := readStr(br, b[0:])
-		if err != nil {
-			return
-		}
-		name0, err := readStr(br, b[0:])
-		if err != nil {
-			return
-		}
-		data0, err := readStr(br, b[0:])
-		if err != nil {
-			return
-		}
-		if family == familyLocal && addr == hostname && disp == displayStr {
-			return name0, data0, nil
-		}
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/exp/gui/x11/conn.go b/src/pkg/exp/gui/x11/conn.go
deleted file mode 100644
index 4645073..0000000
--- a/src/pkg/exp/gui/x11/conn.go
+++ /dev/null
@@ -1,627 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package x11 implements an X11 backend for the exp/gui package.
-//
-// The X protocol specification is at ftp://ftp.x.org/pub/X11R7.0/doc/PDF/proto.pdf.
-// A summary of the wire format can be found in XCB's xproto.xml.
-package x11
-
-import (
-	"bufio"
-	"exp/gui"
-	"image"
-	"image/draw"
-	"io"
-	"log"
-	"net"
-	"os"
-	"strconv"
-	"strings"
-	"time"
-)
-
-type resID uint32 // X resource IDs.
-
-// TODO(nigeltao): Handle window resizes.
-const (
-	windowHeight = 600
-	windowWidth  = 800
-)
-
-const (
-	keymapLo = 8
-	keymapHi = 255
-)
-
-type conn struct {
-	c io.Closer
-	r *bufio.Reader
-	w *bufio.Writer
-
-	gc, window, root, visual resID
-
-	img        *image.RGBA
-	eventc     chan interface{}
-	mouseState gui.MouseEvent
-
-	buf [256]byte // General purpose scratch buffer.
-
-	flush     chan bool
-	flushBuf0 [24]byte
-	flushBuf1 [4 * 1024]byte
-}
-
-// writeSocket runs in its own goroutine, serving both FlushImage calls
-// directly from the exp/gui client and indirectly from X expose events.
-// It paints c.img to the X server via PutImage requests.
-func (c *conn) writeSocket() {
-	defer c.c.Close()
-	for _ = range c.flush {
-		b := c.img.Bounds()
-		if b.Empty() {
-			continue
-		}
-		// Each X request has a 16-bit length (in terms of 4-byte units). To avoid going over
-		// this limit, we send PutImage for each row of the image, rather than trying to paint
-		// the entire image in one X request. This approach could easily be optimized (or the
-		// X protocol may have an escape sequence to delimit very large requests).
-		// TODO(nigeltao): See what XCB's xcb_put_image does in this situation.
-		units := 6 + b.Dx()
-		if units > 0xffff || b.Dy() > 0xffff {
-			log.Print("x11: window is too large for PutImage")
-			return
-		}
-
-		c.flushBuf0[0] = 0x48 // PutImage opcode.
-		c.flushBuf0[1] = 0x02 // XCB_IMAGE_FORMAT_Z_PIXMAP.
-		c.flushBuf0[2] = uint8(units)
-		c.flushBuf0[3] = uint8(units >> 8)
-		setU32LE(c.flushBuf0[4:8], uint32(c.window))
-		setU32LE(c.flushBuf0[8:12], uint32(c.gc))
-		setU32LE(c.flushBuf0[12:16], 1<<16|uint32(b.Dx()))
-		c.flushBuf0[21] = 0x18 // depth = 24 bits.
-
-		for y := b.Min.Y; y < b.Max.Y; y++ {
-			setU32LE(c.flushBuf0[16:20], uint32(y<<16))
-			if _, err := c.w.Write(c.flushBuf0[:24]); err != nil {
-				if err != os.EOF {
-					log.Println("x11:", err.String())
-				}
-				return
-			}
-			p := c.img.Pix[(y-b.Min.Y)*c.img.Stride:]
-			for x, dx := 0, 4*b.Dx(); x < dx; {
-				nx := dx - x
-				if nx > len(c.flushBuf1) {
-					nx = len(c.flushBuf1) &^ 3
-				}
-				for i := 0; i < nx; i += 4 {
-					// X11's order is BGRX, not RGBA.
-					c.flushBuf1[i+0] = p[x+i+2]
-					c.flushBuf1[i+1] = p[x+i+1]
-					c.flushBuf1[i+2] = p[x+i+0]
-				}
-				x += nx
-				if _, err := c.w.Write(c.flushBuf1[:nx]); err != nil {
-					if err != os.EOF {
-						log.Println("x11:", err.String())
-					}
-					return
-				}
-			}
-		}
-		if err := c.w.Flush(); err != nil {
-			if err != os.EOF {
-				log.Println("x11:", err.String())
-			}
-			return
-		}
-	}
-}
-
-func (c *conn) Screen() draw.Image { return c.img }
-
-func (c *conn) FlushImage() {
-	select {
-	case c.flush <- false:
-		// Flush notification sent.
-	default:
-		// Could not send.
-		// Flush notification must be pending already.
-	}
-}
-
-func (c *conn) Close() os.Error {
-	// Shut down the writeSocket goroutine. This will close the socket to the
-	// X11 server, which will cause c.eventc to close.
-	close(c.flush)
-	for _ = range c.eventc {
-		// Drain the channel to allow the readSocket goroutine to shut down.
-	}
-	return nil
-}
-
-func (c *conn) EventChan() <-chan interface{} { return c.eventc }
-
-// readSocket runs in its own goroutine, reading X events and sending gui
-// events on c's EventChan.
-func (c *conn) readSocket() {
-	var (
-		keymap            [256][]int
-		keysymsPerKeycode int
-	)
-	defer close(c.eventc)
-	for {
-		// X events are always 32 bytes long.
-		if _, err := io.ReadFull(c.r, c.buf[:32]); err != nil {
-			if err != os.EOF {
-				c.eventc <- gui.ErrEvent{err}
-			}
-			return
-		}
-		switch c.buf[0] {
-		case 0x01: // Reply from a request (e.g. GetKeyboardMapping).
-			cookie := int(c.buf[3])<<8 | int(c.buf[2])
-			if cookie != 1 {
-				// We issued only one request (GetKeyboardMapping) with a cookie of 1,
-				// so we shouldn't get any other reply from the X server.
-				c.eventc <- gui.ErrEvent{os.NewError("x11: unexpected cookie")}
-				return
-			}
-			keysymsPerKeycode = int(c.buf[1])
-			b := make([]int, 256*keysymsPerKeycode)
-			for i := range keymap {
-				keymap[i] = b[i*keysymsPerKeycode : (i+1)*keysymsPerKeycode]
-			}
-			for i := keymapLo; i <= keymapHi; i++ {
-				m := keymap[i]
-				for j := range m {
-					u, err := readU32LE(c.r, c.buf[:4])
-					if err != nil {
-						if err != os.EOF {
-							c.eventc <- gui.ErrEvent{err}
-						}
-						return
-					}
-					m[j] = int(u)
-				}
-			}
-		case 0x02, 0x03: // Key press, key release.
-			// X Keyboard Encoding is documented at http://tronche.com/gui/x/xlib/input/keyboard-encoding.html
-			// TODO(nigeltao): Do we need to implement the "MODE SWITCH / group modifier" feature
-			// or is that some no-longer-used X construct?
-			if keysymsPerKeycode < 2 {
-				// Either we haven't yet received the GetKeyboardMapping reply or
-				// the X server has sent one that's too short.
-				continue
-			}
-			keycode := int(c.buf[1])
-			shift := int(c.buf[28]) & 0x01
-			keysym := keymap[keycode][shift]
-			if keysym == 0 {
-				keysym = keymap[keycode][0]
-			}
-			// TODO(nigeltao): Should we send KeyEvents for Shift/Ctrl/Alt? Should Shift-A send
-			// the same int down the channel as the sent on just the A key?
-			// TODO(nigeltao): How should IME events (e.g. key presses that should generate CJK text) work? Or
-			// is that outside the scope of the gui.Window interface?
-			if c.buf[0] == 0x03 {
-				keysym = -keysym
-			}
-			c.eventc <- gui.KeyEvent{keysym}
-		case 0x04, 0x05: // Button press, button release.
-			mask := 1 << (c.buf[1] - 1)
-			if c.buf[0] == 0x04 {
-				c.mouseState.Buttons |= mask
-			} else {
-				c.mouseState.Buttons &^= mask
-			}
-			c.mouseState.Nsec = time.Nanoseconds()
-			c.eventc <- c.mouseState
-		case 0x06: // Motion notify.
-			c.mouseState.Loc.X = int(int16(c.buf[25])<<8 | int16(c.buf[24]))
-			c.mouseState.Loc.Y = int(int16(c.buf[27])<<8 | int16(c.buf[26]))
-			c.mouseState.Nsec = time.Nanoseconds()
-			c.eventc <- c.mouseState
-		case 0x0c: // Expose.
-			// A single user action could trigger multiple expose events (e.g. if moving another
-			// window with XShape'd rounded corners over our window). In that case, the X server will
-			// send a uint16 count (in bytes 16-17) of the number of additional expose events coming.
-			// We could parse each event for the (x, y, width, height) and maintain a minimal dirty
-			// rectangle, but for now, the simplest approach is to paint the entire window, when
-			// receiving the final event in the series.
-			if c.buf[17] == 0 && c.buf[16] == 0 {
-				// TODO(nigeltao): Should we ignore the very first expose event? A freshly mapped window
-				// will trigger expose, but until the first c.FlushImage call, there's probably nothing to
-				// paint but black. For an 800x600 window, at 4 bytes per pixel, each repaint writes about
-				// 2MB over the socket.
-				c.FlushImage()
-			}
-			// TODO(nigeltao): Should we listen to DestroyNotify (0x11) and ResizeRequest (0x19) events?
-			// What about EnterNotify (0x07) and LeaveNotify (0x08)?
-		}
-	}
-}
-
-// connect connects to the X server given by the full X11 display name (e.g.
-// ":12.0") and returns the connection as well as the portion of the full name
-// that is the display number (e.g. "12").
-// Examples:
-//	connect(":1")                 // calls net.Dial("unix", "", "/tmp/.X11-unix/X1"), displayStr="1"
-//	connect("/tmp/launch-123/:0") // calls net.Dial("unix", "", "/tmp/launch-123/:0"), displayStr="0"
-//	connect("hostname:2.1")       // calls net.Dial("tcp", "", "hostname:6002"), displayStr="2"
-//	connect("tcp/hostname:1.0")   // calls net.Dial("tcp", "", "hostname:6001"), displayStr="1"
-func connect(display string) (conn net.Conn, displayStr string, err os.Error) {
-	colonIdx := strings.LastIndex(display, ":")
-	if colonIdx < 0 {
-		return nil, "", os.NewError("bad display: " + display)
-	}
-	// Parse the section before the colon.
-	var protocol, host, socket string
-	if display[0] == '/' {
-		socket = display[:colonIdx]
-	} else {
-		if i := strings.LastIndex(display, "/"); i < 0 {
-			// The default protocol is TCP.
-			protocol = "tcp"
-			host = display[:colonIdx]
-		} else {
-			protocol = display[:i]
-			host = display[i+1 : colonIdx]
-		}
-	}
-	// Parse the section after the colon.
-	after := display[colonIdx+1:]
-	if after == "" {
-		return nil, "", os.NewError("bad display: " + display)
-	}
-	if i := strings.LastIndex(after, "."); i < 0 {
-		displayStr = after
-	} else {
-		displayStr = after[:i]
-	}
-	displayInt, err := strconv.Atoi(displayStr)
-	if err != nil || displayInt < 0 {
-		return nil, "", os.NewError("bad display: " + display)
-	}
-	// Make the connection.
-	if socket != "" {
-		conn, err = net.Dial("unix", socket+":"+displayStr)
-	} else if host != "" {
-		conn, err = net.Dial(protocol, host+":"+strconv.Itoa(6000+displayInt))
-	} else {
-		conn, err = net.Dial("unix", "/tmp/.X11-unix/X"+displayStr)
-	}
-	if err != nil {
-		return nil, "", os.NewError("cannot connect to " + display + ": " + err.String())
-	}
-	return
-}
-
-// authenticate authenticates ourselves with the X server.
-// displayStr is the "12" out of ":12.0".
-func authenticate(w *bufio.Writer, displayStr string) os.Error {
-	key, value, err := readAuth(displayStr)
-	if err != nil {
-		return err
-	}
-	// Assume that the authentication protocol is "MIT-MAGIC-COOKIE-1".
-	if len(key) != 18 || len(value) != 16 {
-		return os.NewError("unsupported Xauth")
-	}
-	// 0x006c means little-endian. 0x000b, 0x0000 means X major version 11, minor version 0.
-	// 0x0012 and 0x0010 means the auth key and value have lengths 18 and 16.
-	// The final 0x0000 is padding, so that the string length is a multiple of 4.
-	_, err = io.WriteString(w, "\x6c\x00\x0b\x00\x00\x00\x12\x00\x10\x00\x00\x00")
-	if err != nil {
-		return err
-	}
-	_, err = io.WriteString(w, key)
-	if err != nil {
-		return err
-	}
-	// Again, the 0x0000 is padding.
-	_, err = io.WriteString(w, "\x00\x00")
-	if err != nil {
-		return err
-	}
-	_, err = io.WriteString(w, value)
-	if err != nil {
-		return err
-	}
-	err = w.Flush()
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
-// readU8 reads a uint8 from r, using b as a scratch buffer.
-func readU8(r io.Reader, b []byte) (uint8, os.Error) {
-	_, err := io.ReadFull(r, b[:1])
-	if err != nil {
-		return 0, err
-	}
-	return uint8(b[0]), nil
-}
-
-// readU16LE reads a little-endian uint16 from r, using b as a scratch buffer.
-func readU16LE(r io.Reader, b []byte) (uint16, os.Error) {
-	_, err := io.ReadFull(r, b[:2])
-	if err != nil {
-		return 0, err
-	}
-	return uint16(b[0]) | uint16(b[1])<<8, nil
-}
-
-// readU32LE reads a little-endian uint32 from r, using b as a scratch buffer.
-func readU32LE(r io.Reader, b []byte) (uint32, os.Error) {
-	_, err := io.ReadFull(r, b[:4])
-	if err != nil {
-		return 0, err
-	}
-	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, nil
-}
-
-// setU32LE sets b[:4] to be the little-endian representation of u.
-func setU32LE(b []byte, u uint32) {
-	b[0] = byte((u >> 0) & 0xff)
-	b[1] = byte((u >> 8) & 0xff)
-	b[2] = byte((u >> 16) & 0xff)
-	b[3] = byte((u >> 24) & 0xff)
-}
-
-// checkPixmapFormats checks that we have an agreeable X pixmap Format.
-func checkPixmapFormats(r io.Reader, b []byte, n int) (agree bool, err os.Error) {
-	for i := 0; i < n; i++ {
-		_, err = io.ReadFull(r, b[:8])
-		if err != nil {
-			return
-		}
-		// Byte 0 is depth, byte 1 is bits-per-pixel, byte 2 is scanline-pad, the rest (5) is padding.
-		if b[0] == 24 && b[1] == 32 {
-			agree = true
-		}
-	}
-	return
-}
-
-// checkDepths checks that we have an agreeable X Depth (i.e. one that has an agreeable X VisualType).
-func checkDepths(r io.Reader, b []byte, n int, visual uint32) (agree bool, err os.Error) {
-	for i := 0; i < n; i++ {
-		depth, err := readU16LE(r, b)
-		if err != nil {
-			return
-		}
-		depth &= 0xff
-		visualsLen, err := readU16LE(r, b)
-		if err != nil {
-			return
-		}
-		// Ignore 4 bytes of padding.
-		_, err = io.ReadFull(r, b[:4])
-		if err != nil {
-			return
-		}
-		for j := 0; j < int(visualsLen); j++ {
-			// Read 24 bytes: visual(4), class(1), bits per rgb value(1), colormap entries(2),
-			// red mask(4), green mask(4), blue mask(4), padding(4).
-			v, err := readU32LE(r, b)
-			_, err = readU32LE(r, b)
-			rm, err := readU32LE(r, b)
-			gm, err := readU32LE(r, b)
-			bm, err := readU32LE(r, b)
-			_, err = readU32LE(r, b)
-			if err != nil {
-				return
-			}
-			if v == visual && rm == 0xff0000 && gm == 0xff00 && bm == 0xff && depth == 24 {
-				agree = true
-			}
-		}
-	}
-	return
-}
-
-// checkScreens checks that we have an agreeable X Screen.
-func checkScreens(r io.Reader, b []byte, n int) (root, visual uint32, err os.Error) {
-	for i := 0; i < n; i++ {
-		root0, err := readU32LE(r, b)
-		if err != nil {
-			return
-		}
-		// Ignore the next 7x4 bytes, which is: colormap, whitepixel, blackpixel, current input masks,
-		// width and height (pixels), width and height (mm), min and max installed maps.
-		_, err = io.ReadFull(r, b[:28])
-		if err != nil {
-			return
-		}
-		visual0, err := readU32LE(r, b)
-		if err != nil {
-			return
-		}
-		// Next 4 bytes: backing stores, save unders, root depth, allowed depths length.
-		x, err := readU32LE(r, b)
-		if err != nil {
-			return
-		}
-		nDepths := int(x >> 24)
-		agree, err := checkDepths(r, b, nDepths, visual0)
-		if err != nil {
-			return
-		}
-		if agree && root == 0 {
-			root = root0
-			visual = visual0
-		}
-	}
-	return
-}
-
-// handshake performs the protocol handshake with the X server, and ensures
-// that the server provides a compatible Screen, Depth, etc.
-func (c *conn) handshake() os.Error {
-	_, err := io.ReadFull(c.r, c.buf[:8])
-	if err != nil {
-		return err
-	}
-	// Byte 0 should be 1 (success), bytes 2:6 should be 0xb0000000 (major/minor version 11.0).
-	if c.buf[0] != 1 || c.buf[2] != 11 || c.buf[3] != 0 || c.buf[4] != 0 || c.buf[5] != 0 {
-		return os.NewError("unsupported X version")
-	}
-	// Ignore the release number.
-	_, err = io.ReadFull(c.r, c.buf[:4])
-	if err != nil {
-		return err
-	}
-	// Read the resource ID base.
-	resourceIdBase, err := readU32LE(c.r, c.buf[:4])
-	if err != nil {
-		return err
-	}
-	// Read the resource ID mask.
-	resourceIdMask, err := readU32LE(c.r, c.buf[:4])
-	if err != nil {
-		return err
-	}
-	if resourceIdMask < 256 {
-		return os.NewError("X resource ID mask is too small")
-	}
-	// Ignore the motion buffer size.
-	_, err = io.ReadFull(c.r, c.buf[:4])
-	if err != nil {
-		return err
-	}
-	// Read the vendor length and round it up to a multiple of 4,
-	// for X11 protocol alignment reasons.
-	vendorLen, err := readU16LE(c.r, c.buf[:2])
-	if err != nil {
-		return err
-	}
-	vendorLen = (vendorLen + 3) &^ 3
-	// Read the maximum request length.
-	maxReqLen, err := readU16LE(c.r, c.buf[:2])
-	if err != nil {
-		return err
-	}
-	if maxReqLen != 0xffff {
-		return os.NewError("unsupported X maximum request length")
-	}
-	// Read the roots length.
-	rootsLen, err := readU8(c.r, c.buf[:1])
-	if err != nil {
-		return err
-	}
-	// Read the pixmap formats length.
-	pixmapFormatsLen, err := readU8(c.r, c.buf[:1])
-	if err != nil {
-		return err
-	}
-	// Ignore some things that we don't care about (totaling 10 + vendorLen bytes):
-	// imageByteOrder(1), bitmapFormatBitOrder(1), bitmapFormatScanlineUnit(1) bitmapFormatScanlinePad(1),
-	// minKeycode(1), maxKeycode(1), padding(4), vendor (vendorLen).
-	if 10+int(vendorLen) > cap(c.buf) {
-		return os.NewError("unsupported X vendor")
-	}
-	_, err = io.ReadFull(c.r, c.buf[:10+int(vendorLen)])
-	if err != nil {
-		return err
-	}
-	// Check that we have an agreeable pixmap format.
-	agree, err := checkPixmapFormats(c.r, c.buf[:8], int(pixmapFormatsLen))
-	if err != nil {
-		return err
-	}
-	if !agree {
-		return os.NewError("unsupported X pixmap formats")
-	}
-	// Check that we have an agreeable screen.
-	root, visual, err := checkScreens(c.r, c.buf[:24], int(rootsLen))
-	if err != nil {
-		return err
-	}
-	if root == 0 || visual == 0 {
-		return os.NewError("unsupported X screen")
-	}
-	c.gc = resID(resourceIdBase)
-	c.window = resID(resourceIdBase + 1)
-	c.root = resID(root)
-	c.visual = resID(visual)
-	return nil
-}
-
-// NewWindow calls NewWindowDisplay with $DISPLAY.
-func NewWindow() (gui.Window, os.Error) {
-	display := os.Getenv("DISPLAY")
-	if len(display) == 0 {
-		return nil, os.NewError("$DISPLAY not set")
-	}
-	return NewWindowDisplay(display)
-}
-
-// NewWindowDisplay returns a new gui.Window, backed by a newly created and
-// mapped X11 window. The X server to connect to is specified by the display
-// string, such as ":1".
-func NewWindowDisplay(display string) (gui.Window, os.Error) {
-	socket, displayStr, err := connect(display)
-	if err != nil {
-		return nil, err
-	}
-	c := new(conn)
-	c.c = socket
-	c.r = bufio.NewReader(socket)
-	c.w = bufio.NewWriter(socket)
-	err = authenticate(c.w, displayStr)
-	if err != nil {
-		return nil, err
-	}
-	err = c.handshake()
-	if err != nil {
-		return nil, err
-	}
-
-	// Now that we're connected, show a window, via three X protocol messages.
-	// First, issue a GetKeyboardMapping request. This is the first request, and
-	// will be associated with a cookie of 1.
-	setU32LE(c.buf[0:4], 0x00020065) // 0x65 is the GetKeyboardMapping opcode, and the message is 2 x 4 bytes long.
-	setU32LE(c.buf[4:8], uint32((keymapHi-keymapLo+1)<<8|keymapLo))
-	// Second, create a graphics context (GC).
-	setU32LE(c.buf[8:12], 0x00060037) // 0x37 is the CreateGC opcode, and the message is 6 x 4 bytes long.
-	setU32LE(c.buf[12:16], uint32(c.gc))
-	setU32LE(c.buf[16:20], uint32(c.root))
-	setU32LE(c.buf[20:24], 0x00010004) // Bit 2 is XCB_GC_FOREGROUND, bit 16 is XCB_GC_GRAPHICS_EXPOSURES.
-	setU32LE(c.buf[24:28], 0x00000000) // The Foreground is black.
-	setU32LE(c.buf[28:32], 0x00000000) // GraphicsExposures' value is unused.
-	// Third, create the window.
-	setU32LE(c.buf[32:36], 0x000a0001) // 0x01 is the CreateWindow opcode, and the message is 10 x 4 bytes long.
-	setU32LE(c.buf[36:40], uint32(c.window))
-	setU32LE(c.buf[40:44], uint32(c.root))
-	setU32LE(c.buf[44:48], 0x00000000) // Initial (x, y) is (0, 0).
-	setU32LE(c.buf[48:52], windowHeight<<16|windowWidth)
-	setU32LE(c.buf[52:56], 0x00010000) // Border width is 0, XCB_WINDOW_CLASS_INPUT_OUTPUT is 1.
-	setU32LE(c.buf[56:60], uint32(c.visual))
-	setU32LE(c.buf[60:64], 0x00000802) // Bit 1 is XCB_CW_BACK_PIXEL, bit 11 is XCB_CW_EVENT_MASK.
-	setU32LE(c.buf[64:68], 0x00000000) // The Back-Pixel is black.
-	setU32LE(c.buf[68:72], 0x0000804f) // Key/button press and release, pointer motion, and expose event masks.
-	// Fourth, map the window.
-	setU32LE(c.buf[72:76], 0x00020008) // 0x08 is the MapWindow opcode, and the message is 2 x 4 bytes long.
-	setU32LE(c.buf[76:80], uint32(c.window))
-	// Write the bytes.
-	_, err = c.w.Write(c.buf[:80])
-	if err != nil {
-		return nil, err
-	}
-	err = c.w.Flush()
-	if err != nil {
-		return nil, err
-	}
-
-	c.img = image.NewRGBA(image.Rect(0, 0, windowWidth, windowHeight))
-	c.eventc = make(chan interface{}, 16)
-	c.flush = make(chan bool, 1)
-	go c.readSocket()
-	go c.writeSocket()
-	return c, nil
-}
diff --git a/src/pkg/exp/html/Makefile b/src/pkg/exp/html/Makefile
new file mode 100644
index 0000000..3ba6a0d
--- /dev/null
+++ b/src/pkg/exp/html/Makefile
@@ -0,0 +1,20 @@
+# Copyright 2010 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=html
+GOFILES=\
+	const.go\
+	doc.go\
+	doctype.go\
+	entity.go\
+	escape.go\
+	foreign.go\
+	node.go\
+	parse.go\
+	render.go\
+	token.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/exp/html/const.go b/src/pkg/exp/html/const.go
new file mode 100644
index 0000000..d7cc8bb
--- /dev/null
+++ b/src/pkg/exp/html/const.go
@@ -0,0 +1,100 @@
+// Copyright 2011 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 html
+
+// Section 12.2.3.2 of the HTML5 specification says "The following elements
+// have varying levels of special parsing rules".
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#the-stack-of-open-elements
+var isSpecialElementMap = map[string]bool{
+	"address":    true,
+	"applet":     true,
+	"area":       true,
+	"article":    true,
+	"aside":      true,
+	"base":       true,
+	"basefont":   true,
+	"bgsound":    true,
+	"blockquote": true,
+	"body":       true,
+	"br":         true,
+	"button":     true,
+	"caption":    true,
+	"center":     true,
+	"col":        true,
+	"colgroup":   true,
+	"command":    true,
+	"dd":         true,
+	"details":    true,
+	"dir":        true,
+	"div":        true,
+	"dl":         true,
+	"dt":         true,
+	"embed":      true,
+	"fieldset":   true,
+	"figcaption": true,
+	"figure":     true,
+	"footer":     true,
+	"form":       true,
+	"frame":      true,
+	"frameset":   true,
+	"h1":         true,
+	"h2":         true,
+	"h3":         true,
+	"h4":         true,
+	"h5":         true,
+	"h6":         true,
+	"head":       true,
+	"header":     true,
+	"hgroup":     true,
+	"hr":         true,
+	"html":       true,
+	"iframe":     true,
+	"img":        true,
+	"input":      true,
+	"isindex":    true,
+	"li":         true,
+	"link":       true,
+	"listing":    true,
+	"marquee":    true,
+	"menu":       true,
+	"meta":       true,
+	"nav":        true,
+	"noembed":    true,
+	"noframes":   true,
+	"noscript":   true,
+	"object":     true,
+	"ol":         true,
+	"p":          true,
+	"param":      true,
+	"plaintext":  true,
+	"pre":        true,
+	"script":     true,
+	"section":    true,
+	"select":     true,
+	"style":      true,
+	"summary":    true,
+	"table":      true,
+	"tbody":      true,
+	"td":         true,
+	"textarea":   true,
+	"tfoot":      true,
+	"th":         true,
+	"thead":      true,
+	"title":      true,
+	"tr":         true,
+	"ul":         true,
+	"wbr":        true,
+	"xmp":        true,
+}
+
+func isSpecialElement(element *Node) bool {
+	switch element.Namespace {
+	case "", "html":
+		return isSpecialElementMap[element.Data]
+	case "svg":
+		return element.Data == "foreignObject"
+	}
+	return false
+}
diff --git a/src/pkg/exp/html/doc.go b/src/pkg/exp/html/doc.go
new file mode 100644
index 0000000..56b194f
--- /dev/null
+++ b/src/pkg/exp/html/doc.go
@@ -0,0 +1,107 @@
+// Copyright 2010 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 html implements an HTML5-compliant tokenizer and parser.
+INCOMPLETE.
+
+Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
+caller's responsibility to ensure that r provides UTF-8 encoded HTML.
+
+	z := html.NewTokenizer(r)
+
+Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
+which parses the next token and returns its type, or an error:
+
+	for {
+		tt := z.Next()
+		if tt == html.ErrorToken {
+			// ...
+			return ...
+		}
+		// Process the current token.
+	}
+
+There are two APIs for retrieving the current token. The high-level API is to
+call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
+allow optionally calling Raw after Next but before Token, Text, TagName, or
+TagAttr. In EBNF notation, the valid call sequence per token is:
+
+	Next {Raw} [ Token | Text | TagName {TagAttr} ]
+
+Token returns an independent data structure that completely describes a token.
+Entities (such as "<") are unescaped, tag names and attribute keys are
+lower-cased, and attributes are collected into a []Attribute. For example:
+
+	for {
+		if z.Next() == html.ErrorToken {
+			// Returning io.EOF indicates success.
+			return z.Err()
+		}
+		emitToken(z.Token())
+	}
+
+The low-level API performs fewer allocations and copies, but the contents of
+the []byte values returned by Text, TagName and TagAttr may change on the next
+call to Next. For example, to extract an HTML page's anchor text:
+
+	depth := 0
+	for {
+		tt := z.Next()
+		switch tt {
+		case ErrorToken:
+			return z.Err()
+		case TextToken:
+			if depth > 0 {
+				// emitBytes should copy the []byte it receives,
+				// if it doesn't process it immediately.
+				emitBytes(z.Text())
+			}
+		case StartTagToken, EndTagToken:
+			tn, _ := z.TagName()
+			if len(tn) == 1 && tn[0] == 'a' {
+				if tt == StartTagToken {
+					depth++
+				} else {
+					depth--
+				}
+			}
+		}
+	}
+
+Parsing is done by calling Parse with an io.Reader, which returns the root of
+the parse tree (the document element) as a *Node. It is the caller's
+responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
+example, to process each anchor node in depth-first order:
+
+	doc, err := html.Parse(r)
+	if err != nil {
+		// ...
+	}
+	var f func(*html.Node)
+	f = func(n *html.Node) {
+		if n.Type == html.ElementNode && n.Data == "a" {
+			// Do something with n...
+		}
+		for _, c := range n.Child {
+			f(c)
+		}
+	}
+	f(doc)
+
+The relevant specifications include:
+http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html and
+http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html
+*/
+package html
+
+// The tokenization algorithm implemented by this package is not a line-by-line
+// transliteration of the relatively verbose state-machine in the WHATWG
+// specification. A more direct approach is used instead, where the program
+// counter implies the state, such as whether it is tokenizing a tag or a text
+// node. Specification compliance is verified by checking expected and actual
+// outputs over a test suite rather than aiming for algorithmic fidelity.
+
+// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
+// TODO(nigeltao): How does parsing interact with a JavaScript engine?
diff --git a/src/pkg/exp/html/doctype.go b/src/pkg/exp/html/doctype.go
new file mode 100644
index 0000000..f692061
--- /dev/null
+++ b/src/pkg/exp/html/doctype.go
@@ -0,0 +1,156 @@
+// Copyright 2011 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 html
+
+import (
+	"strings"
+)
+
+// parseDoctype parses the data from a DoctypeToken into a name,
+// public identifier, and system identifier. It returns a Node whose Type 
+// is DoctypeNode, whose Data is the name, and which has attributes
+// named "system" and "public" for the two identifiers if they were present.
+// quirks is whether the document should be parsed in "quirks mode".
+func parseDoctype(s string) (n *Node, quirks bool) {
+	n = &Node{Type: DoctypeNode}
+
+	// Find the name.
+	space := strings.IndexAny(s, whitespace)
+	if space == -1 {
+		space = len(s)
+	}
+	n.Data = s[:space]
+	// The comparison to "html" is case-sensitive.
+	if n.Data != "html" {
+		quirks = true
+	}
+	n.Data = strings.ToLower(n.Data)
+	s = strings.TrimLeft(s[space:], whitespace)
+
+	if len(s) < 6 {
+		// It can't start with "PUBLIC" or "SYSTEM".
+		// Ignore the rest of the string.
+		return n, quirks || s != ""
+	}
+
+	key := strings.ToLower(s[:6])
+	s = s[6:]
+	for key == "public" || key == "system" {
+		s = strings.TrimLeft(s, whitespace)
+		if s == "" {
+			break
+		}
+		quote := s[0]
+		if quote != '"' && quote != '\'' {
+			break
+		}
+		s = s[1:]
+		q := strings.IndexRune(s, rune(quote))
+		var id string
+		if q == -1 {
+			id = s
+			s = ""
+		} else {
+			id = s[:q]
+			s = s[q+1:]
+		}
+		n.Attr = append(n.Attr, Attribute{Key: key, Val: id})
+		if key == "public" {
+			key = "system"
+		} else {
+			key = ""
+		}
+	}
+
+	if key != "" || s != "" {
+		quirks = true
+	} else if len(n.Attr) > 0 {
+		if n.Attr[0].Key == "public" {
+			public := strings.ToLower(n.Attr[0].Val)
+			switch public {
+			case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html":
+				quirks = true
+			default:
+				for _, q := range quirkyIDs {
+					if strings.HasPrefix(public, q) {
+						quirks = true
+						break
+					}
+				}
+			}
+			// The following two public IDs only cause quirks mode if there is no system ID.
+			if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") ||
+				strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) {
+				quirks = true
+			}
+		}
+		if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" &&
+			strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" {
+			quirks = true
+		}
+	}
+
+	return n, quirks
+}
+
+// quirkyIDs is a list of public doctype identifiers that cause a document
+// to be interpreted in quirks mode. The identifiers should be in lower case.
+var quirkyIDs = []string{
+	"+//silmaril//dtd html pro v0r11 19970101//",
+	"-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
+	"-//as//dtd html 3.0 aswedit + extensions//",
+	"-//ietf//dtd html 2.0 level 1//",
+	"-//ietf//dtd html 2.0 level 2//",
+	"-//ietf//dtd html 2.0 strict level 1//",
+	"-//ietf//dtd html 2.0 strict level 2//",
+	"-//ietf//dtd html 2.0 strict//",
+	"-//ietf//dtd html 2.0//",
+	"-//ietf//dtd html 2.1e//",
+	"-//ietf//dtd html 3.0//",
+	"-//ietf//dtd html 3.2 final//",
+	"-//ietf//dtd html 3.2//",
+	"-//ietf//dtd html 3//",
+	"-//ietf//dtd html level 0//",
+	"-//ietf//dtd html level 1//",
+	"-//ietf//dtd html level 2//",
+	"-//ietf//dtd html level 3//",
+	"-//ietf//dtd html strict level 0//",
+	"-//ietf//dtd html strict level 1//",
+	"-//ietf//dtd html strict level 2//",
+	"-//ietf//dtd html strict level 3//",
+	"-//ietf//dtd html strict//",
+	"-//ietf//dtd html//",
+	"-//metrius//dtd metrius presentational//",
+	"-//microsoft//dtd internet explorer 2.0 html strict//",
+	"-//microsoft//dtd internet explorer 2.0 html//",
+	"-//microsoft//dtd internet explorer 2.0 tables//",
+	"-//microsoft//dtd internet explorer 3.0 html strict//",
+	"-//microsoft//dtd internet explorer 3.0 html//",
+	"-//microsoft//dtd internet explorer 3.0 tables//",
+	"-//netscape comm. corp.//dtd html//",
+	"-//netscape comm. corp.//dtd strict html//",
+	"-//o'reilly and associates//dtd html 2.0//",
+	"-//o'reilly and associates//dtd html extended 1.0//",
+	"-//o'reilly and associates//dtd html extended relaxed 1.0//",
+	"-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
+	"-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
+	"-//spyglass//dtd html 2.0 extended//",
+	"-//sq//dtd html 2.0 hotmetal + extensions//",
+	"-//sun microsystems corp.//dtd hotjava html//",
+	"-//sun microsystems corp.//dtd hotjava strict html//",
+	"-//w3c//dtd html 3 1995-03-24//",
+	"-//w3c//dtd html 3.2 draft//",
+	"-//w3c//dtd html 3.2 final//",
+	"-//w3c//dtd html 3.2//",
+	"-//w3c//dtd html 3.2s draft//",
+	"-//w3c//dtd html 4.0 frameset//",
+	"-//w3c//dtd html 4.0 transitional//",
+	"-//w3c//dtd html experimental 19960712//",
+	"-//w3c//dtd html experimental 970421//",
+	"-//w3c//dtd w3 html//",
+	"-//w3o//dtd w3 html 3.0//",
+	"-//webtechs//dtd mozilla html 2.0//",
+	"-//webtechs//dtd mozilla html//",
+}
diff --git a/src/pkg/exp/html/entity.go b/src/pkg/exp/html/entity.go
new file mode 100644
index 0000000..bd83075
--- /dev/null
+++ b/src/pkg/exp/html/entity.go
@@ -0,0 +1,2253 @@
+// Copyright 2010 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 html
+
+// All entities that do not end with ';' are 6 or fewer bytes long.
+const longestEntityWithoutSemicolon = 6
+
+// entity is a map from HTML entity names to their values. The semicolon matters:
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html
+// lists both "amp" and "amp;" as two separate entries.
+//
+// Note that the HTML5 list is larger than the HTML4 list at
+// http://www.w3.org/TR/html4/sgml/entities.html
+var entity = map[string]rune{
+	"AElig;":                           '\U000000C6',
+	"AMP;":                             '\U00000026',
+	"Aacute;":                          '\U000000C1',
+	"Abreve;":                          '\U00000102',
+	"Acirc;":                           '\U000000C2',
+	"Acy;":                             '\U00000410',
+	"Afr;":                             '\U0001D504',
+	"Agrave;":                          '\U000000C0',
+	"Alpha;":                           '\U00000391',
+	"Amacr;":                           '\U00000100',
+	"And;":                             '\U00002A53',
+	"Aogon;":                           '\U00000104',
+	"Aopf;":                            '\U0001D538',
+	"ApplyFunction;":                   '\U00002061',
+	"Aring;":                           '\U000000C5',
+	"Ascr;":                            '\U0001D49C',
+	"Assign;":                          '\U00002254',
+	"Atilde;":                          '\U000000C3',
+	"Auml;":                            '\U000000C4',
+	"Backslash;":                       '\U00002216',
+	"Barv;":                            '\U00002AE7',
+	"Barwed;":                          '\U00002306',
+	"Bcy;":                             '\U00000411',
+	"Because;":                         '\U00002235',
+	"Bernoullis;":                      '\U0000212C',
+	"Beta;":                            '\U00000392',
+	"Bfr;":                             '\U0001D505',
+	"Bopf;":                            '\U0001D539',
+	"Breve;":                           '\U000002D8',
+	"Bscr;":                            '\U0000212C',
+	"Bumpeq;":                          '\U0000224E',
+	"CHcy;":                            '\U00000427',
+	"COPY;":                            '\U000000A9',
+	"Cacute;":                          '\U00000106',
+	"Cap;":                             '\U000022D2',
+	"CapitalDifferentialD;":            '\U00002145',
+	"Cayleys;":                         '\U0000212D',
+	"Ccaron;":                          '\U0000010C',
+	"Ccedil;":                          '\U000000C7',
+	"Ccirc;":                           '\U00000108',
+	"Cconint;":                         '\U00002230',
+	"Cdot;":                            '\U0000010A',
+	"Cedilla;":                         '\U000000B8',
+	"CenterDot;":                       '\U000000B7',
+	"Cfr;":                             '\U0000212D',
+	"Chi;":                             '\U000003A7',
+	"CircleDot;":                       '\U00002299',
+	"CircleMinus;":                     '\U00002296',
+	"CirclePlus;":                      '\U00002295',
+	"CircleTimes;":                     '\U00002297',
+	"ClockwiseContourIntegral;":        '\U00002232',
+	"CloseCurlyDoubleQuote;":           '\U0000201D',
+	"CloseCurlyQuote;":                 '\U00002019',
+	"Colon;":                           '\U00002237',
+	"Colone;":                          '\U00002A74',
+	"Congruent;":                       '\U00002261',
+	"Conint;":                          '\U0000222F',
+	"ContourIntegral;":                 '\U0000222E',
+	"Copf;":                            '\U00002102',
+	"Coproduct;":                       '\U00002210',
+	"CounterClockwiseContourIntegral;": '\U00002233',
+	"Cross;":                           '\U00002A2F',
+	"Cscr;":                            '\U0001D49E',
+	"Cup;":                             '\U000022D3',
+	"CupCap;":                          '\U0000224D',
+	"DD;":                              '\U00002145',
+	"DDotrahd;":                        '\U00002911',
+	"DJcy;":                            '\U00000402',
+	"DScy;":                            '\U00000405',
+	"DZcy;":                            '\U0000040F',
+	"Dagger;":                          '\U00002021',
+	"Darr;":                            '\U000021A1',
+	"Dashv;":                           '\U00002AE4',
+	"Dcaron;":                          '\U0000010E',
+	"Dcy;":                             '\U00000414',
+	"Del;":                             '\U00002207',
+	"Delta;":                           '\U00000394',
+	"Dfr;":                             '\U0001D507',
+	"DiacriticalAcute;":                '\U000000B4',
+	"DiacriticalDot;":                  '\U000002D9',
+	"DiacriticalDoubleAcute;":          '\U000002DD',
+	"DiacriticalGrave;":                '\U00000060',
+	"DiacriticalTilde;":                '\U000002DC',
+	"Diamond;":                         '\U000022C4',
+	"DifferentialD;":                   '\U00002146',
+	"Dopf;":                            '\U0001D53B',
+	"Dot;":                             '\U000000A8',
+	"DotDot;":                          '\U000020DC',
+	"DotEqual;":                        '\U00002250',
+	"DoubleContourIntegral;":           '\U0000222F',
+	"DoubleDot;":                       '\U000000A8',
+	"DoubleDownArrow;":                 '\U000021D3',
+	"DoubleLeftArrow;":                 '\U000021D0',
+	"DoubleLeftRightArrow;":            '\U000021D4',
+	"DoubleLeftTee;":                   '\U00002AE4',
+	"DoubleLongLeftArrow;":             '\U000027F8',
+	"DoubleLongLeftRightArrow;":        '\U000027FA',
+	"DoubleLongRightArrow;":            '\U000027F9',
+	"DoubleRightArrow;":                '\U000021D2',
+	"DoubleRightTee;":                  '\U000022A8',
+	"DoubleUpArrow;":                   '\U000021D1',
+	"DoubleUpDownArrow;":               '\U000021D5',
+	"DoubleVerticalBar;":               '\U00002225',
+	"DownArrow;":                       '\U00002193',
+	"DownArrowBar;":                    '\U00002913',
+	"DownArrowUpArrow;":                '\U000021F5',
+	"DownBreve;":                       '\U00000311',
+	"DownLeftRightVector;":             '\U00002950',
+	"DownLeftTeeVector;":               '\U0000295E',
+	"DownLeftVector;":                  '\U000021BD',
+	"DownLeftVectorBar;":               '\U00002956',
+	"DownRightTeeVector;":              '\U0000295F',
+	"DownRightVector;":                 '\U000021C1',
+	"DownRightVectorBar;":              '\U00002957',
+	"DownTee;":                         '\U000022A4',
+	"DownTeeArrow;":                    '\U000021A7',
+	"Downarrow;":                       '\U000021D3',
+	"Dscr;":                            '\U0001D49F',
+	"Dstrok;":                          '\U00000110',
+	"ENG;":                             '\U0000014A',
+	"ETH;":                             '\U000000D0',
+	"Eacute;":                          '\U000000C9',
+	"Ecaron;":                          '\U0000011A',
+	"Ecirc;":                           '\U000000CA',
+	"Ecy;":                             '\U0000042D',
+	"Edot;":                            '\U00000116',
+	"Efr;":                             '\U0001D508',
+	"Egrave;":                          '\U000000C8',
+	"Element;":                         '\U00002208',
+	"Emacr;":                           '\U00000112',
+	"EmptySmallSquare;":                '\U000025FB',
+	"EmptyVerySmallSquare;":            '\U000025AB',
+	"Eogon;":                           '\U00000118',
+	"Eopf;":                            '\U0001D53C',
+	"Epsilon;":                         '\U00000395',
+	"Equal;":                           '\U00002A75',
+	"EqualTilde;":                      '\U00002242',
+	"Equilibrium;":                     '\U000021CC',
+	"Escr;":                            '\U00002130',
+	"Esim;":                            '\U00002A73',
+	"Eta;":                             '\U00000397',
+	"Euml;":                            '\U000000CB',
+	"Exists;":                          '\U00002203',
+	"ExponentialE;":                    '\U00002147',
+	"Fcy;":                             '\U00000424',
+	"Ffr;":                             '\U0001D509',
+	"FilledSmallSquare;":               '\U000025FC',
+	"FilledVerySmallSquare;":           '\U000025AA',
+	"Fopf;":                            '\U0001D53D',
+	"ForAll;":                          '\U00002200',
+	"Fouriertrf;":                      '\U00002131',
+	"Fscr;":                            '\U00002131',
+	"GJcy;":                            '\U00000403',
+	"GT;":                              '\U0000003E',
+	"Gamma;":                           '\U00000393',
+	"Gammad;":                          '\U000003DC',
+	"Gbreve;":                          '\U0000011E',
+	"Gcedil;":                          '\U00000122',
+	"Gcirc;":                           '\U0000011C',
+	"Gcy;":                             '\U00000413',
+	"Gdot;":                            '\U00000120',
+	"Gfr;":                             '\U0001D50A',
+	"Gg;":                              '\U000022D9',
+	"Gopf;":                            '\U0001D53E',
+	"GreaterEqual;":                    '\U00002265',
+	"GreaterEqualLess;":                '\U000022DB',
+	"GreaterFullEqual;":                '\U00002267',
+	"GreaterGreater;":                  '\U00002AA2',
+	"GreaterLess;":                     '\U00002277',
+	"GreaterSlantEqual;":               '\U00002A7E',
+	"GreaterTilde;":                    '\U00002273',
+	"Gscr;":                            '\U0001D4A2',
+	"Gt;":                              '\U0000226B',
+	"HARDcy;":                          '\U0000042A',
+	"Hacek;":                           '\U000002C7',
+	"Hat;":                             '\U0000005E',
+	"Hcirc;":                           '\U00000124',
+	"Hfr;":                             '\U0000210C',
+	"HilbertSpace;":                    '\U0000210B',
+	"Hopf;":                            '\U0000210D',
+	"HorizontalLine;":                  '\U00002500',
+	"Hscr;":                            '\U0000210B',
+	"Hstrok;":                          '\U00000126',
+	"HumpDownHump;":                    '\U0000224E',
+	"HumpEqual;":                       '\U0000224F',
+	"IEcy;":                            '\U00000415',
+	"IJlig;":                           '\U00000132',
+	"IOcy;":                            '\U00000401',
+	"Iacute;":                          '\U000000CD',
+	"Icirc;":                           '\U000000CE',
+	"Icy;":                             '\U00000418',
+	"Idot;":                            '\U00000130',
+	"Ifr;":                             '\U00002111',
+	"Igrave;":                          '\U000000CC',
+	"Im;":                              '\U00002111',
+	"Imacr;":                           '\U0000012A',
+	"ImaginaryI;":                      '\U00002148',
+	"Implies;":                         '\U000021D2',
+	"Int;":                             '\U0000222C',
+	"Integral;":                        '\U0000222B',
+	"Intersection;":                    '\U000022C2',
+	"InvisibleComma;":                  '\U00002063',
+	"InvisibleTimes;":                  '\U00002062',
+	"Iogon;":                           '\U0000012E',
+	"Iopf;":                            '\U0001D540',
+	"Iota;":                            '\U00000399',
+	"Iscr;":                            '\U00002110',
+	"Itilde;":                          '\U00000128',
+	"Iukcy;":                           '\U00000406',
+	"Iuml;":                            '\U000000CF',
+	"Jcirc;":                           '\U00000134',
+	"Jcy;":                             '\U00000419',
+	"Jfr;":                             '\U0001D50D',
+	"Jopf;":                            '\U0001D541',
+	"Jscr;":                            '\U0001D4A5',
+	"Jsercy;":                          '\U00000408',
+	"Jukcy;":                           '\U00000404',
+	"KHcy;":                            '\U00000425',
+	"KJcy;":                            '\U0000040C',
+	"Kappa;":                           '\U0000039A',
+	"Kcedil;":                          '\U00000136',
+	"Kcy;":                             '\U0000041A',
+	"Kfr;":                             '\U0001D50E',
+	"Kopf;":                            '\U0001D542',
+	"Kscr;":                            '\U0001D4A6',
+	"LJcy;":                            '\U00000409',
+	"LT;":                              '\U0000003C',
+	"Lacute;":                          '\U00000139',
+	"Lambda;":                          '\U0000039B',
+	"Lang;":                            '\U000027EA',
+	"Laplacetrf;":                      '\U00002112',
+	"Larr;":                            '\U0000219E',
+	"Lcaron;":                          '\U0000013D',
+	"Lcedil;":                          '\U0000013B',
+	"Lcy;":                             '\U0000041B',
+	"LeftAngleBracket;":                '\U000027E8',
+	"LeftArrow;":                       '\U00002190',
+	"LeftArrowBar;":                    '\U000021E4',
+	"LeftArrowRightArrow;":             '\U000021C6',
+	"LeftCeiling;":                     '\U00002308',
+	"LeftDoubleBracket;":               '\U000027E6',
+	"LeftDownTeeVector;":               '\U00002961',
+	"LeftDownVector;":                  '\U000021C3',
+	"LeftDownVectorBar;":               '\U00002959',
+	"LeftFloor;":                       '\U0000230A',
+	"LeftRightArrow;":                  '\U00002194',
+	"LeftRightVector;":                 '\U0000294E',
+	"LeftTee;":                         '\U000022A3',
+	"LeftTeeArrow;":                    '\U000021A4',
+	"LeftTeeVector;":                   '\U0000295A',
+	"LeftTriangle;":                    '\U000022B2',
+	"LeftTriangleBar;":                 '\U000029CF',
+	"LeftTriangleEqual;":               '\U000022B4',
+	"LeftUpDownVector;":                '\U00002951',
+	"LeftUpTeeVector;":                 '\U00002960',
+	"LeftUpVector;":                    '\U000021BF',
+	"LeftUpVectorBar;":                 '\U00002958',
+	"LeftVector;":                      '\U000021BC',
+	"LeftVectorBar;":                   '\U00002952',
+	"Leftarrow;":                       '\U000021D0',
+	"Leftrightarrow;":                  '\U000021D4',
+	"LessEqualGreater;":                '\U000022DA',
+	"LessFullEqual;":                   '\U00002266',
+	"LessGreater;":                     '\U00002276',
+	"LessLess;":                        '\U00002AA1',
+	"LessSlantEqual;":                  '\U00002A7D',
+	"LessTilde;":                       '\U00002272',
+	"Lfr;":                             '\U0001D50F',
+	"Ll;":                              '\U000022D8',
+	"Lleftarrow;":                      '\U000021DA',
+	"Lmidot;":                          '\U0000013F',
+	"LongLeftArrow;":                   '\U000027F5',
+	"LongLeftRightArrow;":              '\U000027F7',
+	"LongRightArrow;":                  '\U000027F6',
+	"Longleftarrow;":                   '\U000027F8',
+	"Longleftrightarrow;":              '\U000027FA',
+	"Longrightarrow;":                  '\U000027F9',
+	"Lopf;":                            '\U0001D543',
+	"LowerLeftArrow;":                  '\U00002199',
+	"LowerRightArrow;":                 '\U00002198',
+	"Lscr;":                            '\U00002112',
+	"Lsh;":                             '\U000021B0',
+	"Lstrok;":                          '\U00000141',
+	"Lt;":                              '\U0000226A',
+	"Map;":                             '\U00002905',
+	"Mcy;":                             '\U0000041C',
+	"MediumSpace;":                     '\U0000205F',
+	"Mellintrf;":                       '\U00002133',
+	"Mfr;":                             '\U0001D510',
+	"MinusPlus;":                       '\U00002213',
+	"Mopf;":                            '\U0001D544',
+	"Mscr;":                            '\U00002133',
+	"Mu;":                              '\U0000039C',
+	"NJcy;":                            '\U0000040A',
+	"Nacute;":                          '\U00000143',
+	"Ncaron;":                          '\U00000147',
+	"Ncedil;":                          '\U00000145',
+	"Ncy;":                             '\U0000041D',
+	"NegativeMediumSpace;":             '\U0000200B',
+	"NegativeThickSpace;":              '\U0000200B',
+	"NegativeThinSpace;":               '\U0000200B',
+	"NegativeVeryThinSpace;":           '\U0000200B',
+	"NestedGreaterGreater;":            '\U0000226B',
+	"NestedLessLess;":                  '\U0000226A',
+	"NewLine;":                         '\U0000000A',
+	"Nfr;":                             '\U0001D511',
+	"NoBreak;":                         '\U00002060',
+	"NonBreakingSpace;":                '\U000000A0',
+	"Nopf;":                            '\U00002115',
+	"Not;":                             '\U00002AEC',
+	"NotCongruent;":                    '\U00002262',
+	"NotCupCap;":                       '\U0000226D',
+	"NotDoubleVerticalBar;":            '\U00002226',
+	"NotElement;":                      '\U00002209',
+	"NotEqual;":                        '\U00002260',
+	"NotExists;":                       '\U00002204',
+	"NotGreater;":                      '\U0000226F',
+	"NotGreaterEqual;":                 '\U00002271',
+	"NotGreaterLess;":                  '\U00002279',
+	"NotGreaterTilde;":                 '\U00002275',
+	"NotLeftTriangle;":                 '\U000022EA',
+	"NotLeftTriangleEqual;":            '\U000022EC',
+	"NotLess;":                         '\U0000226E',
+	"NotLessEqual;":                    '\U00002270',
+	"NotLessGreater;":                  '\U00002278',
+	"NotLessTilde;":                    '\U00002274',
+	"NotPrecedes;":                     '\U00002280',
+	"NotPrecedesSlantEqual;":           '\U000022E0',
+	"NotReverseElement;":               '\U0000220C',
+	"NotRightTriangle;":                '\U000022EB',
+	"NotRightTriangleEqual;":           '\U000022ED',
+	"NotSquareSubsetEqual;":            '\U000022E2',
+	"NotSquareSupersetEqual;":          '\U000022E3',
+	"NotSubsetEqual;":                  '\U00002288',
+	"NotSucceeds;":                     '\U00002281',
+	"NotSucceedsSlantEqual;":           '\U000022E1',
+	"NotSupersetEqual;":                '\U00002289',
+	"NotTilde;":                        '\U00002241',
+	"NotTildeEqual;":                   '\U00002244',
+	"NotTildeFullEqual;":               '\U00002247',
+	"NotTildeTilde;":                   '\U00002249',
+	"NotVerticalBar;":                  '\U00002224',
+	"Nscr;":                            '\U0001D4A9',
+	"Ntilde;":                          '\U000000D1',
+	"Nu;":                              '\U0000039D',
+	"OElig;":                           '\U00000152',
+	"Oacute;":                          '\U000000D3',
+	"Ocirc;":                           '\U000000D4',
+	"Ocy;":                             '\U0000041E',
+	"Odblac;":                          '\U00000150',
+	"Ofr;":                             '\U0001D512',
+	"Ograve;":                          '\U000000D2',
+	"Omacr;":                           '\U0000014C',
+	"Omega;":                           '\U000003A9',
+	"Omicron;":                         '\U0000039F',
+	"Oopf;":                            '\U0001D546',
+	"OpenCurlyDoubleQuote;":            '\U0000201C',
+	"OpenCurlyQuote;":                  '\U00002018',
+	"Or;":                              '\U00002A54',
+	"Oscr;":                            '\U0001D4AA',
+	"Oslash;":                          '\U000000D8',
+	"Otilde;":                          '\U000000D5',
+	"Otimes;":                          '\U00002A37',
+	"Ouml;":                            '\U000000D6',
+	"OverBar;":                         '\U0000203E',
+	"OverBrace;":                       '\U000023DE',
+	"OverBracket;":                     '\U000023B4',
+	"OverParenthesis;":                 '\U000023DC',
+	"PartialD;":                        '\U00002202',
+	"Pcy;":                             '\U0000041F',
+	"Pfr;":                             '\U0001D513',
+	"Phi;":                             '\U000003A6',
+	"Pi;":                              '\U000003A0',
+	"PlusMinus;":                       '\U000000B1',
+	"Poincareplane;":                   '\U0000210C',
+	"Popf;":                            '\U00002119',
+	"Pr;":                              '\U00002ABB',
+	"Precedes;":                        '\U0000227A',
+	"PrecedesEqual;":                   '\U00002AAF',
+	"PrecedesSlantEqual;":              '\U0000227C',
+	"PrecedesTilde;":                   '\U0000227E',
+	"Prime;":                           '\U00002033',
+	"Product;":                         '\U0000220F',
+	"Proportion;":                      '\U00002237',
+	"Proportional;":                    '\U0000221D',
+	"Pscr;":                            '\U0001D4AB',
+	"Psi;":                             '\U000003A8',
+	"QUOT;":                            '\U00000022',
+	"Qfr;":                             '\U0001D514',
+	"Qopf;":                            '\U0000211A',
+	"Qscr;":                            '\U0001D4AC',
+	"RBarr;":                           '\U00002910',
+	"REG;":                             '\U000000AE',
+	"Racute;":                          '\U00000154',
+	"Rang;":                            '\U000027EB',
+	"Rarr;":                            '\U000021A0',
+	"Rarrtl;":                          '\U00002916',
+	"Rcaron;":                          '\U00000158',
+	"Rcedil;":                          '\U00000156',
+	"Rcy;":                             '\U00000420',
+	"Re;":                              '\U0000211C',
+	"ReverseElement;":                  '\U0000220B',
+	"ReverseEquilibrium;":              '\U000021CB',
+	"ReverseUpEquilibrium;":            '\U0000296F',
+	"Rfr;":                             '\U0000211C',
+	"Rho;":                             '\U000003A1',
+	"RightAngleBracket;":               '\U000027E9',
+	"RightArrow;":                      '\U00002192',
+	"RightArrowBar;":                   '\U000021E5',
+	"RightArrowLeftArrow;":             '\U000021C4',
+	"RightCeiling;":                    '\U00002309',
+	"RightDoubleBracket;":              '\U000027E7',
+	"RightDownTeeVector;":              '\U0000295D',
+	"RightDownVector;":                 '\U000021C2',
+	"RightDownVectorBar;":              '\U00002955',
+	"RightFloor;":                      '\U0000230B',
+	"RightTee;":                        '\U000022A2',
+	"RightTeeArrow;":                   '\U000021A6',
+	"RightTeeVector;":                  '\U0000295B',
+	"RightTriangle;":                   '\U000022B3',
+	"RightTriangleBar;":                '\U000029D0',
+	"RightTriangleEqual;":              '\U000022B5',
+	"RightUpDownVector;":               '\U0000294F',
+	"RightUpTeeVector;":                '\U0000295C',
+	"RightUpVector;":                   '\U000021BE',
+	"RightUpVectorBar;":                '\U00002954',
+	"RightVector;":                     '\U000021C0',
+	"RightVectorBar;":                  '\U00002953',
+	"Rightarrow;":                      '\U000021D2',
+	"Ropf;":                            '\U0000211D',
+	"RoundImplies;":                    '\U00002970',
+	"Rrightarrow;":                     '\U000021DB',
+	"Rscr;":                            '\U0000211B',
+	"Rsh;":                             '\U000021B1',
+	"RuleDelayed;":                     '\U000029F4',
+	"SHCHcy;":                          '\U00000429',
+	"SHcy;":                            '\U00000428',
+	"SOFTcy;":                          '\U0000042C',
+	"Sacute;":                          '\U0000015A',
+	"Sc;":                              '\U00002ABC',
+	"Scaron;":                          '\U00000160',
+	"Scedil;":                          '\U0000015E',
+	"Scirc;":                           '\U0000015C',
+	"Scy;":                             '\U00000421',
+	"Sfr;":                             '\U0001D516',
+	"ShortDownArrow;":                  '\U00002193',
+	"ShortLeftArrow;":                  '\U00002190',
+	"ShortRightArrow;":                 '\U00002192',
+	"ShortUpArrow;":                    '\U00002191',
+	"Sigma;":                           '\U000003A3',
+	"SmallCircle;":                     '\U00002218',
+	"Sopf;":                            '\U0001D54A',
+	"Sqrt;":                            '\U0000221A',
+	"Square;":                          '\U000025A1',
+	"SquareIntersection;":              '\U00002293',
+	"SquareSubset;":                    '\U0000228F',
+	"SquareSubsetEqual;":               '\U00002291',
+	"SquareSuperset;":                  '\U00002290',
+	"SquareSupersetEqual;":             '\U00002292',
+	"SquareUnion;":                     '\U00002294',
+	"Sscr;":                            '\U0001D4AE',
+	"Star;":                            '\U000022C6',
+	"Sub;":                             '\U000022D0',
+	"Subset;":                          '\U000022D0',
+	"SubsetEqual;":                     '\U00002286',
+	"Succeeds;":                        '\U0000227B',
+	"SucceedsEqual;":                   '\U00002AB0',
+	"SucceedsSlantEqual;":              '\U0000227D',
+	"SucceedsTilde;":                   '\U0000227F',
+	"SuchThat;":                        '\U0000220B',
+	"Sum;":                             '\U00002211',
+	"Sup;":                             '\U000022D1',
+	"Superset;":                        '\U00002283',
+	"SupersetEqual;":                   '\U00002287',
+	"Supset;":                          '\U000022D1',
+	"THORN;":                           '\U000000DE',
+	"TRADE;":                           '\U00002122',
+	"TSHcy;":                           '\U0000040B',
+	"TScy;":                            '\U00000426',
+	"Tab;":                             '\U00000009',
+	"Tau;":                             '\U000003A4',
+	"Tcaron;":                          '\U00000164',
+	"Tcedil;":                          '\U00000162',
+	"Tcy;":                             '\U00000422',
+	"Tfr;":                             '\U0001D517',
+	"Therefore;":                       '\U00002234',
+	"Theta;":                           '\U00000398',
+	"ThinSpace;":                       '\U00002009',
+	"Tilde;":                           '\U0000223C',
+	"TildeEqual;":                      '\U00002243',
+	"TildeFullEqual;":                  '\U00002245',
+	"TildeTilde;":                      '\U00002248',
+	"Topf;":                            '\U0001D54B',
+	"TripleDot;":                       '\U000020DB',
+	"Tscr;":                            '\U0001D4AF',
+	"Tstrok;":                          '\U00000166',
+	"Uacute;":                          '\U000000DA',
+	"Uarr;":                            '\U0000219F',
+	"Uarrocir;":                        '\U00002949',
+	"Ubrcy;":                           '\U0000040E',
+	"Ubreve;":                          '\U0000016C',
+	"Ucirc;":                           '\U000000DB',
+	"Ucy;":                             '\U00000423',
+	"Udblac;":                          '\U00000170',
+	"Ufr;":                             '\U0001D518',
+	"Ugrave;":                          '\U000000D9',
+	"Umacr;":                           '\U0000016A',
+	"UnderBar;":                        '\U0000005F',
+	"UnderBrace;":                      '\U000023DF',
+	"UnderBracket;":                    '\U000023B5',
+	"UnderParenthesis;":                '\U000023DD',
+	"Union;":                           '\U000022C3',
+	"UnionPlus;":                       '\U0000228E',
+	"Uogon;":                           '\U00000172',
+	"Uopf;":                            '\U0001D54C',
+	"UpArrow;":                         '\U00002191',
+	"UpArrowBar;":                      '\U00002912',
+	"UpArrowDownArrow;":                '\U000021C5',
+	"UpDownArrow;":                     '\U00002195',
+	"UpEquilibrium;":                   '\U0000296E',
+	"UpTee;":                           '\U000022A5',
+	"UpTeeArrow;":                      '\U000021A5',
+	"Uparrow;":                         '\U000021D1',
+	"Updownarrow;":                     '\U000021D5',
+	"UpperLeftArrow;":                  '\U00002196',
+	"UpperRightArrow;":                 '\U00002197',
+	"Upsi;":                            '\U000003D2',
+	"Upsilon;":                         '\U000003A5',
+	"Uring;":                           '\U0000016E',
+	"Uscr;":                            '\U0001D4B0',
+	"Utilde;":                          '\U00000168',
+	"Uuml;":                            '\U000000DC',
+	"VDash;":                           '\U000022AB',
+	"Vbar;":                            '\U00002AEB',
+	"Vcy;":                             '\U00000412',
+	"Vdash;":                           '\U000022A9',
+	"Vdashl;":                          '\U00002AE6',
+	"Vee;":                             '\U000022C1',
+	"Verbar;":                          '\U00002016',
+	"Vert;":                            '\U00002016',
+	"VerticalBar;":                     '\U00002223',
+	"VerticalLine;":                    '\U0000007C',
+	"VerticalSeparator;":               '\U00002758',
+	"VerticalTilde;":                   '\U00002240',
+	"VeryThinSpace;":                   '\U0000200A',
+	"Vfr;":                             '\U0001D519',
+	"Vopf;":                            '\U0001D54D',
+	"Vscr;":                            '\U0001D4B1',
+	"Vvdash;":                          '\U000022AA',
+	"Wcirc;":                           '\U00000174',
+	"Wedge;":                           '\U000022C0',
+	"Wfr;":                             '\U0001D51A',
+	"Wopf;":                            '\U0001D54E',
+	"Wscr;":                            '\U0001D4B2',
+	"Xfr;":                             '\U0001D51B',
+	"Xi;":                              '\U0000039E',
+	"Xopf;":                            '\U0001D54F',
+	"Xscr;":                            '\U0001D4B3',
+	"YAcy;":                            '\U0000042F',
+	"YIcy;":                            '\U00000407',
+	"YUcy;":                            '\U0000042E',
+	"Yacute;":                          '\U000000DD',
+	"Ycirc;":                           '\U00000176',
+	"Ycy;":                             '\U0000042B',
+	"Yfr;":                             '\U0001D51C',
+	"Yopf;":                            '\U0001D550',
+	"Yscr;":                            '\U0001D4B4',
+	"Yuml;":                            '\U00000178',
+	"ZHcy;":                            '\U00000416',
+	"Zacute;":                          '\U00000179',
+	"Zcaron;":                          '\U0000017D',
+	"Zcy;":                             '\U00000417',
+	"Zdot;":                            '\U0000017B',
+	"ZeroWidthSpace;":                  '\U0000200B',
+	"Zeta;":                            '\U00000396',
+	"Zfr;":                             '\U00002128',
+	"Zopf;":                            '\U00002124',
+	"Zscr;":                            '\U0001D4B5',
+	"aacute;":                          '\U000000E1',
+	"abreve;":                          '\U00000103',
+	"ac;":                              '\U0000223E',
+	"acd;":                             '\U0000223F',
+	"acirc;":                           '\U000000E2',
+	"acute;":                           '\U000000B4',
+	"acy;":                             '\U00000430',
+	"aelig;":                           '\U000000E6',
+	"af;":                              '\U00002061',
+	"afr;":                             '\U0001D51E',
+	"agrave;":                          '\U000000E0',
+	"alefsym;":                         '\U00002135',
+	"aleph;":                           '\U00002135',
+	"alpha;":                           '\U000003B1',
+	"amacr;":                           '\U00000101',
+	"amalg;":                           '\U00002A3F',
+	"amp;":                             '\U00000026',
+	"and;":                             '\U00002227',
+	"andand;":                          '\U00002A55',
+	"andd;":                            '\U00002A5C',
+	"andslope;":                        '\U00002A58',
+	"andv;":                            '\U00002A5A',
+	"ang;":                             '\U00002220',
+	"ange;":                            '\U000029A4',
+	"angle;":                           '\U00002220',
+	"angmsd;":                          '\U00002221',
+	"angmsdaa;":                        '\U000029A8',
+	"angmsdab;":                        '\U000029A9',
+	"angmsdac;":                        '\U000029AA',
+	"angmsdad;":                        '\U000029AB',
+	"angmsdae;":                        '\U000029AC',
+	"angmsdaf;":                        '\U000029AD',
+	"angmsdag;":                        '\U000029AE',
+	"angmsdah;":                        '\U000029AF',
+	"angrt;":                           '\U0000221F',
+	"angrtvb;":                         '\U000022BE',
+	"angrtvbd;":                        '\U0000299D',
+	"angsph;":                          '\U00002222',
+	"angst;":                           '\U000000C5',
+	"angzarr;":                         '\U0000237C',
+	"aogon;":                           '\U00000105',
+	"aopf;":                            '\U0001D552',
+	"ap;":                              '\U00002248',
+	"apE;":                             '\U00002A70',
+	"apacir;":                          '\U00002A6F',
+	"ape;":                             '\U0000224A',
+	"apid;":                            '\U0000224B',
+	"apos;":                            '\U00000027',
+	"approx;":                          '\U00002248',
+	"approxeq;":                        '\U0000224A',
+	"aring;":                           '\U000000E5',
+	"ascr;":                            '\U0001D4B6',
+	"ast;":                             '\U0000002A',
+	"asymp;":                           '\U00002248',
+	"asympeq;":                         '\U0000224D',
+	"atilde;":                          '\U000000E3',
+	"auml;":                            '\U000000E4',
+	"awconint;":                        '\U00002233',
+	"awint;":                           '\U00002A11',
+	"bNot;":                            '\U00002AED',
+	"backcong;":                        '\U0000224C',
+	"backepsilon;":                     '\U000003F6',
+	"backprime;":                       '\U00002035',
+	"backsim;":                         '\U0000223D',
+	"backsimeq;":                       '\U000022CD',
+	"barvee;":                          '\U000022BD',
+	"barwed;":                          '\U00002305',
+	"barwedge;":                        '\U00002305',
+	"bbrk;":                            '\U000023B5',
+	"bbrktbrk;":                        '\U000023B6',
+	"bcong;":                           '\U0000224C',
+	"bcy;":                             '\U00000431',
+	"bdquo;":                           '\U0000201E',
+	"becaus;":                          '\U00002235',
+	"because;":                         '\U00002235',
+	"bemptyv;":                         '\U000029B0',
+	"bepsi;":                           '\U000003F6',
+	"bernou;":                          '\U0000212C',
+	"beta;":                            '\U000003B2',
+	"beth;":                            '\U00002136',
+	"between;":                         '\U0000226C',
+	"bfr;":                             '\U0001D51F',
+	"bigcap;":                          '\U000022C2',
+	"bigcirc;":                         '\U000025EF',
+	"bigcup;":                          '\U000022C3',
+	"bigodot;":                         '\U00002A00',
+	"bigoplus;":                        '\U00002A01',
+	"bigotimes;":                       '\U00002A02',
+	"bigsqcup;":                        '\U00002A06',
+	"bigstar;":                         '\U00002605',
+	"bigtriangledown;":                 '\U000025BD',
+	"bigtriangleup;":                   '\U000025B3',
+	"biguplus;":                        '\U00002A04',
+	"bigvee;":                          '\U000022C1',
+	"bigwedge;":                        '\U000022C0',
+	"bkarow;":                          '\U0000290D',
+	"blacklozenge;":                    '\U000029EB',
+	"blacksquare;":                     '\U000025AA',
+	"blacktriangle;":                   '\U000025B4',
+	"blacktriangledown;":               '\U000025BE',
+	"blacktriangleleft;":               '\U000025C2',
+	"blacktriangleright;":              '\U000025B8',
+	"blank;":                           '\U00002423',
+	"blk12;":                           '\U00002592',
+	"blk14;":                           '\U00002591',
+	"blk34;":                           '\U00002593',
+	"block;":                           '\U00002588',
+	"bnot;":                            '\U00002310',
+	"bopf;":                            '\U0001D553',
+	"bot;":                             '\U000022A5',
+	"bottom;":                          '\U000022A5',
+	"bowtie;":                          '\U000022C8',
+	"boxDL;":                           '\U00002557',
+	"boxDR;":                           '\U00002554',
+	"boxDl;":                           '\U00002556',
+	"boxDr;":                           '\U00002553',
+	"boxH;":                            '\U00002550',
+	"boxHD;":                           '\U00002566',
+	"boxHU;":                           '\U00002569',
+	"boxHd;":                           '\U00002564',
+	"boxHu;":                           '\U00002567',
+	"boxUL;":                           '\U0000255D',
+	"boxUR;":                           '\U0000255A',
+	"boxUl;":                           '\U0000255C',
+	"boxUr;":                           '\U00002559',
+	"boxV;":                            '\U00002551',
+	"boxVH;":                           '\U0000256C',
+	"boxVL;":                           '\U00002563',
+	"boxVR;":                           '\U00002560',
+	"boxVh;":                           '\U0000256B',
+	"boxVl;":                           '\U00002562',
+	"boxVr;":                           '\U0000255F',
+	"boxbox;":                          '\U000029C9',
+	"boxdL;":                           '\U00002555',
+	"boxdR;":                           '\U00002552',
+	"boxdl;":                           '\U00002510',
+	"boxdr;":                           '\U0000250C',
+	"boxh;":                            '\U00002500',
+	"boxhD;":                           '\U00002565',
+	"boxhU;":                           '\U00002568',
+	"boxhd;":                           '\U0000252C',
+	"boxhu;":                           '\U00002534',
+	"boxminus;":                        '\U0000229F',
+	"boxplus;":                         '\U0000229E',
+	"boxtimes;":                        '\U000022A0',
+	"boxuL;":                           '\U0000255B',
+	"boxuR;":                           '\U00002558',
+	"boxul;":                           '\U00002518',
+	"boxur;":                           '\U00002514',
+	"boxv;":                            '\U00002502',
+	"boxvH;":                           '\U0000256A',
+	"boxvL;":                           '\U00002561',
+	"boxvR;":                           '\U0000255E',
+	"boxvh;":                           '\U0000253C',
+	"boxvl;":                           '\U00002524',
+	"boxvr;":                           '\U0000251C',
+	"bprime;":                          '\U00002035',
+	"breve;":                           '\U000002D8',
+	"brvbar;":                          '\U000000A6',
+	"bscr;":                            '\U0001D4B7',
+	"bsemi;":                           '\U0000204F',
+	"bsim;":                            '\U0000223D',
+	"bsime;":                           '\U000022CD',
+	"bsol;":                            '\U0000005C',
+	"bsolb;":                           '\U000029C5',
+	"bsolhsub;":                        '\U000027C8',
+	"bull;":                            '\U00002022',
+	"bullet;":                          '\U00002022',
+	"bump;":                            '\U0000224E',
+	"bumpE;":                           '\U00002AAE',
+	"bumpe;":                           '\U0000224F',
+	"bumpeq;":                          '\U0000224F',
+	"cacute;":                          '\U00000107',
+	"cap;":                             '\U00002229',
+	"capand;":                          '\U00002A44',
+	"capbrcup;":                        '\U00002A49',
+	"capcap;":                          '\U00002A4B',
+	"capcup;":                          '\U00002A47',
+	"capdot;":                          '\U00002A40',
+	"caret;":                           '\U00002041',
+	"caron;":                           '\U000002C7',
+	"ccaps;":                           '\U00002A4D',
+	"ccaron;":                          '\U0000010D',
+	"ccedil;":                          '\U000000E7',
+	"ccirc;":                           '\U00000109',
+	"ccups;":                           '\U00002A4C',
+	"ccupssm;":                         '\U00002A50',
+	"cdot;":                            '\U0000010B',
+	"cedil;":                           '\U000000B8',
+	"cemptyv;":                         '\U000029B2',
+	"cent;":                            '\U000000A2',
+	"centerdot;":                       '\U000000B7',
+	"cfr;":                             '\U0001D520',
+	"chcy;":                            '\U00000447',
+	"check;":                           '\U00002713',
+	"checkmark;":                       '\U00002713',
+	"chi;":                             '\U000003C7',
+	"cir;":                             '\U000025CB',
+	"cirE;":                            '\U000029C3',
+	"circ;":                            '\U000002C6',
+	"circeq;":                          '\U00002257',
+	"circlearrowleft;":                 '\U000021BA',
+	"circlearrowright;":                '\U000021BB',
+	"circledR;":                        '\U000000AE',
+	"circledS;":                        '\U000024C8',
+	"circledast;":                      '\U0000229B',
+	"circledcirc;":                     '\U0000229A',
+	"circleddash;":                     '\U0000229D',
+	"cire;":                            '\U00002257',
+	"cirfnint;":                        '\U00002A10',
+	"cirmid;":                          '\U00002AEF',
+	"cirscir;":                         '\U000029C2',
+	"clubs;":                           '\U00002663',
+	"clubsuit;":                        '\U00002663',
+	"colon;":                           '\U0000003A',
+	"colone;":                          '\U00002254',
+	"coloneq;":                         '\U00002254',
+	"comma;":                           '\U0000002C',
+	"commat;":                          '\U00000040',
+	"comp;":                            '\U00002201',
+	"compfn;":                          '\U00002218',
+	"complement;":                      '\U00002201',
+	"complexes;":                       '\U00002102',
+	"cong;":                            '\U00002245',
+	"congdot;":                         '\U00002A6D',
+	"conint;":                          '\U0000222E',
+	"copf;":                            '\U0001D554',
+	"coprod;":                          '\U00002210',
+	"copy;":                            '\U000000A9',
+	"copysr;":                          '\U00002117',
+	"crarr;":                           '\U000021B5',
+	"cross;":                           '\U00002717',
+	"cscr;":                            '\U0001D4B8',
+	"csub;":                            '\U00002ACF',
+	"csube;":                           '\U00002AD1',
+	"csup;":                            '\U00002AD0',
+	"csupe;":                           '\U00002AD2',
+	"ctdot;":                           '\U000022EF',
+	"cudarrl;":                         '\U00002938',
+	"cudarrr;":                         '\U00002935',
+	"cuepr;":                           '\U000022DE',
+	"cuesc;":                           '\U000022DF',
+	"cularr;":                          '\U000021B6',
+	"cularrp;":                         '\U0000293D',
+	"cup;":                             '\U0000222A',
+	"cupbrcap;":                        '\U00002A48',
+	"cupcap;":                          '\U00002A46',
+	"cupcup;":                          '\U00002A4A',
+	"cupdot;":                          '\U0000228D',
+	"cupor;":                           '\U00002A45',
+	"curarr;":                          '\U000021B7',
+	"curarrm;":                         '\U0000293C',
+	"curlyeqprec;":                     '\U000022DE',
+	"curlyeqsucc;":                     '\U000022DF',
+	"curlyvee;":                        '\U000022CE',
+	"curlywedge;":                      '\U000022CF',
+	"curren;":                          '\U000000A4',
+	"curvearrowleft;":                  '\U000021B6',
+	"curvearrowright;":                 '\U000021B7',
+	"cuvee;":                           '\U000022CE',
+	"cuwed;":                           '\U000022CF',
+	"cwconint;":                        '\U00002232',
+	"cwint;":                           '\U00002231',
+	"cylcty;":                          '\U0000232D',
+	"dArr;":                            '\U000021D3',
+	"dHar;":                            '\U00002965',
+	"dagger;":                          '\U00002020',
+	"daleth;":                          '\U00002138',
+	"darr;":                            '\U00002193',
+	"dash;":                            '\U00002010',
+	"dashv;":                           '\U000022A3',
+	"dbkarow;":                         '\U0000290F',
+	"dblac;":                           '\U000002DD',
+	"dcaron;":                          '\U0000010F',
+	"dcy;":                             '\U00000434',
+	"dd;":                              '\U00002146',
+	"ddagger;":                         '\U00002021',
+	"ddarr;":                           '\U000021CA',
+	"ddotseq;":                         '\U00002A77',
+	"deg;":                             '\U000000B0',
+	"delta;":                           '\U000003B4',
+	"demptyv;":                         '\U000029B1',
+	"dfisht;":                          '\U0000297F',
+	"dfr;":                             '\U0001D521',
+	"dharl;":                           '\U000021C3',
+	"dharr;":                           '\U000021C2',
+	"diam;":                            '\U000022C4',
+	"diamond;":                         '\U000022C4',
+	"diamondsuit;":                     '\U00002666',
+	"diams;":                           '\U00002666',
+	"die;":                             '\U000000A8',
+	"digamma;":                         '\U000003DD',
+	"disin;":                           '\U000022F2',
+	"div;":                             '\U000000F7',
+	"divide;":                          '\U000000F7',
+	"divideontimes;":                   '\U000022C7',
+	"divonx;":                          '\U000022C7',
+	"djcy;":                            '\U00000452',
+	"dlcorn;":                          '\U0000231E',
+	"dlcrop;":                          '\U0000230D',
+	"dollar;":                          '\U00000024',
+	"dopf;":                            '\U0001D555',
+	"dot;":                             '\U000002D9',
+	"doteq;":                           '\U00002250',
+	"doteqdot;":                        '\U00002251',
+	"dotminus;":                        '\U00002238',
+	"dotplus;":                         '\U00002214',
+	"dotsquare;":                       '\U000022A1',
+	"doublebarwedge;":                  '\U00002306',
+	"downarrow;":                       '\U00002193',
+	"downdownarrows;":                  '\U000021CA',
+	"downharpoonleft;":                 '\U000021C3',
+	"downharpoonright;":                '\U000021C2',
+	"drbkarow;":                        '\U00002910',
+	"drcorn;":                          '\U0000231F',
+	"drcrop;":                          '\U0000230C',
+	"dscr;":                            '\U0001D4B9',
+	"dscy;":                            '\U00000455',
+	"dsol;":                            '\U000029F6',
+	"dstrok;":                          '\U00000111',
+	"dtdot;":                           '\U000022F1',
+	"dtri;":                            '\U000025BF',
+	"dtrif;":                           '\U000025BE',
+	"duarr;":                           '\U000021F5',
+	"duhar;":                           '\U0000296F',
+	"dwangle;":                         '\U000029A6',
+	"dzcy;":                            '\U0000045F',
+	"dzigrarr;":                        '\U000027FF',
+	"eDDot;":                           '\U00002A77',
+	"eDot;":                            '\U00002251',
+	"eacute;":                          '\U000000E9',
+	"easter;":                          '\U00002A6E',
+	"ecaron;":                          '\U0000011B',
+	"ecir;":                            '\U00002256',
+	"ecirc;":                           '\U000000EA',
+	"ecolon;":                          '\U00002255',
+	"ecy;":                             '\U0000044D',
+	"edot;":                            '\U00000117',
+	"ee;":                              '\U00002147',
+	"efDot;":                           '\U00002252',
+	"efr;":                             '\U0001D522',
+	"eg;":                              '\U00002A9A',
+	"egrave;":                          '\U000000E8',
+	"egs;":                             '\U00002A96',
+	"egsdot;":                          '\U00002A98',
+	"el;":                              '\U00002A99',
+	"elinters;":                        '\U000023E7',
+	"ell;":                             '\U00002113',
+	"els;":                             '\U00002A95',
+	"elsdot;":                          '\U00002A97',
+	"emacr;":                           '\U00000113',
+	"empty;":                           '\U00002205',
+	"emptyset;":                        '\U00002205',
+	"emptyv;":                          '\U00002205',
+	"emsp;":                            '\U00002003',
+	"emsp13;":                          '\U00002004',
+	"emsp14;":                          '\U00002005',
+	"eng;":                             '\U0000014B',
+	"ensp;":                            '\U00002002',
+	"eogon;":                           '\U00000119',
+	"eopf;":                            '\U0001D556',
+	"epar;":                            '\U000022D5',
+	"eparsl;":                          '\U000029E3',
+	"eplus;":                           '\U00002A71',
+	"epsi;":                            '\U000003B5',
+	"epsilon;":                         '\U000003B5',
+	"epsiv;":                           '\U000003F5',
+	"eqcirc;":                          '\U00002256',
+	"eqcolon;":                         '\U00002255',
+	"eqsim;":                           '\U00002242',
+	"eqslantgtr;":                      '\U00002A96',
+	"eqslantless;":                     '\U00002A95',
+	"equals;":                          '\U0000003D',
+	"equest;":                          '\U0000225F',
+	"equiv;":                           '\U00002261',
+	"equivDD;":                         '\U00002A78',
+	"eqvparsl;":                        '\U000029E5',
+	"erDot;":                           '\U00002253',
+	"erarr;":                           '\U00002971',
+	"escr;":                            '\U0000212F',
+	"esdot;":                           '\U00002250',
+	"esim;":                            '\U00002242',
+	"eta;":                             '\U000003B7',
+	"eth;":                             '\U000000F0',
+	"euml;":                            '\U000000EB',
+	"euro;":                            '\U000020AC',
+	"excl;":                            '\U00000021',
+	"exist;":                           '\U00002203',
+	"expectation;":                     '\U00002130',
+	"exponentiale;":                    '\U00002147',
+	"fallingdotseq;":                   '\U00002252',
+	"fcy;":                             '\U00000444',
+	"female;":                          '\U00002640',
+	"ffilig;":                          '\U0000FB03',
+	"fflig;":                           '\U0000FB00',
+	"ffllig;":                          '\U0000FB04',
+	"ffr;":                             '\U0001D523',
+	"filig;":                           '\U0000FB01',
+	"flat;":                            '\U0000266D',
+	"fllig;":                           '\U0000FB02',
+	"fltns;":                           '\U000025B1',
+	"fnof;":                            '\U00000192',
+	"fopf;":                            '\U0001D557',
+	"forall;":                          '\U00002200',
+	"fork;":                            '\U000022D4',
+	"forkv;":                           '\U00002AD9',
+	"fpartint;":                        '\U00002A0D',
+	"frac12;":                          '\U000000BD',
+	"frac13;":                          '\U00002153',
+	"frac14;":                          '\U000000BC',
+	"frac15;":                          '\U00002155',
+	"frac16;":                          '\U00002159',
+	"frac18;":                          '\U0000215B',
+	"frac23;":                          '\U00002154',
+	"frac25;":                          '\U00002156',
+	"frac34;":                          '\U000000BE',
+	"frac35;":                          '\U00002157',
+	"frac38;":                          '\U0000215C',
+	"frac45;":                          '\U00002158',
+	"frac56;":                          '\U0000215A',
+	"frac58;":                          '\U0000215D',
+	"frac78;":                          '\U0000215E',
+	"frasl;":                           '\U00002044',
+	"frown;":                           '\U00002322',
+	"fscr;":                            '\U0001D4BB',
+	"gE;":                              '\U00002267',
+	"gEl;":                             '\U00002A8C',
+	"gacute;":                          '\U000001F5',
+	"gamma;":                           '\U000003B3',
+	"gammad;":                          '\U000003DD',
+	"gap;":                             '\U00002A86',
+	"gbreve;":                          '\U0000011F',
+	"gcirc;":                           '\U0000011D',
+	"gcy;":                             '\U00000433',
+	"gdot;":                            '\U00000121',
+	"ge;":                              '\U00002265',
+	"gel;":                             '\U000022DB',
+	"geq;":                             '\U00002265',
+	"geqq;":                            '\U00002267',
+	"geqslant;":                        '\U00002A7E',
+	"ges;":                             '\U00002A7E',
+	"gescc;":                           '\U00002AA9',
+	"gesdot;":                          '\U00002A80',
+	"gesdoto;":                         '\U00002A82',
+	"gesdotol;":                        '\U00002A84',
+	"gesles;":                          '\U00002A94',
+	"gfr;":                             '\U0001D524',
+	"gg;":                              '\U0000226B',
+	"ggg;":                             '\U000022D9',
+	"gimel;":                           '\U00002137',
+	"gjcy;":                            '\U00000453',
+	"gl;":                              '\U00002277',
+	"glE;":                             '\U00002A92',
+	"gla;":                             '\U00002AA5',
+	"glj;":                             '\U00002AA4',
+	"gnE;":                             '\U00002269',
+	"gnap;":                            '\U00002A8A',
+	"gnapprox;":                        '\U00002A8A',
+	"gne;":                             '\U00002A88',
+	"gneq;":                            '\U00002A88',
+	"gneqq;":                           '\U00002269',
+	"gnsim;":                           '\U000022E7',
+	"gopf;":                            '\U0001D558',
+	"grave;":                           '\U00000060',
+	"gscr;":                            '\U0000210A',
+	"gsim;":                            '\U00002273',
+	"gsime;":                           '\U00002A8E',
+	"gsiml;":                           '\U00002A90',
+	"gt;":                              '\U0000003E',
+	"gtcc;":                            '\U00002AA7',
+	"gtcir;":                           '\U00002A7A',
+	"gtdot;":                           '\U000022D7',
+	"gtlPar;":                          '\U00002995',
+	"gtquest;":                         '\U00002A7C',
+	"gtrapprox;":                       '\U00002A86',
+	"gtrarr;":                          '\U00002978',
+	"gtrdot;":                          '\U000022D7',
+	"gtreqless;":                       '\U000022DB',
+	"gtreqqless;":                      '\U00002A8C',
+	"gtrless;":                         '\U00002277',
+	"gtrsim;":                          '\U00002273',
+	"hArr;":                            '\U000021D4',
+	"hairsp;":                          '\U0000200A',
+	"half;":                            '\U000000BD',
+	"hamilt;":                          '\U0000210B',
+	"hardcy;":                          '\U0000044A',
+	"harr;":                            '\U00002194',
+	"harrcir;":                         '\U00002948',
+	"harrw;":                           '\U000021AD',
+	"hbar;":                            '\U0000210F',
+	"hcirc;":                           '\U00000125',
+	"hearts;":                          '\U00002665',
+	"heartsuit;":                       '\U00002665',
+	"hellip;":                          '\U00002026',
+	"hercon;":                          '\U000022B9',
+	"hfr;":                             '\U0001D525',
+	"hksearow;":                        '\U00002925',
+	"hkswarow;":                        '\U00002926',
+	"hoarr;":                           '\U000021FF',
+	"homtht;":                          '\U0000223B',
+	"hookleftarrow;":                   '\U000021A9',
+	"hookrightarrow;":                  '\U000021AA',
+	"hopf;":                            '\U0001D559',
+	"horbar;":                          '\U00002015',
+	"hscr;":                            '\U0001D4BD',
+	"hslash;":                          '\U0000210F',
+	"hstrok;":                          '\U00000127',
+	"hybull;":                          '\U00002043',
+	"hyphen;":                          '\U00002010',
+	"iacute;":                          '\U000000ED',
+	"ic;":                              '\U00002063',
+	"icirc;":                           '\U000000EE',
+	"icy;":                             '\U00000438',
+	"iecy;":                            '\U00000435',
+	"iexcl;":                           '\U000000A1',
+	"iff;":                             '\U000021D4',
+	"ifr;":                             '\U0001D526',
+	"igrave;":                          '\U000000EC',
+	"ii;":                              '\U00002148',
+	"iiiint;":                          '\U00002A0C',
+	"iiint;":                           '\U0000222D',
+	"iinfin;":                          '\U000029DC',
+	"iiota;":                           '\U00002129',
+	"ijlig;":                           '\U00000133',
+	"imacr;":                           '\U0000012B',
+	"image;":                           '\U00002111',
+	"imagline;":                        '\U00002110',
+	"imagpart;":                        '\U00002111',
+	"imath;":                           '\U00000131',
+	"imof;":                            '\U000022B7',
+	"imped;":                           '\U000001B5',
+	"in;":                              '\U00002208',
+	"incare;":                          '\U00002105',
+	"infin;":                           '\U0000221E',
+	"infintie;":                        '\U000029DD',
+	"inodot;":                          '\U00000131',
+	"int;":                             '\U0000222B',
+	"intcal;":                          '\U000022BA',
+	"integers;":                        '\U00002124',
+	"intercal;":                        '\U000022BA',
+	"intlarhk;":                        '\U00002A17',
+	"intprod;":                         '\U00002A3C',
+	"iocy;":                            '\U00000451',
+	"iogon;":                           '\U0000012F',
+	"iopf;":                            '\U0001D55A',
+	"iota;":                            '\U000003B9',
+	"iprod;":                           '\U00002A3C',
+	"iquest;":                          '\U000000BF',
+	"iscr;":                            '\U0001D4BE',
+	"isin;":                            '\U00002208',
+	"isinE;":                           '\U000022F9',
+	"isindot;":                         '\U000022F5',
+	"isins;":                           '\U000022F4',
+	"isinsv;":                          '\U000022F3',
+	"isinv;":                           '\U00002208',
+	"it;":                              '\U00002062',
+	"itilde;":                          '\U00000129',
+	"iukcy;":                           '\U00000456',
+	"iuml;":                            '\U000000EF',
+	"jcirc;":                           '\U00000135',
+	"jcy;":                             '\U00000439',
+	"jfr;":                             '\U0001D527',
+	"jmath;":                           '\U00000237',
+	"jopf;":                            '\U0001D55B',
+	"jscr;":                            '\U0001D4BF',
+	"jsercy;":                          '\U00000458',
+	"jukcy;":                           '\U00000454',
+	"kappa;":                           '\U000003BA',
+	"kappav;":                          '\U000003F0',
+	"kcedil;":                          '\U00000137',
+	"kcy;":                             '\U0000043A',
+	"kfr;":                             '\U0001D528',
+	"kgreen;":                          '\U00000138',
+	"khcy;":                            '\U00000445',
+	"kjcy;":                            '\U0000045C',
+	"kopf;":                            '\U0001D55C',
+	"kscr;":                            '\U0001D4C0',
+	"lAarr;":                           '\U000021DA',
+	"lArr;":                            '\U000021D0',
+	"lAtail;":                          '\U0000291B',
+	"lBarr;":                           '\U0000290E',
+	"lE;":                              '\U00002266',
+	"lEg;":                             '\U00002A8B',
+	"lHar;":                            '\U00002962',
+	"lacute;":                          '\U0000013A',
+	"laemptyv;":                        '\U000029B4',
+	"lagran;":                          '\U00002112',
+	"lambda;":                          '\U000003BB',
+	"lang;":                            '\U000027E8',
+	"langd;":                           '\U00002991',
+	"langle;":                          '\U000027E8',
+	"lap;":                             '\U00002A85',
+	"laquo;":                           '\U000000AB',
+	"larr;":                            '\U00002190',
+	"larrb;":                           '\U000021E4',
+	"larrbfs;":                         '\U0000291F',
+	"larrfs;":                          '\U0000291D',
+	"larrhk;":                          '\U000021A9',
+	"larrlp;":                          '\U000021AB',
+	"larrpl;":                          '\U00002939',
+	"larrsim;":                         '\U00002973',
+	"larrtl;":                          '\U000021A2',
+	"lat;":                             '\U00002AAB',
+	"latail;":                          '\U00002919',
+	"late;":                            '\U00002AAD',
+	"lbarr;":                           '\U0000290C',
+	"lbbrk;":                           '\U00002772',
+	"lbrace;":                          '\U0000007B',
+	"lbrack;":                          '\U0000005B',
+	"lbrke;":                           '\U0000298B',
+	"lbrksld;":                         '\U0000298F',
+	"lbrkslu;":                         '\U0000298D',
+	"lcaron;":                          '\U0000013E',
+	"lcedil;":                          '\U0000013C',
+	"lceil;":                           '\U00002308',
+	"lcub;":                            '\U0000007B',
+	"lcy;":                             '\U0000043B',
+	"ldca;":                            '\U00002936',
+	"ldquo;":                           '\U0000201C',
+	"ldquor;":                          '\U0000201E',
+	"ldrdhar;":                         '\U00002967',
+	"ldrushar;":                        '\U0000294B',
+	"ldsh;":                            '\U000021B2',
+	"le;":                              '\U00002264',
+	"leftarrow;":                       '\U00002190',
+	"leftarrowtail;":                   '\U000021A2',
+	"leftharpoondown;":                 '\U000021BD',
+	"leftharpoonup;":                   '\U000021BC',
+	"leftleftarrows;":                  '\U000021C7',
+	"leftrightarrow;":                  '\U00002194',
+	"leftrightarrows;":                 '\U000021C6',
+	"leftrightharpoons;":               '\U000021CB',
+	"leftrightsquigarrow;":             '\U000021AD',
+	"leftthreetimes;":                  '\U000022CB',
+	"leg;":                             '\U000022DA',
+	"leq;":                             '\U00002264',
+	"leqq;":                            '\U00002266',
+	"leqslant;":                        '\U00002A7D',
+	"les;":                             '\U00002A7D',
+	"lescc;":                           '\U00002AA8',
+	"lesdot;":                          '\U00002A7F',
+	"lesdoto;":                         '\U00002A81',
+	"lesdotor;":                        '\U00002A83',
+	"lesges;":                          '\U00002A93',
+	"lessapprox;":                      '\U00002A85',
+	"lessdot;":                         '\U000022D6',
+	"lesseqgtr;":                       '\U000022DA',
+	"lesseqqgtr;":                      '\U00002A8B',
+	"lessgtr;":                         '\U00002276',
+	"lesssim;":                         '\U00002272',
+	"lfisht;":                          '\U0000297C',
+	"lfloor;":                          '\U0000230A',
+	"lfr;":                             '\U0001D529',
+	"lg;":                              '\U00002276',
+	"lgE;":                             '\U00002A91',
+	"lhard;":                           '\U000021BD',
+	"lharu;":                           '\U000021BC',
+	"lharul;":                          '\U0000296A',
+	"lhblk;":                           '\U00002584',
+	"ljcy;":                            '\U00000459',
+	"ll;":                              '\U0000226A',
+	"llarr;":                           '\U000021C7',
+	"llcorner;":                        '\U0000231E',
+	"llhard;":                          '\U0000296B',
+	"lltri;":                           '\U000025FA',
+	"lmidot;":                          '\U00000140',
+	"lmoust;":                          '\U000023B0',
+	"lmoustache;":                      '\U000023B0',
+	"lnE;":                             '\U00002268',
+	"lnap;":                            '\U00002A89',
+	"lnapprox;":                        '\U00002A89',
+	"lne;":                             '\U00002A87',
+	"lneq;":                            '\U00002A87',
+	"lneqq;":                           '\U00002268',
+	"lnsim;":                           '\U000022E6',
+	"loang;":                           '\U000027EC',
+	"loarr;":                           '\U000021FD',
+	"lobrk;":                           '\U000027E6',
+	"longleftarrow;":                   '\U000027F5',
+	"longleftrightarrow;":              '\U000027F7',
+	"longmapsto;":                      '\U000027FC',
+	"longrightarrow;":                  '\U000027F6',
+	"looparrowleft;":                   '\U000021AB',
+	"looparrowright;":                  '\U000021AC',
+	"lopar;":                           '\U00002985',
+	"lopf;":                            '\U0001D55D',
+	"loplus;":                          '\U00002A2D',
+	"lotimes;":                         '\U00002A34',
+	"lowast;":                          '\U00002217',
+	"lowbar;":                          '\U0000005F',
+	"loz;":                             '\U000025CA',
+	"lozenge;":                         '\U000025CA',
+	"lozf;":                            '\U000029EB',
+	"lpar;":                            '\U00000028',
+	"lparlt;":                          '\U00002993',
+	"lrarr;":                           '\U000021C6',
+	"lrcorner;":                        '\U0000231F',
+	"lrhar;":                           '\U000021CB',
+	"lrhard;":                          '\U0000296D',
+	"lrm;":                             '\U0000200E',
+	"lrtri;":                           '\U000022BF',
+	"lsaquo;":                          '\U00002039',
+	"lscr;":                            '\U0001D4C1',
+	"lsh;":                             '\U000021B0',
+	"lsim;":                            '\U00002272',
+	"lsime;":                           '\U00002A8D',
+	"lsimg;":                           '\U00002A8F',
+	"lsqb;":                            '\U0000005B',
+	"lsquo;":                           '\U00002018',
+	"lsquor;":                          '\U0000201A',
+	"lstrok;":                          '\U00000142',
+	"lt;":                              '\U0000003C',
+	"ltcc;":                            '\U00002AA6',
+	"ltcir;":                           '\U00002A79',
+	"ltdot;":                           '\U000022D6',
+	"lthree;":                          '\U000022CB',
+	"ltimes;":                          '\U000022C9',
+	"ltlarr;":                          '\U00002976',
+	"ltquest;":                         '\U00002A7B',
+	"ltrPar;":                          '\U00002996',
+	"ltri;":                            '\U000025C3',
+	"ltrie;":                           '\U000022B4',
+	"ltrif;":                           '\U000025C2',
+	"lurdshar;":                        '\U0000294A',
+	"luruhar;":                         '\U00002966',
+	"mDDot;":                           '\U0000223A',
+	"macr;":                            '\U000000AF',
+	"male;":                            '\U00002642',
+	"malt;":                            '\U00002720',
+	"maltese;":                         '\U00002720',
+	"map;":                             '\U000021A6',
+	"mapsto;":                          '\U000021A6',
+	"mapstodown;":                      '\U000021A7',
+	"mapstoleft;":                      '\U000021A4',
+	"mapstoup;":                        '\U000021A5',
+	"marker;":                          '\U000025AE',
+	"mcomma;":                          '\U00002A29',
+	"mcy;":                             '\U0000043C',
+	"mdash;":                           '\U00002014',
+	"measuredangle;":                   '\U00002221',
+	"mfr;":                             '\U0001D52A',
+	"mho;":                             '\U00002127',
+	"micro;":                           '\U000000B5',
+	"mid;":                             '\U00002223',
+	"midast;":                          '\U0000002A',
+	"midcir;":                          '\U00002AF0',
+	"middot;":                          '\U000000B7',
+	"minus;":                           '\U00002212',
+	"minusb;":                          '\U0000229F',
+	"minusd;":                          '\U00002238',
+	"minusdu;":                         '\U00002A2A',
+	"mlcp;":                            '\U00002ADB',
+	"mldr;":                            '\U00002026',
+	"mnplus;":                          '\U00002213',
+	"models;":                          '\U000022A7',
+	"mopf;":                            '\U0001D55E',
+	"mp;":                              '\U00002213',
+	"mscr;":                            '\U0001D4C2',
+	"mstpos;":                          '\U0000223E',
+	"mu;":                              '\U000003BC',
+	"multimap;":                        '\U000022B8',
+	"mumap;":                           '\U000022B8',
+	"nLeftarrow;":                      '\U000021CD',
+	"nLeftrightarrow;":                 '\U000021CE',
+	"nRightarrow;":                     '\U000021CF',
+	"nVDash;":                          '\U000022AF',
+	"nVdash;":                          '\U000022AE',
+	"nabla;":                           '\U00002207',
+	"nacute;":                          '\U00000144',
+	"nap;":                             '\U00002249',
+	"napos;":                           '\U00000149',
+	"napprox;":                         '\U00002249',
+	"natur;":                           '\U0000266E',
+	"natural;":                         '\U0000266E',
+	"naturals;":                        '\U00002115',
+	"nbsp;":                            '\U000000A0',
+	"ncap;":                            '\U00002A43',
+	"ncaron;":                          '\U00000148',
+	"ncedil;":                          '\U00000146',
+	"ncong;":                           '\U00002247',
+	"ncup;":                            '\U00002A42',
+	"ncy;":                             '\U0000043D',
+	"ndash;":                           '\U00002013',
+	"ne;":                              '\U00002260',
+	"neArr;":                           '\U000021D7',
+	"nearhk;":                          '\U00002924',
+	"nearr;":                           '\U00002197',
+	"nearrow;":                         '\U00002197',
+	"nequiv;":                          '\U00002262',
+	"nesear;":                          '\U00002928',
+	"nexist;":                          '\U00002204',
+	"nexists;":                         '\U00002204',
+	"nfr;":                             '\U0001D52B',
+	"nge;":                             '\U00002271',
+	"ngeq;":                            '\U00002271',
+	"ngsim;":                           '\U00002275',
+	"ngt;":                             '\U0000226F',
+	"ngtr;":                            '\U0000226F',
+	"nhArr;":                           '\U000021CE',
+	"nharr;":                           '\U000021AE',
+	"nhpar;":                           '\U00002AF2',
+	"ni;":                              '\U0000220B',
+	"nis;":                             '\U000022FC',
+	"nisd;":                            '\U000022FA',
+	"niv;":                             '\U0000220B',
+	"njcy;":                            '\U0000045A',
+	"nlArr;":                           '\U000021CD',
+	"nlarr;":                           '\U0000219A',
+	"nldr;":                            '\U00002025',
+	"nle;":                             '\U00002270',
+	"nleftarrow;":                      '\U0000219A',
+	"nleftrightarrow;":                 '\U000021AE',
+	"nleq;":                            '\U00002270',
+	"nless;":                           '\U0000226E',
+	"nlsim;":                           '\U00002274',
+	"nlt;":                             '\U0000226E',
+	"nltri;":                           '\U000022EA',
+	"nltrie;":                          '\U000022EC',
+	"nmid;":                            '\U00002224',
+	"nopf;":                            '\U0001D55F',
+	"not;":                             '\U000000AC',
+	"notin;":                           '\U00002209',
+	"notinva;":                         '\U00002209',
+	"notinvb;":                         '\U000022F7',
+	"notinvc;":                         '\U000022F6',
+	"notni;":                           '\U0000220C',
+	"notniva;":                         '\U0000220C',
+	"notnivb;":                         '\U000022FE',
+	"notnivc;":                         '\U000022FD',
+	"npar;":                            '\U00002226',
+	"nparallel;":                       '\U00002226',
+	"npolint;":                         '\U00002A14',
+	"npr;":                             '\U00002280',
+	"nprcue;":                          '\U000022E0',
+	"nprec;":                           '\U00002280',
+	"nrArr;":                           '\U000021CF',
+	"nrarr;":                           '\U0000219B',
+	"nrightarrow;":                     '\U0000219B',
+	"nrtri;":                           '\U000022EB',
+	"nrtrie;":                          '\U000022ED',
+	"nsc;":                             '\U00002281',
+	"nsccue;":                          '\U000022E1',
+	"nscr;":                            '\U0001D4C3',
+	"nshortmid;":                       '\U00002224',
+	"nshortparallel;":                  '\U00002226',
+	"nsim;":                            '\U00002241',
+	"nsime;":                           '\U00002244',
+	"nsimeq;":                          '\U00002244',
+	"nsmid;":                           '\U00002224',
+	"nspar;":                           '\U00002226',
+	"nsqsube;":                         '\U000022E2',
+	"nsqsupe;":                         '\U000022E3',
+	"nsub;":                            '\U00002284',
+	"nsube;":                           '\U00002288',
+	"nsubseteq;":                       '\U00002288',
+	"nsucc;":                           '\U00002281',
+	"nsup;":                            '\U00002285',
+	"nsupe;":                           '\U00002289',
+	"nsupseteq;":                       '\U00002289',
+	"ntgl;":                            '\U00002279',
+	"ntilde;":                          '\U000000F1',
+	"ntlg;":                            '\U00002278',
+	"ntriangleleft;":                   '\U000022EA',
+	"ntrianglelefteq;":                 '\U000022EC',
+	"ntriangleright;":                  '\U000022EB',
+	"ntrianglerighteq;":                '\U000022ED',
+	"nu;":                              '\U000003BD',
+	"num;":                             '\U00000023',
+	"numero;":                          '\U00002116',
+	"numsp;":                           '\U00002007',
+	"nvDash;":                          '\U000022AD',
+	"nvHarr;":                          '\U00002904',
+	"nvdash;":                          '\U000022AC',
+	"nvinfin;":                         '\U000029DE',
+	"nvlArr;":                          '\U00002902',
+	"nvrArr;":                          '\U00002903',
+	"nwArr;":                           '\U000021D6',
+	"nwarhk;":                          '\U00002923',
+	"nwarr;":                           '\U00002196',
+	"nwarrow;":                         '\U00002196',
+	"nwnear;":                          '\U00002927',
+	"oS;":                              '\U000024C8',
+	"oacute;":                          '\U000000F3',
+	"oast;":                            '\U0000229B',
+	"ocir;":                            '\U0000229A',
+	"ocirc;":                           '\U000000F4',
+	"ocy;":                             '\U0000043E',
+	"odash;":                           '\U0000229D',
+	"odblac;":                          '\U00000151',
+	"odiv;":                            '\U00002A38',
+	"odot;":                            '\U00002299',
+	"odsold;":                          '\U000029BC',
+	"oelig;":                           '\U00000153',
+	"ofcir;":                           '\U000029BF',
+	"ofr;":                             '\U0001D52C',
+	"ogon;":                            '\U000002DB',
+	"ograve;":                          '\U000000F2',
+	"ogt;":                             '\U000029C1',
+	"ohbar;":                           '\U000029B5',
+	"ohm;":                             '\U000003A9',
+	"oint;":                            '\U0000222E',
+	"olarr;":                           '\U000021BA',
+	"olcir;":                           '\U000029BE',
+	"olcross;":                         '\U000029BB',
+	"oline;":                           '\U0000203E',
+	"olt;":                             '\U000029C0',
+	"omacr;":                           '\U0000014D',
+	"omega;":                           '\U000003C9',
+	"omicron;":                         '\U000003BF',
+	"omid;":                            '\U000029B6',
+	"ominus;":                          '\U00002296',
+	"oopf;":                            '\U0001D560',
+	"opar;":                            '\U000029B7',
+	"operp;":                           '\U000029B9',
+	"oplus;":                           '\U00002295',
+	"or;":                              '\U00002228',
+	"orarr;":                           '\U000021BB',
+	"ord;":                             '\U00002A5D',
+	"order;":                           '\U00002134',
+	"orderof;":                         '\U00002134',
+	"ordf;":                            '\U000000AA',
+	"ordm;":                            '\U000000BA',
+	"origof;":                          '\U000022B6',
+	"oror;":                            '\U00002A56',
+	"orslope;":                         '\U00002A57',
+	"orv;":                             '\U00002A5B',
+	"oscr;":                            '\U00002134',
+	"oslash;":                          '\U000000F8',
+	"osol;":                            '\U00002298',
+	"otilde;":                          '\U000000F5',
+	"otimes;":                          '\U00002297',
+	"otimesas;":                        '\U00002A36',
+	"ouml;":                            '\U000000F6',
+	"ovbar;":                           '\U0000233D',
+	"par;":                             '\U00002225',
+	"para;":                            '\U000000B6',
+	"parallel;":                        '\U00002225',
+	"parsim;":                          '\U00002AF3',
+	"parsl;":                           '\U00002AFD',
+	"part;":                            '\U00002202',
+	"pcy;":                             '\U0000043F',
+	"percnt;":                          '\U00000025',
+	"period;":                          '\U0000002E',
+	"permil;":                          '\U00002030',
+	"perp;":                            '\U000022A5',
+	"pertenk;":                         '\U00002031',
+	"pfr;":                             '\U0001D52D',
+	"phi;":                             '\U000003C6',
+	"phiv;":                            '\U000003D5',
+	"phmmat;":                          '\U00002133',
+	"phone;":                           '\U0000260E',
+	"pi;":                              '\U000003C0',
+	"pitchfork;":                       '\U000022D4',
+	"piv;":                             '\U000003D6',
+	"planck;":                          '\U0000210F',
+	"planckh;":                         '\U0000210E',
+	"plankv;":                          '\U0000210F',
+	"plus;":                            '\U0000002B',
+	"plusacir;":                        '\U00002A23',
+	"plusb;":                           '\U0000229E',
+	"pluscir;":                         '\U00002A22',
+	"plusdo;":                          '\U00002214',
+	"plusdu;":                          '\U00002A25',
+	"pluse;":                           '\U00002A72',
+	"plusmn;":                          '\U000000B1',
+	"plussim;":                         '\U00002A26',
+	"plustwo;":                         '\U00002A27',
+	"pm;":                              '\U000000B1',
+	"pointint;":                        '\U00002A15',
+	"popf;":                            '\U0001D561',
+	"pound;":                           '\U000000A3',
+	"pr;":                              '\U0000227A',
+	"prE;":                             '\U00002AB3',
+	"prap;":                            '\U00002AB7',
+	"prcue;":                           '\U0000227C',
+	"pre;":                             '\U00002AAF',
+	"prec;":                            '\U0000227A',
+	"precapprox;":                      '\U00002AB7',
+	"preccurlyeq;":                     '\U0000227C',
+	"preceq;":                          '\U00002AAF',
+	"precnapprox;":                     '\U00002AB9',
+	"precneqq;":                        '\U00002AB5',
+	"precnsim;":                        '\U000022E8',
+	"precsim;":                         '\U0000227E',
+	"prime;":                           '\U00002032',
+	"primes;":                          '\U00002119',
+	"prnE;":                            '\U00002AB5',
+	"prnap;":                           '\U00002AB9',
+	"prnsim;":                          '\U000022E8',
+	"prod;":                            '\U0000220F',
+	"profalar;":                        '\U0000232E',
+	"profline;":                        '\U00002312',
+	"profsurf;":                        '\U00002313',
+	"prop;":                            '\U0000221D',
+	"propto;":                          '\U0000221D',
+	"prsim;":                           '\U0000227E',
+	"prurel;":                          '\U000022B0',
+	"pscr;":                            '\U0001D4C5',
+	"psi;":                             '\U000003C8',
+	"puncsp;":                          '\U00002008',
+	"qfr;":                             '\U0001D52E',
+	"qint;":                            '\U00002A0C',
+	"qopf;":                            '\U0001D562',
+	"qprime;":                          '\U00002057',
+	"qscr;":                            '\U0001D4C6',
+	"quaternions;":                     '\U0000210D',
+	"quatint;":                         '\U00002A16',
+	"quest;":                           '\U0000003F',
+	"questeq;":                         '\U0000225F',
+	"quot;":                            '\U00000022',
+	"rAarr;":                           '\U000021DB',
+	"rArr;":                            '\U000021D2',
+	"rAtail;":                          '\U0000291C',
+	"rBarr;":                           '\U0000290F',
+	"rHar;":                            '\U00002964',
+	"racute;":                          '\U00000155',
+	"radic;":                           '\U0000221A',
+	"raemptyv;":                        '\U000029B3',
+	"rang;":                            '\U000027E9',
+	"rangd;":                           '\U00002992',
+	"range;":                           '\U000029A5',
+	"rangle;":                          '\U000027E9',
+	"raquo;":                           '\U000000BB',
+	"rarr;":                            '\U00002192',
+	"rarrap;":                          '\U00002975',
+	"rarrb;":                           '\U000021E5',
+	"rarrbfs;":                         '\U00002920',
+	"rarrc;":                           '\U00002933',
+	"rarrfs;":                          '\U0000291E',
+	"rarrhk;":                          '\U000021AA',
+	"rarrlp;":                          '\U000021AC',
+	"rarrpl;":                          '\U00002945',
+	"rarrsim;":                         '\U00002974',
+	"rarrtl;":                          '\U000021A3',
+	"rarrw;":                           '\U0000219D',
+	"ratail;":                          '\U0000291A',
+	"ratio;":                           '\U00002236',
+	"rationals;":                       '\U0000211A',
+	"rbarr;":                           '\U0000290D',
+	"rbbrk;":                           '\U00002773',
+	"rbrace;":                          '\U0000007D',
+	"rbrack;":                          '\U0000005D',
+	"rbrke;":                           '\U0000298C',
+	"rbrksld;":                         '\U0000298E',
+	"rbrkslu;":                         '\U00002990',
+	"rcaron;":                          '\U00000159',
+	"rcedil;":                          '\U00000157',
+	"rceil;":                           '\U00002309',
+	"rcub;":                            '\U0000007D',
+	"rcy;":                             '\U00000440',
+	"rdca;":                            '\U00002937',
+	"rdldhar;":                         '\U00002969',
+	"rdquo;":                           '\U0000201D',
+	"rdquor;":                          '\U0000201D',
+	"rdsh;":                            '\U000021B3',
+	"real;":                            '\U0000211C',
+	"realine;":                         '\U0000211B',
+	"realpart;":                        '\U0000211C',
+	"reals;":                           '\U0000211D',
+	"rect;":                            '\U000025AD',
+	"reg;":                             '\U000000AE',
+	"rfisht;":                          '\U0000297D',
+	"rfloor;":                          '\U0000230B',
+	"rfr;":                             '\U0001D52F',
+	"rhard;":                           '\U000021C1',
+	"rharu;":                           '\U000021C0',
+	"rharul;":                          '\U0000296C',
+	"rho;":                             '\U000003C1',
+	"rhov;":                            '\U000003F1',
+	"rightarrow;":                      '\U00002192',
+	"rightarrowtail;":                  '\U000021A3',
+	"rightharpoondown;":                '\U000021C1',
+	"rightharpoonup;":                  '\U000021C0',
+	"rightleftarrows;":                 '\U000021C4',
+	"rightleftharpoons;":               '\U000021CC',
+	"rightrightarrows;":                '\U000021C9',
+	"rightsquigarrow;":                 '\U0000219D',
+	"rightthreetimes;":                 '\U000022CC',
+	"ring;":                            '\U000002DA',
+	"risingdotseq;":                    '\U00002253',
+	"rlarr;":                           '\U000021C4',
+	"rlhar;":                           '\U000021CC',
+	"rlm;":                             '\U0000200F',
+	"rmoust;":                          '\U000023B1',
+	"rmoustache;":                      '\U000023B1',
+	"rnmid;":                           '\U00002AEE',
+	"roang;":                           '\U000027ED',
+	"roarr;":                           '\U000021FE',
+	"robrk;":                           '\U000027E7',
+	"ropar;":                           '\U00002986',
+	"ropf;":                            '\U0001D563',
+	"roplus;":                          '\U00002A2E',
+	"rotimes;":                         '\U00002A35',
+	"rpar;":                            '\U00000029',
+	"rpargt;":                          '\U00002994',
+	"rppolint;":                        '\U00002A12',
+	"rrarr;":                           '\U000021C9',
+	"rsaquo;":                          '\U0000203A',
+	"rscr;":                            '\U0001D4C7',
+	"rsh;":                             '\U000021B1',
+	"rsqb;":                            '\U0000005D',
+	"rsquo;":                           '\U00002019',
+	"rsquor;":                          '\U00002019',
+	"rthree;":                          '\U000022CC',
+	"rtimes;":                          '\U000022CA',
+	"rtri;":                            '\U000025B9',
+	"rtrie;":                           '\U000022B5',
+	"rtrif;":                           '\U000025B8',
+	"rtriltri;":                        '\U000029CE',
+	"ruluhar;":                         '\U00002968',
+	"rx;":                              '\U0000211E',
+	"sacute;":                          '\U0000015B',
+	"sbquo;":                           '\U0000201A',
+	"sc;":                              '\U0000227B',
+	"scE;":                             '\U00002AB4',
+	"scap;":                            '\U00002AB8',
+	"scaron;":                          '\U00000161',
+	"sccue;":                           '\U0000227D',
+	"sce;":                             '\U00002AB0',
+	"scedil;":                          '\U0000015F',
+	"scirc;":                           '\U0000015D',
+	"scnE;":                            '\U00002AB6',
+	"scnap;":                           '\U00002ABA',
+	"scnsim;":                          '\U000022E9',
+	"scpolint;":                        '\U00002A13',
+	"scsim;":                           '\U0000227F',
+	"scy;":                             '\U00000441',
+	"sdot;":                            '\U000022C5',
+	"sdotb;":                           '\U000022A1',
+	"sdote;":                           '\U00002A66',
+	"seArr;":                           '\U000021D8',
+	"searhk;":                          '\U00002925',
+	"searr;":                           '\U00002198',
+	"searrow;":                         '\U00002198',
+	"sect;":                            '\U000000A7',
+	"semi;":                            '\U0000003B',
+	"seswar;":                          '\U00002929',
+	"setminus;":                        '\U00002216',
+	"setmn;":                           '\U00002216',
+	"sext;":                            '\U00002736',
+	"sfr;":                             '\U0001D530',
+	"sfrown;":                          '\U00002322',
+	"sharp;":                           '\U0000266F',
+	"shchcy;":                          '\U00000449',
+	"shcy;":                            '\U00000448',
+	"shortmid;":                        '\U00002223',
+	"shortparallel;":                   '\U00002225',
+	"shy;":                             '\U000000AD',
+	"sigma;":                           '\U000003C3',
+	"sigmaf;":                          '\U000003C2',
+	"sigmav;":                          '\U000003C2',
+	"sim;":                             '\U0000223C',
+	"simdot;":                          '\U00002A6A',
+	"sime;":                            '\U00002243',
+	"simeq;":                           '\U00002243',
+	"simg;":                            '\U00002A9E',
+	"simgE;":                           '\U00002AA0',
+	"siml;":                            '\U00002A9D',
+	"simlE;":                           '\U00002A9F',
+	"simne;":                           '\U00002246',
+	"simplus;":                         '\U00002A24',
+	"simrarr;":                         '\U00002972',
+	"slarr;":                           '\U00002190',
+	"smallsetminus;":                   '\U00002216',
+	"smashp;":                          '\U00002A33',
+	"smeparsl;":                        '\U000029E4',
+	"smid;":                            '\U00002223',
+	"smile;":                           '\U00002323',
+	"smt;":                             '\U00002AAA',
+	"smte;":                            '\U00002AAC',
+	"softcy;":                          '\U0000044C',
+	"sol;":                             '\U0000002F',
+	"solb;":                            '\U000029C4',
+	"solbar;":                          '\U0000233F',
+	"sopf;":                            '\U0001D564',
+	"spades;":                          '\U00002660',
+	"spadesuit;":                       '\U00002660',
+	"spar;":                            '\U00002225',
+	"sqcap;":                           '\U00002293',
+	"sqcup;":                           '\U00002294',
+	"sqsub;":                           '\U0000228F',
+	"sqsube;":                          '\U00002291',
+	"sqsubset;":                        '\U0000228F',
+	"sqsubseteq;":                      '\U00002291',
+	"sqsup;":                           '\U00002290',
+	"sqsupe;":                          '\U00002292',
+	"sqsupset;":                        '\U00002290',
+	"sqsupseteq;":                      '\U00002292',
+	"squ;":                             '\U000025A1',
+	"square;":                          '\U000025A1',
+	"squarf;":                          '\U000025AA',
+	"squf;":                            '\U000025AA',
+	"srarr;":                           '\U00002192',
+	"sscr;":                            '\U0001D4C8',
+	"ssetmn;":                          '\U00002216',
+	"ssmile;":                          '\U00002323',
+	"sstarf;":                          '\U000022C6',
+	"star;":                            '\U00002606',
+	"starf;":                           '\U00002605',
+	"straightepsilon;":                 '\U000003F5',
+	"straightphi;":                     '\U000003D5',
+	"strns;":                           '\U000000AF',
+	"sub;":                             '\U00002282',
+	"subE;":                            '\U00002AC5',
+	"subdot;":                          '\U00002ABD',
+	"sube;":                            '\U00002286',
+	"subedot;":                         '\U00002AC3',
+	"submult;":                         '\U00002AC1',
+	"subnE;":                           '\U00002ACB',
+	"subne;":                           '\U0000228A',
+	"subplus;":                         '\U00002ABF',
+	"subrarr;":                         '\U00002979',
+	"subset;":                          '\U00002282',
+	"subseteq;":                        '\U00002286',
+	"subseteqq;":                       '\U00002AC5',
+	"subsetneq;":                       '\U0000228A',
+	"subsetneqq;":                      '\U00002ACB',
+	"subsim;":                          '\U00002AC7',
+	"subsub;":                          '\U00002AD5',
+	"subsup;":                          '\U00002AD3',
+	"succ;":                            '\U0000227B',
+	"succapprox;":                      '\U00002AB8',
+	"succcurlyeq;":                     '\U0000227D',
+	"succeq;":                          '\U00002AB0',
+	"succnapprox;":                     '\U00002ABA',
+	"succneqq;":                        '\U00002AB6',
+	"succnsim;":                        '\U000022E9',
+	"succsim;":                         '\U0000227F',
+	"sum;":                             '\U00002211',
+	"sung;":                            '\U0000266A',
+	"sup;":                             '\U00002283',
+	"sup1;":                            '\U000000B9',
+	"sup2;":                            '\U000000B2',
+	"sup3;":                            '\U000000B3',
+	"supE;":                            '\U00002AC6',
+	"supdot;":                          '\U00002ABE',
+	"supdsub;":                         '\U00002AD8',
+	"supe;":                            '\U00002287',
+	"supedot;":                         '\U00002AC4',
+	"suphsol;":                         '\U000027C9',
+	"suphsub;":                         '\U00002AD7',
+	"suplarr;":                         '\U0000297B',
+	"supmult;":                         '\U00002AC2',
+	"supnE;":                           '\U00002ACC',
+	"supne;":                           '\U0000228B',
+	"supplus;":                         '\U00002AC0',
+	"supset;":                          '\U00002283',
+	"supseteq;":                        '\U00002287',
+	"supseteqq;":                       '\U00002AC6',
+	"supsetneq;":                       '\U0000228B',
+	"supsetneqq;":                      '\U00002ACC',
+	"supsim;":                          '\U00002AC8',
+	"supsub;":                          '\U00002AD4',
+	"supsup;":                          '\U00002AD6',
+	"swArr;":                           '\U000021D9',
+	"swarhk;":                          '\U00002926',
+	"swarr;":                           '\U00002199',
+	"swarrow;":                         '\U00002199',
+	"swnwar;":                          '\U0000292A',
+	"szlig;":                           '\U000000DF',
+	"target;":                          '\U00002316',
+	"tau;":                             '\U000003C4',
+	"tbrk;":                            '\U000023B4',
+	"tcaron;":                          '\U00000165',
+	"tcedil;":                          '\U00000163',
+	"tcy;":                             '\U00000442',
+	"tdot;":                            '\U000020DB',
+	"telrec;":                          '\U00002315',
+	"tfr;":                             '\U0001D531',
+	"there4;":                          '\U00002234',
+	"therefore;":                       '\U00002234',
+	"theta;":                           '\U000003B8',
+	"thetasym;":                        '\U000003D1',
+	"thetav;":                          '\U000003D1',
+	"thickapprox;":                     '\U00002248',
+	"thicksim;":                        '\U0000223C',
+	"thinsp;":                          '\U00002009',
+	"thkap;":                           '\U00002248',
+	"thksim;":                          '\U0000223C',
+	"thorn;":                           '\U000000FE',
+	"tilde;":                           '\U000002DC',
+	"times;":                           '\U000000D7',
+	"timesb;":                          '\U000022A0',
+	"timesbar;":                        '\U00002A31',
+	"timesd;":                          '\U00002A30',
+	"tint;":                            '\U0000222D',
+	"toea;":                            '\U00002928',
+	"top;":                             '\U000022A4',
+	"topbot;":                          '\U00002336',
+	"topcir;":                          '\U00002AF1',
+	"topf;":                            '\U0001D565',
+	"topfork;":                         '\U00002ADA',
+	"tosa;":                            '\U00002929',
+	"tprime;":                          '\U00002034',
+	"trade;":                           '\U00002122',
+	"triangle;":                        '\U000025B5',
+	"triangledown;":                    '\U000025BF',
+	"triangleleft;":                    '\U000025C3',
+	"trianglelefteq;":                  '\U000022B4',
+	"triangleq;":                       '\U0000225C',
+	"triangleright;":                   '\U000025B9',
+	"trianglerighteq;":                 '\U000022B5',
+	"tridot;":                          '\U000025EC',
+	"trie;":                            '\U0000225C',
+	"triminus;":                        '\U00002A3A',
+	"triplus;":                         '\U00002A39',
+	"trisb;":                           '\U000029CD',
+	"tritime;":                         '\U00002A3B',
+	"trpezium;":                        '\U000023E2',
+	"tscr;":                            '\U0001D4C9',
+	"tscy;":                            '\U00000446',
+	"tshcy;":                           '\U0000045B',
+	"tstrok;":                          '\U00000167',
+	"twixt;":                           '\U0000226C',
+	"twoheadleftarrow;":                '\U0000219E',
+	"twoheadrightarrow;":               '\U000021A0',
+	"uArr;":                            '\U000021D1',
+	"uHar;":                            '\U00002963',
+	"uacute;":                          '\U000000FA',
+	"uarr;":                            '\U00002191',
+	"ubrcy;":                           '\U0000045E',
+	"ubreve;":                          '\U0000016D',
+	"ucirc;":                           '\U000000FB',
+	"ucy;":                             '\U00000443',
+	"udarr;":                           '\U000021C5',
+	"udblac;":                          '\U00000171',
+	"udhar;":                           '\U0000296E',
+	"ufisht;":                          '\U0000297E',
+	"ufr;":                             '\U0001D532',
+	"ugrave;":                          '\U000000F9',
+	"uharl;":                           '\U000021BF',
+	"uharr;":                           '\U000021BE',
+	"uhblk;":                           '\U00002580',
+	"ulcorn;":                          '\U0000231C',
+	"ulcorner;":                        '\U0000231C',
+	"ulcrop;":                          '\U0000230F',
+	"ultri;":                           '\U000025F8',
+	"umacr;":                           '\U0000016B',
+	"uml;":                             '\U000000A8',
+	"uogon;":                           '\U00000173',
+	"uopf;":                            '\U0001D566',
+	"uparrow;":                         '\U00002191',
+	"updownarrow;":                     '\U00002195',
+	"upharpoonleft;":                   '\U000021BF',
+	"upharpoonright;":                  '\U000021BE',
+	"uplus;":                           '\U0000228E',
+	"upsi;":                            '\U000003C5',
+	"upsih;":                           '\U000003D2',
+	"upsilon;":                         '\U000003C5',
+	"upuparrows;":                      '\U000021C8',
+	"urcorn;":                          '\U0000231D',
+	"urcorner;":                        '\U0000231D',
+	"urcrop;":                          '\U0000230E',
+	"uring;":                           '\U0000016F',
+	"urtri;":                           '\U000025F9',
+	"uscr;":                            '\U0001D4CA',
+	"utdot;":                           '\U000022F0',
+	"utilde;":                          '\U00000169',
+	"utri;":                            '\U000025B5',
+	"utrif;":                           '\U000025B4',
+	"uuarr;":                           '\U000021C8',
+	"uuml;":                            '\U000000FC',
+	"uwangle;":                         '\U000029A7',
+	"vArr;":                            '\U000021D5',
+	"vBar;":                            '\U00002AE8',
+	"vBarv;":                           '\U00002AE9',
+	"vDash;":                           '\U000022A8',
+	"vangrt;":                          '\U0000299C',
+	"varepsilon;":                      '\U000003F5',
+	"varkappa;":                        '\U000003F0',
+	"varnothing;":                      '\U00002205',
+	"varphi;":                          '\U000003D5',
+	"varpi;":                           '\U000003D6',
+	"varpropto;":                       '\U0000221D',
+	"varr;":                            '\U00002195',
+	"varrho;":                          '\U000003F1',
+	"varsigma;":                        '\U000003C2',
+	"vartheta;":                        '\U000003D1',
+	"vartriangleleft;":                 '\U000022B2',
+	"vartriangleright;":                '\U000022B3',
+	"vcy;":                             '\U00000432',
+	"vdash;":                           '\U000022A2',
+	"vee;":                             '\U00002228',
+	"veebar;":                          '\U000022BB',
+	"veeeq;":                           '\U0000225A',
+	"vellip;":                          '\U000022EE',
+	"verbar;":                          '\U0000007C',
+	"vert;":                            '\U0000007C',
+	"vfr;":                             '\U0001D533',
+	"vltri;":                           '\U000022B2',
+	"vopf;":                            '\U0001D567',
+	"vprop;":                           '\U0000221D',
+	"vrtri;":                           '\U000022B3',
+	"vscr;":                            '\U0001D4CB',
+	"vzigzag;":                         '\U0000299A',
+	"wcirc;":                           '\U00000175',
+	"wedbar;":                          '\U00002A5F',
+	"wedge;":                           '\U00002227',
+	"wedgeq;":                          '\U00002259',
+	"weierp;":                          '\U00002118',
+	"wfr;":                             '\U0001D534',
+	"wopf;":                            '\U0001D568',
+	"wp;":                              '\U00002118',
+	"wr;":                              '\U00002240',
+	"wreath;":                          '\U00002240',
+	"wscr;":                            '\U0001D4CC',
+	"xcap;":                            '\U000022C2',
+	"xcirc;":                           '\U000025EF',
+	"xcup;":                            '\U000022C3',
+	"xdtri;":                           '\U000025BD',
+	"xfr;":                             '\U0001D535',
+	"xhArr;":                           '\U000027FA',
+	"xharr;":                           '\U000027F7',
+	"xi;":                              '\U000003BE',
+	"xlArr;":                           '\U000027F8',
+	"xlarr;":                           '\U000027F5',
+	"xmap;":                            '\U000027FC',
+	"xnis;":                            '\U000022FB',
+	"xodot;":                           '\U00002A00',
+	"xopf;":                            '\U0001D569',
+	"xoplus;":                          '\U00002A01',
+	"xotime;":                          '\U00002A02',
+	"xrArr;":                           '\U000027F9',
+	"xrarr;":                           '\U000027F6',
+	"xscr;":                            '\U0001D4CD',
+	"xsqcup;":                          '\U00002A06',
+	"xuplus;":                          '\U00002A04',
+	"xutri;":                           '\U000025B3',
+	"xvee;":                            '\U000022C1',
+	"xwedge;":                          '\U000022C0',
+	"yacute;":                          '\U000000FD',
+	"yacy;":                            '\U0000044F',
+	"ycirc;":                           '\U00000177',
+	"ycy;":                             '\U0000044B',
+	"yen;":                             '\U000000A5',
+	"yfr;":                             '\U0001D536',
+	"yicy;":                            '\U00000457',
+	"yopf;":                            '\U0001D56A',
+	"yscr;":                            '\U0001D4CE',
+	"yucy;":                            '\U0000044E',
+	"yuml;":                            '\U000000FF',
+	"zacute;":                          '\U0000017A',
+	"zcaron;":                          '\U0000017E',
+	"zcy;":                             '\U00000437',
+	"zdot;":                            '\U0000017C',
+	"zeetrf;":                          '\U00002128',
+	"zeta;":                            '\U000003B6',
+	"zfr;":                             '\U0001D537',
+	"zhcy;":                            '\U00000436',
+	"zigrarr;":                         '\U000021DD',
+	"zopf;":                            '\U0001D56B',
+	"zscr;":                            '\U0001D4CF',
+	"zwj;":                             '\U0000200D',
+	"zwnj;":                            '\U0000200C',
+	"AElig":                            '\U000000C6',
+	"AMP":                              '\U00000026',
+	"Aacute":                           '\U000000C1',
+	"Acirc":                            '\U000000C2',
+	"Agrave":                           '\U000000C0',
+	"Aring":                            '\U000000C5',
+	"Atilde":                           '\U000000C3',
+	"Auml":                             '\U000000C4',
+	"COPY":                             '\U000000A9',
+	"Ccedil":                           '\U000000C7',
+	"ETH":                              '\U000000D0',
+	"Eacute":                           '\U000000C9',
+	"Ecirc":                            '\U000000CA',
+	"Egrave":                           '\U000000C8',
+	"Euml":                             '\U000000CB',
+	"GT":                               '\U0000003E',
+	"Iacute":                           '\U000000CD',
+	"Icirc":                            '\U000000CE',
+	"Igrave":                           '\U000000CC',
+	"Iuml":                             '\U000000CF',
+	"LT":                               '\U0000003C',
+	"Ntilde":                           '\U000000D1',
+	"Oacute":                           '\U000000D3',
+	"Ocirc":                            '\U000000D4',
+	"Ograve":                           '\U000000D2',
+	"Oslash":                           '\U000000D8',
+	"Otilde":                           '\U000000D5',
+	"Ouml":                             '\U000000D6',
+	"QUOT":                             '\U00000022',
+	"REG":                              '\U000000AE',
+	"THORN":                            '\U000000DE',
+	"Uacute":                           '\U000000DA',
+	"Ucirc":                            '\U000000DB',
+	"Ugrave":                           '\U000000D9',
+	"Uuml":                             '\U000000DC',
+	"Yacute":                           '\U000000DD',
+	"aacute":                           '\U000000E1',
+	"acirc":                            '\U000000E2',
+	"acute":                            '\U000000B4',
+	"aelig":                            '\U000000E6',
+	"agrave":                           '\U000000E0',
+	"amp":                              '\U00000026',
+	"aring":                            '\U000000E5',
+	"atilde":                           '\U000000E3',
+	"auml":                             '\U000000E4',
+	"brvbar":                           '\U000000A6',
+	"ccedil":                           '\U000000E7',
+	"cedil":                            '\U000000B8',
+	"cent":                             '\U000000A2',
+	"copy":                             '\U000000A9',
+	"curren":                           '\U000000A4',
+	"deg":                              '\U000000B0',
+	"divide":                           '\U000000F7',
+	"eacute":                           '\U000000E9',
+	"ecirc":                            '\U000000EA',
+	"egrave":                           '\U000000E8',
+	"eth":                              '\U000000F0',
+	"euml":                             '\U000000EB',
+	"frac12":                           '\U000000BD',
+	"frac14":                           '\U000000BC',
+	"frac34":                           '\U000000BE',
+	"gt":                               '\U0000003E',
+	"iacute":                           '\U000000ED',
+	"icirc":                            '\U000000EE',
+	"iexcl":                            '\U000000A1',
+	"igrave":                           '\U000000EC',
+	"iquest":                           '\U000000BF',
+	"iuml":                             '\U000000EF',
+	"laquo":                            '\U000000AB',
+	"lt":                               '\U0000003C',
+	"macr":                             '\U000000AF',
+	"micro":                            '\U000000B5',
+	"middot":                           '\U000000B7',
+	"nbsp":                             '\U000000A0',
+	"not":                              '\U000000AC',
+	"ntilde":                           '\U000000F1',
+	"oacute":                           '\U000000F3',
+	"ocirc":                            '\U000000F4',
+	"ograve":                           '\U000000F2',
+	"ordf":                             '\U000000AA',
+	"ordm":                             '\U000000BA',
+	"oslash":                           '\U000000F8',
+	"otilde":                           '\U000000F5',
+	"ouml":                             '\U000000F6',
+	"para":                             '\U000000B6',
+	"plusmn":                           '\U000000B1',
+	"pound":                            '\U000000A3',
+	"quot":                             '\U00000022',
+	"raquo":                            '\U000000BB',
+	"reg":                              '\U000000AE',
+	"sect":                             '\U000000A7',
+	"shy":                              '\U000000AD',
+	"sup1":                             '\U000000B9',
+	"sup2":                             '\U000000B2',
+	"sup3":                             '\U000000B3',
+	"szlig":                            '\U000000DF',
+	"thorn":                            '\U000000FE',
+	"times":                            '\U000000D7',
+	"uacute":                           '\U000000FA',
+	"ucirc":                            '\U000000FB',
+	"ugrave":                           '\U000000F9',
+	"uml":                              '\U000000A8',
+	"uuml":                             '\U000000FC',
+	"yacute":                           '\U000000FD',
+	"yen":                              '\U000000A5',
+	"yuml":                             '\U000000FF',
+}
+
+// HTML entities that are two unicode codepoints.
+var entity2 = map[string][2]rune{
+	// TODO(nigeltao): Handle replacements that are wider than their names.
+	// "nLt;":                     {'\u226A', '\u20D2'},
+	// "nGt;":                     {'\u226B', '\u20D2'},
+	"NotEqualTilde;":           {'\u2242', '\u0338'},
+	"NotGreaterFullEqual;":     {'\u2267', '\u0338'},
+	"NotGreaterGreater;":       {'\u226B', '\u0338'},
+	"NotGreaterSlantEqual;":    {'\u2A7E', '\u0338'},
+	"NotHumpDownHump;":         {'\u224E', '\u0338'},
+	"NotHumpEqual;":            {'\u224F', '\u0338'},
+	"NotLeftTriangleBar;":      {'\u29CF', '\u0338'},
+	"NotLessLess;":             {'\u226A', '\u0338'},
+	"NotLessSlantEqual;":       {'\u2A7D', '\u0338'},
+	"NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
+	"NotNestedLessLess;":       {'\u2AA1', '\u0338'},
+	"NotPrecedesEqual;":        {'\u2AAF', '\u0338'},
+	"NotRightTriangleBar;":     {'\u29D0', '\u0338'},
+	"NotSquareSubset;":         {'\u228F', '\u0338'},
+	"NotSquareSuperset;":       {'\u2290', '\u0338'},
+	"NotSubset;":               {'\u2282', '\u20D2'},
+	"NotSucceedsEqual;":        {'\u2AB0', '\u0338'},
+	"NotSucceedsTilde;":        {'\u227F', '\u0338'},
+	"NotSuperset;":             {'\u2283', '\u20D2'},
+	"ThickSpace;":              {'\u205F', '\u200A'},
+	"acE;":                     {'\u223E', '\u0333'},
+	"bne;":                     {'\u003D', '\u20E5'},
+	"bnequiv;":                 {'\u2261', '\u20E5'},
+	"caps;":                    {'\u2229', '\uFE00'},
+	"cups;":                    {'\u222A', '\uFE00'},
+	"fjlig;":                   {'\u0066', '\u006A'},
+	"gesl;":                    {'\u22DB', '\uFE00'},
+	"gvertneqq;":               {'\u2269', '\uFE00'},
+	"gvnE;":                    {'\u2269', '\uFE00'},
+	"lates;":                   {'\u2AAD', '\uFE00'},
+	"lesg;":                    {'\u22DA', '\uFE00'},
+	"lvertneqq;":               {'\u2268', '\uFE00'},
+	"lvnE;":                    {'\u2268', '\uFE00'},
+	"nGg;":                     {'\u22D9', '\u0338'},
+	"nGtv;":                    {'\u226B', '\u0338'},
+	"nLl;":                     {'\u22D8', '\u0338'},
+	"nLtv;":                    {'\u226A', '\u0338'},
+	"nang;":                    {'\u2220', '\u20D2'},
+	"napE;":                    {'\u2A70', '\u0338'},
+	"napid;":                   {'\u224B', '\u0338'},
+	"nbump;":                   {'\u224E', '\u0338'},
+	"nbumpe;":                  {'\u224F', '\u0338'},
+	"ncongdot;":                {'\u2A6D', '\u0338'},
+	"nedot;":                   {'\u2250', '\u0338'},
+	"nesim;":                   {'\u2242', '\u0338'},
+	"ngE;":                     {'\u2267', '\u0338'},
+	"ngeqq;":                   {'\u2267', '\u0338'},
+	"ngeqslant;":               {'\u2A7E', '\u0338'},
+	"nges;":                    {'\u2A7E', '\u0338'},
+	"nlE;":                     {'\u2266', '\u0338'},
+	"nleqq;":                   {'\u2266', '\u0338'},
+	"nleqslant;":               {'\u2A7D', '\u0338'},
+	"nles;":                    {'\u2A7D', '\u0338'},
+	"notinE;":                  {'\u22F9', '\u0338'},
+	"notindot;":                {'\u22F5', '\u0338'},
+	"nparsl;":                  {'\u2AFD', '\u20E5'},
+	"npart;":                   {'\u2202', '\u0338'},
+	"npre;":                    {'\u2AAF', '\u0338'},
+	"npreceq;":                 {'\u2AAF', '\u0338'},
+	"nrarrc;":                  {'\u2933', '\u0338'},
+	"nrarrw;":                  {'\u219D', '\u0338'},
+	"nsce;":                    {'\u2AB0', '\u0338'},
+	"nsubE;":                   {'\u2AC5', '\u0338'},
+	"nsubset;":                 {'\u2282', '\u20D2'},
+	"nsubseteqq;":              {'\u2AC5', '\u0338'},
+	"nsucceq;":                 {'\u2AB0', '\u0338'},
+	"nsupE;":                   {'\u2AC6', '\u0338'},
+	"nsupset;":                 {'\u2283', '\u20D2'},
+	"nsupseteqq;":              {'\u2AC6', '\u0338'},
+	"nvap;":                    {'\u224D', '\u20D2'},
+	"nvge;":                    {'\u2265', '\u20D2'},
+	"nvgt;":                    {'\u003E', '\u20D2'},
+	"nvle;":                    {'\u2264', '\u20D2'},
+	"nvlt;":                    {'\u003C', '\u20D2'},
+	"nvltrie;":                 {'\u22B4', '\u20D2'},
+	"nvrtrie;":                 {'\u22B5', '\u20D2'},
+	"nvsim;":                   {'\u223C', '\u20D2'},
+	"race;":                    {'\u223D', '\u0331'},
+	"smtes;":                   {'\u2AAC', '\uFE00'},
+	"sqcaps;":                  {'\u2293', '\uFE00'},
+	"sqcups;":                  {'\u2294', '\uFE00'},
+	"varsubsetneq;":            {'\u228A', '\uFE00'},
+	"varsubsetneqq;":           {'\u2ACB', '\uFE00'},
+	"varsupsetneq;":            {'\u228B', '\uFE00'},
+	"varsupsetneqq;":           {'\u2ACC', '\uFE00'},
+	"vnsub;":                   {'\u2282', '\u20D2'},
+	"vnsup;":                   {'\u2283', '\u20D2'},
+	"vsubnE;":                  {'\u2ACB', '\uFE00'},
+	"vsubne;":                  {'\u228A', '\uFE00'},
+	"vsupnE;":                  {'\u2ACC', '\uFE00'},
+	"vsupne;":                  {'\u228B', '\uFE00'},
+}
diff --git a/src/pkg/exp/html/entity_test.go b/src/pkg/exp/html/entity_test.go
new file mode 100644
index 0000000..b53f866
--- /dev/null
+++ b/src/pkg/exp/html/entity_test.go
@@ -0,0 +1,29 @@
+// Copyright 2010 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 html
+
+import (
+	"testing"
+	"unicode/utf8"
+)
+
+func TestEntityLength(t *testing.T) {
+	// We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
+	// The +1 comes from the leading "&". This property implies that the length of
+	// unescaped text is <= the length of escaped text.
+	for k, v := range entity {
+		if 1+len(k) < utf8.RuneLen(v) {
+			t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v))
+		}
+		if len(k) > longestEntityWithoutSemicolon && k[len(k)-1] != ';' {
+			t.Errorf("entity name %s is %d characters, but longestEntityWithoutSemicolon=%d", k, len(k), longestEntityWithoutSemicolon)
+		}
+	}
+	for k, v := range entity2 {
+		if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) {
+			t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1]))
+		}
+	}
+}
diff --git a/src/pkg/exp/html/escape.go b/src/pkg/exp/html/escape.go
new file mode 100644
index 0000000..42be865
--- /dev/null
+++ b/src/pkg/exp/html/escape.go
@@ -0,0 +1,253 @@
+// Copyright 2010 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 html
+
+import (
+	"bytes"
+	"strings"
+	"unicode/utf8"
+)
+
+// These replacements permit compatibility with old numeric entities that 
+// assumed Windows-1252 encoding.
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
+var replacementTable = [...]rune{
+	'\u20AC', // First entry is what 0x80 should be replaced with.
+	'\u0081',
+	'\u201A',
+	'\u0192',
+	'\u201E',
+	'\u2026',
+	'\u2020',
+	'\u2021',
+	'\u02C6',
+	'\u2030',
+	'\u0160',
+	'\u2039',
+	'\u0152',
+	'\u008D',
+	'\u017D',
+	'\u008F',
+	'\u0090',
+	'\u2018',
+	'\u2019',
+	'\u201C',
+	'\u201D',
+	'\u2022',
+	'\u2013',
+	'\u2014',
+	'\u02DC',
+	'\u2122',
+	'\u0161',
+	'\u203A',
+	'\u0153',
+	'\u009D',
+	'\u017E',
+	'\u0178', // Last entry is 0x9F.
+	// 0x00->'\uFFFD' is handled programmatically. 
+	// 0x0D->'\u000D' is a no-op.
+}
+
+// unescapeEntity reads an entity like "<" from b[src:] and writes the
+// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
+// Precondition: b[src] == '&' && dst <= src.
+// attribute should be true if parsing an attribute value.
+func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
+	// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
+
+	// i starts at 1 because we already know that s[0] == '&'.
+	i, s := 1, b[src:]
+
+	if len(s) <= 1 {
+		b[dst] = b[src]
+		return dst + 1, src + 1
+	}
+
+	if s[i] == '#' {
+		if len(s) <= 3 { // We need to have at least "&#.".
+			b[dst] = b[src]
+			return dst + 1, src + 1
+		}
+		i++
+		c := s[i]
+		hex := false
+		if c == 'x' || c == 'X' {
+			hex = true
+			i++
+		}
+
+		x := '\x00'
+		for i < len(s) {
+			c = s[i]
+			i++
+			if hex {
+				if '0' <= c && c <= '9' {
+					x = 16*x + rune(c) - '0'
+					continue
+				} else if 'a' <= c && c <= 'f' {
+					x = 16*x + rune(c) - 'a' + 10
+					continue
+				} else if 'A' <= c && c <= 'F' {
+					x = 16*x + rune(c) - 'A' + 10
+					continue
+				}
+			} else if '0' <= c && c <= '9' {
+				x = 10*x + rune(c) - '0'
+				continue
+			}
+			if c != ';' {
+				i--
+			}
+			break
+		}
+
+		if i <= 3 { // No characters matched.
+			b[dst] = b[src]
+			return dst + 1, src + 1
+		}
+
+		if 0x80 <= x && x <= 0x9F {
+			// Replace characters from Windows-1252 with UTF-8 equivalents.
+			x = replacementTable[x-0x80]
+		} else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
+			// Replace invalid characters with the replacement character.
+			x = '\uFFFD'
+		}
+
+		return dst + utf8.EncodeRune(b[dst:], x), src + i
+	}
+
+	// Consume the maximum number of characters possible, with the
+	// consumed characters matching one of the named references.
+
+	for i < len(s) {
+		c := s[i]
+		i++
+		// Lower-cased characters are more common in entities, so we check for them first.
+		if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
+			continue
+		}
+		if c != ';' {
+			i--
+		}
+		break
+	}
+
+	entityName := string(s[1:i])
+	if entityName == "" {
+		// No-op.
+	} else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
+		// No-op.
+	} else if x := entity[entityName]; x != 0 {
+		return dst + utf8.EncodeRune(b[dst:], x), src + i
+	} else if x := entity2[entityName]; x[0] != 0 {
+		dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
+		return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
+	} else if !attribute {
+		maxLen := len(entityName) - 1
+		if maxLen > longestEntityWithoutSemicolon {
+			maxLen = longestEntityWithoutSemicolon
+		}
+		for j := maxLen; j > 1; j-- {
+			if x := entity[entityName[:j]]; x != 0 {
+				return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
+			}
+		}
+	}
+
+	dst1, src1 = dst+i, src+i
+	copy(b[dst:dst1], b[src:src1])
+	return dst1, src1
+}
+
+// unescape unescapes b's entities in-place, so that "a<b" becomes "a<b".
+func unescape(b []byte) []byte {
+	for i, c := range b {
+		if c == '&' {
+			dst, src := unescapeEntity(b, i, i, false)
+			for src < len(b) {
+				c := b[src]
+				if c == '&' {
+					dst, src = unescapeEntity(b, dst, src, false)
+				} else {
+					b[dst] = c
+					dst, src = dst+1, src+1
+				}
+			}
+			return b[0:dst]
+		}
+	}
+	return b
+}
+
+// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
+func lower(b []byte) []byte {
+	for i, c := range b {
+		if 'A' <= c && c <= 'Z' {
+			b[i] = c + 'a' - 'A'
+		}
+	}
+	return b
+}
+
+const escapedChars = `&'<>"`
+
+func escape(w writer, s string) error {
+	i := strings.IndexAny(s, escapedChars)
+	for i != -1 {
+		if _, err := w.WriteString(s[:i]); err != nil {
+			return err
+		}
+		var esc string
+		switch s[i] {
+		case '&':
+			esc = "&"
+		case '\'':
+			esc = "'"
+		case '<':
+			esc = "<"
+		case '>':
+			esc = ">"
+		case '"':
+			esc = """
+		default:
+			panic("unrecognized escape character")
+		}
+		s = s[i+1:]
+		if _, err := w.WriteString(esc); err != nil {
+			return err
+		}
+		i = strings.IndexAny(s, escapedChars)
+	}
+	_, err := w.WriteString(s)
+	return err
+}
+
+// EscapeString escapes special characters like "<" to become "<". It
+// escapes only five such characters: amp, apos, lt, gt and quot.
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func EscapeString(s string) string {
+	if strings.IndexAny(s, escapedChars) == -1 {
+		return s
+	}
+	buf := bytes.NewBuffer(nil)
+	escape(buf, s)
+	return buf.String()
+}
+
+// UnescapeString unescapes entities like "<" to become "<". It unescapes a
+// larger range of entities than EscapeString escapes. For example, "á"
+// unescapes to "á", as does "á" and "&xE1;".
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func UnescapeString(s string) string {
+	for _, c := range s {
+		if c == '&' {
+			return string(unescape([]byte(s)))
+		}
+	}
+	return s
+}
diff --git a/src/pkg/exp/html/foreign.go b/src/pkg/exp/html/foreign.go
new file mode 100644
index 0000000..3ba81ce
--- /dev/null
+++ b/src/pkg/exp/html/foreign.go
@@ -0,0 +1,132 @@
+// Copyright 2011 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 html
+
+import (
+	"strings"
+)
+
+func adjustForeignAttributes(aa []Attribute) {
+	for i, a := range aa {
+		if a.Key == "" || a.Key[0] != 'x' {
+			continue
+		}
+		switch a.Key {
+		case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show",
+			"xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink":
+			j := strings.Index(a.Key, ":")
+			aa[i].Namespace = a.Key[:j]
+			aa[i].Key = a.Key[j+1:]
+		}
+	}
+}
+
+func htmlIntegrationPoint(n *Node) bool {
+	if n.Type != ElementNode {
+		return false
+	}
+	switch n.Namespace {
+	case "math":
+		// TODO: annotation-xml elements whose start tags have "text/html" or
+		// "application/xhtml+xml" encodings.
+	case "svg":
+		switch n.Data {
+		case "desc", "foreignObject", "title":
+			return true
+		}
+	}
+	return false
+}
+
+// Section 12.2.5.5.
+var breakout = map[string]bool{
+	"b":          true,
+	"big":        true,
+	"blockquote": true,
+	"body":       true,
+	"br":         true,
+	"center":     true,
+	"code":       true,
+	"dd":         true,
+	"div":        true,
+	"dl":         true,
+	"dt":         true,
+	"em":         true,
+	"embed":      true,
+	"font":       true,
+	"h1":         true,
+	"h2":         true,
+	"h3":         true,
+	"h4":         true,
+	"h5":         true,
+	"h6":         true,
+	"head":       true,
+	"hr":         true,
+	"i":          true,
+	"img":        true,
+	"li":         true,
+	"listing":    true,
+	"menu":       true,
+	"meta":       true,
+	"nobr":       true,
+	"ol":         true,
+	"p":          true,
+	"pre":        true,
+	"ruby":       true,
+	"s":          true,
+	"small":      true,
+	"span":       true,
+	"strong":     true,
+	"strike":     true,
+	"sub":        true,
+	"sup":        true,
+	"table":      true,
+	"tt":         true,
+	"u":          true,
+	"ul":         true,
+	"var":        true,
+}
+
+// Section 12.2.5.5.
+var svgTagNameAdjustments = map[string]string{
+	"altglyph":            "altGlyph",
+	"altglyphdef":         "altGlyphDef",
+	"altglyphitem":        "altGlyphItem",
+	"animatecolor":        "animateColor",
+	"animatemotion":       "animateMotion",
+	"animatetransform":    "animateTransform",
+	"clippath":            "clipPath",
+	"feblend":             "feBlend",
+	"fecolormatrix":       "feColorMatrix",
+	"fecomponenttransfer": "feComponentTransfer",
+	"fecomposite":         "feComposite",
+	"feconvolvematrix":    "feConvolveMatrix",
+	"fediffuselighting":   "feDiffuseLighting",
+	"fedisplacementmap":   "feDisplacementMap",
+	"fedistantlight":      "feDistantLight",
+	"feflood":             "feFlood",
+	"fefunca":             "feFuncA",
+	"fefuncb":             "feFuncB",
+	"fefuncg":             "feFuncG",
+	"fefuncr":             "feFuncR",
+	"fegaussianblur":      "feGaussianBlur",
+	"feimage":             "feImage",
+	"femerge":             "feMerge",
+	"femergenode":         "feMergeNode",
+	"femorphology":        "feMorphology",
+	"feoffset":            "feOffset",
+	"fepointlight":        "fePointLight",
+	"fespecularlighting":  "feSpecularLighting",
+	"fespotlight":         "feSpotLight",
+	"fetile":              "feTile",
+	"feturbulence":        "feTurbulence",
+	"foreignobject":       "foreignObject",
+	"glyphref":            "glyphRef",
+	"lineargradient":      "linearGradient",
+	"radialgradient":      "radialGradient",
+	"textpath":            "textPath",
+}
+
+// TODO: add look-up tables for MathML and SVG attribute adjustments.
diff --git a/src/pkg/exp/html/node.go b/src/pkg/exp/html/node.go
new file mode 100644
index 0000000..83f1730
--- /dev/null
+++ b/src/pkg/exp/html/node.go
@@ -0,0 +1,154 @@
+// Copyright 2011 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 html
+
+// A NodeType is the type of a Node.
+type NodeType int
+
+const (
+	ErrorNode NodeType = iota
+	TextNode
+	DocumentNode
+	ElementNode
+	CommentNode
+	DoctypeNode
+	scopeMarkerNode
+)
+
+// Section 12.2.3.3 says "scope markers are inserted when entering applet
+// elements, buttons, object elements, marquees, table cells, and table
+// captions, and are used to prevent formatting from 'leaking'".
+var scopeMarker = Node{Type: scopeMarkerNode}
+
+// A Node consists of a NodeType and some Data (tag name for element nodes,
+// content for text) and are part of a tree of Nodes. Element nodes may also
+// have a Namespace and contain a slice of Attributes. Data is unescaped, so
+// that it looks like "a<b" rather than "a<b".
+//
+// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
+// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
+// "svg" is short for "http://www.w3.org/2000/svg".
+type Node struct {
+	Parent    *Node
+	Child     []*Node
+	Type      NodeType
+	Data      string
+	Namespace string
+	Attr      []Attribute
+}
+
+// Add adds a node as a child of n.
+// It will panic if the child's parent is not nil.
+func (n *Node) Add(child *Node) {
+	if child.Parent != nil {
+		panic("html: Node.Add called for a child Node that already has a parent")
+	}
+	child.Parent = n
+	n.Child = append(n.Child, child)
+}
+
+// Remove removes a node as a child of n.
+// It will panic if the child's parent is not n.
+func (n *Node) Remove(child *Node) {
+	if child.Parent == n {
+		child.Parent = nil
+		for i, m := range n.Child {
+			if m == child {
+				copy(n.Child[i:], n.Child[i+1:])
+				j := len(n.Child) - 1
+				n.Child[j] = nil
+				n.Child = n.Child[:j]
+				return
+			}
+		}
+	}
+	panic("html: Node.Remove called for a non-child Node")
+}
+
+// reparentChildren reparents all of src's child nodes to dst.
+func reparentChildren(dst, src *Node) {
+	for _, n := range src.Child {
+		if n.Parent != src {
+			panic("html: nodes have an inconsistent parent/child relationship")
+		}
+		n.Parent = dst
+	}
+	dst.Child = append(dst.Child, src.Child...)
+	src.Child = nil
+}
+
+// clone returns a new node with the same type, data and attributes.
+// The clone has no parent and no children.
+func (n *Node) clone() *Node {
+	m := &Node{
+		Type: n.Type,
+		Data: n.Data,
+		Attr: make([]Attribute, len(n.Attr)),
+	}
+	copy(m.Attr, n.Attr)
+	return m
+}
+
+// nodeStack is a stack of nodes.
+type nodeStack []*Node
+
+// pop pops the stack. It will panic if s is empty.
+func (s *nodeStack) pop() *Node {
+	i := len(*s)
+	n := (*s)[i-1]
+	*s = (*s)[:i-1]
+	return n
+}
+
+// top returns the most recently pushed node, or nil if s is empty.
+func (s *nodeStack) top() *Node {
+	if i := len(*s); i > 0 {
+		return (*s)[i-1]
+	}
+	return nil
+}
+
+// index returns the index of the top-most occurence of n in the stack, or -1
+// if n is not present.
+func (s *nodeStack) index(n *Node) int {
+	for i := len(*s) - 1; i >= 0; i-- {
+		if (*s)[i] == n {
+			return i
+		}
+	}
+	return -1
+}
+
+// insert inserts a node at the given index.
+func (s *nodeStack) insert(i int, n *Node) {
+	(*s) = append(*s, nil)
+	copy((*s)[i+1:], (*s)[i:])
+	(*s)[i] = n
+}
+
+// remove removes a node from the stack. It is a no-op if n is not present.
+func (s *nodeStack) remove(n *Node) {
+	i := s.index(n)
+	if i == -1 {
+		return
+	}
+	copy((*s)[i:], (*s)[i+1:])
+	j := len(*s) - 1
+	(*s)[j] = nil
+	*s = (*s)[:j]
+}
+
+// TODO(nigeltao): forTag no longer used. Should it be deleted?
+
+// forTag returns the top-most element node with the given tag.
+func (s *nodeStack) forTag(tag string) *Node {
+	for i := len(*s) - 1; i >= 0; i-- {
+		n := (*s)[i]
+		if n.Type == ElementNode && n.Data == tag {
+			return n
+		}
+	}
+	return nil
+}
diff --git a/src/pkg/exp/html/parse.go b/src/pkg/exp/html/parse.go
new file mode 100644
index 0000000..04f4ae7
--- /dev/null
+++ b/src/pkg/exp/html/parse.go
@@ -0,0 +1,1869 @@
+// Copyright 2010 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 html
+
+import (
+	"io"
+	"strings"
+)
+
+// A parser implements the HTML5 parsing algorithm:
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#tree-construction
+type parser struct {
+	// tokenizer provides the tokens for the parser.
+	tokenizer *Tokenizer
+	// tok is the most recently read token.
+	tok Token
+	// Self-closing tags like <hr/> are re-interpreted as a two-token sequence:
+	// <hr> followed by </hr>. hasSelfClosingToken is true if we have just read
+	// the synthetic start tag and the next one due is the matching end tag.
+	hasSelfClosingToken bool
+	// doc is the document root element.
+	doc *Node
+	// The stack of open elements (section 12.2.3.2) and active formatting
+	// elements (section 12.2.3.3).
+	oe, afe nodeStack
+	// Element pointers (section 12.2.3.4).
+	head, form *Node
+	// Other parsing state flags (section 12.2.3.5).
+	scripting, framesetOK bool
+	// im is the current insertion mode.
+	im insertionMode
+	// originalIM is the insertion mode to go back to after completing a text
+	// or inTableText insertion mode.
+	originalIM insertionMode
+	// fosterParenting is whether new elements should be inserted according to
+	// the foster parenting rules (section 12.2.5.3).
+	fosterParenting bool
+	// quirks is whether the parser is operating in "quirks mode."
+	quirks bool
+	// context is the context element when parsing an HTML fragment
+	// (section 12.4).
+	context *Node
+}
+
+func (p *parser) top() *Node {
+	if n := p.oe.top(); n != nil {
+		return n
+	}
+	return p.doc
+}
+
+// Stop tags for use in popUntil. These come from section 12.2.3.2.
+var (
+	defaultScopeStopTags = map[string][]string{
+		"":     {"applet", "caption", "html", "table", "td", "th", "marquee", "object"},
+		"math": {"annotation-xml", "mi", "mn", "mo", "ms", "mtext"},
+		"svg":  {"desc", "foreignObject", "title"},
+	}
+)
+
+type scope int
+
+const (
+	defaultScope scope = iota
+	listItemScope
+	buttonScope
+	tableScope
+	tableRowScope
+)
+
+// popUntil pops the stack of open elements at the highest element whose tag
+// is in matchTags, provided there is no higher element in the scope's stop
+// tags (as defined in section 12.2.3.2). It returns whether or not there was
+// such an element. If there was not, popUntil leaves the stack unchanged.
+//
+// For example, the set of stop tags for table scope is: "html", "table". If
+// the stack was:
+// ["html", "body", "font", "table", "b", "i", "u"]
+// then popUntil(tableScope, "font") would return false, but
+// popUntil(tableScope, "i") would return true and the stack would become:
+// ["html", "body", "font", "table", "b"]
+//
+// If an element's tag is in both the stop tags and matchTags, then the stack
+// will be popped and the function returns true (provided, of course, there was
+// no higher element in the stack that was also in the stop tags). For example,
+// popUntil(tableScope, "table") returns true and leaves:
+// ["html", "body", "font"]
+func (p *parser) popUntil(s scope, matchTags ...string) bool {
+	if i := p.indexOfElementInScope(s, matchTags...); i != -1 {
+		p.oe = p.oe[:i]
+		return true
+	}
+	return false
+}
+
+// indexOfElementInScope returns the index in p.oe of the highest element whose
+// tag is in matchTags that is in scope. If no matching element is in scope, it
+// returns -1.
+func (p *parser) indexOfElementInScope(s scope, matchTags ...string) int {
+	for i := len(p.oe) - 1; i >= 0; i-- {
+		tag := p.oe[i].Data
+		if p.oe[i].Namespace == "" {
+			for _, t := range matchTags {
+				if t == tag {
+					return i
+				}
+			}
+			switch s {
+			case defaultScope:
+				// No-op.
+			case listItemScope:
+				if tag == "ol" || tag == "ul" {
+					return -1
+				}
+			case buttonScope:
+				if tag == "button" {
+					return -1
+				}
+			case tableScope:
+				if tag == "html" || tag == "table" {
+					return -1
+				}
+			default:
+				panic("unreachable")
+			}
+		}
+		switch s {
+		case defaultScope, listItemScope, buttonScope:
+			for _, t := range defaultScopeStopTags[p.oe[i].Namespace] {
+				if t == tag {
+					return -1
+				}
+			}
+		}
+	}
+	return -1
+}
+
+// elementInScope is like popUntil, except that it doesn't modify the stack of
+// open elements.
+func (p *parser) elementInScope(s scope, matchTags ...string) bool {
+	return p.indexOfElementInScope(s, matchTags...) != -1
+}
+
+// clearStackToContext pops elements off the stack of open elements until a
+// scope-defined element is found.
+func (p *parser) clearStackToContext(s scope) {
+	for i := len(p.oe) - 1; i >= 0; i-- {
+		tag := p.oe[i].Data
+		switch s {
+		case tableScope:
+			if tag == "html" || tag == "table" {
+				p.oe = p.oe[:i+1]
+				return
+			}
+		case tableRowScope:
+			if tag == "html" || tag == "tr" {
+				p.oe = p.oe[:i+1]
+				return
+			}
+		default:
+			panic("unreachable")
+		}
+	}
+}
+
+// addChild adds a child node n to the top element, and pushes n onto the stack
+// of open elements if it is an element node.
+func (p *parser) addChild(n *Node) {
+	if p.fosterParenting {
+		p.fosterParent(n)
+	} else {
+		p.top().Add(n)
+	}
+
+	if n.Type == ElementNode {
+		p.oe = append(p.oe, n)
+	}
+}
+
+// fosterParent adds a child node according to the foster parenting rules.
+// Section 12.2.5.3, "foster parenting".
+func (p *parser) fosterParent(n *Node) {
+	p.fosterParenting = false
+	var table, parent *Node
+	var i int
+	for i = len(p.oe) - 1; i >= 0; i-- {
+		if p.oe[i].Data == "table" {
+			table = p.oe[i]
+			break
+		}
+	}
+
+	if table == nil {
+		// The foster parent is the html element.
+		parent = p.oe[0]
+	} else {
+		parent = table.Parent
+	}
+	if parent == nil {
+		parent = p.oe[i-1]
+	}
+
+	var child *Node
+	for i, child = range parent.Child {
+		if child == table {
+			break
+		}
+	}
+
+	if i > 0 && parent.Child[i-1].Type == TextNode && n.Type == TextNode {
+		parent.Child[i-1].Data += n.Data
+		return
+	}
+
+	if i == len(parent.Child) {
+		parent.Add(n)
+	} else {
+		// Insert n into parent.Child at index i.
+		parent.Child = append(parent.Child[:i+1], parent.Child[i:]...)
+		parent.Child[i] = n
+		n.Parent = parent
+	}
+}
+
+// addText adds text to the preceding node if it is a text node, or else it
+// calls addChild with a new text node.
+func (p *parser) addText(text string) {
+	// TODO: distinguish whitespace text from others.
+	t := p.top()
+	if i := len(t.Child); i > 0 && t.Child[i-1].Type == TextNode {
+		t.Child[i-1].Data += text
+		return
+	}
+	p.addChild(&Node{
+		Type: TextNode,
+		Data: text,
+	})
+}
+
+// addElement calls addChild with an element node.
+func (p *parser) addElement(tag string, attr []Attribute) {
+	p.addChild(&Node{
+		Type: ElementNode,
+		Data: tag,
+		Attr: attr,
+	})
+}
+
+// Section 12.2.3.3.
+func (p *parser) addFormattingElement(tag string, attr []Attribute) {
+	p.addElement(tag, attr)
+	p.afe = append(p.afe, p.top())
+	// TODO.
+}
+
+// Section 12.2.3.3.
+func (p *parser) clearActiveFormattingElements() {
+	for {
+		n := p.afe.pop()
+		if len(p.afe) == 0 || n.Type == scopeMarkerNode {
+			return
+		}
+	}
+}
+
+// Section 12.2.3.3.
+func (p *parser) reconstructActiveFormattingElements() {
+	n := p.afe.top()
+	if n == nil {
+		return
+	}
+	if n.Type == scopeMarkerNode || p.oe.index(n) != -1 {
+		return
+	}
+	i := len(p.afe) - 1
+	for n.Type != scopeMarkerNode && p.oe.index(n) == -1 {
+		if i == 0 {
+			i = -1
+			break
+		}
+		i--
+		n = p.afe[i]
+	}
+	for {
+		i++
+		clone := p.afe[i].clone()
+		p.addChild(clone)
+		p.afe[i] = clone
+		if i == len(p.afe)-1 {
+			break
+		}
+	}
+}
+
+// read reads the next token. This is usually from the tokenizer, but it may
+// be the synthesized end tag implied by a self-closing tag.
+func (p *parser) read() error {
+	if p.hasSelfClosingToken {
+		p.hasSelfClosingToken = false
+		p.tok.Type = EndTagToken
+		p.tok.Attr = nil
+		return nil
+	}
+	p.tokenizer.Next()
+	p.tok = p.tokenizer.Token()
+	switch p.tok.Type {
+	case ErrorToken:
+		return p.tokenizer.Err()
+	case SelfClosingTagToken:
+		p.hasSelfClosingToken = true
+		p.tok.Type = StartTagToken
+	}
+	return nil
+}
+
+// Section 12.2.4.
+func (p *parser) acknowledgeSelfClosingTag() {
+	p.hasSelfClosingToken = false
+}
+
+// An insertion mode (section 12.2.3.1) is the state transition function from
+// a particular state in the HTML5 parser's state machine. It updates the
+// parser's fields depending on parser.tok (where ErrorToken means EOF).
+// It returns whether the token was consumed.
+type insertionMode func(*parser) bool
+
+// setOriginalIM sets the insertion mode to return to after completing a text or
+// inTableText insertion mode.
+// Section 12.2.3.1, "using the rules for".
+func (p *parser) setOriginalIM() {
+	if p.originalIM != nil {
+		panic("html: bad parser state: originalIM was set twice")
+	}
+	p.originalIM = p.im
+}
+
+// Section 12.2.3.1, "reset the insertion mode".
+func (p *parser) resetInsertionMode() {
+	for i := len(p.oe) - 1; i >= 0; i-- {
+		n := p.oe[i]
+		if i == 0 && p.context != nil {
+			n = p.context
+		}
+
+		switch n.Data {
+		case "select":
+			p.im = inSelectIM
+		case "td", "th":
+			p.im = inCellIM
+		case "tr":
+			p.im = inRowIM
+		case "tbody", "thead", "tfoot":
+			p.im = inTableBodyIM
+		case "caption":
+			p.im = inCaptionIM
+		case "colgroup":
+			p.im = inColumnGroupIM
+		case "table":
+			p.im = inTableIM
+		case "head":
+			p.im = inBodyIM
+		case "body":
+			p.im = inBodyIM
+		case "frameset":
+			p.im = inFramesetIM
+		case "html":
+			p.im = beforeHeadIM
+		default:
+			continue
+		}
+		return
+	}
+	p.im = inBodyIM
+}
+
+const whitespace = " \t\r\n\f"
+
+// Section 12.2.5.4.1.
+func initialIM(p *parser) bool {
+	switch p.tok.Type {
+	case TextToken:
+		p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+		if len(p.tok.Data) == 0 {
+			// It was all whitespace, so ignore it.
+			return true
+		}
+	case CommentToken:
+		p.doc.Add(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	case DoctypeToken:
+		n, quirks := parseDoctype(p.tok.Data)
+		p.doc.Add(n)
+		p.quirks = quirks
+		p.im = beforeHTMLIM
+		return true
+	}
+	p.quirks = true
+	p.im = beforeHTMLIM
+	return false
+}
+
+// Section 12.2.5.4.2.
+func beforeHTMLIM(p *parser) bool {
+	switch p.tok.Type {
+	case TextToken:
+		p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+		if len(p.tok.Data) == 0 {
+			// It was all whitespace, so ignore it.
+			return true
+		}
+	case StartTagToken:
+		if p.tok.Data == "html" {
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.im = beforeHeadIM
+			return true
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "head", "body", "html", "br":
+			// Drop down to creating an implied <html> tag.
+		default:
+			// Ignore the token.
+			return true
+		}
+	case CommentToken:
+		p.doc.Add(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	// Create an implied <html> tag.
+	p.addElement("html", nil)
+	p.im = beforeHeadIM
+	return false
+}
+
+// Section 12.2.5.4.3.
+func beforeHeadIM(p *parser) bool {
+	var (
+		add     bool
+		attr    []Attribute
+		implied bool
+	)
+	switch p.tok.Type {
+	case ErrorToken:
+		implied = true
+	case TextToken:
+		p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+		if len(p.tok.Data) == 0 {
+			// It was all whitespace, so ignore it.
+			return true
+		}
+		implied = true
+	case StartTagToken:
+		switch p.tok.Data {
+		case "head":
+			add = true
+			attr = p.tok.Attr
+		case "html":
+			return inBodyIM(p)
+		default:
+			implied = true
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "head", "body", "html", "br":
+			implied = true
+		default:
+			// Ignore the token.
+		}
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	if add || implied {
+		p.addElement("head", attr)
+		p.head = p.top()
+	}
+	p.im = inHeadIM
+	return !implied
+}
+
+// Section 12.2.5.4.4.
+func inHeadIM(p *parser) bool {
+	var (
+		pop     bool
+		implied bool
+	)
+	switch p.tok.Type {
+	case ErrorToken:
+		implied = true
+	case TextToken:
+		s := strings.TrimLeft(p.tok.Data, whitespace)
+		if len(s) < len(p.tok.Data) {
+			// Add the initial whitespace to the current node.
+			p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+			if s == "" {
+				return true
+			}
+			p.tok.Data = s
+		}
+		implied = true
+	case StartTagToken:
+		switch p.tok.Data {
+		case "html":
+			return inBodyIM(p)
+		case "base", "basefont", "bgsound", "command", "link", "meta":
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.oe.pop()
+			p.acknowledgeSelfClosingTag()
+		case "script", "title", "noscript", "noframes", "style":
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.setOriginalIM()
+			p.im = textIM
+			return true
+		case "head":
+			// Ignore the token.
+			return true
+		default:
+			implied = true
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "head":
+			pop = true
+		case "body", "html", "br":
+			implied = true
+		default:
+			// Ignore the token.
+			return true
+		}
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	if pop || implied {
+		n := p.oe.pop()
+		if n.Data != "head" {
+			panic("html: bad parser state: <head> element not found, in the in-head insertion mode")
+		}
+		p.im = afterHeadIM
+		return !implied
+	}
+	return true
+}
+
+// Section 12.2.5.4.6.
+func afterHeadIM(p *parser) bool {
+	var (
+		add        bool
+		attr       []Attribute
+		framesetOK bool
+		implied    bool
+	)
+	switch p.tok.Type {
+	case ErrorToken:
+		implied = true
+		framesetOK = true
+	case TextToken:
+		s := strings.TrimLeft(p.tok.Data, whitespace)
+		if len(s) < len(p.tok.Data) {
+			// Add the initial whitespace to the current node.
+			p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+			if s == "" {
+				return true
+			}
+			p.tok.Data = s
+		}
+		implied = true
+		framesetOK = true
+	case StartTagToken:
+		switch p.tok.Data {
+		case "html":
+			// TODO.
+		case "body":
+			add = true
+			attr = p.tok.Attr
+			framesetOK = false
+		case "frameset":
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.im = inFramesetIM
+			return true
+		case "base", "basefont", "bgsound", "link", "meta", "noframes", "script", "style", "title":
+			p.oe = append(p.oe, p.head)
+			defer p.oe.pop()
+			return inHeadIM(p)
+		case "head":
+			// Ignore the token.
+			return true
+		default:
+			implied = true
+			framesetOK = true
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "body", "html", "br":
+			implied = true
+			framesetOK = true
+		default:
+			// Ignore the token.
+			return true
+		}
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	if add || implied {
+		p.addElement("body", attr)
+		p.framesetOK = framesetOK
+	}
+	p.im = inBodyIM
+	return !implied
+}
+
+// copyAttributes copies attributes of src not found on dst to dst.
+func copyAttributes(dst *Node, src Token) {
+	if len(src.Attr) == 0 {
+		return
+	}
+	attr := map[string]string{}
+	for _, a := range dst.Attr {
+		attr[a.Key] = a.Val
+	}
+	for _, a := range src.Attr {
+		if _, ok := attr[a.Key]; !ok {
+			dst.Attr = append(dst.Attr, a)
+			attr[a.Key] = a.Val
+		}
+	}
+}
+
+// Section 12.2.5.4.7.
+func inBodyIM(p *parser) bool {
+	switch p.tok.Type {
+	case TextToken:
+		switch n := p.oe.top(); n.Data {
+		case "pre", "listing", "textarea":
+			if len(n.Child) == 0 {
+				// Ignore a newline at the start of a <pre> block.
+				d := p.tok.Data
+				if d != "" && d[0] == '\r' {
+					d = d[1:]
+				}
+				if d != "" && d[0] == '\n' {
+					d = d[1:]
+				}
+				if d == "" {
+					return true
+				}
+				p.tok.Data = d
+			}
+		}
+		p.reconstructActiveFormattingElements()
+		p.addText(p.tok.Data)
+		p.framesetOK = false
+	case StartTagToken:
+		switch p.tok.Data {
+		case "html":
+			copyAttributes(p.oe[0], p.tok)
+		case "address", "article", "aside", "blockquote", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "menu", "nav", "ol", "p", "section", "summary", "ul":
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "h1", "h2", "h3", "h4", "h5", "h6":
+			p.popUntil(buttonScope, "p")
+			switch n := p.top(); n.Data {
+			case "h1", "h2", "h3", "h4", "h5", "h6":
+				p.oe.pop()
+			}
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "a":
+			for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
+				if n := p.afe[i]; n.Type == ElementNode && n.Data == "a" {
+					p.inBodyEndTagFormatting("a")
+					p.oe.remove(n)
+					p.afe.remove(n)
+					break
+				}
+			}
+			p.reconstructActiveFormattingElements()
+			p.addFormattingElement(p.tok.Data, p.tok.Attr)
+		case "b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u":
+			p.reconstructActiveFormattingElements()
+			p.addFormattingElement(p.tok.Data, p.tok.Attr)
+		case "nobr":
+			p.reconstructActiveFormattingElements()
+			if p.elementInScope(defaultScope, "nobr") {
+				p.inBodyEndTagFormatting("nobr")
+				p.reconstructActiveFormattingElements()
+			}
+			p.addFormattingElement(p.tok.Data, p.tok.Attr)
+		case "applet", "marquee", "object":
+			p.reconstructActiveFormattingElements()
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.afe = append(p.afe, &scopeMarker)
+			p.framesetOK = false
+		case "area", "br", "embed", "img", "input", "keygen", "wbr":
+			p.reconstructActiveFormattingElements()
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.oe.pop()
+			p.acknowledgeSelfClosingTag()
+			p.framesetOK = false
+		case "table":
+			if !p.quirks {
+				p.popUntil(buttonScope, "p")
+			}
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.framesetOK = false
+			p.im = inTableIM
+			return true
+		case "hr":
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.oe.pop()
+			p.acknowledgeSelfClosingTag()
+			p.framesetOK = false
+		case "select":
+			p.reconstructActiveFormattingElements()
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.framesetOK = false
+			p.im = inSelectIM
+			return true
+		case "form":
+			if p.form == nil {
+				p.popUntil(buttonScope, "p")
+				p.addElement(p.tok.Data, p.tok.Attr)
+				p.form = p.top()
+			}
+		case "li":
+			p.framesetOK = false
+			for i := len(p.oe) - 1; i >= 0; i-- {
+				node := p.oe[i]
+				switch node.Data {
+				case "li":
+					p.popUntil(listItemScope, "li")
+				case "address", "div", "p":
+					continue
+				default:
+					if !isSpecialElement(node) {
+						continue
+					}
+				}
+				break
+			}
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "dd", "dt":
+			p.framesetOK = false
+			for i := len(p.oe) - 1; i >= 0; i-- {
+				node := p.oe[i]
+				switch node.Data {
+				case "dd", "dt":
+					p.oe = p.oe[:i]
+				case "address", "div", "p":
+					continue
+				default:
+					if !isSpecialElement(node) {
+						continue
+					}
+				}
+				break
+			}
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "plaintext":
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "button":
+			p.popUntil(defaultScope, "button")
+			p.reconstructActiveFormattingElements()
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.framesetOK = false
+		case "optgroup", "option":
+			if p.top().Data == "option" {
+				p.oe.pop()
+			}
+			p.reconstructActiveFormattingElements()
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "body":
+			if len(p.oe) >= 2 {
+				body := p.oe[1]
+				if body.Type == ElementNode && body.Data == "body" {
+					p.framesetOK = false
+					copyAttributes(body, p.tok)
+				}
+			}
+		case "frameset":
+			if !p.framesetOK || len(p.oe) < 2 || p.oe[1].Data != "body" {
+				// Ignore the token.
+				return true
+			}
+			body := p.oe[1]
+			if body.Parent != nil {
+				body.Parent.Remove(body)
+			}
+			p.oe = p.oe[:1]
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.im = inFramesetIM
+			return true
+		case "base", "basefont", "bgsound", "command", "link", "meta", "noframes", "script", "style", "title":
+			return inHeadIM(p)
+		case "image":
+			p.tok.Data = "img"
+			return false
+		case "isindex":
+			if p.form != nil {
+				// Ignore the token.
+				return true
+			}
+			action := ""
+			prompt := "This is a searchable index. Enter search keywords: "
+			attr := []Attribute{{Key: "name", Val: "isindex"}}
+			for _, a := range p.tok.Attr {
+				switch a.Key {
+				case "action":
+					action = a.Val
+				case "name":
+					// Ignore the attribute.
+				case "prompt":
+					prompt = a.Val
+				default:
+					attr = append(attr, a)
+				}
+			}
+			p.acknowledgeSelfClosingTag()
+			p.popUntil(buttonScope, "p")
+			p.addElement("form", nil)
+			p.form = p.top()
+			if action != "" {
+				p.form.Attr = []Attribute{{Key: "action", Val: action}}
+			}
+			p.addElement("hr", nil)
+			p.oe.pop()
+			p.addElement("label", nil)
+			p.addText(prompt)
+			p.addElement("input", attr)
+			p.oe.pop()
+			p.oe.pop()
+			p.addElement("hr", nil)
+			p.oe.pop()
+			p.oe.pop()
+			p.form = nil
+		case "xmp":
+			p.popUntil(buttonScope, "p")
+			p.reconstructActiveFormattingElements()
+			p.framesetOK = false
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "math", "svg":
+			p.reconstructActiveFormattingElements()
+			if p.tok.Data == "math" {
+				// TODO: adjust MathML attributes.
+			} else {
+				// TODO: adjust SVG attributes.
+			}
+			adjustForeignAttributes(p.tok.Attr)
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.top().Namespace = p.tok.Data
+			return true
+		case "caption", "col", "colgroup", "frame", "head", "tbody", "td", "tfoot", "th", "thead", "tr":
+			// Ignore the token.
+		default:
+			// TODO.
+			p.addElement(p.tok.Data, p.tok.Attr)
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "body":
+			// TODO: autoclose the stack of open elements.
+			p.im = afterBodyIM
+			return true
+		case "p":
+			if !p.elementInScope(buttonScope, "p") {
+				p.addElement("p", nil)
+			}
+			p.popUntil(buttonScope, "p")
+		case "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u":
+			p.inBodyEndTagFormatting(p.tok.Data)
+		case "address", "article", "aside", "blockquote", "button", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "listing", "menu", "nav", "ol", "pre", "section", "summary", "ul":
+			p.popUntil(defaultScope, p.tok.Data)
+		case "applet", "marquee", "object":
+			if p.popUntil(defaultScope, p.tok.Data) {
+				p.clearActiveFormattingElements()
+			}
+		case "br":
+			p.tok.Type = StartTagToken
+			return false
+		default:
+			p.inBodyEndTagOther(p.tok.Data)
+		}
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+	}
+
+	return true
+}
+
+func (p *parser) inBodyEndTagFormatting(tag string) {
+	// This is the "adoption agency" algorithm, described at
+	// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#adoptionAgency
+
+	// TODO: this is a fairly literal line-by-line translation of that algorithm.
+	// Once the code successfully parses the comprehensive test suite, we should
+	// refactor this code to be more idiomatic.
+
+	// Steps 1-3. The outer loop.
+	for i := 0; i < 8; i++ {
+		// Step 4. Find the formatting element.
+		var formattingElement *Node
+		for j := len(p.afe) - 1; j >= 0; j-- {
+			if p.afe[j].Type == scopeMarkerNode {
+				break
+			}
+			if p.afe[j].Data == tag {
+				formattingElement = p.afe[j]
+				break
+			}
+		}
+		if formattingElement == nil {
+			p.inBodyEndTagOther(tag)
+			return
+		}
+		feIndex := p.oe.index(formattingElement)
+		if feIndex == -1 {
+			p.afe.remove(formattingElement)
+			return
+		}
+		if !p.elementInScope(defaultScope, tag) {
+			// Ignore the tag.
+			return
+		}
+
+		// Steps 5-6. Find the furthest block.
+		var furthestBlock *Node
+		for _, e := range p.oe[feIndex:] {
+			if isSpecialElement(e) {
+				furthestBlock = e
+				break
+			}
+		}
+		if furthestBlock == nil {
+			e := p.oe.pop()
+			for e != formattingElement {
+				e = p.oe.pop()
+			}
+			p.afe.remove(e)
+			return
+		}
+
+		// Steps 7-8. Find the common ancestor and bookmark node.
+		commonAncestor := p.oe[feIndex-1]
+		bookmark := p.afe.index(formattingElement)
+
+		// Step 9. The inner loop. Find the lastNode to reparent.
+		lastNode := furthestBlock
+		node := furthestBlock
+		x := p.oe.index(node)
+		// Steps 9.1-9.3.
+		for j := 0; j < 3; j++ {
+			// Step 9.4.
+			x--
+			node = p.oe[x]
+			// Step 9.5.
+			if p.afe.index(node) == -1 {
+				p.oe.remove(node)
+				continue
+			}
+			// Step 9.6.
+			if node == formattingElement {
+				break
+			}
+			// Step 9.7.
+			clone := node.clone()
+			p.afe[p.afe.index(node)] = clone
+			p.oe[p.oe.index(node)] = clone
+			node = clone
+			// Step 9.8.
+			if lastNode == furthestBlock {
+				bookmark = p.afe.index(node) + 1
+			}
+			// Step 9.9.
+			if lastNode.Parent != nil {
+				lastNode.Parent.Remove(lastNode)
+			}
+			node.Add(lastNode)
+			// Step 9.10.
+			lastNode = node
+		}
+
+		// Step 10. Reparent lastNode to the common ancestor,
+		// or for misnested table nodes, to the foster parent.
+		if lastNode.Parent != nil {
+			lastNode.Parent.Remove(lastNode)
+		}
+		switch commonAncestor.Data {
+		case "table", "tbody", "tfoot", "thead", "tr":
+			p.fosterParent(lastNode)
+		default:
+			commonAncestor.Add(lastNode)
+		}
+
+		// Steps 11-13. Reparent nodes from the furthest block's children
+		// to a clone of the formatting element.
+		clone := formattingElement.clone()
+		reparentChildren(clone, furthestBlock)
+		furthestBlock.Add(clone)
+
+		// Step 14. Fix up the list of active formatting elements.
+		if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
+			// Move the bookmark with the rest of the list.
+			bookmark--
+		}
+		p.afe.remove(formattingElement)
+		p.afe.insert(bookmark, clone)
+
+		// Step 15. Fix up the stack of open elements.
+		p.oe.remove(formattingElement)
+		p.oe.insert(p.oe.index(furthestBlock)+1, clone)
+	}
+}
+
+// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
+func (p *parser) inBodyEndTagOther(tag string) {
+	for i := len(p.oe) - 1; i >= 0; i-- {
+		if p.oe[i].Data == tag {
+			p.oe = p.oe[:i]
+			break
+		}
+		if isSpecialElement(p.oe[i]) {
+			break
+		}
+	}
+}
+
+// Section 12.2.5.4.8.
+func textIM(p *parser) bool {
+	switch p.tok.Type {
+	case ErrorToken:
+		p.oe.pop()
+	case TextToken:
+		p.addText(p.tok.Data)
+		return true
+	case EndTagToken:
+		p.oe.pop()
+	}
+	p.im = p.originalIM
+	p.originalIM = nil
+	return p.tok.Type == EndTagToken
+}
+
+// Section 12.2.5.4.9.
+func inTableIM(p *parser) bool {
+	switch p.tok.Type {
+	case ErrorToken:
+		// Stop parsing.
+		return true
+	case TextToken:
+		// TODO.
+	case StartTagToken:
+		switch p.tok.Data {
+		case "caption":
+			p.clearStackToContext(tableScope)
+			p.afe = append(p.afe, &scopeMarker)
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.im = inCaptionIM
+			return true
+		case "tbody", "tfoot", "thead":
+			p.clearStackToContext(tableScope)
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.im = inTableBodyIM
+			return true
+		case "td", "th", "tr":
+			p.clearStackToContext(tableScope)
+			p.addElement("tbody", nil)
+			p.im = inTableBodyIM
+			return false
+		case "table":
+			if p.popUntil(tableScope, "table") {
+				p.resetInsertionMode()
+				return false
+			}
+			// Ignore the token.
+			return true
+		case "colgroup":
+			p.clearStackToContext(tableScope)
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.im = inColumnGroupIM
+			return true
+		case "col":
+			p.clearStackToContext(tableScope)
+			p.addElement("colgroup", p.tok.Attr)
+			p.im = inColumnGroupIM
+			return false
+		case "select":
+			p.reconstructActiveFormattingElements()
+			switch p.top().Data {
+			case "table", "tbody", "tfoot", "thead", "tr":
+				p.fosterParenting = true
+			}
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.fosterParenting = false
+			p.framesetOK = false
+			p.im = inSelectInTableIM
+			return true
+		default:
+			// TODO.
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "table":
+			if p.popUntil(tableScope, "table") {
+				p.resetInsertionMode()
+				return true
+			}
+			// Ignore the token.
+			return true
+		case "body", "caption", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr":
+			// Ignore the token.
+			return true
+		}
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+
+	switch p.top().Data {
+	case "table", "tbody", "tfoot", "thead", "tr":
+		p.fosterParenting = true
+		defer func() { p.fosterParenting = false }()
+	}
+
+	return inBodyIM(p)
+}
+
+// Section 12.2.5.4.11.
+func inCaptionIM(p *parser) bool {
+	switch p.tok.Type {
+	case StartTagToken:
+		switch p.tok.Data {
+		case "caption", "col", "colgroup", "tbody", "td", "tfoot", "thead", "tr":
+			if p.popUntil(tableScope, "caption") {
+				p.clearActiveFormattingElements()
+				p.im = inTableIM
+				return false
+			} else {
+				// Ignore the token.
+				return true
+			}
+		case "select":
+			p.reconstructActiveFormattingElements()
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.framesetOK = false
+			p.im = inSelectInTableIM
+			return true
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "caption":
+			if p.popUntil(tableScope, "caption") {
+				p.clearActiveFormattingElements()
+				p.im = inTableIM
+			}
+			return true
+		case "table":
+			if p.popUntil(tableScope, "caption") {
+				p.clearActiveFormattingElements()
+				p.im = inTableIM
+				return false
+			} else {
+				// Ignore the token.
+				return true
+			}
+		case "body", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr":
+			// Ignore the token.
+			return true
+		}
+	}
+	return inBodyIM(p)
+}
+
+// Section 12.2.5.4.12.
+func inColumnGroupIM(p *parser) bool {
+	switch p.tok.Type {
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	case DoctypeToken:
+		// Ignore the token.
+		return true
+	case StartTagToken:
+		switch p.tok.Data {
+		case "html":
+			return inBodyIM(p)
+		case "col":
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.oe.pop()
+			p.acknowledgeSelfClosingTag()
+			return true
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "colgroup":
+			if p.oe.top().Data != "html" {
+				p.oe.pop()
+				p.im = inTableIM
+			}
+			return true
+		case "col":
+			// Ignore the token.
+			return true
+		}
+	}
+	if p.oe.top().Data != "html" {
+		p.oe.pop()
+		p.im = inTableIM
+		return false
+	}
+	return true
+}
+
+// Section 12.2.5.4.13.
+func inTableBodyIM(p *parser) bool {
+	var (
+		add      bool
+		data     string
+		attr     []Attribute
+		consumed bool
+	)
+	switch p.tok.Type {
+	case ErrorToken:
+		// TODO.
+	case TextToken:
+		// TODO.
+	case StartTagToken:
+		switch p.tok.Data {
+		case "tr":
+			add = true
+			data = p.tok.Data
+			attr = p.tok.Attr
+			consumed = true
+		case "td", "th":
+			add = true
+			data = "tr"
+			consumed = false
+		case "caption", "col", "colgroup", "tbody", "tfoot", "thead":
+			if !p.popUntil(tableScope, "tbody", "thead", "tfoot") {
+				// Ignore the token.
+				return true
+			}
+			p.im = inTableIM
+			return false
+		default:
+			// TODO.
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "table":
+			if p.popUntil(tableScope, "tbody", "thead", "tfoot") {
+				p.im = inTableIM
+				return false
+			}
+			// Ignore the token.
+			return true
+		case "body", "caption", "col", "colgroup", "html", "td", "th", "tr":
+			// Ignore the token.
+			return true
+		}
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	if add {
+		// TODO: clear the stack back to a table body context.
+		p.addElement(data, attr)
+		p.im = inRowIM
+		return consumed
+	}
+	return inTableIM(p)
+}
+
+// Section 12.2.5.4.14.
+func inRowIM(p *parser) bool {
+	switch p.tok.Type {
+	case ErrorToken:
+		// TODO.
+	case TextToken:
+		// TODO.
+	case StartTagToken:
+		switch p.tok.Data {
+		case "td", "th":
+			p.clearStackToContext(tableRowScope)
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.afe = append(p.afe, &scopeMarker)
+			p.im = inCellIM
+			return true
+		case "caption", "col", "colgroup", "tbody", "tfoot", "thead", "tr":
+			if p.popUntil(tableScope, "tr") {
+				p.im = inTableBodyIM
+				return false
+			}
+			// Ignore the token.
+			return true
+		default:
+			// TODO.
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "tr":
+			if p.popUntil(tableScope, "tr") {
+				p.im = inTableBodyIM
+				return true
+			}
+			// Ignore the token.
+			return true
+		case "table":
+			if p.popUntil(tableScope, "tr") {
+				p.im = inTableBodyIM
+				return false
+			}
+			// Ignore the token.
+			return true
+		case "tbody", "tfoot", "thead":
+			// TODO.
+		case "body", "caption", "col", "colgroup", "html", "td", "th":
+			// Ignore the token.
+			return true
+		default:
+			// TODO.
+		}
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	return inTableIM(p)
+}
+
+// Section 12.2.5.4.15.
+func inCellIM(p *parser) bool {
+	var (
+		closeTheCellAndReprocess bool
+	)
+	switch p.tok.Type {
+	case StartTagToken:
+		switch p.tok.Data {
+		case "caption", "col", "colgroup", "tbody", "td", "tfoot", "th", "thead", "tr":
+			// TODO: check for "td" or "th" in table scope.
+			closeTheCellAndReprocess = true
+		case "select":
+			p.reconstructActiveFormattingElements()
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.framesetOK = false
+			p.im = inSelectInTableIM
+			return true
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "td", "th":
+			if !p.popUntil(tableScope, p.tok.Data) {
+				// Ignore the token.
+				return true
+			}
+			p.clearActiveFormattingElements()
+			p.im = inRowIM
+			return true
+		case "body", "caption", "col", "colgroup", "html":
+			// TODO.
+		case "table", "tbody", "tfoot", "thead", "tr":
+			// TODO: check for matching element in table scope.
+			closeTheCellAndReprocess = true
+		}
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	if closeTheCellAndReprocess {
+		if p.popUntil(tableScope, "td") || p.popUntil(tableScope, "th") {
+			p.clearActiveFormattingElements()
+			p.im = inRowIM
+			return false
+		}
+	}
+	return inBodyIM(p)
+}
+
+// Section 12.2.5.4.16.
+func inSelectIM(p *parser) bool {
+	endSelect := false
+	switch p.tok.Type {
+	case ErrorToken:
+		// TODO.
+	case TextToken:
+		p.addText(p.tok.Data)
+	case StartTagToken:
+		switch p.tok.Data {
+		case "html":
+			// TODO.
+		case "option":
+			if p.top().Data == "option" {
+				p.oe.pop()
+			}
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "optgroup":
+			if p.top().Data == "option" {
+				p.oe.pop()
+			}
+			if p.top().Data == "optgroup" {
+				p.oe.pop()
+			}
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "select":
+			endSelect = true
+		case "input", "keygen", "textarea":
+			// TODO.
+		case "script":
+			// TODO.
+		default:
+			// Ignore the token.
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "option":
+			if p.top().Data == "option" {
+				p.oe.pop()
+			}
+		case "optgroup":
+			i := len(p.oe) - 1
+			if p.oe[i].Data == "option" {
+				i--
+			}
+			if p.oe[i].Data == "optgroup" {
+				p.oe = p.oe[:i]
+			}
+		case "select":
+			endSelect = true
+		default:
+			// Ignore the token.
+		}
+	case CommentToken:
+		p.doc.Add(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+	}
+	if endSelect {
+		p.endSelect()
+	}
+	return true
+}
+
+// Section 12.2.5.4.17.
+func inSelectInTableIM(p *parser) bool {
+	switch p.tok.Type {
+	case StartTagToken, EndTagToken:
+		switch p.tok.Data {
+		case "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th":
+			if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.Data) {
+				p.endSelect()
+				return false
+			} else {
+				// Ignore the token.
+				return true
+			}
+		}
+	}
+	return inSelectIM(p)
+}
+
+func (p *parser) endSelect() {
+	for i := len(p.oe) - 1; i >= 0; i-- {
+		switch p.oe[i].Data {
+		case "option", "optgroup":
+			continue
+		case "select":
+			p.oe = p.oe[:i]
+			p.resetInsertionMode()
+		}
+		return
+	}
+}
+
+// Section 12.2.5.4.18.
+func afterBodyIM(p *parser) bool {
+	switch p.tok.Type {
+	case ErrorToken:
+		// Stop parsing.
+		return true
+	case StartTagToken:
+		if p.tok.Data == "html" {
+			return inBodyIM(p)
+		}
+	case EndTagToken:
+		if p.tok.Data == "html" {
+			p.im = afterAfterBodyIM
+			return true
+		}
+	case CommentToken:
+		// The comment is attached to the <html> element.
+		if len(p.oe) < 1 || p.oe[0].Data != "html" {
+			panic("html: bad parser state: <html> element not found, in the after-body insertion mode")
+		}
+		p.oe[0].Add(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	p.im = inBodyIM
+	return false
+}
+
+// Section 12.2.5.4.19.
+func inFramesetIM(p *parser) bool {
+	switch p.tok.Type {
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+	case TextToken:
+		// Ignore all text but whitespace.
+		s := strings.Map(func(c rune) rune {
+			switch c {
+			case ' ', '\t', '\n', '\f', '\r':
+				return c
+			}
+			return -1
+		}, p.tok.Data)
+		if s != "" {
+			p.addText(s)
+		}
+	case StartTagToken:
+		switch p.tok.Data {
+		case "html":
+			return inBodyIM(p)
+		case "frameset":
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "frame":
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.oe.pop()
+			p.acknowledgeSelfClosingTag()
+		case "noframes":
+			return inHeadIM(p)
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "frameset":
+			if p.oe.top().Data != "html" {
+				p.oe.pop()
+				if p.oe.top().Data != "frameset" {
+					p.im = afterFramesetIM
+					return true
+				}
+			}
+		}
+	default:
+		// Ignore the token.
+	}
+	return true
+}
+
+// Section 12.2.5.4.20.
+func afterFramesetIM(p *parser) bool {
+	switch p.tok.Type {
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+	case TextToken:
+		// Ignore all text but whitespace.
+		s := strings.Map(func(c rune) rune {
+			switch c {
+			case ' ', '\t', '\n', '\f', '\r':
+				return c
+			}
+			return -1
+		}, p.tok.Data)
+		if s != "" {
+			p.addText(s)
+		}
+	case StartTagToken:
+		switch p.tok.Data {
+		case "html":
+			return inBodyIM(p)
+		case "noframes":
+			return inHeadIM(p)
+		}
+	case EndTagToken:
+		switch p.tok.Data {
+		case "html":
+			p.im = afterAfterFramesetIM
+			return true
+		}
+	default:
+		// Ignore the token.
+	}
+	return true
+}
+
+// Section 12.2.5.4.21.
+func afterAfterBodyIM(p *parser) bool {
+	switch p.tok.Type {
+	case ErrorToken:
+		// Stop parsing.
+		return true
+	case TextToken:
+		// TODO.
+	case StartTagToken:
+		if p.tok.Data == "html" {
+			return inBodyIM(p)
+		}
+	case CommentToken:
+		p.doc.Add(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+		return true
+	}
+	p.im = inBodyIM
+	return false
+}
+
+// Section 12.2.5.4.22.
+func afterAfterFramesetIM(p *parser) bool {
+	switch p.tok.Type {
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+	case TextToken:
+		// Ignore all text but whitespace.
+		s := strings.Map(func(c rune) rune {
+			switch c {
+			case ' ', '\t', '\n', '\f', '\r':
+				return c
+			}
+			return -1
+		}, p.tok.Data)
+		if s != "" {
+			p.reconstructActiveFormattingElements()
+			p.addText(s)
+		}
+	case StartTagToken:
+		switch p.tok.Data {
+		case "html":
+			return inBodyIM(p)
+		case "noframes":
+			return inHeadIM(p)
+		}
+	default:
+		// Ignore the token.
+	}
+	return true
+}
+
+// Section 12.2.5.5.
+func parseForeignContent(p *parser) bool {
+	switch p.tok.Type {
+	case TextToken:
+		// TODO: HTML integration points.
+		if p.top().Namespace == "" {
+			inBodyIM(p)
+			p.resetInsertionMode()
+			return true
+		}
+		if p.framesetOK {
+			p.framesetOK = strings.TrimLeft(p.tok.Data, whitespace) == ""
+		}
+		p.addText(p.tok.Data)
+	case CommentToken:
+		p.addChild(&Node{
+			Type: CommentNode,
+			Data: p.tok.Data,
+		})
+	case StartTagToken:
+		if htmlIntegrationPoint(p.top()) {
+			inBodyIM(p)
+			p.resetInsertionMode()
+			return true
+		}
+		if breakout[p.tok.Data] {
+			for i := len(p.oe) - 1; i >= 0; i-- {
+				// TODO: MathML integration points.
+				if p.oe[i].Namespace == "" || htmlIntegrationPoint(p.oe[i]) {
+					p.oe = p.oe[:i+1]
+					break
+				}
+			}
+			return false
+		}
+		switch p.top().Namespace {
+		case "math":
+			// TODO: adjust MathML attributes.
+		case "svg":
+			// Adjust SVG tag names. The tokenizer lower-cases tag names, but
+			// SVG wants e.g. "foreignObject" with a capital second "O".
+			if x := svgTagNameAdjustments[p.tok.Data]; x != "" {
+				p.tok.Data = x
+			}
+			// TODO: adjust SVG attributes.
+		default:
+			panic("html: bad parser state: unexpected namespace")
+		}
+		adjustForeignAttributes(p.tok.Attr)
+		namespace := p.top().Namespace
+		p.addElement(p.tok.Data, p.tok.Attr)
+		p.top().Namespace = namespace
+	case EndTagToken:
+		for i := len(p.oe) - 1; i >= 0; i-- {
+			if p.oe[i].Namespace == "" {
+				return p.im(p)
+			}
+			if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
+				p.oe = p.oe[:i]
+				break
+			}
+		}
+		return true
+	default:
+		// Ignore the token.
+	}
+	return true
+}
+
+// Section 12.2.5.
+func (p *parser) inForeignContent() bool {
+	if len(p.oe) == 0 {
+		return false
+	}
+	n := p.oe[len(p.oe)-1]
+	if n.Namespace == "" {
+		return false
+	}
+	// TODO: MathML, HTML integration points.
+	// TODO: MathML's annotation-xml combining with SVG's svg.
+	return true
+}
+
+func (p *parser) parse() error {
+	// Iterate until EOF. Any other error will cause an early return.
+	consumed := true
+	for {
+		if consumed {
+			if err := p.read(); err != nil {
+				if err == io.EOF {
+					break
+				}
+				return err
+			}
+		}
+		if p.inForeignContent() {
+			consumed = parseForeignContent(p)
+		} else {
+			consumed = p.im(p)
+		}
+	}
+	// Loop until the final token (the ErrorToken signifying EOF) is consumed.
+	for {
+		if consumed = p.im(p); consumed {
+			break
+		}
+	}
+	return nil
+}
+
+// Parse returns the parse tree for the HTML from the given Reader.
+// The input is assumed to be UTF-8 encoded.
+func Parse(r io.Reader) (*Node, error) {
+	p := &parser{
+		tokenizer: NewTokenizer(r),
+		doc: &Node{
+			Type: DocumentNode,
+		},
+		scripting:  true,
+		framesetOK: true,
+		im:         initialIM,
+	}
+	err := p.parse()
+	if err != nil {
+		return nil, err
+	}
+	return p.doc, nil
+}
+
+// ParseFragment parses a fragment of HTML and returns the nodes that were 
+// found. If the fragment is the InnerHTML for an existing element, pass that
+// element in context.
+func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
+	p := &parser{
+		tokenizer: NewTokenizer(r),
+		doc: &Node{
+			Type: DocumentNode,
+		},
+		scripting: true,
+		context:   context,
+	}
+
+	if context != nil {
+		switch context.Data {
+		case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp":
+			p.tokenizer.rawTag = context.Data
+		}
+	}
+
+	root := &Node{
+		Type: ElementNode,
+		Data: "html",
+	}
+	p.doc.Add(root)
+	p.oe = nodeStack{root}
+	p.resetInsertionMode()
+
+	for n := context; n != nil; n = n.Parent {
+		if n.Type == ElementNode && n.Data == "form" {
+			p.form = n
+			break
+		}
+	}
+
+	err := p.parse()
+	if err != nil {
+		return nil, err
+	}
+
+	parent := p.doc
+	if context != nil {
+		parent = root
+	}
+
+	result := parent.Child
+	parent.Child = nil
+	for _, n := range result {
+		n.Parent = nil
+	}
+	return result, nil
+}
diff --git a/src/pkg/exp/html/parse_test.go b/src/pkg/exp/html/parse_test.go
new file mode 100644
index 0000000..1528dff
--- /dev/null
+++ b/src/pkg/exp/html/parse_test.go
@@ -0,0 +1,276 @@
+// Copyright 2010 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 html
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"testing"
+)
+
+// readParseTest reads a single test case from r.
+func readParseTest(r *bufio.Reader) (text, want, context string, err error) {
+	line, err := r.ReadSlice('\n')
+	if err != nil {
+		return "", "", "", err
+	}
+	var b []byte
+
+	// Read the HTML.
+	if string(line) != "#data\n" {
+		return "", "", "", fmt.Errorf(`got %q want "#data\n"`, line)
+	}
+	for {
+		line, err = r.ReadSlice('\n')
+		if err != nil {
+			return "", "", "", err
+		}
+		if line[0] == '#' {
+			break
+		}
+		b = append(b, line...)
+	}
+	text = strings.TrimRight(string(b), "\n")
+	b = b[:0]
+
+	// Skip the error list.
+	if string(line) != "#errors\n" {
+		return "", "", "", fmt.Errorf(`got %q want "#errors\n"`, line)
+	}
+	for {
+		line, err = r.ReadSlice('\n')
+		if err != nil {
+			return "", "", "", err
+		}
+		if line[0] == '#' {
+			break
+		}
+	}
+
+	if string(line) == "#document-fragment\n" {
+		line, err = r.ReadSlice('\n')
+		if err != nil {
+			return "", "", "", err
+		}
+		context = strings.TrimSpace(string(line))
+		line, err = r.ReadSlice('\n')
+		if err != nil {
+			return "", "", "", err
+		}
+	}
+
+	// Read the dump of what the parse tree should be.
+	if string(line) != "#document\n" {
+		return "", "", "", fmt.Errorf(`got %q want "#document\n"`, line)
+	}
+	for {
+		line, err = r.ReadSlice('\n')
+		if err != nil && err != io.EOF {
+			return "", "", "", err
+		}
+		if len(line) == 0 || len(line) == 1 && line[0] == '\n' {
+			break
+		}
+		b = append(b, line...)
+	}
+	return text, string(b), context, nil
+}
+
+func dumpIndent(w io.Writer, level int) {
+	io.WriteString(w, "| ")
+	for i := 0; i < level; i++ {
+		io.WriteString(w, "  ")
+	}
+}
+
+func dumpLevel(w io.Writer, n *Node, level int) error {
+	dumpIndent(w, level)
+	switch n.Type {
+	case ErrorNode:
+		return errors.New("unexpected ErrorNode")
+	case DocumentNode:
+		return errors.New("unexpected DocumentNode")
+	case ElementNode:
+		if n.Namespace != "" {
+			fmt.Fprintf(w, "<%s %s>", n.Namespace, n.Data)
+		} else {
+			fmt.Fprintf(w, "<%s>", n.Data)
+		}
+		attr := n.Attr
+		if len(attr) == 2 && attr[0].Namespace == "xml" && attr[1].Namespace == "xlink" {
+			// Some of the test cases in tests10.dat change the order of adjusted
+			// foreign attributes, but that behavior is not in the spec, and could
+			// simply be an implementation detail of html5lib's python map ordering.
+			attr[0], attr[1] = attr[1], attr[0]
+		}
+		for _, a := range attr {
+			io.WriteString(w, "\n")
+			dumpIndent(w, level+1)
+			if a.Namespace != "" {
+				fmt.Fprintf(w, `%s %s="%s"`, a.Namespace, a.Key, a.Val)
+			} else {
+				fmt.Fprintf(w, `%s="%s"`, a.Key, a.Val)
+			}
+		}
+	case TextNode:
+		fmt.Fprintf(w, `"%s"`, n.Data)
+	case CommentNode:
+		fmt.Fprintf(w, "<!-- %s -->", n.Data)
+	case DoctypeNode:
+		fmt.Fprintf(w, "<!DOCTYPE %s", n.Data)
+		if n.Attr != nil {
+			var p, s string
+			for _, a := range n.Attr {
+				switch a.Key {
+				case "public":
+					p = a.Val
+				case "system":
+					s = a.Val
+				}
+			}
+			if p != "" || s != "" {
+				fmt.Fprintf(w, ` "%s"`, p)
+				fmt.Fprintf(w, ` "%s"`, s)
+			}
+		}
+		io.WriteString(w, ">")
+	case scopeMarkerNode:
+		return errors.New("unexpected scopeMarkerNode")
+	default:
+		return errors.New("unknown node type")
+	}
+	io.WriteString(w, "\n")
+	for _, c := range n.Child {
+		if err := dumpLevel(w, c, level+1); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func dump(n *Node) (string, error) {
+	if n == nil || len(n.Child) == 0 {
+		return "", nil
+	}
+	b := bytes.NewBuffer(nil)
+	for _, child := range n.Child {
+		if err := dumpLevel(b, child, 0); err != nil {
+			return "", err
+		}
+	}
+	return b.String(), nil
+}
+
+func TestParser(t *testing.T) {
+	testFiles := []struct {
+		filename string
+		// n is the number of test cases to run from that file.
+		// -1 means all test cases.
+		n int
+	}{
+		// TODO(nigeltao): Process all the test cases from all the .dat files.
+		{"adoption01.dat", -1},
+		{"doctype01.dat", -1},
+		{"tests1.dat", -1},
+		{"tests2.dat", -1},
+		{"tests3.dat", -1},
+		{"tests4.dat", -1},
+		{"tests5.dat", -1},
+		{"tests6.dat", -1},
+		{"tests10.dat", 35},
+	}
+	for _, tf := range testFiles {
+		f, err := os.Open("testdata/webkit/" + tf.filename)
+		if err != nil {
+			t.Fatal(err)
+		}
+		defer f.Close()
+		r := bufio.NewReader(f)
+		for i := 0; i != tf.n; i++ {
+			text, want, context, err := readParseTest(r)
+			if err == io.EOF && tf.n == -1 {
+				break
+			}
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			var doc *Node
+			if context == "" {
+				doc, err = Parse(strings.NewReader(text))
+				if err != nil {
+					t.Fatal(err)
+				}
+			} else {
+				contextNode := &Node{
+					Type: ElementNode,
+					Data: context,
+				}
+				nodes, err := ParseFragment(strings.NewReader(text), contextNode)
+				if err != nil {
+					t.Fatal(err)
+				}
+				doc = &Node{
+					Type: DocumentNode,
+				}
+				for _, n := range nodes {
+					doc.Add(n)
+				}
+			}
+
+			got, err := dump(doc)
+			if err != nil {
+				t.Fatal(err)
+			}
+			// Compare the parsed tree to the #document section.
+			if got != want {
+				t.Errorf("%s test #%d %q, got vs want:\n----\n%s----\n%s----", tf.filename, i, text, got, want)
+				continue
+			}
+			if renderTestBlacklist[text] || context != "" {
+				continue
+			}
+			// Check that rendering and re-parsing results in an identical tree.
+			pr, pw := io.Pipe()
+			go func() {
+				pw.CloseWithError(Render(pw, doc))
+			}()
+			doc1, err := Parse(pr)
+			if err != nil {
+				t.Fatal(err)
+			}
+			got1, err := dump(doc1)
+			if err != nil {
+				t.Fatal(err)
+			}
+			if got != got1 {
+				t.Errorf("%s test #%d %q, got vs got1:\n----\n%s----\n%s----", tf.filename, i, text, got, got1)
+				continue
+			}
+		}
+	}
+}
+
+// Some test input result in parse trees are not 'well-formed' despite
+// following the HTML5 recovery algorithms. Rendering and re-parsing such a
+// tree will not result in an exact clone of that tree. We blacklist such
+// inputs from the render test.
+var renderTestBlacklist = map[string]bool{
+	// The second <a> will be reparented to the first <table>'s parent. This
+	// results in an <a> whose parent is an <a>, which is not 'well-formed'.
+	`<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y`: true,
+	// More cases of <a> being reparented:
+	`<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe`: true,
+	`<a><table><a></table><p><a><div><a>`:                                     true,
+	`<a><table><td><a><table></table><a></tr><a></table><a>`:                  true,
+	// A <plaintext> element is reparented, putting it before a table.
+	// A <plaintext> element can't have anything after it in HTML.
+	`<table><plaintext><td>`: true,
+}
diff --git a/src/pkg/exp/html/render.go b/src/pkg/exp/html/render.go
new file mode 100644
index 0000000..07859fa
--- /dev/null
+++ b/src/pkg/exp/html/render.go
@@ -0,0 +1,277 @@
+// Copyright 2011 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 html
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"strings"
+)
+
+type writer interface {
+	io.Writer
+	WriteByte(byte) error
+	WriteString(string) (int, error)
+}
+
+// Render renders the parse tree n to the given writer.
+//
+// Rendering is done on a 'best effort' basis: calling Parse on the output of
+// Render will always result in something similar to the original tree, but it
+// is not necessarily an exact clone unless the original tree was 'well-formed'.
+// 'Well-formed' is not easily specified; the HTML5 specification is
+// complicated.
+//
+// Calling Parse on arbitrary input typically results in a 'well-formed' parse
+// tree. However, it is possible for Parse to yield a 'badly-formed' parse tree.
+// For example, in a 'well-formed' parse tree, no <a> element is a child of
+// another <a> element: parsing "<a><a>" results in two sibling elements.
+// Similarly, in a 'well-formed' parse tree, no <a> element is a child of a
+// <table> element: parsing "<p><table><a>" results in a <p> with two sibling
+// children; the <a> is reparented to the <table>'s parent. However, calling
+// Parse on "<a><table><a>" does not return an error, but the result has an <a>
+// element with an <a> child, and is therefore not 'well-formed'.
+// 
+// Programmatically constructed trees are typically also 'well-formed', but it
+// is possible to construct a tree that looks innocuous but, when rendered and
+// re-parsed, results in a different tree. A simple example is that a solitary
+// text node would become a tree containing <html>, <head> and <body> elements.
+// Another example is that the programmatic equivalent of "a<head>b</head>c"
+// becomes "<html><head><head/><body>abc</body></html>".
+func Render(w io.Writer, n *Node) error {
+	if x, ok := w.(writer); ok {
+		return render(x, n)
+	}
+	buf := bufio.NewWriter(w)
+	if err := render(buf, n); err != nil {
+		return err
+	}
+	return buf.Flush()
+}
+
+// plaintextAbort is returned from render1 when a <plaintext> element 
+// has been rendered. No more end tags should be rendered after that.
+var plaintextAbort = errors.New("html: internal error (plaintext abort)")
+
+func render(w writer, n *Node) error {
+	err := render1(w, n)
+	if err == plaintextAbort {
+		err = nil
+	}
+	return err
+}
+
+func render1(w writer, n *Node) error {
+	// Render non-element nodes; these are the easy cases.
+	switch n.Type {
+	case ErrorNode:
+		return errors.New("html: cannot render an ErrorNode node")
+	case TextNode:
+		return escape(w, n.Data)
+	case DocumentNode:
+		for _, c := range n.Child {
+			if err := render1(w, c); err != nil {
+				return err
+			}
+		}
+		return nil
+	case ElementNode:
+		// No-op.
+	case CommentNode:
+		if _, err := w.WriteString("<!--"); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(n.Data); err != nil {
+			return err
+		}
+		if _, err := w.WriteString("-->"); err != nil {
+			return err
+		}
+		return nil
+	case DoctypeNode:
+		if _, err := w.WriteString("<!DOCTYPE "); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(n.Data); err != nil {
+			return err
+		}
+		if n.Attr != nil {
+			var p, s string
+			for _, a := range n.Attr {
+				switch a.Key {
+				case "public":
+					p = a.Val
+				case "system":
+					s = a.Val
+				}
+			}
+			if p != "" {
+				if _, err := w.WriteString(" PUBLIC "); err != nil {
+					return err
+				}
+				if err := writeQuoted(w, p); err != nil {
+					return err
+				}
+				if s != "" {
+					if err := w.WriteByte(' '); err != nil {
+						return err
+					}
+					if err := writeQuoted(w, s); err != nil {
+						return err
+					}
+				}
+			} else if s != "" {
+				if _, err := w.WriteString(" SYSTEM "); err != nil {
+					return err
+				}
+				if err := writeQuoted(w, s); err != nil {
+					return err
+				}
+			}
+		}
+		return w.WriteByte('>')
+	default:
+		return errors.New("html: unknown node type")
+	}
+
+	// Render the <xxx> opening tag.
+	if err := w.WriteByte('<'); err != nil {
+		return err
+	}
+	if _, err := w.WriteString(n.Data); err != nil {
+		return err
+	}
+	for _, a := range n.Attr {
+		if err := w.WriteByte(' '); err != nil {
+			return err
+		}
+		if a.Namespace != "" {
+			if _, err := w.WriteString(a.Namespace); err != nil {
+				return err
+			}
+			if err := w.WriteByte(':'); err != nil {
+				return err
+			}
+		}
+		if _, err := w.WriteString(a.Key); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(`="`); err != nil {
+			return err
+		}
+		if err := escape(w, a.Val); err != nil {
+			return err
+		}
+		if err := w.WriteByte('"'); err != nil {
+			return err
+		}
+	}
+	if voidElements[n.Data] {
+		if len(n.Child) != 0 {
+			return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
+		}
+		_, err := w.WriteString("/>")
+		return err
+	}
+	if err := w.WriteByte('>'); err != nil {
+		return err
+	}
+
+	// Add initial newline where there is danger of a newline beging ignored.
+	if len(n.Child) > 0 && n.Child[0].Type == TextNode && strings.HasPrefix(n.Child[0].Data, "\n") {
+		switch n.Data {
+		case "pre", "listing", "textarea":
+			if err := w.WriteByte('\n'); err != nil {
+				return err
+			}
+		}
+	}
+
+	// Render any child nodes.
+	switch n.Data {
+	case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
+		for _, c := range n.Child {
+			if c.Type != TextNode {
+				return fmt.Errorf("html: raw text element <%s> has non-text child node", n.Data)
+			}
+			if _, err := w.WriteString(c.Data); err != nil {
+				return err
+			}
+		}
+		if n.Data == "plaintext" {
+			// Don't render anything else. <plaintext> must be the
+			// last element in the file, with no closing tag.
+			return plaintextAbort
+		}
+	case "textarea", "title":
+		for _, c := range n.Child {
+			if c.Type != TextNode {
+				return fmt.Errorf("html: RCDATA element <%s> has non-text child node", n.Data)
+			}
+			if err := render1(w, c); err != nil {
+				return err
+			}
+		}
+	default:
+		for _, c := range n.Child {
+			if err := render1(w, c); err != nil {
+				return err
+			}
+		}
+	}
+
+	// Render the </xxx> closing tag.
+	if _, err := w.WriteString("</"); err != nil {
+		return err
+	}
+	if _, err := w.WriteString(n.Data); err != nil {
+		return err
+	}
+	return w.WriteByte('>')
+}
+
+// writeQuoted writes s to w surrounded by quotes. Normally it will use double
+// quotes, but if s contains a double quote, it will use single quotes.
+// It is used for writing the identifiers in a doctype declaration.
+// In valid HTML, they can't contain both types of quotes.
+func writeQuoted(w writer, s string) error {
+	var q byte = '"'
+	if strings.Contains(s, `"`) {
+		q = '\''
+	}
+	if err := w.WriteByte(q); err != nil {
+		return err
+	}
+	if _, err := w.WriteString(s); err != nil {
+		return err
+	}
+	if err := w.WriteByte(q); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Section 12.1.2, "Elements", gives this list of void elements. Void elements
+// are those that can't have any contents.
+var voidElements = map[string]bool{
+	"area":    true,
+	"base":    true,
+	"br":      true,
+	"col":     true,
+	"command": true,
+	"embed":   true,
+	"hr":      true,
+	"img":     true,
+	"input":   true,
+	"keygen":  true,
+	"link":    true,
+	"meta":    true,
+	"param":   true,
+	"source":  true,
+	"track":   true,
+	"wbr":     true,
+}
diff --git a/src/pkg/exp/html/render_test.go b/src/pkg/exp/html/render_test.go
new file mode 100644
index 0000000..0584f35
--- /dev/null
+++ b/src/pkg/exp/html/render_test.go
@@ -0,0 +1,111 @@
+// Copyright 2010 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 html
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestRenderer(t *testing.T) {
+	n := &Node{
+		Type: ElementNode,
+		Data: "html",
+		Child: []*Node{
+			{
+				Type: ElementNode,
+				Data: "head",
+			},
+			{
+				Type: ElementNode,
+				Data: "body",
+				Child: []*Node{
+					{
+						Type: TextNode,
+						Data: "0<1",
+					},
+					{
+						Type: ElementNode,
+						Data: "p",
+						Attr: []Attribute{
+							{
+								Key: "id",
+								Val: "A",
+							},
+							{
+								Key: "foo",
+								Val: `abc"def`,
+							},
+						},
+						Child: []*Node{
+							{
+								Type: TextNode,
+								Data: "2",
+							},
+							{
+								Type: ElementNode,
+								Data: "b",
+								Attr: []Attribute{
+									{
+										Key: "empty",
+										Val: "",
+									},
+								},
+								Child: []*Node{
+									{
+										Type: TextNode,
+										Data: "3",
+									},
+								},
+							},
+							{
+								Type: ElementNode,
+								Data: "i",
+								Attr: []Attribute{
+									{
+										Key: "backslash",
+										Val: `\`,
+									},
+								},
+								Child: []*Node{
+									{
+										Type: TextNode,
+										Data: "&4",
+									},
+								},
+							},
+						},
+					},
+					{
+						Type: TextNode,
+						Data: "5",
+					},
+					{
+						Type: ElementNode,
+						Data: "blockquote",
+					},
+					{
+						Type: ElementNode,
+						Data: "br",
+					},
+					{
+						Type: TextNode,
+						Data: "6",
+					},
+				},
+			},
+		},
+	}
+	want := `<html><head></head><body>0<1<p id="A" foo="abc"def">` +
+		`2<b empty="">3</b><i backslash="\">&4</i></p>` +
+		`5<blockquote></blockquote><br/>6</body></html>`
+	b := new(bytes.Buffer)
+	if err := Render(b, n); err != nil {
+		t.Fatal(err)
+	}
+	if got := b.String(); got != want {
+		t.Errorf("got vs want:\n%s\n%s\n", got, want)
+	}
+}
diff --git a/src/pkg/html/testdata/webkit/README b/src/pkg/exp/html/testdata/webkit/README
similarity index 100%
rename from src/pkg/html/testdata/webkit/README
rename to src/pkg/exp/html/testdata/webkit/README
diff --git a/src/pkg/html/testdata/webkit/adoption01.dat b/src/pkg/exp/html/testdata/webkit/adoption01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/adoption01.dat
rename to src/pkg/exp/html/testdata/webkit/adoption01.dat
diff --git a/src/pkg/html/testdata/webkit/adoption02.dat b/src/pkg/exp/html/testdata/webkit/adoption02.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/adoption02.dat
rename to src/pkg/exp/html/testdata/webkit/adoption02.dat
diff --git a/src/pkg/html/testdata/webkit/comments01.dat b/src/pkg/exp/html/testdata/webkit/comments01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/comments01.dat
rename to src/pkg/exp/html/testdata/webkit/comments01.dat
diff --git a/src/pkg/html/testdata/webkit/doctype01.dat b/src/pkg/exp/html/testdata/webkit/doctype01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/doctype01.dat
rename to src/pkg/exp/html/testdata/webkit/doctype01.dat
diff --git a/src/pkg/html/testdata/webkit/entities01.dat b/src/pkg/exp/html/testdata/webkit/entities01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/entities01.dat
rename to src/pkg/exp/html/testdata/webkit/entities01.dat
diff --git a/src/pkg/html/testdata/webkit/entities02.dat b/src/pkg/exp/html/testdata/webkit/entities02.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/entities02.dat
rename to src/pkg/exp/html/testdata/webkit/entities02.dat
diff --git a/src/pkg/html/testdata/webkit/html5test-com.dat b/src/pkg/exp/html/testdata/webkit/html5test-com.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/html5test-com.dat
rename to src/pkg/exp/html/testdata/webkit/html5test-com.dat
diff --git a/src/pkg/html/testdata/webkit/inbody01.dat b/src/pkg/exp/html/testdata/webkit/inbody01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/inbody01.dat
rename to src/pkg/exp/html/testdata/webkit/inbody01.dat
diff --git a/src/pkg/html/testdata/webkit/isindex.dat b/src/pkg/exp/html/testdata/webkit/isindex.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/isindex.dat
rename to src/pkg/exp/html/testdata/webkit/isindex.dat
diff --git a/src/pkg/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat b/src/pkg/exp/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
rename to src/pkg/exp/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
diff --git a/src/pkg/html/testdata/webkit/pending-spec-changes.dat b/src/pkg/exp/html/testdata/webkit/pending-spec-changes.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/pending-spec-changes.dat
rename to src/pkg/exp/html/testdata/webkit/pending-spec-changes.dat
diff --git a/src/pkg/html/testdata/webkit/plain-text-unsafe.dat b/src/pkg/exp/html/testdata/webkit/plain-text-unsafe.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/plain-text-unsafe.dat
rename to src/pkg/exp/html/testdata/webkit/plain-text-unsafe.dat
diff --git a/src/pkg/html/testdata/webkit/scriptdata01.dat b/src/pkg/exp/html/testdata/webkit/scriptdata01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/scriptdata01.dat
rename to src/pkg/exp/html/testdata/webkit/scriptdata01.dat
diff --git a/src/pkg/html/testdata/webkit/scripted/adoption01.dat b/src/pkg/exp/html/testdata/webkit/scripted/adoption01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/scripted/adoption01.dat
rename to src/pkg/exp/html/testdata/webkit/scripted/adoption01.dat
diff --git a/src/pkg/html/testdata/webkit/scripted/webkit01.dat b/src/pkg/exp/html/testdata/webkit/scripted/webkit01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/scripted/webkit01.dat
rename to src/pkg/exp/html/testdata/webkit/scripted/webkit01.dat
diff --git a/src/pkg/html/testdata/webkit/tables01.dat b/src/pkg/exp/html/testdata/webkit/tables01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tables01.dat
rename to src/pkg/exp/html/testdata/webkit/tables01.dat
diff --git a/src/pkg/html/testdata/webkit/tests1.dat b/src/pkg/exp/html/testdata/webkit/tests1.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests1.dat
rename to src/pkg/exp/html/testdata/webkit/tests1.dat
diff --git a/src/pkg/html/testdata/webkit/tests10.dat b/src/pkg/exp/html/testdata/webkit/tests10.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests10.dat
rename to src/pkg/exp/html/testdata/webkit/tests10.dat
diff --git a/src/pkg/html/testdata/webkit/tests11.dat b/src/pkg/exp/html/testdata/webkit/tests11.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests11.dat
rename to src/pkg/exp/html/testdata/webkit/tests11.dat
diff --git a/src/pkg/html/testdata/webkit/tests12.dat b/src/pkg/exp/html/testdata/webkit/tests12.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests12.dat
rename to src/pkg/exp/html/testdata/webkit/tests12.dat
diff --git a/src/pkg/html/testdata/webkit/tests14.dat b/src/pkg/exp/html/testdata/webkit/tests14.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests14.dat
rename to src/pkg/exp/html/testdata/webkit/tests14.dat
diff --git a/src/pkg/html/testdata/webkit/tests15.dat b/src/pkg/exp/html/testdata/webkit/tests15.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests15.dat
rename to src/pkg/exp/html/testdata/webkit/tests15.dat
diff --git a/src/pkg/html/testdata/webkit/tests16.dat b/src/pkg/exp/html/testdata/webkit/tests16.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests16.dat
rename to src/pkg/exp/html/testdata/webkit/tests16.dat
diff --git a/src/pkg/html/testdata/webkit/tests17.dat b/src/pkg/exp/html/testdata/webkit/tests17.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests17.dat
rename to src/pkg/exp/html/testdata/webkit/tests17.dat
diff --git a/src/pkg/html/testdata/webkit/tests18.dat b/src/pkg/exp/html/testdata/webkit/tests18.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests18.dat
rename to src/pkg/exp/html/testdata/webkit/tests18.dat
diff --git a/src/pkg/html/testdata/webkit/tests19.dat b/src/pkg/exp/html/testdata/webkit/tests19.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests19.dat
rename to src/pkg/exp/html/testdata/webkit/tests19.dat
diff --git a/src/pkg/html/testdata/webkit/tests2.dat b/src/pkg/exp/html/testdata/webkit/tests2.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests2.dat
rename to src/pkg/exp/html/testdata/webkit/tests2.dat
diff --git a/src/pkg/html/testdata/webkit/tests20.dat b/src/pkg/exp/html/testdata/webkit/tests20.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests20.dat
rename to src/pkg/exp/html/testdata/webkit/tests20.dat
diff --git a/src/pkg/html/testdata/webkit/tests21.dat b/src/pkg/exp/html/testdata/webkit/tests21.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests21.dat
rename to src/pkg/exp/html/testdata/webkit/tests21.dat
diff --git a/src/pkg/html/testdata/webkit/tests22.dat b/src/pkg/exp/html/testdata/webkit/tests22.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests22.dat
rename to src/pkg/exp/html/testdata/webkit/tests22.dat
diff --git a/src/pkg/html/testdata/webkit/tests23.dat b/src/pkg/exp/html/testdata/webkit/tests23.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests23.dat
rename to src/pkg/exp/html/testdata/webkit/tests23.dat
diff --git a/src/pkg/html/testdata/webkit/tests24.dat b/src/pkg/exp/html/testdata/webkit/tests24.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests24.dat
rename to src/pkg/exp/html/testdata/webkit/tests24.dat
diff --git a/src/pkg/html/testdata/webkit/tests25.dat b/src/pkg/exp/html/testdata/webkit/tests25.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests25.dat
rename to src/pkg/exp/html/testdata/webkit/tests25.dat
diff --git a/src/pkg/html/testdata/webkit/tests26.dat b/src/pkg/exp/html/testdata/webkit/tests26.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests26.dat
rename to src/pkg/exp/html/testdata/webkit/tests26.dat
diff --git a/src/pkg/html/testdata/webkit/tests3.dat b/src/pkg/exp/html/testdata/webkit/tests3.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests3.dat
rename to src/pkg/exp/html/testdata/webkit/tests3.dat
diff --git a/src/pkg/html/testdata/webkit/tests4.dat b/src/pkg/exp/html/testdata/webkit/tests4.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests4.dat
rename to src/pkg/exp/html/testdata/webkit/tests4.dat
diff --git a/src/pkg/html/testdata/webkit/tests5.dat b/src/pkg/exp/html/testdata/webkit/tests5.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests5.dat
rename to src/pkg/exp/html/testdata/webkit/tests5.dat
diff --git a/src/pkg/html/testdata/webkit/tests6.dat b/src/pkg/exp/html/testdata/webkit/tests6.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests6.dat
rename to src/pkg/exp/html/testdata/webkit/tests6.dat
diff --git a/src/pkg/html/testdata/webkit/tests7.dat b/src/pkg/exp/html/testdata/webkit/tests7.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests7.dat
rename to src/pkg/exp/html/testdata/webkit/tests7.dat
diff --git a/src/pkg/html/testdata/webkit/tests8.dat b/src/pkg/exp/html/testdata/webkit/tests8.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests8.dat
rename to src/pkg/exp/html/testdata/webkit/tests8.dat
diff --git a/src/pkg/html/testdata/webkit/tests9.dat b/src/pkg/exp/html/testdata/webkit/tests9.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests9.dat
rename to src/pkg/exp/html/testdata/webkit/tests9.dat
diff --git a/src/pkg/html/testdata/webkit/tests_innerHTML_1.dat b/src/pkg/exp/html/testdata/webkit/tests_innerHTML_1.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tests_innerHTML_1.dat
rename to src/pkg/exp/html/testdata/webkit/tests_innerHTML_1.dat
diff --git a/src/pkg/html/testdata/webkit/tricky01.dat b/src/pkg/exp/html/testdata/webkit/tricky01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/tricky01.dat
rename to src/pkg/exp/html/testdata/webkit/tricky01.dat
diff --git a/src/pkg/html/testdata/webkit/webkit01.dat b/src/pkg/exp/html/testdata/webkit/webkit01.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/webkit01.dat
rename to src/pkg/exp/html/testdata/webkit/webkit01.dat
diff --git a/src/pkg/html/testdata/webkit/webkit02.dat b/src/pkg/exp/html/testdata/webkit/webkit02.dat
similarity index 100%
rename from src/pkg/html/testdata/webkit/webkit02.dat
rename to src/pkg/exp/html/testdata/webkit/webkit02.dat
diff --git a/src/pkg/exp/html/token.go b/src/pkg/exp/html/token.go
new file mode 100644
index 0000000..5a385a1
--- /dev/null
+++ b/src/pkg/exp/html/token.go
@@ -0,0 +1,780 @@
+// Copyright 2010 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 html
+
+import (
+	"bytes"
+	"io"
+	"strconv"
+	"strings"
+)
+
+// A TokenType is the type of a Token.
+type TokenType int
+
+const (
+	// ErrorToken means that an error occurred during tokenization.
+	ErrorToken TokenType = iota
+	// TextToken means a text node.
+	TextToken
+	// A StartTagToken looks like <a>.
+	StartTagToken
+	// An EndTagToken looks like </a>.
+	EndTagToken
+	// A SelfClosingTagToken tag looks like <br/>.
+	SelfClosingTagToken
+	// A CommentToken looks like <!--x-->.
+	CommentToken
+	// A DoctypeToken looks like <!DOCTYPE x>
+	DoctypeToken
+)
+
+// String returns a string representation of the TokenType.
+func (t TokenType) String() string {
+	switch t {
+	case ErrorToken:
+		return "Error"
+	case TextToken:
+		return "Text"
+	case StartTagToken:
+		return "StartTag"
+	case EndTagToken:
+		return "EndTag"
+	case SelfClosingTagToken:
+		return "SelfClosingTag"
+	case CommentToken:
+		return "Comment"
+	case DoctypeToken:
+		return "Doctype"
+	}
+	return "Invalid(" + strconv.Itoa(int(t)) + ")"
+}
+
+// An Attribute is an attribute namespace-key-value triple. Namespace is
+// non-empty for foreign attributes like xlink, Key is alphabetic (and hence
+// does not contain escapable characters like '&', '<' or '>'), and Val is
+// unescaped (it looks like "a<b" rather than "a<b").
+//
+// Namespace is only used by the parser, not the tokenizer.
+type Attribute struct {
+	Namespace, Key, Val string
+}
+
+// A Token consists of a TokenType and some Data (tag name for start and end
+// tags, content for text, comments and doctypes). A tag Token may also contain
+// a slice of Attributes. Data is unescaped for all Tokens (it looks like "a<b"
+// rather than "a<b").
+type Token struct {
+	Type TokenType
+	Data string
+	Attr []Attribute
+}
+
+// tagString returns a string representation of a tag Token's Data and Attr.
+func (t Token) tagString() string {
+	if len(t.Attr) == 0 {
+		return t.Data
+	}
+	buf := bytes.NewBuffer(nil)
+	buf.WriteString(t.Data)
+	for _, a := range t.Attr {
+		buf.WriteByte(' ')
+		buf.WriteString(a.Key)
+		buf.WriteString(`="`)
+		escape(buf, a.Val)
+		buf.WriteByte('"')
+	}
+	return buf.String()
+}
+
+// String returns a string representation of the Token.
+func (t Token) String() string {
+	switch t.Type {
+	case ErrorToken:
+		return ""
+	case TextToken:
+		return EscapeString(t.Data)
+	case StartTagToken:
+		return "<" + t.tagString() + ">"
+	case EndTagToken:
+		return "</" + t.tagString() + ">"
+	case SelfClosingTagToken:
+		return "<" + t.tagString() + "/>"
+	case CommentToken:
+		return "<!--" + t.Data + "-->"
+	case DoctypeToken:
+		return "<!DOCTYPE " + t.Data + ">"
+	}
+	return "Invalid(" + strconv.Itoa(int(t.Type)) + ")"
+}
+
+// span is a range of bytes in a Tokenizer's buffer. The start is inclusive,
+// the end is exclusive.
+type span struct {
+	start, end int
+}
+
+// A Tokenizer returns a stream of HTML Tokens.
+type Tokenizer struct {
+	// r is the source of the HTML text.
+	r io.Reader
+	// tt is the TokenType of the current token.
+	tt TokenType
+	// err is the first error encountered during tokenization. It is possible
+	// for tt != Error && err != nil to hold: this means that Next returned a
+	// valid token but the subsequent Next call will return an error token.
+	// For example, if the HTML text input was just "plain", then the first
+	// Next call would set z.err to io.EOF but return a TextToken, and all
+	// subsequent Next calls would return an ErrorToken.
+	// err is never reset. Once it becomes non-nil, it stays non-nil.
+	err error
+	// buf[raw.start:raw.end] holds the raw bytes of the current token.
+	// buf[raw.end:] is buffered input that will yield future tokens.
+	raw span
+	buf []byte
+	// buf[data.start:data.end] holds the raw bytes of the current token's data:
+	// a text token's text, a tag token's tag name, etc.
+	data span
+	// pendingAttr is the attribute key and value currently being tokenized.
+	// When complete, pendingAttr is pushed onto attr. nAttrReturned is
+	// incremented on each call to TagAttr.
+	pendingAttr   [2]span
+	attr          [][2]span
+	nAttrReturned int
+	// rawTag is the "script" in "</script>" that closes the next token. If
+	// non-empty, the subsequent call to Next will return a raw or RCDATA text
+	// token: one that treats "<p>" as text instead of an element.
+	// rawTag's contents are lower-cased.
+	rawTag string
+	// textIsRaw is whether the current text token's data is not escaped.
+	textIsRaw bool
+}
+
+// Err returns the error associated with the most recent ErrorToken token.
+// This is typically io.EOF, meaning the end of tokenization.
+func (z *Tokenizer) Err() error {
+	if z.tt != ErrorToken {
+		return nil
+	}
+	return z.err
+}
+
+// readByte returns the next byte from the input stream, doing a buffered read
+// from z.r into z.buf if necessary. z.buf[z.raw.start:z.raw.end] remains a contiguous byte
+// slice that holds all the bytes read so far for the current token.
+// It sets z.err if the underlying reader returns an error.
+// Pre-condition: z.err == nil.
+func (z *Tokenizer) readByte() byte {
+	if z.raw.end >= len(z.buf) {
+		// Our buffer is exhausted and we have to read from z.r.
+		// We copy z.buf[z.raw.start:z.raw.end] to the beginning of z.buf. If the length
+		// z.raw.end - z.raw.start is more than half the capacity of z.buf, then we
+		// allocate a new buffer before the copy.
+		c := cap(z.buf)
+		d := z.raw.end - z.raw.start
+		var buf1 []byte
+		if 2*d > c {
+			buf1 = make([]byte, d, 2*c)
+		} else {
+			buf1 = z.buf[:d]
+		}
+		copy(buf1, z.buf[z.raw.start:z.raw.end])
+		if x := z.raw.start; x != 0 {
+			// Adjust the data/attr spans to refer to the same contents after the copy.
+			z.data.start -= x
+			z.data.end -= x
+			z.pendingAttr[0].start -= x
+			z.pendingAttr[0].end -= x
+			z.pendingAttr[1].start -= x
+			z.pendingAttr[1].end -= x
+			for i := range z.attr {
+				z.attr[i][0].start -= x
+				z.attr[i][0].end -= x
+				z.attr[i][1].start -= x
+				z.attr[i][1].end -= x
+			}
+		}
+		z.raw.start, z.raw.end, z.buf = 0, d, buf1[:d]
+		// Now that we have copied the live bytes to the start of the buffer,
+		// we read from z.r into the remainder.
+		n, err := z.r.Read(buf1[d:cap(buf1)])
+		if err != nil {
+			z.err = err
+			return 0
+		}
+		z.buf = buf1[:d+n]
+	}
+	x := z.buf[z.raw.end]
+	z.raw.end++
+	return x
+}
+
+// skipWhiteSpace skips past any white space.
+func (z *Tokenizer) skipWhiteSpace() {
+	if z.err != nil {
+		return
+	}
+	for {
+		c := z.readByte()
+		if z.err != nil {
+			return
+		}
+		switch c {
+		case ' ', '\n', '\r', '\t', '\f':
+			// No-op.
+		default:
+			z.raw.end--
+			return
+		}
+	}
+}
+
+// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and
+// is typically something like "script" or "textarea".
+func (z *Tokenizer) readRawOrRCDATA() {
+loop:
+	for {
+		c := z.readByte()
+		if z.err != nil {
+			break loop
+		}
+		if c != '<' {
+			continue loop
+		}
+		c = z.readByte()
+		if z.err != nil {
+			break loop
+		}
+		if c != '/' {
+			continue loop
+		}
+		for i := 0; i < len(z.rawTag); i++ {
+			c = z.readByte()
+			if z.err != nil {
+				break loop
+			}
+			if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') {
+				continue loop
+			}
+		}
+		c = z.readByte()
+		if z.err != nil {
+			break loop
+		}
+		switch c {
+		case ' ', '\n', '\r', '\t', '\f', '/', '>':
+			// The 3 is 2 for the leading "</" plus 1 for the trailing character c.
+			z.raw.end -= 3 + len(z.rawTag)
+			break loop
+		case '<':
+			// Step back one, to catch "</foo</foo>".
+			z.raw.end--
+		}
+	}
+	z.data.end = z.raw.end
+	// A textarea's or title's RCDATA can contain escaped entities.
+	z.textIsRaw = z.rawTag != "textarea" && z.rawTag != "title"
+	z.rawTag = ""
+}
+
+// readComment reads the next comment token starting with "<!--". The opening
+// "<!--" has already been consumed.
+func (z *Tokenizer) readComment() {
+	z.data.start = z.raw.end
+	defer func() {
+		if z.data.end < z.data.start {
+			// It's a comment with no data, like <!-->.
+			z.data.end = z.data.start
+		}
+	}()
+	for dashCount := 2; ; {
+		c := z.readByte()
+		if z.err != nil {
+			// Ignore up to two dashes at EOF.
+			if dashCount > 2 {
+				dashCount = 2
+			}
+			z.data.end = z.raw.end - dashCount
+			return
+		}
+		switch c {
+		case '-':
+			dashCount++
+			continue
+		case '>':
+			if dashCount >= 2 {
+				z.data.end = z.raw.end - len("-->")
+				return
+			}
+		case '!':
+			if dashCount >= 2 {
+				c = z.readByte()
+				if z.err != nil {
+					z.data.end = z.raw.end
+					return
+				}
+				if c == '>' {
+					z.data.end = z.raw.end - len("--!>")
+					return
+				}
+			}
+		}
+		dashCount = 0
+	}
+}
+
+// readUntilCloseAngle reads until the next ">".
+func (z *Tokenizer) readUntilCloseAngle() {
+	z.data.start = z.raw.end
+	for {
+		c := z.readByte()
+		if z.err != nil {
+			z.data.end = z.raw.end
+			return
+		}
+		if c == '>' {
+			z.data.end = z.raw.end - len(">")
+			return
+		}
+	}
+}
+
+// readMarkupDeclaration reads the next token starting with "<!". It might be
+// a "<!--comment-->", a "<!DOCTYPE foo>", or "<!a bogus comment". The opening
+// "<!" has already been consumed.
+func (z *Tokenizer) readMarkupDeclaration() TokenType {
+	z.data.start = z.raw.end
+	var c [2]byte
+	for i := 0; i < 2; i++ {
+		c[i] = z.readByte()
+		if z.err != nil {
+			z.data.end = z.raw.end
+			return CommentToken
+		}
+	}
+	if c[0] == '-' && c[1] == '-' {
+		z.readComment()
+		return CommentToken
+	}
+	z.raw.end -= 2
+	const s = "DOCTYPE"
+	for i := 0; i < len(s); i++ {
+		c := z.readByte()
+		if z.err != nil {
+			z.data.end = z.raw.end
+			return CommentToken
+		}
+		if c != s[i] && c != s[i]+('a'-'A') {
+			// Back up to read the fragment of "DOCTYPE" again.
+			z.raw.end = z.data.start
+			z.readUntilCloseAngle()
+			return CommentToken
+		}
+	}
+	if z.skipWhiteSpace(); z.err != nil {
+		z.data.start = z.raw.end
+		z.data.end = z.raw.end
+		return DoctypeToken
+	}
+	z.readUntilCloseAngle()
+	return DoctypeToken
+}
+
+// startTagIn returns whether the start tag in z.buf[z.data.start:z.data.end]
+// case-insensitively matches any element of ss.
+func (z *Tokenizer) startTagIn(ss ...string) bool {
+loop:
+	for _, s := range ss {
+		if z.data.end-z.data.start != len(s) {
+			continue loop
+		}
+		for i := 0; i < len(s); i++ {
+			c := z.buf[z.data.start+i]
+			if 'A' <= c && c <= 'Z' {
+				c += 'a' - 'A'
+			}
+			if c != s[i] {
+				continue loop
+			}
+		}
+		return true
+	}
+	return false
+}
+
+// readStartTag reads the next start tag token. The opening "<a" has already
+// been consumed, where 'a' means anything in [A-Za-z].
+func (z *Tokenizer) readStartTag() TokenType {
+	z.attr = z.attr[:0]
+	z.nAttrReturned = 0
+	// Read the tag name and attribute key/value pairs.
+	z.readTagName()
+	if z.skipWhiteSpace(); z.err != nil {
+		return ErrorToken
+	}
+	for {
+		c := z.readByte()
+		if z.err != nil || c == '>' {
+			break
+		}
+		z.raw.end--
+		z.readTagAttrKey()
+		z.readTagAttrVal()
+		// Save pendingAttr if it has a non-empty key.
+		if z.pendingAttr[0].start != z.pendingAttr[0].end {
+			z.attr = append(z.attr, z.pendingAttr)
+		}
+		if z.skipWhiteSpace(); z.err != nil {
+			break
+		}
+	}
+	// Several tags flag the tokenizer's next token as raw.
+	c, raw := z.buf[z.data.start], false
+	if 'A' <= c && c <= 'Z' {
+		c += 'a' - 'A'
+	}
+	switch c {
+	case 'i':
+		raw = z.startTagIn("iframe")
+	case 'n':
+		raw = z.startTagIn("noembed", "noframes", "noscript")
+	case 'p':
+		raw = z.startTagIn("plaintext")
+	case 's':
+		raw = z.startTagIn("script", "style")
+	case 't':
+		raw = z.startTagIn("textarea", "title")
+	case 'x':
+		raw = z.startTagIn("xmp")
+	}
+	if raw {
+		z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end]))
+	}
+	// Look for a self-closing token like "<br/>".
+	if z.err == nil && z.buf[z.raw.end-2] == '/' {
+		return SelfClosingTagToken
+	}
+	return StartTagToken
+}
+
+// readEndTag reads the next end tag token. The opening "</a" has already
+// been consumed, where 'a' means anything in [A-Za-z].
+func (z *Tokenizer) readEndTag() {
+	z.attr = z.attr[:0]
+	z.nAttrReturned = 0
+	z.readTagName()
+	for {
+		c := z.readByte()
+		if z.err != nil || c == '>' {
+			return
+		}
+	}
+}
+
+// readTagName sets z.data to the "div" in "<div k=v>". The reader (z.raw.end)
+// is positioned such that the first byte of the tag name (the "d" in "<div")
+// has already been consumed.
+func (z *Tokenizer) readTagName() {
+	z.data.start = z.raw.end - 1
+	for {
+		c := z.readByte()
+		if z.err != nil {
+			z.data.end = z.raw.end
+			return
+		}
+		switch c {
+		case ' ', '\n', '\r', '\t', '\f':
+			z.data.end = z.raw.end - 1
+			return
+		case '/', '>':
+			z.raw.end--
+			z.data.end = z.raw.end
+			return
+		}
+	}
+}
+
+// readTagAttrKey sets z.pendingAttr[0] to the "k" in "<div k=v>".
+// Precondition: z.err == nil.
+func (z *Tokenizer) readTagAttrKey() {
+	z.pendingAttr[0].start = z.raw.end
+	for {
+		c := z.readByte()
+		if z.err != nil {
+			z.pendingAttr[0].end = z.raw.end
+			return
+		}
+		switch c {
+		case ' ', '\n', '\r', '\t', '\f', '/':
+			z.pendingAttr[0].end = z.raw.end - 1
+			return
+		case '=', '>':
+			z.raw.end--
+			z.pendingAttr[0].end = z.raw.end
+			return
+		}
+	}
+}
+
+// readTagAttrVal sets z.pendingAttr[1] to the "v" in "<div k=v>".
+func (z *Tokenizer) readTagAttrVal() {
+	z.pendingAttr[1].start = z.raw.end
+	z.pendingAttr[1].end = z.raw.end
+	if z.skipWhiteSpace(); z.err != nil {
+		return
+	}
+	c := z.readByte()
+	if z.err != nil {
+		return
+	}
+	if c != '=' {
+		z.raw.end--
+		return
+	}
+	if z.skipWhiteSpace(); z.err != nil {
+		return
+	}
+	quote := z.readByte()
+	if z.err != nil {
+		return
+	}
+	switch quote {
+	case '>':
+		z.raw.end--
+		return
+
+	case '\'', '"':
+		z.pendingAttr[1].start = z.raw.end
+		for {
+			c := z.readByte()
+			if z.err != nil {
+				z.pendingAttr[1].end = z.raw.end
+				return
+			}
+			if c == quote {
+				z.pendingAttr[1].end = z.raw.end - 1
+				return
+			}
+		}
+
+	default:
+		z.pendingAttr[1].start = z.raw.end - 1
+		for {
+			c := z.readByte()
+			if z.err != nil {
+				z.pendingAttr[1].end = z.raw.end
+				return
+			}
+			switch c {
+			case ' ', '\n', '\r', '\t', '\f':
+				z.pendingAttr[1].end = z.raw.end - 1
+				return
+			case '>':
+				z.raw.end--
+				z.pendingAttr[1].end = z.raw.end
+				return
+			}
+		}
+	}
+}
+
+// Next scans the next token and returns its type.
+func (z *Tokenizer) Next() TokenType {
+	if z.err != nil {
+		z.tt = ErrorToken
+		return z.tt
+	}
+	z.raw.start = z.raw.end
+	z.data.start = z.raw.end
+	z.data.end = z.raw.end
+	if z.rawTag != "" {
+		if z.rawTag == "plaintext" {
+			// Read everything up to EOF.
+			for z.err == nil {
+				z.readByte()
+			}
+			z.textIsRaw = true
+		} else {
+			z.readRawOrRCDATA()
+		}
+		if z.data.end > z.data.start {
+			z.tt = TextToken
+			return z.tt
+		}
+	}
+	z.textIsRaw = false
+
+loop:
+	for {
+		c := z.readByte()
+		if z.err != nil {
+			break loop
+		}
+		if c != '<' {
+			continue loop
+		}
+
+		// Check if the '<' we have just read is part of a tag, comment
+		// or doctype. If not, it's part of the accumulated text token.
+		c = z.readByte()
+		if z.err != nil {
+			break loop
+		}
+		var tokenType TokenType
+		switch {
+		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+			tokenType = StartTagToken
+		case c == '/':
+			tokenType = EndTagToken
+		case c == '!' || c == '?':
+			// We use CommentToken to mean any of "<!--actual comments-->",
+			// "<!DOCTYPE declarations>" and "<?xml processing instructions?>".
+			tokenType = CommentToken
+		default:
+			continue
+		}
+
+		// We have a non-text token, but we might have accumulated some text
+		// before that. If so, we return the text first, and return the non-
+		// text token on the subsequent call to Next.
+		if x := z.raw.end - len("<a"); z.raw.start < x {
+			z.raw.end = x
+			z.data.end = x
+			z.tt = TextToken
+			return z.tt
+		}
+		switch tokenType {
+		case StartTagToken:
+			z.tt = z.readStartTag()
+			return z.tt
+		case EndTagToken:
+			c = z.readByte()
+			if z.err != nil {
+				break loop
+			}
+			if c == '>' {
+				// "</>" does not generate a token at all.
+				// Reset the tokenizer state and start again.
+				z.raw.start = z.raw.end
+				z.data.start = z.raw.end
+				z.data.end = z.raw.end
+				continue loop
+			}
+			if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
+				z.readEndTag()
+				z.tt = EndTagToken
+				return z.tt
+			}
+			z.raw.end--
+			z.readUntilCloseAngle()
+			z.tt = CommentToken
+			return z.tt
+		case CommentToken:
+			if c == '!' {
+				z.tt = z.readMarkupDeclaration()
+				return z.tt
+			}
+			z.raw.end--
+			z.readUntilCloseAngle()
+			z.tt = CommentToken
+			return z.tt
+		}
+	}
+	if z.raw.start < z.raw.end {
+		z.data.end = z.raw.end
+		z.tt = TextToken
+		return z.tt
+	}
+	z.tt = ErrorToken
+	return z.tt
+}
+
+// Raw returns the unmodified text of the current token. Calling Next, Token,
+// Text, TagName or TagAttr may change the contents of the returned slice.
+func (z *Tokenizer) Raw() []byte {
+	return z.buf[z.raw.start:z.raw.end]
+}
+
+// Text returns the unescaped text of a text, comment or doctype token. The
+// contents of the returned slice may change on the next call to Next.
+func (z *Tokenizer) Text() []byte {
+	switch z.tt {
+	case TextToken, CommentToken, DoctypeToken:
+		s := z.buf[z.data.start:z.data.end]
+		z.data.start = z.raw.end
+		z.data.end = z.raw.end
+		if !z.textIsRaw {
+			s = unescape(s)
+		}
+		return s
+	}
+	return nil
+}
+
+// TagName returns the lower-cased name of a tag token (the `img` out of
+// `<IMG SRC="foo">`) and whether the tag has attributes.
+// The contents of the returned slice may change on the next call to Next.
+func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
+	if z.data.start < z.data.end {
+		switch z.tt {
+		case StartTagToken, EndTagToken, SelfClosingTagToken:
+			s := z.buf[z.data.start:z.data.end]
+			z.data.start = z.raw.end
+			z.data.end = z.raw.end
+			return lower(s), z.nAttrReturned < len(z.attr)
+		}
+	}
+	return nil, false
+}
+
+// TagAttr returns the lower-cased key and unescaped value of the next unparsed
+// attribute for the current tag token and whether there are more attributes.
+// The contents of the returned slices may change on the next call to Next.
+func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
+	if z.nAttrReturned < len(z.attr) {
+		switch z.tt {
+		case StartTagToken, SelfClosingTagToken:
+			x := z.attr[z.nAttrReturned]
+			z.nAttrReturned++
+			key = z.buf[x[0].start:x[0].end]
+			val = z.buf[x[1].start:x[1].end]
+			return lower(key), unescape(val), z.nAttrReturned < len(z.attr)
+		}
+	}
+	return nil, nil, false
+}
+
+// Token returns the next Token. The result's Data and Attr values remain valid
+// after subsequent Next calls.
+func (z *Tokenizer) Token() Token {
+	t := Token{Type: z.tt}
+	switch z.tt {
+	case TextToken, CommentToken, DoctypeToken:
+		t.Data = string(z.Text())
+	case StartTagToken, SelfClosingTagToken:
+		var attr []Attribute
+		name, moreAttr := z.TagName()
+		for moreAttr {
+			var key, val []byte
+			key, val, moreAttr = z.TagAttr()
+			attr = append(attr, Attribute{"", string(key), string(val)})
+		}
+		t.Data = string(name)
+		t.Attr = attr
+	case EndTagToken:
+		name, _ := z.TagName()
+		t.Data = string(name)
+	}
+	return t
+}
+
+// NewTokenizer returns a new HTML Tokenizer for the given Reader.
+// The input is assumed to be UTF-8 encoded.
+func NewTokenizer(r io.Reader) *Tokenizer {
+	return &Tokenizer{
+		r:   r,
+		buf: make([]byte, 0, 4096),
+	}
+}
diff --git a/src/pkg/exp/html/token_test.go b/src/pkg/exp/html/token_test.go
new file mode 100644
index 0000000..672d60c
--- /dev/null
+++ b/src/pkg/exp/html/token_test.go
@@ -0,0 +1,590 @@
+// Copyright 2010 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 html
+
+import (
+	"bytes"
+	"io"
+	"strings"
+	"testing"
+)
+
+type tokenTest struct {
+	// A short description of the test case.
+	desc string
+	// The HTML to parse.
+	html string
+	// The string representations of the expected tokens, joined by '$'.
+	golden string
+}
+
+var tokenTests = []tokenTest{
+	{
+		"empty",
+		"",
+		"",
+	},
+	// A single text node. The tokenizer should not break text nodes on whitespace,
+	// nor should it normalize whitespace within a text node.
+	{
+		"text",
+		"foo  bar",
+		"foo  bar",
+	},
+	// An entity.
+	{
+		"entity",
+		"one < two",
+		"one < two",
+	},
+	// A start, self-closing and end tag. The tokenizer does not care if the start
+	// and end tokens don't match; that is the job of the parser.
+	{
+		"tags",
+		"<a>b<c/>d</e>",
+		"<a>$b$<c/>$d$</e>",
+	},
+	// Angle brackets that aren't a tag.
+	{
+		"not a tag #0",
+		"<",
+		"<",
+	},
+	{
+		"not a tag #1",
+		"</",
+		"</",
+	},
+	{
+		"not a tag #2",
+		"</>",
+		"",
+	},
+	{
+		"not a tag #3",
+		"a</>b",
+		"a$b",
+	},
+	{
+		"not a tag #4",
+		"</ >",
+		"<!-- -->",
+	},
+	{
+		"not a tag #5",
+		"</.",
+		"<!--.-->",
+	},
+	{
+		"not a tag #6",
+		"</.>",
+		"<!--.-->",
+	},
+	{
+		"not a tag #7",
+		"a < b",
+		"a < b",
+	},
+	{
+		"not a tag #8",
+		"<.>",
+		"<.>",
+	},
+	{
+		"not a tag #9",
+		"a<<<b>>>c",
+		"a<<$<b>$>>c",
+	},
+	{
+		"not a tag #10",
+		"if x<0 and y < 0 then x*y>0",
+		"if x<0 and y < 0 then x*y>0",
+	},
+	// EOF in a tag name.
+	{
+		"tag name eof #0",
+		"<a",
+		"",
+	},
+	{
+		"tag name eof #1",
+		"<a ",
+		"",
+	},
+	{
+		"tag name eof #2",
+		"a<b",
+		"a",
+	},
+	{
+		"tag name eof #3",
+		"<a><b",
+		"<a>",
+	},
+	{
+		"tag name eof #4",
+		`<a x`,
+		`<a x="">`,
+	},
+	// Some malformed tags that are missing a '>'.
+	{
+		"malformed tag #0",
+		`<p</p>`,
+		`<p< p="">`,
+	},
+	{
+		"malformed tag #1",
+		`<p </p>`,
+		`<p <="" p="">`,
+	},
+	{
+		"malformed tag #2",
+		`<p id`,
+		`<p id="">`,
+	},
+	{
+		"malformed tag #3",
+		`<p id=`,
+		`<p id="">`,
+	},
+	{
+		"malformed tag #4",
+		`<p id=>`,
+		`<p id="">`,
+	},
+	{
+		"malformed tag #5",
+		`<p id=0`,
+		`<p id="0">`,
+	},
+	{
+		"malformed tag #6",
+		`<p id=0</p>`,
+		`<p id="0</p">`,
+	},
+	{
+		"malformed tag #7",
+		`<p id="0</p>`,
+		`<p id="0</p>">`,
+	},
+	{
+		"malformed tag #8",
+		`<p id="0"</p>`,
+		`<p id="0" <="" p="">`,
+	},
+	// Raw text and RCDATA.
+	{
+		"basic raw text",
+		"<script><a></b></script>",
+		"<script>$<a></b>$</script>",
+	},
+	{
+		"unfinished script end tag",
+		"<SCRIPT>a</SCR",
+		"<script>$a</SCR",
+	},
+	{
+		"broken script end tag",
+		"<SCRIPT>a</SCR ipt>",
+		"<script>$a</SCR ipt>",
+	},
+	{
+		"EOF in script end tag",
+		"<SCRIPT>a</SCRipt",
+		"<script>$a</SCRipt",
+	},
+	{
+		"scriptx end tag",
+		"<SCRIPT>a</SCRiptx",
+		"<script>$a</SCRiptx",
+	},
+	{
+		"' ' completes script end tag",
+		"<SCRIPT>a</SCRipt ",
+		"<script>$a$</script>",
+	},
+	{
+		"'>' completes script end tag",
+		"<SCRIPT>a</SCRipt>",
+		"<script>$a$</script>",
+	},
+	{
+		"self-closing script end tag",
+		"<SCRIPT>a</SCRipt/>",
+		"<script>$a$</script>",
+	},
+	{
+		"nested script tag",
+		"<SCRIPT>a</SCRipt<script>",
+		"<script>$a</SCRipt<script>",
+	},
+	{
+		"script end tag after unfinished",
+		"<SCRIPT>a</SCRipt</script>",
+		"<script>$a</SCRipt$</script>",
+	},
+	{
+		"script/style mismatched tags",
+		"<script>a</style>",
+		"<script>$a</style>",
+	},
+	{
+		"style element with entity",
+		"<style>'",
+		"<style>$&apos;",
+	},
+	{
+		"textarea with tag",
+		"<textarea><div></textarea>",
+		"<textarea>$<div>$</textarea>",
+	},
+	{
+		"title with tag and entity",
+		"<title><b>K&R C</b></title>",
+		"<title>$<b>K&R C</b>$</title>",
+	},
+	// DOCTYPE tests.
+	{
+		"Proper DOCTYPE",
+		"<!DOCTYPE html>",
+		"<!DOCTYPE html>",
+	},
+	{
+		"DOCTYPE with no space",
+		"<!doctypehtml>",
+		"<!DOCTYPE html>",
+	},
+	{
+		"DOCTYPE with two spaces",
+		"<!doctype  html>",
+		"<!DOCTYPE html>",
+	},
+	{
+		"looks like DOCTYPE but isn't",
+		"<!DOCUMENT html>",
+		"<!--DOCUMENT html-->",
+	},
+	{
+		"DOCTYPE at EOF",
+		"<!DOCtype",
+		"<!DOCTYPE >",
+	},
+	// XML processing instructions.
+	{
+		"XML processing instruction",
+		"<?xml?>",
+		"<!--?xml?-->",
+	},
+	// Comments.
+	{
+		"comment0",
+		"abc<b><!-- skipme --></b>def",
+		"abc$<b>$<!-- skipme -->$</b>$def",
+	},
+	{
+		"comment1",
+		"a<!-->z",
+		"a$<!---->$z",
+	},
+	{
+		"comment2",
+		"a<!--->z",
+		"a$<!---->$z",
+	},
+	{
+		"comment3",
+		"a<!--x>-->z",
+		"a$<!--x>-->$z",
+	},
+	{
+		"comment4",
+		"a<!--x->-->z",
+		"a$<!--x->-->$z",
+	},
+	{
+		"comment5",
+		"a<!>z",
+		"a$<!---->$z",
+	},
+	{
+		"comment6",
+		"a<!->z",
+		"a$<!----->$z",
+	},
+	{
+		"comment7",
+		"a<!---<>z",
+		"a$<!---<>z-->",
+	},
+	{
+		"comment8",
+		"a<!--z",
+		"a$<!--z-->",
+	},
+	{
+		"comment9",
+		"a<!--z-",
+		"a$<!--z-->",
+	},
+	{
+		"comment10",
+		"a<!--z--",
+		"a$<!--z-->",
+	},
+	{
+		"comment11",
+		"a<!--z---",
+		"a$<!--z--->",
+	},
+	{
+		"comment12",
+		"a<!--z----",
+		"a$<!--z---->",
+	},
+	{
+		"comment13",
+		"a<!--x--!>z",
+		"a$<!--x-->$z",
+	},
+	// An attribute with a backslash.
+	{
+		"backslash",
+		`<p id="a\"b">`,
+		`<p id="a\" b"="">`,
+	},
+	// Entities, tag name and attribute key lower-casing, and whitespace
+	// normalization within a tag.
+	{
+		"tricky",
+		"<p \t\n iD=\"a"B\"  foo=\"bar\"><EM>te<&;xt</em></p>",
+		`<p id="a"B" foo="bar">$<em>$te<&;xt$</em>$</p>`,
+	},
+	// A nonexistent entity. Tokenizing and converting back to a string should
+	// escape the "&" to become "&".
+	{
+		"noSuchEntity",
+		`<a b="c&noSuchEntity;d"><&alsoDoesntExist;&`,
+		`<a b="c&noSuchEntity;d">$<&alsoDoesntExist;&`,
+	},
+	/*
+		// TODO: re-enable this test when it works. This input/output matches html5lib's behavior.
+		{
+			"entity without semicolon",
+			`¬it;∉<a b="q=z&amp=5&notice=hello¬=world">`,
+			`¬it;∉$<a b="q=z&amp=5&notice=hello¬=world">`,
+		},
+	*/
+	{
+		"entity with digits",
+		"&frac12;",
+		"½",
+	},
+	// Attribute tests:
+	// http://dev.w3.org/html5/spec/Overview.html#attributes-0
+	{
+		"Empty attribute",
+		`<input disabled FOO>`,
+		`<input disabled="" foo="">`,
+	},
+	{
+		"Empty attribute, whitespace",
+		`<input disabled FOO >`,
+		`<input disabled="" foo="">`,
+	},
+	{
+		"Unquoted attribute value",
+		`<input value=yes FOO=BAR>`,
+		`<input value="yes" foo="BAR">`,
+	},
+	{
+		"Unquoted attribute value, spaces",
+		`<input value = yes FOO = BAR>`,
+		`<input value="yes" foo="BAR">`,
+	},
+	{
+		"Unquoted attribute value, trailing space",
+		`<input value=yes FOO=BAR >`,
+		`<input value="yes" foo="BAR">`,
+	},
+	{
+		"Single-quoted attribute value",
+		`<input value='yes' FOO='BAR'>`,
+		`<input value="yes" foo="BAR">`,
+	},
+	{
+		"Single-quoted attribute value, trailing space",
+		`<input value='yes' FOO='BAR' >`,
+		`<input value="yes" foo="BAR">`,
+	},
+	{
+		"Double-quoted attribute value",
+		`<input value="I'm an attribute" FOO="BAR">`,
+		`<input value="I'm an attribute" foo="BAR">`,
+	},
+	{
+		"Attribute name characters",
+		`<meta http-equiv="content-type">`,
+		`<meta http-equiv="content-type">`,
+	},
+	{
+		"Mixed attributes",
+		`a<P V="0 1" w='2' X=3 y>z`,
+		`a$<p v="0 1" w="2" x="3" y="">$z`,
+	},
+	{
+		"Attributes with a solitary single quote",
+		`<p id=can't><p id=won't>`,
+		`<p id="can't">$<p id="won't">`,
+	},
+}
+
+func TestTokenizer(t *testing.T) {
+loop:
+	for _, tt := range tokenTests {
+		z := NewTokenizer(strings.NewReader(tt.html))
+		if tt.golden != "" {
+			for i, s := range strings.Split(tt.golden, "$") {
+				if z.Next() == ErrorToken {
+					t.Errorf("%s token %d: want %q got error %v", tt.desc, i, s, z.Err())
+					continue loop
+				}
+				actual := z.Token().String()
+				if s != actual {
+					t.Errorf("%s token %d: want %q got %q", tt.desc, i, s, actual)
+					continue loop
+				}
+			}
+		}
+		z.Next()
+		if z.Err() != io.EOF {
+			t.Errorf("%s: want EOF got %q", tt.desc, z.Err())
+		}
+	}
+}
+
+type unescapeTest struct {
+	// A short description of the test case.
+	desc string
+	// The HTML text.
+	html string
+	// The unescaped text.
+	unescaped string
+}
+
+var unescapeTests = []unescapeTest{
+	// Handle no entities.
+	{
+		"copy",
+		"A\ttext\nstring",
+		"A\ttext\nstring",
+	},
+	// Handle simple named entities.
+	{
+		"simple",
+		"& > <",
+		"& > <",
+	},
+	// Handle hitting the end of the string.
+	{
+		"stringEnd",
+		"&amp &amp",
+		"& &",
+	},
+	// Handle entities with two codepoints.
+	{
+		"multiCodepoint",
+		"text ⋛︀ blah",
+		"text \u22db\ufe00 blah",
+	},
+	// Handle decimal numeric entities.
+	{
+		"decimalEntity",
+		"Delta = Δ ",
+		"Delta = Δ ",
+	},
+	// Handle hexadecimal numeric entities.
+	{
+		"hexadecimalEntity",
+		"Lambda = &#x3bb; = &#X3Bb ",
+		"Lambda = λ = λ ",
+	},
+	// Handle numeric early termination.
+	{
+		"numericEnds",
+		"&# &#x €43 &copy = &#169f = &#xa9",
+		"&# &#x €43 © = ©f = ©",
+	},
+	// Handle numeric ISO-8859-1 entity replacements.
+	{
+		"numericReplacements",
+		"Footnote&#x87;",
+		"Footnote‡",
+	},
+}
+
+func TestUnescape(t *testing.T) {
+	for _, tt := range unescapeTests {
+		unescaped := UnescapeString(tt.html)
+		if unescaped != tt.unescaped {
+			t.Errorf("TestUnescape %s: want %q, got %q", tt.desc, tt.unescaped, unescaped)
+		}
+	}
+}
+
+func TestUnescapeEscape(t *testing.T) {
+	ss := []string{
+		``,
+		`abc def`,
+		`a & b`,
+		`a&b`,
+		`a &amp b`,
+		`"`,
+		`"`,
+		`"<&>"`,
+		`"<&>"`,
+		`3&5==1 && 0<1, "0<1", a+acute=á`,
+	}
+	for _, s := range ss {
+		if s != UnescapeString(EscapeString(s)) {
+			t.Errorf("s != UnescapeString(EscapeString(s)), s=%q", s)
+		}
+	}
+}
+
+func TestBufAPI(t *testing.T) {
+	s := "0<a>1</a>2<b>3<a>4<a>5</a>6</b>7</a>8<a/>9"
+	z := NewTokenizer(bytes.NewBuffer([]byte(s)))
+	result := bytes.NewBuffer(nil)
+	depth := 0
+loop:
+	for {
+		tt := z.Next()
+		switch tt {
+		case ErrorToken:
+			if z.Err() != io.EOF {
+				t.Error(z.Err())
+			}
+			break loop
+		case TextToken:
+			if depth > 0 {
+				result.Write(z.Text())
+			}
+		case StartTagToken, EndTagToken:
+			tn, _ := z.TagName()
+			if len(tn) == 1 && tn[0] == 'a' {
+				if tt == StartTagToken {
+					depth++
+				} else {
+					depth--
+				}
+			}
+		}
+	}
+	u := "14567"
+	v := string(result.Bytes())
+	if u != v {
+		t.Errorf("TestBufAPI: want %q got %q", u, v)
+	}
+}
diff --git a/src/pkg/exp/inotify/Makefile b/src/pkg/exp/inotify/Makefile
new file mode 100644
index 0000000..1e822fb
--- /dev/null
+++ b/src/pkg/exp/inotify/Makefile
@@ -0,0 +1,14 @@
+# Copyright 2010 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=exp/inotify
+
+GOFILES_linux=\
+	inotify_linux.go\
+
+GOFILES+=$(GOFILES_$(GOOS))
+
+include ../../../Make.pkg
diff --git a/src/pkg/exp/inotify/inotify_linux.go b/src/pkg/exp/inotify/inotify_linux.go
new file mode 100644
index 0000000..f124366
--- /dev/null
+++ b/src/pkg/exp/inotify/inotify_linux.go
@@ -0,0 +1,285 @@
+// Copyright 2010 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 inotify implements a wrapper for the Linux inotify system.
+
+Example:
+    watcher, err := inotify.NewWatcher()
+    if err != nil {
+        log.Fatal(err)
+    }
+    err = watcher.Watch("/tmp")
+    if err != nil {
+        log.Fatal(err)
+    }
+    for {
+        select {
+        case ev := <-watcher.Event:
+            log.Println("event:", ev)
+        case err := <-watcher.Error:
+            log.Println("error:", err)
+        }
+    }
+
+*/
+package inotify
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"strings"
+	"syscall"
+	"unsafe"
+)
+
+type Event struct {
+	Mask   uint32 // Mask of events
+	Cookie uint32 // Unique cookie associating related events (for rename(2))
+	Name   string // File name (optional)
+}
+
+type watch struct {
+	wd    uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
+	flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
+}
+
+type Watcher struct {
+	fd       int               // File descriptor (as returned by the inotify_init() syscall)
+	watches  map[string]*watch // Map of inotify watches (key: path)
+	paths    map[int]string    // Map of watched paths (key: watch descriptor)
+	Error    chan error        // Errors are sent on this channel
+	Event    chan *Event       // Events are returned on this channel
+	done     chan bool         // Channel for sending a "quit message" to the reader goroutine
+	isClosed bool              // Set to true when Close() is first called
+}
+
+// NewWatcher creates and returns a new inotify instance using inotify_init(2)
+func NewWatcher() (*Watcher, error) {
+	fd, errno := syscall.InotifyInit()
+	if fd == -1 {
+		return nil, os.NewSyscallError("inotify_init", errno)
+	}
+	w := &Watcher{
+		fd:      fd,
+		watches: make(map[string]*watch),
+		paths:   make(map[int]string),
+		Event:   make(chan *Event),
+		Error:   make(chan error),
+		done:    make(chan bool, 1),
+	}
+
+	go w.readEvents()
+	return w, nil
+}
+
+// Close closes an inotify watcher instance
+// It sends a message to the reader goroutine to quit and removes all watches
+// associated with the inotify instance
+func (w *Watcher) Close() error {
+	if w.isClosed {
+		return nil
+	}
+	w.isClosed = true
+
+	// Send "quit" message to the reader goroutine
+	w.done <- true
+	for path := range w.watches {
+		w.RemoveWatch(path)
+	}
+
+	return nil
+}
+
+// AddWatch adds path to the watched file set.
+// The flags are interpreted as described in inotify_add_watch(2).
+func (w *Watcher) AddWatch(path string, flags uint32) error {
+	if w.isClosed {
+		return errors.New("inotify instance already closed")
+	}
+
+	watchEntry, found := w.watches[path]
+	if found {
+		watchEntry.flags |= flags
+		flags |= syscall.IN_MASK_ADD
+	}
+	wd, err := syscall.InotifyAddWatch(w.fd, path, flags)
+	if err != nil {
+		return &os.PathError{"inotify_add_watch", path, err}
+	}
+
+	if !found {
+		w.watches[path] = &watch{wd: uint32(wd), flags: flags}
+		w.paths[wd] = path
+	}
+	return nil
+}
+
+// Watch adds path to the watched file set, watching all events.
+func (w *Watcher) Watch(path string) error {
+	return w.AddWatch(path, IN_ALL_EVENTS)
+}
+
+// RemoveWatch removes path from the watched file set.
+func (w *Watcher) RemoveWatch(path string) error {
+	watch, ok := w.watches[path]
+	if !ok {
+		return errors.New(fmt.Sprintf("can't remove non-existent inotify watch for: %s", path))
+	}
+	success, errno := syscall.InotifyRmWatch(w.fd, watch.wd)
+	if success == -1 {
+		return os.NewSyscallError("inotify_rm_watch", errno)
+	}
+	delete(w.watches, path)
+	return nil
+}
+
+// readEvents reads from the inotify file descriptor, converts the
+// received events into Event objects and sends them via the Event channel
+func (w *Watcher) readEvents() {
+	var buf [syscall.SizeofInotifyEvent * 4096]byte
+
+	for {
+		n, err := syscall.Read(w.fd, buf[0:])
+		// See if there is a message on the "done" channel
+		var done bool
+		select {
+		case done = <-w.done:
+		default:
+		}
+
+		// If EOF or a "done" message is received
+		if n == 0 || done {
+			err := syscall.Close(w.fd)
+			if err != nil {
+				w.Error <- os.NewSyscallError("close", err)
+			}
+			close(w.Event)
+			close(w.Error)
+			return
+		}
+		if n < 0 {
+			w.Error <- os.NewSyscallError("read", err)
+			continue
+		}
+		if n < syscall.SizeofInotifyEvent {
+			w.Error <- errors.New("inotify: short read in readEvents()")
+			continue
+		}
+
+		var offset uint32 = 0
+		// We don't know how many events we just read into the buffer
+		// While the offset points to at least one whole event...
+		for offset <= uint32(n-syscall.SizeofInotifyEvent) {
+			// Point "raw" to the event in the buffer
+			raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
+			event := new(Event)
+			event.Mask = uint32(raw.Mask)
+			event.Cookie = uint32(raw.Cookie)
+			nameLen := uint32(raw.Len)
+			// If the event happened to the watched directory or the watched file, the kernel
+			// doesn't append the filename to the event, but we would like to always fill the
+			// the "Name" field with a valid filename. We retrieve the path of the watch from
+			// the "paths" map.
+			event.Name = w.paths[int(raw.Wd)]
+			if nameLen > 0 {
+				// Point "bytes" at the first byte of the filename
+				bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))
+				// The filename is padded with NUL bytes. TrimRight() gets rid of those.
+				event.Name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
+			}
+			// Send the event on the events channel
+			w.Event <- event
+
+			// Move to the next event in the buffer
+			offset += syscall.SizeofInotifyEvent + nameLen
+		}
+	}
+}
+
+// String formats the event e in the form
+// "filename: 0xEventMask = IN_ACCESS|IN_ATTRIB_|..."
+func (e *Event) String() string {
+	var events string = ""
+
+	m := e.Mask
+	for _, b := range eventBits {
+		if m&b.Value != 0 {
+			m &^= b.Value
+			events += "|" + b.Name
+		}
+	}
+
+	if m != 0 {
+		events += fmt.Sprintf("|%#x", m)
+	}
+	if len(events) > 0 {
+		events = " == " + events[1:]
+	}
+
+	return fmt.Sprintf("%q: %#x%s", e.Name, e.Mask, events)
+}
+
+const (
+	// Options for inotify_init() are not exported
+	// IN_CLOEXEC    uint32 = syscall.IN_CLOEXEC
+	// IN_NONBLOCK   uint32 = syscall.IN_NONBLOCK
+
+	// Options for AddWatch
+	IN_DONT_FOLLOW uint32 = syscall.IN_DONT_FOLLOW
+	IN_ONESHOT     uint32 = syscall.IN_ONESHOT
+	IN_ONLYDIR     uint32 = syscall.IN_ONLYDIR
+
+	// The "IN_MASK_ADD" option is not exported, as AddWatch
+	// adds it automatically, if there is already a watch for the given path
+	// IN_MASK_ADD      uint32 = syscall.IN_MASK_ADD
+
+	// Events
+	IN_ACCESS        uint32 = syscall.IN_ACCESS
+	IN_ALL_EVENTS    uint32 = syscall.IN_ALL_EVENTS
+	IN_ATTRIB        uint32 = syscall.IN_ATTRIB
+	IN_CLOSE         uint32 = syscall.IN_CLOSE
+	IN_CLOSE_NOWRITE uint32 = syscall.IN_CLOSE_NOWRITE
+	IN_CLOSE_WRITE   uint32 = syscall.IN_CLOSE_WRITE
+	IN_CREATE        uint32 = syscall.IN_CREATE
+	IN_DELETE        uint32 = syscall.IN_DELETE
+	IN_DELETE_SELF   uint32 = syscall.IN_DELETE_SELF
+	IN_MODIFY        uint32 = syscall.IN_MODIFY
+	IN_MOVE          uint32 = syscall.IN_MOVE
+	IN_MOVED_FROM    uint32 = syscall.IN_MOVED_FROM
+	IN_MOVED_TO      uint32 = syscall.IN_MOVED_TO
+	IN_MOVE_SELF     uint32 = syscall.IN_MOVE_SELF
+	IN_OPEN          uint32 = syscall.IN_OPEN
+
+	// Special events
+	IN_ISDIR      uint32 = syscall.IN_ISDIR
+	IN_IGNORED    uint32 = syscall.IN_IGNORED
+	IN_Q_OVERFLOW uint32 = syscall.IN_Q_OVERFLOW
+	IN_UNMOUNT    uint32 = syscall.IN_UNMOUNT
+)
+
+var eventBits = []struct {
+	Value uint32
+	Name  string
+}{
+	{IN_ACCESS, "IN_ACCESS"},
+	{IN_ATTRIB, "IN_ATTRIB"},
+	{IN_CLOSE, "IN_CLOSE"},
+	{IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE"},
+	{IN_CLOSE_WRITE, "IN_CLOSE_WRITE"},
+	{IN_CREATE, "IN_CREATE"},
+	{IN_DELETE, "IN_DELETE"},
+	{IN_DELETE_SELF, "IN_DELETE_SELF"},
+	{IN_MODIFY, "IN_MODIFY"},
+	{IN_MOVE, "IN_MOVE"},
+	{IN_MOVED_FROM, "IN_MOVED_FROM"},
+	{IN_MOVED_TO, "IN_MOVED_TO"},
+	{IN_MOVE_SELF, "IN_MOVE_SELF"},
+	{IN_OPEN, "IN_OPEN"},
+	{IN_ISDIR, "IN_ISDIR"},
+	{IN_IGNORED, "IN_IGNORED"},
+	{IN_Q_OVERFLOW, "IN_Q_OVERFLOW"},
+	{IN_UNMOUNT, "IN_UNMOUNT"},
+}
diff --git a/src/pkg/exp/inotify/inotify_linux_test.go b/src/pkg/exp/inotify/inotify_linux_test.go
new file mode 100644
index 0000000..c2160fc
--- /dev/null
+++ b/src/pkg/exp/inotify/inotify_linux_test.go
@@ -0,0 +1,102 @@
+// Copyright 2010 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
+
+package inotify
+
+import (
+	"os"
+	"testing"
+	"time"
+)
+
+func TestInotifyEvents(t *testing.T) {
+	// Create an inotify watcher instance and initialize it
+	watcher, err := NewWatcher()
+	if err != nil {
+		t.Fatalf("NewWatcher() failed: %s", err)
+	}
+
+	t.Logf("NEEDS TO BE CONVERTED TO NEW GO TOOL") // TODO
+	return
+
+	// Add a watch for "_test"
+	err = watcher.Watch("_test")
+	if err != nil {
+		t.Fatalf("Watcher.Watch() failed: %s", err)
+	}
+
+	// Receive errors on the error channel on a separate goroutine
+	go func() {
+		for err := range watcher.Error {
+			t.Fatalf("error received: %s", err)
+		}
+	}()
+
+	const testFile string = "_test/TestInotifyEvents.testfile"
+
+	// Receive events on the event channel on a separate goroutine
+	eventstream := watcher.Event
+	var eventsReceived = 0
+	done := make(chan bool)
+	go func() {
+		for event := range eventstream {
+			// Only count relevant events
+			if event.Name == testFile {
+				eventsReceived++
+				t.Logf("event received: %s", event)
+			} else {
+				t.Logf("unexpected event received: %s", event)
+			}
+		}
+		done <- true
+	}()
+
+	// Create a file
+	// This should add at least one event to the inotify event queue
+	_, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
+	if err != nil {
+		t.Fatalf("creating test file failed: %s", err)
+	}
+
+	// We expect this event to be received almost immediately, but let's wait 1 s to be sure
+	time.Sleep(1 * time.Second)
+	if eventsReceived == 0 {
+		t.Fatal("inotify event hasn't been received after 1 second")
+	}
+
+	// Try closing the inotify instance
+	t.Log("calling Close()")
+	watcher.Close()
+	t.Log("waiting for the event channel to become closed...")
+	select {
+	case <-done:
+		t.Log("event channel closed")
+	case <-time.After(1 * time.Second):
+		t.Fatal("event stream was not closed after 1 second")
+	}
+}
+
+func TestInotifyClose(t *testing.T) {
+	watcher, _ := NewWatcher()
+	watcher.Close()
+
+	done := make(chan bool)
+	go func() {
+		watcher.Close()
+		done <- true
+	}()
+
+	select {
+	case <-done:
+	case <-time.After(50 * time.Millisecond):
+		t.Fatal("double Close() test failed: second Close() call didn't return")
+	}
+
+	err := watcher.Watch("_test")
+	if err == nil {
+		t.Fatal("expected error on Watch() after Close(), got nil")
+	}
+}
diff --git a/src/pkg/exp/norm/Makefile b/src/pkg/exp/norm/Makefile
index fd32f86..b4faa24 100644
--- a/src/pkg/exp/norm/Makefile
+++ b/src/pkg/exp/norm/Makefile
@@ -7,6 +7,7 @@ include ../../../Make.inc
 TARG=exp/norm
 GOFILES=\
 	composition.go\
+	input.go\
 	forminfo.go\
 	normalize.go\
 	readwriter.go\
@@ -18,15 +19,15 @@ include ../../../Make.pkg
 CLEANFILES+=maketables maketesttables
 
 maketables: maketables.go triegen.go
-	$(GC) maketables.go triegen.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) maketables.go triegen.go
 	$(LD) -o maketables maketables.$O
 
 maketesttables: maketesttables.go triegen.go
-	$(GC) maketesttables.go triegen.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) maketesttables.go triegen.go
 	$(LD) -o maketesttables maketesttables.$O
 
 normregtest: normregtest.go
-	$(GC) normregtest.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) normregtest.go
 	$(LD) -o normregtest normregtest.$O
 
 tables:	maketables
diff --git a/src/pkg/exp/norm/composition.go b/src/pkg/exp/norm/composition.go
index ea59c81..7cad8a2 100644
--- a/src/pkg/exp/norm/composition.go
+++ b/src/pkg/exp/norm/composition.go
@@ -4,7 +4,7 @@
 
 package norm
 
-import "utf8"
+import "unicode/utf8"
 
 const (
 	maxCombiningChars = 30
@@ -27,6 +27,26 @@ type reorderBuffer struct {
 	nrune int                     // Number of runeInfos.
 	nbyte uint8                   // Number or bytes.
 	f     formInfo
+
+	src       input
+	nsrc      int
+	srcBytes  inputBytes
+	srcString inputString
+	tmpBytes  inputBytes
+}
+
+func (rb *reorderBuffer) init(f Form, src []byte) {
+	rb.f = *formTable[f]
+	rb.srcBytes = inputBytes(src)
+	rb.src = &rb.srcBytes
+	rb.nsrc = len(src)
+}
+
+func (rb *reorderBuffer) initString(f Form, src string) {
+	rb.f = *formTable[f]
+	rb.srcString = inputString(src)
+	rb.src = &rb.srcString
+	rb.nsrc = len(src)
 }
 
 // reset discards all characters from the buffer.
@@ -75,45 +95,17 @@ func (rb *reorderBuffer) insertOrdered(info runeInfo) bool {
 
 // insert inserts the given rune in the buffer ordered by CCC.
 // It returns true if the buffer was large enough to hold the decomposed rune.
-func (rb *reorderBuffer) insert(src []byte, info runeInfo) bool {
-	if info.size == 3 && isHangul(src) {
-		rune, _ := utf8.DecodeRune(src)
-		return rb.decomposeHangul(uint32(rune))
-	}
-	if info.flags.hasDecomposition() {
-		dcomp := rb.f.decompose(src)
-		for i := 0; i < len(dcomp); {
-			info = rb.f.info(dcomp[i:])
-			pos := rb.nbyte
-			if !rb.insertOrdered(info) {
-				return false
-			}
-			end := i + int(info.size)
-			copy(rb.byte[pos:], dcomp[i:end])
-			i = end
+func (rb *reorderBuffer) insert(src input, i int, info runeInfo) bool {
+	if info.size == 3 {
+		if rune := src.hangul(i); rune != 0 {
+			return rb.decomposeHangul(uint32(rune))
 		}
-	} else {
-		// insertOrder changes nbyte
-		pos := rb.nbyte
-		if !rb.insertOrdered(info) {
-			return false
-		}
-		copy(rb.byte[pos:], src[:info.size])
-	}
-	return true
-}
-
-// insertString inserts the given rune in the buffer ordered by CCC.
-// It returns true if the buffer was large enough to hold the decomposed rune.
-func (rb *reorderBuffer) insertString(src string, info runeInfo) bool {
-	if info.size == 3 && isHangulString(src) {
-		rune, _ := utf8.DecodeRuneInString(src)
-		return rb.decomposeHangul(uint32(rune))
 	}
 	if info.flags.hasDecomposition() {
-		dcomp := rb.f.decomposeString(src)
+		dcomp := rb.f.decompose(src, i)
+		rb.tmpBytes = inputBytes(dcomp)
 		for i := 0; i < len(dcomp); {
-			info = rb.f.info(dcomp[i:])
+			info = rb.f.info(&rb.tmpBytes, i)
 			pos := rb.nbyte
 			if !rb.insertOrdered(info) {
 				return false
@@ -128,32 +120,32 @@ func (rb *reorderBuffer) insertString(src string, info runeInfo) bool {
 		if !rb.insertOrdered(info) {
 			return false
 		}
-		copy(rb.byte[pos:], src[:info.size])
+		src.copySlice(rb.byte[pos:], i, i+int(info.size))
 	}
 	return true
 }
 
 // appendRune inserts a rune at the end of the buffer. It is used for Hangul.
-func (rb *reorderBuffer) appendRune(rune uint32) {
+func (rb *reorderBuffer) appendRune(r uint32) {
 	bn := rb.nbyte
-	sz := utf8.EncodeRune(rb.byte[bn:], int(rune))
+	sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
 	rb.nbyte += utf8.UTFMax
 	rb.rune[rb.nrune] = runeInfo{bn, uint8(sz), 0, 0}
 	rb.nrune++
 }
 
 // assignRune sets a rune at position pos. It is used for Hangul and recomposition.
-func (rb *reorderBuffer) assignRune(pos int, rune uint32) {
+func (rb *reorderBuffer) assignRune(pos int, r uint32) {
 	bn := rb.rune[pos].pos
-	sz := utf8.EncodeRune(rb.byte[bn:], int(rune))
+	sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
 	rb.rune[pos] = runeInfo{bn, uint8(sz), 0, 0}
 }
 
 // runeAt returns the rune at position n. It is used for Hangul and recomposition.
 func (rb *reorderBuffer) runeAt(n int) uint32 {
 	inf := rb.rune[n]
-	rune, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size])
-	return uint32(rune)
+	r, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size])
+	return uint32(r)
 }
 
 // bytesAt returns the UTF-8 encoding of the rune at position n.
@@ -245,17 +237,17 @@ func isHangulWithoutJamoT(b []byte) bool {
 // decomposeHangul algorithmically decomposes a Hangul rune into
 // its Jamo components.
 // See http://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul.
-func (rb *reorderBuffer) decomposeHangul(rune uint32) bool {
+func (rb *reorderBuffer) decomposeHangul(r uint32) bool {
 	b := rb.rune[:]
 	n := rb.nrune
 	if n+3 > len(b) {
 		return false
 	}
-	rune -= hangulBase
-	x := rune % jamoTCount
-	rune /= jamoTCount
-	rb.appendRune(jamoLBase + rune/jamoVCount)
-	rb.appendRune(jamoVBase + rune%jamoVCount)
+	r -= hangulBase
+	x := r % jamoTCount
+	r /= jamoTCount
+	rb.appendRune(jamoLBase + r/jamoVCount)
+	rb.appendRune(jamoVBase + r%jamoVCount)
 	if x != 0 {
 		rb.appendRune(jamoTBase + x)
 	}
diff --git a/src/pkg/exp/norm/composition_test.go b/src/pkg/exp/norm/composition_test.go
index 195a0c1..e32380d 100644
--- a/src/pkg/exp/norm/composition_test.go
+++ b/src/pkg/exp/norm/composition_test.go
@@ -8,28 +8,26 @@ import "testing"
 
 // TestCase is used for most tests.
 type TestCase struct {
-	in  []int
-	out []int
+	in  []rune
+	out []rune
 }
 
-type insertFunc func(rb *reorderBuffer, rune int) bool
+type insertFunc func(rb *reorderBuffer, r rune) bool
 
-func insert(rb *reorderBuffer, rune int) bool {
-	b := []byte(string(rune))
-	return rb.insert(b, rb.f.info(b))
+func insert(rb *reorderBuffer, r rune) bool {
+	src := inputString(string(r))
+	return rb.insert(src, 0, rb.f.info(src, 0))
 }
 
-func insertString(rb *reorderBuffer, rune int) bool {
-	s := string(rune)
-	return rb.insertString(s, rb.f.infoString(s))
-}
-
-func runTests(t *testing.T, name string, rb *reorderBuffer, f insertFunc, tests []TestCase) {
+func runTests(t *testing.T, name string, fm Form, f insertFunc, tests []TestCase) {
+	rb := reorderBuffer{}
+	rb.init(fm, nil)
 	for i, test := range tests {
 		rb.reset()
 		for j, rune := range test.in {
 			b := []byte(string(rune))
-			if !rb.insert(b, rb.f.info(b)) {
+			src := inputBytes(b)
+			if !rb.insert(src, 0, rb.f.info(src, 0)) {
 				t.Errorf("%s:%d: insert failed for rune %d", name, i, j)
 			}
 		}
@@ -41,7 +39,7 @@ func runTests(t *testing.T, name string, rb *reorderBuffer, f insertFunc, tests
 			continue
 		}
 		for j, want := range test.out {
-			found := int(rb.runeAt(j))
+			found := rune(rb.runeAt(j))
 			if found != want {
 				t.Errorf("%s:%d: runeAt(%d) = %U; want %U", name, i, j, found, want)
 			}
@@ -50,7 +48,8 @@ func runTests(t *testing.T, name string, rb *reorderBuffer, f insertFunc, tests
 }
 
 func TestFlush(t *testing.T) {
-	rb := &reorderBuffer{f: *formTable[NFC]}
+	rb := reorderBuffer{}
+	rb.init(NFC, nil)
 	out := make([]byte, 0)
 
 	out = rb.flush(out)
@@ -58,8 +57,8 @@ func TestFlush(t *testing.T) {
 		t.Errorf("wrote bytes on flush of empty buffer. (len(out) = %d)", len(out))
 	}
 
-	for _, r := range []int("world!") {
-		insert(rb, r)
+	for _, r := range []rune("world!") {
+		insert(&rb, r)
 	}
 
 	out = []byte("Hello ")
@@ -77,62 +76,52 @@ func TestFlush(t *testing.T) {
 }
 
 var insertTests = []TestCase{
-	{[]int{'a'}, []int{'a'}},
-	{[]int{0x300}, []int{0x300}},
-	{[]int{0x300, 0x316}, []int{0x316, 0x300}}, // CCC(0x300)==230; CCC(0x316)==220
-	{[]int{0x316, 0x300}, []int{0x316, 0x300}},
-	{[]int{0x41, 0x316, 0x300}, []int{0x41, 0x316, 0x300}},
-	{[]int{0x41, 0x300, 0x316}, []int{0x41, 0x316, 0x300}},
-	{[]int{0x300, 0x316, 0x41}, []int{0x316, 0x300, 0x41}},
-	{[]int{0x41, 0x300, 0x40, 0x316}, []int{0x41, 0x300, 0x40, 0x316}},
+	{[]rune{'a'}, []rune{'a'}},
+	{[]rune{0x300}, []rune{0x300}},
+	{[]rune{0x300, 0x316}, []rune{0x316, 0x300}}, // CCC(0x300)==230; CCC(0x316)==220
+	{[]rune{0x316, 0x300}, []rune{0x316, 0x300}},
+	{[]rune{0x41, 0x316, 0x300}, []rune{0x41, 0x316, 0x300}},
+	{[]rune{0x41, 0x300, 0x316}, []rune{0x41, 0x316, 0x300}},
+	{[]rune{0x300, 0x316, 0x41}, []rune{0x316, 0x300, 0x41}},
+	{[]rune{0x41, 0x300, 0x40, 0x316}, []rune{0x41, 0x300, 0x40, 0x316}},
 }
 
 func TestInsert(t *testing.T) {
-	rb := &reorderBuffer{f: *formTable[NFD]}
-	runTests(t, "TestInsert", rb, insert, insertTests)
-}
-
-func TestInsertString(t *testing.T) {
-	rb := &reorderBuffer{f: *formTable[NFD]}
-	runTests(t, "TestInsertString", rb, insertString, insertTests)
+	runTests(t, "TestInsert", NFD, insert, insertTests)
 }
 
 var decompositionNFDTest = []TestCase{
-	{[]int{0xC0}, []int{0x41, 0x300}},
-	{[]int{0xAC00}, []int{0x1100, 0x1161}},
-	{[]int{0x01C4}, []int{0x01C4}},
-	{[]int{0x320E}, []int{0x320E}},
-	{[]int("음ẻ과"), []int{0x110B, 0x1173, 0x11B7, 0x65, 0x309, 0x1100, 0x116A}},
+	{[]rune{0xC0}, []rune{0x41, 0x300}},
+	{[]rune{0xAC00}, []rune{0x1100, 0x1161}},
+	{[]rune{0x01C4}, []rune{0x01C4}},
+	{[]rune{0x320E}, []rune{0x320E}},
+	{[]rune("음ẻ과"), []rune{0x110B, 0x1173, 0x11B7, 0x65, 0x309, 0x1100, 0x116A}},
 }
 
 var decompositionNFKDTest = []TestCase{
-	{[]int{0xC0}, []int{0x41, 0x300}},
-	{[]int{0xAC00}, []int{0x1100, 0x1161}},
-	{[]int{0x01C4}, []int{0x44, 0x5A, 0x030C}},
-	{[]int{0x320E}, []int{0x28, 0x1100, 0x1161, 0x29}},
+	{[]rune{0xC0}, []rune{0x41, 0x300}},
+	{[]rune{0xAC00}, []rune{0x1100, 0x1161}},
+	{[]rune{0x01C4}, []rune{0x44, 0x5A, 0x030C}},
+	{[]rune{0x320E}, []rune{0x28, 0x1100, 0x1161, 0x29}},
 }
 
 func TestDecomposition(t *testing.T) {
-	rb := &reorderBuffer{}
-	rb.f = *formTable[NFD]
-	runTests(t, "TestDecompositionNFD", rb, insert, decompositionNFDTest)
-	rb.f = *formTable[NFKD]
-	runTests(t, "TestDecompositionNFKD", rb, insert, decompositionNFKDTest)
+	runTests(t, "TestDecompositionNFD", NFD, insert, decompositionNFDTest)
+	runTests(t, "TestDecompositionNFKD", NFKD, insert, decompositionNFKDTest)
 }
 
 var compositionTest = []TestCase{
-	{[]int{0x41, 0x300}, []int{0xC0}},
-	{[]int{0x41, 0x316}, []int{0x41, 0x316}},
-	{[]int{0x41, 0x300, 0x35D}, []int{0xC0, 0x35D}},
-	{[]int{0x41, 0x316, 0x300}, []int{0xC0, 0x316}},
+	{[]rune{0x41, 0x300}, []rune{0xC0}},
+	{[]rune{0x41, 0x316}, []rune{0x41, 0x316}},
+	{[]rune{0x41, 0x300, 0x35D}, []rune{0xC0, 0x35D}},
+	{[]rune{0x41, 0x316, 0x300}, []rune{0xC0, 0x316}},
 	// blocking starter
-	{[]int{0x41, 0x316, 0x40, 0x300}, []int{0x41, 0x316, 0x40, 0x300}},
-	{[]int{0x1100, 0x1161}, []int{0xAC00}},
+	{[]rune{0x41, 0x316, 0x40, 0x300}, []rune{0x41, 0x316, 0x40, 0x300}},
+	{[]rune{0x1100, 0x1161}, []rune{0xAC00}},
 	// parenthesized Hangul, alternate between ASCII and Hangul.
-	{[]int{0x28, 0x1100, 0x1161, 0x29}, []int{0x28, 0xAC00, 0x29}},
+	{[]rune{0x28, 0x1100, 0x1161, 0x29}, []rune{0x28, 0xAC00, 0x29}},
 }
 
 func TestComposition(t *testing.T) {
-	rb := &reorderBuffer{f: *formTable[NFC]}
-	runTests(t, "TestComposition", rb, insert, compositionTest)
+	runTests(t, "TestComposition", NFC, insert, compositionTest)
 }
diff --git a/src/pkg/exp/norm/forminfo.go b/src/pkg/exp/norm/forminfo.go
index 5e01e89..d06a006 100644
--- a/src/pkg/exp/norm/forminfo.go
+++ b/src/pkg/exp/norm/forminfo.go
@@ -15,10 +15,8 @@ type runeInfo struct {
 
 // functions dispatchable per form
 type boundaryFunc func(f *formInfo, info runeInfo) bool
-type lookupFunc func(b []byte) runeInfo
-type lookupFuncString func(s string) runeInfo
-type decompFunc func(b []byte) []byte
-type decompFuncString func(s string) []byte
+type lookupFunc func(b input, i int) runeInfo
+type decompFunc func(b input, i int) []byte
 
 // formInfo holds Form-specific functions and tables.
 type formInfo struct {
@@ -26,12 +24,10 @@ type formInfo struct {
 
 	composing, compatibility bool // form type
 
-	decompose       decompFunc
-	decomposeString decompFuncString
-	info            lookupFunc
-	infoString      lookupFuncString
-	boundaryBefore  boundaryFunc
-	boundaryAfter   boundaryFunc
+	decompose      decompFunc
+	info           lookupFunc
+	boundaryBefore boundaryFunc
+	boundaryAfter  boundaryFunc
 }
 
 var formTable []*formInfo
@@ -46,14 +42,10 @@ func init() {
 		if Form(i) == NFKD || Form(i) == NFKC {
 			f.compatibility = true
 			f.decompose = decomposeNFKC
-			f.decomposeString = decomposeStringNFKC
 			f.info = lookupInfoNFKC
-			f.infoString = lookupInfoStringNFKC
 		} else {
 			f.decompose = decomposeNFC
-			f.decomposeString = decomposeStringNFC
 			f.info = lookupInfoNFC
-			f.infoString = lookupInfoStringNFC
 		}
 		if Form(i) == NFC || Form(i) == NFKC {
 			f.composing = true
@@ -123,29 +115,15 @@ func (r runeInfo) isInert() bool {
 // array of UTF-8 decomposition sequences. The first byte is the number
 // of bytes in the decomposition (excluding this length byte). The actual
 // sequence starts at the offset+1.
-func decomposeNFC(b []byte) []byte {
-	p := nfcDecompTrie.lookupUnsafe(b)
+func decomposeNFC(s input, i int) []byte {
+	p := s.decomposeNFC(i)
 	n := decomps[p]
 	p++
 	return decomps[p : p+uint16(n)]
 }
 
-func decomposeNFKC(b []byte) []byte {
-	p := nfkcDecompTrie.lookupUnsafe(b)
-	n := decomps[p]
-	p++
-	return decomps[p : p+uint16(n)]
-}
-
-func decomposeStringNFC(s string) []byte {
-	p := nfcDecompTrie.lookupStringUnsafe(s)
-	n := decomps[p]
-	p++
-	return decomps[p : p+uint16(n)]
-}
-
-func decomposeStringNFKC(s string) []byte {
-	p := nfkcDecompTrie.lookupStringUnsafe(s)
+func decomposeNFKC(s input, i int) []byte {
+	p := s.decomposeNFKC(i)
 	n := decomps[p]
 	p++
 	return decomps[p : p+uint16(n)]
@@ -168,22 +146,12 @@ func combine(a, b uint32) uint32 {
 //    0..7   CCC value.
 //    8..11  qcInfo for NFC/NFD
 //   12..15  qcInfo for NFKC/NFKD
-func lookupInfoNFC(b []byte) runeInfo {
-	v, sz := charInfoTrie.lookup(b)
-	return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 8)}
-}
-
-func lookupInfoStringNFC(s string) runeInfo {
-	v, sz := charInfoTrie.lookupString(s)
+func lookupInfoNFC(b input, i int) runeInfo {
+	v, sz := b.charinfo(i)
 	return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 8)}
 }
 
-func lookupInfoNFKC(b []byte) runeInfo {
-	v, sz := charInfoTrie.lookup(b)
-	return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 12)}
-}
-
-func lookupInfoStringNFKC(s string) runeInfo {
-	v, sz := charInfoTrie.lookupString(s)
+func lookupInfoNFKC(b input, i int) runeInfo {
+	v, sz := b.charinfo(i)
 	return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 12)}
 }
diff --git a/src/pkg/exp/norm/input.go b/src/pkg/exp/norm/input.go
new file mode 100644
index 0000000..42e6f1b
--- /dev/null
+++ b/src/pkg/exp/norm/input.go
@@ -0,0 +1,105 @@
+// Copyright 2011 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 norm
+
+import "unicode/utf8"
+
+type input interface {
+	skipASCII(p int) int
+	skipNonStarter(p int) int
+	appendSlice(buf []byte, s, e int) []byte
+	copySlice(buf []byte, s, e int)
+	charinfo(p int) (uint16, int)
+	decomposeNFC(p int) uint16
+	decomposeNFKC(p int) uint16
+	hangul(p int) uint32
+}
+
+type inputString string
+
+func (s inputString) skipASCII(p int) int {
+	for ; p < len(s) && s[p] < utf8.RuneSelf; p++ {
+	}
+	return p
+}
+
+func (s inputString) skipNonStarter(p int) int {
+	for ; p < len(s) && !utf8.RuneStart(s[p]); p++ {
+	}
+	return p
+}
+
+func (s inputString) appendSlice(buf []byte, b, e int) []byte {
+	for i := b; i < e; i++ {
+		buf = append(buf, s[i])
+	}
+	return buf
+}
+
+func (s inputString) copySlice(buf []byte, b, e int) {
+	copy(buf, s[b:e])
+}
+
+func (s inputString) charinfo(p int) (uint16, int) {
+	return charInfoTrie.lookupString(string(s[p:]))
+}
+
+func (s inputString) decomposeNFC(p int) uint16 {
+	return nfcDecompTrie.lookupStringUnsafe(string(s[p:]))
+}
+
+func (s inputString) decomposeNFKC(p int) uint16 {
+	return nfkcDecompTrie.lookupStringUnsafe(string(s[p:]))
+}
+
+func (s inputString) hangul(p int) uint32 {
+	if !isHangulString(string(s[p:])) {
+		return 0
+	}
+	rune, _ := utf8.DecodeRuneInString(string(s[p:]))
+	return uint32(rune)
+}
+
+type inputBytes []byte
+
+func (s inputBytes) skipASCII(p int) int {
+	for ; p < len(s) && s[p] < utf8.RuneSelf; p++ {
+	}
+	return p
+}
+
+func (s inputBytes) skipNonStarter(p int) int {
+	for ; p < len(s) && !utf8.RuneStart(s[p]); p++ {
+	}
+	return p
+}
+
+func (s inputBytes) appendSlice(buf []byte, b, e int) []byte {
+	return append(buf, s[b:e]...)
+}
+
+func (s inputBytes) copySlice(buf []byte, b, e int) {
+	copy(buf, s[b:e])
+}
+
+func (s inputBytes) charinfo(p int) (uint16, int) {
+	return charInfoTrie.lookup(s[p:])
+}
+
+func (s inputBytes) decomposeNFC(p int) uint16 {
+	return nfcDecompTrie.lookupUnsafe(s[p:])
+}
+
+func (s inputBytes) decomposeNFKC(p int) uint16 {
+	return nfkcDecompTrie.lookupUnsafe(s[p:])
+}
+
+func (s inputBytes) hangul(p int) uint32 {
+	if !isHangul(s[p:]) {
+		return 0
+	}
+	rune, _ := utf8.DecodeRune(s[p:])
+	return uint32(rune)
+}
diff --git a/src/pkg/exp/norm/maketables.go b/src/pkg/exp/norm/maketables.go
index 14718c5..9a97831 100644
--- a/src/pkg/exp/norm/maketables.go
+++ b/src/pkg/exp/norm/maketables.go
@@ -12,9 +12,9 @@ import (
 	"bytes"
 	"flag"
 	"fmt"
-	"http"
 	"io"
 	"log"
+	"net/http"
 	"os"
 	"regexp"
 	"strconv"
@@ -119,7 +119,7 @@ const (
 // This contains only the properties we're interested in.
 type Char struct {
 	name          string
-	codePoint     int   // if zero, this index is not a valid code point.
+	codePoint     rune  // if zero, this index is not a valid code point.
 	ccc           uint8 // canonical combining class
 	excludeInComp bool  // from CompositionExclusions.txt
 	compatDecomp  bool  // it has a compatibility expansion
@@ -160,7 +160,7 @@ const (
 	SMissing
 )
 
-var lastChar int = 0
+var lastChar = rune('\u0000')
 
 func (c Char) isValid() bool {
 	return c.codePoint != 0 && c.state != SMissing
@@ -193,7 +193,7 @@ func (f FormInfo) String() string {
 	return buf.String()
 }
 
-type Decomposition []int
+type Decomposition []rune
 
 func (d Decomposition) String() string {
 	return fmt.Sprintf("%.4X", d)
@@ -220,17 +220,17 @@ func openReader(file string) (input io.ReadCloser) {
 	return
 }
 
-func parseDecomposition(s string, skipfirst bool) (a []int, e os.Error) {
+func parseDecomposition(s string, skipfirst bool) (a []rune, e error) {
 	decomp := strings.Split(s, " ")
 	if len(decomp) > 0 && skipfirst {
 		decomp = decomp[1:]
 	}
 	for _, d := range decomp {
-		point, err := strconv.Btoui64(d, 16)
+		point, err := strconv.ParseUint(d, 16, 64)
 		if err != nil {
 			return a, err
 		}
-		a = append(a, int(point))
+		a = append(a, rune(point))
 	}
 	return a, nil
 }
@@ -240,7 +240,7 @@ func parseCharacter(line string) {
 	if len(field) != NumField {
 		logger.Fatalf("%5s: %d fields (expected %d)\n", line, len(field), NumField)
 	}
-	x, err := strconv.Btoui64(field[FCodePoint], 16)
+	x, err := strconv.ParseUint(field[FCodePoint], 16, 64)
 	point := int(x)
 	if err != nil {
 		logger.Fatalf("%.5s...: %s", line, err)
@@ -260,11 +260,11 @@ func parseCharacter(line string) {
 		state = SLast
 	}
 	firstChar := lastChar + 1
-	lastChar = int(point)
+	lastChar = rune(point)
 	if state != SLast {
 		firstChar = lastChar
 	}
-	x, err = strconv.Atoui64(field[FCanonicalCombiningClass])
+	x, err = strconv.ParseUint(field[FCanonicalCombiningClass], 10, 64)
 	if err != nil {
 		logger.Fatalf("%U: bad ccc field: %s", int(x), err)
 	}
@@ -310,7 +310,7 @@ func loadUnicodeData() {
 	for {
 		line, err := input.ReadString('\n')
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				break
 			}
 			logger.Fatal(err)
@@ -336,7 +336,7 @@ func parseExclusion(line string) int {
 	if len(matches) != 2 {
 		logger.Fatalf("%s: %d matches (expected 1)\n", line, len(matches))
 	}
-	point, err := strconv.Btoui64(matches[1], 16)
+	point, err := strconv.ParseUint(matches[1], 16, 64)
 	if err != nil {
 		logger.Fatalf("%.5s...: %s", line, err)
 	}
@@ -350,7 +350,7 @@ func loadCompositionExclusions() {
 	for {
 		line, err := input.ReadString('\n')
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				break
 			}
 			logger.Fatal(err)
@@ -370,8 +370,8 @@ func loadCompositionExclusions() {
 // hasCompatDecomp returns true if any of the recursive
 // decompositions contains a compatibility expansion.
 // In this case, the character may not occur in NFK*.
-func hasCompatDecomp(rune int) bool {
-	c := &chars[rune]
+func hasCompatDecomp(r rune) bool {
+	c := &chars[r]
 	if c.compatDecomp {
 		return true
 	}
@@ -396,19 +396,19 @@ const (
 	JamoTEnd  = 0x11C3
 )
 
-func isHangul(rune int) bool {
-	return HangulBase <= rune && rune < HangulEnd
+func isHangul(r rune) bool {
+	return HangulBase <= r && r < HangulEnd
 }
 
-func ccc(rune int) uint8 {
-	return chars[rune].ccc
+func ccc(r rune) uint8 {
+	return chars[r].ccc
 }
 
 // Insert a rune in a buffer, ordered by Canonical Combining Class.
-func insertOrdered(b Decomposition, rune int) Decomposition {
+func insertOrdered(b Decomposition, r rune) Decomposition {
 	n := len(b)
 	b = append(b, 0)
-	cc := ccc(rune)
+	cc := ccc(r)
 	if cc > 0 {
 		// Use bubble sort.
 		for ; n > 0; n-- {
@@ -418,18 +418,18 @@ func insertOrdered(b Decomposition, rune int) Decomposition {
 			b[n] = b[n-1]
 		}
 	}
-	b[n] = rune
+	b[n] = r
 	return b
 }
 
 // Recursively decompose.
-func decomposeRecursive(form int, rune int, d Decomposition) Decomposition {
-	if isHangul(rune) {
+func decomposeRecursive(form int, r rune, d Decomposition) Decomposition {
+	if isHangul(r) {
 		return d
 	}
-	dcomp := chars[rune].forms[form].decomp
+	dcomp := chars[r].forms[form].decomp
 	if len(dcomp) == 0 {
-		return insertOrdered(d, rune)
+		return insertOrdered(d, r)
 	}
 	for _, c := range dcomp {
 		d = decomposeRecursive(form, c, d)
@@ -475,8 +475,8 @@ func completeCharFields(form int) {
 			f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint)
 		}
 
-		for _, rune := range f.decomp {
-			chars[rune].forms[form].inDecomp = true
+		for _, r := range f.decomp {
+			chars[r].forms[form].inDecomp = true
 		}
 	}
 
@@ -505,7 +505,7 @@ func completeCharFields(form int) {
 		switch {
 		case len(f.decomp) > 0:
 			f.quickCheck[MDecomposed] = QCNo
-		case isHangul(i):
+		case isHangul(rune(i)):
 			f.quickCheck[MDecomposed] = QCNo
 		default:
 			f.quickCheck[MDecomposed] = QCYes
@@ -588,7 +588,7 @@ func printCharInfoTables() int {
 	for i, char := range chars {
 		v := makeCharInfo(char)
 		if v != 0 {
-			t.insert(i, v)
+			t.insert(rune(i), v)
 		}
 	}
 	return t.printTables("charInfo")
@@ -606,7 +606,7 @@ func printDecompositionTables() int {
 	for _, c := range chars {
 		for f := 0; f < 2; f++ {
 			d := c.forms[f].expandedDecomp
-			s := string([]int(d))
+			s := string([]rune(d))
 			if _, ok := positionMap[s]; !ok {
 				p := decompositions.Len()
 				decompositions.WriteByte(uint8(len(s)))
@@ -624,7 +624,7 @@ func printDecompositionTables() int {
 	for i, c := range chars {
 		d := c.forms[FCanonical].expandedDecomp
 		if len(d) != 0 {
-			nfcT.insert(i, positionMap[string([]int(d))])
+			nfcT.insert(rune(i), positionMap[string([]rune(d))])
 			if ccc(c.codePoint) != ccc(d[0]) {
 				// We assume the lead ccc of a decomposition is !=0 in this case.
 				if ccc(d[0]) == 0 {
@@ -634,7 +634,7 @@ func printDecompositionTables() int {
 		}
 		d = c.forms[FCompatibility].expandedDecomp
 		if len(d) != 0 {
-			nfkcT.insert(i, positionMap[string([]int(d))])
+			nfkcT.insert(rune(i), positionMap[string([]rune(d))])
 			if ccc(c.codePoint) != ccc(d[0]) {
 				// We assume the lead ccc of a decomposition is !=0 in this case.
 				if ccc(d[0]) == 0 {
@@ -752,7 +752,7 @@ func verifyComputed() {
 	for i, c := range chars {
 		for _, f := range c.forms {
 			isNo := (f.quickCheck[MDecomposed] == QCNo)
-			if (len(f.decomp) > 0) != isNo && !isHangul(i) {
+			if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) {
 				log.Fatalf("%U: NF*D must be no if rune decomposes", i)
 			}
 
@@ -764,7 +764,7 @@ func verifyComputed() {
 	}
 }
 
-var qcRe = regexp.MustCompile(`^([0-9A-F\.]+) *; (NF.*_QC); ([YNM]) #.*$`)
+var qcRe = regexp.MustCompile(`([0-9A-F\.]+) *; (NF.*_QC); ([YNM]) #.*`)
 
 // Use values in DerivedNormalizationProps.txt to compare against the
 // values we computed.
@@ -782,7 +782,7 @@ func testDerived() {
 	for {
 		line, err := input.ReadString('\n')
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				break
 			}
 			logger.Fatal(err)
@@ -792,13 +792,13 @@ func testDerived() {
 			continue
 		}
 		rng := strings.Split(qc[1], "..")
-		i, err := strconv.Btoui64(rng[0], 16)
+		i, err := strconv.ParseUint(rng[0], 16, 64)
 		if err != nil {
 			log.Fatal(err)
 		}
 		j := i
 		if len(rng) > 1 {
-			j, err = strconv.Btoui64(rng[1], 16)
+			j, err = strconv.ParseUint(rng[1], 16, 64)
 			if err != nil {
 				log.Fatal(err)
 			}
diff --git a/src/pkg/exp/norm/maketesttables.go b/src/pkg/exp/norm/maketesttables.go
index fdcc114..20eb889 100644
--- a/src/pkg/exp/norm/maketesttables.go
+++ b/src/pkg/exp/norm/maketesttables.go
@@ -16,7 +16,7 @@ func main() {
 
 // We take the smallest, largest and an arbitrary value for each 
 // of the UTF-8 sequence lengths.
-var testRunes = []int{
+var testRunes = []rune{
 	0x01, 0x0C, 0x7F, // 1-byte sequences
 	0x80, 0x100, 0x7FF, // 2-byte sequences
 	0x800, 0x999, 0xFFFF, // 3-byte sequences
diff --git a/src/pkg/exp/norm/normalize.go b/src/pkg/exp/norm/normalize.go
index 0bbf254..3bd4047 100644
--- a/src/pkg/exp/norm/normalize.go
+++ b/src/pkg/exp/norm/normalize.go
@@ -5,7 +5,7 @@
 // Package norm contains types and functions for normalizing Unicode strings.
 package norm
 
-import "utf8"
+import "unicode/utf8"
 
 // A Form denotes a canonical representation of Unicode code points.
 // The Unicode-defined normalization and equivalence forms are:
@@ -34,37 +34,41 @@ const (
 
 // Bytes returns f(b). May return b if f(b) = b.
 func (f Form) Bytes(b []byte) []byte {
-	n := f.QuickSpan(b)
+	rb := reorderBuffer{}
+	rb.init(f, b)
+	n := quickSpan(&rb, 0)
 	if n == len(b) {
 		return b
 	}
 	out := make([]byte, n, len(b))
 	copy(out, b[0:n])
-	return f.Append(out, b[n:]...)
+	return doAppend(&rb, out, n)
 }
 
 // String returns f(s).
 func (f Form) String(s string) string {
-	n := f.QuickSpanString(s)
+	rb := reorderBuffer{}
+	rb.initString(f, s)
+	n := quickSpan(&rb, 0)
 	if n == len(s) {
 		return s
 	}
-	out := make([]byte, 0, len(s))
+	out := make([]byte, n, len(s))
 	copy(out, s[0:n])
-	return string(f.AppendString(out, s[n:]))
+	return string(doAppend(&rb, out, n))
 }
 
 // IsNormal returns true if b == f(b).
 func (f Form) IsNormal(b []byte) bool {
-	fd := formTable[f]
-	bp := quickSpan(fd, b)
+	rb := reorderBuffer{}
+	rb.init(f, b)
+	bp := quickSpan(&rb, 0)
 	if bp == len(b) {
 		return true
 	}
-	rb := reorderBuffer{f: *fd}
 	for bp < len(b) {
-		decomposeSegment(&rb, b[bp:])
-		if fd.composing {
+		decomposeSegment(&rb, bp)
+		if rb.f.composing {
 			rb.compose()
 		}
 		for i := 0; i < rb.nrune; i++ {
@@ -82,43 +86,75 @@ func (f Form) IsNormal(b []byte) bool {
 			}
 		}
 		rb.reset()
-		bp += quickSpan(fd, b[bp:])
+		bp = quickSpan(&rb, bp)
 	}
 	return true
 }
 
 // IsNormalString returns true if s == f(s).
 func (f Form) IsNormalString(s string) bool {
-	panic("not implemented")
+	rb := reorderBuffer{}
+	rb.initString(f, s)
+	bp := quickSpan(&rb, 0)
+	if bp == len(s) {
+		return true
+	}
+	for bp < len(s) {
+		decomposeSegment(&rb, bp)
+		if rb.f.composing {
+			rb.compose()
+		}
+		for i := 0; i < rb.nrune; i++ {
+			info := rb.rune[i]
+			if bp+int(info.size) > len(s) {
+				return false
+			}
+			p := info.pos
+			pe := p + info.size
+			for ; p < pe; p++ {
+				if s[bp] != rb.byte[p] {
+					return false
+				}
+				bp++
+			}
+		}
+		rb.reset()
+		bp = quickSpan(&rb, bp)
+	}
+	return true
 }
 
 // patchTail fixes a case where a rune may be incorrectly normalized
 // if it is followed by illegal continuation bytes. It returns the
-// patched buffer and the number of trailing continuation bytes that
-// have been dropped.
-func patchTail(rb *reorderBuffer, buf []byte) ([]byte, int) {
+// patched buffer and whether there were trailing continuation bytes.
+func patchTail(rb *reorderBuffer, buf []byte) ([]byte, bool) {
 	info, p := lastRuneStart(&rb.f, buf)
 	if p == -1 || info.size == 0 {
-		return buf, 0
+		return buf, false
 	}
 	end := p + int(info.size)
 	extra := len(buf) - end
 	if extra > 0 {
+		// Potentially allocating memory. However, this only
+		// happens with ill-formed UTF-8.
+		x := make([]byte, 0)
+		x = append(x, buf[len(buf)-extra:]...)
 		buf = decomposeToLastBoundary(rb, buf[:end])
 		if rb.f.composing {
 			rb.compose()
 		}
-		return rb.flush(buf), extra
+		buf = rb.flush(buf)
+		return append(buf, x...), true
 	}
-	return buf, 0
+	return buf, false
 }
 
-func appendQuick(f *formInfo, dst, src []byte) ([]byte, int) {
-	if len(src) == 0 {
-		return dst, 0
+func appendQuick(rb *reorderBuffer, dst []byte, i int) ([]byte, int) {
+	if rb.nsrc == i {
+		return dst, i
 	}
-	end := quickSpan(f, src)
-	return append(dst, src[:end]...), end
+	end := quickSpan(rb, i)
+	return rb.src.appendSlice(dst, i, end), end
 }
 
 // Append returns f(append(out, b...)).
@@ -127,32 +163,31 @@ func (f Form) Append(out []byte, src ...byte) []byte {
 	if len(src) == 0 {
 		return out
 	}
-	fd := formTable[f]
-	rb := &reorderBuffer{f: *fd}
-	return doAppend(rb, out, src)
+	rb := reorderBuffer{}
+	rb.init(f, src)
+	return doAppend(&rb, out, 0)
 }
 
-func doAppend(rb *reorderBuffer, out, src []byte) []byte {
+func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
+	src, n := rb.src, rb.nsrc
 	doMerge := len(out) > 0
-	p := 0
-	if !utf8.RuneStart(src[0]) {
+	if q := src.skipNonStarter(p); q > p {
 		// Move leading non-starters to destination.
-		for p++; p < len(src) && !utf8.RuneStart(src[p]); p++ {
-		}
-		out = append(out, src[:p]...)
-		buf, ndropped := patchTail(rb, out)
-		if ndropped > 0 {
-			out = append(buf, src[p-ndropped:p]...)
+		out = src.appendSlice(out, p, q)
+		buf, endsInError := patchTail(rb, out)
+		if endsInError {
+			out = buf
 			doMerge = false // no need to merge, ends with illegal UTF-8
 		} else {
 			out = decomposeToLastBoundary(rb, buf) // force decomposition
 		}
+		p = q
 	}
 	fd := &rb.f
 	if doMerge {
 		var info runeInfo
-		if p < len(src) {
-			info = fd.info(src[p:])
+		if p < n {
+			info = fd.info(src, p)
 			if p == 0 && !fd.boundaryBefore(fd, info) {
 				out = decomposeToLastBoundary(rb, out)
 			}
@@ -164,59 +199,64 @@ func doAppend(rb *reorderBuffer, out, src []byte) []byte {
 			out = rb.flush(out)
 			if info.size == 0 {
 				// Append incomplete UTF-8 encoding.
-				return append(out, src[p:]...)
+				return src.appendSlice(out, p, n)
 			}
 		}
 	}
 	if rb.nrune == 0 {
-		src = src[p:]
-		out, p = appendQuick(fd, out, src)
+		out, p = appendQuick(rb, out, p)
 	}
-	for n := 0; p < len(src); p += n {
-		p += decomposeSegment(rb, src[p:])
+	for p < n {
+		p = decomposeSegment(rb, p)
 		if fd.composing {
 			rb.compose()
 		}
 		out = rb.flush(out)
-		out, n = appendQuick(fd, out, src[p:])
+		out, p = appendQuick(rb, out, p)
 	}
 	return out
 }
 
 // AppendString returns f(append(out, []byte(s))).
 // The buffer out must be nil, empty, or equal to f(out).
-func (f Form) AppendString(out []byte, s string) []byte {
-	panic("not implemented")
+func (f Form) AppendString(out []byte, src string) []byte {
+	if len(src) == 0 {
+		return out
+	}
+	rb := reorderBuffer{}
+	rb.initString(f, src)
+	return doAppend(&rb, out, 0)
 }
 
 // QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]).
 // It is not guaranteed to return the largest such n.
 func (f Form) QuickSpan(b []byte) int {
-	return quickSpan(formTable[f], b)
+	rb := reorderBuffer{}
+	rb.init(f, b)
+	n := quickSpan(&rb, 0)
+	return n
 }
 
-func quickSpan(fd *formInfo, b []byte) int {
+func quickSpan(rb *reorderBuffer, i int) int {
 	var lastCC uint8
-	var lastSegStart int
-	var i, nc int
-	for i < len(b) {
-		if b[i] < utf8.RuneSelf {
-			// Keep the loop tight for ASCII processing, as this is where
-			// most of the time is spent for this case.
-			for i++; i < len(b) && b[i] < utf8.RuneSelf; i++ {
-			}
+	var nc int
+	lastSegStart := i
+	src, n := rb.src, rb.nsrc
+	for i < n {
+		if j := src.skipASCII(i); i != j {
+			i = j
 			lastSegStart = i - 1
 			lastCC = 0
 			nc = 0
 			continue
 		}
-		info := fd.info(b[i:])
+		info := rb.f.info(src, i)
 		if info.size == 0 {
 			// include incomplete runes
-			return len(b)
+			return n
 		}
 		cc := info.ccc
-		if fd.composing {
+		if rb.f.composing {
 			if !info.flags.isYesC() {
 				break
 			}
@@ -243,10 +283,10 @@ func quickSpan(fd *formInfo, b []byte) int {
 		lastCC = cc
 		i += int(info.size)
 	}
-	if i == len(b) {
-		return len(b)
+	if i == n {
+		return n
 	}
-	if fd.composing {
+	if rb.f.composing {
 		return lastSegStart
 	}
 	return i
@@ -255,32 +295,39 @@ func quickSpan(fd *formInfo, b []byte) int {
 // QuickSpanString returns a boundary n such that b[0:n] == f(s[0:n]).
 // It is not guaranteed to return the largest such n.
 func (f Form) QuickSpanString(s string) int {
-	panic("not implemented")
+	rb := reorderBuffer{}
+	rb.initString(f, s)
+	return quickSpan(&rb, 0)
 }
 
 // FirstBoundary returns the position i of the first boundary in b
 // or -1 if b contains no boundary.
 func (f Form) FirstBoundary(b []byte) int {
-	i := 0
-	for ; i < len(b) && !utf8.RuneStart(b[i]); i++ {
-	}
-	if i >= len(b) {
+	rb := reorderBuffer{}
+	rb.init(f, b)
+	return firstBoundary(&rb)
+}
+
+func firstBoundary(rb *reorderBuffer) int {
+	src, nsrc := rb.src, rb.nsrc
+	i := src.skipNonStarter(0)
+	if i >= nsrc {
 		return -1
 	}
-	fd := formTable[f]
-	info := fd.info(b[i:])
+	fd := &rb.f
+	info := fd.info(src, i)
 	for n := 0; info.size != 0 && !fd.boundaryBefore(fd, info); {
 		i += int(info.size)
 		if n++; n >= maxCombiningChars {
 			return i
 		}
-		if i >= len(b) {
+		if i >= nsrc {
 			if !fd.boundaryAfter(fd, info) {
 				return -1
 			}
-			return len(b)
+			return nsrc
 		}
-		info = fd.info(b[i:])
+		info = fd.info(src, i)
 	}
 	if info.size == 0 {
 		return -1
@@ -290,8 +337,10 @@ func (f Form) FirstBoundary(b []byte) int {
 
 // FirstBoundaryInString returns the position i of the first boundary in s
 // or -1 if s contains no boundary.
-func (f Form) FirstBoundaryInString(s string) (i int, ok bool) {
-	panic("not implemented")
+func (f Form) FirstBoundaryInString(s string) int {
+	rb := reorderBuffer{}
+	rb.initString(f, s)
+	return firstBoundary(&rb)
 }
 
 // LastBoundary returns the position i of the last boundary in b
@@ -339,29 +388,22 @@ func lastBoundary(fd *formInfo, b []byte) int {
 	return i
 }
 
-// LastBoundaryInString returns the position i of the last boundary in s
-// or -1 if s contains no boundary.
-func (f Form) LastBoundaryInString(s string) int {
-	panic("not implemented")
-}
-
 // decomposeSegment scans the first segment in src into rb.
 // It returns the number of bytes consumed from src.
 // TODO(mpvl): consider inserting U+034f (Combining Grapheme Joiner)
 // when we detect a sequence of 30+ non-starter chars.
-func decomposeSegment(rb *reorderBuffer, src []byte) int {
+func decomposeSegment(rb *reorderBuffer, sp int) int {
 	// Force one character to be consumed.
-	info := rb.f.info(src)
+	info := rb.f.info(rb.src, sp)
 	if info.size == 0 {
 		return 0
 	}
-	sp := 0
-	for rb.insert(src[sp:], info) {
+	for rb.insert(rb.src, sp, info) {
 		sp += int(info.size)
-		if sp >= len(src) {
+		if sp >= rb.nsrc {
 			break
 		}
-		info = rb.f.info(src[sp:])
+		info = rb.f.info(rb.src, sp)
 		bound := rb.f.boundaryBefore(&rb.f, info)
 		if bound || info.size == 0 {
 			break
@@ -379,7 +421,7 @@ func lastRuneStart(fd *formInfo, buf []byte) (runeInfo, int) {
 	if p < 0 {
 		return runeInfo{0, 0, 0, 0}, -1
 	}
-	return fd.info(buf[p:]), p
+	return fd.info(inputBytes(buf), p), p
 }
 
 // decomposeToLastBoundary finds an open segment at the end of the buffer
@@ -406,9 +448,9 @@ func decomposeToLastBoundary(rb *reorderBuffer, buf []byte) []byte {
 		}
 		// Check that decomposition doesn't result in overflow.
 		if info.flags.hasDecomposition() {
-			dcomp := rb.f.decompose(buf[p-int(info.size):])
+			dcomp := rb.f.decompose(inputBytes(buf), p-int(info.size))
 			for i := 0; i < len(dcomp); {
-				inf := rb.f.info(dcomp[i:])
+				inf := rb.f.info(inputBytes(dcomp), i)
 				i += int(inf.size)
 				n++
 			}
@@ -424,7 +466,7 @@ func decomposeToLastBoundary(rb *reorderBuffer, buf []byte) []byte {
 	pp := p
 	for padd--; padd >= 0; padd-- {
 		info = add[padd]
-		rb.insert(buf[pp:], info)
+		rb.insert(inputBytes(buf), pp, info)
 		pp += int(info.size)
 	}
 	return buf[:p]
diff --git a/src/pkg/exp/norm/normalize_test.go b/src/pkg/exp/norm/normalize_test.go
index 6e8650d..2e0c1f1 100644
--- a/src/pkg/exp/norm/normalize_test.go
+++ b/src/pkg/exp/norm/normalize_test.go
@@ -18,20 +18,23 @@ type PositionTest struct {
 type positionFunc func(rb *reorderBuffer, s string) int
 
 func runPosTests(t *testing.T, name string, f Form, fn positionFunc, tests []PositionTest) {
-	rb := reorderBuffer{f: *formTable[f]}
+	rb := reorderBuffer{}
+	rb.init(f, nil)
 	for i, test := range tests {
 		rb.reset()
+		rb.src = inputString(test.input)
+		rb.nsrc = len(test.input)
 		pos := fn(&rb, test.input)
 		if pos != test.pos {
 			t.Errorf("%s:%d: position is %d; want %d", name, i, pos, test.pos)
 		}
-		runes := []int(test.buffer)
+		runes := []rune(test.buffer)
 		if rb.nrune != len(runes) {
 			t.Errorf("%s:%d: reorder buffer lenght is %d; want %d", name, i, rb.nrune, len(runes))
 			continue
 		}
 		for j, want := range runes {
-			found := int(rb.runeAt(j))
+			found := rune(rb.runeAt(j))
 			if found != want {
 				t.Errorf("%s:%d: rune at %d is %U; want %U", name, i, j, found, want)
 			}
@@ -60,7 +63,9 @@ var decomposeSegmentTests = []PositionTest{
 }
 
 func decomposeSegmentF(rb *reorderBuffer, s string) int {
-	return decomposeSegment(rb, []byte(s))
+	rb.src = inputString(s)
+	rb.nsrc = len(s)
+	return decomposeSegment(rb, 0)
 }
 
 func TestDecomposeSegment(t *testing.T) {
@@ -90,12 +95,17 @@ var firstBoundaryTests = []PositionTest{
 	{strings.Repeat("\u0300", maxCombiningChars+1), 60, ""},
 }
 
-func firstBoundary(rb *reorderBuffer, s string) int {
+func firstBoundaryF(rb *reorderBuffer, s string) int {
 	return rb.f.form.FirstBoundary([]byte(s))
 }
 
+func firstBoundaryStringF(rb *reorderBuffer, s string) int {
+	return rb.f.form.FirstBoundaryInString(s)
+}
+
 func TestFirstBoundary(t *testing.T) {
-	runPosTests(t, "TestFirstBoundary", NFC, firstBoundary, firstBoundaryTests)
+	runPosTests(t, "TestFirstBoundary", NFC, firstBoundaryF, firstBoundaryTests)
+	runPosTests(t, "TestFirstBoundaryInString", NFC, firstBoundaryStringF, firstBoundaryTests)
 }
 
 var decomposeToLastTests = []PositionTest{
@@ -243,7 +253,7 @@ var quickSpanNFDTests = []PositionTest{
 	{"\u0316\u0300cd", 6, ""},
 	{"\u043E\u0308b", 5, ""},
 	// incorrectly ordered combining characters
-	{"ab\u0300\u0316", 1, ""}, // TODO(mpvl): we could skip 'b' as well.
+	{"ab\u0300\u0316", 1, ""}, // TODO: we could skip 'b' as well.
 	{"ab\u0300\u0316cd", 1, ""},
 	// Hangul
 	{"같은", 0, ""},
@@ -275,11 +285,20 @@ func doQuickSpan(rb *reorderBuffer, s string) int {
 	return rb.f.form.QuickSpan([]byte(s))
 }
 
+func doQuickSpanString(rb *reorderBuffer, s string) int {
+	return rb.f.form.QuickSpanString(s)
+}
+
 func TestQuickSpan(t *testing.T) {
 	runPosTests(t, "TestQuickSpanNFD1", NFD, doQuickSpan, quickSpanTests)
 	runPosTests(t, "TestQuickSpanNFD2", NFD, doQuickSpan, quickSpanNFDTests)
 	runPosTests(t, "TestQuickSpanNFC1", NFC, doQuickSpan, quickSpanTests)
 	runPosTests(t, "TestQuickSpanNFC2", NFC, doQuickSpan, quickSpanNFCTests)
+
+	runPosTests(t, "TestQuickSpanStringNFD1", NFD, doQuickSpanString, quickSpanTests)
+	runPosTests(t, "TestQuickSpanStringNFD2", NFD, doQuickSpanString, quickSpanNFDTests)
+	runPosTests(t, "TestQuickSpanStringNFC1", NFC, doQuickSpanString, quickSpanTests)
+	runPosTests(t, "TestQuickSpanStringNFC2", NFC, doQuickSpanString, quickSpanNFCTests)
 }
 
 var isNormalTests = []PositionTest{
@@ -334,7 +353,7 @@ var isNormalNFCTests = []PositionTest{
 	{"같은", 1, ""},
 }
 
-func isNormal(rb *reorderBuffer, s string) int {
+func isNormalF(rb *reorderBuffer, s string) int {
 	if rb.f.form.IsNormal([]byte(s)) {
 		return 1
 	}
@@ -342,10 +361,10 @@ func isNormal(rb *reorderBuffer, s string) int {
 }
 
 func TestIsNormal(t *testing.T) {
-	runPosTests(t, "TestIsNormalNFD1", NFD, isNormal, isNormalTests)
-	runPosTests(t, "TestIsNormalNFD2", NFD, isNormal, isNormalNFDTests)
-	runPosTests(t, "TestIsNormalNFC1", NFC, isNormal, isNormalTests)
-	runPosTests(t, "TestIsNormalNFC2", NFC, isNormal, isNormalNFCTests)
+	runPosTests(t, "TestIsNormalNFD1", NFD, isNormalF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFD2", NFD, isNormalF, isNormalNFDTests)
+	runPosTests(t, "TestIsNormalNFC1", NFC, isNormalF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFC2", NFC, isNormalF, isNormalNFCTests)
 }
 
 type AppendTest struct {
@@ -366,8 +385,8 @@ func runAppendTests(t *testing.T, name string, f Form, fn appendFunc, tests []Ap
 		}
 		if outs != test.out {
 			// Find first rune that differs and show context.
-			ir := []int(outs)
-			ig := []int(test.out)
+			ir := []rune(outs)
+			ig := []rune(test.out)
 			for j := 0; j < len(ir) && j < len(ig); j++ {
 				if ir[j] == ig[j] {
 					continue
@@ -446,14 +465,34 @@ var appendTests = []AppendTest{
 	{"\u0300", "\xFC\x80\x80\x80\x80\x80\u0300", "\u0300\xFC\x80\x80\x80\x80\x80\u0300"},
 	{"\xF8\x80\x80\x80\x80\u0300", "\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
 	{"\xFC\x80\x80\x80\x80\x80\u0300", "\u0300", "\xFC\x80\x80\x80\x80\x80\u0300\u0300"},
+	{"\xF8\x80\x80\x80", "\x80\u0300\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
 }
 
 func appendF(f Form, out []byte, s string) []byte {
 	return f.Append(out, []byte(s)...)
 }
 
+func appendStringF(f Form, out []byte, s string) []byte {
+	return f.AppendString(out, s)
+}
+
+func bytesF(f Form, out []byte, s string) []byte {
+	buf := []byte{}
+	buf = append(buf, out...)
+	buf = append(buf, s...)
+	return f.Bytes(buf)
+}
+
+func stringF(f Form, out []byte, s string) []byte {
+	outs := string(out) + s
+	return []byte(f.String(outs))
+}
+
 func TestAppend(t *testing.T) {
 	runAppendTests(t, "TestAppend", NFKC, appendF, appendTests)
+	runAppendTests(t, "TestAppendString", NFKC, appendStringF, appendTests)
+	runAppendTests(t, "TestBytes", NFKC, bytesF, appendTests)
+	runAppendTests(t, "TestString", NFKC, stringF, appendTests)
 }
 
 func doFormBenchmark(b *testing.B, f Form, s string) {
@@ -485,19 +524,15 @@ func BenchmarkNormalizeAsciiNFKD(b *testing.B) {
 
 func doTextBenchmark(b *testing.B, s string) {
 	b.StopTimer()
-	in := make([]byte, len(s))
-	for i := range s {
-		in[i] = s[i]
-	}
-	// Using copy(in, s) makes many tests much slower!?
 	b.SetBytes(int64(len(s)) * 4)
-	var buf = make([]byte, 2*len(in))
+	in := []byte(s)
+	var buf = make([]byte, 0, 2*len(in))
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
-		buf = NFC.Append(buf[0:0], in...)
-		buf = NFD.Append(buf[0:0], in...)
-		buf = NFKC.Append(buf[0:0], in...)
-		buf = NFKD.Append(buf[0:0], in...)
+		NFC.Append(buf, in...)
+		NFD.Append(buf, in...)
+		NFKC.Append(buf, in...)
+		NFKD.Append(buf, in...)
 	}
 }
 
diff --git a/src/pkg/exp/norm/normregtest.go b/src/pkg/exp/norm/normregtest.go
index 3ab10b7..57ba703 100644
--- a/src/pkg/exp/norm/normregtest.go
+++ b/src/pkg/exp/norm/normregtest.go
@@ -8,18 +8,19 @@ import (
 	"bufio"
 	"bytes"
 	"exp/norm"
-	"exp/regexp"
 	"flag"
 	"fmt"
-	"http"
+	"io"
 	"log"
+	"net/http"
 	"os"
 	"path"
+	"regexp"
 	"runtime"
-	"strings"
 	"strconv"
+	"strings"
 	"time"
-	"utf8"
+	"unicode/utf8"
 )
 
 func main() {
@@ -103,7 +104,7 @@ type Test struct {
 	name   string
 	partnr int
 	number int
-	rune   int                 // used for character by character test
+	r      rune                // used for character by character test
 	cols   [cMaxColumns]string // Each has 5 entries, see below.
 }
 
@@ -141,7 +142,7 @@ func loadTestData() {
 	for {
 		line, err := input.ReadString('\n')
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				break
 			}
 			logger.Fatal(err)
@@ -170,16 +171,16 @@ func loadTestData() {
 		counter++
 		for j := 1; j < len(m)-1; j++ {
 			for _, split := range strings.Split(m[j], " ") {
-				r, err := strconv.Btoui64(split, 16)
+				r, err := strconv.ParseUint(split, 16, 64)
 				if err != nil {
 					logger.Fatal(err)
 				}
-				if test.rune == 0 {
+				if test.r == 0 {
 					// save for CharacterByCharacterTests
-					test.rune = int(r)
+					test.r = rune(r)
 				}
 				var buf [utf8.UTFMax]byte
-				sz := utf8.EncodeRune(buf[:], int(r))
+				sz := utf8.EncodeRune(buf[:], rune(r))
 				test.cols[j-1] += string(buf[:sz])
 			}
 		}
@@ -198,7 +199,7 @@ func cmpResult(t *Test, name string, f norm.Form, gold, test, result string) {
 		if errorCount > 20 {
 			return
 		}
-		st, sr, sg := []int(test), []int(result), []int(gold)
+		st, sr, sg := []rune(test), []rune(result), []rune(gold)
 		logger.Printf("%s:%s: %s(%X)=%X; want:%X: %s",
 			t.Name(), name, fstr[f], st, sr, sg, t.name)
 	}
@@ -210,7 +211,7 @@ func cmpIsNormal(t *Test, name string, f norm.Form, test string, result, want bo
 		if errorCount > 20 {
 			return
 		}
-		logger.Printf("%s:%s: %s(%X)=%v; want: %v", t.Name(), name, fstr[f], []int(test), result, want)
+		logger.Printf("%s:%s: %s(%X)=%v; want: %v", t.Name(), name, fstr[f], []rune(test), result, want)
 	}
 }
 
@@ -241,15 +242,15 @@ func doConformanceTests(t *Test, partn int) {
 
 func CharacterByCharacterTests() {
 	tests := part[1].tests
-	last := 0
+	var last rune = 0
 	for i := 0; i <= len(tests); i++ { // last one is special case
-		var rune int
+		var r rune
 		if i == len(tests) {
-			rune = 0x2FA1E // Don't have to go to 0x10FFFF
+			r = 0x2FA1E // Don't have to go to 0x10FFFF
 		} else {
-			rune = tests[i].rune
+			r = tests[i].r
 		}
-		for last++; last < rune; last++ {
+		for last++; last < r; last++ {
 			// Check all characters that were not explicitly listed in the test.
 			t := &Test{partnr: 1, number: -1}
 			char := string(last)
@@ -280,11 +281,11 @@ func PerformanceTest() {
 	success := make(chan bool, 1)
 	go func() {
 		buf := bytes.Repeat([]byte("\u035D"), 1024*1024)
-		buf = append(buf, []byte("\u035B")...)
+		buf = append(buf, "\u035B"...)
 		norm.NFC.Append(nil, buf...)
 		success <- true
 	}()
-	timeout := time.After(1e9)
+	timeout := time.After(1 * time.Second)
 	select {
 	case <-success:
 		// test completed before the timeout
diff --git a/src/pkg/exp/norm/readwriter.go b/src/pkg/exp/norm/readwriter.go
index fce6c40..2682894 100644
--- a/src/pkg/exp/norm/readwriter.go
+++ b/src/pkg/exp/norm/readwriter.go
@@ -4,10 +4,7 @@
 
 package norm
 
-import (
-	"io"
-	"os"
-)
+import "io"
 
 type normWriter struct {
 	rb  reorderBuffer
@@ -18,7 +15,7 @@ type normWriter struct {
 // Write implements the standard write interface.  If the last characters are
 // not at a normalization boundary, the bytes will be buffered for the next
 // write. The remaining bytes will be written on close.
-func (w *normWriter) Write(data []byte) (n int, err os.Error) {
+func (w *normWriter) Write(data []byte) (n int, err error) {
 	// Process data in pieces to keep w.buf size bounded.
 	const chunk = 4000
 
@@ -28,7 +25,9 @@ func (w *normWriter) Write(data []byte) (n int, err os.Error) {
 		if m > chunk {
 			m = chunk
 		}
-		w.buf = doAppend(&w.rb, w.buf, data[:m])
+		w.rb.src = inputBytes(data[:m])
+		w.rb.nsrc = m
+		w.buf = doAppend(&w.rb, w.buf, 0)
 		data = data[m:]
 		n += m
 
@@ -50,7 +49,7 @@ func (w *normWriter) Write(data []byte) (n int, err os.Error) {
 }
 
 // Close forces data that remains in the buffer to be written.
-func (w *normWriter) Close() os.Error {
+func (w *normWriter) Close() error {
 	if len(w.buf) > 0 {
 		_, err := w.w.Write(w.buf)
 		if err != nil {
@@ -65,7 +64,9 @@ func (w *normWriter) Close() os.Error {
 // an internal buffer to maintain state across Write calls.
 // Calling its Close method writes any buffered data to w.
 func (f Form) Writer(w io.Writer) io.WriteCloser {
-	return &normWriter{rb: reorderBuffer{f: *formTable[f]}, w: w}
+	wr := &normWriter{rb: reorderBuffer{}, w: w}
+	wr.rb.init(f, nil)
+	return wr
 }
 
 type normReader struct {
@@ -75,11 +76,11 @@ type normReader struct {
 	outbuf       []byte
 	bufStart     int
 	lastBoundary int
-	err          os.Error
+	err          error
 }
 
 // Read implements the standard read interface.
-func (r *normReader) Read(p []byte) (int, os.Error) {
+func (r *normReader) Read(p []byte) (int, error) {
 	for {
 		if r.lastBoundary-r.bufStart > 0 {
 			n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
@@ -97,11 +98,12 @@ func (r *normReader) Read(p []byte) (int, os.Error) {
 		r.bufStart = 0
 
 		n, err := r.r.Read(r.inbuf)
-		r.err = err // save error for when done with buffer
+		r.rb.src = inputBytes(r.inbuf[0:n])
+		r.rb.nsrc, r.err = n, err
 		if n > 0 {
-			r.outbuf = doAppend(&r.rb, r.outbuf, r.inbuf[0:n])
+			r.outbuf = doAppend(&r.rb, r.outbuf, 0)
 		}
-		if err == os.EOF {
+		if err == io.EOF {
 			r.lastBoundary = len(r.outbuf)
 		} else {
 			r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
@@ -117,5 +119,8 @@ func (r *normReader) Read(p []byte) (int, os.Error) {
 // by reading data from r and returning f(data).
 func (f Form) Reader(r io.Reader) io.Reader {
 	const chunk = 4000
-	return &normReader{rb: reorderBuffer{f: *formTable[f]}, r: r, inbuf: make([]byte, chunk)}
+	buf := make([]byte, chunk)
+	rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
+	rr.rb.init(f, buf)
+	return rr
 }
diff --git a/src/pkg/exp/norm/readwriter_test.go b/src/pkg/exp/norm/readwriter_test.go
index b415f2b..3b49eb0 100644
--- a/src/pkg/exp/norm/readwriter_test.go
+++ b/src/pkg/exp/norm/readwriter_test.go
@@ -7,7 +7,6 @@ package norm
 import (
 	"bytes"
 	"fmt"
-	"os"
 	"strings"
 	"testing"
 )
@@ -23,11 +22,11 @@ var bufSizes = []int{1, 2, 3, 4, 5, 6, 7, 8, 100, 101, 102, 103, 4000, 4001, 400
 
 func readFunc(size int) appendFunc {
 	return func(f Form, out []byte, s string) []byte {
-		out = append(out, []byte(s)...)
+		out = append(out, s...)
 		r := f.Reader(bytes.NewBuffer(out))
 		buf := make([]byte, size)
 		result := []byte{}
-		for n, err := 0, os.Error(nil); err == nil; {
+		for n, err := 0, error(nil); err == nil; {
 			n, err = r.Read(buf)
 			result = append(result, buf[:n]...)
 		}
@@ -46,7 +45,7 @@ func TestReader(t *testing.T) {
 
 func writeFunc(size int) appendFunc {
 	return func(f Form, out []byte, s string) []byte {
-		in := append(out, []byte(s)...)
+		in := append(out, s...)
 		result := new(bytes.Buffer)
 		w := f.Writer(result)
 		buf := make([]byte, size)
diff --git a/src/pkg/exp/norm/tables.go b/src/pkg/exp/norm/tables.go
index 55ff052..9044a72 100644
--- a/src/pkg/exp/norm/tables.go
+++ b/src/pkg/exp/norm/tables.go
@@ -2804,12 +2804,12 @@ var nfcDecompSparseValues = [341]valueRange{
 	{value: 0x0005, lo: 0x01},
 	{value: 0x068d, lo: 0xa2, hi: 0xa6},
 	// Block 0xc, offset 0xd
-	{value: 0x0005, lo: 0x03},
+	{value: 0x0000, lo: 0x03},
 	{value: 0x06ba, lo: 0x80, hi: 0x80},
 	{value: 0x06bf, lo: 0x82, hi: 0x82},
 	{value: 0x06c4, lo: 0x93, hi: 0x93},
 	// Block 0xd, offset 0xe
-	{value: 0x0007, lo: 0x03},
+	{value: 0x0000, lo: 0x03},
 	{value: 0x06c9, lo: 0xa9, hi: 0xa9},
 	{value: 0x06d0, lo: 0xb1, hi: 0xb1},
 	{value: 0x06d7, lo: 0xb4, hi: 0xb4},
@@ -2822,7 +2822,7 @@ var nfcDecompSparseValues = [341]valueRange{
 	{value: 0x0724, lo: 0x9c, hi: 0x9d},
 	{value: 0x0732, lo: 0x9f, hi: 0x9f},
 	// Block 0x10, offset 0x11
-	{value: 0x0007, lo: 0x02},
+	{value: 0x0000, lo: 0x02},
 	{value: 0x0739, lo: 0xb3, hi: 0xb3},
 	{value: 0x0740, lo: 0xb6, hi: 0xb6},
 	// Block 0x11, offset 0x12
@@ -2868,7 +2868,7 @@ var nfcDecompSparseValues = [341]valueRange{
 	{value: 0x0854, lo: 0xb5, hi: 0xb6},
 	{value: 0x086c, lo: 0xb8, hi: 0xb8},
 	// Block 0x1a, offset 0x1b
-	{value: 0x0007, lo: 0x07},
+	{value: 0x0000, lo: 0x07},
 	{value: 0x087d, lo: 0x81, hi: 0x81},
 	{value: 0x0884, lo: 0x93, hi: 0x93},
 	{value: 0x088b, lo: 0x9d, hi: 0x9d},
@@ -2880,7 +2880,7 @@ var nfcDecompSparseValues = [341]valueRange{
 	{value: 0x0000, lo: 0x01},
 	{value: 0x08ae, lo: 0xa6, hi: 0xa6},
 	// Block 0x1c, offset 0x1d
-	{value: 0x0007, lo: 0x08},
+	{value: 0x0000, lo: 0x08},
 	{value: 0x08b9, lo: 0x86, hi: 0x86},
 	{value: 0x08c0, lo: 0x88, hi: 0x88},
 	{value: 0x08c7, lo: 0x8a, hi: 0x8a},
@@ -2924,7 +2924,7 @@ var nfcDecompSparseValues = [341]valueRange{
 	{value: 0x0006, lo: 0x01},
 	{value: 0x15b1, lo: 0x8d, hi: 0x8f},
 	// Block 0x23, offset 0x24
-	{value: 0x0006, lo: 0x05},
+	{value: 0x0000, lo: 0x05},
 	{value: 0x15c3, lo: 0x84, hi: 0x84},
 	{value: 0x15c9, lo: 0x89, hi: 0x89},
 	{value: 0x15cf, lo: 0x8c, hi: 0x8c},
@@ -2960,7 +2960,7 @@ var nfcDecompSparseValues = [341]valueRange{
 	{value: 0x0000, lo: 0x01},
 	{value: 0x1814, lo: 0x9c, hi: 0x9c},
 	// Block 0x29, offset 0x2a
-	{value: 0x0007, lo: 0x0c},
+	{value: 0x0000, lo: 0x0c},
 	{value: 0x1c39, lo: 0x94, hi: 0x94},
 	{value: 0x1c4a, lo: 0x9e, hi: 0x9e},
 	{value: 0x1c58, lo: 0xac, hi: 0xac},
@@ -3084,7 +3084,7 @@ var nfcDecompSparseValues = [341]valueRange{
 	{value: 0x3191, lo: 0x83, hi: 0x84},
 	{value: 0x319b, lo: 0x86, hi: 0x8e},
 	// Block 0x33, offset 0x34
-	{value: 0x0009, lo: 0x03},
+	{value: 0x0000, lo: 0x03},
 	{value: 0x3a73, lo: 0x9a, hi: 0x9a},
 	{value: 0x3a7c, lo: 0x9c, hi: 0x9c},
 	{value: 0x3a85, lo: 0xab, hi: 0xab},
@@ -3897,10 +3897,10 @@ var nfkcDecompValues = [4224]uint16{
 }
 
 // nfkcDecompSparseOffset: 93 entries, 186 bytes
-var nfkcDecompSparseOffset = []uint16{0x0, 0xc, 0x16, 0x1e, 0x24, 0x27, 0x31, 0x37, 0x3e, 0x44, 0x4c, 0x59, 0x60, 0x66, 0x6e, 0x70, 0x72, 0x74, 0x78, 0x7c, 0x7e, 0x82, 0x85, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x96, 0x98, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xae, 0xb6, 0xb8, 0xba, 0xc3, 0xc6, 0xcd, 0xd8, 0xe6, 0xf4, 0xfe, 0x102, 0x104, 0x10e, 0x11a, 0x11f, 0x122, 0x124, 0x126, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x139, 0x13b, 0x140, 0x14f, 0x15d, 0x15f, 0x161, 0x169, 0x179, 0x17b, 0x186, 0x18d, 0x198, 0x1a4, 0x1b5, 0x1c6, 0x1cd, 0x1de, 0x1ec, 0x1fa, 0x209, 0x21a, 0x21f, 0x22c, 0x230, 0x234, 0x238, 0x23a, 0x249, 0x24b, 0x24f}
+var nfkcDecompSparseOffset = []uint16{0x0, 0xc, 0x16, 0x1e, 0x24, 0x27, 0x31, 0x37, 0x3e, 0x44, 0x4c, 0x59, 0x60, 0x66, 0x6e, 0x70, 0x72, 0x74, 0x78, 0x7c, 0x7e, 0x82, 0x85, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x96, 0x98, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xae, 0xb6, 0xb8, 0xba, 0xc3, 0xc6, 0xcd, 0xd8, 0xe6, 0xf4, 0xfe, 0x102, 0x104, 0x10c, 0x118, 0x11d, 0x120, 0x122, 0x124, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x139, 0x13e, 0x14d, 0x15b, 0x15d, 0x15f, 0x167, 0x177, 0x179, 0x184, 0x18b, 0x196, 0x1a2, 0x1b3, 0x1c4, 0x1cb, 0x1dc, 0x1ea, 0x1f8, 0x207, 0x218, 0x21d, 0x22a, 0x22e, 0x232, 0x236, 0x238, 0x247, 0x249, 0x24d}
 
-// nfkcDecompSparseValues: 605 entries, 2420 bytes
-var nfkcDecompSparseValues = [605]valueRange{
+// nfkcDecompSparseValues: 603 entries, 2412 bytes
+var nfkcDecompSparseValues = [603]valueRange{
 	// Block 0x0, offset 0x1
 	{value: 0x0002, lo: 0x0b},
 	{value: 0x0001, lo: 0xa0, hi: 0xa0},
@@ -4035,12 +4035,12 @@ var nfkcDecompSparseValues = [605]valueRange{
 	{value: 0x0005, lo: 0x01},
 	{value: 0x06a6, lo: 0xb5, hi: 0xb8},
 	// Block 0x11, offset 0x12
-	{value: 0x0005, lo: 0x03},
+	{value: 0x0000, lo: 0x03},
 	{value: 0x06ba, lo: 0x80, hi: 0x80},
 	{value: 0x06bf, lo: 0x82, hi: 0x82},
 	{value: 0x06c4, lo: 0x93, hi: 0x93},
 	// Block 0x12, offset 0x13
-	{value: 0x0007, lo: 0x03},
+	{value: 0x0000, lo: 0x03},
 	{value: 0x06c9, lo: 0xa9, hi: 0xa9},
 	{value: 0x06d0, lo: 0xb1, hi: 0xb1},
 	{value: 0x06d7, lo: 0xb4, hi: 0xb4},
@@ -4053,7 +4053,7 @@ var nfkcDecompSparseValues = [605]valueRange{
 	{value: 0x0724, lo: 0x9c, hi: 0x9d},
 	{value: 0x0732, lo: 0x9f, hi: 0x9f},
 	// Block 0x15, offset 0x16
-	{value: 0x0007, lo: 0x02},
+	{value: 0x0000, lo: 0x02},
 	{value: 0x0739, lo: 0xb3, hi: 0xb3},
 	{value: 0x0740, lo: 0xb6, hi: 0xb6},
 	// Block 0x16, offset 0x17
@@ -4111,7 +4111,7 @@ var nfkcDecompSparseValues = [605]valueRange{
 	{value: 0x0854, lo: 0xb5, hi: 0xb7},
 	{value: 0x086c, lo: 0xb8, hi: 0xb9},
 	// Block 0x23, offset 0x24
-	{value: 0x0007, lo: 0x07},
+	{value: 0x0000, lo: 0x07},
 	{value: 0x087d, lo: 0x81, hi: 0x81},
 	{value: 0x0884, lo: 0x93, hi: 0x93},
 	{value: 0x088b, lo: 0x9d, hi: 0x9d},
@@ -4126,7 +4126,7 @@ var nfkcDecompSparseValues = [605]valueRange{
 	{value: 0x0000, lo: 0x01},
 	{value: 0x08b5, lo: 0xbc, hi: 0xbc},
 	// Block 0x26, offset 0x27
-	{value: 0x0007, lo: 0x08},
+	{value: 0x0000, lo: 0x08},
 	{value: 0x08b9, lo: 0x86, hi: 0x86},
 	{value: 0x08c0, lo: 0x88, hi: 0x88},
 	{value: 0x08c7, lo: 0x8a, hi: 0x8a},
@@ -4209,16 +4209,14 @@ var nfkcDecompSparseValues = [605]valueRange{
 	{value: 0x0006, lo: 0x01},
 	{value: 0x15b1, lo: 0x8d, hi: 0x8f},
 	// Block 0x2f, offset 0x30
-	{value: 0x0006, lo: 0x09},
+	{value: 0x0007, lo: 0x07},
 	{value: 0x15c3, lo: 0x84, hi: 0x84},
 	{value: 0x15c9, lo: 0x89, hi: 0x89},
 	{value: 0x15cf, lo: 0x8c, hi: 0x8c},
 	{value: 0x15d5, lo: 0xa4, hi: 0xa4},
 	{value: 0x15db, lo: 0xa6, hi: 0xa6},
-	{value: 0x15e1, lo: 0xac, hi: 0xac},
-	{value: 0x15e8, lo: 0xad, hi: 0xad},
-	{value: 0x15f2, lo: 0xaf, hi: 0xaf},
-	{value: 0x15f9, lo: 0xb0, hi: 0xb0},
+	{value: 0x15e1, lo: 0xac, hi: 0xad},
+	{value: 0x15f2, lo: 0xaf, hi: 0xb0},
 	// Block 0x30, offset 0x31
 	{value: 0x0006, lo: 0x0b},
 	{value: 0x1603, lo: 0x81, hi: 0x81},
@@ -4249,9 +4247,9 @@ var nfkcDecompSparseValues = [605]valueRange{
 	{value: 0x0000, lo: 0x01},
 	{value: 0x17fc, lo: 0x8c, hi: 0x8c},
 	// Block 0x35, offset 0x36
-	{value: 0x0004, lo: 0x02},
-	{value: 0x1809, lo: 0xb4, hi: 0xb5},
-	{value: 0x1810, lo: 0xb6, hi: 0xb6},
+	{value: 0x0003, lo: 0x02},
+	{value: 0x1809, lo: 0xb4, hi: 0xb4},
+	{value: 0x180d, lo: 0xb5, hi: 0xb6},
 	// Block 0x36, offset 0x37
 	{value: 0x0000, lo: 0x01},
 	{value: 0x1814, lo: 0x9c, hi: 0x9c},
@@ -4280,17 +4278,17 @@ var nfkcDecompSparseValues = [605]valueRange{
 	{value: 0x0004, lo: 0x01},
 	{value: 0x1b26, lo: 0x80, hi: 0x95},
 	// Block 0x3f, offset 0x40
-	{value: 0x0300, lo: 0x04},
+	{value: 0x0004, lo: 0x04},
 	{value: 0x0001, lo: 0x80, hi: 0x80},
 	{value: 0x1b7e, lo: 0xb6, hi: 0xb6},
-	{value: 0x1882, lo: 0xb8, hi: 0xb9},
-	{value: 0x1b86, lo: 0xba, hi: 0xba},
+	{value: 0x1882, lo: 0xb8, hi: 0xb8},
+	{value: 0x1b82, lo: 0xb9, hi: 0xba},
 	// Block 0x40, offset 0x41
-	{value: 0x0007, lo: 0x0e},
+	{value: 0x0005, lo: 0x0e},
 	{value: 0x1c39, lo: 0x94, hi: 0x94},
-	{value: 0x1c40, lo: 0x9b, hi: 0x9b},
-	{value: 0x1c45, lo: 0x9c, hi: 0x9c},
-	{value: 0x1c4a, lo: 0x9e, hi: 0x9f},
+	{value: 0x1c40, lo: 0x9b, hi: 0x9c},
+	{value: 0x1c4a, lo: 0x9e, hi: 0x9e},
+	{value: 0x1c51, lo: 0x9f, hi: 0x9f},
 	{value: 0x1c58, lo: 0xac, hi: 0xac},
 	{value: 0x1c5f, lo: 0xae, hi: 0xae},
 	{value: 0x1c66, lo: 0xb0, hi: 0xb0},
@@ -4543,7 +4541,7 @@ var nfkcDecompSparseValues = [605]valueRange{
 	{value: 0x3a53, lo: 0xa6, hi: 0xa6},
 	{value: 0x3a57, lo: 0xa8, hi: 0xae},
 	// Block 0x55, offset 0x56
-	{value: 0x0009, lo: 0x03},
+	{value: 0x0000, lo: 0x03},
 	{value: 0x3a73, lo: 0x9a, hi: 0x9a},
 	{value: 0x3a7c, lo: 0x9c, hi: 0x9c},
 	{value: 0x3a85, lo: 0xab, hi: 0xab},
@@ -5760,10 +5758,10 @@ var charInfoValues = [1024]uint16{
 }
 
 // charInfoSparseOffset: 156 entries, 312 bytes
-var charInfoSparseOffset = []uint16{0x0, 0x8, 0x13, 0x21, 0x25, 0x2f, 0x36, 0x39, 0x3c, 0x4a, 0x56, 0x58, 0x62, 0x67, 0x6e, 0x7d, 0x8a, 0x92, 0x96, 0x9b, 0x9d, 0xa5, 0xab, 0xae, 0xb5, 0xb9, 0xbd, 0xbf, 0xc1, 0xc8, 0xcc, 0xd1, 0xd7, 0xda, 0xe3, 0xe5, 0xed, 0xf1, 0xf3, 0xf6, 0xf9, 0xff, 0x10f, 0x11b, 0x11d, 0x123, 0x125, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x134, 0x137, 0x139, 0x13c, 0x13f, 0x143, 0x152, 0x15a, 0x15c, 0x15f, 0x161, 0x16a, 0x16e, 0x172, 0x174, 0x183, 0x187, 0x18d, 0x195, 0x199, 0x1a2, 0x1ab, 0x1b6, 0x1bc, 0x1c0, 0x1ce, 0x1dd, 0x1e1, 0x1e8, 0x1ed, 0x1fc, 0x208, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21d, 0x220, 0x222, 0x224, 0x226, 0x228, 0x231, 0x233, 0x236, 0x239, 0x23c, 0x23e, 0x241, 0x243, 0x245, 0x247, 0x24a, 0x24c, 0x24e, 0x250, 0x252, 0x258, 0x25a, 0x25c, 0x25e, 0x260, 0x262, 0x26c, 0x26f, 0x271, 0x27b, 0x280, 0x282, 0x284, 0x286, 0x288, 0x28b, 0x28e, 0x292, 0x29a, 0x29c, 0x29e, 0x2a5, 0x2a7, 0x2ae, 0x2b6, 0x2bd, 0x2c3, 0x2c5, 0x2c7, 0x2ca, 0x2d3, 0x2d6, 0x2dd, 0x2e2, 0x2e5, 0x2e8, 0x2ec, 0x2ee, 0x2f0, 0x2f3, 0x2f6}
+var charInfoSparseOffset = []uint16{0x0, 0x8, 0x13, 0x21, 0x25, 0x2f, 0x36, 0x39, 0x3c, 0x4a, 0x56, 0x58, 0x62, 0x67, 0x6e, 0x7d, 0x8a, 0x92, 0x96, 0x9b, 0x9d, 0xa5, 0xab, 0xae, 0xb5, 0xb9, 0xbd, 0xbf, 0xc1, 0xc8, 0xcc, 0xd1, 0xd6, 0xd9, 0xe2, 0xe4, 0xec, 0xf0, 0xf2, 0xf5, 0xf8, 0xfe, 0x10e, 0x11a, 0x11c, 0x122, 0x124, 0x126, 0x128, 0x12a, 0x12c, 0x12e, 0x130, 0x133, 0x136, 0x138, 0x13b, 0x13e, 0x142, 0x151, 0x159, 0x15b, 0x15e, 0x160, 0x169, 0x16d, 0x171, 0x173, 0x182, 0x186, 0x18c, 0x194, 0x198, 0x1a1, 0x1aa, 0x1b5, 0x1bb, 0x1bf, 0x1cd, 0x1dc, 0x1e0, 0x1e7, 0x1ec, 0x1fa, 0x206, 0x209, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21e, 0x220, 0x222, 0x224, 0x226, 0x22f, 0x231, 0x234, 0x237, 0x23a, 0x23c, 0x23f, 0x241, 0x243, 0x245, 0x248, 0x24a, 0x24c, 0x24e, 0x250, 0x256, 0x258, 0x25a, 0x25c, 0x25e, 0x260, 0x26a, 0x26d, 0x26f, 0x279, 0x27e, 0x280, 0x282, 0x284, 0x286, 0x289, 0x28c, 0x290, 0x298, 0x29a, 0x29c, 0x2a3, 0x2a5, 0x2ab, 0x2b3, 0x2ba, 0x2c0, 0x2c2, 0x2c4, 0x2c7, 0x2d0, 0x2d3, 0x2da, 0x2df, 0x2e2, 0x2e5, 0x2e9, 0x2eb, 0x2ed, 0x2f0, 0x2f3}
 
-// charInfoSparseValues: 760 entries, 3040 bytes
-var charInfoSparseValues = [760]valueRange{
+// charInfoSparseValues: 757 entries, 3028 bytes
+var charInfoSparseValues = [757]valueRange{
 	// Block 0x0, offset 0x1
 	{value: 0x0000, lo: 0x07},
 	{value: 0x3000, lo: 0xa0, hi: 0xa0},
@@ -5942,7 +5940,7 @@ var charInfoSparseValues = [760]valueRange{
 	{value: 0x0000, lo: 0x01},
 	{value: 0x00dc, lo: 0x99, hi: 0x9b},
 	// Block 0x14, offset 0x15
-	{value: 0x7700, lo: 0x07},
+	{value: 0x0000, lo: 0x07},
 	{value: 0x8800, lo: 0xa8, hi: 0xa8},
 	{value: 0x1100, lo: 0xa9, hi: 0xa9},
 	{value: 0x8800, lo: 0xb0, hi: 0xb0},
@@ -5958,7 +5956,7 @@ var charInfoSparseValues = [760]valueRange{
 	{value: 0x00e6, lo: 0x93, hi: 0x94},
 	{value: 0x3300, lo: 0x98, hi: 0x9f},
 	// Block 0x16, offset 0x17
-	{value: 0x65f9, lo: 0x02},
+	{value: 0x0000, lo: 0x02},
 	{value: 0x0007, lo: 0xbc, hi: 0xbc},
 	{value: 0x6600, lo: 0xbe, hi: 0xbe},
 	// Block 0x17, offset 0x18
@@ -5994,7 +5992,7 @@ var charInfoSparseValues = [760]valueRange{
 	{value: 0x6600, lo: 0x96, hi: 0x97},
 	{value: 0x3300, lo: 0x9c, hi: 0x9d},
 	// Block 0x1d, offset 0x1e
-	{value: 0x5500, lo: 0x03},
+	{value: 0x0000, lo: 0x03},
 	{value: 0x8800, lo: 0x92, hi: 0x92},
 	{value: 0x1100, lo: 0x94, hi: 0x94},
 	{value: 0x6600, lo: 0xbe, hi: 0xbe},
@@ -6005,14 +6003,13 @@ var charInfoSparseValues = [760]valueRange{
 	{value: 0x0009, lo: 0x8d, hi: 0x8d},
 	{value: 0x6600, lo: 0x97, hi: 0x97},
 	// Block 0x1f, offset 0x20
-	{value: 0x004b, lo: 0x05},
+	{value: 0x6607, lo: 0x04},
 	{value: 0x8800, lo: 0x86, hi: 0x86},
 	{value: 0x1100, lo: 0x88, hi: 0x88},
 	{value: 0x0009, lo: 0x8d, hi: 0x8d},
-	{value: 0x0054, lo: 0x95, hi: 0x95},
-	{value: 0x665b, lo: 0x96, hi: 0x96},
+	{value: 0x0054, lo: 0x95, hi: 0x96},
 	// Block 0x20, offset 0x21
-	{value: 0x87f9, lo: 0x02},
+	{value: 0x0000, lo: 0x02},
 	{value: 0x0007, lo: 0xbc, hi: 0xbc},
 	{value: 0x8800, lo: 0xbf, hi: 0xbf},
 	// Block 0x21, offset 0x22
@@ -6126,7 +6123,7 @@ var charInfoSparseValues = [760]valueRange{
 	{value: 0x0009, lo: 0x94, hi: 0x94},
 	{value: 0x0009, lo: 0xb4, hi: 0xb4},
 	// Block 0x35, offset 0x36
-	{value: 0x00dd, lo: 0x02},
+	{value: 0x0000, lo: 0x02},
 	{value: 0x0009, lo: 0x92, hi: 0x92},
 	{value: 0x00e6, lo: 0x9d, hi: 0x9d},
 	// Block 0x36, offset 0x37
@@ -6340,7 +6337,7 @@ var charInfoSparseValues = [760]valueRange{
 	{value: 0x8800, lo: 0x92, hi: 0x92},
 	{value: 0x8800, lo: 0x94, hi: 0x94},
 	// Block 0x52, offset 0x53
-	{value: 0x7700, lo: 0x0e},
+	{value: 0x0000, lo: 0x0d},
 	{value: 0x8800, lo: 0x83, hi: 0x83},
 	{value: 0x1100, lo: 0x84, hi: 0x84},
 	{value: 0x8800, lo: 0x88, hi: 0x88},
@@ -6348,12 +6345,11 @@ var charInfoSparseValues = [760]valueRange{
 	{value: 0x8800, lo: 0x8b, hi: 0x8b},
 	{value: 0x1100, lo: 0x8c, hi: 0x8c},
 	{value: 0x8800, lo: 0xa3, hi: 0xa3},
-	{value: 0x1100, lo: 0xa4, hi: 0xa5},
+	{value: 0x1100, lo: 0xa4, hi: 0xa4},
+	{value: 0x8800, lo: 0xa5, hi: 0xa5},
 	{value: 0x1100, lo: 0xa6, hi: 0xa6},
-	{value: 0x3000, lo: 0xac, hi: 0xac},
-	{value: 0x3000, lo: 0xad, hi: 0xad},
-	{value: 0x3000, lo: 0xaf, hi: 0xaf},
-	{value: 0x3000, lo: 0xb0, hi: 0xb0},
+	{value: 0x3000, lo: 0xac, hi: 0xad},
+	{value: 0x3000, lo: 0xaf, hi: 0xb0},
 	{value: 0x8800, lo: 0xbc, hi: 0xbc},
 	// Block 0x53, offset 0x54
 	{value: 0x0000, lo: 0x0b},
@@ -6581,22 +6577,21 @@ var charInfoSparseValues = [760]valueRange{
 	{value: 0x0000, lo: 0x01},
 	{value: 0x00dc, lo: 0xbd, hi: 0xbd},
 	// Block 0x89, offset 0x8a
-	{value: 0x0000, lo: 0x06},
+	{value: 0x00db, lo: 0x05},
 	{value: 0x00dc, lo: 0x8d, hi: 0x8d},
 	{value: 0x00e6, lo: 0x8f, hi: 0x8f},
 	{value: 0x00e6, lo: 0xb8, hi: 0xb8},
-	{value: 0x0001, lo: 0xb9, hi: 0xb9},
-	{value: 0x00dc, lo: 0xba, hi: 0xba},
+	{value: 0x0001, lo: 0xb9, hi: 0xba},
 	{value: 0x0009, lo: 0xbf, hi: 0xbf},
 	// Block 0x8a, offset 0x8b
-	{value: 0x7700, lo: 0x07},
+	{value: 0x65fe, lo: 0x07},
 	{value: 0x8800, lo: 0x99, hi: 0x99},
-	{value: 0x1100, lo: 0x9a, hi: 0x9b},
+	{value: 0x1100, lo: 0x9a, hi: 0x9a},
+	{value: 0x8800, lo: 0x9b, hi: 0x9b},
 	{value: 0x1100, lo: 0x9c, hi: 0x9c},
 	{value: 0x8800, lo: 0xa5, hi: 0xa5},
 	{value: 0x1100, lo: 0xab, hi: 0xab},
-	{value: 0x0009, lo: 0xb9, hi: 0xb9},
-	{value: 0x6607, lo: 0xba, hi: 0xba},
+	{value: 0x0009, lo: 0xb9, hi: 0xba},
 	// Block 0x8b, offset 0x8c
 	{value: 0x0000, lo: 0x06},
 	{value: 0x3300, lo: 0x9e, hi: 0xa4},
@@ -6768,4 +6763,4 @@ var charInfoLookup = [1152]uint8{
 
 var charInfoTrie = trie{charInfoLookup[:], charInfoValues[:], charInfoSparseValues[:], charInfoSparseOffset[:], 16}
 
-// Total size of tables: 48KB (48756 bytes)
+// Total size of tables: 48KB (48736 bytes)
diff --git a/src/pkg/exp/norm/trie_test.go b/src/pkg/exp/norm/trie_test.go
index 5649fb7..c457c9d 100644
--- a/src/pkg/exp/norm/trie_test.go
+++ b/src/pkg/exp/norm/trie_test.go
@@ -1,8 +1,12 @@
+// Copyright 2011 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 norm
 
 import (
 	"testing"
-	"utf8"
+	"unicode/utf8"
 )
 
 // Test data is located in triedata_test.go; generated by maketesttables.
@@ -73,15 +77,15 @@ var tests = []trietest{
 	{1, []byte{t6, tx, tx, tx, tx, tx}},
 }
 
-func mkUtf8(rune int) ([]byte, int) {
+func mkUTF8(r rune) ([]byte, int) {
 	var b [utf8.UTFMax]byte
-	sz := utf8.EncodeRune(b[:], rune)
+	sz := utf8.EncodeRune(b[:], r)
 	return b[:sz], sz
 }
 
 func TestLookup(t *testing.T) {
 	for i, tt := range testRunes {
-		b, szg := mkUtf8(tt)
+		b, szg := mkUTF8(tt)
 		v, szt := testdata.lookup(b)
 		if int(v) != i {
 			t.Errorf("lookup(%U): found value %#x, expected %#x", tt, v, i)
@@ -103,7 +107,7 @@ func TestLookup(t *testing.T) {
 
 func TestLookupUnsafe(t *testing.T) {
 	for i, tt := range testRunes {
-		b, _ := mkUtf8(tt)
+		b, _ := mkUTF8(tt)
 		v := testdata.lookupUnsafe(b)
 		if int(v) != i {
 			t.Errorf("lookupUnsafe(%U): found value %#x, expected %#x", i, v, i)
@@ -113,7 +117,7 @@ func TestLookupUnsafe(t *testing.T) {
 
 func TestLookupString(t *testing.T) {
 	for i, tt := range testRunes {
-		b, szg := mkUtf8(tt)
+		b, szg := mkUTF8(tt)
 		v, szt := testdata.lookupString(string(b))
 		if int(v) != i {
 			t.Errorf("lookup(%U): found value %#x, expected %#x", i, v, i)
@@ -135,7 +139,7 @@ func TestLookupString(t *testing.T) {
 
 func TestLookupStringUnsafe(t *testing.T) {
 	for i, tt := range testRunes {
-		b, _ := mkUtf8(tt)
+		b, _ := mkUTF8(tt)
 		v := testdata.lookupStringUnsafe(string(b))
 		if int(v) != i {
 			t.Errorf("lookupUnsafe(%U): found value %#x, expected %#x", i, v, i)
diff --git a/src/pkg/exp/norm/triedata_test.go b/src/pkg/exp/norm/triedata_test.go
index e8898e5..7f62760 100644
--- a/src/pkg/exp/norm/triedata_test.go
+++ b/src/pkg/exp/norm/triedata_test.go
@@ -4,7 +4,7 @@
 
 package norm
 
-var testRunes = []int{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111, 512, 513, 514, 528, 533}
+var testRunes = []rune{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111, 512, 513, 514, 528, 533}
 
 // testdataValues: 192 entries, 384 bytes
 // Block 2 is the null block.
diff --git a/src/pkg/exp/norm/triegen.go b/src/pkg/exp/norm/triegen.go
index 515e1c7..4ad9e0e 100644
--- a/src/pkg/exp/norm/triegen.go
+++ b/src/pkg/exp/norm/triegen.go
@@ -14,7 +14,7 @@ import (
 	"fmt"
 	"hash/crc32"
 	"log"
-	"utf8"
+	"unicode/utf8"
 )
 
 const blockSize = 64
@@ -65,11 +65,13 @@ func (n trieNode) mostFrequentStride() int {
 				counts[stride]++
 			}
 			v = t.value
+		} else {
+			v = 0
 		}
 	}
 	var maxs, maxc int
 	for stride, cnt := range counts {
-		if cnt > maxc {
+		if cnt > maxc || (cnt == maxc && stride < maxs) {
 			maxs, maxc = stride, cnt
 		}
 	}
@@ -94,9 +96,9 @@ func (n trieNode) countSparseEntries() int {
 	return count
 }
 
-func (n *trieNode) insert(rune int, value uint16) {
+func (n *trieNode) insert(r rune, value uint16) {
 	var p [utf8.UTFMax]byte
-	sz := utf8.EncodeRune(p[:], rune)
+	sz := utf8.EncodeRune(p[:], r)
 
 	for i := 0; i < sz; i++ {
 		if n.leaf {
diff --git a/src/pkg/exp/proxy/Makefile b/src/pkg/exp/proxy/Makefile
new file mode 100644
index 0000000..7067de1
--- /dev/null
+++ b/src/pkg/exp/proxy/Makefile
@@ -0,0 +1,14 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=exp/proxy
+GOFILES=\
+	direct.go\
+	per_host.go\
+	proxy.go\
+	socks5.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/exp/proxy/direct.go b/src/pkg/exp/proxy/direct.go
new file mode 100644
index 0000000..4c5ad88
--- /dev/null
+++ b/src/pkg/exp/proxy/direct.go
@@ -0,0 +1,18 @@
+// Copyright 2011 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 proxy
+
+import (
+	"net"
+)
+
+type direct struct{}
+
+// Direct is a direct proxy: one that makes network connections directly.
+var Direct = direct{}
+
+func (direct) Dial(network, addr string) (net.Conn, error) {
+	return net.Dial(network, addr)
+}
diff --git a/src/pkg/exp/proxy/per_host.go b/src/pkg/exp/proxy/per_host.go
new file mode 100644
index 0000000..397ef57
--- /dev/null
+++ b/src/pkg/exp/proxy/per_host.go
@@ -0,0 +1,140 @@
+// Copyright 2011 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 proxy
+
+import (
+	"net"
+	"strings"
+)
+
+// A PerHost directs connections to a default Dailer unless the hostname
+// requested matches one of a number of exceptions.
+type PerHost struct {
+	def, bypass Dialer
+
+	bypassNetworks []*net.IPNet
+	bypassIPs      []net.IP
+	bypassZones    []string
+	bypassHosts    []string
+}
+
+// NewPerHost returns a PerHost Dialer that directs connections to either
+// defaultDialer or bypass, depending on whether the connection matches one of
+// the configured rules.
+func NewPerHost(defaultDialer, bypass Dialer) *PerHost {
+	return &PerHost{
+		def:    defaultDialer,
+		bypass: bypass,
+	}
+}
+
+// Dial connects to the address addr on the network net through either
+// defaultDialer or bypass.
+func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) {
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+
+	return p.dialerForRequest(host).Dial(network, addr)
+}
+
+func (p *PerHost) dialerForRequest(host string) Dialer {
+	if ip := net.ParseIP(host); ip != nil {
+		for _, net := range p.bypassNetworks {
+			if net.Contains(ip) {
+				return p.bypass
+			}
+		}
+		for _, bypassIP := range p.bypassIPs {
+			if bypassIP.Equal(ip) {
+				return p.bypass
+			}
+		}
+		return p.def
+	}
+
+	for _, zone := range p.bypassZones {
+		if strings.HasSuffix(host, zone) {
+			return p.bypass
+		}
+		if host == zone[1:] {
+			// For a zone "example.com", we match "example.com"
+			// too.
+			return p.bypass
+		}
+	}
+	for _, bypassHost := range p.bypassHosts {
+		if bypassHost == host {
+			return p.bypass
+		}
+	}
+	return p.def
+}
+
+// AddFromString parses a string that contains comma-separated values
+// specifing hosts that should use the bypass proxy. Each value is either an
+// IP address, a CIDR range, a zone (*.example.com) or a hostname
+// (localhost). A best effort is made to parse the string and errors are
+// ignored.
+func (p *PerHost) AddFromString(s string) {
+	hosts := strings.Split(s, ",")
+	for _, host := range hosts {
+		host = strings.TrimSpace(host)
+		if len(host) == 0 {
+			continue
+		}
+		if strings.Contains(host, "/") {
+			// We assume that it's a CIDR address like 127.0.0.0/8
+			if _, net, err := net.ParseCIDR(host); err == nil {
+				p.AddNetwork(net)
+			}
+			continue
+		}
+		if ip := net.ParseIP(host); ip != nil {
+			p.AddIP(ip)
+			continue
+		}
+		if strings.HasPrefix(host, "*.") {
+			p.AddZone(host[1:])
+			continue
+		}
+		p.AddHost(host)
+	}
+}
+
+// AddIP specifies an IP address that will use the bypass proxy. Note that
+// this will only take effect if a literal IP address is dialed. A connection
+// to a named host will never match an IP.
+func (p *PerHost) AddIP(ip net.IP) {
+	p.bypassIPs = append(p.bypassIPs, ip)
+}
+
+// AddIP specifies an IP range that will use the bypass proxy. Note that this
+// will only take effect if a literal IP address is dialed. A connection to a
+// named host will never match.
+func (p *PerHost) AddNetwork(net *net.IPNet) {
+	p.bypassNetworks = append(p.bypassNetworks, net)
+}
+
+// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
+// "example.com" matches "example.com" and all of its subdomains.
+func (p *PerHost) AddZone(zone string) {
+	if strings.HasSuffix(zone, ".") {
+		zone = zone[:len(zone)-1]
+	}
+	if !strings.HasPrefix(zone, ".") {
+		zone = "." + zone
+	}
+	p.bypassZones = append(p.bypassZones, zone)
+}
+
+// AddHost specifies a hostname that will use the bypass proxy.
+func (p *PerHost) AddHost(host string) {
+	if strings.HasSuffix(host, ".") {
+		host = host[:len(host)-1]
+	}
+	p.bypassHosts = append(p.bypassHosts, host)
+}
diff --git a/src/pkg/exp/proxy/per_host_test.go b/src/pkg/exp/proxy/per_host_test.go
new file mode 100644
index 0000000..a7d8095
--- /dev/null
+++ b/src/pkg/exp/proxy/per_host_test.go
@@ -0,0 +1,55 @@
+// Copyright 2011 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 proxy
+
+import (
+	"errors"
+	"net"
+	"reflect"
+	"testing"
+)
+
+type recordingProxy struct {
+	addrs []string
+}
+
+func (r *recordingProxy) Dial(network, addr string) (net.Conn, error) {
+	r.addrs = append(r.addrs, addr)
+	return nil, errors.New("recordingProxy")
+}
+
+func TestPerHost(t *testing.T) {
+	var def, bypass recordingProxy
+	perHost := NewPerHost(&def, &bypass)
+	perHost.AddFromString("localhost,*.zone,127.0.0.1,10.0.0.1/8,1000::/16")
+
+	expectedDef := []string{
+		"example.com:123",
+		"1.2.3.4:123",
+		"[1001::]:123",
+	}
+	expectedBypass := []string{
+		"localhost:123",
+		"zone:123",
+		"foo.zone:123",
+		"127.0.0.1:123",
+		"10.1.2.3:123",
+		"[1000::]:123",
+	}
+
+	for _, addr := range expectedDef {
+		perHost.Dial("tcp", addr)
+	}
+	for _, addr := range expectedBypass {
+		perHost.Dial("tcp", addr)
+	}
+
+	if !reflect.DeepEqual(expectedDef, def.addrs) {
+		t.Errorf("Hosts which went to the default proxy didn't match. Got %v, want %v", def.addrs, expectedDef)
+	}
+	if !reflect.DeepEqual(expectedBypass, bypass.addrs) {
+		t.Errorf("Hosts which went to the bypass proxy didn't match. Got %v, want %v", bypass.addrs, expectedBypass)
+	}
+}
diff --git a/src/pkg/exp/proxy/proxy.go b/src/pkg/exp/proxy/proxy.go
new file mode 100644
index 0000000..b6cfd45
--- /dev/null
+++ b/src/pkg/exp/proxy/proxy.go
@@ -0,0 +1,94 @@
+// Copyright 2011 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 proxy provides support for a variety of protocols to proxy network
+// data.
+package proxy
+
+import (
+	"errors"
+	"net"
+	"net/url"
+	"os"
+)
+
+// A Dialer is a means to establish a connection.
+type Dialer interface {
+	// Dial connects to the given address via the proxy.
+	Dial(network, addr string) (c net.Conn, err error)
+}
+
+// Auth contains authentication parameters that specific Dialers may require.
+type Auth struct {
+	User, Password string
+}
+
+// DefaultDialer returns the dialer specified by the proxy related variables in
+// the environment.
+func FromEnvironment() Dialer {
+	allProxy := os.Getenv("all_proxy")
+	if len(allProxy) == 0 {
+		return Direct
+	}
+
+	proxyURL, err := url.Parse(allProxy)
+	if err != nil {
+		return Direct
+	}
+	proxy, err := FromURL(proxyURL, Direct)
+	if err != nil {
+		return Direct
+	}
+
+	noProxy := os.Getenv("no_proxy")
+	if len(noProxy) == 0 {
+		return proxy
+	}
+
+	perHost := NewPerHost(proxy, Direct)
+	perHost.AddFromString(noProxy)
+	return perHost
+}
+
+// proxySchemes is a map from URL schemes to a function that creates a Dialer
+// from a URL with such a scheme.
+var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
+
+// RegisterDialerType takes a URL scheme and a function to generate Dialers from
+// a URL with that scheme and a forwarding Dialer. Registered schemes are used
+// by FromURL.
+func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
+	if proxySchemes == nil {
+		proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
+	}
+	proxySchemes[scheme] = f
+}
+
+// FromURL returns a Dialer given a URL specification and an underlying
+// Dialer for it to make network requests.
+func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
+	var auth *Auth
+	if u.User != nil {
+		auth = new(Auth)
+		auth.User = u.User.Username()
+		if p, ok := u.User.Password(); ok {
+			auth.Password = p
+		}
+	}
+
+	switch u.Scheme {
+	case "socks5":
+		return SOCKS5("tcp", u.Host, auth, forward)
+	}
+
+	// If the scheme doesn't match any of the built-in schemes, see if it
+	// was registered by another package.
+	if proxySchemes != nil {
+		if f, ok := proxySchemes[u.Scheme]; ok {
+			return f(u, forward)
+		}
+	}
+
+	return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
+}
diff --git a/src/pkg/exp/proxy/proxy_test.go b/src/pkg/exp/proxy/proxy_test.go
new file mode 100644
index 0000000..4078bc7
--- /dev/null
+++ b/src/pkg/exp/proxy/proxy_test.go
@@ -0,0 +1,50 @@
+// Copyright 2011 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 proxy
+
+import (
+	"net"
+	"net/url"
+	"testing"
+)
+
+type testDialer struct {
+	network, addr string
+}
+
+func (t *testDialer) Dial(network, addr string) (net.Conn, error) {
+	t.network = network
+	t.addr = addr
+	return nil, t
+}
+
+func (t *testDialer) Error() string {
+	return "testDialer " + t.network + " " + t.addr
+}
+
+func TestFromURL(t *testing.T) {
+	u, err := url.Parse("socks5://user:password at 1.2.3.4:5678")
+	if err != nil {
+		t.Fatalf("failed to parse URL: %s", err)
+	}
+
+	tp := &testDialer{}
+	proxy, err := FromURL(u, tp)
+	if err != nil {
+		t.Fatalf("FromURL failed: %s", err)
+	}
+
+	conn, err := proxy.Dial("tcp", "example.com:80")
+	if conn != nil {
+		t.Error("Dial unexpected didn't return an error")
+	}
+	if tp, ok := err.(*testDialer); ok {
+		if tp.network != "tcp" || tp.addr != "1.2.3.4:5678" {
+			t.Errorf("Dialer connected to wrong host. Wanted 1.2.3.4:5678, got: %v", tp)
+		}
+	} else {
+		t.Errorf("Unexpected error from Dial: %s", err)
+	}
+}
diff --git a/src/pkg/exp/proxy/socks5.go b/src/pkg/exp/proxy/socks5.go
new file mode 100644
index 0000000..466e135
--- /dev/null
+++ b/src/pkg/exp/proxy/socks5.go
@@ -0,0 +1,207 @@
+// Copyright 2011 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 proxy
+
+import (
+	"errors"
+	"io"
+	"net"
+	"strconv"
+)
+
+// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
+// with an optional username and password. See RFC 1928.
+func SOCKS5(network, addr string, auth *Auth, forward Dialer) (Dialer, error) {
+	s := &socks5{
+		network: network,
+		addr:    addr,
+		forward: forward,
+	}
+	if auth != nil {
+		s.user = auth.User
+		s.password = auth.Password
+	}
+
+	return s, nil
+}
+
+type socks5 struct {
+	user, password string
+	network, addr  string
+	forward        Dialer
+}
+
+const socks5Version = 5
+
+const (
+	socks5AuthNone     = 0
+	socks5AuthPassword = 2
+)
+
+const socks5Connect = 1
+
+const (
+	socks5IP4    = 1
+	socks5Domain = 3
+	socks5IP6    = 4
+)
+
+var socks5Errors = []string{
+	"",
+	"general failure",
+	"connection forbidden",
+	"network unreachable",
+	"host unreachable",
+	"connection refused",
+	"TTL expired",
+	"command not supported",
+	"address type not supported",
+}
+
+// Dial connects to the address addr on the network net via the SOCKS5 proxy.
+func (s *socks5) Dial(network, addr string) (net.Conn, error) {
+	switch network {
+	case "tcp", "tcp6", "tcp4":
+		break
+	default:
+		return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
+	}
+
+	conn, err := s.forward.Dial(s.network, s.addr)
+	if err != nil {
+		return nil, err
+	}
+	closeConn := &conn
+	defer func() {
+		if closeConn != nil {
+			(*closeConn).Close()
+		}
+	}()
+
+	host, portStr, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+
+	port, err := strconv.Atoi(portStr)
+	if err != nil {
+		return nil, errors.New("proxy: failed to parse port number: " + portStr)
+	}
+	if port < 1 || port > 0xffff {
+		return nil, errors.New("proxy: port number out of range: " + portStr)
+	}
+
+	// the size here is just an estimate
+	buf := make([]byte, 0, 6+len(host))
+
+	buf = append(buf, socks5Version)
+	if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
+		buf = append(buf, 2, /* num auth methods */ socks5AuthNone, socks5AuthPassword)
+	} else {
+		buf = append(buf, 1, /* num auth methods */ socks5AuthNone)
+	}
+
+	if _, err = conn.Write(buf); err != nil {
+		return nil, errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	if _, err = io.ReadFull(conn, buf[:2]); err != nil {
+		return nil, errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+	if buf[0] != 5 {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
+	}
+	if buf[1] == 0xff {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
+	}
+
+	if buf[1] == socks5AuthPassword {
+		buf = buf[:0]
+		buf = append(buf, socks5Version)
+		buf = append(buf, uint8(len(s.user)))
+		buf = append(buf, s.user...)
+		buf = append(buf, uint8(len(s.password)))
+		buf = append(buf, s.password...)
+
+		if _, err = conn.Write(buf); err != nil {
+			return nil, errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+
+		if _, err = io.ReadFull(conn, buf[:2]); err != nil {
+			return nil, errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+
+		if buf[1] != 0 {
+			return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
+		}
+	}
+
+	buf = buf[:0]
+	buf = append(buf, socks5Version, socks5Connect, 0 /* reserved */ )
+
+	if ip := net.ParseIP(host); ip != nil {
+		if len(ip) == 4 {
+			buf = append(buf, socks5IP4)
+		} else {
+			buf = append(buf, socks5IP6)
+		}
+		buf = append(buf, []byte(ip)...)
+	} else {
+		buf = append(buf, socks5Domain)
+		buf = append(buf, byte(len(host)))
+		buf = append(buf, host...)
+	}
+	buf = append(buf, byte(port>>8), byte(port))
+
+	if _, err = conn.Write(buf); err != nil {
+		return nil, errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	if _, err = io.ReadFull(conn, buf[:4]); err != nil {
+		return nil, errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	failure := "unknown error"
+	if int(buf[1]) < len(socks5Errors) {
+		failure = socks5Errors[buf[1]]
+	}
+
+	if len(failure) > 0 {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
+	}
+
+	bytesToDiscard := 0
+	switch buf[3] {
+	case socks5IP4:
+		bytesToDiscard = 4
+	case socks5IP6:
+		bytesToDiscard = 16
+	case socks5Domain:
+		_, err := io.ReadFull(conn, buf[:1])
+		if err != nil {
+			return nil, errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+		bytesToDiscard = int(buf[0])
+	default:
+		return nil, errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
+	}
+
+	if cap(buf) < bytesToDiscard {
+		buf = make([]byte, bytesToDiscard)
+	} else {
+		buf = buf[:bytesToDiscard]
+	}
+	if _, err = io.ReadFull(conn, buf); err != nil {
+		return nil, errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	// Also need to discard the port number
+	if _, err = io.ReadFull(conn, buf[:2]); err != nil {
+		return nil, errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	closeConn = nil
+	return conn, nil
+}
diff --git a/src/pkg/exp/regexp/Makefile b/src/pkg/exp/regexp/Makefile
deleted file mode 100644
index fc90df3..0000000
--- a/src/pkg/exp/regexp/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=exp/regexp
-GOFILES=\
-	exec.go\
-	regexp.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/exp/regexp/all_test.go b/src/pkg/exp/regexp/all_test.go
deleted file mode 100644
index 77f32ca..0000000
--- a/src/pkg/exp/regexp/all_test.go
+++ /dev/null
@@ -1,429 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package regexp
-
-import (
-	"os"
-	"strings"
-	"testing"
-)
-
-var good_re = []string{
-	``,
-	`.`,
-	`^.$`,
-	`a`,
-	`a*`,
-	`a+`,
-	`a?`,
-	`a|b`,
-	`a*|b*`,
-	`(a*|b)(c*|d)`,
-	`[a-z]`,
-	`[a-abc-c\-\]\[]`,
-	`[a-z]+`,
-	`[abc]`,
-	`[^1234]`,
-	`[^\n]`,
-	`\!\\`,
-}
-
-/*
-type stringError struct {
-	re  string
-	err os.Error
-}
-
-var bad_re = []stringError{
-	{`*`, ErrBareClosure},
-	{`+`, ErrBareClosure},
-	{`?`, ErrBareClosure},
-	{`(abc`, ErrUnmatchedLpar},
-	{`abc)`, ErrUnmatchedRpar},
-	{`x[a-z`, ErrUnmatchedLbkt},
-	{`abc]`, ErrUnmatchedRbkt},
-	{`[z-a]`, ErrBadRange},
-	{`abc\`, ErrExtraneousBackslash},
-	{`a**`, ErrBadClosure},
-	{`a*+`, ErrBadClosure},
-	{`a??`, ErrBadClosure},
-	{`\x`, ErrBadBackslash},
-}
-*/
-
-func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
-	re, err := Compile(expr)
-	if err != error {
-		t.Error("compiling `", expr, "`; unexpected error: ", err.String())
-	}
-	return re
-}
-
-func TestGoodCompile(t *testing.T) {
-	for i := 0; i < len(good_re); i++ {
-		compileTest(t, good_re[i], nil)
-	}
-}
-
-/*
-func TestBadCompile(t *testing.T) {
-	for i := 0; i < len(bad_re); i++ {
-		compileTest(t, bad_re[i].re, bad_re[i].err)
-	}
-}
-*/
-
-func matchTest(t *testing.T, test *FindTest) {
-	re := compileTest(t, test.pat, nil)
-	if re == nil {
-		return
-	}
-	m := re.MatchString(test.text)
-	if m != (len(test.matches) > 0) {
-		t.Errorf("MatchString failure on %s: %t should be %t", test, m, len(test.matches) > 0)
-	}
-	// now try bytes
-	m = re.Match([]byte(test.text))
-	if m != (len(test.matches) > 0) {
-		t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
-	}
-}
-
-func TestMatch(t *testing.T) {
-	for _, test := range findTests {
-		matchTest(t, &test)
-	}
-}
-
-func matchFunctionTest(t *testing.T, test *FindTest) {
-	m, err := MatchString(test.pat, test.text)
-	if err == nil {
-		return
-	}
-	if m != (len(test.matches) > 0) {
-		t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
-	}
-}
-
-func TestMatchFunction(t *testing.T) {
-	for _, test := range findTests {
-		matchFunctionTest(t, &test)
-	}
-}
-
-type ReplaceTest struct {
-	pattern, replacement, input, output string
-}
-
-var replaceTests = []ReplaceTest{
-	// Test empty input and/or replacement, with pattern that matches the empty string.
-	{"", "", "", ""},
-	{"", "x", "", "x"},
-	{"", "", "abc", "abc"},
-	{"", "x", "abc", "xaxbxcx"},
-
-	// Test empty input and/or replacement, with pattern that does not match the empty string.
-	{"b", "", "", ""},
-	{"b", "x", "", ""},
-	{"b", "", "abc", "ac"},
-	{"b", "x", "abc", "axc"},
-	{"y", "", "", ""},
-	{"y", "x", "", ""},
-	{"y", "", "abc", "abc"},
-	{"y", "x", "abc", "abc"},
-
-	// Multibyte characters -- verify that we don't try to match in the middle
-	// of a character.
-	{"[a-c]*", "x", "\u65e5", "x\u65e5x"},
-	{"[^\u65e5]", "x", "abc\u65e5def", "xxx\u65e5xxx"},
-
-	// Start and end of a string.
-	{"^[a-c]*", "x", "abcdabc", "xdabc"},
-	{"[a-c]*$", "x", "abcdabc", "abcdx"},
-	{"^[a-c]*$", "x", "abcdabc", "abcdabc"},
-	{"^[a-c]*", "x", "abc", "x"},
-	{"[a-c]*$", "x", "abc", "x"},
-	{"^[a-c]*$", "x", "abc", "x"},
-	{"^[a-c]*", "x", "dabce", "xdabce"},
-	{"[a-c]*$", "x", "dabce", "dabcex"},
-	{"^[a-c]*$", "x", "dabce", "dabce"},
-	{"^[a-c]*", "x", "", "x"},
-	{"[a-c]*$", "x", "", "x"},
-	{"^[a-c]*$", "x", "", "x"},
-
-	{"^[a-c]+", "x", "abcdabc", "xdabc"},
-	{"[a-c]+$", "x", "abcdabc", "abcdx"},
-	{"^[a-c]+$", "x", "abcdabc", "abcdabc"},
-	{"^[a-c]+", "x", "abc", "x"},
-	{"[a-c]+$", "x", "abc", "x"},
-	{"^[a-c]+$", "x", "abc", "x"},
-	{"^[a-c]+", "x", "dabce", "dabce"},
-	{"[a-c]+$", "x", "dabce", "dabce"},
-	{"^[a-c]+$", "x", "dabce", "dabce"},
-	{"^[a-c]+", "x", "", ""},
-	{"[a-c]+$", "x", "", ""},
-	{"^[a-c]+$", "x", "", ""},
-
-	// Other cases.
-	{"abc", "def", "abcdefg", "defdefg"},
-	{"bc", "BC", "abcbcdcdedef", "aBCBCdcdedef"},
-	{"abc", "", "abcdabc", "d"},
-	{"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"},
-	{"abc", "d", "", ""},
-	{"abc", "d", "abc", "d"},
-	{".+", "x", "abc", "x"},
-	{"[a-c]*", "x", "def", "xdxexfx"},
-	{"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"},
-	{"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"},
-}
-
-type ReplaceFuncTest struct {
-	pattern       string
-	replacement   func(string) string
-	input, output string
-}
-
-var replaceFuncTests = []ReplaceFuncTest{
-	{"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"},
-	{"[a-c]+", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxabcydef"},
-	{"[a-c]*", func(s string) string { return "x" + s + "y" }, "defabcdef", "xydxyexyfxabcydxyexyfxy"},
-}
-
-func TestReplaceAll(t *testing.T) {
-	for _, tc := range replaceTests {
-		re, err := Compile(tc.pattern)
-		if err != nil {
-			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
-			continue
-		}
-		actual := re.ReplaceAllString(tc.input, tc.replacement)
-		if actual != tc.output {
-			t.Errorf("%q.Replace(%q,%q) = %q; want %q",
-				tc.pattern, tc.input, tc.replacement, actual, tc.output)
-		}
-		// now try bytes
-		actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replacement)))
-		if actual != tc.output {
-			t.Errorf("%q.Replace(%q,%q) = %q; want %q",
-				tc.pattern, tc.input, tc.replacement, actual, tc.output)
-		}
-	}
-}
-
-func TestReplaceAllFunc(t *testing.T) {
-	for _, tc := range replaceFuncTests {
-		re, err := Compile(tc.pattern)
-		if err != nil {
-			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
-			continue
-		}
-		actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
-		if actual != tc.output {
-			t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
-				tc.pattern, tc.input, tc.replacement, actual, tc.output)
-		}
-		// now try bytes
-		actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) }))
-		if actual != tc.output {
-			t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
-				tc.pattern, tc.input, tc.replacement, actual, tc.output)
-		}
-	}
-}
-
-type MetaTest struct {
-	pattern, output, literal string
-	isLiteral                bool
-}
-
-var metaTests = []MetaTest{
-	{``, ``, ``, true},
-	{`foo`, `foo`, `foo`, true},
-	{`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
-	{`foo.\$`, `foo\.\\\$`, `foo`, false},     // has escaped operators and real operators
-	{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false},
-}
-
-func TestQuoteMeta(t *testing.T) {
-	for _, tc := range metaTests {
-		// Verify that QuoteMeta returns the expected string.
-		quoted := QuoteMeta(tc.pattern)
-		if quoted != tc.output {
-			t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
-				tc.pattern, quoted, tc.output)
-			continue
-		}
-
-		// Verify that the quoted string is in fact treated as expected
-		// by Compile -- i.e. that it matches the original, unquoted string.
-		if tc.pattern != "" {
-			re, err := Compile(quoted)
-			if err != nil {
-				t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
-				continue
-			}
-			src := "abc" + tc.pattern + "def"
-			repl := "xyz"
-			replaced := re.ReplaceAllString(src, repl)
-			expected := "abcxyzdef"
-			if replaced != expected {
-				t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
-					tc.pattern, src, repl, replaced, expected)
-			}
-		}
-	}
-}
-
-func TestLiteralPrefix(t *testing.T) {
-	for _, tc := range metaTests {
-		// Literal method needs to scan the pattern.
-		re := MustCompile(tc.pattern)
-		str, complete := re.LiteralPrefix()
-		if complete != tc.isLiteral {
-			t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
-		}
-		if str != tc.literal {
-			t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
-		}
-	}
-}
-
-type numSubexpCase struct {
-	input    string
-	expected int
-}
-
-var numSubexpCases = []numSubexpCase{
-	{``, 0},
-	{`.*`, 0},
-	{`abba`, 0},
-	{`ab(b)a`, 1},
-	{`ab(.*)a`, 1},
-	{`(.*)ab(.*)a`, 2},
-	{`(.*)(ab)(.*)a`, 3},
-	{`(.*)((a)b)(.*)a`, 4},
-	{`(.*)(\(ab)(.*)a`, 3},
-	{`(.*)(\(a\)b)(.*)a`, 3},
-}
-
-func TestNumSubexp(t *testing.T) {
-	for _, c := range numSubexpCases {
-		re := MustCompile(c.input)
-		n := re.NumSubexp()
-		if n != c.expected {
-			t.Errorf("NumSubexp for %q returned %d, expected %d", c.input, n, c.expected)
-		}
-	}
-}
-
-func BenchmarkLiteral(b *testing.B) {
-	x := strings.Repeat("x", 50) + "y"
-	b.StopTimer()
-	re := MustCompile("y")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		if !re.MatchString(x) {
-			println("no match!")
-			break
-		}
-	}
-}
-
-func BenchmarkNotLiteral(b *testing.B) {
-	x := strings.Repeat("x", 50) + "y"
-	b.StopTimer()
-	re := MustCompile(".y")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		if !re.MatchString(x) {
-			println("no match!")
-			break
-		}
-	}
-}
-
-func BenchmarkMatchClass(b *testing.B) {
-	b.StopTimer()
-	x := strings.Repeat("xxxx", 20) + "w"
-	re := MustCompile("[abcdw]")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		if !re.MatchString(x) {
-			println("no match!")
-			break
-		}
-	}
-}
-
-func BenchmarkMatchClass_InRange(b *testing.B) {
-	b.StopTimer()
-	// 'b' is between 'a' and 'c', so the charclass
-	// range checking is no help here.
-	x := strings.Repeat("bbbb", 20) + "c"
-	re := MustCompile("[ac]")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		if !re.MatchString(x) {
-			println("no match!")
-			break
-		}
-	}
-}
-
-func BenchmarkReplaceAll(b *testing.B) {
-	x := "abcdefghijklmnopqrstuvwxyz"
-	b.StopTimer()
-	re := MustCompile("[cjrw]")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		re.ReplaceAllString(x, "")
-	}
-}
-
-func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) {
-	b.StopTimer()
-	x := []byte("abcdefghijklmnopqrstuvwxyz")
-	re := MustCompile("^zbc(d|e)")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		re.Match(x)
-	}
-}
-
-func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) {
-	b.StopTimer()
-	x := []byte("abcdefghijklmnopqrstuvwxyz")
-	for i := 0; i < 15; i++ {
-		x = append(x, x...)
-	}
-	re := MustCompile("^zbc(d|e)")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		re.Match(x)
-	}
-}
-
-func BenchmarkAnchoredShortMatch(b *testing.B) {
-	b.StopTimer()
-	x := []byte("abcdefghijklmnopqrstuvwxyz")
-	re := MustCompile("^.bc(d|e)")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		re.Match(x)
-	}
-}
-
-func BenchmarkAnchoredLongMatch(b *testing.B) {
-	b.StopTimer()
-	x := []byte("abcdefghijklmnopqrstuvwxyz")
-	for i := 0; i < 15; i++ {
-		x = append(x, x...)
-	}
-	re := MustCompile("^.bc(d|e)")
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		re.Match(x)
-	}
-}
diff --git a/src/pkg/exp/regexp/exec.go b/src/pkg/exp/regexp/exec.go
deleted file mode 100644
index 43499a9..0000000
--- a/src/pkg/exp/regexp/exec.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package regexp
-
-import "exp/regexp/syntax"
-
-// A queue is a 'sparse array' holding pending threads of execution.
-// See http://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html
-type queue struct {
-	sparse []uint32
-	dense  []entry
-}
-
-// A entry is an entry on a queue.
-// It holds both the instruction pc and the actual thread.
-// Some queue entries are just place holders so that the machine
-// knows it has considered that pc.  Such entries have t == nil.
-type entry struct {
-	pc uint32
-	t  *thread
-}
-
-// A thread is the state of a single path through the machine:
-// an instruction and a corresponding capture array.
-// See http://swtch.com/~rsc/regexp/regexp2.html
-type thread struct {
-	inst *syntax.Inst
-	cap  []int
-}
-
-// A machine holds all the state during an NFA simulation for p.
-type machine struct {
-	re       *Regexp      // corresponding Regexp
-	p        *syntax.Prog // compiled program
-	q0, q1   queue        // two queues for runq, nextq
-	pool     []*thread    // pool of available threads
-	matched  bool         // whether a match was found
-	matchcap []int        // capture information for the match
-}
-
-// progMachine returns a new machine running the prog p.
-func progMachine(p *syntax.Prog) *machine {
-	m := &machine{p: p}
-	n := len(m.p.Inst)
-	m.q0 = queue{make([]uint32, n), make([]entry, 0, n)}
-	m.q1 = queue{make([]uint32, n), make([]entry, 0, n)}
-	ncap := p.NumCap
-	if ncap < 2 {
-		ncap = 2
-	}
-	m.matchcap = make([]int, ncap)
-	return m
-}
-
-// alloc allocates a new thread with the given instruction.
-// It uses the free pool if possible.
-func (m *machine) alloc(i *syntax.Inst) *thread {
-	var t *thread
-	if n := len(m.pool); n > 0 {
-		t = m.pool[n-1]
-		m.pool = m.pool[:n-1]
-	} else {
-		t = new(thread)
-		t.cap = make([]int, cap(m.matchcap))
-	}
-	t.cap = t.cap[:len(m.matchcap)]
-	t.inst = i
-	return t
-}
-
-// free returns t to the free pool.
-func (m *machine) free(t *thread) {
-	m.pool = append(m.pool, t)
-}
-
-// match runs the machine over the input starting at pos.
-// It reports whether a match was found.
-// If so, m.matchcap holds the submatch information.
-func (m *machine) match(i input, pos int) bool {
-	startCond := m.re.cond
-	if startCond == ^syntax.EmptyOp(0) { // impossible
-		return false
-	}
-	m.matched = false
-	for i := range m.matchcap {
-		m.matchcap[i] = -1
-	}
-	runq, nextq := &m.q0, &m.q1
-	rune, rune1 := endOfText, endOfText
-	width, width1 := 0, 0
-	rune, width = i.step(pos)
-	if rune != endOfText {
-		rune1, width1 = i.step(pos + width)
-	}
-	var flag syntax.EmptyOp
-	if pos == 0 {
-		flag = syntax.EmptyOpContext(-1, rune)
-	} else {
-		flag = i.context(pos)
-	}
-	for {
-		if len(runq.dense) == 0 {
-			if startCond&syntax.EmptyBeginText != 0 && pos != 0 {
-				// Anchored match, past beginning of text.
-				break
-			}
-			if m.matched {
-				// Have match; finished exploring alternatives.
-				break
-			}
-			if len(m.re.prefix) > 0 && rune1 != m.re.prefixRune && i.canCheckPrefix() {
-				// Match requires literal prefix; fast search for it.
-				advance := i.index(m.re, pos)
-				if advance < 0 {
-					break
-				}
-				pos += advance
-				rune, width = i.step(pos)
-				rune1, width1 = i.step(pos + width)
-			}
-		}
-		if !m.matched {
-			if len(m.matchcap) > 0 {
-				m.matchcap[0] = pos
-			}
-			m.add(runq, uint32(m.p.Start), pos, m.matchcap, flag)
-		}
-		flag = syntax.EmptyOpContext(rune, rune1)
-		m.step(runq, nextq, pos, pos+width, rune, flag)
-		if width == 0 {
-			break
-		}
-		if len(m.matchcap) == 0 && m.matched {
-			// Found a match and not paying attention
-			// to where it is, so any match will do.
-			break
-		}
-		pos += width
-		rune, width = rune1, width1
-		if rune != endOfText {
-			rune1, width1 = i.step(pos + width)
-		}
-		runq, nextq = nextq, runq
-	}
-	m.clear(nextq)
-	return m.matched
-}
-
-// clear frees all threads on the thread queue.
-func (m *machine) clear(q *queue) {
-	for _, d := range q.dense {
-		if d.t != nil {
-			m.free(d.t)
-		}
-	}
-	q.dense = q.dense[:0]
-}
-
-// step executes one step of the machine, running each of the threads
-// on runq and appending new threads to nextq.
-// The step processes the rune c (which may be endOfText),
-// which starts at position pos and ends at nextPos.
-// nextCond gives the setting for the empty-width flags after c.
-func (m *machine) step(runq, nextq *queue, pos, nextPos, c int, nextCond syntax.EmptyOp) {
-	longest := m.re.longest
-	for j := 0; j < len(runq.dense); j++ {
-		d := &runq.dense[j]
-		t := d.t
-		if t == nil {
-			continue
-		}
-		if longest && m.matched && len(t.cap) > 0 && m.matchcap[0] < t.cap[0] {
-			m.free(t)
-			continue
-		}
-		i := t.inst
-		switch i.Op {
-		default:
-			panic("bad inst")
-
-		case syntax.InstMatch:
-			if len(t.cap) > 0 && (!longest || !m.matched || m.matchcap[1] < pos) {
-				t.cap[1] = pos
-				copy(m.matchcap, t.cap)
-			}
-			if !longest {
-				// First-match mode: cut off all lower-priority threads.
-				for _, d := range runq.dense[j+1:] {
-					if d.t != nil {
-						m.free(d.t)
-					}
-				}
-				runq.dense = runq.dense[:0]
-			}
-			m.matched = true
-
-		case syntax.InstRune:
-			if i.MatchRune(c) {
-				m.add(nextq, i.Out, nextPos, t.cap, nextCond)
-			}
-		}
-		m.free(t)
-	}
-	runq.dense = runq.dense[:0]
-}
-
-// add adds an entry to q for pc, unless the q already has such an entry.
-// It also recursively adds an entry for all instructions reachable from pc by following
-// empty-width conditions satisfied by cond.  pos gives the current position
-// in the input.
-func (m *machine) add(q *queue, pc uint32, pos int, cap []int, cond syntax.EmptyOp) {
-	if pc == 0 {
-		return
-	}
-	if j := q.sparse[pc]; j < uint32(len(q.dense)) && q.dense[j].pc == pc {
-		return
-	}
-
-	j := len(q.dense)
-	q.dense = q.dense[:j+1]
-	d := &q.dense[j]
-	d.t = nil
-	d.pc = pc
-	q.sparse[pc] = uint32(j)
-
-	i := &m.p.Inst[pc]
-	switch i.Op {
-	default:
-		panic("unhandled")
-	case syntax.InstFail:
-		// nothing
-	case syntax.InstAlt, syntax.InstAltMatch:
-		m.add(q, i.Out, pos, cap, cond)
-		m.add(q, i.Arg, pos, cap, cond)
-	case syntax.InstEmptyWidth:
-		if syntax.EmptyOp(i.Arg)&^cond == 0 {
-			m.add(q, i.Out, pos, cap, cond)
-		}
-	case syntax.InstNop:
-		m.add(q, i.Out, pos, cap, cond)
-	case syntax.InstCapture:
-		if int(i.Arg) < len(cap) {
-			opos := cap[i.Arg]
-			cap[i.Arg] = pos
-			m.add(q, i.Out, pos, cap, cond)
-			cap[i.Arg] = opos
-		} else {
-			m.add(q, i.Out, pos, cap, cond)
-		}
-	case syntax.InstMatch, syntax.InstRune:
-		t := m.alloc(i)
-		if len(t.cap) > 0 {
-			copy(t.cap, cap)
-		}
-		d.t = t
-	}
-}
-
-// empty is a non-nil 0-element slice,
-// so doExecute can avoid an allocation
-// when 0 captures are requested from a successful match.
-var empty = make([]int, 0)
-
-// doExecute finds the leftmost match in the input and returns
-// the position of its subexpressions.
-func (re *Regexp) doExecute(i input, pos int, ncap int) []int {
-	m := re.get()
-	m.matchcap = m.matchcap[:ncap]
-	if !m.match(i, pos) {
-		re.put(m)
-		return nil
-	}
-	if ncap == 0 {
-		re.put(m)
-		return empty // empty but not nil
-	}
-	cap := make([]int, ncap)
-	copy(cap, m.matchcap)
-	re.put(m)
-	return cap
-}
diff --git a/src/pkg/exp/regexp/exec_test.go b/src/pkg/exp/regexp/exec_test.go
deleted file mode 100644
index 3adf848..0000000
--- a/src/pkg/exp/regexp/exec_test.go
+++ /dev/null
@@ -1,649 +0,0 @@
-// Copyright 2010 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 regexp
-
-import (
-	"bufio"
-	"compress/bzip2"
-	"exp/regexp/syntax"
-	"fmt"
-	"io"
-	"os"
-	"path/filepath"
-	"strconv"
-	"strings"
-	"testing"
-	"utf8"
-)
-
-// TestRE2 tests this package's regexp API against test cases
-// considered during RE2's exhaustive tests, which run all possible
-// regexps over a given set of atoms and operators, up to a given
-// complexity, over all possible strings over a given alphabet,
-// up to a given size.  Rather than try to link with RE2, we read a
-// log file containing the test cases and the expected matches.
-// The log file, re2.txt, is generated by running 'make exhaustive-log'
-// in the open source RE2 distribution.  http://code.google.com/p/re2/
-//
-// The test file format is a sequence of stanzas like:
-//
-//	strings
-//	"abc"
-//	"123x"
-//	regexps
-//	"[a-z]+"
-//	0-3;0-3
-//	-;-
-//	"([0-9])([0-9])([0-9])"
-//	-;-
-//	-;0-3 0-1 1-2 2-3
-//
-// The stanza begins by defining a set of strings, quoted
-// using Go double-quote syntax, one per line.  Then the
-// regexps section gives a sequence of regexps to run on
-// the strings.  In the block that follows a regexp, each line
-// gives the semicolon-separated match results of running
-// the regexp on the corresponding string.
-// Each match result is either a single -, meaning no match, or a
-// space-separated sequence of pairs giving the match and
-// submatch indices.  An unmatched subexpression formats
-// its pair as a single - (not illustrated above).  For now
-// each regexp run produces two match results, one for a
-// ``full match'' that restricts the regexp to matching the entire
-// string or nothing, and one for a ``partial match'' that gives
-// the leftmost first match found in the string.
-//
-// Lines beginning with # are comments.  Lines beginning with
-// a capital letter are test names printed during RE2's test suite
-// and are echoed into t but otherwise ignored.
-//
-// At time of writing, re2.txt is 32 MB but compresses to 760 kB,
-// so we store re2.txt.gz in the repository and decompress it on the fly.
-//
-func TestRE2Search(t *testing.T) {
-	testRE2(t, "testdata/re2-search.txt")
-}
-
-func TestRE2Exhaustive(t *testing.T) {
-	if testing.Short() {
-		t.Log("skipping TestRE2Exhaustive during short test")
-		return
-	}
-	testRE2(t, "testdata/re2-exhaustive.txt.bz2")
-}
-
-func testRE2(t *testing.T, file string) {
-	f, err := os.Open(file)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer f.Close()
-	var txt io.Reader
-	if strings.HasSuffix(file, ".bz2") {
-		z := bzip2.NewReader(f)
-		txt = z
-		file = file[:len(file)-len(".bz2")] // for error messages
-	} else {
-		txt = f
-	}
-	lineno := 0
-	r := bufio.NewReader(txt)
-	var (
-		str       []string
-		input     []string
-		inStrings bool
-		re        *Regexp
-		refull    *Regexp
-		nfail     int
-		ncase     int
-	)
-	for {
-		line, err := r.ReadString('\n')
-		if err != nil {
-			if err == os.EOF {
-				break
-			}
-			t.Fatalf("%s:%d: %v", file, lineno, err)
-		}
-		line = line[:len(line)-1] // chop \n
-		lineno++
-		switch {
-		case line == "":
-			t.Fatalf("%s:%d: unexpected blank line", file, lineno)
-		case line[0] == '#':
-			continue
-		case 'A' <= line[0] && line[0] <= 'Z':
-			// Test name.
-			t.Logf("%s\n", line)
-			continue
-		case line == "strings":
-			str = str[:0]
-			inStrings = true
-		case line == "regexps":
-			inStrings = false
-		case line[0] == '"':
-			q, err := strconv.Unquote(line)
-			if err != nil {
-				// Fatal because we'll get out of sync.
-				t.Fatalf("%s:%d: unquote %s: %v", file, lineno, line, err)
-			}
-			if inStrings {
-				str = append(str, q)
-				continue
-			}
-			// Is a regexp.
-			if len(input) != 0 {
-				t.Fatalf("%s:%d: out of sync: have %d strings left before %#q", file, lineno, len(input), q)
-			}
-			re, err = tryCompile(q)
-			if err != nil {
-				if err.String() == "error parsing regexp: invalid escape sequence: `\\C`" {
-					// We don't and likely never will support \C; keep going.
-					continue
-				}
-				t.Errorf("%s:%d: compile %#q: %v", file, lineno, q, err)
-				if nfail++; nfail >= 100 {
-					t.Fatalf("stopping after %d errors", nfail)
-				}
-				continue
-			}
-			full := `\A(?:` + q + `)\z`
-			refull, err = tryCompile(full)
-			if err != nil {
-				// Fatal because q worked, so this should always work.
-				t.Fatalf("%s:%d: compile full %#q: %v", file, lineno, full, err)
-			}
-			input = str
-		case line[0] == '-' || '0' <= line[0] && line[0] <= '9':
-			// A sequence of match results.
-			ncase++
-			if re == nil {
-				// Failed to compile: skip results.
-				continue
-			}
-			if len(input) == 0 {
-				t.Fatalf("%s:%d: out of sync: no input remaining", file, lineno)
-			}
-			var text string
-			text, input = input[0], input[1:]
-			if !isSingleBytes(text) && strings.Contains(re.String(), `\B`) {
-				// RE2's \B considers every byte position,
-				// so it sees 'not word boundary' in the
-				// middle of UTF-8 sequences.  This package
-				// only considers the positions between runes,
-				// so it disagrees.  Skip those cases.
-				continue
-			}
-			res := strings.Split(line, ";")
-			if len(res) != len(run) {
-				t.Fatalf("%s:%d: have %d test results, want %d", file, lineno, len(res), len(run))
-			}
-			for i := range res {
-				have, suffix := run[i](re, refull, text)
-				want := parseResult(t, file, lineno, res[i])
-				if !same(have, want) {
-					t.Errorf("%s:%d: %#q%s.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, re, suffix, text, have, want)
-					if nfail++; nfail >= 100 {
-						t.Fatalf("stopping after %d errors", nfail)
-					}
-					continue
-				}
-				b, suffix := match[i](re, refull, text)
-				if b != (want != nil) {
-					t.Errorf("%s:%d: %#q%s.MatchString(%#q) = %v, want %v", file, lineno, re, suffix, text, b, !b)
-					if nfail++; nfail >= 100 {
-						t.Fatalf("stopping after %d errors", nfail)
-					}
-					continue
-				}
-			}
-
-		default:
-			t.Fatalf("%s:%d: out of sync: %s\n", file, lineno, line)
-		}
-	}
-	if len(input) != 0 {
-		t.Fatalf("%s:%d: out of sync: have %d strings left at EOF", file, lineno, len(input))
-	}
-	t.Logf("%d cases tested", ncase)
-}
-
-var run = []func(*Regexp, *Regexp, string) ([]int, string){
-	runFull,
-	runPartial,
-	runFullLongest,
-	runPartialLongest,
-}
-
-func runFull(re, refull *Regexp, text string) ([]int, string) {
-	refull.longest = false
-	return refull.FindStringSubmatchIndex(text), "[full]"
-}
-
-func runPartial(re, refull *Regexp, text string) ([]int, string) {
-	re.longest = false
-	return re.FindStringSubmatchIndex(text), ""
-}
-
-func runFullLongest(re, refull *Regexp, text string) ([]int, string) {
-	refull.longest = true
-	return refull.FindStringSubmatchIndex(text), "[full,longest]"
-}
-
-func runPartialLongest(re, refull *Regexp, text string) ([]int, string) {
-	re.longest = true
-	return re.FindStringSubmatchIndex(text), "[longest]"
-}
-
-var match = []func(*Regexp, *Regexp, string) (bool, string){
-	matchFull,
-	matchPartial,
-	matchFullLongest,
-	matchPartialLongest,
-}
-
-func matchFull(re, refull *Regexp, text string) (bool, string) {
-	refull.longest = false
-	return refull.MatchString(text), "[full]"
-}
-
-func matchPartial(re, refull *Regexp, text string) (bool, string) {
-	re.longest = false
-	return re.MatchString(text), ""
-}
-
-func matchFullLongest(re, refull *Regexp, text string) (bool, string) {
-	refull.longest = true
-	return refull.MatchString(text), "[full,longest]"
-}
-
-func matchPartialLongest(re, refull *Regexp, text string) (bool, string) {
-	re.longest = true
-	return re.MatchString(text), "[longest]"
-}
-
-func isSingleBytes(s string) bool {
-	for _, c := range s {
-		if c >= utf8.RuneSelf {
-			return false
-		}
-	}
-	return true
-}
-
-func tryCompile(s string) (re *Regexp, err os.Error) {
-	// Protect against panic during Compile.
-	defer func() {
-		if r := recover(); r != nil {
-			err = fmt.Errorf("panic: %v", r)
-		}
-	}()
-	return Compile(s)
-}
-
-func parseResult(t *testing.T, file string, lineno int, res string) []int {
-	// A single - indicates no match.
-	if res == "-" {
-		return nil
-	}
-	// Otherwise, a space-separated list of pairs.
-	n := 1
-	for j := 0; j < len(res); j++ {
-		if res[j] == ' ' {
-			n++
-		}
-	}
-	out := make([]int, 2*n)
-	i := 0
-	n = 0
-	for j := 0; j <= len(res); j++ {
-		if j == len(res) || res[j] == ' ' {
-			// Process a single pair.  - means no submatch.
-			pair := res[i:j]
-			if pair == "-" {
-				out[n] = -1
-				out[n+1] = -1
-			} else {
-				k := strings.Index(pair, "-")
-				if k < 0 {
-					t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
-				}
-				lo, err1 := strconv.Atoi(pair[:k])
-				hi, err2 := strconv.Atoi(pair[k+1:])
-				if err1 != nil || err2 != nil || lo > hi {
-					t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
-				}
-				out[n] = lo
-				out[n+1] = hi
-			}
-			n += 2
-			i = j + 1
-		}
-	}
-	return out
-}
-
-func same(x, y []int) bool {
-	if len(x) != len(y) {
-		return false
-	}
-	for i, xi := range x {
-		if xi != y[i] {
-			return false
-		}
-	}
-	return true
-}
-
-// TestFowler runs this package's regexp API against the
-// POSIX regular expression tests collected by Glenn Fowler
-// at http://www2.research.att.com/~gsf/testregex/.
-func TestFowler(t *testing.T) {
-	files, err := filepath.Glob("testdata/*.dat")
-	if err != nil {
-		t.Fatal(err)
-	}
-	for _, file := range files {
-		t.Log(file)
-		testFowler(t, file)
-	}
-}
-
-var notab = MustCompilePOSIX(`[^\t]+`)
-
-func testFowler(t *testing.T, file string) {
-	f, err := os.Open(file)
-	if err != nil {
-		t.Error(err)
-		return
-	}
-	defer f.Close()
-	b := bufio.NewReader(f)
-	lineno := 0
-	lastRegexp := ""
-Reading:
-	for {
-		lineno++
-		line, err := b.ReadString('\n')
-		if err != nil {
-			if err != os.EOF {
-				t.Errorf("%s:%d: %v", file, lineno, err)
-			}
-			break Reading
-		}
-
-		// http://www2.research.att.com/~gsf/man/man1/testregex.html
-		//
-		// INPUT FORMAT
-		//   Input lines may be blank, a comment beginning with #, or a test
-		//   specification. A specification is five fields separated by one
-		//   or more tabs. NULL denotes the empty string and NIL denotes the
-		//   0 pointer.
-		if line[0] == '#' || line[0] == '\n' {
-			continue Reading
-		}
-		line = line[:len(line)-1]
-		field := notab.FindAllString(line, -1)
-		for i, f := range field {
-			if f == "NULL" {
-				field[i] = ""
-			}
-			if f == "NIL" {
-				t.Logf("%s:%d: skip: %s", file, lineno, line)
-				continue Reading
-			}
-		}
-		if len(field) == 0 {
-			continue Reading
-		}
-
-		//   Field 1: the regex(3) flags to apply, one character per REG_feature
-		//   flag. The test is skipped if REG_feature is not supported by the
-		//   implementation. If the first character is not [BEASKLP] then the
-		//   specification is a global control line. One or more of [BEASKLP] may be
-		//   specified; the test will be repeated for each mode.
-		// 
-		//     B 	basic			BRE	(grep, ed, sed)
-		//     E 	REG_EXTENDED		ERE	(egrep)
-		//     A	REG_AUGMENTED		ARE	(egrep with negation)
-		//     S	REG_SHELL		SRE	(sh glob)
-		//     K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)
-		//     L	REG_LITERAL		LRE	(fgrep)
-		// 
-		//     a	REG_LEFT|REG_RIGHT	implicit ^...$
-		//     b	REG_NOTBOL		lhs does not match ^
-		//     c	REG_COMMENT		ignore space and #...\n
-		//     d	REG_SHELL_DOT		explicit leading . match
-		//     e	REG_NOTEOL		rhs does not match $
-		//     f	REG_MULTIPLE		multiple \n separated patterns
-		//     g	FNM_LEADING_DIR		testfnmatch only -- match until /
-		//     h	REG_MULTIREF		multiple digit backref
-		//     i	REG_ICASE		ignore case
-		//     j	REG_SPAN		. matches \n
-		//     k	REG_ESCAPE		\ to ecape [...] delimiter
-		//     l	REG_LEFT		implicit ^...
-		//     m	REG_MINIMAL		minimal match
-		//     n	REG_NEWLINE		explicit \n match
-		//     o	REG_ENCLOSED		(|&) magic inside [@|&](...)
-		//     p	REG_SHELL_PATH		explicit / match
-		//     q	REG_DELIMITED		delimited pattern
-		//     r	REG_RIGHT		implicit ...$
-		//     s	REG_SHELL_ESCAPED	\ not special
-		//     t	REG_MUSTDELIM		all delimiters must be specified
-		//     u	standard unspecified behavior -- errors not counted
-		//     v	REG_CLASS_ESCAPE	\ special inside [...]
-		//     w	REG_NOSUB		no subexpression match array
-		//     x	REG_LENIENT		let some errors slide
-		//     y	REG_LEFT		regexec() implicit ^...
-		//     z	REG_NULL		NULL subexpressions ok
-		//     $	                        expand C \c escapes in fields 2 and 3
-		//     /	                        field 2 is a regsubcomp() expression
-		//     =	                        field 3 is a regdecomp() expression
-		// 
-		//   Field 1 control lines:
-		// 
-		//     C		set LC_COLLATE and LC_CTYPE to locale in field 2
-		// 
-		//     ?test ...	output field 5 if passed and != EXPECTED, silent otherwise
-		//     &test ...	output field 5 if current and previous passed
-		//     |test ...	output field 5 if current passed and previous failed
-		//     ; ...	output field 2 if previous failed
-		//     {test ...	skip if failed until }
-		//     }		end of skip
-		// 
-		//     : comment		comment copied as output NOTE
-		//     :comment:test	:comment: ignored
-		//     N[OTE] comment	comment copied as output NOTE
-		//     T[EST] comment	comment
-		// 
-		//     number		use number for nmatch (20 by default)
-		flag := field[0]
-		switch flag[0] {
-		case '?', '&', '|', ';', '{', '}':
-			// Ignore all the control operators.
-			// Just run everything.
-			flag = flag[1:]
-			if flag == "" {
-				continue Reading
-			}
-		case ':':
-			i := strings.Index(flag[1:], ":")
-			if i < 0 {
-				t.Logf("skip: %s", line)
-				continue Reading
-			}
-			flag = flag[1+i+1:]
-		case 'C', 'N', 'T', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
-			t.Logf("skip: %s", line)
-			continue Reading
-		}
-
-		// Can check field count now that we've handled the myriad comment formats.
-		if len(field) < 4 {
-			t.Errorf("%s:%d: too few fields: %s", file, lineno, line)
-			continue Reading
-		}
-
-		// Expand C escapes (a.k.a. Go escapes).
-		if strings.Contains(flag, "$") {
-			f := `"` + field[1] + `"`
-			if field[1], err = strconv.Unquote(f); err != nil {
-				t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
-			}
-			f = `"` + field[2] + `"`
-			if field[2], err = strconv.Unquote(f); err != nil {
-				t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
-			}
-		}
-
-		//   Field 2: the regular expression pattern; SAME uses the pattern from
-		//     the previous specification.
-		// 
-		if field[1] == "SAME" {
-			field[1] = lastRegexp
-		}
-		lastRegexp = field[1]
-
-		//   Field 3: the string to match.
-		text := field[2]
-
-		//   Field 4: the test outcome...
-		ok, shouldCompile, shouldMatch, pos := parseFowlerResult(field[3])
-		if !ok {
-			t.Errorf("%s:%d: cannot parse result %#q", file, lineno, field[3])
-			continue Reading
-		}
-
-		//   Field 5: optional comment appended to the report.
-
-	Testing:
-		// Run test once for each specified capital letter mode that we support.
-		for _, c := range flag {
-			pattern := field[1]
-			syn := syntax.POSIX | syntax.ClassNL
-			switch c {
-			default:
-				continue Testing
-			case 'E':
-				// extended regexp (what we support)
-			case 'L':
-				// literal
-				pattern = QuoteMeta(pattern)
-			}
-
-			for _, c := range flag {
-				switch c {
-				case 'i':
-					syn |= syntax.FoldCase
-				}
-			}
-
-			re, err := compile(pattern, syn, true)
-			if err != nil {
-				if shouldCompile {
-					t.Errorf("%s:%d: %#q did not compile", file, lineno, pattern)
-				}
-				continue Testing
-			}
-			if !shouldCompile {
-				t.Errorf("%s:%d: %#q should not compile", file, lineno, pattern)
-				continue Testing
-			}
-			match := re.MatchString(text)
-			if match != shouldMatch {
-				t.Errorf("%s:%d: %#q.Match(%#q) = %v, want %v", file, lineno, pattern, text, match, shouldMatch)
-				continue Testing
-			}
-			have := re.FindStringSubmatchIndex(text)
-			if (len(have) > 0) != match {
-				t.Errorf("%s:%d: %#q.Match(%#q) = %v, but %#q.FindSubmatchIndex(%#q) = %v", file, lineno, pattern, text, match, pattern, text, have)
-				continue Testing
-			}
-			if len(have) > len(pos) {
-				have = have[:len(pos)]
-			}
-			if !same(have, pos) {
-				t.Errorf("%s:%d: %#q.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, pattern, text, have, pos)
-			}
-		}
-	}
-}
-
-func parseFowlerResult(s string) (ok, compiled, matched bool, pos []int) {
-	//   Field 4: the test outcome. This is either one of the posix error
-	//     codes (with REG_ omitted) or the match array, a list of (m,n)
-	//     entries with m and n being first and last+1 positions in the
-	//     field 3 string, or NULL if REG_NOSUB is in effect and success
-	//     is expected. BADPAT is acceptable in place of any regcomp(3)
-	//     error code. The match[] array is initialized to (-2,-2) before
-	//     each test. All array elements from 0 to nmatch-1 must be specified
-	//     in the outcome. Unspecified endpoints (offset -1) are denoted by ?.
-	//     Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a
-	//     matched (?{...}) expression, where x is the text enclosed by {...},
-	//     o is the expression ordinal counting from 1, and n is the length of
-	//     the unmatched portion of the subject string. If x starts with a
-	//     number then that is the return value of re_execf(), otherwise 0 is
-	//     returned.
-	switch {
-	case s == "":
-		// Match with no position information.
-		ok = true
-		compiled = true
-		matched = true
-		return
-	case s == "NOMATCH":
-		// Match failure.
-		ok = true
-		compiled = true
-		matched = false
-		return
-	case 'A' <= s[0] && s[0] <= 'Z':
-		// All the other error codes are compile errors.
-		ok = true
-		compiled = false
-		return
-	}
-	compiled = true
-
-	var x []int
-	for s != "" {
-		var end byte = ')'
-		if len(x)%2 == 0 {
-			if s[0] != '(' {
-				ok = false
-				return
-			}
-			s = s[1:]
-			end = ','
-		}
-		i := 0
-		for i < len(s) && s[i] != end {
-			i++
-		}
-		if i == 0 || i == len(s) {
-			ok = false
-			return
-		}
-		var v = -1
-		var err os.Error
-		if s[:i] != "?" {
-			v, err = strconv.Atoi(s[:i])
-			if err != nil {
-				ok = false
-				return
-			}
-		}
-		x = append(x, v)
-		s = s[i+1:]
-	}
-	if len(x)%2 != 0 {
-		ok = false
-		return
-	}
-	ok = true
-	matched = true
-	pos = x
-	return
-}
diff --git a/src/pkg/exp/regexp/find_test.go b/src/pkg/exp/regexp/find_test.go
deleted file mode 100644
index e07eb7d..0000000
--- a/src/pkg/exp/regexp/find_test.go
+++ /dev/null
@@ -1,498 +0,0 @@
-// Copyright 2010 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 regexp
-
-import (
-	"fmt"
-	"strings"
-	"testing"
-)
-
-// For each pattern/text pair, what is the expected output of each function?
-// We can derive the textual results from the indexed results, the non-submatch
-// results from the submatched results, the single results from the 'all' results,
-// and the byte results from the string results. Therefore the table includes
-// only the FindAllStringSubmatchIndex result.
-type FindTest struct {
-	pat     string
-	text    string
-	matches [][]int
-}
-
-func (t FindTest) String() string {
-	return fmt.Sprintf("pat: %#q text: %#q", t.pat, t.text)
-}
-
-var findTests = []FindTest{
-	{``, ``, build(1, 0, 0)},
-	{`^abcdefg`, "abcdefg", build(1, 0, 7)},
-	{`a+`, "baaab", build(1, 1, 4)},
-	{"abcd..", "abcdef", build(1, 0, 6)},
-	{`a`, "a", build(1, 0, 1)},
-	{`x`, "y", nil},
-	{`b`, "abc", build(1, 1, 2)},
-	{`.`, "a", build(1, 0, 1)},
-	{`.*`, "abcdef", build(1, 0, 6)},
-	{`^`, "abcde", build(1, 0, 0)},
-	{`$`, "abcde", build(1, 5, 5)},
-	{`^abcd$`, "abcd", build(1, 0, 4)},
-	{`^bcd'`, "abcdef", nil},
-	{`^abcd$`, "abcde", nil},
-	{`a+`, "baaab", build(1, 1, 4)},
-	{`a*`, "baaab", build(3, 0, 0, 1, 4, 5, 5)},
-	{`[a-z]+`, "abcd", build(1, 0, 4)},
-	{`[^a-z]+`, "ab1234cd", build(1, 2, 6)},
-	{`[a\-\]z]+`, "az]-bcz", build(2, 0, 4, 6, 7)},
-	{`[^\n]+`, "abcd\n", build(1, 0, 4)},
-	{`[日本語]+`, "日本語日本語", build(1, 0, 18)},
-	{`日本語+`, "日本語", build(1, 0, 9)},
-	{`日本語+`, "日本語語語語", build(1, 0, 18)},
-	{`()`, "", build(1, 0, 0, 0, 0)},
-	{`(a)`, "a", build(1, 0, 1, 0, 1)},
-	{`(.)(.)`, "æ—¥a", build(1, 0, 4, 0, 3, 3, 4)},
-	{`(.*)`, "", build(1, 0, 0, 0, 0)},
-	{`(.*)`, "abcd", build(1, 0, 4, 0, 4)},
-	{`(..)(..)`, "abcd", build(1, 0, 4, 0, 2, 2, 4)},
-	{`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)},
-	{`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)},
-	{`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
-	{`\a\f\n\r\t\v`, "\a\f\n\r\t\v", build(1, 0, 6)},
-	{`[\a\f\n\r\t\v]+`, "\a\f\n\r\t\v", build(1, 0, 6)},
-
-	{`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)},
-	{`(.*).*`, "ab", build(1, 0, 2, 0, 2)},
-	{`[.]`, ".", build(1, 0, 1)},
-	{`/$`, "/abc/", build(1, 4, 5)},
-	{`/$`, "/abc", nil},
-
-	// multiple matches
-	{`.`, "abc", build(3, 0, 1, 1, 2, 2, 3)},
-	{`(.)`, "abc", build(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)},
-	{`.(.)`, "abcd", build(2, 0, 2, 1, 2, 2, 4, 3, 4)},
-	{`ab*`, "abbaab", build(3, 0, 3, 3, 4, 4, 6)},
-	{`a(b*)`, "abbaab", build(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)},
-
-	// fixed bugs
-	{`ab$`, "cab", build(1, 1, 3)},
-	{`axxb$`, "axxcb", nil},
-	{`data`, "daXY data", build(1, 5, 9)},
-	{`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
-	{`zx+`, "zzx", build(1, 1, 3)},
-	{`ab$`, "abcab", build(1, 3, 5)},
-	{`(aa)*$`, "a", build(1, 1, 1, -1, -1)},
-	{`(?:.|(?:.a))`, "", nil},
-	{`(?:A(?:A|a))`, "Aa", build(1, 0, 2)},
-	{`(?:A|(?:A|a))`, "a", build(1, 0, 1)},
-	{`(a){0}`, "", build(1, 0, 0, -1, -1)},
-	{`(?-s)(?:(?:^).)`, "\n", nil},
-	{`(?s)(?:(?:^).)`, "\n", build(1, 0, 1)},
-	{`(?:(?:^).)`, "\n", nil},
-	{`\b`, "x", build(2, 0, 0, 1, 1)},
-	{`\b`, "xx", build(2, 0, 0, 2, 2)},
-	{`\b`, "x y", build(4, 0, 0, 1, 1, 2, 2, 3, 3)},
-	{`\b`, "xx yy", build(4, 0, 0, 2, 2, 3, 3, 5, 5)},
-	{`\B`, "x", nil},
-	{`\B`, "xx", build(1, 1, 1)},
-	{`\B`, "x y", nil},
-	{`\B`, "xx yy", build(2, 1, 1, 4, 4)},
-
-	// RE2 tests
-	{`[^\S\s]`, "abcd", nil},
-	{`[^\S[:space:]]`, "abcd", nil},
-	{`[^\D\d]`, "abcd", nil},
-	{`[^\D[:digit:]]`, "abcd", nil},
-	{`(?i)\W`, "x", nil},
-	{`(?i)\W`, "k", nil},
-	{`(?i)\W`, "s", nil},
-
-	// can backslash-escape any punctuation
-	{`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
-		`!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
-	{`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`,
-		`!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
-	{"\\`", "`", build(1, 0, 1)},
-	{"[\\`]+", "`", build(1, 0, 1)},
-
-	// long set of matches (longer than startSize)
-	{
-		".",
-		"qwertyuiopasdfghjklzxcvbnm1234567890",
-		build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
-			10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
-			20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
-			30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36),
-	},
-}
-
-// build is a helper to construct a [][]int by extracting n sequences from x.
-// This represents n matches with len(x)/n submatches each.
-func build(n int, x ...int) [][]int {
-	ret := make([][]int, n)
-	runLength := len(x) / n
-	j := 0
-	for i := range ret {
-		ret[i] = make([]int, runLength)
-		copy(ret[i], x[j:])
-		j += runLength
-		if j > len(x) {
-			panic("invalid build entry")
-		}
-	}
-	return ret
-}
-
-// First the simple cases.
-
-func TestFind(t *testing.T) {
-	for _, test := range findTests {
-		re := MustCompile(test.pat)
-		if re.String() != test.pat {
-			t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat)
-		}
-		result := re.Find([]byte(test.text))
-		switch {
-		case len(test.matches) == 0 && len(result) == 0:
-			// ok
-		case test.matches == nil && result != nil:
-			t.Errorf("expected no match; got one: %s", test)
-		case test.matches != nil && result == nil:
-			t.Errorf("expected match; got none: %s", test)
-		case test.matches != nil && result != nil:
-			expect := test.text[test.matches[0][0]:test.matches[0][1]]
-			if expect != string(result) {
-				t.Errorf("expected %q got %q: %s", expect, result, test)
-			}
-		}
-	}
-}
-
-func TestFindString(t *testing.T) {
-	for _, test := range findTests {
-		result := MustCompile(test.pat).FindString(test.text)
-		switch {
-		case len(test.matches) == 0 && len(result) == 0:
-			// ok
-		case test.matches == nil && result != "":
-			t.Errorf("expected no match; got one: %s", test)
-		case test.matches != nil && result == "":
-			// Tricky because an empty result has two meanings: no match or empty match.
-			if test.matches[0][0] != test.matches[0][1] {
-				t.Errorf("expected match; got none: %s", test)
-			}
-		case test.matches != nil && result != "":
-			expect := test.text[test.matches[0][0]:test.matches[0][1]]
-			if expect != result {
-				t.Errorf("expected %q got %q: %s", expect, result, test)
-			}
-		}
-	}
-}
-
-func testFindIndex(test *FindTest, result []int, t *testing.T) {
-	switch {
-	case len(test.matches) == 0 && len(result) == 0:
-		// ok
-	case test.matches == nil && result != nil:
-		t.Errorf("expected no match; got one: %s", test)
-	case test.matches != nil && result == nil:
-		t.Errorf("expected match; got none: %s", test)
-	case test.matches != nil && result != nil:
-		expect := test.matches[0]
-		if expect[0] != result[0] || expect[1] != result[1] {
-			t.Errorf("expected %v got %v: %s", expect, result, test)
-		}
-	}
-}
-
-func TestFindIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test.text)), t)
-	}
-}
-
-func TestFindStringIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.text), t)
-	}
-}
-
-func TestFindReaderIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strings.NewReader(test.text)), t)
-	}
-}
-
-// Now come the simple All cases.
-
-func TestFindAll(t *testing.T) {
-	for _, test := range findTests {
-		result := MustCompile(test.pat).FindAll([]byte(test.text), -1)
-		switch {
-		case test.matches == nil && result == nil:
-			// ok
-		case test.matches == nil && result != nil:
-			t.Errorf("expected no match; got one: %s", test)
-		case test.matches != nil && result == nil:
-			t.Fatalf("expected match; got none: %s", test)
-		case test.matches != nil && result != nil:
-			if len(test.matches) != len(result) {
-				t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
-				continue
-			}
-			for k, e := range test.matches {
-				expect := test.text[e[0]:e[1]]
-				if expect != string(result[k]) {
-					t.Errorf("match %d: expected %q got %q: %s", k, expect, result[k], test)
-				}
-			}
-		}
-	}
-}
-
-func TestFindAllString(t *testing.T) {
-	for _, test := range findTests {
-		result := MustCompile(test.pat).FindAllString(test.text, -1)
-		switch {
-		case test.matches == nil && result == nil:
-			// ok
-		case test.matches == nil && result != nil:
-			t.Errorf("expected no match; got one: %s", test)
-		case test.matches != nil && result == nil:
-			t.Errorf("expected match; got none: %s", test)
-		case test.matches != nil && result != nil:
-			if len(test.matches) != len(result) {
-				t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
-				continue
-			}
-			for k, e := range test.matches {
-				expect := test.text[e[0]:e[1]]
-				if expect != result[k] {
-					t.Errorf("expected %q got %q: %s", expect, result, test)
-				}
-			}
-		}
-	}
-}
-
-func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) {
-	switch {
-	case test.matches == nil && result == nil:
-		// ok
-	case test.matches == nil && result != nil:
-		t.Errorf("expected no match; got one: %s", test)
-	case test.matches != nil && result == nil:
-		t.Errorf("expected match; got none: %s", test)
-	case test.matches != nil && result != nil:
-		if len(test.matches) != len(result) {
-			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
-			return
-		}
-		for k, e := range test.matches {
-			if e[0] != result[k][0] || e[1] != result[k][1] {
-				t.Errorf("match %d: expected %v got %v: %s", k, e, result[k], test)
-			}
-		}
-	}
-}
-
-func TestFindAllIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byte(test.text), -1), t)
-	}
-}
-
-func TestFindAllStringIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex(test.text, -1), t)
-	}
-}
-
-// Now come the Submatch cases.
-
-func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte, t *testing.T) {
-	if len(submatches) != len(result)*2 {
-		t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
-		return
-	}
-	for k := 0; k < len(submatches); k += 2 {
-		if submatches[k] == -1 {
-			if result[k/2] != nil {
-				t.Errorf("match %d: expected nil got %q: %s", n, result, test)
-			}
-			continue
-		}
-		expect := test.text[submatches[k]:submatches[k+1]]
-		if expect != string(result[k/2]) {
-			t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
-			return
-		}
-	}
-}
-
-func TestFindSubmatch(t *testing.T) {
-	for _, test := range findTests {
-		result := MustCompile(test.pat).FindSubmatch([]byte(test.text))
-		switch {
-		case test.matches == nil && result == nil:
-			// ok
-		case test.matches == nil && result != nil:
-			t.Errorf("expected no match; got one: %s", test)
-		case test.matches != nil && result == nil:
-			t.Errorf("expected match; got none: %s", test)
-		case test.matches != nil && result != nil:
-			testSubmatchBytes(&test, 0, test.matches[0], result, t)
-		}
-	}
-}
-
-func testSubmatchString(test *FindTest, n int, submatches []int, result []string, t *testing.T) {
-	if len(submatches) != len(result)*2 {
-		t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
-		return
-	}
-	for k := 0; k < len(submatches); k += 2 {
-		if submatches[k] == -1 {
-			if result[k/2] != "" {
-				t.Errorf("match %d: expected nil got %q: %s", n, result, test)
-			}
-			continue
-		}
-		expect := test.text[submatches[k]:submatches[k+1]]
-		if expect != result[k/2] {
-			t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
-			return
-		}
-	}
-}
-
-func TestFindStringSubmatch(t *testing.T) {
-	for _, test := range findTests {
-		result := MustCompile(test.pat).FindStringSubmatch(test.text)
-		switch {
-		case test.matches == nil && result == nil:
-			// ok
-		case test.matches == nil && result != nil:
-			t.Errorf("expected no match; got one: %s", test)
-		case test.matches != nil && result == nil:
-			t.Errorf("expected match; got none: %s", test)
-		case test.matches != nil && result != nil:
-			testSubmatchString(&test, 0, test.matches[0], result, t)
-		}
-	}
-}
-
-func testSubmatchIndices(test *FindTest, n int, expect, result []int, t *testing.T) {
-	if len(expect) != len(result) {
-		t.Errorf("match %d: expected %d matches; got %d: %s", n, len(expect)/2, len(result)/2, test)
-		return
-	}
-	for k, e := range expect {
-		if e != result[k] {
-			t.Errorf("match %d: submatch error: expected %v got %v: %s", n, expect, result, test)
-		}
-	}
-}
-
-func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) {
-	switch {
-	case test.matches == nil && result == nil:
-		// ok
-	case test.matches == nil && result != nil:
-		t.Errorf("expected no match; got one: %s", test)
-	case test.matches != nil && result == nil:
-		t.Errorf("expected match; got none: %s", test)
-	case test.matches != nil && result != nil:
-		testSubmatchIndices(test, 0, test.matches[0], result, t)
-	}
-}
-
-func TestFindSubmatchIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchIndex([]byte(test.text)), t)
-	}
-}
-
-func TestFindStringSubmatchIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSubmatchIndex(test.text), t)
-	}
-}
-
-func TestFindReaderSubmatchIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSubmatchIndex(strings.NewReader(test.text)), t)
-	}
-}
-
-// Now come the monster AllSubmatch cases.
-
-func TestFindAllSubmatch(t *testing.T) {
-	for _, test := range findTests {
-		result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text), -1)
-		switch {
-		case test.matches == nil && result == nil:
-			// ok
-		case test.matches == nil && result != nil:
-			t.Errorf("expected no match; got one: %s", test)
-		case test.matches != nil && result == nil:
-			t.Errorf("expected match; got none: %s", test)
-		case len(test.matches) != len(result):
-			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
-		case test.matches != nil && result != nil:
-			for k, match := range test.matches {
-				testSubmatchBytes(&test, k, match, result[k], t)
-			}
-		}
-	}
-}
-
-func TestFindAllStringSubmatch(t *testing.T) {
-	for _, test := range findTests {
-		result := MustCompile(test.pat).FindAllStringSubmatch(test.text, -1)
-		switch {
-		case test.matches == nil && result == nil:
-			// ok
-		case test.matches == nil && result != nil:
-			t.Errorf("expected no match; got one: %s", test)
-		case test.matches != nil && result == nil:
-			t.Errorf("expected match; got none: %s", test)
-		case len(test.matches) != len(result):
-			t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
-		case test.matches != nil && result != nil:
-			for k, match := range test.matches {
-				testSubmatchString(&test, k, match, result[k], t)
-			}
-		}
-	}
-}
-
-func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) {
-	switch {
-	case test.matches == nil && result == nil:
-		// ok
-	case test.matches == nil && result != nil:
-		t.Errorf("expected no match; got one: %s", test)
-	case test.matches != nil && result == nil:
-		t.Errorf("expected match; got none: %s", test)
-	case len(test.matches) != len(result):
-		t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
-	case test.matches != nil && result != nil:
-		for k, match := range test.matches {
-			testSubmatchIndices(test, k, match, result[k], t)
-		}
-	}
-}
-
-func TestFindAllSubmatchIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSubmatchIndex([]byte(test.text), -1), t)
-	}
-}
-
-func TestFindAllStringSubmatchIndex(t *testing.T) {
-	for _, test := range findTests {
-		testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStringSubmatchIndex(test.text, -1), t)
-	}
-}
diff --git a/src/pkg/exp/regexp/regexp.go b/src/pkg/exp/regexp/regexp.go
deleted file mode 100644
index 7480b09..0000000
--- a/src/pkg/exp/regexp/regexp.go
+++ /dev/null
@@ -1,897 +0,0 @@
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package regexp implements a simple regular expression library.
-//
-// The syntax of the regular expressions accepted is the same
-// general syntax used by Perl, Python, and other languages.
-// More precisely, it is the syntax accepted by RE2 and described at
-// http://code.google.com/p/re2/wiki/Syntax, except for \C.
-//
-// All characters are UTF-8-encoded code points.
-//
-// There are 16 methods of Regexp that match a regular expression and identify
-// the matched text.  Their names are matched by this regular expression:
-//
-//	Find(All)?(String)?(Submatch)?(Index)?
-//
-// If 'All' is present, the routine matches successive non-overlapping
-// matches of the entire expression.  Empty matches abutting a preceding
-// match are ignored.  The return value is a slice containing the successive
-// return values of the corresponding non-'All' routine.  These routines take
-// an extra integer argument, n; if n >= 0, the function returns at most n
-// matches/submatches.
-//
-// If 'String' is present, the argument is a string; otherwise it is a slice
-// of bytes; return values are adjusted as appropriate.
-//
-// If 'Submatch' is present, the return value is a slice identifying the
-// successive submatches of the expression.  Submatches are matches of
-// parenthesized subexpressions within the regular expression, numbered from
-// left to right in order of opening parenthesis.  Submatch 0 is the match of
-// the entire expression, submatch 1 the match of the first parenthesized
-// subexpression, and so on.
-//
-// If 'Index' is present, matches and submatches are identified by byte index
-// pairs within the input string: result[2*n:2*n+1] identifies the indexes of
-// the nth submatch.  The pair for n==0 identifies the match of the entire
-// expression.  If 'Index' is not present, the match is identified by the
-// text of the match/submatch.  If an index is negative, it means that
-// subexpression did not match any string in the input.
-//
-// There is also a subset of the methods that can be applied to text read
-// from a RuneReader:
-//
-//	MatchReader, FindReaderIndex, FindReaderSubmatchIndex
-//
-// This set may grow.  Note that regular expression matches may need to
-// examine text beyond the text returned by a match, so the methods that
-// match text from a RuneReader may read arbitrarily far into the input
-// before returning.
-//
-// (There are a few other methods that do not match this pattern.)
-//
-package regexp
-
-import (
-	"bytes"
-	"exp/regexp/syntax"
-	"io"
-	"os"
-	"strconv"
-	"strings"
-	"sync"
-	"utf8"
-)
-
-var debug = false
-
-// Error is the local type for a parsing error.
-type Error string
-
-func (e Error) String() string {
-	return string(e)
-}
-
-// Regexp is the representation of a compiled regular expression.
-// The public interface is entirely through methods.
-// A Regexp is safe for concurrent use by multiple goroutines.
-type Regexp struct {
-	// read-only after Compile
-	expr           string         // as passed to Compile
-	prog           *syntax.Prog   // compiled program
-	prefix         string         // required prefix in unanchored matches
-	prefixBytes    []byte         // prefix, as a []byte
-	prefixComplete bool           // prefix is the entire regexp
-	prefixRune     int            // first rune in prefix
-	cond           syntax.EmptyOp // empty-width conditions required at start of match
-	numSubexp      int
-	longest        bool
-
-	// cache of machines for running regexp
-	mu      sync.Mutex
-	machine []*machine
-}
-
-// String returns the source text used to compile the regular expression.
-func (re *Regexp) String() string {
-	return re.expr
-}
-
-// Compile parses a regular expression and returns, if successful,
-// a Regexp object that can be used to match against text.
-//
-// When matching against text, the regexp returns a match that
-// begins as early as possible in the input (leftmost), and among those
-// it chooses the one that a backtracking search would have found first.
-// This so-called leftmost-first matching is the same semantics
-// that Perl, Python, and other implementations use, although this
-// package implements it without the expense of backtracking.
-// For POSIX leftmost-longest matching, see CompilePOSIX.
-func Compile(expr string) (*Regexp, os.Error) {
-	return compile(expr, syntax.Perl, false)
-}
-
-// CompilePOSIX is like Compile but restricts the regular expression
-// to POSIX ERE (egrep) syntax and changes the match semantics to
-// leftmost-longest.
-//
-// That is, when matching against text, the regexp returns a match that
-// begins as early as possible in the input (leftmost), and among those
-// it chooses a match that is as long as possible.
-// This so-called leftmost-longest matching is the same semantics
-// that early regular expression implementations used and that POSIX
-// specifies.
-//
-// However, there can be multiple leftmost-longest matches, with different
-// submatch choices, and here this package diverges from POSIX.
-// Among the possible leftmost-longest matches, this package chooses
-// the one that a backtracking search would have found first, while POSIX
-// specifies that the match be chosen to maximize the length of the first
-// subexpression, then the second, and so on from left to right.
-// The POSIX rule is computationally prohibitive and not even well-defined.
-// See http://swtch.com/~rsc/regexp/regexp2.html#posix for details.
-func CompilePOSIX(expr string) (*Regexp, os.Error) {
-	return compile(expr, syntax.POSIX, true)
-}
-
-func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, os.Error) {
-	re, err := syntax.Parse(expr, mode)
-	if err != nil {
-		return nil, err
-	}
-	maxCap := re.MaxCap()
-	re = re.Simplify()
-	prog, err := syntax.Compile(re)
-	if err != nil {
-		return nil, err
-	}
-	regexp := &Regexp{
-		expr:      expr,
-		prog:      prog,
-		numSubexp: maxCap,
-		cond:      prog.StartCond(),
-		longest:   longest,
-	}
-	regexp.prefix, regexp.prefixComplete = prog.Prefix()
-	if regexp.prefix != "" {
-		// TODO(rsc): Remove this allocation by adding
-		// IndexString to package bytes.
-		regexp.prefixBytes = []byte(regexp.prefix)
-		regexp.prefixRune, _ = utf8.DecodeRuneInString(regexp.prefix)
-	}
-	return regexp, nil
-}
-
-// get returns a machine to use for matching re.
-// It uses the re's machine cache if possible, to avoid
-// unnecessary allocation.
-func (re *Regexp) get() *machine {
-	re.mu.Lock()
-	if n := len(re.machine); n > 0 {
-		z := re.machine[n-1]
-		re.machine = re.machine[:n-1]
-		re.mu.Unlock()
-		return z
-	}
-	re.mu.Unlock()
-	z := progMachine(re.prog)
-	z.re = re
-	return z
-}
-
-// put returns a machine to the re's machine cache.
-// There is no attempt to limit the size of the cache, so it will
-// grow to the maximum number of simultaneous matches
-// run using re.  (The cache empties when re gets garbage collected.)
-func (re *Regexp) put(z *machine) {
-	re.mu.Lock()
-	re.machine = append(re.machine, z)
-	re.mu.Unlock()
-}
-
-// MustCompile is like Compile but panics if the expression cannot be parsed.
-// It simplifies safe initialization of global variables holding compiled regular
-// expressions.
-func MustCompile(str string) *Regexp {
-	regexp, error := Compile(str)
-	if error != nil {
-		panic(`regexp: Compile(` + quote(str) + `): ` + error.String())
-	}
-	return regexp
-}
-
-// MustCompilePOSIX is like CompilePOSIX but panics if the expression cannot be parsed.
-// It simplifies safe initialization of global variables holding compiled regular
-// expressions.
-func MustCompilePOSIX(str string) *Regexp {
-	regexp, error := CompilePOSIX(str)
-	if error != nil {
-		panic(`regexp: CompilePOSIX(` + quote(str) + `): ` + error.String())
-	}
-	return regexp
-}
-
-func quote(s string) string {
-	if strconv.CanBackquote(s) {
-		return "`" + s + "`"
-	}
-	return strconv.Quote(s)
-}
-
-// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
-func (re *Regexp) NumSubexp() int {
-	return re.numSubexp
-}
-
-const endOfText = -1
-
-// input abstracts different representations of the input text. It provides
-// one-character lookahead.
-type input interface {
-	step(pos int) (rune int, width int) // advance one rune
-	canCheckPrefix() bool               // can we look ahead without losing info?
-	hasPrefix(re *Regexp) bool
-	index(re *Regexp, pos int) int
-	context(pos int) syntax.EmptyOp
-}
-
-// inputString scans a string.
-type inputString struct {
-	str string
-}
-
-func newInputString(str string) *inputString {
-	return &inputString{str: str}
-}
-
-func (i *inputString) step(pos int) (int, int) {
-	if pos < len(i.str) {
-		return utf8.DecodeRuneInString(i.str[pos:len(i.str)])
-	}
-	return endOfText, 0
-}
-
-func (i *inputString) canCheckPrefix() bool {
-	return true
-}
-
-func (i *inputString) hasPrefix(re *Regexp) bool {
-	return strings.HasPrefix(i.str, re.prefix)
-}
-
-func (i *inputString) index(re *Regexp, pos int) int {
-	return strings.Index(i.str[pos:], re.prefix)
-}
-
-func (i *inputString) context(pos int) syntax.EmptyOp {
-	r1, r2 := -1, -1
-	if pos > 0 && pos <= len(i.str) {
-		r1, _ = utf8.DecodeLastRuneInString(i.str[:pos])
-	}
-	if pos < len(i.str) {
-		r2, _ = utf8.DecodeRuneInString(i.str[pos:])
-	}
-	return syntax.EmptyOpContext(r1, r2)
-}
-
-// inputBytes scans a byte slice.
-type inputBytes struct {
-	str []byte
-}
-
-func newInputBytes(str []byte) *inputBytes {
-	return &inputBytes{str: str}
-}
-
-func (i *inputBytes) step(pos int) (int, int) {
-	if pos < len(i.str) {
-		return utf8.DecodeRune(i.str[pos:len(i.str)])
-	}
-	return endOfText, 0
-}
-
-func (i *inputBytes) canCheckPrefix() bool {
-	return true
-}
-
-func (i *inputBytes) hasPrefix(re *Regexp) bool {
-	return bytes.HasPrefix(i.str, re.prefixBytes)
-}
-
-func (i *inputBytes) index(re *Regexp, pos int) int {
-	return bytes.Index(i.str[pos:], re.prefixBytes)
-}
-
-func (i *inputBytes) context(pos int) syntax.EmptyOp {
-	r1, r2 := -1, -1
-	if pos > 0 && pos <= len(i.str) {
-		r1, _ = utf8.DecodeLastRune(i.str[:pos])
-	}
-	if pos < len(i.str) {
-		r2, _ = utf8.DecodeRune(i.str[pos:])
-	}
-	return syntax.EmptyOpContext(r1, r2)
-}
-
-// inputReader scans a RuneReader.
-type inputReader struct {
-	r     io.RuneReader
-	atEOT bool
-	pos   int
-}
-
-func newInputReader(r io.RuneReader) *inputReader {
-	return &inputReader{r: r}
-}
-
-func (i *inputReader) step(pos int) (int, int) {
-	if !i.atEOT && pos != i.pos {
-		return endOfText, 0
-
-	}
-	r, w, err := i.r.ReadRune()
-	if err != nil {
-		i.atEOT = true
-		return endOfText, 0
-	}
-	i.pos += w
-	return r, w
-}
-
-func (i *inputReader) canCheckPrefix() bool {
-	return false
-}
-
-func (i *inputReader) hasPrefix(re *Regexp) bool {
-	return false
-}
-
-func (i *inputReader) index(re *Regexp, pos int) int {
-	return -1
-}
-
-func (i *inputReader) context(pos int) syntax.EmptyOp {
-	return 0
-}
-
-// LiteralPrefix returns a literal string that must begin any match
-// of the regular expression re.  It returns the boolean true if the
-// literal string comprises the entire regular expression.
-func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
-	return re.prefix, re.prefixComplete
-}
-
-// MatchReader returns whether the Regexp matches the text read by the
-// RuneReader.  The return value is a boolean: true for match, false for no
-// match.
-func (re *Regexp) MatchReader(r io.RuneReader) bool {
-	return re.doExecute(newInputReader(r), 0, 0) != nil
-}
-
-// MatchString returns whether the Regexp matches the string s.
-// The return value is a boolean: true for match, false for no match.
-func (re *Regexp) MatchString(s string) bool {
-	return re.doExecute(newInputString(s), 0, 0) != nil
-}
-
-// Match returns whether the Regexp matches the byte slice b.
-// The return value is a boolean: true for match, false for no match.
-func (re *Regexp) Match(b []byte) bool {
-	return re.doExecute(newInputBytes(b), 0, 0) != nil
-}
-
-// MatchReader checks whether a textual regular expression matches the text
-// read by the RuneReader.  More complicated queries need to use Compile and
-// the full Regexp interface.
-func MatchReader(pattern string, r io.RuneReader) (matched bool, error os.Error) {
-	re, err := Compile(pattern)
-	if err != nil {
-		return false, err
-	}
-	return re.MatchReader(r), nil
-}
-
-// MatchString checks whether a textual regular expression
-// matches a string.  More complicated queries need
-// to use Compile and the full Regexp interface.
-func MatchString(pattern string, s string) (matched bool, error os.Error) {
-	re, err := Compile(pattern)
-	if err != nil {
-		return false, err
-	}
-	return re.MatchString(s), nil
-}
-
-// Match checks whether a textual regular expression
-// matches a byte slice.  More complicated queries need
-// to use Compile and the full Regexp interface.
-func Match(pattern string, b []byte) (matched bool, error os.Error) {
-	re, err := Compile(pattern)
-	if err != nil {
-		return false, err
-	}
-	return re.Match(b), nil
-}
-
-// ReplaceAllString returns a copy of src in which all matches for the Regexp
-// have been replaced by repl.  No support is provided for expressions
-// (e.g. \1 or $1) in the replacement string.
-func (re *Regexp) ReplaceAllString(src, repl string) string {
-	return re.ReplaceAllStringFunc(src, func(string) string { return repl })
-}
-
-// ReplaceAllStringFunc returns a copy of src in which all matches for the
-// Regexp have been replaced by the return value of of function repl (whose
-// first argument is the matched string).  No support is provided for
-// expressions (e.g. \1 or $1) in the replacement string.
-func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
-	lastMatchEnd := 0 // end position of the most recent match
-	searchPos := 0    // position where we next look for a match
-	buf := new(bytes.Buffer)
-	for searchPos <= len(src) {
-		a := re.doExecute(newInputString(src), searchPos, 2)
-		if len(a) == 0 {
-			break // no more matches
-		}
-
-		// Copy the unmatched characters before this match.
-		io.WriteString(buf, src[lastMatchEnd:a[0]])
-
-		// Now insert a copy of the replacement string, but not for a
-		// match of the empty string immediately after another match.
-		// (Otherwise, we get double replacement for patterns that
-		// match both empty and nonempty strings.)
-		if a[1] > lastMatchEnd || a[0] == 0 {
-			io.WriteString(buf, repl(src[a[0]:a[1]]))
-		}
-		lastMatchEnd = a[1]
-
-		// Advance past this match; always advance at least one character.
-		_, width := utf8.DecodeRuneInString(src[searchPos:])
-		if searchPos+width > a[1] {
-			searchPos += width
-		} else if searchPos+1 > a[1] {
-			// This clause is only needed at the end of the input
-			// string.  In that case, DecodeRuneInString returns width=0.
-			searchPos++
-		} else {
-			searchPos = a[1]
-		}
-	}
-
-	// Copy the unmatched characters after the last match.
-	io.WriteString(buf, src[lastMatchEnd:])
-
-	return buf.String()
-}
-
-// ReplaceAll returns a copy of src in which all matches for the Regexp
-// have been replaced by repl.  No support is provided for expressions
-// (e.g. \1 or $1) in the replacement text.
-func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
-	return re.ReplaceAllFunc(src, func([]byte) []byte { return repl })
-}
-
-// ReplaceAllFunc returns a copy of src in which all matches for the
-// Regexp have been replaced by the return value of of function repl (whose
-// first argument is the matched []byte).  No support is provided for
-// expressions (e.g. \1 or $1) in the replacement string.
-func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
-	lastMatchEnd := 0 // end position of the most recent match
-	searchPos := 0    // position where we next look for a match
-	buf := new(bytes.Buffer)
-	for searchPos <= len(src) {
-		a := re.doExecute(newInputBytes(src), searchPos, 2)
-		if len(a) == 0 {
-			break // no more matches
-		}
-
-		// Copy the unmatched characters before this match.
-		buf.Write(src[lastMatchEnd:a[0]])
-
-		// Now insert a copy of the replacement string, but not for a
-		// match of the empty string immediately after another match.
-		// (Otherwise, we get double replacement for patterns that
-		// match both empty and nonempty strings.)
-		if a[1] > lastMatchEnd || a[0] == 0 {
-			buf.Write(repl(src[a[0]:a[1]]))
-		}
-		lastMatchEnd = a[1]
-
-		// Advance past this match; always advance at least one character.
-		_, width := utf8.DecodeRune(src[searchPos:])
-		if searchPos+width > a[1] {
-			searchPos += width
-		} else if searchPos+1 > a[1] {
-			// This clause is only needed at the end of the input
-			// string.  In that case, DecodeRuneInString returns width=0.
-			searchPos++
-		} else {
-			searchPos = a[1]
-		}
-	}
-
-	// Copy the unmatched characters after the last match.
-	buf.Write(src[lastMatchEnd:])
-
-	return buf.Bytes()
-}
-
-var specialBytes = []byte(`\.+*?()|[]{}^$`)
-
-func special(b byte) bool {
-	return bytes.IndexByte(specialBytes, b) >= 0
-}
-
-// QuoteMeta returns a string that quotes all regular expression metacharacters
-// inside the argument text; the returned string is a regular expression matching
-// the literal text.  For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
-func QuoteMeta(s string) string {
-	b := make([]byte, 2*len(s))
-
-	// A byte loop is correct because all metacharacters are ASCII.
-	j := 0
-	for i := 0; i < len(s); i++ {
-		if special(s[i]) {
-			b[j] = '\\'
-			j++
-		}
-		b[j] = s[i]
-		j++
-	}
-	return string(b[0:j])
-}
-
-// The number of capture values in the program may correspond
-// to fewer capturing expressions than are in the regexp.
-// For example, "(a){0}" turns into an empty program, so the
-// maximum capture in the program is 0 but we need to return
-// an expression for \1.  Pad appends -1s to the slice a as needed.
-func (re *Regexp) pad(a []int) []int {
-	if a == nil {
-		// No match.
-		return nil
-	}
-	n := (1 + re.numSubexp) * 2
-	for len(a) < n {
-		a = append(a, -1)
-	}
-	return a
-}
-
-// Find matches in slice b if b is non-nil, otherwise find matches in string s.
-func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
-	var end int
-	if b == nil {
-		end = len(s)
-	} else {
-		end = len(b)
-	}
-
-	for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
-		var in input
-		if b == nil {
-			in = newInputString(s)
-		} else {
-			in = newInputBytes(b)
-		}
-		matches := re.doExecute(in, pos, re.prog.NumCap)
-		if len(matches) == 0 {
-			break
-		}
-
-		accept := true
-		if matches[1] == pos {
-			// We've found an empty match.
-			if matches[0] == prevMatchEnd {
-				// We don't allow an empty match right
-				// after a previous match, so ignore it.
-				accept = false
-			}
-			var width int
-			// TODO: use step()
-			if b == nil {
-				_, width = utf8.DecodeRuneInString(s[pos:end])
-			} else {
-				_, width = utf8.DecodeRune(b[pos:end])
-			}
-			if width > 0 {
-				pos += width
-			} else {
-				pos = end + 1
-			}
-		} else {
-			pos = matches[1]
-		}
-		prevMatchEnd = matches[1]
-
-		if accept {
-			deliver(re.pad(matches))
-			i++
-		}
-	}
-}
-
-// Find returns a slice holding the text of the leftmost match in b of the regular expression.
-// A return value of nil indicates no match.
-func (re *Regexp) Find(b []byte) []byte {
-	a := re.doExecute(newInputBytes(b), 0, 2)
-	if a == nil {
-		return nil
-	}
-	return b[a[0]:a[1]]
-}
-
-// FindIndex returns a two-element slice of integers defining the location of
-// the leftmost match in b of the regular expression.  The match itself is at
-// b[loc[0]:loc[1]].
-// A return value of nil indicates no match.
-func (re *Regexp) FindIndex(b []byte) (loc []int) {
-	a := re.doExecute(newInputBytes(b), 0, 2)
-	if a == nil {
-		return nil
-	}
-	return a[0:2]
-}
-
-// FindString returns a string holding the text of the leftmost match in s of the regular
-// expression.  If there is no match, the return value is an empty string,
-// but it will also be empty if the regular expression successfully matches
-// an empty string.  Use FindStringIndex or FindStringSubmatch if it is
-// necessary to distinguish these cases.
-func (re *Regexp) FindString(s string) string {
-	a := re.doExecute(newInputString(s), 0, 2)
-	if a == nil {
-		return ""
-	}
-	return s[a[0]:a[1]]
-}
-
-// FindStringIndex returns a two-element slice of integers defining the
-// location of the leftmost match in s of the regular expression.  The match
-// itself is at s[loc[0]:loc[1]].
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringIndex(s string) []int {
-	a := re.doExecute(newInputString(s), 0, 2)
-	if a == nil {
-		return nil
-	}
-	return a[0:2]
-}
-
-// FindReaderIndex returns a two-element slice of integers defining the
-// location of the leftmost match of the regular expression in text read from
-// the RuneReader.  The match itself is at s[loc[0]:loc[1]].  A return
-// value of nil indicates no match.
-func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
-	a := re.doExecute(newInputReader(r), 0, 2)
-	if a == nil {
-		return nil
-	}
-	return a[0:2]
-}
-
-// FindSubmatch returns a slice of slices holding the text of the leftmost
-// match of the regular expression in b and the matches, if any, of its
-// subexpressions, as defined by the 'Submatch' descriptions in the package
-// comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindSubmatch(b []byte) [][]byte {
-	a := re.doExecute(newInputBytes(b), 0, re.prog.NumCap)
-	if a == nil {
-		return nil
-	}
-	ret := make([][]byte, 1+re.numSubexp)
-	for i := range ret {
-		if 2*i < len(a) && a[2*i] >= 0 {
-			ret[i] = b[a[2*i]:a[2*i+1]]
-		}
-	}
-	return ret
-}
-
-// FindSubmatchIndex returns a slice holding the index pairs identifying the
-// leftmost match of the regular expression in b and the matches, if any, of
-// its subexpressions, as defined by the 'Submatch' and 'Index' descriptions
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindSubmatchIndex(b []byte) []int {
-	return re.pad(re.doExecute(newInputBytes(b), 0, re.prog.NumCap))
-}
-
-// FindStringSubmatch returns a slice of strings holding the text of the
-// leftmost match of the regular expression in s and the matches, if any, of
-// its subexpressions, as defined by the 'Submatch' description in the
-// package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringSubmatch(s string) []string {
-	a := re.doExecute(newInputString(s), 0, re.prog.NumCap)
-	if a == nil {
-		return nil
-	}
-	ret := make([]string, 1+re.numSubexp)
-	for i := range ret {
-		if 2*i < len(a) && a[2*i] >= 0 {
-			ret[i] = s[a[2*i]:a[2*i+1]]
-		}
-	}
-	return ret
-}
-
-// FindStringSubmatchIndex returns a slice holding the index pairs
-// identifying the leftmost match of the regular expression in s and the
-// matches, if any, of its subexpressions, as defined by the 'Submatch' and
-// 'Index' descriptions in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringSubmatchIndex(s string) []int {
-	return re.pad(re.doExecute(newInputString(s), 0, re.prog.NumCap))
-}
-
-// FindReaderSubmatchIndex returns a slice holding the index pairs
-// identifying the leftmost match of the regular expression of text read by
-// the RuneReader, and the matches, if any, of its subexpressions, as defined
-// by the 'Submatch' and 'Index' descriptions in the package comment.  A
-// return value of nil indicates no match.
-func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
-	return re.pad(re.doExecute(newInputReader(r), 0, re.prog.NumCap))
-}
-
-const startSize = 10 // The size at which to start a slice in the 'All' routines.
-
-// FindAll is the 'All' version of Find; it returns a slice of all successive
-// matches of the expression, as defined by the 'All' description in the
-// package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAll(b []byte, n int) [][]byte {
-	if n < 0 {
-		n = len(b) + 1
-	}
-	result := make([][]byte, 0, startSize)
-	re.allMatches("", b, n, func(match []int) {
-		result = append(result, b[match[0]:match[1]])
-	})
-	if len(result) == 0 {
-		return nil
-	}
-	return result
-}
-
-// FindAllIndex is the 'All' version of FindIndex; it returns a slice of all
-// successive matches of the expression, as defined by the 'All' description
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllIndex(b []byte, n int) [][]int {
-	if n < 0 {
-		n = len(b) + 1
-	}
-	result := make([][]int, 0, startSize)
-	re.allMatches("", b, n, func(match []int) {
-		result = append(result, match[0:2])
-	})
-	if len(result) == 0 {
-		return nil
-	}
-	return result
-}
-
-// FindAllString is the 'All' version of FindString; it returns a slice of all
-// successive matches of the expression, as defined by the 'All' description
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllString(s string, n int) []string {
-	if n < 0 {
-		n = len(s) + 1
-	}
-	result := make([]string, 0, startSize)
-	re.allMatches(s, nil, n, func(match []int) {
-		result = append(result, s[match[0]:match[1]])
-	})
-	if len(result) == 0 {
-		return nil
-	}
-	return result
-}
-
-// FindAllStringIndex is the 'All' version of FindStringIndex; it returns a
-// slice of all successive matches of the expression, as defined by the 'All'
-// description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringIndex(s string, n int) [][]int {
-	if n < 0 {
-		n = len(s) + 1
-	}
-	result := make([][]int, 0, startSize)
-	re.allMatches(s, nil, n, func(match []int) {
-		result = append(result, match[0:2])
-	})
-	if len(result) == 0 {
-		return nil
-	}
-	return result
-}
-
-// FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice
-// of all successive matches of the expression, as defined by the 'All'
-// description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
-	if n < 0 {
-		n = len(b) + 1
-	}
-	result := make([][][]byte, 0, startSize)
-	re.allMatches("", b, n, func(match []int) {
-		slice := make([][]byte, len(match)/2)
-		for j := range slice {
-			if match[2*j] >= 0 {
-				slice[j] = b[match[2*j]:match[2*j+1]]
-			}
-		}
-		result = append(result, slice)
-	})
-	if len(result) == 0 {
-		return nil
-	}
-	return result
-}
-
-// FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns
-// a slice of all successive matches of the expression, as defined by the
-// 'All' description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int {
-	if n < 0 {
-		n = len(b) + 1
-	}
-	result := make([][]int, 0, startSize)
-	re.allMatches("", b, n, func(match []int) {
-		result = append(result, match)
-	})
-	if len(result) == 0 {
-		return nil
-	}
-	return result
-}
-
-// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it
-// returns a slice of all successive matches of the expression, as defined by
-// the 'All' description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
-	if n < 0 {
-		n = len(s) + 1
-	}
-	result := make([][]string, 0, startSize)
-	re.allMatches(s, nil, n, func(match []int) {
-		slice := make([]string, len(match)/2)
-		for j := range slice {
-			if match[2*j] >= 0 {
-				slice[j] = s[match[2*j]:match[2*j+1]]
-			}
-		}
-		result = append(result, slice)
-	})
-	if len(result) == 0 {
-		return nil
-	}
-	return result
-}
-
-// FindAllStringSubmatchIndex is the 'All' version of
-// FindStringSubmatchIndex; it returns a slice of all successive matches of
-// the expression, as defined by the 'All' description in the package
-// comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
-	if n < 0 {
-		n = len(s) + 1
-	}
-	result := make([][]int, 0, startSize)
-	re.allMatches(s, nil, n, func(match []int) {
-		result = append(result, match)
-	})
-	if len(result) == 0 {
-		return nil
-	}
-	return result
-}
diff --git a/src/pkg/exp/regexp/syntax/Makefile b/src/pkg/exp/regexp/syntax/Makefile
deleted file mode 100644
index 97d4ad6..0000000
--- a/src/pkg/exp/regexp/syntax/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../../Make.inc
-
-TARG=exp/regexp/syntax
-GOFILES=\
-	compile.go\
-	parse.go\
-	perl_groups.go\
-	prog.go\
-	regexp.go\
-	simplify.go\
-
-include ../../../../Make.pkg
diff --git a/src/pkg/exp/regexp/syntax/compile.go b/src/pkg/exp/regexp/syntax/compile.go
deleted file mode 100644
index 6b6d062..0000000
--- a/src/pkg/exp/regexp/syntax/compile.go
+++ /dev/null
@@ -1,277 +0,0 @@
-package syntax
-
-import (
-	"os"
-	"unicode"
-)
-
-// A patchList is a list of instruction pointers that need to be filled in (patched).
-// Because the pointers haven't been filled in yet, we can reuse their storage
-// to hold the list.  It's kind of sleazy, but works well in practice.
-// See http://swtch.com/~rsc/regexp/regexp1.html for inspiration.
-// 
-// These aren't really pointers: they're integers, so we can reinterpret them
-// this way without using package unsafe.  A value l denotes
-// p.inst[l>>1].Out (l&1==0) or .Arg (l&1==1). 
-// l == 0 denotes the empty list, okay because we start every program
-// with a fail instruction, so we'll never want to point at its output link.
-type patchList uint32
-
-func (l patchList) next(p *Prog) patchList {
-	i := &p.Inst[l>>1]
-	if l&1 == 0 {
-		return patchList(i.Out)
-	}
-	return patchList(i.Arg)
-}
-
-func (l patchList) patch(p *Prog, val uint32) {
-	for l != 0 {
-		i := &p.Inst[l>>1]
-		if l&1 == 0 {
-			l = patchList(i.Out)
-			i.Out = val
-		} else {
-			l = patchList(i.Arg)
-			i.Arg = val
-		}
-	}
-}
-
-func (l1 patchList) append(p *Prog, l2 patchList) patchList {
-	if l1 == 0 {
-		return l2
-	}
-	if l2 == 0 {
-		return l1
-	}
-
-	last := l1
-	for {
-		next := last.next(p)
-		if next == 0 {
-			break
-		}
-		last = next
-	}
-
-	i := &p.Inst[last>>1]
-	if last&1 == 0 {
-		i.Out = uint32(l2)
-	} else {
-		i.Arg = uint32(l2)
-	}
-	return l1
-}
-
-// A frag represents a compiled program fragment.
-type frag struct {
-	i   uint32    // index of first instruction
-	out patchList // where to record end instruction
-}
-
-type compiler struct {
-	p *Prog
-}
-
-// Compile compiles the regexp into a program to be executed.
-// The regexp should have been simplified already (returned from re.Simplify).
-func Compile(re *Regexp) (*Prog, os.Error) {
-	var c compiler
-	c.init()
-	f := c.compile(re)
-	f.out.patch(c.p, c.inst(InstMatch).i)
-	c.p.Start = int(f.i)
-	return c.p, nil
-}
-
-func (c *compiler) init() {
-	c.p = new(Prog)
-	c.p.NumCap = 2 // implicit ( and ) for whole match $0
-	c.inst(InstFail)
-}
-
-var anyRuneNotNL = []int{0, '\n' - 1, '\n' + 1, unicode.MaxRune}
-var anyRune = []int{0, unicode.MaxRune}
-
-func (c *compiler) compile(re *Regexp) frag {
-	switch re.Op {
-	case OpNoMatch:
-		return c.fail()
-	case OpEmptyMatch:
-		return c.nop()
-	case OpLiteral:
-		if len(re.Rune) == 0 {
-			return c.nop()
-		}
-		var f frag
-		for j := range re.Rune {
-			f1 := c.rune(re.Rune[j:j+1], re.Flags)
-			if j == 0 {
-				f = f1
-			} else {
-				f = c.cat(f, f1)
-			}
-		}
-		return f
-	case OpCharClass:
-		return c.rune(re.Rune, re.Flags)
-	case OpAnyCharNotNL:
-		return c.rune(anyRuneNotNL, 0)
-	case OpAnyChar:
-		return c.rune(anyRune, 0)
-	case OpBeginLine:
-		return c.empty(EmptyBeginLine)
-	case OpEndLine:
-		return c.empty(EmptyEndLine)
-	case OpBeginText:
-		return c.empty(EmptyBeginText)
-	case OpEndText:
-		return c.empty(EmptyEndText)
-	case OpWordBoundary:
-		return c.empty(EmptyWordBoundary)
-	case OpNoWordBoundary:
-		return c.empty(EmptyNoWordBoundary)
-	case OpCapture:
-		bra := c.cap(uint32(re.Cap << 1))
-		sub := c.compile(re.Sub[0])
-		ket := c.cap(uint32(re.Cap<<1 | 1))
-		return c.cat(c.cat(bra, sub), ket)
-	case OpStar:
-		return c.star(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
-	case OpPlus:
-		return c.plus(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
-	case OpQuest:
-		return c.quest(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
-	case OpConcat:
-		if len(re.Sub) == 0 {
-			return c.nop()
-		}
-		var f frag
-		for i, sub := range re.Sub {
-			if i == 0 {
-				f = c.compile(sub)
-			} else {
-				f = c.cat(f, c.compile(sub))
-			}
-		}
-		return f
-	case OpAlternate:
-		var f frag
-		for _, sub := range re.Sub {
-			f = c.alt(f, c.compile(sub))
-		}
-		return f
-	}
-	panic("regexp: unhandled case in compile")
-}
-
-func (c *compiler) inst(op InstOp) frag {
-	// TODO: impose length limit
-	f := frag{i: uint32(len(c.p.Inst))}
-	c.p.Inst = append(c.p.Inst, Inst{Op: op})
-	return f
-}
-
-func (c *compiler) nop() frag {
-	f := c.inst(InstNop)
-	f.out = patchList(f.i << 1)
-	return f
-}
-
-func (c *compiler) fail() frag {
-	return frag{}
-}
-
-func (c *compiler) cap(arg uint32) frag {
-	f := c.inst(InstCapture)
-	f.out = patchList(f.i << 1)
-	c.p.Inst[f.i].Arg = arg
-
-	if c.p.NumCap < int(arg)+1 {
-		c.p.NumCap = int(arg) + 1
-	}
-	return f
-}
-
-func (c *compiler) cat(f1, f2 frag) frag {
-	// concat of failure is failure
-	if f1.i == 0 || f2.i == 0 {
-		return frag{}
-	}
-
-	// TODO: elide nop
-
-	f1.out.patch(c.p, f2.i)
-	return frag{f1.i, f2.out}
-}
-
-func (c *compiler) alt(f1, f2 frag) frag {
-	// alt of failure is other
-	if f1.i == 0 {
-		return f2
-	}
-	if f2.i == 0 {
-		return f1
-	}
-
-	f := c.inst(InstAlt)
-	i := &c.p.Inst[f.i]
-	i.Out = f1.i
-	i.Arg = f2.i
-	f.out = f1.out.append(c.p, f2.out)
-	return f
-}
-
-func (c *compiler) quest(f1 frag, nongreedy bool) frag {
-	f := c.inst(InstAlt)
-	i := &c.p.Inst[f.i]
-	if nongreedy {
-		i.Arg = f1.i
-		f.out = patchList(f.i << 1)
-	} else {
-		i.Out = f1.i
-		f.out = patchList(f.i<<1 | 1)
-	}
-	f.out = f.out.append(c.p, f1.out)
-	return f
-}
-
-func (c *compiler) star(f1 frag, nongreedy bool) frag {
-	f := c.inst(InstAlt)
-	i := &c.p.Inst[f.i]
-	if nongreedy {
-		i.Arg = f1.i
-		f.out = patchList(f.i << 1)
-	} else {
-		i.Out = f1.i
-		f.out = patchList(f.i<<1 | 1)
-	}
-	f1.out.patch(c.p, f.i)
-	return f
-}
-
-func (c *compiler) plus(f1 frag, nongreedy bool) frag {
-	return frag{f1.i, c.star(f1, nongreedy).out}
-}
-
-func (c *compiler) empty(op EmptyOp) frag {
-	f := c.inst(InstEmptyWidth)
-	c.p.Inst[f.i].Arg = uint32(op)
-	f.out = patchList(f.i << 1)
-	return f
-}
-
-func (c *compiler) rune(rune []int, flags Flags) frag {
-	f := c.inst(InstRune)
-	i := &c.p.Inst[f.i]
-	i.Rune = rune
-	flags &= FoldCase // only relevant flag is FoldCase
-	if len(rune) != 1 || unicode.SimpleFold(rune[0]) == rune[0] {
-		// and sometimes not even that
-		flags &^= FoldCase
-	}
-	i.Arg = uint32(flags)
-	f.out = patchList(f.i << 1)
-	return f
-}
diff --git a/src/pkg/exp/regexp/syntax/make_perl_groups.pl b/src/pkg/exp/regexp/syntax/make_perl_groups.pl
deleted file mode 100755
index 6d1b84b..0000000
--- a/src/pkg/exp/regexp/syntax/make_perl_groups.pl
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/perl
-# Copyright 2008 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.
-
-# Modified version of RE2's make_perl_groups.pl.
-
-# Generate table entries giving character ranges
-# for POSIX/Perl character classes.  Rather than
-# figure out what the definition is, it is easier to ask
-# Perl about each letter from 0-128 and write down
-# its answer.
-
- at posixclasses = (
-	"[:alnum:]",
-	"[:alpha:]",
-	"[:ascii:]",
-	"[:blank:]",
-	"[:cntrl:]",
-	"[:digit:]",
-	"[:graph:]",
-	"[:lower:]",
-	"[:print:]",
-	"[:punct:]",
-	"[:space:]",
-	"[:upper:]",
-	"[:word:]",
-	"[:xdigit:]",
-);
-
- at perlclasses = (
-	"\\d",
-	"\\s",
-	"\\w",
-);
-
-sub ComputeClass($) {
-  my @ranges;
-  my ($class) = @_;
-  my $regexp = "[$class]";
-  my $start = -1;
-  for (my $i=0; $i<=129; $i++) {
-    if ($i == 129) { $i = 256; }
-    if ($i <= 128 && chr($i) =~ $regexp) {
-      if ($start < 0) {
-        $start = $i;
-      }
-    } else {
-      if ($start >= 0) {
-        push @ranges, [$start, $i-1];
-      }
-      $start = -1;
-    }
-  }
-  return @ranges;
-}
-
-sub PrintClass($$@) {
-  my ($cname, $name, @ranges) = @_;
-  print "var code$cname = []int{  /* $name */\n";
-  for (my $i=0; $i<@ranges; $i++) {
-    my @a = @{$ranges[$i]};
-    printf "\t0x%x, 0x%x,\n", $a[0], $a[1];
-  }
-  print "}\n\n";
-  my $n = @ranges;
-  $negname = $name;
-  if ($negname =~ /:/) {
-    $negname =~ s/:/:^/;
-  } else {
-    $negname =~ y/a-z/A-Z/;
-  }
-  return "\t`$name`: {+1, code$cname},\n" .
-  	"\t`$negname`: {-1, code$cname},\n";
-}
-
-my $gen = 0;
-
-sub PrintClasses($@) {
-  my ($cname, @classes) = @_;
-  my @entries;
-  foreach my $cl (@classes) {
-    my @ranges = ComputeClass($cl);
-    push @entries, PrintClass(++$gen, $cl, @ranges);
-  }
-  print "var ${cname}Group = map[string]charGroup{\n";
-  foreach my $e (@entries) {
-    print $e;
-  }
-  print "}\n";
-  my $count = @entries;
-}
-
-print <<EOF;
-// GENERATED BY make_perl_groups.pl; DO NOT EDIT.
-// make_perl_groups.pl >perl_groups.go
-
-package syntax
-
-EOF
-
-PrintClasses("perl", @perlclasses);
-PrintClasses("posix", @posixclasses);
diff --git a/src/pkg/exp/regexp/syntax/parse.go b/src/pkg/exp/regexp/syntax/parse.go
deleted file mode 100644
index 1165db3..0000000
--- a/src/pkg/exp/regexp/syntax/parse.go
+++ /dev/null
@@ -1,1861 +0,0 @@
-// Copyright 2011 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 syntax
-
-import (
-	"os"
-	"sort"
-	"strings"
-	"unicode"
-	"utf8"
-)
-
-// An Error describes a failure to parse a regular expression
-// and gives the offending expression.
-type Error struct {
-	Code ErrorCode
-	Expr string
-}
-
-func (e *Error) String() string {
-	return "error parsing regexp: " + e.Code.String() + ": `" + e.Expr + "`"
-}
-
-// An ErrorCode describes a failure to parse a regular expression.
-type ErrorCode string
-
-const (
-	// Unexpected error
-	ErrInternalError ErrorCode = "regexp/syntax: internal error"
-
-	// Parse errors
-	ErrInvalidCharClass      ErrorCode = "invalid character class"
-	ErrInvalidCharRange      ErrorCode = "invalid character class range"
-	ErrInvalidEscape         ErrorCode = "invalid escape sequence"
-	ErrInvalidNamedCapture   ErrorCode = "invalid named capture"
-	ErrInvalidPerlOp         ErrorCode = "invalid or unsupported Perl syntax"
-	ErrInvalidRepeatOp       ErrorCode = "invalid nested repetition operator"
-	ErrInvalidRepeatSize     ErrorCode = "invalid repeat count"
-	ErrInvalidUTF8           ErrorCode = "invalid UTF-8"
-	ErrMissingBracket        ErrorCode = "missing closing ]"
-	ErrMissingParen          ErrorCode = "missing closing )"
-	ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator"
-	ErrTrailingBackslash     ErrorCode = "trailing backslash at end of expression"
-)
-
-func (e ErrorCode) String() string {
-	return string(e)
-}
-
-// Flags control the behavior of the parser and record information about regexp context.
-type Flags uint16
-
-const (
-	FoldCase      Flags = 1 << iota // case-insensitive match
-	Literal                         // treat pattern as literal string
-	ClassNL                         // allow character classes like [^a-z] and [[:space:]] to match newline
-	DotNL                           // allow . to match newline
-	OneLine                         // treat ^ and $ as only matching at beginning and end of text
-	NonGreedy                       // make repetition operators default to non-greedy
-	PerlX                           // allow Perl extensions
-	UnicodeGroups                   // allow \p{Han}, \P{Han} for Unicode group and negation
-	WasDollar                       // regexp OpEndText was $, not \z
-	Simple                          // regexp contains no counted repetition
-
-	MatchNL = ClassNL | DotNL
-
-	Perl        = ClassNL | OneLine | PerlX | UnicodeGroups // as close to Perl as possible
-	POSIX Flags = 0                                         // POSIX syntax
-)
-
-// Pseudo-ops for parsing stack.
-const (
-	opLeftParen = opPseudo + iota
-	opVerticalBar
-)
-
-type parser struct {
-	flags       Flags     // parse mode flags
-	stack       []*Regexp // stack of parsed expressions
-	free        *Regexp
-	numCap      int // number of capturing groups seen
-	wholeRegexp string
-	tmpClass    []int // temporary char class work space
-}
-
-func (p *parser) newRegexp(op Op) *Regexp {
-	re := p.free
-	if re != nil {
-		p.free = re.Sub0[0]
-		*re = Regexp{}
-	} else {
-		re = new(Regexp)
-	}
-	re.Op = op
-	return re
-}
-
-func (p *parser) reuse(re *Regexp) {
-	re.Sub0[0] = p.free
-	p.free = re
-}
-
-// Parse stack manipulation.
-
-// push pushes the regexp re onto the parse stack and returns the regexp.
-func (p *parser) push(re *Regexp) *Regexp {
-	if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
-		// Single rune.
-		if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
-			return nil
-		}
-		re.Op = OpLiteral
-		re.Rune = re.Rune[:1]
-		re.Flags = p.flags &^ FoldCase
-	} else if re.Op == OpCharClass && len(re.Rune) == 4 &&
-		re.Rune[0] == re.Rune[1] && re.Rune[2] == re.Rune[3] &&
-		unicode.SimpleFold(re.Rune[0]) == re.Rune[2] &&
-		unicode.SimpleFold(re.Rune[2]) == re.Rune[0] ||
-		re.Op == OpCharClass && len(re.Rune) == 2 &&
-			re.Rune[0]+1 == re.Rune[1] &&
-			unicode.SimpleFold(re.Rune[0]) == re.Rune[1] &&
-			unicode.SimpleFold(re.Rune[1]) == re.Rune[0] {
-		// Case-insensitive rune like [Aa] or [Δδ].
-		if p.maybeConcat(re.Rune[0], p.flags|FoldCase) {
-			return nil
-		}
-
-		// Rewrite as (case-insensitive) literal.
-		re.Op = OpLiteral
-		re.Rune = re.Rune[:1]
-		re.Flags = p.flags | FoldCase
-	} else {
-		// Incremental concatenation.
-		p.maybeConcat(-1, 0)
-	}
-
-	p.stack = append(p.stack, re)
-	return re
-}
-
-// maybeConcat implements incremental concatenation
-// of literal runes into string nodes.  The parser calls this
-// before each push, so only the top fragment of the stack
-// might need processing.  Since this is called before a push,
-// the topmost literal is no longer subject to operators like *
-// (Otherwise ab* would turn into (ab)*.)
-// If r >= 0 and there's a node left over, maybeConcat uses it
-// to push r with the given flags.
-// maybeConcat reports whether r was pushed.
-func (p *parser) maybeConcat(r int, flags Flags) bool {
-	n := len(p.stack)
-	if n < 2 {
-		return false
-	}
-
-	re1 := p.stack[n-1]
-	re2 := p.stack[n-2]
-	if re1.Op != OpLiteral || re2.Op != OpLiteral || re1.Flags&FoldCase != re2.Flags&FoldCase {
-		return false
-	}
-
-	// Push re1 into re2.
-	re2.Rune = append(re2.Rune, re1.Rune...)
-
-	// Reuse re1 if possible.
-	if r >= 0 {
-		re1.Rune = re1.Rune0[:1]
-		re1.Rune[0] = r
-		re1.Flags = flags
-		return true
-	}
-
-	p.stack = p.stack[:n-1]
-	p.reuse(re1)
-	return false // did not push r
-}
-
-// newLiteral returns a new OpLiteral Regexp with the given flags
-func (p *parser) newLiteral(r int, flags Flags) *Regexp {
-	re := p.newRegexp(OpLiteral)
-	re.Flags = flags
-	if flags&FoldCase != 0 {
-		r = minFoldRune(r)
-	}
-	re.Rune0[0] = r
-	re.Rune = re.Rune0[:1]
-	return re
-}
-
-// minFoldRune returns the minimum rune fold-equivalent to r.
-func minFoldRune(r int) int {
-	if r < minFold || r > maxFold {
-		return r
-	}
-	min := r
-	r0 := r
-	for r = unicode.SimpleFold(r); r != r0; r = unicode.SimpleFold(r) {
-		if min > r {
-			min = r
-		}
-	}
-	return min
-}
-
-// literal pushes a literal regexp for the rune r on the stack
-// and returns that regexp.
-func (p *parser) literal(r int) {
-	p.push(p.newLiteral(r, p.flags))
-}
-
-// op pushes a regexp with the given op onto the stack
-// and returns that regexp.
-func (p *parser) op(op Op) *Regexp {
-	re := p.newRegexp(op)
-	re.Flags = p.flags
-	return p.push(re)
-}
-
-// repeat replaces the top stack element with itself repeated according to op, min, max.
-// before is the regexp suffix starting at the repetition operator.
-// after is the regexp suffix following after the repetition operator.
-// repeat returns an updated 'after' and an error, if any.
-func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (string, os.Error) {
-	flags := p.flags
-	if p.flags&PerlX != 0 {
-		if len(after) > 0 && after[0] == '?' {
-			after = after[1:]
-			flags ^= NonGreedy
-		}
-		if lastRepeat != "" {
-			// In Perl it is not allowed to stack repetition operators:
-			// a** is a syntax error, not a doubled star, and a++ means
-			// something else entirely, which we don't support!
-			return "", &Error{ErrInvalidRepeatOp, lastRepeat[:len(lastRepeat)-len(after)]}
-		}
-	}
-	n := len(p.stack)
-	if n == 0 {
-		return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
-	}
-	sub := p.stack[n-1]
-	if sub.Op >= opPseudo {
-		return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
-	}
-	re := p.newRegexp(op)
-	re.Min = min
-	re.Max = max
-	re.Flags = flags
-	re.Sub = re.Sub0[:1]
-	re.Sub[0] = sub
-	p.stack[n-1] = re
-	return after, nil
-}
-
-// concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation.
-func (p *parser) concat() *Regexp {
-	p.maybeConcat(-1, 0)
-
-	// Scan down to find pseudo-operator | or (.
-	i := len(p.stack)
-	for i > 0 && p.stack[i-1].Op < opPseudo {
-		i--
-	}
-	subs := p.stack[i:]
-	p.stack = p.stack[:i]
-
-	// Empty concatenation is special case.
-	if len(subs) == 0 {
-		return p.push(p.newRegexp(OpEmptyMatch))
-	}
-
-	return p.push(p.collapse(subs, OpConcat))
-}
-
-// alternate replaces the top of the stack (above the topmost '(') with its alternation.
-func (p *parser) alternate() *Regexp {
-	// Scan down to find pseudo-operator (.
-	// There are no | above (.
-	i := len(p.stack)
-	for i > 0 && p.stack[i-1].Op < opPseudo {
-		i--
-	}
-	subs := p.stack[i:]
-	p.stack = p.stack[:i]
-
-	// Make sure top class is clean.
-	// All the others already are (see swapVerticalBar).
-	if len(subs) > 0 {
-		cleanAlt(subs[len(subs)-1])
-	}
-
-	// Empty alternate is special case
-	// (shouldn't happen but easy to handle).
-	if len(subs) == 0 {
-		return p.push(p.newRegexp(OpNoMatch))
-	}
-
-	return p.push(p.collapse(subs, OpAlternate))
-}
-
-// cleanAlt cleans re for eventual inclusion in an alternation.
-func cleanAlt(re *Regexp) {
-	switch re.Op {
-	case OpCharClass:
-		re.Rune = cleanClass(&re.Rune)
-		if len(re.Rune) == 2 && re.Rune[0] == 0 && re.Rune[1] == unicode.MaxRune {
-			re.Rune = nil
-			re.Op = OpAnyChar
-			return
-		}
-		if len(re.Rune) == 4 && re.Rune[0] == 0 && re.Rune[1] == '\n'-1 && re.Rune[2] == '\n'+1 && re.Rune[3] == unicode.MaxRune {
-			re.Rune = nil
-			re.Op = OpAnyCharNotNL
-			return
-		}
-		if cap(re.Rune)-len(re.Rune) > 100 {
-			// re.Rune will not grow any more.
-			// Make a copy or inline to reclaim storage.
-			re.Rune = append(re.Rune0[:0], re.Rune...)
-		}
-	}
-}
-
-// collapse returns the result of applying op to sub.
-// If sub contains op nodes, they all get hoisted up
-// so that there is never a concat of a concat or an
-// alternate of an alternate.
-func (p *parser) collapse(subs []*Regexp, op Op) *Regexp {
-	if len(subs) == 1 {
-		return subs[0]
-	}
-	re := p.newRegexp(op)
-	re.Sub = re.Sub0[:0]
-	for _, sub := range subs {
-		if sub.Op == op {
-			re.Sub = append(re.Sub, sub.Sub...)
-			p.reuse(sub)
-		} else {
-			re.Sub = append(re.Sub, sub)
-		}
-	}
-	if op == OpAlternate {
-		re.Sub = p.factor(re.Sub, re.Flags)
-		if len(re.Sub) == 1 {
-			old := re
-			re = re.Sub[0]
-			p.reuse(old)
-		}
-	}
-	return re
-}
-
-// factor factors common prefixes from the alternation list sub.
-// It returns a replacement list that reuses the same storage and
-// frees (passes to p.reuse) any removed *Regexps.
-//
-// For example,
-//     ABC|ABD|AEF|BCX|BCY
-// simplifies by literal prefix extraction to
-//     A(B(C|D)|EF)|BC(X|Y)
-// which simplifies by character class introduction to
-//     A(B[CD]|EF)|BC[XY]
-//
-func (p *parser) factor(sub []*Regexp, flags Flags) []*Regexp {
-	if len(sub) < 2 {
-		return sub
-	}
-
-	// Round 1: Factor out common literal prefixes.
-	var str []int
-	var strflags Flags
-	start := 0
-	out := sub[:0]
-	for i := 0; i <= len(sub); i++ {
-		// Invariant: the Regexps that were in sub[0:start] have been
-		// used or marked for reuse, and the slice space has been reused
-		// for out (len(out) <= start).
-		//
-		// Invariant: sub[start:i] consists of regexps that all begin
-		// with str as modified by strflags.
-		var istr []int
-		var iflags Flags
-		if i < len(sub) {
-			istr, iflags = p.leadingString(sub[i])
-			if iflags == strflags {
-				same := 0
-				for same < len(str) && same < len(istr) && str[same] == istr[same] {
-					same++
-				}
-				if same > 0 {
-					// Matches at least one rune in current range.
-					// Keep going around.
-					str = str[:same]
-					continue
-				}
-			}
-		}
-
-		// Found end of a run with common leading literal string:
-		// sub[start:i] all begin with str[0:len(str)], but sub[i]
-		// does not even begin with str[0].
-		//
-		// Factor out common string and append factored expression to out.
-		if i == start {
-			// Nothing to do - run of length 0.
-		} else if i == start+1 {
-			// Just one: don't bother factoring.
-			out = append(out, sub[start])
-		} else {
-			// Construct factored form: prefix(suffix1|suffix2|...)
-			prefix := p.newRegexp(OpLiteral)
-			prefix.Flags = strflags
-			prefix.Rune = append(prefix.Rune[:0], str...)
-
-			for j := start; j < i; j++ {
-				sub[j] = p.removeLeadingString(sub[j], len(str))
-			}
-			suffix := p.collapse(sub[start:i], OpAlternate) // recurse
-
-			re := p.newRegexp(OpConcat)
-			re.Sub = append(re.Sub[:0], prefix, suffix)
-			out = append(out, re)
-		}
-
-		// Prepare for next iteration.
-		start = i
-		str = istr
-		strflags = iflags
-	}
-	sub = out
-
-	// Round 2: Factor out common complex prefixes,
-	// just the first piece of each concatenation,
-	// whatever it is.  This is good enough a lot of the time.
-	start = 0
-	out = sub[:0]
-	var first *Regexp
-	for i := 0; i <= len(sub); i++ {
-		// Invariant: the Regexps that were in sub[0:start] have been
-		// used or marked for reuse, and the slice space has been reused
-		// for out (len(out) <= start).
-		//
-		// Invariant: sub[start:i] consists of regexps that all begin with ifirst.
-		var ifirst *Regexp
-		if i < len(sub) {
-			ifirst = p.leadingRegexp(sub[i])
-			if first != nil && first.Equal(ifirst) {
-				continue
-			}
-		}
-
-		// Found end of a run with common leading regexp:
-		// sub[start:i] all begin with first but sub[i] does not.
-		//
-		// Factor out common regexp and append factored expression to out.
-		if i == start {
-			// Nothing to do - run of length 0.
-		} else if i == start+1 {
-			// Just one: don't bother factoring.
-			out = append(out, sub[start])
-		} else {
-			// Construct factored form: prefix(suffix1|suffix2|...)
-			prefix := first
-			for j := start; j < i; j++ {
-				reuse := j != start // prefix came from sub[start] 
-				sub[j] = p.removeLeadingRegexp(sub[j], reuse)
-			}
-			suffix := p.collapse(sub[start:i], OpAlternate) // recurse
-
-			re := p.newRegexp(OpConcat)
-			re.Sub = append(re.Sub[:0], prefix, suffix)
-			out = append(out, re)
-		}
-
-		// Prepare for next iteration.
-		start = i
-		first = ifirst
-	}
-	sub = out
-
-	// Round 3: Collapse runs of single literals into character classes.
-	start = 0
-	out = sub[:0]
-	for i := 0; i <= len(sub); i++ {
-		// Invariant: the Regexps that were in sub[0:start] have been
-		// used or marked for reuse, and the slice space has been reused
-		// for out (len(out) <= start).
-		//
-		// Invariant: sub[start:i] consists of regexps that are either
-		// literal runes or character classes.
-		if i < len(sub) && isCharClass(sub[i]) {
-			continue
-		}
-
-		// sub[i] is not a char or char class;
-		// emit char class for sub[start:i]...
-		if i == start {
-			// Nothing to do - run of length 0.
-		} else if i == start+1 {
-			out = append(out, sub[start])
-		} else {
-			// Make new char class.
-			// Start with most complex regexp in sub[start].
-			max := start
-			for j := start + 1; j < i; j++ {
-				if sub[max].Op < sub[j].Op || sub[max].Op == sub[j].Op && len(sub[max].Rune) < len(sub[j].Rune) {
-					max = j
-				}
-			}
-			sub[start], sub[max] = sub[max], sub[start]
-
-			for j := start + 1; j < i; j++ {
-				mergeCharClass(sub[start], sub[j])
-				p.reuse(sub[j])
-			}
-			cleanAlt(sub[start])
-			out = append(out, sub[start])
-		}
-
-		// ... and then emit sub[i].
-		if i < len(sub) {
-			out = append(out, sub[i])
-		}
-		start = i + 1
-	}
-	sub = out
-
-	// Round 4: Collapse runs of empty matches into a single empty match.
-	start = 0
-	out = sub[:0]
-	for i := range sub {
-		if i+1 < len(sub) && sub[i].Op == OpEmptyMatch && sub[i+1].Op == OpEmptyMatch {
-			continue
-		}
-		out = append(out, sub[i])
-	}
-	sub = out
-
-	return sub
-}
-
-// leadingString returns the leading literal string that re begins with.
-// The string refers to storage in re or its children.
-func (p *parser) leadingString(re *Regexp) ([]int, Flags) {
-	if re.Op == OpConcat && len(re.Sub) > 0 {
-		re = re.Sub[0]
-	}
-	if re.Op != OpLiteral {
-		return nil, 0
-	}
-	return re.Rune, re.Flags & FoldCase
-}
-
-// removeLeadingString removes the first n leading runes
-// from the beginning of re.  It returns the replacement for re.
-func (p *parser) removeLeadingString(re *Regexp, n int) *Regexp {
-	if re.Op == OpConcat && len(re.Sub) > 0 {
-		// Removing a leading string in a concatenation
-		// might simplify the concatenation.
-		sub := re.Sub[0]
-		sub = p.removeLeadingString(sub, n)
-		re.Sub[0] = sub
-		if sub.Op == OpEmptyMatch {
-			p.reuse(sub)
-			switch len(re.Sub) {
-			case 0, 1:
-				// Impossible but handle.
-				re.Op = OpEmptyMatch
-				re.Sub = nil
-			case 2:
-				old := re
-				re = re.Sub[1]
-				p.reuse(old)
-			default:
-				copy(re.Sub, re.Sub[1:])
-				re.Sub = re.Sub[:len(re.Sub)-1]
-			}
-		}
-		return re
-	}
-
-	if re.Op == OpLiteral {
-		re.Rune = re.Rune[:copy(re.Rune, re.Rune[n:])]
-		if len(re.Rune) == 0 {
-			re.Op = OpEmptyMatch
-		}
-	}
-	return re
-}
-
-// leadingRegexp returns the leading regexp that re begins with.
-// The regexp refers to storage in re or its children.
-func (p *parser) leadingRegexp(re *Regexp) *Regexp {
-	if re.Op == OpEmptyMatch {
-		return nil
-	}
-	if re.Op == OpConcat && len(re.Sub) > 0 {
-		sub := re.Sub[0]
-		if sub.Op == OpEmptyMatch {
-			return nil
-		}
-		return sub
-	}
-	return re
-}
-
-// removeLeadingRegexp removes the leading regexp in re.
-// It returns the replacement for re.
-// If reuse is true, it passes the removed regexp (if no longer needed) to p.reuse.
-func (p *parser) removeLeadingRegexp(re *Regexp, reuse bool) *Regexp {
-	if re.Op == OpConcat && len(re.Sub) > 0 {
-		if reuse {
-			p.reuse(re.Sub[0])
-		}
-		re.Sub = re.Sub[:copy(re.Sub, re.Sub[1:])]
-		switch len(re.Sub) {
-		case 0:
-			re.Op = OpEmptyMatch
-			re.Sub = nil
-		case 1:
-			old := re
-			re = re.Sub[0]
-			p.reuse(old)
-		}
-		return re
-	}
-	if reuse {
-		p.reuse(re)
-	}
-	return p.newRegexp(OpEmptyMatch)
-}
-
-func literalRegexp(s string, flags Flags) *Regexp {
-	re := &Regexp{Op: OpLiteral}
-	re.Flags = flags
-	re.Rune = re.Rune0[:0] // use local storage for small strings
-	for _, c := range s {
-		if len(re.Rune) >= cap(re.Rune) {
-			// string is too long to fit in Rune0.  let Go handle it
-			re.Rune = []int(s)
-			break
-		}
-		re.Rune = append(re.Rune, c)
-	}
-	return re
-}
-
-// Parsing.
-
-func Parse(s string, flags Flags) (*Regexp, os.Error) {
-	if flags&Literal != 0 {
-		// Trivial parser for literal string.
-		if err := checkUTF8(s); err != nil {
-			return nil, err
-		}
-		return literalRegexp(s, flags), nil
-	}
-
-	// Otherwise, must do real work.
-	var (
-		p          parser
-		err        os.Error
-		c          int
-		op         Op
-		lastRepeat string
-		min, max   int
-	)
-	p.flags = flags
-	p.wholeRegexp = s
-	t := s
-	for t != "" {
-		repeat := ""
-	BigSwitch:
-		switch t[0] {
-		default:
-			if c, t, err = nextRune(t); err != nil {
-				return nil, err
-			}
-			p.literal(c)
-
-		case '(':
-			if p.flags&PerlX != 0 && len(t) >= 2 && t[1] == '?' {
-				// Flag changes and non-capturing groups.
-				if t, err = p.parsePerlFlags(t); err != nil {
-					return nil, err
-				}
-				break
-			}
-			p.numCap++
-			p.op(opLeftParen).Cap = p.numCap
-			t = t[1:]
-		case '|':
-			if err = p.parseVerticalBar(); err != nil {
-				return nil, err
-			}
-			t = t[1:]
-		case ')':
-			if err = p.parseRightParen(); err != nil {
-				return nil, err
-			}
-			t = t[1:]
-		case '^':
-			if p.flags&OneLine != 0 {
-				p.op(OpBeginText)
-			} else {
-				p.op(OpBeginLine)
-			}
-			t = t[1:]
-		case '$':
-			if p.flags&OneLine != 0 {
-				p.op(OpEndText).Flags |= WasDollar
-			} else {
-				p.op(OpEndLine)
-			}
-			t = t[1:]
-		case '.':
-			if p.flags&DotNL != 0 {
-				p.op(OpAnyChar)
-			} else {
-				p.op(OpAnyCharNotNL)
-			}
-			t = t[1:]
-		case '[':
-			if t, err = p.parseClass(t); err != nil {
-				return nil, err
-			}
-		case '*', '+', '?':
-			before := t
-			switch t[0] {
-			case '*':
-				op = OpStar
-			case '+':
-				op = OpPlus
-			case '?':
-				op = OpQuest
-			}
-			after := t[1:]
-			if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil {
-				return nil, err
-			}
-			repeat = before
-			t = after
-		case '{':
-			op = OpRepeat
-			before := t
-			min, max, after, ok := p.parseRepeat(t)
-			if !ok {
-				// If the repeat cannot be parsed, { is a literal.
-				p.literal('{')
-				t = t[1:]
-				break
-			}
-			if min < 0 || min > 1000 || max > 1000 || max >= 0 && min > max {
-				// Numbers were too big, or max is present and min > max.
-				return nil, &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
-			}
-			if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil {
-				return nil, err
-			}
-			repeat = before
-			t = after
-		case '\\':
-			if p.flags&PerlX != 0 && len(t) >= 2 {
-				switch t[1] {
-				case 'A':
-					p.op(OpBeginText)
-					t = t[2:]
-					break BigSwitch
-				case 'b':
-					p.op(OpWordBoundary)
-					t = t[2:]
-					break BigSwitch
-				case 'B':
-					p.op(OpNoWordBoundary)
-					t = t[2:]
-					break BigSwitch
-				case 'C':
-					// any byte; not supported
-					return nil, &Error{ErrInvalidEscape, t[:2]}
-				case 'Q':
-					// \Q ... \E: the ... is always literals
-					var lit string
-					if i := strings.Index(t, `\E`); i < 0 {
-						lit = t[2:]
-						t = ""
-					} else {
-						lit = t[2:i]
-						t = t[i+2:]
-					}
-					p.push(literalRegexp(lit, p.flags))
-					break BigSwitch
-				case 'z':
-					p.op(OpEndText)
-					t = t[2:]
-					break BigSwitch
-				}
-			}
-
-			re := p.newRegexp(OpCharClass)
-			re.Flags = p.flags
-
-			// Look for Unicode character group like \p{Han}
-			if len(t) >= 2 && (t[1] == 'p' || t[1] == 'P') {
-				r, rest, err := p.parseUnicodeClass(t, re.Rune0[:0])
-				if err != nil {
-					return nil, err
-				}
-				if r != nil {
-					re.Rune = r
-					t = rest
-					p.push(re)
-					break BigSwitch
-				}
-			}
-
-			// Perl character class escape.
-			if r, rest := p.parsePerlClassEscape(t, re.Rune0[:0]); r != nil {
-				re.Rune = r
-				t = rest
-				p.push(re)
-				break BigSwitch
-			}
-			p.reuse(re)
-
-			// Ordinary single-character escape.
-			if c, t, err = p.parseEscape(t); err != nil {
-				return nil, err
-			}
-			p.literal(c)
-		}
-		lastRepeat = repeat
-	}
-
-	p.concat()
-	if p.swapVerticalBar() {
-		// pop vertical bar
-		p.stack = p.stack[:len(p.stack)-1]
-	}
-	p.alternate()
-
-	n := len(p.stack)
-	if n != 1 {
-		return nil, &Error{ErrMissingParen, s}
-	}
-	return p.stack[0], nil
-}
-
-// parseRepeat parses {min} (max=min) or {min,} (max=-1) or {min,max}.
-// If s is not of that form, it returns ok == false.
-// If s has the right form but the values are too big, it returns min == -1, ok == true.
-func (p *parser) parseRepeat(s string) (min, max int, rest string, ok bool) {
-	if s == "" || s[0] != '{' {
-		return
-	}
-	s = s[1:]
-	var ok1 bool
-	if min, s, ok1 = p.parseInt(s); !ok1 {
-		return
-	}
-	if s == "" {
-		return
-	}
-	if s[0] != ',' {
-		max = min
-	} else {
-		s = s[1:]
-		if s == "" {
-			return
-		}
-		if s[0] == '}' {
-			max = -1
-		} else if max, s, ok1 = p.parseInt(s); !ok1 {
-			return
-		} else if max < 0 {
-			// parseInt found too big a number
-			min = -1
-		}
-	}
-	if s == "" || s[0] != '}' {
-		return
-	}
-	rest = s[1:]
-	ok = true
-	return
-}
-
-// parsePerlFlags parses a Perl flag setting or non-capturing group or both,
-// like (?i) or (?: or (?i:.  It removes the prefix from s and updates the parse state.
-// The caller must have ensured that s begins with "(?".
-func (p *parser) parsePerlFlags(s string) (rest string, err os.Error) {
-	t := s
-
-	// Check for named captures, first introduced in Python's regexp library.
-	// As usual, there are three slightly different syntaxes:
-	//
-	//   (?P<name>expr)   the original, introduced by Python
-	//   (?<name>expr)    the .NET alteration, adopted by Perl 5.10
-	//   (?'name'expr)    another .NET alteration, adopted by Perl 5.10
-	//
-	// Perl 5.10 gave in and implemented the Python version too,
-	// but they claim that the last two are the preferred forms.
-	// PCRE and languages based on it (specifically, PHP and Ruby)
-	// support all three as well.  EcmaScript 4 uses only the Python form.
-	//
-	// In both the open source world (via Code Search) and the
-	// Google source tree, (?P<expr>name) is the dominant form,
-	// so that's the one we implement.  One is enough.
-	if len(t) > 4 && t[2] == 'P' && t[3] == '<' {
-		// Pull out name.
-		end := strings.IndexRune(t, '>')
-		if end < 0 {
-			if err = checkUTF8(t); err != nil {
-				return "", err
-			}
-			return "", &Error{ErrInvalidNamedCapture, s}
-		}
-
-		capture := t[:end+1] // "(?P<name>"
-		name := t[4:end]     // "name"
-		if err = checkUTF8(name); err != nil {
-			return "", err
-		}
-		if !isValidCaptureName(name) {
-			return "", &Error{ErrInvalidNamedCapture, capture}
-		}
-
-		// Like ordinary capture, but named.
-		p.numCap++
-		re := p.op(opLeftParen)
-		re.Cap = p.numCap
-		re.Name = name
-		return t[end+1:], nil
-	}
-
-	// Non-capturing group.  Might also twiddle Perl flags.
-	var c int
-	t = t[2:] // skip (?
-	flags := p.flags
-	sign := +1
-	sawFlag := false
-Loop:
-	for t != "" {
-		if c, t, err = nextRune(t); err != nil {
-			return "", err
-		}
-		switch c {
-		default:
-			break Loop
-
-		// Flags.
-		case 'i':
-			flags |= FoldCase
-			sawFlag = true
-		case 'm':
-			flags &^= OneLine
-			sawFlag = true
-		case 's':
-			flags |= DotNL
-			sawFlag = true
-		case 'U':
-			flags |= NonGreedy
-			sawFlag = true
-
-		// Switch to negation.
-		case '-':
-			if sign < 0 {
-				break Loop
-			}
-			sign = -1
-			// Invert flags so that | above turn into &^ and vice versa.
-			// We'll invert flags again before using it below.
-			flags = ^flags
-			sawFlag = false
-
-		// End of flags, starting group or not.
-		case ':', ')':
-			if sign < 0 {
-				if !sawFlag {
-					break Loop
-				}
-				flags = ^flags
-			}
-			if c == ':' {
-				// Open new group
-				p.op(opLeftParen)
-			}
-			p.flags = flags
-			return t, nil
-		}
-	}
-
-	return "", &Error{ErrInvalidPerlOp, s[:len(s)-len(t)]}
-}
-
-// isValidCaptureName reports whether name
-// is a valid capture name: [A-Za-z0-9_]+.
-// PCRE limits names to 32 bytes.
-// Python rejects names starting with digits.
-// We don't enforce either of those.
-func isValidCaptureName(name string) bool {
-	if name == "" {
-		return false
-	}
-	for _, c := range name {
-		if c != '_' && !isalnum(c) {
-			return false
-		}
-	}
-	return true
-}
-
-// parseInt parses a decimal integer.
-func (p *parser) parseInt(s string) (n int, rest string, ok bool) {
-	if s == "" || s[0] < '0' || '9' < s[0] {
-		return
-	}
-	// Disallow leading zeros.
-	if len(s) >= 2 && s[0] == '0' && '0' <= s[1] && s[1] <= '9' {
-		return
-	}
-	t := s
-	for s != "" && '0' <= s[0] && s[0] <= '9' {
-		s = s[1:]
-	}
-	rest = s
-	ok = true
-	// Have digits, compute value.
-	t = t[:len(t)-len(s)]
-	for i := 0; i < len(t); i++ {
-		// Avoid overflow.
-		if n >= 1e8 {
-			n = -1
-			break
-		}
-		n = n*10 + int(t[i]) - '0'
-	}
-	return
-}
-
-// can this be represented as a character class?
-// single-rune literal string, char class, ., and .|\n.
-func isCharClass(re *Regexp) bool {
-	return re.Op == OpLiteral && len(re.Rune) == 1 ||
-		re.Op == OpCharClass ||
-		re.Op == OpAnyCharNotNL ||
-		re.Op == OpAnyChar
-}
-
-// does re match r?
-func matchRune(re *Regexp, r int) bool {
-	switch re.Op {
-	case OpLiteral:
-		return len(re.Rune) == 1 && re.Rune[0] == r
-	case OpCharClass:
-		for i := 0; i < len(re.Rune); i += 2 {
-			if re.Rune[i] <= r && r <= re.Rune[i+1] {
-				return true
-			}
-		}
-		return false
-	case OpAnyCharNotNL:
-		return r != '\n'
-	case OpAnyChar:
-		return true
-	}
-	return false
-}
-
-// parseVerticalBar handles a | in the input.
-func (p *parser) parseVerticalBar() os.Error {
-	p.concat()
-
-	// The concatenation we just parsed is on top of the stack.
-	// If it sits above an opVerticalBar, swap it below
-	// (things below an opVerticalBar become an alternation).
-	// Otherwise, push a new vertical bar.
-	if !p.swapVerticalBar() {
-		p.op(opVerticalBar)
-	}
-
-	return nil
-}
-
-// mergeCharClass makes dst = dst|src.
-// The caller must ensure that dst.Op >= src.Op,
-// to reduce the amount of copying.
-func mergeCharClass(dst, src *Regexp) {
-	switch dst.Op {
-	case OpAnyChar:
-		// src doesn't add anything.
-	case OpAnyCharNotNL:
-		// src might add \n
-		if matchRune(src, '\n') {
-			dst.Op = OpAnyChar
-		}
-	case OpCharClass:
-		// src is simpler, so either literal or char class
-		if src.Op == OpLiteral {
-			dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
-		} else {
-			dst.Rune = appendClass(dst.Rune, src.Rune)
-		}
-	case OpLiteral:
-		// both literal
-		if src.Rune[0] == dst.Rune[0] && src.Flags == dst.Flags {
-			break
-		}
-		dst.Op = OpCharClass
-		dst.Rune = appendLiteral(dst.Rune[:0], dst.Rune[0], dst.Flags)
-		dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
-	}
-}
-
-// If the top of the stack is an element followed by an opVerticalBar
-// swapVerticalBar swaps the two and returns true.
-// Otherwise it returns false.
-func (p *parser) swapVerticalBar() bool {
-	// If above and below vertical bar are literal or char class,
-	// can merge into a single char class.
-	n := len(p.stack)
-	if n >= 3 && p.stack[n-2].Op == opVerticalBar && isCharClass(p.stack[n-1]) && isCharClass(p.stack[n-3]) {
-		re1 := p.stack[n-1]
-		re3 := p.stack[n-3]
-		// Make re3 the more complex of the two.
-		if re1.Op > re3.Op {
-			re1, re3 = re3, re1
-			p.stack[n-3] = re3
-		}
-		mergeCharClass(re3, re1)
-		p.reuse(re1)
-		p.stack = p.stack[:n-1]
-		return true
-	}
-
-	if n >= 2 {
-		re1 := p.stack[n-1]
-		re2 := p.stack[n-2]
-		if re2.Op == opVerticalBar {
-			if n >= 3 {
-				// Now out of reach.
-				// Clean opportunistically.
-				cleanAlt(p.stack[n-3])
-			}
-			p.stack[n-2] = re1
-			p.stack[n-1] = re2
-			return true
-		}
-	}
-	return false
-}
-
-// parseRightParen handles a ) in the input.
-func (p *parser) parseRightParen() os.Error {
-	p.concat()
-	if p.swapVerticalBar() {
-		// pop vertical bar
-		p.stack = p.stack[:len(p.stack)-1]
-	}
-	p.alternate()
-
-	n := len(p.stack)
-	if n < 2 {
-		return &Error{ErrInternalError, ""}
-	}
-	re1 := p.stack[n-1]
-	re2 := p.stack[n-2]
-	p.stack = p.stack[:n-2]
-	if re2.Op != opLeftParen {
-		return &Error{ErrMissingParen, p.wholeRegexp}
-	}
-	// Restore flags at time of paren.
-	p.flags = re2.Flags
-	if re2.Cap == 0 {
-		// Just for grouping.
-		p.push(re1)
-	} else {
-		re2.Op = OpCapture
-		re2.Sub = re2.Sub0[:1]
-		re2.Sub[0] = re1
-		p.push(re2)
-	}
-	return nil
-}
-
-// parseEscape parses an escape sequence at the beginning of s
-// and returns the rune.
-func (p *parser) parseEscape(s string) (r int, rest string, err os.Error) {
-	t := s[1:]
-	if t == "" {
-		return 0, "", &Error{ErrTrailingBackslash, ""}
-	}
-	c, t, err := nextRune(t)
-	if err != nil {
-		return 0, "", err
-	}
-
-Switch:
-	switch c {
-	default:
-		if c < utf8.RuneSelf && !isalnum(c) {
-			// Escaped non-word characters are always themselves.
-			// PCRE is not quite so rigorous: it accepts things like
-			// \q, but we don't.  We once rejected \_, but too many
-			// programs and people insist on using it, so allow \_.
-			return c, t, nil
-		}
-
-	// Octal escapes.
-	case '1', '2', '3', '4', '5', '6', '7':
-		// Single non-zero digit is a backreference; not supported
-		if t == "" || t[0] < '0' || t[0] > '7' {
-			break
-		}
-		fallthrough
-	case '0':
-		// Consume up to three octal digits; already have one.
-		r = c - '0'
-		for i := 1; i < 3; i++ {
-			if t == "" || t[0] < '0' || t[0] > '7' {
-				break
-			}
-			r = r*8 + int(t[0]) - '0'
-			t = t[1:]
-		}
-		return r, t, nil
-
-	// Hexadecimal escapes.
-	case 'x':
-		if t == "" {
-			break
-		}
-		if c, t, err = nextRune(t); err != nil {
-			return 0, "", err
-		}
-		if c == '{' {
-			// Any number of digits in braces.
-			// Perl accepts any text at all; it ignores all text
-			// after the first non-hex digit.  We require only hex digits,
-			// and at least one.
-			nhex := 0
-			r = 0
-			for {
-				if t == "" {
-					break Switch
-				}
-				if c, t, err = nextRune(t); err != nil {
-					return 0, "", err
-				}
-				if c == '}' {
-					break
-				}
-				v := unhex(c)
-				if v < 0 {
-					break Switch
-				}
-				r = r*16 + v
-				if r > unicode.MaxRune {
-					break Switch
-				}
-				nhex++
-			}
-			if nhex == 0 {
-				break Switch
-			}
-			return r, t, nil
-		}
-
-		// Easy case: two hex digits.
-		x := unhex(c)
-		if c, t, err = nextRune(t); err != nil {
-			return 0, "", err
-		}
-		y := unhex(c)
-		if x < 0 || y < 0 {
-			break
-		}
-		return x*16 + y, t, nil
-
-	// C escapes.  There is no case 'b', to avoid misparsing
-	// the Perl word-boundary \b as the C backspace \b
-	// when in POSIX mode.  In Perl, /\b/ means word-boundary
-	// but /[\b]/ means backspace.  We don't support that.
-	// If you want a backspace, embed a literal backspace
-	// character or use \x08.
-	case 'a':
-		return '\a', t, err
-	case 'f':
-		return '\f', t, err
-	case 'n':
-		return '\n', t, err
-	case 'r':
-		return '\r', t, err
-	case 't':
-		return '\t', t, err
-	case 'v':
-		return '\v', t, err
-	}
-	return 0, "", &Error{ErrInvalidEscape, s[:len(s)-len(t)]}
-}
-
-// parseClassChar parses a character class character at the beginning of s
-// and returns it.
-func (p *parser) parseClassChar(s, wholeClass string) (r int, rest string, err os.Error) {
-	if s == "" {
-		return 0, "", &Error{Code: ErrMissingBracket, Expr: wholeClass}
-	}
-
-	// Allow regular escape sequences even though
-	// many need not be escaped in this context.
-	if s[0] == '\\' {
-		return p.parseEscape(s)
-	}
-
-	return nextRune(s)
-}
-
-type charGroup struct {
-	sign  int
-	class []int
-}
-
-// parsePerlClassEscape parses a leading Perl character class escape like \d
-// from the beginning of s.  If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parsePerlClassEscape(s string, r []int) (out []int, rest string) {
-	if p.flags&PerlX == 0 || len(s) < 2 || s[0] != '\\' {
-		return
-	}
-	g := perlGroup[s[0:2]]
-	if g.sign == 0 {
-		return
-	}
-	return p.appendGroup(r, g), s[2:]
-}
-
-// parseNamedClass parses a leading POSIX named character class like [:alnum:]
-// from the beginning of s.  If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parseNamedClass(s string, r []int) (out []int, rest string, err os.Error) {
-	if len(s) < 2 || s[0] != '[' || s[1] != ':' {
-		return
-	}
-
-	i := strings.Index(s[2:], ":]")
-	if i < 0 {
-		return
-	}
-	i += 2
-	name, s := s[0:i+2], s[i+2:]
-	g := posixGroup[name]
-	if g.sign == 0 {
-		return nil, "", &Error{ErrInvalidCharRange, name}
-	}
-	return p.appendGroup(r, g), s, nil
-}
-
-func (p *parser) appendGroup(r []int, g charGroup) []int {
-	if p.flags&FoldCase == 0 {
-		if g.sign < 0 {
-			r = appendNegatedClass(r, g.class)
-		} else {
-			r = appendClass(r, g.class)
-		}
-	} else {
-		tmp := p.tmpClass[:0]
-		tmp = appendFoldedClass(tmp, g.class)
-		p.tmpClass = tmp
-		tmp = cleanClass(&p.tmpClass)
-		if g.sign < 0 {
-			r = appendNegatedClass(r, tmp)
-		} else {
-			r = appendClass(r, tmp)
-		}
-	}
-	return r
-}
-
-var anyTable = &unicode.RangeTable{
-	[]unicode.Range16{{0, 1<<16 - 1, 1}},
-	[]unicode.Range32{{1 << 16, unicode.MaxRune, 1}},
-}
-
-// unicodeTable returns the unicode.RangeTable identified by name
-// and the table of additional fold-equivalent code points.
-func unicodeTable(name string) (*unicode.RangeTable, *unicode.RangeTable) {
-	// Special case: "Any" means any.
-	if name == "Any" {
-		return anyTable, anyTable
-	}
-	if t := unicode.Categories[name]; t != nil {
-		return t, unicode.FoldCategory[name]
-	}
-	if t := unicode.Scripts[name]; t != nil {
-		return t, unicode.FoldScript[name]
-	}
-	return nil, nil
-}
-
-// parseUnicodeClass parses a leading Unicode character class like \p{Han}
-// from the beginning of s.  If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parseUnicodeClass(s string, r []int) (out []int, rest string, err os.Error) {
-	if p.flags&UnicodeGroups == 0 || len(s) < 2 || s[0] != '\\' || s[1] != 'p' && s[1] != 'P' {
-		return
-	}
-
-	// Committed to parse or return error.
-	sign := +1
-	if s[1] == 'P' {
-		sign = -1
-	}
-	t := s[2:]
-	c, t, err := nextRune(t)
-	if err != nil {
-		return
-	}
-	var seq, name string
-	if c != '{' {
-		// Single-letter name.
-		seq = s[:len(s)-len(t)]
-		name = seq[2:]
-	} else {
-		// Name is in braces.
-		end := strings.IndexRune(s, '}')
-		if end < 0 {
-			if err = checkUTF8(s); err != nil {
-				return
-			}
-			return nil, "", &Error{ErrInvalidCharRange, s}
-		}
-		seq, t = s[:end+1], s[end+1:]
-		name = s[3:end]
-		if err = checkUTF8(name); err != nil {
-			return
-		}
-	}
-
-	// Group can have leading negation too.  \p{^Han} == \P{Han}, \P{^Han} == \p{Han}.
-	if name != "" && name[0] == '^' {
-		sign = -sign
-		name = name[1:]
-	}
-
-	tab, fold := unicodeTable(name)
-	if tab == nil {
-		return nil, "", &Error{ErrInvalidCharRange, seq}
-	}
-
-	if p.flags&FoldCase == 0 || fold == nil {
-		if sign > 0 {
-			r = appendTable(r, tab)
-		} else {
-			r = appendNegatedTable(r, tab)
-		}
-	} else {
-		// Merge and clean tab and fold in a temporary buffer.
-		// This is necessary for the negative case and just tidy
-		// for the positive case.
-		tmp := p.tmpClass[:0]
-		tmp = appendTable(tmp, tab)
-		tmp = appendTable(tmp, fold)
-		p.tmpClass = tmp
-		tmp = cleanClass(&p.tmpClass)
-		if sign > 0 {
-			r = appendClass(r, tmp)
-		} else {
-			r = appendNegatedClass(r, tmp)
-		}
-	}
-	return r, t, nil
-}
-
-// parseClass parses a character class at the beginning of s
-// and pushes it onto the parse stack.
-func (p *parser) parseClass(s string) (rest string, err os.Error) {
-	t := s[1:] // chop [
-	re := p.newRegexp(OpCharClass)
-	re.Flags = p.flags
-	re.Rune = re.Rune0[:0]
-
-	sign := +1
-	if t != "" && t[0] == '^' {
-		sign = -1
-		t = t[1:]
-
-		// If character class does not match \n, add it here,
-		// so that negation later will do the right thing.
-		if p.flags&ClassNL == 0 {
-			re.Rune = append(re.Rune, '\n', '\n')
-		}
-	}
-
-	class := re.Rune
-	first := true // ] and - are okay as first char in class
-	for t == "" || t[0] != ']' || first {
-		// POSIX: - is only okay unescaped as first or last in class.
-		// Perl: - is okay anywhere.
-		if t != "" && t[0] == '-' && p.flags&PerlX == 0 && !first && (len(t) == 1 || t[1] != ']') {
-			_, size := utf8.DecodeRuneInString(t[1:])
-			return "", &Error{Code: ErrInvalidCharRange, Expr: t[:1+size]}
-		}
-		first = false
-
-		// Look for POSIX [:alnum:] etc.
-		if len(t) > 2 && t[0] == '[' && t[1] == ':' {
-			nclass, nt, err := p.parseNamedClass(t, class)
-			if err != nil {
-				return "", err
-			}
-			if nclass != nil {
-				class, t = nclass, nt
-				continue
-			}
-		}
-
-		// Look for Unicode character group like \p{Han}.
-		nclass, nt, err := p.parseUnicodeClass(t, class)
-		if err != nil {
-			return "", err
-		}
-		if nclass != nil {
-			class, t = nclass, nt
-			continue
-		}
-
-		// Look for Perl character class symbols (extension).
-		if nclass, nt := p.parsePerlClassEscape(t, class); nclass != nil {
-			class, t = nclass, nt
-			continue
-		}
-
-		// Single character or simple range.
-		rng := t
-		var lo, hi int
-		if lo, t, err = p.parseClassChar(t, s); err != nil {
-			return "", err
-		}
-		hi = lo
-		// [a-] means (a|-) so check for final ].
-		if len(t) >= 2 && t[0] == '-' && t[1] != ']' {
-			t = t[1:]
-			if hi, t, err = p.parseClassChar(t, s); err != nil {
-				return "", err
-			}
-			if hi < lo {
-				rng = rng[:len(rng)-len(t)]
-				return "", &Error{Code: ErrInvalidCharRange, Expr: rng}
-			}
-		}
-		if p.flags&FoldCase == 0 {
-			class = appendRange(class, lo, hi)
-		} else {
-			class = appendFoldedRange(class, lo, hi)
-		}
-	}
-	t = t[1:] // chop ]
-
-	// Use &re.Rune instead of &class to avoid allocation.
-	re.Rune = class
-	class = cleanClass(&re.Rune)
-	if sign < 0 {
-		class = negateClass(class)
-	}
-	re.Rune = class
-	p.push(re)
-	return t, nil
-}
-
-// cleanClass sorts the ranges (pairs of elements of r),
-// merges them, and eliminates duplicates.
-func cleanClass(rp *[]int) []int {
-
-	// Sort by lo increasing, hi decreasing to break ties.
-	sort.Sort(ranges{rp})
-
-	r := *rp
-	if len(r) < 2 {
-		return r
-	}
-
-	// Merge abutting, overlapping.
-	w := 2 // write index
-	for i := 2; i < len(r); i += 2 {
-		lo, hi := r[i], r[i+1]
-		if lo <= r[w-1]+1 {
-			// merge with previous range
-			if hi > r[w-1] {
-				r[w-1] = hi
-			}
-			continue
-		}
-		// new disjoint range
-		r[w] = lo
-		r[w+1] = hi
-		w += 2
-	}
-
-	return r[:w]
-}
-
-// appendLiteral returns the result of appending the literal x to the class r.
-func appendLiteral(r []int, x int, flags Flags) []int {
-	if flags&FoldCase != 0 {
-		return appendFoldedRange(r, x, x)
-	}
-	return appendRange(r, x, x)
-}
-
-// appendRange returns the result of appending the range lo-hi to the class r.
-func appendRange(r []int, lo, hi int) []int {
-	// Expand last range or next to last range if it overlaps or abuts.
-	// Checking two ranges helps when appending case-folded
-	// alphabets, so that one range can be expanding A-Z and the
-	// other expanding a-z.
-	n := len(r)
-	for i := 2; i <= 4; i += 2 { // twice, using i=2, i=4
-		if n >= i {
-			rlo, rhi := r[n-i], r[n-i+1]
-			if lo <= rhi+1 && rlo <= hi+1 {
-				if lo < rlo {
-					r[n-i] = lo
-				}
-				if hi > rhi {
-					r[n-i+1] = hi
-				}
-				return r
-			}
-		}
-	}
-
-	return append(r, lo, hi)
-}
-
-const (
-	// minimum and maximum runes involved in folding.
-	// checked during test.
-	minFold = 0x0041
-	maxFold = 0x1044f
-)
-
-// appendFoldedRange returns the result of appending the range lo-hi
-// and its case folding-equivalent runes to the class r.
-func appendFoldedRange(r []int, lo, hi int) []int {
-	// Optimizations.
-	if lo <= minFold && hi >= maxFold {
-		// Range is full: folding can't add more.
-		return appendRange(r, lo, hi)
-	}
-	if hi < minFold || lo > maxFold {
-		// Range is outside folding possibilities.
-		return appendRange(r, lo, hi)
-	}
-	if lo < minFold {
-		// [lo, minFold-1] needs no folding.
-		r = appendRange(r, lo, minFold-1)
-		lo = minFold
-	}
-	if hi > maxFold {
-		// [maxFold+1, hi] needs no folding.
-		r = appendRange(r, maxFold+1, hi)
-		hi = maxFold
-	}
-
-	// Brute force.  Depend on appendRange to coalesce ranges on the fly.
-	for c := lo; c <= hi; c++ {
-		r = appendRange(r, c, c)
-		f := unicode.SimpleFold(c)
-		for f != c {
-			r = appendRange(r, f, f)
-			f = unicode.SimpleFold(f)
-		}
-	}
-	return r
-}
-
-// appendClass returns the result of appending the class x to the class r.
-// It assume x is clean.
-func appendClass(r []int, x []int) []int {
-	for i := 0; i < len(x); i += 2 {
-		r = appendRange(r, x[i], x[i+1])
-	}
-	return r
-}
-
-// appendFolded returns the result of appending the case folding of the class x to the class r.
-func appendFoldedClass(r []int, x []int) []int {
-	for i := 0; i < len(x); i += 2 {
-		r = appendFoldedRange(r, x[i], x[i+1])
-	}
-	return r
-}
-
-// appendNegatedClass returns the result of appending the negation of the class x to the class r.
-// It assumes x is clean.
-func appendNegatedClass(r []int, x []int) []int {
-	nextLo := 0
-	for i := 0; i < len(x); i += 2 {
-		lo, hi := x[i], x[i+1]
-		if nextLo <= lo-1 {
-			r = appendRange(r, nextLo, lo-1)
-		}
-		nextLo = hi + 1
-	}
-	if nextLo <= unicode.MaxRune {
-		r = appendRange(r, nextLo, unicode.MaxRune)
-	}
-	return r
-}
-
-// appendTable returns the result of appending x to the class r.
-func appendTable(r []int, x *unicode.RangeTable) []int {
-	for _, xr := range x.R16 {
-		lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
-		if stride == 1 {
-			r = appendRange(r, lo, hi)
-			continue
-		}
-		for c := lo; c <= hi; c += stride {
-			r = appendRange(r, c, c)
-		}
-	}
-	for _, xr := range x.R32 {
-		lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
-		if stride == 1 {
-			r = appendRange(r, lo, hi)
-			continue
-		}
-		for c := lo; c <= hi; c += stride {
-			r = appendRange(r, c, c)
-		}
-	}
-	return r
-}
-
-// appendNegatedTable returns the result of appending the negation of x to the class r.
-func appendNegatedTable(r []int, x *unicode.RangeTable) []int {
-	nextLo := 0 // lo end of next class to add
-	for _, xr := range x.R16 {
-		lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
-		if stride == 1 {
-			if nextLo <= lo-1 {
-				r = appendRange(r, nextLo, lo-1)
-			}
-			nextLo = hi + 1
-			continue
-		}
-		for c := lo; c <= hi; c += stride {
-			if nextLo <= c-1 {
-				r = appendRange(r, nextLo, c-1)
-			}
-			nextLo = c + 1
-		}
-	}
-	for _, xr := range x.R32 {
-		lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
-		if stride == 1 {
-			if nextLo <= lo-1 {
-				r = appendRange(r, nextLo, lo-1)
-			}
-			nextLo = hi + 1
-			continue
-		}
-		for c := lo; c <= hi; c += stride {
-			if nextLo <= c-1 {
-				r = appendRange(r, nextLo, c-1)
-			}
-			nextLo = c + 1
-		}
-	}
-	if nextLo <= unicode.MaxRune {
-		r = appendRange(r, nextLo, unicode.MaxRune)
-	}
-	return r
-}
-
-// negateClass overwrites r and returns r's negation.
-// It assumes the class r is already clean.
-func negateClass(r []int) []int {
-	nextLo := 0 // lo end of next class to add
-	w := 0      // write index
-	for i := 0; i < len(r); i += 2 {
-		lo, hi := r[i], r[i+1]
-		if nextLo <= lo-1 {
-			r[w] = nextLo
-			r[w+1] = lo - 1
-			w += 2
-		}
-		nextLo = hi + 1
-	}
-	r = r[:w]
-	if nextLo <= unicode.MaxRune {
-		// It's possible for the negation to have one more
-		// range - this one - than the original class, so use append.
-		r = append(r, nextLo, unicode.MaxRune)
-	}
-	return r
-}
-
-// ranges implements sort.Interface on a []rune.
-// The choice of receiver type definition is strange
-// but avoids an allocation since we already have
-// a *[]int.
-type ranges struct {
-	p *[]int
-}
-
-func (ra ranges) Less(i, j int) bool {
-	p := *ra.p
-	i *= 2
-	j *= 2
-	return p[i] < p[j] || p[i] == p[j] && p[i+1] > p[j+1]
-}
-
-func (ra ranges) Len() int {
-	return len(*ra.p) / 2
-}
-
-func (ra ranges) Swap(i, j int) {
-	p := *ra.p
-	i *= 2
-	j *= 2
-	p[i], p[i+1], p[j], p[j+1] = p[j], p[j+1], p[i], p[i+1]
-}
-
-func checkUTF8(s string) os.Error {
-	for s != "" {
-		rune, size := utf8.DecodeRuneInString(s)
-		if rune == utf8.RuneError && size == 1 {
-			return &Error{Code: ErrInvalidUTF8, Expr: s}
-		}
-		s = s[size:]
-	}
-	return nil
-}
-
-func nextRune(s string) (c int, t string, err os.Error) {
-	c, size := utf8.DecodeRuneInString(s)
-	if c == utf8.RuneError && size == 1 {
-		return 0, "", &Error{Code: ErrInvalidUTF8, Expr: s}
-	}
-	return c, s[size:], nil
-}
-
-func isalnum(c int) bool {
-	return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
-}
-
-func unhex(c int) int {
-	if '0' <= c && c <= '9' {
-		return c - '0'
-	}
-	if 'a' <= c && c <= 'f' {
-		return c - 'a' + 10
-	}
-	if 'A' <= c && c <= 'F' {
-		return c - 'A' + 10
-	}
-	return -1
-}
diff --git a/src/pkg/exp/regexp/syntax/parse_test.go b/src/pkg/exp/regexp/syntax/parse_test.go
deleted file mode 100644
index f20276c..0000000
--- a/src/pkg/exp/regexp/syntax/parse_test.go
+++ /dev/null
@@ -1,551 +0,0 @@
-// Copyright 2011 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 syntax
-
-import (
-	"bytes"
-	"fmt"
-	"testing"
-	"unicode"
-)
-
-type parseTest struct {
-	Regexp string
-	Dump   string
-}
-
-var parseTests = []parseTest{
-	// Base cases
-	{`a`, `lit{a}`},
-	{`a.`, `cat{lit{a}dot{}}`},
-	{`a.b`, `cat{lit{a}dot{}lit{b}}`},
-	{`ab`, `str{ab}`},
-	{`a.b.c`, `cat{lit{a}dot{}lit{b}dot{}lit{c}}`},
-	{`abc`, `str{abc}`},
-	{`a|^`, `alt{lit{a}bol{}}`},
-	{`a|b`, `cc{0x61-0x62}`},
-	{`(a)`, `cap{lit{a}}`},
-	{`(a)|b`, `alt{cap{lit{a}}lit{b}}`},
-	{`a*`, `star{lit{a}}`},
-	{`a+`, `plus{lit{a}}`},
-	{`a?`, `que{lit{a}}`},
-	{`a{2}`, `rep{2,2 lit{a}}`},
-	{`a{2,3}`, `rep{2,3 lit{a}}`},
-	{`a{2,}`, `rep{2,-1 lit{a}}`},
-	{`a*?`, `nstar{lit{a}}`},
-	{`a+?`, `nplus{lit{a}}`},
-	{`a??`, `nque{lit{a}}`},
-	{`a{2}?`, `nrep{2,2 lit{a}}`},
-	{`a{2,3}?`, `nrep{2,3 lit{a}}`},
-	{`a{2,}?`, `nrep{2,-1 lit{a}}`},
-	// Malformed { } are treated as literals.
-	{`x{1001`, `str{x{1001}`},
-	{`x{9876543210`, `str{x{9876543210}`},
-	{`x{9876543210,`, `str{x{9876543210,}`},
-	{`x{2,1`, `str{x{2,1}`},
-	{`x{1,9876543210`, `str{x{1,9876543210}`},
-	{``, `emp{}`},
-	{`|`, `emp{}`}, // alt{emp{}emp{}} but got factored
-	{`|x|`, `alt{emp{}lit{x}emp{}}`},
-	{`.`, `dot{}`},
-	{`^`, `bol{}`},
-	{`$`, `eol{}`},
-	{`\|`, `lit{|}`},
-	{`\(`, `lit{(}`},
-	{`\)`, `lit{)}`},
-	{`\*`, `lit{*}`},
-	{`\+`, `lit{+}`},
-	{`\?`, `lit{?}`},
-	{`{`, `lit{{}`},
-	{`}`, `lit{}}`},
-	{`\.`, `lit{.}`},
-	{`\^`, `lit{^}`},
-	{`\$`, `lit{$}`},
-	{`\\`, `lit{\}`},
-	{`[ace]`, `cc{0x61 0x63 0x65}`},
-	{`[abc]`, `cc{0x61-0x63}`},
-	{`[a-z]`, `cc{0x61-0x7a}`},
-	{`[a]`, `lit{a}`},
-	{`\-`, `lit{-}`},
-	{`-`, `lit{-}`},
-	{`\_`, `lit{_}`},
-	{`abc`, `str{abc}`},
-	{`abc|def`, `alt{str{abc}str{def}}`},
-	{`abc|def|ghi`, `alt{str{abc}str{def}str{ghi}}`},
-
-	// Posix and Perl extensions
-	{`[[:lower:]]`, `cc{0x61-0x7a}`},
-	{`[a-z]`, `cc{0x61-0x7a}`},
-	{`[^[:lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
-	{`[[:^lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
-	{`(?i)[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
-	{`(?i)[a-z]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
-	{`(?i)[^[:lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
-	{`(?i)[[:^lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
-	{`\d`, `cc{0x30-0x39}`},
-	{`\D`, `cc{0x0-0x2f 0x3a-0x10ffff}`},
-	{`\s`, `cc{0x9-0xa 0xc-0xd 0x20}`},
-	{`\S`, `cc{0x0-0x8 0xb 0xe-0x1f 0x21-0x10ffff}`},
-	{`\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a}`},
-	{`\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x10ffff}`},
-	{`(?i)\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a 0x17f 0x212a}`},
-	{`(?i)\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
-	{`[^\\]`, `cc{0x0-0x5b 0x5d-0x10ffff}`},
-	//	{ `\C`, `byte{}` },  // probably never
-
-	// Unicode, negatives, and a double negative.
-	{`\p{Braille}`, `cc{0x2800-0x28ff}`},
-	{`\P{Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
-	{`\p{^Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
-	{`\P{^Braille}`, `cc{0x2800-0x28ff}`},
-	{`\pZ`, `cc{0x20 0xa0 0x1680 0x180e 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
-	{`[\p{Braille}]`, `cc{0x2800-0x28ff}`},
-	{`[\P{Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
-	{`[\p{^Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
-	{`[\P{^Braille}]`, `cc{0x2800-0x28ff}`},
-	{`[\pZ]`, `cc{0x20 0xa0 0x1680 0x180e 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
-	{`\p{Lu}`, mkCharClass(unicode.IsUpper)},
-	{`[\p{Lu}]`, mkCharClass(unicode.IsUpper)},
-	{`(?i)[\p{Lu}]`, mkCharClass(isUpperFold)},
-	{`\p{Any}`, `dot{}`},
-	{`\p{^Any}`, `cc{}`},
-
-	// Hex, octal.
-	{`[\012-\234]\141`, `cat{cc{0xa-0x9c}lit{a}}`},
-	{`[\x{41}-\x7a]\x61`, `cat{cc{0x41-0x7a}lit{a}}`},
-
-	// More interesting regular expressions.
-	{`a{,2}`, `str{a{,2}}`},
-	{`\.\^\$\\`, `str{.^$\}`},
-	{`[a-zABC]`, `cc{0x41-0x43 0x61-0x7a}`},
-	{`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
-	{`[α-ε☺]`, `cc{0x3b1-0x3b5 0x263a}`}, // utf-8
-	{`a*{`, `cat{star{lit{a}}lit{{}}`},
-
-	// Test precedences
-	{`(?:ab)*`, `star{str{ab}}`},
-	{`(ab)*`, `star{cap{str{ab}}}`},
-	{`ab|cd`, `alt{str{ab}str{cd}}`},
-	{`a(b|c)d`, `cat{lit{a}cap{cc{0x62-0x63}}lit{d}}`},
-
-	// Test flattening.
-	{`(?:a)`, `lit{a}`},
-	{`(?:ab)(?:cd)`, `str{abcd}`},
-	{`(?:a+b+)(?:c+d+)`, `cat{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
-	{`(?:a+|b+)|(?:c+|d+)`, `alt{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
-	{`(?:a|b)|(?:c|d)`, `cc{0x61-0x64}`},
-	{`a|.`, `dot{}`},
-	{`.|a`, `dot{}`},
-	{`(?:[abc]|A|Z|hello|world)`, `alt{cc{0x41 0x5a 0x61-0x63}str{hello}str{world}}`},
-	{`(?:[abc]|A|Z)`, `cc{0x41 0x5a 0x61-0x63}`},
-
-	// Test Perl quoted literals
-	{`\Q+|*?{[\E`, `str{+|*?{[}`},
-	{`\Q+\E+`, `plus{lit{+}}`},
-	{`\Q\\E`, `lit{\}`},
-	{`\Q\\\E`, `str{\\}`},
-
-	// Test Perl \A and \z
-	{`(?m)^`, `bol{}`},
-	{`(?m)$`, `eol{}`},
-	{`(?-m)^`, `bot{}`},
-	{`(?-m)$`, `eot{}`},
-	{`(?m)\A`, `bot{}`},
-	{`(?m)\z`, `eot{\z}`},
-	{`(?-m)\A`, `bot{}`},
-	{`(?-m)\z`, `eot{\z}`},
-
-	// Test named captures
-	{`(?P<name>a)`, `cap{name:lit{a}}`},
-
-	// Case-folded literals
-	{`[Aa]`, `litfold{A}`},
-	{`[\x{100}\x{101}]`, `litfold{Ä€}`},
-	{`[Δδ]`, `litfold{Δ}`},
-
-	// Strings
-	{`abcde`, `str{abcde}`},
-	{`[Aa][Bb]cd`, `cat{strfold{AB}str{cd}}`},
-
-	// Factoring.
-	{`abc|abd|aef|bcx|bcy`, `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}cat{str{bc}cc{0x78-0x79}}}`},
-	{`ax+y|ax+z|ay+w`, `cat{lit{a}alt{cat{plus{lit{x}}cc{0x79-0x7a}}cat{plus{lit{y}}lit{w}}}}`},
-
-	// Bug fixes.
-	{`(?:.)`, `dot{}`},
-	{`(?:x|(?:xa))`, `cat{lit{x}alt{emp{}lit{a}}}`},
-	{`(?:.|(?:.a))`, `cat{dot{}alt{emp{}lit{a}}}`},
-	{`(?:A(?:A|a))`, `cat{lit{A}litfold{A}}`},
-	{`(?:A|a)`, `litfold{A}`},
-	{`A|(?:A|a)`, `litfold{A}`},
-	{`(?s).`, `dot{}`},
-	{`(?-s).`, `dnl{}`},
-	{`(?:(?:^).)`, `cat{bol{}dot{}}`},
-	{`(?-s)(?:(?:^).)`, `cat{bol{}dnl{}}`},
-
-	// RE2 prefix_tests
-	{`abc|abd`, `cat{str{ab}cc{0x63-0x64}}`},
-	{`a(?:b)c|abd`, `cat{str{ab}cc{0x63-0x64}}`},
-	{`abc|abd|aef|bcx|bcy`,
-		`alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}` +
-			`cat{str{bc}cc{0x78-0x79}}}`},
-	{`abc|x|abd`, `alt{str{abc}lit{x}str{abd}}`},
-	{`(?i)abc|ABD`, `cat{strfold{AB}cc{0x43-0x44 0x63-0x64}}`},
-	{`[ab]c|[ab]d`, `cat{cc{0x61-0x62}cc{0x63-0x64}}`},
-	{`(?:xx|yy)c|(?:xx|yy)d`,
-		`cat{alt{str{xx}str{yy}}cc{0x63-0x64}}`},
-	{`x{2}|x{2}[0-9]`,
-		`cat{rep{2,2 lit{x}}alt{emp{}cc{0x30-0x39}}}`},
-	{`x{2}y|x{2}[0-9]y`,
-		`cat{rep{2,2 lit{x}}alt{lit{y}cat{cc{0x30-0x39}lit{y}}}}`},
-}
-
-const testFlags = MatchNL | PerlX | UnicodeGroups
-
-func TestParseSimple(t *testing.T) {
-	testParseDump(t, parseTests, testFlags)
-}
-
-var foldcaseTests = []parseTest{
-	{`AbCdE`, `strfold{ABCDE}`},
-	{`[Aa]`, `litfold{A}`},
-	{`a`, `litfold{A}`},
-
-	// 0x17F is an old English long s (looks like an f) and folds to s.
-	// 0x212A is the Kelvin symbol and folds to k.
-	{`A[F-g]`, `cat{litfold{A}cc{0x41-0x7a 0x17f 0x212a}}`}, // [Aa][A-z...]
-	{`[[:upper:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
-	{`[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
-}
-
-func TestParseFoldCase(t *testing.T) {
-	testParseDump(t, foldcaseTests, FoldCase)
-}
-
-var literalTests = []parseTest{
-	{"(|)^$.[*+?]{5,10},\\", "str{(|)^$.[*+?]{5,10},\\}"},
-}
-
-func TestParseLiteral(t *testing.T) {
-	testParseDump(t, literalTests, Literal)
-}
-
-var matchnlTests = []parseTest{
-	{`.`, `dot{}`},
-	{"\n", "lit{\n}"},
-	{`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
-	{`[a\n]`, `cc{0xa 0x61}`},
-}
-
-func TestParseMatchNL(t *testing.T) {
-	testParseDump(t, matchnlTests, MatchNL)
-}
-
-var nomatchnlTests = []parseTest{
-	{`.`, `dnl{}`},
-	{"\n", "lit{\n}"},
-	{`[^a]`, `cc{0x0-0x9 0xb-0x60 0x62-0x10ffff}`},
-	{`[a\n]`, `cc{0xa 0x61}`},
-}
-
-func TestParseNoMatchNL(t *testing.T) {
-	testParseDump(t, nomatchnlTests, 0)
-}
-
-// Test Parse -> Dump.
-func testParseDump(t *testing.T, tests []parseTest, flags Flags) {
-	for _, tt := range tests {
-		re, err := Parse(tt.Regexp, flags)
-		if err != nil {
-			t.Errorf("Parse(%#q): %v", tt.Regexp, err)
-			continue
-		}
-		d := dump(re)
-		if d != tt.Dump {
-			t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
-		}
-	}
-}
-
-// dump prints a string representation of the regexp showing
-// the structure explicitly.
-func dump(re *Regexp) string {
-	var b bytes.Buffer
-	dumpRegexp(&b, re)
-	return b.String()
-}
-
-var opNames = []string{
-	OpNoMatch:        "no",
-	OpEmptyMatch:     "emp",
-	OpLiteral:        "lit",
-	OpCharClass:      "cc",
-	OpAnyCharNotNL:   "dnl",
-	OpAnyChar:        "dot",
-	OpBeginLine:      "bol",
-	OpEndLine:        "eol",
-	OpBeginText:      "bot",
-	OpEndText:        "eot",
-	OpWordBoundary:   "wb",
-	OpNoWordBoundary: "nwb",
-	OpCapture:        "cap",
-	OpStar:           "star",
-	OpPlus:           "plus",
-	OpQuest:          "que",
-	OpRepeat:         "rep",
-	OpConcat:         "cat",
-	OpAlternate:      "alt",
-}
-
-// dumpRegexp writes an encoding of the syntax tree for the regexp re to b.
-// It is used during testing to distinguish between parses that might print
-// the same using re's String method.
-func dumpRegexp(b *bytes.Buffer, re *Regexp) {
-	if int(re.Op) >= len(opNames) || opNames[re.Op] == "" {
-		fmt.Fprintf(b, "op%d", re.Op)
-	} else {
-		switch re.Op {
-		default:
-			b.WriteString(opNames[re.Op])
-		case OpStar, OpPlus, OpQuest, OpRepeat:
-			if re.Flags&NonGreedy != 0 {
-				b.WriteByte('n')
-			}
-			b.WriteString(opNames[re.Op])
-		case OpLiteral:
-			if len(re.Rune) > 1 {
-				b.WriteString("str")
-			} else {
-				b.WriteString("lit")
-			}
-			if re.Flags&FoldCase != 0 {
-				for _, r := range re.Rune {
-					if unicode.SimpleFold(r) != r {
-						b.WriteString("fold")
-						break
-					}
-				}
-			}
-		}
-	}
-	b.WriteByte('{')
-	switch re.Op {
-	case OpEndText:
-		if re.Flags&WasDollar == 0 {
-			b.WriteString(`\z`)
-		}
-	case OpLiteral:
-		for _, r := range re.Rune {
-			b.WriteRune(r)
-		}
-	case OpConcat, OpAlternate:
-		for _, sub := range re.Sub {
-			dumpRegexp(b, sub)
-		}
-	case OpStar, OpPlus, OpQuest:
-		dumpRegexp(b, re.Sub[0])
-	case OpRepeat:
-		fmt.Fprintf(b, "%d,%d ", re.Min, re.Max)
-		dumpRegexp(b, re.Sub[0])
-	case OpCapture:
-		if re.Name != "" {
-			b.WriteString(re.Name)
-			b.WriteByte(':')
-		}
-		dumpRegexp(b, re.Sub[0])
-	case OpCharClass:
-		sep := ""
-		for i := 0; i < len(re.Rune); i += 2 {
-			b.WriteString(sep)
-			sep = " "
-			lo, hi := re.Rune[i], re.Rune[i+1]
-			if lo == hi {
-				fmt.Fprintf(b, "%#x", lo)
-			} else {
-				fmt.Fprintf(b, "%#x-%#x", lo, hi)
-			}
-		}
-	}
-	b.WriteByte('}')
-}
-
-func mkCharClass(f func(int) bool) string {
-	re := &Regexp{Op: OpCharClass}
-	lo := -1
-	for i := 0; i <= unicode.MaxRune; i++ {
-		if f(i) {
-			if lo < 0 {
-				lo = i
-			}
-		} else {
-			if lo >= 0 {
-				re.Rune = append(re.Rune, lo, i-1)
-				lo = -1
-			}
-		}
-	}
-	if lo >= 0 {
-		re.Rune = append(re.Rune, lo, unicode.MaxRune)
-	}
-	return dump(re)
-}
-
-func isUpperFold(rune int) bool {
-	if unicode.IsUpper(rune) {
-		return true
-	}
-	c := unicode.SimpleFold(rune)
-	for c != rune {
-		if unicode.IsUpper(c) {
-			return true
-		}
-		c = unicode.SimpleFold(c)
-	}
-	return false
-}
-
-func TestFoldConstants(t *testing.T) {
-	last := -1
-	for i := 0; i <= unicode.MaxRune; i++ {
-		if unicode.SimpleFold(i) == i {
-			continue
-		}
-		if last == -1 && minFold != i {
-			t.Errorf("minFold=%#U should be %#U", minFold, i)
-		}
-		last = i
-	}
-	if maxFold != last {
-		t.Errorf("maxFold=%#U should be %#U", maxFold, last)
-	}
-}
-
-func TestAppendRangeCollapse(t *testing.T) {
-	// AppendRange should collapse each of the new ranges
-	// into the earlier ones (it looks back two ranges), so that
-	// the slice never grows very large.
-	// Note that we are not calling cleanClass.
-	var r []int
-	for i := 'A'; i <= 'Z'; i++ {
-		r = appendRange(r, i, i)
-		r = appendRange(r, i+'a'-'A', i+'a'-'A')
-	}
-	if string(r) != "AZaz" {
-		t.Errorf("appendRange interlaced A-Z a-z = %s, want AZaz", string(r))
-	}
-}
-
-var invalidRegexps = []string{
-	`(`,
-	`)`,
-	`(a`,
-	`(a|b|`,
-	`(a|b`,
-	`[a-z`,
-	`([a-z)`,
-	`x{1001}`,
-	`x{9876543210}`,
-	`x{2,1}`,
-	`x{1,9876543210}`,
-	"\xff", // Invalid UTF-8
-	"[\xff]",
-	"[\\\xff]",
-	"\\\xff",
-	`(?P<name>a`,
-	`(?P<name>`,
-	`(?P<name`,
-	`(?P<x y>a)`,
-	`(?P<>a)`,
-	`[a-Z]`,
-	`(?i)[a-Z]`,
-	`a{100000}`,
-	`a{100000,}`,
-}
-
-var onlyPerl = []string{
-	`[a-b-c]`,
-	`\Qabc\E`,
-	`\Q*+?{[\E`,
-	`\Q\\E`,
-	`\Q\\\E`,
-	`\Q\\\\E`,
-	`\Q\\\\\E`,
-	`(?:a)`,
-	`(?P<name>a)`,
-}
-
-var onlyPOSIX = []string{
-	"a++",
-	"a**",
-	"a?*",
-	"a+*",
-	"a{1}*",
-	".{1}{2}.{3}",
-}
-
-func TestParseInvalidRegexps(t *testing.T) {
-	for _, regexp := range invalidRegexps {
-		if re, err := Parse(regexp, Perl); err == nil {
-			t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re))
-		}
-		if re, err := Parse(regexp, POSIX); err == nil {
-			t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re))
-		}
-	}
-	for _, regexp := range onlyPerl {
-		if _, err := Parse(regexp, Perl); err != nil {
-			t.Errorf("Parse(%#q, Perl): %v", regexp, err)
-		}
-		if re, err := Parse(regexp, POSIX); err == nil {
-			t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re))
-		}
-	}
-	for _, regexp := range onlyPOSIX {
-		if re, err := Parse(regexp, Perl); err == nil {
-			t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re))
-		}
-		if _, err := Parse(regexp, POSIX); err != nil {
-			t.Errorf("Parse(%#q, POSIX): %v", regexp, err)
-		}
-	}
-}
-
-func TestToStringEquivalentParse(t *testing.T) {
-	for _, tt := range parseTests {
-		re, err := Parse(tt.Regexp, testFlags)
-		if err != nil {
-			t.Errorf("Parse(%#q): %v", tt.Regexp, err)
-			continue
-		}
-		d := dump(re)
-		if d != tt.Dump {
-			t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
-			continue
-		}
-
-		s := re.String()
-		if s != tt.Regexp {
-			// If ToString didn't return the original regexp,
-			// it must have found one with fewer parens.
-			// Unfortunately we can't check the length here, because
-			// ToString produces "\\{" for a literal brace,
-			// but "{" is a shorter equivalent in some contexts.
-			nre, err := Parse(s, testFlags)
-			if err != nil {
-				t.Errorf("Parse(%#q.String() = %#q): %v", tt.Regexp, t, err)
-				continue
-			}
-			nd := dump(nre)
-			if d != nd {
-				t.Errorf("Parse(%#q) -> %#q; %#q vs %#q", tt.Regexp, s, d, nd)
-			}
-
-			ns := nre.String()
-			if s != ns {
-				t.Errorf("Parse(%#q) -> %#q -> %#q", tt.Regexp, s, ns)
-			}
-		}
-	}
-}
diff --git a/src/pkg/exp/regexp/syntax/perl_groups.go b/src/pkg/exp/regexp/syntax/perl_groups.go
deleted file mode 100644
index 05b392c..0000000
--- a/src/pkg/exp/regexp/syntax/perl_groups.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// GENERATED BY make_perl_groups.pl; DO NOT EDIT.
-// make_perl_groups.pl >perl_groups.go
-
-package syntax
-
-var code1 = []int{ /* \d */
-	0x30, 0x39,
-}
-
-var code2 = []int{ /* \s */
-	0x9, 0xa,
-	0xc, 0xd,
-	0x20, 0x20,
-}
-
-var code3 = []int{ /* \w */
-	0x30, 0x39,
-	0x41, 0x5a,
-	0x5f, 0x5f,
-	0x61, 0x7a,
-}
-
-var perlGroup = map[string]charGroup{
-	`\d`: {+1, code1},
-	`\D`: {-1, code1},
-	`\s`: {+1, code2},
-	`\S`: {-1, code2},
-	`\w`: {+1, code3},
-	`\W`: {-1, code3},
-}
-var code4 = []int{ /* [:alnum:] */
-	0x30, 0x39,
-	0x41, 0x5a,
-	0x61, 0x7a,
-}
-
-var code5 = []int{ /* [:alpha:] */
-	0x41, 0x5a,
-	0x61, 0x7a,
-}
-
-var code6 = []int{ /* [:ascii:] */
-	0x0, 0x7f,
-}
-
-var code7 = []int{ /* [:blank:] */
-	0x9, 0x9,
-	0x20, 0x20,
-}
-
-var code8 = []int{ /* [:cntrl:] */
-	0x0, 0x1f,
-	0x7f, 0x7f,
-}
-
-var code9 = []int{ /* [:digit:] */
-	0x30, 0x39,
-}
-
-var code10 = []int{ /* [:graph:] */
-	0x21, 0x7e,
-}
-
-var code11 = []int{ /* [:lower:] */
-	0x61, 0x7a,
-}
-
-var code12 = []int{ /* [:print:] */
-	0x20, 0x7e,
-}
-
-var code13 = []int{ /* [:punct:] */
-	0x21, 0x2f,
-	0x3a, 0x40,
-	0x5b, 0x60,
-	0x7b, 0x7e,
-}
-
-var code14 = []int{ /* [:space:] */
-	0x9, 0xd,
-	0x20, 0x20,
-}
-
-var code15 = []int{ /* [:upper:] */
-	0x41, 0x5a,
-}
-
-var code16 = []int{ /* [:word:] */
-	0x30, 0x39,
-	0x41, 0x5a,
-	0x5f, 0x5f,
-	0x61, 0x7a,
-}
-
-var code17 = []int{ /* [:xdigit:] */
-	0x30, 0x39,
-	0x41, 0x46,
-	0x61, 0x66,
-}
-
-var posixGroup = map[string]charGroup{
-	`[:alnum:]`:   {+1, code4},
-	`[:^alnum:]`:  {-1, code4},
-	`[:alpha:]`:   {+1, code5},
-	`[:^alpha:]`:  {-1, code5},
-	`[:ascii:]`:   {+1, code6},
-	`[:^ascii:]`:  {-1, code6},
-	`[:blank:]`:   {+1, code7},
-	`[:^blank:]`:  {-1, code7},
-	`[:cntrl:]`:   {+1, code8},
-	`[:^cntrl:]`:  {-1, code8},
-	`[:digit:]`:   {+1, code9},
-	`[:^digit:]`:  {-1, code9},
-	`[:graph:]`:   {+1, code10},
-	`[:^graph:]`:  {-1, code10},
-	`[:lower:]`:   {+1, code11},
-	`[:^lower:]`:  {-1, code11},
-	`[:print:]`:   {+1, code12},
-	`[:^print:]`:  {-1, code12},
-	`[:punct:]`:   {+1, code13},
-	`[:^punct:]`:  {-1, code13},
-	`[:space:]`:   {+1, code14},
-	`[:^space:]`:  {-1, code14},
-	`[:upper:]`:   {+1, code15},
-	`[:^upper:]`:  {-1, code15},
-	`[:word:]`:    {+1, code16},
-	`[:^word:]`:   {-1, code16},
-	`[:xdigit:]`:  {+1, code17},
-	`[:^xdigit:]`: {-1, code17},
-}
diff --git a/src/pkg/exp/regexp/syntax/prog.go b/src/pkg/exp/regexp/syntax/prog.go
deleted file mode 100644
index e92baac..0000000
--- a/src/pkg/exp/regexp/syntax/prog.go
+++ /dev/null
@@ -1,287 +0,0 @@
-package syntax
-
-import (
-	"bytes"
-	"strconv"
-	"unicode"
-)
-
-// Compiled program.
-// May not belong in this package, but convenient for now.
-
-// A Prog is a compiled regular expression program.
-type Prog struct {
-	Inst   []Inst
-	Start  int // index of start instruction
-	NumCap int // number of InstCapture insts in re
-}
-
-// An InstOp is an instruction opcode.
-type InstOp uint8
-
-const (
-	InstAlt InstOp = iota
-	InstAltMatch
-	InstCapture
-	InstEmptyWidth
-	InstMatch
-	InstFail
-	InstNop
-	InstRune
-)
-
-// An EmptyOp specifies a kind or mixture of zero-width assertions.
-type EmptyOp uint8
-
-const (
-	EmptyBeginLine EmptyOp = 1 << iota
-	EmptyEndLine
-	EmptyBeginText
-	EmptyEndText
-	EmptyWordBoundary
-	EmptyNoWordBoundary
-)
-
-// EmptyOpContext returns the zero-width assertions
-// satisfied at the position between the runes r1 and r2.
-// Passing r1 == -1 indicates that the position is
-// at the beginning of the text.
-// Passing r2 == -1 indicates that the position is
-// at the end of the text.
-func EmptyOpContext(r1, r2 int) EmptyOp {
-	var op EmptyOp
-	if r1 < 0 {
-		op |= EmptyBeginText | EmptyBeginLine
-	}
-	if r1 == '\n' {
-		op |= EmptyBeginLine
-	}
-	if r2 < 0 {
-		op |= EmptyEndText | EmptyEndLine
-	}
-	if r2 == '\n' {
-		op |= EmptyEndLine
-	}
-	if IsWordChar(r1) != IsWordChar(r2) {
-		op |= EmptyWordBoundary
-	} else {
-		op |= EmptyNoWordBoundary
-	}
-	return op
-}
-
-// IsWordChar reports whether r is consider a ``word character''
-// during the evaluation of the \b and \B zero-width assertions.
-// These assertions are ASCII-only: the word characters are [A-Za-z0-9_].
-func IsWordChar(r int) bool {
-	return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_'
-}
-
-// An Inst is a single instruction in a regular expression program.
-type Inst struct {
-	Op   InstOp
-	Out  uint32 // all but InstMatch, InstFail
-	Arg  uint32 // InstAlt, InstAltMatch, InstCapture, InstEmptyWidth
-	Rune []int
-}
-
-func (p *Prog) String() string {
-	var b bytes.Buffer
-	dumpProg(&b, p)
-	return b.String()
-}
-
-// skipNop follows any no-op or capturing instructions
-// and returns the resulting pc.
-func (p *Prog) skipNop(pc uint32) *Inst {
-	i := &p.Inst[pc]
-	for i.Op == InstNop || i.Op == InstCapture {
-		pc = i.Out
-		i = &p.Inst[pc]
-	}
-	return i
-}
-
-// Prefix returns a literal string that all matches for the
-// regexp must start with.  Complete is true if the prefix
-// is the entire match.
-func (p *Prog) Prefix() (prefix string, complete bool) {
-	i := p.skipNop(uint32(p.Start))
-
-	// Avoid allocation of buffer if prefix is empty.
-	if i.Op != InstRune || len(i.Rune) != 1 {
-		return "", i.Op == InstMatch
-	}
-
-	// Have prefix; gather characters.
-	var buf bytes.Buffer
-	for i.Op == InstRune && len(i.Rune) == 1 && Flags(i.Arg)&FoldCase == 0 {
-		buf.WriteRune(i.Rune[0])
-		i = p.skipNop(i.Out)
-	}
-	return buf.String(), i.Op == InstMatch
-}
-
-// StartCond returns the leading empty-width conditions that must
-// be true in any match.  It returns ^EmptyOp(0) if no matches are possible.
-func (p *Prog) StartCond() EmptyOp {
-	var flag EmptyOp
-	pc := uint32(p.Start)
-	i := &p.Inst[pc]
-Loop:
-	for {
-		switch i.Op {
-		case InstEmptyWidth:
-			flag |= EmptyOp(i.Arg)
-		case InstFail:
-			return ^EmptyOp(0)
-		case InstCapture, InstNop:
-			// skip
-		default:
-			break Loop
-		}
-		pc = i.Out
-		i = &p.Inst[pc]
-	}
-	return flag
-}
-
-// MatchRune returns true if the instruction matches (and consumes) r.
-// It should only be called when i.Op == InstRune.
-func (i *Inst) MatchRune(r int) bool {
-	rune := i.Rune
-
-	// Special case: single-rune slice is from literal string, not char class.
-	if len(rune) == 1 {
-		r0 := rune[0]
-		if r == r0 {
-			return true
-		}
-		if Flags(i.Arg)&FoldCase != 0 {
-			for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) {
-				if r == r1 {
-					return true
-				}
-			}
-		}
-		return false
-	}
-
-	// Peek at the first few pairs.
-	// Should handle ASCII well.
-	for j := 0; j < len(rune) && j <= 8; j += 2 {
-		if r < rune[j] {
-			return false
-		}
-		if r <= rune[j+1] {
-			return true
-		}
-	}
-
-	// Otherwise binary search.
-	lo := 0
-	hi := len(rune) / 2
-	for lo < hi {
-		m := lo + (hi-lo)/2
-		if c := rune[2*m]; c <= r {
-			if r <= rune[2*m+1] {
-				return true
-			}
-			lo = m + 1
-		} else {
-			hi = m
-		}
-	}
-	return false
-}
-
-// As per re2's Prog::IsWordChar. Determines whether rune is an ASCII word char.
-// Since we act on runes, it would be easy to support Unicode here.
-func wordRune(rune int) bool {
-	return rune == '_' ||
-		('A' <= rune && rune <= 'Z') ||
-		('a' <= rune && rune <= 'z') ||
-		('0' <= rune && rune <= '9')
-}
-
-// MatchEmptyWidth returns true if the instruction matches
-// an empty string between the runes before and after.
-// It should only be called when i.Op == InstEmptyWidth.
-func (i *Inst) MatchEmptyWidth(before int, after int) bool {
-	switch EmptyOp(i.Arg) {
-	case EmptyBeginLine:
-		return before == '\n' || before == -1
-	case EmptyEndLine:
-		return after == '\n' || after == -1
-	case EmptyBeginText:
-		return before == -1
-	case EmptyEndText:
-		return after == -1
-	case EmptyWordBoundary:
-		return wordRune(before) != wordRune(after)
-	case EmptyNoWordBoundary:
-		return wordRune(before) == wordRune(after)
-	}
-	panic("unknown empty width arg")
-}
-
-func (i *Inst) String() string {
-	var b bytes.Buffer
-	dumpInst(&b, i)
-	return b.String()
-}
-
-func bw(b *bytes.Buffer, args ...string) {
-	for _, s := range args {
-		b.WriteString(s)
-	}
-}
-
-func dumpProg(b *bytes.Buffer, p *Prog) {
-	for j := range p.Inst {
-		i := &p.Inst[j]
-		pc := strconv.Itoa(j)
-		if len(pc) < 3 {
-			b.WriteString("   "[len(pc):])
-		}
-		if j == p.Start {
-			pc += "*"
-		}
-		bw(b, pc, "\t")
-		dumpInst(b, i)
-		bw(b, "\n")
-	}
-}
-
-func u32(i uint32) string {
-	return strconv.Uitoa64(uint64(i))
-}
-
-func dumpInst(b *bytes.Buffer, i *Inst) {
-	switch i.Op {
-	case InstAlt:
-		bw(b, "alt -> ", u32(i.Out), ", ", u32(i.Arg))
-	case InstAltMatch:
-		bw(b, "altmatch -> ", u32(i.Out), ", ", u32(i.Arg))
-	case InstCapture:
-		bw(b, "cap ", u32(i.Arg), " -> ", u32(i.Out))
-	case InstEmptyWidth:
-		bw(b, "empty ", u32(i.Arg), " -> ", u32(i.Out))
-	case InstMatch:
-		bw(b, "match")
-	case InstFail:
-		bw(b, "fail")
-	case InstNop:
-		bw(b, "nop -> ", u32(i.Out))
-	case InstRune:
-		if i.Rune == nil {
-			// shouldn't happen
-			bw(b, "rune <nil>")
-		}
-		bw(b, "rune ", strconv.QuoteToASCII(string(i.Rune)))
-		if Flags(i.Arg)&FoldCase != 0 {
-			bw(b, "/i")
-		}
-		bw(b, " -> ", u32(i.Out))
-	}
-}
diff --git a/src/pkg/exp/regexp/syntax/prog_test.go b/src/pkg/exp/regexp/syntax/prog_test.go
deleted file mode 100644
index 3fe0c58..0000000
--- a/src/pkg/exp/regexp/syntax/prog_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-package syntax
-
-import (
-	"testing"
-)
-
-var compileTests = []struct {
-	Regexp string
-	Prog   string
-}{
-	{"a", `  0	fail
-  1*	rune "a" -> 2
-  2	match
-`},
-	{"[A-M][n-z]", `  0	fail
-  1*	rune "AM" -> 2
-  2	rune "nz" -> 3
-  3	match
-`},
-	{"", `  0	fail
-  1*	nop -> 2
-  2	match
-`},
-	{"a?", `  0	fail
-  1	rune "a" -> 3
-  2*	alt -> 1, 3
-  3	match
-`},
-	{"a??", `  0	fail
-  1	rune "a" -> 3
-  2*	alt -> 3, 1
-  3	match
-`},
-	{"a+", `  0	fail
-  1*	rune "a" -> 2
-  2	alt -> 1, 3
-  3	match
-`},
-	{"a+?", `  0	fail
-  1*	rune "a" -> 2
-  2	alt -> 3, 1
-  3	match
-`},
-	{"a*", `  0	fail
-  1	rune "a" -> 2
-  2*	alt -> 1, 3
-  3	match
-`},
-	{"a*?", `  0	fail
-  1	rune "a" -> 2
-  2*	alt -> 3, 1
-  3	match
-`},
-	{"a+b+", `  0	fail
-  1*	rune "a" -> 2
-  2	alt -> 1, 3
-  3	rune "b" -> 4
-  4	alt -> 3, 5
-  5	match
-`},
-	{"(a+)(b+)", `  0	fail
-  1*	cap 2 -> 2
-  2	rune "a" -> 3
-  3	alt -> 2, 4
-  4	cap 3 -> 5
-  5	cap 4 -> 6
-  6	rune "b" -> 7
-  7	alt -> 6, 8
-  8	cap 5 -> 9
-  9	match
-`},
-	{"a+|b+", `  0	fail
-  1	rune "a" -> 2
-  2	alt -> 1, 6
-  3	rune "b" -> 4
-  4	alt -> 3, 6
-  5*	alt -> 1, 3
-  6	match
-`},
-	{"A[Aa]", `  0	fail
-  1*	rune "A" -> 2
-  2	rune "A"/i -> 3
-  3	match
-`},
-	{"(?:(?:^).)", `  0	fail
-  1*	empty 4 -> 2
-  2	rune "\x00\t\v\U0010ffff" -> 3
-  3	match
-`},
-}
-
-func TestCompile(t *testing.T) {
-	for _, tt := range compileTests {
-		re, _ := Parse(tt.Regexp, Perl)
-		p, _ := Compile(re)
-		s := p.String()
-		if s != tt.Prog {
-			t.Errorf("compiled %#q:\n--- have\n%s---\n--- want\n%s---", tt.Regexp, s, tt.Prog)
-		}
-	}
-}
diff --git a/src/pkg/exp/regexp/syntax/regexp.go b/src/pkg/exp/regexp/syntax/regexp.go
deleted file mode 100644
index 033848d..0000000
--- a/src/pkg/exp/regexp/syntax/regexp.go
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright 2011 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 syntax parses regular expressions into syntax trees.
-// WORK IN PROGRESS.
-package syntax
-
-// Note to implementers:
-// In this package, re is always a *Regexp and r is always a rune.
-
-import (
-	"bytes"
-	"strconv"
-	"strings"
-	"unicode"
-)
-
-// A Regexp is a node in a regular expression syntax tree.
-type Regexp struct {
-	Op       Op // operator
-	Flags    Flags
-	Sub      []*Regexp  // subexpressions, if any
-	Sub0     [1]*Regexp // storage for short Sub
-	Rune     []int      // matched runes, for OpLiteral, OpCharClass
-	Rune0    [2]int     // storage for short Rune
-	Min, Max int        // min, max for OpRepeat
-	Cap      int        // capturing index, for OpCapture
-	Name     string     // capturing name, for OpCapture
-}
-
-// An Op is a single regular expression operator.
-type Op uint8
-
-// Operators are listed in precedence order, tightest binding to weakest.
-// Character class operators are listed simplest to most complex
-// (OpLiteral, OpCharClass, OpAnyCharNotNL, OpAnyChar).
-
-const (
-	OpNoMatch        Op = 1 + iota // matches no strings
-	OpEmptyMatch                   // matches empty string
-	OpLiteral                      // matches Runes sequence
-	OpCharClass                    // matches Runes interpreted as range pair list
-	OpAnyCharNotNL                 // matches any character
-	OpAnyChar                      // matches any character
-	OpBeginLine                    // matches empty string at beginning of line
-	OpEndLine                      // matches empty string at end of line
-	OpBeginText                    // matches empty string at beginning of text
-	OpEndText                      // matches empty string at end of text
-	OpWordBoundary                 // matches word boundary `\b`
-	OpNoWordBoundary               // matches word non-boundary `\B`
-	OpCapture                      // capturing subexpression with index Cap, optional name Name
-	OpStar                         // matches Sub[0] zero or more times
-	OpPlus                         // matches Sub[0] one or more times
-	OpQuest                        // matches Sub[0] zero or one times
-	OpRepeat                       // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit)
-	OpConcat                       // matches concatenation of Subs
-	OpAlternate                    // matches alternation of Subs
-)
-
-const opPseudo Op = 128 // where pseudo-ops start
-
-// Equal returns true if x and y have identical structure.
-func (x *Regexp) Equal(y *Regexp) bool {
-	if x == nil || y == nil {
-		return x == y
-	}
-	if x.Op != y.Op {
-		return false
-	}
-	switch x.Op {
-	case OpEndText:
-		// The parse flags remember whether this is \z or \Z.
-		if x.Flags&WasDollar != y.Flags&WasDollar {
-			return false
-		}
-
-	case OpLiteral, OpCharClass:
-		if len(x.Rune) != len(y.Rune) {
-			return false
-		}
-		for i, r := range x.Rune {
-			if r != y.Rune[i] {
-				return false
-			}
-		}
-
-	case OpAlternate, OpConcat:
-		if len(x.Sub) != len(y.Sub) {
-			return false
-		}
-		for i, sub := range x.Sub {
-			if !sub.Equal(y.Sub[i]) {
-				return false
-			}
-		}
-
-	case OpStar, OpPlus, OpQuest:
-		if x.Flags&NonGreedy != y.Flags&NonGreedy || !x.Sub[0].Equal(y.Sub[0]) {
-			return false
-		}
-
-	case OpRepeat:
-		if x.Flags&NonGreedy != y.Flags&NonGreedy || x.Min != y.Min || x.Max != y.Max || !x.Sub[0].Equal(y.Sub[0]) {
-			return false
-		}
-
-	case OpCapture:
-		if x.Cap != y.Cap || x.Name != y.Name || !x.Sub[0].Equal(y.Sub[0]) {
-			return false
-		}
-	}
-	return true
-}
-
-// writeRegexp writes the Perl syntax for the regular expression re to b.
-func writeRegexp(b *bytes.Buffer, re *Regexp) {
-	switch re.Op {
-	default:
-		b.WriteString("<invalid op" + strconv.Itoa(int(re.Op)) + ">")
-	case OpNoMatch:
-		b.WriteString(`[^\x00-\x{10FFFF}]`)
-	case OpEmptyMatch:
-		b.WriteString(`(?:)`)
-	case OpLiteral:
-		if re.Flags&FoldCase != 0 {
-			b.WriteString(`(?i:`)
-		}
-		for _, r := range re.Rune {
-			escape(b, r, false)
-		}
-		if re.Flags&FoldCase != 0 {
-			b.WriteString(`)`)
-		}
-	case OpCharClass:
-		if len(re.Rune)%2 != 0 {
-			b.WriteString(`[invalid char class]`)
-			break
-		}
-		b.WriteRune('[')
-		if len(re.Rune) == 0 {
-			b.WriteString(`^\x00-\x{10FFFF}`)
-		} else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune {
-			// Contains 0 and MaxRune.  Probably a negated class.
-			// Print the gaps.
-			b.WriteRune('^')
-			for i := 1; i < len(re.Rune)-1; i += 2 {
-				lo, hi := re.Rune[i]+1, re.Rune[i+1]-1
-				escape(b, lo, lo == '-')
-				if lo != hi {
-					b.WriteRune('-')
-					escape(b, hi, hi == '-')
-				}
-			}
-		} else {
-			for i := 0; i < len(re.Rune); i += 2 {
-				lo, hi := re.Rune[i], re.Rune[i+1]
-				escape(b, lo, lo == '-')
-				if lo != hi {
-					b.WriteRune('-')
-					escape(b, hi, hi == '-')
-				}
-			}
-		}
-		b.WriteRune(']')
-	case OpAnyCharNotNL:
-		b.WriteString(`(?-s:.)`)
-	case OpAnyChar:
-		b.WriteString(`(?s:.)`)
-	case OpBeginLine:
-		b.WriteRune('^')
-	case OpEndLine:
-		b.WriteRune('$')
-	case OpBeginText:
-		b.WriteString(`\A`)
-	case OpEndText:
-		if re.Flags&WasDollar != 0 {
-			b.WriteString(`(?-m:$)`)
-		} else {
-			b.WriteString(`\z`)
-		}
-	case OpWordBoundary:
-		b.WriteString(`\b`)
-	case OpNoWordBoundary:
-		b.WriteString(`\B`)
-	case OpCapture:
-		if re.Name != "" {
-			b.WriteString(`(?P<`)
-			b.WriteString(re.Name)
-			b.WriteRune('>')
-		} else {
-			b.WriteRune('(')
-		}
-		if re.Sub[0].Op != OpEmptyMatch {
-			writeRegexp(b, re.Sub[0])
-		}
-		b.WriteRune(')')
-	case OpStar, OpPlus, OpQuest, OpRepeat:
-		if sub := re.Sub[0]; sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 {
-			b.WriteString(`(?:`)
-			writeRegexp(b, sub)
-			b.WriteString(`)`)
-		} else {
-			writeRegexp(b, sub)
-		}
-		switch re.Op {
-		case OpStar:
-			b.WriteRune('*')
-		case OpPlus:
-			b.WriteRune('+')
-		case OpQuest:
-			b.WriteRune('?')
-		case OpRepeat:
-			b.WriteRune('{')
-			b.WriteString(strconv.Itoa(re.Min))
-			if re.Max != re.Min {
-				b.WriteRune(',')
-				if re.Max >= 0 {
-					b.WriteString(strconv.Itoa(re.Max))
-				}
-			}
-			b.WriteRune('}')
-		}
-		if re.Flags&NonGreedy != 0 {
-			b.WriteRune('?')
-		}
-	case OpConcat:
-		for _, sub := range re.Sub {
-			if sub.Op == OpAlternate {
-				b.WriteString(`(?:`)
-				writeRegexp(b, sub)
-				b.WriteString(`)`)
-			} else {
-				writeRegexp(b, sub)
-			}
-		}
-	case OpAlternate:
-		for i, sub := range re.Sub {
-			if i > 0 {
-				b.WriteRune('|')
-			}
-			writeRegexp(b, sub)
-		}
-	}
-}
-
-func (re *Regexp) String() string {
-	var b bytes.Buffer
-	writeRegexp(&b, re)
-	return b.String()
-}
-
-const meta = `\.+*?()|[]{}^$`
-
-func escape(b *bytes.Buffer, r int, force bool) {
-	if unicode.IsPrint(r) {
-		if strings.IndexRune(meta, r) >= 0 || force {
-			b.WriteRune('\\')
-		}
-		b.WriteRune(r)
-		return
-	}
-
-	switch r {
-	case '\a':
-		b.WriteString(`\a`)
-	case '\f':
-		b.WriteString(`\f`)
-	case '\n':
-		b.WriteString(`\n`)
-	case '\r':
-		b.WriteString(`\r`)
-	case '\t':
-		b.WriteString(`\t`)
-	case '\v':
-		b.WriteString(`\v`)
-	default:
-		if r < 0x100 {
-			b.WriteString(`\x`)
-			s := strconv.Itob(r, 16)
-			if len(s) == 1 {
-				b.WriteRune('0')
-			}
-			b.WriteString(s)
-			break
-		}
-		b.WriteString(`\x{`)
-		b.WriteString(strconv.Itob(r, 16))
-		b.WriteString(`}`)
-	}
-}
-
-// MaxCap walks the regexp to find the maximum capture index.
-func (re *Regexp) MaxCap() int {
-	m := 0
-	if re.Op == OpCapture {
-		m = re.Cap
-	}
-	for _, sub := range re.Sub {
-		if n := sub.MaxCap(); m < n {
-			m = n
-		}
-	}
-	return m
-}
diff --git a/src/pkg/exp/ssh/Makefile b/src/pkg/exp/ssh/Makefile
deleted file mode 100644
index e8f33b7..0000000
--- a/src/pkg/exp/ssh/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=exp/ssh
-GOFILES=\
-	common.go\
-	messages.go\
-	server.go\
-	transport.go\
-        channel.go\
-        server_shell.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/exp/ssh/channel.go b/src/pkg/exp/ssh/channel.go
deleted file mode 100644
index 922584f..0000000
--- a/src/pkg/exp/ssh/channel.go
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"os"
-	"sync"
-)
-
-// A Channel is an ordered, reliable, duplex stream that is multiplexed over an
-// SSH connection.
-type Channel interface {
-	// Accept accepts the channel creation request.
-	Accept() os.Error
-	// Reject rejects the channel creation request. After calling this, no
-	// other methods on the Channel may be called. If they are then the
-	// peer is likely to signal a protocol error and drop the connection.
-	Reject(reason RejectionReason, message string) os.Error
-
-	// Read may return a ChannelRequest as an os.Error.
-	Read(data []byte) (int, os.Error)
-	Write(data []byte) (int, os.Error)
-	Close() os.Error
-
-	// AckRequest either sends an ack or nack to the channel request.
-	AckRequest(ok bool) os.Error
-
-	// ChannelType returns the type of the channel, as supplied by the
-	// client.
-	ChannelType() string
-	// ExtraData returns the arbitary payload for this channel, as supplied
-	// by the client. This data is specific to the channel type.
-	ExtraData() []byte
-}
-
-// ChannelRequest represents a request sent on a channel, outside of the normal
-// stream of bytes. It may result from calling Read on a Channel.
-type ChannelRequest struct {
-	Request   string
-	WantReply bool
-	Payload   []byte
-}
-
-func (c ChannelRequest) String() string {
-	return "channel request received"
-}
-
-// RejectionReason is an enumeration used when rejecting channel creation
-// requests. See RFC 4254, section 5.1.
-type RejectionReason int
-
-const (
-	Prohibited RejectionReason = iota + 1
-	ConnectionFailed
-	UnknownChannelType
-	ResourceShortage
-)
-
-type channel struct {
-	// immutable once created
-	chanType  string
-	extraData []byte
-
-	theyClosed  bool
-	theySentEOF bool
-	weClosed    bool
-	dead        bool
-
-	serverConn            *ServerConnection
-	myId, theirId         uint32
-	myWindow, theirWindow uint32
-	maxPacketSize         uint32
-	err                   os.Error
-
-	pendingRequests []ChannelRequest
-	pendingData     []byte
-	head, length    int
-
-	// This lock is inferior to serverConn.lock
-	lock sync.Mutex
-	cond *sync.Cond
-}
-
-func (c *channel) Accept() os.Error {
-	c.serverConn.lock.Lock()
-	defer c.serverConn.lock.Unlock()
-
-	if c.serverConn.err != nil {
-		return c.serverConn.err
-	}
-
-	confirm := channelOpenConfirmMsg{
-		PeersId:       c.theirId,
-		MyId:          c.myId,
-		MyWindow:      c.myWindow,
-		MaxPacketSize: c.maxPacketSize,
-	}
-	return c.serverConn.writePacket(marshal(msgChannelOpenConfirm, confirm))
-}
-
-func (c *channel) Reject(reason RejectionReason, message string) os.Error {
-	c.serverConn.lock.Lock()
-	defer c.serverConn.lock.Unlock()
-
-	if c.serverConn.err != nil {
-		return c.serverConn.err
-	}
-
-	reject := channelOpenFailureMsg{
-		PeersId:  c.theirId,
-		Reason:   uint32(reason),
-		Message:  message,
-		Language: "en",
-	}
-	return c.serverConn.writePacket(marshal(msgChannelOpenFailure, reject))
-}
-
-func (c *channel) handlePacket(packet interface{}) {
-	c.lock.Lock()
-	defer c.lock.Unlock()
-
-	switch packet := packet.(type) {
-	case *channelRequestMsg:
-		req := ChannelRequest{
-			Request:   packet.Request,
-			WantReply: packet.WantReply,
-			Payload:   packet.RequestSpecificData,
-		}
-
-		c.pendingRequests = append(c.pendingRequests, req)
-		c.cond.Signal()
-	case *channelCloseMsg:
-		c.theyClosed = true
-		c.cond.Signal()
-	case *channelEOFMsg:
-		c.theySentEOF = true
-		c.cond.Signal()
-	default:
-		panic("unknown packet type")
-	}
-}
-
-func (c *channel) handleData(data []byte) {
-	c.lock.Lock()
-	defer c.lock.Unlock()
-
-	// The other side should never send us more than our window.
-	if len(data)+c.length > len(c.pendingData) {
-		// TODO(agl): we should tear down the channel with a protocol
-		// error.
-		return
-	}
-
-	c.myWindow -= uint32(len(data))
-	for i := 0; i < 2; i++ {
-		tail := c.head + c.length
-		if tail > len(c.pendingData) {
-			tail -= len(c.pendingData)
-		}
-		n := copy(c.pendingData[tail:], data)
-		data = data[n:]
-		c.length += n
-	}
-
-	c.cond.Signal()
-}
-
-func (c *channel) Read(data []byte) (n int, err os.Error) {
-	c.lock.Lock()
-	defer c.lock.Unlock()
-
-	if c.err != nil {
-		return 0, c.err
-	}
-
-	if c.myWindow <= uint32(len(c.pendingData))/2 {
-		packet := marshal(msgChannelWindowAdjust, windowAdjustMsg{
-			PeersId:         c.theirId,
-			AdditionalBytes: uint32(len(c.pendingData)) - c.myWindow,
-		})
-		if err := c.serverConn.writePacket(packet); err != nil {
-			return 0, err
-		}
-	}
-
-	for {
-		if c.theySentEOF || c.theyClosed || c.dead {
-			return 0, os.EOF
-		}
-
-		if len(c.pendingRequests) > 0 {
-			req := c.pendingRequests[0]
-			if len(c.pendingRequests) == 1 {
-				c.pendingRequests = nil
-			} else {
-				oldPendingRequests := c.pendingRequests
-				c.pendingRequests = make([]ChannelRequest, len(oldPendingRequests)-1)
-				copy(c.pendingRequests, oldPendingRequests[1:])
-			}
-
-			return 0, req
-		}
-
-		if c.length > 0 {
-			tail := c.head + c.length
-			if tail > len(c.pendingData) {
-				tail -= len(c.pendingData)
-			}
-			n = copy(data, c.pendingData[c.head:tail])
-			c.head += n
-			c.length -= n
-			if c.head == len(c.pendingData) {
-				c.head = 0
-			}
-			return
-		}
-
-		c.cond.Wait()
-	}
-
-	panic("unreachable")
-}
-
-func (c *channel) Write(data []byte) (n int, err os.Error) {
-	for len(data) > 0 {
-		c.lock.Lock()
-		if c.dead || c.weClosed {
-			return 0, os.EOF
-		}
-
-		if c.theirWindow == 0 {
-			c.cond.Wait()
-			continue
-		}
-		c.lock.Unlock()
-
-		todo := data
-		if uint32(len(todo)) > c.theirWindow {
-			todo = todo[:c.theirWindow]
-		}
-
-		packet := make([]byte, 1+4+4+len(todo))
-		packet[0] = msgChannelData
-		packet[1] = byte(c.theirId) >> 24
-		packet[2] = byte(c.theirId) >> 16
-		packet[3] = byte(c.theirId) >> 8
-		packet[4] = byte(c.theirId)
-		packet[5] = byte(len(todo)) >> 24
-		packet[6] = byte(len(todo)) >> 16
-		packet[7] = byte(len(todo)) >> 8
-		packet[8] = byte(len(todo))
-		copy(packet[9:], todo)
-
-		c.serverConn.lock.Lock()
-		if err = c.serverConn.writePacket(packet); err != nil {
-			c.serverConn.lock.Unlock()
-			return
-		}
-		c.serverConn.lock.Unlock()
-
-		n += len(todo)
-		data = data[len(todo):]
-	}
-
-	return
-}
-
-func (c *channel) Close() os.Error {
-	c.serverConn.lock.Lock()
-	defer c.serverConn.lock.Unlock()
-
-	if c.serverConn.err != nil {
-		return c.serverConn.err
-	}
-
-	if c.weClosed {
-		return os.NewError("ssh: channel already closed")
-	}
-	c.weClosed = true
-
-	closeMsg := channelCloseMsg{
-		PeersId: c.theirId,
-	}
-	return c.serverConn.writePacket(marshal(msgChannelClose, closeMsg))
-}
-
-func (c *channel) AckRequest(ok bool) os.Error {
-	c.serverConn.lock.Lock()
-	defer c.serverConn.lock.Unlock()
-
-	if c.serverConn.err != nil {
-		return c.serverConn.err
-	}
-
-	if ok {
-		ack := channelRequestSuccessMsg{
-			PeersId: c.theirId,
-		}
-		return c.serverConn.writePacket(marshal(msgChannelSuccess, ack))
-	} else {
-		ack := channelRequestFailureMsg{
-			PeersId: c.theirId,
-		}
-		return c.serverConn.writePacket(marshal(msgChannelFailure, ack))
-	}
-	panic("unreachable")
-}
-
-func (c *channel) ChannelType() string {
-	return c.chanType
-}
-
-func (c *channel) ExtraData() []byte {
-	return c.extraData
-}
diff --git a/src/pkg/exp/ssh/common.go b/src/pkg/exp/ssh/common.go
deleted file mode 100644
index 698db60..0000000
--- a/src/pkg/exp/ssh/common.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"strconv"
-)
-
-// These are string constants in the SSH protocol.
-const (
-	kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
-	hostAlgoRSA     = "ssh-rsa"
-	cipherAES128CTR = "aes128-ctr"
-	macSHA196       = "hmac-sha1-96"
-	compressionNone = "none"
-	serviceUserAuth = "ssh-userauth"
-	serviceSSH      = "ssh-connection"
-)
-
-// UnexpectedMessageError results when the SSH message that we received didn't
-// match what we wanted.
-type UnexpectedMessageError struct {
-	expected, got uint8
-}
-
-func (u UnexpectedMessageError) String() string {
-	return "ssh: unexpected message type " + strconv.Itoa(int(u.got)) + " (expected " + strconv.Itoa(int(u.expected)) + ")"
-}
-
-// ParseError results from a malformed SSH message.
-type ParseError struct {
-	msgType uint8
-}
-
-func (p ParseError) String() string {
-	return "ssh: parse error in message type " + strconv.Itoa(int(p.msgType))
-}
-
-func findCommonAlgorithm(clientAlgos []string, serverAlgos []string) (commonAlgo string, ok bool) {
-	for _, clientAlgo := range clientAlgos {
-		for _, serverAlgo := range serverAlgos {
-			if clientAlgo == serverAlgo {
-				return clientAlgo, true
-			}
-		}
-	}
-
-	return
-}
-
-func findAgreedAlgorithms(clientToServer, serverToClient *transport, clientKexInit, serverKexInit *kexInitMsg) (kexAlgo, hostKeyAlgo string, ok bool) {
-	kexAlgo, ok = findCommonAlgorithm(clientKexInit.KexAlgos, serverKexInit.KexAlgos)
-	if !ok {
-		return
-	}
-
-	hostKeyAlgo, ok = findCommonAlgorithm(clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
-	if !ok {
-		return
-	}
-
-	clientToServer.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
-	if !ok {
-		return
-	}
-
-	serverToClient.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
-	if !ok {
-		return
-	}
-
-	clientToServer.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
-	if !ok {
-		return
-	}
-
-	serverToClient.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
-	if !ok {
-		return
-	}
-
-	clientToServer.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
-	if !ok {
-		return
-	}
-
-	serverToClient.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
-	if !ok {
-		return
-	}
-
-	ok = true
-	return
-}
diff --git a/src/pkg/exp/ssh/doc.go b/src/pkg/exp/ssh/doc.go
deleted file mode 100644
index 54a7ba9..0000000
--- a/src/pkg/exp/ssh/doc.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2011 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 ssh implements an SSH server.
-
-SSH is a transport security protocol, an authentication protocol and a
-family of application protocols. The most typical application level
-protocol is a remote shell and this is specifically implemented.  However,
-the multiplexed nature of SSH is exposed to users that wish to support
-others.
-
-An SSH server is represented by a Server, which manages a number of
-ServerConnections and handles authentication.
-
-	var s Server
-	s.PubKeyCallback = pubKeyAuth
-	s.PasswordCallback = passwordAuth
-
-	pemBytes, err := ioutil.ReadFile("id_rsa")
-	if err != nil {
-		panic("Failed to load private key")
-	}
-	err = s.SetRSAPrivateKey(pemBytes)
-	if err != nil {
-		panic("Failed to parse private key")
-	}
-
-Once a Server has been set up, connections can be attached.
-
-	var sConn ServerConnection
-	sConn.Server = &s
-	err = sConn.Handshake(conn)
-	if err != nil {
-		panic("failed to handshake")
-	}
-
-An SSH connection multiplexes several channels, which must be accepted themselves:
-
-
-	for {
-		channel, err := sConn.Accept()
-		if err != nil {
-			panic("error from Accept")
-		}
-
-		...
-	}
-
-Accept reads from the connection, demultiplexes packets to their corresponding
-channels and returns when a new channel request is seen. Some goroutine must
-always be calling Accept; otherwise no messages will be forwarded to the
-channels.
-
-Channels have a type, depending on the application level protocol intended. In
-the case of a shell, the type is "session" and ServerShell may be used to
-present a simple terminal interface.
-
-	if channel.ChannelType() != "session" {
-		c.Reject(UnknownChannelType, "unknown channel type")
-		return
-	}
-	channel.Accept()
-
-	shell := NewServerShell(channel, "> ")
-	go func() {
-		defer channel.Close()
-		for {
-			line, err := shell.ReadLine()
-			if err != nil {
-				break
-			}
-			println(line)
-		}
-		return
-	}()
-*/
-package ssh
diff --git a/src/pkg/exp/ssh/messages.go b/src/pkg/exp/ssh/messages.go
deleted file mode 100644
index d375eaf..0000000
--- a/src/pkg/exp/ssh/messages.go
+++ /dev/null
@@ -1,557 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"big"
-	"bytes"
-	"io"
-	"os"
-	"reflect"
-)
-
-// These are SSH message type numbers. They are scattered around several
-// documents but many were taken from
-// http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
-const (
-	msgDisconnect     = 1
-	msgIgnore         = 2
-	msgUnimplemented  = 3
-	msgDebug          = 4
-	msgServiceRequest = 5
-	msgServiceAccept  = 6
-
-	msgKexInit = 20
-	msgNewKeys = 21
-
-	msgKexDHInit  = 30
-	msgKexDHReply = 31
-
-	msgUserAuthRequest  = 50
-	msgUserAuthFailure  = 51
-	msgUserAuthSuccess  = 52
-	msgUserAuthBanner   = 53
-	msgUserAuthPubKeyOk = 60
-
-	msgGlobalRequest  = 80
-	msgRequestSuccess = 81
-	msgRequestFailure = 82
-
-	msgChannelOpen         = 90
-	msgChannelOpenConfirm  = 91
-	msgChannelOpenFailure  = 92
-	msgChannelWindowAdjust = 93
-	msgChannelData         = 94
-	msgChannelExtendedData = 95
-	msgChannelEOF          = 96
-	msgChannelClose        = 97
-	msgChannelRequest      = 98
-	msgChannelSuccess      = 99
-	msgChannelFailure      = 100
-)
-
-// SSH messages:
-//
-// These structures mirror the wire format of the corresponding SSH messages.
-// They are marshaled using reflection with the marshal and unmarshal functions
-// in this file. The only wrinkle is that a final member of type []byte with a
-// tag of "rest" receives the remainder of a packet when unmarshaling.
-
-// See RFC 4253, section 7.1.
-type kexInitMsg struct {
-	Cookie                  [16]byte
-	KexAlgos                []string
-	ServerHostKeyAlgos      []string
-	CiphersClientServer     []string
-	CiphersServerClient     []string
-	MACsClientServer        []string
-	MACsServerClient        []string
-	CompressionClientServer []string
-	CompressionServerClient []string
-	LanguagesClientServer   []string
-	LanguagesServerClient   []string
-	FirstKexFollows         bool
-	Reserved                uint32
-}
-
-// See RFC 4253, section 8.
-type kexDHInitMsg struct {
-	X *big.Int
-}
-
-type kexDHReplyMsg struct {
-	HostKey   []byte
-	Y         *big.Int
-	Signature []byte
-}
-
-// See RFC 4253, section 10.
-type serviceRequestMsg struct {
-	Service string
-}
-
-// See RFC 4253, section 10.
-type serviceAcceptMsg struct {
-	Service string
-}
-
-// See RFC 4252, section 5.
-type userAuthRequestMsg struct {
-	User    string
-	Service string
-	Method  string
-	Payload []byte "rest"
-}
-
-// See RFC 4252, section 5.1
-type userAuthFailureMsg struct {
-	Methods        []string
-	PartialSuccess bool
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenMsg struct {
-	ChanType         string
-	PeersId          uint32
-	PeersWindow      uint32
-	MaxPacketSize    uint32
-	TypeSpecificData []byte "rest"
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenConfirmMsg struct {
-	PeersId          uint32
-	MyId             uint32
-	MyWindow         uint32
-	MaxPacketSize    uint32
-	TypeSpecificData []byte "rest"
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenFailureMsg struct {
-	PeersId  uint32
-	Reason   uint32
-	Message  string
-	Language string
-}
-
-type channelRequestMsg struct {
-	PeersId             uint32
-	Request             string
-	WantReply           bool
-	RequestSpecificData []byte "rest"
-}
-
-// See RFC 4254, section 5.4.
-type channelRequestSuccessMsg struct {
-	PeersId uint32
-}
-
-// See RFC 4254, section 5.4.
-type channelRequestFailureMsg struct {
-	PeersId uint32
-}
-
-// See RFC 4254, section 5.3
-type channelCloseMsg struct {
-	PeersId uint32
-}
-
-// See RFC 4254, section 5.3
-type channelEOFMsg struct {
-	PeersId uint32
-}
-
-// See RFC 4254, section 4
-type globalRequestMsg struct {
-	Type      string
-	WantReply bool
-}
-
-// See RFC 4254, section 5.2
-type windowAdjustMsg struct {
-	PeersId         uint32
-	AdditionalBytes uint32
-}
-
-// See RFC 4252, section 7
-type userAuthPubKeyOkMsg struct {
-	Algo   string
-	PubKey string
-}
-
-// unmarshal parses the SSH wire data in packet into out using reflection.
-// expectedType is the expected SSH message type. It either returns nil on
-// success, or a ParseError or UnexpectedMessageError on error.
-func unmarshal(out interface{}, packet []byte, expectedType uint8) os.Error {
-	if len(packet) == 0 {
-		return ParseError{expectedType}
-	}
-	if packet[0] != expectedType {
-		return UnexpectedMessageError{expectedType, packet[0]}
-	}
-	packet = packet[1:]
-
-	v := reflect.ValueOf(out).Elem()
-	structType := v.Type()
-	var ok bool
-	for i := 0; i < v.NumField(); i++ {
-		field := v.Field(i)
-		t := field.Type()
-		switch t.Kind() {
-		case reflect.Bool:
-			if len(packet) < 1 {
-				return ParseError{expectedType}
-			}
-			field.SetBool(packet[0] != 0)
-			packet = packet[1:]
-		case reflect.Array:
-			if t.Elem().Kind() != reflect.Uint8 {
-				panic("array of non-uint8")
-			}
-			if len(packet) < t.Len() {
-				return ParseError{expectedType}
-			}
-			for j := 0; j < t.Len(); j++ {
-				field.Index(j).Set(reflect.ValueOf(packet[j]))
-			}
-			packet = packet[t.Len():]
-		case reflect.Uint32:
-			var u32 uint32
-			if u32, packet, ok = parseUint32(packet); !ok {
-				return ParseError{expectedType}
-			}
-			field.SetUint(uint64(u32))
-		case reflect.String:
-			var s []byte
-			if s, packet, ok = parseString(packet); !ok {
-				return ParseError{expectedType}
-			}
-			field.SetString(string(s))
-		case reflect.Slice:
-			switch t.Elem().Kind() {
-			case reflect.Uint8:
-				if structType.Field(i).Tag == "rest" {
-					field.Set(reflect.ValueOf(packet))
-					packet = nil
-				} else {
-					var s []byte
-					if s, packet, ok = parseString(packet); !ok {
-						return ParseError{expectedType}
-					}
-					field.Set(reflect.ValueOf(s))
-				}
-			case reflect.String:
-				var nl []string
-				if nl, packet, ok = parseNameList(packet); !ok {
-					return ParseError{expectedType}
-				}
-				field.Set(reflect.ValueOf(nl))
-			default:
-				panic("slice of unknown type")
-			}
-		case reflect.Ptr:
-			if t == bigIntType {
-				var n *big.Int
-				if n, packet, ok = parseInt(packet); !ok {
-					return ParseError{expectedType}
-				}
-				field.Set(reflect.ValueOf(n))
-			} else {
-				panic("pointer to unknown type")
-			}
-		default:
-			panic("unknown type")
-		}
-	}
-
-	if len(packet) != 0 {
-		return ParseError{expectedType}
-	}
-
-	return nil
-}
-
-// marshal serializes the message in msg, using the given message type.
-func marshal(msgType uint8, msg interface{}) []byte {
-	var out []byte
-	out = append(out, msgType)
-
-	v := reflect.ValueOf(msg)
-	structType := v.Type()
-	for i := 0; i < v.NumField(); i++ {
-		field := v.Field(i)
-		t := field.Type()
-		switch t.Kind() {
-		case reflect.Bool:
-			var v uint8
-			if field.Bool() {
-				v = 1
-			}
-			out = append(out, v)
-		case reflect.Array:
-			if t.Elem().Kind() != reflect.Uint8 {
-				panic("array of non-uint8")
-			}
-			for j := 0; j < t.Len(); j++ {
-				out = append(out, byte(field.Index(j).Uint()))
-			}
-		case reflect.Uint32:
-			u32 := uint32(field.Uint())
-			out = append(out, byte(u32>>24))
-			out = append(out, byte(u32>>16))
-			out = append(out, byte(u32>>8))
-			out = append(out, byte(u32))
-		case reflect.String:
-			s := field.String()
-			out = append(out, byte(len(s)>>24))
-			out = append(out, byte(len(s)>>16))
-			out = append(out, byte(len(s)>>8))
-			out = append(out, byte(len(s)))
-			out = append(out, []byte(s)...)
-		case reflect.Slice:
-			switch t.Elem().Kind() {
-			case reflect.Uint8:
-				length := field.Len()
-				if structType.Field(i).Tag != "rest" {
-					out = append(out, byte(length>>24))
-					out = append(out, byte(length>>16))
-					out = append(out, byte(length>>8))
-					out = append(out, byte(length))
-				}
-				for j := 0; j < length; j++ {
-					out = append(out, byte(field.Index(j).Uint()))
-				}
-			case reflect.String:
-				var length int
-				for j := 0; j < field.Len(); j++ {
-					if j != 0 {
-						length++ /* comma */
-					}
-					length += len(field.Index(j).String())
-				}
-
-				out = append(out, byte(length>>24))
-				out = append(out, byte(length>>16))
-				out = append(out, byte(length>>8))
-				out = append(out, byte(length))
-				for j := 0; j < field.Len(); j++ {
-					if j != 0 {
-						out = append(out, ',')
-					}
-					out = append(out, []byte(field.Index(j).String())...)
-				}
-			default:
-				panic("slice of unknown type")
-			}
-		case reflect.Ptr:
-			if t == bigIntType {
-				var n *big.Int
-				nValue := reflect.ValueOf(&n)
-				nValue.Elem().Set(field)
-				needed := intLength(n)
-				oldLength := len(out)
-
-				if cap(out)-len(out) < needed {
-					newOut := make([]byte, len(out), 2*(len(out)+needed))
-					copy(newOut, out)
-					out = newOut
-				}
-				out = out[:oldLength+needed]
-				marshalInt(out[oldLength:], n)
-			} else {
-				panic("pointer to unknown type")
-			}
-		}
-	}
-
-	return out
-}
-
-var bigOne = big.NewInt(1)
-
-func parseString(in []byte) (out, rest []byte, ok bool) {
-	if len(in) < 4 {
-		return
-	}
-	length := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
-	if uint32(len(in)) < 4+length {
-		return
-	}
-	out = in[4 : 4+length]
-	rest = in[4+length:]
-	ok = true
-	return
-}
-
-var comma = []byte{','}
-
-func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
-	contents, rest, ok := parseString(in)
-	if !ok {
-		return
-	}
-	if len(contents) == 0 {
-		return
-	}
-	parts := bytes.Split(contents, comma)
-	out = make([]string, len(parts))
-	for i, part := range parts {
-		out[i] = string(part)
-	}
-	return
-}
-
-func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
-	contents, rest, ok := parseString(in)
-	if !ok {
-		return
-	}
-	out = new(big.Int)
-
-	if len(contents) > 0 && contents[0]&0x80 == 0x80 {
-		// This is a negative number
-		notBytes := make([]byte, len(contents))
-		for i := range notBytes {
-			notBytes[i] = ^contents[i]
-		}
-		out.SetBytes(notBytes)
-		out.Add(out, bigOne)
-		out.Neg(out)
-	} else {
-		// Positive number
-		out.SetBytes(contents)
-	}
-	ok = true
-	return
-}
-
-func parseUint32(in []byte) (out uint32, rest []byte, ok bool) {
-	if len(in) < 4 {
-		return
-	}
-	out = uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
-	rest = in[4:]
-	ok = true
-	return
-}
-
-const maxPacketSize = 36000
-
-func nameListLength(namelist []string) int {
-	length := 4 /* uint32 length prefix */
-	for i, name := range namelist {
-		if i != 0 {
-			length++ /* comma */
-		}
-		length += len(name)
-	}
-	return length
-}
-
-func intLength(n *big.Int) int {
-	length := 4 /* length bytes */
-	if n.Sign() < 0 {
-		nMinus1 := new(big.Int).Neg(n)
-		nMinus1.Sub(nMinus1, bigOne)
-		bitLen := nMinus1.BitLen()
-		if bitLen%8 == 0 {
-			// The number will need 0xff padding
-			length++
-		}
-		length += (bitLen + 7) / 8
-	} else if n.Sign() == 0 {
-		// A zero is the zero length string
-	} else {
-		bitLen := n.BitLen()
-		if bitLen%8 == 0 {
-			// The number will need 0x00 padding
-			length++
-		}
-		length += (bitLen + 7) / 8
-	}
-
-	return length
-}
-
-func marshalInt(to []byte, n *big.Int) []byte {
-	lengthBytes := to
-	to = to[4:]
-	length := 0
-
-	if n.Sign() < 0 {
-		// A negative number has to be converted to two's-complement
-		// form. So we'll subtract 1 and invert. If the
-		// most-significant-bit isn't set then we'll need to pad the
-		// beginning with 0xff in order to keep the number negative.
-		nMinus1 := new(big.Int).Neg(n)
-		nMinus1.Sub(nMinus1, bigOne)
-		bytes := nMinus1.Bytes()
-		for i := range bytes {
-			bytes[i] ^= 0xff
-		}
-		if len(bytes) == 0 || bytes[0]&0x80 == 0 {
-			to[0] = 0xff
-			to = to[1:]
-			length++
-		}
-		nBytes := copy(to, bytes)
-		to = to[nBytes:]
-		length += nBytes
-	} else if n.Sign() == 0 {
-		// A zero is the zero length string
-	} else {
-		bytes := n.Bytes()
-		if len(bytes) > 0 && bytes[0]&0x80 != 0 {
-			// We'll have to pad this with a 0x00 in order to
-			// stop it looking like a negative number.
-			to[0] = 0
-			to = to[1:]
-			length++
-		}
-		nBytes := copy(to, bytes)
-		to = to[nBytes:]
-		length += nBytes
-	}
-
-	lengthBytes[0] = byte(length >> 24)
-	lengthBytes[1] = byte(length >> 16)
-	lengthBytes[2] = byte(length >> 8)
-	lengthBytes[3] = byte(length)
-	return to
-}
-
-func writeInt(w io.Writer, n *big.Int) {
-	length := intLength(n)
-	buf := make([]byte, length)
-	marshalInt(buf, n)
-	w.Write(buf)
-}
-
-func writeString(w io.Writer, s []byte) {
-	var lengthBytes [4]byte
-	lengthBytes[0] = byte(len(s) >> 24)
-	lengthBytes[1] = byte(len(s) >> 16)
-	lengthBytes[2] = byte(len(s) >> 8)
-	lengthBytes[3] = byte(len(s))
-	w.Write(lengthBytes[:])
-	w.Write(s)
-}
-
-func stringLength(s []byte) int {
-	return 4 + len(s)
-}
-
-func marshalString(to []byte, s []byte) []byte {
-	to[0] = byte(len(s) >> 24)
-	to[1] = byte(len(s) >> 16)
-	to[2] = byte(len(s) >> 8)
-	to[3] = byte(len(s))
-	to = to[4:]
-	copy(to, s)
-	return to[len(s):]
-}
-
-var bigIntType = reflect.TypeOf((*big.Int)(nil))
diff --git a/src/pkg/exp/ssh/messages_test.go b/src/pkg/exp/ssh/messages_test.go
deleted file mode 100644
index 629f3d3..0000000
--- a/src/pkg/exp/ssh/messages_test.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"big"
-	"rand"
-	"reflect"
-	"testing"
-	"testing/quick"
-)
-
-var intLengthTests = []struct {
-	val, length int
-}{
-	{0, 4 + 0},
-	{1, 4 + 1},
-	{127, 4 + 1},
-	{128, 4 + 2},
-	{-1, 4 + 1},
-}
-
-func TestIntLength(t *testing.T) {
-	for _, test := range intLengthTests {
-		v := new(big.Int).SetInt64(int64(test.val))
-		length := intLength(v)
-		if length != test.length {
-			t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
-		}
-	}
-}
-
-var messageTypes = []interface{}{
-	&kexInitMsg{},
-	&kexDHInitMsg{},
-	&serviceRequestMsg{},
-	&serviceAcceptMsg{},
-	&userAuthRequestMsg{},
-	&channelOpenMsg{},
-	&channelOpenConfirmMsg{},
-	&channelRequestMsg{},
-	&channelRequestSuccessMsg{},
-}
-
-func TestMarshalUnmarshal(t *testing.T) {
-	rand := rand.New(rand.NewSource(0))
-	for i, iface := range messageTypes {
-		ty := reflect.ValueOf(iface).Type()
-
-		n := 100
-		if testing.Short() {
-			n = 5
-		}
-		for j := 0; j < n; j++ {
-			v, ok := quick.Value(ty, rand)
-			if !ok {
-				t.Errorf("#%d: failed to create value", i)
-				break
-			}
-
-			m1 := v.Elem().Interface()
-			m2 := iface
-
-			marshaled := marshal(msgIgnore, m1)
-			if err := unmarshal(m2, marshaled, msgIgnore); err != nil {
-				t.Errorf("#%d failed to unmarshal %#v: %s", i, m1, err)
-				break
-			}
-
-			if !reflect.DeepEqual(v.Interface(), m2) {
-				t.Errorf("#%d\ngot: %#v\nwant:%#v\n%x", i, m2, m1, marshaled)
-				break
-			}
-		}
-	}
-}
-
-func randomBytes(out []byte, rand *rand.Rand) {
-	for i := 0; i < len(out); i++ {
-		out[i] = byte(rand.Int31())
-	}
-}
-
-func randomNameList(rand *rand.Rand) []string {
-	ret := make([]string, rand.Int31()&15)
-	for i := range ret {
-		s := make([]byte, 1+(rand.Int31()&15))
-		for j := range s {
-			s[j] = 'a' + uint8(rand.Int31()&15)
-		}
-		ret[i] = string(s)
-	}
-	return ret
-}
-
-func randomInt(rand *rand.Rand) *big.Int {
-	return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
-}
-
-func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
-	ki := &kexInitMsg{}
-	randomBytes(ki.Cookie[:], rand)
-	ki.KexAlgos = randomNameList(rand)
-	ki.ServerHostKeyAlgos = randomNameList(rand)
-	ki.CiphersClientServer = randomNameList(rand)
-	ki.CiphersServerClient = randomNameList(rand)
-	ki.MACsClientServer = randomNameList(rand)
-	ki.MACsServerClient = randomNameList(rand)
-	ki.CompressionClientServer = randomNameList(rand)
-	ki.CompressionServerClient = randomNameList(rand)
-	ki.LanguagesClientServer = randomNameList(rand)
-	ki.LanguagesServerClient = randomNameList(rand)
-	if rand.Int31()&1 == 1 {
-		ki.FirstKexFollows = true
-	}
-	return reflect.ValueOf(ki)
-}
-
-func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
-	dhi := &kexDHInitMsg{}
-	dhi.X = randomInt(rand)
-	return reflect.ValueOf(dhi)
-}
diff --git a/src/pkg/exp/ssh/server.go b/src/pkg/exp/ssh/server.go
deleted file mode 100644
index bc0af13..0000000
--- a/src/pkg/exp/ssh/server.go
+++ /dev/null
@@ -1,714 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"big"
-	"bufio"
-	"bytes"
-	"crypto"
-	"crypto/rand"
-	"crypto/rsa"
-	_ "crypto/sha1"
-	"crypto/x509"
-	"encoding/pem"
-	"net"
-	"os"
-	"sync"
-)
-
-var supportedKexAlgos = []string{kexAlgoDH14SHA1}
-var supportedHostKeyAlgos = []string{hostAlgoRSA}
-var supportedCiphers = []string{cipherAES128CTR}
-var supportedMACs = []string{macSHA196}
-var supportedCompressions = []string{compressionNone}
-
-// Server represents an SSH server. A Server may have several ServerConnections.
-type Server struct {
-	rsa           *rsa.PrivateKey
-	rsaSerialized []byte
-
-	// NoClientAuth is true if clients are allowed to connect without
-	// authenticating.
-	NoClientAuth bool
-
-	// PasswordCallback, if non-nil, is called when a user attempts to
-	// authenticate using a password. It may be called concurrently from
-	// several goroutines.
-	PasswordCallback func(user, password string) bool
-
-	// PubKeyCallback, if non-nil, is called when a client attempts public
-	// key authentication. It must return true iff the given public key is
-	// valid for the given user.
-	PubKeyCallback func(user, algo string, pubkey []byte) bool
-}
-
-// SetRSAPrivateKey sets the private key for a Server. A Server must have a
-// private key configured in order to accept connections. The private key must
-// be in the form of a PEM encoded, PKCS#1, RSA private key. The file "id_rsa"
-// typically contains such a key.
-func (s *Server) SetRSAPrivateKey(pemBytes []byte) os.Error {
-	block, _ := pem.Decode(pemBytes)
-	if block == nil {
-		return os.NewError("ssh: no key found")
-	}
-	var err os.Error
-	s.rsa, err = x509.ParsePKCS1PrivateKey(block.Bytes)
-	if err != nil {
-		return err
-	}
-
-	s.rsaSerialized = marshalRSA(s.rsa)
-	return nil
-}
-
-// marshalRSA serializes an RSA private key according to RFC 4256, section 6.6.
-func marshalRSA(priv *rsa.PrivateKey) []byte {
-	e := new(big.Int).SetInt64(int64(priv.E))
-	length := stringLength([]byte(hostAlgoRSA))
-	length += intLength(e)
-	length += intLength(priv.N)
-
-	ret := make([]byte, length)
-	r := marshalString(ret, []byte(hostAlgoRSA))
-	r = marshalInt(r, e)
-	r = marshalInt(r, priv.N)
-
-	return ret
-}
-
-// parseRSA parses an RSA key according to RFC 4256, section 6.6.
-func parseRSA(in []byte) (pubKey *rsa.PublicKey, ok bool) {
-	algo, in, ok := parseString(in)
-	if !ok || string(algo) != hostAlgoRSA {
-		return nil, false
-	}
-	bigE, in, ok := parseInt(in)
-	if !ok || bigE.BitLen() > 24 {
-		return nil, false
-	}
-	e := bigE.Int64()
-	if e < 3 || e&1 == 0 {
-		return nil, false
-	}
-	N, in, ok := parseInt(in)
-	if !ok || len(in) > 0 {
-		return nil, false
-	}
-	return &rsa.PublicKey{
-		N: N,
-		E: int(e),
-	}, true
-}
-
-func parseRSASig(in []byte) (sig []byte, ok bool) {
-	algo, in, ok := parseString(in)
-	if !ok || string(algo) != hostAlgoRSA {
-		return nil, false
-	}
-	sig, in, ok = parseString(in)
-	if len(in) > 0 {
-		ok = false
-	}
-	return
-}
-
-// cachedPubKey contains the results of querying whether a public key is
-// acceptable for a user. The cache only applies to a single ServerConnection.
-type cachedPubKey struct {
-	user, algo string
-	pubKey     []byte
-	result     bool
-}
-
-const maxCachedPubKeys = 16
-
-// ServerConnection represents an incomming connection to a Server.
-type ServerConnection struct {
-	Server *Server
-
-	*transport
-
-	channels   map[uint32]*channel
-	nextChanId uint32
-
-	// lock protects err and also allows Channels to serialise their writes
-	// to out.
-	lock sync.RWMutex
-	err  os.Error
-
-	// cachedPubKeys contains the cache results of tests for public keys.
-	// Since SSH clients will query whether a public key is acceptable
-	// before attempting to authenticate with it, we end up with duplicate
-	// queries for public key validity.
-	cachedPubKeys []cachedPubKey
-}
-
-// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
-type dhGroup struct {
-	g, p *big.Int
-}
-
-// dhGroup14 is the group called diffie-hellman-group14-sha1 in RFC 4253 and
-// Oakley Group 14 in RFC 3526.
-var dhGroup14 *dhGroup
-
-var dhGroup14Once sync.Once
-
-func initDHGroup14() {
-	p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
-
-	dhGroup14 = &dhGroup{
-		g: new(big.Int).SetInt64(2),
-		p: p,
-	}
-}
-
-type handshakeMagics struct {
-	clientVersion, serverVersion []byte
-	clientKexInit, serverKexInit []byte
-}
-
-// kexDH performs Diffie-Hellman key agreement on a ServerConnection. The
-// returned values are given the same names as in RFC 4253, section 8.
-func (s *ServerConnection) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handshakeMagics, hostKeyAlgo string) (H, K []byte, err os.Error) {
-	packet, err := s.readPacket()
-	if err != nil {
-		return
-	}
-	var kexDHInit kexDHInitMsg
-	if err = unmarshal(&kexDHInit, packet, msgKexDHInit); err != nil {
-		return
-	}
-
-	if kexDHInit.X.Sign() == 0 || kexDHInit.X.Cmp(group.p) >= 0 {
-		return nil, nil, os.NewError("client DH parameter out of bounds")
-	}
-
-	y, err := rand.Int(rand.Reader, group.p)
-	if err != nil {
-		return
-	}
-
-	Y := new(big.Int).Exp(group.g, y, group.p)
-	kInt := new(big.Int).Exp(kexDHInit.X, y, group.p)
-
-	var serializedHostKey []byte
-	switch hostKeyAlgo {
-	case hostAlgoRSA:
-		serializedHostKey = s.Server.rsaSerialized
-	default:
-		return nil, nil, os.NewError("internal error")
-	}
-
-	h := hashFunc.New()
-	writeString(h, magics.clientVersion)
-	writeString(h, magics.serverVersion)
-	writeString(h, magics.clientKexInit)
-	writeString(h, magics.serverKexInit)
-	writeString(h, serializedHostKey)
-	writeInt(h, kexDHInit.X)
-	writeInt(h, Y)
-	K = make([]byte, intLength(kInt))
-	marshalInt(K, kInt)
-	h.Write(K)
-
-	H = h.Sum()
-
-	h.Reset()
-	h.Write(H)
-	hh := h.Sum()
-
-	var sig []byte
-	switch hostKeyAlgo {
-	case hostAlgoRSA:
-		sig, err = rsa.SignPKCS1v15(rand.Reader, s.Server.rsa, hashFunc, hh)
-		if err != nil {
-			return
-		}
-	default:
-		return nil, nil, os.NewError("internal error")
-	}
-
-	serializedSig := serializeRSASignature(sig)
-
-	kexDHReply := kexDHReplyMsg{
-		HostKey:   serializedHostKey,
-		Y:         Y,
-		Signature: serializedSig,
-	}
-	packet = marshal(msgKexDHReply, kexDHReply)
-
-	err = s.writePacket(packet)
-	return
-}
-
-func serializeRSASignature(sig []byte) []byte {
-	length := stringLength([]byte(hostAlgoRSA))
-	length += stringLength(sig)
-
-	ret := make([]byte, length)
-	r := marshalString(ret, []byte(hostAlgoRSA))
-	r = marshalString(r, sig)
-
-	return ret
-}
-
-// serverVersion is the fixed identification string that Server will use.
-var serverVersion = []byte("SSH-2.0-Go\r\n")
-
-// buildDataSignedForAuth returns the data that is signed in order to prove
-// posession of a private key. See RFC 4252, section 7.
-func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
-	user := []byte(req.User)
-	service := []byte(req.Service)
-	method := []byte(req.Method)
-
-	length := stringLength(sessionId)
-	length += 1
-	length += stringLength(user)
-	length += stringLength(service)
-	length += stringLength(method)
-	length += 1
-	length += stringLength(algo)
-	length += stringLength(pubKey)
-
-	ret := make([]byte, length)
-	r := marshalString(ret, sessionId)
-	r[0] = msgUserAuthRequest
-	r = r[1:]
-	r = marshalString(r, user)
-	r = marshalString(r, service)
-	r = marshalString(r, method)
-	r[0] = 1
-	r = r[1:]
-	r = marshalString(r, algo)
-	r = marshalString(r, pubKey)
-	return ret
-}
-
-// Handshake performs an SSH transport and client authentication on the given ServerConnection.
-func (s *ServerConnection) Handshake(conn net.Conn) os.Error {
-	var magics handshakeMagics
-	s.transport = &transport{
-		reader: reader{
-			Reader: bufio.NewReader(conn),
-		},
-		writer: writer{
-			Writer: bufio.NewWriter(conn),
-			rand:   rand.Reader,
-		},
-		Close: func() os.Error {
-			return conn.Close()
-		},
-	}
-
-	if _, err := conn.Write(serverVersion); err != nil {
-		return err
-	}
-	magics.serverVersion = serverVersion[:len(serverVersion)-2]
-
-	version, ok := readVersion(s.transport)
-	if !ok {
-		return os.NewError("failed to read version string from client")
-	}
-	magics.clientVersion = version
-
-	serverKexInit := kexInitMsg{
-		KexAlgos:                supportedKexAlgos,
-		ServerHostKeyAlgos:      supportedHostKeyAlgos,
-		CiphersClientServer:     supportedCiphers,
-		CiphersServerClient:     supportedCiphers,
-		MACsClientServer:        supportedMACs,
-		MACsServerClient:        supportedMACs,
-		CompressionClientServer: supportedCompressions,
-		CompressionServerClient: supportedCompressions,
-	}
-	kexInitPacket := marshal(msgKexInit, serverKexInit)
-	magics.serverKexInit = kexInitPacket
-
-	if err := s.writePacket(kexInitPacket); err != nil {
-		return err
-	}
-
-	packet, err := s.readPacket()
-	if err != nil {
-		return err
-	}
-
-	magics.clientKexInit = packet
-
-	var clientKexInit kexInitMsg
-	if err = unmarshal(&clientKexInit, packet, msgKexInit); err != nil {
-		return err
-	}
-
-	kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, s.transport, &clientKexInit, &serverKexInit)
-	if !ok {
-		return os.NewError("ssh: no common algorithms")
-	}
-
-	if clientKexInit.FirstKexFollows && kexAlgo != clientKexInit.KexAlgos[0] {
-		// The client sent a Kex message for the wrong algorithm,
-		// which we have to ignore.
-		_, err := s.readPacket()
-		if err != nil {
-			return err
-		}
-	}
-
-	var H, K []byte
-	var hashFunc crypto.Hash
-	switch kexAlgo {
-	case kexAlgoDH14SHA1:
-		hashFunc = crypto.SHA1
-		dhGroup14Once.Do(initDHGroup14)
-		H, K, err = s.kexDH(dhGroup14, hashFunc, &magics, hostKeyAlgo)
-	default:
-		err = os.NewError("ssh: internal error")
-	}
-
-	if err != nil {
-		return err
-	}
-
-	packet = []byte{msgNewKeys}
-	if err = s.writePacket(packet); err != nil {
-		return err
-	}
-	if err = s.transport.writer.setupKeys(serverKeys, K, H, H, hashFunc); err != nil {
-		return err
-	}
-
-	if packet, err = s.readPacket(); err != nil {
-		return err
-	}
-	if packet[0] != msgNewKeys {
-		return UnexpectedMessageError{msgNewKeys, packet[0]}
-	}
-
-	s.transport.reader.setupKeys(clientKeys, K, H, H, hashFunc)
-
-	packet, err = s.readPacket()
-	if err != nil {
-		return err
-	}
-
-	var serviceRequest serviceRequestMsg
-	if err = unmarshal(&serviceRequest, packet, msgServiceRequest); err != nil {
-		return err
-	}
-	if serviceRequest.Service != serviceUserAuth {
-		return os.NewError("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
-	}
-
-	serviceAccept := serviceAcceptMsg{
-		Service: serviceUserAuth,
-	}
-	packet = marshal(msgServiceAccept, serviceAccept)
-	if err = s.writePacket(packet); err != nil {
-		return err
-	}
-
-	if err = s.authenticate(H); err != nil {
-		return err
-	}
-
-	s.channels = make(map[uint32]*channel)
-	return nil
-}
-
-func isAcceptableAlgo(algo string) bool {
-	return algo == hostAlgoRSA
-}
-
-// testPubKey returns true if the given public key is acceptable for the user.
-func (s *ServerConnection) testPubKey(user, algo string, pubKey []byte) bool {
-	if s.Server.PubKeyCallback == nil || !isAcceptableAlgo(algo) {
-		return false
-	}
-
-	for _, c := range s.cachedPubKeys {
-		if c.user == user && c.algo == algo && bytes.Equal(c.pubKey, pubKey) {
-			return c.result
-		}
-	}
-
-	result := s.Server.PubKeyCallback(user, algo, pubKey)
-	if len(s.cachedPubKeys) < maxCachedPubKeys {
-		c := cachedPubKey{
-			user:   user,
-			algo:   algo,
-			pubKey: make([]byte, len(pubKey)),
-			result: result,
-		}
-		copy(c.pubKey, pubKey)
-		s.cachedPubKeys = append(s.cachedPubKeys, c)
-	}
-
-	return result
-}
-
-func (s *ServerConnection) authenticate(H []byte) os.Error {
-	var userAuthReq userAuthRequestMsg
-	var err os.Error
-	var packet []byte
-
-userAuthLoop:
-	for {
-		if packet, err = s.readPacket(); err != nil {
-			return err
-		}
-		if err = unmarshal(&userAuthReq, packet, msgUserAuthRequest); err != nil {
-			return err
-		}
-
-		if userAuthReq.Service != serviceSSH {
-			return os.NewError("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
-		}
-
-		switch userAuthReq.Method {
-		case "none":
-			if s.Server.NoClientAuth {
-				break userAuthLoop
-			}
-		case "password":
-			if s.Server.PasswordCallback == nil {
-				break
-			}
-			payload := userAuthReq.Payload
-			if len(payload) < 1 || payload[0] != 0 {
-				return ParseError{msgUserAuthRequest}
-			}
-			payload = payload[1:]
-			password, payload, ok := parseString(payload)
-			if !ok || len(payload) > 0 {
-				return ParseError{msgUserAuthRequest}
-			}
-
-			if s.Server.PasswordCallback(userAuthReq.User, string(password)) {
-				break userAuthLoop
-			}
-		case "publickey":
-			if s.Server.PubKeyCallback == nil {
-				break
-			}
-			payload := userAuthReq.Payload
-			if len(payload) < 1 {
-				return ParseError{msgUserAuthRequest}
-			}
-			isQuery := payload[0] == 0
-			payload = payload[1:]
-			algoBytes, payload, ok := parseString(payload)
-			if !ok {
-				return ParseError{msgUserAuthRequest}
-			}
-			algo := string(algoBytes)
-
-			pubKey, payload, ok := parseString(payload)
-			if !ok {
-				return ParseError{msgUserAuthRequest}
-			}
-			if isQuery {
-				// The client can query if the given public key
-				// would be ok.
-				if len(payload) > 0 {
-					return ParseError{msgUserAuthRequest}
-				}
-				if s.testPubKey(userAuthReq.User, algo, pubKey) {
-					okMsg := userAuthPubKeyOkMsg{
-						Algo:   algo,
-						PubKey: string(pubKey),
-					}
-					if err = s.writePacket(marshal(msgUserAuthPubKeyOk, okMsg)); err != nil {
-						return err
-					}
-					continue userAuthLoop
-				}
-			} else {
-				sig, payload, ok := parseString(payload)
-				if !ok || len(payload) > 0 {
-					return ParseError{msgUserAuthRequest}
-				}
-				if !isAcceptableAlgo(algo) {
-					break
-				}
-				rsaSig, ok := parseRSASig(sig)
-				if !ok {
-					return ParseError{msgUserAuthRequest}
-				}
-				signedData := buildDataSignedForAuth(H, userAuthReq, algoBytes, pubKey)
-				switch algo {
-				case hostAlgoRSA:
-					hashFunc := crypto.SHA1
-					h := hashFunc.New()
-					h.Write(signedData)
-					digest := h.Sum()
-					rsaKey, ok := parseRSA(pubKey)
-					if !ok {
-						return ParseError{msgUserAuthRequest}
-					}
-					if rsa.VerifyPKCS1v15(rsaKey, hashFunc, digest, rsaSig) != nil {
-						return ParseError{msgUserAuthRequest}
-					}
-				default:
-					return os.NewError("ssh: isAcceptableAlgo incorrect")
-				}
-				if s.testPubKey(userAuthReq.User, algo, pubKey) {
-					break userAuthLoop
-				}
-			}
-		}
-
-		var failureMsg userAuthFailureMsg
-		if s.Server.PasswordCallback != nil {
-			failureMsg.Methods = append(failureMsg.Methods, "password")
-		}
-		if s.Server.PubKeyCallback != nil {
-			failureMsg.Methods = append(failureMsg.Methods, "publickey")
-		}
-
-		if len(failureMsg.Methods) == 0 {
-			return os.NewError("ssh: no authentication methods configured but NoClientAuth is also false")
-		}
-
-		if err = s.writePacket(marshal(msgUserAuthFailure, failureMsg)); err != nil {
-			return err
-		}
-	}
-
-	packet = []byte{msgUserAuthSuccess}
-	if err = s.writePacket(packet); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-const defaultWindowSize = 32768
-
-// Accept reads and processes messages on a ServerConnection. It must be called
-// in order to demultiplex messages to any resulting Channels.
-func (s *ServerConnection) Accept() (Channel, os.Error) {
-	if s.err != nil {
-		return nil, s.err
-	}
-
-	for {
-		packet, err := s.readPacket()
-		if err != nil {
-
-			s.lock.Lock()
-			s.err = err
-			s.lock.Unlock()
-
-			for _, c := range s.channels {
-				c.dead = true
-				c.handleData(nil)
-			}
-
-			return nil, err
-		}
-
-		switch packet[0] {
-		case msgChannelOpen:
-			var chanOpen channelOpenMsg
-			if err := unmarshal(&chanOpen, packet, msgChannelOpen); err != nil {
-				return nil, err
-			}
-
-			c := new(channel)
-			c.chanType = chanOpen.ChanType
-			c.theirId = chanOpen.PeersId
-			c.theirWindow = chanOpen.PeersWindow
-			c.maxPacketSize = chanOpen.MaxPacketSize
-			c.extraData = chanOpen.TypeSpecificData
-			c.myWindow = defaultWindowSize
-			c.serverConn = s
-			c.cond = sync.NewCond(&c.lock)
-			c.pendingData = make([]byte, c.myWindow)
-
-			s.lock.Lock()
-			c.myId = s.nextChanId
-			s.nextChanId++
-			s.channels[c.myId] = c
-			s.lock.Unlock()
-			return c, nil
-
-		case msgChannelRequest:
-			var chanRequest channelRequestMsg
-			if err := unmarshal(&chanRequest, packet, msgChannelRequest); err != nil {
-				return nil, err
-			}
-
-			s.lock.Lock()
-			c, ok := s.channels[chanRequest.PeersId]
-			if !ok {
-				continue
-			}
-			c.handlePacket(&chanRequest)
-			s.lock.Unlock()
-
-		case msgChannelData:
-			if len(packet) < 5 {
-				return nil, ParseError{msgChannelData}
-			}
-			chanId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
-
-			s.lock.Lock()
-			c, ok := s.channels[chanId]
-			if !ok {
-				continue
-			}
-			c.handleData(packet[9:])
-			s.lock.Unlock()
-
-		case msgChannelEOF:
-			var eofMsg channelEOFMsg
-			if err := unmarshal(&eofMsg, packet, msgChannelEOF); err != nil {
-				return nil, err
-			}
-
-			s.lock.Lock()
-			c, ok := s.channels[eofMsg.PeersId]
-			if !ok {
-				continue
-			}
-			c.handlePacket(&eofMsg)
-			s.lock.Unlock()
-
-		case msgChannelClose:
-			var closeMsg channelCloseMsg
-			if err := unmarshal(&closeMsg, packet, msgChannelClose); err != nil {
-				return nil, err
-			}
-
-			s.lock.Lock()
-			c, ok := s.channels[closeMsg.PeersId]
-			if !ok {
-				continue
-			}
-			c.handlePacket(&closeMsg)
-			s.lock.Unlock()
-
-		case msgGlobalRequest:
-			var request globalRequestMsg
-			if err := unmarshal(&request, packet, msgGlobalRequest); err != nil {
-				return nil, err
-			}
-
-			if request.WantReply {
-				if err := s.writePacket([]byte{msgRequestFailure}); err != nil {
-					return nil, err
-				}
-			}
-
-		default:
-			// Unknown message. Ignore.
-		}
-	}
-
-	panic("unreachable")
-}
diff --git a/src/pkg/exp/ssh/server_shell.go b/src/pkg/exp/ssh/server_shell.go
deleted file mode 100644
index 53a3241..0000000
--- a/src/pkg/exp/ssh/server_shell.go
+++ /dev/null
@@ -1,399 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"os"
-)
-
-// ServerShell contains the state for running a VT100 terminal that is capable
-// of reading lines of input.
-type ServerShell struct {
-	c      Channel
-	prompt string
-
-	// line is the current line being entered.
-	line []byte
-	// pos is the logical position of the cursor in line
-	pos int
-
-	// cursorX contains the current X value of the cursor where the left
-	// edge is 0. cursorY contains the row number where the first row of
-	// the current line is 0.
-	cursorX, cursorY int
-	// maxLine is the greatest value of cursorY so far.
-	maxLine int
-
-	termWidth, termHeight int
-
-	// outBuf contains the terminal data to be sent.
-	outBuf []byte
-	// remainder contains the remainder of any partial key sequences after
-	// a read. It aliases into inBuf.
-	remainder []byte
-	inBuf     [256]byte
-}
-
-// NewServerShell runs a VT100 terminal on the given channel. prompt is a
-// string that is written at the start of each input line. For example: "> ".
-func NewServerShell(c Channel, prompt string) *ServerShell {
-	return &ServerShell{
-		c:          c,
-		prompt:     prompt,
-		termWidth:  80,
-		termHeight: 24,
-	}
-}
-
-const (
-	keyCtrlD     = 4
-	keyEnter     = '\r'
-	keyEscape    = 27
-	keyBackspace = 127
-	keyUnknown   = 256 + iota
-	keyUp
-	keyDown
-	keyLeft
-	keyRight
-	keyAltLeft
-	keyAltRight
-)
-
-// bytesToKey tries to parse a key sequence from b. If successful, it returns
-// the key and the remainder of the input. Otherwise it returns -1.
-func bytesToKey(b []byte) (int, []byte) {
-	if len(b) == 0 {
-		return -1, nil
-	}
-
-	if b[0] != keyEscape {
-		return int(b[0]), b[1:]
-	}
-
-	if len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
-		switch b[2] {
-		case 'A':
-			return keyUp, b[3:]
-		case 'B':
-			return keyDown, b[3:]
-		case 'C':
-			return keyRight, b[3:]
-		case 'D':
-			return keyLeft, b[3:]
-		}
-	}
-
-	if len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
-		switch b[5] {
-		case 'C':
-			return keyAltRight, b[6:]
-		case 'D':
-			return keyAltLeft, b[6:]
-		}
-	}
-
-	// If we get here then we have a key that we don't recognise, or a
-	// partial sequence. It's not clear how one should find the end of a
-	// sequence without knowing them all, but it seems that [a-zA-Z] only
-	// appears at the end of a sequence.
-	for i, c := range b[0:] {
-		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {
-			return keyUnknown, b[i+1:]
-		}
-	}
-
-	return -1, b
-}
-
-// queue appends data to the end of ss.outBuf
-func (ss *ServerShell) queue(data []byte) {
-	if len(ss.outBuf)+len(data) > cap(ss.outBuf) {
-		newOutBuf := make([]byte, len(ss.outBuf), 2*(len(ss.outBuf)+len(data)))
-		copy(newOutBuf, ss.outBuf)
-		ss.outBuf = newOutBuf
-	}
-
-	oldLen := len(ss.outBuf)
-	ss.outBuf = ss.outBuf[:len(ss.outBuf)+len(data)]
-	copy(ss.outBuf[oldLen:], data)
-}
-
-var eraseUnderCursor = []byte{' ', keyEscape, '[', 'D'}
-
-func isPrintable(key int) bool {
-	return key >= 32 && key < 127
-}
-
-// moveCursorToPos appends data to ss.outBuf which will move the cursor to the
-// given, logical position in the text.
-func (ss *ServerShell) moveCursorToPos(pos int) {
-	x := len(ss.prompt) + pos
-	y := x / ss.termWidth
-	x = x % ss.termWidth
-
-	up := 0
-	if y < ss.cursorY {
-		up = ss.cursorY - y
-	}
-
-	down := 0
-	if y > ss.cursorY {
-		down = y - ss.cursorY
-	}
-
-	left := 0
-	if x < ss.cursorX {
-		left = ss.cursorX - x
-	}
-
-	right := 0
-	if x > ss.cursorX {
-		right = x - ss.cursorX
-	}
-
-	movement := make([]byte, 3*(up+down+left+right))
-	m := movement
-	for i := 0; i < up; i++ {
-		m[0] = keyEscape
-		m[1] = '['
-		m[2] = 'A'
-		m = m[3:]
-	}
-	for i := 0; i < down; i++ {
-		m[0] = keyEscape
-		m[1] = '['
-		m[2] = 'B'
-		m = m[3:]
-	}
-	for i := 0; i < left; i++ {
-		m[0] = keyEscape
-		m[1] = '['
-		m[2] = 'D'
-		m = m[3:]
-	}
-	for i := 0; i < right; i++ {
-		m[0] = keyEscape
-		m[1] = '['
-		m[2] = 'C'
-		m = m[3:]
-	}
-
-	ss.cursorX = x
-	ss.cursorY = y
-	ss.queue(movement)
-}
-
-const maxLineLength = 4096
-
-// handleKey processes the given key and, optionally, returns a line of text
-// that the user has entered.
-func (ss *ServerShell) handleKey(key int) (line string, ok bool) {
-	switch key {
-	case keyBackspace:
-		if ss.pos == 0 {
-			return
-		}
-		ss.pos--
-
-		copy(ss.line[ss.pos:], ss.line[1+ss.pos:])
-		ss.line = ss.line[:len(ss.line)-1]
-		ss.writeLine(ss.line[ss.pos:])
-		ss.moveCursorToPos(ss.pos)
-		ss.queue(eraseUnderCursor)
-	case keyAltLeft:
-		// move left by a word.
-		if ss.pos == 0 {
-			return
-		}
-		ss.pos--
-		for ss.pos > 0 {
-			if ss.line[ss.pos] != ' ' {
-				break
-			}
-			ss.pos--
-		}
-		for ss.pos > 0 {
-			if ss.line[ss.pos] == ' ' {
-				ss.pos++
-				break
-			}
-			ss.pos--
-		}
-		ss.moveCursorToPos(ss.pos)
-	case keyAltRight:
-		// move right by a word.
-		for ss.pos < len(ss.line) {
-			if ss.line[ss.pos] == ' ' {
-				break
-			}
-			ss.pos++
-		}
-		for ss.pos < len(ss.line) {
-			if ss.line[ss.pos] != ' ' {
-				break
-			}
-			ss.pos++
-		}
-		ss.moveCursorToPos(ss.pos)
-	case keyLeft:
-		if ss.pos == 0 {
-			return
-		}
-		ss.pos--
-		ss.moveCursorToPos(ss.pos)
-	case keyRight:
-		if ss.pos == len(ss.line) {
-			return
-		}
-		ss.pos++
-		ss.moveCursorToPos(ss.pos)
-	case keyEnter:
-		ss.moveCursorToPos(len(ss.line))
-		ss.queue([]byte("\r\n"))
-		line = string(ss.line)
-		ok = true
-		ss.line = ss.line[:0]
-		ss.pos = 0
-		ss.cursorX = 0
-		ss.cursorY = 0
-		ss.maxLine = 0
-	default:
-		if !isPrintable(key) {
-			return
-		}
-		if len(ss.line) == maxLineLength {
-			return
-		}
-		if len(ss.line) == cap(ss.line) {
-			newLine := make([]byte, len(ss.line), 2*(1+len(ss.line)))
-			copy(newLine, ss.line)
-			ss.line = newLine
-		}
-		ss.line = ss.line[:len(ss.line)+1]
-		copy(ss.line[ss.pos+1:], ss.line[ss.pos:])
-		ss.line[ss.pos] = byte(key)
-		ss.writeLine(ss.line[ss.pos:])
-		ss.pos++
-		ss.moveCursorToPos(ss.pos)
-	}
-	return
-}
-
-func (ss *ServerShell) writeLine(line []byte) {
-	for len(line) != 0 {
-		if ss.cursorX == ss.termWidth {
-			ss.queue([]byte("\r\n"))
-			ss.cursorX = 0
-			ss.cursorY++
-			if ss.cursorY > ss.maxLine {
-				ss.maxLine = ss.cursorY
-			}
-		}
-
-		remainingOnLine := ss.termWidth - ss.cursorX
-		todo := len(line)
-		if todo > remainingOnLine {
-			todo = remainingOnLine
-		}
-		ss.queue(line[:todo])
-		ss.cursorX += todo
-		line = line[todo:]
-	}
-}
-
-// parsePtyRequest parses the payload of the pty-req message and extracts the
-// dimensions of the terminal. See RFC 4254, section 6.2.
-func parsePtyRequest(s []byte) (width, height int, ok bool) {
-	_, s, ok = parseString(s)
-	if !ok {
-		return
-	}
-	width32, s, ok := parseUint32(s)
-	if !ok {
-		return
-	}
-	height32, _, ok := parseUint32(s)
-	width = int(width32)
-	height = int(height32)
-	if width < 1 {
-		ok = false
-	}
-	if height < 1 {
-		ok = false
-	}
-	return
-}
-
-func (ss *ServerShell) Write(buf []byte) (n int, err os.Error) {
-	return ss.c.Write(buf)
-}
-
-// ReadLine returns a line of input from the terminal.
-func (ss *ServerShell) ReadLine() (line string, err os.Error) {
-	ss.writeLine([]byte(ss.prompt))
-	ss.c.Write(ss.outBuf)
-	ss.outBuf = ss.outBuf[:0]
-
-	for {
-		// ss.remainder is a slice at the beginning of ss.inBuf
-		// containing a partial key sequence
-		readBuf := ss.inBuf[len(ss.remainder):]
-		n, err := ss.c.Read(readBuf)
-		if err == nil {
-			ss.remainder = ss.inBuf[:n+len(ss.remainder)]
-			rest := ss.remainder
-			lineOk := false
-			for !lineOk {
-				var key int
-				key, rest = bytesToKey(rest)
-				if key < 0 {
-					break
-				}
-				if key == keyCtrlD {
-					return "", os.EOF
-				}
-				line, lineOk = ss.handleKey(key)
-			}
-			if len(rest) > 0 {
-				n := copy(ss.inBuf[:], rest)
-				ss.remainder = ss.inBuf[:n]
-			} else {
-				ss.remainder = nil
-			}
-			ss.c.Write(ss.outBuf)
-			ss.outBuf = ss.outBuf[:0]
-			if lineOk {
-				return
-			}
-			continue
-		}
-
-		if req, ok := err.(ChannelRequest); ok {
-			ok := false
-			switch req.Request {
-			case "pty-req":
-				ss.termWidth, ss.termHeight, ok = parsePtyRequest(req.Payload)
-				if !ok {
-					ss.termWidth = 80
-					ss.termHeight = 24
-				}
-			case "shell":
-				ok = true
-				if len(req.Payload) > 0 {
-					// We don't accept any commands, only the default shell.
-					ok = false
-				}
-			case "env":
-				ok = true
-			}
-			if req.WantReply {
-				ss.c.AckRequest(ok)
-			}
-		} else {
-			return "", err
-		}
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/exp/ssh/server_shell_test.go b/src/pkg/exp/ssh/server_shell_test.go
deleted file mode 100644
index 622cf7c..0000000
--- a/src/pkg/exp/ssh/server_shell_test.go
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"testing"
-	"os"
-)
-
-type MockChannel struct {
-	toSend       []byte
-	bytesPerRead int
-	received     []byte
-}
-
-func (c *MockChannel) Accept() os.Error {
-	return nil
-}
-
-func (c *MockChannel) Reject(RejectionReason, string) os.Error {
-	return nil
-}
-
-func (c *MockChannel) Read(data []byte) (n int, err os.Error) {
-	n = len(data)
-	if n == 0 {
-		return
-	}
-	if n > len(c.toSend) {
-		n = len(c.toSend)
-	}
-	if n == 0 {
-		return 0, os.EOF
-	}
-	if c.bytesPerRead > 0 && n > c.bytesPerRead {
-		n = c.bytesPerRead
-	}
-	copy(data, c.toSend[:n])
-	c.toSend = c.toSend[n:]
-	return
-}
-
-func (c *MockChannel) Write(data []byte) (n int, err os.Error) {
-	c.received = append(c.received, data...)
-	return len(data), nil
-}
-
-func (c *MockChannel) Close() os.Error {
-	return nil
-}
-
-func (c *MockChannel) AckRequest(ok bool) os.Error {
-	return nil
-}
-
-func (c *MockChannel) ChannelType() string {
-	return ""
-}
-
-func (c *MockChannel) ExtraData() []byte {
-	return nil
-}
-
-func TestClose(t *testing.T) {
-	c := &MockChannel{}
-	ss := NewServerShell(c, "> ")
-	line, err := ss.ReadLine()
-	if line != "" {
-		t.Errorf("Expected empty line but got: %s", line)
-	}
-	if err != os.EOF {
-		t.Errorf("Error should have been EOF but got: %s", err)
-	}
-}
-
-var keyPressTests = []struct {
-	in   string
-	line string
-	err  os.Error
-}{
-	{
-		"",
-		"",
-		os.EOF,
-	},
-	{
-		"\r",
-		"",
-		nil,
-	},
-	{
-		"foo\r",
-		"foo",
-		nil,
-	},
-	{
-		"a\x1b[Cb\r", // right
-		"ab",
-		nil,
-	},
-	{
-		"a\x1b[Db\r", // left
-		"ba",
-		nil,
-	},
-	{
-		"a\177b\r", // backspace
-		"b",
-		nil,
-	},
-}
-
-func TestKeyPresses(t *testing.T) {
-	for i, test := range keyPressTests {
-		for j := 0; j < len(test.in); j++ {
-			c := &MockChannel{
-				toSend:       []byte(test.in),
-				bytesPerRead: j,
-			}
-			ss := NewServerShell(c, "> ")
-			line, err := ss.ReadLine()
-			if line != test.line {
-				t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
-				break
-			}
-			if err != test.err {
-				t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
-				break
-			}
-		}
-	}
-}
diff --git a/src/pkg/exp/ssh/transport.go b/src/pkg/exp/ssh/transport.go
deleted file mode 100644
index 5a474a9..0000000
--- a/src/pkg/exp/ssh/transport.go
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"bufio"
-	"crypto"
-	"crypto/aes"
-	"crypto/cipher"
-	"crypto/hmac"
-	"crypto/subtle"
-	"hash"
-	"io"
-	"os"
-)
-
-const (
-	paddingMultiple = 16 // TODO(dfc) does this need to be configurable?
-)
-
-// transport represents the SSH connection to the remote peer.
-type transport struct {
-	reader
-	writer
-
-	cipherAlgo      string
-	macAlgo         string
-	compressionAlgo string
-
-	Close func() os.Error
-}
-
-// reader represents the incoming connection state.
-type reader struct {
-	io.Reader
-	common
-}
-
-// writer represnts the outgoing connection state.
-type writer struct {
-	*bufio.Writer
-	paddingMultiple int
-	rand            io.Reader
-	common
-}
-
-// common represents the cipher state needed to process messages in a single
-// direction.
-type common struct {
-	seqNum uint32
-	mac    hash.Hash
-	cipher cipher.Stream
-}
-
-// Read and decrypt a single packet from the remote peer.
-func (r *reader) readOnePacket() ([]byte, os.Error) {
-	var lengthBytes = make([]byte, 5)
-	var macSize uint32
-
-	if _, err := io.ReadFull(r, lengthBytes); err != nil {
-		return nil, err
-	}
-
-	if r.cipher != nil {
-		r.cipher.XORKeyStream(lengthBytes, lengthBytes)
-	}
-
-	if r.mac != nil {
-		r.mac.Reset()
-		seqNumBytes := []byte{
-			byte(r.seqNum >> 24),
-			byte(r.seqNum >> 16),
-			byte(r.seqNum >> 8),
-			byte(r.seqNum),
-		}
-		r.mac.Write(seqNumBytes)
-		r.mac.Write(lengthBytes)
-		macSize = uint32(r.mac.Size())
-	}
-
-	length := uint32(lengthBytes[0])<<24 | uint32(lengthBytes[1])<<16 | uint32(lengthBytes[2])<<8 | uint32(lengthBytes[3])
-	paddingLength := uint32(lengthBytes[4])
-
-	if length <= paddingLength+1 {
-		return nil, os.NewError("invalid packet length")
-	}
-	if length > maxPacketSize {
-		return nil, os.NewError("packet too large")
-	}
-
-	packet := make([]byte, length-1+macSize)
-	if _, err := io.ReadFull(r, packet); err != nil {
-		return nil, err
-	}
-	mac := packet[length-1:]
-	if r.cipher != nil {
-		r.cipher.XORKeyStream(packet, packet[:length-1])
-	}
-
-	if r.mac != nil {
-		r.mac.Write(packet[:length-1])
-		if subtle.ConstantTimeCompare(r.mac.Sum(), mac) != 1 {
-			return nil, os.NewError("ssh: MAC failure")
-		}
-	}
-
-	r.seqNum++
-	return packet[:length-paddingLength-1], nil
-}
-
-// Read and decrypt next packet discarding debug and noop messages.
-func (t *transport) readPacket() ([]byte, os.Error) {
-	for {
-		packet, err := t.readOnePacket()
-		if err != nil {
-			return nil, err
-		}
-		if packet[0] != msgIgnore && packet[0] != msgDebug {
-			return packet, nil
-		}
-	}
-	panic("unreachable")
-}
-
-// Encrypt and send a packet of data to the remote peer.
-func (w *writer) writePacket(packet []byte) os.Error {
-	paddingLength := paddingMultiple - (5+len(packet))%paddingMultiple
-	if paddingLength < 4 {
-		paddingLength += paddingMultiple
-	}
-
-	length := len(packet) + 1 + paddingLength
-	lengthBytes := []byte{
-		byte(length >> 24),
-		byte(length >> 16),
-		byte(length >> 8),
-		byte(length),
-		byte(paddingLength),
-	}
-	padding := make([]byte, paddingLength)
-	_, err := io.ReadFull(w.rand, padding)
-	if err != nil {
-		return err
-	}
-
-	if w.mac != nil {
-		w.mac.Reset()
-		seqNumBytes := []byte{
-			byte(w.seqNum >> 24),
-			byte(w.seqNum >> 16),
-			byte(w.seqNum >> 8),
-			byte(w.seqNum),
-		}
-		w.mac.Write(seqNumBytes)
-		w.mac.Write(lengthBytes)
-		w.mac.Write(packet)
-		w.mac.Write(padding)
-	}
-
-	// TODO(dfc) lengthBytes, packet and padding should be
-	// subslices of a single buffer
-	if w.cipher != nil {
-		w.cipher.XORKeyStream(lengthBytes, lengthBytes)
-		w.cipher.XORKeyStream(packet, packet)
-		w.cipher.XORKeyStream(padding, padding)
-	}
-
-	if _, err := w.Write(lengthBytes); err != nil {
-		return err
-	}
-	if _, err := w.Write(packet); err != nil {
-		return err
-	}
-	if _, err := w.Write(padding); err != nil {
-		return err
-	}
-
-	if w.mac != nil {
-		if _, err := w.Write(w.mac.Sum()); err != nil {
-			return err
-		}
-	}
-
-	if err := w.Flush(); err != nil {
-		return err
-	}
-	w.seqNum++
-	return err
-}
-
-type direction struct {
-	ivTag     []byte
-	keyTag    []byte
-	macKeyTag []byte
-}
-
-// TODO(dfc) can this be made a constant ?
-var (
-	serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}}
-	clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
-)
-
-// setupKeys sets the cipher and MAC keys from K, H and sessionId, as
-// described in RFC 4253, section 6.4. direction should either be serverKeys
-// (to setup server->client keys) or clientKeys (for client->server keys).
-func (c *common) setupKeys(d direction, K, H, sessionId []byte, hashFunc crypto.Hash) os.Error {
-	h := hashFunc.New()
-
-	blockSize := 16
-	keySize := 16
-	macKeySize := 20
-
-	iv := make([]byte, blockSize)
-	key := make([]byte, keySize)
-	macKey := make([]byte, macKeySize)
-	generateKeyMaterial(iv, d.ivTag, K, H, sessionId, h)
-	generateKeyMaterial(key, d.keyTag, K, H, sessionId, h)
-	generateKeyMaterial(macKey, d.macKeyTag, K, H, sessionId, h)
-
-	c.mac = truncatingMAC{12, hmac.NewSHA1(macKey)}
-	aes, err := aes.NewCipher(key)
-	if err != nil {
-		return err
-	}
-	c.cipher = cipher.NewCTR(aes, iv)
-	return nil
-}
-
-// generateKeyMaterial fills out with key material generated from tag, K, H
-// and sessionId, as specified in RFC 4253, section 7.2.
-func generateKeyMaterial(out, tag []byte, K, H, sessionId []byte, h hash.Hash) {
-	var digestsSoFar []byte
-
-	for len(out) > 0 {
-		h.Reset()
-		h.Write(K)
-		h.Write(H)
-
-		if len(digestsSoFar) == 0 {
-			h.Write(tag)
-			h.Write(sessionId)
-		} else {
-			h.Write(digestsSoFar)
-		}
-
-		digest := h.Sum()
-		n := copy(out, digest)
-		out = out[n:]
-		if len(out) > 0 {
-			digestsSoFar = append(digestsSoFar, digest...)
-		}
-	}
-}
-
-// truncatingMAC wraps around a hash.Hash and truncates the output digest to
-// a given size.
-type truncatingMAC struct {
-	length int
-	hmac   hash.Hash
-}
-
-func (t truncatingMAC) Write(data []byte) (int, os.Error) {
-	return t.hmac.Write(data)
-}
-
-func (t truncatingMAC) Sum() []byte {
-	digest := t.hmac.Sum()
-	return digest[:t.length]
-}
-
-func (t truncatingMAC) Reset() {
-	t.hmac.Reset()
-}
-
-func (t truncatingMAC) Size() int {
-	return t.length
-}
-
-// maxVersionStringBytes is the maximum number of bytes that we'll accept as a
-// version string. In the event that the client is talking a different protocol
-// we need to set a limit otherwise we will keep using more and more memory
-// while searching for the end of the version handshake.
-const maxVersionStringBytes = 1024
-
-// Read version string as specified by RFC 4253, section 4.2.
-func readVersion(r io.Reader) (versionString []byte, ok bool) {
-	versionString = make([]byte, 0, 64)
-	seenCR := false
-
-	var buf [1]byte
-forEachByte:
-	for len(versionString) < maxVersionStringBytes {
-		_, err := io.ReadFull(r, buf[:])
-		if err != nil {
-			return
-		}
-		b := buf[0]
-
-		if !seenCR {
-			if b == '\r' {
-				seenCR = true
-			}
-		} else {
-			if b == '\n' {
-				ok = true
-				break forEachByte
-			} else {
-				seenCR = false
-			}
-		}
-		versionString = append(versionString, b)
-	}
-
-	if ok {
-		// We need to remove the CR from versionString
-		versionString = versionString[:len(versionString)-1]
-	}
-
-	return
-}
diff --git a/src/pkg/exp/ssh/transport_test.go b/src/pkg/exp/ssh/transport_test.go
deleted file mode 100644
index 9a610a7..0000000
--- a/src/pkg/exp/ssh/transport_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2011 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 ssh
-
-import (
-	"bufio"
-	"bytes"
-	"testing"
-)
-
-func TestReadVersion(t *testing.T) {
-	buf := []byte(serverVersion)
-	result, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf)))
-	if !ok {
-		t.Error("readVersion didn't read version correctly")
-	}
-	if !bytes.Equal(buf[:len(buf)-2], result) {
-		t.Error("version read did not match expected")
-	}
-}
-
-func TestReadVersionTooLong(t *testing.T) {
-	buf := make([]byte, maxVersionStringBytes+1)
-	if _, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); ok {
-		t.Errorf("readVersion consumed %d bytes without error", len(buf))
-	}
-}
-
-func TestReadVersionWithoutCRLF(t *testing.T) {
-	buf := []byte(serverVersion)
-	buf = buf[:len(buf)-1]
-	if _, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); ok {
-		t.Error("readVersion did not notice \\n was missing")
-	}
-}
diff --git a/src/pkg/exp/template/html/Makefile b/src/pkg/exp/template/html/Makefile
deleted file mode 100644
index 9032aea..0000000
--- a/src/pkg/exp/template/html/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../../Make.inc
-
-TARG=exp/template/html
-GOFILES=\
-	clone.go\
-	content.go\
-	context.go\
-	css.go\
-	doc.go\
-	error.go\
-	escape.go\
-	html.go\
-	js.go\
-	transition.go\
-	url.go\
-
-include ../../../../Make.pkg
diff --git a/src/pkg/exp/template/html/clone.go b/src/pkg/exp/template/html/clone.go
deleted file mode 100644
index 803a64d..0000000
--- a/src/pkg/exp/template/html/clone.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"template/parse"
-)
-
-// clone clones a template Node.
-func clone(n parse.Node) parse.Node {
-	switch t := n.(type) {
-	case *parse.ActionNode:
-		return cloneAction(t)
-	case *parse.IfNode:
-		b := new(parse.IfNode)
-		copyBranch(&b.BranchNode, &t.BranchNode)
-		return b
-	case *parse.ListNode:
-		return cloneList(t)
-	case *parse.RangeNode:
-		b := new(parse.RangeNode)
-		copyBranch(&b.BranchNode, &t.BranchNode)
-		return b
-	case *parse.TemplateNode:
-		return cloneTemplate(t)
-	case *parse.TextNode:
-		return cloneText(t)
-	case *parse.WithNode:
-		b := new(parse.WithNode)
-		copyBranch(&b.BranchNode, &t.BranchNode)
-		return b
-	}
-	panic("cloning " + n.String() + " is unimplemented")
-}
-
-// cloneAction returns a deep clone of n.
-func cloneAction(n *parse.ActionNode) *parse.ActionNode {
-	// We use keyless fields because they won't compile if a field is added.
-	return &parse.ActionNode{n.NodeType, n.Line, clonePipe(n.Pipe)}
-}
-
-// cloneList returns a deep clone of n.
-func cloneList(n *parse.ListNode) *parse.ListNode {
-	if n == nil {
-		return nil
-	}
-	// We use keyless fields because they won't compile if a field is added.
-	c := parse.ListNode{n.NodeType, make([]parse.Node, len(n.Nodes))}
-	for i, child := range n.Nodes {
-		c.Nodes[i] = clone(child)
-	}
-	return &c
-}
-
-// clonePipe returns a shallow clone of n.
-// The escaper does not modify pipe descendants in place so there's no need to
-// clone deeply.
-func clonePipe(n *parse.PipeNode) *parse.PipeNode {
-	if n == nil {
-		return nil
-	}
-	// We use keyless fields because they won't compile if a field is added.
-	return &parse.PipeNode{n.NodeType, n.Line, n.Decl, n.Cmds}
-}
-
-// cloneTemplate returns a deep clone of n.
-func cloneTemplate(n *parse.TemplateNode) *parse.TemplateNode {
-	// We use keyless fields because they won't compile if a field is added.
-	return &parse.TemplateNode{n.NodeType, n.Line, n.Name, clonePipe(n.Pipe)}
-}
-
-// cloneText clones the given node sharing its []byte.
-func cloneText(n *parse.TextNode) *parse.TextNode {
-	// We use keyless fields because they won't compile if a field is added.
-	return &parse.TextNode{n.NodeType, n.Text}
-}
-
-// copyBranch clones src into dst.
-func copyBranch(dst, src *parse.BranchNode) {
-	// We use keyless fields because they won't compile if a field is added.
-	*dst = parse.BranchNode{
-		src.NodeType,
-		src.Line,
-		clonePipe(src.Pipe),
-		cloneList(src.List),
-		cloneList(src.ElseList),
-	}
-}
diff --git a/src/pkg/exp/template/html/clone_test.go b/src/pkg/exp/template/html/clone_test.go
deleted file mode 100644
index d915425..0000000
--- a/src/pkg/exp/template/html/clone_test.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"template"
-	"template/parse"
-	"testing"
-)
-
-func TestClone(t *testing.T) {
-	tests := []struct {
-		input, want, wantClone string
-	}{
-		{
-			`Hello, {{if true}}{{"<World>"}}{{end}}!`,
-			"Hello, <World>!",
-			"Hello, <World>!",
-		},
-		{
-			`Hello, {{if false}}{{.X}}{{else}}{{"<World>"}}{{end}}!`,
-			"Hello, <World>!",
-			"Hello, <World>!",
-		},
-		{
-			`Hello, {{with "<World>"}}{{.}}{{end}}!`,
-			"Hello, <World>!",
-			"Hello, <World>!",
-		},
-		{
-			`{{range .}}<p>{{.}}</p>{{end}}`,
-			"<p>foo</p><p><bar></p><p>baz</p>",
-			"<p>foo</p><p><bar></p><p>baz</p>",
-		},
-		{
-			`Hello, {{"<World>" | html}}!`,
-			"Hello, <World>!",
-			"Hello, <World>!",
-		},
-		{
-			`Hello{{if 1}}, World{{else}}{{template "d"}}{{end}}!`,
-			"Hello, World!",
-			"Hello, World!",
-		},
-	}
-
-	for _, test := range tests {
-		s := template.Must(template.New("s").Parse(test.input))
-		d := template.New("d")
-		d.Tree = &parse.Tree{Name: d.Name(), Root: cloneList(s.Root)}
-
-		if want, got := s.Root.String(), d.Root.String(); want != got {
-			t.Errorf("want %q, got %q", want, got)
-		}
-
-		d, err := Escape(d)
-		if err != nil {
-			t.Errorf("%q: failed to escape: %s", test.input, err)
-			continue
-		}
-
-		if want, got := "s", s.Name(); want != got {
-			t.Errorf("want %q, got %q", want, got)
-			continue
-		}
-		if want, got := "d", d.Name(); want != got {
-			t.Errorf("want %q, got %q", want, got)
-			continue
-		}
-
-		data := []string{"foo", "<bar>", "baz"}
-
-		// Make sure escaping d did not affect s.
-		var b bytes.Buffer
-		s.Execute(&b, data)
-		if got := b.String(); got != test.want {
-			t.Errorf("%q: want %q, got %q", test.input, test.want, got)
-			continue
-		}
-
-		b.Reset()
-		d.Execute(&b, data)
-		if got := b.String(); got != test.wantClone {
-			t.Errorf("%q: want %q, got %q", test.input, test.wantClone, got)
-		}
-	}
-}
diff --git a/src/pkg/exp/template/html/content.go b/src/pkg/exp/template/html/content.go
deleted file mode 100644
index 8b9809b..0000000
--- a/src/pkg/exp/template/html/content.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"fmt"
-)
-
-// Strings of content from a trusted source.
-type (
-	// CSS encapsulates known safe content that matches any of:
-	// (1) The CSS3 stylesheet production, such as `p { color: purple }`.
-	// (2) The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.
-	// (3) CSS3 declaration productions, such as `color: red; margin: 2px`.
-	// (4) The CSS3 value production, such as `rgba(0, 0, 255, 127)`.
-	// See http://www.w3.org/TR/css3-syntax/#style
-	CSS string
-
-	// HTML encapsulates a known safe HTML document fragment.
-	// It should not be used for HTML from a third-party, or HTML with
-	// unclosed tags or comments. The outputs of a sound HTML sanitizer
-	// and a template escaped by this package are fine for use with HTML.
-	HTML string
-
-	// HTMLAttr encapsulates an HTML attribute from a trusted source,
-	// for example: ` dir="ltr"`.
-	HTMLAttr string
-
-	// JS encapsulates a known safe EcmaScript5 Expression, or example,
-	// `(x + y * z())`. 
-	// Template authors are responsible for ensuring that typed expressions
-	// do not break the intended precedence and that there is no
-	// statement/expression ambiguity as when passing an expression like
-	// "{ foo: bar() }\n['foo']()", which is both a valid Expression and a
-	// valid Program with a very different meaning.
-	JS string
-
-	// JSStr encapsulates a sequence of characters meant to be embedded
-	// between quotes in a JavaScript expression.
-	// The string must match a series of StringCharacters:
-	// StringCharacter :: SourceCharacter but not `\` or LineTerminator
-	//                  | EscapeSequence
-	// Note that LineContinuations are not allowed.
-	// JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
-	JSStr string
-
-	// URL encapsulates a known safe URL as defined in RFC 3896.
-	// A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
-	// from a trusted source should go in the page, but by default dynamic
-	// `javascript:` URLs are filtered out since they are a frequently
-	// exploited injection vector.
-	URL string
-)
-
-type contentType uint8
-
-const (
-	contentTypePlain contentType = iota
-	contentTypeCSS
-	contentTypeHTML
-	contentTypeHTMLAttr
-	contentTypeJS
-	contentTypeJSStr
-	contentTypeURL
-)
-
-// stringify converts its arguments to a string and the type of the content.
-func stringify(args ...interface{}) (string, contentType) {
-	if len(args) == 1 {
-		switch s := args[0].(type) {
-		case string:
-			return s, contentTypePlain
-		case CSS:
-			return string(s), contentTypeCSS
-		case HTML:
-			return string(s), contentTypeHTML
-		case HTMLAttr:
-			return string(s), contentTypeHTMLAttr
-		case JS:
-			return string(s), contentTypeJS
-		case JSStr:
-			return string(s), contentTypeJSStr
-		case URL:
-			return string(s), contentTypeURL
-		}
-	}
-	return fmt.Sprint(args...), contentTypePlain
-}
diff --git a/src/pkg/exp/template/html/content_test.go b/src/pkg/exp/template/html/content_test.go
deleted file mode 100644
index 033dee1..0000000
--- a/src/pkg/exp/template/html/content_test.go
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"strings"
-	"template"
-	"testing"
-)
-
-func TestTypedContent(t *testing.T) {
-	data := []interface{}{
-		`<b> "foo%" O'Reilly &bar;`,
-		CSS(`a[href =~ "//example.com"]#foo`),
-		HTML(`Hello, <b>World</b> &tc!`),
-		HTMLAttr(` dir="ltr"`),
-		JS(`c && alert("Hello, World!");`),
-		JSStr(`Hello, World & O'Reilly\x21`),
-		URL(`greeting=H%69&addressee=(World)`),
-	}
-
-	// For each content sensitive escaper, see how it does on
-	// each of the typed strings above.
-	tests := []struct {
-		// A template containing a single {{.}}.
-		input string
-		want  []string
-	}{
-		{
-			`<style>{{.}} { color: blue }</style>`,
-			[]string{
-				`ZgotmplZ`,
-				// Allowed but not escaped.
-				`a[href =~ "//example.com"]#foo`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-			},
-		},
-		{
-			`<div style="{{.}}">`,
-			[]string{
-				`ZgotmplZ`,
-				// Allowed and HTML escaped.
-				`a[href =~ "//example.com"]#foo`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-			},
-		},
-		{
-			`{{.}}`,
-			[]string{
-				`<b> "foo%" O'Reilly &bar;`,
-				`a[href =~ "//example.com"]#foo`,
-				// Not escaped.
-				`Hello, <b>World</b> &tc!`,
-				` dir="ltr"`,
-				`c && alert("Hello, World!");`,
-				`Hello, World & O'Reilly\x21`,
-				`greeting=H%69&addressee=(World)`,
-			},
-		},
-		{
-			`<a{{.}}>`,
-			[]string{
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				// Allowed and HTML escaped.
-				` dir="ltr"`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-				`ZgotmplZ`,
-			},
-		},
-		{
-			`<a title={{.}}>`,
-			[]string{
-				`<b> "foo%" O'Reilly &bar;`,
-				`a[href =~ "//example.com"]#foo`,
-				// Tags stripped, spaces escaped, entity not re-escaped.
-				`Hello, World &tc!`,
-				` dir="ltr"`,
-				`c && alert("Hello, World!");`,
-				`Hello, World & O'Reilly\x21`,
-				`greeting=H%69&addressee=(World)`,
-			},
-		},
-		{
-			`<a title='{{.}}'>`,
-			[]string{
-				`<b> "foo%" O'Reilly &bar;`,
-				`a[href =~ "//example.com"]#foo`,
-				// Tags stripped, entity not re-escaped.
-				`Hello, World &tc!`,
-				` dir="ltr"`,
-				`c && alert("Hello, World!");`,
-				`Hello, World & O'Reilly\x21`,
-				`greeting=H%69&addressee=(World)`,
-			},
-		},
-		{
-			`<textarea>{{.}}</textarea>`,
-			[]string{
-				`<b> "foo%" O'Reilly &bar;`,
-				`a[href =~ "//example.com"]#foo`,
-				// Angle brackets escaped to prevent injection of close tags, entity not re-escaped.
-				`Hello, <b>World</b> &tc!`,
-				` dir="ltr"`,
-				`c && alert("Hello, World!");`,
-				`Hello, World & O'Reilly\x21`,
-				`greeting=H%69&addressee=(World)`,
-			},
-		},
-		{
-			`<script>alert({{.}})</script>`,
-			[]string{
-				`"\u003cb\u003e \"foo%\" O'Reilly &bar;"`,
-				`"a[href =~ \"//example.com\"]#foo"`,
-				`"Hello, \u003cb\u003eWorld\u003c/b\u003e &tc!"`,
-				`" dir=\"ltr\""`,
-				// Not escaped.
-				`c && alert("Hello, World!");`,
-				// Escape sequence not over-escaped.
-				`"Hello, World & O'Reilly\x21"`,
-				`"greeting=H%69&addressee=(World)"`,
-			},
-		},
-		{
-			`<button onclick="alert({{.}})">`,
-			[]string{
-				`"\u003cb\u003e \"foo%\" O'Reilly &bar;"`,
-				`"a[href =~ \"//example.com\"]#foo"`,
-				`"Hello, \u003cb\u003eWorld\u003c/b\u003e &amp;tc!"`,
-				`" dir=\"ltr\""`,
-				// Not JS escaped but HTML escaped.
-				`c && alert("Hello, World!");`,
-				// Escape sequence not over-escaped.
-				`"Hello, World & O'Reilly\x21"`,
-				`"greeting=H%69&addressee=(World)"`,
-			},
-		},
-		{
-			`<script>alert("{{.}}")</script>`,
-			[]string{
-				`\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
-				`a[href =~ \x22\/\/example.com\x22]#foo`,
-				`Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
-				` dir=\x22ltr\x22`,
-				`c \x26\x26 alert(\x22Hello, World!\x22);`,
-				// Escape sequence not over-escaped.
-				`Hello, World \x26 O\x27Reilly\x21`,
-				`greeting=H%69\x26addressee=(World)`,
-			},
-		},
-		{
-			`<button onclick='alert("{{.}}")'>`,
-			[]string{
-				`\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
-				`a[href =~ \x22\/\/example.com\x22]#foo`,
-				`Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
-				` dir=\x22ltr\x22`,
-				`c \x26\x26 alert(\x22Hello, World!\x22);`,
-				// Escape sequence not over-escaped.
-				`Hello, World \x26 O\x27Reilly\x21`,
-				`greeting=H%69\x26addressee=(World)`,
-			},
-		},
-		{
-			`<a href="?q={{.}}">`,
-			[]string{
-				`%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
-				`a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
-				`Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
-				`%20dir%3d%22ltr%22`,
-				`c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
-				`Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
-				// Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is done.
-				`greeting=H%69&addressee=%28World%29`,
-			},
-		},
-		{
-			`<style>body { background: url('?img={{.}}') }</style>`,
-			[]string{
-				`%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
-				`a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
-				`Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
-				`%20dir%3d%22ltr%22`,
-				`c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
-				`Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
-				// Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is not done.
-				`greeting=H%69&addressee=%28World%29`,
-			},
-		},
-	}
-
-	for _, test := range tests {
-		tmpl := template.Must(Escape(template.Must(template.New("x").Parse(test.input))))
-		pre := strings.Index(test.input, "{{.}}")
-		post := len(test.input) - (pre + 5)
-		var b bytes.Buffer
-		for i, x := range data {
-			b.Reset()
-			if err := tmpl.Execute(&b, x); err != nil {
-				t.Errorf("%q with %v: %s", test.input, x, err)
-				continue
-			}
-			if want, got := test.want[i], b.String()[pre:b.Len()-post]; want != got {
-				t.Errorf("%q with %v:\nwant\n\t%q,\ngot\n\t%q\n", test.input, x, want, got)
-				continue
-			}
-		}
-	}
-}
diff --git a/src/pkg/exp/template/html/context.go b/src/pkg/exp/template/html/context.go
deleted file mode 100644
index de073f1..0000000
--- a/src/pkg/exp/template/html/context.go
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"fmt"
-)
-
-// context describes the state an HTML parser must be in when it reaches the
-// portion of HTML produced by evaluating a particular template node.
-//
-// The zero value of type context is the start context for a template that
-// produces an HTML fragment as defined at
-// http://www.w3.org/TR/html5/the-end.html#parsing-html-fragments
-// where the context element is null.
-type context struct {
-	state   state
-	delim   delim
-	urlPart urlPart
-	jsCtx   jsCtx
-	attr    attr
-	element element
-	err     *Error
-}
-
-// eq returns whether two contexts are equal.
-func (c context) eq(d context) bool {
-	return c.state == d.state &&
-		c.delim == d.delim &&
-		c.urlPart == d.urlPart &&
-		c.jsCtx == d.jsCtx &&
-		c.attr == d.attr &&
-		c.element == d.element &&
-		c.err == d.err
-}
-
-// mangle produces an identifier that includes a suffix that distinguishes it
-// from template names mangled with different contexts.
-func (c context) mangle(templateName string) string {
-	// The mangled name for the default context is the input templateName.
-	if c.state == stateText {
-		return templateName
-	}
-	s := templateName + "$htmltemplate_" + c.state.String()
-	if c.delim != 0 {
-		s += "_" + c.delim.String()
-	}
-	if c.urlPart != 0 {
-		s += "_" + c.urlPart.String()
-	}
-	if c.jsCtx != 0 {
-		s += "_" + c.jsCtx.String()
-	}
-	if c.attr != 0 {
-		s += "_" + c.attr.String()
-	}
-	if c.element != 0 {
-		s += "_" + c.element.String()
-	}
-	return s
-}
-
-// state describes a high-level HTML parser state.
-//
-// It bounds the top of the element stack, and by extension the HTML insertion
-// mode, but also contains state that does not correspond to anything in the
-// HTML5 parsing algorithm because a single token production in the HTML
-// grammar may contain embedded actions in a template. For instance, the quoted
-// HTML attribute produced by
-//     <div title="Hello {{.World}}">
-// is a single token in HTML's grammar but in a template spans several nodes.
-type state uint8
-
-const (
-	// stateText is parsed character data. An HTML parser is in
-	// this state when its parse position is outside an HTML tag,
-	// directive, comment, and special element body.
-	stateText state = iota
-	// stateTag occurs before an HTML attribute or the end of a tag.
-	stateTag
-	// stateAttrName occurs inside an attribute name.
-	// It occurs between the ^'s in ` ^name^ = value`.
-	stateAttrName
-	// stateAfterName occurs after an attr name has ended but before any
-	// equals sign. It occurs between the ^'s in ` name^ ^= value`.
-	stateAfterName
-	// stateBeforeValue occurs after the equals sign but before the value.
-	// It occurs between the ^'s in ` name =^ ^value`.
-	stateBeforeValue
-	// stateHTMLCmt occurs inside an <!-- HTML comment -->.
-	stateHTMLCmt
-	// stateRCDATA occurs inside an RCDATA element (<textarea> or <title>)
-	// as described at http://dev.w3.org/html5/spec/syntax.html#elements-0
-	stateRCDATA
-	// stateAttr occurs inside an HTML attribute whose content is text.
-	stateAttr
-	// stateURL occurs inside an HTML attribute whose content is a URL.
-	stateURL
-	// stateJS occurs inside an event handler or script element.
-	stateJS
-	// stateJSDqStr occurs inside a JavaScript double quoted string.
-	stateJSDqStr
-	// stateJSSqStr occurs inside a JavaScript single quoted string.
-	stateJSSqStr
-	// stateJSRegexp occurs inside a JavaScript regexp literal.
-	stateJSRegexp
-	// stateJSBlockCmt occurs inside a JavaScript /* block comment */.
-	stateJSBlockCmt
-	// stateJSLineCmt occurs inside a JavaScript // line comment.
-	stateJSLineCmt
-	// stateCSS occurs inside a <style> element or style attribute.
-	stateCSS
-	// stateCSSDqStr occurs inside a CSS double quoted string.
-	stateCSSDqStr
-	// stateCSSSqStr occurs inside a CSS single quoted string.
-	stateCSSSqStr
-	// stateCSSDqURL occurs inside a CSS double quoted url("...").
-	stateCSSDqURL
-	// stateCSSSqURL occurs inside a CSS single quoted url('...').
-	stateCSSSqURL
-	// stateCSSURL occurs inside a CSS unquoted url(...).
-	stateCSSURL
-	// stateCSSBlockCmt occurs inside a CSS /* block comment */.
-	stateCSSBlockCmt
-	// stateCSSLineCmt occurs inside a CSS // line comment.
-	stateCSSLineCmt
-	// stateError is an infectious error state outside any valid
-	// HTML/CSS/JS construct.
-	stateError
-)
-
-var stateNames = [...]string{
-	stateText:        "stateText",
-	stateTag:         "stateTag",
-	stateAttrName:    "stateAttrName",
-	stateAfterName:   "stateAfterName",
-	stateBeforeValue: "stateBeforeValue",
-	stateHTMLCmt:     "stateHTMLCmt",
-	stateRCDATA:      "stateRCDATA",
-	stateAttr:        "stateAttr",
-	stateURL:         "stateURL",
-	stateJS:          "stateJS",
-	stateJSDqStr:     "stateJSDqStr",
-	stateJSSqStr:     "stateJSSqStr",
-	stateJSRegexp:    "stateJSRegexp",
-	stateJSBlockCmt:  "stateJSBlockCmt",
-	stateJSLineCmt:   "stateJSLineCmt",
-	stateCSS:         "stateCSS",
-	stateCSSDqStr:    "stateCSSDqStr",
-	stateCSSSqStr:    "stateCSSSqStr",
-	stateCSSDqURL:    "stateCSSDqURL",
-	stateCSSSqURL:    "stateCSSSqURL",
-	stateCSSURL:      "stateCSSURL",
-	stateCSSBlockCmt: "stateCSSBlockCmt",
-	stateCSSLineCmt:  "stateCSSLineCmt",
-	stateError:       "stateError",
-}
-
-func (s state) String() string {
-	if int(s) < len(stateNames) {
-		return stateNames[s]
-	}
-	return fmt.Sprintf("illegal state %d", int(s))
-}
-
-// isComment is true for any state that contains content meant for template
-// authors & maintainers, not for end-users or machines.
-func isComment(s state) bool {
-	switch s {
-	case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
-		return true
-	}
-	return false
-}
-
-// isInTag return whether s occurs solely inside an HTML tag.
-func isInTag(s state) bool {
-	switch s {
-	case stateTag, stateAttrName, stateAfterName, stateBeforeValue, stateAttr:
-		return true
-	}
-	return false
-}
-
-// delim is the delimiter that will end the current HTML attribute.
-type delim uint8
-
-const (
-	// delimNone occurs outside any attribute.
-	delimNone delim = iota
-	// delimDoubleQuote occurs when a double quote (") closes the attribute.
-	delimDoubleQuote
-	// delimSingleQuote occurs when a single quote (') closes the attribute.
-	delimSingleQuote
-	// delimSpaceOrTagEnd occurs when a space or right angle bracket (>)
-	// closes the attribute.
-	delimSpaceOrTagEnd
-)
-
-var delimNames = [...]string{
-	delimNone:          "delimNone",
-	delimDoubleQuote:   "delimDoubleQuote",
-	delimSingleQuote:   "delimSingleQuote",
-	delimSpaceOrTagEnd: "delimSpaceOrTagEnd",
-}
-
-func (d delim) String() string {
-	if int(d) < len(delimNames) {
-		return delimNames[d]
-	}
-	return fmt.Sprintf("illegal delim %d", int(d))
-}
-
-// urlPart identifies a part in an RFC 3986 hierarchical URL to allow different
-// encoding strategies.
-type urlPart uint8
-
-const (
-	// urlPartNone occurs when not in a URL, or possibly at the start:
-	// ^ in "^http://auth/path?k=v#frag".
-	urlPartNone urlPart = iota
-	// urlPartPreQuery occurs in the scheme, authority, or path; between the
-	// ^s in "h^ttp://auth/path^?k=v#frag".
-	urlPartPreQuery
-	// urlPartQueryOrFrag occurs in the query portion between the ^s in
-	// "http://auth/path?^k=v#frag^".
-	urlPartQueryOrFrag
-	// urlPartUnknown occurs due to joining of contexts both before and
-	// after the query separator.
-	urlPartUnknown
-)
-
-var urlPartNames = [...]string{
-	urlPartNone:        "urlPartNone",
-	urlPartPreQuery:    "urlPartPreQuery",
-	urlPartQueryOrFrag: "urlPartQueryOrFrag",
-	urlPartUnknown:     "urlPartUnknown",
-}
-
-func (u urlPart) String() string {
-	if int(u) < len(urlPartNames) {
-		return urlPartNames[u]
-	}
-	return fmt.Sprintf("illegal urlPart %d", int(u))
-}
-
-// jsCtx determines whether a '/' starts a regular expression literal or a
-// division operator.
-type jsCtx uint8
-
-const (
-	// jsCtxRegexp occurs where a '/' would start a regexp literal.
-	jsCtxRegexp jsCtx = iota
-	// jsCtxDivOp occurs where a '/' would start a division operator.
-	jsCtxDivOp
-	// jsCtxUnknown occurs where a '/' is ambiguous due to context joining.
-	jsCtxUnknown
-)
-
-func (c jsCtx) String() string {
-	switch c {
-	case jsCtxRegexp:
-		return "jsCtxRegexp"
-	case jsCtxDivOp:
-		return "jsCtxDivOp"
-	case jsCtxUnknown:
-		return "jsCtxUnknown"
-	}
-	return fmt.Sprintf("illegal jsCtx %d", int(c))
-}
-
-// element identifies the HTML element when inside a start tag or special body.
-// Certain HTML element (for example <script> and <style>) have bodies that are
-// treated differently from stateText so the element type is necessary to
-// transition into the correct context at the end of a tag and to identify the
-// end delimiter for the body.
-type element uint8
-
-const (
-	// elementNone occurs outside a special tag or special element body.
-	elementNone element = iota
-	// elementScript corresponds to the raw text <script> element.
-	elementScript
-	// elementStyle corresponds to the raw text <style> element.
-	elementStyle
-	// elementTextarea corresponds to the RCDATA <textarea> element.
-	elementTextarea
-	// elementTitle corresponds to the RCDATA <title> element.
-	elementTitle
-)
-
-var elementNames = [...]string{
-	elementNone:     "elementNone",
-	elementScript:   "elementScript",
-	elementStyle:    "elementStyle",
-	elementTextarea: "elementTextarea",
-	elementTitle:    "elementTitle",
-}
-
-func (e element) String() string {
-	if int(e) < len(elementNames) {
-		return elementNames[e]
-	}
-	return fmt.Sprintf("illegal element %d", int(e))
-}
-
-// attr identifies the most recent HTML attribute when inside a start tag.
-type attr uint8
-
-const (
-	// attrNone corresponds to a normal attribute or no attribute.
-	attrNone attr = iota
-	// attrScript corresponds to an event handler attribute.
-	attrScript
-	// attrStyle corresponds to the style attribute whose value is CSS.
-	attrStyle
-	// attrURL corresponds to an attribute whose value is a URL.
-	attrURL
-)
-
-var attrNames = [...]string{
-	attrNone:   "attrNone",
-	attrScript: "attrScript",
-	attrStyle:  "attrStyle",
-	attrURL:    "attrURL",
-}
-
-func (a attr) String() string {
-	if int(a) < len(attrNames) {
-		return attrNames[a]
-	}
-	return fmt.Sprintf("illegal attr %d", int(a))
-}
diff --git a/src/pkg/exp/template/html/css.go b/src/pkg/exp/template/html/css.go
deleted file mode 100644
index d881328..0000000
--- a/src/pkg/exp/template/html/css.go
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"fmt"
-	"unicode"
-	"utf8"
-)
-
-// endsWithCSSKeyword returns whether b ends with an ident that
-// case-insensitively matches the lower-case kw.
-func endsWithCSSKeyword(b []byte, kw string) bool {
-	i := len(b) - len(kw)
-	if i < 0 {
-		// Too short.
-		return false
-	}
-	if i != 0 {
-		r, _ := utf8.DecodeLastRune(b[:i])
-		if isCSSNmchar(r) {
-			// Too long.
-			return false
-		}
-	}
-	// Many CSS keywords, such as "!important" can have characters encoded,
-	// but the URI production does not allow that according to
-	// http://www.w3.org/TR/css3-syntax/#TOK-URI
-	// This does not attempt to recognize encoded keywords. For example,
-	// given "\75\72\6c" and "url" this return false.
-	return string(bytes.ToLower(b[i:])) == kw
-}
-
-// isCSSNmchar returns whether rune is allowed anywhere in a CSS identifier.
-func isCSSNmchar(rune int) bool {
-	// Based on the CSS3 nmchar production but ignores multi-rune escape
-	// sequences.
-	// http://www.w3.org/TR/css3-syntax/#SUBTOK-nmchar
-	return 'a' <= rune && rune <= 'z' ||
-		'A' <= rune && rune <= 'Z' ||
-		'0' <= rune && rune <= '9' ||
-		'-' == rune ||
-		'_' == rune ||
-		// Non-ASCII cases below.
-		0x80 <= rune && rune <= 0xd7ff ||
-		0xe000 <= rune && rune <= 0xfffd ||
-		0x10000 <= rune && rune <= 0x10ffff
-}
-
-// decodeCSS decodes CSS3 escapes given a sequence of stringchars.
-// If there is no change, it returns the input, otherwise it returns a slice
-// backed by a new array.
-// http://www.w3.org/TR/css3-syntax/#SUBTOK-stringchar defines stringchar.
-func decodeCSS(s []byte) []byte {
-	i := bytes.IndexByte(s, '\\')
-	if i == -1 {
-		return s
-	}
-	// The UTF-8 sequence for a codepoint is never longer than 1 + the
-	// number hex digits need to represent that codepoint, so len(s) is an
-	// upper bound on the output length.
-	b := make([]byte, 0, len(s))
-	for len(s) != 0 {
-		i := bytes.IndexByte(s, '\\')
-		if i == -1 {
-			i = len(s)
-		}
-		b, s = append(b, s[:i]...), s[i:]
-		if len(s) < 2 {
-			break
-		}
-		// http://www.w3.org/TR/css3-syntax/#SUBTOK-escape
-		// escape ::= unicode | '\' [#x20-#x7E#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
-		if isHex(s[1]) {
-			// http://www.w3.org/TR/css3-syntax/#SUBTOK-unicode
-			//   unicode ::= '\' [0-9a-fA-F]{1,6} wc?
-			j := 2
-			for j < len(s) && j < 7 && isHex(s[j]) {
-				j++
-			}
-			rune := hexDecode(s[1:j])
-			if rune > unicode.MaxRune {
-				rune, j = rune/16, j-1
-			}
-			n := utf8.EncodeRune(b[len(b):cap(b)], rune)
-			// The optional space at the end allows a hex
-			// sequence to be followed by a literal hex.
-			// string(decodeCSS([]byte(`\A B`))) == "\nB"
-			b, s = b[:len(b)+n], skipCSSSpace(s[j:])
-		} else {
-			// `\\` decodes to `\` and `\"` to `"`.
-			_, n := utf8.DecodeRune(s[1:])
-			b, s = append(b, s[1:1+n]...), s[1+n:]
-		}
-	}
-	return b
-}
-
-// isHex returns whether the given character is a hex digit.
-func isHex(c byte) bool {
-	return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
-}
-
-// hexDecode decodes a short hex digit sequence: "10" -> 16.
-func hexDecode(s []byte) int {
-	n := 0
-	for _, c := range s {
-		n <<= 4
-		switch {
-		case '0' <= c && c <= '9':
-			n |= int(c - '0')
-		case 'a' <= c && c <= 'f':
-			n |= int(c-'a') + 10
-		case 'A' <= c && c <= 'F':
-			n |= int(c-'A') + 10
-		default:
-			panic(fmt.Sprintf("Bad hex digit in %q", s))
-		}
-	}
-	return n
-}
-
-// skipCSSSpace returns a suffix of c, skipping over a single space.
-func skipCSSSpace(c []byte) []byte {
-	if len(c) == 0 {
-		return c
-	}
-	// wc ::= #x9 | #xA | #xC | #xD | #x20
-	switch c[0] {
-	case '\t', '\n', '\f', ' ':
-		return c[1:]
-	case '\r':
-		// This differs from CSS3's wc production because it contains a
-		// probable spec error whereby wc contains all the single byte
-		// sequences in nl (newline) but not CRLF.
-		if len(c) >= 2 && c[1] == '\n' {
-			return c[2:]
-		}
-		return c[1:]
-	}
-	return c
-}
-
-// cssEscaper escapes HTML and CSS special characters using \<hex>+ escapes.
-func cssEscaper(args ...interface{}) string {
-	s, _ := stringify(args...)
-	var b bytes.Buffer
-	written := 0
-	for i, r := range s {
-		var repl string
-		switch r {
-		case 0:
-			repl = `\0`
-		case '\t':
-			repl = `\9`
-		case '\n':
-			repl = `\a`
-		case '\f':
-			repl = `\c`
-		case '\r':
-			repl = `\d`
-		// Encode HTML specials as hex so the output can be embedded
-		// in HTML attributes without further encoding.
-		case '"':
-			repl = `\22`
-		case '&':
-			repl = `\26`
-		case '\'':
-			repl = `\27`
-		case '(':
-			repl = `\28`
-		case ')':
-			repl = `\29`
-		case '+':
-			repl = `\2b`
-		case '/':
-			repl = `\2f`
-		case ':':
-			repl = `\3a`
-		case ';':
-			repl = `\3b`
-		case '<':
-			repl = `\3c`
-		case '>':
-			repl = `\3e`
-		case '\\':
-			repl = `\\`
-		case '{':
-			repl = `\7b`
-		case '}':
-			repl = `\7d`
-		default:
-			continue
-		}
-		b.WriteString(s[written:i])
-		b.WriteString(repl)
-		written = i + utf8.RuneLen(r)
-		if repl != `\\` && (written == len(s) || isHex(s[written])) {
-			b.WriteByte(' ')
-		}
-	}
-	if written == 0 {
-		return s
-	}
-	b.WriteString(s[written:])
-	return b.String()
-}
-
-var expressionBytes = []byte("expression")
-var mozBindingBytes = []byte("mozbinding")
-
-// cssValueFilter allows innocuous CSS values in the output including CSS
-// quantities (10px or 25%), ID or class literals (#foo, .bar), keyword values
-// (inherit, blue), and colors (#888).
-// It filters out unsafe values, such as those that affect token boundaries,
-// and anything that might execute scripts.
-func cssValueFilter(args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeCSS {
-		return s
-	}
-	b, id := decodeCSS([]byte(s)), make([]byte, 0, 64)
-
-	// CSS3 error handling is specified as honoring string boundaries per
-	// http://www.w3.org/TR/css3-syntax/#error-handling :
-	//     Malformed declarations. User agents must handle unexpected
-	//     tokens encountered while parsing a declaration by reading until
-	//     the end of the declaration, while observing the rules for
-	//     matching pairs of (), [], {}, "", and '', and correctly handling
-	//     escapes. For example, a malformed declaration may be missing a
-	//     property, colon (:) or value.
-	// So we need to make sure that values do not have mismatched bracket
-	// or quote characters to prevent the browser from restarting parsing
-	// inside a string that might embed JavaScript source.
-	for i, c := range b {
-		switch c {
-		case 0, '"', '\'', '(', ')', '/', ';', '@', '[', '\\', ']', '`', '{', '}':
-			return filterFailsafe
-		case '-':
-			// Disallow <!-- or -->.
-			// -- should not appear in valid identifiers.
-			if i != 0 && '-' == b[i-1] {
-				return filterFailsafe
-			}
-		default:
-			if c < 0x80 && isCSSNmchar(int(c)) {
-				id = append(id, c)
-			}
-		}
-	}
-	id = bytes.ToLower(id)
-	if bytes.Index(id, expressionBytes) != -1 || bytes.Index(id, mozBindingBytes) != -1 {
-		return filterFailsafe
-	}
-	return string(b)
-}
diff --git a/src/pkg/exp/template/html/css_test.go b/src/pkg/exp/template/html/css_test.go
deleted file mode 100644
index 5ba3e77..0000000
--- a/src/pkg/exp/template/html/css_test.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"strconv"
-	"strings"
-	"testing"
-)
-
-func TestEndsWithCSSKeyword(t *testing.T) {
-	tests := []struct {
-		css, kw string
-		want    bool
-	}{
-		{"", "url", false},
-		{"url", "url", true},
-		{"URL", "url", true},
-		{"Url", "url", true},
-		{"url", "important", false},
-		{"important", "important", true},
-		{"image-url", "url", false},
-		{"imageurl", "url", false},
-		{"image url", "url", true},
-	}
-	for _, test := range tests {
-		got := endsWithCSSKeyword([]byte(test.css), test.kw)
-		if got != test.want {
-			t.Errorf("want %t but got %t for css=%v, kw=%v", test.want, got, test.css, test.kw)
-		}
-	}
-}
-
-func TestIsCSSNmchar(t *testing.T) {
-	tests := []struct {
-		rune int
-		want bool
-	}{
-		{0, false},
-		{'0', true},
-		{'9', true},
-		{'A', true},
-		{'Z', true},
-		{'a', true},
-		{'z', true},
-		{'_', true},
-		{'-', true},
-		{':', false},
-		{';', false},
-		{' ', false},
-		{0x7f, false},
-		{0x80, true},
-		{0x1234, true},
-		{0xd800, false},
-		{0xdc00, false},
-		{0xfffe, false},
-		{0x10000, true},
-		{0x110000, false},
-	}
-	for _, test := range tests {
-		got := isCSSNmchar(test.rune)
-		if got != test.want {
-			t.Errorf("%q: want %t but got %t", string(test.rune), test.want, got)
-		}
-	}
-}
-
-func TestDecodeCSS(t *testing.T) {
-	tests := []struct {
-		css, want string
-	}{
-		{``, ``},
-		{`foo`, `foo`},
-		{`foo\`, `foo`},
-		{`foo\\`, `foo\`},
-		{`\`, ``},
-		{`\A`, "\n"},
-		{`\a`, "\n"},
-		{`\0a`, "\n"},
-		{`\00000a`, "\n"},
-		{`\000000a`, "\u0000a"},
-		{`\1234 5`, "\u1234" + "5"},
-		{`\1234\20 5`, "\u1234" + " 5"},
-		{`\1234\A 5`, "\u1234" + "\n5"},
-		{"\\1234\t5", "\u1234" + "5"},
-		{"\\1234\n5", "\u1234" + "5"},
-		{"\\1234\r\n5", "\u1234" + "5"},
-		{`\12345`, "\U00012345"},
-		{`\\`, `\`},
-		{`\\ `, `\ `},
-		{`\"`, `"`},
-		{`\'`, `'`},
-		{`\.`, `.`},
-		{`\. .`, `. .`},
-		{
-			`The \3c i\3equick\3c/i\3e,\d\A\3cspan style=\27 color:brown\27\3e brown\3c/span\3e  fox jumps\2028over the \3c canine class=\22lazy\22 \3e dog\3c/canine\3e`,
-			"The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>",
-		},
-	}
-	for _, test := range tests {
-		got := string(decodeCSS([]byte(test.css)))
-		if got != test.want {
-			t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.css, test.want, got)
-		}
-	}
-}
-
-func TestHexDecode(t *testing.T) {
-	for i := 0; i < 0x200000; i += 101 /* coprime with 16 */ {
-		s := strconv.Itob(i, 16)
-		if got := hexDecode([]byte(s)); got != i {
-			t.Errorf("%s: want %d but got %d", s, i, got)
-		}
-		s = strings.ToUpper(s)
-		if got := hexDecode([]byte(s)); got != i {
-			t.Errorf("%s: want %d but got %d", s, i, got)
-		}
-	}
-}
-
-func TestSkipCSSSpace(t *testing.T) {
-	tests := []struct {
-		css, want string
-	}{
-		{"", ""},
-		{"foo", "foo"},
-		{"\n", ""},
-		{"\r\n", ""},
-		{"\r", ""},
-		{"\t", ""},
-		{" ", ""},
-		{"\f", ""},
-		{" foo", "foo"},
-		{"  foo", " foo"},
-		{`\20`, `\20`},
-	}
-	for _, test := range tests {
-		got := string(skipCSSSpace([]byte(test.css)))
-		if got != test.want {
-			t.Errorf("%q: want %q but got %q", test.css, test.want, got)
-		}
-	}
-}
-
-func TestCSSEscaper(t *testing.T) {
-	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
-		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
-		` !"#$%&'()*+,-./` +
-		`0123456789:;<=>?` +
-		`@ABCDEFGHIJKLMNO` +
-		`PQRSTUVWXYZ[\]^_` +
-		"`abcdefghijklmno" +
-		"pqrstuvwxyz{|}~\x7f" +
-		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
-
-	want := ("\\0\x01\x02\x03\x04\x05\x06\x07" +
-		"\x08\\9\\a\x0b\\c\\d\x0E\x0F" +
-		"\x10\x11\x12\x13\x14\x15\x16\x17" +
-		"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
-		` !\22#$%\26\27\28\29*\2b,-.\2f ` +
-		`0123456789\3a\3b\3c=\3e?` +
-		`@ABCDEFGHIJKLMNO` +
-		`PQRSTUVWXYZ[\\]^_` +
-		"`abcdefghijklmno" +
-		`pqrstuvwxyz\7b|\7d~` + "\u007f" +
-		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
-
-	got := cssEscaper(input)
-	if got != want {
-		t.Errorf("encode: want\n\t%q\nbut got\n\t%q", want, got)
-	}
-
-	got = string(decodeCSS([]byte(got)))
-	if input != got {
-		t.Errorf("decode: want\n\t%q\nbut got\n\t%q", input, got)
-	}
-}
-
-func TestCSSValueFilter(t *testing.T) {
-	tests := []struct {
-		css, want string
-	}{
-		{"", ""},
-		{"foo", "foo"},
-		{"0", "0"},
-		{"0px", "0px"},
-		{"-5px", "-5px"},
-		{"1.25in", "1.25in"},
-		{"+.33em", "+.33em"},
-		{"100%", "100%"},
-		{"12.5%", "12.5%"},
-		{".foo", ".foo"},
-		{"#bar", "#bar"},
-		{"corner-radius", "corner-radius"},
-		{"-moz-corner-radius", "-moz-corner-radius"},
-		{"#000", "#000"},
-		{"#48f", "#48f"},
-		{"#123456", "#123456"},
-		{"U+00-FF, U+980-9FF", "U+00-FF, U+980-9FF"},
-		{"color: red", "color: red"},
-		{"<!--", "ZgotmplZ"},
-		{"-->", "ZgotmplZ"},
-		{"<![CDATA[", "ZgotmplZ"},
-		{"]]>", "ZgotmplZ"},
-		{"</style", "ZgotmplZ"},
-		{`"`, "ZgotmplZ"},
-		{`'`, "ZgotmplZ"},
-		{"`", "ZgotmplZ"},
-		{"\x00", "ZgotmplZ"},
-		{"/* foo */", "ZgotmplZ"},
-		{"//", "ZgotmplZ"},
-		{"[href=~", "ZgotmplZ"},
-		{"expression(alert(1337))", "ZgotmplZ"},
-		{"-expression(alert(1337))", "ZgotmplZ"},
-		{"expression", "ZgotmplZ"},
-		{"Expression", "ZgotmplZ"},
-		{"EXPRESSION", "ZgotmplZ"},
-		{"-moz-binding", "ZgotmplZ"},
-		{"-expr\x00ession(alert(1337))", "ZgotmplZ"},
-		{`-expr\0ession(alert(1337))`, "ZgotmplZ"},
-		{`-express\69on(alert(1337))`, "ZgotmplZ"},
-		{`-express\69 on(alert(1337))`, "ZgotmplZ"},
-		{`-exp\72 ession(alert(1337))`, "ZgotmplZ"},
-		{`-exp\52 ession(alert(1337))`, "ZgotmplZ"},
-		{`-exp\000052 ession(alert(1337))`, "ZgotmplZ"},
-		{`-expre\0000073sion`, "-expre\x073sion"},
-		{`@import url evil.css`, "ZgotmplZ"},
-	}
-	for _, test := range tests {
-		got := cssValueFilter(test.css)
-		if got != test.want {
-			t.Errorf("%q: want %q but got %q", test.css, test.want, got)
-		}
-	}
-}
-
-func BenchmarkCSSEscaper(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		cssEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
-	}
-}
-
-func BenchmarkCSSEscaperNoSpecials(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		cssEscaper("The quick, brown fox jumps over the lazy dog.")
-	}
-}
-
-func BenchmarkDecodeCSS(b *testing.B) {
-	s := []byte(`The \3c i\3equick\3c/i\3e,\d\A\3cspan style=\27 color:brown\27\3e brown\3c/span\3e fox jumps\2028over the \3c canine class=\22lazy\22 \3edog\3c/canine\3e`)
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		decodeCSS(s)
-	}
-}
-
-func BenchmarkDecodeCSSNoSpecials(b *testing.B) {
-	s := []byte("The quick, brown fox jumps over the lazy dog.")
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		decodeCSS(s)
-	}
-}
-
-func BenchmarkCSSValueFilter(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		cssValueFilter(`  e\78preS\0Sio/**/n(alert(1337))`)
-	}
-}
-
-func BenchmarkCSSValueFilterOk(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		cssValueFilter(`Times New Roman`)
-	}
-}
diff --git a/src/pkg/exp/template/html/doc.go b/src/pkg/exp/template/html/doc.go
deleted file mode 100644
index a9b78ca..0000000
--- a/src/pkg/exp/template/html/doc.go
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2011 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 html is a specialization of package template that automates the
-construction of HTML output that is safe against code injection.
-
-
-Introduction
-
-To use this package, invoke the standard template package to parse a template
-set, and then use this package’s EscapeSet function to secure the set.
-The arguments to EscapeSet are the template set and the names of all templates
-that will be passed to Execute.
-
-    set, err := new(template.Set).Parse(...)
-    set, err = EscapeSet(set, "templateName0", ...)
-
-If successful, set will now be injection-safe. Otherwise, the returned set will
-be nil and an error, described below, will explain the problem.
-
-The template names do not need to include helper templates but should include
-all names x used thus:
-
-    set.Execute(out, x, ...)
-
-EscapeSet modifies the named templates in place to treat data values as plain
-text safe for embedding in an HTML document. The escaping is contextual, so
-actions can appear within JavaScript, CSS, and URI contexts without introducing'hazards.
-
-The security model used by this package assumes that template authors are
-trusted, while Execute's data parameter is not. More details are provided below.
-
-Example
-
-    tmpls, err := new(template.Set).Parse(`{{define "t'}}Hello, {{.}}!{{end}}`)
-
-when used by itself
-
-    tmpls.Execute(out, "t", "<script>alert('you have been pwned')</script>")
-
-produces
-
-    Hello, <script>alert('you have been pwned')</script>!
-
-but after securing with EscapeSet like this,
-
-    tmpls, err := EscapeSet(tmpls, "t")
-    tmpls.Execute(out, "t", ...)
-
-produces the safe, escaped HTML output
-
-    Hello, <script>alert('you have been pwned')</script>!
-
-
-Contexts
-
-EscapeSet understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
-functions to each simple action pipeline, so given the excerpt
-
-  <a href="/search?q={{.}}">{{.}}</a>
-
-EscapeSet will rewrite each {{.}} to add escaping functions where necessary,
-in this case,
-
-  <a href="/search?q={{. | urlquery}}">{{. | html}}</a>
-
-
-Errors
-
-See the documentation of ErrorCode for details.
-
-
-A fuller picture
-
-The rest of this package comment may be skipped on first reading; it includes
-details necessary to understand escaping contexts and error messages. Most users
-will not need to understand these details.
-
-
-Contexts
-
-Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
-how {{.}} appears when used in the context to the left.
-
-Context                          {{.}} After
-{{.}}                            O'Reilly: How are <i>you</i>?
-<a title='{{.}}'>                O'Reilly: How are you?
-<a href="/{{.}}">                O'Reilly: How are %3ci%3eyou%3c/i%3e?
-<a href="?q={{.}}">              O'Reilly%3a%20How%20are%3ci%3e...%3f
-<a onx='f("{{.}}")'>             O\x27Reilly: How are \x3ci\x3eyou...?
-<a onx='f({{.}})'>               "O\x27Reilly: How are \x3ci\x3eyou...?"
-<a onx='pattern = /{{.}}/;'>     O\x27Reilly: How are \x3ci\x3eyou...\x3f
-
-If used in an unsafe context, then the value might be filtered out:
-
-Context                          {{.}} After
-<a href="{{.}}">                 #ZgotmplZ
-
-since "O'Reilly:" is not an allowed protocol like "http:".
-
-
-If {{.}} is the innocuous word, `left`, then it can appear more widely,
-
-Context                              {{.}} After
-{{.}}                                left
-<a title='{{.}}'>                    left
-<a href='{{.}}'>                     left
-<a href='/{{.}}'>                    left
-<a href='?dir={{.}}'>                left
-<a style="border-{{.}}: 4px">        left
-<a style="align: {{.}}">             left
-<a style="background: '{{.}}'>       left
-<a style="background: url('{{.}}')>  left
-<style>p.{{.}} {color:red}</style>   left
-
-Non-string values can be used in JavaScript contexts.
-If {{.}} is
-
-  []struct{A,B string}{ "foo", "bar" }
-
-in the escaped template
-
-  <script>var pair = {{.}};</script>
-
-then the template output is
-
-  <script>var pair = {"A": "foo", "B": "bar"};</script>
-
-See package json to understand how non-string content is marshalled for
-embedding in JavaScript contexts.
-
-
-Typed Strings
-
-By default, EscapeSet assumes all pipelines produce a plain text string. It
-adds escaping pipeline stages necessary to correctly and safely embed that
-plain text string in the appropriate context.
-
-When a data value is not plain text, you can make sure it is not over-escaped
-by marking it with its type.
-
-Types HTML, JS, URL, and others from content.go can carry safe content that is
-exempted from escaping.
-
-The template
-
-  Hello, {{.}}!
-
-can be invoked with
-
-  tmpl.Execute(out, HTML(`<b>World</b>`))
-
-to produce
-
-  Hello, <b>World</b>!
-
-instead of the
-
-  Hello, <b>World<b>!
-
-that would have been produced if {{.}} was a regular string.
-
-
-Security Model
-
-http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.
-
-This package assumes that template authors are trusted, that Execute's data
-parameter is not, and seeks to preserve the properties below in the face
-of untrusted data:
-
-Structure Preservation Property
-"... when a template author writes an HTML tag in a safe templating language,
-the browser will interpret the corresponding portion of the output as a tag
-regardless of the values of untrusted data, and similarly for other structures
-such as attribute boundaries and JS and CSS string boundaries."
-
-Code Effect Property
-"... only code specified by the template author should run as a result of
-injecting the template output into a page and all code specified by the
-template author should run as a result of the same."
-
-Least Surprise Property
-"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript;
-who knows that EscapeSet is applied should be able to look at a {{.}}
-and correctly infer what sanitization happens."
-*/
-package html
diff --git a/src/pkg/exp/template/html/error.go b/src/pkg/exp/template/html/error.go
deleted file mode 100644
index f06251d..0000000
--- a/src/pkg/exp/template/html/error.go
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"fmt"
-)
-
-// Error describes a problem encountered during template Escaping.
-type Error struct {
-	// ErrorCode describes the kind of error.
-	ErrorCode ErrorCode
-	// Name is the name of the template in which the error was encountered.
-	Name string
-	// Line is the line number of the error in the template source or 0.
-	Line int
-	// Description is a human-readable description of the problem.
-	Description string
-}
-
-// ErrorCode is a code for a kind of error.
-type ErrorCode int
-
-// We define codes for each error that manifests while escaping templates, but
-// escaped templates may also fail at runtime.
-//
-// Output: "ZgotmplZ"
-// Example:
-//   <img src="{{.X}}">
-//   where {{.X}} evaluates to `javascript:...`
-// Discussion:
-//   "ZgotmplZ" is a special value that indicates that unsafe content reached a
-//   CSS or URL context at runtime. The output of the example will be
-//     <img src="#ZgotmplZ">
-//   If the data comes from a trusted source, use content types to exempt it
-//   from filtering: URL(`javascript:...`).
-const (
-	// OK indicates the lack of an error.
-	OK ErrorCode = iota
-
-	// ErrorAmbigContext: "... appears in an ambiguous URL context"
-	// Example:
-	//   <a href="
-	//      {{if .C}}
-	//        /path/
-	//      {{else}}
-	//        /search?q=
-	//      {{end}}
-	//      {{.X}}
-	//   ">
-	// Discussion:
-	//   {{.X}} is in an ambiguous URL context since, depending on {{.C}},
-	//  it may be either a URL suffix or a query parameter.
-	//   Moving {{.X}} into the condition removes the ambiguity:
-	//   <a href="{{if .C}}/path/{{.X}}{{else}}/search?q={{.X}}">
-	ErrAmbigContext
-
-	// TODO: document
-	ErrBadHTML
-
-	// ErrBranchEnd: "{{if}} branches end in different contexts"
-	// Example:
-	//   {{if .C}}<a href="{{end}}{{.X}}
-	// Discussion:
-	//   EscapeSet statically examines each possible path when it encounters
-	//   a {{if}}, {{range}}, or {{with}} to escape any following pipelines.
-	//   The example is ambiguous since {{.X}} might be an HTML text node,
-	//   or a URL prefix in an HTML attribute. EscapeSet needs to understand
-	//   the context of {{.X}} to escape it, but that depends on the
-	//   run-time value of {{.C}}.
-	//
-	//   The problem is usually something like missing quotes or angle
-	//   brackets, or can be avoided by refactoring to put the two contexts
-	//   into different branches of an if, range or with. If the problem
-	//   is in a {{range}} over a collection that should never be empty,
-	//   adding a dummy {{else}} can help.
-	ErrBranchEnd
-
-	// ErrEndContext: "... ends in a non-text context: ..."
-	// Examples:
-	//   <div
-	//   <div title="no close quote>
-	//   <script>f()
-	// Discussion:
-	//   EscapeSet assumes the ouput is a DocumentFragment of HTML.
-	//   Templates that end without closing tags will trigger this error.
-	//   Templates that produce incomplete Fragments should not be named
-	//   in the call to EscapeSet.
-	//
-	// If you have a helper template in your set that is not meant to
-	// produce a document fragment, then do not pass its name to
-	// EscapeSet(set, ...names).
-	//
-	//   {{define "main"}} <script>{{template "helper"}}</script> {{end}}
-	//   {{define "helper"}} document.write(' <div title=" ') {{end}}
-	// 
-	// "helper" does not produce a valid document fragment, though it does
-	// produce a valid JavaScript Program.
-	ErrEndContext
-
-	// ErrNoNames: "must specify names of top level templates"
-	// 
-	//   EscapeSet does not assume that all templates in a set produce HTML.
-	//   Some may be helpers that produce snippets of other languages.
-	//   Passing in no template names is most likely an error,
-	//   so EscapeSet(set) will panic.
-	//   If you call EscapeSet with a slice of names, guard it with len:
-	// 
-	//     if len(names) != 0 {
-	//       set, err := EscapeSet(set, ...names)
-	//     }
-	ErrNoNames
-
-	// ErrNoSuchTemplate: "no such template ..."
-	// Examples:
-	//    {{define "main"}}<div {{template "attrs"}}>{{end}}
-	//    {{define "attrs"}}href="{{.URL}}"{{end}}
-	// Discussion:
-	//   EscapeSet looks through template calls to compute the context.
-	//   Here the {{.URL}} in "attrs" must be treated as a URL when called
-	//   from "main", but if "attrs" is not in set when
-	//   EscapeSet(&set, "main") is called, this error will arise.
-	ErrNoSuchTemplate
-
-	// TODO: document
-	ErrOutputContext
-
-	// ErrPartialCharset: "unfinished JS regexp charset in ..."
-	// Example:
-	//     <script>var pattern = /foo[{{.Chars}}]/</script>
-	// Discussion:
-	//   EscapeSet does not support interpolation into regular expression
-	//   literal character sets.
-	ErrPartialCharset
-
-	// ErrPartialEscape: "unfinished escape sequence in ..."
-	// Example:
-	//   <script>alert("\{{.X}}")</script>
-	// Discussion:
-	//   EscapeSet does not support actions following a backslash.
-	//   This is usually an error and there are better solutions; for
-	//   our example
-	//     <script>alert("{{.X}}")</script>
-	//   should work, and if {{.X}} is a partial escape sequence such as
-	//   "xA0", mark the whole sequence as safe content: JSStr(`\xA0`)
-	ErrPartialEscape
-
-	// ErrRangeLoopReentry: "on range loop re-entry: ..."
-	// Example:
-	//   {{range .}}<p class={{.}}{{end}}
-	// Discussion:
-	//   If an iteration through a range would cause it to end in a
-	//   different context than an earlier pass, there is no single context.
-	//   In the example, the <p> tag is missing a '>'.
-	//   EscapeSet cannot tell whether {{.}} is meant to be an HTML class or
-	//   the content of a broken <p> element and complains because the
-	//   second iteration would produce something like
-	// 
-	//     <p class=foo<p class=bar
-	ErrRangeLoopReentry
-
-	// TODO: document
-	ErrSlashAmbig
-)
-
-func (e *Error) String() string {
-	if e.Line != 0 {
-		return fmt.Sprintf("exp/template/html:%s:%d: %s", e.Name, e.Line, e.Description)
-	} else if e.Name != "" {
-		return fmt.Sprintf("exp/template/html:%s: %s", e.Name, e.Description)
-	}
-	return "exp/template/html: " + e.Description
-}
-
-// errorf creates an error given a format string f and args.
-// The template Name still needs to be supplied.
-func errorf(k ErrorCode, line int, f string, args ...interface{}) *Error {
-	return &Error{k, "", line, fmt.Sprintf(f, args...)}
-}
diff --git a/src/pkg/exp/template/html/escape.go b/src/pkg/exp/template/html/escape.go
deleted file mode 100644
index 650a6ac..0000000
--- a/src/pkg/exp/template/html/escape.go
+++ /dev/null
@@ -1,699 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"fmt"
-	"html"
-	"os"
-	"template"
-	"template/parse"
-)
-
-// Escape rewrites each action in the template to guarantee that the output is
-// properly escaped.
-func Escape(t *template.Template) (*template.Template, os.Error) {
-	var s template.Set
-	s.Add(t)
-	if _, err := EscapeSet(&s, t.Name()); err != nil {
-		return nil, err
-	}
-	// TODO: if s contains cloned dependencies due to self-recursion
-	// cross-context, error out.
-	return t, nil
-}
-
-// EscapeSet rewrites the template set to guarantee that the output of any of
-// the named templates is properly escaped.
-// Names should include the names of all templates that might be Executed but
-// need not include helper templates.
-// If no error is returned, then the named templates have been modified. 
-// Otherwise the named templates have been rendered unusable.
-func EscapeSet(s *template.Set, names ...string) (*template.Set, os.Error) {
-	if len(names) == 0 {
-		// TODO: Maybe add a method to Set to enumerate template names
-		// and use those instead.
-		return nil, &Error{ErrNoNames, "", 0, "must specify names of top level templates"}
-	}
-	e := newEscaper(s)
-	for _, name := range names {
-		c, _ := e.escapeTree(context{}, name, 0)
-		var err os.Error
-		if c.err != nil {
-			err, c.err.Name = c.err, name
-		} else if c.state != stateText {
-			err = &Error{ErrEndContext, name, 0, fmt.Sprintf("ends in a non-text context: %v", c)}
-		}
-		if err != nil {
-			// Prevent execution of unsafe templates.
-			for _, name := range names {
-				if t := s.Template(name); t != nil {
-					t.Tree = nil
-				}
-			}
-			return nil, err
-		}
-	}
-	e.commit()
-	return s, nil
-}
-
-// funcMap maps command names to functions that render their inputs safe.
-var funcMap = template.FuncMap{
-	"exp_template_html_attrescaper":     attrEscaper,
-	"exp_template_html_commentescaper":  commentEscaper,
-	"exp_template_html_cssescaper":      cssEscaper,
-	"exp_template_html_cssvaluefilter":  cssValueFilter,
-	"exp_template_html_htmlnamefilter":  htmlNameFilter,
-	"exp_template_html_htmlescaper":     htmlEscaper,
-	"exp_template_html_jsregexpescaper": jsRegexpEscaper,
-	"exp_template_html_jsstrescaper":    jsStrEscaper,
-	"exp_template_html_jsvalescaper":    jsValEscaper,
-	"exp_template_html_nospaceescaper":  htmlNospaceEscaper,
-	"exp_template_html_rcdataescaper":   rcdataEscaper,
-	"exp_template_html_urlescaper":      urlEscaper,
-	"exp_template_html_urlfilter":       urlFilter,
-	"exp_template_html_urlnormalizer":   urlNormalizer,
-}
-
-// equivEscapers matches contextual escapers to equivalent template builtins.
-var equivEscapers = map[string]string{
-	"exp_template_html_attrescaper":    "html",
-	"exp_template_html_htmlescaper":    "html",
-	"exp_template_html_nospaceescaper": "html",
-	"exp_template_html_rcdataescaper":  "html",
-	"exp_template_html_urlescaper":     "urlquery",
-	"exp_template_html_urlnormalizer":  "urlquery",
-}
-
-// escaper collects type inferences about templates and changes needed to make
-// templates injection safe.
-type escaper struct {
-	// set is the template set being escaped.
-	set *template.Set
-	// output[templateName] is the output context for a templateName that
-	// has been mangled to include its input context.
-	output map[string]context
-	// derived[c.mangle(name)] maps to a template derived from the template
-	// named name templateName for the start context c.
-	derived map[string]*template.Template
-	// called[templateName] is a set of called mangled template names.
-	called map[string]bool
-	// xxxNodeEdits are the accumulated edits to apply during commit.
-	// Such edits are not applied immediately in case a template set
-	// executes a given template in different escaping contexts.
-	actionNodeEdits   map[*parse.ActionNode][]string
-	templateNodeEdits map[*parse.TemplateNode]string
-	textNodeEdits     map[*parse.TextNode][]byte
-}
-
-// newEscaper creates a blank escaper for the given set.
-func newEscaper(s *template.Set) *escaper {
-	return &escaper{
-		s,
-		map[string]context{},
-		map[string]*template.Template{},
-		map[string]bool{},
-		map[*parse.ActionNode][]string{},
-		map[*parse.TemplateNode]string{},
-		map[*parse.TextNode][]byte{},
-	}
-}
-
-// filterFailsafe is an innocuous word that is emitted in place of unsafe values
-// by sanitizer functions. It is not a keyword in any programming language,
-// contains no special characters, is not empty, and when it appears in output
-// it is distinct enough that a developer can find the source of the problem
-// via a search engine.
-const filterFailsafe = "ZgotmplZ"
-
-// escape escapes a template node.
-func (e *escaper) escape(c context, n parse.Node) context {
-	switch n := n.(type) {
-	case *parse.ActionNode:
-		return e.escapeAction(c, n)
-	case *parse.IfNode:
-		return e.escapeBranch(c, &n.BranchNode, "if")
-	case *parse.ListNode:
-		return e.escapeList(c, n)
-	case *parse.RangeNode:
-		return e.escapeBranch(c, &n.BranchNode, "range")
-	case *parse.TemplateNode:
-		return e.escapeTemplate(c, n)
-	case *parse.TextNode:
-		return e.escapeText(c, n)
-	case *parse.WithNode:
-		return e.escapeBranch(c, &n.BranchNode, "with")
-	}
-	panic("escaping " + n.String() + " is unimplemented")
-}
-
-// escapeAction escapes an action template node.
-func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
-	c = nudge(c)
-	s := make([]string, 0, 3)
-	switch c.state {
-	case stateError:
-		return c
-	case stateURL, stateCSSDqStr, stateCSSSqStr, stateCSSDqURL, stateCSSSqURL, stateCSSURL:
-		switch c.urlPart {
-		case urlPartNone:
-			s = append(s, "exp_template_html_urlfilter")
-			fallthrough
-		case urlPartPreQuery:
-			switch c.state {
-			case stateCSSDqStr, stateCSSSqStr:
-				s = append(s, "exp_template_html_cssescaper")
-			case stateCSSDqURL, stateCSSSqURL, stateCSSURL:
-				s = append(s, "exp_template_html_urlnormalizer")
-			}
-		case urlPartQueryOrFrag:
-			s = append(s, "exp_template_html_urlescaper")
-		case urlPartUnknown:
-			return context{
-				state: stateError,
-				err:   errorf(ErrAmbigContext, n.Line, "%s appears in an ambiguous URL context", n),
-			}
-		default:
-			panic(c.urlPart.String())
-		}
-	case stateJS:
-		s = append(s, "exp_template_html_jsvalescaper")
-		// A slash after a value starts a div operator.
-		c.jsCtx = jsCtxDivOp
-	case stateJSDqStr, stateJSSqStr:
-		s = append(s, "exp_template_html_jsstrescaper")
-	case stateJSRegexp:
-		s = append(s, "exp_template_html_jsregexpescaper")
-	case stateCSS:
-		s = append(s, "exp_template_html_cssvaluefilter")
-	case stateText:
-		s = append(s, "exp_template_html_htmlescaper")
-	case stateRCDATA:
-		s = append(s, "exp_template_html_rcdataescaper")
-	case stateAttr:
-		// Handled below in delim check.
-	case stateAttrName, stateTag:
-		c.state = stateAttrName
-		s = append(s, "exp_template_html_htmlnamefilter")
-	default:
-		if isComment(c.state) {
-			s = append(s, "exp_template_html_commentescaper")
-		} else {
-			panic("unexpected state " + c.state.String())
-		}
-	}
-	switch c.delim {
-	case delimNone:
-		// No extra-escaping needed for raw text content.
-	case delimSpaceOrTagEnd:
-		s = append(s, "exp_template_html_nospaceescaper")
-	default:
-		s = append(s, "exp_template_html_attrescaper")
-	}
-	e.editActionNode(n, s)
-	return c
-}
-
-// ensurePipelineContains ensures that the pipeline has commands with
-// the identifiers in s in order.
-// If the pipeline already has some of the sanitizers, do not interfere.
-// For example, if p is (.X | html) and s is ["escapeJSVal", "html"] then it
-// has one matching, "html", and one to insert, "escapeJSVal", to produce
-// (.X | escapeJSVal | html).
-func ensurePipelineContains(p *parse.PipeNode, s []string) {
-	if len(s) == 0 {
-		return
-	}
-	n := len(p.Cmds)
-	// Find the identifiers at the end of the command chain.
-	idents := p.Cmds
-	for i := n - 1; i >= 0; i-- {
-		if cmd := p.Cmds[i]; len(cmd.Args) != 0 {
-			if id, ok := cmd.Args[0].(*parse.IdentifierNode); ok {
-				if id.Ident == "noescape" {
-					return
-				}
-				continue
-			}
-		}
-		idents = p.Cmds[i+1:]
-	}
-	dups := 0
-	for _, id := range idents {
-		if escFnsEq(s[dups], (id.Args[0].(*parse.IdentifierNode)).Ident) {
-			dups++
-			if dups == len(s) {
-				return
-			}
-		}
-	}
-	newCmds := make([]*parse.CommandNode, n-len(idents), n+len(s)-dups)
-	copy(newCmds, p.Cmds)
-	// Merge existing identifier commands with the sanitizers needed.
-	for _, id := range idents {
-		i := indexOfStr((id.Args[0].(*parse.IdentifierNode)).Ident, s, escFnsEq)
-		if i != -1 {
-			for _, name := range s[:i] {
-				newCmds = append(newCmds, newIdentCmd(name))
-			}
-			s = s[i+1:]
-		}
-		newCmds = append(newCmds, id)
-	}
-	// Create any remaining sanitizers.
-	for _, name := range s {
-		newCmds = append(newCmds, newIdentCmd(name))
-	}
-	p.Cmds = newCmds
-}
-
-// indexOfStr is the first i such that eq(s, strs[i]) or -1 if s was not found.
-func indexOfStr(s string, strs []string, eq func(a, b string) bool) int {
-	for i, t := range strs {
-		if eq(s, t) {
-			return i
-		}
-	}
-	return -1
-}
-
-// escFnsEq returns whether the two escaping functions are equivalent.
-func escFnsEq(a, b string) bool {
-	if e := equivEscapers[a]; e != "" {
-		a = e
-	}
-	if e := equivEscapers[b]; e != "" {
-		b = e
-	}
-	return a == b
-}
-
-// newIdentCmd produces a command containing a single identifier node.
-func newIdentCmd(identifier string) *parse.CommandNode {
-	return &parse.CommandNode{
-		NodeType: parse.NodeCommand,
-		Args:     []parse.Node{parse.NewIdentifier(identifier)},
-	}
-}
-
-// nudge returns the context that would result from following empty string
-// transitions from the input context.
-// For example, parsing:
-//     `<a href=`
-// will end in context{stateBeforeValue, attrURL}, but parsing one extra rune:
-//     `<a href=x`
-// will end in context{stateURL, delimSpaceOrTagEnd, ...}.
-// There are two transitions that happen when the 'x' is seen:
-// (1) Transition from a before-value state to a start-of-value state without
-//     consuming any character.
-// (2) Consume 'x' and transition past the first value character.
-// In this case, nudging produces the context after (1) happens.
-func nudge(c context) context {
-	switch c.state {
-	case stateTag:
-		// In `<foo {{.}}`, the action should emit an attribute.
-		c.state = stateAttrName
-	case stateBeforeValue:
-		// In `<foo bar={{.}}`, the action is an undelimited value.
-		c.state, c.delim, c.attr = attrStartStates[c.attr], delimSpaceOrTagEnd, attrNone
-	case stateAfterName:
-		// In `<foo bar {{.}}`, the action is an attribute name.
-		c.state, c.attr = stateAttrName, attrNone
-	}
-	return c
-}
-
-// join joins the two contexts of a branch template node. The result is an
-// error context if either of the input contexts are error contexts, or if the
-// the input contexts differ.
-func join(a, b context, line int, nodeName string) context {
-	if a.state == stateError {
-		return a
-	}
-	if b.state == stateError {
-		return b
-	}
-	if a.eq(b) {
-		return a
-	}
-
-	c := a
-	c.urlPart = b.urlPart
-	if c.eq(b) {
-		// The contexts differ only by urlPart.
-		c.urlPart = urlPartUnknown
-		return c
-	}
-
-	c = a
-	c.jsCtx = b.jsCtx
-	if c.eq(b) {
-		// The contexts differ only by jsCtx.
-		c.jsCtx = jsCtxUnknown
-		return c
-	}
-
-	// Allow a nudged context to join with an unnudged one.
-	// This means that
-	//   <p title={{if .C}}{{.}}{{end}}
-	// ends in an unquoted value state even though the else branch
-	// ends in stateBeforeValue.
-	if c, d := nudge(a), nudge(b); !(c.eq(a) && d.eq(b)) {
-		if e := join(c, d, line, nodeName); e.state != stateError {
-			return e
-		}
-	}
-
-	return context{
-		state: stateError,
-		err:   errorf(ErrBranchEnd, line, "{{%s}} branches end in different contexts: %v, %v", nodeName, a, b),
-	}
-}
-
-// escapeBranch escapes a branch template node: "if", "range" and "with".
-func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context {
-	c0 := e.escapeList(c, n.List)
-	if nodeName == "range" && c0.state != stateError {
-		// The "true" branch of a "range" node can execute multiple times.
-		// We check that executing n.List once results in the same context
-		// as executing n.List twice.
-		c1, _ := e.escapeListConditionally(c0, n.List, nil)
-		c0 = join(c0, c1, n.Line, nodeName)
-		if c0.state == stateError {
-			// Make clear that this is a problem on loop re-entry
-			// since developers tend to overlook that branch when
-			// debugging templates.
-			c0.err.Line = n.Line
-			c0.err.Description = "on range loop re-entry: " + c0.err.Description
-			return c0
-		}
-	}
-	c1 := e.escapeList(c, n.ElseList)
-	return join(c0, c1, n.Line, nodeName)
-}
-
-// escapeList escapes a list template node.
-func (e *escaper) escapeList(c context, n *parse.ListNode) context {
-	if n == nil {
-		return c
-	}
-	for _, m := range n.Nodes {
-		c = e.escape(c, m)
-	}
-	return c
-}
-
-// escapeListConditionally escapes a list node but only preserves edits and
-// inferences in e if the inferences and output context satisfy filter.
-// It returns the best guess at an output context, and the result of the filter
-// which is the same as whether e was updated.
-func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) {
-	e1 := newEscaper(e.set)
-	// Make type inferences available to f.
-	for k, v := range e.output {
-		e1.output[k] = v
-	}
-	c = e1.escapeList(c, n)
-	ok := filter != nil && filter(e1, c)
-	if ok {
-		// Copy inferences and edits from e1 back into e.
-		for k, v := range e1.output {
-			e.output[k] = v
-		}
-		for k, v := range e1.derived {
-			e.derived[k] = v
-		}
-		for k, v := range e1.called {
-			e.called[k] = v
-		}
-		for k, v := range e1.actionNodeEdits {
-			e.editActionNode(k, v)
-		}
-		for k, v := range e1.templateNodeEdits {
-			e.editTemplateNode(k, v)
-		}
-		for k, v := range e1.textNodeEdits {
-			e.editTextNode(k, v)
-		}
-	}
-	return c, ok
-}
-
-// escapeTemplate escapes a {{template}} call node.
-func (e *escaper) escapeTemplate(c context, n *parse.TemplateNode) context {
-	c, name := e.escapeTree(c, n.Name, n.Line)
-	if name != n.Name {
-		e.editTemplateNode(n, name)
-	}
-	return c
-}
-
-// escapeTree escapes the named template starting in the given context as
-// necessary and returns its output context.
-func (e *escaper) escapeTree(c context, name string, line int) (context, string) {
-	// Mangle the template name with the input context to produce a reliable
-	// identifier.
-	dname := c.mangle(name)
-	e.called[dname] = true
-	if out, ok := e.output[dname]; ok {
-		// Already escaped.
-		return out, dname
-	}
-	t := e.template(name)
-	if t == nil {
-		return context{
-			state: stateError,
-			err:   errorf(ErrNoSuchTemplate, line, "no such template %s", name),
-		}, dname
-	}
-	if dname != name {
-		// Use any template derived during an earlier call to EscapeSet
-		// with different top level templates, or clone if necessary.
-		dt := e.template(dname)
-		if dt == nil {
-			dt = template.New(dname)
-			dt.Tree = &parse.Tree{Name: dname, Root: cloneList(t.Root)}
-			e.derived[dname] = dt
-		}
-		t = dt
-	}
-	return e.computeOutCtx(c, t), dname
-}
-
-// computeOutCtx takes a template and its start context and computes the output
-// context while storing any inferences in e.
-func (e *escaper) computeOutCtx(c context, t *template.Template) context {
-	// Propagate context over the body.
-	c1, ok := e.escapeTemplateBody(c, t)
-	if !ok {
-		// Look for a fixed point by assuming c1 as the output context.
-		if c2, ok2 := e.escapeTemplateBody(c1, t); ok2 {
-			c1, ok = c2, true
-		}
-		// Use c1 as the error context if neither assumption worked.
-	}
-	if !ok && c1.state != stateError {
-		return context{
-			state: stateError,
-			// TODO: Find the first node with a line in t.Tree.Root
-			err: errorf(ErrOutputContext, 0, "cannot compute output context for template %s", t.Name()),
-		}
-	}
-	return c1
-}
-
-// escapeTemplateBody escapes the given template assuming the given output
-// context, and returns the best guess at the output context and whether the
-// assumption was correct.
-func (e *escaper) escapeTemplateBody(c context, t *template.Template) (context, bool) {
-	filter := func(e1 *escaper, c1 context) bool {
-		if c1.state == stateError {
-			// Do not update the input escaper, e.
-			return false
-		}
-		if !e1.called[t.Name()] {
-			// If t is not recursively called, then c1 is an
-			// accurate output context.
-			return true
-		}
-		// c1 is accurate if it matches our assumed output context.
-		return c.eq(c1)
-	}
-	// We need to assume an output context so that recursive template calls
-	// take the fast path out of escapeTree instead of infinitely recursing.
-	// Naively assuming that the input context is the same as the output
-	// works >90% of the time.
-	e.output[t.Name()] = c
-	return e.escapeListConditionally(c, t.Tree.Root, filter)
-}
-
-// delimEnds maps each delim to a string of characters that terminate it.
-var delimEnds = [...]string{
-	delimDoubleQuote: `"`,
-	delimSingleQuote: "'",
-	// Determined empirically by running the below in various browsers.
-	// var div = document.createElement("DIV");
-	// for (var i = 0; i < 0x10000; ++i) {
-	//   div.innerHTML = "<span title=x" + String.fromCharCode(i) + "-bar>";
-	//   if (div.getElementsByTagName("SPAN")[0].title.indexOf("bar") < 0)
-	//     document.write("<p>U+" + i.toString(16));
-	// }
-	delimSpaceOrTagEnd: " \t\n\f\r>",
-}
-
-// escapeText escapes a text template node.
-func (e *escaper) escapeText(c context, n *parse.TextNode) context {
-	s, written, i, b := n.Text, 0, 0, new(bytes.Buffer)
-	for i != len(s) {
-		c1, nread := contextAfterText(c, s[i:])
-		i1 := i + nread
-		if c.state == stateText || c.state == stateRCDATA {
-			end := i1
-			if c1.state != c.state {
-				for j := end - 1; j >= i; j-- {
-					if s[j] == '<' {
-						end = j
-						break
-					}
-				}
-			}
-			for j := i; j < end; j++ {
-				if s[j] == '<' {
-					b.Write(s[written:j])
-					b.WriteString("<")
-					written = j + 1
-				}
-			}
-		} else if isComment(c.state) && c.delim == delimNone {
-			switch c.state {
-			case stateJSBlockCmt:
-				// http://es5.github.com/#x7.4:
-				// "Comments behave like white space and are
-				// discarded except that, if a MultiLineComment
-				// contains a line terminator character, then
-				// the entire comment is considered to be a
-				// LineTerminator for purposes of parsing by
-				// the syntactic grammar."
-				if bytes.IndexAny(s[written:i1], "\n\r\u2028\u2029") != -1 {
-					b.WriteByte('\n')
-				} else {
-					b.WriteByte(' ')
-				}
-			case stateCSSBlockCmt:
-				b.WriteByte(' ')
-			}
-			written = i1
-		}
-		if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
-			// Preserve the portion between written and the comment start.
-			cs := i1 - 2
-			if c1.state == stateHTMLCmt {
-				// "<!--" instead of "/*" or "//"
-				cs -= 2
-			}
-			b.Write(s[written:cs])
-			written = i1
-		}
-		c, i = c1, i1
-	}
-
-	if written != 0 && c.state != stateError {
-		if !isComment(c.state) || c.delim != delimNone {
-			b.Write(n.Text[written:])
-		}
-		e.editTextNode(n, b.Bytes())
-	}
-	return c
-}
-
-// contextAfterText starts in context c, consumes some tokens from the front of
-// s, then returns the context after those tokens and the unprocessed suffix.
-func contextAfterText(c context, s []byte) (context, int) {
-	if c.delim == delimNone {
-		c1, i := tSpecialTagEnd(c, s)
-		if i == 0 {
-			// A special end tag (`</script>`) has been seen and
-			// all content preceding it has been consumed.
-			return c1, 0
-		}
-		// Consider all content up to any end tag.
-		return transitionFunc[c.state](c, s[:i])
-	}
-
-	i := bytes.IndexAny(s, delimEnds[c.delim])
-	if i == -1 {
-		// Remain inside the attribute.
-		// Decode the value so non-HTML rules can easily handle
-		//     <button onclick="alert("Hi!")">
-		// without having to entity decode token boundaries.
-		for u := []byte(html.UnescapeString(string(s))); len(u) != 0; {
-			c1, i1 := transitionFunc[c.state](c, u)
-			c, u = c1, u[i1:]
-		}
-		return c, len(s)
-	}
-	if c.delim != delimSpaceOrTagEnd {
-		// Consume any quote.
-		i++
-	}
-	// On exiting an attribute, we discard all state information
-	// except the state and element.
-	return context{state: stateTag, element: c.element}, i
-}
-
-// editActionNode records a change to an action pipeline for later commit.
-func (e *escaper) editActionNode(n *parse.ActionNode, cmds []string) {
-	if _, ok := e.actionNodeEdits[n]; ok {
-		panic(fmt.Sprintf("node %s shared between templates", n))
-	}
-	e.actionNodeEdits[n] = cmds
-}
-
-// editTemplateNode records a change to a {{template}} callee for later commit.
-func (e *escaper) editTemplateNode(n *parse.TemplateNode, callee string) {
-	if _, ok := e.templateNodeEdits[n]; ok {
-		panic(fmt.Sprintf("node %s shared between templates", n))
-	}
-	e.templateNodeEdits[n] = callee
-}
-
-// editTextNode records a change to a text node for later commit.
-func (e *escaper) editTextNode(n *parse.TextNode, text []byte) {
-	if _, ok := e.textNodeEdits[n]; ok {
-		panic(fmt.Sprintf("node %s shared between templates", n))
-	}
-	e.textNodeEdits[n] = text
-}
-
-// commit applies changes to actions and template calls needed to contextually
-// autoescape content and adds any derived templates to the set.
-func (e *escaper) commit() {
-	for name, _ := range e.output {
-		e.template(name).Funcs(funcMap)
-	}
-	for _, t := range e.derived {
-		e.set.Add(t)
-	}
-	for n, s := range e.actionNodeEdits {
-		ensurePipelineContains(n.Pipe, s)
-	}
-	for n, name := range e.templateNodeEdits {
-		n.Name = name
-	}
-	for n, s := range e.textNodeEdits {
-		n.Text = s
-	}
-}
-
-// template returns the named template given a mangled template name.
-func (e *escaper) template(name string) *template.Template {
-	t := e.set.Template(name)
-	if t == nil {
-		t = e.derived[name]
-	}
-	return t
-}
diff --git a/src/pkg/exp/template/html/escape_test.go b/src/pkg/exp/template/html/escape_test.go
deleted file mode 100644
index 8a64515..0000000
--- a/src/pkg/exp/template/html/escape_test.go
+++ /dev/null
@@ -1,1404 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"strings"
-	"template"
-	"template/parse"
-	"testing"
-)
-
-func TestEscape(t *testing.T) {
-	var data = struct {
-		F, T    bool
-		C, G, H string
-		A, E    []string
-		N       int
-		Z       *int
-		W       HTML
-	}{
-		F: false,
-		T: true,
-		C: "<Cincinatti>",
-		G: "<Goodbye>",
-		H: "<Hello>",
-		A: []string{"<a>", "<b>"},
-		E: []string{},
-		N: 42,
-		Z: nil,
-		W: HTML(`¡<b class="foo">Hello</b>, <textarea>O'World</textarea>!`),
-	}
-
-	tests := []struct {
-		name   string
-		input  string
-		output string
-	}{
-		{
-			"if",
-			"{{if .T}}Hello{{end}}, {{.C}}!",
-			"Hello, <Cincinatti>!",
-		},
-		{
-			"else",
-			"{{if .F}}{{.H}}{{else}}{{.G}}{{end}}!",
-			"<Goodbye>!",
-		},
-		{
-			"overescaping",
-			"Hello, {{.C | html}}!",
-			"Hello, <Cincinatti>!",
-		},
-		{
-			"assignment",
-			"{{if $x := .H}}{{$x}}{{end}}",
-			"<Hello>",
-		},
-		{
-			"withBody",
-			"{{with .H}}{{.}}{{end}}",
-			"<Hello>",
-		},
-		{
-			"withElse",
-			"{{with .E}}{{.}}{{else}}{{.H}}{{end}}",
-			"<Hello>",
-		},
-		{
-			"rangeBody",
-			"{{range .A}}{{.}}{{end}}",
-			"<a><b>",
-		},
-		{
-			"rangeElse",
-			"{{range .E}}{{.}}{{else}}{{.H}}{{end}}",
-			"<Hello>",
-		},
-		{
-			"nonStringValue",
-			"{{.T}}",
-			"true",
-		},
-		{
-			"constant",
-			`<a href="/search?q={{"'a<b'"}}">`,
-			`<a href="/search?q=%27a%3cb%27">`,
-		},
-		{
-			"multipleAttrs",
-			"<a b=1 c={{.H}}>",
-			"<a b=1 c=<Hello>>",
-		},
-		{
-			"urlStartRel",
-			`<a href='{{"/foo/bar?a=b&c=d"}}'>`,
-			`<a href='/foo/bar?a=b&c=d'>`,
-		},
-		{
-			"urlStartAbsOk",
-			`<a href='{{"http://example.com/foo/bar?a=b&c=d"}}'>`,
-			`<a href='http://example.com/foo/bar?a=b&c=d'>`,
-		},
-		{
-			"protocolRelativeURLStart",
-			`<a href='{{"//example.com:8000/foo/bar?a=b&c=d"}}'>`,
-			`<a href='//example.com:8000/foo/bar?a=b&c=d'>`,
-		},
-		{
-			"pathRelativeURLStart",
-			`<a href="{{"/javascript:80/foo/bar"}}">`,
-			`<a href="/javascript:80/foo/bar">`,
-		},
-		{
-			"dangerousURLStart",
-			`<a href='{{"javascript:alert(%22pwned%22)"}}'>`,
-			`<a href='#ZgotmplZ'>`,
-		},
-		{
-			"dangerousURLStart2",
-			`<a href='  {{"javascript:alert(%22pwned%22)"}}'>`,
-			`<a href='  #ZgotmplZ'>`,
-		},
-		{
-			"nonHierURL",
-			`<a href={{"mailto:Muhammed \"The Greatest\" Ali <m.ali at example.com>"}}>`,
-			`<a href=mailto:Muhammed "The Greatest" Ali <m.ali at example.com>>`,
-		},
-		{
-			"urlPath",
-			`<a href='http://{{"javascript:80"}}/foo'>`,
-			`<a href='http://javascript:80/foo'>`,
-		},
-		{
-			"urlQuery",
-			`<a href='/search?q={{.H}}'>`,
-			`<a href='/search?q=%3cHello%3e'>`,
-		},
-		{
-			"urlFragment",
-			`<a href='/faq#{{.H}}'>`,
-			`<a href='/faq#%3cHello%3e'>`,
-		},
-		{
-			"urlBranch",
-			`<a href="{{if .F}}/foo?a=b{{else}}/bar{{end}}">`,
-			`<a href="/bar">`,
-		},
-		{
-			"urlBranchConflictMoot",
-			`<a href="{{if .T}}/foo?a={{else}}/bar#{{end}}{{.C}}">`,
-			`<a href="/foo?a=%3cCincinatti%3e">`,
-		},
-		{
-			"jsStrValue",
-			"<button onclick='alert({{.H}})'>",
-			`<button onclick='alert("\u003cHello\u003e")'>`,
-		},
-		{
-			"jsNumericValue",
-			"<button onclick='alert({{.N}})'>",
-			`<button onclick='alert( 42 )'>`,
-		},
-		{
-			"jsBoolValue",
-			"<button onclick='alert({{.T}})'>",
-			`<button onclick='alert( true )'>`,
-		},
-		{
-			"jsNilValue",
-			"<button onclick='alert(typeof{{.Z}})'>",
-			`<button onclick='alert(typeof null )'>`,
-		},
-		{
-			"jsObjValue",
-			"<button onclick='alert({{.A}})'>",
-			`<button onclick='alert(["\u003ca\u003e","\u003cb\u003e"])'>`,
-		},
-		{
-			"jsObjValueScript",
-			"<script>alert({{.A}})</script>",
-			`<script>alert(["\u003ca\u003e","\u003cb\u003e"])</script>`,
-		},
-		{
-			"jsObjValueNotOverEscaped",
-			"<button onclick='alert({{.A | html}})'>",
-			`<button onclick='alert(["\u003ca\u003e","\u003cb\u003e"])'>`,
-		},
-		{
-			"jsStr",
-			"<button onclick='alert("{{.H}}")'>",
-			`<button onclick='alert("\x3cHello\x3e")'>`,
-		},
-		{
-			"jsStrNotUnderEscaped",
-			"<button onclick='alert({{.C | urlquery}})'>",
-			// URL escaped, then quoted for JS.
-			`<button onclick='alert("%3CCincinatti%3E")'>`,
-		},
-		{
-			"jsRe",
-			`<button onclick='alert(/{{"foo+bar"}}/.test(""))'>`,
-			`<button onclick='alert(/foo\x2bbar/.test(""))'>`,
-		},
-		{
-			"jsReBlank",
-			`<script>alert(/{{""}}/.test(""));</script>`,
-			`<script>alert(/(?:)/.test(""));</script>`,
-		},
-		{
-			"jsReAmbigOk",
-			`<script>{{if true}}var x = 1{{end}}</script>`,
-			// The {if} ends in an ambiguous jsCtx but there is
-			// no slash following so we shouldn't care.
-			`<script>var x = 1</script>`,
-		},
-		{
-			"styleBidiKeywordPassed",
-			`<p style="dir: {{"ltr"}}">`,
-			`<p style="dir: ltr">`,
-		},
-		{
-			"styleBidiPropNamePassed",
-			`<p style="border-{{"left"}}: 0; border-{{"right"}}: 1in">`,
-			`<p style="border-left: 0; border-right: 1in">`,
-		},
-		{
-			"styleExpressionBlocked",
-			`<p style="width: {{"expression(alert(1337))"}}">`,
-			`<p style="width: ZgotmplZ">`,
-		},
-		{
-			"styleTagSelectorPassed",
-			`<style>{{"p"}} { color: pink }</style>`,
-			`<style>p { color: pink }</style>`,
-		},
-		{
-			"styleIDPassed",
-			`<style>p{{"#my-ID"}} { font: Arial }</style>`,
-			`<style>p#my-ID { font: Arial }</style>`,
-		},
-		{
-			"styleClassPassed",
-			`<style>p{{".my_class"}} { font: Arial }</style>`,
-			`<style>p.my_class { font: Arial }</style>`,
-		},
-		{
-			"styleQuantityPassed",
-			`<a style="left: {{"2em"}}; top: {{0}}">`,
-			`<a style="left: 2em; top: 0">`,
-		},
-		{
-			"stylePctPassed",
-			`<table style=width:{{"100%"}}>`,
-			`<table style=width:100%>`,
-		},
-		{
-			"styleColorPassed",
-			`<p style="color: {{"#8ff"}}; background: {{"#000"}}">`,
-			`<p style="color: #8ff; background: #000">`,
-		},
-		{
-			"styleObfuscatedExpressionBlocked",
-			`<p style="width: {{"  e\78preS\0Sio/**/n(alert(1337))"}}">`,
-			`<p style="width: ZgotmplZ">`,
-		},
-		{
-			"styleMozBindingBlocked",
-			`<p style="{{"-moz-binding(alert(1337))"}}: ...">`,
-			`<p style="ZgotmplZ: ...">`,
-		},
-		{
-			"styleObfuscatedMozBindingBlocked",
-			`<p style="{{"  -mo\7a-B\0I/**/nding(alert(1337))"}}: ...">`,
-			`<p style="ZgotmplZ: ...">`,
-		},
-		{
-			"styleFontNameString",
-			`<p style='font-family: "{{"Times New Roman"}}"'>`,
-			`<p style='font-family: "Times New Roman"'>`,
-		},
-		{
-			"styleFontNameString",
-			`<p style='font-family: "{{"Times New Roman"}}", "{{"sans-serif"}}"'>`,
-			`<p style='font-family: "Times New Roman", "sans-serif"'>`,
-		},
-		{
-			"styleFontNameUnquoted",
-			`<p style='font-family: {{"Times New Roman"}}'>`,
-			`<p style='font-family: Times New Roman'>`,
-		},
-		{
-			"styleURLQueryEncoded",
-			`<p style="background: url(/img?name={{"O'Reilly Animal(1)<2>.png"}})">`,
-			`<p style="background: url(/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png)">`,
-		},
-		{
-			"styleQuotedURLQueryEncoded",
-			`<p style="background: url('/img?name={{"O'Reilly Animal(1)<2>.png"}}')">`,
-			`<p style="background: url('/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png')">`,
-		},
-		{
-			"styleStrQueryEncoded",
-			`<p style="background: '/img?name={{"O'Reilly Animal(1)<2>.png"}}'">`,
-			`<p style="background: '/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png'">`,
-		},
-		{
-			"styleURLBadProtocolBlocked",
-			`<a style="background: url('{{"javascript:alert(1337)"}}')">`,
-			`<a style="background: url('#ZgotmplZ')">`,
-		},
-		{
-			"styleStrBadProtocolBlocked",
-			`<a style="background: '{{"javascript:alert(1337)"}}'">`,
-			`<a style="background: '#ZgotmplZ'">`,
-		},
-		{
-			"styleURLGoodProtocolPassed",
-			`<a style="background: url('{{"http://oreilly.com/O'Reilly Animals(1)<2>;{}.html"}}')">`,
-			`<a style="background: url('http://oreilly.com/O%27Reilly%20Animals%281%29%3c2%3e;%7b%7d.html')">`,
-		},
-		{
-			"styleStrGoodProtocolPassed",
-			`<a style="background: '{{"http://oreilly.com/O'Reilly Animals(1)<2>;{}.html"}}'">`,
-			`<a style="background: 'http\3a\2f\2foreilly.com\2fO\27Reilly Animals\28 1\29\3c 2\3e\3b\7b\7d.html'">`,
-		},
-		{
-			"styleURLEncodedForHTMLInAttr",
-			`<a style="background: url('{{"/search?img=foo&size=icon"}}')">`,
-			`<a style="background: url('/search?img=foo&size=icon')">`,
-		},
-		{
-			"styleURLNotEncodedForHTMLInCdata",
-			`<style>body { background: url('{{"/search?img=foo&size=icon"}}') }</style>`,
-			`<style>body { background: url('/search?img=foo&size=icon') }</style>`,
-		},
-		{
-			"styleURLMixedCase",
-			`<p style="background: URL(#{{.H}})">`,
-			`<p style="background: URL(#%3cHello%3e)">`,
-		},
-		{
-			"stylePropertyPairPassed",
-			`<a style='{{"color: red"}}'>`,
-			`<a style='color: red'>`,
-		},
-		{
-			"styleStrSpecialsEncoded",
-			`<a style="font-family: '{{"/**/'\";:// \\"}}', "{{"/**/'\";:// \\"}}"">`,
-			`<a style="font-family: '\2f**\2f\27\22\3b\3a\2f\2f \\', "\2f**\2f\27\22\3b\3a\2f\2f \\"">`,
-		},
-		{
-			"styleURLSpecialsEncoded",
-			// TODO: Find out what IE does with url(/*foo*/bar)
-			// FF, Chrome, and Safari seem to treat it as a URL.
-			`<a style="border-image: url({{"/**/'\";:// \\"}}), url("{{"/**/'\";:// \\"}}"), url('{{"/**/'\";:// \\"}}'), 'http://www.example.com/?q={{"/**/'\";:// \\"}}''">`,
-			`<a style="border-image: url(/**/%27%22;://%20%5c), url("/**/%27%22;://%20%5c"), url('/**/%27%22;://%20%5c'), 'http://www.example.com/?q=%2f%2a%2a%2f%27%22%3b%3a%2f%2f%20%5c''">`,
-		},
-		{
-			"HTML comment",
-			"<b>Hello, <!-- name of world -->{{.C}}</b>",
-			"<b>Hello, <Cincinatti></b>",
-		},
-		{
-			"HTML comment not first < in text node.",
-			"<<!-- -->!--",
-			"<!--",
-		},
-		{
-			"HTML normalization 1",
-			"a < b",
-			"a < b",
-		},
-		{
-			"HTML normalization 2",
-			"a << b",
-			"a << b",
-		},
-		{
-			"HTML normalization 3",
-			"a<<!-- --><!-- -->b",
-			"a<b",
-		},
-		{
-			"Split HTML comment",
-			"<b>Hello, <!-- name of {{if .T}}city -->{{.C}}{{else}}world -->{{.W}}{{end}}</b>",
-			"<b>Hello, <Cincinatti></b>",
-		},
-		{
-			"JS line comment",
-			"<script>for (;;) { if (c()) break// foo not a label\n" +
-				"foo({{.T}});}</script>",
-			"<script>for (;;) { if (c()) break\n" +
-				"foo( true );}</script>",
-		},
-		{
-			"JS multiline block comment",
-			"<script>for (;;) { if (c()) break/* foo not a label\n" +
-				" */foo({{.T}});}</script>",
-			// Newline separates break from call. If newline
-			// removed, then break will consume label leaving
-			// code invalid.
-			"<script>for (;;) { if (c()) break\n" +
-				"foo( true );}</script>",
-		},
-		{
-			"JS single-line block comment",
-			"<script>for (;;) {\n" +
-				"if (c()) break/* foo a label */foo;" +
-				"x({{.T}});}</script>",
-			// Newline separates break from call. If newline
-			// removed, then break will consume label leaving
-			// code invalid.
-			"<script>for (;;) {\n" +
-				"if (c()) break foo;" +
-				"x( true );}</script>",
-		},
-		{
-			"JS block comment flush with mathematical division",
-			"<script>var a/*b*//c\nd</script>",
-			"<script>var a /c\nd</script>",
-		},
-		{
-			"JS mixed comments",
-			"<script>var a/*b*///c\nd</script>",
-			"<script>var a \nd</script>",
-		},
-		{
-			"CSS comments",
-			"<style>p// paragraph\n" +
-				`{border: 1px/* color */{{"#00f"}}}</style>`,
-			"<style>p\n" +
-				"{border: 1px #00f}</style>",
-		},
-		{
-			"JS attr block comment",
-			`<a onclick="f(""); /* alert({{.H}}) */">`,
-			// Attribute comment tests should pass if the comments
-			// are successfully elided.
-			`<a onclick="f(""); /* alert() */">`,
-		},
-		{
-			"JS attr line comment",
-			`<a onclick="// alert({{.G}})">`,
-			`<a onclick="// alert()">`,
-		},
-		{
-			"CSS attr block comment",
-			`<a style="/* color: {{.H}} */">`,
-			`<a style="/* color:  */">`,
-		},
-		{
-			"CSS attr line comment",
-			`<a style="// color: {{.G}}">`,
-			`<a style="// color: ">`,
-		},
-		{
-			"HTML substitution commented out",
-			"<p><!-- {{.H}} --></p>",
-			"<p></p>",
-		},
-		{
-			"Comment ends flush with start",
-			"<!--{{.}}--><script>/*{{.}}*///{{.}}\n</script><style>/*{{.}}*///{{.}}\n</style><a onclick='/*{{.}}*///{{.}}' style='/*{{.}}*///{{.}}'>",
-			"<script> \n</script><style> \n</style><a onclick='/**///' style='/**///'>",
-		},
-		{
-			"typed HTML in text",
-			`{{.W}}`,
-			`¡<b class="foo">Hello</b>, <textarea>O'World</textarea>!`,
-		},
-		{
-			"typed HTML in attribute",
-			`<div title="{{.W}}">`,
-			`<div title="¡Hello, O'World!">`,
-		},
-		{
-			"typed HTML in script",
-			`<button onclick="alert({{.W}})">`,
-			`<button onclick="alert("&iexcl;\u003cb class=\"foo\"\u003eHello\u003c/b\u003e, \u003ctextarea\u003eO'World\u003c/textarea\u003e!")">`,
-		},
-		{
-			"typed HTML in RCDATA",
-			`<textarea>{{.W}}</textarea>`,
-			`<textarea>¡<b class="foo">Hello</b>, <textarea>O'World</textarea>!</textarea>`,
-		},
-		{
-			"range in textarea",
-			"<textarea>{{range .A}}{{.}}{{end}}</textarea>",
-			"<textarea><a><b></textarea>",
-		},
-		{
-			"auditable exemption from escaping",
-			"{{range .A}}{{. | noescape}}{{end}}",
-			"<a><b>",
-		},
-		{
-			"No tag injection",
-			`{{"10$"}}<{{"script src,evil.org/pwnd.js"}}...`,
-			`10$<script src,evil.org/pwnd.js...`,
-		},
-		{
-			"No comment injection",
-			`<{{"!--"}}`,
-			`<!--`,
-		},
-		{
-			"No RCDATA end tag injection",
-			`<textarea><{{"/textarea "}}...</textarea>`,
-			`<textarea></textarea ...</textarea>`,
-		},
-		{
-			"optional attrs",
-			`<img class="{{"iconClass"}}"` +
-				`{{if .T}} id="{{"<iconId>"}}"{{end}}` +
-				// Double quotes inside if/else.
-				` src=` +
-				`{{if .T}}"?{{"<iconPath>"}}"` +
-				`{{else}}"images/cleardot.gif"{{end}}` +
-				// Missing space before title, but it is not a
-				// part of the src attribute.
-				`{{if .T}}title="{{"<title>"}}"{{end}}` +
-				// Quotes outside if/else.
-				` alt="` +
-				`{{if .T}}{{"<alt>"}}` +
-				`{{else}}{{if .F}}{{"<title>"}}{{end}}` +
-				`{{end}}"` +
-				`>`,
-			`<img class="iconClass" id="<iconId>" src="?%3ciconPath%3e"title="<title>" alt="<alt>">`,
-		},
-		{
-			"conditional valueless attr name",
-			`<input{{if .T}} checked{{end}} name=n>`,
-			`<input checked name=n>`,
-		},
-		{
-			"conditional dynamic valueless attr name 1",
-			`<input{{if .T}} {{"checked"}}{{end}} name=n>`,
-			`<input checked name=n>`,
-		},
-		{
-			"conditional dynamic valueless attr name 2",
-			`<input {{if .T}}{{"checked"}} {{end}}name=n>`,
-			`<input checked name=n>`,
-		},
-		{
-			"dynamic attribute name",
-			`<img on{{"load"}}="alert({{"loaded"}})">`,
-			// Treated as JS since quotes are inserted.
-			`<img onload="alert("loaded")">`,
-		},
-		{
-			"dynamic element name",
-			`<h{{3}}><table><t{{"head"}}>...</h{{3}}>`,
-			`<h3><table><thead>...</h3>`,
-		},
-	}
-
-	for _, test := range tests {
-		tmpl := template.New(test.name)
-		// TODO: Move noescape into template/func.go
-		tmpl.Funcs(template.FuncMap{
-			"noescape": func(a ...interface{}) string {
-				return fmt.Sprint(a...)
-			},
-		})
-		tmpl = template.Must(Escape(template.Must(tmpl.Parse(test.input))))
-		b := new(bytes.Buffer)
-		if err := tmpl.Execute(b, data); err != nil {
-			t.Errorf("%s: template execution failed: %s", test.name, err)
-			continue
-		}
-		if w, g := test.output, b.String(); w != g {
-			t.Errorf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
-			continue
-		}
-	}
-}
-
-func TestEscapeSet(t *testing.T) {
-	type dataItem struct {
-		Children []*dataItem
-		X        string
-	}
-
-	data := dataItem{
-		Children: []*dataItem{
-			&dataItem{X: "foo"},
-			&dataItem{X: "<bar>"},
-			&dataItem{
-				Children: []*dataItem{
-					&dataItem{X: "baz"},
-				},
-			},
-		},
-	}
-
-	tests := []struct {
-		inputs map[string]string
-		want   string
-	}{
-		// The trivial set.
-		{
-			map[string]string{
-				"main": ``,
-			},
-			``,
-		},
-		// A template called in the start context.
-		{
-			map[string]string{
-				"main": `Hello, {{template "helper"}}!`,
-				// Not a valid top level HTML template.
-				// "<b" is not a full tag.
-				"helper": `{{"<World>"}}`,
-			},
-			`Hello, <World>!`,
-		},
-		// A template called in a context other than the start.
-		{
-			map[string]string{
-				"main": `<a onclick='a = {{template "helper"}};'>`,
-				// Not a valid top level HTML template.
-				// "<b" is not a full tag.
-				"helper": `{{"<a>"}}<b`,
-			},
-			`<a onclick='a = "\u003ca\u003e"<b;'>`,
-		},
-		// A recursive template that ends in its start context.
-		{
-			map[string]string{
-				"main": `{{range .Children}}{{template "main" .}}{{else}}{{.X}} {{end}}`,
-			},
-			`foo <bar> baz `,
-		},
-		// A recursive helper template that ends in its start context.
-		{
-			map[string]string{
-				"main":   `{{template "helper" .}}`,
-				"helper": `{{if .Children}}<ul>{{range .Children}}<li>{{template "main" .}}</li>{{end}}</ul>{{else}}{{.X}}{{end}}`,
-			},
-			`<ul><li>foo</li><li><bar></li><li><ul><li>baz</li></ul></li></ul>`,
-		},
-		// Co-recursive templates that end in its start context.
-		{
-			map[string]string{
-				"main":   `<blockquote>{{range .Children}}{{template "helper" .}}{{end}}</blockquote>`,
-				"helper": `{{if .Children}}{{template "main" .}}{{else}}{{.X}}<br>{{end}}`,
-			},
-			`<blockquote>foo<br><bar><br><blockquote>baz<br></blockquote></blockquote>`,
-		},
-		// A template that is called in two different contexts.
-		{
-			map[string]string{
-				"main":   `<button onclick="title='{{template "helper"}}'; ...">{{template "helper"}}</button>`,
-				"helper": `{{11}} of {{"<100>"}}`,
-			},
-			`<button onclick="title='11 of \x3c100\x3e'; ...">11 of <100></button>`,
-		},
-		// A non-recursive template that ends in a different context.
-		// helper starts in jsCtxRegexp and ends in jsCtxDivOp.
-		{
-			map[string]string{
-				"main":   `<script>var x={{template "helper"}}/{{"42"}};</script>`,
-				"helper": "{{126}}",
-			},
-			`<script>var x= 126 /"42";</script>`,
-		},
-		// A recursive template that ends in a similar context.
-		{
-			map[string]string{
-				"main":      `<script>var x=[{{template "countdown" 4}}];</script>`,
-				"countdown": `{{.}}{{if .}},{{template "countdown" . | pred}}{{end}}`,
-			},
-			`<script>var x=[ 4 , 3 , 2 , 1 , 0 ];</script>`,
-		},
-		// A recursive template that ends in a different context.
-		/*
-			{
-				map[string]string{
-					"main":   `<a href="/foo{{template "helper" .}}">`,
-					"helper": `{{if .Children}}{{range .Children}}{{template "helper" .}}{{end}}{{else}}?x={{.X}}{{end}}`,
-				},
-				`<a href="/foo?x=foo?x=%3cbar%3e?x=baz">`,
-			},
-		*/
-	}
-
-	// pred is a template function that returns the predecessor of a
-	// natural number for testing recursive templates.
-	fns := template.FuncMap{"pred": func(a ...interface{}) (interface{}, os.Error) {
-		if len(a) == 1 {
-			if i, _ := a[0].(int); i > 0 {
-				return i - 1, nil
-			}
-		}
-		return nil, fmt.Errorf("undefined pred(%v)", a)
-	}}
-
-	for _, test := range tests {
-		var s template.Set
-		for name, src := range test.inputs {
-			t := template.New(name)
-			t.Funcs(fns)
-			s.Add(template.Must(t.Parse(src)))
-		}
-		s.Funcs(fns)
-		if _, err := EscapeSet(&s, "main"); err != nil {
-			t.Errorf("%s for input:\n%v", err, test.inputs)
-			continue
-		}
-		var b bytes.Buffer
-
-		if err := s.Execute(&b, "main", data); err != nil {
-			t.Errorf("%q executing %v", err.String(), s.Template("main"))
-			continue
-		}
-		if got := b.String(); test.want != got {
-			t.Errorf("want\n\t%q\ngot\n\t%q", test.want, got)
-		}
-	}
-
-}
-
-func TestErrors(t *testing.T) {
-	tests := []struct {
-		input string
-		err   string
-	}{
-		// Non-error cases.
-		{
-			"{{if .Cond}}<a>{{else}}<b>{{end}}",
-			"",
-		},
-		{
-			"{{if .Cond}}<a>{{end}}",
-			"",
-		},
-		{
-			"{{if .Cond}}{{else}}<b>{{end}}",
-			"",
-		},
-		{
-			"{{with .Cond}}<div>{{end}}",
-			"",
-		},
-		{
-			"{{range .Items}}<a>{{end}}",
-			"",
-		},
-		{
-			"<a href='/foo?{{range .Items}}&{{.K}}={{.V}}{{end}}'>",
-			"",
-		},
-		// Error cases.
-		{
-			"{{if .Cond}}<a{{end}}",
-			"z:1: {{if}} branches",
-		},
-		{
-			"{{if .Cond}}\n{{else}}\n<a{{end}}",
-			"z:1: {{if}} branches",
-		},
-		{
-			// Missing quote in the else branch.
-			`{{if .Cond}}<a href="foo">{{else}}<a href="bar>{{end}}`,
-			"z:1: {{if}} branches",
-		},
-		{
-			// Different kind of attribute: href implies a URL.
-			"<a {{if .Cond}}href='{{else}}title='{{end}}{{.X}}'>",
-			"z:1: {{if}} branches",
-		},
-		{
-			"\n{{with .X}}<a{{end}}",
-			"z:2: {{with}} branches",
-		},
-		{
-			"\n{{with .X}}<a>{{else}}<a{{end}}",
-			"z:2: {{with}} branches",
-		},
-		{
-			"{{range .Items}}<a{{end}}",
-			`z:1: on range loop re-entry: "<" in attribute name: "<a"`,
-		},
-		{
-			"\n{{range .Items}} x='<a{{end}}",
-			"z:2: on range loop re-entry: {{range}} branches",
-		},
-		{
-			"<a b=1 c={{.H}}",
-			"z: ends in a non-text context: {stateAttr delimSpaceOrTagEnd",
-		},
-		{
-			"<script>foo();",
-			"z: ends in a non-text context: {stateJS",
-		},
-		{
-			`<a href="{{if .F}}/foo?a={{else}}/bar/{{end}}{{.H}}">`,
-			"z:1: (action: [(command: [F=[H]])]) appears in an ambiguous URL context",
-		},
-		{
-			`<a onclick="alert('Hello \`,
-			`unfinished escape sequence in JS string: "Hello \\"`,
-		},
-		{
-			`<a onclick='alert("Hello\, World\`,
-			`unfinished escape sequence in JS string: "Hello\\, World\\"`,
-		},
-		{
-			`<a onclick='alert(/x+\`,
-			`unfinished escape sequence in JS string: "x+\\"`,
-		},
-		{
-			`<a onclick="/foo[\]/`,
-			`unfinished JS regexp charset: "foo[\\]/"`,
-		},
-		{
-			// It is ambiguous whether 1.5 should be 1\.5 or 1.5.
-			// Either `var x = 1/- 1.5 /i.test(x)`
-			// where `i.test(x)` is a method call of reference i,
-			// or `/-1\.5/i.test(x)` which is a method call on a
-			// case insensitive regular expression.
-			`<script>{{if false}}var x = 1{{end}}/-{{"1.5"}}/i.test(x)</script>`,
-			`'/' could start div or regexp: "/-"`,
-		},
-		{
-			`{{template "foo"}}`,
-			"z:1: no such template foo",
-		},
-		{
-			`{{define "z"}}<div{{template "y"}}>{{end}}` +
-				// Illegal starting in stateTag but not in stateText.
-				`{{define "y"}} foo<b{{end}}`,
-			`"<" in attribute name: " foo<b"`,
-		},
-		{
-			`{{define "z"}}<script>reverseList = [{{template "t"}}]</script>{{end}}` +
-				// Missing " after recursive call.
-				`{{define "t"}}{{if .Tail}}{{template "t" .Tail}}{{end}}{{.Head}}",{{end}}`,
-			`: cannot compute output context for template t$htmltemplate_stateJS_elementScript`,
-		},
-	}
-
-	for _, test := range tests {
-		var err os.Error
-		if strings.HasPrefix(test.input, "{{define") {
-			var s template.Set
-			_, err = s.Parse(test.input)
-			if err != nil {
-				t.Errorf("Failed to parse %q: %s", test.input, err)
-				continue
-			}
-			_, err = EscapeSet(&s, "z")
-		} else {
-			tmpl := template.Must(template.New("z").Parse(test.input))
-			_, err = Escape(tmpl)
-		}
-		var got string
-		if err != nil {
-			got = err.String()
-		}
-		if test.err == "" {
-			if got != "" {
-				t.Errorf("input=%q: unexpected error %q", test.input, got)
-			}
-			continue
-		}
-		if strings.Index(got, test.err) == -1 {
-			t.Errorf("input=%q: error\n\t%q\ndoes not contain expected string\n\t%q", test.input, got, test.err)
-			continue
-		}
-	}
-}
-
-func TestEscapeText(t *testing.T) {
-	tests := []struct {
-		input  string
-		output context
-	}{
-		{
-			``,
-			context{},
-		},
-		{
-			`Hello, World!`,
-			context{},
-		},
-		{
-			// An orphaned "<" is OK.
-			`I <3 Ponies!`,
-			context{},
-		},
-		{
-			`<a`,
-			context{state: stateTag},
-		},
-		{
-			`<a `,
-			context{state: stateTag},
-		},
-		{
-			`<a>`,
-			context{state: stateText},
-		},
-		{
-			`<a href`,
-			context{state: stateAttrName, attr: attrURL},
-		},
-		{
-			`<a on`,
-			context{state: stateAttrName, attr: attrScript},
-		},
-		{
-			`<a href `,
-			context{state: stateAfterName, attr: attrURL},
-		},
-		{
-			`<a style  =  `,
-			context{state: stateBeforeValue, attr: attrStyle},
-		},
-		{
-			`<a href=`,
-			context{state: stateBeforeValue, attr: attrURL},
-		},
-		{
-			`<a href=x`,
-			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a href=x `,
-			context{state: stateTag},
-		},
-		{
-			`<a href=>`,
-			context{state: stateText},
-		},
-		{
-			`<a href=x>`,
-			context{state: stateText},
-		},
-		{
-			`<a href ='`,
-			context{state: stateURL, delim: delimSingleQuote},
-		},
-		{
-			`<a href=''`,
-			context{state: stateTag},
-		},
-		{
-			`<a href= "`,
-			context{state: stateURL, delim: delimDoubleQuote},
-		},
-		{
-			`<a href=""`,
-			context{state: stateTag},
-		},
-		{
-			`<a title="`,
-			context{state: stateAttr, delim: delimDoubleQuote},
-		},
-		{
-			`<a HREF='http:`,
-			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a Href='/`,
-			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a href='"`,
-			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a href="'`,
-			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a href=''`,
-			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a href=""`,
-			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a href=""`,
-			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a href="`,
-			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
-		},
-		{
-			`<img alt="1">`,
-			context{state: stateText},
-		},
-		{
-			`<img alt="1>"`,
-			context{state: stateTag},
-		},
-		{
-			`<img alt="1>">`,
-			context{state: stateText},
-		},
-		{
-			`<input checked type="checkbox"`,
-			context{state: stateTag},
-		},
-		{
-			`<a onclick="`,
-			context{state: stateJS, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="//foo`,
-			context{state: stateJSLineCmt, delim: delimDoubleQuote},
-		},
-		{
-			"<a onclick='//\n",
-			context{state: stateJS, delim: delimSingleQuote},
-		},
-		{
-			"<a onclick='//\r\n",
-			context{state: stateJS, delim: delimSingleQuote},
-		},
-		{
-			"<a onclick='//\u2028",
-			context{state: stateJS, delim: delimSingleQuote},
-		},
-		{
-			`<a onclick="/*`,
-			context{state: stateJSBlockCmt, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="/*/`,
-			context{state: stateJSBlockCmt, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="/**/`,
-			context{state: stateJS, delim: delimDoubleQuote},
-		},
-		{
-			`<a onkeypress=""`,
-			context{state: stateJSDqStr, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick='"foo"`,
-			context{state: stateJS, delim: delimSingleQuote, jsCtx: jsCtxDivOp},
-		},
-		{
-			`<a onclick='foo'`,
-			context{state: stateJS, delim: delimSpaceOrTagEnd, jsCtx: jsCtxDivOp},
-		},
-		{
-			`<a onclick='foo`,
-			context{state: stateJSSqStr, delim: delimSpaceOrTagEnd},
-		},
-		{
-			`<a onclick=""foo'`,
-			context{state: stateJSDqStr, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="'foo"`,
-			context{state: stateJSSqStr, delim: delimDoubleQuote},
-		},
-		{
-			`<A ONCLICK="'`,
-			context{state: stateJSSqStr, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="/`,
-			context{state: stateJSRegexp, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="'foo'`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
-		},
-		{
-			`<a onclick="'foo\'`,
-			context{state: stateJSSqStr, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="'foo\'`,
-			context{state: stateJSSqStr, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="/foo/`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
-		},
-		{
-			`<script>/foo/ /=`,
-			context{state: stateJS, element: elementScript},
-		},
-		{
-			`<a onclick="1 /foo`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
-		},
-		{
-			`<a onclick="1 /*c*/ /foo`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
-		},
-		{
-			`<a onclick="/foo[/]`,
-			context{state: stateJSRegexp, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="/foo\/`,
-			context{state: stateJSRegexp, delim: delimDoubleQuote},
-		},
-		{
-			`<a onclick="/foo/`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
-		},
-		{
-			`<input checked style="`,
-			context{state: stateCSS, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="//`,
-			context{state: stateCSSLineCmt, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="//</script>`,
-			context{state: stateCSSLineCmt, delim: delimDoubleQuote},
-		},
-		{
-			"<a style='//\n",
-			context{state: stateCSS, delim: delimSingleQuote},
-		},
-		{
-			"<a style='//\r",
-			context{state: stateCSS, delim: delimSingleQuote},
-		},
-		{
-			`<a style="/*`,
-			context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="/*/`,
-			context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="/**/`,
-			context{state: stateCSS, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="background: '`,
-			context{state: stateCSSSqStr, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="background: "`,
-			context{state: stateCSSDqStr, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="background: '/foo?img=`,
-			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
-		},
-		{
-			`<a style="background: '/`,
-			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a style="background: url(&#x22;/`,
-			context{state: stateCSSDqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a style="background: url('/`,
-			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a style="background: url('/)`,
-			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a style="background: url('/ `,
-			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a style="background: url(/`,
-			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
-		},
-		{
-			`<a style="background: url( `,
-			context{state: stateCSSURL, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="background: url( /image?name=`,
-			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
-		},
-		{
-			`<a style="background: url(x)`,
-			context{state: stateCSS, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="background: url('x'`,
-			context{state: stateCSS, delim: delimDoubleQuote},
-		},
-		{
-			`<a style="background: url( x `,
-			context{state: stateCSS, delim: delimDoubleQuote},
-		},
-		{
-			`<!-- foo`,
-			context{state: stateHTMLCmt},
-		},
-		{
-			`<!-->`,
-			context{state: stateHTMLCmt},
-		},
-		{
-			`<!--->`,
-			context{state: stateHTMLCmt},
-		},
-		{
-			`<!-- foo -->`,
-			context{state: stateText},
-		},
-		{
-			`<script`,
-			context{state: stateTag, element: elementScript},
-		},
-		{
-			`<script `,
-			context{state: stateTag, element: elementScript},
-		},
-		{
-			`<script src="foo.js" `,
-			context{state: stateTag, element: elementScript},
-		},
-		{
-			`<script src='foo.js' `,
-			context{state: stateTag, element: elementScript},
-		},
-		{
-			`<script type=text/javascript `,
-			context{state: stateTag, element: elementScript},
-		},
-		{
-			`<script>foo`,
-			context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
-		},
-		{
-			`<script>foo</script>`,
-			context{state: stateText},
-		},
-		{
-			`<script>foo</script><!--`,
-			context{state: stateHTMLCmt},
-		},
-		{
-			`<script>document.write("<p>foo</p>");`,
-			context{state: stateJS, element: elementScript},
-		},
-		{
-			`<script>document.write("<p>foo<\/script>");`,
-			context{state: stateJS, element: elementScript},
-		},
-		{
-			`<script>document.write("<script>alert(1)</script>");`,
-			context{state: stateText},
-		},
-		{
-			`<Script>`,
-			context{state: stateJS, element: elementScript},
-		},
-		{
-			`<SCRIPT>foo`,
-			context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
-		},
-		{
-			`<textarea>value`,
-			context{state: stateRCDATA, element: elementTextarea},
-		},
-		{
-			`<textarea>value</TEXTAREA>`,
-			context{state: stateText},
-		},
-		{
-			`<textarea name=html><b`,
-			context{state: stateRCDATA, element: elementTextarea},
-		},
-		{
-			`<title>value`,
-			context{state: stateRCDATA, element: elementTitle},
-		},
-		{
-			`<style>value`,
-			context{state: stateCSS, element: elementStyle},
-		},
-	}
-
-	for _, test := range tests {
-		b, e := []byte(test.input), newEscaper(nil)
-		c := e.escapeText(context{}, &parse.TextNode{parse.NodeText, b})
-		if !test.output.eq(c) {
-			t.Errorf("input %q: want context\n\t%v\ngot\n\t%v", test.input, test.output, c)
-			continue
-		}
-		if test.input != string(b) {
-			t.Errorf("input %q: text node was modified: want %q got %q", test.input, test.input, b)
-			continue
-		}
-	}
-}
-
-func TestEnsurePipelineContains(t *testing.T) {
-	tests := []struct {
-		input, output string
-		ids           []string
-	}{
-		{
-			"{{.X}}",
-			"[(command: [F=[X]])]",
-			[]string{},
-		},
-		{
-			"{{.X | html}}",
-			"[(command: [F=[X]]) (command: [I=html])]",
-			[]string{},
-		},
-		{
-			"{{.X}}",
-			"[(command: [F=[X]]) (command: [I=html])]",
-			[]string{"html"},
-		},
-		{
-			"{{.X | html}}",
-			"[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
-			[]string{"urlquery"},
-		},
-		{
-			"{{.X | html | urlquery}}",
-			"[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
-			[]string{"urlquery"},
-		},
-		{
-			"{{.X | html | urlquery}}",
-			"[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
-			[]string{"html", "urlquery"},
-		},
-		{
-			"{{.X | html | urlquery}}",
-			"[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
-			[]string{"html"},
-		},
-		{
-			"{{.X | urlquery}}",
-			"[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
-			[]string{"html", "urlquery"},
-		},
-		{
-			"{{.X | html | print}}",
-			"[(command: [F=[X]]) (command: [I=urlquery]) (command: [I=html]) (command: [I=print])]",
-			[]string{"urlquery", "html"},
-		},
-	}
-	for _, test := range tests {
-		tmpl := template.Must(template.New("test").Parse(test.input))
-		action, ok := (tmpl.Tree.Root.Nodes[0].(*parse.ActionNode))
-		if !ok {
-			t.Errorf("First node is not an action: %s", test.input)
-			continue
-		}
-		pipe := action.Pipe
-		ensurePipelineContains(pipe, test.ids)
-		got := pipe.String()
-		if got != test.output {
-			t.Errorf("%s, %v: want\n\t%s\ngot\n\t%s", test.input, test.ids, test.output, got)
-		}
-	}
-}
-
-func expectExecuteFailure(t *testing.T, b *bytes.Buffer) {
-	if x := recover(); x != nil {
-		if b.Len() != 0 {
-			t.Errorf("output on buffer: %q", b.String())
-		}
-	} else {
-		t.Errorf("unescaped template executed")
-	}
-}
-
-func TestEscapeErrorsNotIgnorable(t *testing.T) {
-	var b bytes.Buffer
-	tmpl := template.Must(template.New("dangerous").Parse("<a"))
-	Escape(tmpl)
-	defer expectExecuteFailure(t, &b)
-	tmpl.Execute(&b, nil)
-}
-
-func TestEscapeSetErrorsNotIgnorable(t *testing.T) {
-	s, err := (&template.Set{}).Parse(`{{define "t"}}<a{{end}}`)
-	if err != nil {
-		t.Error("failed to parse set: %q", err)
-	}
-	EscapeSet(s, "t")
-	var b bytes.Buffer
-	defer expectExecuteFailure(t, &b)
-	s.Execute(&b, "t", nil)
-}
diff --git a/src/pkg/exp/template/html/html.go b/src/pkg/exp/template/html/html.go
deleted file mode 100644
index 3924b19..0000000
--- a/src/pkg/exp/template/html/html.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"fmt"
-	"utf8"
-)
-
-// htmlNospaceEscaper escapes for inclusion in unquoted attribute values.
-func htmlNospaceEscaper(args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeHTML {
-		return htmlReplacer(stripTags(s), htmlNospaceNormReplacementTable, false)
-	}
-	return htmlReplacer(s, htmlNospaceReplacementTable, false)
-}
-
-// attrEscaper escapes for inclusion in quoted attribute values.
-func attrEscaper(args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeHTML {
-		return htmlReplacer(stripTags(s), htmlNormReplacementTable, true)
-	}
-	return htmlReplacer(s, htmlReplacementTable, true)
-}
-
-// rcdataEscaper escapes for inclusion in an RCDATA element body.
-func rcdataEscaper(args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeHTML {
-		return htmlReplacer(s, htmlNormReplacementTable, true)
-	}
-	return htmlReplacer(s, htmlReplacementTable, true)
-}
-
-// htmlEscaper escapes for inclusion in HTML text.
-func htmlEscaper(args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeHTML {
-		return s
-	}
-	return htmlReplacer(s, htmlReplacementTable, true)
-}
-
-// htmlReplacementTable contains the runes that need to be escaped
-// inside a quoted attribute value or in a text node.
-var htmlReplacementTable = []string{
-	// http://www.w3.org/TR/html5/tokenization.html#attribute-value-unquoted-state: "
-	// U+0000 NULL Parse error. Append a U+FFFD REPLACEMENT
-	// CHARACTER character to the current attribute's value.
-	// "
-	// and similarly
-	// http://www.w3.org/TR/html5/tokenization.html#before-attribute-value-state
-	0:    "\uFFFD",
-	'"':  """,
-	'&':  "&",
-	'\'': "'",
-	'+':  "+",
-	'<':  "<",
-	'>':  ">",
-}
-
-// htmlNormReplacementTable is like htmlReplacementTable but without '&' to
-// avoid over-encoding existing entities.
-var htmlNormReplacementTable = []string{
-	0:    "\uFFFD",
-	'"':  """,
-	'\'': "'",
-	'+':  "+",
-	'<':  "<",
-	'>':  ">",
-}
-
-// htmlNospaceReplacementTable contains the runes that need to be escaped
-// inside an unquoted attribute value.
-// The set of runes escaped is the union of the HTML specials and
-// those determined by running the JS below in browsers:
-// <div id=d></div>
-// <script>(function () {
-// var a = [], d = document.getElementById("d"), i, c, s;
-// for (i = 0; i < 0x10000; ++i) {
-//   c = String.fromCharCode(i);
-//   d.innerHTML = "<span title=" + c + "lt" + c + "></span>"
-//   s = d.getElementsByTagName("SPAN")[0];
-//   if (!s || s.title !== c + "lt" + c) { a.push(i.toString(16)); }
-// }
-// document.write(a.join(", "));
-// })()</script>
-var htmlNospaceReplacementTable = []string{
-	0:    "&#xfffd;",
-	'\t': "	",
-	'\n': "
",
-	'\v': "",
-	'\f': "",
-	'\r': "
",
-	' ':  " ",
-	'"':  """,
-	'&':  "&",
-	'\'': "'",
-	'+':  "+",
-	'<':  "<",
-	'=':  "=",
-	'>':  ">",
-	// A parse error in the attribute value (unquoted) and 
-	// before attribute value states.
-	// Treated as a quoting character by IE.
-	'`': "`",
-}
-
-// htmlNospaceNormReplacementTable is like htmlNospaceReplacementTable but
-// without '&' to avoid over-encoding existing entities.
-var htmlNospaceNormReplacementTable = []string{
-	0:    "&#xfffd;",
-	'\t': "	",
-	'\n': "
",
-	'\v': "",
-	'\f': "",
-	'\r': "
",
-	' ':  " ",
-	'"':  """,
-	'\'': "'",
-	'+':  "+",
-	'<':  "<",
-	'=':  "=",
-	'>':  ">",
-	// A parse error in the attribute value (unquoted) and 
-	// before attribute value states.
-	// Treated as a quoting character by IE.
-	'`': "`",
-}
-
-// htmlReplacer returns s with runes replaced acccording to replacementTable
-// and when badRunes is true, certain bad runes are allowed through unescaped.
-func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
-	written, b := 0, new(bytes.Buffer)
-	for i, r := range s {
-		if r < len(replacementTable) {
-			if repl := replacementTable[r]; len(repl) != 0 {
-				b.WriteString(s[written:i])
-				b.WriteString(repl)
-				// Valid as long as replacementTable doesn't 
-				// include anything above 0x7f.
-				written = i + utf8.RuneLen(r)
-			}
-		} else if badRunes {
-			// No-op.
-			// IE does not allow these ranges in unquoted attrs.
-		} else if 0xfdd0 <= r && r <= 0xfdef || 0xfff0 <= r && r <= 0xffff {
-			fmt.Fprintf(b, "%s&#x%x;", s[written:i], r)
-			written = i + utf8.RuneLen(r)
-		}
-	}
-	if written == 0 {
-		return s
-	}
-	b.WriteString(s[written:])
-	return b.String()
-}
-
-// stripTags takes a snippet of HTML and returns only the text content.
-// For example, `<b>¡Hi!</b> <script>...</script>` -> `¡Hi! `.
-func stripTags(html string) string {
-	var b bytes.Buffer
-	s, c, i, allText := []byte(html), context{}, 0, true
-	// Using the transition funcs helps us avoid mangling
-	// `<div title="1>2">` or `I <3 Ponies!`.
-	for i != len(s) {
-		if c.delim == delimNone {
-			st := c.state
-			// Use RCDATA instead of parsing into JS or CSS styles.
-			if c.element != elementNone && !isInTag(st) {
-				st = stateRCDATA
-			}
-			d, nread := transitionFunc[st](c, s[i:])
-			i1 := i + nread
-			if c.state == stateText || c.state == stateRCDATA {
-				// Emit text up to the start of the tag or comment.
-				j := i1
-				if d.state != c.state {
-					for j1 := j - 1; j1 >= i; j1-- {
-						if s[j1] == '<' {
-							j = j1
-							break
-						}
-					}
-				}
-				b.Write(s[i:j])
-			} else {
-				allText = false
-			}
-			c, i = d, i1
-			continue
-		}
-		i1 := i + bytes.IndexAny(s[i:], delimEnds[c.delim])
-		if i1 < i {
-			break
-		}
-		if c.delim != delimSpaceOrTagEnd {
-			// Consume any quote.
-			i1++
-		}
-		c, i = context{state: stateTag, element: c.element}, i1
-	}
-	if allText {
-		return html
-	} else if c.state == stateText || c.state == stateRCDATA {
-		b.Write(s[i:])
-	}
-	return b.String()
-}
-
-// htmlNameFilter accepts valid parts of an HTML attribute or tag name or
-// a known-safe HTML attribute.
-func htmlNameFilter(args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeHTMLAttr {
-		return s
-	}
-	for _, r := range s {
-		switch {
-		case '0' <= r && r <= '9':
-		case 'A' <= r && r <= 'Z':
-		case 'a' <= r && r <= 'z':
-		default:
-			return filterFailsafe
-		}
-	}
-	return s
-}
-
-// commentEscaper returns the empty string regardless of input.
-// Comment content does not correspond to any parsed structure or
-// human-readable content, so the simplest and most secure policy is to drop
-// content interpolated into comments.
-// This approach is equally valid whether or not static comment content is
-// removed from the template.
-func commentEscaper(args ...interface{}) string {
-	return ""
-}
diff --git a/src/pkg/exp/template/html/html_test.go b/src/pkg/exp/template/html/html_test.go
deleted file mode 100644
index e178d0f..0000000
--- a/src/pkg/exp/template/html/html_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"html"
-	"strings"
-	"testing"
-)
-
-func TestHTMLNospaceEscaper(t *testing.T) {
-	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
-		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
-		` !"#$%&'()*+,-./` +
-		`0123456789:;<=>?` +
-		`@ABCDEFGHIJKLMNO` +
-		`PQRSTUVWXYZ[\]^_` +
-		"`abcdefghijklmno" +
-		"pqrstuvwxyz{|}~\x7f" +
-		"\u00A0\u0100\u2028\u2029\ufeff\ufdec\U0001D11E")
-
-	want := ("&#xfffd;\x01\x02\x03\x04\x05\x06\x07" +
-		"\x08	

\x0E\x0F" +
-		"\x10\x11\x12\x13\x14\x15\x16\x17" +
-		"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
-		` !"#$%&'()*+,-./` +
-		`0123456789:;<=>?` +
-		`@ABCDEFGHIJKLMNO` +
-		`PQRSTUVWXYZ[\]^_` +
-		``abcdefghijklmno` +
-		`pqrstuvwxyz{|}~` + "\u007f" +
-		"\u00A0\u0100\u2028\u2029\ufeff&#xfdec;\U0001D11E")
-
-	got := htmlNospaceEscaper(input)
-	if got != want {
-		t.Errorf("encode: want\n\t%q\nbut got\n\t%q", want, got)
-	}
-
-	got, want = html.UnescapeString(got), strings.Replace(input, "\x00", "\ufffd", 1)
-	if want != got {
-		t.Errorf("decode: want\n\t%q\nbut got\n\t%q", want, got)
-	}
-}
-
-func TestStripTags(t *testing.T) {
-	tests := []struct {
-		input, want string
-	}{
-		{"", ""},
-		{"Hello, World!", "Hello, World!"},
-		{"foo&bar", "foo&bar"},
-		{`Hello <a href="www.example.com/">World</a>!`, "Hello World!"},
-		{"Foo <textarea>Bar</textarea> Baz", "Foo Bar Baz"},
-		{"Foo <!-- Bar --> Baz", "Foo  Baz"},
-		{"<", "<"},
-		{"foo < bar", "foo < bar"},
-		{`Foo<script type="text/javascript">alert(1337)</script>Bar`, "FooBar"},
-		{`Foo<div title="1>2">Bar`, "FooBar"},
-		{`I <3 Ponies!`, `I <3 Ponies!`},
-		{`<script>foo()</script>`, ``},
-	}
-
-	for _, test := range tests {
-		if got := stripTags(test.input); got != test.want {
-			t.Errorf("%q: want %q, got %q", test.input, test.want, got)
-		}
-	}
-}
-
-func BenchmarkHTMLNospaceEscaper(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		htmlNospaceEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
-	}
-}
-
-func BenchmarkHTMLNospaceEscaperNoSpecials(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		htmlNospaceEscaper("The_quick,_brown_fox_jumps_over_the_lazy_dog.")
-	}
-}
-
-func BenchmarkStripTags(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		stripTags("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
-	}
-}
-
-func BenchmarkStripTagsNoSpecials(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		stripTags("The quick, brown fox jumps over the lazy dog.")
-	}
-}
diff --git a/src/pkg/exp/template/html/js.go b/src/pkg/exp/template/html/js.go
deleted file mode 100644
index 4318b00..0000000
--- a/src/pkg/exp/template/html/js.go
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"fmt"
-	"json"
-	"strings"
-	"utf8"
-)
-
-// nextJSCtx returns the context that determines whether a slash after the
-// given run of tokens tokens starts a regular expression instead of a division
-// operator: / or /=.
-//
-// This assumes that the token run does not include any string tokens, comment
-// tokens, regular expression literal tokens, or division operators.
-//
-// This fails on some valid but nonsensical JavaScript programs like
-// "x = ++/foo/i" which is quite different than "x++/foo/i", but is not known to
-// fail on any known useful programs. It is based on the draft
-// JavaScript 2.0 lexical grammar and requires one token of lookbehind:
-// http://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
-func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
-	s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029")
-	if len(s) == 0 {
-		return preceding
-	}
-
-	// All cases below are in the single-byte UTF-8 group.
-	switch c, n := s[len(s)-1], len(s); c {
-	case '+', '-':
-		// ++ and -- are not regexp preceders, but + and - are whether
-		// they are used as infix or prefix operators.
-		start := n - 1
-		// Count the number of adjacent dashes or pluses.
-		for start > 0 && s[start-1] == c {
-			start--
-		}
-		if (n-start)&1 == 1 {
-			// Reached for trailing minus signs since "---" is the
-			// same as "-- -".
-			return jsCtxRegexp
-		}
-		return jsCtxDivOp
-	case '.':
-		// Handle "42."
-		if n != 1 && '0' <= s[n-2] && s[n-2] <= '9' {
-			return jsCtxDivOp
-		}
-		return jsCtxRegexp
-	// Suffixes for all punctuators from section 7.7 of the language spec
-	// that only end binary operators not handled above.
-	case ',', '<', '>', '=', '*', '%', '&', '|', '^', '?':
-		return jsCtxRegexp
-	// Suffixes for all punctuators from section 7.7 of the language spec
-	// that are prefix operators not handled above.
-	case '!', '~':
-		return jsCtxRegexp
-	// Matches all the punctuators from section 7.7 of the language spec
-	// that are open brackets not handled above.
-	case '(', '[':
-		return jsCtxRegexp
-	// Matches all the punctuators from section 7.7 of the language spec
-	// that precede expression starts.
-	case ':', ';', '{':
-		return jsCtxRegexp
-	// CAVEAT: the close punctuators ('}', ']', ')') precede div ops and
-	// are handled in the default except for '}' which can precede a
-	// division op as in
-	//    ({ valueOf: function () { return 42 } } / 2
-	// which is valid, but, in practice, developers don't divide object
-	// literals, so our heuristic works well for code like
-	//    function () { ... }  /foo/.test(x) && sideEffect();
-	// The ')' punctuator can precede a regular expression as in
-	//     if (b) /foo/.test(x) && ...
-	// but this is much less likely than
-	//     (a + b) / c
-	case '}':
-		return jsCtxRegexp
-	default:
-		// Look for an IdentifierName and see if it is a keyword that
-		// can precede a regular expression.
-		j := n
-		for j > 0 && isJSIdentPart(int(s[j-1])) {
-			j--
-		}
-		if regexpPrecederKeywords[string(s[j:])] {
-			return jsCtxRegexp
-		}
-	}
-	// Otherwise is a punctuator not listed above, or
-	// a string which precedes a div op, or an identifier
-	// which precedes a div op.
-	return jsCtxDivOp
-}
-
-// regexPrecederKeywords is a set of reserved JS keywords that can precede a
-// regular expression in JS source.
-var regexpPrecederKeywords = map[string]bool{
-	"break":      true,
-	"case":       true,
-	"continue":   true,
-	"delete":     true,
-	"do":         true,
-	"else":       true,
-	"finally":    true,
-	"in":         true,
-	"instanceof": true,
-	"return":     true,
-	"throw":      true,
-	"try":        true,
-	"typeof":     true,
-	"void":       true,
-}
-
-// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
-// nether side-effects nor free variables outside (NaN, Infinity).
-func jsValEscaper(args ...interface{}) string {
-	var a interface{}
-	if len(args) == 1 {
-		a = args[0]
-		switch t := a.(type) {
-		case JS:
-			return string(t)
-		case JSStr:
-			// TODO: normalize quotes.
-			return `"` + string(t) + `"`
-		case json.Marshaler:
-			// Do not treat as a Stringer.
-		case fmt.Stringer:
-			a = t.String()
-		}
-	} else {
-		a = fmt.Sprint(args...)
-	}
-	// TODO: detect cycles before calling Marshal which loops infinitely on
-	// cyclic data. This may be an unnacceptable DoS risk.
-
-	// TODO: make sure that json.Marshal escapes codepoints U+2028 & U+2029
-	// so it falls within the subset of JSON which is valid JS and maybe
-	// post-process to prevent it from containing
-	// "<!--", "-->", "<![CDATA[", "]]>", or "</script"
-	// in case custom marshallers produce output containing those.
-
-	// TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.
-
-	// TODO: JSON allows arbitrary unicode codepoints, but EcmaScript
-	// defines a SourceCharacter as either a UTF-16 or UCS-2 code-unit.
-	// Determine whether supplemental codepoints in UTF-8 encoded JS inside
-	// string literals are properly interpreted by major interpreters.
-
-	b, err := json.Marshal(a)
-	if err != nil {
-		// Put a space before comment so that if it is flush against
-		// a division operator it is not turned into a line comment:
-		//     x/{{y}}
-		// turning into
-		//     x//* error marshalling y:
-		//          second line of error message */null
-		return fmt.Sprintf(" /* %s */null ", strings.Replace(err.String(), "*/", "* /", -1))
-	}
-	if len(b) != 0 {
-		first, _ := utf8.DecodeRune(b)
-		last, _ := utf8.DecodeLastRune(b)
-		if isJSIdentPart(first) || isJSIdentPart(last) {
-			return " " + string(b) + " "
-		}
-	}
-	return string(b)
-}
-
-// jsStrEscaper produces a string that can be included between quotes in
-// JavaScript source, in JavaScript embedded in an HTML5 <script> element,
-// or in an HTML5 event handler attribute such as onclick.
-func jsStrEscaper(args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeJSStr {
-		return replace(s, jsStrNormReplacementTable)
-	}
-	return replace(s, jsStrReplacementTable)
-}
-
-// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
-// specials so the result is treated literally when included in a regular
-// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
-// the literal text of {{.X}} followed by the string "bar".
-func jsRegexpEscaper(args ...interface{}) string {
-	s, _ := stringify(args...)
-	s = replace(s, jsRegexpReplacementTable)
-	if s == "" {
-		// /{{.X}}/ should not produce a line comment when .X == "".
-		return "(?:)"
-	}
-	return s
-}
-
-// replace replaces each rune r of s with replacementTable[r], provided that
-// r < len(replacementTable). If replacementTable[r] is the empty string then
-// no replacement is made.
-// It also replaces runes U+2028 and U+2029 with the raw strings `\u2028` and
-// `\u2029`.
-func replace(s string, replacementTable []string) string {
-	var b bytes.Buffer
-	written := 0
-	for i, r := range s {
-		var repl string
-		switch {
-		case r < len(replacementTable) && replacementTable[r] != "":
-			repl = replacementTable[r]
-		case r == '\u2028':
-			repl = `\u2028`
-		case r == '\u2029':
-			repl = `\u2029`
-		default:
-			continue
-		}
-		b.WriteString(s[written:i])
-		b.WriteString(repl)
-		written = i + utf8.RuneLen(r)
-	}
-	if written == 0 {
-		return s
-	}
-	b.WriteString(s[written:])
-	return b.String()
-}
-
-var jsStrReplacementTable = []string{
-	0:    `\0`,
-	'\t': `\t`,
-	'\n': `\n`,
-	'\v': `\x0b`, // "\v" == "v" on IE 6.
-	'\f': `\f`,
-	'\r': `\r`,
-	// Encode HTML specials as hex so the output can be embedded
-	// in HTML attributes without further encoding.
-	'"':  `\x22`,
-	'&':  `\x26`,
-	'\'': `\x27`,
-	'+':  `\x2b`,
-	'/':  `\/`,
-	'<':  `\x3c`,
-	'>':  `\x3e`,
-	'\\': `\\`,
-}
-
-// jsStrNormReplacementTable is like jsStrReplacementTable but does not
-// overencode existing escapes since this table has no entry for `\`.
-var jsStrNormReplacementTable = []string{
-	0:    `\0`,
-	'\t': `\t`,
-	'\n': `\n`,
-	'\v': `\x0b`, // "\v" == "v" on IE 6.
-	'\f': `\f`,
-	'\r': `\r`,
-	// Encode HTML specials as hex so the output can be embedded
-	// in HTML attributes without further encoding.
-	'"':  `\x22`,
-	'&':  `\x26`,
-	'\'': `\x27`,
-	'+':  `\x2b`,
-	'/':  `\/`,
-	'<':  `\x3c`,
-	'>':  `\x3e`,
-}
-
-var jsRegexpReplacementTable = []string{
-	0:    `\0`,
-	'\t': `\t`,
-	'\n': `\n`,
-	'\v': `\x0b`, // "\v" == "v" on IE 6.
-	'\f': `\f`,
-	'\r': `\r`,
-	// Encode HTML specials as hex so the output can be embedded
-	// in HTML attributes without further encoding.
-	'"':  `\x22`,
-	'$':  `\$`,
-	'&':  `\x26`,
-	'\'': `\x27`,
-	'(':  `\(`,
-	')':  `\)`,
-	'*':  `\*`,
-	'+':  `\x2b`,
-	'-':  `\-`,
-	'.':  `\.`,
-	'/':  `\/`,
-	'<':  `\x3c`,
-	'>':  `\x3e`,
-	'?':  `\?`,
-	'[':  `\[`,
-	'\\': `\\`,
-	']':  `\]`,
-	'^':  `\^`,
-	'{':  `\{`,
-	'|':  `\|`,
-	'}':  `\}`,
-}
-
-// isJSIdentPart returns whether the given rune is a JS identifier part.
-// It does not handle all the non-Latin letters, joiners, and combining marks,
-// but it does handle every codepoint that can occur in a numeric literal or
-// a keyword.
-func isJSIdentPart(rune int) bool {
-	switch {
-	case '$' == rune:
-		return true
-	case '0' <= rune && rune <= '9':
-		return true
-	case 'A' <= rune && rune <= 'Z':
-		return true
-	case '_' == rune:
-		return true
-	case 'a' <= rune && rune <= 'z':
-		return true
-	}
-	return false
-}
diff --git a/src/pkg/exp/template/html/js_test.go b/src/pkg/exp/template/html/js_test.go
deleted file mode 100644
index 76fc238..0000000
--- a/src/pkg/exp/template/html/js_test.go
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"math"
-	"strings"
-	"testing"
-)
-
-func TestNextJsCtx(t *testing.T) {
-	tests := []struct {
-		jsCtx jsCtx
-		s     string
-	}{
-		// Statement terminators precede regexps.
-		{jsCtxRegexp, ";"},
-		// This is not airtight.
-		//     ({ valueOf: function () { return 1 } } / 2)
-		// is valid JavaScript but in practice, devs do not do this.
-		// A block followed by a statement starting with a RegExp is
-		// much more common:
-		//     while (x) {...} /foo/.test(x) || panic()
-		{jsCtxRegexp, "}"},
-		// But member, call, grouping, and array expression terminators
-		// precede div ops.
-		{jsCtxDivOp, ")"},
-		{jsCtxDivOp, "]"},
-		// At the start of a primary expression, array, or expression
-		// statement, expect a regexp.
-		{jsCtxRegexp, "("},
-		{jsCtxRegexp, "["},
-		{jsCtxRegexp, "{"},
-		// Assignment operators precede regexps as do all exclusively
-		// prefix and binary operators.
-		{jsCtxRegexp, "="},
-		{jsCtxRegexp, "+="},
-		{jsCtxRegexp, "*="},
-		{jsCtxRegexp, "*"},
-		{jsCtxRegexp, "!"},
-		// Whether the + or - is infix or prefix, it cannot precede a
-		// div op.
-		{jsCtxRegexp, "+"},
-		{jsCtxRegexp, "-"},
-		// An incr/decr op precedes a div operator.
-		// This is not airtight. In (g = ++/h/i) a regexp follows a
-		// pre-increment operator, but in practice devs do not try to
-		// increment or decrement regular expressions.
-		// (g++/h/i) where ++ is a postfix operator on g is much more
-		// common.
-		{jsCtxDivOp, "--"},
-		{jsCtxDivOp, "++"},
-		{jsCtxDivOp, "x--"},
-		// When we have many dashes or pluses, then they are grouped
-		// left to right.
-		{jsCtxRegexp, "x---"}, // A postfix -- then a -.
-		// return followed by a slash returns the regexp literal or the
-		// slash starts a regexp literal in an expression statement that
-		// is dead code.
-		{jsCtxRegexp, "return"},
-		{jsCtxRegexp, "return "},
-		{jsCtxRegexp, "return\t"},
-		{jsCtxRegexp, "return\n"},
-		{jsCtxRegexp, "return\u2028"},
-		// Identifiers can be divided and cannot validly be preceded by
-		// a regular expressions. Semicolon insertion cannot happen
-		// between an identifier and a regular expression on a new line
-		// because the one token lookahead for semicolon insertion has
-		// to conclude that it could be a div binary op and treat it as
-		// such.
-		{jsCtxDivOp, "x"},
-		{jsCtxDivOp, "x "},
-		{jsCtxDivOp, "x\t"},
-		{jsCtxDivOp, "x\n"},
-		{jsCtxDivOp, "x\u2028"},
-		{jsCtxDivOp, "preturn"},
-		// Numbers precede div ops.
-		{jsCtxDivOp, "0"},
-		// Dots that are part of a number are div preceders.
-		{jsCtxDivOp, "0."},
-	}
-
-	for _, test := range tests {
-		if nextJSCtx([]byte(test.s), jsCtxRegexp) != test.jsCtx {
-			t.Errorf("want %s got %q", test.jsCtx, test.s)
-		}
-		if nextJSCtx([]byte(test.s), jsCtxDivOp) != test.jsCtx {
-			t.Errorf("want %s got %q", test.jsCtx, test.s)
-		}
-	}
-
-	if nextJSCtx([]byte("   "), jsCtxRegexp) != jsCtxRegexp {
-		t.Error("Blank tokens")
-	}
-
-	if nextJSCtx([]byte("   "), jsCtxDivOp) != jsCtxDivOp {
-		t.Error("Blank tokens")
-	}
-}
-
-func TestJSValEscaper(t *testing.T) {
-	tests := []struct {
-		x  interface{}
-		js string
-	}{
-		{int(42), " 42 "},
-		{uint(42), " 42 "},
-		{int16(42), " 42 "},
-		{uint16(42), " 42 "},
-		{int32(-42), " -42 "},
-		{uint32(42), " 42 "},
-		{int16(-42), " -42 "},
-		{uint16(42), " 42 "},
-		{int64(-42), " -42 "},
-		{uint64(42), " 42 "},
-		{uint64(1) << 53, " 9007199254740992 "},
-		// ulp(1 << 53) > 1 so this loses precision in JS
-		// but it is still a representable integer literal.
-		{uint64(1)<<53 + 1, " 9007199254740993 "},
-		{float32(1.0), " 1 "},
-		{float32(-1.0), " -1 "},
-		{float32(0.5), " 0.5 "},
-		{float32(-0.5), " -0.5 "},
-		{float32(1.0) / float32(256), " 0.00390625 "},
-		{float32(0), " 0 "},
-		{math.Copysign(0, -1), " -0 "},
-		{float64(1.0), " 1 "},
-		{float64(-1.0), " -1 "},
-		{float64(0.5), " 0.5 "},
-		{float64(-0.5), " -0.5 "},
-		{float64(0), " 0 "},
-		{math.Copysign(0, -1), " -0 "},
-		{"", `""`},
-		{"foo", `"foo"`},
-		// Newlines.
-		// {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`}, // TODO: FAILING. Maybe fix in json package.
-		// "\v" == "v" on IE 6 so use "\x0b" instead.
-		{"\t\x0b", `"\u0009\u000b"`},
-		{struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
-		{[]interface{}{}, "[]"},
-		{[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
-		{"<!--", `"\u003c!--"`},
-		{"-->", `"--\u003e"`},
-		{"<![CDATA[", `"\u003c![CDATA["`},
-		{"]]>", `"]]\u003e"`},
-		{"</script", `"\u003c/script"`},
-		{"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
-	}
-
-	for _, test := range tests {
-		if js := jsValEscaper(test.x); js != test.js {
-			t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js)
-		}
-		// Make sure that escaping corner cases are not broken
-		// by nesting.
-		a := []interface{}{test.x}
-		want := "[" + strings.TrimSpace(test.js) + "]"
-		if js := jsValEscaper(a); js != want {
-			t.Errorf("%+v: want\n\t%q\ngot\n\t%q", a, want, js)
-		}
-	}
-}
-
-func TestJSStrEscaper(t *testing.T) {
-	tests := []struct {
-		x   interface{}
-		esc string
-	}{
-		{"", ``},
-		{"foo", `foo`},
-		{"\u0000", `\0`},
-		{"\t", `\t`},
-		{"\n", `\n`},
-		{"\r", `\r`},
-		{"\u2028", `\u2028`},
-		{"\u2029", `\u2029`},
-		{"\\", `\\`},
-		{"\\n", `\\n`},
-		{"foo\r\nbar", `foo\r\nbar`},
-		// Preserve attribute boundaries.
-		{`"`, `\x22`},
-		{`'`, `\x27`},
-		// Allow embedding in HTML without further escaping.
-		{`&`, `\x26amp;`},
-		// Prevent breaking out of text node and element boundaries.
-		{"</script>", `\x3c\/script\x3e`},
-		{"<![CDATA[", `\x3c![CDATA[`},
-		{"]]>", `]]\x3e`},
-		// http://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span
-		//   "The text in style, script, title, and textarea elements
-		//   must not have an escaping text span start that is not
-		//   followed by an escaping text span end."
-		// Furthermore, spoofing an escaping text span end could lead
-		// to different interpretation of a </script> sequence otherwise
-		// masked by the escaping text span, and spoofing a start could
-		// allow regular text content to be interpreted as script
-		// allowing script execution via a combination of a JS string
-		// injection followed by an HTML text injection.
-		{"<!--", `\x3c!--`},
-		{"-->", `--\x3e`},
-		// From http://code.google.com/p/doctype/wiki/ArticleUtf7
-		{"+ADw-script+AD4-alert(1)+ADw-/script+AD4-",
-			`\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`,
-		},
-		// Invalid UTF-8 sequence
-		{"foo\xA0bar", "foo\xA0bar"},
-		// Invalid unicode scalar value.
-		{"foo\xed\xa0\x80bar", "foo\xed\xa0\x80bar"},
-	}
-
-	for _, test := range tests {
-		esc := jsStrEscaper(test.x)
-		if esc != test.esc {
-			t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
-		}
-	}
-}
-
-func TestJSRegexpEscaper(t *testing.T) {
-	tests := []struct {
-		x   interface{}
-		esc string
-	}{
-		{"", `(?:)`},
-		{"foo", `foo`},
-		{"\u0000", `\0`},
-		{"\t", `\t`},
-		{"\n", `\n`},
-		{"\r", `\r`},
-		{"\u2028", `\u2028`},
-		{"\u2029", `\u2029`},
-		{"\\", `\\`},
-		{"\\n", `\\n`},
-		{"foo\r\nbar", `foo\r\nbar`},
-		// Preserve attribute boundaries.
-		{`"`, `\x22`},
-		{`'`, `\x27`},
-		// Allow embedding in HTML without further escaping.
-		{`&`, `\x26amp;`},
-		// Prevent breaking out of text node and element boundaries.
-		{"</script>", `\x3c\/script\x3e`},
-		{"<![CDATA[", `\x3c!\[CDATA\[`},
-		{"]]>", `\]\]\x3e`},
-		// Escaping text spans.
-		{"<!--", `\x3c!\-\-`},
-		{"-->", `\-\-\x3e`},
-		{"*", `\*`},
-		{"+", `\x2b`},
-		{"?", `\?`},
-		{"[](){}", `\[\]\(\)\{\}`},
-		{"$foo|x.y", `\$foo\|x\.y`},
-		{"x^y", `x\^y`},
-	}
-
-	for _, test := range tests {
-		esc := jsRegexpEscaper(test.x)
-		if esc != test.esc {
-			t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
-		}
-	}
-}
-
-func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
-	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
-		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
-		` !"#$%&'()*+,-./` +
-		`0123456789:;<=>?` +
-		`@ABCDEFGHIJKLMNO` +
-		`PQRSTUVWXYZ[\]^_` +
-		"`abcdefghijklmno" +
-		"pqrstuvwxyz{|}~\x7f" +
-		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
-
-	tests := []struct {
-		name    string
-		escaper func(...interface{}) string
-		escaped string
-	}{
-		{
-			"jsStrEscaper",
-			jsStrEscaper,
-			"\\0\x01\x02\x03\x04\x05\x06\x07" +
-				"\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
-				"\x10\x11\x12\x13\x14\x15\x16\x17" +
-				"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
-				` !\x22#$%\x26\x27()*\x2b,-.\/` +
-				`0123456789:;\x3c=\x3e?` +
-				`@ABCDEFGHIJKLMNO` +
-				`PQRSTUVWXYZ[\\]^_` +
-				"`abcdefghijklmno" +
-				"pqrstuvwxyz{|}~\x7f" +
-				"\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
-		},
-		{
-			"jsRegexpEscaper",
-			jsRegexpEscaper,
-			"\\0\x01\x02\x03\x04\x05\x06\x07" +
-				"\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
-				"\x10\x11\x12\x13\x14\x15\x16\x17" +
-				"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
-				` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` +
-				`0123456789:;\x3c=\x3e\?` +
-				`@ABCDEFGHIJKLMNO` +
-				`PQRSTUVWXYZ\[\\\]\^_` +
-				"`abcdefghijklmno" +
-				`pqrstuvwxyz\{\|\}~` + "\u007f" +
-				"\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
-		},
-	}
-
-	for _, test := range tests {
-		if s := test.escaper(input); s != test.escaped {
-			t.Errorf("%s once: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
-			continue
-		}
-
-		// Escape it rune by rune to make sure that any
-		// fast-path checking does not break escaping.
-		var buf bytes.Buffer
-		for _, c := range input {
-			buf.WriteString(test.escaper(string(c)))
-		}
-
-		if s := buf.String(); s != test.escaped {
-			t.Errorf("%s rune-wise: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
-			continue
-		}
-	}
-}
-
-func BenchmarkJSStrEscaperNoSpecials(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		jsStrEscaper("The quick, brown fox jumps over the lazy dog.")
-	}
-}
-
-func BenchmarkJSStrEscaper(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		jsStrEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
-	}
-}
-
-func BenchmarkJSRegexpEscaperNoSpecials(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		jsRegexpEscaper("The quick, brown fox jumps over the lazy dog")
-	}
-}
-
-func BenchmarkJSRegexpEscaper(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		jsRegexpEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
-	}
-}
diff --git a/src/pkg/exp/template/html/transition.go b/src/pkg/exp/template/html/transition.go
deleted file mode 100644
index 3be3a01..0000000
--- a/src/pkg/exp/template/html/transition.go
+++ /dev/null
@@ -1,560 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"strings"
-)
-
-// TODO: ensure transition error messages contain template name and ideally
-// line info.
-
-// transitionFunc is the array of context transition functions for text nodes.
-// A transition function takes a context and template text input, and returns
-// the updated context and the number of bytes consumed from the front of the
-// input.
-var transitionFunc = [...]func(context, []byte) (context, int){
-	stateText:        tText,
-	stateTag:         tTag,
-	stateAttrName:    tAttrName,
-	stateAfterName:   tAfterName,
-	stateBeforeValue: tBeforeValue,
-	stateHTMLCmt:     tHTMLCmt,
-	stateRCDATA:      tSpecialTagEnd,
-	stateAttr:        tAttr,
-	stateURL:         tURL,
-	stateJS:          tJS,
-	stateJSDqStr:     tJSDelimited,
-	stateJSSqStr:     tJSDelimited,
-	stateJSRegexp:    tJSDelimited,
-	stateJSBlockCmt:  tBlockCmt,
-	stateJSLineCmt:   tLineCmt,
-	stateCSS:         tCSS,
-	stateCSSDqStr:    tCSSStr,
-	stateCSSSqStr:    tCSSStr,
-	stateCSSDqURL:    tCSSStr,
-	stateCSSSqURL:    tCSSStr,
-	stateCSSURL:      tCSSStr,
-	stateCSSBlockCmt: tBlockCmt,
-	stateCSSLineCmt:  tLineCmt,
-	stateError:       tError,
-}
-
-var commentStart = []byte("<!--")
-var commentEnd = []byte("-->")
-
-// tText is the context transition function for the text state.
-func tText(c context, s []byte) (context, int) {
-	k := 0
-	for {
-		i := k + bytes.IndexByte(s[k:], '<')
-		if i < k || i+1 == len(s) {
-			return c, len(s)
-		} else if i+4 <= len(s) && bytes.Equal(commentStart, s[i:i+4]) {
-			return context{state: stateHTMLCmt}, i + 4
-		}
-		i++
-		end := false
-		if s[i] == '/' {
-			if i+1 == len(s) {
-				return c, len(s)
-			}
-			end, i = true, i+1
-		}
-		j, e := eatTagName(s, i)
-		if j != i {
-			if end {
-				e = elementNone
-			}
-			// We've found an HTML tag.
-			return context{state: stateTag, element: e}, j
-		}
-		k = j
-	}
-	panic("unreachable")
-}
-
-var elementContentType = [...]state{
-	elementNone:     stateText,
-	elementScript:   stateJS,
-	elementStyle:    stateCSS,
-	elementTextarea: stateRCDATA,
-	elementTitle:    stateRCDATA,
-}
-
-// tTag is the context transition function for the tag state.
-func tTag(c context, s []byte) (context, int) {
-	// Find the attribute name.
-	i := eatWhiteSpace(s, 0)
-	if i == len(s) {
-		return c, len(s)
-	}
-	if s[i] == '>' {
-		return context{
-			state:   elementContentType[c.element],
-			element: c.element,
-		}, i + 1
-	}
-	j, err := eatAttrName(s, i)
-	if err != nil {
-		return context{state: stateError, err: err}, len(s)
-	}
-	state, attr := stateTag, attrNone
-	if i != j {
-		canonAttrName := strings.ToLower(string(s[i:j]))
-		if urlAttr[canonAttrName] {
-			attr = attrURL
-		} else if strings.HasPrefix(canonAttrName, "on") {
-			attr = attrScript
-		} else if canonAttrName == "style" {
-			attr = attrStyle
-		}
-		if j == len(s) {
-			state = stateAttrName
-		} else {
-			state = stateAfterName
-		}
-	}
-	return context{state: state, element: c.element, attr: attr}, j
-}
-
-// tAttrName is the context transition function for stateAttrName.
-func tAttrName(c context, s []byte) (context, int) {
-	i, err := eatAttrName(s, 0)
-	if err != nil {
-		return context{state: stateError, err: err}, len(s)
-	} else if i != len(s) {
-		c.state = stateAfterName
-	}
-	return c, i
-}
-
-// tAfterName is the context transition function for stateAfterName.
-func tAfterName(c context, s []byte) (context, int) {
-	// Look for the start of the value.
-	i := eatWhiteSpace(s, 0)
-	if i == len(s) {
-		return c, len(s)
-	} else if s[i] != '=' {
-		// Occurs due to tag ending '>', and valueless attribute.
-		c.state = stateTag
-		return c, i
-	}
-	c.state = stateBeforeValue
-	// Consume the "=".
-	return c, i + 1
-}
-
-var attrStartStates = [...]state{
-	attrNone:   stateAttr,
-	attrScript: stateJS,
-	attrStyle:  stateCSS,
-	attrURL:    stateURL,
-}
-
-// tBeforeValue is the context transition function for stateBeforeValue.
-func tBeforeValue(c context, s []byte) (context, int) {
-	i := eatWhiteSpace(s, 0)
-	if i == len(s) {
-		return c, len(s)
-	}
-	// Find the attribute delimiter.
-	delim := delimSpaceOrTagEnd
-	switch s[i] {
-	case '\'':
-		delim, i = delimSingleQuote, i+1
-	case '"':
-		delim, i = delimDoubleQuote, i+1
-	}
-	c.state, c.delim, c.attr = attrStartStates[c.attr], delim, attrNone
-	return c, i
-}
-
-// tHTMLCmt is the context transition function for stateHTMLCmt.
-func tHTMLCmt(c context, s []byte) (context, int) {
-	if i := bytes.Index(s, commentEnd); i != -1 {
-		return context{}, i + 3
-	}
-	return c, len(s)
-}
-
-// specialTagEndMarkers maps element types to the character sequence that
-// case-insensitively signals the end of the special tag body.
-var specialTagEndMarkers = [...]string{
-	elementScript:   "</script",
-	elementStyle:    "</style",
-	elementTextarea: "</textarea",
-	elementTitle:    "</title",
-}
-
-// tSpecialTagEnd is the context transition function for raw text and RCDATA
-// element states.
-func tSpecialTagEnd(c context, s []byte) (context, int) {
-	if c.element != elementNone {
-		if i := strings.Index(strings.ToLower(string(s)), specialTagEndMarkers[c.element]); i != -1 {
-			return context{}, i
-		}
-	}
-	return c, len(s)
-}
-
-// tAttr is the context transition function for the attribute state.
-func tAttr(c context, s []byte) (context, int) {
-	return c, len(s)
-}
-
-// tURL is the context transition function for the URL state.
-func tURL(c context, s []byte) (context, int) {
-	if bytes.IndexAny(s, "#?") >= 0 {
-		c.urlPart = urlPartQueryOrFrag
-	} else if len(s) != eatWhiteSpace(s, 0) && c.urlPart == urlPartNone {
-		// HTML5 uses "Valid URL potentially surrounded by spaces" for
-		// attrs: http://www.w3.org/TR/html5/index.html#attributes-1
-		c.urlPart = urlPartPreQuery
-	}
-	return c, len(s)
-}
-
-// tJS is the context transition function for the JS state.
-func tJS(c context, s []byte) (context, int) {
-	i := bytes.IndexAny(s, `"'/`)
-	if i == -1 {
-		// Entire input is non string, comment, regexp tokens.
-		c.jsCtx = nextJSCtx(s, c.jsCtx)
-		return c, len(s)
-	}
-	c.jsCtx = nextJSCtx(s[:i], c.jsCtx)
-	switch s[i] {
-	case '"':
-		c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp
-	case '\'':
-		c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp
-	case '/':
-		switch {
-		case i+1 < len(s) && s[i+1] == '/':
-			c.state, i = stateJSLineCmt, i+1
-		case i+1 < len(s) && s[i+1] == '*':
-			c.state, i = stateJSBlockCmt, i+1
-		case c.jsCtx == jsCtxRegexp:
-			c.state = stateJSRegexp
-		case c.jsCtx == jsCtxDivOp:
-			c.jsCtx = jsCtxRegexp
-		default:
-			return context{
-				state: stateError,
-				err:   errorf(ErrSlashAmbig, 0, "'/' could start div or regexp: %.32q", s[i:]),
-			}, len(s)
-		}
-	default:
-		panic("unreachable")
-	}
-	return c, i + 1
-}
-
-// tJSDelimited is the context transition function for the JS string and regexp
-// states.
-func tJSDelimited(c context, s []byte) (context, int) {
-	specials := `\"`
-	switch c.state {
-	case stateJSSqStr:
-		specials = `\'`
-	case stateJSRegexp:
-		specials = `\/[]`
-	}
-
-	k, inCharset := 0, false
-	for {
-		i := k + bytes.IndexAny(s[k:], specials)
-		if i < k {
-			break
-		}
-		switch s[i] {
-		case '\\':
-			i++
-			if i == len(s) {
-				return context{
-					state: stateError,
-					err:   errorf(ErrPartialEscape, 0, "unfinished escape sequence in JS string: %q", s),
-				}, len(s)
-			}
-		case '[':
-			inCharset = true
-		case ']':
-			inCharset = false
-		default:
-			// end delimiter
-			if !inCharset {
-				c.state, c.jsCtx = stateJS, jsCtxDivOp
-				return c, i + 1
-			}
-		}
-		k = i + 1
-	}
-
-	if inCharset {
-		// This can be fixed by making context richer if interpolation
-		// into charsets is desired.
-		return context{
-			state: stateError,
-			err:   errorf(ErrPartialCharset, 0, "unfinished JS regexp charset: %q", s),
-		}, len(s)
-	}
-
-	return c, len(s)
-}
-
-var blockCommentEnd = []byte("*/")
-
-// tBlockCmt is the context transition function for /*comment*/ states.
-func tBlockCmt(c context, s []byte) (context, int) {
-	i := bytes.Index(s, blockCommentEnd)
-	if i == -1 {
-		return c, len(s)
-	}
-	switch c.state {
-	case stateJSBlockCmt:
-		c.state = stateJS
-	case stateCSSBlockCmt:
-		c.state = stateCSS
-	default:
-		panic(c.state.String())
-	}
-	return c, i + 2
-}
-
-// tLineCmt is the context transition function for //comment states.
-func tLineCmt(c context, s []byte) (context, int) {
-	var lineTerminators string
-	var endState state
-	switch c.state {
-	case stateJSLineCmt:
-		lineTerminators, endState = "\n\r\u2028\u2029", stateJS
-	case stateCSSLineCmt:
-		lineTerminators, endState = "\n\f\r", stateCSS
-		// Line comments are not part of any published CSS standard but
-		// are supported by the 4 major browsers.
-		// This defines line comments as
-		//     LINECOMMENT ::= "//" [^\n\f\d]*
-		// since http://www.w3.org/TR/css3-syntax/#SUBTOK-nl defines
-		// newlines:
-		//     nl ::= #xA | #xD #xA | #xD | #xC
-	default:
-		panic(c.state.String())
-	}
-
-	i := bytes.IndexAny(s, lineTerminators)
-	if i == -1 {
-		return c, len(s)
-	}
-	c.state = endState
-	// Per section 7.4 of EcmaScript 5 : http://es5.github.com/#x7.4
-	// "However, the LineTerminator at the end of the line is not
-	// considered to be part of the single-line comment; it is
-	// recognized separately by the lexical grammar and becomes part
-	// of the stream of input elements for the syntactic grammar."
-	return c, i
-}
-
-// tCSS is the context transition function for the CSS state.
-func tCSS(c context, s []byte) (context, int) {
-	// CSS quoted strings are almost never used except for:
-	// (1) URLs as in background: "/foo.png"
-	// (2) Multiword font-names as in font-family: "Times New Roman"
-	// (3) List separators in content values as in inline-lists:
-	//    <style>
-	//    ul.inlineList { list-style: none; padding:0 }
-	//    ul.inlineList > li { display: inline }
-	//    ul.inlineList > li:before { content: ", " }
-	//    ul.inlineList > li:first-child:before { content: "" }
-	//    </style>
-	//    <ul class=inlineList><li>One<li>Two<li>Three</ul>
-	// (4) Attribute value selectors as in a[href="http://example.com/"]
-	//
-	// We conservatively treat all strings as URLs, but make some
-	// allowances to avoid confusion.
-	//
-	// In (1), our conservative assumption is justified.
-	// In (2), valid font names do not contain ':', '?', or '#', so our
-	// conservative assumption is fine since we will never transition past
-	// urlPartPreQuery.
-	// In (3), our protocol heuristic should not be tripped, and there
-	// should not be non-space content after a '?' or '#', so as long as
-	// we only %-encode RFC 3986 reserved characters we are ok.
-	// In (4), we should URL escape for URL attributes, and for others we
-	// have the attribute name available if our conservative assumption
-	// proves problematic for real code.
-
-	k := 0
-	for {
-		i := k + bytes.IndexAny(s[k:], `("'/`)
-		if i < k {
-			return c, len(s)
-		}
-		switch s[i] {
-		case '(':
-			// Look for url to the left.
-			p := bytes.TrimRight(s[:i], "\t\n\f\r ")
-			if endsWithCSSKeyword(p, "url") {
-				j := len(s) - len(bytes.TrimLeft(s[i+1:], "\t\n\f\r "))
-				switch {
-				case j != len(s) && s[j] == '"':
-					c.state, j = stateCSSDqURL, j+1
-				case j != len(s) && s[j] == '\'':
-					c.state, j = stateCSSSqURL, j+1
-				default:
-					c.state = stateCSSURL
-				}
-				return c, j
-			}
-		case '/':
-			if i+1 < len(s) {
-				switch s[i+1] {
-				case '/':
-					c.state = stateCSSLineCmt
-					return c, i + 2
-				case '*':
-					c.state = stateCSSBlockCmt
-					return c, i + 2
-				}
-			}
-		case '"':
-			c.state = stateCSSDqStr
-			return c, i + 1
-		case '\'':
-			c.state = stateCSSSqStr
-			return c, i + 1
-		}
-		k = i + 1
-	}
-	panic("unreachable")
-}
-
-// tCSSStr is the context transition function for the CSS string and URL states.
-func tCSSStr(c context, s []byte) (context, int) {
-	var endAndEsc string
-	switch c.state {
-	case stateCSSDqStr, stateCSSDqURL:
-		endAndEsc = `\"`
-	case stateCSSSqStr, stateCSSSqURL:
-		endAndEsc = `\'`
-	case stateCSSURL:
-		// Unquoted URLs end with a newline or close parenthesis.
-		// The below includes the wc (whitespace character) and nl.
-		endAndEsc = "\\\t\n\f\r )"
-	default:
-		panic(c.state.String())
-	}
-
-	k := 0
-	for {
-		i := k + bytes.IndexAny(s[k:], endAndEsc)
-		if i < k {
-			c, nread := tURL(c, decodeCSS(s[k:]))
-			return c, k + nread
-		}
-		if s[i] == '\\' {
-			i++
-			if i == len(s) {
-				return context{
-					state: stateError,
-					err:   errorf(ErrPartialEscape, 0, "unfinished escape sequence in CSS string: %q", s),
-				}, len(s)
-			}
-		} else {
-			c.state = stateCSS
-			return c, i + 1
-		}
-		c, _ = tURL(c, decodeCSS(s[:i+1]))
-		k = i + 1
-	}
-	panic("unreachable")
-}
-
-// tError is the context transition function for the error state.
-func tError(c context, s []byte) (context, int) {
-	return c, len(s)
-}
-
-// eatAttrName returns the largest j such that s[i:j] is an attribute name.
-// It returns an error if s[i:] does not look like it begins with an
-// attribute name, such as encountering a quote mark without a preceding
-// equals sign.
-func eatAttrName(s []byte, i int) (int, *Error) {
-	for j := i; j < len(s); j++ {
-		switch s[j] {
-		case ' ', '\t', '\n', '\f', '\r', '=', '>':
-			return j, nil
-		case '\'', '"', '<':
-			// These result in a parse warning in HTML5 and are
-			// indicative of serious problems if seen in an attr
-			// name in a template.
-			return -1, errorf(ErrBadHTML, 0, "%q in attribute name: %.32q", s[j:j+1], s)
-		default:
-			// No-op.
-		}
-	}
-	return len(s), nil
-}
-
-var elementNameMap = map[string]element{
-	"script":   elementScript,
-	"style":    elementStyle,
-	"textarea": elementTextarea,
-	"title":    elementTitle,
-}
-
-// eatTagName returns the largest j such that s[i:j] is a tag name and the tag type.
-func eatTagName(s []byte, i int) (int, element) {
-	j := i
-	for ; j < len(s); j++ {
-		x := s[j]
-		if !(('a' <= x && x <= 'z') ||
-			('A' <= x && x <= 'Z') ||
-			('0' <= x && x <= '9' && i != j)) {
-			break
-		}
-	}
-	return j, elementNameMap[strings.ToLower(string(s[i:j]))]
-}
-
-// eatWhiteSpace returns the largest j such that s[i:j] is white space.
-func eatWhiteSpace(s []byte, i int) int {
-	for j := i; j < len(s); j++ {
-		switch s[j] {
-		case ' ', '\t', '\n', '\f', '\r':
-			// No-op.
-		default:
-			return j
-		}
-	}
-	return len(s)
-}
-
-// urlAttr is the set of attribute names whose values are URLs.
-// It consists of all "%URI"-typed attributes from
-// http://www.w3.org/TR/html4/index/attributes.html
-// as well as those attributes defined at
-// http://dev.w3.org/html5/spec/index.html#attributes-1
-// whose Value column in that table matches
-// "Valid [non-empty] URL potentially surrounded by spaces".
-var urlAttr = map[string]bool{
-	"action":     true,
-	"archive":    true,
-	"background": true,
-	"cite":       true,
-	"classid":    true,
-	"codebase":   true,
-	"data":       true,
-	"formaction": true,
-	"href":       true,
-	"icon":       true,
-	"longdesc":   true,
-	"manifest":   true,
-	"poster":     true,
-	"profile":    true,
-	"src":        true,
-	"usemap":     true,
-}
diff --git a/src/pkg/exp/template/html/url.go b/src/pkg/exp/template/html/url.go
deleted file mode 100644
index 8a43e63..0000000
--- a/src/pkg/exp/template/html/url.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"bytes"
-	"fmt"
-	"strings"
-)
-
-// urlFilter returns the HTML equivalent of its input unless it contains an
-// unsafe protocol in which case it defangs the entire URL.
-func urlFilter(args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeURL {
-		return urlProcessor(true, s)
-	}
-	i := strings.IndexRune(s, ':')
-	if i >= 0 && strings.IndexRune(s[:i], '/') < 0 {
-		protocol := strings.ToLower(s[:i])
-		if protocol != "http" && protocol != "https" && protocol != "mailto" {
-			// Return a value that someone investigating a bug
-			// report can put into a search engine.
-			return "#" + filterFailsafe
-		}
-	}
-	// TODO: Once we handle <style>#id { background: url({{.Img}}) }</style>
-	// we will need to stop this from HTML escaping and pipeline sanitizers.
-	return s
-}
-
-// urlEscaper produces an output that can be embedded in a URL query.
-// The output can be embedded in an HTML attribute without further escaping.
-func urlEscaper(args ...interface{}) string {
-	return urlProcessor(false, args...)
-}
-
-// urlEscaper normalizes URL content so it can be embedded in a quote-delimited
-// string or parenthesis delimited url(...).
-// The normalizer does not encode all HTML specials. Specifically, it does not
-// encode '&' so correct embedding in an HTML attribute requires escaping of
-// '&' to '&'.
-func urlNormalizer(args ...interface{}) string {
-	return urlProcessor(true, args...)
-}
-
-// urlProcessor normalizes (when norm is true) or escapes its input to produce
-// a valid hierarchical or opaque URL part.
-func urlProcessor(norm bool, args ...interface{}) string {
-	s, t := stringify(args...)
-	if t == contentTypeURL {
-		norm = true
-	}
-	var b bytes.Buffer
-	written := 0
-	// The byte loop below assumes that all URLs use UTF-8 as the
-	// content-encoding. This is similar to the URI to IRI encoding scheme
-	// defined in section 3.1 of  RFC 3987, and behaves the same as the
-	// EcmaScript builtin encodeURIComponent.
-	// It should not cause any misencoding of URLs in pages with
-	// Content-type: text/html;charset=UTF-8.
-	for i, n := 0, len(s); i < n; i++ {
-		c := s[i]
-		switch c {
-		// Single quote and parens are sub-delims in RFC 3986, but we
-		// escape them so the output can be embedded in in single
-		// quoted attributes and unquoted CSS url(...) constructs.
-		// Single quotes are reserved in URLs, but are only used in
-		// the obsolete "mark" rule in an appendix in RFC 3986
-		// so can be safely encoded.
-		case '!', '#', '$', '&', '*', '+', ',', '/', ':', ';', '=', '?', '@', '[', ']':
-			if norm {
-				continue
-			}
-		// Unreserved according to RFC 3986 sec 2.3
-		// "For consistency, percent-encoded octets in the ranges of
-		// ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D),
-		// period (%2E), underscore (%5F), or tilde (%7E) should not be
-		// created by URI producers
-		case '-', '.', '_', '~':
-			continue
-		case '%':
-			// When normalizing do not re-encode valid escapes.
-			if norm && i+2 < len(s) && isHex(s[i+1]) && isHex(s[i+2]) {
-				continue
-			}
-		default:
-			// Unreserved according to RFC 3986 sec 2.3
-			if 'a' <= c && c <= 'z' {
-				continue
-			}
-			if 'A' <= c && c <= 'Z' {
-				continue
-			}
-			if '0' <= c && c <= '9' {
-				continue
-			}
-		}
-		b.WriteString(s[written:i])
-		fmt.Fprintf(&b, "%%%02x", c)
-		written = i + 1
-	}
-	if written == 0 {
-		return s
-	}
-	b.WriteString(s[written:])
-	return b.String()
-}
diff --git a/src/pkg/exp/template/html/url_test.go b/src/pkg/exp/template/html/url_test.go
deleted file mode 100644
index b846231..0000000
--- a/src/pkg/exp/template/html/url_test.go
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2011 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 html
-
-import (
-	"testing"
-)
-
-func TestURLNormalizer(t *testing.T) {
-	tests := []struct {
-		url, want string
-	}{
-		{"", ""},
-		{
-			"http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
-			"http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
-		},
-		{" ", "%20"},
-		{"%7c", "%7c"},
-		{"%7C", "%7C"},
-		{"%2", "%252"},
-		{"%", "%25"},
-		{"%z", "%25z"},
-		{"/foo|bar/%5c\u1234", "/foo%7cbar/%5c%e1%88%b4"},
-	}
-	for _, test := range tests {
-		if got := urlNormalizer(test.url); test.want != got {
-			t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.url, test.want, got)
-		}
-		if test.want != urlNormalizer(test.want) {
-			t.Errorf("not idempotent: %q", test.want)
-		}
-	}
-}
-
-func TestURLFilters(t *testing.T) {
-	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
-		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
-		` !"#$%&'()*+,-./` +
-		`0123456789:;<=>?` +
-		`@ABCDEFGHIJKLMNO` +
-		`PQRSTUVWXYZ[\]^_` +
-		"`abcdefghijklmno" +
-		"pqrstuvwxyz{|}~\x7f" +
-		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
-
-	tests := []struct {
-		name    string
-		escaper func(...interface{}) string
-		escaped string
-	}{
-		{
-			"urlEscaper",
-			urlEscaper,
-			"%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
-				"%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
-				"%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f" +
-				"0123456789%3a%3b%3c%3d%3e%3f" +
-				"%40ABCDEFGHIJKLMNO" +
-				"PQRSTUVWXYZ%5b%5c%5d%5e_" +
-				"%60abcdefghijklmno" +
-				"pqrstuvwxyz%7b%7c%7d~%7f" +
-				"%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
-		},
-		{
-			"urlNormalizer",
-			urlNormalizer,
-			"%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
-				"%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
-				"%20!%22#$%25&%27%28%29*+,-./" +
-				"0123456789:;%3c=%3e?" +
-				"@ABCDEFGHIJKLMNO" +
-				"PQRSTUVWXYZ[%5c]%5e_" +
-				"%60abcdefghijklmno" +
-				"pqrstuvwxyz%7b%7c%7d~%7f" +
-				"%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
-		},
-	}
-
-	for _, test := range tests {
-		if s := test.escaper(input); s != test.escaped {
-			t.Errorf("%s: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
-			continue
-		}
-	}
-}
-
-func BenchmarkURLEscaper(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		urlEscaper("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
-	}
-}
-
-func BenchmarkURLEscaperNoSpecials(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		urlEscaper("TheQuickBrownFoxJumpsOverTheLazyDog.")
-	}
-}
-
-func BenchmarkURLNormalizer(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		urlNormalizer("The quick brown fox jumps over the lazy dog.\n")
-	}
-}
-
-func BenchmarkURLNormalizerNoSpecials(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		urlNormalizer("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
-	}
-}
diff --git a/src/pkg/exp/terminal/Makefile b/src/pkg/exp/terminal/Makefile
new file mode 100644
index 0000000..7f702ef
--- /dev/null
+++ b/src/pkg/exp/terminal/Makefile
@@ -0,0 +1,16 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=exp/terminal
+GOFILES=\
+	terminal.go\
+
+ifeq ($(GOOS),linux)
+GOFILES+=\
+	util.go
+endif
+
+include ../../../Make.pkg
diff --git a/src/pkg/exp/terminal/terminal.go b/src/pkg/exp/terminal/terminal.go
new file mode 100644
index 0000000..c3ba5bd
--- /dev/null
+++ b/src/pkg/exp/terminal/terminal.go
@@ -0,0 +1,520 @@
+// Copyright 2011 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 terminal
+
+import (
+	"io"
+	"sync"
+)
+
+// EscapeCodes contains escape sequences that can be written to the terminal in
+// order to achieve different styles of text.
+type EscapeCodes struct {
+	// Foreground colors
+	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte
+
+	// Reset all attributes
+	Reset []byte
+}
+
+var vt100EscapeCodes = EscapeCodes{
+	Black:   []byte{keyEscape, '[', '3', '0', 'm'},
+	Red:     []byte{keyEscape, '[', '3', '1', 'm'},
+	Green:   []byte{keyEscape, '[', '3', '2', 'm'},
+	Yellow:  []byte{keyEscape, '[', '3', '3', 'm'},
+	Blue:    []byte{keyEscape, '[', '3', '4', 'm'},
+	Magenta: []byte{keyEscape, '[', '3', '5', 'm'},
+	Cyan:    []byte{keyEscape, '[', '3', '6', 'm'},
+	White:   []byte{keyEscape, '[', '3', '7', 'm'},
+
+	Reset: []byte{keyEscape, '[', '0', 'm'},
+}
+
+// Terminal contains the state for running a VT100 terminal that is capable of
+// reading lines of input.
+type Terminal struct {
+	// AutoCompleteCallback, if non-null, is called for each keypress
+	// with the full input line and the current position of the cursor.
+	// If it returns a nil newLine, the key press is processed normally.
+	// Otherwise it returns a replacement line and the new cursor position.
+	AutoCompleteCallback func(line []byte, pos, key int) (newLine []byte, newPos int)
+
+	// Escape contains a pointer to the escape codes for this terminal.
+	// It's always a valid pointer, although the escape codes themselves
+	// may be empty if the terminal doesn't support them.
+	Escape *EscapeCodes
+
+	// lock protects the terminal and the state in this object from
+	// concurrent processing of a key press and a Write() call.
+	lock sync.Mutex
+
+	c      io.ReadWriter
+	prompt string
+
+	// line is the current line being entered.
+	line []byte
+	// pos is the logical position of the cursor in line
+	pos int
+	// echo is true if local echo is enabled
+	echo bool
+
+	// cursorX contains the current X value of the cursor where the left
+	// edge is 0. cursorY contains the row number where the first row of
+	// the current line is 0.
+	cursorX, cursorY int
+	// maxLine is the greatest value of cursorY so far.
+	maxLine int
+
+	termWidth, termHeight int
+
+	// outBuf contains the terminal data to be sent.
+	outBuf []byte
+	// remainder contains the remainder of any partial key sequences after
+	// a read. It aliases into inBuf.
+	remainder []byte
+	inBuf     [256]byte
+}
+
+// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
+// a local terminal, that terminal must first have been put into raw mode.
+// prompt is a string that is written at the start of each input line (i.e.
+// "> ").
+func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
+	return &Terminal{
+		Escape:     &vt100EscapeCodes,
+		c:          c,
+		prompt:     prompt,
+		termWidth:  80,
+		termHeight: 24,
+		echo:       true,
+	}
+}
+
+const (
+	keyCtrlD     = 4
+	keyEnter     = '\r'
+	keyEscape    = 27
+	keyBackspace = 127
+	keyUnknown   = 256 + iota
+	keyUp
+	keyDown
+	keyLeft
+	keyRight
+	keyAltLeft
+	keyAltRight
+)
+
+// bytesToKey tries to parse a key sequence from b. If successful, it returns
+// the key and the remainder of the input. Otherwise it returns -1.
+func bytesToKey(b []byte) (int, []byte) {
+	if len(b) == 0 {
+		return -1, nil
+	}
+
+	if b[0] != keyEscape {
+		return int(b[0]), b[1:]
+	}
+
+	if len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
+		switch b[2] {
+		case 'A':
+			return keyUp, b[3:]
+		case 'B':
+			return keyDown, b[3:]
+		case 'C':
+			return keyRight, b[3:]
+		case 'D':
+			return keyLeft, b[3:]
+		}
+	}
+
+	if len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
+		switch b[5] {
+		case 'C':
+			return keyAltRight, b[6:]
+		case 'D':
+			return keyAltLeft, b[6:]
+		}
+	}
+
+	// If we get here then we have a key that we don't recognise, or a
+	// partial sequence. It's not clear how one should find the end of a
+	// sequence without knowing them all, but it seems that [a-zA-Z] only
+	// appears at the end of a sequence.
+	for i, c := range b[0:] {
+		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {
+			return keyUnknown, b[i+1:]
+		}
+	}
+
+	return -1, b
+}
+
+// queue appends data to the end of t.outBuf
+func (t *Terminal) queue(data []byte) {
+	t.outBuf = append(t.outBuf, data...)
+}
+
+var eraseUnderCursor = []byte{' ', keyEscape, '[', 'D'}
+var space = []byte{' '}
+
+func isPrintable(key int) bool {
+	return key >= 32 && key < 127
+}
+
+// moveCursorToPos appends data to t.outBuf which will move the cursor to the
+// given, logical position in the text.
+func (t *Terminal) moveCursorToPos(pos int) {
+	if !t.echo {
+		return
+	}
+
+	x := len(t.prompt) + pos
+	y := x / t.termWidth
+	x = x % t.termWidth
+
+	up := 0
+	if y < t.cursorY {
+		up = t.cursorY - y
+	}
+
+	down := 0
+	if y > t.cursorY {
+		down = y - t.cursorY
+	}
+
+	left := 0
+	if x < t.cursorX {
+		left = t.cursorX - x
+	}
+
+	right := 0
+	if x > t.cursorX {
+		right = x - t.cursorX
+	}
+
+	t.cursorX = x
+	t.cursorY = y
+	t.move(up, down, left, right)
+}
+
+func (t *Terminal) move(up, down, left, right int) {
+	movement := make([]byte, 3*(up+down+left+right))
+	m := movement
+	for i := 0; i < up; i++ {
+		m[0] = keyEscape
+		m[1] = '['
+		m[2] = 'A'
+		m = m[3:]
+	}
+	for i := 0; i < down; i++ {
+		m[0] = keyEscape
+		m[1] = '['
+		m[2] = 'B'
+		m = m[3:]
+	}
+	for i := 0; i < left; i++ {
+		m[0] = keyEscape
+		m[1] = '['
+		m[2] = 'D'
+		m = m[3:]
+	}
+	for i := 0; i < right; i++ {
+		m[0] = keyEscape
+		m[1] = '['
+		m[2] = 'C'
+		m = m[3:]
+	}
+
+	t.queue(movement)
+}
+
+func (t *Terminal) clearLineToRight() {
+	op := []byte{keyEscape, '[', 'K'}
+	t.queue(op)
+}
+
+const maxLineLength = 4096
+
+// handleKey processes the given key and, optionally, returns a line of text
+// that the user has entered.
+func (t *Terminal) handleKey(key int) (line string, ok bool) {
+	switch key {
+	case keyBackspace:
+		if t.pos == 0 {
+			return
+		}
+		t.pos--
+		t.moveCursorToPos(t.pos)
+
+		copy(t.line[t.pos:], t.line[1+t.pos:])
+		t.line = t.line[:len(t.line)-1]
+		if t.echo {
+			t.writeLine(t.line[t.pos:])
+		}
+		t.queue(eraseUnderCursor)
+		t.moveCursorToPos(t.pos)
+	case keyAltLeft:
+		// move left by a word.
+		if t.pos == 0 {
+			return
+		}
+		t.pos--
+		for t.pos > 0 {
+			if t.line[t.pos] != ' ' {
+				break
+			}
+			t.pos--
+		}
+		for t.pos > 0 {
+			if t.line[t.pos] == ' ' {
+				t.pos++
+				break
+			}
+			t.pos--
+		}
+		t.moveCursorToPos(t.pos)
+	case keyAltRight:
+		// move right by a word.
+		for t.pos < len(t.line) {
+			if t.line[t.pos] == ' ' {
+				break
+			}
+			t.pos++
+		}
+		for t.pos < len(t.line) {
+			if t.line[t.pos] != ' ' {
+				break
+			}
+			t.pos++
+		}
+		t.moveCursorToPos(t.pos)
+	case keyLeft:
+		if t.pos == 0 {
+			return
+		}
+		t.pos--
+		t.moveCursorToPos(t.pos)
+	case keyRight:
+		if t.pos == len(t.line) {
+			return
+		}
+		t.pos++
+		t.moveCursorToPos(t.pos)
+	case keyEnter:
+		t.moveCursorToPos(len(t.line))
+		t.queue([]byte("\r\n"))
+		line = string(t.line)
+		ok = true
+		t.line = t.line[:0]
+		t.pos = 0
+		t.cursorX = 0
+		t.cursorY = 0
+		t.maxLine = 0
+	default:
+		if t.AutoCompleteCallback != nil {
+			t.lock.Unlock()
+			newLine, newPos := t.AutoCompleteCallback(t.line, t.pos, key)
+			t.lock.Lock()
+
+			if newLine != nil {
+				if t.echo {
+					t.moveCursorToPos(0)
+					t.writeLine(newLine)
+					for i := len(newLine); i < len(t.line); i++ {
+						t.writeLine(space)
+					}
+					t.moveCursorToPos(newPos)
+				}
+				t.line = newLine
+				t.pos = newPos
+				return
+			}
+		}
+		if !isPrintable(key) {
+			return
+		}
+		if len(t.line) == maxLineLength {
+			return
+		}
+		if len(t.line) == cap(t.line) {
+			newLine := make([]byte, len(t.line), 2*(1+len(t.line)))
+			copy(newLine, t.line)
+			t.line = newLine
+		}
+		t.line = t.line[:len(t.line)+1]
+		copy(t.line[t.pos+1:], t.line[t.pos:])
+		t.line[t.pos] = byte(key)
+		if t.echo {
+			t.writeLine(t.line[t.pos:])
+		}
+		t.pos++
+		t.moveCursorToPos(t.pos)
+	}
+	return
+}
+
+func (t *Terminal) writeLine(line []byte) {
+	for len(line) != 0 {
+		remainingOnLine := t.termWidth - t.cursorX
+		todo := len(line)
+		if todo > remainingOnLine {
+			todo = remainingOnLine
+		}
+		t.queue(line[:todo])
+		t.cursorX += todo
+		line = line[todo:]
+
+		if t.cursorX == t.termWidth {
+			t.cursorX = 0
+			t.cursorY++
+			if t.cursorY > t.maxLine {
+				t.maxLine = t.cursorY
+			}
+		}
+	}
+}
+
+func (t *Terminal) Write(buf []byte) (n int, err error) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	if t.cursorX == 0 && t.cursorY == 0 {
+		// This is the easy case: there's nothing on the screen that we
+		// have to move out of the way.
+		return t.c.Write(buf)
+	}
+
+	// We have a prompt and possibly user input on the screen. We
+	// have to clear it first.
+	t.move(0, /* up */ 0, /* down */ t.cursorX, /* left */ 0 /* right */ )
+	t.cursorX = 0
+	t.clearLineToRight()
+
+	for t.cursorY > 0 {
+		t.move(1, /* up */ 0, 0, 0)
+		t.cursorY--
+		t.clearLineToRight()
+	}
+
+	if _, err = t.c.Write(t.outBuf); err != nil {
+		return
+	}
+	t.outBuf = t.outBuf[:0]
+
+	if n, err = t.c.Write(buf); err != nil {
+		return
+	}
+
+	t.queue([]byte(t.prompt))
+	chars := len(t.prompt)
+	if t.echo {
+		t.queue(t.line)
+		chars += len(t.line)
+	}
+	t.cursorX = chars % t.termWidth
+	t.cursorY = chars / t.termWidth
+	t.moveCursorToPos(t.pos)
+
+	if _, err = t.c.Write(t.outBuf); err != nil {
+		return
+	}
+	t.outBuf = t.outBuf[:0]
+	return
+}
+
+// ReadPassword temporarily changes the prompt and reads a password, without
+// echo, from the terminal.
+func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	oldPrompt := t.prompt
+	t.prompt = prompt
+	t.echo = false
+
+	line, err = t.readLine()
+
+	t.prompt = oldPrompt
+	t.echo = true
+
+	return
+}
+
+// ReadLine returns a line of input from the terminal.
+func (t *Terminal) ReadLine() (line string, err error) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	return t.readLine()
+}
+
+func (t *Terminal) readLine() (line string, err error) {
+	// t.lock must be held at this point
+
+	if t.cursorX == 0 && t.cursorY == 0 {
+		t.writeLine([]byte(t.prompt))
+		t.c.Write(t.outBuf)
+		t.outBuf = t.outBuf[:0]
+	}
+
+	for {
+		rest := t.remainder
+		lineOk := false
+		for !lineOk {
+			var key int
+			key, rest = bytesToKey(rest)
+			if key < 0 {
+				break
+			}
+			if key == keyCtrlD {
+				return "", io.EOF
+			}
+			line, lineOk = t.handleKey(key)
+		}
+		if len(rest) > 0 {
+			n := copy(t.inBuf[:], rest)
+			t.remainder = t.inBuf[:n]
+		} else {
+			t.remainder = nil
+		}
+		t.c.Write(t.outBuf)
+		t.outBuf = t.outBuf[:0]
+		if lineOk {
+			return
+		}
+
+		// t.remainder is a slice at the beginning of t.inBuf
+		// containing a partial key sequence
+		readBuf := t.inBuf[len(t.remainder):]
+		var n int
+
+		t.lock.Unlock()
+		n, err = t.c.Read(readBuf)
+		t.lock.Lock()
+
+		if err != nil {
+			return
+		}
+
+		t.remainder = t.inBuf[:n+len(t.remainder)]
+	}
+	panic("unreachable")
+}
+
+// SetPrompt sets the prompt to be used when reading subsequent lines.
+func (t *Terminal) SetPrompt(prompt string) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	t.prompt = prompt
+}
+
+func (t *Terminal) SetSize(width, height int) {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	t.termWidth, t.termHeight = width, height
+}
diff --git a/src/pkg/exp/terminal/terminal_test.go b/src/pkg/exp/terminal/terminal_test.go
new file mode 100644
index 0000000..a219721
--- /dev/null
+++ b/src/pkg/exp/terminal/terminal_test.go
@@ -0,0 +1,110 @@
+// Copyright 2011 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 terminal
+
+import (
+	"io"
+	"testing"
+)
+
+type MockTerminal struct {
+	toSend       []byte
+	bytesPerRead int
+	received     []byte
+}
+
+func (c *MockTerminal) Read(data []byte) (n int, err error) {
+	n = len(data)
+	if n == 0 {
+		return
+	}
+	if n > len(c.toSend) {
+		n = len(c.toSend)
+	}
+	if n == 0 {
+		return 0, io.EOF
+	}
+	if c.bytesPerRead > 0 && n > c.bytesPerRead {
+		n = c.bytesPerRead
+	}
+	copy(data, c.toSend[:n])
+	c.toSend = c.toSend[n:]
+	return
+}
+
+func (c *MockTerminal) Write(data []byte) (n int, err error) {
+	c.received = append(c.received, data...)
+	return len(data), nil
+}
+
+func TestClose(t *testing.T) {
+	c := &MockTerminal{}
+	ss := NewTerminal(c, "> ")
+	line, err := ss.ReadLine()
+	if line != "" {
+		t.Errorf("Expected empty line but got: %s", line)
+	}
+	if err != io.EOF {
+		t.Errorf("Error should have been EOF but got: %s", err)
+	}
+}
+
+var keyPressTests = []struct {
+	in   string
+	line string
+	err  error
+}{
+	{
+		"",
+		"",
+		io.EOF,
+	},
+	{
+		"\r",
+		"",
+		nil,
+	},
+	{
+		"foo\r",
+		"foo",
+		nil,
+	},
+	{
+		"a\x1b[Cb\r", // right
+		"ab",
+		nil,
+	},
+	{
+		"a\x1b[Db\r", // left
+		"ba",
+		nil,
+	},
+	{
+		"a\177b\r", // backspace
+		"b",
+		nil,
+	},
+}
+
+func TestKeyPresses(t *testing.T) {
+	for i, test := range keyPressTests {
+		for j := 0; j < len(test.in); j++ {
+			c := &MockTerminal{
+				toSend:       []byte(test.in),
+				bytesPerRead: j,
+			}
+			ss := NewTerminal(c, "> ")
+			line, err := ss.ReadLine()
+			if line != test.line {
+				t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
+				break
+			}
+			if err != test.err {
+				t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
+				break
+			}
+		}
+	}
+}
diff --git a/src/pkg/exp/terminal/util.go b/src/pkg/exp/terminal/util.go
new file mode 100644
index 0000000..67b287c
--- /dev/null
+++ b/src/pkg/exp/terminal/util.go
@@ -0,0 +1,115 @@
+// Copyright 2011 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
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// 	oldState, err := terminal.MakeRaw(0)
+// 	if err != nil {
+// 	        panic(err)
+// 	}
+// 	defer terminal.Restore(0, oldState)
+package terminal
+
+import (
+	"io"
+	"syscall"
+	"unsafe"
+)
+
+// State contains the state of a terminal.
+type State struct {
+	termios syscall.Termios
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+	var termios syscall.Termios
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCGETS), uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
+	return err == 0
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, error) {
+	var oldState State
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCGETS), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 {
+		return nil, err
+	}
+
+	newState := oldState.termios
+	newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF
+	newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
+		return nil, err
+	}
+
+	return &oldState, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) error {
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0)
+	return err
+}
+
+// GetSize returns the dimensions of the given terminal.
+func GetSize(fd int) (width, height int, err error) {
+	var dimensions [4]uint16
+
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 {
+		return -1, -1, err
+	}
+	return int(dimensions[1]), int(dimensions[0]), nil
+}
+
+// ReadPassword reads a line of input from a terminal without local echo.  This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, error) {
+	var oldState syscall.Termios
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCGETS), uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 {
+		return nil, err
+	}
+
+	newState := oldState
+	newState.Lflag &^= syscall.ECHO
+	if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 {
+		return nil, err
+	}
+
+	defer func() {
+		syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(&oldState)), 0, 0, 0)
+	}()
+
+	var buf [16]byte
+	var ret []byte
+	for {
+		n, err := syscall.Read(fd, buf[:])
+		if err != nil {
+			return nil, err
+		}
+		if n == 0 {
+			if len(ret) == 0 {
+				return nil, io.EOF
+			}
+			break
+		}
+		if buf[n-1] == '\n' {
+			n--
+		}
+		ret = append(ret, buf[:n]...)
+		if n < len(buf) {
+			break
+		}
+	}
+
+	return ret, nil
+}
diff --git a/src/pkg/exp/types/Makefile b/src/pkg/exp/types/Makefile
new file mode 100644
index 0000000..e8fec9f
--- /dev/null
+++ b/src/pkg/exp/types/Makefile
@@ -0,0 +1,18 @@
+# Copyright 2010 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=exp/types
+GOFILES=\
+	check.go\
+	const.go\
+	exportdata.go\
+	gcimporter.go\
+	types.go\
+	universe.go\
+
+include ../../../Make.pkg
+
+CLEANFILES+=testdata/exports.[$(OS)]
diff --git a/src/pkg/exp/types/check.go b/src/pkg/exp/types/check.go
new file mode 100644
index 0000000..09e29d1
--- /dev/null
+++ b/src/pkg/exp/types/check.go
@@ -0,0 +1,225 @@
+// Copyright 2011 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 file implements the Check function, which typechecks a package.
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/scanner"
+	"go/token"
+	"strconv"
+)
+
+const debug = false
+
+type checker struct {
+	fset *token.FileSet
+	scanner.ErrorVector
+	types map[ast.Expr]Type
+}
+
+func (c *checker) errorf(pos token.Pos, format string, args ...interface{}) string {
+	msg := fmt.Sprintf(format, args...)
+	c.Error(c.fset.Position(pos), msg)
+	return msg
+}
+
+// collectFields collects struct fields tok = token.STRUCT), interface methods
+// (tok = token.INTERFACE), and function arguments/results (tok = token.FUNC).
+func (c *checker) collectFields(tok token.Token, list *ast.FieldList, cycleOk bool) (fields ObjList, tags []string, isVariadic bool) {
+	if list != nil {
+		for _, field := range list.List {
+			ftype := field.Type
+			if t, ok := ftype.(*ast.Ellipsis); ok {
+				ftype = t.Elt
+				isVariadic = true
+			}
+			typ := c.makeType(ftype, cycleOk)
+			tag := ""
+			if field.Tag != nil {
+				assert(field.Tag.Kind == token.STRING)
+				tag, _ = strconv.Unquote(field.Tag.Value)
+			}
+			if len(field.Names) > 0 {
+				// named fields
+				for _, name := range field.Names {
+					obj := name.Obj
+					obj.Type = typ
+					fields = append(fields, obj)
+					if tok == token.STRUCT {
+						tags = append(tags, tag)
+					}
+				}
+			} else {
+				// anonymous field
+				switch tok {
+				case token.STRUCT:
+					tags = append(tags, tag)
+					fallthrough
+				case token.FUNC:
+					obj := ast.NewObj(ast.Var, "")
+					obj.Type = typ
+					fields = append(fields, obj)
+				case token.INTERFACE:
+					utyp := Underlying(typ)
+					if typ, ok := utyp.(*Interface); ok {
+						// TODO(gri) This is not good enough. Check for double declarations!
+						fields = append(fields, typ.Methods...)
+					} else if _, ok := utyp.(*Bad); !ok {
+						// if utyp is Bad, don't complain (the root cause was reported before)
+						c.errorf(ftype.Pos(), "interface contains embedded non-interface type")
+					}
+				default:
+					panic("unreachable")
+				}
+			}
+		}
+	}
+	return
+}
+
+// makeType makes a new type for an AST type specification x or returns
+// the type referred to by a type name x. If cycleOk is set, a type may
+// refer to itself directly or indirectly; otherwise cycles are errors.
+//
+func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
+	if debug {
+		fmt.Printf("makeType (cycleOk = %v)\n", cycleOk)
+		ast.Print(c.fset, x)
+		defer func() {
+			fmt.Printf("-> %T %v\n\n", typ, typ)
+		}()
+	}
+
+	switch t := x.(type) {
+	case *ast.BadExpr:
+		return &Bad{}
+
+	case *ast.Ident:
+		// type name
+		obj := t.Obj
+		if obj == nil {
+			// unresolved identifier (error has been reported before)
+			return &Bad{Msg: "unresolved identifier"}
+		}
+		if obj.Kind != ast.Typ {
+			msg := c.errorf(t.Pos(), "%s is not a type", t.Name)
+			return &Bad{Msg: msg}
+		}
+		c.checkObj(obj, cycleOk)
+		if !cycleOk && obj.Type.(*Name).Underlying == nil {
+			// TODO(gri) Enable this message again once its position
+			// is independent of the underlying map implementation.
+			// msg := c.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
+			msg := "illegal cycle"
+			return &Bad{Msg: msg}
+		}
+		return obj.Type.(Type)
+
+	case *ast.ParenExpr:
+		return c.makeType(t.X, cycleOk)
+
+	case *ast.SelectorExpr:
+		// qualified identifier
+		// TODO (gri) eventually, this code belongs to expression
+		//            type checking - here for the time being
+		if ident, ok := t.X.(*ast.Ident); ok {
+			if obj := ident.Obj; obj != nil {
+				if obj.Kind != ast.Pkg {
+					msg := c.errorf(ident.Pos(), "%s is not a package", obj.Name)
+					return &Bad{Msg: msg}
+				}
+				// TODO(gri) we have a package name but don't
+				// have the mapping from package name to package
+				// scope anymore (created in ast.NewPackage).
+				return &Bad{} // for now
+			}
+		}
+		// TODO(gri) can this really happen (the parser should have excluded this)?
+		msg := c.errorf(t.Pos(), "expected qualified identifier")
+		return &Bad{Msg: msg}
+
+	case *ast.StarExpr:
+		return &Pointer{Base: c.makeType(t.X, true)}
+
+	case *ast.ArrayType:
+		if t.Len != nil {
+			// TODO(gri) compute length
+			return &Array{Elt: c.makeType(t.Elt, cycleOk)}
+		}
+		return &Slice{Elt: c.makeType(t.Elt, true)}
+
+	case *ast.StructType:
+		fields, tags, _ := c.collectFields(token.STRUCT, t.Fields, cycleOk)
+		return &Struct{Fields: fields, Tags: tags}
+
+	case *ast.FuncType:
+		params, _, _ := c.collectFields(token.FUNC, t.Params, true)
+		results, _, isVariadic := c.collectFields(token.FUNC, t.Results, true)
+		return &Func{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
+
+	case *ast.InterfaceType:
+		methods, _, _ := c.collectFields(token.INTERFACE, t.Methods, cycleOk)
+		methods.Sort()
+		return &Interface{Methods: methods}
+
+	case *ast.MapType:
+		return &Map{Key: c.makeType(t.Key, true), Elt: c.makeType(t.Key, true)}
+
+	case *ast.ChanType:
+		return &Chan{Dir: t.Dir, Elt: c.makeType(t.Value, true)}
+	}
+
+	panic(fmt.Sprintf("unreachable (%T)", x))
+}
+
+// checkObj type checks an object.
+func (c *checker) checkObj(obj *ast.Object, ref bool) {
+	if obj.Type != nil {
+		// object has already been type checked
+		return
+	}
+
+	switch obj.Kind {
+	case ast.Bad:
+		// ignore
+
+	case ast.Con:
+		// TODO(gri) complete this
+
+	case ast.Typ:
+		typ := &Name{Obj: obj}
+		obj.Type = typ // "mark" object so recursion terminates
+		typ.Underlying = Underlying(c.makeType(obj.Decl.(*ast.TypeSpec).Type, ref))
+
+	case ast.Var:
+		// TODO(gri) complete this
+
+	case ast.Fun:
+		// TODO(gri) complete this
+
+	default:
+		panic("unreachable")
+	}
+}
+
+// Check typechecks a package.
+// It augments the AST by assigning types to all ast.Objects and returns a map
+// of types for all expression nodes in statements, and a scanner.ErrorList if
+// there are errors.
+//
+func Check(fset *token.FileSet, pkg *ast.Package) (types map[ast.Expr]Type, err error) {
+	var c checker
+	c.fset = fset
+	c.types = make(map[ast.Expr]Type)
+
+	for _, obj := range pkg.Scope.Objects {
+		c.checkObj(obj, false)
+	}
+
+	return c.types, c.GetError(scanner.NoMultiples)
+}
diff --git a/src/pkg/exp/types/check_test.go b/src/pkg/exp/types/check_test.go
new file mode 100644
index 0000000..0e20646
--- /dev/null
+++ b/src/pkg/exp/types/check_test.go
@@ -0,0 +1,217 @@
+// Copyright 2011 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 file implements a typechecker test harness. The packages specified
+// in tests are typechecked. Error messages reported by the typechecker are
+// compared against the error messages expected in the test files.
+//
+// Expected errors are indicated in the test files by putting a comment
+// of the form /* ERROR "rx" */ immediately following an offending token.
+// The harness will verify that an error matching the regular expression
+// rx is reported at that source position. Consecutive comments may be
+// used to indicate multiple errors for the same token position.
+//
+// For instance, the following test file indicates that a "not declared"
+// error should be reported for the undeclared variable x:
+//
+//	package p
+//	func f() {
+//		_ = x /* ERROR "not declared" */ + 1
+//	}
+
+package types
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"regexp"
+	"testing"
+)
+
+// The test filenames do not end in .go so that they are invisible
+// to gofmt since they contain comments that must not change their
+// positions relative to surrounding tokens.
+
+var tests = []struct {
+	name  string
+	files []string
+}{
+	{"test0", []string{"testdata/test0.src"}},
+}
+
+var fset = token.NewFileSet()
+
+func getFile(filename string) (file *token.File) {
+	fset.Iterate(func(f *token.File) bool {
+		if f.Name() == filename {
+			file = f
+			return false // end iteration
+		}
+		return true
+	})
+	return file
+}
+
+func getPos(filename string, offset int) token.Pos {
+	if f := getFile(filename); f != nil {
+		return f.Pos(offset)
+	}
+	return token.NoPos
+}
+
+func parseFiles(t *testing.T, testname string, filenames []string) (map[string]*ast.File, error) {
+	files := make(map[string]*ast.File)
+	var errors scanner.ErrorList
+	for _, filename := range filenames {
+		if _, exists := files[filename]; exists {
+			t.Fatalf("%s: duplicate file %s", testname, filename)
+		}
+		file, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors)
+		if file == nil {
+			t.Fatalf("%s: could not parse file %s", testname, filename)
+		}
+		files[filename] = file
+		if err != nil {
+			// if the parser returns a non-scanner.ErrorList error
+			// the file couldn't be read in the first place and
+			// file == nil; in that case we shouldn't reach here
+			errors = append(errors, err.(scanner.ErrorList)...)
+		}
+
+	}
+	return files, errors
+}
+
+// ERROR comments must be of the form /* ERROR "rx" */ and rx is
+// a regular expression that matches the expected error message.
+//
+var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`)
+
+// expectedErrors collects the regular expressions of ERROR comments found
+// in files and returns them as a map of error positions to error messages.
+//
+func expectedErrors(t *testing.T, testname string, files map[string]*ast.File) map[token.Pos]string {
+	errors := make(map[token.Pos]string)
+	for filename := range files {
+		src, err := ioutil.ReadFile(filename)
+		if err != nil {
+			t.Fatalf("%s: could not read %s", testname, filename)
+		}
+
+		var s scanner.Scanner
+		// file was parsed already - do not add it again to the file
+		// set otherwise the position information returned here will
+		// not match the position information collected by the parser
+		s.Init(getFile(filename), src, nil, scanner.ScanComments)
+		var prev token.Pos // position of last non-comment, non-semicolon token
+
+	scanFile:
+		for {
+			pos, tok, lit := s.Scan()
+			switch tok {
+			case token.EOF:
+				break scanFile
+			case token.COMMENT:
+				s := errRx.FindStringSubmatch(lit)
+				if len(s) == 2 {
+					errors[prev] = string(s[1])
+				}
+			case token.SEMICOLON:
+				// ignore automatically inserted semicolon
+				if lit == "\n" {
+					break
+				}
+				fallthrough
+			default:
+				prev = pos
+			}
+		}
+	}
+	return errors
+}
+
+func eliminate(t *testing.T, expected map[token.Pos]string, errors error) {
+	if errors == nil {
+		return
+	}
+	for _, error := range errors.(scanner.ErrorList) {
+		// error.Pos is a token.Position, but we want
+		// a token.Pos so we can do a map lookup
+		pos := getPos(error.Pos.Filename, error.Pos.Offset)
+		if msg, found := expected[pos]; found {
+			// we expect a message at pos; check if it matches
+			rx, err := regexp.Compile(msg)
+			if err != nil {
+				t.Errorf("%s: %v", error.Pos, err)
+				continue
+			}
+			if match := rx.MatchString(error.Msg); !match {
+				t.Errorf("%s: %q does not match %q", error.Pos, error.Msg, msg)
+				continue
+			}
+			// we have a match - eliminate this error
+			delete(expected, pos)
+		} else {
+			// To keep in mind when analyzing failed test output:
+			// If the same error position occurs multiple times in errors,
+			// this message will be triggered (because the first error at
+			// the position removes this position from the expected errors).
+			t.Errorf("%s: no (multiple?) error expected, but found: %s", error.Pos, error.Msg)
+		}
+	}
+}
+
+func check(t *testing.T, testname string, testfiles []string) {
+	// TODO(gri) Eventually all these different phases should be
+	//           subsumed into a single function call that takes
+	//           a set of files and creates a fully resolved and
+	//           type-checked AST.
+
+	files, err := parseFiles(t, testname, testfiles)
+
+	// we are expecting the following errors
+	// (collect these after parsing the files so that
+	// they are found in the file set)
+	errors := expectedErrors(t, testname, files)
+
+	// verify errors returned by the parser
+	eliminate(t, errors, err)
+
+	// verify errors returned after resolving identifiers
+	pkg, err := ast.NewPackage(fset, files, GcImporter, Universe)
+	eliminate(t, errors, err)
+
+	// verify errors returned by the typechecker
+	_, err = Check(fset, pkg)
+	eliminate(t, errors, err)
+
+	// there should be no expected errors left
+	if len(errors) > 0 {
+		t.Errorf("%s: %d errors not reported:", testname, len(errors))
+		for pos, msg := range errors {
+			t.Errorf("%s: %s\n", fset.Position(pos), msg)
+		}
+	}
+}
+
+func TestCheck(t *testing.T) {
+	// For easy debugging w/o changing the testing code,
+	// if there is a local test file, only test that file.
+	const testfile = "test.go"
+	if fi, err := os.Stat(testfile); err == nil && !fi.IsDir() {
+		fmt.Printf("WARNING: Testing only %s (remove it to run all tests)\n", testfile)
+		check(t, testfile, []string{testfile})
+		return
+	}
+
+	// Otherwise, run all the tests.
+	for _, test := range tests {
+		check(t, test.name, test.files)
+	}
+}
diff --git a/src/pkg/exp/types/const.go b/src/pkg/exp/types/const.go
new file mode 100644
index 0000000..048f63b
--- /dev/null
+++ b/src/pkg/exp/types/const.go
@@ -0,0 +1,332 @@
+// Copyright 2011 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 file implements operations on ideal constants.
+
+package types
+
+import (
+	"go/token"
+	"math/big"
+	"strconv"
+)
+
+// TODO(gri) Consider changing the API so Const is an interface
+//           and operations on consts don't have to type switch.
+
+// A Const implements an ideal constant Value.
+// The zero value z for a Const is not a valid constant value.
+type Const struct {
+	// representation of constant values:
+	// ideal bool     ->  bool
+	// ideal int      ->  *big.Int
+	// ideal float    ->  *big.Rat
+	// ideal complex  ->  cmplx
+	// ideal string   ->  string
+	val interface{}
+}
+
+// Representation of complex values.
+type cmplx struct {
+	re, im *big.Rat
+}
+
+func assert(cond bool) {
+	if !cond {
+		panic("go/types internal error: assertion failed")
+	}
+}
+
+// MakeConst makes an ideal constant from a literal
+// token and the corresponding literal string.
+func MakeConst(tok token.Token, lit string) Const {
+	switch tok {
+	case token.INT:
+		var x big.Int
+		_, ok := x.SetString(lit, 0)
+		assert(ok)
+		return Const{&x}
+	case token.FLOAT:
+		var y big.Rat
+		_, ok := y.SetString(lit)
+		assert(ok)
+		return Const{&y}
+	case token.IMAG:
+		assert(lit[len(lit)-1] == 'i')
+		var im big.Rat
+		_, ok := im.SetString(lit[0 : len(lit)-1])
+		assert(ok)
+		return Const{cmplx{big.NewRat(0, 1), &im}}
+	case token.CHAR:
+		assert(lit[0] == '\'' && lit[len(lit)-1] == '\'')
+		code, _, _, err := strconv.UnquoteChar(lit[1:len(lit)-1], '\'')
+		assert(err == nil)
+		return Const{big.NewInt(int64(code))}
+	case token.STRING:
+		s, err := strconv.Unquote(lit)
+		assert(err == nil)
+		return Const{s}
+	}
+	panic("unreachable")
+}
+
+// MakeZero returns the zero constant for the given type.
+func MakeZero(typ *Type) Const {
+	// TODO(gri) fix this
+	return Const{0}
+}
+
+// Match attempts to match the internal constant representations of x and y.
+// If the attempt is successful, the result is the values of x and y,
+// if necessary converted to have the same internal representation; otherwise
+// the results are invalid.
+func (x Const) Match(y Const) (u, v Const) {
+	switch a := x.val.(type) {
+	case bool:
+		if _, ok := y.val.(bool); ok {
+			u, v = x, y
+		}
+	case *big.Int:
+		switch y.val.(type) {
+		case *big.Int:
+			u, v = x, y
+		case *big.Rat:
+			var z big.Rat
+			z.SetInt(a)
+			u, v = Const{&z}, y
+		case cmplx:
+			var z big.Rat
+			z.SetInt(a)
+			u, v = Const{cmplx{&z, big.NewRat(0, 1)}}, y
+		}
+	case *big.Rat:
+		switch y.val.(type) {
+		case *big.Int:
+			v, u = y.Match(x)
+		case *big.Rat:
+			u, v = x, y
+		case cmplx:
+			u, v = Const{cmplx{a, big.NewRat(0, 0)}}, y
+		}
+	case cmplx:
+		switch y.val.(type) {
+		case *big.Int, *big.Rat:
+			v, u = y.Match(x)
+		case cmplx:
+			u, v = x, y
+		}
+	case string:
+		if _, ok := y.val.(string); ok {
+			u, v = x, y
+		}
+	default:
+		panic("unreachable")
+	}
+	return
+}
+
+// Convert attempts to convert the constant x to a given type.
+// If the attempt is successful, the result is the new constant;
+// otherwise the result is invalid.
+func (x Const) Convert(typ *Type) Const {
+	// TODO(gri) implement this
+	switch x.val.(type) {
+	case bool:
+	case *big.Int:
+	case *big.Rat:
+	case cmplx:
+	case string:
+	}
+	return x
+}
+
+func (x Const) String() string {
+	switch x := x.val.(type) {
+	case bool:
+		if x {
+			return "true"
+		}
+		return "false"
+	case *big.Int:
+		return x.String()
+	case *big.Rat:
+		return x.FloatString(10) // 10 digits of precision after decimal point seems fine
+	case cmplx:
+		// TODO(gri) don't print 0 components
+		return x.re.FloatString(10) + " + " + x.im.FloatString(10) + "i"
+	case string:
+		return x
+	}
+	panic("unreachable")
+}
+
+func (x Const) UnaryOp(op token.Token) Const {
+	panic("unimplemented")
+}
+
+func (x Const) BinaryOp(op token.Token, y Const) Const {
+	var z interface{}
+	switch x := x.val.(type) {
+	case bool:
+		z = binaryBoolOp(x, op, y.val.(bool))
+	case *big.Int:
+		z = binaryIntOp(x, op, y.val.(*big.Int))
+	case *big.Rat:
+		z = binaryFloatOp(x, op, y.val.(*big.Rat))
+	case cmplx:
+		z = binaryCmplxOp(x, op, y.val.(cmplx))
+	case string:
+		z = binaryStringOp(x, op, y.val.(string))
+	default:
+		panic("unreachable")
+	}
+	return Const{z}
+}
+
+func binaryBoolOp(x bool, op token.Token, y bool) interface{} {
+	switch op {
+	case token.EQL:
+		return x == y
+	case token.NEQ:
+		return x != y
+	}
+	panic("unreachable")
+}
+
+func binaryIntOp(x *big.Int, op token.Token, y *big.Int) interface{} {
+	var z big.Int
+	switch op {
+	case token.ADD:
+		return z.Add(x, y)
+	case token.SUB:
+		return z.Sub(x, y)
+	case token.MUL:
+		return z.Mul(x, y)
+	case token.QUO:
+		return z.Quo(x, y)
+	case token.REM:
+		return z.Rem(x, y)
+	case token.AND:
+		return z.And(x, y)
+	case token.OR:
+		return z.Or(x, y)
+	case token.XOR:
+		return z.Xor(x, y)
+	case token.AND_NOT:
+		return z.AndNot(x, y)
+	case token.SHL:
+		panic("unimplemented")
+	case token.SHR:
+		panic("unimplemented")
+	case token.EQL:
+		return x.Cmp(y) == 0
+	case token.NEQ:
+		return x.Cmp(y) != 0
+	case token.LSS:
+		return x.Cmp(y) < 0
+	case token.LEQ:
+		return x.Cmp(y) <= 0
+	case token.GTR:
+		return x.Cmp(y) > 0
+	case token.GEQ:
+		return x.Cmp(y) >= 0
+	}
+	panic("unreachable")
+}
+
+func binaryFloatOp(x *big.Rat, op token.Token, y *big.Rat) interface{} {
+	var z big.Rat
+	switch op {
+	case token.ADD:
+		return z.Add(x, y)
+	case token.SUB:
+		return z.Sub(x, y)
+	case token.MUL:
+		return z.Mul(x, y)
+	case token.QUO:
+		return z.Quo(x, y)
+	case token.EQL:
+		return x.Cmp(y) == 0
+	case token.NEQ:
+		return x.Cmp(y) != 0
+	case token.LSS:
+		return x.Cmp(y) < 0
+	case token.LEQ:
+		return x.Cmp(y) <= 0
+	case token.GTR:
+		return x.Cmp(y) > 0
+	case token.GEQ:
+		return x.Cmp(y) >= 0
+	}
+	panic("unreachable")
+}
+
+func binaryCmplxOp(x cmplx, op token.Token, y cmplx) interface{} {
+	a, b := x.re, x.im
+	c, d := y.re, y.im
+	switch op {
+	case token.ADD:
+		// (a+c) + i(b+d)
+		var re, im big.Rat
+		re.Add(a, c)
+		im.Add(b, d)
+		return cmplx{&re, &im}
+	case token.SUB:
+		// (a-c) + i(b-d)
+		var re, im big.Rat
+		re.Sub(a, c)
+		im.Sub(b, d)
+		return cmplx{&re, &im}
+	case token.MUL:
+		// (ac-bd) + i(bc+ad)
+		var ac, bd, bc, ad big.Rat
+		ac.Mul(a, c)
+		bd.Mul(b, d)
+		bc.Mul(b, c)
+		ad.Mul(a, d)
+		var re, im big.Rat
+		re.Sub(&ac, &bd)
+		im.Add(&bc, &ad)
+		return cmplx{&re, &im}
+	case token.QUO:
+		// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
+		var ac, bd, bc, ad, s big.Rat
+		ac.Mul(a, c)
+		bd.Mul(b, d)
+		bc.Mul(b, c)
+		ad.Mul(a, d)
+		s.Add(c.Mul(c, c), d.Mul(d, d))
+		var re, im big.Rat
+		re.Add(&ac, &bd)
+		re.Quo(&re, &s)
+		im.Sub(&bc, &ad)
+		im.Quo(&im, &s)
+		return cmplx{&re, &im}
+	case token.EQL:
+		return a.Cmp(c) == 0 && b.Cmp(d) == 0
+	case token.NEQ:
+		return a.Cmp(c) != 0 || b.Cmp(d) != 0
+	}
+	panic("unreachable")
+}
+
+func binaryStringOp(x string, op token.Token, y string) interface{} {
+	switch op {
+	case token.ADD:
+		return x + y
+	case token.EQL:
+		return x == y
+	case token.NEQ:
+		return x != y
+	case token.LSS:
+		return x < y
+	case token.LEQ:
+		return x <= y
+	case token.GTR:
+		return x > y
+	case token.GEQ:
+		return x >= y
+	}
+	panic("unreachable")
+}
diff --git a/src/pkg/exp/types/exportdata.go b/src/pkg/exp/types/exportdata.go
new file mode 100644
index 0000000..fa5b6a3
--- /dev/null
+++ b/src/pkg/exp/types/exportdata.go
@@ -0,0 +1,133 @@
+// Copyright 2011 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 file implements ExportData.
+
+package types
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"os"
+	"strconv"
+	"strings"
+)
+
+func readGopackHeader(buf *bufio.Reader) (name string, size int, err error) {
+	// See $GOROOT/include/ar.h.
+	hdr := make([]byte, 16+12+6+6+8+10+2)
+	_, err = io.ReadFull(buf, hdr)
+	if err != nil {
+		return
+	}
+	if trace {
+		fmt.Printf("header: %s", hdr)
+	}
+	s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
+	size, err = strconv.Atoi(s)
+	if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
+		err = errors.New("invalid archive header")
+		return
+	}
+	name = strings.TrimSpace(string(hdr[:16]))
+	return
+}
+
+type dataReader struct {
+	*bufio.Reader
+	io.Closer
+}
+
+// ExportData returns a readCloser positioned at the beginning of the
+// export data section of the given object/archive file, or an error.
+// It is the caller's responsibility to close the readCloser.
+//
+func ExportData(filename string) (rc io.ReadCloser, err error) {
+	file, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+
+	defer func() {
+		if err != nil {
+			file.Close()
+			// Add file name to error.
+			err = fmt.Errorf("reading export data: %s: %v", filename, err)
+		}
+	}()
+
+	buf := bufio.NewReader(file)
+
+	// Read first line to make sure this is an object file.
+	line, err := buf.ReadSlice('\n')
+	if err != nil {
+		return
+	}
+	if string(line) == "!<arch>\n" {
+		// Archive file.  Scan to __.PKGDEF, which should
+		// be second archive entry.
+		var name string
+		var size int
+
+		// First entry should be __.SYMDEF.
+		// Read and discard.
+		if name, size, err = readGopackHeader(buf); err != nil {
+			return
+		}
+		if name != "__.SYMDEF" {
+			err = errors.New("go archive does not begin with __.SYMDEF")
+			return
+		}
+		const block = 4096
+		tmp := make([]byte, block)
+		for size > 0 {
+			n := size
+			if n > block {
+				n = block
+			}
+			_, err = io.ReadFull(buf, tmp[:n])
+			if err != nil {
+				return
+			}
+			size -= n
+		}
+
+		// Second entry should be __.PKGDEF.
+		if name, size, err = readGopackHeader(buf); err != nil {
+			return
+		}
+		if name != "__.PKGDEF" {
+			err = errors.New("go archive is missing __.PKGDEF")
+			return
+		}
+
+		// Read first line of __.PKGDEF data, so that line
+		// is once again the first line of the input.
+		line, err = buf.ReadSlice('\n')
+		if err != nil {
+			return
+		}
+	}
+
+	// Now at __.PKGDEF in archive or still at beginning of file.
+	// Either way, line should begin with "go object ".
+	if !strings.HasPrefix(string(line), "go object ") {
+		err = errors.New("not a go object file")
+		return
+	}
+
+	// Skip over object header to export data.
+	// Begins after first line with $$.
+	for line[0] != '$' {
+		line, err = buf.ReadSlice('\n')
+		if err != nil {
+			return
+		}
+	}
+
+	rc = &dataReader{buf, file}
+	return
+}
diff --git a/src/pkg/exp/types/gcimporter.go b/src/pkg/exp/types/gcimporter.go
new file mode 100644
index 0000000..a573fbb
--- /dev/null
+++ b/src/pkg/exp/types/gcimporter.go
@@ -0,0 +1,842 @@
+// Copyright 2011 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 file implements an ast.Importer for gc generated object files.
+// TODO(gri) Eventually move this into a separate package outside types.
+
+package types
+
+import (
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"io"
+	"math/big"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"text/scanner"
+)
+
+const trace = false // set to true for debugging
+
+var (
+	pkgRoot = filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH)
+	pkgExts = [...]string{".a", ".5", ".6", ".8"}
+)
+
+// findPkg returns the filename and package id for an import path.
+// If no file was found, an empty filename is returned.
+func findPkg(path string) (filename, id string) {
+	if len(path) == 0 {
+		return
+	}
+
+	id = path
+	var noext string
+	switch path[0] {
+	default:
+		// "x" -> "$GOROOT/pkg/$GOOS_$GOARCH/x.ext", "x"
+		noext = filepath.Join(pkgRoot, path)
+
+	case '.':
+		// "./x" -> "/this/directory/x.ext", "/this/directory/x"
+		cwd, err := os.Getwd()
+		if err != nil {
+			return
+		}
+		noext = filepath.Join(cwd, path)
+		id = noext
+
+	case '/':
+		// "/x" -> "/x.ext", "/x"
+		noext = path
+	}
+
+	// try extensions
+	for _, ext := range pkgExts {
+		filename = noext + ext
+		if f, err := os.Stat(filename); err == nil && !f.IsDir() {
+			return
+		}
+	}
+
+	filename = "" // not found
+	return
+}
+
+// gcParser parses the exports inside a gc compiler-produced
+// object/archive file and populates its scope with the results.
+type gcParser struct {
+	scanner scanner.Scanner
+	tok     rune                   // current token
+	lit     string                 // literal string; only valid for Ident, Int, String tokens
+	id      string                 // package id of imported package
+	imports map[string]*ast.Object // package id -> package object
+}
+
+func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
+	p.scanner.Init(src)
+	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+	p.scanner.Whitespace = 1<<'\t' | 1<<' '
+	p.scanner.Filename = filename // for good error messages
+	p.next()
+	p.id = id
+	p.imports = imports
+}
+
+func (p *gcParser) next() {
+	p.tok = p.scanner.Scan()
+	switch p.tok {
+	case scanner.Ident, scanner.Int, scanner.String:
+		p.lit = p.scanner.TokenText()
+	default:
+		p.lit = ""
+	}
+	if trace {
+		fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
+	}
+}
+
+// GcImporter implements the ast.Importer signature.
+func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, err error) {
+	if path == "unsafe" {
+		return Unsafe, nil
+	}
+
+	defer func() {
+		if r := recover(); r != nil {
+			err = r.(importError) // will re-panic if r is not an importError
+			if trace {
+				panic(err) // force a stack trace
+			}
+		}
+	}()
+
+	filename, id := findPkg(path)
+	if filename == "" {
+		err = errors.New("can't find import: " + id)
+		return
+	}
+
+	if pkg = imports[id]; pkg != nil {
+		return // package was imported before
+	}
+
+	buf, err := ExportData(filename)
+	if err != nil {
+		return
+	}
+	defer buf.Close()
+
+	if trace {
+		fmt.Printf("importing %s (%s)\n", id, filename)
+	}
+
+	var p gcParser
+	p.init(filename, id, buf, imports)
+	pkg = p.parseExport()
+	return
+}
+
+// Declare inserts a named object of the given kind in scope.
+func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
+	// the object may have been imported before - if it exists
+	// already in the respective package scope, return that object
+	if obj := scope.Lookup(name); obj != nil {
+		assert(obj.Kind == kind)
+		return obj
+	}
+
+	// otherwise create a new object and insert it into the package scope
+	obj := ast.NewObj(kind, name)
+	if scope.Insert(obj) != nil {
+		p.errorf("already declared: %v %s", kind, obj.Name)
+	}
+
+	// a new type object is a named type and may be referred
+	// to before the underlying type is known - set it up
+	if kind == ast.Typ {
+		obj.Type = &Name{Obj: obj}
+	}
+
+	return obj
+}
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+// Internal errors are boxed as importErrors.
+type importError struct {
+	pos scanner.Position
+	err error
+}
+
+func (e importError) Error() string {
+	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *gcParser) error(err interface{}) {
+	if s, ok := err.(string); ok {
+		err = errors.New(s)
+	}
+	// panic with a runtime.Error if err is not an error
+	panic(importError{p.scanner.Pos(), err.(error)})
+}
+
+func (p *gcParser) errorf(format string, args ...interface{}) {
+	p.error(fmt.Sprintf(format, args...))
+}
+
+func (p *gcParser) expect(tok rune) string {
+	lit := p.lit
+	if p.tok != tok {
+		panic(1)
+		p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+	}
+	p.next()
+	return lit
+}
+
+func (p *gcParser) expectSpecial(tok string) {
+	sep := 'x' // not white space
+	i := 0
+	for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
+		sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+		p.next()
+		i++
+	}
+	if i < len(tok) {
+		p.errorf("expected %q, got %q", tok, tok[0:i])
+	}
+}
+
+func (p *gcParser) expectKeyword(keyword string) {
+	lit := p.expect(scanner.Ident)
+	if lit != keyword {
+		p.errorf("expected keyword %s, got %q", keyword, lit)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Import declarations
+
+// ImportPath = string_lit .
+//
+func (p *gcParser) parsePkgId() *ast.Object {
+	id, err := strconv.Unquote(p.expect(scanner.String))
+	if err != nil {
+		p.error(err)
+	}
+
+	switch id {
+	case "":
+		// id == "" stands for the imported package id
+		// (only known at time of package installation)
+		id = p.id
+	case "unsafe":
+		// package unsafe is not in the imports map - handle explicitly
+		return Unsafe
+	}
+
+	pkg := p.imports[id]
+	if pkg == nil {
+		scope = ast.NewScope(nil)
+		pkg = ast.NewObj(ast.Pkg, "")
+		pkg.Data = scope
+		p.imports[id] = pkg
+	}
+
+	return pkg
+}
+
+// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
+func (p *gcParser) parseDotIdent() string {
+	ident := ""
+	if p.tok != scanner.Int {
+		sep := 'x' // not white space
+		for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
+			ident += p.lit
+			sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+			p.next()
+		}
+	}
+	if ident == "" {
+		p.expect(scanner.Ident) // use expect() for error handling
+	}
+	return ident
+}
+
+// ExportedName = "@" ImportPath "." dotIdentifier .
+//
+func (p *gcParser) parseExportedName() (*ast.Object, string) {
+	p.expect('@')
+	pkg := p.parsePkgId()
+	p.expect('.')
+	name := p.parseDotIdent()
+	return pkg, name
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+// BasicType = identifier .
+//
+func (p *gcParser) parseBasicType() Type {
+	id := p.expect(scanner.Ident)
+	obj := Universe.Lookup(id)
+	if obj == nil || obj.Kind != ast.Typ {
+		p.errorf("not a basic type: %s", id)
+	}
+	return obj.Type.(Type)
+}
+
+// ArrayType = "[" int_lit "]" Type .
+//
+func (p *gcParser) parseArrayType() Type {
+	// "[" already consumed and lookahead known not to be "]"
+	lit := p.expect(scanner.Int)
+	p.expect(']')
+	elt := p.parseType()
+	n, err := strconv.ParseUint(lit, 10, 64)
+	if err != nil {
+		p.error(err)
+	}
+	return &Array{Len: n, Elt: elt}
+}
+
+// MapType = "map" "[" Type "]" Type .
+//
+func (p *gcParser) parseMapType() Type {
+	p.expectKeyword("map")
+	p.expect('[')
+	key := p.parseType()
+	p.expect(']')
+	elt := p.parseType()
+	return &Map{Key: key, Elt: elt}
+}
+
+// Name = identifier | "?" | ExportedName  .
+//
+func (p *gcParser) parseName() (name string) {
+	switch p.tok {
+	case scanner.Ident:
+		name = p.lit
+		p.next()
+	case '?':
+		// anonymous
+		p.next()
+	case '@':
+		// exported name prefixed with package path
+		_, name = p.parseExportedName()
+	default:
+		p.error("name expected")
+	}
+	return
+}
+
+// Field = Name Type [ string_lit ] .
+//
+func (p *gcParser) parseField() (fld *ast.Object, tag string) {
+	name := p.parseName()
+	ftyp := p.parseType()
+	if name == "" {
+		// anonymous field - ftyp must be T or *T and T must be a type name
+		if _, ok := Deref(ftyp).(*Name); !ok {
+			p.errorf("anonymous field expected")
+		}
+	}
+	if p.tok == scanner.String {
+		tag = p.expect(scanner.String)
+	}
+	fld = ast.NewObj(ast.Var, name)
+	fld.Type = ftyp
+	return
+}
+
+// StructType = "struct" "{" [ FieldList ] "}" .
+// FieldList  = Field { ";" Field } .
+//
+func (p *gcParser) parseStructType() Type {
+	var fields []*ast.Object
+	var tags []string
+
+	parseField := func() {
+		fld, tag := p.parseField()
+		fields = append(fields, fld)
+		tags = append(tags, tag)
+	}
+
+	p.expectKeyword("struct")
+	p.expect('{')
+	if p.tok != '}' {
+		parseField()
+		for p.tok == ';' {
+			p.next()
+			parseField()
+		}
+	}
+	p.expect('}')
+
+	return &Struct{Fields: fields, Tags: tags}
+}
+
+// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
+//
+func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) {
+	name := p.parseName()
+	if name == "" {
+		name = "_" // cannot access unnamed identifiers
+	}
+	if p.tok == '.' {
+		p.expectSpecial("...")
+		isVariadic = true
+	}
+	ptyp := p.parseType()
+	// ignore argument tag
+	if p.tok == scanner.String {
+		p.expect(scanner.String)
+	}
+	par = ast.NewObj(ast.Var, name)
+	par.Type = ptyp
+	return
+}
+
+// Parameters    = "(" [ ParameterList ] ")" .
+// ParameterList = { Parameter "," } Parameter .
+//
+func (p *gcParser) parseParameters() (list []*ast.Object, isVariadic bool) {
+	parseParameter := func() {
+		par, variadic := p.parseParameter()
+		list = append(list, par)
+		if variadic {
+			if isVariadic {
+				p.error("... not on final argument")
+			}
+			isVariadic = true
+		}
+	}
+
+	p.expect('(')
+	if p.tok != ')' {
+		parseParameter()
+		for p.tok == ',' {
+			p.next()
+			parseParameter()
+		}
+	}
+	p.expect(')')
+
+	return
+}
+
+// Signature = Parameters [ Result ] .
+// Result    = Type | Parameters .
+//
+func (p *gcParser) parseSignature() *Func {
+	params, isVariadic := p.parseParameters()
+
+	// optional result type
+	var results []*ast.Object
+	switch p.tok {
+	case scanner.Ident, '[', '*', '<', '@':
+		// single, unnamed result
+		result := ast.NewObj(ast.Var, "_")
+		result.Type = p.parseType()
+		results = []*ast.Object{result}
+	case '(':
+		// named or multiple result(s)
+		var variadic bool
+		results, variadic = p.parseParameters()
+		if variadic {
+			p.error("... not permitted on result type")
+		}
+	}
+
+	return &Func{Params: params, Results: results, IsVariadic: isVariadic}
+}
+
+// MethodOrEmbedSpec = Name [ Signature ] .
+//
+func (p *gcParser) parseMethodOrEmbedSpec() *ast.Object {
+	p.parseName()
+	if p.tok == '(' {
+		p.parseSignature()
+		// TODO(gri) compute method object
+		return ast.NewObj(ast.Fun, "_")
+	}
+	// TODO lookup name and return that type
+	return ast.NewObj(ast.Typ, "_")
+}
+
+// InterfaceType = "interface" "{" [ MethodOrEmbedList ] "}" .
+// MethodOrEmbedList = MethodOrEmbedSpec { ";" MethodOrEmbedSpec } .
+//
+func (p *gcParser) parseInterfaceType() Type {
+	var methods ObjList
+
+	parseMethod := func() {
+		switch m := p.parseMethodOrEmbedSpec(); m.Kind {
+		case ast.Typ:
+			// TODO expand embedded methods
+		case ast.Fun:
+			methods = append(methods, m)
+		}
+	}
+
+	p.expectKeyword("interface")
+	p.expect('{')
+	if p.tok != '}' {
+		parseMethod()
+		for p.tok == ';' {
+			p.next()
+			parseMethod()
+		}
+	}
+	p.expect('}')
+
+	methods.Sort()
+	return &Interface{Methods: methods}
+}
+
+// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
+//
+func (p *gcParser) parseChanType() Type {
+	dir := ast.SEND | ast.RECV
+	if p.tok == scanner.Ident {
+		p.expectKeyword("chan")
+		if p.tok == '<' {
+			p.expectSpecial("<-")
+			dir = ast.SEND
+		}
+	} else {
+		p.expectSpecial("<-")
+		p.expectKeyword("chan")
+		dir = ast.RECV
+	}
+	elt := p.parseType()
+	return &Chan{Dir: dir, Elt: elt}
+}
+
+// Type =
+//	BasicType | TypeName | ArrayType | SliceType | StructType |
+//      PointerType | FuncType | InterfaceType | MapType | ChanType |
+//      "(" Type ")" .
+// BasicType = ident .
+// TypeName = ExportedName .
+// SliceType = "[" "]" Type .
+// PointerType = "*" Type .
+// FuncType = "func" Signature .
+//
+func (p *gcParser) parseType() Type {
+	switch p.tok {
+	case scanner.Ident:
+		switch p.lit {
+		default:
+			return p.parseBasicType()
+		case "struct":
+			return p.parseStructType()
+		case "func":
+			// FuncType
+			p.next()
+			return p.parseSignature()
+		case "interface":
+			return p.parseInterfaceType()
+		case "map":
+			return p.parseMapType()
+		case "chan":
+			return p.parseChanType()
+		}
+	case '@':
+		// TypeName
+		pkg, name := p.parseExportedName()
+		return p.declare(pkg.Data.(*ast.Scope), ast.Typ, name).Type.(Type)
+	case '[':
+		p.next() // look ahead
+		if p.tok == ']' {
+			// SliceType
+			p.next()
+			return &Slice{Elt: p.parseType()}
+		}
+		return p.parseArrayType()
+	case '*':
+		// PointerType
+		p.next()
+		return &Pointer{Base: p.parseType()}
+	case '<':
+		return p.parseChanType()
+	case '(':
+		// "(" Type ")"
+		p.next()
+		typ := p.parseType()
+		p.expect(')')
+		return typ
+	}
+	p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+	return nil
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// ImportDecl = "import" identifier string_lit .
+//
+func (p *gcParser) parseImportDecl() {
+	p.expectKeyword("import")
+	// The identifier has no semantic meaning in the import data.
+	// It exists so that error messages can print the real package
+	// name: binary.ByteOrder instead of "encoding/binary".ByteOrder.
+	name := p.expect(scanner.Ident)
+	pkg := p.parsePkgId()
+	assert(pkg.Name == "" || pkg.Name == name)
+	pkg.Name = name
+}
+
+// int_lit = [ "+" | "-" ] { "0" ... "9" } .
+//
+func (p *gcParser) parseInt() (sign, val string) {
+	switch p.tok {
+	case '-':
+		p.next()
+		sign = "-"
+	case '+':
+		p.next()
+	}
+	val = p.expect(scanner.Int)
+	return
+}
+
+// number = int_lit [ "p" int_lit ] .
+//
+func (p *gcParser) parseNumber() Const {
+	// mantissa
+	sign, val := p.parseInt()
+	mant, ok := new(big.Int).SetString(sign+val, 10)
+	assert(ok)
+
+	if p.lit == "p" {
+		// exponent (base 2)
+		p.next()
+		sign, val = p.parseInt()
+		exp64, err := strconv.ParseUint(val, 10, 0)
+		if err != nil {
+			p.error(err)
+		}
+		exp := uint(exp64)
+		if sign == "-" {
+			denom := big.NewInt(1)
+			denom.Lsh(denom, exp)
+			return Const{new(big.Rat).SetFrac(mant, denom)}
+		}
+		if exp > 0 {
+			mant.Lsh(mant, exp)
+		}
+		return Const{new(big.Rat).SetInt(mant)}
+	}
+
+	return Const{mant}
+}
+
+// ConstDecl   = "const" ExportedName [ Type ] "=" Literal .
+// Literal     = bool_lit | int_lit | float_lit | complex_lit | string_lit .
+// bool_lit    = "true" | "false" .
+// complex_lit = "(" float_lit "+" float_lit ")" .
+// rune_lit = "(" int_lit "+" int_lit ")" .
+// string_lit  = `"` { unicode_char } `"` .
+//
+func (p *gcParser) parseConstDecl() {
+	p.expectKeyword("const")
+	pkg, name := p.parseExportedName()
+	obj := p.declare(pkg.Data.(*ast.Scope), ast.Con, name)
+	var x Const
+	var typ Type
+	if p.tok != '=' {
+		obj.Type = p.parseType()
+	}
+	p.expect('=')
+	switch p.tok {
+	case scanner.Ident:
+		// bool_lit
+		if p.lit != "true" && p.lit != "false" {
+			p.error("expected true or false")
+		}
+		x = Const{p.lit == "true"}
+		typ = Bool.Underlying
+		p.next()
+	case '-', scanner.Int:
+		// int_lit
+		x = p.parseNumber()
+		typ = Int.Underlying
+		if _, ok := x.val.(*big.Rat); ok {
+			typ = Float64.Underlying
+		}
+	case '(':
+		// complex_lit or rune_lit
+		p.next()
+		if p.tok == scanner.Char {
+			p.next()
+			p.expect('+')
+			p.parseNumber()
+			p.expect(')')
+			// TODO: x = ...
+			break
+		}
+		re := p.parseNumber()
+		p.expect('+')
+		im := p.parseNumber()
+		p.expect(')')
+		x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
+		typ = Complex128.Underlying
+	case scanner.Char:
+		// TODO: x = ...
+		p.next()
+	case scanner.String:
+		// string_lit
+		x = MakeConst(token.STRING, p.lit)
+		p.next()
+		typ = String.Underlying
+	default:
+		println(p.tok)
+		p.errorf("expected literal got %s", scanner.TokenString(p.tok))
+	}
+	if obj.Type == nil {
+		obj.Type = typ
+	}
+	obj.Data = x
+}
+
+// TypeDecl = "type" ExportedName Type .
+//
+func (p *gcParser) parseTypeDecl() {
+	p.expectKeyword("type")
+	pkg, name := p.parseExportedName()
+	obj := p.declare(pkg.Data.(*ast.Scope), ast.Typ, name)
+
+	// The type object may have been imported before and thus already
+	// have a type associated with it. We still need to parse the type
+	// structure, but throw it away if the object already has a type.
+	// This ensures that all imports refer to the same type object for
+	// a given type declaration.
+	typ := p.parseType()
+
+	if name := obj.Type.(*Name); name.Underlying == nil {
+		assert(Underlying(typ) == typ)
+		name.Underlying = typ
+	}
+}
+
+// VarDecl = "var" ExportedName Type .
+//
+func (p *gcParser) parseVarDecl() {
+	p.expectKeyword("var")
+	pkg, name := p.parseExportedName()
+	obj := p.declare(pkg.Data.(*ast.Scope), ast.Var, name)
+	obj.Type = p.parseType()
+}
+
+// FuncBody = "{" ... "}" .
+// 
+func (p *gcParser) parseFuncBody() {
+	p.expect('{')
+	for i := 1; i > 0; p.next() {
+		switch p.tok {
+		case '{':
+			i++
+		case '}':
+			i--
+		}
+	}
+}
+
+// FuncDecl = "func" ExportedName Signature [ FuncBody ] .
+//
+func (p *gcParser) parseFuncDecl() {
+	// "func" already consumed
+	pkg, name := p.parseExportedName()
+	obj := p.declare(pkg.Data.(*ast.Scope), ast.Fun, name)
+	obj.Type = p.parseSignature()
+	if p.tok == '{' {
+		p.parseFuncBody()
+	}
+}
+
+// MethodDecl = "func" Receiver Name Signature .
+// Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
+//
+func (p *gcParser) parseMethodDecl() {
+	// "func" already consumed
+	p.expect('(')
+	p.parseParameter() // receiver
+	p.expect(')')
+	p.parseName() // unexported method names in imports are qualified with their package.
+	p.parseSignature()
+	if p.tok == '{' {
+		p.parseFuncBody()
+	}
+}
+
+// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
+//
+func (p *gcParser) parseDecl() {
+	switch p.lit {
+	case "import":
+		p.parseImportDecl()
+	case "const":
+		p.parseConstDecl()
+	case "type":
+		p.parseTypeDecl()
+	case "var":
+		p.parseVarDecl()
+	case "func":
+		p.next() // look ahead
+		if p.tok == '(' {
+			p.parseMethodDecl()
+		} else {
+			p.parseFuncDecl()
+		}
+	}
+	p.expect('\n')
+}
+
+// ----------------------------------------------------------------------------
+// Export
+
+// Export        = "PackageClause { Decl } "$$" .
+// PackageClause = "package" identifier [ "safe" ] "\n" .
+//
+func (p *gcParser) parseExport() *ast.Object {
+	p.expectKeyword("package")
+	name := p.expect(scanner.Ident)
+	if p.tok != '\n' {
+		// A package is safe if it was compiled with the -u flag,
+		// which disables the unsafe package.
+		// TODO(gri) remember "safe" package
+		p.expectKeyword("safe")
+	}
+	p.expect('\n')
+
+	assert(p.imports[p.id] == nil)
+	pkg := ast.NewObj(ast.Pkg, name)
+	pkg.Data = ast.NewScope(nil)
+	p.imports[p.id] = pkg
+
+	for p.tok != '$' && p.tok != scanner.EOF {
+		p.parseDecl()
+	}
+
+	if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
+		// don't call next()/expect() since reading past the
+		// export data may cause scanner errors (e.g. NUL chars)
+		p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
+	}
+
+	if n := p.scanner.ErrorCount; n != 0 {
+		p.errorf("expected no scanner errors, got %d", n)
+	}
+
+	return pkg
+}
diff --git a/src/pkg/exp/types/gcimporter_test.go b/src/pkg/exp/types/gcimporter_test.go
new file mode 100644
index 0000000..7475d35
--- /dev/null
+++ b/src/pkg/exp/types/gcimporter_test.go
@@ -0,0 +1,101 @@
+// Copyright 2011 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 types
+
+import (
+	"go/ast"
+	"io/ioutil"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+var gcName, gcPath string // compiler name and path
+
+func init() {
+	// determine compiler
+	switch runtime.GOARCH {
+	case "386":
+		gcName = "8g"
+	case "amd64":
+		gcName = "6g"
+	case "arm":
+		gcName = "5g"
+	default:
+		gcName = "unknown-GOARCH-compiler"
+		gcPath = gcName
+		return
+	}
+	gcPath, _ = exec.LookPath(gcName)
+}
+
+func compile(t *testing.T, dirname, filename string) {
+	cmd := exec.Command(gcPath, filename)
+	cmd.Dir = dirname
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Errorf("%s %s failed: %s", gcName, filename, err)
+		return
+	}
+	t.Logf("%s", string(out))
+}
+
+// Use the same global imports map for all tests. The effect is
+// as if all tested packages were imported into a single package.
+var imports = make(map[string]*ast.Object)
+
+func testPath(t *testing.T, path string) bool {
+	_, err := GcImporter(imports, path)
+	if err != nil {
+		t.Errorf("testPath(%s): %s", path, err)
+		return false
+	}
+	return true
+}
+
+const maxTime = 3 * time.Second
+
+func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
+	dirname := filepath.Join(pkgRoot, dir)
+	list, err := ioutil.ReadDir(dirname)
+	if err != nil {
+		t.Errorf("testDir(%s): %s", dirname, err)
+	}
+	for _, f := range list {
+		if time.Now().After(endTime) {
+			t.Log("testing time used up")
+			return
+		}
+		switch {
+		case !f.IsDir():
+			// try extensions
+			for _, ext := range pkgExts {
+				if strings.HasSuffix(f.Name(), ext) {
+					name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension
+					if testPath(t, filepath.Join(dir, name)) {
+						nimports++
+					}
+				}
+			}
+		case f.IsDir():
+			nimports += testDir(t, filepath.Join(dir, f.Name()), endTime)
+		}
+	}
+	return
+}
+
+func TestGcImport(t *testing.T) {
+	compile(t, "testdata", "exports.go")
+
+	nimports := 0
+	if testPath(t, "./testdata/exports") {
+		nimports++
+	}
+	nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
+	t.Logf("tested %d imports", nimports)
+}
diff --git a/src/pkg/go/types/testdata/exports.go b/src/pkg/exp/types/testdata/exports.go
similarity index 100%
rename from src/pkg/go/types/testdata/exports.go
rename to src/pkg/exp/types/testdata/exports.go
diff --git a/src/pkg/go/types/testdata/test0.src b/src/pkg/exp/types/testdata/test0.src
similarity index 100%
rename from src/pkg/go/types/testdata/test0.src
rename to src/pkg/exp/types/testdata/test0.src
diff --git a/src/pkg/go/types/types.go b/src/pkg/exp/types/types.go
similarity index 100%
rename from src/pkg/go/types/types.go
rename to src/pkg/exp/types/types.go
diff --git a/src/pkg/exp/types/universe.go b/src/pkg/exp/types/universe.go
new file mode 100644
index 0000000..46cff31
--- /dev/null
+++ b/src/pkg/exp/types/universe.go
@@ -0,0 +1,112 @@
+// Copyright 2011 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.
+
+// FILE UNDER CONSTRUCTION. ANY AND ALL PARTS MAY CHANGE.
+// This file implements the universe and unsafe package scopes.
+
+package types
+
+import "go/ast"
+
+var (
+	scope    *ast.Scope // current scope to use for initialization
+	Universe *ast.Scope
+	Unsafe   *ast.Object // package unsafe
+)
+
+func define(kind ast.ObjKind, name string) *ast.Object {
+	obj := ast.NewObj(kind, name)
+	if scope.Insert(obj) != nil {
+		panic("types internal error: double declaration")
+	}
+	obj.Decl = scope
+	return obj
+}
+
+func defType(name string) *Name {
+	obj := define(ast.Typ, name)
+	typ := &Name{Underlying: &Basic{}, Obj: obj}
+	obj.Type = typ
+	return typ
+}
+
+func defConst(name string) {
+	obj := define(ast.Con, name)
+	_ = obj // TODO(gri) fill in other properties
+}
+
+func defFun(name string) {
+	obj := define(ast.Fun, name)
+	_ = obj // TODO(gri) fill in other properties
+}
+
+var (
+	Bool,
+	Int,
+	Float64,
+	Complex128,
+	String *Name
+)
+
+func init() {
+	scope = ast.NewScope(nil)
+	Universe = scope
+
+	Bool = defType("bool")
+	defType("byte") // TODO(gri) should be an alias for uint8
+	defType("rune") // TODO(gri) should be an alias for int
+	defType("complex64")
+	Complex128 = defType("complex128")
+	defType("error")
+	defType("float32")
+	Float64 = defType("float64")
+	defType("int8")
+	defType("int16")
+	defType("int32")
+	defType("int64")
+	String = defType("string")
+	defType("uint8")
+	defType("uint16")
+	defType("uint32")
+	defType("uint64")
+	Int = defType("int")
+	defType("uint")
+	defType("uintptr")
+
+	defConst("true")
+	defConst("false")
+	defConst("iota")
+	defConst("nil")
+
+	defFun("append")
+	defFun("cap")
+	defFun("close")
+	defFun("complex")
+	defFun("copy")
+	defFun("delete")
+	defFun("imag")
+	defFun("len")
+	defFun("make")
+	defFun("new")
+	defFun("panic")
+	defFun("print")
+	defFun("println")
+	defFun("real")
+	defFun("recover")
+
+	scope = ast.NewScope(nil)
+	Unsafe = ast.NewObj(ast.Pkg, "unsafe")
+	Unsafe.Data = scope
+
+	defType("Pointer")
+
+	defFun("Alignof")
+	defFun("New")
+	defFun("NewArray")
+	defFun("Offsetof")
+	defFun("Reflect")
+	defFun("Sizeof")
+	defFun("Typeof")
+	defFun("Unreflect")
+}
diff --git a/src/pkg/exp/utf8string/Makefile b/src/pkg/exp/utf8string/Makefile
new file mode 100644
index 0000000..49c1928
--- /dev/null
+++ b/src/pkg/exp/utf8string/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=exp/utf8string
+GOFILES=\
+	string.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/exp/utf8string/string.go b/src/pkg/exp/utf8string/string.go
new file mode 100644
index 0000000..da1e2de
--- /dev/null
+++ b/src/pkg/exp/utf8string/string.go
@@ -0,0 +1,203 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package utf8string provides an efficient way to index strings by rune rather than by byte.
+package utf8string
+
+import (
+	"errors"
+	"unicode/utf8"
+)
+
+// String wraps a regular string with a small structure that provides more
+// efficient indexing by code point index, as opposed to byte index.
+// Scanning incrementally forwards or backwards is O(1) per index operation
+// (although not as fast a range clause going forwards).  Random access is
+// O(N) in the length of the string, but the overhead is less than always
+// scanning from the beginning.
+// If the string is ASCII, random access is O(1).
+// Unlike the built-in string type, String has internal mutable state and
+// is not thread-safe.
+type String struct {
+	str      string
+	numRunes int
+	// If width > 0, the rune at runePos starts at bytePos and has the specified width.
+	width    int
+	bytePos  int
+	runePos  int
+	nonASCII int // byte index of the first non-ASCII rune.
+}
+
+// NewString returns a new UTF-8 string with the provided contents.
+func NewString(contents string) *String {
+	return new(String).Init(contents)
+}
+
+// Init initializes an existing String to hold the provided contents.
+// It returns a pointer to the initialized String.
+func (s *String) Init(contents string) *String {
+	s.str = contents
+	s.bytePos = 0
+	s.runePos = 0
+	for i := 0; i < len(contents); i++ {
+		if contents[i] >= utf8.RuneSelf {
+			// Not ASCII.
+			s.numRunes = utf8.RuneCountInString(contents)
+			_, s.width = utf8.DecodeRuneInString(contents)
+			s.nonASCII = i
+			return s
+		}
+	}
+	// ASCII is simple.  Also, the empty string is ASCII.
+	s.numRunes = len(contents)
+	s.width = 0
+	s.nonASCII = len(contents)
+	return s
+}
+
+// String returns the contents of the String.  This method also means the
+// String is directly printable by fmt.Print.
+func (s *String) String() string {
+	return s.str
+}
+
+// RuneCount returns the number of runes (Unicode code points) in the String.
+func (s *String) RuneCount() int {
+	return s.numRunes
+}
+
+// IsASCII returns a boolean indicating whether the String contains only ASCII bytes.
+func (s *String) IsASCII() bool {
+	return s.width == 0
+}
+
+// Slice returns the string sliced at rune positions [i:j].
+func (s *String) Slice(i, j int) string {
+	// ASCII is easy.  Let the compiler catch the indexing error if there is one.
+	if j < s.nonASCII {
+		return s.str[i:j]
+	}
+	if i < 0 || j > s.numRunes || i > j {
+		panic(sliceOutOfRange)
+	}
+	if i == j {
+		return ""
+	}
+	// For non-ASCII, after At(i), bytePos is always the position of the indexed character.
+	var low, high int
+	switch {
+	case i < s.nonASCII:
+		low = i
+	case i == s.numRunes:
+		low = len(s.str)
+	default:
+		s.At(i)
+		low = s.bytePos
+	}
+	switch {
+	case j == s.numRunes:
+		high = len(s.str)
+	default:
+		s.At(j)
+		high = s.bytePos
+	}
+	return s.str[low:high]
+}
+
+// At returns the rune with index i in the String.  The sequence of runes is the same
+// as iterating over the contents with a "for range" clause.
+func (s *String) At(i int) rune {
+	// ASCII is easy.  Let the compiler catch the indexing error if there is one.
+	if i < s.nonASCII {
+		return rune(s.str[i])
+	}
+
+	// Now we do need to know the index is valid.
+	if i < 0 || i >= s.numRunes {
+		panic(outOfRange)
+	}
+
+	var r rune
+
+	// Five easy common cases: within 1 spot of bytePos/runePos, or the beginning, or the end.
+	// With these cases, all scans from beginning or end work in O(1) time per rune.
+	switch {
+
+	case i == s.runePos-1: // backing up one rune
+		r, s.width = utf8.DecodeLastRuneInString(s.str[0:s.bytePos])
+		s.runePos = i
+		s.bytePos -= s.width
+		return r
+	case i == s.runePos+1: // moving ahead one rune
+		s.runePos = i
+		s.bytePos += s.width
+		fallthrough
+	case i == s.runePos:
+		r, s.width = utf8.DecodeRuneInString(s.str[s.bytePos:])
+		return r
+	case i == 0: // start of string
+		r, s.width = utf8.DecodeRuneInString(s.str)
+		s.runePos = 0
+		s.bytePos = 0
+		return r
+
+	case i == s.numRunes-1: // last rune in string
+		r, s.width = utf8.DecodeLastRuneInString(s.str)
+		s.runePos = i
+		s.bytePos = len(s.str) - s.width
+		return r
+	}
+
+	// We need to do a linear scan.  There are three places to start from:
+	// 1) The beginning
+	// 2) bytePos/runePos.
+	// 3) The end
+	// Choose the closest in rune count, scanning backwards if necessary.
+	forward := true
+	if i < s.runePos {
+		// Between beginning and pos.  Which is closer?
+		// Since both i and runePos are guaranteed >= nonASCII, that's the
+		// lowest location we need to start from.
+		if i < (s.runePos-s.nonASCII)/2 {
+			// Scan forward from beginning
+			s.bytePos, s.runePos = s.nonASCII, s.nonASCII
+		} else {
+			// Scan backwards from where we are
+			forward = false
+		}
+	} else {
+		// Between pos and end.  Which is closer?
+		if i-s.runePos < (s.numRunes-s.runePos)/2 {
+			// Scan forward from pos
+		} else {
+			// Scan backwards from end
+			s.bytePos, s.runePos = len(s.str), s.numRunes
+			forward = false
+		}
+	}
+	if forward {
+		// TODO: Is it much faster to use a range loop for this scan?
+		for {
+			r, s.width = utf8.DecodeRuneInString(s.str[s.bytePos:])
+			if s.runePos == i {
+				break
+			}
+			s.runePos++
+			s.bytePos += s.width
+		}
+	} else {
+		for {
+			r, s.width = utf8.DecodeLastRuneInString(s.str[0:s.bytePos])
+			s.runePos--
+			s.bytePos -= s.width
+			if s.runePos == i {
+				break
+			}
+		}
+	}
+	return r
+}
+
+var outOfRange = errors.New("utf8.String: index out of range")
+var sliceOutOfRange = errors.New("utf8.String: slice index out of range")
diff --git a/src/pkg/exp/utf8string/string_test.go b/src/pkg/exp/utf8string/string_test.go
new file mode 100644
index 0000000..28511b2
--- /dev/null
+++ b/src/pkg/exp/utf8string/string_test.go
@@ -0,0 +1,123 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package utf8string
+
+import (
+	"math/rand"
+	"testing"
+	"unicode/utf8"
+)
+
+var testStrings = []string{
+	"",
+	"abcd",
+	"☺☻☹",
+	"日a本b語ç日ð本Ê語þ日¥本¼語i日©",
+	"日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©",
+	"\x80\x80\x80\x80",
+}
+
+func TestScanForwards(t *testing.T) {
+	for _, s := range testStrings {
+		runes := []rune(s)
+		str := NewString(s)
+		if str.RuneCount() != len(runes) {
+			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
+			break
+		}
+		for i, expect := range runes {
+			got := str.At(i)
+			if got != expect {
+				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
+			}
+		}
+	}
+}
+
+func TestScanBackwards(t *testing.T) {
+	for _, s := range testStrings {
+		runes := []rune(s)
+		str := NewString(s)
+		if str.RuneCount() != len(runes) {
+			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
+			break
+		}
+		for i := len(runes) - 1; i >= 0; i-- {
+			expect := runes[i]
+			got := str.At(i)
+			if got != expect {
+				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
+			}
+		}
+	}
+}
+
+func randCount() int {
+	if testing.Short() {
+		return 100
+	}
+	return 100000
+}
+
+func TestRandomAccess(t *testing.T) {
+	for _, s := range testStrings {
+		if len(s) == 0 {
+			continue
+		}
+		runes := []rune(s)
+		str := NewString(s)
+		if str.RuneCount() != len(runes) {
+			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
+			break
+		}
+		for j := 0; j < randCount(); j++ {
+			i := rand.Intn(len(runes))
+			expect := runes[i]
+			got := str.At(i)
+			if got != expect {
+				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
+			}
+		}
+	}
+}
+
+func TestRandomSliceAccess(t *testing.T) {
+	for _, s := range testStrings {
+		if len(s) == 0 || s[0] == '\x80' { // the bad-UTF-8 string fools this simple test
+			continue
+		}
+		runes := []rune(s)
+		str := NewString(s)
+		if str.RuneCount() != len(runes) {
+			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
+			break
+		}
+		for k := 0; k < randCount(); k++ {
+			i := rand.Intn(len(runes))
+			j := rand.Intn(len(runes) + 1)
+			if i > j { // include empty strings
+				continue
+			}
+			expect := string(runes[i:j])
+			got := str.Slice(i, j)
+			if got != expect {
+				t.Errorf("%s[%d:%d]: expected %q got %q", s, i, j, expect, got)
+			}
+		}
+	}
+}
+
+func TestLimitSliceAccess(t *testing.T) {
+	for _, s := range testStrings {
+		str := NewString(s)
+		if str.Slice(0, 0) != "" {
+			t.Error("failure with empty slice at beginning")
+		}
+		nr := utf8.RuneCountInString(s)
+		if str.Slice(nr, nr) != "" {
+			t.Error("failure with empty slice at end")
+		}
+	}
+}
diff --git a/src/pkg/exp/winfsnotify/Makefile b/src/pkg/exp/winfsnotify/Makefile
new file mode 100644
index 0000000..f0fe096
--- /dev/null
+++ b/src/pkg/exp/winfsnotify/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=exp/winfsnotify
+GOFILES=\
+	winfsnotify.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/exp/winfsnotify/winfsnotify.go b/src/pkg/exp/winfsnotify/winfsnotify.go
new file mode 100644
index 0000000..a6e3a6a
--- /dev/null
+++ b/src/pkg/exp/winfsnotify/winfsnotify.go
@@ -0,0 +1,572 @@
+// Copyright 2011 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 windows
+
+// Package winfsnotify allows the user to receive
+// file system event notifications on Windows.
+package winfsnotify
+
+import (
+	"errors"
+	"fmt"
+	"os"
+	"path/filepath"
+	"runtime"
+	"syscall"
+	"unsafe"
+)
+
+// Event is the type of the notification messages
+// received on the watcher's Event channel.
+type Event struct {
+	Mask   uint32 // Mask of events
+	Cookie uint32 // Unique cookie associating related events (for rename)
+	Name   string // File name (optional)
+}
+
+const (
+	opAddWatch = iota
+	opRemoveWatch
+)
+
+const (
+	provisional uint64 = 1 << (32 + iota)
+)
+
+type input struct {
+	op    int
+	path  string
+	flags uint32
+	reply chan error
+}
+
+type inode struct {
+	handle syscall.Handle
+	volume uint32
+	index  uint64
+}
+
+type watch struct {
+	ov     syscall.Overlapped
+	ino    *inode            // i-number
+	path   string            // Directory path
+	mask   uint64            // Directory itself is being watched with these notify flags
+	names  map[string]uint64 // Map of names being watched and their notify flags
+	rename string            // Remembers the old name while renaming a file
+	buf    [4096]byte
+}
+
+type indexMap map[uint64]*watch
+type watchMap map[uint32]indexMap
+
+// A Watcher waits for and receives event notifications
+// for a specific set of files and directories.
+type Watcher struct {
+	port     syscall.Handle // Handle to completion port
+	watches  watchMap       // Map of watches (key: i-number)
+	input    chan *input    // Inputs to the reader are sent on this channel
+	Event    chan *Event    // Events are returned on this channel
+	Error    chan error     // Errors are sent on this channel
+	isClosed bool           // Set to true when Close() is first called
+	quit     chan chan<- error
+	cookie   uint32
+}
+
+// NewWatcher creates and returns a Watcher.
+func NewWatcher() (*Watcher, error) {
+	port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0)
+	if e != nil {
+		return nil, os.NewSyscallError("CreateIoCompletionPort", e)
+	}
+	w := &Watcher{
+		port:    port,
+		watches: make(watchMap),
+		input:   make(chan *input, 1),
+		Event:   make(chan *Event, 50),
+		Error:   make(chan error),
+		quit:    make(chan chan<- error, 1),
+	}
+	go w.readEvents()
+	return w, nil
+}
+
+// Close closes a Watcher.
+// It sends a message to the reader goroutine to quit and removes all watches
+// associated with the watcher.
+func (w *Watcher) Close() error {
+	if w.isClosed {
+		return nil
+	}
+	w.isClosed = true
+
+	// Send "quit" message to the reader goroutine
+	ch := make(chan error)
+	w.quit <- ch
+	if err := w.wakeupReader(); err != nil {
+		return err
+	}
+	return <-ch
+}
+
+// AddWatch adds path to the watched file set.
+func (w *Watcher) AddWatch(path string, flags uint32) error {
+	if w.isClosed {
+		return errors.New("watcher already closed")
+	}
+	in := &input{
+		op:    opAddWatch,
+		path:  filepath.Clean(path),
+		flags: flags,
+		reply: make(chan error),
+	}
+	w.input <- in
+	if err := w.wakeupReader(); err != nil {
+		return err
+	}
+	return <-in.reply
+}
+
+// Watch adds path to the watched file set, watching all events.
+func (w *Watcher) Watch(path string) error {
+	return w.AddWatch(path, FS_ALL_EVENTS)
+}
+
+// RemoveWatch removes path from the watched file set.
+func (w *Watcher) RemoveWatch(path string) error {
+	in := &input{
+		op:    opRemoveWatch,
+		path:  filepath.Clean(path),
+		reply: make(chan error),
+	}
+	w.input <- in
+	if err := w.wakeupReader(); err != nil {
+		return err
+	}
+	return <-in.reply
+}
+
+func (w *Watcher) wakeupReader() error {
+	e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil)
+	if e != nil {
+		return os.NewSyscallError("PostQueuedCompletionStatus", e)
+	}
+	return nil
+}
+
+func getDir(pathname string) (dir string, err error) {
+	attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname))
+	if e != nil {
+		return "", os.NewSyscallError("GetFileAttributes", e)
+	}
+	if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
+		dir = pathname
+	} else {
+		dir, _ = filepath.Split(pathname)
+		dir = filepath.Clean(dir)
+	}
+	return
+}
+
+func getIno(path string) (ino *inode, err error) {
+	h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path),
+		syscall.FILE_LIST_DIRECTORY,
+		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
+		nil, syscall.OPEN_EXISTING,
+		syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0)
+	if e != nil {
+		return nil, os.NewSyscallError("CreateFile", e)
+	}
+	var fi syscall.ByHandleFileInformation
+	if e = syscall.GetFileInformationByHandle(h, &fi); e != nil {
+		syscall.CloseHandle(h)
+		return nil, os.NewSyscallError("GetFileInformationByHandle", e)
+	}
+	ino = &inode{
+		handle: h,
+		volume: fi.VolumeSerialNumber,
+		index:  uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow),
+	}
+	return ino, nil
+}
+
+// Must run within the I/O thread.
+func (m watchMap) get(ino *inode) *watch {
+	if i := m[ino.volume]; i != nil {
+		return i[ino.index]
+	}
+	return nil
+}
+
+// Must run within the I/O thread.
+func (m watchMap) set(ino *inode, watch *watch) {
+	i := m[ino.volume]
+	if i == nil {
+		i = make(indexMap)
+		m[ino.volume] = i
+	}
+	i[ino.index] = watch
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) addWatch(pathname string, flags uint64) error {
+	dir, err := getDir(pathname)
+	if err != nil {
+		return err
+	}
+	if flags&FS_ONLYDIR != 0 && pathname != dir {
+		return nil
+	}
+	ino, err := getIno(dir)
+	if err != nil {
+		return err
+	}
+	watchEntry := w.watches.get(ino)
+	if watchEntry == nil {
+		if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil {
+			syscall.CloseHandle(ino.handle)
+			return os.NewSyscallError("CreateIoCompletionPort", e)
+		}
+		watchEntry = &watch{
+			ino:   ino,
+			path:  dir,
+			names: make(map[string]uint64),
+		}
+		w.watches.set(ino, watchEntry)
+		flags |= provisional
+	} else {
+		syscall.CloseHandle(ino.handle)
+	}
+	if pathname == dir {
+		watchEntry.mask |= flags
+	} else {
+		watchEntry.names[filepath.Base(pathname)] |= flags
+	}
+	if err = w.startRead(watchEntry); err != nil {
+		return err
+	}
+	if pathname == dir {
+		watchEntry.mask &= ^provisional
+	} else {
+		watchEntry.names[filepath.Base(pathname)] &= ^provisional
+	}
+	return nil
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) removeWatch(pathname string) error {
+	dir, err := getDir(pathname)
+	if err != nil {
+		return err
+	}
+	ino, err := getIno(dir)
+	if err != nil {
+		return err
+	}
+	watch := w.watches.get(ino)
+	if watch == nil {
+		return fmt.Errorf("can't remove non-existent watch for: %s", pathname)
+	}
+	if pathname == dir {
+		w.sendEvent(watch.path, watch.mask&FS_IGNORED)
+		watch.mask = 0
+	} else {
+		name := filepath.Base(pathname)
+		w.sendEvent(watch.path+"/"+name, watch.names[name]&FS_IGNORED)
+		delete(watch.names, name)
+	}
+	return w.startRead(watch)
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) deleteWatch(watch *watch) {
+	for name, mask := range watch.names {
+		if mask&provisional == 0 {
+			w.sendEvent(watch.path+"/"+name, mask&FS_IGNORED)
+		}
+		delete(watch.names, name)
+	}
+	if watch.mask != 0 {
+		if watch.mask&provisional == 0 {
+			w.sendEvent(watch.path, watch.mask&FS_IGNORED)
+		}
+		watch.mask = 0
+	}
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) startRead(watch *watch) error {
+	if e := syscall.CancelIo(watch.ino.handle); e != nil {
+		w.Error <- os.NewSyscallError("CancelIo", e)
+		w.deleteWatch(watch)
+	}
+	mask := toWindowsFlags(watch.mask)
+	for _, m := range watch.names {
+		mask |= toWindowsFlags(m)
+	}
+	if mask == 0 {
+		if e := syscall.CloseHandle(watch.ino.handle); e != nil {
+			w.Error <- os.NewSyscallError("CloseHandle", e)
+		}
+		delete(w.watches[watch.ino.volume], watch.ino.index)
+		return nil
+	}
+	e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0],
+		uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0)
+	if e != nil {
+		err := os.NewSyscallError("ReadDirectoryChanges", e)
+		if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
+			// Watched directory was probably removed
+			if w.sendEvent(watch.path, watch.mask&FS_DELETE_SELF) {
+				if watch.mask&FS_ONESHOT != 0 {
+					watch.mask = 0
+				}
+			}
+			err = nil
+		}
+		w.deleteWatch(watch)
+		w.startRead(watch)
+		return err
+	}
+	return nil
+}
+
+// readEvents reads from the I/O completion port, converts the
+// received events into Event objects and sends them via the Event channel.
+// Entry point to the I/O thread.
+func (w *Watcher) readEvents() {
+	var (
+		n, key uint32
+		ov     *syscall.Overlapped
+	)
+	runtime.LockOSThread()
+
+	for {
+		e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE)
+		watch := (*watch)(unsafe.Pointer(ov))
+
+		if watch == nil {
+			select {
+			case ch := <-w.quit:
+				for _, index := range w.watches {
+					for _, watch := range index {
+						w.deleteWatch(watch)
+						w.startRead(watch)
+					}
+				}
+				var err error
+				if e := syscall.CloseHandle(w.port); e != nil {
+					err = os.NewSyscallError("CloseHandle", e)
+				}
+				close(w.Event)
+				close(w.Error)
+				ch <- err
+				return
+			case in := <-w.input:
+				switch in.op {
+				case opAddWatch:
+					in.reply <- w.addWatch(in.path, uint64(in.flags))
+				case opRemoveWatch:
+					in.reply <- w.removeWatch(in.path)
+				}
+			default:
+			}
+			continue
+		}
+
+		switch e {
+		case syscall.ERROR_ACCESS_DENIED:
+			// Watched directory was probably removed
+			w.sendEvent(watch.path, watch.mask&FS_DELETE_SELF)
+			w.deleteWatch(watch)
+			w.startRead(watch)
+			continue
+		case syscall.ERROR_OPERATION_ABORTED:
+			// CancelIo was called on this handle
+			continue
+		default:
+			w.Error <- os.NewSyscallError("GetQueuedCompletionPort", e)
+			continue
+		case nil:
+		}
+
+		var offset uint32
+		for {
+			if n == 0 {
+				w.Event <- &Event{Mask: FS_Q_OVERFLOW}
+				w.Error <- errors.New("short read in readEvents()")
+				break
+			}
+
+			// Point "raw" to the event in the buffer
+			raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset]))
+			buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))
+			name := syscall.UTF16ToString(buf[:raw.FileNameLength/2])
+			fullname := watch.path + "/" + name
+
+			var mask uint64
+			switch raw.Action {
+			case syscall.FILE_ACTION_REMOVED:
+				mask = FS_DELETE_SELF
+			case syscall.FILE_ACTION_MODIFIED:
+				mask = FS_MODIFY
+			case syscall.FILE_ACTION_RENAMED_OLD_NAME:
+				watch.rename = name
+			case syscall.FILE_ACTION_RENAMED_NEW_NAME:
+				if watch.names[watch.rename] != 0 {
+					watch.names[name] |= watch.names[watch.rename]
+					delete(watch.names, watch.rename)
+					mask = FS_MOVE_SELF
+				}
+			}
+
+			sendNameEvent := func() {
+				if w.sendEvent(fullname, watch.names[name]&mask) {
+					if watch.names[name]&FS_ONESHOT != 0 {
+						delete(watch.names, name)
+					}
+				}
+			}
+			if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME {
+				sendNameEvent()
+			}
+			if raw.Action == syscall.FILE_ACTION_REMOVED {
+				w.sendEvent(fullname, watch.names[name]&FS_IGNORED)
+				delete(watch.names, name)
+			}
+			if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) {
+				if watch.mask&FS_ONESHOT != 0 {
+					watch.mask = 0
+				}
+			}
+			if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME {
+				fullname = watch.path + "/" + watch.rename
+				sendNameEvent()
+			}
+
+			// Move to the next event in the buffer
+			if raw.NextEntryOffset == 0 {
+				break
+			}
+			offset += raw.NextEntryOffset
+		}
+
+		if err := w.startRead(watch); err != nil {
+			w.Error <- err
+		}
+	}
+}
+
+func (w *Watcher) sendEvent(name string, mask uint64) bool {
+	if mask == 0 {
+		return false
+	}
+	event := &Event{Mask: uint32(mask), Name: name}
+	if mask&FS_MOVE != 0 {
+		if mask&FS_MOVED_FROM != 0 {
+			w.cookie++
+		}
+		event.Cookie = w.cookie
+	}
+	select {
+	case ch := <-w.quit:
+		w.quit <- ch
+	case w.Event <- event:
+	}
+	return true
+}
+
+// String formats the event e in the form
+// "filename: 0xEventMask = FS_ACCESS|FS_ATTRIB_|..."
+func (e *Event) String() string {
+	var events string
+	m := e.Mask
+	for _, b := range eventBits {
+		if m&b.Value != 0 {
+			m &^= b.Value
+			events += "|" + b.Name
+		}
+	}
+	if m != 0 {
+		events += fmt.Sprintf("|%#x", m)
+	}
+	if len(events) > 0 {
+		events = " == " + events[1:]
+	}
+	return fmt.Sprintf("%q: %#x%s", e.Name, e.Mask, events)
+}
+
+func toWindowsFlags(mask uint64) uint32 {
+	var m uint32
+	if mask&FS_ACCESS != 0 {
+		m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS
+	}
+	if mask&FS_MODIFY != 0 {
+		m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE
+	}
+	if mask&FS_ATTRIB != 0 {
+		m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES
+	}
+	if mask&(FS_MOVE|FS_CREATE|FS_DELETE) != 0 {
+		m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME
+	}
+	return m
+}
+
+func toFSnotifyFlags(action uint32) uint64 {
+	switch action {
+	case syscall.FILE_ACTION_ADDED:
+		return FS_CREATE
+	case syscall.FILE_ACTION_REMOVED:
+		return FS_DELETE
+	case syscall.FILE_ACTION_MODIFIED:
+		return FS_MODIFY
+	case syscall.FILE_ACTION_RENAMED_OLD_NAME:
+		return FS_MOVED_FROM
+	case syscall.FILE_ACTION_RENAMED_NEW_NAME:
+		return FS_MOVED_TO
+	}
+	return 0
+}
+
+const (
+	// Options for AddWatch
+	FS_ONESHOT = 0x80000000
+	FS_ONLYDIR = 0x1000000
+
+	// Events
+	FS_ACCESS      = 0x1
+	FS_ALL_EVENTS  = 0xfff
+	FS_ATTRIB      = 0x4
+	FS_CLOSE       = 0x18
+	FS_CREATE      = 0x100
+	FS_DELETE      = 0x200
+	FS_DELETE_SELF = 0x400
+	FS_MODIFY      = 0x2
+	FS_MOVE        = 0xc0
+	FS_MOVED_FROM  = 0x40
+	FS_MOVED_TO    = 0x80
+	FS_MOVE_SELF   = 0x800
+
+	// Special events
+	FS_IGNORED    = 0x8000
+	FS_Q_OVERFLOW = 0x4000
+)
+
+var eventBits = []struct {
+	Value uint32
+	Name  string
+}{
+	{FS_ACCESS, "FS_ACCESS"},
+	{FS_ATTRIB, "FS_ATTRIB"},
+	{FS_CREATE, "FS_CREATE"},
+	{FS_DELETE, "FS_DELETE"},
+	{FS_DELETE_SELF, "FS_DELETE_SELF"},
+	{FS_MODIFY, "FS_MODIFY"},
+	{FS_MOVED_FROM, "FS_MOVED_FROM"},
+	{FS_MOVED_TO, "FS_MOVED_TO"},
+	{FS_MOVE_SELF, "FS_MOVE_SELF"},
+	{FS_IGNORED, "FS_IGNORED"},
+	{FS_Q_OVERFLOW, "FS_Q_OVERFLOW"},
+}
diff --git a/src/pkg/exp/winfsnotify/winfsnotify_test.go b/src/pkg/exp/winfsnotify/winfsnotify_test.go
new file mode 100644
index 0000000..59ac162
--- /dev/null
+++ b/src/pkg/exp/winfsnotify/winfsnotify_test.go
@@ -0,0 +1,122 @@
+// Copyright 2011 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 windows
+
+package winfsnotify
+
+import (
+	"os"
+	"testing"
+	"time"
+)
+
+func expect(t *testing.T, eventstream <-chan *Event, name string, mask uint32) {
+	t.Logf(`expected: "%s": 0x%x`, name, mask)
+	select {
+	case event := <-eventstream:
+		if event == nil {
+			t.Fatal("nil event received")
+		}
+		t.Logf("received: %s", event)
+		if event.Name != name || event.Mask != mask {
+			t.Fatal("did not receive expected event")
+		}
+	case <-time.After(1 * time.Second):
+		t.Fatal("timed out waiting for event")
+	}
+}
+
+func TestNotifyEvents(t *testing.T) {
+	watcher, err := NewWatcher()
+	if err != nil {
+		t.Fatalf("NewWatcher() failed: %s", err)
+	}
+
+	testDir := "TestNotifyEvents.testdirectory"
+	testFile := testDir + "/TestNotifyEvents.testfile"
+	testFile2 := testFile + ".new"
+	const mask = FS_ALL_EVENTS & ^(FS_ATTRIB|FS_CLOSE) | FS_IGNORED
+
+	// Add a watch for testDir
+	os.RemoveAll(testDir)
+	if err = os.Mkdir(testDir, 0777); err != nil {
+		t.Fatalf("Failed to create test directory: %s", err)
+	}
+	defer os.RemoveAll(testDir)
+	err = watcher.AddWatch(testDir, mask)
+	if err != nil {
+		t.Fatalf("Watcher.Watch() failed: %s", err)
+	}
+
+	// Receive errors on the error channel on a separate goroutine
+	go func() {
+		for err := range watcher.Error {
+			t.Fatalf("error received: %s", err)
+		}
+	}()
+
+	// Create a file
+	file, err := os.Create(testFile)
+	if err != nil {
+		t.Fatalf("creating test file failed: %s", err)
+	}
+	expect(t, watcher.Event, testFile, FS_CREATE)
+
+	err = watcher.AddWatch(testFile, mask)
+	if err != nil {
+		t.Fatalf("Watcher.Watch() failed: %s", err)
+	}
+
+	if _, err = file.WriteString("hello, world"); err != nil {
+		t.Fatalf("failed to write to test file: %s", err)
+	}
+	if err = file.Close(); err != nil {
+		t.Fatalf("failed to close test file: %s", err)
+	}
+	expect(t, watcher.Event, testFile, FS_MODIFY)
+	expect(t, watcher.Event, testFile, FS_MODIFY)
+
+	if err = os.Rename(testFile, testFile2); err != nil {
+		t.Fatalf("failed to rename test file: %s", err)
+	}
+	expect(t, watcher.Event, testFile, FS_MOVED_FROM)
+	expect(t, watcher.Event, testFile2, FS_MOVED_TO)
+	expect(t, watcher.Event, testFile, FS_MOVE_SELF)
+
+	if err = os.RemoveAll(testDir); err != nil {
+		t.Fatalf("failed to remove test directory: %s", err)
+	}
+	expect(t, watcher.Event, testFile2, FS_DELETE_SELF)
+	expect(t, watcher.Event, testFile2, FS_IGNORED)
+	expect(t, watcher.Event, testFile2, FS_DELETE)
+	expect(t, watcher.Event, testDir, FS_DELETE_SELF)
+	expect(t, watcher.Event, testDir, FS_IGNORED)
+
+	t.Log("calling Close()")
+	if err = watcher.Close(); err != nil {
+		t.Fatalf("failed to close watcher: %s", err)
+	}
+}
+
+func TestNotifyClose(t *testing.T) {
+	watcher, _ := NewWatcher()
+	watcher.Close()
+
+	done := false
+	go func() {
+		watcher.Close()
+		done = true
+	}()
+
+	time.Sleep(50 * time.Millisecond)
+	if !done {
+		t.Fatal("double Close() test failed: second Close() call didn't return")
+	}
+
+	err := watcher.Watch("_test")
+	if err == nil {
+		t.Fatal("expected error on Watch() after Close(), got nil")
+	}
+}
diff --git a/src/pkg/exp/wingui/Makefile b/src/pkg/exp/wingui/Makefile
index 00f7d23..bf69c98 100644
--- a/src/pkg/exp/wingui/Makefile
+++ b/src/pkg/exp/wingui/Makefile
@@ -18,12 +18,7 @@ GOFILES=\
 include ../../../Make.cmd
 
 zwinapi.go: winapi.go
-	$(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $< \
-		| sed 's/^package.*syscall$$/package main/' \
-		| sed '/^import/a \
-			import "syscall"' \
-		| sed 's/Syscall/syscall.Syscall/' \
-		| sed 's/NewLazyDLL/syscall.NewLazyDLL/' \
-		| sed 's/EINVAL/syscall.EINVAL/' \
+	(echo '// +build windows'; \
+	$(GOROOT)/src/pkg/syscall/mksyscall_windows.pl $<) \
 		| gofmt \
 		> $@
diff --git a/src/pkg/exp/wingui/gui.go b/src/pkg/exp/wingui/gui.go
index a2f16f2..3b79873 100644
--- a/src/pkg/exp/wingui/gui.go
+++ b/src/pkg/exp/wingui/gui.go
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build windows
+
 package main
 
 import (
 	"fmt"
-	"syscall"
 	"os"
+	"syscall"
 	"unsafe"
 )
 
@@ -18,8 +20,9 @@ func abortf(format string, a ...interface{}) {
 	os.Exit(1)
 }
 
-func abortErrNo(funcname string, err int) {
-	abortf("%s failed: %d %s\n", funcname, err, syscall.Errstr(err))
+func abortErrNo(funcname string, err error) {
+	errno, _ := err.(syscall.Errno)
+	abortf("%s failed: %d %s\n", funcname, uint32(errno), err)
 }
 
 // global vars
@@ -33,7 +36,7 @@ var (
 func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintptr) {
 	switch msg {
 	case WM_CREATE:
-		var e int
+		var e error
 		// CreateWindowEx
 		bh, e = CreateWindowEx(
 			0,
@@ -42,7 +45,7 @@ func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintpt
 			WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
 			75, 70, 140, 25,
 			hwnd, 1, mh, 0)
-		if e != 0 {
+		if e != nil {
 			abortErrNo("CreateWindowEx", e)
 		}
 		fmt.Printf("button handle is %x\n", bh)
@@ -51,7 +54,7 @@ func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintpt
 		switch syscall.Handle(lparam) {
 		case bh:
 			e := PostMessage(hwnd, WM_CLOSE, 0, 0)
-			if e != 0 {
+			if e != nil {
 				abortErrNo("PostMessage", e)
 			}
 		default:
@@ -69,23 +72,23 @@ func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintpt
 }
 
 func rungui() int {
-	var e int
+	var e error
 
 	// GetModuleHandle
 	mh, e = GetModuleHandle(nil)
-	if e != 0 {
+	if e != nil {
 		abortErrNo("GetModuleHandle", e)
 	}
 
 	// Get icon we're going to use.
 	myicon, e := LoadIcon(0, IDI_APPLICATION)
-	if e != 0 {
+	if e != nil {
 		abortErrNo("LoadIcon", e)
 	}
 
 	// Get cursor we're going to use.
 	mycursor, e := LoadCursor(0, IDC_ARROW)
-	if e != 0 {
+	if e != nil {
 		abortErrNo("LoadCursor", e)
 	}
 
@@ -104,7 +107,7 @@ func rungui() int {
 	wc.MenuName = nil
 	wc.ClassName = wcname
 	wc.IconSm = myicon
-	if _, e := RegisterClassEx(&wc); e != 0 {
+	if _, e := RegisterClassEx(&wc); e != nil {
 		abortErrNo("RegisterClassEx", e)
 	}
 
@@ -116,7 +119,7 @@ func rungui() int {
 		WS_OVERLAPPEDWINDOW,
 		CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
 		0, 0, mh, 0)
-	if e != 0 {
+	if e != nil {
 		abortErrNo("CreateWindowEx", e)
 	}
 	fmt.Printf("main window handle is %x\n", wh)
@@ -125,7 +128,7 @@ func rungui() int {
 	ShowWindow(wh, SW_SHOWDEFAULT)
 
 	// UpdateWindow
-	if e := UpdateWindow(wh); e != 0 {
+	if e := UpdateWindow(wh); e != nil {
 		abortErrNo("UpdateWindow", e)
 	}
 
@@ -133,7 +136,7 @@ func rungui() int {
 	var m Msg
 	for {
 		r, e := GetMessage(&m, 0, 0, 0)
-		if e != 0 {
+		if e != nil {
 			abortErrNo("GetMessage", e)
 		}
 		if r == 0 {
diff --git a/src/pkg/exp/wingui/winapi.go b/src/pkg/exp/wingui/winapi.go
index 3201528..f876088 100644
--- a/src/pkg/exp/wingui/winapi.go
+++ b/src/pkg/exp/wingui/winapi.go
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build windows
+
 package main
 
 import (
-	"unsafe"
 	"syscall"
+	"unsafe"
 )
 
 type Wndclassex struct {
@@ -110,22 +112,22 @@ var (
 	IDI_INFORMATION = IDI_ASTERISK
 )
 
-//sys	GetModuleHandle(modname *uint16) (handle syscall.Handle, errno int) = GetModuleHandleW
-//sys	RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) = user32.RegisterClassExW
-//sys	CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, errno int) = user32.CreateWindowExW
+//sys	GetModuleHandle(modname *uint16) (handle syscall.Handle, err error) = GetModuleHandleW
+//sys	RegisterClassEx(wndclass *Wndclassex) (atom uint16, err error) = user32.RegisterClassExW
+//sys	CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, err error) = user32.CreateWindowExW
 //sys	DefWindowProc(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) = user32.DefWindowProcW
-//sys	DestroyWindow(hwnd syscall.Handle) (errno int) = user32.DestroyWindow
+//sys	DestroyWindow(hwnd syscall.Handle) (err error) = user32.DestroyWindow
 //sys	PostQuitMessage(exitcode int32) = user32.PostQuitMessage
 //sys	ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) = user32.ShowWindow
-//sys	UpdateWindow(hwnd syscall.Handle) (errno int) = user32.UpdateWindow
-//sys	GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) [failretval==-1] = user32.GetMessageW
+//sys	UpdateWindow(hwnd syscall.Handle) (err error) = user32.UpdateWindow
+//sys	GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) [failretval==-1] = user32.GetMessageW
 //sys	TranslateMessage(msg *Msg) (done bool) = user32.TranslateMessage
 //sys	DispatchMessage(msg *Msg) (ret int32) = user32.DispatchMessageW
-//sys	LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, errno int) = user32.LoadIconW
-//sys	LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, errno int) = user32.LoadCursorW
-//sys	SetCursor(cursor syscall.Handle) (precursor syscall.Handle, errno int) = user32.SetCursor
+//sys	LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, err error) = user32.LoadIconW
+//sys	LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, err error) = user32.LoadCursorW
+//sys	SetCursor(cursor syscall.Handle) (precursor syscall.Handle, err error) = user32.SetCursor
 //sys	SendMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) = user32.SendMessageW
-//sys	PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (errno int) = user32.PostMessageW
+//sys	PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (err error) = user32.PostMessageW
 
 func MakeIntResource(id uint16) *uint16 {
 	return (*uint16)(unsafe.Pointer(uintptr(id)))
diff --git a/src/pkg/exp/wingui/zwinapi.go b/src/pkg/exp/wingui/zwinapi.go
index 38e93ee..5666c6d 100644
--- a/src/pkg/exp/wingui/zwinapi.go
+++ b/src/pkg/exp/wingui/zwinapi.go
@@ -1,3 +1,4 @@
+// +build windows
 // mksyscall_windows.pl winapi.go
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
@@ -28,47 +29,41 @@ var (
 	procPostMessageW     = moduser32.NewProc("PostMessageW")
 )
 
-func GetModuleHandle(modname *uint16) (handle syscall.Handle, errno int) {
+func GetModuleHandle(modname *uint16) (handle syscall.Handle, err error) {
 	r0, _, e1 := syscall.Syscall(procGetModuleHandleW.Addr(), 1, uintptr(unsafe.Pointer(modname)), 0, 0)
 	handle = syscall.Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) {
+func RegisterClassEx(wndclass *Wndclassex) (atom uint16, err error) {
 	r0, _, e1 := syscall.Syscall(procRegisterClassExW.Addr(), 1, uintptr(unsafe.Pointer(wndclass)), 0, 0)
 	atom = uint16(r0)
 	if atom == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, errno int) {
+func CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, err error) {
 	r0, _, e1 := syscall.Syscall12(procCreateWindowExW.Addr(), 12, uintptr(exstyle), uintptr(unsafe.Pointer(classname)), uintptr(unsafe.Pointer(windowname)), uintptr(style), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(wndparent), uintptr(menu), uintptr(instance), uintptr(param))
 	hwnd = syscall.Handle(r0)
 	if hwnd == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -79,16 +74,14 @@ func DefWindowProc(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintp
 	return
 }
 
-func DestroyWindow(hwnd syscall.Handle) (errno int) {
+func DestroyWindow(hwnd syscall.Handle) (err error) {
 	r1, _, e1 := syscall.Syscall(procDestroyWindow.Addr(), 1, uintptr(hwnd), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -104,31 +97,27 @@ func ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) {
 	return
 }
 
-func UpdateWindow(hwnd syscall.Handle) (errno int) {
+func UpdateWindow(hwnd syscall.Handle) (err error) {
 	r1, _, e1 := syscall.Syscall(procUpdateWindow.Addr(), 1, uintptr(hwnd), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) {
+func GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, err error) {
 	r0, _, e1 := syscall.Syscall6(procGetMessageW.Addr(), 4, uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax), 0, 0)
 	ret = int32(r0)
 	if ret == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -145,47 +134,41 @@ func DispatchMessage(msg *Msg) (ret int32) {
 	return
 }
 
-func LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, errno int) {
+func LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, err error) {
 	r0, _, e1 := syscall.Syscall(procLoadIconW.Addr(), 2, uintptr(instance), uintptr(unsafe.Pointer(iconname)), 0)
 	icon = syscall.Handle(r0)
 	if icon == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, errno int) {
+func LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, err error) {
 	r0, _, e1 := syscall.Syscall(procLoadCursorW.Addr(), 2, uintptr(instance), uintptr(unsafe.Pointer(cursorname)), 0)
 	cursor = syscall.Handle(r0)
 	if cursor == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetCursor(cursor syscall.Handle) (precursor syscall.Handle, errno int) {
+func SetCursor(cursor syscall.Handle) (precursor syscall.Handle, err error) {
 	r0, _, e1 := syscall.Syscall(procSetCursor.Addr(), 1, uintptr(cursor), 0, 0)
 	precursor = syscall.Handle(r0)
 	if precursor == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -196,16 +179,14 @@ func SendMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr
 	return
 }
 
-func PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (errno int) {
+func PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (err error) {
 	r1, _, e1 := syscall.Syscall6(procPostMessageW.Addr(), 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = syscall.EINVAL
+			err = syscall.EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
diff --git a/src/pkg/expvar/expvar.go b/src/pkg/expvar/expvar.go
index 7b733fa..5ced285 100644
--- a/src/pkg/expvar/expvar.go
+++ b/src/pkg/expvar/expvar.go
@@ -23,10 +23,10 @@ package expvar
 
 import (
 	"bytes"
+	"encoding/json"
 	"fmt"
-	"http"
-	"json"
 	"log"
+	"net/http"
 	"os"
 	"runtime"
 	"strconv"
@@ -44,7 +44,7 @@ type Int struct {
 	mu sync.Mutex
 }
 
-func (v *Int) String() string { return strconv.Itoa64(v.i) }
+func (v *Int) String() string { return strconv.FormatInt(v.i, 10) }
 
 func (v *Int) Add(delta int64) {
 	v.mu.Lock()
@@ -64,7 +64,7 @@ type Float struct {
 	mu sync.Mutex
 }
 
-func (v *Float) String() string { return strconv.Ftoa64(v.f, 'g', -1) }
+func (v *Float) String() string { return strconv.FormatFloat(v.f, 'g', -1, 64) }
 
 // Add adds delta to v.
 func (v *Float) Add(delta float64) {
@@ -102,7 +102,7 @@ func (v *Map) String() string {
 		if !first {
 			fmt.Fprintf(b, ", ")
 		}
-		fmt.Fprintf(b, "\"%s\": %v", key, val.String())
+		fmt.Fprintf(b, "\"%s\": %v", key, val)
 		first = false
 	}
 	fmt.Fprintf(b, "}")
@@ -193,7 +193,7 @@ func (f Func) String() string {
 var vars map[string]Var = make(map[string]Var)
 var mutex sync.Mutex
 
-// Publish declares an named exported variable. This should be called from a
+// Publish declares a named exported variable. This should be called from a
 // package's init function when it creates its Vars. If the name is already
 // registered then this will log.Panic.
 func Publish(name string, v Var) {
diff --git a/src/pkg/expvar/expvar_test.go b/src/pkg/expvar/expvar_test.go
index 8f7a481..fc60727 100644
--- a/src/pkg/expvar/expvar_test.go
+++ b/src/pkg/expvar/expvar_test.go
@@ -5,7 +5,7 @@
 package expvar
 
 import (
-	"json"
+	"encoding/json"
 	"testing"
 )
 
diff --git a/src/pkg/flag/flag.go b/src/pkg/flag/flag.go
index f13f7a4..964f554 100644
--- a/src/pkg/flag/flag.go
+++ b/src/pkg/flag/flag.go
@@ -60,16 +60,18 @@
 package flag
 
 import (
+	"errors"
 	"fmt"
 	"os"
 	"sort"
 	"strconv"
+	"time"
 )
 
 // ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.
-var ErrHelp = os.NewError("flag: help requested")
+var ErrHelp = errors.New("flag: help requested")
 
-// -- Bool Value
+// -- bool Value
 type boolValue bool
 
 func newBoolValue(val bool, p *bool) *boolValue {
@@ -77,15 +79,15 @@ func newBoolValue(val bool, p *bool) *boolValue {
 	return (*boolValue)(p)
 }
 
-func (b *boolValue) Set(s string) bool {
-	v, err := strconv.Atob(s)
+func (b *boolValue) Set(s string) error {
+	v, err := strconv.ParseBool(s)
 	*b = boolValue(v)
-	return err == nil
+	return err
 }
 
 func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
 
-// -- Int Value
+// -- int Value
 type intValue int
 
 func newIntValue(val int, p *int) *intValue {
@@ -93,15 +95,15 @@ func newIntValue(val int, p *int) *intValue {
 	return (*intValue)(p)
 }
 
-func (i *intValue) Set(s string) bool {
-	v, err := strconv.Btoi64(s, 0)
+func (i *intValue) Set(s string) error {
+	v, err := strconv.ParseInt(s, 0, 64)
 	*i = intValue(v)
-	return err == nil
+	return err
 }
 
 func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
 
-// -- Int64 Value
+// -- int64 Value
 type int64Value int64
 
 func newInt64Value(val int64, p *int64) *int64Value {
@@ -109,15 +111,15 @@ func newInt64Value(val int64, p *int64) *int64Value {
 	return (*int64Value)(p)
 }
 
-func (i *int64Value) Set(s string) bool {
-	v, err := strconv.Btoi64(s, 0)
+func (i *int64Value) Set(s string) error {
+	v, err := strconv.ParseInt(s, 0, 64)
 	*i = int64Value(v)
-	return err == nil
+	return err
 }
 
 func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
 
-// -- Uint Value
+// -- uint Value
 type uintValue uint
 
 func newUintValue(val uint, p *uint) *uintValue {
@@ -125,10 +127,10 @@ func newUintValue(val uint, p *uint) *uintValue {
 	return (*uintValue)(p)
 }
 
-func (i *uintValue) Set(s string) bool {
-	v, err := strconv.Btoui64(s, 0)
+func (i *uintValue) Set(s string) error {
+	v, err := strconv.ParseUint(s, 0, 64)
 	*i = uintValue(v)
-	return err == nil
+	return err
 }
 
 func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
@@ -141,10 +143,10 @@ func newUint64Value(val uint64, p *uint64) *uint64Value {
 	return (*uint64Value)(p)
 }
 
-func (i *uint64Value) Set(s string) bool {
-	v, err := strconv.Btoui64(s, 0)
+func (i *uint64Value) Set(s string) error {
+	v, err := strconv.ParseUint(s, 0, 64)
 	*i = uint64Value(v)
-	return err == nil
+	return err
 }
 
 func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
@@ -157,14 +159,14 @@ func newStringValue(val string, p *string) *stringValue {
 	return (*stringValue)(p)
 }
 
-func (s *stringValue) Set(val string) bool {
+func (s *stringValue) Set(val string) error {
 	*s = stringValue(val)
-	return true
+	return nil
 }
 
 func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
 
-// -- Float64 Value
+// -- float64 Value
 type float64Value float64
 
 func newFloat64Value(val float64, p *float64) *float64Value {
@@ -172,19 +174,35 @@ func newFloat64Value(val float64, p *float64) *float64Value {
 	return (*float64Value)(p)
 }
 
-func (f *float64Value) Set(s string) bool {
-	v, err := strconv.Atof64(s)
+func (f *float64Value) Set(s string) error {
+	v, err := strconv.ParseFloat(s, 64)
 	*f = float64Value(v)
-	return err == nil
+	return err
 }
 
 func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
 
+// -- time.Duration Value
+type durationValue time.Duration
+
+func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
+	*p = val
+	return (*durationValue)(p)
+}
+
+func (d *durationValue) Set(s string) error {
+	v, err := time.ParseDuration(s)
+	*d = durationValue(v)
+	return err
+}
+
+func (d *durationValue) String() string { return (*time.Duration)(d).String() }
+
 // Value is the interface to the dynamic value stored in a flag.
 // (The default value is represented as a string.)
 type Value interface {
 	String() string
-	Set(string) bool
+	Set(string) error
 }
 
 // ErrorHandling defines how to handle flag parsing errors.
@@ -275,27 +293,25 @@ func Lookup(name string) *Flag {
 	return commandLine.formal[name]
 }
 
-// Set sets the value of the named flag.  It returns true if the set succeeded; false if
-// there is no such flag defined.
-func (f *FlagSet) Set(name, value string) bool {
+// Set sets the value of the named flag.
+func (f *FlagSet) Set(name, value string) error {
 	flag, ok := f.formal[name]
 	if !ok {
-		return false
+		return fmt.Errorf("no such flag -%v", name)
 	}
-	ok = flag.Value.Set(value)
-	if !ok {
-		return false
+	err := flag.Value.Set(value)
+	if err != nil {
+		return err
 	}
 	if f.actual == nil {
 		f.actual = make(map[string]*Flag)
 	}
 	f.actual[name] = flag
-	return true
+	return nil
 }
 
-// Set sets the value of the named command-line flag. It returns true if the
-// set succeeded; false if there is no such flag defined.
-func Set(name, value string) bool {
+// Set sets the value of the named command-line flag.
+func Set(name, value string) error {
 	return commandLine.Set(name, value)
 }
 
@@ -542,12 +558,38 @@ func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
 	return p
 }
 
-// Float64 defines an int flag with specified name, default value, and usage string.
+// Float64 defines a float64 flag with specified name, default value, and usage string.
 // The return value is the address of a float64 variable that stores the value of the flag.
 func Float64(name string, value float64, usage string) *float64 {
 	return commandLine.Float64(name, value, usage)
 }
 
+// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
+// The argument p points to a time.Duration variable in which to store the value of the flag.
+func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
+	f.Var(newDurationValue(value, p), name, usage)
+}
+
+// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
+// The argument p points to a time.Duration variable in which to store the value of the flag.
+func DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
+	commandLine.Var(newDurationValue(value, p), name, usage)
+}
+
+// Duration defines a time.Duration flag with specified name, default value, and usage string.
+// The return value is the address of a time.Duration variable that stores the value of the flag.
+func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration {
+	p := new(time.Duration)
+	f.DurationVar(p, name, value, usage)
+	return p
+}
+
+// Duration defines a time.Duration flag with specified name, default value, and usage string.
+// The return value is the address of a time.Duration variable that stores the value of the flag.
+func Duration(name string, value time.Duration, usage string) *time.Duration {
+	return commandLine.Duration(name, value, usage)
+}
+
 // Var defines a flag with the specified name and usage string. The type and
 // value of the flag are represented by the first argument, of type Value, which
 // typically holds a user-defined implementation of Value. For instance, the
@@ -580,7 +622,7 @@ func Var(value Value, name string, usage string) {
 
 // failf prints to standard error a formatted error and usage message and
 // returns the error.
-func (f *FlagSet) failf(format string, a ...interface{}) os.Error {
+func (f *FlagSet) failf(format string, a ...interface{}) error {
 	err := fmt.Errorf(format, a...)
 	fmt.Fprintln(os.Stderr, err)
 	f.usage()
@@ -600,7 +642,7 @@ func (f *FlagSet) usage() {
 }
 
 // parseOne parses one flag. It returns whether a flag was seen.
-func (f *FlagSet) parseOne() (bool, os.Error) {
+func (f *FlagSet) parseOne() (bool, error) {
 	if len(f.args) == 0 {
 		return false, nil
 	}
@@ -644,8 +686,8 @@ func (f *FlagSet) parseOne() (bool, os.Error) {
 	}
 	if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
 		if has_value {
-			if !fv.Set(value) {
-				f.failf("invalid boolean value %q for flag: -%s", value, name)
+			if err := fv.Set(value); err != nil {
+				f.failf("invalid boolean value %q for  -%s: %v", value, name, err)
 			}
 		} else {
 			fv.Set("true")
@@ -660,9 +702,8 @@ func (f *FlagSet) parseOne() (bool, os.Error) {
 		if !has_value {
 			return false, f.failf("flag needs an argument: -%s", name)
 		}
-		ok = flag.Value.Set(value)
-		if !ok {
-			return false, f.failf("invalid value %q for flag: -%s", value, name)
+		if err := flag.Value.Set(value); err != nil {
+			return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
 		}
 	}
 	if f.actual == nil {
@@ -676,7 +717,7 @@ func (f *FlagSet) parseOne() (bool, os.Error) {
 // include the command name.  Must be called after all flags in the FlagSet
 // are defined and before flags are accessed by the program.
 // The return value will be ErrHelp if -help was set but not defined.
-func (f *FlagSet) Parse(arguments []string) os.Error {
+func (f *FlagSet) Parse(arguments []string) error {
 	f.parsed = true
 	f.args = arguments
 	for {
diff --git a/src/pkg/flag/flag_test.go b/src/pkg/flag/flag_test.go
index f135316..698c15f 100644
--- a/src/pkg/flag/flag_test.go
+++ b/src/pkg/flag/flag_test.go
@@ -10,16 +10,18 @@ import (
 	"os"
 	"sort"
 	"testing"
+	"time"
 )
 
 var (
-	test_bool    = Bool("test_bool", false, "bool value")
-	test_int     = Int("test_int", 0, "int value")
-	test_int64   = Int64("test_int64", 0, "int64 value")
-	test_uint    = Uint("test_uint", 0, "uint value")
-	test_uint64  = Uint64("test_uint64", 0, "uint64 value")
-	test_string  = String("test_string", "0", "string value")
-	test_float64 = Float64("test_float64", 0, "float64 value")
+	test_bool     = Bool("test_bool", false, "bool value")
+	test_int      = Int("test_int", 0, "int value")
+	test_int64    = Int64("test_int64", 0, "int64 value")
+	test_uint     = Uint("test_uint", 0, "uint value")
+	test_uint64   = Uint64("test_uint64", 0, "uint64 value")
+	test_string   = String("test_string", "0", "string value")
+	test_float64  = Float64("test_float64", 0, "float64 value")
+	test_duration = Duration("test_duration", 0, "time.Duration value")
 )
 
 func boolString(s string) string {
@@ -41,6 +43,8 @@ func TestEverything(t *testing.T) {
 				ok = true
 			case f.Name == "test_bool" && f.Value.String() == boolString(desired):
 				ok = true
+			case f.Name == "test_duration" && f.Value.String() == desired+"s":
+				ok = true
 			}
 			if !ok {
 				t.Error("Visit: bad value", f.Value.String(), "for", f.Name)
@@ -48,7 +52,7 @@ func TestEverything(t *testing.T) {
 		}
 	}
 	VisitAll(visitor)
-	if len(m) != 7 {
+	if len(m) != 8 {
 		t.Error("VisitAll misses some flags")
 		for k, v := range m {
 			t.Log(k, *v)
@@ -70,9 +74,10 @@ func TestEverything(t *testing.T) {
 	Set("test_uint64", "1")
 	Set("test_string", "1")
 	Set("test_float64", "1")
+	Set("test_duration", "1s")
 	desired = "1"
 	Visit(visitor)
-	if len(m) != 7 {
+	if len(m) != 8 {
 		t.Error("Visit fails after set")
 		for k, v := range m {
 			t.Log(k, *v)
@@ -109,6 +114,7 @@ func testParse(f *FlagSet, t *testing.T) {
 	uint64Flag := f.Uint64("uint64", 0, "uint64 value")
 	stringFlag := f.String("string", "0", "string value")
 	float64Flag := f.Float64("float64", 0, "float64 value")
+	durationFlag := f.Duration("duration", 5*time.Second, "time.Duration value")
 	extra := "one-extra-argument"
 	args := []string{
 		"-bool",
@@ -119,6 +125,7 @@ func testParse(f *FlagSet, t *testing.T) {
 		"--uint64", "25",
 		"-string", "hello",
 		"-float64", "2718e28",
+		"-duration", "2m",
 		extra,
 	}
 	if err := f.Parse(args); err != nil {
@@ -151,6 +158,9 @@ func testParse(f *FlagSet, t *testing.T) {
 	if *float64Flag != 2718e28 {
 		t.Error("float64 flag should be 2718e28, is ", *float64Flag)
 	}
+	if *durationFlag != 2*time.Minute {
+		t.Error("duration flag should be 2m, is ", *durationFlag)
+	}
 	if len(f.Args()) != 1 {
 		t.Error("expected one argument, got", len(f.Args()))
 	} else if f.Args()[0] != extra {
@@ -174,9 +184,9 @@ func (f *flagVar) String() string {
 	return fmt.Sprint([]string(*f))
 }
 
-func (f *flagVar) Set(value string) bool {
+func (f *flagVar) Set(value string) error {
 	*f = append(*f, value)
-	return true
+	return nil
 }
 
 func TestUserDefined(t *testing.T) {
diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go
index 35a11e1..7d4178d 100644
--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -30,8 +30,9 @@
 		%X	base 16, with upper-case letters for A-F
 		%U	Unicode format: U+1234; same as "U+%04X"
 	Floating-point and complex constituents:
-		%b	decimalless scientific notation with exponent a power
-			of two, in the manner of strconv.Ftoa32, e.g. -123456p-78
+		%b	decimalless scientific notation with exponent a power of two, 
+			in the manner of strconv.FormatFloat with the 'b' format, 
+			e.g. -123456p-78
 		%e	scientific notation, e.g. -1234.456e+78
 		%E	scientific notation, e.g. -1234.456E+78
 		%f	decimal point but no exponent, e.g. 123.456
@@ -89,14 +90,22 @@
 	If an operand implements interface Formatter, that interface
 	can be used for fine control of formatting.
 
-	If an operand implements method String() string that method
+	If the format (which is implicitly %v for Println etc.) is valid
+	for a string (%s %q %v %x %X), the following two rules also apply:
+
+	1. If an operand implements the error interface, the Error method
+	will be used to convert the object to a string, which will then
+	be formatted as required by the verb (if any).
+
+	2. If an operand implements method String() string, that method
 	will be used to convert the object to a string, which will then
-	be formatted as required by the verb (if any). To avoid
-	recursion in cases such as
-		type X int
-		func (x X) String() string { return Sprintf("%d", x) }
-	cast the value before recurring:
-		func (x X) String() string { return Sprintf("%d", int(x)) }
+	be formatted as required by the verb (if any).
+
+	To avoid recursion in cases such as
+		type X string
+		func (x X) String() string { return Sprintf("<%s>", x) }
+	convert the value before recurring:
+		func (x X) String() string { return Sprintf("<%s>", string(x)) }
 
 	Format errors:
 
@@ -122,7 +131,7 @@
 
 	An analogous set of functions scans formatted text to yield
 	values.  Scan, Scanf and Scanln read from os.Stdin; Fscan,
-	Fscanf and Fscanln read from a specified os.Reader; Sscan,
+	Fscanf and Fscanln read from a specified io.Reader; Sscan,
 	Sscanf and Sscanln read from an argument string.  Scanln,
 	Fscanln and Sscanln stop scanning at a newline and require that
 	the items be followed by one; Sscanf, Fscanf and Sscanf require
diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go
index b1ad345..2f92f94 100644
--- a/src/pkg/fmt/fmt_test.go
+++ b/src/pkg/fmt/fmt_test.go
@@ -12,6 +12,7 @@ import (
 	"runtime" // for the malloc count test only
 	"strings"
 	"testing"
+	"time"
 )
 
 type (
@@ -47,8 +48,10 @@ func TestFmtInterface(t *testing.T) {
 const b32 uint32 = 1<<32 - 1
 const b64 uint64 = 1<<64 - 1
 
-var array = []int{1, 2, 3, 4, 5}
-var iarray = []interface{}{1, "hello", 2.5, nil}
+var array = [5]int{1, 2, 3, 4, 5}
+var iarray = [4]interface{}{1, "hello", 2.5, nil}
+var slice = array[:]
+var islice = iarray[:]
 
 type A struct {
 	i int
@@ -62,7 +65,7 @@ type I int
 func (i I) String() string { return Sprintf("<%d>", int(i)) }
 
 type B struct {
-	i I
+	I I
 	j int
 }
 
@@ -73,7 +76,7 @@ type C struct {
 
 type F int
 
-func (f F) Format(s State, c int) {
+func (f F) Format(s State, c rune) {
 	Fprintf(s, "<%c=F(%d)>", c, int(f))
 }
 
@@ -84,8 +87,12 @@ func (g G) GoString() string {
 }
 
 type S struct {
-	f F // a struct field that Formats
-	g G // a struct field that GoStrings
+	F F // a struct field that Formats
+	G G // a struct field that GoStrings
+}
+
+type SI struct {
+	I interface{}
 }
 
 // A type with a String method with pointer receiver for testing %p
@@ -323,6 +330,12 @@ var fmttests = []struct {
 	{"%v", &array, "&[1 2 3 4 5]"},
 	{"%v", &iarray, "&[1 hello 2.5 <nil>]"},
 
+	// slices
+	{"%v", slice, "[1 2 3 4 5]"},
+	{"%v", islice, "[1 hello 2.5 <nil>]"},
+	{"%v", &slice, "&[1 2 3 4 5]"},
+	{"%v", &islice, "&[1 hello 2.5 <nil>]"},
+
 	// complexes with %v
 	{"%v", 1 + 2i, "(1+2i)"},
 	{"%v", complex64(1 + 2i), "(1+2i)"},
@@ -333,14 +346,14 @@ var fmttests = []struct {
 	{"%+v", A{1, 2, "a", []int{1, 2}}, `{i:1 j:2 s:a x:[1 2]}`},
 
 	// +v on structs with Stringable items
-	{"%+v", B{1, 2}, `{i:<1> j:2}`},
-	{"%+v", C{1, B{2, 3}}, `{i:1 B:{i:<2> j:3}}`},
+	{"%+v", B{1, 2}, `{I:<1> j:2}`},
+	{"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`},
 
 	// q on Stringable items
 	{"%s", I(23), `<23>`},
 	{"%q", I(23), `"<23>"`},
 	{"%x", I(23), `3c32333e`},
-	{"%d", I(23), `%!d(string=<23>)`},
+	{"%d", I(23), `23`}, // Stringer applies only to string formats.
 
 	// go syntax
 	{"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
@@ -349,9 +362,18 @@ var fmttests = []struct {
 	{"%#v", make(chan int), "(chan int)(0xPTR)"},
 	{"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
 	{"%#v", 1000000000, "1000000000"},
-	{"%#v", map[string]int{"a": 1, "b": 2}, `map[string] int{"a":1, "b":2}`},
-	{"%#v", map[string]B{"a": {1, 2}, "b": {3, 4}}, `map[string] fmt_test.B{"a":fmt_test.B{i:1, j:2}, "b":fmt_test.B{i:3, j:4}}`},
+	{"%#v", map[string]int{"a": 1}, `map[string]int{"a":1}`},
+	{"%#v", map[string]B{"a": {1, 2}}, `map[string]fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
 	{"%#v", []string{"a", "b"}, `[]string{"a", "b"}`},
+	{"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`},
+	{"%#v", []int(nil), `[]int(nil)`},
+	{"%#v", []int{}, `[]int{}`},
+	{"%#v", array, `[5]int{1, 2, 3, 4, 5}`},
+	{"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`},
+	{"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
+	{"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
+	{"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
+	{"%#v", map[int]byte{}, `map[int]uint8{}`},
 
 	// slices with other formats
 	{"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
@@ -385,11 +407,11 @@ var fmttests = []struct {
 	// Formatter
 	{"%x", F(1), "<x=F(1)>"},
 	{"%x", G(2), "2"},
-	{"%+v", S{F(4), G(5)}, "{f:<v=F(4)> g:5}"},
+	{"%+v", S{F(4), G(5)}, "{F:<v=F(4)> G:5}"},
 
 	// GoStringer
 	{"%#v", G(6), "GoString(6)"},
-	{"%#v", S{F(7), G(8)}, "fmt_test.S{f:<v=F(7)>, g:GoString(8)}"},
+	{"%#v", S{F(7), G(8)}, "fmt_test.S{F:<v=F(7)>, G:GoString(8)}"},
 
 	// %T
 	{"%T", (4 - 3i), "complex128"},
@@ -409,6 +431,10 @@ var fmttests = []struct {
 	{"%p", make([]int, 1), "0xPTR"},
 	{"%p", 27, "%!p(int=27)"}, // not a pointer at all
 
+	// %d on Stringer should give integer if possible
+	{"%s", time.Time{}.Month(), "January"},
+	{"%d", time.Time{}.Month(), "1"},
+
 	// erroneous things
 	{"%s %", "hello", "hello %!(NOVERB)"},
 	{"%s %.2", "hello", "hello %!(NOVERB)"},
@@ -474,74 +500,52 @@ func BenchmarkSprintfPrefixedInt(b *testing.B) {
 	}
 }
 
-func TestCountMallocs(t *testing.T) {
-	if testing.Short() {
-		return
-	}
-	runtime.UpdateMemStats()
-	mallocs := 0 - runtime.MemStats.Mallocs
-	for i := 0; i < 100; i++ {
-		Sprintf("")
-	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/100)
-	runtime.UpdateMemStats()
-	mallocs = 0 - runtime.MemStats.Mallocs
-	for i := 0; i < 100; i++ {
-		Sprintf("xxx")
-	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/100)
-	runtime.UpdateMemStats()
-	mallocs = 0 - runtime.MemStats.Mallocs
-	for i := 0; i < 100; i++ {
-		Sprintf("%x", i)
-	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/100)
-	runtime.UpdateMemStats()
-	mallocs = 0 - runtime.MemStats.Mallocs
-	for i := 0; i < 100; i++ {
-		Sprintf("%s", "hello")
-	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/100)
-	runtime.UpdateMemStats()
-	mallocs = 0 - runtime.MemStats.Mallocs
-	for i := 0; i < 100; i++ {
-		Sprintf("%x %x", i, i)
-	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/100)
-	buf := new(bytes.Buffer)
-	runtime.UpdateMemStats()
-	mallocs = 0 - runtime.MemStats.Mallocs
-	for i := 0; i < 100; i++ {
-		buf.Reset()
-		Fprintf(buf, "%x %x %x", i, i, i)
+func BenchmarkSprintfFloat(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sprintf("%g", 5.23184)
 	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/100)
-	runtime.UpdateMemStats()
-	mallocs = 0 - runtime.MemStats.Mallocs
-	for i := 0; i < 100; i++ {
-		buf.Reset()
-		Fprintf(buf, "%s", "hello")
+}
+
+var mallocBuf bytes.Buffer
+
+var mallocTest = []struct {
+	count int
+	desc  string
+	fn    func()
+}{
+	{0, `Sprintf("")`, func() { Sprintf("") }},
+	{1, `Sprintf("xxx")`, func() { Sprintf("xxx") }},
+	{1, `Sprintf("%x")`, func() { Sprintf("%x", 7) }},
+	{2, `Sprintf("%s")`, func() { Sprintf("%s", "hello") }},
+	{1, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }},
+	// For %g we use a float32, not float64, to guarantee passing the argument
+	// does not need to allocate memory to store the result in a pointer-sized word.
+	{2, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }},
+	{0, `Fprintf(buf, "%x %x %x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x %x %x", 7, 8, 9) }},
+	{1, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }},
+}
+
+var _ bytes.Buffer
+
+func TestCountMallocs(t *testing.T) {
+	for _, mt := range mallocTest {
+		const N = 100
+		runtime.UpdateMemStats()
+		mallocs := 0 - runtime.MemStats.Mallocs
+		for i := 0; i < N; i++ {
+			mt.fn()
+		}
+		runtime.UpdateMemStats()
+		mallocs += runtime.MemStats.Mallocs
+		if mallocs/N > uint64(mt.count) {
+			t.Errorf("%s: expected %d mallocs, got %d", mt.desc, mt.count, mallocs/N)
+		}
 	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/100)
 }
 
 type flagPrinter struct{}
 
-func (*flagPrinter) Format(f State, c int) {
+func (*flagPrinter) Format(f State, c rune) {
 	s := "%"
 	for i := 0; i < 128; i++ {
 		if f.Flag(i) {
@@ -741,7 +745,7 @@ type PanicF struct {
 }
 
 // Value receiver.
-func (p PanicF) Format(f State, c int) {
+func (p PanicF) Format(f State, c rune) {
 	panic(p.message)
 }
 
@@ -751,9 +755,9 @@ var panictests = []struct {
 	out string
 }{
 	// String
-	{"%d", (*Panic)(nil), "<nil>"}, // nil pointer special case
-	{"%d", Panic{io.ErrUnexpectedEOF}, "%d(PANIC=unexpected EOF)"},
-	{"%d", Panic{3}, "%d(PANIC=3)"},
+	{"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case
+	{"%s", Panic{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
+	{"%s", Panic{3}, "%s(PANIC=3)"},
 	// GoString
 	{"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case
 	{"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"},
@@ -772,3 +776,37 @@ func TestPanics(t *testing.T) {
 		}
 	}
 }
+
+// Test that erroneous String routine doesn't cause fatal recursion.
+var recurCount = 0
+
+type Recur struct {
+	i      int
+	failed *bool
+}
+
+func (r Recur) String() string {
+	if recurCount++; recurCount > 10 {
+		*r.failed = true
+		return "FAIL"
+	}
+	// This will call badVerb. Before the fix, that would cause us to recur into
+	// this routine to print %!p(value). Now we don't call the user's method
+	// during an error.
+	return Sprintf("recur@%p value: %d", r, r.i)
+}
+
+func TestBadVerbRecursion(t *testing.T) {
+	failed := false
+	r := Recur{3, &failed}
+	Sprintf("recur@%p value: %d\n", &r, r.i)
+	if failed {
+		t.Error("fail with pointer")
+	}
+	failed = false
+	r = Recur{4, &failed}
+	Sprintf("recur@%p, value: %d\n", r, r.i)
+	if failed {
+		t.Error("fail with value")
+	}
+}
diff --git a/src/pkg/fmt/format.go b/src/pkg/fmt/format.go
index 24b15a2..78d9e99 100644
--- a/src/pkg/fmt/format.go
+++ b/src/pkg/fmt/format.go
@@ -8,7 +8,7 @@ import (
 	"bytes"
 	"strconv"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 const (
@@ -154,12 +154,17 @@ func putint(buf []byte, base, val uint64, digits string) int {
 	return i - 1
 }
 
+var (
+	trueBytes  = []byte("true")
+	falseBytes = []byte("false")
+)
+
 // fmt_boolean formats a boolean.
 func (f *fmt) fmt_boolean(v bool) {
 	if v {
-		f.padString("true")
+		f.pad(trueBytes)
 	} else {
-		f.padString("false")
+		f.pad(falseBytes)
 	}
 }
 
@@ -242,8 +247,8 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
 	}
 
 	// If we want a quoted char for %#U, move the data up to make room.
-	if f.unicode && f.uniQuote && a >= 0 && a <= unicode.MaxRune && unicode.IsPrint(int(a)) {
-		runeWidth := utf8.RuneLen(int(a))
+	if f.unicode && f.uniQuote && a >= 0 && a <= unicode.MaxRune && unicode.IsPrint(rune(a)) {
+		runeWidth := utf8.RuneLen(rune(a))
 		width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
 		copy(buf[i-width:], buf[i:])   // guaranteed to have enough room.
 		i -= width
@@ -253,7 +258,7 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
 		j++
 		buf[j] = '\''
 		j++
-		utf8.EncodeRune(buf[j:], int(a))
+		utf8.EncodeRune(buf[j:], rune(a))
 		j += runeWidth
 		buf[j] = '\''
 	}
@@ -283,31 +288,18 @@ func (f *fmt) fmt_s(s string) {
 }
 
 // fmt_sx formats a string as a hexadecimal encoding of its bytes.
-func (f *fmt) fmt_sx(s string) {
-	t := ""
+func (f *fmt) fmt_sx(s, digits string) {
+	// TODO: Avoid buffer by pre-padding.
+	var b bytes.Buffer
 	for i := 0; i < len(s); i++ {
 		if i > 0 && f.space {
-			t += " "
+			b.WriteByte(' ')
 		}
 		v := s[i]
-		t += string(ldigits[v>>4])
-		t += string(ldigits[v&0xF])
+		b.WriteByte(digits[v>>4])
+		b.WriteByte(digits[v&0xF])
 	}
-	f.padString(t)
-}
-
-// fmt_sX formats a string as an uppercase hexadecimal encoding of its bytes.
-func (f *fmt) fmt_sX(s string) {
-	t := ""
-	for i := 0; i < len(s); i++ {
-		if i > 0 && f.space {
-			t += " "
-		}
-		v := s[i]
-		t += string(udigits[v>>4])
-		t += string(udigits[v&0xF])
-	}
-	f.padString(t)
+	f.pad(b.Bytes())
 }
 
 // fmt_q formats a string as a double-quoted, escaped Go string constant.
@@ -329,13 +321,13 @@ func (f *fmt) fmt_q(s string) {
 // fmt_qc formats the integer as a single-quoted, escaped Go character constant.
 // If the character is not valid Unicode, it will print '\ufffd'.
 func (f *fmt) fmt_qc(c int64) {
-	var quoted string
+	var quoted []byte
 	if f.plus {
-		quoted = strconv.QuoteRuneToASCII(int(c))
+		quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
 	} else {
-		quoted = strconv.QuoteRune(int(c))
+		quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
 	}
-	f.padString(quoted)
+	f.pad(quoted)
 }
 
 // floating-point
@@ -347,60 +339,73 @@ func doPrec(f *fmt, def int) int {
 	return def
 }
 
-// Add a plus sign or space to the floating-point string representation if missing and required.
-func (f *fmt) plusSpace(s string) {
-	if s[0] != '-' {
+// formatFloat formats a float64; it is an efficient equivalent to  f.pad(strconv.FormatFloat()...).
+func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
+	// We leave one byte at the beginning of f.intbuf for a sign if needed,
+	// and make it a space, which we might be able to use.
+	f.intbuf[0] = ' '
+	slice := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n)
+	// Add a plus sign or space to the floating-point string representation if missing and required.
+	// The formatted number starts at slice[1].
+	switch slice[1] {
+	case '-', '+':
+		// We're set; drop the leading space.
+		slice = slice[1:]
+	default:
+		// There's no sign, but we might need one.
 		if f.plus {
-			s = "+" + s
+			slice[0] = '+'
 		} else if f.space {
-			s = " " + s
+			// space is already there
+		} else {
+			slice = slice[1:]
 		}
 	}
-	f.padString(s)
+	f.pad(slice)
 }
 
 // fmt_e64 formats a float64 in the form -1.23e+12.
-func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) }
+func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
 
 // fmt_E64 formats a float64 in the form -1.23E+12.
-func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) }
+func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
 
 // fmt_f64 formats a float64 in the form -1.23.
-func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) }
+func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
 
 // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
-func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) }
+func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
 
 // fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
-func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) }
+func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
 
 // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
-func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) }
+func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
 
 // float32
 // cannot defer to float64 versions
 // because it will get rounding wrong in corner cases.
 
 // fmt_e32 formats a float32 in the form -1.23e+12.
-func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) }
+func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
 
 // fmt_E32 formats a float32 in the form -1.23E+12.
-func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) }
+func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
 
 // fmt_f32 formats a float32 in the form -1.23.
-func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) }
+func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
 
 // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
-func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) }
+func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
 
 // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
-func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) }
+func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
 
 // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
-func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) }
+func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
 
 // fmt_c64 formats a complex64 according to the verb.
-func (f *fmt) fmt_c64(v complex64, verb int) {
+func (f *fmt) fmt_c64(v complex64, verb rune) {
 	f.buf.WriteByte('(')
 	r := real(v)
 	for i := 0; ; i++ {
@@ -426,7 +431,7 @@ func (f *fmt) fmt_c64(v complex64, verb int) {
 }
 
 // fmt_c128 formats a complex128 according to the verb.
-func (f *fmt) fmt_c128(v complex128, verb int) {
+func (f *fmt) fmt_c128(v complex128, verb rune) {
 	f.buf.WriteByte('(')
 	r := real(v)
 	for i := 0; ; i++ {
diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go
index 7387349..3b7d346 100644
--- a/src/pkg/fmt/print.go
+++ b/src/pkg/fmt/print.go
@@ -6,11 +6,13 @@ package fmt
 
 import (
 	"bytes"
+	"errors"
 	"io"
 	"os"
 	"reflect"
+	"sync"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 // Some constants in the form of bytes, to avoid string overhead.
@@ -36,7 +38,7 @@ var (
 // the flags and options for the operand's format specifier.
 type State interface {
 	// Write is the function to call to emit formatted output to be printed.
-	Write(b []byte) (ret int, err os.Error)
+	Write(b []byte) (ret int, err error)
 	// Width returns the value of the width option and whether it has been set.
 	Width() (wid int, ok bool)
 	// Precision returns the value of the precision option and whether it has been set.
@@ -50,7 +52,7 @@ type State interface {
 // The implementation of Format may call Sprintf or Fprintf(f) etc.
 // to generate its output.
 type Formatter interface {
-	Format(f State, c int)
+	Format(f State, c rune)
 }
 
 // Stringer is implemented by any value that has a String method,
@@ -72,40 +74,49 @@ type GoStringer interface {
 type pp struct {
 	n         int
 	panicking bool
+	erroring  bool // printing an error condition
 	buf       bytes.Buffer
-	runeBuf   [utf8.UTFMax]byte
-	fmt       fmt
+	// field holds the current item, as an interface{}.
+	field interface{}
+	// value holds the current item, as a reflect.Value, and will be
+	// the zero Value if the item has not been reflected.
+	value   reflect.Value
+	runeBuf [utf8.UTFMax]byte
+	fmt     fmt
 }
 
 // A cache holds a set of reusable objects.
-// The buffered channel holds the currently available objects.
+// The slice is a stack (LIFO).
 // If more are needed, the cache creates them by calling new.
 type cache struct {
-	saved chan interface{}
+	mu    sync.Mutex
+	saved []interface{}
 	new   func() interface{}
 }
 
 func (c *cache) put(x interface{}) {
-	select {
-	case c.saved <- x:
-		// saved in cache
-	default:
-		// discard
+	c.mu.Lock()
+	if len(c.saved) < cap(c.saved) {
+		c.saved = append(c.saved, x)
 	}
+	c.mu.Unlock()
 }
 
 func (c *cache) get() interface{} {
-	select {
-	case x := <-c.saved:
-		return x // reused from cache
-	default:
+	c.mu.Lock()
+	n := len(c.saved)
+	if n == 0 {
+		c.mu.Unlock()
 		return c.new()
 	}
-	panic("not reached")
+	x := c.saved[n-1]
+	c.saved = c.saved[0 : n-1]
+	c.mu.Unlock()
+	return x
 }
 
 func newCache(f func() interface{}) *cache {
-	return &cache{make(chan interface{}, 100), f}
+	return &cache{saved: make([]interface{}, 0, 100), new: f}
 }
 
 var ppFree = newCache(func() interface{} { return new(pp) })
@@ -114,6 +125,7 @@ var ppFree = newCache(func() interface{} { return new(pp) })
 func newPrinter() *pp {
 	p := ppFree.get().(*pp)
 	p.panicking = false
+	p.erroring = false
 	p.fmt.init(&p.buf)
 	return p
 }
@@ -125,6 +137,8 @@ func (p *pp) free() {
 		return
 	}
 	p.buf.Reset()
+	p.field = nil
+	p.value = reflect.Value{}
 	ppFree.put(p)
 }
 
@@ -148,13 +162,13 @@ func (p *pp) Flag(b int) bool {
 	return false
 }
 
-func (p *pp) add(c int) {
+func (p *pp) add(c rune) {
 	p.buf.WriteRune(c)
 }
 
 // Implement Write so we can call Fprintf on a pp (through State), for
 // recursive use in custom verbs.
-func (p *pp) Write(b []byte) (ret int, err os.Error) {
+func (p *pp) Write(b []byte) (ret int, err error) {
 	return p.buf.Write(b)
 }
 
@@ -162,7 +176,7 @@ func (p *pp) Write(b []byte) (ret int, err os.Error) {
 
 // Fprintf formats according to a format specifier and writes to w.
 // It returns the number of bytes written and any write error encountered.
-func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err os.Error) {
+func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
 	p := newPrinter()
 	p.doPrintf(format, a)
 	n64, err := p.buf.WriteTo(w)
@@ -172,7 +186,7 @@ func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err os.Error)
 
 // Printf formats according to a format specifier and writes to standard output.
 // It returns the number of bytes written and any write error encountered.
-func Printf(format string, a ...interface{}) (n int, err os.Error) {
+func Printf(format string, a ...interface{}) (n int, err error) {
 	return Fprintf(os.Stdout, format, a...)
 }
 
@@ -186,9 +200,9 @@ func Sprintf(format string, a ...interface{}) string {
 }
 
 // Errorf formats according to a format specifier and returns the string 
-// converted to an os.ErrorString, which satisfies the os.Error interface.
-func Errorf(format string, a ...interface{}) os.Error {
-	return os.NewError(Sprintf(format, a...))
+// as a value that satisfies error.
+func Errorf(format string, a ...interface{}) error {
+	return errors.New(Sprintf(format, a...))
 }
 
 // These routines do not take a format string
@@ -196,7 +210,7 @@ func Errorf(format string, a ...interface{}) os.Error {
 // Fprint formats using the default formats for its operands and writes to w.
 // Spaces are added between operands when neither is a string.
 // It returns the number of bytes written and any write error encountered.
-func Fprint(w io.Writer, a ...interface{}) (n int, err os.Error) {
+func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
 	p := newPrinter()
 	p.doPrint(a, false, false)
 	n64, err := p.buf.WriteTo(w)
@@ -207,7 +221,7 @@ func Fprint(w io.Writer, a ...interface{}) (n int, err os.Error) {
 // Print formats using the default formats for its operands and writes to standard output.
 // Spaces are added between operands when neither is a string.
 // It returns the number of bytes written and any write error encountered.
-func Print(a ...interface{}) (n int, err os.Error) {
+func Print(a ...interface{}) (n int, err error) {
 	return Fprint(os.Stdout, a...)
 }
 
@@ -228,7 +242,7 @@ func Sprint(a ...interface{}) string {
 // Fprintln formats using the default formats for its operands and writes to w.
 // Spaces are always added between operands and a newline is appended.
 // It returns the number of bytes written and any write error encountered.
-func Fprintln(w io.Writer, a ...interface{}) (n int, err os.Error) {
+func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
 	p := newPrinter()
 	p.doPrint(a, true, true)
 	n64, err := p.buf.WriteTo(w)
@@ -239,7 +253,7 @@ func Fprintln(w io.Writer, a ...interface{}) (n int, err os.Error) {
 // Println formats using the default formats for its operands and writes to standard output.
 // Spaces are always added between operands and a newline is appended.
 // It returns the number of bytes written and any write error encountered.
-func Println(a ...interface{}) (n int, err os.Error) {
+func Println(a ...interface{}) (n int, err error) {
 	return Fprintln(os.Stdout, a...)
 }
 
@@ -258,10 +272,8 @@ func Sprintln(a ...interface{}) string {
 // the thing inside the interface, not the interface itself.
 func getField(v reflect.Value, i int) reflect.Value {
 	val := v.Field(i)
-	if i := val; i.Kind() == reflect.Interface {
-		if inter := i.Interface(); inter != nil {
-			return reflect.ValueOf(inter)
-		}
+	if val.Kind() == reflect.Interface && !val.IsNil() {
+		val = val.Elem()
 	}
 	return val
 }
@@ -288,41 +300,48 @@ func (p *pp) unknownType(v interface{}) {
 	p.buf.WriteByte('?')
 }
 
-func (p *pp) badVerb(verb int, val interface{}) {
+func (p *pp) badVerb(verb rune) {
+	p.erroring = true
 	p.add('%')
 	p.add('!')
 	p.add(verb)
 	p.add('(')
-	if val == nil {
-		p.buf.Write(nilAngleBytes)
-	} else {
-		p.buf.WriteString(reflect.TypeOf(val).String())
+	switch {
+	case p.field != nil:
+		p.buf.WriteString(reflect.TypeOf(p.field).String())
+		p.add('=')
+		p.printField(p.field, 'v', false, false, 0)
+	case p.value.IsValid():
+		p.buf.WriteString(p.value.Type().String())
 		p.add('=')
-		p.printField(val, 'v', false, false, 0)
+		p.printValue(p.value, 'v', false, false, 0)
+	default:
+		p.buf.Write(nilAngleBytes)
 	}
 	p.add(')')
+	p.erroring = false
 }
 
-func (p *pp) fmtBool(v bool, verb int, value interface{}) {
+func (p *pp) fmtBool(v bool, verb rune) {
 	switch verb {
 	case 't', 'v':
 		p.fmt.fmt_boolean(v)
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
 // fmtC formats a rune for the 'c' format.
 func (p *pp) fmtC(c int64) {
-	rune := int(c) // Check for overflow.
-	if int64(rune) != c {
-		rune = utf8.RuneError
+	r := rune(c) // Check for overflow.
+	if int64(r) != c {
+		r = utf8.RuneError
 	}
-	w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], rune)
+	w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], r)
 	p.fmt.pad(p.runeBuf[0:w])
 }
 
-func (p *pp) fmtInt64(v int64, verb int, value interface{}) {
+func (p *pp) fmtInt64(v int64, verb rune) {
 	switch verb {
 	case 'b':
 		p.fmt.integer(v, 2, signed, ldigits)
@@ -336,7 +355,7 @@ func (p *pp) fmtInt64(v int64, verb int, value interface{}) {
 		if 0 <= v && v <= unicode.MaxRune {
 			p.fmt.fmt_qc(v)
 		} else {
-			p.badVerb(verb, value)
+			p.badVerb(verb)
 		}
 	case 'x':
 		p.fmt.integer(v, 16, signed, ldigits)
@@ -345,7 +364,7 @@ func (p *pp) fmtInt64(v int64, verb int, value interface{}) {
 	case 'X':
 		p.fmt.integer(v, 16, signed, udigits)
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
@@ -380,7 +399,7 @@ func (p *pp) fmtUnicode(v int64) {
 	p.fmt.sharp = sharp
 }
 
-func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) {
+func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) {
 	switch verb {
 	case 'b':
 		p.fmt.integer(int64(v), 2, unsigned, ldigits)
@@ -400,7 +419,7 @@ func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) {
 		if 0 <= v && v <= unicode.MaxRune {
 			p.fmt.fmt_qc(int64(v))
 		} else {
-			p.badVerb(verb, value)
+			p.badVerb(verb)
 		}
 	case 'x':
 		p.fmt.integer(int64(v), 16, unsigned, ldigits)
@@ -409,11 +428,11 @@ func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) {
 	case 'U':
 		p.fmtUnicode(int64(v))
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
-func (p *pp) fmtFloat32(v float32, verb int, value interface{}) {
+func (p *pp) fmtFloat32(v float32, verb rune) {
 	switch verb {
 	case 'b':
 		p.fmt.fmt_fb32(v)
@@ -428,11 +447,11 @@ func (p *pp) fmtFloat32(v float32, verb int, value interface{}) {
 	case 'G':
 		p.fmt.fmt_G32(v)
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
-func (p *pp) fmtFloat64(v float64, verb int, value interface{}) {
+func (p *pp) fmtFloat64(v float64, verb rune) {
 	switch verb {
 	case 'b':
 		p.fmt.fmt_fb64(v)
@@ -447,33 +466,33 @@ func (p *pp) fmtFloat64(v float64, verb int, value interface{}) {
 	case 'G':
 		p.fmt.fmt_G64(v)
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
-func (p *pp) fmtComplex64(v complex64, verb int, value interface{}) {
+func (p *pp) fmtComplex64(v complex64, verb rune) {
 	switch verb {
 	case 'e', 'E', 'f', 'F', 'g', 'G':
 		p.fmt.fmt_c64(v, verb)
 	case 'v':
 		p.fmt.fmt_c64(v, 'g')
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
-func (p *pp) fmtComplex128(v complex128, verb int, value interface{}) {
+func (p *pp) fmtComplex128(v complex128, verb rune) {
 	switch verb {
 	case 'e', 'E', 'f', 'F', 'g', 'G':
 		p.fmt.fmt_c128(v, verb)
 	case 'v':
 		p.fmt.fmt_c128(v, 'g')
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
-func (p *pp) fmtString(v string, verb int, goSyntax bool, value interface{}) {
+func (p *pp) fmtString(v string, verb rune, goSyntax bool) {
 	switch verb {
 	case 'v':
 		if goSyntax {
@@ -484,17 +503,17 @@ func (p *pp) fmtString(v string, verb int, goSyntax bool, value interface{}) {
 	case 's':
 		p.fmt.fmt_s(v)
 	case 'x':
-		p.fmt.fmt_sx(v)
+		p.fmt.fmt_sx(v, ldigits)
 	case 'X':
-		p.fmt.fmt_sX(v)
+		p.fmt.fmt_sx(v, udigits)
 	case 'q':
 		p.fmt.fmt_q(v)
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
-func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interface{}) {
+func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, depth int) {
 	if verb == 'v' || verb == 'd' {
 		if goSyntax {
 			p.buf.Write(bytesBytes)
@@ -523,28 +542,28 @@ func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interf
 	case 's':
 		p.fmt.fmt_s(s)
 	case 'x':
-		p.fmt.fmt_sx(s)
+		p.fmt.fmt_sx(s, ldigits)
 	case 'X':
-		p.fmt.fmt_sX(s)
+		p.fmt.fmt_sx(s, udigits)
 	case 'q':
 		p.fmt.fmt_q(s)
 	default:
-		p.badVerb(verb, value)
+		p.badVerb(verb)
 	}
 }
 
-func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) {
+func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
 	var u uintptr
 	switch value.Kind() {
 	case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
 		u = value.Pointer()
 	default:
-		p.badVerb(verb, field)
+		p.badVerb(verb)
 		return
 	}
 	if goSyntax {
 		p.add('(')
-		p.buf.WriteString(reflect.TypeOf(field).String())
+		p.buf.WriteString(value.Type().String())
 		p.add(')')
 		p.add('(')
 		if u == 0 {
@@ -565,12 +584,12 @@ var (
 	uintptrBits = reflect.TypeOf(uintptr(0)).Bits()
 )
 
-func (p *pp) catchPanic(val interface{}, verb int) {
+func (p *pp) catchPanic(field interface{}, verb rune) {
 	if err := recover(); err != nil {
 		// If it's a nil pointer, just say "<nil>". The likeliest causes are a
 		// Stringer that fails to guard against nil or a nil pointer for a
 		// value receiver, and in either case, "<nil>" is a nice result.
-		if v := reflect.ValueOf(val); v.Kind() == reflect.Ptr && v.IsNil() {
+		if v := reflect.ValueOf(field); v.Kind() == reflect.Ptr && v.IsNil() {
 			p.buf.Write(nilAngleBytes)
 			return
 		}
@@ -590,16 +609,77 @@ func (p *pp) catchPanic(val interface{}, verb int) {
 	}
 }
 
-func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) {
+func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) {
+	if p.erroring {
+		return
+	}
+	// Is it a Formatter?
+	if formatter, ok := p.field.(Formatter); ok {
+		handled = true
+		wasString = false
+		defer p.catchPanic(p.field, verb)
+		formatter.Format(p, verb)
+		return
+	}
+	// Must not touch flags before Formatter looks at them.
+	if plus {
+		p.fmt.plus = false
+	}
+
+	// If we're doing Go syntax and the field knows how to supply it, take care of it now.
+	if goSyntax {
+		p.fmt.sharp = false
+		if stringer, ok := p.field.(GoStringer); ok {
+			wasString = false
+			handled = true
+			defer p.catchPanic(p.field, verb)
+			// Print the result of GoString unadorned.
+			p.fmtString(stringer.GoString(), 's', false)
+			return
+		}
+	} else {
+		// If a string is acceptable according to the format, see if
+		// the value satisfies one of the string-valued interfaces.
+		// Println etc. set verb to %v, which is "stringable".
+		switch verb {
+		case 'v', 's', 'x', 'X', 'q':
+			// Is it an error or Stringer?
+			// The duplication in the bodies is necessary:
+			// setting wasString and handled, and deferring catchPanic,
+			// must happen before calling the method.
+			switch v := p.field.(type) {
+			case error:
+				wasString = false
+				handled = true
+				defer p.catchPanic(p.field, verb)
+				p.printField(v.Error(), verb, plus, false, depth)
+				return
+
+			case Stringer:
+				wasString = false
+				handled = true
+				defer p.catchPanic(p.field, verb)
+				p.printField(v.String(), verb, plus, false, depth)
+				return
+			}
+		}
+	}
+	handled = false
+	return
+}
+
+func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
 	if field == nil {
 		if verb == 'T' || verb == 'v' {
 			p.buf.Write(nilAngleBytes)
 		} else {
-			p.badVerb(verb, field)
+			p.badVerb(verb)
 		}
 		return false
 	}
 
+	p.field = field
+	p.value = reflect.Value{}
 	// Special processing considerations.
 	// %T (the value's type) and %p (its address) are special; we always do them first.
 	switch verb {
@@ -607,124 +687,131 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
 		p.printField(reflect.TypeOf(field).String(), 's', false, false, 0)
 		return false
 	case 'p':
-		p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax)
+		p.fmtPointer(reflect.ValueOf(field), verb, goSyntax)
 		return false
 	}
-	// Is it a Formatter?
-	if formatter, ok := field.(Formatter); ok {
-		defer p.catchPanic(field, verb)
-		formatter.Format(p, verb)
-		return false // this value is not a string
 
-	}
-	// Must not touch flags before Formatter looks at them.
-	if plus {
-		p.fmt.plus = false
-	}
-	// If we're doing Go syntax and the field knows how to supply it, take care of it now.
-	if goSyntax {
-		p.fmt.sharp = false
-		if stringer, ok := field.(GoStringer); ok {
-			defer p.catchPanic(field, verb)
-			// Print the result of GoString unadorned.
-			p.fmtString(stringer.GoString(), 's', false, field)
-			return false // this value is not a string
-		}
-	} else {
-		// Is it a Stringer?
-		if stringer, ok := field.(Stringer); ok {
-			defer p.catchPanic(field, verb)
-			p.printField(stringer.String(), verb, plus, false, depth)
-			return false // this value is not a string
-		}
+	if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
+		return wasString
 	}
 
 	// Some types can be done without reflection.
 	switch f := field.(type) {
 	case bool:
-		p.fmtBool(f, verb, field)
-		return false
+		p.fmtBool(f, verb)
 	case float32:
-		p.fmtFloat32(f, verb, field)
-		return false
+		p.fmtFloat32(f, verb)
 	case float64:
-		p.fmtFloat64(f, verb, field)
-		return false
+		p.fmtFloat64(f, verb)
 	case complex64:
-		p.fmtComplex64(complex64(f), verb, field)
-		return false
+		p.fmtComplex64(complex64(f), verb)
 	case complex128:
-		p.fmtComplex128(f, verb, field)
-		return false
+		p.fmtComplex128(f, verb)
 	case int:
-		p.fmtInt64(int64(f), verb, field)
-		return false
+		p.fmtInt64(int64(f), verb)
 	case int8:
-		p.fmtInt64(int64(f), verb, field)
-		return false
+		p.fmtInt64(int64(f), verb)
 	case int16:
-		p.fmtInt64(int64(f), verb, field)
-		return false
+		p.fmtInt64(int64(f), verb)
 	case int32:
-		p.fmtInt64(int64(f), verb, field)
-		return false
+		p.fmtInt64(int64(f), verb)
 	case int64:
-		p.fmtInt64(f, verb, field)
-		return false
+		p.fmtInt64(f, verb)
 	case uint:
-		p.fmtUint64(uint64(f), verb, goSyntax, field)
-		return false
+		p.fmtUint64(uint64(f), verb, goSyntax)
 	case uint8:
-		p.fmtUint64(uint64(f), verb, goSyntax, field)
-		return false
+		p.fmtUint64(uint64(f), verb, goSyntax)
 	case uint16:
-		p.fmtUint64(uint64(f), verb, goSyntax, field)
-		return false
+		p.fmtUint64(uint64(f), verb, goSyntax)
 	case uint32:
-		p.fmtUint64(uint64(f), verb, goSyntax, field)
-		return false
+		p.fmtUint64(uint64(f), verb, goSyntax)
 	case uint64:
-		p.fmtUint64(f, verb, goSyntax, field)
-		return false
+		p.fmtUint64(f, verb, goSyntax)
 	case uintptr:
-		p.fmtUint64(uint64(f), verb, goSyntax, field)
-		return false
+		p.fmtUint64(uint64(f), verb, goSyntax)
 	case string:
-		p.fmtString(f, verb, goSyntax, field)
-		return verb == 's' || verb == 'v'
+		p.fmtString(f, verb, goSyntax)
+		wasString = verb == 's' || verb == 'v'
 	case []byte:
-		p.fmtBytes(f, verb, goSyntax, depth, field)
-		return verb == 's'
+		p.fmtBytes(f, verb, goSyntax, depth)
+		wasString = verb == 's'
+	default:
+		// Need to use reflection
+		return p.printReflectValue(reflect.ValueOf(field), verb, plus, goSyntax, depth)
 	}
+	p.field = nil
+	return
+}
 
-	// Need to use reflection
-	value := reflect.ValueOf(field)
+// printValue is like printField but starts with a reflect value, not an interface{} value.
+func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+	if !value.IsValid() {
+		if verb == 'T' || verb == 'v' {
+			p.buf.Write(nilAngleBytes)
+		} else {
+			p.badVerb(verb)
+		}
+		return false
+	}
+
+	// Special processing considerations.
+	// %T (the value's type) and %p (its address) are special; we always do them first.
+	switch verb {
+	case 'T':
+		p.printField(value.Type().String(), 's', false, false, 0)
+		return false
+	case 'p':
+		p.fmtPointer(value, verb, goSyntax)
+		return false
+	}
+
+	// Handle values with special methods.
+	// Call always, even when field == nil, because handleMethods clears p.fmt.plus for us.
+	p.field = nil // Make sure it's cleared, for safety.
+	if value.CanInterface() {
+		p.field = value.Interface()
+	}
+	if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
+		return wasString
+	}
+
+	return p.printReflectValue(value, verb, plus, goSyntax, depth)
+}
 
+// printReflectValue is the fallback for both printField and printValue.
+// It uses reflect to print the value.
+func (p *pp) printReflectValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+	oldValue := p.value
+	p.value = value
 BigSwitch:
 	switch f := value; f.Kind() {
 	case reflect.Bool:
-		p.fmtBool(f.Bool(), verb, field)
+		p.fmtBool(f.Bool(), verb)
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		p.fmtInt64(f.Int(), verb, field)
+		p.fmtInt64(f.Int(), verb)
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		p.fmtUint64(uint64(f.Uint()), verb, goSyntax, field)
+		p.fmtUint64(uint64(f.Uint()), verb, goSyntax)
 	case reflect.Float32, reflect.Float64:
 		if f.Type().Size() == 4 {
-			p.fmtFloat32(float32(f.Float()), verb, field)
+			p.fmtFloat32(float32(f.Float()), verb)
 		} else {
-			p.fmtFloat64(float64(f.Float()), verb, field)
+			p.fmtFloat64(float64(f.Float()), verb)
 		}
 	case reflect.Complex64, reflect.Complex128:
 		if f.Type().Size() == 8 {
-			p.fmtComplex64(complex64(f.Complex()), verb, field)
+			p.fmtComplex64(complex64(f.Complex()), verb)
 		} else {
-			p.fmtComplex128(complex128(f.Complex()), verb, field)
+			p.fmtComplex128(complex128(f.Complex()), verb)
 		}
 	case reflect.String:
-		p.fmtString(f.String(), verb, goSyntax, field)
+		p.fmtString(f.String(), verb, goSyntax)
 	case reflect.Map:
 		if goSyntax {
 			p.buf.WriteString(f.Type().String())
+			if f.IsNil() {
+				p.buf.WriteString("(nil)")
+				break
+			}
 			p.buf.WriteByte('{')
 		} else {
 			p.buf.Write(mapBytes)
@@ -738,9 +825,9 @@ BigSwitch:
 					p.buf.WriteByte(' ')
 				}
 			}
-			p.printField(key.Interface(), verb, plus, goSyntax, depth+1)
+			p.printValue(key, verb, plus, goSyntax, depth+1)
 			p.buf.WriteByte(':')
-			p.printField(f.MapIndex(key).Interface(), verb, plus, goSyntax, depth+1)
+			p.printValue(f.MapIndex(key), verb, plus, goSyntax, depth+1)
 		}
 		if goSyntax {
 			p.buf.WriteByte('}')
@@ -749,7 +836,7 @@ BigSwitch:
 		}
 	case reflect.Struct:
 		if goSyntax {
-			p.buf.WriteString(reflect.TypeOf(field).String())
+			p.buf.WriteString(value.Type().String())
 		}
 		p.add('{')
 		v := f
@@ -768,20 +855,20 @@ BigSwitch:
 					p.buf.WriteByte(':')
 				}
 			}
-			p.printField(getField(v, i).Interface(), verb, plus, goSyntax, depth+1)
+			p.printValue(getField(v, i), verb, plus, goSyntax, depth+1)
 		}
 		p.buf.WriteByte('}')
 	case reflect.Interface:
 		value := f.Elem()
 		if !value.IsValid() {
 			if goSyntax {
-				p.buf.WriteString(reflect.TypeOf(field).String())
+				p.buf.WriteString(f.Type().String())
 				p.buf.Write(nilParenBytes)
 			} else {
 				p.buf.Write(nilAngleBytes)
 			}
 		} else {
-			return p.printField(value.Interface(), verb, plus, goSyntax, depth+1)
+			wasString = p.printValue(value, verb, plus, goSyntax, depth+1)
 		}
 	case reflect.Array, reflect.Slice:
 		// Byte slices are special.
@@ -797,11 +884,16 @@ BigSwitch:
 			for i := range bytes {
 				bytes[i] = byte(f.Index(i).Uint())
 			}
-			p.fmtBytes(bytes, verb, goSyntax, depth, field)
-			return verb == 's'
+			p.fmtBytes(bytes, verb, goSyntax, depth)
+			wasString = verb == 's'
+			break
 		}
 		if goSyntax {
-			p.buf.WriteString(reflect.TypeOf(field).String())
+			p.buf.WriteString(value.Type().String())
+			if f.Kind() == reflect.Slice && f.IsNil() {
+				p.buf.WriteString("(nil)")
+				break
+			}
 			p.buf.WriteByte('{')
 		} else {
 			p.buf.WriteByte('[')
@@ -814,7 +906,7 @@ BigSwitch:
 					p.buf.WriteByte(' ')
 				}
 			}
-			p.printField(f.Index(i).Interface(), verb, plus, goSyntax, depth+1)
+			p.printValue(f.Index(i), verb, plus, goSyntax, depth+1)
 		}
 		if goSyntax {
 			p.buf.WriteByte('}')
@@ -829,17 +921,17 @@ BigSwitch:
 			switch a := f.Elem(); a.Kind() {
 			case reflect.Array, reflect.Slice:
 				p.buf.WriteByte('&')
-				p.printField(a.Interface(), verb, plus, goSyntax, depth+1)
+				p.printValue(a, verb, plus, goSyntax, depth+1)
 				break BigSwitch
 			case reflect.Struct:
 				p.buf.WriteByte('&')
-				p.printField(a.Interface(), verb, plus, goSyntax, depth+1)
+				p.printValue(a, verb, plus, goSyntax, depth+1)
 				break BigSwitch
 			}
 		}
 		if goSyntax {
 			p.buf.WriteByte('(')
-			p.buf.WriteString(reflect.TypeOf(field).String())
+			p.buf.WriteString(value.Type().String())
 			p.buf.WriteByte(')')
 			p.buf.WriteByte('(')
 			if v == 0 {
@@ -856,11 +948,12 @@ BigSwitch:
 		}
 		p.fmt0x64(uint64(v), true)
 	case reflect.Chan, reflect.Func, reflect.UnsafePointer:
-		p.fmtPointer(field, value, verb, goSyntax)
+		p.fmtPointer(value, verb, goSyntax)
 	default:
 		p.unknownType(f)
 	}
-	return false
+	p.value = oldValue
+	return wasString
 }
 
 // intFromArg gets the fieldnumth element of a. On return, isInt reports whether the argument has type int.
diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go
index 259451d..2815251 100644
--- a/src/pkg/fmt/scan.go
+++ b/src/pkg/fmt/scan.go
@@ -6,6 +6,7 @@ package fmt
 
 import (
 	"bytes"
+	"errors"
 	"io"
 	"math"
 	"os"
@@ -13,7 +14,7 @@ import (
 	"strconv"
 	"strings"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 // runeUnreader is the interface to something that can unread runes.
@@ -21,7 +22,7 @@ import (
 // a local buffer will be used to back up the input, but its contents
 // will be lost when Scan returns.
 type runeUnreader interface {
-	UnreadRune() os.Error
+	UnreadRune() error
 }
 
 // ScanState represents the scanner state passed to custom scanners.
@@ -32,9 +33,9 @@ type ScanState interface {
 	// If invoked during Scanln, Fscanln, or Sscanln, ReadRune() will
 	// return EOF after returning the first '\n' or when reading beyond
 	// the specified width.
-	ReadRune() (rune int, size int, err os.Error)
+	ReadRune() (r rune, size int, err error)
 	// UnreadRune causes the next call to ReadRune to return the same rune.
-	UnreadRune() os.Error
+	UnreadRune() error
 	// SkipSpace skips space in the input. Newlines are treated as space 
 	// unless the scan operation is Scanln, Fscanln or Sscanln, in which case 
 	// a newline is treated as EOF.
@@ -47,14 +48,14 @@ type ScanState interface {
 	// EOF.  The returned slice points to shared data that may be overwritten
 	// by the next call to Token, a call to a Scan function using the ScanState
 	// as input, or when the calling Scan method returns.
-	Token(skipSpace bool, f func(int) bool) (token []byte, err os.Error)
+	Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
 	// Width returns the value of the width option and whether it has been set.
 	// The unit is Unicode code points.
 	Width() (wid int, ok bool)
 	// Because ReadRune is implemented by the interface, Read should never be
 	// called by the scanning routines and a valid implementation of
 	// ScanState may choose always to return an error from Read.
-	Read(buf []byte) (n int, err os.Error)
+	Read(buf []byte) (n int, err error)
 }
 
 // Scanner is implemented by any value that has a Scan method, which scans
@@ -62,27 +63,27 @@ type ScanState interface {
 // receiver, which must be a pointer to be useful.  The Scan method is called
 // for any argument to Scan, Scanf, or Scanln that implements it.
 type Scanner interface {
-	Scan(state ScanState, verb int) os.Error
+	Scan(state ScanState, verb rune) error
 }
 
 // Scan scans text read from standard input, storing successive
 // space-separated values into successive arguments.  Newlines count
 // as space.  It returns the number of items successfully scanned.
 // If that is less than the number of arguments, err will report why.
-func Scan(a ...interface{}) (n int, err os.Error) {
+func Scan(a ...interface{}) (n int, err error) {
 	return Fscan(os.Stdin, a...)
 }
 
 // Scanln is similar to Scan, but stops scanning at a newline and
 // after the final item there must be a newline or EOF.
-func Scanln(a ...interface{}) (n int, err os.Error) {
+func Scanln(a ...interface{}) (n int, err error) {
 	return Fscanln(os.Stdin, a...)
 }
 
 // Scanf scans text read from standard input, storing successive
 // space-separated values into successive arguments as determined by
 // the format.  It returns the number of items successfully scanned.
-func Scanf(format string, a ...interface{}) (n int, err os.Error) {
+func Scanf(format string, a ...interface{}) (n int, err error) {
 	return Fscanf(os.Stdin, format, a...)
 }
 
@@ -90,20 +91,20 @@ func Scanf(format string, a ...interface{}) (n int, err os.Error) {
 // values into successive arguments.  Newlines count as space.  It
 // returns the number of items successfully scanned.  If that is less
 // than the number of arguments, err will report why.
-func Sscan(str string, a ...interface{}) (n int, err os.Error) {
+func Sscan(str string, a ...interface{}) (n int, err error) {
 	return Fscan(strings.NewReader(str), a...)
 }
 
 // Sscanln is similar to Sscan, but stops scanning at a newline and
 // after the final item there must be a newline or EOF.
-func Sscanln(str string, a ...interface{}) (n int, err os.Error) {
+func Sscanln(str string, a ...interface{}) (n int, err error) {
 	return Fscanln(strings.NewReader(str), a...)
 }
 
 // Sscanf scans the argument string, storing successive space-separated
 // values into successive arguments as determined by the format.  It
 // returns the number of items successfully parsed.
-func Sscanf(str string, format string, a ...interface{}) (n int, err os.Error) {
+func Sscanf(str string, format string, a ...interface{}) (n int, err error) {
 	return Fscanf(strings.NewReader(str), format, a...)
 }
 
@@ -111,7 +112,7 @@ func Sscanf(str string, format string, a ...interface{}) (n int, err os.Error) {
 // values into successive arguments.  Newlines count as space.  It
 // returns the number of items successfully scanned.  If that is less
 // than the number of arguments, err will report why.
-func Fscan(r io.Reader, a ...interface{}) (n int, err os.Error) {
+func Fscan(r io.Reader, a ...interface{}) (n int, err error) {
 	s, old := newScanState(r, true, false)
 	n, err = s.doScan(a)
 	s.free(old)
@@ -120,7 +121,7 @@ func Fscan(r io.Reader, a ...interface{}) (n int, err os.Error) {
 
 // Fscanln is similar to Fscan, but stops scanning at a newline and
 // after the final item there must be a newline or EOF.
-func Fscanln(r io.Reader, a ...interface{}) (n int, err os.Error) {
+func Fscanln(r io.Reader, a ...interface{}) (n int, err error) {
 	s, old := newScanState(r, false, true)
 	n, err = s.doScan(a)
 	s.free(old)
@@ -130,7 +131,7 @@ func Fscanln(r io.Reader, a ...interface{}) (n int, err os.Error) {
 // Fscanf scans text read from r, storing successive space-separated
 // values into successive arguments as determined by the format.  It
 // returns the number of items successfully parsed.
-func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err os.Error) {
+func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) {
 	s, old := newScanState(r, false, false)
 	n, err = s.doScanf(format, a)
 	s.free(old)
@@ -140,7 +141,7 @@ func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err os.Error)
 // scanError represents an error generated by the scanning software.
 // It's used as a unique signature to identify such errors when recovering.
 type scanError struct {
-	err os.Error
+	err error
 }
 
 const eof = -1
@@ -149,8 +150,8 @@ const eof = -1
 type ss struct {
 	rr       io.RuneReader // where to read input
 	buf      bytes.Buffer  // token accumulator
-	peekRune int           // one-rune lookahead
-	prevRune int           // last rune returned by ReadRune
+	peekRune rune          // one-rune lookahead
+	prevRune rune          // last rune returned by ReadRune
 	count    int           // runes consumed so far.
 	atEOF    bool          // already read EOF
 	ssave
@@ -170,29 +171,29 @@ type ssave struct {
 // The Read method is only in ScanState so that ScanState
 // satisfies io.Reader. It will never be called when used as
 // intended, so there is no need to make it actually work.
-func (s *ss) Read(buf []byte) (n int, err os.Error) {
-	return 0, os.NewError("ScanState's Read should not be called. Use ReadRune")
+func (s *ss) Read(buf []byte) (n int, err error) {
+	return 0, errors.New("ScanState's Read should not be called. Use ReadRune")
 }
 
-func (s *ss) ReadRune() (rune int, size int, err os.Error) {
+func (s *ss) ReadRune() (r rune, size int, err error) {
 	if s.peekRune >= 0 {
 		s.count++
-		rune = s.peekRune
-		size = utf8.RuneLen(rune)
-		s.prevRune = rune
+		r = s.peekRune
+		size = utf8.RuneLen(r)
+		s.prevRune = r
 		s.peekRune = -1
 		return
 	}
 	if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.fieldLimit {
-		err = os.EOF
+		err = io.EOF
 		return
 	}
 
-	rune, size, err = s.rr.ReadRune()
+	r, size, err = s.rr.ReadRune()
 	if err == nil {
 		s.count++
-		s.prevRune = rune
-	} else if err == os.EOF {
+		s.prevRune = r
+	} else if err == io.EOF {
 		s.atEOF = true
 	}
 	return
@@ -207,10 +208,10 @@ func (s *ss) Width() (wid int, ok bool) {
 
 // The public method returns an error; this private one panics.
 // If getRune reaches EOF, the return value is EOF (-1).
-func (s *ss) getRune() (rune int) {
-	rune, _, err := s.ReadRune()
+func (s *ss) getRune() (r rune) {
+	r, _, err := s.ReadRune()
 	if err != nil {
-		if err == os.EOF {
+		if err == io.EOF {
 			return eof
 		}
 		s.error(err)
@@ -218,18 +219,18 @@ func (s *ss) getRune() (rune int) {
 	return
 }
 
-// mustReadRune turns os.EOF into a panic(io.ErrUnexpectedEOF).
+// mustReadRune turns io.EOF into a panic(io.ErrUnexpectedEOF).
 // It is called in cases such as string scanning where an EOF is a
 // syntax error.
-func (s *ss) mustReadRune() (rune int) {
-	rune = s.getRune()
-	if rune == eof {
+func (s *ss) mustReadRune() (r rune) {
+	r = s.getRune()
+	if r == eof {
 		s.error(io.ErrUnexpectedEOF)
 	}
 	return
 }
 
-func (s *ss) UnreadRune() os.Error {
+func (s *ss) UnreadRune() error {
 	if u, ok := s.rr.(runeUnreader); ok {
 		u.UnreadRune()
 	} else {
@@ -240,15 +241,15 @@ func (s *ss) UnreadRune() os.Error {
 	return nil
 }
 
-func (s *ss) error(err os.Error) {
+func (s *ss) error(err error) {
 	panic(scanError{err})
 }
 
 func (s *ss) errorString(err string) {
-	panic(scanError{os.NewError(err)})
+	panic(scanError{errors.New(err)})
 }
 
-func (s *ss) Token(skipSpace bool, f func(int) bool) (tok []byte, err os.Error) {
+func (s *ss) Token(skipSpace bool, f func(rune) bool) (tok []byte, err error) {
 	defer func() {
 		if e := recover(); e != nil {
 			if se, ok := e.(scanError); ok {
@@ -267,7 +268,7 @@ func (s *ss) Token(skipSpace bool, f func(int) bool) (tok []byte, err os.Error)
 }
 
 // notSpace is the default scanning function used in Token.
-func notSpace(r int) bool {
+func notSpace(r rune) bool {
 	return !unicode.IsSpace(r)
 }
 
@@ -289,7 +290,7 @@ type readRune struct {
 
 // readByte returns the next byte from the input, which may be
 // left over from a previous read if the UTF-8 was ill-formed.
-func (r *readRune) readByte() (b byte, err os.Error) {
+func (r *readRune) readByte() (b byte, err error) {
 	if r.pending > 0 {
 		b = r.pendBuf[0]
 		copy(r.pendBuf[0:], r.pendBuf[1:])
@@ -308,27 +309,27 @@ func (r *readRune) unread(buf []byte) {
 
 // ReadRune returns the next UTF-8 encoded code point from the
 // io.Reader inside r.
-func (r *readRune) ReadRune() (rune int, size int, err os.Error) {
+func (r *readRune) ReadRune() (rr rune, size int, err error) {
 	r.buf[0], err = r.readByte()
 	if err != nil {
 		return 0, 0, err
 	}
 	if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case
-		rune = int(r.buf[0])
+		rr = rune(r.buf[0])
 		return
 	}
 	var n int
 	for n = 1; !utf8.FullRune(r.buf[0:n]); n++ {
 		r.buf[n], err = r.readByte()
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				err = nil
 				break
 			}
 			return
 		}
 	}
-	rune, size = utf8.DecodeRune(r.buf[0:n])
+	rr, size = utf8.DecodeRune(r.buf[0:n])
 	if size < n { // an error
 		r.unread(r.buf[size:n])
 	}
@@ -387,11 +388,11 @@ func (s *ss) free(old ssave) {
 // skipSpace skips spaces and maybe newlines.
 func (s *ss) skipSpace(stopAtNewline bool) {
 	for {
-		rune := s.getRune()
-		if rune == eof {
+		r := s.getRune()
+		if r == eof {
 			return
 		}
-		if rune == '\n' {
+		if r == '\n' {
 			if stopAtNewline {
 				break
 			}
@@ -401,7 +402,7 @@ func (s *ss) skipSpace(stopAtNewline bool) {
 			s.errorString("unexpected newline")
 			return
 		}
-		if !unicode.IsSpace(rune) {
+		if !unicode.IsSpace(r) {
 			s.UnreadRune()
 			break
 		}
@@ -411,21 +412,21 @@ func (s *ss) skipSpace(stopAtNewline bool) {
 // token returns the next space-delimited string from the input.  It
 // skips white space.  For Scanln, it stops at newlines.  For Scan,
 // newlines are treated as spaces.
-func (s *ss) token(skipSpace bool, f func(int) bool) []byte {
+func (s *ss) token(skipSpace bool, f func(rune) bool) []byte {
 	if skipSpace {
 		s.skipSpace(false)
 	}
 	// read until white space or newline
 	for {
-		rune := s.getRune()
-		if rune == eof {
+		r := s.getRune()
+		if r == eof {
 			break
 		}
-		if !f(rune) {
+		if !f(r) {
 			s.UnreadRune()
 			break
 		}
-		s.buf.WriteRune(rune)
+		s.buf.WriteRune(r)
 	}
 	return s.buf.Bytes()
 }
@@ -435,23 +436,23 @@ func (s *ss) typeError(field interface{}, expected string) {
 	s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String())
 }
 
-var complexError = os.NewError("syntax error scanning complex number")
-var boolError = os.NewError("syntax error scanning boolean")
+var complexError = errors.New("syntax error scanning complex number")
+var boolError = errors.New("syntax error scanning boolean")
 
 // consume reads the next rune in the input and reports whether it is in the ok string.
 // If accept is true, it puts the character into the input token.
 func (s *ss) consume(ok string, accept bool) bool {
-	rune := s.getRune()
-	if rune == eof {
+	r := s.getRune()
+	if r == eof {
 		return false
 	}
-	if strings.IndexRune(ok, rune) >= 0 {
+	if strings.IndexRune(ok, r) >= 0 {
 		if accept {
-			s.buf.WriteRune(rune)
+			s.buf.WriteRune(r)
 		}
 		return true
 	}
-	if rune != eof && accept {
+	if r != eof && accept {
 		s.UnreadRune()
 	}
 	return false
@@ -459,17 +460,17 @@ func (s *ss) consume(ok string, accept bool) bool {
 
 // peek reports whether the next character is in the ok string, without consuming it.
 func (s *ss) peek(ok string) bool {
-	rune := s.getRune()
-	if rune != eof {
+	r := s.getRune()
+	if r != eof {
 		s.UnreadRune()
 	}
-	return strings.IndexRune(ok, rune) >= 0
+	return strings.IndexRune(ok, r) >= 0
 }
 
 func (s *ss) notEOF() {
 	// Guarantee there is data to be read.
-	if rune := s.getRune(); rune == eof {
-		panic(os.EOF)
+	if r := s.getRune(); r == eof {
+		panic(io.EOF)
 	}
 	s.UnreadRune()
 }
@@ -481,7 +482,7 @@ func (s *ss) accept(ok string) bool {
 }
 
 // okVerb verifies that the verb is present in the list, setting s.err appropriately if not.
-func (s *ss) okVerb(verb int, okVerbs, typ string) bool {
+func (s *ss) okVerb(verb rune, okVerbs, typ string) bool {
 	for _, v := range okVerbs {
 		if v == verb {
 			return true
@@ -492,7 +493,7 @@ func (s *ss) okVerb(verb int, okVerbs, typ string) bool {
 }
 
 // scanBool returns the value of the boolean represented by the next token.
-func (s *ss) scanBool(verb int) bool {
+func (s *ss) scanBool(verb rune) bool {
 	s.skipSpace(false)
 	s.notEOF()
 	if !s.okVerb(verb, "tv", "boolean") {
@@ -530,7 +531,7 @@ const (
 )
 
 // getBase returns the numeric base represented by the verb and its digit string.
-func (s *ss) getBase(verb int) (base int, digits string) {
+func (s *ss) getBase(verb rune) (base int, digits string) {
 	s.okVerb(verb, "bdoUxXv", "integer") // sets s.err
 	base = 10
 	digits = decimalDigits
@@ -564,13 +565,13 @@ func (s *ss) scanNumber(digits string, haveDigits bool) string {
 // scanRune returns the next rune value in the input.
 func (s *ss) scanRune(bitSize int) int64 {
 	s.notEOF()
-	rune := int64(s.getRune())
+	r := int64(s.getRune())
 	n := uint(bitSize)
-	x := (rune << (64 - n)) >> (64 - n)
-	if x != rune {
-		s.errorString("overflow on character value " + string(rune))
+	x := (r << (64 - n)) >> (64 - n)
+	if x != r {
+		s.errorString("overflow on character value " + string(r))
 	}
-	return rune
+	return r
 }
 
 // scanBasePrefix reports whether the integer begins with a 0 or 0x,
@@ -593,7 +594,7 @@ func (s *ss) scanBasePrefix() (base int, digits string, found bool) {
 
 // scanInt returns the value of the integer represented by the next
 // token, checking for overflow.  Any error is stored in s.err.
-func (s *ss) scanInt(verb int, bitSize int) int64 {
+func (s *ss) scanInt(verb rune, bitSize int) int64 {
 	if verb == 'c' {
 		return s.scanRune(bitSize)
 	}
@@ -612,7 +613,7 @@ func (s *ss) scanInt(verb int, bitSize int) int64 {
 		}
 	}
 	tok := s.scanNumber(digits, haveDigits)
-	i, err := strconv.Btoi64(tok, base)
+	i, err := strconv.ParseInt(tok, base, 64)
 	if err != nil {
 		s.error(err)
 	}
@@ -626,7 +627,7 @@ func (s *ss) scanInt(verb int, bitSize int) int64 {
 
 // scanUint returns the value of the unsigned integer represented
 // by the next token, checking for overflow.  Any error is stored in s.err.
-func (s *ss) scanUint(verb int, bitSize int) uint64 {
+func (s *ss) scanUint(verb rune, bitSize int) uint64 {
 	if verb == 'c' {
 		return uint64(s.scanRune(bitSize))
 	}
@@ -642,7 +643,7 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 {
 		base, digits, haveDigits = s.scanBasePrefix()
 	}
 	tok := s.scanNumber(digits, haveDigits)
-	i, err := strconv.Btoui64(tok, base)
+	i, err := strconv.ParseUint(tok, base, 64)
 	if err != nil {
 		s.error(err)
 	}
@@ -718,7 +719,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
 	if p := strings.Index(str, "p"); p >= 0 {
 		// Atof doesn't handle power-of-2 exponents,
 		// but they're easy to evaluate.
-		f, err := strconv.AtofN(str[:p], n)
+		f, err := strconv.ParseFloat(str[:p], n)
 		if err != nil {
 			// Put full string into error.
 			if e, ok := err.(*strconv.NumError); ok {
@@ -736,7 +737,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
 		}
 		return math.Ldexp(f, n)
 	}
-	f, err := strconv.AtofN(str, n)
+	f, err := strconv.ParseFloat(str, n)
 	if err != nil {
 		s.error(err)
 	}
@@ -747,7 +748,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
 // The atof argument is a type-specific reader for the underlying type.
 // If we're reading complex64, atof will parse float32s and convert them
 // to float64's to avoid reproducing this code for each complex type.
-func (s *ss) scanComplex(verb int, n int) complex128 {
+func (s *ss) scanComplex(verb rune, n int) complex128 {
 	if !s.okVerb(verb, floatVerbs, "complex") {
 		return 0
 	}
@@ -761,7 +762,7 @@ func (s *ss) scanComplex(verb int, n int) complex128 {
 
 // convertString returns the string represented by the next input characters.
 // The format of the input is determined by the verb.
-func (s *ss) convertString(verb int) (str string) {
+func (s *ss) convertString(verb rune) (str string) {
 	if !s.okVerb(verb, "svqx", "string") {
 		return ""
 	}
@@ -786,26 +787,26 @@ func (s *ss) quotedString() string {
 	case '`':
 		// Back-quoted: Anything goes until EOF or back quote.
 		for {
-			rune := s.mustReadRune()
-			if rune == quote {
+			r := s.mustReadRune()
+			if r == quote {
 				break
 			}
-			s.buf.WriteRune(rune)
+			s.buf.WriteRune(r)
 		}
 		return s.buf.String()
 	case '"':
 		// Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes.
 		s.buf.WriteRune(quote)
 		for {
-			rune := s.mustReadRune()
-			s.buf.WriteRune(rune)
-			if rune == '\\' {
+			r := s.mustReadRune()
+			s.buf.WriteRune(r)
+			if r == '\\' {
 				// In a legal backslash escape, no matter how long, only the character
 				// immediately after the escape can itself be a backslash or quote.
 				// Thus we only need to protect the first character after the backslash.
-				rune := s.mustReadRune()
-				s.buf.WriteRune(rune)
-			} else if rune == '"' {
+				r := s.mustReadRune()
+				s.buf.WriteRune(r)
+			} else if r == '"' {
 				break
 			}
 		}
@@ -821,7 +822,8 @@ func (s *ss) quotedString() string {
 }
 
 // hexDigit returns the value of the hexadecimal digit
-func (s *ss) hexDigit(digit int) int {
+func (s *ss) hexDigit(d rune) int {
+	digit := int(d)
 	switch digit {
 	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
 		return digit - '0'
@@ -871,14 +873,14 @@ const floatVerbs = "beEfFgGv"
 const hugeWid = 1 << 30
 
 // scanOne scans a single value, deriving the scanner from the type of the argument.
-func (s *ss) scanOne(verb int, field interface{}) {
+func (s *ss) scanOne(verb rune, field interface{}) {
 	s.buf.Reset()
-	var err os.Error
+	var err error
 	// If the parameter has its own Scan method, use that.
 	if v, ok := field.(Scanner); ok {
 		err = v.Scan(s, verb)
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				err = io.ErrUnexpectedEOF
 			}
 			s.error(err)
@@ -975,11 +977,11 @@ func (s *ss) scanOne(verb int, field interface{}) {
 }
 
 // errorHandler turns local panics into error returns.
-func errorHandler(errp *os.Error) {
+func errorHandler(errp *error) {
 	if e := recover(); e != nil {
 		if se, ok := e.(scanError); ok { // catch local error
 			*errp = se.err
-		} else if eof, ok := e.(os.Error); ok && eof == os.EOF { // out of input
+		} else if eof, ok := e.(error); ok && eof == io.EOF { // out of input
 			*errp = eof
 		} else {
 			panic(e)
@@ -988,7 +990,7 @@ func errorHandler(errp *os.Error) {
 }
 
 // doScan does the real work for scanning without a format string.
-func (s *ss) doScan(a []interface{}) (numProcessed int, err os.Error) {
+func (s *ss) doScan(a []interface{}) (numProcessed int, err error) {
 	defer errorHandler(&err)
 	for _, field := range a {
 		s.scanOne('v', field)
@@ -997,11 +999,11 @@ func (s *ss) doScan(a []interface{}) (numProcessed int, err os.Error) {
 	// Check for newline if required.
 	if !s.nlIsSpace {
 		for {
-			rune := s.getRune()
-			if rune == '\n' || rune == eof {
+			r := s.getRune()
+			if r == '\n' || r == eof {
 				break
 			}
-			if !unicode.IsSpace(rune) {
+			if !unicode.IsSpace(r) {
 				s.errorString("Scan: expected newline")
 				break
 			}
@@ -1060,7 +1062,7 @@ func (s *ss) advance(format string) (i int) {
 
 // doScanf does the real work when scanning with a format string.
 //  At the moment, it handles only pointers to basic types.
-func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err os.Error) {
+func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err error) {
 	defer errorHandler(&err)
 	end := len(format) - 1
 	// We process one item per non-trivial format
diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go
index 3f06e57..b26c828 100644
--- a/src/pkg/fmt/scan_test.go
+++ b/src/pkg/fmt/scan_test.go
@@ -7,15 +7,15 @@ package fmt_test
 import (
 	"bufio"
 	"bytes"
+	"errors"
 	. "fmt"
 	"io"
 	"math"
-	"os"
 	"reflect"
 	"regexp"
 	"strings"
 	"testing"
-	"utf8"
+	"unicode/utf8"
 )
 
 type ScanTest struct {
@@ -56,6 +56,7 @@ var (
 	stringVal            string
 	stringVal1           string
 	bytesVal             []byte
+	runeVal              rune
 	complex64Val         complex64
 	complex128Val        complex128
 	renamedBoolVal       renamedBool
@@ -87,14 +88,14 @@ type FloatTest struct {
 // Xs accepts any non-empty run of the verb character
 type Xs string
 
-func (x *Xs) Scan(state ScanState, verb int) os.Error {
-	tok, err := state.Token(true, func(r int) bool { return r == verb })
+func (x *Xs) Scan(state ScanState, verb rune) error {
+	tok, err := state.Token(true, func(r rune) bool { return r == verb })
 	if err != nil {
 		return err
 	}
 	s := string(tok)
 	if !regexp.MustCompile("^" + string(verb) + "+$").MatchString(s) {
-		return os.NewError("syntax error for xs")
+		return errors.New("syntax error for xs")
 	}
 	*x = Xs(s)
 	return nil
@@ -109,7 +110,7 @@ type IntString struct {
 	s string
 }
 
-func (s *IntString) Scan(state ScanState, verb int) os.Error {
+func (s *IntString) Scan(state ScanState, verb rune) error {
 	if _, err := Fscan(state, &s.i); err != nil {
 		return err
 	}
@@ -130,7 +131,7 @@ type myStringReader struct {
 	r *strings.Reader
 }
 
-func (s *myStringReader) Read(p []byte) (n int, err os.Error) {
+func (s *myStringReader) Read(p []byte) (n int, err error) {
 	return s.r.Read(p)
 }
 
@@ -225,9 +226,9 @@ var scanfTests = []ScanfTest{
 	{"%v", "0377\n", &intVal, 0377},
 	{"%v", "0x44\n", &intVal, 0x44},
 	{"%d", "72\n", &intVal, 72},
-	{"%c", "a\n", &intVal, 'a'},
-	{"%c", "\u5072\n", &intVal, 0x5072},
-	{"%c", "\u1234\n", &intVal, '\u1234'},
+	{"%c", "a\n", &runeVal, 'a'},
+	{"%c", "\u5072\n", &runeVal, '\u5072'},
+	{"%c", "\u1234\n", &runeVal, '\u1234'},
 	{"%d", "73\n", &int8Val, int8(73)},
 	{"%d", "+74\n", &int16Val, int16(74)},
 	{"%d", "75\n", &int32Val, int32(75)},
@@ -322,9 +323,10 @@ var s, t string
 var c complex128
 var x, y Xs
 var z IntString
+var r1, r2, r3 rune
 
 var multiTests = []ScanfMultiTest{
-	{"", "", nil, nil, ""},
+	{"", "", []interface{}{}, []interface{}{}, ""},
 	{"%d", "23", args(&i), args(23), ""},
 	{"%2s%3s", "22333", args(&s, &t), args("22", "333"), ""},
 	{"%2d%3d", "44555", args(&i, &j), args(44, 555), ""},
@@ -333,7 +335,7 @@ var multiTests = []ScanfMultiTest{
 	{"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""},
 	{"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""},
 	{"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""},
-	{"%c%c%c", "2\u50c2X", args(&i, &j, &k), args('2', '\u50c2', 'X'), ""},
+	{"%c%c%c", "2\u50c2X", args(&r1, &r2, &r3), args('2', '\u50c2', 'X'), ""},
 
 	// Custom scanners.
 	{"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""},
@@ -347,10 +349,10 @@ var multiTests = []ScanfMultiTest{
 	{"X%d", "10X", args(&intVal), nil, "input does not match format"},
 
 	// Bad UTF-8: should see every byte.
-	{"%c%c%c", "\xc2X\xc2", args(&i, &j, &k), args(utf8.RuneError, 'X', utf8.RuneError), ""},
+	{"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
 }
 
-func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, os.Error)) {
+func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) {
 	for _, test := range scanTests {
 		var r io.Reader
 		if name == "StringReader" {
@@ -378,7 +380,7 @@ func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}
 		}
 		val := v.Interface()
 		if !reflect.DeepEqual(val, test.out) {
-			t.Errorf("%s scanning %q: expected %v got %v, type %T", name, test.text, test.out, val, val)
+			t.Errorf("%s scanning %q: expected %#v got %#v, type %T", name, test.text, test.out, val, val)
 		}
 	}
 }
@@ -417,7 +419,7 @@ func TestScanf(t *testing.T) {
 		}
 		val := v.Interface()
 		if !reflect.DeepEqual(val, test.out) {
-			t.Errorf("scanning (%q, %q): expected %v got %v, type %T", test.format, test.text, test.out, val, val)
+			t.Errorf("scanning (%q, %q): expected %#v got %#v, type %T", test.format, test.text, test.out, val, val)
 		}
 	}
 }
@@ -431,7 +433,7 @@ func TestScanOverflow(t *testing.T) {
 			t.Errorf("expected overflow scanning %q", test.text)
 			continue
 		}
-		if !re.MatchString(err.String()) {
+		if !re.MatchString(err.Error()) {
 			t.Errorf("expected overflow error scanning %q: %s", test.text, err)
 		}
 	}
@@ -500,7 +502,7 @@ func testScanfMulti(name string, t *testing.T) {
 		if err != nil {
 			if test.err == "" {
 				t.Errorf("got error scanning (%q, %q): %q", test.format, test.text, err)
-			} else if strings.Index(err.String(), test.err) < 0 {
+			} else if strings.Index(err.Error(), test.err) < 0 {
 				t.Errorf("got wrong error scanning (%q, %q): %q; expected %q", test.format, test.text, err, test.err)
 			}
 			continue
@@ -520,7 +522,7 @@ func testScanfMulti(name string, t *testing.T) {
 		}
 		result := resultVal.Interface()
 		if !reflect.DeepEqual(result, test.out) {
-			t.Errorf("scanning (%q, %q): expected %v got %v", test.format, test.text, test.out, result)
+			t.Errorf("scanning (%q, %q): expected %#v got %#v", test.format, test.text, test.out, result)
 		}
 	}
 }
@@ -594,7 +596,7 @@ func TestScanNotPointer(t *testing.T) {
 	_, err := Fscan(r, a)
 	if err == nil {
 		t.Error("expected error scanning non-pointer")
-	} else if strings.Index(err.String(), "pointer") < 0 {
+	} else if strings.Index(err.Error(), "pointer") < 0 {
 		t.Errorf("expected pointer error scanning non-pointer, got: %s", err)
 	}
 }
@@ -604,7 +606,7 @@ func TestScanlnNoNewline(t *testing.T) {
 	_, err := Sscanln("1 x\n", &a)
 	if err == nil {
 		t.Error("expected error scanning string missing newline")
-	} else if strings.Index(err.String(), "newline") < 0 {
+	} else if strings.Index(err.Error(), "newline") < 0 {
 		t.Errorf("expected newline error scanning string missing newline, got: %s", err)
 	}
 }
@@ -615,7 +617,7 @@ func TestScanlnWithMiddleNewline(t *testing.T) {
 	_, err := Fscanln(r, &a, &b)
 	if err == nil {
 		t.Error("expected error scanning string with extra newline")
-	} else if strings.Index(err.String(), "newline") < 0 {
+	} else if strings.Index(err.Error(), "newline") < 0 {
 		t.Errorf("expected newline error scanning string with extra newline, got: %s", err)
 	}
 }
@@ -626,7 +628,7 @@ type eofCounter struct {
 	eofCount int
 }
 
-func (ec *eofCounter) Read(b []byte) (n int, err os.Error) {
+func (ec *eofCounter) Read(b []byte) (n int, err error) {
 	n, err = ec.reader.Read(b)
 	if n == 0 {
 		ec.eofCount++
@@ -670,14 +672,14 @@ func TestEOFAtEndOfInput(t *testing.T) {
 	if n != 1 || i != 23 {
 		t.Errorf("Sscanf expected one value of 23; got %d %d", n, i)
 	}
-	if err != os.EOF {
+	if err != io.EOF {
 		t.Errorf("Sscanf expected EOF; got %q", err)
 	}
 	n, err = Sscan("234", &i, &j)
 	if n != 1 || i != 234 {
 		t.Errorf("Sscan expected one value of 234; got %d %d", n, i)
 	}
-	if err != os.EOF {
+	if err != io.EOF {
 		t.Errorf("Sscan expected EOF; got %q", err)
 	}
 	// Trailing space is tougher.
@@ -685,7 +687,7 @@ func TestEOFAtEndOfInput(t *testing.T) {
 	if n != 1 || i != 234 {
 		t.Errorf("Sscan expected one value of 234; got %d %d", n, i)
 	}
-	if err != os.EOF {
+	if err != io.EOF {
 		t.Errorf("Sscan expected EOF; got %q", err)
 	}
 }
@@ -715,10 +717,10 @@ var eofTests = []struct {
 
 func TestEOFAllTypes(t *testing.T) {
 	for i, test := range eofTests {
-		if _, err := Sscanf("", test.format, test.v); err != os.EOF {
+		if _, err := Sscanf("", test.format, test.v); err != io.EOF {
 			t.Errorf("#%d: %s %T not eof on empty string: %s", i, test.format, test.v, err)
 		}
-		if _, err := Sscanf("   ", test.format, test.v); err != os.EOF {
+		if _, err := Sscanf("   ", test.format, test.v); err != io.EOF {
 			t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err)
 		}
 	}
@@ -749,8 +751,8 @@ type TwoLines string
 
 // Attempt to read two lines into the object.  Scanln should prevent this
 // because it stops at newline; Scan and Scanf should be fine.
-func (t *TwoLines) Scan(state ScanState, verb int) os.Error {
-	chars := make([]int, 0, 100)
+func (t *TwoLines) Scan(state ScanState, verb rune) error {
+	chars := make([]rune, 0, 100)
 	for nlCount := 0; nlCount < 2; {
 		c, _, err := state.ReadRune()
 		if err != nil {
@@ -812,7 +814,7 @@ type RecursiveInt struct {
 	next *RecursiveInt
 }
 
-func (r *RecursiveInt) Scan(state ScanState, verb int) (err os.Error) {
+func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) {
 	_, err = Fscan(state, &r.i)
 	if err != nil {
 		return
@@ -820,7 +822,7 @@ func (r *RecursiveInt) Scan(state ScanState, verb int) (err os.Error) {
 	next := new(RecursiveInt)
 	_, err = Fscanf(state, ".%v", next)
 	if err != nil {
-		if err == os.NewError("input does not match format") || err == io.ErrUnexpectedEOF {
+		if err == errors.New("input does not match format") || err == io.ErrUnexpectedEOF {
 			err = nil
 		}
 		return
@@ -832,16 +834,15 @@ func (r *RecursiveInt) Scan(state ScanState, verb int) (err os.Error) {
 // Perform the same scanning task as RecursiveInt.Scan
 // but without recurring through scanner, so we can compare
 // performance more directly.
-func scanInts(r *RecursiveInt, b *bytes.Buffer) (err os.Error) {
+func scanInts(r *RecursiveInt, b *bytes.Buffer) (err error) {
 	r.next = nil
 	_, err = Fscan(b, &r.i)
 	if err != nil {
 		return
 	}
-	var c int
-	c, _, err = b.ReadRune()
+	c, _, err := b.ReadRune()
 	if err != nil {
-		if err == os.EOF {
+		if err == io.EOF {
 			err = nil
 		}
 		return
@@ -868,7 +869,7 @@ func makeInts(n int) []byte {
 
 func TestScanInts(t *testing.T) {
 	testScanInts(t, scanInts)
-	testScanInts(t, func(r *RecursiveInt, b *bytes.Buffer) (err os.Error) {
+	testScanInts(t, func(r *RecursiveInt, b *bytes.Buffer) (err error) {
 		_, err = Fscan(b, r)
 		return
 	})
@@ -878,7 +879,7 @@ func TestScanInts(t *testing.T) {
 // platform that does not support split stack.
 const intCount = 800
 
-func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) os.Error) {
+func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) error) {
 	r := new(RecursiveInt)
 	ints := makeInts(intCount)
 	buf := bytes.NewBuffer(ints)
diff --git a/src/pkg/go/ast/Makefile b/src/pkg/go/ast/Makefile
index 40be102..30c386c 100644
--- a/src/pkg/go/ast/Makefile
+++ b/src/pkg/go/ast/Makefile
@@ -8,6 +8,7 @@ TARG=go/ast
 GOFILES=\
 	ast.go\
 	filter.go\
+	import.go\
 	print.go\
 	resolve.go\
 	scope.go\
diff --git a/src/pkg/go/ast/ast.go b/src/pkg/go/ast/ast.go
index 22bd5ee..7123fe5 100644
--- a/src/pkg/go/ast/ast.go
+++ b/src/pkg/go/ast/ast.go
@@ -9,8 +9,9 @@ package ast
 
 import (
 	"go/token"
+	"strings"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 // ----------------------------------------------------------------------------
@@ -76,6 +77,74 @@ type CommentGroup struct {
 func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() }
 func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() }
 
+func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' }
+
+func stripTrailingWhitespace(s string) string {
+	i := len(s)
+	for i > 0 && isWhitespace(s[i-1]) {
+		i--
+	}
+	return s[0:i]
+}
+
+// Text returns the text of the comment,
+// with the comment markers - //, /*, and */ - removed.
+func (g *CommentGroup) Text() string {
+	if g == nil {
+		return ""
+	}
+	comments := make([]string, len(g.List))
+	for i, c := range g.List {
+		comments[i] = string(c.Text)
+	}
+
+	lines := make([]string, 0, 10) // most comments are less than 10 lines
+	for _, c := range comments {
+		// Remove comment markers.
+		// The parser has given us exactly the comment text.
+		switch c[1] {
+		case '/':
+			//-style comment
+			c = c[2:]
+			// Remove leading space after //, if there is one.
+			// TODO(gri) This appears to be necessary in isolated
+			//           cases (bignum.RatFromString) - why?
+			if len(c) > 0 && c[0] == ' ' {
+				c = c[1:]
+			}
+		case '*':
+			/*-style comment */
+			c = c[2 : len(c)-2]
+		}
+
+		// Split on newlines.
+		cl := strings.Split(c, "\n")
+
+		// Walk lines, stripping trailing white space and adding to list.
+		for _, l := range cl {
+			lines = append(lines, stripTrailingWhitespace(l))
+		}
+	}
+
+	// Remove leading blank lines; convert runs of
+	// interior blank lines to a single blank line.
+	n := 0
+	for _, line := range lines {
+		if line != "" || n > 0 && lines[n-1] != "" {
+			lines[n] = line
+			n++
+		}
+	}
+	lines = lines[0:n]
+
+	// Add final "" entry to get trailing newline from Join.
+	if n > 0 && lines[n-1] != "" {
+		lines = append(lines, "")
+	}
+
+	return strings.Join(lines, "\n")
+}
+
 // ----------------------------------------------------------------------------
 // Expressions and types
 
@@ -412,29 +481,29 @@ func (x *ChanType) End() token.Pos      { return x.Value.End() }
 // exprNode() ensures that only expression/type nodes can be
 // assigned to an ExprNode.
 //
-func (x *BadExpr) exprNode()        {}
-func (x *Ident) exprNode()          {}
-func (x *Ellipsis) exprNode()       {}
-func (x *BasicLit) exprNode()       {}
-func (x *FuncLit) exprNode()        {}
-func (x *CompositeLit) exprNode()   {}
-func (x *ParenExpr) exprNode()      {}
-func (x *SelectorExpr) exprNode()   {}
-func (x *IndexExpr) exprNode()      {}
-func (x *SliceExpr) exprNode()      {}
-func (x *TypeAssertExpr) exprNode() {}
-func (x *CallExpr) exprNode()       {}
-func (x *StarExpr) exprNode()       {}
-func (x *UnaryExpr) exprNode()      {}
-func (x *BinaryExpr) exprNode()     {}
-func (x *KeyValueExpr) exprNode()   {}
-
-func (x *ArrayType) exprNode()     {}
-func (x *StructType) exprNode()    {}
-func (x *FuncType) exprNode()      {}
-func (x *InterfaceType) exprNode() {}
-func (x *MapType) exprNode()       {}
-func (x *ChanType) exprNode()      {}
+func (*BadExpr) exprNode()        {}
+func (*Ident) exprNode()          {}
+func (*Ellipsis) exprNode()       {}
+func (*BasicLit) exprNode()       {}
+func (*FuncLit) exprNode()        {}
+func (*CompositeLit) exprNode()   {}
+func (*ParenExpr) exprNode()      {}
+func (*SelectorExpr) exprNode()   {}
+func (*IndexExpr) exprNode()      {}
+func (*SliceExpr) exprNode()      {}
+func (*TypeAssertExpr) exprNode() {}
+func (*CallExpr) exprNode()       {}
+func (*StarExpr) exprNode()       {}
+func (*UnaryExpr) exprNode()      {}
+func (*BinaryExpr) exprNode()     {}
+func (*KeyValueExpr) exprNode()   {}
+
+func (*ArrayType) exprNode()     {}
+func (*StructType) exprNode()    {}
+func (*FuncType) exprNode()      {}
+func (*InterfaceType) exprNode() {}
+func (*MapType) exprNode()       {}
+func (*ChanType) exprNode()      {}
 
 // ----------------------------------------------------------------------------
 // Convenience functions for Idents
@@ -711,27 +780,27 @@ func (s *RangeStmt) End() token.Pos  { return s.Body.End() }
 // stmtNode() ensures that only statement nodes can be
 // assigned to a StmtNode.
 //
-func (s *BadStmt) stmtNode()        {}
-func (s *DeclStmt) stmtNode()       {}
-func (s *EmptyStmt) stmtNode()      {}
-func (s *LabeledStmt) stmtNode()    {}
-func (s *ExprStmt) stmtNode()       {}
-func (s *SendStmt) stmtNode()       {}
-func (s *IncDecStmt) stmtNode()     {}
-func (s *AssignStmt) stmtNode()     {}
-func (s *GoStmt) stmtNode()         {}
-func (s *DeferStmt) stmtNode()      {}
-func (s *ReturnStmt) stmtNode()     {}
-func (s *BranchStmt) stmtNode()     {}
-func (s *BlockStmt) stmtNode()      {}
-func (s *IfStmt) stmtNode()         {}
-func (s *CaseClause) stmtNode()     {}
-func (s *SwitchStmt) stmtNode()     {}
-func (s *TypeSwitchStmt) stmtNode() {}
-func (s *CommClause) stmtNode()     {}
-func (s *SelectStmt) stmtNode()     {}
-func (s *ForStmt) stmtNode()        {}
-func (s *RangeStmt) stmtNode()      {}
+func (*BadStmt) stmtNode()        {}
+func (*DeclStmt) stmtNode()       {}
+func (*EmptyStmt) stmtNode()      {}
+func (*LabeledStmt) stmtNode()    {}
+func (*ExprStmt) stmtNode()       {}
+func (*SendStmt) stmtNode()       {}
+func (*IncDecStmt) stmtNode()     {}
+func (*AssignStmt) stmtNode()     {}
+func (*GoStmt) stmtNode()         {}
+func (*DeferStmt) stmtNode()      {}
+func (*ReturnStmt) stmtNode()     {}
+func (*BranchStmt) stmtNode()     {}
+func (*BlockStmt) stmtNode()      {}
+func (*IfStmt) stmtNode()         {}
+func (*CaseClause) stmtNode()     {}
+func (*SwitchStmt) stmtNode()     {}
+func (*TypeSwitchStmt) stmtNode() {}
+func (*CommClause) stmtNode()     {}
+func (*SelectStmt) stmtNode()     {}
+func (*ForStmt) stmtNode()        {}
+func (*RangeStmt) stmtNode()      {}
 
 // ----------------------------------------------------------------------------
 // Declarations
@@ -752,6 +821,7 @@ type (
 		Name    *Ident        // local package name (including "."); or nil
 		Path    *BasicLit     // import path
 		Comment *CommentGroup // line comments; or nil
+		EndPos  token.Pos     // end of spec (overrides Path.Pos if nonzero)
 	}
 
 	// A ValueSpec node represents a constant or variable declaration
@@ -785,7 +855,13 @@ func (s *ImportSpec) Pos() token.Pos {
 func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() }
 func (s *TypeSpec) Pos() token.Pos  { return s.Name.Pos() }
 
-func (s *ImportSpec) End() token.Pos { return s.Path.End() }
+func (s *ImportSpec) End() token.Pos {
+	if s.EndPos != 0 {
+		return s.EndPos
+	}
+	return s.Path.End()
+}
+
 func (s *ValueSpec) End() token.Pos {
 	if n := len(s.Values); n > 0 {
 		return s.Values[n-1].End()
@@ -800,9 +876,9 @@ func (s *TypeSpec) End() token.Pos { return s.Type.End() }
 // specNode() ensures that only spec nodes can be
 // assigned to a Spec.
 //
-func (s *ImportSpec) specNode() {}
-func (s *ValueSpec) specNode()  {}
-func (s *TypeSpec) specNode()   {}
+func (*ImportSpec) specNode() {}
+func (*ValueSpec) specNode()  {}
+func (*TypeSpec) specNode()   {}
 
 // A declaration is represented by one of the following declaration nodes.
 //
@@ -868,9 +944,9 @@ func (d *FuncDecl) End() token.Pos {
 // declNode() ensures that only declaration nodes can be
 // assigned to a DeclNode.
 //
-func (d *BadDecl) declNode()  {}
-func (d *GenDecl) declNode()  {}
-func (d *FuncDecl) declNode() {}
+func (*BadDecl) declNode()  {}
+func (*GenDecl) declNode()  {}
+func (*FuncDecl) declNode() {}
 
 // ----------------------------------------------------------------------------
 // Files and packages
diff --git a/src/pkg/go/ast/filter.go b/src/pkg/go/ast/filter.go
index 1bd8990..4a89b89 100644
--- a/src/pkg/go/ast/filter.go
+++ b/src/pkg/go/ast/filter.go
@@ -4,7 +4,10 @@
 
 package ast
 
-import "go/token"
+import (
+	"go/token"
+	"sort"
+)
 
 // ----------------------------------------------------------------------------
 // Export filtering
@@ -18,14 +21,13 @@ func exportFilter(name string) bool {
 // only exported nodes remain: all top-level identifiers which are not exported
 // and their associated information (such as type, initial value, or function
 // body) are removed. Non-exported fields and methods of exported types are
-// stripped, and the function bodies of exported functions are set to nil.
-// The File.Comments list is not changed.
+// stripped. The File.Comments list is not changed.
 //
-// FileExports returns true if there are exported declarationa;
+// FileExports returns true if there are exported declarations;
 // it returns false otherwise.
 //
 func FileExports(src *File) bool {
-	return FilterFile(src, exportFilter)
+	return filterFile(src, exportFilter, true)
 }
 
 // PackageExports trims the AST for a Go package in place such that
@@ -36,7 +38,7 @@ func FileExports(src *File) bool {
 // it returns false otherwise.
 //
 func PackageExports(pkg *Package) bool {
-	return FilterPackage(pkg, exportFilter)
+	return filterPackage(pkg, exportFilter, true)
 }
 
 // ----------------------------------------------------------------------------
@@ -73,7 +75,7 @@ func fieldName(x Expr) *Ident {
 	return nil
 }
 
-func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
+func filterFieldList(fields *FieldList, filter Filter, export bool) (removedFields bool) {
 	if fields == nil {
 		return false
 	}
@@ -94,8 +96,8 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
 			keepField = len(f.Names) > 0
 		}
 		if keepField {
-			if filter == exportFilter {
-				filterType(f.Type, filter)
+			if export {
+				filterType(f.Type, filter, export)
 			}
 			list[j] = f
 			j++
@@ -108,84 +110,84 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
 	return
 }
 
-func filterParamList(fields *FieldList, filter Filter) bool {
+func filterParamList(fields *FieldList, filter Filter, export bool) bool {
 	if fields == nil {
 		return false
 	}
 	var b bool
 	for _, f := range fields.List {
-		if filterType(f.Type, filter) {
+		if filterType(f.Type, filter, export) {
 			b = true
 		}
 	}
 	return b
 }
 
-func filterType(typ Expr, f Filter) bool {
+func filterType(typ Expr, f Filter, export bool) bool {
 	switch t := typ.(type) {
 	case *Ident:
 		return f(t.Name)
 	case *ParenExpr:
-		return filterType(t.X, f)
+		return filterType(t.X, f, export)
 	case *ArrayType:
-		return filterType(t.Elt, f)
+		return filterType(t.Elt, f, export)
 	case *StructType:
-		if filterFieldList(t.Fields, f) {
+		if filterFieldList(t.Fields, f, export) {
 			t.Incomplete = true
 		}
 		return len(t.Fields.List) > 0
 	case *FuncType:
-		b1 := filterParamList(t.Params, f)
-		b2 := filterParamList(t.Results, f)
+		b1 := filterParamList(t.Params, f, export)
+		b2 := filterParamList(t.Results, f, export)
 		return b1 || b2
 	case *InterfaceType:
-		if filterFieldList(t.Methods, f) {
+		if filterFieldList(t.Methods, f, export) {
 			t.Incomplete = true
 		}
 		return len(t.Methods.List) > 0
 	case *MapType:
-		b1 := filterType(t.Key, f)
-		b2 := filterType(t.Value, f)
+		b1 := filterType(t.Key, f, export)
+		b2 := filterType(t.Value, f, export)
 		return b1 || b2
 	case *ChanType:
-		return filterType(t.Value, f)
+		return filterType(t.Value, f, export)
 	}
 	return false
 }
 
-func filterSpec(spec Spec, f Filter) bool {
+func filterSpec(spec Spec, f Filter, export bool) bool {
 	switch s := spec.(type) {
 	case *ValueSpec:
 		s.Names = filterIdentList(s.Names, f)
 		if len(s.Names) > 0 {
-			if f == exportFilter {
-				filterType(s.Type, f)
+			if export {
+				filterType(s.Type, f, export)
 			}
 			return true
 		}
 	case *TypeSpec:
 		if f(s.Name.Name) {
-			if f == exportFilter {
-				filterType(s.Type, f)
+			if export {
+				filterType(s.Type, f, export)
 			}
 			return true
 		}
-		if f != exportFilter {
+		if !export {
 			// For general filtering (not just exports),
 			// filter type even if name is not filtered
 			// out.
 			// If the type contains filtered elements,
 			// keep the declaration.
-			return filterType(s.Type, f)
+			return filterType(s.Type, f, export)
 		}
 	}
 	return false
 }
 
-func filterSpecList(list []Spec, f Filter) []Spec {
+func filterSpecList(list []Spec, f Filter, export bool) []Spec {
 	j := 0
 	for _, s := range list {
-		if filterSpec(s, f) {
+		if filterSpec(s, f, export) {
 			list[j] = s
 			j++
 		}
@@ -201,14 +203,15 @@ func filterSpecList(list []Spec, f Filter) []Spec {
 // filtering; it returns false otherwise.
 //
 func FilterDecl(decl Decl, f Filter) bool {
+	return filterDecl(decl, f, false)
+}
+
+func filterDecl(decl Decl, f Filter, export bool) bool {
 	switch d := decl.(type) {
 	case *GenDecl:
-		d.Specs = filterSpecList(d.Specs, f)
+		d.Specs = filterSpecList(d.Specs, f, export)
 		return len(d.Specs) > 0
 	case *FuncDecl:
-		if f == exportFilter {
-			d.Body = nil // strip body
-		}
 		return f(d.Name.Name)
 	}
 	return false
@@ -225,9 +228,13 @@ func FilterDecl(decl Decl, f Filter) bool {
 // left after filtering; it returns false otherwise.
 //
 func FilterFile(src *File, f Filter) bool {
+	return filterFile(src, f, false)
+}
+
+func filterFile(src *File, f Filter, export bool) bool {
 	j := 0
 	for _, d := range src.Decls {
-		if FilterDecl(d, f) {
+		if filterDecl(d, f, export) {
 			src.Decls[j] = d
 			j++
 		}
@@ -248,9 +255,13 @@ func FilterFile(src *File, f Filter) bool {
 // left after filtering; it returns false otherwise.
 //
 func FilterPackage(pkg *Package, f Filter) bool {
+	return filterPackage(pkg, f, false)
+}
+
+func filterPackage(pkg *Package, f Filter, export bool) bool {
 	hasDecls := false
 	for _, src := range pkg.Files {
-		if FilterFile(src, f) {
+		if filterFile(src, f, export) {
 			hasDecls = true
 		}
 	}
@@ -283,29 +294,35 @@ var separator = &Comment{noPos, "//"}
 //
 func MergePackageFiles(pkg *Package, mode MergeMode) *File {
 	// Count the number of package docs, comments and declarations across
-	// all package files.
+	// all package files. Also, compute sorted list of filenames, so that
+	// subsequent iterations can always iterate in the same order.
 	ndocs := 0
 	ncomments := 0
 	ndecls := 0
-	for _, f := range pkg.Files {
+	filenames := make([]string, len(pkg.Files))
+	i := 0
+	for filename, f := range pkg.Files {
+		filenames[i] = filename
+		i++
 		if f.Doc != nil {
 			ndocs += len(f.Doc.List) + 1 // +1 for separator
 		}
 		ncomments += len(f.Comments)
 		ndecls += len(f.Decls)
 	}
+	sort.Strings(filenames)
 
 	// Collect package comments from all package files into a single
-	// CommentGroup - the collected package documentation. The order
-	// is unspecified. In general there should be only one file with
-	// a package comment; but it's better to collect extra comments
-	// than drop them on the floor.
+	// CommentGroup - the collected package documentation. In general
+	// there should be only one file with a package comment; but it's
+	// better to collect extra comments than drop them on the floor.
 	var doc *CommentGroup
 	var pos token.Pos
 	if ndocs > 0 {
 		list := make([]*Comment, ndocs-1) // -1: no separator before first group
 		i := 0
-		for _, f := range pkg.Files {
+		for _, filename := range filenames {
+			f := pkg.Files[filename]
 			if f.Doc != nil {
 				if i > 0 {
 					// not the first group - add separator
@@ -334,7 +351,8 @@ func MergePackageFiles(pkg *Package, mode MergeMode) *File {
 		funcs := make(map[string]int) // map of global function name -> decls index
 		i := 0                        // current index
 		n := 0                        // number of filtered entries
-		for _, f := range pkg.Files {
+		for _, filename := range filenames {
+			f := pkg.Files[filename]
 			for _, d := range f.Decls {
 				if mode&FilterFuncDuplicates != 0 {
 					// A language entity may be declared multiple
@@ -390,7 +408,8 @@ func MergePackageFiles(pkg *Package, mode MergeMode) *File {
 	var imports []*ImportSpec
 	if mode&FilterImportDuplicates != 0 {
 		seen := make(map[string]bool)
-		for _, f := range pkg.Files {
+		for _, filename := range filenames {
+			f := pkg.Files[filename]
 			for _, imp := range f.Imports {
 				if path := imp.Path.Value; !seen[path] {
 					// TODO: consider handling cases where:
diff --git a/src/pkg/go/ast/import.go b/src/pkg/go/ast/import.go
new file mode 100644
index 0000000..2d4f69a
--- /dev/null
+++ b/src/pkg/go/ast/import.go
@@ -0,0 +1,134 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ast
+
+import (
+	"go/token"
+	"sort"
+	"strconv"
+)
+
+// SortImports sorts runs of consecutive import lines in import blocks in f.
+func SortImports(fset *token.FileSet, f *File) {
+	for _, d := range f.Decls {
+		d, ok := d.(*GenDecl)
+		if !ok || d.Tok != token.IMPORT {
+			// Not an import declaration, so we're done.
+			// Imports are always first.
+			break
+		}
+
+		if d.Lparen == token.NoPos {
+			// Not a block: sorted by default.
+			continue
+		}
+
+		// Identify and sort runs of specs on successive lines.
+		i := 0
+		for j, s := range d.Specs {
+			if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line {
+				// j begins a new run.  End this one.
+				sortSpecs(fset, f, d.Specs[i:j])
+				i = j
+			}
+		}
+		sortSpecs(fset, f, d.Specs[i:])
+	}
+}
+
+func importPath(s Spec) string {
+	t, err := strconv.Unquote(s.(*ImportSpec).Path.Value)
+	if err == nil {
+		return t
+	}
+	return ""
+}
+
+type posSpan struct {
+	Start token.Pos
+	End   token.Pos
+}
+
+func sortSpecs(fset *token.FileSet, f *File, specs []Spec) {
+	// Avoid work if already sorted (also catches < 2 entries).
+	sorted := true
+	for i, s := range specs {
+		if i > 0 && importPath(specs[i-1]) > importPath(s) {
+			sorted = false
+			break
+		}
+	}
+	if sorted {
+		return
+	}
+
+	// Record positions for specs.
+	pos := make([]posSpan, len(specs))
+	for i, s := range specs {
+		pos[i] = posSpan{s.Pos(), s.End()}
+	}
+
+	// Identify comments in this range.
+	// Any comment from pos[0].Start to the final line counts.
+	lastLine := fset.Position(pos[len(pos)-1].End).Line
+	cstart := len(f.Comments)
+	cend := len(f.Comments)
+	for i, g := range f.Comments {
+		if g.Pos() < pos[0].Start {
+			continue
+		}
+		if i < cstart {
+			cstart = i
+		}
+		if fset.Position(g.End()).Line > lastLine {
+			cend = i
+			break
+		}
+	}
+	comments := f.Comments[cstart:cend]
+
+	// Assign each comment to the import spec preceding it.
+	importComment := map[*ImportSpec][]*CommentGroup{}
+	specIndex := 0
+	for _, g := range comments {
+		for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() {
+			specIndex++
+		}
+		s := specs[specIndex].(*ImportSpec)
+		importComment[s] = append(importComment[s], g)
+	}
+
+	// Sort the import specs by import path.
+	// Reassign the import paths to have the same position sequence.
+	// Reassign each comment to abut the end of its spec.
+	// Sort the comments by new position.
+	sort.Sort(byImportPath(specs))
+	for i, s := range specs {
+		s := s.(*ImportSpec)
+		if s.Name != nil {
+			s.Name.NamePos = pos[i].Start
+		}
+		s.Path.ValuePos = pos[i].Start
+		s.EndPos = pos[i].End
+		for _, g := range importComment[s] {
+			for _, c := range g.List {
+				c.Slash = pos[i].End
+			}
+		}
+	}
+	sort.Sort(byCommentPos(comments))
+}
+
+type byImportPath []Spec // slice of *ImportSpec
+
+func (x byImportPath) Len() int           { return len(x) }
+func (x byImportPath) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byImportPath) Less(i, j int) bool { return importPath(x[i]) < importPath(x[j]) }
+
+type byCommentPos []*CommentGroup
+
+func (x byCommentPos) Len() int           { return len(x) }
+func (x byCommentPos) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }
diff --git a/src/pkg/go/ast/print.go b/src/pkg/go/ast/print.go
index 62a3048..f6c63c0 100644
--- a/src/pkg/go/ast/print.go
+++ b/src/pkg/go/ast/print.go
@@ -36,7 +36,7 @@ func NotNilFilter(_ string, v reflect.Value) bool {
 // struct fields for which f(fieldname, fieldvalue) is true are
 // are printed; all others are filtered from the output.
 //
-func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (n int, err os.Error) {
+func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (err error) {
 	// setup printer
 	p := printer{
 		output: w,
@@ -48,7 +48,6 @@ func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (n i
 
 	// install error handler
 	defer func() {
-		n = p.written
 		if e := recover(); e != nil {
 			err = e.(localError).err // re-panics if it's not a localError
 		}
@@ -67,24 +66,23 @@ func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (n i
 
 // Print prints x to standard output, skipping nil fields.
 // Print(fset, x) is the same as Fprint(os.Stdout, fset, x, NotNilFilter).
-func Print(fset *token.FileSet, x interface{}) (int, os.Error) {
+func Print(fset *token.FileSet, x interface{}) error {
 	return Fprint(os.Stdout, fset, x, NotNilFilter)
 }
 
 type printer struct {
-	output  io.Writer
-	fset    *token.FileSet
-	filter  FieldFilter
-	ptrmap  map[interface{}]int // *T -> line number
-	written int                 // number of bytes written to output
-	indent  int                 // current indentation level
-	last    byte                // the last byte processed by Write
-	line    int                 // current line number
+	output io.Writer
+	fset   *token.FileSet
+	filter FieldFilter
+	ptrmap map[interface{}]int // *T -> line number
+	indent int                 // current indentation level
+	last   byte                // the last byte processed by Write
+	line   int                 // current line number
 }
 
 var indent = []byte(".  ")
 
-func (p *printer) Write(data []byte) (n int, err os.Error) {
+func (p *printer) Write(data []byte) (n int, err error) {
 	var m int
 	for i, b := range data {
 		// invariant: data[0:n] has been written
@@ -114,17 +112,15 @@ func (p *printer) Write(data []byte) (n int, err os.Error) {
 	return
 }
 
-// localError wraps locally caught os.Errors so we can distinguish
+// localError wraps locally caught errors so we can distinguish
 // them from genuine panics which we don't want to return as errors.
 type localError struct {
-	err os.Error
+	err error
 }
 
 // printf is a convenience wrapper that takes care of print errors.
 func (p *printer) printf(format string, args ...interface{}) {
-	n, err := fmt.Fprintf(p, format, args...)
-	p.written += n
-	if err != nil {
+	if _, err := fmt.Fprintf(p, format, args...); err != nil {
 		panic(localError{err})
 	}
 }
@@ -149,7 +145,7 @@ func (p *printer) print(x reflect.Value) {
 		p.print(x.Elem())
 
 	case reflect.Map:
-		p.printf("%s (len = %d) {\n", x.Type().String(), x.Len())
+		p.printf("%s (len = %d) {\n", x.Type(), x.Len())
 		p.indent++
 		for _, key := range x.MapKeys() {
 			p.print(key)
@@ -178,7 +174,7 @@ func (p *printer) print(x reflect.Value) {
 			p.printf("%#q", s)
 			return
 		}
-		p.printf("%s (len = %d) {\n", x.Type().String(), x.Len())
+		p.printf("%s (len = %d) {\n", x.Type(), x.Len())
 		p.indent++
 		for i, n := 0, x.Len(); i < n; i++ {
 			p.printf("%d: ", i)
@@ -189,7 +185,7 @@ func (p *printer) print(x reflect.Value) {
 		p.printf("}")
 
 	case reflect.Struct:
-		p.printf("%s {\n", x.Type().String())
+		p.printf("%s {\n", x.Type())
 		p.indent++
 		t := x.Type()
 		for i, n := 0, t.NumField(); i < n; i++ {
diff --git a/src/pkg/go/ast/print_test.go b/src/pkg/go/ast/print_test.go
index f4e8f7a..71c028e 100644
--- a/src/pkg/go/ast/print_test.go
+++ b/src/pkg/go/ast/print_test.go
@@ -23,11 +23,10 @@ var tests = []struct {
 	{"foobar", "0  \"foobar\""},
 
 	// maps
-	{map[string]int{"a": 1, "b": 2},
-		`0  map[string] int (len = 2) {
+	{map[string]int{"a": 1},
+		`0  map[string]int (len = 1) {
 		1  .  "a": 1
-		2  .  "b": 2
-		3  }`},
+		2  }`},
 
 	// pointers
 	{new(int), "0  *0"},
@@ -41,10 +40,10 @@ var tests = []struct {
 		4  }`},
 
 	// structs
-	{struct{ x, y int }{42, 991},
-		`0  struct { x int; y int } {
-		1  .  x: 42
-		2  .  y: 991
+	{struct{ X, Y int }{42, 991},
+		`0  struct { X int; Y int } {
+		1  .  X: 42
+		2  .  Y: 991
 		3  }`},
 }
 
@@ -67,7 +66,7 @@ func TestPrint(t *testing.T) {
 	var buf bytes.Buffer
 	for _, test := range tests {
 		buf.Reset()
-		if _, err := Fprint(&buf, nil, test.x, nil); err != nil {
+		if err := Fprint(&buf, nil, test.x, nil); err != nil {
 			t.Errorf("Fprint failed: %s", err)
 		}
 		if s, ts := trim(buf.String()), trim(test.s); s != ts {
diff --git a/src/pkg/go/ast/resolve.go b/src/pkg/go/ast/resolve.go
index 3927a79..c7c8e7c 100644
--- a/src/pkg/go/ast/resolve.go
+++ b/src/pkg/go/ast/resolve.go
@@ -10,7 +10,6 @@ import (
 	"fmt"
 	"go/scanner"
 	"go/token"
-	"os"
 	"strconv"
 )
 
@@ -61,7 +60,7 @@ func resolve(scope *Scope, ident *Ident) bool {
 // Importer should load the package data for the given path into 
 // a new *Object (pkg), record pkg in the imports map, and then
 // return pkg.
-type Importer func(imports map[string]*Object, path string) (pkg *Object, err os.Error)
+type Importer func(imports map[string]*Object, path string) (pkg *Object, err error)
 
 // NewPackage creates a new Package node from a set of File nodes. It resolves
 // unresolved identifiers across files and updates each file's Unresolved list
@@ -72,7 +71,7 @@ type Importer func(imports map[string]*Object, path string) (pkg *Object, err os
 // different package names are reported and then ignored.
 // The result is a package node and a scanner.ErrorList if there were errors.
 //
-func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer, universe *Scope) (*Package, os.Error) {
+func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer, universe *Scope) (*Package, error) {
 	var p pkgBuilder
 	p.fset = fset
 
@@ -114,7 +113,7 @@ func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer,
 				importErrors = true
 				continue
 			}
-			path, _ := strconv.Unquote(string(spec.Path.Value))
+			path, _ := strconv.Unquote(spec.Path.Value)
 			pkg, err := importer(imports, path)
 			if err != nil {
 				p.errorf(spec.Path.Pos(), "could not import %s (%s)", path, err)
diff --git a/src/pkg/go/ast/scope.go b/src/pkg/go/ast/scope.go
index 92e3669..11e6b13 100644
--- a/src/pkg/go/ast/scope.go
+++ b/src/pkg/go/ast/scope.go
@@ -80,7 +80,7 @@ func (s *Scope) String() string {
 type Object struct {
 	Kind ObjKind
 	Name string      // declared name
-	Decl interface{} // corresponding Field, XxxSpec, FuncDecl, or LabeledStmt; or nil
+	Decl interface{} // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil
 	Data interface{} // object-specific data; or nil
 	Type interface{} // place holder for type information; may be nil
 }
@@ -125,6 +125,14 @@ func (obj *Object) Pos() token.Pos {
 		if d.Label.Name == name {
 			return d.Label.Pos()
 		}
+	case *AssignStmt:
+		for _, x := range d.Lhs {
+			if ident, isIdent := x.(*Ident); isIdent && ident.Name == name {
+				return ident.Pos()
+			}
+		}
+	case *Scope:
+		// predeclared object - nothing to do for now
 	}
 	return token.NoPos
 }
diff --git a/src/pkg/go/build/Makefile b/src/pkg/go/build/Makefile
index 349e00e..68c7317 100644
--- a/src/pkg/go/build/Makefile
+++ b/src/pkg/go/build/Makefile
@@ -11,12 +11,13 @@ GOFILES=\
 	path.go\
 	syslist.go\
 
-CLEANFILES+=syslist.go pkgtest/_obj cmdtest/_obj cgotest/_obj
+CLEANFILES+=pkgtest/_obj cmdtest/_obj cgotest/_obj
 
 include ../../../Make.pkg
 
 syslist.go: ../../../Make.inc Makefile
 	echo '// Generated automatically by make.' >$@
 	echo 'package build' >>$@
+	echo >>$@
 	echo 'const goosList = "$(GOOS_LIST)"' >>$@
 	echo 'const goarchList = "$(GOARCH_LIST)"' >>$@
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index 97f92bf..68e8d34 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -5,247 +5,11 @@
 // Package build provides tools for building Go packages.
 package build
 
-import (
-	"bytes"
-	"exec"
-	"fmt"
-	"os"
-	"path/filepath"
-	"regexp"
-	"runtime"
-	"strings"
-)
-
-// Build produces a build Script for the given package.
-func Build(tree *Tree, pkg string, info *DirInfo) (*Script, os.Error) {
-	s := &Script{}
-	b := &build{
-		script: s,
-		path:   filepath.Join(tree.SrcDir(), pkg),
-	}
-	b.obj = b.abs("_obj") + string(filepath.Separator)
-
-	b.goarch = runtime.GOARCH
-	if g := os.Getenv("GOARCH"); g != "" {
-		b.goarch = g
-	}
-	var err os.Error
-	b.arch, err = ArchChar(b.goarch)
-	if err != nil {
-		return nil, err
-	}
-
-	// add import object files to list of Inputs
-	for _, pkg := range info.Imports {
-		t, p, err := FindTree(pkg)
-		if err != nil && err != ErrNotFound {
-			// FindTree should always be able to suggest an import
-			// path and tree. The path must be malformed
-			// (for example, an absolute or relative path).
-			return nil, os.NewError("build: invalid import: " + pkg)
-		}
-		s.addInput(filepath.Join(t.PkgDir(), p+".a"))
-	}
-
-	// .go files to be built with gc
-	gofiles := b.abss(info.GoFiles...)
-	s.addInput(gofiles...)
-
-	var ofiles []string // object files to be linked or packed
-
-	// make build directory
-	b.mkdir(b.obj)
-	s.addIntermediate(b.obj)
-
-	// cgo
-	if len(info.CgoFiles) > 0 {
-		cgoFiles := b.abss(info.CgoFiles...)
-		s.addInput(cgoFiles...)
-		cgoCFiles := b.abss(info.CFiles...)
-		s.addInput(cgoCFiles...)
-		outGo, outObj := b.cgo(cgoFiles, cgoCFiles)
-		gofiles = append(gofiles, outGo...)
-		ofiles = append(ofiles, outObj...)
-		s.addIntermediate(outGo...)
-		s.addIntermediate(outObj...)
-	}
-
-	// compile
-	if len(gofiles) > 0 {
-		ofile := b.obj + "_go_." + b.arch
-		b.gc(ofile, gofiles...)
-		ofiles = append(ofiles, ofile)
-		s.addIntermediate(ofile)
-	}
-
-	// assemble
-	for _, sfile := range info.SFiles {
-		ofile := b.obj + sfile[:len(sfile)-1] + b.arch
-		sfile = b.abs(sfile)
-		s.addInput(sfile)
-		b.asm(ofile, sfile)
-		ofiles = append(ofiles, ofile)
-		s.addIntermediate(ofile)
-	}
-
-	if len(ofiles) == 0 {
-		return nil, os.NewError("make: no object files to build")
-	}
-
-	// choose target file
-	var targ string
-	if info.IsCommand() {
-		// use the last part of the import path as binary name
-		_, bin := filepath.Split(pkg)
-		if runtime.GOOS == "windows" {
-			bin += ".exe"
-		}
-		targ = filepath.Join(tree.BinDir(), bin)
-	} else {
-		targ = filepath.Join(tree.PkgDir(), pkg+".a")
-	}
-
-	// make target directory
-	targDir, _ := filepath.Split(targ)
-	b.mkdir(targDir)
-
-	// link binary or pack object
-	if info.IsCommand() {
-		b.ld(targ, ofiles...)
-	} else {
-		b.gopack(targ, ofiles...)
-	}
-	s.Output = append(s.Output, targ)
-
-	return b.script, nil
-}
-
-// A Script describes the build process for a Go package.
-// The Input, Intermediate, and Output fields are lists of absolute paths.
-type Script struct {
-	Cmd          []*Cmd
-	Input        []string
-	Intermediate []string
-	Output       []string
-}
-
-func (s *Script) addInput(file ...string) {
-	s.Input = append(s.Input, file...)
-}
-
-func (s *Script) addIntermediate(file ...string) {
-	s.Intermediate = append(s.Intermediate, file...)
-}
-
-// Run runs the Script's Cmds in order.
-func (s *Script) Run() os.Error {
-	for _, c := range s.Cmd {
-		if err := c.Run(); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// Stale returns true if the build's inputs are newer than its outputs.
-func (s *Script) Stale() bool {
-	var latest int64
-	// get latest mtime of outputs
-	for _, file := range s.Output {
-		fi, err := os.Stat(file)
-		if err != nil {
-			// any error reading output files means stale
-			return true
-		}
-		if m := fi.Mtime_ns; m > latest {
-			latest = m
-		}
-	}
-	for _, file := range s.Input {
-		fi, err := os.Stat(file)
-		if err != nil || fi.Mtime_ns > latest {
-			// any error reading input files means stale
-			// (attempt to rebuild to figure out why)
-			return true
-		}
-	}
-	return false
-}
-
-// Clean removes the Script's Intermediate files.
-// It tries to remove every file and returns the first error it encounters.
-func (s *Script) Clean() (err os.Error) {
-	// Reverse order so that directories get removed after the files they contain.
-	for i := len(s.Intermediate) - 1; i >= 0; i-- {
-		if e := os.Remove(s.Intermediate[i]); err == nil {
-			err = e
-		}
-	}
-	return
-}
-
-// Nuke removes the Script's Intermediate and Output files.
-// It tries to remove every file and returns the first error it encounters.
-func (s *Script) Nuke() (err os.Error) {
-	// Reverse order so that directories get removed after the files they contain.
-	for i := len(s.Output) - 1; i >= 0; i-- {
-		if e := os.Remove(s.Output[i]); err == nil {
-			err = e
-		}
-	}
-	if e := s.Clean(); err == nil {
-		err = e
-	}
-	return
-}
-
-// A Cmd describes an individual build command.
-type Cmd struct {
-	Args   []string // command-line
-	Stdout string   // write standard output to this file, "" is passthrough
-	Dir    string   // working directory
-	Env    []string // environment
-	Input  []string // file paths (dependencies)
-	Output []string // file paths
-}
-
-func (c *Cmd) String() string {
-	return strings.Join(c.Args, " ")
-}
-
-// Run executes the Cmd.
-func (c *Cmd) Run() os.Error {
-	if c.Args[0] == "mkdir" {
-		for _, p := range c.Output {
-			if err := os.MkdirAll(p, 0777); err != nil {
-				return fmt.Errorf("command %q: %v", c, err)
-			}
-		}
-		return nil
-	}
-	out := new(bytes.Buffer)
-	cmd := exec.Command(c.Args[0], c.Args[1:]...)
-	cmd.Dir = c.Dir
-	cmd.Env = c.Env
-	cmd.Stdout = out
-	cmd.Stderr = out
-	if c.Stdout != "" {
-		f, err := os.Create(c.Stdout)
-		if err != nil {
-			return err
-		}
-		defer f.Close()
-		cmd.Stdout = f
-	}
-	if err := cmd.Run(); err != nil {
-		return fmt.Errorf("command %q: %v\n%v", c, err, out)
-	}
-	return nil
-}
+import "errors"
 
 // ArchChar returns the architecture character for the given goarch.
 // For example, ArchChar("amd64") returns "6".
-func ArchChar(goarch string) (string, os.Error) {
+func ArchChar(goarch string) (string, error) {
 	switch goarch {
 	case "386":
 		return "8", nil
@@ -254,191 +18,5 @@ func ArchChar(goarch string) (string, os.Error) {
 	case "arm":
 		return "5", nil
 	}
-	return "", os.NewError("unsupported GOARCH " + goarch)
-}
-
-type build struct {
-	script *Script
-	path   string
-	obj    string
-	goarch string
-	arch   string
-}
-
-func (b *build) abs(file string) string {
-	if filepath.IsAbs(file) {
-		return file
-	}
-	return filepath.Join(b.path, file)
-}
-
-func (b *build) abss(file ...string) []string {
-	s := make([]string, len(file))
-	for i, f := range file {
-		s[i] = b.abs(f)
-	}
-	return s
-}
-
-func (b *build) add(c Cmd) {
-	b.script.Cmd = append(b.script.Cmd, &c)
-}
-
-func (b *build) mkdir(name string) {
-	b.add(Cmd{
-		Args:   []string{"mkdir", "-p", name},
-		Output: []string{name},
-	})
-}
-
-func (b *build) gc(ofile string, gofiles ...string) {
-	gc := b.arch + "g"
-	args := append([]string{gc, "-o", ofile}, gcImportArgs...)
-	args = append(args, gofiles...)
-	b.add(Cmd{
-		Args:   args,
-		Input:  gofiles,
-		Output: []string{ofile},
-	})
-}
-
-func (b *build) asm(ofile string, sfile string) {
-	asm := b.arch + "a"
-	b.add(Cmd{
-		Args:   []string{asm, "-o", ofile, sfile},
-		Input:  []string{sfile},
-		Output: []string{ofile},
-	})
-}
-
-func (b *build) ld(targ string, ofiles ...string) {
-	ld := b.arch + "l"
-	args := append([]string{ld, "-o", targ}, ldImportArgs...)
-	args = append(args, ofiles...)
-	b.add(Cmd{
-		Args:   args,
-		Input:  ofiles,
-		Output: []string{targ},
-	})
-}
-
-func (b *build) gopack(targ string, ofiles ...string) {
-	b.add(Cmd{
-		Args:   append([]string{"gopack", "grc", targ}, ofiles...),
-		Input:  ofiles,
-		Output: []string{targ},
-	})
-}
-
-func (b *build) cc(ofile string, cfiles ...string) {
-	cc := b.arch + "c"
-	dir := fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
-	inc := filepath.Join(runtime.GOROOT(), "pkg", dir)
-	args := []string{cc, "-FVw", "-I", inc, "-o", ofile}
-	b.add(Cmd{
-		Args:   append(args, cfiles...),
-		Input:  cfiles,
-		Output: []string{ofile},
-	})
-}
-
-func (b *build) gccCompile(ofile, cfile string) {
-	b.add(Cmd{
-		Args:   b.gccArgs("-o", ofile, "-c", cfile),
-		Input:  []string{cfile},
-		Output: []string{ofile},
-	})
-}
-
-func (b *build) gccLink(ofile string, ofiles ...string) {
-	b.add(Cmd{
-		Args:   append(b.gccArgs("-o", ofile), ofiles...),
-		Input:  ofiles,
-		Output: []string{ofile},
-	})
-}
-
-func (b *build) gccArgs(args ...string) []string {
-	// TODO(adg): HOST_CC
-	a := []string{"gcc", "-I", b.path, "-g", "-fPIC", "-O2"}
-	switch b.arch {
-	case "8":
-		a = append(a, "-m32")
-	case "6":
-		a = append(a, "-m64")
-	}
-	return append(a, args...)
-}
-
-var cgoRe = regexp.MustCompile(`[/\\:]`)
-
-func (b *build) cgo(cgofiles, cgocfiles []string) (outGo, outObj []string) {
-	// cgo
-	// TODO(adg): CGOPKGPATH
-	// TODO(adg): CGO_FLAGS
-	gofiles := []string{b.obj + "_cgo_gotypes.go"}
-	cfiles := []string{b.obj + "_cgo_main.c", b.obj + "_cgo_export.c"}
-	for _, fn := range cgofiles {
-		f := b.obj + cgoRe.ReplaceAllString(fn[:len(fn)-2], "_")
-		gofiles = append(gofiles, f+"cgo1.go")
-		cfiles = append(cfiles, f+"cgo2.c")
-	}
-	defunC := b.obj + "_cgo_defun.c"
-	output := append([]string{defunC}, cfiles...)
-	output = append(output, gofiles...)
-	b.add(Cmd{
-		Args:   append([]string{"cgo", "--"}, cgofiles...),
-		Dir:    b.path,
-		Env:    append(os.Environ(), "GOARCH="+b.goarch),
-		Input:  cgofiles,
-		Output: output,
-	})
-	outGo = append(outGo, gofiles...)
-	exportH := filepath.Join(b.path, "_cgo_export.h")
-	b.script.addIntermediate(defunC, exportH, b.obj+"_cgo_flags")
-	b.script.addIntermediate(cfiles...)
-
-	// cc _cgo_defun.c
-	defunObj := b.obj + "_cgo_defun." + b.arch
-	b.cc(defunObj, defunC)
-	outObj = append(outObj, defunObj)
-
-	// gcc
-	linkobj := make([]string, 0, len(cfiles))
-	for _, cfile := range cfiles {
-		ofile := cfile[:len(cfile)-1] + "o"
-		b.gccCompile(ofile, cfile)
-		linkobj = append(linkobj, ofile)
-		if !strings.HasSuffix(ofile, "_cgo_main.o") {
-			outObj = append(outObj, ofile)
-		} else {
-			b.script.addIntermediate(ofile)
-		}
-	}
-	for _, cfile := range cgocfiles {
-		ofile := b.obj + cgoRe.ReplaceAllString(cfile[:len(cfile)-1], "_") + "o"
-		b.gccCompile(ofile, cfile)
-		linkobj = append(linkobj, ofile)
-		outObj = append(outObj, ofile)
-	}
-	dynObj := b.obj + "_cgo_.o"
-	b.gccLink(dynObj, linkobj...)
-	b.script.addIntermediate(dynObj)
-
-	// cgo -dynimport
-	importC := b.obj + "_cgo_import.c"
-	b.add(Cmd{
-		Args:   []string{"cgo", "-dynimport", dynObj},
-		Stdout: importC,
-		Input:  []string{dynObj},
-		Output: []string{importC},
-	})
-	b.script.addIntermediate(importC)
-
-	// cc _cgo_import.ARCH
-	importObj := b.obj + "_cgo_import." + b.arch
-	b.cc(importObj, importC)
-	outObj = append(outObj, importObj)
-
-	return
+	return "", errors.New("unsupported GOARCH " + goarch)
 }
diff --git a/src/pkg/go/build/build_test.go b/src/pkg/go/build/build_test.go
index 68a4180..381e2b2 100644
--- a/src/pkg/go/build/build_test.go
+++ b/src/pkg/go/build/build_test.go
@@ -5,7 +5,6 @@
 package build
 
 import (
-	"exec"
 	"path/filepath"
 	"reflect"
 	"runtime"
@@ -28,7 +27,7 @@ var buildPkgs = []struct {
 			GoFiles:      []string{"pkgtest.go"},
 			SFiles:       []string{"sqrt_" + runtime.GOARCH + ".s"},
 			Package:      "pkgtest",
-			Imports:      []string{"os"},
+			Imports:      []string{"bytes"},
 			TestImports:  []string{"fmt", "pkgtest"},
 			TestGoFiles:  sortstr([]string{"sqrt_test.go", "sqrt_" + runtime.GOARCH + "_test.go"}),
 			XTestGoFiles: []string{"xsqrt_test.go"},
@@ -37,23 +36,31 @@ var buildPkgs = []struct {
 	{
 		"go/build/cmdtest",
 		&DirInfo{
-			GoFiles: []string{"main.go"},
-			Package: "main",
-			Imports: []string{"go/build/pkgtest"},
+			GoFiles:     []string{"main.go"},
+			Package:     "main",
+			Imports:     []string{"go/build/pkgtest"},
+			TestImports: []string{},
 		},
 	},
 	{
 		"go/build/cgotest",
 		&DirInfo{
-			CgoFiles: []string{"cgotest.go"},
-			CFiles:   []string{"cgotest.c"},
-			Imports:  []string{"C", "unsafe"},
-			Package:  "cgotest",
+			CgoFiles:    ifCgo([]string{"cgotest.go"}),
+			CFiles:      []string{"cgotest.c"},
+			HFiles:      []string{"cgotest.h"},
+			Imports:     []string{"C", "unsafe"},
+			TestImports: []string{},
+			Package:     "cgotest",
 		},
 	},
 }
 
-const cmdtestOutput = "3"
+func ifCgo(x []string) []string {
+	if DefaultContext.CgoEnabled {
+		return x
+	}
+	return nil
+}
 
 func TestBuild(t *testing.T) {
 	for _, tt := range buildPkgs {
@@ -68,35 +75,32 @@ func TestBuild(t *testing.T) {
 			t.Errorf("ScanDir(%#q) = %#v, want %#v\n", tt.dir, info, tt.info)
 			continue
 		}
+	}
+}
 
-		s, err := Build(tree, tt.dir, info)
-		if err != nil {
-			t.Errorf("Build(%#q): %v", tt.dir, err)
-			continue
+func TestMatch(t *testing.T) {
+	ctxt := DefaultContext
+	what := "default"
+	match := func(tag string) {
+		if !ctxt.match(tag) {
+			t.Errorf("%s context should match %s, does not", what, tag)
 		}
-
-		if err := s.Run(); err != nil {
-			t.Errorf("Run(%#q): %v", tt.dir, err)
-			continue
+	}
+	nomatch := func(tag string) {
+		if ctxt.match(tag) {
+			t.Errorf("%s context should NOT match %s, does", what, tag)
 		}
+	}
 
-		if tt.dir == "go/build/cmdtest" {
-			bin := s.Output[0]
-			b, err := exec.Command(bin).CombinedOutput()
-			if err != nil {
-				t.Errorf("exec %s: %v", bin, err)
-				continue
-			}
-			if string(b) != cmdtestOutput {
-				t.Errorf("cmdtest output: %s want: %s", b, cmdtestOutput)
-			}
-		}
+	match(runtime.GOOS + "," + runtime.GOARCH)
+	match(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
+	nomatch(runtime.GOOS + "," + runtime.GOARCH + ",foo")
 
-		// Deferred because cmdtest depends on pkgtest.
-		defer func(s *Script) {
-			if err := s.Nuke(); err != nil {
-				t.Errorf("nuking: %v", err)
-			}
-		}(s)
-	}
+	what = "modified"
+	ctxt.BuildTags = []string{"foo"}
+	match(runtime.GOOS + "," + runtime.GOARCH)
+	match(runtime.GOOS + "," + runtime.GOARCH + ",foo")
+	nomatch(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
+	match(runtime.GOOS + "," + runtime.GOARCH + ",!bar")
+	nomatch(runtime.GOOS + "," + runtime.GOARCH + ",bar")
 }
diff --git a/src/pkg/go/build/dir.go b/src/pkg/go/build/dir.go
index 3ee10ab..d49846f 100644
--- a/src/pkg/go/build/dir.go
+++ b/src/pkg/go/build/dir.go
@@ -6,9 +6,9 @@ package build
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"go/ast"
-	"go/doc"
 	"go/parser"
 	"go/token"
 	"io/ioutil"
@@ -25,9 +25,10 @@ import (
 
 // A Context specifies the supporting context for a build.
 type Context struct {
-	GOARCH string // target architecture
-	GOOS   string // target operating system
-	// TODO(rsc,adg): GOPATH
+	GOARCH     string   // target architecture
+	GOOS       string   // target operating system
+	CgoEnabled bool     // whether cgo can be used
+	BuildTags  []string // additional tags to recognize in +build lines
 
 	// By default, ScanDir uses the operating system's
 	// file system calls to read directories and files.
@@ -37,32 +38,32 @@ type Context struct {
 	// format of the strings dir and file: they can be
 	// slash-separated, backslash-separated, even URLs.
 
-	// ReadDir returns a slice of *os.FileInfo, sorted by Name,
+	// ReadDir returns a slice of os.FileInfo, sorted by Name,
 	// describing the content of the named directory.
 	// The dir argument is the argument to ScanDir.
 	// If ReadDir is nil, ScanDir uses io.ReadDir.
-	ReadDir func(dir string) (fi []*os.FileInfo, err os.Error)
+	ReadDir func(dir string) (fi []os.FileInfo, err error)
 
 	// ReadFile returns the content of the file named file
 	// in the directory named dir.  The dir argument is the
 	// argument to ScanDir, and the file argument is the
-	// Name field from an *os.FileInfo returned by ReadDir.
+	// Name field from an os.FileInfo returned by ReadDir.
 	// The returned path is the full name of the file, to be
 	// used in error messages.
 	//
 	// If ReadFile is nil, ScanDir uses filepath.Join(dir, file)
 	// as the path and ioutil.ReadFile to read the data.
-	ReadFile func(dir, file string) (path string, content []byte, err os.Error)
+	ReadFile func(dir, file string) (path string, content []byte, err error)
 }
 
-func (ctxt *Context) readDir(dir string) ([]*os.FileInfo, os.Error) {
+func (ctxt *Context) readDir(dir string) ([]os.FileInfo, error) {
 	if f := ctxt.ReadDir; f != nil {
 		return f(dir)
 	}
 	return ioutil.ReadDir(dir)
 }
 
-func (ctxt *Context) readFile(dir, file string) (string, []byte, os.Error) {
+func (ctxt *Context) readFile(dir, file string) (string, []byte, error) {
 	if f := ctxt.ReadFile; f != nil {
 		return f(dir, file)
 	}
@@ -74,9 +75,36 @@ func (ctxt *Context) readFile(dir, file string) (string, []byte, os.Error) {
 // The DefaultContext is the default Context for builds.
 // It uses the GOARCH and GOOS environment variables
 // if set, or else the compiled code's GOARCH and GOOS.
-var DefaultContext = Context{
-	GOARCH: envOr("GOARCH", runtime.GOARCH),
-	GOOS:   envOr("GOOS", runtime.GOOS),
+var DefaultContext Context = defaultContext()
+
+var cgoEnabled = map[string]bool{
+	"darwin/386":    true,
+	"darwin/amd64":  true,
+	"linux/386":     true,
+	"linux/amd64":   true,
+	"freebsd/386":   true,
+	"freebsd/amd64": true,
+	"windows/386":   true,
+	"windows/amd64": true,
+}
+
+func defaultContext() Context {
+	var c Context
+
+	c.GOARCH = envOr("GOARCH", runtime.GOARCH)
+	c.GOOS = envOr("GOOS", runtime.GOOS)
+
+	s := os.Getenv("CGO_ENABLED")
+	switch s {
+	case "1":
+		c.CgoEnabled = true
+	case "0":
+		c.CgoEnabled = false
+	default:
+		c.CgoEnabled = cgoEnabled[c.GOOS+"/"+c.GOARCH]
+	}
+
+	return c
 }
 
 func envOr(name, def string) string {
@@ -94,9 +122,10 @@ type DirInfo struct {
 	Imports        []string          // All packages imported by GoFiles
 
 	// Source files
-	GoFiles  []string // .go files in dir (excluding CgoFiles)
+	GoFiles  []string // .go files in dir (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+	HFiles   []string // .h files in dir
 	CFiles   []string // .c files in dir
-	SFiles   []string // .s files in dir
+	SFiles   []string // .s (and, when using cgo, .S files in dir)
 	CgoFiles []string // .go files that import "C"
 
 	// Cgo directives
@@ -116,43 +145,103 @@ func (d *DirInfo) IsCommand() bool {
 }
 
 // ScanDir calls DefaultContext.ScanDir.
-func ScanDir(dir string) (info *DirInfo, err os.Error) {
+func ScanDir(dir string) (info *DirInfo, err error) {
 	return DefaultContext.ScanDir(dir)
 }
 
-// ScanDir returns a structure with details about the Go content found
-// in the given directory. The file lists exclude:
+// TODO(rsc): Move this comment to a more appropriate place.
+
+// ScanDir returns a structure with details about the Go package
+// found in the given directory.
+//
+// Most .go, .c, .h, and .s files in the directory are considered part
+// of the package.  The exceptions are:
 //
-//	- files in package main (unless no other package is found)
-//	- files in package documentation
-//	- files ending in _test.go
+//	- .go files in package main (unless no other package is found)
+//	- .go files in package documentation
 //	- files starting with _ or .
+//	- files with build constraints not satisfied by the context
+//
+// Build Constraints
+//
+// A build constraint is a line comment beginning with the directive +build
+// that lists the conditions under which a file should be included in the package.
+// Constraints may appear in any kind of source file (not just Go), but
+// they must be appear near the top of the file, preceded
+// only by blank lines and other line comments.
+//
+// A build constraint is evaluated as the OR of space-separated options;
+// each option evaluates as the AND of its comma-separated terms;
+// and each term is an alphanumeric word or, preceded by !, its negation.
+// That is, the build constraint:
+//
+//	// +build linux,386 darwin,!cgo
+//
+// corresponds to the boolean formula:
+//
+//	(linux AND 386) OR (darwin AND (NOT cgo))
+//
+// During a particular build, the following words are satisfied:
+//
+//	- the target operating system, as spelled by runtime.GOOS
+//	- the target architecture, as spelled by runtime.GOARCH
+//	- "cgo", if ctxt.CgoEnabled is true
+//	- any additional words listed in ctxt.BuildTags
+//
+// If a file's name, after stripping the extension and a possible _test suffix,
+// matches *_GOOS, *_GOARCH, or *_GOOS_GOARCH for any known operating
+// system and architecture values, then the file is considered to have an implicit
+// build constraint requiring those terms.
+//
+// Examples
+//
+// To keep a file from being considered for the build:
+//
+//	// +build ignore
+//
+// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
+//
+// To build a file only when using cgo, and only on Linux and OS X:
+//
+//	// +build linux,cgo darwin,cgo
+// 
+// Such a file is usually paired with another file implementing the
+// default functionality for other systems, which in this case would
+// carry the constraint:
+//
+//	// +build !linux !darwin !cgo
 //
-func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err os.Error) {
+// Naming a file dns_windows.go will cause it to be included only when
+// building the package for Windows; similarly, math_386.s will be included
+// only when building the package for 32-bit x86.
+//
+func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err error) {
 	dirs, err := ctxt.readDir(dir)
 	if err != nil {
 		return nil, err
 	}
 
+	var Sfiles []string // files with ".S" (capital S)
 	var di DirInfo
 	imported := make(map[string]bool)
 	testImported := make(map[string]bool)
 	fset := token.NewFileSet()
 	for _, d := range dirs {
-		if !d.IsRegular() {
+		if d.IsDir() {
 			continue
 		}
-		if strings.HasPrefix(d.Name, "_") ||
-			strings.HasPrefix(d.Name, ".") {
+		name := d.Name()
+		if strings.HasPrefix(name, "_") ||
+			strings.HasPrefix(name, ".") {
 			continue
 		}
-		if !ctxt.goodOSArchFile(d.Name) {
+		if !ctxt.goodOSArchFile(name) {
 			continue
 		}
 
-		ext := path.Ext(d.Name)
+		ext := path.Ext(name)
 		switch ext {
-		case ".go", ".c", ".s":
+		case ".go", ".c", ".s", ".h", ".S":
 			// tentatively okay
 		default:
 			// skip
@@ -160,7 +249,7 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err os.Error) {
 		}
 
 		// Look for +build comments to accept or reject the file.
-		filename, data, err := ctxt.readFile(dir, d.Name)
+		filename, data, err := ctxt.readFile(dir, name)
 		if err != nil {
 			return nil, err
 		}
@@ -171,10 +260,16 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err os.Error) {
 		// Going to save the file.  For non-Go files, can stop here.
 		switch ext {
 		case ".c":
-			di.CFiles = append(di.CFiles, d.Name)
+			di.CFiles = append(di.CFiles, name)
+			continue
+		case ".h":
+			di.HFiles = append(di.HFiles, name)
 			continue
 		case ".s":
-			di.SFiles = append(di.SFiles, d.Name)
+			di.SFiles = append(di.SFiles, name)
+			continue
+		case ".S":
+			Sfiles = append(Sfiles, name)
 			continue
 		}
 
@@ -191,7 +286,7 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err os.Error) {
 			continue
 		}
 
-		isTest := strings.HasSuffix(d.Name, "_test.go")
+		isTest := strings.HasSuffix(name, "_test.go")
 		if isTest && strings.HasSuffix(pkg, "_test") {
 			pkg = pkg[:len(pkg)-len("_test")]
 		}
@@ -254,15 +349,17 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err os.Error) {
 			}
 		}
 		if isCgo {
-			di.CgoFiles = append(di.CgoFiles, d.Name)
+			if ctxt.CgoEnabled {
+				di.CgoFiles = append(di.CgoFiles, name)
+			}
 		} else if isTest {
 			if pkg == string(pf.Name.Name) {
-				di.TestGoFiles = append(di.TestGoFiles, d.Name)
+				di.TestGoFiles = append(di.TestGoFiles, name)
 			} else {
-				di.XTestGoFiles = append(di.XTestGoFiles, d.Name)
+				di.XTestGoFiles = append(di.XTestGoFiles, name)
 			}
 		} else {
-			di.GoFiles = append(di.GoFiles, d.Name)
+			di.GoFiles = append(di.GoFiles, name)
 		}
 	}
 	if di.Package == "" {
@@ -280,6 +377,15 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err os.Error) {
 		di.TestImports[i] = p
 		i++
 	}
+
+	// add the .S files only if we are using cgo
+	// (which means gcc will compile them).
+	// The standard assemblers expect .s files.
+	if len(di.CgoFiles) > 0 {
+		di.SFiles = append(di.SFiles, Sfiles...)
+		sort.Strings(di.SFiles)
+	}
+
 	// File name lists are sorted because ReadDir sorts.
 	sort.Strings(di.Imports)
 	sort.Strings(di.TestImports)
@@ -287,7 +393,6 @@ func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err os.Error) {
 }
 
 var slashslash = []byte("//")
-var plusBuild = []byte("+build")
 
 // shouldBuild reports whether it is okay to use this file,
 // The rule is that in the file's leading run of // comments
@@ -343,7 +448,7 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
 				if f[0] == "+build" {
 					ok := false
 					for _, tok := range f[1:] {
-						if ctxt.matchOSArch(tok) {
+						if ctxt.match(tok) {
 							ok = true
 							break
 						}
@@ -364,8 +469,8 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
 //
 // TODO(rsc): This duplicates code in cgo.
 // Once the dust settles, remove this code from cgo.
-func (ctxt *Context) saveCgo(filename string, di *DirInfo, cg *ast.CommentGroup) os.Error {
-	text := doc.CommentText(cg)
+func (ctxt *Context) saveCgo(filename string, di *DirInfo, cg *ast.CommentGroup) error {
+	text := cg.Text()
 	for _, line := range strings.Split(text, "\n") {
 		orig := line
 
@@ -395,7 +500,7 @@ func (ctxt *Context) saveCgo(filename string, di *DirInfo, cg *ast.CommentGroup)
 		if len(cond) > 0 {
 			ok := false
 			for _, c := range cond {
-				if ctxt.matchOSArch(c) {
+				if ctxt.match(c) {
 					ok = true
 					break
 				}
@@ -429,7 +534,7 @@ func (ctxt *Context) saveCgo(filename string, di *DirInfo, cg *ast.CommentGroup)
 	return nil
 }
 
-var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:")
 
 func safeName(s string) bool {
 	if s == "" {
@@ -459,12 +564,12 @@ func safeName(s string) bool {
 //
 //     []string{"a", "b:c d", "ef", `g"`}
 //
-func splitQuoted(s string) (r []string, err os.Error) {
+func splitQuoted(s string) (r []string, err error) {
 	var args []string
-	arg := make([]int, len(s))
+	arg := make([]rune, len(s))
 	escaped := false
 	quoted := false
-	quote := 0
+	quote := '\x00'
 	i := 0
 	for _, rune := range s {
 		switch {
@@ -473,9 +578,9 @@ func splitQuoted(s string) (r []string, err os.Error) {
 		case rune == '\\':
 			escaped = true
 			continue
-		case quote != 0:
+		case quote != '\x00':
 			if rune == quote {
-				quote = 0
+				quote = '\x00'
 				continue
 			}
 		case rune == '"' || rune == '\'':
@@ -497,25 +602,62 @@ func splitQuoted(s string) (r []string, err os.Error) {
 		args = append(args, string(arg[:i]))
 	}
 	if quote != 0 {
-		err = os.NewError("unclosed quote")
+		err = errors.New("unclosed quote")
 	} else if escaped {
-		err = os.NewError("unfinished escaping")
+		err = errors.New("unfinished escaping")
 	}
 	return args, err
 }
 
-// matchOSArch returns true if the name is one of:
+// match returns true if the name is one of:
 //
 //	$GOOS
 //	$GOARCH
-//	$GOOS/$GOARCH
+//	cgo (if cgo is enabled)
+//	!cgo (if cgo is disabled)
+//	tag (if tag is listed in ctxt.BuildTags)
+//	!tag (if tag is not listed in ctxt.BuildTags)
+//	a slash-separated list of any of these
 //
-func (ctxt *Context) matchOSArch(name string) bool {
+func (ctxt *Context) match(name string) bool {
+	if name == "" {
+		return false
+	}
+	if i := strings.Index(name, ","); i >= 0 {
+		// comma-separated list
+		return ctxt.match(name[:i]) && ctxt.match(name[i+1:])
+	}
+	if strings.HasPrefix(name, "!!") { // bad syntax, reject always
+		return false
+	}
+	if strings.HasPrefix(name, "!") { // negation
+		return !ctxt.match(name[1:])
+	}
+
+	// Tags must be letters, digits, underscores.
+	// Unlike in Go identifiers, all digits is fine (e.g., "386").
+	for _, c := range name {
+		if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
+			return false
+		}
+	}
+
+	// special tags
+	if ctxt.CgoEnabled && name == "cgo" {
+		return true
+	}
 	if name == ctxt.GOOS || name == ctxt.GOARCH {
 		return true
 	}
-	i := strings.Index(name, "/")
-	return i >= 0 && name[:i] == ctxt.GOOS && name[i+1:] == ctxt.GOARCH
+
+	// other tags
+	for _, tag := range ctxt.BuildTags {
+		if tag == name {
+			return true
+		}
+	}
+
+	return false
 }
 
 // goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
diff --git a/src/pkg/go/build/path.go b/src/pkg/go/build/path.go
index e39b5f8..7e931fa 100644
--- a/src/pkg/go/build/path.go
+++ b/src/pkg/go/build/path.go
@@ -5,8 +5,8 @@
 package build
 
 import (
+	"errors"
 	"fmt"
-	"log"
 	"os"
 	"path/filepath"
 	"runtime"
@@ -21,9 +21,9 @@ type Tree struct {
 	Goroot bool
 }
 
-func newTree(p string) (*Tree, os.Error) {
+func newTree(p string) (*Tree, error) {
 	if !filepath.IsAbs(p) {
-		return nil, os.NewError("must be absolute")
+		return nil, errors.New("must be absolute")
 	}
 	ep, err := filepath.EvalSymlinks(p)
 	if err != nil {
@@ -56,7 +56,7 @@ func (t *Tree) PkgDir() string {
 func (t *Tree) BinDir() string {
 	if t.Goroot {
 		if gobin := os.Getenv("GOBIN"); gobin != "" {
-			return gobin
+			return filepath.Clean(gobin)
 		}
 	}
 	return filepath.Join(t.Path, "bin")
@@ -69,7 +69,7 @@ func (t *Tree) HasSrc(pkg string) bool {
 	if err != nil {
 		return false
 	}
-	return fi.IsDirectory()
+	return fi.IsDir()
 }
 
 // HasPkg returns whether the given package's
@@ -79,18 +79,17 @@ func (t *Tree) HasPkg(pkg string) bool {
 	if err != nil {
 		return false
 	}
-	return fi.IsRegular()
-	// TODO(adg): check object version is consistent
+	return !fi.IsDir()
 }
 
 var (
-	ErrNotFound     = os.NewError("go/build: package could not be found locally")
-	ErrTreeNotFound = os.NewError("go/build: no valid GOROOT or GOPATH could be found")
+	ErrNotFound     = errors.New("package could not be found locally")
+	ErrTreeNotFound = errors.New("no valid GOROOT or GOPATH could be found")
 )
 
 // FindTree takes an import or filesystem path and returns the
 // tree where the package source should be and the package import path.
-func FindTree(path string) (tree *Tree, pkg string, err os.Error) {
+func FindTree(path string) (tree *Tree, pkg string, err error) {
 	if isLocalPath(path) {
 		if path, err = filepath.Abs(path); err != nil {
 			return
@@ -104,14 +103,14 @@ func FindTree(path string) (tree *Tree, pkg string, err os.Error) {
 				continue
 			}
 			tree = t
-			pkg = path[len(tpath):]
+			pkg = filepath.ToSlash(path[len(tpath):])
 			return
 		}
 		err = fmt.Errorf("path %q not inside a GOPATH", path)
 		return
 	}
 	tree = defaultTree
-	pkg = path
+	pkg = filepath.ToSlash(path)
 	for _, t := range Path {
 		if t.HasSrc(pkg) {
 			tree = t
@@ -149,9 +148,7 @@ var (
 func init() {
 	root := runtime.GOROOT()
 	t, err := newTree(root)
-	if err != nil {
-		log.Printf("go/build: invalid GOROOT %q: %v", root, err)
-	} else {
+	if err == nil {
 		t.Goroot = true
 		Path = []*Tree{t}
 	}
@@ -162,9 +159,9 @@ func init() {
 		}
 		t, err := newTree(p)
 		if err != nil {
-			log.Printf("go/build: invalid GOPATH %q: %v", p, err)
 			continue
 		}
+
 		Path = append(Path, t)
 		gcImportArgs = append(gcImportArgs, "-I", t.PkgDir())
 		ldImportArgs = append(ldImportArgs, "-L", t.PkgDir())
diff --git a/src/pkg/go/build/pkgtest/pkgtest.go b/src/pkg/go/build/pkgtest/pkgtest.go
index 03ebb98..08eea1e 100644
--- a/src/pkg/go/build/pkgtest/pkgtest.go
+++ b/src/pkg/go/build/pkgtest/pkgtest.go
@@ -4,9 +4,9 @@
 
 package pkgtest
 
-import "os"
+import "bytes"
 
-func Foo() os.Error {
+func Foo() *bytes.Buffer {
 	return nil
 }
 
diff --git a/src/pkg/go/build/pkgtest/sqrt_test.go b/src/pkg/go/build/pkgtest/sqrt_test.go
index 95fb625..ee9fd5d 100644
--- a/src/pkg/go/build/pkgtest/sqrt_test.go
+++ b/src/pkg/go/build/pkgtest/sqrt_test.go
@@ -1,3 +1,7 @@
+// Copyright 2011 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 pkgtest
 
 import "fmt"
diff --git a/src/pkg/go/build/pkgtest/xsqrt_test.go b/src/pkg/go/build/pkgtest/xsqrt_test.go
index 77e903d..3898d1d 100644
--- a/src/pkg/go/build/pkgtest/xsqrt_test.go
+++ b/src/pkg/go/build/pkgtest/xsqrt_test.go
@@ -1,3 +1,7 @@
+// Copyright 2011 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 pkgtest_test
 
 import "pkgtest"
diff --git a/src/pkg/go/build/syslist.go b/src/pkg/go/build/syslist.go
new file mode 100644
index 0000000..0ee9821
--- /dev/null
+++ b/src/pkg/go/build/syslist.go
@@ -0,0 +1,5 @@
+// Generated automatically by make.
+package build
+
+const goosList = "darwin freebsd linux netbsd openbsd plan9 windows "
+const goarchList = "386 amd64 arm "
diff --git a/src/pkg/go/doc/Makefile b/src/pkg/go/doc/Makefile
index a5152c7..ac2eeb9 100644
--- a/src/pkg/go/doc/Makefile
+++ b/src/pkg/go/doc/Makefile
@@ -8,5 +8,15 @@ TARG=go/doc
 GOFILES=\
 	comment.go\
 	doc.go\
+	example.go\
+	exports.go\
+	filter.go\
+	reader.go\
 
 include ../../../Make.pkg
+
+# Script to test heading detection heuristic
+CLEANFILES+=headscan
+headscan: headscan.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) headscan.go
+	$(LD) -o headscan headscan.$(O)
diff --git a/src/pkg/go/doc/comment.go b/src/pkg/go/doc/comment.go
index e198922..d73b131 100644
--- a/src/pkg/go/doc/comment.go
+++ b/src/pkg/go/doc/comment.go
@@ -7,114 +7,14 @@
 package doc
 
 import (
-	"go/ast"
 	"io"
 	"regexp"
 	"strings"
-	"template" // for HTMLEscape
+	"text/template" // for HTMLEscape
+	"unicode"
+	"unicode/utf8"
 )
 
-func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' }
-
-func stripTrailingWhitespace(s string) string {
-	i := len(s)
-	for i > 0 && isWhitespace(s[i-1]) {
-		i--
-	}
-	return s[0:i]
-}
-
-// CommentText returns the text of comment,
-// with the comment markers - //, /*, and */ - removed.
-func CommentText(comment *ast.CommentGroup) string {
-	if comment == nil {
-		return ""
-	}
-	comments := make([]string, len(comment.List))
-	for i, c := range comment.List {
-		comments[i] = string(c.Text)
-	}
-
-	lines := make([]string, 0, 10) // most comments are less than 10 lines
-	for _, c := range comments {
-		// Remove comment markers.
-		// The parser has given us exactly the comment text.
-		switch c[1] {
-		case '/':
-			//-style comment
-			c = c[2:]
-			// Remove leading space after //, if there is one.
-			// TODO(gri) This appears to be necessary in isolated
-			//           cases (bignum.RatFromString) - why?
-			if len(c) > 0 && c[0] == ' ' {
-				c = c[1:]
-			}
-		case '*':
-			/*-style comment */
-			c = c[2 : len(c)-2]
-		}
-
-		// Split on newlines.
-		cl := strings.Split(c, "\n")
-
-		// Walk lines, stripping trailing white space and adding to list.
-		for _, l := range cl {
-			lines = append(lines, stripTrailingWhitespace(l))
-		}
-	}
-
-	// Remove leading blank lines; convert runs of
-	// interior blank lines to a single blank line.
-	n := 0
-	for _, line := range lines {
-		if line != "" || n > 0 && lines[n-1] != "" {
-			lines[n] = line
-			n++
-		}
-	}
-	lines = lines[0:n]
-
-	// Add final "" entry to get trailing newline from Join.
-	if n > 0 && lines[n-1] != "" {
-		lines = append(lines, "")
-	}
-
-	return strings.Join(lines, "\n")
-}
-
-// Split bytes into lines.
-func split(text []byte) [][]byte {
-	// count lines
-	n := 0
-	last := 0
-	for i, c := range text {
-		if c == '\n' {
-			last = i + 1
-			n++
-		}
-	}
-	if last < len(text) {
-		n++
-	}
-
-	// split
-	out := make([][]byte, n)
-	last = 0
-	n = 0
-	for i, c := range text {
-		if c == '\n' {
-			out[n] = text[last : i+1]
-			last = i + 1
-			n++
-		}
-	}
-	if last < len(text) {
-		out[n] = text[last:]
-	}
-
-	return out
-}
-
 var (
 	ldquo = []byte("“")
 	rdquo = []byte("”")
@@ -122,13 +22,13 @@ var (
 
 // Escape comment text for HTML. If nice is set,
 // also turn `` into “ and '' into ”.
-func commentEscape(w io.Writer, s []byte, nice bool) {
+func commentEscape(w io.Writer, text string, nice bool) {
 	last := 0
 	if nice {
-		for i := 0; i < len(s)-1; i++ {
-			ch := s[i]
-			if ch == s[i+1] && (ch == '`' || ch == '\'') {
-				template.HTMLEscape(w, s[last:i])
+		for i := 0; i < len(text)-1; i++ {
+			ch := text[i]
+			if ch == text[i+1] && (ch == '`' || ch == '\'') {
+				template.HTMLEscape(w, []byte(text[last:i]))
 				last = i + 2
 				switch ch {
 				case '`':
@@ -140,7 +40,7 @@ func commentEscape(w io.Writer, s []byte, nice bool) {
 			}
 		}
 	}
-	template.HTMLEscape(w, s[last:])
+	template.HTMLEscape(w, []byte(text[last:]))
 }
 
 const (
@@ -168,6 +68,9 @@ var (
 	html_endp   = []byte("</p>\n")
 	html_pre    = []byte("<pre>")
 	html_endpre = []byte("</pre>\n")
+	html_h      = []byte(`<h3 id="`)
+	html_hq     = []byte(`">`)
+	html_endh   = []byte("</h3>\n")
 )
 
 // Emphasize and escape a line of text for HTML. URLs are converted into links;
@@ -178,9 +81,9 @@ var (
 // and the word is converted into a link. If nice is set, the remaining text's
 // appearance is improved where it makes sense (e.g., `` is turned into “
 // and '' into ”).
-func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) {
+func emphasize(w io.Writer, line string, words map[string]string, nice bool) {
 	for {
-		m := matchRx.FindSubmatchIndex(line)
+		m := matchRx.FindStringSubmatchIndex(line)
 		if m == nil {
 			break
 		}
@@ -228,7 +131,7 @@ func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) {
 	commentEscape(w, line, nice)
 }
 
-func indentLen(s []byte) int {
+func indentLen(s string) int {
 	i := 0
 	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
 		i++
@@ -236,9 +139,11 @@ func indentLen(s []byte) int {
 	return i
 }
 
-func isBlank(s []byte) bool { return len(s) == 0 || (len(s) == 1 && s[0] == '\n') }
+func isBlank(s string) bool {
+	return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
+}
 
-func commonPrefix(a, b []byte) []byte {
+func commonPrefix(a, b string) string {
 	i := 0
 	for i < len(a) && i < len(b) && a[i] == b[i] {
 		i++
@@ -246,7 +151,7 @@ func commonPrefix(a, b []byte) []byte {
 	return a[0:i]
 }
 
-func unindent(block [][]byte) {
+func unindent(block []string) {
 	if len(block) == 0 {
 		return
 	}
@@ -268,7 +173,66 @@ func unindent(block [][]byte) {
 	}
 }
 
-// Convert comment text to formatted HTML.
+// heading returns the trimmed line if it passes as a section heading;
+// otherwise it returns the empty string. 
+func heading(line string) string {
+	line = strings.TrimSpace(line)
+	if len(line) == 0 {
+		return ""
+	}
+
+	// a heading must start with an uppercase letter
+	r, _ := utf8.DecodeRuneInString(line)
+	if !unicode.IsLetter(r) || !unicode.IsUpper(r) {
+		return ""
+	}
+
+	// it must end in a letter or digit:
+	r, _ = utf8.DecodeLastRuneInString(line)
+	if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
+		return ""
+	}
+
+	// exclude lines with illegal characters
+	if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
+		return ""
+	}
+
+	// allow "'" for possessive "'s" only
+	for b := line; ; {
+		i := strings.IndexRune(b, '\'')
+		if i < 0 {
+			break
+		}
+		if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
+			return "" // not followed by "s "
+		}
+		b = b[i+2:]
+	}
+
+	return line
+}
+
+type op int
+
+const (
+	opPara op = iota
+	opHead
+	opPre
+)
+
+type block struct {
+	op    op
+	lines []string
+}
+
+var nonAlphaNumRx = regexp.MustCompile(`[^a-zA-Z0-9]`)
+
+func anchorID(line string) string {
+	return nonAlphaNumRx.ReplaceAllString(line, "_")
+}
+
+// ToHTML converts comment text to formatted HTML.
 // The comment was prepared by DocReader,
 // so it is known not to have leading, trailing blank lines
 // nor to have trailing spaces at the end of lines.
@@ -276,6 +240,7 @@ func unindent(block [][]byte) {
 //
 // Turn each run of multiple \n into </p><p>.
 // Turn each run of indented lines into a <pre> block without indent.
+// Enclose headings with header tags.
 //
 // URLs in the comment text are converted into links; if the URL also appears
 // in the words map, the link is taken from the map (if the corresponding map
@@ -284,23 +249,57 @@ func unindent(block [][]byte) {
 // Go identifiers that appear in the words map are italicized; if the corresponding
 // map value is not the empty string, it is considered a URL and the word is converted
 // into a link.
-func ToHTML(w io.Writer, s []byte, words map[string]string) {
-	inpara := false
-
-	close := func() {
-		if inpara {
+func ToHTML(w io.Writer, text string, words map[string]string) {
+	for _, b := range blocks(text) {
+		switch b.op {
+		case opPara:
+			w.Write(html_p)
+			for _, line := range b.lines {
+				emphasize(w, line, words, true)
+			}
 			w.Write(html_endp)
-			inpara = false
+		case opHead:
+			w.Write(html_h)
+			id := ""
+			for _, line := range b.lines {
+				if id == "" {
+					id = anchorID(line)
+					w.Write([]byte(id))
+					w.Write(html_hq)
+				}
+				commentEscape(w, line, true)
+			}
+			if id == "" {
+				w.Write(html_hq)
+			}
+			w.Write(html_endh)
+		case opPre:
+			w.Write(html_pre)
+			for _, line := range b.lines {
+				emphasize(w, line, nil, false)
+			}
+			w.Write(html_endpre)
 		}
 	}
-	open := func() {
-		if !inpara {
-			w.Write(html_p)
-			inpara = true
+}
+
+func blocks(text string) []block {
+	var (
+		out  []block
+		para []string
+
+		lastWasBlank   = false
+		lastWasHeading = false
+	)
+
+	close := func() {
+		if para != nil {
+			out = append(out, block{opPara, para})
+			para = nil
 		}
 	}
 
-	lines := split(s)
+	lines := strings.SplitAfter(text, "\n")
 	unindent(lines)
 	for i := 0; i < len(lines); {
 		line := lines[i]
@@ -308,6 +307,7 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) {
 			// close paragraph
 			close()
 			i++
+			lastWasBlank = true
 			continue
 		}
 		if indentLen(line) > 0 {
@@ -323,23 +323,119 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) {
 			for j > i && isBlank(lines[j-1]) {
 				j--
 			}
-			block := lines[i:j]
+			pre := lines[i:j]
 			i = j
 
-			unindent(block)
+			unindent(pre)
 
 			// put those lines in a pre block
-			w.Write(html_pre)
-			for _, line := range block {
-				emphasize(w, line, nil, false) // no nice text formatting
-			}
-			w.Write(html_endpre)
+			out = append(out, block{opPre, pre})
+			lastWasHeading = false
 			continue
 		}
+
+		if lastWasBlank && !lastWasHeading && i+2 < len(lines) &&
+			isBlank(lines[i+1]) && !isBlank(lines[i+2]) && indentLen(lines[i+2]) == 0 {
+			// current line is non-blank, sourounded by blank lines
+			// and the next non-blank line is not indented: this
+			// might be a heading.
+			if head := heading(line); head != "" {
+				close()
+				out = append(out, block{opHead, []string{head}})
+				i += 2
+				lastWasHeading = true
+				continue
+			}
+		}
+
 		// open paragraph
-		open()
-		emphasize(w, lines[i], words, true) // nice text formatting
+		lastWasBlank = false
+		lastWasHeading = false
+		para = append(para, lines[i])
 		i++
 	}
 	close()
+
+	return out
+}
+
+// ToText prepares comment text for presentation in textual output.
+// It wraps paragraphs of text to width or fewer Unicode code points
+// and then prefixes each line with the indent.  In preformatted sections
+// (such as program text), it prefixes each non-blank line with preIndent.
+func ToText(w io.Writer, text string, indent, preIndent string, width int) {
+	l := lineWrapper{
+		out:    w,
+		width:  width,
+		indent: indent,
+	}
+	for _, b := range blocks(text) {
+		switch b.op {
+		case opPara:
+			// l.write will add leading newline if required
+			for _, line := range b.lines {
+				l.write(line)
+			}
+			l.flush()
+		case opHead:
+			w.Write(nl)
+			for _, line := range b.lines {
+				l.write(line + "\n")
+			}
+			l.flush()
+		case opPre:
+			w.Write(nl)
+			for _, line := range b.lines {
+				if !isBlank(line) {
+					w.Write([]byte(preIndent))
+					w.Write([]byte(line))
+				}
+			}
+		}
+	}
+}
+
+type lineWrapper struct {
+	out       io.Writer
+	printed   bool
+	width     int
+	indent    string
+	n         int
+	pendSpace int
+}
+
+var nl = []byte("\n")
+var space = []byte(" ")
+
+func (l *lineWrapper) write(text string) {
+	if l.n == 0 && l.printed {
+		l.out.Write(nl) // blank line before new paragraph
+	}
+	l.printed = true
+
+	for _, f := range strings.Fields(text) {
+		w := utf8.RuneCountInString(f)
+		// wrap if line is too long
+		if l.n > 0 && l.n+l.pendSpace+w > l.width {
+			l.out.Write(nl)
+			l.n = 0
+			l.pendSpace = 0
+		}
+		if l.n == 0 {
+			l.out.Write([]byte(l.indent))
+		}
+		l.out.Write(space[:l.pendSpace])
+		l.out.Write([]byte(f))
+		l.n += l.pendSpace + w
+		l.pendSpace = 1
+	}
+}
+
+func (l *lineWrapper) flush() {
+	if l.n == 0 {
+		return
+	}
+	l.out.Write(nl)
+	l.pendSpace = 0
+	l.n = 0
 }
diff --git a/src/pkg/go/doc/comment_test.go b/src/pkg/go/doc/comment_test.go
new file mode 100644
index 0000000..e8d7f2e
--- /dev/null
+++ b/src/pkg/go/doc/comment_test.go
@@ -0,0 +1,83 @@
+// Copyright 2011 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 doc
+
+import (
+	"reflect"
+	"testing"
+)
+
+var headingTests = []struct {
+	line string
+	ok   bool
+}{
+	{"Section", true},
+	{"A typical usage", true},
+	{"ΔΛΞ is Greek", true},
+	{"Foo 42", true},
+	{"", false},
+	{"section", false},
+	{"A typical usage:", false},
+	{"This code:", false},
+	{"δ is Greek", false},
+	{"Foo §", false},
+	{"Fermat's Last Sentence", true},
+	{"Fermat's", true},
+	{"'sX", false},
+	{"Ted 'Too' Bar", false},
+	{"Use n+m", false},
+	{"Scanning:", false},
+	{"N:M", false},
+}
+
+func TestIsHeading(t *testing.T) {
+	for _, tt := range headingTests {
+		if h := heading(tt.line); (len(h) > 0) != tt.ok {
+			t.Errorf("isHeading(%q) = %v, want %v", tt.line, h, tt.ok)
+		}
+	}
+}
+
+var blocksTests = []struct {
+	in  string
+	out []block
+}{
+	{
+		in: `Para 1.
+Para 1 line 2.
+
+Para 2.
+
+Section
+
+Para 3.
+
+	pre
+	pre1
+
+Para 4.
+	pre
+	pre2
+`,
+		out: []block{
+			{opPara, []string{"Para 1.\n", "Para 1 line 2.\n"}},
+			{opPara, []string{"Para 2.\n"}},
+			{opHead, []string{"Section"}},
+			{opPara, []string{"Para 3.\n"}},
+			{opPre, []string{"pre\n", "pre1\n"}},
+			{opPara, []string{"Para 4.\n"}},
+			{opPre, []string{"pre\n", "pre2\n"}},
+		},
+	},
+}
+
+func TestBlocks(t *testing.T) {
+	for i, tt := range blocksTests {
+		b := blocks(tt.in)
+		if !reflect.DeepEqual(b, tt.out) {
+			t.Errorf("#%d: mismatch\nhave: %v\nwant: %v", i, b, tt.out)
+		}
+	}
+}
diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go
index c7fed97..d4aae8f 100644
--- a/src/pkg/go/doc/doc.go
+++ b/src/pkg/go/doc/doc.go
@@ -8,634 +8,86 @@ package doc
 import (
 	"go/ast"
 	"go/token"
-	"regexp"
-	"sort"
 )
 
-// ----------------------------------------------------------------------------
+// Package is the documentation for an entire package.
+type Package struct {
+	Doc        string
+	Name       string
+	ImportPath string
+	Imports    []string
+	Filenames  []string
+	Bugs       []string
 
-type typeDoc struct {
-	// len(decl.Specs) == 1, and the element type is *ast.TypeSpec
-	// if the type declaration hasn't been seen yet, decl is nil
-	decl *ast.GenDecl
-	// values, factory functions, and methods associated with the type
-	values    []*ast.GenDecl // consts and vars
-	factories map[string]*ast.FuncDecl
-	methods   map[string]*ast.FuncDecl
+	// declarations
+	Consts []*Value
+	Types  []*Type
+	Vars   []*Value
+	Funcs  []*Func
 }
 
-// docReader accumulates documentation for a single package.
-// It modifies the AST: Comments (declaration documentation)
-// that have been collected by the DocReader are set to nil
-// in the respective AST nodes so that they are not printed
-// twice (once when printing the documentation and once when
-// printing the corresponding AST node).
-//
-type docReader struct {
-	doc     *ast.CommentGroup // package documentation, if any
-	pkgName string
-	values  []*ast.GenDecl // consts and vars
-	types   map[string]*typeDoc
-	funcs   map[string]*ast.FuncDecl
-	bugs    []*ast.CommentGroup
-}
-
-func (doc *docReader) init(pkgName string) {
-	doc.pkgName = pkgName
-	doc.types = make(map[string]*typeDoc)
-	doc.funcs = make(map[string]*ast.FuncDecl)
-}
-
-func (doc *docReader) addDoc(comments *ast.CommentGroup) {
-	if doc.doc == nil {
-		// common case: just one package comment
-		doc.doc = comments
-		return
-	}
-
-	// More than one package comment: Usually there will be only
-	// one file with a package comment, but it's better to collect
-	// all comments than drop them on the floor.
-	// (This code isn't particularly clever - no amortized doubling is
-	// used - but this situation occurs rarely and is not time-critical.)
-	n1 := len(doc.doc.List)
-	n2 := len(comments.List)
-	list := make([]*ast.Comment, n1+1+n2) // + 1 for separator line
-	copy(list, doc.doc.List)
-	list[n1] = &ast.Comment{token.NoPos, "//"} // separator line
-	copy(list[n1+1:], comments.List)
-	doc.doc = &ast.CommentGroup{list}
-}
-
-func (doc *docReader) addType(decl *ast.GenDecl) {
-	spec := decl.Specs[0].(*ast.TypeSpec)
-	typ := doc.lookupTypeDoc(spec.Name.Name)
-	// typ should always be != nil since declared types
-	// are always named - be conservative and check
-	if typ != nil {
-		// a type should be added at most once, so typ.decl
-		// should be nil - if it isn't, simply overwrite it
-		typ.decl = decl
-	}
-}
-
-func (doc *docReader) lookupTypeDoc(name string) *typeDoc {
-	if name == "" {
-		return nil // no type docs for anonymous types
-	}
-	if tdoc, found := doc.types[name]; found {
-		return tdoc
-	}
-	// type wasn't found - add one without declaration
-	tdoc := &typeDoc{nil, nil, make(map[string]*ast.FuncDecl), make(map[string]*ast.FuncDecl)}
-	doc.types[name] = tdoc
-	return tdoc
-}
-
-func baseTypeName(typ ast.Expr) string {
-	switch t := typ.(type) {
-	case *ast.Ident:
-		// if the type is not exported, the effect to
-		// a client is as if there were no type name
-		if t.IsExported() {
-			return t.Name
-		}
-	case *ast.StarExpr:
-		return baseTypeName(t.X)
-	}
-	return ""
-}
-
-func (doc *docReader) addValue(decl *ast.GenDecl) {
-	// determine if decl should be associated with a type
-	// Heuristic: For each typed entry, determine the type name, if any.
-	//            If there is exactly one type name that is sufficiently
-	//            frequent, associate the decl with the respective type.
-	domName := ""
-	domFreq := 0
-	prev := ""
-	for _, s := range decl.Specs {
-		if v, ok := s.(*ast.ValueSpec); ok {
-			name := ""
-			switch {
-			case v.Type != nil:
-				// a type is present; determine its name
-				name = baseTypeName(v.Type)
-			case decl.Tok == token.CONST:
-				// no type is present but we have a constant declaration;
-				// use the previous type name (w/o more type information
-				// we cannot handle the case of unnamed variables with
-				// initializer expressions except for some trivial cases)
-				name = prev
-			}
-			if name != "" {
-				// entry has a named type
-				if domName != "" && domName != name {
-					// more than one type name - do not associate
-					// with any type
-					domName = ""
-					break
-				}
-				domName = name
-				domFreq++
-			}
-			prev = name
-		}
-	}
-
-	// determine values list
-	const threshold = 0.75
-	values := &doc.values
-	if domName != "" && domFreq >= int(float64(len(decl.Specs))*threshold) {
-		// typed entries are sufficiently frequent
-		typ := doc.lookupTypeDoc(domName)
-		if typ != nil {
-			values = &typ.values // associate with that type
-		}
-	}
-
-	*values = append(*values, decl)
-}
-
-// Helper function to set the table entry for function f. Makes sure that
-// at least one f with associated documentation is stored in table, if there
-// are multiple f's with the same name.
-func setFunc(table map[string]*ast.FuncDecl, f *ast.FuncDecl) {
-	name := f.Name.Name
-	if g, exists := table[name]; exists && g.Doc != nil {
-		// a function with the same name has already been registered;
-		// since it has documentation, assume f is simply another
-		// implementation and ignore it
-		// TODO(gri) consider collecting all functions, or at least
-		//           all comments
-		return
-	}
-	// function doesn't exist or has no documentation; use f
-	table[name] = f
-}
-
-func (doc *docReader) addFunc(fun *ast.FuncDecl) {
-	name := fun.Name.Name
-
-	// determine if it should be associated with a type
-	if fun.Recv != nil {
-		// method
-		typ := doc.lookupTypeDoc(baseTypeName(fun.Recv.List[0].Type))
-		if typ != nil {
-			// exported receiver type
-			setFunc(typ.methods, fun)
-		}
-		// otherwise don't show the method
-		// TODO(gri): There may be exported methods of non-exported types
-		// that can be called because of exported values (consts, vars, or
-		// function results) of that type. Could determine if that is the
-		// case and then show those methods in an appropriate section.
-		return
-	}
-
-	// perhaps a factory function
-	// determine result type, if any
-	if fun.Type.Results.NumFields() >= 1 {
-		res := fun.Type.Results.List[0]
-		if len(res.Names) <= 1 {
-			// exactly one (named or anonymous) result associated
-			// with the first type in result signature (there may
-			// be more than one result)
-			tname := baseTypeName(res.Type)
-			typ := doc.lookupTypeDoc(tname)
-			if typ != nil {
-				// named and exported result type
-
-				// Work-around for failure of heuristic: In package os
-				// too many functions are considered factory functions
-				// for the Error type. Eliminate manually for now as
-				// this appears to be the only important case in the
-				// current library where the heuristic fails.
-				if doc.pkgName == "os" && tname == "Error" &&
-					name != "NewError" && name != "NewSyscallError" {
-					// not a factory function for os.Error
-					setFunc(doc.funcs, fun) // treat as ordinary function
-					return
-				}
-
-				setFunc(typ.factories, fun)
-				return
-			}
-		}
-	}
-
-	// ordinary function
-	setFunc(doc.funcs, fun)
-}
-
-func (doc *docReader) addDecl(decl ast.Decl) {
-	switch d := decl.(type) {
-	case *ast.GenDecl:
-		if len(d.Specs) > 0 {
-			switch d.Tok {
-			case token.CONST, token.VAR:
-				// constants and variables are always handled as a group
-				doc.addValue(d)
-			case token.TYPE:
-				// types are handled individually
-				for _, spec := range d.Specs {
-					// make a (fake) GenDecl node for this TypeSpec
-					// (we need to do this here - as opposed to just
-					// for printing - so we don't lose the GenDecl
-					// documentation)
-					//
-					// TODO(gri): Consider just collecting the TypeSpec
-					// node (and copy in the GenDecl.doc if there is no
-					// doc in the TypeSpec - this is currently done in
-					// makeTypeDocs below). Simpler data structures, but
-					// would lose GenDecl documentation if the TypeSpec
-					// has documentation as well.
-					doc.addType(&ast.GenDecl{d.Doc, d.Pos(), token.TYPE, token.NoPos, []ast.Spec{spec}, token.NoPos})
-					// A new GenDecl node is created, no need to nil out d.Doc.
-				}
-			}
-		}
-	case *ast.FuncDecl:
-		doc.addFunc(d)
-	}
-}
-
-func copyCommentList(list []*ast.Comment) []*ast.Comment {
-	return append([]*ast.Comment(nil), list...)
-}
-
-var (
-	bug_markers = regexp.MustCompile("^/[/*][ \t]*BUG\\(.*\\):[ \t]*") // BUG(uid):
-	bug_content = regexp.MustCompile("[^ \n\r\t]+")                    // at least one non-whitespace char
-)
-
-// addFile adds the AST for a source file to the docReader.
-// Adding the same AST multiple times is a no-op.
-//
-func (doc *docReader) addFile(src *ast.File) {
-	// add package documentation
-	if src.Doc != nil {
-		doc.addDoc(src.Doc)
-		src.Doc = nil // doc consumed - remove from ast.File node
-	}
-
-	// add all declarations
-	for _, decl := range src.Decls {
-		doc.addDecl(decl)
-	}
-
-	// collect BUG(...) comments
-	for _, c := range src.Comments {
-		text := c.List[0].Text
-		if m := bug_markers.FindStringIndex(text); m != nil {
-			// found a BUG comment; maybe empty
-			if btxt := text[m[1]:]; bug_content.MatchString(btxt) {
-				// non-empty BUG comment; collect comment without BUG prefix
-				list := copyCommentList(c.List)
-				list[0].Text = text[m[1]:]
-				doc.bugs = append(doc.bugs, &ast.CommentGroup{list})
-			}
-		}
-	}
-	src.Comments = nil // consumed unassociated comments - remove from ast.File node
-}
-
-func NewFileDoc(file *ast.File) *PackageDoc {
-	var r docReader
-	r.init(file.Name.Name)
-	r.addFile(file)
-	return r.newDoc("", nil)
-}
-
-func NewPackageDoc(pkg *ast.Package, importpath string) *PackageDoc {
-	var r docReader
-	r.init(pkg.Name)
-	filenames := make([]string, len(pkg.Files))
-	i := 0
-	for filename, f := range pkg.Files {
-		r.addFile(f)
-		filenames[i] = filename
-		i++
-	}
-	return r.newDoc(importpath, filenames)
-}
-
-// ----------------------------------------------------------------------------
-// Conversion to external representation
-
-// ValueDoc is the documentation for a group of declared
-// values, either vars or consts.
-//
-type ValueDoc struct {
+// Value is the documentation for a (possibly grouped) var or const declaration.
+type Value struct {
 	Doc   string
+	Names []string // var or const names in declaration order
 	Decl  *ast.GenDecl
-	order int
-}
-
-type sortValueDoc []*ValueDoc
-
-func (p sortValueDoc) Len() int      { return len(p) }
-func (p sortValueDoc) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
 
-func declName(d *ast.GenDecl) string {
-	if len(d.Specs) != 1 {
-		return ""
-	}
-
-	switch v := d.Specs[0].(type) {
-	case *ast.ValueSpec:
-		return v.Names[0].Name
-	case *ast.TypeSpec:
-		return v.Name.Name
-	}
-
-	return ""
+	order int
 }
 
-func (p sortValueDoc) Less(i, j int) bool {
-	// sort by name
-	// pull blocks (name = "") up to top
-	// in original order
-	if ni, nj := declName(p[i].Decl), declName(p[j].Decl); ni != nj {
-		return ni < nj
-	}
-	return p[i].order < p[j].order
-}
+// Type is the documentation for a type declaration.
+type Type struct {
+	Doc  string
+	Name string
+	Decl *ast.GenDecl
 
-func makeValueDocs(list []*ast.GenDecl, tok token.Token) []*ValueDoc {
-	d := make([]*ValueDoc, len(list)) // big enough in any case
-	n := 0
-	for i, decl := range list {
-		if decl.Tok == tok {
-			d[n] = &ValueDoc{CommentText(decl.Doc), decl, i}
-			n++
-			decl.Doc = nil // doc consumed - removed from AST
-		}
-	}
-	d = d[0:n]
-	sort.Sort(sortValueDoc(d))
-	return d
+	// associated declarations
+	Consts  []*Value // sorted list of constants of (mostly) this type
+	Vars    []*Value // sorted list of variables of (mostly) this type
+	Funcs   []*Func  // sorted list of functions returning this type
+	Methods []*Func  // sorted list of methods (including embedded ones) of this type
 }
 
-// FuncDoc is the documentation for a func declaration,
-// either a top-level function or a method function.
-//
-type FuncDoc struct {
+// Func is the documentation for a func declaration.
+type Func struct {
 	Doc  string
-	Recv ast.Expr // TODO(rsc): Would like string here
 	Name string
 	Decl *ast.FuncDecl
-}
-
-type sortFuncDoc []*FuncDoc
-
-func (p sortFuncDoc) Len() int           { return len(p) }
-func (p sortFuncDoc) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
-func (p sortFuncDoc) Less(i, j int) bool { return p[i].Name < p[j].Name }
 
-func makeFuncDocs(m map[string]*ast.FuncDecl) []*FuncDoc {
-	d := make([]*FuncDoc, len(m))
-	i := 0
-	for _, f := range m {
-		doc := new(FuncDoc)
-		doc.Doc = CommentText(f.Doc)
-		f.Doc = nil // doc consumed - remove from ast.FuncDecl node
-		if f.Recv != nil {
-			doc.Recv = f.Recv.List[0].Type
-		}
-		doc.Name = f.Name.Name
-		doc.Decl = f
-		d[i] = doc
-		i++
-	}
-	sort.Sort(sortFuncDoc(d))
-	return d
-}
-
-// TypeDoc is the documentation for a declared type.
-// Consts and Vars are sorted lists of constants and variables of (mostly) that type.
-// Factories is a sorted list of factory functions that return that type.
-// Methods is a sorted list of method functions on that type.
-type TypeDoc struct {
-	Doc       string
-	Type      *ast.TypeSpec
-	Consts    []*ValueDoc
-	Vars      []*ValueDoc
-	Factories []*FuncDoc
-	Methods   []*FuncDoc
-	Decl      *ast.GenDecl
-	order     int
+	// methods
+	// (for functions, these fields have the respective zero value)
+	Recv  string // actual   receiver "T" or "*T"
+	Orig  string // original receiver "T" or "*T"
+	Level int    // embedding level; 0 means not embedded
 }
 
-type sortTypeDoc []*TypeDoc
+// Mode values control the operation of New.
+type Mode int
 
-func (p sortTypeDoc) Len() int      { return len(p) }
-func (p sortTypeDoc) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
-func (p sortTypeDoc) Less(i, j int) bool {
-	// sort by name
-	// pull blocks (name = "") up to top
-	// in original order
-	if ni, nj := p[i].Type.Name.Name, p[j].Type.Name.Name; ni != nj {
-		return ni < nj
-	}
-	return p[i].order < p[j].order
-}
-
-// NOTE(rsc): This would appear not to be correct for type ( )
-// blocks, but the doc extractor above has split them into
-// individual declarations.
-func (doc *docReader) makeTypeDocs(m map[string]*typeDoc) []*TypeDoc {
-	d := make([]*TypeDoc, len(m))
-	i := 0
-	for _, old := range m {
-		// all typeDocs should have a declaration associated with
-		// them after processing an entire package - be conservative
-		// and check
-		if decl := old.decl; decl != nil {
-			typespec := decl.Specs[0].(*ast.TypeSpec)
-			t := new(TypeDoc)
-			doc := typespec.Doc
-			typespec.Doc = nil // doc consumed - remove from ast.TypeSpec node
-			if doc == nil {
-				// no doc associated with the spec, use the declaration doc, if any
-				doc = decl.Doc
-			}
-			decl.Doc = nil // doc consumed - remove from ast.Decl node
-			t.Doc = CommentText(doc)
-			t.Type = typespec
-			t.Consts = makeValueDocs(old.values, token.CONST)
-			t.Vars = makeValueDocs(old.values, token.VAR)
-			t.Factories = makeFuncDocs(old.factories)
-			t.Methods = makeFuncDocs(old.methods)
-			t.Decl = old.decl
-			t.order = i
-			d[i] = t
-			i++
-		} else {
-			// no corresponding type declaration found - move any associated
-			// values, factory functions, and methods back to the top-level
-			// so that they are not lost (this should only happen if a package
-			// file containing the explicit type declaration is missing or if
-			// an unqualified type name was used after a "." import)
-			// 1) move values
-			doc.values = append(doc.values, old.values...)
-			// 2) move factory functions
-			for name, f := range old.factories {
-				doc.funcs[name] = f
-			}
-			// 3) move methods
-			for name, f := range old.methods {
-				// don't overwrite functions with the same name
-				if _, found := doc.funcs[name]; !found {
-					doc.funcs[name] = f
-				}
-			}
-		}
-	}
-	d = d[0:i] // some types may have been ignored
-	sort.Sort(sortTypeDoc(d))
-	return d
-}
-
-func makeBugDocs(list []*ast.CommentGroup) []string {
-	d := make([]string, len(list))
-	for i, g := range list {
-		d[i] = CommentText(g)
-	}
-	return d
-}
-
-// PackageDoc is the documentation for an entire package.
-//
-type PackageDoc struct {
-	PackageName string
-	ImportPath  string
-	Filenames   []string
-	Doc         string
-	Consts      []*ValueDoc
-	Types       []*TypeDoc
-	Vars        []*ValueDoc
-	Funcs       []*FuncDoc
-	Bugs        []string
-}
+const (
+	// extract documentation for all package-level declarations,
+	// not just exported ones
+	AllDecls Mode = 1 << iota
+)
 
-// newDoc returns the accumulated documentation for the package.
+// New computes the package documentation for the given package AST.
+// New takes ownership of the AST pkg and may edit or overwrite it.
 //
-func (doc *docReader) newDoc(importpath string, filenames []string) *PackageDoc {
-	p := new(PackageDoc)
-	p.PackageName = doc.pkgName
-	p.ImportPath = importpath
-	sort.Strings(filenames)
-	p.Filenames = filenames
-	p.Doc = CommentText(doc.doc)
-	// makeTypeDocs may extend the list of doc.values and
-	// doc.funcs and thus must be called before any other
-	// function consuming those lists
-	p.Types = doc.makeTypeDocs(doc.types)
-	p.Consts = makeValueDocs(doc.values, token.CONST)
-	p.Vars = makeValueDocs(doc.values, token.VAR)
-	p.Funcs = makeFuncDocs(doc.funcs)
-	p.Bugs = makeBugDocs(doc.bugs)
-	return p
-}
-
-// ----------------------------------------------------------------------------
-// Filtering by name
-
-type Filter func(string) bool
-
-func matchFields(fields *ast.FieldList, f Filter) bool {
-	if fields != nil {
-		for _, field := range fields.List {
-			for _, name := range field.Names {
-				if f(name.Name) {
-					return true
-				}
-			}
-		}
+func New(pkg *ast.Package, importPath string, mode Mode) *Package {
+	var r reader
+	r.readPackage(pkg, mode)
+	r.computeMethodSets()
+	r.cleanupTypes()
+	return &Package{
+		Doc:        r.doc,
+		Name:       pkg.Name,
+		ImportPath: importPath,
+		Imports:    sortedKeys(r.imports),
+		Filenames:  r.filenames,
+		Bugs:       r.bugs,
+		Consts:     sortedValues(r.values, token.CONST),
+		Types:      sortedTypes(r.types),
+		Vars:       sortedValues(r.values, token.VAR),
+		Funcs:      sortedFuncs(r.funcs),
 	}
-	return false
-}
-
-func matchDecl(d *ast.GenDecl, f Filter) bool {
-	for _, d := range d.Specs {
-		switch v := d.(type) {
-		case *ast.ValueSpec:
-			for _, name := range v.Names {
-				if f(name.Name) {
-					return true
-				}
-			}
-		case *ast.TypeSpec:
-			if f(v.Name.Name) {
-				return true
-			}
-			switch t := v.Type.(type) {
-			case *ast.StructType:
-				if matchFields(t.Fields, f) {
-					return true
-				}
-			case *ast.InterfaceType:
-				if matchFields(t.Methods, f) {
-					return true
-				}
-			}
-		}
-	}
-	return false
-}
-
-func filterValueDocs(a []*ValueDoc, f Filter) []*ValueDoc {
-	w := 0
-	for _, vd := range a {
-		if matchDecl(vd.Decl, f) {
-			a[w] = vd
-			w++
-		}
-	}
-	return a[0:w]
-}
-
-func filterFuncDocs(a []*FuncDoc, f Filter) []*FuncDoc {
-	w := 0
-	for _, fd := range a {
-		if f(fd.Name) {
-			a[w] = fd
-			w++
-		}
-	}
-	return a[0:w]
-}
-
-func filterTypeDocs(a []*TypeDoc, f Filter) []*TypeDoc {
-	w := 0
-	for _, td := range a {
-		n := 0 // number of matches
-		if matchDecl(td.Decl, f) {
-			n = 1
-		} else {
-			// type name doesn't match, but we may have matching consts, vars, factories or methods
-			td.Consts = filterValueDocs(td.Consts, f)
-			td.Vars = filterValueDocs(td.Vars, f)
-			td.Factories = filterFuncDocs(td.Factories, f)
-			td.Methods = filterFuncDocs(td.Methods, f)
-			n += len(td.Consts) + len(td.Vars) + len(td.Factories) + len(td.Methods)
-		}
-		if n > 0 {
-			a[w] = td
-			w++
-		}
-	}
-	return a[0:w]
-}
-
-// Filter eliminates documentation for names that don't pass through the filter f.
-// TODO: Recognize "Type.Method" as a name.
-//
-func (p *PackageDoc) Filter(f Filter) {
-	p.Consts = filterValueDocs(p.Consts, f)
-	p.Vars = filterValueDocs(p.Vars, f)
-	p.Types = filterTypeDocs(p.Types, f)
-	p.Funcs = filterFuncDocs(p.Funcs, f)
-	p.Doc = "" // don't show top-level package doc
 }
diff --git a/src/pkg/go/doc/doc_test.go b/src/pkg/go/doc/doc_test.go
new file mode 100644
index 0000000..d9ffe47
--- /dev/null
+++ b/src/pkg/go/doc/doc_test.go
@@ -0,0 +1,121 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package doc
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+	"text/template"
+)
+
+var update = flag.Bool("update", false, "update golden (.out) files")
+
+const dataDir = "testdata"
+
+var templateTxt = readTemplate("template.txt")
+
+func readTemplate(filename string) *template.Template {
+	t := template.New(filename)
+	t.Funcs(template.FuncMap{
+		"node":     nodeFmt,
+		"synopsis": synopsisFmt,
+	})
+	return template.Must(t.ParseFiles(filepath.Join(dataDir, filename)))
+}
+
+func nodeFmt(node interface{}, fset *token.FileSet) string {
+	var buf bytes.Buffer
+	printer.Fprint(&buf, fset, node)
+	return strings.Replace(strings.TrimSpace(buf.String()), "\n", "\n\t", -1)
+}
+
+func synopsisFmt(s string) string {
+	const n = 64
+	if len(s) > n {
+		// cut off excess text and go back to a word boundary
+		s = s[0:n]
+		if i := strings.LastIndexAny(s, "\t\n "); i >= 0 {
+			s = s[0:i]
+		}
+		s = strings.TrimSpace(s) + " ..."
+	}
+	return "// " + strings.Replace(s, "\n", " ", -1)
+}
+
+func isGoFile(fi os.FileInfo) bool {
+	name := fi.Name()
+	return !fi.IsDir() &&
+		len(name) > 0 && name[0] != '.' && // ignore .files
+		filepath.Ext(name) == ".go"
+}
+
+type bundle struct {
+	*Package
+	FSet *token.FileSet
+}
+
+func test(t *testing.T, mode Mode) {
+	// get all packages
+	fset := token.NewFileSet()
+	pkgs, err := parser.ParseDir(fset, dataDir, isGoFile, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// test all packages
+	for _, pkg := range pkgs {
+		importpath := dataDir + "/" + pkg.Name
+		doc := New(pkg, importpath, mode)
+
+		// golden files always use / in filenames - canonicalize them
+		for i, filename := range doc.Filenames {
+			doc.Filenames[i] = filepath.ToSlash(filename)
+		}
+
+		// print documentation
+		var buf bytes.Buffer
+		if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
+			t.Error(err)
+			continue
+		}
+		got := buf.Bytes()
+
+		// update golden file if necessary
+		golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
+		if *update {
+			err := ioutil.WriteFile(golden, got, 0644)
+			if err != nil {
+				t.Error(err)
+			}
+			continue
+		}
+
+		// get golden file
+		want, err := ioutil.ReadFile(golden)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		// compare
+		if bytes.Compare(got, want) != 0 {
+			t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
+		}
+	}
+}
+
+func Test(t *testing.T) {
+	test(t, 0)
+	test(t, AllDecls)
+}
diff --git a/src/pkg/go/doc/example.go b/src/pkg/go/doc/example.go
new file mode 100644
index 0000000..7c59bf9
--- /dev/null
+++ b/src/pkg/go/doc/example.go
@@ -0,0 +1,57 @@
+// Copyright 2011 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.
+
+// Extract example functions from package ASTs.
+
+package doc
+
+import (
+	"go/ast"
+	"go/printer"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+type Example struct {
+	Name   string                 // name of the item being demonstrated
+	Body   *printer.CommentedNode // code
+	Output string                 // expected output
+}
+
+func Examples(pkg *ast.Package) []*Example {
+	var examples []*Example
+	for _, src := range pkg.Files {
+		for _, decl := range src.Decls {
+			f, ok := decl.(*ast.FuncDecl)
+			if !ok {
+				continue
+			}
+			name := f.Name.Name
+			if !isTest(name, "Example") {
+				continue
+			}
+			examples = append(examples, &Example{
+				Name:   name[len("Example"):],
+				Body:   &printer.CommentedNode{f.Body, src.Comments},
+				Output: f.Doc.Text(),
+			})
+		}
+	}
+	return examples
+}
+
+// isTest tells whether name looks like a test, example, or benchmark.
+// It is a Test (say) if there is a character after Test that is not a
+// lower-case letter. (We don't want Testiness.)
+func isTest(name, prefix string) bool {
+	if !strings.HasPrefix(name, prefix) {
+		return false
+	}
+	if len(name) == len(prefix) { // "Test" is ok
+		return true
+	}
+	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
+	return !unicode.IsLower(rune)
+}
diff --git a/src/pkg/go/doc/exports.go b/src/pkg/go/doc/exports.go
new file mode 100644
index 0000000..e6f58cc
--- /dev/null
+++ b/src/pkg/go/doc/exports.go
@@ -0,0 +1,169 @@
+// Copyright 2011 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 file implements export filtering of an AST.
+
+package doc
+
+import "go/ast"
+
+// filterIdentList removes unexported names from list in place
+// and returns the resulting list.
+//
+func filterIdentList(list []*ast.Ident) []*ast.Ident {
+	j := 0
+	for _, x := range list {
+		if ast.IsExported(x.Name) {
+			list[j] = x
+			j++
+		}
+	}
+	return list[0:j]
+}
+
+// filterFieldList removes unexported fields (field names) from the field list
+// in place and returns true if fields were removed. Removed fields that are
+// anonymous (embedded) fields are added as embedded types to base. filterType
+// is called with the types of all remaining fields.
+//
+func (r *reader) filterFieldList(base *baseType, fields *ast.FieldList) (removedFields bool) {
+	if fields == nil {
+		return
+	}
+	list := fields.List
+	j := 0
+	for _, field := range list {
+		keepField := false
+		if n := len(field.Names); n == 0 {
+			// anonymous field
+			name, imp := baseTypeName(field.Type)
+			if ast.IsExported(name) {
+				// we keep the field - in this case r.readDecl
+				// will take care of adding the embedded type
+				keepField = true
+			} else if base != nil && !imp {
+				// we don't keep the field - add it as an embedded
+				// type so we won't loose its methods, if any
+				if embedded := r.lookupType(name); embedded != nil {
+					_, ptr := field.Type.(*ast.StarExpr)
+					base.addEmbeddedType(embedded, ptr)
+				}
+			}
+		} else {
+			field.Names = filterIdentList(field.Names)
+			if len(field.Names) < n {
+				removedFields = true
+			}
+			if len(field.Names) > 0 {
+				keepField = true
+			}
+		}
+		if keepField {
+			r.filterType(nil, field.Type)
+			list[j] = field
+			j++
+		}
+	}
+	if j < len(list) {
+		removedFields = true
+	}
+	fields.List = list[0:j]
+	return
+}
+
+// filterParamList applies filterType to each parameter type in fields.
+//
+func (r *reader) filterParamList(fields *ast.FieldList) {
+	if fields != nil {
+		for _, f := range fields.List {
+			r.filterType(nil, f.Type)
+		}
+	}
+}
+
+// filterType strips any unexported struct fields or method types from typ
+// in place. If fields (or methods) have been removed, the corresponding
+// struct or interface type has the Incomplete field set to true. 
+//
+func (r *reader) filterType(base *baseType, typ ast.Expr) {
+	switch t := typ.(type) {
+	case *ast.Ident:
+		// nothing to do
+	case *ast.ParenExpr:
+		r.filterType(nil, t.X)
+	case *ast.ArrayType:
+		r.filterType(nil, t.Elt)
+	case *ast.StructType:
+		if r.filterFieldList(base, t.Fields) {
+			t.Incomplete = true
+		}
+	case *ast.FuncType:
+		r.filterParamList(t.Params)
+		r.filterParamList(t.Results)
+	case *ast.InterfaceType:
+		if r.filterFieldList(base, t.Methods) {
+			t.Incomplete = true
+		}
+	case *ast.MapType:
+		r.filterType(nil, t.Key)
+		r.filterType(nil, t.Value)
+	case *ast.ChanType:
+		r.filterType(nil, t.Value)
+	}
+}
+
+func (r *reader) filterSpec(spec ast.Spec) bool {
+	switch s := spec.(type) {
+	case *ast.ImportSpec:
+		// always keep imports so we can collect them
+		return true
+	case *ast.ValueSpec:
+		s.Names = filterIdentList(s.Names)
+		if len(s.Names) > 0 {
+			r.filterType(nil, s.Type)
+			return true
+		}
+	case *ast.TypeSpec:
+		if ast.IsExported(s.Name.Name) {
+			r.filterType(r.lookupType(s.Name.Name), s.Type)
+			return true
+		}
+	}
+	return false
+}
+
+func (r *reader) filterSpecList(list []ast.Spec) []ast.Spec {
+	j := 0
+	for _, s := range list {
+		if r.filterSpec(s) {
+			list[j] = s
+			j++
+		}
+	}
+	return list[0:j]
+}
+
+func (r *reader) filterDecl(decl ast.Decl) bool {
+	switch d := decl.(type) {
+	case *ast.GenDecl:
+		d.Specs = r.filterSpecList(d.Specs)
+		return len(d.Specs) > 0
+	case *ast.FuncDecl:
+		return ast.IsExported(d.Name.Name)
+	}
+	return false
+}
+
+// fileExports removes unexported declarations from src in place.
+//
+func (r *reader) fileExports(src *ast.File) {
+	j := 0
+	for _, d := range src.Decls {
+		if r.filterDecl(d) {
+			src.Decls[j] = d
+			j++
+		}
+	}
+	src.Decls = src.Decls[0:j]
+}
diff --git a/src/pkg/go/doc/filter.go b/src/pkg/go/doc/filter.go
new file mode 100644
index 0000000..02b66cc
--- /dev/null
+++ b/src/pkg/go/doc/filter.go
@@ -0,0 +1,105 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package doc
+
+import "go/ast"
+
+type Filter func(string) bool
+
+func matchFields(fields *ast.FieldList, f Filter) bool {
+	if fields != nil {
+		for _, field := range fields.List {
+			for _, name := range field.Names {
+				if f(name.Name) {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+func matchDecl(d *ast.GenDecl, f Filter) bool {
+	for _, d := range d.Specs {
+		switch v := d.(type) {
+		case *ast.ValueSpec:
+			for _, name := range v.Names {
+				if f(name.Name) {
+					return true
+				}
+			}
+		case *ast.TypeSpec:
+			if f(v.Name.Name) {
+				return true
+			}
+			switch t := v.Type.(type) {
+			case *ast.StructType:
+				if matchFields(t.Fields, f) {
+					return true
+				}
+			case *ast.InterfaceType:
+				if matchFields(t.Methods, f) {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+func filterValues(a []*Value, f Filter) []*Value {
+	w := 0
+	for _, vd := range a {
+		if matchDecl(vd.Decl, f) {
+			a[w] = vd
+			w++
+		}
+	}
+	return a[0:w]
+}
+
+func filterFuncs(a []*Func, f Filter) []*Func {
+	w := 0
+	for _, fd := range a {
+		if f(fd.Name) {
+			a[w] = fd
+			w++
+		}
+	}
+	return a[0:w]
+}
+
+func filterTypes(a []*Type, f Filter) []*Type {
+	w := 0
+	for _, td := range a {
+		n := 0 // number of matches
+		if matchDecl(td.Decl, f) {
+			n = 1
+		} else {
+			// type name doesn't match, but we may have matching consts, vars, factories or methods
+			td.Consts = filterValues(td.Consts, f)
+			td.Vars = filterValues(td.Vars, f)
+			td.Funcs = filterFuncs(td.Funcs, f)
+			td.Methods = filterFuncs(td.Methods, f)
+			n += len(td.Consts) + len(td.Vars) + len(td.Funcs) + len(td.Methods)
+		}
+		if n > 0 {
+			a[w] = td
+			w++
+		}
+	}
+	return a[0:w]
+}
+
+// Filter eliminates documentation for names that don't pass through the filter f.
+// TODO: Recognize "Type.Method" as a name.
+//
+func (p *Package) Filter(f Filter) {
+	p.Consts = filterValues(p.Consts, f)
+	p.Vars = filterValues(p.Vars, f)
+	p.Types = filterTypes(p.Types, f)
+	p.Funcs = filterFuncs(p.Funcs, f)
+	p.Doc = "" // don't show top-level package doc
+}
diff --git a/src/pkg/go/doc/headscan.go b/src/pkg/go/doc/headscan.go
new file mode 100644
index 0000000..37486b1
--- /dev/null
+++ b/src/pkg/go/doc/headscan.go
@@ -0,0 +1,111 @@
+// Copyright 2011 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.
+
+/*
+	The headscan command extracts comment headings from package files;
+	it is used to detect false positives which may require an adjustment
+	to the comment formatting heuristics in comment.go.
+
+	Usage: headscan [-root root_directory]
+
+	By default, the $GOROOT/src directory is scanned.
+*/
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"go/doc"
+	"go/parser"
+	"go/token"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strings"
+)
+
+var (
+	root    = flag.String("root", filepath.Join(runtime.GOROOT(), "src"), "root of filesystem tree to scan")
+	verbose = flag.Bool("v", false, "verbose mode")
+)
+
+const (
+	html_h    = "<h3>"
+	html_endh = "</h3>\n"
+)
+
+func isGoFile(fi os.FileInfo) bool {
+	return strings.HasSuffix(fi.Name(), ".go") &&
+		!strings.HasSuffix(fi.Name(), "_test.go")
+}
+
+func appendHeadings(list []string, comment string) []string {
+	var buf bytes.Buffer
+	doc.ToHTML(&buf, comment, nil)
+	for s := buf.String(); ; {
+		i := strings.Index(s, html_h)
+		if i < 0 {
+			break
+		}
+		i += len(html_h)
+		j := strings.Index(s, html_endh)
+		if j < 0 {
+			list = append(list, s[i:]) // incorrect HTML
+			break
+		}
+		list = append(list, s[i:j])
+		s = s[j+len(html_endh):]
+	}
+	return list
+}
+
+func main() {
+	flag.Parse()
+	fset := token.NewFileSet()
+	nheadings := 0
+	err := filepath.Walk(*root, func(path string, fi os.FileInfo, err error) error {
+		if !fi.IsDir() {
+			return nil
+		}
+		pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments)
+		if err != nil {
+			if *verbose {
+				fmt.Fprintln(os.Stderr, err)
+			}
+			return nil
+		}
+		for _, pkg := range pkgs {
+			d := doc.New(pkg, path, doc.Mode(0))
+			list := appendHeadings(nil, d.Doc)
+			for _, d := range d.Consts {
+				list = appendHeadings(list, d.Doc)
+			}
+			for _, d := range d.Types {
+				list = appendHeadings(list, d.Doc)
+			}
+			for _, d := range d.Vars {
+				list = appendHeadings(list, d.Doc)
+			}
+			for _, d := range d.Funcs {
+				list = appendHeadings(list, d.Doc)
+			}
+			if len(list) > 0 {
+				// directories may contain multiple packages;
+				// print path and package name
+				fmt.Printf("%s (package %s)\n", path, pkg.Name)
+				for _, h := range list {
+					fmt.Printf("\t%s\n", h)
+				}
+				nheadings += len(list)
+			}
+		}
+		return nil
+	})
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+	fmt.Println(nheadings, "headings found")
+}
diff --git a/src/pkg/go/doc/reader.go b/src/pkg/go/doc/reader.go
new file mode 100644
index 0000000..9c6f081
--- /dev/null
+++ b/src/pkg/go/doc/reader.go
@@ -0,0 +1,734 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package doc
+
+import (
+	"go/ast"
+	"go/token"
+	"regexp"
+	"sort"
+	"strconv"
+)
+
+// ----------------------------------------------------------------------------
+// function/method sets
+//
+// Internally, we treat functions like methods and collect them in method sets.
+
+// methodSet describes a set of methods. Entries where Decl == nil are conflict
+// entries (more then one method with the same name at the same embedding level).
+//
+type methodSet map[string]*Func
+
+// recvString returns a string representation of recv of the
+// form "T", "*T", or "BADRECV" (if not a proper receiver type).
+//
+func recvString(recv ast.Expr) string {
+	switch t := recv.(type) {
+	case *ast.Ident:
+		return t.Name
+	case *ast.StarExpr:
+		return "*" + recvString(t.X)
+	}
+	return "BADRECV"
+}
+
+// set creates the corresponding Func for f and adds it to mset.
+// If there are multiple f's with the same name, set keeps the first
+// one with documentation; conflicts are ignored.
+//
+func (mset methodSet) set(f *ast.FuncDecl) {
+	name := f.Name.Name
+	if g := mset[name]; g != nil && g.Doc != "" {
+		// A function with the same name has already been registered;
+		// since it has documentation, assume f is simply another
+		// implementation and ignore it. This does not happen if the
+		// caller is using go/build.ScanDir to determine the list of
+		// files implementing a package. 
+		return
+	}
+	// function doesn't exist or has no documentation; use f
+	recv := ""
+	if f.Recv != nil {
+		var typ ast.Expr
+		// be careful in case of incorrect ASTs
+		if list := f.Recv.List; len(list) == 1 {
+			typ = list[0].Type
+		}
+		recv = recvString(typ)
+	}
+	mset[name] = &Func{
+		Doc:  f.Doc.Text(),
+		Name: name,
+		Decl: f,
+		Recv: recv,
+		Orig: recv,
+	}
+	f.Doc = nil // doc consumed - remove from AST
+}
+
+// add adds method m to the method set; m is ignored if the method set
+// already contains a method with the same name at the same or a higher
+// level then m.
+//
+func (mset methodSet) add(m *Func) {
+	old := mset[m.Name]
+	if old == nil || m.Level < old.Level {
+		mset[m.Name] = m
+		return
+	}
+	if old != nil && m.Level == old.Level {
+		// conflict - mark it using a method with nil Decl
+		mset[m.Name] = &Func{
+			Name:  m.Name,
+			Level: m.Level,
+		}
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Base types
+
+// baseTypeName returns the name of the base type of x (or "")
+// and whether the type is imported or not.
+//
+func baseTypeName(x ast.Expr) (name string, imported bool) {
+	switch t := x.(type) {
+	case *ast.Ident:
+		return t.Name, false
+	case *ast.SelectorExpr:
+		if _, ok := t.X.(*ast.Ident); ok {
+			// only possible for qualified type names;
+			// assume type is imported
+			return t.Sel.Name, true
+		}
+	case *ast.StarExpr:
+		return baseTypeName(t.X)
+	}
+	return
+}
+
+// embeddedType describes the type of an anonymous field.
+//
+type embeddedType struct {
+	typ *baseType // the corresponding base type
+	ptr bool      // if set, the anonymous field type is a pointer
+}
+
+type baseType struct {
+	doc  string       // doc comment for type
+	name string       // local type name (excluding package qualifier)
+	decl *ast.GenDecl // nil if declaration hasn't been seen yet
+
+	// associated declarations
+	values  []*Value // consts and vars
+	funcs   methodSet
+	methods methodSet
+
+	isEmbedded bool           // true if this type is embedded
+	isStruct   bool           // true if this type is a struct
+	embedded   []embeddedType // list of embedded types
+}
+
+func (typ *baseType) addEmbeddedType(e *baseType, isPtr bool) {
+	e.isEmbedded = true
+	typ.embedded = append(typ.embedded, embeddedType{e, isPtr})
+}
+
+// ----------------------------------------------------------------------------
+// AST reader
+
+// reader accumulates documentation for a single package.
+// It modifies the AST: Comments (declaration documentation)
+// that have been collected by the reader are set to nil
+// in the respective AST nodes so that they are not printed
+// twice (once when printing the documentation and once when
+// printing the corresponding AST node).
+//
+type reader struct {
+	mode Mode
+
+	// package properties
+	doc       string // package documentation, if any
+	filenames []string
+	bugs      []string
+
+	// declarations
+	imports map[string]int
+	values  []*Value // consts and vars
+	types   map[string]*baseType
+	funcs   methodSet
+}
+
+// isVisible reports whether name is visible in the documentation.
+//
+func (r *reader) isVisible(name string) bool {
+	return r.mode&AllDecls != 0 || ast.IsExported(name)
+}
+
+// lookupType returns the base type with the given name.
+// If the base type has not been encountered yet, a new
+// type with the given name but no associated declaration
+// is added to the type map.
+//
+func (r *reader) lookupType(name string) *baseType {
+	if name == "" || name == "_" {
+		return nil // no type docs for anonymous types
+	}
+	if typ, found := r.types[name]; found {
+		return typ
+	}
+	// type not found - add one without declaration
+	typ := &baseType{
+		name:    name,
+		funcs:   make(methodSet),
+		methods: make(methodSet),
+	}
+	r.types[name] = typ
+	return typ
+}
+
+func (r *reader) readDoc(comment *ast.CommentGroup) {
+	// By convention there should be only one package comment
+	// but collect all of them if there are more then one.
+	text := comment.Text()
+	if r.doc == "" {
+		r.doc = text
+		return
+	}
+	r.doc += "\n" + text
+}
+
+func specNames(specs []ast.Spec) []string {
+	names := make([]string, 0, len(specs)) // reasonable estimate
+	for _, s := range specs {
+		// s guaranteed to be an *ast.ValueSpec by readValue
+		for _, ident := range s.(*ast.ValueSpec).Names {
+			names = append(names, ident.Name)
+		}
+	}
+	return names
+}
+
+// readValue processes a const or var declaration.
+//
+func (r *reader) readValue(decl *ast.GenDecl) {
+	// determine if decl should be associated with a type
+	// Heuristic: For each typed entry, determine the type name, if any.
+	//            If there is exactly one type name that is sufficiently
+	//            frequent, associate the decl with the respective type.
+	domName := ""
+	domFreq := 0
+	prev := ""
+	n := 0
+	for _, spec := range decl.Specs {
+		s, ok := spec.(*ast.ValueSpec)
+		if !ok {
+			continue // should not happen, but be conservative
+		}
+		name := ""
+		switch {
+		case s.Type != nil:
+			// a type is present; determine its name
+			if n, imp := baseTypeName(s.Type); !imp && r.isVisible(n) {
+				name = n
+			}
+		case decl.Tok == token.CONST:
+			// no type is present but we have a constant declaration;
+			// use the previous type name (w/o more type information
+			// we cannot handle the case of unnamed variables with
+			// initializer expressions except for some trivial cases)
+			name = prev
+		}
+		if name != "" {
+			// entry has a named type
+			if domName != "" && domName != name {
+				// more than one type name - do not associate
+				// with any type
+				domName = ""
+				break
+			}
+			domName = name
+			domFreq++
+		}
+		prev = name
+		n++
+	}
+
+	// nothing to do w/o a legal declaration
+	if n == 0 {
+		return
+	}
+
+	// determine values list with which to associate the Value for this decl
+	values := &r.values
+	const threshold = 0.75
+	if domName != "" && domFreq >= int(float64(len(decl.Specs))*threshold) {
+		// typed entries are sufficiently frequent
+		typ := r.lookupType(domName)
+		if typ != nil {
+			values = &typ.values // associate with that type
+		}
+	}
+
+	*values = append(*values, &Value{
+		Doc:   decl.Doc.Text(),
+		Names: specNames(decl.Specs),
+		Decl:  decl,
+		order: len(*values),
+	})
+	decl.Doc = nil // doc consumed - remove from AST
+}
+
+// fields returns a struct's fields or an interface's methods.
+//
+func fields(typ ast.Expr) (list []*ast.Field, isStruct bool) {
+	var fields *ast.FieldList
+	switch t := typ.(type) {
+	case *ast.StructType:
+		fields = t.Fields
+		isStruct = true
+	case *ast.InterfaceType:
+		fields = t.Methods
+	}
+	if fields != nil {
+		list = fields.List
+	}
+	return
+}
+
+// readType processes a type declaration.
+//
+func (r *reader) readType(decl *ast.GenDecl, spec *ast.TypeSpec) {
+	typ := r.lookupType(spec.Name.Name)
+	if typ == nil {
+		return // no name or blank name - ignore the type
+	}
+
+	// A type should be added at most once, so info.decl
+	// should be nil - if it is not, simply overwrite it.
+	typ.decl = decl
+
+	// compute documentation
+	doc := spec.Doc
+	spec.Doc = nil // doc consumed - remove from AST
+	if doc == nil {
+		// no doc associated with the spec, use the declaration doc, if any
+		doc = decl.Doc
+	}
+	decl.Doc = nil // doc consumed - remove from AST
+	typ.doc = doc.Text()
+
+	// look for anonymous fields that might contribute methods
+	var list []*ast.Field
+	list, typ.isStruct = fields(spec.Type)
+	for _, field := range list {
+		if len(field.Names) == 0 {
+			// anonymous field - add corresponding field type to typ
+			n, imp := baseTypeName(field.Type)
+			if imp {
+				// imported type - we don't handle this case
+				// at the moment
+				return
+			}
+			if embedded := r.lookupType(n); embedded != nil {
+				_, ptr := field.Type.(*ast.StarExpr)
+				typ.addEmbeddedType(embedded, ptr)
+			}
+		}
+	}
+}
+
+// readFunc processes a func or method declaration.
+//
+func (r *reader) readFunc(fun *ast.FuncDecl) {
+	// strip function body
+	fun.Body = nil
+
+	// determine if it should be associated with a type
+	if fun.Recv != nil {
+		// method
+		recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type)
+		if imp {
+			// should not happen (incorrect AST);
+			// don't show this method
+			return
+		}
+		var typ *baseType
+		if r.isVisible(recvTypeName) {
+			// visible recv type: if not found, add it to r.types
+			typ = r.lookupType(recvTypeName)
+		} else {
+			// invisible recv type: if not found, do not add it
+			// (invisible embedded types are added before this
+			// phase, so if the type doesn't exist yet, we don't
+			// care about this method)
+			typ = r.types[recvTypeName]
+		}
+		if typ != nil {
+			// associate method with the type
+			// (if the type is not exported, it may be embedded
+			// somewhere so we need to collect the method anyway)
+			typ.methods.set(fun)
+		}
+		// otherwise don't show the method
+		// TODO(gri): There may be exported methods of non-exported types
+		// that can be called because of exported values (consts, vars, or
+		// function results) of that type. Could determine if that is the
+		// case and then show those methods in an appropriate section.
+		return
+	}
+
+	// perhaps a factory function
+	// determine result type, if any
+	if fun.Type.Results.NumFields() >= 1 {
+		res := fun.Type.Results.List[0]
+		if len(res.Names) <= 1 {
+			// exactly one (named or anonymous) result associated
+			// with the first type in result signature (there may
+			// be more than one result)
+			if n, imp := baseTypeName(res.Type); !imp && r.isVisible(n) {
+				if typ := r.lookupType(n); typ != nil {
+					// associate Func with typ
+					typ.funcs.set(fun)
+					return
+				}
+			}
+		}
+	}
+
+	// just an ordinary function
+	r.funcs.set(fun)
+}
+
+var (
+	bug_markers = regexp.MustCompile("^/[/*][ \t]*BUG\\(.*\\):[ \t]*") // BUG(uid):
+	bug_content = regexp.MustCompile("[^ \n\r\t]+")                    // at least one non-whitespace char
+)
+
+// readFile adds the AST for a source file to the reader.
+//
+func (r *reader) readFile(src *ast.File) {
+	// add package documentation
+	if src.Doc != nil {
+		r.readDoc(src.Doc)
+		src.Doc = nil // doc consumed - remove from AST
+	}
+
+	// add all declarations
+	for _, decl := range src.Decls {
+		switch d := decl.(type) {
+		case *ast.GenDecl:
+			switch d.Tok {
+			case token.IMPORT:
+				// imports are handled individually
+				for _, spec := range d.Specs {
+					if s, ok := spec.(*ast.ImportSpec); ok {
+						if import_, err := strconv.Unquote(s.Path.Value); err == nil {
+							r.imports[import_] = 1
+						}
+					}
+				}
+			case token.CONST, token.VAR:
+				// constants and variables are always handled as a group
+				r.readValue(d)
+			case token.TYPE:
+				// types are handled individually
+				for _, spec := range d.Specs {
+					if s, ok := spec.(*ast.TypeSpec); ok {
+						// use an individual (possibly fake) declaration
+						// for each type; this also ensures that each type
+						// gets to (re-)use the declaration documentation
+						// if there's none associated with the spec itself
+						fake := &ast.GenDecl{
+							d.Doc, d.Pos(), token.TYPE, token.NoPos,
+							[]ast.Spec{s}, token.NoPos,
+						}
+						r.readType(fake, s)
+					}
+				}
+			}
+		case *ast.FuncDecl:
+			r.readFunc(d)
+		}
+	}
+
+	// collect BUG(...) comments
+	for _, c := range src.Comments {
+		text := c.List[0].Text
+		if m := bug_markers.FindStringIndex(text); m != nil {
+			// found a BUG comment; maybe empty
+			if btxt := text[m[1]:]; bug_content.MatchString(btxt) {
+				// non-empty BUG comment; collect comment without BUG prefix
+				list := append([]*ast.Comment(nil), c.List...) // make a copy
+				list[0].Text = text[m[1]:]
+				r.bugs = append(r.bugs, (&ast.CommentGroup{list}).Text())
+			}
+		}
+	}
+	src.Comments = nil // consumed unassociated comments - remove from AST
+}
+
+func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
+	// initialize reader
+	r.filenames = make([]string, len(pkg.Files))
+	r.imports = make(map[string]int)
+	r.mode = mode
+	r.types = make(map[string]*baseType)
+	r.funcs = make(methodSet)
+
+	// sort package files before reading them so that the
+	// result result does not depend on map iteration order
+	i := 0
+	for filename := range pkg.Files {
+		r.filenames[i] = filename
+		i++
+	}
+	sort.Strings(r.filenames)
+
+	// process files in sorted order
+	for _, filename := range r.filenames {
+		f := pkg.Files[filename]
+		if mode&AllDecls == 0 {
+			r.fileExports(f)
+		}
+		r.readFile(f)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+var predeclaredTypes = map[string]bool{
+	"bool":       true,
+	"byte":       true,
+	"complex64":  true,
+	"complex128": true,
+	"float32":    true,
+	"float64":    true,
+	"int":        true,
+	"int8":       true,
+	"int16":      true,
+	"int32":      true,
+	"int64":      true,
+	"string":     true,
+	"uint":       true,
+	"uint8":      true,
+	"uint16":     true,
+	"uint32":     true,
+	"uint64":     true,
+	"uintptr":    true,
+}
+
+func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func {
+	if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 {
+		return f // shouldn't happen, but be safe
+	}
+
+	// copy existing receiver field and set new type
+	newField := *f.Decl.Recv.List[0]
+	_, origRecvIsPtr := newField.Type.(*ast.StarExpr)
+	var typ ast.Expr = ast.NewIdent(recvTypeName)
+	if !embeddedIsPtr && origRecvIsPtr {
+		typ = &ast.StarExpr{token.NoPos, typ}
+	}
+	newField.Type = typ
+
+	// copy existing receiver field list and set new receiver field
+	newFieldList := *f.Decl.Recv
+	newFieldList.List = []*ast.Field{&newField}
+
+	// copy existing function declaration and set new receiver field list
+	newFuncDecl := *f.Decl
+	newFuncDecl.Recv = &newFieldList
+
+	// copy existing function documentation and set new declaration
+	newF := *f
+	newF.Decl = &newFuncDecl
+	newF.Recv = recvString(typ)
+	// the Orig field never changes
+	newF.Level = level
+
+	return &newF
+}
+
+// collectEmbeddedMethods collects the embedded methods from
+// all processed embedded types found in info in mset.
+//
+func collectEmbeddedMethods(mset methodSet, typ *baseType, recvTypeName string, embeddedIsPtr bool, level int) {
+	for _, e := range typ.embedded {
+		// Once an embedded type is embedded as a pointer type
+		// all embedded types in those types are treated like
+		// pointer types for the purpose of the receiver type
+		// computation; i.e., embeddedIsPtr is sticky for this
+		// embedding hierarchy.
+		thisEmbeddedIsPtr := embeddedIsPtr || e.ptr
+		for _, m := range e.typ.methods {
+			// only top-level methods are embedded
+			if m.Level == 0 {
+				mset.add(customizeRecv(m, recvTypeName, thisEmbeddedIsPtr, level))
+			}
+		}
+		collectEmbeddedMethods(mset, e.typ, recvTypeName, thisEmbeddedIsPtr, level+1)
+	}
+}
+
+// computeMethodSets determines the actual method sets for each type encountered.
+//
+func (r *reader) computeMethodSets() {
+	for _, t := range r.types {
+		// collect embedded methods for t
+		if t.isStruct {
+			// struct
+			collectEmbeddedMethods(t.methods, t, t.name, false, 1)
+		} else {
+			// interface
+			// TODO(gri) fix this
+		}
+	}
+}
+
+// cleanupTypes removes the association of functions and methods with
+// types that have no declaration. Instead, these functions and methods
+// are shown at the package level. It also removes types with missing
+// declarations or which are not visible.
+// 
+func (r *reader) cleanupTypes() {
+	for _, t := range r.types {
+		visible := r.isVisible(t.name)
+		if t.decl == nil && (predeclaredTypes[t.name] || t.isEmbedded && visible) {
+			// t.name is a predeclared type (and was not redeclared in this package),
+			// or it was embedded somewhere but its declaration is missing (because
+			// the AST is incomplete): move any associated values, funcs, and methods
+			// back to the top-level so that they are not lost.
+			// 1) move values
+			r.values = append(r.values, t.values...)
+			// 2) move factory functions
+			for name, f := range t.funcs {
+				r.funcs[name] = f
+			}
+			// 3) move methods
+			for name, m := range t.methods {
+				// don't overwrite functions with the same name - drop them
+				if _, found := r.funcs[name]; !found {
+					r.funcs[name] = m
+				}
+			}
+		}
+		// remove types w/o declaration or which are not visible
+		if t.decl == nil || !visible {
+			delete(r.types, t.name)
+		}
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Sorting
+
+type data struct {
+	n    int
+	swap func(i, j int)
+	less func(i, j int) bool
+}
+
+func (d *data) Len() int           { return d.n }
+func (d *data) Swap(i, j int)      { d.swap(i, j) }
+func (d *data) Less(i, j int) bool { return d.less(i, j) }
+
+// sortBy is a helper function for sorting
+func sortBy(less func(i, j int) bool, swap func(i, j int), n int) {
+	sort.Sort(&data{n, swap, less})
+}
+
+func sortedKeys(m map[string]int) []string {
+	list := make([]string, len(m))
+	i := 0
+	for key := range m {
+		list[i] = key
+		i++
+	}
+	sort.Strings(list)
+	return list
+}
+
+// sortingName returns the name to use when sorting d into place.
+//
+func sortingName(d *ast.GenDecl) string {
+	if len(d.Specs) == 1 {
+		if s, ok := d.Specs[0].(*ast.ValueSpec); ok {
+			return s.Names[0].Name
+		}
+	}
+	return ""
+}
+
+func sortedValues(m []*Value, tok token.Token) []*Value {
+	list := make([]*Value, len(m)) // big enough in any case
+	i := 0
+	for _, val := range m {
+		if val.Decl.Tok == tok {
+			list[i] = val
+			i++
+		}
+	}
+	list = list[0:i]
+
+	sortBy(
+		func(i, j int) bool {
+			if ni, nj := sortingName(list[i].Decl), sortingName(list[j].Decl); ni != nj {
+				return ni < nj
+			}
+			return list[i].order < list[j].order
+		},
+		func(i, j int) { list[i], list[j] = list[j], list[i] },
+		len(list),
+	)
+
+	return list
+}
+
+func sortedTypes(m map[string]*baseType) []*Type {
+	list := make([]*Type, len(m))
+	i := 0
+	for _, t := range m {
+		list[i] = &Type{
+			Doc:     t.doc,
+			Name:    t.name,
+			Decl:    t.decl,
+			Consts:  sortedValues(t.values, token.CONST),
+			Vars:    sortedValues(t.values, token.VAR),
+			Funcs:   sortedFuncs(t.funcs),
+			Methods: sortedFuncs(t.methods),
+		}
+		i++
+	}
+
+	sortBy(
+		func(i, j int) bool { return list[i].Name < list[j].Name },
+		func(i, j int) { list[i], list[j] = list[j], list[i] },
+		len(list),
+	)
+
+	return list
+}
+
+func sortedFuncs(m methodSet) []*Func {
+	list := make([]*Func, len(m))
+	i := 0
+	for _, m := range m {
+		// exclude conflict entries
+		if m.Decl != nil {
+			list[i] = m
+			i++
+		}
+	}
+	list = list[0:i]
+	sortBy(
+		func(i, j int) bool { return list[i].Name < list[j].Name },
+		func(i, j int) { list[i], list[j] = list[j], list[i] },
+		len(list),
+	)
+	return list
+}
diff --git a/src/pkg/go/doc/testdata/a.0.golden b/src/pkg/go/doc/testdata/a.0.golden
new file mode 100644
index 0000000..24db02d
--- /dev/null
+++ b/src/pkg/go/doc/testdata/a.0.golden
@@ -0,0 +1,13 @@
+// comment 0  comment 1 
+PACKAGE a
+
+IMPORTPATH
+	testdata/a
+
+FILENAMES
+	testdata/a0.go
+	testdata/a1.go
+
+BUGS
+	// bug0 
+	// bug1 
diff --git a/src/pkg/go/doc/testdata/a.1.golden b/src/pkg/go/doc/testdata/a.1.golden
new file mode 100644
index 0000000..24db02d
--- /dev/null
+++ b/src/pkg/go/doc/testdata/a.1.golden
@@ -0,0 +1,13 @@
+// comment 0  comment 1 
+PACKAGE a
+
+IMPORTPATH
+	testdata/a
+
+FILENAMES
+	testdata/a0.go
+	testdata/a1.go
+
+BUGS
+	// bug0 
+	// bug1 
diff --git a/src/pkg/go/doc/testdata/a0.go b/src/pkg/go/doc/testdata/a0.go
new file mode 100644
index 0000000..dc55298
--- /dev/null
+++ b/src/pkg/go/doc/testdata/a0.go
@@ -0,0 +1,8 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// comment 0
+package a
+
+//BUG(uid): bug0
diff --git a/src/pkg/go/doc/testdata/a1.go b/src/pkg/go/doc/testdata/a1.go
new file mode 100644
index 0000000..098776c
--- /dev/null
+++ b/src/pkg/go/doc/testdata/a1.go
@@ -0,0 +1,8 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// comment 1
+package a
+
+//BUG(uid): bug1
diff --git a/src/pkg/go/doc/testdata/b.0.golden b/src/pkg/go/doc/testdata/b.0.golden
new file mode 100644
index 0000000..7c33300
--- /dev/null
+++ b/src/pkg/go/doc/testdata/b.0.golden
@@ -0,0 +1,43 @@
+// 
+PACKAGE b
+
+IMPORTPATH
+	testdata/b
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/b.go
+
+CONSTANTS
+	// 
+	const Pi = 3.14	// Pi
+
+
+VARIABLES
+	// 
+	var MaxInt int	// MaxInt
+
+
+FUNCTIONS
+	// 
+	func F(x int) int
+
+	// Always under the package functions list. 
+	func NotAFactory() int
+
+	// Associated with uint type if AllDecls is set. 
+	func UintFactory() uint
+
+
+TYPES
+	// 
+	type T struct{}	// T
+
+	// 
+	var V T	// v
+
+	// 
+	func (x *T) M()
+
diff --git a/src/pkg/go/doc/testdata/b.1.golden b/src/pkg/go/doc/testdata/b.1.golden
new file mode 100644
index 0000000..f303805
--- /dev/null
+++ b/src/pkg/go/doc/testdata/b.1.golden
@@ -0,0 +1,49 @@
+// 
+PACKAGE b
+
+IMPORTPATH
+	testdata/b
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/b.go
+
+CONSTANTS
+	// 
+	const Pi = 3.14	// Pi
+
+
+VARIABLES
+	// 
+	var MaxInt int	// MaxInt
+
+
+FUNCTIONS
+	// 
+	func F(x int) int
+
+	// Always under the package functions list. 
+	func NotAFactory() int
+
+
+TYPES
+	// 
+	type T struct{}	// T
+
+	// 
+	var V T	// v
+
+	// 
+	func (x *T) M()
+
+	// Should only appear if AllDecls is set. 
+	type uint struct{}
+
+	// Associated with uint type if AllDecls is set. 
+	func UintFactory() uint
+
+	// Associated with uint type if AllDecls is set. 
+	func uintFactory() uint
+
diff --git a/src/pkg/go/doc/testdata/b.go b/src/pkg/go/doc/testdata/b.go
new file mode 100644
index 0000000..28660f9
--- /dev/null
+++ b/src/pkg/go/doc/testdata/b.go
@@ -0,0 +1,30 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "a"
+
+// Basic declarations
+
+const Pi = 3.14   // Pi
+var MaxInt int    // MaxInt
+type T struct{}   // T
+var V T           // v
+func F(x int) int {} // F
+func (x *T) M()   {} // M
+
+// Corner cases: association with (presumed) predeclared types
+
+// Always under the package functions list.
+func NotAFactory() int {}
+
+// Associated with uint type if AllDecls is set.
+func UintFactory() uint {}
+
+// Associated with uint type if AllDecls is set.
+func uintFactory() uint {}
+
+// Should only appear if AllDecls is set.
+type uint struct{} // overrides a predeclared type uint
diff --git a/src/pkg/go/doc/testdata/benchmark.go b/src/pkg/go/doc/testdata/benchmark.go
new file mode 100644
index 0000000..0bf567b
--- /dev/null
+++ b/src/pkg/go/doc/testdata/benchmark.go
@@ -0,0 +1,293 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testing
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"runtime"
+	"time"
+)
+
+var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
+var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+
+// An internal type but exported because it is cross-package; part of the implementation
+// of gotest.
+type InternalBenchmark struct {
+	Name string
+	F    func(b *B)
+}
+
+// B is a type passed to Benchmark functions to manage benchmark
+// timing and to specify the number of iterations to run.
+type B struct {
+	common
+	N         int
+	benchmark InternalBenchmark
+	bytes     int64
+	timerOn   bool
+	result    BenchmarkResult
+}
+
+// StartTimer starts timing a test.  This function is called automatically
+// before a benchmark starts, but it can also used to resume timing after
+// a call to StopTimer.
+func (b *B) StartTimer() {
+	if !b.timerOn {
+		b.start = time.Now()
+		b.timerOn = true
+	}
+}
+
+// StopTimer stops timing a test.  This can be used to pause the timer
+// while performing complex initialization that you don't
+// want to measure.
+func (b *B) StopTimer() {
+	if b.timerOn {
+		b.duration += time.Now().Sub(b.start)
+		b.timerOn = false
+	}
+}
+
+// ResetTimer sets the elapsed benchmark time to zero.
+// It does not affect whether the timer is running.
+func (b *B) ResetTimer() {
+	if b.timerOn {
+		b.start = time.Now()
+	}
+	b.duration = 0
+}
+
+// SetBytes records the number of bytes processed in a single operation.
+// If this is called, the benchmark will report ns/op and MB/s.
+func (b *B) SetBytes(n int64) { b.bytes = n }
+
+func (b *B) nsPerOp() int64 {
+	if b.N <= 0 {
+		return 0
+	}
+	return b.duration.Nanoseconds() / int64(b.N)
+}
+
+// runN runs a single benchmark for the specified number of iterations.
+func (b *B) runN(n int) {
+	// Try to get a comparable environment for each run
+	// by clearing garbage from previous runs.
+	runtime.GC()
+	b.N = n
+	b.ResetTimer()
+	b.StartTimer()
+	b.benchmark.F(b)
+	b.StopTimer()
+}
+
+func min(x, y int) int {
+	if x > y {
+		return y
+	}
+	return x
+}
+
+func max(x, y int) int {
+	if x < y {
+		return y
+	}
+	return x
+}
+
+// roundDown10 rounds a number down to the nearest power of 10.
+func roundDown10(n int) int {
+	var tens = 0
+	// tens = floor(log_10(n))
+	for n > 10 {
+		n = n / 10
+		tens++
+	}
+	// result = 10^tens
+	result := 1
+	for i := 0; i < tens; i++ {
+		result *= 10
+	}
+	return result
+}
+
+// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
+func roundUp(n int) int {
+	base := roundDown10(n)
+	if n < (2 * base) {
+		return 2 * base
+	}
+	if n < (5 * base) {
+		return 5 * base
+	}
+	return 10 * base
+}
+
+// run times the benchmark function in a separate goroutine.
+func (b *B) run() BenchmarkResult {
+	go b.launch()
+	<-b.signal
+	return b.result
+}
+
+// launch launches the benchmark function.  It gradually increases the number
+// of benchmark iterations until the benchmark runs for a second in order
+// to get a reasonable measurement.  It prints timing information in this form
+//		testing.BenchmarkHello	100000		19 ns/op
+// launch is run by the fun function as a separate goroutine.
+func (b *B) launch() {
+	// Run the benchmark for a single iteration in case it's expensive.
+	n := 1
+
+	// Signal that we're done whether we return normally
+	// or by FailNow's runtime.Goexit.
+	defer func() {
+		b.signal <- b
+	}()
+
+	b.runN(n)
+	// Run the benchmark for at least the specified amount of time.
+	d := time.Duration(*benchTime * float64(time.Second))
+	for !b.failed && b.duration < d && n < 1e9 {
+		last := n
+		// Predict iterations/sec.
+		if b.nsPerOp() == 0 {
+			n = 1e9
+		} else {
+			n = int(d.Nanoseconds() / b.nsPerOp())
+		}
+		// Run more iterations than we think we'll need for a second (1.5x).
+		// Don't grow too fast in case we had timing errors previously.
+		// Be sure to run at least one more than last time.
+		n = max(min(n+n/2, 100*last), last+1)
+		// Round up to something easy to read.
+		n = roundUp(n)
+		b.runN(n)
+	}
+	b.result = BenchmarkResult{b.N, b.duration, b.bytes}
+}
+
+// The results of a benchmark run.
+type BenchmarkResult struct {
+	N     int           // The number of iterations.
+	T     time.Duration // The total time taken.
+	Bytes int64         // Bytes processed in one iteration.
+}
+
+func (r BenchmarkResult) NsPerOp() int64 {
+	if r.N <= 0 {
+		return 0
+	}
+	return r.T.Nanoseconds() / int64(r.N)
+}
+
+func (r BenchmarkResult) mbPerSec() float64 {
+	if r.Bytes <= 0 || r.T <= 0 || r.N <= 0 {
+		return 0
+	}
+	return (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds()
+}
+
+func (r BenchmarkResult) String() string {
+	mbs := r.mbPerSec()
+	mb := ""
+	if mbs != 0 {
+		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
+	}
+	nsop := r.NsPerOp()
+	ns := fmt.Sprintf("%10d ns/op", nsop)
+	if r.N > 0 && nsop < 100 {
+		// The format specifiers here make sure that
+		// the ones digits line up for all three possible formats.
+		if nsop < 10 {
+			ns = fmt.Sprintf("%13.2f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
+		} else {
+			ns = fmt.Sprintf("%12.1f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
+		}
+	}
+	return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
+}
+
+// An internal function but exported because it is cross-package; part of the implementation
+// of gotest.
+func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
+	// If no flag was specified, don't run benchmarks.
+	if len(*matchBenchmarks) == 0 {
+		return
+	}
+	for _, Benchmark := range benchmarks {
+		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.bench: %s\n", err)
+			os.Exit(1)
+		}
+		if !matched {
+			continue
+		}
+		for _, procs := range cpuList {
+			runtime.GOMAXPROCS(procs)
+			b := &B{
+				common: common{
+					signal: make(chan interface{}),
+				},
+				benchmark: Benchmark,
+			}
+			benchName := Benchmark.Name
+			if procs != 1 {
+				benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
+			}
+			fmt.Printf("%s\t", benchName)
+			r := b.run()
+			if b.failed {
+				// The output could be very long here, but probably isn't.
+				// We print it all, regardless, because we don't want to trim the reason
+				// the benchmark failed.
+				fmt.Printf("--- FAIL: %s\n%s", benchName, b.output)
+				continue
+			}
+			fmt.Printf("%v\n", r)
+			// Unlike with tests, we ignore the -chatty flag and always print output for
+			// benchmarks since the output generation time will skew the results.
+			if len(b.output) > 0 {
+				b.trimOutput()
+				fmt.Printf("--- BENCH: %s\n%s", benchName, b.output)
+			}
+			if p := runtime.GOMAXPROCS(-1); p != procs {
+				fmt.Fprintf(os.Stderr, "testing: %s left GOMAXPROCS set to %d\n", benchName, p)
+			}
+		}
+	}
+}
+
+// trimOutput shortens the output from a benchmark, which can be very long.
+func (b *B) trimOutput() {
+	// The output is likely to appear multiple times because the benchmark
+	// is run multiple times, but at least it will be seen. This is not a big deal
+	// because benchmarks rarely print, but just in case, we trim it if it's too long.
+	const maxNewlines = 10
+	for nlCount, j := 0, 0; j < len(b.output); j++ {
+		if b.output[j] == '\n' {
+			nlCount++
+			if nlCount >= maxNewlines {
+				b.output = append(b.output[:j], "\n\t... [output truncated]\n"...)
+				break
+			}
+		}
+	}
+}
+
+// Benchmark benchmarks a single function. Useful for creating
+// custom benchmarks that do not use gotest.
+func Benchmark(f func(b *B)) BenchmarkResult {
+	b := &B{
+		common: common{
+			signal: make(chan interface{}),
+		},
+		benchmark: InternalBenchmark{"", f},
+	}
+	return b.run()
+}
diff --git a/src/pkg/go/doc/testdata/c.0.golden b/src/pkg/go/doc/testdata/c.0.golden
new file mode 100644
index 0000000..e21959b
--- /dev/null
+++ b/src/pkg/go/doc/testdata/c.0.golden
@@ -0,0 +1,48 @@
+// 
+PACKAGE c
+
+IMPORTPATH
+	testdata/c
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/c.go
+
+TYPES
+	// A (should see this) 
+	type A struct{}
+
+	// B (should see this) 
+	type B struct{}
+
+	// C (should see this) 
+	type C struct{}
+
+	// D (should see this) 
+	type D struct{}
+
+	// E1 (should see this) 
+	type E1 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E2 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E3 struct{}
+
+	// E4 (should see this) 
+	type E4 struct{}
+
+	// 
+	type T1 struct{}
+
+	// 
+	func (t1 *T1) M()
+
+	// T2 must not show methods of local T1 
+	type T2 struct {
+		a.T1	// not the same as locally declared T1
+	}
+
diff --git a/src/pkg/go/doc/testdata/c.1.golden b/src/pkg/go/doc/testdata/c.1.golden
new file mode 100644
index 0000000..e21959b
--- /dev/null
+++ b/src/pkg/go/doc/testdata/c.1.golden
@@ -0,0 +1,48 @@
+// 
+PACKAGE c
+
+IMPORTPATH
+	testdata/c
+
+IMPORTS
+	a
+
+FILENAMES
+	testdata/c.go
+
+TYPES
+	// A (should see this) 
+	type A struct{}
+
+	// B (should see this) 
+	type B struct{}
+
+	// C (should see this) 
+	type C struct{}
+
+	// D (should see this) 
+	type D struct{}
+
+	// E1 (should see this) 
+	type E1 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E2 struct{}
+
+	// E (should see this for E2 and E3) 
+	type E3 struct{}
+
+	// E4 (should see this) 
+	type E4 struct{}
+
+	// 
+	type T1 struct{}
+
+	// 
+	func (t1 *T1) M()
+
+	// T2 must not show methods of local T1 
+	type T2 struct {
+		a.T1	// not the same as locally declared T1
+	}
+
diff --git a/src/pkg/go/doc/testdata/c.go b/src/pkg/go/doc/testdata/c.go
new file mode 100644
index 0000000..e0f3919
--- /dev/null
+++ b/src/pkg/go/doc/testdata/c.go
@@ -0,0 +1,62 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package c
+
+import "a"
+
+// ----------------------------------------------------------------------------
+// Test that empty declarations don't cause problems
+
+const ()
+
+type ()
+
+var ()
+
+// ----------------------------------------------------------------------------
+// Test that types with documentation on both, the Decl and the Spec node
+// are handled correctly.
+
+// A (should see this)
+type A struct{}
+
+// B (should see this)
+type (
+	B struct{}
+)
+
+type (
+	// C (should see this)
+	C struct{}
+)
+
+// D (should not see this)
+type (
+	// D (should see this)
+	D struct{}
+)
+
+// E (should see this for E2 and E3)
+type (
+	// E1 (should see this)
+	E1 struct{}
+	E2 struct{}
+	E3 struct{}
+	// E4 (should see this)
+	E4 struct{}
+)
+
+// ----------------------------------------------------------------------------
+// Test that local and imported types are different when
+// handling anonymous fields.
+
+type T1 struct{}
+
+func (t1 *T1) M() {}
+
+// T2 must not show methods of local T1
+type T2 struct {
+	a.T1 // not the same as locally declared T1
+}
diff --git a/src/pkg/go/doc/testdata/d.0.golden b/src/pkg/go/doc/testdata/d.0.golden
new file mode 100644
index 0000000..c005199
--- /dev/null
+++ b/src/pkg/go/doc/testdata/d.0.golden
@@ -0,0 +1,104 @@
+// 
+PACKAGE d
+
+IMPORTPATH
+	testdata/d
+
+FILENAMES
+	testdata/d1.go
+	testdata/d2.go
+
+CONSTANTS
+	// CBx constants should appear before CAx constants. 
+	const (
+		CB2	= iota	// before CB1
+		CB1		// before CB0
+		CB0		// at end
+	)
+
+	// CAx constants should appear after CBx constants. 
+	const (
+		CA2	= iota	// before CA1
+		CA1		// before CA0
+		CA0		// at end
+	)
+
+	// C0 should be first. 
+	const C0 = 0
+
+	// C1 should be second. 
+	const C1 = 1
+
+	// C2 should be third. 
+	const C2 = 2
+
+	// 
+	const (
+		// Single const declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Cungrouped = 0
+	)
+
+
+VARIABLES
+	// VBx variables should appear before VAx variables. 
+	var (
+		VB2	int	// before VB1
+		VB1	int	// before VB0
+		VB0	int	// at end
+	)
+
+	// VAx variables should appear after VBx variables. 
+	var (
+		VA2	int	// before VA1
+		VA1	int	// before VA0
+		VA0	int	// at end
+	)
+
+	// V0 should be first. 
+	var V0 uintptr
+
+	// V1 should be second. 
+	var V1 uint
+
+	// V2 should be third. 
+	var V2 int
+
+	// 
+	var (
+		// Single var declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Vungrouped = 0
+	)
+
+
+FUNCTIONS
+	// F0 should be first. 
+	func F0()
+
+	// F1 should be second. 
+	func F1()
+
+	// F2 should be third. 
+	func F2()
+
+
+TYPES
+	// T0 should be first. 
+	type T0 struct{}
+
+	// T1 should be second. 
+	type T1 struct{}
+
+	// T2 should be third. 
+	type T2 struct{}
+
+	// TG0 should be first. 
+	type TG0 struct{}
+
+	// TG1 should be second. 
+	type TG1 struct{}
+
+	// TG2 should be third. 
+	type TG2 struct{}
+
diff --git a/src/pkg/go/doc/testdata/d.1.golden b/src/pkg/go/doc/testdata/d.1.golden
new file mode 100644
index 0000000..c005199
--- /dev/null
+++ b/src/pkg/go/doc/testdata/d.1.golden
@@ -0,0 +1,104 @@
+// 
+PACKAGE d
+
+IMPORTPATH
+	testdata/d
+
+FILENAMES
+	testdata/d1.go
+	testdata/d2.go
+
+CONSTANTS
+	// CBx constants should appear before CAx constants. 
+	const (
+		CB2	= iota	// before CB1
+		CB1		// before CB0
+		CB0		// at end
+	)
+
+	// CAx constants should appear after CBx constants. 
+	const (
+		CA2	= iota	// before CA1
+		CA1		// before CA0
+		CA0		// at end
+	)
+
+	// C0 should be first. 
+	const C0 = 0
+
+	// C1 should be second. 
+	const C1 = 1
+
+	// C2 should be third. 
+	const C2 = 2
+
+	// 
+	const (
+		// Single const declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Cungrouped = 0
+	)
+
+
+VARIABLES
+	// VBx variables should appear before VAx variables. 
+	var (
+		VB2	int	// before VB1
+		VB1	int	// before VB0
+		VB0	int	// at end
+	)
+
+	// VAx variables should appear after VBx variables. 
+	var (
+		VA2	int	// before VA1
+		VA1	int	// before VA0
+		VA0	int	// at end
+	)
+
+	// V0 should be first. 
+	var V0 uintptr
+
+	// V1 should be second. 
+	var V1 uint
+
+	// V2 should be third. 
+	var V2 int
+
+	// 
+	var (
+		// Single var declarations inside ()'s are considered ungrouped
+		// and show up in sorted order.
+		Vungrouped = 0
+	)
+
+
+FUNCTIONS
+	// F0 should be first. 
+	func F0()
+
+	// F1 should be second. 
+	func F1()
+
+	// F2 should be third. 
+	func F2()
+
+
+TYPES
+	// T0 should be first. 
+	type T0 struct{}
+
+	// T1 should be second. 
+	type T1 struct{}
+
+	// T2 should be third. 
+	type T2 struct{}
+
+	// TG0 should be first. 
+	type TG0 struct{}
+
+	// TG1 should be second. 
+	type TG1 struct{}
+
+	// TG2 should be third. 
+	type TG2 struct{}
+
diff --git a/src/pkg/go/doc/testdata/d1.go b/src/pkg/go/doc/testdata/d1.go
new file mode 100644
index 0000000..ebd6941
--- /dev/null
+++ b/src/pkg/go/doc/testdata/d1.go
@@ -0,0 +1,57 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test cases for sort order of declarations.
+
+package d
+
+// C2 should be third.
+const C2 = 2
+
+// V2 should be third.
+var V2 int
+
+// CBx constants should appear before CAx constants.
+const (
+	CB2 = iota // before CB1
+	CB1        // before CB0
+	CB0        // at end
+)
+
+// VBx variables should appear before VAx variables.
+var (
+	VB2 int // before VB1
+	VB1 int // before VB0
+	VB0 int // at end
+)
+
+const (
+	// Single const declarations inside ()'s are considered ungrouped
+	// and show up in sorted order.
+	Cungrouped = 0
+)
+
+var (
+	// Single var declarations inside ()'s are considered ungrouped
+	// and show up in sorted order.
+	Vungrouped = 0
+)
+
+// T2 should be third.
+type T2 struct{}
+
+// Grouped types are sorted nevertheless.
+type (
+	// TG2 should be third.
+	TG2 struct{}
+
+	// TG1 should be second.
+	TG1 struct{}
+
+	// TG0 should be first.
+	TG0 struct{}
+)
+
+// F2 should be third.
+func F2() {}
diff --git a/src/pkg/go/doc/testdata/d2.go b/src/pkg/go/doc/testdata/d2.go
new file mode 100644
index 0000000..2f56f4f
--- /dev/null
+++ b/src/pkg/go/doc/testdata/d2.go
@@ -0,0 +1,45 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test cases for sort order of declarations.
+
+package d
+
+// C1 should be second.
+const C1 = 1
+
+// C0 should be first.
+const C0 = 0
+
+// V1 should be second.
+var V1 uint
+
+// V0 should be first.
+var V0 uintptr
+
+// CAx constants should appear after CBx constants.
+const (
+	CA2 = iota // before CA1
+	CA1        // before CA0
+	CA0        // at end
+)
+
+// VAx variables should appear after VBx variables.
+var (
+	VA2 int // before VA1
+	VA1 int // before VA0
+	VA0 int // at end
+)
+
+// T1 should be second.
+type T1 struct{}
+
+// T0 should be first.
+type T0 struct{}
+
+// F1 should be second.
+func F1() {}
+
+// F0 should be first.
+func F0() {}
diff --git a/src/pkg/go/doc/testdata/e.0.golden b/src/pkg/go/doc/testdata/e.0.golden
new file mode 100644
index 0000000..3b128f7
--- /dev/null
+++ b/src/pkg/go/doc/testdata/e.0.golden
@@ -0,0 +1,31 @@
+// 
+PACKAGE e
+
+IMPORTPATH
+	testdata/e
+
+FILENAMES
+	testdata/e.go
+
+TYPES
+	// T1 has no (top-level) M method due to conflict. 
+	type T1 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T2 has only M as top-level method. 
+	type T2 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T2.M should appear as method of T2. 
+	func (T2) M()
+
+	// T3 has only M as top-level method. 
+	type T3 struct {
+		// contains filtered or unexported fields
+	}
+
+	// T3.M should appear as method of T3. 
+	func (T3) M()
+
diff --git a/src/pkg/go/doc/testdata/e.1.golden b/src/pkg/go/doc/testdata/e.1.golden
new file mode 100644
index 0000000..d05602d
--- /dev/null
+++ b/src/pkg/go/doc/testdata/e.1.golden
@@ -0,0 +1,61 @@
+// 
+PACKAGE e
+
+IMPORTPATH
+	testdata/e
+
+FILENAMES
+	testdata/e.go
+
+TYPES
+	// T1 has no (top-level) M method due to conflict. 
+	type T1 struct {
+		t1
+		t2
+	}
+
+	// T2 has only M as top-level method. 
+	type T2 struct {
+		t1
+	}
+
+	// T2.M should appear as method of T2. 
+	func (T2) M()
+
+	// T3 has only M as top-level method. 
+	type T3 struct {
+		t1e
+		t2e
+	}
+
+	// T3.M should appear as method of T3. 
+	func (T3) M()
+
+	// 
+	type t1 struct{}
+
+	// t1.M should not appear as method in a Tx type. 
+	func (t1) M()
+
+	// 
+	type t1e struct {
+		t1
+	}
+
+	// t1.M should not appear as method in a Tx type. 
+	func (t1e) M()
+
+	// 
+	type t2 struct{}
+
+	// t2.M should not appear as method in a Tx type. 
+	func (t2) M()
+
+	// 
+	type t2e struct {
+		t2
+	}
+
+	// t2.M should not appear as method in a Tx type. 
+	func (t2e) M()
+
diff --git a/src/pkg/go/doc/testdata/e.go b/src/pkg/go/doc/testdata/e.go
new file mode 100644
index 0000000..8ea6a83
--- /dev/null
+++ b/src/pkg/go/doc/testdata/e.go
@@ -0,0 +1,58 @@
+// Copyright 2011 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.
+
+// Embedding tests.
+// TODO(gri): This should be comprehensive.
+
+package e
+
+// ----------------------------------------------------------------------------
+// Conflicting methods M must not show up.
+
+type t1 struct{}
+
+// t1.M should not appear as method in a Tx type.
+func (t1) M() {}
+
+type t2 struct{}
+
+// t2.M should not appear as method in a Tx type.
+func (t2) M() {}
+
+// T1 has no (top-level) M method due to conflict.
+type T1 struct {
+	t1
+	t2
+}
+
+// ----------------------------------------------------------------------------
+// Higher-level method M wins over lower-level method M.
+
+// T2 has only M as top-level method.
+type T2 struct {
+	t1
+}
+
+// T2.M should appear as method of T2.
+func (T2) M() {}
+
+// ----------------------------------------------------------------------------
+// Higher-level method M wins over lower-level conflicting methods M.
+
+type t1e struct {
+	t1
+}
+
+type t2e struct {
+	t2
+}
+
+// T3 has only M as top-level method.
+type T3 struct {
+	t1e
+	t2e
+}
+
+// T3.M should appear as method of T3.
+func (T3) M() {}
diff --git a/src/pkg/go/doc/testdata/example.go b/src/pkg/go/doc/testdata/example.go
new file mode 100644
index 0000000..fdeda13
--- /dev/null
+++ b/src/pkg/go/doc/testdata/example.go
@@ -0,0 +1,81 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testing
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"time"
+)
+
+type InternalExample struct {
+	Name   string
+	F      func()
+	Output string
+}
+
+func RunExamples(examples []InternalExample) (ok bool) {
+	ok = true
+
+	var eg InternalExample
+
+	stdout, stderr := os.Stdout, os.Stderr
+	defer func() {
+		os.Stdout, os.Stderr = stdout, stderr
+		if e := recover(); e != nil {
+			fmt.Printf("--- FAIL: %s\npanic: %v\n", eg.Name, e)
+			os.Exit(1)
+		}
+	}()
+
+	for _, eg = range examples {
+		if *chatty {
+			fmt.Printf("=== RUN: %s\n", eg.Name)
+		}
+
+		// capture stdout and stderr
+		r, w, err := os.Pipe()
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			os.Exit(1)
+		}
+		os.Stdout, os.Stderr = w, w
+		outC := make(chan string)
+		go func() {
+			buf := new(bytes.Buffer)
+			_, err := io.Copy(buf, r)
+			if err != nil {
+				fmt.Fprintf(stderr, "testing: copying pipe: %v\n", err)
+				os.Exit(1)
+			}
+			outC <- buf.String()
+		}()
+
+		// run example
+		t0 := time.Now()
+		eg.F()
+		dt := time.Now().Sub(t0)
+
+		// close pipe, restore stdout/stderr, get output
+		w.Close()
+		os.Stdout, os.Stderr = stdout, stderr
+		out := <-outC
+
+		// report any errors
+		tstr := fmt.Sprintf("(%.2f seconds)", dt.Seconds())
+		if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e {
+			fmt.Printf("--- FAIL: %s %s\ngot:\n%s\nwant:\n%s\n",
+				eg.Name, tstr, g, e)
+			ok = false
+		} else if *chatty {
+			fmt.Printf("--- PASS: %s %s\n", eg.Name, tstr)
+		}
+	}
+
+	return
+}
diff --git a/src/pkg/go/doc/testdata/template.txt b/src/pkg/go/doc/testdata/template.txt
new file mode 100644
index 0000000..32e331c
--- /dev/null
+++ b/src/pkg/go/doc/testdata/template.txt
@@ -0,0 +1,65 @@
+{{synopsis .Doc}}
+PACKAGE {{.Name}}
+
+IMPORTPATH
+	{{.ImportPath}}
+
+{{with .Imports}}IMPORTS
+{{range .}}	{{.}}
+{{end}}
+{{end}}{{/*
+
+*/}}FILENAMES
+{{range .Filenames}}	{{.}}
+{{end}}{{/*
+
+*/}}{{with .Consts}}
+CONSTANTS
+{{range .}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{end}}{{/*
+
+*/}}{{with .Vars}}
+VARIABLES
+{{range .}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{end}}{{/*
+
+*/}}{{with .Funcs}}
+FUNCTIONS
+{{range .}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{end}}{{/*
+
+*/}}{{with .Types}}
+TYPES
+{{range .}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{range .Consts}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{/*
+
+*/}}{{range .Vars}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{/*
+
+*/}}{{range .Funcs}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{/*
+
+*/}}{{range .Methods}}	{{synopsis .Doc}}
+	{{node .Decl $.FSet}}
+
+{{end}}{{end}}{{end}}{{/*
+
+*/}}{{with .Bugs}}
+BUGS
+{{range .}}	{{synopsis .}}
+{{end}}{{end}}
\ No newline at end of file
diff --git a/src/pkg/go/doc/testdata/testing.0.golden b/src/pkg/go/doc/testdata/testing.0.golden
new file mode 100644
index 0000000..15a9039
--- /dev/null
+++ b/src/pkg/go/doc/testdata/testing.0.golden
@@ -0,0 +1,156 @@
+// Package testing provides support for automated testing of Go ...
+PACKAGE testing
+
+IMPORTPATH
+	testdata/testing
+
+IMPORTS
+	bytes
+	flag
+	fmt
+	io
+	os
+	runtime
+	runtime/pprof
+	strconv
+	strings
+	time
+
+FILENAMES
+	testdata/benchmark.go
+	testdata/example.go
+	testdata/testing.go
+
+FUNCTIONS
+	// An internal function but exported because it is cross-package; ...
+	func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)
+
+	// An internal function but exported because it is cross-package; ...
+	func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)
+
+	// 
+	func RunExamples(examples []InternalExample) (ok bool)
+
+	// 
+	func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)
+
+	// Short reports whether the -test.short flag is set. 
+	func Short() bool
+
+
+TYPES
+	// B is a type passed to Benchmark functions to manage benchmark ...
+	type B struct {
+		N int
+		// contains filtered or unexported fields
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *B) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *B) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *B) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *B) FailNow()
+
+	// Failed returns whether the function has failed. 
+	func (c *B) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *B) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *B) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *B) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *B) Logf(format string, args ...interface{})
+
+	// ResetTimer sets the elapsed benchmark time to zero. It does not ...
+	func (b *B) ResetTimer()
+
+	// SetBytes records the number of bytes processed in a single ...
+	func (b *B) SetBytes(n int64)
+
+	// StartTimer starts timing a test.  This function is called ...
+	func (b *B) StartTimer()
+
+	// StopTimer stops timing a test.  This can be used to pause the ...
+	func (b *B) StopTimer()
+
+	// The results of a benchmark run. 
+	type BenchmarkResult struct {
+		N	int		// The number of iterations.
+		T	time.Duration	// The total time taken.
+		Bytes	int64		// Bytes processed in one iteration.
+	}
+
+	// Benchmark benchmarks a single function. Useful for creating ...
+	func Benchmark(f func(b *B)) BenchmarkResult
+
+	// 
+	func (r BenchmarkResult) NsPerOp() int64
+
+	// 
+	func (r BenchmarkResult) String() string
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalBenchmark struct {
+		Name	string
+		F	func(b *B)
+	}
+
+	// 
+	type InternalExample struct {
+		Name	string
+		F	func()
+		Output	string
+	}
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalTest struct {
+		Name	string
+		F	func(*T)
+	}
+
+	// T is a type passed to Test functions to manage test state and ...
+	type T struct {
+		// contains filtered or unexported fields
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *T) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *T) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *T) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *T) FailNow()
+
+	// Failed returns whether the function has failed. 
+	func (c *T) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *T) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *T) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *T) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *T) Logf(format string, args ...interface{})
+
+	// Parallel signals that this test is to be run in parallel with ...
+	func (t *T) Parallel()
+
diff --git a/src/pkg/go/doc/testdata/testing.1.golden b/src/pkg/go/doc/testdata/testing.1.golden
new file mode 100644
index 0000000..1f92f8f
--- /dev/null
+++ b/src/pkg/go/doc/testdata/testing.1.golden
@@ -0,0 +1,298 @@
+// Package testing provides support for automated testing of Go ...
+PACKAGE testing
+
+IMPORTPATH
+	testdata/testing
+
+IMPORTS
+	bytes
+	flag
+	fmt
+	io
+	os
+	runtime
+	runtime/pprof
+	strconv
+	strings
+	time
+
+FILENAMES
+	testdata/benchmark.go
+	testdata/example.go
+	testdata/testing.go
+
+VARIABLES
+	// 
+	var (
+		// The short flag requests that tests run more quickly, but its functionality
+		// is provided by test writers themselves.  The testing package is just its
+		// home.  The all.bash installation script sets it to make installation more
+		// efficient, but by default the flag is off so a plain "gotest" will do a
+		// full test of the package.
+		short	= flag.Bool("test.short", false, "run smaller test suite to save time")
+	
+		// Report as tests are run; default is silent for success.
+		chatty		= flag.Bool("test.v", false, "verbose: print additional output")
+		match		= flag.String("test.run", "", "regular expression to select tests to run")
+		memProfile	= flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+		memProfileRate	= flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+		cpuProfile	= flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+		timeout		= flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+		cpuListStr	= flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+		parallel	= flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+	
+		cpuList	[]int
+	)
+
+	// 
+	var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+
+	// 
+	var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
+
+	// 
+	var timer *time.Timer
+
+
+FUNCTIONS
+	// An internal function but exported because it is cross-package; ...
+	func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)
+
+	// An internal function but exported because it is cross-package; ...
+	func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)
+
+	// 
+	func RunExamples(examples []InternalExample) (ok bool)
+
+	// 
+	func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)
+
+	// Short reports whether the -test.short flag is set. 
+	func Short() bool
+
+	// after runs after all testing. 
+	func after()
+
+	// alarm is called if the timeout expires. 
+	func alarm()
+
+	// before runs before all testing. 
+	func before()
+
+	// decorate inserts the final newline if needed and indentation ...
+	func decorate(s string, addFileLine bool) string
+
+	// 
+	func max(x, y int) int
+
+	// 
+	func min(x, y int) int
+
+	// 
+	func parseCpuList()
+
+	// roundDown10 rounds a number down to the nearest power of 10. 
+	func roundDown10(n int) int
+
+	// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX]. 
+	func roundUp(n int) int
+
+	// startAlarm starts an alarm if requested. 
+	func startAlarm()
+
+	// stopAlarm turns off the alarm. 
+	func stopAlarm()
+
+	// 
+	func tRunner(t *T, test *InternalTest)
+
+
+TYPES
+	// B is a type passed to Benchmark functions to manage benchmark ...
+	type B struct {
+		common
+		N		int
+		benchmark	InternalBenchmark
+		bytes		int64
+		timerOn		bool
+		result		BenchmarkResult
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *B) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *B) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *B) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *B) FailNow()
+
+	// Failed returns whether the function has failed. 
+	func (c *B) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *B) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *B) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *B) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *B) Logf(format string, args ...interface{})
+
+	// ResetTimer sets the elapsed benchmark time to zero. It does not ...
+	func (b *B) ResetTimer()
+
+	// SetBytes records the number of bytes processed in a single ...
+	func (b *B) SetBytes(n int64)
+
+	// StartTimer starts timing a test.  This function is called ...
+	func (b *B) StartTimer()
+
+	// StopTimer stops timing a test.  This can be used to pause the ...
+	func (b *B) StopTimer()
+
+	// launch launches the benchmark function.  It gradually increases ...
+	func (b *B) launch()
+
+	// log generates the output. It's always at the same stack depth. 
+	func (c *B) log(s string)
+
+	// 
+	func (b *B) nsPerOp() int64
+
+	// run times the benchmark function in a separate goroutine. 
+	func (b *B) run() BenchmarkResult
+
+	// runN runs a single benchmark for the specified number of ...
+	func (b *B) runN(n int)
+
+	// trimOutput shortens the output from a benchmark, which can be ...
+	func (b *B) trimOutput()
+
+	// The results of a benchmark run. 
+	type BenchmarkResult struct {
+		N	int		// The number of iterations.
+		T	time.Duration	// The total time taken.
+		Bytes	int64		// Bytes processed in one iteration.
+	}
+
+	// Benchmark benchmarks a single function. Useful for creating ...
+	func Benchmark(f func(b *B)) BenchmarkResult
+
+	// 
+	func (r BenchmarkResult) NsPerOp() int64
+
+	// 
+	func (r BenchmarkResult) String() string
+
+	// 
+	func (r BenchmarkResult) mbPerSec() float64
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalBenchmark struct {
+		Name	string
+		F	func(b *B)
+	}
+
+	// 
+	type InternalExample struct {
+		Name	string
+		F	func()
+		Output	string
+	}
+
+	// An internal type but exported because it is cross-package; part ...
+	type InternalTest struct {
+		Name	string
+		F	func(*T)
+	}
+
+	// T is a type passed to Test functions to manage test state and ...
+	type T struct {
+		common
+		name		string		// Name of test.
+		startParallel	chan bool	// Parallel tests will wait on this.
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *T) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *T) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *T) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *T) FailNow()
+
+	// Failed returns whether the function has failed. 
+	func (c *T) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *T) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *T) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *T) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *T) Logf(format string, args ...interface{})
+
+	// Parallel signals that this test is to be run in parallel with ...
+	func (t *T) Parallel()
+
+	// log generates the output. It's always at the same stack depth. 
+	func (c *T) log(s string)
+
+	// 
+	func (t *T) report()
+
+	// common holds the elements common between T and B and captures ...
+	type common struct {
+		output		[]byte		// Output generated by test or benchmark.
+		failed		bool		// Test or benchmark has failed.
+		start		time.Time	// Time test or benchmark started
+		duration	time.Duration
+		self		interface{}		// To be sent on signal channel when done.
+		signal		chan interface{}	// Output for serial tests.
+	}
+
+	// Error is equivalent to Log() followed by Fail(). 
+	func (c *common) Error(args ...interface{})
+
+	// Errorf is equivalent to Logf() followed by Fail(). 
+	func (c *common) Errorf(format string, args ...interface{})
+
+	// Fail marks the function as having failed but continues ...
+	func (c *common) Fail()
+
+	// FailNow marks the function as having failed and stops its ...
+	func (c *common) FailNow()
+
+	// Failed returns whether the function has failed. 
+	func (c *common) Failed() bool
+
+	// Fatal is equivalent to Log() followed by FailNow(). 
+	func (c *common) Fatal(args ...interface{})
+
+	// Fatalf is equivalent to Logf() followed by FailNow(). 
+	func (c *common) Fatalf(format string, args ...interface{})
+
+	// Log formats its arguments using default formatting, analogous ...
+	func (c *common) Log(args ...interface{})
+
+	// Logf formats its arguments according to the format, analogous ...
+	func (c *common) Logf(format string, args ...interface{})
+
+	// log generates the output. It's always at the same stack depth. 
+	func (c *common) log(s string)
+
diff --git a/src/pkg/go/doc/testdata/testing.go b/src/pkg/go/doc/testdata/testing.go
new file mode 100644
index 0000000..cfe212d
--- /dev/null
+++ b/src/pkg/go/doc/testdata/testing.go
@@ -0,0 +1,404 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package testing provides support for automated testing of Go packages.
+// It is intended to be used in concert with the ``gotest'' utility, which automates
+// execution of any function of the form
+//     func TestXxx(*testing.T)
+// where Xxx can be any alphanumeric string (but the first letter must not be in
+// [a-z]) and serves to identify the test routine.
+// These TestXxx routines should be declared within the package they are testing.
+//
+// Functions of the form
+//     func BenchmarkXxx(*testing.B)
+// are considered benchmarks, and are executed by gotest when the -test.bench
+// flag is provided.
+//
+// A sample benchmark function looks like this:
+//     func BenchmarkHello(b *testing.B) {
+//         for i := 0; i < b.N; i++ {
+//             fmt.Sprintf("hello")
+//         }
+//     }
+// The benchmark package will vary b.N until the benchmark function lasts
+// long enough to be timed reliably.  The output
+//     testing.BenchmarkHello    10000000    282 ns/op
+// means that the loop ran 10000000 times at a speed of 282 ns per loop.
+//
+// If a benchmark needs some expensive setup before running, the timer
+// may be stopped:
+//     func BenchmarkBigLen(b *testing.B) {
+//         b.StopTimer()
+//         big := NewBig()
+//         b.StartTimer()
+//         for i := 0; i < b.N; i++ {
+//             big.Len()
+//         }
+//     }
+package testing
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"runtime"
+	"runtime/pprof"
+	"strconv"
+	"strings"
+	"time"
+)
+
+var (
+	// The short flag requests that tests run more quickly, but its functionality
+	// is provided by test writers themselves.  The testing package is just its
+	// home.  The all.bash installation script sets it to make installation more
+	// efficient, but by default the flag is off so a plain "gotest" will do a
+	// full test of the package.
+	short = flag.Bool("test.short", false, "run smaller test suite to save time")
+
+	// Report as tests are run; default is silent for success.
+	chatty         = flag.Bool("test.v", false, "verbose: print additional output")
+	match          = flag.String("test.run", "", "regular expression to select tests to run")
+	memProfile     = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+	memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+	cpuProfile     = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+	timeout        = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+	cpuListStr     = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+	parallel       = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+
+	cpuList []int
+)
+
+// common holds the elements common between T and B and
+// captures common methods such as Errorf.
+type common struct {
+	output   []byte    // Output generated by test or benchmark.
+	failed   bool      // Test or benchmark has failed.
+	start    time.Time // Time test or benchmark started
+	duration time.Duration
+	self     interface{}      // To be sent on signal channel when done.
+	signal   chan interface{} // Output for serial tests.
+}
+
+// Short reports whether the -test.short flag is set.
+func Short() bool {
+	return *short
+}
+
+// decorate inserts the final newline if needed and indentation tabs for formatting.
+// If addFileLine is true, it also prefixes the string with the file and line of the call site.
+func decorate(s string, addFileLine bool) string {
+	if addFileLine {
+		_, file, line, ok := runtime.Caller(3) // decorate + log + public function.
+		if ok {
+			// Truncate file name at last file name separator.
+			if index := strings.LastIndex(file, "/"); index >= 0 {
+				file = file[index+1:]
+			} else if index = strings.LastIndex(file, "\\"); index >= 0 {
+				file = file[index+1:]
+			}
+		} else {
+			file = "???"
+			line = 1
+		}
+		s = fmt.Sprintf("%s:%d: %s", file, line, s)
+	}
+	s = "\t" + s // Every line is indented at least one tab.
+	n := len(s)
+	if n > 0 && s[n-1] != '\n' {
+		s += "\n"
+		n++
+	}
+	for i := 0; i < n-1; i++ { // -1 to avoid final newline
+		if s[i] == '\n' {
+			// Second and subsequent lines are indented an extra tab.
+			return s[0:i+1] + "\t" + decorate(s[i+1:n], false)
+		}
+	}
+	return s
+}
+
+// T is a type passed to Test functions to manage test state and support formatted test logs.
+// Logs are accumulated during execution and dumped to standard error when done.
+type T struct {
+	common
+	name          string    // Name of test.
+	startParallel chan bool // Parallel tests will wait on this.
+}
+
+// Fail marks the function as having failed but continues execution.
+func (c *common) Fail() { c.failed = true }
+
+// Failed returns whether the function has failed.
+func (c *common) Failed() bool { return c.failed }
+
+// FailNow marks the function as having failed and stops its execution.
+// Execution will continue at the next Test.
+func (c *common) FailNow() {
+	c.Fail()
+
+	// Calling runtime.Goexit will exit the goroutine, which
+	// will run the deferred functions in this goroutine,
+	// which will eventually run the deferred lines in tRunner,
+	// which will signal to the test loop that this test is done.
+	//
+	// A previous version of this code said:
+	//
+	//	c.duration = ...
+	//	c.signal <- c.self
+	//	runtime.Goexit()
+	//
+	// This previous version duplicated code (those lines are in
+	// tRunner no matter what), but worse the goroutine teardown
+	// implicit in runtime.Goexit was not guaranteed to complete
+	// before the test exited.  If a test deferred an important cleanup
+	// function (like removing temporary files), there was no guarantee
+	// it would run on a test failure.  Because we send on c.signal during
+	// a top-of-stack deferred function now, we know that the send
+	// only happens after any other stacked defers have completed.
+	runtime.Goexit()
+}
+
+// log generates the output. It's always at the same stack depth.
+func (c *common) log(s string) {
+	c.output = append(c.output, decorate(s, true)...)
+}
+
+// Log formats its arguments using default formatting, analogous to Println(),
+// and records the text in the error log.
+func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
+
+// Logf formats its arguments according to the format, analogous to Printf(),
+// and records the text in the error log.
+func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
+
+// Error is equivalent to Log() followed by Fail().
+func (c *common) Error(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.Fail()
+}
+
+// Errorf is equivalent to Logf() followed by Fail().
+func (c *common) Errorf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.Fail()
+}
+
+// Fatal is equivalent to Log() followed by FailNow().
+func (c *common) Fatal(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.FailNow()
+}
+
+// Fatalf is equivalent to Logf() followed by FailNow().
+func (c *common) Fatalf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.FailNow()
+}
+
+// Parallel signals that this test is to be run in parallel with (and only with) 
+// other parallel tests in this CPU group.
+func (t *T) Parallel() {
+	t.signal <- (*T)(nil) // Release main testing loop
+	<-t.startParallel     // Wait for serial tests to finish
+}
+
+// An internal type but exported because it is cross-package; part of the implementation
+// of gotest.
+type InternalTest struct {
+	Name string
+	F    func(*T)
+}
+
+func tRunner(t *T, test *InternalTest) {
+	t.start = time.Now()
+
+	// When this goroutine is done, either because test.F(t)
+	// returned normally or because a test failure triggered 
+	// a call to runtime.Goexit, record the duration and send
+	// a signal saying that the test is done.
+	defer func() {
+		t.duration = time.Now().Sub(t.start)
+		t.signal <- t
+	}()
+
+	test.F(t)
+}
+
+// An internal function but exported because it is cross-package; part of the implementation
+// of gotest.
+func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
+	flag.Parse()
+	parseCpuList()
+
+	before()
+	startAlarm()
+	testOk := RunTests(matchString, tests)
+	exampleOk := RunExamples(examples)
+	if !testOk || !exampleOk {
+		fmt.Println("FAIL")
+		os.Exit(1)
+	}
+	fmt.Println("PASS")
+	stopAlarm()
+	RunBenchmarks(matchString, benchmarks)
+	after()
+}
+
+func (t *T) report() {
+	tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
+	format := "--- %s: %s %s\n%s"
+	if t.failed {
+		fmt.Printf(format, "FAIL", t.name, tstr, t.output)
+	} else if *chatty {
+		fmt.Printf(format, "PASS", t.name, tstr, t.output)
+	}
+}
+
+func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
+	ok = true
+	if len(tests) == 0 {
+		fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
+		return
+	}
+	for _, procs := range cpuList {
+		runtime.GOMAXPROCS(procs)
+		// We build a new channel tree for each run of the loop.
+		// collector merges in one channel all the upstream signals from parallel tests.
+		// If all tests pump to the same channel, a bug can occur where a test
+		// kicks off a goroutine that Fails, yet the test still delivers a completion signal,
+		// which skews the counting.
+		var collector = make(chan interface{})
+
+		numParallel := 0
+		startParallel := make(chan bool)
+
+		for i := 0; i < len(tests); i++ {
+			matched, err := matchString(*match, tests[i].Name)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
+				os.Exit(1)
+			}
+			if !matched {
+				continue
+			}
+			testName := tests[i].Name
+			if procs != 1 {
+				testName = fmt.Sprintf("%s-%d", tests[i].Name, procs)
+			}
+			t := &T{
+				common: common{
+					signal: make(chan interface{}),
+				},
+				name:          testName,
+				startParallel: startParallel,
+			}
+			t.self = t
+			if *chatty {
+				fmt.Printf("=== RUN %s\n", t.name)
+			}
+			go tRunner(t, &tests[i])
+			out := (<-t.signal).(*T)
+			if out == nil { // Parallel run.
+				go func() {
+					collector <- <-t.signal
+				}()
+				numParallel++
+				continue
+			}
+			t.report()
+			ok = ok && !out.failed
+		}
+
+		running := 0
+		for numParallel+running > 0 {
+			if running < *parallel && numParallel > 0 {
+				startParallel <- true
+				running++
+				numParallel--
+				continue
+			}
+			t := (<-collector).(*T)
+			t.report()
+			ok = ok && !t.failed
+			running--
+		}
+	}
+	return
+}
+
+// before runs before all testing.
+func before() {
+	if *memProfileRate > 0 {
+		runtime.MemProfileRate = *memProfileRate
+	}
+	if *cpuProfile != "" {
+		f, err := os.Create(*cpuProfile)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: %s", err)
+			return
+		}
+		if err := pprof.StartCPUProfile(f); err != nil {
+			fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err)
+			f.Close()
+			return
+		}
+		// Could save f so after can call f.Close; not worth the effort.
+	}
+
+}
+
+// after runs after all testing.
+func after() {
+	if *cpuProfile != "" {
+		pprof.StopCPUProfile() // flushes profile to disk
+	}
+	if *memProfile != "" {
+		f, err := os.Create(*memProfile)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "testing: %s", err)
+			return
+		}
+		if err = pprof.WriteHeapProfile(f); err != nil {
+			fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err)
+		}
+		f.Close()
+	}
+}
+
+var timer *time.Timer
+
+// startAlarm starts an alarm if requested.
+func startAlarm() {
+	if *timeout > 0 {
+		timer = time.AfterFunc(*timeout, alarm)
+	}
+}
+
+// stopAlarm turns off the alarm.
+func stopAlarm() {
+	if *timeout > 0 {
+		timer.Stop()
+	}
+}
+
+// alarm is called if the timeout expires.
+func alarm() {
+	panic("test timed out")
+}
+
+func parseCpuList() {
+	if len(*cpuListStr) == 0 {
+		cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
+	} else {
+		for _, val := range strings.Split(*cpuListStr, ",") {
+			cpu, err := strconv.Atoi(val)
+			if err != nil || cpu <= 0 {
+				fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu", val)
+				os.Exit(1)
+			}
+			cpuList = append(cpuList, cpu)
+		}
+	}
+}
diff --git a/src/pkg/go/parser/interface.go b/src/pkg/go/parser/interface.go
index 4f980fc..f1b4ce3 100644
--- a/src/pkg/go/parser/interface.go
+++ b/src/pkg/go/parser/interface.go
@@ -8,8 +8,8 @@ package parser
 
 import (
 	"bytes"
+	"errors"
 	"go/ast"
-	"go/scanner"
 	"go/token"
 	"io"
 	"io/ioutil"
@@ -21,7 +21,7 @@ import (
 // otherwise it returns an error. If src == nil, readSource returns
 // the result of reading the file specified by filename.
 //
-func readSource(filename string, src interface{}) ([]byte, os.Error) {
+func readSource(filename string, src interface{}) ([]byte, error) {
 	if src != nil {
 		switch s := src.(type) {
 		case string:
@@ -35,86 +35,30 @@ func readSource(filename string, src interface{}) ([]byte, os.Error) {
 			}
 		case io.Reader:
 			var buf bytes.Buffer
-			_, err := io.Copy(&buf, s)
-			if err != nil {
+			if _, err := io.Copy(&buf, s); err != nil {
 				return nil, err
 			}
 			return buf.Bytes(), nil
-		default:
-			return nil, os.NewError("invalid source")
 		}
+		return nil, errors.New("invalid source")
 	}
-
 	return ioutil.ReadFile(filename)
 }
 
-func (p *parser) errors() os.Error {
-	mode := scanner.Sorted
-	if p.mode&SpuriousErrors == 0 {
-		mode = scanner.NoMultiples
-	}
-	return p.GetError(mode)
-}
-
-// ParseExpr parses a Go expression and returns the corresponding
-// AST node. The fset, filename, and src arguments have the same interpretation
-// as for ParseFile. If there is an error, the result expression
-// may be nil or contain a partial AST.
-//
-func ParseExpr(fset *token.FileSet, filename string, src interface{}) (ast.Expr, os.Error) {
-	data, err := readSource(filename, src)
-	if err != nil {
-		return nil, err
-	}
-
-	var p parser
-	p.init(fset, filename, data, 0)
-	x := p.parseRhs()
-	if p.tok == token.SEMICOLON {
-		p.next() // consume automatically inserted semicolon, if any
-	}
-	p.expect(token.EOF)
-
-	return x, p.errors()
-}
-
-// ParseStmtList parses a list of Go statements and returns the list
-// of corresponding AST nodes. The fset, filename, and src arguments have the same
-// interpretation as for ParseFile. If there is an error, the node
-// list may be nil or contain partial ASTs.
+// A Mode value is a set of flags (or 0).
+// They control the amount of source code parsed and other optional
+// parser functionality.
 //
-func ParseStmtList(fset *token.FileSet, filename string, src interface{}) ([]ast.Stmt, os.Error) {
-	data, err := readSource(filename, src)
-	if err != nil {
-		return nil, err
-	}
-
-	var p parser
-	p.init(fset, filename, data, 0)
-	list := p.parseStmtList()
-	p.expect(token.EOF)
-
-	return list, p.errors()
-}
-
-// ParseDeclList parses a list of Go declarations and returns the list
-// of corresponding AST nodes. The fset, filename, and src arguments have the same
-// interpretation as for ParseFile. If there is an error, the node
-// list may be nil or contain partial ASTs.
-//
-func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast.Decl, os.Error) {
-	data, err := readSource(filename, src)
-	if err != nil {
-		return nil, err
-	}
-
-	var p parser
-	p.init(fset, filename, data, 0)
-	list := p.parseDeclList()
-	p.expect(token.EOF)
-
-	return list, p.errors()
-}
+type Mode uint
+
+const (
+	PackageClauseOnly Mode = 1 << iota // parsing stops after package clause
+	ImportsOnly                        // parsing stops after import declarations
+	ParseComments                      // parse comments and add them to AST
+	Trace                              // print a trace of parsed productions
+	DeclarationErrors                  // report declaration errors
+	SpuriousErrors                     // report all (not just the first) errors per line
+)
 
 // ParseFile parses the source code of a single Go source file and returns
 // the corresponding ast.File node. The source code may be provided via
@@ -123,7 +67,6 @@ func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast
 // If src != nil, ParseFile parses the source from src and the filename is
 // only used when recording position information. The type of the argument
 // for the src parameter must be string, []byte, or io.Reader.
-//
 // If src == nil, ParseFile parses the file specified by filename.
 //
 // The mode parameter controls the amount of source text parsed and other
@@ -132,49 +75,18 @@ func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast
 //
 // If the source couldn't be read, the returned AST is nil and the error
 // indicates the specific failure. If the source was read but syntax
-// errors were found, the result is a partial AST (with ast.BadX nodes
+// errors were found, the result is a partial AST (with ast.Bad* nodes
 // representing the fragments of erroneous source code). Multiple errors
 // are returned via a scanner.ErrorList which is sorted by file position.
 //
-func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint) (*ast.File, os.Error) {
-	data, err := readSource(filename, src)
+func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (*ast.File, error) {
+	text, err := readSource(filename, src)
 	if err != nil {
 		return nil, err
 	}
-
 	var p parser
-	p.init(fset, filename, data, mode)
-	file := p.parseFile() // parseFile reads to EOF
-
-	return file, p.errors()
-}
-
-// ParseFiles calls ParseFile for each file in the filenames list and returns
-// a map of package name -> package AST with all the packages found. The mode
-// bits are passed to ParseFile unchanged. Position information is recorded
-// in the file set fset.
-//
-// Files with parse errors are ignored. In this case the map of packages may
-// be incomplete (missing packages and/or incomplete packages) and the first
-// error encountered is returned.
-//
-func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[string]*ast.Package, first os.Error) {
-	pkgs = make(map[string]*ast.Package)
-	for _, filename := range filenames {
-		if src, err := ParseFile(fset, filename, nil, mode); err == nil {
-			name := src.Name.Name
-			pkg, found := pkgs[name]
-			if !found {
-				// TODO(gri) Use NewPackage here; reconsider ParseFiles API.
-				pkg = &ast.Package{name, nil, nil, make(map[string]*ast.File)}
-				pkgs[name] = pkg
-			}
-			pkg.Files[filename] = src
-		} else if first == nil {
-			first = err
-		}
-	}
-	return
+	p.init(fset, filename, text, mode)
+	return p.parseFile(), p.errors()
 }
 
 // ParseDir calls ParseFile for the files in the directory specified by path and
@@ -185,9 +97,9 @@ func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[st
 //
 // If the directory couldn't be read, a nil map and the respective error are
 // returned. If a parse error occurred, a non-nil but incomplete map and the
-// error are returned.
+// first error encountered are returned.
 //
-func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool, mode uint) (map[string]*ast.Package, os.Error) {
+func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) {
 	fd, err := os.Open(path)
 	if err != nil {
 		return nil, err
@@ -199,16 +111,41 @@ func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool,
 		return nil, err
 	}
 
-	filenames := make([]string, len(list))
-	n := 0
-	for i := 0; i < len(list); i++ {
-		d := &list[i]
+	pkgs = make(map[string]*ast.Package)
+	for _, d := range list {
 		if filter == nil || filter(d) {
-			filenames[n] = filepath.Join(path, d.Name)
-			n++
+			filename := filepath.Join(path, d.Name())
+			if src, err := ParseFile(fset, filename, nil, mode); err == nil {
+				name := src.Name.Name
+				pkg, found := pkgs[name]
+				if !found {
+					pkg = &ast.Package{
+						Name:  name,
+						Files: make(map[string]*ast.File),
+					}
+					pkgs[name] = pkg
+				}
+				pkg.Files[filename] = src
+			} else if first == nil {
+				first = err
+			}
 		}
 	}
-	filenames = filenames[0:n]
 
-	return ParseFiles(fset, filenames, mode)
+	return
+}
+
+// ParseExpr is a convenience function for obtaining the AST of an expression x.
+// The position information recorded in the AST is undefined.
+// 
+func ParseExpr(x string) (ast.Expr, error) {
+	// parse x within the context of a complete package for correct scopes;
+	// use //line directive for correct positions in error messages and put
+	// x alone on a separate line (handles line comments), followed by a ';'
+	// to force an error if the expression is incomplete
+	file, err := ParseFile(token.NewFileSet(), "", "package p;func _(){_=\n//line :1\n"+x+"\n;}", 0)
+	if err != nil {
+		return nil, err
+	}
+	return file.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.AssignStmt).Rhs[0], nil
 }
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go
index be82b2f..6bee8de 100644
--- a/src/pkg/go/parser/parser.go
+++ b/src/pkg/go/parser/parser.go
@@ -16,19 +16,6 @@ import (
 	"go/token"
 )
 
-// The mode parameter to the Parse* functions is a set of flags (or 0).
-// They control the amount of source code parsed and other optional
-// parser functionality.
-//
-const (
-	PackageClauseOnly uint = 1 << iota // parsing stops after package clause
-	ImportsOnly                        // parsing stops after import declarations
-	ParseComments                      // parse comments and add them to AST
-	Trace                              // print a trace of parsed productions
-	DeclarationErrors                  // report declaration errors
-	SpuriousErrors                     // report all (not just the first) errors per line
-)
-
 // The parser structure holds the parser's internal state.
 type parser struct {
 	file *token.File
@@ -36,7 +23,7 @@ type parser struct {
 	scanner scanner.Scanner
 
 	// Tracing/debugging
-	mode   uint // parsing mode
+	mode   Mode // parsing mode
 	trace  bool // == (mode & Trace != 0)
 	indent uint // indentation used for tracing output
 
@@ -65,18 +52,13 @@ type parser struct {
 	targetStack [][]*ast.Ident // stack of unresolved labels
 }
 
-// scannerMode returns the scanner mode bits given the parser's mode bits.
-func scannerMode(mode uint) uint {
-	var m uint = scanner.InsertSemis
+func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) {
+	p.file = fset.AddFile(filename, fset.Base(), len(src))
+	var m scanner.Mode
 	if mode&ParseComments != 0 {
-		m |= scanner.ScanComments
+		m = scanner.ScanComments
 	}
-	return m
-}
-
-func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uint) {
-	p.file = fset.AddFile(filename, fset.Base(), len(src))
-	p.scanner.Init(p.file, src, p, scannerMode(mode))
+	p.scanner.Init(p.file, src, p, m)
 
 	p.mode = mode
 	p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
@@ -92,6 +74,14 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uin
 	p.openLabelScope()
 }
 
+func (p *parser) errors() error {
+	m := scanner.Sorted
+	if p.mode&SpuriousErrors == 0 {
+		m = scanner.NoMultiples
+	}
+	return p.GetError(m)
+}
+
 // ----------------------------------------------------------------------------
 // Scoping support
 
@@ -144,28 +134,31 @@ func (p *parser) declare(decl, data interface{}, scope *ast.Scope, kind ast.ObjK
 	}
 }
 
-func (p *parser) shortVarDecl(idents []*ast.Ident) {
+func (p *parser) shortVarDecl(decl *ast.AssignStmt, list []ast.Expr) {
 	// Go spec: A short variable declaration may redeclare variables
 	// provided they were originally declared in the same block with
 	// the same type, and at least one of the non-blank variables is new.
 	n := 0 // number of new variables
-	for _, ident := range idents {
-		assert(ident.Obj == nil, "identifier already declared or resolved")
-		obj := ast.NewObj(ast.Var, ident.Name)
-		// short var declarations cannot have redeclaration errors
-		// and are not global => no need to remember the respective
-		// declaration
-		ident.Obj = obj
-		if ident.Name != "_" {
-			if alt := p.topScope.Insert(obj); alt != nil {
-				ident.Obj = alt // redeclaration
-			} else {
-				n++ // new declaration
+	for _, x := range list {
+		if ident, isIdent := x.(*ast.Ident); isIdent {
+			assert(ident.Obj == nil, "identifier already declared or resolved")
+			obj := ast.NewObj(ast.Var, ident.Name)
+			// remember corresponding assignment for other tools
+			obj.Decl = decl
+			ident.Obj = obj
+			if ident.Name != "_" {
+				if alt := p.topScope.Insert(obj); alt != nil {
+					ident.Obj = alt // redeclaration
+				} else {
+					n++ // new declaration
+				}
 			}
+		} else {
+			p.errorExpected(x.Pos(), "identifier")
 		}
 	}
 	if n == 0 && p.mode&DeclarationErrors != 0 {
-		p.error(idents[0].Pos(), "no new variables on left side of :=")
+		p.error(list[0].Pos(), "no new variables on left side of :=")
 	}
 }
 
@@ -434,7 +427,9 @@ func (p *parser) parseLhsList() []ast.Expr {
 	switch p.tok {
 	case token.DEFINE:
 		// lhs of a short variable declaration
-		p.shortVarDecl(p.makeIdentList(list))
+		// but doesn't enter scope until later:
+		// caller must call p.shortVarDecl(p.makeIdentList(list))
+		// at appropriate time.
 	case token.COLON:
 		// lhs of a label declaration or a communication clause of a select
 		// statement (parseLhsList is not called when parsing the case clause
@@ -520,7 +515,7 @@ func (p *parser) makeIdentList(list []ast.Expr) []*ast.Ident {
 	for i, x := range list {
 		ident, isIdent := x.(*ast.Ident)
 		if !isIdent {
-			pos := x.(ast.Expr).Pos()
+			pos := x.Pos()
 			p.errorExpected(pos, "identifier")
 			ident = &ast.Ident{pos, "_", nil}
 		}
@@ -1129,7 +1124,7 @@ func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr {
 
 // checkExpr checks that x is an expression (and not a type).
 func (p *parser) checkExpr(x ast.Expr) ast.Expr {
-	switch t := unparen(x).(type) {
+	switch unparen(x).(type) {
 	case *ast.BadExpr:
 	case *ast.Ident:
 	case *ast.BasicLit:
@@ -1398,7 +1393,11 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
 		} else {
 			y = p.parseRhsList()
 		}
-		return &ast.AssignStmt{x, pos, tok, y}, isRange
+		as := &ast.AssignStmt{x, pos, tok, y}
+		if tok == token.DEFINE {
+			p.shortVarDecl(as, x)
+		}
+		return as, isRange
 	}
 
 	if len(x) > 1 {
@@ -1710,31 +1709,28 @@ func (p *parser) parseCommClause() *ast.CommClause {
 			comm = &ast.SendStmt{lhs[0], arrow, rhs}
 		} else {
 			// RecvStmt
-			pos := p.pos
-			tok := p.tok
-			var rhs ast.Expr
-			if tok == token.ASSIGN || tok == token.DEFINE {
+			if tok := p.tok; tok == token.ASSIGN || tok == token.DEFINE {
 				// RecvStmt with assignment
 				if len(lhs) > 2 {
 					p.errorExpected(lhs[0].Pos(), "1 or 2 expressions")
 					// continue with first two expressions
 					lhs = lhs[0:2]
 				}
+				pos := p.pos
 				p.next()
-				rhs = p.parseRhs()
+				rhs := p.parseRhs()
+				as := &ast.AssignStmt{lhs, pos, tok, []ast.Expr{rhs}}
+				if tok == token.DEFINE {
+					p.shortVarDecl(as, lhs)
+				}
+				comm = as
 			} else {
-				// rhs must be single receive operation
+				// lhs must be single receive operation
 				if len(lhs) > 1 {
 					p.errorExpected(lhs[0].Pos(), "1 expression")
 					// continue with first expression
 				}
-				rhs = lhs[0]
-				lhs = nil // there is no lhs
-			}
-			if lhs != nil {
-				comm = &ast.AssignStmt{lhs, pos, tok, []ast.Expr{rhs}}
-			} else {
-				comm = &ast.ExprStmt{rhs}
+				comm = &ast.ExprStmt{lhs[0]}
 			}
 		}
 	} else {
@@ -1909,7 +1905,7 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
 	p.expectSemi() // call before accessing p.linecomment
 
 	// collect imports
-	spec := &ast.ImportSpec{doc, ident, path, p.lineComment}
+	spec := &ast.ImportSpec{doc, ident, path, p.lineComment, token.NoPos}
 	p.imports = append(p.imports, spec)
 
 	return spec
@@ -2018,7 +2014,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
 	// must have exactly one receiver
 	if par.NumFields() != 1 {
 		p.errorExpected(par.Opening, "exactly one receiver")
-		par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{par.Opening, par.Closing + 1}}}
+		par.List = []*ast.Field{{Type: &ast.BadExpr{par.Opening, par.Closing + 1}}}
 		return par
 	}
 
@@ -2027,7 +2023,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
 	base := deref(recv.Type)
 	if _, isIdent := base.(*ast.Ident); !isIdent {
 		p.errorExpected(base.Pos(), "(unqualified) identifier")
-		par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
+		par.List = []*ast.Field{{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
 	}
 
 	return par
@@ -2103,18 +2099,6 @@ func (p *parser) parseDecl() ast.Decl {
 	return p.parseGenDecl(p.tok, f)
 }
 
-func (p *parser) parseDeclList() (list []ast.Decl) {
-	if p.trace {
-		defer un(trace(p, "DeclList"))
-	}
-
-	for p.tok != token.EOF {
-		list = append(list, p.parseDecl())
-	}
-
-	return
-}
-
 // ----------------------------------------------------------------------------
 // Source files
 
diff --git a/src/pkg/go/parser/parser_test.go b/src/pkg/go/parser/parser_test.go
index 9705dcf..a3ee852 100644
--- a/src/pkg/go/parser/parser_test.go
+++ b/src/pkg/go/parser/parser_test.go
@@ -5,6 +5,7 @@
 package parser
 
 import (
+	"go/ast"
 	"go/token"
 	"os"
 	"testing"
@@ -53,7 +54,7 @@ func TestParseIllegalInputs(t *testing.T) {
 	}
 }
 
-var validPrograms = []interface{}{
+var validPrograms = []string{
 	"package p\n",
 	`package p;`,
 	`package p; import "fmt"; func f() { fmt.Println("Hello, World!") };`,
@@ -112,7 +113,7 @@ func nameFilter(filename string) bool {
 	return true
 }
 
-func dirFilter(f *os.FileInfo) bool { return nameFilter(f.Name) }
+func dirFilter(f os.FileInfo) bool { return nameFilter(f.Name()) }
 
 func TestParse4(t *testing.T) {
 	path := "."
@@ -134,3 +135,72 @@ func TestParse4(t *testing.T) {
 		}
 	}
 }
+
+func TestParseExpr(t *testing.T) {
+	// just kicking the tires:
+	// a valid expression
+	src := "a + b"
+	x, err := ParseExpr(src)
+	if err != nil {
+		t.Errorf("ParseExpr(%s): %v", src, err)
+	}
+	// sanity check
+	if _, ok := x.(*ast.BinaryExpr); !ok {
+		t.Errorf("ParseExpr(%s): got %T, expected *ast.BinaryExpr", src, x)
+	}
+
+	// an invalid expression
+	src = "a + *"
+	_, err = ParseExpr(src)
+	if err == nil {
+		t.Errorf("ParseExpr(%s): %v", src, err)
+	}
+
+	// it must not crash
+	for _, src := range validPrograms {
+		ParseExpr(src)
+	}
+}
+
+func TestColonEqualsScope(t *testing.T) {
+	f, err := ParseFile(fset, "", `package p; func f() { x, y, z := x, y, z }`, 0)
+	if err != nil {
+		t.Errorf("parse: %s", err)
+	}
+
+	// RHS refers to undefined globals; LHS does not.
+	as := f.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.AssignStmt)
+	for _, v := range as.Rhs {
+		id := v.(*ast.Ident)
+		if id.Obj != nil {
+			t.Errorf("rhs %s has Obj, should not", id.Name)
+		}
+	}
+	for _, v := range as.Lhs {
+		id := v.(*ast.Ident)
+		if id.Obj == nil {
+			t.Errorf("lhs %s does not have Obj, should", id.Name)
+		}
+	}
+}
+
+func TestVarScope(t *testing.T) {
+	f, err := ParseFile(fset, "", `package p; func f() { var x, y, z = x, y, z }`, 0)
+	if err != nil {
+		t.Errorf("parse: %s", err)
+	}
+
+	// RHS refers to undefined globals; LHS does not.
+	as := f.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.DeclStmt).Decl.(*ast.GenDecl).Specs[0].(*ast.ValueSpec)
+	for _, v := range as.Values {
+		id := v.(*ast.Ident)
+		if id.Obj != nil {
+			t.Errorf("rhs %s has Obj, should not", id.Name)
+		}
+	}
+	for _, id := range as.Names {
+		if id.Obj == nil {
+			t.Errorf("lhs %s does not have Obj, should", id.Name)
+		}
+	}
+}
diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go
index 3645306..5f3b4d4 100644
--- a/src/pkg/go/printer/nodes.go
+++ b/src/pkg/go/printer/nodes.go
@@ -39,7 +39,10 @@ import (
 //            future (not yet interspersed) comments in this function.
 //
 func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (printedBreak bool) {
-	n := p.nlines(line-p.pos.Line, min)
+	n := nlimit(line - p.pos.Line)
+	if n < min {
+		n = min
+	}
 	if n > 0 {
 		p.print(ws)
 		if newSection {
@@ -69,7 +72,7 @@ func (p *printer) setComment(g *ast.CommentGroup) {
 		// for some reason there are pending comments; this
 		// should never happen - handle gracefully and flush
 		// all comments up to g, ignore anything after that
-		p.flush(p.fset.Position(g.List[0].Pos()), token.ILLEGAL)
+		p.flush(p.posFor(g.List[0].Pos()), token.ILLEGAL)
 	}
 	p.comments[0] = g
 	p.cindex = 0
@@ -119,10 +122,10 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 		p.print(blank)
 	}
 
-	prev := p.fset.Position(prev0)
-	next := p.fset.Position(next0)
-	line := p.fset.Position(list[0].Pos()).Line
-	endLine := p.fset.Position(list[len(list)-1].End()).Line
+	prev := p.posFor(prev0)
+	next := p.posFor(next0)
+	line := p.lineFor(list[0].Pos())
+	endLine := p.lineFor(list[len(list)-1].End())
 
 	if prev.IsValid() && prev.Line == line && line == endLine {
 		// all list entries on a single line
@@ -166,7 +169,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 	// print all list elements
 	for i, x := range list {
 		prevLine := line
-		line = p.fset.Position(x.Pos()).Line
+		line = p.lineFor(x.Pos())
 
 		// determine if the next linebreak, if any, needs to use formfeed:
 		// in general, use the entire node size to make the decision; for
@@ -269,23 +272,32 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
 	p.print(fields.Opening, token.LPAREN)
 	if len(fields.List) > 0 {
+		prevLine := p.lineFor(fields.Opening)
 		ws := indent
-		var prevLine, line int
 		for i, par := range fields.List {
+			// determine par begin and end line (may be different
+			// if there are multiple parameter names for this par
+			// or the type is on a separate line)
+			var parLineBeg int
+			var parLineEnd = p.lineFor(par.Type.Pos())
+			if len(par.Names) > 0 {
+				parLineBeg = p.lineFor(par.Names[0].Pos())
+			} else {
+				parLineBeg = parLineEnd
+			}
+			// separating "," if needed
 			if i > 0 {
 				p.print(token.COMMA)
-				if len(par.Names) > 0 {
-					line = p.fset.Position(par.Names[0].Pos()).Line
-				} else {
-					line = p.fset.Position(par.Type.Pos()).Line
-				}
-				if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ws, true) {
-					ws = ignore
-					*multiLine = true
-				} else {
-					p.print(blank)
-				}
 			}
+			// separator if needed (linebreak or blank)
+			if 0 < prevLine && prevLine < parLineBeg && p.linebreak(parLineBeg, 0, ws, true) {
+				// break line if the opening "(" or previous parameter ended on a different line
+				ws = ignore
+				*multiLine = true
+			} else if i > 0 {
+				p.print(blank)
+			}
+			// parameter names
 			if len(par.Names) > 0 {
 				// Very subtle: If we indented before (ws == ignore), identList
 				// won't indent again. If we didn't (ws == indent), identList will
@@ -296,11 +308,18 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
 				p.identList(par.Names, ws == indent, multiLine)
 				p.print(blank)
 			}
+			// parameter type
 			p.expr(par.Type, multiLine)
-			prevLine = p.fset.Position(par.Type.Pos()).Line
+			prevLine = parLineEnd
 		}
+		// if the closing ")" is on a separate line from the last parameter,
+		// print an additional "," and line break
+		if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
+			p.print(",")
+			p.linebreak(closing, 0, ignore, true)
+		}
+		// unindent if we indented
 		if ws == ignore {
-			// unindent if we indented
 			p.print(unindent)
 		}
 	}
@@ -354,16 +373,17 @@ func (p *printer) isOneLineFieldList(list []*ast.Field) bool {
 }
 
 func (p *printer) setLineComment(text string) {
-	p.setComment(&ast.CommentGroup{[]*ast.Comment{&ast.Comment{token.NoPos, text}}})
+	p.setComment(&ast.CommentGroup{[]*ast.Comment{{token.NoPos, text}}})
 }
 
 func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
 	lbrace := fields.Opening
 	list := fields.List
 	rbrace := fields.Closing
-	srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.fset.Position(lbrace).Line == p.fset.Position(rbrace).Line
+	hasComments := isIncomplete || p.commentBefore(p.posFor(rbrace))
+	srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.lineFor(lbrace) == p.lineFor(rbrace)
 
-	if !isIncomplete && !p.commentBefore(p.fset.Position(rbrace)) && srcIsOneLine {
+	if !hasComments && srcIsOneLine {
 		// possibly a one-line struct/interface
 		if len(list) == 0 {
 			// no blank between keyword and {} in this case
@@ -388,9 +408,13 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
 			return
 		}
 	}
+	// hasComments || !srcIsOneLine
+
+	p.print(blank, lbrace, token.LBRACE, indent)
+	if hasComments || len(list) > 0 {
+		p.print(formfeed)
+	}
 
-	// at least one entry or incomplete
-	p.print(blank, lbrace, token.LBRACE, indent, formfeed)
 	if isStruct {
 
 		sep := vtab
@@ -400,7 +424,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
 		var ml bool
 		for i, f := range list {
 			if i > 0 {
-				p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml)
+				p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml)
 			}
 			ml = false
 			extraTabs := 0
@@ -435,7 +459,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
 			if len(list) > 0 {
 				p.print(formfeed)
 			}
-			p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't lose the last line comment
+			p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
 			p.setLineComment("// contains filtered or unexported fields")
 		}
 
@@ -444,7 +468,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
 		var ml bool
 		for i, f := range list {
 			if i > 0 {
-				p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml)
+				p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml)
 			}
 			ml = false
 			p.setComment(f.Doc)
@@ -462,7 +486,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
 			if len(list) > 0 {
 				p.print(formfeed)
 			}
-			p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't lose the last line comment
+			p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
 			p.setLineComment("// contains filtered or unexported methods")
 		}
 
@@ -618,7 +642,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL
 		p.print(blank)
 	}
 	xline := p.pos.Line // before the operator (it may be on the next line!)
-	yline := p.fset.Position(x.Y.Pos()).Line
+	yline := p.lineFor(x.Y.Pos())
 	p.print(x.OpPos, x.Op)
 	if xline != yline && xline > 0 && yline > 0 {
 		// at least one line break, but respect an extra empty line
@@ -911,7 +935,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
 	for i, s := range list {
 		// _indent == 0 only for lists of switch/select case clauses;
 		// in those cases each clause is a new section
-		p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, i == 0 || _indent == 0 || multiLine)
+		p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || _indent == 0 || multiLine)
 		multiLine = false
 		p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine)
 	}
@@ -924,7 +948,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
 func (p *printer) block(s *ast.BlockStmt, indent int) {
 	p.print(s.Pos(), token.LBRACE)
 	p.stmtList(s.List, indent, true)
-	p.linebreak(p.fset.Position(s.Rbrace).Line, 1, ignore, true)
+	p.linebreak(p.lineFor(s.Rbrace), 1, ignore, true)
 	p.print(s.Rbrace, token.RBRACE)
 }
 
@@ -1025,7 +1049,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
 				break
 			}
 		} else {
-			p.linebreak(p.fset.Position(s.Stmt.Pos()).Line, 1, ignore, true)
+			p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true)
 		}
 		p.stmt(s.Stmt, nextIsRBrace, multiLine)
 
@@ -1137,7 +1161,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
 	case *ast.SelectStmt:
 		p.print(token.SELECT, blank)
 		body := s.Body
-		if len(body.List) == 0 && !p.commentBefore(p.fset.Position(body.Rbrace)) {
+		if len(body.List) == 0 && !p.commentBefore(p.posFor(body.Rbrace)) {
 			// print empty select statement w/o comments on one line
 			p.print(body.Lbrace, token.LBRACE, body.Rbrace, token.RBRACE)
 		} else {
@@ -1278,6 +1302,7 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool, multiLine *bool) {
 		}
 		p.expr(s.Path, multiLine)
 		p.setComment(s.Comment)
+		p.print(s.EndPos)
 
 	case *ast.ValueSpec:
 		if n != 1 {
@@ -1328,7 +1353,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
 				var ml bool
 				for i, s := range d.Specs {
 					if i > 0 {
-						p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml)
+						p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml)
 					}
 					ml = false
 					p.valueSpec(s.(*ast.ValueSpec), keepType[i], false, &ml)
@@ -1337,7 +1362,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
 				var ml bool
 				for i, s := range d.Specs {
 					if i > 0 {
-						p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml)
+						p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml)
 					}
 					ml = false
 					p.spec(s, n, false, &ml)
@@ -1376,7 +1401,7 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
 	// in RawFormat
 	cfg := Config{Mode: RawFormat}
 	var buf bytes.Buffer
-	if _, err := cfg.fprint(&buf, p.fset, n, p.nodeSizes); err != nil {
+	if err := cfg.fprint(&buf, p.fset, n, p.nodeSizes); err != nil {
 		return
 	}
 	if buf.Len() <= maxSize {
@@ -1394,11 +1419,11 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
 func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
 	pos1 := b.Pos()
 	pos2 := b.Rbrace
-	if pos1.IsValid() && pos2.IsValid() && p.fset.Position(pos1).Line != p.fset.Position(pos2).Line {
+	if pos1.IsValid() && pos2.IsValid() && p.lineFor(pos1) != p.lineFor(pos2) {
 		// opening and closing brace are on different lines - don't make it a one-liner
 		return false
 	}
-	if len(b.List) > 5 || p.commentBefore(p.fset.Position(pos2)) {
+	if len(b.List) > 5 || p.commentBefore(p.posFor(pos2)) {
 		// too many statements or there is a comment inside - don't make it a one-liner
 		return false
 	}
@@ -1449,7 +1474,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
 // are on the same line; if they are on different lines (or unknown)
 // the result is infinity.
 func (p *printer) distance(from0 token.Pos, to token.Position) int {
-	from := p.fset.Position(from0)
+	from := p.posFor(from0)
 	if from.IsValid() && to.IsValid() && from.Line == to.Line {
 		return to.Column - from.Column
 	}
@@ -1508,12 +1533,17 @@ func (p *printer) file(src *ast.File) {
 			prev := tok
 			tok = declToken(d)
 			// if the declaration token changed (e.g., from CONST to TYPE)
+			// or the next declaration has documentation associated with it,
 			// print an empty line between top-level declarations
+			// (because p.linebreak is called with the position of d, which
+			// is past any documentation, the minimum requirement is satisfied
+			// even w/o the extra getDoc(d) nil-check - leave it in case the
+			// linebreak logic improves - there's already a TODO).
 			min := 1
-			if prev != tok {
+			if prev != tok || getDoc(d) != nil {
 				min = 2
 			}
-			p.linebreak(p.fset.Position(d.Pos()).Line, min, ignore, false)
+			p.linebreak(p.lineFor(d.Pos()), min, ignore, false)
 			p.decl(d, ignoreMultiLine)
 		}
 	}
diff --git a/src/pkg/go/printer/performance_test.go b/src/pkg/go/printer/performance_test.go
index 84fb280..dbd9422 100644
--- a/src/pkg/go/printer/performance_test.go
+++ b/src/pkg/go/printer/performance_test.go
@@ -20,7 +20,7 @@ import (
 var testfile *ast.File
 
 func testprint(out io.Writer, file *ast.File) {
-	if _, err := (&Config{TabIndent | UseSpaces, 8}).Fprint(out, fset, file); err != nil {
+	if err := (&Config{TabIndent | UseSpaces, 8}).Fprint(out, fset, file); err != nil {
 		log.Fatalf("print error: %s", err)
 	}
 }
diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go
index bfabd74..52dfff6 100644
--- a/src/pkg/go/printer/printer.go
+++ b/src/pkg/go/printer/printer.go
@@ -13,13 +13,18 @@ import (
 	"io"
 	"os"
 	"path/filepath"
-	"tabwriter"
+	"strconv"
+	"strings"
+	"text/tabwriter"
 )
 
-const debug = false // enable for debugging
-
+const (
+	maxNewlines = 2     // max. number of newlines between source text
+	debug       = false // enable for debugging
+	infinity    = 1 << 30
+)
 
-type whiteSpace int
+type whiteSpace byte
 
 const (
 	ignore   = whiteSpace(0)
@@ -31,18 +36,6 @@ const (
 	unindent = whiteSpace('<')
 )
 
-var (
-	esc       = []byte{tabwriter.Escape}
-	htab      = []byte{'\t'}
-	htabs     = []byte("\t\t\t\t\t\t\t\t")
-	newlines  = []byte("\n\n\n\n\n\n\n\n") // more than the max determined by nlines
-	formfeeds = []byte("\f\f\f\f\f\f\f\f") // more than the max determined by nlines
-)
-
-// Special positions
-var noPos token.Position // use noPos when a position is needed but not known
-var infinity = 1 << 30
-
 // Use ignoreMultiLine if the multiLine information is not important.
 var ignoreMultiLine = new(bool)
 
@@ -50,31 +43,20 @@ var ignoreMultiLine = new(bool)
 type pmode int
 
 const (
-	inLiteral pmode = 1 << iota
-	noExtraLinebreak
+	noExtraLinebreak pmode = 1 << iota
 )
 
-// local error wrapper so we can distinguish os.Errors we want to return
-// as errors from genuine panics (which we don't want to return as errors)
-type osError struct {
-	err os.Error
-}
-
 type printer struct {
 	// Configuration (does not change after initialization)
-	output io.Writer
 	Config
 	fset *token.FileSet
 
 	// Current state
-	written int         // number of bytes written
-	indent  int         // current indentation
-	mode    pmode       // current printer mode
-	lastTok token.Token // the last token printed (token.ILLEGAL if it's whitespace)
-
-	// Reused buffers
-	wsbuf  []whiteSpace // delayed white space
-	litbuf bytes.Buffer // for creation of escaped literals and comments
+	output  bytes.Buffer // raw printer result
+	indent  int          // current indentation
+	mode    pmode        // current printer mode
+	lastTok token.Token  // the last token printed (token.ILLEGAL if it's whitespace)
+	wsbuf   []whiteSpace // delayed white space
 
 	// The (possibly estimated) position in the generated output;
 	// in AST space (i.e., pos is set whenever a token position is
@@ -93,14 +75,18 @@ type printer struct {
 
 	// Cache of already computed node sizes.
 	nodeSizes map[ast.Node]int
+
+	// Cache of most recently computed line position.
+	cachedPos  token.Pos
+	cachedLine int // line corresponding to cachedPos
 }
 
-func (p *printer) init(output io.Writer, cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node]int) {
-	p.output = output
+func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node]int) {
 	p.Config = *cfg
 	p.fset = fset
 	p.wsbuf = make([]whiteSpace, 0, 16) // whitespace sequences are short
 	p.nodeSizes = nodeSizes
+	p.cachedPos = -1
 }
 
 func (p *printer) internalError(msg ...interface{}) {
@@ -111,109 +97,90 @@ func (p *printer) internalError(msg ...interface{}) {
 	}
 }
 
-// escape escapes string s by bracketing it with tabwriter.Escape.
-// Escaped strings pass through tabwriter unchanged. (Note that
-// valid Go programs cannot contain tabwriter.Escape bytes since
-// they do not appear in legal UTF-8 sequences).
-//
-func (p *printer) escape(s string) string {
-	p.litbuf.Reset()
-	p.litbuf.WriteByte(tabwriter.Escape)
-	p.litbuf.WriteString(s)
-	p.litbuf.WriteByte(tabwriter.Escape)
-	return p.litbuf.String()
+func (p *printer) posFor(pos token.Pos) token.Position {
+	// not used frequently enough to cache entire token.Position
+	return p.fset.Position(pos)
 }
 
-// nlines returns the adjusted number of linebreaks given the desired number
-// of breaks n such that min <= result <= max.
-//
-func (p *printer) nlines(n, min int) int {
-	const max = 2 // max. number of newlines
-	switch {
-	case n < min:
-		return min
-	case n > max:
-		return max
+func (p *printer) lineFor(pos token.Pos) int {
+	if pos != p.cachedPos {
+		p.cachedPos = pos
+		p.cachedLine = p.fset.Position(pos).Line
 	}
-	return n
+	return p.cachedLine
 }
 
-// write0 writes raw (uninterpreted) data to p.output and handles errors.
-// write0 does not indent after newlines, and does not HTML-escape or update p.pos.
-//
-func (p *printer) write0(data []byte) {
-	if len(data) > 0 {
-		n, err := p.output.Write(data)
-		p.written += n
-		if err != nil {
-			panic(osError{err})
+// writeByte writes ch to p.output and updates p.pos.
+func (p *printer) writeByte(ch byte) {
+	p.output.WriteByte(ch)
+	p.pos.Offset++
+	p.pos.Column++
+
+	if ch == '\n' || ch == '\f' {
+		// write indentation
+		// use "hard" htabs - indentation columns
+		// must not be discarded by the tabwriter
+		const htabs = "\t\t\t\t\t\t\t\t"
+		j := p.indent
+		for j > len(htabs) {
+			p.output.WriteString(htabs)
+			j -= len(htabs)
 		}
+		p.output.WriteString(htabs[0:j])
+
+		// update p.pos
+		p.pos.Line++
+		p.pos.Offset += p.indent
+		p.pos.Column = 1 + p.indent
 	}
 }
 
-// write interprets data and writes it to p.output. It inserts indentation
-// after a line break unless in a tabwriter escape sequence.
-// It updates p.pos as a side-effect.
-//
-func (p *printer) write(data []byte) {
-	i0 := 0
-	for i, b := range data {
-		switch b {
-		case '\n', '\f':
-			// write segment ending in b
-			p.write0(data[i0 : i+1])
-
-			// update p.pos
-			p.pos.Offset += i + 1 - i0
-			p.pos.Line++
-			p.pos.Column = 1
-
-			if p.mode&inLiteral == 0 {
-				// write indentation
-				// use "hard" htabs - indentation columns
-				// must not be discarded by the tabwriter
-				j := p.indent
-				for ; j > len(htabs); j -= len(htabs) {
-					p.write0(htabs)
-				}
-				p.write0(htabs[0:j])
-
-				// update p.pos
-				p.pos.Offset += p.indent
-				p.pos.Column += p.indent
-			}
-
-			// next segment start
-			i0 = i + 1
-
-		case tabwriter.Escape:
-			p.mode ^= inLiteral
+// writeByteN writes ch n times to p.output and updates p.pos.
+func (p *printer) writeByteN(ch byte, n int) {
+	for n > 0 {
+		p.writeByte(ch)
+		n--
+	}
+}
 
-			// ignore escape chars introduced by printer - they are
-			// invisible and must not affect p.pos (was issue #1089)
-			p.pos.Offset--
-			p.pos.Column--
-		}
+// writeString writes the string s to p.output and updates p.pos.
+// If isLit is set, s is escaped w/ tabwriter.Escape characters
+// to protect s from being interpreted by the tabwriter.
+//
+// Note: writeString is only used to write Go tokens, literals, and
+// comments, all of which must be written literally. Thus, it is correct
+// to always set isLit = true. However, setting it explicitly only when
+// needed (i.e., when we don't know that s contains no tabs or line breaks)
+// avoids processing extra escape characters and reduces run time of the
+// printer benchmark by up to 10%.
+//
+func (p *printer) writeString(s string, isLit bool) {
+	if isLit {
+		// Protect s such that is passes through the tabwriter
+		// unchanged. Note that valid Go programs cannot contain
+		// tabwriter.Escape bytes since they do not appear in legal
+		// UTF-8 sequences.
+		p.output.WriteByte(tabwriter.Escape)
 	}
 
-	// write remaining segment
-	p.write0(data[i0:])
+	p.output.WriteString(s)
 
 	// update p.pos
-	d := len(data) - i0
-	p.pos.Offset += d
-	p.pos.Column += d
-}
-
-func (p *printer) writeNewlines(n int, useFF bool) {
-	if n > 0 {
-		n = p.nlines(n, 0)
-		if useFF {
-			p.write(formfeeds[0:n])
-		} else {
-			p.write(newlines[0:n])
+	nlines := 0
+	column := p.pos.Column + len(s)
+	for i := 0; i < len(s); i++ {
+		if s[i] == '\n' {
+			nlines++
+			column = len(s) - i
 		}
 	}
+	p.pos.Offset += len(s)
+	p.pos.Line += nlines
+	p.pos.Column = column
+
+	if isLit {
+		p.output.WriteByte(tabwriter.Escape)
+	}
 }
 
 // writeItem writes data at position pos. data is the text corresponding to
@@ -222,7 +189,7 @@ func (p *printer) writeNewlines(n int, useFF bool) {
 // source text. writeItem updates p.last to the position immediately following
 // the data.
 //
-func (p *printer) writeItem(pos token.Position, data string) {
+func (p *printer) writeItem(pos token.Position, data string, isLit bool) {
 	if pos.IsValid() {
 		// continue with previous position if we don't have a valid pos
 		if p.last.IsValid() && p.last.Filename != pos.Filename {
@@ -238,12 +205,14 @@ func (p *printer) writeItem(pos token.Position, data string) {
 	if debug {
 		// do not update p.pos - use write0
 		_, filename := filepath.Split(pos.Filename)
-		p.write0([]byte(fmt.Sprintf("[%s:%d:%d]", filename, pos.Line, pos.Column)))
+		fmt.Fprintf(&p.output, "[%s:%d:%d]", filename, pos.Line, pos.Column)
 	}
-	p.write([]byte(data))
+	p.writeString(data, isLit)
 	p.last = p.pos
 }
 
+const linePrefix = "//line "
+
 // writeCommentPrefix writes the whitespace before a comment.
 // If there is any pending whitespace, it consumes as much of
 // it as is likely to help position the comment nicely.
@@ -252,15 +221,15 @@ func (p *printer) writeItem(pos token.Position, data string) {
 // a group of comments (or nil), and isKeyword indicates if the
 // next item is a keyword.
 //
-func (p *printer) writeCommentPrefix(pos, next token.Position, prev *ast.Comment, isKeyword bool) {
-	if p.written == 0 {
+func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *ast.Comment, isKeyword bool) {
+	if p.output.Len() == 0 {
 		// the comment is the first item to be printed - don't write any whitespace
 		return
 	}
 
 	if pos.IsValid() && pos.Filename != p.last.Filename {
-		// comment in a different file - separate with newlines (writeNewlines will limit the number)
-		p.writeNewlines(10, true)
+		// comment in a different file - separate with newlines
+		p.writeByteN('\f', maxNewlines)
 		return
 	}
 
@@ -293,19 +262,20 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, prev *ast.Comment
 		}
 		// make sure there is at least one separator
 		if !hasSep {
+			sep := byte('\t')
 			if pos.Line == next.Line {
 				// next item is on the same line as the comment
 				// (which must be a /*-style comment): separate
 				// with a blank instead of a tab
-				p.write([]byte{' '})
-			} else {
-				p.write(htab)
+				sep = ' '
 			}
+			p.writeByte(sep)
 		}
 
 	} else {
 		// comment on a different line:
 		// separate with at least one line break
+		droppedLinebreak := false
 		if prev == nil {
 			// first comment of a comment group
 			j := 0
@@ -331,44 +301,70 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, prev *ast.Comment
 				case newline, formfeed:
 					// TODO(gri): may want to keep formfeed info in some cases
 					p.wsbuf[i] = ignore
+					droppedLinebreak = true
 				}
 				j = i
 				break
 			}
 			p.writeWhitespace(j)
 		}
-		// use formfeeds to break columns before a comment;
-		// this is analogous to using formfeeds to separate
-		// individual lines of /*-style comments - but make
-		// sure there is at least one line break if the previous
-		// comment was a line comment
-		n := pos.Line - p.last.Line // if !pos.IsValid(), pos.Line == 0, and n will be 0
-		if n <= 0 && prev != nil && prev.Text[1] == '/' {
+
+		// determine number of linebreaks before the comment
+		n := 0
+		if pos.IsValid() && p.last.IsValid() {
+			n = pos.Line - p.last.Line
+			if n < 0 { // should never happen
+				n = 0
+			}
+		}
+
+		// at the package scope level only (p.indent == 0),
+		// add an extra newline if we dropped one before:
+		// this preserves a blank line before documentation
+		// comments at the package scope level (issue 2570)
+		if p.indent == 0 && droppedLinebreak {
+			n++
+		}
+
+		// make sure there is at least one line break
+		// if the previous comment was a line comment
+		if n == 0 && prev != nil && prev.Text[1] == '/' {
 			n = 1
 		}
-		p.writeNewlines(n, true)
+
+		if n > 0 {
+			// turn off indent if we're about to print a line directive
+			indent := p.indent
+			if strings.HasPrefix(comment.Text, linePrefix) {
+				p.indent = 0
+			}
+			// use formfeeds to break columns before a comment;
+			// this is analogous to using formfeeds to separate
+			// individual lines of /*-style comments
+			p.writeByteN('\f', nlimit(n))
+			p.indent = indent // restore indent
+		}
 	}
 }
 
-// TODO(gri): It should be possible to convert the code below from using
-//            []byte to string and in the process eliminate some conversions.
-
 // Split comment text into lines
-func split(text []byte) [][]byte {
+// (using strings.Split(text, "\n") is significantly slower for
+// this specific purpose, as measured with: gotest -bench=Print)
+func split(text string) []string {
 	// count lines (comment text never ends in a newline)
 	n := 1
-	for _, c := range text {
-		if c == '\n' {
+	for i := 0; i < len(text); i++ {
+		if text[i] == '\n' {
 			n++
 		}
 	}
 
 	// split
-	lines := make([][]byte, n)
+	lines := make([]string, n)
 	n = 0
 	i := 0
-	for j, c := range text {
-		if c == '\n' {
+	for j := 0; j < len(text); j++ {
+		if text[j] == '\n' {
 			lines[n] = text[i:j] // exclude newline
 			i = j + 1            // discard newline
 			n++
@@ -379,16 +375,18 @@ func split(text []byte) [][]byte {
 	return lines
 }
 
-func isBlank(s []byte) bool {
-	for _, b := range s {
-		if b > ' ' {
+// Returns true if s contains only white space
+// (only tabs and blanks can appear in the printer's context).
+func isBlank(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] > ' ' {
 			return false
 		}
 	}
 	return true
 }
 
-func commonPrefix(a, b []byte) []byte {
+func commonPrefix(a, b string) string {
 	i := 0
 	for i < len(a) && i < len(b) && a[i] == b[i] && (a[i] <= ' ' || a[i] == '*') {
 		i++
@@ -396,7 +394,7 @@ func commonPrefix(a, b []byte) []byte {
 	return a[0:i]
 }
 
-func stripCommonPrefix(lines [][]byte) {
+func stripCommonPrefix(lines []string) {
 	if len(lines) < 2 {
 		return // at most one line - nothing to do
 	}
@@ -420,19 +418,21 @@ func stripCommonPrefix(lines [][]byte) {
 	// Note that the first and last line are never empty (they
 	// contain the opening /* and closing */ respectively) and
 	// thus they can be ignored by the blank line check.
-	var prefix []byte
+	var prefix string
 	if len(lines) > 2 {
+		first := true
 		for i, line := range lines[1 : len(lines)-1] {
 			switch {
 			case isBlank(line):
-				lines[1+i] = nil // range starts at line 1
-			case prefix == nil:
+				lines[1+i] = "" // range starts at line 1
+			case first:
 				prefix = commonPrefix(line, line)
+				first = false
 			default:
 				prefix = commonPrefix(prefix, line)
 			}
 		}
-	} else { // len(lines) == 2
+	} else { // len(lines) == 2, lines cannot be blank (contain /* and */)
 		line := lines[1]
 		prefix = commonPrefix(line, line)
 	}
@@ -441,7 +441,7 @@ func stripCommonPrefix(lines [][]byte) {
 	 * Check for vertical "line of stars" and correct prefix accordingly.
 	 */
 	lineOfStars := false
-	if i := bytes.Index(prefix, []byte{'*'}); i >= 0 {
+	if i := strings.Index(prefix, "*"); i >= 0 {
 		// Line of stars present.
 		if i > 0 && prefix[i-1] == ' ' {
 			i-- // remove trailing blank from prefix so stars remain aligned
@@ -489,7 +489,7 @@ func stripCommonPrefix(lines [][]byte) {
 			}
 			// Shorten the computed common prefix by the length of
 			// suffix, if it is found as suffix of the prefix.
-			if bytes.HasSuffix(prefix, suffix) {
+			if strings.HasSuffix(prefix, string(suffix)) {
 				prefix = prefix[0 : len(prefix)-len(suffix)]
 			}
 		}
@@ -499,19 +499,18 @@ func stripCommonPrefix(lines [][]byte) {
 	// with the opening /*, otherwise align the text with the other
 	// lines.
 	last := lines[len(lines)-1]
-	closing := []byte("*/")
-	i := bytes.Index(last, closing)
+	closing := "*/"
+	i := strings.Index(last, closing) // i >= 0 (closing is always present)
 	if isBlank(last[0:i]) {
 		// last line only contains closing */
-		var sep []byte
 		if lineOfStars {
-			// insert an aligning blank
-			sep = []byte{' '}
+			closing = " */" // add blank to align final star
 		}
-		lines[len(lines)-1] = bytes.Join([][]byte{prefix, closing}, sep)
+		lines[len(lines)-1] = prefix + closing
 	} else {
 		// last line contains more comment text - assume
-		// it is aligned like the other lines
+		// it is aligned like the other lines and include
+		// in prefix computation
 		prefix = commonPrefix(prefix, last)
 	}
 
@@ -526,28 +525,47 @@ func stripCommonPrefix(lines [][]byte) {
 func (p *printer) writeComment(comment *ast.Comment) {
 	text := comment.Text
 
+	if strings.HasPrefix(text, linePrefix) {
+		pos := strings.TrimSpace(text[len(linePrefix):])
+		i := strings.LastIndex(pos, ":")
+		if i >= 0 {
+			// The line directive we are about to print changed
+			// the Filename and Line number used by go/token
+			// as it was reading the input originally.
+			// In order to match the original input, we have to
+			// update our own idea of the file and line number
+			// accordingly, after printing the directive.
+			file := pos[:i]
+			line, _ := strconv.Atoi(pos[i+1:])
+			defer func() {
+				p.pos.Filename = file
+				p.pos.Line = line
+				p.pos.Column = 1
+			}()
+		}
+	}
+
 	// shortcut common case of //-style comments
 	if text[1] == '/' {
-		p.writeItem(p.fset.Position(comment.Pos()), p.escape(text))
+		p.writeItem(p.posFor(comment.Pos()), text, true)
 		return
 	}
 
 	// for /*-style comments, print line by line and let the
 	// write function take care of the proper indentation
-	lines := split([]byte(text))
+	lines := split(text)
 	stripCommonPrefix(lines)
 
 	// write comment lines, separated by formfeed,
 	// without a line break after the last line
-	linebreak := formfeeds[0:1]
-	pos := p.fset.Position(comment.Pos())
+	pos := p.posFor(comment.Pos())
 	for i, line := range lines {
 		if i > 0 {
-			p.write(linebreak)
+			p.writeByte('\f')
 			pos = p.pos
 		}
 		if len(line) > 0 {
-			p.writeItem(pos, p.escape(string(line)))
+			p.writeItem(pos, line, true)
 		}
 	}
 }
@@ -555,10 +573,11 @@ func (p *printer) writeComment(comment *ast.Comment) {
 // writeCommentSuffix writes a line break after a comment if indicated
 // and processes any leftover indentation information. If a line break
 // is needed, the kind of break (newline vs formfeed) depends on the
-// pending whitespace. writeCommentSuffix returns true if a pending
-// formfeed was dropped from the whitespace buffer.
+// pending whitespace. The writeCommentSuffix result indicates if a
+// newline was written or if a formfeed was dropped from the whitespace
+// buffer.
 //
-func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
+func (p *printer) writeCommentSuffix(needsLinebreak bool) (wroteNewline, droppedFF bool) {
 	for i, ch := range p.wsbuf {
 		switch ch {
 		case blank, vtab:
@@ -571,6 +590,7 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
 			// but remember if we dropped any formfeeds
 			if needsLinebreak {
 				needsLinebreak = false
+				wroteNewline = true
 			} else {
 				if ch == formfeed {
 					droppedFF = true
@@ -583,7 +603,8 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
 
 	// make sure we have a line break
 	if needsLinebreak {
-		p.write([]byte{'\n'})
+		p.writeByte('\n')
+		wroteNewline = true
 	}
 
 	return
@@ -592,24 +613,24 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
 // intersperseComments consumes all comments that appear before the next token
 // tok and prints it together with the buffered whitespace (i.e., the whitespace
 // that needs to be written before the next token). A heuristic is used to mix
-// the comments and whitespace. intersperseComments returns true if a pending
-// formfeed was dropped from the whitespace buffer.
+// the comments and whitespace. The intersperseComments result indicates if a
+// newline was written or if a formfeed was dropped from the whitespace buffer.
 //
-func (p *printer) intersperseComments(next token.Position, tok token.Token) (droppedFF bool) {
+func (p *printer) intersperseComments(next token.Position, tok token.Token) (wroteNewline, droppedFF bool) {
 	var last *ast.Comment
 	for ; p.commentBefore(next); p.cindex++ {
 		for _, c := range p.comments[p.cindex].List {
-			p.writeCommentPrefix(p.fset.Position(c.Pos()), next, last, tok.IsKeyword())
+			p.writeCommentPrefix(p.posFor(c.Pos()), next, last, c, tok.IsKeyword())
 			p.writeComment(c)
 			last = c
 		}
 	}
 
 	if last != nil {
-		if last.Text[1] == '*' && p.fset.Position(last.Pos()).Line == next.Line {
+		if last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line {
 			// the last comment is a /*-style comment and the next item
 			// follows on the same line: separate with an extra blank
-			p.write([]byte{' '})
+			p.writeByte(' ')
 		}
 		// ensure that there is a line break after a //-style comment,
 		// before a closing '}' unless explicitly disabled, or at eof
@@ -623,13 +644,12 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (dro
 	// no comment was written - we should never reach here since
 	// intersperseComments should not be called in that case
 	p.internalError("intersperseComments called without pending comments")
-	return false
+	return
 }
 
 // whiteWhitespace writes the first n whitespace entries.
 func (p *printer) writeWhitespace(n int) {
 	// write entries
-	var data [1]byte
 	for i := 0; i < n; i++ {
 		switch ch := p.wsbuf[i]; ch {
 		case ignore:
@@ -661,8 +681,7 @@ func (p *printer) writeWhitespace(n int) {
 			}
 			fallthrough
 		default:
-			data[0] = byte(ch)
-			p.write(data[0:])
+			p.writeByte(byte(ch))
 		}
 	}
 
@@ -678,6 +697,13 @@ func (p *printer) writeWhitespace(n int) {
 // ----------------------------------------------------------------------------
 // Printing interface
 
+// nlines limits n to maxNewlines.
+func nlimit(n int) int {
+	if n > maxNewlines {
+		n = maxNewlines
+	}
+	return n
+}
 
 func mayCombine(prev token.Token, next byte) (b bool) {
 	switch prev {
@@ -711,7 +737,8 @@ func mayCombine(prev token.Token, next byte) (b bool) {
 func (p *printer) print(args ...interface{}) {
 	for _, f := range args {
 		next := p.pos // estimated position of next item
-		var data string
+		data := ""
+		isLit := false
 		var tok token.Token
 
 		switch x := f.(type) {
@@ -739,7 +766,8 @@ func (p *printer) print(args ...interface{}) {
 			data = x.Name
 			tok = token.IDENT
 		case *ast.BasicLit:
-			data = p.escape(x.Value)
+			data = x.Value
+			isLit = true
 			tok = x.Kind
 		case token.Token:
 			s := x.String()
@@ -760,26 +788,41 @@ func (p *printer) print(args ...interface{}) {
 			tok = x
 		case token.Pos:
 			if x.IsValid() {
-				next = p.fset.Position(x) // accurate position of next item
+				next = p.posFor(x) // accurate position of next item
 			}
 			tok = p.lastTok
+		case string:
+			// incorrect AST - print error message
+			data = x
+			isLit = true
+			tok = token.STRING
 		default:
-			fmt.Fprintf(os.Stderr, "print: unsupported argument type %T\n", f)
+			fmt.Fprintf(os.Stderr, "print: unsupported argument %v (%T)\n", f, f)
 			panic("go/printer type")
 		}
 		p.lastTok = tok
 		p.pos = next
 
 		if data != "" {
-			droppedFF := p.flush(next, tok)
+			wroteNewline, droppedFF := p.flush(next, tok)
 
 			// intersperse extra newlines if present in the source
 			// (don't do this in flush as it will cause extra newlines
-			// at the end of a file) - use formfeeds if we dropped one
-			// before
-			p.writeNewlines(next.Line-p.pos.Line, droppedFF)
+			// at the end of a file)
+			n := nlimit(next.Line - p.pos.Line)
+			// don't exceed maxNewlines if we already wrote one
+			if wroteNewline && n == maxNewlines {
+				n = maxNewlines - 1
+			}
+			if n > 0 {
+				ch := byte('\n')
+				if droppedFF {
+					ch = '\f' // use formfeed since we dropped one before
+				}
+				p.writeByteN(ch, n)
+			}
 
-			p.writeItem(next, data)
+			p.writeItem(next, data, isLit)
 		}
 	}
 }
@@ -788,19 +831,18 @@ func (p *printer) print(args ...interface{}) {
 // before the next position in the source code.
 //
 func (p *printer) commentBefore(next token.Position) bool {
-	return p.cindex < len(p.comments) && p.fset.Position(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset
+	return p.cindex < len(p.comments) && p.posFor(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset
 }
 
-// Flush prints any pending comments and whitespace occurring
-// textually before the position of the next token tok. Flush
-// returns true if a pending formfeed character was dropped
-// from the whitespace buffer as a result of interspersing
-// comments.
+// Flush prints any pending comments and whitespace occurring textually
+// before the position of the next token tok. The Flush result indicates
+// if a newline was written or if a formfeed was dropped from the whitespace
+// buffer.
 //
-func (p *printer) flush(next token.Position, tok token.Token) (droppedFF bool) {
+func (p *printer) flush(next token.Position, tok token.Token) (wroteNewline, droppedFF bool) {
 	if p.commentBefore(next) {
 		// if there are comments before the next item, intersperse them
-		droppedFF = p.intersperseComments(next, tok)
+		wroteNewline, droppedFF = p.intersperseComments(next, tok)
 	} else {
 		// otherwise, write any leftover whitespace
 		p.writeWhitespace(len(p.wsbuf))
@@ -808,6 +850,98 @@ func (p *printer) flush(next token.Position, tok token.Token) (droppedFF bool) {
 	return
 }
 
+// getNode returns the ast.CommentGroup associated with n, if any.
+func getDoc(n ast.Node) *ast.CommentGroup {
+	switch n := n.(type) {
+	case *ast.Field:
+		return n.Doc
+	case *ast.ImportSpec:
+		return n.Doc
+	case *ast.ValueSpec:
+		return n.Doc
+	case *ast.TypeSpec:
+		return n.Doc
+	case *ast.GenDecl:
+		return n.Doc
+	case *ast.FuncDecl:
+		return n.Doc
+	case *ast.File:
+		return n.Doc
+	}
+	return nil
+}
+
+func (p *printer) printNode(node interface{}) error {
+	// unpack *CommentedNode, if any
+	var comments []*ast.CommentGroup
+	if cnode, ok := node.(*CommentedNode); ok {
+		node = cnode.Node
+		comments = cnode.Comments
+	}
+
+	if comments != nil {
+		// commented node - restrict comment list to relevant range
+		n, ok := node.(ast.Node)
+		if !ok {
+			goto unsupported
+		}
+		beg := n.Pos()
+		end := n.End()
+		// if the node has associated documentation,
+		// include that commentgroup in the range
+		// (the comment list is sorted in the order
+		// of the comment appearance in the source code)
+		if doc := getDoc(n); doc != nil {
+			beg = doc.Pos()
+		}
+		// token.Pos values are global offsets, we can
+		// compare them directly
+		i := 0
+		for i < len(comments) && comments[i].End() < beg {
+			i++
+		}
+		j := i
+		for j < len(comments) && comments[j].Pos() < end {
+			j++
+		}
+		if i < j {
+			p.comments = comments[i:j]
+		}
+	} else if n, ok := node.(*ast.File); ok {
+		// use ast.File comments, if any
+		p.comments = n.Comments
+	}
+
+	// if there are no comments, use node comments
+	p.useNodeComments = p.comments == nil
+
+	// format node
+	switch n := node.(type) {
+	case ast.Expr:
+		p.expr(n, ignoreMultiLine)
+	case ast.Stmt:
+		// A labeled statement will un-indent to position the
+		// label. Set indent to 1 so we don't get indent "underflow".
+		if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
+			p.indent = 1
+		}
+		p.stmt(n, false, ignoreMultiLine)
+	case ast.Decl:
+		p.decl(n, ignoreMultiLine)
+	case ast.Spec:
+		p.spec(n, 1, false, ignoreMultiLine)
+	case *ast.File:
+		p.file(n)
+	default:
+		goto unsupported
+	}
+
+	return nil
+
+unsupported:
+	return fmt.Errorf("go/printer: unsupported node type %T", node)
+}
+
 // ----------------------------------------------------------------------------
 // Trimmer
 
@@ -837,7 +971,9 @@ const (
 //              However, this would mess up any formatting done by
 //              the tabwriter.
 
-func (p *trimmer) Write(data []byte) (n int, err os.Error) {
+var aNewline = []byte("\n")
+
+func (p *trimmer) Write(data []byte) (n int, err error) {
 	// invariants:
 	// p.state == inSpace:
 	//	p.space is unwritten
@@ -855,8 +991,8 @@ func (p *trimmer) Write(data []byte) (n int, err os.Error) {
 			case '\t', ' ':
 				p.space.WriteByte(b) // WriteByte returns no errors
 			case '\n', '\f':
-				p.space.Reset()                        // discard trailing space
-				_, err = p.output.Write(newlines[0:1]) // write newline
+				p.space.Reset() // discard trailing space
+				_, err = p.output.Write(aNewline)
 			case tabwriter.Escape:
 				_, err = p.output.Write(p.space.Bytes())
 				p.state = inEscape
@@ -883,7 +1019,7 @@ func (p *trimmer) Write(data []byte) (n int, err os.Error) {
 				_, err = p.output.Write(data[m:n])
 				p.state = inSpace
 				p.space.Reset()
-				_, err = p.output.Write(newlines[0:1]) // write newline
+				_, err = p.output.Write(aNewline)
 			case tabwriter.Escape:
 				_, err = p.output.Write(data[m:n])
 				p.state = inEscape
@@ -925,15 +1061,22 @@ type Config struct {
 }
 
 // fprint implements Fprint and takes a nodesSizes map for setting up the printer state.
-func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{}, nodeSizes map[ast.Node]int) (written int, err os.Error) {
+func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{}, nodeSizes map[ast.Node]int) (err error) {
+	// print node
+	var p printer
+	p.init(cfg, fset, nodeSizes)
+	if err = p.printNode(node); err != nil {
+		return
+	}
+	p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF)
+
 	// redirect output through a trimmer to eliminate trailing whitespace
 	// (Input to a tabwriter must be untrimmed since trailing tabs provide
 	// formatting information. The tabwriter could provide trimming
 	// functionality but no tabwriter is used when RawFormat is set.)
 	output = &trimmer{output: output}
 
-	// setup tabwriter if needed and redirect output
-	var tw *tabwriter.Writer
+	// redirect output through a tabwriter if necessary
 	if cfg.Mode&RawFormat == 0 {
 		minwidth := cfg.Tabwidth
 
@@ -948,70 +1091,42 @@ func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{
 			twmode |= tabwriter.TabIndent
 		}
 
-		tw = tabwriter.NewWriter(output, minwidth, cfg.Tabwidth, 1, padchar, twmode)
-		output = tw
+		output = tabwriter.NewWriter(output, minwidth, cfg.Tabwidth, 1, padchar, twmode)
 	}
 
-	// setup printer
-	var p printer
-	p.init(output, cfg, fset, nodeSizes)
-	defer func() {
-		written = p.written
-		if e := recover(); e != nil {
-			err = e.(osError).err // re-panics if it's not a local osError
-		}
-	}()
-
-	// print node
-	switch n := node.(type) {
-	case ast.Expr:
-		p.useNodeComments = true
-		p.expr(n, ignoreMultiLine)
-	case ast.Stmt:
-		p.useNodeComments = true
-		// A labeled statement will un-indent to position the
-		// label. Set indent to 1 so we don't get indent "underflow".
-		if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
-			p.indent = 1
-		}
-		p.stmt(n, false, ignoreMultiLine)
-	case ast.Decl:
-		p.useNodeComments = true
-		p.decl(n, ignoreMultiLine)
-	case ast.Spec:
-		p.useNodeComments = true
-		p.spec(n, 1, false, ignoreMultiLine)
-	case *ast.File:
-		p.comments = n.Comments
-		p.useNodeComments = n.Comments == nil
-		p.file(n)
-	default:
-		panic(osError{fmt.Errorf("printer.Fprint: unsupported node type %T", n)})
+	// write printer result via tabwriter/trimmer to output
+	if _, err = output.Write(p.output.Bytes()); err != nil {
+		return
 	}
-	p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF)
 
 	// flush tabwriter, if any
-	if tw != nil {
-		tw.Flush() // ignore errors
+	if tw, _ := (output).(*tabwriter.Writer); tw != nil {
+		err = tw.Flush()
 	}
 
 	return
 }
 
-// Fprint "pretty-prints" an AST node to output and returns the number
-// of bytes written and an error (if any) for a given configuration cfg.
+// A CommentedNode bundles an AST node and corresponding comments.
+// It may be provided as argument to any of the FPrint functions.
+//
+type CommentedNode struct {
+	Node     interface{} // *ast.File, or ast.Expr, ast.Decl, ast.Spec, or ast.Stmt
+	Comments []*ast.CommentGroup
+}
+
+// Fprint "pretty-prints" an AST node to output for a given configuration cfg.
 // Position information is interpreted relative to the file set fset.
-// The node type must be *ast.File, or assignment-compatible to ast.Expr,
-// ast.Decl, ast.Spec, or ast.Stmt.
+// The node type must be *ast.File, *CommentedNode, or assignment-compatible
+// to ast.Expr, ast.Decl, ast.Spec, or ast.Stmt.
 //
-func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{}) (int, os.Error) {
+func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{}) error {
 	return cfg.fprint(output, fset, node, make(map[ast.Node]int))
 }
 
 // Fprint "pretty-prints" an AST node to output.
 // It calls Config.Fprint with default settings.
 //
-func Fprint(output io.Writer, fset *token.FileSet, node interface{}) os.Error {
-	_, err := (&Config{Tabwidth: 8}).Fprint(output, fset, node) // don't care about number of bytes written
-	return err
+func Fprint(output io.Writer, fset *token.FileSet, node interface{}) error {
+	return (&Config{Tabwidth: 8}).Fprint(output, fset, node)
 }
diff --git a/src/pkg/go/printer/printer_test.go b/src/pkg/go/printer/printer_test.go
index a644aa3..525fcc1 100644
--- a/src/pkg/go/printer/printer_test.go
+++ b/src/pkg/go/printer/printer_test.go
@@ -62,7 +62,7 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) {
 
 	// format source
 	var buf bytes.Buffer
-	if _, err := cfg.Fprint(&buf, fset, prog); err != nil {
+	if err := cfg.Fprint(&buf, fset, prog); err != nil {
 		t.Error(err)
 	}
 	res := buf.Bytes()
@@ -107,7 +107,7 @@ func check(t *testing.T, source, golden string, mode checkMode) {
 	// start a timer to produce a time-out signal
 	tc := make(chan int)
 	go func() {
-		time.Sleep(10e9) // plenty of a safety margin, even for very slow machines
+		time.Sleep(10 * time.Second) // plenty of a safety margin, even for very slow machines
 		tc <- 0
 	}()
 
@@ -204,3 +204,18 @@ func init() {
 		panic("got " + s + ", want " + name)
 	}
 }
+
+// Verify that the printer doesn't crash if the AST contains BadXXX nodes.
+func TestBadNodes(t *testing.T) {
+	const src = "package p\n("
+	const res = "package p\nBadDecl\n"
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err == nil {
+		t.Errorf("expected illegal program")
+	}
+	var buf bytes.Buffer
+	Fprint(&buf, fset, f)
+	if buf.String() != res {
+		t.Errorf("got %q, expected %q", buf.String(), res)
+	}
+}
diff --git a/src/pkg/go/printer/testdata/comments.golden b/src/pkg/go/printer/testdata/comments.golden
index 7b33225..d2ad9e3 100644
--- a/src/pkg/go/printer/testdata/comments.golden
+++ b/src/pkg/go/printer/testdata/comments.golden
@@ -106,7 +106,7 @@ type S3 struct {
 var x int	// x
 var ()
 
-// This comment SHOULD be associated with the next declaration.
+// This comment SHOULD be associated with f0.
 func f0() {
 	const pi = 3.14	// pi
 	var s1 struct{}	/* an empty struct */	/* foo */
@@ -115,8 +115,9 @@ func f0() {
 	var s2 struct{} = struct{}{}
 	x := pi
 }
+
 //
-// NO SPACE HERE
+// This comment should be associated with f1, with one blank line before the comment.
 //
 func f1() {
 	f0()
diff --git a/src/pkg/go/printer/testdata/comments.input b/src/pkg/go/printer/testdata/comments.input
index 2a9a86b..222e0a7 100644
--- a/src/pkg/go/printer/testdata/comments.input
+++ b/src/pkg/go/printer/testdata/comments.input
@@ -107,7 +107,7 @@ var x int  // x
 var ()
 
 
-// This comment SHOULD be associated with the next declaration.
+// This comment SHOULD be associated with f0.
 func f0() {
 	const pi = 3.14  // pi
 	var s1 struct {}  /* an empty struct */ /* foo */
@@ -117,7 +117,7 @@ func f0() {
 	x := pi
 }
 //
-// NO SPACE HERE
+// This comment should be associated with f1, with one blank line before the comment.
 //
 func f1() {
 	f0()
@@ -130,7 +130,7 @@ func f1() {
 
 
 func _() {
-	// this comment should be properly indented
+// this comment should be properly indented
 }
 
 
diff --git a/src/pkg/go/printer/testdata/declarations.golden b/src/pkg/go/printer/testdata/declarations.golden
index bfa2568..928b8ce 100644
--- a/src/pkg/go/printer/testdata/declarations.golden
+++ b/src/pkg/go/printer/testdata/declarations.golden
@@ -115,6 +115,18 @@ import _ "io"
 
 var _ int
 
+// at least one empty line between declarations of the same kind
+// if there is associated documentation (was issue 2570)
+type T1 struct{}
+
+// T2 comment
+type T2 struct {
+}	// should be a two-line struct
+
+// T3 comment
+type T2 struct {
+}	// should be a two-line struct
+
 // printing of constant literals
 const (
 	_	= "foobar"
@@ -286,6 +298,15 @@ type _ struct {
 	}
 }
 
+// no blank lines in empty structs and interfaces, but leave 1- or 2-line layout alone
+type _ struct{}
+type _ struct {
+}
+
+type _ interface{}
+type _ interface {
+}
+
 // no tabs for single or ungrouped decls
 func _() {
 	const xxxxxx = 0
@@ -752,30 +773,39 @@ func ManageStatus(in <-chan *Status, req <-chan Request,
 	TargetHistorySize int) {
 }
 
-func MultiLineSignature0(a, b, c int) {
+func MultiLineSignature0(
+	a, b, c int,
+) {
 }
 
-func MultiLineSignature1(a, b, c int,
-	u, v, w float) {
+func MultiLineSignature1(
+	a, b, c int,
+	u, v, w float,
+) {
 }
 
-func MultiLineSignature2(a, b,
-	c int) {
+func MultiLineSignature2(
+	a, b,
+	c int,
+) {
 }
 
-func MultiLineSignature3(a, b,
+func MultiLineSignature3(
+	a, b,
 	c int, u, v,
 	w float,
 	x ...int) {
 }
 
-func MultiLineSignature4(a, b, c int,
+func MultiLineSignature4(
+	a, b, c int,
 	u, v,
 	w float,
 	x ...int) {
 }
 
-func MultiLineSignature5(a, b, c int,
+func MultiLineSignature5(
+	a, b, c int,
 	u, v, w float,
 	p, q,
 	r string,
@@ -784,25 +814,34 @@ func MultiLineSignature5(a, b, c int,
 
 // make sure it also works for methods in interfaces
 type _ interface {
-	MultiLineSignature0(a, b, c int)
+	MultiLineSignature0(
+		a, b, c int,
+	)
 
-	MultiLineSignature1(a, b, c int,
-		u, v, w float)
+	MultiLineSignature1(
+		a, b, c int,
+		u, v, w float,
+	)
 
-	MultiLineSignature2(a, b,
-		c int)
+	MultiLineSignature2(
+		a, b,
+		c int,
+	)
 
-	MultiLineSignature3(a, b,
+	MultiLineSignature3(
+		a, b,
 		c int, u, v,
 		w float,
 		x ...int)
 
-	MultiLineSignature4(a, b, c int,
+	MultiLineSignature4(
+		a, b, c int,
 		u, v,
 		w float,
 		x ...int)
 
-	MultiLineSignature5(a, b, c int,
+	MultiLineSignature5(
+		a, b, c int,
 		u, v, w float,
 		p, q,
 		r string,
diff --git a/src/pkg/go/printer/testdata/declarations.input b/src/pkg/go/printer/testdata/declarations.input
index 1d69c57..68f9030 100644
--- a/src/pkg/go/printer/testdata/declarations.input
+++ b/src/pkg/go/printer/testdata/declarations.input
@@ -115,6 +115,20 @@ import (
 import _ "io"
 var _ int
 
+// at least one empty line between declarations of the same kind
+// if there is associated documentation (was issue 2570)
+type T1 struct{}
+// T2 comment
+type T2 struct {
+} // should be a two-line struct
+
+
+// T3 comment
+type T2 struct {
+
+
+} // should be a two-line struct
+
 
 // printing of constant literals
 const (
@@ -293,6 +307,18 @@ type _ struct {
 }
 
 
+// no blank lines in empty structs and interfaces, but leave 1- or 2-line layout alone
+type _ struct{            }
+type _ struct {
+
+}
+
+type _ interface{            }
+type _ interface {
+
+}
+
+
 // no tabs for single or ungrouped decls
 func _() {
 	const xxxxxx = 0
diff --git a/src/pkg/go/printer/testdata/linebreaks.golden b/src/pkg/go/printer/testdata/linebreaks.golden
index be780da..006cf17 100644
--- a/src/pkg/go/printer/testdata/linebreaks.golden
+++ b/src/pkg/go/printer/testdata/linebreaks.golden
@@ -220,4 +220,56 @@ testLoop:
 	}
 }
 
+// Respect line breaks in function calls.
+func _() {
+	f(x)
+	f(x,
+		x)
+	f(x,
+		x,
+	)
+	f(
+		x,
+		x)
+	f(
+		x,
+		x,
+	)
+}
+
+// Respect line breaks in function declarations.
+func _(x T)	{}
+func _(x T,
+	y T) {
+}
+func _(x T,
+	y T,
+) {
+}
+func _(
+	x T,
+	y T) {
+}
+func _(
+	x T,
+	y T,
+) {
+}
+
+// Example from issue 2597.
+func ManageStatus0(
+	in <-chan *Status,
+	req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int) {
+}
+
+func ManageStatus1(
+	in <-chan *Status,
+	req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int,
+) {
+}
+
 // There should be exactly one linebreak after this comment.
diff --git a/src/pkg/go/printer/testdata/linebreaks.input b/src/pkg/go/printer/testdata/linebreaks.input
index 457b491..e782bb0 100644
--- a/src/pkg/go/printer/testdata/linebreaks.input
+++ b/src/pkg/go/printer/testdata/linebreaks.input
@@ -220,4 +220,52 @@ testLoop:
 	}
 }
 
+// Respect line breaks in function calls.
+func _() {
+	f(x)
+	f(x,
+	  x)
+	f(x,
+	  x,
+	)
+	f(
+	  x,
+	  x)
+	f(
+	  x,
+	  x,
+	)
+}
+
+// Respect line breaks in function declarations.
+func _(x T) {}
+func _(x T,
+       y T) {}
+func _(x T,
+       y T,
+) {}
+func _(
+       x T,
+       y T) {}
+func _(
+       x T,
+       y T,
+) {}
+
+// Example from issue 2597.
+func ManageStatus0(
+	in <-chan *Status,
+	req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int) {
+}
+    
+func ManageStatus1(
+	in <-chan *Status,
+	req <-chan Request,
+	stat chan<- *TargetInfo,
+	TargetHistorySize int,
+) {
+}
+    
 // There should be exactly one linebreak after this comment.
diff --git a/src/pkg/go/printer/testdata/parser.go b/src/pkg/go/printer/testdata/parser.go
index 2d27af4..89e341c 100644
--- a/src/pkg/go/printer/testdata/parser.go
+++ b/src/pkg/go/printer/testdata/parser.go
@@ -1999,7 +1999,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
 	if par.NumFields() != 1 {
 		p.errorExpected(pos, "exactly one receiver")
 		// TODO determine a better range for BadExpr below
-		par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{pos, pos}}}
+		par.List = []*ast.Field{{Type: &ast.BadExpr{pos, pos}}}
 		return par
 	}
 
@@ -2008,7 +2008,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
 	base := deref(recv.Type)
 	if _, isIdent := base.(*ast.Ident); !isIdent {
 		p.errorExpected(base.Pos(), "(unqualified) identifier")
-		par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
+		par.List = []*ast.Field{{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
 	}
 
 	return par
diff --git a/src/pkg/go/printer/testdata/statements.golden b/src/pkg/go/printer/testdata/statements.golden
index a6d8510..90e1743 100644
--- a/src/pkg/go/printer/testdata/statements.golden
+++ b/src/pkg/go/printer/testdata/statements.golden
@@ -271,7 +271,6 @@ func _() {
 	// Known bug: The first use call may have more than one empty line before
 	//            (see go/printer/nodes.go, func linebreak).
 
-
 	use(x)
 
 	if x < x {
@@ -386,7 +385,6 @@ L:	// A comment on the same line as the label, followed by a single empty line.
 	// Known bug: There may be more than one empty line before MoreCode()
 	//            (see go/printer/nodes.go, func linebreak).
 
-
 	MoreCode()
 }
 
diff --git a/src/pkg/go/scanner/errors.go b/src/pkg/go/scanner/errors.go
index a0927e4..cd9620b 100644
--- a/src/pkg/go/scanner/errors.go
+++ b/src/pkg/go/scanner/errors.go
@@ -8,7 +8,6 @@ import (
 	"fmt"
 	"go/token"
 	"io"
-	"os"
 	"sort"
 )
 
@@ -49,7 +48,7 @@ type Error struct {
 	Msg string
 }
 
-func (e *Error) String() string {
+func (e *Error) Error() string {
 	if e.Pos.Filename != "" || e.Pos.IsValid() {
 		// don't print "<unknown position>"
 		// TODO(gri) reconsider the semantics of Position.IsValid
@@ -85,14 +84,14 @@ func (p ErrorList) Less(i, j int) bool {
 	return false
 }
 
-func (p ErrorList) String() string {
+func (p ErrorList) Error() string {
 	switch len(p) {
 	case 0:
 		return "unspecified error"
 	case 1:
-		return p[0].String()
+		return p[0].Error()
 	}
-	return fmt.Sprintf("%s (and %d more errors)", p[0].String(), len(p)-1)
+	return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1)
 }
 
 // These constants control the construction of the ErrorList
@@ -136,11 +135,11 @@ func (h *ErrorVector) GetErrorList(mode int) ErrorList {
 	return list
 }
 
-// GetError is like GetErrorList, but it returns an os.Error instead
-// so that a nil result can be assigned to an os.Error variable and
+// GetError is like GetErrorList, but it returns an error instead
+// so that a nil result can be assigned to an error variable and
 // remains nil.
 //
-func (h *ErrorVector) GetError(mode int) os.Error {
+func (h *ErrorVector) GetError(mode int) error {
 	if len(h.errors) == 0 {
 		return nil
 	}
@@ -157,7 +156,7 @@ func (h *ErrorVector) Error(pos token.Position, msg string) {
 // one error per line, if the err parameter is an ErrorList. Otherwise
 // it prints the err string.
 //
-func PrintError(w io.Writer, err os.Error) {
+func PrintError(w io.Writer, err error) {
 	if list, ok := err.(ErrorList); ok {
 		for _, e := range list {
 			fmt.Fprintf(w, "%s\n", e)
diff --git a/src/pkg/go/scanner/scanner.go b/src/pkg/go/scanner/scanner.go
index 7f3dd23..7c72c0a 100644
--- a/src/pkg/go/scanner/scanner.go
+++ b/src/pkg/go/scanner/scanner.go
@@ -6,7 +6,7 @@
 // source which can then be tokenized through repeated calls to the Scan
 // function. Typical use:
 //
-//	var s Scanner
+//	var s scanner.Scanner
 //	fset := token.NewFileSet()  // position information is relative to fset
 //      file := fset.AddFile(filename, fset.Base(), len(src))  // register file
 //	s.Init(file, src, nil /* no error handler */, 0)
@@ -27,7 +27,7 @@ import (
 	"path/filepath"
 	"strconv"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 // A Scanner holds the scanner's internal state while processing
@@ -40,10 +40,10 @@ type Scanner struct {
 	dir  string       // directory portion of file.Name()
 	src  []byte       // source
 	err  ErrorHandler // error reporting; or nil
-	mode uint         // scanning mode
+	mode Mode         // scanning mode
 
 	// scanning state
-	ch         int  // current character
+	ch         rune // current character
 	offset     int  // character offset
 	rdOffset   int  // reading offset (position after current character)
 	lineOffset int  // current line offset
@@ -63,7 +63,7 @@ func (S *Scanner) next() {
 			S.lineOffset = S.offset
 			S.file.AddLine(S.offset)
 		}
-		r, w := int(S.src[S.rdOffset]), 1
+		r, w := rune(S.src[S.rdOffset]), 1
 		switch {
 		case r == 0:
 			S.error(S.offset, "illegal character NUL")
@@ -86,13 +86,14 @@ func (S *Scanner) next() {
 	}
 }
 
-// The mode parameter to the Init function is a set of flags (or 0).
+// A mode value is set of flags (or 0).
 // They control scanner behavior.
 //
+type Mode uint
+
 const (
-	ScanComments      = 1 << iota // return comments as COMMENT tokens
-	AllowIllegalChars             // do not report an error for illegal chars
-	InsertSemis                   // automatically insert semicolons
+	ScanComments    Mode = 1 << iota // return comments as COMMENT tokens
+	dontInsertSemis                  // do not automatically insert semicolons - for testing only
 )
 
 // Init prepares the scanner S to tokenize the text src by setting the
@@ -105,12 +106,12 @@ const (
 // Calls to Scan will use the error handler err if they encounter a
 // syntax error and err is not nil. Also, for each error encountered,
 // the Scanner field ErrorCount is incremented by one. The mode parameter
-// determines how comments, illegal characters, and semicolons are handled.
+// determines how comments are handled.
 //
 // Note that Init may call err if there is an error in the first character
 // of the file.
 //
-func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode uint) {
+func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) {
 	// Explicitly initialize all fields since a scanner may be reused.
 	if file.Size() != len(src) {
 		panic("file size does not match src len")
@@ -152,13 +153,13 @@ func (S *Scanner) interpretLineComment(text []byte) {
 					filename = filepath.Join(S.dir, filename)
 				}
 				// update scanner position
-				S.file.AddLineInfo(S.lineOffset, filename, line-1) // -1 since comment applies to next line
+				S.file.AddLineInfo(S.lineOffset+len(text)+1, filename, line) // +len(text)+1 since comment applies to next line
 			}
 		}
 	}
 }
 
-func (S *Scanner) scanComment() {
+func (S *Scanner) scanComment() string {
 	// initial '/' already consumed; S.ch == '/' || S.ch == '*'
 	offs := S.offset - 1 // position of initial '/'
 
@@ -172,7 +173,7 @@ func (S *Scanner) scanComment() {
 			// comment starts at the beginning of the current line
 			S.interpretLineComment(S.src[offs:S.offset])
 		}
-		return
+		goto exit
 	}
 
 	/*-style comment */
@@ -182,11 +183,14 @@ func (S *Scanner) scanComment() {
 		S.next()
 		if ch == '*' && S.ch == '/' {
 			S.next()
-			return
+			goto exit
 		}
 	}
 
 	S.error(offs, "comment not terminated")
+
+exit:
+	return string(S.src[offs:S.offset])
 }
 
 func (S *Scanner) findLineEnd() bool {
@@ -233,30 +237,30 @@ func (S *Scanner) findLineEnd() bool {
 	return false
 }
 
-func isLetter(ch int) bool {
+func isLetter(ch rune) bool {
 	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
 }
 
-func isDigit(ch int) bool {
+func isDigit(ch rune) bool {
 	return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
 }
 
-func (S *Scanner) scanIdentifier() token.Token {
+func (S *Scanner) scanIdentifier() string {
 	offs := S.offset
 	for isLetter(S.ch) || isDigit(S.ch) {
 		S.next()
 	}
-	return token.Lookup(S.src[offs:S.offset])
+	return string(S.src[offs:S.offset])
 }
 
-func digitVal(ch int) int {
+func digitVal(ch rune) int {
 	switch {
 	case '0' <= ch && ch <= '9':
-		return ch - '0'
+		return int(ch - '0')
 	case 'a' <= ch && ch <= 'f':
-		return ch - 'a' + 10
+		return int(ch - 'a' + 10)
 	case 'A' <= ch && ch <= 'F':
-		return ch - 'A' + 10
+		return int(ch - 'A' + 10)
 	}
 	return 16 // larger than any legal digit val
 }
@@ -267,11 +271,13 @@ func (S *Scanner) scanMantissa(base int) {
 	}
 }
 
-func (S *Scanner) scanNumber(seenDecimalPoint bool) token.Token {
+func (S *Scanner) scanNumber(seenDecimalPoint bool) (token.Token, string) {
 	// digitVal(S.ch) < 10
+	offs := S.offset
 	tok := token.INT
 
 	if seenDecimalPoint {
+		offs--
 		tok = token.FLOAT
 		S.scanMantissa(10)
 		goto exponent
@@ -335,10 +341,10 @@ exponent:
 	}
 
 exit:
-	return tok
+	return tok, string(S.src[offs:S.offset])
 }
 
-func (S *Scanner) scanEscape(quote int) {
+func (S *Scanner) scanEscape(quote rune) {
 	offs := S.offset
 
 	var i, base, max uint32
@@ -382,7 +388,7 @@ func (S *Scanner) scanEscape(quote int) {
 	}
 }
 
-func (S *Scanner) scanChar() {
+func (S *Scanner) scanChar() string {
 	// '\'' opening already consumed
 	offs := S.offset - 1
 
@@ -406,9 +412,11 @@ func (S *Scanner) scanChar() {
 	if n != 1 {
 		S.error(offs, "illegal character literal")
 	}
+
+	return string(S.src[offs:S.offset])
 }
 
-func (S *Scanner) scanString() {
+func (S *Scanner) scanString() string {
 	// '"' opening already consumed
 	offs := S.offset - 1
 
@@ -425,15 +433,33 @@ func (S *Scanner) scanString() {
 	}
 
 	S.next()
+
+	return string(S.src[offs:S.offset])
+}
+
+func stripCR(b []byte) []byte {
+	c := make([]byte, len(b))
+	i := 0
+	for _, ch := range b {
+		if ch != '\r' {
+			c[i] = ch
+			i++
+		}
+	}
+	return c[:i]
 }
 
-func (S *Scanner) scanRawString() {
+func (S *Scanner) scanRawString() string {
 	// '`' opening already consumed
 	offs := S.offset - 1
 
+	hasCR := false
 	for S.ch != '`' {
 		ch := S.ch
 		S.next()
+		if ch == '\r' {
+			hasCR = true
+		}
 		if ch < 0 {
 			S.error(offs, "string not terminated")
 			break
@@ -441,6 +467,13 @@ func (S *Scanner) scanRawString() {
 	}
 
 	S.next()
+
+	lit := S.src[offs:S.offset]
+	if hasCR {
+		lit = stripCR(lit)
+	}
+
+	return string(lit)
 }
 
 func (S *Scanner) skipWhitespace() {
@@ -463,7 +496,7 @@ func (S *Scanner) switch2(tok0, tok1 token.Token) token.Token {
 	return tok0
 }
 
-func (S *Scanner) switch3(tok0, tok1 token.Token, ch2 int, tok2 token.Token) token.Token {
+func (S *Scanner) switch3(tok0, tok1 token.Token, ch2 rune, tok2 token.Token) token.Token {
 	if S.ch == '=' {
 		S.next()
 		return tok1
@@ -475,7 +508,7 @@ func (S *Scanner) switch3(tok0, tok1 token.Token, ch2 int, tok2 token.Token) tok
 	return tok0
 }
 
-func (S *Scanner) switch4(tok0, tok1 token.Token, ch2 int, tok2, tok3 token.Token) token.Token {
+func (S *Scanner) switch4(tok0, tok1 token.Token, ch2 rune, tok2, tok3 token.Token) token.Token {
 	if S.ch == '=' {
 		S.next()
 		return tok1
@@ -491,15 +524,24 @@ func (S *Scanner) switch4(tok0, tok1 token.Token, ch2 int, tok2, tok3 token.Toke
 	return tok0
 }
 
-// Scan scans the next token and returns the token position,
-// the token, and the literal string corresponding to the
-// token. The source end is indicated by token.EOF.
+// Scan scans the next token and returns the token position, the token,
+// and its literal string if applicable. The source end is indicated by
+// token.EOF.
+//
+// If the returned token is a literal (token.IDENT, token.INT, token.FLOAT,
+// token.IMAG, token.CHAR, token.STRING) or token.COMMENT, the literal string
+// has the corresponding value.
 //
 // If the returned token is token.SEMICOLON, the corresponding
 // literal string is ";" if the semicolon was present in the source,
 // and "\n" if the semicolon was inserted because of a newline or
 // at EOF.
 //
+// If the returned token is token.ILLEGAL, the literal string is the
+// offending character.
+//
+// In all other cases, Scan returns an empty literal string.
+//
 // For more tolerant parsing, Scan will return a valid token if
 // possible even if a syntax error was encountered. Thus, even
 // if the resulting token sequence contains no illegal tokens,
@@ -511,33 +553,33 @@ func (S *Scanner) switch4(tok0, tok1 token.Token, ch2 int, tok2, tok3 token.Toke
 // set with Init. Token positions are relative to that file
 // and thus relative to the file set.
 //
-func (S *Scanner) Scan() (token.Pos, token.Token, string) {
+func (S *Scanner) Scan() (pos token.Pos, tok token.Token, lit string) {
 scanAgain:
 	S.skipWhitespace()
 
 	// current token start
-	insertSemi := false
-	offs := S.offset
-	tok := token.ILLEGAL
+	pos = S.file.Pos(S.offset)
 
 	// determine token value
+	insertSemi := false
 	switch ch := S.ch; {
 	case isLetter(ch):
-		tok = S.scanIdentifier()
+		lit = S.scanIdentifier()
+		tok = token.Lookup(lit)
 		switch tok {
 		case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
 			insertSemi = true
 		}
 	case digitVal(ch) < 10:
 		insertSemi = true
-		tok = S.scanNumber(false)
+		tok, lit = S.scanNumber(false)
 	default:
 		S.next() // always make progress
 		switch ch {
 		case -1:
 			if S.insertSemi {
 				S.insertSemi = false // EOF consumed
-				return S.file.Pos(offs), token.SEMICOLON, "\n"
+				return pos, token.SEMICOLON, "\n"
 			}
 			tok = token.EOF
 		case '\n':
@@ -545,25 +587,25 @@ scanAgain:
 			// set in the first place and exited early
 			// from S.skipWhitespace()
 			S.insertSemi = false // newline consumed
-			return S.file.Pos(offs), token.SEMICOLON, "\n"
+			return pos, token.SEMICOLON, "\n"
 		case '"':
 			insertSemi = true
 			tok = token.STRING
-			S.scanString()
+			lit = S.scanString()
 		case '\'':
 			insertSemi = true
 			tok = token.CHAR
-			S.scanChar()
+			lit = S.scanChar()
 		case '`':
 			insertSemi = true
 			tok = token.STRING
-			S.scanRawString()
+			lit = S.scanRawString()
 		case ':':
 			tok = S.switch2(token.COLON, token.DEFINE)
 		case '.':
 			if digitVal(S.ch) < 10 {
 				insertSemi = true
-				tok = S.scanNumber(true)
+				tok, lit = S.scanNumber(true)
 			} else if S.ch == '.' {
 				S.next()
 				if S.ch == '.' {
@@ -577,6 +619,7 @@ scanAgain:
 			tok = token.COMMA
 		case ';':
 			tok = token.SEMICOLON
+			lit = ";"
 		case '(':
 			tok = token.LPAREN
 		case ')':
@@ -610,12 +653,12 @@ scanAgain:
 				if S.insertSemi && S.findLineEnd() {
 					// reset position to the beginning of the comment
 					S.ch = '/'
-					S.offset = offs
-					S.rdOffset = offs + 1
+					S.offset = S.file.Offset(pos)
+					S.rdOffset = S.offset + 1
 					S.insertSemi = false // newline consumed
-					return S.file.Pos(offs), token.SEMICOLON, "\n"
+					return pos, token.SEMICOLON, "\n"
 				}
-				S.scanComment()
+				lit = S.scanComment()
 				if S.mode&ScanComments == 0 {
 					// skip comment
 					S.insertSemi = false // newline consumed
@@ -652,19 +695,15 @@ scanAgain:
 		case '|':
 			tok = S.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR)
 		default:
-			if S.mode&AllowIllegalChars == 0 {
-				S.error(offs, fmt.Sprintf("illegal character %#U", ch))
-			}
+			S.error(S.file.Offset(pos), fmt.Sprintf("illegal character %#U", ch))
 			insertSemi = S.insertSemi // preserve insertSemi info
+			tok = token.ILLEGAL
+			lit = string(ch)
 		}
 	}
-
-	if S.mode&InsertSemis != 0 {
+	if S.mode&dontInsertSemis == 0 {
 		S.insertSemi = insertSemi
 	}
 
-	// TODO(gri): The scanner API should change such that the literal string
-	//            is only valid if an actual literal was scanned. This will
-	//            permit a more efficient implementation.
-	return S.file.Pos(offs), tok, string(S.src[offs:S.offset])
+	return
 }
diff --git a/src/pkg/go/scanner/scanner_test.go b/src/pkg/go/scanner/scanner_test.go
index eb9e1cb..af45bc5 100644
--- a/src/pkg/go/scanner/scanner_test.go
+++ b/src/pkg/go/scanner/scanner_test.go
@@ -83,6 +83,8 @@ var tokens = [...]elt{
 		"`",
 		literal,
 	},
+	{token.STRING, "`\r`", literal},
+	{token.STRING, "`foo\r\nbar`", literal},
 
 	// Operators and delimiters
 	{token.ADD, "+", operator},
@@ -175,6 +177,15 @@ var tokens = [...]elt{
 
 const whitespace = "  \t  \n\n\n" // to separate tokens
 
+var source = func() []byte {
+	var src []byte
+	for _, t := range tokens {
+		src = append(src, t.lit...)
+		src = append(src, whitespace...)
+	}
+	return src
+}()
+
 type testErrorHandler struct {
 	t *testing.T
 }
@@ -212,20 +223,20 @@ func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) {
 // Verify that calling Scan() provides the correct results.
 func TestScan(t *testing.T) {
 	// make source
-	var src string
-	for _, e := range tokens {
-		src += e.lit + whitespace
-	}
-	src_linecount := newlineCount(src)
+	src_linecount := newlineCount(string(source))
 	whitespace_linecount := newlineCount(whitespace)
 
 	// verify scan
 	var s Scanner
-	s.Init(fset.AddFile("", fset.Base(), len(src)), []byte(src), &testErrorHandler{t}, ScanComments)
+	s.Init(fset.AddFile("", fset.Base(), len(source)), source, &testErrorHandler{t}, ScanComments|dontInsertSemis)
 	index := 0
 	epos := token.Position{"", 0, 1, 1} // expected position
 	for {
 		pos, tok, lit := s.Scan()
+		if lit == "" {
+			// no literal value for non-literal tokens
+			lit = tok.String()
+		}
 		e := elt{token.EOF, "", special}
 		if index < len(tokens) {
 			e = tokens[index]
@@ -237,10 +248,18 @@ func TestScan(t *testing.T) {
 		}
 		checkPos(t, lit, pos, epos)
 		if tok != e.tok {
-			t.Errorf("bad token for %q: got %s, expected %s", lit, tok.String(), e.tok.String())
+			t.Errorf("bad token for %q: got %s, expected %s", lit, tok, e.tok)
 		}
-		if e.tok.IsLiteral() && lit != e.lit {
-			t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, e.lit)
+		if e.tok.IsLiteral() {
+			// no CRs in raw string literals
+			elit := e.lit
+			if elit[0] == '`' {
+				elit = string(stripCR([]byte(elit)))
+				epos.Offset += len(e.lit) - len(lit) // correct position
+			}
+			if lit != elit {
+				t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, elit)
+			}
 		}
 		if tokenclass(tok) != e.class {
 			t.Errorf("bad class for %q: got %d, expected %d", lit, tokenclass(tok), e.class)
@@ -262,7 +281,7 @@ func TestScan(t *testing.T) {
 	}
 }
 
-func checkSemi(t *testing.T, line string, mode uint) {
+func checkSemi(t *testing.T, line string, mode Mode) {
 	var S Scanner
 	file := fset.AddFile("TestSemis", fset.Base(), len(line))
 	S.Init(file, []byte(line), nil, mode)
@@ -286,7 +305,7 @@ func checkSemi(t *testing.T, line string, mode uint) {
 				}
 				checkPos(t, line, pos, semiPos)
 			} else {
-				t.Errorf("bad token for %q: got %s, expected ;", line, tok.String())
+				t.Errorf("bad token for %q: got %s, expected ;", line, tok)
 			}
 		} else if tok == token.SEMICOLON {
 			t.Errorf("bad token for %q: got ;, expected no ;", line)
@@ -420,14 +439,14 @@ var lines = []string{
 
 func TestSemis(t *testing.T) {
 	for _, line := range lines {
-		checkSemi(t, line, AllowIllegalChars|InsertSemis)
-		checkSemi(t, line, AllowIllegalChars|InsertSemis|ScanComments)
+		checkSemi(t, line, 0)
+		checkSemi(t, line, ScanComments)
 
 		// if the input ended in newlines, the input must tokenize the
 		// same with or without those newlines
 		for i := len(line) - 1; i >= 0 && line[i] == '\n'; i-- {
-			checkSemi(t, line[0:i], AllowIllegalChars|InsertSemis)
-			checkSemi(t, line[0:i], AllowIllegalChars|InsertSemis|ScanComments)
+			checkSemi(t, line[0:i], 0)
+			checkSemi(t, line[0:i], ScanComments)
 		}
 	}
 }
@@ -482,7 +501,7 @@ func TestLineComments(t *testing.T) {
 	// verify scan
 	var S Scanner
 	file := fset.AddFile(filepath.Join("dir", "TestLineComments"), fset.Base(), len(src))
-	S.Init(file, []byte(src), nil, 0)
+	S.Init(file, []byte(src), nil, dontInsertSemis)
 	for _, s := range segs {
 		p, _, lit := S.Scan()
 		pos := file.Position(p)
@@ -501,7 +520,7 @@ func TestInit(t *testing.T) {
 	// 1st init
 	src1 := "if true { }"
 	f1 := fset.AddFile("src1", fset.Base(), len(src1))
-	s.Init(f1, []byte(src1), nil, 0)
+	s.Init(f1, []byte(src1), nil, dontInsertSemis)
 	if f1.Size() != len(src1) {
 		t.Errorf("bad file size: got %d, expected %d", f1.Size(), len(src1))
 	}
@@ -509,40 +528,19 @@ func TestInit(t *testing.T) {
 	s.Scan()              // true
 	_, tok, _ := s.Scan() // {
 	if tok != token.LBRACE {
-		t.Errorf("bad token: got %s, expected %s", tok.String(), token.LBRACE)
+		t.Errorf("bad token: got %s, expected %s", tok, token.LBRACE)
 	}
 
 	// 2nd init
 	src2 := "go true { ]"
 	f2 := fset.AddFile("src2", fset.Base(), len(src2))
-	s.Init(f2, []byte(src2), nil, 0)
+	s.Init(f2, []byte(src2), nil, dontInsertSemis)
 	if f2.Size() != len(src2) {
 		t.Errorf("bad file size: got %d, expected %d", f2.Size(), len(src2))
 	}
 	_, tok, _ = s.Scan() // go
 	if tok != token.GO {
-		t.Errorf("bad token: got %s, expected %s", tok.String(), token.GO)
-	}
-
-	if s.ErrorCount != 0 {
-		t.Errorf("found %d errors", s.ErrorCount)
-	}
-}
-
-func TestIllegalChars(t *testing.T) {
-	var s Scanner
-
-	const src = "*?*$*@*"
-	file := fset.AddFile("", fset.Base(), len(src))
-	s.Init(file, []byte(src), &testErrorHandler{t}, AllowIllegalChars)
-	for offs, ch := range src {
-		pos, tok, lit := s.Scan()
-		if poffs := file.Offset(pos); poffs != offs {
-			t.Errorf("bad position for %s: got %d, expected %d", lit, poffs, offs)
-		}
-		if tok == token.ILLEGAL && lit != string(ch) {
-			t.Errorf("bad token: got %s, expected %s", lit, string(ch))
-		}
+		t.Errorf("bad token: got %s, expected %s", tok, token.GO)
 	}
 
 	if s.ErrorCount != 0 {
@@ -562,7 +560,7 @@ func TestStdErrorHander(t *testing.T) {
 
 	v := new(ErrorVector)
 	var s Scanner
-	s.Init(fset.AddFile("File1", fset.Base(), len(src)), []byte(src), v, 0)
+	s.Init(fset.AddFile("File1", fset.Base(), len(src)), []byte(src), v, dontInsertSemis)
 	for {
 		if _, tok, _ := s.Scan(); tok == token.EOF {
 			break
@@ -607,7 +605,7 @@ func (h *errorCollector) Error(pos token.Position, msg string) {
 func checkError(t *testing.T, src string, tok token.Token, pos int, err string) {
 	var s Scanner
 	var h errorCollector
-	s.Init(fset.AddFile("", fset.Base(), len(src)), []byte(src), &h, ScanComments)
+	s.Init(fset.AddFile("", fset.Base(), len(src)), []byte(src), &h, ScanComments|dontInsertSemis)
 	_, tok0, _ := s.Scan()
 	_, tok1, _ := s.Scan()
 	if tok0 != tok {
@@ -670,3 +668,20 @@ func TestScanErrors(t *testing.T) {
 		checkError(t, e.src, e.tok, e.pos, e.err)
 	}
 }
+
+func BenchmarkScan(b *testing.B) {
+	b.StopTimer()
+	fset := token.NewFileSet()
+	file := fset.AddFile("", fset.Base(), len(source))
+	var s Scanner
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		s.Init(file, source, nil, ScanComments)
+		for {
+			_, tok, _ := s.Scan()
+			if tok == token.EOF {
+				break
+			}
+		}
+	}
+}
diff --git a/src/pkg/go/token/position.go b/src/pkg/go/token/position.go
index 9155b50..647d1b7 100644
--- a/src/pkg/go/token/position.go
+++ b/src/pkg/go/token/position.go
@@ -12,6 +12,9 @@ import (
 	"sync"
 )
 
+// -----------------------------------------------------------------------------
+// Positions
+
 // Position describes an arbitrary source position
 // including the file, line, and column location.
 // A Position is valid if the line number is > 0.
@@ -81,86 +84,8 @@ func (p Pos) IsValid() bool {
 	return p != NoPos
 }
 
-func searchFiles(a []*File, x int) int {
-	return sort.Search(len(a), func(i int) bool { return a[i].base > x }) - 1
-}
-
-func (s *FileSet) file(p Pos) *File {
-	if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size {
-		return f
-	}
-	if i := searchFiles(s.files, int(p)); i >= 0 {
-		f := s.files[i]
-		// f.base <= int(p) by definition of searchFiles
-		if int(p) <= f.base+f.size {
-			s.last = f
-			return f
-		}
-	}
-	return nil
-}
-
-// File returns the file which contains the position p.
-// If no such file is found (for instance for p == NoPos),
-// the result is nil.
-//
-func (s *FileSet) File(p Pos) (f *File) {
-	if p != NoPos {
-		s.mutex.RLock()
-		f = s.file(p)
-		s.mutex.RUnlock()
-	}
-	return
-}
-
-func (f *File) position(p Pos) (pos Position) {
-	offset := int(p) - f.base
-	pos.Offset = offset
-	pos.Filename, pos.Line, pos.Column = f.info(offset)
-	return
-}
-
-// Position converts a Pos in the fileset into a general Position.
-func (s *FileSet) Position(p Pos) (pos Position) {
-	if p != NoPos {
-		// TODO(gri) consider optimizing the case where p
-		//           is in the last file added, or perhaps
-		//           looked at - will eliminate one level
-		//           of search
-		s.mutex.RLock()
-		if f := s.file(p); f != nil {
-			pos = f.position(p)
-		}
-		s.mutex.RUnlock()
-	}
-	return
-}
-
-// A lineInfo object describes alternative file and line number
-// information (such as provided via a //line comment in a .go
-// file) for a given file offset.
-type lineInfo struct {
-	// fields are exported to make them accessible to gob
-	Offset   int
-	Filename string
-	Line     int
-}
-
-// AddLineInfo adds alternative file and line number information for
-// a given file offset. The offset must be larger than the offset for
-// the previously added alternative line info and smaller than the
-// file size; otherwise the information is ignored.
-//
-// AddLineInfo is typically used to register alternative position
-// information for //line filename:line comments in source files.
-//
-func (f *File) AddLineInfo(offset int, filename string, line int) {
-	f.set.mutex.Lock()
-	if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size {
-		f.infos = append(f.infos, lineInfo{offset, filename, line})
-	}
-	f.set.mutex.Unlock()
-}
+// -----------------------------------------------------------------------------
+// File
 
 // A File is a handle for a file belonging to a FileSet.
 // A File has a name, size, and line offset table.
@@ -255,6 +180,32 @@ func (f *File) SetLinesForContent(content []byte) {
 	f.set.mutex.Unlock()
 }
 
+// A lineInfo object describes alternative file and line number
+// information (such as provided via a //line comment in a .go
+// file) for a given file offset.
+type lineInfo struct {
+	// fields are exported to make them accessible to gob
+	Offset   int
+	Filename string
+	Line     int
+}
+
+// AddLineInfo adds alternative file and line number information for
+// a given file offset. The offset must be larger than the offset for
+// the previously added alternative line info and smaller than the
+// file size; otherwise the information is ignored.
+//
+// AddLineInfo is typically used to register alternative position
+// information for //line filename:line comments in source files.
+//
+func (f *File) AddLineInfo(offset int, filename string, line int) {
+	f.set.mutex.Lock()
+	if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size {
+		f.infos = append(f.infos, lineInfo{offset, filename, line})
+	}
+	f.set.mutex.Unlock()
+}
+
 // Pos returns the Pos value for the given file offset;
 // the offset must be <= f.Size().
 // f.Pos(f.Offset(p)) == p.
@@ -285,41 +236,6 @@ func (f *File) Line(p Pos) int {
 	return f.Position(p).Line
 }
 
-// Position returns the Position value for the given file position p;
-// p must be a Pos value in that file or NoPos.
-//
-func (f *File) Position(p Pos) (pos Position) {
-	if p != NoPos {
-		if int(p) < f.base || int(p) > f.base+f.size {
-			panic("illegal Pos value")
-		}
-		pos = f.position(p)
-	}
-	return
-}
-
-func searchInts(a []int, x int) int {
-	// This function body is a manually inlined version of:
-	//
-	//   return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1
-	//
-	// With better compiler optimizations, this may not be needed in the
-	// future, but at the moment this change improves the go/printer
-	// benchmark performance by ~30%. This has a direct impact on the
-	// speed of gofmt and thus seems worthwhile (2011-04-29).
-	i, j := 0, len(a)
-	for i < j {
-		h := i + (j-i)/2 // avoid overflow when computing h
-		// i ≤ h < j
-		if a[h] <= x {
-			i = h + 1
-		} else {
-			j = h
-		}
-	}
-	return i - 1
-}
-
 func searchLineInfos(a []lineInfo, x int) int {
 	return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1
 }
@@ -343,6 +259,29 @@ func (f *File) info(offset int) (filename string, line, column int) {
 	return
 }
 
+func (f *File) position(p Pos) (pos Position) {
+	offset := int(p) - f.base
+	pos.Offset = offset
+	pos.Filename, pos.Line, pos.Column = f.info(offset)
+	return
+}
+
+// Position returns the Position value for the given file position p;
+// p must be a Pos value in that file or NoPos.
+//
+func (f *File) Position(p Pos) (pos Position) {
+	if p != NoPos {
+		if int(p) < f.base || int(p) > f.base+f.size {
+			panic("illegal Pos value")
+		}
+		pos = f.position(p)
+	}
+	return
+}
+
+// -----------------------------------------------------------------------------
+// FileSet
+
 // A FileSet represents a set of source files.
 // Methods of file sets are synchronized; multiple goroutines
 // may invoke them concurrently.
@@ -406,23 +345,91 @@ func (s *FileSet) AddFile(filename string, base, size int) *File {
 	return f
 }
 
-// Files returns the files added to the file set.
-func (s *FileSet) Files() <-chan *File {
-	ch := make(chan *File)
-	go func() {
-		for i := 0; ; i++ {
-			var f *File
-			s.mutex.RLock()
-			if i < len(s.files) {
-				f = s.files[i]
-			}
-			s.mutex.RUnlock()
-			if f == nil {
-				break
-			}
-			ch <- f
+// Iterate calls f for the files in the file set in the order they were added
+// until f returns false.
+// 
+func (s *FileSet) Iterate(f func(*File) bool) {
+	for i := 0; ; i++ {
+		var file *File
+		s.mutex.RLock()
+		if i < len(s.files) {
+			file = s.files[i]
+		}
+		s.mutex.RUnlock()
+		if file == nil || !f(file) {
+			break
 		}
-		close(ch)
-	}()
-	return ch
+	}
+}
+
+func searchFiles(a []*File, x int) int {
+	return sort.Search(len(a), func(i int) bool { return a[i].base > x }) - 1
+}
+
+func (s *FileSet) file(p Pos) *File {
+	// common case: p is in last file
+	if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size {
+		return f
+	}
+	// p is not in last file - search all files
+	if i := searchFiles(s.files, int(p)); i >= 0 {
+		f := s.files[i]
+		// f.base <= int(p) by definition of searchFiles
+		if int(p) <= f.base+f.size {
+			s.last = f
+			return f
+		}
+	}
+	return nil
+}
+
+// File returns the file that contains the position p.
+// If no such file is found (for instance for p == NoPos),
+// the result is nil.
+//
+func (s *FileSet) File(p Pos) (f *File) {
+	if p != NoPos {
+		s.mutex.RLock()
+		f = s.file(p)
+		s.mutex.RUnlock()
+	}
+	return
+}
+
+// Position converts a Pos in the fileset into a general Position.
+func (s *FileSet) Position(p Pos) (pos Position) {
+	if p != NoPos {
+		s.mutex.RLock()
+		if f := s.file(p); f != nil {
+			pos = f.position(p)
+		}
+		s.mutex.RUnlock()
+	}
+	return
+}
+
+// -----------------------------------------------------------------------------
+// Helper functions
+
+func searchInts(a []int, x int) int {
+	// This function body is a manually inlined version of:
+	//
+	//   return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1
+	//
+	// With better compiler optimizations, this may not be needed in the
+	// future, but at the moment this change improves the go/printer
+	// benchmark performance by ~30%. This has a direct impact on the
+	// speed of gofmt and thus seems worthwhile (2011-04-29).
+	// TODO(gri): Remove this when compilers have caught up.
+	i, j := 0, len(a)
+	for i < j {
+		h := i + (j-i)/2 // avoid overflow when computing h
+		// i ≤ h < j
+		if a[h] <= x {
+			i = h + 1
+		} else {
+			j = h
+		}
+	}
+	return i - 1
 }
diff --git a/src/pkg/go/token/position_test.go b/src/pkg/go/token/position_test.go
index 30bec59..160107d 100644
--- a/src/pkg/go/token/position_test.go
+++ b/src/pkg/go/token/position_test.go
@@ -167,12 +167,13 @@ func TestFiles(t *testing.T) {
 	for i, test := range tests {
 		fset.AddFile(test.filename, fset.Base(), test.size)
 		j := 0
-		for g := range fset.Files() {
-			if g.Name() != tests[j].filename {
-				t.Errorf("expected filename = %s; got %s", tests[j].filename, g.Name())
+		fset.Iterate(func(f *File) bool {
+			if f.Name() != tests[j].filename {
+				t.Errorf("expected filename = %s; got %s", tests[j].filename, f.Name())
 			}
 			j++
-		}
+			return true
+		})
 		if j != i+1 {
 			t.Errorf("expected %d files; got %d", i+1, j)
 		}
diff --git a/src/pkg/go/token/serialize.go b/src/pkg/go/token/serialize.go
index 80a3323..042d6ab 100644
--- a/src/pkg/go/token/serialize.go
+++ b/src/pkg/go/token/serialize.go
@@ -5,9 +5,8 @@
 package token
 
 import (
-	"gob"
+	"encoding/gob"
 	"io"
-	"os"
 )
 
 type serializedFile struct {
@@ -24,10 +23,19 @@ type serializedFileSet struct {
 	Files []serializedFile
 }
 
+func (s *serializedFileSet) Read(r io.Reader) error {
+	return gob.NewDecoder(r).Decode(s)
+}
+
+func (s *serializedFileSet) Write(w io.Writer) error {
+	return gob.NewEncoder(w).Encode(s)
+}
+
 // Read reads the fileset from r into s; s must not be nil.
-func (s *FileSet) Read(r io.Reader) os.Error {
+// If r does not also implement io.ByteReader, it will be wrapped in a bufio.Reader.
+func (s *FileSet) Read(r io.Reader) error {
 	var ss serializedFileSet
-	if err := gob.NewDecoder(r).Decode(&ss); err != nil {
+	if err := ss.Read(r); err != nil {
 		return err
 	}
 
@@ -46,7 +54,7 @@ func (s *FileSet) Read(r io.Reader) os.Error {
 }
 
 // Write writes the fileset s to w.
-func (s *FileSet) Write(w io.Writer) os.Error {
+func (s *FileSet) Write(w io.Writer) error {
 	var ss serializedFileSet
 
 	s.mutex.Lock()
@@ -58,5 +66,5 @@ func (s *FileSet) Write(w io.Writer) os.Error {
 	ss.Files = files
 	s.mutex.Unlock()
 
-	return gob.NewEncoder(w).Encode(ss)
+	return ss.Write(w)
 }
diff --git a/src/pkg/go/token/serialize_test.go b/src/pkg/go/token/serialize_test.go
index 24e419a..a8ce30a 100644
--- a/src/pkg/go/token/serialize_test.go
+++ b/src/pkg/go/token/serialize_test.go
@@ -7,13 +7,12 @@ package token
 import (
 	"bytes"
 	"fmt"
-	"os"
 	"testing"
 )
 
 // equal returns nil if p and q describe the same file set;
 // otherwise it returns an error describing the discrepancy.
-func equal(p, q *FileSet) os.Error {
+func equal(p, q *FileSet) error {
 	if p == q {
 		// avoid deadlock if p == q
 		return nil
diff --git a/src/pkg/go/token/token.go b/src/pkg/go/token/token.go
index 5573740..84b6314 100644
--- a/src/pkg/go/token/token.go
+++ b/src/pkg/go/token/token.go
@@ -283,10 +283,8 @@ func init() {
 
 // Lookup maps an identifier to its keyword token or IDENT (if not a keyword).
 //
-func Lookup(ident []byte) Token {
-	// TODO Maps with []byte key are illegal because []byte does not
-	//      support == . Should find a more efficient solution eventually.
-	if tok, is_keyword := keywords[string(ident)]; is_keyword {
+func Lookup(ident string) Token {
+	if tok, is_keyword := keywords[ident]; is_keyword {
 		return tok
 	}
 	return IDENT
@@ -295,16 +293,16 @@ func Lookup(ident []byte) Token {
 // Predicates
 
 // IsLiteral returns true for tokens corresponding to identifiers
-// and basic type literals; returns false otherwise.
+// and basic type literals; it returns false otherwise.
 //
 func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end }
 
 // IsOperator returns true for tokens corresponding to operators and
-// delimiters; returns false otherwise.
+// delimiters; it returns false otherwise.
 //
 func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end }
 
 // IsKeyword returns true for tokens corresponding to keywords;
-// returns false otherwise.
+// it returns false otherwise.
 //
 func (tok Token) IsKeyword() bool { return keyword_beg < tok && tok < keyword_end }
diff --git a/src/pkg/go/typechecker/Makefile b/src/pkg/go/typechecker/Makefile
deleted file mode 100644
index 83af3ef..0000000
--- a/src/pkg/go/typechecker/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=go/typechecker
-GOFILES=\
-	scope.go\
-	type.go\
-	typechecker.go\
-	universe.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/go/typechecker/scope.go b/src/pkg/go/typechecker/scope.go
deleted file mode 100644
index d73d1a4..0000000
--- a/src/pkg/go/typechecker/scope.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2010 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.
-
-// DEPRECATED FILE - WILL GO AWAY EVENTUALLY.
-//
-// Scope handling is now done in go/parser.
-// The functionality here is only present to
-// keep the typechecker running for now.
-
-package typechecker
-
-import "go/ast"
-
-func (tc *typechecker) openScope() *ast.Scope {
-	tc.topScope = ast.NewScope(tc.topScope)
-	return tc.topScope
-}
-
-func (tc *typechecker) closeScope() {
-	tc.topScope = tc.topScope.Outer
-}
-
-// declInScope declares an object of a given kind and name in scope and sets the object's Decl and N fields.
-// It returns the newly allocated object. If an object with the same name already exists in scope, an error
-// is reported and the object is not inserted.
-func (tc *typechecker) declInScope(scope *ast.Scope, kind ast.ObjKind, name *ast.Ident, decl interface{}, n int) *ast.Object {
-	obj := ast.NewObj(kind, name.Name)
-	obj.Decl = decl
-	//obj.N = n
-	name.Obj = obj
-	if name.Name != "_" {
-		if alt := scope.Insert(obj); alt != nil {
-			tc.Errorf(name.Pos(), "%s already declared at %s", name.Name, tc.fset.Position(alt.Pos()).String())
-		}
-	}
-	return obj
-}
-
-// decl is the same as declInScope(tc.topScope, ...)
-func (tc *typechecker) decl(kind ast.ObjKind, name *ast.Ident, decl interface{}, n int) *ast.Object {
-	return tc.declInScope(tc.topScope, kind, name, decl, n)
-}
-
-// find returns the object with the given name if visible in the current scope hierarchy.
-// If no such object is found, an error is reported and a bad object is returned instead.
-func (tc *typechecker) find(name *ast.Ident) (obj *ast.Object) {
-	for s := tc.topScope; s != nil && obj == nil; s = s.Outer {
-		obj = s.Lookup(name.Name)
-	}
-	if obj == nil {
-		tc.Errorf(name.Pos(), "%s not declared", name.Name)
-		obj = ast.NewObj(ast.Bad, name.Name)
-	}
-	name.Obj = obj
-	return
-}
-
-// findField returns the object with the given name if visible in the type's scope.
-// If no such object is found, an error is reported and a bad object is returned instead.
-func (tc *typechecker) findField(typ *Type, name *ast.Ident) (obj *ast.Object) {
-	// TODO(gri) This is simplistic at the moment and ignores anonymous fields.
-	obj = typ.Scope.Lookup(name.Name)
-	if obj == nil {
-		tc.Errorf(name.Pos(), "%s not declared", name.Name)
-		obj = ast.NewObj(ast.Bad, name.Name)
-	}
-	return
-}
diff --git a/src/pkg/go/typechecker/testdata/test0.src b/src/pkg/go/typechecker/testdata/test0.src
deleted file mode 100644
index 4e317f2..0000000
--- a/src/pkg/go/typechecker/testdata/test0.src
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2010 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.
-
-// type declarations
-
-package P0
-
-type (
-	B bool
-	I int32
-	A [10]P
-	T struct {
-		x, y P
-	}
-	P *T
-	R *R
-	F func(A) I
-	Y interface {
-		f(A) I
-	}
-	S []P
-	M map[I]F
-	C chan<- I
-)
-
-type (
-	a/* ERROR "illegal cycle" */ a
-	a/* ERROR "already declared" */ int
-
-	b/* ERROR "illegal cycle" */ c
-	c d
-	d e
-	e b /* ERROR "not a type" */
-
-	t *t
-
-	U V
-	V W
-	W *U
-
-	P1 *S2
-	P2 P1
-
-	S1 struct {
-		a, b, c int
-		u, v, a/* ERROR "already declared" */ float
-	}
-	S2/* ERROR "illegal cycle" */ struct {
-		x S2
-	}
-
-	L1 []L1
-	L2 []int
-
-	A1 [10]int
-	A2/* ERROR "illegal cycle" */ [10]A2
-	A3/* ERROR "illegal cycle" */ [10]struct {
-		x A4
-	}
-	A4 [10]A3
-
-	F1 func()
-	F2 func(x, y, z float)
-	F3 func(x, y, x /* ERROR "already declared" */ float)
-	F4 func() (x, y, x /* ERROR "already declared" */ float)
-	F5 func(x int) (x /* ERROR "already declared" */ float)
-
-	I1 interface{}
-	I2 interface {
-		m1()
-	}
-	I3 interface {
-		m1()
-		m1 /* ERROR "already declared" */ ()
-	}
-	I4 interface {
-		m1(x, y, x /* ERROR "already declared" */ float)
-		m2() (x, y, x /* ERROR "already declared" */ float)
-		m3(x int) (x /* ERROR "already declared" */ float)
-	}
-	I5 interface {
-		m1(I5)
-	}
-
-	C1 chan int
-	C2 <-chan int
-	C3 chan<- C3
-
-	M1 map[Last]string
-	M2 map[string]M2
-
-	Last int
-)
diff --git a/src/pkg/go/typechecker/testdata/test1.src b/src/pkg/go/typechecker/testdata/test1.src
deleted file mode 100644
index b5531fb..0000000
--- a/src/pkg/go/typechecker/testdata/test1.src
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2010 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.
-
-// const and var declarations
-
-package P1
-
-const (
-	c1 = 0
-	c2     int = 0
-	c3, c4 = 0
-)
diff --git a/src/pkg/go/typechecker/testdata/test3.src b/src/pkg/go/typechecker/testdata/test3.src
deleted file mode 100644
index 2e1a9fa..0000000
--- a/src/pkg/go/typechecker/testdata/test3.src
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2010 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 P3
-
-// function and method signatures
-
-func _()                                        {}
-func _()                                        {}
-func _(x, x /* ERROR "already declared" */ int) {}
-
-func f()                                 {}
-func f /* ERROR "already declared" */ () {}
-
-func (*foo /* ERROR "invalid receiver" */ ) m() {}
-func (bar /* ERROR "not a type" */ ) m()        {}
-
-func f1(x, _, _ int) (_, _ float)                              {}
-func f2(x, y, x /* ERROR "already declared" */ int)            {}
-func f3(x, y int) (a, b, x /* ERROR "already declared" */ int) {}
-
-func (x *T) m1()                                 {}
-func (x *T) m1 /* ERROR "already declared" */ () {}
-func (x T) m1 /* ERROR "already declared" */ ()  {}
-func (T) m1 /* ERROR "already declared" */ ()    {}
-
-func (x *T) m2(u, x /* ERROR "already declared" */ int)               {}
-func (x *T) m3(a, b, c int) (u, x /* ERROR "already declared" */ int) {}
-// The following are disabled for now because the typechecker
-// in in the process of being rewritten and cannot handle them
-// at the moment
-//func (T) _(x, x /* "already declared" */ int)                   {}
-//func (T) _() (x, x /* "already declared" */ int)                {}
-
-//func (PT) _() {}
-
-var bar int
-
-type T struct{}
-type PT (T)
diff --git a/src/pkg/go/typechecker/testdata/test4.src b/src/pkg/go/typechecker/testdata/test4.src
deleted file mode 100644
index 94d3558..0000000
--- a/src/pkg/go/typechecker/testdata/test4.src
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2010 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.
-
-// Constant declarations
-
-package P4
-
-const (
-	c0 = 0
-)
diff --git a/src/pkg/go/typechecker/type.go b/src/pkg/go/typechecker/type.go
deleted file mode 100644
index 1b88eb5..0000000
--- a/src/pkg/go/typechecker/type.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2010 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 typechecker
-
-import "go/ast"
-
-// A Type represents a Go type.
-type Type struct {
-	Form     Form
-	Obj      *ast.Object // corresponding type name, or nil
-	Scope    *ast.Scope  // fields and methods, always present
-	N        uint        // basic type id, array length, number of function results, or channel direction
-	Key, Elt *Type       // map key and array, pointer, slice, map or channel element
-	Params   *ast.Scope  // function (receiver, input and result) parameters, tuple expressions (results of function calls), or nil
-	Expr     ast.Expr    // corresponding AST expression
-}
-
-// NewType creates a new type of a given form.
-func NewType(form Form) *Type {
-	return &Type{Form: form, Scope: ast.NewScope(nil)}
-}
-
-// Form describes the form of a type.
-type Form int
-
-// The list of possible type forms.
-const (
-	BadType    Form = iota // for error handling
-	Unresolved             // type not fully setup
-	Basic
-	Array
-	Struct
-	Pointer
-	Function
-	Method
-	Interface
-	Slice
-	Map
-	Channel
-	Tuple
-)
-
-var formStrings = [...]string{
-	BadType:    "badType",
-	Unresolved: "unresolved",
-	Basic:      "basic",
-	Array:      "array",
-	Struct:     "struct",
-	Pointer:    "pointer",
-	Function:   "function",
-	Method:     "method",
-	Interface:  "interface",
-	Slice:      "slice",
-	Map:        "map",
-	Channel:    "channel",
-	Tuple:      "tuple",
-}
-
-func (form Form) String() string { return formStrings[form] }
-
-// The list of basic type id's.
-const (
-	Bool = iota
-	Byte
-	Uint
-	Int
-	Float
-	Complex
-	Uintptr
-	String
-
-	Uint8
-	Uint16
-	Uint32
-	Uint64
-
-	Int8
-	Int16
-	Int32
-	Int64
-
-	Float32
-	Float64
-
-	Complex64
-	Complex128
-
-	// TODO(gri) ideal types are missing
-)
-
-var BasicTypes = map[uint]string{
-	Bool:    "bool",
-	Byte:    "byte",
-	Uint:    "uint",
-	Int:     "int",
-	Float:   "float",
-	Complex: "complex",
-	Uintptr: "uintptr",
-	String:  "string",
-
-	Uint8:  "uint8",
-	Uint16: "uint16",
-	Uint32: "uint32",
-	Uint64: "uint64",
-
-	Int8:  "int8",
-	Int16: "int16",
-	Int32: "int32",
-	Int64: "int64",
-
-	Float32: "float32",
-	Float64: "float64",
-
-	Complex64:  "complex64",
-	Complex128: "complex128",
-}
diff --git a/src/pkg/go/typechecker/typechecker.go b/src/pkg/go/typechecker/typechecker.go
deleted file mode 100644
index 2448016..0000000
--- a/src/pkg/go/typechecker/typechecker.go
+++ /dev/null
@@ -1,468 +0,0 @@
-// Copyright 2010 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.
-
-// DEPRECATED PACKAGE - SEE go/types INSTEAD.
-// This package implements typechecking of a Go AST.
-// The result of the typecheck is an augmented AST
-// with object and type information for each identifier.
-//
-package typechecker
-
-import (
-	"fmt"
-	"go/ast"
-	"go/token"
-	"go/scanner"
-	"os"
-)
-
-// TODO(gri) don't report errors for objects/types that are marked as bad.
-
-
-const debug = true // set for debugging output
-
-// An importer takes an import path and returns the data describing the
-// respective package's exported interface. The data format is TBD.
-//
-type Importer func(path string) ([]byte, os.Error)
-
-// CheckPackage typechecks a package and augments the AST by setting
-// *ast.Object, *ast.Type, and *ast.Scope fields accordingly. If an
-// importer is provided, it is used to handle imports, otherwise they
-// are ignored (likely leading to typechecking errors).
-//
-// If errors are reported, the AST may be incompletely augmented (fields
-// may be nil) or contain incomplete object, type, or scope information.
-//
-func CheckPackage(fset *token.FileSet, pkg *ast.Package, importer Importer) os.Error {
-	var tc typechecker
-	tc.fset = fset
-	tc.importer = importer
-	tc.checkPackage(pkg)
-	return tc.GetError(scanner.Sorted)
-}
-
-// CheckFile typechecks a single file, but otherwise behaves like
-// CheckPackage. If the complete package consists of more than just
-// one file, the file may not typecheck without errors.
-//
-func CheckFile(fset *token.FileSet, file *ast.File, importer Importer) os.Error {
-	// create a single-file dummy package
-	pkg := &ast.Package{file.Name.Name, nil, nil, map[string]*ast.File{fset.Position(file.Name.NamePos).Filename: file}}
-	return CheckPackage(fset, pkg, importer)
-}
-
-// ----------------------------------------------------------------------------
-// Typechecker state
-
-type typechecker struct {
-	fset *token.FileSet
-	scanner.ErrorVector
-	importer Importer
-	globals  []*ast.Object        // list of global objects
-	topScope *ast.Scope           // current top-most scope
-	cyclemap map[*ast.Object]bool // for cycle detection
-	iota     int                  // current value of iota
-}
-
-func (tc *typechecker) Errorf(pos token.Pos, format string, args ...interface{}) {
-	tc.Error(tc.fset.Position(pos), fmt.Sprintf(format, args...))
-}
-
-func assert(pred bool) {
-	if !pred {
-		panic("internal error")
-	}
-}
-
-/*
-Typechecking is done in several phases:
-
-phase 1: declare all global objects; also collect all function and method declarations
-	- all objects have kind, name, decl fields; the decl field permits
-	  quick lookup of an object's declaration
-	- constant objects have an iota value
-	- type objects have unresolved types with empty scopes, all others have nil types
-	- report global double declarations
-
-phase 2: bind methods to their receiver base types
-	- receiver base types must be declared in the package, thus for
-	  each method a corresponding (unresolved) type must exist
-	- report method double declarations and errors with base types
-
-phase 3: resolve all global objects
-	- sequentially iterate through all objects in the global scope
-	- resolve types for all unresolved types and assign types to
-	  all attached methods
-	- assign types to all other objects, possibly by evaluating
-	  constant and initializer expressions
-	- resolution may recurse; a cyclemap is used to detect cycles
-	- report global typing errors
-
-phase 4: sequentially typecheck function and method bodies
-	- all global objects are declared and have types and values;
-	  all methods have types
-	- sequentially process statements in each body; any object
-	  referred to must be fully defined at this point
-	- report local typing errors
-*/
-
-func (tc *typechecker) checkPackage(pkg *ast.Package) {
-	// setup package scope
-	tc.topScope = Universe
-	tc.openScope()
-	defer tc.closeScope()
-
-	// TODO(gri) there's no file scope at the moment since we ignore imports
-
-	// phase 1: declare all global objects; also collect all function and method declarations
-	var funcs []*ast.FuncDecl
-	for _, file := range pkg.Files {
-		for _, decl := range file.Decls {
-			tc.declGlobal(decl)
-			if f, isFunc := decl.(*ast.FuncDecl); isFunc {
-				funcs = append(funcs, f)
-			}
-		}
-	}
-
-	// phase 2: bind methods to their receiver base types
-	for _, m := range funcs {
-		if m.Recv != nil {
-			tc.bindMethod(m)
-		}
-	}
-
-	// phase 3: resolve all global objects
-	tc.cyclemap = make(map[*ast.Object]bool)
-	for _, obj := range tc.globals {
-		tc.resolve(obj)
-	}
-	assert(len(tc.cyclemap) == 0)
-
-	// 4: sequentially typecheck function and method bodies
-	for _, f := range funcs {
-		ftype, _ := f.Name.Obj.Type.(*Type)
-		tc.checkBlock(f.Body.List, ftype)
-	}
-
-	pkg.Scope = tc.topScope
-}
-
-func (tc *typechecker) declGlobal(global ast.Decl) {
-	switch d := global.(type) {
-	case *ast.BadDecl:
-		// ignore
-
-	case *ast.GenDecl:
-		iota := 0
-		var prev *ast.ValueSpec
-		for _, spec := range d.Specs {
-			switch s := spec.(type) {
-			case *ast.ImportSpec:
-				// TODO(gri) imports go into file scope
-			case *ast.ValueSpec:
-				switch d.Tok {
-				case token.CONST:
-					if s.Values == nil {
-						// create a new spec with type and values from the previous one
-						if prev != nil {
-							s = &ast.ValueSpec{s.Doc, s.Names, prev.Type, prev.Values, s.Comment}
-						} else {
-							// TODO(gri) this should probably go into the const decl code
-							tc.Errorf(s.Pos(), "missing initializer for const %s", s.Names[0].Name)
-						}
-					}
-					for _, name := range s.Names {
-						tc.globals = append(tc.globals, tc.decl(ast.Con, name, s, iota))
-					}
-				case token.VAR:
-					for _, name := range s.Names {
-						tc.globals = append(tc.globals, tc.decl(ast.Var, name, s, 0))
-					}
-				default:
-					panic("unreachable")
-				}
-				prev = s
-				iota++
-			case *ast.TypeSpec:
-				obj := tc.decl(ast.Typ, s.Name, s, 0)
-				tc.globals = append(tc.globals, obj)
-				// give all type objects an unresolved type so
-				// that we can collect methods in the type scope
-				typ := NewType(Unresolved)
-				obj.Type = typ
-				typ.Obj = obj
-			default:
-				panic("unreachable")
-			}
-		}
-
-	case *ast.FuncDecl:
-		if d.Recv == nil {
-			tc.globals = append(tc.globals, tc.decl(ast.Fun, d.Name, d, 0))
-		}
-
-	default:
-		panic("unreachable")
-	}
-}
-
-// If x is of the form *T, deref returns T, otherwise it returns x.
-func deref(x ast.Expr) ast.Expr {
-	if p, isPtr := x.(*ast.StarExpr); isPtr {
-		x = p.X
-	}
-	return x
-}
-
-func (tc *typechecker) bindMethod(method *ast.FuncDecl) {
-	// a method is declared in the receiver base type's scope
-	var scope *ast.Scope
-	base := deref(method.Recv.List[0].Type)
-	if name, isIdent := base.(*ast.Ident); isIdent {
-		// if base is not an *ast.Ident, we had a syntax
-		// error and the parser reported an error already
-		obj := tc.topScope.Lookup(name.Name)
-		if obj == nil {
-			tc.Errorf(name.Pos(), "invalid receiver: %s is not declared in this package", name.Name)
-		} else if obj.Kind != ast.Typ {
-			tc.Errorf(name.Pos(), "invalid receiver: %s is not a type", name.Name)
-		} else {
-			typ := obj.Type.(*Type)
-			assert(typ.Form == Unresolved)
-			scope = typ.Scope
-		}
-	}
-	if scope == nil {
-		// no receiver type found; use a dummy scope
-		// (we still want to type-check the method
-		// body, so make sure there is a name object
-		// and type)
-		// TODO(gri) should we record the scope so
-		// that we don't lose the receiver for type-
-		// checking of the method body?
-		scope = ast.NewScope(nil)
-	}
-	tc.declInScope(scope, ast.Fun, method.Name, method, 0)
-}
-
-func (tc *typechecker) resolve(obj *ast.Object) {
-	// check for declaration cycles
-	if tc.cyclemap[obj] {
-		tc.Errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
-		obj.Kind = ast.Bad
-		return
-	}
-	tc.cyclemap[obj] = true
-	defer func() {
-		tc.cyclemap[obj] = false, false
-	}()
-
-	// resolve non-type objects
-	typ, _ := obj.Type.(*Type)
-	if typ == nil {
-		switch obj.Kind {
-		case ast.Bad:
-			// ignore
-
-		case ast.Con:
-			tc.declConst(obj)
-
-		case ast.Var:
-			tc.declVar(obj)
-			obj.Type = tc.typeFor(nil, obj.Decl.(*ast.ValueSpec).Type, false)
-
-		case ast.Fun:
-			obj.Type = NewType(Function)
-			t := obj.Decl.(*ast.FuncDecl).Type
-			tc.declSignature(obj.Type.(*Type), nil, t.Params, t.Results)
-
-		default:
-			// type objects have non-nil types when resolve is called
-			if debug {
-				fmt.Printf("kind = %s\n", obj.Kind)
-			}
-			panic("unreachable")
-		}
-		return
-	}
-
-	// resolve type objects
-	if typ.Form == Unresolved {
-		tc.typeFor(typ, typ.Obj.Decl.(*ast.TypeSpec).Type, false)
-
-		// provide types for all methods
-		for _, obj := range typ.Scope.Objects {
-			if obj.Kind == ast.Fun {
-				assert(obj.Type == nil)
-				obj.Type = NewType(Method)
-				f := obj.Decl.(*ast.FuncDecl)
-				t := f.Type
-				tc.declSignature(obj.Type.(*Type), f.Recv, t.Params, t.Results)
-			}
-		}
-	}
-}
-
-func (tc *typechecker) checkBlock(body []ast.Stmt, ftype *Type) {
-	tc.openScope()
-	defer tc.closeScope()
-
-	// inject function/method parameters into block scope, if any
-	if ftype != nil {
-		for _, par := range ftype.Params.Objects {
-			if par.Name != "_" {
-				alt := tc.topScope.Insert(par)
-				assert(alt == nil) // ftype has no double declarations
-			}
-		}
-	}
-
-	for _, stmt := range body {
-		tc.checkStmt(stmt)
-	}
-}
-
-// ----------------------------------------------------------------------------
-// Types
-
-// unparen removes parentheses around x, if any.
-func unparen(x ast.Expr) ast.Expr {
-	if ux, hasParens := x.(*ast.ParenExpr); hasParens {
-		return unparen(ux.X)
-	}
-	return x
-}
-
-func (tc *typechecker) declFields(scope *ast.Scope, fields *ast.FieldList, ref bool) (n uint) {
-	if fields != nil {
-		for _, f := range fields.List {
-			typ := tc.typeFor(nil, f.Type, ref)
-			for _, name := range f.Names {
-				fld := tc.declInScope(scope, ast.Var, name, f, 0)
-				fld.Type = typ
-				n++
-			}
-		}
-	}
-	return n
-}
-
-func (tc *typechecker) declSignature(typ *Type, recv, params, results *ast.FieldList) {
-	assert((typ.Form == Method) == (recv != nil))
-	typ.Params = ast.NewScope(nil)
-	tc.declFields(typ.Params, recv, true)
-	tc.declFields(typ.Params, params, true)
-	typ.N = tc.declFields(typ.Params, results, true)
-}
-
-func (tc *typechecker) typeFor(def *Type, x ast.Expr, ref bool) (typ *Type) {
-	x = unparen(x)
-
-	// type name
-	if t, isIdent := x.(*ast.Ident); isIdent {
-		obj := tc.find(t)
-
-		if obj.Kind != ast.Typ {
-			tc.Errorf(t.Pos(), "%s is not a type", t.Name)
-			if def == nil {
-				typ = NewType(BadType)
-			} else {
-				typ = def
-				typ.Form = BadType
-			}
-			typ.Expr = x
-			return
-		}
-
-		if !ref {
-			tc.resolve(obj) // check for cycles even if type resolved
-		}
-		typ = obj.Type.(*Type)
-
-		if def != nil {
-			// new type declaration: copy type structure
-			def.Form = typ.Form
-			def.N = typ.N
-			def.Key, def.Elt = typ.Key, typ.Elt
-			def.Params = typ.Params
-			def.Expr = x
-			typ = def
-		}
-		return
-	}
-
-	// type literal
-	typ = def
-	if typ == nil {
-		typ = NewType(BadType)
-	}
-	typ.Expr = x
-
-	switch t := x.(type) {
-	case *ast.SelectorExpr:
-		if debug {
-			fmt.Println("qualified identifier unimplemented")
-		}
-		typ.Form = BadType
-
-	case *ast.StarExpr:
-		typ.Form = Pointer
-		typ.Elt = tc.typeFor(nil, t.X, true)
-
-	case *ast.ArrayType:
-		if t.Len != nil {
-			typ.Form = Array
-			// TODO(gri) compute the real length
-			// (this may call resolve recursively)
-			(*typ).N = 42
-		} else {
-			typ.Form = Slice
-		}
-		typ.Elt = tc.typeFor(nil, t.Elt, t.Len == nil)
-
-	case *ast.StructType:
-		typ.Form = Struct
-		tc.declFields(typ.Scope, t.Fields, false)
-
-	case *ast.FuncType:
-		typ.Form = Function
-		tc.declSignature(typ, nil, t.Params, t.Results)
-
-	case *ast.InterfaceType:
-		typ.Form = Interface
-		tc.declFields(typ.Scope, t.Methods, true)
-
-	case *ast.MapType:
-		typ.Form = Map
-		typ.Key = tc.typeFor(nil, t.Key, true)
-		typ.Elt = tc.typeFor(nil, t.Value, true)
-
-	case *ast.ChanType:
-		typ.Form = Channel
-		typ.N = uint(t.Dir)
-		typ.Elt = tc.typeFor(nil, t.Value, true)
-
-	default:
-		if debug {
-			fmt.Printf("x is %T\n", x)
-		}
-		panic("unreachable")
-	}
-
-	return
-}
-
-// ----------------------------------------------------------------------------
-// TODO(gri) implement these place holders
-
-func (tc *typechecker) declConst(*ast.Object) {
-}
-
-func (tc *typechecker) declVar(*ast.Object) {
-}
-
-func (tc *typechecker) checkStmt(ast.Stmt) {
-}
diff --git a/src/pkg/go/typechecker/typechecker_test.go b/src/pkg/go/typechecker/typechecker_test.go
deleted file mode 100644
index 4bad449..0000000
--- a/src/pkg/go/typechecker/typechecker_test.go
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2010 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 file implements a simple typechecker test harness. Packages found
-// in the testDir directory are typechecked. Error messages reported by
-// the typechecker are compared against the error messages expected for
-// the test files.
-//
-// Expected errors are indicated in the test files by putting a comment
-// of the form /* ERROR "rx" */ immediately following an offending token.
-// The harness will verify that an error matching the regular expression
-// rx is reported at that source position. Consecutive comments may be
-// used to indicate multiple errors for the same token position.
-//
-// For instance, the following test file indicates that a "not declared"
-// error should be reported for the undeclared variable x:
-//
-//	package P0
-//	func f() {
-//		_ = x /* ERROR "not declared" */ + 1
-//	}
-// 
-// If the -pkg flag is set, only packages with package names matching
-// the regular expression provided via the flag value are tested.
-
-package typechecker
-
-import (
-	"flag"
-	"fmt"
-	"go/ast"
-	"go/parser"
-	"go/scanner"
-	"go/token"
-	"io/ioutil"
-	"os"
-	"regexp"
-	"sort"
-	"strings"
-	"testing"
-)
-
-const testDir = "./testdata" // location of test packages
-
-var fset = token.NewFileSet()
-
-var (
-	pkgPat = flag.String("pkg", ".*", "regular expression to select test packages by package name")
-	trace  = flag.Bool("trace", false, "print package names")
-)
-
-// ERROR comments must be of the form /* ERROR "rx" */ and rx is
-// a regular expression that matches the expected error message.
-var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`)
-
-// expectedErrors collects the regular expressions of ERROR comments
-// found in the package files of pkg and returns them in sorted order
-// (by filename and position).
-func expectedErrors(t *testing.T, pkg *ast.Package) (list scanner.ErrorList) {
-	// scan all package files
-	for filename := range pkg.Files {
-		src, err := ioutil.ReadFile(filename)
-		if err != nil {
-			t.Fatalf("expectedErrors(%s): %v", pkg.Name, err)
-		}
-
-		var s scanner.Scanner
-		file := fset.AddFile(filename, fset.Base(), len(src))
-		s.Init(file, src, nil, scanner.ScanComments)
-		var prev token.Pos // position of last non-comment token
-	loop:
-		for {
-			pos, tok, lit := s.Scan()
-			switch tok {
-			case token.EOF:
-				break loop
-			case token.COMMENT:
-				s := errRx.FindStringSubmatch(lit)
-				if len(s) == 2 {
-					list = append(list, &scanner.Error{fset.Position(prev), string(s[1])})
-				}
-			default:
-				prev = pos
-			}
-		}
-	}
-	sort.Sort(list) // multiple files may not be sorted
-	return
-}
-
-func testFilter(f *os.FileInfo) bool {
-	return strings.HasSuffix(f.Name, ".src") && f.Name[0] != '.'
-}
-
-func checkError(t *testing.T, expected, found *scanner.Error) {
-	rx, err := regexp.Compile(expected.Msg)
-	if err != nil {
-		t.Errorf("%s: %v", expected.Pos, err)
-		return
-	}
-
-	match := rx.MatchString(found.Msg)
-
-	if expected.Pos.Offset != found.Pos.Offset {
-		if match {
-			t.Errorf("%s: expected error should have been at %s", expected.Pos, found.Pos)
-		} else {
-			t.Errorf("%s: error matching %q expected", expected.Pos, expected.Msg)
-			return
-		}
-	}
-
-	if !match {
-		t.Errorf("%s: %q does not match %q", expected.Pos, expected.Msg, found.Msg)
-	}
-}
-
-func TestTypeCheck(t *testing.T) {
-	flag.Parse()
-	pkgRx, err := regexp.Compile(*pkgPat)
-	if err != nil {
-		t.Fatalf("illegal flag value %q: %s", *pkgPat, err)
-	}
-
-	pkgs, err := parser.ParseDir(fset, testDir, testFilter, 0)
-	if err != nil {
-		scanner.PrintError(os.Stderr, err)
-		t.Fatalf("packages in %s contain syntax errors", testDir)
-	}
-
-	for _, pkg := range pkgs {
-		if !pkgRx.MatchString(pkg.Name) {
-			continue // only test selected packages
-		}
-
-		if *trace {
-			fmt.Println(pkg.Name)
-		}
-
-		xlist := expectedErrors(t, pkg)
-		err := CheckPackage(fset, pkg, nil)
-		if err != nil {
-			if elist, ok := err.(scanner.ErrorList); ok {
-				// verify that errors match
-				for i := 0; i < len(xlist) && i < len(elist); i++ {
-					checkError(t, xlist[i], elist[i])
-				}
-				// the correct number or errors must have been found
-				if len(xlist) != len(elist) {
-					fmt.Fprintf(os.Stderr, "%s\n", pkg.Name)
-					scanner.PrintError(os.Stderr, elist)
-					fmt.Fprintln(os.Stderr)
-					t.Errorf("TypeCheck(%s): %d errors expected but %d reported", pkg.Name, len(xlist), len(elist))
-				}
-			} else {
-				t.Errorf("TypeCheck(%s): %v", pkg.Name, err)
-			}
-		} else if len(xlist) > 0 {
-			t.Errorf("TypeCheck(%s): %d errors expected but 0 reported", pkg.Name, len(xlist))
-		}
-	}
-}
diff --git a/src/pkg/go/typechecker/universe.go b/src/pkg/go/typechecker/universe.go
deleted file mode 100644
index 81c14a0..0000000
--- a/src/pkg/go/typechecker/universe.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2010 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 typechecker
-
-import "go/ast"
-
-// TODO(gri) should this be in package ast?
-
-// The Universe scope contains all predeclared identifiers.
-var Universe *ast.Scope
-
-func def(obj *ast.Object) {
-	alt := Universe.Insert(obj)
-	if alt != nil {
-		panic("object declared twice")
-	}
-}
-
-func init() {
-	Universe = ast.NewScope(nil)
-
-	// basic types
-	for n, name := range BasicTypes {
-		typ := NewType(Basic)
-		typ.N = n
-		obj := ast.NewObj(ast.Typ, name)
-		obj.Type = typ
-		typ.Obj = obj
-		def(obj)
-	}
-
-	// built-in functions
-	// TODO(gri) implement this
-}
diff --git a/src/pkg/go/types/Makefile b/src/pkg/go/types/Makefile
deleted file mode 100644
index 4ca707c..0000000
--- a/src/pkg/go/types/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=go/types
-GOFILES=\
-	check.go\
-	const.go\
-	exportdata.go\
-	gcimporter.go\
-	types.go\
-	universe.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/go/types/check.go b/src/pkg/go/types/check.go
deleted file mode 100644
index 87e3e93..0000000
--- a/src/pkg/go/types/check.go
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2011 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 file implements the Check function, which typechecks a package.
-
-package types
-
-import (
-	"fmt"
-	"go/ast"
-	"go/scanner"
-	"go/token"
-	"os"
-	"strconv"
-)
-
-const debug = false
-
-type checker struct {
-	fset *token.FileSet
-	scanner.ErrorVector
-	types map[ast.Expr]Type
-}
-
-func (c *checker) errorf(pos token.Pos, format string, args ...interface{}) string {
-	msg := fmt.Sprintf(format, args...)
-	c.Error(c.fset.Position(pos), msg)
-	return msg
-}
-
-// collectFields collects struct fields tok = token.STRUCT), interface methods
-// (tok = token.INTERFACE), and function arguments/results (tok = token.FUNC).
-func (c *checker) collectFields(tok token.Token, list *ast.FieldList, cycleOk bool) (fields ObjList, tags []string, isVariadic bool) {
-	if list != nil {
-		for _, field := range list.List {
-			ftype := field.Type
-			if t, ok := ftype.(*ast.Ellipsis); ok {
-				ftype = t.Elt
-				isVariadic = true
-			}
-			typ := c.makeType(ftype, cycleOk)
-			tag := ""
-			if field.Tag != nil {
-				assert(field.Tag.Kind == token.STRING)
-				tag, _ = strconv.Unquote(field.Tag.Value)
-			}
-			if len(field.Names) > 0 {
-				// named fields
-				for _, name := range field.Names {
-					obj := name.Obj
-					obj.Type = typ
-					fields = append(fields, obj)
-					if tok == token.STRUCT {
-						tags = append(tags, tag)
-					}
-				}
-			} else {
-				// anonymous field
-				switch tok {
-				case token.STRUCT:
-					tags = append(tags, tag)
-					fallthrough
-				case token.FUNC:
-					obj := ast.NewObj(ast.Var, "")
-					obj.Type = typ
-					fields = append(fields, obj)
-				case token.INTERFACE:
-					utyp := Underlying(typ)
-					if typ, ok := utyp.(*Interface); ok {
-						// TODO(gri) This is not good enough. Check for double declarations!
-						fields = append(fields, typ.Methods...)
-					} else if _, ok := utyp.(*Bad); !ok {
-						// if utyp is Bad, don't complain (the root cause was reported before)
-						c.errorf(ftype.Pos(), "interface contains embedded non-interface type")
-					}
-				default:
-					panic("unreachable")
-				}
-			}
-		}
-	}
-	return
-}
-
-// makeType makes a new type for an AST type specification x or returns
-// the type referred to by a type name x. If cycleOk is set, a type may
-// refer to itself directly or indirectly; otherwise cycles are errors.
-//
-func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
-	if debug {
-		fmt.Printf("makeType (cycleOk = %v)\n", cycleOk)
-		ast.Print(c.fset, x)
-		defer func() {
-			fmt.Printf("-> %T %v\n\n", typ, typ)
-		}()
-	}
-
-	switch t := x.(type) {
-	case *ast.BadExpr:
-		return &Bad{}
-
-	case *ast.Ident:
-		// type name
-		obj := t.Obj
-		if obj == nil {
-			// unresolved identifier (error has been reported before)
-			return &Bad{Msg: "unresolved identifier"}
-		}
-		if obj.Kind != ast.Typ {
-			msg := c.errorf(t.Pos(), "%s is not a type", t.Name)
-			return &Bad{Msg: msg}
-		}
-		c.checkObj(obj, cycleOk)
-		if !cycleOk && obj.Type.(*Name).Underlying == nil {
-			// TODO(gri) Enable this message again once its position
-			// is independent of the underlying map implementation.
-			// msg := c.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
-			msg := "illegal cycle"
-			return &Bad{Msg: msg}
-		}
-		return obj.Type.(Type)
-
-	case *ast.ParenExpr:
-		return c.makeType(t.X, cycleOk)
-
-	case *ast.SelectorExpr:
-		// qualified identifier
-		// TODO (gri) eventually, this code belongs to expression
-		//            type checking - here for the time being
-		if ident, ok := t.X.(*ast.Ident); ok {
-			if obj := ident.Obj; obj != nil {
-				if obj.Kind != ast.Pkg {
-					msg := c.errorf(ident.Pos(), "%s is not a package", obj.Name)
-					return &Bad{Msg: msg}
-				}
-				// TODO(gri) we have a package name but don't
-				// have the mapping from package name to package
-				// scope anymore (created in ast.NewPackage).
-				return &Bad{} // for now
-			}
-		}
-		// TODO(gri) can this really happen (the parser should have excluded this)?
-		msg := c.errorf(t.Pos(), "expected qualified identifier")
-		return &Bad{Msg: msg}
-
-	case *ast.StarExpr:
-		return &Pointer{Base: c.makeType(t.X, true)}
-
-	case *ast.ArrayType:
-		if t.Len != nil {
-			// TODO(gri) compute length
-			return &Array{Elt: c.makeType(t.Elt, cycleOk)}
-		}
-		return &Slice{Elt: c.makeType(t.Elt, true)}
-
-	case *ast.StructType:
-		fields, tags, _ := c.collectFields(token.STRUCT, t.Fields, cycleOk)
-		return &Struct{Fields: fields, Tags: tags}
-
-	case *ast.FuncType:
-		params, _, _ := c.collectFields(token.FUNC, t.Params, true)
-		results, _, isVariadic := c.collectFields(token.FUNC, t.Results, true)
-		return &Func{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
-
-	case *ast.InterfaceType:
-		methods, _, _ := c.collectFields(token.INTERFACE, t.Methods, cycleOk)
-		methods.Sort()
-		return &Interface{Methods: methods}
-
-	case *ast.MapType:
-		return &Map{Key: c.makeType(t.Key, true), Elt: c.makeType(t.Key, true)}
-
-	case *ast.ChanType:
-		return &Chan{Dir: t.Dir, Elt: c.makeType(t.Value, true)}
-	}
-
-	panic(fmt.Sprintf("unreachable (%T)", x))
-}
-
-// checkObj type checks an object.
-func (c *checker) checkObj(obj *ast.Object, ref bool) {
-	if obj.Type != nil {
-		// object has already been type checked
-		return
-	}
-
-	switch obj.Kind {
-	case ast.Bad:
-		// ignore
-
-	case ast.Con:
-		// TODO(gri) complete this
-
-	case ast.Typ:
-		typ := &Name{Obj: obj}
-		obj.Type = typ // "mark" object so recursion terminates
-		typ.Underlying = Underlying(c.makeType(obj.Decl.(*ast.TypeSpec).Type, ref))
-
-	case ast.Var:
-		// TODO(gri) complete this
-
-	case ast.Fun:
-		// TODO(gri) complete this
-
-	default:
-		panic("unreachable")
-	}
-}
-
-// Check typechecks a package.
-// It augments the AST by assigning types to all ast.Objects and returns a map
-// of types for all expression nodes in statements, and a scanner.ErrorList if
-// there are errors.
-//
-func Check(fset *token.FileSet, pkg *ast.Package) (types map[ast.Expr]Type, err os.Error) {
-	var c checker
-	c.fset = fset
-	c.types = make(map[ast.Expr]Type)
-
-	for _, obj := range pkg.Scope.Objects {
-		c.checkObj(obj, false)
-	}
-
-	return c.types, c.GetError(scanner.NoMultiples)
-}
diff --git a/src/pkg/go/types/check_test.go b/src/pkg/go/types/check_test.go
deleted file mode 100644
index 8be653f..0000000
--- a/src/pkg/go/types/check_test.go
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2011 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 file implements a typechecker test harness. The packages specified
-// in tests are typechecked. Error messages reported by the typechecker are
-// compared against the error messages expected in the test files.
-//
-// Expected errors are indicated in the test files by putting a comment
-// of the form /* ERROR "rx" */ immediately following an offending token.
-// The harness will verify that an error matching the regular expression
-// rx is reported at that source position. Consecutive comments may be
-// used to indicate multiple errors for the same token position.
-//
-// For instance, the following test file indicates that a "not declared"
-// error should be reported for the undeclared variable x:
-//
-//	package p
-//	func f() {
-//		_ = x /* ERROR "not declared" */ + 1
-//	}
-
-package types
-
-import (
-	"fmt"
-	"go/ast"
-	"go/parser"
-	"go/scanner"
-	"go/token"
-	"io/ioutil"
-	"os"
-	"regexp"
-	"testing"
-)
-
-// The test filenames do not end in .go so that they are invisible
-// to gofmt since they contain comments that must not change their
-// positions relative to surrounding tokens.
-
-var tests = []struct {
-	name  string
-	files []string
-}{
-	{"test0", []string{"testdata/test0.src"}},
-}
-
-var fset = token.NewFileSet()
-
-// TODO(gri) This functionality should be in token.Fileset.
-func getFile(filename string) *token.File {
-	for f := range fset.Files() {
-		if f.Name() == filename {
-			return f
-		}
-	}
-	return nil
-}
-
-// TODO(gri) This functionality should be in token.Fileset.
-func getPos(filename string, offset int) token.Pos {
-	if f := getFile(filename); f != nil {
-		return f.Pos(offset)
-	}
-	return token.NoPos
-}
-
-// TODO(gri) Need to revisit parser interface. We should be able to use parser.ParseFiles
-//           or a similar function instead.
-func parseFiles(t *testing.T, testname string, filenames []string) (map[string]*ast.File, os.Error) {
-	files := make(map[string]*ast.File)
-	var errors scanner.ErrorList
-	for _, filename := range filenames {
-		if _, exists := files[filename]; exists {
-			t.Fatalf("%s: duplicate file %s", testname, filename)
-		}
-		file, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors)
-		if file == nil {
-			t.Fatalf("%s: could not parse file %s", testname, filename)
-		}
-		files[filename] = file
-		if err != nil {
-			// if the parser returns a non-scanner.ErrorList error
-			// the file couldn't be read in the first place and
-			// file == nil; in that case we shouldn't reach here
-			errors = append(errors, err.(scanner.ErrorList)...)
-		}
-
-	}
-	return files, errors
-}
-
-// ERROR comments must be of the form /* ERROR "rx" */ and rx is
-// a regular expression that matches the expected error message.
-//
-var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`)
-
-// expectedErrors collects the regular expressions of ERROR comments found
-// in files and returns them as a map of error positions to error messages.
-//
-func expectedErrors(t *testing.T, testname string, files map[string]*ast.File) map[token.Pos]string {
-	errors := make(map[token.Pos]string)
-	for filename := range files {
-		src, err := ioutil.ReadFile(filename)
-		if err != nil {
-			t.Fatalf("%s: could not read %s", testname, filename)
-		}
-
-		var s scanner.Scanner
-		// file was parsed already - do not add it again to the file
-		// set otherwise the position information returned here will
-		// not match the position information collected by the parser
-		s.Init(getFile(filename), src, nil, scanner.ScanComments)
-		var prev token.Pos // position of last non-comment token
-
-	scanFile:
-		for {
-			pos, tok, lit := s.Scan()
-			switch tok {
-			case token.EOF:
-				break scanFile
-			case token.COMMENT:
-				s := errRx.FindStringSubmatch(lit)
-				if len(s) == 2 {
-					errors[prev] = string(s[1])
-				}
-			default:
-				prev = pos
-			}
-		}
-	}
-	return errors
-}
-
-func eliminate(t *testing.T, expected map[token.Pos]string, errors os.Error) {
-	if errors == nil {
-		return
-	}
-	for _, error := range errors.(scanner.ErrorList) {
-		// error.Pos is a token.Position, but we want
-		// a token.Pos so we can do a map lookup
-		// TODO(gri) Need to move scanner.Errors over
-		//           to use token.Pos and file set info.
-		pos := getPos(error.Pos.Filename, error.Pos.Offset)
-		if msg, found := expected[pos]; found {
-			// we expect a message at pos; check if it matches
-			rx, err := regexp.Compile(msg)
-			if err != nil {
-				t.Errorf("%s: %v", error.Pos, err)
-				continue
-			}
-			if match := rx.MatchString(error.Msg); !match {
-				t.Errorf("%s: %q does not match %q", error.Pos, error.Msg, msg)
-				continue
-			}
-			// we have a match - eliminate this error
-			expected[pos] = "", false
-		} else {
-			// To keep in mind when analyzing failed test output:
-			// If the same error position occurs multiple times in errors,
-			// this message will be triggered (because the first error at
-			// the position removes this position from the expected errors).
-			t.Errorf("%s: no (multiple?) error expected, but found: %s", error.Pos, error.Msg)
-		}
-	}
-}
-
-func check(t *testing.T, testname string, testfiles []string) {
-	// TODO(gri) Eventually all these different phases should be
-	//           subsumed into a single function call that takes
-	//           a set of files and creates a fully resolved and
-	//           type-checked AST.
-
-	files, err := parseFiles(t, testname, testfiles)
-
-	// we are expecting the following errors
-	// (collect these after parsing the files so that
-	// they are found in the file set)
-	errors := expectedErrors(t, testname, files)
-
-	// verify errors returned by the parser
-	eliminate(t, errors, err)
-
-	// verify errors returned after resolving identifiers
-	pkg, err := ast.NewPackage(fset, files, GcImporter, Universe)
-	eliminate(t, errors, err)
-
-	// verify errors returned by the typechecker
-	_, err = Check(fset, pkg)
-	eliminate(t, errors, err)
-
-	// there should be no expected errors left
-	if len(errors) > 0 {
-		t.Errorf("%s: %d errors not reported:", testname, len(errors))
-		for pos, msg := range errors {
-			t.Errorf("%s: %s\n", fset.Position(pos), msg)
-		}
-	}
-}
-
-func TestCheck(t *testing.T) {
-	// For easy debugging w/o changing the testing code,
-	// if there is a local test file, only test that file.
-	const testfile = "test.go"
-	if fi, err := os.Stat(testfile); err == nil && fi.IsRegular() {
-		fmt.Printf("WARNING: Testing only %s (remove it to run all tests)\n", testfile)
-		check(t, testfile, []string{testfile})
-		return
-	}
-
-	// Otherwise, run all the tests.
-	for _, test := range tests {
-		check(t, test.name, test.files)
-	}
-}
diff --git a/src/pkg/go/types/const.go b/src/pkg/go/types/const.go
deleted file mode 100644
index 1ef95d9..0000000
--- a/src/pkg/go/types/const.go
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright 2011 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 file implements operations on ideal constants.
-
-package types
-
-import (
-	"big"
-	"go/token"
-	"strconv"
-)
-
-// TODO(gri) Consider changing the API so Const is an interface
-//           and operations on consts don't have to type switch.
-
-// A Const implements an ideal constant Value.
-// The zero value z for a Const is not a valid constant value.
-type Const struct {
-	// representation of constant values:
-	// ideal bool     ->  bool
-	// ideal int      ->  *big.Int
-	// ideal float    ->  *big.Rat
-	// ideal complex  ->  cmplx
-	// ideal string   ->  string
-	val interface{}
-}
-
-// Representation of complex values.
-type cmplx struct {
-	re, im *big.Rat
-}
-
-func assert(cond bool) {
-	if !cond {
-		panic("go/types internal error: assertion failed")
-	}
-}
-
-// MakeConst makes an ideal constant from a literal
-// token and the corresponding literal string.
-func MakeConst(tok token.Token, lit string) Const {
-	switch tok {
-	case token.INT:
-		var x big.Int
-		_, ok := x.SetString(lit, 0)
-		assert(ok)
-		return Const{&x}
-	case token.FLOAT:
-		var y big.Rat
-		_, ok := y.SetString(lit)
-		assert(ok)
-		return Const{&y}
-	case token.IMAG:
-		assert(lit[len(lit)-1] == 'i')
-		var im big.Rat
-		_, ok := im.SetString(lit[0 : len(lit)-1])
-		assert(ok)
-		return Const{cmplx{big.NewRat(0, 1), &im}}
-	case token.CHAR:
-		assert(lit[0] == '\'' && lit[len(lit)-1] == '\'')
-		code, _, _, err := strconv.UnquoteChar(lit[1:len(lit)-1], '\'')
-		assert(err == nil)
-		return Const{big.NewInt(int64(code))}
-	case token.STRING:
-		s, err := strconv.Unquote(lit)
-		assert(err == nil)
-		return Const{s}
-	}
-	panic("unreachable")
-}
-
-// MakeZero returns the zero constant for the given type.
-func MakeZero(typ *Type) Const {
-	// TODO(gri) fix this
-	return Const{0}
-}
-
-// Match attempts to match the internal constant representations of x and y.
-// If the attempt is successful, the result is the values of x and y,
-// if necessary converted to have the same internal representation; otherwise
-// the results are invalid.
-func (x Const) Match(y Const) (u, v Const) {
-	switch a := x.val.(type) {
-	case bool:
-		if _, ok := y.val.(bool); ok {
-			u, v = x, y
-		}
-	case *big.Int:
-		switch y.val.(type) {
-		case *big.Int:
-			u, v = x, y
-		case *big.Rat:
-			var z big.Rat
-			z.SetInt(a)
-			u, v = Const{&z}, y
-		case cmplx:
-			var z big.Rat
-			z.SetInt(a)
-			u, v = Const{cmplx{&z, big.NewRat(0, 1)}}, y
-		}
-	case *big.Rat:
-		switch y.val.(type) {
-		case *big.Int:
-			v, u = y.Match(x)
-		case *big.Rat:
-			u, v = x, y
-		case cmplx:
-			u, v = Const{cmplx{a, big.NewRat(0, 0)}}, y
-		}
-	case cmplx:
-		switch y.val.(type) {
-		case *big.Int, *big.Rat:
-			v, u = y.Match(x)
-		case cmplx:
-			u, v = x, y
-		}
-	case string:
-		if _, ok := y.val.(string); ok {
-			u, v = x, y
-		}
-	default:
-		panic("unreachable")
-	}
-	return
-}
-
-// Convert attempts to convert the constant x to a given type.
-// If the attempt is successful, the result is the new constant;
-// otherwise the result is invalid.
-func (x Const) Convert(typ *Type) Const {
-	// TODO(gri) implement this
-	switch x := x.val.(type) {
-	case bool:
-	case *big.Int:
-	case *big.Rat:
-	case cmplx:
-	case string:
-	}
-	return x
-}
-
-func (x Const) String() string {
-	switch x := x.val.(type) {
-	case bool:
-		if x {
-			return "true"
-		}
-		return "false"
-	case *big.Int:
-		return x.String()
-	case *big.Rat:
-		return x.FloatString(10) // 10 digits of precision after decimal point seems fine
-	case cmplx:
-		// TODO(gri) don't print 0 components
-		return x.re.FloatString(10) + " + " + x.im.FloatString(10) + "i"
-	case string:
-		return x
-	}
-	panic("unreachable")
-}
-
-func (x Const) UnaryOp(op token.Token) Const {
-	panic("unimplemented")
-}
-
-func (x Const) BinaryOp(op token.Token, y Const) Const {
-	var z interface{}
-	switch x := x.val.(type) {
-	case bool:
-		z = binaryBoolOp(x, op, y.val.(bool))
-	case *big.Int:
-		z = binaryIntOp(x, op, y.val.(*big.Int))
-	case *big.Rat:
-		z = binaryFloatOp(x, op, y.val.(*big.Rat))
-	case cmplx:
-		z = binaryCmplxOp(x, op, y.val.(cmplx))
-	case string:
-		z = binaryStringOp(x, op, y.val.(string))
-	default:
-		panic("unreachable")
-	}
-	return Const{z}
-}
-
-func binaryBoolOp(x bool, op token.Token, y bool) interface{} {
-	switch op {
-	case token.EQL:
-		return x == y
-	case token.NEQ:
-		return x != y
-	}
-	panic("unreachable")
-}
-
-func binaryIntOp(x *big.Int, op token.Token, y *big.Int) interface{} {
-	var z big.Int
-	switch op {
-	case token.ADD:
-		return z.Add(x, y)
-	case token.SUB:
-		return z.Sub(x, y)
-	case token.MUL:
-		return z.Mul(x, y)
-	case token.QUO:
-		return z.Quo(x, y)
-	case token.REM:
-		return z.Rem(x, y)
-	case token.AND:
-		return z.And(x, y)
-	case token.OR:
-		return z.Or(x, y)
-	case token.XOR:
-		return z.Xor(x, y)
-	case token.AND_NOT:
-		return z.AndNot(x, y)
-	case token.SHL:
-		panic("unimplemented")
-	case token.SHR:
-		panic("unimplemented")
-	case token.EQL:
-		return x.Cmp(y) == 0
-	case token.NEQ:
-		return x.Cmp(y) != 0
-	case token.LSS:
-		return x.Cmp(y) < 0
-	case token.LEQ:
-		return x.Cmp(y) <= 0
-	case token.GTR:
-		return x.Cmp(y) > 0
-	case token.GEQ:
-		return x.Cmp(y) >= 0
-	}
-	panic("unreachable")
-}
-
-func binaryFloatOp(x *big.Rat, op token.Token, y *big.Rat) interface{} {
-	var z big.Rat
-	switch op {
-	case token.ADD:
-		return z.Add(x, y)
-	case token.SUB:
-		return z.Sub(x, y)
-	case token.MUL:
-		return z.Mul(x, y)
-	case token.QUO:
-		return z.Quo(x, y)
-	case token.EQL:
-		return x.Cmp(y) == 0
-	case token.NEQ:
-		return x.Cmp(y) != 0
-	case token.LSS:
-		return x.Cmp(y) < 0
-	case token.LEQ:
-		return x.Cmp(y) <= 0
-	case token.GTR:
-		return x.Cmp(y) > 0
-	case token.GEQ:
-		return x.Cmp(y) >= 0
-	}
-	panic("unreachable")
-}
-
-func binaryCmplxOp(x cmplx, op token.Token, y cmplx) interface{} {
-	a, b := x.re, x.im
-	c, d := y.re, y.im
-	switch op {
-	case token.ADD:
-		// (a+c) + i(b+d)
-		var re, im big.Rat
-		re.Add(a, c)
-		im.Add(b, d)
-		return cmplx{&re, &im}
-	case token.SUB:
-		// (a-c) + i(b-d)
-		var re, im big.Rat
-		re.Sub(a, c)
-		im.Sub(b, d)
-		return cmplx{&re, &im}
-	case token.MUL:
-		// (ac-bd) + i(bc+ad)
-		var ac, bd, bc, ad big.Rat
-		ac.Mul(a, c)
-		bd.Mul(b, d)
-		bc.Mul(b, c)
-		ad.Mul(a, d)
-		var re, im big.Rat
-		re.Sub(&ac, &bd)
-		im.Add(&bc, &ad)
-		return cmplx{&re, &im}
-	case token.QUO:
-		// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
-		var ac, bd, bc, ad, s big.Rat
-		ac.Mul(a, c)
-		bd.Mul(b, d)
-		bc.Mul(b, c)
-		ad.Mul(a, d)
-		s.Add(c.Mul(c, c), d.Mul(d, d))
-		var re, im big.Rat
-		re.Add(&ac, &bd)
-		re.Quo(&re, &s)
-		im.Sub(&bc, &ad)
-		im.Quo(&im, &s)
-		return cmplx{&re, &im}
-	case token.EQL:
-		return a.Cmp(c) == 0 && b.Cmp(d) == 0
-	case token.NEQ:
-		return a.Cmp(c) != 0 || b.Cmp(d) != 0
-	}
-	panic("unreachable")
-}
-
-func binaryStringOp(x string, op token.Token, y string) interface{} {
-	switch op {
-	case token.ADD:
-		return x + y
-	case token.EQL:
-		return x == y
-	case token.NEQ:
-		return x != y
-	case token.LSS:
-		return x < y
-	case token.LEQ:
-		return x <= y
-	case token.GTR:
-		return x > y
-	case token.GEQ:
-		return x >= y
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/go/types/exportdata.go b/src/pkg/go/types/exportdata.go
deleted file mode 100644
index 3835203..0000000
--- a/src/pkg/go/types/exportdata.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2011 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 file implements ExportData.
-
-package types
-
-import (
-	"bufio"
-	"fmt"
-	"io"
-	"os"
-	"strconv"
-	"strings"
-)
-
-func readGopackHeader(buf *bufio.Reader) (name string, size int, err os.Error) {
-	// See $GOROOT/include/ar.h.
-	hdr := make([]byte, 64+12+6+6+8+10+2)
-	_, err = io.ReadFull(buf, hdr)
-	if err != nil {
-		return
-	}
-	if trace {
-		fmt.Printf("header: %s", hdr)
-	}
-	s := strings.TrimSpace(string(hdr[64+12+6+6+8:][:10]))
-	size, err = strconv.Atoi(s)
-	if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
-		err = os.NewError("invalid archive header")
-		return
-	}
-	name = strings.TrimSpace(string(hdr[:64]))
-	return
-}
-
-type dataReader struct {
-	*bufio.Reader
-	io.Closer
-}
-
-// ExportData returns a readCloser positioned at the beginning of the
-// export data section of the given object/archive file, or an error.
-// It is the caller's responsibility to close the readCloser.
-//
-func ExportData(filename string) (rc io.ReadCloser, err os.Error) {
-	file, err := os.Open(filename)
-	if err != nil {
-		return
-	}
-
-	defer func() {
-		if err != nil {
-			file.Close()
-			// Add file name to error.
-			err = fmt.Errorf("reading export data: %s: %v", filename, err)
-		}
-	}()
-
-	buf := bufio.NewReader(file)
-
-	// Read first line to make sure this is an object file.
-	line, err := buf.ReadSlice('\n')
-	if err != nil {
-		return
-	}
-	if string(line) == "!<arch>\n" {
-		// Archive file.  Scan to __.PKGDEF, which should
-		// be second archive entry.
-		var name string
-		var size int
-
-		// First entry should be __.SYMDEF.
-		// Read and discard.
-		if name, size, err = readGopackHeader(buf); err != nil {
-			return
-		}
-		if name != "__.SYMDEF" {
-			err = os.NewError("go archive does not begin with __.SYMDEF")
-			return
-		}
-		const block = 4096
-		tmp := make([]byte, block)
-		for size > 0 {
-			n := size
-			if n > block {
-				n = block
-			}
-			_, err = io.ReadFull(buf, tmp[:n])
-			if err != nil {
-				return
-			}
-			size -= n
-		}
-
-		// Second entry should be __.PKGDEF.
-		if name, size, err = readGopackHeader(buf); err != nil {
-			return
-		}
-		if name != "__.PKGDEF" {
-			err = os.NewError("go archive is missing __.PKGDEF")
-			return
-		}
-
-		// Read first line of __.PKGDEF data, so that line
-		// is once again the first line of the input.
-		line, err = buf.ReadSlice('\n')
-		if err != nil {
-			return
-		}
-	}
-
-	// Now at __.PKGDEF in archive or still at beginning of file.
-	// Either way, line should begin with "go object ".
-	if !strings.HasPrefix(string(line), "go object ") {
-		err = os.NewError("not a go object file")
-		return
-	}
-
-	// Skip over object header to export data.
-	// Begins after first line with $$.
-	for line[0] != '$' {
-		line, err = buf.ReadSlice('\n')
-		if err != nil {
-			return
-		}
-	}
-
-	rc = &dataReader{buf, file}
-	return
-}
diff --git a/src/pkg/go/types/gcimporter.go b/src/pkg/go/types/gcimporter.go
deleted file mode 100644
index 6ab1806..0000000
--- a/src/pkg/go/types/gcimporter.go
+++ /dev/null
@@ -1,799 +0,0 @@
-// Copyright 2011 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 file implements an ast.Importer for gc generated object files.
-// TODO(gri) Eventually move this into a separate package outside types.
-
-package types
-
-import (
-	"big"
-	"fmt"
-	"go/ast"
-	"go/token"
-	"io"
-	"os"
-	"path/filepath"
-	"runtime"
-	"scanner"
-	"strconv"
-)
-
-const trace = false // set to true for debugging
-
-var (
-	pkgRoot = filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH)
-	pkgExts = [...]string{".a", ".5", ".6", ".8"}
-)
-
-// findPkg returns the filename and package id for an import path.
-// If no file was found, an empty filename is returned.
-func findPkg(path string) (filename, id string) {
-	if len(path) == 0 {
-		return
-	}
-
-	id = path
-	var noext string
-	switch path[0] {
-	default:
-		// "x" -> "$GOROOT/pkg/$GOOS_$GOARCH/x.ext", "x"
-		noext = filepath.Join(pkgRoot, path)
-
-	case '.':
-		// "./x" -> "/this/directory/x.ext", "/this/directory/x"
-		cwd, err := os.Getwd()
-		if err != nil {
-			return
-		}
-		noext = filepath.Join(cwd, path)
-		id = noext
-
-	case '/':
-		// "/x" -> "/x.ext", "/x"
-		noext = path
-	}
-
-	// try extensions
-	for _, ext := range pkgExts {
-		filename = noext + ext
-		if f, err := os.Stat(filename); err == nil && f.IsRegular() {
-			return
-		}
-	}
-
-	filename = "" // not found
-	return
-}
-
-// gcParser parses the exports inside a gc compiler-produced
-// object/archive file and populates its scope with the results.
-type gcParser struct {
-	scanner scanner.Scanner
-	tok     int                    // current token
-	lit     string                 // literal string; only valid for Ident, Int, String tokens
-	id      string                 // package id of imported package
-	imports map[string]*ast.Object // package id -> package object
-}
-
-func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
-	p.scanner.Init(src)
-	p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
-	p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
-	p.scanner.Whitespace = 1<<'\t' | 1<<' '
-	p.scanner.Filename = filename // for good error messages
-	p.next()
-	p.id = id
-	p.imports = imports
-}
-
-func (p *gcParser) next() {
-	p.tok = p.scanner.Scan()
-	switch p.tok {
-	case scanner.Ident, scanner.Int, scanner.String:
-		p.lit = p.scanner.TokenText()
-	default:
-		p.lit = ""
-	}
-	if trace {
-		fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
-	}
-}
-
-// GcImporter implements the ast.Importer signature.
-func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, err os.Error) {
-	if path == "unsafe" {
-		return Unsafe, nil
-	}
-
-	defer func() {
-		if r := recover(); r != nil {
-			err = r.(importError) // will re-panic if r is not an importError
-			if trace {
-				panic(err) // force a stack trace
-			}
-		}
-	}()
-
-	filename, id := findPkg(path)
-	if filename == "" {
-		err = os.NewError("can't find import: " + id)
-		return
-	}
-
-	if pkg = imports[id]; pkg != nil {
-		return // package was imported before
-	}
-
-	buf, err := ExportData(filename)
-	if err != nil {
-		return
-	}
-	defer buf.Close()
-
-	if trace {
-		fmt.Printf("importing %s (%s)\n", id, filename)
-	}
-
-	var p gcParser
-	p.init(filename, id, buf, imports)
-	pkg = p.parseExport()
-	return
-}
-
-// ----------------------------------------------------------------------------
-// Error handling
-
-// Internal errors are boxed as importErrors.
-type importError struct {
-	pos scanner.Position
-	err os.Error
-}
-
-func (e importError) String() string {
-	return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
-}
-
-func (p *gcParser) error(err interface{}) {
-	if s, ok := err.(string); ok {
-		err = os.NewError(s)
-	}
-	// panic with a runtime.Error if err is not an os.Error
-	panic(importError{p.scanner.Pos(), err.(os.Error)})
-}
-
-func (p *gcParser) errorf(format string, args ...interface{}) {
-	p.error(fmt.Sprintf(format, args...))
-}
-
-func (p *gcParser) expect(tok int) string {
-	lit := p.lit
-	if p.tok != tok {
-		p.errorf("expected %q, got %q (%q)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
-	}
-	p.next()
-	return lit
-}
-
-func (p *gcParser) expectSpecial(tok string) {
-	sep := 'x' // not white space
-	i := 0
-	for i < len(tok) && p.tok == int(tok[i]) && sep > ' ' {
-		sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
-		p.next()
-		i++
-	}
-	if i < len(tok) {
-		p.errorf("expected %q, got %q", tok, tok[0:i])
-	}
-}
-
-func (p *gcParser) expectKeyword(keyword string) {
-	lit := p.expect(scanner.Ident)
-	if lit != keyword {
-		p.errorf("expected keyword %s, got %q", keyword, lit)
-	}
-}
-
-// ----------------------------------------------------------------------------
-// Import declarations
-
-// ImportPath = string_lit .
-//
-func (p *gcParser) parsePkgId() *ast.Object {
-	id, err := strconv.Unquote(p.expect(scanner.String))
-	if err != nil {
-		p.error(err)
-	}
-
-	switch id {
-	case "":
-		// id == "" stands for the imported package id
-		// (only known at time of package installation)
-		id = p.id
-	case "unsafe":
-		// package unsafe is not in the imports map - handle explicitly
-		return Unsafe
-	}
-
-	pkg := p.imports[id]
-	if pkg == nil {
-		scope = ast.NewScope(nil)
-		pkg = ast.NewObj(ast.Pkg, "")
-		pkg.Data = scope
-		p.imports[id] = pkg
-	}
-
-	return pkg
-}
-
-// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
-func (p *gcParser) parseDotIdent() string {
-	ident := ""
-	if p.tok != scanner.Int {
-		sep := 'x' // not white space
-		for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
-			ident += p.lit
-			sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
-			p.next()
-		}
-	}
-	if ident == "" {
-		p.expect(scanner.Ident) // use expect() for error handling
-	}
-	return ident
-}
-
-// ExportedName = ImportPath "." dotIdentifier .
-//
-func (p *gcParser) parseExportedName(kind ast.ObjKind) *ast.Object {
-	pkg := p.parsePkgId()
-	p.expect('.')
-	name := p.parseDotIdent()
-
-	// a type may have been declared before - if it exists
-	// already in the respective package scope, return that
-	// type
-	scope := pkg.Data.(*ast.Scope)
-	if kind == ast.Typ {
-		if obj := scope.Lookup(name); obj != nil {
-			assert(obj.Kind == ast.Typ)
-			return obj
-		}
-	}
-
-	// any other object must be a newly declared object -
-	// create it and insert it into the package scope
-	obj := ast.NewObj(kind, name)
-	if scope.Insert(obj) != nil {
-		p.errorf("already declared: %s", obj.Name)
-	}
-
-	// a new type object is a named type and may be referred
-	// to before the underlying type is known - set it up
-	if kind == ast.Typ {
-		obj.Type = &Name{Obj: obj}
-	}
-
-	return obj
-}
-
-// ----------------------------------------------------------------------------
-// Types
-
-// BasicType = identifier .
-//
-func (p *gcParser) parseBasicType() Type {
-	obj := Universe.Lookup(p.expect(scanner.Ident))
-	if obj == nil || obj.Kind != ast.Typ {
-		p.errorf("not a basic type: %s", obj.Name)
-	}
-	return obj.Type.(Type)
-}
-
-// ArrayType = "[" int_lit "]" Type .
-//
-func (p *gcParser) parseArrayType() Type {
-	// "[" already consumed and lookahead known not to be "]"
-	lit := p.expect(scanner.Int)
-	p.expect(']')
-	elt := p.parseType()
-	n, err := strconv.Atoui64(lit)
-	if err != nil {
-		p.error(err)
-	}
-	return &Array{Len: n, Elt: elt}
-}
-
-// MapType = "map" "[" Type "]" Type .
-//
-func (p *gcParser) parseMapType() Type {
-	p.expectKeyword("map")
-	p.expect('[')
-	key := p.parseType()
-	p.expect(']')
-	elt := p.parseType()
-	return &Map{Key: key, Elt: elt}
-}
-
-// Name = identifier | "?" .
-//
-func (p *gcParser) parseName() (name string) {
-	switch p.tok {
-	case scanner.Ident:
-		name = p.lit
-		p.next()
-	case '?':
-		// anonymous
-		p.next()
-	default:
-		p.error("name expected")
-	}
-	return
-}
-
-// Field = Name Type [ ":" string_lit ] .
-//
-func (p *gcParser) parseField() (fld *ast.Object, tag string) {
-	name := p.parseName()
-	ftyp := p.parseType()
-	if name == "" {
-		// anonymous field - ftyp must be T or *T and T must be a type name
-		if _, ok := Deref(ftyp).(*Name); !ok {
-			p.errorf("anonymous field expected")
-		}
-	}
-	if p.tok == ':' {
-		p.next()
-		tag = p.expect(scanner.String)
-	}
-	fld = ast.NewObj(ast.Var, name)
-	fld.Type = ftyp
-	return
-}
-
-// StructType = "struct" "{" [ FieldList ] "}" .
-// FieldList  = Field { ";" Field } .
-//
-func (p *gcParser) parseStructType() Type {
-	var fields []*ast.Object
-	var tags []string
-
-	parseField := func() {
-		fld, tag := p.parseField()
-		fields = append(fields, fld)
-		tags = append(tags, tag)
-	}
-
-	p.expectKeyword("struct")
-	p.expect('{')
-	if p.tok != '}' {
-		parseField()
-		for p.tok == ';' {
-			p.next()
-			parseField()
-		}
-	}
-	p.expect('}')
-
-	return &Struct{Fields: fields, Tags: tags}
-}
-
-// Parameter = ( identifier | "?" ) [ "..." ] Type [ ":" string_lit ] .
-//
-func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) {
-	name := p.parseName()
-	if name == "" {
-		name = "_" // cannot access unnamed identifiers
-	}
-	if p.tok == '.' {
-		p.expectSpecial("...")
-		isVariadic = true
-	}
-	ptyp := p.parseType()
-	// ignore argument tag
-	if p.tok == ':' {
-		p.next()
-		p.expect(scanner.String)
-	}
-	par = ast.NewObj(ast.Var, name)
-	par.Type = ptyp
-	return
-}
-
-// Parameters    = "(" [ ParameterList ] ")" .
-// ParameterList = { Parameter "," } Parameter .
-//
-func (p *gcParser) parseParameters() (list []*ast.Object, isVariadic bool) {
-	parseParameter := func() {
-		par, variadic := p.parseParameter()
-		list = append(list, par)
-		if variadic {
-			if isVariadic {
-				p.error("... not on final argument")
-			}
-			isVariadic = true
-		}
-	}
-
-	p.expect('(')
-	if p.tok != ')' {
-		parseParameter()
-		for p.tok == ',' {
-			p.next()
-			parseParameter()
-		}
-	}
-	p.expect(')')
-
-	return
-}
-
-// Signature = Parameters [ Result ] .
-// Result    = Type | Parameters .
-//
-func (p *gcParser) parseSignature() *Func {
-	params, isVariadic := p.parseParameters()
-
-	// optional result type
-	var results []*ast.Object
-	switch p.tok {
-	case scanner.Ident, scanner.String, '[', '*', '<':
-		// single, unnamed result
-		result := ast.NewObj(ast.Var, "_")
-		result.Type = p.parseType()
-		results = []*ast.Object{result}
-	case '(':
-		// named or multiple result(s)
-		var variadic bool
-		results, variadic = p.parseParameters()
-		if variadic {
-			p.error("... not permitted on result type")
-		}
-	}
-
-	return &Func{Params: params, Results: results, IsVariadic: isVariadic}
-}
-
-// MethodSpec = identifier Signature .
-//
-func (p *gcParser) parseMethodSpec() *ast.Object {
-	if p.tok == scanner.Ident {
-		p.expect(scanner.Ident)
-	} else {
-		// TODO(gri) should this be parseExportedName here?
-		p.parsePkgId()
-		p.expect('.')
-		p.parseDotIdent()
-	}
-	p.parseSignature()
-
-	// TODO(gri) compute method object
-	return ast.NewObj(ast.Fun, "_")
-}
-
-// InterfaceType = "interface" "{" [ MethodList ] "}" .
-// MethodList    = MethodSpec { ";" MethodSpec } .
-//
-func (p *gcParser) parseInterfaceType() Type {
-	var methods ObjList
-
-	parseMethod := func() {
-		meth := p.parseMethodSpec()
-		methods = append(methods, meth)
-	}
-
-	p.expectKeyword("interface")
-	p.expect('{')
-	if p.tok != '}' {
-		parseMethod()
-		for p.tok == ';' {
-			p.next()
-			parseMethod()
-		}
-	}
-	p.expect('}')
-
-	methods.Sort()
-	return &Interface{Methods: methods}
-}
-
-// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
-//
-func (p *gcParser) parseChanType() Type {
-	dir := ast.SEND | ast.RECV
-	if p.tok == scanner.Ident {
-		p.expectKeyword("chan")
-		if p.tok == '<' {
-			p.expectSpecial("<-")
-			dir = ast.SEND
-		}
-	} else {
-		p.expectSpecial("<-")
-		p.expectKeyword("chan")
-		dir = ast.RECV
-	}
-	elt := p.parseType()
-	return &Chan{Dir: dir, Elt: elt}
-}
-
-// Type =
-//	BasicType | TypeName | ArrayType | SliceType | StructType |
-//      PointerType | FuncType | InterfaceType | MapType | ChanType |
-//      "(" Type ")" .
-// BasicType = ident .
-// TypeName = ExportedName .
-// SliceType = "[" "]" Type .
-// PointerType = "*" Type .
-// FuncType = "func" Signature .
-//
-func (p *gcParser) parseType() Type {
-	switch p.tok {
-	case scanner.Ident:
-		switch p.lit {
-		default:
-			return p.parseBasicType()
-		case "struct":
-			return p.parseStructType()
-		case "func":
-			// FuncType
-			p.next()
-			return p.parseSignature()
-		case "interface":
-			return p.parseInterfaceType()
-		case "map":
-			return p.parseMapType()
-		case "chan":
-			return p.parseChanType()
-		}
-	case scanner.String:
-		// TypeName
-		return p.parseExportedName(ast.Typ).Type.(Type)
-	case '[':
-		p.next() // look ahead
-		if p.tok == ']' {
-			// SliceType
-			p.next()
-			return &Slice{Elt: p.parseType()}
-		}
-		return p.parseArrayType()
-	case '*':
-		// PointerType
-		p.next()
-		return &Pointer{Base: p.parseType()}
-	case '<':
-		return p.parseChanType()
-	case '(':
-		// "(" Type ")"
-		p.next()
-		typ := p.parseType()
-		p.expect(')')
-		return typ
-	}
-	p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
-	return nil
-}
-
-// ----------------------------------------------------------------------------
-// Declarations
-
-// ImportDecl = "import" identifier string_lit .
-//
-func (p *gcParser) parseImportDecl() {
-	p.expectKeyword("import")
-	// The identifier has no semantic meaning in the import data.
-	// It exists so that error messages can print the real package
-	// name: binary.ByteOrder instead of "encoding/binary".ByteOrder.
-	name := p.expect(scanner.Ident)
-	pkg := p.parsePkgId()
-	assert(pkg.Name == "" || pkg.Name == name)
-	pkg.Name = name
-}
-
-// int_lit = [ "+" | "-" ] { "0" ... "9" } .
-//
-func (p *gcParser) parseInt() (sign, val string) {
-	switch p.tok {
-	case '-':
-		p.next()
-		sign = "-"
-	case '+':
-		p.next()
-	}
-	val = p.expect(scanner.Int)
-	return
-}
-
-// number = int_lit [ "p" int_lit ] .
-//
-func (p *gcParser) parseNumber() Const {
-	// mantissa
-	sign, val := p.parseInt()
-	mant, ok := new(big.Int).SetString(sign+val, 10)
-	assert(ok)
-
-	if p.lit == "p" {
-		// exponent (base 2)
-		p.next()
-		sign, val = p.parseInt()
-		exp, err := strconv.Atoui(val)
-		if err != nil {
-			p.error(err)
-		}
-		if sign == "-" {
-			denom := big.NewInt(1)
-			denom.Lsh(denom, exp)
-			return Const{new(big.Rat).SetFrac(mant, denom)}
-		}
-		if exp > 0 {
-			mant.Lsh(mant, exp)
-		}
-		return Const{new(big.Rat).SetInt(mant)}
-	}
-
-	return Const{mant}
-}
-
-// ConstDecl   = "const" ExportedName [ Type ] "=" Literal .
-// Literal     = bool_lit | int_lit | float_lit | complex_lit | string_lit .
-// bool_lit    = "true" | "false" .
-// complex_lit = "(" float_lit "+" float_lit ")" .
-// string_lit  = `"` { unicode_char } `"` .
-//
-func (p *gcParser) parseConstDecl() {
-	p.expectKeyword("const")
-	obj := p.parseExportedName(ast.Con)
-	var x Const
-	var typ Type
-	if p.tok != '=' {
-		obj.Type = p.parseType()
-	}
-	p.expect('=')
-	switch p.tok {
-	case scanner.Ident:
-		// bool_lit
-		if p.lit != "true" && p.lit != "false" {
-			p.error("expected true or false")
-		}
-		x = Const{p.lit == "true"}
-		typ = Bool.Underlying
-		p.next()
-	case '-', scanner.Int:
-		// int_lit
-		x = p.parseNumber()
-		typ = Int.Underlying
-		if _, ok := x.val.(*big.Rat); ok {
-			typ = Float64.Underlying
-		}
-	case '(':
-		// complex_lit
-		p.next()
-		re := p.parseNumber()
-		p.expect('+')
-		im := p.parseNumber()
-		p.expect(')')
-		x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
-		typ = Complex128.Underlying
-	case scanner.String:
-		// string_lit
-		x = MakeConst(token.STRING, p.lit)
-		p.next()
-		typ = String.Underlying
-	default:
-		p.error("expected literal")
-	}
-	if obj.Type == nil {
-		obj.Type = typ
-	}
-	obj.Data = x
-}
-
-// TypeDecl = "type" ExportedName Type .
-//
-func (p *gcParser) parseTypeDecl() {
-	p.expectKeyword("type")
-	obj := p.parseExportedName(ast.Typ)
-
-	// The type object may have been imported before and thus already
-	// have a type associated with it. We still need to parse the type
-	// structure, but throw it away if the object already has a type.
-	// This ensures that all imports refer to the same type object for
-	// a given type declaration.
-	typ := p.parseType()
-
-	if name := obj.Type.(*Name); name.Underlying == nil {
-		assert(Underlying(typ) == typ)
-		name.Underlying = typ
-	}
-}
-
-// VarDecl = "var" ExportedName Type .
-//
-func (p *gcParser) parseVarDecl() {
-	p.expectKeyword("var")
-	obj := p.parseExportedName(ast.Var)
-	obj.Type = p.parseType()
-}
-
-// FuncDecl = "func" ExportedName Signature .
-//
-func (p *gcParser) parseFuncDecl() {
-	// "func" already consumed
-	obj := p.parseExportedName(ast.Fun)
-	obj.Type = p.parseSignature()
-}
-
-// MethodDecl = "func" Receiver identifier Signature .
-// Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
-//
-func (p *gcParser) parseMethodDecl() {
-	// "func" already consumed
-	p.expect('(')
-	p.parseParameter() // receiver
-	p.expect(')')
-	p.expect(scanner.Ident)
-	p.parseSignature()
-}
-
-// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
-//
-func (p *gcParser) parseDecl() {
-	switch p.lit {
-	case "import":
-		p.parseImportDecl()
-	case "const":
-		p.parseConstDecl()
-	case "type":
-		p.parseTypeDecl()
-	case "var":
-		p.parseVarDecl()
-	case "func":
-		p.next() // look ahead
-		if p.tok == '(' {
-			p.parseMethodDecl()
-		} else {
-			p.parseFuncDecl()
-		}
-	}
-	p.expect('\n')
-}
-
-// ----------------------------------------------------------------------------
-// Export
-
-// Export        = "PackageClause { Decl } "$$" .
-// PackageClause = "package" identifier [ "safe" ] "\n" .
-//
-func (p *gcParser) parseExport() *ast.Object {
-	p.expectKeyword("package")
-	name := p.expect(scanner.Ident)
-	if p.tok != '\n' {
-		// A package is safe if it was compiled with the -u flag,
-		// which disables the unsafe package.
-		// TODO(gri) remember "safe" package
-		p.expectKeyword("safe")
-	}
-	p.expect('\n')
-
-	assert(p.imports[p.id] == nil)
-	pkg := ast.NewObj(ast.Pkg, name)
-	pkg.Data = ast.NewScope(nil)
-	p.imports[p.id] = pkg
-
-	for p.tok != '$' && p.tok != scanner.EOF {
-		p.parseDecl()
-	}
-
-	if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
-		// don't call next()/expect() since reading past the
-		// export data may cause scanner errors (e.g. NUL chars)
-		p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
-	}
-
-	if n := p.scanner.ErrorCount; n != 0 {
-		p.errorf("expected no scanner errors, got %d", n)
-	}
-
-	return pkg
-}
diff --git a/src/pkg/go/types/gcimporter_test.go b/src/pkg/go/types/gcimporter_test.go
deleted file mode 100644
index ec87f5d..0000000
--- a/src/pkg/go/types/gcimporter_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2011 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 types
-
-import (
-	"exec"
-	"go/ast"
-	"io/ioutil"
-	"path/filepath"
-	"runtime"
-	"strings"
-	"testing"
-	"time"
-)
-
-var gcName, gcPath string // compiler name and path
-
-func init() {
-	// determine compiler
-	switch runtime.GOARCH {
-	case "386":
-		gcName = "8g"
-	case "amd64":
-		gcName = "6g"
-	case "arm":
-		gcName = "5g"
-	default:
-		gcName = "unknown-GOARCH-compiler"
-		gcPath = gcName
-		return
-	}
-	gcPath, _ = exec.LookPath(gcName)
-}
-
-func compile(t *testing.T, dirname, filename string) {
-	cmd := exec.Command(gcPath, filename)
-	cmd.Dir = dirname
-	out, err := cmd.CombinedOutput()
-	if err != nil {
-		t.Errorf("%s %s failed: %s", gcName, filename, err)
-		return
-	}
-	t.Logf("%s", string(out))
-}
-
-// Use the same global imports map for all tests. The effect is
-// as if all tested packages were imported into a single package.
-var imports = make(map[string]*ast.Object)
-
-func testPath(t *testing.T, path string) bool {
-	_, err := GcImporter(imports, path)
-	if err != nil {
-		t.Errorf("testPath(%s): %s", path, err)
-		return false
-	}
-	return true
-}
-
-const maxTime = 3e9 // maximum allotted testing time in ns
-
-func testDir(t *testing.T, dir string, endTime int64) (nimports int) {
-	dirname := filepath.Join(pkgRoot, dir)
-	list, err := ioutil.ReadDir(dirname)
-	if err != nil {
-		t.Errorf("testDir(%s): %s", dirname, err)
-	}
-	for _, f := range list {
-		if time.Nanoseconds() >= endTime {
-			t.Log("testing time used up")
-			return
-		}
-		switch {
-		case f.IsRegular():
-			// try extensions
-			for _, ext := range pkgExts {
-				if strings.HasSuffix(f.Name, ext) {
-					name := f.Name[0 : len(f.Name)-len(ext)] // remove extension
-					if testPath(t, filepath.Join(dir, name)) {
-						nimports++
-					}
-				}
-			}
-		case f.IsDirectory():
-			nimports += testDir(t, filepath.Join(dir, f.Name), endTime)
-		}
-	}
-	return
-}
-
-func TestGcImport(t *testing.T) {
-	compile(t, "testdata", "exports.go")
-
-	nimports := 0
-	if testPath(t, "./testdata/exports") {
-		nimports++
-	}
-	nimports += testDir(t, "", time.Nanoseconds()+maxTime) // installed packages
-	t.Logf("tested %d imports", nimports)
-}
diff --git a/src/pkg/go/types/universe.go b/src/pkg/go/types/universe.go
deleted file mode 100644
index 6ae88e5..0000000
--- a/src/pkg/go/types/universe.go
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2011 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.
-
-// FILE UNDER CONSTRUCTION. ANY AND ALL PARTS MAY CHANGE.
-// This file implements the universe and unsafe package scopes.
-
-package types
-
-import "go/ast"
-
-var (
-	scope    *ast.Scope // current scope to use for initialization
-	Universe *ast.Scope
-	Unsafe   *ast.Object // package unsafe
-)
-
-func define(kind ast.ObjKind, name string) *ast.Object {
-	obj := ast.NewObj(kind, name)
-	if scope.Insert(obj) != nil {
-		panic("types internal error: double declaration")
-	}
-	return obj
-}
-
-func defType(name string) *Name {
-	obj := define(ast.Typ, name)
-	typ := &Name{Underlying: &Basic{}, Obj: obj}
-	obj.Type = typ
-	return typ
-}
-
-func defConst(name string) {
-	obj := define(ast.Con, name)
-	_ = obj // TODO(gri) fill in other properties
-}
-
-func defFun(name string) {
-	obj := define(ast.Fun, name)
-	_ = obj // TODO(gri) fill in other properties
-}
-
-var (
-	Bool,
-	Int,
-	Float64,
-	Complex128,
-	String *Name
-)
-
-func init() {
-	scope = ast.NewScope(nil)
-	Universe = scope
-
-	Bool = defType("bool")
-	defType("byte") // TODO(gri) should be an alias for uint8
-	defType("complex64")
-	Complex128 = defType("complex128")
-	defType("float32")
-	Float64 = defType("float64")
-	defType("int8")
-	defType("int16")
-	defType("int32")
-	defType("int64")
-	String = defType("string")
-	defType("uint8")
-	defType("uint16")
-	defType("uint32")
-	defType("uint64")
-	Int = defType("int")
-	defType("uint")
-	defType("uintptr")
-
-	defConst("true")
-	defConst("false")
-	defConst("iota")
-	defConst("nil")
-
-	defFun("append")
-	defFun("cap")
-	defFun("close")
-	defFun("complex")
-	defFun("copy")
-	defFun("imag")
-	defFun("len")
-	defFun("make")
-	defFun("new")
-	defFun("panic")
-	defFun("print")
-	defFun("println")
-	defFun("real")
-	defFun("recover")
-
-	scope = ast.NewScope(nil)
-	Unsafe = ast.NewObj(ast.Pkg, "unsafe")
-	Unsafe.Data = scope
-
-	defType("Pointer")
-
-	defFun("Alignof")
-	defFun("New")
-	defFun("NewArray")
-	defFun("Offsetof")
-	defFun("Reflect")
-	defFun("Sizeof")
-	defFun("Typeof")
-	defFun("Unreflect")
-}
diff --git a/src/pkg/gob/Makefile b/src/pkg/gob/Makefile
deleted file mode 100644
index 68007c1..0000000
--- a/src/pkg/gob/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=gob
-GOFILES=\
-	decode.go\
-	decoder.go\
-	doc.go\
-	encode.go\
-	encoder.go\
-	error.go\
-	type.go\
-
-include ../../Make.pkg
-
-# Help for debugging. Requires adding debug.go to the gob package as well.
-
-dump:	dump.$O
-	$(LD) -o dump $<
-
-dump.$O:	dump.go
-	$(GC) $<
diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go
deleted file mode 100644
index 2bcbf82..0000000
--- a/src/pkg/gob/codec_test.go
+++ /dev/null
@@ -1,1406 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-import (
-	"bytes"
-	"math"
-	"os"
-	"reflect"
-	"strings"
-	"testing"
-	"unsafe"
-)
-
-// Guarantee encoding format by comparing some encodings to hand-written values
-type EncodeT struct {
-	x uint64
-	b []byte
-}
-
-var encodeT = []EncodeT{
-	{0x00, []byte{0x00}},
-	{0x0F, []byte{0x0F}},
-	{0xFF, []byte{0xFF, 0xFF}},
-	{0xFFFF, []byte{0xFE, 0xFF, 0xFF}},
-	{0xFFFFFF, []byte{0xFD, 0xFF, 0xFF, 0xFF}},
-	{0xFFFFFFFF, []byte{0xFC, 0xFF, 0xFF, 0xFF, 0xFF}},
-	{0xFFFFFFFFFF, []byte{0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
-	{0xFFFFFFFFFFFF, []byte{0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
-	{0xFFFFFFFFFFFFFF, []byte{0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
-	{0xFFFFFFFFFFFFFFFF, []byte{0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
-	{0x1111, []byte{0xFE, 0x11, 0x11}},
-	{0x1111111111111111, []byte{0xF8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
-	{0x8888888888888888, []byte{0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}},
-	{1 << 63, []byte{0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
-}
-
-// testError is meant to be used as a deferred function to turn a panic(gobError) into a
-// plain test.Error call.
-func testError(t *testing.T) {
-	if e := recover(); e != nil {
-		t.Error(e.(gobError).Error) // Will re-panic if not one of our errors, such as a runtime error.
-	}
-	return
-}
-
-// Test basic encode/decode routines for unsigned integers
-func TestUintCodec(t *testing.T) {
-	defer testError(t)
-	b := new(bytes.Buffer)
-	encState := newEncoderState(b)
-	for _, tt := range encodeT {
-		b.Reset()
-		encState.encodeUint(tt.x)
-		if !bytes.Equal(tt.b, b.Bytes()) {
-			t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes())
-		}
-	}
-	decState := newDecodeState(b)
-	for u := uint64(0); ; u = (u + 1) * 7 {
-		b.Reset()
-		encState.encodeUint(u)
-		v := decState.decodeUint()
-		if u != v {
-			t.Errorf("Encode/Decode: sent %#x received %#x", u, v)
-		}
-		if u&(1<<63) != 0 {
-			break
-		}
-	}
-}
-
-func verifyInt(i int64, t *testing.T) {
-	defer testError(t)
-	var b = new(bytes.Buffer)
-	encState := newEncoderState(b)
-	encState.encodeInt(i)
-	decState := newDecodeState(b)
-	decState.buf = make([]byte, 8)
-	j := decState.decodeInt()
-	if i != j {
-		t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j))
-	}
-}
-
-// Test basic encode/decode routines for signed integers
-func TestIntCodec(t *testing.T) {
-	for u := uint64(0); ; u = (u + 1) * 7 {
-		// Do positive and negative values
-		i := int64(u)
-		verifyInt(i, t)
-		verifyInt(-i, t)
-		verifyInt(^i, t)
-		if u&(1<<63) != 0 {
-			break
-		}
-	}
-	verifyInt(-1<<63, t) // a tricky case
-}
-
-// The result of encoding a true boolean with field number 7
-var boolResult = []byte{0x07, 0x01}
-// The result of encoding a number 17 with field number 7
-var signedResult = []byte{0x07, 2 * 17}
-var unsignedResult = []byte{0x07, 17}
-var floatResult = []byte{0x07, 0xFE, 0x31, 0x40}
-// The result of encoding a number 17+19i with field number 7
-var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40}
-// The result of encoding "hello" with field number 7
-var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
-
-func newDecodeState(buf *bytes.Buffer) *decoderState {
-	d := new(decoderState)
-	d.b = buf
-	d.buf = make([]byte, uint64Size)
-	return d
-}
-
-func newEncoderState(b *bytes.Buffer) *encoderState {
-	b.Reset()
-	state := &encoderState{enc: nil, b: b}
-	state.fieldnum = -1
-	return state
-}
-
-// Test instruction execution for encoding.
-// Do not run the machine yet; instead do individual instructions crafted by hand.
-func TestScalarEncInstructions(t *testing.T) {
-	var b = new(bytes.Buffer)
-
-	// bool
-	{
-		data := struct{ a bool }{true}
-		instr := &encInstr{encBool, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(boolResult, b.Bytes()) {
-			t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes())
-		}
-	}
-
-	// int
-	{
-		b.Reset()
-		data := struct{ a int }{17}
-		instr := &encInstr{encInt, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(signedResult, b.Bytes()) {
-			t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes())
-		}
-	}
-
-	// uint
-	{
-		b.Reset()
-		data := struct{ a uint }{17}
-		instr := &encInstr{encUint, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(unsignedResult, b.Bytes()) {
-			t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes())
-		}
-	}
-
-	// int8
-	{
-		b.Reset()
-		data := struct{ a int8 }{17}
-		instr := &encInstr{encInt8, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(signedResult, b.Bytes()) {
-			t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes())
-		}
-	}
-
-	// uint8
-	{
-		b.Reset()
-		data := struct{ a uint8 }{17}
-		instr := &encInstr{encUint8, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(unsignedResult, b.Bytes()) {
-			t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
-		}
-	}
-
-	// int16
-	{
-		b.Reset()
-		data := struct{ a int16 }{17}
-		instr := &encInstr{encInt16, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(signedResult, b.Bytes()) {
-			t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes())
-		}
-	}
-
-	// uint16
-	{
-		b.Reset()
-		data := struct{ a uint16 }{17}
-		instr := &encInstr{encUint16, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(unsignedResult, b.Bytes()) {
-			t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
-		}
-	}
-
-	// int32
-	{
-		b.Reset()
-		data := struct{ a int32 }{17}
-		instr := &encInstr{encInt32, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(signedResult, b.Bytes()) {
-			t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes())
-		}
-	}
-
-	// uint32
-	{
-		b.Reset()
-		data := struct{ a uint32 }{17}
-		instr := &encInstr{encUint32, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(unsignedResult, b.Bytes()) {
-			t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
-		}
-	}
-
-	// int64
-	{
-		b.Reset()
-		data := struct{ a int64 }{17}
-		instr := &encInstr{encInt64, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(signedResult, b.Bytes()) {
-			t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes())
-		}
-	}
-
-	// uint64
-	{
-		b.Reset()
-		data := struct{ a uint64 }{17}
-		instr := &encInstr{encUint64, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(unsignedResult, b.Bytes()) {
-			t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
-		}
-	}
-
-	// float32
-	{
-		b.Reset()
-		data := struct{ a float32 }{17}
-		instr := &encInstr{encFloat32, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(floatResult, b.Bytes()) {
-			t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes())
-		}
-	}
-
-	// float64
-	{
-		b.Reset()
-		data := struct{ a float64 }{17}
-		instr := &encInstr{encFloat64, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(floatResult, b.Bytes()) {
-			t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes())
-		}
-	}
-
-	// bytes == []uint8
-	{
-		b.Reset()
-		data := struct{ a []byte }{[]byte("hello")}
-		instr := &encInstr{encUint8Array, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(bytesResult, b.Bytes()) {
-			t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes())
-		}
-	}
-
-	// string
-	{
-		b.Reset()
-		data := struct{ a string }{"hello"}
-		instr := &encInstr{encString, 6, 0, 0}
-		state := newEncoderState(b)
-		instr.op(instr, state, unsafe.Pointer(&data))
-		if !bytes.Equal(bytesResult, b.Bytes()) {
-			t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes())
-		}
-	}
-}
-
-func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, p unsafe.Pointer) {
-	defer testError(t)
-	v := int(state.decodeUint())
-	if v+state.fieldnum != 6 {
-		t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum)
-	}
-	instr.op(instr, state, decIndirect(p, instr.indir))
-	state.fieldnum = 6
-}
-
-func newDecodeStateFromData(data []byte) *decoderState {
-	b := bytes.NewBuffer(data)
-	state := newDecodeState(b)
-	state.fieldnum = -1
-	return state
-}
-
-// Test instruction execution for decoding.
-// Do not run the machine yet; instead do individual instructions crafted by hand.
-func TestScalarDecInstructions(t *testing.T) {
-	ovfl := os.NewError("overflow")
-
-	// bool
-	{
-		var data struct {
-			a bool
-		}
-		instr := &decInstr{decBool, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(boolResult)
-		execDec("bool", instr, state, t, unsafe.Pointer(&data))
-		if data.a != true {
-			t.Errorf("bool a = %v not true", data.a)
-		}
-	}
-	// int
-	{
-		var data struct {
-			a int
-		}
-		instr := &decInstr{decOpTable[reflect.Int], 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(signedResult)
-		execDec("int", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("int a = %v not 17", data.a)
-		}
-	}
-
-	// uint
-	{
-		var data struct {
-			a uint
-		}
-		instr := &decInstr{decOpTable[reflect.Uint], 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(unsignedResult)
-		execDec("uint", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("uint a = %v not 17", data.a)
-		}
-	}
-
-	// int8
-	{
-		var data struct {
-			a int8
-		}
-		instr := &decInstr{decInt8, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(signedResult)
-		execDec("int8", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("int8 a = %v not 17", data.a)
-		}
-	}
-
-	// uint8
-	{
-		var data struct {
-			a uint8
-		}
-		instr := &decInstr{decUint8, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(unsignedResult)
-		execDec("uint8", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("uint8 a = %v not 17", data.a)
-		}
-	}
-
-	// int16
-	{
-		var data struct {
-			a int16
-		}
-		instr := &decInstr{decInt16, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(signedResult)
-		execDec("int16", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("int16 a = %v not 17", data.a)
-		}
-	}
-
-	// uint16
-	{
-		var data struct {
-			a uint16
-		}
-		instr := &decInstr{decUint16, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(unsignedResult)
-		execDec("uint16", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("uint16 a = %v not 17", data.a)
-		}
-	}
-
-	// int32
-	{
-		var data struct {
-			a int32
-		}
-		instr := &decInstr{decInt32, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(signedResult)
-		execDec("int32", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("int32 a = %v not 17", data.a)
-		}
-	}
-
-	// uint32
-	{
-		var data struct {
-			a uint32
-		}
-		instr := &decInstr{decUint32, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(unsignedResult)
-		execDec("uint32", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("uint32 a = %v not 17", data.a)
-		}
-	}
-
-	// uintptr
-	{
-		var data struct {
-			a uintptr
-		}
-		instr := &decInstr{decOpTable[reflect.Uintptr], 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(unsignedResult)
-		execDec("uintptr", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("uintptr a = %v not 17", data.a)
-		}
-	}
-
-	// int64
-	{
-		var data struct {
-			a int64
-		}
-		instr := &decInstr{decInt64, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(signedResult)
-		execDec("int64", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("int64 a = %v not 17", data.a)
-		}
-	}
-
-	// uint64
-	{
-		var data struct {
-			a uint64
-		}
-		instr := &decInstr{decUint64, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(unsignedResult)
-		execDec("uint64", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("uint64 a = %v not 17", data.a)
-		}
-	}
-
-	// float32
-	{
-		var data struct {
-			a float32
-		}
-		instr := &decInstr{decFloat32, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(floatResult)
-		execDec("float32", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("float32 a = %v not 17", data.a)
-		}
-	}
-
-	// float64
-	{
-		var data struct {
-			a float64
-		}
-		instr := &decInstr{decFloat64, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(floatResult)
-		execDec("float64", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17 {
-			t.Errorf("float64 a = %v not 17", data.a)
-		}
-	}
-
-	// complex64
-	{
-		var data struct {
-			a complex64
-		}
-		instr := &decInstr{decOpTable[reflect.Complex64], 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(complexResult)
-		execDec("complex", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17+19i {
-			t.Errorf("complex a = %v not 17+19i", data.a)
-		}
-	}
-
-	// complex128
-	{
-		var data struct {
-			a complex128
-		}
-		instr := &decInstr{decOpTable[reflect.Complex128], 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(complexResult)
-		execDec("complex", instr, state, t, unsafe.Pointer(&data))
-		if data.a != 17+19i {
-			t.Errorf("complex a = %v not 17+19i", data.a)
-		}
-	}
-
-	// bytes == []uint8
-	{
-		var data struct {
-			a []byte
-		}
-		instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(bytesResult)
-		execDec("bytes", instr, state, t, unsafe.Pointer(&data))
-		if string(data.a) != "hello" {
-			t.Errorf(`bytes a = %q not "hello"`, string(data.a))
-		}
-	}
-
-	// string
-	{
-		var data struct {
-			a string
-		}
-		instr := &decInstr{decString, 6, 0, 0, ovfl}
-		state := newDecodeStateFromData(bytesResult)
-		execDec("bytes", instr, state, t, unsafe.Pointer(&data))
-		if data.a != "hello" {
-			t.Errorf(`bytes a = %q not "hello"`, data.a)
-		}
-	}
-}
-
-func TestEndToEnd(t *testing.T) {
-	type T2 struct {
-		T string
-	}
-	s1 := "string1"
-	s2 := "string2"
-	type T1 struct {
-		A, B, C  int
-		M        map[string]*float64
-		EmptyMap map[string]int // to check that we receive a non-nil map.
-		N        *[3]float64
-		Strs     *[2]string
-		Int64s   *[]int64
-		RI       complex64
-		S        string
-		Y        []byte
-		T        *T2
-	}
-	pi := 3.14159
-	e := 2.71828
-	t1 := &T1{
-		A:        17,
-		B:        18,
-		C:        -5,
-		M:        map[string]*float64{"pi": &pi, "e": &e},
-		EmptyMap: make(map[string]int),
-		N:        &[3]float64{1.5, 2.5, 3.5},
-		Strs:     &[2]string{s1, s2},
-		Int64s:   &[]int64{77, 89, 123412342134},
-		RI:       17 - 23i,
-		S:        "Now is the time",
-		Y:        []byte("hello, sailor"),
-		T:        &T2{"this is T2"},
-	}
-	b := new(bytes.Buffer)
-	err := NewEncoder(b).Encode(t1)
-	if err != nil {
-		t.Error("encode:", err)
-	}
-	var _t1 T1
-	err = NewDecoder(b).Decode(&_t1)
-	if err != nil {
-		t.Fatal("decode:", err)
-	}
-	if !reflect.DeepEqual(t1, &_t1) {
-		t.Errorf("encode expected %v got %v", *t1, _t1)
-	}
-	// Be absolutely sure the received map is non-nil.
-	if t1.EmptyMap == nil {
-		t.Errorf("nil map sent")
-	}
-	if _t1.EmptyMap == nil {
-		t.Errorf("nil map received")
-	}
-}
-
-func TestOverflow(t *testing.T) {
-	type inputT struct {
-		Maxi int64
-		Mini int64
-		Maxu uint64
-		Maxf float64
-		Minf float64
-		Maxc complex128
-		Minc complex128
-	}
-	var it inputT
-	var err os.Error
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	dec := NewDecoder(b)
-
-	// int8
-	b.Reset()
-	it = inputT{
-		Maxi: math.MaxInt8 + 1,
-	}
-	type outi8 struct {
-		Maxi int8
-		Mini int8
-	}
-	var o1 outi8
-	enc.Encode(it)
-	err = dec.Decode(&o1)
-	if err == nil || err.String() != `value for "Maxi" out of range` {
-		t.Error("wrong overflow error for int8:", err)
-	}
-	it = inputT{
-		Mini: math.MinInt8 - 1,
-	}
-	b.Reset()
-	enc.Encode(it)
-	err = dec.Decode(&o1)
-	if err == nil || err.String() != `value for "Mini" out of range` {
-		t.Error("wrong underflow error for int8:", err)
-	}
-
-	// int16
-	b.Reset()
-	it = inputT{
-		Maxi: math.MaxInt16 + 1,
-	}
-	type outi16 struct {
-		Maxi int16
-		Mini int16
-	}
-	var o2 outi16
-	enc.Encode(it)
-	err = dec.Decode(&o2)
-	if err == nil || err.String() != `value for "Maxi" out of range` {
-		t.Error("wrong overflow error for int16:", err)
-	}
-	it = inputT{
-		Mini: math.MinInt16 - 1,
-	}
-	b.Reset()
-	enc.Encode(it)
-	err = dec.Decode(&o2)
-	if err == nil || err.String() != `value for "Mini" out of range` {
-		t.Error("wrong underflow error for int16:", err)
-	}
-
-	// int32
-	b.Reset()
-	it = inputT{
-		Maxi: math.MaxInt32 + 1,
-	}
-	type outi32 struct {
-		Maxi int32
-		Mini int32
-	}
-	var o3 outi32
-	enc.Encode(it)
-	err = dec.Decode(&o3)
-	if err == nil || err.String() != `value for "Maxi" out of range` {
-		t.Error("wrong overflow error for int32:", err)
-	}
-	it = inputT{
-		Mini: math.MinInt32 - 1,
-	}
-	b.Reset()
-	enc.Encode(it)
-	err = dec.Decode(&o3)
-	if err == nil || err.String() != `value for "Mini" out of range` {
-		t.Error("wrong underflow error for int32:", err)
-	}
-
-	// uint8
-	b.Reset()
-	it = inputT{
-		Maxu: math.MaxUint8 + 1,
-	}
-	type outu8 struct {
-		Maxu uint8
-	}
-	var o4 outu8
-	enc.Encode(it)
-	err = dec.Decode(&o4)
-	if err == nil || err.String() != `value for "Maxu" out of range` {
-		t.Error("wrong overflow error for uint8:", err)
-	}
-
-	// uint16
-	b.Reset()
-	it = inputT{
-		Maxu: math.MaxUint16 + 1,
-	}
-	type outu16 struct {
-		Maxu uint16
-	}
-	var o5 outu16
-	enc.Encode(it)
-	err = dec.Decode(&o5)
-	if err == nil || err.String() != `value for "Maxu" out of range` {
-		t.Error("wrong overflow error for uint16:", err)
-	}
-
-	// uint32
-	b.Reset()
-	it = inputT{
-		Maxu: math.MaxUint32 + 1,
-	}
-	type outu32 struct {
-		Maxu uint32
-	}
-	var o6 outu32
-	enc.Encode(it)
-	err = dec.Decode(&o6)
-	if err == nil || err.String() != `value for "Maxu" out of range` {
-		t.Error("wrong overflow error for uint32:", err)
-	}
-
-	// float32
-	b.Reset()
-	it = inputT{
-		Maxf: math.MaxFloat32 * 2,
-	}
-	type outf32 struct {
-		Maxf float32
-		Minf float32
-	}
-	var o7 outf32
-	enc.Encode(it)
-	err = dec.Decode(&o7)
-	if err == nil || err.String() != `value for "Maxf" out of range` {
-		t.Error("wrong overflow error for float32:", err)
-	}
-
-	// complex64
-	b.Reset()
-	it = inputT{
-		Maxc: complex(math.MaxFloat32*2, math.MaxFloat32*2),
-	}
-	type outc64 struct {
-		Maxc complex64
-		Minc complex64
-	}
-	var o8 outc64
-	enc.Encode(it)
-	err = dec.Decode(&o8)
-	if err == nil || err.String() != `value for "Maxc" out of range` {
-		t.Error("wrong overflow error for complex64:", err)
-	}
-}
-
-func TestNesting(t *testing.T) {
-	type RT struct {
-		A    string
-		Next *RT
-	}
-	rt := new(RT)
-	rt.A = "level1"
-	rt.Next = new(RT)
-	rt.Next.A = "level2"
-	b := new(bytes.Buffer)
-	NewEncoder(b).Encode(rt)
-	var drt RT
-	dec := NewDecoder(b)
-	err := dec.Decode(&drt)
-	if err != nil {
-		t.Fatal("decoder error:", err)
-	}
-	if drt.A != rt.A {
-		t.Errorf("nesting: encode expected %v got %v", *rt, drt)
-	}
-	if drt.Next == nil {
-		t.Errorf("nesting: recursion failed")
-	}
-	if drt.Next.A != rt.Next.A {
-		t.Errorf("nesting: encode expected %v got %v", *rt.Next, *drt.Next)
-	}
-}
-
-// These three structures have the same data with different indirections
-type T0 struct {
-	A int
-	B int
-	C int
-	D int
-}
-type T1 struct {
-	A int
-	B *int
-	C **int
-	D ***int
-}
-type T2 struct {
-	A ***int
-	B **int
-	C *int
-	D int
-}
-
-func TestAutoIndirection(t *testing.T) {
-	// First transfer t1 into t0
-	var t1 T1
-	t1.A = 17
-	t1.B = new(int)
-	*t1.B = 177
-	t1.C = new(*int)
-	*t1.C = new(int)
-	**t1.C = 1777
-	t1.D = new(**int)
-	*t1.D = new(*int)
-	**t1.D = new(int)
-	***t1.D = 17777
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	enc.Encode(t1)
-	dec := NewDecoder(b)
-	var t0 T0
-	dec.Decode(&t0)
-	if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
-		t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0)
-	}
-
-	// Now transfer t2 into t0
-	var t2 T2
-	t2.D = 17777
-	t2.C = new(int)
-	*t2.C = 1777
-	t2.B = new(*int)
-	*t2.B = new(int)
-	**t2.B = 177
-	t2.A = new(**int)
-	*t2.A = new(*int)
-	**t2.A = new(int)
-	***t2.A = 17
-	b.Reset()
-	enc.Encode(t2)
-	t0 = T0{}
-	dec.Decode(&t0)
-	if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
-		t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0)
-	}
-
-	// Now transfer t0 into t1
-	t0 = T0{17, 177, 1777, 17777}
-	b.Reset()
-	enc.Encode(t0)
-	t1 = T1{}
-	dec.Decode(&t1)
-	if t1.A != 17 || *t1.B != 177 || **t1.C != 1777 || ***t1.D != 17777 {
-		t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.A, *t1.B, **t1.C, ***t1.D)
-	}
-
-	// Now transfer t0 into t2
-	b.Reset()
-	enc.Encode(t0)
-	t2 = T2{}
-	dec.Decode(&t2)
-	if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
-		t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
-	}
-
-	// Now do t2 again but without pre-allocated pointers.
-	b.Reset()
-	enc.Encode(t0)
-	***t2.A = 0
-	**t2.B = 0
-	*t2.C = 0
-	t2.D = 0
-	dec.Decode(&t2)
-	if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
-		t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
-	}
-}
-
-type RT0 struct {
-	A int
-	B string
-	C float64
-}
-type RT1 struct {
-	C      float64
-	B      string
-	A      int
-	NotSet string
-}
-
-func TestReorderedFields(t *testing.T) {
-	var rt0 RT0
-	rt0.A = 17
-	rt0.B = "hello"
-	rt0.C = 3.14159
-	b := new(bytes.Buffer)
-	NewEncoder(b).Encode(rt0)
-	dec := NewDecoder(b)
-	var rt1 RT1
-	// Wire type is RT0, local type is RT1.
-	err := dec.Decode(&rt1)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if rt0.A != rt1.A || rt0.B != rt1.B || rt0.C != rt1.C {
-		t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1)
-	}
-}
-
-// Like an RT0 but with fields we'll ignore on the decode side.
-type IT0 struct {
-	A        int64
-	B        string
-	Ignore_d []int
-	Ignore_e [3]float64
-	Ignore_f bool
-	Ignore_g string
-	Ignore_h []byte
-	Ignore_i *RT1
-	Ignore_m map[string]int
-	C        float64
-}
-
-func TestIgnoredFields(t *testing.T) {
-	var it0 IT0
-	it0.A = 17
-	it0.B = "hello"
-	it0.C = 3.14159
-	it0.Ignore_d = []int{1, 2, 3}
-	it0.Ignore_e[0] = 1.0
-	it0.Ignore_e[1] = 2.0
-	it0.Ignore_e[2] = 3.0
-	it0.Ignore_f = true
-	it0.Ignore_g = "pay no attention"
-	it0.Ignore_h = []byte("to the curtain")
-	it0.Ignore_i = &RT1{3.1, "hi", 7, "hello"}
-	it0.Ignore_m = map[string]int{"one": 1, "two": 2}
-
-	b := new(bytes.Buffer)
-	NewEncoder(b).Encode(it0)
-	dec := NewDecoder(b)
-	var rt1 RT1
-	// Wire type is IT0, local type is RT1.
-	err := dec.Decode(&rt1)
-	if err != nil {
-		t.Error("error: ", err)
-	}
-	if int(it0.A) != rt1.A || it0.B != rt1.B || it0.C != rt1.C {
-		t.Errorf("rt0->rt1: expected %v; got %v", it0, rt1)
-	}
-}
-
-func TestBadRecursiveType(t *testing.T) {
-	type Rec ***Rec
-	var rec Rec
-	b := new(bytes.Buffer)
-	err := NewEncoder(b).Encode(&rec)
-	if err == nil {
-		t.Error("expected error; got none")
-	} else if strings.Index(err.String(), "recursive") < 0 {
-		t.Error("expected recursive type error; got", err)
-	}
-	// Can't test decode easily because we can't encode one, so we can't pass one to a Decoder.
-}
-
-type Bad0 struct {
-	CH chan int
-	C  float64
-}
-
-func TestInvalidField(t *testing.T) {
-	var bad0 Bad0
-	bad0.CH = make(chan int)
-	b := new(bytes.Buffer)
-	dummyEncoder := new(Encoder) // sufficient for this purpose.
-	dummyEncoder.encode(b, reflect.ValueOf(&bad0), userType(reflect.TypeOf(&bad0)))
-	if err := dummyEncoder.err; err == nil {
-		t.Error("expected error; got none")
-	} else if strings.Index(err.String(), "type") < 0 {
-		t.Error("expected type error; got", err)
-	}
-}
-
-type Indirect struct {
-	A ***[3]int
-	S ***[]int
-	M ****map[string]int
-}
-
-type Direct struct {
-	A [3]int
-	S []int
-	M map[string]int
-}
-
-func TestIndirectSliceMapArray(t *testing.T) {
-	// Marshal indirect, unmarshal to direct.
-	i := new(Indirect)
-	i.A = new(**[3]int)
-	*i.A = new(*[3]int)
-	**i.A = new([3]int)
-	***i.A = [3]int{1, 2, 3}
-	i.S = new(**[]int)
-	*i.S = new(*[]int)
-	**i.S = new([]int)
-	***i.S = []int{4, 5, 6}
-	i.M = new(***map[string]int)
-	*i.M = new(**map[string]int)
-	**i.M = new(*map[string]int)
-	***i.M = new(map[string]int)
-	****i.M = map[string]int{"one": 1, "two": 2, "three": 3}
-	b := new(bytes.Buffer)
-	NewEncoder(b).Encode(i)
-	dec := NewDecoder(b)
-	var d Direct
-	err := dec.Decode(&d)
-	if err != nil {
-		t.Error("error: ", err)
-	}
-	if len(d.A) != 3 || d.A[0] != 1 || d.A[1] != 2 || d.A[2] != 3 {
-		t.Errorf("indirect to direct: d.A is %v not %v", d.A, ***i.A)
-	}
-	if len(d.S) != 3 || d.S[0] != 4 || d.S[1] != 5 || d.S[2] != 6 {
-		t.Errorf("indirect to direct: d.S is %v not %v", d.S, ***i.S)
-	}
-	if len(d.M) != 3 || d.M["one"] != 1 || d.M["two"] != 2 || d.M["three"] != 3 {
-		t.Errorf("indirect to direct: d.M is %v not %v", d.M, ***i.M)
-	}
-	// Marshal direct, unmarshal to indirect.
-	d.A = [3]int{11, 22, 33}
-	d.S = []int{44, 55, 66}
-	d.M = map[string]int{"four": 4, "five": 5, "six": 6}
-	i = new(Indirect)
-	b.Reset()
-	NewEncoder(b).Encode(d)
-	dec = NewDecoder(b)
-	err = dec.Decode(&i)
-	if err != nil {
-		t.Fatal("error: ", err)
-	}
-	if len(***i.A) != 3 || (***i.A)[0] != 11 || (***i.A)[1] != 22 || (***i.A)[2] != 33 {
-		t.Errorf("direct to indirect: ***i.A is %v not %v", ***i.A, d.A)
-	}
-	if len(***i.S) != 3 || (***i.S)[0] != 44 || (***i.S)[1] != 55 || (***i.S)[2] != 66 {
-		t.Errorf("direct to indirect: ***i.S is %v not %v", ***i.S, ***i.S)
-	}
-	if len(****i.M) != 3 || (****i.M)["four"] != 4 || (****i.M)["five"] != 5 || (****i.M)["six"] != 6 {
-		t.Errorf("direct to indirect: ****i.M is %v not %v", ****i.M, d.M)
-	}
-}
-
-// An interface with several implementations
-type Squarer interface {
-	Square() int
-}
-
-type Int int
-
-func (i Int) Square() int {
-	return int(i * i)
-}
-
-type Float float64
-
-func (f Float) Square() int {
-	return int(f * f)
-}
-
-type Vector []int
-
-func (v Vector) Square() int {
-	sum := 0
-	for _, x := range v {
-		sum += x * x
-	}
-	return sum
-}
-
-type Point struct {
-	X, Y int
-}
-
-func (p Point) Square() int {
-	return p.X*p.X + p.Y*p.Y
-}
-
-// A struct with interfaces in it.
-type InterfaceItem struct {
-	I             int
-	Sq1, Sq2, Sq3 Squarer
-	F             float64
-	Sq            []Squarer
-}
-
-// The same struct without interfaces
-type NoInterfaceItem struct {
-	I int
-	F float64
-}
-
-func TestInterface(t *testing.T) {
-	iVal := Int(3)
-	fVal := Float(5)
-	// Sending a Vector will require that the receiver define a type in the middle of
-	// receiving the value for item2.
-	vVal := Vector{1, 2, 3}
-	b := new(bytes.Buffer)
-	item1 := &InterfaceItem{1, iVal, fVal, vVal, 11.5, []Squarer{iVal, fVal, nil, vVal}}
-	// Register the types.
-	Register(Int(0))
-	Register(Float(0))
-	Register(Vector{})
-	err := NewEncoder(b).Encode(item1)
-	if err != nil {
-		t.Error("expected no encode error; got", err)
-	}
-
-	item2 := InterfaceItem{}
-	err = NewDecoder(b).Decode(&item2)
-	if err != nil {
-		t.Fatal("decode:", err)
-	}
-	if item2.I != item1.I {
-		t.Error("normal int did not decode correctly")
-	}
-	if item2.Sq1 == nil || item2.Sq1.Square() != iVal.Square() {
-		t.Error("Int did not decode correctly")
-	}
-	if item2.Sq2 == nil || item2.Sq2.Square() != fVal.Square() {
-		t.Error("Float did not decode correctly")
-	}
-	if item2.Sq3 == nil || item2.Sq3.Square() != vVal.Square() {
-		t.Error("Vector did not decode correctly")
-	}
-	if item2.F != item1.F {
-		t.Error("normal float did not decode correctly")
-	}
-	// Now check that we received a slice of Squarers correctly, including a nil element
-	if len(item1.Sq) != len(item2.Sq) {
-		t.Fatalf("[]Squarer length wrong: got %d; expected %d", len(item2.Sq), len(item1.Sq))
-	}
-	for i, v1 := range item1.Sq {
-		v2 := item2.Sq[i]
-		if v1 == nil || v2 == nil {
-			if v1 != nil || v2 != nil {
-				t.Errorf("item %d inconsistent nils", i)
-			}
-			continue
-			if v1.Square() != v2.Square() {
-				t.Errorf("item %d inconsistent values: %v %v", i, v1, v2)
-			}
-		}
-	}
-}
-
-// A struct with all basic types, stored in interfaces.
-type BasicInterfaceItem struct {
-	Int, Int8, Int16, Int32, Int64      interface{}
-	Uint, Uint8, Uint16, Uint32, Uint64 interface{}
-	Float32, Float64                    interface{}
-	Complex64, Complex128               interface{}
-	Bool                                interface{}
-	String                              interface{}
-	Bytes                               interface{}
-}
-
-func TestInterfaceBasic(t *testing.T) {
-	b := new(bytes.Buffer)
-	item1 := &BasicInterfaceItem{
-		int(1), int8(1), int16(1), int32(1), int64(1),
-		uint(1), uint8(1), uint16(1), uint32(1), uint64(1),
-		float32(1), 1.0,
-		complex64(1i), complex128(1i),
-		true,
-		"hello",
-		[]byte("sailor"),
-	}
-	err := NewEncoder(b).Encode(item1)
-	if err != nil {
-		t.Error("expected no encode error; got", err)
-	}
-
-	item2 := &BasicInterfaceItem{}
-	err = NewDecoder(b).Decode(&item2)
-	if err != nil {
-		t.Fatal("decode:", err)
-	}
-	if !reflect.DeepEqual(item1, item2) {
-		t.Errorf("encode expected %v got %v", item1, item2)
-	}
-	// Hand check a couple for correct types.
-	if v, ok := item2.Bool.(bool); !ok || !v {
-		t.Error("boolean should be true")
-	}
-	if v, ok := item2.String.(string); !ok || v != item1.String.(string) {
-		t.Errorf("string should be %v is %v", item1.String, v)
-	}
-}
-
-type String string
-
-type PtrInterfaceItem struct {
-	Str1 interface{} // basic
-	Str2 interface{} // derived
-}
-
-// We'll send pointers; should receive values.
-// Also check that we can register T but send *T.
-func TestInterfacePointer(t *testing.T) {
-	b := new(bytes.Buffer)
-	str1 := "howdy"
-	str2 := String("kiddo")
-	item1 := &PtrInterfaceItem{
-		&str1,
-		&str2,
-	}
-	// Register the type.
-	Register(str2)
-	err := NewEncoder(b).Encode(item1)
-	if err != nil {
-		t.Error("expected no encode error; got", err)
-	}
-
-	item2 := &PtrInterfaceItem{}
-	err = NewDecoder(b).Decode(&item2)
-	if err != nil {
-		t.Fatal("decode:", err)
-	}
-	// Hand test for correct types and values.
-	if v, ok := item2.Str1.(string); !ok || v != str1 {
-		t.Errorf("basic string failed: %q should be %q", v, str1)
-	}
-	if v, ok := item2.Str2.(String); !ok || v != str2 {
-		t.Errorf("derived type String failed: %q should be %q", v, str2)
-	}
-}
-
-func TestIgnoreInterface(t *testing.T) {
-	iVal := Int(3)
-	fVal := Float(5)
-	// Sending a Point will require that the receiver define a type in the middle of
-	// receiving the value for item2.
-	pVal := Point{2, 3}
-	b := new(bytes.Buffer)
-	item1 := &InterfaceItem{1, iVal, fVal, pVal, 11.5, nil}
-	// Register the types.
-	Register(Int(0))
-	Register(Float(0))
-	Register(Point{})
-	err := NewEncoder(b).Encode(item1)
-	if err != nil {
-		t.Error("expected no encode error; got", err)
-	}
-
-	item2 := NoInterfaceItem{}
-	err = NewDecoder(b).Decode(&item2)
-	if err != nil {
-		t.Fatal("decode:", err)
-	}
-	if item2.I != item1.I {
-		t.Error("normal int did not decode correctly")
-	}
-	if item2.F != item2.F {
-		t.Error("normal float did not decode correctly")
-	}
-}
-
-type U struct {
-	A int
-	B string
-	c float64
-	D uint
-}
-
-func TestUnexportedFields(t *testing.T) {
-	var u0 U
-	u0.A = 17
-	u0.B = "hello"
-	u0.c = 3.14159
-	u0.D = 23
-	b := new(bytes.Buffer)
-	NewEncoder(b).Encode(u0)
-	dec := NewDecoder(b)
-	var u1 U
-	u1.c = 1234.
-	err := dec.Decode(&u1)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D {
-		t.Errorf("u1->u0: expected %v; got %v", u0, u1)
-	}
-	if u1.c != 1234. {
-		t.Error("u1.c modified")
-	}
-}
-
-var singletons = []interface{}{
-	true,
-	7,
-	3.2,
-	"hello",
-	[3]int{11, 22, 33},
-	[]float32{0.5, 0.25, 0.125},
-	map[string]int{"one": 1, "two": 2},
-}
-
-func TestDebugSingleton(t *testing.T) {
-	if debugFunc == nil {
-		return
-	}
-	b := new(bytes.Buffer)
-	// Accumulate a number of values and print them out all at once.
-	for _, x := range singletons {
-		err := NewEncoder(b).Encode(x)
-		if err != nil {
-			t.Fatal("encode:", err)
-		}
-	}
-	debugFunc(b)
-}
-
-// A type that won't be defined in the gob until we send it in an interface value.
-type OnTheFly struct {
-	A int
-}
-
-type DT struct {
-	//	X OnTheFly
-	A     int
-	B     string
-	C     float64
-	I     interface{}
-	J     interface{}
-	I_nil interface{}
-	M     map[string]int
-	T     [3]int
-	S     []string
-}
-
-func TestDebugStruct(t *testing.T) {
-	if debugFunc == nil {
-		return
-	}
-	Register(OnTheFly{})
-	var dt DT
-	dt.A = 17
-	dt.B = "hello"
-	dt.C = 3.14159
-	dt.I = 271828
-	dt.J = OnTheFly{3}
-	dt.I_nil = nil
-	dt.M = map[string]int{"one": 1, "two": 2}
-	dt.T = [3]int{11, 22, 33}
-	dt.S = []string{"hi", "joe"}
-	b := new(bytes.Buffer)
-	err := NewEncoder(b).Encode(dt)
-	if err != nil {
-		t.Fatal("encode:", err)
-	}
-	debugBuffer := bytes.NewBuffer(b.Bytes())
-	dt2 := &DT{}
-	err = NewDecoder(b).Decode(&dt2)
-	if err != nil {
-		t.Error("decode:", err)
-	}
-	debugFunc(debugBuffer)
-}
diff --git a/src/pkg/gob/debug.go b/src/pkg/gob/debug.go
deleted file mode 100644
index 16c2194..0000000
--- a/src/pkg/gob/debug.go
+++ /dev/null
@@ -1,687 +0,0 @@
-package gob
-
-// This file is not normally included in the gob package.  Used only for debugging the package itself.
-// Add debug.go to the files listed in the Makefile to add Debug to the gob package.
-// Except for reading uints, it is an implementation of a reader that is independent of
-// the one implemented by Decoder.
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"strings"
-	"sync"
-)
-
-var dumpBytes = false // If true, print the remaining bytes in the input buffer at each item.
-
-// Init installs the debugging facility. If this file is not compiled in the
-// package, the tests in codec_test.go are no-ops.
-func init() {
-	debugFunc = Debug
-}
-
-var (
-	blanks = bytes.Repeat([]byte{' '}, 3*10)
-	empty  = []byte(": <empty>\n")
-	tabs   = strings.Repeat("\t", 100)
-)
-
-// tab indents itself when printed.
-type tab int
-
-func (t tab) String() string {
-	n := int(t)
-	if n > len(tabs) {
-		n = len(tabs)
-	}
-	return tabs[0:n]
-}
-
-func (t tab) print() {
-	fmt.Fprint(os.Stderr, t)
-}
-
-// A peekReader wraps an io.Reader, allowing one to peek ahead to see
-// what's coming without stealing the data from the client of the Reader.
-type peekReader struct {
-	r    io.Reader
-	data []byte // read-ahead data
-}
-
-// newPeekReader returns a peekReader that wraps r.
-func newPeekReader(r io.Reader) *peekReader {
-	return &peekReader{r: r}
-}
-
-// Read is the usual method. It will first take data that has been read ahead.
-func (p *peekReader) Read(b []byte) (n int, err os.Error) {
-	if len(p.data) == 0 {
-		return p.r.Read(b)
-	}
-	// Satisfy what's possible from the read-ahead data.
-	n = copy(b, p.data)
-	// Move data down to beginning of slice, to avoid endless growth
-	copy(p.data, p.data[n:])
-	p.data = p.data[:len(p.data)-n]
-	return
-}
-
-// peek returns as many bytes as possible from the unread
-// portion of the stream, up to the length of b.
-func (p *peekReader) peek(b []byte) (n int, err os.Error) {
-	if len(p.data) > 0 {
-		n = copy(b, p.data)
-		if n == len(b) {
-			return
-		}
-		b = b[n:]
-	}
-	if len(b) == 0 {
-		return
-	}
-	m, e := io.ReadFull(p.r, b)
-	if m > 0 {
-		p.data = append(p.data, b[:m]...)
-	}
-	n += m
-	if e == io.ErrUnexpectedEOF {
-		// That means m > 0 but we reached EOF. If we got data
-		// we won't complain about not being able to peek enough.
-		if n > 0 {
-			e = nil
-		} else {
-			e = os.EOF
-		}
-	}
-	return n, e
-}
-
-type debugger struct {
-	mutex          sync.Mutex
-	remain         int  // the number of bytes known to remain in the input
-	remainingKnown bool // the value of 'remain' is valid
-	r              *peekReader
-	wireType       map[typeId]*wireType
-	tmp            []byte // scratch space for decoding uints.
-}
-
-// dump prints the next nBytes of the input.
-// It arranges to print the output aligned from call to
-// call, to make it easy to see what has been consumed.
-func (deb *debugger) dump(format string, args ...interface{}) {
-	if !dumpBytes {
-		return
-	}
-	fmt.Fprintf(os.Stderr, format+" ", args...)
-	if !deb.remainingKnown {
-		return
-	}
-	if deb.remain < 0 {
-		fmt.Fprintf(os.Stderr, "remaining byte count is negative! %d\n", deb.remain)
-		return
-	}
-	data := make([]byte, deb.remain)
-	n, _ := deb.r.peek(data)
-	if n == 0 {
-		os.Stderr.Write(empty)
-		return
-	}
-	b := new(bytes.Buffer)
-	fmt.Fprintf(b, "[%d]{\n", deb.remain)
-	// Blanks until first byte
-	lineLength := 0
-	if n := len(data); n%10 != 0 {
-		lineLength = 10 - n%10
-		fmt.Fprintf(b, "\t%s", blanks[:lineLength*3])
-	}
-	// 10 bytes per line
-	for len(data) > 0 {
-		if lineLength == 0 {
-			fmt.Fprint(b, "\t")
-		}
-		m := 10 - lineLength
-		lineLength = 0
-		if m > len(data) {
-			m = len(data)
-		}
-		fmt.Fprintf(b, "% x\n", data[:m])
-		data = data[m:]
-	}
-	fmt.Fprint(b, "}\n")
-	os.Stderr.Write(b.Bytes())
-}
-
-// Debug prints a human-readable representation of the gob data read from r.
-// It is a no-op unless debugging was enabled when the package was built.
-func Debug(r io.Reader) {
-	err := debug(r)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "gob debug: %s\n", err)
-	}
-}
-
-// debug implements Debug, but catches panics and returns
-// them as errors to be printed by Debug.
-func debug(r io.Reader) (err os.Error) {
-	defer catchError(&err)
-	fmt.Fprintln(os.Stderr, "Start of debugging")
-	deb := &debugger{
-		r:        newPeekReader(r),
-		wireType: make(map[typeId]*wireType),
-		tmp:      make([]byte, 16),
-	}
-	if b, ok := r.(*bytes.Buffer); ok {
-		deb.remain = b.Len()
-		deb.remainingKnown = true
-	}
-	deb.gobStream()
-	return
-}
-
-// note that we've consumed some bytes
-func (deb *debugger) consumed(n int) {
-	if deb.remainingKnown {
-		deb.remain -= n
-	}
-}
-
-// int64 decodes and returns the next integer, which must be present.
-// Don't call this if you could be at EOF.
-func (deb *debugger) int64() int64 {
-	return toInt(deb.uint64())
-}
-
-// uint64 returns and decodes the next unsigned integer, which must be present.
-// Don't call this if you could be at EOF.
-// TODO: handle errors better.
-func (deb *debugger) uint64() uint64 {
-	n, w, err := decodeUintReader(deb.r, deb.tmp)
-	if err != nil {
-		errorf("debug: read error: %s", err)
-	}
-	deb.consumed(w)
-	return n
-}
-
-// GobStream:
-//	DelimitedMessage* (until EOF)
-func (deb *debugger) gobStream() {
-	// Make sure we're single-threaded through here.
-	deb.mutex.Lock()
-	defer deb.mutex.Unlock()
-
-	for deb.delimitedMessage(0) {
-	}
-}
-
-// DelimitedMessage:
-//	uint(lengthOfMessage) Message
-func (deb *debugger) delimitedMessage(indent tab) bool {
-	for {
-		n := deb.loadBlock(true)
-		if n < 0 {
-			return false
-		}
-		deb.dump("Delimited message of length %d", n)
-		deb.message(indent)
-	}
-	return true
-}
-
-// loadBlock preps us to read a message
-// of the length specified next in the input. It returns
-// the length of the block. The argument tells whether
-// an EOF is acceptable now.  If it is and one is found,
-// the return value is negative.
-func (deb *debugger) loadBlock(eofOK bool) int {
-	n64, w, err := decodeUintReader(deb.r, deb.tmp) // deb.uint64 will error at EOF
-	if err != nil {
-		if eofOK && err == os.EOF {
-			return -1
-		}
-		errorf("debug: unexpected error: %s", err)
-	}
-	deb.consumed(w)
-	n := int(n64)
-	if n < 0 {
-		errorf("huge value for message length: %d", n64)
-	}
-	return int(n)
-}
-
-// Message:
-//	TypeSequence TypedValue
-// TypeSequence
-//	(TypeDefinition DelimitedTypeDefinition*)?
-// DelimitedTypeDefinition:
-//	uint(lengthOfTypeDefinition) TypeDefinition
-// TypedValue:
-//	int(typeId) Value
-func (deb *debugger) message(indent tab) bool {
-	for {
-		// Convert the uint64 to a signed integer typeId
-		uid := deb.int64()
-		id := typeId(uid)
-		deb.dump("type id=%d", id)
-		if id < 0 {
-			deb.typeDefinition(indent, -id)
-			n := deb.loadBlock(false)
-			deb.dump("Message of length %d", n)
-			continue
-		} else {
-			deb.value(indent, id)
-			break
-		}
-	}
-	return true
-}
-
-// Helper methods to make it easy to scan a type descriptor.
-
-// common returns the CommonType at the input point.
-func (deb *debugger) common() CommonType {
-	fieldNum := -1
-	name := ""
-	id := typeId(0)
-	for {
-		delta := deb.delta(-1)
-		if delta == 0 {
-			break
-		}
-		fieldNum += delta
-		switch fieldNum {
-		case 0:
-			name = deb.string()
-		case 1:
-			// Id typeId
-			id = deb.typeId()
-		default:
-			errorf("corrupted CommonType")
-		}
-	}
-	return CommonType{name, id}
-}
-
-// uint returns the unsigned int at the input point, as a uint (not uint64).
-func (deb *debugger) uint() uint {
-	return uint(deb.uint64())
-}
-
-// int returns the signed int at the input point, as an int (not int64).
-func (deb *debugger) int() int {
-	return int(deb.int64())
-}
-
-// typeId returns the type id at the input point.
-func (deb *debugger) typeId() typeId {
-	return typeId(deb.int64())
-}
-
-// string returns the string at the input point.
-func (deb *debugger) string() string {
-	x := int(deb.uint64())
-	b := make([]byte, x)
-	nb, _ := deb.r.Read(b)
-	if nb != x {
-		errorf("corrupted type")
-	}
-	deb.consumed(nb)
-	return string(b)
-}
-
-// delta returns the field delta at the input point.  The expect argument,
-// if non-negative, identifies what the value should be.
-func (deb *debugger) delta(expect int) int {
-	delta := int(deb.uint64())
-	if delta < 0 || (expect >= 0 && delta != expect) {
-		errorf("decode: corrupted type: delta %d expected %d", delta, expect)
-	}
-	return delta
-}
-
-// TypeDefinition:
-//	[int(-typeId) (already read)] encodingOfWireType
-func (deb *debugger) typeDefinition(indent tab, id typeId) {
-	deb.dump("type definition for id %d", id)
-	// Encoding is of a wireType. Decode the structure as usual
-	fieldNum := -1
-	wire := new(wireType)
-	// A wireType defines a single field.
-	delta := deb.delta(-1)
-	fieldNum += delta
-	switch fieldNum {
-	case 0: // array type, one field of {{Common}, elem, length}
-		// Field number 0 is CommonType
-		deb.delta(1)
-		com := deb.common()
-		// Field number 1 is type Id of elem
-		deb.delta(1)
-		id := deb.typeId()
-		// Field number 3 is length
-		deb.delta(1)
-		length := deb.int()
-		wire.ArrayT = &arrayType{com, id, length}
-
-	case 1: // slice type, one field of {{Common}, elem}
-		// Field number 0 is CommonType
-		deb.delta(1)
-		com := deb.common()
-		// Field number 1 is type Id of elem
-		deb.delta(1)
-		id := deb.typeId()
-		wire.SliceT = &sliceType{com, id}
-
-	case 2: // struct type, one field of {{Common}, []fieldType}
-		// Field number 0 is CommonType
-		deb.delta(1)
-		com := deb.common()
-		// Field number 1 is slice of FieldType
-		deb.delta(1)
-		numField := int(deb.uint())
-		field := make([]*fieldType, numField)
-		for i := 0; i < numField; i++ {
-			field[i] = new(fieldType)
-			deb.delta(1) // field 0 of fieldType: name
-			field[i].Name = deb.string()
-			deb.delta(1) // field 1 of fieldType: id
-			field[i].Id = deb.typeId()
-			deb.delta(0) // end of fieldType
-		}
-		wire.StructT = &structType{com, field}
-
-	case 3: // map type, one field of {{Common}, key, elem}
-		// Field number 0 is CommonType
-		deb.delta(1)
-		com := deb.common()
-		// Field number 1 is type Id of key
-		deb.delta(1)
-		keyId := deb.typeId()
-		// Field number 2 is type Id of elem
-		deb.delta(1)
-		elemId := deb.typeId()
-		wire.MapT = &mapType{com, keyId, elemId}
-	case 4: // GobEncoder type, one field of {{Common}}
-		// Field number 0 is CommonType
-		deb.delta(1)
-		com := deb.common()
-		wire.GobEncoderT = &gobEncoderType{com}
-	default:
-		errorf("bad field in type %d", fieldNum)
-	}
-	deb.printWireType(indent, wire)
-	deb.delta(0) // end inner type (arrayType, etc.)
-	deb.delta(0) // end wireType
-	// Remember we've seen this type.
-	deb.wireType[id] = wire
-}
-
-// Value:
-//	SingletonValue | StructValue
-func (deb *debugger) value(indent tab, id typeId) {
-	wire, ok := deb.wireType[id]
-	if ok && wire.StructT != nil {
-		deb.structValue(indent, id)
-	} else {
-		deb.singletonValue(indent, id)
-	}
-}
-
-// SingletonValue:
-//	uint(0) FieldValue
-func (deb *debugger) singletonValue(indent tab, id typeId) {
-	deb.dump("Singleton value")
-	// is it a builtin type?
-	wire := deb.wireType[id]
-	_, ok := builtinIdToType[id]
-	if !ok && wire == nil {
-		errorf("type id %d not defined", id)
-	}
-	m := deb.uint64()
-	if m != 0 {
-		errorf("expected zero; got %d", m)
-	}
-	deb.fieldValue(indent, id)
-}
-
-// InterfaceValue:
-//	NilInterfaceValue | NonNilInterfaceValue
-func (deb *debugger) interfaceValue(indent tab) {
-	deb.dump("Start of interface value")
-	if nameLen := deb.uint64(); nameLen == 0 {
-		deb.nilInterfaceValue(indent)
-	} else {
-		deb.nonNilInterfaceValue(indent, int(nameLen))
-	}
-}
-
-// NilInterfaceValue:
-//	uint(0) [already read]
-func (deb *debugger) nilInterfaceValue(indent tab) int {
-	fmt.Fprintf(os.Stderr, "%snil interface\n", indent)
-	return 0
-}
-
-// NonNilInterfaceValue:
-//	ConcreteTypeName TypeSequence InterfaceContents
-// ConcreteTypeName:
-//	uint(lengthOfName) [already read=n] name
-// InterfaceContents:
-//	int(concreteTypeId) DelimitedValue
-// DelimitedValue:
-//	uint(length) Value
-func (deb *debugger) nonNilInterfaceValue(indent tab, nameLen int) {
-	// ConcreteTypeName
-	b := make([]byte, nameLen)
-	deb.r.Read(b) // TODO: CHECK THESE READS!!
-	deb.consumed(nameLen)
-	name := string(b)
-
-	for {
-		id := deb.typeId()
-		if id < 0 {
-			deb.typeDefinition(indent, -id)
-			n := deb.loadBlock(false)
-			deb.dump("Nested message of length %d", n)
-		} else {
-			// DelimitedValue
-			x := deb.uint64() // in case we want to ignore the value; we don't.
-			fmt.Fprintf(os.Stderr, "%sinterface value, type %q id=%d; valueLength %d\n", indent, name, id, x)
-			deb.value(indent, id)
-			break
-		}
-	}
-}
-
-// printCommonType prints a common type; used by printWireType.
-func (deb *debugger) printCommonType(indent tab, kind string, common *CommonType) {
-	indent.print()
-	fmt.Fprintf(os.Stderr, "%s %q id=%d\n", kind, common.Name, common.Id)
-}
-
-// printWireType prints the contents of a wireType.
-func (deb *debugger) printWireType(indent tab, wire *wireType) {
-	fmt.Fprintf(os.Stderr, "%stype definition {\n", indent)
-	indent++
-	switch {
-	case wire.ArrayT != nil:
-		deb.printCommonType(indent, "array", &wire.ArrayT.CommonType)
-		fmt.Fprintf(os.Stderr, "%slen %d\n", indent+1, wire.ArrayT.Len)
-		fmt.Fprintf(os.Stderr, "%selemid %d\n", indent+1, wire.ArrayT.Elem)
-	case wire.MapT != nil:
-		deb.printCommonType(indent, "map", &wire.MapT.CommonType)
-		fmt.Fprintf(os.Stderr, "%skey id=%d\n", indent+1, wire.MapT.Key)
-		fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.MapT.Elem)
-	case wire.SliceT != nil:
-		deb.printCommonType(indent, "slice", &wire.SliceT.CommonType)
-		fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.SliceT.Elem)
-	case wire.StructT != nil:
-		deb.printCommonType(indent, "struct", &wire.StructT.CommonType)
-		for i, field := range wire.StructT.Field {
-			fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id)
-		}
-	case wire.GobEncoderT != nil:
-		deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType)
-	}
-	indent--
-	fmt.Fprintf(os.Stderr, "%s}\n", indent)
-}
-
-// fieldValue prints a value of any type, such as a struct field.
-// FieldValue:
-//	builtinValue | ArrayValue | MapValue | SliceValue | StructValue | InterfaceValue
-func (deb *debugger) fieldValue(indent tab, id typeId) {
-	_, ok := builtinIdToType[id]
-	if ok {
-		if id == tInterface {
-			deb.interfaceValue(indent)
-		} else {
-			deb.printBuiltin(indent, id)
-		}
-		return
-	}
-	wire, ok := deb.wireType[id]
-	if !ok {
-		errorf("type id %d not defined", id)
-	}
-	switch {
-	case wire.ArrayT != nil:
-		deb.arrayValue(indent, wire)
-	case wire.MapT != nil:
-		deb.mapValue(indent, wire)
-	case wire.SliceT != nil:
-		deb.sliceValue(indent, wire)
-	case wire.StructT != nil:
-		deb.structValue(indent, id)
-	case wire.GobEncoderT != nil:
-		deb.gobEncoderValue(indent, id)
-	default:
-		panic("bad wire type for field")
-	}
-}
-
-// printBuiltin prints a value not of a fundamental type, that is,
-// one whose type is known to gobs at bootstrap time.
-func (deb *debugger) printBuiltin(indent tab, id typeId) {
-	switch id {
-	case tBool:
-		x := deb.int64()
-		if x == 0 {
-			fmt.Fprintf(os.Stderr, "%sfalse\n", indent)
-		} else {
-			fmt.Fprintf(os.Stderr, "%strue\n", indent)
-		}
-	case tInt:
-		x := deb.int64()
-		fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
-	case tUint:
-		x := deb.int64()
-		fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
-	case tFloat:
-		x := deb.uint64()
-		fmt.Fprintf(os.Stderr, "%s%g\n", indent, floatFromBits(x))
-	case tComplex:
-		r := deb.uint64()
-		i := deb.uint64()
-		fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, floatFromBits(r), floatFromBits(i))
-	case tBytes:
-		x := int(deb.uint64())
-		b := make([]byte, x)
-		deb.r.Read(b)
-		deb.consumed(x)
-		fmt.Fprintf(os.Stderr, "%s{% x}=%q\n", indent, b, b)
-	case tString:
-		x := int(deb.uint64())
-		b := make([]byte, x)
-		deb.r.Read(b)
-		deb.consumed(x)
-		fmt.Fprintf(os.Stderr, "%s%q\n", indent, b)
-	default:
-		panic("unknown builtin")
-	}
-}
-
-// ArrayValue:
-//	uint(n) FieldValue*n
-func (deb *debugger) arrayValue(indent tab, wire *wireType) {
-	elemId := wire.ArrayT.Elem
-	u := deb.uint64()
-	length := int(u)
-	for i := 0; i < length; i++ {
-		deb.fieldValue(indent, elemId)
-	}
-	if length != wire.ArrayT.Len {
-		fmt.Fprintf(os.Stderr, "%s(wrong length for array: %d should be %d)\n", indent, length, wire.ArrayT.Len)
-	}
-}
-
-// MapValue:
-//	uint(n) (FieldValue FieldValue)*n  [n (key, value) pairs]
-func (deb *debugger) mapValue(indent tab, wire *wireType) {
-	keyId := wire.MapT.Key
-	elemId := wire.MapT.Elem
-	u := deb.uint64()
-	length := int(u)
-	for i := 0; i < length; i++ {
-		deb.fieldValue(indent+1, keyId)
-		deb.fieldValue(indent+1, elemId)
-	}
-}
-
-// SliceValue:
-//	uint(n) (n FieldValue)
-func (deb *debugger) sliceValue(indent tab, wire *wireType) {
-	elemId := wire.SliceT.Elem
-	u := deb.uint64()
-	length := int(u)
-	deb.dump("Start of slice of length %d", length)
-
-	for i := 0; i < length; i++ {
-		deb.fieldValue(indent, elemId)
-	}
-}
-
-// StructValue:
-//	(uint(fieldDelta) FieldValue)*
-func (deb *debugger) structValue(indent tab, id typeId) {
-	deb.dump("Start of struct value of %q id=%d\n<<\n", id.name(), id)
-	fmt.Fprintf(os.Stderr, "%s%s struct {\n", indent, id.name())
-	wire, ok := deb.wireType[id]
-	if !ok {
-		errorf("type id %d not defined", id)
-	}
-	strct := wire.StructT
-	fieldNum := -1
-	indent++
-	for {
-		delta := deb.uint64()
-		if delta == 0 { // struct terminator is zero delta fieldnum
-			break
-		}
-		fieldNum += int(delta)
-		if fieldNum < 0 || fieldNum >= len(strct.Field) {
-			deb.dump("field number out of range: prevField=%d delta=%d", fieldNum-int(delta), delta)
-			break
-		}
-		fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\n", indent, fieldNum, wire.StructT.Field[fieldNum].Name)
-		deb.fieldValue(indent+1, strct.Field[fieldNum].Id)
-	}
-	indent--
-	fmt.Fprintf(os.Stderr, "%s} // end %s struct\n", indent, id.name())
-	deb.dump(">> End of struct value of type %d %q", id, id.name())
-}
-
-// GobEncoderValue:
-//	uint(n) byte*n
-func (deb *debugger) gobEncoderValue(indent tab, id typeId) {
-	len := deb.uint64()
-	deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len)
-	fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name())
-	data := make([]byte, len)
-	_, err := deb.r.Read(data)
-	if err != nil {
-		errorf("gobEncoder data read: %s", err)
-	}
-	fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data)
-}
diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go
deleted file mode 100644
index 9d8d905..0000000
--- a/src/pkg/gob/decode.go
+++ /dev/null
@@ -1,1279 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-// TODO(rsc): When garbage collector changes, revisit
-// the allocations in this file that use unsafe.Pointer.
-
-import (
-	"bytes"
-	"io"
-	"math"
-	"os"
-	"reflect"
-	"unsafe"
-)
-
-var (
-	errBadUint = os.NewError("gob: encoded unsigned integer out of range")
-	errBadType = os.NewError("gob: unknown type id or corrupted data")
-	errRange   = os.NewError("gob: bad data: field numbers out of bounds")
-)
-
-// decoderState is the execution state of an instance of the decoder. A new state
-// is created for nested objects.
-type decoderState struct {
-	dec *Decoder
-	// The buffer is stored with an extra indirection because it may be replaced
-	// if we load a type during decode (when reading an interface value).
-	b        *bytes.Buffer
-	fieldnum int // the last field number read.
-	buf      []byte
-	next     *decoderState // for free list
-}
-
-// We pass the bytes.Buffer separately for easier testing of the infrastructure
-// without requiring a full Decoder.
-func (dec *Decoder) newDecoderState(buf *bytes.Buffer) *decoderState {
-	d := dec.freeList
-	if d == nil {
-		d = new(decoderState)
-		d.dec = dec
-		d.buf = make([]byte, uint64Size)
-	} else {
-		dec.freeList = d.next
-	}
-	d.b = buf
-	return d
-}
-
-func (dec *Decoder) freeDecoderState(d *decoderState) {
-	d.next = dec.freeList
-	dec.freeList = d
-}
-
-func overflow(name string) os.Error {
-	return os.NewError(`value for "` + name + `" out of range`)
-}
-
-// decodeUintReader reads an encoded unsigned integer from an io.Reader.
-// Used only by the Decoder to read the message length.
-func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err os.Error) {
-	width = 1
-	_, err = r.Read(buf[0:width])
-	if err != nil {
-		return
-	}
-	b := buf[0]
-	if b <= 0x7f {
-		return uint64(b), width, nil
-	}
-	n := -int(int8(b))
-	if n > uint64Size {
-		err = errBadUint
-		return
-	}
-	width, err = io.ReadFull(r, buf[0:n])
-	if err != nil {
-		if err == os.EOF {
-			err = io.ErrUnexpectedEOF
-		}
-		return
-	}
-	// Could check that the high byte is zero but it's not worth it.
-	for _, b := range buf[0:width] {
-		x = x<<8 | uint64(b)
-	}
-	width++ // +1 for length byte
-	return
-}
-
-// decodeUint reads an encoded unsigned integer from state.r.
-// Does not check for overflow.
-func (state *decoderState) decodeUint() (x uint64) {
-	b, err := state.b.ReadByte()
-	if err != nil {
-		error(err)
-	}
-	if b <= 0x7f {
-		return uint64(b)
-	}
-	n := -int(int8(b))
-	if n > uint64Size {
-		error(errBadUint)
-	}
-	width, err := state.b.Read(state.buf[0:n])
-	if err != nil {
-		error(err)
-	}
-	// Don't need to check error; it's safe to loop regardless.
-	// Could check that the high byte is zero but it's not worth it.
-	for _, b := range state.buf[0:width] {
-		x = x<<8 | uint64(b)
-	}
-	return x
-}
-
-// decodeInt reads an encoded signed integer from state.r.
-// Does not check for overflow.
-func (state *decoderState) decodeInt() int64 {
-	x := state.decodeUint()
-	if x&1 != 0 {
-		return ^int64(x >> 1)
-	}
-	return int64(x >> 1)
-}
-
-// decOp is the signature of a decoding operator for a given type.
-type decOp func(i *decInstr, state *decoderState, p unsafe.Pointer)
-
-// The 'instructions' of the decoding machine
-type decInstr struct {
-	op     decOp
-	field  int      // field number of the wire type
-	indir  int      // how many pointer indirections to reach the value in the struct
-	offset uintptr  // offset in the structure of the field to encode
-	ovfl   os.Error // error message for overflow/underflow (for arrays, of the elements)
-}
-
-// Since the encoder writes no zeros, if we arrive at a decoder we have
-// a value to extract and store.  The field number has already been read
-// (it's how we knew to call this decoder).
-// Each decoder is responsible for handling any indirections associated
-// with the data structure.  If any pointer so reached is nil, allocation must
-// be done.
-
-// Walk the pointer hierarchy, allocating if we find a nil.  Stop one before the end.
-func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
-	for ; indir > 1; indir-- {
-		if *(*unsafe.Pointer)(p) == nil {
-			// Allocation required
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	return p
-}
-
-// ignoreUint discards a uint value with no destination.
-func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	state.decodeUint()
-}
-
-// ignoreTwoUints discards a uint value with no destination. It's used to skip
-// complex values.
-func ignoreTwoUints(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	state.decodeUint()
-	state.decodeUint()
-}
-
-// decBool decodes a uint and stores it as a boolean through p.
-func decBool(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	*(*bool)(p) = state.decodeUint() != 0
-}
-
-// decInt8 decodes an integer and stores it as an int8 through p.
-func decInt8(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	v := state.decodeInt()
-	if v < math.MinInt8 || math.MaxInt8 < v {
-		error(i.ovfl)
-	} else {
-		*(*int8)(p) = int8(v)
-	}
-}
-
-// decUint8 decodes an unsigned integer and stores it as a uint8 through p.
-func decUint8(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	v := state.decodeUint()
-	if math.MaxUint8 < v {
-		error(i.ovfl)
-	} else {
-		*(*uint8)(p) = uint8(v)
-	}
-}
-
-// decInt16 decodes an integer and stores it as an int16 through p.
-func decInt16(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	v := state.decodeInt()
-	if v < math.MinInt16 || math.MaxInt16 < v {
-		error(i.ovfl)
-	} else {
-		*(*int16)(p) = int16(v)
-	}
-}
-
-// decUint16 decodes an unsigned integer and stores it as a uint16 through p.
-func decUint16(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	v := state.decodeUint()
-	if math.MaxUint16 < v {
-		error(i.ovfl)
-	} else {
-		*(*uint16)(p) = uint16(v)
-	}
-}
-
-// decInt32 decodes an integer and stores it as an int32 through p.
-func decInt32(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	v := state.decodeInt()
-	if v < math.MinInt32 || math.MaxInt32 < v {
-		error(i.ovfl)
-	} else {
-		*(*int32)(p) = int32(v)
-	}
-}
-
-// decUint32 decodes an unsigned integer and stores it as a uint32 through p.
-func decUint32(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	v := state.decodeUint()
-	if math.MaxUint32 < v {
-		error(i.ovfl)
-	} else {
-		*(*uint32)(p) = uint32(v)
-	}
-}
-
-// decInt64 decodes an integer and stores it as an int64 through p.
-func decInt64(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	*(*int64)(p) = int64(state.decodeInt())
-}
-
-// decUint64 decodes an unsigned integer and stores it as a uint64 through p.
-func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	*(*uint64)(p) = uint64(state.decodeUint())
-}
-
-// Floating-point numbers are transmitted as uint64s holding the bits
-// of the underlying representation.  They are sent byte-reversed, with
-// the exponent end coming out first, so integer floating point numbers
-// (for example) transmit more compactly.  This routine does the
-// unswizzling.
-func floatFromBits(u uint64) float64 {
-	var v uint64
-	for i := 0; i < 8; i++ {
-		v <<= 8
-		v |= u & 0xFF
-		u >>= 8
-	}
-	return math.Float64frombits(v)
-}
-
-// storeFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
-// number, and stores it through p. It's a helper function for float32 and complex64.
-func storeFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	v := floatFromBits(state.decodeUint())
-	av := v
-	if av < 0 {
-		av = -av
-	}
-	// +Inf is OK in both 32- and 64-bit floats.  Underflow is always OK.
-	if math.MaxFloat32 < av && av <= math.MaxFloat64 {
-		error(i.ovfl)
-	} else {
-		*(*float32)(p) = float32(v)
-	}
-}
-
-// decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point
-// number, and stores it through p.
-func decFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	storeFloat32(i, state, p)
-}
-
-// decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point
-// number, and stores it through p.
-func decFloat64(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	*(*float64)(p) = floatFromBits(uint64(state.decodeUint()))
-}
-
-// decComplex64 decodes a pair of unsigned integers, treats them as a
-// pair of floating point numbers, and stores them as a complex64 through p.
-// The real part comes first.
-func decComplex64(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	storeFloat32(i, state, p)
-	storeFloat32(i, state, unsafe.Pointer(uintptr(p)+unsafe.Sizeof(float32(0))))
-}
-
-// decComplex128 decodes a pair of unsigned integers, treats them as a
-// pair of floating point numbers, and stores them as a complex128 through p.
-// The real part comes first.
-func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	real := floatFromBits(uint64(state.decodeUint()))
-	imag := floatFromBits(uint64(state.decodeUint()))
-	*(*complex128)(p) = complex(real, imag)
-}
-
-// decUint8Slice decodes a byte slice and stores through p a slice header
-// describing the data.
-// uint8 slices are encoded as an unsigned count followed by the raw bytes.
-func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	n := int(state.decodeUint())
-	if n < 0 {
-		errorf("negative length decoding []byte")
-	}
-	slice := (*[]uint8)(p)
-	if cap(*slice) < n {
-		*slice = make([]uint8, n)
-	} else {
-		*slice = (*slice)[0:n]
-	}
-	if _, err := state.b.Read(*slice); err != nil {
-		errorf("error decoding []byte: %s", err)
-	}
-}
-
-// decString decodes byte array and stores through p a string header
-// describing the data.
-// Strings are encoded as an unsigned count followed by the raw bytes.
-func decString(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	if i.indir > 0 {
-		if *(*unsafe.Pointer)(p) == nil {
-			*(*unsafe.Pointer)(p) = unsafe.Pointer(new(string))
-		}
-		p = *(*unsafe.Pointer)(p)
-	}
-	b := make([]byte, state.decodeUint())
-	state.b.Read(b)
-	// It would be a shame to do the obvious thing here,
-	//	*(*string)(p) = string(b)
-	// because we've already allocated the storage and this would
-	// allocate again and copy.  So we do this ugly hack, which is even
-	// even more unsafe than it looks as it depends the memory
-	// representation of a string matching the beginning of the memory
-	// representation of a byte slice (a byte slice is longer).
-	*(*string)(p) = *(*string)(unsafe.Pointer(&b))
-}
-
-// ignoreUint8Array skips over the data for a byte slice value with no destination.
-func ignoreUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
-	b := make([]byte, state.decodeUint())
-	state.b.Read(b)
-}
-
-// Execution engine
-
-// The encoder engine is an array of instructions indexed by field number of the incoming
-// decoder.  It is executed with random access according to field number.
-type decEngine struct {
-	instr    []decInstr
-	numInstr int // the number of active instructions
-}
-
-// allocate makes sure storage is available for an object of underlying type rtyp
-// that is indir levels of indirection through p.
-func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
-	if indir == 0 {
-		return p
-	}
-	up := unsafe.Pointer(p)
-	if indir > 1 {
-		up = decIndirect(up, indir)
-	}
-	if *(*unsafe.Pointer)(up) == nil {
-		// Allocate object.
-		*(*unsafe.Pointer)(up) = unsafe.New(rtyp)
-	}
-	return *(*uintptr)(up)
-}
-
-// decodeSingle decodes a top-level value that is not a struct and stores it through p.
-// Such values are preceded by a zero, making them have the memory layout of a
-// struct field (although with an illegal field number).
-func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uintptr) (err os.Error) {
-	state := dec.newDecoderState(&dec.buf)
-	state.fieldnum = singletonField
-	delta := int(state.decodeUint())
-	if delta != 0 {
-		errorf("decode: corrupted data: non-zero delta for singleton")
-	}
-	instr := &engine.instr[singletonField]
-	if instr.indir != ut.indir {
-		return os.NewError("gob: internal error: inconsistent indirection")
-	}
-	ptr := unsafe.Pointer(basep) // offset will be zero
-	if instr.indir > 1 {
-		ptr = decIndirect(ptr, instr.indir)
-	}
-	instr.op(instr, state, ptr)
-	dec.freeDecoderState(state)
-	return nil
-}
-
-// decodeSingle decodes a top-level struct and stores it through p.
-// Indir is for the value, not the type.  At the time of the call it may
-// differ from ut.indir, which was computed when the engine was built.
-// This state cannot arise for decodeSingle, which is called directly
-// from the user's value, not from the innards of an engine.
-func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr, indir int) {
-	p = allocate(ut.base, p, indir)
-	state := dec.newDecoderState(&dec.buf)
-	state.fieldnum = -1
-	basep := p
-	for state.b.Len() > 0 {
-		delta := int(state.decodeUint())
-		if delta < 0 {
-			errorf("decode: corrupted data: negative delta")
-		}
-		if delta == 0 { // struct terminator is zero delta fieldnum
-			break
-		}
-		fieldnum := state.fieldnum + delta
-		if fieldnum >= len(engine.instr) {
-			error(errRange)
-			break
-		}
-		instr := &engine.instr[fieldnum]
-		p := unsafe.Pointer(basep + instr.offset)
-		if instr.indir > 1 {
-			p = decIndirect(p, instr.indir)
-		}
-		instr.op(instr, state, p)
-		state.fieldnum = fieldnum
-	}
-	dec.freeDecoderState(state)
-}
-
-// ignoreStruct discards the data for a struct with no destination.
-func (dec *Decoder) ignoreStruct(engine *decEngine) {
-	state := dec.newDecoderState(&dec.buf)
-	state.fieldnum = -1
-	for state.b.Len() > 0 {
-		delta := int(state.decodeUint())
-		if delta < 0 {
-			errorf("ignore decode: corrupted data: negative delta")
-		}
-		if delta == 0 { // struct terminator is zero delta fieldnum
-			break
-		}
-		fieldnum := state.fieldnum + delta
-		if fieldnum >= len(engine.instr) {
-			error(errRange)
-		}
-		instr := &engine.instr[fieldnum]
-		instr.op(instr, state, unsafe.Pointer(nil))
-		state.fieldnum = fieldnum
-	}
-	dec.freeDecoderState(state)
-}
-
-// ignoreSingle discards the data for a top-level non-struct value with no
-// destination. It's used when calling Decode with a nil value.
-func (dec *Decoder) ignoreSingle(engine *decEngine) {
-	state := dec.newDecoderState(&dec.buf)
-	state.fieldnum = singletonField
-	delta := int(state.decodeUint())
-	if delta != 0 {
-		errorf("decode: corrupted data: non-zero delta for singleton")
-	}
-	instr := &engine.instr[singletonField]
-	instr.op(instr, state, unsafe.Pointer(nil))
-	dec.freeDecoderState(state)
-}
-
-// decodeArrayHelper does the work for decoding arrays and slices.
-func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl os.Error) {
-	instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
-	for i := 0; i < length; i++ {
-		up := unsafe.Pointer(p)
-		if elemIndir > 1 {
-			up = decIndirect(up, elemIndir)
-		}
-		elemOp(instr, state, up)
-		p += uintptr(elemWid)
-	}
-}
-
-// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
-// The length is an unsigned integer preceding the elements.  Even though the length is redundant
-// (it's part of the type), it's a useful check and is included in the encoding.
-func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl os.Error) {
-	if indir > 0 {
-		p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
-	}
-	if n := state.decodeUint(); n != uint64(length) {
-		errorf("length mismatch in decodeArray")
-	}
-	dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl)
-}
-
-// decodeIntoValue is a helper for map decoding.  Since maps are decoded using reflection,
-// unlike the other items we can't use a pointer directly.
-func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl os.Error) reflect.Value {
-	instr := &decInstr{op, 0, indir, 0, ovfl}
-	up := unsafe.Pointer(unsafeAddr(v))
-	if indir > 1 {
-		up = decIndirect(up, indir)
-	}
-	op(instr, state, up)
-	return v
-}
-
-// decodeMap decodes a map and stores its header through p.
-// Maps are encoded as a length followed by key:value pairs.
-// Because the internals of maps are not visible to us, we must
-// use reflection rather than pointer magic.
-func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl os.Error) {
-	if indir > 0 {
-		p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
-	}
-	up := unsafe.Pointer(p)
-	if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime
-		// Allocate map.
-		*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Pointer())
-	}
-	// Maps cannot be accessed by moving addresses around the way
-	// that slices etc. can.  We must recover a full reflection value for
-	// the iteration.
-	v := reflect.ValueOf(unsafe.Unreflect(mtyp, unsafe.Pointer(p)))
-	n := int(state.decodeUint())
-	for i := 0; i < n; i++ {
-		key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
-		elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl)
-		v.SetMapIndex(key, elem)
-	}
-}
-
-// ignoreArrayHelper does the work for discarding arrays and slices.
-func (dec *Decoder) ignoreArrayHelper(state *decoderState, elemOp decOp, length int) {
-	instr := &decInstr{elemOp, 0, 0, 0, os.NewError("no error")}
-	for i := 0; i < length; i++ {
-		elemOp(instr, state, nil)
-	}
-}
-
-// ignoreArray discards the data for an array value with no destination.
-func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) {
-	if n := state.decodeUint(); n != uint64(length) {
-		errorf("length mismatch in ignoreArray")
-	}
-	dec.ignoreArrayHelper(state, elemOp, length)
-}
-
-// ignoreMap discards the data for a map value with no destination.
-func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
-	n := int(state.decodeUint())
-	keyInstr := &decInstr{keyOp, 0, 0, 0, os.NewError("no error")}
-	elemInstr := &decInstr{elemOp, 0, 0, 0, os.NewError("no error")}
-	for i := 0; i < n; i++ {
-		keyOp(keyInstr, state, nil)
-		elemOp(elemInstr, state, nil)
-	}
-}
-
-// decodeSlice decodes a slice and stores the slice header through p.
-// Slices are encoded as an unsigned length followed by the elements.
-func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl os.Error) {
-	n := int(uintptr(state.decodeUint()))
-	if indir > 0 {
-		up := unsafe.Pointer(p)
-		if *(*unsafe.Pointer)(up) == nil {
-			// Allocate the slice header.
-			*(*unsafe.Pointer)(up) = unsafe.Pointer(new([]unsafe.Pointer))
-		}
-		p = *(*uintptr)(up)
-	}
-	// Allocate storage for the slice elements, that is, the underlying array,
-	// if the existing slice does not have the capacity.
-	// Always write a header at p.
-	hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p))
-	if hdrp.Cap < n {
-		hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n))
-		hdrp.Cap = n
-	}
-	hdrp.Len = n
-	dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
-}
-
-// ignoreSlice skips over the data for a slice value with no destination.
-func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
-	dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint()))
-}
-
-// setInterfaceValue sets an interface value to a concrete value,
-// but first it checks that the assignment will succeed.
-func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
-	if !value.Type().AssignableTo(ivalue.Type()) {
-		errorf("cannot assign value of type %s to %s", value.Type(), ivalue.Type())
-	}
-	ivalue.Set(value)
-}
-
-// decodeInterface decodes an interface value and stores it through p.
-// Interfaces are encoded as the name of a concrete type followed by a value.
-// If the name is empty, the value is nil and no value is sent.
-func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p uintptr, indir int) {
-	// Create a writable interface reflect.Value.  We need one even for the nil case.
-	ivalue := allocValue(ityp)
-	// Read the name of the concrete type.
-	b := make([]byte, state.decodeUint())
-	state.b.Read(b)
-	name := string(b)
-	if name == "" {
-		// Copy the representation of the nil interface value to the target.
-		// This is horribly unsafe and special.
-		*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
-		return
-	}
-	// The concrete type must be registered.
-	typ, ok := nameToConcreteType[name]
-	if !ok {
-		errorf("name not registered for interface: %q", name)
-	}
-	// Read the type id of the concrete value.
-	concreteId := dec.decodeTypeSequence(true)
-	if concreteId < 0 {
-		error(dec.err)
-	}
-	// Byte count of value is next; we don't care what it is (it's there
-	// in case we want to ignore the value by skipping it completely).
-	state.decodeUint()
-	// Read the concrete value.
-	value := allocValue(typ)
-	dec.decodeValue(concreteId, value)
-	if dec.err != nil {
-		error(dec.err)
-	}
-	// Allocate the destination interface value.
-	if indir > 0 {
-		p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect
-	}
-	// Assign the concrete value to the interface.
-	// Tread carefully; it might not satisfy the interface.
-	setInterfaceValue(ivalue, value)
-	// Copy the representation of the interface value to the target.
-	// This is horribly unsafe and special.
-	*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
-}
-
-// ignoreInterface discards the data for an interface value with no destination.
-func (dec *Decoder) ignoreInterface(state *decoderState) {
-	// Read the name of the concrete type.
-	b := make([]byte, state.decodeUint())
-	_, err := state.b.Read(b)
-	if err != nil {
-		error(err)
-	}
-	id := dec.decodeTypeSequence(true)
-	if id < 0 {
-		error(dec.err)
-	}
-	// At this point, the decoder buffer contains a delimited value. Just toss it.
-	state.b.Next(int(state.decodeUint()))
-}
-
-// decodeGobDecoder decodes something implementing the GobDecoder interface.
-// The data is encoded as a byte slice.
-func (dec *Decoder) decodeGobDecoder(state *decoderState, v reflect.Value) {
-	// Read the bytes for the value.
-	b := make([]byte, state.decodeUint())
-	_, err := state.b.Read(b)
-	if err != nil {
-		error(err)
-	}
-	// We know it's a GobDecoder, so just call the method directly.
-	err = v.Interface().(GobDecoder).GobDecode(b)
-	if err != nil {
-		error(err)
-	}
-}
-
-// ignoreGobDecoder discards the data for a GobDecoder value with no destination.
-func (dec *Decoder) ignoreGobDecoder(state *decoderState) {
-	// Read the bytes for the value.
-	b := make([]byte, state.decodeUint())
-	_, err := state.b.Read(b)
-	if err != nil {
-		error(err)
-	}
-}
-
-// Index by Go types.
-var decOpTable = [...]decOp{
-	reflect.Bool:       decBool,
-	reflect.Int8:       decInt8,
-	reflect.Int16:      decInt16,
-	reflect.Int32:      decInt32,
-	reflect.Int64:      decInt64,
-	reflect.Uint8:      decUint8,
-	reflect.Uint16:     decUint16,
-	reflect.Uint32:     decUint32,
-	reflect.Uint64:     decUint64,
-	reflect.Float32:    decFloat32,
-	reflect.Float64:    decFloat64,
-	reflect.Complex64:  decComplex64,
-	reflect.Complex128: decComplex128,
-	reflect.String:     decString,
-}
-
-// Indexed by gob types.  tComplex will be added during type.init().
-var decIgnoreOpMap = map[typeId]decOp{
-	tBool:    ignoreUint,
-	tInt:     ignoreUint,
-	tUint:    ignoreUint,
-	tFloat:   ignoreUint,
-	tBytes:   ignoreUint8Array,
-	tString:  ignoreUint8Array,
-	tComplex: ignoreTwoUints,
-}
-
-// decOpFor returns the decoding op for the base type under rt and
-// the indirection count to reach it.
-func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) {
-	ut := userType(rt)
-	// If the type implements GobEncoder, we handle it without further processing.
-	if ut.isGobDecoder {
-		return dec.gobDecodeOpFor(ut)
-	}
-	// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
-	// Return the pointer to the op we're already building.
-	if opPtr := inProgress[rt]; opPtr != nil {
-		return opPtr, ut.indir
-	}
-	typ := ut.base
-	indir := ut.indir
-	var op decOp
-	k := typ.Kind()
-	if int(k) < len(decOpTable) {
-		op = decOpTable[k]
-	}
-	if op == nil {
-		inProgress[rt] = &op
-		// Special cases
-		switch t := typ; t.Kind() {
-		case reflect.Array:
-			name = "element of " + name
-			elemId := dec.wireType[wireId].ArrayT.Elem
-			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
-			ovfl := overflow(name)
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				state.dec.decodeArray(t, state, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
-			}
-
-		case reflect.Map:
-			name = "element of " + name
-			keyId := dec.wireType[wireId].MapT.Key
-			elemId := dec.wireType[wireId].MapT.Elem
-			keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), name, inProgress)
-			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
-			ovfl := overflow(name)
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				up := unsafe.Pointer(p)
-				state.dec.decodeMap(t, state, uintptr(up), *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
-			}
-
-		case reflect.Slice:
-			name = "element of " + name
-			if t.Elem().Kind() == reflect.Uint8 {
-				op = decUint8Slice
-				break
-			}
-			var elemId typeId
-			if tt, ok := builtinIdToType[wireId]; ok {
-				elemId = tt.(*sliceType).Elem
-			} else {
-				elemId = dec.wireType[wireId].SliceT.Elem
-			}
-			elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
-			ovfl := overflow(name)
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				state.dec.decodeSlice(t, state, uintptr(p), *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl)
-			}
-
-		case reflect.Struct:
-			// Generate a closure that calls out to the engine for the nested type.
-			enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ))
-			if err != nil {
-				error(err)
-			}
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				// indirect through enginePtr to delay evaluation for recursive structs.
-				dec.decodeStruct(*enginePtr, userType(typ), uintptr(p), i.indir)
-			}
-		case reflect.Interface:
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				state.dec.decodeInterface(t, state, uintptr(p), i.indir)
-			}
-		}
-	}
-	if op == nil {
-		errorf("decode can't handle type %s", rt.String())
-	}
-	return &op, indir
-}
-
-// decIgnoreOpFor returns the decoding op for a field that has no destination.
-func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
-	op, ok := decIgnoreOpMap[wireId]
-	if !ok {
-		if wireId == tInterface {
-			// Special case because it's a method: the ignored item might
-			// define types and we need to record their state in the decoder.
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				state.dec.ignoreInterface(state)
-			}
-			return op
-		}
-		// Special cases
-		wire := dec.wireType[wireId]
-		switch {
-		case wire == nil:
-			errorf("bad data: undefined type %s", wireId.string())
-		case wire.ArrayT != nil:
-			elemId := wire.ArrayT.Elem
-			elemOp := dec.decIgnoreOpFor(elemId)
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len)
-			}
-
-		case wire.MapT != nil:
-			keyId := dec.wireType[wireId].MapT.Key
-			elemId := dec.wireType[wireId].MapT.Elem
-			keyOp := dec.decIgnoreOpFor(keyId)
-			elemOp := dec.decIgnoreOpFor(elemId)
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				state.dec.ignoreMap(state, keyOp, elemOp)
-			}
-
-		case wire.SliceT != nil:
-			elemId := wire.SliceT.Elem
-			elemOp := dec.decIgnoreOpFor(elemId)
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				state.dec.ignoreSlice(state, elemOp)
-			}
-
-		case wire.StructT != nil:
-			// Generate a closure that calls out to the engine for the nested type.
-			enginePtr, err := dec.getIgnoreEnginePtr(wireId)
-			if err != nil {
-				error(err)
-			}
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				// indirect through enginePtr to delay evaluation for recursive structs
-				state.dec.ignoreStruct(*enginePtr)
-			}
-
-		case wire.GobEncoderT != nil:
-			op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-				state.dec.ignoreGobDecoder(state)
-			}
-		}
-	}
-	if op == nil {
-		errorf("bad data: ignore can't handle type %s", wireId.string())
-	}
-	return op
-}
-
-// gobDecodeOpFor returns the op for a type that is known to implement
-// GobDecoder.
-func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
-	rcvrType := ut.user
-	if ut.decIndir == -1 {
-		rcvrType = reflect.PtrTo(rcvrType)
-	} else if ut.decIndir > 0 {
-		for i := int8(0); i < ut.decIndir; i++ {
-			rcvrType = rcvrType.Elem()
-		}
-	}
-	var op decOp
-	op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
-		// Caller has gotten us to within one indirection of our value.
-		if i.indir > 0 {
-			if *(*unsafe.Pointer)(p) == nil {
-				*(*unsafe.Pointer)(p) = unsafe.New(ut.base)
-			}
-		}
-		// Now p is a pointer to the base type.  Do we need to climb out to
-		// get to the receiver type?
-		var v reflect.Value
-		if ut.decIndir == -1 {
-			v = reflect.ValueOf(unsafe.Unreflect(rcvrType, unsafe.Pointer(&p)))
-		} else {
-			v = reflect.ValueOf(unsafe.Unreflect(rcvrType, p))
-		}
-		state.dec.decodeGobDecoder(state, v)
-	}
-	return &op, int(ut.indir)
-
-}
-
-// compatibleType asks: Are these two gob Types compatible?
-// Answers the question for basic types, arrays, maps and slices, plus
-// GobEncoder/Decoder pairs.
-// Structs are considered ok; fields will be checked later.
-func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[reflect.Type]typeId) bool {
-	if rhs, ok := inProgress[fr]; ok {
-		return rhs == fw
-	}
-	inProgress[fr] = fw
-	ut := userType(fr)
-	wire, ok := dec.wireType[fw]
-	// If fr is a GobDecoder, the wire type must be GobEncoder.
-	// And if fr is not a GobDecoder, the wire type must not be either.
-	if ut.isGobDecoder != (ok && wire.GobEncoderT != nil) { // the parentheses look odd but are correct.
-		return false
-	}
-	if ut.isGobDecoder { // This test trumps all others.
-		return true
-	}
-	switch t := ut.base; t.Kind() {
-	default:
-		// chan, etc: cannot handle.
-		return false
-	case reflect.Bool:
-		return fw == tBool
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return fw == tInt
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return fw == tUint
-	case reflect.Float32, reflect.Float64:
-		return fw == tFloat
-	case reflect.Complex64, reflect.Complex128:
-		return fw == tComplex
-	case reflect.String:
-		return fw == tString
-	case reflect.Interface:
-		return fw == tInterface
-	case reflect.Array:
-		if !ok || wire.ArrayT == nil {
-			return false
-		}
-		array := wire.ArrayT
-		return t.Len() == array.Len && dec.compatibleType(t.Elem(), array.Elem, inProgress)
-	case reflect.Map:
-		if !ok || wire.MapT == nil {
-			return false
-		}
-		MapType := wire.MapT
-		return dec.compatibleType(t.Key(), MapType.Key, inProgress) && dec.compatibleType(t.Elem(), MapType.Elem, inProgress)
-	case reflect.Slice:
-		// Is it an array of bytes?
-		if t.Elem().Kind() == reflect.Uint8 {
-			return fw == tBytes
-		}
-		// Extract and compare element types.
-		var sw *sliceType
-		if tt, ok := builtinIdToType[fw]; ok {
-			sw = tt.(*sliceType)
-		} else {
-			sw = dec.wireType[fw].SliceT
-		}
-		elem := userType(t.Elem()).base
-		return sw != nil && dec.compatibleType(elem, sw.Elem, inProgress)
-	case reflect.Struct:
-		return true
-	}
-	return true
-}
-
-// typeString returns a human-readable description of the type identified by remoteId.
-func (dec *Decoder) typeString(remoteId typeId) string {
-	if t := idToType[remoteId]; t != nil {
-		// globally known type.
-		return t.string()
-	}
-	return dec.wireType[remoteId].string()
-}
-
-// compileSingle compiles the decoder engine for a non-struct top-level value, including
-// GobDecoders.
-func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err os.Error) {
-	rt := ut.user
-	engine = new(decEngine)
-	engine.instr = make([]decInstr, 1) // one item
-	name := rt.String()                // best we can do
-	if !dec.compatibleType(rt, remoteId, make(map[reflect.Type]typeId)) {
-		return nil, os.NewError("gob: wrong type received for local value " + name + ": " + dec.typeString(remoteId))
-	}
-	op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp))
-	ovfl := os.NewError(`value for "` + name + `" out of range`)
-	engine.instr[singletonField] = decInstr{*op, singletonField, indir, 0, ovfl}
-	engine.numInstr = 1
-	return
-}
-
-// compileIgnoreSingle compiles the decoder engine for a non-struct top-level value that will be discarded.
-func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err os.Error) {
-	engine = new(decEngine)
-	engine.instr = make([]decInstr, 1) // one item
-	op := dec.decIgnoreOpFor(remoteId)
-	ovfl := overflow(dec.typeString(remoteId))
-	engine.instr[0] = decInstr{op, 0, 0, 0, ovfl}
-	engine.numInstr = 1
-	return
-}
-
-// compileDec compiles the decoder engine for a value.  If the value is not a struct,
-// it calls out to compileSingle.
-func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err os.Error) {
-	rt := ut.base
-	srt := rt
-	if srt.Kind() != reflect.Struct ||
-		ut.isGobDecoder {
-		return dec.compileSingle(remoteId, ut)
-	}
-	var wireStruct *structType
-	// Builtin types can come from global pool; the rest must be defined by the decoder.
-	// Also we know we're decoding a struct now, so the client must have sent one.
-	if t, ok := builtinIdToType[remoteId]; ok {
-		wireStruct, _ = t.(*structType)
-	} else {
-		wire := dec.wireType[remoteId]
-		if wire == nil {
-			error(errBadType)
-		}
-		wireStruct = wire.StructT
-	}
-	if wireStruct == nil {
-		errorf("type mismatch in decoder: want struct type %s; got non-struct", rt.String())
-	}
-	engine = new(decEngine)
-	engine.instr = make([]decInstr, len(wireStruct.Field))
-	seen := make(map[reflect.Type]*decOp)
-	// Loop over the fields of the wire type.
-	for fieldnum := 0; fieldnum < len(wireStruct.Field); fieldnum++ {
-		wireField := wireStruct.Field[fieldnum]
-		if wireField.Name == "" {
-			errorf("empty name for remote field of type %s", wireStruct.Name)
-		}
-		ovfl := overflow(wireField.Name)
-		// Find the field of the local type with the same name.
-		localField, present := srt.FieldByName(wireField.Name)
-		// TODO(r): anonymous names
-		if !present || !isExported(wireField.Name) {
-			op := dec.decIgnoreOpFor(wireField.Id)
-			engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl}
-			continue
-		}
-		if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) {
-			errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name)
-		}
-		op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen)
-		engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl}
-		engine.numInstr++
-	}
-	return
-}
-
-// getDecEnginePtr returns the engine for the specified type.
-func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePtr **decEngine, err os.Error) {
-	rt := ut.base
-	decoderMap, ok := dec.decoderCache[rt]
-	if !ok {
-		decoderMap = make(map[typeId]**decEngine)
-		dec.decoderCache[rt] = decoderMap
-	}
-	if enginePtr, ok = decoderMap[remoteId]; !ok {
-		// To handle recursive types, mark this engine as underway before compiling.
-		enginePtr = new(*decEngine)
-		decoderMap[remoteId] = enginePtr
-		*enginePtr, err = dec.compileDec(remoteId, ut)
-		if err != nil {
-			decoderMap[remoteId] = nil, false
-		}
-	}
-	return
-}
-
-// emptyStruct is the type we compile into when ignoring a struct value.
-type emptyStruct struct{}
-
-var emptyStructType = reflect.TypeOf(emptyStruct{})
-
-// getDecEnginePtr returns the engine for the specified type when the value is to be discarded.
-func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, err os.Error) {
-	var ok bool
-	if enginePtr, ok = dec.ignorerCache[wireId]; !ok {
-		// To handle recursive types, mark this engine as underway before compiling.
-		enginePtr = new(*decEngine)
-		dec.ignorerCache[wireId] = enginePtr
-		wire := dec.wireType[wireId]
-		if wire != nil && wire.StructT != nil {
-			*enginePtr, err = dec.compileDec(wireId, userType(emptyStructType))
-		} else {
-			*enginePtr, err = dec.compileIgnoreSingle(wireId)
-		}
-		if err != nil {
-			dec.ignorerCache[wireId] = nil, false
-		}
-	}
-	return
-}
-
-// decodeValue decodes the data stream representing a value and stores it in val.
-func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
-	defer catchError(&dec.err)
-	// If the value is nil, it means we should just ignore this item.
-	if !val.IsValid() {
-		dec.decodeIgnoredValue(wireId)
-		return
-	}
-	// Dereference down to the underlying type.
-	ut := userType(val.Type())
-	base := ut.base
-	var enginePtr **decEngine
-	enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut)
-	if dec.err != nil {
-		return
-	}
-	engine := *enginePtr
-	if st := base; st.Kind() == reflect.Struct && !ut.isGobDecoder {
-		if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
-			name := base.Name()
-			errorf("type mismatch: no fields matched compiling decoder for %s", name)
-		}
-		dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir)
-	} else {
-		dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val)))
-	}
-}
-
-// decodeIgnoredValue decodes the data stream representing a value of the specified type and discards it.
-func (dec *Decoder) decodeIgnoredValue(wireId typeId) {
-	var enginePtr **decEngine
-	enginePtr, dec.err = dec.getIgnoreEnginePtr(wireId)
-	if dec.err != nil {
-		return
-	}
-	wire := dec.wireType[wireId]
-	if wire != nil && wire.StructT != nil {
-		dec.ignoreStruct(*enginePtr)
-	} else {
-		dec.ignoreSingle(*enginePtr)
-	}
-}
-
-func init() {
-	var iop, uop decOp
-	switch reflect.TypeOf(int(0)).Bits() {
-	case 32:
-		iop = decInt32
-		uop = decUint32
-	case 64:
-		iop = decInt64
-		uop = decUint64
-	default:
-		panic("gob: unknown size of int/uint")
-	}
-	decOpTable[reflect.Int] = iop
-	decOpTable[reflect.Uint] = uop
-
-	// Finally uintptr
-	switch reflect.TypeOf(uintptr(0)).Bits() {
-	case 32:
-		uop = decUint32
-	case 64:
-		uop = decUint64
-	default:
-		panic("gob: unknown size of uintptr")
-	}
-	decOpTable[reflect.Uintptr] = uop
-}
-
-// Gob assumes it can call UnsafeAddr on any Value
-// in order to get a pointer it can copy data from.
-// Values that have just been created and do not point
-// into existing structs or slices cannot be addressed,
-// so simulate it by returning a pointer to a copy.
-// Each call allocates once.
-func unsafeAddr(v reflect.Value) uintptr {
-	if v.CanAddr() {
-		return v.UnsafeAddr()
-	}
-	x := reflect.New(v.Type()).Elem()
-	x.Set(v)
-	return x.UnsafeAddr()
-}
-
-// Gob depends on being able to take the address
-// of zeroed Values it creates, so use this wrapper instead
-// of the standard reflect.Zero.
-// Each call allocates once.
-func allocValue(t reflect.Type) reflect.Value {
-	return reflect.New(t).Elem()
-}
diff --git a/src/pkg/gob/decoder.go b/src/pkg/gob/decoder.go
deleted file mode 100644
index 2819471..0000000
--- a/src/pkg/gob/decoder.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-import (
-	"bufio"
-	"bytes"
-	"io"
-	"os"
-	"reflect"
-	"sync"
-)
-
-// A Decoder manages the receipt of type and data information read from the
-// remote side of a connection.
-type Decoder struct {
-	mutex        sync.Mutex                              // each item must be received atomically
-	r            io.Reader                               // source of the data
-	buf          bytes.Buffer                            // buffer for more efficient i/o from r
-	wireType     map[typeId]*wireType                    // map from remote ID to local description
-	decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines
-	ignorerCache map[typeId]**decEngine                  // ditto for ignored objects
-	freeList     *decoderState                           // list of free decoderStates; avoids reallocation
-	countBuf     []byte                                  // used for decoding integers while parsing messages
-	tmp          []byte                                  // temporary storage for i/o; saves reallocating
-	err          os.Error
-}
-
-// NewDecoder returns a new decoder that reads from the io.Reader.
-func NewDecoder(r io.Reader) *Decoder {
-	dec := new(Decoder)
-	dec.r = bufio.NewReader(r)
-	dec.wireType = make(map[typeId]*wireType)
-	dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
-	dec.ignorerCache = make(map[typeId]**decEngine)
-	dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes
-
-	return dec
-}
-
-// recvType loads the definition of a type.
-func (dec *Decoder) recvType(id typeId) {
-	// Have we already seen this type?  That's an error
-	if id < firstUserId || dec.wireType[id] != nil {
-		dec.err = os.NewError("gob: duplicate type received")
-		return
-	}
-
-	// Type:
-	wire := new(wireType)
-	dec.decodeValue(tWireType, reflect.ValueOf(wire))
-	if dec.err != nil {
-		return
-	}
-	// Remember we've seen this type.
-	dec.wireType[id] = wire
-}
-
-// recvMessage reads the next count-delimited item from the input. It is the converse
-// of Encoder.writeMessage. It returns false on EOF or other error reading the message.
-func (dec *Decoder) recvMessage() bool {
-	// Read a count.
-	nbytes, _, err := decodeUintReader(dec.r, dec.countBuf)
-	if err != nil {
-		dec.err = err
-		return false
-	}
-	dec.readMessage(int(nbytes))
-	return dec.err == nil
-}
-
-// readMessage reads the next nbytes bytes from the input.
-func (dec *Decoder) readMessage(nbytes int) {
-	// Allocate the buffer.
-	if cap(dec.tmp) < nbytes {
-		dec.tmp = make([]byte, nbytes+100) // room to grow
-	}
-	dec.tmp = dec.tmp[:nbytes]
-
-	// Read the data
-	_, dec.err = io.ReadFull(dec.r, dec.tmp)
-	if dec.err != nil {
-		if dec.err == os.EOF {
-			dec.err = io.ErrUnexpectedEOF
-		}
-		return
-	}
-	dec.buf.Write(dec.tmp)
-}
-
-// toInt turns an encoded uint64 into an int, according to the marshaling rules.
-func toInt(x uint64) int64 {
-	i := int64(x >> 1)
-	if x&1 != 0 {
-		i = ^i
-	}
-	return i
-}
-
-func (dec *Decoder) nextInt() int64 {
-	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
-	if err != nil {
-		dec.err = err
-	}
-	return toInt(n)
-}
-
-func (dec *Decoder) nextUint() uint64 {
-	n, _, err := decodeUintReader(&dec.buf, dec.countBuf)
-	if err != nil {
-		dec.err = err
-	}
-	return n
-}
-
-// decodeTypeSequence parses:
-// TypeSequence
-//	(TypeDefinition DelimitedTypeDefinition*)?
-// and returns the type id of the next value.  It returns -1 at
-// EOF.  Upon return, the remainder of dec.buf is the value to be
-// decoded.  If this is an interface value, it can be ignored by
-// simply resetting that buffer.
-func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
-	for dec.err == nil {
-		if dec.buf.Len() == 0 {
-			if !dec.recvMessage() {
-				break
-			}
-		}
-		// Receive a type id.
-		id := typeId(dec.nextInt())
-		if id >= 0 {
-			// Value follows.
-			return id
-		}
-		// Type definition for (-id) follows.
-		dec.recvType(-id)
-		// When decoding an interface, after a type there may be a
-		// DelimitedValue still in the buffer.  Skip its count.
-		// (Alternatively, the buffer is empty and the byte count
-		// will be absorbed by recvMessage.)
-		if dec.buf.Len() > 0 {
-			if !isInterface {
-				dec.err = os.NewError("extra data in buffer")
-				break
-			}
-			dec.nextUint()
-		}
-	}
-	return -1
-}
-
-// Decode reads the next value from the connection and stores
-// it in the data represented by the empty interface value.
-// If e is nil, the value will be discarded. Otherwise,
-// the value underlying e must be a pointer to the
-// correct type for the next data item received.
-func (dec *Decoder) Decode(e interface{}) os.Error {
-	if e == nil {
-		return dec.DecodeValue(reflect.Value{})
-	}
-	value := reflect.ValueOf(e)
-	// If e represents a value as opposed to a pointer, the answer won't
-	// get back to the caller.  Make sure it's a pointer.
-	if value.Type().Kind() != reflect.Ptr {
-		dec.err = os.NewError("gob: attempt to decode into a non-pointer")
-		return dec.err
-	}
-	return dec.DecodeValue(value)
-}
-
-// DecodeValue reads the next value from the connection.
-// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
-// Otherwise, it stores the value into v.  In that case, v must represent
-// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
-func (dec *Decoder) DecodeValue(v reflect.Value) os.Error {
-	if v.IsValid() {
-		if v.Kind() == reflect.Ptr && !v.IsNil() {
-			// That's okay, we'll store through the pointer.
-		} else if !v.CanSet() {
-			return os.NewError("gob: DecodeValue of unassignable value")
-		}
-	}
-	// Make sure we're single-threaded through here.
-	dec.mutex.Lock()
-	defer dec.mutex.Unlock()
-
-	dec.buf.Reset() // In case data lingers from previous invocation.
-	dec.err = nil
-	id := dec.decodeTypeSequence(false)
-	if dec.err == nil {
-		dec.decodeValue(id, v)
-	}
-	return dec.err
-}
-
-// If debug.go is compiled into the program , debugFunc prints a human-readable
-// representation of the gob data read from r by calling that file's Debug function.
-// Otherwise it is nil.
-var debugFunc func(io.Reader)
diff --git a/src/pkg/gob/dump.go b/src/pkg/gob/dump.go
deleted file mode 100644
index 1555f0f..0000000
--- a/src/pkg/gob/dump.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package main
-
-// Need to compile package gob with debug.go to build this program.
-
-import (
-	"fmt"
-	"gob"
-	"os"
-)
-
-func main() {
-	var err os.Error
-	file := os.Stdin
-	if len(os.Args) > 1 {
-		file, err = os.Open(os.Args[1])
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "dump: %s\n", err)
-			os.Exit(1)
-		}
-	}
-	gob.Debug(file)
-}
diff --git a/src/pkg/gob/encode.go b/src/pkg/gob/encode.go
deleted file mode 100644
index 5100eaa..0000000
--- a/src/pkg/gob/encode.go
+++ /dev/null
@@ -1,716 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-import (
-	"bytes"
-	"math"
-	"reflect"
-	"unsafe"
-)
-
-const uint64Size = int(unsafe.Sizeof(uint64(0)))
-
-// encoderState is the global execution state of an instance of the encoder.
-// Field numbers are delta encoded and always increase. The field
-// number is initialized to -1 so 0 comes out as delta(1). A delta of
-// 0 terminates the structure.
-type encoderState struct {
-	enc      *Encoder
-	b        *bytes.Buffer
-	sendZero bool                 // encoding an array element or map key/value pair; send zero values
-	fieldnum int                  // the last field number written.
-	buf      [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation.
-	next     *encoderState        // for free list
-}
-
-func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState {
-	e := enc.freeList
-	if e == nil {
-		e = new(encoderState)
-		e.enc = enc
-	} else {
-		enc.freeList = e.next
-	}
-	e.sendZero = false
-	e.fieldnum = 0
-	e.b = b
-	return e
-}
-
-func (enc *Encoder) freeEncoderState(e *encoderState) {
-	e.next = enc.freeList
-	enc.freeList = e
-}
-
-// Unsigned integers have a two-state encoding.  If the number is less
-// than 128 (0 through 0x7F), its value is written directly.
-// Otherwise the value is written in big-endian byte order preceded
-// by the byte length, negated.
-
-// encodeUint writes an encoded unsigned integer to state.b.
-func (state *encoderState) encodeUint(x uint64) {
-	if x <= 0x7F {
-		err := state.b.WriteByte(uint8(x))
-		if err != nil {
-			error(err)
-		}
-		return
-	}
-	i := uint64Size
-	for x > 0 {
-		state.buf[i] = uint8(x)
-		x >>= 8
-		i--
-	}
-	state.buf[i] = uint8(i - uint64Size) // = loop count, negated
-	_, err := state.b.Write(state.buf[i : uint64Size+1])
-	if err != nil {
-		error(err)
-	}
-}
-
-// encodeInt writes an encoded signed integer to state.w.
-// The low bit of the encoding says whether to bit complement the (other bits of the)
-// uint to recover the int.
-func (state *encoderState) encodeInt(i int64) {
-	var x uint64
-	if i < 0 {
-		x = uint64(^i<<1) | 1
-	} else {
-		x = uint64(i << 1)
-	}
-	state.encodeUint(uint64(x))
-}
-
-// encOp is the signature of an encoding operator for a given type.
-type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer)
-
-// The 'instructions' of the encoding machine
-type encInstr struct {
-	op     encOp
-	field  int     // field number
-	indir  int     // how many pointer indirections to reach the value in the struct
-	offset uintptr // offset in the structure of the field to encode
-}
-
-// update emits a field number and updates the state to record its value for delta encoding.
-// If the instruction pointer is nil, it does nothing
-func (state *encoderState) update(instr *encInstr) {
-	if instr != nil {
-		state.encodeUint(uint64(instr.field - state.fieldnum))
-		state.fieldnum = instr.field
-	}
-}
-
-// Each encoder for a composite is responsible for handling any
-// indirections associated with the elements of the data structure.
-// If any pointer so reached is nil, no bytes are written.  If the
-// data item is zero, no bytes are written.  Single values - ints,
-// strings etc. - are indirected before calling their encoders.
-// Otherwise, the output (for a scalar) is the field number, as an
-// encoded integer, followed by the field data in its appropriate
-// format.
-
-// encIndirect dereferences p indir times and returns the result.
-func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
-	for ; indir > 0; indir-- {
-		p = *(*unsafe.Pointer)(p)
-		if p == nil {
-			return unsafe.Pointer(nil)
-		}
-	}
-	return p
-}
-
-// encBool encodes the bool with address p as an unsigned 0 or 1.
-func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	b := *(*bool)(p)
-	if b || state.sendZero {
-		state.update(i)
-		if b {
-			state.encodeUint(1)
-		} else {
-			state.encodeUint(0)
-		}
-	}
-}
-
-// encInt encodes the int with address p.
-func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := int64(*(*int)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeInt(v)
-	}
-}
-
-// encUint encodes the uint with address p.
-func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := uint64(*(*uint)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeUint(v)
-	}
-}
-
-// encInt8 encodes the int8 with address p.
-func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := int64(*(*int8)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeInt(v)
-	}
-}
-
-// encUint8 encodes the uint8 with address p.
-func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := uint64(*(*uint8)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeUint(v)
-	}
-}
-
-// encInt16 encodes the int16 with address p.
-func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := int64(*(*int16)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeInt(v)
-	}
-}
-
-// encUint16 encodes the uint16 with address p.
-func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := uint64(*(*uint16)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeUint(v)
-	}
-}
-
-// encInt32 encodes the int32 with address p.
-func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := int64(*(*int32)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeInt(v)
-	}
-}
-
-// encUint encodes the uint32 with address p.
-func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := uint64(*(*uint32)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeUint(v)
-	}
-}
-
-// encInt64 encodes the int64 with address p.
-func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := *(*int64)(p)
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeInt(v)
-	}
-}
-
-// encInt64 encodes the uint64 with address p.
-func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := *(*uint64)(p)
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeUint(v)
-	}
-}
-
-// encUintptr encodes the uintptr with address p.
-func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	v := uint64(*(*uintptr)(p))
-	if v != 0 || state.sendZero {
-		state.update(i)
-		state.encodeUint(v)
-	}
-}
-
-// floatBits returns a uint64 holding the bits of a floating-point number.
-// Floating-point numbers are transmitted as uint64s holding the bits
-// of the underlying representation.  They are sent byte-reversed, with
-// the exponent end coming out first, so integer floating point numbers
-// (for example) transmit more compactly.  This routine does the
-// swizzling.
-func floatBits(f float64) uint64 {
-	u := math.Float64bits(f)
-	var v uint64
-	for i := 0; i < 8; i++ {
-		v <<= 8
-		v |= u & 0xFF
-		u >>= 8
-	}
-	return v
-}
-
-// encFloat32 encodes the float32 with address p.
-func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	f := *(*float32)(p)
-	if f != 0 || state.sendZero {
-		v := floatBits(float64(f))
-		state.update(i)
-		state.encodeUint(v)
-	}
-}
-
-// encFloat64 encodes the float64 with address p.
-func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	f := *(*float64)(p)
-	if f != 0 || state.sendZero {
-		state.update(i)
-		v := floatBits(f)
-		state.encodeUint(v)
-	}
-}
-
-// encComplex64 encodes the complex64 with address p.
-// Complex numbers are just a pair of floating-point numbers, real part first.
-func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	c := *(*complex64)(p)
-	if c != 0+0i || state.sendZero {
-		rpart := floatBits(float64(real(c)))
-		ipart := floatBits(float64(imag(c)))
-		state.update(i)
-		state.encodeUint(rpart)
-		state.encodeUint(ipart)
-	}
-}
-
-// encComplex128 encodes the complex128 with address p.
-func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	c := *(*complex128)(p)
-	if c != 0+0i || state.sendZero {
-		rpart := floatBits(real(c))
-		ipart := floatBits(imag(c))
-		state.update(i)
-		state.encodeUint(rpart)
-		state.encodeUint(ipart)
-	}
-}
-
-// encUint8Array encodes the byte slice whose header has address p.
-// Byte arrays are encoded as an unsigned count followed by the raw bytes.
-func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	b := *(*[]byte)(p)
-	if len(b) > 0 || state.sendZero {
-		state.update(i)
-		state.encodeUint(uint64(len(b)))
-		state.b.Write(b)
-	}
-}
-
-// encString encodes the string whose header has address p.
-// Strings are encoded as an unsigned count followed by the raw bytes.
-func encString(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	s := *(*string)(p)
-	if len(s) > 0 || state.sendZero {
-		state.update(i)
-		state.encodeUint(uint64(len(s)))
-		state.b.WriteString(s)
-	}
-}
-
-// encStructTerminator encodes the end of an encoded struct
-// as delta field number of 0.
-func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) {
-	state.encodeUint(0)
-}
-
-// Execution engine
-
-// encEngine an array of instructions indexed by field number of the encoding
-// data, typically a struct.  It is executed top to bottom, walking the struct.
-type encEngine struct {
-	instr []encInstr
-}
-
-const singletonField = 0
-
-// encodeSingle encodes a single top-level non-struct value.
-func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) {
-	state := enc.newEncoderState(b)
-	state.fieldnum = singletonField
-	// There is no surrounding struct to frame the transmission, so we must
-	// generate data even if the item is zero.  To do this, set sendZero.
-	state.sendZero = true
-	instr := &engine.instr[singletonField]
-	p := unsafe.Pointer(basep) // offset will be zero
-	if instr.indir > 0 {
-		if p = encIndirect(p, instr.indir); p == nil {
-			return
-		}
-	}
-	instr.op(instr, state, p)
-	enc.freeEncoderState(state)
-}
-
-// encodeStruct encodes a single struct value.
-func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) {
-	state := enc.newEncoderState(b)
-	state.fieldnum = -1
-	for i := 0; i < len(engine.instr); i++ {
-		instr := &engine.instr[i]
-		p := unsafe.Pointer(basep + instr.offset)
-		if instr.indir > 0 {
-			if p = encIndirect(p, instr.indir); p == nil {
-				continue
-			}
-		}
-		instr.op(instr, state, p)
-	}
-	enc.freeEncoderState(state)
-}
-
-// encodeArray encodes the array whose 0th element is at p.
-func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) {
-	state := enc.newEncoderState(b)
-	state.fieldnum = -1
-	state.sendZero = true
-	state.encodeUint(uint64(length))
-	for i := 0; i < length; i++ {
-		elemp := p
-		up := unsafe.Pointer(elemp)
-		if elemIndir > 0 {
-			if up = encIndirect(up, elemIndir); up == nil {
-				errorf("encodeArray: nil element")
-			}
-			elemp = uintptr(up)
-		}
-		op(nil, state, unsafe.Pointer(elemp))
-		p += uintptr(elemWid)
-	}
-	enc.freeEncoderState(state)
-}
-
-// encodeReflectValue is a helper for maps. It encodes the value v.
-func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) {
-	for i := 0; i < indir && v.IsValid(); i++ {
-		v = reflect.Indirect(v)
-	}
-	if !v.IsValid() {
-		errorf("encodeReflectValue: nil element")
-	}
-	op(nil, state, unsafe.Pointer(unsafeAddr(v)))
-}
-
-// encodeMap encodes a map as unsigned count followed by key:value pairs.
-// Because map internals are not exposed, we must use reflection rather than
-// addresses.
-func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) {
-	state := enc.newEncoderState(b)
-	state.fieldnum = -1
-	state.sendZero = true
-	keys := mv.MapKeys()
-	state.encodeUint(uint64(len(keys)))
-	for _, key := range keys {
-		encodeReflectValue(state, key, keyOp, keyIndir)
-		encodeReflectValue(state, mv.MapIndex(key), elemOp, elemIndir)
-	}
-	enc.freeEncoderState(state)
-}
-
-// encodeInterface encodes the interface value iv.
-// To send an interface, we send a string identifying the concrete type, followed
-// by the type identifier (which might require defining that type right now), followed
-// by the concrete value.  A nil value gets sent as the empty string for the name,
-// followed by no value.
-func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
-	state := enc.newEncoderState(b)
-	state.fieldnum = -1
-	state.sendZero = true
-	if iv.IsNil() {
-		state.encodeUint(0)
-		return
-	}
-
-	ut := userType(iv.Elem().Type())
-	name, ok := concreteTypeToName[ut.base]
-	if !ok {
-		errorf("type not registered for interface: %s", ut.base)
-	}
-	// Send the name.
-	state.encodeUint(uint64(len(name)))
-	_, err := state.b.WriteString(name)
-	if err != nil {
-		error(err)
-	}
-	// Define the type id if necessary.
-	enc.sendTypeDescriptor(enc.writer(), state, ut)
-	// Send the type id.
-	enc.sendTypeId(state, ut)
-	// Encode the value into a new buffer.  Any nested type definitions
-	// should be written to b, before the encoded value.
-	enc.pushWriter(b)
-	data := new(bytes.Buffer)
-	enc.encode(data, iv.Elem(), ut)
-	if enc.err != nil {
-		error(enc.err)
-	}
-	enc.popWriter()
-	enc.writeMessage(b, data)
-	if enc.err != nil {
-		error(err)
-	}
-	enc.freeEncoderState(state)
-}
-
-// isZero returns whether the value is the zero of its type.
-func isZero(val reflect.Value) bool {
-	switch val.Kind() {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return val.Len() == 0
-	case reflect.Bool:
-		return !val.Bool()
-	case reflect.Complex64, reflect.Complex128:
-		return val.Complex() == 0
-	case reflect.Chan, reflect.Func, reflect.Ptr:
-		return val.IsNil()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return val.Int() == 0
-	case reflect.Float32, reflect.Float64:
-		return val.Float() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return val.Uint() == 0
-	}
-	panic("unknown type in isZero " + val.Type().String())
-}
-
-// encGobEncoder encodes a value that implements the GobEncoder interface.
-// The data is sent as a byte array.
-func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, v reflect.Value) {
-	// TODO: should we catch panics from the called method?
-	// We know it's a GobEncoder, so just call the method directly.
-	data, err := v.Interface().(GobEncoder).GobEncode()
-	if err != nil {
-		error(err)
-	}
-	state := enc.newEncoderState(b)
-	state.fieldnum = -1
-	state.encodeUint(uint64(len(data)))
-	state.b.Write(data)
-	enc.freeEncoderState(state)
-}
-
-var encOpTable = [...]encOp{
-	reflect.Bool:       encBool,
-	reflect.Int:        encInt,
-	reflect.Int8:       encInt8,
-	reflect.Int16:      encInt16,
-	reflect.Int32:      encInt32,
-	reflect.Int64:      encInt64,
-	reflect.Uint:       encUint,
-	reflect.Uint8:      encUint8,
-	reflect.Uint16:     encUint16,
-	reflect.Uint32:     encUint32,
-	reflect.Uint64:     encUint64,
-	reflect.Uintptr:    encUintptr,
-	reflect.Float32:    encFloat32,
-	reflect.Float64:    encFloat64,
-	reflect.Complex64:  encComplex64,
-	reflect.Complex128: encComplex128,
-	reflect.String:     encString,
-}
-
-// encOpFor returns (a pointer to) the encoding op for the base type under rt and
-// the indirection count to reach it.
-func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) {
-	ut := userType(rt)
-	// If the type implements GobEncoder, we handle it without further processing.
-	if ut.isGobEncoder {
-		return enc.gobEncodeOpFor(ut)
-	}
-	// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
-	// Return the pointer to the op we're already building.
-	if opPtr := inProgress[rt]; opPtr != nil {
-		return opPtr, ut.indir
-	}
-	typ := ut.base
-	indir := ut.indir
-	k := typ.Kind()
-	var op encOp
-	if int(k) < len(encOpTable) {
-		op = encOpTable[k]
-	}
-	if op == nil {
-		inProgress[rt] = &op
-		// Special cases
-		switch t := typ; t.Kind() {
-		case reflect.Slice:
-			if t.Elem().Kind() == reflect.Uint8 {
-				op = encUint8Array
-				break
-			}
-			// Slices have a header; we decode it to find the underlying array.
-			elemOp, indir := enc.encOpFor(t.Elem(), inProgress)
-			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
-				slice := (*reflect.SliceHeader)(p)
-				if !state.sendZero && slice.Len == 0 {
-					return
-				}
-				state.update(i)
-				state.enc.encodeArray(state.b, slice.Data, *elemOp, t.Elem().Size(), indir, int(slice.Len))
-			}
-		case reflect.Array:
-			// True arrays have size in the type.
-			elemOp, indir := enc.encOpFor(t.Elem(), inProgress)
-			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
-				state.update(i)
-				state.enc.encodeArray(state.b, uintptr(p), *elemOp, t.Elem().Size(), indir, t.Len())
-			}
-		case reflect.Map:
-			keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress)
-			elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
-			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
-				// Maps cannot be accessed by moving addresses around the way
-				// that slices etc. can.  We must recover a full reflection value for
-				// the iteration.
-				v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p)))
-				mv := reflect.Indirect(v)
-				// We send zero-length (but non-nil) maps because the
-				// receiver might want to use the map.  (Maps don't use append.)
-				if !state.sendZero && mv.IsNil() {
-					return
-				}
-				state.update(i)
-				state.enc.encodeMap(state.b, mv, *keyOp, *elemOp, keyIndir, elemIndir)
-			}
-		case reflect.Struct:
-			// Generate a closure that calls out to the engine for the nested type.
-			enc.getEncEngine(userType(typ))
-			info := mustGetTypeInfo(typ)
-			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
-				state.update(i)
-				// indirect through info to delay evaluation for recursive structs
-				state.enc.encodeStruct(state.b, info.encoder, uintptr(p))
-			}
-		case reflect.Interface:
-			op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
-				// Interfaces transmit the name and contents of the concrete
-				// value they contain.
-				v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p)))
-				iv := reflect.Indirect(v)
-				if !state.sendZero && (!iv.IsValid() || iv.IsNil()) {
-					return
-				}
-				state.update(i)
-				state.enc.encodeInterface(state.b, iv)
-			}
-		}
-	}
-	if op == nil {
-		errorf("can't happen: encode type %s", rt.String())
-	}
-	return &op, indir
-}
-
-// gobEncodeOpFor returns the op for a type that is known to implement
-// GobEncoder.
-func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
-	rt := ut.user
-	if ut.encIndir == -1 {
-		rt = reflect.PtrTo(rt)
-	} else if ut.encIndir > 0 {
-		for i := int8(0); i < ut.encIndir; i++ {
-			rt = rt.Elem()
-		}
-	}
-	var op encOp
-	op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
-		var v reflect.Value
-		if ut.encIndir == -1 {
-			// Need to climb up one level to turn value into pointer.
-			v = reflect.ValueOf(unsafe.Unreflect(rt, unsafe.Pointer(&p)))
-		} else {
-			v = reflect.ValueOf(unsafe.Unreflect(rt, p))
-		}
-		if !state.sendZero && isZero(v) {
-			return
-		}
-		state.update(i)
-		state.enc.encodeGobEncoder(state.b, v)
-	}
-	return &op, int(ut.encIndir) // encIndir: op will get called with p == address of receiver.
-}
-
-// compileEnc returns the engine to compile the type.
-func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
-	srt := ut.base
-	engine := new(encEngine)
-	seen := make(map[reflect.Type]*encOp)
-	rt := ut.base
-	if ut.isGobEncoder {
-		rt = ut.user
-	}
-	if !ut.isGobEncoder &&
-		srt.Kind() == reflect.Struct {
-		for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ {
-			f := srt.Field(fieldNum)
-			if !isExported(f.Name) {
-				continue
-			}
-			op, indir := enc.encOpFor(f.Type, seen)
-			engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, indir, uintptr(f.Offset)})
-			wireFieldNum++
-		}
-		if srt.NumField() > 0 && len(engine.instr) == 0 {
-			errorf("type %s has no exported fields", rt)
-		}
-		engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, 0, 0})
-	} else {
-		engine.instr = make([]encInstr, 1)
-		op, indir := enc.encOpFor(rt, seen)
-		engine.instr[0] = encInstr{*op, singletonField, indir, 0} // offset is zero
-	}
-	return engine
-}
-
-// getEncEngine returns the engine to compile the type.
-// typeLock must be held (or we're in initialization and guaranteed single-threaded).
-func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine {
-	info, err1 := getTypeInfo(ut)
-	if err1 != nil {
-		error(err1)
-	}
-	if info.encoder == nil {
-		// mark this engine as underway before compiling to handle recursive types.
-		info.encoder = new(encEngine)
-		info.encoder = enc.compileEnc(ut)
-	}
-	return info.encoder
-}
-
-// lockAndGetEncEngine is a function that locks and compiles.
-// This lets us hold the lock only while compiling, not when encoding.
-func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine {
-	typeLock.Lock()
-	defer typeLock.Unlock()
-	return enc.getEncEngine(ut)
-}
-
-func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) {
-	defer catchError(&enc.err)
-	engine := enc.lockAndGetEncEngine(ut)
-	indir := ut.indir
-	if ut.isGobEncoder {
-		indir = int(ut.encIndir)
-	}
-	for i := 0; i < indir; i++ {
-		value = reflect.Indirect(value)
-	}
-	if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct {
-		enc.encodeStruct(b, engine, unsafeAddr(value))
-	} else {
-		enc.encodeSingle(b, engine, unsafeAddr(value))
-	}
-}
diff --git a/src/pkg/gob/encoder.go b/src/pkg/gob/encoder.go
deleted file mode 100644
index 96101d9..0000000
--- a/src/pkg/gob/encoder.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-import (
-	"bytes"
-	"io"
-	"os"
-	"reflect"
-	"sync"
-)
-
-// An Encoder manages the transmission of type and data information to the
-// other side of a connection.
-type Encoder struct {
-	mutex      sync.Mutex              // each item must be sent atomically
-	w          []io.Writer             // where to send the data
-	sent       map[reflect.Type]typeId // which types we've already sent
-	countState *encoderState           // stage for writing counts
-	freeList   *encoderState           // list of free encoderStates; avoids reallocation
-	buf        []byte                  // for collecting the output.
-	byteBuf    bytes.Buffer            // buffer for top-level encoderState
-	err        os.Error
-}
-
-// NewEncoder returns a new encoder that will transmit on the io.Writer.
-func NewEncoder(w io.Writer) *Encoder {
-	enc := new(Encoder)
-	enc.w = []io.Writer{w}
-	enc.sent = make(map[reflect.Type]typeId)
-	enc.countState = enc.newEncoderState(new(bytes.Buffer))
-	return enc
-}
-
-// writer() returns the innermost writer the encoder is using
-func (enc *Encoder) writer() io.Writer {
-	return enc.w[len(enc.w)-1]
-}
-
-// pushWriter adds a writer to the encoder.
-func (enc *Encoder) pushWriter(w io.Writer) {
-	enc.w = append(enc.w, w)
-}
-
-// popWriter pops the innermost writer.
-func (enc *Encoder) popWriter() {
-	enc.w = enc.w[0 : len(enc.w)-1]
-}
-
-func (enc *Encoder) badType(rt reflect.Type) {
-	enc.setError(os.NewError("gob: can't encode type " + rt.String()))
-}
-
-func (enc *Encoder) setError(err os.Error) {
-	if enc.err == nil { // remember the first.
-		enc.err = err
-	}
-}
-
-// writeMessage sends the data item preceded by a unsigned count of its length.
-func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) {
-	enc.countState.encodeUint(uint64(b.Len()))
-	// Build the buffer.
-	countLen := enc.countState.b.Len()
-	total := countLen + b.Len()
-	if total > len(enc.buf) {
-		enc.buf = make([]byte, total+1000) // extra for growth
-	}
-	// Place the length before the data.
-	// TODO(r): avoid the extra copy here.
-	enc.countState.b.Read(enc.buf[0:countLen])
-	// Now the data.
-	b.Read(enc.buf[countLen:total])
-	// Write the data.
-	_, err := w.Write(enc.buf[0:total])
-	if err != nil {
-		enc.setError(err)
-	}
-}
-
-// sendActualType sends the requested type, without further investigation, unless
-// it's been sent before.
-func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) {
-	if _, alreadySent := enc.sent[actual]; alreadySent {
-		return false
-	}
-	typeLock.Lock()
-	info, err := getTypeInfo(ut)
-	typeLock.Unlock()
-	if err != nil {
-		enc.setError(err)
-		return
-	}
-	// Send the pair (-id, type)
-	// Id:
-	state.encodeInt(-int64(info.id))
-	// Type:
-	enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo)
-	enc.writeMessage(w, state.b)
-	if enc.err != nil {
-		return
-	}
-
-	// Remember we've sent this type, both what the user gave us and the base type.
-	enc.sent[ut.base] = info.id
-	if ut.user != ut.base {
-		enc.sent[ut.user] = info.id
-	}
-	// Now send the inner types
-	switch st := actual; st.Kind() {
-	case reflect.Struct:
-		for i := 0; i < st.NumField(); i++ {
-			enc.sendType(w, state, st.Field(i).Type)
-		}
-	case reflect.Array, reflect.Slice:
-		enc.sendType(w, state, st.Elem())
-	case reflect.Map:
-		enc.sendType(w, state, st.Key())
-		enc.sendType(w, state, st.Elem())
-	}
-	return true
-}
-
-// sendType sends the type info to the other side, if necessary. 
-func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
-	ut := userType(origt)
-	if ut.isGobEncoder {
-		// The rules are different: regardless of the underlying type's representation,
-		// we need to tell the other side that this exact type is a GobEncoder.
-		return enc.sendActualType(w, state, ut, ut.user)
-	}
-
-	// It's a concrete value, so drill down to the base type.
-	switch rt := ut.base; rt.Kind() {
-	default:
-		// Basic types and interfaces do not need to be described.
-		return
-	case reflect.Slice:
-		// If it's []uint8, don't send; it's considered basic.
-		if rt.Elem().Kind() == reflect.Uint8 {
-			return
-		}
-		// Otherwise we do send.
-		break
-	case reflect.Array:
-		// arrays must be sent so we know their lengths and element types.
-		break
-	case reflect.Map:
-		// maps must be sent so we know their lengths and key/value types.
-		break
-	case reflect.Struct:
-		// structs must be sent so we know their fields.
-		break
-	case reflect.Chan, reflect.Func:
-		// Probably a bad field in a struct.
-		enc.badType(rt)
-		return
-	}
-
-	return enc.sendActualType(w, state, ut, ut.base)
-}
-
-// Encode transmits the data item represented by the empty interface value,
-// guaranteeing that all necessary type information has been transmitted first.
-func (enc *Encoder) Encode(e interface{}) os.Error {
-	return enc.EncodeValue(reflect.ValueOf(e))
-}
-
-// sendTypeDescriptor makes sure the remote side knows about this type.
-// It will send a descriptor if this is the first time the type has been
-// sent.
-func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) {
-	// Make sure the type is known to the other side.
-	// First, have we already sent this type?
-	rt := ut.base
-	if ut.isGobEncoder {
-		rt = ut.user
-	}
-	if _, alreadySent := enc.sent[rt]; !alreadySent {
-		// No, so send it.
-		sent := enc.sendType(w, state, rt)
-		if enc.err != nil {
-			return
-		}
-		// If the type info has still not been transmitted, it means we have
-		// a singleton basic type (int, []byte etc.) at top level.  We don't
-		// need to send the type info but we do need to update enc.sent.
-		if !sent {
-			typeLock.Lock()
-			info, err := getTypeInfo(ut)
-			typeLock.Unlock()
-			if err != nil {
-				enc.setError(err)
-				return
-			}
-			enc.sent[rt] = info.id
-		}
-	}
-}
-
-// sendTypeId sends the id, which must have already been defined.
-func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
-	// Identify the type of this top-level value.
-	state.encodeInt(int64(enc.sent[ut.base]))
-}
-
-// EncodeValue transmits the data item represented by the reflection value,
-// guaranteeing that all necessary type information has been transmitted first.
-func (enc *Encoder) EncodeValue(value reflect.Value) os.Error {
-	// Make sure we're single-threaded through here, so multiple
-	// goroutines can share an encoder.
-	enc.mutex.Lock()
-	defer enc.mutex.Unlock()
-
-	// Remove any nested writers remaining due to previous errors.
-	enc.w = enc.w[0:1]
-
-	ut, err := validUserType(value.Type())
-	if err != nil {
-		return err
-	}
-
-	enc.err = nil
-	enc.byteBuf.Reset()
-	state := enc.newEncoderState(&enc.byteBuf)
-
-	enc.sendTypeDescriptor(enc.writer(), state, ut)
-	enc.sendTypeId(state, ut)
-	if enc.err != nil {
-		return enc.err
-	}
-
-	// Encode the object.
-	enc.encode(state.b, value, ut)
-	if enc.err == nil {
-		enc.writeMessage(enc.writer(), state.b)
-	}
-
-	enc.freeEncoderState(state)
-	return enc.err
-}
diff --git a/src/pkg/gob/encoder_test.go b/src/pkg/gob/encoder_test.go
deleted file mode 100644
index 79d2897..0000000
--- a/src/pkg/gob/encoder_test.go
+++ /dev/null
@@ -1,630 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"reflect"
-	"strings"
-	"testing"
-)
-
-type ET2 struct {
-	X string
-}
-
-type ET1 struct {
-	A    int
-	Et2  *ET2
-	Next *ET1
-}
-
-// Like ET1 but with a different name for a field
-type ET3 struct {
-	A             int
-	Et2           *ET2
-	DifferentNext *ET1
-}
-
-// Like ET1 but with a different type for a field
-type ET4 struct {
-	A    int
-	Et2  float64
-	Next int
-}
-
-func TestEncoderDecoder(t *testing.T) {
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	et1 := new(ET1)
-	et1.A = 7
-	et1.Et2 = new(ET2)
-	err := enc.Encode(et1)
-	if err != nil {
-		t.Error("encoder fail:", err)
-	}
-	dec := NewDecoder(b)
-	newEt1 := new(ET1)
-	err = dec.Decode(newEt1)
-	if err != nil {
-		t.Fatal("error decoding ET1:", err)
-	}
-
-	if !reflect.DeepEqual(et1, newEt1) {
-		t.Fatalf("invalid data for et1: expected %+v; got %+v", *et1, *newEt1)
-	}
-	if b.Len() != 0 {
-		t.Error("not at eof;", b.Len(), "bytes left")
-	}
-
-	enc.Encode(et1)
-	newEt1 = new(ET1)
-	err = dec.Decode(newEt1)
-	if err != nil {
-		t.Fatal("round 2: error decoding ET1:", err)
-	}
-	if !reflect.DeepEqual(et1, newEt1) {
-		t.Fatalf("round 2: invalid data for et1: expected %+v; got %+v", *et1, *newEt1)
-	}
-	if b.Len() != 0 {
-		t.Error("round 2: not at eof;", b.Len(), "bytes left")
-	}
-
-	// Now test with a running encoder/decoder pair that we recognize a type mismatch.
-	err = enc.Encode(et1)
-	if err != nil {
-		t.Error("round 3: encoder fail:", err)
-	}
-	newEt2 := new(ET2)
-	err = dec.Decode(newEt2)
-	if err == nil {
-		t.Fatal("round 3: expected `bad type' error decoding ET2")
-	}
-}
-
-// Run one value through the encoder/decoder, but use the wrong type.
-// Input is always an ET1; we compare it to whatever is under 'e'.
-func badTypeCheck(e interface{}, shouldFail bool, msg string, t *testing.T) {
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	et1 := new(ET1)
-	et1.A = 7
-	et1.Et2 = new(ET2)
-	err := enc.Encode(et1)
-	if err != nil {
-		t.Error("encoder fail:", err)
-	}
-	dec := NewDecoder(b)
-	err = dec.Decode(e)
-	if shouldFail && err == nil {
-		t.Error("expected error for", msg)
-	}
-	if !shouldFail && err != nil {
-		t.Error("unexpected error for", msg, err)
-	}
-}
-
-// Test that we recognize a bad type the first time.
-func TestWrongTypeDecoder(t *testing.T) {
-	badTypeCheck(new(ET2), true, "no fields in common", t)
-	badTypeCheck(new(ET3), false, "different name of field", t)
-	badTypeCheck(new(ET4), true, "different type of field", t)
-}
-
-func corruptDataCheck(s string, err os.Error, t *testing.T) {
-	b := bytes.NewBufferString(s)
-	dec := NewDecoder(b)
-	err1 := dec.Decode(new(ET2))
-	if err1 != err {
-		t.Errorf("from %q expected error %s; got %s", s, err, err1)
-	}
-}
-
-// Check that we survive bad data.
-func TestBadData(t *testing.T) {
-	corruptDataCheck("", os.EOF, t)
-	corruptDataCheck("\x7Fhi", io.ErrUnexpectedEOF, t)
-	corruptDataCheck("\x03now is the time for all good men", errBadType, t)
-}
-
-// Types not supported by the Encoder.
-var unsupportedValues = []interface{}{
-	make(chan int),
-	func(a int) bool { return true },
-}
-
-func TestUnsupported(t *testing.T) {
-	var b bytes.Buffer
-	enc := NewEncoder(&b)
-	for _, v := range unsupportedValues {
-		err := enc.Encode(v)
-		if err == nil {
-			t.Errorf("expected error for %T; got none", v)
-		}
-	}
-}
-
-func encAndDec(in, out interface{}) os.Error {
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	err := enc.Encode(in)
-	if err != nil {
-		return err
-	}
-	dec := NewDecoder(b)
-	err = dec.Decode(out)
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
-func TestTypeToPtrType(t *testing.T) {
-	// Encode a T, decode a *T
-	type Type0 struct {
-		A int
-	}
-	t0 := Type0{7}
-	t0p := new(Type0)
-	if err := encAndDec(t0, t0p); err != nil {
-		t.Error(err)
-	}
-}
-
-func TestPtrTypeToType(t *testing.T) {
-	// Encode a *T, decode a T
-	type Type1 struct {
-		A uint
-	}
-	t1p := &Type1{17}
-	var t1 Type1
-	if err := encAndDec(t1, t1p); err != nil {
-		t.Error(err)
-	}
-}
-
-func TestTypeToPtrPtrPtrPtrType(t *testing.T) {
-	type Type2 struct {
-		A ****float64
-	}
-	t2 := Type2{}
-	t2.A = new(***float64)
-	*t2.A = new(**float64)
-	**t2.A = new(*float64)
-	***t2.A = new(float64)
-	****t2.A = 27.4
-	t2pppp := new(***Type2)
-	if err := encAndDec(t2, t2pppp); err != nil {
-		t.Fatal(err)
-	}
-	if ****(****t2pppp).A != ****t2.A {
-		t.Errorf("wrong value after decode: %g not %g", ****(****t2pppp).A, ****t2.A)
-	}
-}
-
-func TestSlice(t *testing.T) {
-	type Type3 struct {
-		A []string
-	}
-	t3p := &Type3{[]string{"hello", "world"}}
-	var t3 Type3
-	if err := encAndDec(t3, t3p); err != nil {
-		t.Error(err)
-	}
-}
-
-func TestValueError(t *testing.T) {
-	// Encode a *T, decode a T
-	type Type4 struct {
-		A int
-	}
-	t4p := &Type4{3}
-	var t4 Type4 // note: not a pointer.
-	if err := encAndDec(t4p, t4); err == nil || strings.Index(err.String(), "pointer") < 0 {
-		t.Error("expected error about pointer; got", err)
-	}
-}
-
-func TestArray(t *testing.T) {
-	type Type5 struct {
-		A [3]string
-		B [3]byte
-	}
-	type Type6 struct {
-		A [2]string // can't hold t5.a
-	}
-	t5 := Type5{[3]string{"hello", ",", "world"}, [3]byte{1, 2, 3}}
-	var t5p Type5
-	if err := encAndDec(t5, &t5p); err != nil {
-		t.Error(err)
-	}
-	var t6 Type6
-	if err := encAndDec(t5, &t6); err == nil {
-		t.Error("should fail with mismatched array sizes")
-	}
-}
-
-func TestRecursiveMapType(t *testing.T) {
-	type recursiveMap map[string]recursiveMap
-	r1 := recursiveMap{"A": recursiveMap{"B": nil, "C": nil}, "D": nil}
-	r2 := make(recursiveMap)
-	if err := encAndDec(r1, &r2); err != nil {
-		t.Error(err)
-	}
-}
-
-func TestRecursiveSliceType(t *testing.T) {
-	type recursiveSlice []recursiveSlice
-	r1 := recursiveSlice{0: recursiveSlice{0: nil}, 1: nil}
-	r2 := make(recursiveSlice, 0)
-	if err := encAndDec(r1, &r2); err != nil {
-		t.Error(err)
-	}
-}
-
-// Regression test for bug: must send zero values inside arrays
-func TestDefaultsInArray(t *testing.T) {
-	type Type7 struct {
-		B []bool
-		I []int
-		S []string
-		F []float64
-	}
-	t7 := Type7{
-		[]bool{false, false, true},
-		[]int{0, 0, 1},
-		[]string{"hi", "", "there"},
-		[]float64{0, 0, 1},
-	}
-	var t7p Type7
-	if err := encAndDec(t7, &t7p); err != nil {
-		t.Error(err)
-	}
-}
-
-var testInt int
-var testFloat32 float32
-var testString string
-var testSlice []string
-var testMap map[string]int
-var testArray [7]int
-
-type SingleTest struct {
-	in  interface{}
-	out interface{}
-	err string
-}
-
-var singleTests = []SingleTest{
-	{17, &testInt, ""},
-	{float32(17.5), &testFloat32, ""},
-	{"bike shed", &testString, ""},
-	{[]string{"bike", "shed", "paint", "color"}, &testSlice, ""},
-	{map[string]int{"seven": 7, "twelve": 12}, &testMap, ""},
-	{[7]int{4, 55, 0, 0, 0, 0, 0}, &testArray, ""}, // case that once triggered a bug
-	{[7]int{4, 55, 1, 44, 22, 66, 1234}, &testArray, ""},
-
-	// Decode errors
-	{172, &testFloat32, "wrong type"},
-}
-
-func TestSingletons(t *testing.T) {
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	dec := NewDecoder(b)
-	for _, test := range singleTests {
-		b.Reset()
-		err := enc.Encode(test.in)
-		if err != nil {
-			t.Errorf("error encoding %v: %s", test.in, err)
-			continue
-		}
-		err = dec.Decode(test.out)
-		switch {
-		case err != nil && test.err == "":
-			t.Errorf("error decoding %v: %s", test.in, err)
-			continue
-		case err == nil && test.err != "":
-			t.Errorf("expected error decoding %v: %s", test.in, test.err)
-			continue
-		case err != nil && test.err != "":
-			if strings.Index(err.String(), test.err) < 0 {
-				t.Errorf("wrong error decoding %v: wanted %s, got %v", test.in, test.err, err)
-			}
-			continue
-		}
-		// Get rid of the pointer in the rhs
-		val := reflect.ValueOf(test.out).Elem().Interface()
-		if !reflect.DeepEqual(test.in, val) {
-			t.Errorf("decoding singleton: expected %v got %v", test.in, val)
-		}
-	}
-}
-
-func TestStructNonStruct(t *testing.T) {
-	type Struct struct {
-		A string
-	}
-	type NonStruct string
-	s := Struct{"hello"}
-	var sp Struct
-	if err := encAndDec(s, &sp); err != nil {
-		t.Error(err)
-	}
-	var ns NonStruct
-	if err := encAndDec(s, &ns); err == nil {
-		t.Error("should get error for struct/non-struct")
-	} else if strings.Index(err.String(), "type") < 0 {
-		t.Error("for struct/non-struct expected type error; got", err)
-	}
-	// Now try the other way
-	var nsp NonStruct
-	if err := encAndDec(ns, &nsp); err != nil {
-		t.Error(err)
-	}
-	if err := encAndDec(ns, &s); err == nil {
-		t.Error("should get error for non-struct/struct")
-	} else if strings.Index(err.String(), "type") < 0 {
-		t.Error("for non-struct/struct expected type error; got", err)
-	}
-}
-
-type interfaceIndirectTestI interface {
-	F() bool
-}
-
-type interfaceIndirectTestT struct{}
-
-func (this *interfaceIndirectTestT) F() bool {
-	return true
-}
-
-// A version of a bug reported on golang-nuts.  Also tests top-level
-// slice of interfaces.  The issue was registering *T caused T to be
-// stored as the concrete type.
-func TestInterfaceIndirect(t *testing.T) {
-	Register(&interfaceIndirectTestT{})
-	b := new(bytes.Buffer)
-	w := []interfaceIndirectTestI{&interfaceIndirectTestT{}}
-	err := NewEncoder(b).Encode(w)
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-
-	var r []interfaceIndirectTestI
-	err = NewDecoder(b).Decode(&r)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-}
-
-// Now follow various tests that decode into things that can't represent the
-// encoded value, all of which should be legal.
-
-// Also, when the ignored object contains an interface value, it may define
-// types. Make sure that skipping the value still defines the types by using
-// the encoder/decoder pair to send a value afterwards.  If an interface
-// is sent, its type in the test is always NewType0, so this checks that the
-// encoder and decoder don't skew with respect to type definitions.
-
-type Struct0 struct {
-	I interface{}
-}
-
-type NewType0 struct {
-	S string
-}
-
-type ignoreTest struct {
-	in, out interface{}
-}
-
-var ignoreTests = []ignoreTest{
-	// Decode normal struct into an empty struct
-	{&struct{ A int }{23}, &struct{}{}},
-	// Decode normal struct into a nil.
-	{&struct{ A int }{23}, nil},
-	// Decode singleton string into a nil.
-	{"hello, world", nil},
-	// Decode singleton slice into a nil.
-	{[]int{1, 2, 3, 4}, nil},
-	// Decode struct containing an interface into a nil.
-	{&Struct0{&NewType0{"value0"}}, nil},
-	// Decode singleton slice of interfaces into a nil.
-	{[]interface{}{"hi", &NewType0{"value1"}, 23}, nil},
-}
-
-func TestDecodeIntoNothing(t *testing.T) {
-	Register(new(NewType0))
-	for i, test := range ignoreTests {
-		b := new(bytes.Buffer)
-		enc := NewEncoder(b)
-		err := enc.Encode(test.in)
-		if err != nil {
-			t.Errorf("%d: encode error %s:", i, err)
-			continue
-		}
-		dec := NewDecoder(b)
-		err = dec.Decode(test.out)
-		if err != nil {
-			t.Errorf("%d: decode error: %s", i, err)
-			continue
-		}
-		// Now see if the encoder and decoder are in a consistent state.
-		str := fmt.Sprintf("Value %d", i)
-		err = enc.Encode(&NewType0{str})
-		if err != nil {
-			t.Fatalf("%d: NewType0 encode error: %s", i, err)
-		}
-		ns := new(NewType0)
-		err = dec.Decode(ns)
-		if err != nil {
-			t.Fatalf("%d: NewType0 decode error: %s", i, err)
-		}
-		if ns.S != str {
-			t.Fatalf("%d: expected %q got %q", i, str, ns.S)
-		}
-	}
-}
-
-// Another bug from golang-nuts, involving nested interfaces.
-type Bug0Outer struct {
-	Bug0Field interface{}
-}
-
-type Bug0Inner struct {
-	A int
-}
-
-func TestNestedInterfaces(t *testing.T) {
-	var buf bytes.Buffer
-	e := NewEncoder(&buf)
-	d := NewDecoder(&buf)
-	Register(new(Bug0Outer))
-	Register(new(Bug0Inner))
-	f := &Bug0Outer{&Bug0Outer{&Bug0Inner{7}}}
-	var v interface{} = f
-	err := e.Encode(&v)
-	if err != nil {
-		t.Fatal("Encode:", err)
-	}
-	err = d.Decode(&v)
-	if err != nil {
-		t.Fatal("Decode:", err)
-	}
-	// Make sure it decoded correctly.
-	outer1, ok := v.(*Bug0Outer)
-	if !ok {
-		t.Fatalf("v not Bug0Outer: %T", v)
-	}
-	outer2, ok := outer1.Bug0Field.(*Bug0Outer)
-	if !ok {
-		t.Fatalf("v.Bug0Field not Bug0Outer: %T", outer1.Bug0Field)
-	}
-	inner, ok := outer2.Bug0Field.(*Bug0Inner)
-	if !ok {
-		t.Fatalf("v.Bug0Field.Bug0Field not Bug0Inner: %T", outer2.Bug0Field)
-	}
-	if inner.A != 7 {
-		t.Fatalf("final value %d; expected %d", inner.A, 7)
-	}
-}
-
-// The bugs keep coming. We forgot to send map subtypes before the map.
-
-type Bug1Elem struct {
-	Name string
-	Id   int
-}
-
-type Bug1StructMap map[string]Bug1Elem
-
-func bug1EncDec(in Bug1StructMap, out *Bug1StructMap) os.Error {
-	return nil
-}
-
-func TestMapBug1(t *testing.T) {
-	in := make(Bug1StructMap)
-	in["val1"] = Bug1Elem{"elem1", 1}
-	in["val2"] = Bug1Elem{"elem2", 2}
-
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	err := enc.Encode(in)
-	if err != nil {
-		t.Fatal("encode:", err)
-	}
-	dec := NewDecoder(b)
-	out := make(Bug1StructMap)
-	err = dec.Decode(&out)
-	if err != nil {
-		t.Fatal("decode:", err)
-	}
-	if !reflect.DeepEqual(in, out) {
-		t.Errorf("mismatch: %v %v", in, out)
-	}
-}
-
-func TestGobMapInterfaceEncode(t *testing.T) {
-	m := map[string]interface{}{
-		"up": uintptr(0),
-		"i0": []int{-1},
-		"i1": []int8{-1},
-		"i2": []int16{-1},
-		"i3": []int32{-1},
-		"i4": []int64{-1},
-		"u0": []uint{1},
-		"u1": []uint8{1},
-		"u2": []uint16{1},
-		"u3": []uint32{1},
-		"u4": []uint64{1},
-		"f0": []float32{1},
-		"f1": []float64{1},
-		"c0": []complex64{complex(2, -2)},
-		"c1": []complex128{complex(2, float64(-2))},
-		"us": []uintptr{0},
-		"bo": []bool{false},
-		"st": []string{"s"},
-	}
-	buf := bytes.NewBuffer(nil)
-	enc := NewEncoder(buf)
-	err := enc.Encode(m)
-	if err != nil {
-		t.Errorf("encode map: %s", err)
-	}
-}
-
-func TestSliceReusesMemory(t *testing.T) {
-	buf := bytes.NewBuffer(nil)
-	// Bytes
-	{
-		x := []byte("abcd")
-		enc := NewEncoder(buf)
-		err := enc.Encode(x)
-		if err != nil {
-			t.Errorf("bytes: encode: %s", err)
-		}
-		// Decode into y, which is big enough.
-		y := []byte("ABCDE")
-		addr := &y[0]
-		dec := NewDecoder(buf)
-		err = dec.Decode(&y)
-		if err != nil {
-			t.Fatal("bytes: decode:", err)
-		}
-		if !bytes.Equal(x, y) {
-			t.Errorf("bytes: expected %q got %q\n", x, y)
-		}
-		if addr != &y[0] {
-			t.Errorf("bytes: unnecessary reallocation")
-		}
-	}
-	// general slice
-	{
-		x := []int("abcd")
-		enc := NewEncoder(buf)
-		err := enc.Encode(x)
-		if err != nil {
-			t.Errorf("ints: encode: %s", err)
-		}
-		// Decode into y, which is big enough.
-		y := []int("ABCDE")
-		addr := &y[0]
-		dec := NewDecoder(buf)
-		err = dec.Decode(&y)
-		if err != nil {
-			t.Fatal("ints: decode:", err)
-		}
-		if !reflect.DeepEqual(x, y) {
-			t.Errorf("ints: expected %q got %q\n", x, y)
-		}
-		if addr != &y[0] {
-			t.Errorf("ints: unnecessary reallocation")
-		}
-	}
-}
diff --git a/src/pkg/gob/error.go b/src/pkg/gob/error.go
deleted file mode 100644
index bfd38fc..0000000
--- a/src/pkg/gob/error.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-import (
-	"fmt"
-	"os"
-)
-
-// Errors in decoding and encoding are handled using panic and recover.
-// Panics caused by user error (that is, everything except run-time panics
-// such as "index out of bounds" errors) do not leave the file that caused
-// them, but are instead turned into plain os.Error returns.  Encoding and
-// decoding functions and methods that do not return an os.Error either use
-// panic to report an error or are guaranteed error-free.
-
-// A gobError wraps an os.Error and is used to distinguish errors (panics) generated in this package.
-type gobError struct {
-	os.Error
-}
-
-// errorf is like error but takes Printf-style arguments to construct an os.Error.
-// It always prefixes the message with "gob: ".
-func errorf(format string, args ...interface{}) {
-	error(fmt.Errorf("gob: "+format, args...))
-}
-
-// error wraps the argument error and uses it as the argument to panic.
-func error(err os.Error) {
-	panic(gobError{Error: err})
-}
-
-// catchError is meant to be used as a deferred function to turn a panic(gobError) into a
-// plain os.Error.  It overwrites the error return of the function that deferred its call.
-func catchError(err *os.Error) {
-	if e := recover(); e != nil {
-		*err = e.(gobError).Error // Will re-panic if not one of our errors, such as a runtime error.
-	}
-	return
-}
diff --git a/src/pkg/gob/gobencdec_test.go b/src/pkg/gob/gobencdec_test.go
deleted file mode 100644
index 01addbe..0000000
--- a/src/pkg/gob/gobencdec_test.go
+++ /dev/null
@@ -1,527 +0,0 @@
-// Copyright 20011 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 file contains tests of the GobEncoder/GobDecoder support.
-
-package gob
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"strings"
-	"testing"
-)
-
-// Types that implement the GobEncoder/Decoder interfaces.
-
-type ByteStruct struct {
-	a byte // not an exported field
-}
-
-type StringStruct struct {
-	s string // not an exported field
-}
-
-type ArrayStruct struct {
-	a [8192]byte // not an exported field
-}
-
-type Gobber int
-
-type ValueGobber string // encodes with a value, decodes with a pointer.
-
-// The relevant methods
-
-func (g *ByteStruct) GobEncode() ([]byte, os.Error) {
-	b := make([]byte, 3)
-	b[0] = g.a
-	b[1] = g.a + 1
-	b[2] = g.a + 2
-	return b, nil
-}
-
-func (g *ByteStruct) GobDecode(data []byte) os.Error {
-	if g == nil {
-		return os.NewError("NIL RECEIVER")
-	}
-	// Expect N sequential-valued bytes.
-	if len(data) == 0 {
-		return os.EOF
-	}
-	g.a = data[0]
-	for i, c := range data {
-		if c != g.a+byte(i) {
-			return os.NewError("invalid data sequence")
-		}
-	}
-	return nil
-}
-
-func (g *StringStruct) GobEncode() ([]byte, os.Error) {
-	return []byte(g.s), nil
-}
-
-func (g *StringStruct) GobDecode(data []byte) os.Error {
-	// Expect N sequential-valued bytes.
-	if len(data) == 0 {
-		return os.EOF
-	}
-	a := data[0]
-	for i, c := range data {
-		if c != a+byte(i) {
-			return os.NewError("invalid data sequence")
-		}
-	}
-	g.s = string(data)
-	return nil
-}
-
-func (a *ArrayStruct) GobEncode() ([]byte, os.Error) {
-	return a.a[:], nil
-}
-
-func (a *ArrayStruct) GobDecode(data []byte) os.Error {
-	if len(data) != len(a.a) {
-		return os.NewError("wrong length in array decode")
-	}
-	copy(a.a[:], data)
-	return nil
-}
-
-func (g *Gobber) GobEncode() ([]byte, os.Error) {
-	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
-}
-
-func (g *Gobber) GobDecode(data []byte) os.Error {
-	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
-	return err
-}
-
-func (v ValueGobber) GobEncode() ([]byte, os.Error) {
-	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
-}
-
-func (v *ValueGobber) GobDecode(data []byte) os.Error {
-	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
-	return err
-}
-
-// Structs that include GobEncodable fields.
-
-type GobTest0 struct {
-	X int // guarantee we have  something in common with GobTest*
-	G *ByteStruct
-}
-
-type GobTest1 struct {
-	X int // guarantee we have  something in common with GobTest*
-	G *StringStruct
-}
-
-type GobTest2 struct {
-	X int    // guarantee we have  something in common with GobTest*
-	G string // not a GobEncoder - should give us errors
-}
-
-type GobTest3 struct {
-	X int // guarantee we have  something in common with GobTest*
-	G *Gobber
-}
-
-type GobTest4 struct {
-	X int // guarantee we have  something in common with GobTest*
-	V ValueGobber
-}
-
-type GobTest5 struct {
-	X int // guarantee we have  something in common with GobTest*
-	V *ValueGobber
-}
-
-type GobTestIgnoreEncoder struct {
-	X int // guarantee we have  something in common with GobTest*
-}
-
-type GobTestValueEncDec struct {
-	X int          // guarantee we have  something in common with GobTest*
-	G StringStruct // not a pointer.
-}
-
-type GobTestIndirectEncDec struct {
-	X int             // guarantee we have  something in common with GobTest*
-	G ***StringStruct // indirections to the receiver.
-}
-
-type GobTestArrayEncDec struct {
-	X int         // guarantee we have  something in common with GobTest*
-	A ArrayStruct // not a pointer.
-}
-
-type GobTestIndirectArrayEncDec struct {
-	X int            // guarantee we have  something in common with GobTest*
-	A ***ArrayStruct // indirections to a large receiver.
-}
-
-func TestGobEncoderField(t *testing.T) {
-	b := new(bytes.Buffer)
-	// First a field that's a structure.
-	enc := NewEncoder(b)
-	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTest0)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if x.G.a != 'A' {
-		t.Errorf("expected 'A' got %c", x.G.a)
-	}
-	// Now a field that's not a structure.
-	b.Reset()
-	gobber := Gobber(23)
-	err = enc.Encode(GobTest3{17, &gobber})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	y := new(GobTest3)
-	err = dec.Decode(y)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if *y.G != 23 {
-		t.Errorf("expected '23 got %d", *y.G)
-	}
-}
-
-// Even though the field is a value, we can still take its address
-// and should be able to call the methods.
-func TestGobEncoderValueField(t *testing.T) {
-	b := new(bytes.Buffer)
-	// First a field that's a structure.
-	enc := NewEncoder(b)
-	err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTestValueEncDec)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if x.G.s != "HIJKL" {
-		t.Errorf("expected `HIJKL` got %s", x.G.s)
-	}
-}
-
-// GobEncode/Decode should work even if the value is
-// more indirect than the receiver.
-func TestGobEncoderIndirectField(t *testing.T) {
-	b := new(bytes.Buffer)
-	// First a field that's a structure.
-	enc := NewEncoder(b)
-	s := &StringStruct{"HIJKL"}
-	sp := &s
-	err := enc.Encode(GobTestIndirectEncDec{17, &sp})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTestIndirectEncDec)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if (***x.G).s != "HIJKL" {
-		t.Errorf("expected `HIJKL` got %s", (***x.G).s)
-	}
-}
-
-// Test with a large field with methods.
-func TestGobEncoderArrayField(t *testing.T) {
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	var a GobTestArrayEncDec
-	a.X = 17
-	for i := range a.A.a {
-		a.A.a[i] = byte(i)
-	}
-	err := enc.Encode(a)
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTestArrayEncDec)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	for i, v := range x.A.a {
-		if v != byte(i) {
-			t.Errorf("expected %x got %x", byte(i), v)
-			break
-		}
-	}
-}
-
-// Test an indirection to a large field with methods.
-func TestGobEncoderIndirectArrayField(t *testing.T) {
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	var a GobTestIndirectArrayEncDec
-	a.X = 17
-	var array ArrayStruct
-	ap := &array
-	app := &ap
-	a.A = &app
-	for i := range array.a {
-		array.a[i] = byte(i)
-	}
-	err := enc.Encode(a)
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTestIndirectArrayEncDec)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	for i, v := range (***x.A).a {
-		if v != byte(i) {
-			t.Errorf("expected %x got %x", byte(i), v)
-			break
-		}
-	}
-}
-
-// As long as the fields have the same name and implement the
-// interface, we can cross-connect them.  Not sure it's useful
-// and may even be bad but it works and it's hard to prevent
-// without exposing the contents of the object, which would
-// defeat the purpose.
-func TestGobEncoderFieldsOfDifferentType(t *testing.T) {
-	// first, string in field to byte in field
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTest0)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if x.G.a != 'A' {
-		t.Errorf("expected 'A' got %c", x.G.a)
-	}
-	// now the other direction, byte in field to string in field
-	b.Reset()
-	err = enc.Encode(GobTest0{17, &ByteStruct{'X'}})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	y := new(GobTest1)
-	err = dec.Decode(y)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if y.G.s != "XYZ" {
-		t.Fatalf("expected `XYZ` got %c", y.G.s)
-	}
-}
-
-// Test that we can encode a value and decode into a pointer.
-func TestGobEncoderValueEncoder(t *testing.T) {
-	// first, string in field to byte in field
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	err := enc.Encode(GobTest4{17, ValueGobber("hello")})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTest5)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if *x.V != "hello" {
-		t.Errorf("expected `hello` got %s", x.V)
-	}
-}
-
-func TestGobEncoderFieldTypeError(t *testing.T) {
-	// GobEncoder to non-decoder: error
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := &GobTest2{}
-	err = dec.Decode(x)
-	if err == nil {
-		t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
-	}
-	if strings.Index(err.String(), "type") < 0 {
-		t.Fatal("expected type error; got", err)
-	}
-	// Non-encoder to GobDecoder: error
-	b.Reset()
-	err = enc.Encode(GobTest2{17, "ABC"})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	y := &GobTest1{}
-	err = dec.Decode(y)
-	if err == nil {
-		t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
-	}
-	if strings.Index(err.String(), "type") < 0 {
-		t.Fatal("expected type error; got", err)
-	}
-}
-
-// Even though ByteStruct is a struct, it's treated as a singleton at the top level.
-func TestGobEncoderStructSingleton(t *testing.T) {
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	err := enc.Encode(&ByteStruct{'A'})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(ByteStruct)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if x.a != 'A' {
-		t.Errorf("expected 'A' got %c", x.a)
-	}
-}
-
-func TestGobEncoderNonStructSingleton(t *testing.T) {
-	b := new(bytes.Buffer)
-	enc := NewEncoder(b)
-	err := enc.Encode(Gobber(1234))
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	var x Gobber
-	err = dec.Decode(&x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if x != 1234 {
-		t.Errorf("expected 1234 got %d", x)
-	}
-}
-
-func TestGobEncoderIgnoreStructField(t *testing.T) {
-	b := new(bytes.Buffer)
-	// First a field that's a structure.
-	enc := NewEncoder(b)
-	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTestIgnoreEncoder)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if x.X != 17 {
-		t.Errorf("expected 17 got %c", x.X)
-	}
-}
-
-func TestGobEncoderIgnoreNonStructField(t *testing.T) {
-	b := new(bytes.Buffer)
-	// First a field that's a structure.
-	enc := NewEncoder(b)
-	gobber := Gobber(23)
-	err := enc.Encode(GobTest3{17, &gobber})
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTestIgnoreEncoder)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if x.X != 17 {
-		t.Errorf("expected 17 got %c", x.X)
-	}
-}
-
-func TestGobEncoderIgnoreNilEncoder(t *testing.T) {
-	b := new(bytes.Buffer)
-	// First a field that's a structure.
-	enc := NewEncoder(b)
-	err := enc.Encode(GobTest0{X: 18}) // G is nil
-	if err != nil {
-		t.Fatal("encode error:", err)
-	}
-	dec := NewDecoder(b)
-	x := new(GobTest0)
-	err = dec.Decode(x)
-	if err != nil {
-		t.Fatal("decode error:", err)
-	}
-	if x.X != 18 {
-		t.Errorf("expected x.X = 18, got %v", x.X)
-	}
-	if x.G != nil {
-		t.Errorf("expected x.G = nil, got %v", x.G)
-	}
-}
-
-type gobDecoderBug0 struct {
-	foo, bar string
-}
-
-func (br *gobDecoderBug0) String() string {
-	return br.foo + "-" + br.bar
-}
-
-func (br *gobDecoderBug0) GobEncode() ([]byte, os.Error) {
-	return []byte(br.String()), nil
-}
-
-func (br *gobDecoderBug0) GobDecode(b []byte) os.Error {
-	br.foo = "foo"
-	br.bar = "bar"
-	return nil
-}
-
-// This was a bug: the receiver has a different indirection level
-// than the variable.
-func TestGobEncoderExtraIndirect(t *testing.T) {
-	gdb := &gobDecoderBug0{"foo", "bar"}
-	buf := new(bytes.Buffer)
-	e := NewEncoder(buf)
-	if err := e.Encode(gdb); err != nil {
-		t.Fatalf("encode: %v", err)
-	}
-	d := NewDecoder(buf)
-	var got *gobDecoderBug0
-	if err := d.Decode(&got); err != nil {
-		t.Fatalf("decode: %v", err)
-	}
-	if got.foo != gdb.foo || got.bar != gdb.bar {
-		t.Errorf("got = %q, want %q", got, gdb)
-	}
-}
diff --git a/src/pkg/gob/timing_test.go b/src/pkg/gob/timing_test.go
deleted file mode 100644
index 2a2be73..0000000
--- a/src/pkg/gob/timing_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2011 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 gob
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"runtime"
-	"testing"
-)
-
-type Bench struct {
-	A int
-	B float64
-	C string
-	D []byte
-}
-
-func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) {
-	b.StopTimer()
-	enc := NewEncoder(w)
-	dec := NewDecoder(r)
-	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
-	b.StartTimer()
-	for i := 0; i < b.N; i++ {
-		if enc.Encode(bench) != nil {
-			panic("encode error")
-		}
-		if dec.Decode(bench) != nil {
-			panic("decode error")
-		}
-	}
-}
-
-func BenchmarkEndToEndPipe(b *testing.B) {
-	r, w, err := os.Pipe()
-	if err != nil {
-		panic("can't get pipe:" + err.String())
-	}
-	benchmarkEndToEnd(r, w, b)
-}
-
-func BenchmarkEndToEndByteBuffer(b *testing.B) {
-	var buf bytes.Buffer
-	benchmarkEndToEnd(&buf, &buf, b)
-}
-
-func TestCountEncodeMallocs(t *testing.T) {
-	var buf bytes.Buffer
-	enc := NewEncoder(&buf)
-	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
-	runtime.UpdateMemStats()
-	mallocs := 0 - runtime.MemStats.Mallocs
-	const count = 1000
-	for i := 0; i < count; i++ {
-		err := enc.Encode(bench)
-		if err != nil {
-			t.Fatal("encode:", err)
-		}
-	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count)
-}
-
-func TestCountDecodeMallocs(t *testing.T) {
-	var buf bytes.Buffer
-	enc := NewEncoder(&buf)
-	bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
-	const count = 1000
-	for i := 0; i < count; i++ {
-		err := enc.Encode(bench)
-		if err != nil {
-			t.Fatal("encode:", err)
-		}
-	}
-	dec := NewDecoder(&buf)
-	runtime.UpdateMemStats()
-	mallocs := 0 - runtime.MemStats.Mallocs
-	for i := 0; i < count; i++ {
-		*bench = Bench{}
-		err := dec.Decode(&bench)
-		if err != nil {
-			t.Fatal("decode:", err)
-		}
-	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count)
-}
diff --git a/src/pkg/gob/type.go b/src/pkg/gob/type.go
deleted file mode 100644
index b2f716c..0000000
--- a/src/pkg/gob/type.go
+++ /dev/null
@@ -1,786 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-import (
-	"fmt"
-	"os"
-	"reflect"
-	"sync"
-	"unicode"
-	"utf8"
-)
-
-// userTypeInfo stores the information associated with a type the user has handed
-// to the package.  It's computed once and stored in a map keyed by reflection
-// type.
-type userTypeInfo struct {
-	user         reflect.Type // the type the user handed us
-	base         reflect.Type // the base type after all indirections
-	indir        int          // number of indirections to reach the base type
-	isGobEncoder bool         // does the type implement GobEncoder?
-	isGobDecoder bool         // does the type implement GobDecoder?
-	encIndir     int8         // number of indirections to reach the receiver type; may be negative
-	decIndir     int8         // number of indirections to reach the receiver type; may be negative
-}
-
-var (
-	// Protected by an RWMutex because we read it a lot and write
-	// it only when we see a new type, typically when compiling.
-	userTypeLock  sync.RWMutex
-	userTypeCache = make(map[reflect.Type]*userTypeInfo)
-)
-
-// validType returns, and saves, the information associated with user-provided type rt.
-// If the user type is not valid, err will be non-nil.  To be used when the error handler
-// is not set up.
-func validUserType(rt reflect.Type) (ut *userTypeInfo, err os.Error) {
-	userTypeLock.RLock()
-	ut = userTypeCache[rt]
-	userTypeLock.RUnlock()
-	if ut != nil {
-		return
-	}
-	// Now set the value under the write lock.
-	userTypeLock.Lock()
-	defer userTypeLock.Unlock()
-	if ut = userTypeCache[rt]; ut != nil {
-		// Lost the race; not a problem.
-		return
-	}
-	ut = new(userTypeInfo)
-	ut.base = rt
-	ut.user = rt
-	// A type that is just a cycle of pointers (such as type T *T) cannot
-	// be represented in gobs, which need some concrete data.  We use a
-	// cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6,
-	// pp 539-540.  As we step through indirections, run another type at
-	// half speed. If they meet up, there's a cycle.
-	slowpoke := ut.base // walks half as fast as ut.base
-	for {
-		pt := ut.base
-		if pt.Kind() != reflect.Ptr {
-			break
-		}
-		ut.base = pt.Elem()
-		if ut.base == slowpoke { // ut.base lapped slowpoke
-			// recursive pointer type.
-			return nil, os.NewError("can't represent recursive pointer type " + ut.base.String())
-		}
-		if ut.indir%2 == 0 {
-			slowpoke = slowpoke.Elem()
-		}
-		ut.indir++
-	}
-	ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType)
-	ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType)
-	userTypeCache[rt] = ut
-	return
-}
-
-var (
-	gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem()
-	gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem()
-)
-
-// implementsInterface reports whether the type implements the
-// gobEncoder/gobDecoder interface.
-// It also returns the number of indirections required to get to the
-// implementation.
-func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) {
-	if typ == nil {
-		return
-	}
-	rt := typ
-	// The type might be a pointer and we need to keep
-	// dereferencing to the base type until we find an implementation.
-	for {
-		if rt.Implements(gobEncDecType) {
-			return true, indir
-		}
-		if p := rt; p.Kind() == reflect.Ptr {
-			indir++
-			if indir > 100 { // insane number of indirections
-				return false, 0
-			}
-			rt = p.Elem()
-			continue
-		}
-		break
-	}
-	// No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
-	if typ.Kind() != reflect.Ptr {
-		// Not a pointer, but does the pointer work?
-		if reflect.PtrTo(typ).Implements(gobEncDecType) {
-			return true, -1
-		}
-	}
-	return false, 0
-}
-
-// userType returns, and saves, the information associated with user-provided type rt.
-// If the user type is not valid, it calls error.
-func userType(rt reflect.Type) *userTypeInfo {
-	ut, err := validUserType(rt)
-	if err != nil {
-		error(err)
-	}
-	return ut
-}
-// A typeId represents a gob Type as an integer that can be passed on the wire.
-// Internally, typeIds are used as keys to a map to recover the underlying type info.
-type typeId int32
-
-var nextId typeId       // incremented for each new type we build
-var typeLock sync.Mutex // set while building a type
-const firstUserId = 64  // lowest id number granted to user
-
-type gobType interface {
-	id() typeId
-	setId(id typeId)
-	name() string
-	string() string // not public; only for debugging
-	safeString(seen map[typeId]bool) string
-}
-
-var types = make(map[reflect.Type]gobType)
-var idToType = make(map[typeId]gobType)
-var builtinIdToType map[typeId]gobType // set in init() after builtins are established
-
-func setTypeId(typ gobType) {
-	nextId++
-	typ.setId(nextId)
-	idToType[nextId] = typ
-}
-
-func (t typeId) gobType() gobType {
-	if t == 0 {
-		return nil
-	}
-	return idToType[t]
-}
-
-// string returns the string representation of the type associated with the typeId.
-func (t typeId) string() string {
-	if t.gobType() == nil {
-		return "<nil>"
-	}
-	return t.gobType().string()
-}
-
-// Name returns the name of the type associated with the typeId.
-func (t typeId) name() string {
-	if t.gobType() == nil {
-		return "<nil>"
-	}
-	return t.gobType().name()
-}
-
-// Common elements of all types.
-type CommonType struct {
-	Name string
-	Id   typeId
-}
-
-func (t *CommonType) id() typeId { return t.Id }
-
-func (t *CommonType) setId(id typeId) { t.Id = id }
-
-func (t *CommonType) string() string { return t.Name }
-
-func (t *CommonType) safeString(seen map[typeId]bool) string {
-	return t.Name
-}
-
-func (t *CommonType) name() string { return t.Name }
-
-// Create and check predefined types
-// The string for tBytes is "bytes" not "[]byte" to signify its specialness.
-
-var (
-	// Primordial types, needed during initialization.
-	// Always passed as pointers so the interface{} type
-	// goes through without losing its interfaceness.
-	tBool      = bootstrapType("bool", (*bool)(nil), 1)
-	tInt       = bootstrapType("int", (*int)(nil), 2)
-	tUint      = bootstrapType("uint", (*uint)(nil), 3)
-	tFloat     = bootstrapType("float", (*float64)(nil), 4)
-	tBytes     = bootstrapType("bytes", (*[]byte)(nil), 5)
-	tString    = bootstrapType("string", (*string)(nil), 6)
-	tComplex   = bootstrapType("complex", (*complex128)(nil), 7)
-	tInterface = bootstrapType("interface", (*interface{})(nil), 8)
-	// Reserve some Ids for compatible expansion
-	tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9)
-	tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10)
-	tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11)
-	tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12)
-	tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13)
-	tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14)
-	tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15)
-)
-
-// Predefined because it's needed by the Decoder
-var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
-var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType)
-
-func init() {
-	// Some magic numbers to make sure there are no surprises.
-	checkId(16, tWireType)
-	checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
-	checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
-	checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
-	checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
-	checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
-	checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)
-
-	builtinIdToType = make(map[typeId]gobType)
-	for k, v := range idToType {
-		builtinIdToType[k] = v
-	}
-
-	// Move the id space upwards to allow for growth in the predefined world
-	// without breaking existing files.
-	if nextId > firstUserId {
-		panic(fmt.Sprintln("nextId too large:", nextId))
-	}
-	nextId = firstUserId
-	registerBasics()
-	wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
-}
-
-// Array type
-type arrayType struct {
-	CommonType
-	Elem typeId
-	Len  int
-}
-
-func newArrayType(name string) *arrayType {
-	a := &arrayType{CommonType{Name: name}, 0, 0}
-	return a
-}
-
-func (a *arrayType) init(elem gobType, len int) {
-	// Set our type id before evaluating the element's, in case it's our own.
-	setTypeId(a)
-	a.Elem = elem.id()
-	a.Len = len
-}
-
-func (a *arrayType) safeString(seen map[typeId]bool) string {
-	if seen[a.Id] {
-		return a.Name
-	}
-	seen[a.Id] = true
-	return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen))
-}
-
-func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) }
-
-// GobEncoder type (something that implements the GobEncoder interface)
-type gobEncoderType struct {
-	CommonType
-}
-
-func newGobEncoderType(name string) *gobEncoderType {
-	g := &gobEncoderType{CommonType{Name: name}}
-	setTypeId(g)
-	return g
-}
-
-func (g *gobEncoderType) safeString(seen map[typeId]bool) string {
-	return g.Name
-}
-
-func (g *gobEncoderType) string() string { return g.Name }
-
-// Map type
-type mapType struct {
-	CommonType
-	Key  typeId
-	Elem typeId
-}
-
-func newMapType(name string) *mapType {
-	m := &mapType{CommonType{Name: name}, 0, 0}
-	return m
-}
-
-func (m *mapType) init(key, elem gobType) {
-	// Set our type id before evaluating the element's, in case it's our own.
-	setTypeId(m)
-	m.Key = key.id()
-	m.Elem = elem.id()
-}
-
-func (m *mapType) safeString(seen map[typeId]bool) string {
-	if seen[m.Id] {
-		return m.Name
-	}
-	seen[m.Id] = true
-	key := m.Key.gobType().safeString(seen)
-	elem := m.Elem.gobType().safeString(seen)
-	return fmt.Sprintf("map[%s]%s", key, elem)
-}
-
-func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) }
-
-// Slice type
-type sliceType struct {
-	CommonType
-	Elem typeId
-}
-
-func newSliceType(name string) *sliceType {
-	s := &sliceType{CommonType{Name: name}, 0}
-	return s
-}
-
-func (s *sliceType) init(elem gobType) {
-	// Set our type id before evaluating the element's, in case it's our own.
-	setTypeId(s)
-	s.Elem = elem.id()
-}
-
-func (s *sliceType) safeString(seen map[typeId]bool) string {
-	if seen[s.Id] {
-		return s.Name
-	}
-	seen[s.Id] = true
-	return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen))
-}
-
-func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) }
-
-// Struct type
-type fieldType struct {
-	Name string
-	Id   typeId
-}
-
-type structType struct {
-	CommonType
-	Field []*fieldType
-}
-
-func (s *structType) safeString(seen map[typeId]bool) string {
-	if s == nil {
-		return "<nil>"
-	}
-	if _, ok := seen[s.Id]; ok {
-		return s.Name
-	}
-	seen[s.Id] = true
-	str := s.Name + " = struct { "
-	for _, f := range s.Field {
-		str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
-	}
-	str += "}"
-	return str
-}
-
-func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }
-
-func newStructType(name string) *structType {
-	s := &structType{CommonType{Name: name}, nil}
-	// For historical reasons we set the id here rather than init.
-	// See the comment in newTypeObject for details.
-	setTypeId(s)
-	return s
-}
-
-// newTypeObject allocates a gobType for the reflection type rt.
-// Unless ut represents a GobEncoder, rt should be the base type
-// of ut.
-// This is only called from the encoding side. The decoding side
-// works through typeIds and userTypeInfos alone.
-func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.Error) {
-	// Does this type implement GobEncoder?
-	if ut.isGobEncoder {
-		return newGobEncoderType(name), nil
-	}
-	var err os.Error
-	var type0, type1 gobType
-	defer func() {
-		if err != nil {
-			types[rt] = nil, false
-		}
-	}()
-	// Install the top-level type before the subtypes (e.g. struct before
-	// fields) so recursive types can be constructed safely.
-	switch t := rt; t.Kind() {
-	// All basic types are easy: they are predefined.
-	case reflect.Bool:
-		return tBool.gobType(), nil
-
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return tInt.gobType(), nil
-
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return tUint.gobType(), nil
-
-	case reflect.Float32, reflect.Float64:
-		return tFloat.gobType(), nil
-
-	case reflect.Complex64, reflect.Complex128:
-		return tComplex.gobType(), nil
-
-	case reflect.String:
-		return tString.gobType(), nil
-
-	case reflect.Interface:
-		return tInterface.gobType(), nil
-
-	case reflect.Array:
-		at := newArrayType(name)
-		types[rt] = at
-		type0, err = getBaseType("", t.Elem())
-		if err != nil {
-			return nil, err
-		}
-		// Historical aside:
-		// For arrays, maps, and slices, we set the type id after the elements
-		// are constructed. This is to retain the order of type id allocation after
-		// a fix made to handle recursive types, which changed the order in
-		// which types are built.  Delaying the setting in this way preserves
-		// type ids while allowing recursive types to be described. Structs,
-		// done below, were already handling recursion correctly so they
-		// assign the top-level id before those of the field.
-		at.init(type0, t.Len())
-		return at, nil
-
-	case reflect.Map:
-		mt := newMapType(name)
-		types[rt] = mt
-		type0, err = getBaseType("", t.Key())
-		if err != nil {
-			return nil, err
-		}
-		type1, err = getBaseType("", t.Elem())
-		if err != nil {
-			return nil, err
-		}
-		mt.init(type0, type1)
-		return mt, nil
-
-	case reflect.Slice:
-		// []byte == []uint8 is a special case
-		if t.Elem().Kind() == reflect.Uint8 {
-			return tBytes.gobType(), nil
-		}
-		st := newSliceType(name)
-		types[rt] = st
-		type0, err = getBaseType(t.Elem().Name(), t.Elem())
-		if err != nil {
-			return nil, err
-		}
-		st.init(type0)
-		return st, nil
-
-	case reflect.Struct:
-		st := newStructType(name)
-		types[rt] = st
-		idToType[st.id()] = st
-		for i := 0; i < t.NumField(); i++ {
-			f := t.Field(i)
-			if !isExported(f.Name) {
-				continue
-			}
-			typ := userType(f.Type).base
-			tname := typ.Name()
-			if tname == "" {
-				t := userType(f.Type).base
-				tname = t.String()
-			}
-			gt, err := getBaseType(tname, f.Type)
-			if err != nil {
-				return nil, err
-			}
-			st.Field = append(st.Field, &fieldType{f.Name, gt.id()})
-		}
-		return st, nil
-
-	default:
-		return nil, os.NewError("gob NewTypeObject can't handle type: " + rt.String())
-	}
-	return nil, nil
-}
-
-// isExported reports whether this is an exported - upper case - name.
-func isExported(name string) bool {
-	rune, _ := utf8.DecodeRuneInString(name)
-	return unicode.IsUpper(rune)
-}
-
-// getBaseType returns the Gob type describing the given reflect.Type's base type.
-// typeLock must be held.
-func getBaseType(name string, rt reflect.Type) (gobType, os.Error) {
-	ut := userType(rt)
-	return getType(name, ut, ut.base)
-}
-
-// getType returns the Gob type describing the given reflect.Type.
-// Should be called only when handling GobEncoders/Decoders,
-// which may be pointers.  All other types are handled through the
-// base type, never a pointer.
-// typeLock must be held.
-func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.Error) {
-	typ, present := types[rt]
-	if present {
-		return typ, nil
-	}
-	typ, err := newTypeObject(name, ut, rt)
-	if err == nil {
-		types[rt] = typ
-	}
-	return typ, err
-}
-
-func checkId(want, got typeId) {
-	if want != got {
-		fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want))
-		panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string())
-	}
-}
-
-// used for building the basic types; called only from init().  the incoming
-// interface always refers to a pointer.
-func bootstrapType(name string, e interface{}, expect typeId) typeId {
-	rt := reflect.TypeOf(e).Elem()
-	_, present := types[rt]
-	if present {
-		panic("bootstrap type already present: " + name + ", " + rt.String())
-	}
-	typ := &CommonType{Name: name}
-	types[rt] = typ
-	setTypeId(typ)
-	checkId(expect, nextId)
-	userType(rt) // might as well cache it now
-	return nextId
-}
-
-// Representation of the information we send and receive about this type.
-// Each value we send is preceded by its type definition: an encoded int.
-// However, the very first time we send the value, we first send the pair
-// (-id, wireType).
-// For bootstrapping purposes, we assume that the recipient knows how
-// to decode a wireType; it is exactly the wireType struct here, interpreted
-// using the gob rules for sending a structure, except that we assume the
-// ids for wireType and structType etc. are known.  The relevant pieces
-// are built in encode.go's init() function.
-// To maintain binary compatibility, if you extend this type, always put
-// the new fields last.
-type wireType struct {
-	ArrayT      *arrayType
-	SliceT      *sliceType
-	StructT     *structType
-	MapT        *mapType
-	GobEncoderT *gobEncoderType
-}
-
-func (w *wireType) string() string {
-	const unknown = "unknown type"
-	if w == nil {
-		return unknown
-	}
-	switch {
-	case w.ArrayT != nil:
-		return w.ArrayT.Name
-	case w.SliceT != nil:
-		return w.SliceT.Name
-	case w.StructT != nil:
-		return w.StructT.Name
-	case w.MapT != nil:
-		return w.MapT.Name
-	case w.GobEncoderT != nil:
-		return w.GobEncoderT.Name
-	}
-	return unknown
-}
-
-type typeInfo struct {
-	id      typeId
-	encoder *encEngine
-	wire    *wireType
-}
-
-var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock
-
-// typeLock must be held.
-func getTypeInfo(ut *userTypeInfo) (*typeInfo, os.Error) {
-	rt := ut.base
-	if ut.isGobEncoder {
-		// We want the user type, not the base type.
-		rt = ut.user
-	}
-	info, ok := typeInfoMap[rt]
-	if ok {
-		return info, nil
-	}
-	info = new(typeInfo)
-	gt, err := getBaseType(rt.Name(), rt)
-	if err != nil {
-		return nil, err
-	}
-	info.id = gt.id()
-
-	if ut.isGobEncoder {
-		userType, err := getType(rt.Name(), ut, rt)
-		if err != nil {
-			return nil, err
-		}
-		info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)}
-		typeInfoMap[ut.user] = info
-		return info, nil
-	}
-
-	t := info.id.gobType()
-	switch typ := rt; typ.Kind() {
-	case reflect.Array:
-		info.wire = &wireType{ArrayT: t.(*arrayType)}
-	case reflect.Map:
-		info.wire = &wireType{MapT: t.(*mapType)}
-	case reflect.Slice:
-		// []byte == []uint8 is a special case handled separately
-		if typ.Elem().Kind() != reflect.Uint8 {
-			info.wire = &wireType{SliceT: t.(*sliceType)}
-		}
-	case reflect.Struct:
-		info.wire = &wireType{StructT: t.(*structType)}
-	}
-	typeInfoMap[rt] = info
-	return info, nil
-}
-
-// Called only when a panic is acceptable and unexpected.
-func mustGetTypeInfo(rt reflect.Type) *typeInfo {
-	t, err := getTypeInfo(userType(rt))
-	if err != nil {
-		panic("getTypeInfo: " + err.String())
-	}
-	return t
-}
-
-// GobEncoder is the interface describing data that provides its own
-// representation for encoding values for transmission to a GobDecoder.
-// A type that implements GobEncoder and GobDecoder has complete
-// control over the representation of its data and may therefore
-// contain things such as private fields, channels, and functions,
-// which are not usually transmissible in gob streams.
-//
-// Note: Since gobs can be stored permanently, It is good design
-// to guarantee the encoding used by a GobEncoder is stable as the
-// software evolves.  For instance, it might make sense for GobEncode
-// to include a version number in the encoding.
-type GobEncoder interface {
-	// GobEncode returns a byte slice representing the encoding of the
-	// receiver for transmission to a GobDecoder, usually of the same
-	// concrete type.
-	GobEncode() ([]byte, os.Error)
-}
-
-// GobDecoder is the interface describing data that provides its own
-// routine for decoding transmitted values sent by a GobEncoder.
-type GobDecoder interface {
-	// GobDecode overwrites the receiver, which must be a pointer,
-	// with the value represented by the byte slice, which was written
-	// by GobEncode, usually for the same concrete type.
-	GobDecode([]byte) os.Error
-}
-
-var (
-	nameToConcreteType = make(map[string]reflect.Type)
-	concreteTypeToName = make(map[reflect.Type]string)
-)
-
-// RegisterName is like Register but uses the provided name rather than the
-// type's default.
-func RegisterName(name string, value interface{}) {
-	if name == "" {
-		// reserved for nil
-		panic("attempt to register empty name")
-	}
-	base := userType(reflect.TypeOf(value)).base
-	// Check for incompatible duplicates.
-	if t, ok := nameToConcreteType[name]; ok && t != base {
-		panic("gob: registering duplicate types for " + name)
-	}
-	if n, ok := concreteTypeToName[base]; ok && n != name {
-		panic("gob: registering duplicate names for " + base.String())
-	}
-	// Store the name and type provided by the user....
-	nameToConcreteType[name] = reflect.TypeOf(value)
-	// but the flattened type in the type table, since that's what decode needs.
-	concreteTypeToName[base] = name
-}
-
-// Register records a type, identified by a value for that type, under its
-// internal type name.  That name will identify the concrete type of a value
-// sent or received as an interface variable.  Only types that will be
-// transferred as implementations of interface values need to be registered.
-// Expecting to be used only during initialization, it panics if the mapping
-// between types and names is not a bijection.
-func Register(value interface{}) {
-	// Default to printed representation for unnamed types
-	rt := reflect.TypeOf(value)
-	name := rt.String()
-
-	// But for named types (or pointers to them), qualify with import path.
-	// Dereference one pointer looking for a named type.
-	star := ""
-	if rt.Name() == "" {
-		if pt := rt; pt.Kind() == reflect.Ptr {
-			star = "*"
-			rt = pt
-		}
-	}
-	if rt.Name() != "" {
-		if rt.PkgPath() == "" {
-			name = star + rt.Name()
-		} else {
-			name = star + rt.PkgPath() + "." + rt.Name()
-		}
-	}
-
-	RegisterName(name, value)
-}
-
-func registerBasics() {
-	Register(int(0))
-	Register(int8(0))
-	Register(int16(0))
-	Register(int32(0))
-	Register(int64(0))
-	Register(uint(0))
-	Register(uint8(0))
-	Register(uint16(0))
-	Register(uint32(0))
-	Register(uint64(0))
-	Register(float32(0))
-	Register(float64(0))
-	Register(complex64(0i))
-	Register(complex128(0i))
-	Register(uintptr(0))
-	Register(false)
-	Register("")
-	Register([]byte(nil))
-	Register([]int(nil))
-	Register([]int8(nil))
-	Register([]int16(nil))
-	Register([]int32(nil))
-	Register([]int64(nil))
-	Register([]uint(nil))
-	Register([]uint8(nil))
-	Register([]uint16(nil))
-	Register([]uint32(nil))
-	Register([]uint64(nil))
-	Register([]float32(nil))
-	Register([]float64(nil))
-	Register([]complex64(nil))
-	Register([]complex128(nil))
-	Register([]uintptr(nil))
-	Register([]bool(nil))
-	Register([]string(nil))
-}
diff --git a/src/pkg/gob/type_test.go b/src/pkg/gob/type_test.go
deleted file mode 100644
index 411ffb7..0000000
--- a/src/pkg/gob/type_test.go
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gob
-
-import (
-	"reflect"
-	"testing"
-)
-
-type typeT struct {
-	id  typeId
-	str string
-}
-
-var basicTypes = []typeT{
-	{tBool, "bool"},
-	{tInt, "int"},
-	{tUint, "uint"},
-	{tFloat, "float"},
-	{tBytes, "bytes"},
-	{tString, "string"},
-}
-
-func getTypeUnlocked(name string, rt reflect.Type) gobType {
-	typeLock.Lock()
-	defer typeLock.Unlock()
-	t, err := getBaseType(name, rt)
-	if err != nil {
-		panic("getTypeUnlocked: " + err.String())
-	}
-	return t
-}
-
-// Sanity checks
-func TestBasic(t *testing.T) {
-	for _, tt := range basicTypes {
-		if tt.id.string() != tt.str {
-			t.Errorf("checkType: expected %q got %s", tt.str, tt.id.string())
-		}
-		if tt.id == 0 {
-			t.Errorf("id for %q is zero", tt.str)
-		}
-	}
-}
-
-// Reregister some basic types to check registration is idempotent.
-func TestReregistration(t *testing.T) {
-	newtyp := getTypeUnlocked("int", reflect.TypeOf(int(0)))
-	if newtyp != tInt.gobType() {
-		t.Errorf("reregistration of %s got new type", newtyp.string())
-	}
-	newtyp = getTypeUnlocked("uint", reflect.TypeOf(uint(0)))
-	if newtyp != tUint.gobType() {
-		t.Errorf("reregistration of %s got new type", newtyp.string())
-	}
-	newtyp = getTypeUnlocked("string", reflect.TypeOf("hello"))
-	if newtyp != tString.gobType() {
-		t.Errorf("reregistration of %s got new type", newtyp.string())
-	}
-}
-
-func TestArrayType(t *testing.T) {
-	var a3 [3]int
-	a3int := getTypeUnlocked("foo", reflect.TypeOf(a3))
-	newa3int := getTypeUnlocked("bar", reflect.TypeOf(a3))
-	if a3int != newa3int {
-		t.Errorf("second registration of [3]int creates new type")
-	}
-	var a4 [4]int
-	a4int := getTypeUnlocked("goo", reflect.TypeOf(a4))
-	if a3int == a4int {
-		t.Errorf("registration of [3]int creates same type as [4]int")
-	}
-	var b3 [3]bool
-	a3bool := getTypeUnlocked("", reflect.TypeOf(b3))
-	if a3int == a3bool {
-		t.Errorf("registration of [3]bool creates same type as [3]int")
-	}
-	str := a3bool.string()
-	expected := "[3]bool"
-	if str != expected {
-		t.Errorf("array printed as %q; expected %q", str, expected)
-	}
-}
-
-func TestSliceType(t *testing.T) {
-	var s []int
-	sint := getTypeUnlocked("slice", reflect.TypeOf(s))
-	var news []int
-	newsint := getTypeUnlocked("slice1", reflect.TypeOf(news))
-	if sint != newsint {
-		t.Errorf("second registration of []int creates new type")
-	}
-	var b []bool
-	sbool := getTypeUnlocked("", reflect.TypeOf(b))
-	if sbool == sint {
-		t.Errorf("registration of []bool creates same type as []int")
-	}
-	str := sbool.string()
-	expected := "[]bool"
-	if str != expected {
-		t.Errorf("slice printed as %q; expected %q", str, expected)
-	}
-}
-
-func TestMapType(t *testing.T) {
-	var m map[string]int
-	mapStringInt := getTypeUnlocked("map", reflect.TypeOf(m))
-	var newm map[string]int
-	newMapStringInt := getTypeUnlocked("map1", reflect.TypeOf(newm))
-	if mapStringInt != newMapStringInt {
-		t.Errorf("second registration of map[string]int creates new type")
-	}
-	var b map[string]bool
-	mapStringBool := getTypeUnlocked("", reflect.TypeOf(b))
-	if mapStringBool == mapStringInt {
-		t.Errorf("registration of map[string]bool creates same type as map[string]int")
-	}
-	str := mapStringBool.string()
-	expected := "map[string]bool"
-	if str != expected {
-		t.Errorf("map printed as %q; expected %q", str, expected)
-	}
-}
-
-type Bar struct {
-	X string
-}
-
-// This structure has pointers and refers to itself, making it a good test case.
-type Foo struct {
-	A int
-	B int32 // will become int
-	C string
-	D []byte
-	E *float64    // will become float64
-	F ****float64 // will become float64
-	G *Bar
-	H *Bar // should not interpolate the definition of Bar again
-	I *Foo // will not explode
-}
-
-func TestStructType(t *testing.T) {
-	sstruct := getTypeUnlocked("Foo", reflect.TypeOf(Foo{}))
-	str := sstruct.string()
-	// If we can print it correctly, we built it correctly.
-	expected := "Foo = struct { A int; B int; C string; D bytes; E float; F float; G Bar = struct { X string; }; H Bar; I Foo; }"
-	if str != expected {
-		t.Errorf("struct printed as %q; expected %q", str, expected)
-	}
-}
diff --git a/src/pkg/hash/adler32/adler32.go b/src/pkg/hash/adler32/adler32.go
index 84943d9..64fe68c 100644
--- a/src/pkg/hash/adler32/adler32.go
+++ b/src/pkg/hash/adler32/adler32.go
@@ -11,10 +11,7 @@
 //	significant-byte first (network) order.
 package adler32
 
-import (
-	"hash"
-	"os"
-)
+import "hash"
 
 const (
 	mod = 65521
@@ -41,6 +38,8 @@ func New() hash.Hash32 {
 
 func (d *digest) Size() int { return Size }
 
+func (d *digest) BlockSize() int { return 1 }
+
 // Add p to the running checksum a, b.
 func update(a, b uint32, p []byte) (aa, bb uint32) {
 	for _, pi := range p {
@@ -67,21 +66,20 @@ func finish(a, b uint32) uint32 {
 	return b<<16 | a
 }
 
-func (d *digest) Write(p []byte) (nn int, err os.Error) {
+func (d *digest) Write(p []byte) (nn int, err error) {
 	d.a, d.b = update(d.a, d.b, p)
 	return len(p), nil
 }
 
 func (d *digest) Sum32() uint32 { return finish(d.a, d.b) }
 
-func (d *digest) Sum() []byte {
-	p := make([]byte, 4)
+func (d *digest) Sum(in []byte) []byte {
 	s := d.Sum32()
-	p[0] = byte(s >> 24)
-	p[1] = byte(s >> 16)
-	p[2] = byte(s >> 8)
-	p[3] = byte(s)
-	return p
+	in = append(in, byte(s>>24))
+	in = append(in, byte(s>>16))
+	in = append(in, byte(s>>8))
+	in = append(in, byte(s))
+	return in
 }
 
 // Checksum returns the Adler-32 checksum of data.
diff --git a/src/pkg/hash/crc32/crc32.go b/src/pkg/hash/crc32/crc32.go
index 0245b1e..236d778 100644
--- a/src/pkg/hash/crc32/crc32.go
+++ b/src/pkg/hash/crc32/crc32.go
@@ -9,7 +9,6 @@ package crc32
 
 import (
 	"hash"
-	"os"
 	"sync"
 )
 
@@ -95,6 +94,8 @@ func NewIEEE() hash.Hash32 { return New(IEEETable) }
 
 func (d *digest) Size() int { return Size }
 
+func (d *digest) BlockSize() int { return 1 }
+
 func (d *digest) Reset() { d.crc = 0 }
 
 func update(crc uint32, tab *Table, p []byte) uint32 {
@@ -113,21 +114,20 @@ func Update(crc uint32, tab *Table, p []byte) uint32 {
 	return update(crc, tab, p)
 }
 
-func (d *digest) Write(p []byte) (n int, err os.Error) {
+func (d *digest) Write(p []byte) (n int, err error) {
 	d.crc = Update(d.crc, d.tab, p)
 	return len(p), nil
 }
 
 func (d *digest) Sum32() uint32 { return d.crc }
 
-func (d *digest) Sum() []byte {
-	p := make([]byte, 4)
+func (d *digest) Sum(in []byte) []byte {
 	s := d.Sum32()
-	p[0] = byte(s >> 24)
-	p[1] = byte(s >> 16)
-	p[2] = byte(s >> 8)
-	p[3] = byte(s)
-	return p
+	in = append(in, byte(s>>24))
+	in = append(in, byte(s>>16))
+	in = append(in, byte(s>>8))
+	in = append(in, byte(s))
+	return in
 }
 
 // Checksum returns the CRC-32 checksum of data
diff --git a/src/pkg/hash/crc32/crc32_generic.go b/src/pkg/hash/crc32/crc32_generic.go
index 27aabd9..c3fdcd6 100644
--- a/src/pkg/hash/crc32/crc32_generic.go
+++ b/src/pkg/hash/crc32/crc32_generic.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build 386 arm
+
 package crc32
 
 // The file contains the generic version of updateCastagnoli which just calls
diff --git a/src/pkg/hash/crc64/crc64.go b/src/pkg/hash/crc64/crc64.go
index ae37e78..5b64390 100644
--- a/src/pkg/hash/crc64/crc64.go
+++ b/src/pkg/hash/crc64/crc64.go
@@ -7,10 +7,7 @@
 // information.
 package crc64
 
-import (
-	"hash"
-	"os"
-)
+import "hash"
 
 // The size of a CRC-64 checksum in bytes.
 const Size = 8
@@ -56,6 +53,8 @@ func New(tab *Table) hash.Hash64 { return &digest{0, tab} }
 
 func (d *digest) Size() int { return Size }
 
+func (d *digest) BlockSize() int { return 1 }
+
 func (d *digest) Reset() { d.crc = 0 }
 
 func update(crc uint64, tab *Table, p []byte) uint64 {
@@ -71,25 +70,24 @@ func Update(crc uint64, tab *Table, p []byte) uint64 {
 	return update(crc, tab, p)
 }
 
-func (d *digest) Write(p []byte) (n int, err os.Error) {
+func (d *digest) Write(p []byte) (n int, err error) {
 	d.crc = update(d.crc, d.tab, p)
 	return len(p), nil
 }
 
 func (d *digest) Sum64() uint64 { return d.crc }
 
-func (d *digest) Sum() []byte {
-	p := make([]byte, 8)
+func (d *digest) Sum(in []byte) []byte {
 	s := d.Sum64()
-	p[0] = byte(s >> 56)
-	p[1] = byte(s >> 48)
-	p[2] = byte(s >> 40)
-	p[3] = byte(s >> 32)
-	p[4] = byte(s >> 24)
-	p[5] = byte(s >> 16)
-	p[6] = byte(s >> 8)
-	p[7] = byte(s)
-	return p
+	in = append(in, byte(s>>56))
+	in = append(in, byte(s>>48))
+	in = append(in, byte(s>>40))
+	in = append(in, byte(s>>32))
+	in = append(in, byte(s>>24))
+	in = append(in, byte(s>>16))
+	in = append(in, byte(s>>8))
+	in = append(in, byte(s))
+	return in
 }
 
 // Checksum returns the CRC-64 checksum of data
diff --git a/src/pkg/hash/fnv/fnv.go b/src/pkg/hash/fnv/fnv.go
index 3ff7d7c..ea50198 100644
--- a/src/pkg/hash/fnv/fnv.go
+++ b/src/pkg/hash/fnv/fnv.go
@@ -8,9 +8,7 @@
 package fnv
 
 import (
-	"encoding/binary"
 	"hash"
-	"os"
 )
 
 type (
@@ -61,7 +59,7 @@ func (s *sum32a) Sum32() uint32 { return uint32(*s) }
 func (s *sum64) Sum64() uint64  { return uint64(*s) }
 func (s *sum64a) Sum64() uint64 { return uint64(*s) }
 
-func (s *sum32) Write(data []byte) (int, os.Error) {
+func (s *sum32) Write(data []byte) (int, error) {
 	hash := *s
 	for _, c := range data {
 		hash *= prime32
@@ -71,7 +69,7 @@ func (s *sum32) Write(data []byte) (int, os.Error) {
 	return len(data), nil
 }
 
-func (s *sum32a) Write(data []byte) (int, os.Error) {
+func (s *sum32a) Write(data []byte) (int, error) {
 	hash := *s
 	for _, c := range data {
 		hash ^= sum32a(c)
@@ -81,7 +79,7 @@ func (s *sum32a) Write(data []byte) (int, os.Error) {
 	return len(data), nil
 }
 
-func (s *sum64) Write(data []byte) (int, os.Error) {
+func (s *sum64) Write(data []byte) (int, error) {
 	hash := *s
 	for _, c := range data {
 		hash *= prime64
@@ -91,7 +89,7 @@ func (s *sum64) Write(data []byte) (int, os.Error) {
 	return len(data), nil
 }
 
-func (s *sum64a) Write(data []byte) (int, os.Error) {
+func (s *sum64a) Write(data []byte) (int, error) {
 	hash := *s
 	for _, c := range data {
 		hash ^= sum64a(c)
@@ -106,26 +104,51 @@ func (s *sum32a) Size() int { return 4 }
 func (s *sum64) Size() int  { return 8 }
 func (s *sum64a) Size() int { return 8 }
 
-func (s *sum32) Sum() []byte {
-	a := make([]byte, 4)
-	binary.BigEndian.PutUint32(a, uint32(*s))
-	return a
+func (s *sum32) BlockSize() int  { return 1 }
+func (s *sum32a) BlockSize() int { return 1 }
+func (s *sum64) BlockSize() int  { return 1 }
+func (s *sum64a) BlockSize() int { return 1 }
+
+func (s *sum32) Sum(in []byte) []byte {
+	v := uint32(*s)
+	in = append(in, byte(v>>24))
+	in = append(in, byte(v>>16))
+	in = append(in, byte(v>>8))
+	in = append(in, byte(v))
+	return in
 }
 
-func (s *sum32a) Sum() []byte {
-	a := make([]byte, 4)
-	binary.BigEndian.PutUint32(a, uint32(*s))
-	return a
+func (s *sum32a) Sum(in []byte) []byte {
+	v := uint32(*s)
+	in = append(in, byte(v>>24))
+	in = append(in, byte(v>>16))
+	in = append(in, byte(v>>8))
+	in = append(in, byte(v))
+	return in
 }
 
-func (s *sum64) Sum() []byte {
-	a := make([]byte, 8)
-	binary.BigEndian.PutUint64(a, uint64(*s))
-	return a
+func (s *sum64) Sum(in []byte) []byte {
+	v := uint64(*s)
+	in = append(in, byte(v>>56))
+	in = append(in, byte(v>>48))
+	in = append(in, byte(v>>40))
+	in = append(in, byte(v>>32))
+	in = append(in, byte(v>>24))
+	in = append(in, byte(v>>16))
+	in = append(in, byte(v>>8))
+	in = append(in, byte(v))
+	return in
 }
 
-func (s *sum64a) Sum() []byte {
-	a := make([]byte, 8)
-	binary.BigEndian.PutUint64(a, uint64(*s))
-	return a
+func (s *sum64a) Sum(in []byte) []byte {
+	v := uint64(*s)
+	in = append(in, byte(v>>56))
+	in = append(in, byte(v>>48))
+	in = append(in, byte(v>>40))
+	in = append(in, byte(v>>32))
+	in = append(in, byte(v>>24))
+	in = append(in, byte(v>>16))
+	in = append(in, byte(v>>8))
+	in = append(in, byte(v))
+	return in
 }
diff --git a/src/pkg/hash/fnv/fnv_test.go b/src/pkg/hash/fnv/fnv_test.go
index 429230c..17454de 100644
--- a/src/pkg/hash/fnv/fnv_test.go
+++ b/src/pkg/hash/fnv/fnv_test.go
@@ -72,7 +72,7 @@ func testGolden(t *testing.T, hash hash.Hash, gold []golden) {
 		if done != len(g.text) {
 			t.Fatalf("wrote only %d out of %d bytes", done, len(g.text))
 		}
-		if actual := hash.Sum(); !bytes.Equal(g.sum, actual) {
+		if actual := hash.Sum(nil); !bytes.Equal(g.sum, actual) {
 			t.Errorf("hash(%q) = 0x%x want 0x%x", g.text, actual, g.sum)
 		}
 	}
@@ -97,26 +97,26 @@ func TestIntegrity64a(t *testing.T) {
 func testIntegrity(t *testing.T, h hash.Hash) {
 	data := []byte{'1', '2', 3, 4, 5}
 	h.Write(data)
-	sum := h.Sum()
+	sum := h.Sum(nil)
 
 	if size := h.Size(); size != len(sum) {
 		t.Fatalf("Size()=%d but len(Sum())=%d", size, len(sum))
 	}
 
-	if a := h.Sum(); !bytes.Equal(sum, a) {
+	if a := h.Sum(nil); !bytes.Equal(sum, a) {
 		t.Fatalf("first Sum()=0x%x, second Sum()=0x%x", sum, a)
 	}
 
 	h.Reset()
 	h.Write(data)
-	if a := h.Sum(); !bytes.Equal(sum, a) {
+	if a := h.Sum(nil); !bytes.Equal(sum, a) {
 		t.Fatalf("Sum()=0x%x, but after Reset() Sum()=0x%x", sum, a)
 	}
 
 	h.Reset()
 	h.Write(data[:2])
 	h.Write(data[2:])
-	if a := h.Sum(); !bytes.Equal(sum, a) {
+	if a := h.Sum(nil); !bytes.Equal(sum, a) {
 		t.Fatalf("Sum()=0x%x, but with partial writes, Sum()=0x%x", sum, a)
 	}
 
@@ -162,6 +162,6 @@ func benchmark(b *testing.B, h hash.Hash) {
 	for todo := b.N; todo != 0; todo-- {
 		h.Reset()
 		h.Write(data)
-		h.Sum()
+		h.Sum(nil)
 	}
 }
diff --git a/src/pkg/hash/hash.go b/src/pkg/hash/hash.go
index 3536c0b..aa895cf 100644
--- a/src/pkg/hash/hash.go
+++ b/src/pkg/hash/hash.go
@@ -13,15 +13,21 @@ type Hash interface {
 	// It never returns an error.
 	io.Writer
 
-	// Sum returns the current hash, without changing the
-	// underlying hash state.
-	Sum() []byte
+	// Sum appends the current hash to b and returns the resulting slice.
+	// It does not change the underlying hash state.
+	Sum(b []byte) []byte
 
 	// Reset resets the hash to one with zero bytes written.
 	Reset()
 
 	// Size returns the number of bytes Sum will return.
 	Size() int
+
+	// BlockSize returns the hash's underlying block size.
+	// The Write method must be able to accept any amount
+	// of data, but it may operate more efficiently if all writes
+	// are a multiple of the block size.
+	BlockSize() int
 }
 
 // Hash32 is the common interface implemented by all 32-bit hash functions.
diff --git a/src/pkg/html/Makefile b/src/pkg/html/Makefile
index 28dc1a3..1b18358 100644
--- a/src/pkg/html/Makefile
+++ b/src/pkg/html/Makefile
@@ -6,12 +6,7 @@ include ../../Make.inc
 
 TARG=html
 GOFILES=\
-	const.go\
-	doc.go\
 	entity.go\
 	escape.go\
-	node.go\
-	parse.go\
-	token.go\
 
 include ../../Make.pkg
diff --git a/src/pkg/html/const.go b/src/pkg/html/const.go
deleted file mode 100644
index 9078d26..0000000
--- a/src/pkg/html/const.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2011 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 html
-
-// Section 11.2.3.2 of the HTML5 specification says "The following elements
-// have varying levels of special parsing rules".
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#the-stack-of-open-elements
-var isSpecialElement = map[string]bool{
-	"address":    true,
-	"applet":     true,
-	"area":       true,
-	"article":    true,
-	"aside":      true,
-	"base":       true,
-	"basefont":   true,
-	"bgsound":    true,
-	"blockquote": true,
-	"body":       true,
-	"br":         true,
-	"button":     true,
-	"caption":    true,
-	"center":     true,
-	"col":        true,
-	"colgroup":   true,
-	"command":    true,
-	"dd":         true,
-	"details":    true,
-	"dir":        true,
-	"div":        true,
-	"dl":         true,
-	"dt":         true,
-	"embed":      true,
-	"fieldset":   true,
-	"figcaption": true,
-	"figure":     true,
-	"footer":     true,
-	"form":       true,
-	"frame":      true,
-	"frameset":   true,
-	"h1":         true,
-	"h2":         true,
-	"h3":         true,
-	"h4":         true,
-	"h5":         true,
-	"h6":         true,
-	"head":       true,
-	"header":     true,
-	"hgroup":     true,
-	"hr":         true,
-	"html":       true,
-	"iframe":     true,
-	"img":        true,
-	"input":      true,
-	"isindex":    true,
-	"li":         true,
-	"link":       true,
-	"listing":    true,
-	"marquee":    true,
-	"menu":       true,
-	"meta":       true,
-	"nav":        true,
-	"noembed":    true,
-	"noframes":   true,
-	"noscript":   true,
-	"object":     true,
-	"ol":         true,
-	"p":          true,
-	"param":      true,
-	"plaintext":  true,
-	"pre":        true,
-	"script":     true,
-	"section":    true,
-	"select":     true,
-	"style":      true,
-	"summary":    true,
-	"table":      true,
-	"tbody":      true,
-	"td":         true,
-	"textarea":   true,
-	"tfoot":      true,
-	"th":         true,
-	"thead":      true,
-	"title":      true,
-	"tr":         true,
-	"ul":         true,
-	"wbr":        true,
-	"xmp":        true,
-}
diff --git a/src/pkg/html/doc.go b/src/pkg/html/doc.go
deleted file mode 100644
index 5bc0630..0000000
--- a/src/pkg/html/doc.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2010 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 html implements an HTML5-compliant tokenizer and parser.
-INCOMPLETE.
-
-Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
-caller's responsibility to ensure that r provides UTF-8 encoded HTML.
-
-	z := html.NewTokenizer(r)
-
-Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
-which parses the next token and returns its type, or an error:
-
-	for {
-		tt := z.Next()
-		if tt == html.ErrorToken {
-			// ...
-			return ...
-		}
-		// Process the current token.
-	}
-
-There are two APIs for retrieving the current token. The high-level API is to
-call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
-allow optionally calling Raw after Next but before Token, Text, TagName, or
-TagAttr. In EBNF notation, the valid call sequence per token is:
-
-	Next {Raw} [ Token | Text | TagName {TagAttr} ]
-
-Token returns an independent data structure that completely describes a token.
-Entities (such as "<") are unescaped, tag names and attribute keys are
-lower-cased, and attributes are collected into a []Attribute. For example:
-
-	for {
-		if z.Next() == html.ErrorToken {
-			// Returning os.EOF indicates success.
-			return z.Error()
-		}
-		emitToken(z.Token())
-	}
-
-The low-level API performs fewer allocations and copies, but the contents of
-the []byte values returned by Text, TagName and TagAttr may change on the next
-call to Next. For example, to extract an HTML page's anchor text:
-
-	depth := 0
-	for {
-		tt := z.Next()
-		switch tt {
-		case ErrorToken:
-			return z.Error()
-		case TextToken:
-			if depth > 0 {
-				// emitBytes should copy the []byte it receives,
-				// if it doesn't process it immediately.
-				emitBytes(z.Text())
-			}
-		case StartTagToken, EndTagToken:
-			tn, _ := z.TagName()
-			if len(tn) == 1 && tn[0] == 'a' {
-				if tt == StartTag {
-					depth++
-				} else {
-					depth--
-				}
-			}
-		}
-	}
-
-A Tokenizer typically skips over HTML comments. To return comment tokens, set
-Tokenizer.ReturnComments to true before looping over calls to Next.
-
-Parsing is done by calling Parse with an io.Reader, which returns the root of
-the parse tree (the document element) as a *Node. It is the caller's
-responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
-example, to process each anchor node in depth-first order:
-
-	doc, err := html.Parse(r)
-	if err != nil {
-		// ...
-	}
-	var f func(*html.Node)
-	f = func(n *html.Node) {
-		if n.Type == html.ElementNode && n.Data == "a" {
-			// Do something with n...
-		}
-		for _, c := range n.Child {
-			f(c)
-		}
-	}
-	f(doc)
-
-The relevant specifications include:
-http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html and
-http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html
-*/
-package html
-
-// The tokenization algorithm implemented by this package is not a line-by-line
-// transliteration of the relatively verbose state-machine in the WHATWG
-// specification. A more direct approach is used instead, where the program
-// counter implies the state, such as whether it is tokenizing a tag or a text
-// node. Specification compliance is verified by checking expected and actual
-// outputs over a test suite rather than aiming for algorithmic fidelity.
-
-// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
-// TODO(nigeltao): How does parsing interact with a JavaScript engine?
diff --git a/src/pkg/html/entity.go b/src/pkg/html/entity.go
index 21263e2..bd83075 100644
--- a/src/pkg/html/entity.go
+++ b/src/pkg/html/entity.go
@@ -13,7 +13,7 @@ const longestEntityWithoutSemicolon = 6
 //
 // Note that the HTML5 list is larger than the HTML4 list at
 // http://www.w3.org/TR/html4/sgml/entities.html
-var entity = map[string]int{
+var entity = map[string]rune{
 	"AElig;":                           '\U000000C6',
 	"AMP;":                             '\U00000026',
 	"Aacute;":                          '\U000000C1',
@@ -2155,7 +2155,7 @@ var entity = map[string]int{
 }
 
 // HTML entities that are two unicode codepoints.
-var entity2 = map[string][2]int{
+var entity2 = map[string][2]rune{
 	// TODO(nigeltao): Handle replacements that are wider than their names.
 	// "nLt;":                     {'\u226A', '\u20D2'},
 	// "nGt;":                     {'\u226B', '\u20D2'},
diff --git a/src/pkg/html/entity_test.go b/src/pkg/html/entity_test.go
index 2cf49d6..b53f866 100644
--- a/src/pkg/html/entity_test.go
+++ b/src/pkg/html/entity_test.go
@@ -6,7 +6,7 @@ package html
 
 import (
 	"testing"
-	"utf8"
+	"unicode/utf8"
 )
 
 func TestEntityLength(t *testing.T) {
diff --git a/src/pkg/html/escape.go b/src/pkg/html/escape.go
index 0de97c5..c0b5262 100644
--- a/src/pkg/html/escape.go
+++ b/src/pkg/html/escape.go
@@ -7,13 +7,17 @@ package html
 import (
 	"bytes"
 	"strings"
-	"utf8"
+	"unicode/utf8"
 )
 
+type writer interface {
+	WriteString(string) (int, error)
+}
+
 // These replacements permit compatibility with old numeric entities that 
 // assumed Windows-1252 encoding.
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
-var replacementTable = [...]int{
+var replacementTable = [...]rune{
 	'\u20AC', // First entry is what 0x80 should be replaced with.
 	'\u0081',
 	'\u201A',
@@ -78,23 +82,23 @@ func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
 			i++
 		}
 
-		x := 0
+		x := '\x00'
 		for i < len(s) {
 			c = s[i]
 			i++
 			if hex {
 				if '0' <= c && c <= '9' {
-					x = 16*x + int(c) - '0'
+					x = 16*x + rune(c) - '0'
 					continue
 				} else if 'a' <= c && c <= 'f' {
-					x = 16*x + int(c) - 'a' + 10
+					x = 16*x + rune(c) - 'a' + 10
 					continue
 				} else if 'A' <= c && c <= 'F' {
-					x = 16*x + int(c) - 'A' + 10
+					x = 16*x + rune(c) - 'A' + 10
 					continue
 				}
 			} else if '0' <= c && c <= '9' {
-				x = 10*x + int(c) - '0'
+				x = 10*x + rune(c) - '0'
 				continue
 			}
 			if c != ';' {
@@ -182,12 +186,24 @@ func unescape(b []byte) []byte {
 	return b
 }
 
+// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
+func lower(b []byte) []byte {
+	for i, c := range b {
+		if 'A' <= c && c <= 'Z' {
+			b[i] = c + 'a' - 'A'
+		}
+	}
+	return b
+}
+
 const escapedChars = `&'<>"`
 
-func escape(buf *bytes.Buffer, s string) {
+func escape(w writer, s string) error {
 	i := strings.IndexAny(s, escapedChars)
 	for i != -1 {
-		buf.WriteString(s[0:i])
+		if _, err := w.WriteString(s[:i]); err != nil {
+			return err
+		}
 		var esc string
 		switch s[i] {
 		case '&':
@@ -204,10 +220,13 @@ func escape(buf *bytes.Buffer, s string) {
 			panic("unrecognized escape character")
 		}
 		s = s[i+1:]
-		buf.WriteString(esc)
+		if _, err := w.WriteString(esc); err != nil {
+			return err
+		}
 		i = strings.IndexAny(s, escapedChars)
 	}
-	buf.WriteString(s)
+	_, err := w.WriteString(s)
+	return err
 }
 
 // EscapeString escapes special characters like "<" to become "<". It
diff --git a/src/pkg/html/node.go b/src/pkg/html/node.go
deleted file mode 100644
index 4ecfd6c..0000000
--- a/src/pkg/html/node.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2011 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 html
-
-// A NodeType is the type of a Node.
-type NodeType int
-
-const (
-	ErrorNode NodeType = iota
-	TextNode
-	DocumentNode
-	ElementNode
-	CommentNode
-	DoctypeNode
-	scopeMarkerNode
-)
-
-// Section 11.2.3.3 says "scope markers are inserted when entering applet
-// elements, buttons, object elements, marquees, table cells, and table
-// captions, and are used to prevent formatting from 'leaking'".
-var scopeMarker = Node{Type: scopeMarkerNode}
-
-// A Node consists of a NodeType and some Data (tag name for element nodes,
-// content for text) and are part of a tree of Nodes. Element nodes may also
-// contain a slice of Attributes. Data is unescaped, so that it looks like
-// "a<b" rather than "a<b".
-type Node struct {
-	Parent *Node
-	Child  []*Node
-	Type   NodeType
-	Data   string
-	Attr   []Attribute
-}
-
-// Add adds a node as a child of n.
-// It will panic if the child's parent is not nil.
-func (n *Node) Add(child *Node) {
-	if child.Parent != nil {
-		panic("html: Node.Add called for a child Node that already has a parent")
-	}
-	child.Parent = n
-	n.Child = append(n.Child, child)
-}
-
-// Remove removes a node as a child of n.
-// It will panic if the child's parent is not n.
-func (n *Node) Remove(child *Node) {
-	if child.Parent == n {
-		child.Parent = nil
-		for i, m := range n.Child {
-			if m == child {
-				copy(n.Child[i:], n.Child[i+1:])
-				j := len(n.Child) - 1
-				n.Child[j] = nil
-				n.Child = n.Child[:j]
-				return
-			}
-		}
-	}
-	panic("html: Node.Remove called for a non-child Node")
-}
-
-// reparentChildren reparents all of src's child nodes to dst.
-func reparentChildren(dst, src *Node) {
-	for _, n := range src.Child {
-		if n.Parent != src {
-			panic("html: nodes have an inconsistent parent/child relationship")
-		}
-		n.Parent = dst
-	}
-	dst.Child = append(dst.Child, src.Child...)
-	src.Child = nil
-}
-
-// clone returns a new node with the same type, data and attributes.
-// The clone has no parent and no children.
-func (n *Node) clone() *Node {
-	m := &Node{
-		Type: n.Type,
-		Data: n.Data,
-		Attr: make([]Attribute, len(n.Attr)),
-	}
-	copy(m.Attr, n.Attr)
-	return m
-}
-
-// nodeStack is a stack of nodes.
-type nodeStack []*Node
-
-// pop pops the stack. It will panic if s is empty.
-func (s *nodeStack) pop() *Node {
-	i := len(*s)
-	n := (*s)[i-1]
-	*s = (*s)[:i-1]
-	return n
-}
-
-// top returns the most recently pushed node, or nil if s is empty.
-func (s *nodeStack) top() *Node {
-	if i := len(*s); i > 0 {
-		return (*s)[i-1]
-	}
-	return nil
-}
-
-// index returns the index of the top-most occurence of n in the stack, or -1
-// if n is not present.
-func (s *nodeStack) index(n *Node) int {
-	for i := len(*s) - 1; i >= 0; i-- {
-		if (*s)[i] == n {
-			return i
-		}
-	}
-	return -1
-}
-
-// insert inserts a node at the given index.
-func (s *nodeStack) insert(i int, n *Node) {
-	(*s) = append(*s, nil)
-	copy((*s)[i+1:], (*s)[i:])
-	(*s)[i] = n
-}
-
-// remove removes a node from the stack. It is a no-op if n is not present.
-func (s *nodeStack) remove(n *Node) {
-	i := s.index(n)
-	if i == -1 {
-		return
-	}
-	copy((*s)[i:], (*s)[i+1:])
-	j := len(*s) - 1
-	(*s)[j] = nil
-	*s = (*s)[:j]
-}
-
-// forTag returns the top-most element node with the given tag.
-func (s *nodeStack) forTag(tag string) *Node {
-	for i := len(*s) - 1; i >= 0; i-- {
-		n := (*s)[i]
-		if n.Type == ElementNode && n.Data == tag {
-			return n
-		}
-	}
-	return nil
-}
diff --git a/src/pkg/html/parse.go b/src/pkg/html/parse.go
deleted file mode 100644
index 519ebe5..0000000
--- a/src/pkg/html/parse.go
+++ /dev/null
@@ -1,800 +0,0 @@
-// Copyright 2010 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 html
-
-import (
-	"io"
-	"os"
-)
-
-// A parser implements the HTML5 parsing algorithm:
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#tree-construction
-type parser struct {
-	// tokenizer provides the tokens for the parser.
-	tokenizer *Tokenizer
-	// tok is the most recently read token.
-	tok Token
-	// Self-closing tags like <hr/> are re-interpreted as a two-token sequence:
-	// <hr> followed by </hr>. hasSelfClosingToken is true if we have just read
-	// the synthetic start tag and the next one due is the matching end tag.
-	hasSelfClosingToken bool
-	// doc is the document root element.
-	doc *Node
-	// The stack of open elements (section 11.2.3.2) and active formatting
-	// elements (section 11.2.3.3).
-	oe, afe nodeStack
-	// Element pointers (section 11.2.3.4).
-	head, form *Node
-	// Other parsing state flags (section 11.2.3.5).
-	scripting, framesetOK bool
-}
-
-func (p *parser) top() *Node {
-	if n := p.oe.top(); n != nil {
-		return n
-	}
-	return p.doc
-}
-
-// stopTags for use in popUntil. These come from section 11.2.3.2.
-var (
-	defaultScopeStopTags  = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object"}
-	listItemScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object", "ol", "ul"}
-	buttonScopeStopTags   = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object", "button"}
-	tableScopeStopTags    = []string{"html", "table"}
-)
-
-// popUntil pops the stack of open elements at the highest element whose tag
-// is in matchTags, provided there is no higher element in stopTags. It returns
-// whether or not there was such an element. If there was not, popUntil leaves
-// the stack unchanged.
-//
-// For example, if the stack was:
-// ["html", "body", "font", "table", "b", "i", "u"]
-// then popUntil([]string{"html, "table"}, "font") would return false, but
-// popUntil([]string{"html, "table"}, "i") would return true and the resultant
-// stack would be:
-// ["html", "body", "font", "table", "b"]
-//
-// If an element's tag is in both stopTags and matchTags, then the stack will
-// be popped and the function returns true (provided, of course, there was no
-// higher element in the stack that was also in stopTags). For example,
-// popUntil([]string{"html, "table"}, "table") would return true and leave:
-// ["html", "body", "font"]
-func (p *parser) popUntil(stopTags []string, matchTags ...string) bool {
-	for i := len(p.oe) - 1; i >= 0; i-- {
-		tag := p.oe[i].Data
-		for _, t := range matchTags {
-			if t == tag {
-				p.oe = p.oe[:i]
-				return true
-			}
-		}
-		for _, t := range stopTags {
-			if t == tag {
-				return false
-			}
-		}
-	}
-	return false
-}
-
-// addChild adds a child node n to the top element, and pushes n onto the stack
-// of open elements if it is an element node.
-func (p *parser) addChild(n *Node) {
-	p.top().Add(n)
-	if n.Type == ElementNode {
-		p.oe = append(p.oe, n)
-	}
-}
-
-// addText adds text to the preceding node if it is a text node, or else it
-// calls addChild with a new text node.
-func (p *parser) addText(text string) {
-	// TODO: distinguish whitespace text from others.
-	t := p.top()
-	if i := len(t.Child); i > 0 && t.Child[i-1].Type == TextNode {
-		t.Child[i-1].Data += text
-		return
-	}
-	p.addChild(&Node{
-		Type: TextNode,
-		Data: text,
-	})
-}
-
-// addElement calls addChild with an element node.
-func (p *parser) addElement(tag string, attr []Attribute) {
-	p.addChild(&Node{
-		Type: ElementNode,
-		Data: tag,
-		Attr: attr,
-	})
-}
-
-// Section 11.2.3.3.
-func (p *parser) addFormattingElement(tag string, attr []Attribute) {
-	p.addElement(tag, attr)
-	p.afe = append(p.afe, p.top())
-	// TODO.
-}
-
-// Section 11.2.3.3.
-func (p *parser) clearActiveFormattingElements() {
-	for {
-		n := p.afe.pop()
-		if len(p.afe) == 0 || n.Type == scopeMarkerNode {
-			return
-		}
-	}
-}
-
-// Section 11.2.3.3.
-func (p *parser) reconstructActiveFormattingElements() {
-	n := p.afe.top()
-	if n == nil {
-		return
-	}
-	if n.Type == scopeMarkerNode || p.oe.index(n) != -1 {
-		return
-	}
-	i := len(p.afe) - 1
-	for n.Type != scopeMarkerNode && p.oe.index(n) == -1 {
-		if i == 0 {
-			i = -1
-			break
-		}
-		i--
-		n = p.afe[i]
-	}
-	for {
-		i++
-		n = p.afe[i]
-		p.addChild(n.clone())
-		p.afe[i] = n
-		if i == len(p.afe)-1 {
-			break
-		}
-	}
-}
-
-// read reads the next token. This is usually from the tokenizer, but it may
-// be the synthesized end tag implied by a self-closing tag.
-func (p *parser) read() os.Error {
-	if p.hasSelfClosingToken {
-		p.hasSelfClosingToken = false
-		p.tok.Type = EndTagToken
-		p.tok.Attr = nil
-		return nil
-	}
-	p.tokenizer.Next()
-	p.tok = p.tokenizer.Token()
-	switch p.tok.Type {
-	case ErrorToken:
-		return p.tokenizer.Error()
-	case SelfClosingTagToken:
-		p.hasSelfClosingToken = true
-		p.tok.Type = StartTagToken
-	}
-	return nil
-}
-
-// Section 11.2.4.
-func (p *parser) acknowledgeSelfClosingTag() {
-	p.hasSelfClosingToken = false
-}
-
-// An insertion mode (section 11.2.3.1) is the state transition function from
-// a particular state in the HTML5 parser's state machine. It updates the
-// parser's fields depending on parser.token (where ErrorToken means EOF). In
-// addition to returning the next insertionMode state, it also returns whether
-// the token was consumed.
-type insertionMode func(*parser) (insertionMode, bool)
-
-// useTheRulesFor runs the delegate insertionMode over p, returning the actual
-// insertionMode unless the delegate caused a state transition.
-// Section 11.2.3.1, "using the rules for".
-func useTheRulesFor(p *parser, actual, delegate insertionMode) (insertionMode, bool) {
-	im, consumed := delegate(p)
-	if im != delegate {
-		return im, consumed
-	}
-	return actual, consumed
-}
-
-// Section 11.2.5.4.1.
-func initialIM(p *parser) (insertionMode, bool) {
-	if p.tok.Type == DoctypeToken {
-		p.addChild(&Node{
-			Type: DoctypeNode,
-			Data: p.tok.Data,
-		})
-		return beforeHTMLIM, true
-	}
-	// TODO: set "quirks mode"? It's defined in the DOM spec instead of HTML5 proper,
-	// and so switching on "quirks mode" might belong in a different package.
-	return beforeHTMLIM, false
-}
-
-// Section 11.2.5.4.2.
-func beforeHTMLIM(p *parser) (insertionMode, bool) {
-	var (
-		add     bool
-		attr    []Attribute
-		implied bool
-	)
-	switch p.tok.Type {
-	case ErrorToken:
-		implied = true
-	case TextToken:
-		// TODO: distinguish whitespace text from others.
-		implied = true
-	case StartTagToken:
-		if p.tok.Data == "html" {
-			add = true
-			attr = p.tok.Attr
-		} else {
-			implied = true
-		}
-	case EndTagToken:
-		switch p.tok.Data {
-		case "head", "body", "html", "br":
-			implied = true
-		default:
-			// Ignore the token.
-		}
-	}
-	if add || implied {
-		p.addElement("html", attr)
-	}
-	return beforeHeadIM, !implied
-}
-
-// Section 11.2.5.4.3.
-func beforeHeadIM(p *parser) (insertionMode, bool) {
-	var (
-		add     bool
-		attr    []Attribute
-		implied bool
-	)
-	switch p.tok.Type {
-	case ErrorToken:
-		implied = true
-	case TextToken:
-		// TODO: distinguish whitespace text from others.
-		implied = true
-	case StartTagToken:
-		switch p.tok.Data {
-		case "head":
-			add = true
-			attr = p.tok.Attr
-		case "html":
-			return useTheRulesFor(p, beforeHeadIM, inBodyIM)
-		default:
-			implied = true
-		}
-	case EndTagToken:
-		switch p.tok.Data {
-		case "head", "body", "html", "br":
-			implied = true
-		default:
-			// Ignore the token.
-		}
-	}
-	if add || implied {
-		p.addElement("head", attr)
-	}
-	return inHeadIM, !implied
-}
-
-// Section 11.2.5.4.4.
-func inHeadIM(p *parser) (insertionMode, bool) {
-	var (
-		pop     bool
-		implied bool
-	)
-	switch p.tok.Type {
-	case ErrorToken, TextToken:
-		implied = true
-	case StartTagToken:
-		switch p.tok.Data {
-		case "meta":
-			// TODO.
-		case "script":
-			// TODO.
-		default:
-			implied = true
-		}
-	case EndTagToken:
-		if p.tok.Data == "head" {
-			pop = true
-		}
-		// TODO.
-	}
-	if pop || implied {
-		n := p.oe.pop()
-		if n.Data != "head" {
-			panic("html: bad parser state")
-		}
-		return afterHeadIM, !implied
-	}
-	return inHeadIM, !implied
-}
-
-// Section 11.2.5.4.6.
-func afterHeadIM(p *parser) (insertionMode, bool) {
-	var (
-		add        bool
-		attr       []Attribute
-		framesetOK bool
-		implied    bool
-	)
-	switch p.tok.Type {
-	case ErrorToken, TextToken:
-		implied = true
-		framesetOK = true
-	case StartTagToken:
-		switch p.tok.Data {
-		case "html":
-			// TODO.
-		case "body":
-			add = true
-			attr = p.tok.Attr
-			framesetOK = false
-		case "frameset":
-			// TODO.
-		case "base", "basefont", "bgsound", "link", "meta", "noframes", "script", "style", "title":
-			// TODO.
-		case "head":
-			// TODO.
-		default:
-			implied = true
-			framesetOK = true
-		}
-	case EndTagToken:
-		// TODO.
-	}
-	if add || implied {
-		p.addElement("body", attr)
-		p.framesetOK = framesetOK
-	}
-	return inBodyIM, !implied
-}
-
-// Section 11.2.5.4.7.
-func inBodyIM(p *parser) (insertionMode, bool) {
-	var endP bool
-	switch p.tok.Type {
-	case TextToken:
-		p.reconstructActiveFormattingElements()
-		p.addText(p.tok.Data)
-		p.framesetOK = false
-	case StartTagToken:
-		switch p.tok.Data {
-		case "address", "article", "aside", "blockquote", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "menu", "nav", "ol", "p", "section", "summary", "ul":
-			// TODO: Do the proper "does the stack of open elements has a p element in button scope" algorithm in section 11.2.3.2.
-			n := p.top()
-			if n.Type == ElementNode && n.Data == "p" {
-				endP = true
-			} else {
-				p.addElement(p.tok.Data, p.tok.Attr)
-			}
-		case "h1", "h2", "h3", "h4", "h5", "h6":
-			// TODO: auto-insert </p> if necessary.
-			switch n := p.top(); n.Data {
-			case "h1", "h2", "h3", "h4", "h5", "h6":
-				p.oe.pop()
-			}
-			p.addElement(p.tok.Data, p.tok.Attr)
-		case "a":
-			if n := p.afe.forTag("a"); n != nil {
-				p.inBodyEndTagFormatting("a")
-				p.oe.remove(n)
-				p.afe.remove(n)
-			}
-			p.reconstructActiveFormattingElements()
-			p.addFormattingElement(p.tok.Data, p.tok.Attr)
-		case "b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u":
-			p.reconstructActiveFormattingElements()
-			p.addFormattingElement(p.tok.Data, p.tok.Attr)
-		case "area", "br", "embed", "img", "input", "keygen", "wbr":
-			p.reconstructActiveFormattingElements()
-			p.addElement(p.tok.Data, p.tok.Attr)
-			p.oe.pop()
-			p.acknowledgeSelfClosingTag()
-			p.framesetOK = false
-		case "table":
-			// TODO: auto-insert </p> if necessary, depending on quirks mode.
-			p.addElement(p.tok.Data, p.tok.Attr)
-			p.framesetOK = false
-			return inTableIM, true
-		case "hr":
-			// TODO: auto-insert </p> if necessary.
-			p.addElement(p.tok.Data, p.tok.Attr)
-			p.oe.pop()
-			p.acknowledgeSelfClosingTag()
-			p.framesetOK = false
-		default:
-			// TODO.
-			p.addElement(p.tok.Data, p.tok.Attr)
-		}
-	case EndTagToken:
-		switch p.tok.Data {
-		case "body":
-			// TODO: autoclose the stack of open elements.
-			return afterBodyIM, true
-		case "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u":
-			p.inBodyEndTagFormatting(p.tok.Data)
-		default:
-			// TODO: any other end tag
-			if p.tok.Data == p.top().Data {
-				p.oe.pop()
-			}
-		}
-	}
-	if endP {
-		// TODO: do the proper algorithm.
-		n := p.oe.pop()
-		if n.Type != ElementNode || n.Data != "p" {
-			panic("unreachable")
-		}
-	}
-	return inBodyIM, !endP
-}
-
-func (p *parser) inBodyEndTagFormatting(tag string) {
-	// This is the "adoption agency" algorithm, described at
-	// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#adoptionAgency
-
-	// TODO: this is a fairly literal line-by-line translation of that algorithm.
-	// Once the code successfully parses the comprehensive test suite, we should
-	// refactor this code to be more idiomatic.
-
-	// Steps 1-3. The outer loop.
-	for i := 0; i < 8; i++ {
-		// Step 4. Find the formatting element.
-		var formattingElement *Node
-		for j := len(p.afe) - 1; j >= 0; j-- {
-			if p.afe[j].Type == scopeMarkerNode {
-				break
-			}
-			if p.afe[j].Data == tag {
-				formattingElement = p.afe[j]
-				break
-			}
-		}
-		if formattingElement == nil {
-			return
-		}
-		feIndex := p.oe.index(formattingElement)
-		if feIndex == -1 {
-			p.afe.remove(formattingElement)
-			return
-		}
-
-		// Steps 5-6. Find the furthest block.
-		var furthestBlock *Node
-		for _, e := range p.oe[feIndex:] {
-			if isSpecialElement[e.Data] {
-				furthestBlock = e
-				break
-			}
-		}
-		if furthestBlock == nil {
-			e := p.oe.pop()
-			for e != formattingElement {
-				e = p.oe.pop()
-			}
-			p.afe.remove(e)
-			return
-		}
-
-		// Steps 7-8. Find the common ancestor and bookmark node.
-		commonAncestor := p.oe[feIndex-1]
-		bookmark := p.afe.index(formattingElement)
-
-		// Step 9. The inner loop. Find the lastNode to reparent.
-		lastNode := furthestBlock
-		node := furthestBlock
-		x := p.oe.index(node)
-		// Steps 9.1-9.3.
-		for j := 0; j < 3; j++ {
-			// Step 9.4.
-			x--
-			node = p.oe[x]
-			// Step 9.5.
-			if p.afe.index(node) == -1 {
-				p.oe.remove(node)
-				continue
-			}
-			// Step 9.6.
-			if node == formattingElement {
-				break
-			}
-			// Step 9.7.
-			clone := node.clone()
-			p.afe[p.afe.index(node)] = clone
-			p.oe[p.oe.index(node)] = clone
-			node = clone
-			// Step 9.8.
-			if lastNode == furthestBlock {
-				bookmark = p.afe.index(node) + 1
-			}
-			// Step 9.9.
-			if lastNode.Parent != nil {
-				lastNode.Parent.Remove(lastNode)
-			}
-			node.Add(lastNode)
-			// Step 9.10.
-			lastNode = node
-		}
-
-		// Step 10. Reparent lastNode to the common ancestor,
-		// or for misnested table nodes, to the foster parent.
-		if lastNode.Parent != nil {
-			lastNode.Parent.Remove(lastNode)
-		}
-		switch commonAncestor.Data {
-		case "table", "tbody", "tfoot", "thead", "tr":
-			// TODO: fix up misnested table nodes; find the foster parent.
-			fallthrough
-		default:
-			commonAncestor.Add(lastNode)
-		}
-
-		// Steps 11-13. Reparent nodes from the furthest block's children
-		// to a clone of the formatting element.
-		clone := formattingElement.clone()
-		reparentChildren(clone, furthestBlock)
-		furthestBlock.Add(clone)
-
-		// Step 14. Fix up the list of active formatting elements.
-		p.afe.remove(formattingElement)
-		p.afe.insert(bookmark, clone)
-
-		// Step 15. Fix up the stack of open elements.
-		p.oe.remove(formattingElement)
-		p.oe.insert(p.oe.index(furthestBlock)+1, clone)
-	}
-}
-
-// Section 11.2.5.4.9.
-func inTableIM(p *parser) (insertionMode, bool) {
-	var (
-		add      bool
-		data     string
-		attr     []Attribute
-		consumed bool
-	)
-	switch p.tok.Type {
-	case ErrorToken:
-		// Stop parsing.
-		return nil, true
-	case TextToken:
-		// TODO.
-	case StartTagToken:
-		switch p.tok.Data {
-		case "tbody", "tfoot", "thead":
-			add = true
-			data = p.tok.Data
-			attr = p.tok.Attr
-			consumed = true
-		case "td", "th", "tr":
-			add = true
-			data = "tbody"
-		default:
-			// TODO.
-		}
-	case EndTagToken:
-		switch p.tok.Data {
-		case "table":
-			if p.popUntil(tableScopeStopTags, "table") {
-				// TODO: "reset the insertion mode appropriately" as per 11.2.3.1.
-				return inBodyIM, false
-			}
-			// Ignore the token.
-			return inTableIM, true
-		case "body", "caption", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr":
-			// Ignore the token.
-			return inTableIM, true
-		}
-	}
-	if add {
-		// TODO: clear the stack back to a table context.
-		p.addElement(data, attr)
-		return inTableBodyIM, consumed
-	}
-	// TODO: return useTheRulesFor(inTableIM, inBodyIM, p) unless etc. etc. foster parenting.
-	return inTableIM, true
-}
-
-// Section 11.2.5.4.13.
-func inTableBodyIM(p *parser) (insertionMode, bool) {
-	var (
-		add      bool
-		data     string
-		attr     []Attribute
-		consumed bool
-	)
-	switch p.tok.Type {
-	case ErrorToken:
-		// TODO.
-	case TextToken:
-		// TODO.
-	case StartTagToken:
-		switch p.tok.Data {
-		case "tr":
-			add = true
-			data = p.tok.Data
-			attr = p.tok.Attr
-			consumed = true
-		case "td", "th":
-			add = true
-			data = "tr"
-			consumed = false
-		default:
-			// TODO.
-		}
-	case EndTagToken:
-		switch p.tok.Data {
-		case "table":
-			if p.popUntil(tableScopeStopTags, "tbody", "thead", "tfoot") {
-				return inTableIM, false
-			}
-			// Ignore the token.
-			return inTableBodyIM, true
-		case "body", "caption", "col", "colgroup", "html", "td", "th", "tr":
-			// Ignore the token.
-			return inTableBodyIM, true
-		}
-	}
-	if add {
-		// TODO: clear the stack back to a table body context.
-		p.addElement(data, attr)
-		return inRowIM, consumed
-	}
-	return useTheRulesFor(p, inTableBodyIM, inTableIM)
-}
-
-// Section 11.2.5.4.14.
-func inRowIM(p *parser) (insertionMode, bool) {
-	switch p.tok.Type {
-	case ErrorToken:
-		// TODO.
-	case TextToken:
-		// TODO.
-	case StartTagToken:
-		switch p.tok.Data {
-		case "td", "th":
-			// TODO: clear the stack back to a table row context.
-			p.addElement(p.tok.Data, p.tok.Attr)
-			p.afe = append(p.afe, &scopeMarker)
-			return inCellIM, true
-		default:
-			// TODO.
-		}
-	case EndTagToken:
-		switch p.tok.Data {
-		case "tr":
-			// TODO.
-		case "table":
-			if p.popUntil(tableScopeStopTags, "tr") {
-				return inTableBodyIM, false
-			}
-			// Ignore the token.
-			return inRowIM, true
-		case "tbody", "tfoot", "thead":
-			// TODO.
-		case "body", "caption", "col", "colgroup", "html", "td", "th":
-			// Ignore the token.
-			return inRowIM, true
-		default:
-			// TODO.
-		}
-	}
-	return useTheRulesFor(p, inRowIM, inTableIM)
-}
-
-// Section 11.2.5.4.15.
-func inCellIM(p *parser) (insertionMode, bool) {
-	var (
-		closeTheCellAndReprocess bool
-	)
-	switch p.tok.Type {
-	case StartTagToken:
-		switch p.tok.Data {
-		case "caption", "col", "colgroup", "tbody", "td", "tfoot", "th", "thead", "tr":
-			// TODO: check for "td" or "th" in table scope.
-			closeTheCellAndReprocess = true
-		}
-	case EndTagToken:
-		switch p.tok.Data {
-		case "td", "th":
-			// TODO.
-		case "body", "caption", "col", "colgroup", "html":
-			// TODO.
-		case "table", "tbody", "tfoot", "thead", "tr":
-			// TODO: check for matching element in table scope.
-			closeTheCellAndReprocess = true
-		}
-	}
-	if closeTheCellAndReprocess {
-		if p.popUntil(tableScopeStopTags, "td") || p.popUntil(tableScopeStopTags, "th") {
-			p.clearActiveFormattingElements()
-			return inRowIM, false
-		}
-	}
-	return useTheRulesFor(p, inCellIM, inBodyIM)
-}
-
-// Section 11.2.5.4.18.
-func afterBodyIM(p *parser) (insertionMode, bool) {
-	switch p.tok.Type {
-	case ErrorToken:
-		// TODO.
-	case TextToken:
-		// TODO.
-	case StartTagToken:
-		// TODO.
-	case EndTagToken:
-		switch p.tok.Data {
-		case "html":
-			// TODO: autoclose the stack of open elements.
-			return afterAfterBodyIM, true
-		default:
-			// TODO.
-		}
-	}
-	return afterBodyIM, true
-}
-
-// Section 11.2.5.4.21.
-func afterAfterBodyIM(p *parser) (insertionMode, bool) {
-	switch p.tok.Type {
-	case ErrorToken:
-		// Stop parsing.
-		return nil, true
-	case TextToken:
-		// TODO.
-	case StartTagToken:
-		if p.tok.Data == "html" {
-			return useTheRulesFor(p, afterAfterBodyIM, inBodyIM)
-		}
-	}
-	return inBodyIM, false
-}
-
-// Parse returns the parse tree for the HTML from the given Reader.
-// The input is assumed to be UTF-8 encoded.
-func Parse(r io.Reader) (*Node, os.Error) {
-	p := &parser{
-		tokenizer: NewTokenizer(r),
-		doc: &Node{
-			Type: DocumentNode,
-		},
-		scripting:  true,
-		framesetOK: true,
-	}
-	// Iterate until EOF. Any other error will cause an early return.
-	im, consumed := initialIM, true
-	for {
-		if consumed {
-			if err := p.read(); err != nil {
-				if err == os.EOF {
-					break
-				}
-				return nil, err
-			}
-		}
-		im, consumed = im(p)
-	}
-	// Loop until the final token (the ErrorToken signifying EOF) is consumed.
-	for {
-		if im, consumed = im(p); consumed {
-			break
-		}
-	}
-	return p.doc, nil
-}
diff --git a/src/pkg/html/parse_test.go b/src/pkg/html/parse_test.go
deleted file mode 100644
index 7d918d2..0000000
--- a/src/pkg/html/parse_test.go
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2010 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 html
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"strings"
-	"testing"
-)
-
-func pipeErr(err os.Error) io.Reader {
-	pr, pw := io.Pipe()
-	pw.CloseWithError(err)
-	return pr
-}
-
-func readDat(filename string, c chan io.Reader) {
-	f, err := os.Open("testdata/webkit/" + filename)
-	if err != nil {
-		c <- pipeErr(err)
-		return
-	}
-	defer f.Close()
-
-	// Loop through the lines of the file. Each line beginning with "#" denotes
-	// a new section, which is returned as a separate io.Reader.
-	r := bufio.NewReader(f)
-	var pw *io.PipeWriter
-	for {
-		line, err := r.ReadSlice('\n')
-		if err != nil {
-			if pw != nil {
-				pw.CloseWithError(err)
-				pw = nil
-			} else {
-				c <- pipeErr(err)
-			}
-			return
-		}
-		if len(line) == 0 {
-			continue
-		}
-		if line[0] == '#' {
-			if pw != nil {
-				pw.Close()
-			}
-			var pr *io.PipeReader
-			pr, pw = io.Pipe()
-			c <- pr
-			continue
-		}
-		if line[0] != '|' {
-			// Strip the trailing '\n'.
-			line = line[:len(line)-1]
-		}
-		if pw != nil {
-			if _, err := pw.Write(line); err != nil {
-				pw.CloseWithError(err)
-				pw = nil
-			}
-		}
-	}
-}
-
-func dumpLevel(w io.Writer, n *Node, level int) os.Error {
-	io.WriteString(w, "| ")
-	for i := 0; i < level; i++ {
-		io.WriteString(w, "  ")
-	}
-	switch n.Type {
-	case ErrorNode:
-		return os.NewError("unexpected ErrorNode")
-	case DocumentNode:
-		return os.NewError("unexpected DocumentNode")
-	case ElementNode:
-		fmt.Fprintf(w, "<%s>", EscapeString(n.Data))
-	case TextNode:
-		fmt.Fprintf(w, "%q", EscapeString(n.Data))
-	case CommentNode:
-		return os.NewError("COMMENT")
-	case DoctypeNode:
-		fmt.Fprintf(w, "<!DOCTYPE %s>", EscapeString(n.Data))
-	case scopeMarkerNode:
-		return os.NewError("unexpected scopeMarkerNode")
-	default:
-		return os.NewError("unknown node type")
-	}
-	io.WriteString(w, "\n")
-	for _, c := range n.Child {
-		if err := dumpLevel(w, c, level+1); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func dump(n *Node) (string, os.Error) {
-	if n == nil || len(n.Child) == 0 {
-		return "", nil
-	}
-	b := bytes.NewBuffer(nil)
-	for _, child := range n.Child {
-		if err := dumpLevel(b, child, 0); err != nil {
-			return "", err
-		}
-	}
-	return b.String(), nil
-}
-
-func TestParser(t *testing.T) {
-	// TODO(nigeltao): Process all the .dat files, not just the first one.
-	filenames := []string{
-		"tests1.dat",
-	}
-	for _, filename := range filenames {
-		rc := make(chan io.Reader)
-		go readDat(filename, rc)
-		// TODO(nigeltao): Process all test cases, not just a subset.
-		for i := 0; i < 25; i++ {
-			// Parse the #data section.
-			b, err := ioutil.ReadAll(<-rc)
-			if err != nil {
-				t.Fatal(err)
-			}
-			text := string(b)
-			doc, err := Parse(strings.NewReader(text))
-			if err != nil {
-				t.Fatal(err)
-			}
-			actual, err := dump(doc)
-			if err != nil {
-				t.Fatal(err)
-			}
-			// Skip the #error section.
-			if _, err := io.Copy(ioutil.Discard, <-rc); err != nil {
-				t.Fatal(err)
-			}
-			// Compare the parsed tree to the #document section.
-			b, err = ioutil.ReadAll(<-rc)
-			if err != nil {
-				t.Fatal(err)
-			}
-			expected := string(b)
-			if actual != expected {
-				t.Errorf("%s test #%d %q, actual vs expected:\n----\n%s----\n%s----", filename, i, text, actual, expected)
-			}
-		}
-	}
-}
diff --git a/src/pkg/html/template/Makefile b/src/pkg/html/template/Makefile
new file mode 100644
index 0000000..d27601a
--- /dev/null
+++ b/src/pkg/html/template/Makefile
@@ -0,0 +1,23 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=html/template
+GOFILES=\
+	attr.go\
+	clone.go\
+	content.go\
+	context.go\
+	css.go\
+	doc.go\
+	error.go\
+	escape.go\
+	html.go\
+	js.go\
+	template.go\
+	transition.go\
+	url.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/html/template/attr.go b/src/pkg/html/template/attr.go
new file mode 100644
index 0000000..3ea0288
--- /dev/null
+++ b/src/pkg/html/template/attr.go
@@ -0,0 +1,175 @@
+// Copyright 2011 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 template
+
+import (
+	"strings"
+)
+
+// attrTypeMap[n] describes the value of the given attribute.
+// If an attribute affects (or can mask) the encoding or interpretation of
+// other content, or affects the contents, idempotency, or credentials of a
+// network message, then the value in this map is contentTypeUnsafe.
+// This map is derived from HTML5, specifically
+// http://www.w3.org/TR/html5/Overview.html#attributes-1
+// as well as "%URI"-typed attributes from
+// http://www.w3.org/TR/html4/index/attributes.html
+var attrTypeMap = map[string]contentType{
+	"accept":          contentTypePlain,
+	"accept-charset":  contentTypeUnsafe,
+	"action":          contentTypeURL,
+	"alt":             contentTypePlain,
+	"archive":         contentTypeURL,
+	"async":           contentTypeUnsafe,
+	"autocomplete":    contentTypePlain,
+	"autofocus":       contentTypePlain,
+	"autoplay":        contentTypePlain,
+	"background":      contentTypeURL,
+	"border":          contentTypePlain,
+	"checked":         contentTypePlain,
+	"cite":            contentTypeURL,
+	"challenge":       contentTypeUnsafe,
+	"charset":         contentTypeUnsafe,
+	"class":           contentTypePlain,
+	"classid":         contentTypeURL,
+	"codebase":        contentTypeURL,
+	"cols":            contentTypePlain,
+	"colspan":         contentTypePlain,
+	"content":         contentTypeUnsafe,
+	"contenteditable": contentTypePlain,
+	"contextmenu":     contentTypePlain,
+	"controls":        contentTypePlain,
+	"coords":          contentTypePlain,
+	"crossorigin":     contentTypeUnsafe,
+	"data":            contentTypeURL,
+	"datetime":        contentTypePlain,
+	"default":         contentTypePlain,
+	"defer":           contentTypeUnsafe,
+	"dir":             contentTypePlain,
+	"dirname":         contentTypePlain,
+	"disabled":        contentTypePlain,
+	"draggable":       contentTypePlain,
+	"dropzone":        contentTypePlain,
+	"enctype":         contentTypeUnsafe,
+	"for":             contentTypePlain,
+	"form":            contentTypeUnsafe,
+	"formaction":      contentTypeURL,
+	"formenctype":     contentTypeUnsafe,
+	"formmethod":      contentTypeUnsafe,
+	"formnovalidate":  contentTypeUnsafe,
+	"formtarget":      contentTypePlain,
+	"headers":         contentTypePlain,
+	"height":          contentTypePlain,
+	"hidden":          contentTypePlain,
+	"high":            contentTypePlain,
+	"href":            contentTypeURL,
+	"hreflang":        contentTypePlain,
+	"http-equiv":      contentTypeUnsafe,
+	"icon":            contentTypeURL,
+	"id":              contentTypePlain,
+	"ismap":           contentTypePlain,
+	"keytype":         contentTypeUnsafe,
+	"kind":            contentTypePlain,
+	"label":           contentTypePlain,
+	"lang":            contentTypePlain,
+	"language":        contentTypeUnsafe,
+	"list":            contentTypePlain,
+	"longdesc":        contentTypeURL,
+	"loop":            contentTypePlain,
+	"low":             contentTypePlain,
+	"manifest":        contentTypeURL,
+	"max":             contentTypePlain,
+	"maxlength":       contentTypePlain,
+	"media":           contentTypePlain,
+	"mediagroup":      contentTypePlain,
+	"method":          contentTypeUnsafe,
+	"min":             contentTypePlain,
+	"multiple":        contentTypePlain,
+	"name":            contentTypePlain,
+	"novalidate":      contentTypeUnsafe,
+	// Skip handler names from
+	// http://www.w3.org/TR/html5/Overview.html#event-handlers-on-elements-document-objects-and-window-objects
+	// since we have special handling in attrType.
+	"open":        contentTypePlain,
+	"optimum":     contentTypePlain,
+	"pattern":     contentTypeUnsafe,
+	"placeholder": contentTypePlain,
+	"poster":      contentTypeURL,
+	"profile":     contentTypeURL,
+	"preload":     contentTypePlain,
+	"pubdate":     contentTypePlain,
+	"radiogroup":  contentTypePlain,
+	"readonly":    contentTypePlain,
+	"rel":         contentTypeUnsafe,
+	"required":    contentTypePlain,
+	"reversed":    contentTypePlain,
+	"rows":        contentTypePlain,
+	"rowspan":     contentTypePlain,
+	"sandbox":     contentTypeUnsafe,
+	"spellcheck":  contentTypePlain,
+	"scope":       contentTypePlain,
+	"scoped":      contentTypePlain,
+	"seamless":    contentTypePlain,
+	"selected":    contentTypePlain,
+	"shape":       contentTypePlain,
+	"size":        contentTypePlain,
+	"sizes":       contentTypePlain,
+	"span":        contentTypePlain,
+	"src":         contentTypeURL,
+	"srcdoc":      contentTypeHTML,
+	"srclang":     contentTypePlain,
+	"start":       contentTypePlain,
+	"step":        contentTypePlain,
+	"style":       contentTypeCSS,
+	"tabindex":    contentTypePlain,
+	"target":      contentTypePlain,
+	"title":       contentTypePlain,
+	"type":        contentTypeUnsafe,
+	"usemap":      contentTypeURL,
+	"value":       contentTypeUnsafe,
+	"width":       contentTypePlain,
+	"wrap":        contentTypePlain,
+	"xmlns":       contentTypeURL,
+}
+
+// attrType returns a conservative (upper-bound on authority) guess at the
+// type of the named attribute.
+func attrType(name string) contentType {
+	name = strings.ToLower(name)
+	if strings.HasPrefix(name, "data-") {
+		// Strip data- so that custom attribute heuristics below are
+		// widely applied.
+		// Treat data-action as URL below.
+		name = name[5:]
+	} else if colon := strings.IndexRune(name, ':'); colon != -1 {
+		if name[:colon] == "xmlns" {
+			return contentTypeURL
+		}
+		// Treat svg:href and xlink:href as href below.
+		name = name[colon+1:]
+	}
+	if t, ok := attrTypeMap[name]; ok {
+		return t
+	}
+	// Treat partial event handler names as script.
+	if strings.HasPrefix(name, "on") {
+		return contentTypeJS
+	}
+
+	// Heuristics to prevent "javascript:..." injection in custom
+	// data attributes and custom attributes like g:tweetUrl.
+	// http://www.w3.org/TR/html5/elements.html#embedding-custom-non-visible-data-with-the-data-attributes:
+	// "Custom data attributes are intended to store custom data
+	//  private to the page or application, for which there are no
+	//  more appropriate attributes or elements."
+	// Developers seem to store URL content in data URLs that start
+	// or end with "URI" or "URL".
+	if strings.Contains(name, "src") ||
+		strings.Contains(name, "uri") ||
+		strings.Contains(name, "url") {
+		return contentTypeURL
+	}
+	return contentTypePlain
+}
diff --git a/src/pkg/html/template/clone.go b/src/pkg/html/template/clone.go
new file mode 100644
index 0000000..d0d8ea4
--- /dev/null
+++ b/src/pkg/html/template/clone.go
@@ -0,0 +1,90 @@
+// Copyright 2011 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 template
+
+import (
+	"text/template/parse"
+)
+
+// clone clones a template Node.
+func clone(n parse.Node) parse.Node {
+	switch t := n.(type) {
+	case *parse.ActionNode:
+		return cloneAction(t)
+	case *parse.IfNode:
+		b := new(parse.IfNode)
+		copyBranch(&b.BranchNode, &t.BranchNode)
+		return b
+	case *parse.ListNode:
+		return cloneList(t)
+	case *parse.RangeNode:
+		b := new(parse.RangeNode)
+		copyBranch(&b.BranchNode, &t.BranchNode)
+		return b
+	case *parse.TemplateNode:
+		return cloneTemplate(t)
+	case *parse.TextNode:
+		return cloneText(t)
+	case *parse.WithNode:
+		b := new(parse.WithNode)
+		copyBranch(&b.BranchNode, &t.BranchNode)
+		return b
+	}
+	panic("cloning " + n.String() + " is unimplemented")
+}
+
+// cloneAction returns a deep clone of n.
+func cloneAction(n *parse.ActionNode) *parse.ActionNode {
+	// We use keyless fields because they won't compile if a field is added.
+	return &parse.ActionNode{n.NodeType, n.Line, clonePipe(n.Pipe)}
+}
+
+// cloneList returns a deep clone of n.
+func cloneList(n *parse.ListNode) *parse.ListNode {
+	if n == nil {
+		return nil
+	}
+	// We use keyless fields because they won't compile if a field is added.
+	c := parse.ListNode{n.NodeType, make([]parse.Node, len(n.Nodes))}
+	for i, child := range n.Nodes {
+		c.Nodes[i] = clone(child)
+	}
+	return &c
+}
+
+// clonePipe returns a shallow clone of n.
+// The escaper does not modify pipe descendants in place so there's no need to
+// clone deeply.
+func clonePipe(n *parse.PipeNode) *parse.PipeNode {
+	if n == nil {
+		return nil
+	}
+	// We use keyless fields because they won't compile if a field is added.
+	return &parse.PipeNode{n.NodeType, n.Line, n.Decl, n.Cmds}
+}
+
+// cloneTemplate returns a deep clone of n.
+func cloneTemplate(n *parse.TemplateNode) *parse.TemplateNode {
+	// We use keyless fields because they won't compile if a field is added.
+	return &parse.TemplateNode{n.NodeType, n.Line, n.Name, clonePipe(n.Pipe)}
+}
+
+// cloneText clones the given node sharing its []byte.
+func cloneText(n *parse.TextNode) *parse.TextNode {
+	// We use keyless fields because they won't compile if a field is added.
+	return &parse.TextNode{n.NodeType, n.Text}
+}
+
+// copyBranch clones src into dst.
+func copyBranch(dst, src *parse.BranchNode) {
+	// We use keyless fields because they won't compile if a field is added.
+	*dst = parse.BranchNode{
+		src.NodeType,
+		src.Line,
+		clonePipe(src.Pipe),
+		cloneList(src.List),
+		cloneList(src.ElseList),
+	}
+}
diff --git a/src/pkg/html/template/clone_test.go b/src/pkg/html/template/clone_test.go
new file mode 100644
index 0000000..3978817
--- /dev/null
+++ b/src/pkg/html/template/clone_test.go
@@ -0,0 +1,92 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestClone(t *testing.T) {
+	tests := []struct {
+		input, want, wantClone string
+	}{
+		{
+			`Hello, {{if true}}{{"<World>"}}{{end}}!`,
+			"Hello, <World>!",
+			"Hello, <World>!",
+		},
+		{
+			`Hello, {{if false}}{{.X}}{{else}}{{"<World>"}}{{end}}!`,
+			"Hello, <World>!",
+			"Hello, <World>!",
+		},
+		{
+			`Hello, {{with "<World>"}}{{.}}{{end}}!`,
+			"Hello, <World>!",
+			"Hello, <World>!",
+		},
+		{
+			`{{range .}}<p>{{.}}</p>{{end}}`,
+			"<p>foo</p><p><bar></p><p>baz</p>",
+			"<p>foo</p><p><bar></p><p>baz</p>",
+		},
+		{
+			`Hello, {{"<World>" | html}}!`,
+			"Hello, <World>!",
+			"Hello, <World>!",
+		},
+		{
+			`Hello{{if 1}}, World{{else}}{{template "d"}}{{end}}!`,
+			"Hello, World!",
+			"Hello, World!",
+		},
+	}
+
+	for _, test := range tests {
+		s, err := New("s").Parse(test.input)
+		if err != nil {
+			t.Errorf("input=%q: unexpected parse error %v", test.input, err)
+		}
+
+		d, _ := New("d").Parse(test.input)
+		// Hack: just replace the root of the tree.
+		d.text.Root = cloneList(s.text.Root)
+
+		if want, got := s.text.Root.String(), d.text.Root.String(); want != got {
+			t.Errorf("want %q, got %q", want, got)
+		}
+
+		err = escapeTemplates(d, "d")
+		if err != nil {
+			t.Errorf("%q: failed to escape: %s", test.input, err)
+			continue
+		}
+
+		if want, got := "s", s.Name(); want != got {
+			t.Errorf("want %q, got %q", want, got)
+			continue
+		}
+		if want, got := "d", d.Name(); want != got {
+			t.Errorf("want %q, got %q", want, got)
+			continue
+		}
+
+		data := []string{"foo", "<bar>", "baz"}
+
+		var b bytes.Buffer
+		d.Execute(&b, data)
+		if got := b.String(); got != test.wantClone {
+			t.Errorf("input=%q: want %q, got %q", test.input, test.wantClone, got)
+		}
+
+		// Make sure escaping d did not affect s.
+		b.Reset()
+		s.text.Execute(&b, data)
+		if got := b.String(); got != test.want {
+			t.Errorf("input=%q: want %q, got %q", test.input, test.want, got)
+		}
+	}
+}
diff --git a/src/pkg/html/template/content.go b/src/pkg/html/template/content.go
new file mode 100644
index 0000000..4de7ccd
--- /dev/null
+++ b/src/pkg/html/template/content.go
@@ -0,0 +1,113 @@
+// Copyright 2011 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 template
+
+import (
+	"fmt"
+	"reflect"
+)
+
+// Strings of content from a trusted source.
+type (
+	// CSS encapsulates known safe content that matches any of:
+	//   1. The CSS3 stylesheet production, such as `p { color: purple }`.
+	//   2. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.
+	//   3. CSS3 declaration productions, such as `color: red; margin: 2px`.
+	//   4. The CSS3 value production, such as `rgba(0, 0, 255, 127)`.
+	// See http://www.w3.org/TR/css3-syntax/#style
+	CSS string
+
+	// HTML encapsulates a known safe HTML document fragment.
+	// It should not be used for HTML from a third-party, or HTML with
+	// unclosed tags or comments. The outputs of a sound HTML sanitizer
+	// and a template escaped by this package are fine for use with HTML.
+	HTML string
+
+	// HTMLAttr encapsulates an HTML attribute from a trusted source,
+	// for example: ` dir="ltr"`.
+	HTMLAttr string
+
+	// JS encapsulates a known safe EcmaScript5 Expression, or example,
+	// `(x + y * z())`. 
+	// Template authors are responsible for ensuring that typed expressions
+	// do not break the intended precedence and that there is no
+	// statement/expression ambiguity as when passing an expression like
+	// "{ foo: bar() }\n['foo']()", which is both a valid Expression and a
+	// valid Program with a very different meaning.
+	JS string
+
+	// JSStr encapsulates a sequence of characters meant to be embedded
+	// between quotes in a JavaScript expression.
+	// The string must match a series of StringCharacters:
+	//   StringCharacter :: SourceCharacter but not `\` or LineTerminator
+	//                    | EscapeSequence
+	// Note that LineContinuations are not allowed.
+	// JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
+	JSStr string
+
+	// URL encapsulates a known safe URL as defined in RFC 3896.
+	// A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
+	// from a trusted source should go in the page, but by default dynamic
+	// `javascript:` URLs are filtered out since they are a frequently
+	// exploited injection vector.
+	URL string
+)
+
+type contentType uint8
+
+const (
+	contentTypePlain contentType = iota
+	contentTypeCSS
+	contentTypeHTML
+	contentTypeHTMLAttr
+	contentTypeJS
+	contentTypeJSStr
+	contentTypeURL
+	// contentTypeUnsafe is used in attr.go for values that affect how
+	// embedded content and network messages are formed, vetted,
+	// or interpreted; or which credentials network messages carry.
+	contentTypeUnsafe
+)
+
+// indirect returns the value, after dereferencing as many times
+// as necessary to reach the base type (or nil).
+func indirect(a interface{}) interface{} {
+	if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
+		// Avoid creating a reflect.Value if it's not a pointer.
+		return a
+	}
+	v := reflect.ValueOf(a)
+	for v.Kind() == reflect.Ptr && !v.IsNil() {
+		v = v.Elem()
+	}
+	return v.Interface()
+}
+
+// stringify converts its arguments to a string and the type of the content.
+// All pointers are dereferenced, as in the text/template package.
+func stringify(args ...interface{}) (string, contentType) {
+	if len(args) == 1 {
+		switch s := indirect(args[0]).(type) {
+		case string:
+			return s, contentTypePlain
+		case CSS:
+			return string(s), contentTypeCSS
+		case HTML:
+			return string(s), contentTypeHTML
+		case HTMLAttr:
+			return string(s), contentTypeHTMLAttr
+		case JS:
+			return string(s), contentTypeJS
+		case JSStr:
+			return string(s), contentTypeJSStr
+		case URL:
+			return string(s), contentTypeURL
+		}
+	}
+	for i, arg := range args {
+		args[i] = indirect(arg)
+	}
+	return fmt.Sprint(args...), contentTypePlain
+}
diff --git a/src/pkg/html/template/content_test.go b/src/pkg/html/template/content_test.go
new file mode 100644
index 0000000..c96a521
--- /dev/null
+++ b/src/pkg/html/template/content_test.go
@@ -0,0 +1,221 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+)
+
+func TestTypedContent(t *testing.T) {
+	data := []interface{}{
+		`<b> "foo%" O'Reilly &bar;`,
+		CSS(`a[href =~ "//example.com"]#foo`),
+		HTML(`Hello, <b>World</b> &tc!`),
+		HTMLAttr(` dir="ltr"`),
+		JS(`c && alert("Hello, World!");`),
+		JSStr(`Hello, World & O'Reilly\x21`),
+		URL(`greeting=H%69&addressee=(World)`),
+	}
+
+	// For each content sensitive escaper, see how it does on
+	// each of the typed strings above.
+	tests := []struct {
+		// A template containing a single {{.}}.
+		input string
+		want  []string
+	}{
+		{
+			`<style>{{.}} { color: blue }</style>`,
+			[]string{
+				`ZgotmplZ`,
+				// Allowed but not escaped.
+				`a[href =~ "//example.com"]#foo`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+			},
+		},
+		{
+			`<div style="{{.}}">`,
+			[]string{
+				`ZgotmplZ`,
+				// Allowed and HTML escaped.
+				`a[href =~ "//example.com"]#foo`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+			},
+		},
+		{
+			`{{.}}`,
+			[]string{
+				`<b> "foo%" O'Reilly &bar;`,
+				`a[href =~ "//example.com"]#foo`,
+				// Not escaped.
+				`Hello, <b>World</b> &tc!`,
+				` dir="ltr"`,
+				`c && alert("Hello, World!");`,
+				`Hello, World & O'Reilly\x21`,
+				`greeting=H%69&addressee=(World)`,
+			},
+		},
+		{
+			`<a{{.}}>`,
+			[]string{
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				// Allowed and HTML escaped.
+				` dir="ltr"`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+				`ZgotmplZ`,
+			},
+		},
+		{
+			`<a title={{.}}>`,
+			[]string{
+				`<b> "foo%" O'Reilly &bar;`,
+				`a[href =~ "//example.com"]#foo`,
+				// Tags stripped, spaces escaped, entity not re-escaped.
+				`Hello, World &tc!`,
+				` dir="ltr"`,
+				`c && alert("Hello, World!");`,
+				`Hello, World & O'Reilly\x21`,
+				`greeting=H%69&addressee=(World)`,
+			},
+		},
+		{
+			`<a title='{{.}}'>`,
+			[]string{
+				`<b> "foo%" O'Reilly &bar;`,
+				`a[href =~ "//example.com"]#foo`,
+				// Tags stripped, entity not re-escaped.
+				`Hello, World &tc!`,
+				` dir="ltr"`,
+				`c && alert("Hello, World!");`,
+				`Hello, World & O'Reilly\x21`,
+				`greeting=H%69&addressee=(World)`,
+			},
+		},
+		{
+			`<textarea>{{.}}</textarea>`,
+			[]string{
+				`<b> "foo%" O'Reilly &bar;`,
+				`a[href =~ "//example.com"]#foo`,
+				// Angle brackets escaped to prevent injection of close tags, entity not re-escaped.
+				`Hello, <b>World</b> &tc!`,
+				` dir="ltr"`,
+				`c && alert("Hello, World!");`,
+				`Hello, World & O'Reilly\x21`,
+				`greeting=H%69&addressee=(World)`,
+			},
+		},
+		{
+			`<script>alert({{.}})</script>`,
+			[]string{
+				`"\u003cb\u003e \"foo%\" O'Reilly &bar;"`,
+				`"a[href =~ \"//example.com\"]#foo"`,
+				`"Hello, \u003cb\u003eWorld\u003c/b\u003e &tc!"`,
+				`" dir=\"ltr\""`,
+				// Not escaped.
+				`c && alert("Hello, World!");`,
+				// Escape sequence not over-escaped.
+				`"Hello, World & O'Reilly\x21"`,
+				`"greeting=H%69&addressee=(World)"`,
+			},
+		},
+		{
+			`<button onclick="alert({{.}})">`,
+			[]string{
+				`"\u003cb\u003e \"foo%\" O'Reilly &bar;"`,
+				`"a[href =~ \"//example.com\"]#foo"`,
+				`"Hello, \u003cb\u003eWorld\u003c/b\u003e &amp;tc!"`,
+				`" dir=\"ltr\""`,
+				// Not JS escaped but HTML escaped.
+				`c && alert("Hello, World!");`,
+				// Escape sequence not over-escaped.
+				`"Hello, World & O'Reilly\x21"`,
+				`"greeting=H%69&addressee=(World)"`,
+			},
+		},
+		{
+			`<script>alert("{{.}}")</script>`,
+			[]string{
+				`\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
+				`a[href =~ \x22\/\/example.com\x22]#foo`,
+				`Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
+				` dir=\x22ltr\x22`,
+				`c \x26\x26 alert(\x22Hello, World!\x22);`,
+				// Escape sequence not over-escaped.
+				`Hello, World \x26 O\x27Reilly\x21`,
+				`greeting=H%69\x26addressee=(World)`,
+			},
+		},
+		{
+			`<button onclick='alert("{{.}}")'>`,
+			[]string{
+				`\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
+				`a[href =~ \x22\/\/example.com\x22]#foo`,
+				`Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
+				` dir=\x22ltr\x22`,
+				`c \x26\x26 alert(\x22Hello, World!\x22);`,
+				// Escape sequence not over-escaped.
+				`Hello, World \x26 O\x27Reilly\x21`,
+				`greeting=H%69\x26addressee=(World)`,
+			},
+		},
+		{
+			`<a href="?q={{.}}">`,
+			[]string{
+				`%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
+				`a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
+				`Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
+				`%20dir%3d%22ltr%22`,
+				`c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
+				`Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
+				// Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is done.
+				`greeting=H%69&addressee=%28World%29`,
+			},
+		},
+		{
+			`<style>body { background: url('?img={{.}}') }</style>`,
+			[]string{
+				`%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
+				`a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
+				`Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
+				`%20dir%3d%22ltr%22`,
+				`c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
+				`Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
+				// Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is not done.
+				`greeting=H%69&addressee=%28World%29`,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		tmpl := Must(New("x").Parse(test.input))
+		pre := strings.Index(test.input, "{{.}}")
+		post := len(test.input) - (pre + 5)
+		var b bytes.Buffer
+		for i, x := range data {
+			b.Reset()
+			if err := tmpl.Execute(&b, x); err != nil {
+				t.Errorf("%q with %v: %s", test.input, x, err)
+				continue
+			}
+			if want, got := test.want[i], b.String()[pre:b.Len()-post]; want != got {
+				t.Errorf("%q with %v:\nwant\n\t%q,\ngot\n\t%q\n", test.input, x, want, got)
+				continue
+			}
+		}
+	}
+}
diff --git a/src/pkg/html/template/context.go b/src/pkg/html/template/context.go
new file mode 100644
index 0000000..7202221
--- /dev/null
+++ b/src/pkg/html/template/context.go
@@ -0,0 +1,339 @@
+// Copyright 2011 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 template
+
+import (
+	"fmt"
+)
+
+// context describes the state an HTML parser must be in when it reaches the
+// portion of HTML produced by evaluating a particular template node.
+//
+// The zero value of type context is the start context for a template that
+// produces an HTML fragment as defined at
+// http://www.w3.org/TR/html5/the-end.html#parsing-html-fragments
+// where the context element is null.
+type context struct {
+	state   state
+	delim   delim
+	urlPart urlPart
+	jsCtx   jsCtx
+	attr    attr
+	element element
+	err     *Error
+}
+
+func (c context) String() string {
+	return fmt.Sprintf("{%v %v %v %v %v %v %v}", c.state, c.delim, c.urlPart, c.jsCtx, c.attr, c.element, c.err)
+}
+
+// eq returns whether two contexts are equal.
+func (c context) eq(d context) bool {
+	return c.state == d.state &&
+		c.delim == d.delim &&
+		c.urlPart == d.urlPart &&
+		c.jsCtx == d.jsCtx &&
+		c.attr == d.attr &&
+		c.element == d.element &&
+		c.err == d.err
+}
+
+// mangle produces an identifier that includes a suffix that distinguishes it
+// from template names mangled with different contexts.
+func (c context) mangle(templateName string) string {
+	// The mangled name for the default context is the input templateName.
+	if c.state == stateText {
+		return templateName
+	}
+	s := templateName + "$htmltemplate_" + c.state.String()
+	if c.delim != 0 {
+		s += "_" + c.delim.String()
+	}
+	if c.urlPart != 0 {
+		s += "_" + c.urlPart.String()
+	}
+	if c.jsCtx != 0 {
+		s += "_" + c.jsCtx.String()
+	}
+	if c.attr != 0 {
+		s += "_" + c.attr.String()
+	}
+	if c.element != 0 {
+		s += "_" + c.element.String()
+	}
+	return s
+}
+
+// state describes a high-level HTML parser state.
+//
+// It bounds the top of the element stack, and by extension the HTML insertion
+// mode, but also contains state that does not correspond to anything in the
+// HTML5 parsing algorithm because a single token production in the HTML
+// grammar may contain embedded actions in a template. For instance, the quoted
+// HTML attribute produced by
+//     <div title="Hello {{.World}}">
+// is a single token in HTML's grammar but in a template spans several nodes.
+type state uint8
+
+const (
+	// stateText is parsed character data. An HTML parser is in
+	// this state when its parse position is outside an HTML tag,
+	// directive, comment, and special element body.
+	stateText state = iota
+	// stateTag occurs before an HTML attribute or the end of a tag.
+	stateTag
+	// stateAttrName occurs inside an attribute name.
+	// It occurs between the ^'s in ` ^name^ = value`.
+	stateAttrName
+	// stateAfterName occurs after an attr name has ended but before any
+	// equals sign. It occurs between the ^'s in ` name^ ^= value`.
+	stateAfterName
+	// stateBeforeValue occurs after the equals sign but before the value.
+	// It occurs between the ^'s in ` name =^ ^value`.
+	stateBeforeValue
+	// stateHTMLCmt occurs inside an <!-- HTML comment -->.
+	stateHTMLCmt
+	// stateRCDATA occurs inside an RCDATA element (<textarea> or <title>)
+	// as described at http://dev.w3.org/html5/spec/syntax.html#elements-0
+	stateRCDATA
+	// stateAttr occurs inside an HTML attribute whose content is text.
+	stateAttr
+	// stateURL occurs inside an HTML attribute whose content is a URL.
+	stateURL
+	// stateJS occurs inside an event handler or script element.
+	stateJS
+	// stateJSDqStr occurs inside a JavaScript double quoted string.
+	stateJSDqStr
+	// stateJSSqStr occurs inside a JavaScript single quoted string.
+	stateJSSqStr
+	// stateJSRegexp occurs inside a JavaScript regexp literal.
+	stateJSRegexp
+	// stateJSBlockCmt occurs inside a JavaScript /* block comment */.
+	stateJSBlockCmt
+	// stateJSLineCmt occurs inside a JavaScript // line comment.
+	stateJSLineCmt
+	// stateCSS occurs inside a <style> element or style attribute.
+	stateCSS
+	// stateCSSDqStr occurs inside a CSS double quoted string.
+	stateCSSDqStr
+	// stateCSSSqStr occurs inside a CSS single quoted string.
+	stateCSSSqStr
+	// stateCSSDqURL occurs inside a CSS double quoted url("...").
+	stateCSSDqURL
+	// stateCSSSqURL occurs inside a CSS single quoted url('...').
+	stateCSSSqURL
+	// stateCSSURL occurs inside a CSS unquoted url(...).
+	stateCSSURL
+	// stateCSSBlockCmt occurs inside a CSS /* block comment */.
+	stateCSSBlockCmt
+	// stateCSSLineCmt occurs inside a CSS // line comment.
+	stateCSSLineCmt
+	// stateError is an infectious error state outside any valid
+	// HTML/CSS/JS construct.
+	stateError
+)
+
+var stateNames = [...]string{
+	stateText:        "stateText",
+	stateTag:         "stateTag",
+	stateAttrName:    "stateAttrName",
+	stateAfterName:   "stateAfterName",
+	stateBeforeValue: "stateBeforeValue",
+	stateHTMLCmt:     "stateHTMLCmt",
+	stateRCDATA:      "stateRCDATA",
+	stateAttr:        "stateAttr",
+	stateURL:         "stateURL",
+	stateJS:          "stateJS",
+	stateJSDqStr:     "stateJSDqStr",
+	stateJSSqStr:     "stateJSSqStr",
+	stateJSRegexp:    "stateJSRegexp",
+	stateJSBlockCmt:  "stateJSBlockCmt",
+	stateJSLineCmt:   "stateJSLineCmt",
+	stateCSS:         "stateCSS",
+	stateCSSDqStr:    "stateCSSDqStr",
+	stateCSSSqStr:    "stateCSSSqStr",
+	stateCSSDqURL:    "stateCSSDqURL",
+	stateCSSSqURL:    "stateCSSSqURL",
+	stateCSSURL:      "stateCSSURL",
+	stateCSSBlockCmt: "stateCSSBlockCmt",
+	stateCSSLineCmt:  "stateCSSLineCmt",
+	stateError:       "stateError",
+}
+
+func (s state) String() string {
+	if int(s) < len(stateNames) {
+		return stateNames[s]
+	}
+	return fmt.Sprintf("illegal state %d", int(s))
+}
+
+// isComment is true for any state that contains content meant for template
+// authors & maintainers, not for end-users or machines.
+func isComment(s state) bool {
+	switch s {
+	case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
+		return true
+	}
+	return false
+}
+
+// isInTag return whether s occurs solely inside an HTML tag.
+func isInTag(s state) bool {
+	switch s {
+	case stateTag, stateAttrName, stateAfterName, stateBeforeValue, stateAttr:
+		return true
+	}
+	return false
+}
+
+// delim is the delimiter that will end the current HTML attribute.
+type delim uint8
+
+const (
+	// delimNone occurs outside any attribute.
+	delimNone delim = iota
+	// delimDoubleQuote occurs when a double quote (") closes the attribute.
+	delimDoubleQuote
+	// delimSingleQuote occurs when a single quote (') closes the attribute.
+	delimSingleQuote
+	// delimSpaceOrTagEnd occurs when a space or right angle bracket (>)
+	// closes the attribute.
+	delimSpaceOrTagEnd
+)
+
+var delimNames = [...]string{
+	delimNone:          "delimNone",
+	delimDoubleQuote:   "delimDoubleQuote",
+	delimSingleQuote:   "delimSingleQuote",
+	delimSpaceOrTagEnd: "delimSpaceOrTagEnd",
+}
+
+func (d delim) String() string {
+	if int(d) < len(delimNames) {
+		return delimNames[d]
+	}
+	return fmt.Sprintf("illegal delim %d", int(d))
+}
+
+// urlPart identifies a part in an RFC 3986 hierarchical URL to allow different
+// encoding strategies.
+type urlPart uint8
+
+const (
+	// urlPartNone occurs when not in a URL, or possibly at the start:
+	// ^ in "^http://auth/path?k=v#frag".
+	urlPartNone urlPart = iota
+	// urlPartPreQuery occurs in the scheme, authority, or path; between the
+	// ^s in "h^ttp://auth/path^?k=v#frag".
+	urlPartPreQuery
+	// urlPartQueryOrFrag occurs in the query portion between the ^s in
+	// "http://auth/path?^k=v#frag^".
+	urlPartQueryOrFrag
+	// urlPartUnknown occurs due to joining of contexts both before and
+	// after the query separator.
+	urlPartUnknown
+)
+
+var urlPartNames = [...]string{
+	urlPartNone:        "urlPartNone",
+	urlPartPreQuery:    "urlPartPreQuery",
+	urlPartQueryOrFrag: "urlPartQueryOrFrag",
+	urlPartUnknown:     "urlPartUnknown",
+}
+
+func (u urlPart) String() string {
+	if int(u) < len(urlPartNames) {
+		return urlPartNames[u]
+	}
+	return fmt.Sprintf("illegal urlPart %d", int(u))
+}
+
+// jsCtx determines whether a '/' starts a regular expression literal or a
+// division operator.
+type jsCtx uint8
+
+const (
+	// jsCtxRegexp occurs where a '/' would start a regexp literal.
+	jsCtxRegexp jsCtx = iota
+	// jsCtxDivOp occurs where a '/' would start a division operator.
+	jsCtxDivOp
+	// jsCtxUnknown occurs where a '/' is ambiguous due to context joining.
+	jsCtxUnknown
+)
+
+func (c jsCtx) String() string {
+	switch c {
+	case jsCtxRegexp:
+		return "jsCtxRegexp"
+	case jsCtxDivOp:
+		return "jsCtxDivOp"
+	case jsCtxUnknown:
+		return "jsCtxUnknown"
+	}
+	return fmt.Sprintf("illegal jsCtx %d", int(c))
+}
+
+// element identifies the HTML element when inside a start tag or special body.
+// Certain HTML element (for example <script> and <style>) have bodies that are
+// treated differently from stateText so the element type is necessary to
+// transition into the correct context at the end of a tag and to identify the
+// end delimiter for the body.
+type element uint8
+
+const (
+	// elementNone occurs outside a special tag or special element body.
+	elementNone element = iota
+	// elementScript corresponds to the raw text <script> element.
+	elementScript
+	// elementStyle corresponds to the raw text <style> element.
+	elementStyle
+	// elementTextarea corresponds to the RCDATA <textarea> element.
+	elementTextarea
+	// elementTitle corresponds to the RCDATA <title> element.
+	elementTitle
+)
+
+var elementNames = [...]string{
+	elementNone:     "elementNone",
+	elementScript:   "elementScript",
+	elementStyle:    "elementStyle",
+	elementTextarea: "elementTextarea",
+	elementTitle:    "elementTitle",
+}
+
+func (e element) String() string {
+	if int(e) < len(elementNames) {
+		return elementNames[e]
+	}
+	return fmt.Sprintf("illegal element %d", int(e))
+}
+
+// attr identifies the most recent HTML attribute when inside a start tag.
+type attr uint8
+
+const (
+	// attrNone corresponds to a normal attribute or no attribute.
+	attrNone attr = iota
+	// attrScript corresponds to an event handler attribute.
+	attrScript
+	// attrStyle corresponds to the style attribute whose value is CSS.
+	attrStyle
+	// attrURL corresponds to an attribute whose value is a URL.
+	attrURL
+)
+
+var attrNames = [...]string{
+	attrNone:   "attrNone",
+	attrScript: "attrScript",
+	attrStyle:  "attrStyle",
+	attrURL:    "attrURL",
+}
+
+func (a attr) String() string {
+	if int(a) < len(attrNames) {
+		return attrNames[a]
+	}
+	return fmt.Sprintf("illegal attr %d", int(a))
+}
diff --git a/src/pkg/html/template/css.go b/src/pkg/html/template/css.go
new file mode 100644
index 0000000..3bcd984
--- /dev/null
+++ b/src/pkg/html/template/css.go
@@ -0,0 +1,268 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"fmt"
+	"unicode"
+	"unicode/utf8"
+)
+
+// endsWithCSSKeyword returns whether b ends with an ident that
+// case-insensitively matches the lower-case kw.
+func endsWithCSSKeyword(b []byte, kw string) bool {
+	i := len(b) - len(kw)
+	if i < 0 {
+		// Too short.
+		return false
+	}
+	if i != 0 {
+		r, _ := utf8.DecodeLastRune(b[:i])
+		if isCSSNmchar(r) {
+			// Too long.
+			return false
+		}
+	}
+	// Many CSS keywords, such as "!important" can have characters encoded,
+	// but the URI production does not allow that according to
+	// http://www.w3.org/TR/css3-syntax/#TOK-URI
+	// This does not attempt to recognize encoded keywords. For example,
+	// given "\75\72\6c" and "url" this return false.
+	return string(bytes.ToLower(b[i:])) == kw
+}
+
+// isCSSNmchar returns whether rune is allowed anywhere in a CSS identifier.
+func isCSSNmchar(r rune) bool {
+	// Based on the CSS3 nmchar production but ignores multi-rune escape
+	// sequences.
+	// http://www.w3.org/TR/css3-syntax/#SUBTOK-nmchar
+	return 'a' <= r && r <= 'z' ||
+		'A' <= r && r <= 'Z' ||
+		'0' <= r && r <= '9' ||
+		r == '-' ||
+		r == '_' ||
+		// Non-ASCII cases below.
+		0x80 <= r && r <= 0xd7ff ||
+		0xe000 <= r && r <= 0xfffd ||
+		0x10000 <= r && r <= 0x10ffff
+}
+
+// decodeCSS decodes CSS3 escapes given a sequence of stringchars.
+// If there is no change, it returns the input, otherwise it returns a slice
+// backed by a new array.
+// http://www.w3.org/TR/css3-syntax/#SUBTOK-stringchar defines stringchar.
+func decodeCSS(s []byte) []byte {
+	i := bytes.IndexByte(s, '\\')
+	if i == -1 {
+		return s
+	}
+	// The UTF-8 sequence for a codepoint is never longer than 1 + the
+	// number hex digits need to represent that codepoint, so len(s) is an
+	// upper bound on the output length.
+	b := make([]byte, 0, len(s))
+	for len(s) != 0 {
+		i := bytes.IndexByte(s, '\\')
+		if i == -1 {
+			i = len(s)
+		}
+		b, s = append(b, s[:i]...), s[i:]
+		if len(s) < 2 {
+			break
+		}
+		// http://www.w3.org/TR/css3-syntax/#SUBTOK-escape
+		// escape ::= unicode | '\' [#x20-#x7E#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
+		if isHex(s[1]) {
+			// http://www.w3.org/TR/css3-syntax/#SUBTOK-unicode
+			//   unicode ::= '\' [0-9a-fA-F]{1,6} wc?
+			j := 2
+			for j < len(s) && j < 7 && isHex(s[j]) {
+				j++
+			}
+			r := hexDecode(s[1:j])
+			if r > unicode.MaxRune {
+				r, j = r/16, j-1
+			}
+			n := utf8.EncodeRune(b[len(b):cap(b)], r)
+			// The optional space at the end allows a hex
+			// sequence to be followed by a literal hex.
+			// string(decodeCSS([]byte(`\A B`))) == "\nB"
+			b, s = b[:len(b)+n], skipCSSSpace(s[j:])
+		} else {
+			// `\\` decodes to `\` and `\"` to `"`.
+			_, n := utf8.DecodeRune(s[1:])
+			b, s = append(b, s[1:1+n]...), s[1+n:]
+		}
+	}
+	return b
+}
+
+// isHex returns whether the given character is a hex digit.
+func isHex(c byte) bool {
+	return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
+}
+
+// hexDecode decodes a short hex digit sequence: "10" -> 16.
+func hexDecode(s []byte) rune {
+	n := '\x00'
+	for _, c := range s {
+		n <<= 4
+		switch {
+		case '0' <= c && c <= '9':
+			n |= rune(c - '0')
+		case 'a' <= c && c <= 'f':
+			n |= rune(c-'a') + 10
+		case 'A' <= c && c <= 'F':
+			n |= rune(c-'A') + 10
+		default:
+			panic(fmt.Sprintf("Bad hex digit in %q", s))
+		}
+	}
+	return n
+}
+
+// skipCSSSpace returns a suffix of c, skipping over a single space.
+func skipCSSSpace(c []byte) []byte {
+	if len(c) == 0 {
+		return c
+	}
+	// wc ::= #x9 | #xA | #xC | #xD | #x20
+	switch c[0] {
+	case '\t', '\n', '\f', ' ':
+		return c[1:]
+	case '\r':
+		// This differs from CSS3's wc production because it contains a
+		// probable spec error whereby wc contains all the single byte
+		// sequences in nl (newline) but not CRLF.
+		if len(c) >= 2 && c[1] == '\n' {
+			return c[2:]
+		}
+		return c[1:]
+	}
+	return c
+}
+
+// isCSSSpace returns whether b is a CSS space char as defined in wc.
+func isCSSSpace(b byte) bool {
+	switch b {
+	case '\t', '\n', '\f', '\r', ' ':
+		return true
+	}
+	return false
+}
+
+// cssEscaper escapes HTML and CSS special characters using \<hex>+ escapes.
+func cssEscaper(args ...interface{}) string {
+	s, _ := stringify(args...)
+	var b bytes.Buffer
+	written := 0
+	for i, r := range s {
+		var repl string
+		switch r {
+		case 0:
+			repl = `\0`
+		case '\t':
+			repl = `\9`
+		case '\n':
+			repl = `\a`
+		case '\f':
+			repl = `\c`
+		case '\r':
+			repl = `\d`
+		// Encode HTML specials as hex so the output can be embedded
+		// in HTML attributes without further encoding.
+		case '"':
+			repl = `\22`
+		case '&':
+			repl = `\26`
+		case '\'':
+			repl = `\27`
+		case '(':
+			repl = `\28`
+		case ')':
+			repl = `\29`
+		case '+':
+			repl = `\2b`
+		case '/':
+			repl = `\2f`
+		case ':':
+			repl = `\3a`
+		case ';':
+			repl = `\3b`
+		case '<':
+			repl = `\3c`
+		case '>':
+			repl = `\3e`
+		case '\\':
+			repl = `\\`
+		case '{':
+			repl = `\7b`
+		case '}':
+			repl = `\7d`
+		default:
+			continue
+		}
+		b.WriteString(s[written:i])
+		b.WriteString(repl)
+		written = i + utf8.RuneLen(r)
+		if repl != `\\` && (written == len(s) || isHex(s[written]) || isCSSSpace(s[written])) {
+			b.WriteByte(' ')
+		}
+	}
+	if written == 0 {
+		return s
+	}
+	b.WriteString(s[written:])
+	return b.String()
+}
+
+var expressionBytes = []byte("expression")
+var mozBindingBytes = []byte("mozbinding")
+
+// cssValueFilter allows innocuous CSS values in the output including CSS
+// quantities (10px or 25%), ID or class literals (#foo, .bar), keyword values
+// (inherit, blue), and colors (#888).
+// It filters out unsafe values, such as those that affect token boundaries,
+// and anything that might execute scripts.
+func cssValueFilter(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeCSS {
+		return s
+	}
+	b, id := decodeCSS([]byte(s)), make([]byte, 0, 64)
+
+	// CSS3 error handling is specified as honoring string boundaries per
+	// http://www.w3.org/TR/css3-syntax/#error-handling :
+	//     Malformed declarations. User agents must handle unexpected
+	//     tokens encountered while parsing a declaration by reading until
+	//     the end of the declaration, while observing the rules for
+	//     matching pairs of (), [], {}, "", and '', and correctly handling
+	//     escapes. For example, a malformed declaration may be missing a
+	//     property, colon (:) or value.
+	// So we need to make sure that values do not have mismatched bracket
+	// or quote characters to prevent the browser from restarting parsing
+	// inside a string that might embed JavaScript source.
+	for i, c := range b {
+		switch c {
+		case 0, '"', '\'', '(', ')', '/', ';', '@', '[', '\\', ']', '`', '{', '}':
+			return filterFailsafe
+		case '-':
+			// Disallow <!-- or -->.
+			// -- should not appear in valid identifiers.
+			if i != 0 && b[i-1] == '-' {
+				return filterFailsafe
+			}
+		default:
+			if c < 0x80 && isCSSNmchar(rune(c)) {
+				id = append(id, c)
+			}
+		}
+	}
+	id = bytes.ToLower(id)
+	if bytes.Index(id, expressionBytes) != -1 || bytes.Index(id, mozBindingBytes) != -1 {
+		return filterFailsafe
+	}
+	return string(b)
+}
diff --git a/src/pkg/html/template/css_test.go b/src/pkg/html/template/css_test.go
new file mode 100644
index 0000000..a735638
--- /dev/null
+++ b/src/pkg/html/template/css_test.go
@@ -0,0 +1,281 @@
+// Copyright 2011 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 template
+
+import (
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func TestEndsWithCSSKeyword(t *testing.T) {
+	tests := []struct {
+		css, kw string
+		want    bool
+	}{
+		{"", "url", false},
+		{"url", "url", true},
+		{"URL", "url", true},
+		{"Url", "url", true},
+		{"url", "important", false},
+		{"important", "important", true},
+		{"image-url", "url", false},
+		{"imageurl", "url", false},
+		{"image url", "url", true},
+	}
+	for _, test := range tests {
+		got := endsWithCSSKeyword([]byte(test.css), test.kw)
+		if got != test.want {
+			t.Errorf("want %t but got %t for css=%v, kw=%v", test.want, got, test.css, test.kw)
+		}
+	}
+}
+
+func TestIsCSSNmchar(t *testing.T) {
+	tests := []struct {
+		rune rune
+		want bool
+	}{
+		{0, false},
+		{'0', true},
+		{'9', true},
+		{'A', true},
+		{'Z', true},
+		{'a', true},
+		{'z', true},
+		{'_', true},
+		{'-', true},
+		{':', false},
+		{';', false},
+		{' ', false},
+		{0x7f, false},
+		{0x80, true},
+		{0x1234, true},
+		{0xd800, false},
+		{0xdc00, false},
+		{0xfffe, false},
+		{0x10000, true},
+		{0x110000, false},
+	}
+	for _, test := range tests {
+		got := isCSSNmchar(test.rune)
+		if got != test.want {
+			t.Errorf("%q: want %t but got %t", string(test.rune), test.want, got)
+		}
+	}
+}
+
+func TestDecodeCSS(t *testing.T) {
+	tests := []struct {
+		css, want string
+	}{
+		{``, ``},
+		{`foo`, `foo`},
+		{`foo\`, `foo`},
+		{`foo\\`, `foo\`},
+		{`\`, ``},
+		{`\A`, "\n"},
+		{`\a`, "\n"},
+		{`\0a`, "\n"},
+		{`\00000a`, "\n"},
+		{`\000000a`, "\u0000a"},
+		{`\1234 5`, "\u1234" + "5"},
+		{`\1234\20 5`, "\u1234" + " 5"},
+		{`\1234\A 5`, "\u1234" + "\n5"},
+		{"\\1234\t5", "\u1234" + "5"},
+		{"\\1234\n5", "\u1234" + "5"},
+		{"\\1234\r\n5", "\u1234" + "5"},
+		{`\12345`, "\U00012345"},
+		{`\\`, `\`},
+		{`\\ `, `\ `},
+		{`\"`, `"`},
+		{`\'`, `'`},
+		{`\.`, `.`},
+		{`\. .`, `. .`},
+		{
+			`The \3c i\3equick\3c/i\3e,\d\A\3cspan style=\27 color:brown\27\3e brown\3c/span\3e  fox jumps\2028over the \3c canine class=\22lazy\22 \3e dog\3c/canine\3e`,
+			"The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>",
+		},
+	}
+	for _, test := range tests {
+		got1 := string(decodeCSS([]byte(test.css)))
+		if got1 != test.want {
+			t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.css, test.want, got1)
+		}
+		recoded := cssEscaper(got1)
+		if got2 := string(decodeCSS([]byte(recoded))); got2 != test.want {
+			t.Errorf("%q: escape & decode not dual for %q", test.css, recoded)
+		}
+	}
+}
+
+func TestHexDecode(t *testing.T) {
+	for i := 0; i < 0x200000; i += 101 /* coprime with 16 */ {
+		s := strconv.FormatInt(int64(i), 16)
+		if got := int(hexDecode([]byte(s))); got != i {
+			t.Errorf("%s: want %d but got %d", s, i, got)
+		}
+		s = strings.ToUpper(s)
+		if got := int(hexDecode([]byte(s))); got != i {
+			t.Errorf("%s: want %d but got %d", s, i, got)
+		}
+	}
+}
+
+func TestSkipCSSSpace(t *testing.T) {
+	tests := []struct {
+		css, want string
+	}{
+		{"", ""},
+		{"foo", "foo"},
+		{"\n", ""},
+		{"\r\n", ""},
+		{"\r", ""},
+		{"\t", ""},
+		{" ", ""},
+		{"\f", ""},
+		{" foo", "foo"},
+		{"  foo", " foo"},
+		{`\20`, `\20`},
+	}
+	for _, test := range tests {
+		got := string(skipCSSSpace([]byte(test.css)))
+		if got != test.want {
+			t.Errorf("%q: want %q but got %q", test.css, test.want, got)
+		}
+	}
+}
+
+func TestCSSEscaper(t *testing.T) {
+	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		"`abcdefghijklmno" +
+		"pqrstuvwxyz{|}~\x7f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+	want := ("\\0\x01\x02\x03\x04\x05\x06\x07" +
+		"\x08\\9 \\a\x0b\\c \\d\x0E\x0F" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17" +
+		"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !\22#$%\26\27\28\29*\2b,-.\2f ` +
+		`0123456789\3a\3b\3c=\3e?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\\]^_` +
+		"`abcdefghijklmno" +
+		`pqrstuvwxyz\7b|\7d~` + "\u007f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+	got := cssEscaper(input)
+	if got != want {
+		t.Errorf("encode: want\n\t%q\nbut got\n\t%q", want, got)
+	}
+
+	got = string(decodeCSS([]byte(got)))
+	if input != got {
+		t.Errorf("decode: want\n\t%q\nbut got\n\t%q", input, got)
+	}
+}
+
+func TestCSSValueFilter(t *testing.T) {
+	tests := []struct {
+		css, want string
+	}{
+		{"", ""},
+		{"foo", "foo"},
+		{"0", "0"},
+		{"0px", "0px"},
+		{"-5px", "-5px"},
+		{"1.25in", "1.25in"},
+		{"+.33em", "+.33em"},
+		{"100%", "100%"},
+		{"12.5%", "12.5%"},
+		{".foo", ".foo"},
+		{"#bar", "#bar"},
+		{"corner-radius", "corner-radius"},
+		{"-moz-corner-radius", "-moz-corner-radius"},
+		{"#000", "#000"},
+		{"#48f", "#48f"},
+		{"#123456", "#123456"},
+		{"U+00-FF, U+980-9FF", "U+00-FF, U+980-9FF"},
+		{"color: red", "color: red"},
+		{"<!--", "ZgotmplZ"},
+		{"-->", "ZgotmplZ"},
+		{"<![CDATA[", "ZgotmplZ"},
+		{"]]>", "ZgotmplZ"},
+		{"</style", "ZgotmplZ"},
+		{`"`, "ZgotmplZ"},
+		{`'`, "ZgotmplZ"},
+		{"`", "ZgotmplZ"},
+		{"\x00", "ZgotmplZ"},
+		{"/* foo */", "ZgotmplZ"},
+		{"//", "ZgotmplZ"},
+		{"[href=~", "ZgotmplZ"},
+		{"expression(alert(1337))", "ZgotmplZ"},
+		{"-expression(alert(1337))", "ZgotmplZ"},
+		{"expression", "ZgotmplZ"},
+		{"Expression", "ZgotmplZ"},
+		{"EXPRESSION", "ZgotmplZ"},
+		{"-moz-binding", "ZgotmplZ"},
+		{"-expr\x00ession(alert(1337))", "ZgotmplZ"},
+		{`-expr\0ession(alert(1337))`, "ZgotmplZ"},
+		{`-express\69on(alert(1337))`, "ZgotmplZ"},
+		{`-express\69 on(alert(1337))`, "ZgotmplZ"},
+		{`-exp\72 ession(alert(1337))`, "ZgotmplZ"},
+		{`-exp\52 ession(alert(1337))`, "ZgotmplZ"},
+		{`-exp\000052 ession(alert(1337))`, "ZgotmplZ"},
+		{`-expre\0000073sion`, "-expre\x073sion"},
+		{`@import url evil.css`, "ZgotmplZ"},
+	}
+	for _, test := range tests {
+		got := cssValueFilter(test.css)
+		if got != test.want {
+			t.Errorf("%q: want %q but got %q", test.css, test.want, got)
+		}
+	}
+}
+
+func BenchmarkCSSEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		cssEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkCSSEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		cssEscaper("The quick, brown fox jumps over the lazy dog.")
+	}
+}
+
+func BenchmarkDecodeCSS(b *testing.B) {
+	s := []byte(`The \3c i\3equick\3c/i\3e,\d\A\3cspan style=\27 color:brown\27\3e brown\3c/span\3e fox jumps\2028over the \3c canine class=\22lazy\22 \3edog\3c/canine\3e`)
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		decodeCSS(s)
+	}
+}
+
+func BenchmarkDecodeCSSNoSpecials(b *testing.B) {
+	s := []byte("The quick, brown fox jumps over the lazy dog.")
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		decodeCSS(s)
+	}
+}
+
+func BenchmarkCSSValueFilter(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		cssValueFilter(`  e\78preS\0Sio/**/n(alert(1337))`)
+	}
+}
+
+func BenchmarkCSSValueFilterOk(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		cssValueFilter(`Times New Roman`)
+	}
+}
diff --git a/src/pkg/html/template/doc.go b/src/pkg/html/template/doc.go
new file mode 100644
index 0000000..77a9bf2
--- /dev/null
+++ b/src/pkg/html/template/doc.go
@@ -0,0 +1,186 @@
+// Copyright 2011 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 template (html/template) is a specialization of package text/template
+that automates the construction of HTML output that is safe against code
+injection.
+
+
+Introduction
+
+This package wraps package template so you can use the standard template API
+to parse and execute templates.
+
+  set, err := new(template.Set).Parse(...)
+  // Error checking elided
+  err = set.Execute(out, "Foo", data)
+
+If successful, set will now be injection-safe. Otherwise, err is an error
+defined in the docs for ErrorCode.
+
+HTML templates treat data values as plain text which should be encoded so they
+can be safely embedded in an HTML document. The escaping is contextual, so
+actions can appear within JavaScript, CSS, and URI contexts.
+
+The security model used by this package assumes that template authors are
+trusted, while Execute's data parameter is not. More details are provided below.
+
+Example
+
+  import "text/template"
+  ...
+  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
+  err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
+
+produces
+
+  Hello, <script>alert('you have been pwned')</script>!
+
+but with contextual autoescaping,
+
+  import "html/template"
+  ...
+  t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
+  err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
+
+produces safe, escaped HTML output
+
+  Hello, <script>alert('you have been pwned')</script>!
+
+
+Contexts
+
+This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
+functions to each simple action pipeline, so given the excerpt
+
+  <a href="/search?q={{.}}">{{.}}</a>
+
+At parse time each {{.}} is overwritten to add escaping functions as necessary.
+In this case it becomes
+
+  <a href="/search?q={{. | urlquery}}">{{. | html}}</a>
+
+
+Errors
+
+See the documentation of ErrorCode for details.
+
+
+A fuller picture
+
+The rest of this package comment may be skipped on first reading; it includes
+details necessary to understand escaping contexts and error messages. Most users
+will not need to understand these details.
+
+
+Contexts
+
+Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
+how {{.}} appears when used in the context to the left.
+
+  Context                          {{.}} After
+  {{.}}                            O'Reilly: How are <i>you</i>?
+  <a title='{{.}}'>                O'Reilly: How are you?
+  <a href="/{{.}}">                O'Reilly: How are %3ci%3eyou%3c/i%3e?
+  <a href="?q={{.}}">              O'Reilly%3a%20How%20are%3ci%3e...%3f
+  <a onx='f("{{.}}")'>             O\x27Reilly: How are \x3ci\x3eyou...?
+  <a onx='f({{.}})'>               "O\x27Reilly: How are \x3ci\x3eyou...?"
+  <a onx='pattern = /{{.}}/;'>     O\x27Reilly: How are \x3ci\x3eyou...\x3f
+
+If used in an unsafe context, then the value might be filtered out:
+
+  Context                          {{.}} After
+  <a href="{{.}}">                 #ZgotmplZ
+
+since "O'Reilly:" is not an allowed protocol like "http:".
+
+
+If {{.}} is the innocuous word, `left`, then it can appear more widely,
+
+  Context                              {{.}} After
+  {{.}}                                left
+  <a title='{{.}}'>                    left
+  <a href='{{.}}'>                     left
+  <a href='/{{.}}'>                    left
+  <a href='?dir={{.}}'>                left
+  <a style="border-{{.}}: 4px">        left
+  <a style="align: {{.}}">             left
+  <a style="background: '{{.}}'>       left
+  <a style="background: url('{{.}}')>  left
+  <style>p.{{.}} {color:red}</style>   left
+
+Non-string values can be used in JavaScript contexts.
+If {{.}} is
+
+  []struct{A,B string}{ "foo", "bar" }
+
+in the escaped template
+
+  <script>var pair = {{.}};</script>
+
+then the template output is
+
+  <script>var pair = {"A": "foo", "B": "bar"};</script>
+
+See package json to understand how non-string content is marshalled for
+embedding in JavaScript contexts.
+
+
+Typed Strings
+
+By default, this package assumes that all pipelines produce a plain text string.
+It adds escaping pipeline stages necessary to correctly and safely embed that
+plain text string in the appropriate context.
+
+When a data value is not plain text, you can make sure it is not over-escaped
+by marking it with its type.
+
+Types HTML, JS, URL, and others from content.go can carry safe content that is
+exempted from escaping.
+
+The template
+
+  Hello, {{.}}!
+
+can be invoked with
+
+  tmpl.Execute(out, HTML(`<b>World</b>`))
+
+to produce
+
+  Hello, <b>World</b>!
+
+instead of the
+
+  Hello, <b>World<b>!
+
+that would have been produced if {{.}} was a regular string.
+
+
+Security Model
+
+http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.
+
+This package assumes that template authors are trusted, that Execute's data
+parameter is not, and seeks to preserve the properties below in the face
+of untrusted data:
+
+Structure Preservation Property
+"... when a template author writes an HTML tag in a safe templating language,
+the browser will interpret the corresponding portion of the output as a tag
+regardless of the values of untrusted data, and similarly for other structures
+such as attribute boundaries and JS and CSS string boundaries."
+
+Code Effect Property
+"... only code specified by the template author should run as a result of
+injecting the template output into a page and all code specified by the
+template author should run as a result of the same."
+
+Least Surprise Property
+"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who
+knows that contextual autoescaping happens should be able to look at a {{.}}
+and correctly infer what sanitization happens."
+*/
+package template
diff --git a/src/pkg/html/template/error.go b/src/pkg/html/template/error.go
new file mode 100644
index 0000000..dcac748
--- /dev/null
+++ b/src/pkg/html/template/error.go
@@ -0,0 +1,197 @@
+// Copyright 2011 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 template
+
+import (
+	"fmt"
+)
+
+// Error describes a problem encountered during template Escaping.
+type Error struct {
+	// ErrorCode describes the kind of error.
+	ErrorCode ErrorCode
+	// Name is the name of the template in which the error was encountered.
+	Name string
+	// Line is the line number of the error in the template source or 0.
+	Line int
+	// Description is a human-readable description of the problem.
+	Description string
+}
+
+// ErrorCode is a code for a kind of error.
+type ErrorCode int
+
+// We define codes for each error that manifests while escaping templates, but
+// escaped templates may also fail at runtime.
+//
+// Output: "ZgotmplZ"
+// Example:
+//   <img src="{{.X}}">
+//   where {{.X}} evaluates to `javascript:...`
+// Discussion:
+//   "ZgotmplZ" is a special value that indicates that unsafe content reached a
+//   CSS or URL context at runtime. The output of the example will be
+//     <img src="#ZgotmplZ">
+//   If the data comes from a trusted source, use content types to exempt it
+//   from filtering: URL(`javascript:...`).
+const (
+	// OK indicates the lack of an error.
+	OK ErrorCode = iota
+
+	// ErrAmbigContext: "... appears in an ambiguous URL context"
+	// Example:
+	//   <a href="
+	//      {{if .C}}
+	//        /path/
+	//      {{else}}
+	//        /search?q=
+	//      {{end}}
+	//      {{.X}}
+	//   ">
+	// Discussion:
+	//   {{.X}} is in an ambiguous URL context since, depending on {{.C}},
+	//  it may be either a URL suffix or a query parameter.
+	//   Moving {{.X}} into the condition removes the ambiguity:
+	//   <a href="{{if .C}}/path/{{.X}}{{else}}/search?q={{.X}}">
+	ErrAmbigContext
+
+	// ErrBadHTML: "expected space, attr name, or end of tag, but got ...",
+	//   "... in unquoted attr", "... in attribute name"
+	// Example:
+	//   <a href = /search?q=foo>
+	//   <href=foo>
+	//   <form na<e=...>
+	//   <option selected<
+	// Discussion:
+	//   This is often due to a typo in an HTML element, but some runes
+	//   are banned in tag names, attribute names, and unquoted attribute
+	//   values because they can tickle parser ambiguities.
+	//   Quoting all attributes is the best policy.
+	ErrBadHTML
+
+	// ErrBranchEnd: "{{if}} branches end in different contexts"
+	// Example:
+	//   {{if .C}}<a href="{{end}}{{.X}}
+	// Discussion:
+	//   Package html/template statically examines each path through an
+	//   {{if}}, {{range}}, or {{with}} to escape any following pipelines.
+	//   The example is ambiguous since {{.X}} might be an HTML text node,
+	//   or a URL prefix in an HTML attribute. The context of {{.X}} is
+	//   used to figure out how to escape it, but that context depends on
+	//   the run-time value of {{.C}} which is not statically known.
+	//
+	//   The problem is usually something like missing quotes or angle
+	//   brackets, or can be avoided by refactoring to put the two contexts
+	//   into different branches of an if, range or with. If the problem
+	//   is in a {{range}} over a collection that should never be empty,
+	//   adding a dummy {{else}} can help.
+	ErrBranchEnd
+
+	// ErrEndContext: "... ends in a non-text context: ..."
+	// Examples:
+	//   <div
+	//   <div title="no close quote>
+	//   <script>f()
+	// Discussion:
+	//   Executed templates should produce a DocumentFragment of HTML.
+	//   Templates that end without closing tags will trigger this error.
+	//   Templates that should not be used in an HTML context or that
+	//   produce incomplete Fragments should not be executed directly.
+	//
+	//   {{define "main"}} <script>{{template "helper"}}</script> {{end}}
+	//   {{define "helper"}} document.write(' <div title=" ') {{end}}
+	// 
+	//   "helper" does not produce a valid document fragment, so should
+	//   not be Executed directly.
+	ErrEndContext
+
+	// ErrNoSuchTemplate: "no such template ..."
+	// Examples:
+	//   {{define "main"}}<div {{template "attrs"}}>{{end}}
+	//   {{define "attrs"}}href="{{.URL}}"{{end}}
+	// Discussion:
+	//   Package html/template looks through template calls to compute the
+	//   context.
+	//   Here the {{.URL}} in "attrs" must be treated as a URL when called
+	//   from "main", but you will get this error if "attrs" is not defined
+	//   when "main" is parsed.
+	ErrNoSuchTemplate
+
+	// ErrOutputContext: "cannot compute output context for template ..."
+	// Examples:
+	//   {{define "t"}}{{if .T}}{{template "t" .T}}{{end}}{{.H}}",{{end}}
+	// Discussion:
+	//   A recursive template does not end in the same context in which it
+	//   starts, and a reliable output context cannot be computed.
+	//   Look for typos in the named template.
+	//   If the template should not be called in the named start context,
+	//   look for calls to that template in unexpected contexts.
+	//   Maybe refactor recursive templates to not be recursive.
+	ErrOutputContext
+
+	// ErrPartialCharset: "unfinished JS regexp charset in ..."
+	// Example:
+	//     <script>var pattern = /foo[{{.Chars}}]/</script>
+	// Discussion:
+	//   Package html/template does not support interpolation into regular
+	//   expression literal character sets.
+	ErrPartialCharset
+
+	// ErrPartialEscape: "unfinished escape sequence in ..."
+	// Example:
+	//   <script>alert("\{{.X}}")</script>
+	// Discussion:
+	//   Package html/template does not support actions following a
+	//   backslash.
+	//   This is usually an error and there are better solutions; for
+	//   example
+	//     <script>alert("{{.X}}")</script>
+	//   should work, and if {{.X}} is a partial escape sequence such as
+	//   "xA0", mark the whole sequence as safe content: JSStr(`\xA0`)
+	ErrPartialEscape
+
+	// ErrRangeLoopReentry: "on range loop re-entry: ..."
+	// Example:
+	//   <script>var x = [{{range .}}'{{.}},{{end}}]</script>
+	// Discussion:
+	//   If an iteration through a range would cause it to end in a
+	//   different context than an earlier pass, there is no single context.
+	//   In the example, there is missing a quote, so it is not clear
+	//   whether {{.}} is meant to be inside a JS string or in a JS value
+	//   context.  The second iteration would produce something like
+	// 
+	//     <script>var x = ['firstValue,'secondValue]</script>
+	ErrRangeLoopReentry
+
+	// ErrSlashAmbig: '/' could start a division or regexp.
+	// Example:
+	//   <script>
+	//     {{if .C}}var x = 1{{end}}
+	//     /-{{.N}}/i.test(x) ? doThis : doThat();
+	//   </script>
+	// Discussion:
+	//   The example above could produce `var x = 1/-2/i.test(s)...`
+	//   in which the first '/' is a mathematical division operator or it
+	//   could produce `/-2/i.test(s)` in which the first '/' starts a
+	//   regexp literal.
+	//   Look for missing semicolons inside branches, and maybe add
+	//   parentheses to make it clear which interpretation you intend.
+	ErrSlashAmbig
+)
+
+func (e *Error) Error() string {
+	if e.Line != 0 {
+		return fmt.Sprintf("html/template:%s:%d: %s", e.Name, e.Line, e.Description)
+	} else if e.Name != "" {
+		return fmt.Sprintf("html/template:%s: %s", e.Name, e.Description)
+	}
+	return "html/template: " + e.Description
+}
+
+// errorf creates an error given a format string f and args.
+// The template Name still needs to be supplied.
+func errorf(k ErrorCode, line int, f string, args ...interface{}) *Error {
+	return &Error{k, "", line, fmt.Sprintf(f, args...)}
+}
diff --git a/src/pkg/html/template/escape.go b/src/pkg/html/template/escape.go
new file mode 100644
index 0000000..c6f723a
--- /dev/null
+++ b/src/pkg/html/template/escape.go
@@ -0,0 +1,753 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"fmt"
+	"html"
+	"text/template"
+	"text/template/parse"
+)
+
+// escapeTemplates rewrites the named templates, which must be
+// associated with t, to guarantee that the output of any of the named
+// templates is properly escaped.  Names should include the names of
+// all templates that might be Executed but need not include helper
+// templates.  If no error is returned, then the named templates have
+// been modified.  Otherwise the named templates have been rendered
+// unusable.
+func escapeTemplates(tmpl *Template, names ...string) error {
+	e := newEscaper(tmpl)
+	for _, name := range names {
+		c, _ := e.escapeTree(context{}, name, 0)
+		var err error
+		if c.err != nil {
+			err, c.err.Name = c.err, name
+		} else if c.state != stateText {
+			err = &Error{ErrEndContext, name, 0, fmt.Sprintf("ends in a non-text context: %v", c)}
+		}
+		if err != nil {
+			// Prevent execution of unsafe templates.
+			for _, name := range names {
+				if t := tmpl.set[name]; t != nil {
+					t.text.Tree = nil
+				}
+			}
+			return err
+		}
+		tmpl.escaped = true
+	}
+	e.commit()
+	return nil
+}
+
+// funcMap maps command names to functions that render their inputs safe.
+var funcMap = template.FuncMap{
+	"exp_template_html_attrescaper":     attrEscaper,
+	"exp_template_html_commentescaper":  commentEscaper,
+	"exp_template_html_cssescaper":      cssEscaper,
+	"exp_template_html_cssvaluefilter":  cssValueFilter,
+	"exp_template_html_htmlnamefilter":  htmlNameFilter,
+	"exp_template_html_htmlescaper":     htmlEscaper,
+	"exp_template_html_jsregexpescaper": jsRegexpEscaper,
+	"exp_template_html_jsstrescaper":    jsStrEscaper,
+	"exp_template_html_jsvalescaper":    jsValEscaper,
+	"exp_template_html_nospaceescaper":  htmlNospaceEscaper,
+	"exp_template_html_rcdataescaper":   rcdataEscaper,
+	"exp_template_html_urlescaper":      urlEscaper,
+	"exp_template_html_urlfilter":       urlFilter,
+	"exp_template_html_urlnormalizer":   urlNormalizer,
+}
+
+// equivEscapers matches contextual escapers to equivalent template builtins.
+var equivEscapers = map[string]string{
+	"exp_template_html_attrescaper":    "html",
+	"exp_template_html_htmlescaper":    "html",
+	"exp_template_html_nospaceescaper": "html",
+	"exp_template_html_rcdataescaper":  "html",
+	"exp_template_html_urlescaper":     "urlquery",
+	"exp_template_html_urlnormalizer":  "urlquery",
+}
+
+// escaper collects type inferences about templates and changes needed to make
+// templates injection safe.
+type escaper struct {
+	tmpl *Template
+	// output[templateName] is the output context for a templateName that
+	// has been mangled to include its input context.
+	output map[string]context
+	// derived[c.mangle(name)] maps to a template derived from the template
+	// named name templateName for the start context c.
+	derived map[string]*template.Template
+	// called[templateName] is a set of called mangled template names.
+	called map[string]bool
+	// xxxNodeEdits are the accumulated edits to apply during commit.
+	// Such edits are not applied immediately in case a template set
+	// executes a given template in different escaping contexts.
+	actionNodeEdits   map[*parse.ActionNode][]string
+	templateNodeEdits map[*parse.TemplateNode]string
+	textNodeEdits     map[*parse.TextNode][]byte
+}
+
+// newEscaper creates a blank escaper for the given set.
+func newEscaper(t *Template) *escaper {
+	return &escaper{
+		t,
+		map[string]context{},
+		map[string]*template.Template{},
+		map[string]bool{},
+		map[*parse.ActionNode][]string{},
+		map[*parse.TemplateNode]string{},
+		map[*parse.TextNode][]byte{},
+	}
+}
+
+// filterFailsafe is an innocuous word that is emitted in place of unsafe values
+// by sanitizer functions. It is not a keyword in any programming language,
+// contains no special characters, is not empty, and when it appears in output
+// it is distinct enough that a developer can find the source of the problem
+// via a search engine.
+const filterFailsafe = "ZgotmplZ"
+
+// escape escapes a template node.
+func (e *escaper) escape(c context, n parse.Node) context {
+	switch n := n.(type) {
+	case *parse.ActionNode:
+		return e.escapeAction(c, n)
+	case *parse.IfNode:
+		return e.escapeBranch(c, &n.BranchNode, "if")
+	case *parse.ListNode:
+		return e.escapeList(c, n)
+	case *parse.RangeNode:
+		return e.escapeBranch(c, &n.BranchNode, "range")
+	case *parse.TemplateNode:
+		return e.escapeTemplate(c, n)
+	case *parse.TextNode:
+		return e.escapeText(c, n)
+	case *parse.WithNode:
+		return e.escapeBranch(c, &n.BranchNode, "with")
+	}
+	panic("escaping " + n.String() + " is unimplemented")
+}
+
+// escapeAction escapes an action template node.
+func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
+	if len(n.Pipe.Decl) != 0 {
+		// A local variable assignment, not an interpolation.
+		return c
+	}
+	c = nudge(c)
+	s := make([]string, 0, 3)
+	switch c.state {
+	case stateError:
+		return c
+	case stateURL, stateCSSDqStr, stateCSSSqStr, stateCSSDqURL, stateCSSSqURL, stateCSSURL:
+		switch c.urlPart {
+		case urlPartNone:
+			s = append(s, "exp_template_html_urlfilter")
+			fallthrough
+		case urlPartPreQuery:
+			switch c.state {
+			case stateCSSDqStr, stateCSSSqStr:
+				s = append(s, "exp_template_html_cssescaper")
+			default:
+				s = append(s, "exp_template_html_urlnormalizer")
+			}
+		case urlPartQueryOrFrag:
+			s = append(s, "exp_template_html_urlescaper")
+		case urlPartUnknown:
+			return context{
+				state: stateError,
+				err:   errorf(ErrAmbigContext, n.Line, "%s appears in an ambiguous URL context", n),
+			}
+		default:
+			panic(c.urlPart.String())
+		}
+	case stateJS:
+		s = append(s, "exp_template_html_jsvalescaper")
+		// A slash after a value starts a div operator.
+		c.jsCtx = jsCtxDivOp
+	case stateJSDqStr, stateJSSqStr:
+		s = append(s, "exp_template_html_jsstrescaper")
+	case stateJSRegexp:
+		s = append(s, "exp_template_html_jsregexpescaper")
+	case stateCSS:
+		s = append(s, "exp_template_html_cssvaluefilter")
+	case stateText:
+		s = append(s, "exp_template_html_htmlescaper")
+	case stateRCDATA:
+		s = append(s, "exp_template_html_rcdataescaper")
+	case stateAttr:
+		// Handled below in delim check.
+	case stateAttrName, stateTag:
+		c.state = stateAttrName
+		s = append(s, "exp_template_html_htmlnamefilter")
+	default:
+		if isComment(c.state) {
+			s = append(s, "exp_template_html_commentescaper")
+		} else {
+			panic("unexpected state " + c.state.String())
+		}
+	}
+	switch c.delim {
+	case delimNone:
+		// No extra-escaping needed for raw text content.
+	case delimSpaceOrTagEnd:
+		s = append(s, "exp_template_html_nospaceescaper")
+	default:
+		s = append(s, "exp_template_html_attrescaper")
+	}
+	e.editActionNode(n, s)
+	return c
+}
+
+// ensurePipelineContains ensures that the pipeline has commands with
+// the identifiers in s in order.
+// If the pipeline already has some of the sanitizers, do not interfere.
+// For example, if p is (.X | html) and s is ["escapeJSVal", "html"] then it
+// has one matching, "html", and one to insert, "escapeJSVal", to produce
+// (.X | escapeJSVal | html).
+func ensurePipelineContains(p *parse.PipeNode, s []string) {
+	if len(s) == 0 {
+		return
+	}
+	n := len(p.Cmds)
+	// Find the identifiers at the end of the command chain.
+	idents := p.Cmds
+	for i := n - 1; i >= 0; i-- {
+		if cmd := p.Cmds[i]; len(cmd.Args) != 0 {
+			if id, ok := cmd.Args[0].(*parse.IdentifierNode); ok {
+				if id.Ident == "noescape" {
+					return
+				}
+				continue
+			}
+		}
+		idents = p.Cmds[i+1:]
+	}
+	dups := 0
+	for _, id := range idents {
+		if escFnsEq(s[dups], (id.Args[0].(*parse.IdentifierNode)).Ident) {
+			dups++
+			if dups == len(s) {
+				return
+			}
+		}
+	}
+	newCmds := make([]*parse.CommandNode, n-len(idents), n+len(s)-dups)
+	copy(newCmds, p.Cmds)
+	// Merge existing identifier commands with the sanitizers needed.
+	for _, id := range idents {
+		i := indexOfStr((id.Args[0].(*parse.IdentifierNode)).Ident, s, escFnsEq)
+		if i != -1 {
+			for _, name := range s[:i] {
+				newCmds = appendCmd(newCmds, newIdentCmd(name))
+			}
+			s = s[i+1:]
+		}
+		newCmds = appendCmd(newCmds, id)
+	}
+	// Create any remaining sanitizers.
+	for _, name := range s {
+		newCmds = appendCmd(newCmds, newIdentCmd(name))
+	}
+	p.Cmds = newCmds
+}
+
+// redundantFuncs[a][b] implies that funcMap[b](funcMap[a](x)) == funcMap[a](x)
+// for all x.
+var redundantFuncs = map[string]map[string]bool{
+	"exp_template_html_commentescaper": {
+		"exp_template_html_attrescaper":    true,
+		"exp_template_html_nospaceescaper": true,
+		"exp_template_html_htmlescaper":    true,
+	},
+	"exp_template_html_cssescaper": {
+		"exp_template_html_attrescaper": true,
+	},
+	"exp_template_html_jsregexpescaper": {
+		"exp_template_html_attrescaper": true,
+	},
+	"exp_template_html_jsstrescaper": {
+		"exp_template_html_attrescaper": true,
+	},
+	"exp_template_html_urlescaper": {
+		"exp_template_html_urlnormalizer": true,
+	},
+}
+
+// appendCmd appends the given command to the end of the command pipeline
+// unless it is redundant with the last command.
+func appendCmd(cmds []*parse.CommandNode, cmd *parse.CommandNode) []*parse.CommandNode {
+	if n := len(cmds); n != 0 {
+		last, ok := cmds[n-1].Args[0].(*parse.IdentifierNode)
+		next, _ := cmd.Args[0].(*parse.IdentifierNode)
+		if ok && redundantFuncs[last.Ident][next.Ident] {
+			return cmds
+		}
+	}
+	return append(cmds, cmd)
+}
+
+// indexOfStr is the first i such that eq(s, strs[i]) or -1 if s was not found.
+func indexOfStr(s string, strs []string, eq func(a, b string) bool) int {
+	for i, t := range strs {
+		if eq(s, t) {
+			return i
+		}
+	}
+	return -1
+}
+
+// escFnsEq returns whether the two escaping functions are equivalent.
+func escFnsEq(a, b string) bool {
+	if e := equivEscapers[a]; e != "" {
+		a = e
+	}
+	if e := equivEscapers[b]; e != "" {
+		b = e
+	}
+	return a == b
+}
+
+// newIdentCmd produces a command containing a single identifier node.
+func newIdentCmd(identifier string) *parse.CommandNode {
+	return &parse.CommandNode{
+		NodeType: parse.NodeCommand,
+		Args:     []parse.Node{parse.NewIdentifier(identifier)},
+	}
+}
+
+// nudge returns the context that would result from following empty string
+// transitions from the input context.
+// For example, parsing:
+//     `<a href=`
+// will end in context{stateBeforeValue, attrURL}, but parsing one extra rune:
+//     `<a href=x`
+// will end in context{stateURL, delimSpaceOrTagEnd, ...}.
+// There are two transitions that happen when the 'x' is seen:
+// (1) Transition from a before-value state to a start-of-value state without
+//     consuming any character.
+// (2) Consume 'x' and transition past the first value character.
+// In this case, nudging produces the context after (1) happens.
+func nudge(c context) context {
+	switch c.state {
+	case stateTag:
+		// In `<foo {{.}}`, the action should emit an attribute.
+		c.state = stateAttrName
+	case stateBeforeValue:
+		// In `<foo bar={{.}}`, the action is an undelimited value.
+		c.state, c.delim, c.attr = attrStartStates[c.attr], delimSpaceOrTagEnd, attrNone
+	case stateAfterName:
+		// In `<foo bar {{.}}`, the action is an attribute name.
+		c.state, c.attr = stateAttrName, attrNone
+	}
+	return c
+}
+
+// join joins the two contexts of a branch template node. The result is an
+// error context if either of the input contexts are error contexts, or if the
+// the input contexts differ.
+func join(a, b context, line int, nodeName string) context {
+	if a.state == stateError {
+		return a
+	}
+	if b.state == stateError {
+		return b
+	}
+	if a.eq(b) {
+		return a
+	}
+
+	c := a
+	c.urlPart = b.urlPart
+	if c.eq(b) {
+		// The contexts differ only by urlPart.
+		c.urlPart = urlPartUnknown
+		return c
+	}
+
+	c = a
+	c.jsCtx = b.jsCtx
+	if c.eq(b) {
+		// The contexts differ only by jsCtx.
+		c.jsCtx = jsCtxUnknown
+		return c
+	}
+
+	// Allow a nudged context to join with an unnudged one.
+	// This means that
+	//   <p title={{if .C}}{{.}}{{end}}
+	// ends in an unquoted value state even though the else branch
+	// ends in stateBeforeValue.
+	if c, d := nudge(a), nudge(b); !(c.eq(a) && d.eq(b)) {
+		if e := join(c, d, line, nodeName); e.state != stateError {
+			return e
+		}
+	}
+
+	return context{
+		state: stateError,
+		err:   errorf(ErrBranchEnd, line, "{{%s}} branches end in different contexts: %v, %v", nodeName, a, b),
+	}
+}
+
+// escapeBranch escapes a branch template node: "if", "range" and "with".
+func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context {
+	c0 := e.escapeList(c, n.List)
+	if nodeName == "range" && c0.state != stateError {
+		// The "true" branch of a "range" node can execute multiple times.
+		// We check that executing n.List once results in the same context
+		// as executing n.List twice.
+		c1, _ := e.escapeListConditionally(c0, n.List, nil)
+		c0 = join(c0, c1, n.Line, nodeName)
+		if c0.state == stateError {
+			// Make clear that this is a problem on loop re-entry
+			// since developers tend to overlook that branch when
+			// debugging templates.
+			c0.err.Line = n.Line
+			c0.err.Description = "on range loop re-entry: " + c0.err.Description
+			return c0
+		}
+	}
+	c1 := e.escapeList(c, n.ElseList)
+	return join(c0, c1, n.Line, nodeName)
+}
+
+// escapeList escapes a list template node.
+func (e *escaper) escapeList(c context, n *parse.ListNode) context {
+	if n == nil {
+		return c
+	}
+	for _, m := range n.Nodes {
+		c = e.escape(c, m)
+	}
+	return c
+}
+
+// escapeListConditionally escapes a list node but only preserves edits and
+// inferences in e if the inferences and output context satisfy filter.
+// It returns the best guess at an output context, and the result of the filter
+// which is the same as whether e was updated.
+func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) {
+	e1 := newEscaper(e.tmpl)
+	// Make type inferences available to f.
+	for k, v := range e.output {
+		e1.output[k] = v
+	}
+	c = e1.escapeList(c, n)
+	ok := filter != nil && filter(e1, c)
+	if ok {
+		// Copy inferences and edits from e1 back into e.
+		for k, v := range e1.output {
+			e.output[k] = v
+		}
+		for k, v := range e1.derived {
+			e.derived[k] = v
+		}
+		for k, v := range e1.called {
+			e.called[k] = v
+		}
+		for k, v := range e1.actionNodeEdits {
+			e.editActionNode(k, v)
+		}
+		for k, v := range e1.templateNodeEdits {
+			e.editTemplateNode(k, v)
+		}
+		for k, v := range e1.textNodeEdits {
+			e.editTextNode(k, v)
+		}
+	}
+	return c, ok
+}
+
+// escapeTemplate escapes a {{template}} call node.
+func (e *escaper) escapeTemplate(c context, n *parse.TemplateNode) context {
+	c, name := e.escapeTree(c, n.Name, n.Line)
+	if name != n.Name {
+		e.editTemplateNode(n, name)
+	}
+	return c
+}
+
+// escapeTree escapes the named template starting in the given context as
+// necessary and returns its output context.
+func (e *escaper) escapeTree(c context, name string, line int) (context, string) {
+	// Mangle the template name with the input context to produce a reliable
+	// identifier.
+	dname := c.mangle(name)
+	e.called[dname] = true
+	if out, ok := e.output[dname]; ok {
+		// Already escaped.
+		return out, dname
+	}
+	t := e.template(name)
+	if t == nil {
+		// Two cases: The template exists but is empty, or has never been mentioned at
+		// all. Distinguish the cases in the error messages.
+		if e.tmpl.set[name] != nil {
+			return context{
+				state: stateError,
+				err:   errorf(ErrNoSuchTemplate, line, "%q is an incomplete or empty template", name),
+			}, dname
+		}
+		return context{
+			state: stateError,
+			err:   errorf(ErrNoSuchTemplate, line, "no such template %q", name),
+		}, dname
+	}
+	if dname != name {
+		// Use any template derived during an earlier call to escapeTemplate
+		// with different top level templates, or clone if necessary.
+		dt := e.template(dname)
+		if dt == nil {
+			dt = template.New(dname)
+			dt.Tree = &parse.Tree{Name: dname, Root: cloneList(t.Root)}
+			e.derived[dname] = dt
+		}
+		t = dt
+	}
+	return e.computeOutCtx(c, t), dname
+}
+
+// computeOutCtx takes a template and its start context and computes the output
+// context while storing any inferences in e.
+func (e *escaper) computeOutCtx(c context, t *template.Template) context {
+	// Propagate context over the body.
+	c1, ok := e.escapeTemplateBody(c, t)
+	if !ok {
+		// Look for a fixed point by assuming c1 as the output context.
+		if c2, ok2 := e.escapeTemplateBody(c1, t); ok2 {
+			c1, ok = c2, true
+		}
+		// Use c1 as the error context if neither assumption worked.
+	}
+	if !ok && c1.state != stateError {
+		return context{
+			state: stateError,
+			// TODO: Find the first node with a line in t.text.Tree.Root
+			err: errorf(ErrOutputContext, 0, "cannot compute output context for template %s", t.Name()),
+		}
+	}
+	return c1
+}
+
+// escapeTemplateBody escapes the given template assuming the given output
+// context, and returns the best guess at the output context and whether the
+// assumption was correct.
+func (e *escaper) escapeTemplateBody(c context, t *template.Template) (context, bool) {
+	filter := func(e1 *escaper, c1 context) bool {
+		if c1.state == stateError {
+			// Do not update the input escaper, e.
+			return false
+		}
+		if !e1.called[t.Name()] {
+			// If t is not recursively called, then c1 is an
+			// accurate output context.
+			return true
+		}
+		// c1 is accurate if it matches our assumed output context.
+		return c.eq(c1)
+	}
+	// We need to assume an output context so that recursive template calls
+	// take the fast path out of escapeTree instead of infinitely recursing.
+	// Naively assuming that the input context is the same as the output
+	// works >90% of the time.
+	e.output[t.Name()] = c
+	return e.escapeListConditionally(c, t.Tree.Root, filter)
+}
+
+// delimEnds maps each delim to a string of characters that terminate it.
+var delimEnds = [...]string{
+	delimDoubleQuote: `"`,
+	delimSingleQuote: "'",
+	// Determined empirically by running the below in various browsers.
+	// var div = document.createElement("DIV");
+	// for (var i = 0; i < 0x10000; ++i) {
+	//   div.innerHTML = "<span title=x" + String.fromCharCode(i) + "-bar>";
+	//   if (div.getElementsByTagName("SPAN")[0].title.indexOf("bar") < 0)
+	//     document.write("<p>U+" + i.toString(16));
+	// }
+	delimSpaceOrTagEnd: " \t\n\f\r>",
+}
+
+var doctypeBytes = []byte("<!DOCTYPE")
+
+// escapeText escapes a text template node.
+func (e *escaper) escapeText(c context, n *parse.TextNode) context {
+	s, written, i, b := n.Text, 0, 0, new(bytes.Buffer)
+	for i != len(s) {
+		c1, nread := contextAfterText(c, s[i:])
+		i1 := i + nread
+		if c.state == stateText || c.state == stateRCDATA {
+			end := i1
+			if c1.state != c.state {
+				for j := end - 1; j >= i; j-- {
+					if s[j] == '<' {
+						end = j
+						break
+					}
+				}
+			}
+			for j := i; j < end; j++ {
+				if s[j] == '<' && !bytes.HasPrefix(s[j:], doctypeBytes) {
+					b.Write(s[written:j])
+					b.WriteString("<")
+					written = j + 1
+				}
+			}
+		} else if isComment(c.state) && c.delim == delimNone {
+			switch c.state {
+			case stateJSBlockCmt:
+				// http://es5.github.com/#x7.4:
+				// "Comments behave like white space and are
+				// discarded except that, if a MultiLineComment
+				// contains a line terminator character, then
+				// the entire comment is considered to be a
+				// LineTerminator for purposes of parsing by
+				// the syntactic grammar."
+				if bytes.IndexAny(s[written:i1], "\n\r\u2028\u2029") != -1 {
+					b.WriteByte('\n')
+				} else {
+					b.WriteByte(' ')
+				}
+			case stateCSSBlockCmt:
+				b.WriteByte(' ')
+			}
+			written = i1
+		}
+		if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
+			// Preserve the portion between written and the comment start.
+			cs := i1 - 2
+			if c1.state == stateHTMLCmt {
+				// "<!--" instead of "/*" or "//"
+				cs -= 2
+			}
+			b.Write(s[written:cs])
+			written = i1
+		}
+		if i == i1 && c.state == c1.state {
+			panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
+		}
+		c, i = c1, i1
+	}
+
+	if written != 0 && c.state != stateError {
+		if !isComment(c.state) || c.delim != delimNone {
+			b.Write(n.Text[written:])
+		}
+		e.editTextNode(n, b.Bytes())
+	}
+	return c
+}
+
+// contextAfterText starts in context c, consumes some tokens from the front of
+// s, then returns the context after those tokens and the unprocessed suffix.
+func contextAfterText(c context, s []byte) (context, int) {
+	if c.delim == delimNone {
+		c1, i := tSpecialTagEnd(c, s)
+		if i == 0 {
+			// A special end tag (`</script>`) has been seen and
+			// all content preceding it has been consumed.
+			return c1, 0
+		}
+		// Consider all content up to any end tag.
+		return transitionFunc[c.state](c, s[:i])
+	}
+
+	i := bytes.IndexAny(s, delimEnds[c.delim])
+	if i == -1 {
+		i = len(s)
+	}
+	if c.delim == delimSpaceOrTagEnd {
+		// http://www.w3.org/TR/html5/tokenization.html#attribute-value-unquoted-state
+		// lists the runes below as error characters.
+		// Error out because HTML parsers may differ on whether
+		// "<a id= onclick=f("     ends inside id's or onclick's value,
+		// "<a class=`foo "        ends inside a value,
+		// "<a style=font:'Arial'" needs open-quote fixup.
+		// IE treats '`' as a quotation character.
+		if j := bytes.IndexAny(s[:i], "\"'<=`"); j >= 0 {
+			return context{
+				state: stateError,
+				err:   errorf(ErrBadHTML, 0, "%q in unquoted attr: %q", s[j:j+1], s[:i]),
+			}, len(s)
+		}
+	}
+	if i == len(s) {
+		// Remain inside the attribute.
+		// Decode the value so non-HTML rules can easily handle
+		//     <button onclick="alert("Hi!")">
+		// without having to entity decode token boundaries.
+		for u := []byte(html.UnescapeString(string(s))); len(u) != 0; {
+			c1, i1 := transitionFunc[c.state](c, u)
+			c, u = c1, u[i1:]
+		}
+		return c, len(s)
+	}
+	if c.delim != delimSpaceOrTagEnd {
+		// Consume any quote.
+		i++
+	}
+	// On exiting an attribute, we discard all state information
+	// except the state and element.
+	return context{state: stateTag, element: c.element}, i
+}
+
+// editActionNode records a change to an action pipeline for later commit.
+func (e *escaper) editActionNode(n *parse.ActionNode, cmds []string) {
+	if _, ok := e.actionNodeEdits[n]; ok {
+		panic(fmt.Sprintf("node %s shared between templates", n))
+	}
+	e.actionNodeEdits[n] = cmds
+}
+
+// editTemplateNode records a change to a {{template}} callee for later commit.
+func (e *escaper) editTemplateNode(n *parse.TemplateNode, callee string) {
+	if _, ok := e.templateNodeEdits[n]; ok {
+		panic(fmt.Sprintf("node %s shared between templates", n))
+	}
+	e.templateNodeEdits[n] = callee
+}
+
+// editTextNode records a change to a text node for later commit.
+func (e *escaper) editTextNode(n *parse.TextNode, text []byte) {
+	if _, ok := e.textNodeEdits[n]; ok {
+		panic(fmt.Sprintf("node %s shared between templates", n))
+	}
+	e.textNodeEdits[n] = text
+}
+
+// commit applies changes to actions and template calls needed to contextually
+// autoescape content and adds any derived templates to the set.
+func (e *escaper) commit() {
+	for name := range e.output {
+		e.template(name).Funcs(funcMap)
+	}
+	for _, t := range e.derived {
+		if _, err := e.tmpl.text.AddParseTree(t.Name(), t.Tree); err != nil {
+			panic("error adding derived template")
+		}
+	}
+	for n, s := range e.actionNodeEdits {
+		ensurePipelineContains(n.Pipe, s)
+	}
+	for n, name := range e.templateNodeEdits {
+		n.Name = name
+	}
+	for n, s := range e.textNodeEdits {
+		n.Text = s
+	}
+}
+
+// template returns the named template given a mangled template name.
+func (e *escaper) template(name string) *template.Template {
+	t := e.tmpl.text.Lookup(name)
+	if t == nil {
+		t = e.derived[name]
+	}
+	return t
+}
diff --git a/src/pkg/html/template/escape_test.go b/src/pkg/html/template/escape_test.go
new file mode 100644
index 0000000..0e31674
--- /dev/null
+++ b/src/pkg/html/template/escape_test.go
@@ -0,0 +1,1643 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"strings"
+	"testing"
+	"text/template"
+	"text/template/parse"
+)
+
+type badMarshaler struct{}
+
+func (x *badMarshaler) MarshalJSON() ([]byte, error) {
+	// Keys in valid JSON must be double quoted as must all strings.
+	return []byte("{ foo: 'not quite valid JSON' }"), nil
+}
+
+type goodMarshaler struct{}
+
+func (x *goodMarshaler) MarshalJSON() ([]byte, error) {
+	return []byte(`{ "<foo>": "O'Reilly" }`), nil
+}
+
+func TestEscape(t *testing.T) {
+	data := struct {
+		F, T    bool
+		C, G, H string
+		A, E    []string
+		B, M    json.Marshaler
+		N       int
+		Z       *int
+		W       HTML
+	}{
+		F: false,
+		T: true,
+		C: "<Cincinatti>",
+		G: "<Goodbye>",
+		H: "<Hello>",
+		A: []string{"<a>", "<b>"},
+		E: []string{},
+		N: 42,
+		B: &badMarshaler{},
+		M: &goodMarshaler{},
+		Z: nil,
+		W: HTML(`¡<b class="foo">Hello</b>, <textarea>O'World</textarea>!`),
+	}
+	pdata := &data
+
+	tests := []struct {
+		name   string
+		input  string
+		output string
+	}{
+		{
+			"if",
+			"{{if .T}}Hello{{end}}, {{.C}}!",
+			"Hello, <Cincinatti>!",
+		},
+		{
+			"else",
+			"{{if .F}}{{.H}}{{else}}{{.G}}{{end}}!",
+			"<Goodbye>!",
+		},
+		{
+			"overescaping1",
+			"Hello, {{.C | html}}!",
+			"Hello, <Cincinatti>!",
+		},
+		{
+			"overescaping2",
+			"Hello, {{html .C}}!",
+			"Hello, <Cincinatti>!",
+		},
+		{
+			"overescaping3",
+			"{{with .C}}{{$msg := .}}Hello, {{$msg}}!{{end}}",
+			"Hello, <Cincinatti>!",
+		},
+		{
+			"assignment",
+			"{{if $x := .H}}{{$x}}{{end}}",
+			"<Hello>",
+		},
+		{
+			"withBody",
+			"{{with .H}}{{.}}{{end}}",
+			"<Hello>",
+		},
+		{
+			"withElse",
+			"{{with .E}}{{.}}{{else}}{{.H}}{{end}}",
+			"<Hello>",
+		},
+		{
+			"rangeBody",
+			"{{range .A}}{{.}}{{end}}",
+			"<a><b>",
+		},
+		{
+			"rangeElse",
+			"{{range .E}}{{.}}{{else}}{{.H}}{{end}}",
+			"<Hello>",
+		},
+		{
+			"nonStringValue",
+			"{{.T}}",
+			"true",
+		},
+		{
+			"constant",
+			`<a href="/search?q={{"'a<b'"}}">`,
+			`<a href="/search?q=%27a%3cb%27">`,
+		},
+		{
+			"multipleAttrs",
+			"<a b=1 c={{.H}}>",
+			"<a b=1 c=<Hello>>",
+		},
+		{
+			"urlStartRel",
+			`<a href='{{"/foo/bar?a=b&c=d"}}'>`,
+			`<a href='/foo/bar?a=b&c=d'>`,
+		},
+		{
+			"urlStartAbsOk",
+			`<a href='{{"http://example.com/foo/bar?a=b&c=d"}}'>`,
+			`<a href='http://example.com/foo/bar?a=b&c=d'>`,
+		},
+		{
+			"protocolRelativeURLStart",
+			`<a href='{{"//example.com:8000/foo/bar?a=b&c=d"}}'>`,
+			`<a href='//example.com:8000/foo/bar?a=b&c=d'>`,
+		},
+		{
+			"pathRelativeURLStart",
+			`<a href="{{"/javascript:80/foo/bar"}}">`,
+			`<a href="/javascript:80/foo/bar">`,
+		},
+		{
+			"dangerousURLStart",
+			`<a href='{{"javascript:alert(%22pwned%22)"}}'>`,
+			`<a href='#ZgotmplZ'>`,
+		},
+		{
+			"dangerousURLStart2",
+			`<a href='  {{"javascript:alert(%22pwned%22)"}}'>`,
+			`<a href='  #ZgotmplZ'>`,
+		},
+		{
+			"nonHierURL",
+			`<a href={{"mailto:Muhammed \"The Greatest\" Ali <m.ali at example.com>"}}>`,
+			`<a href=mailto:Muhammed%20%22The%20Greatest%22%20Ali%20%3cm.ali at example.com%3e>`,
+		},
+		{
+			"urlPath",
+			`<a href='http://{{"javascript:80"}}/foo'>`,
+			`<a href='http://javascript:80/foo'>`,
+		},
+		{
+			"urlQuery",
+			`<a href='/search?q={{.H}}'>`,
+			`<a href='/search?q=%3cHello%3e'>`,
+		},
+		{
+			"urlFragment",
+			`<a href='/faq#{{.H}}'>`,
+			`<a href='/faq#%3cHello%3e'>`,
+		},
+		{
+			"urlBranch",
+			`<a href="{{if .F}}/foo?a=b{{else}}/bar{{end}}">`,
+			`<a href="/bar">`,
+		},
+		{
+			"urlBranchConflictMoot",
+			`<a href="{{if .T}}/foo?a={{else}}/bar#{{end}}{{.C}}">`,
+			`<a href="/foo?a=%3cCincinatti%3e">`,
+		},
+		{
+			"jsStrValue",
+			"<button onclick='alert({{.H}})'>",
+			`<button onclick='alert("\u003cHello\u003e")'>`,
+		},
+		{
+			"jsNumericValue",
+			"<button onclick='alert({{.N}})'>",
+			`<button onclick='alert( 42 )'>`,
+		},
+		{
+			"jsBoolValue",
+			"<button onclick='alert({{.T}})'>",
+			`<button onclick='alert( true )'>`,
+		},
+		{
+			"jsNilValue",
+			"<button onclick='alert(typeof{{.Z}})'>",
+			`<button onclick='alert(typeof null )'>`,
+		},
+		{
+			"jsObjValue",
+			"<button onclick='alert({{.A}})'>",
+			`<button onclick='alert(["\u003ca\u003e","\u003cb\u003e"])'>`,
+		},
+		{
+			"jsObjValueScript",
+			"<script>alert({{.A}})</script>",
+			`<script>alert(["\u003ca\u003e","\u003cb\u003e"])</script>`,
+		},
+		{
+			"jsObjValueNotOverEscaped",
+			"<button onclick='alert({{.A | html}})'>",
+			`<button onclick='alert(["\u003ca\u003e","\u003cb\u003e"])'>`,
+		},
+		{
+			"jsStr",
+			"<button onclick='alert("{{.H}}")'>",
+			`<button onclick='alert("\x3cHello\x3e")'>`,
+		},
+		{
+			"badMarshaller",
+			`<button onclick='alert(1/{{.B}}in numbers)'>`,
+			`<button onclick='alert(1/ /* json: error calling MarshalJSON for type *template.badMarshaler: invalid character 'f' looking for beginning of object key string */null in numbers)'>`,
+		},
+		{
+			"jsMarshaller",
+			`<button onclick='alert({{.M}})'>`,
+			`<button onclick='alert({"<foo>":"O'Reilly"})'>`,
+		},
+		{
+			"jsStrNotUnderEscaped",
+			"<button onclick='alert({{.C | urlquery}})'>",
+			// URL escaped, then quoted for JS.
+			`<button onclick='alert("%3CCincinatti%3E")'>`,
+		},
+		{
+			"jsRe",
+			`<button onclick='alert(/{{"foo+bar"}}/.test(""))'>`,
+			`<button onclick='alert(/foo\x2bbar/.test(""))'>`,
+		},
+		{
+			"jsReBlank",
+			`<script>alert(/{{""}}/.test(""));</script>`,
+			`<script>alert(/(?:)/.test(""));</script>`,
+		},
+		{
+			"jsReAmbigOk",
+			`<script>{{if true}}var x = 1{{end}}</script>`,
+			// The {if} ends in an ambiguous jsCtx but there is
+			// no slash following so we shouldn't care.
+			`<script>var x = 1</script>`,
+		},
+		{
+			"styleBidiKeywordPassed",
+			`<p style="dir: {{"ltr"}}">`,
+			`<p style="dir: ltr">`,
+		},
+		{
+			"styleBidiPropNamePassed",
+			`<p style="border-{{"left"}}: 0; border-{{"right"}}: 1in">`,
+			`<p style="border-left: 0; border-right: 1in">`,
+		},
+		{
+			"styleExpressionBlocked",
+			`<p style="width: {{"expression(alert(1337))"}}">`,
+			`<p style="width: ZgotmplZ">`,
+		},
+		{
+			"styleTagSelectorPassed",
+			`<style>{{"p"}} { color: pink }</style>`,
+			`<style>p { color: pink }</style>`,
+		},
+		{
+			"styleIDPassed",
+			`<style>p{{"#my-ID"}} { font: Arial }</style>`,
+			`<style>p#my-ID { font: Arial }</style>`,
+		},
+		{
+			"styleClassPassed",
+			`<style>p{{".my_class"}} { font: Arial }</style>`,
+			`<style>p.my_class { font: Arial }</style>`,
+		},
+		{
+			"styleQuantityPassed",
+			`<a style="left: {{"2em"}}; top: {{0}}">`,
+			`<a style="left: 2em; top: 0">`,
+		},
+		{
+			"stylePctPassed",
+			`<table style=width:{{"100%"}}>`,
+			`<table style=width:100%>`,
+		},
+		{
+			"styleColorPassed",
+			`<p style="color: {{"#8ff"}}; background: {{"#000"}}">`,
+			`<p style="color: #8ff; background: #000">`,
+		},
+		{
+			"styleObfuscatedExpressionBlocked",
+			`<p style="width: {{"  e\\78preS\x00Sio/**/n(alert(1337))"}}">`,
+			`<p style="width: ZgotmplZ">`,
+		},
+		{
+			"styleMozBindingBlocked",
+			`<p style="{{"-moz-binding(alert(1337))"}}: ...">`,
+			`<p style="ZgotmplZ: ...">`,
+		},
+		{
+			"styleObfuscatedMozBindingBlocked",
+			`<p style="{{"  -mo\\7a-B\x00I/**/nding(alert(1337))"}}: ...">`,
+			`<p style="ZgotmplZ: ...">`,
+		},
+		{
+			"styleFontNameString",
+			`<p style='font-family: "{{"Times New Roman"}}"'>`,
+			`<p style='font-family: "Times New Roman"'>`,
+		},
+		{
+			"styleFontNameString",
+			`<p style='font-family: "{{"Times New Roman"}}", "{{"sans-serif"}}"'>`,
+			`<p style='font-family: "Times New Roman", "sans-serif"'>`,
+		},
+		{
+			"styleFontNameUnquoted",
+			`<p style='font-family: {{"Times New Roman"}}'>`,
+			`<p style='font-family: Times New Roman'>`,
+		},
+		{
+			"styleURLQueryEncoded",
+			`<p style="background: url(/img?name={{"O'Reilly Animal(1)<2>.png"}})">`,
+			`<p style="background: url(/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png)">`,
+		},
+		{
+			"styleQuotedURLQueryEncoded",
+			`<p style="background: url('/img?name={{"O'Reilly Animal(1)<2>.png"}}')">`,
+			`<p style="background: url('/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png')">`,
+		},
+		{
+			"styleStrQueryEncoded",
+			`<p style="background: '/img?name={{"O'Reilly Animal(1)<2>.png"}}'">`,
+			`<p style="background: '/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png'">`,
+		},
+		{
+			"styleURLBadProtocolBlocked",
+			`<a style="background: url('{{"javascript:alert(1337)"}}')">`,
+			`<a style="background: url('#ZgotmplZ')">`,
+		},
+		{
+			"styleStrBadProtocolBlocked",
+			`<a style="background: '{{"vbscript:alert(1337)"}}'">`,
+			`<a style="background: '#ZgotmplZ'">`,
+		},
+		{
+			"styleStrEncodedProtocolEncoded",
+			`<a style="background: '{{"javascript\\3a alert(1337)"}}'">`,
+			// The CSS string 'javascript\\3a alert(1337)' does not contains a colon.
+			`<a style="background: 'javascript\\3a alert\28 1337\29 '">`,
+		},
+		{
+			"styleURLGoodProtocolPassed",
+			`<a style="background: url('{{"http://oreilly.com/O'Reilly Animals(1)<2>;{}.html"}}')">`,
+			`<a style="background: url('http://oreilly.com/O%27Reilly%20Animals%281%29%3c2%3e;%7b%7d.html')">`,
+		},
+		{
+			"styleStrGoodProtocolPassed",
+			`<a style="background: '{{"http://oreilly.com/O'Reilly Animals(1)<2>;{}.html"}}'">`,
+			`<a style="background: 'http\3a\2f\2foreilly.com\2fO\27Reilly Animals\28 1\29\3c 2\3e\3b\7b\7d.html'">`,
+		},
+		{
+			"styleURLEncodedForHTMLInAttr",
+			`<a style="background: url('{{"/search?img=foo&size=icon"}}')">`,
+			`<a style="background: url('/search?img=foo&size=icon')">`,
+		},
+		{
+			"styleURLNotEncodedForHTMLInCdata",
+			`<style>body { background: url('{{"/search?img=foo&size=icon"}}') }</style>`,
+			`<style>body { background: url('/search?img=foo&size=icon') }</style>`,
+		},
+		{
+			"styleURLMixedCase",
+			`<p style="background: URL(#{{.H}})">`,
+			`<p style="background: URL(#%3cHello%3e)">`,
+		},
+		{
+			"stylePropertyPairPassed",
+			`<a style='{{"color: red"}}'>`,
+			`<a style='color: red'>`,
+		},
+		{
+			"styleStrSpecialsEncoded",
+			`<a style="font-family: '{{"/**/'\";:// \\"}}', "{{"/**/'\";:// \\"}}"">`,
+			`<a style="font-family: '\2f**\2f\27\22\3b\3a\2f\2f  \\', "\2f**\2f\27\22\3b\3a\2f\2f  \\"">`,
+		},
+		{
+			"styleURLSpecialsEncoded",
+			`<a style="border-image: url({{"/**/'\";:// \\"}}), url("{{"/**/'\";:// \\"}}"), url('{{"/**/'\";:// \\"}}'), 'http://www.example.com/?q={{"/**/'\";:// \\"}}''">`,
+			`<a style="border-image: url(/**/%27%22;://%20%5c), url("/**/%27%22;://%20%5c"), url('/**/%27%22;://%20%5c'), 'http://www.example.com/?q=%2f%2a%2a%2f%27%22%3b%3a%2f%2f%20%5c''">`,
+		},
+		{
+			"HTML comment",
+			"<b>Hello, <!-- name of world -->{{.C}}</b>",
+			"<b>Hello, <Cincinatti></b>",
+		},
+		{
+			"HTML comment not first < in text node.",
+			"<<!-- -->!--",
+			"<!--",
+		},
+		{
+			"HTML normalization 1",
+			"a < b",
+			"a < b",
+		},
+		{
+			"HTML normalization 2",
+			"a << b",
+			"a << b",
+		},
+		{
+			"HTML normalization 3",
+			"a<<!-- --><!-- -->b",
+			"a<b",
+		},
+		{
+			"HTML doctype not normalized",
+			"<!DOCTYPE html>Hello, World!",
+			"<!DOCTYPE html>Hello, World!",
+		},
+		{
+			"No doctype injection",
+			`<!{{"DOCTYPE"}}`,
+			"<!DOCTYPE",
+		},
+		{
+			"Split HTML comment",
+			"<b>Hello, <!-- name of {{if .T}}city -->{{.C}}{{else}}world -->{{.W}}{{end}}</b>",
+			"<b>Hello, <Cincinatti></b>",
+		},
+		{
+			"JS line comment",
+			"<script>for (;;) { if (c()) break// foo not a label\n" +
+				"foo({{.T}});}</script>",
+			"<script>for (;;) { if (c()) break\n" +
+				"foo( true );}</script>",
+		},
+		{
+			"JS multiline block comment",
+			"<script>for (;;) { if (c()) break/* foo not a label\n" +
+				" */foo({{.T}});}</script>",
+			// Newline separates break from call. If newline
+			// removed, then break will consume label leaving
+			// code invalid.
+			"<script>for (;;) { if (c()) break\n" +
+				"foo( true );}</script>",
+		},
+		{
+			"JS single-line block comment",
+			"<script>for (;;) {\n" +
+				"if (c()) break/* foo a label */foo;" +
+				"x({{.T}});}</script>",
+			// Newline separates break from call. If newline
+			// removed, then break will consume label leaving
+			// code invalid.
+			"<script>for (;;) {\n" +
+				"if (c()) break foo;" +
+				"x( true );}</script>",
+		},
+		{
+			"JS block comment flush with mathematical division",
+			"<script>var a/*b*//c\nd</script>",
+			"<script>var a /c\nd</script>",
+		},
+		{
+			"JS mixed comments",
+			"<script>var a/*b*///c\nd</script>",
+			"<script>var a \nd</script>",
+		},
+		{
+			"CSS comments",
+			"<style>p// paragraph\n" +
+				`{border: 1px/* color */{{"#00f"}}}</style>`,
+			"<style>p\n" +
+				"{border: 1px #00f}</style>",
+		},
+		{
+			"JS attr block comment",
+			`<a onclick="f(""); /* alert({{.H}}) */">`,
+			// Attribute comment tests should pass if the comments
+			// are successfully elided.
+			`<a onclick="f(""); /* alert() */">`,
+		},
+		{
+			"JS attr line comment",
+			`<a onclick="// alert({{.G}})">`,
+			`<a onclick="// alert()">`,
+		},
+		{
+			"CSS attr block comment",
+			`<a style="/* color: {{.H}} */">`,
+			`<a style="/* color:  */">`,
+		},
+		{
+			"CSS attr line comment",
+			`<a style="// color: {{.G}}">`,
+			`<a style="// color: ">`,
+		},
+		{
+			"HTML substitution commented out",
+			"<p><!-- {{.H}} --></p>",
+			"<p></p>",
+		},
+		{
+			"Comment ends flush with start",
+			"<!--{{.}}--><script>/*{{.}}*///{{.}}\n</script><style>/*{{.}}*///{{.}}\n</style><a onclick='/*{{.}}*///{{.}}' style='/*{{.}}*///{{.}}'>",
+			"<script> \n</script><style> \n</style><a onclick='/**///' style='/**///'>",
+		},
+		{
+			"typed HTML in text",
+			`{{.W}}`,
+			`¡<b class="foo">Hello</b>, <textarea>O'World</textarea>!`,
+		},
+		{
+			"typed HTML in attribute",
+			`<div title="{{.W}}">`,
+			`<div title="¡Hello, O'World!">`,
+		},
+		{
+			"typed HTML in script",
+			`<button onclick="alert({{.W}})">`,
+			`<button onclick="alert("&iexcl;\u003cb class=\"foo\"\u003eHello\u003c/b\u003e, \u003ctextarea\u003eO'World\u003c/textarea\u003e!")">`,
+		},
+		{
+			"typed HTML in RCDATA",
+			`<textarea>{{.W}}</textarea>`,
+			`<textarea>¡<b class="foo">Hello</b>, <textarea>O'World</textarea>!</textarea>`,
+		},
+		{
+			"range in textarea",
+			"<textarea>{{range .A}}{{.}}{{end}}</textarea>",
+			"<textarea><a><b></textarea>",
+		},
+		{
+			"auditable exemption from escaping",
+			"{{range .A}}{{. | noescape}}{{end}}",
+			"<a><b>",
+		},
+		{
+			"No tag injection",
+			`{{"10$"}}<{{"script src,evil.org/pwnd.js"}}...`,
+			`10$<script src,evil.org/pwnd.js...`,
+		},
+		{
+			"No comment injection",
+			`<{{"!--"}}`,
+			`<!--`,
+		},
+		{
+			"No RCDATA end tag injection",
+			`<textarea><{{"/textarea "}}...</textarea>`,
+			`<textarea></textarea ...</textarea>`,
+		},
+		{
+			"optional attrs",
+			`<img class="{{"iconClass"}}"` +
+				`{{if .T}} id="{{"<iconId>"}}"{{end}}` +
+				// Double quotes inside if/else.
+				` src=` +
+				`{{if .T}}"?{{"<iconPath>"}}"` +
+				`{{else}}"images/cleardot.gif"{{end}}` +
+				// Missing space before title, but it is not a
+				// part of the src attribute.
+				`{{if .T}}title="{{"<title>"}}"{{end}}` +
+				// Quotes outside if/else.
+				` alt="` +
+				`{{if .T}}{{"<alt>"}}` +
+				`{{else}}{{if .F}}{{"<title>"}}{{end}}` +
+				`{{end}}"` +
+				`>`,
+			`<img class="iconClass" id="<iconId>" src="?%3ciconPath%3e"title="<title>" alt="<alt>">`,
+		},
+		{
+			"conditional valueless attr name",
+			`<input{{if .T}} checked{{end}} name=n>`,
+			`<input checked name=n>`,
+		},
+		{
+			"conditional dynamic valueless attr name 1",
+			`<input{{if .T}} {{"checked"}}{{end}} name=n>`,
+			`<input checked name=n>`,
+		},
+		{
+			"conditional dynamic valueless attr name 2",
+			`<input {{if .T}}{{"checked"}} {{end}}name=n>`,
+			`<input checked name=n>`,
+		},
+		{
+			"dynamic attribute name",
+			`<img on{{"load"}}="alert({{"loaded"}})">`,
+			// Treated as JS since quotes are inserted.
+			`<img onload="alert("loaded")">`,
+		},
+		{
+			"bad dynamic attribute name 1",
+			// Allow checked, selected, disabled, but not JS or
+			// CSS attributes.
+			`<input {{"onchange"}}="{{"doEvil()"}}">`,
+			`<input ZgotmplZ="doEvil()">`,
+		},
+		{
+			"bad dynamic attribute name 2",
+			`<div {{"sTyle"}}="{{"color: expression(alert(1337))"}}">`,
+			`<div ZgotmplZ="color: expression(alert(1337))">`,
+		},
+		{
+			"bad dynamic attribute name 3",
+			// Allow title or alt, but not a URL.
+			`<img {{"src"}}="{{"javascript:doEvil()"}}">`,
+			`<img ZgotmplZ="javascript:doEvil()">`,
+		},
+		{
+			"bad dynamic attribute name 4",
+			// Structure preservation requires values to associate
+			// with a consistent attribute.
+			`<input checked {{""}}="Whose value am I?">`,
+			`<input checked ZgotmplZ="Whose value am I?">`,
+		},
+		{
+			"dynamic element name",
+			`<h{{3}}><table><t{{"head"}}>...</h{{3}}>`,
+			`<h3><table><thead>...</h3>`,
+		},
+		{
+			"bad dynamic element name",
+			// Dynamic element names are typically used to switch
+			// between (thead, tfoot, tbody), (ul, ol), (th, td),
+			// and other replaceable sets.
+			// We do not currently easily support (ul, ol).
+			// If we do change to support that, this test should
+			// catch failures to filter out special tag names which
+			// would violate the structure preservation property --
+			// if any special tag name could be substituted, then
+			// the content could be raw text/RCDATA for some inputs
+			// and regular HTML content for others.
+			`<{{"script"}}>{{"doEvil()"}}</{{"script"}}>`,
+			`<script>doEvil()</script>`,
+		},
+	}
+
+	for _, test := range tests {
+		tmpl := New(test.name)
+		// TODO: Move noescape into template/func.go
+		tmpl.Funcs(FuncMap{
+			"noescape": func(a ...interface{}) string {
+				return fmt.Sprint(a...)
+			},
+		})
+		tmpl = Must(tmpl.Parse(test.input))
+		b := new(bytes.Buffer)
+		if err := tmpl.Execute(b, data); err != nil {
+			t.Errorf("%s: template execution failed: %s", test.name, err)
+			continue
+		}
+		if w, g := test.output, b.String(); w != g {
+			t.Errorf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
+			continue
+		}
+		b.Reset()
+		if err := tmpl.Execute(b, pdata); err != nil {
+			t.Errorf("%s: template execution failed for pointer: %s", test.name, err)
+			continue
+		}
+		if w, g := test.output, b.String(); w != g {
+			t.Errorf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
+			continue
+		}
+	}
+}
+
+func TestEscapeSet(t *testing.T) {
+	type dataItem struct {
+		Children []*dataItem
+		X        string
+	}
+
+	data := dataItem{
+		Children: []*dataItem{
+			{X: "foo"},
+			{X: "<bar>"},
+			{
+				Children: []*dataItem{
+					{X: "baz"},
+				},
+			},
+		},
+	}
+
+	tests := []struct {
+		inputs map[string]string
+		want   string
+	}{
+		// The trivial set.
+		{
+			map[string]string{
+				"main": ``,
+			},
+			``,
+		},
+		// A template called in the start context.
+		{
+			map[string]string{
+				"main": `Hello, {{template "helper"}}!`,
+				// Not a valid top level HTML template.
+				// "<b" is not a full tag.
+				"helper": `{{"<World>"}}`,
+			},
+			`Hello, <World>!`,
+		},
+		// A template called in a context other than the start.
+		{
+			map[string]string{
+				"main": `<a onclick='a = {{template "helper"}};'>`,
+				// Not a valid top level HTML template.
+				// "<b" is not a full tag.
+				"helper": `{{"<a>"}}<b`,
+			},
+			`<a onclick='a = "\u003ca\u003e"<b;'>`,
+		},
+		// A recursive template that ends in its start context.
+		{
+			map[string]string{
+				"main": `{{range .Children}}{{template "main" .}}{{else}}{{.X}} {{end}}`,
+			},
+			`foo <bar> baz `,
+		},
+		// A recursive helper template that ends in its start context.
+		{
+			map[string]string{
+				"main":   `{{template "helper" .}}`,
+				"helper": `{{if .Children}}<ul>{{range .Children}}<li>{{template "main" .}}</li>{{end}}</ul>{{else}}{{.X}}{{end}}`,
+			},
+			`<ul><li>foo</li><li><bar></li><li><ul><li>baz</li></ul></li></ul>`,
+		},
+		// Co-recursive templates that end in its start context.
+		{
+			map[string]string{
+				"main":   `<blockquote>{{range .Children}}{{template "helper" .}}{{end}}</blockquote>`,
+				"helper": `{{if .Children}}{{template "main" .}}{{else}}{{.X}}<br>{{end}}`,
+			},
+			`<blockquote>foo<br><bar><br><blockquote>baz<br></blockquote></blockquote>`,
+		},
+		// A template that is called in two different contexts.
+		{
+			map[string]string{
+				"main":   `<button onclick="title='{{template "helper"}}'; ...">{{template "helper"}}</button>`,
+				"helper": `{{11}} of {{"<100>"}}`,
+			},
+			`<button onclick="title='11 of \x3c100\x3e'; ...">11 of <100></button>`,
+		},
+		// A non-recursive template that ends in a different context.
+		// helper starts in jsCtxRegexp and ends in jsCtxDivOp.
+		{
+			map[string]string{
+				"main":   `<script>var x={{template "helper"}}/{{"42"}};</script>`,
+				"helper": "{{126}}",
+			},
+			`<script>var x= 126 /"42";</script>`,
+		},
+		// A recursive template that ends in a similar context.
+		{
+			map[string]string{
+				"main":      `<script>var x=[{{template "countdown" 4}}];</script>`,
+				"countdown": `{{.}}{{if .}},{{template "countdown" . | pred}}{{end}}`,
+			},
+			`<script>var x=[ 4 , 3 , 2 , 1 , 0 ];</script>`,
+		},
+		// A recursive template that ends in a different context.
+		/*
+			{
+				map[string]string{
+					"main":   `<a href="/foo{{template "helper" .}}">`,
+					"helper": `{{if .Children}}{{range .Children}}{{template "helper" .}}{{end}}{{else}}?x={{.X}}{{end}}`,
+				},
+				`<a href="/foo?x=foo?x=%3cbar%3e?x=baz">`,
+			},
+		*/
+	}
+
+	// pred is a template function that returns the predecessor of a
+	// natural number for testing recursive templates.
+	fns := FuncMap{"pred": func(a ...interface{}) (interface{}, error) {
+		if len(a) == 1 {
+			if i, _ := a[0].(int); i > 0 {
+				return i - 1, nil
+			}
+		}
+		return nil, fmt.Errorf("undefined pred(%v)", a)
+	}}
+
+	for _, test := range tests {
+		source := ""
+		for name, body := range test.inputs {
+			source += fmt.Sprintf("{{define %q}}%s{{end}} ", name, body)
+		}
+		tmpl, err := New("root").Funcs(fns).Parse(source)
+		if err != nil {
+			t.Errorf("error parsing %q: %v", source, err)
+			continue
+		}
+		var b bytes.Buffer
+
+		if err := tmpl.ExecuteTemplate(&b, "main", data); err != nil {
+			t.Errorf("%q executing %v", err.Error(), tmpl.Lookup("main"))
+			continue
+		}
+		if got := b.String(); test.want != got {
+			t.Errorf("want\n\t%q\ngot\n\t%q", test.want, got)
+		}
+	}
+
+}
+
+func TestErrors(t *testing.T) {
+	tests := []struct {
+		input string
+		err   string
+	}{
+		// Non-error cases.
+		{
+			"{{if .Cond}}<a>{{else}}<b>{{end}}",
+			"",
+		},
+		{
+			"{{if .Cond}}<a>{{end}}",
+			"",
+		},
+		{
+			"{{if .Cond}}{{else}}<b>{{end}}",
+			"",
+		},
+		{
+			"{{with .Cond}}<div>{{end}}",
+			"",
+		},
+		{
+			"{{range .Items}}<a>{{end}}",
+			"",
+		},
+		{
+			"<a href='/foo?{{range .Items}}&{{.K}}={{.V}}{{end}}'>",
+			"",
+		},
+		// Error cases.
+		{
+			"{{if .Cond}}<a{{end}}",
+			"z:1: {{if}} branches",
+		},
+		{
+			"{{if .Cond}}\n{{else}}\n<a{{end}}",
+			"z:1: {{if}} branches",
+		},
+		{
+			// Missing quote in the else branch.
+			`{{if .Cond}}<a href="foo">{{else}}<a href="bar>{{end}}`,
+			"z:1: {{if}} branches",
+		},
+		{
+			// Different kind of attribute: href implies a URL.
+			"<a {{if .Cond}}href='{{else}}title='{{end}}{{.X}}'>",
+			"z:1: {{if}} branches",
+		},
+		{
+			"\n{{with .X}}<a{{end}}",
+			"z:2: {{with}} branches",
+		},
+		{
+			"\n{{with .X}}<a>{{else}}<a{{end}}",
+			"z:2: {{with}} branches",
+		},
+		{
+			"{{range .Items}}<a{{end}}",
+			`z:1: on range loop re-entry: "<" in attribute name: "<a"`,
+		},
+		{
+			"\n{{range .Items}} x='<a{{end}}",
+			"z:2: on range loop re-entry: {{range}} branches",
+		},
+		{
+			"<a b=1 c={{.H}}",
+			"z: ends in a non-text context: {stateAttr delimSpaceOrTagEnd",
+		},
+		{
+			"<script>foo();",
+			"z: ends in a non-text context: {stateJS",
+		},
+		{
+			`<a href="{{if .F}}/foo?a={{else}}/bar/{{end}}{{.H}}">`,
+			"z:1: {{.H}} appears in an ambiguous URL context",
+		},
+		{
+			`<a onclick="alert('Hello \`,
+			`unfinished escape sequence in JS string: "Hello \\"`,
+		},
+		{
+			`<a onclick='alert("Hello\, World\`,
+			`unfinished escape sequence in JS string: "Hello\\, World\\"`,
+		},
+		{
+			`<a onclick='alert(/x+\`,
+			`unfinished escape sequence in JS string: "x+\\"`,
+		},
+		{
+			`<a onclick="/foo[\]/`,
+			`unfinished JS regexp charset: "foo[\\]/"`,
+		},
+		{
+			// It is ambiguous whether 1.5 should be 1\.5 or 1.5.
+			// Either `var x = 1/- 1.5 /i.test(x)`
+			// where `i.test(x)` is a method call of reference i,
+			// or `/-1\.5/i.test(x)` which is a method call on a
+			// case insensitive regular expression.
+			`<script>{{if false}}var x = 1{{end}}/-{{"1.5"}}/i.test(x)</script>`,
+			`'/' could start a division or regexp: "/-"`,
+		},
+		{
+			`{{template "foo"}}`,
+			"z:1: no such template \"foo\"",
+		},
+		{
+			`<div{{template "y"}}>` +
+				// Illegal starting in stateTag but not in stateText.
+				`{{define "y"}} foo<b{{end}}`,
+			`"<" in attribute name: " foo<b"`,
+		},
+		{
+			`<script>reverseList = [{{template "t"}}]</script>` +
+				// Missing " after recursive call.
+				`{{define "t"}}{{if .Tail}}{{template "t" .Tail}}{{end}}{{.Head}}",{{end}}`,
+			`: cannot compute output context for template t$htmltemplate_stateJS_elementScript`,
+		},
+		{
+			`<input type=button value=onclick=>`,
+			`html/template:z: "=" in unquoted attr: "onclick="`,
+		},
+		{
+			`<input type=button value= onclick=>`,
+			`html/template:z: "=" in unquoted attr: "onclick="`,
+		},
+		{
+			`<input type=button value= 1+1=2>`,
+			`html/template:z: "=" in unquoted attr: "1+1=2"`,
+		},
+		{
+			"<a class=`foo>",
+			"html/template:z: \"`\" in unquoted attr: \"`foo\"",
+		},
+		{
+			`<a style=font:'Arial'>`,
+			`html/template:z: "'" in unquoted attr: "font:'Arial'"`,
+		},
+		{
+			`<a=foo>`,
+			`: expected space, attr name, or end of tag, but got "=foo>"`,
+		},
+	}
+
+	for _, test := range tests {
+		buf := new(bytes.Buffer)
+		tmpl, err := New("z").Parse(test.input)
+		if err != nil {
+			t.Errorf("input=%q: unexpected parse error %s\n", test.input, err)
+			continue
+		}
+		err = tmpl.Execute(buf, nil)
+		var got string
+		if err != nil {
+			got = err.Error()
+		}
+		if test.err == "" {
+			if got != "" {
+				t.Errorf("input=%q: unexpected error %q", test.input, got)
+			}
+			continue
+		}
+		if strings.Index(got, test.err) == -1 {
+			t.Errorf("input=%q: error\n\t%q\ndoes not contain expected string\n\t%q", test.input, got, test.err)
+			continue
+		}
+	}
+}
+
+func TestEscapeText(t *testing.T) {
+	tests := []struct {
+		input  string
+		output context
+	}{
+		{
+			``,
+			context{},
+		},
+		{
+			`Hello, World!`,
+			context{},
+		},
+		{
+			// An orphaned "<" is OK.
+			`I <3 Ponies!`,
+			context{},
+		},
+		{
+			`<a`,
+			context{state: stateTag},
+		},
+		{
+			`<a `,
+			context{state: stateTag},
+		},
+		{
+			`<a>`,
+			context{state: stateText},
+		},
+		{
+			`<a href`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a on`,
+			context{state: stateAttrName, attr: attrScript},
+		},
+		{
+			`<a href `,
+			context{state: stateAfterName, attr: attrURL},
+		},
+		{
+			`<a style  =  `,
+			context{state: stateBeforeValue, attr: attrStyle},
+		},
+		{
+			`<a href=`,
+			context{state: stateBeforeValue, attr: attrURL},
+		},
+		{
+			`<a href=x`,
+			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href=x `,
+			context{state: stateTag},
+		},
+		{
+			`<a href=>`,
+			context{state: stateText},
+		},
+		{
+			`<a href=x>`,
+			context{state: stateText},
+		},
+		{
+			`<a href ='`,
+			context{state: stateURL, delim: delimSingleQuote},
+		},
+		{
+			`<a href=''`,
+			context{state: stateTag},
+		},
+		{
+			`<a href= "`,
+			context{state: stateURL, delim: delimDoubleQuote},
+		},
+		{
+			`<a href=""`,
+			context{state: stateTag},
+		},
+		{
+			`<a title="`,
+			context{state: stateAttr, delim: delimDoubleQuote},
+		},
+		{
+			`<a HREF='http:`,
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a Href='/`,
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href='"`,
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href="'`,
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href=''`,
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href=""`,
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href=""`,
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a href="`,
+			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
+		},
+		{
+			`<img alt="1">`,
+			context{state: stateText},
+		},
+		{
+			`<img alt="1>"`,
+			context{state: stateTag},
+		},
+		{
+			`<img alt="1>">`,
+			context{state: stateText},
+		},
+		{
+			`<input checked type="checkbox"`,
+			context{state: stateTag},
+		},
+		{
+			`<a onclick="`,
+			context{state: stateJS, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="//foo`,
+			context{state: stateJSLineCmt, delim: delimDoubleQuote},
+		},
+		{
+			"<a onclick='//\n",
+			context{state: stateJS, delim: delimSingleQuote},
+		},
+		{
+			"<a onclick='//\r\n",
+			context{state: stateJS, delim: delimSingleQuote},
+		},
+		{
+			"<a onclick='//\u2028",
+			context{state: stateJS, delim: delimSingleQuote},
+		},
+		{
+			`<a onclick="/*`,
+			context{state: stateJSBlockCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/*/`,
+			context{state: stateJSBlockCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/**/`,
+			context{state: stateJS, delim: delimDoubleQuote},
+		},
+		{
+			`<a onkeypress=""`,
+			context{state: stateJSDqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick='"foo"`,
+			context{state: stateJS, delim: delimSingleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick='foo'`,
+			context{state: stateJS, delim: delimSpaceOrTagEnd, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick='foo`,
+			context{state: stateJSSqStr, delim: delimSpaceOrTagEnd},
+		},
+		{
+			`<a onclick=""foo'`,
+			context{state: stateJSDqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="'foo"`,
+			context{state: stateJSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<A ONCLICK="'`,
+			context{state: stateJSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/`,
+			context{state: stateJSRegexp, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="'foo'`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick="'foo\'`,
+			context{state: stateJSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="'foo\'`,
+			context{state: stateJSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/foo/`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<script>/foo/ /=`,
+			context{state: stateJS, element: elementScript},
+		},
+		{
+			`<a onclick="1 /foo`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick="1 /*c*/ /foo`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<a onclick="/foo[/]`,
+			context{state: stateJSRegexp, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/foo\/`,
+			context{state: stateJSRegexp, delim: delimDoubleQuote},
+		},
+		{
+			`<a onclick="/foo/`,
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+		},
+		{
+			`<input checked style="`,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="//`,
+			context{state: stateCSSLineCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="//</script>`,
+			context{state: stateCSSLineCmt, delim: delimDoubleQuote},
+		},
+		{
+			"<a style='//\n",
+			context{state: stateCSS, delim: delimSingleQuote},
+		},
+		{
+			"<a style='//\r",
+			context{state: stateCSS, delim: delimSingleQuote},
+		},
+		{
+			`<a style="/*`,
+			context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="/*/`,
+			context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="/**/`,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: '`,
+			context{state: stateCSSSqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: "`,
+			context{state: stateCSSDqStr, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: '/foo?img=`,
+			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
+		},
+		{
+			`<a style="background: '/`,
+			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url(&#x22;/`,
+			context{state: stateCSSDqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url('/`,
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url('/)`,
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url('/ `,
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url(/`,
+			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+		},
+		{
+			`<a style="background: url( `,
+			context{state: stateCSSURL, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: url( /image?name=`,
+			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
+		},
+		{
+			`<a style="background: url(x)`,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: url('x'`,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<a style="background: url( x `,
+			context{state: stateCSS, delim: delimDoubleQuote},
+		},
+		{
+			`<!-- foo`,
+			context{state: stateHTMLCmt},
+		},
+		{
+			`<!-->`,
+			context{state: stateHTMLCmt},
+		},
+		{
+			`<!--->`,
+			context{state: stateHTMLCmt},
+		},
+		{
+			`<!-- foo -->`,
+			context{state: stateText},
+		},
+		{
+			`<script`,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script `,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script src="foo.js" `,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script src='foo.js' `,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script type=text/javascript `,
+			context{state: stateTag, element: elementScript},
+		},
+		{
+			`<script>foo`,
+			context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
+		},
+		{
+			`<script>foo</script>`,
+			context{state: stateText},
+		},
+		{
+			`<script>foo</script><!--`,
+			context{state: stateHTMLCmt},
+		},
+		{
+			`<script>document.write("<p>foo</p>");`,
+			context{state: stateJS, element: elementScript},
+		},
+		{
+			`<script>document.write("<p>foo<\/script>");`,
+			context{state: stateJS, element: elementScript},
+		},
+		{
+			`<script>document.write("<script>alert(1)</script>");`,
+			context{state: stateText},
+		},
+		{
+			`<Script>`,
+			context{state: stateJS, element: elementScript},
+		},
+		{
+			`<SCRIPT>foo`,
+			context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
+		},
+		{
+			`<textarea>value`,
+			context{state: stateRCDATA, element: elementTextarea},
+		},
+		{
+			`<textarea>value</TEXTAREA>`,
+			context{state: stateText},
+		},
+		{
+			`<textarea name=html><b`,
+			context{state: stateRCDATA, element: elementTextarea},
+		},
+		{
+			`<title>value`,
+			context{state: stateRCDATA, element: elementTitle},
+		},
+		{
+			`<style>value`,
+			context{state: stateCSS, element: elementStyle},
+		},
+		{
+			`<a xlink:href`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a xmlns`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a xmlns:foo`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a xmlnsxyz`,
+			context{state: stateAttrName},
+		},
+		{
+			`<a data-url`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a data-iconUri`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a data-urlItem`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a g:`,
+			context{state: stateAttrName},
+		},
+		{
+			`<a g:url`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a g:iconUri`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a g:urlItem`,
+			context{state: stateAttrName, attr: attrURL},
+		},
+		{
+			`<a g:value`,
+			context{state: stateAttrName},
+		},
+		{
+			`<a svg:style='`,
+			context{state: stateCSS, delim: delimSingleQuote},
+		},
+		{
+			`<svg:font-face`,
+			context{state: stateTag},
+		},
+		{
+			`<svg:a svg:onclick="`,
+			context{state: stateJS, delim: delimDoubleQuote},
+		},
+	}
+
+	for _, test := range tests {
+		b, e := []byte(test.input), newEscaper(nil)
+		c := e.escapeText(context{}, &parse.TextNode{parse.NodeText, b})
+		if !test.output.eq(c) {
+			t.Errorf("input %q: want context\n\t%v\ngot\n\t%v", test.input, test.output, c)
+			continue
+		}
+		if test.input != string(b) {
+			t.Errorf("input %q: text node was modified: want %q got %q", test.input, test.input, b)
+			continue
+		}
+	}
+}
+
+func TestEnsurePipelineContains(t *testing.T) {
+	tests := []struct {
+		input, output string
+		ids           []string
+	}{
+		{
+			"{{.X}}",
+			".X",
+			[]string{},
+		},
+		{
+			"{{.X | html}}",
+			".X | html",
+			[]string{},
+		},
+		{
+			"{{.X}}",
+			".X | html",
+			[]string{"html"},
+		},
+		{
+			"{{.X | html}}",
+			".X | html | urlquery",
+			[]string{"urlquery"},
+		},
+		{
+			"{{.X | html | urlquery}}",
+			".X | html | urlquery",
+			[]string{"urlquery"},
+		},
+		{
+			"{{.X | html | urlquery}}",
+			".X | html | urlquery",
+			[]string{"html", "urlquery"},
+		},
+		{
+			"{{.X | html | urlquery}}",
+			".X | html | urlquery",
+			[]string{"html"},
+		},
+		{
+			"{{.X | urlquery}}",
+			".X | html | urlquery",
+			[]string{"html", "urlquery"},
+		},
+		{
+			"{{.X | html | print}}",
+			".X | urlquery | html | print",
+			[]string{"urlquery", "html"},
+		},
+	}
+	for i, test := range tests {
+		tmpl := template.Must(template.New("test").Parse(test.input))
+		action, ok := (tmpl.Tree.Root.Nodes[0].(*parse.ActionNode))
+		if !ok {
+			t.Errorf("#%d: First node is not an action: %s", i, test.input)
+			continue
+		}
+		pipe := action.Pipe
+		ensurePipelineContains(pipe, test.ids)
+		got := pipe.String()
+		if got != test.output {
+			t.Errorf("#%d: %s, %v: want\n\t%s\ngot\n\t%s", i, test.input, test.ids, test.output, got)
+		}
+	}
+}
+
+func TestEscapeErrorsNotIgnorable(t *testing.T) {
+	var b bytes.Buffer
+	tmpl, _ := New("dangerous").Parse("<a")
+	err := tmpl.Execute(&b, nil)
+	if err == nil {
+		t.Errorf("Expected error")
+	} else if b.Len() != 0 {
+		t.Errorf("Emitted output despite escaping failure")
+	}
+}
+
+func TestEscapeSetErrorsNotIgnorable(t *testing.T) {
+	var b bytes.Buffer
+	tmpl, err := New("root").Parse(`{{define "t"}}<a{{end}}`)
+	if err != nil {
+		t.Errorf("failed to parse set: %q", err)
+	}
+	err = tmpl.ExecuteTemplate(&b, "t", nil)
+	if err == nil {
+		t.Errorf("Expected error")
+	} else if b.Len() != 0 {
+		t.Errorf("Emitted output despite escaping failure")
+	}
+}
+
+func TestRedundantFuncs(t *testing.T) {
+	inputs := []interface{}{
+		"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+			"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+			` !"#$%&'()*+,-./` +
+			`0123456789:;<=>?` +
+			`@ABCDEFGHIJKLMNO` +
+			`PQRSTUVWXYZ[\]^_` +
+			"`abcdefghijklmno" +
+			"pqrstuvwxyz{|}~\x7f" +
+			"\u00A0\u0100\u2028\u2029\ufeff\ufdec\ufffd\uffff\U0001D11E" +
+			"&%22\\",
+		CSS(`a[href =~ "//example.com"]#foo`),
+		HTML(`Hello, <b>World</b> &tc!`),
+		HTMLAttr(` dir="ltr"`),
+		JS(`c && alert("Hello, World!");`),
+		JSStr(`Hello, World & O'Reilly\x21`),
+		URL(`greeting=H%69&addressee=(World)`),
+	}
+
+	for n0, m := range redundantFuncs {
+		f0 := funcMap[n0].(func(...interface{}) string)
+		for n1 := range m {
+			f1 := funcMap[n1].(func(...interface{}) string)
+			for _, input := range inputs {
+				want := f0(input)
+				if got := f1(want); want != got {
+					t.Errorf("%s %s with %T %q: want\n\t%q,\ngot\n\t%q", n0, n1, input, input, want, got)
+				}
+			}
+		}
+	}
+}
+
+func TestIndirectPrint(t *testing.T) {
+	a := 3
+	ap := &a
+	b := "hello"
+	bp := &b
+	bpp := &bp
+	tmpl := Must(New("t").Parse(`{{.}}`))
+	var buf bytes.Buffer
+	err := tmpl.Execute(&buf, ap)
+	if err != nil {
+		t.Errorf("Unexpected error: %s", err)
+	} else if buf.String() != "3" {
+		t.Errorf(`Expected "3"; got %q`, buf.String())
+	}
+	buf.Reset()
+	err = tmpl.Execute(&buf, bpp)
+	if err != nil {
+		t.Errorf("Unexpected error: %s", err)
+	} else if buf.String() != "hello" {
+		t.Errorf(`Expected "hello"; got %q`, buf.String())
+	}
+}
+
+func BenchmarkEscapedExecute(b *testing.B) {
+	tmpl := Must(New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`))
+	var buf bytes.Buffer
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		tmpl.Execute(&buf, "foo & 'bar' & baz")
+		buf.Reset()
+	}
+}
diff --git a/src/pkg/html/template/html.go b/src/pkg/html/template/html.go
new file mode 100644
index 0000000..7b77d65
--- /dev/null
+++ b/src/pkg/html/template/html.go
@@ -0,0 +1,257 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"unicode/utf8"
+)
+
+// htmlNospaceEscaper escapes for inclusion in unquoted attribute values.
+func htmlNospaceEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTML {
+		return htmlReplacer(stripTags(s), htmlNospaceNormReplacementTable, false)
+	}
+	return htmlReplacer(s, htmlNospaceReplacementTable, false)
+}
+
+// attrEscaper escapes for inclusion in quoted attribute values.
+func attrEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTML {
+		return htmlReplacer(stripTags(s), htmlNormReplacementTable, true)
+	}
+	return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// rcdataEscaper escapes for inclusion in an RCDATA element body.
+func rcdataEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTML {
+		return htmlReplacer(s, htmlNormReplacementTable, true)
+	}
+	return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// htmlEscaper escapes for inclusion in HTML text.
+func htmlEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTML {
+		return s
+	}
+	return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// htmlReplacementTable contains the runes that need to be escaped
+// inside a quoted attribute value or in a text node.
+var htmlReplacementTable = []string{
+	// http://www.w3.org/TR/html5/tokenization.html#attribute-value-unquoted-state: "
+	// U+0000 NULL Parse error. Append a U+FFFD REPLACEMENT
+	// CHARACTER character to the current attribute's value.
+	// "
+	// and similarly
+	// http://www.w3.org/TR/html5/tokenization.html#before-attribute-value-state
+	0:    "\uFFFD",
+	'"':  """,
+	'&':  "&",
+	'\'': "'",
+	'+':  "+",
+	'<':  "<",
+	'>':  ">",
+}
+
+// htmlNormReplacementTable is like htmlReplacementTable but without '&' to
+// avoid over-encoding existing entities.
+var htmlNormReplacementTable = []string{
+	0:    "\uFFFD",
+	'"':  """,
+	'\'': "'",
+	'+':  "+",
+	'<':  "<",
+	'>':  ">",
+}
+
+// htmlNospaceReplacementTable contains the runes that need to be escaped
+// inside an unquoted attribute value.
+// The set of runes escaped is the union of the HTML specials and
+// those determined by running the JS below in browsers:
+// <div id=d></div>
+// <script>(function () {
+// var a = [], d = document.getElementById("d"), i, c, s;
+// for (i = 0; i < 0x10000; ++i) {
+//   c = String.fromCharCode(i);
+//   d.innerHTML = "<span title=" + c + "lt" + c + "></span>"
+//   s = d.getElementsByTagName("SPAN")[0];
+//   if (!s || s.title !== c + "lt" + c) { a.push(i.toString(16)); }
+// }
+// document.write(a.join(", "));
+// })()</script>
+var htmlNospaceReplacementTable = []string{
+	0:    "&#xfffd;",
+	'\t': "	",
+	'\n': "
",
+	'\v': "",
+	'\f': "",
+	'\r': "
",
+	' ':  " ",
+	'"':  """,
+	'&':  "&",
+	'\'': "'",
+	'+':  "+",
+	'<':  "<",
+	'=':  "=",
+	'>':  ">",
+	// A parse error in the attribute value (unquoted) and 
+	// before attribute value states.
+	// Treated as a quoting character by IE.
+	'`': "`",
+}
+
+// htmlNospaceNormReplacementTable is like htmlNospaceReplacementTable but
+// without '&' to avoid over-encoding existing entities.
+var htmlNospaceNormReplacementTable = []string{
+	0:    "&#xfffd;",
+	'\t': "	",
+	'\n': "
",
+	'\v': "",
+	'\f': "",
+	'\r': "
",
+	' ':  " ",
+	'"':  """,
+	'\'': "'",
+	'+':  "+",
+	'<':  "<",
+	'=':  "=",
+	'>':  ">",
+	// A parse error in the attribute value (unquoted) and 
+	// before attribute value states.
+	// Treated as a quoting character by IE.
+	'`': "`",
+}
+
+// htmlReplacer returns s with runes replaced acccording to replacementTable
+// and when badRunes is true, certain bad runes are allowed through unescaped.
+func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
+	written, b := 0, new(bytes.Buffer)
+	for i, r := range s {
+		if int(r) < len(replacementTable) {
+			if repl := replacementTable[r]; len(repl) != 0 {
+				b.WriteString(s[written:i])
+				b.WriteString(repl)
+				// Valid as long as replacementTable doesn't 
+				// include anything above 0x7f.
+				written = i + utf8.RuneLen(r)
+			}
+		} else if badRunes {
+			// No-op.
+			// IE does not allow these ranges in unquoted attrs.
+		} else if 0xfdd0 <= r && r <= 0xfdef || 0xfff0 <= r && r <= 0xffff {
+			fmt.Fprintf(b, "%s&#x%x;", s[written:i], r)
+			written = i + utf8.RuneLen(r)
+		}
+	}
+	if written == 0 {
+		return s
+	}
+	b.WriteString(s[written:])
+	return b.String()
+}
+
+// stripTags takes a snippet of HTML and returns only the text content.
+// For example, `<b>¡Hi!</b> <script>...</script>` -> `¡Hi! `.
+func stripTags(html string) string {
+	var b bytes.Buffer
+	s, c, i, allText := []byte(html), context{}, 0, true
+	// Using the transition funcs helps us avoid mangling
+	// `<div title="1>2">` or `I <3 Ponies!`.
+	for i != len(s) {
+		if c.delim == delimNone {
+			st := c.state
+			// Use RCDATA instead of parsing into JS or CSS styles.
+			if c.element != elementNone && !isInTag(st) {
+				st = stateRCDATA
+			}
+			d, nread := transitionFunc[st](c, s[i:])
+			i1 := i + nread
+			if c.state == stateText || c.state == stateRCDATA {
+				// Emit text up to the start of the tag or comment.
+				j := i1
+				if d.state != c.state {
+					for j1 := j - 1; j1 >= i; j1-- {
+						if s[j1] == '<' {
+							j = j1
+							break
+						}
+					}
+				}
+				b.Write(s[i:j])
+			} else {
+				allText = false
+			}
+			c, i = d, i1
+			continue
+		}
+		i1 := i + bytes.IndexAny(s[i:], delimEnds[c.delim])
+		if i1 < i {
+			break
+		}
+		if c.delim != delimSpaceOrTagEnd {
+			// Consume any quote.
+			i1++
+		}
+		c, i = context{state: stateTag, element: c.element}, i1
+	}
+	if allText {
+		return html
+	} else if c.state == stateText || c.state == stateRCDATA {
+		b.Write(s[i:])
+	}
+	return b.String()
+}
+
+// htmlNameFilter accepts valid parts of an HTML attribute or tag name or
+// a known-safe HTML attribute.
+func htmlNameFilter(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeHTMLAttr {
+		return s
+	}
+	if len(s) == 0 {
+		// Avoid violation of structure preservation.
+		// <input checked {{.K}}={{.V}}>.
+		// Without this, if .K is empty then .V is the value of
+		// checked, but otherwise .V is the value of the attribute
+		// named .K.
+		return filterFailsafe
+	}
+	s = strings.ToLower(s)
+	if t := attrType(s); t != contentTypePlain {
+		// TODO: Split attr and element name part filters so we can whitelist
+		// attributes.
+		return filterFailsafe
+	}
+	for _, r := range s {
+		switch {
+		case '0' <= r && r <= '9':
+		case 'a' <= r && r <= 'z':
+		default:
+			return filterFailsafe
+		}
+	}
+	return s
+}
+
+// commentEscaper returns the empty string regardless of input.
+// Comment content does not correspond to any parsed structure or
+// human-readable content, so the simplest and most secure policy is to drop
+// content interpolated into comments.
+// This approach is equally valid whether or not static comment content is
+// removed from the template.
+func commentEscaper(args ...interface{}) string {
+	return ""
+}
diff --git a/src/pkg/html/template/html_test.go b/src/pkg/html/template/html_test.go
new file mode 100644
index 0000000..b9b9703
--- /dev/null
+++ b/src/pkg/html/template/html_test.go
@@ -0,0 +1,94 @@
+// Copyright 2011 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 template
+
+import (
+	"html"
+	"strings"
+	"testing"
+)
+
+func TestHTMLNospaceEscaper(t *testing.T) {
+	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		"`abcdefghijklmno" +
+		"pqrstuvwxyz{|}~\x7f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\ufdec\U0001D11E")
+
+	want := ("&#xfffd;\x01\x02\x03\x04\x05\x06\x07" +
+		"\x08	

\x0E\x0F" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17" +
+		"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		``abcdefghijklmno` +
+		`pqrstuvwxyz{|}~` + "\u007f" +
+		"\u00A0\u0100\u2028\u2029\ufeff&#xfdec;\U0001D11E")
+
+	got := htmlNospaceEscaper(input)
+	if got != want {
+		t.Errorf("encode: want\n\t%q\nbut got\n\t%q", want, got)
+	}
+
+	got, want = html.UnescapeString(got), strings.Replace(input, "\x00", "\ufffd", 1)
+	if want != got {
+		t.Errorf("decode: want\n\t%q\nbut got\n\t%q", want, got)
+	}
+}
+
+func TestStripTags(t *testing.T) {
+	tests := []struct {
+		input, want string
+	}{
+		{"", ""},
+		{"Hello, World!", "Hello, World!"},
+		{"foo&bar", "foo&bar"},
+		{`Hello <a href="www.example.com/">World</a>!`, "Hello World!"},
+		{"Foo <textarea>Bar</textarea> Baz", "Foo Bar Baz"},
+		{"Foo <!-- Bar --> Baz", "Foo  Baz"},
+		{"<", "<"},
+		{"foo < bar", "foo < bar"},
+		{`Foo<script type="text/javascript">alert(1337)</script>Bar`, "FooBar"},
+		{`Foo<div title="1>2">Bar`, "FooBar"},
+		{`I <3 Ponies!`, `I <3 Ponies!`},
+		{`<script>foo()</script>`, ``},
+	}
+
+	for _, test := range tests {
+		if got := stripTags(test.input); got != test.want {
+			t.Errorf("%q: want %q, got %q", test.input, test.want, got)
+		}
+	}
+}
+
+func BenchmarkHTMLNospaceEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		htmlNospaceEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkHTMLNospaceEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		htmlNospaceEscaper("The_quick,_brown_fox_jumps_over_the_lazy_dog.")
+	}
+}
+
+func BenchmarkStripTags(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		stripTags("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkStripTagsNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		stripTags("The quick, brown fox jumps over the lazy dog.")
+	}
+}
diff --git a/src/pkg/html/template/js.go b/src/pkg/html/template/js.go
new file mode 100644
index 0000000..0e632df
--- /dev/null
+++ b/src/pkg/html/template/js.go
@@ -0,0 +1,362 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"strings"
+	"unicode/utf8"
+)
+
+// nextJSCtx returns the context that determines whether a slash after the
+// given run of tokens tokens starts a regular expression instead of a division
+// operator: / or /=.
+//
+// This assumes that the token run does not include any string tokens, comment
+// tokens, regular expression literal tokens, or division operators.
+//
+// This fails on some valid but nonsensical JavaScript programs like
+// "x = ++/foo/i" which is quite different than "x++/foo/i", but is not known to
+// fail on any known useful programs. It is based on the draft
+// JavaScript 2.0 lexical grammar and requires one token of lookbehind:
+// http://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
+func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
+	s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029")
+	if len(s) == 0 {
+		return preceding
+	}
+
+	// All cases below are in the single-byte UTF-8 group.
+	switch c, n := s[len(s)-1], len(s); c {
+	case '+', '-':
+		// ++ and -- are not regexp preceders, but + and - are whether
+		// they are used as infix or prefix operators.
+		start := n - 1
+		// Count the number of adjacent dashes or pluses.
+		for start > 0 && s[start-1] == c {
+			start--
+		}
+		if (n-start)&1 == 1 {
+			// Reached for trailing minus signs since "---" is the
+			// same as "-- -".
+			return jsCtxRegexp
+		}
+		return jsCtxDivOp
+	case '.':
+		// Handle "42."
+		if n != 1 && '0' <= s[n-2] && s[n-2] <= '9' {
+			return jsCtxDivOp
+		}
+		return jsCtxRegexp
+	// Suffixes for all punctuators from section 7.7 of the language spec
+	// that only end binary operators not handled above.
+	case ',', '<', '>', '=', '*', '%', '&', '|', '^', '?':
+		return jsCtxRegexp
+	// Suffixes for all punctuators from section 7.7 of the language spec
+	// that are prefix operators not handled above.
+	case '!', '~':
+		return jsCtxRegexp
+	// Matches all the punctuators from section 7.7 of the language spec
+	// that are open brackets not handled above.
+	case '(', '[':
+		return jsCtxRegexp
+	// Matches all the punctuators from section 7.7 of the language spec
+	// that precede expression starts.
+	case ':', ';', '{':
+		return jsCtxRegexp
+	// CAVEAT: the close punctuators ('}', ']', ')') precede div ops and
+	// are handled in the default except for '}' which can precede a
+	// division op as in
+	//    ({ valueOf: function () { return 42 } } / 2
+	// which is valid, but, in practice, developers don't divide object
+	// literals, so our heuristic works well for code like
+	//    function () { ... }  /foo/.test(x) && sideEffect();
+	// The ')' punctuator can precede a regular expression as in
+	//     if (b) /foo/.test(x) && ...
+	// but this is much less likely than
+	//     (a + b) / c
+	case '}':
+		return jsCtxRegexp
+	default:
+		// Look for an IdentifierName and see if it is a keyword that
+		// can precede a regular expression.
+		j := n
+		for j > 0 && isJSIdentPart(rune(s[j-1])) {
+			j--
+		}
+		if regexpPrecederKeywords[string(s[j:])] {
+			return jsCtxRegexp
+		}
+	}
+	// Otherwise is a punctuator not listed above, or
+	// a string which precedes a div op, or an identifier
+	// which precedes a div op.
+	return jsCtxDivOp
+}
+
+// regexPrecederKeywords is a set of reserved JS keywords that can precede a
+// regular expression in JS source.
+var regexpPrecederKeywords = map[string]bool{
+	"break":      true,
+	"case":       true,
+	"continue":   true,
+	"delete":     true,
+	"do":         true,
+	"else":       true,
+	"finally":    true,
+	"in":         true,
+	"instanceof": true,
+	"return":     true,
+	"throw":      true,
+	"try":        true,
+	"typeof":     true,
+	"void":       true,
+}
+
+var jsonMarshalType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
+
+// indirectToJSONMarshaler returns the value, after dereferencing as many times
+// as necessary to reach the base type (or nil) or an implementation of json.Marshal.
+func indirectToJSONMarshaler(a interface{}) interface{} {
+	v := reflect.ValueOf(a)
+	for !v.Type().Implements(jsonMarshalType) && v.Kind() == reflect.Ptr && !v.IsNil() {
+		v = v.Elem()
+	}
+	return v.Interface()
+}
+
+// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
+// neither side-effects nor free variables outside (NaN, Infinity).
+func jsValEscaper(args ...interface{}) string {
+	var a interface{}
+	if len(args) == 1 {
+		a = indirectToJSONMarshaler(args[0])
+		switch t := a.(type) {
+		case JS:
+			return string(t)
+		case JSStr:
+			// TODO: normalize quotes.
+			return `"` + string(t) + `"`
+		case json.Marshaler:
+			// Do not treat as a Stringer.
+		case fmt.Stringer:
+			a = t.String()
+		}
+	} else {
+		for i, arg := range args {
+			args[i] = indirectToJSONMarshaler(arg)
+		}
+		a = fmt.Sprint(args...)
+	}
+	// TODO: detect cycles before calling Marshal which loops infinitely on
+	// cyclic data. This may be an unnacceptable DoS risk.
+
+	b, err := json.Marshal(a)
+	if err != nil {
+		// Put a space before comment so that if it is flush against
+		// a division operator it is not turned into a line comment:
+		//     x/{{y}}
+		// turning into
+		//     x//* error marshalling y:
+		//          second line of error message */null
+		return fmt.Sprintf(" /* %s */null ", strings.Replace(err.Error(), "*/", "* /", -1))
+	}
+
+	// TODO: maybe post-process output to prevent it from containing
+	// "<!--", "-->", "<![CDATA[", "]]>", or "</script"
+	// in case custom marshallers produce output containing those.
+
+	// TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.
+	if len(b) == 0 {
+		// In, `x=y/{{.}}*z` a json.Marshaler that produces "" should
+		// not cause the output `x=y/*z`.
+		return " null "
+	}
+	first, _ := utf8.DecodeRune(b)
+	last, _ := utf8.DecodeLastRune(b)
+	var buf bytes.Buffer
+	// Prevent IdentifierNames and NumericLiterals from running into
+	// keywords: in, instanceof, typeof, void
+	pad := isJSIdentPart(first) || isJSIdentPart(last)
+	if pad {
+		buf.WriteByte(' ')
+	}
+	written := 0
+	// Make sure that json.Marshal escapes codepoints U+2028 & U+2029
+	// so it falls within the subset of JSON which is valid JS.
+	for i := 0; i < len(b); {
+		rune, n := utf8.DecodeRune(b[i:])
+		repl := ""
+		if rune == 0x2028 {
+			repl = `\u2028`
+		} else if rune == 0x2029 {
+			repl = `\u2029`
+		}
+		if repl != "" {
+			buf.Write(b[written:i])
+			buf.WriteString(repl)
+			written = i + n
+		}
+		i += n
+	}
+	if buf.Len() != 0 {
+		buf.Write(b[written:])
+		if pad {
+			buf.WriteByte(' ')
+		}
+		b = buf.Bytes()
+	}
+	return string(b)
+}
+
+// jsStrEscaper produces a string that can be included between quotes in
+// JavaScript source, in JavaScript embedded in an HTML5 <script> element,
+// or in an HTML5 event handler attribute such as onclick.
+func jsStrEscaper(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeJSStr {
+		return replace(s, jsStrNormReplacementTable)
+	}
+	return replace(s, jsStrReplacementTable)
+}
+
+// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
+// specials so the result is treated literally when included in a regular
+// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
+// the literal text of {{.X}} followed by the string "bar".
+func jsRegexpEscaper(args ...interface{}) string {
+	s, _ := stringify(args...)
+	s = replace(s, jsRegexpReplacementTable)
+	if s == "" {
+		// /{{.X}}/ should not produce a line comment when .X == "".
+		return "(?:)"
+	}
+	return s
+}
+
+// replace replaces each rune r of s with replacementTable[r], provided that
+// r < len(replacementTable). If replacementTable[r] is the empty string then
+// no replacement is made.
+// It also replaces runes U+2028 and U+2029 with the raw strings `\u2028` and
+// `\u2029`.
+func replace(s string, replacementTable []string) string {
+	var b bytes.Buffer
+	written := 0
+	for i, r := range s {
+		var repl string
+		switch {
+		case int(r) < len(replacementTable) && replacementTable[r] != "":
+			repl = replacementTable[r]
+		case r == '\u2028':
+			repl = `\u2028`
+		case r == '\u2029':
+			repl = `\u2029`
+		default:
+			continue
+		}
+		b.WriteString(s[written:i])
+		b.WriteString(repl)
+		written = i + utf8.RuneLen(r)
+	}
+	if written == 0 {
+		return s
+	}
+	b.WriteString(s[written:])
+	return b.String()
+}
+
+var jsStrReplacementTable = []string{
+	0:    `\0`,
+	'\t': `\t`,
+	'\n': `\n`,
+	'\v': `\x0b`, // "\v" == "v" on IE 6.
+	'\f': `\f`,
+	'\r': `\r`,
+	// Encode HTML specials as hex so the output can be embedded
+	// in HTML attributes without further encoding.
+	'"':  `\x22`,
+	'&':  `\x26`,
+	'\'': `\x27`,
+	'+':  `\x2b`,
+	'/':  `\/`,
+	'<':  `\x3c`,
+	'>':  `\x3e`,
+	'\\': `\\`,
+}
+
+// jsStrNormReplacementTable is like jsStrReplacementTable but does not
+// overencode existing escapes since this table has no entry for `\`.
+var jsStrNormReplacementTable = []string{
+	0:    `\0`,
+	'\t': `\t`,
+	'\n': `\n`,
+	'\v': `\x0b`, // "\v" == "v" on IE 6.
+	'\f': `\f`,
+	'\r': `\r`,
+	// Encode HTML specials as hex so the output can be embedded
+	// in HTML attributes without further encoding.
+	'"':  `\x22`,
+	'&':  `\x26`,
+	'\'': `\x27`,
+	'+':  `\x2b`,
+	'/':  `\/`,
+	'<':  `\x3c`,
+	'>':  `\x3e`,
+}
+
+var jsRegexpReplacementTable = []string{
+	0:    `\0`,
+	'\t': `\t`,
+	'\n': `\n`,
+	'\v': `\x0b`, // "\v" == "v" on IE 6.
+	'\f': `\f`,
+	'\r': `\r`,
+	// Encode HTML specials as hex so the output can be embedded
+	// in HTML attributes without further encoding.
+	'"':  `\x22`,
+	'$':  `\$`,
+	'&':  `\x26`,
+	'\'': `\x27`,
+	'(':  `\(`,
+	')':  `\)`,
+	'*':  `\*`,
+	'+':  `\x2b`,
+	'-':  `\-`,
+	'.':  `\.`,
+	'/':  `\/`,
+	'<':  `\x3c`,
+	'>':  `\x3e`,
+	'?':  `\?`,
+	'[':  `\[`,
+	'\\': `\\`,
+	']':  `\]`,
+	'^':  `\^`,
+	'{':  `\{`,
+	'|':  `\|`,
+	'}':  `\}`,
+}
+
+// isJSIdentPart returns whether the given rune is a JS identifier part.
+// It does not handle all the non-Latin letters, joiners, and combining marks,
+// but it does handle every codepoint that can occur in a numeric literal or
+// a keyword.
+func isJSIdentPart(r rune) bool {
+	switch {
+	case r == '$':
+		return true
+	case '0' <= r && r <= '9':
+		return true
+	case 'A' <= r && r <= 'Z':
+		return true
+	case r == '_':
+		return true
+	case 'a' <= r && r <= 'z':
+		return true
+	}
+	return false
+}
diff --git a/src/pkg/html/template/js_test.go b/src/pkg/html/template/js_test.go
new file mode 100644
index 0000000..311e1d2
--- /dev/null
+++ b/src/pkg/html/template/js_test.go
@@ -0,0 +1,401 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"math"
+	"strings"
+	"testing"
+)
+
+func TestNextJsCtx(t *testing.T) {
+	tests := []struct {
+		jsCtx jsCtx
+		s     string
+	}{
+		// Statement terminators precede regexps.
+		{jsCtxRegexp, ";"},
+		// This is not airtight.
+		//     ({ valueOf: function () { return 1 } } / 2)
+		// is valid JavaScript but in practice, devs do not do this.
+		// A block followed by a statement starting with a RegExp is
+		// much more common:
+		//     while (x) {...} /foo/.test(x) || panic()
+		{jsCtxRegexp, "}"},
+		// But member, call, grouping, and array expression terminators
+		// precede div ops.
+		{jsCtxDivOp, ")"},
+		{jsCtxDivOp, "]"},
+		// At the start of a primary expression, array, or expression
+		// statement, expect a regexp.
+		{jsCtxRegexp, "("},
+		{jsCtxRegexp, "["},
+		{jsCtxRegexp, "{"},
+		// Assignment operators precede regexps as do all exclusively
+		// prefix and binary operators.
+		{jsCtxRegexp, "="},
+		{jsCtxRegexp, "+="},
+		{jsCtxRegexp, "*="},
+		{jsCtxRegexp, "*"},
+		{jsCtxRegexp, "!"},
+		// Whether the + or - is infix or prefix, it cannot precede a
+		// div op.
+		{jsCtxRegexp, "+"},
+		{jsCtxRegexp, "-"},
+		// An incr/decr op precedes a div operator.
+		// This is not airtight. In (g = ++/h/i) a regexp follows a
+		// pre-increment operator, but in practice devs do not try to
+		// increment or decrement regular expressions.
+		// (g++/h/i) where ++ is a postfix operator on g is much more
+		// common.
+		{jsCtxDivOp, "--"},
+		{jsCtxDivOp, "++"},
+		{jsCtxDivOp, "x--"},
+		// When we have many dashes or pluses, then they are grouped
+		// left to right.
+		{jsCtxRegexp, "x---"}, // A postfix -- then a -.
+		// return followed by a slash returns the regexp literal or the
+		// slash starts a regexp literal in an expression statement that
+		// is dead code.
+		{jsCtxRegexp, "return"},
+		{jsCtxRegexp, "return "},
+		{jsCtxRegexp, "return\t"},
+		{jsCtxRegexp, "return\n"},
+		{jsCtxRegexp, "return\u2028"},
+		// Identifiers can be divided and cannot validly be preceded by
+		// a regular expressions. Semicolon insertion cannot happen
+		// between an identifier and a regular expression on a new line
+		// because the one token lookahead for semicolon insertion has
+		// to conclude that it could be a div binary op and treat it as
+		// such.
+		{jsCtxDivOp, "x"},
+		{jsCtxDivOp, "x "},
+		{jsCtxDivOp, "x\t"},
+		{jsCtxDivOp, "x\n"},
+		{jsCtxDivOp, "x\u2028"},
+		{jsCtxDivOp, "preturn"},
+		// Numbers precede div ops.
+		{jsCtxDivOp, "0"},
+		// Dots that are part of a number are div preceders.
+		{jsCtxDivOp, "0."},
+	}
+
+	for _, test := range tests {
+		if nextJSCtx([]byte(test.s), jsCtxRegexp) != test.jsCtx {
+			t.Errorf("want %s got %q", test.jsCtx, test.s)
+		}
+		if nextJSCtx([]byte(test.s), jsCtxDivOp) != test.jsCtx {
+			t.Errorf("want %s got %q", test.jsCtx, test.s)
+		}
+	}
+
+	if nextJSCtx([]byte("   "), jsCtxRegexp) != jsCtxRegexp {
+		t.Error("Blank tokens")
+	}
+
+	if nextJSCtx([]byte("   "), jsCtxDivOp) != jsCtxDivOp {
+		t.Error("Blank tokens")
+	}
+}
+
+func TestJSValEscaper(t *testing.T) {
+	tests := []struct {
+		x  interface{}
+		js string
+	}{
+		{int(42), " 42 "},
+		{uint(42), " 42 "},
+		{int16(42), " 42 "},
+		{uint16(42), " 42 "},
+		{int32(-42), " -42 "},
+		{uint32(42), " 42 "},
+		{int16(-42), " -42 "},
+		{uint16(42), " 42 "},
+		{int64(-42), " -42 "},
+		{uint64(42), " 42 "},
+		{uint64(1) << 53, " 9007199254740992 "},
+		// ulp(1 << 53) > 1 so this loses precision in JS
+		// but it is still a representable integer literal.
+		{uint64(1)<<53 + 1, " 9007199254740993 "},
+		{float32(1.0), " 1 "},
+		{float32(-1.0), " -1 "},
+		{float32(0.5), " 0.5 "},
+		{float32(-0.5), " -0.5 "},
+		{float32(1.0) / float32(256), " 0.00390625 "},
+		{float32(0), " 0 "},
+		{math.Copysign(0, -1), " -0 "},
+		{float64(1.0), " 1 "},
+		{float64(-1.0), " -1 "},
+		{float64(0.5), " 0.5 "},
+		{float64(-0.5), " -0.5 "},
+		{float64(0), " 0 "},
+		{math.Copysign(0, -1), " -0 "},
+		{"", `""`},
+		{"foo", `"foo"`},
+		// Newlines.
+		{"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
+		// "\v" == "v" on IE 6 so use "\x0b" instead.
+		{"\t\x0b", `"\u0009\u000b"`},
+		{struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
+		{[]interface{}{}, "[]"},
+		{[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
+		{[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`},
+		{"<!--", `"\u003c!--"`},
+		{"-->", `"--\u003e"`},
+		{"<![CDATA[", `"\u003c![CDATA["`},
+		{"]]>", `"]]\u003e"`},
+		{"</script", `"\u003c/script"`},
+		{"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
+	}
+
+	for _, test := range tests {
+		if js := jsValEscaper(test.x); js != test.js {
+			t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js)
+		}
+		// Make sure that escaping corner cases are not broken
+		// by nesting.
+		a := []interface{}{test.x}
+		want := "[" + strings.TrimSpace(test.js) + "]"
+		if js := jsValEscaper(a); js != want {
+			t.Errorf("%+v: want\n\t%q\ngot\n\t%q", a, want, js)
+		}
+	}
+}
+
+func TestJSStrEscaper(t *testing.T) {
+	tests := []struct {
+		x   interface{}
+		esc string
+	}{
+		{"", ``},
+		{"foo", `foo`},
+		{"\u0000", `\0`},
+		{"\t", `\t`},
+		{"\n", `\n`},
+		{"\r", `\r`},
+		{"\u2028", `\u2028`},
+		{"\u2029", `\u2029`},
+		{"\\", `\\`},
+		{"\\n", `\\n`},
+		{"foo\r\nbar", `foo\r\nbar`},
+		// Preserve attribute boundaries.
+		{`"`, `\x22`},
+		{`'`, `\x27`},
+		// Allow embedding in HTML without further escaping.
+		{`&`, `\x26amp;`},
+		// Prevent breaking out of text node and element boundaries.
+		{"</script>", `\x3c\/script\x3e`},
+		{"<![CDATA[", `\x3c![CDATA[`},
+		{"]]>", `]]\x3e`},
+		// http://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span
+		//   "The text in style, script, title, and textarea elements
+		//   must not have an escaping text span start that is not
+		//   followed by an escaping text span end."
+		// Furthermore, spoofing an escaping text span end could lead
+		// to different interpretation of a </script> sequence otherwise
+		// masked by the escaping text span, and spoofing a start could
+		// allow regular text content to be interpreted as script
+		// allowing script execution via a combination of a JS string
+		// injection followed by an HTML text injection.
+		{"<!--", `\x3c!--`},
+		{"-->", `--\x3e`},
+		// From http://code.google.com/p/doctype/wiki/ArticleUtf7
+		{"+ADw-script+AD4-alert(1)+ADw-/script+AD4-",
+			`\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`,
+		},
+		// Invalid UTF-8 sequence
+		{"foo\xA0bar", "foo\xA0bar"},
+		// Invalid unicode scalar value.
+		{"foo\xed\xa0\x80bar", "foo\xed\xa0\x80bar"},
+	}
+
+	for _, test := range tests {
+		esc := jsStrEscaper(test.x)
+		if esc != test.esc {
+			t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
+		}
+	}
+}
+
+func TestJSRegexpEscaper(t *testing.T) {
+	tests := []struct {
+		x   interface{}
+		esc string
+	}{
+		{"", `(?:)`},
+		{"foo", `foo`},
+		{"\u0000", `\0`},
+		{"\t", `\t`},
+		{"\n", `\n`},
+		{"\r", `\r`},
+		{"\u2028", `\u2028`},
+		{"\u2029", `\u2029`},
+		{"\\", `\\`},
+		{"\\n", `\\n`},
+		{"foo\r\nbar", `foo\r\nbar`},
+		// Preserve attribute boundaries.
+		{`"`, `\x22`},
+		{`'`, `\x27`},
+		// Allow embedding in HTML without further escaping.
+		{`&`, `\x26amp;`},
+		// Prevent breaking out of text node and element boundaries.
+		{"</script>", `\x3c\/script\x3e`},
+		{"<![CDATA[", `\x3c!\[CDATA\[`},
+		{"]]>", `\]\]\x3e`},
+		// Escaping text spans.
+		{"<!--", `\x3c!\-\-`},
+		{"-->", `\-\-\x3e`},
+		{"*", `\*`},
+		{"+", `\x2b`},
+		{"?", `\?`},
+		{"[](){}", `\[\]\(\)\{\}`},
+		{"$foo|x.y", `\$foo\|x\.y`},
+		{"x^y", `x\^y`},
+	}
+
+	for _, test := range tests {
+		esc := jsRegexpEscaper(test.x)
+		if esc != test.esc {
+			t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
+		}
+	}
+}
+
+func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
+	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		"`abcdefghijklmno" +
+		"pqrstuvwxyz{|}~\x7f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+	tests := []struct {
+		name    string
+		escaper func(...interface{}) string
+		escaped string
+	}{
+		{
+			"jsStrEscaper",
+			jsStrEscaper,
+			"\\0\x01\x02\x03\x04\x05\x06\x07" +
+				"\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
+				"\x10\x11\x12\x13\x14\x15\x16\x17" +
+				"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+				` !\x22#$%\x26\x27()*\x2b,-.\/` +
+				`0123456789:;\x3c=\x3e?` +
+				`@ABCDEFGHIJKLMNO` +
+				`PQRSTUVWXYZ[\\]^_` +
+				"`abcdefghijklmno" +
+				"pqrstuvwxyz{|}~\x7f" +
+				"\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
+		},
+		{
+			"jsRegexpEscaper",
+			jsRegexpEscaper,
+			"\\0\x01\x02\x03\x04\x05\x06\x07" +
+				"\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
+				"\x10\x11\x12\x13\x14\x15\x16\x17" +
+				"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+				` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` +
+				`0123456789:;\x3c=\x3e\?` +
+				`@ABCDEFGHIJKLMNO` +
+				`PQRSTUVWXYZ\[\\\]\^_` +
+				"`abcdefghijklmno" +
+				`pqrstuvwxyz\{\|\}~` + "\u007f" +
+				"\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
+		},
+	}
+
+	for _, test := range tests {
+		if s := test.escaper(input); s != test.escaped {
+			t.Errorf("%s once: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+			continue
+		}
+
+		// Escape it rune by rune to make sure that any
+		// fast-path checking does not break escaping.
+		var buf bytes.Buffer
+		for _, c := range input {
+			buf.WriteString(test.escaper(string(c)))
+		}
+
+		if s := buf.String(); s != test.escaped {
+			t.Errorf("%s rune-wise: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+			continue
+		}
+	}
+}
+
+func BenchmarkJSValEscaperWithNum(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsValEscaper(3.141592654)
+	}
+}
+
+func BenchmarkJSValEscaperWithStr(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsValEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkJSValEscaperWithStrNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsValEscaper("The quick, brown fox jumps over the lazy dog")
+	}
+}
+
+func BenchmarkJSValEscaperWithObj(b *testing.B) {
+	o := struct {
+		S string
+		N int
+	}{
+		"The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>\u2028",
+		42,
+	}
+	for i := 0; i < b.N; i++ {
+		jsValEscaper(o)
+	}
+}
+
+func BenchmarkJSValEscaperWithObjNoSpecials(b *testing.B) {
+	o := struct {
+		S string
+		N int
+	}{
+		"The quick, brown fox jumps over the lazy dog",
+		42,
+	}
+	for i := 0; i < b.N; i++ {
+		jsValEscaper(o)
+	}
+}
+
+func BenchmarkJSStrEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsStrEscaper("The quick, brown fox jumps over the lazy dog.")
+	}
+}
+
+func BenchmarkJSStrEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsStrEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
+
+func BenchmarkJSRegexpEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsRegexpEscaper("The quick, brown fox jumps over the lazy dog")
+	}
+}
+
+func BenchmarkJSRegexpEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		jsRegexpEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+	}
+}
diff --git a/src/pkg/html/template/template.go b/src/pkg/html/template/template.go
new file mode 100644
index 0000000..9ffe414
--- /dev/null
+++ b/src/pkg/html/template/template.go
@@ -0,0 +1,280 @@
+// Copyright 2011 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 template
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"path/filepath"
+	"sync"
+	"text/template"
+	"text/template/parse"
+)
+
+// Template is a specialized template.Template that produces a safe HTML
+// document fragment.
+type Template struct {
+	escaped bool
+	// We could embed the text/template field, but it's safer not to because
+	// we need to keep our version of the name space and the underlying
+	// template's in sync.
+	text       *template.Template
+	*nameSpace // common to all associated templates
+}
+
+// nameSpace is the data structure shared by all templates in an association.
+type nameSpace struct {
+	mu  sync.Mutex
+	set map[string]*Template
+}
+
+// Execute applies a parsed template to the specified data object,
+// writing the output to wr.
+func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
+	t.nameSpace.mu.Lock()
+	if !t.escaped {
+		if err = escapeTemplates(t, t.Name()); err != nil {
+			t.escaped = true
+		}
+	}
+	t.nameSpace.mu.Unlock()
+	if err != nil {
+		return
+	}
+	return t.text.Execute(wr, data)
+}
+
+// ExecuteTemplate applies the template associated with t that has the given
+// name to the specified data object and writes the output to wr.
+func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
+	tmpl, err := t.lookupAndEscapeTemplate(wr, name)
+	if err != nil {
+		return err
+	}
+	return tmpl.text.Execute(wr, data)
+}
+
+// lookupAndEscapeTemplate guarantees that the template with the given name
+// is escaped, or returns an error if it cannot be. It returns the named
+// template.
+func (t *Template) lookupAndEscapeTemplate(wr io.Writer, name string) (tmpl *Template, err error) {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	tmpl = t.set[name]
+	if (tmpl == nil) != (t.text.Lookup(name) == nil) {
+		panic("html/template internal error: template escaping out of sync")
+	}
+	if tmpl != nil && !tmpl.escaped {
+		err = escapeTemplates(tmpl, name)
+	}
+	return tmpl, err
+}
+
+// Parse parses a string into a template. Nested template definitions
+// will be associated with the top-level template t. Parse may be
+// called multiple times to parse definitions of templates to associate
+// with t. It is an error if a resulting template is non-empty (contains
+// content other than template definitions) and would replace a
+// non-empty template with the same name.  (In multiple calls to Parse
+// with the same receiver template, only one call can contain text
+// other than space, comments, and template definitions.)
+func (t *Template) Parse(src string) (*Template, error) {
+	t.nameSpace.mu.Lock()
+	t.escaped = false
+	t.nameSpace.mu.Unlock()
+	ret, err := t.text.Parse(src)
+	if err != nil {
+		return nil, err
+	}
+	// In general, all the named templates might have changed underfoot.
+	// Regardless, some new ones may have been defined.
+	// The template.Template set has been updated; update ours.
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	for _, v := range ret.Templates() {
+		name := v.Name()
+		tmpl := t.set[name]
+		if tmpl == nil {
+			tmpl = t.new(name)
+		}
+		tmpl.escaped = false
+		tmpl.text = v
+	}
+	return t, nil
+}
+
+// AddParseTree is unimplemented.
+func (t *Template) AddParseTree(name string, tree *parse.Tree) error {
+	return fmt.Errorf("html/template: AddParseTree unimplemented")
+}
+
+// Clone is unimplemented.
+func (t *Template) Clone(name string) error {
+	return fmt.Errorf("html/template: Clone unimplemented")
+}
+
+// New allocates a new HTML template with the given name.
+func New(name string) *Template {
+	tmpl := &Template{
+		false,
+		template.New(name),
+		&nameSpace{
+			set: make(map[string]*Template),
+		},
+	}
+	tmpl.set[name] = tmpl
+	return tmpl
+}
+
+// New allocates a new HTML template associated with the given one
+// and with the same delimiters. The association, which is transitive,
+// allows one template to invoke another with a {{template}} action.
+func (t *Template) New(name string) *Template {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	return t.new(name)
+}
+
+// new is the implementation of New, without the lock.
+func (t *Template) new(name string) *Template {
+	tmpl := &Template{
+		false,
+		t.text.New(name),
+		t.nameSpace,
+	}
+	tmpl.set[name] = tmpl
+	return tmpl
+}
+
+// Name returns the name of the template.
+func (t *Template) Name() string {
+	return t.text.Name()
+}
+
+// FuncMap is the type of the map defining the mapping from names to
+// functions. Each function must have either a single return value, or two
+// return values of which the second has type error. In that case, if the
+// second (error) argument evaluates to non-nil during execution, execution
+// terminates and Execute returns that error. FuncMap has the same base type
+// as template.FuncMap, copied here so clients need not import "text/template".
+type FuncMap map[string]interface{}
+
+// Funcs adds the elements of the argument map to the template's function map.
+// It panics if a value in the map is not a function with appropriate return
+// type. However, it is legal to overwrite elements of the map. The return
+// value is the template, so calls can be chained.
+func (t *Template) Funcs(funcMap FuncMap) *Template {
+	t.text.Funcs(template.FuncMap(funcMap))
+	return t
+}
+
+// Delims sets the action delimiters to the specified strings, to be used in
+// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
+// definitions will inherit the settings. An empty delimiter stands for the
+// corresponding default: {{ or }}.
+// The return value is the template, so calls can be chained.
+func (t *Template) Delims(left, right string) *Template {
+	t.text.Delims(left, right)
+	return t
+}
+
+// Lookup returns the template with the given name that is associated with t,
+// or nil if there is no such template.
+func (t *Template) Lookup(name string) *Template {
+	t.nameSpace.mu.Lock()
+	defer t.nameSpace.mu.Unlock()
+	return t.set[name]
+}
+
+// Must panics if err is non-nil in the same way as template.Must.
+func Must(t *Template, err error) *Template {
+	if err != nil {
+		panic(err)
+	}
+	return t
+}
+
+// ParseFiles creates a new Template and parses the template definitions from
+// the named files. The returned template's name will have the (base) name and
+// (parsed) contents of the first file. There must be at least one file.
+// If an error occurs, parsing stops and the returned *Template is nil.
+func ParseFiles(filenames ...string) (*Template, error) {
+	return parseFiles(nil, filenames...)
+}
+
+// ParseFiles parses the named files and associates the resulting templates with
+// t. If an error occurs, parsing stops and the returned template is nil;
+// otherwise it is t. There must be at least one file.
+func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
+	return parseFiles(t, filenames...)
+}
+
+// parseFiles is the helper for the method and function. If the argument
+// template is nil, it is created from the first file.
+func parseFiles(t *Template, filenames ...string) (*Template, error) {
+	if len(filenames) == 0 {
+		// Not really a problem, but be consistent.
+		return nil, fmt.Errorf("template: no files named in call to ParseFiles")
+	}
+	for _, filename := range filenames {
+		b, err := ioutil.ReadFile(filename)
+		if err != nil {
+			return nil, err
+		}
+		s := string(b)
+		name := filepath.Base(filename)
+		// First template becomes return value if not already defined,
+		// and we use that one for subsequent New calls to associate
+		// all the templates together. Also, if this file has the same name
+		// as t, this file becomes the contents of t, so
+		//  t, err := New(name).Funcs(xxx).ParseFiles(name)
+		// works. Otherwise we create a new template associated with t.
+		var tmpl *Template
+		if t == nil {
+			t = New(name)
+		}
+		if name == t.Name() {
+			tmpl = t
+		} else {
+			tmpl = t.New(name)
+		}
+		_, err = tmpl.Parse(s)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return t, nil
+}
+
+// ParseGlob creates a new Template and parses the template definitions from the
+// files identified by the pattern, which must match at least one file. The
+// returned template will have the (base) name and (parsed) contents of the
+// first file matched by the pattern. ParseGlob is equivalent to calling
+// ParseFiles with the list of files matched by the pattern.
+func ParseGlob(pattern string) (*Template, error) {
+	return parseGlob(nil, pattern)
+}
+
+// ParseGlob parses the template definitions in the files identified by the
+// pattern and associates the resulting templates with t. The pattern is
+// processed by filepath.Glob and must match at least one file. ParseGlob is
+// equivalent to calling t.ParseFiles with the list of files matched by the
+// pattern.
+func (t *Template) ParseGlob(pattern string) (*Template, error) {
+	return parseGlob(t, pattern)
+}
+
+// parseGlob is the implementation of the function and method ParseGlob.
+func parseGlob(t *Template, pattern string) (*Template, error) {
+	filenames, err := filepath.Glob(pattern)
+	if err != nil {
+		return nil, err
+	}
+	if len(filenames) == 0 {
+		return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
+	}
+	return parseFiles(t, filenames...)
+}
diff --git a/src/pkg/html/template/transition.go b/src/pkg/html/template/transition.go
new file mode 100644
index 0000000..96a4f66
--- /dev/null
+++ b/src/pkg/html/template/transition.go
@@ -0,0 +1,553 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"strings"
+)
+
+// transitionFunc is the array of context transition functions for text nodes.
+// A transition function takes a context and template text input, and returns
+// the updated context and the number of bytes consumed from the front of the
+// input.
+var transitionFunc = [...]func(context, []byte) (context, int){
+	stateText:        tText,
+	stateTag:         tTag,
+	stateAttrName:    tAttrName,
+	stateAfterName:   tAfterName,
+	stateBeforeValue: tBeforeValue,
+	stateHTMLCmt:     tHTMLCmt,
+	stateRCDATA:      tSpecialTagEnd,
+	stateAttr:        tAttr,
+	stateURL:         tURL,
+	stateJS:          tJS,
+	stateJSDqStr:     tJSDelimited,
+	stateJSSqStr:     tJSDelimited,
+	stateJSRegexp:    tJSDelimited,
+	stateJSBlockCmt:  tBlockCmt,
+	stateJSLineCmt:   tLineCmt,
+	stateCSS:         tCSS,
+	stateCSSDqStr:    tCSSStr,
+	stateCSSSqStr:    tCSSStr,
+	stateCSSDqURL:    tCSSStr,
+	stateCSSSqURL:    tCSSStr,
+	stateCSSURL:      tCSSStr,
+	stateCSSBlockCmt: tBlockCmt,
+	stateCSSLineCmt:  tLineCmt,
+	stateError:       tError,
+}
+
+var commentStart = []byte("<!--")
+var commentEnd = []byte("-->")
+
+// tText is the context transition function for the text state.
+func tText(c context, s []byte) (context, int) {
+	k := 0
+	for {
+		i := k + bytes.IndexByte(s[k:], '<')
+		if i < k || i+1 == len(s) {
+			return c, len(s)
+		} else if i+4 <= len(s) && bytes.Equal(commentStart, s[i:i+4]) {
+			return context{state: stateHTMLCmt}, i + 4
+		}
+		i++
+		end := false
+		if s[i] == '/' {
+			if i+1 == len(s) {
+				return c, len(s)
+			}
+			end, i = true, i+1
+		}
+		j, e := eatTagName(s, i)
+		if j != i {
+			if end {
+				e = elementNone
+			}
+			// We've found an HTML tag.
+			return context{state: stateTag, element: e}, j
+		}
+		k = j
+	}
+	panic("unreachable")
+}
+
+var elementContentType = [...]state{
+	elementNone:     stateText,
+	elementScript:   stateJS,
+	elementStyle:    stateCSS,
+	elementTextarea: stateRCDATA,
+	elementTitle:    stateRCDATA,
+}
+
+// tTag is the context transition function for the tag state.
+func tTag(c context, s []byte) (context, int) {
+	// Find the attribute name.
+	i := eatWhiteSpace(s, 0)
+	if i == len(s) {
+		return c, len(s)
+	}
+	if s[i] == '>' {
+		return context{
+			state:   elementContentType[c.element],
+			element: c.element,
+		}, i + 1
+	}
+	j, err := eatAttrName(s, i)
+	if err != nil {
+		return context{state: stateError, err: err}, len(s)
+	}
+	state, attr := stateTag, attrNone
+	if i == j {
+		return context{
+			state: stateError,
+			err:   errorf(ErrBadHTML, 0, "expected space, attr name, or end of tag, but got %q", s[i:]),
+		}, len(s)
+	}
+	switch attrType(string(s[i:j])) {
+	case contentTypeURL:
+		attr = attrURL
+	case contentTypeCSS:
+		attr = attrStyle
+	case contentTypeJS:
+		attr = attrScript
+	}
+	if j == len(s) {
+		state = stateAttrName
+	} else {
+		state = stateAfterName
+	}
+	return context{state: state, element: c.element, attr: attr}, j
+}
+
+// tAttrName is the context transition function for stateAttrName.
+func tAttrName(c context, s []byte) (context, int) {
+	i, err := eatAttrName(s, 0)
+	if err != nil {
+		return context{state: stateError, err: err}, len(s)
+	} else if i != len(s) {
+		c.state = stateAfterName
+	}
+	return c, i
+}
+
+// tAfterName is the context transition function for stateAfterName.
+func tAfterName(c context, s []byte) (context, int) {
+	// Look for the start of the value.
+	i := eatWhiteSpace(s, 0)
+	if i == len(s) {
+		return c, len(s)
+	} else if s[i] != '=' {
+		// Occurs due to tag ending '>', and valueless attribute.
+		c.state = stateTag
+		return c, i
+	}
+	c.state = stateBeforeValue
+	// Consume the "=".
+	return c, i + 1
+}
+
+var attrStartStates = [...]state{
+	attrNone:   stateAttr,
+	attrScript: stateJS,
+	attrStyle:  stateCSS,
+	attrURL:    stateURL,
+}
+
+// tBeforeValue is the context transition function for stateBeforeValue.
+func tBeforeValue(c context, s []byte) (context, int) {
+	i := eatWhiteSpace(s, 0)
+	if i == len(s) {
+		return c, len(s)
+	}
+	// Find the attribute delimiter.
+	delim := delimSpaceOrTagEnd
+	switch s[i] {
+	case '\'':
+		delim, i = delimSingleQuote, i+1
+	case '"':
+		delim, i = delimDoubleQuote, i+1
+	}
+	c.state, c.delim, c.attr = attrStartStates[c.attr], delim, attrNone
+	return c, i
+}
+
+// tHTMLCmt is the context transition function for stateHTMLCmt.
+func tHTMLCmt(c context, s []byte) (context, int) {
+	if i := bytes.Index(s, commentEnd); i != -1 {
+		return context{}, i + 3
+	}
+	return c, len(s)
+}
+
+// specialTagEndMarkers maps element types to the character sequence that
+// case-insensitively signals the end of the special tag body.
+var specialTagEndMarkers = [...]string{
+	elementScript:   "</script",
+	elementStyle:    "</style",
+	elementTextarea: "</textarea",
+	elementTitle:    "</title",
+}
+
+// tSpecialTagEnd is the context transition function for raw text and RCDATA
+// element states.
+func tSpecialTagEnd(c context, s []byte) (context, int) {
+	if c.element != elementNone {
+		if i := strings.Index(strings.ToLower(string(s)), specialTagEndMarkers[c.element]); i != -1 {
+			return context{}, i
+		}
+	}
+	return c, len(s)
+}
+
+// tAttr is the context transition function for the attribute state.
+func tAttr(c context, s []byte) (context, int) {
+	return c, len(s)
+}
+
+// tURL is the context transition function for the URL state.
+func tURL(c context, s []byte) (context, int) {
+	if bytes.IndexAny(s, "#?") >= 0 {
+		c.urlPart = urlPartQueryOrFrag
+	} else if len(s) != eatWhiteSpace(s, 0) && c.urlPart == urlPartNone {
+		// HTML5 uses "Valid URL potentially surrounded by spaces" for
+		// attrs: http://www.w3.org/TR/html5/index.html#attributes-1
+		c.urlPart = urlPartPreQuery
+	}
+	return c, len(s)
+}
+
+// tJS is the context transition function for the JS state.
+func tJS(c context, s []byte) (context, int) {
+	i := bytes.IndexAny(s, `"'/`)
+	if i == -1 {
+		// Entire input is non string, comment, regexp tokens.
+		c.jsCtx = nextJSCtx(s, c.jsCtx)
+		return c, len(s)
+	}
+	c.jsCtx = nextJSCtx(s[:i], c.jsCtx)
+	switch s[i] {
+	case '"':
+		c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp
+	case '\'':
+		c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp
+	case '/':
+		switch {
+		case i+1 < len(s) && s[i+1] == '/':
+			c.state, i = stateJSLineCmt, i+1
+		case i+1 < len(s) && s[i+1] == '*':
+			c.state, i = stateJSBlockCmt, i+1
+		case c.jsCtx == jsCtxRegexp:
+			c.state = stateJSRegexp
+		case c.jsCtx == jsCtxDivOp:
+			c.jsCtx = jsCtxRegexp
+		default:
+			return context{
+				state: stateError,
+				err:   errorf(ErrSlashAmbig, 0, "'/' could start a division or regexp: %.32q", s[i:]),
+			}, len(s)
+		}
+	default:
+		panic("unreachable")
+	}
+	return c, i + 1
+}
+
+// tJSDelimited is the context transition function for the JS string and regexp
+// states.
+func tJSDelimited(c context, s []byte) (context, int) {
+	specials := `\"`
+	switch c.state {
+	case stateJSSqStr:
+		specials = `\'`
+	case stateJSRegexp:
+		specials = `\/[]`
+	}
+
+	k, inCharset := 0, false
+	for {
+		i := k + bytes.IndexAny(s[k:], specials)
+		if i < k {
+			break
+		}
+		switch s[i] {
+		case '\\':
+			i++
+			if i == len(s) {
+				return context{
+					state: stateError,
+					err:   errorf(ErrPartialEscape, 0, "unfinished escape sequence in JS string: %q", s),
+				}, len(s)
+			}
+		case '[':
+			inCharset = true
+		case ']':
+			inCharset = false
+		default:
+			// end delimiter
+			if !inCharset {
+				c.state, c.jsCtx = stateJS, jsCtxDivOp
+				return c, i + 1
+			}
+		}
+		k = i + 1
+	}
+
+	if inCharset {
+		// This can be fixed by making context richer if interpolation
+		// into charsets is desired.
+		return context{
+			state: stateError,
+			err:   errorf(ErrPartialCharset, 0, "unfinished JS regexp charset: %q", s),
+		}, len(s)
+	}
+
+	return c, len(s)
+}
+
+var blockCommentEnd = []byte("*/")
+
+// tBlockCmt is the context transition function for /*comment*/ states.
+func tBlockCmt(c context, s []byte) (context, int) {
+	i := bytes.Index(s, blockCommentEnd)
+	if i == -1 {
+		return c, len(s)
+	}
+	switch c.state {
+	case stateJSBlockCmt:
+		c.state = stateJS
+	case stateCSSBlockCmt:
+		c.state = stateCSS
+	default:
+		panic(c.state.String())
+	}
+	return c, i + 2
+}
+
+// tLineCmt is the context transition function for //comment states.
+func tLineCmt(c context, s []byte) (context, int) {
+	var lineTerminators string
+	var endState state
+	switch c.state {
+	case stateJSLineCmt:
+		lineTerminators, endState = "\n\r\u2028\u2029", stateJS
+	case stateCSSLineCmt:
+		lineTerminators, endState = "\n\f\r", stateCSS
+		// Line comments are not part of any published CSS standard but
+		// are supported by the 4 major browsers.
+		// This defines line comments as
+		//     LINECOMMENT ::= "//" [^\n\f\d]*
+		// since http://www.w3.org/TR/css3-syntax/#SUBTOK-nl defines
+		// newlines:
+		//     nl ::= #xA | #xD #xA | #xD | #xC
+	default:
+		panic(c.state.String())
+	}
+
+	i := bytes.IndexAny(s, lineTerminators)
+	if i == -1 {
+		return c, len(s)
+	}
+	c.state = endState
+	// Per section 7.4 of EcmaScript 5 : http://es5.github.com/#x7.4
+	// "However, the LineTerminator at the end of the line is not
+	// considered to be part of the single-line comment; it is
+	// recognized separately by the lexical grammar and becomes part
+	// of the stream of input elements for the syntactic grammar."
+	return c, i
+}
+
+// tCSS is the context transition function for the CSS state.
+func tCSS(c context, s []byte) (context, int) {
+	// CSS quoted strings are almost never used except for:
+	// (1) URLs as in background: "/foo.png"
+	// (2) Multiword font-names as in font-family: "Times New Roman"
+	// (3) List separators in content values as in inline-lists:
+	//    <style>
+	//    ul.inlineList { list-style: none; padding:0 }
+	//    ul.inlineList > li { display: inline }
+	//    ul.inlineList > li:before { content: ", " }
+	//    ul.inlineList > li:first-child:before { content: "" }
+	//    </style>
+	//    <ul class=inlineList><li>One<li>Two<li>Three</ul>
+	// (4) Attribute value selectors as in a[href="http://example.com/"]
+	//
+	// We conservatively treat all strings as URLs, but make some
+	// allowances to avoid confusion.
+	//
+	// In (1), our conservative assumption is justified.
+	// In (2), valid font names do not contain ':', '?', or '#', so our
+	// conservative assumption is fine since we will never transition past
+	// urlPartPreQuery.
+	// In (3), our protocol heuristic should not be tripped, and there
+	// should not be non-space content after a '?' or '#', so as long as
+	// we only %-encode RFC 3986 reserved characters we are ok.
+	// In (4), we should URL escape for URL attributes, and for others we
+	// have the attribute name available if our conservative assumption
+	// proves problematic for real code.
+
+	k := 0
+	for {
+		i := k + bytes.IndexAny(s[k:], `("'/`)
+		if i < k {
+			return c, len(s)
+		}
+		switch s[i] {
+		case '(':
+			// Look for url to the left.
+			p := bytes.TrimRight(s[:i], "\t\n\f\r ")
+			if endsWithCSSKeyword(p, "url") {
+				j := len(s) - len(bytes.TrimLeft(s[i+1:], "\t\n\f\r "))
+				switch {
+				case j != len(s) && s[j] == '"':
+					c.state, j = stateCSSDqURL, j+1
+				case j != len(s) && s[j] == '\'':
+					c.state, j = stateCSSSqURL, j+1
+				default:
+					c.state = stateCSSURL
+				}
+				return c, j
+			}
+		case '/':
+			if i+1 < len(s) {
+				switch s[i+1] {
+				case '/':
+					c.state = stateCSSLineCmt
+					return c, i + 2
+				case '*':
+					c.state = stateCSSBlockCmt
+					return c, i + 2
+				}
+			}
+		case '"':
+			c.state = stateCSSDqStr
+			return c, i + 1
+		case '\'':
+			c.state = stateCSSSqStr
+			return c, i + 1
+		}
+		k = i + 1
+	}
+	panic("unreachable")
+}
+
+// tCSSStr is the context transition function for the CSS string and URL states.
+func tCSSStr(c context, s []byte) (context, int) {
+	var endAndEsc string
+	switch c.state {
+	case stateCSSDqStr, stateCSSDqURL:
+		endAndEsc = `\"`
+	case stateCSSSqStr, stateCSSSqURL:
+		endAndEsc = `\'`
+	case stateCSSURL:
+		// Unquoted URLs end with a newline or close parenthesis.
+		// The below includes the wc (whitespace character) and nl.
+		endAndEsc = "\\\t\n\f\r )"
+	default:
+		panic(c.state.String())
+	}
+
+	k := 0
+	for {
+		i := k + bytes.IndexAny(s[k:], endAndEsc)
+		if i < k {
+			c, nread := tURL(c, decodeCSS(s[k:]))
+			return c, k + nread
+		}
+		if s[i] == '\\' {
+			i++
+			if i == len(s) {
+				return context{
+					state: stateError,
+					err:   errorf(ErrPartialEscape, 0, "unfinished escape sequence in CSS string: %q", s),
+				}, len(s)
+			}
+		} else {
+			c.state = stateCSS
+			return c, i + 1
+		}
+		c, _ = tURL(c, decodeCSS(s[:i+1]))
+		k = i + 1
+	}
+	panic("unreachable")
+}
+
+// tError is the context transition function for the error state.
+func tError(c context, s []byte) (context, int) {
+	return c, len(s)
+}
+
+// eatAttrName returns the largest j such that s[i:j] is an attribute name.
+// It returns an error if s[i:] does not look like it begins with an
+// attribute name, such as encountering a quote mark without a preceding
+// equals sign.
+func eatAttrName(s []byte, i int) (int, *Error) {
+	for j := i; j < len(s); j++ {
+		switch s[j] {
+		case ' ', '\t', '\n', '\f', '\r', '=', '>':
+			return j, nil
+		case '\'', '"', '<':
+			// These result in a parse warning in HTML5 and are
+			// indicative of serious problems if seen in an attr
+			// name in a template.
+			return -1, errorf(ErrBadHTML, 0, "%q in attribute name: %.32q", s[j:j+1], s)
+		default:
+			// No-op.
+		}
+	}
+	return len(s), nil
+}
+
+var elementNameMap = map[string]element{
+	"script":   elementScript,
+	"style":    elementStyle,
+	"textarea": elementTextarea,
+	"title":    elementTitle,
+}
+
+// asciiAlpha returns whether c is an ASCII letter.
+func asciiAlpha(c byte) bool {
+	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
+}
+
+// asciiAlphaNum returns whether c is an ASCII letter or digit.
+func asciiAlphaNum(c byte) bool {
+	return asciiAlpha(c) || '0' <= c && c <= '9'
+}
+
+// eatTagName returns the largest j such that s[i:j] is a tag name and the tag type.
+func eatTagName(s []byte, i int) (int, element) {
+	if i == len(s) || !asciiAlpha(s[i]) {
+		return i, elementNone
+	}
+	j := i + 1
+	for j < len(s) {
+		x := s[j]
+		if asciiAlphaNum(x) {
+			j++
+			continue
+		}
+		// Allow "x-y" or "x:y" but not "x-", "-y", or "x--y".
+		if (x == ':' || x == '-') && j+1 < len(s) && asciiAlphaNum(s[j+1]) {
+			j += 2
+			continue
+		}
+		break
+	}
+	return j, elementNameMap[strings.ToLower(string(s[i:j]))]
+}
+
+// eatWhiteSpace returns the largest j such that s[i:j] is white space.
+func eatWhiteSpace(s []byte, i int) int {
+	for j := i; j < len(s); j++ {
+		switch s[j] {
+		case ' ', '\t', '\n', '\f', '\r':
+			// No-op.
+		default:
+			return j
+		}
+	}
+	return len(s)
+}
diff --git a/src/pkg/html/template/url.go b/src/pkg/html/template/url.go
new file mode 100644
index 0000000..454c791
--- /dev/null
+++ b/src/pkg/html/template/url.go
@@ -0,0 +1,105 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+)
+
+// urlFilter returns its input unless it contains an unsafe protocol in which
+// case it defangs the entire URL.
+func urlFilter(args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeURL {
+		return s
+	}
+	if i := strings.IndexRune(s, ':'); i >= 0 && strings.IndexRune(s[:i], '/') < 0 {
+		protocol := strings.ToLower(s[:i])
+		if protocol != "http" && protocol != "https" && protocol != "mailto" {
+			return "#" + filterFailsafe
+		}
+	}
+	return s
+}
+
+// urlEscaper produces an output that can be embedded in a URL query.
+// The output can be embedded in an HTML attribute without further escaping.
+func urlEscaper(args ...interface{}) string {
+	return urlProcessor(false, args...)
+}
+
+// urlEscaper normalizes URL content so it can be embedded in a quote-delimited
+// string or parenthesis delimited url(...).
+// The normalizer does not encode all HTML specials. Specifically, it does not
+// encode '&' so correct embedding in an HTML attribute requires escaping of
+// '&' to '&'.
+func urlNormalizer(args ...interface{}) string {
+	return urlProcessor(true, args...)
+}
+
+// urlProcessor normalizes (when norm is true) or escapes its input to produce
+// a valid hierarchical or opaque URL part.
+func urlProcessor(norm bool, args ...interface{}) string {
+	s, t := stringify(args...)
+	if t == contentTypeURL {
+		norm = true
+	}
+	var b bytes.Buffer
+	written := 0
+	// The byte loop below assumes that all URLs use UTF-8 as the
+	// content-encoding. This is similar to the URI to IRI encoding scheme
+	// defined in section 3.1 of  RFC 3987, and behaves the same as the
+	// EcmaScript builtin encodeURIComponent.
+	// It should not cause any misencoding of URLs in pages with
+	// Content-type: text/html;charset=UTF-8.
+	for i, n := 0, len(s); i < n; i++ {
+		c := s[i]
+		switch c {
+		// Single quote and parens are sub-delims in RFC 3986, but we
+		// escape them so the output can be embedded in in single
+		// quoted attributes and unquoted CSS url(...) constructs.
+		// Single quotes are reserved in URLs, but are only used in
+		// the obsolete "mark" rule in an appendix in RFC 3986
+		// so can be safely encoded.
+		case '!', '#', '$', '&', '*', '+', ',', '/', ':', ';', '=', '?', '@', '[', ']':
+			if norm {
+				continue
+			}
+		// Unreserved according to RFC 3986 sec 2.3
+		// "For consistency, percent-encoded octets in the ranges of
+		// ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D),
+		// period (%2E), underscore (%5F), or tilde (%7E) should not be
+		// created by URI producers
+		case '-', '.', '_', '~':
+			continue
+		case '%':
+			// When normalizing do not re-encode valid escapes.
+			if norm && i+2 < len(s) && isHex(s[i+1]) && isHex(s[i+2]) {
+				continue
+			}
+		default:
+			// Unreserved according to RFC 3986 sec 2.3
+			if 'a' <= c && c <= 'z' {
+				continue
+			}
+			if 'A' <= c && c <= 'Z' {
+				continue
+			}
+			if '0' <= c && c <= '9' {
+				continue
+			}
+		}
+		b.WriteString(s[written:i])
+		fmt.Fprintf(&b, "%%%02x", c)
+		written = i + 1
+	}
+	if written == 0 {
+		return s
+	}
+	b.WriteString(s[written:])
+	return b.String()
+}
diff --git a/src/pkg/html/template/url_test.go b/src/pkg/html/template/url_test.go
new file mode 100644
index 0000000..5182e9d
--- /dev/null
+++ b/src/pkg/html/template/url_test.go
@@ -0,0 +1,112 @@
+// Copyright 2011 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 template
+
+import (
+	"testing"
+)
+
+func TestURLNormalizer(t *testing.T) {
+	tests := []struct {
+		url, want string
+	}{
+		{"", ""},
+		{
+			"http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
+			"http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
+		},
+		{" ", "%20"},
+		{"%7c", "%7c"},
+		{"%7C", "%7C"},
+		{"%2", "%252"},
+		{"%", "%25"},
+		{"%z", "%25z"},
+		{"/foo|bar/%5c\u1234", "/foo%7cbar/%5c%e1%88%b4"},
+	}
+	for _, test := range tests {
+		if got := urlNormalizer(test.url); test.want != got {
+			t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.url, test.want, got)
+		}
+		if test.want != urlNormalizer(test.want) {
+			t.Errorf("not idempotent: %q", test.want)
+		}
+	}
+}
+
+func TestURLFilters(t *testing.T) {
+	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+		` !"#$%&'()*+,-./` +
+		`0123456789:;<=>?` +
+		`@ABCDEFGHIJKLMNO` +
+		`PQRSTUVWXYZ[\]^_` +
+		"`abcdefghijklmno" +
+		"pqrstuvwxyz{|}~\x7f" +
+		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+	tests := []struct {
+		name    string
+		escaper func(...interface{}) string
+		escaped string
+	}{
+		{
+			"urlEscaper",
+			urlEscaper,
+			"%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
+				"%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
+				"%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f" +
+				"0123456789%3a%3b%3c%3d%3e%3f" +
+				"%40ABCDEFGHIJKLMNO" +
+				"PQRSTUVWXYZ%5b%5c%5d%5e_" +
+				"%60abcdefghijklmno" +
+				"pqrstuvwxyz%7b%7c%7d~%7f" +
+				"%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
+		},
+		{
+			"urlNormalizer",
+			urlNormalizer,
+			"%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
+				"%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
+				"%20!%22#$%25&%27%28%29*+,-./" +
+				"0123456789:;%3c=%3e?" +
+				"@ABCDEFGHIJKLMNO" +
+				"PQRSTUVWXYZ[%5c]%5e_" +
+				"%60abcdefghijklmno" +
+				"pqrstuvwxyz%7b%7c%7d~%7f" +
+				"%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
+		},
+	}
+
+	for _, test := range tests {
+		if s := test.escaper(input); s != test.escaped {
+			t.Errorf("%s: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+			continue
+		}
+	}
+}
+
+func BenchmarkURLEscaper(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		urlEscaper("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
+	}
+}
+
+func BenchmarkURLEscaperNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		urlEscaper("TheQuickBrownFoxJumpsOverTheLazyDog.")
+	}
+}
+
+func BenchmarkURLNormalizer(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		urlNormalizer("The quick brown fox jumps over the lazy dog.\n")
+	}
+}
+
+func BenchmarkURLNormalizerNoSpecials(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		urlNormalizer("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
+	}
+}
diff --git a/src/pkg/html/token.go b/src/pkg/html/token.go
deleted file mode 100644
index d266b3a..0000000
--- a/src/pkg/html/token.go
+++ /dev/null
@@ -1,575 +0,0 @@
-// Copyright 2010 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 html
-
-import (
-	"bytes"
-	"io"
-	"os"
-	"strconv"
-)
-
-// A TokenType is the type of a Token.
-type TokenType int
-
-const (
-	// ErrorToken means that an error occurred during tokenization.
-	ErrorToken TokenType = iota
-	// TextToken means a text node.
-	TextToken
-	// A StartTagToken looks like <a>.
-	StartTagToken
-	// An EndTagToken looks like </a>.
-	EndTagToken
-	// A SelfClosingTagToken tag looks like <br/>.
-	SelfClosingTagToken
-	// A CommentToken looks like <!--x-->.
-	CommentToken
-	// A DoctypeToken looks like <!DOCTYPE x>
-	DoctypeToken
-)
-
-// String returns a string representation of the TokenType.
-func (t TokenType) String() string {
-	switch t {
-	case ErrorToken:
-		return "Error"
-	case TextToken:
-		return "Text"
-	case StartTagToken:
-		return "StartTag"
-	case EndTagToken:
-		return "EndTag"
-	case SelfClosingTagToken:
-		return "SelfClosingTag"
-	case CommentToken:
-		return "Comment"
-	case DoctypeToken:
-		return "Doctype"
-	}
-	return "Invalid(" + strconv.Itoa(int(t)) + ")"
-}
-
-// An Attribute is an attribute key-value pair. Key is alphabetic (and hence
-// does not contain escapable characters like '&', '<' or '>'), and Val is
-// unescaped (it looks like "a<b" rather than "a<b").
-type Attribute struct {
-	Key, Val string
-}
-
-// A Token consists of a TokenType and some Data (tag name for start and end
-// tags, content for text, comments and doctypes). A tag Token may also contain
-// a slice of Attributes. Data is unescaped for all Tokens (it looks like "a<b"
-// rather than "a<b").
-type Token struct {
-	Type TokenType
-	Data string
-	Attr []Attribute
-}
-
-// tagString returns a string representation of a tag Token's Data and Attr.
-func (t Token) tagString() string {
-	if len(t.Attr) == 0 {
-		return t.Data
-	}
-	buf := bytes.NewBuffer(nil)
-	buf.WriteString(t.Data)
-	for _, a := range t.Attr {
-		buf.WriteByte(' ')
-		buf.WriteString(a.Key)
-		buf.WriteString(`="`)
-		escape(buf, a.Val)
-		buf.WriteByte('"')
-	}
-	return buf.String()
-}
-
-// String returns a string representation of the Token.
-func (t Token) String() string {
-	switch t.Type {
-	case ErrorToken:
-		return ""
-	case TextToken:
-		return EscapeString(t.Data)
-	case StartTagToken:
-		return "<" + t.tagString() + ">"
-	case EndTagToken:
-		return "</" + t.tagString() + ">"
-	case SelfClosingTagToken:
-		return "<" + t.tagString() + "/>"
-	case CommentToken:
-		return "<!--" + EscapeString(t.Data) + "-->"
-	case DoctypeToken:
-		return "<!DOCTYPE " + EscapeString(t.Data) + ">"
-	}
-	return "Invalid(" + strconv.Itoa(int(t.Type)) + ")"
-}
-
-// A Tokenizer returns a stream of HTML Tokens.
-type Tokenizer struct {
-	// If ReturnComments is set, Next returns comment tokens;
-	// otherwise it skips over comments (default).
-	ReturnComments bool
-
-	// r is the source of the HTML text.
-	r io.Reader
-	// tt is the TokenType of the most recently read token.
-	tt TokenType
-	// err is the first error encountered during tokenization. It is possible
-	// for tt != Error && err != nil to hold: this means that Next returned a
-	// valid token but the subsequent Next call will return an error token.
-	// For example, if the HTML text input was just "plain", then the first
-	// Next call would set z.err to os.EOF but return a TextToken, and all
-	// subsequent Next calls would return an ErrorToken.
-	// err is never reset. Once it becomes non-nil, it stays non-nil.
-	err os.Error
-	// buf[p0:p1] holds the raw data of the most recent token.
-	// buf[p1:] is buffered input that will yield future tokens.
-	p0, p1 int
-	buf    []byte
-}
-
-// Error returns the error associated with the most recent ErrorToken token.
-// This is typically os.EOF, meaning the end of tokenization.
-func (z *Tokenizer) Error() os.Error {
-	if z.tt != ErrorToken {
-		return nil
-	}
-	return z.err
-}
-
-// Raw returns the unmodified text of the current token. Calling Next, Token,
-// Text, TagName or TagAttr may change the contents of the returned slice.
-func (z *Tokenizer) Raw() []byte {
-	return z.buf[z.p0:z.p1]
-}
-
-// readByte returns the next byte from the input stream, doing a buffered read
-// from z.r into z.buf if necessary. z.buf[z.p0:z.p1] remains a contiguous byte
-// slice that holds all the bytes read so far for the current token.
-// It sets z.err if the underlying reader returns an error.
-// Pre-condition: z.err == nil.
-func (z *Tokenizer) readByte() byte {
-	if z.p1 >= len(z.buf) {
-		// Our buffer is exhausted and we have to read from z.r.
-		// We copy z.buf[z.p0:z.p1] to the beginning of z.buf. If the length
-		// z.p1 - z.p0 is more than half the capacity of z.buf, then we
-		// allocate a new buffer before the copy.
-		c := cap(z.buf)
-		d := z.p1 - z.p0
-		var buf1 []byte
-		if 2*d > c {
-			buf1 = make([]byte, d, 2*c)
-		} else {
-			buf1 = z.buf[:d]
-		}
-		copy(buf1, z.buf[z.p0:z.p1])
-		z.p0, z.p1, z.buf = 0, d, buf1[:d]
-		// Now that we have copied the live bytes to the start of the buffer,
-		// we read from z.r into the remainder.
-		n, err := z.r.Read(buf1[d:cap(buf1)])
-		if err != nil {
-			z.err = err
-			return 0
-		}
-		z.buf = buf1[:d+n]
-	}
-	x := z.buf[z.p1]
-	z.p1++
-	return x
-}
-
-// readTo keeps reading bytes until x is found or a read error occurs. If an
-// error does occur, z.err is set to that error.
-// Pre-condition: z.err == nil.
-func (z *Tokenizer) readTo(x uint8) {
-	for {
-		c := z.readByte()
-		if z.err != nil {
-			return
-		}
-		switch c {
-		case x:
-			return
-		case '\\':
-			z.readByte()
-			if z.err != nil {
-				return
-			}
-		}
-	}
-}
-
-// nextComment reads the next token starting with "<!--".
-// The opening "<!--" has already been consumed.
-// Pre-condition: z.tt == TextToken && z.err == nil && z.p0 + 4 <= z.p1.
-func (z *Tokenizer) nextComment() {
-	// <!--> is a valid comment.
-	for dashCount := 2; ; {
-		c := z.readByte()
-		if z.err != nil {
-			return
-		}
-		switch c {
-		case '-':
-			dashCount++
-		case '>':
-			if dashCount >= 2 {
-				z.tt = CommentToken
-				return
-			}
-			dashCount = 0
-		default:
-			dashCount = 0
-		}
-	}
-}
-
-// nextMarkupDeclaration reads the next token starting with "<!".
-// It might be a "<!--comment-->", a "<!DOCTYPE foo>", or "<!malformed text".
-// The opening "<!" has already been consumed.
-// Pre-condition: z.tt == TextToken && z.err == nil && z.p0 + 2 <= z.p1.
-func (z *Tokenizer) nextMarkupDeclaration() {
-	var c [2]byte
-	for i := 0; i < 2; i++ {
-		c[i] = z.readByte()
-		if z.err != nil {
-			return
-		}
-	}
-	if c[0] == '-' && c[1] == '-' {
-		z.nextComment()
-		return
-	}
-	z.p1 -= 2
-	const s = "DOCTYPE "
-	for i := 0; ; i++ {
-		c := z.readByte()
-		if z.err != nil {
-			return
-		}
-		// Capitalize c.
-		if 'a' <= c && c <= 'z' {
-			c = 'A' + (c - 'a')
-		}
-		if i < len(s) && c != s[i] {
-			z.nextText()
-			return
-		}
-		if c == '>' {
-			if i >= len(s) {
-				z.tt = DoctypeToken
-			}
-			return
-		}
-	}
-}
-
-// nextTag reads the next token starting with "<". It might be a "<startTag>",
-// an "</endTag>", a "<!markup declaration>", or "<malformed text".
-// The opening "<" has already been consumed.
-// Pre-condition: z.tt == TextToken && z.err == nil && z.p0 + 1 <= z.p1.
-func (z *Tokenizer) nextTag() {
-	c := z.readByte()
-	if z.err != nil {
-		return
-	}
-	switch {
-	case c == '/':
-		z.tt = EndTagToken
-	// Lower-cased characters are more common in tag names, so we check for them first.
-	case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
-		z.tt = StartTagToken
-	case c == '!':
-		z.nextMarkupDeclaration()
-		return
-	case c == '?':
-		z.tt, z.err = ErrorToken, os.NewError("html: TODO: implement XML processing instructions")
-		return
-	default:
-		z.tt, z.err = ErrorToken, os.NewError("html: TODO: handle malformed tags")
-		return
-	}
-	for {
-		c := z.readByte()
-		if z.err != nil {
-			return
-		}
-		switch c {
-		case '"', '\'':
-			z.readTo(c)
-			if z.err != nil {
-				return
-			}
-		case '>':
-			if z.buf[z.p1-2] == '/' && z.tt == StartTagToken {
-				z.tt = SelfClosingTagToken
-			}
-			return
-		}
-	}
-}
-
-// nextText reads all text up until an '<'.
-// Pre-condition: z.tt == TextToken && z.err == nil && z.p0 + 1 <= z.p1.
-func (z *Tokenizer) nextText() {
-	for {
-		c := z.readByte()
-		if z.err != nil {
-			return
-		}
-		if c == '<' {
-			z.p1--
-			return
-		}
-	}
-}
-
-// Next scans the next token and returns its type.
-func (z *Tokenizer) Next() TokenType {
-	for {
-		if z.err != nil {
-			z.tt = ErrorToken
-			return z.tt
-		}
-		z.p0 = z.p1
-		c := z.readByte()
-		if z.err != nil {
-			z.tt = ErrorToken
-			return z.tt
-		}
-		// We assume that the next token is text unless proven otherwise.
-		z.tt = TextToken
-		if c != '<' {
-			z.nextText()
-		} else {
-			z.nextTag()
-			if z.tt == CommentToken && !z.ReturnComments {
-				continue
-			}
-		}
-		return z.tt
-	}
-	panic("unreachable")
-}
-
-// trim returns the largest j such that z.buf[i:j] contains only white space,
-// or only white space plus the final ">" or "/>" of the raw data.
-func (z *Tokenizer) trim(i int) int {
-	k := z.p1
-	for ; i < k; i++ {
-		switch z.buf[i] {
-		case ' ', '\n', '\t', '\f':
-			continue
-		case '>':
-			if i == k-1 {
-				return k
-			}
-		case '/':
-			if i == k-2 {
-				return k
-			}
-		}
-		return i
-	}
-	return k
-}
-
-// tagName finds the tag name at the start of z.buf[i:] and returns that name
-// lower-cased, as well as the trimmed cursor location afterwards.
-func (z *Tokenizer) tagName(i int) ([]byte, int) {
-	i0 := i
-loop:
-	for ; i < z.p1; i++ {
-		c := z.buf[i]
-		switch c {
-		case ' ', '\n', '\t', '\f', '/', '>':
-			break loop
-		}
-		if 'A' <= c && c <= 'Z' {
-			z.buf[i] = c + 'a' - 'A'
-		}
-	}
-	return z.buf[i0:i], z.trim(i)
-}
-
-// unquotedAttrVal finds the unquoted attribute value at the start of z.buf[i:]
-// and returns that value, as well as the trimmed cursor location afterwards.
-func (z *Tokenizer) unquotedAttrVal(i int) ([]byte, int) {
-	i0 := i
-loop:
-	for ; i < z.p1; i++ {
-		switch z.buf[i] {
-		case ' ', '\n', '\t', '\f', '>':
-			break loop
-		case '&':
-			// TODO: unescape the entity.
-		}
-	}
-	return z.buf[i0:i], z.trim(i)
-}
-
-// attrName finds the largest attribute name at the start
-// of z.buf[i:] and returns it lower-cased, as well
-// as the trimmed cursor location after that name.
-//
-// http://dev.w3.org/html5/spec/Overview.html#syntax-attribute-name
-// TODO: unicode characters
-func (z *Tokenizer) attrName(i int) ([]byte, int) {
-	for z.buf[i] == '/' {
-		i++
-		if z.buf[i] == '>' {
-			return nil, z.trim(i)
-		}
-	}
-	i0 := i
-loop:
-	for ; i < z.p1; i++ {
-		c := z.buf[i]
-		switch c {
-		case '>', '/', '=':
-			break loop
-		}
-		switch {
-		case 'A' <= c && c <= 'Z':
-			z.buf[i] = c + 'a' - 'A'
-		case c > ' ' && c < 0x7f:
-			// No-op.
-		default:
-			break loop
-		}
-	}
-	return z.buf[i0:i], z.trim(i)
-}
-
-// Text returns the unescaped text of a text, comment or doctype token. The
-// contents of the returned slice may change on the next call to Next.
-func (z *Tokenizer) Text() []byte {
-	var i0, i1 int
-	switch z.tt {
-	case TextToken:
-		i0 = z.p0
-		i1 = z.p1
-	case CommentToken:
-		// Trim the "<!--" from the left and the "-->" from the right.
-		// "<!-->" is a valid comment, so the adjusted endpoints might overlap.
-		i0 = z.p0 + 4
-		i1 = z.p1 - 3
-	case DoctypeToken:
-		// Trim the "<!DOCTYPE " from the left and the ">" from the right.
-		i0 = z.p0 + 10
-		i1 = z.p1 - 1
-	default:
-		return nil
-	}
-	z.p0 = z.p1
-	if i0 < i1 {
-		return unescape(z.buf[i0:i1])
-	}
-	return nil
-}
-
-// TagName returns the lower-cased name of a tag token (the `img` out of
-// `<IMG SRC="foo">`) and whether the tag has attributes.
-// The contents of the returned slice may change on the next call to Next.
-func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
-	i := z.p0 + 1
-	if i >= z.p1 {
-		z.p0 = z.p1
-		return nil, false
-	}
-	if z.buf[i] == '/' {
-		i++
-	}
-	name, z.p0 = z.tagName(i)
-	hasAttr = z.p0 != z.p1
-	return
-}
-
-// TagAttr returns the lower-cased key and unescaped value of the next unparsed
-// attribute for the current tag token and whether there are more attributes.
-// The contents of the returned slices may change on the next call to Next.
-func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
-	key, i := z.attrName(z.p0)
-	// Check for an empty attribute value.
-	if i == z.p1 {
-		z.p0 = i
-		return
-	}
-	// Get past the equals and quote characters.
-	if z.buf[i] != '=' {
-		z.p0, moreAttr = i, true
-		return
-	}
-	i = z.trim(i + 1)
-	if i == z.p1 {
-		z.p0 = i
-		return
-	}
-	closeQuote := z.buf[i]
-	if closeQuote != '\'' && closeQuote != '"' {
-		val, z.p0 = z.unquotedAttrVal(i)
-		moreAttr = z.p0 != z.p1
-		return
-	}
-	i = z.trim(i + 1)
-	// Copy and unescape everything up to the closing quote.
-	dst, src := i, i
-loop:
-	for src < z.p1 {
-		c := z.buf[src]
-		switch c {
-		case closeQuote:
-			src++
-			break loop
-		case '&':
-			dst, src = unescapeEntity(z.buf, dst, src, true)
-		case '\\':
-			if src == z.p1 {
-				z.buf[dst] = '\\'
-				dst++
-			} else {
-				z.buf[dst] = z.buf[src+1]
-				dst, src = dst+1, src+2
-			}
-		default:
-			z.buf[dst] = c
-			dst, src = dst+1, src+1
-		}
-	}
-	val, z.p0 = z.buf[i:dst], z.trim(src)
-	moreAttr = z.p0 != z.p1
-	return
-}
-
-// Token returns the next Token. The result's Data and Attr values remain valid
-// after subsequent Next calls.
-func (z *Tokenizer) Token() Token {
-	t := Token{Type: z.tt}
-	switch z.tt {
-	case TextToken, CommentToken, DoctypeToken:
-		t.Data = string(z.Text())
-	case StartTagToken, EndTagToken, SelfClosingTagToken:
-		var attr []Attribute
-		name, moreAttr := z.TagName()
-		for moreAttr {
-			var key, val []byte
-			key, val, moreAttr = z.TagAttr()
-			attr = append(attr, Attribute{string(key), string(val)})
-		}
-		t.Data = string(name)
-		t.Attr = attr
-	}
-	return t
-}
-
-// NewTokenizer returns a new HTML Tokenizer for the given Reader.
-// The input is assumed to be UTF-8 encoded.
-func NewTokenizer(r io.Reader) *Tokenizer {
-	return &Tokenizer{
-		r:   r,
-		buf: make([]byte, 0, 4096),
-	}
-}
diff --git a/src/pkg/html/token_test.go b/src/pkg/html/token_test.go
deleted file mode 100644
index 0a0beb2..0000000
--- a/src/pkg/html/token_test.go
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright 2010 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 html
-
-import (
-	"bytes"
-	"os"
-	"strings"
-	"testing"
-)
-
-type tokenTest struct {
-	// A short description of the test case.
-	desc string
-	// The HTML to parse.
-	html string
-	// The string representations of the expected tokens, joined by '$'.
-	golden string
-}
-
-var tokenTests = []tokenTest{
-	// A single text node. The tokenizer should not break text nodes on whitespace,
-	// nor should it normalize whitespace within a text node.
-	{
-		"text",
-		"foo  bar",
-		"foo  bar",
-	},
-	// An entity.
-	{
-		"entity",
-		"one < two",
-		"one < two",
-	},
-	// A start, self-closing and end tag. The tokenizer does not care if the start
-	// and end tokens don't match; that is the job of the parser.
-	{
-		"tags",
-		"<a>b<c/>d</e>",
-		"<a>$b$<c/>$d$</e>",
-	},
-	// Some malformed tags that are missing a '>'.
-	{
-		"malformed tag #0",
-		`<p</p>`,
-		`<p< p="">`,
-	},
-	{
-		"malformed tag #1",
-		`<p </p>`,
-		`<p <="" p="">`,
-	},
-	{
-		"malformed tag #2",
-		`<p id=0</p>`,
-		`<p id="0</p">`,
-	},
-	{
-		"malformed tag #3",
-		`<p id="0</p>`,
-		`<p id="0</p>">`,
-	},
-	{
-		"malformed tag #4",
-		`<p id="0"</p>`,
-		`<p id="0" <="" p="">`,
-	},
-	// Comments.
-	{
-		"comment0",
-		"abc<b><!-- skipme --></b>def",
-		"abc$<b>$</b>$def",
-	},
-	{
-		"comment1",
-		"a<!-->z",
-		"a$z",
-	},
-	{
-		"comment2",
-		"a<!--->z",
-		"a$z",
-	},
-	{
-		"comment3",
-		"a<!--x>-->z",
-		"a$z",
-	},
-	{
-		"comment4",
-		"a<!--x->-->z",
-		"a$z",
-	},
-	{
-		"comment5",
-		"a<!>z",
-		"a$<!>z",
-	},
-	{
-		"comment6",
-		"a<!->z",
-		"a$<!->z",
-	},
-	{
-		"comment7",
-		"a<!---<>z",
-		"a$<!---<>z",
-	},
-	{
-		"comment8",
-		"a<!--z",
-		"a$<!--z",
-	},
-	// An attribute with a backslash.
-	{
-		"backslash",
-		`<p id="a\"b">`,
-		`<p id="a"b">`,
-	},
-	// Entities, tag name and attribute key lower-casing, and whitespace
-	// normalization within a tag.
-	{
-		"tricky",
-		"<p \t\n iD=\"a"B\"  foo=\"bar\"><EM>te<&;xt</em></p>",
-		`<p id="a"B" foo="bar">$<em>$te<&;xt$</em>$</p>`,
-	},
-	// A nonexistent entity. Tokenizing and converting back to a string should
-	// escape the "&" to become "&".
-	{
-		"noSuchEntity",
-		`<a b="c&noSuchEntity;d"><&alsoDoesntExist;&`,
-		`<a b="c&noSuchEntity;d">$<&alsoDoesntExist;&`,
-	},
-	{
-		"entity without semicolon",
-		`¬it;∉<a b="q=z&amp=5&notice=hello¬=world">`,
-		`¬it;∉$<a b="q=z&amp=5&notice=hello¬=world">`,
-	},
-	{
-		"entity with digits",
-		"&frac12;",
-		"½",
-	},
-	// Attribute tests:
-	// http://dev.w3.org/html5/spec/Overview.html#attributes-0
-	{
-		"Empty attribute",
-		`<input disabled FOO>`,
-		`<input disabled="" foo="">`,
-	},
-	{
-		"Empty attribute, whitespace",
-		`<input disabled FOO >`,
-		`<input disabled="" foo="">`,
-	},
-	{
-		"Unquoted attribute value",
-		`<input value=yes FOO=BAR>`,
-		`<input value="yes" foo="BAR">`,
-	},
-	{
-		"Unquoted attribute value, spaces",
-		`<input value = yes FOO = BAR>`,
-		`<input value="yes" foo="BAR">`,
-	},
-	{
-		"Unquoted attribute value, trailing space",
-		`<input value=yes FOO=BAR >`,
-		`<input value="yes" foo="BAR">`,
-	},
-	{
-		"Single-quoted attribute value",
-		`<input value='yes' FOO='BAR'>`,
-		`<input value="yes" foo="BAR">`,
-	},
-	{
-		"Single-quoted attribute value, trailing space",
-		`<input value='yes' FOO='BAR' >`,
-		`<input value="yes" foo="BAR">`,
-	},
-	{
-		"Double-quoted attribute value",
-		`<input value="I'm an attribute" FOO="BAR">`,
-		`<input value="I'm an attribute" foo="BAR">`,
-	},
-	{
-		"Attribute name characters",
-		`<meta http-equiv="content-type">`,
-		`<meta http-equiv="content-type">`,
-	},
-}
-
-func TestTokenizer(t *testing.T) {
-loop:
-	for _, tt := range tokenTests {
-		z := NewTokenizer(bytes.NewBuffer([]byte(tt.html)))
-		for i, s := range strings.Split(tt.golden, "$") {
-			if z.Next() == ErrorToken {
-				t.Errorf("%s token %d: want %q got error %v", tt.desc, i, s, z.Error())
-				continue loop
-			}
-			actual := z.Token().String()
-			if s != actual {
-				t.Errorf("%s token %d: want %q got %q", tt.desc, i, s, actual)
-				continue loop
-			}
-		}
-		z.Next()
-		if z.Error() != os.EOF {
-			t.Errorf("%s: want EOF got %q", tt.desc, z.Token().String())
-		}
-	}
-}
-
-type unescapeTest struct {
-	// A short description of the test case.
-	desc string
-	// The HTML text.
-	html string
-	// The unescaped text.
-	unescaped string
-}
-
-var unescapeTests = []unescapeTest{
-	// Handle no entities.
-	{
-		"copy",
-		"A\ttext\nstring",
-		"A\ttext\nstring",
-	},
-	// Handle simple named entities.
-	{
-		"simple",
-		"& > <",
-		"& > <",
-	},
-	// Handle hitting the end of the string.
-	{
-		"stringEnd",
-		"&amp &amp",
-		"& &",
-	},
-	// Handle entities with two codepoints.
-	{
-		"multiCodepoint",
-		"text ⋛︀ blah",
-		"text \u22db\ufe00 blah",
-	},
-	// Handle decimal numeric entities.
-	{
-		"decimalEntity",
-		"Delta = Δ ",
-		"Delta = Δ ",
-	},
-	// Handle hexadecimal numeric entities.
-	{
-		"hexadecimalEntity",
-		"Lambda = &#x3bb; = &#X3Bb ",
-		"Lambda = λ = λ ",
-	},
-	// Handle numeric early termination.
-	{
-		"numericEnds",
-		"&# &#x €43 &copy = &#169f = &#xa9",
-		"&# &#x €43 © = ©f = ©",
-	},
-	// Handle numeric ISO-8859-1 entity replacements.
-	{
-		"numericReplacements",
-		"Footnote&#x87;",
-		"Footnote‡",
-	},
-}
-
-func TestUnescape(t *testing.T) {
-	for _, tt := range unescapeTests {
-		unescaped := UnescapeString(tt.html)
-		if unescaped != tt.unescaped {
-			t.Errorf("TestUnescape %s: want %q, got %q", tt.desc, tt.unescaped, unescaped)
-		}
-	}
-}
-
-func TestUnescapeEscape(t *testing.T) {
-	ss := []string{
-		``,
-		`abc def`,
-		`a & b`,
-		`a&b`,
-		`a &amp b`,
-		`"`,
-		`"`,
-		`"<&>"`,
-		`"<&>"`,
-		`3&5==1 && 0<1, "0<1", a+acute=á`,
-	}
-	for _, s := range ss {
-		if s != UnescapeString(EscapeString(s)) {
-			t.Errorf("s != UnescapeString(EscapeString(s)), s=%q", s)
-		}
-	}
-}
-
-func TestBufAPI(t *testing.T) {
-	s := "0<a>1</a>2<b>3<a>4<a>5</a>6</b>7</a>8<a/>9"
-	z := NewTokenizer(bytes.NewBuffer([]byte(s)))
-	result := bytes.NewBuffer(nil)
-	depth := 0
-loop:
-	for {
-		tt := z.Next()
-		switch tt {
-		case ErrorToken:
-			if z.Error() != os.EOF {
-				t.Error(z.Error())
-			}
-			break loop
-		case TextToken:
-			if depth > 0 {
-				result.Write(z.Text())
-			}
-		case StartTagToken, EndTagToken:
-			tn, _ := z.TagName()
-			if len(tn) == 1 && tn[0] == 'a' {
-				if tt == StartTagToken {
-					depth++
-				} else {
-					depth--
-				}
-			}
-		}
-	}
-	u := "14567"
-	v := string(result.Bytes())
-	if u != v {
-		t.Errorf("TestBufAPI: want %q got %q", u, v)
-	}
-}
diff --git a/src/pkg/http/Makefile b/src/pkg/http/Makefile
deleted file mode 100644
index af4fbc1..0000000
--- a/src/pkg/http/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=http
-GOFILES=\
-	chunked.go\
-	client.go\
-	cookie.go\
-	dump.go\
-	filetransport.go\
-	fs.go\
-	header.go\
-	lex.go\
-	persist.go\
-	request.go\
-	response.go\
-	reverseproxy.go\
-	server.go\
-	sniff.go\
-	status.go\
-	transfer.go\
-	transport.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/http/cgi/Makefile b/src/pkg/http/cgi/Makefile
deleted file mode 100644
index 19b1039..0000000
--- a/src/pkg/http/cgi/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=http/cgi
-GOFILES=\
-	child.go\
-	host.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/http/cgi/child.go b/src/pkg/http/cgi/child.go
deleted file mode 100644
index 8d0eca8..0000000
--- a/src/pkg/http/cgi/child.go
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2011 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 file implements CGI from the perspective of a child
-// process.
-
-package cgi
-
-import (
-	"bufio"
-	"crypto/tls"
-	"fmt"
-	"http"
-	"io"
-	"io/ioutil"
-	"net"
-	"os"
-	"strconv"
-	"strings"
-	"url"
-)
-
-// Request returns the HTTP request as represented in the current
-// environment. This assumes the current program is being run
-// by a web server in a CGI environment.
-// The returned Request's Body is populated, if applicable.
-func Request() (*http.Request, os.Error) {
-	r, err := RequestFromMap(envMap(os.Environ()))
-	if err != nil {
-		return nil, err
-	}
-	if r.ContentLength > 0 {
-		r.Body = ioutil.NopCloser(io.LimitReader(os.Stdin, r.ContentLength))
-	}
-	return r, nil
-}
-
-func envMap(env []string) map[string]string {
-	m := make(map[string]string)
-	for _, kv := range env {
-		if idx := strings.Index(kv, "="); idx != -1 {
-			m[kv[:idx]] = kv[idx+1:]
-		}
-	}
-	return m
-}
-
-// RequestFromMap creates an http.Request from CGI variables.
-// The returned Request's Body field is not populated.
-func RequestFromMap(params map[string]string) (*http.Request, os.Error) {
-	r := new(http.Request)
-	r.Method = params["REQUEST_METHOD"]
-	if r.Method == "" {
-		return nil, os.NewError("cgi: no REQUEST_METHOD in environment")
-	}
-
-	r.Proto = params["SERVER_PROTOCOL"]
-	var ok bool
-	r.ProtoMajor, r.ProtoMinor, ok = http.ParseHTTPVersion(r.Proto)
-	if !ok {
-		return nil, os.NewError("cgi: invalid SERVER_PROTOCOL version")
-	}
-
-	r.Close = true
-	r.Trailer = http.Header{}
-	r.Header = http.Header{}
-
-	r.Host = params["HTTP_HOST"]
-
-	if lenstr := params["CONTENT_LENGTH"]; lenstr != "" {
-		clen, err := strconv.Atoi64(lenstr)
-		if err != nil {
-			return nil, os.NewError("cgi: bad CONTENT_LENGTH in environment: " + lenstr)
-		}
-		r.ContentLength = clen
-	}
-
-	if ct := params["CONTENT_TYPE"]; ct != "" {
-		r.Header.Set("Content-Type", ct)
-	}
-
-	// Copy "HTTP_FOO_BAR" variables to "Foo-Bar" Headers
-	for k, v := range params {
-		if !strings.HasPrefix(k, "HTTP_") || k == "HTTP_HOST" {
-			continue
-		}
-		r.Header.Add(strings.Replace(k[5:], "_", "-", -1), v)
-	}
-
-	// TODO: cookies.  parsing them isn't exported, though.
-
-	if r.Host != "" {
-		// Hostname is provided, so we can reasonably construct a URL,
-		// even if we have to assume 'http' for the scheme.
-		r.RawURL = "http://" + r.Host + params["REQUEST_URI"]
-		url, err := url.Parse(r.RawURL)
-		if err != nil {
-			return nil, os.NewError("cgi: failed to parse host and REQUEST_URI into a URL: " + r.RawURL)
-		}
-		r.URL = url
-	}
-	// Fallback logic if we don't have a Host header or the URL
-	// failed to parse
-	if r.URL == nil {
-		r.RawURL = params["REQUEST_URI"]
-		url, err := url.Parse(r.RawURL)
-		if err != nil {
-			return nil, os.NewError("cgi: failed to parse REQUEST_URI into a URL: " + r.RawURL)
-		}
-		r.URL = url
-	}
-
-	// There's apparently a de-facto standard for this.
-	// http://docstore.mik.ua/orelly/linux/cgi/ch03_02.htm#ch03-35636
-	if s := params["HTTPS"]; s == "on" || s == "ON" || s == "1" {
-		r.TLS = &tls.ConnectionState{HandshakeComplete: true}
-	}
-
-	// Request.RemoteAddr has its port set by Go's standard http
-	// server, so we do here too. We don't have one, though, so we
-	// use a dummy one.
-	r.RemoteAddr = net.JoinHostPort(params["REMOTE_ADDR"], "0")
-
-	return r, nil
-}
-
-// Serve executes the provided Handler on the currently active CGI
-// request, if any. If there's no current CGI environment
-// an error is returned. The provided handler may be nil to use
-// http.DefaultServeMux.
-func Serve(handler http.Handler) os.Error {
-	req, err := Request()
-	if err != nil {
-		return err
-	}
-	if handler == nil {
-		handler = http.DefaultServeMux
-	}
-	rw := &response{
-		req:    req,
-		header: make(http.Header),
-		bufw:   bufio.NewWriter(os.Stdout),
-	}
-	handler.ServeHTTP(rw, req)
-	if err = rw.bufw.Flush(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type response struct {
-	req        *http.Request
-	header     http.Header
-	bufw       *bufio.Writer
-	headerSent bool
-}
-
-func (r *response) Flush() {
-	r.bufw.Flush()
-}
-
-func (r *response) Header() http.Header {
-	return r.header
-}
-
-func (r *response) Write(p []byte) (n int, err os.Error) {
-	if !r.headerSent {
-		r.WriteHeader(http.StatusOK)
-	}
-	return r.bufw.Write(p)
-}
-
-func (r *response) WriteHeader(code int) {
-	if r.headerSent {
-		// Note: explicitly using Stderr, as Stdout is our HTTP output.
-		fmt.Fprintf(os.Stderr, "CGI attempted to write header twice on request for %s", r.req.URL)
-		return
-	}
-	r.headerSent = true
-	fmt.Fprintf(r.bufw, "Status: %d %s\r\n", code, http.StatusText(code))
-
-	// Set a default Content-Type
-	if _, hasType := r.header["Content-Type"]; !hasType {
-		r.header.Add("Content-Type", "text/html; charset=utf-8")
-	}
-
-	r.header.Write(r.bufw)
-	r.bufw.WriteString("\r\n")
-	r.bufw.Flush()
-}
diff --git a/src/pkg/http/cgi/child_test.go b/src/pkg/http/cgi/child_test.go
deleted file mode 100644
index eee043b..0000000
--- a/src/pkg/http/cgi/child_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2011 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.
-
-// Tests for CGI (the child process perspective)
-
-package cgi
-
-import (
-	"testing"
-)
-
-func TestRequest(t *testing.T) {
-	env := map[string]string{
-		"SERVER_PROTOCOL": "HTTP/1.1",
-		"REQUEST_METHOD":  "GET",
-		"HTTP_HOST":       "example.com",
-		"HTTP_REFERER":    "elsewhere",
-		"HTTP_USER_AGENT": "goclient",
-		"HTTP_FOO_BAR":    "baz",
-		"REQUEST_URI":     "/path?a=b",
-		"CONTENT_LENGTH":  "123",
-		"CONTENT_TYPE":    "text/xml",
-		"HTTPS":           "1",
-		"REMOTE_ADDR":     "5.6.7.8",
-	}
-	req, err := RequestFromMap(env)
-	if err != nil {
-		t.Fatalf("RequestFromMap: %v", err)
-	}
-	if g, e := req.UserAgent(), "goclient"; e != g {
-		t.Errorf("expected UserAgent %q; got %q", e, g)
-	}
-	if g, e := req.Method, "GET"; e != g {
-		t.Errorf("expected Method %q; got %q", e, g)
-	}
-	if g, e := req.Header.Get("Content-Type"), "text/xml"; e != g {
-		t.Errorf("expected Content-Type %q; got %q", e, g)
-	}
-	if g, e := req.ContentLength, int64(123); e != g {
-		t.Errorf("expected ContentLength %d; got %d", e, g)
-	}
-	if g, e := req.Referer(), "elsewhere"; e != g {
-		t.Errorf("expected Referer %q; got %q", e, g)
-	}
-	if req.Header == nil {
-		t.Fatalf("unexpected nil Header")
-	}
-	if g, e := req.Header.Get("Foo-Bar"), "baz"; e != g {
-		t.Errorf("expected Foo-Bar %q; got %q", e, g)
-	}
-	if g, e := req.RawURL, "http://example.com/path?a=b"; e != g {
-		t.Errorf("expected RawURL %q; got %q", e, g)
-	}
-	if g, e := req.URL.String(), "http://example.com/path?a=b"; e != g {
-		t.Errorf("expected URL %q; got %q", e, g)
-	}
-	if g, e := req.FormValue("a"), "b"; e != g {
-		t.Errorf("expected FormValue(a) %q; got %q", e, g)
-	}
-	if req.Trailer == nil {
-		t.Errorf("unexpected nil Trailer")
-	}
-	if req.TLS == nil {
-		t.Errorf("expected non-nil TLS")
-	}
-	if e, g := "5.6.7.8:0", req.RemoteAddr; e != g {
-		t.Errorf("RemoteAddr: got %q; want %q", g, e)
-	}
-}
-
-func TestRequestWithoutHost(t *testing.T) {
-	env := map[string]string{
-		"SERVER_PROTOCOL": "HTTP/1.1",
-		"HTTP_HOST":       "",
-		"REQUEST_METHOD":  "GET",
-		"REQUEST_URI":     "/path?a=b",
-		"CONTENT_LENGTH":  "123",
-	}
-	req, err := RequestFromMap(env)
-	if err != nil {
-		t.Fatalf("RequestFromMap: %v", err)
-	}
-	if g, e := req.RawURL, "/path?a=b"; e != g {
-		t.Errorf("expected RawURL %q; got %q", e, g)
-	}
-	if req.URL == nil {
-		t.Fatalf("unexpected nil URL")
-	}
-	if g, e := req.URL.String(), "/path?a=b"; e != g {
-		t.Errorf("expected URL %q; got %q", e, g)
-	}
-}
diff --git a/src/pkg/http/cgi/host.go b/src/pkg/http/cgi/host.go
deleted file mode 100644
index 1d63821..0000000
--- a/src/pkg/http/cgi/host.go
+++ /dev/null
@@ -1,351 +0,0 @@
-// Copyright 2011 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 file implements the host side of CGI (being the webserver
-// parent process).
-
-// Package cgi implements CGI (Common Gateway Interface) as specified
-// in RFC 3875.
-//
-// Note that using CGI means starting a new process to handle each
-// request, which is typically less efficient than using a
-// long-running server.  This package is intended primarily for
-// compatibility with existing systems.
-package cgi
-
-import (
-	"bufio"
-	"exec"
-	"fmt"
-	"http"
-	"io"
-	"log"
-	"os"
-	"path/filepath"
-	"regexp"
-	"runtime"
-	"strconv"
-	"strings"
-)
-
-var trailingPort = regexp.MustCompile(`:([0-9]+)$`)
-
-var osDefaultInheritEnv = map[string][]string{
-	"darwin":  {"DYLD_LIBRARY_PATH"},
-	"freebsd": {"LD_LIBRARY_PATH"},
-	"hpux":    {"LD_LIBRARY_PATH", "SHLIB_PATH"},
-	"irix":    {"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"},
-	"linux":   {"LD_LIBRARY_PATH"},
-	"openbsd": {"LD_LIBRARY_PATH"},
-	"solaris": {"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"},
-	"windows": {"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"},
-}
-
-// Handler runs an executable in a subprocess with a CGI environment.
-type Handler struct {
-	Path string // path to the CGI executable
-	Root string // root URI prefix of handler or empty for "/"
-
-	// Dir specifies the CGI executable's working directory.
-	// If Dir is empty, the base directory of Path is used.
-	// If Path has no base directory, the current working
-	// directory is used.
-	Dir string
-
-	Env        []string    // extra environment variables to set, if any, as "key=value"
-	InheritEnv []string    // environment variables to inherit from host, as "key"
-	Logger     *log.Logger // optional log for errors or nil to use log.Print
-	Args       []string    // optional arguments to pass to child process
-
-	// PathLocationHandler specifies the root http Handler that
-	// should handle internal redirects when the CGI process
-	// returns a Location header value starting with a "/", as
-	// specified in RFC 3875 § 6.3.2. This will likely be
-	// http.DefaultServeMux.
-	//
-	// If nil, a CGI response with a local URI path is instead sent
-	// back to the client and not redirected internally.
-	PathLocationHandler http.Handler
-}
-
-// removeLeadingDuplicates remove leading duplicate in environments.
-// It's possible to override environment like following.
-//    cgi.Handler{
-//      ...
-//      Env: []string{"SCRIPT_FILENAME=foo.php"},
-//    }
-func removeLeadingDuplicates(env []string) (ret []string) {
-	n := len(env)
-	for i := 0; i < n; i++ {
-		e := env[i]
-		s := strings.SplitN(e, "=", 2)[0]
-		found := false
-		for j := i + 1; j < n; j++ {
-			if s == strings.SplitN(env[j], "=", 2)[0] {
-				found = true
-				break
-			}
-		}
-		if !found {
-			ret = append(ret, e)
-		}
-	}
-	return
-}
-
-func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
-	root := h.Root
-	if root == "" {
-		root = "/"
-	}
-
-	if len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked" {
-		rw.WriteHeader(http.StatusBadRequest)
-		rw.Write([]byte("Chunked request bodies are not supported by CGI."))
-		return
-	}
-
-	pathInfo := req.URL.Path
-	if root != "/" && strings.HasPrefix(pathInfo, root) {
-		pathInfo = pathInfo[len(root):]
-	}
-
-	port := "80"
-	if matches := trailingPort.FindStringSubmatch(req.Host); len(matches) != 0 {
-		port = matches[1]
-	}
-
-	env := []string{
-		"SERVER_SOFTWARE=go",
-		"SERVER_NAME=" + req.Host,
-		"SERVER_PROTOCOL=HTTP/1.1",
-		"HTTP_HOST=" + req.Host,
-		"GATEWAY_INTERFACE=CGI/1.1",
-		"REQUEST_METHOD=" + req.Method,
-		"QUERY_STRING=" + req.URL.RawQuery,
-		"REQUEST_URI=" + req.URL.RawPath,
-		"PATH_INFO=" + pathInfo,
-		"SCRIPT_NAME=" + root,
-		"SCRIPT_FILENAME=" + h.Path,
-		"REMOTE_ADDR=" + req.RemoteAddr,
-		"REMOTE_HOST=" + req.RemoteAddr,
-		"SERVER_PORT=" + port,
-	}
-
-	if req.TLS != nil {
-		env = append(env, "HTTPS=on")
-	}
-
-	for k, v := range req.Header {
-		k = strings.Map(upperCaseAndUnderscore, k)
-		joinStr := ", "
-		if k == "COOKIE" {
-			joinStr = "; "
-		}
-		env = append(env, "HTTP_"+k+"="+strings.Join(v, joinStr))
-	}
-
-	if req.ContentLength > 0 {
-		env = append(env, fmt.Sprintf("CONTENT_LENGTH=%d", req.ContentLength))
-	}
-	if ctype := req.Header.Get("Content-Type"); ctype != "" {
-		env = append(env, "CONTENT_TYPE="+ctype)
-	}
-
-	if h.Env != nil {
-		env = append(env, h.Env...)
-	}
-
-	envPath := os.Getenv("PATH")
-	if envPath == "" {
-		envPath = "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
-	}
-	env = append(env, "PATH="+envPath)
-
-	for _, e := range h.InheritEnv {
-		if v := os.Getenv(e); v != "" {
-			env = append(env, e+"="+v)
-		}
-	}
-
-	for _, e := range osDefaultInheritEnv[runtime.GOOS] {
-		if v := os.Getenv(e); v != "" {
-			env = append(env, e+"="+v)
-		}
-	}
-
-	env = removeLeadingDuplicates(env)
-
-	var cwd, path string
-	if h.Dir != "" {
-		path = h.Path
-		cwd = h.Dir
-	} else {
-		cwd, path = filepath.Split(h.Path)
-	}
-	if cwd == "" {
-		cwd = "."
-	}
-
-	internalError := func(err os.Error) {
-		rw.WriteHeader(http.StatusInternalServerError)
-		h.printf("CGI error: %v", err)
-	}
-
-	cmd := &exec.Cmd{
-		Path:   path,
-		Args:   append([]string{h.Path}, h.Args...),
-		Dir:    cwd,
-		Env:    env,
-		Stderr: os.Stderr, // for now
-	}
-	if req.ContentLength != 0 {
-		cmd.Stdin = req.Body
-	}
-	stdoutRead, err := cmd.StdoutPipe()
-	if err != nil {
-		internalError(err)
-		return
-	}
-
-	err = cmd.Start()
-	if err != nil {
-		internalError(err)
-		return
-	}
-	defer cmd.Wait()
-	defer stdoutRead.Close()
-
-	linebody, _ := bufio.NewReaderSize(stdoutRead, 1024)
-	headers := make(http.Header)
-	statusCode := 0
-	for {
-		line, isPrefix, err := linebody.ReadLine()
-		if isPrefix {
-			rw.WriteHeader(http.StatusInternalServerError)
-			h.printf("cgi: long header line from subprocess.")
-			return
-		}
-		if err == os.EOF {
-			break
-		}
-		if err != nil {
-			rw.WriteHeader(http.StatusInternalServerError)
-			h.printf("cgi: error reading headers: %v", err)
-			return
-		}
-		if len(line) == 0 {
-			break
-		}
-		parts := strings.SplitN(string(line), ":", 2)
-		if len(parts) < 2 {
-			h.printf("cgi: bogus header line: %s", string(line))
-			continue
-		}
-		header, val := parts[0], parts[1]
-		header = strings.TrimSpace(header)
-		val = strings.TrimSpace(val)
-		switch {
-		case header == "Status":
-			if len(val) < 3 {
-				h.printf("cgi: bogus status (short): %q", val)
-				return
-			}
-			code, err := strconv.Atoi(val[0:3])
-			if err != nil {
-				h.printf("cgi: bogus status: %q", val)
-				h.printf("cgi: line was %q", line)
-				return
-			}
-			statusCode = code
-		default:
-			headers.Add(header, val)
-		}
-	}
-
-	if loc := headers.Get("Location"); loc != "" {
-		if strings.HasPrefix(loc, "/") && h.PathLocationHandler != nil {
-			h.handleInternalRedirect(rw, req, loc)
-			return
-		}
-		if statusCode == 0 {
-			statusCode = http.StatusFound
-		}
-	}
-
-	if statusCode == 0 {
-		statusCode = http.StatusOK
-	}
-
-	// Copy headers to rw's headers, after we've decided not to
-	// go into handleInternalRedirect, which won't want its rw
-	// headers to have been touched.
-	for k, vv := range headers {
-		for _, v := range vv {
-			rw.Header().Add(k, v)
-		}
-	}
-
-	rw.WriteHeader(statusCode)
-
-	_, err = io.Copy(rw, linebody)
-	if err != nil {
-		h.printf("cgi: copy error: %v", err)
-	}
-}
-
-func (h *Handler) printf(format string, v ...interface{}) {
-	if h.Logger != nil {
-		h.Logger.Printf(format, v...)
-	} else {
-		log.Printf(format, v...)
-	}
-}
-
-func (h *Handler) handleInternalRedirect(rw http.ResponseWriter, req *http.Request, path string) {
-	url, err := req.URL.Parse(path)
-	if err != nil {
-		rw.WriteHeader(http.StatusInternalServerError)
-		h.printf("cgi: error resolving local URI path %q: %v", path, err)
-		return
-	}
-	// TODO: RFC 3875 isn't clear if only GET is supported, but it
-	// suggests so: "Note that any message-body attached to the
-	// request (such as for a POST request) may not be available
-	// to the resource that is the target of the redirect."  We
-	// should do some tests against Apache to see how it handles
-	// POST, HEAD, etc. Does the internal redirect get the same
-	// method or just GET? What about incoming headers?
-	// (e.g. Cookies) Which headers, if any, are copied into the
-	// second request?
-	newReq := &http.Request{
-		Method:     "GET",
-		URL:        url,
-		RawURL:     path,
-		Proto:      "HTTP/1.1",
-		ProtoMajor: 1,
-		ProtoMinor: 1,
-		Header:     make(http.Header),
-		Host:       url.Host,
-		RemoteAddr: req.RemoteAddr,
-		TLS:        req.TLS,
-	}
-	h.PathLocationHandler.ServeHTTP(rw, newReq)
-}
-
-func upperCaseAndUnderscore(rune int) int {
-	switch {
-	case rune >= 'a' && rune <= 'z':
-		return rune - ('a' - 'A')
-	case rune == '-':
-		return '_'
-	case rune == '=':
-		// Maybe not part of the CGI 'spec' but would mess up
-		// the environment in any case, as Go represents the
-		// environment as a slice of "key=value" strings.
-		return '_'
-	}
-	// TODO: other transformations in spec or practice?
-	return rune
-}
diff --git a/src/pkg/http/cgi/host_test.go b/src/pkg/http/cgi/host_test.go
deleted file mode 100644
index 8111ba1..0000000
--- a/src/pkg/http/cgi/host_test.go
+++ /dev/null
@@ -1,478 +0,0 @@
-// Copyright 2011 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.
-
-// Tests for package cgi
-
-package cgi
-
-import (
-	"bufio"
-	"exec"
-	"fmt"
-	"http"
-	"http/httptest"
-	"io"
-	"os"
-	"net"
-	"path/filepath"
-	"strconv"
-	"strings"
-	"testing"
-	"time"
-	"runtime"
-)
-
-func newRequest(httpreq string) *http.Request {
-	buf := bufio.NewReader(strings.NewReader(httpreq))
-	req, err := http.ReadRequest(buf)
-	if err != nil {
-		panic("cgi: bogus http request in test: " + httpreq)
-	}
-	req.RemoteAddr = "1.2.3.4"
-	return req
-}
-
-func runCgiTest(t *testing.T, h *Handler, httpreq string, expectedMap map[string]string) *httptest.ResponseRecorder {
-	rw := httptest.NewRecorder()
-	req := newRequest(httpreq)
-	h.ServeHTTP(rw, req)
-
-	// Make a map to hold the test map that the CGI returns.
-	m := make(map[string]string)
-	linesRead := 0
-readlines:
-	for {
-		line, err := rw.Body.ReadString('\n')
-		switch {
-		case err == os.EOF:
-			break readlines
-		case err != nil:
-			t.Fatalf("unexpected error reading from CGI: %v", err)
-		}
-		linesRead++
-		trimmedLine := strings.TrimRight(line, "\r\n")
-		split := strings.SplitN(trimmedLine, "=", 2)
-		if len(split) != 2 {
-			t.Fatalf("Unexpected %d parts from invalid line number %v: %q; existing map=%v",
-				len(split), linesRead, line, m)
-		}
-		m[split[0]] = split[1]
-	}
-
-	for key, expected := range expectedMap {
-		if got := m[key]; got != expected {
-			t.Errorf("for key %q got %q; expected %q", key, got, expected)
-		}
-	}
-	return rw
-}
-
-var cgiTested = false
-var cgiWorks bool
-
-func skipTest(t *testing.T) bool {
-	if !cgiTested {
-		cgiTested = true
-		cgiWorks = exec.Command("./testdata/test.cgi").Run() == nil
-	}
-	if !cgiWorks {
-		// No Perl on Windows, needed by test.cgi
-		// TODO: make the child process be Go, not Perl.
-		t.Logf("Skipping test: test.cgi failed.")
-		return true
-	}
-	return false
-}
-
-func TestCGIBasicGet(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/test.cgi",
-	}
-	expectedMap := map[string]string{
-		"test":                  "Hello CGI",
-		"param-a":               "b",
-		"param-foo":             "bar",
-		"env-GATEWAY_INTERFACE": "CGI/1.1",
-		"env-HTTP_HOST":         "example.com",
-		"env-PATH_INFO":         "",
-		"env-QUERY_STRING":      "foo=bar&a=b",
-		"env-REMOTE_ADDR":       "1.2.3.4",
-		"env-REMOTE_HOST":       "1.2.3.4",
-		"env-REQUEST_METHOD":    "GET",
-		"env-REQUEST_URI":       "/test.cgi?foo=bar&a=b",
-		"env-SCRIPT_FILENAME":   "testdata/test.cgi",
-		"env-SCRIPT_NAME":       "/test.cgi",
-		"env-SERVER_NAME":       "example.com",
-		"env-SERVER_PORT":       "80",
-		"env-SERVER_SOFTWARE":   "go",
-	}
-	replay := runCgiTest(t, h, "GET /test.cgi?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
-
-	if expected, got := "text/html", replay.Header().Get("Content-Type"); got != expected {
-		t.Errorf("got a Content-Type of %q; expected %q", got, expected)
-	}
-	if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
-		t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
-	}
-}
-
-func TestCGIBasicGetAbsPath(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	pwd, err := os.Getwd()
-	if err != nil {
-		t.Fatalf("getwd error: %v", err)
-	}
-	h := &Handler{
-		Path: pwd + "/testdata/test.cgi",
-		Root: "/test.cgi",
-	}
-	expectedMap := map[string]string{
-		"env-REQUEST_URI":     "/test.cgi?foo=bar&a=b",
-		"env-SCRIPT_FILENAME": pwd + "/testdata/test.cgi",
-		"env-SCRIPT_NAME":     "/test.cgi",
-	}
-	runCgiTest(t, h, "GET /test.cgi?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
-}
-
-func TestPathInfo(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/test.cgi",
-	}
-	expectedMap := map[string]string{
-		"param-a":             "b",
-		"env-PATH_INFO":       "/extrapath",
-		"env-QUERY_STRING":    "a=b",
-		"env-REQUEST_URI":     "/test.cgi/extrapath?a=b",
-		"env-SCRIPT_FILENAME": "testdata/test.cgi",
-		"env-SCRIPT_NAME":     "/test.cgi",
-	}
-	runCgiTest(t, h, "GET /test.cgi/extrapath?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
-}
-
-func TestPathInfoDirRoot(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/myscript/",
-	}
-	expectedMap := map[string]string{
-		"env-PATH_INFO":       "bar",
-		"env-QUERY_STRING":    "a=b",
-		"env-REQUEST_URI":     "/myscript/bar?a=b",
-		"env-SCRIPT_FILENAME": "testdata/test.cgi",
-		"env-SCRIPT_NAME":     "/myscript/",
-	}
-	runCgiTest(t, h, "GET /myscript/bar?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
-}
-
-func TestDupHeaders(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	h := &Handler{
-		Path: "testdata/test.cgi",
-	}
-	expectedMap := map[string]string{
-		"env-REQUEST_URI":     "/myscript/bar?a=b",
-		"env-SCRIPT_FILENAME": "testdata/test.cgi",
-		"env-HTTP_COOKIE":     "nom=NOM; yum=YUM",
-		"env-HTTP_X_FOO":      "val1, val2",
-	}
-	runCgiTest(t, h, "GET /myscript/bar?a=b HTTP/1.0\n"+
-		"Cookie: nom=NOM\n"+
-		"Cookie: yum=YUM\n"+
-		"X-Foo: val1\n"+
-		"X-Foo: val2\n"+
-		"Host: example.com\n\n",
-		expectedMap)
-}
-
-func TestPathInfoNoRoot(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "",
-	}
-	expectedMap := map[string]string{
-		"env-PATH_INFO":       "/bar",
-		"env-QUERY_STRING":    "a=b",
-		"env-REQUEST_URI":     "/bar?a=b",
-		"env-SCRIPT_FILENAME": "testdata/test.cgi",
-		"env-SCRIPT_NAME":     "/",
-	}
-	runCgiTest(t, h, "GET /bar?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
-}
-
-func TestCGIBasicPost(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	postReq := `POST /test.cgi?a=b HTTP/1.0
-Host: example.com
-Content-Type: application/x-www-form-urlencoded
-Content-Length: 15
-
-postfoo=postbar`
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/test.cgi",
-	}
-	expectedMap := map[string]string{
-		"test":               "Hello CGI",
-		"param-postfoo":      "postbar",
-		"env-REQUEST_METHOD": "POST",
-		"env-CONTENT_LENGTH": "15",
-		"env-REQUEST_URI":    "/test.cgi?a=b",
-	}
-	runCgiTest(t, h, postReq, expectedMap)
-}
-
-func chunk(s string) string {
-	return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
-}
-
-// The CGI spec doesn't allow chunked requests.
-func TestCGIPostChunked(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	postReq := `POST /test.cgi?a=b HTTP/1.1
-Host: example.com
-Content-Type: application/x-www-form-urlencoded
-Transfer-Encoding: chunked
-
-` + chunk("postfoo") + chunk("=") + chunk("postbar") + chunk("")
-
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/test.cgi",
-	}
-	expectedMap := map[string]string{}
-	resp := runCgiTest(t, h, postReq, expectedMap)
-	if got, expected := resp.Code, http.StatusBadRequest; got != expected {
-		t.Fatalf("Expected %v response code from chunked request body; got %d",
-			expected, got)
-	}
-}
-
-func TestRedirect(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/test.cgi",
-	}
-	rec := runCgiTest(t, h, "GET /test.cgi?loc=http://foo.com/ HTTP/1.0\nHost: example.com\n\n", nil)
-	if e, g := 302, rec.Code; e != g {
-		t.Errorf("expected status code %d; got %d", e, g)
-	}
-	if e, g := "http://foo.com/", rec.Header().Get("Location"); e != g {
-		t.Errorf("expected Location header of %q; got %q", e, g)
-	}
-}
-
-func TestInternalRedirect(t *testing.T) {
-	if skipTest(t) {
-		return
-	}
-	baseHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
-		fmt.Fprintf(rw, "basepath=%s\n", req.URL.Path)
-		fmt.Fprintf(rw, "remoteaddr=%s\n", req.RemoteAddr)
-	})
-	h := &Handler{
-		Path:                "testdata/test.cgi",
-		Root:                "/test.cgi",
-		PathLocationHandler: baseHandler,
-	}
-	expectedMap := map[string]string{
-		"basepath":   "/foo",
-		"remoteaddr": "1.2.3.4",
-	}
-	runCgiTest(t, h, "GET /test.cgi?loc=/foo HTTP/1.0\nHost: example.com\n\n", expectedMap)
-}
-
-// TestCopyError tests that we kill the process if there's an error copying
-// its output. (for example, from the client having gone away)
-func TestCopyError(t *testing.T) {
-	if skipTest(t) || runtime.GOOS == "windows" {
-		return
-	}
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/test.cgi",
-	}
-	ts := httptest.NewServer(h)
-	defer ts.Close()
-
-	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
-	if err != nil {
-		t.Fatal(err)
-	}
-	req, _ := http.NewRequest("GET", "http://example.com/test.cgi?bigresponse=1", nil)
-	err = req.Write(conn)
-	if err != nil {
-		t.Fatalf("Write: %v", err)
-	}
-
-	res, err := http.ReadResponse(bufio.NewReader(conn), req)
-	if err != nil {
-		t.Fatalf("ReadResponse: %v", err)
-	}
-
-	pidstr := res.Header.Get("X-CGI-Pid")
-	if pidstr == "" {
-		t.Fatalf("expected an X-CGI-Pid header in response")
-	}
-	pid, err := strconv.Atoi(pidstr)
-	if err != nil {
-		t.Fatalf("invalid X-CGI-Pid value")
-	}
-
-	var buf [5000]byte
-	n, err := io.ReadFull(res.Body, buf[:])
-	if err != nil {
-		t.Fatalf("ReadFull: %d bytes, %v", n, err)
-	}
-
-	childRunning := func() bool {
-		p, err := os.FindProcess(pid)
-		if err != nil {
-			return false
-		}
-		return p.Signal(os.UnixSignal(0)) == nil
-	}
-
-	if !childRunning() {
-		t.Fatalf("pre-conn.Close, expected child to be running")
-	}
-	conn.Close()
-
-	if tries := 0; childRunning() {
-		for tries < 15 && childRunning() {
-			time.Sleep(50e6 * int64(tries))
-			tries++
-		}
-		if childRunning() {
-			t.Fatalf("post-conn.Close, expected child to be gone")
-		}
-	}
-}
-
-func TestDirUnix(t *testing.T) {
-	if skipTest(t) || runtime.GOOS == "windows" {
-		return
-	}
-
-	cwd, _ := os.Getwd()
-	h := &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/test.cgi",
-		Dir:  cwd,
-	}
-	expectedMap := map[string]string{
-		"cwd": cwd,
-	}
-	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
-
-	cwd, _ = os.Getwd()
-	cwd = filepath.Join(cwd, "testdata")
-	h = &Handler{
-		Path: "testdata/test.cgi",
-		Root: "/test.cgi",
-	}
-	expectedMap = map[string]string{
-		"cwd": cwd,
-	}
-	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
-}
-
-func TestDirWindows(t *testing.T) {
-	if skipTest(t) || runtime.GOOS != "windows" {
-		return
-	}
-
-	cgifile, _ := filepath.Abs("testdata/test.cgi")
-
-	var perl string
-	var err os.Error
-	perl, err = exec.LookPath("perl")
-	if err != nil {
-		return
-	}
-	perl, _ = filepath.Abs(perl)
-
-	cwd, _ := os.Getwd()
-	h := &Handler{
-		Path: perl,
-		Root: "/test.cgi",
-		Dir:  cwd,
-		Args: []string{cgifile},
-		Env:  []string{"SCRIPT_FILENAME=" + cgifile},
-	}
-	expectedMap := map[string]string{
-		"cwd": cwd,
-	}
-	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
-
-	// If not specify Dir on windows, working directory should be
-	// base directory of perl.
-	cwd, _ = filepath.Split(perl)
-	if cwd != "" && cwd[len(cwd)-1] == filepath.Separator {
-		cwd = cwd[:len(cwd)-1]
-	}
-	h = &Handler{
-		Path: perl,
-		Root: "/test.cgi",
-		Args: []string{cgifile},
-		Env:  []string{"SCRIPT_FILENAME=" + cgifile},
-	}
-	expectedMap = map[string]string{
-		"cwd": cwd,
-	}
-	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
-}
-
-func TestEnvOverride(t *testing.T) {
-	cgifile, _ := filepath.Abs("testdata/test.cgi")
-
-	var perl string
-	var err os.Error
-	perl, err = exec.LookPath("perl")
-	if err != nil {
-		return
-	}
-	perl, _ = filepath.Abs(perl)
-
-	cwd, _ := os.Getwd()
-	h := &Handler{
-		Path: perl,
-		Root: "/test.cgi",
-		Dir:  cwd,
-		Args: []string{cgifile},
-		Env: []string{
-			"SCRIPT_FILENAME=" + cgifile,
-			"REQUEST_URI=/foo/bar"},
-	}
-	expectedMap := map[string]string{
-		"cwd": cwd,
-		"env-SCRIPT_FILENAME": cgifile,
-		"env-REQUEST_URI":     "/foo/bar",
-	}
-	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
-}
diff --git a/src/pkg/http/cgi/matryoshka_test.go b/src/pkg/http/cgi/matryoshka_test.go
deleted file mode 100644
index 3e4a6ad..0000000
--- a/src/pkg/http/cgi/matryoshka_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2011 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.
-
-// Tests a Go CGI program running under a Go CGI host process.
-// Further, the two programs are the same binary, just checking
-// their environment to figure out what mode to run in.
-
-package cgi
-
-import (
-	"fmt"
-	"http"
-	"os"
-	"testing"
-)
-
-// This test is a CGI host (testing host.go) that runs its own binary
-// as a child process testing the other half of CGI (child.go).
-func TestHostingOurselves(t *testing.T) {
-	h := &Handler{
-		Path: os.Args[0],
-		Root: "/test.go",
-		Args: []string{"-test.run=TestBeChildCGIProcess"},
-	}
-	expectedMap := map[string]string{
-		"test":                  "Hello CGI-in-CGI",
-		"param-a":               "b",
-		"param-foo":             "bar",
-		"env-GATEWAY_INTERFACE": "CGI/1.1",
-		"env-HTTP_HOST":         "example.com",
-		"env-PATH_INFO":         "",
-		"env-QUERY_STRING":      "foo=bar&a=b",
-		"env-REMOTE_ADDR":       "1.2.3.4",
-		"env-REMOTE_HOST":       "1.2.3.4",
-		"env-REQUEST_METHOD":    "GET",
-		"env-REQUEST_URI":       "/test.go?foo=bar&a=b",
-		"env-SCRIPT_FILENAME":   os.Args[0],
-		"env-SCRIPT_NAME":       "/test.go",
-		"env-SERVER_NAME":       "example.com",
-		"env-SERVER_PORT":       "80",
-		"env-SERVER_SOFTWARE":   "go",
-	}
-	replay := runCgiTest(t, h, "GET /test.go?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
-
-	if expected, got := "text/html; charset=utf-8", replay.Header().Get("Content-Type"); got != expected {
-		t.Errorf("got a Content-Type of %q; expected %q", got, expected)
-	}
-	if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
-		t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
-	}
-}
-
-// Note: not actually a test.
-func TestBeChildCGIProcess(t *testing.T) {
-	if os.Getenv("REQUEST_METHOD") == "" {
-		// Not in a CGI environment; skipping test.
-		return
-	}
-	Serve(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
-		rw.Header().Set("X-Test-Header", "X-Test-Value")
-		fmt.Fprintf(rw, "test=Hello CGI-in-CGI\n")
-		req.ParseForm()
-		for k, vv := range req.Form {
-			for _, v := range vv {
-				fmt.Fprintf(rw, "param-%s=%s\n", k, v)
-			}
-		}
-		for _, kv := range os.Environ() {
-			fmt.Fprintf(rw, "env-%s\n", kv)
-		}
-	}))
-	os.Exit(0)
-}
diff --git a/src/pkg/http/chunked.go b/src/pkg/http/chunked.go
deleted file mode 100644
index eff9ae2..0000000
--- a/src/pkg/http/chunked.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http
-
-import (
-	"bufio"
-	"io"
-	"log"
-	"os"
-	"strconv"
-)
-
-// NewChunkedWriter returns a new writer that translates writes into HTTP
-// "chunked" format before writing them to w. Closing the returned writer
-// sends the final 0-length chunk that marks the end of the stream.
-//
-// NewChunkedWriter is not needed by normal applications. The http
-// package adds chunking automatically if handlers don't set a
-// Content-Length header. Using NewChunkedWriter inside a handler
-// would result in double chunking or chunking with a Content-Length
-// length, both of which are wrong.
-func NewChunkedWriter(w io.Writer) io.WriteCloser {
-	if _, bad := w.(*response); bad {
-		log.Printf("warning: using NewChunkedWriter in an http.Handler; expect corrupt output")
-	}
-	return &chunkedWriter{w}
-}
-
-// Writing to ChunkedWriter translates to writing in HTTP chunked Transfer
-// Encoding wire format to the underlying Wire writer.
-type chunkedWriter struct {
-	Wire io.Writer
-}
-
-// Write the contents of data as one chunk to Wire.
-// NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
-// a bug since it does not check for success of io.WriteString
-func (cw *chunkedWriter) Write(data []byte) (n int, err os.Error) {
-
-	// Don't send 0-length data. It looks like EOF for chunked encoding.
-	if len(data) == 0 {
-		return 0, nil
-	}
-
-	head := strconv.Itob(len(data), 16) + "\r\n"
-
-	if _, err = io.WriteString(cw.Wire, head); err != nil {
-		return 0, err
-	}
-	if n, err = cw.Wire.Write(data); err != nil {
-		return
-	}
-	if n != len(data) {
-		err = io.ErrShortWrite
-		return
-	}
-	_, err = io.WriteString(cw.Wire, "\r\n")
-
-	return
-}
-
-func (cw *chunkedWriter) Close() os.Error {
-	_, err := io.WriteString(cw.Wire, "0\r\n")
-	return err
-}
-
-// NewChunkedReader returns a new reader that translates the data read from r
-// out of HTTP "chunked" format before returning it. 
-// The reader returns os.EOF when the final 0-length chunk is read.
-//
-// NewChunkedReader is not needed by normal applications. The http package
-// automatically decodes chunking when reading response bodies.
-func NewChunkedReader(r *bufio.Reader) io.Reader {
-	return &chunkedReader{r: r}
-}
diff --git a/src/pkg/http/client.go b/src/pkg/http/client.go
deleted file mode 100644
index 8997a07..0000000
--- a/src/pkg/http/client.go
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Primitive HTTP client. See RFC 2616.
-
-package http
-
-import (
-	"encoding/base64"
-	"fmt"
-	"io"
-	"os"
-	"strings"
-	"url"
-)
-
-// A Client is an HTTP client. Its zero value (DefaultClient) is a usable client
-// that uses DefaultTransport.
-//
-// The Client's Transport typically has internal state (cached
-// TCP connections), so Clients should be reused instead of created as
-// needed. Clients are safe for concurrent use by multiple goroutines.
-//
-// Client is not yet very configurable.
-type Client struct {
-	Transport RoundTripper // if nil, DefaultTransport is used
-
-	// If CheckRedirect is not nil, the client calls it before
-	// following an HTTP redirect. The arguments req and via
-	// are the upcoming request and the requests made already,
-	// oldest first. If CheckRedirect returns an error, the client
-	// returns that error instead of issue the Request req.
-	//
-	// If CheckRedirect is nil, the Client uses its default policy,
-	// which is to stop after 10 consecutive requests.
-	CheckRedirect func(req *Request, via []*Request) os.Error
-}
-
-// DefaultClient is the default Client and is used by Get, Head, and Post.
-var DefaultClient = &Client{}
-
-// RoundTripper is an interface representing the ability to execute a
-// single HTTP transaction, obtaining the Response for a given Request.
-//
-// A RoundTripper must be safe for concurrent use by multiple
-// goroutines.
-type RoundTripper interface {
-	// RoundTrip executes a single HTTP transaction, returning
-	// the Response for the request req.  RoundTrip should not
-	// attempt to interpret the response.  In particular,
-	// RoundTrip must return err == nil if it obtained a response,
-	// regardless of the response's HTTP status code.  A non-nil
-	// err should be reserved for failure to obtain a response.
-	// Similarly, RoundTrip should not attempt to handle
-	// higher-level protocol details such as redirects,
-	// authentication, or cookies.
-	//
-	// RoundTrip may modify the request. The request Headers field is
-	// guaranteed to be initialized.
-	RoundTrip(req *Request) (resp *Response, err os.Error)
-}
-
-// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
-// return true if the string includes a port.
-func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
-
-// Used in Send to implement io.ReadCloser by bundling together the
-// bufio.Reader through which we read the response, and the underlying
-// network connection.
-type readClose struct {
-	io.Reader
-	io.Closer
-}
-
-// Do sends an HTTP request and returns an HTTP response, following
-// policy (e.g. redirects, cookies, auth) as configured on the client.
-//
-// A non-nil response always contains a non-nil resp.Body.
-//
-// Callers should close resp.Body when done reading from it. If
-// resp.Body is not closed, the Client's underlying RoundTripper
-// (typically Transport) may not be able to re-use a persistent TCP
-// connection to the server for a subsequent "keep-alive" request.
-//
-// Generally Get, Post, or PostForm will be used instead of Do.
-func (c *Client) Do(req *Request) (resp *Response, err os.Error) {
-	if req.Method == "GET" || req.Method == "HEAD" {
-		return c.doFollowingRedirects(req)
-	}
-	return send(req, c.Transport)
-}
-
-// send issues an HTTP request.  Caller should close resp.Body when done reading from it.
-func send(req *Request, t RoundTripper) (resp *Response, err os.Error) {
-	if t == nil {
-		t = DefaultTransport
-		if t == nil {
-			err = os.NewError("no http.Client.Transport or http.DefaultTransport")
-			return
-		}
-	}
-
-	// Most the callers of send (Get, Post, et al) don't need
-	// Headers, leaving it uninitialized.  We guarantee to the
-	// Transport that this has been initialized, though.
-	if req.Header == nil {
-		req.Header = make(Header)
-	}
-
-	info := req.URL.RawUserinfo
-	if len(info) > 0 {
-		if req.Header == nil {
-			req.Header = make(Header)
-		}
-		req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(info)))
-	}
-	return t.RoundTrip(req)
-}
-
-// True if the specified HTTP status code is one for which the Get utility should
-// automatically redirect.
-func shouldRedirect(statusCode int) bool {
-	switch statusCode {
-	case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
-		return true
-	}
-	return false
-}
-
-// Get issues a GET to the specified URL.  If the response is one of the following
-// redirect codes, Get follows the redirect, up to a maximum of 10 redirects:
-//
-//    301 (Moved Permanently)
-//    302 (Found)
-//    303 (See Other)
-//    307 (Temporary Redirect)
-//
-// Caller should close r.Body when done reading from it.
-//
-// Get is a convenience wrapper around DefaultClient.Get.
-func Get(url string) (r *Response, err os.Error) {
-	return DefaultClient.Get(url)
-}
-
-// Get issues a GET to the specified URL.  If the response is one of the
-// following redirect codes, Get follows the redirect after calling the
-// Client's CheckRedirect function.
-//
-//    301 (Moved Permanently)
-//    302 (Found)
-//    303 (See Other)
-//    307 (Temporary Redirect)
-//
-// Caller should close r.Body when done reading from it.
-func (c *Client) Get(url string) (r *Response, err os.Error) {
-	req, err := NewRequest("GET", url, nil)
-	if err != nil {
-		return nil, err
-	}
-	return c.doFollowingRedirects(req)
-}
-
-func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err os.Error) {
-	// TODO: if/when we add cookie support, the redirected request shouldn't
-	// necessarily supply the same cookies as the original.
-	var base *url.URL
-	redirectChecker := c.CheckRedirect
-	if redirectChecker == nil {
-		redirectChecker = defaultCheckRedirect
-	}
-	var via []*Request
-
-	req := ireq
-	urlStr := "" // next relative or absolute URL to fetch (after first request)
-	for redirect := 0; ; redirect++ {
-		if redirect != 0 {
-			req = new(Request)
-			req.Method = ireq.Method
-			req.Header = make(Header)
-			req.URL, err = base.Parse(urlStr)
-			if err != nil {
-				break
-			}
-			if len(via) > 0 {
-				// Add the Referer header.
-				lastReq := via[len(via)-1]
-				if lastReq.URL.Scheme != "https" {
-					req.Header.Set("Referer", lastReq.URL.String())
-				}
-
-				err = redirectChecker(req, via)
-				if err != nil {
-					break
-				}
-			}
-		}
-
-		urlStr = req.URL.String()
-		if r, err = send(req, c.Transport); err != nil {
-			break
-		}
-		if shouldRedirect(r.StatusCode) {
-			r.Body.Close()
-			if urlStr = r.Header.Get("Location"); urlStr == "" {
-				err = os.NewError(fmt.Sprintf("%d response missing Location header", r.StatusCode))
-				break
-			}
-			base = req.URL
-			via = append(via, req)
-			continue
-		}
-		return
-	}
-
-	method := ireq.Method
-	err = &url.Error{method[0:1] + strings.ToLower(method[1:]), urlStr, err}
-	return
-}
-
-func defaultCheckRedirect(req *Request, via []*Request) os.Error {
-	if len(via) >= 10 {
-		return os.NewError("stopped after 10 redirects")
-	}
-	return nil
-}
-
-// Post issues a POST to the specified URL.
-//
-// Caller should close r.Body when done reading from it.
-//
-// Post is a wrapper around DefaultClient.Post
-func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) {
-	return DefaultClient.Post(url, bodyType, body)
-}
-
-// Post issues a POST to the specified URL.
-//
-// Caller should close r.Body when done reading from it.
-func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) {
-	req, err := NewRequest("POST", url, body)
-	if err != nil {
-		return nil, err
-	}
-	req.Header.Set("Content-Type", bodyType)
-	return send(req, c.Transport)
-}
-
-// PostForm issues a POST to the specified URL, 
-// with data's keys and values urlencoded as the request body.
-//
-// Caller should close r.Body when done reading from it.
-//
-// PostForm is a wrapper around DefaultClient.PostForm
-func PostForm(url string, data url.Values) (r *Response, err os.Error) {
-	return DefaultClient.PostForm(url, data)
-}
-
-// PostForm issues a POST to the specified URL, 
-// with data's keys and values urlencoded as the request body.
-//
-// Caller should close r.Body when done reading from it.
-func (c *Client) PostForm(url string, data url.Values) (r *Response, err os.Error) {
-	return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
-}
-
-// Head issues a HEAD to the specified URL.  If the response is one of the
-// following redirect codes, Head follows the redirect after calling the
-// Client's CheckRedirect function.
-//
-//    301 (Moved Permanently)
-//    302 (Found)
-//    303 (See Other)
-//    307 (Temporary Redirect)
-//
-// Head is a wrapper around DefaultClient.Head
-func Head(url string) (r *Response, err os.Error) {
-	return DefaultClient.Head(url)
-}
-
-// Head issues a HEAD to the specified URL.  If the response is one of the
-// following redirect codes, Head follows the redirect after calling the
-// Client's CheckRedirect function.
-//
-//    301 (Moved Permanently)
-//    302 (Found)
-//    303 (See Other)
-//    307 (Temporary Redirect)
-func (c *Client) Head(url string) (r *Response, err os.Error) {
-	req, err := NewRequest("HEAD", url, nil)
-	if err != nil {
-		return nil, err
-	}
-	return c.doFollowingRedirects(req)
-}
diff --git a/src/pkg/http/client_test.go b/src/pkg/http/client_test.go
deleted file mode 100644
index f22cce5..0000000
--- a/src/pkg/http/client_test.go
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Tests for client.go
-
-package http_test
-
-import (
-	"fmt"
-	. "http"
-	"http/httptest"
-	"io"
-	"io/ioutil"
-	"net"
-	"os"
-	"strconv"
-	"strings"
-	"testing"
-	"url"
-)
-
-var robotsTxtHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
-	w.Header().Set("Last-Modified", "sometime")
-	fmt.Fprintf(w, "User-agent: go\nDisallow: /something/")
-})
-
-func TestClient(t *testing.T) {
-	ts := httptest.NewServer(robotsTxtHandler)
-	defer ts.Close()
-
-	r, err := Get(ts.URL)
-	var b []byte
-	if err == nil {
-		b, err = ioutil.ReadAll(r.Body)
-		r.Body.Close()
-	}
-	if err != nil {
-		t.Error(err)
-	} else if s := string(b); !strings.HasPrefix(s, "User-agent:") {
-		t.Errorf("Incorrect page body (did not begin with User-agent): %q", s)
-	}
-}
-
-func TestClientHead(t *testing.T) {
-	ts := httptest.NewServer(robotsTxtHandler)
-	defer ts.Close()
-
-	r, err := Head(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if _, ok := r.Header["Last-Modified"]; !ok {
-		t.Error("Last-Modified header not found.")
-	}
-}
-
-type recordingTransport struct {
-	req *Request
-}
-
-func (t *recordingTransport) RoundTrip(req *Request) (resp *Response, err os.Error) {
-	t.req = req
-	return nil, os.NewError("dummy impl")
-}
-
-func TestGetRequestFormat(t *testing.T) {
-	tr := &recordingTransport{}
-	client := &Client{Transport: tr}
-	url := "http://dummy.faketld/"
-	client.Get(url) // Note: doesn't hit network
-	if tr.req.Method != "GET" {
-		t.Errorf("expected method %q; got %q", "GET", tr.req.Method)
-	}
-	if tr.req.URL.String() != url {
-		t.Errorf("expected URL %q; got %q", url, tr.req.URL.String())
-	}
-	if tr.req.Header == nil {
-		t.Errorf("expected non-nil request Header")
-	}
-}
-
-func TestPostRequestFormat(t *testing.T) {
-	tr := &recordingTransport{}
-	client := &Client{Transport: tr}
-
-	url := "http://dummy.faketld/"
-	json := `{"key":"value"}`
-	b := strings.NewReader(json)
-	client.Post(url, "application/json", b) // Note: doesn't hit network
-
-	if tr.req.Method != "POST" {
-		t.Errorf("got method %q, want %q", tr.req.Method, "POST")
-	}
-	if tr.req.URL.String() != url {
-		t.Errorf("got URL %q, want %q", tr.req.URL.String(), url)
-	}
-	if tr.req.Header == nil {
-		t.Fatalf("expected non-nil request Header")
-	}
-	if tr.req.Close {
-		t.Error("got Close true, want false")
-	}
-	if g, e := tr.req.ContentLength, int64(len(json)); g != e {
-		t.Errorf("got ContentLength %d, want %d", g, e)
-	}
-}
-
-func TestPostFormRequestFormat(t *testing.T) {
-	tr := &recordingTransport{}
-	client := &Client{Transport: tr}
-
-	urlStr := "http://dummy.faketld/"
-	form := make(url.Values)
-	form.Set("foo", "bar")
-	form.Add("foo", "bar2")
-	form.Set("bar", "baz")
-	client.PostForm(urlStr, form) // Note: doesn't hit network
-
-	if tr.req.Method != "POST" {
-		t.Errorf("got method %q, want %q", tr.req.Method, "POST")
-	}
-	if tr.req.URL.String() != urlStr {
-		t.Errorf("got URL %q, want %q", tr.req.URL.String(), urlStr)
-	}
-	if tr.req.Header == nil {
-		t.Fatalf("expected non-nil request Header")
-	}
-	if g, e := tr.req.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; g != e {
-		t.Errorf("got Content-Type %q, want %q", g, e)
-	}
-	if tr.req.Close {
-		t.Error("got Close true, want false")
-	}
-	expectedBody := "foo=bar&foo=bar2&bar=baz"
-	if g, e := tr.req.ContentLength, int64(len(expectedBody)); g != e {
-		t.Errorf("got ContentLength %d, want %d", g, e)
-	}
-	bodyb, err := ioutil.ReadAll(tr.req.Body)
-	if err != nil {
-		t.Fatalf("ReadAll on req.Body: %v", err)
-	}
-	if g := string(bodyb); g != expectedBody {
-		t.Errorf("got body %q, want %q", g, expectedBody)
-	}
-}
-
-func TestRedirects(t *testing.T) {
-	var ts *httptest.Server
-	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		n, _ := strconv.Atoi(r.FormValue("n"))
-		// Test Referer header. (7 is arbitrary position to test at)
-		if n == 7 {
-			if g, e := r.Referer(), ts.URL+"/?n=6"; e != g {
-				t.Errorf("on request ?n=7, expected referer of %q; got %q", e, g)
-			}
-		}
-		if n < 15 {
-			Redirect(w, r, fmt.Sprintf("/?n=%d", n+1), StatusFound)
-			return
-		}
-		fmt.Fprintf(w, "n=%d", n)
-	}))
-	defer ts.Close()
-
-	c := &Client{}
-	_, err := c.Get(ts.URL)
-	if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
-		t.Errorf("with default client Get, expected error %q, got %q", e, g)
-	}
-
-	// HEAD request should also have the ability to follow redirects.
-	_, err = c.Head(ts.URL)
-	if e, g := "Head /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
-		t.Errorf("with default client Head, expected error %q, got %q", e, g)
-	}
-
-	// Do should also follow redirects.
-	greq, _ := NewRequest("GET", ts.URL, nil)
-	_, err = c.Do(greq)
-	if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
-		t.Errorf("with default client Do, expected error %q, got %q", e, g)
-	}
-
-	var checkErr os.Error
-	var lastVia []*Request
-	c = &Client{CheckRedirect: func(_ *Request, via []*Request) os.Error {
-		lastVia = via
-		return checkErr
-	}}
-	res, err := c.Get(ts.URL)
-	finalUrl := res.Request.URL.String()
-	if e, g := "<nil>", fmt.Sprintf("%v", err); e != g {
-		t.Errorf("with custom client, expected error %q, got %q", e, g)
-	}
-	if !strings.HasSuffix(finalUrl, "/?n=15") {
-		t.Errorf("expected final url to end in /?n=15; got url %q", finalUrl)
-	}
-	if e, g := 15, len(lastVia); e != g {
-		t.Errorf("expected lastVia to have contained %d elements; got %d", e, g)
-	}
-
-	checkErr = os.NewError("no redirects allowed")
-	res, err = c.Get(ts.URL)
-	finalUrl = res.Request.URL.String()
-	if e, g := "Get /?n=1: no redirects allowed", fmt.Sprintf("%v", err); e != g {
-		t.Errorf("with redirects forbidden, expected error %q, got %q", e, g)
-	}
-}
-
-func TestStreamingGet(t *testing.T) {
-	say := make(chan string)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.(Flusher).Flush()
-		for str := range say {
-			w.Write([]byte(str))
-			w.(Flusher).Flush()
-		}
-	}))
-	defer ts.Close()
-
-	c := &Client{}
-	res, err := c.Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	var buf [10]byte
-	for _, str := range []string{"i", "am", "also", "known", "as", "comet"} {
-		say <- str
-		n, err := io.ReadFull(res.Body, buf[0:len(str)])
-		if err != nil {
-			t.Fatalf("ReadFull on %q: %v", str, err)
-		}
-		if n != len(str) {
-			t.Fatalf("Receiving %q, only read %d bytes", str, n)
-		}
-		got := string(buf[0:n])
-		if got != str {
-			t.Fatalf("Expected %q, got %q", str, got)
-		}
-	}
-	close(say)
-	_, err = io.ReadFull(res.Body, buf[0:1])
-	if err != os.EOF {
-		t.Fatalf("at end expected EOF, got %v", err)
-	}
-}
-
-type writeCountingConn struct {
-	net.Conn
-	count *int
-}
-
-func (c *writeCountingConn) Write(p []byte) (int, os.Error) {
-	*c.count++
-	return c.Conn.Write(p)
-}
-
-// TestClientWrites verifies that client requests are buffered and we
-// don't send a TCP packet per line of the http request + body.
-func TestClientWrites(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-	}))
-	defer ts.Close()
-
-	writes := 0
-	dialer := func(netz string, addr string) (net.Conn, os.Error) {
-		c, err := net.Dial(netz, addr)
-		if err == nil {
-			c = &writeCountingConn{c, &writes}
-		}
-		return c, err
-	}
-	c := &Client{Transport: &Transport{Dial: dialer}}
-
-	_, err := c.Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if writes != 1 {
-		t.Errorf("Get request did %d Write calls, want 1", writes)
-	}
-
-	writes = 0
-	_, err = c.PostForm(ts.URL, url.Values{"foo": {"bar"}})
-	if err != nil {
-		t.Fatal(err)
-	}
-	if writes != 1 {
-		t.Errorf("Post request did %d Write calls, want 1", writes)
-	}
-}
diff --git a/src/pkg/http/cookie.go b/src/pkg/http/cookie.go
deleted file mode 100644
index fe70431..0000000
--- a/src/pkg/http/cookie.go
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http
-
-import (
-	"bytes"
-	"fmt"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// This implementation is done according to RFC 6265:
-//
-//    http://tools.ietf.org/html/rfc6265
-
-// A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an
-// HTTP response or the Cookie header of an HTTP request.
-type Cookie struct {
-	Name       string
-	Value      string
-	Path       string
-	Domain     string
-	Expires    time.Time
-	RawExpires string
-
-	// MaxAge=0 means no 'Max-Age' attribute specified. 
-	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
-	// MaxAge>0 means Max-Age attribute present and given in seconds
-	MaxAge   int
-	Secure   bool
-	HttpOnly bool
-	Raw      string
-	Unparsed []string // Raw text of unparsed attribute-value pairs
-}
-
-// readSetCookies parses all "Set-Cookie" values from
-// the header h and returns the successfully parsed Cookies.
-func readSetCookies(h Header) []*Cookie {
-	cookies := []*Cookie{}
-	for _, line := range h["Set-Cookie"] {
-		parts := strings.Split(strings.TrimSpace(line), ";")
-		if len(parts) == 1 && parts[0] == "" {
-			continue
-		}
-		parts[0] = strings.TrimSpace(parts[0])
-		j := strings.Index(parts[0], "=")
-		if j < 0 {
-			continue
-		}
-		name, value := parts[0][:j], parts[0][j+1:]
-		if !isCookieNameValid(name) {
-			continue
-		}
-		value, success := parseCookieValue(value)
-		if !success {
-			continue
-		}
-		c := &Cookie{
-			Name:  name,
-			Value: value,
-			Raw:   line,
-		}
-		for i := 1; i < len(parts); i++ {
-			parts[i] = strings.TrimSpace(parts[i])
-			if len(parts[i]) == 0 {
-				continue
-			}
-
-			attr, val := parts[i], ""
-			if j := strings.Index(attr, "="); j >= 0 {
-				attr, val = attr[:j], attr[j+1:]
-			}
-			lowerAttr := strings.ToLower(attr)
-			parseCookieValueFn := parseCookieValue
-			if lowerAttr == "expires" {
-				parseCookieValueFn = parseCookieExpiresValue
-			}
-			val, success = parseCookieValueFn(val)
-			if !success {
-				c.Unparsed = append(c.Unparsed, parts[i])
-				continue
-			}
-			switch lowerAttr {
-			case "secure":
-				c.Secure = true
-				continue
-			case "httponly":
-				c.HttpOnly = true
-				continue
-			case "domain":
-				c.Domain = val
-				// TODO: Add domain parsing
-				continue
-			case "max-age":
-				secs, err := strconv.Atoi(val)
-				if err != nil || secs < 0 || secs != 0 && val[0] == '0' {
-					break
-				}
-				if secs <= 0 {
-					c.MaxAge = -1
-				} else {
-					c.MaxAge = secs
-				}
-				continue
-			case "expires":
-				c.RawExpires = val
-				exptime, err := time.Parse(time.RFC1123, val)
-				if err != nil {
-					exptime, err = time.Parse("Mon, 02-Jan-2006 15:04:05 MST", val)
-					if err != nil {
-						c.Expires = time.Time{}
-						break
-					}
-				}
-				c.Expires = *exptime
-				continue
-			case "path":
-				c.Path = val
-				// TODO: Add path parsing
-				continue
-			}
-			c.Unparsed = append(c.Unparsed, parts[i])
-		}
-		cookies = append(cookies, c)
-	}
-	return cookies
-}
-
-// SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers.
-func SetCookie(w ResponseWriter, cookie *Cookie) {
-	w.Header().Add("Set-Cookie", cookie.String())
-}
-
-// String returns the serialization of the cookie for use in a Cookie
-// header (if only Name and Value are set) or a Set-Cookie response
-// header (if other fields are set).
-func (c *Cookie) String() string {
-	var b bytes.Buffer
-	fmt.Fprintf(&b, "%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
-	if len(c.Path) > 0 {
-		fmt.Fprintf(&b, "; Path=%s", sanitizeValue(c.Path))
-	}
-	if len(c.Domain) > 0 {
-		fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(c.Domain))
-	}
-	if len(c.Expires.Zone) > 0 {
-		fmt.Fprintf(&b, "; Expires=%s", c.Expires.Format(time.RFC1123))
-	}
-	if c.MaxAge > 0 {
-		fmt.Fprintf(&b, "; Max-Age=%d", c.MaxAge)
-	} else if c.MaxAge < 0 {
-		fmt.Fprintf(&b, "; Max-Age=0")
-	}
-	if c.HttpOnly {
-		fmt.Fprintf(&b, "; HttpOnly")
-	}
-	if c.Secure {
-		fmt.Fprintf(&b, "; Secure")
-	}
-	return b.String()
-}
-
-// readCookies parses all "Cookie" values from the header h and
-// returns the successfully parsed Cookies.
-//
-// if filter isn't empty, only cookies of that name are returned
-func readCookies(h Header, filter string) []*Cookie {
-	cookies := []*Cookie{}
-	lines, ok := h["Cookie"]
-	if !ok {
-		return cookies
-	}
-
-	for _, line := range lines {
-		parts := strings.Split(strings.TrimSpace(line), ";")
-		if len(parts) == 1 && parts[0] == "" {
-			continue
-		}
-		// Per-line attributes
-		parsedPairs := 0
-		for i := 0; i < len(parts); i++ {
-			parts[i] = strings.TrimSpace(parts[i])
-			if len(parts[i]) == 0 {
-				continue
-			}
-			name, val := parts[i], ""
-			if j := strings.Index(name, "="); j >= 0 {
-				name, val = name[:j], name[j+1:]
-			}
-			if !isCookieNameValid(name) {
-				continue
-			}
-			if filter != "" && filter != name {
-				continue
-			}
-			val, success := parseCookieValue(val)
-			if !success {
-				continue
-			}
-			cookies = append(cookies, &Cookie{Name: name, Value: val})
-			parsedPairs++
-		}
-	}
-	return cookies
-}
-
-func sanitizeName(n string) string {
-	n = strings.Replace(n, "\n", "-", -1)
-	n = strings.Replace(n, "\r", "-", -1)
-	return n
-}
-
-func sanitizeValue(v string) string {
-	v = strings.Replace(v, "\n", " ", -1)
-	v = strings.Replace(v, "\r", " ", -1)
-	v = strings.Replace(v, ";", " ", -1)
-	return v
-}
-
-func unquoteCookieValue(v string) string {
-	if len(v) > 1 && v[0] == '"' && v[len(v)-1] == '"' {
-		return v[1 : len(v)-1]
-	}
-	return v
-}
-
-func isCookieByte(c byte) bool {
-	switch {
-	case c == 0x21, 0x23 <= c && c <= 0x2b, 0x2d <= c && c <= 0x3a,
-		0x3c <= c && c <= 0x5b, 0x5d <= c && c <= 0x7e:
-		return true
-	}
-	return false
-}
-
-func isCookieExpiresByte(c byte) (ok bool) {
-	return isCookieByte(c) || c == ',' || c == ' '
-}
-
-func parseCookieValue(raw string) (string, bool) {
-	return parseCookieValueUsing(raw, isCookieByte)
-}
-
-func parseCookieExpiresValue(raw string) (string, bool) {
-	return parseCookieValueUsing(raw, isCookieExpiresByte)
-}
-
-func parseCookieValueUsing(raw string, validByte func(byte) bool) (string, bool) {
-	raw = unquoteCookieValue(raw)
-	for i := 0; i < len(raw); i++ {
-		if !validByte(raw[i]) {
-			return "", false
-		}
-	}
-	return raw, true
-}
-
-func isCookieNameValid(raw string) bool {
-	for _, c := range raw {
-		if !isToken(byte(c)) {
-			return false
-		}
-	}
-	return true
-}
diff --git a/src/pkg/http/cookie_test.go b/src/pkg/http/cookie_test.go
deleted file mode 100644
index 5de6aab..0000000
--- a/src/pkg/http/cookie_test.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2010 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 http
-
-import (
-	"fmt"
-	"json"
-	"os"
-	"reflect"
-	"testing"
-	"time"
-)
-
-var writeSetCookiesTests = []struct {
-	Cookie *Cookie
-	Raw    string
-}{
-	{
-		&Cookie{Name: "cookie-1", Value: "v$1"},
-		"cookie-1=v$1",
-	},
-	{
-		&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
-		"cookie-2=two; Max-Age=3600",
-	},
-	{
-		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
-		"cookie-3=three; Domain=.example.com",
-	},
-	{
-		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
-		"cookie-4=four; Path=/restricted/",
-	},
-}
-
-func TestWriteSetCookies(t *testing.T) {
-	for i, tt := range writeSetCookiesTests {
-		if g, e := tt.Cookie.String(), tt.Raw; g != e {
-			t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, e, g)
-			continue
-		}
-	}
-}
-
-type headerOnlyResponseWriter Header
-
-func (ho headerOnlyResponseWriter) Header() Header {
-	return Header(ho)
-}
-
-func (ho headerOnlyResponseWriter) Write([]byte) (int, os.Error) {
-	panic("NOIMPL")
-}
-
-func (ho headerOnlyResponseWriter) WriteHeader(int) {
-	panic("NOIMPL")
-}
-
-func TestSetCookie(t *testing.T) {
-	m := make(Header)
-	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-1", Value: "one", Path: "/restricted/"})
-	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600})
-	if l := len(m["Set-Cookie"]); l != 2 {
-		t.Fatalf("expected %d cookies, got %d", 2, l)
-	}
-	if g, e := m["Set-Cookie"][0], "cookie-1=one; Path=/restricted/"; g != e {
-		t.Errorf("cookie #1: want %q, got %q", e, g)
-	}
-	if g, e := m["Set-Cookie"][1], "cookie-2=two; Max-Age=3600"; g != e {
-		t.Errorf("cookie #2: want %q, got %q", e, g)
-	}
-}
-
-var addCookieTests = []struct {
-	Cookies []*Cookie
-	Raw     string
-}{
-	{
-		[]*Cookie{},
-		"",
-	},
-	{
-		[]*Cookie{&Cookie{Name: "cookie-1", Value: "v$1"}},
-		"cookie-1=v$1",
-	},
-	{
-		[]*Cookie{
-			&Cookie{Name: "cookie-1", Value: "v$1"},
-			&Cookie{Name: "cookie-2", Value: "v$2"},
-			&Cookie{Name: "cookie-3", Value: "v$3"},
-		},
-		"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
-	},
-}
-
-func TestAddCookie(t *testing.T) {
-	for i, tt := range addCookieTests {
-		req, _ := NewRequest("GET", "http://example.com/", nil)
-		for _, c := range tt.Cookies {
-			req.AddCookie(c)
-		}
-		if g := req.Header.Get("Cookie"); g != tt.Raw {
-			t.Errorf("Test %d:\nwant: %s\n got: %s\n", i, tt.Raw, g)
-			continue
-		}
-	}
-}
-
-var readSetCookiesTests = []struct {
-	Header  Header
-	Cookies []*Cookie
-}{
-	{
-		Header{"Set-Cookie": {"Cookie-1=v$1"}},
-		[]*Cookie{&Cookie{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
-	},
-	{
-		Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
-		[]*Cookie{&Cookie{
-			Name:       "NID",
-			Value:      "99=YsDT5i3E-CXax-",
-			Path:       "/",
-			Domain:     ".google.ch",
-			HttpOnly:   true,
-			Expires:    time.Time{Year: 2011, Month: 11, Day: 23, Hour: 1, Minute: 5, Second: 3, ZoneOffset: 0, Zone: "GMT"},
-			RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
-			Raw:        "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
-		}},
-	},
-}
-
-func toJSON(v interface{}) string {
-	b, err := json.Marshal(v)
-	if err != nil {
-		return fmt.Sprintf("%#v", v)
-	}
-	return string(b)
-}
-
-func TestReadSetCookies(t *testing.T) {
-	for i, tt := range readSetCookiesTests {
-		for n := 0; n < 2; n++ { // to verify readSetCookies doesn't mutate its input
-			c := readSetCookies(tt.Header)
-			if !reflect.DeepEqual(c, tt.Cookies) {
-				t.Errorf("#%d readSetCookies: have\n%s\nwant\n%s\n", i, toJSON(c), toJSON(tt.Cookies))
-				continue
-			}
-		}
-	}
-}
-
-var readCookiesTests = []struct {
-	Header  Header
-	Filter  string
-	Cookies []*Cookie
-}{
-	{
-		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
-		"",
-		[]*Cookie{
-			&Cookie{Name: "Cookie-1", Value: "v$1"},
-			&Cookie{Name: "c2", Value: "v2"},
-		},
-	},
-	{
-		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
-		"c2",
-		[]*Cookie{
-			&Cookie{Name: "c2", Value: "v2"},
-		},
-	},
-	{
-		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
-		"",
-		[]*Cookie{
-			&Cookie{Name: "Cookie-1", Value: "v$1"},
-			&Cookie{Name: "c2", Value: "v2"},
-		},
-	},
-	{
-		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
-		"c2",
-		[]*Cookie{
-			&Cookie{Name: "c2", Value: "v2"},
-		},
-	},
-}
-
-func TestReadCookies(t *testing.T) {
-	for i, tt := range readCookiesTests {
-		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input                                                  
-			c := readCookies(tt.Header, tt.Filter)
-			if !reflect.DeepEqual(c, tt.Cookies) {
-				t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
-				continue
-			}
-		}
-	}
-}
diff --git a/src/pkg/http/dump.go b/src/pkg/http/dump.go
deleted file mode 100644
index f78df57..0000000
--- a/src/pkg/http/dump.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http
-
-import (
-	"bytes"
-	"io"
-	"io/ioutil"
-	"os"
-)
-
-// One of the copies, say from b to r2, could be avoided by using a more
-// elaborate trick where the other copy is made during Request/Response.Write.
-// This would complicate things too much, given that these functions are for
-// debugging only.
-func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err os.Error) {
-	var buf bytes.Buffer
-	if _, err = buf.ReadFrom(b); err != nil {
-		return nil, nil, err
-	}
-	if err = b.Close(); err != nil {
-		return nil, nil, err
-	}
-	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewBuffer(buf.Bytes())), nil
-}
-
-// DumpRequest returns the wire representation of req,
-// optionally including the request body, for debugging.
-// DumpRequest is semantically a no-op, but in order to
-// dump the body, it reads the body data into memory and
-// changes req.Body to refer to the in-memory copy.
-// The documentation for Request.Write details which fields
-// of req are used.
-func DumpRequest(req *Request, body bool) (dump []byte, err os.Error) {
-	var b bytes.Buffer
-	save := req.Body
-	if !body || req.Body == nil {
-		req.Body = nil
-	} else {
-		save, req.Body, err = drainBody(req.Body)
-		if err != nil {
-			return
-		}
-	}
-	err = req.dumpWrite(&b)
-	req.Body = save
-	if err != nil {
-		return
-	}
-	dump = b.Bytes()
-	return
-}
-
-// DumpResponse is like DumpRequest but dumps a response.
-func DumpResponse(resp *Response, body bool) (dump []byte, err os.Error) {
-	var b bytes.Buffer
-	save := resp.Body
-	savecl := resp.ContentLength
-	if !body || resp.Body == nil {
-		resp.Body = nil
-		resp.ContentLength = 0
-	} else {
-		save, resp.Body, err = drainBody(resp.Body)
-		if err != nil {
-			return
-		}
-	}
-	err = resp.Write(&b)
-	resp.Body = save
-	resp.ContentLength = savecl
-	if err != nil {
-		return
-	}
-	dump = b.Bytes()
-	return
-}
diff --git a/src/pkg/http/export_test.go b/src/pkg/http/export_test.go
deleted file mode 100644
index 3fe6586..0000000
--- a/src/pkg/http/export_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2011 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.
-
-// Bridge package to expose http internals to tests in the http_test
-// package.
-
-package http
-
-func (t *Transport) IdleConnKeysForTesting() (keys []string) {
-	keys = make([]string, 0)
-	t.lk.Lock()
-	defer t.lk.Unlock()
-	if t.idleConn == nil {
-		return
-	}
-	for key := range t.idleConn {
-		keys = append(keys, key)
-	}
-	return
-}
-
-func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
-	t.lk.Lock()
-	defer t.lk.Unlock()
-	if t.idleConn == nil {
-		return 0
-	}
-	conns, ok := t.idleConn[cacheKey]
-	if !ok {
-		return 0
-	}
-	return len(conns)
-}
-
-func NewTestTimeoutHandler(handler Handler, ch <-chan int64) Handler {
-	f := func() <-chan int64 {
-		return ch
-	}
-	return &timeoutHandler{handler, f, ""}
-}
diff --git a/src/pkg/http/fcgi/Makefile b/src/pkg/http/fcgi/Makefile
deleted file mode 100644
index bc01cde..0000000
--- a/src/pkg/http/fcgi/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=http/fcgi
-GOFILES=\
-	child.go\
-	fcgi.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/http/fcgi/child.go b/src/pkg/http/fcgi/child.go
deleted file mode 100644
index 1971882..0000000
--- a/src/pkg/http/fcgi/child.go
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2011 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 fcgi
-
-// This file implements FastCGI from the perspective of a child process.
-
-import (
-	"fmt"
-	"http"
-	"http/cgi"
-	"io"
-	"net"
-	"os"
-	"time"
-)
-
-// request holds the state for an in-progress request. As soon as it's complete,
-// it's converted to an http.Request.
-type request struct {
-	pw        *io.PipeWriter
-	reqId     uint16
-	params    map[string]string
-	buf       [1024]byte
-	rawParams []byte
-	keepConn  bool
-}
-
-func newRequest(reqId uint16, flags uint8) *request {
-	r := &request{
-		reqId:    reqId,
-		params:   map[string]string{},
-		keepConn: flags&flagKeepConn != 0,
-	}
-	r.rawParams = r.buf[:0]
-	return r
-}
-
-// parseParams reads an encoded []byte into Params.
-func (r *request) parseParams() {
-	text := r.rawParams
-	r.rawParams = nil
-	for len(text) > 0 {
-		keyLen, n := readSize(text)
-		if n == 0 {
-			return
-		}
-		text = text[n:]
-		valLen, n := readSize(text)
-		if n == 0 {
-			return
-		}
-		text = text[n:]
-		key := readString(text, keyLen)
-		text = text[keyLen:]
-		val := readString(text, valLen)
-		text = text[valLen:]
-		r.params[key] = val
-	}
-}
-
-// response implements http.ResponseWriter.
-type response struct {
-	req         *request
-	header      http.Header
-	w           *bufWriter
-	wroteHeader bool
-}
-
-func newResponse(c *child, req *request) *response {
-	return &response{
-		req:    req,
-		header: http.Header{},
-		w:      newWriter(c.conn, typeStdout, req.reqId),
-	}
-}
-
-func (r *response) Header() http.Header {
-	return r.header
-}
-
-func (r *response) Write(data []byte) (int, os.Error) {
-	if !r.wroteHeader {
-		r.WriteHeader(http.StatusOK)
-	}
-	return r.w.Write(data)
-}
-
-func (r *response) WriteHeader(code int) {
-	if r.wroteHeader {
-		return
-	}
-	r.wroteHeader = true
-	if code == http.StatusNotModified {
-		// Must not have body.
-		r.header.Del("Content-Type")
-		r.header.Del("Content-Length")
-		r.header.Del("Transfer-Encoding")
-	} else if r.header.Get("Content-Type") == "" {
-		r.header.Set("Content-Type", "text/html; charset=utf-8")
-	}
-
-	if r.header.Get("Date") == "" {
-		r.header.Set("Date", time.UTC().Format(http.TimeFormat))
-	}
-
-	fmt.Fprintf(r.w, "Status: %d %s\r\n", code, http.StatusText(code))
-	r.header.Write(r.w)
-	r.w.WriteString("\r\n")
-}
-
-func (r *response) Flush() {
-	if !r.wroteHeader {
-		r.WriteHeader(http.StatusOK)
-	}
-	r.w.Flush()
-}
-
-func (r *response) Close() os.Error {
-	r.Flush()
-	return r.w.Close()
-}
-
-type child struct {
-	conn    *conn
-	handler http.Handler
-}
-
-func newChild(rwc net.Conn, handler http.Handler) *child {
-	return &child{newConn(rwc), handler}
-}
-
-func (c *child) serve() {
-	requests := map[uint16]*request{}
-	defer c.conn.Close()
-	var rec record
-	var br beginRequest
-	for {
-		if err := rec.read(c.conn.rwc); err != nil {
-			return
-		}
-
-		req, ok := requests[rec.h.Id]
-		if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
-			// The spec says to ignore unknown request IDs.
-			continue
-		}
-		if ok && rec.h.Type == typeBeginRequest {
-			// The server is trying to begin a request with the same ID
-			// as an in-progress request. This is an error.
-			return
-		}
-
-		switch rec.h.Type {
-		case typeBeginRequest:
-			if err := br.read(rec.content()); err != nil {
-				return
-			}
-			if br.role != roleResponder {
-				c.conn.writeEndRequest(rec.h.Id, 0, statusUnknownRole)
-				break
-			}
-			requests[rec.h.Id] = newRequest(rec.h.Id, br.flags)
-		case typeParams:
-			// NOTE(eds): Technically a key-value pair can straddle the boundary
-			// between two packets. We buffer until we've received all parameters.
-			if len(rec.content()) > 0 {
-				req.rawParams = append(req.rawParams, rec.content()...)
-				break
-			}
-			req.parseParams()
-		case typeStdin:
-			content := rec.content()
-			if req.pw == nil {
-				var body io.ReadCloser
-				if len(content) > 0 {
-					// body could be an io.LimitReader, but it shouldn't matter
-					// as long as both sides are behaving.
-					body, req.pw = io.Pipe()
-				}
-				go c.serveRequest(req, body)
-			}
-			if len(content) > 0 {
-				// TODO(eds): This blocks until the handler reads from the pipe.
-				// If the handler takes a long time, it might be a problem.
-				req.pw.Write(content)
-			} else if req.pw != nil {
-				req.pw.Close()
-			}
-		case typeGetValues:
-			values := map[string]string{"FCGI_MPXS_CONNS": "1"}
-			c.conn.writePairs(0, typeGetValuesResult, values)
-		case typeData:
-			// If the filter role is implemented, read the data stream here.
-		case typeAbortRequest:
-			requests[rec.h.Id] = nil, false
-			c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
-			if !req.keepConn {
-				// connection will close upon return
-				return
-			}
-		default:
-			b := make([]byte, 8)
-			b[0] = rec.h.Type
-			c.conn.writeRecord(typeUnknownType, 0, b)
-		}
-	}
-}
-
-func (c *child) serveRequest(req *request, body io.ReadCloser) {
-	r := newResponse(c, req)
-	httpReq, err := cgi.RequestFromMap(req.params)
-	if err != nil {
-		// there was an error reading the request
-		r.WriteHeader(http.StatusInternalServerError)
-		c.conn.writeRecord(typeStderr, req.reqId, []byte(err.String()))
-	} else {
-		httpReq.Body = body
-		c.handler.ServeHTTP(r, httpReq)
-	}
-	if body != nil {
-		body.Close()
-	}
-	r.Close()
-	c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
-	if !req.keepConn {
-		c.conn.Close()
-	}
-}
-
-// Serve accepts incoming FastCGI connections on the listener l, creating a new
-// service thread for each. The service threads read requests and then call handler
-// to reply to them.
-// If l is nil, Serve accepts connections on stdin.
-// If handler is nil, http.DefaultServeMux is used.
-func Serve(l net.Listener, handler http.Handler) os.Error {
-	if l == nil {
-		var err os.Error
-		l, err = net.FileListener(os.Stdin)
-		if err != nil {
-			return err
-		}
-		defer l.Close()
-	}
-	if handler == nil {
-		handler = http.DefaultServeMux
-	}
-	for {
-		rw, err := l.Accept()
-		if err != nil {
-			return err
-		}
-		c := newChild(rw, handler)
-		go c.serve()
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/http/fcgi/fcgi.go b/src/pkg/http/fcgi/fcgi.go
deleted file mode 100644
index 8e2e1cd..0000000
--- a/src/pkg/http/fcgi/fcgi.go
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright 2011 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 fcgi implements the FastCGI protocol.
-// Currently only the responder role is supported.
-// The protocol is defined at http://www.fastcgi.com/drupal/node/6?q=node/22
-package fcgi
-
-// This file defines the raw protocol and some utilities used by the child and
-// the host.
-
-import (
-	"bufio"
-	"bytes"
-	"encoding/binary"
-	"io"
-	"os"
-	"sync"
-)
-
-const (
-	// Packet Types
-	typeBeginRequest = iota + 1
-	typeAbortRequest
-	typeEndRequest
-	typeParams
-	typeStdin
-	typeStdout
-	typeStderr
-	typeData
-	typeGetValues
-	typeGetValuesResult
-	typeUnknownType
-)
-
-// keep the connection between web-server and responder open after request
-const flagKeepConn = 1
-
-const (
-	maxWrite = 65535 // maximum record body
-	maxPad   = 255
-)
-
-const (
-	roleResponder = iota + 1 // only Responders are implemented.
-	roleAuthorizer
-	roleFilter
-)
-
-const (
-	statusRequestComplete = iota
-	statusCantMultiplex
-	statusOverloaded
-	statusUnknownRole
-)
-
-const headerLen = 8
-
-type header struct {
-	Version       uint8
-	Type          uint8
-	Id            uint16
-	ContentLength uint16
-	PaddingLength uint8
-	Reserved      uint8
-}
-
-type beginRequest struct {
-	role     uint16
-	flags    uint8
-	reserved [5]uint8
-}
-
-func (br *beginRequest) read(content []byte) os.Error {
-	if len(content) != 8 {
-		return os.NewError("fcgi: invalid begin request record")
-	}
-	br.role = binary.BigEndian.Uint16(content)
-	br.flags = content[2]
-	return nil
-}
-
-// for padding so we don't have to allocate all the time
-// not synchronized because we don't care what the contents are
-var pad [maxPad]byte
-
-func (h *header) init(recType uint8, reqId uint16, contentLength int) {
-	h.Version = 1
-	h.Type = recType
-	h.Id = reqId
-	h.ContentLength = uint16(contentLength)
-	h.PaddingLength = uint8(-contentLength & 7)
-}
-
-// conn sends records over rwc
-type conn struct {
-	mutex sync.Mutex
-	rwc   io.ReadWriteCloser
-
-	// to avoid allocations
-	buf bytes.Buffer
-	h   header
-}
-
-func newConn(rwc io.ReadWriteCloser) *conn {
-	return &conn{rwc: rwc}
-}
-
-func (c *conn) Close() os.Error {
-	c.mutex.Lock()
-	defer c.mutex.Unlock()
-	return c.rwc.Close()
-}
-
-type record struct {
-	h   header
-	buf [maxWrite + maxPad]byte
-}
-
-func (rec *record) read(r io.Reader) (err os.Error) {
-	if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
-		return err
-	}
-	if rec.h.Version != 1 {
-		return os.NewError("fcgi: invalid header version")
-	}
-	n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
-	if _, err = io.ReadFull(r, rec.buf[:n]); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (r *record) content() []byte {
-	return r.buf[:r.h.ContentLength]
-}
-
-// writeRecord writes and sends a single record.
-func (c *conn) writeRecord(recType uint8, reqId uint16, b []byte) os.Error {
-	c.mutex.Lock()
-	defer c.mutex.Unlock()
-	c.buf.Reset()
-	c.h.init(recType, reqId, len(b))
-	if err := binary.Write(&c.buf, binary.BigEndian, c.h); err != nil {
-		return err
-	}
-	if _, err := c.buf.Write(b); err != nil {
-		return err
-	}
-	if _, err := c.buf.Write(pad[:c.h.PaddingLength]); err != nil {
-		return err
-	}
-	_, err := c.rwc.Write(c.buf.Bytes())
-	return err
-}
-
-func (c *conn) writeBeginRequest(reqId uint16, role uint16, flags uint8) os.Error {
-	b := [8]byte{byte(role >> 8), byte(role), flags}
-	return c.writeRecord(typeBeginRequest, reqId, b[:])
-}
-
-func (c *conn) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) os.Error {
-	b := make([]byte, 8)
-	binary.BigEndian.PutUint32(b, uint32(appStatus))
-	b[4] = protocolStatus
-	return c.writeRecord(typeEndRequest, reqId, b)
-}
-
-func (c *conn) writePairs(recType uint8, reqId uint16, pairs map[string]string) os.Error {
-	w := newWriter(c, recType, reqId)
-	b := make([]byte, 8)
-	for k, v := range pairs {
-		n := encodeSize(b, uint32(len(k)))
-		n += encodeSize(b[n:], uint32(len(k)))
-		if _, err := w.Write(b[:n]); err != nil {
-			return err
-		}
-		if _, err := w.WriteString(k); err != nil {
-			return err
-		}
-		if _, err := w.WriteString(v); err != nil {
-			return err
-		}
-	}
-	w.Close()
-	return nil
-}
-
-func readSize(s []byte) (uint32, int) {
-	if len(s) == 0 {
-		return 0, 0
-	}
-	size, n := uint32(s[0]), 1
-	if size&(1<<7) != 0 {
-		if len(s) < 4 {
-			return 0, 0
-		}
-		n = 4
-		size = binary.BigEndian.Uint32(s)
-		size &^= 1 << 31
-	}
-	return size, n
-}
-
-func readString(s []byte, size uint32) string {
-	if size > uint32(len(s)) {
-		return ""
-	}
-	return string(s[:size])
-}
-
-func encodeSize(b []byte, size uint32) int {
-	if size > 127 {
-		size |= 1 << 31
-		binary.BigEndian.PutUint32(b, size)
-		return 4
-	}
-	b[0] = byte(size)
-	return 1
-}
-
-// bufWriter encapsulates bufio.Writer but also closes the underlying stream when
-// Closed.
-type bufWriter struct {
-	closer io.Closer
-	*bufio.Writer
-}
-
-func (w *bufWriter) Close() os.Error {
-	if err := w.Writer.Flush(); err != nil {
-		w.closer.Close()
-		return err
-	}
-	return w.closer.Close()
-}
-
-func newWriter(c *conn, recType uint8, reqId uint16) *bufWriter {
-	s := &streamWriter{c: c, recType: recType, reqId: reqId}
-	w, _ := bufio.NewWriterSize(s, maxWrite)
-	return &bufWriter{s, w}
-}
-
-// streamWriter abstracts out the separation of a stream into discrete records.
-// It only writes maxWrite bytes at a time.
-type streamWriter struct {
-	c       *conn
-	recType uint8
-	reqId   uint16
-}
-
-func (w *streamWriter) Write(p []byte) (int, os.Error) {
-	nn := 0
-	for len(p) > 0 {
-		n := len(p)
-		if n > maxWrite {
-			n = maxWrite
-		}
-		if err := w.c.writeRecord(w.recType, w.reqId, p[:n]); err != nil {
-			return nn, err
-		}
-		nn += n
-		p = p[n:]
-	}
-	return nn, nil
-}
-
-func (w *streamWriter) Close() os.Error {
-	// send empty record to close the stream
-	return w.c.writeRecord(w.recType, w.reqId, nil)
-}
diff --git a/src/pkg/http/fcgi/fcgi_test.go b/src/pkg/http/fcgi/fcgi_test.go
deleted file mode 100644
index 5c8e46b..0000000
--- a/src/pkg/http/fcgi/fcgi_test.go
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2011 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 fcgi
-
-import (
-	"bytes"
-	"io"
-	"os"
-	"testing"
-)
-
-var sizeTests = []struct {
-	size  uint32
-	bytes []byte
-}{
-	{0, []byte{0x00}},
-	{127, []byte{0x7F}},
-	{128, []byte{0x80, 0x00, 0x00, 0x80}},
-	{1000, []byte{0x80, 0x00, 0x03, 0xE8}},
-	{33554431, []byte{0x81, 0xFF, 0xFF, 0xFF}},
-}
-
-func TestSize(t *testing.T) {
-	b := make([]byte, 4)
-	for i, test := range sizeTests {
-		n := encodeSize(b, test.size)
-		if !bytes.Equal(b[:n], test.bytes) {
-			t.Errorf("%d expected %x, encoded %x", i, test.bytes, b)
-		}
-		size, n := readSize(test.bytes)
-		if size != test.size {
-			t.Errorf("%d expected %d, read %d", i, test.size, size)
-		}
-		if len(test.bytes) != n {
-			t.Errorf("%d did not consume all the bytes", i)
-		}
-	}
-}
-
-var streamTests = []struct {
-	desc    string
-	recType uint8
-	reqId   uint16
-	content []byte
-	raw     []byte
-}{
-	{"single record", typeStdout, 1, nil,
-		[]byte{1, typeStdout, 0, 1, 0, 0, 0, 0},
-	},
-	// this data will have to be split into two records
-	{"two records", typeStdin, 300, make([]byte, 66000),
-		bytes.Join([][]byte{
-			// header for the first record
-			{1, typeStdin, 0x01, 0x2C, 0xFF, 0xFF, 1, 0},
-			make([]byte, 65536),
-			// header for the second
-			{1, typeStdin, 0x01, 0x2C, 0x01, 0xD1, 7, 0},
-			make([]byte, 472),
-			// header for the empty record
-			{1, typeStdin, 0x01, 0x2C, 0, 0, 0, 0},
-		},
-			nil),
-	},
-}
-
-type nilCloser struct {
-	io.ReadWriter
-}
-
-func (c *nilCloser) Close() os.Error { return nil }
-
-func TestStreams(t *testing.T) {
-	var rec record
-outer:
-	for _, test := range streamTests {
-		buf := bytes.NewBuffer(test.raw)
-		var content []byte
-		for buf.Len() > 0 {
-			if err := rec.read(buf); err != nil {
-				t.Errorf("%s: error reading record: %v", test.desc, err)
-				continue outer
-			}
-			content = append(content, rec.content()...)
-		}
-		if rec.h.Type != test.recType {
-			t.Errorf("%s: got type %d expected %d", test.desc, rec.h.Type, test.recType)
-			continue
-		}
-		if rec.h.Id != test.reqId {
-			t.Errorf("%s: got request ID %d expected %d", test.desc, rec.h.Id, test.reqId)
-			continue
-		}
-		if !bytes.Equal(content, test.content) {
-			t.Errorf("%s: read wrong content", test.desc)
-			continue
-		}
-		buf.Reset()
-		c := newConn(&nilCloser{buf})
-		w := newWriter(c, test.recType, test.reqId)
-		if _, err := w.Write(test.content); err != nil {
-			t.Errorf("%s: error writing record: %v", test.desc, err)
-			continue
-		}
-		if err := w.Close(); err != nil {
-			t.Errorf("%s: error closing stream: %v", test.desc, err)
-			continue
-		}
-		if !bytes.Equal(buf.Bytes(), test.raw) {
-			t.Errorf("%s: wrote wrong content", test.desc)
-		}
-	}
-}
diff --git a/src/pkg/http/filetransport.go b/src/pkg/http/filetransport.go
deleted file mode 100644
index 78f3aa2..0000000
--- a/src/pkg/http/filetransport.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2011 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 http
-
-import (
-	"fmt"
-	"io"
-	"os"
-)
-
-// fileTransport implements RoundTripper for the 'file' protocol.
-type fileTransport struct {
-	fh fileHandler
-}
-
-// NewFileTransport returns a new RoundTripper, serving the provided
-// FileSystem. The returned RoundTripper ignores the URL host in its
-// incoming requests, as well as most other properties of the
-// request.
-//
-// The typical use case for NewFileTransport is to register the "file"
-// protocol with a Transport, as in:
-//
-//   t := &http.Transport{}
-//   t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
-//   c := &http.Client{Transport: t}
-//   res, err := c.Get("file:///etc/passwd")
-//   ...
-func NewFileTransport(fs FileSystem) RoundTripper {
-	return fileTransport{fileHandler{fs}}
-}
-
-func (t fileTransport) RoundTrip(req *Request) (resp *Response, err os.Error) {
-	// We start ServeHTTP in a goroutine, which may take a long
-	// time if the file is large.  The newPopulateResponseWriter
-	// call returns a channel which either ServeHTTP or finish()
-	// sends our *Response on, once the *Response itself has been
-	// populated (even if the body itself is still being
-	// written to the res.Body, a pipe)
-	rw, resc := newPopulateResponseWriter()
-	go func() {
-		t.fh.ServeHTTP(rw, req)
-		rw.finish()
-	}()
-	return <-resc, nil
-}
-
-func newPopulateResponseWriter() (*populateResponse, <-chan *Response) {
-	pr, pw := io.Pipe()
-	rw := &populateResponse{
-		ch: make(chan *Response),
-		pw: pw,
-		res: &Response{
-			Proto:      "HTTP/1.0",
-			ProtoMajor: 1,
-			Header:     make(Header),
-			Close:      true,
-			Body:       pr,
-		},
-	}
-	return rw, rw.ch
-}
-
-// populateResponse is a ResponseWriter that populates the *Response
-// in res, and writes its body to a pipe connected to the response
-// body. Once writes begin or finish() is called, the response is sent
-// on ch.
-type populateResponse struct {
-	res          *Response
-	ch           chan *Response
-	wroteHeader  bool
-	hasContent   bool
-	sentResponse bool
-	pw           *io.PipeWriter
-}
-
-func (pr *populateResponse) finish() {
-	if !pr.wroteHeader {
-		pr.WriteHeader(500)
-	}
-	if !pr.sentResponse {
-		pr.sendResponse()
-	}
-	pr.pw.Close()
-}
-
-func (pr *populateResponse) sendResponse() {
-	if pr.sentResponse {
-		return
-	}
-	pr.sentResponse = true
-
-	if pr.hasContent {
-		pr.res.ContentLength = -1
-	}
-	pr.ch <- pr.res
-}
-
-func (pr *populateResponse) Header() Header {
-	return pr.res.Header
-}
-
-func (pr *populateResponse) WriteHeader(code int) {
-	if pr.wroteHeader {
-		return
-	}
-	pr.wroteHeader = true
-
-	pr.res.StatusCode = code
-	pr.res.Status = fmt.Sprintf("%d %s", code, StatusText(code))
-}
-
-func (pr *populateResponse) Write(p []byte) (n int, err os.Error) {
-	if !pr.wroteHeader {
-		pr.WriteHeader(StatusOK)
-	}
-	pr.hasContent = true
-	if !pr.sentResponse {
-		pr.sendResponse()
-	}
-	return pr.pw.Write(p)
-}
diff --git a/src/pkg/http/filetransport_test.go b/src/pkg/http/filetransport_test.go
deleted file mode 100644
index 2634243..0000000
--- a/src/pkg/http/filetransport_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2011 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 http_test
-
-import (
-	"http"
-	"io/ioutil"
-	"path/filepath"
-	"os"
-	"testing"
-)
-
-func checker(t *testing.T) func(string, os.Error) {
-	return func(call string, err os.Error) {
-		if err == nil {
-			return
-		}
-		t.Fatalf("%s: %v", call, err)
-	}
-}
-
-func TestFileTransport(t *testing.T) {
-	check := checker(t)
-
-	dname, err := ioutil.TempDir("", "")
-	check("TempDir", err)
-	fname := filepath.Join(dname, "foo.txt")
-	err = ioutil.WriteFile(fname, []byte("Bar"), 0644)
-	check("WriteFile", err)
-
-	tr := &http.Transport{}
-	tr.RegisterProtocol("file", http.NewFileTransport(http.Dir(dname)))
-	c := &http.Client{Transport: tr}
-
-	fooURLs := []string{"file:///foo.txt", "file://../foo.txt"}
-	for _, urlstr := range fooURLs {
-		res, err := c.Get(urlstr)
-		check("Get "+urlstr, err)
-		if res.StatusCode != 200 {
-			t.Errorf("for %s, StatusCode = %d, want 200", urlstr, res.StatusCode)
-		}
-		if res.ContentLength != -1 {
-			t.Errorf("for %s, ContentLength = %d, want -1", urlstr, res.ContentLength)
-		}
-		if res.Body == nil {
-			t.Fatalf("for %s, nil Body", urlstr)
-		}
-		slurp, err := ioutil.ReadAll(res.Body)
-		check("ReadAll "+urlstr, err)
-		if string(slurp) != "Bar" {
-			t.Errorf("for %s, got content %q, want %q", urlstr, string(slurp), "Bar")
-		}
-	}
-
-	const badURL = "file://../no-exist.txt"
-	res, err := c.Get(badURL)
-	check("Get "+badURL, err)
-	if res.StatusCode != 404 {
-		t.Errorf("for %s, StatusCode = %d, want 404", badURL, res.StatusCode)
-	}
-}
diff --git a/src/pkg/http/fs.go b/src/pkg/http/fs.go
deleted file mode 100644
index 2c7c636..0000000
--- a/src/pkg/http/fs.go
+++ /dev/null
@@ -1,323 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// HTTP file system request handler
-
-package http
-
-import (
-	"fmt"
-	"io"
-	"mime"
-	"os"
-	"path"
-	"path/filepath"
-	"strconv"
-	"strings"
-	"time"
-	"utf8"
-)
-
-// A Dir implements http.FileSystem using the native file
-// system restricted to a specific directory tree.
-type Dir string
-
-func (d Dir) Open(name string) (File, os.Error) {
-	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 {
-		return nil, os.NewError("http: invalid character in file path")
-	}
-	f, err := os.Open(filepath.Join(string(d), filepath.FromSlash(path.Clean("/"+name))))
-	if err != nil {
-		return nil, err
-	}
-	return f, nil
-}
-
-// A FileSystem implements access to a collection of named files.
-// The elements in a file path are separated by slash ('/', U+002F)
-// characters, regardless of host operating system convention.
-type FileSystem interface {
-	Open(name string) (File, os.Error)
-}
-
-// A File is returned by a FileSystem's Open method and can be
-// served by the FileServer implementation.
-type File interface {
-	Close() os.Error
-	Stat() (*os.FileInfo, os.Error)
-	Readdir(count int) ([]os.FileInfo, os.Error)
-	Read([]byte) (int, os.Error)
-	Seek(offset int64, whence int) (int64, os.Error)
-}
-
-// Heuristic: b is text if it is valid UTF-8 and doesn't
-// contain any unprintable ASCII or Unicode characters.
-func isText(b []byte) bool {
-	for len(b) > 0 && utf8.FullRune(b) {
-		rune, size := utf8.DecodeRune(b)
-		if size == 1 && rune == utf8.RuneError {
-			// decoding error
-			return false
-		}
-		if 0x7F <= rune && rune <= 0x9F {
-			return false
-		}
-		if rune < ' ' {
-			switch rune {
-			case '\n', '\r', '\t':
-				// okay
-			default:
-				// binary garbage
-				return false
-			}
-		}
-		b = b[size:]
-	}
-	return true
-}
-
-func dirList(w ResponseWriter, f File) {
-	w.Header().Set("Content-Type", "text/html; charset=utf-8")
-	fmt.Fprintf(w, "<pre>\n")
-	for {
-		dirs, err := f.Readdir(100)
-		if err != nil || len(dirs) == 0 {
-			break
-		}
-		for _, d := range dirs {
-			name := d.Name
-			if d.IsDirectory() {
-				name += "/"
-			}
-			// TODO htmlescape
-			fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", name, name)
-		}
-	}
-	fmt.Fprintf(w, "</pre>\n")
-}
-
-// name is '/'-separated, not filepath.Separator.
-func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
-	const indexPage = "/index.html"
-
-	// redirect .../index.html to .../
-	// can't use Redirect() because that would make the path absolute,
-	// which would be a problem running under StripPrefix
-	if strings.HasSuffix(r.URL.Path, indexPage) {
-		localRedirect(w, r, "./")
-		return
-	}
-
-	f, err := fs.Open(name)
-	if err != nil {
-		// TODO expose actual error?
-		NotFound(w, r)
-		return
-	}
-	defer f.Close()
-
-	d, err1 := f.Stat()
-	if err1 != nil {
-		// TODO expose actual error?
-		NotFound(w, r)
-		return
-	}
-
-	if redirect {
-		// redirect to canonical path: / at end of directory url
-		// r.URL.Path always begins with /
-		url := r.URL.Path
-		if d.IsDirectory() {
-			if url[len(url)-1] != '/' {
-				localRedirect(w, r, path.Base(url)+"/")
-				return
-			}
-		} else {
-			if url[len(url)-1] == '/' {
-				localRedirect(w, r, "../"+path.Base(url))
-				return
-			}
-		}
-	}
-
-	if t, _ := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); t != nil && d.Mtime_ns/1e9 <= t.Seconds() {
-		w.WriteHeader(StatusNotModified)
-		return
-	}
-	w.Header().Set("Last-Modified", time.SecondsToUTC(d.Mtime_ns/1e9).Format(TimeFormat))
-
-	// use contents of index.html for directory, if present
-	if d.IsDirectory() {
-		index := name + indexPage
-		ff, err := fs.Open(index)
-		if err == nil {
-			defer ff.Close()
-			dd, err := ff.Stat()
-			if err == nil {
-				name = index
-				d = dd
-				f = ff
-			}
-		}
-	}
-
-	if d.IsDirectory() {
-		dirList(w, f)
-		return
-	}
-
-	// serve file
-	size := d.Size
-	code := StatusOK
-
-	// If Content-Type isn't set, use the file's extension to find it.
-	if w.Header().Get("Content-Type") == "" {
-		ctype := mime.TypeByExtension(filepath.Ext(name))
-		if ctype == "" {
-			// read a chunk to decide between utf-8 text and binary
-			var buf [1024]byte
-			n, _ := io.ReadFull(f, buf[:])
-			b := buf[:n]
-			if isText(b) {
-				ctype = "text/plain; charset=utf-8"
-			} else {
-				// generic binary
-				ctype = "application/octet-stream"
-			}
-			f.Seek(0, os.SEEK_SET) // rewind to output whole file
-		}
-		w.Header().Set("Content-Type", ctype)
-	}
-
-	// handle Content-Range header.
-	// TODO(adg): handle multiple ranges
-	ranges, err := parseRange(r.Header.Get("Range"), size)
-	if err == nil && len(ranges) > 1 {
-		err = os.NewError("multiple ranges not supported")
-	}
-	if err != nil {
-		Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
-		return
-	}
-	if len(ranges) == 1 {
-		ra := ranges[0]
-		if _, err := f.Seek(ra.start, os.SEEK_SET); err != nil {
-			Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
-			return
-		}
-		size = ra.length
-		code = StatusPartialContent
-		w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", ra.start, ra.start+ra.length-1, d.Size))
-	}
-
-	w.Header().Set("Accept-Ranges", "bytes")
-	if w.Header().Get("Content-Encoding") == "" {
-		w.Header().Set("Content-Length", strconv.Itoa64(size))
-	}
-
-	w.WriteHeader(code)
-
-	if r.Method != "HEAD" {
-		io.Copyn(w, f, size)
-	}
-}
-
-// localRedirect gives a Moved Permanently response.
-// It does not convert relative paths to absolute paths like Redirect does.
-func localRedirect(w ResponseWriter, r *Request, newPath string) {
-	if q := r.URL.RawQuery; q != "" {
-		newPath += "?" + q
-	}
-	w.Header().Set("Location", newPath)
-	w.WriteHeader(StatusMovedPermanently)
-}
-
-// ServeFile replies to the request with the contents of the named file or directory.
-func ServeFile(w ResponseWriter, r *Request, name string) {
-	dir, file := filepath.Split(name)
-	serveFile(w, r, Dir(dir), file, false)
-}
-
-type fileHandler struct {
-	root FileSystem
-}
-
-// FileServer returns a handler that serves HTTP requests
-// with the contents of the file system rooted at root.
-//
-// To use the operating system's file system implementation,
-// use http.Dir:
-//
-//     http.Handle("/", http.FileServer(http.Dir("/tmp")))
-func FileServer(root FileSystem) Handler {
-	return &fileHandler{root}
-}
-
-func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
-	upath := r.URL.Path
-	if !strings.HasPrefix(upath, "/") {
-		upath = "/" + upath
-		r.URL.Path = upath
-	}
-	serveFile(w, r, f.root, path.Clean(upath), true)
-}
-
-// httpRange specifies the byte range to be sent to the client.
-type httpRange struct {
-	start, length int64
-}
-
-// parseRange parses a Range header string as per RFC 2616.
-func parseRange(s string, size int64) ([]httpRange, os.Error) {
-	if s == "" {
-		return nil, nil // header not present
-	}
-	const b = "bytes="
-	if !strings.HasPrefix(s, b) {
-		return nil, os.NewError("invalid range")
-	}
-	var ranges []httpRange
-	for _, ra := range strings.Split(s[len(b):], ",") {
-		i := strings.Index(ra, "-")
-		if i < 0 {
-			return nil, os.NewError("invalid range")
-		}
-		start, end := ra[:i], ra[i+1:]
-		var r httpRange
-		if start == "" {
-			// If no start is specified, end specifies the
-			// range start relative to the end of the file.
-			i, err := strconv.Atoi64(end)
-			if err != nil {
-				return nil, os.NewError("invalid range")
-			}
-			if i > size {
-				i = size
-			}
-			r.start = size - i
-			r.length = size - r.start
-		} else {
-			i, err := strconv.Atoi64(start)
-			if err != nil || i > size || i < 0 {
-				return nil, os.NewError("invalid range")
-			}
-			r.start = i
-			if end == "" {
-				// If no end is specified, range extends to end of the file.
-				r.length = size - r.start
-			} else {
-				i, err := strconv.Atoi64(end)
-				if err != nil || r.start > i {
-					return nil, os.NewError("invalid range")
-				}
-				if i >= size {
-					i = size - 1
-				}
-				r.length = i - r.start + 1
-			}
-		}
-		ranges = append(ranges, r)
-	}
-	return ranges, nil
-}
diff --git a/src/pkg/http/fs_test.go b/src/pkg/http/fs_test.go
deleted file mode 100644
index bb6d015..0000000
--- a/src/pkg/http/fs_test.go
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright 2010 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 http_test
-
-import (
-	"fmt"
-	. "http"
-	"http/httptest"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"strings"
-	"testing"
-	"url"
-)
-
-const (
-	testFile       = "testdata/file"
-	testFileLength = 11
-)
-
-var ServeFileRangeTests = []struct {
-	start, end int
-	r          string
-	code       int
-}{
-	{0, testFileLength, "", StatusOK},
-	{0, 5, "0-4", StatusPartialContent},
-	{2, testFileLength, "2-", StatusPartialContent},
-	{testFileLength - 5, testFileLength, "-5", StatusPartialContent},
-	{3, 8, "3-7", StatusPartialContent},
-	{0, 0, "20-", StatusRequestedRangeNotSatisfiable},
-}
-
-func TestServeFile(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		ServeFile(w, r, "testdata/file")
-	}))
-	defer ts.Close()
-
-	var err os.Error
-
-	file, err := ioutil.ReadFile(testFile)
-	if err != nil {
-		t.Fatal("reading file:", err)
-	}
-
-	// set up the Request (re-used for all tests)
-	var req Request
-	req.Header = make(Header)
-	if req.URL, err = url.Parse(ts.URL); err != nil {
-		t.Fatal("ParseURL:", err)
-	}
-	req.Method = "GET"
-
-	// straight GET
-	_, body := getBody(t, req)
-	if !equal(body, file) {
-		t.Fatalf("body mismatch: got %q, want %q", body, file)
-	}
-
-	// Range tests
-	for _, rt := range ServeFileRangeTests {
-		req.Header.Set("Range", "bytes="+rt.r)
-		if rt.r == "" {
-			req.Header["Range"] = nil
-		}
-		r, body := getBody(t, req)
-		if r.StatusCode != rt.code {
-			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
-		}
-		if rt.code == StatusRequestedRangeNotSatisfiable {
-			continue
-		}
-		h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
-		if rt.r == "" {
-			h = ""
-		}
-		cr := r.Header.Get("Content-Range")
-		if cr != h {
-			t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
-		}
-		if !equal(body, file[rt.start:rt.end]) {
-			t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
-		}
-	}
-}
-
-var fsRedirectTestData = []struct {
-	original, redirect string
-}{
-	{"/test/index.html", "/test/"},
-	{"/test/testdata", "/test/testdata/"},
-	{"/test/testdata/file/", "/test/testdata/file"},
-}
-
-func TestFSRedirect(t *testing.T) {
-	ts := httptest.NewServer(StripPrefix("/test", FileServer(Dir("."))))
-	defer ts.Close()
-
-	for _, data := range fsRedirectTestData {
-		res, err := Get(ts.URL + data.original)
-		if err != nil {
-			t.Fatal(err)
-		}
-		res.Body.Close()
-		if g, e := res.Request.URL.Path, data.redirect; g != e {
-			t.Errorf("redirect from %s: got %s, want %s", data.original, g, e)
-		}
-	}
-}
-
-type testFileSystem struct {
-	open func(name string) (File, os.Error)
-}
-
-func (fs *testFileSystem) Open(name string) (File, os.Error) {
-	return fs.open(name)
-}
-
-func TestFileServerCleans(t *testing.T) {
-	ch := make(chan string, 1)
-	fs := FileServer(&testFileSystem{func(name string) (File, os.Error) {
-		ch <- name
-		return nil, os.ENOENT
-	}})
-	tests := []struct {
-		reqPath, openArg string
-	}{
-		{"/foo.txt", "/foo.txt"},
-		{"//foo.txt", "/foo.txt"},
-		{"/../foo.txt", "/foo.txt"},
-	}
-	req, _ := NewRequest("GET", "http://example.com", nil)
-	for n, test := range tests {
-		rec := httptest.NewRecorder()
-		req.URL.Path = test.reqPath
-		fs.ServeHTTP(rec, req)
-		if got := <-ch; got != test.openArg {
-			t.Errorf("test %d: got %q, want %q", n, got, test.openArg)
-		}
-	}
-}
-
-func TestFileServerImplicitLeadingSlash(t *testing.T) {
-	tempDir, err := ioutil.TempDir("", "")
-	if err != nil {
-		t.Fatalf("TempDir: %v", err)
-	}
-	defer os.RemoveAll(tempDir)
-	if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
-		t.Fatalf("WriteFile: %v", err)
-	}
-	ts := httptest.NewServer(StripPrefix("/bar/", FileServer(Dir(tempDir))))
-	defer ts.Close()
-	get := func(suffix string) string {
-		res, err := Get(ts.URL + suffix)
-		if err != nil {
-			t.Fatalf("Get %s: %v", suffix, err)
-		}
-		b, err := ioutil.ReadAll(res.Body)
-		if err != nil {
-			t.Fatalf("ReadAll %s: %v", suffix, err)
-		}
-		return string(b)
-	}
-	if s := get("/bar/"); !strings.Contains(s, ">foo.txt<") {
-		t.Logf("expected a directory listing with foo.txt, got %q", s)
-	}
-	if s := get("/bar/foo.txt"); s != "Hello world" {
-		t.Logf("expected %q, got %q", "Hello world", s)
-	}
-}
-
-func TestDirJoin(t *testing.T) {
-	wfi, err := os.Stat("/etc/hosts")
-	if err != nil {
-		t.Logf("skipping test; no /etc/hosts file")
-		return
-	}
-	test := func(d Dir, name string) {
-		f, err := d.Open(name)
-		if err != nil {
-			t.Fatalf("open of %s: %v", name, err)
-		}
-		defer f.Close()
-		gfi, err := f.Stat()
-		if err != nil {
-			t.Fatalf("stat of %s: %v", name, err)
-		}
-		if gfi.Ino != wfi.Ino {
-			t.Errorf("%s got different inode", name)
-		}
-	}
-	test(Dir("/etc/"), "/hosts")
-	test(Dir("/etc/"), "hosts")
-	test(Dir("/etc/"), "../../../../hosts")
-	test(Dir("/etc"), "/hosts")
-	test(Dir("/etc"), "hosts")
-	test(Dir("/etc"), "../../../../hosts")
-
-	// Not really directories, but since we use this trick in
-	// ServeFile, test it:
-	test(Dir("/etc/hosts"), "")
-	test(Dir("/etc/hosts"), "/")
-	test(Dir("/etc/hosts"), "../")
-}
-
-func TestServeFileContentType(t *testing.T) {
-	const ctype = "icecream/chocolate"
-	override := false
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		if override {
-			w.Header().Set("Content-Type", ctype)
-		}
-		ServeFile(w, r, "testdata/file")
-	}))
-	defer ts.Close()
-	get := func(want string) {
-		resp, err := Get(ts.URL)
-		if err != nil {
-			t.Fatal(err)
-		}
-		if h := resp.Header.Get("Content-Type"); h != want {
-			t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
-		}
-	}
-	get("text/plain; charset=utf-8")
-	override = true
-	get(ctype)
-}
-
-func TestServeFileMimeType(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		ServeFile(w, r, "testdata/style.css")
-	}))
-	defer ts.Close()
-	resp, err := Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	want := "text/css; charset=utf-8"
-	if h := resp.Header.Get("Content-Type"); h != want {
-		t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
-	}
-}
-
-func TestServeFileWithContentEncoding(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header().Set("Content-Encoding", "foo")
-		ServeFile(w, r, "testdata/file")
-	}))
-	defer ts.Close()
-	resp, err := Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if g, e := resp.ContentLength, int64(-1); g != e {
-		t.Errorf("Content-Length mismatch: got %d, want %d", g, e)
-	}
-}
-
-func TestServeIndexHtml(t *testing.T) {
-	const want = "index.html says hello\n"
-	ts := httptest.NewServer(FileServer(Dir(".")))
-	defer ts.Close()
-
-	for _, path := range []string{"/testdata/", "/testdata/index.html"} {
-		res, err := Get(ts.URL + path)
-		if err != nil {
-			t.Fatal(err)
-		}
-		defer res.Body.Close()
-		b, err := ioutil.ReadAll(res.Body)
-		if err != nil {
-			t.Fatal("reading Body:", err)
-		}
-		if s := string(b); s != want {
-			t.Errorf("for path %q got %q, want %q", path, s, want)
-		}
-	}
-}
-
-func getBody(t *testing.T, req Request) (*Response, []byte) {
-	r, err := DefaultClient.Do(&req)
-	if err != nil {
-		t.Fatal(req.URL.String(), "send:", err)
-	}
-	b, err := ioutil.ReadAll(r.Body)
-	if err != nil {
-		t.Fatal("reading Body:", err)
-	}
-	return r, b
-}
-
-func equal(a, b []byte) bool {
-	if len(a) != len(b) {
-		return false
-	}
-	for i := range a {
-		if a[i] != b[i] {
-			return false
-		}
-	}
-	return true
-}
diff --git a/src/pkg/http/header.go b/src/pkg/http/header.go
deleted file mode 100644
index 08b0771..0000000
--- a/src/pkg/http/header.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2010 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 http
-
-import (
-	"fmt"
-	"io"
-	"net/textproto"
-	"os"
-	"sort"
-	"strings"
-)
-
-// A Header represents the key-value pairs in an HTTP header.
-type Header map[string][]string
-
-// Add adds the key, value pair to the header.
-// It appends to any existing values associated with key.
-func (h Header) Add(key, value string) {
-	textproto.MIMEHeader(h).Add(key, value)
-}
-
-// Set sets the header entries associated with key to
-// the single element value.  It replaces any existing
-// values associated with key.
-func (h Header) Set(key, value string) {
-	textproto.MIMEHeader(h).Set(key, value)
-}
-
-// Get gets the first value associated with the given key.
-// If there are no values associated with the key, Get returns "".
-// Get is a convenience method.  For more complex queries,
-// access the map directly.
-func (h Header) Get(key string) string {
-	return textproto.MIMEHeader(h).Get(key)
-}
-
-// Del deletes the values associated with key.
-func (h Header) Del(key string) {
-	textproto.MIMEHeader(h).Del(key)
-}
-
-// Write writes a header in wire format.
-func (h Header) Write(w io.Writer) os.Error {
-	return h.WriteSubset(w, nil)
-}
-
-// WriteSubset writes a header in wire format.
-// If exclude is not nil, keys where exclude[key] == true are not written.
-func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) os.Error {
-	keys := make([]string, 0, len(h))
-	for k := range h {
-		if exclude == nil || !exclude[k] {
-			keys = append(keys, k)
-		}
-	}
-	sort.Strings(keys)
-	for _, k := range keys {
-		for _, v := range h[k] {
-			v = strings.Replace(v, "\n", " ", -1)
-			v = strings.Replace(v, "\r", " ", -1)
-			v = strings.TrimSpace(v)
-			if _, err := fmt.Fprintf(w, "%s: %s\r\n", k, v); err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-// CanonicalHeaderKey returns the canonical format of the
-// header key s.  The canonicalization converts the first
-// letter and any letter following a hyphen to upper case;
-// the rest are converted to lowercase.  For example, the
-// canonical key for "accept-encoding" is "Accept-Encoding".
-func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
diff --git a/src/pkg/http/httptest/Makefile b/src/pkg/http/httptest/Makefile
deleted file mode 100644
index eb35d8a..0000000
--- a/src/pkg/http/httptest/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=http/httptest
-GOFILES=\
-	recorder.go\
-	server.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/http/httptest/recorder.go b/src/pkg/http/httptest/recorder.go
deleted file mode 100644
index f2fedef..0000000
--- a/src/pkg/http/httptest/recorder.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2011 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 httptest provides utilities for HTTP testing.
-package httptest
-
-import (
-	"bytes"
-	"http"
-	"os"
-)
-
-// ResponseRecorder is an implementation of http.ResponseWriter that
-// records its mutations for later inspection in tests.
-type ResponseRecorder struct {
-	Code      int           // the HTTP response code from WriteHeader
-	HeaderMap http.Header   // the HTTP response headers
-	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
-	Flushed   bool
-}
-
-// NewRecorder returns an initialized ResponseRecorder.
-func NewRecorder() *ResponseRecorder {
-	return &ResponseRecorder{
-		HeaderMap: make(http.Header),
-		Body:      new(bytes.Buffer),
-	}
-}
-
-// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
-// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
-const DefaultRemoteAddr = "1.2.3.4"
-
-// Header returns the response headers.
-func (rw *ResponseRecorder) Header() http.Header {
-	return rw.HeaderMap
-}
-
-// Write always succeeds and writes to rw.Body, if not nil.
-func (rw *ResponseRecorder) Write(buf []byte) (int, os.Error) {
-	if rw.Body != nil {
-		rw.Body.Write(buf)
-	}
-	if rw.Code == 0 {
-		rw.Code = http.StatusOK
-	}
-	return len(buf), nil
-}
-
-// WriteHeader sets rw.Code.
-func (rw *ResponseRecorder) WriteHeader(code int) {
-	rw.Code = code
-}
-
-// Flush sets rw.Flushed to true.
-func (rw *ResponseRecorder) Flush() {
-	rw.Flushed = true
-}
diff --git a/src/pkg/http/httptest/server.go b/src/pkg/http/httptest/server.go
deleted file mode 100644
index 43a48eb..0000000
--- a/src/pkg/http/httptest/server.go
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2011 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.
-
-// Implementation of Server
-
-package httptest
-
-import (
-	"crypto/rand"
-	"crypto/tls"
-	"flag"
-	"fmt"
-	"http"
-	"net"
-	"os"
-	"time"
-)
-
-// A Server is an HTTP server listening on a system-chosen port on the
-// local loopback interface, for use in end-to-end HTTP tests.
-type Server struct {
-	URL      string // base URL of form http://ipaddr:port with no trailing slash
-	Listener net.Listener
-	TLS      *tls.Config // nil if not using using TLS
-
-	// Config may be changed after calling NewUnstartedServer and
-	// before Start or StartTLS.
-	Config *http.Server
-}
-
-// historyListener keeps track of all connections that it's ever
-// accepted.
-type historyListener struct {
-	net.Listener
-	history []net.Conn
-}
-
-func (hs *historyListener) Accept() (c net.Conn, err os.Error) {
-	c, err = hs.Listener.Accept()
-	if err == nil {
-		hs.history = append(hs.history, c)
-	}
-	return
-}
-
-func newLocalListener() net.Listener {
-	if *serve != "" {
-		l, err := net.Listen("tcp", *serve)
-		if err != nil {
-			panic(fmt.Sprintf("httptest: failed to listen on %v: %v", *serve, err))
-		}
-		return l
-	}
-	l, err := net.Listen("tcp", "127.0.0.1:0")
-	if err != nil {
-		if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
-			panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
-		}
-	}
-	return l
-}
-
-// When debugging a particular http server-based test,
-// this flag lets you run
-//	gotest -run=BrokenTest -httptest.serve=127.0.0.1:8000
-// to start the broken server so you can interact with it manually.
-var serve = flag.String("httptest.serve", "", "if non-empty, httptest.NewServer serves on this address and blocks")
-
-// NewServer starts and returns a new Server.
-// The caller should call Close when finished, to shut it down.
-func NewServer(handler http.Handler) *Server {
-	ts := NewUnstartedServer(handler)
-	ts.Start()
-	return ts
-}
-
-// NewUnstartedServer returns a new Server but doesn't start it.
-//
-// After changing its configuration, the caller should call Start or
-// StartTLS.
-//
-// The caller should call Close when finished, to shut it down.
-func NewUnstartedServer(handler http.Handler) *Server {
-	return &Server{
-		Listener: newLocalListener(),
-		Config:   &http.Server{Handler: handler},
-	}
-}
-
-// Start starts a server from NewUnstartedServer.
-func (s *Server) Start() {
-	if s.URL != "" {
-		panic("Server already started")
-	}
-	s.Listener = &historyListener{s.Listener, make([]net.Conn, 0)}
-	s.URL = "http://" + s.Listener.Addr().String()
-	go s.Config.Serve(s.Listener)
-	if *serve != "" {
-		fmt.Println(os.Stderr, "httptest: serving on", s.URL)
-		select {}
-	}
-}
-
-// StartTLS starts TLS on a server from NewUnstartedServer.
-func (s *Server) StartTLS() {
-	if s.URL != "" {
-		panic("Server already started")
-	}
-	cert, err := tls.X509KeyPair(localhostCert, localhostKey)
-	if err != nil {
-		panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
-	}
-
-	s.TLS = &tls.Config{
-		Rand:         rand.Reader,
-		Time:         time.Seconds,
-		NextProtos:   []string{"http/1.1"},
-		Certificates: []tls.Certificate{cert},
-	}
-	tlsListener := tls.NewListener(s.Listener, s.TLS)
-
-	s.Listener = &historyListener{tlsListener, make([]net.Conn, 0)}
-	s.URL = "https://" + s.Listener.Addr().String()
-	go s.Config.Serve(s.Listener)
-}
-
-// NewTLSServer starts and returns a new Server using TLS.
-// The caller should call Close when finished, to shut it down.
-func NewTLSServer(handler http.Handler) *Server {
-	ts := NewUnstartedServer(handler)
-	ts.StartTLS()
-	return ts
-}
-
-// Close shuts down the server.
-func (s *Server) Close() {
-	s.Listener.Close()
-}
-
-// CloseClientConnections closes any currently open HTTP connections
-// to the test Server.
-func (s *Server) CloseClientConnections() {
-	hl, ok := s.Listener.(*historyListener)
-	if !ok {
-		return
-	}
-	for _, conn := range hl.history {
-		conn.Close()
-	}
-}
-
-// localhostCert is a PEM-encoded TLS cert with SAN DNS names
-// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
-// of ASN.1 time).
-var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
-MIIBOTCB5qADAgECAgEAMAsGCSqGSIb3DQEBBTAAMB4XDTcwMDEwMTAwMDAwMFoX
-DTQ5MTIzMTIzNTk1OVowADBaMAsGCSqGSIb3DQEBAQNLADBIAkEAsuA5mAFMj6Q7
-qoBzcvKzIq4kzuT5epSp2AkcQfyBHm7K13Ws7u+0b5Vb9gqTf5cAiIKcrtrXVqkL
-8i1UQF6AzwIDAQABo08wTTAOBgNVHQ8BAf8EBAMCACQwDQYDVR0OBAYEBAECAwQw
-DwYDVR0jBAgwBoAEAQIDBDAbBgNVHREEFDASggkxMjcuMC4wLjGCBVs6OjFdMAsG
-CSqGSIb3DQEBBQNBAJH30zjLWRztrWpOCgJL8RQWLaKzhK79pVhAx6q/3NrF16C7
-+l1BRZstTwIGdoGId8BRpErK1TXkniFb95ZMynM=
------END CERTIFICATE-----
-`)
-
-// localhostKey is the private key for localhostCert.
-var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIIBPQIBAAJBALLgOZgBTI+kO6qAc3LysyKuJM7k+XqUqdgJHEH8gR5uytd1rO7v
-tG+VW/YKk3+XAIiCnK7a11apC/ItVEBegM8CAwEAAQJBAI5sxq7naeR9ahyqRkJi
-SIv2iMxLuPEHaezf5CYOPWjSjBPyVhyRevkhtqEjF/WkgL7C2nWpYHsUcBDBQVF0
-3KECIQDtEGB2ulnkZAahl3WuJziXGLB+p8Wgx7wzSM6bHu1c6QIhAMEp++CaS+SJ
-/TrU0zwY/fW4SvQeb49BPZUF3oqR8Xz3AiEA1rAJHBzBgdOQKdE3ksMUPcnvNJSN
-poCcELmz2clVXtkCIQCLytuLV38XHToTipR4yMl6O+6arzAjZ56uq7m7ZRV0TwIh
-AM65XAOw8Dsg9Kq78aYXiOEDc5DL0sbFUu/SlmRcCg93
------END RSA PRIVATE KEY-----
-`)
diff --git a/src/pkg/http/persist.go b/src/pkg/http/persist.go
deleted file mode 100644
index 78bf905..0000000
--- a/src/pkg/http/persist.go
+++ /dev/null
@@ -1,420 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http
-
-import (
-	"bufio"
-	"io"
-	"net"
-	"net/textproto"
-	"os"
-	"sync"
-)
-
-var (
-	ErrPersistEOF = &ProtocolError{"persistent connection closed"}
-	ErrPipeline   = &ProtocolError{"pipeline error"}
-)
-
-// A ServerConn reads requests and sends responses over an underlying
-// connection, until the HTTP keepalive logic commands an end. ServerConn
-// also allows hijacking the underlying connection by calling Hijack
-// to regain control over the connection. ServerConn supports pipe-lining,
-// i.e. requests can be read out of sync (but in the same order) while the
-// respective responses are sent.
-//
-// ServerConn is low-level and should not be needed by most applications.
-// See Server.
-type ServerConn struct {
-	lk              sync.Mutex // read-write protects the following fields
-	c               net.Conn
-	r               *bufio.Reader
-	re, we          os.Error // read/write errors
-	lastbody        io.ReadCloser
-	nread, nwritten int
-	pipereq         map[*Request]uint
-
-	pipe textproto.Pipeline
-}
-
-// NewServerConn returns a new ServerConn reading and writing c.  If r is not
-// nil, it is the buffer to use when reading c.
-func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
-	if r == nil {
-		r = bufio.NewReader(c)
-	}
-	return &ServerConn{c: c, r: r, pipereq: make(map[*Request]uint)}
-}
-
-// Hijack detaches the ServerConn and returns the underlying connection as well
-// as the read-side bufio which may have some left over data. Hijack may be
-// called before Read has signaled the end of the keep-alive logic. The user
-// should not call Hijack while Read or Write is in progress.
-func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
-	sc.lk.Lock()
-	defer sc.lk.Unlock()
-	c = sc.c
-	r = sc.r
-	sc.c = nil
-	sc.r = nil
-	return
-}
-
-// Close calls Hijack and then also closes the underlying connection
-func (sc *ServerConn) Close() os.Error {
-	c, _ := sc.Hijack()
-	if c != nil {
-		return c.Close()
-	}
-	return nil
-}
-
-// Read returns the next request on the wire. An ErrPersistEOF is returned if
-// it is gracefully determined that there are no more requests (e.g. after the
-// first request on an HTTP/1.0 connection, or after a Connection:close on a
-// HTTP/1.1 connection).
-func (sc *ServerConn) Read() (req *Request, err os.Error) {
-
-	// Ensure ordered execution of Reads and Writes
-	id := sc.pipe.Next()
-	sc.pipe.StartRequest(id)
-	defer func() {
-		sc.pipe.EndRequest(id)
-		if req == nil {
-			sc.pipe.StartResponse(id)
-			sc.pipe.EndResponse(id)
-		} else {
-			// Remember the pipeline id of this request
-			sc.lk.Lock()
-			sc.pipereq[req] = id
-			sc.lk.Unlock()
-		}
-	}()
-
-	sc.lk.Lock()
-	if sc.we != nil { // no point receiving if write-side broken or closed
-		defer sc.lk.Unlock()
-		return nil, sc.we
-	}
-	if sc.re != nil {
-		defer sc.lk.Unlock()
-		return nil, sc.re
-	}
-	if sc.r == nil { // connection closed by user in the meantime
-		defer sc.lk.Unlock()
-		return nil, os.EBADF
-	}
-	r := sc.r
-	lastbody := sc.lastbody
-	sc.lastbody = nil
-	sc.lk.Unlock()
-
-	// Make sure body is fully consumed, even if user does not call body.Close
-	if lastbody != nil {
-		// body.Close is assumed to be idempotent and multiple calls to
-		// it should return the error that its first invocation
-		// returned.
-		err = lastbody.Close()
-		if err != nil {
-			sc.lk.Lock()
-			defer sc.lk.Unlock()
-			sc.re = err
-			return nil, err
-		}
-	}
-
-	req, err = ReadRequest(r)
-	sc.lk.Lock()
-	defer sc.lk.Unlock()
-	if err != nil {
-		if err == io.ErrUnexpectedEOF {
-			// A close from the opposing client is treated as a
-			// graceful close, even if there was some unparse-able
-			// data before the close.
-			sc.re = ErrPersistEOF
-			return nil, sc.re
-		} else {
-			sc.re = err
-			return req, err
-		}
-	}
-	sc.lastbody = req.Body
-	sc.nread++
-	if req.Close {
-		sc.re = ErrPersistEOF
-		return req, sc.re
-	}
-	return req, err
-}
-
-// Pending returns the number of unanswered requests
-// that have been received on the connection.
-func (sc *ServerConn) Pending() int {
-	sc.lk.Lock()
-	defer sc.lk.Unlock()
-	return sc.nread - sc.nwritten
-}
-
-// Write writes resp in response to req. To close the connection gracefully, set the
-// Response.Close field to true. Write should be considered operational until
-// it returns an error, regardless of any errors returned on the Read side.
-func (sc *ServerConn) Write(req *Request, resp *Response) os.Error {
-
-	// Retrieve the pipeline ID of this request/response pair
-	sc.lk.Lock()
-	id, ok := sc.pipereq[req]
-	sc.pipereq[req] = 0, false
-	if !ok {
-		sc.lk.Unlock()
-		return ErrPipeline
-	}
-	sc.lk.Unlock()
-
-	// Ensure pipeline order
-	sc.pipe.StartResponse(id)
-	defer sc.pipe.EndResponse(id)
-
-	sc.lk.Lock()
-	if sc.we != nil {
-		defer sc.lk.Unlock()
-		return sc.we
-	}
-	if sc.c == nil { // connection closed by user in the meantime
-		defer sc.lk.Unlock()
-		return os.EBADF
-	}
-	c := sc.c
-	if sc.nread <= sc.nwritten {
-		defer sc.lk.Unlock()
-		return os.NewError("persist server pipe count")
-	}
-	if resp.Close {
-		// After signaling a keep-alive close, any pipelined unread
-		// requests will be lost. It is up to the user to drain them
-		// before signaling.
-		sc.re = ErrPersistEOF
-	}
-	sc.lk.Unlock()
-
-	err := resp.Write(c)
-	sc.lk.Lock()
-	defer sc.lk.Unlock()
-	if err != nil {
-		sc.we = err
-		return err
-	}
-	sc.nwritten++
-
-	return nil
-}
-
-// A ClientConn sends request and receives headers over an underlying
-// connection, while respecting the HTTP keepalive logic. ClientConn
-// supports hijacking the connection calling Hijack to
-// regain control of the underlying net.Conn and deal with it as desired.
-//
-// ClientConn is low-level and should not be needed by most applications.
-// See Client.
-type ClientConn struct {
-	lk              sync.Mutex // read-write protects the following fields
-	c               net.Conn
-	r               *bufio.Reader
-	re, we          os.Error // read/write errors
-	lastbody        io.ReadCloser
-	nread, nwritten int
-	pipereq         map[*Request]uint
-
-	pipe     textproto.Pipeline
-	writeReq func(*Request, io.Writer) os.Error
-}
-
-// NewClientConn returns a new ClientConn reading and writing c.  If r is not
-// nil, it is the buffer to use when reading c.
-func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
-	if r == nil {
-		r = bufio.NewReader(c)
-	}
-	return &ClientConn{
-		c:        c,
-		r:        r,
-		pipereq:  make(map[*Request]uint),
-		writeReq: (*Request).Write,
-	}
-}
-
-// NewProxyClientConn works like NewClientConn but writes Requests
-// using Request's WriteProxy method.
-func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
-	cc := NewClientConn(c, r)
-	cc.writeReq = (*Request).WriteProxy
-	return cc
-}
-
-// Hijack detaches the ClientConn and returns the underlying connection as well
-// as the read-side bufio which may have some left over data. Hijack may be
-// called before the user or Read have signaled the end of the keep-alive
-// logic. The user should not call Hijack while Read or Write is in progress.
-func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
-	cc.lk.Lock()
-	defer cc.lk.Unlock()
-	c = cc.c
-	r = cc.r
-	cc.c = nil
-	cc.r = nil
-	return
-}
-
-// Close calls Hijack and then also closes the underlying connection
-func (cc *ClientConn) Close() os.Error {
-	c, _ := cc.Hijack()
-	if c != nil {
-		return c.Close()
-	}
-	return nil
-}
-
-// Write writes a request. An ErrPersistEOF error is returned if the connection
-// has been closed in an HTTP keepalive sense. If req.Close equals true, the
-// keepalive connection is logically closed after this request and the opposing
-// server is informed. An ErrUnexpectedEOF indicates the remote closed the
-// underlying TCP connection, which is usually considered as graceful close.
-func (cc *ClientConn) Write(req *Request) (err os.Error) {
-
-	// Ensure ordered execution of Writes
-	id := cc.pipe.Next()
-	cc.pipe.StartRequest(id)
-	defer func() {
-		cc.pipe.EndRequest(id)
-		if err != nil {
-			cc.pipe.StartResponse(id)
-			cc.pipe.EndResponse(id)
-		} else {
-			// Remember the pipeline id of this request
-			cc.lk.Lock()
-			cc.pipereq[req] = id
-			cc.lk.Unlock()
-		}
-	}()
-
-	cc.lk.Lock()
-	if cc.re != nil { // no point sending if read-side closed or broken
-		defer cc.lk.Unlock()
-		return cc.re
-	}
-	if cc.we != nil {
-		defer cc.lk.Unlock()
-		return cc.we
-	}
-	if cc.c == nil { // connection closed by user in the meantime
-		defer cc.lk.Unlock()
-		return os.EBADF
-	}
-	c := cc.c
-	if req.Close {
-		// We write the EOF to the write-side error, because there
-		// still might be some pipelined reads
-		cc.we = ErrPersistEOF
-	}
-	cc.lk.Unlock()
-
-	err = cc.writeReq(req, c)
-	cc.lk.Lock()
-	defer cc.lk.Unlock()
-	if err != nil {
-		cc.we = err
-		return err
-	}
-	cc.nwritten++
-
-	return nil
-}
-
-// Pending returns the number of unanswered requests
-// that have been sent on the connection.
-func (cc *ClientConn) Pending() int {
-	cc.lk.Lock()
-	defer cc.lk.Unlock()
-	return cc.nwritten - cc.nread
-}
-
-// Read reads the next response from the wire. A valid response might be
-// returned together with an ErrPersistEOF, which means that the remote
-// requested that this be the last request serviced. Read can be called
-// concurrently with Write, but not with another Read.
-func (cc *ClientConn) Read(req *Request) (*Response, os.Error) {
-	return cc.readUsing(req, ReadResponse)
-}
-
-// readUsing is the implementation of Read with a replaceable
-// ReadResponse-like function, used by the Transport.
-func (cc *ClientConn) readUsing(req *Request, readRes func(*bufio.Reader, *Request) (*Response, os.Error)) (resp *Response, err os.Error) {
-	// Retrieve the pipeline ID of this request/response pair
-	cc.lk.Lock()
-	id, ok := cc.pipereq[req]
-	cc.pipereq[req] = 0, false
-	if !ok {
-		cc.lk.Unlock()
-		return nil, ErrPipeline
-	}
-	cc.lk.Unlock()
-
-	// Ensure pipeline order
-	cc.pipe.StartResponse(id)
-	defer cc.pipe.EndResponse(id)
-
-	cc.lk.Lock()
-	if cc.re != nil {
-		defer cc.lk.Unlock()
-		return nil, cc.re
-	}
-	if cc.r == nil { // connection closed by user in the meantime
-		defer cc.lk.Unlock()
-		return nil, os.EBADF
-	}
-	r := cc.r
-	lastbody := cc.lastbody
-	cc.lastbody = nil
-	cc.lk.Unlock()
-
-	// Make sure body is fully consumed, even if user does not call body.Close
-	if lastbody != nil {
-		// body.Close is assumed to be idempotent and multiple calls to
-		// it should return the error that its first invokation
-		// returned.
-		err = lastbody.Close()
-		if err != nil {
-			cc.lk.Lock()
-			defer cc.lk.Unlock()
-			cc.re = err
-			return nil, err
-		}
-	}
-
-	resp, err = readRes(r, req)
-	cc.lk.Lock()
-	defer cc.lk.Unlock()
-	if err != nil {
-		cc.re = err
-		return resp, err
-	}
-	cc.lastbody = resp.Body
-
-	cc.nread++
-
-	if resp.Close {
-		cc.re = ErrPersistEOF // don't send any more requests
-		return resp, cc.re
-	}
-	return resp, err
-}
-
-// Do is convenience method that writes a request and reads a response.
-func (cc *ClientConn) Do(req *Request) (resp *Response, err os.Error) {
-	err = cc.Write(req)
-	if err != nil {
-		return
-	}
-	return cc.Read(req)
-}
diff --git a/src/pkg/http/pprof/Makefile b/src/pkg/http/pprof/Makefile
deleted file mode 100644
index 5858a0e..0000000
--- a/src/pkg/http/pprof/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=http/pprof
-GOFILES=\
-	pprof.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/http/pprof/pprof.go b/src/pkg/http/pprof/pprof.go
deleted file mode 100644
index 917c7f8..0000000
--- a/src/pkg/http/pprof/pprof.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2010 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 pprof serves via its HTTP server runtime profiling data
-// in the format expected by the pprof visualization tool.
-// For more information about pprof, see
-// http://code.google.com/p/google-perftools/.
-//
-// The package is typically only imported for the side effect of
-// registering its HTTP handlers.
-// The handled paths all begin with /debug/pprof/.
-//
-// To use pprof, link this package into your program:
-//	import _ "http/pprof"
-//
-// Then use the pprof tool to look at the heap profile:
-//
-//	pprof http://localhost:6060/debug/pprof/heap
-//
-// Or to look at a 30-second CPU profile:
-//
-//	pprof http://localhost:6060/debug/pprof/profile
-//
-package pprof
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"http"
-	"os"
-	"runtime"
-	"runtime/pprof"
-	"strconv"
-	"strings"
-	"time"
-)
-
-func init() {
-	http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
-	http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
-	http.Handle("/debug/pprof/heap", http.HandlerFunc(Heap))
-	http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
-}
-
-// Cmdline responds with the running program's
-// command line, with arguments separated by NUL bytes.
-// The package initialization registers it as /debug/pprof/cmdline.
-func Cmdline(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-	fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
-}
-
-// Heap responds with the pprof-formatted heap profile.
-// The package initialization registers it as /debug/pprof/heap.
-func Heap(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-	pprof.WriteHeapProfile(w)
-}
-
-// Profile responds with the pprof-formatted cpu profile.
-// The package initialization registers it as /debug/pprof/profile.
-func Profile(w http.ResponseWriter, r *http.Request) {
-	sec, _ := strconv.Atoi64(r.FormValue("seconds"))
-	if sec == 0 {
-		sec = 30
-	}
-
-	// Set Content Type assuming StartCPUProfile will work,
-	// because if it does it starts writing.
-	w.Header().Set("Content-Type", "application/octet-stream")
-	if err := pprof.StartCPUProfile(w); err != nil {
-		// StartCPUProfile failed, so no writes yet.
-		// Can change header back to text content
-		// and send error code.
-		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-		w.WriteHeader(http.StatusInternalServerError)
-		fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err)
-		return
-	}
-	time.Sleep(sec * 1e9)
-	pprof.StopCPUProfile()
-}
-
-// Symbol looks up the program counters listed in the request,
-// responding with a table mapping program counters to function names.
-// The package initialization registers it as /debug/pprof/symbol.
-func Symbol(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-
-	// We have to read the whole POST body before
-	// writing any output.  Buffer the output here.
-	var buf bytes.Buffer
-
-	// We don't know how many symbols we have, but we
-	// do have symbol information.  Pprof only cares whether
-	// this number is 0 (no symbols available) or > 0.
-	fmt.Fprintf(&buf, "num_symbols: 1\n")
-
-	var b *bufio.Reader
-	if r.Method == "POST" {
-		b = bufio.NewReader(r.Body)
-	} else {
-		b = bufio.NewReader(strings.NewReader(r.URL.RawQuery))
-	}
-
-	for {
-		word, err := b.ReadSlice('+')
-		if err == nil {
-			word = word[0 : len(word)-1] // trim +
-		}
-		pc, _ := strconv.Btoui64(string(word), 0)
-		if pc != 0 {
-			f := runtime.FuncForPC(uintptr(pc))
-			if f != nil {
-				fmt.Fprintf(&buf, "%#x %s\n", pc, f.Name())
-			}
-		}
-
-		// Wait until here to check for err; the last
-		// symbol will have an err because it doesn't end in +.
-		if err != nil {
-			if err != os.EOF {
-				fmt.Fprintf(&buf, "reading request: %v\n", err)
-			}
-			break
-		}
-	}
-
-	w.Write(buf.Bytes())
-}
diff --git a/src/pkg/http/readrequest_test.go b/src/pkg/http/readrequest_test.go
deleted file mode 100644
index f6dc99e..0000000
--- a/src/pkg/http/readrequest_test.go
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2010 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 http
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"testing"
-	"url"
-)
-
-type reqTest struct {
-	Raw   string
-	Req   *Request
-	Body  string
-	Error string
-}
-
-var noError = ""
-var noBody = ""
-
-var reqTests = []reqTest{
-	// Baseline test; All Request fields included for template use
-	{
-		"GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
-			"Host: www.techcrunch.com\r\n" +
-			"User-Agent: Fake\r\n" +
-			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
-			"Accept-Language: en-us,en;q=0.5\r\n" +
-			"Accept-Encoding: gzip,deflate\r\n" +
-			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
-			"Keep-Alive: 300\r\n" +
-			"Content-Length: 7\r\n" +
-			"Proxy-Connection: keep-alive\r\n\r\n" +
-			"abcdef\n???",
-
-		&Request{
-			Method: "GET",
-			RawURL: "http://www.techcrunch.com/",
-			URL: &url.URL{
-				Raw:          "http://www.techcrunch.com/",
-				Scheme:       "http",
-				RawPath:      "/",
-				RawAuthority: "www.techcrunch.com",
-				RawUserinfo:  "",
-				Host:         "www.techcrunch.com",
-				Path:         "/",
-				RawQuery:     "",
-				Fragment:     "",
-			},
-			Proto:      "HTTP/1.1",
-			ProtoMajor: 1,
-			ProtoMinor: 1,
-			Header: Header{
-				"Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
-				"Accept-Language":  {"en-us,en;q=0.5"},
-				"Accept-Encoding":  {"gzip,deflate"},
-				"Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
-				"Keep-Alive":       {"300"},
-				"Proxy-Connection": {"keep-alive"},
-				"Content-Length":   {"7"},
-				"User-Agent":       {"Fake"},
-			},
-			Close:         false,
-			ContentLength: 7,
-			Host:          "www.techcrunch.com",
-			Form:          url.Values{},
-		},
-
-		"abcdef\n",
-
-		noError,
-	},
-
-	// GET request with no body (the normal case)
-	{
-		"GET / HTTP/1.1\r\n" +
-			"Host: foo.com\r\n\r\n",
-
-		&Request{
-			Method: "GET",
-			RawURL: "/",
-			URL: &url.URL{
-				Raw:     "/",
-				Path:    "/",
-				RawPath: "/",
-			},
-			Proto:         "HTTP/1.1",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			Close:         false,
-			ContentLength: 0,
-			Host:          "foo.com",
-			Form:          url.Values{},
-		},
-
-		noBody,
-		noError,
-	},
-
-	// Tests that we don't parse a path that looks like a
-	// scheme-relative URI as a scheme-relative URI.
-	{
-		"GET //user at host/is/actually/a/path/ HTTP/1.1\r\n" +
-			"Host: test\r\n\r\n",
-
-		&Request{
-			Method: "GET",
-			RawURL: "//user at host/is/actually/a/path/",
-			URL: &url.URL{
-				Raw:          "//user at host/is/actually/a/path/",
-				Scheme:       "",
-				RawPath:      "//user at host/is/actually/a/path/",
-				RawAuthority: "",
-				RawUserinfo:  "",
-				Host:         "",
-				Path:         "//user at host/is/actually/a/path/",
-				RawQuery:     "",
-				Fragment:     "",
-			},
-			Proto:         "HTTP/1.1",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			Header:        Header{},
-			Close:         false,
-			ContentLength: 0,
-			Host:          "test",
-			Form:          url.Values{},
-		},
-
-		noBody,
-		noError,
-	},
-
-	// Tests a bogus abs_path on the Request-Line (RFC 2616 section 5.1.2)
-	{
-		"GET ../../../../etc/passwd HTTP/1.1\r\n" +
-			"Host: test\r\n\r\n",
-		nil,
-		noBody,
-		"parse ../../../../etc/passwd: invalid URI for request",
-	},
-
-	// Tests missing URL:
-	{
-		"GET  HTTP/1.1\r\n" +
-			"Host: test\r\n\r\n",
-		nil,
-		noBody,
-		"parse : empty url",
-	},
-}
-
-func TestReadRequest(t *testing.T) {
-	for i := range reqTests {
-		tt := &reqTests[i]
-		var braw bytes.Buffer
-		braw.WriteString(tt.Raw)
-		req, err := ReadRequest(bufio.NewReader(&braw))
-		if err != nil {
-			if err.String() != tt.Error {
-				t.Errorf("#%d: error %q, want error %q", i, err.String(), tt.Error)
-			}
-			continue
-		}
-		rbody := req.Body
-		req.Body = nil
-		diff(t, fmt.Sprintf("#%d Request", i), req, tt.Req)
-		var bout bytes.Buffer
-		if rbody != nil {
-			io.Copy(&bout, rbody)
-			rbody.Close()
-		}
-		body := bout.String()
-		if body != tt.Body {
-			t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
-		}
-	}
-}
diff --git a/src/pkg/http/request.go b/src/pkg/http/request.go
deleted file mode 100644
index dc344ca..0000000
--- a/src/pkg/http/request.go
+++ /dev/null
@@ -1,856 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// HTTP Request reading and parsing.
-
-// Package http implements parsing of HTTP requests, replies, and URLs and
-// provides an extensible HTTP server and a basic HTTP client.
-package http
-
-import (
-	"bufio"
-	"bytes"
-	"crypto/tls"
-	"encoding/base64"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"mime"
-	"mime/multipart"
-	"net/textproto"
-	"os"
-	"strconv"
-	"strings"
-	"url"
-)
-
-const (
-	maxLineLength    = 4096 // assumed <= bufio.defaultBufSize
-	maxValueLength   = 4096
-	maxHeaderLines   = 1024
-	chunkSize        = 4 << 10  // 4 KB chunks
-	defaultMaxMemory = 32 << 20 // 32 MB
-)
-
-// ErrMissingFile is returned by FormFile when the provided file field name
-// is either not present in the request or not a file field.
-var ErrMissingFile = os.NewError("http: no such file")
-
-// HTTP request parsing errors.
-type ProtocolError struct {
-	ErrorString string
-}
-
-func (err *ProtocolError) String() string { return err.ErrorString }
-
-var (
-	ErrLineTooLong          = &ProtocolError{"header line too long"}
-	ErrHeaderTooLong        = &ProtocolError{"header too long"}
-	ErrShortBody            = &ProtocolError{"entity body too short"}
-	ErrNotSupported         = &ProtocolError{"feature not supported"}
-	ErrUnexpectedTrailer    = &ProtocolError{"trailer header without chunked transfer encoding"}
-	ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
-	ErrNotMultipart         = &ProtocolError{"request Content-Type isn't multipart/form-data"}
-	ErrMissingBoundary      = &ProtocolError{"no multipart boundary param Content-Type"}
-)
-
-type badStringError struct {
-	what string
-	str  string
-}
-
-func (e *badStringError) String() string { return fmt.Sprintf("%s %q", e.what, e.str) }
-
-// Headers that Request.Write handles itself and should be skipped.
-var reqWriteExcludeHeader = map[string]bool{
-	"Host":              true, // not in Header map anyway
-	"User-Agent":        true,
-	"Content-Length":    true,
-	"Transfer-Encoding": true,
-	"Trailer":           true,
-}
-
-var reqWriteExcludeHeaderDump = map[string]bool{
-	"Host":              true, // not in Header map anyway
-	"Content-Length":    true,
-	"Transfer-Encoding": true,
-	"Trailer":           true,
-}
-
-// A Request represents a parsed HTTP request header.
-type Request struct {
-	Method string   // GET, POST, PUT, etc.
-	RawURL string   // The raw URL given in the request.
-	URL    *url.URL // Parsed URL.
-
-	// The protocol version for incoming requests.
-	// Outgoing requests always use HTTP/1.1.
-	Proto      string // "HTTP/1.0"
-	ProtoMajor int    // 1
-	ProtoMinor int    // 0
-
-	// A header maps request lines to their values.
-	// If the header says
-	//
-	//	accept-encoding: gzip, deflate
-	//	Accept-Language: en-us
-	//	Connection: keep-alive
-	//
-	// then
-	//
-	//	Header = map[string][]string{
-	//		"Accept-Encoding": {"gzip, deflate"},
-	//		"Accept-Language": {"en-us"},
-	//		"Connection": {"keep-alive"},
-	//	}
-	//
-	// HTTP defines that header names are case-insensitive.
-	// The request parser implements this by canonicalizing the
-	// name, making the first character and any characters
-	// following a hyphen uppercase and the rest lowercase.
-	Header Header
-
-	// The message body.
-	Body io.ReadCloser
-
-	// ContentLength records the length of the associated content.
-	// The value -1 indicates that the length is unknown.
-	// Values >= 0 indicate that the given number of bytes may be read from Body.
-	ContentLength int64
-
-	// TransferEncoding lists the transfer encodings from outermost to innermost.
-	// An empty list denotes the "identity" encoding.
-	TransferEncoding []string
-
-	// Whether to close the connection after replying to this request.
-	Close bool
-
-	// The host on which the URL is sought.
-	// Per RFC 2616, this is either the value of the Host: header
-	// or the host name given in the URL itself.
-	Host string
-
-	// The parsed form. Only available after ParseForm is called.
-	Form url.Values
-
-	// The parsed multipart form, including file uploads.
-	// Only available after ParseMultipartForm is called.
-	MultipartForm *multipart.Form
-
-	// Trailer maps trailer keys to values.  Like for Header, if the
-	// response has multiple trailer lines with the same key, they will be
-	// concatenated, delimited by commas.
-	Trailer Header
-
-	// RemoteAddr allows HTTP servers and other software to record
-	// the network address that sent the request, usually for
-	// logging. This field is not filled in by ReadRequest and
-	// has no defined format. The HTTP server in this package
-	// sets RemoteAddr to an "IP:port" address before invoking a
-	// handler.
-	RemoteAddr string
-
-	// TLS allows HTTP servers and other software to record
-	// information about the TLS connection on which the request
-	// was received. This field is not filled in by ReadRequest.
-	// The HTTP server in this package sets the field for
-	// TLS-enabled connections before invoking a handler;
-	// otherwise it leaves the field nil.
-	TLS *tls.ConnectionState
-}
-
-// ProtoAtLeast returns whether the HTTP protocol used
-// in the request is at least major.minor.
-func (r *Request) ProtoAtLeast(major, minor int) bool {
-	return r.ProtoMajor > major ||
-		r.ProtoMajor == major && r.ProtoMinor >= minor
-}
-
-// UserAgent returns the client's User-Agent, if sent in the request.
-func (r *Request) UserAgent() string {
-	return r.Header.Get("User-Agent")
-}
-
-// Cookies parses and returns the HTTP cookies sent with the request.
-func (r *Request) Cookies() []*Cookie {
-	return readCookies(r.Header, "")
-}
-
-var ErrNoCookie = os.NewError("http: named cookied not present")
-
-// Cookie returns the named cookie provided in the request or
-// ErrNoCookie if not found.
-func (r *Request) Cookie(name string) (*Cookie, os.Error) {
-	for _, c := range readCookies(r.Header, name) {
-		return c, nil
-	}
-	return nil, ErrNoCookie
-}
-
-// AddCookie adds a cookie to the request.  Per RFC 6265 section 5.4,
-// AddCookie does not attach more than one Cookie header field.  That
-// means all cookies, if any, are written into the same line,
-// separated by semicolon.
-func (r *Request) AddCookie(c *Cookie) {
-	s := fmt.Sprintf("%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
-	if c := r.Header.Get("Cookie"); c != "" {
-		r.Header.Set("Cookie", c+"; "+s)
-	} else {
-		r.Header.Set("Cookie", s)
-	}
-}
-
-// Referer returns the referring URL, if sent in the request.
-//
-// Referer is misspelled as in the request itself, a mistake from the
-// earliest days of HTTP.  This value can also be fetched from the
-// Header map as Header["Referer"]; the benefit of making it available
-// as a method is that the compiler can diagnose programs that use the
-// alternate (correct English) spelling req.Referrer() but cannot
-// diagnose programs that use Header["Referrer"].
-func (r *Request) Referer() string {
-	return r.Header.Get("Referer")
-}
-
-// multipartByReader is a sentinel value.
-// Its presence in Request.MultipartForm indicates that parsing of the request
-// body has been handed off to a MultipartReader instead of ParseMultipartFrom.
-var multipartByReader = &multipart.Form{
-	Value: make(map[string][]string),
-	File:  make(map[string][]*multipart.FileHeader),
-}
-
-// MultipartReader returns a MIME multipart reader if this is a
-// multipart/form-data POST request, else returns nil and an error.
-// Use this function instead of ParseMultipartForm to
-// process the request body as a stream.
-func (r *Request) MultipartReader() (*multipart.Reader, os.Error) {
-	if r.MultipartForm == multipartByReader {
-		return nil, os.NewError("http: MultipartReader called twice")
-	}
-	if r.MultipartForm != nil {
-		return nil, os.NewError("http: multipart handled by ParseMultipartForm")
-	}
-	r.MultipartForm = multipartByReader
-	return r.multipartReader()
-}
-
-func (r *Request) multipartReader() (*multipart.Reader, os.Error) {
-	v := r.Header.Get("Content-Type")
-	if v == "" {
-		return nil, ErrNotMultipart
-	}
-	d, params, err := mime.ParseMediaType(v)
-	if err != nil || d != "multipart/form-data" {
-		return nil, ErrNotMultipart
-	}
-	boundary, ok := params["boundary"]
-	if !ok {
-		return nil, ErrMissingBoundary
-	}
-	return multipart.NewReader(r.Body, boundary), nil
-}
-
-// Return value if nonempty, def otherwise.
-func valueOrDefault(value, def string) string {
-	if value != "" {
-		return value
-	}
-	return def
-}
-
-const defaultUserAgent = "Go http package"
-
-// Write writes an HTTP/1.1 request -- header and body -- in wire format.
-// This method consults the following fields of req:
-//	Host
-//	RawURL, if non-empty, or else URL
-//	Method (defaults to "GET")
-//	Header
-//	ContentLength
-//	TransferEncoding
-//	Body
-//
-// If Body is present, Content-Length is <= 0 and TransferEncoding
-// hasn't been set to "identity", Write adds "Transfer-Encoding:
-// chunked" to the header. Body is closed after it is sent.
-func (req *Request) Write(w io.Writer) os.Error {
-	return req.write(w, false)
-}
-
-// WriteProxy is like Write but writes the request in the form
-// expected by an HTTP proxy.  In particular, WriteProxy writes the
-// initial Request-URI line of the request with an absolute URI, per
-// section 5.1.2 of RFC 2616, including the scheme and host.  If
-// req.RawURL is non-empty, WriteProxy uses it unchanged.  In either
-// case, WriteProxy also writes a Host header, using either req.Host
-// or req.URL.Host.
-func (req *Request) WriteProxy(w io.Writer) os.Error {
-	return req.write(w, true)
-}
-
-func (req *Request) dumpWrite(w io.Writer) os.Error {
-	urlStr := req.RawURL
-	if urlStr == "" {
-		urlStr = valueOrDefault(req.URL.EncodedPath(), "/")
-		if req.URL.RawQuery != "" {
-			urlStr += "?" + req.URL.RawQuery
-		}
-	}
-
-	bw := bufio.NewWriter(w)
-	fmt.Fprintf(bw, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"), urlStr,
-		req.ProtoMajor, req.ProtoMinor)
-
-	host := req.Host
-	if host == "" && req.URL != nil {
-		host = req.URL.Host
-	}
-	if host != "" {
-		fmt.Fprintf(bw, "Host: %s\r\n", host)
-	}
-
-	// Process Body,ContentLength,Close,Trailer
-	tw, err := newTransferWriter(req)
-	if err != nil {
-		return err
-	}
-	err = tw.WriteHeader(bw)
-	if err != nil {
-		return err
-	}
-
-	err = req.Header.WriteSubset(bw, reqWriteExcludeHeaderDump)
-	if err != nil {
-		return err
-	}
-
-	io.WriteString(bw, "\r\n")
-
-	// Write body and trailer
-	err = tw.WriteBody(bw)
-	if err != nil {
-		return err
-	}
-	bw.Flush()
-	return nil
-}
-
-func (req *Request) write(w io.Writer, usingProxy bool) os.Error {
-	host := req.Host
-	if host == "" {
-		if req.URL == nil {
-			return os.NewError("http: Request.Write on Request with no Host or URL set")
-		}
-		host = req.URL.Host
-	}
-
-	urlStr := req.RawURL
-	if urlStr == "" {
-		urlStr = valueOrDefault(req.URL.EncodedPath(), "/")
-		if req.URL.RawQuery != "" {
-			urlStr += "?" + req.URL.RawQuery
-		}
-		if usingProxy {
-			if urlStr == "" || urlStr[0] != '/' {
-				urlStr = "/" + urlStr
-			}
-			urlStr = req.URL.Scheme + "://" + host + urlStr
-		}
-	}
-
-	bw := bufio.NewWriter(w)
-	fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), urlStr)
-
-	// Header lines
-	fmt.Fprintf(bw, "Host: %s\r\n", host)
-
-	// Use the defaultUserAgent unless the Header contains one, which
-	// may be blank to not send the header.
-	userAgent := defaultUserAgent
-	if req.Header != nil {
-		if ua := req.Header["User-Agent"]; len(ua) > 0 {
-			userAgent = ua[0]
-		}
-	}
-	if userAgent != "" {
-		fmt.Fprintf(bw, "User-Agent: %s\r\n", userAgent)
-	}
-
-	// Process Body,ContentLength,Close,Trailer
-	tw, err := newTransferWriter(req)
-	if err != nil {
-		return err
-	}
-	err = tw.WriteHeader(bw)
-	if err != nil {
-		return err
-	}
-
-	// TODO: split long values?  (If so, should share code with Conn.Write)
-	err = req.Header.WriteSubset(bw, reqWriteExcludeHeader)
-	if err != nil {
-		return err
-	}
-
-	io.WriteString(bw, "\r\n")
-
-	// Write body and trailer
-	err = tw.WriteBody(bw)
-	if err != nil {
-		return err
-	}
-	bw.Flush()
-	return nil
-}
-
-// Read a line of bytes (up to \n) from b.
-// Give up if the line exceeds maxLineLength.
-// The returned bytes are a pointer into storage in
-// the bufio, so they are only valid until the next bufio read.
-func readLineBytes(b *bufio.Reader) (p []byte, err os.Error) {
-	if p, err = b.ReadSlice('\n'); err != nil {
-		// We always know when EOF is coming.
-		// If the caller asked for a line, there should be a line.
-		if err == os.EOF {
-			err = io.ErrUnexpectedEOF
-		} else if err == bufio.ErrBufferFull {
-			err = ErrLineTooLong
-		}
-		return nil, err
-	}
-	if len(p) >= maxLineLength {
-		return nil, ErrLineTooLong
-	}
-
-	// Chop off trailing white space.
-	var i int
-	for i = len(p); i > 0; i-- {
-		if c := p[i-1]; c != ' ' && c != '\r' && c != '\t' && c != '\n' {
-			break
-		}
-	}
-	return p[0:i], nil
-}
-
-// readLineBytes, but convert the bytes into a string.
-func readLine(b *bufio.Reader) (s string, err os.Error) {
-	p, e := readLineBytes(b)
-	if e != nil {
-		return "", e
-	}
-	return string(p), nil
-}
-
-// Convert decimal at s[i:len(s)] to integer,
-// returning value, string position where the digits stopped,
-// and whether there was a valid number (digits, not too big).
-func atoi(s string, i int) (n, i1 int, ok bool) {
-	const Big = 1000000
-	if i >= len(s) || s[i] < '0' || s[i] > '9' {
-		return 0, 0, false
-	}
-	n = 0
-	for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
-		n = n*10 + int(s[i]-'0')
-		if n > Big {
-			return 0, 0, false
-		}
-	}
-	return n, i, true
-}
-
-// ParseHTTPVersion parses a HTTP version string.
-// "HTTP/1.0" returns (1, 0, true).
-func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
-	if len(vers) < 5 || vers[0:5] != "HTTP/" {
-		return 0, 0, false
-	}
-	major, i, ok := atoi(vers, 5)
-	if !ok || i >= len(vers) || vers[i] != '.' {
-		return 0, 0, false
-	}
-	minor, i, ok = atoi(vers, i+1)
-	if !ok || i != len(vers) {
-		return 0, 0, false
-	}
-	return major, minor, true
-}
-
-type chunkedReader struct {
-	r   *bufio.Reader
-	n   uint64 // unread bytes in chunk
-	err os.Error
-}
-
-func (cr *chunkedReader) beginChunk() {
-	// chunk-size CRLF
-	var line string
-	line, cr.err = readLine(cr.r)
-	if cr.err != nil {
-		return
-	}
-	cr.n, cr.err = strconv.Btoui64(line, 16)
-	if cr.err != nil {
-		return
-	}
-	if cr.n == 0 {
-		// trailer CRLF
-		for {
-			line, cr.err = readLine(cr.r)
-			if cr.err != nil {
-				return
-			}
-			if line == "" {
-				break
-			}
-		}
-		cr.err = os.EOF
-	}
-}
-
-func (cr *chunkedReader) Read(b []uint8) (n int, err os.Error) {
-	if cr.err != nil {
-		return 0, cr.err
-	}
-	if cr.n == 0 {
-		cr.beginChunk()
-		if cr.err != nil {
-			return 0, cr.err
-		}
-	}
-	if uint64(len(b)) > cr.n {
-		b = b[0:cr.n]
-	}
-	n, cr.err = cr.r.Read(b)
-	cr.n -= uint64(n)
-	if cr.n == 0 && cr.err == nil {
-		// end of chunk (CRLF)
-		b := make([]byte, 2)
-		if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
-			if b[0] != '\r' || b[1] != '\n' {
-				cr.err = os.NewError("malformed chunked encoding")
-			}
-		}
-	}
-	return n, cr.err
-}
-
-// NewRequest returns a new Request given a method, URL, and optional body.
-func NewRequest(method, urlStr string, body io.Reader) (*Request, os.Error) {
-	u, err := url.Parse(urlStr)
-	if err != nil {
-		return nil, err
-	}
-	rc, ok := body.(io.ReadCloser)
-	if !ok && body != nil {
-		rc = ioutil.NopCloser(body)
-	}
-	req := &Request{
-		Method:     method,
-		URL:        u,
-		Proto:      "HTTP/1.1",
-		ProtoMajor: 1,
-		ProtoMinor: 1,
-		Header:     make(Header),
-		Body:       rc,
-		Host:       u.Host,
-	}
-	if body != nil {
-		switch v := body.(type) {
-		case *strings.Reader:
-			req.ContentLength = int64(v.Len())
-		case *bytes.Buffer:
-			req.ContentLength = int64(v.Len())
-		}
-	}
-
-	return req, nil
-}
-
-// SetBasicAuth sets the request's Authorization header to use HTTP
-// Basic Authentication with the provided username and password.
-//
-// With HTTP Basic Authentication the provided username and password
-// are not encrypted.
-func (r *Request) SetBasicAuth(username, password string) {
-	s := username + ":" + password
-	r.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
-}
-
-// ReadRequest reads and parses a request from b.
-func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
-
-	tp := textproto.NewReader(b)
-	req = new(Request)
-
-	// First line: GET /index.html HTTP/1.0
-	var s string
-	if s, err = tp.ReadLine(); err != nil {
-		if err == os.EOF {
-			err = io.ErrUnexpectedEOF
-		}
-		return nil, err
-	}
-
-	var f []string
-	if f = strings.SplitN(s, " ", 3); len(f) < 3 {
-		return nil, &badStringError{"malformed HTTP request", s}
-	}
-	req.Method, req.RawURL, req.Proto = f[0], f[1], f[2]
-	var ok bool
-	if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
-		return nil, &badStringError{"malformed HTTP version", req.Proto}
-	}
-
-	if req.URL, err = url.ParseRequest(req.RawURL); err != nil {
-		return nil, err
-	}
-
-	// Subsequent lines: Key: value.
-	mimeHeader, err := tp.ReadMIMEHeader()
-	if err != nil {
-		return nil, err
-	}
-	req.Header = Header(mimeHeader)
-
-	// RFC2616: Must treat
-	//	GET /index.html HTTP/1.1
-	//	Host: www.google.com
-	// and
-	//	GET http://www.google.com/index.html HTTP/1.1
-	//	Host: doesntmatter
-	// the same.  In the second case, any Host line is ignored.
-	req.Host = req.URL.Host
-	if req.Host == "" {
-		req.Host = req.Header.Get("Host")
-	}
-	req.Header.Del("Host")
-
-	fixPragmaCacheControl(req.Header)
-
-	// TODO: Parse specific header values:
-	//	Accept
-	//	Accept-Encoding
-	//	Accept-Language
-	//	Authorization
-	//	Cache-Control
-	//	Connection
-	//	Date
-	//	Expect
-	//	From
-	//	If-Match
-	//	If-Modified-Since
-	//	If-None-Match
-	//	If-Range
-	//	If-Unmodified-Since
-	//	Max-Forwards
-	//	Proxy-Authorization
-	//	Referer [sic]
-	//	TE (transfer-codings)
-	//	Trailer
-	//	Transfer-Encoding
-	//	Upgrade
-	//	User-Agent
-	//	Via
-	//	Warning
-
-	err = readTransfer(req, b)
-	if err != nil {
-		return nil, err
-	}
-
-	return req, nil
-}
-
-// MaxBytesReader is similar to io.LimitReader but is intended for
-// limiting the size of incoming request bodies. In contrast to
-// io.LimitReader, MaxBytesReader's result is a ReadCloser, returns a
-// non-EOF error for a Read beyond the limit, and Closes the
-// underlying reader when its Close method is called.
-//
-// MaxBytesReader prevents clients from accidentally or maliciously
-// sending a large request and wasting server resources.
-func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
-	return &maxBytesReader{w: w, r: r, n: n}
-}
-
-type maxBytesReader struct {
-	w       ResponseWriter
-	r       io.ReadCloser // underlying reader
-	n       int64         // max bytes remaining
-	stopped bool
-}
-
-func (l *maxBytesReader) Read(p []byte) (n int, err os.Error) {
-	if l.n <= 0 {
-		if !l.stopped {
-			l.stopped = true
-			if res, ok := l.w.(*response); ok {
-				res.requestTooLarge()
-			}
-		}
-		return 0, os.NewError("http: request body too large")
-	}
-	if int64(len(p)) > l.n {
-		p = p[:l.n]
-	}
-	n, err = l.r.Read(p)
-	l.n -= int64(n)
-	return
-}
-
-func (l *maxBytesReader) Close() os.Error {
-	return l.r.Close()
-}
-
-// ParseForm parses the raw query from the URL.
-//
-// For POST or PUT requests, it also parses the request body as a form.
-// If the request Body's size has not already been limited by MaxBytesReader,
-// the size is capped at 10MB.
-//
-// ParseMultipartForm calls ParseForm automatically.
-// It is idempotent.
-func (r *Request) ParseForm() (err os.Error) {
-	if r.Form != nil {
-		return
-	}
-	if r.URL != nil {
-		r.Form, err = url.ParseQuery(r.URL.RawQuery)
-	}
-	if r.Method == "POST" || r.Method == "PUT" {
-		if r.Body == nil {
-			return os.NewError("missing form body")
-		}
-		ct := r.Header.Get("Content-Type")
-		ct, _, err := mime.ParseMediaType(ct)
-		switch {
-		case ct == "text/plain" || ct == "application/x-www-form-urlencoded" || ct == "":
-			var reader io.Reader = r.Body
-			maxFormSize := int64(1<<63 - 1)
-			if _, ok := r.Body.(*maxBytesReader); !ok {
-				maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
-				reader = io.LimitReader(r.Body, maxFormSize+1)
-			}
-			b, e := ioutil.ReadAll(reader)
-			if e != nil {
-				if err == nil {
-					err = e
-				}
-				break
-			}
-			if int64(len(b)) > maxFormSize {
-				return os.NewError("http: POST too large")
-			}
-			var newValues url.Values
-			newValues, e = url.ParseQuery(string(b))
-			if err == nil {
-				err = e
-			}
-			if r.Form == nil {
-				r.Form = make(url.Values)
-			}
-			// Copy values into r.Form. TODO: make this smoother.
-			for k, vs := range newValues {
-				for _, value := range vs {
-					r.Form.Add(k, value)
-				}
-			}
-		case ct == "multipart/form-data":
-			// handled by ParseMultipartForm (which is calling us, or should be)
-			// TODO(bradfitz): there are too many possible
-			// orders to call too many functions here.
-			// Clean this up and write more tests.
-			// request_test.go contains the start of this,
-			// in TestRequestMultipartCallOrder.
-		default:
-			return &badStringError{"unknown Content-Type", ct}
-		}
-	}
-	return err
-}
-
-// ParseMultipartForm parses a request body as multipart/form-data.
-// The whole request body is parsed and up to a total of maxMemory bytes of
-// its file parts are stored in memory, with the remainder stored on
-// disk in temporary files.
-// ParseMultipartForm calls ParseForm if necessary.
-// After one call to ParseMultipartForm, subsequent calls have no effect.
-func (r *Request) ParseMultipartForm(maxMemory int64) os.Error {
-	if r.MultipartForm == multipartByReader {
-		return os.NewError("http: multipart handled by MultipartReader")
-	}
-	if r.Form == nil {
-		err := r.ParseForm()
-		if err != nil {
-			return err
-		}
-	}
-	if r.MultipartForm != nil {
-		return nil
-	}
-
-	mr, err := r.multipartReader()
-	if err == ErrNotMultipart {
-		return nil
-	} else if err != nil {
-		return err
-	}
-
-	f, err := mr.ReadForm(maxMemory)
-	if err != nil {
-		return err
-	}
-	for k, v := range f.Value {
-		r.Form[k] = append(r.Form[k], v...)
-	}
-	r.MultipartForm = f
-
-	return nil
-}
-
-// FormValue returns the first value for the named component of the query.
-// FormValue calls ParseMultipartForm and ParseForm if necessary.
-func (r *Request) FormValue(key string) string {
-	if r.Form == nil {
-		r.ParseMultipartForm(defaultMaxMemory)
-	}
-	if vs := r.Form[key]; len(vs) > 0 {
-		return vs[0]
-	}
-	return ""
-}
-
-// FormFile returns the first file for the provided form key.
-// FormFile calls ParseMultipartForm and ParseForm if necessary.
-func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, os.Error) {
-	if r.MultipartForm == multipartByReader {
-		return nil, nil, os.NewError("http: multipart handled by MultipartReader")
-	}
-	if r.MultipartForm == nil {
-		err := r.ParseMultipartForm(defaultMaxMemory)
-		if err != nil {
-			return nil, nil, err
-		}
-	}
-	if r.MultipartForm != nil && r.MultipartForm.File != nil {
-		if fhs := r.MultipartForm.File[key]; len(fhs) > 0 {
-			f, err := fhs[0].Open()
-			return f, fhs[0], err
-		}
-	}
-	return nil, nil, ErrMissingFile
-}
-
-func (r *Request) expectsContinue() bool {
-	return strings.ToLower(r.Header.Get("Expect")) == "100-continue"
-}
-
-func (r *Request) wantsHttp10KeepAlive() bool {
-	if r.ProtoMajor != 1 || r.ProtoMinor != 0 {
-		return false
-	}
-	return strings.Contains(strings.ToLower(r.Header.Get("Connection")), "keep-alive")
-}
diff --git a/src/pkg/http/request_test.go b/src/pkg/http/request_test.go
deleted file mode 100644
index 175d6f1..0000000
--- a/src/pkg/http/request_test.go
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http_test
-
-import (
-	"bytes"
-	"fmt"
-	. "http"
-	"http/httptest"
-	"io"
-	"io/ioutil"
-	"mime/multipart"
-	"os"
-	"reflect"
-	"regexp"
-	"strings"
-	"testing"
-	"url"
-)
-
-func TestQuery(t *testing.T) {
-	req := &Request{Method: "GET"}
-	req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
-	if q := req.FormValue("q"); q != "foo" {
-		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
-	}
-}
-
-func TestPostQuery(t *testing.T) {
-	req := &Request{Method: "POST"}
-	req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar&both=x")
-	req.Header = Header{
-		"Content-Type": {"application/x-www-form-urlencoded; boo!"},
-	}
-	req.Body = ioutil.NopCloser(strings.NewReader("z=post&both=y"))
-	if q := req.FormValue("q"); q != "foo" {
-		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
-	}
-	if z := req.FormValue("z"); z != "post" {
-		t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
-	}
-	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"x", "y"}) {
-		t.Errorf(`req.FormValue("both") = %q, want ["x", "y"]`, both)
-	}
-}
-
-type stringMap map[string][]string
-type parseContentTypeTest struct {
-	contentType stringMap
-	error       bool
-}
-
-var parseContentTypeTests = []parseContentTypeTest{
-	{contentType: stringMap{"Content-Type": {"text/plain"}}},
-	{contentType: stringMap{}}, // Non-existent keys are not placed. The value nil is illegal.
-	{contentType: stringMap{"Content-Type": {"text/plain; boundary="}}},
-	{
-		contentType: stringMap{"Content-Type": {"application/unknown"}},
-		error:       true,
-	},
-}
-
-func TestPostContentTypeParsing(t *testing.T) {
-	for i, test := range parseContentTypeTests {
-		req := &Request{
-			Method: "POST",
-			Header: Header(test.contentType),
-			Body:   ioutil.NopCloser(bytes.NewBufferString("body")),
-		}
-		err := req.ParseForm()
-		if !test.error && err != nil {
-			t.Errorf("test %d: Unexpected error: %v", i, err)
-		}
-		if test.error && err == nil {
-			t.Errorf("test %d should have returned error", i)
-		}
-	}
-}
-
-func TestMultipartReader(t *testing.T) {
-	req := &Request{
-		Method: "POST",
-		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
-		Body:   ioutil.NopCloser(new(bytes.Buffer)),
-	}
-	multipart, err := req.MultipartReader()
-	if multipart == nil {
-		t.Errorf("expected multipart; error: %v", err)
-	}
-
-	req.Header = Header{"Content-Type": {"text/plain"}}
-	multipart, err = req.MultipartReader()
-	if multipart != nil {
-		t.Errorf("unexpected multipart for text/plain")
-	}
-}
-
-func TestRedirect(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		switch r.URL.Path {
-		case "/":
-			w.Header().Set("Location", "/foo/")
-			w.WriteHeader(StatusSeeOther)
-		case "/foo/":
-			fmt.Fprintf(w, "foo")
-		default:
-			w.WriteHeader(StatusBadRequest)
-		}
-	}))
-	defer ts.Close()
-
-	var end = regexp.MustCompile("/foo/$")
-	r, err := Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	r.Body.Close()
-	url := r.Request.URL.String()
-	if r.StatusCode != 200 || !end.MatchString(url) {
-		t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
-	}
-}
-
-func TestSetBasicAuth(t *testing.T) {
-	r, _ := NewRequest("GET", "http://example.com/", nil)
-	r.SetBasicAuth("Aladdin", "open sesame")
-	if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e {
-		t.Errorf("got header %q, want %q", g, e)
-	}
-}
-
-func TestMultipartRequest(t *testing.T) {
-	// Test that we can read the values and files of a 
-	// multipart request with FormValue and FormFile,
-	// and that ParseMultipartForm can be called multiple times.
-	req := newTestMultipartRequest(t)
-	if err := req.ParseMultipartForm(25); err != nil {
-		t.Fatal("ParseMultipartForm first call:", err)
-	}
-	defer req.MultipartForm.RemoveAll()
-	validateTestMultipartContents(t, req, false)
-	if err := req.ParseMultipartForm(25); err != nil {
-		t.Fatal("ParseMultipartForm second call:", err)
-	}
-	validateTestMultipartContents(t, req, false)
-}
-
-func TestMultipartRequestAuto(t *testing.T) {
-	// Test that FormValue and FormFile automatically invoke
-	// ParseMultipartForm and return the right values.
-	req := newTestMultipartRequest(t)
-	defer func() {
-		if req.MultipartForm != nil {
-			req.MultipartForm.RemoveAll()
-		}
-	}()
-	validateTestMultipartContents(t, req, true)
-}
-
-func TestEmptyMultipartRequest(t *testing.T) {
-	// Test that FormValue and FormFile automatically invoke
-	// ParseMultipartForm and return the right values.
-	req, err := NewRequest("GET", "/", nil)
-	if err != nil {
-		t.Errorf("NewRequest err = %q", err)
-	}
-	testMissingFile(t, req)
-}
-
-func TestRequestMultipartCallOrder(t *testing.T) {
-	req := newTestMultipartRequest(t)
-	_, err := req.MultipartReader()
-	if err != nil {
-		t.Fatalf("MultipartReader: %v", err)
-	}
-	err = req.ParseMultipartForm(1024)
-	if err == nil {
-		t.Errorf("expected an error from ParseMultipartForm after call to MultipartReader")
-	}
-}
-
-func testMissingFile(t *testing.T, req *Request) {
-	f, fh, err := req.FormFile("missing")
-	if f != nil {
-		t.Errorf("FormFile file = %q, want nil", f)
-	}
-	if fh != nil {
-		t.Errorf("FormFile file header = %q, want nil", fh)
-	}
-	if err != ErrMissingFile {
-		t.Errorf("FormFile err = %q, want ErrMissingFile", err)
-	}
-}
-
-func newTestMultipartRequest(t *testing.T) *Request {
-	b := bytes.NewBufferString(strings.Replace(message, "\n", "\r\n", -1))
-	req, err := NewRequest("POST", "/", b)
-	if err != nil {
-		t.Fatal("NewRequest:", err)
-	}
-	ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
-	req.Header.Set("Content-type", ctype)
-	return req
-}
-
-func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
-	if g, e := req.FormValue("texta"), textaValue; g != e {
-		t.Errorf("texta value = %q, want %q", g, e)
-	}
-	if g, e := req.FormValue("texta"), textaValue; g != e {
-		t.Errorf("texta value = %q, want %q", g, e)
-	}
-	if g := req.FormValue("missing"); g != "" {
-		t.Errorf("missing value = %q, want empty string", g)
-	}
-
-	assertMem := func(n string, fd multipart.File) {
-		if _, ok := fd.(*os.File); ok {
-			t.Error(n, " is *os.File, should not be")
-		}
-	}
-	fd := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
-	assertMem("filea", fd)
-	fd = testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
-	if allMem {
-		assertMem("fileb", fd)
-	} else {
-		if _, ok := fd.(*os.File); !ok {
-			t.Errorf("fileb has unexpected underlying type %T", fd)
-		}
-	}
-
-	testMissingFile(t, req)
-}
-
-func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
-	f, fh, err := req.FormFile(key)
-	if err != nil {
-		t.Fatalf("FormFile(%q): %q", key, err)
-	}
-	if fh.Filename != expectFilename {
-		t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
-	}
-	var b bytes.Buffer
-	_, err = io.Copy(&b, f)
-	if err != nil {
-		t.Fatal("copying contents:", err)
-	}
-	if g := b.String(); g != expectContent {
-		t.Errorf("contents = %q, want %q", g, expectContent)
-	}
-	return f
-}
-
-const (
-	fileaContents = "This is a test file."
-	filebContents = "Another test file."
-	textaValue    = "foo"
-	textbValue    = "bar"
-	boundary      = `MyBoundary`
-)
-
-const message = `
---MyBoundary
-Content-Disposition: form-data; name="filea"; filename="filea.txt"
-Content-Type: text/plain
-
-` + fileaContents + `
---MyBoundary
-Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
-Content-Type: text/plain
-
-` + filebContents + `
---MyBoundary
-Content-Disposition: form-data; name="texta"
-
-` + textaValue + `
---MyBoundary
-Content-Disposition: form-data; name="textb"
-
-` + textbValue + `
---MyBoundary--
-`
diff --git a/src/pkg/http/requestwrite_test.go b/src/pkg/http/requestwrite_test.go
deleted file mode 100644
index 8c29c44..0000000
--- a/src/pkg/http/requestwrite_test.go
+++ /dev/null
@@ -1,466 +0,0 @@
-// Copyright 2010 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 http
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"strings"
-	"testing"
-	"url"
-)
-
-type reqWriteTest struct {
-	Req  Request
-	Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
-
-	// Any of these three may be empty to skip that test.
-	WantWrite string // Request.Write
-	WantProxy string // Request.WriteProxy
-	WantDump  string // DumpRequest
-
-	WantError os.Error // wanted error from Request.Write
-}
-
-var reqWriteTests = []reqWriteTest{
-	// HTTP/1.1 => chunked coding; no body; no trailer
-	{
-		Req: Request{
-			Method: "GET",
-			RawURL: "http://www.techcrunch.com/",
-			URL: &url.URL{
-				Raw:          "http://www.techcrunch.com/",
-				Scheme:       "http",
-				RawPath:      "http://www.techcrunch.com/",
-				RawAuthority: "www.techcrunch.com",
-				RawUserinfo:  "",
-				Host:         "www.techcrunch.com",
-				Path:         "/",
-				RawQuery:     "",
-				Fragment:     "",
-			},
-			Proto:      "HTTP/1.1",
-			ProtoMajor: 1,
-			ProtoMinor: 1,
-			Header: Header{
-				"Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
-				"Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
-				"Accept-Encoding":  {"gzip,deflate"},
-				"Accept-Language":  {"en-us,en;q=0.5"},
-				"Keep-Alive":       {"300"},
-				"Proxy-Connection": {"keep-alive"},
-				"User-Agent":       {"Fake"},
-			},
-			Body:  nil,
-			Close: false,
-			Host:  "www.techcrunch.com",
-			Form:  map[string][]string{},
-		},
-
-		WantWrite: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
-			"Host: www.techcrunch.com\r\n" +
-			"User-Agent: Fake\r\n" +
-			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
-			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
-			"Accept-Encoding: gzip,deflate\r\n" +
-			"Accept-Language: en-us,en;q=0.5\r\n" +
-			"Keep-Alive: 300\r\n" +
-			"Proxy-Connection: keep-alive\r\n\r\n",
-
-		WantProxy: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
-			"Host: www.techcrunch.com\r\n" +
-			"User-Agent: Fake\r\n" +
-			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
-			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
-			"Accept-Encoding: gzip,deflate\r\n" +
-			"Accept-Language: en-us,en;q=0.5\r\n" +
-			"Keep-Alive: 300\r\n" +
-			"Proxy-Connection: keep-alive\r\n\r\n",
-	},
-	// HTTP/1.1 => chunked coding; body; empty trailer
-	{
-		Req: Request{
-			Method: "GET",
-			URL: &url.URL{
-				Scheme: "http",
-				Host:   "www.google.com",
-				Path:   "/search",
-			},
-			ProtoMajor:       1,
-			ProtoMinor:       1,
-			Header:           Header{},
-			TransferEncoding: []string{"chunked"},
-		},
-
-		Body: []byte("abcdef"),
-
-		WantWrite: "GET /search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Transfer-Encoding: chunked\r\n\r\n" +
-			chunk("abcdef") + chunk(""),
-
-		WantProxy: "GET http://www.google.com/search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Transfer-Encoding: chunked\r\n\r\n" +
-			chunk("abcdef") + chunk(""),
-
-		WantDump: "GET /search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"Transfer-Encoding: chunked\r\n\r\n" +
-			chunk("abcdef") + chunk(""),
-	},
-	// HTTP/1.1 POST => chunked coding; body; empty trailer
-	{
-		Req: Request{
-			Method: "POST",
-			URL: &url.URL{
-				Scheme: "http",
-				Host:   "www.google.com",
-				Path:   "/search",
-			},
-			ProtoMajor:       1,
-			ProtoMinor:       1,
-			Header:           Header{},
-			Close:            true,
-			TransferEncoding: []string{"chunked"},
-		},
-
-		Body: []byte("abcdef"),
-
-		WantWrite: "POST /search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Connection: close\r\n" +
-			"Transfer-Encoding: chunked\r\n\r\n" +
-			chunk("abcdef") + chunk(""),
-
-		WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Connection: close\r\n" +
-			"Transfer-Encoding: chunked\r\n\r\n" +
-			chunk("abcdef") + chunk(""),
-	},
-
-	// HTTP/1.1 POST with Content-Length, no chunking
-	{
-		Req: Request{
-			Method: "POST",
-			URL: &url.URL{
-				Scheme: "http",
-				Host:   "www.google.com",
-				Path:   "/search",
-			},
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			Header:        Header{},
-			Close:         true,
-			ContentLength: 6,
-		},
-
-		Body: []byte("abcdef"),
-
-		WantWrite: "POST /search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Connection: close\r\n" +
-			"Content-Length: 6\r\n" +
-			"\r\n" +
-			"abcdef",
-
-		WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Connection: close\r\n" +
-			"Content-Length: 6\r\n" +
-			"\r\n" +
-			"abcdef",
-	},
-
-	// HTTP/1.1 POST with Content-Length in headers
-	{
-		Req: Request{
-			Method: "POST",
-			RawURL: "http://example.com/",
-			Host:   "example.com",
-			Header: Header{
-				"Content-Length": []string{"10"}, // ignored
-			},
-			ContentLength: 6,
-		},
-
-		Body: []byte("abcdef"),
-
-		WantWrite: "POST http://example.com/ HTTP/1.1\r\n" +
-			"Host: example.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Content-Length: 6\r\n" +
-			"\r\n" +
-			"abcdef",
-
-		WantProxy: "POST http://example.com/ HTTP/1.1\r\n" +
-			"Host: example.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Content-Length: 6\r\n" +
-			"\r\n" +
-			"abcdef",
-	},
-
-	// default to HTTP/1.1
-	{
-		Req: Request{
-			Method: "GET",
-			RawURL: "/search",
-			Host:   "www.google.com",
-		},
-
-		WantWrite: "GET /search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"\r\n",
-
-		// Looks weird but RawURL overrides what WriteProxy would choose.
-		WantProxy: "GET /search HTTP/1.1\r\n" +
-			"Host: www.google.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"\r\n",
-	},
-
-	// Request with a 0 ContentLength and a 0 byte body.
-	{
-		Req: Request{
-			Method:        "POST",
-			RawURL:        "/",
-			Host:          "example.com",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			ContentLength: 0, // as if unset by user
-		},
-
-		Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
-
-		// RFC 2616 Section 14.13 says Content-Length should be specified
-		// unless body is prohibited by the request method.
-		// Also, nginx expects it for POST and PUT.
-		WantWrite: "POST / HTTP/1.1\r\n" +
-			"Host: example.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Content-Length: 0\r\n" +
-			"\r\n",
-
-		WantProxy: "POST / HTTP/1.1\r\n" +
-			"Host: example.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Content-Length: 0\r\n" +
-			"\r\n",
-	},
-
-	// Request with a 0 ContentLength and a 1 byte body.
-	{
-		Req: Request{
-			Method:        "POST",
-			RawURL:        "/",
-			Host:          "example.com",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			ContentLength: 0, // as if unset by user
-		},
-
-		Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
-
-		WantWrite: "POST / HTTP/1.1\r\n" +
-			"Host: example.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Transfer-Encoding: chunked\r\n\r\n" +
-			chunk("x") + chunk(""),
-
-		WantProxy: "POST / HTTP/1.1\r\n" +
-			"Host: example.com\r\n" +
-			"User-Agent: Go http package\r\n" +
-			"Transfer-Encoding: chunked\r\n\r\n" +
-			chunk("x") + chunk(""),
-	},
-
-	// Request with a ContentLength of 10 but a 5 byte body.
-	{
-		Req: Request{
-			Method:        "POST",
-			RawURL:        "/",
-			Host:          "example.com",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			ContentLength: 10, // but we're going to send only 5 bytes
-		},
-		Body:      []byte("12345"),
-		WantError: os.NewError("http: Request.ContentLength=10 with Body length 5"),
-	},
-
-	// Request with a ContentLength of 4 but an 8 byte body.
-	{
-		Req: Request{
-			Method:        "POST",
-			RawURL:        "/",
-			Host:          "example.com",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			ContentLength: 4, // but we're going to try to send 8 bytes
-		},
-		Body:      []byte("12345678"),
-		WantError: os.NewError("http: Request.ContentLength=4 with Body length 8"),
-	},
-
-	// Request with a 5 ContentLength and nil body.
-	{
-		Req: Request{
-			Method:        "POST",
-			RawURL:        "/",
-			Host:          "example.com",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			ContentLength: 5, // but we'll omit the body
-		},
-		WantError: os.NewError("http: Request.ContentLength=5 with nil Body"),
-	},
-
-	// Verify that DumpRequest preserves the HTTP version number, doesn't add a Host,
-	// and doesn't add a User-Agent.
-	{
-		Req: Request{
-			Method:     "GET",
-			RawURL:     "/foo",
-			ProtoMajor: 1,
-			ProtoMinor: 0,
-			Header: Header{
-				"X-Foo": []string{"X-Bar"},
-			},
-		},
-
-		// We can dump it:
-		WantDump: "GET /foo HTTP/1.0\r\n" +
-			"X-Foo: X-Bar\r\n\r\n",
-
-		// .. but we can't call Request.Write on it, due to its lack of Host header.
-		// TODO(bradfitz): there might be an argument to allow this, but for now I'd
-		// rather let HTTP/1.0 continue to die.
-		WantError: os.NewError("http: Request.Write on Request with no Host or URL set"),
-	},
-}
-
-func TestRequestWrite(t *testing.T) {
-	for i := range reqWriteTests {
-		tt := &reqWriteTests[i]
-
-		setBody := func() {
-			if tt.Body == nil {
-				return
-			}
-			switch b := tt.Body.(type) {
-			case []byte:
-				tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
-			case func() io.ReadCloser:
-				tt.Req.Body = b()
-			}
-		}
-		setBody()
-		if tt.Req.Header == nil {
-			tt.Req.Header = make(Header)
-		}
-
-		var braw bytes.Buffer
-		err := tt.Req.Write(&braw)
-		if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.WantError); g != e {
-			t.Errorf("writing #%d, err = %q, want %q", i, g, e)
-			continue
-		}
-		if err != nil {
-			continue
-		}
-
-		if tt.WantWrite != "" {
-			sraw := braw.String()
-			if sraw != tt.WantWrite {
-				t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantWrite, sraw)
-				continue
-			}
-		}
-
-		if tt.WantProxy != "" {
-			setBody()
-			var praw bytes.Buffer
-			err = tt.Req.WriteProxy(&praw)
-			if err != nil {
-				t.Errorf("WriteProxy #%d: %s", i, err)
-				continue
-			}
-			sraw := praw.String()
-			if sraw != tt.WantProxy {
-				t.Errorf("Test Proxy %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantProxy, sraw)
-				continue
-			}
-		}
-
-		if tt.WantDump != "" {
-			setBody()
-			dump, err := DumpRequest(&tt.Req, true)
-			if err != nil {
-				t.Errorf("DumpRequest #%d: %s", i, err)
-				continue
-			}
-			if string(dump) != tt.WantDump {
-				t.Errorf("DumpRequest %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantDump, string(dump))
-				continue
-			}
-		}
-	}
-}
-
-type closeChecker struct {
-	io.Reader
-	closed bool
-}
-
-func (rc *closeChecker) Close() os.Error {
-	rc.closed = true
-	return nil
-}
-
-// TestRequestWriteClosesBody tests that Request.Write does close its request.Body.
-// It also indirectly tests NewRequest and that it doesn't wrap an existing Closer
-// inside a NopCloser, and that it serializes it correctly.
-func TestRequestWriteClosesBody(t *testing.T) {
-	rc := &closeChecker{Reader: strings.NewReader("my body")}
-	req, _ := NewRequest("POST", "http://foo.com/", rc)
-	if req.ContentLength != 0 {
-		t.Errorf("got req.ContentLength %d, want 0", req.ContentLength)
-	}
-	buf := new(bytes.Buffer)
-	req.Write(buf)
-	if !rc.closed {
-		t.Error("body not closed after write")
-	}
-	expected := "POST / HTTP/1.1\r\n" +
-		"Host: foo.com\r\n" +
-		"User-Agent: Go http package\r\n" +
-		"Transfer-Encoding: chunked\r\n\r\n" +
-		// TODO: currently we don't buffer before chunking, so we get a
-		// single "m" chunk before the other chunks, as this was the 1-byte
-		// read from our MultiReader where we stiched the Body back together
-		// after sniffing whether the Body was 0 bytes or not.
-		chunk("m") +
-		chunk("y body") +
-		chunk("")
-	if buf.String() != expected {
-		t.Errorf("write:\n got: %s\nwant: %s", buf.String(), expected)
-	}
-}
-
-func chunk(s string) string {
-	return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
-}
diff --git a/src/pkg/http/response.go b/src/pkg/http/response.go
deleted file mode 100644
index b01a303..0000000
--- a/src/pkg/http/response.go
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// HTTP Response reading and parsing.
-
-package http
-
-import (
-	"bufio"
-	"io"
-	"net/textproto"
-	"os"
-	"strconv"
-	"strings"
-)
-
-var respExcludeHeader = map[string]bool{
-	"Content-Length":    true,
-	"Transfer-Encoding": true,
-	"Trailer":           true,
-}
-
-// Response represents the response from an HTTP request.
-//
-type Response struct {
-	Status     string // e.g. "200 OK"
-	StatusCode int    // e.g. 200
-	Proto      string // e.g. "HTTP/1.0"
-	ProtoMajor int    // e.g. 1
-	ProtoMinor int    // e.g. 0
-
-	// Header maps header keys to values.  If the response had multiple
-	// headers with the same key, they will be concatenated, with comma
-	// delimiters.  (Section 4.2 of RFC 2616 requires that multiple headers
-	// be semantically equivalent to a comma-delimited sequence.) Values
-	// duplicated by other fields in this struct (e.g., ContentLength) are
-	// omitted from Header.
-	//
-	// Keys in the map are canonicalized (see CanonicalHeaderKey).
-	Header Header
-
-	// Body represents the response body.
-	//
-	// The http Client and Transport guarantee that Body is always
-	// non-nil, even on responses without a body or responses with
-	// a zero-lengthed body.
-	Body io.ReadCloser
-
-	// ContentLength records the length of the associated content.  The
-	// value -1 indicates that the length is unknown.  Unless RequestMethod
-	// is "HEAD", values >= 0 indicate that the given number of bytes may
-	// be read from Body.
-	ContentLength int64
-
-	// Contains transfer encodings from outer-most to inner-most. Value is
-	// nil, means that "identity" encoding is used.
-	TransferEncoding []string
-
-	// Close records whether the header directed that the connection be
-	// closed after reading Body.  The value is advice for clients: neither
-	// ReadResponse nor Response.Write ever closes a connection.
-	Close bool
-
-	// Trailer maps trailer keys to values, in the same
-	// format as the header.
-	Trailer Header
-
-	// The Request that was sent to obtain this Response.
-	// Request's Body is nil (having already been consumed).
-	// This is only populated for Client requests.
-	Request *Request
-}
-
-// Cookies parses and returns the cookies set in the Set-Cookie headers.
-func (r *Response) Cookies() []*Cookie {
-	return readSetCookies(r.Header)
-}
-
-// ReadResponse reads and returns an HTTP response from r.  The
-// req parameter specifies the Request that corresponds to
-// this Response.  Clients must call resp.Body.Close when finished
-// reading resp.Body.  After that call, clients can inspect
-// resp.Trailer to find key/value pairs included in the response
-// trailer.
-func ReadResponse(r *bufio.Reader, req *Request) (resp *Response, err os.Error) {
-
-	tp := textproto.NewReader(r)
-	resp = new(Response)
-
-	resp.Request = req
-	resp.Request.Method = strings.ToUpper(resp.Request.Method)
-
-	// Parse the first line of the response.
-	line, err := tp.ReadLine()
-	if err != nil {
-		if err == os.EOF {
-			err = io.ErrUnexpectedEOF
-		}
-		return nil, err
-	}
-	f := strings.SplitN(line, " ", 3)
-	if len(f) < 2 {
-		return nil, &badStringError{"malformed HTTP response", line}
-	}
-	reasonPhrase := ""
-	if len(f) > 2 {
-		reasonPhrase = f[2]
-	}
-	resp.Status = f[1] + " " + reasonPhrase
-	resp.StatusCode, err = strconv.Atoi(f[1])
-	if err != nil {
-		return nil, &badStringError{"malformed HTTP status code", f[1]}
-	}
-
-	resp.Proto = f[0]
-	var ok bool
-	if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok {
-		return nil, &badStringError{"malformed HTTP version", resp.Proto}
-	}
-
-	// Parse the response headers.
-	mimeHeader, err := tp.ReadMIMEHeader()
-	if err != nil {
-		return nil, err
-	}
-	resp.Header = Header(mimeHeader)
-
-	fixPragmaCacheControl(resp.Header)
-
-	err = readTransfer(resp, r)
-	if err != nil {
-		return nil, err
-	}
-
-	return resp, nil
-}
-
-// RFC2616: Should treat
-//	Pragma: no-cache
-// like
-//	Cache-Control: no-cache
-func fixPragmaCacheControl(header Header) {
-	if hp, ok := header["Pragma"]; ok && len(hp) > 0 && hp[0] == "no-cache" {
-		if _, presentcc := header["Cache-Control"]; !presentcc {
-			header["Cache-Control"] = []string{"no-cache"}
-		}
-	}
-}
-
-// ProtoAtLeast returns whether the HTTP protocol used
-// in the response is at least major.minor.
-func (r *Response) ProtoAtLeast(major, minor int) bool {
-	return r.ProtoMajor > major ||
-		r.ProtoMajor == major && r.ProtoMinor >= minor
-}
-
-// Writes the response (header, body and trailer) in wire format. This method
-// consults the following fields of resp:
-//
-//  StatusCode
-//  ProtoMajor
-//  ProtoMinor
-//  RequestMethod
-//  TransferEncoding
-//  Trailer
-//  Body
-//  ContentLength
-//  Header, values for non-canonical keys will have unpredictable behavior
-//
-func (resp *Response) Write(w io.Writer) os.Error {
-
-	// RequestMethod should be upper-case
-	if resp.Request != nil {
-		resp.Request.Method = strings.ToUpper(resp.Request.Method)
-	}
-
-	// Status line
-	text := resp.Status
-	if text == "" {
-		var ok bool
-		text, ok = statusText[resp.StatusCode]
-		if !ok {
-			text = "status code " + strconv.Itoa(resp.StatusCode)
-		}
-	}
-	io.WriteString(w, "HTTP/"+strconv.Itoa(resp.ProtoMajor)+".")
-	io.WriteString(w, strconv.Itoa(resp.ProtoMinor)+" ")
-	io.WriteString(w, strconv.Itoa(resp.StatusCode)+" "+text+"\r\n")
-
-	// Process Body,ContentLength,Close,Trailer
-	tw, err := newTransferWriter(resp)
-	if err != nil {
-		return err
-	}
-	err = tw.WriteHeader(w)
-	if err != nil {
-		return err
-	}
-
-	// Rest of header
-	err = resp.Header.WriteSubset(w, respExcludeHeader)
-	if err != nil {
-		return err
-	}
-
-	// End-of-header
-	io.WriteString(w, "\r\n")
-
-	// Write body and trailer
-	err = tw.WriteBody(w)
-	if err != nil {
-		return err
-	}
-
-	// Success
-	return nil
-}
diff --git a/src/pkg/http/response_test.go b/src/pkg/http/response_test.go
deleted file mode 100644
index 1d4a234..0000000
--- a/src/pkg/http/response_test.go
+++ /dev/null
@@ -1,397 +0,0 @@
-// Copyright 2010 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 http
-
-import (
-	"bufio"
-	"bytes"
-	"compress/gzip"
-	"crypto/rand"
-	"fmt"
-	"os"
-	"io"
-	"io/ioutil"
-	"reflect"
-	"testing"
-)
-
-type respTest struct {
-	Raw  string
-	Resp Response
-	Body string
-}
-
-func dummyReq(method string) *Request {
-	return &Request{Method: method}
-}
-
-var respTests = []respTest{
-	// Unchunked response without Content-Length.
-	{
-		"HTTP/1.0 200 OK\r\n" +
-			"Connection: close\r\n" +
-			"\r\n" +
-			"Body here\n",
-
-		Response{
-			Status:     "200 OK",
-			StatusCode: 200,
-			Proto:      "HTTP/1.0",
-			ProtoMajor: 1,
-			ProtoMinor: 0,
-			Request:    dummyReq("GET"),
-			Header: Header{
-				"Connection": {"close"}, // TODO(rsc): Delete?
-			},
-			Close:         true,
-			ContentLength: -1,
-		},
-
-		"Body here\n",
-	},
-
-	// Unchunked HTTP/1.1 response without Content-Length or
-	// Connection headers.
-	{
-		"HTTP/1.1 200 OK\r\n" +
-			"\r\n" +
-			"Body here\n",
-
-		Response{
-			Status:        "200 OK",
-			StatusCode:    200,
-			Proto:         "HTTP/1.1",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			Request:       dummyReq("GET"),
-			Close:         true,
-			ContentLength: -1,
-		},
-
-		"Body here\n",
-	},
-
-	// Unchunked HTTP/1.1 204 response without Content-Length.
-	{
-		"HTTP/1.1 204 No Content\r\n" +
-			"\r\n" +
-			"Body should not be read!\n",
-
-		Response{
-			Status:        "204 No Content",
-			StatusCode:    204,
-			Proto:         "HTTP/1.1",
-			ProtoMajor:    1,
-			ProtoMinor:    1,
-			Request:       dummyReq("GET"),
-			Close:         false,
-			ContentLength: 0,
-		},
-
-		"",
-	},
-
-	// Unchunked response with Content-Length.
-	{
-		"HTTP/1.0 200 OK\r\n" +
-			"Content-Length: 10\r\n" +
-			"Connection: close\r\n" +
-			"\r\n" +
-			"Body here\n",
-
-		Response{
-			Status:     "200 OK",
-			StatusCode: 200,
-			Proto:      "HTTP/1.0",
-			ProtoMajor: 1,
-			ProtoMinor: 0,
-			Request:    dummyReq("GET"),
-			Header: Header{
-				"Connection":     {"close"}, // TODO(rsc): Delete?
-				"Content-Length": {"10"},    // TODO(rsc): Delete?
-			},
-			Close:         true,
-			ContentLength: 10,
-		},
-
-		"Body here\n",
-	},
-
-	// Chunked response without Content-Length.
-	{
-		"HTTP/1.0 200 OK\r\n" +
-			"Transfer-Encoding: chunked\r\n" +
-			"\r\n" +
-			"0a\r\n" +
-			"Body here\n\r\n" +
-			"09\r\n" +
-			"continued\r\n" +
-			"0\r\n" +
-			"\r\n",
-
-		Response{
-			Status:           "200 OK",
-			StatusCode:       200,
-			Proto:            "HTTP/1.0",
-			ProtoMajor:       1,
-			ProtoMinor:       0,
-			Request:          dummyReq("GET"),
-			Header:           Header{},
-			Close:            true,
-			ContentLength:    -1,
-			TransferEncoding: []string{"chunked"},
-		},
-
-		"Body here\ncontinued",
-	},
-
-	// Chunked response with Content-Length.
-	{
-		"HTTP/1.0 200 OK\r\n" +
-			"Transfer-Encoding: chunked\r\n" +
-			"Content-Length: 10\r\n" +
-			"\r\n" +
-			"0a\r\n" +
-			"Body here\n" +
-			"0\r\n" +
-			"\r\n",
-
-		Response{
-			Status:           "200 OK",
-			StatusCode:       200,
-			Proto:            "HTTP/1.0",
-			ProtoMajor:       1,
-			ProtoMinor:       0,
-			Request:          dummyReq("GET"),
-			Header:           Header{},
-			Close:            true,
-			ContentLength:    -1, // TODO(rsc): Fix?
-			TransferEncoding: []string{"chunked"},
-		},
-
-		"Body here\n",
-	},
-
-	// Chunked response in response to a HEAD request (the "chunked" should
-	// be ignored, as HEAD responses never have bodies)
-	{
-		"HTTP/1.0 200 OK\r\n" +
-			"Transfer-Encoding: chunked\r\n" +
-			"\r\n",
-
-		Response{
-			Status:        "200 OK",
-			StatusCode:    200,
-			Proto:         "HTTP/1.0",
-			ProtoMajor:    1,
-			ProtoMinor:    0,
-			Request:       dummyReq("HEAD"),
-			Header:        Header{},
-			Close:         true,
-			ContentLength: 0,
-		},
-
-		"",
-	},
-
-	// explicit Content-Length of 0.
-	{
-		"HTTP/1.1 200 OK\r\n" +
-			"Content-Length: 0\r\n" +
-			"\r\n",
-
-		Response{
-			Status:     "200 OK",
-			StatusCode: 200,
-			Proto:      "HTTP/1.1",
-			ProtoMajor: 1,
-			ProtoMinor: 1,
-			Request:    dummyReq("GET"),
-			Header: Header{
-				"Content-Length": {"0"},
-			},
-			Close:         false,
-			ContentLength: 0,
-		},
-
-		"",
-	},
-
-	// Status line without a Reason-Phrase, but trailing space.
-	// (permitted by RFC 2616)
-	{
-		"HTTP/1.0 303 \r\n\r\n",
-		Response{
-			Status:        "303 ",
-			StatusCode:    303,
-			Proto:         "HTTP/1.0",
-			ProtoMajor:    1,
-			ProtoMinor:    0,
-			Request:       dummyReq("GET"),
-			Header:        Header{},
-			Close:         true,
-			ContentLength: -1,
-		},
-
-		"",
-	},
-
-	// Status line without a Reason-Phrase, and no trailing space.
-	// (not permitted by RFC 2616, but we'll accept it anyway)
-	{
-		"HTTP/1.0 303\r\n\r\n",
-		Response{
-			Status:        "303 ",
-			StatusCode:    303,
-			Proto:         "HTTP/1.0",
-			ProtoMajor:    1,
-			ProtoMinor:    0,
-			Request:       dummyReq("GET"),
-			Header:        Header{},
-			Close:         true,
-			ContentLength: -1,
-		},
-
-		"",
-	},
-}
-
-func TestReadResponse(t *testing.T) {
-	for i := range respTests {
-		tt := &respTests[i]
-		var braw bytes.Buffer
-		braw.WriteString(tt.Raw)
-		resp, err := ReadResponse(bufio.NewReader(&braw), tt.Resp.Request)
-		if err != nil {
-			t.Errorf("#%d: %s", i, err)
-			continue
-		}
-		rbody := resp.Body
-		resp.Body = nil
-		diff(t, fmt.Sprintf("#%d Response", i), resp, &tt.Resp)
-		var bout bytes.Buffer
-		if rbody != nil {
-			io.Copy(&bout, rbody)
-			rbody.Close()
-		}
-		body := bout.String()
-		if body != tt.Body {
-			t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
-		}
-	}
-}
-
-var readResponseCloseInMiddleTests = []struct {
-	chunked, compressed bool
-}{
-	{false, false},
-	{true, false},
-	{true, true},
-}
-
-// TestReadResponseCloseInMiddle tests that closing a body after
-// reading only part of its contents advances the read to the end of
-// the request, right up until the next request.
-func TestReadResponseCloseInMiddle(t *testing.T) {
-	for _, test := range readResponseCloseInMiddleTests {
-		fatalf := func(format string, args ...interface{}) {
-			args = append([]interface{}{test.chunked, test.compressed}, args...)
-			t.Fatalf("on test chunked=%v, compressed=%v: "+format, args...)
-		}
-		checkErr := func(err os.Error, msg string) {
-			if err == nil {
-				return
-			}
-			fatalf(msg+": %v", err)
-		}
-		var buf bytes.Buffer
-		buf.WriteString("HTTP/1.1 200 OK\r\n")
-		if test.chunked {
-			buf.WriteString("Transfer-Encoding: chunked\r\n")
-		} else {
-			buf.WriteString("Content-Length: 1000000\r\n")
-		}
-		var wr io.Writer = &buf
-		if test.chunked {
-			wr = &chunkedWriter{wr}
-		}
-		if test.compressed {
-			buf.WriteString("Content-Encoding: gzip\r\n")
-			var err os.Error
-			wr, err = gzip.NewWriter(wr)
-			checkErr(err, "gzip.NewWriter")
-		}
-		buf.WriteString("\r\n")
-
-		chunk := bytes.Repeat([]byte{'x'}, 1000)
-		for i := 0; i < 1000; i++ {
-			if test.compressed {
-				// Otherwise this compresses too well.
-				_, err := io.ReadFull(rand.Reader, chunk)
-				checkErr(err, "rand.Reader ReadFull")
-			}
-			wr.Write(chunk)
-		}
-		if test.compressed {
-			err := wr.(*gzip.Compressor).Close()
-			checkErr(err, "compressor close")
-		}
-		if test.chunked {
-			buf.WriteString("0\r\n\r\n")
-		}
-		buf.WriteString("Next Request Here")
-
-		bufr := bufio.NewReader(&buf)
-		resp, err := ReadResponse(bufr, dummyReq("GET"))
-		checkErr(err, "ReadResponse")
-		expectedLength := int64(-1)
-		if !test.chunked {
-			expectedLength = 1000000
-		}
-		if resp.ContentLength != expectedLength {
-			fatalf("expected response length %d, got %d", expectedLength, resp.ContentLength)
-		}
-		if resp.Body == nil {
-			fatalf("nil body")
-		}
-		if test.compressed {
-			gzReader, err := gzip.NewReader(resp.Body)
-			checkErr(err, "gzip.NewReader")
-			resp.Body = &readFirstCloseBoth{gzReader, resp.Body}
-		}
-
-		rbuf := make([]byte, 2500)
-		n, err := io.ReadFull(resp.Body, rbuf)
-		checkErr(err, "2500 byte ReadFull")
-		if n != 2500 {
-			fatalf("ReadFull only read %d bytes", n)
-		}
-		if test.compressed == false && !bytes.Equal(bytes.Repeat([]byte{'x'}, 2500), rbuf) {
-			fatalf("ReadFull didn't read 2500 'x'; got %q", string(rbuf))
-		}
-		resp.Body.Close()
-
-		rest, err := ioutil.ReadAll(bufr)
-		checkErr(err, "ReadAll on remainder")
-		if e, g := "Next Request Here", string(rest); e != g {
-			fatalf("remainder = %q, expected %q", g, e)
-		}
-	}
-}
-
-func diff(t *testing.T, prefix string, have, want interface{}) {
-	hv := reflect.ValueOf(have).Elem()
-	wv := reflect.ValueOf(want).Elem()
-	if hv.Type() != wv.Type() {
-		t.Errorf("%s: type mismatch %v want %v", prefix, hv.Type(), wv.Type())
-	}
-	for i := 0; i < hv.NumField(); i++ {
-		hf := hv.Field(i).Interface()
-		wf := wv.Field(i).Interface()
-		if !reflect.DeepEqual(hf, wf) {
-			t.Errorf("%s: %s = %v want %v", prefix, hv.Type().Field(i).Name, hf, wf)
-		}
-	}
-}
diff --git a/src/pkg/http/reverseproxy.go b/src/pkg/http/reverseproxy.go
deleted file mode 100644
index 3f8bfdc..0000000
--- a/src/pkg/http/reverseproxy.go
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2011 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.
-
-// HTTP reverse proxy handler
-
-package http
-
-import (
-	"io"
-	"log"
-	"net"
-	"os"
-	"strings"
-	"sync"
-	"time"
-	"url"
-)
-
-// ReverseProxy is an HTTP Handler that takes an incoming request and
-// sends it to another server, proxying the response back to the
-// client.
-type ReverseProxy struct {
-	// Director must be a function which modifies
-	// the request into a new request to be sent
-	// using Transport. Its response is then copied
-	// back to the original client unmodified.
-	Director func(*Request)
-
-	// The Transport used to perform proxy requests.
-	// If nil, DefaultTransport is used.
-	Transport RoundTripper
-
-	// FlushInterval specifies the flush interval, in
-	// nanoseconds, to flush to the client while
-	// coping the response body.
-	// If zero, no periodic flushing is done.
-	FlushInterval int64
-}
-
-func singleJoiningSlash(a, b string) string {
-	aslash := strings.HasSuffix(a, "/")
-	bslash := strings.HasPrefix(b, "/")
-	switch {
-	case aslash && bslash:
-		return a + b[1:]
-	case !aslash && !bslash:
-		return a + "/" + b
-	}
-	return a + b
-}
-
-// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
-// URLs to the scheme, host, and base path provided in target. If the
-// target's path is "/base" and the incoming request was for "/dir",
-// the target request will be for /base/dir.
-func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
-	director := func(req *Request) {
-		req.URL.Scheme = target.Scheme
-		req.URL.Host = target.Host
-		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
-		if q := req.URL.RawQuery; q != "" {
-			req.URL.RawPath = req.URL.Path + "?" + q
-		} else {
-			req.URL.RawPath = req.URL.Path
-		}
-		req.URL.RawQuery = target.RawQuery
-	}
-	return &ReverseProxy{Director: director}
-}
-
-func (p *ReverseProxy) ServeHTTP(rw ResponseWriter, req *Request) {
-	transport := p.Transport
-	if transport == nil {
-		transport = DefaultTransport
-	}
-
-	outreq := new(Request)
-	*outreq = *req // includes shallow copies of maps, but okay
-
-	p.Director(outreq)
-	outreq.Proto = "HTTP/1.1"
-	outreq.ProtoMajor = 1
-	outreq.ProtoMinor = 1
-	outreq.Close = false
-
-	if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
-		outreq.Header.Set("X-Forwarded-For", clientIp)
-	}
-
-	res, err := transport.RoundTrip(outreq)
-	if err != nil {
-		log.Printf("http: proxy error: %v", err)
-		rw.WriteHeader(StatusInternalServerError)
-		return
-	}
-
-	hdr := rw.Header()
-	for k, vv := range res.Header {
-		for _, v := range vv {
-			hdr.Add(k, v)
-		}
-	}
-
-	rw.WriteHeader(res.StatusCode)
-
-	if res.Body != nil {
-		var dst io.Writer = rw
-		if p.FlushInterval != 0 {
-			if wf, ok := rw.(writeFlusher); ok {
-				dst = &maxLatencyWriter{dst: wf, latency: p.FlushInterval}
-			}
-		}
-		io.Copy(dst, res.Body)
-	}
-}
-
-type writeFlusher interface {
-	io.Writer
-	Flusher
-}
-
-type maxLatencyWriter struct {
-	dst     writeFlusher
-	latency int64 // nanos
-
-	lk   sync.Mutex // protects init of done, as well Write + Flush
-	done chan bool
-}
-
-func (m *maxLatencyWriter) Write(p []byte) (n int, err os.Error) {
-	m.lk.Lock()
-	defer m.lk.Unlock()
-	if m.done == nil {
-		m.done = make(chan bool)
-		go m.flushLoop()
-	}
-	n, err = m.dst.Write(p)
-	if err != nil {
-		m.done <- true
-	}
-	return
-}
-
-func (m *maxLatencyWriter) flushLoop() {
-	t := time.NewTicker(m.latency)
-	defer t.Stop()
-	for {
-		select {
-		case <-t.C:
-			m.lk.Lock()
-			m.dst.Flush()
-			m.lk.Unlock()
-		case <-m.done:
-			return
-		}
-	}
-	panic("unreached")
-}
diff --git a/src/pkg/http/reverseproxy_test.go b/src/pkg/http/reverseproxy_test.go
deleted file mode 100644
index 8078c8d..0000000
--- a/src/pkg/http/reverseproxy_test.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2011 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.
-
-// Reverse proxy tests.
-
-package http_test
-
-import (
-	. "http"
-	"http/httptest"
-	"io/ioutil"
-	"testing"
-	"url"
-)
-
-func TestReverseProxy(t *testing.T) {
-	const backendResponse = "I am the backend"
-	const backendStatus = 404
-	backend := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		if len(r.TransferEncoding) > 0 {
-			t.Errorf("backend got unexpected TransferEncoding: %v", r.TransferEncoding)
-		}
-		if r.Header.Get("X-Forwarded-For") == "" {
-			t.Errorf("didn't get X-Forwarded-For header")
-		}
-		if g, e := r.Host, "some-name"; g != e {
-			t.Errorf("backend got Host header %q, want %q", g, e)
-		}
-		w.Header().Set("X-Foo", "bar")
-		SetCookie(w, &Cookie{Name: "flavor", Value: "chocolateChip"})
-		w.WriteHeader(backendStatus)
-		w.Write([]byte(backendResponse))
-	}))
-	defer backend.Close()
-	backendURL, err := url.Parse(backend.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	proxyHandler := NewSingleHostReverseProxy(backendURL)
-	frontend := httptest.NewServer(proxyHandler)
-	defer frontend.Close()
-
-	getReq, _ := NewRequest("GET", frontend.URL, nil)
-	getReq.Host = "some-name"
-	res, err := DefaultClient.Do(getReq)
-	if err != nil {
-		t.Fatalf("Get: %v", err)
-	}
-	if g, e := res.StatusCode, backendStatus; g != e {
-		t.Errorf("got res.StatusCode %d; expected %d", g, e)
-	}
-	if g, e := res.Header.Get("X-Foo"), "bar"; g != e {
-		t.Errorf("got X-Foo %q; expected %q", g, e)
-	}
-	if g, e := len(res.Header["Set-Cookie"]), 1; g != e {
-		t.Fatalf("got %d SetCookies, want %d", g, e)
-	}
-	if cookie := res.Cookies()[0]; cookie.Name != "flavor" {
-		t.Errorf("unexpected cookie %q", cookie.Name)
-	}
-	bodyBytes, _ := ioutil.ReadAll(res.Body)
-	if g, e := string(bodyBytes), backendResponse; g != e {
-		t.Errorf("got body %q; expected %q", g, e)
-	}
-}
diff --git a/src/pkg/http/serve_test.go b/src/pkg/http/serve_test.go
deleted file mode 100644
index 1bb748c..0000000
--- a/src/pkg/http/serve_test.go
+++ /dev/null
@@ -1,1050 +0,0 @@
-// Copyright 2010 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.
-
-// End-to-end serving tests
-
-package http_test
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	. "http"
-	"http/httptest"
-	"io"
-	"io/ioutil"
-	"log"
-	"os"
-	"net"
-	"reflect"
-	"strings"
-	"syscall"
-	"testing"
-	"time"
-	"url"
-)
-
-type dummyAddr string
-type oneConnListener struct {
-	conn net.Conn
-}
-
-func (l *oneConnListener) Accept() (c net.Conn, err os.Error) {
-	c = l.conn
-	if c == nil {
-		err = os.EOF
-		return
-	}
-	err = nil
-	l.conn = nil
-	return
-}
-
-func (l *oneConnListener) Close() os.Error {
-	return nil
-}
-
-func (l *oneConnListener) Addr() net.Addr {
-	return dummyAddr("test-address")
-}
-
-func (a dummyAddr) Network() string {
-	return string(a)
-}
-
-func (a dummyAddr) String() string {
-	return string(a)
-}
-
-type testConn struct {
-	readBuf  bytes.Buffer
-	writeBuf bytes.Buffer
-}
-
-func (c *testConn) Read(b []byte) (int, os.Error) {
-	return c.readBuf.Read(b)
-}
-
-func (c *testConn) Write(b []byte) (int, os.Error) {
-	return c.writeBuf.Write(b)
-}
-
-func (c *testConn) Close() os.Error {
-	return nil
-}
-
-func (c *testConn) LocalAddr() net.Addr {
-	return dummyAddr("local-addr")
-}
-
-func (c *testConn) RemoteAddr() net.Addr {
-	return dummyAddr("remote-addr")
-}
-
-func (c *testConn) SetTimeout(nsec int64) os.Error {
-	return nil
-}
-
-func (c *testConn) SetReadTimeout(nsec int64) os.Error {
-	return nil
-}
-
-func (c *testConn) SetWriteTimeout(nsec int64) os.Error {
-	return nil
-}
-
-func TestConsumingBodyOnNextConn(t *testing.T) {
-	conn := new(testConn)
-	for i := 0; i < 2; i++ {
-		conn.readBuf.Write([]byte(
-			"POST / HTTP/1.1\r\n" +
-				"Host: test\r\n" +
-				"Content-Length: 11\r\n" +
-				"\r\n" +
-				"foo=1&bar=1"))
-	}
-
-	reqNum := 0
-	ch := make(chan *Request)
-	servech := make(chan os.Error)
-	listener := &oneConnListener{conn}
-	handler := func(res ResponseWriter, req *Request) {
-		reqNum++
-		ch <- req
-	}
-
-	go func() {
-		servech <- Serve(listener, HandlerFunc(handler))
-	}()
-
-	var req *Request
-	req = <-ch
-	if req == nil {
-		t.Fatal("Got nil first request.")
-	}
-	if req.Method != "POST" {
-		t.Errorf("For request #1's method, got %q; expected %q",
-			req.Method, "POST")
-	}
-
-	req = <-ch
-	if req == nil {
-		t.Fatal("Got nil first request.")
-	}
-	if req.Method != "POST" {
-		t.Errorf("For request #2's method, got %q; expected %q",
-			req.Method, "POST")
-	}
-
-	if serveerr := <-servech; serveerr != os.EOF {
-		t.Errorf("Serve returned %q; expected EOF", serveerr)
-	}
-}
-
-type stringHandler string
-
-func (s stringHandler) ServeHTTP(w ResponseWriter, r *Request) {
-	w.Header().Set("Result", string(s))
-}
-
-var handlers = []struct {
-	pattern string
-	msg     string
-}{
-	{"/", "Default"},
-	{"/someDir/", "someDir"},
-	{"someHost.com/someDir/", "someHost.com/someDir"},
-}
-
-var vtests = []struct {
-	url      string
-	expected string
-}{
-	{"http://localhost/someDir/apage", "someDir"},
-	{"http://localhost/otherDir/apage", "Default"},
-	{"http://someHost.com/someDir/apage", "someHost.com/someDir"},
-	{"http://otherHost.com/someDir/apage", "someDir"},
-	{"http://otherHost.com/aDir/apage", "Default"},
-}
-
-func TestHostHandlers(t *testing.T) {
-	for _, h := range handlers {
-		Handle(h.pattern, stringHandler(h.msg))
-	}
-	ts := httptest.NewServer(nil)
-	defer ts.Close()
-
-	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer conn.Close()
-	cc := NewClientConn(conn, nil)
-	for _, vt := range vtests {
-		var r *Response
-		var req Request
-		if req.URL, err = url.Parse(vt.url); err != nil {
-			t.Errorf("cannot parse url: %v", err)
-			continue
-		}
-		if err := cc.Write(&req); err != nil {
-			t.Errorf("writing request: %v", err)
-			continue
-		}
-		r, err := cc.Read(&req)
-		if err != nil {
-			t.Errorf("reading response: %v", err)
-			continue
-		}
-		s := r.Header.Get("Result")
-		if s != vt.expected {
-			t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
-		}
-	}
-}
-
-// Tests for http://code.google.com/p/go/issues/detail?id=900
-func TestMuxRedirectLeadingSlashes(t *testing.T) {
-	paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
-	for _, path := range paths {
-		req, err := ReadRequest(bufio.NewReader(bytes.NewBufferString("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n")))
-		if err != nil {
-			t.Errorf("%s", err)
-		}
-		mux := NewServeMux()
-		resp := httptest.NewRecorder()
-
-		mux.ServeHTTP(resp, req)
-
-		if loc, expected := resp.Header().Get("Location"), "/foo.txt"; loc != expected {
-			t.Errorf("Expected Location header set to %q; got %q", expected, loc)
-			return
-		}
-
-		if code, expected := resp.Code, StatusMovedPermanently; code != expected {
-			t.Errorf("Expected response code of StatusMovedPermanently; got %d", code)
-			return
-		}
-	}
-}
-
-func TestServerTimeouts(t *testing.T) {
-	// TODO(bradfitz): convert this to use httptest.Server
-	l, err := net.Listen("tcp", "127.0.0.1:0")
-	if err != nil {
-		t.Fatalf("listen error: %v", err)
-	}
-	addr, _ := l.Addr().(*net.TCPAddr)
-
-	reqNum := 0
-	handler := HandlerFunc(func(res ResponseWriter, req *Request) {
-		reqNum++
-		fmt.Fprintf(res, "req=%d", reqNum)
-	})
-
-	const second = 1000000000 /* nanos */
-	server := &Server{Handler: handler, ReadTimeout: 0.25 * second, WriteTimeout: 0.25 * second}
-	go server.Serve(l)
-
-	url := fmt.Sprintf("http://%s/", addr)
-
-	// Hit the HTTP server successfully.
-	tr := &Transport{DisableKeepAlives: true} // they interfere with this test
-	c := &Client{Transport: tr}
-	r, err := c.Get(url)
-	if err != nil {
-		t.Fatalf("http Get #1: %v", err)
-	}
-	got, _ := ioutil.ReadAll(r.Body)
-	expected := "req=1"
-	if string(got) != expected {
-		t.Errorf("Unexpected response for request #1; got %q; expected %q",
-			string(got), expected)
-	}
-
-	// Slow client that should timeout.
-	t1 := time.Nanoseconds()
-	conn, err := net.Dial("tcp", addr.String())
-	if err != nil {
-		t.Fatalf("Dial: %v", err)
-	}
-	buf := make([]byte, 1)
-	n, err := conn.Read(buf)
-	latency := time.Nanoseconds() - t1
-	if n != 0 || err != os.EOF {
-		t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, os.EOF)
-	}
-	if latency < second*0.20 /* fudge from 0.25 above */ {
-		t.Errorf("got EOF after %d ns, want >= %d", latency, second*0.20)
-	}
-
-	// Hit the HTTP server successfully again, verifying that the
-	// previous slow connection didn't run our handler.  (that we
-	// get "req=2", not "req=3")
-	r, err = Get(url)
-	if err != nil {
-		t.Fatalf("http Get #2: %v", err)
-	}
-	got, _ = ioutil.ReadAll(r.Body)
-	expected = "req=2"
-	if string(got) != expected {
-		t.Errorf("Get #2 got %q, want %q", string(got), expected)
-	}
-
-	l.Close()
-}
-
-// TestIdentityResponse verifies that a handler can unset 
-func TestIdentityResponse(t *testing.T) {
-	handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
-		rw.Header().Set("Content-Length", "3")
-		rw.Header().Set("Transfer-Encoding", req.FormValue("te"))
-		switch {
-		case req.FormValue("overwrite") == "1":
-			_, err := rw.Write([]byte("foo TOO LONG"))
-			if err != ErrContentLength {
-				t.Errorf("expected ErrContentLength; got %v", err)
-			}
-		case req.FormValue("underwrite") == "1":
-			rw.Header().Set("Content-Length", "500")
-			rw.Write([]byte("too short"))
-		default:
-			rw.Write([]byte("foo"))
-		}
-	})
-
-	ts := httptest.NewServer(handler)
-	defer ts.Close()
-
-	// Note: this relies on the assumption (which is true) that
-	// Get sends HTTP/1.1 or greater requests.  Otherwise the
-	// server wouldn't have the choice to send back chunked
-	// responses.
-	for _, te := range []string{"", "identity"} {
-		url := ts.URL + "/?te=" + te
-		res, err := Get(url)
-		if err != nil {
-			t.Fatalf("error with Get of %s: %v", url, err)
-		}
-		if cl, expected := res.ContentLength, int64(3); cl != expected {
-			t.Errorf("for %s expected res.ContentLength of %d; got %d", url, expected, cl)
-		}
-		if cl, expected := res.Header.Get("Content-Length"), "3"; cl != expected {
-			t.Errorf("for %s expected Content-Length header of %q; got %q", url, expected, cl)
-		}
-		if tl, expected := len(res.TransferEncoding), 0; tl != expected {
-			t.Errorf("for %s expected len(res.TransferEncoding) of %d; got %d (%v)",
-				url, expected, tl, res.TransferEncoding)
-		}
-		res.Body.Close()
-	}
-
-	// Verify that ErrContentLength is returned
-	url := ts.URL + "/?overwrite=1"
-	_, err := Get(url)
-	if err != nil {
-		t.Fatalf("error with Get of %s: %v", url, err)
-	}
-	// Verify that the connection is closed when the declared Content-Length
-	// is larger than what the handler wrote.
-	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
-	if err != nil {
-		t.Fatalf("error dialing: %v", err)
-	}
-	_, err = conn.Write([]byte("GET /?underwrite=1 HTTP/1.1\r\nHost: foo\r\n\r\n"))
-	if err != nil {
-		t.Fatalf("error writing: %v", err)
-	}
-	// The next ReadAll will hang for a failing test, so use a Timer instead
-	// to fail more traditionally
-	timer := time.AfterFunc(2e9, func() {
-		t.Fatalf("Timeout expired in ReadAll.")
-	})
-	defer timer.Stop()
-	got, _ := ioutil.ReadAll(conn)
-	expectedSuffix := "\r\n\r\ntoo short"
-	if !strings.HasSuffix(string(got), expectedSuffix) {
-		t.Fatalf("Expected output to end with %q; got response body %q",
-			expectedSuffix, string(got))
-	}
-}
-
-func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
-	s := httptest.NewServer(h)
-	defer s.Close()
-
-	conn, err := net.Dial("tcp", s.Listener.Addr().String())
-	if err != nil {
-		t.Fatal("dial error:", err)
-	}
-	defer conn.Close()
-
-	_, err = fmt.Fprint(conn, req)
-	if err != nil {
-		t.Fatal("print error:", err)
-	}
-
-	r := bufio.NewReader(conn)
-	_, err = ReadResponse(r, &Request{Method: "GET"})
-	if err != nil {
-		t.Fatal("ReadResponse error:", err)
-	}
-
-	success := make(chan bool)
-	go func() {
-		select {
-		case <-time.After(5e9):
-			t.Fatal("body not closed after 5s")
-		case <-success:
-		}
-	}()
-
-	_, err = ioutil.ReadAll(r)
-	if err != nil {
-		t.Fatal("read error:", err)
-	}
-
-	success <- true
-}
-
-// TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
-func TestServeHTTP10Close(t *testing.T) {
-	testTcpConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
-		ServeFile(w, r, "testdata/file")
-	}))
-}
-
-// TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close,
-// even for HTTP/1.1 requests.
-func TestHandlersCanSetConnectionClose11(t *testing.T) {
-	testTcpConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header().Set("Connection", "close")
-	}))
-}
-
-func TestHandlersCanSetConnectionClose10(t *testing.T) {
-	testTcpConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header().Set("Connection", "close")
-	}))
-}
-
-func TestSetsRemoteAddr(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		fmt.Fprintf(w, "%s", r.RemoteAddr)
-	}))
-	defer ts.Close()
-
-	res, err := Get(ts.URL)
-	if err != nil {
-		t.Fatalf("Get error: %v", err)
-	}
-	body, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Fatalf("ReadAll error: %v", err)
-	}
-	ip := string(body)
-	if !strings.HasPrefix(ip, "127.0.0.1:") && !strings.HasPrefix(ip, "[::1]:") {
-		t.Fatalf("Expected local addr; got %q", ip)
-	}
-}
-
-func TestChunkedResponseHeaders(t *testing.T) {
-	log.SetOutput(ioutil.Discard) // is noisy otherwise
-	defer log.SetOutput(os.Stderr)
-
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
-		fmt.Fprintf(w, "I am a chunked response.")
-	}))
-	defer ts.Close()
-
-	res, err := Get(ts.URL)
-	if err != nil {
-		t.Fatalf("Get error: %v", err)
-	}
-	if g, e := res.ContentLength, int64(-1); g != e {
-		t.Errorf("expected ContentLength of %d; got %d", e, g)
-	}
-	if g, e := res.TransferEncoding, []string{"chunked"}; !reflect.DeepEqual(g, e) {
-		t.Errorf("expected TransferEncoding of %v; got %v", e, g)
-	}
-	if _, haveCL := res.Header["Content-Length"]; haveCL {
-		t.Errorf("Unexpected Content-Length")
-	}
-}
-
-// Test304Responses verifies that 304s don't declare that they're
-// chunking in their response headers and aren't allowed to produce
-// output.
-func Test304Responses(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.WriteHeader(StatusNotModified)
-		_, err := w.Write([]byte("illegal body"))
-		if err != ErrBodyNotAllowed {
-			t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
-		}
-	}))
-	defer ts.Close()
-	res, err := Get(ts.URL)
-	if err != nil {
-		t.Error(err)
-	}
-	if len(res.TransferEncoding) > 0 {
-		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
-	}
-	body, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Error(err)
-	}
-	if len(body) > 0 {
-		t.Errorf("got unexpected body %q", string(body))
-	}
-}
-
-// TestHeadResponses verifies that responses to HEAD requests don't
-// declare that they're chunking in their response headers and aren't
-// allowed to produce output.
-func TestHeadResponses(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		_, err := w.Write([]byte("Ignored body"))
-		if err != ErrBodyNotAllowed {
-			t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
-		}
-
-		// Also exercise the ReaderFrom path
-		_, err = io.Copy(w, strings.NewReader("Ignored body"))
-		if err != ErrBodyNotAllowed {
-			t.Errorf("on Copy, expected ErrBodyNotAllowed, got %v", err)
-		}
-	}))
-	defer ts.Close()
-	res, err := Head(ts.URL)
-	if err != nil {
-		t.Error(err)
-	}
-	if len(res.TransferEncoding) > 0 {
-		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
-	}
-	body, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Error(err)
-	}
-	if len(body) > 0 {
-		t.Errorf("got unexpected body %q", string(body))
-	}
-}
-
-func TestTLSHandshakeTimeout(t *testing.T) {
-	if true {
-		t.Logf("Skipping broken test; issue 2281")
-		return
-	}
-	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
-	ts.Config.ReadTimeout = 250e6
-	ts.StartTLS()
-	defer ts.Close()
-	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
-	if err != nil {
-		t.Fatalf("Dial: %v", err)
-	}
-	defer conn.Close()
-	timer := time.AfterFunc(10e9, func() { t.Fatalf("Timeout") })
-	defer timer.Stop()
-
-	var buf [1]byte
-	n, err := conn.Read(buf[:])
-	if err == nil || n != 0 {
-		t.Errorf("Read = %d, %v; want an error and no bytes", n, err)
-	}
-}
-
-func TestTLSServer(t *testing.T) {
-	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		if r.TLS != nil {
-			w.Header().Set("X-TLS-Set", "true")
-			if r.TLS.HandshakeComplete {
-				w.Header().Set("X-TLS-HandshakeComplete", "true")
-			}
-		}
-	}))
-	defer ts.Close()
-
-	// Connect an idle TCP connection to this server before we run
-	// our real tests.  This idle connection used to block forever
-	// in the TLS handshake, preventing future connections from
-	// being accepted. It may prevent future accidental blocking
-	// in newConn.
-	idleConn, err := net.Dial("tcp", ts.Listener.Addr().String())
-	if err != nil {
-		t.Fatalf("Dial: %v", err)
-	}
-	defer idleConn.Close()
-	time.AfterFunc(10e9, func() { t.Fatalf("Timeout") })
-
-	if !strings.HasPrefix(ts.URL, "https://") {
-		t.Fatalf("expected test TLS server to start with https://, got %q", ts.URL)
-	}
-	res, err := Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if res == nil {
-		t.Fatalf("got nil Response")
-	}
-	defer res.Body.Close()
-	if res.Header.Get("X-TLS-Set") != "true" {
-		t.Errorf("expected X-TLS-Set response header")
-	}
-	if res.Header.Get("X-TLS-HandshakeComplete") != "true" {
-		t.Errorf("expected X-TLS-HandshakeComplete header")
-	}
-}
-
-type serverExpectTest struct {
-	contentLength    int    // of request body
-	expectation      string // e.g. "100-continue"
-	readBody         bool   // whether handler should read the body (if false, sends StatusUnauthorized)
-	expectedResponse string // expected substring in first line of http response
-}
-
-var serverExpectTests = []serverExpectTest{
-	// Normal 100-continues, case-insensitive.
-	{100, "100-continue", true, "100 Continue"},
-	{100, "100-cOntInUE", true, "100 Continue"},
-
-	// No 100-continue.
-	{100, "", true, "200 OK"},
-
-	// 100-continue but requesting client to deny us,
-	// so it never reads the body.
-	{100, "100-continue", false, "401 Unauthorized"},
-	// Likewise without 100-continue:
-	{100, "", false, "401 Unauthorized"},
-
-	// Non-standard expectations are failures
-	{0, "a-pony", false, "417 Expectation Failed"},
-
-	// Expect-100 requested but no body
-	{0, "100-continue", true, "400 Bad Request"},
-}
-
-// Tests that the server responds to the "Expect" request header
-// correctly.
-func TestServerExpect(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		// Note using r.FormValue("readbody") because for POST
-		// requests that would read from r.Body, which we only
-		// conditionally want to do.
-		if strings.Contains(r.URL.RawPath, "readbody=true") {
-			ioutil.ReadAll(r.Body)
-			w.Write([]byte("Hi"))
-		} else {
-			w.WriteHeader(StatusUnauthorized)
-		}
-	}))
-	defer ts.Close()
-
-	runTest := func(test serverExpectTest) {
-		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
-		if err != nil {
-			t.Fatalf("Dial: %v", err)
-		}
-		defer conn.Close()
-		sendf := func(format string, args ...interface{}) {
-			_, err := fmt.Fprintf(conn, format, args...)
-			if err != nil {
-				t.Fatalf("On test %#v, error writing %q: %v", test, format, err)
-			}
-		}
-		go func() {
-			sendf("POST /?readbody=%v HTTP/1.1\r\n"+
-				"Connection: close\r\n"+
-				"Content-Length: %d\r\n"+
-				"Expect: %s\r\nHost: foo\r\n\r\n",
-				test.readBody, test.contentLength, test.expectation)
-			if test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue" {
-				body := strings.Repeat("A", test.contentLength)
-				sendf(body)
-			}
-		}()
-		bufr := bufio.NewReader(conn)
-		line, err := bufr.ReadString('\n')
-		if err != nil {
-			t.Fatalf("ReadString: %v", err)
-		}
-		if !strings.Contains(line, test.expectedResponse) {
-			t.Errorf("for test %#v got first line=%q", test, line)
-		}
-	}
-
-	for _, test := range serverExpectTests {
-		runTest(test)
-	}
-}
-
-func TestServerConsumesRequestBody(t *testing.T) {
-	conn := new(testConn)
-	body := strings.Repeat("x", 1<<20)
-	conn.readBuf.Write([]byte(fmt.Sprintf(
-		"POST / HTTP/1.1\r\n"+
-			"Host: test\r\n"+
-			"Content-Length: %d\r\n"+
-			"\r\n", len(body))))
-	conn.readBuf.Write([]byte(body))
-
-	done := make(chan bool)
-
-	ls := &oneConnListener{conn}
-	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
-		if conn.readBuf.Len() < len(body)/2 {
-			t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
-		}
-		rw.WriteHeader(200)
-		if g, e := conn.readBuf.Len(), 0; g != e {
-			t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
-		}
-		done <- true
-	}))
-	<-done
-}
-
-func TestTimeoutHandler(t *testing.T) {
-	sendHi := make(chan bool, 1)
-	writeErrors := make(chan os.Error, 1)
-	sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
-		<-sendHi
-		_, werr := w.Write([]byte("hi"))
-		writeErrors <- werr
-	})
-	timeout := make(chan int64, 1) // write to this to force timeouts
-	ts := httptest.NewServer(NewTestTimeoutHandler(sayHi, timeout))
-	defer ts.Close()
-
-	// Succeed without timing out:
-	sendHi <- true
-	res, err := Get(ts.URL)
-	if err != nil {
-		t.Error(err)
-	}
-	if g, e := res.StatusCode, StatusOK; g != e {
-		t.Errorf("got res.StatusCode %d; expected %d", g, e)
-	}
-	body, _ := ioutil.ReadAll(res.Body)
-	if g, e := string(body), "hi"; g != e {
-		t.Errorf("got body %q; expected %q", g, e)
-	}
-	if g := <-writeErrors; g != nil {
-		t.Errorf("got unexpected Write error on first request: %v", g)
-	}
-
-	// Times out:
-	timeout <- 1
-	res, err = Get(ts.URL)
-	if err != nil {
-		t.Error(err)
-	}
-	if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
-		t.Errorf("got res.StatusCode %d; expected %d", g, e)
-	}
-	body, _ = ioutil.ReadAll(res.Body)
-	if !strings.Contains(string(body), "<title>Timeout</title>") {
-		t.Errorf("expected timeout body; got %q", string(body))
-	}
-
-	// Now make the previously-timed out handler speak again,
-	// which verifies the panic is handled:
-	sendHi <- true
-	if g, e := <-writeErrors, ErrHandlerTimeout; g != e {
-		t.Errorf("expected Write error of %v; got %v", e, g)
-	}
-}
-
-// Verifies we don't path.Clean() on the wrong parts in redirects.
-func TestRedirectMunging(t *testing.T) {
-	req, _ := NewRequest("GET", "http://example.com/", nil)
-
-	resp := httptest.NewRecorder()
-	Redirect(resp, req, "/foo?next=http://bar.com/", 302)
-	if g, e := resp.Header().Get("Location"), "/foo?next=http://bar.com/"; g != e {
-		t.Errorf("Location header was %q; want %q", g, e)
-	}
-
-	resp = httptest.NewRecorder()
-	Redirect(resp, req, "http://localhost:8080/_ah/login?continue=http://localhost:8080/", 302)
-	if g, e := resp.Header().Get("Location"), "http://localhost:8080/_ah/login?continue=http://localhost:8080/"; g != e {
-		t.Errorf("Location header was %q; want %q", g, e)
-	}
-}
-
-// TestZeroLengthPostAndResponse exercises an optimization done by the Transport:
-// when there is no body (either because the method doesn't permit a body, or an
-// explicit Content-Length of zero is present), then the transport can re-use the
-// connection immediately. But when it re-uses the connection, it typically closes
-// the previous request's body, which is not optimal for zero-lengthed bodies,
-// as the client would then see http.ErrBodyReadAfterClose and not 0, os.EOF.
-func TestZeroLengthPostAndResponse(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
-		all, err := ioutil.ReadAll(r.Body)
-		if err != nil {
-			t.Fatalf("handler ReadAll: %v", err)
-		}
-		if len(all) != 0 {
-			t.Errorf("handler got %d bytes; expected 0", len(all))
-		}
-		rw.Header().Set("Content-Length", "0")
-	}))
-	defer ts.Close()
-
-	req, err := NewRequest("POST", ts.URL, strings.NewReader(""))
-	if err != nil {
-		t.Fatal(err)
-	}
-	req.ContentLength = 0
-
-	var resp [5]*Response
-	for i := range resp {
-		resp[i], err = DefaultClient.Do(req)
-		if err != nil {
-			t.Fatalf("client post #%d: %v", i, err)
-		}
-	}
-
-	for i := range resp {
-		all, err := ioutil.ReadAll(resp[i].Body)
-		if err != nil {
-			t.Fatalf("req #%d: client ReadAll: %v", i, err)
-		}
-		if len(all) != 0 {
-			t.Errorf("req #%d: client got %d bytes; expected 0", i, len(all))
-		}
-	}
-}
-
-func TestHandlerPanic(t *testing.T) {
-	// Unlike the other tests that set the log output to ioutil.Discard
-	// to quiet the output, this test uses a pipe.  The pipe serves three
-	// purposes:
-	//
-	//   1) The log.Print from the http server (generated by the caught
-	//      panic) will go to the pipe instead of stderr, making the
-	//      output quiet.
-	//
-	//   2) We read from the pipe to verify that the handler
-	//      actually caught the panic and logged something.
-	//
-	//   3) The blocking Read call prevents this TestHandlerPanic
-	//      function from exiting before the HTTP server handler
-	//      finishes crashing. If this text function exited too
-	//      early (and its defer log.SetOutput(os.Stderr) ran),
-	//      then the crash output could spill into the next test.
-	pr, pw := io.Pipe()
-	log.SetOutput(pw)
-	defer log.SetOutput(os.Stderr)
-
-	ts := httptest.NewServer(HandlerFunc(func(ResponseWriter, *Request) {
-		panic("intentional death for testing")
-	}))
-	defer ts.Close()
-	_, err := Get(ts.URL)
-	if err == nil {
-		t.Logf("expected an error")
-	}
-
-	// Do a blocking read on the log output pipe so its logging
-	// doesn't bleed into the next test.  But wait only 5 seconds
-	// for it.
-	done := make(chan bool)
-	go func() {
-		buf := make([]byte, 1024)
-		_, err := pr.Read(buf)
-		pr.Close()
-		if err != nil {
-			t.Fatal(err)
-		}
-		done <- true
-	}()
-	select {
-	case <-done:
-		return
-	case <-time.After(5e9):
-		t.Fatal("expected server handler to log an error")
-	}
-}
-
-func TestNoDate(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header()["Date"] = nil
-	}))
-	defer ts.Close()
-	res, err := Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	_, present := res.Header["Date"]
-	if present {
-		t.Fatalf("Expected no Date header; got %v", res.Header["Date"])
-	}
-}
-
-func TestStripPrefix(t *testing.T) {
-	h := HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header().Set("X-Path", r.URL.Path)
-	})
-	ts := httptest.NewServer(StripPrefix("/foo", h))
-	defer ts.Close()
-
-	res, err := Get(ts.URL + "/foo/bar")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if g, e := res.Header.Get("X-Path"), "/bar"; g != e {
-		t.Errorf("test 1: got %s, want %s", g, e)
-	}
-
-	res, err = Get(ts.URL + "/bar")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if g, e := res.StatusCode, 404; g != e {
-		t.Errorf("test 2: got status %v, want %v", g, e)
-	}
-}
-
-func TestRequestLimit(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		t.Fatalf("didn't expect to get request in Handler")
-	}))
-	defer ts.Close()
-	req, _ := NewRequest("GET", ts.URL, nil)
-	var bytesPerHeader = len("header12345: val12345\r\n")
-	for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ {
-		req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i))
-	}
-	res, err := DefaultClient.Do(req)
-	if err != nil {
-		// Some HTTP clients may fail on this undefined behavior (server replying and
-		// closing the connection while the request is still being written), but
-		// we do support it (at least currently), so we expect a response below.
-		t.Fatalf("Do: %v", err)
-	}
-	if res.StatusCode != 413 {
-		t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status)
-	}
-}
-
-type neverEnding byte
-
-func (b neverEnding) Read(p []byte) (n int, err os.Error) {
-	for i := range p {
-		p[i] = byte(b)
-	}
-	return len(p), nil
-}
-
-type countReader struct {
-	r io.Reader
-	n *int64
-}
-
-func (cr countReader) Read(p []byte) (n int, err os.Error) {
-	n, err = cr.r.Read(p)
-	*cr.n += int64(n)
-	return
-}
-
-func TestRequestBodyLimit(t *testing.T) {
-	const limit = 1 << 20
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		r.Body = MaxBytesReader(w, r.Body, limit)
-		n, err := io.Copy(ioutil.Discard, r.Body)
-		if err == nil {
-			t.Errorf("expected error from io.Copy")
-		}
-		if n != limit {
-			t.Errorf("io.Copy = %d, want %d", n, limit)
-		}
-	}))
-	defer ts.Close()
-
-	nWritten := int64(0)
-	req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), &nWritten}, limit*200))
-
-	// Send the POST, but don't care it succeeds or not.  The
-	// remote side is going to reply and then close the TCP
-	// connection, and HTTP doesn't really define if that's
-	// allowed or not.  Some HTTP clients will get the response
-	// and some (like ours, currently) will complain that the
-	// request write failed, without reading the response.
-	//
-	// But that's okay, since what we're really testing is that
-	// the remote side hung up on us before we wrote too much.
-	_, _ = DefaultClient.Do(req)
-
-	if nWritten > limit*100 {
-		t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
-			limit, nWritten)
-	}
-}
-
-type errorListener struct {
-	errs []os.Error
-}
-
-func (l *errorListener) Accept() (c net.Conn, err os.Error) {
-	if len(l.errs) == 0 {
-		return nil, os.EOF
-	}
-	err = l.errs[0]
-	l.errs = l.errs[1:]
-	return
-}
-
-func (l *errorListener) Close() os.Error {
-	return nil
-}
-
-func (l *errorListener) Addr() net.Addr {
-	return dummyAddr("test-address")
-}
-
-func TestAcceptMaxFds(t *testing.T) {
-	log.SetOutput(ioutil.Discard) // is noisy otherwise
-	defer log.SetOutput(os.Stderr)
-
-	ln := &errorListener{[]os.Error{
-		&net.OpError{
-			Op:    "accept",
-			Error: os.Errno(syscall.EMFILE),
-		}}}
-	err := Serve(ln, HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})))
-	if err != os.EOF {
-		t.Errorf("got error %v, want EOF", err)
-	}
-}
-
-func BenchmarkClientServer(b *testing.B) {
-	b.StopTimer()
-	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
-		fmt.Fprintf(rw, "Hello world.\n")
-	}))
-	defer ts.Close()
-	b.StartTimer()
-
-	for i := 0; i < b.N; i++ {
-		res, err := Get(ts.URL)
-		if err != nil {
-			panic("Get: " + err.String())
-		}
-		all, err := ioutil.ReadAll(res.Body)
-		if err != nil {
-			panic("ReadAll: " + err.String())
-		}
-		body := string(all)
-		if body != "Hello world.\n" {
-			panic("Got body: " + body)
-		}
-	}
-
-	b.StopTimer()
-}
diff --git a/src/pkg/http/server.go b/src/pkg/http/server.go
deleted file mode 100644
index 6be3611..0000000
--- a/src/pkg/http/server.go
+++ /dev/null
@@ -1,1159 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// HTTP server.  See RFC 2616.
-
-// TODO(rsc):
-//	logging
-
-package http
-
-import (
-	"bufio"
-	"bytes"
-	"crypto/rand"
-	"crypto/tls"
-	"fmt"
-	"io"
-	"log"
-	"net"
-	"os"
-	"path"
-	"runtime/debug"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-	"url"
-)
-
-// Errors introduced by the HTTP server.
-var (
-	ErrWriteAfterFlush = os.NewError("Conn.Write called after Flush")
-	ErrBodyNotAllowed  = os.NewError("http: response status code does not allow body")
-	ErrHijacked        = os.NewError("Conn has been hijacked")
-	ErrContentLength   = os.NewError("Conn.Write wrote more than the declared Content-Length")
-)
-
-// Objects implementing the Handler interface can be
-// registered to serve a particular path or subtree
-// in the HTTP server.
-//
-// ServeHTTP should write reply headers and data to the ResponseWriter
-// and then return.  Returning signals that the request is finished
-// and that the HTTP server can move on to the next request on
-// the connection.
-type Handler interface {
-	ServeHTTP(ResponseWriter, *Request)
-}
-
-// A ResponseWriter interface is used by an HTTP handler to
-// construct an HTTP response.
-type ResponseWriter interface {
-	// Header returns the header map that will be sent by WriteHeader.
-	// Changing the header after a call to WriteHeader (or Write) has
-	// no effect.
-	Header() Header
-
-	// Write writes the data to the connection as part of an HTTP reply.
-	// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
-	// before writing the data.
-	Write([]byte) (int, os.Error)
-
-	// WriteHeader sends an HTTP response header with status code.
-	// If WriteHeader is not called explicitly, the first call to Write
-	// will trigger an implicit WriteHeader(http.StatusOK).
-	// Thus explicit calls to WriteHeader are mainly used to
-	// send error codes.
-	WriteHeader(int)
-}
-
-// The Flusher interface is implemented by ResponseWriters that allow
-// an HTTP handler to flush buffered data to the client.
-//
-// Note that even for ResponseWriters that support Flush,
-// if the client is connected through an HTTP proxy,
-// the buffered data may not reach the client until the response
-// completes.
-type Flusher interface {
-	// Flush sends any buffered data to the client.
-	Flush()
-}
-
-// The Hijacker interface is implemented by ResponseWriters that allow
-// an HTTP handler to take over the connection.
-type Hijacker interface {
-	// Hijack lets the caller take over the connection.
-	// After a call to Hijack(), the HTTP server library
-	// will not do anything else with the connection.
-	// It becomes the caller's responsibility to manage
-	// and close the connection.
-	Hijack() (net.Conn, *bufio.ReadWriter, os.Error)
-}
-
-// A conn represents the server side of an HTTP connection.
-type conn struct {
-	remoteAddr string               // network address of remote side
-	server     *Server              // the Server on which the connection arrived
-	rwc        net.Conn             // i/o connection
-	lr         *io.LimitedReader    // io.LimitReader(rwc)
-	buf        *bufio.ReadWriter    // buffered(lr,rwc), reading from bufio->limitReader->rwc
-	hijacked   bool                 // connection has been hijacked by handler
-	tlsState   *tls.ConnectionState // or nil when not using TLS
-	body       []byte
-}
-
-// A response represents the server side of an HTTP response.
-type response struct {
-	conn          *conn
-	req           *Request // request for this response
-	chunking      bool     // using chunked transfer encoding for reply body
-	wroteHeader   bool     // reply header has been written
-	wroteContinue bool     // 100 Continue response was written
-	header        Header   // reply header parameters
-	written       int64    // number of bytes written in body
-	contentLength int64    // explicitly-declared Content-Length; or -1
-	status        int      // status code passed to WriteHeader
-	needSniff     bool     // need to sniff to find Content-Type
-
-	// close connection after this reply.  set on request and
-	// updated after response from handler if there's a
-	// "Connection: keep-alive" response header and a
-	// Content-Length.
-	closeAfterReply bool
-
-	// requestBodyLimitHit is set by requestTooLarge when
-	// maxBytesReader hits its max size. It is checked in
-	// WriteHeader, to make sure we don't consume the the
-	// remaining request body to try to advance to the next HTTP
-	// request. Instead, when this is set, we stop doing
-	// subsequent requests on this connection and stop reading
-	// input from it.
-	requestBodyLimitHit bool
-}
-
-// requestTooLarge is called by maxBytesReader when too much input has
-// been read from the client.
-func (r *response) requestTooLarge() {
-	r.closeAfterReply = true
-	r.requestBodyLimitHit = true
-	if !r.wroteHeader {
-		r.Header().Set("Connection", "close")
-	}
-}
-
-type writerOnly struct {
-	io.Writer
-}
-
-func (r *response) ReadFrom(src io.Reader) (n int64, err os.Error) {
-	// Flush before checking r.chunking, as Flush will call
-	// WriteHeader if it hasn't been called yet, and WriteHeader
-	// is what sets r.chunking.
-	r.Flush()
-	if !r.chunking && r.bodyAllowed() && !r.needSniff {
-		if rf, ok := r.conn.rwc.(io.ReaderFrom); ok {
-			n, err = rf.ReadFrom(src)
-			r.written += n
-			return
-		}
-	}
-	// Fall back to default io.Copy implementation.
-	// Use wrapper to hide r.ReadFrom from io.Copy.
-	return io.Copy(writerOnly{r}, src)
-}
-
-// noLimit is an effective infinite upper bound for io.LimitedReader
-const noLimit int64 = (1 << 63) - 1
-
-// Create new connection from rwc.
-func (srv *Server) newConn(rwc net.Conn) (c *conn, err os.Error) {
-	c = new(conn)
-	c.remoteAddr = rwc.RemoteAddr().String()
-	c.server = srv
-	c.rwc = rwc
-	c.body = make([]byte, sniffLen)
-	c.lr = io.LimitReader(rwc, noLimit).(*io.LimitedReader)
-	br := bufio.NewReader(c.lr)
-	bw := bufio.NewWriter(rwc)
-	c.buf = bufio.NewReadWriter(br, bw)
-	return c, nil
-}
-
-// DefaultMaxHeaderBytes is the maximum permitted size of the headers
-// in an HTTP request.
-// This can be overridden by setting Server.MaxHeaderBytes.
-const DefaultMaxHeaderBytes = 1 << 20 // 1 MB
-
-func (srv *Server) maxHeaderBytes() int {
-	if srv.MaxHeaderBytes > 0 {
-		return srv.MaxHeaderBytes
-	}
-	return DefaultMaxHeaderBytes
-}
-
-// wrapper around io.ReaderCloser which on first read, sends an
-// HTTP/1.1 100 Continue header
-type expectContinueReader struct {
-	resp       *response
-	readCloser io.ReadCloser
-	closed     bool
-}
-
-func (ecr *expectContinueReader) Read(p []byte) (n int, err os.Error) {
-	if ecr.closed {
-		return 0, os.NewError("http: Read after Close on request Body")
-	}
-	if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked {
-		ecr.resp.wroteContinue = true
-		io.WriteString(ecr.resp.conn.buf, "HTTP/1.1 100 Continue\r\n\r\n")
-		ecr.resp.conn.buf.Flush()
-	}
-	return ecr.readCloser.Read(p)
-}
-
-func (ecr *expectContinueReader) Close() os.Error {
-	ecr.closed = true
-	return ecr.readCloser.Close()
-}
-
-// TimeFormat is the time format to use with
-// time.Parse and time.Time.Format when parsing
-// or generating times in HTTP headers.
-// It is like time.RFC1123 but hard codes GMT as the time zone.
-const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
-
-var errTooLarge = os.NewError("http: request too large")
-
-// Read next request from connection.
-func (c *conn) readRequest() (w *response, err os.Error) {
-	if c.hijacked {
-		return nil, ErrHijacked
-	}
-	c.lr.N = int64(c.server.maxHeaderBytes()) + 4096 /* bufio slop */
-	var req *Request
-	if req, err = ReadRequest(c.buf.Reader); err != nil {
-		if c.lr.N == 0 {
-			return nil, errTooLarge
-		}
-		return nil, err
-	}
-	c.lr.N = noLimit
-
-	req.RemoteAddr = c.remoteAddr
-	req.TLS = c.tlsState
-
-	w = new(response)
-	w.conn = c
-	w.req = req
-	w.header = make(Header)
-	w.contentLength = -1
-	c.body = c.body[:0]
-	return w, nil
-}
-
-func (w *response) Header() Header {
-	return w.header
-}
-
-func (w *response) WriteHeader(code int) {
-	if w.conn.hijacked {
-		log.Print("http: response.WriteHeader on hijacked connection")
-		return
-	}
-	if w.wroteHeader {
-		log.Print("http: multiple response.WriteHeader calls")
-		return
-	}
-
-	// Per RFC 2616, we should consume the request body before
-	// replying, if the handler hasn't already done so.
-	if w.req.ContentLength != 0 && !w.requestBodyLimitHit {
-		ecr, isExpecter := w.req.Body.(*expectContinueReader)
-		if !isExpecter || ecr.resp.wroteContinue {
-			w.req.Body.Close()
-		}
-	}
-
-	w.wroteHeader = true
-	w.status = code
-	if code == StatusNotModified {
-		// Must not have body.
-		for _, header := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
-			if w.header.Get(header) != "" {
-				// TODO: return an error if WriteHeader gets a return parameter
-				// or set a flag on w to make future Writes() write an error page?
-				// for now just log and drop the header.
-				log.Printf("http: StatusNotModified response with header %q defined", header)
-				w.header.Del(header)
-			}
-		}
-	} else {
-		// If no content type, apply sniffing algorithm to body.
-		if w.header.Get("Content-Type") == "" {
-			w.needSniff = true
-		}
-	}
-
-	if _, ok := w.header["Date"]; !ok {
-		w.Header().Set("Date", time.UTC().Format(TimeFormat))
-	}
-
-	// Check for a explicit (and valid) Content-Length header.
-	var hasCL bool
-	var contentLength int64
-	if clenStr := w.header.Get("Content-Length"); clenStr != "" {
-		var err os.Error
-		contentLength, err = strconv.Atoi64(clenStr)
-		if err == nil {
-			hasCL = true
-		} else {
-			log.Printf("http: invalid Content-Length of %q sent", clenStr)
-			w.header.Del("Content-Length")
-		}
-	}
-
-	te := w.header.Get("Transfer-Encoding")
-	hasTE := te != ""
-	if hasCL && hasTE && te != "identity" {
-		// TODO: return an error if WriteHeader gets a return parameter
-		// For now just ignore the Content-Length.
-		log.Printf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
-			te, contentLength)
-		w.header.Del("Content-Length")
-		hasCL = false
-	}
-
-	if w.req.Method == "HEAD" || code == StatusNotModified {
-		// do nothing
-	} else if hasCL {
-		w.contentLength = contentLength
-		w.header.Del("Transfer-Encoding")
-	} else if w.req.ProtoAtLeast(1, 1) {
-		// HTTP/1.1 or greater: use chunked transfer encoding
-		// to avoid closing the connection at EOF.
-		// TODO: this blows away any custom or stacked Transfer-Encoding they
-		// might have set.  Deal with that as need arises once we have a valid
-		// use case.
-		w.chunking = true
-		w.header.Set("Transfer-Encoding", "chunked")
-	} else {
-		// HTTP version < 1.1: cannot do chunked transfer
-		// encoding and we don't know the Content-Length so
-		// signal EOF by closing connection.
-		w.closeAfterReply = true
-		w.header.Del("Transfer-Encoding") // in case already set
-	}
-
-	if w.req.wantsHttp10KeepAlive() && (w.req.Method == "HEAD" || hasCL) {
-		_, connectionHeaderSet := w.header["Connection"]
-		if !connectionHeaderSet {
-			w.header.Set("Connection", "keep-alive")
-		}
-	} else if !w.req.ProtoAtLeast(1, 1) {
-		// Client did not ask to keep connection alive.
-		w.closeAfterReply = true
-	}
-
-	if w.header.Get("Connection") == "close" {
-		w.closeAfterReply = true
-	}
-
-	// Cannot use Content-Length with non-identity Transfer-Encoding.
-	if w.chunking {
-		w.header.Del("Content-Length")
-	}
-	if !w.req.ProtoAtLeast(1, 0) {
-		return
-	}
-	proto := "HTTP/1.0"
-	if w.req.ProtoAtLeast(1, 1) {
-		proto = "HTTP/1.1"
-	}
-	codestring := strconv.Itoa(code)
-	text, ok := statusText[code]
-	if !ok {
-		text = "status code " + codestring
-	}
-	io.WriteString(w.conn.buf, proto+" "+codestring+" "+text+"\r\n")
-	w.header.Write(w.conn.buf)
-
-	// If we need to sniff the body, leave the header open.
-	// Otherwise, end it here.
-	if !w.needSniff {
-		io.WriteString(w.conn.buf, "\r\n")
-	}
-}
-
-// sniff uses the first block of written data,
-// stored in w.conn.body, to decide the Content-Type
-// for the HTTP body.
-func (w *response) sniff() {
-	if !w.needSniff {
-		return
-	}
-	w.needSniff = false
-
-	data := w.conn.body
-	fmt.Fprintf(w.conn.buf, "Content-Type: %s\r\n\r\n", DetectContentType(data))
-
-	if len(data) == 0 {
-		return
-	}
-	if w.chunking {
-		fmt.Fprintf(w.conn.buf, "%x\r\n", len(data))
-	}
-	_, err := w.conn.buf.Write(data)
-	if w.chunking && err == nil {
-		io.WriteString(w.conn.buf, "\r\n")
-	}
-}
-
-// bodyAllowed returns true if a Write is allowed for this response type.
-// It's illegal to call this before the header has been flushed.
-func (w *response) bodyAllowed() bool {
-	if !w.wroteHeader {
-		panic("")
-	}
-	return w.status != StatusNotModified && w.req.Method != "HEAD"
-}
-
-func (w *response) Write(data []byte) (n int, err os.Error) {
-	if w.conn.hijacked {
-		log.Print("http: response.Write on hijacked connection")
-		return 0, ErrHijacked
-	}
-	if !w.wroteHeader {
-		w.WriteHeader(StatusOK)
-	}
-	if len(data) == 0 {
-		return 0, nil
-	}
-	if !w.bodyAllowed() {
-		return 0, ErrBodyNotAllowed
-	}
-
-	w.written += int64(len(data)) // ignoring errors, for errorKludge
-	if w.contentLength != -1 && w.written > w.contentLength {
-		return 0, ErrContentLength
-	}
-
-	var m int
-	if w.needSniff {
-		// We need to sniff the beginning of the output to
-		// determine the content type.  Accumulate the
-		// initial writes in w.conn.body.
-		// Cap m so that append won't allocate.
-		m := cap(w.conn.body) - len(w.conn.body)
-		if m > len(data) {
-			m = len(data)
-		}
-		w.conn.body = append(w.conn.body, data[:m]...)
-		data = data[m:]
-		if len(data) == 0 {
-			// Copied everything into the buffer.
-			// Wait for next write.
-			return m, nil
-		}
-
-		// Filled the buffer; more data remains.
-		// Sniff the content (flushes the buffer)
-		// and then proceed with the remainder
-		// of the data as a normal Write.
-		// Calling sniff clears needSniff.
-		w.sniff()
-	}
-
-	// TODO(rsc): if chunking happened after the buffering,
-	// then there would be fewer chunk headers.
-	// On the other hand, it would make hijacking more difficult.
-	if w.chunking {
-		fmt.Fprintf(w.conn.buf, "%x\r\n", len(data)) // TODO(rsc): use strconv not fmt
-	}
-	n, err = w.conn.buf.Write(data)
-	if err == nil && w.chunking {
-		if n != len(data) {
-			err = io.ErrShortWrite
-		}
-		if err == nil {
-			io.WriteString(w.conn.buf, "\r\n")
-		}
-	}
-
-	return m + n, err
-}
-
-func (w *response) finishRequest() {
-	// If this was an HTTP/1.0 request with keep-alive and we sent a Content-Length
-	// back, we can make this a keep-alive response ...
-	if w.req.wantsHttp10KeepAlive() {
-		sentLength := w.header.Get("Content-Length") != ""
-		if sentLength && w.header.Get("Connection") == "keep-alive" {
-			w.closeAfterReply = false
-		}
-	}
-	if !w.wroteHeader {
-		w.WriteHeader(StatusOK)
-	}
-	if w.needSniff {
-		w.sniff()
-	}
-	if w.chunking {
-		io.WriteString(w.conn.buf, "0\r\n")
-		// trailer key/value pairs, followed by blank line
-		io.WriteString(w.conn.buf, "\r\n")
-	}
-	w.conn.buf.Flush()
-	// Close the body, unless we're about to close the whole TCP connection
-	// anyway.
-	if !w.closeAfterReply {
-		w.req.Body.Close()
-	}
-	if w.req.MultipartForm != nil {
-		w.req.MultipartForm.RemoveAll()
-	}
-
-	if w.contentLength != -1 && w.contentLength != w.written {
-		// Did not write enough. Avoid getting out of sync.
-		w.closeAfterReply = true
-	}
-}
-
-func (w *response) Flush() {
-	if !w.wroteHeader {
-		w.WriteHeader(StatusOK)
-	}
-	w.sniff()
-	w.conn.buf.Flush()
-}
-
-// Close the connection.
-func (c *conn) close() {
-	if c.buf != nil {
-		c.buf.Flush()
-		c.buf = nil
-	}
-	if c.rwc != nil {
-		c.rwc.Close()
-		c.rwc = nil
-	}
-}
-
-// Serve a new connection.
-func (c *conn) serve() {
-	defer func() {
-		err := recover()
-		if err == nil {
-			return
-		}
-		c.rwc.Close()
-
-		var buf bytes.Buffer
-		fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
-		buf.Write(debug.Stack())
-		log.Print(buf.String())
-	}()
-
-	if tlsConn, ok := c.rwc.(*tls.Conn); ok {
-		tlsConn.Handshake()
-		c.tlsState = new(tls.ConnectionState)
-		*c.tlsState = tlsConn.ConnectionState()
-	}
-
-	for {
-		w, err := c.readRequest()
-		if err != nil {
-			msg := "400 Bad Request"
-			if err == errTooLarge {
-				// Their HTTP client may or may not be
-				// able to read this if we're
-				// responding to them and hanging up
-				// while they're still writing their
-				// request.  Undefined behavior.
-				msg = "413 Request Entity Too Large"
-			} else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
-				break // Don't reply
-			}
-			fmt.Fprintf(c.rwc, "HTTP/1.1 %s\r\n\r\n", msg)
-			break
-		}
-
-		// Expect 100 Continue support
-		req := w.req
-		if req.expectsContinue() {
-			if req.ProtoAtLeast(1, 1) {
-				// Wrap the Body reader with one that replies on the connection
-				req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
-			}
-			if req.ContentLength == 0 {
-				w.Header().Set("Connection", "close")
-				w.WriteHeader(StatusBadRequest)
-				w.finishRequest()
-				break
-			}
-			req.Header.Del("Expect")
-		} else if req.Header.Get("Expect") != "" {
-			// TODO(bradfitz): let ServeHTTP handlers handle
-			// requests with non-standard expectation[s]? Seems
-			// theoretical at best, and doesn't fit into the
-			// current ServeHTTP model anyway.  We'd need to
-			// make the ResponseWriter an optional
-			// "ExpectReplier" interface or something.
-			//
-			// For now we'll just obey RFC 2616 14.20 which says
-			// "If a server receives a request containing an
-			// Expect field that includes an expectation-
-			// extension that it does not support, it MUST
-			// respond with a 417 (Expectation Failed) status."
-			w.Header().Set("Connection", "close")
-			w.WriteHeader(StatusExpectationFailed)
-			w.finishRequest()
-			break
-		}
-
-		handler := c.server.Handler
-		if handler == nil {
-			handler = DefaultServeMux
-		}
-
-		// HTTP cannot have multiple simultaneous active requests.[*]
-		// Until the server replies to this request, it can't read another,
-		// so we might as well run the handler in this goroutine.
-		// [*] Not strictly true: HTTP pipelining.  We could let them all process
-		// in parallel even if their responses need to be serialized.
-		handler.ServeHTTP(w, w.req)
-		if c.hijacked {
-			return
-		}
-		w.finishRequest()
-		if w.closeAfterReply {
-			break
-		}
-	}
-	c.close()
-}
-
-// Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter
-// and a Hijacker.
-func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err os.Error) {
-	if w.conn.hijacked {
-		return nil, nil, ErrHijacked
-	}
-	w.conn.hijacked = true
-	rwc = w.conn.rwc
-	buf = w.conn.buf
-	w.conn.rwc = nil
-	w.conn.buf = nil
-	return
-}
-
-// The HandlerFunc type is an adapter to allow the use of
-// ordinary functions as HTTP handlers.  If f is a function
-// with the appropriate signature, HandlerFunc(f) is a
-// Handler object that calls f.
-type HandlerFunc func(ResponseWriter, *Request)
-
-// ServeHTTP calls f(w, r).
-func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
-	f(w, r)
-}
-
-// Helper handlers
-
-// Error replies to the request with the specified error message and HTTP code.
-func Error(w ResponseWriter, error string, code int) {
-	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-	w.WriteHeader(code)
-	fmt.Fprintln(w, error)
-}
-
-// NotFound replies to the request with an HTTP 404 not found error.
-func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
-
-// NotFoundHandler returns a simple request handler
-// that replies to each request with a ``404 page not found'' reply.
-func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
-
-// StripPrefix returns a handler that serves HTTP requests
-// by removing the given prefix from the request URL's Path
-// and invoking the handler h. StripPrefix handles a
-// request for a path that doesn't begin with prefix by
-// replying with an HTTP 404 not found error.
-func StripPrefix(prefix string, h Handler) Handler {
-	return HandlerFunc(func(w ResponseWriter, r *Request) {
-		if !strings.HasPrefix(r.URL.Path, prefix) {
-			NotFound(w, r)
-			return
-		}
-		r.URL.Path = r.URL.Path[len(prefix):]
-		h.ServeHTTP(w, r)
-	})
-}
-
-// Redirect replies to the request with a redirect to url,
-// which may be a path relative to the request path.
-func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
-	if u, err := url.Parse(urlStr); err == nil {
-		// If url was relative, make absolute by
-		// combining with request path.
-		// The browser would probably do this for us,
-		// but doing it ourselves is more reliable.
-
-		// NOTE(rsc): RFC 2616 says that the Location
-		// line must be an absolute URI, like
-		// "http://www.google.com/redirect/",
-		// not a path like "/redirect/".
-		// Unfortunately, we don't know what to
-		// put in the host name section to get the
-		// client to connect to us again, so we can't
-		// know the right absolute URI to send back.
-		// Because of this problem, no one pays attention
-		// to the RFC; they all send back just a new path.
-		// So do we.
-		oldpath := r.URL.Path
-		if oldpath == "" { // should not happen, but avoid a crash if it does
-			oldpath = "/"
-		}
-		if u.Scheme == "" {
-			// no leading http://server
-			if urlStr == "" || urlStr[0] != '/' {
-				// make relative path absolute
-				olddir, _ := path.Split(oldpath)
-				urlStr = olddir + urlStr
-			}
-
-			var query string
-			if i := strings.Index(urlStr, "?"); i != -1 {
-				urlStr, query = urlStr[:i], urlStr[i:]
-			}
-
-			// clean up but preserve trailing slash
-			trailing := urlStr[len(urlStr)-1] == '/'
-			urlStr = path.Clean(urlStr)
-			if trailing && urlStr[len(urlStr)-1] != '/' {
-				urlStr += "/"
-			}
-			urlStr += query
-		}
-	}
-
-	w.Header().Set("Location", urlStr)
-	w.WriteHeader(code)
-
-	// RFC2616 recommends that a short note "SHOULD" be included in the
-	// response because older user agents may not understand 301/307.
-	// Shouldn't send the response for POST or HEAD; that leaves GET.
-	if r.Method == "GET" {
-		note := "<a href=\"" + htmlEscape(urlStr) + "\">" + statusText[code] + "</a>.\n"
-		fmt.Fprintln(w, note)
-	}
-}
-
-func htmlEscape(s string) string {
-	s = strings.Replace(s, "&", "&", -1)
-	s = strings.Replace(s, "<", "<", -1)
-	s = strings.Replace(s, ">", ">", -1)
-	s = strings.Replace(s, "\"", """, -1)
-	s = strings.Replace(s, "'", "'", -1)
-	return s
-}
-
-// Redirect to a fixed URL
-type redirectHandler struct {
-	url  string
-	code int
-}
-
-func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
-	Redirect(w, r, rh.url, rh.code)
-}
-
-// RedirectHandler returns a request handler that redirects
-// each request it receives to the given url using the given
-// status code.
-func RedirectHandler(url string, code int) Handler {
-	return &redirectHandler{url, code}
-}
-
-// ServeMux is an HTTP request multiplexer.
-// It matches the URL of each incoming request against a list of registered
-// patterns and calls the handler for the pattern that
-// most closely matches the URL.
-//
-// Patterns named fixed, rooted paths, like "/favicon.ico",
-// or rooted subtrees, like "/images/" (note the trailing slash).
-// Longer patterns take precedence over shorter ones, so that
-// if there are handlers registered for both "/images/"
-// and "/images/thumbnails/", the latter handler will be
-// called for paths beginning "/images/thumbnails/" and the
-// former will receiver requests for any other paths in the
-// "/images/" subtree.
-//
-// Patterns may optionally begin with a host name, restricting matches to
-// URLs on that host only.  Host-specific patterns take precedence over
-// general patterns, so that a handler might register for the two patterns
-// "/codesearch" and "codesearch.google.com/" without also taking over
-// requests for "http://www.google.com/".
-//
-// ServeMux also takes care of sanitizing the URL request path,
-// redirecting any request containing . or .. elements to an
-// equivalent .- and ..-free URL.
-type ServeMux struct {
-	m map[string]Handler
-}
-
-// NewServeMux allocates and returns a new ServeMux.
-func NewServeMux() *ServeMux { return &ServeMux{make(map[string]Handler)} }
-
-// DefaultServeMux is the default ServeMux used by Serve.
-var DefaultServeMux = NewServeMux()
-
-// Does path match pattern?
-func pathMatch(pattern, path string) bool {
-	if len(pattern) == 0 {
-		// should not happen
-		return false
-	}
-	n := len(pattern)
-	if pattern[n-1] != '/' {
-		return pattern == path
-	}
-	return len(path) >= n && path[0:n] == pattern
-}
-
-// Return the canonical path for p, eliminating . and .. elements.
-func cleanPath(p string) string {
-	if p == "" {
-		return "/"
-	}
-	if p[0] != '/' {
-		p = "/" + p
-	}
-	np := path.Clean(p)
-	// path.Clean removes trailing slash except for root;
-	// put the trailing slash back if necessary.
-	if p[len(p)-1] == '/' && np != "/" {
-		np += "/"
-	}
-	return np
-}
-
-// Find a handler on a handler map given a path string
-// Most-specific (longest) pattern wins
-func (mux *ServeMux) match(path string) Handler {
-	var h Handler
-	var n = 0
-	for k, v := range mux.m {
-		if !pathMatch(k, path) {
-			continue
-		}
-		if h == nil || len(k) > n {
-			n = len(k)
-			h = v
-		}
-	}
-	return h
-}
-
-// ServeHTTP dispatches the request to the handler whose
-// pattern most closely matches the request URL.
-func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
-	// Clean path to canonical form and redirect.
-	if p := cleanPath(r.URL.Path); p != r.URL.Path {
-		w.Header().Set("Location", p)
-		w.WriteHeader(StatusMovedPermanently)
-		return
-	}
-	// Host-specific pattern takes precedence over generic ones
-	h := mux.match(r.Host + r.URL.Path)
-	if h == nil {
-		h = mux.match(r.URL.Path)
-	}
-	if h == nil {
-		h = NotFoundHandler()
-	}
-	h.ServeHTTP(w, r)
-}
-
-// Handle registers the handler for the given pattern.
-func (mux *ServeMux) Handle(pattern string, handler Handler) {
-	if pattern == "" {
-		panic("http: invalid pattern " + pattern)
-	}
-
-	mux.m[pattern] = handler
-
-	// Helpful behavior:
-	// If pattern is /tree/, insert permanent redirect for /tree.
-	n := len(pattern)
-	if n > 0 && pattern[n-1] == '/' {
-		mux.m[pattern[0:n-1]] = RedirectHandler(pattern, StatusMovedPermanently)
-	}
-}
-
-// HandleFunc registers the handler function for the given pattern.
-func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
-	mux.Handle(pattern, HandlerFunc(handler))
-}
-
-// Handle registers the handler for the given pattern
-// in the DefaultServeMux.
-// The documentation for ServeMux explains how patterns are matched.
-func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
-
-// HandleFunc registers the handler function for the given pattern
-// in the DefaultServeMux.
-// The documentation for ServeMux explains how patterns are matched.
-func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
-	DefaultServeMux.HandleFunc(pattern, handler)
-}
-
-// Serve accepts incoming HTTP connections on the listener l,
-// creating a new service thread for each.  The service threads
-// read requests and then call handler to reply to them.
-// Handler is typically nil, in which case the DefaultServeMux is used.
-func Serve(l net.Listener, handler Handler) os.Error {
-	srv := &Server{Handler: handler}
-	return srv.Serve(l)
-}
-
-// A Server defines parameters for running an HTTP server.
-type Server struct {
-	Addr           string  // TCP address to listen on, ":http" if empty
-	Handler        Handler // handler to invoke, http.DefaultServeMux if nil
-	ReadTimeout    int64   // the net.Conn.SetReadTimeout value for new connections
-	WriteTimeout   int64   // the net.Conn.SetWriteTimeout value for new connections
-	MaxHeaderBytes int     // maximum size of request headers, DefaultMaxHeaderBytes if 0
-}
-
-// ListenAndServe listens on the TCP network address srv.Addr and then
-// calls Serve to handle requests on incoming connections.  If
-// srv.Addr is blank, ":http" is used.
-func (srv *Server) ListenAndServe() os.Error {
-	addr := srv.Addr
-	if addr == "" {
-		addr = ":http"
-	}
-	l, e := net.Listen("tcp", addr)
-	if e != nil {
-		return e
-	}
-	return srv.Serve(l)
-}
-
-// Serve accepts incoming connections on the Listener l, creating a
-// new service thread for each.  The service threads read requests and
-// then call srv.Handler to reply to them.
-func (srv *Server) Serve(l net.Listener) os.Error {
-	defer l.Close()
-	for {
-		rw, e := l.Accept()
-		if e != nil {
-			if ne, ok := e.(net.Error); ok && ne.Temporary() {
-				log.Printf("http: Accept error: %v", e)
-				continue
-			}
-			return e
-		}
-		if srv.ReadTimeout != 0 {
-			rw.SetReadTimeout(srv.ReadTimeout)
-		}
-		if srv.WriteTimeout != 0 {
-			rw.SetWriteTimeout(srv.WriteTimeout)
-		}
-		c, err := srv.newConn(rw)
-		if err != nil {
-			continue
-		}
-		go c.serve()
-	}
-	panic("not reached")
-}
-
-// ListenAndServe listens on the TCP network address addr
-// and then calls Serve with handler to handle requests
-// on incoming connections.  Handler is typically nil,
-// in which case the DefaultServeMux is used.
-//
-// A trivial example server is:
-//
-//	package main
-//
-//	import (
-//		"http"
-//		"io"
-//		"log"
-//	)
-//
-//	// hello world, the web server
-//	func HelloServer(w http.ResponseWriter, req *http.Request) {
-//		io.WriteString(w, "hello, world!\n")
-//	}
-//
-//	func main() {
-//		http.HandleFunc("/hello", HelloServer)
-//		err := http.ListenAndServe(":12345", nil)
-//		if err != nil {
-//			log.Fatal("ListenAndServe: ", err.String())
-//		}
-//	}
-func ListenAndServe(addr string, handler Handler) os.Error {
-	server := &Server{Addr: addr, Handler: handler}
-	return server.ListenAndServe()
-}
-
-// ListenAndServeTLS acts identically to ListenAndServe, except that it
-// expects HTTPS connections. Additionally, files containing a certificate and
-// matching private key for the server must be provided. If the certificate
-// is signed by a certificate authority, the certFile should be the concatenation
-// of the server's certificate followed by the CA's certificate.
-//
-// A trivial example server is:
-//
-//	import (
-//		"http"
-//		"log"
-//	)
-//
-//	func handler(w http.ResponseWriter, req *http.Request) {
-//		w.Header().Set("Content-Type", "text/plain")
-//		w.Write([]byte("This is an example server.\n"))
-//	}
-//
-//	func main() {
-//		http.HandleFunc("/", handler)
-//		log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
-//		err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
-//		if err != nil {
-//			log.Fatal(err)
-//		}
-//	}
-//
-// One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
-func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) os.Error {
-	server := &Server{Addr: addr, Handler: handler}
-	return server.ListenAndServeTLS(certFile, keyFile)
-}
-
-// ListenAndServeTLS listens on the TCP network address srv.Addr and
-// then calls Serve to handle requests on incoming TLS connections.
-//
-// Filenames containing a certificate and matching private key for
-// the server must be provided. If the certificate is signed by a
-// certificate authority, the certFile should be the concatenation
-// of the server's certificate followed by the CA's certificate.
-//
-// If srv.Addr is blank, ":https" is used.
-func (s *Server) ListenAndServeTLS(certFile, keyFile string) os.Error {
-	addr := s.Addr
-	if addr == "" {
-		addr = ":https"
-	}
-	config := &tls.Config{
-		Rand:       rand.Reader,
-		Time:       time.Seconds,
-		NextProtos: []string{"http/1.1"},
-	}
-
-	var err os.Error
-	config.Certificates = make([]tls.Certificate, 1)
-	config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
-	if err != nil {
-		return err
-	}
-
-	conn, err := net.Listen("tcp", addr)
-	if err != nil {
-		return err
-	}
-
-	tlsListener := tls.NewListener(conn, config)
-	return s.Serve(tlsListener)
-}
-
-// TimeoutHandler returns a Handler that runs h with the given time limit.
-//
-// The new Handler calls h.ServeHTTP to handle each request, but if a
-// call runs for more than ns nanoseconds, the handler responds with
-// a 503 Service Unavailable error and the given message in its body.
-// (If msg is empty, a suitable default message will be sent.)
-// After such a timeout, writes by h to its ResponseWriter will return
-// ErrHandlerTimeout.
-func TimeoutHandler(h Handler, ns int64, msg string) Handler {
-	f := func() <-chan int64 {
-		return time.After(ns)
-	}
-	return &timeoutHandler{h, f, msg}
-}
-
-// ErrHandlerTimeout is returned on ResponseWriter Write calls
-// in handlers which have timed out.
-var ErrHandlerTimeout = os.NewError("http: Handler timeout")
-
-type timeoutHandler struct {
-	handler Handler
-	timeout func() <-chan int64 // returns channel producing a timeout
-	body    string
-}
-
-func (h *timeoutHandler) errorBody() string {
-	if h.body != "" {
-		return h.body
-	}
-	return "<html><head><title>Timeout</title></head><body><h1>Timeout</h1></body></html>"
-}
-
-func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
-	done := make(chan bool)
-	tw := &timeoutWriter{w: w}
-	go func() {
-		h.handler.ServeHTTP(tw, r)
-		done <- true
-	}()
-	select {
-	case <-done:
-		return
-	case <-h.timeout():
-		tw.mu.Lock()
-		defer tw.mu.Unlock()
-		if !tw.wroteHeader {
-			tw.w.WriteHeader(StatusServiceUnavailable)
-			tw.w.Write([]byte(h.errorBody()))
-		}
-		tw.timedOut = true
-	}
-}
-
-type timeoutWriter struct {
-	w ResponseWriter
-
-	mu          sync.Mutex
-	timedOut    bool
-	wroteHeader bool
-}
-
-func (tw *timeoutWriter) Header() Header {
-	return tw.w.Header()
-}
-
-func (tw *timeoutWriter) Write(p []byte) (int, os.Error) {
-	tw.mu.Lock()
-	timedOut := tw.timedOut
-	tw.mu.Unlock()
-	if timedOut {
-		return 0, ErrHandlerTimeout
-	}
-	return tw.w.Write(p)
-}
-
-func (tw *timeoutWriter) WriteHeader(code int) {
-	tw.mu.Lock()
-	if tw.timedOut || tw.wroteHeader {
-		tw.mu.Unlock()
-		return
-	}
-	tw.wroteHeader = true
-	tw.mu.Unlock()
-	tw.w.WriteHeader(code)
-}
diff --git a/src/pkg/http/sniff.go b/src/pkg/http/sniff.go
deleted file mode 100644
index d608687..0000000
--- a/src/pkg/http/sniff.go
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2011 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 http
-
-import (
-	"bytes"
-	"encoding/binary"
-)
-
-// Content-type sniffing algorithm.
-// References in this file refer to this draft specification:
-//   http://tools.ietf.org/html/draft-ietf-websec-mime-sniff-03
-
-// The algorithm prefers to use sniffLen bytes to make its decision.
-const sniffLen = 512
-
-// DetectContentType returns the sniffed Content-Type string
-// for the given data. This function always returns a valid MIME type.
-func DetectContentType(data []byte) string {
-	if len(data) > sniffLen {
-		data = data[:sniffLen]
-	}
-
-	// Index of the first non-whitespace byte in data.
-	firstNonWS := 0
-	for ; firstNonWS < len(data) && isWS(data[firstNonWS]); firstNonWS++ {
-	}
-
-	for _, sig := range sniffSignatures {
-		if ct := sig.match(data, firstNonWS); ct != "" {
-			return ct
-		}
-	}
-
-	return "application/octet-stream" // fallback
-}
-
-func isWS(b byte) bool {
-	return bytes.IndexByte([]byte("\t\n\x0C\n "), b) != -1
-}
-
-type sniffSig interface {
-	// match returns the MIME type of the data, or "" if unknown.
-	match(data []byte, firstNonWS int) string
-}
-
-// Data matching the table in section 6.
-var sniffSignatures = []sniffSig{
-	htmlSig([]byte("<!DOCTYPE HTML")),
-	htmlSig([]byte("<HTML")),
-	htmlSig([]byte("<HEAD")),
-	htmlSig([]byte("<SCRIPT")),
-	htmlSig([]byte("<IFRAME")),
-	htmlSig([]byte("<H1")),
-	htmlSig([]byte("<DIV")),
-	htmlSig([]byte("<FONT")),
-	htmlSig([]byte("<TABLE")),
-	htmlSig([]byte("<A")),
-	htmlSig([]byte("<STYLE")),
-	htmlSig([]byte("<TITLE")),
-	htmlSig([]byte("<B")),
-	htmlSig([]byte("<BODY")),
-	htmlSig([]byte("<BR")),
-	htmlSig([]byte("<P")),
-	htmlSig([]byte("<!--")),
-
-	&maskedSig{mask: []byte("\xFF\xFF\xFF\xFF\xFF"), pat: []byte("<?xml"), skipWS: true, ct: "text/xml; charset=utf-8"},
-
-	&exactSig{[]byte("%PDF-"), "application/pdf"},
-	&exactSig{[]byte("%!PS-Adobe-"), "application/postscript"},
-
-	// UTF BOMs.
-	&maskedSig{mask: []byte("\xFF\xFF\x00\x00"), pat: []byte("\xFE\xFF\x00\x00"), ct: "text/plain; charset=utf-16be"},
-	&maskedSig{mask: []byte("\xFF\xFF\x00\x00"), pat: []byte("\xFF\xFE\x00\x00"), ct: "text/plain; charset=utf-16le"},
-	&maskedSig{mask: []byte("\xFF\xFF\xFF\x00"), pat: []byte("\xEF\xBB\xBF\x00"), ct: "text/plain; charset=utf-8"},
-
-	&exactSig{[]byte("GIF87a"), "image/gif"},
-	&exactSig{[]byte("GIF89a"), "image/gif"},
-	&exactSig{[]byte("\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"), "image/png"},
-	&exactSig{[]byte("\xFF\xD8\xFF"), "image/jpeg"},
-	&exactSig{[]byte("BM"), "image/bmp"},
-	&maskedSig{
-		mask: []byte("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"),
-		pat:  []byte("RIFF\x00\x00\x00\x00WEBPVP"),
-		ct:   "image/webp",
-	},
-	&exactSig{[]byte("\x00\x00\x01\x00"), "image/vnd.microsoft.icon"},
-	&exactSig{[]byte("\x4F\x67\x67\x53\x00"), "application/ogg"},
-	&maskedSig{
-		mask: []byte("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF"),
-		pat:  []byte("RIFF\x00\x00\x00\x00WAVE"),
-		ct:   "audio/wave",
-	},
-	&exactSig{[]byte("\x1A\x45\xDF\xA3"), "video/webm"},
-	&exactSig{[]byte("\x52\x61\x72\x20\x1A\x07\x00"), "application/x-rar-compressed"},
-	&exactSig{[]byte("\x50\x4B\x03\x04"), "application/zip"},
-	&exactSig{[]byte("\x1F\x8B\x08"), "application/x-gzip"},
-
-	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
-	//mp4Sig(0),
-
-	textSig(0), // should be last
-}
-
-type exactSig struct {
-	sig []byte
-	ct  string
-}
-
-func (e *exactSig) match(data []byte, firstNonWS int) string {
-	if bytes.HasPrefix(data, e.sig) {
-		return e.ct
-	}
-	return ""
-}
-
-type maskedSig struct {
-	mask, pat []byte
-	skipWS    bool
-	ct        string
-}
-
-func (m *maskedSig) match(data []byte, firstNonWS int) string {
-	if m.skipWS {
-		data = data[firstNonWS:]
-	}
-	if len(data) < len(m.mask) {
-		return ""
-	}
-	for i, mask := range m.mask {
-		db := data[i] & mask
-		if db != m.pat[i] {
-			return ""
-		}
-	}
-	return m.ct
-}
-
-type htmlSig []byte
-
-func (h htmlSig) match(data []byte, firstNonWS int) string {
-	data = data[firstNonWS:]
-	if len(data) < len(h)+1 {
-		return ""
-	}
-	for i, b := range h {
-		db := data[i]
-		if 'A' <= b && b <= 'Z' {
-			db &= 0xDF
-		}
-		if b != db {
-			return ""
-		}
-	}
-	// Next byte must be space or right angle bracket.
-	if db := data[len(h)]; db != ' ' && db != '>' {
-		return ""
-	}
-	return "text/html; charset=utf-8"
-}
-
-type mp4Sig int
-
-func (mp4Sig) match(data []byte, firstNonWS int) string {
-	// c.f. section 6.1.
-	if len(data) < 8 {
-		return ""
-	}
-	boxSize := int(binary.BigEndian.Uint32(data[:4]))
-	if boxSize%4 != 0 || len(data) < boxSize {
-		return ""
-	}
-	if !bytes.Equal(data[4:8], []byte("ftyp")) {
-		return ""
-	}
-	for st := 8; st < boxSize; st += 4 {
-		if st == 12 {
-			// minor version number
-			continue
-		}
-		seg := string(data[st : st+3])
-		switch seg {
-		case "mp4", "iso", "M4V", "M4P", "M4B":
-			return "video/mp4"
-			/* The remainder are not in the spec.
-			case "M4A":
-				return "audio/mp4"
-			case "3gp":
-				return "video/3gpp"
-			case "jp2":
-				return "image/jp2" // JPEG 2000
-			*/
-		}
-	}
-	return ""
-}
-
-type textSig int
-
-func (textSig) match(data []byte, firstNonWS int) string {
-	// c.f. section 5, step 4.
-	for _, b := range data[firstNonWS:] {
-		switch {
-		case 0x00 <= b && b <= 0x08,
-			b == 0x0B,
-			0x0E <= b && b <= 0x1A,
-			0x1C <= b && b <= 0x1F:
-			return ""
-		}
-	}
-	return "text/plain; charset=utf-8"
-}
diff --git a/src/pkg/http/sniff_test.go b/src/pkg/http/sniff_test.go
deleted file mode 100644
index faf05e4..0000000
--- a/src/pkg/http/sniff_test.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2011 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 http_test
-
-import (
-	"bytes"
-	. "http"
-	"http/httptest"
-	"io/ioutil"
-	"log"
-	"strconv"
-	"testing"
-)
-
-var sniffTests = []struct {
-	desc        string
-	data        []byte
-	contentType string
-}{
-	// Some nonsense.
-	{"Empty", []byte{}, "text/plain; charset=utf-8"},
-	{"Binary", []byte{1, 2, 3}, "application/octet-stream"},
-
-	{"HTML document #1", []byte(`<HtMl><bOdY>blah blah blah</body></html>`), "text/html; charset=utf-8"},
-	{"HTML document #2", []byte(`<HTML></HTML>`), "text/html; charset=utf-8"},
-	{"HTML document #3 (leading whitespace)", []byte(`   <!DOCTYPE HTML>...`), "text/html; charset=utf-8"},
-
-	{"Plain text", []byte(`This is not HTML. It has ☃ though.`), "text/plain; charset=utf-8"},
-
-	{"XML", []byte("\n<?xml!"), "text/xml; charset=utf-8"},
-
-	// Image types.
-	{"GIF 87a", []byte(`GIF87a`), "image/gif"},
-	{"GIF 89a", []byte(`GIF89a...`), "image/gif"},
-
-	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
-	//{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
-	//{"MP4 audio", []byte("\x00\x00\x00\x20ftypM4A \x00\x00\x00\x00M4A mp42isom\x00\x00\x00\x00"), "audio/mp4"},
-}
-
-func TestDetectContentType(t *testing.T) {
-	for _, tt := range sniffTests {
-		ct := DetectContentType(tt.data)
-		if ct != tt.contentType {
-			t.Errorf("%v: DetectContentType = %q, want %q", tt.desc, ct, tt.contentType)
-		}
-	}
-}
-
-func TestServerContentType(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		i, _ := strconv.Atoi(r.FormValue("i"))
-		tt := sniffTests[i]
-		n, err := w.Write(tt.data)
-		if n != len(tt.data) || err != nil {
-			log.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt.desc, tt.data, n, err, len(tt.data))
-		}
-	}))
-	defer ts.Close()
-
-	for i, tt := range sniffTests {
-		resp, err := Get(ts.URL + "/?i=" + strconv.Itoa(i))
-		if err != nil {
-			t.Errorf("%v: %v", tt.desc, err)
-			continue
-		}
-		if ct := resp.Header.Get("Content-Type"); ct != tt.contentType {
-			t.Errorf("%v: Content-Type = %q, want %q", tt.desc, ct, tt.contentType)
-		}
-		data, err := ioutil.ReadAll(resp.Body)
-		if err != nil {
-			t.Errorf("%v: reading body: %v", tt.desc, err)
-		} else if !bytes.Equal(data, tt.data) {
-			t.Errorf("%v: data is %q, want %q", tt.desc, data, tt.data)
-		}
-		resp.Body.Close()
-	}
-}
diff --git a/src/pkg/http/spdy/Makefile b/src/pkg/http/spdy/Makefile
deleted file mode 100644
index 3bec220..0000000
--- a/src/pkg/http/spdy/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=http/spdy
-GOFILES=\
-	read.go\
-	types.go\
-	write.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/http/spdy/read.go b/src/pkg/http/spdy/read.go
deleted file mode 100644
index 2b1fd3d..0000000
--- a/src/pkg/http/spdy/read.go
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright 2011 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 spdy
-
-import (
-	"compress/zlib"
-	"encoding/binary"
-	"http"
-	"io"
-	"os"
-	"strings"
-)
-
-func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) os.Error {
-	return f.readSynStreamFrame(h, frame)
-}
-
-func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) os.Error {
-	return f.readSynReplyFrame(h, frame)
-}
-
-func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) os.Error {
-	frame.CFHeader = h
-	if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
-		return err
-	}
-	if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) os.Error {
-	frame.CFHeader = h
-	var numSettings uint32
-	if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
-		return err
-	}
-	frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
-	for i := uint32(0); i < numSettings; i++ {
-		if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
-			return err
-		}
-		frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
-		frame.FlagIdValues[i].Id &= 0xffffff
-		if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (frame *NoopFrame) read(h ControlFrameHeader, f *Framer) os.Error {
-	frame.CFHeader = h
-	return nil
-}
-
-func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) os.Error {
-	frame.CFHeader = h
-	if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) os.Error {
-	frame.CFHeader = h
-	if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) os.Error {
-	return f.readHeadersFrame(h, frame)
-}
-
-func newControlFrame(frameType ControlFrameType) (controlFrame, os.Error) {
-	ctor, ok := cframeCtor[frameType]
-	if !ok {
-		return nil, &Error{Err: InvalidControlFrame}
-	}
-	return ctor(), nil
-}
-
-var cframeCtor = map[ControlFrameType]func() controlFrame{
-	TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
-	TypeSynReply:  func() controlFrame { return new(SynReplyFrame) },
-	TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
-	TypeSettings:  func() controlFrame { return new(SettingsFrame) },
-	TypeNoop:      func() controlFrame { return new(NoopFrame) },
-	TypePing:      func() controlFrame { return new(PingFrame) },
-	TypeGoAway:    func() controlFrame { return new(GoAwayFrame) },
-	TypeHeaders:   func() controlFrame { return new(HeadersFrame) },
-	// TODO(willchan): Add TypeWindowUpdate
-}
-
-func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) os.Error {
-	if f.headerDecompressor != nil {
-		f.headerReader.N = payloadSize
-		return nil
-	}
-	f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
-	decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(HeaderDictionary))
-	if err != nil {
-		return err
-	}
-	f.headerDecompressor = decompressor
-	return nil
-}
-
-// ReadFrame reads SPDY encoded data and returns a decompressed Frame.
-func (f *Framer) ReadFrame() (Frame, os.Error) {
-	var firstWord uint32
-	if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
-		return nil, err
-	}
-	if (firstWord & 0x80000000) != 0 {
-		frameType := ControlFrameType(firstWord & 0xffff)
-		version := uint16(0x7fff & (firstWord >> 16))
-		return f.parseControlFrame(version, frameType)
-	}
-	return f.parseDataFrame(firstWord & 0x7fffffff)
-}
-
-func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, os.Error) {
-	var length uint32
-	if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
-		return nil, err
-	}
-	flags := ControlFlags((length & 0xff000000) >> 24)
-	length &= 0xffffff
-	header := ControlFrameHeader{version, frameType, flags, length}
-	cframe, err := newControlFrame(frameType)
-	if err != nil {
-		return nil, err
-	}
-	if err = cframe.read(header, f); err != nil {
-		return nil, err
-	}
-	return cframe, nil
-}
-
-func parseHeaderValueBlock(r io.Reader, streamId uint32) (http.Header, os.Error) {
-	var numHeaders uint16
-	if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
-		return nil, err
-	}
-	var e os.Error
-	h := make(http.Header, int(numHeaders))
-	for i := 0; i < int(numHeaders); i++ {
-		var length uint16
-		if err := binary.Read(r, binary.BigEndian, &length); err != nil {
-			return nil, err
-		}
-		nameBytes := make([]byte, length)
-		if _, err := io.ReadFull(r, nameBytes); err != nil {
-			return nil, err
-		}
-		name := string(nameBytes)
-		if name != strings.ToLower(name) {
-			e = &Error{UnlowercasedHeaderName, streamId}
-			name = strings.ToLower(name)
-		}
-		if h[name] != nil {
-			e = &Error{DuplicateHeaders, streamId}
-		}
-		if err := binary.Read(r, binary.BigEndian, &length); err != nil {
-			return nil, err
-		}
-		value := make([]byte, length)
-		if _, err := io.ReadFull(r, value); err != nil {
-			return nil, err
-		}
-		valueList := strings.Split(string(value), "\x00")
-		for _, v := range valueList {
-			h.Add(name, v)
-		}
-	}
-	if e != nil {
-		return h, e
-	}
-	return h, nil
-}
-
-func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) os.Error {
-	frame.CFHeader = h
-	var err os.Error
-	if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
-		return err
-	}
-	if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
-		return err
-	}
-	if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
-		return err
-	}
-	frame.Priority >>= 14
-
-	reader := f.r
-	if !f.headerCompressionDisabled {
-		f.uncorkHeaderDecompressor(int64(h.length - 10))
-		reader = f.headerDecompressor
-	}
-
-	frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
-	if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
-		err = &Error{WrongCompressedPayloadSize, 0}
-	}
-	if err != nil {
-		return err
-	}
-	// Remove this condition when we bump Version to 3.
-	if Version >= 3 {
-		for h := range frame.Headers {
-			if invalidReqHeaders[h] {
-				return &Error{InvalidHeaderPresent, frame.StreamId}
-			}
-		}
-	}
-	return nil
-}
-
-func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) os.Error {
-	frame.CFHeader = h
-	var err os.Error
-	if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
-		return err
-	}
-	var unused uint16
-	if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
-		return err
-	}
-	reader := f.r
-	if !f.headerCompressionDisabled {
-		f.uncorkHeaderDecompressor(int64(h.length - 6))
-		reader = f.headerDecompressor
-	}
-	frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
-	if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
-		err = &Error{WrongCompressedPayloadSize, 0}
-	}
-	if err != nil {
-		return err
-	}
-	// Remove this condition when we bump Version to 3.
-	if Version >= 3 {
-		for h := range frame.Headers {
-			if invalidRespHeaders[h] {
-				return &Error{InvalidHeaderPresent, frame.StreamId}
-			}
-		}
-	}
-	return nil
-}
-
-func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) os.Error {
-	frame.CFHeader = h
-	var err os.Error
-	if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
-		return err
-	}
-	var unused uint16
-	if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
-		return err
-	}
-	reader := f.r
-	if !f.headerCompressionDisabled {
-		f.uncorkHeaderDecompressor(int64(h.length - 6))
-		reader = f.headerDecompressor
-	}
-	frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
-	if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
-		err = &Error{WrongCompressedPayloadSize, 0}
-	}
-	if err != nil {
-		return err
-	}
-
-	// Remove this condition when we bump Version to 3.
-	if Version >= 3 {
-		var invalidHeaders map[string]bool
-		if frame.StreamId%2 == 0 {
-			invalidHeaders = invalidReqHeaders
-		} else {
-			invalidHeaders = invalidRespHeaders
-		}
-		for h := range frame.Headers {
-			if invalidHeaders[h] {
-				return &Error{InvalidHeaderPresent, frame.StreamId}
-			}
-		}
-	}
-	return nil
-}
-
-func (f *Framer) parseDataFrame(streamId uint32) (*DataFrame, os.Error) {
-	var length uint32
-	if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
-		return nil, err
-	}
-	var frame DataFrame
-	frame.StreamId = streamId
-	frame.Flags = DataFlags(length >> 24)
-	length &= 0xffffff
-	frame.Data = make([]byte, length)
-	if _, err := io.ReadFull(f.r, frame.Data); err != nil {
-		return nil, err
-	}
-	return &frame, nil
-}
diff --git a/src/pkg/http/spdy/spdy_test.go b/src/pkg/http/spdy/spdy_test.go
deleted file mode 100644
index cb91e02..0000000
--- a/src/pkg/http/spdy/spdy_test.go
+++ /dev/null
@@ -1,497 +0,0 @@
-// Copyright 2011 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 spdy
-
-import (
-	"bytes"
-	"http"
-	"io"
-	"reflect"
-	"testing"
-)
-
-func TestHeaderParsing(t *testing.T) {
-	headers := http.Header{
-		"Url":     []string{"http://www.google.com/"},
-		"Method":  []string{"get"},
-		"Version": []string{"http/1.1"},
-	}
-	var headerValueBlockBuf bytes.Buffer
-	writeHeaderValueBlock(&headerValueBlockBuf, headers)
-
-	const bogusStreamId = 1
-	newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf, bogusStreamId)
-	if err != nil {
-		t.Fatal("parseHeaderValueBlock:", err)
-	}
-
-	if !reflect.DeepEqual(headers, newHeaders) {
-		t.Fatal("got: ", newHeaders, "\nwant: ", headers)
-	}
-}
-
-func TestCreateParseSynStreamFrame(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer := &Framer{
-		headerCompressionDisabled: true,
-		w:                         buffer,
-		headerBuf:                 new(bytes.Buffer),
-		r:                         buffer,
-	}
-	synStreamFrame := SynStreamFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeSynStream,
-		},
-		Headers: http.Header{
-			"Url":     []string{"http://www.google.com/"},
-			"Method":  []string{"get"},
-			"Version": []string{"http/1.1"},
-		},
-	}
-	if err := framer.WriteFrame(&synStreamFrame); err != nil {
-		t.Fatal("WriteFrame without compression:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame without compression:", err)
-	}
-	parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
-		t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
-	}
-
-	// Test again with compression
-	buffer.Reset()
-	framer, err = NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	if err := framer.WriteFrame(&synStreamFrame); err != nil {
-		t.Fatal("WriteFrame with compression:", err)
-	}
-	frame, err = framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame with compression:", err)
-	}
-	parsedSynStreamFrame, ok = frame.(*SynStreamFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
-		t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
-	}
-}
-
-func TestCreateParseSynReplyFrame(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer := &Framer{
-		headerCompressionDisabled: true,
-		w:                         buffer,
-		headerBuf:                 new(bytes.Buffer),
-		r:                         buffer,
-	}
-	synReplyFrame := SynReplyFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeSynReply,
-		},
-		Headers: http.Header{
-			"Url":     []string{"http://www.google.com/"},
-			"Method":  []string{"get"},
-			"Version": []string{"http/1.1"},
-		},
-	}
-	if err := framer.WriteFrame(&synReplyFrame); err != nil {
-		t.Fatal("WriteFrame without compression:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame without compression:", err)
-	}
-	parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
-		t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
-	}
-
-	// Test again with compression
-	buffer.Reset()
-	framer, err = NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	if err := framer.WriteFrame(&synReplyFrame); err != nil {
-		t.Fatal("WriteFrame with compression:", err)
-	}
-	frame, err = framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame with compression:", err)
-	}
-	parsedSynReplyFrame, ok = frame.(*SynReplyFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
-		t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
-	}
-}
-
-func TestCreateParseRstStream(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer, err := NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	rstStreamFrame := RstStreamFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeRstStream,
-		},
-		StreamId: 1,
-		Status:   InvalidStream,
-	}
-	if err := framer.WriteFrame(&rstStreamFrame); err != nil {
-		t.Fatal("WriteFrame:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame:", err)
-	}
-	parsedRstStreamFrame, ok := frame.(*RstStreamFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) {
-		t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame)
-	}
-}
-
-func TestCreateParseSettings(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer, err := NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	settingsFrame := SettingsFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeSettings,
-		},
-		FlagIdValues: []SettingsFlagIdValue{
-			{FlagSettingsPersistValue, SettingsCurrentCwnd, 10},
-			{FlagSettingsPersisted, SettingsUploadBandwidth, 1},
-		},
-	}
-	if err := framer.WriteFrame(&settingsFrame); err != nil {
-		t.Fatal("WriteFrame:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame:", err)
-	}
-	parsedSettingsFrame, ok := frame.(*SettingsFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) {
-		t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame)
-	}
-}
-
-func TestCreateParseNoop(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer, err := NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	noopFrame := NoopFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeNoop,
-		},
-	}
-	if err := framer.WriteFrame(&noopFrame); err != nil {
-		t.Fatal("WriteFrame:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame:", err)
-	}
-	parsedNoopFrame, ok := frame.(*NoopFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(noopFrame, *parsedNoopFrame) {
-		t.Fatal("got: ", *parsedNoopFrame, "\nwant: ", noopFrame)
-	}
-}
-
-func TestCreateParsePing(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer, err := NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	pingFrame := PingFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypePing,
-		},
-		Id: 31337,
-	}
-	if err := framer.WriteFrame(&pingFrame); err != nil {
-		t.Fatal("WriteFrame:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame:", err)
-	}
-	parsedPingFrame, ok := frame.(*PingFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(pingFrame, *parsedPingFrame) {
-		t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame)
-	}
-}
-
-func TestCreateParseGoAway(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer, err := NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	goAwayFrame := GoAwayFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeGoAway,
-		},
-		LastGoodStreamId: 31337,
-	}
-	if err := framer.WriteFrame(&goAwayFrame); err != nil {
-		t.Fatal("WriteFrame:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame:", err)
-	}
-	parsedGoAwayFrame, ok := frame.(*GoAwayFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) {
-		t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame)
-	}
-}
-
-func TestCreateParseHeadersFrame(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer := &Framer{
-		headerCompressionDisabled: true,
-		w:                         buffer,
-		headerBuf:                 new(bytes.Buffer),
-		r:                         buffer,
-	}
-	headersFrame := HeadersFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeHeaders,
-		},
-	}
-	headersFrame.Headers = http.Header{
-		"Url":     []string{"http://www.google.com/"},
-		"Method":  []string{"get"},
-		"Version": []string{"http/1.1"},
-	}
-	if err := framer.WriteFrame(&headersFrame); err != nil {
-		t.Fatal("WriteFrame without compression:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame without compression:", err)
-	}
-	parsedHeadersFrame, ok := frame.(*HeadersFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
-		t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
-	}
-
-	// Test again with compression
-	buffer.Reset()
-	framer, err = NewFramer(buffer, buffer)
-	if err := framer.WriteFrame(&headersFrame); err != nil {
-		t.Fatal("WriteFrame with compression:", err)
-	}
-	frame, err = framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame with compression:", err)
-	}
-	parsedHeadersFrame, ok = frame.(*HeadersFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
-		t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
-	}
-}
-
-func TestCreateParseDataFrame(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer, err := NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	dataFrame := DataFrame{
-		StreamId: 1,
-		Data:     []byte{'h', 'e', 'l', 'l', 'o'},
-	}
-	if err := framer.WriteFrame(&dataFrame); err != nil {
-		t.Fatal("WriteFrame:", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame:", err)
-	}
-	parsedDataFrame, ok := frame.(*DataFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(dataFrame, *parsedDataFrame) {
-		t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame)
-	}
-}
-
-func TestCompressionContextAcrossFrames(t *testing.T) {
-	buffer := new(bytes.Buffer)
-	framer, err := NewFramer(buffer, buffer)
-	if err != nil {
-		t.Fatal("Failed to create new framer:", err)
-	}
-	headersFrame := HeadersFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeHeaders,
-		},
-		Headers: http.Header{
-			"Url":     []string{"http://www.google.com/"},
-			"Method":  []string{"get"},
-			"Version": []string{"http/1.1"},
-		},
-	}
-	if err := framer.WriteFrame(&headersFrame); err != nil {
-		t.Fatal("WriteFrame (HEADERS):", err)
-	}
-	synStreamFrame := SynStreamFrame{ControlFrameHeader{Version, TypeSynStream, 0, 0}, 0, 0, 0, nil}
-	synStreamFrame.Headers = http.Header{
-		"Url":     []string{"http://www.google.com/"},
-		"Method":  []string{"get"},
-		"Version": []string{"http/1.1"},
-	}
-	if err := framer.WriteFrame(&synStreamFrame); err != nil {
-		t.Fatal("WriteFrame (SYN_STREAM):", err)
-	}
-	frame, err := framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes())
-	}
-	parsedHeadersFrame, ok := frame.(*HeadersFrame)
-	if !ok {
-		t.Fatalf("expected HeadersFrame; got %T %v", frame, frame)
-	}
-	if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
-		t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
-	}
-	frame, err = framer.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes())
-	}
-	parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
-	if !ok {
-		t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame)
-	}
-	if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
-		t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
-	}
-}
-
-func TestMultipleSPDYFrames(t *testing.T) {
-	// Initialize the framers.
-	pr1, pw1 := io.Pipe()
-	pr2, pw2 := io.Pipe()
-	writer, err := NewFramer(pw1, pr2)
-	if err != nil {
-		t.Fatal("Failed to create writer:", err)
-	}
-	reader, err := NewFramer(pw2, pr1)
-	if err != nil {
-		t.Fatal("Failed to create reader:", err)
-	}
-
-	// Set up the frames we're actually transferring.
-	headersFrame := HeadersFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeHeaders,
-		},
-		Headers: http.Header{
-			"Url":     []string{"http://www.google.com/"},
-			"Method":  []string{"get"},
-			"Version": []string{"http/1.1"},
-		},
-	}
-	synStreamFrame := SynStreamFrame{
-		CFHeader: ControlFrameHeader{
-			version:   Version,
-			frameType: TypeSynStream,
-		},
-		Headers: http.Header{
-			"Url":     []string{"http://www.google.com/"},
-			"Method":  []string{"get"},
-			"Version": []string{"http/1.1"},
-		},
-	}
-
-	// Start the goroutines to write the frames.
-	go func() {
-		if err := writer.WriteFrame(&headersFrame); err != nil {
-			t.Fatal("WriteFrame (HEADERS): ", err)
-		}
-		if err := writer.WriteFrame(&synStreamFrame); err != nil {
-			t.Fatal("WriteFrame (SYN_STREAM): ", err)
-		}
-	}()
-
-	// Read the frames and verify they look as expected.
-	frame, err := reader.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame (HEADERS): ", err)
-	}
-	parsedHeadersFrame, ok := frame.(*HeadersFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type:", frame)
-	}
-	if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
-		t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
-	}
-	frame, err = reader.ReadFrame()
-	if err != nil {
-		t.Fatal("ReadFrame (SYN_STREAM):", err)
-	}
-	parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
-	if !ok {
-		t.Fatal("Parsed incorrect frame type.")
-	}
-	if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
-		t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
-	}
-}
diff --git a/src/pkg/http/spdy/types.go b/src/pkg/http/spdy/types.go
deleted file mode 100644
index 41cafb1..0000000
--- a/src/pkg/http/spdy/types.go
+++ /dev/null
@@ -1,370 +0,0 @@
-// Copyright 2011 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 spdy
-
-import (
-	"bytes"
-	"compress/zlib"
-	"http"
-	"io"
-	"os"
-)
-
-//  Data Frame Format
-//  +----------------------------------+
-//  |0|       Stream-ID (31bits)       |
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |
-//  +----------------------------------+
-//  |               Data               |
-//  +----------------------------------+
-//
-//  Control Frame Format
-//  +----------------------------------+
-//  |1| Version(15bits) | Type(16bits) |
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |
-//  +----------------------------------+
-//  |               Data               |
-//  +----------------------------------+
-//
-//  Control Frame: SYN_STREAM
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000001|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |  >= 12
-//  +----------------------------------+
-//  |X|       Stream-ID(31bits)        |
-//  +----------------------------------+
-//  |X|Associated-To-Stream-ID (31bits)|
-//  +----------------------------------+
-//  |Pri| unused      | Length (16bits)|
-//  +----------------------------------+
-//
-//  Control Frame: SYN_REPLY
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000010|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |  >= 8
-//  +----------------------------------+
-//  |X|       Stream-ID(31bits)        |
-//  +----------------------------------+
-//  | unused (16 bits)| Length (16bits)|
-//  +----------------------------------+
-//
-//  Control Frame: RST_STREAM
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000011|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |  >= 4
-//  +----------------------------------+
-//  |X|       Stream-ID(31bits)        |
-//  +----------------------------------+
-//  |        Status code (32 bits)     |
-//  +----------------------------------+
-//
-//  Control Frame: SETTINGS
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000100|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |
-//  +----------------------------------+
-//  |        # of entries (32)         |
-//  +----------------------------------+
-//
-//  Control Frame: NOOP
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000101|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | = 0
-//  +----------------------------------+
-//
-//  Control Frame: PING
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000110|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | = 4
-//  +----------------------------------+
-//  |        Unique id (32 bits)       |
-//  +----------------------------------+
-//
-//  Control Frame: GOAWAY
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000111|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | = 4
-//  +----------------------------------+
-//  |X|  Last-accepted-stream-id       |
-//  +----------------------------------+
-//
-//  Control Frame: HEADERS
-//  +----------------------------------+
-//  |1|000000000000001|0000000000001000|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | >= 8
-//  +----------------------------------+
-//  |X|      Stream-ID (31 bits)       |
-//  +----------------------------------+
-//  | unused (16 bits)| Length (16bits)|
-//  +----------------------------------+
-//
-//  Control Frame: WINDOW_UPDATE
-//  +----------------------------------+
-//  |1|000000000000001|0000000000001001|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | = 8
-//  +----------------------------------+
-//  |X|      Stream-ID (31 bits)       |
-//  +----------------------------------+
-//  |   Delta-Window-Size (32 bits)    |
-//  +----------------------------------+
-
-// Version is the protocol version number that this package implements.
-const Version = 2
-
-// ControlFrameType stores the type field in a control frame header.
-type ControlFrameType uint16
-
-// Control frame type constants
-const (
-	TypeSynStream    ControlFrameType = 0x0001
-	TypeSynReply                      = 0x0002
-	TypeRstStream                     = 0x0003
-	TypeSettings                      = 0x0004
-	TypeNoop                          = 0x0005
-	TypePing                          = 0x0006
-	TypeGoAway                        = 0x0007
-	TypeHeaders                       = 0x0008
-	TypeWindowUpdate                  = 0x0009
-)
-
-// ControlFlags are the flags that can be set on a control frame.
-type ControlFlags uint8
-
-const (
-	ControlFlagFin ControlFlags = 0x01
-)
-
-// DataFlags are the flags that can be set on a data frame.
-type DataFlags uint8
-
-const (
-	DataFlagFin        DataFlags = 0x01
-	DataFlagCompressed           = 0x02
-)
-
-// MaxDataLength is the maximum number of bytes that can be stored in one frame.
-const MaxDataLength = 1<<24 - 1
-
-// Frame is a single SPDY frame in its unpacked in-memory representation. Use
-// Framer to read and write it.
-type Frame interface {
-	write(f *Framer) os.Error
-}
-
-// ControlFrameHeader contains all the fields in a control frame header,
-// in its unpacked in-memory representation.
-type ControlFrameHeader struct {
-	// Note, high bit is the "Control" bit.
-	version   uint16
-	frameType ControlFrameType
-	Flags     ControlFlags
-	length    uint32
-}
-
-type controlFrame interface {
-	Frame
-	read(h ControlFrameHeader, f *Framer) os.Error
-}
-
-// SynStreamFrame is the unpacked, in-memory representation of a SYN_STREAM
-// frame.
-type SynStreamFrame struct {
-	CFHeader             ControlFrameHeader
-	StreamId             uint32
-	AssociatedToStreamId uint32
-	// Note, only 2 highest bits currently used
-	// Rest of Priority is unused.
-	Priority uint16
-	Headers  http.Header
-}
-
-// SynReplyFrame is the unpacked, in-memory representation of a SYN_REPLY frame.
-type SynReplyFrame struct {
-	CFHeader ControlFrameHeader
-	StreamId uint32
-	Headers  http.Header
-}
-
-// StatusCode represents the status that led to a RST_STREAM
-type StatusCode uint32
-
-const (
-	ProtocolError      StatusCode = 1
-	InvalidStream                 = 2
-	RefusedStream                 = 3
-	UnsupportedVersion            = 4
-	Cancel                        = 5
-	InternalError                 = 6
-	FlowControlError              = 7
-)
-
-// RstStreamFrame is the unpacked, in-memory representation of a RST_STREAM
-// frame.
-type RstStreamFrame struct {
-	CFHeader ControlFrameHeader
-	StreamId uint32
-	Status   StatusCode
-}
-
-// SettingsFlag represents a flag in a SETTINGS frame.
-type SettingsFlag uint8
-
-const (
-	FlagSettingsPersistValue SettingsFlag = 0x1
-	FlagSettingsPersisted                 = 0x2
-)
-
-// SettingsFlag represents the id of an id/value pair in a SETTINGS frame.
-type SettingsId uint32
-
-const (
-	SettingsUploadBandwidth      SettingsId = 1
-	SettingsDownloadBandwidth               = 2
-	SettingsRoundTripTime                   = 3
-	SettingsMaxConcurrentStreams            = 4
-	SettingsCurrentCwnd                     = 5
-)
-
-// SettingsFlagIdValue is the unpacked, in-memory representation of the
-// combined flag/id/value for a setting in a SETTINGS frame.
-type SettingsFlagIdValue struct {
-	Flag  SettingsFlag
-	Id    SettingsId
-	Value uint32
-}
-
-// SettingsFrame is the unpacked, in-memory representation of a SPDY
-// SETTINGS frame.
-type SettingsFrame struct {
-	CFHeader     ControlFrameHeader
-	FlagIdValues []SettingsFlagIdValue
-}
-
-// NoopFrame is the unpacked, in-memory representation of a NOOP frame.
-type NoopFrame struct {
-	CFHeader ControlFrameHeader
-}
-
-// PingFrame is the unpacked, in-memory representation of a PING frame.
-type PingFrame struct {
-	CFHeader ControlFrameHeader
-	Id       uint32
-}
-
-// GoAwayFrame is the unpacked, in-memory representation of a GOAWAY frame.
-type GoAwayFrame struct {
-	CFHeader         ControlFrameHeader
-	LastGoodStreamId uint32
-}
-
-// HeadersFrame is the unpacked, in-memory representation of a HEADERS frame.
-type HeadersFrame struct {
-	CFHeader ControlFrameHeader
-	StreamId uint32
-	Headers  http.Header
-}
-
-// DataFrame is the unpacked, in-memory representation of a DATA frame.
-type DataFrame struct {
-	// Note, high bit is the "Control" bit. Should be 0 for data frames.
-	StreamId uint32
-	Flags    DataFlags
-	Data     []byte
-}
-
-// HeaderDictionary is the dictionary sent to the zlib compressor/decompressor.
-// Even though the specification states there is no null byte at the end, Chrome sends it.
-const HeaderDictionary = "optionsgetheadpostputdeletetrace" +
-	"acceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhost" +
-	"if-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsince" +
-	"max-forwardsproxy-authorizationrangerefererteuser-agent" +
-	"100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505" +
-	"accept-rangesageetaglocationproxy-authenticatepublicretry-after" +
-	"servervarywarningwww-authenticateallowcontent-basecontent-encodingcache-control" +
-	"connectiondatetrailertransfer-encodingupgradeviawarning" +
-	"content-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookie" +
-	"MondayTuesdayWednesdayThursdayFridaySaturdaySunday" +
-	"JanFebMarAprMayJunJulAugSepOctNovDec" +
-	"chunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-age" +
-	"charset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl\x00"
-
-// A SPDY specific error.
-type ErrorCode string
-
-const (
-	UnlowercasedHeaderName     ErrorCode = "header was not lowercased"
-	DuplicateHeaders           ErrorCode = "multiple headers with same name"
-	WrongCompressedPayloadSize ErrorCode = "compressed payload size was incorrect"
-	UnknownFrameType           ErrorCode = "unknown frame type"
-	InvalidControlFrame        ErrorCode = "invalid control frame"
-	InvalidDataFrame           ErrorCode = "invalid data frame"
-	InvalidHeaderPresent       ErrorCode = "frame contained invalid header"
-)
-
-// Error contains both the type of error and additional values. StreamId is 0
-// if Error is not associated with a stream.
-type Error struct {
-	Err      ErrorCode
-	StreamId uint32
-}
-
-func (e *Error) String() string {
-	return string(e.Err)
-}
-
-var invalidReqHeaders = map[string]bool{
-	"Connection":        true,
-	"Keep-Alive":        true,
-	"Proxy-Connection":  true,
-	"Transfer-Encoding": true,
-}
-
-var invalidRespHeaders = map[string]bool{
-	"Connection":        true,
-	"Keep-Alive":        true,
-	"Transfer-Encoding": true,
-}
-
-// Framer handles serializing/deserializing SPDY frames, including compressing/
-// decompressing payloads.
-type Framer struct {
-	headerCompressionDisabled bool
-	w                         io.Writer
-	headerBuf                 *bytes.Buffer
-	headerCompressor          *zlib.Writer
-	r                         io.Reader
-	headerReader              io.LimitedReader
-	headerDecompressor        io.ReadCloser
-}
-
-// NewFramer allocates a new Framer for a given SPDY connection, repesented by
-// a io.Writer and io.Reader. Note that Framer will read and write individual fields 
-// from/to the Reader and Writer, so the caller should pass in an appropriately 
-// buffered implementation to optimize performance.
-func NewFramer(w io.Writer, r io.Reader) (*Framer, os.Error) {
-	compressBuf := new(bytes.Buffer)
-	compressor, err := zlib.NewWriterDict(compressBuf, zlib.BestCompression, []byte(HeaderDictionary))
-	if err != nil {
-		return nil, err
-	}
-	framer := &Framer{
-		w:                w,
-		headerBuf:        compressBuf,
-		headerCompressor: compressor,
-		r:                r,
-	}
-	return framer, nil
-}
diff --git a/src/pkg/http/spdy/write.go b/src/pkg/http/spdy/write.go
deleted file mode 100644
index 7d40bbe..0000000
--- a/src/pkg/http/spdy/write.go
+++ /dev/null
@@ -1,286 +0,0 @@
-// Copyright 2011 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 spdy
-
-import (
-	"encoding/binary"
-	"http"
-	"io"
-	"os"
-	"strings"
-)
-
-func (frame *SynStreamFrame) write(f *Framer) os.Error {
-	return f.writeSynStreamFrame(frame)
-}
-
-func (frame *SynReplyFrame) write(f *Framer) os.Error {
-	return f.writeSynReplyFrame(frame)
-}
-
-func (frame *RstStreamFrame) write(f *Framer) (err os.Error) {
-	frame.CFHeader.version = Version
-	frame.CFHeader.frameType = TypeRstStream
-	frame.CFHeader.length = 8
-
-	// Serialize frame to Writer
-	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
-		return
-	}
-	return
-}
-
-func (frame *SettingsFrame) write(f *Framer) (err os.Error) {
-	frame.CFHeader.version = Version
-	frame.CFHeader.frameType = TypeSettings
-	frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
-
-	// Serialize frame to Writer
-	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
-		return
-	}
-	for _, flagIdValue := range frame.FlagIdValues {
-		flagId := (uint32(flagIdValue.Flag) << 24) | uint32(flagIdValue.Id)
-		if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
-			return
-		}
-		if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
-			return
-		}
-	}
-	return
-}
-
-func (frame *NoopFrame) write(f *Framer) os.Error {
-	frame.CFHeader.version = Version
-	frame.CFHeader.frameType = TypeNoop
-
-	// Serialize frame to Writer
-	return writeControlFrameHeader(f.w, frame.CFHeader)
-}
-
-func (frame *PingFrame) write(f *Framer) (err os.Error) {
-	frame.CFHeader.version = Version
-	frame.CFHeader.frameType = TypePing
-	frame.CFHeader.length = 4
-
-	// Serialize frame to Writer
-	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
-		return
-	}
-	return
-}
-
-func (frame *GoAwayFrame) write(f *Framer) (err os.Error) {
-	frame.CFHeader.version = Version
-	frame.CFHeader.frameType = TypeGoAway
-	frame.CFHeader.length = 4
-
-	// Serialize frame to Writer
-	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
-		return
-	}
-	return nil
-}
-
-func (frame *HeadersFrame) write(f *Framer) os.Error {
-	return f.writeHeadersFrame(frame)
-}
-
-func (frame *DataFrame) write(f *Framer) os.Error {
-	return f.writeDataFrame(frame)
-}
-
-// WriteFrame writes a frame.
-func (f *Framer) WriteFrame(frame Frame) os.Error {
-	return frame.write(f)
-}
-
-func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) os.Error {
-	if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
-		return err
-	}
-	if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
-		return err
-	}
-	flagsAndLength := (uint32(h.Flags) << 24) | h.length
-	if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
-		return err
-	}
-	return nil
-}
-
-func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err os.Error) {
-	n = 0
-	if err = binary.Write(w, binary.BigEndian, uint16(len(h))); err != nil {
-		return
-	}
-	n += 2
-	for name, values := range h {
-		if err = binary.Write(w, binary.BigEndian, uint16(len(name))); err != nil {
-			return
-		}
-		n += 2
-		name = strings.ToLower(name)
-		if _, err = io.WriteString(w, name); err != nil {
-			return
-		}
-		n += len(name)
-		v := strings.Join(values, "\x00")
-		if err = binary.Write(w, binary.BigEndian, uint16(len(v))); err != nil {
-			return
-		}
-		n += 2
-		if _, err = io.WriteString(w, v); err != nil {
-			return
-		}
-		n += len(v)
-	}
-	return
-}
-
-func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err os.Error) {
-	// Marshal the headers.
-	var writer io.Writer = f.headerBuf
-	if !f.headerCompressionDisabled {
-		writer = f.headerCompressor
-	}
-	if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
-		return
-	}
-	if !f.headerCompressionDisabled {
-		f.headerCompressor.Flush()
-	}
-
-	// Set ControlFrameHeader
-	frame.CFHeader.version = Version
-	frame.CFHeader.frameType = TypeSynStream
-	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
-
-	// Serialize frame to Writer
-	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-		return err
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-		return err
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
-		return err
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<14); err != nil {
-		return err
-	}
-	if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
-		return err
-	}
-	f.headerBuf.Reset()
-	return nil
-}
-
-func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err os.Error) {
-	// Marshal the headers.
-	var writer io.Writer = f.headerBuf
-	if !f.headerCompressionDisabled {
-		writer = f.headerCompressor
-	}
-	if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
-		return
-	}
-	if !f.headerCompressionDisabled {
-		f.headerCompressor.Flush()
-	}
-
-	// Set ControlFrameHeader
-	frame.CFHeader.version = Version
-	frame.CFHeader.frameType = TypeSynReply
-	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6)
-
-	// Serialize frame to Writer
-	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil {
-		return
-	}
-	if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
-		return
-	}
-	f.headerBuf.Reset()
-	return
-}
-
-func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err os.Error) {
-	// Marshal the headers.
-	var writer io.Writer = f.headerBuf
-	if !f.headerCompressionDisabled {
-		writer = f.headerCompressor
-	}
-	if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
-		return
-	}
-	if !f.headerCompressionDisabled {
-		f.headerCompressor.Flush()
-	}
-
-	// Set ControlFrameHeader
-	frame.CFHeader.version = Version
-	frame.CFHeader.frameType = TypeHeaders
-	frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6)
-
-	// Serialize frame to Writer
-	if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-		return
-	}
-	if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil {
-		return
-	}
-	if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
-		return
-	}
-	f.headerBuf.Reset()
-	return
-}
-
-func (f *Framer) writeDataFrame(frame *DataFrame) (err os.Error) {
-	// Validate DataFrame
-	if frame.StreamId&0x80000000 != 0 || len(frame.Data) >= 0x0f000000 {
-		return &Error{InvalidDataFrame, frame.StreamId}
-	}
-
-	// Serialize frame to Writer
-	if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-		return
-	}
-	flagsAndLength := (uint32(frame.Flags) << 24) | uint32(len(frame.Data))
-	if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
-		return
-	}
-	if _, err = f.w.Write(frame.Data); err != nil {
-		return
-	}
-
-	return nil
-}
diff --git a/src/pkg/http/transfer.go b/src/pkg/http/transfer.go
deleted file mode 100644
index 300c7a8..0000000
--- a/src/pkg/http/transfer.go
+++ /dev/null
@@ -1,571 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http
-
-import (
-	"bytes"
-	"bufio"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"os"
-	"strconv"
-	"strings"
-)
-
-// transferWriter inspects the fields of a user-supplied Request or Response,
-// sanitizes them without changing the user object and provides methods for
-// writing the respective header, body and trailer in wire format.
-type transferWriter struct {
-	Method           string
-	Body             io.Reader
-	BodyCloser       io.Closer
-	ResponseToHEAD   bool
-	ContentLength    int64 // -1 means unknown, 0 means exactly none
-	Close            bool
-	TransferEncoding []string
-	Trailer          Header
-}
-
-func newTransferWriter(r interface{}) (t *transferWriter, err os.Error) {
-	t = &transferWriter{}
-
-	// Extract relevant fields
-	atLeastHTTP11 := false
-	switch rr := r.(type) {
-	case *Request:
-		if rr.ContentLength != 0 && rr.Body == nil {
-			return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
-		}
-		t.Method = rr.Method
-		t.Body = rr.Body
-		t.BodyCloser = rr.Body
-		t.ContentLength = rr.ContentLength
-		t.Close = rr.Close
-		t.TransferEncoding = rr.TransferEncoding
-		t.Trailer = rr.Trailer
-		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
-		if t.Body != nil && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
-			if t.ContentLength == 0 {
-				// Test to see if it's actually zero or just unset.
-				var buf [1]byte
-				n, _ := io.ReadFull(t.Body, buf[:])
-				if n == 1 {
-					// Oh, guess there is data in this Body Reader after all.
-					// The ContentLength field just wasn't set.
-					// Stich the Body back together again, re-attaching our
-					// consumed byte.
-					t.ContentLength = -1
-					t.Body = io.MultiReader(bytes.NewBuffer(buf[:]), t.Body)
-				} else {
-					// Body is actually empty.
-					t.Body = nil
-					t.BodyCloser = nil
-				}
-			}
-			if t.ContentLength < 0 {
-				t.TransferEncoding = []string{"chunked"}
-			}
-		}
-	case *Response:
-		t.Method = rr.Request.Method
-		t.Body = rr.Body
-		t.BodyCloser = rr.Body
-		t.ContentLength = rr.ContentLength
-		t.Close = rr.Close
-		t.TransferEncoding = rr.TransferEncoding
-		t.Trailer = rr.Trailer
-		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
-		t.ResponseToHEAD = noBodyExpected(rr.Request.Method)
-	}
-
-	// Sanitize Body,ContentLength,TransferEncoding
-	if t.ResponseToHEAD {
-		t.Body = nil
-		t.TransferEncoding = nil
-		// ContentLength is expected to hold Content-Length
-		if t.ContentLength < 0 {
-			return nil, ErrMissingContentLength
-		}
-	} else {
-		if !atLeastHTTP11 || t.Body == nil {
-			t.TransferEncoding = nil
-		}
-		if chunked(t.TransferEncoding) {
-			t.ContentLength = -1
-		} else if t.Body == nil { // no chunking, no body
-			t.ContentLength = 0
-		}
-	}
-
-	// Sanitize Trailer
-	if !chunked(t.TransferEncoding) {
-		t.Trailer = nil
-	}
-
-	return t, nil
-}
-
-func noBodyExpected(requestMethod string) bool {
-	return requestMethod == "HEAD"
-}
-
-func (t *transferWriter) shouldSendContentLength() bool {
-	if chunked(t.TransferEncoding) {
-		return false
-	}
-	if t.ContentLength > 0 {
-		return true
-	}
-	if t.ResponseToHEAD {
-		return true
-	}
-	// Many servers expect a Content-Length for these methods
-	if t.Method == "POST" || t.Method == "PUT" {
-		return true
-	}
-	if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
-		return true
-	}
-
-	return false
-}
-
-func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
-	if t.Close {
-		_, err = io.WriteString(w, "Connection: close\r\n")
-		if err != nil {
-			return
-		}
-	}
-
-	// Write Content-Length and/or Transfer-Encoding whose values are a
-	// function of the sanitized field triple (Body, ContentLength,
-	// TransferEncoding)
-	if t.shouldSendContentLength() {
-		io.WriteString(w, "Content-Length: ")
-		_, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
-		if err != nil {
-			return
-		}
-	} else if chunked(t.TransferEncoding) {
-		_, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
-		if err != nil {
-			return
-		}
-	}
-
-	// Write Trailer header
-	if t.Trailer != nil {
-		// TODO: At some point, there should be a generic mechanism for
-		// writing long headers, using HTTP line splitting
-		io.WriteString(w, "Trailer: ")
-		needComma := false
-		for k := range t.Trailer {
-			k = CanonicalHeaderKey(k)
-			switch k {
-			case "Transfer-Encoding", "Trailer", "Content-Length":
-				return &badStringError{"invalid Trailer key", k}
-			}
-			if needComma {
-				io.WriteString(w, ",")
-			}
-			io.WriteString(w, k)
-			needComma = true
-		}
-		_, err = io.WriteString(w, "\r\n")
-	}
-
-	return
-}
-
-func (t *transferWriter) WriteBody(w io.Writer) (err os.Error) {
-	var ncopy int64
-
-	// Write body
-	if t.Body != nil {
-		if chunked(t.TransferEncoding) {
-			cw := NewChunkedWriter(w)
-			_, err = io.Copy(cw, t.Body)
-			if err == nil {
-				err = cw.Close()
-			}
-		} else if t.ContentLength == -1 {
-			ncopy, err = io.Copy(w, t.Body)
-		} else {
-			ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
-			nextra, err := io.Copy(ioutil.Discard, t.Body)
-			if err != nil {
-				return err
-			}
-			ncopy += nextra
-		}
-		if err != nil {
-			return err
-		}
-		if err = t.BodyCloser.Close(); err != nil {
-			return err
-		}
-	}
-
-	if t.ContentLength != -1 && t.ContentLength != ncopy {
-		return fmt.Errorf("http: Request.ContentLength=%d with Body length %d",
-			t.ContentLength, ncopy)
-	}
-
-	// TODO(petar): Place trailer writer code here.
-	if chunked(t.TransferEncoding) {
-		// Last chunk, empty trailer
-		_, err = io.WriteString(w, "\r\n")
-	}
-
-	return
-}
-
-type transferReader struct {
-	// Input
-	Header        Header
-	StatusCode    int
-	RequestMethod string
-	ProtoMajor    int
-	ProtoMinor    int
-	// Output
-	Body             io.ReadCloser
-	ContentLength    int64
-	TransferEncoding []string
-	Close            bool
-	Trailer          Header
-}
-
-// bodyAllowedForStatus returns whether a given response status code
-// permits a body.  See RFC2616, section 4.4.
-func bodyAllowedForStatus(status int) bool {
-	switch {
-	case status >= 100 && status <= 199:
-		return false
-	case status == 204:
-		return false
-	case status == 304:
-		return false
-	}
-	return true
-}
-
-// msg is *Request or *Response.
-func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
-	t := &transferReader{}
-
-	// Unify input
-	isResponse := false
-	switch rr := msg.(type) {
-	case *Response:
-		t.Header = rr.Header
-		t.StatusCode = rr.StatusCode
-		t.RequestMethod = rr.Request.Method
-		t.ProtoMajor = rr.ProtoMajor
-		t.ProtoMinor = rr.ProtoMinor
-		t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header)
-		isResponse = true
-	case *Request:
-		t.Header = rr.Header
-		t.ProtoMajor = rr.ProtoMajor
-		t.ProtoMinor = rr.ProtoMinor
-		// Transfer semantics for Requests are exactly like those for
-		// Responses with status code 200, responding to a GET method
-		t.StatusCode = 200
-		t.RequestMethod = "GET"
-	default:
-		panic("unexpected type")
-	}
-
-	// Default to HTTP/1.1
-	if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
-		t.ProtoMajor, t.ProtoMinor = 1, 1
-	}
-
-	// Transfer encoding, content length
-	t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header)
-	if err != nil {
-		return err
-	}
-
-	t.ContentLength, err = fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
-	if err != nil {
-		return err
-	}
-
-	// Trailer
-	t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
-	if err != nil {
-		return err
-	}
-
-	// If there is no Content-Length or chunked Transfer-Encoding on a *Response
-	// and the status is not 1xx, 204 or 304, then the body is unbounded.
-	// See RFC2616, section 4.4.
-	switch msg.(type) {
-	case *Response:
-		if t.ContentLength == -1 &&
-			!chunked(t.TransferEncoding) &&
-			bodyAllowedForStatus(t.StatusCode) {
-			// Unbounded body.
-			t.Close = true
-		}
-	}
-
-	// Prepare body reader.  ContentLength < 0 means chunked encoding
-	// or close connection when finished, since multipart is not supported yet
-	switch {
-	case chunked(t.TransferEncoding):
-		t.Body = &body{Reader: NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
-	case t.ContentLength >= 0:
-		// TODO: limit the Content-Length. This is an easy DoS vector.
-		t.Body = &body{Reader: io.LimitReader(r, t.ContentLength), closing: t.Close}
-	default:
-		// t.ContentLength < 0, i.e. "Content-Length" not mentioned in header
-		if t.Close {
-			// Close semantics (i.e. HTTP/1.0)
-			t.Body = &body{Reader: r, closing: t.Close}
-		} else {
-			// Persistent connection (i.e. HTTP/1.1)
-			t.Body = &body{Reader: io.LimitReader(r, 0), closing: t.Close}
-		}
-	}
-
-	// Unify output
-	switch rr := msg.(type) {
-	case *Request:
-		rr.Body = t.Body
-		rr.ContentLength = t.ContentLength
-		rr.TransferEncoding = t.TransferEncoding
-		rr.Close = t.Close
-		rr.Trailer = t.Trailer
-	case *Response:
-		rr.Body = t.Body
-		rr.ContentLength = t.ContentLength
-		rr.TransferEncoding = t.TransferEncoding
-		rr.Close = t.Close
-		rr.Trailer = t.Trailer
-	}
-
-	return nil
-}
-
-// Checks whether chunked is part of the encodings stack
-func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
-
-// Checks whether the encoding is explicitly "identity".
-func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
-
-// Sanitize transfer encoding
-func fixTransferEncoding(requestMethod string, header Header) ([]string, os.Error) {
-	raw, present := header["Transfer-Encoding"]
-	if !present {
-		return nil, nil
-	}
-
-	header["Transfer-Encoding"] = nil, false
-
-	// Head responses have no bodies, so the transfer encoding
-	// should be ignored.
-	if requestMethod == "HEAD" {
-		return nil, nil
-	}
-
-	encodings := strings.Split(raw[0], ",")
-	te := make([]string, 0, len(encodings))
-	// TODO: Even though we only support "identity" and "chunked"
-	// encodings, the loop below is designed with foresight. One
-	// invariant that must be maintained is that, if present,
-	// chunked encoding must always come first.
-	for _, encoding := range encodings {
-		encoding = strings.ToLower(strings.TrimSpace(encoding))
-		// "identity" encoding is not recored
-		if encoding == "identity" {
-			break
-		}
-		if encoding != "chunked" {
-			return nil, &badStringError{"unsupported transfer encoding", encoding}
-		}
-		te = te[0 : len(te)+1]
-		te[len(te)-1] = encoding
-	}
-	if len(te) > 1 {
-		return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")}
-	}
-	if len(te) > 0 {
-		// Chunked encoding trumps Content-Length. See RFC 2616
-		// Section 4.4. Currently len(te) > 0 implies chunked
-		// encoding.
-		header["Content-Length"] = nil, false
-		return te, nil
-	}
-
-	return nil, nil
-}
-
-// Determine the expected body length, using RFC 2616 Section 4.4. This
-// function is not a method, because ultimately it should be shared by
-// ReadResponse and ReadRequest.
-func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, os.Error) {
-
-	// Logic based on response type or status
-	if noBodyExpected(requestMethod) {
-		return 0, nil
-	}
-	if status/100 == 1 {
-		return 0, nil
-	}
-	switch status {
-	case 204, 304:
-		return 0, nil
-	}
-
-	// Logic based on Transfer-Encoding
-	if chunked(te) {
-		return -1, nil
-	}
-
-	// Logic based on Content-Length
-	cl := strings.TrimSpace(header.Get("Content-Length"))
-	if cl != "" {
-		n, err := strconv.Atoi64(cl)
-		if err != nil || n < 0 {
-			return -1, &badStringError{"bad Content-Length", cl}
-		}
-		return n, nil
-	} else {
-		header.Del("Content-Length")
-	}
-
-	if !isResponse && requestMethod == "GET" {
-		// RFC 2616 doesn't explicitly permit nor forbid an
-		// entity-body on a GET request so we permit one if
-		// declared, but we default to 0 here (not -1 below)
-		// if there's no mention of a body.
-		return 0, nil
-	}
-
-	// Logic based on media type. The purpose of the following code is just
-	// to detect whether the unsupported "multipart/byteranges" is being
-	// used. A proper Content-Type parser is needed in the future.
-	if strings.Contains(strings.ToLower(header.Get("Content-Type")), "multipart/byteranges") {
-		return -1, ErrNotSupported
-	}
-
-	// Body-EOF logic based on other methods (like closing, or chunked coding)
-	return -1, nil
-}
-
-// Determine whether to hang up after sending a request and body, or
-// receiving a response and body
-// 'header' is the request headers
-func shouldClose(major, minor int, header Header) bool {
-	if major < 1 {
-		return true
-	} else if major == 1 && minor == 0 {
-		if !strings.Contains(strings.ToLower(header.Get("Connection")), "keep-alive") {
-			return true
-		}
-		return false
-	} else {
-		// TODO: Should split on commas, toss surrounding white space,
-		// and check each field.
-		if strings.ToLower(header.Get("Connection")) == "close" {
-			header.Del("Connection")
-			return true
-		}
-	}
-	return false
-}
-
-// Parse the trailer header
-func fixTrailer(header Header, te []string) (Header, os.Error) {
-	raw := header.Get("Trailer")
-	if raw == "" {
-		return nil, nil
-	}
-
-	header.Del("Trailer")
-	trailer := make(Header)
-	keys := strings.Split(raw, ",")
-	for _, key := range keys {
-		key = CanonicalHeaderKey(strings.TrimSpace(key))
-		switch key {
-		case "Transfer-Encoding", "Trailer", "Content-Length":
-			return nil, &badStringError{"bad trailer key", key}
-		}
-		trailer.Del(key)
-	}
-	if len(trailer) == 0 {
-		return nil, nil
-	}
-	if !chunked(te) {
-		// Trailer and no chunking
-		return nil, ErrUnexpectedTrailer
-	}
-	return trailer, nil
-}
-
-// body turns a Reader into a ReadCloser.
-// Close ensures that the body has been fully read
-// and then reads the trailer if necessary.
-type body struct {
-	io.Reader
-	hdr     interface{}   // non-nil (Response or Request) value means read trailer
-	r       *bufio.Reader // underlying wire-format reader for the trailer
-	closing bool          // is the connection to be closed after reading body?
-	closed  bool
-
-	res *response // response writer for server requests, else nil
-}
-
-// ErrBodyReadAfterClose is returned when reading a Request Body after
-// the body has been closed. This typically happens when the body is
-// read after an HTTP Handler calls WriteHeader or Write on its
-// ResponseWriter.
-var ErrBodyReadAfterClose = os.NewError("http: invalid Read on closed request Body")
-
-func (b *body) Read(p []byte) (n int, err os.Error) {
-	if b.closed {
-		return 0, ErrBodyReadAfterClose
-	}
-	return b.Reader.Read(p)
-}
-
-func (b *body) Close() os.Error {
-	if b.closed {
-		return nil
-	}
-	defer func() {
-		b.closed = true
-	}()
-	if b.hdr == nil && b.closing {
-		// no trailer and closing the connection next.
-		// no point in reading to EOF.
-		return nil
-	}
-
-	// In a server request, don't continue reading from the client
-	// if we've already hit the maximum body size set by the
-	// handler. If this is set, that also means the TCP connection
-	// is about to be closed, so getting to the next HTTP request
-	// in the stream is not necessary.
-	if b.res != nil && b.res.requestBodyLimitHit {
-		return nil
-	}
-
-	if _, err := io.Copy(ioutil.Discard, b); err != nil {
-		return err
-	}
-
-	if b.hdr == nil { // not reading trailer
-		return nil
-	}
-
-	// TODO(petar): Put trailer reader code here
-
-	return nil
-}
diff --git a/src/pkg/http/transport.go b/src/pkg/http/transport.go
deleted file mode 100644
index 8ac7832..0000000
--- a/src/pkg/http/transport.go
+++ /dev/null
@@ -1,721 +0,0 @@
-// Copyright 2011 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 http
-
-import (
-	"bufio"
-	"compress/gzip"
-	"crypto/tls"
-	"encoding/base64"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"log"
-	"net"
-	"os"
-	"strings"
-	"sync"
-	"url"
-)
-
-// DefaultTransport is the default implementation of Transport and is
-// used by DefaultClient.  It establishes a new network connection for
-// each call to Do and uses HTTP proxies as directed by the
-// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy)
-// environment variables.
-var DefaultTransport RoundTripper = &Transport{Proxy: ProxyFromEnvironment}
-
-// DefaultMaxIdleConnsPerHost is the default value of Transport's
-// MaxIdleConnsPerHost.
-const DefaultMaxIdleConnsPerHost = 2
-
-// Transport is an implementation of RoundTripper that supports http,
-// https, and http proxies (for either http or https with CONNECT).
-// Transport can also cache connections for future re-use.
-type Transport struct {
-	lk       sync.Mutex
-	idleConn map[string][]*persistConn
-	altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
-
-	// TODO: tunable on global max cached connections
-	// TODO: tunable on timeout on cached connections
-	// TODO: optional pipelining
-
-	// Proxy specifies a function to return a proxy for a given
-	// Request. If the function returns a non-nil error, the
-	// request is aborted with the provided error.
-	// If Proxy is nil or returns a nil *URL, no proxy is used.
-	Proxy func(*Request) (*url.URL, os.Error)
-
-	// Dial specifies the dial function for creating TCP
-	// connections.
-	// If Dial is nil, net.Dial is used.
-	Dial func(net, addr string) (c net.Conn, err os.Error)
-
-	// TLSClientConfig specifies the TLS configuration to use with
-	// tls.Client. If nil, the default configuration is used.
-	TLSClientConfig *tls.Config
-
-	DisableKeepAlives  bool
-	DisableCompression bool
-
-	// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
-	// (keep-alive) to keep to keep per-host.  If zero,
-	// DefaultMaxIdleConnsPerHost is used.
-	MaxIdleConnsPerHost int
-}
-
-// ProxyFromEnvironment returns the URL of the proxy to use for a
-// given request, as indicated by the environment variables
-// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy).
-// Either URL or an error is returned.
-func ProxyFromEnvironment(req *Request) (*url.URL, os.Error) {
-	proxy := getenvEitherCase("HTTP_PROXY")
-	if proxy == "" {
-		return nil, nil
-	}
-	if !useProxy(canonicalAddr(req.URL)) {
-		return nil, nil
-	}
-	proxyURL, err := url.ParseRequest(proxy)
-	if err != nil {
-		return nil, os.NewError("invalid proxy address")
-	}
-	if proxyURL.Host == "" {
-		proxyURL, err = url.ParseRequest("http://" + proxy)
-		if err != nil {
-			return nil, os.NewError("invalid proxy address")
-		}
-	}
-	return proxyURL, nil
-}
-
-// ProxyURL returns a proxy function (for use in a Transport)
-// that always returns the same URL.
-func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, os.Error) {
-	return func(*Request) (*url.URL, os.Error) {
-		return fixedURL, nil
-	}
-}
-
-// RoundTrip implements the RoundTripper interface.
-func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) {
-	if req.URL == nil {
-		if req.URL, err = url.Parse(req.RawURL); err != nil {
-			return
-		}
-	}
-	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
-		t.lk.Lock()
-		var rt RoundTripper
-		if t.altProto != nil {
-			rt = t.altProto[req.URL.Scheme]
-		}
-		t.lk.Unlock()
-		if rt == nil {
-			return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
-		}
-		return rt.RoundTrip(req)
-	}
-
-	cm, err := t.connectMethodForRequest(req)
-	if err != nil {
-		return nil, err
-	}
-
-	// Get the cached or newly-created connection to either the
-	// host (for http or https), the http proxy, or the http proxy
-	// pre-CONNECTed to https server.  In any case, we'll be ready
-	// to send it requests.
-	pconn, err := t.getConn(cm)
-	if err != nil {
-		return nil, err
-	}
-
-	return pconn.roundTrip(req)
-}
-
-// RegisterProtocol registers a new protocol with scheme.
-// The Transport will pass requests using the given scheme to rt.
-// It is rt's responsibility to simulate HTTP request semantics.
-//
-// RegisterProtocol can be used by other packages to provide
-// implementations of protocol schemes like "ftp" or "file".
-func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
-	if scheme == "http" || scheme == "https" {
-		panic("protocol " + scheme + " already registered")
-	}
-	t.lk.Lock()
-	defer t.lk.Unlock()
-	if t.altProto == nil {
-		t.altProto = make(map[string]RoundTripper)
-	}
-	if _, exists := t.altProto[scheme]; exists {
-		panic("protocol " + scheme + " already registered")
-	}
-	t.altProto[scheme] = rt
-}
-
-// CloseIdleConnections closes any connections which were previously
-// connected from previous requests but are now sitting idle in
-// a "keep-alive" state. It does not interrupt any connections currently
-// in use.
-func (t *Transport) CloseIdleConnections() {
-	t.lk.Lock()
-	defer t.lk.Unlock()
-	if t.idleConn == nil {
-		return
-	}
-	for _, conns := range t.idleConn {
-		for _, pconn := range conns {
-			pconn.close()
-		}
-	}
-	t.idleConn = nil
-}
-
-//
-// Private implementation past this point.
-//
-
-func getenvEitherCase(k string) string {
-	if v := os.Getenv(strings.ToUpper(k)); v != "" {
-		return v
-	}
-	return os.Getenv(strings.ToLower(k))
-}
-
-func (t *Transport) connectMethodForRequest(req *Request) (*connectMethod, os.Error) {
-	cm := &connectMethod{
-		targetScheme: req.URL.Scheme,
-		targetAddr:   canonicalAddr(req.URL),
-	}
-	if t.Proxy != nil {
-		var err os.Error
-		cm.proxyURL, err = t.Proxy(req)
-		if err != nil {
-			return nil, err
-		}
-	}
-	return cm, nil
-}
-
-// proxyAuth returns the Proxy-Authorization header to set
-// on requests, if applicable.
-func (cm *connectMethod) proxyAuth() string {
-	if cm.proxyURL == nil {
-		return ""
-	}
-	proxyInfo := cm.proxyURL.RawUserinfo
-	if proxyInfo != "" {
-		return "Basic " + base64.URLEncoding.EncodeToString([]byte(proxyInfo))
-	}
-	return ""
-}
-
-func (t *Transport) putIdleConn(pconn *persistConn) {
-	t.lk.Lock()
-	defer t.lk.Unlock()
-	if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
-		pconn.close()
-		return
-	}
-	if pconn.isBroken() {
-		return
-	}
-	key := pconn.cacheKey
-	max := t.MaxIdleConnsPerHost
-	if max == 0 {
-		max = DefaultMaxIdleConnsPerHost
-	}
-	if len(t.idleConn[key]) >= max {
-		pconn.close()
-		return
-	}
-	t.idleConn[key] = append(t.idleConn[key], pconn)
-}
-
-func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
-	t.lk.Lock()
-	defer t.lk.Unlock()
-	if t.idleConn == nil {
-		t.idleConn = make(map[string][]*persistConn)
-	}
-	key := cm.String()
-	for {
-		pconns, ok := t.idleConn[key]
-		if !ok {
-			return nil
-		}
-		if len(pconns) == 1 {
-			pconn = pconns[0]
-			t.idleConn[key] = nil, false
-		} else {
-			// 2 or more cached connections; pop last
-			// TODO: queue?
-			pconn = pconns[len(pconns)-1]
-			t.idleConn[key] = pconns[0 : len(pconns)-1]
-		}
-		if !pconn.isBroken() {
-			return
-		}
-	}
-	return
-}
-
-func (t *Transport) dial(network, addr string) (c net.Conn, err os.Error) {
-	if t.Dial != nil {
-		return t.Dial(network, addr)
-	}
-	return net.Dial(network, addr)
-}
-
-// getConn dials and creates a new persistConn to the target as
-// specified in the connectMethod.  This includes doing a proxy CONNECT
-// and/or setting up TLS.  If this doesn't return an error, the persistConn
-// is ready to write requests to.
-func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) {
-	if pc := t.getIdleConn(cm); pc != nil {
-		return pc, nil
-	}
-
-	conn, err := t.dial("tcp", cm.addr())
-	if err != nil {
-		if cm.proxyURL != nil {
-			err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
-		}
-		return nil, err
-	}
-
-	pa := cm.proxyAuth()
-
-	pconn := &persistConn{
-		t:        t,
-		cacheKey: cm.String(),
-		conn:     conn,
-		reqch:    make(chan requestAndChan, 50),
-	}
-	newClientConnFunc := NewClientConn
-
-	switch {
-	case cm.proxyURL == nil:
-		// Do nothing.
-	case cm.targetScheme == "http":
-		newClientConnFunc = NewProxyClientConn
-		if pa != "" {
-			pconn.mutateRequestFunc = func(req *Request) {
-				if req.Header == nil {
-					req.Header = make(Header)
-				}
-				req.Header.Set("Proxy-Authorization", pa)
-			}
-		}
-	case cm.targetScheme == "https":
-		connectReq := &Request{
-			Method: "CONNECT",
-			RawURL: cm.targetAddr,
-			Host:   cm.targetAddr,
-			Header: make(Header),
-		}
-		if pa != "" {
-			connectReq.Header.Set("Proxy-Authorization", pa)
-		}
-		connectReq.Write(conn)
-
-		// Read response.
-		// Okay to use and discard buffered reader here, because
-		// TLS server will not speak until spoken to.
-		br := bufio.NewReader(conn)
-		resp, err := ReadResponse(br, connectReq)
-		if err != nil {
-			conn.Close()
-			return nil, err
-		}
-		if resp.StatusCode != 200 {
-			f := strings.SplitN(resp.Status, " ", 2)
-			conn.Close()
-			return nil, os.NewError(f[1])
-		}
-	}
-
-	if cm.targetScheme == "https" {
-		// Initiate TLS and check remote host name against certificate.
-		conn = tls.Client(conn, t.TLSClientConfig)
-		if err = conn.(*tls.Conn).Handshake(); err != nil {
-			return nil, err
-		}
-		if err = conn.(*tls.Conn).VerifyHostname(cm.tlsHost()); err != nil {
-			return nil, err
-		}
-		pconn.conn = conn
-	}
-
-	pconn.br = bufio.NewReader(pconn.conn)
-	pconn.cc = newClientConnFunc(conn, pconn.br)
-	go pconn.readLoop()
-	return pconn, nil
-}
-
-// useProxy returns true if requests to addr should use a proxy,
-// according to the NO_PROXY or no_proxy environment variable.
-// addr is always a canonicalAddr with a host and port.
-func useProxy(addr string) bool {
-	if len(addr) == 0 {
-		return true
-	}
-	host, _, err := net.SplitHostPort(addr)
-	if err != nil {
-		return false
-	}
-	if host == "localhost" {
-		return false
-	}
-	if ip := net.ParseIP(host); ip != nil {
-		if ip.IsLoopback() {
-			return false
-		}
-	}
-
-	no_proxy := getenvEitherCase("NO_PROXY")
-	if no_proxy == "*" {
-		return false
-	}
-
-	addr = strings.ToLower(strings.TrimSpace(addr))
-	if hasPort(addr) {
-		addr = addr[:strings.LastIndex(addr, ":")]
-	}
-
-	for _, p := range strings.Split(no_proxy, ",") {
-		p = strings.ToLower(strings.TrimSpace(p))
-		if len(p) == 0 {
-			continue
-		}
-		if hasPort(p) {
-			p = p[:strings.LastIndex(p, ":")]
-		}
-		if addr == p || (p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:])) {
-			return false
-		}
-	}
-	return true
-}
-
-// connectMethod is the map key (in its String form) for keeping persistent
-// TCP connections alive for subsequent HTTP requests.
-//
-// A connect method may be of the following types:
-//
-// Cache key form                Description
-// -----------------             -------------------------
-// ||http|foo.com                http directly to server, no proxy
-// ||https|foo.com               https directly to server, no proxy
-// http://proxy.com|https|foo.com  http to proxy, then CONNECT to foo.com
-// http://proxy.com|http           http to proxy, http to anywhere after that
-//
-// Note: no support to https to the proxy yet.
-//
-type connectMethod struct {
-	proxyURL     *url.URL // nil for no proxy, else full proxy URL
-	targetScheme string   // "http" or "https"
-	targetAddr   string   // Not used if proxy + http targetScheme (4th example in table)
-}
-
-func (ck *connectMethod) String() string {
-	proxyStr := ""
-	if ck.proxyURL != nil {
-		proxyStr = ck.proxyURL.String()
-	}
-	return strings.Join([]string{proxyStr, ck.targetScheme, ck.targetAddr}, "|")
-}
-
-// addr returns the first hop "host:port" to which we need to TCP connect.
-func (cm *connectMethod) addr() string {
-	if cm.proxyURL != nil {
-		return canonicalAddr(cm.proxyURL)
-	}
-	return cm.targetAddr
-}
-
-// tlsHost returns the host name to match against the peer's
-// TLS certificate.
-func (cm *connectMethod) tlsHost() string {
-	h := cm.targetAddr
-	if hasPort(h) {
-		h = h[:strings.LastIndex(h, ":")]
-	}
-	return h
-}
-
-type readResult struct {
-	res *Response // either res or err will be set
-	err os.Error
-}
-
-type writeRequest struct {
-	// Set by client (in pc.roundTrip)
-	req   *Request
-	resch chan *readResult
-
-	// Set by writeLoop if an error writing headers.
-	writeErr os.Error
-}
-
-// persistConn wraps a connection, usually a persistent one
-// (but may be used for non-keep-alive requests as well)
-type persistConn struct {
-	t                 *Transport
-	cacheKey          string // its connectMethod.String()
-	conn              net.Conn
-	cc                *ClientConn
-	br                *bufio.Reader
-	reqch             chan requestAndChan // written by roundTrip(); read by readLoop()
-	mutateRequestFunc func(*Request)      // nil or func to modify each outbound request
-
-	lk                   sync.Mutex // guards numExpectedResponses and broken
-	numExpectedResponses int
-	broken               bool // an error has happened on this connection; marked broken so it's not reused.
-}
-
-func (pc *persistConn) isBroken() bool {
-	pc.lk.Lock()
-	defer pc.lk.Unlock()
-	return pc.broken
-}
-
-func (pc *persistConn) expectingResponse() bool {
-	pc.lk.Lock()
-	defer pc.lk.Unlock()
-	return pc.numExpectedResponses > 0
-}
-
-func (pc *persistConn) readLoop() {
-	alive := true
-	for alive {
-		pb, err := pc.br.Peek(1)
-		if err != nil {
-			if (err == os.EOF || err == os.EINVAL) && !pc.expectingResponse() {
-				// Remote side closed on us.  (We probably hit their
-				// max idle timeout)
-				pc.close()
-				return
-			}
-		}
-		if !pc.expectingResponse() {
-			log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
-				string(pb), err)
-			pc.close()
-			return
-		}
-
-		rc := <-pc.reqch
-		resp, err := pc.cc.readUsing(rc.req, func(buf *bufio.Reader, forReq *Request) (*Response, os.Error) {
-			resp, err := ReadResponse(buf, forReq)
-			if err != nil || resp.ContentLength == 0 {
-				return resp, err
-			}
-			if rc.addedGzip {
-				forReq.Header.Del("Accept-Encoding")
-			}
-			if rc.addedGzip && resp.Header.Get("Content-Encoding") == "gzip" {
-				resp.Header.Del("Content-Encoding")
-				resp.Header.Del("Content-Length")
-				resp.ContentLength = -1
-				gzReader, err := gzip.NewReader(resp.Body)
-				if err != nil {
-					pc.close()
-					return nil, err
-				}
-				resp.Body = &readFirstCloseBoth{&discardOnCloseReadCloser{gzReader}, resp.Body}
-			}
-			resp.Body = &bodyEOFSignal{body: resp.Body}
-			return resp, err
-		})
-
-		if err == ErrPersistEOF {
-			// Succeeded, but we can't send any more
-			// persistent connections on this again.  We
-			// hide this error to upstream callers.
-			alive = false
-			err = nil
-		} else if err != nil || rc.req.Close {
-			alive = false
-		}
-
-		hasBody := resp != nil && resp.ContentLength != 0
-		var waitForBodyRead chan bool
-		if alive {
-			if hasBody {
-				waitForBodyRead = make(chan bool)
-				resp.Body.(*bodyEOFSignal).fn = func() {
-					pc.t.putIdleConn(pc)
-					waitForBodyRead <- true
-				}
-			} else {
-				// When there's no response body, we immediately
-				// reuse the TCP connection (putIdleConn), but
-				// we need to prevent ClientConn.Read from
-				// closing the Response.Body on the next
-				// loop, otherwise it might close the body
-				// before the client code has had a chance to
-				// read it (even though it'll just be 0, EOF).
-				pc.cc.lk.Lock()
-				pc.cc.lastbody = nil
-				pc.cc.lk.Unlock()
-
-				pc.t.putIdleConn(pc)
-			}
-		}
-
-		rc.ch <- responseAndError{resp, err}
-
-		// Wait for the just-returned response body to be fully consumed
-		// before we race and peek on the underlying bufio reader.
-		if waitForBodyRead != nil {
-			<-waitForBodyRead
-		}
-	}
-}
-
-type responseAndError struct {
-	res *Response
-	err os.Error
-}
-
-type requestAndChan struct {
-	req *Request
-	ch  chan responseAndError
-
-	// did the Transport (as opposed to the client code) add an
-	// Accept-Encoding gzip header? only if it we set it do
-	// we transparently decode the gzip.
-	addedGzip bool
-}
-
-func (pc *persistConn) roundTrip(req *Request) (resp *Response, err os.Error) {
-	if pc.mutateRequestFunc != nil {
-		pc.mutateRequestFunc(req)
-	}
-
-	// Ask for a compressed version if the caller didn't set their
-	// own value for Accept-Encoding. We only attempted to
-	// uncompress the gzip stream if we were the layer that
-	// requested it.
-	requestedGzip := false
-	if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" {
-		// Request gzip only, not deflate. Deflate is ambiguous and 
-		// as universally supported anyway.
-		// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
-		requestedGzip = true
-		req.Header.Set("Accept-Encoding", "gzip")
-	}
-
-	pc.lk.Lock()
-	pc.numExpectedResponses++
-	pc.lk.Unlock()
-
-	err = pc.cc.Write(req)
-	if err != nil {
-		pc.close()
-		return
-	}
-
-	ch := make(chan responseAndError, 1)
-	pc.reqch <- requestAndChan{req, ch, requestedGzip}
-	re := <-ch
-	pc.lk.Lock()
-	pc.numExpectedResponses--
-	pc.lk.Unlock()
-
-	return re.res, re.err
-}
-
-func (pc *persistConn) close() {
-	pc.lk.Lock()
-	defer pc.lk.Unlock()
-	pc.broken = true
-	pc.cc.Close()
-	pc.conn.Close()
-	pc.mutateRequestFunc = nil
-}
-
-var portMap = map[string]string{
-	"http":  "80",
-	"https": "443",
-}
-
-// canonicalAddr returns url.Host but always with a ":port" suffix
-func canonicalAddr(url *url.URL) string {
-	addr := url.Host
-	if !hasPort(addr) {
-		return addr + ":" + portMap[url.Scheme]
-	}
-	return addr
-}
-
-func responseIsKeepAlive(res *Response) bool {
-	// TODO: implement.  for now just always shutting down the connection.
-	return false
-}
-
-// bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
-// once, right before the final Read() or Close() call returns, but after
-// EOF has been seen.
-type bodyEOFSignal struct {
-	body     io.ReadCloser
-	fn       func()
-	isClosed bool
-}
-
-func (es *bodyEOFSignal) Read(p []byte) (n int, err os.Error) {
-	n, err = es.body.Read(p)
-	if es.isClosed && n > 0 {
-		panic("http: unexpected bodyEOFSignal Read after Close; see issue 1725")
-	}
-	if err == os.EOF && es.fn != nil {
-		es.fn()
-		es.fn = nil
-	}
-	return
-}
-
-func (es *bodyEOFSignal) Close() (err os.Error) {
-	if es.isClosed {
-		return nil
-	}
-	es.isClosed = true
-	err = es.body.Close()
-	if err == nil && es.fn != nil {
-		es.fn()
-		es.fn = nil
-	}
-	return
-}
-
-type readFirstCloseBoth struct {
-	io.ReadCloser
-	io.Closer
-}
-
-func (r *readFirstCloseBoth) Close() os.Error {
-	if err := r.ReadCloser.Close(); err != nil {
-		r.Closer.Close()
-		return err
-	}
-	if err := r.Closer.Close(); err != nil {
-		return err
-	}
-	return nil
-}
-
-// discardOnCloseReadCloser consumes all its input on Close.
-type discardOnCloseReadCloser struct {
-	io.ReadCloser
-}
-
-func (d *discardOnCloseReadCloser) Close() os.Error {
-	io.Copy(ioutil.Discard, d.ReadCloser) // ignore errors; likely invalid or already closed
-	return d.ReadCloser.Close()
-}
diff --git a/src/pkg/http/transport_test.go b/src/pkg/http/transport_test.go
deleted file mode 100644
index eafde7f..0000000
--- a/src/pkg/http/transport_test.go
+++ /dev/null
@@ -1,662 +0,0 @@
-// Copyright 2011 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.
-
-// Tests for transport.go
-
-package http_test
-
-import (
-	"bytes"
-	"compress/gzip"
-	"crypto/rand"
-	"fmt"
-	. "http"
-	"http/httptest"
-	"io"
-	"io/ioutil"
-	"os"
-	"strconv"
-	"strings"
-	"testing"
-	"time"
-	"url"
-)
-
-// TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close
-//       and then verify that the final 2 responses get errors back.
-
-// hostPortHandler writes back the client's "host:port".
-var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
-	if r.FormValue("close") == "true" {
-		w.Header().Set("Connection", "close")
-	}
-	w.Write([]byte(r.RemoteAddr))
-})
-
-// Two subsequent requests and verify their response is the same.
-// The response from the server is our own IP:port
-func TestTransportKeepAlives(t *testing.T) {
-	ts := httptest.NewServer(hostPortHandler)
-	defer ts.Close()
-
-	for _, disableKeepAlive := range []bool{false, true} {
-		tr := &Transport{DisableKeepAlives: disableKeepAlive}
-		c := &Client{Transport: tr}
-
-		fetch := func(n int) string {
-			res, err := c.Get(ts.URL)
-			if err != nil {
-				t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
-			}
-			body, err := ioutil.ReadAll(res.Body)
-			if err != nil {
-				t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err)
-			}
-			return string(body)
-		}
-
-		body1 := fetch(1)
-		body2 := fetch(2)
-
-		bodiesDiffer := body1 != body2
-		if bodiesDiffer != disableKeepAlive {
-			t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
-				disableKeepAlive, bodiesDiffer, body1, body2)
-		}
-	}
-}
-
-func TestTransportConnectionCloseOnResponse(t *testing.T) {
-	ts := httptest.NewServer(hostPortHandler)
-	defer ts.Close()
-
-	for _, connectionClose := range []bool{false, true} {
-		tr := &Transport{}
-		c := &Client{Transport: tr}
-
-		fetch := func(n int) string {
-			req := new(Request)
-			var err os.Error
-			req.URL, err = url.Parse(ts.URL + fmt.Sprintf("?close=%v", connectionClose))
-			if err != nil {
-				t.Fatalf("URL parse error: %v", err)
-			}
-			req.Method = "GET"
-			req.Proto = "HTTP/1.1"
-			req.ProtoMajor = 1
-			req.ProtoMinor = 1
-
-			res, err := c.Do(req)
-			if err != nil {
-				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
-			}
-			body, err := ioutil.ReadAll(res.Body)
-			defer res.Body.Close()
-			if err != nil {
-				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
-			}
-			return string(body)
-		}
-
-		body1 := fetch(1)
-		body2 := fetch(2)
-		bodiesDiffer := body1 != body2
-		if bodiesDiffer != connectionClose {
-			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
-				connectionClose, bodiesDiffer, body1, body2)
-		}
-	}
-}
-
-func TestTransportConnectionCloseOnRequest(t *testing.T) {
-	ts := httptest.NewServer(hostPortHandler)
-	defer ts.Close()
-
-	for _, connectionClose := range []bool{false, true} {
-		tr := &Transport{}
-		c := &Client{Transport: tr}
-
-		fetch := func(n int) string {
-			req := new(Request)
-			var err os.Error
-			req.URL, err = url.Parse(ts.URL)
-			if err != nil {
-				t.Fatalf("URL parse error: %v", err)
-			}
-			req.Method = "GET"
-			req.Proto = "HTTP/1.1"
-			req.ProtoMajor = 1
-			req.ProtoMinor = 1
-			req.Close = connectionClose
-
-			res, err := c.Do(req)
-			if err != nil {
-				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
-			}
-			body, err := ioutil.ReadAll(res.Body)
-			if err != nil {
-				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
-			}
-			return string(body)
-		}
-
-		body1 := fetch(1)
-		body2 := fetch(2)
-		bodiesDiffer := body1 != body2
-		if bodiesDiffer != connectionClose {
-			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
-				connectionClose, bodiesDiffer, body1, body2)
-		}
-	}
-}
-
-func TestTransportIdleCacheKeys(t *testing.T) {
-	ts := httptest.NewServer(hostPortHandler)
-	defer ts.Close()
-
-	tr := &Transport{DisableKeepAlives: false}
-	c := &Client{Transport: tr}
-
-	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
-		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
-	}
-
-	resp, err := c.Get(ts.URL)
-	if err != nil {
-		t.Error(err)
-	}
-	ioutil.ReadAll(resp.Body)
-
-	keys := tr.IdleConnKeysForTesting()
-	if e, g := 1, len(keys); e != g {
-		t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g)
-	}
-
-	if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
-		t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
-	}
-
-	tr.CloseIdleConnections()
-	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
-		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
-	}
-}
-
-func TestTransportMaxPerHostIdleConns(t *testing.T) {
-	resch := make(chan string)
-	gotReq := make(chan bool)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		gotReq <- true
-		msg := <-resch
-		_, err := w.Write([]byte(msg))
-		if err != nil {
-			t.Fatalf("Write: %v", err)
-		}
-	}))
-	defer ts.Close()
-	maxIdleConns := 2
-	tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns}
-	c := &Client{Transport: tr}
-
-	// Start 3 outstanding requests and wait for the server to get them.
-	// Their responses will hang until we we write to resch, though.
-	donech := make(chan bool)
-	doReq := func() {
-		resp, err := c.Get(ts.URL)
-		if err != nil {
-			t.Error(err)
-		}
-		_, err = ioutil.ReadAll(resp.Body)
-		if err != nil {
-			t.Fatalf("ReadAll: %v", err)
-		}
-		donech <- true
-	}
-	go doReq()
-	<-gotReq
-	go doReq()
-	<-gotReq
-	go doReq()
-	<-gotReq
-
-	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
-		t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
-	}
-
-	resch <- "res1"
-	<-donech
-	keys := tr.IdleConnKeysForTesting()
-	if e, g := 1, len(keys); e != g {
-		t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
-	}
-	cacheKey := "|http|" + ts.Listener.Addr().String()
-	if keys[0] != cacheKey {
-		t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
-	}
-	if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g {
-		t.Errorf("after first response, expected %d idle conns; got %d", e, g)
-	}
-
-	resch <- "res2"
-	<-donech
-	if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g {
-		t.Errorf("after second response, expected %d idle conns; got %d", e, g)
-	}
-
-	resch <- "res3"
-	<-donech
-	if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g {
-		t.Errorf("after third response, still expected %d idle conns; got %d", e, g)
-	}
-}
-
-func TestTransportServerClosingUnexpectedly(t *testing.T) {
-	ts := httptest.NewServer(hostPortHandler)
-	defer ts.Close()
-
-	tr := &Transport{}
-	c := &Client{Transport: tr}
-
-	fetch := func(n, retries int) string {
-		condFatalf := func(format string, arg ...interface{}) {
-			if retries <= 0 {
-				t.Fatalf(format, arg...)
-			}
-			t.Logf("retrying shortly after expected error: "+format, arg...)
-			time.Sleep(1e9 / int64(retries))
-		}
-		for retries >= 0 {
-			retries--
-			res, err := c.Get(ts.URL)
-			if err != nil {
-				condFatalf("error in req #%d, GET: %v", n, err)
-				continue
-			}
-			body, err := ioutil.ReadAll(res.Body)
-			if err != nil {
-				condFatalf("error in req #%d, ReadAll: %v", n, err)
-				continue
-			}
-			res.Body.Close()
-			return string(body)
-		}
-		panic("unreachable")
-	}
-
-	body1 := fetch(1, 0)
-	body2 := fetch(2, 0)
-
-	ts.CloseClientConnections() // surprise!
-
-	// This test has an expected race. Sleeping for 25 ms prevents
-	// it on most fast machines, causing the next fetch() call to
-	// succeed quickly.  But if we do get errors, fetch() will retry 5
-	// times with some delays between.
-	time.Sleep(25e6)
-
-	body3 := fetch(3, 5)
-
-	if body1 != body2 {
-		t.Errorf("expected body1 and body2 to be equal")
-	}
-	if body2 == body3 {
-		t.Errorf("expected body2 and body3 to be different")
-	}
-}
-
-// TestTransportHeadResponses verifies that we deal with Content-Lengths
-// with no bodies properly
-func TestTransportHeadResponses(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		if r.Method != "HEAD" {
-			panic("expected HEAD; got " + r.Method)
-		}
-		w.Header().Set("Content-Length", "123")
-		w.WriteHeader(200)
-	}))
-	defer ts.Close()
-
-	tr := &Transport{DisableKeepAlives: false}
-	c := &Client{Transport: tr}
-	for i := 0; i < 2; i++ {
-		res, err := c.Head(ts.URL)
-		if err != nil {
-			t.Errorf("error on loop %d: %v", i, err)
-		}
-		if e, g := "123", res.Header.Get("Content-Length"); e != g {
-			t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g)
-		}
-		if e, g := int64(0), res.ContentLength; e != g {
-			t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
-		}
-	}
-}
-
-// TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
-// on responses to HEAD requests.
-func TestTransportHeadChunkedResponse(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		if r.Method != "HEAD" {
-			panic("expected HEAD; got " + r.Method)
-		}
-		w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
-		w.Header().Set("x-client-ipport", r.RemoteAddr)
-		w.WriteHeader(200)
-	}))
-	defer ts.Close()
-
-	tr := &Transport{DisableKeepAlives: false}
-	c := &Client{Transport: tr}
-
-	res1, err := c.Head(ts.URL)
-	if err != nil {
-		t.Fatalf("request 1 error: %v", err)
-	}
-	res2, err := c.Head(ts.URL)
-	if err != nil {
-		t.Fatalf("request 2 error: %v", err)
-	}
-	if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
-		t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
-	}
-}
-
-func TestTransportNilURL(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		fmt.Fprintf(w, "Hi")
-	}))
-	defer ts.Close()
-
-	req := new(Request)
-	req.URL = nil // what we're actually testing
-	req.Method = "GET"
-	req.RawURL = ts.URL
-	req.Proto = "HTTP/1.1"
-	req.ProtoMajor = 1
-	req.ProtoMinor = 1
-	req.Header = make(Header)
-
-	tr := &Transport{}
-	res, err := tr.RoundTrip(req)
-	if err != nil {
-		t.Fatalf("unexpected RoundTrip error: %v", err)
-	}
-	body, err := ioutil.ReadAll(res.Body)
-	if g, e := string(body), "Hi"; g != e {
-		t.Fatalf("Expected response body of %q; got %q", e, g)
-	}
-}
-
-var roundTripTests = []struct {
-	accept       string
-	expectAccept string
-	compressed   bool
-}{
-	// Requests with no accept-encoding header use transparent compression
-	{"", "gzip", false},
-	// Requests with other accept-encoding should pass through unmodified
-	{"foo", "foo", false},
-	// Requests with accept-encoding == gzip should be passed through
-	{"gzip", "gzip", true}}
-
-// Test that the modification made to the Request by the RoundTripper is cleaned up
-func TestRoundTripGzip(t *testing.T) {
-	const responseBody = "test response body"
-	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
-		accept := req.Header.Get("Accept-Encoding")
-		if expect := req.FormValue("expect_accept"); accept != expect {
-			t.Errorf("Accept-Encoding = %q, want %q", accept, expect)
-		}
-		if accept == "gzip" {
-			rw.Header().Set("Content-Encoding", "gzip")
-			gz, _ := gzip.NewWriter(rw)
-			gz.Write([]byte(responseBody))
-			gz.Close()
-		} else {
-			rw.Header().Set("Content-Encoding", accept)
-			rw.Write([]byte(responseBody))
-		}
-	}))
-	defer ts.Close()
-
-	for i, test := range roundTripTests {
-		// Test basic request (no accept-encoding)
-		req, _ := NewRequest("GET", ts.URL+"?expect_accept="+test.expectAccept, nil)
-		req.Header.Set("Accept-Encoding", test.accept)
-		res, err := DefaultTransport.RoundTrip(req)
-		var body []byte
-		if test.compressed {
-			gzip, _ := gzip.NewReader(res.Body)
-			body, err = ioutil.ReadAll(gzip)
-			res.Body.Close()
-		} else {
-			body, err = ioutil.ReadAll(res.Body)
-		}
-		if err != nil {
-			t.Errorf("%d. Error: %q", i, err)
-		} else {
-			if g, e := string(body), responseBody; g != e {
-				t.Errorf("%d. body = %q; want %q", i, g, e)
-			}
-			if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e {
-				t.Errorf("%d. Accept-Encoding = %q; want %q", i, g, e)
-			}
-			if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e {
-				t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e)
-			}
-		}
-	}
-
-}
-
-func TestTransportGzip(t *testing.T) {
-	const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-	const nRandBytes = 1024 * 1024
-	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
-		if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e {
-			t.Errorf("Accept-Encoding = %q, want %q", g, e)
-		}
-		rw.Header().Set("Content-Encoding", "gzip")
-		if req.Method == "HEAD" {
-			return
-		}
-
-		var w io.Writer = rw
-		var buf bytes.Buffer
-		if req.FormValue("chunked") == "0" {
-			w = &buf
-			defer io.Copy(rw, &buf)
-			defer func() {
-				rw.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
-			}()
-		}
-		gz, _ := gzip.NewWriter(w)
-		gz.Write([]byte(testString))
-		if req.FormValue("body") == "large" {
-			io.Copyn(gz, rand.Reader, nRandBytes)
-		}
-		gz.Close()
-	}))
-	defer ts.Close()
-
-	for _, chunked := range []string{"1", "0"} {
-		c := &Client{Transport: &Transport{}}
-
-		// First fetch something large, but only read some of it.
-		res, err := c.Get(ts.URL + "?body=large&chunked=" + chunked)
-		if err != nil {
-			t.Fatalf("large get: %v", err)
-		}
-		buf := make([]byte, len(testString))
-		n, err := io.ReadFull(res.Body, buf)
-		if err != nil {
-			t.Fatalf("partial read of large response: size=%d, %v", n, err)
-		}
-		if e, g := testString, string(buf); e != g {
-			t.Errorf("partial read got %q, expected %q", g, e)
-		}
-		res.Body.Close()
-		// Read on the body, even though it's closed
-		n, err = res.Body.Read(buf)
-		if n != 0 || err == nil {
-			t.Errorf("expected error post-closed large Read; got = %d, %v", n, err)
-		}
-
-		// Then something small.
-		res, err = c.Get(ts.URL + "?chunked=" + chunked)
-		if err != nil {
-			t.Fatal(err)
-		}
-		body, err := ioutil.ReadAll(res.Body)
-		if err != nil {
-			t.Fatal(err)
-		}
-		if g, e := string(body), testString; g != e {
-			t.Fatalf("body = %q; want %q", g, e)
-		}
-		if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
-			t.Fatalf("Content-Encoding = %q; want %q", g, e)
-		}
-
-		// Read on the body after it's been fully read:
-		n, err = res.Body.Read(buf)
-		if n != 0 || err == nil {
-			t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err)
-		}
-		res.Body.Close()
-		n, err = res.Body.Read(buf)
-		if n != 0 || err == nil {
-			t.Errorf("expected Read error after Close; got %d, %v", n, err)
-		}
-	}
-
-	// And a HEAD request too, because they're always weird.
-	c := &Client{Transport: &Transport{}}
-	res, err := c.Head(ts.URL)
-	if err != nil {
-		t.Fatalf("Head: %v", err)
-	}
-	if res.StatusCode != 200 {
-		t.Errorf("Head status=%d; want=200", res.StatusCode)
-	}
-}
-
-func TestTransportProxy(t *testing.T) {
-	ch := make(chan string, 1)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		ch <- "real server"
-	}))
-	defer ts.Close()
-	proxy := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		ch <- "proxy for " + r.URL.String()
-	}))
-	defer proxy.Close()
-
-	pu, err := url.Parse(proxy.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	c := &Client{Transport: &Transport{Proxy: ProxyURL(pu)}}
-	c.Head(ts.URL)
-	got := <-ch
-	want := "proxy for " + ts.URL + "/"
-	if got != want {
-		t.Errorf("want %q, got %q", want, got)
-	}
-}
-
-// TestTransportGzipRecursive sends a gzip quine and checks that the
-// client gets the same value back. This is more cute than anything,
-// but checks that we don't recurse forever, and checks that
-// Content-Encoding is removed.
-func TestTransportGzipRecursive(t *testing.T) {
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header().Set("Content-Encoding", "gzip")
-		w.Write(rgz)
-	}))
-	defer ts.Close()
-
-	c := &Client{Transport: &Transport{}}
-	res, err := c.Get(ts.URL)
-	if err != nil {
-		t.Fatal(err)
-	}
-	body, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !bytes.Equal(body, rgz) {
-		t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x",
-			body, rgz)
-	}
-	if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
-		t.Fatalf("Content-Encoding = %q; want %q", g, e)
-	}
-}
-
-type fooProto struct{}
-
-func (fooProto) RoundTrip(req *Request) (*Response, os.Error) {
-	res := &Response{
-		Status:     "200 OK",
-		StatusCode: 200,
-		Header:     make(Header),
-		Body:       ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())),
-	}
-	return res, nil
-}
-
-func TestTransportAltProto(t *testing.T) {
-	tr := &Transport{}
-	c := &Client{Transport: tr}
-	tr.RegisterProtocol("foo", fooProto{})
-	res, err := c.Get("foo://bar.com/path")
-	if err != nil {
-		t.Fatal(err)
-	}
-	bodyb, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Fatal(err)
-	}
-	body := string(bodyb)
-	if e := "You wanted foo://bar.com/path"; body != e {
-		t.Errorf("got response %q, want %q", body, e)
-	}
-}
-
-// rgz is a gzip quine that uncompresses to itself.
-var rgz = []byte{
-	0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73,
-	0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0,
-	0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2,
-	0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17,
-	0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60,
-	0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2,
-	0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00,
-	0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00,
-	0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16,
-	0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05,
-	0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff,
-	0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00,
-	0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00,
-	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
-	0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88,
-	0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff,
-	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00,
-	0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00,
-	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
-	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
-	0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff,
-	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00,
-	0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
-	0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16,
-	0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08,
-	0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa,
-	0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06,
-	0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00,
-	0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
-	0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
-	0x00, 0x00,
-}
diff --git a/src/pkg/http/triv.go b/src/pkg/http/triv.go
deleted file mode 100644
index a8fd99a..0000000
--- a/src/pkg/http/triv.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-	"bytes"
-	"expvar"
-	"flag"
-	"fmt"
-	"http"
-	"io"
-	"log"
-	"os"
-	"strconv"
-)
-
-// hello world, the web server
-var helloRequests = expvar.NewInt("hello-requests")
-
-func HelloServer(w http.ResponseWriter, req *http.Request) {
-	helloRequests.Add(1)
-	io.WriteString(w, "hello, world!\n")
-}
-
-// Simple counter server. POSTing to it will set the value.
-type Counter struct {
-	n int
-}
-
-// This makes Counter satisfy the expvar.Var interface, so we can export
-// it directly.
-func (ctr *Counter) String() string { return fmt.Sprintf("%d", ctr.n) }
-
-func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
-	switch req.Method {
-	case "GET":
-		ctr.n++
-	case "POST":
-		buf := new(bytes.Buffer)
-		io.Copy(buf, req.Body)
-		body := buf.String()
-		if n, err := strconv.Atoi(body); err != nil {
-			fmt.Fprintf(w, "bad POST: %v\nbody: [%v]\n", err, body)
-		} else {
-			ctr.n = n
-			fmt.Fprint(w, "counter reset\n")
-		}
-	}
-	fmt.Fprintf(w, "counter = %d\n", ctr.n)
-}
-
-// simple flag server
-var booleanflag = flag.Bool("boolean", true, "another flag for testing")
-
-func FlagServer(w http.ResponseWriter, req *http.Request) {
-	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-	fmt.Fprint(w, "Flags:\n")
-	flag.VisitAll(func(f *flag.Flag) {
-		if f.Value.String() != f.DefValue {
-			fmt.Fprintf(w, "%s = %s [default = %s]\n", f.Name, f.Value.String(), f.DefValue)
-		} else {
-			fmt.Fprintf(w, "%s = %s\n", f.Name, f.Value.String())
-		}
-	})
-}
-
-// simple argument server
-func ArgServer(w http.ResponseWriter, req *http.Request) {
-	for _, s := range os.Args {
-		fmt.Fprint(w, s, " ")
-	}
-}
-
-// a channel (just for the fun of it)
-type Chan chan int
-
-func ChanCreate() Chan {
-	c := make(Chan)
-	go func(c Chan) {
-		for x := 0; ; x++ {
-			c <- x
-		}
-	}(c)
-	return c
-}
-
-func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) {
-	io.WriteString(w, fmt.Sprintf("channel send #%d\n", <-ch))
-}
-
-// exec a program, redirecting output
-func DateServer(rw http.ResponseWriter, req *http.Request) {
-	rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
-	r, w, err := os.Pipe()
-	if err != nil {
-		fmt.Fprintf(rw, "pipe: %s\n", err)
-		return
-	}
-
-	p, err := os.StartProcess("/bin/date", []string{"date"}, &os.ProcAttr{Files: []*os.File{nil, w, w}})
-	defer r.Close()
-	w.Close()
-	if err != nil {
-		fmt.Fprintf(rw, "fork/exec: %s\n", err)
-		return
-	}
-	defer p.Release()
-	io.Copy(rw, r)
-	wait, err := p.Wait(0)
-	if err != nil {
-		fmt.Fprintf(rw, "wait: %s\n", err)
-		return
-	}
-	if !wait.Exited() || wait.ExitStatus() != 0 {
-		fmt.Fprintf(rw, "date: %v\n", wait)
-		return
-	}
-}
-
-func Logger(w http.ResponseWriter, req *http.Request) {
-	log.Print(req.URL.Raw)
-	w.WriteHeader(404)
-	w.Write([]byte("oops"))
-}
-
-var webroot = flag.String("root", "/home/rsc", "web root directory")
-
-func main() {
-	flag.Parse()
-
-	// The counter is published as a variable directly.
-	ctr := new(Counter)
-	http.Handle("/counter", ctr)
-	expvar.Publish("counter", ctr)
-
-	http.Handle("/", http.HandlerFunc(Logger))
-	http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot))))
-	http.Handle("/flags", http.HandlerFunc(FlagServer))
-	http.Handle("/args", http.HandlerFunc(ArgServer))
-	http.Handle("/go/hello", http.HandlerFunc(HelloServer))
-	http.Handle("/chan", ChanCreate())
-	http.Handle("/date", http.HandlerFunc(DateServer))
-	err := http.ListenAndServe(":12345", nil)
-	if err != nil {
-		log.Panicln("ListenAndServe:", err)
-	}
-}
diff --git a/src/pkg/image/Makefile b/src/pkg/image/Makefile
index 739ad80..7c995d9 100644
--- a/src/pkg/image/Makefile
+++ b/src/pkg/image/Makefile
@@ -6,10 +6,10 @@ include ../../Make.inc
 
 TARG=image
 GOFILES=\
-	color.go\
 	format.go\
 	geom.go\
 	image.go\
 	names.go\
+	ycbcr.go\
 
 include ../../Make.pkg
diff --git a/src/pkg/image/bmp/reader.go b/src/pkg/image/bmp/reader.go
index 6bf4b1d..58bd781 100644
--- a/src/pkg/image/bmp/reader.go
+++ b/src/pkg/image/bmp/reader.go
@@ -8,14 +8,15 @@
 package bmp
 
 import (
+	"errors"
 	"image"
+	"image/color"
 	"io"
-	"os"
 )
 
 // ErrUnsupported means that the input BMP image uses a valid but unsupported
 // feature.
-var ErrUnsupported = os.NewError("bmp: unsupported BMP image")
+var ErrUnsupported = errors.New("bmp: unsupported BMP image")
 
 func readUint16(b []byte) uint16 {
 	return uint16(b[0]) | uint16(b[1])<<8
@@ -26,9 +27,9 @@ func readUint32(b []byte) uint32 {
 }
 
 // decodePaletted reads an 8 bit-per-pixel BMP image from r.
-func decodePaletted(r io.Reader, c image.Config) (image.Image, os.Error) {
+func decodePaletted(r io.Reader, c image.Config) (image.Image, error) {
 	var tmp [4]byte
-	paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(image.PalettedColorModel))
+	paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
 	// BMP images are stored bottom-up rather than top-down.
 	for y := c.Height - 1; y >= 0; y-- {
 		p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
@@ -48,7 +49,7 @@ func decodePaletted(r io.Reader, c image.Config) (image.Image, os.Error) {
 }
 
 // decodeRGBA reads a 24 bit-per-pixel BMP image from r.
-func decodeRGBA(r io.Reader, c image.Config) (image.Image, os.Error) {
+func decodeRGBA(r io.Reader, c image.Config) (image.Image, error) {
 	rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
 	// There are 3 bytes per pixel, and each row is 4-byte aligned.
 	b := make([]byte, (3*c.Width+3)&^3)
@@ -72,12 +73,12 @@ func decodeRGBA(r io.Reader, c image.Config) (image.Image, os.Error) {
 
 // Decode reads a BMP image from r and returns it as an image.Image.
 // Limitation: The file must be 8 or 24 bits per pixel.
-func Decode(r io.Reader) (image.Image, os.Error) {
+func Decode(r io.Reader) (image.Image, error) {
 	c, err := DecodeConfig(r)
 	if err != nil {
 		return nil, err
 	}
-	if c.ColorModel == image.RGBAColorModel {
+	if c.ColorModel == color.RGBAModel {
 		return decodeRGBA(r, c)
 	}
 	return decodePaletted(r, c)
@@ -86,7 +87,7 @@ func Decode(r io.Reader) (image.Image, os.Error) {
 // DecodeConfig returns the color model and dimensions of a BMP image without
 // decoding the entire image.
 // Limitation: The file must be 8 or 24 bits per pixel.
-func DecodeConfig(r io.Reader) (config image.Config, err os.Error) {
+func DecodeConfig(r io.Reader) (config image.Config, err error) {
 	// We only support those BMP images that are a BITMAPFILEHEADER
 	// immediately followed by a BITMAPINFOHEADER.
 	const (
@@ -98,7 +99,7 @@ func DecodeConfig(r io.Reader) (config image.Config, err os.Error) {
 		return
 	}
 	if string(b[:2]) != "BM" {
-		err = os.NewError("bmp: invalid format")
+		err = errors.New("bmp: invalid format")
 		return
 	}
 	offset := readUint32(b[10:14])
@@ -128,11 +129,11 @@ func DecodeConfig(r io.Reader) (config image.Config, err os.Error) {
 		if err != nil {
 			return
 		}
-		pcm := make(image.PalettedColorModel, 256)
+		pcm := make(color.Palette, 256)
 		for i := range pcm {
 			// BMP images are stored in BGR order rather than RGB order.
 			// Every 4th byte is padding.
-			pcm[i] = image.RGBAColor{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
+			pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
 		}
 		return image.Config{pcm, width, height}, nil
 	case 24:
@@ -140,7 +141,7 @@ func DecodeConfig(r io.Reader) (config image.Config, err os.Error) {
 			err = ErrUnsupported
 			return
 		}
-		return image.Config{image.RGBAColorModel, width, height}, nil
+		return image.Config{color.RGBAModel, width, height}, nil
 	}
 	err = ErrUnsupported
 	return
diff --git a/src/pkg/image/color.go b/src/pkg/image/color.go
deleted file mode 100644
index 501a882..0000000
--- a/src/pkg/image/color.go
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package image
-
-// Color can convert itself to alpha-premultiplied RGBA, with a possible loss
-// of precision. Each value ranges within [0, 0xFFFF], but is represented by a
-// uint32 so that multiplying by a blend factor up to 0xFFFF will not overflow.
-type Color interface {
-	RGBA() (r, g, b, a uint32)
-}
-
-// RGBAColor represents a traditional 32-bit alpha-premultiplied color,
-// having 8 bits for each of red, green, blue and alpha.
-type RGBAColor struct {
-	R, G, B, A uint8
-}
-
-func (c RGBAColor) RGBA() (r, g, b, a uint32) {
-	r = uint32(c.R)
-	r |= r << 8
-	g = uint32(c.G)
-	g |= g << 8
-	b = uint32(c.B)
-	b |= b << 8
-	a = uint32(c.A)
-	a |= a << 8
-	return
-}
-
-// RGBA64Color represents a 64-bit alpha-premultiplied color,
-// having 16 bits for each of red, green, blue and alpha.
-type RGBA64Color struct {
-	R, G, B, A uint16
-}
-
-func (c RGBA64Color) RGBA() (r, g, b, a uint32) {
-	return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
-}
-
-// NRGBAColor represents a non-alpha-premultiplied 32-bit color.
-type NRGBAColor struct {
-	R, G, B, A uint8
-}
-
-func (c NRGBAColor) RGBA() (r, g, b, a uint32) {
-	r = uint32(c.R)
-	r |= r << 8
-	r *= uint32(c.A)
-	r /= 0xff
-	g = uint32(c.G)
-	g |= g << 8
-	g *= uint32(c.A)
-	g /= 0xff
-	b = uint32(c.B)
-	b |= b << 8
-	b *= uint32(c.A)
-	b /= 0xff
-	a = uint32(c.A)
-	a |= a << 8
-	return
-}
-
-// NRGBA64Color represents a non-alpha-premultiplied 64-bit color,
-// having 16 bits for each of red, green, blue and alpha.
-type NRGBA64Color struct {
-	R, G, B, A uint16
-}
-
-func (c NRGBA64Color) RGBA() (r, g, b, a uint32) {
-	r = uint32(c.R)
-	r *= uint32(c.A)
-	r /= 0xffff
-	g = uint32(c.G)
-	g *= uint32(c.A)
-	g /= 0xffff
-	b = uint32(c.B)
-	b *= uint32(c.A)
-	b /= 0xffff
-	a = uint32(c.A)
-	return
-}
-
-// AlphaColor represents an 8-bit alpha.
-type AlphaColor struct {
-	A uint8
-}
-
-func (c AlphaColor) RGBA() (r, g, b, a uint32) {
-	a = uint32(c.A)
-	a |= a << 8
-	return a, a, a, a
-}
-
-// Alpha16Color represents a 16-bit alpha.
-type Alpha16Color struct {
-	A uint16
-}
-
-func (c Alpha16Color) RGBA() (r, g, b, a uint32) {
-	a = uint32(c.A)
-	return a, a, a, a
-}
-
-// GrayColor represents an 8-bit grayscale color.
-type GrayColor struct {
-	Y uint8
-}
-
-func (c GrayColor) RGBA() (r, g, b, a uint32) {
-	y := uint32(c.Y)
-	y |= y << 8
-	return y, y, y, 0xffff
-}
-
-// Gray16Color represents a 16-bit grayscale color.
-type Gray16Color struct {
-	Y uint16
-}
-
-func (c Gray16Color) RGBA() (r, g, b, a uint32) {
-	y := uint32(c.Y)
-	return y, y, y, 0xffff
-}
-
-// ColorModel can convert foreign Colors, with a possible loss of precision,
-// to a Color from its own color model.
-type ColorModel interface {
-	Convert(c Color) Color
-}
-
-// The ColorModelFunc type is an adapter to allow the use of an ordinary
-// color conversion function as a ColorModel.  If f is such a function,
-// ColorModelFunc(f) is a ColorModel object that invokes f to implement
-// the conversion.
-type ColorModelFunc func(Color) Color
-
-func (f ColorModelFunc) Convert(c Color) Color {
-	return f(c)
-}
-
-func toRGBAColor(c Color) Color {
-	if _, ok := c.(RGBAColor); ok {
-		return c
-	}
-	r, g, b, a := c.RGBA()
-	return RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
-}
-
-func toRGBA64Color(c Color) Color {
-	if _, ok := c.(RGBA64Color); ok {
-		return c
-	}
-	r, g, b, a := c.RGBA()
-	return RGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
-}
-
-func toNRGBAColor(c Color) Color {
-	if _, ok := c.(NRGBAColor); ok {
-		return c
-	}
-	r, g, b, a := c.RGBA()
-	if a == 0xffff {
-		return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
-	}
-	if a == 0 {
-		return NRGBAColor{0, 0, 0, 0}
-	}
-	// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
-	r = (r * 0xffff) / a
-	g = (g * 0xffff) / a
-	b = (b * 0xffff) / a
-	return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
-}
-
-func toNRGBA64Color(c Color) Color {
-	if _, ok := c.(NRGBA64Color); ok {
-		return c
-	}
-	r, g, b, a := c.RGBA()
-	if a == 0xffff {
-		return NRGBA64Color{uint16(r), uint16(g), uint16(b), 0xffff}
-	}
-	if a == 0 {
-		return NRGBA64Color{0, 0, 0, 0}
-	}
-	// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
-	r = (r * 0xffff) / a
-	g = (g * 0xffff) / a
-	b = (b * 0xffff) / a
-	return NRGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
-}
-
-func toAlphaColor(c Color) Color {
-	if _, ok := c.(AlphaColor); ok {
-		return c
-	}
-	_, _, _, a := c.RGBA()
-	return AlphaColor{uint8(a >> 8)}
-}
-
-func toAlpha16Color(c Color) Color {
-	if _, ok := c.(Alpha16Color); ok {
-		return c
-	}
-	_, _, _, a := c.RGBA()
-	return Alpha16Color{uint16(a)}
-}
-
-func toGrayColor(c Color) Color {
-	if _, ok := c.(GrayColor); ok {
-		return c
-	}
-	r, g, b, _ := c.RGBA()
-	y := (299*r + 587*g + 114*b + 500) / 1000
-	return GrayColor{uint8(y >> 8)}
-}
-
-func toGray16Color(c Color) Color {
-	if _, ok := c.(Gray16Color); ok {
-		return c
-	}
-	r, g, b, _ := c.RGBA()
-	y := (299*r + 587*g + 114*b + 500) / 1000
-	return Gray16Color{uint16(y)}
-}
-
-// The ColorModel associated with RGBAColor.
-var RGBAColorModel ColorModel = ColorModelFunc(toRGBAColor)
-
-// The ColorModel associated with RGBA64Color.
-var RGBA64ColorModel ColorModel = ColorModelFunc(toRGBA64Color)
-
-// The ColorModel associated with NRGBAColor.
-var NRGBAColorModel ColorModel = ColorModelFunc(toNRGBAColor)
-
-// The ColorModel associated with NRGBA64Color.
-var NRGBA64ColorModel ColorModel = ColorModelFunc(toNRGBA64Color)
-
-// The ColorModel associated with AlphaColor.
-var AlphaColorModel ColorModel = ColorModelFunc(toAlphaColor)
-
-// The ColorModel associated with Alpha16Color.
-var Alpha16ColorModel ColorModel = ColorModelFunc(toAlpha16Color)
-
-// The ColorModel associated with GrayColor.
-var GrayColorModel ColorModel = ColorModelFunc(toGrayColor)
-
-// The ColorModel associated with Gray16Color.
-var Gray16ColorModel ColorModel = ColorModelFunc(toGray16Color)
diff --git a/src/pkg/image/color/Makefile b/src/pkg/image/color/Makefile
new file mode 100644
index 0000000..94b4e39
--- /dev/null
+++ b/src/pkg/image/color/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=image/color
+GOFILES=\
+	color.go\
+	ycbcr.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/image/color/color.go b/src/pkg/image/color/color.go
new file mode 100644
index 0000000..29a7b8a
--- /dev/null
+++ b/src/pkg/image/color/color.go
@@ -0,0 +1,303 @@
+// Copyright 2011 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 color implements a basic color library.
+package color
+
+// Color can convert itself to alpha-premultiplied 16-bits per channel RGBA.
+// The conversion may be lossy.
+type Color interface {
+	// RGBA returns the alpha-premultiplied red, green, blue and alpha values
+	// for the color. Each value ranges within [0, 0xFFFF], but is represented
+	// by a uint32 so that multiplying by a blend factor up to 0xFFFF will not
+	// overflow.
+	RGBA() (r, g, b, a uint32)
+}
+
+// RGBA represents a traditional 32-bit alpha-premultiplied color,
+// having 8 bits for each of red, green, blue and alpha.
+type RGBA struct {
+	R, G, B, A uint8
+}
+
+func (c RGBA) RGBA() (r, g, b, a uint32) {
+	r = uint32(c.R)
+	r |= r << 8
+	g = uint32(c.G)
+	g |= g << 8
+	b = uint32(c.B)
+	b |= b << 8
+	a = uint32(c.A)
+	a |= a << 8
+	return
+}
+
+// RGBA64 represents a 64-bit alpha-premultiplied color,
+// having 16 bits for each of red, green, blue and alpha.
+type RGBA64 struct {
+	R, G, B, A uint16
+}
+
+func (c RGBA64) RGBA() (r, g, b, a uint32) {
+	return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
+}
+
+// NRGBA represents a non-alpha-premultiplied 32-bit color.
+type NRGBA struct {
+	R, G, B, A uint8
+}
+
+func (c NRGBA) RGBA() (r, g, b, a uint32) {
+	r = uint32(c.R)
+	r |= r << 8
+	r *= uint32(c.A)
+	r /= 0xff
+	g = uint32(c.G)
+	g |= g << 8
+	g *= uint32(c.A)
+	g /= 0xff
+	b = uint32(c.B)
+	b |= b << 8
+	b *= uint32(c.A)
+	b /= 0xff
+	a = uint32(c.A)
+	a |= a << 8
+	return
+}
+
+// NRGBA64 represents a non-alpha-premultiplied 64-bit color,
+// having 16 bits for each of red, green, blue and alpha.
+type NRGBA64 struct {
+	R, G, B, A uint16
+}
+
+func (c NRGBA64) RGBA() (r, g, b, a uint32) {
+	r = uint32(c.R)
+	r *= uint32(c.A)
+	r /= 0xffff
+	g = uint32(c.G)
+	g *= uint32(c.A)
+	g /= 0xffff
+	b = uint32(c.B)
+	b *= uint32(c.A)
+	b /= 0xffff
+	a = uint32(c.A)
+	return
+}
+
+// Alpha represents an 8-bit alpha color.
+type Alpha struct {
+	A uint8
+}
+
+func (c Alpha) RGBA() (r, g, b, a uint32) {
+	a = uint32(c.A)
+	a |= a << 8
+	return a, a, a, a
+}
+
+// Alpha16 represents a 16-bit alpha color.
+type Alpha16 struct {
+	A uint16
+}
+
+func (c Alpha16) RGBA() (r, g, b, a uint32) {
+	a = uint32(c.A)
+	return a, a, a, a
+}
+
+// Gray represents an 8-bit grayscale color.
+type Gray struct {
+	Y uint8
+}
+
+func (c Gray) RGBA() (r, g, b, a uint32) {
+	y := uint32(c.Y)
+	y |= y << 8
+	return y, y, y, 0xffff
+}
+
+// Gray16 represents a 16-bit grayscale color.
+type Gray16 struct {
+	Y uint16
+}
+
+func (c Gray16) RGBA() (r, g, b, a uint32) {
+	y := uint32(c.Y)
+	return y, y, y, 0xffff
+}
+
+// Model can convert any Color to one from its own color model. The conversion
+// may be lossy.
+type Model interface {
+	Convert(c Color) Color
+}
+
+// ModelFunc returns a Model that invokes f to implement the conversion.
+func ModelFunc(f func(Color) Color) Model {
+	// Note: using *modelFunc as the implementation
+	// means that callers can still use comparisons
+	// like m == RGBAModel.  This is not possible if
+	// we use the func value directly, because funcs
+	// are no longer comparable.
+	return &modelFunc{f}
+}
+
+type modelFunc struct {
+	f func(Color) Color
+}
+
+func (m *modelFunc) Convert(c Color) Color {
+	return m.f(c)
+}
+
+// Models for the standard color types.
+var (
+	RGBAModel    Model = ModelFunc(rgbaModel)
+	RGBA64Model  Model = ModelFunc(rgba64Model)
+	NRGBAModel   Model = ModelFunc(nrgbaModel)
+	NRGBA64Model Model = ModelFunc(nrgba64Model)
+	AlphaModel   Model = ModelFunc(alphaModel)
+	Alpha16Model Model = ModelFunc(alpha16Model)
+	GrayModel    Model = ModelFunc(grayModel)
+	Gray16Model  Model = ModelFunc(gray16Model)
+)
+
+func rgbaModel(c Color) Color {
+	if _, ok := c.(RGBA); ok {
+		return c
+	}
+	r, g, b, a := c.RGBA()
+	return RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
+}
+
+func rgba64Model(c Color) Color {
+	if _, ok := c.(RGBA64); ok {
+		return c
+	}
+	r, g, b, a := c.RGBA()
+	return RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
+func nrgbaModel(c Color) Color {
+	if _, ok := c.(NRGBA); ok {
+		return c
+	}
+	r, g, b, a := c.RGBA()
+	if a == 0xffff {
+		return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
+	}
+	if a == 0 {
+		return NRGBA{0, 0, 0, 0}
+	}
+	// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
+	r = (r * 0xffff) / a
+	g = (g * 0xffff) / a
+	b = (b * 0xffff) / a
+	return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
+}
+
+func nrgba64Model(c Color) Color {
+	if _, ok := c.(NRGBA64); ok {
+		return c
+	}
+	r, g, b, a := c.RGBA()
+	if a == 0xffff {
+		return NRGBA64{uint16(r), uint16(g), uint16(b), 0xffff}
+	}
+	if a == 0 {
+		return NRGBA64{0, 0, 0, 0}
+	}
+	// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
+	r = (r * 0xffff) / a
+	g = (g * 0xffff) / a
+	b = (b * 0xffff) / a
+	return NRGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
+func alphaModel(c Color) Color {
+	if _, ok := c.(Alpha); ok {
+		return c
+	}
+	_, _, _, a := c.RGBA()
+	return Alpha{uint8(a >> 8)}
+}
+
+func alpha16Model(c Color) Color {
+	if _, ok := c.(Alpha16); ok {
+		return c
+	}
+	_, _, _, a := c.RGBA()
+	return Alpha16{uint16(a)}
+}
+
+func grayModel(c Color) Color {
+	if _, ok := c.(Gray); ok {
+		return c
+	}
+	r, g, b, _ := c.RGBA()
+	y := (299*r + 587*g + 114*b + 500) / 1000
+	return Gray{uint8(y >> 8)}
+}
+
+func gray16Model(c Color) Color {
+	if _, ok := c.(Gray16); ok {
+		return c
+	}
+	r, g, b, _ := c.RGBA()
+	y := (299*r + 587*g + 114*b + 500) / 1000
+	return Gray16{uint16(y)}
+}
+
+// Palette is a palette of colors.
+type Palette []Color
+
+func diff(a, b uint32) uint32 {
+	if a > b {
+		return a - b
+	}
+	return b - a
+}
+
+// Convert returns the palette color closest to c in Euclidean R,G,B space.
+func (p Palette) Convert(c Color) Color {
+	if len(p) == 0 {
+		return nil
+	}
+	return p[p.Index(c)]
+}
+
+// Index returns the index of the palette color closest to c in Euclidean
+// R,G,B space.
+func (p Palette) Index(c Color) int {
+	cr, cg, cb, _ := c.RGBA()
+	// Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
+	cr >>= 1
+	cg >>= 1
+	cb >>= 1
+	ret, bestSSD := 0, uint32(1<<32-1)
+	for i, v := range p {
+		vr, vg, vb, _ := v.RGBA()
+		vr >>= 1
+		vg >>= 1
+		vb >>= 1
+		dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
+		ssd := (dr * dr) + (dg * dg) + (db * db)
+		if ssd < bestSSD {
+			if ssd == 0 {
+				return i
+			}
+			ret, bestSSD = i, ssd
+		}
+	}
+	return ret
+}
+
+// Standard colors.
+var (
+	Black       = Gray16{0}
+	White       = Gray16{0xffff}
+	Transparent = Alpha16{0}
+	Opaque      = Alpha16{0xffff}
+)
diff --git a/src/pkg/image/color/ycbcr.go b/src/pkg/image/color/ycbcr.go
new file mode 100644
index 0000000..4c2f29e
--- /dev/null
+++ b/src/pkg/image/color/ycbcr.go
@@ -0,0 +1,99 @@
+// Copyright 2011 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 color
+
+// RGBToYCbCr converts an RGB triple to a Y'CbCr triple.
+func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
+	// The JFIF specification says:
+	//	Y' =  0.2990*R + 0.5870*G + 0.1140*B
+	//	Cb = -0.1687*R - 0.3313*G + 0.5000*B + 128
+	//	Cr =  0.5000*R - 0.4187*G - 0.0813*B + 128
+	// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
+	r1 := int(r)
+	g1 := int(g)
+	b1 := int(b)
+	yy := (19595*r1 + 38470*g1 + 7471*b1 + 1<<15) >> 16
+	cb := (-11056*r1 - 21712*g1 + 32768*b1 + 257<<15) >> 16
+	cr := (32768*r1 - 27440*g1 - 5328*b1 + 257<<15) >> 16
+	if yy < 0 {
+		yy = 0
+	} else if yy > 255 {
+		yy = 255
+	}
+	if cb < 0 {
+		cb = 0
+	} else if cb > 255 {
+		cb = 255
+	}
+	if cr < 0 {
+		cr = 0
+	} else if cr > 255 {
+		cr = 255
+	}
+	return uint8(yy), uint8(cb), uint8(cr)
+}
+
+// YCbCrToRGB converts a Y'CbCr triple to an RGB triple.
+func YCbCrToRGB(y, cb, cr uint8) (uint8, uint8, uint8) {
+	// The JFIF specification says:
+	//	R = Y' + 1.40200*(Cr-128)
+	//	G = Y' - 0.34414*(Cb-128) - 0.71414*(Cr-128)
+	//	B = Y' + 1.77200*(Cb-128)
+	// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
+	yy1 := int(y)<<16 + 1<<15
+	cb1 := int(cb) - 128
+	cr1 := int(cr) - 128
+	r := (yy1 + 91881*cr1) >> 16
+	g := (yy1 - 22554*cb1 - 46802*cr1) >> 16
+	b := (yy1 + 116130*cb1) >> 16
+	if r < 0 {
+		r = 0
+	} else if r > 255 {
+		r = 255
+	}
+	if g < 0 {
+		g = 0
+	} else if g > 255 {
+		g = 255
+	}
+	if b < 0 {
+		b = 0
+	} else if b > 255 {
+		b = 255
+	}
+	return uint8(r), uint8(g), uint8(b)
+}
+
+// YCbCr represents a fully opaque 24-bit Y'CbCr color, having 8 bits each for
+// one luma and two chroma components.
+//
+// JPEG, VP8, the MPEG family and other codecs use this color model. Such
+// codecs often use the terms YUV and Y'CbCr interchangeably, but strictly
+// speaking, the term YUV applies only to analog video signals, and Y' (luma)
+// is Y (luminance) after applying gamma correction.
+//
+// Conversion between RGB and Y'CbCr is lossy and there are multiple, slightly
+// different formulae for converting between the two. This package follows
+// the JFIF specification at http://www.w3.org/Graphics/JPEG/jfif3.pdf.
+type YCbCr struct {
+	Y, Cb, Cr uint8
+}
+
+func (c YCbCr) RGBA() (uint32, uint32, uint32, uint32) {
+	r, g, b := YCbCrToRGB(c.Y, c.Cb, c.Cr)
+	return uint32(r) * 0x101, uint32(g) * 0x101, uint32(b) * 0x101, 0xffff
+}
+
+// YCbCrModel is the Model for Y'CbCr colors.
+var YCbCrModel Model = ModelFunc(yCbCrModel)
+
+func yCbCrModel(c Color) Color {
+	if _, ok := c.(YCbCr); ok {
+		return c
+	}
+	r, g, b, _ := c.RGBA()
+	y, u, v := RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
+	return YCbCr{y, u, v}
+}
diff --git a/src/pkg/image/color/ycbcr_test.go b/src/pkg/image/color/ycbcr_test.go
new file mode 100644
index 0000000..92a0e6f
--- /dev/null
+++ b/src/pkg/image/color/ycbcr_test.go
@@ -0,0 +1,33 @@
+// Copyright 2011 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 color
+
+import (
+	"testing"
+)
+
+func delta(x, y uint8) uint8 {
+	if x >= y {
+		return x - y
+	}
+	return y - x
+}
+
+// Test that a subset of RGB space can be converted to YCbCr and back to within
+// 1/256 tolerance.
+func TestRoundtrip(t *testing.T) {
+	for r := 0; r < 255; r += 7 {
+		for g := 0; g < 255; g += 5 {
+			for b := 0; b < 255; b += 3 {
+				r0, g0, b0 := uint8(r), uint8(g), uint8(b)
+				y, cb, cr := RGBToYCbCr(r0, g0, b0)
+				r1, g1, b1 := YCbCrToRGB(y, cb, cr)
+				if delta(r0, r1) > 1 || delta(g0, g1) > 1 || delta(b0, b1) > 1 {
+					t.Fatalf("r0, g0, b0 = %d, %d, %d   r1, g1, b1 = %d, %d, %d", r0, g0, b0, r1, g1, b1)
+				}
+			}
+		}
+	}
+}
diff --git a/src/pkg/image/decode_test.go b/src/pkg/image/decode_test.go
index 540d5ed..1b7db8b 100644
--- a/src/pkg/image/decode_test.go
+++ b/src/pkg/image/decode_test.go
@@ -7,6 +7,7 @@ package image_test
 import (
 	"bufio"
 	"image"
+	"image/color"
 	"os"
 	"testing"
 
@@ -40,7 +41,7 @@ var imageTests = []imageTest{
 	{"testdata/video-005.gray.png", "testdata/video-005.gray.png", 0},
 }
 
-func decode(filename string) (image.Image, string, os.Error) {
+func decode(filename string) (image.Image, string, error) {
 	f, err := os.Open(filename)
 	if err != nil {
 		return nil, "", err
@@ -49,7 +50,7 @@ func decode(filename string) (image.Image, string, os.Error) {
 	return image.Decode(bufio.NewReader(f))
 }
 
-func decodeConfig(filename string) (image.Config, string, os.Error) {
+func decodeConfig(filename string) (image.Config, string, error) {
 	f, err := os.Open(filename)
 	if err != nil {
 		return image.Config{}, "", err
@@ -66,7 +67,7 @@ func delta(u0, u1 uint32) int {
 	return d
 }
 
-func withinTolerance(c0, c1 image.Color, tolerance int) bool {
+func withinTolerance(c0, c1 color.Color, tolerance int) bool {
 	r0, g0, b0, a0 := c0.RGBA()
 	r1, g1, b1, a1 := c1.RGBA()
 	r := delta(r0, r1)
@@ -82,7 +83,7 @@ loop:
 	for _, it := range imageTests {
 		g := golden[it.goldenFilename]
 		if g == nil {
-			var err os.Error
+			var err error
 			g, _, err = decode(it.goldenFilename)
 			if err != nil {
 				t.Errorf("%s: %v", it.goldenFilename, err)
diff --git a/src/pkg/image/draw/bench_test.go b/src/pkg/image/draw/bench_test.go
index 0e5e324..4cd2095 100644
--- a/src/pkg/image/draw/bench_test.go
+++ b/src/pkg/image/draw/bench_test.go
@@ -6,7 +6,7 @@ package draw
 
 import (
 	"image"
-	"image/ycbcr"
+	"image/color"
 	"testing"
 )
 
@@ -18,16 +18,16 @@ const (
 // bench benchmarks drawing src and mask images onto a dst image with the
 // given op and the color models to create those images from.
 // The created images' pixels are initialized to non-zero values.
-func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
+func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) {
 	b.StopTimer()
 
 	var dst Image
 	switch dcm {
-	case image.RGBAColorModel:
+	case color.RGBAModel:
 		dst1 := image.NewRGBA(image.Rect(0, 0, dstw, dsth))
 		for y := 0; y < dsth; y++ {
 			for x := 0; x < dstw; x++ {
-				dst1.SetRGBA(x, y, image.RGBAColor{
+				dst1.SetRGBA(x, y, color.RGBA{
 					uint8(5 * x % 0x100),
 					uint8(7 * y % 0x100),
 					uint8((7*x + 5*y) % 0x100),
@@ -36,11 +36,11 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
 			}
 		}
 		dst = dst1
-	case image.RGBA64ColorModel:
+	case color.RGBA64Model:
 		dst1 := image.NewRGBA64(image.Rect(0, 0, dstw, dsth))
 		for y := 0; y < dsth; y++ {
 			for x := 0; x < dstw; x++ {
-				dst1.SetRGBA64(x, y, image.RGBA64Color{
+				dst1.SetRGBA64(x, y, color.RGBA64{
 					uint16(53 * x % 0x10000),
 					uint16(59 * y % 0x10000),
 					uint16((59*x + 53*y) % 0x10000),
@@ -50,18 +50,18 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
 		}
 		dst = dst1
 	default:
-		panic("unreachable")
+		b.Fatal("unknown destination color model", dcm)
 	}
 
 	var src image.Image
 	switch scm {
 	case nil:
-		src = &image.ColorImage{image.RGBAColor{0x11, 0x22, 0x33, 0xff}}
-	case image.RGBAColorModel:
+		src = &image.Uniform{color.RGBA{0x11, 0x22, 0x33, 0xff}}
+	case color.RGBAModel:
 		src1 := image.NewRGBA(image.Rect(0, 0, srcw, srch))
 		for y := 0; y < srch; y++ {
 			for x := 0; x < srcw; x++ {
-				src1.SetRGBA(x, y, image.RGBAColor{
+				src1.SetRGBA(x, y, color.RGBA{
 					uint8(13 * x % 0x80),
 					uint8(11 * y % 0x80),
 					uint8((11*x + 13*y) % 0x80),
@@ -70,11 +70,11 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
 			}
 		}
 		src = src1
-	case image.RGBA64ColorModel:
+	case color.RGBA64Model:
 		src1 := image.NewRGBA64(image.Rect(0, 0, srcw, srch))
 		for y := 0; y < srch; y++ {
 			for x := 0; x < srcw; x++ {
-				src1.SetRGBA64(x, y, image.RGBA64Color{
+				src1.SetRGBA64(x, y, color.RGBA64{
 					uint16(103 * x % 0x8000),
 					uint16(101 * y % 0x8000),
 					uint16((101*x + 103*y) % 0x8000),
@@ -83,11 +83,11 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
 			}
 		}
 		src = src1
-	case image.NRGBAColorModel:
+	case color.NRGBAModel:
 		src1 := image.NewNRGBA(image.Rect(0, 0, srcw, srch))
 		for y := 0; y < srch; y++ {
 			for x := 0; x < srcw; x++ {
-				src1.SetNRGBA(x, y, image.NRGBAColor{
+				src1.SetNRGBA(x, y, color.NRGBA{
 					uint8(13 * x % 0x100),
 					uint8(11 * y % 0x100),
 					uint8((11*x + 13*y) % 0x100),
@@ -96,7 +96,7 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
 			}
 		}
 		src = src1
-	case ycbcr.YCbCrColorModel:
+	case color.YCbCrModel:
 		yy := make([]uint8, srcw*srch)
 		cb := make([]uint8, srcw*srch)
 		cr := make([]uint8, srcw*srch)
@@ -105,24 +105,24 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
 			cb[i] = uint8(5 * i % 0x100)
 			cr[i] = uint8(7 * i % 0x100)
 		}
-		src = &ycbcr.YCbCr{
+		src = &image.YCbCr{
 			Y:              yy,
 			Cb:             cb,
 			Cr:             cr,
 			YStride:        srcw,
 			CStride:        srcw,
-			SubsampleRatio: ycbcr.SubsampleRatio444,
+			SubsampleRatio: image.YCbCrSubsampleRatio444,
 			Rect:           image.Rect(0, 0, srcw, srch),
 		}
 	default:
-		panic("unreachable")
+		b.Fatal("unknown source color model", scm)
 	}
 
 	var mask image.Image
 	switch mcm {
 	case nil:
 		// No-op.
-	case image.AlphaColorModel:
+	case color.AlphaModel:
 		mask1 := image.NewAlpha(image.Rect(0, 0, srcw, srch))
 		for y := 0; y < srch; y++ {
 			for x := 0; x < srcw; x++ {
@@ -130,13 +130,13 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
 				// Glyph masks are typically mostly zero,
 				// so we only set a quarter of mask1's pixels.
 				if a >= 0xc0 {
-					mask1.SetAlpha(x, y, image.AlphaColor{a})
+					mask1.SetAlpha(x, y, color.Alpha{a})
 				}
 			}
 		}
 		mask = mask1
 	default:
-		panic("unreachable")
+		b.Fatal("unknown mask color model", mcm)
 	}
 
 	b.StartTimer()
@@ -152,55 +152,55 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
 // The BenchmarkFoo functions exercise a drawFoo fast-path function in draw.go.
 
 func BenchmarkFillOver(b *testing.B) {
-	bench(b, image.RGBAColorModel, nil, nil, Over)
+	bench(b, color.RGBAModel, nil, nil, Over)
 }
 
 func BenchmarkFillSrc(b *testing.B) {
-	bench(b, image.RGBAColorModel, nil, nil, Src)
+	bench(b, color.RGBAModel, nil, nil, Src)
 }
 
 func BenchmarkCopyOver(b *testing.B) {
-	bench(b, image.RGBAColorModel, image.RGBAColorModel, nil, Over)
+	bench(b, color.RGBAModel, color.RGBAModel, nil, Over)
 }
 
 func BenchmarkCopySrc(b *testing.B) {
-	bench(b, image.RGBAColorModel, image.RGBAColorModel, nil, Src)
+	bench(b, color.RGBAModel, color.RGBAModel, nil, Src)
 }
 
 func BenchmarkNRGBAOver(b *testing.B) {
-	bench(b, image.RGBAColorModel, image.NRGBAColorModel, nil, Over)
+	bench(b, color.RGBAModel, color.NRGBAModel, nil, Over)
 }
 
 func BenchmarkNRGBASrc(b *testing.B) {
-	bench(b, image.RGBAColorModel, image.NRGBAColorModel, nil, Src)
+	bench(b, color.RGBAModel, color.NRGBAModel, nil, Src)
 }
 
 func BenchmarkYCbCr(b *testing.B) {
-	bench(b, image.RGBAColorModel, ycbcr.YCbCrColorModel, nil, Over)
+	bench(b, color.RGBAModel, color.YCbCrModel, nil, Over)
 }
 
 func BenchmarkGlyphOver(b *testing.B) {
-	bench(b, image.RGBAColorModel, nil, image.AlphaColorModel, Over)
+	bench(b, color.RGBAModel, nil, color.AlphaModel, Over)
 }
 
 func BenchmarkRGBA(b *testing.B) {
-	bench(b, image.RGBAColorModel, image.RGBA64ColorModel, nil, Src)
+	bench(b, color.RGBAModel, color.RGBA64Model, nil, Src)
 }
 
 // The BenchmarkGenericFoo functions exercise the generic, slow-path code.
 
 func BenchmarkGenericOver(b *testing.B) {
-	bench(b, image.RGBA64ColorModel, image.RGBA64ColorModel, nil, Over)
+	bench(b, color.RGBA64Model, color.RGBA64Model, nil, Over)
 }
 
 func BenchmarkGenericMaskOver(b *testing.B) {
-	bench(b, image.RGBA64ColorModel, image.RGBA64ColorModel, image.AlphaColorModel, Over)
+	bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Over)
 }
 
 func BenchmarkGenericSrc(b *testing.B) {
-	bench(b, image.RGBA64ColorModel, image.RGBA64ColorModel, nil, Src)
+	bench(b, color.RGBA64Model, color.RGBA64Model, nil, Src)
 }
 
 func BenchmarkGenericMaskSrc(b *testing.B) {
-	bench(b, image.RGBA64ColorModel, image.RGBA64ColorModel, image.AlphaColorModel, Src)
+	bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Src)
 }
diff --git a/src/pkg/image/draw/draw.go b/src/pkg/image/draw/draw.go
index a748ff8..3b6679f 100644
--- a/src/pkg/image/draw/draw.go
+++ b/src/pkg/image/draw/draw.go
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package draw provides image composition functions
-// in the style of the Plan 9 graphics library
-// (see http://plan9.bell-labs.com/magic/man2html/2/draw)
-// and the X Render extension.
+// Package draw provides image composition functions.
+//
+// See "The Go image/draw package" for an introduction to this package:
+// http://blog.golang.org/2011/09/go-imagedraw-package.html
 package draw
 
 import (
 	"image"
-	"image/ycbcr"
+	"image/color"
 )
 
 // m is the maximum color value returned by image.Color.RGBA.
@@ -26,12 +26,10 @@ const (
 	Src
 )
 
-var zeroColor image.Color = image.AlphaColor{0}
-
 // A draw.Image is an image.Image with a Set method to change a single pixel.
 type Image interface {
 	image.Image
-	Set(x, y int, c image.Color)
+	Set(x, y int, c color.Color)
 }
 
 // Draw calls DrawMask with a nil mask.
@@ -73,7 +71,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 		if op == Over {
 			if mask == nil {
 				switch src0 := src.(type) {
-				case *image.ColorImage:
+				case *image.Uniform:
 					drawFillOver(dst0, r, src0)
 					return
 				case *image.RGBA:
@@ -82,13 +80,13 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 				case *image.NRGBA:
 					drawNRGBAOver(dst0, r, src0, sp)
 					return
-				case *ycbcr.YCbCr:
+				case *image.YCbCr:
 					drawYCbCr(dst0, r, src0, sp)
 					return
 				}
 			} else if mask0, ok := mask.(*image.Alpha); ok {
 				switch src0 := src.(type) {
-				case *image.ColorImage:
+				case *image.Uniform:
 					drawGlyphOver(dst0, r, src0, mask0, mp)
 					return
 				}
@@ -96,7 +94,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 		} else {
 			if mask == nil {
 				switch src0 := src.(type) {
-				case *image.ColorImage:
+				case *image.Uniform:
 					drawFillSrc(dst0, r, src0)
 					return
 				case *image.RGBA:
@@ -105,7 +103,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 				case *image.NRGBA:
 					drawNRGBASrc(dst0, r, src0, sp)
 					return
-				case *ycbcr.YCbCr:
+				case *image.YCbCr:
 					drawYCbCr(dst0, r, src0, sp)
 					return
 				}
@@ -125,7 +123,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 		}
 	}
 
-	var out *image.RGBA64Color
+	var out *color.RGBA64
 	sy := sp.Y + y0 - r.Min.Y
 	my := mp.Y + y0 - r.Min.Y
 	for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
@@ -141,14 +139,14 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 				if op == Over {
 					// No-op.
 				} else {
-					dst.Set(x, y, zeroColor)
+					dst.Set(x, y, color.Transparent)
 				}
 			case ma == m && op == Src:
 				dst.Set(x, y, src.At(sx, sy))
 			default:
 				sr, sg, sb, sa := src.At(sx, sy).RGBA()
 				if out == nil {
-					out = new(image.RGBA64Color)
+					out = new(color.RGBA64)
 				}
 				if op == Over {
 					dr, dg, db, da := dst.At(x, y).RGBA()
@@ -169,11 +167,11 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
 	}
 }
 
-func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
+func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
 	sr, sg, sb, sa := src.RGBA()
 	// The 0x101 is here for the same reason as in drawRGBA.
 	a := (m - sa) * 0x101
-	i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
+	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
 	i1 := i0 + r.Dx()*4
 	for y := r.Min.Y; y != r.Max.Y; y++ {
 		for i := i0; i < i1; i += 4 {
@@ -192,12 +190,12 @@ func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
 	}
 }
 
-func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
+func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
 	sr, sg, sb, sa := src.RGBA()
 	// The built-in copy function is faster than a straightforward for loop to fill the destination with
 	// the color, but copy requires a slice source. We therefore use a for loop to fill the first row, and
 	// then use the first row as the slice source for the remaining rows.
-	i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
+	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
 	i1 := i0 + r.Dx()*4
 	for i := i0; i < i1; i += 4 {
 		dst.Pix[i+0] = uint8(sr >> 8)
@@ -215,8 +213,8 @@ func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
 
 func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
 	dx, dy := r.Dx(), r.Dy()
-	d0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
-	s0 := (sp.Y-src.Rect.Min.Y)*src.Stride + (sp.X-src.Rect.Min.X)*4
+	d0 := dst.PixOffset(r.Min.X, r.Min.Y)
+	s0 := src.PixOffset(sp.X, sp.Y)
 	var (
 		ddelta, sdelta int
 		i0, i1, idelta int
@@ -263,8 +261,8 @@ func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.
 
 func drawCopySrc(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
 	n, dy := 4*r.Dx(), r.Dy()
-	d0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
-	s0 := (sp.Y-src.Rect.Min.Y)*src.Stride + (sp.X-src.Rect.Min.X)*4
+	d0 := dst.PixOffset(r.Min.X, r.Min.Y)
+	s0 := src.PixOffset(sp.X, sp.Y)
 	var ddelta, sdelta int
 	if r.Min.Y <= sp.Y {
 		ddelta = dst.Stride
@@ -347,41 +345,36 @@ func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image
 	}
 }
 
-func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *ycbcr.YCbCr, sp image.Point) {
-	// A YCbCr image is always fully opaque, and so if the mask is implicitly nil
+func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) {
+	// An image.YCbCr is always fully opaque, and so if the mask is implicitly nil
 	// (i.e. fully opaque) then the op is effectively always Src.
-	var (
-		yy, cb, cr uint8
-	)
 	x0 := (r.Min.X - dst.Rect.Min.X) * 4
 	x1 := (r.Max.X - dst.Rect.Min.X) * 4
 	y0 := r.Min.Y - dst.Rect.Min.Y
 	y1 := r.Max.Y - dst.Rect.Min.Y
 	switch src.SubsampleRatio {
-	case ycbcr.SubsampleRatio422:
+	case image.YCbCrSubsampleRatio422:
 		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
 			dpix := dst.Pix[y*dst.Stride:]
-			for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
-				i := sx / 2
-				yy = src.Y[sy*src.YStride+sx]
-				cb = src.Cb[sy*src.CStride+i]
-				cr = src.Cr[sy*src.CStride+i]
-				rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
+			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
+			ciBase := (sy-src.Rect.Min.Y)*src.CStride - src.Rect.Min.X/2
+			for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
+				ci := ciBase + sx/2
+				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
 				dpix[x+0] = rr
 				dpix[x+1] = gg
 				dpix[x+2] = bb
 				dpix[x+3] = 255
 			}
 		}
-	case ycbcr.SubsampleRatio420:
+	case image.YCbCrSubsampleRatio420:
 		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
 			dpix := dst.Pix[y*dst.Stride:]
-			for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
-				i, j := sx/2, sy/2
-				yy = src.Y[sy*src.YStride+sx]
-				cb = src.Cb[j*src.CStride+i]
-				cr = src.Cr[j*src.CStride+i]
-				rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
+			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
+			ciBase := (sy/2-src.Rect.Min.Y/2)*src.CStride - src.Rect.Min.X/2
+			for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
+				ci := ciBase + sx/2
+				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
 				dpix[x+0] = rr
 				dpix[x+1] = gg
 				dpix[x+2] = bb
@@ -392,11 +385,10 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *ycbcr.YCbCr, sp image.Po
 		// Default to 4:4:4 subsampling.
 		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
 			dpix := dst.Pix[y*dst.Stride:]
-			for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
-				yy = src.Y[sy*src.YStride+sx]
-				cb = src.Cb[sy*src.CStride+sx]
-				cr = src.Cr[sy*src.CStride+sx]
-				rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
+			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
+			ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X)
+			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
+				rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
 				dpix[x+0] = rr
 				dpix[x+1] = gg
 				dpix[x+2] = bb
@@ -406,10 +398,10 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *ycbcr.YCbCr, sp image.Po
 	}
 }
 
-func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage, mask *image.Alpha, mp image.Point) {
-	i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
+func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {
+	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
 	i1 := i0 + r.Dx()*4
-	mi0 := (mp.Y-mask.Rect.Min.Y)*mask.Stride + mp.X - mask.Rect.Min.X
+	mi0 := mask.PixOffset(mp.X, mp.Y)
 	sr, sg, sb, sa := src.RGBA()
 	for y, my := r.Min.Y, mp.Y; y != r.Max.Y; y, my = y+1, my+1 {
 		for i, mi := i0, mi0; i < i1; i, mi = i+4, mi+1 {
@@ -453,7 +445,7 @@ func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Poin
 	sx0 := sp.X + x0 - r.Min.X
 	mx0 := mp.X + x0 - r.Min.X
 	sx1 := sx0 + (x1 - x0)
-	i0 := (y0-dst.Rect.Min.Y)*dst.Stride + (x0-dst.Rect.Min.X)*4
+	i0 := dst.PixOffset(x0, y0)
 	di := dx * 4
 	for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
 		for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
diff --git a/src/pkg/image/draw/draw_test.go b/src/pkg/image/draw/draw_test.go
index 7634c2e..56a4502 100644
--- a/src/pkg/image/draw/draw_test.go
+++ b/src/pkg/image/draw/draw_test.go
@@ -6,29 +6,29 @@ package draw
 
 import (
 	"image"
-	"image/ycbcr"
+	"image/color"
 	"testing"
 )
 
-func eq(c0, c1 image.Color) bool {
+func eq(c0, c1 color.Color) bool {
 	r0, g0, b0, a0 := c0.RGBA()
 	r1, g1, b1, a1 := c1.RGBA()
 	return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
 }
 
 func fillBlue(alpha int) image.Image {
-	return image.NewColorImage(image.RGBAColor{0, 0, uint8(alpha), uint8(alpha)})
+	return image.NewUniform(color.RGBA{0, 0, uint8(alpha), uint8(alpha)})
 }
 
 func fillAlpha(alpha int) image.Image {
-	return image.NewColorImage(image.AlphaColor{uint8(alpha)})
+	return image.NewUniform(color.Alpha{uint8(alpha)})
 }
 
 func vgradGreen(alpha int) image.Image {
 	m := image.NewRGBA(image.Rect(0, 0, 16, 16))
 	for y := 0; y < 16; y++ {
 		for x := 0; x < 16; x++ {
-			m.Set(x, y, image.RGBAColor{0, uint8(y * alpha / 15), 0, uint8(alpha)})
+			m.Set(x, y, color.RGBA{0, uint8(y * alpha / 15), 0, uint8(alpha)})
 		}
 	}
 	return m
@@ -38,7 +38,7 @@ func vgradAlpha(alpha int) image.Image {
 	m := image.NewAlpha(image.Rect(0, 0, 16, 16))
 	for y := 0; y < 16; y++ {
 		for x := 0; x < 16; x++ {
-			m.Set(x, y, image.AlphaColor{uint8(y * alpha / 15)})
+			m.Set(x, y, color.Alpha{uint8(y * alpha / 15)})
 		}
 	}
 	return m
@@ -48,20 +48,20 @@ func vgradGreenNRGBA(alpha int) image.Image {
 	m := image.NewNRGBA(image.Rect(0, 0, 16, 16))
 	for y := 0; y < 16; y++ {
 		for x := 0; x < 16; x++ {
-			m.Set(x, y, image.RGBAColor{0, uint8(y * 0x11), 0, uint8(alpha)})
+			m.Set(x, y, color.RGBA{0, uint8(y * 0x11), 0, uint8(alpha)})
 		}
 	}
 	return m
 }
 
 func vgradCr() image.Image {
-	m := &ycbcr.YCbCr{
+	m := &image.YCbCr{
 		Y:              make([]byte, 16*16),
 		Cb:             make([]byte, 16*16),
 		Cr:             make([]byte, 16*16),
 		YStride:        16,
 		CStride:        16,
-		SubsampleRatio: ycbcr.SubsampleRatio444,
+		SubsampleRatio: image.YCbCrSubsampleRatio444,
 		Rect:           image.Rect(0, 0, 16, 16),
 	}
 	for y := 0; y < 16; y++ {
@@ -76,7 +76,7 @@ func hgradRed(alpha int) Image {
 	m := image.NewRGBA(image.Rect(0, 0, 16, 16))
 	for y := 0; y < 16; y++ {
 		for x := 0; x < 16; x++ {
-			m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), 0, 0, uint8(alpha)})
+			m.Set(x, y, color.RGBA{uint8(x * alpha / 15), 0, 0, uint8(alpha)})
 		}
 	}
 	return m
@@ -86,7 +86,7 @@ func gradYellow(alpha int) Image {
 	m := image.NewRGBA(image.Rect(0, 0, 16, 16))
 	for y := 0; y < 16; y++ {
 		for x := 0; x < 16; x++ {
-			m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), uint8(y * alpha / 15), 0, uint8(alpha)})
+			m.Set(x, y, color.RGBA{uint8(x * alpha / 15), uint8(y * alpha / 15), 0, uint8(alpha)})
 		}
 	}
 	return m
@@ -97,61 +97,61 @@ type drawTest struct {
 	src      image.Image
 	mask     image.Image
 	op       Op
-	expected image.Color
+	expected color.Color
 }
 
 var drawTests = []drawTest{
 	// Uniform mask (0% opaque).
-	{"nop", vgradGreen(255), fillAlpha(0), Over, image.RGBAColor{136, 0, 0, 255}},
-	{"clear", vgradGreen(255), fillAlpha(0), Src, image.RGBAColor{0, 0, 0, 0}},
+	{"nop", vgradGreen(255), fillAlpha(0), Over, color.RGBA{136, 0, 0, 255}},
+	{"clear", vgradGreen(255), fillAlpha(0), Src, color.RGBA{0, 0, 0, 0}},
 	// Uniform mask (100%, 75%, nil) and uniform source.
 	// At (x, y) == (8, 8):
 	// The destination pixel is {136, 0, 0, 255}.
 	// The source pixel is {0, 0, 90, 90}.
-	{"fill", fillBlue(90), fillAlpha(255), Over, image.RGBAColor{88, 0, 90, 255}},
-	{"fillSrc", fillBlue(90), fillAlpha(255), Src, image.RGBAColor{0, 0, 90, 90}},
-	{"fillAlpha", fillBlue(90), fillAlpha(192), Over, image.RGBAColor{100, 0, 68, 255}},
-	{"fillAlphaSrc", fillBlue(90), fillAlpha(192), Src, image.RGBAColor{0, 0, 68, 68}},
-	{"fillNil", fillBlue(90), nil, Over, image.RGBAColor{88, 0, 90, 255}},
-	{"fillNilSrc", fillBlue(90), nil, Src, image.RGBAColor{0, 0, 90, 90}},
+	{"fill", fillBlue(90), fillAlpha(255), Over, color.RGBA{88, 0, 90, 255}},
+	{"fillSrc", fillBlue(90), fillAlpha(255), Src, color.RGBA{0, 0, 90, 90}},
+	{"fillAlpha", fillBlue(90), fillAlpha(192), Over, color.RGBA{100, 0, 68, 255}},
+	{"fillAlphaSrc", fillBlue(90), fillAlpha(192), Src, color.RGBA{0, 0, 68, 68}},
+	{"fillNil", fillBlue(90), nil, Over, color.RGBA{88, 0, 90, 255}},
+	{"fillNilSrc", fillBlue(90), nil, Src, color.RGBA{0, 0, 90, 90}},
 	// Uniform mask (100%, 75%, nil) and variable source.
 	// At (x, y) == (8, 8):
 	// The destination pixel is {136, 0, 0, 255}.
 	// The source pixel is {0, 48, 0, 90}.
-	{"copy", vgradGreen(90), fillAlpha(255), Over, image.RGBAColor{88, 48, 0, 255}},
-	{"copySrc", vgradGreen(90), fillAlpha(255), Src, image.RGBAColor{0, 48, 0, 90}},
-	{"copyAlpha", vgradGreen(90), fillAlpha(192), Over, image.RGBAColor{100, 36, 0, 255}},
-	{"copyAlphaSrc", vgradGreen(90), fillAlpha(192), Src, image.RGBAColor{0, 36, 0, 68}},
-	{"copyNil", vgradGreen(90), nil, Over, image.RGBAColor{88, 48, 0, 255}},
-	{"copyNilSrc", vgradGreen(90), nil, Src, image.RGBAColor{0, 48, 0, 90}},
+	{"copy", vgradGreen(90), fillAlpha(255), Over, color.RGBA{88, 48, 0, 255}},
+	{"copySrc", vgradGreen(90), fillAlpha(255), Src, color.RGBA{0, 48, 0, 90}},
+	{"copyAlpha", vgradGreen(90), fillAlpha(192), Over, color.RGBA{100, 36, 0, 255}},
+	{"copyAlphaSrc", vgradGreen(90), fillAlpha(192), Src, color.RGBA{0, 36, 0, 68}},
+	{"copyNil", vgradGreen(90), nil, Over, color.RGBA{88, 48, 0, 255}},
+	{"copyNilSrc", vgradGreen(90), nil, Src, color.RGBA{0, 48, 0, 90}},
 	// Uniform mask (100%, 75%, nil) and variable NRGBA source.
 	// At (x, y) == (8, 8):
 	// The destination pixel is {136, 0, 0, 255}.
 	// The source pixel is {0, 136, 0, 90} in NRGBA-space, which is {0, 48, 0, 90} in RGBA-space.
 	// The result pixel is different than in the "copy*" test cases because of rounding errors.
-	{"nrgba", vgradGreenNRGBA(90), fillAlpha(255), Over, image.RGBAColor{88, 46, 0, 255}},
-	{"nrgbaSrc", vgradGreenNRGBA(90), fillAlpha(255), Src, image.RGBAColor{0, 46, 0, 90}},
-	{"nrgbaAlpha", vgradGreenNRGBA(90), fillAlpha(192), Over, image.RGBAColor{100, 34, 0, 255}},
-	{"nrgbaAlphaSrc", vgradGreenNRGBA(90), fillAlpha(192), Src, image.RGBAColor{0, 34, 0, 68}},
-	{"nrgbaNil", vgradGreenNRGBA(90), nil, Over, image.RGBAColor{88, 46, 0, 255}},
-	{"nrgbaNilSrc", vgradGreenNRGBA(90), nil, Src, image.RGBAColor{0, 46, 0, 90}},
+	{"nrgba", vgradGreenNRGBA(90), fillAlpha(255), Over, color.RGBA{88, 46, 0, 255}},
+	{"nrgbaSrc", vgradGreenNRGBA(90), fillAlpha(255), Src, color.RGBA{0, 46, 0, 90}},
+	{"nrgbaAlpha", vgradGreenNRGBA(90), fillAlpha(192), Over, color.RGBA{100, 34, 0, 255}},
+	{"nrgbaAlphaSrc", vgradGreenNRGBA(90), fillAlpha(192), Src, color.RGBA{0, 34, 0, 68}},
+	{"nrgbaNil", vgradGreenNRGBA(90), nil, Over, color.RGBA{88, 46, 0, 255}},
+	{"nrgbaNilSrc", vgradGreenNRGBA(90), nil, Src, color.RGBA{0, 46, 0, 90}},
 	// Uniform mask (100%, 75%, nil) and variable YCbCr source.
 	// At (x, y) == (8, 8):
 	// The destination pixel is {136, 0, 0, 255}.
 	// The source pixel is {0, 0, 136} in YCbCr-space, which is {11, 38, 0, 255} in RGB-space.
-	{"ycbcr", vgradCr(), fillAlpha(255), Over, image.RGBAColor{11, 38, 0, 255}},
-	{"ycbcrSrc", vgradCr(), fillAlpha(255), Src, image.RGBAColor{11, 38, 0, 255}},
-	{"ycbcrAlpha", vgradCr(), fillAlpha(192), Over, image.RGBAColor{42, 28, 0, 255}},
-	{"ycbcrAlphaSrc", vgradCr(), fillAlpha(192), Src, image.RGBAColor{8, 28, 0, 192}},
-	{"ycbcrNil", vgradCr(), nil, Over, image.RGBAColor{11, 38, 0, 255}},
-	{"ycbcrNilSrc", vgradCr(), nil, Src, image.RGBAColor{11, 38, 0, 255}},
+	{"ycbcr", vgradCr(), fillAlpha(255), Over, color.RGBA{11, 38, 0, 255}},
+	{"ycbcrSrc", vgradCr(), fillAlpha(255), Src, color.RGBA{11, 38, 0, 255}},
+	{"ycbcrAlpha", vgradCr(), fillAlpha(192), Over, color.RGBA{42, 28, 0, 255}},
+	{"ycbcrAlphaSrc", vgradCr(), fillAlpha(192), Src, color.RGBA{8, 28, 0, 192}},
+	{"ycbcrNil", vgradCr(), nil, Over, color.RGBA{11, 38, 0, 255}},
+	{"ycbcrNilSrc", vgradCr(), nil, Src, color.RGBA{11, 38, 0, 255}},
 	// Variable mask and variable source.
 	// At (x, y) == (8, 8):
 	// The destination pixel is {136, 0, 0, 255}.
 	// The source pixel is {0, 0, 255, 255}.
 	// The mask pixel's alpha is 102, or 40%.
-	{"generic", fillBlue(255), vgradAlpha(192), Over, image.RGBAColor{81, 0, 102, 255}},
-	{"genericSrc", fillBlue(255), vgradAlpha(192), Src, image.RGBAColor{0, 0, 102, 102}},
+	{"generic", fillBlue(255), vgradAlpha(192), Over, color.RGBA{81, 0, 102, 255}},
+	{"genericSrc", fillBlue(255), vgradAlpha(192), Src, color.RGBA{0, 0, 102, 102}},
 }
 
 func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) image.Image {
@@ -191,7 +191,7 @@ func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Po
 				_, _, _, ma = mask.At(mx, my).RGBA()
 			}
 			a := M - (sa * ma / M)
-			golden.Set(x, y, image.RGBA64Color{
+			golden.Set(x, y, color.RGBA64{
 				uint16((dr*a + sr*ma) / M),
 				uint16((dg*a + sg*ma) / M),
 				uint16((db*a + sb*ma) / M),
@@ -283,13 +283,13 @@ func TestDrawOverlap(t *testing.T) {
 func TestNonZeroSrcPt(t *testing.T) {
 	a := image.NewRGBA(image.Rect(0, 0, 1, 1))
 	b := image.NewRGBA(image.Rect(0, 0, 2, 2))
-	b.Set(0, 0, image.RGBAColor{0, 0, 0, 5})
-	b.Set(1, 0, image.RGBAColor{0, 0, 5, 5})
-	b.Set(0, 1, image.RGBAColor{0, 5, 0, 5})
-	b.Set(1, 1, image.RGBAColor{5, 0, 0, 5})
+	b.Set(0, 0, color.RGBA{0, 0, 0, 5})
+	b.Set(1, 0, color.RGBA{0, 0, 5, 5})
+	b.Set(0, 1, color.RGBA{0, 5, 0, 5})
+	b.Set(1, 1, color.RGBA{5, 0, 0, 5})
 	Draw(a, image.Rect(0, 0, 1, 1), b, image.Pt(1, 1), Over)
-	if !eq(image.RGBAColor{5, 0, 0, 5}, a.At(0, 0)) {
-		t.Errorf("non-zero src pt: want %v got %v", image.RGBAColor{5, 0, 0, 5}, a.At(0, 0))
+	if !eq(color.RGBA{5, 0, 0, 5}, a.At(0, 0)) {
+		t.Errorf("non-zero src pt: want %v got %v", color.RGBA{5, 0, 0, 5}, a.At(0, 0))
 	}
 }
 
@@ -312,8 +312,8 @@ func TestFill(t *testing.T) {
 	for _, r := range rr {
 		m := image.NewRGBA(image.Rect(0, 0, 40, 30)).SubImage(r).(*image.RGBA)
 		b := m.Bounds()
-		c := image.RGBAColor{11, 0, 0, 255}
-		src := &image.ColorImage{c}
+		c := color.RGBA{11, 0, 0, 255}
+		src := &image.Uniform{c}
 		check := func(desc string) {
 			for y := b.Min.Y; y < b.Max.Y; y++ {
 				for x := b.Min.X; x < b.Max.X; x++ {
@@ -332,22 +332,22 @@ func TestFill(t *testing.T) {
 		}
 		check("pixel")
 		// Draw 1 row at a time.
-		c = image.RGBAColor{0, 22, 0, 255}
-		src = &image.ColorImage{c}
+		c = color.RGBA{0, 22, 0, 255}
+		src = &image.Uniform{c}
 		for y := b.Min.Y; y < b.Max.Y; y++ {
 			DrawMask(m, image.Rect(b.Min.X, y, b.Max.X, y+1), src, image.ZP, nil, image.ZP, Src)
 		}
 		check("row")
 		// Draw 1 column at a time.
-		c = image.RGBAColor{0, 0, 33, 255}
-		src = &image.ColorImage{c}
+		c = color.RGBA{0, 0, 33, 255}
+		src = &image.Uniform{c}
 		for x := b.Min.X; x < b.Max.X; x++ {
 			DrawMask(m, image.Rect(x, b.Min.Y, x+1, b.Max.Y), src, image.ZP, nil, image.ZP, Src)
 		}
 		check("column")
 		// Draw the whole image at once.
-		c = image.RGBAColor{44, 55, 66, 77}
-		src = &image.ColorImage{c}
+		c = color.RGBA{44, 55, 66, 77}
+		src = &image.Uniform{c}
 		DrawMask(m, b, src, image.ZP, nil, image.ZP, Src)
 		check("whole")
 	}
diff --git a/src/pkg/image/format.go b/src/pkg/image/format.go
index b485932..78fc3ed 100644
--- a/src/pkg/image/format.go
+++ b/src/pkg/image/format.go
@@ -6,18 +6,18 @@ package image
 
 import (
 	"bufio"
+	"errors"
 	"io"
-	"os"
 )
 
 // An UnknownFormatErr indicates that decoding encountered an unknown format.
-var UnknownFormatErr = os.NewError("image: unknown format")
+var UnknownFormatErr = errors.New("image: unknown format")
 
 // A format holds an image format's name, magic header and how to decode it.
 type format struct {
 	name, magic  string
-	decode       func(io.Reader) (Image, os.Error)
-	decodeConfig func(io.Reader) (Config, os.Error)
+	decode       func(io.Reader) (Image, error)
+	decodeConfig func(io.Reader) (Config, error)
 }
 
 // Formats is the list of registered formats.
@@ -29,14 +29,14 @@ var formats []format
 // string can contain "?" wildcards that each match any one byte.
 // Decode is the function that decodes the encoded image.
 // DecodeConfig is the function that decodes just its configuration.
-func RegisterFormat(name, magic string, decode func(io.Reader) (Image, os.Error), decodeConfig func(io.Reader) (Config, os.Error)) {
+func RegisterFormat(name, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error)) {
 	formats = append(formats, format{name, magic, decode, decodeConfig})
 }
 
 // A reader is an io.Reader that can also peek ahead.
 type reader interface {
 	io.Reader
-	Peek(int) ([]byte, os.Error)
+	Peek(int) ([]byte, error)
 }
 
 // AsReader converts an io.Reader to a reader.
@@ -75,7 +75,7 @@ func sniff(r reader) format {
 // The string returned is the format name used during format registration.
 // Format registration is typically done by the init method of the codec-
 // specific package.
-func Decode(r io.Reader) (Image, string, os.Error) {
+func Decode(r io.Reader) (Image, string, error) {
 	rr := asReader(r)
 	f := sniff(rr)
 	if f.decode == nil {
@@ -89,7 +89,7 @@ func Decode(r io.Reader) (Image, string, os.Error) {
 // been encoded in a registered format. The string returned is the format name
 // used during format registration. Format registration is typically done by
 // the init method of the codec-specific package.
-func DecodeConfig(r io.Reader) (Config, string, os.Error) {
+func DecodeConfig(r io.Reader) (Config, string, error) {
 	rr := asReader(r)
 	f := sniff(rr)
 	if f.decodeConfig == nil {
diff --git a/src/pkg/image/geom.go b/src/pkg/image/geom.go
index 667aee6..e123483 100644
--- a/src/pkg/image/geom.go
+++ b/src/pkg/image/geom.go
@@ -112,7 +112,7 @@ func (r Rectangle) Add(p Point) Rectangle {
 	}
 }
 
-// Add returns the rectangle r translated by -p.
+// Sub returns the rectangle r translated by -p.
 func (r Rectangle) Sub(p Point) Rectangle {
 	return Rectangle{
 		Point{r.Min.X - p.X, r.Min.Y - p.Y},
diff --git a/src/pkg/image/gif/reader.go b/src/pkg/image/gif/reader.go
index 48876f3..24b53c5 100644
--- a/src/pkg/image/gif/reader.go
+++ b/src/pkg/image/gif/reader.go
@@ -10,10 +10,11 @@ package gif
 import (
 	"bufio"
 	"compress/lzw"
+	"errors"
 	"fmt"
 	"image"
+	"image/color"
 	"io"
-	"os"
 )
 
 // If the io.Reader does not also have ReadByte, then decode will introduce its own buffering.
@@ -76,7 +77,7 @@ type decoder struct {
 
 	// Computed.
 	pixelSize      uint
-	globalColorMap image.PalettedColorModel
+	globalColorMap color.Palette
 
 	// Used when decoding.
 	delay []int
@@ -96,7 +97,7 @@ type blockReader struct {
 	tmp   [256]byte
 }
 
-func (b *blockReader) Read(p []byte) (int, os.Error) {
+func (b *blockReader) Read(p []byte) (int, error) {
 	if len(p) == 0 {
 		return 0, nil
 	}
@@ -106,7 +107,7 @@ func (b *blockReader) Read(p []byte) (int, os.Error) {
 			return 0, err
 		}
 		if blockLen == 0 {
-			return 0, os.EOF
+			return 0, io.EOF
 		}
 		b.slice = b.tmp[0:blockLen]
 		if _, err = io.ReadFull(b.r, b.slice); err != nil {
@@ -119,7 +120,7 @@ func (b *blockReader) Read(p []byte) (int, os.Error) {
 }
 
 // decode reads a GIF image from r and stores the result in d.
-func (d *decoder) decode(r io.Reader, configOnly bool) os.Error {
+func (d *decoder) decode(r io.Reader, configOnly bool) error {
 	// Add buffering if r does not provide ReadByte.
 	if rr, ok := r.(reader); ok {
 		d.r = rr
@@ -145,7 +146,7 @@ Loop:
 	for err == nil {
 		var c byte
 		c, err = d.r.ReadByte()
-		if err == os.EOF {
+		if err == io.EOF {
 			break
 		}
 		switch c {
@@ -188,7 +189,7 @@ Loop:
 				return err
 			}
 			if c != 0 {
-				return os.NewError("gif: extra data after image")
+				return errors.New("gif: extra data after image")
 			}
 
 			// Undo the interlacing if necessary.
@@ -216,7 +217,7 @@ Loop:
 	return nil
 }
 
-func (d *decoder) readHeaderAndScreenDescriptor() os.Error {
+func (d *decoder) readHeaderAndScreenDescriptor() error {
 	_, err := io.ReadFull(d.r, d.tmp[0:13])
 	if err != nil {
 		return err
@@ -235,7 +236,7 @@ func (d *decoder) readHeaderAndScreenDescriptor() os.Error {
 	return nil
 }
 
-func (d *decoder) readColorMap() (image.PalettedColorModel, os.Error) {
+func (d *decoder) readColorMap() (color.Palette, error) {
 	if d.pixelSize > 8 {
 		return nil, fmt.Errorf("gif: can't handle %d bits per pixel", d.pixelSize)
 	}
@@ -248,16 +249,16 @@ func (d *decoder) readColorMap() (image.PalettedColorModel, os.Error) {
 	if err != nil {
 		return nil, fmt.Errorf("gif: short read on color map: %s", err)
 	}
-	colorMap := make(image.PalettedColorModel, numColors)
+	colorMap := make(color.Palette, numColors)
 	j := 0
 	for i := range colorMap {
-		colorMap[i] = image.RGBAColor{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
+		colorMap[i] = color.RGBA{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
 		j += 3
 	}
 	return colorMap, nil
 }
 
-func (d *decoder) readExtension() os.Error {
+func (d *decoder) readExtension() error {
 	extension, err := d.r.ReadByte()
 	if err != nil {
 		return err
@@ -306,7 +307,7 @@ func (d *decoder) readExtension() os.Error {
 	panic("unreachable")
 }
 
-func (d *decoder) readGraphicControl() os.Error {
+func (d *decoder) readGraphicControl() error {
 	if _, err := io.ReadFull(d.r, d.tmp[0:6]); err != nil {
 		return fmt.Errorf("gif: can't read graphic control: %s", err)
 	}
@@ -319,13 +320,13 @@ func (d *decoder) readGraphicControl() os.Error {
 	return nil
 }
 
-func (d *decoder) setTransparency(colorMap image.PalettedColorModel) {
+func (d *decoder) setTransparency(colorMap color.Palette) {
 	if int(d.transparentIndex) < len(colorMap) {
-		colorMap[d.transparentIndex] = image.RGBAColor{}
+		colorMap[d.transparentIndex] = color.RGBA{}
 	}
 }
 
-func (d *decoder) newImageFromDescriptor() (*image.Paletted, os.Error) {
+func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
 	if _, err := io.ReadFull(d.r, d.tmp[0:9]); err != nil {
 		return nil, fmt.Errorf("gif: can't read image descriptor: %s", err)
 	}
@@ -337,7 +338,7 @@ func (d *decoder) newImageFromDescriptor() (*image.Paletted, os.Error) {
 	return image.NewPaletted(image.Rect(left, top, left+width, top+height), nil), nil
 }
 
-func (d *decoder) readBlock() (int, os.Error) {
+func (d *decoder) readBlock() (int, error) {
 	n, err := d.r.ReadByte()
 	if n == 0 || err != nil {
 		return 0, err
@@ -378,7 +379,7 @@ func uninterlace(m *image.Paletted) {
 
 // Decode reads a GIF image from r and returns the first embedded
 // image as an image.Image.
-func Decode(r io.Reader) (image.Image, os.Error) {
+func Decode(r io.Reader) (image.Image, error) {
 	var d decoder
 	if err := d.decode(r, false); err != nil {
 		return nil, err
@@ -395,7 +396,7 @@ type GIF struct {
 
 // DecodeAll reads a GIF image from r and returns the sequential frames
 // and timing information.
-func DecodeAll(r io.Reader) (*GIF, os.Error) {
+func DecodeAll(r io.Reader) (*GIF, error) {
 	var d decoder
 	if err := d.decode(r, false); err != nil {
 		return nil, err
@@ -410,7 +411,7 @@ func DecodeAll(r io.Reader) (*GIF, os.Error) {
 
 // DecodeConfig returns the global color model and dimensions of a GIF image
 // without decoding the entire image.
-func DecodeConfig(r io.Reader) (image.Config, os.Error) {
+func DecodeConfig(r io.Reader) (image.Config, error) {
 	var d decoder
 	if err := d.decode(r, true); err != nil {
 		return image.Config{}, err
diff --git a/src/pkg/image/image.go b/src/pkg/image/image.go
index 1ff0c02..9dd676a 100644
--- a/src/pkg/image/image.go
+++ b/src/pkg/image/image.go
@@ -3,25 +3,32 @@
 // license that can be found in the LICENSE file.
 
 // Package image implements a basic 2-D image library.
+//
+// See "The Go image package" for an introduction to this package:
+// http://blog.golang.org/2011/09/go-image-package.html
 package image
 
+import (
+	"image/color"
+)
+
 // Config holds an image's color model and dimensions.
 type Config struct {
-	ColorModel    ColorModel
+	ColorModel    color.Model
 	Width, Height int
 }
 
-// Image is a finite rectangular grid of Colors drawn from a ColorModel.
+// Image is a finite rectangular grid of Colors drawn from a color model.
 type Image interface {
-	// ColorModel returns the Image's ColorModel.
-	ColorModel() ColorModel
+	// ColorModel returns the Image's color model.
+	ColorModel() color.Model
 	// Bounds returns the domain for which At can return non-zero color.
 	// The bounds do not necessarily contain the point (0, 0).
 	Bounds() Rectangle
 	// At returns the color of the pixel at (x, y).
 	// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
 	// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
-	At(x, y int) Color
+	At(x, y int) color.Color
 }
 
 // PalettedImage is an image whose colors may come from a limited palette.
@@ -46,35 +53,41 @@ type RGBA struct {
 	Rect Rectangle
 }
 
-func (p *RGBA) ColorModel() ColorModel { return RGBAColorModel }
+func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
 
 func (p *RGBA) Bounds() Rectangle { return p.Rect }
 
-func (p *RGBA) At(x, y int) Color {
+func (p *RGBA) At(x, y int) color.Color {
 	if !(Point{x, y}.In(p.Rect)) {
-		return RGBAColor{}
+		return color.RGBA{}
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
-	return RGBAColor{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+	i := p.PixOffset(x, y)
+	return color.RGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *RGBA) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
 }
 
-func (p *RGBA) Set(x, y int, c Color) {
+func (p *RGBA) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
-	c1 := toRGBAColor(c).(RGBAColor)
+	i := p.PixOffset(x, y)
+	c1 := color.RGBAModel.Convert(c).(color.RGBA)
 	p.Pix[i+0] = c1.R
 	p.Pix[i+1] = c1.G
 	p.Pix[i+2] = c1.B
 	p.Pix[i+3] = c1.A
 }
 
-func (p *RGBA) SetRGBA(x, y int, c RGBAColor) {
+func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+	i := p.PixOffset(x, y)
 	p.Pix[i+0] = c.R
 	p.Pix[i+1] = c.G
 	p.Pix[i+2] = c.B
@@ -91,7 +104,7 @@ func (p *RGBA) SubImage(r Rectangle) Image {
 	if r.Empty() {
 		return &RGBA{}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*4
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &RGBA{
 		Pix:    p.Pix[i:],
 		Stride: p.Stride,
@@ -117,7 +130,7 @@ func (p *RGBA) Opaque() bool {
 	return true
 }
 
-// NewRGBA returns a new RGBA with the given width and height.
+// NewRGBA returns a new RGBA with the given bounds.
 func NewRGBA(r Rectangle) *RGBA {
 	w, h := r.Dx(), r.Dy()
 	buf := make([]uint8, 4*w*h)
@@ -135,16 +148,16 @@ type RGBA64 struct {
 	Rect Rectangle
 }
 
-func (p *RGBA64) ColorModel() ColorModel { return RGBA64ColorModel }
+func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
 
 func (p *RGBA64) Bounds() Rectangle { return p.Rect }
 
-func (p *RGBA64) At(x, y int) Color {
+func (p *RGBA64) At(x, y int) color.Color {
 	if !(Point{x, y}.In(p.Rect)) {
-		return RGBA64Color{}
+		return color.RGBA64{}
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
-	return RGBA64Color{
+	i := p.PixOffset(x, y)
+	return color.RGBA64{
 		uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
 		uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
 		uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
@@ -152,12 +165,18 @@ func (p *RGBA64) At(x, y int) Color {
 	}
 }
 
-func (p *RGBA64) Set(x, y int, c Color) {
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *RGBA64) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+}
+
+func (p *RGBA64) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
-	c1 := toRGBA64Color(c).(RGBA64Color)
+	i := p.PixOffset(x, y)
+	c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
 	p.Pix[i+0] = uint8(c1.R >> 8)
 	p.Pix[i+1] = uint8(c1.R)
 	p.Pix[i+2] = uint8(c1.G >> 8)
@@ -168,11 +187,11 @@ func (p *RGBA64) Set(x, y int, c Color) {
 	p.Pix[i+7] = uint8(c1.A)
 }
 
-func (p *RGBA64) SetRGBA64(x, y int, c RGBA64Color) {
+func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+	i := p.PixOffset(x, y)
 	p.Pix[i+0] = uint8(c.R >> 8)
 	p.Pix[i+1] = uint8(c.R)
 	p.Pix[i+2] = uint8(c.G >> 8)
@@ -193,7 +212,7 @@ func (p *RGBA64) SubImage(r Rectangle) Image {
 	if r.Empty() {
 		return &RGBA64{}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*8
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &RGBA64{
 		Pix:    p.Pix[i:],
 		Stride: p.Stride,
@@ -219,7 +238,7 @@ func (p *RGBA64) Opaque() bool {
 	return true
 }
 
-// NewRGBA64 returns a new RGBA64 with the given width and height.
+// NewRGBA64 returns a new RGBA64 with the given bounds.
 func NewRGBA64(r Rectangle) *RGBA64 {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 8*w*h)
@@ -237,35 +256,41 @@ type NRGBA struct {
 	Rect Rectangle
 }
 
-func (p *NRGBA) ColorModel() ColorModel { return NRGBAColorModel }
+func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
 
 func (p *NRGBA) Bounds() Rectangle { return p.Rect }
 
-func (p *NRGBA) At(x, y int) Color {
+func (p *NRGBA) At(x, y int) color.Color {
 	if !(Point{x, y}.In(p.Rect)) {
-		return NRGBAColor{}
+		return color.NRGBA{}
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
-	return NRGBAColor{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+	i := p.PixOffset(x, y)
+	return color.NRGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *NRGBA) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
 }
 
-func (p *NRGBA) Set(x, y int, c Color) {
+func (p *NRGBA) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
-	c1 := toNRGBAColor(c).(NRGBAColor)
+	i := p.PixOffset(x, y)
+	c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
 	p.Pix[i+0] = c1.R
 	p.Pix[i+1] = c1.G
 	p.Pix[i+2] = c1.B
 	p.Pix[i+3] = c1.A
 }
 
-func (p *NRGBA) SetNRGBA(x, y int, c NRGBAColor) {
+func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
+	i := p.PixOffset(x, y)
 	p.Pix[i+0] = c.R
 	p.Pix[i+1] = c.G
 	p.Pix[i+2] = c.B
@@ -282,7 +307,7 @@ func (p *NRGBA) SubImage(r Rectangle) Image {
 	if r.Empty() {
 		return &NRGBA{}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*4
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &NRGBA{
 		Pix:    p.Pix[i:],
 		Stride: p.Stride,
@@ -308,7 +333,7 @@ func (p *NRGBA) Opaque() bool {
 	return true
 }
 
-// NewNRGBA returns a new NRGBA with the given width and height.
+// NewNRGBA returns a new NRGBA with the given bounds.
 func NewNRGBA(r Rectangle) *NRGBA {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 4*w*h)
@@ -326,16 +351,16 @@ type NRGBA64 struct {
 	Rect Rectangle
 }
 
-func (p *NRGBA64) ColorModel() ColorModel { return NRGBA64ColorModel }
+func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
 
 func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
 
-func (p *NRGBA64) At(x, y int) Color {
+func (p *NRGBA64) At(x, y int) color.Color {
 	if !(Point{x, y}.In(p.Rect)) {
-		return NRGBA64Color{}
+		return color.NRGBA64{}
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
-	return NRGBA64Color{
+	i := p.PixOffset(x, y)
+	return color.NRGBA64{
 		uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
 		uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
 		uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
@@ -343,12 +368,18 @@ func (p *NRGBA64) At(x, y int) Color {
 	}
 }
 
-func (p *NRGBA64) Set(x, y int, c Color) {
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *NRGBA64) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+}
+
+func (p *NRGBA64) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
-	c1 := toNRGBA64Color(c).(NRGBA64Color)
+	i := p.PixOffset(x, y)
+	c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
 	p.Pix[i+0] = uint8(c1.R >> 8)
 	p.Pix[i+1] = uint8(c1.R)
 	p.Pix[i+2] = uint8(c1.G >> 8)
@@ -359,11 +390,11 @@ func (p *NRGBA64) Set(x, y int, c Color) {
 	p.Pix[i+7] = uint8(c1.A)
 }
 
-func (p *NRGBA64) SetNRGBA64(x, y int, c NRGBA64Color) {
+func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
+	i := p.PixOffset(x, y)
 	p.Pix[i+0] = uint8(c.R >> 8)
 	p.Pix[i+1] = uint8(c.R)
 	p.Pix[i+2] = uint8(c.G >> 8)
@@ -384,7 +415,7 @@ func (p *NRGBA64) SubImage(r Rectangle) Image {
 	if r.Empty() {
 		return &NRGBA64{}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*8
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &NRGBA64{
 		Pix:    p.Pix[i:],
 		Stride: p.Stride,
@@ -410,7 +441,7 @@ func (p *NRGBA64) Opaque() bool {
 	return true
 }
 
-// NewNRGBA64 returns a new NRGBA64 with the given width and height.
+// NewNRGBA64 returns a new NRGBA64 with the given bounds.
 func NewNRGBA64(r Rectangle) *NRGBA64 {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 8*w*h)
@@ -428,31 +459,37 @@ type Alpha struct {
 	Rect Rectangle
 }
 
-func (p *Alpha) ColorModel() ColorModel { return AlphaColorModel }
+func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
 
 func (p *Alpha) Bounds() Rectangle { return p.Rect }
 
-func (p *Alpha) At(x, y int) Color {
+func (p *Alpha) At(x, y int) color.Color {
 	if !(Point{x, y}.In(p.Rect)) {
-		return AlphaColor{}
+		return color.Alpha{}
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
-	return AlphaColor{p.Pix[i]}
+	i := p.PixOffset(x, y)
+	return color.Alpha{p.Pix[i]}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Alpha) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
 }
 
-func (p *Alpha) Set(x, y int, c Color) {
+func (p *Alpha) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
-	p.Pix[i] = toAlphaColor(c).(AlphaColor).A
+	i := p.PixOffset(x, y)
+	p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
 }
 
-func (p *Alpha) SetAlpha(x, y int, c AlphaColor) {
+func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+	i := p.PixOffset(x, y)
 	p.Pix[i] = c.A
 }
 
@@ -466,7 +503,7 @@ func (p *Alpha) SubImage(r Rectangle) Image {
 	if r.Empty() {
 		return &Alpha{}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &Alpha{
 		Pix:    p.Pix[i:],
 		Stride: p.Stride,
@@ -492,7 +529,7 @@ func (p *Alpha) Opaque() bool {
 	return true
 }
 
-// NewAlpha returns a new Alpha with the given width and height.
+// NewAlpha returns a new Alpha with the given bounds.
 func NewAlpha(r Rectangle) *Alpha {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 1*w*h)
@@ -510,33 +547,39 @@ type Alpha16 struct {
 	Rect Rectangle
 }
 
-func (p *Alpha16) ColorModel() ColorModel { return Alpha16ColorModel }
+func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
 
 func (p *Alpha16) Bounds() Rectangle { return p.Rect }
 
-func (p *Alpha16) At(x, y int) Color {
+func (p *Alpha16) At(x, y int) color.Color {
 	if !(Point{x, y}.In(p.Rect)) {
-		return Alpha16Color{}
+		return color.Alpha16{}
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
-	return Alpha16Color{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
+	i := p.PixOffset(x, y)
+	return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
 }
 
-func (p *Alpha16) Set(x, y int, c Color) {
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Alpha16) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+}
+
+func (p *Alpha16) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
-	c1 := toAlpha16Color(c).(Alpha16Color)
+	i := p.PixOffset(x, y)
+	c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
 	p.Pix[i+0] = uint8(c1.A >> 8)
 	p.Pix[i+1] = uint8(c1.A)
 }
 
-func (p *Alpha16) SetAlpha16(x, y int, c Alpha16Color) {
+func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+	i := p.PixOffset(x, y)
 	p.Pix[i+0] = uint8(c.A >> 8)
 	p.Pix[i+1] = uint8(c.A)
 }
@@ -551,7 +594,7 @@ func (p *Alpha16) SubImage(r Rectangle) Image {
 	if r.Empty() {
 		return &Alpha16{}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*2
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &Alpha16{
 		Pix:    p.Pix[i:],
 		Stride: p.Stride,
@@ -577,7 +620,7 @@ func (p *Alpha16) Opaque() bool {
 	return true
 }
 
-// NewAlpha16 returns a new Alpha16 with the given width and height.
+// NewAlpha16 returns a new Alpha16 with the given bounds.
 func NewAlpha16(r Rectangle) *Alpha16 {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 2*w*h)
@@ -595,31 +638,37 @@ type Gray struct {
 	Rect Rectangle
 }
 
-func (p *Gray) ColorModel() ColorModel { return GrayColorModel }
+func (p *Gray) ColorModel() color.Model { return color.GrayModel }
 
 func (p *Gray) Bounds() Rectangle { return p.Rect }
 
-func (p *Gray) At(x, y int) Color {
+func (p *Gray) At(x, y int) color.Color {
 	if !(Point{x, y}.In(p.Rect)) {
-		return GrayColor{}
+		return color.Gray{}
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
-	return GrayColor{p.Pix[i]}
+	i := p.PixOffset(x, y)
+	return color.Gray{p.Pix[i]}
+}
+
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Gray) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
 }
 
-func (p *Gray) Set(x, y int, c Color) {
+func (p *Gray) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
-	p.Pix[i] = toGrayColor(c).(GrayColor).Y
+	i := p.PixOffset(x, y)
+	p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
 }
 
-func (p *Gray) SetGray(x, y int, c GrayColor) {
+func (p *Gray) SetGray(x, y int, c color.Gray) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+	i := p.PixOffset(x, y)
 	p.Pix[i] = c.Y
 }
 
@@ -633,7 +682,7 @@ func (p *Gray) SubImage(r Rectangle) Image {
 	if r.Empty() {
 		return &Gray{}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &Gray{
 		Pix:    p.Pix[i:],
 		Stride: p.Stride,
@@ -646,7 +695,7 @@ func (p *Gray) Opaque() bool {
 	return true
 }
 
-// NewGray returns a new Gray with the given width and height.
+// NewGray returns a new Gray with the given bounds.
 func NewGray(r Rectangle) *Gray {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 1*w*h)
@@ -664,33 +713,39 @@ type Gray16 struct {
 	Rect Rectangle
 }
 
-func (p *Gray16) ColorModel() ColorModel { return Gray16ColorModel }
+func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
 
 func (p *Gray16) Bounds() Rectangle { return p.Rect }
 
-func (p *Gray16) At(x, y int) Color {
+func (p *Gray16) At(x, y int) color.Color {
 	if !(Point{x, y}.In(p.Rect)) {
-		return Gray16Color{}
+		return color.Gray16{}
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
-	return Gray16Color{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
+	i := p.PixOffset(x, y)
+	return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
 }
 
-func (p *Gray16) Set(x, y int, c Color) {
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Gray16) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+}
+
+func (p *Gray16) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
-	c1 := toGray16Color(c).(Gray16Color)
+	i := p.PixOffset(x, y)
+	c1 := color.Gray16Model.Convert(c).(color.Gray16)
 	p.Pix[i+0] = uint8(c1.Y >> 8)
 	p.Pix[i+1] = uint8(c1.Y)
 }
 
-func (p *Gray16) SetGray16(x, y int, c Gray16Color) {
+func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
+	i := p.PixOffset(x, y)
 	p.Pix[i+0] = uint8(c.Y >> 8)
 	p.Pix[i+1] = uint8(c.Y)
 }
@@ -705,7 +760,7 @@ func (p *Gray16) SubImage(r Rectangle) Image {
 	if r.Empty() {
 		return &Gray16{}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*2
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &Gray16{
 		Pix:    p.Pix[i:],
 		Stride: p.Stride,
@@ -718,57 +773,13 @@ func (p *Gray16) Opaque() bool {
 	return true
 }
 
-// NewGray16 returns a new Gray16 with the given width and height.
+// NewGray16 returns a new Gray16 with the given bounds.
 func NewGray16(r Rectangle) *Gray16 {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 2*w*h)
 	return &Gray16{pix, 2 * w, r}
 }
 
-// A PalettedColorModel represents a fixed palette of at most 256 colors.
-type PalettedColorModel []Color
-
-func diff(a, b uint32) uint32 {
-	if a > b {
-		return a - b
-	}
-	return b - a
-}
-
-// Convert returns the palette color closest to c in Euclidean R,G,B space.
-func (p PalettedColorModel) Convert(c Color) Color {
-	if len(p) == 0 {
-		return nil
-	}
-	return p[p.Index(c)]
-}
-
-// Index returns the index of the palette color closest to c in Euclidean
-// R,G,B space.
-func (p PalettedColorModel) Index(c Color) int {
-	cr, cg, cb, _ := c.RGBA()
-	// Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
-	cr >>= 1
-	cg >>= 1
-	cb >>= 1
-	ret, bestSSD := 0, uint32(1<<32-1)
-	for i, v := range p {
-		vr, vg, vb, _ := v.RGBA()
-		vr >>= 1
-		vg >>= 1
-		vb >>= 1
-		dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
-		ssd := (dr * dr) + (dg * dg) + (db * db)
-		if ssd < bestSSD {
-			if ssd == 0 {
-				return i
-			}
-			ret, bestSSD = i, ssd
-		}
-	}
-	return ret
-}
-
 // Paletted is an in-memory image of uint8 indices into a given palette.
 type Paletted struct {
 	// Pix holds the image's pixels, as palette indices. The pixel at
@@ -779,29 +790,35 @@ type Paletted struct {
 	// Rect is the image's bounds.
 	Rect Rectangle
 	// Palette is the image's palette.
-	Palette PalettedColorModel
+	Palette color.Palette
 }
 
-func (p *Paletted) ColorModel() ColorModel { return p.Palette }
+func (p *Paletted) ColorModel() color.Model { return p.Palette }
 
 func (p *Paletted) Bounds() Rectangle { return p.Rect }
 
-func (p *Paletted) At(x, y int) Color {
+func (p *Paletted) At(x, y int) color.Color {
 	if len(p.Palette) == 0 {
 		return nil
 	}
 	if !(Point{x, y}.In(p.Rect)) {
 		return p.Palette[0]
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+	i := p.PixOffset(x, y)
 	return p.Palette[p.Pix[i]]
 }
 
-func (p *Paletted) Set(x, y int, c Color) {
+// PixOffset returns the index of the first element of Pix that corresponds to
+// the pixel at (x, y).
+func (p *Paletted) PixOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
+}
+
+func (p *Paletted) Set(x, y int, c color.Color) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+	i := p.PixOffset(x, y)
 	p.Pix[i] = uint8(p.Palette.Index(c))
 }
 
@@ -809,7 +826,7 @@ func (p *Paletted) ColorIndexAt(x, y int) uint8 {
 	if !(Point{x, y}.In(p.Rect)) {
 		return 0
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+	i := p.PixOffset(x, y)
 	return p.Pix[i]
 }
 
@@ -817,7 +834,7 @@ func (p *Paletted) SetColorIndex(x, y int, index uint8) {
 	if !(Point{x, y}.In(p.Rect)) {
 		return
 	}
-	i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
+	i := p.PixOffset(x, y)
 	p.Pix[i] = index
 }
 
@@ -833,7 +850,7 @@ func (p *Paletted) SubImage(r Rectangle) Image {
 			Palette: p.Palette,
 		}
 	}
-	i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X-p.Rect.Min.X)*1
+	i := p.PixOffset(r.Min.X, r.Min.Y)
 	return &Paletted{
 		Pix:     p.Pix[i:],
 		Stride:  p.Stride,
@@ -866,8 +883,8 @@ func (p *Paletted) Opaque() bool {
 }
 
 // NewPaletted returns a new Paletted with the given width, height and palette.
-func NewPaletted(r Rectangle, m PalettedColorModel) *Paletted {
+func NewPaletted(r Rectangle, p color.Palette) *Paletted {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 1*w*h)
-	return &Paletted{pix, 1 * w, r, m}
+	return &Paletted{pix, 1 * w, r, p}
 }
diff --git a/src/pkg/image/image_test.go b/src/pkg/image/image_test.go
index e23a3c2..799c1a7 100644
--- a/src/pkg/image/image_test.go
+++ b/src/pkg/image/image_test.go
@@ -5,17 +5,18 @@
 package image
 
 import (
+	"image/color"
 	"testing"
 )
 
 type image interface {
 	Image
 	Opaque() bool
-	Set(int, int, Color)
+	Set(int, int, color.Color)
 	SubImage(Rectangle) Image
 }
 
-func cmp(t *testing.T, cm ColorModel, c0, c1 Color) bool {
+func cmp(t *testing.T, cm color.Model, c0, c1 color.Color) bool {
 	r0, g0, b0, a0 := cm.Convert(c0).RGBA()
 	r1, g1, b1, a1 := cm.Convert(c1).RGBA()
 	return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
@@ -31,7 +32,7 @@ func TestImage(t *testing.T) {
 		NewAlpha16(Rect(0, 0, 10, 10)),
 		NewGray(Rect(0, 0, 10, 10)),
 		NewGray16(Rect(0, 0, 10, 10)),
-		NewPaletted(Rect(0, 0, 10, 10), PalettedColorModel{
+		NewPaletted(Rect(0, 0, 10, 10), color.Palette{
 			Transparent,
 			Opaque,
 		}),
@@ -81,14 +82,14 @@ func TestImage(t *testing.T) {
 }
 
 func Test16BitsPerColorChannel(t *testing.T) {
-	testColorModel := []ColorModel{
-		RGBA64ColorModel,
-		NRGBA64ColorModel,
-		Alpha16ColorModel,
-		Gray16ColorModel,
+	testColorModel := []color.Model{
+		color.RGBA64Model,
+		color.NRGBA64Model,
+		color.Alpha16Model,
+		color.Gray16Model,
 	}
 	for _, cm := range testColorModel {
-		c := cm.Convert(RGBA64Color{0x1234, 0x1234, 0x1234, 0x1234}) // Premultiplied alpha.
+		c := cm.Convert(color.RGBA64{0x1234, 0x1234, 0x1234, 0x1234}) // Premultiplied alpha.
 		r, _, _, _ := c.RGBA()
 		if r != 0x1234 {
 			t.Errorf("%T: want red value 0x%04x got 0x%04x", c, 0x1234, r)
@@ -102,7 +103,7 @@ func Test16BitsPerColorChannel(t *testing.T) {
 		NewGray16(Rect(0, 0, 10, 10)),
 	}
 	for _, m := range testImage {
-		m.Set(1, 2, NRGBA64Color{0xffff, 0xffff, 0xffff, 0x1357}) // Non-premultiplied alpha.
+		m.Set(1, 2, color.NRGBA64{0xffff, 0xffff, 0xffff, 0x1357}) // Non-premultiplied alpha.
 		r, _, _, _ := m.At(1, 2).RGBA()
 		if r != 0x1357 {
 			t.Errorf("%T: want red value 0x%04x got 0x%04x", m, 0x1357, r)
diff --git a/src/pkg/image/jpeg/huffman.go b/src/pkg/image/jpeg/huffman.go
index 0d03a73..d238249 100644
--- a/src/pkg/image/jpeg/huffman.go
+++ b/src/pkg/image/jpeg/huffman.go
@@ -4,10 +4,7 @@
 
 package jpeg
 
-import (
-	"io"
-	"os"
-)
+import "io"
 
 // Each code is at most 16 bits long.
 const maxCodeLength = 16
@@ -36,7 +33,7 @@ type huffman struct {
 }
 
 // Reads bytes from the io.Reader to ensure that bits.n is at least n.
-func (d *decoder) ensureNBits(n int) os.Error {
+func (d *decoder) ensureNBits(n int) error {
 	for d.b.n < n {
 		c, err := d.r.ReadByte()
 		if err != nil {
@@ -64,7 +61,7 @@ func (d *decoder) ensureNBits(n int) os.Error {
 }
 
 // The composition of RECEIVE and EXTEND, specified in section F.2.2.1.
-func (d *decoder) receiveExtend(t uint8) (int, os.Error) {
+func (d *decoder) receiveExtend(t uint8) (int, error) {
 	err := d.ensureNBits(int(t))
 	if err != nil {
 		return 0, err
@@ -81,7 +78,7 @@ func (d *decoder) receiveExtend(t uint8) (int, os.Error) {
 
 // Processes a Define Huffman Table marker, and initializes a huffman struct from its contents.
 // Specified in section B.2.4.2.
-func (d *decoder) processDHT(n int) os.Error {
+func (d *decoder) processDHT(n int) error {
 	for n > 0 {
 		if n < 17 {
 			return FormatError("DHT has wrong length")
@@ -167,7 +164,7 @@ func (d *decoder) processDHT(n int) os.Error {
 // Returns the next Huffman-coded value from the bit stream, decoded according to h.
 // TODO(nigeltao): This decoding algorithm is simple, but slow. A lookahead table, instead of always
 // peeling off only 1 bit at at time, ought to be faster.
-func (d *decoder) decodeHuffman(h *huffman) (uint8, os.Error) {
+func (d *decoder) decodeHuffman(h *huffman) (uint8, error) {
 	if h.length == 0 {
 		return 0, FormatError("uninitialized Huffman table")
 	}
diff --git a/src/pkg/image/jpeg/reader.go b/src/pkg/image/jpeg/reader.go
index af69cfc..2e412ad 100644
--- a/src/pkg/image/jpeg/reader.go
+++ b/src/pkg/image/jpeg/reader.go
@@ -10,9 +10,8 @@ package jpeg
 import (
 	"bufio"
 	"image"
-	"image/ycbcr"
+	"image/color"
 	"io"
-	"os"
 )
 
 // TODO(nigeltao): fix up the doc comment style so that sentences start with
@@ -21,12 +20,12 @@ import (
 // A FormatError reports that the input is not a valid JPEG.
 type FormatError string
 
-func (e FormatError) String() string { return "invalid JPEG format: " + string(e) }
+func (e FormatError) Error() string { return "invalid JPEG format: " + string(e) }
 
 // An UnsupportedError reports that the input uses a valid but unimplemented JPEG feature.
 type UnsupportedError string
 
-func (e UnsupportedError) String() string { return "unsupported JPEG feature: " + string(e) }
+func (e UnsupportedError) Error() string { return "unsupported JPEG feature: " + string(e) }
 
 // Component specification, specified in section B.2.2.
 type component struct {
@@ -90,14 +89,14 @@ var unzig = [blockSize]int{
 // If the passed in io.Reader does not also have ReadByte, then Decode will introduce its own buffering.
 type Reader interface {
 	io.Reader
-	ReadByte() (c byte, err os.Error)
+	ReadByte() (c byte, err error)
 }
 
 type decoder struct {
 	r             Reader
 	width, height int
 	img1          *image.Gray
-	img3          *ycbcr.YCbCr
+	img3          *image.YCbCr
 	ri            int // Restart Interval.
 	nComp         int
 	comp          [nColorComponent]component
@@ -108,7 +107,7 @@ type decoder struct {
 }
 
 // Reads and ignores the next n bytes.
-func (d *decoder) ignore(n int) os.Error {
+func (d *decoder) ignore(n int) error {
 	for n > 0 {
 		m := len(d.tmp)
 		if m > n {
@@ -124,7 +123,7 @@ func (d *decoder) ignore(n int) os.Error {
 }
 
 // Specified in section B.2.2.
-func (d *decoder) processSOF(n int) os.Error {
+func (d *decoder) processSOF(n int) error {
 	switch n {
 	case 6 + 3*nGrayComponent:
 		d.nComp = nGrayComponent
@@ -171,7 +170,7 @@ func (d *decoder) processSOF(n int) os.Error {
 }
 
 // Specified in section B.2.4.1.
-func (d *decoder) processDQT(n int) os.Error {
+func (d *decoder) processDQT(n int) error {
 	const qtLength = 1 + blockSize
 	for ; n >= qtLength; n -= qtLength {
 		_, err := io.ReadFull(d.r, d.tmp[0:qtLength])
@@ -203,32 +202,23 @@ func (d *decoder) makeImg(h0, v0, mxx, myy int) {
 		d.img1 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.Gray)
 		return
 	}
-	var subsampleRatio ycbcr.SubsampleRatio
-	n := h0 * v0
-	switch n {
+	var subsampleRatio image.YCbCrSubsampleRatio
+	switch h0 * v0 {
 	case 1:
-		subsampleRatio = ycbcr.SubsampleRatio444
+		subsampleRatio = image.YCbCrSubsampleRatio444
 	case 2:
-		subsampleRatio = ycbcr.SubsampleRatio422
+		subsampleRatio = image.YCbCrSubsampleRatio422
 	case 4:
-		subsampleRatio = ycbcr.SubsampleRatio420
+		subsampleRatio = image.YCbCrSubsampleRatio420
 	default:
 		panic("unreachable")
 	}
-	b := make([]byte, mxx*myy*(1*8*8*n+2*8*8))
-	d.img3 = &ycbcr.YCbCr{
-		Y:              b[mxx*myy*(0*8*8*n+0*8*8) : mxx*myy*(1*8*8*n+0*8*8)],
-		Cb:             b[mxx*myy*(1*8*8*n+0*8*8) : mxx*myy*(1*8*8*n+1*8*8)],
-		Cr:             b[mxx*myy*(1*8*8*n+1*8*8) : mxx*myy*(1*8*8*n+2*8*8)],
-		SubsampleRatio: subsampleRatio,
-		YStride:        mxx * 8 * h0,
-		CStride:        mxx * 8,
-		Rect:           image.Rect(0, 0, d.width, d.height),
-	}
+	m := image.NewYCbCr(image.Rect(0, 0, 8*h0*mxx, 8*v0*myy), subsampleRatio)
+	d.img3 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.YCbCr)
 }
 
 // Specified in section B.2.3.
-func (d *decoder) processSOS(n int) os.Error {
+func (d *decoder) processSOS(n int) error {
 	if d.nComp == 0 {
 		return FormatError("missing SOF marker")
 	}
@@ -361,7 +351,7 @@ func (d *decoder) processSOS(n int) os.Error {
 }
 
 // Specified in section B.2.4.4.
-func (d *decoder) processDRI(n int) os.Error {
+func (d *decoder) processDRI(n int) error {
 	if n != 2 {
 		return FormatError("DRI has wrong length")
 	}
@@ -374,7 +364,7 @@ func (d *decoder) processDRI(n int) os.Error {
 }
 
 // decode reads a JPEG image from r and returns it as an image.Image.
-func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, os.Error) {
+func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
 	if rr, ok := r.(Reader); ok {
 		d.r = rr
 	} else {
@@ -450,23 +440,23 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, os.Error) {
 }
 
 // Decode reads a JPEG image from r and returns it as an image.Image.
-func Decode(r io.Reader) (image.Image, os.Error) {
+func Decode(r io.Reader) (image.Image, error) {
 	var d decoder
 	return d.decode(r, false)
 }
 
 // DecodeConfig returns the color model and dimensions of a JPEG image without
 // decoding the entire image.
-func DecodeConfig(r io.Reader) (image.Config, os.Error) {
+func DecodeConfig(r io.Reader) (image.Config, error) {
 	var d decoder
 	if _, err := d.decode(r, true); err != nil {
 		return image.Config{}, err
 	}
 	switch d.nComp {
 	case nGrayComponent:
-		return image.Config{image.GrayColorModel, d.width, d.height}, nil
+		return image.Config{color.GrayModel, d.width, d.height}, nil
 	case nColorComponent:
-		return image.Config{ycbcr.YCbCrColorModel, d.width, d.height}, nil
+		return image.Config{color.YCbCrModel, d.width, d.height}, nil
 	}
 	return image.Config{}, FormatError("missing SOF marker")
 }
diff --git a/src/pkg/image/jpeg/writer.go b/src/pkg/image/jpeg/writer.go
index 2bb6df5..71fe37c 100644
--- a/src/pkg/image/jpeg/writer.go
+++ b/src/pkg/image/jpeg/writer.go
@@ -6,10 +6,10 @@ package jpeg
 
 import (
 	"bufio"
+	"errors"
 	"image"
-	"image/ycbcr"
+	"image/color"
 	"io"
-	"os"
 )
 
 // min returns the minimum of two integers.
@@ -207,9 +207,9 @@ func init() {
 
 // writer is a buffered writer.
 type writer interface {
-	Flush() os.Error
-	Write([]byte) (int, os.Error)
-	WriteByte(byte) os.Error
+	Flush() error
+	Write([]byte) (int, error)
+	WriteByte(byte) error
 }
 
 // encoder encodes an image to the JPEG format.
@@ -217,7 +217,7 @@ type encoder struct {
 	// w is the writer to write to. err is the first error encountered during
 	// writing. All attempted writes after the first error become no-ops.
 	w   writer
-	err os.Error
+	err error
 	// buf is a scratch buffer.
 	buf [16]byte
 	// bits and nBits are accumulated bits to write to w.
@@ -379,7 +379,7 @@ func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) {
 	for j := 0; j < 8; j++ {
 		for i := 0; i < 8; i++ {
 			r, g, b, _ := m.At(min(p.X+i, xmax), min(p.Y+j, ymax)).RGBA()
-			yy, cb, cr := ycbcr.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
+			yy, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
 			yBlock[8*j+i] = int(yy)
 			cbBlock[8*j+i] = int(cb)
 			crBlock[8*j+i] = int(cr)
@@ -404,7 +404,7 @@ func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block)
 				sx = xmax
 			}
 			pix := m.Pix[offset+sx*4:]
-			yy, cb, cr := ycbcr.RGBToYCbCr(pix[0], pix[1], pix[2])
+			yy, cb, cr := color.RGBToYCbCr(pix[0], pix[1], pix[2])
 			yBlock[8*j+i] = int(yy)
 			cbBlock[8*j+i] = int(cb)
 			crBlock[8*j+i] = int(cr)
@@ -487,10 +487,10 @@ type Options struct {
 
 // Encode writes the Image m to w in JPEG 4:2:0 baseline format with the given
 // options. Default parameters are used if a nil *Options is passed.
-func Encode(w io.Writer, m image.Image, o *Options) os.Error {
+func Encode(w io.Writer, m image.Image, o *Options) error {
 	b := m.Bounds()
 	if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 {
-		return os.NewError("jpeg: image is too large to encode")
+		return errors.New("jpeg: image is too large to encode")
 	}
 	var e encoder
 	if ww, ok := w.(writer); ok {
diff --git a/src/pkg/image/jpeg/writer_test.go b/src/pkg/image/jpeg/writer_test.go
index 44c045e..e4b56d2 100644
--- a/src/pkg/image/jpeg/writer_test.go
+++ b/src/pkg/image/jpeg/writer_test.go
@@ -7,9 +7,10 @@ package jpeg
 import (
 	"bytes"
 	"image"
+	"image/color"
 	"image/png"
 	"io/ioutil"
-	"rand"
+	"math/rand"
 	"os"
 	"testing"
 )
@@ -35,7 +36,7 @@ func delta(u0, u1 uint32) int64 {
 	return d
 }
 
-func readPng(filename string) (image.Image, os.Error) {
+func readPng(filename string) (image.Image, error) {
 	f, err := os.Open(filename)
 	if err != nil {
 		return nil, err
@@ -96,7 +97,7 @@ func BenchmarkEncodeRGBOpaque(b *testing.B) {
 	rnd := rand.New(rand.NewSource(123))
 	for y := bo.Min.Y; y < bo.Max.Y; y++ {
 		for x := bo.Min.X; x < bo.Max.X; x++ {
-			img.Set(x, y, image.RGBAColor{
+			img.Set(x, y, color.RGBA{
 				uint8(rnd.Intn(256)),
 				uint8(rnd.Intn(256)),
 				uint8(rnd.Intn(256)),
@@ -104,7 +105,7 @@ func BenchmarkEncodeRGBOpaque(b *testing.B) {
 		}
 	}
 	if !img.Opaque() {
-		panic("expected image to be opaque")
+		b.Fatal("expected image to be opaque")
 	}
 	b.SetBytes(640 * 480 * 4)
 	b.StartTimer()
diff --git a/src/pkg/image/names.go b/src/pkg/image/names.go
index c309684..b830f88 100644
--- a/src/pkg/image/names.go
+++ b/src/pkg/image/names.go
@@ -4,64 +4,72 @@
 
 package image
 
+import (
+	"image/color"
+)
+
 var (
-	// Black is an opaque black ColorImage.
-	Black = NewColorImage(Gray16Color{0})
-	// White is an opaque white ColorImage.
-	White = NewColorImage(Gray16Color{0xffff})
-	// Transparent is a fully transparent ColorImage.
-	Transparent = NewColorImage(Alpha16Color{0})
-	// Opaque is a fully opaque ColorImage.
-	Opaque = NewColorImage(Alpha16Color{0xffff})
+	// Black is an opaque black uniform image.
+	Black = NewUniform(color.Black)
+	// White is an opaque white uniform image.
+	White = NewUniform(color.White)
+	// Transparent is a fully transparent uniform image.
+	Transparent = NewUniform(color.Transparent)
+	// Opaque is a fully opaque uniform image.
+	Opaque = NewUniform(color.Opaque)
 )
 
-// A ColorImage is an infinite-sized Image of uniform Color.
-// It implements both the Color and Image interfaces.
-type ColorImage struct {
-	C Color
+// Uniform is an infinite-sized Image of uniform color.
+// It implements the color.Color, color.ColorModel, and Image interfaces.
+type Uniform struct {
+	C color.Color
 }
 
-func (c *ColorImage) RGBA() (r, g, b, a uint32) {
+func (c *Uniform) RGBA() (r, g, b, a uint32) {
 	return c.C.RGBA()
 }
 
-func (c *ColorImage) ColorModel() ColorModel {
-	return ColorModelFunc(func(Color) Color { return c.C })
+func (c *Uniform) ColorModel() color.Model {
+	return c
+}
+
+func (c *Uniform) Convert(color.Color) color.Color {
+	return c.C
 }
 
-func (c *ColorImage) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
+func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
 
-func (c *ColorImage) At(x, y int) Color { return c.C }
+func (c *Uniform) At(x, y int) color.Color { return c.C }
 
 // Opaque scans the entire image and returns whether or not it is fully opaque.
-func (c *ColorImage) Opaque() bool {
+func (c *Uniform) Opaque() bool {
 	_, _, _, a := c.C.RGBA()
 	return a == 0xffff
 }
 
-func NewColorImage(c Color) *ColorImage {
-	return &ColorImage{c}
+func NewUniform(c color.Color) *Uniform {
+	return &Uniform{c}
 }
 
-// A Tiled is an infinite-sized Image that repeats another Image in both
-// directions. Tiled{i, p}.At(x, y) will equal i.At(x+p.X, y+p.Y) for all
+// Repeated is an infinite-sized Image that repeats another Image in both
+// directions. Repeated{i, p}.At(x, y) will equal i.At(x+p.X, y+p.Y) for all
 // points {x+p.X, y+p.Y} within i's Bounds.
-type Tiled struct {
+type Repeated struct {
 	I      Image
 	Offset Point
 }
 
-func (t *Tiled) ColorModel() ColorModel {
-	return t.I.ColorModel()
+func (r *Repeated) ColorModel() color.Model {
+	return r.I.ColorModel()
 }
 
-func (t *Tiled) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
+func (r *Repeated) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
 
-func (t *Tiled) At(x, y int) Color {
-	p := Point{x, y}.Add(t.Offset).Mod(t.I.Bounds())
-	return t.I.At(p.X, p.Y)
+func (r *Repeated) At(x, y int) color.Color {
+	p := Point{x, y}.Add(r.Offset).Mod(r.I.Bounds())
+	return r.I.At(p.X, p.Y)
 }
 
-func NewTiled(i Image, offset Point) *Tiled {
-	return &Tiled{i, offset}
+func NewRepeated(i Image, offset Point) *Repeated {
+	return &Repeated{i, offset}
 }
diff --git a/src/pkg/image/png/reader.go b/src/pkg/image/png/reader.go
index 19cb248..7eb8cea 100644
--- a/src/pkg/image/png/reader.go
+++ b/src/pkg/image/png/reader.go
@@ -14,8 +14,8 @@ import (
 	"hash"
 	"hash/crc32"
 	"image"
+	"image/color"
 	"io"
-	"os"
 )
 
 // Color type, as per the PNG spec.
@@ -79,7 +79,7 @@ type decoder struct {
 	crc           hash.Hash32
 	width, height int
 	depth         int
-	palette       image.PalettedColorModel
+	palette       color.Palette
 	cb            int
 	stage         int
 	idatLength    uint32
@@ -89,14 +89,14 @@ type decoder struct {
 // A FormatError reports that the input is not a valid PNG.
 type FormatError string
 
-func (e FormatError) String() string { return "png: invalid format: " + string(e) }
+func (e FormatError) Error() string { return "png: invalid format: " + string(e) }
 
 var chunkOrderError = FormatError("chunk out of order")
 
 // An UnsupportedError reports that the input uses a valid but unimplemented PNG feature.
 type UnsupportedError string
 
-func (e UnsupportedError) String() string { return "png: unsupported feature: " + string(e) }
+func (e UnsupportedError) Error() string { return "png: unsupported feature: " + string(e) }
 
 func abs(x int) int {
 	if x < 0 {
@@ -112,7 +112,7 @@ func min(a, b int) int {
 	return b
 }
 
-func (d *decoder) parseIHDR(length uint32) os.Error {
+func (d *decoder) parseIHDR(length uint32) error {
 	if length != 13 {
 		return FormatError("bad IHDR length")
 	}
@@ -188,7 +188,7 @@ func (d *decoder) parseIHDR(length uint32) os.Error {
 	return d.verifyChecksum()
 }
 
-func (d *decoder) parsePLTE(length uint32) os.Error {
+func (d *decoder) parsePLTE(length uint32) error {
 	np := int(length / 3) // The number of palette entries.
 	if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) {
 		return FormatError("bad PLTE length")
@@ -200,9 +200,9 @@ func (d *decoder) parsePLTE(length uint32) os.Error {
 	d.crc.Write(d.tmp[:n])
 	switch d.cb {
 	case cbP1, cbP2, cbP4, cbP8:
-		d.palette = image.PalettedColorModel(make([]image.Color, np))
+		d.palette = color.Palette(make([]color.Color, np))
 		for i := 0; i < np; i++ {
-			d.palette[i] = image.RGBAColor{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
+			d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
 		}
 	case cbTC8, cbTCA8, cbTC16, cbTCA16:
 		// As per the PNG spec, a PLTE chunk is optional (and for practical purposes,
@@ -213,7 +213,7 @@ func (d *decoder) parsePLTE(length uint32) os.Error {
 	return d.verifyChecksum()
 }
 
-func (d *decoder) parsetRNS(length uint32) os.Error {
+func (d *decoder) parsetRNS(length uint32) error {
 	if length > 256 {
 		return FormatError("bad tRNS length")
 	}
@@ -232,8 +232,8 @@ func (d *decoder) parsetRNS(length uint32) os.Error {
 			return FormatError("bad tRNS length")
 		}
 		for i := 0; i < n; i++ {
-			rgba := d.palette[i].(image.RGBAColor)
-			d.palette[i] = image.RGBAColor{rgba.R, rgba.G, rgba.B, d.tmp[i]}
+			rgba := d.palette[i].(color.RGBA)
+			d.palette[i] = color.RGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
 		}
 	case cbGA8, cbGA16, cbTCA8, cbTCA16:
 		return FormatError("tRNS, color type mismatch")
@@ -262,7 +262,7 @@ func paeth(a, b, c uint8) uint8 {
 // immediately before the first Read call is that d.r is positioned between the
 // first IDAT and xxx, and the decoder state immediately after the last Read
 // call is that d.r is positioned between yy and crc1.
-func (d *decoder) Read(p []byte) (int, os.Error) {
+func (d *decoder) Read(p []byte) (int, error) {
 	if len(p) == 0 {
 		return 0, nil
 	}
@@ -293,7 +293,7 @@ func (d *decoder) Read(p []byte) (int, os.Error) {
 }
 
 // decode decodes the IDAT data into an image.
-func (d *decoder) decode() (image.Image, os.Error) {
+func (d *decoder) decode() (image.Image, error) {
 	r, err := zlib.NewReader(d)
 	if err != nil {
 		return nil, err
@@ -402,7 +402,7 @@ func (d *decoder) decode() (image.Image, os.Error) {
 			for x := 0; x < d.width; x += 8 {
 				b := cdat[x/8]
 				for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
-					gray.SetGray(x+x2, y, image.GrayColor{(b >> 7) * 0xff})
+					gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
 					b <<= 1
 				}
 			}
@@ -410,7 +410,7 @@ func (d *decoder) decode() (image.Image, os.Error) {
 			for x := 0; x < d.width; x += 4 {
 				b := cdat[x/4]
 				for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
-					gray.SetGray(x+x2, y, image.GrayColor{(b >> 6) * 0x55})
+					gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
 					b <<= 2
 				}
 			}
@@ -418,22 +418,22 @@ func (d *decoder) decode() (image.Image, os.Error) {
 			for x := 0; x < d.width; x += 2 {
 				b := cdat[x/2]
 				for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
-					gray.SetGray(x+x2, y, image.GrayColor{(b >> 4) * 0x11})
+					gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
 					b <<= 4
 				}
 			}
 		case cbG8:
 			for x := 0; x < d.width; x++ {
-				gray.SetGray(x, y, image.GrayColor{cdat[x]})
+				gray.SetGray(x, y, color.Gray{cdat[x]})
 			}
 		case cbGA8:
 			for x := 0; x < d.width; x++ {
 				ycol := cdat[2*x+0]
-				nrgba.SetNRGBA(x, y, image.NRGBAColor{ycol, ycol, ycol, cdat[2*x+1]})
+				nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
 			}
 		case cbTC8:
 			for x := 0; x < d.width; x++ {
-				rgba.SetRGBA(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
+				rgba.SetRGBA(x, y, color.RGBA{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
 			}
 		case cbP1:
 			for x := 0; x < d.width; x += 8 {
@@ -480,25 +480,25 @@ func (d *decoder) decode() (image.Image, os.Error) {
 			}
 		case cbTCA8:
 			for x := 0; x < d.width; x++ {
-				nrgba.SetNRGBA(x, y, image.NRGBAColor{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
+				nrgba.SetNRGBA(x, y, color.NRGBA{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
 			}
 		case cbG16:
 			for x := 0; x < d.width; x++ {
 				ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
-				gray16.SetGray16(x, y, image.Gray16Color{ycol})
+				gray16.SetGray16(x, y, color.Gray16{ycol})
 			}
 		case cbGA16:
 			for x := 0; x < d.width; x++ {
 				ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
 				acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
-				nrgba64.SetNRGBA64(x, y, image.NRGBA64Color{ycol, ycol, ycol, acol})
+				nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
 			}
 		case cbTC16:
 			for x := 0; x < d.width; x++ {
 				rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
 				gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
 				bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
-				rgba64.SetRGBA64(x, y, image.RGBA64Color{rcol, gcol, bcol, 0xffff})
+				rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
 			}
 		case cbTCA16:
 			for x := 0; x < d.width; x++ {
@@ -506,7 +506,7 @@ func (d *decoder) decode() (image.Image, os.Error) {
 				gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
 				bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
 				acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
-				nrgba64.SetNRGBA64(x, y, image.NRGBA64Color{rcol, gcol, bcol, acol})
+				nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
 			}
 		}
 
@@ -516,8 +516,8 @@ func (d *decoder) decode() (image.Image, os.Error) {
 
 	// Check for EOF, to verify the zlib checksum.
 	n, err := r.Read(pr[:1])
-	if err != os.EOF {
-		return nil, FormatError(err.String())
+	if err != io.EOF {
+		return nil, FormatError(err.Error())
 	}
 	if n != 0 || d.idatLength != 0 {
 		return nil, FormatError("too much pixel data")
@@ -526,7 +526,7 @@ func (d *decoder) decode() (image.Image, os.Error) {
 	return img, nil
 }
 
-func (d *decoder) parseIDAT(length uint32) (err os.Error) {
+func (d *decoder) parseIDAT(length uint32) (err error) {
 	d.idatLength = length
 	d.img, err = d.decode()
 	if err != nil {
@@ -535,14 +535,14 @@ func (d *decoder) parseIDAT(length uint32) (err os.Error) {
 	return d.verifyChecksum()
 }
 
-func (d *decoder) parseIEND(length uint32) os.Error {
+func (d *decoder) parseIEND(length uint32) error {
 	if length != 0 {
 		return FormatError("bad IEND length")
 	}
 	return d.verifyChecksum()
 }
 
-func (d *decoder) parseChunk() os.Error {
+func (d *decoder) parseChunk() error {
 	// Read the length and chunk type.
 	n, err := io.ReadFull(d.r, d.tmp[:8])
 	if err != nil {
@@ -597,7 +597,7 @@ func (d *decoder) parseChunk() os.Error {
 	return d.verifyChecksum()
 }
 
-func (d *decoder) verifyChecksum() os.Error {
+func (d *decoder) verifyChecksum() error {
 	if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
 		return err
 	}
@@ -607,7 +607,7 @@ func (d *decoder) verifyChecksum() os.Error {
 	return nil
 }
 
-func (d *decoder) checkHeader() os.Error {
+func (d *decoder) checkHeader() error {
 	_, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
 	if err != nil {
 		return err
@@ -620,20 +620,20 @@ func (d *decoder) checkHeader() os.Error {
 
 // Decode reads a PNG image from r and returns it as an image.Image.
 // The type of Image returned depends on the PNG contents.
-func Decode(r io.Reader) (image.Image, os.Error) {
+func Decode(r io.Reader) (image.Image, error) {
 	d := &decoder{
 		r:   r,
 		crc: crc32.NewIEEE(),
 	}
 	if err := d.checkHeader(); err != nil {
-		if err == os.EOF {
+		if err == io.EOF {
 			err = io.ErrUnexpectedEOF
 		}
 		return nil, err
 	}
 	for d.stage != dsSeenIEND {
 		if err := d.parseChunk(); err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				err = io.ErrUnexpectedEOF
 			}
 			return nil, err
@@ -644,20 +644,20 @@ func Decode(r io.Reader) (image.Image, os.Error) {
 
 // DecodeConfig returns the color model and dimensions of a PNG image without
 // decoding the entire image.
-func DecodeConfig(r io.Reader) (image.Config, os.Error) {
+func DecodeConfig(r io.Reader) (image.Config, error) {
 	d := &decoder{
 		r:   r,
 		crc: crc32.NewIEEE(),
 	}
 	if err := d.checkHeader(); err != nil {
-		if err == os.EOF {
+		if err == io.EOF {
 			err = io.ErrUnexpectedEOF
 		}
 		return image.Config{}, err
 	}
 	for {
 		if err := d.parseChunk(); err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				err = io.ErrUnexpectedEOF
 			}
 			return image.Config{}, err
@@ -669,26 +669,26 @@ func DecodeConfig(r io.Reader) (image.Config, os.Error) {
 			break
 		}
 	}
-	var cm image.ColorModel
+	var cm color.Model
 	switch d.cb {
 	case cbG1, cbG2, cbG4, cbG8:
-		cm = image.GrayColorModel
+		cm = color.GrayModel
 	case cbGA8:
-		cm = image.NRGBAColorModel
+		cm = color.NRGBAModel
 	case cbTC8:
-		cm = image.RGBAColorModel
+		cm = color.RGBAModel
 	case cbP1, cbP2, cbP4, cbP8:
 		cm = d.palette
 	case cbTCA8:
-		cm = image.NRGBAColorModel
+		cm = color.NRGBAModel
 	case cbG16:
-		cm = image.Gray16ColorModel
+		cm = color.Gray16Model
 	case cbGA16:
-		cm = image.NRGBA64ColorModel
+		cm = color.NRGBA64Model
 	case cbTC16:
-		cm = image.RGBA64ColorModel
+		cm = color.RGBA64Model
 	case cbTCA16:
-		cm = image.NRGBA64ColorModel
+		cm = color.NRGBA64Model
 	}
 	return image.Config{cm, d.width, d.height}, nil
 }
diff --git a/src/pkg/image/png/reader_test.go b/src/pkg/image/png/reader_test.go
index 1b7c2de..7eb1fc2 100644
--- a/src/pkg/image/png/reader_test.go
+++ b/src/pkg/image/png/reader_test.go
@@ -8,6 +8,7 @@ import (
 	"bufio"
 	"fmt"
 	"image"
+	"image/color"
 	"io"
 	"os"
 	"strings"
@@ -42,7 +43,7 @@ var filenamesShort = []string{
 	"basn6a16",
 }
 
-func readPNG(filename string) (image.Image, os.Error) {
+func readPNG(filename string) (image.Image, error) {
 	f, err := os.Open(filename)
 	if err != nil {
 		return nil, err
@@ -58,12 +59,12 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
 	cm := png.ColorModel()
 	var bitdepth int
 	switch cm {
-	case image.RGBAColorModel, image.NRGBAColorModel, image.AlphaColorModel, image.GrayColorModel:
+	case color.RGBAModel, color.NRGBAModel, color.AlphaModel, color.GrayModel:
 		bitdepth = 8
 	default:
 		bitdepth = 16
 	}
-	cpm, _ := cm.(image.PalettedColorModel)
+	cpm, _ := cm.(color.Palette)
 	var paletted *image.Paletted
 	if cpm != nil {
 		switch {
@@ -83,11 +84,11 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
 	io.WriteString(w, "#SNG: from "+filename+".png\nIHDR {\n")
 	fmt.Fprintf(w, "    width: %d; height: %d; bitdepth: %d;\n", bounds.Dx(), bounds.Dy(), bitdepth)
 	switch {
-	case cm == image.RGBAColorModel, cm == image.RGBA64ColorModel:
+	case cm == color.RGBAModel, cm == color.RGBA64Model:
 		io.WriteString(w, "    using color;\n")
-	case cm == image.NRGBAColorModel, cm == image.NRGBA64ColorModel:
+	case cm == color.NRGBAModel, cm == color.NRGBA64Model:
 		io.WriteString(w, "    using color alpha;\n")
-	case cm == image.GrayColorModel, cm == image.Gray16ColorModel:
+	case cm == color.GrayModel, cm == color.Gray16Model:
 		io.WriteString(w, "    using grayscale;\n")
 	case cpm != nil:
 		io.WriteString(w, "    using color palette;\n")
@@ -130,34 +131,34 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
 	io.WriteString(w, "IMAGE {\n    pixels hex\n")
 	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
 		switch {
-		case cm == image.GrayColorModel:
+		case cm == color.GrayModel:
 			for x := bounds.Min.X; x < bounds.Max.X; x++ {
-				gray := png.At(x, y).(image.GrayColor)
+				gray := png.At(x, y).(color.Gray)
 				fmt.Fprintf(w, "%02x", gray.Y)
 			}
-		case cm == image.Gray16ColorModel:
+		case cm == color.Gray16Model:
 			for x := bounds.Min.X; x < bounds.Max.X; x++ {
-				gray16 := png.At(x, y).(image.Gray16Color)
+				gray16 := png.At(x, y).(color.Gray16)
 				fmt.Fprintf(w, "%04x ", gray16.Y)
 			}
-		case cm == image.RGBAColorModel:
+		case cm == color.RGBAModel:
 			for x := bounds.Min.X; x < bounds.Max.X; x++ {
-				rgba := png.At(x, y).(image.RGBAColor)
+				rgba := png.At(x, y).(color.RGBA)
 				fmt.Fprintf(w, "%02x%02x%02x ", rgba.R, rgba.G, rgba.B)
 			}
-		case cm == image.RGBA64ColorModel:
+		case cm == color.RGBA64Model:
 			for x := bounds.Min.X; x < bounds.Max.X; x++ {
-				rgba64 := png.At(x, y).(image.RGBA64Color)
+				rgba64 := png.At(x, y).(color.RGBA64)
 				fmt.Fprintf(w, "%04x%04x%04x ", rgba64.R, rgba64.G, rgba64.B)
 			}
-		case cm == image.NRGBAColorModel:
+		case cm == color.NRGBAModel:
 			for x := bounds.Min.X; x < bounds.Max.X; x++ {
-				nrgba := png.At(x, y).(image.NRGBAColor)
+				nrgba := png.At(x, y).(color.NRGBA)
 				fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
 			}
-		case cm == image.NRGBA64ColorModel:
+		case cm == color.NRGBA64Model:
 			for x := bounds.Min.X; x < bounds.Max.X; x++ {
-				nrgba64 := png.At(x, y).(image.NRGBA64Color)
+				nrgba64 := png.At(x, y).(color.NRGBA64)
 				fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
 			}
 		case cpm != nil:
@@ -193,7 +194,7 @@ func TestReader(t *testing.T) {
 		if fn == "basn4a16" {
 			// basn4a16.sng is gray + alpha but sng() will produce true color + alpha
 			// so we just check a single random pixel.
-			c := img.At(2, 1).(image.NRGBA64Color)
+			c := img.At(2, 1).(color.NRGBA64)
 			if c.R != 0x11a7 || c.G != 0x11a7 || c.B != 0x11a7 || c.A != 0x1085 {
 				t.Error(fn, fmt.Errorf("wrong pixel value at (2, 1): %x", c))
 			}
@@ -222,7 +223,7 @@ func TestReader(t *testing.T) {
 		for {
 			ps, perr := pb.ReadString('\n')
 			ss, serr := sb.ReadString('\n')
-			if perr == os.EOF && serr == os.EOF {
+			if perr == io.EOF && serr == io.EOF {
 				break
 			}
 			if perr != nil {
@@ -258,7 +259,7 @@ func TestReaderError(t *testing.T) {
 			t.Errorf("decoding %s: missing error", tt.file)
 			continue
 		}
-		if !strings.Contains(err.String(), tt.err) {
+		if !strings.Contains(err.Error(), tt.err) {
 			t.Errorf("decoding %s: %s, want %s", tt.file, err, tt.err)
 		}
 		if img != nil {
diff --git a/src/pkg/image/png/writer.go b/src/pkg/image/png/writer.go
index 2dc5537..641eae1 100644
--- a/src/pkg/image/png/writer.go
+++ b/src/pkg/image/png/writer.go
@@ -9,8 +9,8 @@ import (
 	"compress/zlib"
 	"hash/crc32"
 	"image"
+	"image/color"
 	"io"
-	"os"
 	"strconv"
 )
 
@@ -18,7 +18,7 @@ type encoder struct {
 	w      io.Writer
 	m      image.Image
 	cb     int
-	err    os.Error
+	err    error
 	header [8]byte
 	footer [4]byte
 	tmp    [3 * 256]byte
@@ -125,7 +125,7 @@ func (e *encoder) writeIHDR() {
 	e.writeChunk(e.tmp[0:13], "IHDR")
 }
 
-func (e *encoder) writePLTE(p image.PalettedColorModel) {
+func (e *encoder) writePLTE(p color.Palette) {
 	if len(p) < 1 || len(p) > 256 {
 		e.err = FormatError("bad palette length: " + strconv.Itoa(len(p)))
 		return
@@ -139,7 +139,7 @@ func (e *encoder) writePLTE(p image.PalettedColorModel) {
 	e.writeChunk(e.tmp[0:3*len(p)], "PLTE")
 }
 
-func (e *encoder) maybeWritetRNS(p image.PalettedColorModel) {
+func (e *encoder) maybeWritetRNS(p color.Palette) {
 	last := -1
 	for i, c := range p {
 		_, _, _, a := c.RGBA()
@@ -160,7 +160,7 @@ func (e *encoder) maybeWritetRNS(p image.PalettedColorModel) {
 //
 // This method should only be called from writeIDATs (via writeImage).
 // No other code should treat an encoder as an io.Writer.
-func (e *encoder) Write(b []byte) (int, os.Error) {
+func (e *encoder) Write(b []byte) (int, error) {
 	e.writeChunk(b, "IDAT")
 	if e.err != nil {
 		return 0, e.err
@@ -262,7 +262,7 @@ func filter(cr *[nFilter][]byte, pr []byte, bpp int) int {
 	return filter
 }
 
-func writeImage(w io.Writer, m image.Image, cb int) os.Error {
+func writeImage(w io.Writer, m image.Image, cb int) error {
 	zw, err := zlib.NewWriter(w)
 	if err != nil {
 		return err
@@ -306,7 +306,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
 		switch cb {
 		case cbG8:
 			for x := b.Min.X; x < b.Max.X; x++ {
-				c := image.GrayColorModel.Convert(m.At(x, y)).(image.GrayColor)
+				c := color.GrayModel.Convert(m.At(x, y)).(color.Gray)
 				cr[0][i] = c.Y
 				i++
 			}
@@ -345,7 +345,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
 		case cbTCA8:
 			// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
 			for x := b.Min.X; x < b.Max.X; x++ {
-				c := image.NRGBAColorModel.Convert(m.At(x, y)).(image.NRGBAColor)
+				c := color.NRGBAModel.Convert(m.At(x, y)).(color.NRGBA)
 				cr[0][i+0] = c.R
 				cr[0][i+1] = c.G
 				cr[0][i+2] = c.B
@@ -354,7 +354,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
 			}
 		case cbG16:
 			for x := b.Min.X; x < b.Max.X; x++ {
-				c := image.Gray16ColorModel.Convert(m.At(x, y)).(image.Gray16Color)
+				c := color.Gray16Model.Convert(m.At(x, y)).(color.Gray16)
 				cr[0][i+0] = uint8(c.Y >> 8)
 				cr[0][i+1] = uint8(c.Y)
 				i += 2
@@ -374,7 +374,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
 		case cbTCA16:
 			// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
 			for x := b.Min.X; x < b.Max.X; x++ {
-				c := image.NRGBA64ColorModel.Convert(m.At(x, y)).(image.NRGBA64Color)
+				c := color.NRGBA64Model.Convert(m.At(x, y)).(color.NRGBA64)
 				cr[0][i+0] = uint8(c.R >> 8)
 				cr[0][i+1] = uint8(c.R)
 				cr[0][i+2] = uint8(c.G >> 8)
@@ -423,33 +423,33 @@ func (e *encoder) writeIEND() { e.writeChunk(e.tmp[0:0], "IEND") }
 
 // Encode writes the Image m to w in PNG format. Any Image may be encoded, but
 // images that are not image.NRGBA might be encoded lossily.
-func Encode(w io.Writer, m image.Image) os.Error {
+func Encode(w io.Writer, m image.Image) error {
 	// Obviously, negative widths and heights are invalid. Furthermore, the PNG
 	// spec section 11.2.2 says that zero is invalid. Excessively large images are
 	// also rejected.
 	mw, mh := int64(m.Bounds().Dx()), int64(m.Bounds().Dy())
 	if mw <= 0 || mh <= 0 || mw >= 1<<32 || mh >= 1<<32 {
-		return FormatError("invalid image size: " + strconv.Itoa64(mw) + "x" + strconv.Itoa64(mw))
+		return FormatError("invalid image size: " + strconv.FormatInt(mw, 10) + "x" + strconv.FormatInt(mw, 10))
 	}
 
 	var e encoder
 	e.w = w
 	e.m = m
 
-	var pal image.PalettedColorModel
+	var pal color.Palette
 	// cbP8 encoding needs PalettedImage's ColorIndexAt method.
 	if _, ok := m.(image.PalettedImage); ok {
-		pal, _ = m.ColorModel().(image.PalettedColorModel)
+		pal, _ = m.ColorModel().(color.Palette)
 	}
 	if pal != nil {
 		e.cb = cbP8
 	} else {
 		switch m.ColorModel() {
-		case image.GrayColorModel:
+		case color.GrayModel:
 			e.cb = cbG8
-		case image.Gray16ColorModel:
+		case color.Gray16Model:
 			e.cb = cbG16
-		case image.RGBAColorModel, image.NRGBAColorModel, image.AlphaColorModel:
+		case color.RGBAModel, color.NRGBAModel, color.AlphaModel:
 			if opaque(m) {
 				e.cb = cbTC8
 			} else {
diff --git a/src/pkg/image/png/writer_test.go b/src/pkg/image/png/writer_test.go
index a3864e0..228eccc 100644
--- a/src/pkg/image/png/writer_test.go
+++ b/src/pkg/image/png/writer_test.go
@@ -8,12 +8,12 @@ import (
 	"bytes"
 	"fmt"
 	"image"
+	"image/color"
 	"io/ioutil"
-	"os"
 	"testing"
 )
 
-func diff(m0, m1 image.Image) os.Error {
+func diff(m0, m1 image.Image) error {
 	b0, b1 := m0.Bounds(), m1.Bounds()
 	if !b0.Size().Eq(b1.Size()) {
 		return fmt.Errorf("dimensions differ: %v vs %v", b0, b1)
@@ -34,7 +34,7 @@ func diff(m0, m1 image.Image) os.Error {
 	return nil
 }
 
-func encodeDecode(m image.Image) (image.Image, os.Error) {
+func encodeDecode(m image.Image) (image.Image, error) {
 	b := bytes.NewBuffer(nil)
 	err := Encode(b, m)
 	if err != nil {
@@ -85,7 +85,7 @@ func TestSubImage(t *testing.T) {
 	m0 := image.NewRGBA(image.Rect(0, 0, 256, 256))
 	for y := 0; y < 256; y++ {
 		for x := 0; x < 256; x++ {
-			m0.Set(x, y, image.RGBAColor{uint8(x), uint8(y), 0, 255})
+			m0.Set(x, y, color.RGBA{uint8(x), uint8(y), 0, 255})
 		}
 	}
 	m0 = m0.SubImage(image.Rect(50, 30, 250, 130)).(*image.RGBA)
@@ -103,11 +103,10 @@ func TestSubImage(t *testing.T) {
 
 func BenchmarkEncodePaletted(b *testing.B) {
 	b.StopTimer()
-	img := image.NewPaletted(image.Rect(0, 0, 640, 480),
-		[]image.Color{
-			image.RGBAColor{0, 0, 0, 255},
-			image.RGBAColor{255, 255, 255, 255},
-		})
+	img := image.NewPaletted(image.Rect(0, 0, 640, 480), color.Palette{
+		color.RGBA{0, 0, 0, 255},
+		color.RGBA{255, 255, 255, 255},
+	})
 	b.SetBytes(640 * 480 * 1)
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
@@ -122,11 +121,11 @@ func BenchmarkEncodeRGBOpaque(b *testing.B) {
 	bo := img.Bounds()
 	for y := bo.Min.Y; y < bo.Max.Y; y++ {
 		for x := bo.Min.X; x < bo.Max.X; x++ {
-			img.Set(x, y, image.RGBAColor{0, 0, 0, 255})
+			img.Set(x, y, color.RGBA{0, 0, 0, 255})
 		}
 	}
 	if !img.Opaque() {
-		panic("expected image to be opaque")
+		b.Fatal("expected image to be opaque")
 	}
 	b.SetBytes(640 * 480 * 4)
 	b.StartTimer()
@@ -139,7 +138,7 @@ func BenchmarkEncodeRGBA(b *testing.B) {
 	b.StopTimer()
 	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
 	if img.Opaque() {
-		panic("expected image to not be opaque")
+		b.Fatal("expected image to not be opaque")
 	}
 	b.SetBytes(640 * 480 * 4)
 	b.StartTimer()
diff --git a/src/pkg/image/tiff/Makefile b/src/pkg/image/tiff/Makefile
index 1a001af..67ef5c9 100644
--- a/src/pkg/image/tiff/Makefile
+++ b/src/pkg/image/tiff/Makefile
@@ -7,6 +7,7 @@ include ../../../Make.inc
 TARG=image/tiff
 GOFILES=\
 	buffer.go\
+	compress.go\
 	consts.go\
 	reader.go\
 
diff --git a/src/pkg/image/tiff/buffer.go b/src/pkg/image/tiff/buffer.go
index 7c07142..27533c6 100644
--- a/src/pkg/image/tiff/buffer.go
+++ b/src/pkg/image/tiff/buffer.go
@@ -4,10 +4,7 @@
 
 package tiff
 
-import (
-	"io"
-	"os"
-)
+import "io"
 
 // buffer buffers an io.Reader to satisfy io.ReaderAt.
 type buffer struct {
@@ -15,11 +12,11 @@ type buffer struct {
 	buf []byte
 }
 
-func (b *buffer) ReadAt(p []byte, off int64) (int, os.Error) {
+func (b *buffer) ReadAt(p []byte, off int64) (int, error) {
 	o := int(off)
 	end := o + len(p)
 	if int64(end) != off+int64(len(p)) {
-		return 0, os.EINVAL
+		return 0, io.ErrUnexpectedEOF
 	}
 
 	m := len(b.buf)
diff --git a/src/pkg/image/tiff/buffer_test.go b/src/pkg/image/tiff/buffer_test.go
index 4f3e68e..e13afb3 100644
--- a/src/pkg/image/tiff/buffer_test.go
+++ b/src/pkg/image/tiff/buffer_test.go
@@ -5,7 +5,7 @@
 package tiff
 
 import (
-	"os"
+	"io"
 	"strings"
 	"testing"
 )
@@ -14,13 +14,13 @@ var readAtTests = []struct {
 	n   int
 	off int64
 	s   string
-	err os.Error
+	err error
 }{
 	{2, 0, "ab", nil},
 	{6, 0, "abcdef", nil},
 	{3, 3, "def", nil},
-	{3, 5, "f", os.EOF},
-	{3, 6, "", os.EOF},
+	{3, 5, "f", io.EOF},
+	{3, 6, "", io.EOF},
 }
 
 func TestReadAt(t *testing.T) {
diff --git a/src/pkg/image/tiff/compress.go b/src/pkg/image/tiff/compress.go
new file mode 100644
index 0000000..40c7fd8
--- /dev/null
+++ b/src/pkg/image/tiff/compress.go
@@ -0,0 +1,59 @@
+// Copyright 2011 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 tiff
+
+import (
+	"bufio"
+	"io"
+)
+
+type byteReader interface {
+	io.Reader
+	io.ByteReader
+}
+
+// unpackBits decodes the PackBits-compressed data in src and returns the
+// uncompressed data.
+//
+// The PackBits compression format is described in section 9 (p. 42)
+// of the TIFF spec.
+func unpackBits(r io.Reader) ([]byte, error) {
+	buf := make([]byte, 128)
+	dst := make([]byte, 0, 1024)
+	br, ok := r.(byteReader)
+	if !ok {
+		br = bufio.NewReader(r)
+	}
+
+	for {
+		b, err := br.ReadByte()
+		if err != nil {
+			if err == io.EOF {
+				return dst, nil
+			}
+			return nil, err
+		}
+		code := int(int8(b))
+		switch {
+		case code >= 0:
+			n, err := io.ReadFull(br, buf[:code+1])
+			if err != nil {
+				return nil, err
+			}
+			dst = append(dst, buf[:n]...)
+		case code == -128:
+			// No-op.
+		default:
+			if b, err = br.ReadByte(); err != nil {
+				return nil, err
+			}
+			for j := 0; j < 1-code; j++ {
+				buf[j] = b
+			}
+			dst = append(dst, buf[:1-code]...)
+		}
+	}
+	panic("unreachable")
+}
diff --git a/src/pkg/image/tiff/reader.go b/src/pkg/image/tiff/reader.go
index c1c0a1b..dc5a87a 100644
--- a/src/pkg/image/tiff/reader.go
+++ b/src/pkg/image/tiff/reader.go
@@ -12,15 +12,15 @@ import (
 	"compress/zlib"
 	"encoding/binary"
 	"image"
+	"image/color"
 	"io"
 	"io/ioutil"
-	"os"
 )
 
 // A FormatError reports that the input is not a valid TIFF image.
 type FormatError string
 
-func (e FormatError) String() string {
+func (e FormatError) Error() string {
 	return "tiff: invalid format: " + string(e)
 }
 
@@ -28,14 +28,14 @@ func (e FormatError) String() string {
 // unimplemented feature.
 type UnsupportedError string
 
-func (e UnsupportedError) String() string {
+func (e UnsupportedError) Error() string {
 	return "tiff: unsupported feature: " + string(e)
 }
 
 // An InternalError reports that an internal error was encountered.
 type InternalError string
 
-func (e InternalError) String() string {
+func (e InternalError) Error() string {
 	return "tiff: internal error: " + string(e)
 }
 
@@ -45,7 +45,7 @@ type decoder struct {
 	config    image.Config
 	mode      imageMode
 	features  map[int][]uint
-	palette   []image.Color
+	palette   []color.Color
 
 	buf   []byte
 	off   int    // Current offset in buf.
@@ -65,7 +65,7 @@ func (d *decoder) firstVal(tag int) uint {
 
 // ifdUint decodes the IFD entry in p, which must be of the Byte, Short
 // or Long type, and returns the decoded uint values.
-func (d *decoder) ifdUint(p []byte) (u []uint, err os.Error) {
+func (d *decoder) ifdUint(p []byte) (u []uint, err error) {
 	var raw []byte
 	datatype := d.byteOrder.Uint16(p[2:4])
 	count := d.byteOrder.Uint32(p[4:8])
@@ -102,7 +102,7 @@ func (d *decoder) ifdUint(p []byte) (u []uint, err os.Error) {
 
 // parseIFD decides whether the the IFD entry in p is "interesting" and
 // stows away the data in the decoder.
-func (d *decoder) parseIFD(p []byte) os.Error {
+func (d *decoder) parseIFD(p []byte) error {
 	tag := d.byteOrder.Uint16(p[0:2])
 	switch tag {
 	case tBitsPerSample,
@@ -129,9 +129,9 @@ func (d *decoder) parseIFD(p []byte) os.Error {
 		if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 {
 			return FormatError("bad ColorMap length")
 		}
-		d.palette = make([]image.Color, numcolors)
+		d.palette = make([]color.Color, numcolors)
 		for i := 0; i < numcolors; i++ {
-			d.palette[i] = image.RGBA64Color{
+			d.palette[i] = color.RGBA64{
 				uint16(val[i]),
 				uint16(val[i+numcolors]),
 				uint16(val[i+2*numcolors]),
@@ -179,7 +179,7 @@ func (d *decoder) flushBits() {
 
 // decode decodes the raw data of an image.
 // It reads from d.buf and writes the strip with ymin <= y < ymax into dst.
-func (d *decoder) decode(dst image.Image, ymin, ymax int) os.Error {
+func (d *decoder) decode(dst image.Image, ymin, ymax int) error {
 	d.off = 0
 
 	// Apply horizontal predictor if necessary.
@@ -208,7 +208,7 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) os.Error {
 				if d.mode == mGrayInvert {
 					v = 0xff - v
 				}
-				img.SetGray(x, y, image.GrayColor{v})
+				img.SetGray(x, y, color.Gray{v})
 			}
 			d.flushBits()
 		}
@@ -223,8 +223,8 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) os.Error {
 		}
 	case mRGB:
 		img := dst.(*image.RGBA)
-		min := (ymin-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
-		max := (ymax-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+		min := img.PixOffset(0, ymin)
+		max := img.PixOffset(0, ymax)
 		var off int
 		for i := min; i < max; i += 4 {
 			img.Pix[i+0] = d.buf[off+0]
@@ -235,16 +235,16 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) os.Error {
 		}
 	case mNRGBA:
 		img := dst.(*image.NRGBA)
-		min := (ymin-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
-		max := (ymax-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+		min := img.PixOffset(0, ymin)
+		max := img.PixOffset(0, ymax)
 		if len(d.buf) != max-min {
 			return FormatError("short data strip")
 		}
 		copy(img.Pix[min:max], d.buf)
 	case mRGBA:
 		img := dst.(*image.RGBA)
-		min := (ymin-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
-		max := (ymax-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+		min := img.PixOffset(0, ymin)
+		max := img.PixOffset(0, ymax)
 		if len(d.buf) != max-min {
 			return FormatError("short data strip")
 		}
@@ -254,7 +254,7 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) os.Error {
 	return nil
 }
 
-func newDecoder(r io.Reader) (*decoder, os.Error) {
+func newDecoder(r io.Reader) (*decoder, error) {
 	d := &decoder{
 		r:        newReaderAt(r),
 		features: make(map[int][]uint),
@@ -308,7 +308,7 @@ func newDecoder(r io.Reader) (*decoder, os.Error) {
 				return nil, UnsupportedError("non-8-bit RGB image")
 			}
 		}
-		d.config.ColorModel = image.RGBAColorModel
+		d.config.ColorModel = color.RGBAModel
 		// RGB images normally have 3 samples per pixel.
 		// If there are more, ExtraSamples (p. 31-32 of the spec)
 		// gives their meaning (usually an alpha channel).
@@ -324,7 +324,7 @@ func newDecoder(r io.Reader) (*decoder, os.Error) {
 				d.mode = mRGBA
 			case 2:
 				d.mode = mNRGBA
-				d.config.ColorModel = image.NRGBAColorModel
+				d.config.ColorModel = color.NRGBAModel
 			default:
 				return nil, FormatError("wrong number of samples for RGB")
 			}
@@ -333,13 +333,13 @@ func newDecoder(r io.Reader) (*decoder, os.Error) {
 		}
 	case pPaletted:
 		d.mode = mPaletted
-		d.config.ColorModel = image.PalettedColorModel(d.palette)
+		d.config.ColorModel = color.Palette(d.palette)
 	case pWhiteIsZero:
 		d.mode = mGrayInvert
-		d.config.ColorModel = image.GrayColorModel
+		d.config.ColorModel = color.GrayModel
 	case pBlackIsZero:
 		d.mode = mGray
-		d.config.ColorModel = image.GrayColorModel
+		d.config.ColorModel = color.GrayModel
 	default:
 		return nil, UnsupportedError("color model")
 	}
@@ -349,7 +349,7 @@ func newDecoder(r io.Reader) (*decoder, os.Error) {
 
 // DecodeConfig returns the color model and dimensions of a TIFF image without
 // decoding the entire image.
-func DecodeConfig(r io.Reader) (image.Config, os.Error) {
+func DecodeConfig(r io.Reader) (image.Config, error) {
 	d, err := newDecoder(r)
 	if err != nil {
 		return image.Config{}, err
@@ -359,7 +359,7 @@ func DecodeConfig(r io.Reader) (image.Config, os.Error) {
 
 // Decode reads a TIFF image from r and returns it as an image.Image.
 // The type of Image returned depends on the contents of the TIFF.
-func Decode(r io.Reader) (img image.Image, err os.Error) {
+func Decode(r io.Reader) (img image.Image, err error) {
 	d, err := newDecoder(r)
 	if err != nil {
 		return
@@ -411,6 +411,8 @@ func Decode(r io.Reader) (img image.Image, err os.Error) {
 			}
 			d.buf, err = ioutil.ReadAll(r)
 			r.Close()
+		case cPackBits:
+			d.buf, err = unpackBits(io.NewSectionReader(d.r, offset, n))
 		default:
 			err = UnsupportedError("compression")
 		}
diff --git a/src/pkg/image/tiff/reader_test.go b/src/pkg/image/tiff/reader_test.go
index 1eb2bcd..ee5dafd 100644
--- a/src/pkg/image/tiff/reader_test.go
+++ b/src/pkg/image/tiff/reader_test.go
@@ -5,13 +5,15 @@
 package tiff
 
 import (
+	"image"
 	"io/ioutil"
 	"os"
+	"strings"
 	"testing"
 )
 
 // Read makes *buffer implements io.Reader, so that we can pass one to Decode.
-func (*buffer) Read([]byte) (int, os.Error) {
+func (*buffer) Read([]byte) (int, error) {
 	panic("unimplemented")
 }
 
@@ -30,6 +32,73 @@ func TestNoRPS(t *testing.T) {
 	}
 }
 
+// TestUnpackBits tests the decoding of PackBits-encoded data.
+func TestUnpackBits(t *testing.T) {
+	var unpackBitsTests = []struct {
+		compressed   string
+		uncompressed string
+	}{{
+		// Example data from Wikipedia.
+		"\xfe\xaa\x02\x80\x00\x2a\xfd\xaa\x03\x80\x00\x2a\x22\xf7\xaa",
+		"\xaa\xaa\xaa\x80\x00\x2a\xaa\xaa\xaa\xaa\x80\x00\x2a\x22\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+	}}
+	for _, u := range unpackBitsTests {
+		buf, err := unpackBits(strings.NewReader(u.compressed))
+		if err != nil {
+			t.Fatal(err)
+		}
+		if string(buf) != u.uncompressed {
+			t.Fatalf("unpackBits: want %x, got %x", u.uncompressed, buf)
+		}
+	}
+}
+
+// TestDecompress tests that decoding some TIFF images that use different
+// compression formats result in the same pixel data.
+func TestDecompress(t *testing.T) {
+	var decompressTests = []string{
+		"bw-uncompressed.tiff",
+		"bw-deflate.tiff",
+		"bw-packbits.tiff",
+	}
+	var img0 image.Image
+	for _, name := range decompressTests {
+		f, err := os.Open("testdata/" + name)
+		if err != nil {
+			t.Fatal(err)
+		}
+		defer f.Close()
+		if img0 == nil {
+			img0, err = Decode(f)
+			if err != nil {
+				t.Fatalf("decoding %s: %v", name, err)
+			}
+			continue
+		}
+
+		img1, err := Decode(f)
+		if err != nil {
+			t.Fatalf("decoding %s: %v", name, err)
+		}
+		b := img1.Bounds()
+		// Compare images.
+		if !b.Eq(img0.Bounds()) {
+			t.Fatalf("wrong image size: want %s, got %s", img0.Bounds(), b)
+		}
+		for y := b.Min.Y; y < b.Max.Y; y++ {
+			for x := b.Min.X; x < b.Max.X; x++ {
+				c0 := img0.At(x, y)
+				c1 := img1.At(x, y)
+				r0, g0, b0, a0 := c0.RGBA()
+				r1, g1, b1, a1 := c1.RGBA()
+				if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 {
+					t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1)
+				}
+			}
+		}
+	}
+}
+
 const filename = "testdata/video-001-uncompressed.tiff"
 
 // BenchmarkDecode benchmarks the decoding of an image.
@@ -44,7 +113,7 @@ func BenchmarkDecode(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		_, err := Decode(r)
 		if err != nil {
-			panic(err)
+			b.Fatal("Decode:", err)
 		}
 	}
 }
diff --git a/src/pkg/image/tiff/testdata/bw-deflate.tiff b/src/pkg/image/tiff/testdata/bw-deflate.tiff
new file mode 100644
index 0000000..137a0c3
Binary files /dev/null and b/src/pkg/image/tiff/testdata/bw-deflate.tiff differ
diff --git a/src/pkg/image/tiff/testdata/bw-packbits.tiff b/src/pkg/image/tiff/testdata/bw-packbits.tiff
new file mode 100644
index 0000000..d59fa4a
Binary files /dev/null and b/src/pkg/image/tiff/testdata/bw-packbits.tiff differ
diff --git a/src/pkg/image/tiff/testdata/bw-uncompressed.tiff b/src/pkg/image/tiff/testdata/bw-uncompressed.tiff
new file mode 100644
index 0000000..8390f11
Binary files /dev/null and b/src/pkg/image/tiff/testdata/bw-uncompressed.tiff differ
diff --git a/src/pkg/image/ycbcr.go b/src/pkg/image/ycbcr.go
new file mode 100644
index 0000000..c1a0b66
--- /dev/null
+++ b/src/pkg/image/ycbcr.go
@@ -0,0 +1,144 @@
+// Copyright 2011 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 image
+
+import (
+	"image/color"
+)
+
+// YCbCrSubsampleRatio is the chroma subsample ratio used in a YCbCr image.
+type YCbCrSubsampleRatio int
+
+const (
+	YCbCrSubsampleRatio444 YCbCrSubsampleRatio = iota
+	YCbCrSubsampleRatio422
+	YCbCrSubsampleRatio420
+)
+
+func (s YCbCrSubsampleRatio) String() string {
+	switch s {
+	case YCbCrSubsampleRatio444:
+		return "YCbCrSubsampleRatio444"
+	case YCbCrSubsampleRatio422:
+		return "YCbCrSubsampleRatio422"
+	case YCbCrSubsampleRatio420:
+		return "YCbCrSubsampleRatio420"
+	}
+	return "YCbCrSubsampleRatioUnknown"
+}
+
+// YCbCr is an in-memory image of Y'CbCr colors. There is one Y sample per
+// pixel, but each Cb and Cr sample can span one or more pixels.
+// YStride is the Y slice index delta between vertically adjacent pixels.
+// CStride is the Cb and Cr slice index delta between vertically adjacent pixels
+// that map to separate chroma samples.
+// It is not an absolute requirement, but YStride and len(Y) are typically
+// multiples of 8, and:
+//	For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
+//	For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
+//	For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
+type YCbCr struct {
+	Y, Cb, Cr      []uint8
+	YStride        int
+	CStride        int
+	SubsampleRatio YCbCrSubsampleRatio
+	Rect           Rectangle
+}
+
+func (p *YCbCr) ColorModel() color.Model {
+	return color.YCbCrModel
+}
+
+func (p *YCbCr) Bounds() Rectangle {
+	return p.Rect
+}
+
+func (p *YCbCr) At(x, y int) color.Color {
+	if !(Point{x, y}.In(p.Rect)) {
+		return color.YCbCr{}
+	}
+	yi := p.YOffset(x, y)
+	ci := p.COffset(x, y)
+	return color.YCbCr{
+		p.Y[yi],
+		p.Cb[ci],
+		p.Cr[ci],
+	}
+}
+
+// YOffset returns the index of the first element of Y that corresponds to
+// the pixel at (x, y).
+func (p *YCbCr) YOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.YStride + (x - p.Rect.Min.X)
+}
+
+// COffset returns the index of the first element of Cb or Cr that corresponds
+// to the pixel at (x, y).
+func (p *YCbCr) COffset(x, y int) int {
+	switch p.SubsampleRatio {
+	case YCbCrSubsampleRatio422:
+		return (y-p.Rect.Min.Y)*p.CStride + (x/2 - p.Rect.Min.X/2)
+	case YCbCrSubsampleRatio420:
+		return (y/2-p.Rect.Min.Y/2)*p.CStride + (x/2 - p.Rect.Min.X/2)
+	}
+	// Default to 4:4:4 subsampling.
+	return (y-p.Rect.Min.Y)*p.CStride + (x - p.Rect.Min.X)
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *YCbCr) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &YCbCr{
+			SubsampleRatio: p.SubsampleRatio,
+		}
+	}
+	yi := p.YOffset(r.Min.X, r.Min.Y)
+	ci := p.COffset(r.Min.X, r.Min.Y)
+	return &YCbCr{
+		Y:              p.Y[yi:],
+		Cb:             p.Cb[ci:],
+		Cr:             p.Cr[ci:],
+		SubsampleRatio: p.SubsampleRatio,
+		YStride:        p.YStride,
+		CStride:        p.CStride,
+		Rect:           r,
+	}
+}
+
+func (p *YCbCr) Opaque() bool {
+	return true
+}
+
+// NewYCbCr returns a new YCbCr with the given bounds and subsample ratio.
+func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
+	w, h, cw, ch := r.Dx(), r.Dy(), 0, 0
+	switch subsampleRatio {
+	case YCbCrSubsampleRatio422:
+		cw = (r.Max.X+1)/2 - r.Min.X/2
+		ch = h
+	case YCbCrSubsampleRatio420:
+		cw = (r.Max.X+1)/2 - r.Min.X/2
+		ch = (r.Max.Y+1)/2 - r.Min.Y/2
+	default:
+		// Default to 4:4:4 subsampling.
+		cw = w
+		ch = h
+	}
+	b := make([]byte, w*h+2*cw*ch)
+	return &YCbCr{
+		Y:              b[:w*h],
+		Cb:             b[w*h+0*cw*ch : w*h+1*cw*ch],
+		Cr:             b[w*h+1*cw*ch : w*h+2*cw*ch],
+		SubsampleRatio: subsampleRatio,
+		YStride:        w,
+		CStride:        cw,
+		Rect:           r,
+	}
+}
diff --git a/src/pkg/image/ycbcr/Makefile b/src/pkg/image/ycbcr/Makefile
deleted file mode 100644
index a9c4c13..0000000
--- a/src/pkg/image/ycbcr/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=image/ycbcr
-GOFILES=\
-	ycbcr.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/image/ycbcr/ycbcr.go b/src/pkg/image/ycbcr/ycbcr.go
deleted file mode 100644
index f2de3d6..0000000
--- a/src/pkg/image/ycbcr/ycbcr.go
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2011 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 ycbcr provides images from the Y'CbCr color model.
-//
-// JPEG, VP8, the MPEG family and other codecs use this color model. Such
-// codecs often use the terms YUV and Y'CbCr interchangeably, but strictly
-// speaking, the term YUV applies only to analog video signals.
-//
-// Conversion between RGB and Y'CbCr is lossy and there are multiple, slightly
-// different formulae for converting between the two. This package follows
-// the JFIF specification at http://www.w3.org/Graphics/JPEG/jfif3.pdf.
-package ycbcr
-
-import (
-	"image"
-)
-
-// RGBToYCbCr converts an RGB triple to a YCbCr triple. All components lie
-// within the range [0, 255].
-func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
-	// The JFIF specification says:
-	//	Y' =  0.2990*R + 0.5870*G + 0.1140*B
-	//	Cb = -0.1687*R - 0.3313*G + 0.5000*B + 128
-	//	Cr =  0.5000*R - 0.4187*G - 0.0813*B + 128
-	// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
-	r1 := int(r)
-	g1 := int(g)
-	b1 := int(b)
-	yy := (19595*r1 + 38470*g1 + 7471*b1 + 1<<15) >> 16
-	cb := (-11056*r1 - 21712*g1 + 32768*b1 + 257<<15) >> 16
-	cr := (32768*r1 - 27440*g1 - 5328*b1 + 257<<15) >> 16
-	if yy < 0 {
-		yy = 0
-	} else if yy > 255 {
-		yy = 255
-	}
-	if cb < 0 {
-		cb = 0
-	} else if cb > 255 {
-		cb = 255
-	}
-	if cr < 0 {
-		cr = 0
-	} else if cr > 255 {
-		cr = 255
-	}
-	return uint8(yy), uint8(cb), uint8(cr)
-}
-
-// YCbCrToRGB converts a YCbCr triple to an RGB triple. All components lie
-// within the range [0, 255].
-func YCbCrToRGB(y, cb, cr uint8) (uint8, uint8, uint8) {
-	// The JFIF specification says:
-	//	R = Y' + 1.40200*(Cr-128)
-	//	G = Y' - 0.34414*(Cb-128) - 0.71414*(Cr-128)
-	//	B = Y' + 1.77200*(Cb-128)
-	// http://www.w3.org/Graphics/JPEG/jfif3.pdf says Y but means Y'.
-	yy1 := int(y)<<16 + 1<<15
-	cb1 := int(cb) - 128
-	cr1 := int(cr) - 128
-	r := (yy1 + 91881*cr1) >> 16
-	g := (yy1 - 22554*cb1 - 46802*cr1) >> 16
-	b := (yy1 + 116130*cb1) >> 16
-	if r < 0 {
-		r = 0
-	} else if r > 255 {
-		r = 255
-	}
-	if g < 0 {
-		g = 0
-	} else if g > 255 {
-		g = 255
-	}
-	if b < 0 {
-		b = 0
-	} else if b > 255 {
-		b = 255
-	}
-	return uint8(r), uint8(g), uint8(b)
-}
-
-// YCbCrColor represents a fully opaque 24-bit Y'CbCr color, having 8 bits for
-// each of one luma and two chroma components.
-type YCbCrColor struct {
-	Y, Cb, Cr uint8
-}
-
-func (c YCbCrColor) RGBA() (uint32, uint32, uint32, uint32) {
-	r, g, b := YCbCrToRGB(c.Y, c.Cb, c.Cr)
-	return uint32(r) * 0x101, uint32(g) * 0x101, uint32(b) * 0x101, 0xffff
-}
-
-func toYCbCrColor(c image.Color) image.Color {
-	if _, ok := c.(YCbCrColor); ok {
-		return c
-	}
-	r, g, b, _ := c.RGBA()
-	y, u, v := RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
-	return YCbCrColor{y, u, v}
-}
-
-// YCbCrColorModel is the color model for YCbCrColor.
-var YCbCrColorModel image.ColorModel = image.ColorModelFunc(toYCbCrColor)
-
-// SubsampleRatio is the chroma subsample ratio used in a YCbCr image.
-type SubsampleRatio int
-
-const (
-	SubsampleRatio444 SubsampleRatio = iota
-	SubsampleRatio422
-	SubsampleRatio420
-)
-
-// YCbCr is an in-memory image of YCbCr colors. There is one Y sample per pixel,
-// but each Cb and Cr sample can span one or more pixels.
-// YStride is the Y slice index delta between vertically adjacent pixels.
-// CStride is the Cb and Cr slice index delta between vertically adjacent pixels
-// that map to separate chroma samples.
-// It is not an absolute requirement, but YStride and len(Y) are typically
-// multiples of 8, and:
-//	For 4:4:4, CStride == YStride/1 && len(Cb) == len(Cr) == len(Y)/1.
-//	For 4:2:2, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/2.
-//	For 4:2:0, CStride == YStride/2 && len(Cb) == len(Cr) == len(Y)/4.
-type YCbCr struct {
-	Y              []uint8
-	Cb             []uint8
-	Cr             []uint8
-	YStride        int
-	CStride        int
-	SubsampleRatio SubsampleRatio
-	Rect           image.Rectangle
-}
-
-func (p *YCbCr) ColorModel() image.ColorModel {
-	return YCbCrColorModel
-}
-
-func (p *YCbCr) Bounds() image.Rectangle {
-	return p.Rect
-}
-
-func (p *YCbCr) At(x, y int) image.Color {
-	if !(image.Point{x, y}.In(p.Rect)) {
-		return YCbCrColor{}
-	}
-	switch p.SubsampleRatio {
-	case SubsampleRatio422:
-		i := x / 2
-		return YCbCrColor{
-			p.Y[y*p.YStride+x],
-			p.Cb[y*p.CStride+i],
-			p.Cr[y*p.CStride+i],
-		}
-	case SubsampleRatio420:
-		i, j := x/2, y/2
-		return YCbCrColor{
-			p.Y[y*p.YStride+x],
-			p.Cb[j*p.CStride+i],
-			p.Cr[j*p.CStride+i],
-		}
-	}
-	// Default to 4:4:4 subsampling.
-	return YCbCrColor{
-		p.Y[y*p.YStride+x],
-		p.Cb[y*p.CStride+x],
-		p.Cr[y*p.CStride+x],
-	}
-}
-
-// SubImage returns an image representing the portion of the image p visible
-// through r. The returned value shares pixels with the original image.
-func (p *YCbCr) SubImage(r image.Rectangle) image.Image {
-	q := new(YCbCr)
-	*q = *p
-	q.Rect = q.Rect.Intersect(r)
-	return q
-}
-
-func (p *YCbCr) Opaque() bool {
-	return true
-}
diff --git a/src/pkg/image/ycbcr/ycbcr_test.go b/src/pkg/image/ycbcr/ycbcr_test.go
deleted file mode 100644
index 2e60a6f..0000000
--- a/src/pkg/image/ycbcr/ycbcr_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2011 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 ycbcr
-
-import (
-	"testing"
-)
-
-func delta(x, y uint8) uint8 {
-	if x >= y {
-		return x - y
-	}
-	return y - x
-}
-
-// Test that a subset of RGB space can be converted to YCbCr and back to within
-// 1/256 tolerance.
-func TestRoundtrip(t *testing.T) {
-	for r := 0; r < 255; r += 7 {
-		for g := 0; g < 255; g += 5 {
-			for b := 0; b < 255; b += 3 {
-				r0, g0, b0 := uint8(r), uint8(g), uint8(b)
-				y, cb, cr := RGBToYCbCr(r0, g0, b0)
-				r1, g1, b1 := YCbCrToRGB(y, cb, cr)
-				if delta(r0, r1) > 1 || delta(g0, g1) > 1 || delta(b0, b1) > 1 {
-					t.Fatalf("r0, g0, b0 = %d, %d, %d   r1, g1, b1 = %d, %d, %d", r0, g0, b0, r1, g1, b1)
-				}
-			}
-		}
-	}
-}
diff --git a/src/pkg/image/ycbcr_test.go b/src/pkg/image/ycbcr_test.go
new file mode 100644
index 0000000..7852b31
--- /dev/null
+++ b/src/pkg/image/ycbcr_test.go
@@ -0,0 +1,103 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package image
+
+import (
+	"image/color"
+	"testing"
+)
+
+func TestYCbCr(t *testing.T) {
+	rects := []Rectangle{
+		Rect(0, 0, 16, 16),
+		Rect(1, 0, 16, 16),
+		Rect(0, 1, 16, 16),
+		Rect(1, 1, 16, 16),
+		Rect(1, 1, 15, 16),
+		Rect(1, 1, 16, 15),
+		Rect(1, 1, 15, 15),
+		Rect(2, 3, 14, 15),
+		Rect(7, 0, 7, 16),
+		Rect(0, 8, 16, 8),
+		Rect(0, 0, 10, 11),
+		Rect(5, 6, 16, 16),
+		Rect(7, 7, 8, 8),
+		Rect(7, 8, 8, 9),
+		Rect(8, 7, 9, 8),
+		Rect(8, 8, 9, 9),
+		Rect(7, 7, 17, 17),
+		Rect(8, 8, 17, 17),
+		Rect(9, 9, 17, 17),
+		Rect(10, 10, 17, 17),
+	}
+	subsampleRatios := []YCbCrSubsampleRatio{
+		YCbCrSubsampleRatio444,
+		YCbCrSubsampleRatio422,
+		YCbCrSubsampleRatio420,
+	}
+	deltas := []Point{
+		Pt(0, 0),
+		Pt(1000, 1001),
+		Pt(5001, -400),
+		Pt(-701, -801),
+	}
+	for _, r := range rects {
+		for _, subsampleRatio := range subsampleRatios {
+			for _, delta := range deltas {
+				testYCbCr(t, r, subsampleRatio, delta)
+			}
+		}
+	}
+}
+
+func testYCbCr(t *testing.T, r Rectangle, subsampleRatio YCbCrSubsampleRatio, delta Point) {
+	// Create a YCbCr image m, whose bounds are r translated by (delta.X, delta.Y).
+	r1 := r.Add(delta)
+	m := NewYCbCr(r1, subsampleRatio)
+
+	// Test that the image buffer is reasonably small even if (delta.X, delta.Y) is far from the origin.
+	if len(m.Y) > 100*100 {
+		t.Errorf("r=%v, subsampleRatio=%v, delta=%v: image buffer is too large",
+			r, subsampleRatio, delta)
+		return
+	}
+
+	// Initialize m's pixels. For 422 and 420 subsampling, some of the Cb and Cr elements
+	// will be set multiple times. That's OK. We just want to avoid a uniform image.
+	for y := r1.Min.Y; y < r1.Max.Y; y++ {
+		for x := r1.Min.X; x < r1.Max.X; x++ {
+			yi := m.YOffset(x, y)
+			ci := m.COffset(x, y)
+			m.Y[yi] = uint8(16*y + x)
+			m.Cb[ci] = uint8(y + 16*x)
+			m.Cr[ci] = uint8(y + 16*x)
+		}
+	}
+
+	// Make various sub-images of m.
+	for y0 := delta.Y + 3; y0 < delta.Y+7; y0++ {
+		for y1 := delta.Y + 8; y1 < delta.Y+13; y1++ {
+			for x0 := delta.X + 3; x0 < delta.X+7; x0++ {
+				for x1 := delta.X + 8; x1 < delta.X+13; x1++ {
+					subRect := Rect(x0, y0, x1, y1)
+					sub := m.SubImage(subRect).(*YCbCr)
+
+					// For each point in the sub-image's bounds, check that m.At(x, y) equals sub.At(x, y).
+					for y := sub.Rect.Min.Y; y < sub.Rect.Max.Y; y++ {
+						for x := sub.Rect.Min.X; x < sub.Rect.Max.X; x++ {
+							color0 := m.At(x, y).(color.YCbCr)
+							color1 := sub.At(x, y).(color.YCbCr)
+							if color0 != color1 {
+								t.Errorf("r=%v, subsampleRatio=%v, delta=%v, x=%d, y=%d, color0=%v, color1=%v",
+									r, subsampleRatio, delta, x, y, color0, color1)
+								return
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/src/pkg/index/suffixarray/qsufsort.go b/src/pkg/index/suffixarray/qsufsort.go
index f4ec3a1..c69be43 100644
--- a/src/pkg/index/suffixarray/qsufsort.go
+++ b/src/pkg/index/suffixarray/qsufsort.go
@@ -26,7 +26,7 @@ package suffixarray
 
 import "sort"
 
-func qsufsort(data []byte) []int32 {
+func qsufsort(data []byte) []int {
 	// initial sorting by first byte of suffix
 	sa := sortedByFirstByte(data)
 	if len(sa) < 2 {
@@ -39,20 +39,20 @@ func qsufsort(data []byte) []int32 {
 	// the index starts 1-ordered
 	sufSortable := &suffixSortable{sa: sa, inv: inv, h: 1}
 
-	for int(sa[0]) > -len(sa) { // until all suffixes are one big sorted group
+	for sa[0] > -len(sa) { // until all suffixes are one big sorted group
 		// The suffixes are h-ordered, make them 2*h-ordered
 		pi := 0 // pi is first position of first group
 		sl := 0 // sl is negated length of sorted groups
 		for pi < len(sa) {
-			if s := int(sa[pi]); s < 0 { // if pi starts sorted group
+			if s := sa[pi]; s < 0 { // if pi starts sorted group
 				pi -= s // skip over sorted group
 				sl += s // add negated length to sl
 			} else { // if pi starts unsorted group
 				if sl != 0 {
-					sa[pi+sl] = int32(sl) // combine sorted groups before pi
+					sa[pi+sl] = sl // combine sorted groups before pi
 					sl = 0
 				}
-				pk := int(inv[s]) + 1 // pk-1 is last position of unsorted group
+				pk := inv[s] + 1 // pk-1 is last position of unsorted group
 				sufSortable.sa = sa[pi:pk]
 				sort.Sort(sufSortable)
 				sufSortable.updateGroups(pi)
@@ -60,19 +60,19 @@ func qsufsort(data []byte) []int32 {
 			}
 		}
 		if sl != 0 { // if the array ends with a sorted group
-			sa[pi+sl] = int32(sl) // combine sorted groups at end of sa
+			sa[pi+sl] = sl // combine sorted groups at end of sa
 		}
 
 		sufSortable.h *= 2 // double sorted depth
 	}
 
 	for i := range sa { // reconstruct suffix array from inverse
-		sa[inv[i]] = int32(i)
+		sa[inv[i]] = i
 	}
 	return sa
 }
 
-func sortedByFirstByte(data []byte) []int32 {
+func sortedByFirstByte(data []byte) []int {
 	// total byte counts
 	var count [256]int
 	for _, b := range data {
@@ -84,17 +84,17 @@ func sortedByFirstByte(data []byte) []int32 {
 		count[b], sum = sum, count[b]+sum
 	}
 	// iterate through bytes, placing index into the correct spot in sa
-	sa := make([]int32, len(data))
+	sa := make([]int, len(data))
 	for i, b := range data {
-		sa[count[b]] = int32(i)
+		sa[count[b]] = i
 		count[b]++
 	}
 	return sa
 }
 
-func initGroups(sa []int32, data []byte) []int32 {
+func initGroups(sa []int, data []byte) []int {
 	// label contiguous same-letter groups with the same group number
-	inv := make([]int32, len(data))
+	inv := make([]int, len(data))
 	prevGroup := len(sa) - 1
 	groupByte := data[sa[prevGroup]]
 	for i := len(sa) - 1; i >= 0; i-- {
@@ -105,7 +105,7 @@ func initGroups(sa []int32, data []byte) []int32 {
 			groupByte = b
 			prevGroup = i
 		}
-		inv[sa[i]] = int32(prevGroup)
+		inv[sa[i]] = prevGroup
 		if prevGroup == 0 {
 			sa[0] = -1
 		}
@@ -120,9 +120,9 @@ func initGroups(sa []int32, data []byte) []int32 {
 			if data[sa[i]] == lastByte && s == -1 {
 				s = i
 			}
-			if int(sa[i]) == len(sa)-1 {
+			if sa[i] == len(sa)-1 {
 				sa[i], sa[s] = sa[s], sa[i]
-				inv[sa[s]] = int32(s)
+				inv[sa[s]] = s
 				sa[s] = -1 // mark it as an isolated sorted group
 				break
 			}
@@ -132,9 +132,9 @@ func initGroups(sa []int32, data []byte) []int32 {
 }
 
 type suffixSortable struct {
-	sa  []int32
-	inv []int32
-	h   int32
+	sa  []int
+	inv []int
+	h   int
 	buf []int // common scratch space
 }
 
@@ -158,7 +158,7 @@ func (x *suffixSortable) updateGroups(offset int) {
 	prev := 0
 	for _, b := range bounds {
 		for i := prev; i < b; i++ {
-			x.inv[x.sa[i]] = int32(offset + b - 1)
+			x.inv[x.sa[i]] = offset + b - 1
 		}
 		if b-prev == 1 {
 			x.sa[prev] = -1
diff --git a/src/pkg/index/suffixarray/suffixarray.go b/src/pkg/index/suffixarray/suffixarray.go
index cff7daa..c59ae6e 100644
--- a/src/pkg/index/suffixarray/suffixarray.go
+++ b/src/pkg/index/suffixarray/suffixarray.go
@@ -18,17 +18,16 @@ package suffixarray
 
 import (
 	"bytes"
-	"exp/regexp"
-	"gob"
+	"encoding/binary"
 	"io"
-	"os"
+	"regexp"
 	"sort"
 )
 
 // Index implements a suffix array for fast substring search.
 type Index struct {
 	data []byte
-	sa   []int32 // suffix array for data; len(sa) == len(data)
+	sa   []int // suffix array for data; len(sa) == len(data)
 }
 
 // New creates a new Index for data.
@@ -37,72 +36,125 @@ func New(data []byte) *Index {
 	return &Index{data, qsufsort(data)}
 }
 
-// Read and Write slice the data into successive portions of length gobN,
-// so gob can allocate smaller buffers for its I/O.
-const gobN = 1 << 16 // slightly better than say 1 << 20 (BenchmarkSaveRestore)
+// writeInt writes an int x to w using buf to buffer the write.
+func writeInt(w io.Writer, buf []byte, x int) error {
+	binary.PutVarint(buf, int64(x))
+	_, err := w.Write(buf[0:binary.MaxVarintLen64])
+	return err
+}
+
+// readInt reads an int x from r using buf to buffer the read and returns x.
+func readInt(r io.Reader, buf []byte) (int, error) {
+	_, err := io.ReadFull(r, buf[0:binary.MaxVarintLen64]) // ok to continue with error
+	x, _ := binary.Varint(buf)
+	return int(x), err
+}
+
+// writeSlice writes data[:n] to w and returns n.
+// It uses buf to buffer the write.
+func writeSlice(w io.Writer, buf []byte, data []int) (n int, err error) {
+	// encode as many elements as fit into buf
+	p := binary.MaxVarintLen64
+	for ; n < len(data) && p+binary.MaxVarintLen64 <= len(buf); n++ {
+		p += binary.PutUvarint(buf[p:], uint64(data[n]))
+	}
+
+	// update buffer size
+	binary.PutVarint(buf, int64(p))
+
+	// write buffer
+	_, err = w.Write(buf[0:p])
+	return
+}
+
+// readSlice reads data[:n] from r and returns n.
+// It uses buf to buffer the read.
+func readSlice(r io.Reader, buf []byte, data []int) (n int, err error) {
+	// read buffer size
+	var size int
+	size, err = readInt(r, buf)
+	if err != nil {
+		return
+	}
+
+	// read buffer w/o the size
+	if _, err = io.ReadFull(r, buf[binary.MaxVarintLen64:size]); err != nil {
+		return
+	}
+
+	// decode as many elements as present in buf
+	for p := binary.MaxVarintLen64; p < size; n++ {
+		x, w := binary.Uvarint(buf[p:])
+		data[n] = int(x)
+		p += w
+	}
+
+	return
+}
+
+const bufSize = 16 << 10 // reasonable for BenchmarkSaveRestore
 
 // Read reads the index from r into x; x must not be nil.
-func (x *Index) Read(r io.Reader) os.Error {
-	d := gob.NewDecoder(r)
-	var n int
-	if err := d.Decode(&n); err != nil {
+func (x *Index) Read(r io.Reader) error {
+	// buffer for all reads
+	buf := make([]byte, bufSize)
+
+	// read length
+	n, err := readInt(r, buf)
+	if err != nil {
 		return err
 	}
+
+	// allocate space
 	if 2*n < cap(x.data) || cap(x.data) < n {
 		// new data is significantly smaller or larger then
 		// existing buffers - allocate new ones
 		x.data = make([]byte, n)
-		x.sa = make([]int32, n)
+		x.sa = make([]int, n)
 	} else {
 		// re-use existing buffers
 		x.data = x.data[0:n]
 		x.sa = x.sa[0:n]
 	}
-	for i := 0; i < n; {
-		j := i + gobN
-		if j > n {
-			j = n
-		}
-		// data holds next piece of x.data; its length is updated by Decode
-		data := x.data[i:j]
-		if err := d.Decode(&data); err != nil {
-			return err
-		}
-		if len(data) != j-i {
-			return os.NewError("suffixarray.Read: inconsistent data format")
-		}
-		// sa holds next piece of x.data; its length is updated by Decode
-		sa := x.sa[i:j]
-		if err := d.Decode(&sa); err != nil {
+
+	// read data
+	if _, err := io.ReadFull(r, x.data); err != nil {
+		return err
+	}
+
+	// read index
+	for sa := x.sa; len(sa) > 0; {
+		n, err := readSlice(r, buf, sa)
+		if err != nil {
 			return err
 		}
-		if len(sa) != j-i {
-			return os.NewError("suffixarray.Read: inconsistent data format")
-		}
-		i = j
+		sa = sa[n:]
 	}
 	return nil
 }
 
 // Write writes the index x to w.
-func (x *Index) Write(w io.Writer) os.Error {
-	e := gob.NewEncoder(w)
-	n := len(x.data)
-	if err := e.Encode(n); err != nil {
+func (x *Index) Write(w io.Writer) error {
+	// buffer for all writes
+	buf := make([]byte, bufSize)
+
+	// write length
+	if err := writeInt(w, buf, len(x.data)); err != nil {
 		return err
 	}
-	for i := 0; i < n; {
-		j := i + gobN
-		if j > n {
-			j = n
-		}
-		if err := e.Encode(x.data[i:j]); err != nil {
-			return err
-		}
-		if err := e.Encode(x.sa[i:j]); err != nil {
+
+	// write data
+	if _, err := w.Write(x.data); err != nil {
+		return err
+	}
+
+	// write index
+	for sa := x.sa; len(sa) > 0; {
+		n, err := writeSlice(w, buf, sa)
+		if err != nil {
 			return err
 		}
-		i = j
+		sa = sa[n:]
 	}
 	return nil
 }
@@ -120,7 +172,7 @@ func (x *Index) at(i int) []byte {
 
 // lookupAll returns a slice into the matching region of the index.
 // The runtime is O(log(N)*len(s)).
-func (x *Index) lookupAll(s []byte) []int32 {
+func (x *Index) lookupAll(s []byte) []int {
 	// find matching suffix index range [i:j]
 	// find the first index where s would be the prefix
 	i := sort.Search(len(x.sa), func(i int) bool { return bytes.Compare(x.at(i), s) >= 0 })
@@ -144,9 +196,7 @@ func (x *Index) Lookup(s []byte, n int) (result []int) {
 		// 0 <= n <= len(matches)
 		if n > 0 {
 			result = make([]int, n)
-			for i, x := range matches[0:n] {
-				result[i] = int(x)
-			}
+			copy(result, matches)
 		}
 	}
 	return
diff --git a/src/pkg/index/suffixarray/suffixarray_test.go b/src/pkg/index/suffixarray/suffixarray_test.go
index 9b4d89f..df3e449 100644
--- a/src/pkg/index/suffixarray/suffixarray_test.go
+++ b/src/pkg/index/suffixarray/suffixarray_test.go
@@ -6,8 +6,8 @@ package suffixarray
 
 import (
 	"bytes"
-	"exp/regexp"
-	"rand"
+	"math/rand"
+	"regexp"
 	"sort"
 	"strings"
 	"testing"
@@ -230,11 +230,13 @@ func equal(x, y *Index) bool {
 	return true
 }
 
-func testSaveRestore(t *testing.T, tc *testCase, x *Index) {
+// returns the serialized index size
+func testSaveRestore(t *testing.T, tc *testCase, x *Index) int {
 	var buf bytes.Buffer
 	if err := x.Write(&buf); err != nil {
 		t.Errorf("failed writing index %s (%s)", tc.name, err)
 	}
+	size := buf.Len()
 	var y Index
 	if err := y.Read(&buf); err != nil {
 		t.Errorf("failed reading index %s (%s)", tc.name, err)
@@ -242,6 +244,7 @@ func testSaveRestore(t *testing.T, tc *testCase, x *Index) {
 	if !equal(x, &y) {
 		t.Errorf("restored index doesn't match saved index %s", tc.name)
 	}
+	return size
 }
 
 func TestIndex(t *testing.T) {
@@ -257,16 +260,41 @@ func TestIndex(t *testing.T) {
 	}
 }
 
+// Of all possible inputs, the random bytes have the least amount of substring
+// repetition, and the repeated bytes have the most. For most algorithms,
+// the running time of every input will be between these two.
+func benchmarkNew(b *testing.B, random bool) {
+	b.StopTimer()
+	data := make([]byte, 1e6)
+	if random {
+		for i := range data {
+			data[i] = byte(rand.Intn(256))
+		}
+	}
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		New(data)
+	}
+}
+
+func BenchmarkNewIndexRandom(b *testing.B) {
+	benchmarkNew(b, true)
+}
+func BenchmarkNewIndexRepeat(b *testing.B) {
+	benchmarkNew(b, false)
+}
+
 func BenchmarkSaveRestore(b *testing.B) {
 	b.StopTimer()
 	r := rand.New(rand.NewSource(0x5a77a1)) // guarantee always same sequence
-	data := make([]byte, 10<<20)            // 10MB index data
+	data := make([]byte, 10<<20)            // 10MB of data to index
 	for i := range data {
 		data[i] = byte(r.Intn(256))
 	}
 	x := New(data)
-	testSaveRestore(nil, nil, x)                    // verify correctness
-	buf := bytes.NewBuffer(make([]byte, len(data))) // avoid frequent growing
+	size := testSaveRestore(nil, nil, x)       // verify correctness
+	buf := bytes.NewBuffer(make([]byte, size)) // avoid growing
+	b.SetBytes(int64(size))
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
 		x.Write(buf)
diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go
index 1fdf347..098d223 100644
--- a/src/pkg/io/io.go
+++ b/src/pkg/io/io.go
@@ -8,25 +8,30 @@
 // abstract the functionality, plus some other related primitives.
 package io
 
-import "os"
-
 // Error represents an unexpected I/O behavior.
 type Error struct {
 	ErrorString string
 }
 
-func (err *Error) String() string { return err.ErrorString }
+func (err *Error) Error() string { return err.ErrorString }
 
 // ErrShortWrite means that a write accepted fewer bytes than requested
 // but failed to return an explicit error.
-var ErrShortWrite os.Error = &Error{"short write"}
+var ErrShortWrite error = &Error{"short write"}
 
 // ErrShortBuffer means that a read required a longer buffer than was provided.
-var ErrShortBuffer os.Error = &Error{"short buffer"}
+var ErrShortBuffer error = &Error{"short buffer"}
+
+// EOF is the error returned by Read when no more input is available.
+// Functions should return EOF only to signal a graceful end of input.
+// If the EOF occurs unexpectedly in a structured data stream,
+// the appropriate error is either ErrUnexpectedEOF or some other error
+// giving more detail.
+var EOF error = &Error{"EOF"}
 
-// ErrUnexpectedEOF means that os.EOF was encountered in the
+// ErrUnexpectedEOF means that EOF was encountered in the
 // middle of reading a fixed-size block or data structure.
-var ErrUnexpectedEOF os.Error = &Error{"unexpected EOF"}
+var ErrUnexpectedEOF error = &Error{"unexpected EOF"}
 
 // Reader is the interface that wraps the basic Read method.
 //
@@ -42,15 +47,15 @@ var ErrUnexpectedEOF os.Error = &Error{"unexpected EOF"}
 // or return the error (and n == 0) from a subsequent call.
 // An instance of this general case is that a Reader returning
 // a non-zero number of bytes at the end of the input stream may
-// return either err == os.EOF or err == nil.  The next Read should
-// return 0, os.EOF regardless.
+// return either err == EOF or err == nil.  The next Read should
+// return 0, EOF regardless.
 //
 // Callers should always process the n > 0 bytes returned before
 // considering the error err.  Doing so correctly handles I/O errors
 // that happen after reading some bytes and also both of the
 // allowed EOF behaviors.
 type Reader interface {
-	Read(p []byte) (n int, err os.Error)
+	Read(p []byte) (n int, err error)
 }
 
 // Writer is the interface that wraps the basic Write method.
@@ -60,12 +65,12 @@ type Reader interface {
 // and any error encountered that caused the write to stop early.
 // Write must return a non-nil error if it returns n < len(p).
 type Writer interface {
-	Write(p []byte) (n int, err os.Error)
+	Write(p []byte) (n int, err error)
 }
 
 // Closer is the interface that wraps the basic Close method.
 type Closer interface {
-	Close() os.Error
+	Close() error
 }
 
 // Seeker is the interface that wraps the basic Seek method.
@@ -76,7 +81,7 @@ type Closer interface {
 // relative to the end.  Seek returns the new offset and an Error, if
 // any.
 type Seeker interface {
-	Seek(offset int64, whence int) (ret int64, err os.Error)
+	Seek(offset int64, whence int) (ret int64, err error)
 }
 
 // ReadWriter is the interface that groups the basic Read and Write methods.
@@ -125,12 +130,12 @@ type ReadWriteSeeker interface {
 
 // ReaderFrom is the interface that wraps the ReadFrom method.
 type ReaderFrom interface {
-	ReadFrom(r Reader) (n int64, err os.Error)
+	ReadFrom(r Reader) (n int64, err error)
 }
 
 // WriterTo is the interface that wraps the WriteTo method.
 type WriterTo interface {
-	WriteTo(w Writer) (n int64, err os.Error)
+	WriteTo(w Writer) (n int64, err error)
 }
 
 // ReaderAt is the interface that wraps the basic ReadAt method.
@@ -149,13 +154,13 @@ type WriterTo interface {
 // In this respect ReadAt is different from Read.
 //
 // If the n = len(p) bytes returned by ReadAt are at the end of the
-// input source, ReadAt may return either err == os.EOF or err == nil.
+// input source, ReadAt may return either err == EOF or err == nil.
 //
 // If ReadAt is reading from an input source with a seek offset,
 // ReadAt should not affect nor be affected by the underlying
 // seek offset.
 type ReaderAt interface {
-	ReadAt(p []byte, off int64) (n int, err os.Error)
+	ReadAt(p []byte, off int64) (n int, err error)
 }
 
 // WriterAt is the interface that wraps the basic WriteAt method.
@@ -165,7 +170,7 @@ type ReaderAt interface {
 // and any error encountered that caused the write to stop early.
 // WriteAt must return a non-nil error if it returns n < len(p).
 type WriterAt interface {
-	WriteAt(p []byte, off int64) (n int, err os.Error)
+	WriteAt(p []byte, off int64) (n int, err error)
 }
 
 // ByteReader is the interface that wraps the ReadByte method.
@@ -173,7 +178,7 @@ type WriterAt interface {
 // ReadByte reads and returns the next byte from the input.
 // If no byte is available, err will be set.
 type ByteReader interface {
-	ReadByte() (c byte, err os.Error)
+	ReadByte() (c byte, err error)
 }
 
 // ByteScanner is the interface that adds the UnreadByte method to the
@@ -185,7 +190,7 @@ type ByteReader interface {
 // call to ReadByte.
 type ByteScanner interface {
 	ByteReader
-	UnreadByte() os.Error
+	UnreadByte() error
 }
 
 // RuneReader is the interface that wraps the ReadRune method.
@@ -194,7 +199,7 @@ type ByteScanner interface {
 // and returns the rune and its size in bytes. If no character is
 // available, err will be set.
 type RuneReader interface {
-	ReadRune() (rune int, size int, err os.Error)
+	ReadRune() (r rune, size int, err error)
 }
 
 // RuneScanner is the interface that adds the UnreadRune method to the
@@ -206,16 +211,16 @@ type RuneReader interface {
 // call to ReadRune.
 type RuneScanner interface {
 	RuneReader
-	UnreadRune() os.Error
+	UnreadRune() error
 }
 
 // stringWriter is the interface that wraps the WriteString method.
 type stringWriter interface {
-	WriteString(s string) (n int, err os.Error)
+	WriteString(s string) (n int, err error)
 }
 
 // WriteString writes the contents of the string s to w, which accepts an array of bytes.
-func WriteString(w Writer, s string) (n int, err os.Error) {
+func WriteString(w Writer, s string) (n int, err error) {
 	if sw, ok := w.(stringWriter); ok {
 		return sw.WriteString(s)
 	}
@@ -224,11 +229,11 @@ func WriteString(w Writer, s string) (n int, err os.Error) {
 
 // ReadAtLeast reads from r into buf until it has read at least min bytes.
 // It returns the number of bytes copied and an error if fewer bytes were read.
-// The error is os.EOF only if no bytes were read.
+// The error is EOF only if no bytes were read.
 // If an EOF happens after reading fewer than min bytes,
 // ReadAtLeast returns ErrUnexpectedEOF.
 // If min is greater than the length of buf, ReadAtLeast returns ErrShortBuffer.
-func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) {
+func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
 	if len(buf) < min {
 		return 0, ErrShortBuffer
 	}
@@ -237,7 +242,7 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) {
 		nn, err = r.Read(buf[n:])
 		n += nn
 	}
-	if err == os.EOF {
+	if err == EOF {
 		if n >= min {
 			err = nil
 		} else if n > 0 {
@@ -249,29 +254,29 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) {
 
 // ReadFull reads exactly len(buf) bytes from r into buf.
 // It returns the number of bytes copied and an error if fewer bytes were read.
-// The error is os.EOF only if no bytes were read.
+// The error is EOF only if no bytes were read.
 // If an EOF happens after reading some but not all the bytes,
 // ReadFull returns ErrUnexpectedEOF.
-func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
+func ReadFull(r Reader, buf []byte) (n int, err error) {
 	return ReadAtLeast(r, buf, len(buf))
 }
 
-// Copyn copies n bytes (or until an error) from src to dst.
+// CopyN copies n bytes (or until an error) from src to dst.
 // It returns the number of bytes copied and the earliest
 // error encountered while copying.  Because Read can
 // return the full amount requested as well as an error
-// (including os.EOF), so can Copyn.
+// (including EOF), so can CopyN.
 //
 // If dst implements the ReaderFrom interface,
 // the copy is implemented by calling dst.ReadFrom(src).
-func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) {
+func CopyN(dst Writer, src Reader, n int64) (written int64, err error) {
 	// If the writer has a ReadFrom method, use it to do the copy.
 	// Avoids a buffer allocation and a copy.
 	if rt, ok := dst.(ReaderFrom); ok {
 		written, err = rt.ReadFrom(LimitReader(src, n))
 		if written < n && err == nil {
 			// rt stopped early; must have been EOF.
-			err = os.EOF
+			err = EOF
 		}
 		return
 	}
@@ -308,7 +313,7 @@ func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) {
 // on src or an error occurs.  It returns the number of bytes
 // copied and the first error encountered while copying, if any.
 //
-// A successful Copy returns err == nil, not err == os.EOF.
+// A successful Copy returns err == nil, not err == EOF.
 // Because Copy is defined to read from src until EOF, it does
 // not treat an EOF from Read as an error to be reported.
 //
@@ -316,7 +321,7 @@ func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) {
 // the copy is implemented by calling dst.ReadFrom(src).
 // Otherwise, if src implements the WriterTo interface,
 // the copy is implemented by calling src.WriteTo(dst).
-func Copy(dst Writer, src Reader) (written int64, err os.Error) {
+func Copy(dst Writer, src Reader) (written int64, err error) {
 	// If the writer has a ReadFrom method, use it to do the copy.
 	// Avoids an allocation and a copy.
 	if rt, ok := dst.(ReaderFrom); ok {
@@ -343,7 +348,7 @@ func Copy(dst Writer, src Reader) (written int64, err os.Error) {
 				break
 			}
 		}
-		if er == os.EOF {
+		if er == EOF {
 			break
 		}
 		if er != nil {
@@ -355,7 +360,7 @@ func Copy(dst Writer, src Reader) (written int64, err os.Error) {
 }
 
 // LimitReader returns a Reader that reads from r
-// but stops with os.EOF after n bytes.
+// but stops with EOF after n bytes.
 // The underlying implementation is a *LimitedReader.
 func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }
 
@@ -367,9 +372,9 @@ type LimitedReader struct {
 	N int64  // max bytes remaining
 }
 
-func (l *LimitedReader) Read(p []byte) (n int, err os.Error) {
+func (l *LimitedReader) Read(p []byte) (n int, err error) {
 	if l.N <= 0 {
-		return 0, os.EOF
+		return 0, EOF
 	}
 	if int64(len(p)) > l.N {
 		p = p[0:l.N]
@@ -380,7 +385,7 @@ func (l *LimitedReader) Read(p []byte) (n int, err os.Error) {
 }
 
 // NewSectionReader returns a SectionReader that reads from r
-// starting at offset off and stops with os.EOF after n bytes.
+// starting at offset off and stops with EOF after n bytes.
 func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader {
 	return &SectionReader{r, off, off, off + n}
 }
@@ -394,9 +399,9 @@ type SectionReader struct {
 	limit int64
 }
 
-func (s *SectionReader) Read(p []byte) (n int, err os.Error) {
+func (s *SectionReader) Read(p []byte) (n int, err error) {
 	if s.off >= s.limit {
-		return 0, os.EOF
+		return 0, EOF
 	}
 	if max := s.limit - s.off; int64(len(p)) > max {
 		p = p[0:max]
@@ -406,10 +411,13 @@ func (s *SectionReader) Read(p []byte) (n int, err os.Error) {
 	return
 }
 
-func (s *SectionReader) Seek(offset int64, whence int) (ret int64, err os.Error) {
+var errWhence = &Error{"Seek: invalid whence"}
+var errOffset = &Error{"Seek: invalid offset"}
+
+func (s *SectionReader) Seek(offset int64, whence int) (ret int64, err error) {
 	switch whence {
 	default:
-		return 0, os.EINVAL
+		return 0, errWhence
 	case 0:
 		offset += s.base
 	case 1:
@@ -418,15 +426,15 @@ func (s *SectionReader) Seek(offset int64, whence int) (ret int64, err os.Error)
 		offset += s.limit
 	}
 	if offset < s.base || offset > s.limit {
-		return 0, os.EINVAL
+		return 0, errOffset
 	}
 	s.off = offset
 	return offset - s.base, nil
 }
 
-func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err os.Error) {
+func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) {
 	if off < 0 || off >= s.limit-s.base {
-		return 0, os.EOF
+		return 0, EOF
 	}
 	off += s.base
 	if max := s.limit - off; int64(len(p)) > max {
@@ -452,7 +460,7 @@ type teeReader struct {
 	w Writer
 }
 
-func (t *teeReader) Read(p []byte) (n int, err os.Error) {
+func (t *teeReader) Read(p []byte) (n int, err error) {
 	n, err = t.r.Read(p)
 	if n > 0 {
 		if n, err := t.w.Write(p[:n]); err != nil {
diff --git a/src/pkg/io/io_test.go b/src/pkg/io/io_test.go
index 7449dcf..1e671b5 100644
--- a/src/pkg/io/io_test.go
+++ b/src/pkg/io/io_test.go
@@ -7,7 +7,6 @@ package io_test
 import (
 	"bytes"
 	. "io"
-	"os"
 	"strings"
 	"testing"
 )
@@ -19,7 +18,7 @@ type Buffer struct {
 	WriterTo   // conflicts with and hides bytes.Buffer's WriterTo.
 }
 
-// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and Copyn.
+// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and CopyN.
 
 func TestCopy(t *testing.T) {
 	rb := new(Buffer)
@@ -51,33 +50,33 @@ func TestCopyWriteTo(t *testing.T) {
 	}
 }
 
-func TestCopyn(t *testing.T) {
+func TestCopyN(t *testing.T) {
 	rb := new(Buffer)
 	wb := new(Buffer)
 	rb.WriteString("hello, world.")
-	Copyn(wb, rb, 5)
+	CopyN(wb, rb, 5)
 	if wb.String() != "hello" {
-		t.Errorf("Copyn did not work properly")
+		t.Errorf("CopyN did not work properly")
 	}
 }
 
-func TestCopynReadFrom(t *testing.T) {
+func TestCopyNReadFrom(t *testing.T) {
 	rb := new(Buffer)
 	wb := new(bytes.Buffer) // implements ReadFrom.
 	rb.WriteString("hello")
-	Copyn(wb, rb, 5)
+	CopyN(wb, rb, 5)
 	if wb.String() != "hello" {
-		t.Errorf("Copyn did not work properly")
+		t.Errorf("CopyN did not work properly")
 	}
 }
 
-func TestCopynWriteTo(t *testing.T) {
+func TestCopyNWriteTo(t *testing.T) {
 	rb := new(bytes.Buffer) // implements WriteTo.
 	wb := new(Buffer)
 	rb.WriteString("hello, world.")
-	Copyn(wb, rb, 5)
+	CopyN(wb, rb, 5)
 	if wb.String() != "hello" {
-		t.Errorf("Copyn did not work properly")
+		t.Errorf("CopyN did not work properly")
 	}
 }
 
@@ -85,34 +84,34 @@ type noReadFrom struct {
 	w Writer
 }
 
-func (w *noReadFrom) Write(p []byte) (n int, err os.Error) {
+func (w *noReadFrom) Write(p []byte) (n int, err error) {
 	return w.w.Write(p)
 }
 
-func TestCopynEOF(t *testing.T) {
+func TestCopyNEOF(t *testing.T) {
 	// Test that EOF behavior is the same regardless of whether
-	// argument to Copyn has ReadFrom.
+	// argument to CopyN has ReadFrom.
 
 	b := new(bytes.Buffer)
 
-	n, err := Copyn(&noReadFrom{b}, strings.NewReader("foo"), 3)
+	n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3)
 	if n != 3 || err != nil {
-		t.Errorf("Copyn(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err)
+		t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err)
 	}
 
-	n, err = Copyn(&noReadFrom{b}, strings.NewReader("foo"), 4)
-	if n != 3 || err != os.EOF {
-		t.Errorf("Copyn(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
+	n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4)
+	if n != 3 || err != EOF {
+		t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
 	}
 
-	n, err = Copyn(b, strings.NewReader("foo"), 3) // b has read from
+	n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from
 	if n != 3 || err != nil {
-		t.Errorf("Copyn(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err)
+		t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err)
 	}
 
-	n, err = Copyn(b, strings.NewReader("foo"), 4) // b has read from
-	if n != 3 || err != os.EOF {
-		t.Errorf("Copyn(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
+	n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from
+	if n != 3 || err != EOF {
+		t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
 	}
 }
 
@@ -121,16 +120,16 @@ func TestReadAtLeast(t *testing.T) {
 	testReadAtLeast(t, &rb)
 }
 
-// A version of bytes.Buffer that returns n > 0, os.EOF on Read
+// A version of bytes.Buffer that returns n > 0, EOF on Read
 // when the input is exhausted.
 type dataAndEOFBuffer struct {
 	bytes.Buffer
 }
 
-func (r *dataAndEOFBuffer) Read(p []byte) (n int, err os.Error) {
+func (r *dataAndEOFBuffer) Read(p []byte) (n int, err error) {
 	n, err = r.Buffer.Read(p)
 	if n > 0 && r.Buffer.Len() == 0 && err == nil {
-		err = os.EOF
+		err = EOF
 	}
 	return
 }
@@ -162,7 +161,7 @@ func testReadAtLeast(t *testing.T, rb ReadWriter) {
 		t.Errorf("expected to have read 2 bytes, got %v", n)
 	}
 	n, err = ReadAtLeast(rb, buf, 2)
-	if err != os.EOF {
+	if err != EOF {
 		t.Errorf("expected EOF, got %v", err)
 	}
 	if n != 0 {
@@ -193,14 +192,14 @@ func TestTeeReader(t *testing.T) {
 	if !bytes.Equal(wb.Bytes(), src) {
 		t.Errorf("bytes written = %q want %q", wb.Bytes(), src)
 	}
-	if n, err := r.Read(dst); n != 0 || err != os.EOF {
+	if n, err := r.Read(dst); n != 0 || err != EOF {
 		t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err)
 	}
 	rb = bytes.NewBuffer(src)
 	pr, pw := Pipe()
 	pr.Close()
 	r = TeeReader(rb, pw)
-	if n, err := ReadFull(r, dst); n != 0 || err != os.EPIPE {
+	if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe {
 		t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err)
 	}
 }
diff --git a/src/pkg/io/ioutil/ioutil.go b/src/pkg/io/ioutil/ioutil.go
index fffa132..cbe1a58 100644
--- a/src/pkg/io/ioutil/ioutil.go
+++ b/src/pkg/io/ioutil/ioutil.go
@@ -14,19 +14,32 @@ import (
 
 // readAll reads from r until an error or EOF and returns the data it read
 // from the internal buffer allocated with a specified capacity.
-func readAll(r io.Reader, capacity int64) ([]byte, os.Error) {
+func readAll(r io.Reader, capacity int64) (b []byte, err error) {
 	buf := bytes.NewBuffer(make([]byte, 0, capacity))
-	_, err := buf.ReadFrom(r)
+	// If the buffer overflows, we will get bytes.ErrTooLarge.
+	// Return that as an error. Any other panic remains.
+	defer func() {
+		e := recover()
+		if e == nil {
+			return
+		}
+		if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
+			err = panicErr
+		} else {
+			panic(e)
+		}
+	}()
+	_, err = buf.ReadFrom(r)
 	return buf.Bytes(), err
 }
 
 // ReadAll reads from r until an error or EOF and returns the data it read.
-func ReadAll(r io.Reader) ([]byte, os.Error) {
+func ReadAll(r io.Reader) ([]byte, error) {
 	return readAll(r, bytes.MinRead)
 }
 
 // ReadFile reads the file named by filename and returns the contents.
-func ReadFile(filename string) ([]byte, os.Error) {
+func ReadFile(filename string) ([]byte, error) {
 	f, err := os.Open(filename)
 	if err != nil {
 		return nil, err
@@ -36,8 +49,8 @@ func ReadFile(filename string) ([]byte, os.Error) {
 	// read, so let's try it but be prepared for the answer to be wrong.
 	fi, err := f.Stat()
 	var n int64
-	if err == nil && fi.Size < 2e9 { // Don't preallocate a huge buffer, just in case.
-		n = fi.Size
+	if size := fi.Size(); err == nil && size < 2e9 { // Don't preallocate a huge buffer, just in case.
+		n = size
 	}
 	// As initial capacity for readAll, use n + a little extra in case Size is zero,
 	// and to avoid another allocation after Read has filled the buffer.  The readAll
@@ -50,7 +63,7 @@ func ReadFile(filename string) ([]byte, os.Error) {
 // WriteFile writes data to a file named by filename.
 // If the file does not exist, WriteFile creates it with permissions perm;
 // otherwise WriteFile truncates it before writing.
-func WriteFile(filename string, data []byte, perm uint32) os.Error {
+func WriteFile(filename string, data []byte, perm os.FileMode) error {
 	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
 	if err != nil {
 		return err
@@ -63,16 +76,16 @@ func WriteFile(filename string, data []byte, perm uint32) os.Error {
 	return err
 }
 
-// A fileInfoList implements sort.Interface.
-type fileInfoList []*os.FileInfo
+// byName implements sort.Interface.
+type byName []os.FileInfo
 
-func (f fileInfoList) Len() int           { return len(f) }
-func (f fileInfoList) Less(i, j int) bool { return f[i].Name < f[j].Name }
-func (f fileInfoList) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
+func (f byName) Len() int           { return len(f) }
+func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
+func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
 
 // ReadDir reads the directory named by dirname and returns
 // a list of sorted directory entries.
-func ReadDir(dirname string) ([]*os.FileInfo, os.Error) {
+func ReadDir(dirname string) ([]os.FileInfo, error) {
 	f, err := os.Open(dirname)
 	if err != nil {
 		return nil, err
@@ -82,19 +95,15 @@ func ReadDir(dirname string) ([]*os.FileInfo, os.Error) {
 	if err != nil {
 		return nil, err
 	}
-	fi := make(fileInfoList, len(list))
-	for i := range list {
-		fi[i] = &list[i]
-	}
-	sort.Sort(fi)
-	return fi, nil
+	sort.Sort(byName(list))
+	return list, nil
 }
 
 type nopCloser struct {
 	io.Reader
 }
 
-func (nopCloser) Close() os.Error { return nil }
+func (nopCloser) Close() error { return nil }
 
 // NopCloser returns a ReadCloser with a no-op Close method wrapping
 // the provided Reader r.
@@ -104,19 +113,23 @@ func NopCloser(r io.Reader) io.ReadCloser {
 
 type devNull int
 
-func (devNull) Write(p []byte) (int, os.Error) {
+// devNull implements ReaderFrom as an optimization so io.Copy to
+// ioutil.Discard can avoid doing unnecessary work.
+var _ io.ReaderFrom = devNull(0)
+
+func (devNull) Write(p []byte) (int, error) {
 	return len(p), nil
 }
 
 var blackHole = make([]byte, 8192)
 
-func (devNull) ReadFrom(r io.Reader) (n int64, err os.Error) {
+func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
 	readSize := 0
 	for {
 		readSize, err = r.Read(blackHole)
 		n += int64(readSize)
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				return n, nil
 			}
 			return
diff --git a/src/pkg/io/ioutil/ioutil_test.go b/src/pkg/io/ioutil/ioutil_test.go
index 55e4b2c..d9c43be 100644
--- a/src/pkg/io/ioutil/ioutil_test.go
+++ b/src/pkg/io/ioutil/ioutil_test.go
@@ -15,8 +15,8 @@ func checkSize(t *testing.T, path string, size int64) {
 	if err != nil {
 		t.Fatalf("Stat %q (looking for size %d): %s", path, size, err)
 	}
-	if dir.Size != size {
-		t.Errorf("Stat %q: size %d want %d", path, dir.Size, size)
+	if dir.Size() != size {
+		t.Errorf("Stat %q: size %d want %d", path, dir.Size(), size)
 	}
 }
 
@@ -37,7 +37,11 @@ func TestReadFile(t *testing.T) {
 }
 
 func TestWriteFile(t *testing.T) {
-	filename := "_test/rumpelstilzchen"
+	f, err := TempFile("", "ioutil-test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	filename := f.Name()
 	data := "Programming today is a race between software engineers striving to " +
 		"build bigger and better idiot-proof programs, and the Universe trying " +
 		"to produce bigger and better idiots. So far, the Universe is winning."
@@ -56,6 +60,7 @@ func TestWriteFile(t *testing.T) {
 	}
 
 	// cleanup
+	f.Close()
 	os.Remove(filename) // ignore error
 }
 
@@ -66,26 +71,26 @@ func TestReadDir(t *testing.T) {
 		t.Fatalf("ReadDir %s: error expected, none found", dirname)
 	}
 
-	dirname = "."
+	dirname = ".."
 	list, err := ReadDir(dirname)
 	if err != nil {
 		t.Fatalf("ReadDir %s: %v", dirname, err)
 	}
 
-	foundTest := false
-	foundTestDir := false
+	foundFile := false
+	foundSubDir := false
 	for _, dir := range list {
 		switch {
-		case dir.IsRegular() && dir.Name == "ioutil_test.go":
-			foundTest = true
-		case dir.IsDirectory() && dir.Name == "_test":
-			foundTestDir = true
+		case !dir.IsDir() && dir.Name() == "io_test.go":
+			foundFile = true
+		case dir.IsDir() && dir.Name() == "ioutil":
+			foundSubDir = true
 		}
 	}
-	if !foundTest {
-		t.Fatalf("ReadDir %s: test file not found", dirname)
+	if !foundFile {
+		t.Fatalf("ReadDir %s: io_test.go file not found", dirname)
 	}
-	if !foundTestDir {
-		t.Fatalf("ReadDir %s: _test directory not found", dirname)
+	if !foundSubDir {
+		t.Fatalf("ReadDir %s: ioutil directory not found", dirname)
 	}
 }
diff --git a/src/pkg/io/ioutil/tempfile.go b/src/pkg/io/ioutil/tempfile.go
index 8e681bd..645eed6 100644
--- a/src/pkg/io/ioutil/tempfile.go
+++ b/src/pkg/io/ioutil/tempfile.go
@@ -8,6 +8,7 @@ import (
 	"os"
 	"path/filepath"
 	"strconv"
+	"time"
 )
 
 // Random number state, accessed without lock; racy but harmless.
@@ -17,8 +18,7 @@ import (
 var rand uint32
 
 func reseed() uint32 {
-	sec, nsec, _ := os.Time()
-	return uint32(sec*1e9 + nsec + int64(os.Getpid()))
+	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
 }
 
 func nextSuffix() string {
@@ -40,7 +40,7 @@ func nextSuffix() string {
 // will not choose the same file.  The caller can use f.Name()
 // to find the name of the file.  It is the caller's responsibility to
 // remove the file when no longer needed.
-func TempFile(dir, prefix string) (f *os.File, err os.Error) {
+func TempFile(dir, prefix string) (f *os.File, err error) {
 	if dir == "" {
 		dir = os.TempDir()
 	}
@@ -49,7 +49,7 @@ func TempFile(dir, prefix string) (f *os.File, err os.Error) {
 	for i := 0; i < 10000; i++ {
 		name := filepath.Join(dir, prefix+nextSuffix())
 		f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
-		if pe, ok := err.(*os.PathError); ok && pe.Error == os.EEXIST {
+		if pe, ok := err.(*os.PathError); ok && pe.Err == os.EEXIST {
 			if nconflict++; nconflict > 10 {
 				rand = reseed()
 			}
@@ -67,7 +67,7 @@ func TempFile(dir, prefix string) (f *os.File, err os.Error) {
 // Multiple programs calling TempDir simultaneously
 // will not choose the same directory.  It is the caller's responsibility
 // to remove the directory when no longer needed.
-func TempDir(dir, prefix string) (name string, err os.Error) {
+func TempDir(dir, prefix string) (name string, err error) {
 	if dir == "" {
 		dir = os.TempDir()
 	}
@@ -76,7 +76,7 @@ func TempDir(dir, prefix string) (name string, err os.Error) {
 	for i := 0; i < 10000; i++ {
 		try := filepath.Join(dir, prefix+nextSuffix())
 		err = os.Mkdir(try, 0700)
-		if pe, ok := err.(*os.PathError); ok && pe.Error == os.EEXIST {
+		if pe, ok := err.(*os.PathError); ok && pe.Err == os.EEXIST {
 			if nconflict++; nconflict > 10 {
 				rand = reseed()
 			}
diff --git a/src/pkg/io/multi.go b/src/pkg/io/multi.go
index d702d46..2c7e816 100644
--- a/src/pkg/io/multi.go
+++ b/src/pkg/io/multi.go
@@ -4,17 +4,15 @@
 
 package io
 
-import "os"
-
 type multiReader struct {
 	readers []Reader
 }
 
-func (mr *multiReader) Read(p []byte) (n int, err os.Error) {
+func (mr *multiReader) Read(p []byte) (n int, err error) {
 	for len(mr.readers) > 0 {
 		n, err = mr.readers[0].Read(p)
-		if n > 0 || err != os.EOF {
-			if err == os.EOF {
+		if n > 0 || err != EOF {
+			if err == EOF {
 				// Don't return EOF yet. There may be more bytes
 				// in the remaining readers.
 				err = nil
@@ -23,12 +21,12 @@ func (mr *multiReader) Read(p []byte) (n int, err os.Error) {
 		}
 		mr.readers = mr.readers[1:]
 	}
-	return 0, os.EOF
+	return 0, EOF
 }
 
 // MultiReader returns a Reader that's the logical concatenation of
 // the provided input readers.  They're read sequentially.  Once all
-// inputs are drained, Read will return os.EOF.
+// inputs are drained, Read will return EOF.
 func MultiReader(readers ...Reader) Reader {
 	return &multiReader{readers}
 }
@@ -37,7 +35,7 @@ type multiWriter struct {
 	writers []Writer
 }
 
-func (t *multiWriter) Write(p []byte) (n int, err os.Error) {
+func (t *multiWriter) Write(p []byte) (n int, err error) {
 	for _, w := range t.writers {
 		n, err = w.Write(p)
 		if err != nil {
diff --git a/src/pkg/io/multi_test.go b/src/pkg/io/multi_test.go
index 1b3589d..eb717f7 100644
--- a/src/pkg/io/multi_test.go
+++ b/src/pkg/io/multi_test.go
@@ -5,11 +5,10 @@
 package io_test
 
 import (
-	. "io"
 	"bytes"
 	"crypto/sha1"
 	"fmt"
-	"os"
+	. "io"
 	"strings"
 	"testing"
 )
@@ -26,7 +25,7 @@ func TestMultiReader(t *testing.T) {
 		buf = make([]byte, 20)
 		tests()
 	}
-	expectRead := func(size int, expected string, eerr os.Error) {
+	expectRead := func(size int, expected string, eerr error) {
 		nread++
 		n, gerr := mr.Read(buf[0:size])
 		if n != len(expected) {
@@ -48,13 +47,13 @@ func TestMultiReader(t *testing.T) {
 		expectRead(2, "fo", nil)
 		expectRead(5, "o ", nil)
 		expectRead(5, "bar", nil)
-		expectRead(5, "", os.EOF)
+		expectRead(5, "", EOF)
 	})
 	withFooBar(func() {
 		expectRead(4, "foo ", nil)
 		expectRead(1, "b", nil)
 		expectRead(3, "ar", nil)
-		expectRead(1, "", os.EOF)
+		expectRead(1, "", EOF)
 	})
 	withFooBar(func() {
 		expectRead(5, "foo ", nil)
@@ -78,7 +77,7 @@ func TestMultiWriter(t *testing.T) {
 		t.Errorf("unexpected error: %v", err)
 	}
 
-	sha1hex := fmt.Sprintf("%x", sha1.Sum())
+	sha1hex := fmt.Sprintf("%x", sha1.Sum(nil))
 	if sha1hex != "01cb303fa8c30a64123067c5aa6284ba7ec2d31b" {
 		t.Error("incorrect sha1 value")
 	}
diff --git a/src/pkg/io/pipe.go b/src/pkg/io/pipe.go
index 00be8ef..3dcff0d 100644
--- a/src/pkg/io/pipe.go
+++ b/src/pkg/io/pipe.go
@@ -7,14 +7,14 @@
 
 package io
 
-import (
-	"os"
-	"sync"
-)
+import "sync"
+
+// ErrClosedPipe is the error used for read or write operations on a closed pipe.
+var ErrClosedPipe = &Error{"io: read/write on closed pipe"}
 
 type pipeResult struct {
 	n   int
-	err os.Error
+	err error
 }
 
 // A pipe is the shared pipe structure underlying PipeReader and PipeWriter.
@@ -25,11 +25,11 @@ type pipe struct {
 	data  []byte     // data remaining in pending write
 	rwait sync.Cond  // waiting reader
 	wwait sync.Cond  // waiting writer
-	rerr  os.Error   // if reader closed, error to give writes
-	werr  os.Error   // if writer closed, error to give reads
+	rerr  error      // if reader closed, error to give writes
+	werr  error      // if writer closed, error to give reads
 }
 
-func (p *pipe) read(b []byte) (n int, err os.Error) {
+func (p *pipe) read(b []byte) (n int, err error) {
 	// One reader at a time.
 	p.rl.Lock()
 	defer p.rl.Unlock()
@@ -38,7 +38,7 @@ func (p *pipe) read(b []byte) (n int, err os.Error) {
 	defer p.l.Unlock()
 	for {
 		if p.rerr != nil {
-			return 0, os.EINVAL
+			return 0, ErrClosedPipe
 		}
 		if p.data != nil {
 			break
@@ -59,7 +59,7 @@ func (p *pipe) read(b []byte) (n int, err os.Error) {
 
 var zero [0]byte
 
-func (p *pipe) write(b []byte) (n int, err os.Error) {
+func (p *pipe) write(b []byte) (n int, err error) {
 	// pipe uses nil to mean not available
 	if b == nil {
 		b = zero[:]
@@ -82,7 +82,7 @@ func (p *pipe) write(b []byte) (n int, err os.Error) {
 			break
 		}
 		if p.werr != nil {
-			err = os.EINVAL
+			err = ErrClosedPipe
 		}
 		p.wwait.Wait()
 	}
@@ -91,9 +91,9 @@ func (p *pipe) write(b []byte) (n int, err os.Error) {
 	return
 }
 
-func (p *pipe) rclose(err os.Error) {
+func (p *pipe) rclose(err error) {
 	if err == nil {
-		err = os.EPIPE
+		err = ErrClosedPipe
 	}
 	p.l.Lock()
 	defer p.l.Unlock()
@@ -102,9 +102,9 @@ func (p *pipe) rclose(err os.Error) {
 	p.wwait.Signal()
 }
 
-func (p *pipe) wclose(err os.Error) {
+func (p *pipe) wclose(err error) {
 	if err == nil {
-		err = os.EOF
+		err = EOF
 	}
 	p.l.Lock()
 	defer p.l.Unlock()
@@ -122,20 +122,20 @@ type PipeReader struct {
 // it reads data from the pipe, blocking until a writer
 // arrives or the write end is closed.
 // If the write end is closed with an error, that error is
-// returned as err; otherwise err is os.EOF.
-func (r *PipeReader) Read(data []byte) (n int, err os.Error) {
+// returned as err; otherwise err is EOF.
+func (r *PipeReader) Read(data []byte) (n int, err error) {
 	return r.p.read(data)
 }
 
 // Close closes the reader; subsequent writes to the
-// write half of the pipe will return the error os.EPIPE.
-func (r *PipeReader) Close() os.Error {
+// write half of the pipe will return the error ErrClosedPipe.
+func (r *PipeReader) Close() error {
 	return r.CloseWithError(nil)
 }
 
 // CloseWithError closes the reader; subsequent writes
 // to the write half of the pipe will return the error err.
-func (r *PipeReader) CloseWithError(err os.Error) os.Error {
+func (r *PipeReader) CloseWithError(err error) error {
 	r.p.rclose(err)
 	return nil
 }
@@ -149,20 +149,20 @@ type PipeWriter struct {
 // it writes data to the pipe, blocking until readers
 // have consumed all the data or the read end is closed.
 // If the read end is closed with an error, that err is
-// returned as err; otherwise err is os.EPIPE.
-func (w *PipeWriter) Write(data []byte) (n int, err os.Error) {
+// returned as err; otherwise err is ErrClosedPipe.
+func (w *PipeWriter) Write(data []byte) (n int, err error) {
 	return w.p.write(data)
 }
 
 // Close closes the writer; subsequent reads from the
-// read half of the pipe will return no bytes and os.EOF.
-func (w *PipeWriter) Close() os.Error {
+// read half of the pipe will return no bytes and EOF.
+func (w *PipeWriter) Close() error {
 	return w.CloseWithError(nil)
 }
 
 // CloseWithError closes the writer; subsequent reads from the
 // read half of the pipe will return no bytes and the error err.
-func (w *PipeWriter) CloseWithError(err os.Error) os.Error {
+func (w *PipeWriter) CloseWithError(err error) error {
 	w.p.wclose(err)
 	return nil
 }
diff --git a/src/pkg/io/pipe_test.go b/src/pkg/io/pipe_test.go
index bd4b94f..7718151 100644
--- a/src/pkg/io/pipe_test.go
+++ b/src/pkg/io/pipe_test.go
@@ -7,7 +7,6 @@ package io_test
 import (
 	"fmt"
 	. "io"
-	"os"
 	"testing"
 	"time"
 )
@@ -44,7 +43,7 @@ func reader(t *testing.T, r Reader, c chan int) {
 	var buf = make([]byte, 64)
 	for {
 		n, err := r.Read(buf)
-		if err == os.EOF {
+		if err == EOF {
 			c <- 0
 			break
 		}
@@ -84,7 +83,7 @@ func TestPipe2(t *testing.T) {
 
 type pipeReturn struct {
 	n   int
-	err os.Error
+	err error
 }
 
 // Test a large write that requires multiple reads to satisfy.
@@ -106,7 +105,7 @@ func TestPipe3(t *testing.T) {
 	tot := 0
 	for n := 1; n <= 256; n *= 2 {
 		nn, err := r.Read(rdat[tot : tot+n])
-		if err != nil && err != os.EOF {
+		if err != nil && err != EOF {
 			t.Fatalf("read: %v", err)
 		}
 
@@ -116,7 +115,7 @@ func TestPipe3(t *testing.T) {
 			expect = 1
 		} else if n == 256 {
 			expect = 0
-			if err != os.EOF {
+			if err != EOF {
 				t.Fatalf("read at end: %v", err)
 			}
 		}
@@ -142,13 +141,13 @@ func TestPipe3(t *testing.T) {
 // Test read after/before writer close.
 
 type closer interface {
-	CloseWithError(os.Error) os.Error
-	Close() os.Error
+	CloseWithError(error) error
+	Close() error
 }
 
 type pipeTest struct {
 	async          bool
-	err            os.Error
+	err            error
 	closeWithError bool
 }
 
@@ -166,8 +165,8 @@ var pipeTests = []pipeTest{
 }
 
 func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) {
-	time.Sleep(1e6) // 1 ms
-	var err os.Error
+	time.Sleep(1 * time.Millisecond)
+	var err error
 	if tt.closeWithError {
 		err = cl.CloseWithError(tt.err)
 	} else {
@@ -193,7 +192,7 @@ func TestPipeReadClose(t *testing.T) {
 		<-c
 		want := tt.err
 		if want == nil {
-			want = os.EOF
+			want = EOF
 		}
 		if err != want {
 			t.Errorf("read from closed pipe: %v want %v", err, want)
@@ -214,8 +213,8 @@ func TestPipeReadClose2(t *testing.T) {
 	go delayClose(t, r, c, pipeTest{})
 	n, err := r.Read(make([]byte, 64))
 	<-c
-	if n != 0 || err != os.EINVAL {
-		t.Errorf("read from closed pipe: %v, %v want %v, %v", n, err, 0, os.EINVAL)
+	if n != 0 || err != ErrClosedPipe {
+		t.Errorf("read from closed pipe: %v, %v want %v, %v", n, err, 0, ErrClosedPipe)
 	}
 }
 
@@ -234,7 +233,7 @@ func TestPipeWriteClose(t *testing.T) {
 		<-c
 		expect := tt.err
 		if expect == nil {
-			expect = os.EPIPE
+			expect = ErrClosedPipe
 		}
 		if err != expect {
 			t.Errorf("write on closed pipe: %v want %v", err, expect)
diff --git a/src/pkg/json/Makefile b/src/pkg/json/Makefile
deleted file mode 100644
index 28ed62b..0000000
--- a/src/pkg/json/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=json
-GOFILES=\
-	decode.go\
-	encode.go\
-	indent.go\
-	scanner.go\
-	stream.go\
-	tags.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/json/decode.go b/src/pkg/json/decode.go
deleted file mode 100644
index 5ac01e8..0000000
--- a/src/pkg/json/decode.go
+++ /dev/null
@@ -1,939 +0,0 @@
-// Copyright 2010 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.
-
-// Represents JSON data structure using native Go types: booleans, floats,
-// strings, arrays, and maps.
-
-package json
-
-import (
-	"encoding/base64"
-	"os"
-	"reflect"
-	"runtime"
-	"strconv"
-	"strings"
-	"unicode"
-	"utf16"
-	"utf8"
-)
-
-// Unmarshal parses the JSON-encoded data and stores the result
-// in the value pointed to by v.
-//
-// Unmarshal uses the inverse of the encodings that
-// Marshal uses, allocating maps, slices, and pointers as necessary,
-// with the following additional rules:
-//
-// To unmarshal JSON into a pointer, Unmarshal first handles the case of
-// the JSON being the JSON literal null.  In that case, Unmarshal sets
-// the pointer to nil.  Otherwise, Unmarshal unmarshals the JSON into
-// the value pointed at by the pointer.  If the pointer is nil, Unmarshal
-// allocates a new value for it to point to.
-//
-// To unmarshal JSON into an interface value, Unmarshal unmarshals
-// the JSON into the concrete value contained in the interface value.
-// If the interface value is nil, that is, has no concrete value stored in it,
-// Unmarshal stores one of these in the interface value:
-//
-//	bool, for JSON booleans
-//	float64, for JSON numbers
-//	string, for JSON strings
-//	[]interface{}, for JSON arrays
-//	map[string]interface{}, for JSON objects
-//	nil for JSON null
-//
-// If a JSON value is not appropriate for a given target type,
-// or if a JSON number overflows the target type, Unmarshal
-// skips that field and completes the unmarshalling as best it can.
-// If no more serious errors are encountered, Unmarshal returns
-// an UnmarshalTypeError describing the earliest such error.
-//
-func Unmarshal(data []byte, v interface{}) os.Error {
-	d := new(decodeState).init(data)
-
-	// Quick check for well-formedness.
-	// Avoids filling out half a data structure
-	// before discovering a JSON syntax error.
-	err := checkValid(data, &d.scan)
-	if err != nil {
-		return err
-	}
-
-	return d.unmarshal(v)
-}
-
-// Unmarshaler is the interface implemented by objects
-// that can unmarshal a JSON description of themselves.
-// The input can be assumed to be a valid JSON object
-// encoding.  UnmarshalJSON must copy the JSON data
-// if it wishes to retain the data after returning.
-type Unmarshaler interface {
-	UnmarshalJSON([]byte) os.Error
-}
-
-// An UnmarshalTypeError describes a JSON value that was
-// not appropriate for a value of a specific Go type.
-type UnmarshalTypeError struct {
-	Value string       // description of JSON value - "bool", "array", "number -5"
-	Type  reflect.Type // type of Go value it could not be assigned to
-}
-
-func (e *UnmarshalTypeError) String() string {
-	return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
-}
-
-// An UnmarshalFieldError describes a JSON object key that
-// led to an unexported (and therefore unwritable) struct field.
-type UnmarshalFieldError struct {
-	Key   string
-	Type  reflect.Type
-	Field reflect.StructField
-}
-
-func (e *UnmarshalFieldError) String() string {
-	return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
-}
-
-// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
-// (The argument to Unmarshal must be a non-nil pointer.)
-type InvalidUnmarshalError struct {
-	Type reflect.Type
-}
-
-func (e *InvalidUnmarshalError) String() string {
-	if e.Type == nil {
-		return "json: Unmarshal(nil)"
-	}
-
-	if e.Type.Kind() != reflect.Ptr {
-		return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
-	}
-	return "json: Unmarshal(nil " + e.Type.String() + ")"
-}
-
-func (d *decodeState) unmarshal(v interface{}) (err os.Error) {
-	defer func() {
-		if r := recover(); r != nil {
-			if _, ok := r.(runtime.Error); ok {
-				panic(r)
-			}
-			err = r.(os.Error)
-		}
-	}()
-
-	rv := reflect.ValueOf(v)
-	pv := rv
-	if pv.Kind() != reflect.Ptr || pv.IsNil() {
-		return &InvalidUnmarshalError{reflect.TypeOf(v)}
-	}
-
-	d.scan.reset()
-	// We decode rv not pv.Elem because the Unmarshaler interface
-	// test must be applied at the top level of the value.
-	d.value(rv)
-	return d.savedError
-}
-
-// decodeState represents the state while decoding a JSON value.
-type decodeState struct {
-	data       []byte
-	off        int // read offset in data
-	scan       scanner
-	nextscan   scanner // for calls to nextValue
-	savedError os.Error
-	tempstr    string // scratch space to avoid some allocations
-}
-
-// errPhase is used for errors that should not happen unless
-// there is a bug in the JSON decoder or something is editing
-// the data slice while the decoder executes.
-var errPhase = os.NewError("JSON decoder out of sync - data changing underfoot?")
-
-func (d *decodeState) init(data []byte) *decodeState {
-	d.data = data
-	d.off = 0
-	d.savedError = nil
-	return d
-}
-
-// error aborts the decoding by panicking with err.
-func (d *decodeState) error(err os.Error) {
-	panic(err)
-}
-
-// saveError saves the first err it is called with,
-// for reporting at the end of the unmarshal.
-func (d *decodeState) saveError(err os.Error) {
-	if d.savedError == nil {
-		d.savedError = err
-	}
-}
-
-// next cuts off and returns the next full JSON value in d.data[d.off:].
-// The next value is known to be an object or array, not a literal.
-func (d *decodeState) next() []byte {
-	c := d.data[d.off]
-	item, rest, err := nextValue(d.data[d.off:], &d.nextscan)
-	if err != nil {
-		d.error(err)
-	}
-	d.off = len(d.data) - len(rest)
-
-	// Our scanner has seen the opening brace/bracket
-	// and thinks we're still in the middle of the object.
-	// invent a closing brace/bracket to get it out.
-	if c == '{' {
-		d.scan.step(&d.scan, '}')
-	} else {
-		d.scan.step(&d.scan, ']')
-	}
-
-	return item
-}
-
-// scanWhile processes bytes in d.data[d.off:] until it
-// receives a scan code not equal to op.
-// It updates d.off and returns the new scan code.
-func (d *decodeState) scanWhile(op int) int {
-	var newOp int
-	for {
-		if d.off >= len(d.data) {
-			newOp = d.scan.eof()
-			d.off = len(d.data) + 1 // mark processed EOF with len+1
-		} else {
-			c := int(d.data[d.off])
-			d.off++
-			newOp = d.scan.step(&d.scan, c)
-		}
-		if newOp != op {
-			break
-		}
-	}
-	return newOp
-}
-
-// value decodes a JSON value from d.data[d.off:] into the value.
-// it updates d.off to point past the decoded value.
-func (d *decodeState) value(v reflect.Value) {
-	if !v.IsValid() {
-		_, rest, err := nextValue(d.data[d.off:], &d.nextscan)
-		if err != nil {
-			d.error(err)
-		}
-		d.off = len(d.data) - len(rest)
-
-		// d.scan thinks we're still at the beginning of the item.
-		// Feed in an empty string - the shortest, simplest value -
-		// so that it knows we got to the end of the value.
-		if d.scan.step == stateRedo {
-			panic("redo")
-		}
-		d.scan.step(&d.scan, '"')
-		d.scan.step(&d.scan, '"')
-		return
-	}
-
-	switch op := d.scanWhile(scanSkipSpace); op {
-	default:
-		d.error(errPhase)
-
-	case scanBeginArray:
-		d.array(v)
-
-	case scanBeginObject:
-		d.object(v)
-
-	case scanBeginLiteral:
-		d.literal(v)
-	}
-}
-
-// indirect walks down v allocating pointers as needed,
-// until it gets to a non-pointer.
-// if it encounters an Unmarshaler, indirect stops and returns that.
-// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
-func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) {
-	// If v is a named type and is addressable,
-	// start with its address, so that if the type has pointer methods,
-	// we find them.
-	if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
-		v = v.Addr()
-	}
-	for {
-		var isUnmarshaler bool
-		if v.Type().NumMethod() > 0 {
-			// Remember that this is an unmarshaler,
-			// but wait to return it until after allocating
-			// the pointer (if necessary).
-			_, isUnmarshaler = v.Interface().(Unmarshaler)
-		}
-
-		if iv := v; iv.Kind() == reflect.Interface && !iv.IsNil() {
-			v = iv.Elem()
-			continue
-		}
-
-		pv := v
-		if pv.Kind() != reflect.Ptr {
-			break
-		}
-
-		if pv.Elem().Kind() != reflect.Ptr && decodingNull && pv.CanSet() {
-			return nil, pv
-		}
-		if pv.IsNil() {
-			pv.Set(reflect.New(pv.Type().Elem()))
-		}
-		if isUnmarshaler {
-			// Using v.Interface().(Unmarshaler)
-			// here means that we have to use a pointer
-			// as the struct field.  We cannot use a value inside
-			// a pointer to a struct, because in that case
-			// v.Interface() is the value (x.f) not the pointer (&x.f).
-			// This is an unfortunate consequence of reflect.
-			// An alternative would be to look up the
-			// UnmarshalJSON method and return a FuncValue.
-			return v.Interface().(Unmarshaler), reflect.Value{}
-		}
-		v = pv.Elem()
-	}
-	return nil, v
-}
-
-// array consumes an array from d.data[d.off-1:], decoding into the value v.
-// the first byte of the array ('[') has been read already.
-func (d *decodeState) array(v reflect.Value) {
-	// Check for unmarshaler.
-	unmarshaler, pv := d.indirect(v, false)
-	if unmarshaler != nil {
-		d.off--
-		err := unmarshaler.UnmarshalJSON(d.next())
-		if err != nil {
-			d.error(err)
-		}
-		return
-	}
-	v = pv
-
-	// Decoding into nil interface?  Switch to non-reflect code.
-	iv := v
-	ok := iv.Kind() == reflect.Interface
-	if ok {
-		iv.Set(reflect.ValueOf(d.arrayInterface()))
-		return
-	}
-
-	// Check type of target.
-	av := v
-	if av.Kind() != reflect.Array && av.Kind() != reflect.Slice {
-		d.saveError(&UnmarshalTypeError{"array", v.Type()})
-		d.off--
-		d.next()
-		return
-	}
-
-	sv := v
-
-	i := 0
-	for {
-		// Look ahead for ] - can only happen on first iteration.
-		op := d.scanWhile(scanSkipSpace)
-		if op == scanEndArray {
-			break
-		}
-
-		// Back up so d.value can have the byte we just read.
-		d.off--
-		d.scan.undo(op)
-
-		// Get element of array, growing if necessary.
-		if i >= av.Cap() && sv.IsValid() {
-			newcap := sv.Cap() + sv.Cap()/2
-			if newcap < 4 {
-				newcap = 4
-			}
-			newv := reflect.MakeSlice(sv.Type(), sv.Len(), newcap)
-			reflect.Copy(newv, sv)
-			sv.Set(newv)
-		}
-		if i >= av.Len() && sv.IsValid() {
-			// Must be slice; gave up on array during i >= av.Cap().
-			sv.SetLen(i + 1)
-		}
-
-		// Decode into element.
-		if i < av.Len() {
-			d.value(av.Index(i))
-		} else {
-			// Ran out of fixed array: skip.
-			d.value(reflect.Value{})
-		}
-		i++
-
-		// Next token must be , or ].
-		op = d.scanWhile(scanSkipSpace)
-		if op == scanEndArray {
-			break
-		}
-		if op != scanArrayValue {
-			d.error(errPhase)
-		}
-	}
-	if i < av.Len() {
-		if !sv.IsValid() {
-			// Array.  Zero the rest.
-			z := reflect.Zero(av.Type().Elem())
-			for ; i < av.Len(); i++ {
-				av.Index(i).Set(z)
-			}
-		} else {
-			sv.SetLen(i)
-		}
-	}
-}
-
-// object consumes an object from d.data[d.off-1:], decoding into the value v.
-// the first byte of the object ('{') has been read already.
-func (d *decodeState) object(v reflect.Value) {
-	// Check for unmarshaler.
-	unmarshaler, pv := d.indirect(v, false)
-	if unmarshaler != nil {
-		d.off--
-		err := unmarshaler.UnmarshalJSON(d.next())
-		if err != nil {
-			d.error(err)
-		}
-		return
-	}
-	v = pv
-
-	// Decoding into nil interface?  Switch to non-reflect code.
-	iv := v
-	if iv.Kind() == reflect.Interface {
-		iv.Set(reflect.ValueOf(d.objectInterface()))
-		return
-	}
-
-	// Check type of target: struct or map[string]T
-	var (
-		mv reflect.Value
-		sv reflect.Value
-	)
-	switch v.Kind() {
-	case reflect.Map:
-		// map must have string type
-		t := v.Type()
-		if t.Key() != reflect.TypeOf("") {
-			d.saveError(&UnmarshalTypeError{"object", v.Type()})
-			break
-		}
-		mv = v
-		if mv.IsNil() {
-			mv.Set(reflect.MakeMap(t))
-		}
-	case reflect.Struct:
-		sv = v
-	default:
-		d.saveError(&UnmarshalTypeError{"object", v.Type()})
-	}
-
-	if !mv.IsValid() && !sv.IsValid() {
-		d.off--
-		d.next() // skip over { } in input
-		return
-	}
-
-	var mapElem reflect.Value
-
-	for {
-		// Read opening " of string key or closing }.
-		op := d.scanWhile(scanSkipSpace)
-		if op == scanEndObject {
-			// closing } - can only happen on first iteration.
-			break
-		}
-		if op != scanBeginLiteral {
-			d.error(errPhase)
-		}
-
-		// Read string key.
-		start := d.off - 1
-		op = d.scanWhile(scanContinue)
-		item := d.data[start : d.off-1]
-		key, ok := unquote(item)
-		if !ok {
-			d.error(errPhase)
-		}
-
-		// Figure out field corresponding to key.
-		var subv reflect.Value
-		destring := false // whether the value is wrapped in a string to be decoded first
-
-		if mv.IsValid() {
-			elemType := mv.Type().Elem()
-			if !mapElem.IsValid() {
-				mapElem = reflect.New(elemType).Elem()
-			} else {
-				mapElem.Set(reflect.Zero(elemType))
-			}
-			subv = mapElem
-		} else {
-			var f reflect.StructField
-			var ok bool
-			st := sv.Type()
-			for i := 0; i < sv.NumField(); i++ {
-				sf := st.Field(i)
-				tag := sf.Tag.Get("json")
-				if tag == "-" {
-					// Pretend this field doesn't exist.
-					continue
-				}
-				// First, tag match
-				tagName, _ := parseTag(tag)
-				if tagName == key {
-					f = sf
-					ok = true
-					break // no better match possible
-				}
-				// Second, exact field name match
-				if sf.Name == key {
-					f = sf
-					ok = true
-				}
-				// Third, case-insensitive field name match,
-				// but only if a better match hasn't already been seen
-				if !ok && strings.ToLower(sf.Name) == strings.ToLower(key) {
-					f = sf
-					ok = true
-				}
-			}
-
-			// Extract value; name must be exported.
-			if ok {
-				if f.PkgPath != "" {
-					d.saveError(&UnmarshalFieldError{key, st, f})
-				} else {
-					subv = sv.FieldByIndex(f.Index)
-				}
-				_, opts := parseTag(f.Tag.Get("json"))
-				destring = opts.Contains("string")
-			}
-		}
-
-		// Read : before value.
-		if op == scanSkipSpace {
-			op = d.scanWhile(scanSkipSpace)
-		}
-		if op != scanObjectKey {
-			d.error(errPhase)
-		}
-
-		// Read value.
-		if destring {
-			d.value(reflect.ValueOf(&d.tempstr))
-			d.literalStore([]byte(d.tempstr), subv)
-		} else {
-			d.value(subv)
-		}
-		// Write value back to map;
-		// if using struct, subv points into struct already.
-		if mv.IsValid() {
-			mv.SetMapIndex(reflect.ValueOf(key), subv)
-		}
-
-		// Next token must be , or }.
-		op = d.scanWhile(scanSkipSpace)
-		if op == scanEndObject {
-			break
-		}
-		if op != scanObjectValue {
-			d.error(errPhase)
-		}
-	}
-}
-
-// literal consumes a literal from d.data[d.off-1:], decoding into the value v.
-// The first byte of the literal has been read already
-// (that's how the caller knows it's a literal).
-func (d *decodeState) literal(v reflect.Value) {
-	// All bytes inside literal return scanContinue op code.
-	start := d.off - 1
-	op := d.scanWhile(scanContinue)
-
-	// Scan read one byte too far; back up.
-	d.off--
-	d.scan.undo(op)
-
-	d.literalStore(d.data[start:d.off], v)
-}
-
-// literalStore decodes a literal stored in item into v.
-func (d *decodeState) literalStore(item []byte, v reflect.Value) {
-	// Check for unmarshaler.
-	wantptr := item[0] == 'n' // null
-	unmarshaler, pv := d.indirect(v, wantptr)
-	if unmarshaler != nil {
-		err := unmarshaler.UnmarshalJSON(item)
-		if err != nil {
-			d.error(err)
-		}
-		return
-	}
-	v = pv
-
-	switch c := item[0]; c {
-	case 'n': // null
-		switch v.Kind() {
-		default:
-			d.saveError(&UnmarshalTypeError{"null", v.Type()})
-		case reflect.Interface, reflect.Ptr, reflect.Map:
-			v.Set(reflect.Zero(v.Type()))
-		}
-
-	case 't', 'f': // true, false
-		value := c == 't'
-		switch v.Kind() {
-		default:
-			d.saveError(&UnmarshalTypeError{"bool", v.Type()})
-		case reflect.Bool:
-			v.SetBool(value)
-		case reflect.Interface:
-			v.Set(reflect.ValueOf(value))
-		}
-
-	case '"': // string
-		s, ok := unquoteBytes(item)
-		if !ok {
-			d.error(errPhase)
-		}
-		switch v.Kind() {
-		default:
-			d.saveError(&UnmarshalTypeError{"string", v.Type()})
-		case reflect.Slice:
-			if v.Type() != byteSliceType {
-				d.saveError(&UnmarshalTypeError{"string", v.Type()})
-				break
-			}
-			b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
-			n, err := base64.StdEncoding.Decode(b, s)
-			if err != nil {
-				d.saveError(err)
-				break
-			}
-			v.Set(reflect.ValueOf(b[0:n]))
-		case reflect.String:
-			v.SetString(string(s))
-		case reflect.Interface:
-			v.Set(reflect.ValueOf(string(s)))
-		}
-
-	default: // number
-		if c != '-' && (c < '0' || c > '9') {
-			d.error(errPhase)
-		}
-		s := string(item)
-		switch v.Kind() {
-		default:
-			d.error(&UnmarshalTypeError{"number", v.Type()})
-		case reflect.Interface:
-			n, err := strconv.Atof64(s)
-			if err != nil {
-				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
-				break
-			}
-			v.Set(reflect.ValueOf(n))
-
-		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-			n, err := strconv.Atoi64(s)
-			if err != nil || v.OverflowInt(n) {
-				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
-				break
-			}
-			v.SetInt(n)
-
-		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-			n, err := strconv.Atoui64(s)
-			if err != nil || v.OverflowUint(n) {
-				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
-				break
-			}
-			v.SetUint(n)
-
-		case reflect.Float32, reflect.Float64:
-			n, err := strconv.AtofN(s, v.Type().Bits())
-			if err != nil || v.OverflowFloat(n) {
-				d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
-				break
-			}
-			v.SetFloat(n)
-		}
-	}
-}
-
-// The xxxInterface routines build up a value to be stored
-// in an empty interface.  They are not strictly necessary,
-// but they avoid the weight of reflection in this common case.
-
-// valueInterface is like value but returns interface{}
-func (d *decodeState) valueInterface() interface{} {
-	switch d.scanWhile(scanSkipSpace) {
-	default:
-		d.error(errPhase)
-	case scanBeginArray:
-		return d.arrayInterface()
-	case scanBeginObject:
-		return d.objectInterface()
-	case scanBeginLiteral:
-		return d.literalInterface()
-	}
-	panic("unreachable")
-}
-
-// arrayInterface is like array but returns []interface{}.
-func (d *decodeState) arrayInterface() []interface{} {
-	var v []interface{}
-	for {
-		// Look ahead for ] - can only happen on first iteration.
-		op := d.scanWhile(scanSkipSpace)
-		if op == scanEndArray {
-			break
-		}
-
-		// Back up so d.value can have the byte we just read.
-		d.off--
-		d.scan.undo(op)
-
-		v = append(v, d.valueInterface())
-
-		// Next token must be , or ].
-		op = d.scanWhile(scanSkipSpace)
-		if op == scanEndArray {
-			break
-		}
-		if op != scanArrayValue {
-			d.error(errPhase)
-		}
-	}
-	return v
-}
-
-// objectInterface is like object but returns map[string]interface{}.
-func (d *decodeState) objectInterface() map[string]interface{} {
-	m := make(map[string]interface{})
-	for {
-		// Read opening " of string key or closing }.
-		op := d.scanWhile(scanSkipSpace)
-		if op == scanEndObject {
-			// closing } - can only happen on first iteration.
-			break
-		}
-		if op != scanBeginLiteral {
-			d.error(errPhase)
-		}
-
-		// Read string key.
-		start := d.off - 1
-		op = d.scanWhile(scanContinue)
-		item := d.data[start : d.off-1]
-		key, ok := unquote(item)
-		if !ok {
-			d.error(errPhase)
-		}
-
-		// Read : before value.
-		if op == scanSkipSpace {
-			op = d.scanWhile(scanSkipSpace)
-		}
-		if op != scanObjectKey {
-			d.error(errPhase)
-		}
-
-		// Read value.
-		m[key] = d.valueInterface()
-
-		// Next token must be , or }.
-		op = d.scanWhile(scanSkipSpace)
-		if op == scanEndObject {
-			break
-		}
-		if op != scanObjectValue {
-			d.error(errPhase)
-		}
-	}
-	return m
-}
-
-// literalInterface is like literal but returns an interface value.
-func (d *decodeState) literalInterface() interface{} {
-	// All bytes inside literal return scanContinue op code.
-	start := d.off - 1
-	op := d.scanWhile(scanContinue)
-
-	// Scan read one byte too far; back up.
-	d.off--
-	d.scan.undo(op)
-	item := d.data[start:d.off]
-
-	switch c := item[0]; c {
-	case 'n': // null
-		return nil
-
-	case 't', 'f': // true, false
-		return c == 't'
-
-	case '"': // string
-		s, ok := unquote(item)
-		if !ok {
-			d.error(errPhase)
-		}
-		return s
-
-	default: // number
-		if c != '-' && (c < '0' || c > '9') {
-			d.error(errPhase)
-		}
-		n, err := strconv.Atof64(string(item))
-		if err != nil {
-			d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
-		}
-		return n
-	}
-	panic("unreachable")
-}
-
-// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
-// or it returns -1.
-func getu4(s []byte) int {
-	if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
-		return -1
-	}
-	rune, err := strconv.Btoui64(string(s[2:6]), 16)
-	if err != nil {
-		return -1
-	}
-	return int(rune)
-}
-
-// unquote converts a quoted JSON string literal s into an actual string t.
-// The rules are different than for Go, so cannot use strconv.Unquote.
-func unquote(s []byte) (t string, ok bool) {
-	s, ok = unquoteBytes(s)
-	t = string(s)
-	return
-}
-
-func unquoteBytes(s []byte) (t []byte, ok bool) {
-	if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
-		return
-	}
-	s = s[1 : len(s)-1]
-
-	// Check for unusual characters. If there are none,
-	// then no unquoting is needed, so return a slice of the
-	// original bytes.
-	r := 0
-	for r < len(s) {
-		c := s[r]
-		if c == '\\' || c == '"' || c < ' ' {
-			break
-		}
-		if c < utf8.RuneSelf {
-			r++
-			continue
-		}
-		rune, size := utf8.DecodeRune(s[r:])
-		if rune == utf8.RuneError && size == 1 {
-			break
-		}
-		r += size
-	}
-	if r == len(s) {
-		return s, true
-	}
-
-	b := make([]byte, len(s)+2*utf8.UTFMax)
-	w := copy(b, s[0:r])
-	for r < len(s) {
-		// Out of room?  Can only happen if s is full of
-		// malformed UTF-8 and we're replacing each
-		// byte with RuneError.
-		if w >= len(b)-2*utf8.UTFMax {
-			nb := make([]byte, (len(b)+utf8.UTFMax)*2)
-			copy(nb, b[0:w])
-			b = nb
-		}
-		switch c := s[r]; {
-		case c == '\\':
-			r++
-			if r >= len(s) {
-				return
-			}
-			switch s[r] {
-			default:
-				return
-			case '"', '\\', '/', '\'':
-				b[w] = s[r]
-				r++
-				w++
-			case 'b':
-				b[w] = '\b'
-				r++
-				w++
-			case 'f':
-				b[w] = '\f'
-				r++
-				w++
-			case 'n':
-				b[w] = '\n'
-				r++
-				w++
-			case 'r':
-				b[w] = '\r'
-				r++
-				w++
-			case 't':
-				b[w] = '\t'
-				r++
-				w++
-			case 'u':
-				r--
-				rune := getu4(s[r:])
-				if rune < 0 {
-					return
-				}
-				r += 6
-				if utf16.IsSurrogate(rune) {
-					rune1 := getu4(s[r:])
-					if dec := utf16.DecodeRune(rune, rune1); dec != unicode.ReplacementChar {
-						// A valid pair; consume.
-						r += 6
-						w += utf8.EncodeRune(b[w:], dec)
-						break
-					}
-					// Invalid surrogate; fall back to replacement rune.
-					rune = unicode.ReplacementChar
-				}
-				w += utf8.EncodeRune(b[w:], rune)
-			}
-
-		// Quote, control characters are invalid.
-		case c == '"', c < ' ':
-			return
-
-		// ASCII
-		case c < utf8.RuneSelf:
-			b[w] = c
-			r++
-			w++
-
-		// Coerce to well-formed UTF-8.
-		default:
-			rune, size := utf8.DecodeRune(s[r:])
-			r += size
-			w += utf8.EncodeRune(b[w:], rune)
-		}
-	}
-	return b[0:w], true
-}
diff --git a/src/pkg/json/decode_test.go b/src/pkg/json/decode_test.go
deleted file mode 100644
index 2c7cbc4..0000000
--- a/src/pkg/json/decode_test.go
+++ /dev/null
@@ -1,565 +0,0 @@
-// Copyright 2010 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 json
-
-import (
-	"bytes"
-	"os"
-	"reflect"
-	"strings"
-	"testing"
-)
-
-type T struct {
-	X string
-	Y int
-	Z int `json:"-"`
-}
-
-type tx struct {
-	x int
-}
-
-var txType = reflect.TypeOf((*tx)(nil)).Elem()
-
-// A type that can unmarshal itself.
-
-type unmarshaler struct {
-	T bool
-}
-
-func (u *unmarshaler) UnmarshalJSON(b []byte) os.Error {
-	*u = unmarshaler{true} // All we need to see that UnmarshalJson is called.
-	return nil
-}
-
-type ustruct struct {
-	M unmarshaler
-}
-
-var (
-	um0, um1 unmarshaler // target2 of unmarshaling
-	ump      = &um1
-	umtrue   = unmarshaler{true}
-	umslice  = []unmarshaler{{true}}
-	umslicep = new([]unmarshaler)
-	umstruct = ustruct{unmarshaler{true}}
-)
-
-type unmarshalTest struct {
-	in  string
-	ptr interface{}
-	out interface{}
-	err os.Error
-}
-
-var unmarshalTests = []unmarshalTest{
-	// basic types
-	{`true`, new(bool), true, nil},
-	{`1`, new(int), 1, nil},
-	{`1.2`, new(float64), 1.2, nil},
-	{`-5`, new(int16), int16(-5), nil},
-	{`"a\u1234"`, new(string), "a\u1234", nil},
-	{`"http:\/\/"`, new(string), "http://", nil},
-	{`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
-	{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
-	{"null", new(interface{}), nil, nil},
-	{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
-	{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
-
-	// Z has a "-" tag.
-	{`{"Y": 1, "Z": 2}`, new(T), T{Y: 1}, nil},
-
-	// syntax errors
-	{`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
-
-	// composite tests
-	{allValueIndent, new(All), allValue, nil},
-	{allValueCompact, new(All), allValue, nil},
-	{allValueIndent, new(*All), &allValue, nil},
-	{allValueCompact, new(*All), &allValue, nil},
-	{pallValueIndent, new(All), pallValue, nil},
-	{pallValueCompact, new(All), pallValue, nil},
-	{pallValueIndent, new(*All), &pallValue, nil},
-	{pallValueCompact, new(*All), &pallValue, nil},
-
-	// unmarshal interface test
-	{`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called
-	{`{"T":false}`, &ump, &umtrue, nil},
-	{`[{"T":false}]`, &umslice, umslice, nil},
-	{`[{"T":false}]`, &umslicep, &umslice, nil},
-	{`{"M":{"T":false}}`, &umstruct, umstruct, nil},
-}
-
-func TestMarshal(t *testing.T) {
-	b, err := Marshal(allValue)
-	if err != nil {
-		t.Fatalf("Marshal allValue: %v", err)
-	}
-	if string(b) != allValueCompact {
-		t.Errorf("Marshal allValueCompact")
-		diff(t, b, []byte(allValueCompact))
-		return
-	}
-
-	b, err = Marshal(pallValue)
-	if err != nil {
-		t.Fatalf("Marshal pallValue: %v", err)
-	}
-	if string(b) != pallValueCompact {
-		t.Errorf("Marshal pallValueCompact")
-		diff(t, b, []byte(pallValueCompact))
-		return
-	}
-}
-
-func TestMarshalBadUTF8(t *testing.T) {
-	s := "hello\xffworld"
-	b, err := Marshal(s)
-	if err == nil {
-		t.Fatal("Marshal bad UTF8: no error")
-	}
-	if len(b) != 0 {
-		t.Fatal("Marshal returned data")
-	}
-	if _, ok := err.(*InvalidUTF8Error); !ok {
-		t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err)
-	}
-}
-
-func TestUnmarshal(t *testing.T) {
-	for i, tt := range unmarshalTests {
-		var scan scanner
-		in := []byte(tt.in)
-		if err := checkValid(in, &scan); err != nil {
-			if !reflect.DeepEqual(err, tt.err) {
-				t.Errorf("#%d: checkValid: %#v", i, err)
-				continue
-			}
-		}
-		if tt.ptr == nil {
-			continue
-		}
-		// v = new(right-type)
-		v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
-		if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
-			t.Errorf("#%d: %v want %v", i, err, tt.err)
-			continue
-		}
-		if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
-			t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
-			data, _ := Marshal(v.Elem().Interface())
-			println(string(data))
-			data, _ = Marshal(tt.out)
-			println(string(data))
-			continue
-		}
-	}
-}
-
-func TestUnmarshalMarshal(t *testing.T) {
-	initBig()
-	var v interface{}
-	if err := Unmarshal(jsonBig, &v); err != nil {
-		t.Fatalf("Unmarshal: %v", err)
-	}
-	b, err := Marshal(v)
-	if err != nil {
-		t.Fatalf("Marshal: %v", err)
-	}
-	if bytes.Compare(jsonBig, b) != 0 {
-		t.Errorf("Marshal jsonBig")
-		diff(t, b, jsonBig)
-		return
-	}
-}
-
-func TestLargeByteSlice(t *testing.T) {
-	s0 := make([]byte, 2000)
-	for i := range s0 {
-		s0[i] = byte(i)
-	}
-	b, err := Marshal(s0)
-	if err != nil {
-		t.Fatalf("Marshal: %v", err)
-	}
-	var s1 []byte
-	if err := Unmarshal(b, &s1); err != nil {
-		t.Fatalf("Unmarshal: %v", err)
-	}
-	if bytes.Compare(s0, s1) != 0 {
-		t.Errorf("Marshal large byte slice")
-		diff(t, s0, s1)
-	}
-}
-
-type Xint struct {
-	X int
-}
-
-func TestUnmarshalInterface(t *testing.T) {
-	var xint Xint
-	var i interface{} = &xint
-	if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
-		t.Fatalf("Unmarshal: %v", err)
-	}
-	if xint.X != 1 {
-		t.Fatalf("Did not write to xint")
-	}
-}
-
-func TestUnmarshalPtrPtr(t *testing.T) {
-	var xint Xint
-	pxint := &xint
-	if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
-		t.Fatalf("Unmarshal: %v", err)
-	}
-	if xint.X != 1 {
-		t.Fatalf("Did not write to xint")
-	}
-}
-
-func TestEscape(t *testing.T) {
-	const input = `"foobar"<html>`
-	const expected = `"\"foobar\"\u003chtml\u003e"`
-	b, err := Marshal(input)
-	if err != nil {
-		t.Fatalf("Marshal error: %v", err)
-	}
-	if s := string(b); s != expected {
-		t.Errorf("Encoding of [%s] was [%s], want [%s]", input, s, expected)
-	}
-}
-
-func TestHTMLEscape(t *testing.T) {
-	b, err := MarshalForHTML("foobarbaz<>&quux")
-	if err != nil {
-		t.Fatalf("MarshalForHTML error: %v", err)
-	}
-	if !bytes.Equal(b, []byte(`"foobarbaz\u003c\u003e\u0026quux"`)) {
-		t.Fatalf("Unexpected encoding of \"<>&\": %s", b)
-	}
-}
-
-func noSpace(c int) int {
-	if isSpace(c) {
-		return -1
-	}
-	return c
-}
-
-type All struct {
-	Bool    bool
-	Int     int
-	Int8    int8
-	Int16   int16
-	Int32   int32
-	Int64   int64
-	Uint    uint
-	Uint8   uint8
-	Uint16  uint16
-	Uint32  uint32
-	Uint64  uint64
-	Uintptr uintptr
-	Float32 float32
-	Float64 float64
-
-	Foo  string `json:"bar"`
-	Foo2 string `json:"bar2,dummyopt"`
-
-	IntStr int64 `json:",string"`
-
-	PBool    *bool
-	PInt     *int
-	PInt8    *int8
-	PInt16   *int16
-	PInt32   *int32
-	PInt64   *int64
-	PUint    *uint
-	PUint8   *uint8
-	PUint16  *uint16
-	PUint32  *uint32
-	PUint64  *uint64
-	PUintptr *uintptr
-	PFloat32 *float32
-	PFloat64 *float64
-
-	String  string
-	PString *string
-
-	Map   map[string]Small
-	MapP  map[string]*Small
-	PMap  *map[string]Small
-	PMapP *map[string]*Small
-
-	EmptyMap map[string]Small
-	NilMap   map[string]Small
-
-	Slice   []Small
-	SliceP  []*Small
-	PSlice  *[]Small
-	PSliceP *[]*Small
-
-	EmptySlice []Small
-	NilSlice   []Small
-
-	StringSlice []string
-	ByteSlice   []byte
-
-	Small   Small
-	PSmall  *Small
-	PPSmall **Small
-
-	Interface  interface{}
-	PInterface *interface{}
-
-	unexported int
-}
-
-type Small struct {
-	Tag string
-}
-
-var allValue = All{
-	Bool:    true,
-	Int:     2,
-	Int8:    3,
-	Int16:   4,
-	Int32:   5,
-	Int64:   6,
-	Uint:    7,
-	Uint8:   8,
-	Uint16:  9,
-	Uint32:  10,
-	Uint64:  11,
-	Uintptr: 12,
-	Float32: 14.1,
-	Float64: 15.1,
-	Foo:     "foo",
-	Foo2:    "foo2",
-	IntStr:  42,
-	String:  "16",
-	Map: map[string]Small{
-		"17": {Tag: "tag17"},
-		"18": {Tag: "tag18"},
-	},
-	MapP: map[string]*Small{
-		"19": &Small{Tag: "tag19"},
-		"20": nil,
-	},
-	EmptyMap:    map[string]Small{},
-	Slice:       []Small{{Tag: "tag20"}, {Tag: "tag21"}},
-	SliceP:      []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}},
-	EmptySlice:  []Small{},
-	StringSlice: []string{"str24", "str25", "str26"},
-	ByteSlice:   []byte{27, 28, 29},
-	Small:       Small{Tag: "tag30"},
-	PSmall:      &Small{Tag: "tag31"},
-	Interface:   5.2,
-}
-
-var pallValue = All{
-	PBool:      &allValue.Bool,
-	PInt:       &allValue.Int,
-	PInt8:      &allValue.Int8,
-	PInt16:     &allValue.Int16,
-	PInt32:     &allValue.Int32,
-	PInt64:     &allValue.Int64,
-	PUint:      &allValue.Uint,
-	PUint8:     &allValue.Uint8,
-	PUint16:    &allValue.Uint16,
-	PUint32:    &allValue.Uint32,
-	PUint64:    &allValue.Uint64,
-	PUintptr:   &allValue.Uintptr,
-	PFloat32:   &allValue.Float32,
-	PFloat64:   &allValue.Float64,
-	PString:    &allValue.String,
-	PMap:       &allValue.Map,
-	PMapP:      &allValue.MapP,
-	PSlice:     &allValue.Slice,
-	PSliceP:    &allValue.SliceP,
-	PPSmall:    &allValue.PSmall,
-	PInterface: &allValue.Interface,
-}
-
-var allValueIndent = `{
-	"Bool": true,
-	"Int": 2,
-	"Int8": 3,
-	"Int16": 4,
-	"Int32": 5,
-	"Int64": 6,
-	"Uint": 7,
-	"Uint8": 8,
-	"Uint16": 9,
-	"Uint32": 10,
-	"Uint64": 11,
-	"Uintptr": 12,
-	"Float32": 14.1,
-	"Float64": 15.1,
-	"bar": "foo",
-	"bar2": "foo2",
-	"IntStr": "42",
-	"PBool": null,
-	"PInt": null,
-	"PInt8": null,
-	"PInt16": null,
-	"PInt32": null,
-	"PInt64": null,
-	"PUint": null,
-	"PUint8": null,
-	"PUint16": null,
-	"PUint32": null,
-	"PUint64": null,
-	"PUintptr": null,
-	"PFloat32": null,
-	"PFloat64": null,
-	"String": "16",
-	"PString": null,
-	"Map": {
-		"17": {
-			"Tag": "tag17"
-		},
-		"18": {
-			"Tag": "tag18"
-		}
-	},
-	"MapP": {
-		"19": {
-			"Tag": "tag19"
-		},
-		"20": null
-	},
-	"PMap": null,
-	"PMapP": null,
-	"EmptyMap": {},
-	"NilMap": null,
-	"Slice": [
-		{
-			"Tag": "tag20"
-		},
-		{
-			"Tag": "tag21"
-		}
-	],
-	"SliceP": [
-		{
-			"Tag": "tag22"
-		},
-		null,
-		{
-			"Tag": "tag23"
-		}
-	],
-	"PSlice": null,
-	"PSliceP": null,
-	"EmptySlice": [],
-	"NilSlice": [],
-	"StringSlice": [
-		"str24",
-		"str25",
-		"str26"
-	],
-	"ByteSlice": "Gxwd",
-	"Small": {
-		"Tag": "tag30"
-	},
-	"PSmall": {
-		"Tag": "tag31"
-	},
-	"PPSmall": null,
-	"Interface": 5.2,
-	"PInterface": null
-}`
-
-var allValueCompact = strings.Map(noSpace, allValueIndent)
-
-var pallValueIndent = `{
-	"Bool": false,
-	"Int": 0,
-	"Int8": 0,
-	"Int16": 0,
-	"Int32": 0,
-	"Int64": 0,
-	"Uint": 0,
-	"Uint8": 0,
-	"Uint16": 0,
-	"Uint32": 0,
-	"Uint64": 0,
-	"Uintptr": 0,
-	"Float32": 0,
-	"Float64": 0,
-	"bar": "",
-	"bar2": "",
-        "IntStr": "0",
-	"PBool": true,
-	"PInt": 2,
-	"PInt8": 3,
-	"PInt16": 4,
-	"PInt32": 5,
-	"PInt64": 6,
-	"PUint": 7,
-	"PUint8": 8,
-	"PUint16": 9,
-	"PUint32": 10,
-	"PUint64": 11,
-	"PUintptr": 12,
-	"PFloat32": 14.1,
-	"PFloat64": 15.1,
-	"String": "",
-	"PString": "16",
-	"Map": null,
-	"MapP": null,
-	"PMap": {
-		"17": {
-			"Tag": "tag17"
-		},
-		"18": {
-			"Tag": "tag18"
-		}
-	},
-	"PMapP": {
-		"19": {
-			"Tag": "tag19"
-		},
-		"20": null
-	},
-	"EmptyMap": null,
-	"NilMap": null,
-	"Slice": [],
-	"SliceP": [],
-	"PSlice": [
-		{
-			"Tag": "tag20"
-		},
-		{
-			"Tag": "tag21"
-		}
-	],
-	"PSliceP": [
-		{
-			"Tag": "tag22"
-		},
-		null,
-		{
-			"Tag": "tag23"
-		}
-	],
-	"EmptySlice": [],
-	"NilSlice": [],
-	"StringSlice": [],
-	"ByteSlice": "",
-	"Small": {
-		"Tag": ""
-	},
-	"PSmall": null,
-	"PPSmall": {
-		"Tag": "tag31"
-	},
-	"Interface": null,
-	"PInterface": 5.2
-}`
-
-var pallValueCompact = strings.Map(noSpace, pallValueIndent)
diff --git a/src/pkg/json/encode.go b/src/pkg/json/encode.go
deleted file mode 100644
index 46abe43..0000000
--- a/src/pkg/json/encode.go
+++ /dev/null
@@ -1,465 +0,0 @@
-// Copyright 2010 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 json implements encoding and decoding of JSON objects as defined in
-// RFC 4627.
-//
-// See "JSON and Go" for an introduction to this package:
-// http://blog.golang.org/2011/01/json-and-go.html
-package json
-
-import (
-	"bytes"
-	"encoding/base64"
-	"os"
-	"reflect"
-	"runtime"
-	"sort"
-	"strconv"
-	"unicode"
-	"utf8"
-)
-
-// Marshal returns the JSON encoding of v.
-//
-// Marshal traverses the value v recursively.
-// If an encountered value implements the Marshaler interface
-// and is not a nil pointer, Marshal calls its MarshalJSON method
-// to produce JSON.  The nil pointer exception is not strictly necessary
-// but mimics a similar, necessary exception in the behavior of
-// UnmarshalJSON.
-//
-// Otherwise, Marshal uses the following type-dependent default encodings:
-//
-// Boolean values encode as JSON booleans.
-//
-// Floating point and integer values encode as JSON numbers.
-//
-// String values encode as JSON strings, with each invalid UTF-8 sequence
-// replaced by the encoding of the Unicode replacement character U+FFFD.
-//
-// Array and slice values encode as JSON arrays, except that
-// []byte encodes as a base64-encoded string.
-//
-// Struct values encode as JSON objects. Each exported struct field
-// becomes a member of the object unless
-//   - the field's tag is "-", or
-//   - the field is empty and its tag specifies the "omitempty" option.
-// The empty values are false, 0, any
-// nil pointer or interface value, and any array, slice, map, or string of
-// length zero. The object's default key string is the struct field name
-// but can be specified in the struct field's tag value. The "json" key in
-// struct field's tag value is the key name, followed by an optional comma
-// and options. Examples:
-//
-//   // Field is ignored by this package.
-//   Field int `json:"-"`
-//
-//   // Field appears in JSON as key "myName".
-//   Field int `json:"myName"`
-//
-//   // Field appears in JSON as key "myName" and
-//   // the field is omitted from the object if its value is empty,
-//   // as defined above.
-//   Field int `json:"myName,omitempty"`
-//
-//   // Field appears in JSON as key "Field" (the default), but
-//   // the field is skipped if empty.
-//   // Note the leading comma.
-//   Field int `json:",omitempty"`
-//
-// The "string" option signals that a field is stored as JSON inside a
-// JSON-encoded string.  This extra level of encoding is sometimes
-// used when communicating with JavaScript programs:
-//
-//    Int64String int64 `json:",string"`
-//
-// The key name will be used if it's a non-empty string consisting of
-// only Unicode letters, digits, dollar signs, hyphens, and underscores.
-//
-// Map values encode as JSON objects.
-// The map's key type must be string; the object keys are used directly
-// as map keys.
-//
-// Pointer values encode as the value pointed to.
-// A nil pointer encodes as the null JSON object.
-//
-// Interface values encode as the value contained in the interface.
-// A nil interface value encodes as the null JSON object.
-//
-// Channel, complex, and function values cannot be encoded in JSON.
-// Attempting to encode such a value causes Marshal to return
-// an InvalidTypeError.
-//
-// JSON cannot represent cyclic data structures and Marshal does not
-// handle them.  Passing cyclic structures to Marshal will result in
-// an infinite recursion.
-//
-func Marshal(v interface{}) ([]byte, os.Error) {
-	e := &encodeState{}
-	err := e.marshal(v)
-	if err != nil {
-		return nil, err
-	}
-	return e.Bytes(), nil
-}
-
-// MarshalIndent is like Marshal but applies Indent to format the output.
-func MarshalIndent(v interface{}, prefix, indent string) ([]byte, os.Error) {
-	b, err := Marshal(v)
-	if err != nil {
-		return nil, err
-	}
-	var buf bytes.Buffer
-	err = Indent(&buf, b, prefix, indent)
-	if err != nil {
-		return nil, err
-	}
-	return buf.Bytes(), nil
-}
-
-// MarshalForHTML is like Marshal but applies HTMLEscape to the output.
-func MarshalForHTML(v interface{}) ([]byte, os.Error) {
-	b, err := Marshal(v)
-	if err != nil {
-		return nil, err
-	}
-	var buf bytes.Buffer
-	HTMLEscape(&buf, b)
-	return buf.Bytes(), nil
-}
-
-// HTMLEscape appends to dst the JSON-encoded src with <, >, and &
-// characters inside string literals changed to \u003c, \u003e, \u0026
-// so that the JSON will be safe to embed inside HTML <script> tags.
-// For historical reasons, web browsers don't honor standard HTML
-// escaping within <script> tags, so an alternative JSON encoding must
-// be used.
-func HTMLEscape(dst *bytes.Buffer, src []byte) {
-	// < > & can only appear in string literals,
-	// so just scan the string one byte at a time.
-	start := 0
-	for i, c := range src {
-		if c == '<' || c == '>' || c == '&' {
-			if start < i {
-				dst.Write(src[start:i])
-			}
-			dst.WriteString(`\u00`)
-			dst.WriteByte(hex[c>>4])
-			dst.WriteByte(hex[c&0xF])
-			start = i + 1
-		}
-	}
-	if start < len(src) {
-		dst.Write(src[start:])
-	}
-}
-
-// Marshaler is the interface implemented by objects that
-// can marshal themselves into valid JSON.
-type Marshaler interface {
-	MarshalJSON() ([]byte, os.Error)
-}
-
-type UnsupportedTypeError struct {
-	Type reflect.Type
-}
-
-func (e *UnsupportedTypeError) String() string {
-	return "json: unsupported type: " + e.Type.String()
-}
-
-type InvalidUTF8Error struct {
-	S string
-}
-
-func (e *InvalidUTF8Error) String() string {
-	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
-}
-
-type MarshalerError struct {
-	Type  reflect.Type
-	Error os.Error
-}
-
-func (e *MarshalerError) String() string {
-	return "json: error calling MarshalJSON for type " + e.Type.String() + ": " + e.Error.String()
-}
-
-type interfaceOrPtrValue interface {
-	IsNil() bool
-	Elem() reflect.Value
-}
-
-var hex = "0123456789abcdef"
-
-// An encodeState encodes JSON into a bytes.Buffer.
-type encodeState struct {
-	bytes.Buffer // accumulated output
-}
-
-func (e *encodeState) marshal(v interface{}) (err os.Error) {
-	defer func() {
-		if r := recover(); r != nil {
-			if _, ok := r.(runtime.Error); ok {
-				panic(r)
-			}
-			err = r.(os.Error)
-		}
-	}()
-	e.reflectValue(reflect.ValueOf(v))
-	return nil
-}
-
-func (e *encodeState) error(err os.Error) {
-	panic(err)
-}
-
-var byteSliceType = reflect.TypeOf([]byte(nil))
-
-func isEmptyValue(v reflect.Value) bool {
-	switch v.Kind() {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len() == 0
-	case reflect.Bool:
-		return !v.Bool()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return v.Int() == 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return v.Uint() == 0
-	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
-	case reflect.Interface, reflect.Ptr:
-		return v.IsNil()
-	}
-	return false
-}
-
-func (e *encodeState) reflectValue(v reflect.Value) {
-	e.reflectValueQuoted(v, false)
-}
-
-// reflectValueQuoted writes the value in v to the output.
-// If quoted is true, the serialization is wrapped in a JSON string.
-func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
-	if !v.IsValid() {
-		e.WriteString("null")
-		return
-	}
-
-	if j, ok := v.Interface().(Marshaler); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
-		b, err := j.MarshalJSON()
-		if err == nil {
-			// copy JSON into buffer, checking validity.
-			err = Compact(&e.Buffer, b)
-		}
-		if err != nil {
-			e.error(&MarshalerError{v.Type(), err})
-		}
-		return
-	}
-
-	writeString := (*encodeState).WriteString
-	if quoted {
-		writeString = (*encodeState).string
-	}
-
-	switch v.Kind() {
-	case reflect.Bool:
-		x := v.Bool()
-		if x {
-			writeString(e, "true")
-		} else {
-			writeString(e, "false")
-		}
-
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		writeString(e, strconv.Itoa64(v.Int()))
-
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		writeString(e, strconv.Uitoa64(v.Uint()))
-
-	case reflect.Float32, reflect.Float64:
-		writeString(e, strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits()))
-
-	case reflect.String:
-		if quoted {
-			sb, err := Marshal(v.String())
-			if err != nil {
-				e.error(err)
-			}
-			e.string(string(sb))
-		} else {
-			e.string(v.String())
-		}
-
-	case reflect.Struct:
-		e.WriteByte('{')
-		t := v.Type()
-		n := v.NumField()
-		first := true
-		for i := 0; i < n; i++ {
-			f := t.Field(i)
-			if f.PkgPath != "" {
-				continue
-			}
-			tag, omitEmpty, quoted := f.Name, false, false
-			if tv := f.Tag.Get("json"); tv != "" {
-				if tv == "-" {
-					continue
-				}
-				name, opts := parseTag(tv)
-				if isValidTag(name) {
-					tag = name
-				}
-				omitEmpty = opts.Contains("omitempty")
-				quoted = opts.Contains("string")
-			}
-			fieldValue := v.Field(i)
-			if omitEmpty && isEmptyValue(fieldValue) {
-				continue
-			}
-			if first {
-				first = false
-			} else {
-				e.WriteByte(',')
-			}
-			e.string(tag)
-			e.WriteByte(':')
-			e.reflectValueQuoted(fieldValue, quoted)
-		}
-		e.WriteByte('}')
-
-	case reflect.Map:
-		if v.Type().Key().Kind() != reflect.String {
-			e.error(&UnsupportedTypeError{v.Type()})
-		}
-		if v.IsNil() {
-			e.WriteString("null")
-			break
-		}
-		e.WriteByte('{')
-		var sv stringValues = v.MapKeys()
-		sort.Sort(sv)
-		for i, k := range sv {
-			if i > 0 {
-				e.WriteByte(',')
-			}
-			e.string(k.String())
-			e.WriteByte(':')
-			e.reflectValue(v.MapIndex(k))
-		}
-		e.WriteByte('}')
-
-	case reflect.Array, reflect.Slice:
-		if v.Type() == byteSliceType {
-			e.WriteByte('"')
-			s := v.Interface().([]byte)
-			if len(s) < 1024 {
-				// for small buffers, using Encode directly is much faster.
-				dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
-				base64.StdEncoding.Encode(dst, s)
-				e.Write(dst)
-			} else {
-				// for large buffers, avoid unnecessary extra temporary
-				// buffer space.
-				enc := base64.NewEncoder(base64.StdEncoding, e)
-				enc.Write(s)
-				enc.Close()
-			}
-			e.WriteByte('"')
-			break
-		}
-		e.WriteByte('[')
-		n := v.Len()
-		for i := 0; i < n; i++ {
-			if i > 0 {
-				e.WriteByte(',')
-			}
-			e.reflectValue(v.Index(i))
-		}
-		e.WriteByte(']')
-
-	case reflect.Interface, reflect.Ptr:
-		if v.IsNil() {
-			e.WriteString("null")
-			return
-		}
-		e.reflectValue(v.Elem())
-
-	default:
-		e.error(&UnsupportedTypeError{v.Type()})
-	}
-	return
-}
-
-func isValidTag(s string) bool {
-	if s == "" {
-		return false
-	}
-	for _, c := range s {
-		if c != '$' && c != '-' && c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) {
-			return false
-		}
-	}
-	return true
-}
-
-// stringValues is a slice of reflect.Value holding *reflect.StringValue.
-// It implements the methods to sort by string.
-type stringValues []reflect.Value
-
-func (sv stringValues) Len() int           { return len(sv) }
-func (sv stringValues) Swap(i, j int)      { sv[i], sv[j] = sv[j], sv[i] }
-func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
-func (sv stringValues) get(i int) string   { return sv[i].String() }
-
-func (e *encodeState) string(s string) (int, os.Error) {
-	len0 := e.Len()
-	e.WriteByte('"')
-	start := 0
-	for i := 0; i < len(s); {
-		if b := s[i]; b < utf8.RuneSelf {
-			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' {
-				i++
-				continue
-			}
-			if start < i {
-				e.WriteString(s[start:i])
-			}
-			switch b {
-			case '\\', '"':
-				e.WriteByte('\\')
-				e.WriteByte(b)
-			case '\n':
-				e.WriteByte('\\')
-				e.WriteByte('n')
-			case '\r':
-				e.WriteByte('\\')
-				e.WriteByte('r')
-			default:
-				// This encodes bytes < 0x20 except for \n and \r,
-				// as well as < and >. The latter are escaped because they
-				// can lead to security holes when user-controlled strings
-				// are rendered into JSON and served to some browsers.
-				e.WriteString(`\u00`)
-				e.WriteByte(hex[b>>4])
-				e.WriteByte(hex[b&0xF])
-			}
-			i++
-			start = i
-			continue
-		}
-		c, size := utf8.DecodeRuneInString(s[i:])
-		if c == utf8.RuneError && size == 1 {
-			e.error(&InvalidUTF8Error{s})
-		}
-		i += size
-	}
-	if start < len(s) {
-		e.WriteString(s[start:])
-	}
-	e.WriteByte('"')
-	return e.Len() - len0, nil
-}
diff --git a/src/pkg/json/encode_test.go b/src/pkg/json/encode_test.go
deleted file mode 100644
index f85bb62..0000000
--- a/src/pkg/json/encode_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2011 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 json
-
-import (
-	"bytes"
-	"reflect"
-	"testing"
-)
-
-type Optionals struct {
-	Sr string `json:"sr"`
-	So string `json:"so,omitempty"`
-	Sw string `json:"-"`
-
-	Ir int `json:"omitempty"` // actually named omitempty, not an option
-	Io int `json:"io,omitempty"`
-
-	Slr []string `json:"slr,random"`
-	Slo []string `json:"slo,omitempty"`
-
-	Mr map[string]interface{} `json:"mr"`
-	Mo map[string]interface{} `json:",omitempty"`
-}
-
-var optionalsExpected = `{
- "sr": "",
- "omitempty": 0,
- "slr": [],
- "mr": {}
-}`
-
-func TestOmitEmpty(t *testing.T) {
-	var o Optionals
-	o.Sw = "something"
-	o.Mr = map[string]interface{}{}
-	o.Mo = map[string]interface{}{}
-
-	got, err := MarshalIndent(&o, "", " ")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if got := string(got); got != optionalsExpected {
-		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
-	}
-}
-
-type StringTag struct {
-	BoolStr bool   `json:",string"`
-	IntStr  int64  `json:",string"`
-	StrStr  string `json:",string"`
-}
-
-var stringTagExpected = `{
- "BoolStr": "true",
- "IntStr": "42",
- "StrStr": "\"xzbit\""
-}`
-
-func TestStringTag(t *testing.T) {
-	var s StringTag
-	s.BoolStr = true
-	s.IntStr = 42
-	s.StrStr = "xzbit"
-	got, err := MarshalIndent(&s, "", " ")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if got := string(got); got != stringTagExpected {
-		t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
-	}
-
-	// Verify that it round-trips.
-	var s2 StringTag
-	err = NewDecoder(bytes.NewBuffer(got)).Decode(&s2)
-	if err != nil {
-		t.Fatalf("Decode: %v", err)
-	}
-	if !reflect.DeepEqual(s, s2) {
-		t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
-	}
-}
diff --git a/src/pkg/json/indent.go b/src/pkg/json/indent.go
deleted file mode 100644
index 2a75303..0000000
--- a/src/pkg/json/indent.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2010 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 json
-
-import (
-	"bytes"
-	"os"
-)
-
-// Compact appends to dst the JSON-encoded src with
-// insignificant space characters elided.
-func Compact(dst *bytes.Buffer, src []byte) os.Error {
-	origLen := dst.Len()
-	var scan scanner
-	scan.reset()
-	start := 0
-	for i, c := range src {
-		v := scan.step(&scan, int(c))
-		if v >= scanSkipSpace {
-			if v == scanError {
-				break
-			}
-			if start < i {
-				dst.Write(src[start:i])
-			}
-			start = i + 1
-		}
-	}
-	if scan.eof() == scanError {
-		dst.Truncate(origLen)
-		return scan.err
-	}
-	if start < len(src) {
-		dst.Write(src[start:])
-	}
-	return nil
-}
-
-func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
-	dst.WriteByte('\n')
-	dst.WriteString(prefix)
-	for i := 0; i < depth; i++ {
-		dst.WriteString(indent)
-	}
-}
-
-// Indent appends to dst an indented form of the JSON-encoded src.
-// Each element in a JSON object or array begins on a new,
-// indented line beginning with prefix followed by one or more
-// copies of indent according to the indentation nesting.
-// The data appended to dst has no trailing newline, to make it easier
-// to embed inside other formatted JSON data.
-func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) os.Error {
-	origLen := dst.Len()
-	var scan scanner
-	scan.reset()
-	needIndent := false
-	depth := 0
-	for _, c := range src {
-		scan.bytes++
-		v := scan.step(&scan, int(c))
-		if v == scanSkipSpace {
-			continue
-		}
-		if v == scanError {
-			break
-		}
-		if needIndent && v != scanEndObject && v != scanEndArray {
-			needIndent = false
-			depth++
-			newline(dst, prefix, indent, depth)
-		}
-
-		// Emit semantically uninteresting bytes
-		// (in particular, punctuation in strings) unmodified.
-		if v == scanContinue {
-			dst.WriteByte(c)
-			continue
-		}
-
-		// Add spacing around real punctuation.
-		switch c {
-		case '{', '[':
-			// delay indent so that empty object and array are formatted as {} and [].
-			needIndent = true
-			dst.WriteByte(c)
-
-		case ',':
-			dst.WriteByte(c)
-			newline(dst, prefix, indent, depth)
-
-		case ':':
-			dst.WriteByte(c)
-			dst.WriteByte(' ')
-
-		case '}', ']':
-			if needIndent {
-				// suppress indent in empty object/array
-				needIndent = false
-			} else {
-				depth--
-				newline(dst, prefix, indent, depth)
-			}
-			dst.WriteByte(c)
-
-		default:
-			dst.WriteByte(c)
-		}
-	}
-	if scan.eof() == scanError {
-		dst.Truncate(origLen)
-		return scan.err
-	}
-	return nil
-}
diff --git a/src/pkg/json/scanner.go b/src/pkg/json/scanner.go
deleted file mode 100644
index 49c2edd..0000000
--- a/src/pkg/json/scanner.go
+++ /dev/null
@@ -1,624 +0,0 @@
-// Copyright 2010 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 json
-
-// JSON value parser state machine.
-// Just about at the limit of what is reasonable to write by hand.
-// Some parts are a bit tedious, but overall it nicely factors out the
-// otherwise common code from the multiple scanning functions
-// in this package (Compact, Indent, checkValid, nextValue, etc).
-//
-// This file starts with two simple examples using the scanner
-// before diving into the scanner itself.
-
-import (
-	"os"
-	"strconv"
-)
-
-// checkValid verifies that data is valid JSON-encoded data.
-// scan is passed in for use by checkValid to avoid an allocation.
-func checkValid(data []byte, scan *scanner) os.Error {
-	scan.reset()
-	for _, c := range data {
-		scan.bytes++
-		if scan.step(scan, int(c)) == scanError {
-			return scan.err
-		}
-	}
-	if scan.eof() == scanError {
-		return scan.err
-	}
-	return nil
-}
-
-// nextValue splits data after the next whole JSON value,
-// returning that value and the bytes that follow it as separate slices.
-// scan is passed in for use by nextValue to avoid an allocation.
-func nextValue(data []byte, scan *scanner) (value, rest []byte, err os.Error) {
-	scan.reset()
-	for i, c := range data {
-		v := scan.step(scan, int(c))
-		if v >= scanEnd {
-			switch v {
-			case scanError:
-				return nil, nil, scan.err
-			case scanEnd:
-				return data[0:i], data[i:], nil
-			}
-		}
-	}
-	if scan.eof() == scanError {
-		return nil, nil, scan.err
-	}
-	return data, nil, nil
-}
-
-// A SyntaxError is a description of a JSON syntax error.
-type SyntaxError struct {
-	msg    string // description of error
-	Offset int64  // error occurred after reading Offset bytes
-}
-
-func (e *SyntaxError) String() string { return e.msg }
-
-// A scanner is a JSON scanning state machine.
-// Callers call scan.reset() and then pass bytes in one at a time
-// by calling scan.step(&scan, c) for each byte.
-// The return value, referred to as an opcode, tells the
-// caller about significant parsing events like beginning
-// and ending literals, objects, and arrays, so that the
-// caller can follow along if it wishes.
-// The return value scanEnd indicates that a single top-level
-// JSON value has been completed, *before* the byte that
-// just got passed in.  (The indication must be delayed in order
-// to recognize the end of numbers: is 123 a whole value or
-// the beginning of 12345e+6?).
-type scanner struct {
-	// The step is a func to be called to execute the next transition.
-	// Also tried using an integer constant and a single func
-	// with a switch, but using the func directly was 10% faster
-	// on a 64-bit Mac Mini, and it's nicer to read.
-	step func(*scanner, int) int
-
-	// Stack of what we're in the middle of - array values, object keys, object values.
-	parseState []int
-
-	// Error that happened, if any.
-	err os.Error
-
-	// 1-byte redo (see undo method)
-	redoCode  int
-	redoState func(*scanner, int) int
-
-	// total bytes consumed, updated by decoder.Decode
-	bytes int64
-}
-
-// These values are returned by the state transition functions
-// assigned to scanner.state and the method scanner.eof.
-// They give details about the current state of the scan that
-// callers might be interested to know about.
-// It is okay to ignore the return value of any particular
-// call to scanner.state: if one call returns scanError,
-// every subsequent call will return scanError too.
-const (
-	// Continue.
-	scanContinue     = iota // uninteresting byte
-	scanBeginLiteral        // end implied by next result != scanContinue
-	scanBeginObject         // begin object
-	scanObjectKey           // just finished object key (string)
-	scanObjectValue         // just finished non-last object value
-	scanEndObject           // end object (implies scanObjectValue if possible)
-	scanBeginArray          // begin array
-	scanArrayValue          // just finished array value
-	scanEndArray            // end array (implies scanArrayValue if possible)
-	scanSkipSpace           // space byte; can skip; known to be last "continue" result
-
-	// Stop.
-	scanEnd   // top-level value ended *before* this byte; known to be first "stop" result
-	scanError // hit an error, scanner.err.
-)
-
-// These values are stored in the parseState stack.
-// They give the current state of a composite value
-// being scanned.  If the parser is inside a nested value
-// the parseState describes the nested state, outermost at entry 0.
-const (
-	parseObjectKey   = iota // parsing object key (before colon)
-	parseObjectValue        // parsing object value (after colon)
-	parseArrayValue         // parsing array value
-)
-
-// reset prepares the scanner for use.
-// It must be called before calling s.step.
-func (s *scanner) reset() {
-	s.step = stateBeginValue
-	s.parseState = s.parseState[0:0]
-	s.err = nil
-}
-
-// eof tells the scanner that the end of input has been reached.
-// It returns a scan status just as s.step does.
-func (s *scanner) eof() int {
-	if s.err != nil {
-		return scanError
-	}
-	if s.step == stateEndTop {
-		return scanEnd
-	}
-	s.step(s, ' ')
-	if s.step == stateEndTop {
-		return scanEnd
-	}
-	if s.err == nil {
-		s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
-	}
-	return scanError
-}
-
-// pushParseState pushes a new parse state p onto the parse stack.
-func (s *scanner) pushParseState(p int) {
-	s.parseState = append(s.parseState, p)
-}
-
-// popParseState pops a parse state (already obtained) off the stack
-// and updates s.step accordingly.
-func (s *scanner) popParseState() {
-	n := len(s.parseState) - 1
-	s.parseState = s.parseState[0:n]
-	if n == 0 {
-		s.step = stateEndTop
-	} else {
-		s.step = stateEndValue
-	}
-}
-
-func isSpace(c int) bool {
-	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
-}
-
-// NOTE(rsc): The various instances of
-//
-//	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n')
-//
-// below should all be if c <= ' ' && isSpace(c), but inlining
-// the checks makes a significant difference (>10%) in tight loops
-// such as nextValue.  These should be rewritten with the clearer
-// function call once 6g knows to inline the call.
-
-// stateBeginValueOrEmpty is the state after reading `[`.
-func stateBeginValueOrEmpty(s *scanner, c int) int {
-	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
-		return scanSkipSpace
-	}
-	if c == ']' {
-		return stateEndValue(s, c)
-	}
-	return stateBeginValue(s, c)
-}
-
-// stateBeginValue is the state at the beginning of the input.
-func stateBeginValue(s *scanner, c int) int {
-	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
-		return scanSkipSpace
-	}
-	switch c {
-	case '{':
-		s.step = stateBeginStringOrEmpty
-		s.pushParseState(parseObjectKey)
-		return scanBeginObject
-	case '[':
-		s.step = stateBeginValueOrEmpty
-		s.pushParseState(parseArrayValue)
-		return scanBeginArray
-	case '"':
-		s.step = stateInString
-		return scanBeginLiteral
-	case '-':
-		s.step = stateNeg
-		return scanBeginLiteral
-	case '0': // beginning of 0.123
-		s.step = state0
-		return scanBeginLiteral
-	case 't': // beginning of true
-		s.step = stateT
-		return scanBeginLiteral
-	case 'f': // beginning of false
-		s.step = stateF
-		return scanBeginLiteral
-	case 'n': // beginning of null
-		s.step = stateN
-		return scanBeginLiteral
-	}
-	if '1' <= c && c <= '9' { // beginning of 1234.5
-		s.step = state1
-		return scanBeginLiteral
-	}
-	return s.error(c, "looking for beginning of value")
-}
-
-// stateBeginStringOrEmpty is the state after reading `{`.
-func stateBeginStringOrEmpty(s *scanner, c int) int {
-	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
-		return scanSkipSpace
-	}
-	if c == '}' {
-		n := len(s.parseState)
-		s.parseState[n-1] = parseObjectValue
-		return stateEndValue(s, c)
-	}
-	return stateBeginString(s, c)
-}
-
-// stateBeginString is the state after reading `{"key": value,`.
-func stateBeginString(s *scanner, c int) int {
-	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
-		return scanSkipSpace
-	}
-	if c == '"' {
-		s.step = stateInString
-		return scanBeginLiteral
-	}
-	return s.error(c, "looking for beginning of object key string")
-}
-
-// stateEndValue is the state after completing a value,
-// such as after reading `{}` or `true` or `["x"`.
-func stateEndValue(s *scanner, c int) int {
-	n := len(s.parseState)
-	if n == 0 {
-		// Completed top-level before the current byte.
-		s.step = stateEndTop
-		return stateEndTop(s, c)
-	}
-	if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
-		s.step = stateEndValue
-		return scanSkipSpace
-	}
-	ps := s.parseState[n-1]
-	switch ps {
-	case parseObjectKey:
-		if c == ':' {
-			s.parseState[n-1] = parseObjectValue
-			s.step = stateBeginValue
-			return scanObjectKey
-		}
-		return s.error(c, "after object key")
-	case parseObjectValue:
-		if c == ',' {
-			s.parseState[n-1] = parseObjectKey
-			s.step = stateBeginString
-			return scanObjectValue
-		}
-		if c == '}' {
-			s.popParseState()
-			return scanEndObject
-		}
-		return s.error(c, "after object key:value pair")
-	case parseArrayValue:
-		if c == ',' {
-			s.step = stateBeginValue
-			return scanArrayValue
-		}
-		if c == ']' {
-			s.popParseState()
-			return scanEndArray
-		}
-		return s.error(c, "after array element")
-	}
-	return s.error(c, "")
-}
-
-// stateEndTop is the state after finishing the top-level value,
-// such as after reading `{}` or `[1,2,3]`.
-// Only space characters should be seen now.
-func stateEndTop(s *scanner, c int) int {
-	if c != ' ' && c != '\t' && c != '\r' && c != '\n' {
-		// Complain about non-space byte on next call.
-		s.error(c, "after top-level value")
-	}
-	return scanEnd
-}
-
-// stateInString is the state after reading `"`.
-func stateInString(s *scanner, c int) int {
-	if c == '"' {
-		s.step = stateEndValue
-		return scanContinue
-	}
-	if c == '\\' {
-		s.step = stateInStringEsc
-		return scanContinue
-	}
-	if c < 0x20 {
-		return s.error(c, "in string literal")
-	}
-	return scanContinue
-}
-
-// stateInStringEsc is the state after reading `"\` during a quoted string.
-func stateInStringEsc(s *scanner, c int) int {
-	switch c {
-	case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
-		s.step = stateInString
-		return scanContinue
-	}
-	if c == 'u' {
-		s.step = stateInStringEscU
-		return scanContinue
-	}
-	return s.error(c, "in string escape code")
-}
-
-// stateInStringEscU is the state after reading `"\u` during a quoted string.
-func stateInStringEscU(s *scanner, c int) int {
-	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
-		s.step = stateInStringEscU1
-		return scanContinue
-	}
-	// numbers
-	return s.error(c, "in \\u hexadecimal character escape")
-}
-
-// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
-func stateInStringEscU1(s *scanner, c int) int {
-	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
-		s.step = stateInStringEscU12
-		return scanContinue
-	}
-	// numbers
-	return s.error(c, "in \\u hexadecimal character escape")
-}
-
-// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
-func stateInStringEscU12(s *scanner, c int) int {
-	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
-		s.step = stateInStringEscU123
-		return scanContinue
-	}
-	// numbers
-	return s.error(c, "in \\u hexadecimal character escape")
-}
-
-// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
-func stateInStringEscU123(s *scanner, c int) int {
-	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
-		s.step = stateInString
-		return scanContinue
-	}
-	// numbers
-	return s.error(c, "in \\u hexadecimal character escape")
-}
-
-// stateInStringEscU123 is the state after reading `-` during a number.
-func stateNeg(s *scanner, c int) int {
-	if c == '0' {
-		s.step = state0
-		return scanContinue
-	}
-	if '1' <= c && c <= '9' {
-		s.step = state1
-		return scanContinue
-	}
-	return s.error(c, "in numeric literal")
-}
-
-// state1 is the state after reading a non-zero integer during a number,
-// such as after reading `1` or `100` but not `0`.
-func state1(s *scanner, c int) int {
-	if '0' <= c && c <= '9' {
-		s.step = state1
-		return scanContinue
-	}
-	return state0(s, c)
-}
-
-// state0 is the state after reading `0` during a number.
-func state0(s *scanner, c int) int {
-	if c == '.' {
-		s.step = stateDot
-		return scanContinue
-	}
-	if c == 'e' || c == 'E' {
-		s.step = stateE
-		return scanContinue
-	}
-	return stateEndValue(s, c)
-}
-
-// stateDot is the state after reading the integer and decimal point in a number,
-// such as after reading `1.`.
-func stateDot(s *scanner, c int) int {
-	if '0' <= c && c <= '9' {
-		s.step = stateDot0
-		return scanContinue
-	}
-	return s.error(c, "after decimal point in numeric literal")
-}
-
-// stateDot0 is the state after reading the integer, decimal point, and subsequent
-// digits of a number, such as after reading `3.14`.
-func stateDot0(s *scanner, c int) int {
-	if '0' <= c && c <= '9' {
-		s.step = stateDot0
-		return scanContinue
-	}
-	if c == 'e' || c == 'E' {
-		s.step = stateE
-		return scanContinue
-	}
-	return stateEndValue(s, c)
-}
-
-// stateE is the state after reading the mantissa and e in a number,
-// such as after reading `314e` or `0.314e`.
-func stateE(s *scanner, c int) int {
-	if c == '+' {
-		s.step = stateESign
-		return scanContinue
-	}
-	if c == '-' {
-		s.step = stateESign
-		return scanContinue
-	}
-	return stateESign(s, c)
-}
-
-// stateESign is the state after reading the mantissa, e, and sign in a number,
-// such as after reading `314e-` or `0.314e+`.
-func stateESign(s *scanner, c int) int {
-	if '0' <= c && c <= '9' {
-		s.step = stateE0
-		return scanContinue
-	}
-	return s.error(c, "in exponent of numeric literal")
-}
-
-// stateE0 is the state after reading the mantissa, e, optional sign,
-// and at least one digit of the exponent in a number,
-// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
-func stateE0(s *scanner, c int) int {
-	if '0' <= c && c <= '9' {
-		s.step = stateE0
-		return scanContinue
-	}
-	return stateEndValue(s, c)
-}
-
-// stateT is the state after reading `t`.
-func stateT(s *scanner, c int) int {
-	if c == 'r' {
-		s.step = stateTr
-		return scanContinue
-	}
-	return s.error(c, "in literal true (expecting 'r')")
-}
-
-// stateTr is the state after reading `tr`.
-func stateTr(s *scanner, c int) int {
-	if c == 'u' {
-		s.step = stateTru
-		return scanContinue
-	}
-	return s.error(c, "in literal true (expecting 'u')")
-}
-
-// stateTru is the state after reading `tru`.
-func stateTru(s *scanner, c int) int {
-	if c == 'e' {
-		s.step = stateEndValue
-		return scanContinue
-	}
-	return s.error(c, "in literal true (expecting 'e')")
-}
-
-// stateF is the state after reading `f`.
-func stateF(s *scanner, c int) int {
-	if c == 'a' {
-		s.step = stateFa
-		return scanContinue
-	}
-	return s.error(c, "in literal false (expecting 'a')")
-}
-
-// stateFa is the state after reading `fa`.
-func stateFa(s *scanner, c int) int {
-	if c == 'l' {
-		s.step = stateFal
-		return scanContinue
-	}
-	return s.error(c, "in literal false (expecting 'l')")
-}
-
-// stateFal is the state after reading `fal`.
-func stateFal(s *scanner, c int) int {
-	if c == 's' {
-		s.step = stateFals
-		return scanContinue
-	}
-	return s.error(c, "in literal false (expecting 's')")
-}
-
-// stateFals is the state after reading `fals`.
-func stateFals(s *scanner, c int) int {
-	if c == 'e' {
-		s.step = stateEndValue
-		return scanContinue
-	}
-	return s.error(c, "in literal false (expecting 'e')")
-}
-
-// stateN is the state after reading `n`.
-func stateN(s *scanner, c int) int {
-	if c == 'u' {
-		s.step = stateNu
-		return scanContinue
-	}
-	return s.error(c, "in literal null (expecting 'u')")
-}
-
-// stateNu is the state after reading `nu`.
-func stateNu(s *scanner, c int) int {
-	if c == 'l' {
-		s.step = stateNul
-		return scanContinue
-	}
-	return s.error(c, "in literal null (expecting 'l')")
-}
-
-// stateNul is the state after reading `nul`.
-func stateNul(s *scanner, c int) int {
-	if c == 'l' {
-		s.step = stateEndValue
-		return scanContinue
-	}
-	return s.error(c, "in literal null (expecting 'l')")
-}
-
-// stateError is the state after reaching a syntax error,
-// such as after reading `[1}` or `5.1.2`.
-func stateError(s *scanner, c int) int {
-	return scanError
-}
-
-// error records an error and switches to the error state.
-func (s *scanner) error(c int, context string) int {
-	s.step = stateError
-	s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
-	return scanError
-}
-
-// quoteChar formats c as a quoted character literal
-func quoteChar(c int) string {
-	// special cases - different from quoted strings
-	if c == '\'' {
-		return `'\''`
-	}
-	if c == '"' {
-		return `'"'`
-	}
-
-	// use quoted string with different quotation marks
-	s := strconv.Quote(string(c))
-	return "'" + s[1:len(s)-1] + "'"
-}
-
-// undo causes the scanner to return scanCode from the next state transition.
-// This gives callers a simple 1-byte undo mechanism.
-func (s *scanner) undo(scanCode int) {
-	if s.step == stateRedo {
-		panic("invalid use of scanner")
-	}
-	s.redoCode = scanCode
-	s.redoState = s.step
-	s.step = stateRedo
-}
-
-// stateRedo helps implement the scanner's 1-byte undo.
-func stateRedo(s *scanner, c int) int {
-	s.step = s.redoState
-	return s.redoCode
-}
diff --git a/src/pkg/json/scanner_test.go b/src/pkg/json/scanner_test.go
deleted file mode 100644
index 67d4a28..0000000
--- a/src/pkg/json/scanner_test.go
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright 2010 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 json
-
-import (
-	"bytes"
-	"math"
-	"os"
-	"rand"
-	"reflect"
-	"testing"
-)
-
-// Tests of simple examples.
-
-type example struct {
-	compact string
-	indent  string
-}
-
-var examples = []example{
-	{`1`, `1`},
-	{`{}`, `{}`},
-	{`[]`, `[]`},
-	{`{"":2}`, "{\n\t\"\": 2\n}"},
-	{`[3]`, "[\n\t3\n]"},
-	{`[1,2,3]`, "[\n\t1,\n\t2,\n\t3\n]"},
-	{`{"x":1}`, "{\n\t\"x\": 1\n}"},
-	{ex1, ex1i},
-}
-
-var ex1 = `[true,false,null,"x",1,1.5,0,-5e+2]`
-
-var ex1i = `[
-	true,
-	false,
-	null,
-	"x",
-	1,
-	1.5,
-	0,
-	-5e+2
-]`
-
-func TestCompact(t *testing.T) {
-	var buf bytes.Buffer
-	for _, tt := range examples {
-		buf.Reset()
-		if err := Compact(&buf, []byte(tt.compact)); err != nil {
-			t.Errorf("Compact(%#q): %v", tt.compact, err)
-		} else if s := buf.String(); s != tt.compact {
-			t.Errorf("Compact(%#q) = %#q, want original", tt.compact, s)
-		}
-
-		buf.Reset()
-		if err := Compact(&buf, []byte(tt.indent)); err != nil {
-			t.Errorf("Compact(%#q): %v", tt.indent, err)
-			continue
-		} else if s := buf.String(); s != tt.compact {
-			t.Errorf("Compact(%#q) = %#q, want %#q", tt.indent, s, tt.compact)
-		}
-	}
-}
-
-func TestIndent(t *testing.T) {
-	var buf bytes.Buffer
-	for _, tt := range examples {
-		buf.Reset()
-		if err := Indent(&buf, []byte(tt.indent), "", "\t"); err != nil {
-			t.Errorf("Indent(%#q): %v", tt.indent, err)
-		} else if s := buf.String(); s != tt.indent {
-			t.Errorf("Indent(%#q) = %#q, want original", tt.indent, s)
-		}
-
-		buf.Reset()
-		if err := Indent(&buf, []byte(tt.compact), "", "\t"); err != nil {
-			t.Errorf("Indent(%#q): %v", tt.compact, err)
-			continue
-		} else if s := buf.String(); s != tt.indent {
-			t.Errorf("Indent(%#q) = %#q, want %#q", tt.compact, s, tt.indent)
-		}
-	}
-}
-
-// Tests of a large random structure.
-
-func TestCompactBig(t *testing.T) {
-	initBig()
-	var buf bytes.Buffer
-	if err := Compact(&buf, jsonBig); err != nil {
-		t.Fatalf("Compact: %v", err)
-	}
-	b := buf.Bytes()
-	if bytes.Compare(b, jsonBig) != 0 {
-		t.Error("Compact(jsonBig) != jsonBig")
-		diff(t, b, jsonBig)
-		return
-	}
-}
-
-func TestIndentBig(t *testing.T) {
-	initBig()
-	var buf bytes.Buffer
-	if err := Indent(&buf, jsonBig, "", "\t"); err != nil {
-		t.Fatalf("Indent1: %v", err)
-	}
-	b := buf.Bytes()
-	if len(b) == len(jsonBig) {
-		// jsonBig is compact (no unnecessary spaces);
-		// indenting should make it bigger
-		t.Fatalf("Indent(jsonBig) did not get bigger")
-	}
-
-	// should be idempotent
-	var buf1 bytes.Buffer
-	if err := Indent(&buf1, b, "", "\t"); err != nil {
-		t.Fatalf("Indent2: %v", err)
-	}
-	b1 := buf1.Bytes()
-	if bytes.Compare(b1, b) != 0 {
-		t.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
-		diff(t, b1, b)
-		return
-	}
-
-	// should get back to original
-	buf1.Reset()
-	if err := Compact(&buf1, b); err != nil {
-		t.Fatalf("Compact: %v", err)
-	}
-	b1 = buf1.Bytes()
-	if bytes.Compare(b1, jsonBig) != 0 {
-		t.Error("Compact(Indent(jsonBig)) != jsonBig")
-		diff(t, b1, jsonBig)
-		return
-	}
-}
-
-type indentErrorTest struct {
-	in  string
-	err os.Error
-}
-
-var indentErrorTests = []indentErrorTest{
-	{`{"X": "foo", "Y"}`, &SyntaxError{"invalid character '}' after object key", 17}},
-	{`{"X": "foo" "Y": "bar"}`, &SyntaxError{"invalid character '\"' after object key:value pair", 13}},
-}
-
-func TestIdentErrors(t *testing.T) {
-	for i, tt := range indentErrorTests {
-		slice := make([]uint8, 0)
-		buf := bytes.NewBuffer(slice)
-		if err := Indent(buf, []uint8(tt.in), "", ""); err != nil {
-			if !reflect.DeepEqual(err, tt.err) {
-				t.Errorf("#%d: Indent: %#v", i, err)
-				continue
-			}
-		}
-	}
-}
-
-func TestNextValueBig(t *testing.T) {
-	initBig()
-	var scan scanner
-	item, rest, err := nextValue(jsonBig, &scan)
-	if err != nil {
-		t.Fatalf("nextValue: %s", err)
-	}
-	if len(item) != len(jsonBig) || &item[0] != &jsonBig[0] {
-		t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
-	}
-	if len(rest) != 0 {
-		t.Errorf("invalid rest: %d", len(rest))
-	}
-
-	item, rest, err = nextValue(append(jsonBig, []byte("HELLO WORLD")...), &scan)
-	if err != nil {
-		t.Fatalf("nextValue extra: %s", err)
-	}
-	if len(item) != len(jsonBig) {
-		t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
-	}
-	if string(rest) != "HELLO WORLD" {
-		t.Errorf("invalid rest: %d", len(rest))
-	}
-}
-
-func BenchmarkSkipValue(b *testing.B) {
-	initBig()
-	var scan scanner
-	for i := 0; i < b.N; i++ {
-		nextValue(jsonBig, &scan)
-	}
-	b.SetBytes(int64(len(jsonBig)))
-}
-
-func diff(t *testing.T, a, b []byte) {
-	for i := 0; ; i++ {
-		if i >= len(a) || i >= len(b) || a[i] != b[i] {
-			j := i - 10
-			if j < 0 {
-				j = 0
-			}
-			t.Errorf("diverge at %d: «%s» vs «%s»", i, trim(a[j:]), trim(b[j:]))
-			return
-		}
-	}
-}
-
-func trim(b []byte) []byte {
-	if len(b) > 20 {
-		return b[0:20]
-	}
-	return b
-}
-
-// Generate a random JSON object.
-
-var jsonBig []byte
-
-const (
-	big   = 10000
-	small = 100
-)
-
-func initBig() {
-	n := big
-	if testing.Short() {
-		n = small
-	}
-	if len(jsonBig) != n {
-		b, err := Marshal(genValue(n))
-		if err != nil {
-			panic(err)
-		}
-		jsonBig = b
-	}
-}
-
-func genValue(n int) interface{} {
-	if n > 1 {
-		switch rand.Intn(2) {
-		case 0:
-			return genArray(n)
-		case 1:
-			return genMap(n)
-		}
-	}
-	switch rand.Intn(3) {
-	case 0:
-		return rand.Intn(2) == 0
-	case 1:
-		return rand.NormFloat64()
-	case 2:
-		return genString(30)
-	}
-	panic("unreachable")
-}
-
-func genString(stddev float64) string {
-	n := int(math.Fabs(rand.NormFloat64()*stddev + stddev/2))
-	c := make([]int, n)
-	for i := range c {
-		f := math.Fabs(rand.NormFloat64()*64 + 32)
-		if f > 0x10ffff {
-			f = 0x10ffff
-		}
-		c[i] = int(f)
-	}
-	return string(c)
-}
-
-func genArray(n int) []interface{} {
-	f := int(math.Fabs(rand.NormFloat64()) * math.Fmin(10, float64(n/2)))
-	if f > n {
-		f = n
-	}
-	if n > 0 && f == 0 {
-		f = 1
-	}
-	x := make([]interface{}, f)
-	for i := range x {
-		x[i] = genValue(((i+1)*n)/f - (i*n)/f)
-	}
-	return x
-}
-
-func genMap(n int) map[string]interface{} {
-	f := int(math.Fabs(rand.NormFloat64()) * math.Fmin(10, float64(n/2)))
-	if f > n {
-		f = n
-	}
-	if n > 0 && f == 0 {
-		f = 1
-	}
-	x := make(map[string]interface{})
-	for i := 0; i < f; i++ {
-		x[genString(10)] = genValue(((i+1)*n)/f - (i*n)/f)
-	}
-	return x
-}
diff --git a/src/pkg/json/stream.go b/src/pkg/json/stream.go
deleted file mode 100644
index f143b3f..0000000
--- a/src/pkg/json/stream.go
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright 2010 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 json
-
-import (
-	"io"
-	"os"
-)
-
-// A Decoder reads and decodes JSON objects from an input stream.
-type Decoder struct {
-	r    io.Reader
-	buf  []byte
-	d    decodeState
-	scan scanner
-	err  os.Error
-}
-
-// NewDecoder returns a new decoder that reads from r.
-func NewDecoder(r io.Reader) *Decoder {
-	return &Decoder{r: r}
-}
-
-// Decode reads the next JSON-encoded value from its
-// input and stores it in the value pointed to by v.
-//
-// See the documentation for Unmarshal for details about
-// the conversion of JSON into a Go value.
-func (dec *Decoder) Decode(v interface{}) os.Error {
-	if dec.err != nil {
-		return dec.err
-	}
-
-	n, err := dec.readValue()
-	if err != nil {
-		return err
-	}
-
-	// Don't save err from unmarshal into dec.err:
-	// the connection is still usable since we read a complete JSON
-	// object from it before the error happened.
-	dec.d.init(dec.buf[0:n])
-	err = dec.d.unmarshal(v)
-
-	// Slide rest of data down.
-	rest := copy(dec.buf, dec.buf[n:])
-	dec.buf = dec.buf[0:rest]
-
-	return err
-}
-
-// readValue reads a JSON value into dec.buf.
-// It returns the length of the encoding.
-func (dec *Decoder) readValue() (int, os.Error) {
-	dec.scan.reset()
-
-	scanp := 0
-	var err os.Error
-Input:
-	for {
-		// Look in the buffer for a new value.
-		for i, c := range dec.buf[scanp:] {
-			dec.scan.bytes++
-			v := dec.scan.step(&dec.scan, int(c))
-			if v == scanEnd {
-				scanp += i
-				break Input
-			}
-			// scanEnd is delayed one byte.
-			// We might block trying to get that byte from src,
-			// so instead invent a space byte.
-			if v == scanEndObject && dec.scan.step(&dec.scan, ' ') == scanEnd {
-				scanp += i + 1
-				break Input
-			}
-			if v == scanError {
-				dec.err = dec.scan.err
-				return 0, dec.scan.err
-			}
-		}
-		scanp = len(dec.buf)
-
-		// Did the last read have an error?
-		// Delayed until now to allow buffer scan.
-		if err != nil {
-			if err == os.EOF {
-				if dec.scan.step(&dec.scan, ' ') == scanEnd {
-					break Input
-				}
-				if nonSpace(dec.buf) {
-					err = io.ErrUnexpectedEOF
-				}
-			}
-			dec.err = err
-			return 0, err
-		}
-
-		// Make room to read more into the buffer.
-		const minRead = 512
-		if cap(dec.buf)-len(dec.buf) < minRead {
-			newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
-			copy(newBuf, dec.buf)
-			dec.buf = newBuf
-		}
-
-		// Read.  Delay error for next iteration (after scan).
-		var n int
-		n, err = dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
-		dec.buf = dec.buf[0 : len(dec.buf)+n]
-	}
-	return scanp, nil
-}
-
-func nonSpace(b []byte) bool {
-	for _, c := range b {
-		if !isSpace(int(c)) {
-			return true
-		}
-	}
-	return false
-}
-
-// An Encoder writes JSON objects to an output stream.
-type Encoder struct {
-	w   io.Writer
-	e   encodeState
-	err os.Error
-}
-
-// NewEncoder returns a new encoder that writes to w.
-func NewEncoder(w io.Writer) *Encoder {
-	return &Encoder{w: w}
-}
-
-// Encode writes the JSON encoding of v to the connection.
-//
-// See the documentation for Marshal for details about the
-// conversion of Go values to JSON.
-func (enc *Encoder) Encode(v interface{}) os.Error {
-	if enc.err != nil {
-		return enc.err
-	}
-	enc.e.Reset()
-	err := enc.e.marshal(v)
-	if err != nil {
-		return err
-	}
-
-	// Terminate each value with a newline.
-	// This makes the output look a little nicer
-	// when debugging, and some kind of space
-	// is required if the encoded value was a number,
-	// so that the reader knows there aren't more
-	// digits coming.
-	enc.e.WriteByte('\n')
-
-	if _, err = enc.w.Write(enc.e.Bytes()); err != nil {
-		enc.err = err
-	}
-	return err
-}
-
-// RawMessage is a raw encoded JSON object.
-// It implements Marshaler and Unmarshaler and can
-// be used to delay JSON decoding or precompute a JSON encoding.
-type RawMessage []byte
-
-// MarshalJSON returns *m as the JSON encoding of m.
-func (m *RawMessage) MarshalJSON() ([]byte, os.Error) {
-	return *m, nil
-}
-
-// UnmarshalJSON sets *m to a copy of data.
-func (m *RawMessage) UnmarshalJSON(data []byte) os.Error {
-	if m == nil {
-		return os.NewError("json.RawMessage: UnmarshalJSON on nil pointer")
-	}
-	*m = append((*m)[0:0], data...)
-	return nil
-}
-
-var _ Marshaler = (*RawMessage)(nil)
-var _ Unmarshaler = (*RawMessage)(nil)
diff --git a/src/pkg/json/tagkey_test.go b/src/pkg/json/tagkey_test.go
deleted file mode 100644
index 31fe2be..0000000
--- a/src/pkg/json/tagkey_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2011 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 json
-
-import (
-	"testing"
-)
-
-type basicLatin2xTag struct {
-	V string `json:"$-"`
-}
-
-type basicLatin3xTag struct {
-	V string `json:"0123456789"`
-}
-
-type basicLatin4xTag struct {
-	V string `json:"ABCDEFGHIJKLMO"`
-}
-
-type basicLatin5xTag struct {
-	V string `json:"PQRSTUVWXYZ_"`
-}
-
-type basicLatin6xTag struct {
-	V string `json:"abcdefghijklmno"`
-}
-
-type basicLatin7xTag struct {
-	V string `json:"pqrstuvwxyz"`
-}
-
-type miscPlaneTag struct {
-	V string `json:"色は匂へど"`
-}
-
-type emptyTag struct {
-	W string
-}
-
-type misnamedTag struct {
-	X string `jsom:"Misnamed"`
-}
-
-type badFormatTag struct {
-	Y string `:"BadFormat"`
-}
-
-type badCodeTag struct {
-	Z string `json:" !\"#%&'()*+,./"`
-}
-
-var structTagObjectKeyTests = []struct {
-	raw   interface{}
-	value string
-	key   string
-}{
-	{basicLatin2xTag{"2x"}, "2x", "$-"},
-	{basicLatin3xTag{"3x"}, "3x", "0123456789"},
-	{basicLatin4xTag{"4x"}, "4x", "ABCDEFGHIJKLMO"},
-	{basicLatin5xTag{"5x"}, "5x", "PQRSTUVWXYZ_"},
-	{basicLatin6xTag{"6x"}, "6x", "abcdefghijklmno"},
-	{basicLatin7xTag{"7x"}, "7x", "pqrstuvwxyz"},
-	{miscPlaneTag{"いろはにほへと"}, "いろはにほへと", "色は匂へど"},
-	{emptyTag{"Pour Moi"}, "Pour Moi", "W"},
-	{misnamedTag{"Animal Kingdom"}, "Animal Kingdom", "X"},
-	{badFormatTag{"Orfevre"}, "Orfevre", "Y"},
-	{badCodeTag{"Reliable Man"}, "Reliable Man", "Z"},
-}
-
-func TestStructTagObjectKey(t *testing.T) {
-	for _, tt := range structTagObjectKeyTests {
-		b, err := Marshal(tt.raw)
-		if err != nil {
-			t.Fatalf("Marshal(%#q) failed: %v", tt.raw, err)
-		}
-		var f interface{}
-		err = Unmarshal(b, &f)
-		if err != nil {
-			t.Fatalf("Unmarshal(%#q) failed: %v", b, err)
-		}
-		for i, v := range f.(map[string]interface{}) {
-			switch i {
-			case tt.key:
-				if s, ok := v.(string); !ok || s != tt.value {
-					t.Fatalf("Unexpected value: %#q, want %v", s, tt.value)
-				}
-			default:
-				t.Fatalf("Unexpected key: %#q", i)
-			}
-		}
-	}
-}
diff --git a/src/pkg/log/log.go b/src/pkg/log/log.go
index ec09743..a5d88fd 100644
--- a/src/pkg/log/log.go
+++ b/src/pkg/log/log.go
@@ -16,10 +16,10 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"runtime"
 	"os"
-	"time"
+	"runtime"
 	"sync"
+	"time"
 )
 
 // These flags define which text to prefix to each log entry generated by the Logger.
@@ -83,27 +83,28 @@ func itoa(buf *bytes.Buffer, i int, wid int) {
 	}
 }
 
-func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, file string, line int) {
+func (l *Logger) formatHeader(buf *bytes.Buffer, t time.Time, file string, line int) {
 	buf.WriteString(l.prefix)
 	if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
-		t := time.SecondsToLocalTime(ns / 1e9)
 		if l.flag&Ldate != 0 {
-			itoa(buf, int(t.Year), 4)
+			year, month, day := t.Date()
+			itoa(buf, year, 4)
 			buf.WriteByte('/')
-			itoa(buf, int(t.Month), 2)
+			itoa(buf, int(month), 2)
 			buf.WriteByte('/')
-			itoa(buf, int(t.Day), 2)
+			itoa(buf, day, 2)
 			buf.WriteByte(' ')
 		}
 		if l.flag&(Ltime|Lmicroseconds) != 0 {
-			itoa(buf, int(t.Hour), 2)
+			hour, min, sec := t.Clock()
+			itoa(buf, hour, 2)
 			buf.WriteByte(':')
-			itoa(buf, int(t.Minute), 2)
+			itoa(buf, min, 2)
 			buf.WriteByte(':')
-			itoa(buf, int(t.Second), 2)
+			itoa(buf, sec, 2)
 			if l.flag&Lmicroseconds != 0 {
 				buf.WriteByte('.')
-				itoa(buf, int(ns%1e9)/1e3, 6)
+				itoa(buf, t.Nanosecond()/1e3, 6)
 			}
 			buf.WriteByte(' ')
 		}
@@ -132,8 +133,8 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, file string, line int
 // already a newline.  Calldepth is used to recover the PC and is
 // provided for generality, although at the moment on all pre-defined
 // paths it will be 2.
-func (l *Logger) Output(calldepth int, s string) os.Error {
-	now := time.Nanoseconds() // get this early.
+func (l *Logger) Output(calldepth int, s string) error {
+	now := time.Now() // get this early.
 	var file string
 	var line int
 	l.mu.Lock()
diff --git a/src/pkg/log/syslog/Makefile b/src/pkg/log/syslog/Makefile
new file mode 100644
index 0000000..225307c
--- /dev/null
+++ b/src/pkg/log/syslog/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=log/syslog
+GOFILES=\
+	syslog.go\
+	syslog_unix.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/log/syslog/syslog.go b/src/pkg/log/syslog/syslog.go
new file mode 100644
index 0000000..aef6348
--- /dev/null
+++ b/src/pkg/log/syslog/syslog.go
@@ -0,0 +1,160 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package syslog provides a simple interface to the system log service. It
+// can send messages to the syslog daemon using UNIX domain sockets, UDP, or
+// TCP connections.
+package syslog
+
+import (
+	"errors"
+	"fmt"
+	"log"
+	"net"
+	"os"
+)
+
+type Priority int
+
+const (
+	// From /usr/include/sys/syslog.h.
+	// These are the same on Linux, BSD, and OS X.
+	LOG_EMERG Priority = iota
+	LOG_ALERT
+	LOG_CRIT
+	LOG_ERR
+	LOG_WARNING
+	LOG_NOTICE
+	LOG_INFO
+	LOG_DEBUG
+)
+
+// A Writer is a connection to a syslog server.
+type Writer struct {
+	priority Priority
+	prefix   string
+	conn     serverConn
+}
+
+type serverConn interface {
+	writeBytes(p Priority, prefix string, b []byte) (int, error)
+	writeString(p Priority, prefix string, s string) (int, error)
+	close() error
+}
+
+type netConn struct {
+	conn net.Conn
+}
+
+// New establishes a new connection to the system log daemon.
+// Each write to the returned writer sends a log message with
+// the given priority and prefix.
+func New(priority Priority, prefix string) (w *Writer, err error) {
+	return Dial("", "", priority, prefix)
+}
+
+// Dial establishes a connection to a log daemon by connecting
+// to address raddr on the network net.
+// Each write to the returned writer sends a log message with
+// the given priority and prefix.
+func Dial(network, raddr string, priority Priority, prefix string) (w *Writer, err error) {
+	if prefix == "" {
+		prefix = os.Args[0]
+	}
+	var conn serverConn
+	if network == "" {
+		conn, err = unixSyslog()
+	} else {
+		var c net.Conn
+		c, err = net.Dial(network, raddr)
+		conn = netConn{c}
+	}
+	return &Writer{priority, prefix, conn}, err
+}
+
+// Write sends a log message to the syslog daemon.
+func (w *Writer) Write(b []byte) (int, error) {
+	if w.priority > LOG_DEBUG || w.priority < LOG_EMERG {
+		return 0, errors.New("log/syslog: invalid priority")
+	}
+	return w.conn.writeBytes(w.priority, w.prefix, b)
+}
+
+func (w *Writer) writeString(p Priority, s string) (int, error) {
+	return w.conn.writeString(p, w.prefix, s)
+}
+
+func (w *Writer) Close() error { return w.conn.close() }
+
+// Emerg logs a message using the LOG_EMERG priority.
+func (w *Writer) Emerg(m string) (err error) {
+	_, err = w.writeString(LOG_EMERG, m)
+	return err
+}
+
+// Alert logs a message using the LOG_ALERT priority.
+func (w *Writer) Alert(m string) (err error) {
+	_, err = w.writeString(LOG_ALERT, m)
+	return err
+}
+
+// Crit logs a message using the LOG_CRIT priority.
+func (w *Writer) Crit(m string) (err error) {
+	_, err = w.writeString(LOG_CRIT, m)
+	return err
+}
+
+// Err logs a message using the LOG_ERR priority.
+func (w *Writer) Err(m string) (err error) {
+	_, err = w.writeString(LOG_ERR, m)
+	return err
+}
+
+// Warning logs a message using the LOG_WARNING priority.
+func (w *Writer) Warning(m string) (err error) {
+	_, err = w.writeString(LOG_WARNING, m)
+	return err
+}
+
+// Notice logs a message using the LOG_NOTICE priority.
+func (w *Writer) Notice(m string) (err error) {
+	_, err = w.writeString(LOG_NOTICE, m)
+	return err
+}
+
+// Info logs a message using the LOG_INFO priority.
+func (w *Writer) Info(m string) (err error) {
+	_, err = w.writeString(LOG_INFO, m)
+	return err
+}
+
+// Debug logs a message using the LOG_DEBUG priority.
+func (w *Writer) Debug(m string) (err error) {
+	_, err = w.writeString(LOG_DEBUG, m)
+	return err
+}
+
+func (n netConn) writeBytes(p Priority, prefix string, b []byte) (int, error) {
+	return fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, b)
+}
+
+func (n netConn) writeString(p Priority, prefix string, s string) (int, error) {
+	return fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, s)
+}
+
+func (n netConn) close() error {
+	return n.conn.Close()
+}
+
+// NewLogger provides an object that implements the full log.Logger interface,
+// but sends messages to Syslog instead; flag is passed as is to Logger;
+// priority will be used for all messages sent using this interface.
+// All messages are logged with priority p.
+func NewLogger(p Priority, flag int) *log.Logger {
+	s, err := New(p, "")
+	if err != nil {
+		return nil
+	}
+	return log.New(s, "", flag)
+}
diff --git a/src/pkg/log/syslog/syslog_test.go b/src/pkg/log/syslog/syslog_test.go
new file mode 100644
index 0000000..b9793e9
--- /dev/null
+++ b/src/pkg/log/syslog/syslog_test.go
@@ -0,0 +1,114 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package syslog
+
+import (
+	"io"
+	"log"
+	"net"
+	"testing"
+	"time"
+)
+
+var serverAddr string
+
+func runSyslog(c net.PacketConn, done chan<- string) {
+	var buf [4096]byte
+	var rcvd string = ""
+	for {
+		n, _, err := c.ReadFrom(buf[0:])
+		if err != nil || n == 0 {
+			break
+		}
+		rcvd += string(buf[0:n])
+	}
+	done <- rcvd
+}
+
+func startServer(done chan<- string) {
+	c, e := net.ListenPacket("udp", "127.0.0.1:0")
+	if e != nil {
+		log.Fatalf("net.ListenPacket failed udp :0 %v", e)
+	}
+	serverAddr = c.LocalAddr().String()
+	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+	go runSyslog(c, done)
+}
+
+func skipNetTest(t *testing.T) bool {
+	if testing.Short() {
+		// Depends on syslog daemon running, and sometimes it's not.
+		t.Logf("skipping syslog test during -short")
+		return true
+	}
+	return false
+}
+
+func TestNew(t *testing.T) {
+	if skipNetTest(t) {
+		return
+	}
+	s, err := New(LOG_INFO, "")
+	if err != nil {
+		t.Fatalf("New() failed: %s", err)
+	}
+	// Don't send any messages.
+	s.Close()
+}
+
+func TestNewLogger(t *testing.T) {
+	if skipNetTest(t) {
+		return
+	}
+	f := NewLogger(LOG_INFO, 0)
+	if f == nil {
+		t.Error("NewLogger() failed")
+	}
+}
+
+func TestDial(t *testing.T) {
+	if skipNetTest(t) {
+		return
+	}
+	l, err := Dial("", "", LOG_ERR, "syslog_test")
+	if err != nil {
+		t.Fatalf("Dial() failed: %s", err)
+	}
+	l.Close()
+}
+
+func TestUDPDial(t *testing.T) {
+	done := make(chan string)
+	startServer(done)
+	l, err := Dial("udp", serverAddr, LOG_INFO, "syslog_test")
+	if err != nil {
+		t.Fatalf("syslog.Dial() failed: %s", err)
+	}
+	msg := "udp test"
+	l.Info(msg)
+	expected := "<6>syslog_test: udp test\n"
+	rcvd := <-done
+	if rcvd != expected {
+		t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected)
+	}
+}
+
+func TestWrite(t *testing.T) {
+	done := make(chan string)
+	startServer(done)
+	l, err := Dial("udp", serverAddr, LOG_ERR, "syslog_test")
+	if err != nil {
+		t.Fatalf("syslog.Dial() failed: %s", err)
+	}
+	msg := "write test"
+	_, err = io.WriteString(l, msg)
+	if err != nil {
+		t.Fatalf("WriteString() failed: %s", err)
+	}
+	expected := "<3>syslog_test: write test\n"
+	rcvd := <-done
+	if rcvd != expected {
+		t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected)
+	}
+}
diff --git a/src/pkg/log/syslog/syslog_unix.go b/src/pkg/log/syslog/syslog_unix.go
new file mode 100644
index 0000000..b1c929a
--- /dev/null
+++ b/src/pkg/log/syslog/syslog_unix.go
@@ -0,0 +1,31 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syslog
+
+import (
+	"errors"
+	"net"
+)
+
+// unixSyslog opens a connection to the syslog daemon running on the
+// local machine using a Unix domain socket.
+
+func unixSyslog() (conn serverConn, err error) {
+	logTypes := []string{"unixgram", "unix"}
+	logPaths := []string{"/dev/log", "/var/run/syslog"}
+	var raddr string
+	for _, network := range logTypes {
+		for _, path := range logPaths {
+			raddr = path
+			conn, err := net.Dial(network, raddr)
+			if err != nil {
+				continue
+			} else {
+				return netConn{conn}, nil
+			}
+		}
+	}
+	return nil, errors.New("Unix syslog delivery error")
+}
diff --git a/src/pkg/mail/Makefile b/src/pkg/mail/Makefile
deleted file mode 100644
index e4de542..0000000
--- a/src/pkg/mail/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=mail
-GOFILES=\
-	message.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/mail/message.go b/src/pkg/mail/message.go
deleted file mode 100644
index e227d17..0000000
--- a/src/pkg/mail/message.go
+++ /dev/null
@@ -1,524 +0,0 @@
-// Copyright 2011 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 mail implements parsing of mail messages.
-
-For the most part, this package follows the syntax as specified by RFC 5322.
-Notable divergences:
-	* Obsolete address formats are not parsed, including addresses with
-	  embedded route information.
-	* Group addresses are not parsed.
-	* The full range of spacing (the CFWS syntax element) is not supported,
-	  such as breaking addresses across lines.
-*/
-package mail
-
-import (
-	"bufio"
-	"bytes"
-	"encoding/base64"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"log"
-	"net/textproto"
-	"os"
-	"strconv"
-	"strings"
-	"time"
-)
-
-var debug = debugT(false)
-
-type debugT bool
-
-func (d debugT) Printf(format string, args ...interface{}) {
-	if d {
-		log.Printf(format, args...)
-	}
-}
-
-// A Message represents a parsed mail message.
-type Message struct {
-	Header Header
-	Body   io.Reader
-}
-
-// ReadMessage reads a message from r.
-// The headers are parsed, and the body of the message will be reading from r.
-func ReadMessage(r io.Reader) (msg *Message, err os.Error) {
-	tp := textproto.NewReader(bufio.NewReader(r))
-
-	hdr, err := tp.ReadMIMEHeader()
-	if err != nil {
-		return nil, err
-	}
-
-	return &Message{
-		Header: Header(hdr),
-		Body:   tp.R,
-	}, nil
-}
-
-// Layouts suitable for passing to time.Parse.
-// These are tried in order.
-var dateLayouts []string
-
-func init() {
-	// Generate layouts based on RFC 5322, section 3.3.
-
-	dows := [...]string{"", "Mon, "}     // day-of-week
-	days := [...]string{"2", "02"}       // day = 1*2DIGIT
-	years := [...]string{"2006", "06"}   // year = 4*DIGIT / 2*DIGIT
-	seconds := [...]string{":05", ""}    // second
-	zones := [...]string{"-0700", "MST"} // zone = (("+" / "-") 4DIGIT) / "GMT" / ...
-
-	for _, dow := range dows {
-		for _, day := range days {
-			for _, year := range years {
-				for _, second := range seconds {
-					for _, zone := range zones {
-						s := dow + day + " Jan " + year + " 15:04" + second + " " + zone
-						dateLayouts = append(dateLayouts, s)
-					}
-				}
-			}
-		}
-	}
-}
-
-func parseDate(date string) (*time.Time, os.Error) {
-	for _, layout := range dateLayouts {
-		t, err := time.Parse(layout, date)
-		if err == nil {
-			return t, nil
-		}
-	}
-	return nil, os.NewError("mail: header could not be parsed")
-}
-
-// A Header represents the key-value pairs in a mail message header.
-type Header map[string][]string
-
-// Get gets the first value associated with the given key.
-// If there are no values associated with the key, Get returns "".
-func (h Header) Get(key string) string {
-	return textproto.MIMEHeader(h).Get(key)
-}
-
-var ErrHeaderNotPresent = os.NewError("mail: header not in message")
-
-// Date parses the Date header field.
-func (h Header) Date() (*time.Time, os.Error) {
-	hdr := h.Get("Date")
-	if hdr == "" {
-		return nil, ErrHeaderNotPresent
-	}
-	return parseDate(hdr)
-}
-
-// AddressList parses the named header field as a list of addresses.
-func (h Header) AddressList(key string) ([]*Address, os.Error) {
-	hdr := h.Get(key)
-	if hdr == "" {
-		return nil, ErrHeaderNotPresent
-	}
-	return newAddrParser(hdr).parseAddressList()
-}
-
-// Address represents a single mail address.
-// An address such as "Barry Gibbs <bg at example.com>" is represented
-// as Address{Name: "Barry Gibbs", Address: "bg at example.com"}.
-type Address struct {
-	Name    string // Proper name; may be empty.
-	Address string // user at domain
-}
-
-// String formats the address as a valid RFC 5322 address.
-// If the address's name contains non-ASCII characters
-// the name will be rendered according to RFC 2047.
-func (a *Address) String() string {
-	s := "<" + a.Address + ">"
-	if a.Name == "" {
-		return s
-	}
-	// If every character is printable ASCII, quoting is simple.
-	allPrintable := true
-	for i := 0; i < len(a.Name); i++ {
-		if !isVchar(a.Name[i]) {
-			allPrintable = false
-			break
-		}
-	}
-	if allPrintable {
-		b := bytes.NewBufferString(`"`)
-		for i := 0; i < len(a.Name); i++ {
-			if !isQtext(a.Name[i]) {
-				b.WriteByte('\\')
-			}
-			b.WriteByte(a.Name[i])
-		}
-		b.WriteString(`" `)
-		b.WriteString(s)
-		return b.String()
-	}
-
-	// UTF-8 "Q" encoding
-	b := bytes.NewBufferString("=?utf-8?q?")
-	for i := 0; i < len(a.Name); i++ {
-		switch c := a.Name[i]; {
-		case c == ' ':
-			b.WriteByte('_')
-		case isVchar(c) && c != '=' && c != '?' && c != '_':
-			b.WriteByte(c)
-		default:
-			fmt.Fprintf(b, "=%02X", c)
-		}
-	}
-	b.WriteString("?= ")
-	b.WriteString(s)
-	return b.String()
-}
-
-type addrParser []byte
-
-func newAddrParser(s string) *addrParser {
-	p := addrParser([]byte(s))
-	return &p
-}
-
-func (p *addrParser) parseAddressList() ([]*Address, os.Error) {
-	var list []*Address
-	for {
-		p.skipSpace()
-		addr, err := p.parseAddress()
-		if err != nil {
-			return nil, err
-		}
-		list = append(list, addr)
-
-		p.skipSpace()
-		if p.empty() {
-			break
-		}
-		if !p.consume(',') {
-			return nil, os.NewError("mail: expected comma")
-		}
-	}
-	return list, nil
-}
-
-// parseAddress parses a single RFC 5322 address at the start of p.
-func (p *addrParser) parseAddress() (addr *Address, err os.Error) {
-	debug.Printf("parseAddress: %q", *p)
-	p.skipSpace()
-	if p.empty() {
-		return nil, os.NewError("mail: no address")
-	}
-
-	// address = name-addr / addr-spec
-	// TODO(dsymonds): Support parsing group address.
-
-	// addr-spec has a more restricted grammar than name-addr,
-	// so try parsing it first, and fallback to name-addr.
-	// TODO(dsymonds): Is this really correct?
-	spec, err := p.consumeAddrSpec()
-	if err == nil {
-		return &Address{
-			Address: spec,
-		}, err
-	}
-	debug.Printf("parseAddress: not an addr-spec: %v", err)
-	debug.Printf("parseAddress: state is now %q", *p)
-
-	// display-name
-	var displayName string
-	if p.peek() != '<' {
-		displayName, err = p.consumePhrase()
-		if err != nil {
-			return nil, err
-		}
-	}
-	debug.Printf("parseAddress: displayName=%q", displayName)
-
-	// angle-addr = "<" addr-spec ">"
-	p.skipSpace()
-	if !p.consume('<') {
-		return nil, os.NewError("mail: no angle-addr")
-	}
-	spec, err = p.consumeAddrSpec()
-	if err != nil {
-		return nil, err
-	}
-	if !p.consume('>') {
-		return nil, os.NewError("mail: unclosed angle-addr")
-	}
-	debug.Printf("parseAddress: spec=%q", spec)
-
-	return &Address{
-		Name:    displayName,
-		Address: spec,
-	}, nil
-}
-
-// consumeAddrSpec parses a single RFC 5322 addr-spec at the start of p.
-func (p *addrParser) consumeAddrSpec() (spec string, err os.Error) {
-	debug.Printf("consumeAddrSpec: %q", *p)
-
-	orig := *p
-	defer func() {
-		if err != nil {
-			*p = orig
-		}
-	}()
-
-	// local-part = dot-atom / quoted-string
-	var localPart string
-	p.skipSpace()
-	if p.empty() {
-		return "", os.NewError("mail: no addr-spec")
-	}
-	if p.peek() == '"' {
-		// quoted-string
-		debug.Printf("consumeAddrSpec: parsing quoted-string")
-		localPart, err = p.consumeQuotedString()
-	} else {
-		// dot-atom
-		debug.Printf("consumeAddrSpec: parsing dot-atom")
-		localPart, err = p.consumeAtom(true)
-	}
-	if err != nil {
-		debug.Printf("consumeAddrSpec: failed: %v", err)
-		return "", err
-	}
-
-	if !p.consume('@') {
-		return "", os.NewError("mail: missing @ in addr-spec")
-	}
-
-	// domain = dot-atom / domain-literal
-	var domain string
-	p.skipSpace()
-	if p.empty() {
-		return "", os.NewError("mail: no domain in addr-spec")
-	}
-	// TODO(dsymonds): Handle domain-literal
-	domain, err = p.consumeAtom(true)
-	if err != nil {
-		return "", err
-	}
-
-	return localPart + "@" + domain, nil
-}
-
-// consumePhrase parses the RFC 5322 phrase at the start of p.
-func (p *addrParser) consumePhrase() (phrase string, err os.Error) {
-	debug.Printf("consumePhrase: [%s]", *p)
-	// phrase = 1*word
-	var words []string
-	for {
-		// word = atom / quoted-string
-		var word string
-		p.skipSpace()
-		if p.empty() {
-			return "", os.NewError("mail: missing phrase")
-		}
-		if p.peek() == '"' {
-			// quoted-string
-			word, err = p.consumeQuotedString()
-		} else {
-			// atom
-			word, err = p.consumeAtom(false)
-		}
-
-		// RFC 2047 encoded-word starts with =?, ends with ?=, and has two other ?s.
-		if err == nil && strings.HasPrefix(word, "=?") && strings.HasSuffix(word, "?=") && strings.Count(word, "?") == 4 {
-			word, err = decodeRFC2047Word(word)
-		}
-
-		if err != nil {
-			break
-		}
-		debug.Printf("consumePhrase: consumed %q", word)
-		words = append(words, word)
-	}
-	// Ignore any error if we got at least one word.
-	if err != nil && len(words) == 0 {
-		debug.Printf("consumePhrase: hit err: %v", err)
-		return "", os.NewError("mail: missing word in phrase")
-	}
-	phrase = strings.Join(words, " ")
-	return phrase, nil
-}
-
-// consumeQuotedString parses the quoted string at the start of p.
-func (p *addrParser) consumeQuotedString() (qs string, err os.Error) {
-	// Assume first byte is '"'.
-	i := 1
-	qsb := make([]byte, 0, 10)
-Loop:
-	for {
-		if i >= p.len() {
-			return "", os.NewError("mail: unclosed quoted-string")
-		}
-		switch c := (*p)[i]; {
-		case c == '"':
-			break Loop
-		case c == '\\':
-			if i+1 == p.len() {
-				return "", os.NewError("mail: unclosed quoted-string")
-			}
-			qsb = append(qsb, (*p)[i+1])
-			i += 2
-		case isQtext(c), c == ' ' || c == '\t':
-			// qtext (printable US-ASCII excluding " and \), or
-			// FWS (almost; we're ignoring CRLF)
-			qsb = append(qsb, c)
-			i++
-		default:
-			return "", fmt.Errorf("mail: bad character in quoted-string: %q", c)
-		}
-	}
-	*p = (*p)[i+1:]
-	return string(qsb), nil
-}
-
-// consumeAtom parses an RFC 5322 atom at the start of p.
-// If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
-func (p *addrParser) consumeAtom(dot bool) (atom string, err os.Error) {
-	if !isAtext(p.peek(), false) {
-		return "", os.NewError("mail: invalid string")
-	}
-	i := 1
-	for ; i < p.len() && isAtext((*p)[i], dot); i++ {
-	}
-	// TODO(dsymonds): Remove the []byte() conversion here when 6g doesn't need it.
-	atom, *p = string([]byte((*p)[:i])), (*p)[i:]
-	return atom, nil
-}
-
-func (p *addrParser) consume(c byte) bool {
-	if p.empty() || p.peek() != c {
-		return false
-	}
-	*p = (*p)[1:]
-	return true
-}
-
-// skipSpace skips the leading space and tab characters.
-func (p *addrParser) skipSpace() {
-	*p = bytes.TrimLeft(*p, " \t")
-}
-
-func (p *addrParser) peek() byte {
-	return (*p)[0]
-}
-
-func (p *addrParser) empty() bool {
-	return p.len() == 0
-}
-
-func (p *addrParser) len() int {
-	return len(*p)
-}
-
-func decodeRFC2047Word(s string) (string, os.Error) {
-	fields := strings.Split(s, "?")
-	if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" {
-		return "", os.NewError("mail: address not RFC 2047 encoded")
-	}
-	charset, enc := strings.ToLower(fields[1]), strings.ToLower(fields[2])
-	if charset != "iso-8859-1" && charset != "utf-8" {
-		return "", fmt.Errorf("mail: charset not supported: %q", charset)
-	}
-
-	in := bytes.NewBufferString(fields[3])
-	var r io.Reader
-	switch enc {
-	case "b":
-		r = base64.NewDecoder(base64.StdEncoding, in)
-	case "q":
-		r = qDecoder{r: in}
-	default:
-		return "", fmt.Errorf("mail: RFC 2047 encoding not supported: %q", enc)
-	}
-
-	dec, err := ioutil.ReadAll(r)
-	if err != nil {
-		return "", err
-	}
-
-	switch charset {
-	case "iso-8859-1":
-		b := new(bytes.Buffer)
-		for _, c := range dec {
-			b.WriteRune(int(c))
-		}
-		return b.String(), nil
-	case "utf-8":
-		return string(dec), nil
-	}
-	panic("unreachable")
-}
-
-type qDecoder struct {
-	r       io.Reader
-	scratch [2]byte
-}
-
-func (qd qDecoder) Read(p []byte) (n int, err os.Error) {
-	// This method writes at most one byte into p.
-	if len(p) == 0 {
-		return 0, nil
-	}
-	if _, err := qd.r.Read(qd.scratch[:1]); err != nil {
-		return 0, err
-	}
-	switch c := qd.scratch[0]; {
-	case c == '=':
-		if _, err := io.ReadFull(qd.r, qd.scratch[:2]); err != nil {
-			return 0, err
-		}
-		x, err := strconv.Btoi64(string(qd.scratch[:2]), 16)
-		if err != nil {
-			return 0, fmt.Errorf("mail: invalid RFC 2047 encoding: %q", qd.scratch[:2])
-		}
-		p[0] = byte(x)
-	case c == '_':
-		p[0] = ' '
-	default:
-		p[0] = c
-	}
-	return 1, nil
-}
-
-var atextChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
-	"abcdefghijklmnopqrstuvwxyz" +
-	"0123456789" +
-	"!#$%&'*+-/=?^_`{|}~")
-
-// isAtext returns true if c is an RFC 5322 atext character.
-// If dot is true, period is included.
-func isAtext(c byte, dot bool) bool {
-	if dot && c == '.' {
-		return true
-	}
-	return bytes.IndexByte(atextChars, c) >= 0
-}
-
-// isQtext returns true if c is an RFC 5322 qtest character.
-func isQtext(c byte) bool {
-	// Printable US-ASCII, excluding backslash or quote.
-	if c == '\\' || c == '"' {
-		return false
-	}
-	return '!' <= c && c <= '~'
-}
-
-// isVchar returns true if c is an RFC 5322 VCHAR character.
-func isVchar(c byte) bool {
-	// Visible (printing) characters.
-	return '!' <= c && c <= '~'
-}
diff --git a/src/pkg/mail/message_test.go b/src/pkg/mail/message_test.go
deleted file mode 100644
index 5653647..0000000
--- a/src/pkg/mail/message_test.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2011 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 mail
-
-import (
-	"bytes"
-	"io/ioutil"
-	"reflect"
-	"testing"
-	"time"
-)
-
-var parseTests = []struct {
-	in     string
-	header Header
-	body   string
-}{
-	{
-		// RFC 5322, Appendix A.1.1
-		in: `From: John Doe <jdoe at machine.example>
-To: Mary Smith <mary at example.net>
-Subject: Saying Hello
-Date: Fri, 21 Nov 1997 09:55:06 -0600
-Message-ID: <1234 at local.machine.example>
-
-This is a message just to say hello.
-So, "Hello".
-`,
-		header: Header{
-			"From":       []string{"John Doe <jdoe at machine.example>"},
-			"To":         []string{"Mary Smith <mary at example.net>"},
-			"Subject":    []string{"Saying Hello"},
-			"Date":       []string{"Fri, 21 Nov 1997 09:55:06 -0600"},
-			"Message-Id": []string{"<1234 at local.machine.example>"},
-		},
-		body: "This is a message just to say hello.\nSo, \"Hello\".\n",
-	},
-}
-
-func TestParsing(t *testing.T) {
-	for i, test := range parseTests {
-		msg, err := ReadMessage(bytes.NewBuffer([]byte(test.in)))
-		if err != nil {
-			t.Errorf("test #%d: Failed parsing message: %v", i, err)
-			continue
-		}
-		if !headerEq(msg.Header, test.header) {
-			t.Errorf("test #%d: Incorrectly parsed message header.\nGot:\n%+v\nWant:\n%+v",
-				i, msg.Header, test.header)
-		}
-		body, err := ioutil.ReadAll(msg.Body)
-		if err != nil {
-			t.Errorf("test #%d: Failed reading body: %v", i, err)
-			continue
-		}
-		bodyStr := string(body)
-		if bodyStr != test.body {
-			t.Errorf("test #%d: Incorrectly parsed message body.\nGot:\n%+v\nWant:\n%+v",
-				i, bodyStr, test.body)
-		}
-	}
-}
-
-func headerEq(a, b Header) bool {
-	if len(a) != len(b) {
-		return false
-	}
-	for k, as := range a {
-		bs, ok := b[k]
-		if !ok {
-			return false
-		}
-		if !reflect.DeepEqual(as, bs) {
-			return false
-		}
-	}
-	return true
-}
-
-func TestDateParsing(t *testing.T) {
-	tests := []struct {
-		dateStr string
-		exp     *time.Time
-	}{
-		// RFC 5322, Appendix A.1.1
-		{
-			"Fri, 21 Nov 1997 09:55:06 -0600",
-			&time.Time{
-				Year:       1997,
-				Month:      11,
-				Day:        21,
-				Hour:       9,
-				Minute:     55,
-				Second:     6,
-				ZoneOffset: -6 * 60 * 60,
-			},
-		},
-		// RFC5322, Appendix A.6.2
-		// Obsolete date.
-		{
-			"21 Nov 97 09:55:06 GMT",
-			&time.Time{
-				Year:   1997,
-				Month:  11,
-				Day:    21,
-				Hour:   9,
-				Minute: 55,
-				Second: 6,
-				Zone:   "GMT",
-			},
-		},
-	}
-	for _, test := range tests {
-		hdr := Header{
-			"Date": []string{test.dateStr},
-		}
-		date, err := hdr.Date()
-		if err != nil {
-			t.Errorf("Failed parsing %q: %v", test.dateStr, err)
-			continue
-		}
-		if !reflect.DeepEqual(date, test.exp) {
-			t.Errorf("Parse of %q: got %+v, want %+v", test.dateStr, date, test.exp)
-		}
-	}
-}
-
-func TestAddressParsing(t *testing.T) {
-	tests := []struct {
-		addrsStr string
-		exp      []*Address
-	}{
-		// Bare address
-		{
-			`jdoe at machine.example`,
-			[]*Address{&Address{
-				Address: "jdoe at machine.example",
-			}},
-		},
-		// RFC 5322, Appendix A.1.1
-		{
-			`John Doe <jdoe at machine.example>`,
-			[]*Address{&Address{
-				Name:    "John Doe",
-				Address: "jdoe at machine.example",
-			}},
-		},
-		// RFC 5322, Appendix A.1.2
-		{
-			`"Joe Q. Public" <john.q.public at example.com>`,
-			[]*Address{&Address{
-				Name:    "Joe Q. Public",
-				Address: "john.q.public at example.com",
-			}},
-		},
-		{
-			`Mary Smith <mary at x.test>, jdoe at example.org, Who? <one at y.test>`,
-			[]*Address{
-				&Address{
-					Name:    "Mary Smith",
-					Address: "mary at x.test",
-				},
-				&Address{
-					Address: "jdoe at example.org",
-				},
-				&Address{
-					Name:    "Who?",
-					Address: "one at y.test",
-				},
-			},
-		},
-		{
-			`<boss at nil.test>, "Giant; \"Big\" Box" <sysservices at example.net>`,
-			[]*Address{
-				&Address{
-					Address: "boss at nil.test",
-				},
-				&Address{
-					Name:    `Giant; "Big" Box`,
-					Address: "sysservices at example.net",
-				},
-			},
-		},
-		// RFC 5322, Appendix A.1.3
-		// TODO(dsymonds): Group addresses.
-
-		// RFC 2047 "Q"-encoded ISO-8859-1 address.
-		{
-			`=?iso-8859-1?q?J=F6rg_Doe?= <joerg at example.com>`,
-			[]*Address{
-				&Address{
-					Name:    `Jörg Doe`,
-					Address: "joerg at example.com",
-				},
-			},
-		},
-		// RFC 2047 "Q"-encoded UTF-8 address.
-		{
-			`=?utf-8?q?J=C3=B6rg_Doe?= <joerg at example.com>`,
-			[]*Address{
-				&Address{
-					Name:    `Jörg Doe`,
-					Address: "joerg at example.com",
-				},
-			},
-		},
-		// RFC 2047, Section 8.
-		{
-			`=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD at vm1.ulg.ac.be>`,
-			[]*Address{
-				&Address{
-					Name:    `André Pirard`,
-					Address: "PIRARD at vm1.ulg.ac.be",
-				},
-			},
-		},
-		// Custom example of RFC 2047 "B"-encoded ISO-8859-1 address.
-		{
-			`=?ISO-8859-1?B?SvZyZw==?= <joerg at example.com>`,
-			[]*Address{
-				&Address{
-					Name:    `Jörg`,
-					Address: "joerg at example.com",
-				},
-			},
-		},
-		// Custom example of RFC 2047 "B"-encoded UTF-8 address.
-		{
-			`=?UTF-8?B?SsO2cmc=?= <joerg at example.com>`,
-			[]*Address{
-				&Address{
-					Name:    `Jörg`,
-					Address: "joerg at example.com",
-				},
-			},
-		},
-	}
-	for _, test := range tests {
-		addrs, err := newAddrParser(test.addrsStr).parseAddressList()
-		if err != nil {
-			t.Errorf("Failed parsing %q: %v", test.addrsStr, err)
-			continue
-		}
-		if !reflect.DeepEqual(addrs, test.exp) {
-			t.Errorf("Parse of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp)
-		}
-	}
-}
-
-func TestAddressFormatting(t *testing.T) {
-	tests := []struct {
-		addr *Address
-		exp  string
-	}{
-		{
-			&Address{Address: "bob at example.com"},
-			"<bob at example.com>",
-		},
-		{
-			&Address{Name: "Bob", Address: "bob at example.com"},
-			`"Bob" <bob at example.com>`,
-		},
-		{
-			// note the ö (o with an umlaut)
-			&Address{Name: "Böb", Address: "bob at example.com"},
-			`=?utf-8?q?B=C3=B6b?= <bob at example.com>`,
-		},
-	}
-	for _, test := range tests {
-		s := test.addr.String()
-		if s != test.exp {
-			t.Errorf("Address%+v.String() = %v, want %v", *test.addr, s, test.exp)
-		}
-	}
-}
diff --git a/src/pkg/math/Makefile b/src/pkg/math/Makefile
index 8e8e74a..d70cba7 100644
--- a/src/pkg/math/Makefile
+++ b/src/pkg/math/Makefile
@@ -6,45 +6,32 @@ include ../../Make.inc
 
 TARG=math
 
-OFILES_arm=\
-	sqrt_arm.$O\
-
-OFILES_amd64=\
-	exp_amd64.$O\
-	fabs_amd64.$O\
-	fdim_amd64.$O\
-	hypot_amd64.$O\
-	log_amd64.$O\
-	sincos_amd64.$O\
-	sqrt_amd64.$O\
-
-OFILES_386=\
-	asin_386.$O\
-	atan_386.$O\
-	atan2_386.$O\
-	exp_386.$O\
-	exp2_386.$O\
-	expm1_386.$O\
-	fabs_386.$O\
-	floor_386.$O\
-	frexp_386.$O\
-	fmod_386.$O\
-	hypot_386.$O\
-	ldexp_386.$O\
-	log_386.$O\
-	log10_386.$O\
-	log1p_386.$O\
-	modf_386.$O\
-	remainder_386.$O\
-	sin_386.$O\
-	sincos_386.$O\
-	sqrt_386.$O\
-	tan_386.$O\
-
 OFILES=\
-	$(OFILES_$(GOARCH))
+	abs_$(GOARCH).$O\
+	asin_$(GOARCH).$O\
+	atan_$(GOARCH).$O\
+	atan2_$(GOARCH).$O\
+	dim_$(GOARCH).$O\
+	exp_$(GOARCH).$O\
+	exp2_$(GOARCH).$O\
+	expm1_$(GOARCH).$O\
+	floor_$(GOARCH).$O\
+	frexp_$(GOARCH).$O\
+	hypot_$(GOARCH).$O\
+	ldexp_$(GOARCH).$O\
+	log_$(GOARCH).$O\
+	log10_$(GOARCH).$O\
+	log1p_$(GOARCH).$O\
+	mod_$(GOARCH).$O\
+	modf_$(GOARCH).$O\
+	remainder_$(GOARCH).$O\
+	sin_$(GOARCH).$O\
+	sincos_$(GOARCH).$O\
+	sqrt_$(GOARCH).$O\
+	tan_$(GOARCH).$O\
 
-ALLGOFILES=\
+GOFILES=\
+	abs.go\
 	acosh.go\
 	asin.go\
 	asinh.go\
@@ -55,19 +42,14 @@ ALLGOFILES=\
 	cbrt.go\
 	const.go\
 	copysign.go\
+	dim.go\
 	erf.go\
 	exp.go\
-	exp_port.go\
-	exp2.go\
 	expm1.go\
-	fabs.go\
-	fdim.go\
 	floor.go\
-	fmod.go\
 	frexp.go\
 	gamma.go\
 	hypot.go\
-	hypot_port.go\
 	j0.go\
 	j1.go\
 	jn.go\
@@ -77,6 +59,7 @@ ALLGOFILES=\
 	log10.go\
 	log1p.go\
 	logb.go\
+	mod.go\
 	modf.go\
 	nextafter.go\
 	pow.go\
@@ -87,16 +70,8 @@ ALLGOFILES=\
 	sincos.go\
 	sinh.go\
 	sqrt.go\
-	sqrt_port.go\
 	tan.go\
 	tanh.go\
 	unsafe.go\
 
-NOGOFILES=\
-	$(subst _$(GOARCH).$O,.go,$(OFILES_$(GOARCH)))
-
-GOFILES=\
-	$(filter-out $(NOGOFILES),$(ALLGOFILES))\
-	$(subst .go,_decl.go,$(NOGOFILES))\
-
 include ../../Make.pkg
diff --git a/src/pkg/math/abs.go b/src/pkg/math/abs.go
new file mode 100644
index 0000000..bc41a6d
--- /dev/null
+++ b/src/pkg/math/abs.go
@@ -0,0 +1,22 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+// Abs returns the absolute value of x.
+//
+// Special cases are:
+//	Abs(±Inf) = +Inf
+//	Abs(NaN) = NaN
+func Abs(x float64) float64
+
+func abs(x float64) float64 {
+	switch {
+	case x < 0:
+		return -x
+	case x == 0:
+		return 0 // return correctly abs(-0)
+	}
+	return x
+}
diff --git a/src/pkg/math/abs_386.s b/src/pkg/math/abs_386.s
new file mode 100644
index 0000000..889e801
--- /dev/null
+++ b/src/pkg/math/abs_386.s
@@ -0,0 +1,10 @@
+// Copyright 2010 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.
+
+// func Abs(x float64) float64
+TEXT ·Abs(SB),7,$0
+	FMOVD   x+0(FP), F0  // F0=x
+	FABS                 // F0=|x|
+	FMOVDP  F0, r+8(FP)
+	RET
diff --git a/src/pkg/math/abs_amd64.s b/src/pkg/math/abs_amd64.s
new file mode 100644
index 0000000..32b7853
--- /dev/null
+++ b/src/pkg/math/abs_amd64.s
@@ -0,0 +1,12 @@
+// Copyright 2010 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.
+
+// func Abs(x float64) float64
+TEXT ·Abs(SB),7,$0
+	MOVQ   $(1<<63), BX
+	MOVQ   BX, X0 // movsd $(-0.0), x0
+	MOVSD  x+0(FP), X1
+	ANDNPD X1, X0
+	MOVSD  X0, r+8(FP)
+	RET
diff --git a/src/pkg/math/abs_arm.s b/src/pkg/math/abs_arm.s
new file mode 100644
index 0000000..23f6a2a
--- /dev/null
+++ b/src/pkg/math/abs_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Abs(SB),7,$0
+	B ·abs(SB)
diff --git a/src/pkg/math/acosh.go b/src/pkg/math/acosh.go
index 7e8740b..8d55637 100644
--- a/src/pkg/math/acosh.go
+++ b/src/pkg/math/acosh.go
@@ -36,6 +36,7 @@ package math
 // Acosh(x) calculates the inverse hyperbolic cosine of x.
 //
 // Special cases are:
+//	Acosh(+Inf) = +Inf
 //	Acosh(x) = NaN if x < 1
 //	Acosh(NaN) = NaN
 func Acosh(x float64) float64 {
diff --git a/src/pkg/math/all_test.go b/src/pkg/math/all_test.go
index 1fe4513..ed66a42 100644
--- a/src/pkg/math/all_test.go
+++ b/src/pkg/math/all_test.go
@@ -7,7 +7,6 @@ package math_test
 import (
 	"fmt"
 	. "math"
-	"runtime"
 	"testing"
 )
 
@@ -23,6 +22,7 @@ var vf = []float64{
 	1.8253080916808550e+00,
 	-8.6859247685756013e+00,
 }
+
 // The expected results below were computed by the high precision calculators
 // at http://keisan.casio.com/.  More exact input values (array vf[], above)
 // were obtained by printing them with "%.26f".  The answers were calculated
@@ -160,6 +160,20 @@ var cos = []float64{
 	-2.517729313893103197176091e-01,
 	-7.39241351595676573201918e-01,
 }
+
+// Results for 100000 * Pi + vf[i]
+var cosLarge = []float64{
+	2.634752141185559426744e-01,
+	1.14855126055543100712e-01,
+	9.61912973266488928113e-01,
+	2.9381411499556122552e-01,
+	-9.777138189880161924641e-01,
+	-9.76930413445147608049e-01,
+	4.940088097314976789841e-01,
+	-9.15658690217517835002e-01,
+	-2.51772931436786954751e-01,
+	-7.3924135157173099849e-01,
+}
 var cosh = []float64{
 	7.2668796942212842775517446e+01,
 	1.1479413465659254502011135e+03,
@@ -502,6 +516,20 @@ var sin = []float64{
 	9.6778633541687993721617774e-01,
 	-6.734405869050344734943028e-01,
 }
+
+// Results for 100000 * Pi + vf[i]
+var sinLarge = []float64{
+	-9.646661658548936063912e-01,
+	9.933822527198506903752e-01,
+	-2.7335587036246899796e-01,
+	9.55862576853689321268e-01,
+	-2.099421066862688873691e-01,
+	2.13557878070308981163e-01,
+	-8.694568970959221300497e-01,
+	4.01956668098863248917e-01,
+	9.67786335404528727927e-01,
+	-6.7344058693131973066e-01,
+}
 var sinh = []float64{
 	7.2661916084208532301448439e+01,
 	1.1479409110035194500526446e+03,
@@ -538,6 +566,20 @@ var tan = []float64{
 	-3.843885560201130679995041e+00,
 	9.10988793377685105753416e-01,
 }
+
+// Results for 100000 * Pi + vf[i]
+var tanLarge = []float64{
+	-3.66131656475596512705e+00,
+	8.6490023287202547927e+00,
+	-2.841794195104782406e-01,
+	3.2532901861033120983e+00,
+	2.14727564046880001365e-01,
+	-2.18600910700688062874e-01,
+	-1.760002817699722747043e+00,
+	-4.38980891453536115952e-01,
+	-3.84388555942723509071e+00,
+	9.1098879344275101051e-01,
+}
 var tanh = []float64{
 	9.9990531206936338549262119e-01,
 	9.9999962057085294197613294e-01,
@@ -920,6 +962,75 @@ var fabsSC = []float64{
 	NaN(),
 }
 
+var vffdimSC = [][2]float64{
+	{Inf(-1), Inf(-1)},
+	{Inf(-1), Inf(1)},
+	{Inf(-1), NaN()},
+	{Copysign(0, -1), Copysign(0, -1)},
+	{Copysign(0, -1), 0},
+	{0, Copysign(0, -1)},
+	{0, 0},
+	{Inf(1), Inf(-1)},
+	{Inf(1), Inf(1)},
+	{Inf(1), NaN()},
+	{NaN(), Inf(-1)},
+	{NaN(), Copysign(0, -1)},
+	{NaN(), 0},
+	{NaN(), Inf(1)},
+	{NaN(), NaN()},
+}
+var fdimSC = []float64{
+	NaN(),
+	0,
+	NaN(),
+	0,
+	0,
+	0,
+	0,
+	Inf(1),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+}
+var fmaxSC = []float64{
+	Inf(-1),
+	Inf(1),
+	NaN(),
+	Copysign(0, -1),
+	0,
+	0,
+	0,
+	Inf(1),
+	Inf(1),
+	Inf(1),
+	NaN(),
+	NaN(),
+	NaN(),
+	Inf(1),
+	NaN(),
+}
+var fminSC = []float64{
+	Inf(-1),
+	Inf(-1),
+	Inf(-1),
+	Copysign(0, -1),
+	Copysign(0, -1),
+	Copysign(0, -1),
+	0,
+	Inf(-1),
+	Inf(1),
+	NaN(),
+	Inf(-1),
+	NaN(),
+	NaN(),
+	NaN(),
+	NaN(),
+}
+
 var vffmodSC = [][2]float64{
 	{Inf(-1), Inf(-1)},
 	{Inf(-1), -Pi},
@@ -1221,12 +1332,26 @@ var modfSC = [][2]float64{
 }
 
 var vfnextafterSC = [][2]float64{
+	{0, 0},
+	{0, Copysign(0, -1)},
+	{0, -1},
 	{0, NaN()},
+	{Copysign(0, -1), 1},
+	{Copysign(0, -1), 0},
+	{Copysign(0, -1), Copysign(0, -1)},
+	{Copysign(0, -1), -1},
 	{NaN(), 0},
 	{NaN(), NaN()},
 }
 var nextafterSC = []float64{
+	0,
+	0,
+	-4.9406564584124654418e-324, // Float64frombits(0x8000000000000001)
 	NaN(),
+	4.9406564584124654418e-324, // Float64frombits(0x0000000000000001)
+	Copysign(0, -1),
+	Copysign(0, -1),
+	-4.9406564584124654418e-324, // Float64frombits(0x8000000000000001)
 	NaN(),
 	NaN(),
 }
@@ -1584,7 +1709,7 @@ func TestAcos(t *testing.T) {
 
 func TestAcosh(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := 1 + Fabs(vf[i])
+		a := 1 + Abs(vf[i])
 		if f := Acosh(a); !veryclose(acosh[i], f) {
 			t.Errorf("Acosh(%g) = %g, want %g", a, f, acosh[i])
 		}
@@ -1709,7 +1834,7 @@ func TestCopysign(t *testing.T) {
 
 func TestCos(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if f := Cos(vf[i]); !close(cos[i], f) {
+		if f := Cos(vf[i]); !veryclose(cos[i], f) {
 			t.Errorf("Cos(%g) = %g, want %g", vf[i], f, cos[i])
 		}
 	}
@@ -1818,23 +1943,28 @@ func testExp2(t *testing.T, Exp2 func(float64) float64, name string) {
 	}
 }
 
-func TestFabs(t *testing.T) {
+func TestAbs(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if f := Fabs(vf[i]); fabs[i] != f {
-			t.Errorf("Fabs(%g) = %g, want %g", vf[i], f, fabs[i])
+		if f := Abs(vf[i]); fabs[i] != f {
+			t.Errorf("Abs(%g) = %g, want %g", vf[i], f, fabs[i])
 		}
 	}
 	for i := 0; i < len(vffabsSC); i++ {
-		if f := Fabs(vffabsSC[i]); !alike(fabsSC[i], f) {
-			t.Errorf("Fabs(%g) = %g, want %g", vffabsSC[i], f, fabsSC[i])
+		if f := Abs(vffabsSC[i]); !alike(fabsSC[i], f) {
+			t.Errorf("Abs(%g) = %g, want %g", vffabsSC[i], f, fabsSC[i])
 		}
 	}
 }
 
-func TestFdim(t *testing.T) {
+func TestDim(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if f := Fdim(vf[i], 0); fdim[i] != f {
-			t.Errorf("Fdim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i])
+		if f := Dim(vf[i], 0); fdim[i] != f {
+			t.Errorf("Dim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i])
+		}
+	}
+	for i := 0; i < len(vffdimSC); i++ {
+		if f := Dim(vffdimSC[i][0], vffdimSC[i][1]); !alike(fdimSC[i], f) {
+			t.Errorf("Dim(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fdimSC[i])
 		}
 	}
 }
@@ -1852,31 +1982,41 @@ func TestFloor(t *testing.T) {
 	}
 }
 
-func TestFmax(t *testing.T) {
+func TestMax(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if f := Fmax(vf[i], ceil[i]); ceil[i] != f {
-			t.Errorf("Fmax(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i])
+		if f := Max(vf[i], ceil[i]); ceil[i] != f {
+			t.Errorf("Max(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i])
+		}
+	}
+	for i := 0; i < len(vffdimSC); i++ {
+		if f := Max(vffdimSC[i][0], vffdimSC[i][1]); !alike(fmaxSC[i], f) {
+			t.Errorf("Max(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fmaxSC[i])
 		}
 	}
 }
 
-func TestFmin(t *testing.T) {
+func TestMin(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if f := Fmin(vf[i], floor[i]); floor[i] != f {
-			t.Errorf("Fmin(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i])
+		if f := Min(vf[i], floor[i]); floor[i] != f {
+			t.Errorf("Min(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i])
+		}
+	}
+	for i := 0; i < len(vffdimSC); i++ {
+		if f := Min(vffdimSC[i][0], vffdimSC[i][1]); !alike(fminSC[i], f) {
+			t.Errorf("Min(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fminSC[i])
 		}
 	}
 }
 
-func TestFmod(t *testing.T) {
+func TestMod(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if f := Fmod(10, vf[i]); fmod[i] != f {
-			t.Errorf("Fmod(10, %g) = %g, want %g", vf[i], f, fmod[i])
+		if f := Mod(10, vf[i]); fmod[i] != f {
+			t.Errorf("Mod(10, %g) = %g, want %g", vf[i], f, fmod[i])
 		}
 	}
 	for i := 0; i < len(vffmodSC); i++ {
-		if f := Fmod(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) {
-			t.Errorf("Fmod(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i])
+		if f := Mod(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) {
+			t.Errorf("Mod(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i])
 		}
 	}
 }
@@ -1914,7 +2054,7 @@ func TestGamma(t *testing.T) {
 
 func TestHypot(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := Fabs(1e200 * tanh[i] * Sqrt(2))
+		a := Abs(1e200 * tanh[i] * Sqrt(2))
 		if f := Hypot(1e200*tanh[i], 1e200*tanh[i]); !veryclose(a, f) {
 			t.Errorf("Hypot(%g, %g) = %g, want %g", 1e200*tanh[i], 1e200*tanh[i], f, a)
 		}
@@ -1926,6 +2066,20 @@ func TestHypot(t *testing.T) {
 	}
 }
 
+func TestHypotGo(t *testing.T) {
+	for i := 0; i < len(vf); i++ {
+		a := Abs(1e200 * tanh[i] * Sqrt(2))
+		if f := HypotGo(1e200*tanh[i], 1e200*tanh[i]); !veryclose(a, f) {
+			t.Errorf("HypotGo(%g, %g) = %g, want %g", 1e200*tanh[i], 1e200*tanh[i], f, a)
+		}
+	}
+	for i := 0; i < len(vfhypotSC); i++ {
+		if f := HypotGo(vfhypotSC[i][0], vfhypotSC[i][1]); !alike(hypotSC[i], f) {
+			t.Errorf("HypotGo(%g, %g) = %g, want %g", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i])
+		}
+	}
+}
+
 func TestIlogb(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
 		a := frexp[i].i - 1 // adjust because fr in the interval [½, 1)
@@ -2033,7 +2187,7 @@ func TestLgamma(t *testing.T) {
 
 func TestLog(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := Fabs(vf[i])
+		a := Abs(vf[i])
 		if f := Log(a); log[i] != f {
 			t.Errorf("Log(%g) = %g, want %g", a, f, log[i])
 		}
@@ -2060,15 +2214,15 @@ func TestLogb(t *testing.T) {
 		}
 	}
 	for i := 0; i < len(vffrexpBC); i++ {
-		if e := Logb(vffrexpBC[i]); !alike(logbBC[i], e) {
-			t.Errorf("Ilogb(%g) = %g, want %g", vffrexpBC[i], e, logbBC[i])
+		if f := Logb(vffrexpBC[i]); !alike(logbBC[i], f) {
+			t.Errorf("Logb(%g) = %g, want %g", vffrexpBC[i], f, logbBC[i])
 		}
 	}
 }
 
 func TestLog10(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := Fabs(vf[i])
+		a := Abs(vf[i])
 		if f := Log10(a); !veryclose(log10[i], f) {
 			t.Errorf("Log10(%g) = %g, want %g", a, f, log10[i])
 		}
@@ -2103,7 +2257,7 @@ func TestLog1p(t *testing.T) {
 
 func TestLog2(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := Fabs(vf[i])
+		a := Abs(vf[i])
 		if f := Log2(a); !veryclose(log2[i], f) {
 			t.Errorf("Log2(%g) = %g, want %g", a, f, log2[i])
 		}
@@ -2137,7 +2291,7 @@ func TestNextafter(t *testing.T) {
 			t.Errorf("Nextafter(%g, %g) = %g want %g", vf[i], 10.0, f, nextafter[i])
 		}
 	}
-	for i := 0; i < len(vfmodfSC); i++ {
+	for i := 0; i < len(vfnextafterSC); i++ {
 		if f := Nextafter(vfnextafterSC[i][0], vfnextafterSC[i][1]); !alike(nextafterSC[i], f) {
 			t.Errorf("Nextafter(%g, %g) = %g want %g", vfnextafterSC[i][0], vfnextafterSC[i][1], f, nextafterSC[i])
 		}
@@ -2192,7 +2346,7 @@ func TestSignbit(t *testing.T) {
 }
 func TestSin(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if f := Sin(vf[i]); !close(sin[i], f) {
+		if f := Sin(vf[i]); !veryclose(sin[i], f) {
 			t.Errorf("Sin(%g) = %g, want %g", vf[i], f, sin[i])
 		}
 	}
@@ -2205,7 +2359,7 @@ func TestSin(t *testing.T) {
 
 func TestSincos(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if s, c := Sincos(vf[i]); !close(sin[i], s) || !close(cos[i], c) {
+		if s, c := Sincos(vf[i]); !veryclose(sin[i], s) || !veryclose(cos[i], c) {
 			t.Errorf("Sincos(%g) = %g, %g want %g, %g", vf[i], s, c, sin[i], cos[i])
 		}
 	}
@@ -2226,11 +2380,11 @@ func TestSinh(t *testing.T) {
 
 func TestSqrt(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := Fabs(vf[i])
+		a := Abs(vf[i])
 		if f := SqrtGo(a); sqrt[i] != f {
 			t.Errorf("SqrtGo(%g) = %g, want %g", a, f, sqrt[i])
 		}
-		a = Fabs(vf[i])
+		a = Abs(vf[i])
 		if f := Sqrt(a); sqrt[i] != f {
 			t.Errorf("Sqrt(%g) = %g, want %g", a, f, sqrt[i])
 		}
@@ -2247,7 +2401,7 @@ func TestSqrt(t *testing.T) {
 
 func TestTan(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		if f := Tan(vf[i]); !close(tan[i], f) {
+		if f := Tan(vf[i]); !veryclose(tan[i], f) {
 			t.Errorf("Tan(%g) = %g, want %g", vf[i], f, tan[i])
 		}
 	}
@@ -2257,16 +2411,6 @@ func TestTan(t *testing.T) {
 			t.Errorf("Tan(%g) = %g, want %g", vfsinSC[i], f, sinSC[i])
 		}
 	}
-
-	// Make sure portable Tan(Pi/2) doesn't panic (it used to).
-	// The portable implementation returns NaN.
-	// Assembly implementations might not,
-	// because Pi/2 is not exactly representable.
-	if runtime.GOARCH != "386" {
-		if f := Tan(Pi / 2); !alike(f, NaN()) {
-			t.Errorf("Tan(%g) = %g, want %g", Pi/2, f, NaN())
-		}
-	}
 }
 
 func TestTanh(t *testing.T) {
@@ -2297,7 +2441,7 @@ func TestTrunc(t *testing.T) {
 
 func TestY0(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := Fabs(vf[i])
+		a := Abs(vf[i])
 		if f := Y0(a); !close(y0[i], f) {
 			t.Errorf("Y0(%g) = %g, want %g", a, f, y0[i])
 		}
@@ -2311,7 +2455,7 @@ func TestY0(t *testing.T) {
 
 func TestY1(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := Fabs(vf[i])
+		a := Abs(vf[i])
 		if f := Y1(a); !soclose(y1[i], f, 2e-14) {
 			t.Errorf("Y1(%g) = %g, want %g", a, f, y1[i])
 		}
@@ -2325,7 +2469,7 @@ func TestY1(t *testing.T) {
 
 func TestYn(t *testing.T) {
 	for i := 0; i < len(vf); i++ {
-		a := Fabs(vf[i])
+		a := Abs(vf[i])
 		if f := Yn(2, a); !close(y2[i], f) {
 			t.Errorf("Yn(2, %g) = %g, want %g", a, f, y2[i])
 		}
@@ -2344,13 +2488,15 @@ func TestYn(t *testing.T) {
 }
 
 // Check that math functions of high angle values
-// return similar results to low angle values
+// return accurate results. [Since (vf[i] + large) - large != vf[i],
+// testing for Trig(vf[i] + large) == Trig(vf[i]), where large is
+// a multiple of 2*Pi, is misleading.]
 func TestLargeCos(t *testing.T) {
 	large := float64(100000 * Pi)
 	for i := 0; i < len(vf); i++ {
-		f1 := Cos(vf[i])
+		f1 := cosLarge[i]
 		f2 := Cos(vf[i] + large)
-		if !kindaclose(f1, f2) {
+		if !close(f1, f2) {
 			t.Errorf("Cos(%g) = %g, want %g", vf[i]+large, f2, f1)
 		}
 	}
@@ -2359,9 +2505,9 @@ func TestLargeCos(t *testing.T) {
 func TestLargeSin(t *testing.T) {
 	large := float64(100000 * Pi)
 	for i := 0; i < len(vf); i++ {
-		f1 := Sin(vf[i])
+		f1 := sinLarge[i]
 		f2 := Sin(vf[i] + large)
-		if !kindaclose(f1, f2) {
+		if !close(f1, f2) {
 			t.Errorf("Sin(%g) = %g, want %g", vf[i]+large, f2, f1)
 		}
 	}
@@ -2370,9 +2516,9 @@ func TestLargeSin(t *testing.T) {
 func TestLargeSincos(t *testing.T) {
 	large := float64(100000 * Pi)
 	for i := 0; i < len(vf); i++ {
-		f1, g1 := Sincos(vf[i])
+		f1, g1 := sinLarge[i], cosLarge[i]
 		f2, g2 := Sincos(vf[i] + large)
-		if !kindaclose(f1, f2) || !kindaclose(g1, g2) {
+		if !close(f1, f2) || !close(g1, g2) {
 			t.Errorf("Sincos(%g) = %g, %g, want %g, %g", vf[i]+large, f2, g2, f1, g1)
 		}
 	}
@@ -2381,16 +2527,16 @@ func TestLargeSincos(t *testing.T) {
 func TestLargeTan(t *testing.T) {
 	large := float64(100000 * Pi)
 	for i := 0; i < len(vf); i++ {
-		f1 := Tan(vf[i])
+		f1 := tanLarge[i]
 		f2 := Tan(vf[i] + large)
-		if !kindaclose(f1, f2) {
+		if !close(f1, f2) {
 			t.Errorf("Tan(%g) = %g, want %g", vf[i]+large, f2, f1)
 		}
 	}
 }
 
 // Check that math constants are accepted by compiler
-// and have right value (assumes strconv.Atof works).
+// and have right value (assumes strconv.ParseFloat works).
 // http://code.google.com/p/go/issues/detail?id=201
 
 type floatTest struct {
@@ -2531,15 +2677,15 @@ func BenchmarkExp2Go(b *testing.B) {
 	}
 }
 
-func BenchmarkFabs(b *testing.B) {
+func BenchmarkAbs(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Fabs(.5)
+		Abs(.5)
 	}
 }
 
-func BenchmarkFdim(b *testing.B) {
+func BenchmarkDim(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Fdim(10, 3)
+		Dim(10, 3)
 	}
 }
 
@@ -2549,21 +2695,21 @@ func BenchmarkFloor(b *testing.B) {
 	}
 }
 
-func BenchmarkFmax(b *testing.B) {
+func BenchmarkMax(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Fmax(10, 3)
+		Max(10, 3)
 	}
 }
 
-func BenchmarkFmin(b *testing.B) {
+func BenchmarkMin(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Fmin(10, 3)
+		Min(10, 3)
 	}
 }
 
-func BenchmarkFmod(b *testing.B) {
+func BenchmarkMod(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Fmod(10, 3)
+		Mod(10, 3)
 	}
 }
 
diff --git a/src/pkg/math/asin.go b/src/pkg/math/asin.go
index 0a0b0a1..00bf61e 100644
--- a/src/pkg/math/asin.go
+++ b/src/pkg/math/asin.go
@@ -16,7 +16,9 @@ package math
 // Special cases are:
 //	Asin(±0) = ±0
 //	Asin(x) = NaN if x < -1 or x > 1
-func Asin(x float64) float64 {
+func Asin(x float64) float64
+
+func asin(x float64) float64 {
 	if x == 0 {
 		return x // special case
 	}
@@ -46,4 +48,8 @@ func Asin(x float64) float64 {
 //
 // Special case is:
 //	Acos(x) = NaN if x < -1 or x > 1
-func Acos(x float64) float64 { return Pi/2 - Asin(x) }
+func Acos(x float64) float64
+
+func acos(x float64) float64 {
+	return Pi/2 - Asin(x)
+}
diff --git a/src/pkg/math/asin_amd64.s b/src/pkg/math/asin_amd64.s
new file mode 100644
index 0000000..42151f1
--- /dev/null
+++ b/src/pkg/math/asin_amd64.s
@@ -0,0 +1,9 @@
+// Copyright 2011 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.
+
+TEXT ·Asin(SB),7,$0
+	JMP ·asin(SB)
+
+TEXT ·Acos(SB),7,$0
+	JMP ·acos(SB)
diff --git a/src/pkg/math/asin_arm.s b/src/pkg/math/asin_arm.s
new file mode 100644
index 0000000..d27213f
--- /dev/null
+++ b/src/pkg/math/asin_arm.s
@@ -0,0 +1,9 @@
+// Copyright 2011 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.
+
+TEXT ·Asin(SB),7,$0
+	B ·asin(SB)
+
+TEXT ·Acos(SB),7,$0
+	B ·acos(SB)
diff --git a/src/pkg/math/asin_decl.go b/src/pkg/math/asin_decl.go
deleted file mode 100644
index 63a55dc..0000000
--- a/src/pkg/math/asin_decl.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2010 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 math
-
-func Acos(x float64) float64
-func Asin(x float64) float64
diff --git a/src/pkg/math/asinh.go b/src/pkg/math/asinh.go
index c1cad56..f786dd9 100644
--- a/src/pkg/math/asinh.go
+++ b/src/pkg/math/asinh.go
@@ -33,8 +33,8 @@ package math
 // Asinh(x) calculates the inverse hyperbolic sine of x.
 //
 // Special cases are:
-//	Asinh(+Inf) = +Inf
-//	Asinh(-Inf) = -Inf
+//	Asinh(±0) = ±0
+//	Asinh(±Inf) = ±Inf
 //	Asinh(NaN) = NaN
 func Asinh(x float64) float64 {
 	const (
diff --git a/src/pkg/math/atan.go b/src/pkg/math/atan.go
index 9d4ec2f..d424a2b 100644
--- a/src/pkg/math/atan.go
+++ b/src/pkg/math/atan.go
@@ -51,7 +51,9 @@ func satan(arg float64) float64 {
 // Special cases are:
 //	Atan(±0) = ±0
 //	Atan(±Inf) = ±Pi/2
-func Atan(x float64) float64 {
+func Atan(x float64) float64
+
+func atan(x float64) float64 {
 	if x == 0 {
 		return x
 	}
diff --git a/src/pkg/math/atan2.go b/src/pkg/math/atan2.go
index 49d4bdd..3d1b52a 100644
--- a/src/pkg/math/atan2.go
+++ b/src/pkg/math/atan2.go
@@ -26,7 +26,9 @@ package math
 //	Atan2(y<0, -Inf) = -Pi
 //	Atan2(+Inf, x) = +Pi/2
 //	Atan2(-Inf, x) = -Pi/2
-func Atan2(y, x float64) float64 {
+func Atan2(y, x float64) float64
+
+func atan2(y, x float64) float64 {
 	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
 	// when compiler does it for us
 	// special cases
diff --git a/src/pkg/math/atan2_386.s b/src/pkg/math/atan2_386.s
old mode 100755
new mode 100644
diff --git a/src/pkg/math/atan2_amd64.s b/src/pkg/math/atan2_amd64.s
new file mode 100644
index 0000000..1c5b038
--- /dev/null
+++ b/src/pkg/math/atan2_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Atan2(SB),7,$0
+	JMP ·atan2(SB)
diff --git a/src/pkg/math/atan2_arm.s b/src/pkg/math/atan2_arm.s
new file mode 100644
index 0000000..c2edafa
--- /dev/null
+++ b/src/pkg/math/atan2_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Atan2(SB),7,$0
+	B ·atan2(SB)
diff --git a/src/pkg/math/atan2_decl.go b/src/pkg/math/atan2_decl.go
deleted file mode 100644
index 3932ed6..0000000
--- a/src/pkg/math/atan2_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Atan2(y, x float64) float64
diff --git a/src/pkg/math/atan_amd64.s b/src/pkg/math/atan_amd64.s
new file mode 100644
index 0000000..206072b
--- /dev/null
+++ b/src/pkg/math/atan_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Atan(SB),7,$0
+	JMP ·atan(SB)
diff --git a/src/pkg/math/atan_arm.s b/src/pkg/math/atan_arm.s
new file mode 100644
index 0000000..ed492ab
--- /dev/null
+++ b/src/pkg/math/atan_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Atan(SB),7,$0
+	B ·atan(SB)
diff --git a/src/pkg/math/atan_decl.go b/src/pkg/math/atan_decl.go
deleted file mode 100644
index 14d3fc0..0000000
--- a/src/pkg/math/atan_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Atan(x float64) float64
diff --git a/src/pkg/math/atanh.go b/src/pkg/math/atanh.go
index ed38fca..e150673 100644
--- a/src/pkg/math/atanh.go
+++ b/src/pkg/math/atanh.go
@@ -39,9 +39,10 @@ package math
 // Atanh(x) calculates the inverse hyperbolic tangent of x.
 //
 // Special cases are:
-//	Atanh(x) = NaN if x < -1 or x > 1
 //	Atanh(1) = +Inf
+//	Atanh(±0) = ±0
 //	Atanh(-1) = -Inf
+//	Atanh(x) = NaN if x < -1 or x > 1
 //	Atanh(NaN) = NaN
 func Atanh(x float64) float64 {
 	const NearZero = 1.0 / (1 << 28) // 2**-28
diff --git a/src/pkg/math/big/Makefile b/src/pkg/math/big/Makefile
new file mode 100644
index 0000000..1ba0818
--- /dev/null
+++ b/src/pkg/math/big/Makefile
@@ -0,0 +1,18 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=math/big
+GOFILES=\
+	arith.go\
+	arith_decl.go\
+	int.go\
+	nat.go\
+	rat.go\
+
+OFILES=\
+	arith_$(GOARCH).$O\
+
+include ../../../Make.pkg
diff --git a/src/pkg/math/big/arith.go b/src/pkg/math/big/arith.go
new file mode 100644
index 0000000..5a30d3c
--- /dev/null
+++ b/src/pkg/math/big/arith.go
@@ -0,0 +1,243 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file provides Go implementations of elementary multi-precision
+// arithmetic operations on word vectors. Needed for platforms without
+// assembly implementations of these routines.
+
+package big
+
+// TODO(gri) Decide if Word needs to remain exported.
+
+type Word uintptr
+
+const (
+	// Compute the size _S of a Word in bytes.
+	_m    = ^Word(0)
+	_logS = _m>>8&1 + _m>>16&1 + _m>>32&1
+	_S    = 1 << _logS
+
+	_W = _S << 3 // word size in bits
+	_B = 1 << _W // digit base
+	_M = _B - 1  // digit mask
+
+	_W2 = _W / 2   // half word size in bits
+	_B2 = 1 << _W2 // half digit base
+	_M2 = _B2 - 1  // half digit mask
+)
+
+// ----------------------------------------------------------------------------
+// Elementary operations on words
+//
+// These operations are used by the vector operations below.
+
+// z1<<_W + z0 = x+y+c, with c == 0 or 1
+func addWW_g(x, y, c Word) (z1, z0 Word) {
+	yc := y + c
+	z0 = x + yc
+	if z0 < x || yc < y {
+		z1 = 1
+	}
+	return
+}
+
+// z1<<_W + z0 = x-y-c, with c == 0 or 1
+func subWW_g(x, y, c Word) (z1, z0 Word) {
+	yc := y + c
+	z0 = x - yc
+	if z0 > x || yc < y {
+		z1 = 1
+	}
+	return
+}
+
+// z1<<_W + z0 = x*y
+// Adapted from Warren, Hacker's Delight, p. 132.
+func mulWW_g(x, y Word) (z1, z0 Word) {
+	x0 := x & _M2
+	x1 := x >> _W2
+	y0 := y & _M2
+	y1 := y >> _W2
+	w0 := x0 * y0
+	t := x1*y0 + w0>>_W2
+	w1 := t & _M2
+	w2 := t >> _W2
+	w1 += x0 * y1
+	z1 = x1*y1 + w2 + w1>>_W2
+	z0 = x * y
+	return
+}
+
+// z1<<_W + z0 = x*y + c
+func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
+	z1, zz0 := mulWW(x, y)
+	if z0 = zz0 + c; z0 < zz0 {
+		z1++
+	}
+	return
+}
+
+// Length of x in bits.
+func bitLen_g(x Word) (n int) {
+	for ; x >= 0x8000; x >>= 16 {
+		n += 16
+	}
+	if x >= 0x80 {
+		x >>= 8
+		n += 8
+	}
+	if x >= 0x8 {
+		x >>= 4
+		n += 4
+	}
+	if x >= 0x2 {
+		x >>= 2
+		n += 2
+	}
+	if x >= 0x1 {
+		n++
+	}
+	return
+}
+
+// log2 computes the integer binary logarithm of x.
+// The result is the integer n for which 2^n <= x < 2^(n+1).
+// If x == 0, the result is -1.
+func log2(x Word) int {
+	return bitLen(x) - 1
+}
+
+// Number of leading zeros in x.
+func leadingZeros(x Word) uint {
+	return uint(_W - bitLen(x))
+}
+
+// q = (u1<<_W + u0 - r)/y
+// Adapted from Warren, Hacker's Delight, p. 152.
+func divWW_g(u1, u0, v Word) (q, r Word) {
+	if u1 >= v {
+		return 1<<_W - 1, 1<<_W - 1
+	}
+
+	s := leadingZeros(v)
+	v <<= s
+
+	vn1 := v >> _W2
+	vn0 := v & _M2
+	un32 := u1<<s | u0>>(_W-s)
+	un10 := u0 << s
+	un1 := un10 >> _W2
+	un0 := un10 & _M2
+	q1 := un32 / vn1
+	rhat := un32 - q1*vn1
+
+again1:
+	if q1 >= _B2 || q1*vn0 > _B2*rhat+un1 {
+		q1--
+		rhat += vn1
+		if rhat < _B2 {
+			goto again1
+		}
+	}
+
+	un21 := un32*_B2 + un1 - q1*v
+	q0 := un21 / vn1
+	rhat = un21 - q0*vn1
+
+again2:
+	if q0 >= _B2 || q0*vn0 > _B2*rhat+un0 {
+		q0--
+		rhat += vn1
+		if rhat < _B2 {
+			goto again2
+		}
+	}
+
+	return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s
+}
+
+func addVV_g(z, x, y []Word) (c Word) {
+	for i := range z {
+		c, z[i] = addWW_g(x[i], y[i], c)
+	}
+	return
+}
+
+func subVV_g(z, x, y []Word) (c Word) {
+	for i := range z {
+		c, z[i] = subWW_g(x[i], y[i], c)
+	}
+	return
+}
+
+func addVW_g(z, x []Word, y Word) (c Word) {
+	c = y
+	for i := range z {
+		c, z[i] = addWW_g(x[i], c, 0)
+	}
+	return
+}
+
+func subVW_g(z, x []Word, y Word) (c Word) {
+	c = y
+	for i := range z {
+		c, z[i] = subWW_g(x[i], c, 0)
+	}
+	return
+}
+
+func shlVU_g(z, x []Word, s uint) (c Word) {
+	if n := len(z); n > 0 {
+		ŝ := _W - s
+		w1 := x[n-1]
+		c = w1 >> ŝ
+		for i := n - 1; i > 0; i-- {
+			w := w1
+			w1 = x[i-1]
+			z[i] = w<<s | w1>>ŝ
+		}
+		z[0] = w1 << s
+	}
+	return
+}
+
+func shrVU_g(z, x []Word, s uint) (c Word) {
+	if n := len(z); n > 0 {
+		ŝ := _W - s
+		w1 := x[0]
+		c = w1 << ŝ
+		for i := 0; i < n-1; i++ {
+			w := w1
+			w1 = x[i+1]
+			z[i] = w>>s | w1<<ŝ
+		}
+		z[n-1] = w1 >> s
+	}
+	return
+}
+
+func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
+	c = r
+	for i := range z {
+		c, z[i] = mulAddWWW_g(x[i], y, c)
+	}
+	return
+}
+
+func addMulVVW_g(z, x []Word, y Word) (c Word) {
+	for i := range z {
+		z1, z0 := mulAddWWW_g(x[i], y, z[i])
+		c, z[i] = addWW_g(z0, c, 0)
+		c += z1
+	}
+	return
+}
+
+func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) {
+	r = xn
+	for i := len(z) - 1; i >= 0; i-- {
+		z[i], r = divWW_g(r, x[i], y)
+	}
+	return
+}
diff --git a/src/pkg/math/big/arith_386.s b/src/pkg/math/big/arith_386.s
new file mode 100644
index 0000000..f1262c6
--- /dev/null
+++ b/src/pkg/math/big/arith_386.s
@@ -0,0 +1,276 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file provides fast assembly versions for the elementary
+// arithmetic operations on vectors implemented in arith.go.
+
+// func mulWW(x, y Word) (z1, z0 Word)
+TEXT ·mulWW(SB),7,$0
+	MOVL x+0(FP), AX
+	MULL y+4(FP)
+	MOVL DX, z1+8(FP)
+	MOVL AX, z0+12(FP)
+	RET
+
+
+// func divWW(x1, x0, y Word) (q, r Word)
+TEXT ·divWW(SB),7,$0
+	MOVL x1+0(FP), DX
+	MOVL x0+4(FP), AX
+	DIVL y+8(FP)
+	MOVL AX, q+12(FP)
+	MOVL DX, r+16(FP)
+	RET
+
+
+// func addVV(z, x, y []Word) (c Word)
+TEXT ·addVV(SB),7,$0
+	MOVL z+0(FP), DI
+	MOVL x+12(FP), SI
+	MOVL y+24(FP), CX
+	MOVL n+4(FP), BP
+	MOVL $0, BX		// i = 0
+	MOVL $0, DX		// c = 0
+	JMP E1
+
+L1:	MOVL (SI)(BX*4), AX
+	RCRL $1, DX
+	ADCL (CX)(BX*4), AX
+	RCLL $1, DX
+	MOVL AX, (DI)(BX*4)
+	ADDL $1, BX		// i++
+
+E1:	CMPL BX, BP		// i < n
+	JL L1
+
+	MOVL DX, c+36(FP)
+	RET
+
+
+// func subVV(z, x, y []Word) (c Word)
+// (same as addVV except for SBBL instead of ADCL and label names)
+TEXT ·subVV(SB),7,$0
+	MOVL z+0(FP), DI
+	MOVL x+12(FP), SI
+	MOVL y+24(FP), CX
+	MOVL n+4(FP), BP
+	MOVL $0, BX		// i = 0
+	MOVL $0, DX		// c = 0
+	JMP E2
+
+L2:	MOVL (SI)(BX*4), AX
+	RCRL $1, DX
+	SBBL (CX)(BX*4), AX
+	RCLL $1, DX
+	MOVL AX, (DI)(BX*4)
+	ADDL $1, BX		// i++
+
+E2:	CMPL BX, BP		// i < n
+	JL L2
+
+	MOVL DX, c+36(FP)
+	RET
+
+
+// func addVW(z, x []Word, y Word) (c Word)
+TEXT ·addVW(SB),7,$0
+	MOVL z+0(FP), DI
+	MOVL x+12(FP), SI
+	MOVL y+24(FP), AX	// c = y
+	MOVL n+4(FP), BP
+	MOVL $0, BX		// i = 0
+	JMP E3
+
+L3:	ADDL (SI)(BX*4), AX
+	MOVL AX, (DI)(BX*4)
+	RCLL $1, AX
+	ANDL $1, AX
+	ADDL $1, BX		// i++
+
+E3:	CMPL BX, BP		// i < n
+	JL L3
+
+	MOVL AX, c+28(FP)
+	RET
+
+
+// func subVW(z, x []Word, y Word) (c Word)
+TEXT ·subVW(SB),7,$0
+	MOVL z+0(FP), DI
+	MOVL x+12(FP), SI
+	MOVL y+24(FP), AX	// c = y
+	MOVL n+4(FP), BP
+	MOVL $0, BX		// i = 0
+	JMP E4
+
+L4:	MOVL (SI)(BX*4), DX	// TODO(gri) is there a reverse SUBL?
+	SUBL AX, DX
+	MOVL DX, (DI)(BX*4)
+	RCLL $1, AX
+	ANDL $1, AX
+	ADDL $1, BX		// i++
+
+E4:	CMPL BX, BP		// i < n
+	JL L4
+
+	MOVL AX, c+28(FP)
+	RET
+
+
+// func shlVU(z, x []Word, s uint) (c Word)
+TEXT ·shlVU(SB),7,$0
+	MOVL n+4(FP), BX	// i = n
+	SUBL $1, BX		// i--
+	JL X8b			// i < 0	(n <= 0)
+
+	// n > 0
+	MOVL z+0(FP), DI
+	MOVL x+12(FP), SI
+	MOVL s+24(FP), CX
+	MOVL (SI)(BX*4), AX	// w1 = x[n-1]
+	MOVL $0, DX
+	SHLL CX, DX:AX		// w1>>ŝ
+	MOVL DX, c+28(FP)
+
+	CMPL BX, $0
+	JLE X8a			// i <= 0
+
+	// i > 0
+L8:	MOVL AX, DX		// w = w1
+	MOVL -4(SI)(BX*4), AX	// w1 = x[i-1]
+	SHLL CX, DX:AX		// w<<s | w1>>ŝ
+	MOVL DX, (DI)(BX*4)	// z[i] = w<<s | w1>>ŝ
+	SUBL $1, BX		// i--
+	JG L8			// i > 0
+
+	// i <= 0
+X8a:	SHLL CX, AX		// w1<<s
+	MOVL AX, (DI)		// z[0] = w1<<s
+	RET
+
+X8b:	MOVL $0, c+28(FP)
+	RET
+
+
+// func shrVU(z, x []Word, s uint) (c Word)
+TEXT ·shrVU(SB),7,$0
+	MOVL n+4(FP), BP
+	SUBL $1, BP		// n--
+	JL X9b			// n < 0	(n <= 0)
+
+	// n > 0
+	MOVL z+0(FP), DI
+	MOVL x+12(FP), SI
+	MOVL s+24(FP), CX
+	MOVL (SI), AX		// w1 = x[0]
+	MOVL $0, DX
+	SHRL CX, DX:AX		// w1<<ŝ
+	MOVL DX, c+28(FP)
+
+	MOVL $0, BX		// i = 0
+	JMP E9
+
+	// i < n-1
+L9:	MOVL AX, DX		// w = w1
+	MOVL 4(SI)(BX*4), AX	// w1 = x[i+1]
+	SHRL CX, DX:AX		// w>>s | w1<<ŝ
+	MOVL DX, (DI)(BX*4)	// z[i] = w>>s | w1<<ŝ
+	ADDL $1, BX		// i++
+	
+E9:	CMPL BX, BP
+	JL L9			// i < n-1
+
+	// i >= n-1
+X9a:	SHRL CX, AX		// w1>>s
+	MOVL AX, (DI)(BP*4)	// z[n-1] = w1>>s
+	RET
+
+X9b:	MOVL $0, c+28(FP)
+	RET
+
+
+// func mulAddVWW(z, x []Word, y, r Word) (c Word)
+TEXT ·mulAddVWW(SB),7,$0
+	MOVL z+0(FP), DI
+	MOVL x+12(FP), SI
+	MOVL y+24(FP), BP
+	MOVL r+28(FP), CX	// c = r
+	MOVL n+4(FP), BX
+	LEAL (DI)(BX*4), DI
+	LEAL (SI)(BX*4), SI
+	NEGL BX			// i = -n
+	JMP E5
+
+L5:	MOVL (SI)(BX*4), AX
+	MULL BP
+	ADDL CX, AX
+	ADCL $0, DX
+	MOVL AX, (DI)(BX*4)
+	MOVL DX, CX
+	ADDL $1, BX		// i++
+
+E5:	CMPL BX, $0		// i < 0
+	JL L5
+
+	MOVL CX, c+32(FP)
+	RET
+
+
+// func addMulVVW(z, x []Word, y Word) (c Word)
+TEXT ·addMulVVW(SB),7,$0
+	MOVL z+0(FP), DI
+	MOVL x+12(FP), SI
+	MOVL y+24(FP), BP
+	MOVL n+4(FP), BX
+	LEAL (DI)(BX*4), DI
+	LEAL (SI)(BX*4), SI
+	NEGL BX			// i = -n
+	MOVL $0, CX		// c = 0
+	JMP E6
+
+L6:	MOVL (SI)(BX*4), AX
+	MULL BP
+	ADDL CX, AX
+	ADCL $0, DX
+	ADDL AX, (DI)(BX*4)
+	ADCL $0, DX
+	MOVL DX, CX
+	ADDL $1, BX		// i++
+
+E6:	CMPL BX, $0		// i < 0
+	JL L6
+
+	MOVL CX, c+28(FP)
+	RET
+
+
+// func divWVW(z* Word, xn Word, x []Word, y Word) (r Word)
+TEXT ·divWVW(SB),7,$0
+	MOVL z+0(FP), DI
+	MOVL xn+12(FP), DX	// r = xn
+	MOVL x+16(FP), SI
+	MOVL y+28(FP), CX
+	MOVL n+4(FP), BX	// i = n
+	JMP E7
+
+L7:	MOVL (SI)(BX*4), AX
+	DIVL CX
+	MOVL AX, (DI)(BX*4)
+
+E7:	SUBL $1, BX		// i--
+	JGE L7			// i >= 0
+
+	MOVL DX, r+32(FP)
+	RET
+
+// func bitLen(x Word) (n int)
+TEXT ·bitLen(SB),7,$0
+	BSRL x+0(FP), AX
+	JZ Z1
+	INCL AX
+	MOVL AX, n+4(FP)
+	RET
+
+Z1:	MOVL $0, n+4(FP)
+	RET
diff --git a/src/pkg/math/big/arith_amd64.s b/src/pkg/math/big/arith_amd64.s
new file mode 100644
index 0000000..54f6473
--- /dev/null
+++ b/src/pkg/math/big/arith_amd64.s
@@ -0,0 +1,274 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file provides fast assembly versions for the elementary
+// arithmetic operations on vectors implemented in arith.go.
+
+// TODO(gri) - experiment with unrolled loops for faster execution
+
+// func mulWW(x, y Word) (z1, z0 Word)
+TEXT ·mulWW(SB),7,$0
+	MOVQ x+0(FP), AX
+	MULQ y+8(FP)
+	MOVQ DX, z1+16(FP)
+	MOVQ AX, z0+24(FP)
+	RET
+
+
+// func divWW(x1, x0, y Word) (q, r Word)
+TEXT ·divWW(SB),7,$0
+	MOVQ x1+0(FP), DX
+	MOVQ x0+8(FP), AX
+	DIVQ y+16(FP)
+	MOVQ AX, q+24(FP)
+	MOVQ DX, r+32(FP)
+	RET
+
+
+// func addVV(z, x, y []Word) (c Word)
+TEXT ·addVV(SB),7,$0
+	MOVQ z+0(FP), R10
+	MOVQ x+16(FP), R8
+	MOVQ y+32(FP), R9
+	MOVL n+8(FP), R11
+	MOVQ $0, BX		// i = 0
+	MOVQ $0, DX		// c = 0
+	JMP E1
+
+L1:	MOVQ (R8)(BX*8), AX
+	RCRQ $1, DX
+	ADCQ (R9)(BX*8), AX
+	RCLQ $1, DX
+	MOVQ AX, (R10)(BX*8)
+	ADDL $1, BX		// i++
+
+E1:	CMPQ BX, R11		// i < n
+	JL L1
+
+	MOVQ DX, c+48(FP)
+	RET
+
+
+// func subVV(z, x, y []Word) (c Word)
+// (same as addVV_s except for SBBQ instead of ADCQ and label names)
+TEXT ·subVV(SB),7,$0
+	MOVQ z+0(FP), R10
+	MOVQ x+16(FP), R8
+	MOVQ y+32(FP), R9
+	MOVL n+8(FP), R11
+	MOVQ $0, BX		// i = 0
+	MOVQ $0, DX		// c = 0
+	JMP E2
+
+L2:	MOVQ (R8)(BX*8), AX
+	RCRQ $1, DX
+	SBBQ (R9)(BX*8), AX
+	RCLQ $1, DX
+	MOVQ AX, (R10)(BX*8)
+	ADDL $1, BX		// i++
+
+E2:	CMPQ BX, R11		// i < n
+	JL L2
+
+	MOVQ DX, c+48(FP)
+	RET
+
+
+// func addVW(z, x []Word, y Word) (c Word)
+TEXT ·addVW(SB),7,$0
+	MOVQ z+0(FP), R10
+	MOVQ x+16(FP), R8
+	MOVQ y+32(FP), AX	// c = y
+	MOVL n+8(FP), R11
+	MOVQ $0, BX		// i = 0
+	JMP E3
+
+L3:	ADDQ (R8)(BX*8), AX
+	MOVQ AX, (R10)(BX*8)
+	RCLQ $1, AX
+	ANDQ $1, AX
+	ADDL $1, BX		// i++
+
+E3:	CMPQ BX, R11		// i < n
+	JL L3
+
+	MOVQ AX, c+40(FP)
+	RET
+
+
+// func subVW(z, x []Word, y Word) (c Word)
+TEXT ·subVW(SB),7,$0
+	MOVQ z+0(FP), R10
+	MOVQ x+16(FP), R8
+	MOVQ y+32(FP), AX	// c = y
+	MOVL n+8(FP), R11
+	MOVQ $0, BX		// i = 0
+	JMP E4
+
+L4:	MOVQ (R8)(BX*8), DX	// TODO(gri) is there a reverse SUBQ?
+	SUBQ AX, DX
+	MOVQ DX, (R10)(BX*8)
+	RCLQ $1, AX
+	ANDQ $1, AX
+	ADDL $1, BX		// i++
+
+E4:	CMPQ BX, R11		// i < n
+	JL L4
+
+	MOVQ AX, c+40(FP)
+	RET
+
+
+// func shlVU(z, x []Word, s uint) (c Word)
+TEXT ·shlVU(SB),7,$0
+	MOVL n+8(FP), BX	// i = n
+	SUBL $1, BX		// i--
+	JL X8b			// i < 0	(n <= 0)
+
+	// n > 0
+	MOVQ z+0(FP), R10
+	MOVQ x+16(FP), R8
+	MOVL s+32(FP), CX
+	MOVQ (R8)(BX*8), AX	// w1 = x[n-1]
+	MOVQ $0, DX
+	SHLQ CX, DX:AX		// w1>>ŝ
+	MOVQ DX, c+40(FP)
+
+	CMPL BX, $0
+	JLE X8a			// i <= 0
+
+	// i > 0
+L8:	MOVQ AX, DX		// w = w1
+	MOVQ -8(R8)(BX*8), AX	// w1 = x[i-1]
+	SHLQ CX, DX:AX		// w<<s | w1>>ŝ
+	MOVQ DX, (R10)(BX*8)	// z[i] = w<<s | w1>>ŝ
+	SUBL $1, BX		// i--
+	JG L8			// i > 0
+
+	// i <= 0
+X8a:	SHLQ CX, AX		// w1<<s
+	MOVQ AX, (R10)		// z[0] = w1<<s
+	RET
+
+X8b:	MOVQ $0, c+40(FP)
+	RET
+
+
+// func shrVU(z, x []Word, s uint) (c Word)
+TEXT ·shrVU(SB),7,$0
+	MOVL n+8(FP), R11
+	SUBL $1, R11		// n--
+	JL X9b			// n < 0	(n <= 0)
+
+	// n > 0
+	MOVQ z+0(FP), R10
+	MOVQ x+16(FP), R8
+	MOVL s+32(FP), CX
+	MOVQ (R8), AX		// w1 = x[0]
+	MOVQ $0, DX
+	SHRQ CX, DX:AX		// w1<<ŝ
+	MOVQ DX, c+40(FP)
+
+	MOVQ $0, BX		// i = 0
+	JMP E9
+
+	// i < n-1
+L9:	MOVQ AX, DX		// w = w1
+	MOVQ 8(R8)(BX*8), AX	// w1 = x[i+1]
+	SHRQ CX, DX:AX		// w>>s | w1<<ŝ
+	MOVQ DX, (R10)(BX*8)	// z[i] = w>>s | w1<<ŝ
+	ADDL $1, BX		// i++
+	
+E9:	CMPQ BX, R11
+	JL L9			// i < n-1
+
+	// i >= n-1
+X9a:	SHRQ CX, AX		// w1>>s
+	MOVQ AX, (R10)(R11*8)	// z[n-1] = w1>>s
+	RET
+
+X9b:	MOVQ $0, c+40(FP)
+	RET
+
+
+// func mulAddVWW(z, x []Word, y, r Word) (c Word)
+TEXT ·mulAddVWW(SB),7,$0
+	MOVQ z+0(FP), R10
+	MOVQ x+16(FP), R8
+	MOVQ y+32(FP), R9
+	MOVQ r+40(FP), CX	// c = r
+	MOVL n+8(FP), R11
+	MOVQ $0, BX		// i = 0
+	JMP E5
+
+L5:	MOVQ (R8)(BX*8), AX
+	MULQ R9
+	ADDQ CX, AX
+	ADCQ $0, DX
+	MOVQ AX, (R10)(BX*8)
+	MOVQ DX, CX
+	ADDL $1, BX		// i++
+
+E5:	CMPQ BX, R11		// i < n
+	JL L5
+
+	MOVQ CX, c+48(FP)
+	RET
+
+
+// func addMulVVW(z, x []Word, y Word) (c Word)
+TEXT ·addMulVVW(SB),7,$0
+	MOVQ z+0(FP), R10
+	MOVQ x+16(FP), R8
+	MOVQ y+32(FP), R9
+	MOVL n+8(FP), R11
+	MOVQ $0, BX		// i = 0
+	MOVQ $0, CX		// c = 0
+	JMP E6
+
+L6:	MOVQ (R8)(BX*8), AX
+	MULQ R9
+	ADDQ CX, AX
+	ADCQ $0, DX
+	ADDQ AX, (R10)(BX*8)
+	ADCQ $0, DX
+	MOVQ DX, CX
+	ADDL $1, BX		// i++
+
+E6:	CMPQ BX, R11		// i < n
+	JL L6
+
+	MOVQ CX, c+40(FP)
+	RET
+
+
+// func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
+TEXT ·divWVW(SB),7,$0
+	MOVQ z+0(FP), R10
+	MOVQ xn+16(FP), DX	// r = xn
+	MOVQ x+24(FP), R8
+	MOVQ y+40(FP), R9
+	MOVL n+8(FP), BX	// i = n
+	JMP E7
+
+L7:	MOVQ (R8)(BX*8), AX
+	DIVQ R9
+	MOVQ AX, (R10)(BX*8)
+
+E7:	SUBL $1, BX		// i--
+	JGE L7			// i >= 0
+
+	MOVQ DX, r+48(FP)
+	RET
+
+// func bitLen(x Word) (n int)
+TEXT ·bitLen(SB),7,$0
+	BSRQ x+0(FP), AX
+	JZ Z1
+	INCL AX
+	MOVL AX, n+8(FP)
+	RET
+
+Z1:	MOVL $0, n+8(FP)
+	RET
diff --git a/src/pkg/math/big/arith_arm.s b/src/pkg/math/big/arith_arm.s
new file mode 100644
index 0000000..dbf3360
--- /dev/null
+++ b/src/pkg/math/big/arith_arm.s
@@ -0,0 +1,321 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file provides fast assembly versions for the elementary
+// arithmetic operations on vectors implemented in arith.go.
+
+#define CFLAG 29	// bit position of carry flag
+
+// func addVV(z, x, y []Word) (c Word)
+TEXT ·addVV(SB),7,$0
+	MOVW	$0, R0
+	MOVW	z+0(FP), R1
+	MOVW	x+12(FP), R2
+	MOVW	y+24(FP), R3
+	MOVW	n+4(FP), R4
+	MOVW	R4<<2, R4
+	ADD	R1, R4
+	B E1
+L1:
+	MOVW.P	4(R2), R5
+	MOVW.P	4(R3), R6
+	MOVW	R0, CPSR
+	ADC.S	R6, R5
+	MOVW.P	R5, 4(R1)
+	MOVW	CPSR, R0
+E1:
+	CMP	R1, R4
+	BNE L1
+
+	MOVW	R0>>CFLAG, R0
+	AND	$1, R0
+	MOVW	R0, c+36(FP)
+	RET
+
+
+// func subVV(z, x, y []Word) (c Word)
+// (same as addVV except for SBC instead of ADC and label names)
+TEXT ·subVV(SB),7,$0
+	MOVW	$(1<<CFLAG), R0
+	MOVW	z+0(FP), R1
+	MOVW	x+12(FP), R2
+	MOVW	y+24(FP), R3
+	MOVW	n+4(FP), R4
+	MOVW	R4<<2, R4
+	ADD	R1, R4
+	B E2
+L2:
+	MOVW.P	4(R2), R5
+	MOVW.P	4(R3), R6
+	MOVW	R0, CPSR
+	SBC.S	R6, R5
+	MOVW.P	R5, 4(R1)
+	MOVW	CPSR, R0
+E2:
+	CMP	R1, R4
+	BNE L2
+
+	MOVW	R0>>CFLAG, R0
+	AND	$1, R0
+	EOR	$1, R0
+	MOVW	R0, c+36(FP)
+	RET
+
+
+// func addVW(z, x []Word, y Word) (c Word)
+TEXT ·addVW(SB),7,$0
+	MOVW	z+0(FP), R1
+	MOVW	x+12(FP), R2
+	MOVW	y+24(FP), R3
+	MOVW	n+4(FP), R4
+	MOVW	R4<<2, R4
+	ADD	R1, R4
+	CMP	R1, R4
+	BNE L3a
+	MOVW	R3, c+28(FP)
+	RET
+L3a:
+	MOVW.P	4(R2), R5
+	ADD.S	R3, R5
+	MOVW.P	R5, 4(R1)
+	MOVW	CPSR, R0
+	B	E3
+L3:
+	MOVW.P	4(R2), R5
+	MOVW	R0, CPSR
+	ADC.S	$0, R5
+	MOVW.P	R5, 4(R1)
+	MOVW	CPSR, R0
+E3:
+	CMP	R1, R4
+	BNE	L3
+
+	MOVW	R0>>CFLAG, R0
+	AND	$1, R0
+	MOVW	R0, c+28(FP)
+	RET
+
+
+// func subVW(z, x []Word, y Word) (c Word)
+TEXT ·subVW(SB),7,$0
+	MOVW	z+0(FP), R1
+	MOVW	x+12(FP), R2
+	MOVW	y+24(FP), R3
+	MOVW	n+4(FP), R4
+	MOVW	R4<<2, R4
+	ADD	R1, R4
+	CMP	R1, R4
+	BNE L4a
+	MOVW	R3, c+28(FP)
+	RET
+L4a:
+	MOVW.P	4(R2), R5
+	SUB.S	R3, R5
+	MOVW.P	R5, 4(R1)
+	MOVW	CPSR, R0
+	B	E4
+L4:
+	MOVW.P	4(R2), R5
+	MOVW	R0, CPSR
+	SBC.S	$0, R5
+	MOVW.P	R5, 4(R1)
+	MOVW	CPSR, R0
+E4:
+	CMP	R1, R4
+	BNE	L4
+
+	MOVW	R0>>CFLAG, R0
+	AND	$1, R0
+	EOR	$1, R0
+	MOVW	R0, c+28(FP)
+	RET
+
+
+// func shlVU(z, x []Word, s uint) (c Word)
+TEXT ·shlVU(SB),7,$0
+	MOVW	n+4(FP), R5
+	CMP	$0, R5
+	BEQ	X7
+	
+	MOVW	z+0(FP), R1
+	MOVW	x+12(FP), R2
+	MOVW	R5<<2, R5
+	ADD	R5, R2
+	ADD	R1, R5
+	MOVW	s+24(FP), R3
+	CMP	$0, R3	// shift 0 is special
+	BEQ	Y7
+	ADD	$4, R1	// stop one word early
+	MOVW	$32, R4
+	SUB	R3, R4
+	MOVW	$0, R7
+	
+	MOVW.W	-4(R2), R6
+	MOVW	R6<<R3, R7
+	MOVW	R6>>R4, R6
+	MOVW	R6, c+28(FP)
+	B E7
+
+L7:
+	MOVW.W	-4(R2), R6
+	ORR	R6>>R4, R7
+	MOVW.W	R7, -4(R5)
+	MOVW	R6<<R3, R7
+E7:
+	CMP	R1, R5
+	BNE	L7
+
+	MOVW	R7, -4(R5)
+	RET
+
+Y7:	// copy loop, because shift 0 == shift 32
+	MOVW.W	-4(R2), R6
+	MOVW.W	R6, -4(R5)
+	CMP	R1, R5
+	BNE Y7
+
+X7:
+	MOVW	$0, R1
+	MOVW	R1, c+28(FP)
+	RET
+
+
+// func shrVU(z, x []Word, s uint) (c Word)
+TEXT ·shrVU(SB),7,$0
+	MOVW	n+4(FP), R5
+	CMP	$0, R5
+	BEQ	X6
+
+	MOVW	z+0(FP), R1
+	MOVW	x+12(FP), R2
+	MOVW	R5<<2, R5
+	ADD	R1, R5
+	MOVW	s+24(FP), R3
+	CMP	$0, R3	// shift 0 is special
+	BEQ Y6
+	SUB	$4, R5	// stop one word early
+	MOVW	$32, R4
+	SUB	R3, R4
+	MOVW	$0, R7
+
+	// first word
+	MOVW.P	4(R2), R6
+	MOVW	R6>>R3, R7
+	MOVW	R6<<R4, R6
+	MOVW	R6, c+28(FP)
+	B E6
+
+	// word loop
+L6:
+	MOVW.P	4(R2), R6
+	ORR	R6<<R4, R7
+	MOVW.P	R7, 4(R1)
+	MOVW	R6>>R3, R7
+E6:
+	CMP	R1, R5
+	BNE	L6
+
+	MOVW	R7, 0(R1)
+	RET
+
+Y6:	// copy loop, because shift 0 == shift 32
+	MOVW.P	4(R2), R6
+	MOVW.P	R6, 4(R1)
+	CMP R1, R5
+	BNE Y6
+
+X6:
+	MOVW	$0, R1
+	MOVW	R1, c+28(FP)
+	RET
+
+
+// func mulAddVWW(z, x []Word, y, r Word) (c Word)
+TEXT ·mulAddVWW(SB),7,$0
+	MOVW	$0, R0
+	MOVW	z+0(FP), R1
+	MOVW	x+12(FP), R2
+	MOVW	y+24(FP), R3
+	MOVW	r+28(FP), R4
+	MOVW	n+4(FP), R5
+	MOVW	R5<<2, R5
+	ADD	R1, R5
+	B E8
+
+	// word loop
+L8:
+	MOVW.P	4(R2), R6
+	MULLU	R6, R3, (R7, R6)
+	ADD.S	R4, R6
+	ADC	R0, R7
+	MOVW.P	R6, 4(R1)
+	MOVW	R7, R4
+E8:
+	CMP	R1, R5
+	BNE	L8
+
+	MOVW	R4, c+32(FP)
+	RET
+
+
+// func addMulVVW(z, x []Word, y Word) (c Word)
+TEXT ·addMulVVW(SB),7,$0
+	MOVW	$0, R0
+	MOVW	z+0(FP), R1
+	MOVW	x+12(FP), R2
+	MOVW	y+24(FP), R3
+	MOVW	n+4(FP), R5
+	MOVW	R5<<2, R5
+	ADD	R1, R5
+	MOVW	$0, R4
+	B E9
+
+	// word loop
+L9:
+	MOVW.P	4(R2), R6
+	MULLU	R6, R3, (R7, R6)
+	ADD.S	R4, R6
+	ADC	R0, R7
+	MOVW	0(R1), R4
+	ADD.S	R4, R6
+	ADC	R0, R7
+	MOVW.P	R6, 4(R1)
+	MOVW	R7, R4
+E9:
+	CMP	R1, R5
+	BNE	L9
+
+	MOVW	R4, c+28(FP)
+	RET
+
+
+// func divWVW(z* Word, xn Word, x []Word, y Word) (r Word)
+TEXT ·divWVW(SB),7,$0
+	// ARM has no multiword division, so use portable code.
+	B ·divWVW_g(SB)
+
+
+// func divWW(x1, x0, y Word) (q, r Word)
+TEXT ·divWW(SB),7,$0
+	// ARM has no multiword division, so use portable code.
+	B ·divWW_g(SB)
+
+
+// func mulWW(x, y Word) (z1, z0 Word)
+TEXT ·mulWW(SB),7,$0
+	MOVW	x+0(FP), R1
+	MOVW	y+4(FP), R2
+	MULLU	R1, R2, (R4, R3)
+	MOVW	R4, z1+8(FP)
+	MOVW	R3, z0+12(FP)
+	RET
+
+// func bitLen(x Word) (n int)
+TEXT ·bitLen(SB),7,$0
+	MOVW	x+0(FP), R0
+	WORD	$0xe16f0f10 // CLZ R0, R0  (count leading zeros)
+	MOVW	$32, R1
+	SUB.S	R0, R1
+	MOVW	R1, n+4(FP)
+	RET
diff --git a/src/pkg/math/big/arith_decl.go b/src/pkg/math/big/arith_decl.go
new file mode 100644
index 0000000..068cc8d
--- /dev/null
+++ b/src/pkg/math/big/arith_decl.go
@@ -0,0 +1,19 @@
+// Copyright 2010 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 big
+
+// implemented in arith_$GOARCH.s
+func mulWW(x, y Word) (z1, z0 Word)
+func divWW(x1, x0, y Word) (q, r Word)
+func addVV(z, x, y []Word) (c Word)
+func subVV(z, x, y []Word) (c Word)
+func addVW(z, x []Word, y Word) (c Word)
+func subVW(z, x []Word, y Word) (c Word)
+func shlVU(z, x []Word, s uint) (c Word)
+func shrVU(z, x []Word, s uint) (c Word)
+func mulAddVWW(z, x []Word, y, r Word) (c Word)
+func addMulVVW(z, x []Word, y Word) (c Word)
+func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
+func bitLen(x Word) (n int)
diff --git a/src/pkg/math/big/arith_test.go b/src/pkg/math/big/arith_test.go
new file mode 100644
index 0000000..c7e3d28
--- /dev/null
+++ b/src/pkg/math/big/arith_test.go
@@ -0,0 +1,372 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import "testing"
+
+type funWW func(x, y, c Word) (z1, z0 Word)
+type argWW struct {
+	x, y, c, z1, z0 Word
+}
+
+var sumWW = []argWW{
+	{0, 0, 0, 0, 0},
+	{0, 1, 0, 0, 1},
+	{0, 0, 1, 0, 1},
+	{0, 1, 1, 0, 2},
+	{12345, 67890, 0, 0, 80235},
+	{12345, 67890, 1, 0, 80236},
+	{_M, 1, 0, 1, 0},
+	{_M, 0, 1, 1, 0},
+	{_M, 1, 1, 1, 1},
+	{_M, _M, 0, 1, _M - 1},
+	{_M, _M, 1, 1, _M},
+}
+
+func testFunWW(t *testing.T, msg string, f funWW, a argWW) {
+	z1, z0 := f(a.x, a.y, a.c)
+	if z1 != a.z1 || z0 != a.z0 {
+		t.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg, a, z1, z0, a.z1, a.z0)
+	}
+}
+
+func TestFunWW(t *testing.T) {
+	for _, a := range sumWW {
+		arg := a
+		testFunWW(t, "addWW_g", addWW_g, arg)
+
+		arg = argWW{a.y, a.x, a.c, a.z1, a.z0}
+		testFunWW(t, "addWW_g symmetric", addWW_g, arg)
+
+		arg = argWW{a.z0, a.x, a.c, a.z1, a.y}
+		testFunWW(t, "subWW_g", subWW_g, arg)
+
+		arg = argWW{a.z0, a.y, a.c, a.z1, a.x}
+		testFunWW(t, "subWW_g symmetric", subWW_g, arg)
+	}
+}
+
+type funVV func(z, x, y []Word) (c Word)
+type argVV struct {
+	z, x, y nat
+	c       Word
+}
+
+var sumVV = []argVV{
+	{},
+	{nat{0}, nat{0}, nat{0}, 0},
+	{nat{1}, nat{1}, nat{0}, 0},
+	{nat{0}, nat{_M}, nat{1}, 1},
+	{nat{80235}, nat{12345}, nat{67890}, 0},
+	{nat{_M - 1}, nat{_M}, nat{_M}, 1},
+	{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, nat{1, 0, 0, 0}, 1},
+	{nat{0, 0, 0, _M}, nat{_M, _M, _M, _M - 1}, nat{1, 0, 0, 0}, 0},
+	{nat{0, 0, 0, 0}, nat{_M, 0, _M, 0}, nat{1, _M, 0, _M}, 1},
+}
+
+func testFunVV(t *testing.T, msg string, f funVV, a argVV) {
+	z := make(nat, len(a.z))
+	c := f(z, a.x, a.y)
+	for i, zi := range z {
+		if zi != a.z[i] {
+			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
+			break
+		}
+	}
+	if c != a.c {
+		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
+	}
+}
+
+func TestFunVV(t *testing.T) {
+	for _, a := range sumVV {
+		arg := a
+		testFunVV(t, "addVV_g", addVV_g, arg)
+		testFunVV(t, "addVV", addVV, arg)
+
+		arg = argVV{a.z, a.y, a.x, a.c}
+		testFunVV(t, "addVV_g symmetric", addVV_g, arg)
+		testFunVV(t, "addVV symmetric", addVV, arg)
+
+		arg = argVV{a.x, a.z, a.y, a.c}
+		testFunVV(t, "subVV_g", subVV_g, arg)
+		testFunVV(t, "subVV", subVV, arg)
+
+		arg = argVV{a.y, a.z, a.x, a.c}
+		testFunVV(t, "subVV_g symmetric", subVV_g, arg)
+		testFunVV(t, "subVV symmetric", subVV, arg)
+	}
+}
+
+type funVW func(z, x []Word, y Word) (c Word)
+type argVW struct {
+	z, x nat
+	y    Word
+	c    Word
+}
+
+var sumVW = []argVW{
+	{},
+	{nil, nil, 2, 2},
+	{nat{0}, nat{0}, 0, 0},
+	{nat{1}, nat{0}, 1, 0},
+	{nat{1}, nat{1}, 0, 0},
+	{nat{0}, nat{_M}, 1, 1},
+	{nat{0, 0, 0, 0}, nat{_M, _M, _M, _M}, 1, 1},
+}
+
+var prodVW = []argVW{
+	{},
+	{nat{0}, nat{0}, 0, 0},
+	{nat{0}, nat{_M}, 0, 0},
+	{nat{0}, nat{0}, _M, 0},
+	{nat{1}, nat{1}, 1, 0},
+	{nat{22793}, nat{991}, 23, 0},
+	{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0},
+	{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0},
+	{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0},
+	{nat{_M << 1 & _M}, nat{_M}, 1 << 1, _M >> (_W - 1)},
+	{nat{_M << 7 & _M}, nat{_M}, 1 << 7, _M >> (_W - 7)},
+	{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, _M >> (_W - 7)},
+}
+
+var lshVW = []argVW{
+	{},
+	{nat{0}, nat{0}, 0, 0},
+	{nat{0}, nat{0}, 1, 0},
+	{nat{0}, nat{0}, 20, 0},
+
+	{nat{_M}, nat{_M}, 0, 0},
+	{nat{_M << 1 & _M}, nat{_M}, 1, 1},
+	{nat{_M << 20 & _M}, nat{_M}, 20, _M >> (_W - 20)},
+
+	{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
+	{nat{_M << 1 & _M, _M, _M}, nat{_M, _M, _M}, 1, 1},
+	{nat{_M << 20 & _M, _M, _M}, nat{_M, _M, _M}, 20, _M >> (_W - 20)},
+}
+
+var rshVW = []argVW{
+	{},
+	{nat{0}, nat{0}, 0, 0},
+	{nat{0}, nat{0}, 1, 0},
+	{nat{0}, nat{0}, 20, 0},
+
+	{nat{_M}, nat{_M}, 0, 0},
+	{nat{_M >> 1}, nat{_M}, 1, _M << (_W - 1) & _M},
+	{nat{_M >> 20}, nat{_M}, 20, _M << (_W - 20) & _M},
+
+	{nat{_M, _M, _M}, nat{_M, _M, _M}, 0, 0},
+	{nat{_M, _M, _M >> 1}, nat{_M, _M, _M}, 1, _M << (_W - 1) & _M},
+	{nat{_M, _M, _M >> 20}, nat{_M, _M, _M}, 20, _M << (_W - 20) & _M},
+}
+
+func testFunVW(t *testing.T, msg string, f funVW, a argVW) {
+	z := make(nat, len(a.z))
+	c := f(z, a.x, a.y)
+	for i, zi := range z {
+		if zi != a.z[i] {
+			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
+			break
+		}
+	}
+	if c != a.c {
+		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
+	}
+}
+
+func makeFunVW(f func(z, x []Word, s uint) (c Word)) funVW {
+	return func(z, x []Word, s Word) (c Word) {
+		return f(z, x, uint(s))
+	}
+}
+
+func TestFunVW(t *testing.T) {
+	for _, a := range sumVW {
+		arg := a
+		testFunVW(t, "addVW_g", addVW_g, arg)
+		testFunVW(t, "addVW", addVW, arg)
+
+		arg = argVW{a.x, a.z, a.y, a.c}
+		testFunVW(t, "subVW_g", subVW_g, arg)
+		testFunVW(t, "subVW", subVW, arg)
+	}
+
+	shlVW_g := makeFunVW(shlVU_g)
+	shlVW := makeFunVW(shlVU)
+	for _, a := range lshVW {
+		arg := a
+		testFunVW(t, "shlVU_g", shlVW_g, arg)
+		testFunVW(t, "shlVU", shlVW, arg)
+	}
+
+	shrVW_g := makeFunVW(shrVU_g)
+	shrVW := makeFunVW(shrVU)
+	for _, a := range rshVW {
+		arg := a
+		testFunVW(t, "shrVU_g", shrVW_g, arg)
+		testFunVW(t, "shrVU", shrVW, arg)
+	}
+}
+
+type funVWW func(z, x []Word, y, r Word) (c Word)
+type argVWW struct {
+	z, x nat
+	y, r Word
+	c    Word
+}
+
+var prodVWW = []argVWW{
+	{},
+	{nat{0}, nat{0}, 0, 0, 0},
+	{nat{991}, nat{0}, 0, 991, 0},
+	{nat{0}, nat{_M}, 0, 0, 0},
+	{nat{991}, nat{_M}, 0, 991, 0},
+	{nat{0}, nat{0}, _M, 0, 0},
+	{nat{991}, nat{0}, _M, 991, 0},
+	{nat{1}, nat{1}, 1, 0, 0},
+	{nat{992}, nat{1}, 1, 991, 0},
+	{nat{22793}, nat{991}, 23, 0, 0},
+	{nat{22800}, nat{991}, 23, 7, 0},
+	{nat{0, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 0, 0},
+	{nat{7, 0, 0, 22793}, nat{0, 0, 0, 991}, 23, 7, 0},
+	{nat{0, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 0, 0},
+	{nat{991, 0, 0, 0}, nat{7893475, 7395495, 798547395, 68943}, 0, 991, 0},
+	{nat{0, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 0, 0},
+	{nat{991, 0, 0, 0}, nat{0, 0, 0, 0}, 894375984, 991, 0},
+	{nat{_M << 1 & _M}, nat{_M}, 1 << 1, 0, _M >> (_W - 1)},
+	{nat{_M<<1&_M + 1}, nat{_M}, 1 << 1, 1, _M >> (_W - 1)},
+	{nat{_M << 7 & _M}, nat{_M}, 1 << 7, 0, _M >> (_W - 7)},
+	{nat{_M<<7&_M + 1<<6}, nat{_M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
+	{nat{_M << 7 & _M, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 0, _M >> (_W - 7)},
+	{nat{_M<<7&_M + 1<<6, _M, _M, _M}, nat{_M, _M, _M, _M}, 1 << 7, 1 << 6, _M >> (_W - 7)},
+}
+
+func testFunVWW(t *testing.T, msg string, f funVWW, a argVWW) {
+	z := make(nat, len(a.z))
+	c := f(z, a.x, a.y, a.r)
+	for i, zi := range z {
+		if zi != a.z[i] {
+			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
+			break
+		}
+	}
+	if c != a.c {
+		t.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg, a, c, a.c)
+	}
+}
+
+// TODO(gri) mulAddVWW and divWVW are symmetric operations but
+//           their signature is not symmetric. Try to unify.
+
+type funWVW func(z []Word, xn Word, x []Word, y Word) (r Word)
+type argWVW struct {
+	z  nat
+	xn Word
+	x  nat
+	y  Word
+	r  Word
+}
+
+func testFunWVW(t *testing.T, msg string, f funWVW, a argWVW) {
+	z := make(nat, len(a.z))
+	r := f(z, a.xn, a.x, a.y)
+	for i, zi := range z {
+		if zi != a.z[i] {
+			t.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg, a, i, zi, a.z[i])
+			break
+		}
+	}
+	if r != a.r {
+		t.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg, a, r, a.r)
+	}
+}
+
+func TestFunVWW(t *testing.T) {
+	for _, a := range prodVWW {
+		arg := a
+		testFunVWW(t, "mulAddVWW_g", mulAddVWW_g, arg)
+		testFunVWW(t, "mulAddVWW", mulAddVWW, arg)
+
+		if a.y != 0 && a.r < a.y {
+			arg := argWVW{a.x, a.c, a.z, a.y, a.r}
+			testFunWVW(t, "divWVW_g", divWVW_g, arg)
+			testFunWVW(t, "divWVW", divWVW, arg)
+		}
+	}
+}
+
+var mulWWTests = []struct {
+	x, y Word
+	q, r Word
+}{
+	{_M, _M, _M - 1, 1},
+	// 32 bit only: {0xc47dfa8c, 50911, 0x98a4, 0x998587f4},
+}
+
+func TestMulWW(t *testing.T) {
+	for i, test := range mulWWTests {
+		q, r := mulWW_g(test.x, test.y)
+		if q != test.q || r != test.r {
+			t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
+		}
+	}
+}
+
+var mulAddWWWTests = []struct {
+	x, y, c Word
+	q, r    Word
+}{
+	// TODO(agl): These will only work on 64-bit platforms.
+	// {15064310297182388543, 0xe7df04d2d35d5d80, 13537600649892366549, 13644450054494335067, 10832252001440893781},
+	// {15064310297182388543, 0xdab2f18048baa68d, 13644450054494335067, 12869334219691522700, 14233854684711418382},
+	{_M, _M, 0, _M - 1, 1},
+	{_M, _M, _M, _M, 0},
+}
+
+func TestMulAddWWW(t *testing.T) {
+	for i, test := range mulAddWWWTests {
+		q, r := mulAddWWW_g(test.x, test.y, test.c)
+		if q != test.q || r != test.r {
+			t.Errorf("#%d got (%x, %x) want (%x, %x)", i, q, r, test.q, test.r)
+		}
+	}
+}
+
+func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
+	for i := 0; i <= _W; i++ {
+		x := Word(1) << uint(i-1) // i == 0 => x == 0
+		n := f(x)
+		if n != i {
+			t.Errorf("got %d; want %d for %s(%#x)", n, i, fname, x)
+		}
+	}
+}
+
+func TestWordBitLen(t *testing.T) {
+	testWordBitLen(t, "bitLen", bitLen)
+	testWordBitLen(t, "bitLen_g", bitLen_g)
+}
+
+// runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1.
+func benchmarkBitLenN(b *testing.B, nbits uint) {
+	testword := Word((uint64(1) << nbits) - 1)
+	for i := 0; i < b.N; i++ {
+		bitLen(testword)
+	}
+}
+
+// Individual bitLen tests.  Numbers chosen to examine both sides
+// of powers-of-two boundaries.
+func BenchmarkBitLen0(b *testing.B)  { benchmarkBitLenN(b, 0) }
+func BenchmarkBitLen1(b *testing.B)  { benchmarkBitLenN(b, 1) }
+func BenchmarkBitLen2(b *testing.B)  { benchmarkBitLenN(b, 2) }
+func BenchmarkBitLen3(b *testing.B)  { benchmarkBitLenN(b, 3) }
+func BenchmarkBitLen4(b *testing.B)  { benchmarkBitLenN(b, 4) }
+func BenchmarkBitLen5(b *testing.B)  { benchmarkBitLenN(b, 5) }
+func BenchmarkBitLen8(b *testing.B)  { benchmarkBitLenN(b, 8) }
+func BenchmarkBitLen9(b *testing.B)  { benchmarkBitLenN(b, 9) }
+func BenchmarkBitLen16(b *testing.B) { benchmarkBitLenN(b, 16) }
+func BenchmarkBitLen17(b *testing.B) { benchmarkBitLenN(b, 17) }
+func BenchmarkBitLen31(b *testing.B) { benchmarkBitLenN(b, 31) }
diff --git a/src/pkg/math/big/calibrate_test.go b/src/pkg/math/big/calibrate_test.go
new file mode 100644
index 0000000..0950eee
--- /dev/null
+++ b/src/pkg/math/big/calibrate_test.go
@@ -0,0 +1,88 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file prints execution times for the Mul benchmark
+// given different Karatsuba thresholds. The result may be
+// used to manually fine-tune the threshold constant. The
+// results are somewhat fragile; use repeated runs to get
+// a clear picture.
+
+// Usage: gotest -calibrate
+
+package big
+
+import (
+	"flag"
+	"fmt"
+	"testing"
+	"time"
+)
+
+var calibrate = flag.Bool("calibrate", false, "run calibration test")
+
+// measure returns the time to run f
+func measure(f func()) time.Duration {
+	const N = 100
+	start := time.Now()
+	for i := N; i > 0; i-- {
+		f()
+	}
+	stop := time.Now()
+	return stop.Sub(start) / N
+}
+
+func computeThresholds() {
+	fmt.Printf("Multiplication times for varying Karatsuba thresholds\n")
+	fmt.Printf("(run repeatedly for good results)\n")
+
+	// determine Tk, the work load execution time using basic multiplication
+	karatsubaThreshold = 1e9 // disable karatsuba
+	Tb := measure(benchmarkMulLoad)
+	fmt.Printf("Tb = %dns\n", Tb)
+
+	// thresholds
+	n := 8 // any lower values for the threshold lead to very slow multiplies
+	th1 := -1
+	th2 := -1
+
+	var deltaOld time.Duration
+	for count := -1; count != 0; count-- {
+		// determine Tk, the work load execution time using Karatsuba multiplication
+		karatsubaThreshold = n // enable karatsuba
+		Tk := measure(benchmarkMulLoad)
+
+		// improvement over Tb
+		delta := (Tb - Tk) * 100 / Tb
+
+		fmt.Printf("n = %3d  Tk = %8dns  %4d%%", n, Tk, delta)
+
+		// determine break-even point
+		if Tk < Tb && th1 < 0 {
+			th1 = n
+			fmt.Print("  break-even point")
+		}
+
+		// determine diminishing return
+		if 0 < delta && delta < deltaOld && th2 < 0 {
+			th2 = n
+			fmt.Print("  diminishing return")
+		}
+		deltaOld = delta
+
+		fmt.Println()
+
+		// trigger counter
+		if th1 >= 0 && th2 >= 0 && count < 0 {
+			count = 20 // this many extra measurements after we got both thresholds
+		}
+
+		n++
+	}
+}
+
+func TestCalibrate(t *testing.T) {
+	if *calibrate {
+		computeThresholds()
+	}
+}
diff --git a/src/pkg/math/big/example_test.go b/src/pkg/math/big/example_test.go
new file mode 100644
index 0000000..ba676ec
--- /dev/null
+++ b/src/pkg/math/big/example_test.go
@@ -0,0 +1,51 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big_test
+
+import (
+	"fmt"
+	"log"
+	"math/big"
+)
+
+// 3.142
+func ExampleRat_SetString() {
+	r := new(big.Rat)
+	r.SetString("355/113")
+	fmt.Println(r.FloatString(3))
+}
+
+// 420
+func ExampleInt_SetString() {
+	i := new(big.Int)
+	i.SetString("644", 8) // octal
+	fmt.Println(i)
+}
+
+// 3/2
+func ExampleRat_Scan() {
+	// The Scan function is rarely used directly;
+	// the fmt package recognizes it as an implementation of fmt.Scanner.
+	r := new(big.Rat)
+	_, err := fmt.Sscan("1.5000", r)
+	if err != nil {
+		log.Println("error scanning value:", err)
+	} else {
+		fmt.Println(r)
+	}
+}
+
+// 18446744073709551617
+func ExampleInt_Scan() {
+	// The Scan function is rarely used directly;
+	// the fmt package recognizes it as an implementation of fmt.Scanner.
+	i := new(big.Int)
+	_, err := fmt.Sscan("18446744073709551617", i)
+	if err != nil {
+		log.Println("error scanning value:", err)
+	} else {
+		fmt.Println(i)
+	}
+}
diff --git a/src/pkg/big/hilbert_test.go b/src/pkg/math/big/hilbert_test.go
similarity index 100%
rename from src/pkg/big/hilbert_test.go
rename to src/pkg/math/big/hilbert_test.go
diff --git a/src/pkg/math/big/int.go b/src/pkg/math/big/int.go
new file mode 100644
index 0000000..35e2e29
--- /dev/null
+++ b/src/pkg/math/big/int.go
@@ -0,0 +1,873 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements signed multi-precision integers.
+
+package big
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"math/rand"
+	"strings"
+)
+
+// An Int represents a signed multi-precision integer.
+// The zero value for an Int represents the value 0.
+type Int struct {
+	neg bool // sign
+	abs nat  // absolute value of the integer
+}
+
+var intOne = &Int{false, natOne}
+
+// Sign returns:
+//
+//	-1 if x <  0
+//	 0 if x == 0
+//	+1 if x >  0
+//
+func (x *Int) Sign() int {
+	if len(x.abs) == 0 {
+		return 0
+	}
+	if x.neg {
+		return -1
+	}
+	return 1
+}
+
+// SetInt64 sets z to x and returns z.
+func (z *Int) SetInt64(x int64) *Int {
+	neg := false
+	if x < 0 {
+		neg = true
+		x = -x
+	}
+	z.abs = z.abs.setUint64(uint64(x))
+	z.neg = neg
+	return z
+}
+
+// NewInt allocates and returns a new Int set to x.
+func NewInt(x int64) *Int {
+	return new(Int).SetInt64(x)
+}
+
+// Set sets z to x and returns z.
+func (z *Int) Set(x *Int) *Int {
+	if z != x {
+		z.abs = z.abs.set(x.abs)
+		z.neg = x.neg
+	}
+	return z
+}
+
+// Abs sets z to |x| (the absolute value of x) and returns z.
+func (z *Int) Abs(x *Int) *Int {
+	z.Set(x)
+	z.neg = false
+	return z
+}
+
+// Neg sets z to -x and returns z.
+func (z *Int) Neg(x *Int) *Int {
+	z.Set(x)
+	z.neg = len(z.abs) > 0 && !z.neg // 0 has no sign
+	return z
+}
+
+// Add sets z to the sum x+y and returns z.
+func (z *Int) Add(x, y *Int) *Int {
+	neg := x.neg
+	if x.neg == y.neg {
+		// x + y == x + y
+		// (-x) + (-y) == -(x + y)
+		z.abs = z.abs.add(x.abs, y.abs)
+	} else {
+		// x + (-y) == x - y == -(y - x)
+		// (-x) + y == y - x == -(x - y)
+		if x.abs.cmp(y.abs) >= 0 {
+			z.abs = z.abs.sub(x.abs, y.abs)
+		} else {
+			neg = !neg
+			z.abs = z.abs.sub(y.abs, x.abs)
+		}
+	}
+	z.neg = len(z.abs) > 0 && neg // 0 has no sign
+	return z
+}
+
+// Sub sets z to the difference x-y and returns z.
+func (z *Int) Sub(x, y *Int) *Int {
+	neg := x.neg
+	if x.neg != y.neg {
+		// x - (-y) == x + y
+		// (-x) - y == -(x + y)
+		z.abs = z.abs.add(x.abs, y.abs)
+	} else {
+		// x - y == x - y == -(y - x)
+		// (-x) - (-y) == y - x == -(x - y)
+		if x.abs.cmp(y.abs) >= 0 {
+			z.abs = z.abs.sub(x.abs, y.abs)
+		} else {
+			neg = !neg
+			z.abs = z.abs.sub(y.abs, x.abs)
+		}
+	}
+	z.neg = len(z.abs) > 0 && neg // 0 has no sign
+	return z
+}
+
+// Mul sets z to the product x*y and returns z.
+func (z *Int) Mul(x, y *Int) *Int {
+	// x * y == x * y
+	// x * (-y) == -(x * y)
+	// (-x) * y == -(x * y)
+	// (-x) * (-y) == x * y
+	z.abs = z.abs.mul(x.abs, y.abs)
+	z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
+	return z
+}
+
+// MulRange sets z to the product of all integers
+// in the range [a, b] inclusively and returns z.
+// If a > b (empty range), the result is 1.
+func (z *Int) MulRange(a, b int64) *Int {
+	switch {
+	case a > b:
+		return z.SetInt64(1) // empty range
+	case a <= 0 && b >= 0:
+		return z.SetInt64(0) // range includes 0
+	}
+	// a <= b && (b < 0 || a > 0)
+
+	neg := false
+	if a < 0 {
+		neg = (b-a)&1 == 0
+		a, b = -b, -a
+	}
+
+	z.abs = z.abs.mulRange(uint64(a), uint64(b))
+	z.neg = neg
+	return z
+}
+
+// Binomial sets z to the binomial coefficient of (n, k) and returns z.
+func (z *Int) Binomial(n, k int64) *Int {
+	var a, b Int
+	a.MulRange(n-k+1, n)
+	b.MulRange(1, k)
+	return z.Quo(&a, &b)
+}
+
+// Quo sets z to the quotient x/y for y != 0 and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+// Quo implements truncated division (like Go); see QuoRem for more details.
+func (z *Int) Quo(x, y *Int) *Int {
+	z.abs, _ = z.abs.div(nil, x.abs, y.abs)
+	z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
+	return z
+}
+
+// Rem sets z to the remainder x%y for y != 0 and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+// Rem implements truncated modulus (like Go); see QuoRem for more details.
+func (z *Int) Rem(x, y *Int) *Int {
+	_, z.abs = nat(nil).div(z.abs, x.abs, y.abs)
+	z.neg = len(z.abs) > 0 && x.neg // 0 has no sign
+	return z
+}
+
+// QuoRem sets z to the quotient x/y and r to the remainder x%y
+// and returns the pair (z, r) for y != 0.
+// If y == 0, a division-by-zero run-time panic occurs.
+//
+// QuoRem implements T-division and modulus (like Go):
+//
+//	q = x/y      with the result truncated to zero
+//	r = x - y*q
+//
+// (See Daan Leijen, ``Division and Modulus for Computer Scientists''.)
+//
+func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) {
+	z.abs, r.abs = z.abs.div(r.abs, x.abs, y.abs)
+	z.neg, r.neg = len(z.abs) > 0 && x.neg != y.neg, len(r.abs) > 0 && x.neg // 0 has no sign
+	return z, r
+}
+
+// Div sets z to the quotient x/y for y != 0 and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+// Div implements Euclidean division (unlike Go); see DivMod for more details.
+func (z *Int) Div(x, y *Int) *Int {
+	y_neg := y.neg // z may be an alias for y
+	var r Int
+	z.QuoRem(x, y, &r)
+	if r.neg {
+		if y_neg {
+			z.Add(z, intOne)
+		} else {
+			z.Sub(z, intOne)
+		}
+	}
+	return z
+}
+
+// Mod sets z to the modulus x%y for y != 0 and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+// Mod implements Euclidean modulus (unlike Go); see DivMod for more details.
+func (z *Int) Mod(x, y *Int) *Int {
+	y0 := y // save y
+	if z == y || alias(z.abs, y.abs) {
+		y0 = new(Int).Set(y)
+	}
+	var q Int
+	q.QuoRem(x, y, z)
+	if z.neg {
+		if y0.neg {
+			z.Sub(z, y0)
+		} else {
+			z.Add(z, y0)
+		}
+	}
+	return z
+}
+
+// DivMod sets z to the quotient x div y and m to the modulus x mod y
+// and returns the pair (z, m) for y != 0.
+// If y == 0, a division-by-zero run-time panic occurs.
+//
+// DivMod implements Euclidean division and modulus (unlike Go):
+//
+//	q = x div y  such that
+//	m = x - y*q  with 0 <= m < |q|
+//
+// (See Raymond T. Boute, ``The Euclidean definition of the functions
+// div and mod''. ACM Transactions on Programming Languages and
+// Systems (TOPLAS), 14(2):127-144, New York, NY, USA, 4/1992.
+// ACM press.)
+//
+func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) {
+	y0 := y // save y
+	if z == y || alias(z.abs, y.abs) {
+		y0 = new(Int).Set(y)
+	}
+	z.QuoRem(x, y, m)
+	if m.neg {
+		if y0.neg {
+			z.Add(z, intOne)
+			m.Sub(m, y0)
+		} else {
+			z.Sub(z, intOne)
+			m.Add(m, y0)
+		}
+	}
+	return z, m
+}
+
+// Cmp compares x and y and returns:
+//
+//   -1 if x <  y
+//    0 if x == y
+//   +1 if x >  y
+//
+func (x *Int) Cmp(y *Int) (r int) {
+	// x cmp y == x cmp y
+	// x cmp (-y) == x
+	// (-x) cmp y == y
+	// (-x) cmp (-y) == -(x cmp y)
+	switch {
+	case x.neg == y.neg:
+		r = x.abs.cmp(y.abs)
+		if x.neg {
+			r = -r
+		}
+	case x.neg:
+		r = -1
+	default:
+		r = 1
+	}
+	return
+}
+
+func (x *Int) String() string {
+	switch {
+	case x == nil:
+		return "<nil>"
+	case x.neg:
+		return "-" + x.abs.decimalString()
+	}
+	return x.abs.decimalString()
+}
+
+func charset(ch rune) string {
+	switch ch {
+	case 'b':
+		return lowercaseDigits[0:2]
+	case 'o':
+		return lowercaseDigits[0:8]
+	case 'd', 's', 'v':
+		return lowercaseDigits[0:10]
+	case 'x':
+		return lowercaseDigits[0:16]
+	case 'X':
+		return uppercaseDigits[0:16]
+	}
+	return "" // unknown format
+}
+
+// write count copies of text to s
+func writeMultiple(s fmt.State, text string, count int) {
+	if len(text) > 0 {
+		b := []byte(text)
+		for ; count > 0; count-- {
+			s.Write(b)
+		}
+	}
+}
+
+// Format is a support routine for fmt.Formatter. It accepts
+// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
+// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+// Also supported are the full suite of package fmt's format
+// verbs for integral types, including '+', '-', and ' '
+// for sign control, '#' for leading zero in octal and for
+// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
+// respectively, specification of minimum digits precision,
+// output field width, space or zero padding, and left or
+// right justification.
+//
+func (x *Int) Format(s fmt.State, ch rune) {
+	cs := charset(ch)
+
+	// special cases
+	switch {
+	case cs == "":
+		// unknown format
+		fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
+		return
+	case x == nil:
+		fmt.Fprint(s, "<nil>")
+		return
+	}
+
+	// determine sign character
+	sign := ""
+	switch {
+	case x.neg:
+		sign = "-"
+	case s.Flag('+'): // supersedes ' ' when both specified
+		sign = "+"
+	case s.Flag(' '):
+		sign = " "
+	}
+
+	// determine prefix characters for indicating output base
+	prefix := ""
+	if s.Flag('#') {
+		switch ch {
+		case 'o': // octal
+			prefix = "0"
+		case 'x': // hexadecimal
+			prefix = "0x"
+		case 'X':
+			prefix = "0X"
+		}
+	}
+
+	// determine digits with base set by len(cs) and digit characters from cs
+	digits := x.abs.string(cs)
+
+	// number of characters for the three classes of number padding
+	var left int   // space characters to left of digits for right justification ("%8d")
+	var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
+	var right int  // space characters to right of digits for left justification ("%-8d")
+
+	// determine number padding from precision: the least number of digits to output
+	precision, precisionSet := s.Precision()
+	if precisionSet {
+		switch {
+		case len(digits) < precision:
+			zeroes = precision - len(digits) // count of zero padding 
+		case digits == "0" && precision == 0:
+			return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
+		}
+	}
+
+	// determine field pad from width: the least number of characters to output
+	length := len(sign) + len(prefix) + zeroes + len(digits)
+	if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
+		switch d := width - length; {
+		case s.Flag('-'):
+			// pad on the right with spaces; supersedes '0' when both specified
+			right = d
+		case s.Flag('0') && !precisionSet:
+			// pad with zeroes unless precision also specified
+			zeroes = d
+		default:
+			// pad on the left with spaces
+			left = d
+		}
+	}
+
+	// print number as [left pad][sign][prefix][zero pad][digits][right pad]
+	writeMultiple(s, " ", left)
+	writeMultiple(s, sign, 1)
+	writeMultiple(s, prefix, 1)
+	writeMultiple(s, "0", zeroes)
+	writeMultiple(s, digits, 1)
+	writeMultiple(s, " ", right)
+}
+
+// scan sets z to the integer value corresponding to the longest possible prefix
+// read from r representing a signed integer number in a given conversion base.
+// It returns z, the actual conversion base used, and an error, if any. In the
+// error case, the value of z is undefined but the returned value is nil. The
+// syntax follows the syntax of integer literals in Go.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, error) {
+	// determine sign
+	ch, _, err := r.ReadRune()
+	if err != nil {
+		return nil, 0, err
+	}
+	neg := false
+	switch ch {
+	case '-':
+		neg = true
+	case '+': // nothing to do
+	default:
+		r.UnreadRune()
+	}
+
+	// determine mantissa
+	z.abs, base, err = z.abs.scan(r, base)
+	if err != nil {
+		return nil, base, err
+	}
+	z.neg = len(z.abs) > 0 && neg // 0 has no sign
+
+	return z, base, nil
+}
+
+// Scan is a support routine for fmt.Scanner; it sets z to the value of
+// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
+// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+func (z *Int) Scan(s fmt.ScanState, ch rune) error {
+	s.SkipSpace() // skip leading space characters
+	base := 0
+	switch ch {
+	case 'b':
+		base = 2
+	case 'o':
+		base = 8
+	case 'd':
+		base = 10
+	case 'x', 'X':
+		base = 16
+	case 's', 'v':
+		// let scan determine the base
+	default:
+		return errors.New("Int.Scan: invalid verb")
+	}
+	_, _, err := z.scan(s, base)
+	return err
+}
+
+// Int64 returns the int64 representation of x.
+// If x cannot be represented in an int64, the result is undefined.
+func (x *Int) Int64() int64 {
+	if len(x.abs) == 0 {
+		return 0
+	}
+	v := int64(x.abs[0])
+	if _W == 32 && len(x.abs) > 1 {
+		v |= int64(x.abs[1]) << 32
+	}
+	if x.neg {
+		v = -v
+	}
+	return v
+}
+
+// SetString sets z to the value of s, interpreted in the given base,
+// and returns z and a boolean indicating success. If SetString fails,
+// the value of z is undefined but the returned value is nil.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z *Int) SetString(s string, base int) (*Int, bool) {
+	r := strings.NewReader(s)
+	_, _, err := z.scan(r, base)
+	if err != nil {
+		return nil, false
+	}
+	_, _, err = r.ReadRune()
+	if err != io.EOF {
+		return nil, false
+	}
+	return z, true // err == io.EOF => scan consumed all of s
+}
+
+// SetBytes interprets buf as the bytes of a big-endian unsigned
+// integer, sets z to that value, and returns z.
+func (z *Int) SetBytes(buf []byte) *Int {
+	z.abs = z.abs.setBytes(buf)
+	z.neg = false
+	return z
+}
+
+// Bytes returns the absolute value of z as a big-endian byte slice.
+func (z *Int) Bytes() []byte {
+	buf := make([]byte, len(z.abs)*_S)
+	return buf[z.abs.bytes(buf):]
+}
+
+// BitLen returns the length of the absolute value of z in bits.
+// The bit length of 0 is 0.
+func (z *Int) BitLen() int {
+	return z.abs.bitLen()
+}
+
+// Exp sets z = x**y mod m. If m is nil, z = x**y.
+// See Knuth, volume 2, section 4.6.3.
+func (z *Int) Exp(x, y, m *Int) *Int {
+	if y.neg || len(y.abs) == 0 {
+		neg := x.neg
+		z.SetInt64(1)
+		z.neg = neg
+		return z
+	}
+
+	var mWords nat
+	if m != nil {
+		mWords = m.abs
+	}
+
+	z.abs = z.abs.expNN(x.abs, y.abs, mWords)
+	z.neg = len(z.abs) > 0 && x.neg && y.abs[0]&1 == 1 // 0 has no sign
+	return z
+}
+
+// GcdInt sets d to the greatest common divisor of a and b, which must be
+// positive numbers.
+// If x and y are not nil, GcdInt sets x and y such that d = a*x + b*y.
+// If either a or b is not positive, GcdInt sets d = x = y = 0.
+func GcdInt(d, x, y, a, b *Int) {
+	if a.neg || b.neg {
+		d.SetInt64(0)
+		if x != nil {
+			x.SetInt64(0)
+		}
+		if y != nil {
+			y.SetInt64(0)
+		}
+		return
+	}
+
+	A := new(Int).Set(a)
+	B := new(Int).Set(b)
+
+	X := new(Int)
+	Y := new(Int).SetInt64(1)
+
+	lastX := new(Int).SetInt64(1)
+	lastY := new(Int)
+
+	q := new(Int)
+	temp := new(Int)
+
+	for len(B.abs) > 0 {
+		r := new(Int)
+		q, r = q.QuoRem(A, B, r)
+
+		A, B = B, r
+
+		temp.Set(X)
+		X.Mul(X, q)
+		X.neg = !X.neg
+		X.Add(X, lastX)
+		lastX.Set(temp)
+
+		temp.Set(Y)
+		Y.Mul(Y, q)
+		Y.neg = !Y.neg
+		Y.Add(Y, lastY)
+		lastY.Set(temp)
+	}
+
+	if x != nil {
+		*x = *lastX
+	}
+
+	if y != nil {
+		*y = *lastY
+	}
+
+	*d = *A
+}
+
+// ProbablyPrime performs n Miller-Rabin tests to check whether z is prime.
+// If it returns true, z is prime with probability 1 - 1/4^n.
+// If it returns false, z is not prime.
+func ProbablyPrime(z *Int, n int) bool {
+	return !z.neg && z.abs.probablyPrime(n)
+}
+
+// Rand sets z to a pseudo-random number in [0, n) and returns z.
+func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
+	z.neg = false
+	if n.neg == true || len(n.abs) == 0 {
+		z.abs = nil
+		return z
+	}
+	z.abs = z.abs.random(rnd, n.abs, n.abs.bitLen())
+	return z
+}
+
+// ModInverse sets z to the multiplicative inverse of g in the group ℤ/pℤ (where
+// p is a prime) and returns z.
+func (z *Int) ModInverse(g, p *Int) *Int {
+	var d Int
+	GcdInt(&d, z, nil, g, p)
+	// x and y are such that g*x + p*y = d. Since p is prime, d = 1. Taking
+	// that modulo p results in g*x = 1, therefore x is the inverse element.
+	if z.neg {
+		z.Add(z, p)
+	}
+	return z
+}
+
+// Lsh sets z = x << n and returns z.
+func (z *Int) Lsh(x *Int, n uint) *Int {
+	z.abs = z.abs.shl(x.abs, n)
+	z.neg = x.neg
+	return z
+}
+
+// Rsh sets z = x >> n and returns z.
+func (z *Int) Rsh(x *Int, n uint) *Int {
+	if x.neg {
+		// (-x) >> s == ^(x-1) >> s == ^((x-1) >> s) == -(((x-1) >> s) + 1)
+		t := z.abs.sub(x.abs, natOne) // no underflow because |x| > 0
+		t = t.shr(t, n)
+		z.abs = t.add(t, natOne)
+		z.neg = true // z cannot be zero if x is negative
+		return z
+	}
+
+	z.abs = z.abs.shr(x.abs, n)
+	z.neg = false
+	return z
+}
+
+// Bit returns the value of the i'th bit of z. That is, it
+// returns (z>>i)&1. The bit index i must be >= 0.
+func (z *Int) Bit(i int) uint {
+	if i < 0 {
+		panic("negative bit index")
+	}
+	if z.neg {
+		t := nat(nil).sub(z.abs, natOne)
+		return t.bit(uint(i)) ^ 1
+	}
+
+	return z.abs.bit(uint(i))
+}
+
+// SetBit sets z to x, with x's i'th bit set to b (0 or 1).
+// That is, if bit is 1 SetBit sets z = x | (1 << i);
+// if bit is 0 it sets z = x &^ (1 << i). If bit is not 0 or 1,
+// SetBit will panic.
+func (z *Int) SetBit(x *Int, i int, b uint) *Int {
+	if i < 0 {
+		panic("negative bit index")
+	}
+	if x.neg {
+		t := z.abs.sub(x.abs, natOne)
+		t = t.setBit(t, uint(i), b^1)
+		z.abs = t.add(t, natOne)
+		z.neg = len(z.abs) > 0
+		return z
+	}
+	z.abs = z.abs.setBit(x.abs, uint(i), b)
+	z.neg = false
+	return z
+}
+
+// And sets z = x & y and returns z.
+func (z *Int) And(x, y *Int) *Int {
+	if x.neg == y.neg {
+		if x.neg {
+			// (-x) & (-y) == ^(x-1) & ^(y-1) == ^((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1)
+			x1 := nat(nil).sub(x.abs, natOne)
+			y1 := nat(nil).sub(y.abs, natOne)
+			z.abs = z.abs.add(z.abs.or(x1, y1), natOne)
+			z.neg = true // z cannot be zero if x and y are negative
+			return z
+		}
+
+		// x & y == x & y
+		z.abs = z.abs.and(x.abs, y.abs)
+		z.neg = false
+		return z
+	}
+
+	// x.neg != y.neg
+	if x.neg {
+		x, y = y, x // & is symmetric
+	}
+
+	// x & (-y) == x & ^(y-1) == x &^ (y-1)
+	y1 := nat(nil).sub(y.abs, natOne)
+	z.abs = z.abs.andNot(x.abs, y1)
+	z.neg = false
+	return z
+}
+
+// AndNot sets z = x &^ y and returns z.
+func (z *Int) AndNot(x, y *Int) *Int {
+	if x.neg == y.neg {
+		if x.neg {
+			// (-x) &^ (-y) == ^(x-1) &^ ^(y-1) == ^(x-1) & (y-1) == (y-1) &^ (x-1)
+			x1 := nat(nil).sub(x.abs, natOne)
+			y1 := nat(nil).sub(y.abs, natOne)
+			z.abs = z.abs.andNot(y1, x1)
+			z.neg = false
+			return z
+		}
+
+		// x &^ y == x &^ y
+		z.abs = z.abs.andNot(x.abs, y.abs)
+		z.neg = false
+		return z
+	}
+
+	if x.neg {
+		// (-x) &^ y == ^(x-1) &^ y == ^(x-1) & ^y == ^((x-1) | y) == -(((x-1) | y) + 1)
+		x1 := nat(nil).sub(x.abs, natOne)
+		z.abs = z.abs.add(z.abs.or(x1, y.abs), natOne)
+		z.neg = true // z cannot be zero if x is negative and y is positive
+		return z
+	}
+
+	// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
+	y1 := nat(nil).add(y.abs, natOne)
+	z.abs = z.abs.and(x.abs, y1)
+	z.neg = false
+	return z
+}
+
+// Or sets z = x | y and returns z.
+func (z *Int) Or(x, y *Int) *Int {
+	if x.neg == y.neg {
+		if x.neg {
+			// (-x) | (-y) == ^(x-1) | ^(y-1) == ^((x-1) & (y-1)) == -(((x-1) & (y-1)) + 1)
+			x1 := nat(nil).sub(x.abs, natOne)
+			y1 := nat(nil).sub(y.abs, natOne)
+			z.abs = z.abs.add(z.abs.and(x1, y1), natOne)
+			z.neg = true // z cannot be zero if x and y are negative
+			return z
+		}
+
+		// x | y == x | y
+		z.abs = z.abs.or(x.abs, y.abs)
+		z.neg = false
+		return z
+	}
+
+	// x.neg != y.neg
+	if x.neg {
+		x, y = y, x // | is symmetric
+	}
+
+	// x | (-y) == x | ^(y-1) == ^((y-1) &^ x) == -(^((y-1) &^ x) + 1)
+	y1 := nat(nil).sub(y.abs, natOne)
+	z.abs = z.abs.add(z.abs.andNot(y1, x.abs), natOne)
+	z.neg = true // z cannot be zero if one of x or y is negative
+	return z
+}
+
+// Xor sets z = x ^ y and returns z.
+func (z *Int) Xor(x, y *Int) *Int {
+	if x.neg == y.neg {
+		if x.neg {
+			// (-x) ^ (-y) == ^(x-1) ^ ^(y-1) == (x-1) ^ (y-1)
+			x1 := nat(nil).sub(x.abs, natOne)
+			y1 := nat(nil).sub(y.abs, natOne)
+			z.abs = z.abs.xor(x1, y1)
+			z.neg = false
+			return z
+		}
+
+		// x ^ y == x ^ y
+		z.abs = z.abs.xor(x.abs, y.abs)
+		z.neg = false
+		return z
+	}
+
+	// x.neg != y.neg
+	if x.neg {
+		x, y = y, x // ^ is symmetric
+	}
+
+	// x ^ (-y) == x ^ ^(y-1) == ^(x ^ (y-1)) == -((x ^ (y-1)) + 1)
+	y1 := nat(nil).sub(y.abs, natOne)
+	z.abs = z.abs.add(z.abs.xor(x.abs, y1), natOne)
+	z.neg = true // z cannot be zero if only one of x or y is negative
+	return z
+}
+
+// Not sets z = ^x and returns z.
+func (z *Int) Not(x *Int) *Int {
+	if x.neg {
+		// ^(-x) == ^(^(x-1)) == x-1
+		z.abs = z.abs.sub(x.abs, natOne)
+		z.neg = false
+		return z
+	}
+
+	// ^x == -x-1 == -(x+1)
+	z.abs = z.abs.add(x.abs, natOne)
+	z.neg = true // z cannot be zero if x is positive
+	return z
+}
+
+// Gob codec version. Permits backward-compatible changes to the encoding.
+const intGobVersion byte = 1
+
+// GobEncode implements the gob.GobEncoder interface.
+func (z *Int) GobEncode() ([]byte, error) {
+	buf := make([]byte, 1+len(z.abs)*_S) // extra byte for version and sign bit
+	i := z.abs.bytes(buf) - 1            // i >= 0
+	b := intGobVersion << 1              // make space for sign bit
+	if z.neg {
+		b |= 1
+	}
+	buf[i] = b
+	return buf[i:], nil
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (z *Int) GobDecode(buf []byte) error {
+	if len(buf) == 0 {
+		return errors.New("Int.GobDecode: no data")
+	}
+	b := buf[0]
+	if b>>1 != intGobVersion {
+		return errors.New(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1))
+	}
+	z.neg = b&1 != 0
+	z.abs = z.abs.setBytes(buf[1:])
+	return nil
+}
diff --git a/src/pkg/math/big/int_test.go b/src/pkg/math/big/int_test.go
new file mode 100644
index 0000000..9c4b730
--- /dev/null
+++ b/src/pkg/math/big/int_test.go
@@ -0,0 +1,1414 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/hex"
+	"fmt"
+	"math/rand"
+	"testing"
+	"testing/quick"
+)
+
+func isNormalized(x *Int) bool {
+	if len(x.abs) == 0 {
+		return !x.neg
+	}
+	// len(x.abs) > 0
+	return x.abs[len(x.abs)-1] != 0
+}
+
+type funZZ func(z, x, y *Int) *Int
+type argZZ struct {
+	z, x, y *Int
+}
+
+var sumZZ = []argZZ{
+	{NewInt(0), NewInt(0), NewInt(0)},
+	{NewInt(1), NewInt(1), NewInt(0)},
+	{NewInt(1111111110), NewInt(123456789), NewInt(987654321)},
+	{NewInt(-1), NewInt(-1), NewInt(0)},
+	{NewInt(864197532), NewInt(-123456789), NewInt(987654321)},
+	{NewInt(-1111111110), NewInt(-123456789), NewInt(-987654321)},
+}
+
+var prodZZ = []argZZ{
+	{NewInt(0), NewInt(0), NewInt(0)},
+	{NewInt(0), NewInt(1), NewInt(0)},
+	{NewInt(1), NewInt(1), NewInt(1)},
+	{NewInt(-991 * 991), NewInt(991), NewInt(-991)},
+	// TODO(gri) add larger products
+}
+
+func TestSignZ(t *testing.T) {
+	var zero Int
+	for _, a := range sumZZ {
+		s := a.z.Sign()
+		e := a.z.Cmp(&zero)
+		if s != e {
+			t.Errorf("got %d; want %d for z = %v", s, e, a.z)
+		}
+	}
+}
+
+func TestSetZ(t *testing.T) {
+	for _, a := range sumZZ {
+		var z Int
+		z.Set(a.z)
+		if !isNormalized(&z) {
+			t.Errorf("%v is not normalized", z)
+		}
+		if (&z).Cmp(a.z) != 0 {
+			t.Errorf("got z = %v; want %v", z, a.z)
+		}
+	}
+}
+
+func TestAbsZ(t *testing.T) {
+	var zero Int
+	for _, a := range sumZZ {
+		var z Int
+		z.Abs(a.z)
+		var e Int
+		e.Set(a.z)
+		if e.Cmp(&zero) < 0 {
+			e.Sub(&zero, &e)
+		}
+		if z.Cmp(&e) != 0 {
+			t.Errorf("got z = %v; want %v", z, e)
+		}
+	}
+}
+
+func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
+	var z Int
+	f(&z, a.x, a.y)
+	if !isNormalized(&z) {
+		t.Errorf("%s%v is not normalized", z, msg)
+	}
+	if (&z).Cmp(a.z) != 0 {
+		t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
+	}
+}
+
+func TestSumZZ(t *testing.T) {
+	AddZZ := func(z, x, y *Int) *Int { return z.Add(x, y) }
+	SubZZ := func(z, x, y *Int) *Int { return z.Sub(x, y) }
+	for _, a := range sumZZ {
+		arg := a
+		testFunZZ(t, "AddZZ", AddZZ, arg)
+
+		arg = argZZ{a.z, a.y, a.x}
+		testFunZZ(t, "AddZZ symmetric", AddZZ, arg)
+
+		arg = argZZ{a.x, a.z, a.y}
+		testFunZZ(t, "SubZZ", SubZZ, arg)
+
+		arg = argZZ{a.y, a.z, a.x}
+		testFunZZ(t, "SubZZ symmetric", SubZZ, arg)
+	}
+}
+
+func TestProdZZ(t *testing.T) {
+	MulZZ := func(z, x, y *Int) *Int { return z.Mul(x, y) }
+	for _, a := range prodZZ {
+		arg := a
+		testFunZZ(t, "MulZZ", MulZZ, arg)
+
+		arg = argZZ{a.z, a.y, a.x}
+		testFunZZ(t, "MulZZ symmetric", MulZZ, arg)
+	}
+}
+
+// mulBytes returns x*y via grade school multiplication. Both inputs
+// and the result are assumed to be in big-endian representation (to
+// match the semantics of Int.Bytes and Int.SetBytes).
+func mulBytes(x, y []byte) []byte {
+	z := make([]byte, len(x)+len(y))
+
+	// multiply
+	k0 := len(z) - 1
+	for j := len(y) - 1; j >= 0; j-- {
+		d := int(y[j])
+		if d != 0 {
+			k := k0
+			carry := 0
+			for i := len(x) - 1; i >= 0; i-- {
+				t := int(z[k]) + int(x[i])*d + carry
+				z[k], carry = byte(t), t>>8
+				k--
+			}
+			z[k] = byte(carry)
+		}
+		k0--
+	}
+
+	// normalize (remove leading 0's)
+	i := 0
+	for i < len(z) && z[i] == 0 {
+		i++
+	}
+
+	return z[i:]
+}
+
+func checkMul(a, b []byte) bool {
+	var x, y, z1 Int
+	x.SetBytes(a)
+	y.SetBytes(b)
+	z1.Mul(&x, &y)
+
+	var z2 Int
+	z2.SetBytes(mulBytes(a, b))
+
+	return z1.Cmp(&z2) == 0
+}
+
+func TestMul(t *testing.T) {
+	if err := quick.Check(checkMul, nil); err != nil {
+		t.Error(err)
+	}
+}
+
+var mulRangesZ = []struct {
+	a, b int64
+	prod string
+}{
+	// entirely positive ranges are covered by mulRangesN
+	{-1, 1, "0"},
+	{-2, -1, "2"},
+	{-3, -2, "6"},
+	{-3, -1, "-6"},
+	{1, 3, "6"},
+	{-10, -10, "-10"},
+	{0, -1, "1"},                      // empty range
+	{-1, -100, "1"},                   // empty range
+	{-1, 1, "0"},                      // range includes 0
+	{-1e9, 0, "0"},                    // range includes 0
+	{-1e9, 1e9, "0"},                  // range includes 0
+	{-10, -1, "3628800"},              // 10!
+	{-20, -2, "-2432902008176640000"}, // -20!
+	{-99, -1,
+		"-933262154439441526816992388562667004907159682643816214685929" +
+			"638952175999932299156089414639761565182862536979208272237582" +
+			"511852109168640000000000000000000000", // -99!
+	},
+}
+
+func TestMulRangeZ(t *testing.T) {
+	var tmp Int
+	// test entirely positive ranges
+	for i, r := range mulRangesN {
+		prod := tmp.MulRange(int64(r.a), int64(r.b)).String()
+		if prod != r.prod {
+			t.Errorf("#%da: got %s; want %s", i, prod, r.prod)
+		}
+	}
+	// test other ranges
+	for i, r := range mulRangesZ {
+		prod := tmp.MulRange(r.a, r.b).String()
+		if prod != r.prod {
+			t.Errorf("#%db: got %s; want %s", i, prod, r.prod)
+		}
+	}
+}
+
+var stringTests = []struct {
+	in   string
+	out  string
+	base int
+	val  int64
+	ok   bool
+}{
+	{in: "", ok: false},
+	{in: "a", ok: false},
+	{in: "z", ok: false},
+	{in: "+", ok: false},
+	{in: "-", ok: false},
+	{in: "0b", ok: false},
+	{in: "0x", ok: false},
+	{in: "2", base: 2, ok: false},
+	{in: "0b2", base: 0, ok: false},
+	{in: "08", ok: false},
+	{in: "8", base: 8, ok: false},
+	{in: "0xg", base: 0, ok: false},
+	{in: "g", base: 16, ok: false},
+	{"0", "0", 0, 0, true},
+	{"0", "0", 10, 0, true},
+	{"0", "0", 16, 0, true},
+	{"+0", "0", 0, 0, true},
+	{"-0", "0", 0, 0, true},
+	{"10", "10", 0, 10, true},
+	{"10", "10", 10, 10, true},
+	{"10", "10", 16, 16, true},
+	{"-10", "-10", 16, -16, true},
+	{"+10", "10", 16, 16, true},
+	{"0x10", "16", 0, 16, true},
+	{in: "0x10", base: 16, ok: false},
+	{"-0x10", "-16", 0, -16, true},
+	{"+0x10", "16", 0, 16, true},
+	{"00", "0", 0, 0, true},
+	{"0", "0", 8, 0, true},
+	{"07", "7", 0, 7, true},
+	{"7", "7", 8, 7, true},
+	{"023", "19", 0, 19, true},
+	{"23", "23", 8, 19, true},
+	{"cafebabe", "cafebabe", 16, 0xcafebabe, true},
+	{"0b0", "0", 0, 0, true},
+	{"-111", "-111", 2, -7, true},
+	{"-0b111", "-7", 0, -7, true},
+	{"0b1001010111", "599", 0, 0x257, true},
+	{"1001010111", "1001010111", 2, 0x257, true},
+}
+
+func format(base int) string {
+	switch base {
+	case 2:
+		return "%b"
+	case 8:
+		return "%o"
+	case 16:
+		return "%x"
+	}
+	return "%d"
+}
+
+func TestGetString(t *testing.T) {
+	z := new(Int)
+	for i, test := range stringTests {
+		if !test.ok {
+			continue
+		}
+		z.SetInt64(test.val)
+
+		if test.base == 10 {
+			s := z.String()
+			if s != test.out {
+				t.Errorf("#%da got %s; want %s", i, s, test.out)
+			}
+		}
+
+		s := fmt.Sprintf(format(test.base), z)
+		if s != test.out {
+			t.Errorf("#%db got %s; want %s", i, s, test.out)
+		}
+	}
+}
+
+func TestSetString(t *testing.T) {
+	tmp := new(Int)
+	for i, test := range stringTests {
+		// initialize to a non-zero value so that issues with parsing
+		// 0 are detected
+		tmp.SetInt64(1234567890)
+		n1, ok1 := new(Int).SetString(test.in, test.base)
+		n2, ok2 := tmp.SetString(test.in, test.base)
+		expected := NewInt(test.val)
+		if ok1 != test.ok || ok2 != test.ok {
+			t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
+			continue
+		}
+		if !ok1 {
+			if n1 != nil {
+				t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
+			}
+			continue
+		}
+		if !ok2 {
+			if n2 != nil {
+				t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
+			}
+			continue
+		}
+
+		if ok1 && !isNormalized(n1) {
+			t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
+		}
+		if ok2 && !isNormalized(n2) {
+			t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
+		}
+
+		if n1.Cmp(expected) != 0 {
+			t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
+		}
+		if n2.Cmp(expected) != 0 {
+			t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
+		}
+	}
+}
+
+var formatTests = []struct {
+	input  string
+	format string
+	output string
+}{
+	{"<nil>", "%x", "<nil>"},
+	{"<nil>", "%#x", "<nil>"},
+	{"<nil>", "%#y", "%!y(big.Int=<nil>)"},
+
+	{"10", "%b", "1010"},
+	{"10", "%o", "12"},
+	{"10", "%d", "10"},
+	{"10", "%v", "10"},
+	{"10", "%x", "a"},
+	{"10", "%X", "A"},
+	{"-10", "%X", "-A"},
+	{"10", "%y", "%!y(big.Int=10)"},
+	{"-10", "%y", "%!y(big.Int=-10)"},
+
+	{"10", "%#b", "1010"},
+	{"10", "%#o", "012"},
+	{"10", "%#d", "10"},
+	{"10", "%#v", "10"},
+	{"10", "%#x", "0xa"},
+	{"10", "%#X", "0XA"},
+	{"-10", "%#X", "-0XA"},
+	{"10", "%#y", "%!y(big.Int=10)"},
+	{"-10", "%#y", "%!y(big.Int=-10)"},
+
+	{"1234", "%d", "1234"},
+	{"1234", "%3d", "1234"},
+	{"1234", "%4d", "1234"},
+	{"-1234", "%d", "-1234"},
+	{"1234", "% 5d", " 1234"},
+	{"1234", "%+5d", "+1234"},
+	{"1234", "%-5d", "1234 "},
+	{"1234", "%x", "4d2"},
+	{"1234", "%X", "4D2"},
+	{"-1234", "%3x", "-4d2"},
+	{"-1234", "%4x", "-4d2"},
+	{"-1234", "%5x", " -4d2"},
+	{"-1234", "%-5x", "-4d2 "},
+	{"1234", "%03d", "1234"},
+	{"1234", "%04d", "1234"},
+	{"1234", "%05d", "01234"},
+	{"1234", "%06d", "001234"},
+	{"-1234", "%06d", "-01234"},
+	{"1234", "%+06d", "+01234"},
+	{"1234", "% 06d", " 01234"},
+	{"1234", "%-6d", "1234  "},
+	{"1234", "%-06d", "1234  "},
+	{"-1234", "%-06d", "-1234 "},
+
+	{"1234", "%.3d", "1234"},
+	{"1234", "%.4d", "1234"},
+	{"1234", "%.5d", "01234"},
+	{"1234", "%.6d", "001234"},
+	{"-1234", "%.3d", "-1234"},
+	{"-1234", "%.4d", "-1234"},
+	{"-1234", "%.5d", "-01234"},
+	{"-1234", "%.6d", "-001234"},
+
+	{"1234", "%8.3d", "    1234"},
+	{"1234", "%8.4d", "    1234"},
+	{"1234", "%8.5d", "   01234"},
+	{"1234", "%8.6d", "  001234"},
+	{"-1234", "%8.3d", "   -1234"},
+	{"-1234", "%8.4d", "   -1234"},
+	{"-1234", "%8.5d", "  -01234"},
+	{"-1234", "%8.6d", " -001234"},
+
+	{"1234", "%+8.3d", "   +1234"},
+	{"1234", "%+8.4d", "   +1234"},
+	{"1234", "%+8.5d", "  +01234"},
+	{"1234", "%+8.6d", " +001234"},
+	{"-1234", "%+8.3d", "   -1234"},
+	{"-1234", "%+8.4d", "   -1234"},
+	{"-1234", "%+8.5d", "  -01234"},
+	{"-1234", "%+8.6d", " -001234"},
+
+	{"1234", "% 8.3d", "    1234"},
+	{"1234", "% 8.4d", "    1234"},
+	{"1234", "% 8.5d", "   01234"},
+	{"1234", "% 8.6d", "  001234"},
+	{"-1234", "% 8.3d", "   -1234"},
+	{"-1234", "% 8.4d", "   -1234"},
+	{"-1234", "% 8.5d", "  -01234"},
+	{"-1234", "% 8.6d", " -001234"},
+
+	{"1234", "%.3x", "4d2"},
+	{"1234", "%.4x", "04d2"},
+	{"1234", "%.5x", "004d2"},
+	{"1234", "%.6x", "0004d2"},
+	{"-1234", "%.3x", "-4d2"},
+	{"-1234", "%.4x", "-04d2"},
+	{"-1234", "%.5x", "-004d2"},
+	{"-1234", "%.6x", "-0004d2"},
+
+	{"1234", "%8.3x", "     4d2"},
+	{"1234", "%8.4x", "    04d2"},
+	{"1234", "%8.5x", "   004d2"},
+	{"1234", "%8.6x", "  0004d2"},
+	{"-1234", "%8.3x", "    -4d2"},
+	{"-1234", "%8.4x", "   -04d2"},
+	{"-1234", "%8.5x", "  -004d2"},
+	{"-1234", "%8.6x", " -0004d2"},
+
+	{"1234", "%+8.3x", "    +4d2"},
+	{"1234", "%+8.4x", "   +04d2"},
+	{"1234", "%+8.5x", "  +004d2"},
+	{"1234", "%+8.6x", " +0004d2"},
+	{"-1234", "%+8.3x", "    -4d2"},
+	{"-1234", "%+8.4x", "   -04d2"},
+	{"-1234", "%+8.5x", "  -004d2"},
+	{"-1234", "%+8.6x", " -0004d2"},
+
+	{"1234", "% 8.3x", "     4d2"},
+	{"1234", "% 8.4x", "    04d2"},
+	{"1234", "% 8.5x", "   004d2"},
+	{"1234", "% 8.6x", "  0004d2"},
+	{"1234", "% 8.7x", " 00004d2"},
+	{"1234", "% 8.8x", " 000004d2"},
+	{"-1234", "% 8.3x", "    -4d2"},
+	{"-1234", "% 8.4x", "   -04d2"},
+	{"-1234", "% 8.5x", "  -004d2"},
+	{"-1234", "% 8.6x", " -0004d2"},
+	{"-1234", "% 8.7x", "-00004d2"},
+	{"-1234", "% 8.8x", "-000004d2"},
+
+	{"1234", "%-8.3d", "1234    "},
+	{"1234", "%-8.4d", "1234    "},
+	{"1234", "%-8.5d", "01234   "},
+	{"1234", "%-8.6d", "001234  "},
+	{"1234", "%-8.7d", "0001234 "},
+	{"1234", "%-8.8d", "00001234"},
+	{"-1234", "%-8.3d", "-1234   "},
+	{"-1234", "%-8.4d", "-1234   "},
+	{"-1234", "%-8.5d", "-01234  "},
+	{"-1234", "%-8.6d", "-001234 "},
+	{"-1234", "%-8.7d", "-0001234"},
+	{"-1234", "%-8.8d", "-00001234"},
+
+	{"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
+
+	{"0", "%.d", ""},
+	{"0", "%.0d", ""},
+	{"0", "%3.d", ""},
+}
+
+func TestFormat(t *testing.T) {
+	for i, test := range formatTests {
+		var x *Int
+		if test.input != "<nil>" {
+			var ok bool
+			x, ok = new(Int).SetString(test.input, 0)
+			if !ok {
+				t.Errorf("#%d failed reading input %s", i, test.input)
+			}
+		}
+		output := fmt.Sprintf(test.format, x)
+		if output != test.output {
+			t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
+		}
+	}
+}
+
+var scanTests = []struct {
+	input     string
+	format    string
+	output    string
+	remaining int
+}{
+	{"1010", "%b", "10", 0},
+	{"0b1010", "%v", "10", 0},
+	{"12", "%o", "10", 0},
+	{"012", "%v", "10", 0},
+	{"10", "%d", "10", 0},
+	{"10", "%v", "10", 0},
+	{"a", "%x", "10", 0},
+	{"0xa", "%v", "10", 0},
+	{"A", "%X", "10", 0},
+	{"-A", "%X", "-10", 0},
+	{"+0b1011001", "%v", "89", 0},
+	{"0xA", "%v", "10", 0},
+	{"0 ", "%v", "0", 1},
+	{"2+3", "%v", "2", 2},
+	{"0XABC 12", "%v", "2748", 3},
+}
+
+func TestScan(t *testing.T) {
+	var buf bytes.Buffer
+	for i, test := range scanTests {
+		x := new(Int)
+		buf.Reset()
+		buf.WriteString(test.input)
+		if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
+			t.Errorf("#%d error: %s", i, err)
+		}
+		if x.String() != test.output {
+			t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
+		}
+		if buf.Len() != test.remaining {
+			t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
+		}
+	}
+}
+
+// Examples from the Go Language Spec, section "Arithmetic operators"
+var divisionSignsTests = []struct {
+	x, y int64
+	q, r int64 // T-division
+	d, m int64 // Euclidian division
+}{
+	{5, 3, 1, 2, 1, 2},
+	{-5, 3, -1, -2, -2, 1},
+	{5, -3, -1, 2, -1, 2},
+	{-5, -3, 1, -2, 2, 1},
+	{1, 2, 0, 1, 0, 1},
+	{8, 4, 2, 0, 2, 0},
+}
+
+func TestDivisionSigns(t *testing.T) {
+	for i, test := range divisionSignsTests {
+		x := NewInt(test.x)
+		y := NewInt(test.y)
+		q := NewInt(test.q)
+		r := NewInt(test.r)
+		d := NewInt(test.d)
+		m := NewInt(test.m)
+
+		q1 := new(Int).Quo(x, y)
+		r1 := new(Int).Rem(x, y)
+		if !isNormalized(q1) {
+			t.Errorf("#%d Quo: %v is not normalized", i, *q1)
+		}
+		if !isNormalized(r1) {
+			t.Errorf("#%d Rem: %v is not normalized", i, *r1)
+		}
+		if q1.Cmp(q) != 0 || r1.Cmp(r) != 0 {
+			t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q1, r1, q, r)
+		}
+
+		q2, r2 := new(Int).QuoRem(x, y, new(Int))
+		if !isNormalized(q2) {
+			t.Errorf("#%d Quo: %v is not normalized", i, *q2)
+		}
+		if !isNormalized(r2) {
+			t.Errorf("#%d Rem: %v is not normalized", i, *r2)
+		}
+		if q2.Cmp(q) != 0 || r2.Cmp(r) != 0 {
+			t.Errorf("#%d QuoRem: got (%s, %s), want (%s, %s)", i, q2, r2, q, r)
+		}
+
+		d1 := new(Int).Div(x, y)
+		m1 := new(Int).Mod(x, y)
+		if !isNormalized(d1) {
+			t.Errorf("#%d Div: %v is not normalized", i, *d1)
+		}
+		if !isNormalized(m1) {
+			t.Errorf("#%d Mod: %v is not normalized", i, *m1)
+		}
+		if d1.Cmp(d) != 0 || m1.Cmp(m) != 0 {
+			t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d1, m1, d, m)
+		}
+
+		d2, m2 := new(Int).DivMod(x, y, new(Int))
+		if !isNormalized(d2) {
+			t.Errorf("#%d Div: %v is not normalized", i, *d2)
+		}
+		if !isNormalized(m2) {
+			t.Errorf("#%d Mod: %v is not normalized", i, *m2)
+		}
+		if d2.Cmp(d) != 0 || m2.Cmp(m) != 0 {
+			t.Errorf("#%d DivMod: got (%s, %s), want (%s, %s)", i, d2, m2, d, m)
+		}
+	}
+}
+
+func checkSetBytes(b []byte) bool {
+	hex1 := hex.EncodeToString(new(Int).SetBytes(b).Bytes())
+	hex2 := hex.EncodeToString(b)
+
+	for len(hex1) < len(hex2) {
+		hex1 = "0" + hex1
+	}
+
+	for len(hex1) > len(hex2) {
+		hex2 = "0" + hex2
+	}
+
+	return hex1 == hex2
+}
+
+func TestSetBytes(t *testing.T) {
+	if err := quick.Check(checkSetBytes, nil); err != nil {
+		t.Error(err)
+	}
+}
+
+func checkBytes(b []byte) bool {
+	b2 := new(Int).SetBytes(b).Bytes()
+	return bytes.Compare(b, b2) == 0
+}
+
+func TestBytes(t *testing.T) {
+	if err := quick.Check(checkSetBytes, nil); err != nil {
+		t.Error(err)
+	}
+}
+
+func checkQuo(x, y []byte) bool {
+	u := new(Int).SetBytes(x)
+	v := new(Int).SetBytes(y)
+
+	if len(v.abs) == 0 {
+		return true
+	}
+
+	r := new(Int)
+	q, r := new(Int).QuoRem(u, v, r)
+
+	if r.Cmp(v) >= 0 {
+		return false
+	}
+
+	uprime := new(Int).Set(q)
+	uprime.Mul(uprime, v)
+	uprime.Add(uprime, r)
+
+	return uprime.Cmp(u) == 0
+}
+
+var quoTests = []struct {
+	x, y string
+	q, r string
+}{
+	{
+		"476217953993950760840509444250624797097991362735329973741718102894495832294430498335824897858659711275234906400899559094370964723884706254265559534144986498357",
+		"9353930466774385905609975137998169297361893554149986716853295022578535724979483772383667534691121982974895531435241089241440253066816724367338287092081996",
+		"50911",
+		"1",
+	},
+	{
+		"11510768301994997771168",
+		"1328165573307167369775",
+		"8",
+		"885443715537658812968",
+	},
+}
+
+func TestQuo(t *testing.T) {
+	if err := quick.Check(checkQuo, nil); err != nil {
+		t.Error(err)
+	}
+
+	for i, test := range quoTests {
+		x, _ := new(Int).SetString(test.x, 10)
+		y, _ := new(Int).SetString(test.y, 10)
+		expectedQ, _ := new(Int).SetString(test.q, 10)
+		expectedR, _ := new(Int).SetString(test.r, 10)
+
+		r := new(Int)
+		q, r := new(Int).QuoRem(x, y, r)
+
+		if q.Cmp(expectedQ) != 0 || r.Cmp(expectedR) != 0 {
+			t.Errorf("#%d got (%s, %s) want (%s, %s)", i, q, r, expectedQ, expectedR)
+		}
+	}
+}
+
+func TestQuoStepD6(t *testing.T) {
+	// See Knuth, Volume 2, section 4.3.1, exercise 21. This code exercises
+	// a code path which only triggers 1 in 10^{-19} cases.
+
+	u := &Int{false, nat{0, 0, 1 + 1<<(_W-1), _M ^ (1 << (_W - 1))}}
+	v := &Int{false, nat{5, 2 + 1<<(_W-1), 1 << (_W - 1)}}
+
+	r := new(Int)
+	q, r := new(Int).QuoRem(u, v, r)
+	const expectedQ64 = "18446744073709551613"
+	const expectedR64 = "3138550867693340382088035895064302439801311770021610913807"
+	const expectedQ32 = "4294967293"
+	const expectedR32 = "39614081266355540837921718287"
+	if q.String() != expectedQ64 && q.String() != expectedQ32 ||
+		r.String() != expectedR64 && r.String() != expectedR32 {
+		t.Errorf("got (%s, %s) want (%s, %s) or (%s, %s)", q, r, expectedQ64, expectedR64, expectedQ32, expectedR32)
+	}
+}
+
+var bitLenTests = []struct {
+	in  string
+	out int
+}{
+	{"-1", 1},
+	{"0", 0},
+	{"1", 1},
+	{"2", 2},
+	{"4", 3},
+	{"0xabc", 12},
+	{"0x8000", 16},
+	{"0x80000000", 32},
+	{"0x800000000000", 48},
+	{"0x8000000000000000", 64},
+	{"0x80000000000000000000", 80},
+	{"-0x4000000000000000000000", 87},
+}
+
+func TestBitLen(t *testing.T) {
+	for i, test := range bitLenTests {
+		x, ok := new(Int).SetString(test.in, 0)
+		if !ok {
+			t.Errorf("#%d test input invalid: %s", i, test.in)
+			continue
+		}
+
+		if n := x.BitLen(); n != test.out {
+			t.Errorf("#%d got %d want %d", i, n, test.out)
+		}
+	}
+}
+
+var expTests = []struct {
+	x, y, m string
+	out     string
+}{
+	{"5", "0", "", "1"},
+	{"-5", "0", "", "-1"},
+	{"5", "1", "", "5"},
+	{"-5", "1", "", "-5"},
+	{"-2", "3", "2", "0"},
+	{"5", "2", "", "25"},
+	{"1", "65537", "2", "1"},
+	{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
+	{"0x8000000000000000", "2", "6719", "4944"},
+	{"0x8000000000000000", "3", "6719", "5447"},
+	{"0x8000000000000000", "1000", "6719", "1603"},
+	{"0x8000000000000000", "1000000", "6719", "3199"},
+	{
+		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
+		"298472983472983471903246121093472394872319615612417471234712061",
+		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
+		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
+	},
+}
+
+func TestExp(t *testing.T) {
+	for i, test := range expTests {
+		x, ok1 := new(Int).SetString(test.x, 0)
+		y, ok2 := new(Int).SetString(test.y, 0)
+		out, ok3 := new(Int).SetString(test.out, 0)
+
+		var ok4 bool
+		var m *Int
+
+		if len(test.m) == 0 {
+			m, ok4 = nil, true
+		} else {
+			m, ok4 = new(Int).SetString(test.m, 0)
+		}
+
+		if !ok1 || !ok2 || !ok3 || !ok4 {
+			t.Errorf("#%d: error in input", i)
+			continue
+		}
+
+		z := y.Exp(x, y, m)
+		if !isNormalized(z) {
+			t.Errorf("#%d: %v is not normalized", i, *z)
+		}
+		if z.Cmp(out) != 0 {
+			t.Errorf("#%d: got %s want %s", i, z, out)
+		}
+	}
+}
+
+func checkGcd(aBytes, bBytes []byte) bool {
+	a := new(Int).SetBytes(aBytes)
+	b := new(Int).SetBytes(bBytes)
+
+	x := new(Int)
+	y := new(Int)
+	d := new(Int)
+
+	GcdInt(d, x, y, a, b)
+	x.Mul(x, a)
+	y.Mul(y, b)
+	x.Add(x, y)
+
+	return x.Cmp(d) == 0
+}
+
+var gcdTests = []struct {
+	a, b    int64
+	d, x, y int64
+}{
+	{120, 23, 1, -9, 47},
+}
+
+func TestGcd(t *testing.T) {
+	for i, test := range gcdTests {
+		a := NewInt(test.a)
+		b := NewInt(test.b)
+
+		x := new(Int)
+		y := new(Int)
+		d := new(Int)
+
+		expectedX := NewInt(test.x)
+		expectedY := NewInt(test.y)
+		expectedD := NewInt(test.d)
+
+		GcdInt(d, x, y, a, b)
+
+		if expectedX.Cmp(x) != 0 ||
+			expectedY.Cmp(y) != 0 ||
+			expectedD.Cmp(d) != 0 {
+			t.Errorf("#%d got (%s %s %s) want (%s %s %s)", i, x, y, d, expectedX, expectedY, expectedD)
+		}
+	}
+
+	quick.Check(checkGcd, nil)
+}
+
+var primes = []string{
+	"2",
+	"3",
+	"5",
+	"7",
+	"11",
+
+	"13756265695458089029",
+	"13496181268022124907",
+	"10953742525620032441",
+	"17908251027575790097",
+
+	// http://code.google.com/p/go/issues/detail?id=638
+	"18699199384836356663",
+
+	"98920366548084643601728869055592650835572950932266967461790948584315647051443",
+	"94560208308847015747498523884063394671606671904944666360068158221458669711639",
+
+	// http://primes.utm.edu/lists/small/small3.html
+	"449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163",
+	"230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593",
+	"5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993",
+	"203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123",
+}
+
+var composites = []string{
+	"21284175091214687912771199898307297748211672914763848041968395774954376176754",
+	"6084766654921918907427900243509372380954290099172559290432744450051395395951",
+	"84594350493221918389213352992032324280367711247940675652888030554255915464401",
+	"82793403787388584738507275144194252681",
+}
+
+func TestProbablyPrime(t *testing.T) {
+	nreps := 20
+	if testing.Short() {
+		nreps = 1
+	}
+	for i, s := range primes {
+		p, _ := new(Int).SetString(s, 10)
+		if !ProbablyPrime(p, nreps) {
+			t.Errorf("#%d prime found to be non-prime (%s)", i, s)
+		}
+	}
+
+	for i, s := range composites {
+		c, _ := new(Int).SetString(s, 10)
+		if ProbablyPrime(c, nreps) {
+			t.Errorf("#%d composite found to be prime (%s)", i, s)
+		}
+		if testing.Short() {
+			break
+		}
+	}
+}
+
+type intShiftTest struct {
+	in    string
+	shift uint
+	out   string
+}
+
+var rshTests = []intShiftTest{
+	{"0", 0, "0"},
+	{"-0", 0, "0"},
+	{"0", 1, "0"},
+	{"0", 2, "0"},
+	{"1", 0, "1"},
+	{"1", 1, "0"},
+	{"1", 2, "0"},
+	{"2", 0, "2"},
+	{"2", 1, "1"},
+	{"-1", 0, "-1"},
+	{"-1", 1, "-1"},
+	{"-1", 10, "-1"},
+	{"-100", 2, "-25"},
+	{"-100", 3, "-13"},
+	{"-100", 100, "-1"},
+	{"4294967296", 0, "4294967296"},
+	{"4294967296", 1, "2147483648"},
+	{"4294967296", 2, "1073741824"},
+	{"18446744073709551616", 0, "18446744073709551616"},
+	{"18446744073709551616", 1, "9223372036854775808"},
+	{"18446744073709551616", 2, "4611686018427387904"},
+	{"18446744073709551616", 64, "1"},
+	{"340282366920938463463374607431768211456", 64, "18446744073709551616"},
+	{"340282366920938463463374607431768211456", 128, "1"},
+}
+
+func TestRsh(t *testing.T) {
+	for i, test := range rshTests {
+		in, _ := new(Int).SetString(test.in, 10)
+		expected, _ := new(Int).SetString(test.out, 10)
+		out := new(Int).Rsh(in, test.shift)
+
+		if !isNormalized(out) {
+			t.Errorf("#%d: %v is not normalized", i, *out)
+		}
+		if out.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, expected)
+		}
+	}
+}
+
+func TestRshSelf(t *testing.T) {
+	for i, test := range rshTests {
+		z, _ := new(Int).SetString(test.in, 10)
+		expected, _ := new(Int).SetString(test.out, 10)
+		z.Rsh(z, test.shift)
+
+		if !isNormalized(z) {
+			t.Errorf("#%d: %v is not normalized", i, *z)
+		}
+		if z.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, z, expected)
+		}
+	}
+}
+
+var lshTests = []intShiftTest{
+	{"0", 0, "0"},
+	{"0", 1, "0"},
+	{"0", 2, "0"},
+	{"1", 0, "1"},
+	{"1", 1, "2"},
+	{"1", 2, "4"},
+	{"2", 0, "2"},
+	{"2", 1, "4"},
+	{"2", 2, "8"},
+	{"-87", 1, "-174"},
+	{"4294967296", 0, "4294967296"},
+	{"4294967296", 1, "8589934592"},
+	{"4294967296", 2, "17179869184"},
+	{"18446744073709551616", 0, "18446744073709551616"},
+	{"9223372036854775808", 1, "18446744073709551616"},
+	{"4611686018427387904", 2, "18446744073709551616"},
+	{"1", 64, "18446744073709551616"},
+	{"18446744073709551616", 64, "340282366920938463463374607431768211456"},
+	{"1", 128, "340282366920938463463374607431768211456"},
+}
+
+func TestLsh(t *testing.T) {
+	for i, test := range lshTests {
+		in, _ := new(Int).SetString(test.in, 10)
+		expected, _ := new(Int).SetString(test.out, 10)
+		out := new(Int).Lsh(in, test.shift)
+
+		if !isNormalized(out) {
+			t.Errorf("#%d: %v is not normalized", i, *out)
+		}
+		if out.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, expected)
+		}
+	}
+}
+
+func TestLshSelf(t *testing.T) {
+	for i, test := range lshTests {
+		z, _ := new(Int).SetString(test.in, 10)
+		expected, _ := new(Int).SetString(test.out, 10)
+		z.Lsh(z, test.shift)
+
+		if !isNormalized(z) {
+			t.Errorf("#%d: %v is not normalized", i, *z)
+		}
+		if z.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, z, expected)
+		}
+	}
+}
+
+func TestLshRsh(t *testing.T) {
+	for i, test := range rshTests {
+		in, _ := new(Int).SetString(test.in, 10)
+		out := new(Int).Lsh(in, test.shift)
+		out = out.Rsh(out, test.shift)
+
+		if !isNormalized(out) {
+			t.Errorf("#%d: %v is not normalized", i, *out)
+		}
+		if in.Cmp(out) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, in)
+		}
+	}
+	for i, test := range lshTests {
+		in, _ := new(Int).SetString(test.in, 10)
+		out := new(Int).Lsh(in, test.shift)
+		out.Rsh(out, test.shift)
+
+		if !isNormalized(out) {
+			t.Errorf("#%d: %v is not normalized", i, *out)
+		}
+		if in.Cmp(out) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, in)
+		}
+	}
+}
+
+var int64Tests = []int64{
+	0,
+	1,
+	-1,
+	4294967295,
+	-4294967295,
+	4294967296,
+	-4294967296,
+	9223372036854775807,
+	-9223372036854775807,
+	-9223372036854775808,
+}
+
+func TestInt64(t *testing.T) {
+	for i, testVal := range int64Tests {
+		in := NewInt(testVal)
+		out := in.Int64()
+
+		if out != testVal {
+			t.Errorf("#%d got %d want %d", i, out, testVal)
+		}
+	}
+}
+
+var bitwiseTests = []struct {
+	x, y                 string
+	and, or, xor, andNot string
+}{
+	{"0x00", "0x00", "0x00", "0x00", "0x00", "0x00"},
+	{"0x00", "0x01", "0x00", "0x01", "0x01", "0x00"},
+	{"0x01", "0x00", "0x00", "0x01", "0x01", "0x01"},
+	{"-0x01", "0x00", "0x00", "-0x01", "-0x01", "-0x01"},
+	{"-0xaf", "-0x50", "-0xf0", "-0x0f", "0xe1", "0x41"},
+	{"0x00", "-0x01", "0x00", "-0x01", "-0x01", "0x00"},
+	{"0x01", "0x01", "0x01", "0x01", "0x00", "0x00"},
+	{"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"},
+	{"0x07", "0x08", "0x00", "0x0f", "0x0f", "0x07"},
+	{"0x05", "0x0f", "0x05", "0x0f", "0x0a", "0x00"},
+	{"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8", "0x0125b0"},
+	{"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc", "-0x01c000"},
+	{"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8", "0x8008"},
+	{
+		"0x1000009dc6e3d9822cba04129bcbe3401",
+		"0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
+		"0x1000001186210100001000009048c2001",
+		"0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
+		"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
+		"0x8c40c2d8822caa04120b8321400",
+	},
+	{
+		"0x1000009dc6e3d9822cba04129bcbe3401",
+		"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
+		"0x8c40c2d8822caa04120b8321401",
+		"-0xb9bd7d543685789d57ca918e82229142459020483cd2014001fd",
+		"-0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fe",
+		"0x1000001186210100001000009048c2000",
+	},
+	{
+		"-0x1000009dc6e3d9822cba04129bcbe3401",
+		"-0xb9bd7d543685789d57cb918e833af352559021483cdb05cc21fd",
+		"-0xb9bd7d543685789d57cb918e8bfeff7fddb2ebe87dfbbdfe35fd",
+		"-0x1000001186210100001000009048c2001",
+		"0xb9bd7d543685789d57ca918e8ae69d6fcdb2eae87df2b97215fc",
+		"0xb9bd7d543685789d57ca918e82229142459020483cd2014001fc",
+	},
+}
+
+type bitFun func(z, x, y *Int) *Int
+
+func testBitFun(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
+	expected := new(Int)
+	expected.SetString(exp, 0)
+
+	out := f(new(Int), x, y)
+	if out.Cmp(expected) != 0 {
+		t.Errorf("%s: got %s want %s", msg, out, expected)
+	}
+}
+
+func testBitFunSelf(t *testing.T, msg string, f bitFun, x, y *Int, exp string) {
+	self := new(Int)
+	self.Set(x)
+	expected := new(Int)
+	expected.SetString(exp, 0)
+
+	self = f(self, self, y)
+	if self.Cmp(expected) != 0 {
+		t.Errorf("%s: got %s want %s", msg, self, expected)
+	}
+}
+
+func altBit(x *Int, i int) uint {
+	z := new(Int).Rsh(x, uint(i))
+	z = z.And(z, NewInt(1))
+	if z.Cmp(new(Int)) != 0 {
+		return 1
+	}
+	return 0
+}
+
+func altSetBit(z *Int, x *Int, i int, b uint) *Int {
+	one := NewInt(1)
+	m := one.Lsh(one, uint(i))
+	switch b {
+	case 1:
+		return z.Or(x, m)
+	case 0:
+		return z.AndNot(x, m)
+	}
+	panic("set bit is not 0 or 1")
+}
+
+func testBitset(t *testing.T, x *Int) {
+	n := x.BitLen()
+	z := new(Int).Set(x)
+	z1 := new(Int).Set(x)
+	for i := 0; i < n+10; i++ {
+		old := z.Bit(i)
+		old1 := altBit(z1, i)
+		if old != old1 {
+			t.Errorf("bitset: inconsistent value for Bit(%s, %d), got %v want %v", z1, i, old, old1)
+		}
+		z := new(Int).SetBit(z, i, 1)
+		z1 := altSetBit(new(Int), z1, i, 1)
+		if z.Bit(i) == 0 {
+			t.Errorf("bitset: bit %d of %s got 0 want 1", i, x)
+		}
+		if z.Cmp(z1) != 0 {
+			t.Errorf("bitset: inconsistent value after SetBit 1, got %s want %s", z, z1)
+		}
+		z.SetBit(z, i, 0)
+		altSetBit(z1, z1, i, 0)
+		if z.Bit(i) != 0 {
+			t.Errorf("bitset: bit %d of %s got 1 want 0", i, x)
+		}
+		if z.Cmp(z1) != 0 {
+			t.Errorf("bitset: inconsistent value after SetBit 0, got %s want %s", z, z1)
+		}
+		altSetBit(z1, z1, i, old)
+		z.SetBit(z, i, old)
+		if z.Cmp(z1) != 0 {
+			t.Errorf("bitset: inconsistent value after SetBit old, got %s want %s", z, z1)
+		}
+	}
+	if z.Cmp(x) != 0 {
+		t.Errorf("bitset: got %s want %s", z, x)
+	}
+}
+
+var bitsetTests = []struct {
+	x string
+	i int
+	b uint
+}{
+	{"0", 0, 0},
+	{"0", 200, 0},
+	{"1", 0, 1},
+	{"1", 1, 0},
+	{"-1", 0, 1},
+	{"-1", 200, 1},
+	{"0x2000000000000000000000000000", 108, 0},
+	{"0x2000000000000000000000000000", 109, 1},
+	{"0x2000000000000000000000000000", 110, 0},
+	{"-0x2000000000000000000000000001", 108, 1},
+	{"-0x2000000000000000000000000001", 109, 0},
+	{"-0x2000000000000000000000000001", 110, 1},
+}
+
+func TestBitSet(t *testing.T) {
+	for _, test := range bitwiseTests {
+		x := new(Int)
+		x.SetString(test.x, 0)
+		testBitset(t, x)
+		x = new(Int)
+		x.SetString(test.y, 0)
+		testBitset(t, x)
+	}
+	for i, test := range bitsetTests {
+		x := new(Int)
+		x.SetString(test.x, 0)
+		b := x.Bit(test.i)
+		if b != test.b {
+			t.Errorf("#%d got %v want %v", i, b, test.b)
+		}
+	}
+	z := NewInt(1)
+	z.SetBit(NewInt(0), 2, 1)
+	if z.Cmp(NewInt(4)) != 0 {
+		t.Errorf("destination leaked into result; got %s want 4", z)
+	}
+}
+
+func BenchmarkBitset(b *testing.B) {
+	z := new(Int)
+	z.SetBit(z, 512, 1)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		z.SetBit(z, i&512, 1)
+	}
+}
+
+func BenchmarkBitsetNeg(b *testing.B) {
+	z := NewInt(-1)
+	z.SetBit(z, 512, 0)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		z.SetBit(z, i&512, 0)
+	}
+}
+
+func BenchmarkBitsetOrig(b *testing.B) {
+	z := new(Int)
+	altSetBit(z, z, 512, 1)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		altSetBit(z, z, i&512, 1)
+	}
+}
+
+func BenchmarkBitsetNegOrig(b *testing.B) {
+	z := NewInt(-1)
+	altSetBit(z, z, 512, 0)
+	b.ResetTimer()
+	b.StartTimer()
+	for i := b.N - 1; i >= 0; i-- {
+		altSetBit(z, z, i&512, 0)
+	}
+}
+
+func TestBitwise(t *testing.T) {
+	x := new(Int)
+	y := new(Int)
+	for _, test := range bitwiseTests {
+		x.SetString(test.x, 0)
+		y.SetString(test.y, 0)
+
+		testBitFun(t, "and", (*Int).And, x, y, test.and)
+		testBitFunSelf(t, "and", (*Int).And, x, y, test.and)
+		testBitFun(t, "andNot", (*Int).AndNot, x, y, test.andNot)
+		testBitFunSelf(t, "andNot", (*Int).AndNot, x, y, test.andNot)
+		testBitFun(t, "or", (*Int).Or, x, y, test.or)
+		testBitFunSelf(t, "or", (*Int).Or, x, y, test.or)
+		testBitFun(t, "xor", (*Int).Xor, x, y, test.xor)
+		testBitFunSelf(t, "xor", (*Int).Xor, x, y, test.xor)
+	}
+}
+
+var notTests = []struct {
+	in  string
+	out string
+}{
+	{"0", "-1"},
+	{"1", "-2"},
+	{"7", "-8"},
+	{"0", "-1"},
+	{"-81910", "81909"},
+	{
+		"298472983472983471903246121093472394872319615612417471234712061",
+		"-298472983472983471903246121093472394872319615612417471234712062",
+	},
+}
+
+func TestNot(t *testing.T) {
+	in := new(Int)
+	out := new(Int)
+	expected := new(Int)
+	for i, test := range notTests {
+		in.SetString(test.in, 10)
+		expected.SetString(test.out, 10)
+		out = out.Not(in)
+		if out.Cmp(expected) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, expected)
+		}
+		out = out.Not(out)
+		if out.Cmp(in) != 0 {
+			t.Errorf("#%d: got %s want %s", i, out, in)
+		}
+	}
+}
+
+var modInverseTests = []struct {
+	element string
+	prime   string
+}{
+	{"1", "7"},
+	{"1", "13"},
+	{"239487239847", "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"},
+}
+
+func TestModInverse(t *testing.T) {
+	var element, prime Int
+	one := NewInt(1)
+	for i, test := range modInverseTests {
+		(&element).SetString(test.element, 10)
+		(&prime).SetString(test.prime, 10)
+		inverse := new(Int).ModInverse(&element, &prime)
+		inverse.Mul(inverse, &element)
+		inverse.Mod(inverse, &prime)
+		if inverse.Cmp(one) != 0 {
+			t.Errorf("#%d: failed (e·e^(-1)=%s)", i, inverse)
+		}
+	}
+}
+
+// used by TestIntGobEncoding and TestRatGobEncoding
+var gobEncodingTests = []string{
+	"0",
+	"1",
+	"2",
+	"10",
+	"42",
+	"1234567890",
+	"298472983472983471903246121093472394872319615612417471234712061",
+}
+
+func TestIntGobEncoding(t *testing.T) {
+	var medium bytes.Buffer
+	enc := gob.NewEncoder(&medium)
+	dec := gob.NewDecoder(&medium)
+	for i, test := range gobEncodingTests {
+		for j := 0; j < 2; j++ {
+			medium.Reset() // empty buffer for each test case (in case of failures)
+			stest := test
+			if j != 0 {
+				// negative numbers
+				stest = "-" + test
+			}
+			var tx Int
+			tx.SetString(stest, 10)
+			if err := enc.Encode(&tx); err != nil {
+				t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
+			}
+			var rx Int
+			if err := dec.Decode(&rx); err != nil {
+				t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
+			}
+		}
+	}
+}
+
+func TestIssue2607(t *testing.T) {
+	// This code sequence used to hang.
+	n := NewInt(10)
+	n.Rand(rand.New(rand.NewSource(9)), n)
+}
diff --git a/src/pkg/math/big/nat.go b/src/pkg/math/big/nat.go
new file mode 100644
index 0000000..16f6ce9
--- /dev/null
+++ b/src/pkg/math/big/nat.go
@@ -0,0 +1,1416 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package big implements multi-precision arithmetic (big numbers).
+// The following numeric types are supported:
+//
+//	- Int	signed integers
+//	- Rat	rational numbers
+//
+// All methods on Int take the result as the receiver; if it is one
+// of the operands it may be overwritten (and its memory reused).
+// To enable chaining of operations, the result is also returned.
+//
+package big
+
+// This file contains operations on unsigned multi-precision integers.
+// These are the building blocks for the operations on signed integers
+// and rationals.
+
+import (
+	"errors"
+	"io"
+	"math"
+	"math/rand"
+	"sync"
+)
+
+// An unsigned integer x of the form
+//
+//   x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0]
+//
+// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n,
+// with the digits x[i] as the slice elements.
+//
+// A number is normalized if the slice contains no leading 0 digits.
+// During arithmetic operations, denormalized values may occur but are
+// always normalized before returning the final result. The normalized
+// representation of 0 is the empty or nil slice (length = 0).
+//
+type nat []Word
+
+var (
+	natOne = nat{1}
+	natTwo = nat{2}
+	natTen = nat{10}
+)
+
+func (z nat) clear() {
+	for i := range z {
+		z[i] = 0
+	}
+}
+
+func (z nat) norm() nat {
+	i := len(z)
+	for i > 0 && z[i-1] == 0 {
+		i--
+	}
+	return z[0:i]
+}
+
+func (z nat) make(n int) nat {
+	if n <= cap(z) {
+		return z[0:n] // reuse z
+	}
+	// Choosing a good value for e has significant performance impact
+	// because it increases the chance that a value can be reused.
+	const e = 4 // extra capacity
+	return make(nat, n, n+e)
+}
+
+func (z nat) setWord(x Word) nat {
+	if x == 0 {
+		return z.make(0)
+	}
+	z = z.make(1)
+	z[0] = x
+	return z
+}
+
+func (z nat) setUint64(x uint64) nat {
+	// single-digit values
+	if w := Word(x); uint64(w) == x {
+		return z.setWord(w)
+	}
+
+	// compute number of words n required to represent x
+	n := 0
+	for t := x; t > 0; t >>= _W {
+		n++
+	}
+
+	// split x into n words
+	z = z.make(n)
+	for i := range z {
+		z[i] = Word(x & _M)
+		x >>= _W
+	}
+
+	return z
+}
+
+func (z nat) set(x nat) nat {
+	z = z.make(len(x))
+	copy(z, x)
+	return z
+}
+
+func (z nat) add(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+
+	switch {
+	case m < n:
+		return z.add(y, x)
+	case m == 0:
+		// n == 0 because m >= n; result is 0
+		return z.make(0)
+	case n == 0:
+		// result is x
+		return z.set(x)
+	}
+	// m > 0
+
+	z = z.make(m + 1)
+	c := addVV(z[0:n], x, y)
+	if m > n {
+		c = addVW(z[n:m], x[n:], c)
+	}
+	z[m] = c
+
+	return z.norm()
+}
+
+func (z nat) sub(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+
+	switch {
+	case m < n:
+		panic("underflow")
+	case m == 0:
+		// n == 0 because m >= n; result is 0
+		return z.make(0)
+	case n == 0:
+		// result is x
+		return z.set(x)
+	}
+	// m > 0
+
+	z = z.make(m)
+	c := subVV(z[0:n], x, y)
+	if m > n {
+		c = subVW(z[n:], x[n:], c)
+	}
+	if c != 0 {
+		panic("underflow")
+	}
+
+	return z.norm()
+}
+
+func (x nat) cmp(y nat) (r int) {
+	m := len(x)
+	n := len(y)
+	if m != n || m == 0 {
+		switch {
+		case m < n:
+			r = -1
+		case m > n:
+			r = 1
+		}
+		return
+	}
+
+	i := m - 1
+	for i > 0 && x[i] == y[i] {
+		i--
+	}
+
+	switch {
+	case x[i] < y[i]:
+		r = -1
+	case x[i] > y[i]:
+		r = 1
+	}
+	return
+}
+
+func (z nat) mulAddWW(x nat, y, r Word) nat {
+	m := len(x)
+	if m == 0 || y == 0 {
+		return z.setWord(r) // result is r
+	}
+	// m > 0
+
+	z = z.make(m + 1)
+	z[m] = mulAddVWW(z[0:m], x, y, r)
+
+	return z.norm()
+}
+
+// basicMul multiplies x and y and leaves the result in z.
+// The (non-normalized) result is placed in z[0 : len(x) + len(y)].
+func basicMul(z, x, y nat) {
+	z[0 : len(x)+len(y)].clear() // initialize z
+	for i, d := range y {
+		if d != 0 {
+			z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d)
+		}
+	}
+}
+
+// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks.
+// Factored out for readability - do not use outside karatsuba.
+func karatsubaAdd(z, x nat, n int) {
+	if c := addVV(z[0:n], z, x); c != 0 {
+		addVW(z[n:n+n>>1], z[n:], c)
+	}
+}
+
+// Like karatsubaAdd, but does subtract.
+func karatsubaSub(z, x nat, n int) {
+	if c := subVV(z[0:n], z, x); c != 0 {
+		subVW(z[n:n+n>>1], z[n:], c)
+	}
+}
+
+// Operands that are shorter than karatsubaThreshold are multiplied using
+// "grade school" multiplication; for longer operands the Karatsuba algorithm
+// is used.
+var karatsubaThreshold int = 32 // computed by calibrate.go
+
+// karatsuba multiplies x and y and leaves the result in z.
+// Both x and y must have the same length n and n must be a
+// power of 2. The result vector z must have len(z) >= 6*n.
+// The (non-normalized) result is placed in z[0 : 2*n].
+func karatsuba(z, x, y nat) {
+	n := len(y)
+
+	// Switch to basic multiplication if numbers are odd or small.
+	// (n is always even if karatsubaThreshold is even, but be
+	// conservative)
+	if n&1 != 0 || n < karatsubaThreshold || n < 2 {
+		basicMul(z, x, y)
+		return
+	}
+	// n&1 == 0 && n >= karatsubaThreshold && n >= 2
+
+	// Karatsuba multiplication is based on the observation that
+	// for two numbers x and y with:
+	//
+	//   x = x1*b + x0
+	//   y = y1*b + y0
+	//
+	// the product x*y can be obtained with 3 products z2, z1, z0
+	// instead of 4:
+	//
+	//   x*y = x1*y1*b*b + (x1*y0 + x0*y1)*b + x0*y0
+	//       =    z2*b*b +              z1*b +    z0
+	//
+	// with:
+	//
+	//   xd = x1 - x0
+	//   yd = y0 - y1
+	//
+	//   z1 =      xd*yd                    + z1 + z0
+	//      = (x1-x0)*(y0 - y1)             + z1 + z0
+	//      = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z1 + z0
+	//      = x1*y0 -    z1 -    z0 + x0*y1 + z1 + z0
+	//      = x1*y0                 + x0*y1
+
+	// split x, y into "digits"
+	n2 := n >> 1              // n2 >= 1
+	x1, x0 := x[n2:], x[0:n2] // x = x1*b + y0
+	y1, y0 := y[n2:], y[0:n2] // y = y1*b + y0
+
+	// z is used for the result and temporary storage:
+	//
+	//   6*n     5*n     4*n     3*n     2*n     1*n     0*n
+	// z = [z2 copy|z0 copy| xd*yd | yd:xd | x1*y1 | x0*y0 ]
+	//
+	// For each recursive call of karatsuba, an unused slice of
+	// z is passed in that has (at least) half the length of the
+	// caller's z.
+
+	// compute z0 and z2 with the result "in place" in z
+	karatsuba(z, x0, y0)     // z0 = x0*y0
+	karatsuba(z[n:], x1, y1) // z2 = x1*y1
+
+	// compute xd (or the negative value if underflow occurs)
+	s := 1 // sign of product xd*yd
+	xd := z[2*n : 2*n+n2]
+	if subVV(xd, x1, x0) != 0 { // x1-x0
+		s = -s
+		subVV(xd, x0, x1) // x0-x1
+	}
+
+	// compute yd (or the negative value if underflow occurs)
+	yd := z[2*n+n2 : 3*n]
+	if subVV(yd, y0, y1) != 0 { // y0-y1
+		s = -s
+		subVV(yd, y1, y0) // y1-y0
+	}
+
+	// p = (x1-x0)*(y0-y1) == x1*y0 - x1*y1 - x0*y0 + x0*y1 for s > 0
+	// p = (x0-x1)*(y0-y1) == x0*y0 - x0*y1 - x1*y0 + x1*y1 for s < 0
+	p := z[n*3:]
+	karatsuba(p, xd, yd)
+
+	// save original z2:z0
+	// (ok to use upper half of z since we're done recursing)
+	r := z[n*4:]
+	copy(r, z)
+
+	// add up all partial products
+	//
+	//   2*n     n     0
+	// z = [ z2  | z0  ]
+	//   +    [ z0  ]
+	//   +    [ z2  ]
+	//   +    [  p  ]
+	//
+	karatsubaAdd(z[n2:], r, n)
+	karatsubaAdd(z[n2:], r[n:], n)
+	if s > 0 {
+		karatsubaAdd(z[n2:], p, n)
+	} else {
+		karatsubaSub(z[n2:], p, n)
+	}
+}
+
+// alias returns true if x and y share the same base array.
+func alias(x, y nat) bool {
+	return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
+}
+
+// addAt implements z += x*(1<<(_W*i)); z must be long enough.
+// (we don't use nat.add because we need z to stay the same
+// slice, and we don't need to normalize z after each addition)
+func addAt(z, x nat, i int) {
+	if n := len(x); n > 0 {
+		if c := addVV(z[i:i+n], z[i:], x); c != 0 {
+			j := i + n
+			if j < len(z) {
+				addVW(z[j:], z[j:], c)
+			}
+		}
+	}
+}
+
+func max(x, y int) int {
+	if x > y {
+		return x
+	}
+	return y
+}
+
+// karatsubaLen computes an approximation to the maximum k <= n such that
+// k = p<<i for a number p <= karatsubaThreshold and an i >= 0. Thus, the
+// result is the largest number that can be divided repeatedly by 2 before
+// becoming about the value of karatsubaThreshold.
+func karatsubaLen(n int) int {
+	i := uint(0)
+	for n > karatsubaThreshold {
+		n >>= 1
+		i++
+	}
+	return n << i
+}
+
+func (z nat) mul(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+
+	switch {
+	case m < n:
+		return z.mul(y, x)
+	case m == 0 || n == 0:
+		return z.make(0)
+	case n == 1:
+		return z.mulAddWW(x, y[0], 0)
+	}
+	// m >= n > 1
+
+	// determine if z can be reused
+	if alias(z, x) || alias(z, y) {
+		z = nil // z is an alias for x or y - cannot reuse
+	}
+
+	// use basic multiplication if the numbers are small
+	if n < karatsubaThreshold || n < 2 {
+		z = z.make(m + n)
+		basicMul(z, x, y)
+		return z.norm()
+	}
+	// m >= n && n >= karatsubaThreshold && n >= 2
+
+	// determine Karatsuba length k such that
+	//
+	//   x = x1*b + x0
+	//   y = y1*b + y0  (and k <= len(y), which implies k <= len(x))
+	//   b = 1<<(_W*k)  ("base" of digits xi, yi)
+	//
+	k := karatsubaLen(n)
+	// k <= n
+
+	// multiply x0 and y0 via Karatsuba
+	x0 := x[0:k]              // x0 is not normalized
+	y0 := y[0:k]              // y0 is not normalized
+	z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y
+	karatsuba(z, x0, y0)
+	z = z[0 : m+n] // z has final length but may be incomplete, upper portion is garbage
+
+	// If x1 and/or y1 are not 0, add missing terms to z explicitly:
+	//
+	//     m+n       2*k       0
+	//   z = [   ...   | x0*y0 ]
+	//     +   [ x1*y1 ]
+	//     +   [ x1*y0 ]
+	//     +   [ x0*y1 ]
+	//
+	if k < n || m != n {
+		x1 := x[k:] // x1 is normalized because x is
+		y1 := y[k:] // y1 is normalized because y is
+		var t nat
+		t = t.mul(x1, y1)
+		copy(z[2*k:], t)
+		z[2*k+len(t):].clear() // upper portion of z is garbage
+		t = t.mul(x1, y0.norm())
+		addAt(z, t, k)
+		t = t.mul(x0.norm(), y1)
+		addAt(z, t, k)
+	}
+
+	return z.norm()
+}
+
+// mulRange computes the product of all the unsigned integers in the
+// range [a, b] inclusively. If a > b (empty range), the result is 1.
+func (z nat) mulRange(a, b uint64) nat {
+	switch {
+	case a == 0:
+		// cut long ranges short (optimization)
+		return z.setUint64(0)
+	case a > b:
+		return z.setUint64(1)
+	case a == b:
+		return z.setUint64(a)
+	case a+1 == b:
+		return z.mul(nat(nil).setUint64(a), nat(nil).setUint64(b))
+	}
+	m := (a + b) / 2
+	return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b))
+}
+
+// q = (x-r)/y, with 0 <= r < y
+func (z nat) divW(x nat, y Word) (q nat, r Word) {
+	m := len(x)
+	switch {
+	case y == 0:
+		panic("division by zero")
+	case y == 1:
+		q = z.set(x) // result is x
+		return
+	case m == 0:
+		q = z.make(0) // result is 0
+		return
+	}
+	// m > 0
+	z = z.make(m)
+	r = divWVW(z, 0, x, y)
+	q = z.norm()
+	return
+}
+
+func (z nat) div(z2, u, v nat) (q, r nat) {
+	if len(v) == 0 {
+		panic("division by zero")
+	}
+
+	if u.cmp(v) < 0 {
+		q = z.make(0)
+		r = z2.set(u)
+		return
+	}
+
+	if len(v) == 1 {
+		var rprime Word
+		q, rprime = z.divW(u, v[0])
+		if rprime > 0 {
+			r = z2.make(1)
+			r[0] = rprime
+		} else {
+			r = z2.make(0)
+		}
+		return
+	}
+
+	q, r = z.divLarge(z2, u, v)
+	return
+}
+
+// q = (uIn-r)/v, with 0 <= r < y
+// Uses z as storage for q, and u as storage for r if possible.
+// See Knuth, Volume 2, section 4.3.1, Algorithm D.
+// Preconditions:
+//    len(v) >= 2
+//    len(uIn) >= len(v)
+func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
+	n := len(v)
+	m := len(uIn) - n
+
+	// determine if z can be reused
+	// TODO(gri) should find a better solution - this if statement
+	//           is very costly (see e.g. time pidigits -s -n 10000)
+	if alias(z, uIn) || alias(z, v) {
+		z = nil // z is an alias for uIn or v - cannot reuse
+	}
+	q = z.make(m + 1)
+
+	qhatv := make(nat, n+1)
+	if alias(u, uIn) || alias(u, v) {
+		u = nil // u is an alias for uIn or v - cannot reuse
+	}
+	u = u.make(len(uIn) + 1)
+	u.clear()
+
+	// D1.
+	shift := leadingZeros(v[n-1])
+	if shift > 0 {
+		// do not modify v, it may be used by another goroutine simultaneously
+		v1 := make(nat, n)
+		shlVU(v1, v, shift)
+		v = v1
+	}
+	u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift)
+
+	// D2.
+	for j := m; j >= 0; j-- {
+		// D3.
+		qhat := Word(_M)
+		if u[j+n] != v[n-1] {
+			var rhat Word
+			qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1])
+
+			// x1 | x2 = q̂v_{n-2}
+			x1, x2 := mulWW(qhat, v[n-2])
+			// test if q̂v_{n-2} > br̂ + u_{j+n-2}
+			for greaterThan(x1, x2, rhat, u[j+n-2]) {
+				qhat--
+				prevRhat := rhat
+				rhat += v[n-1]
+				// v[n-1] >= 0, so this tests for overflow.
+				if rhat < prevRhat {
+					break
+				}
+				x1, x2 = mulWW(qhat, v[n-2])
+			}
+		}
+
+		// D4.
+		qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0)
+
+		c := subVV(u[j:j+len(qhatv)], u[j:], qhatv)
+		if c != 0 {
+			c := addVV(u[j:j+n], u[j:], v)
+			u[j+n] += c
+			qhat--
+		}
+
+		q[j] = qhat
+	}
+
+	q = q.norm()
+	shrVU(u, u, shift)
+	r = u.norm()
+
+	return q, r
+}
+
+// Length of x in bits. x must be normalized.
+func (x nat) bitLen() int {
+	if i := len(x) - 1; i >= 0 {
+		return i*_W + bitLen(x[i])
+	}
+	return 0
+}
+
+// MaxBase is the largest number base accepted for string conversions.
+const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1
+
+func hexValue(ch rune) Word {
+	d := int(MaxBase + 1) // illegal base
+	switch {
+	case '0' <= ch && ch <= '9':
+		d = int(ch - '0')
+	case 'a' <= ch && ch <= 'z':
+		d = int(ch - 'a' + 10)
+	case 'A' <= ch && ch <= 'Z':
+		d = int(ch - 'A' + 10)
+	}
+	return Word(d)
+}
+
+// scan sets z to the natural number corresponding to the longest possible prefix
+// read from r representing an unsigned integer in a given conversion base.
+// It returns z, the actual conversion base used, and an error, if any. In the
+// error case, the value of z is undefined. The syntax follows the syntax of
+// unsigned integer literals in Go.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z nat) scan(r io.RuneScanner, base int) (nat, int, error) {
+	// reject illegal bases
+	if base < 0 || base == 1 || MaxBase < base {
+		return z, 0, errors.New("illegal number base")
+	}
+
+	// one char look-ahead
+	ch, _, err := r.ReadRune()
+	if err != nil {
+		return z, 0, err
+	}
+
+	// determine base if necessary
+	b := Word(base)
+	if base == 0 {
+		b = 10
+		if ch == '0' {
+			switch ch, _, err = r.ReadRune(); err {
+			case nil:
+				b = 8
+				switch ch {
+				case 'x', 'X':
+					b = 16
+				case 'b', 'B':
+					b = 2
+				}
+				if b == 2 || b == 16 {
+					if ch, _, err = r.ReadRune(); err != nil {
+						return z, 0, err
+					}
+				}
+			case io.EOF:
+				return z.make(0), 10, nil
+			default:
+				return z, 10, err
+			}
+		}
+	}
+
+	// convert string
+	// - group as many digits d as possible together into a "super-digit" dd with "super-base" bb
+	// - only when bb does not fit into a word anymore, do a full number mulAddWW using bb and dd
+	z = z.make(0)
+	bb := Word(1)
+	dd := Word(0)
+	for max := _M / b; ; {
+		d := hexValue(ch)
+		if d >= b {
+			r.UnreadRune() // ch does not belong to number anymore
+			break
+		}
+
+		if bb <= max {
+			bb *= b
+			dd = dd*b + d
+		} else {
+			// bb * b would overflow
+			z = z.mulAddWW(z, bb, dd)
+			bb = b
+			dd = d
+		}
+
+		if ch, _, err = r.ReadRune(); err != nil {
+			if err != io.EOF {
+				return z, int(b), err
+			}
+			break
+		}
+	}
+
+	switch {
+	case bb > 1:
+		// there was at least one mantissa digit
+		z = z.mulAddWW(z, bb, dd)
+	case base == 0 && b == 8:
+		// there was only the octal prefix 0 (possibly followed by digits > 7);
+		// return base 10, not 8
+		return z, 10, nil
+	case base != 0 || b != 8:
+		// there was neither a mantissa digit nor the octal prefix 0
+		return z, int(b), errors.New("syntax error scanning number")
+	}
+
+	return z.norm(), int(b), nil
+}
+
+// Character sets for string conversion.
+const (
+	lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
+	uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+)
+
+// decimalString returns a decimal representation of x.
+// It calls x.string with the charset "0123456789".
+func (x nat) decimalString() string {
+	return x.string(lowercaseDigits[0:10])
+}
+
+// string converts x to a string using digits from a charset; a digit with
+// value d is represented by charset[d]. The conversion base is determined
+// by len(charset), which must be >= 2 and <= 256.
+func (x nat) string(charset string) string {
+	b := Word(len(charset))
+
+	// special cases
+	switch {
+	case b < 2 || MaxBase > 256:
+		panic("illegal base")
+	case len(x) == 0:
+		return string(charset[0])
+	}
+
+	// allocate buffer for conversion
+	i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
+	s := make([]byte, i)
+
+	// convert power of two and non power of two bases separately
+	if b == b&-b {
+		// shift is base-b digit size in bits
+		shift := uint(trailingZeroBits(b)) // shift > 0 because b >= 2
+		mask := Word(1)<<shift - 1
+		w := x[0]
+		nbits := uint(_W) // number of unprocessed bits in w
+
+		// convert less-significant words
+		for k := 1; k < len(x); k++ {
+			// convert full digits
+			for nbits >= shift {
+				i--
+				s[i] = charset[w&mask]
+				w >>= shift
+				nbits -= shift
+			}
+
+			// convert any partial leading digit and advance to next word
+			if nbits == 0 {
+				// no partial digit remaining, just advance
+				w = x[k]
+				nbits = _W
+			} else {
+				// partial digit in current (k-1) and next (k) word
+				w |= x[k] << nbits
+				i--
+				s[i] = charset[w&mask]
+
+				// advance
+				w = x[k] >> (shift - nbits)
+				nbits = _W - (shift - nbits)
+			}
+		}
+
+		// convert digits of most-significant word (omit leading zeros)
+		for nbits >= 0 && w != 0 {
+			i--
+			s[i] = charset[w&mask]
+			w >>= shift
+			nbits -= shift
+		}
+
+	} else {
+		// determine "big base"; i.e., the largest possible value bb
+		// that is a power of base b and still fits into a Word
+		// (as in 10^19 for 19 decimal digits in a 64bit Word)
+		bb := b      // big base is b**ndigits
+		ndigits := 1 // number of base b digits
+		for max := Word(_M / b); bb <= max; bb *= b {
+			ndigits++ // maximize ndigits where bb = b**ndigits, bb <= _M
+		}
+
+		// construct table of successive squares of bb*leafSize to use in subdivisions
+		// result (table != nil) <=> (len(x) > leafSize > 0)
+		table := divisors(len(x), b, ndigits, bb)
+
+		// preserve x, create local copy for use by convertWords
+		q := nat(nil).set(x)
+
+		// convert q to string s in base b
+		q.convertWords(s, charset, b, ndigits, bb, table)
+
+		// strip leading zeros
+		// (x != 0; thus s must contain at least one non-zero digit
+		// and the loop will terminate)
+		i = 0
+		for zero := charset[0]; s[i] == zero; {
+			i++
+		}
+	}
+
+	return string(s[i:])
+}
+
+// Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
+// by nat/nat division using tabulated divisors. Otherwise, it is converted iteratively using
+// repeated nat/Word divison.
+//
+// The iterative method processes n Words by n divW() calls, each of which visits every Word in the 
+// incrementally shortened q for a total of n + (n-1) + (n-2) ... + 2 + 1, or n(n+1)/2 divW()'s. 
+// Recursive conversion divides q by its approximate square root, yielding two parts, each half 
+// the size of q. Using the iterative method on both halves means 2 * (n/2)(n/2 + 1)/2 divW()'s
+// plus the expensive long div(). Asymptotically, the ratio is favorable at 1/2 the divW()'s, and
+// is made better by splitting the subblocks recursively. Best is to split blocks until one more 
+// split would take longer (because of the nat/nat div()) than the twice as many divW()'s of the 
+// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the 
+// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and 
+// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for 
+// specfic hardware.
+//
+func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
+	// split larger blocks recursively
+	if table != nil {
+		// len(q) > leafSize > 0
+		var r nat
+		index := len(table) - 1
+		for len(q) > leafSize {
+			// find divisor close to sqrt(q) if possible, but in any case < q
+			maxLength := q.bitLen()     // ~= log2 q, or at of least largest possible q of this bit length
+			minLength := maxLength >> 1 // ~= log2 sqrt(q)
+			for index > 0 && table[index-1].nbits > minLength {
+				index-- // desired
+			}
+			if table[index].nbits >= maxLength && table[index].bbb.cmp(q) >= 0 {
+				index--
+				if index < 0 {
+					panic("internal inconsistency")
+				}
+			}
+
+			// split q into the two digit number (q'*bbb + r) to form independent subblocks
+			q, r = q.div(r, q, table[index].bbb)
+
+			// convert subblocks and collect results in s[:h] and s[h:]
+			h := len(s) - table[index].ndigits
+			r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
+			s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
+		}
+	}
+
+	// having split any large blocks now process the remaining (small) block iteratively
+	i := len(s)
+	var r Word
+	if b == 10 {
+		// hard-coding for 10 here speeds this up by 1.25x (allows for / and % by constants)
+		for len(q) > 0 {
+			// extract least significant, base bb "digit"
+			q, r = q.divW(q, bb)
+			for j := 0; j < ndigits && i > 0; j++ {
+				i--
+				// avoid % computation since r%10 == r - int(r/10)*10;
+				// this appears to be faster for BenchmarkString10000Base10
+				// and smaller strings (but a bit slower for larger ones)
+				t := r / 10
+				s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
+				r = t
+			}
+		}
+	} else {
+		for len(q) > 0 {
+			// extract least significant, base bb "digit"
+			q, r = q.divW(q, bb)
+			for j := 0; j < ndigits && i > 0; j++ {
+				i--
+				s[i] = charset[r%b]
+				r /= b
+			}
+		}
+	}
+
+	// prepend high-order zeroes
+	zero := charset[0]
+	for i > 0 { // while need more leading zeroes
+		i--
+		s[i] = zero
+	}
+}
+
+// Split blocks greater than leafSize Words (or set to 0 to disable recursive conversion)
+// Benchmark and configure leafSize using: gotest -test.bench="Leaf"
+//   8 and 16 effective on 3.0 GHz Xeon "Clovertown" CPU (128 byte cache lines)
+//   8 and 16 effective on 2.66 GHz Core 2 Duo "Penryn" CPU
+var leafSize int = 8 // number of Word-size binary values treat as a monolithic block
+
+type divisor struct {
+	bbb     nat // divisor
+	nbits   int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
+	ndigits int // digit length of divisor in terms of output base digits
+}
+
+var cacheBase10 [64]divisor // cached divisors for base 10
+var cacheLock sync.Mutex    // protects cacheBase10
+
+// expWW computes x**y
+func (z nat) expWW(x, y Word) nat {
+	return z.expNN(nat(nil).setWord(x), nat(nil).setWord(y), nil)
+}
+
+// construct table of powers of bb*leafSize to use in subdivisions
+func divisors(m int, b Word, ndigits int, bb Word) []divisor {
+	// only compute table when recursive conversion is enabled and x is large
+	if leafSize == 0 || m <= leafSize {
+		return nil
+	}
+
+	// determine k where (bb**leafSize)**(2**k) >= sqrt(x)
+	k := 1
+	for words := leafSize; words < m>>1 && k < len(cacheBase10); words <<= 1 {
+		k++
+	}
+
+	// create new table of divisors or extend and reuse existing table as appropriate
+	var table []divisor
+	var cached bool
+	switch b {
+	case 10:
+		table = cacheBase10[0:k] // reuse old table for this conversion
+		cached = true
+	default:
+		table = make([]divisor, k) // new table for this conversion
+	}
+
+	// extend table
+	if table[k-1].ndigits == 0 {
+		if cached {
+			cacheLock.Lock() // begin critical section
+		}
+
+		// add new entries as needed
+		var larger nat
+		for i := 0; i < k; i++ {
+			if table[i].ndigits == 0 {
+				if i == 0 {
+					table[i].bbb = nat(nil).expWW(bb, Word(leafSize))
+					table[i].ndigits = ndigits * leafSize
+				} else {
+					table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
+					table[i].ndigits = 2 * table[i-1].ndigits
+				}
+
+				// optimization: exploit aggregated extra bits in macro blocks
+				larger = nat(nil).set(table[i].bbb)
+				for mulAddVWW(larger, larger, b, 0) == 0 {
+					table[i].bbb = table[i].bbb.set(larger)
+					table[i].ndigits++
+				}
+
+				table[i].nbits = table[i].bbb.bitLen()
+			}
+		}
+
+		if cached {
+			cacheLock.Unlock() // end critical section
+		}
+	}
+
+	return table
+}
+
+const deBruijn32 = 0x077CB531
+
+var deBruijn32Lookup = []byte{
+	0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+	31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
+}
+
+const deBruijn64 = 0x03f79d71b4ca8b09
+
+var deBruijn64Lookup = []byte{
+	0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
+	62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
+	63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
+	54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
+}
+
+// trailingZeroBits returns the number of consecutive zero bits on the right
+// side of the given Word.
+// See Knuth, volume 4, section 7.3.1
+func trailingZeroBits(x Word) int {
+	// x & -x leaves only the right-most bit set in the word. Let k be the
+	// index of that bit. Since only a single bit is set, the value is two
+	// to the power of k. Multiplying by a power of two is equivalent to
+	// left shifting, in this case by k bits.  The de Bruijn constant is
+	// such that all six bit, consecutive substrings are distinct.
+	// Therefore, if we have a left shifted version of this constant we can
+	// find by how many bits it was shifted by looking at which six bit
+	// substring ended up at the top of the word.
+	switch _W {
+	case 32:
+		return int(deBruijn32Lookup[((x&-x)*deBruijn32)>>27])
+	case 64:
+		return int(deBruijn64Lookup[((x&-x)*(deBruijn64&_M))>>58])
+	default:
+		panic("Unknown word size")
+	}
+
+	return 0
+}
+
+// z = x << s
+func (z nat) shl(x nat, s uint) nat {
+	m := len(x)
+	if m == 0 {
+		return z.make(0)
+	}
+	// m > 0
+
+	n := m + int(s/_W)
+	z = z.make(n + 1)
+	z[n] = shlVU(z[n-m:n], x, s%_W)
+	z[0 : n-m].clear()
+
+	return z.norm()
+}
+
+// z = x >> s
+func (z nat) shr(x nat, s uint) nat {
+	m := len(x)
+	n := m - int(s/_W)
+	if n <= 0 {
+		return z.make(0)
+	}
+	// n > 0
+
+	z = z.make(n)
+	shrVU(z, x[m-n:], s%_W)
+
+	return z.norm()
+}
+
+func (z nat) setBit(x nat, i uint, b uint) nat {
+	j := int(i / _W)
+	m := Word(1) << (i % _W)
+	n := len(x)
+	switch b {
+	case 0:
+		z = z.make(n)
+		copy(z, x)
+		if j >= n {
+			// no need to grow
+			return z
+		}
+		z[j] &^= m
+		return z.norm()
+	case 1:
+		if j >= n {
+			z = z.make(j + 1)
+			z[n:].clear()
+		} else {
+			z = z.make(n)
+		}
+		copy(z, x)
+		z[j] |= m
+		// no need to normalize
+		return z
+	}
+	panic("set bit is not 0 or 1")
+}
+
+func (z nat) bit(i uint) uint {
+	j := int(i / _W)
+	if j >= len(z) {
+		return 0
+	}
+	return uint(z[j] >> (i % _W) & 1)
+}
+
+func (z nat) and(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+	if m > n {
+		m = n
+	}
+	// m <= n
+
+	z = z.make(m)
+	for i := 0; i < m; i++ {
+		z[i] = x[i] & y[i]
+	}
+
+	return z.norm()
+}
+
+func (z nat) andNot(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+	if n > m {
+		n = m
+	}
+	// m >= n
+
+	z = z.make(m)
+	for i := 0; i < n; i++ {
+		z[i] = x[i] &^ y[i]
+	}
+	copy(z[n:m], x[n:m])
+
+	return z.norm()
+}
+
+func (z nat) or(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+	s := x
+	if m < n {
+		n, m = m, n
+		s = y
+	}
+	// m >= n
+
+	z = z.make(m)
+	for i := 0; i < n; i++ {
+		z[i] = x[i] | y[i]
+	}
+	copy(z[n:m], s[n:m])
+
+	return z.norm()
+}
+
+func (z nat) xor(x, y nat) nat {
+	m := len(x)
+	n := len(y)
+	s := x
+	if m < n {
+		n, m = m, n
+		s = y
+	}
+	// m >= n
+
+	z = z.make(m)
+	for i := 0; i < n; i++ {
+		z[i] = x[i] ^ y[i]
+	}
+	copy(z[n:m], s[n:m])
+
+	return z.norm()
+}
+
+// greaterThan returns true iff (x1<<_W + x2) > (y1<<_W + y2)
+func greaterThan(x1, x2, y1, y2 Word) bool {
+	return x1 > y1 || x1 == y1 && x2 > y2
+}
+
+// modW returns x % d.
+func (x nat) modW(d Word) (r Word) {
+	// TODO(agl): we don't actually need to store the q value.
+	var q nat
+	q = q.make(len(x))
+	return divWVW(q, 0, x, d)
+}
+
+// powersOfTwoDecompose finds q and k with x = q * 1<<k and q is odd, or q and k are 0.
+func (x nat) powersOfTwoDecompose() (q nat, k int) {
+	if len(x) == 0 {
+		return x, 0
+	}
+
+	// One of the words must be non-zero by definition,
+	// so this loop will terminate with i < len(x), and
+	// i is the number of 0 words.
+	i := 0
+	for x[i] == 0 {
+		i++
+	}
+	n := trailingZeroBits(x[i]) // x[i] != 0
+
+	q = make(nat, len(x)-i)
+	shrVU(q, x[i:], uint(n))
+
+	q = q.norm()
+	k = i*_W + n
+	return
+}
+
+// random creates a random integer in [0..limit), using the space in z if
+// possible. n is the bit length of limit.
+func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
+	if alias(z, limit) {
+		z = nil // z is an alias for limit - cannot reuse
+	}
+	z = z.make(len(limit))
+
+	bitLengthOfMSW := uint(n % _W)
+	if bitLengthOfMSW == 0 {
+		bitLengthOfMSW = _W
+	}
+	mask := Word((1 << bitLengthOfMSW) - 1)
+
+	for {
+		for i := range z {
+			switch _W {
+			case 32:
+				z[i] = Word(rand.Uint32())
+			case 64:
+				z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32
+			}
+		}
+
+		z[len(limit)-1] &= mask
+
+		if z.cmp(limit) < 0 {
+			break
+		}
+	}
+
+	return z.norm()
+}
+
+// If m != nil, expNN calculates x**y mod m. Otherwise it calculates x**y. It
+// reuses the storage of z if possible.
+func (z nat) expNN(x, y, m nat) nat {
+	if alias(z, x) || alias(z, y) {
+		// We cannot allow in place modification of x or y.
+		z = nil
+	}
+
+	if len(y) == 0 {
+		z = z.make(1)
+		z[0] = 1
+		return z
+	}
+
+	if m != nil {
+		// We likely end up being as long as the modulus.
+		z = z.make(len(m))
+	}
+	z = z.set(x)
+	v := y[len(y)-1]
+	// It's invalid for the most significant word to be zero, therefore we
+	// will find a one bit.
+	shift := leadingZeros(v) + 1
+	v <<= shift
+	var q nat
+
+	const mask = 1 << (_W - 1)
+
+	// We walk through the bits of the exponent one by one. Each time we
+	// see a bit, we square, thus doubling the power. If the bit is a one,
+	// we also multiply by x, thus adding one to the power.
+
+	w := _W - int(shift)
+	for j := 0; j < w; j++ {
+		z = z.mul(z, z)
+
+		if v&mask != 0 {
+			z = z.mul(z, x)
+		}
+
+		if m != nil {
+			q, z = q.div(z, z, m)
+		}
+
+		v <<= 1
+	}
+
+	for i := len(y) - 2; i >= 0; i-- {
+		v = y[i]
+
+		for j := 0; j < _W; j++ {
+			z = z.mul(z, z)
+
+			if v&mask != 0 {
+				z = z.mul(z, x)
+			}
+
+			if m != nil {
+				q, z = q.div(z, z, m)
+			}
+
+			v <<= 1
+		}
+	}
+
+	return z.norm()
+}
+
+// probablyPrime performs reps Miller-Rabin tests to check whether n is prime.
+// If it returns true, n is prime with probability 1 - 1/4^reps.
+// If it returns false, n is not prime.
+func (n nat) probablyPrime(reps int) bool {
+	if len(n) == 0 {
+		return false
+	}
+
+	if len(n) == 1 {
+		if n[0] < 2 {
+			return false
+		}
+
+		if n[0]%2 == 0 {
+			return n[0] == 2
+		}
+
+		// We have to exclude these cases because we reject all
+		// multiples of these numbers below.
+		switch n[0] {
+		case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53:
+			return true
+		}
+	}
+
+	const primesProduct32 = 0xC0CFD797         // Π {p ∈ primes, 2 < p <= 29}
+	const primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53}
+
+	var r Word
+	switch _W {
+	case 32:
+		r = n.modW(primesProduct32)
+	case 64:
+		r = n.modW(primesProduct64 & _M)
+	default:
+		panic("Unknown word size")
+	}
+
+	if r%3 == 0 || r%5 == 0 || r%7 == 0 || r%11 == 0 ||
+		r%13 == 0 || r%17 == 0 || r%19 == 0 || r%23 == 0 || r%29 == 0 {
+		return false
+	}
+
+	if _W == 64 && (r%31 == 0 || r%37 == 0 || r%41 == 0 ||
+		r%43 == 0 || r%47 == 0 || r%53 == 0) {
+		return false
+	}
+
+	nm1 := nat(nil).sub(n, natOne)
+	// 1<<k * q = nm1;
+	q, k := nm1.powersOfTwoDecompose()
+
+	nm3 := nat(nil).sub(nm1, natTwo)
+	rand := rand.New(rand.NewSource(int64(n[0])))
+
+	var x, y, quotient nat
+	nm3Len := nm3.bitLen()
+
+NextRandom:
+	for i := 0; i < reps; i++ {
+		x = x.random(rand, nm3, nm3Len)
+		x = x.add(x, natTwo)
+		y = y.expNN(x, q, n)
+		if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
+			continue
+		}
+		for j := 1; j < k; j++ {
+			y = y.mul(y, y)
+			quotient, y = quotient.div(y, y, n)
+			if y.cmp(nm1) == 0 {
+				continue NextRandom
+			}
+			if y.cmp(natOne) == 0 {
+				return false
+			}
+		}
+		return false
+	}
+
+	return true
+}
+
+// bytes writes the value of z into buf using big-endian encoding.
+// len(buf) must be >= len(z)*_S. The value of z is encoded in the
+// slice buf[i:]. The number i of unused bytes at the beginning of
+// buf is returned as result.
+func (z nat) bytes(buf []byte) (i int) {
+	i = len(buf)
+	for _, d := range z {
+		for j := 0; j < _S; j++ {
+			i--
+			buf[i] = byte(d)
+			d >>= 8
+		}
+	}
+
+	for i < len(buf) && buf[i] == 0 {
+		i++
+	}
+
+	return
+}
+
+// setBytes interprets buf as the bytes of a big-endian unsigned
+// integer, sets z to that value, and returns z.
+func (z nat) setBytes(buf []byte) nat {
+	z = z.make((len(buf) + _S - 1) / _S)
+
+	k := 0
+	s := uint(0)
+	var d Word
+	for i := len(buf); i > 0; i-- {
+		d |= Word(buf[i-1]) << s
+		if s += 8; s == _S*8 {
+			z[k] = d
+			k++
+			s = 0
+			d = 0
+		}
+	}
+	if k < len(z) {
+		z[k] = d
+	}
+
+	return z.norm()
+}
diff --git a/src/pkg/math/big/nat_test.go b/src/pkg/math/big/nat_test.go
new file mode 100644
index 0000000..25e3927
--- /dev/null
+++ b/src/pkg/math/big/nat_test.go
@@ -0,0 +1,660 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+	"io"
+	"strings"
+	"testing"
+)
+
+var cmpTests = []struct {
+	x, y nat
+	r    int
+}{
+	{nil, nil, 0},
+	{nil, nat(nil), 0},
+	{nat(nil), nil, 0},
+	{nat(nil), nat(nil), 0},
+	{nat{0}, nat{0}, 0},
+	{nat{0}, nat{1}, -1},
+	{nat{1}, nat{0}, 1},
+	{nat{1}, nat{1}, 0},
+	{nat{0, _M}, nat{1}, 1},
+	{nat{1}, nat{0, _M}, -1},
+	{nat{1, _M}, nat{0, _M}, 1},
+	{nat{0, _M}, nat{1, _M}, -1},
+	{nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1},
+	{nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1},
+}
+
+func TestCmp(t *testing.T) {
+	for i, a := range cmpTests {
+		r := a.x.cmp(a.y)
+		if r != a.r {
+			t.Errorf("#%d got r = %v; want %v", i, r, a.r)
+		}
+	}
+}
+
+type funNN func(z, x, y nat) nat
+type argNN struct {
+	z, x, y nat
+}
+
+var sumNN = []argNN{
+	{},
+	{nat{1}, nil, nat{1}},
+	{nat{1111111110}, nat{123456789}, nat{987654321}},
+	{nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}},
+	{nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}},
+	{nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}},
+}
+
+var prodNN = []argNN{
+	{},
+	{nil, nil, nil},
+	{nil, nat{991}, nil},
+	{nat{991}, nat{991}, nat{1}},
+	{nat{991 * 991}, nat{991}, nat{991}},
+	{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}},
+	{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}},
+	{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}},
+}
+
+func TestSet(t *testing.T) {
+	for _, a := range sumNN {
+		z := nat(nil).set(a.z)
+		if z.cmp(a.z) != 0 {
+			t.Errorf("got z = %v; want %v", z, a.z)
+		}
+	}
+}
+
+func testFunNN(t *testing.T, msg string, f funNN, a argNN) {
+	z := f(nil, a.x, a.y)
+	if z.cmp(a.z) != 0 {
+		t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z)
+	}
+}
+
+func TestFunNN(t *testing.T) {
+	for _, a := range sumNN {
+		arg := a
+		testFunNN(t, "add", nat.add, arg)
+
+		arg = argNN{a.z, a.y, a.x}
+		testFunNN(t, "add symmetric", nat.add, arg)
+
+		arg = argNN{a.x, a.z, a.y}
+		testFunNN(t, "sub", nat.sub, arg)
+
+		arg = argNN{a.y, a.z, a.x}
+		testFunNN(t, "sub symmetric", nat.sub, arg)
+	}
+
+	for _, a := range prodNN {
+		arg := a
+		testFunNN(t, "mul", nat.mul, arg)
+
+		arg = argNN{a.z, a.y, a.x}
+		testFunNN(t, "mul symmetric", nat.mul, arg)
+	}
+}
+
+var mulRangesN = []struct {
+	a, b uint64
+	prod string
+}{
+	{0, 0, "0"},
+	{1, 1, "1"},
+	{1, 2, "2"},
+	{1, 3, "6"},
+	{10, 10, "10"},
+	{0, 100, "0"},
+	{0, 1e9, "0"},
+	{1, 0, "1"},                    // empty range
+	{100, 1, "1"},                  // empty range
+	{1, 10, "3628800"},             // 10!
+	{1, 20, "2432902008176640000"}, // 20!
+	{1, 100,
+		"933262154439441526816992388562667004907159682643816214685929" +
+			"638952175999932299156089414639761565182862536979208272237582" +
+			"51185210916864000000000000000000000000", // 100!
+	},
+}
+
+func TestMulRangeN(t *testing.T) {
+	for i, r := range mulRangesN {
+		prod := nat(nil).mulRange(r.a, r.b).decimalString()
+		if prod != r.prod {
+			t.Errorf("#%d: got %s; want %s", i, prod, r.prod)
+		}
+	}
+}
+
+var mulArg, mulTmp nat
+
+func init() {
+	const n = 1000
+	mulArg = make(nat, n)
+	for i := 0; i < n; i++ {
+		mulArg[i] = _M
+	}
+}
+
+func benchmarkMulLoad() {
+	for j := 1; j <= 10; j++ {
+		x := mulArg[0 : j*100]
+		mulTmp.mul(x, x)
+	}
+}
+
+func BenchmarkMul(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		benchmarkMulLoad()
+	}
+}
+
+func toString(x nat, charset string) string {
+	base := len(charset)
+
+	// special cases
+	switch {
+	case base < 2:
+		panic("illegal base")
+	case len(x) == 0:
+		return string(charset[0])
+	}
+
+	// allocate buffer for conversion
+	i := x.bitLen()/log2(Word(base)) + 1 // +1: round up
+	s := make([]byte, i)
+
+	// don't destroy x
+	q := nat(nil).set(x)
+
+	// convert
+	for len(q) > 0 {
+		i--
+		var r Word
+		q, r = q.divW(q, Word(base))
+		s[i] = charset[r]
+	}
+
+	return string(s[i:])
+}
+
+var strTests = []struct {
+	x nat    // nat value to be converted
+	c string // conversion charset
+	s string // expected result
+}{
+	{nil, "01", "0"},
+	{nat{1}, "01", "1"},
+	{nat{0xc5}, "01", "11000101"},
+	{nat{03271}, lowercaseDigits[0:8], "3271"},
+	{nat{10}, lowercaseDigits[0:10], "10"},
+	{nat{1234567890}, uppercaseDigits[0:10], "1234567890"},
+	{nat{0xdeadbeef}, lowercaseDigits[0:16], "deadbeef"},
+	{nat{0xdeadbeef}, uppercaseDigits[0:16], "DEADBEEF"},
+	{nat{0x229be7}, lowercaseDigits[0:17], "1a2b3c"},
+	{nat{0x309663e6}, uppercaseDigits[0:32], "O9COV6"},
+}
+
+func TestString(t *testing.T) {
+	for _, a := range strTests {
+		s := a.x.string(a.c)
+		if s != a.s {
+			t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
+		}
+
+		x, b, err := nat(nil).scan(strings.NewReader(a.s), len(a.c))
+		if x.cmp(a.x) != 0 {
+			t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
+		}
+		if b != len(a.c) {
+			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
+		}
+		if err != nil {
+			t.Errorf("scan%+v\n\tgot error = %s", a, err)
+		}
+	}
+}
+
+var natScanTests = []struct {
+	s    string // string to be scanned
+	base int    // input base
+	x    nat    // expected nat
+	b    int    // expected base
+	ok   bool   // expected success
+	next rune   // next character (or 0, if at EOF)
+}{
+	// error: illegal base
+	{base: -1},
+	{base: 1},
+	{base: 37},
+
+	// error: no mantissa
+	{},
+	{s: "?"},
+	{base: 10},
+	{base: 36},
+	{s: "?", base: 10},
+	{s: "0x"},
+	{s: "345", base: 2},
+
+	// no errors
+	{"0", 0, nil, 10, true, 0},
+	{"0", 10, nil, 10, true, 0},
+	{"0", 36, nil, 36, true, 0},
+	{"1", 0, nat{1}, 10, true, 0},
+	{"1", 10, nat{1}, 10, true, 0},
+	{"0 ", 0, nil, 10, true, ' '},
+	{"08", 0, nil, 10, true, '8'},
+	{"018", 0, nat{1}, 8, true, '8'},
+	{"0b1", 0, nat{1}, 2, true, 0},
+	{"0b11000101", 0, nat{0xc5}, 2, true, 0},
+	{"03271", 0, nat{03271}, 8, true, 0},
+	{"10ab", 0, nat{10}, 10, true, 'a'},
+	{"1234567890", 0, nat{1234567890}, 10, true, 0},
+	{"xyz", 36, nat{(33*36+34)*36 + 35}, 36, true, 0},
+	{"xyz?", 36, nat{(33*36+34)*36 + 35}, 36, true, '?'},
+	{"0x", 16, nil, 16, true, 'x'},
+	{"0xdeadbeef", 0, nat{0xdeadbeef}, 16, true, 0},
+	{"0XDEADBEEF", 0, nat{0xdeadbeef}, 16, true, 0},
+}
+
+func TestScanBase(t *testing.T) {
+	for _, a := range natScanTests {
+		r := strings.NewReader(a.s)
+		x, b, err := nat(nil).scan(r, a.base)
+		if err == nil && !a.ok {
+			t.Errorf("scan%+v\n\texpected error", a)
+		}
+		if err != nil {
+			if a.ok {
+				t.Errorf("scan%+v\n\tgot error = %s", a, err)
+			}
+			continue
+		}
+		if x.cmp(a.x) != 0 {
+			t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
+		}
+		if b != a.b {
+			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base)
+		}
+		next, _, err := r.ReadRune()
+		if err == io.EOF {
+			next = 0
+			err = nil
+		}
+		if err == nil && next != a.next {
+			t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next)
+		}
+	}
+}
+
+var pi = "3" +
+	"14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" +
+	"32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" +
+	"28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" +
+	"96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" +
+	"31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" +
+	"60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" +
+	"22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" +
+	"29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" +
+	"81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" +
+	"21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" +
+	"55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" +
+	"63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" +
+	"75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" +
+	"45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" +
+	"34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" +
+	"16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" +
+	"04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" +
+	"26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" +
+	"99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" +
+	"53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" +
+	"68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" +
+	"13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" +
+	"88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" +
+	"79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" +
+	"68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" +
+	"21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" +
+	"06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" +
+	"14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" +
+	"21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" +
+	"05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" +
+	"23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" +
+	"90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" +
+	"31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" +
+	"20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" +
+	"97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" +
+	"44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" +
+	"44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" +
+	"85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" +
+	"58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" +
+	"27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" +
+	"09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" +
+	"79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" +
+	"06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" +
+	"91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" +
+	"94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" +
+	"78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" +
+	"24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" +
+	"59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" +
+	"34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" +
+	"88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" +
+	"94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337"
+
+// Test case for BenchmarkScanPi.
+func TestScanPi(t *testing.T) {
+	var x nat
+	z, _, err := x.scan(strings.NewReader(pi), 10)
+	if err != nil {
+		t.Errorf("scanning pi: %s", err)
+	}
+	if s := z.decimalString(); s != pi {
+		t.Errorf("scanning pi: got %s", s)
+	}
+}
+
+func BenchmarkScanPi(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		var x nat
+		x.scan(strings.NewReader(pi), 10)
+	}
+}
+
+func BenchmarkScan10Base2(b *testing.B)     { ScanHelper(b, 2, 10, 10) }
+func BenchmarkScan100Base2(b *testing.B)    { ScanHelper(b, 2, 10, 100) }
+func BenchmarkScan1000Base2(b *testing.B)   { ScanHelper(b, 2, 10, 1000) }
+func BenchmarkScan10000Base2(b *testing.B)  { ScanHelper(b, 2, 10, 10000) }
+func BenchmarkScan100000Base2(b *testing.B) { ScanHelper(b, 2, 10, 100000) }
+
+func BenchmarkScan10Base8(b *testing.B)     { ScanHelper(b, 8, 10, 10) }
+func BenchmarkScan100Base8(b *testing.B)    { ScanHelper(b, 8, 10, 100) }
+func BenchmarkScan1000Base8(b *testing.B)   { ScanHelper(b, 8, 10, 1000) }
+func BenchmarkScan10000Base8(b *testing.B)  { ScanHelper(b, 8, 10, 10000) }
+func BenchmarkScan100000Base8(b *testing.B) { ScanHelper(b, 8, 10, 100000) }
+
+func BenchmarkScan10Base10(b *testing.B)     { ScanHelper(b, 10, 10, 10) }
+func BenchmarkScan100Base10(b *testing.B)    { ScanHelper(b, 10, 10, 100) }
+func BenchmarkScan1000Base10(b *testing.B)   { ScanHelper(b, 10, 10, 1000) }
+func BenchmarkScan10000Base10(b *testing.B)  { ScanHelper(b, 10, 10, 10000) }
+func BenchmarkScan100000Base10(b *testing.B) { ScanHelper(b, 10, 10, 100000) }
+
+func BenchmarkScan10Base16(b *testing.B)     { ScanHelper(b, 16, 10, 10) }
+func BenchmarkScan100Base16(b *testing.B)    { ScanHelper(b, 16, 10, 100) }
+func BenchmarkScan1000Base16(b *testing.B)   { ScanHelper(b, 16, 10, 1000) }
+func BenchmarkScan10000Base16(b *testing.B)  { ScanHelper(b, 16, 10, 10000) }
+func BenchmarkScan100000Base16(b *testing.B) { ScanHelper(b, 16, 10, 100000) }
+
+func ScanHelper(b *testing.B, base int, x, y Word) {
+	b.StopTimer()
+	var z nat
+	z = z.expWW(x, y)
+
+	var s string
+	s = z.string(lowercaseDigits[0:base])
+	if t := toString(z, lowercaseDigits[0:base]); t != s {
+		b.Fatalf("scanning: got %s; want %s", s, t)
+	}
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		z.scan(strings.NewReader(s), base)
+	}
+}
+
+func BenchmarkString10Base2(b *testing.B)     { StringHelper(b, 2, 10, 10) }
+func BenchmarkString100Base2(b *testing.B)    { StringHelper(b, 2, 10, 100) }
+func BenchmarkString1000Base2(b *testing.B)   { StringHelper(b, 2, 10, 1000) }
+func BenchmarkString10000Base2(b *testing.B)  { StringHelper(b, 2, 10, 10000) }
+func BenchmarkString100000Base2(b *testing.B) { StringHelper(b, 2, 10, 100000) }
+
+func BenchmarkString10Base8(b *testing.B)     { StringHelper(b, 8, 10, 10) }
+func BenchmarkString100Base8(b *testing.B)    { StringHelper(b, 8, 10, 100) }
+func BenchmarkString1000Base8(b *testing.B)   { StringHelper(b, 8, 10, 1000) }
+func BenchmarkString10000Base8(b *testing.B)  { StringHelper(b, 8, 10, 10000) }
+func BenchmarkString100000Base8(b *testing.B) { StringHelper(b, 8, 10, 100000) }
+
+func BenchmarkString10Base10(b *testing.B)     { StringHelper(b, 10, 10, 10) }
+func BenchmarkString100Base10(b *testing.B)    { StringHelper(b, 10, 10, 100) }
+func BenchmarkString1000Base10(b *testing.B)   { StringHelper(b, 10, 10, 1000) }
+func BenchmarkString10000Base10(b *testing.B)  { StringHelper(b, 10, 10, 10000) }
+func BenchmarkString100000Base10(b *testing.B) { StringHelper(b, 10, 10, 100000) }
+
+func BenchmarkString10Base16(b *testing.B)     { StringHelper(b, 16, 10, 10) }
+func BenchmarkString100Base16(b *testing.B)    { StringHelper(b, 16, 10, 100) }
+func BenchmarkString1000Base16(b *testing.B)   { StringHelper(b, 16, 10, 1000) }
+func BenchmarkString10000Base16(b *testing.B)  { StringHelper(b, 16, 10, 10000) }
+func BenchmarkString100000Base16(b *testing.B) { StringHelper(b, 16, 10, 100000) }
+
+func StringHelper(b *testing.B, base int, x, y Word) {
+	b.StopTimer()
+	var z nat
+	z = z.expWW(x, y)
+	z.string(lowercaseDigits[0:base]) // warm divisor cache
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		_ = z.string(lowercaseDigits[0:base])
+	}
+}
+
+func BenchmarkLeafSize0(b *testing.B)  { LeafSizeHelper(b, 10, 0) } // test without splitting
+func BenchmarkLeafSize1(b *testing.B)  { LeafSizeHelper(b, 10, 1) }
+func BenchmarkLeafSize2(b *testing.B)  { LeafSizeHelper(b, 10, 2) }
+func BenchmarkLeafSize3(b *testing.B)  { LeafSizeHelper(b, 10, 3) }
+func BenchmarkLeafSize4(b *testing.B)  { LeafSizeHelper(b, 10, 4) }
+func BenchmarkLeafSize5(b *testing.B)  { LeafSizeHelper(b, 10, 5) }
+func BenchmarkLeafSize6(b *testing.B)  { LeafSizeHelper(b, 10, 6) }
+func BenchmarkLeafSize7(b *testing.B)  { LeafSizeHelper(b, 10, 7) }
+func BenchmarkLeafSize8(b *testing.B)  { LeafSizeHelper(b, 10, 8) }
+func BenchmarkLeafSize9(b *testing.B)  { LeafSizeHelper(b, 10, 9) }
+func BenchmarkLeafSize10(b *testing.B) { LeafSizeHelper(b, 10, 10) }
+func BenchmarkLeafSize11(b *testing.B) { LeafSizeHelper(b, 10, 11) }
+func BenchmarkLeafSize12(b *testing.B) { LeafSizeHelper(b, 10, 12) }
+func BenchmarkLeafSize13(b *testing.B) { LeafSizeHelper(b, 10, 13) }
+func BenchmarkLeafSize14(b *testing.B) { LeafSizeHelper(b, 10, 14) }
+func BenchmarkLeafSize15(b *testing.B) { LeafSizeHelper(b, 10, 15) }
+func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
+func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths 
+func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
+
+func LeafSizeHelper(b *testing.B, base Word, size int) {
+	b.StopTimer()
+	originalLeafSize := leafSize
+	resetTable(cacheBase10[:])
+	leafSize = size
+	b.StartTimer()
+
+	for d := 1; d <= 10000; d *= 10 {
+		b.StopTimer()
+		var z nat
+		z = z.expWW(base, Word(d))            // build target number
+		_ = z.string(lowercaseDigits[0:base]) // warm divisor cache
+		b.StartTimer()
+
+		for i := 0; i < b.N; i++ {
+			_ = z.string(lowercaseDigits[0:base])
+		}
+	}
+
+	b.StopTimer()
+	resetTable(cacheBase10[:])
+	leafSize = originalLeafSize
+	b.StartTimer()
+}
+
+func resetTable(table []divisor) {
+	if table != nil && table[0].bbb != nil {
+		for i := 0; i < len(table); i++ {
+			table[i].bbb = nil
+			table[i].nbits = 0
+			table[i].ndigits = 0
+		}
+	}
+}
+
+func TestStringPowers(t *testing.T) {
+	var b, p Word
+	for b = 2; b <= 16; b++ {
+		for p = 0; p <= 512; p++ {
+			x := nat(nil).expWW(b, p)
+			xs := x.string(lowercaseDigits[0:b])
+			xs2 := toString(x, lowercaseDigits[0:b])
+			if xs != xs2 {
+				t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
+			}
+		}
+	}
+}
+
+func TestLeadingZeros(t *testing.T) {
+	var x Word = _B >> 1
+	for i := 0; i <= _W; i++ {
+		if int(leadingZeros(x)) != i {
+			t.Errorf("failed at %x: got %d want %d", x, leadingZeros(x), i)
+		}
+		x >>= 1
+	}
+}
+
+type shiftTest struct {
+	in    nat
+	shift uint
+	out   nat
+}
+
+var leftShiftTests = []shiftTest{
+	{nil, 0, nil},
+	{nil, 1, nil},
+	{natOne, 0, natOne},
+	{natOne, 1, natTwo},
+	{nat{1 << (_W - 1)}, 1, nat{0}},
+	{nat{1 << (_W - 1), 0}, 1, nat{0, 1}},
+}
+
+func TestShiftLeft(t *testing.T) {
+	for i, test := range leftShiftTests {
+		var z nat
+		z = z.shl(test.in, test.shift)
+		for j, d := range test.out {
+			if j >= len(z) || z[j] != d {
+				t.Errorf("#%d: got: %v want: %v", i, z, test.out)
+				break
+			}
+		}
+	}
+}
+
+var rightShiftTests = []shiftTest{
+	{nil, 0, nil},
+	{nil, 1, nil},
+	{natOne, 0, natOne},
+	{natOne, 1, nil},
+	{natTwo, 1, natOne},
+	{nat{0, 1}, 1, nat{1 << (_W - 1)}},
+	{nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1)}},
+}
+
+func TestShiftRight(t *testing.T) {
+	for i, test := range rightShiftTests {
+		var z nat
+		z = z.shr(test.in, test.shift)
+		for j, d := range test.out {
+			if j >= len(z) || z[j] != d {
+				t.Errorf("#%d: got: %v want: %v", i, z, test.out)
+				break
+			}
+		}
+	}
+}
+
+type modWTest struct {
+	in       string
+	dividend string
+	out      string
+}
+
+var modWTests32 = []modWTest{
+	{"23492635982634928349238759823742", "252341", "220170"},
+}
+
+var modWTests64 = []modWTest{
+	{"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"},
+}
+
+func runModWTests(t *testing.T, tests []modWTest) {
+	for i, test := range tests {
+		in, _ := new(Int).SetString(test.in, 10)
+		d, _ := new(Int).SetString(test.dividend, 10)
+		out, _ := new(Int).SetString(test.out, 10)
+
+		r := in.abs.modW(d.abs[0])
+		if r != out.abs[0] {
+			t.Errorf("#%d failed: got %s want %s", i, r, out)
+		}
+	}
+}
+
+func TestModW(t *testing.T) {
+	if _W >= 32 {
+		runModWTests(t, modWTests32)
+	}
+	if _W >= 64 {
+		runModWTests(t, modWTests64)
+	}
+}
+
+func TestTrailingZeroBits(t *testing.T) {
+	var x Word
+	x--
+	for i := 0; i < _W; i++ {
+		if trailingZeroBits(x) != i {
+			t.Errorf("Failed at step %d: x: %x got: %d", i, x, trailingZeroBits(x))
+		}
+		x <<= 1
+	}
+}
+
+var expNNTests = []struct {
+	x, y, m string
+	out     string
+}{
+	{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
+	{"0x8000000000000000", "2", "6719", "4944"},
+	{"0x8000000000000000", "3", "6719", "5447"},
+	{"0x8000000000000000", "1000", "6719", "1603"},
+	{"0x8000000000000000", "1000000", "6719", "3199"},
+	{
+		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
+		"298472983472983471903246121093472394872319615612417471234712061",
+		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
+		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
+	},
+}
+
+func TestExpNN(t *testing.T) {
+	for i, test := range expNNTests {
+		x, _, _ := nat(nil).scan(strings.NewReader(test.x), 0)
+		y, _, _ := nat(nil).scan(strings.NewReader(test.y), 0)
+		out, _, _ := nat(nil).scan(strings.NewReader(test.out), 0)
+
+		var m nat
+
+		if len(test.m) > 0 {
+			m, _, _ = nat(nil).scan(strings.NewReader(test.m), 0)
+		}
+
+		z := nat(nil).expNN(x, y, m)
+		if z.cmp(out) != 0 {
+			t.Errorf("#%d got %v want %v", i, z, out)
+		}
+	}
+}
diff --git a/src/pkg/math/big/rat.go b/src/pkg/math/big/rat.go
new file mode 100644
index 0000000..adf4124
--- /dev/null
+++ b/src/pkg/math/big/rat.go
@@ -0,0 +1,432 @@
+// Copyright 2010 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 file implements multi-precision rational numbers.
+
+package big
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"strings"
+)
+
+// A Rat represents a quotient a/b of arbitrary precision.
+// The zero value for a Rat represents the value 0.
+type Rat struct {
+	a Int
+	b nat // len(b) == 0 acts like b == 1
+}
+
+// NewRat creates a new Rat with numerator a and denominator b.
+func NewRat(a, b int64) *Rat {
+	return new(Rat).SetFrac64(a, b)
+}
+
+// SetFrac sets z to a/b and returns z.
+func (z *Rat) SetFrac(a, b *Int) *Rat {
+	z.a.neg = a.neg != b.neg
+	babs := b.abs
+	if len(babs) == 0 {
+		panic("division by zero")
+	}
+	if &z.a == b || alias(z.a.abs, babs) {
+		babs = nat(nil).set(babs) // make a copy
+	}
+	z.a.abs = z.a.abs.set(a.abs)
+	z.b = z.b.set(babs)
+	return z.norm()
+}
+
+// SetFrac64 sets z to a/b and returns z.
+func (z *Rat) SetFrac64(a, b int64) *Rat {
+	z.a.SetInt64(a)
+	if b == 0 {
+		panic("division by zero")
+	}
+	if b < 0 {
+		b = -b
+		z.a.neg = !z.a.neg
+	}
+	z.b = z.b.setUint64(uint64(b))
+	return z.norm()
+}
+
+// SetInt sets z to x (by making a copy of x) and returns z.
+func (z *Rat) SetInt(x *Int) *Rat {
+	z.a.Set(x)
+	z.b = z.b.make(0)
+	return z
+}
+
+// SetInt64 sets z to x and returns z.
+func (z *Rat) SetInt64(x int64) *Rat {
+	z.a.SetInt64(x)
+	z.b = z.b.make(0)
+	return z
+}
+
+// Set sets z to x (by making a copy of x) and returns z.
+func (z *Rat) Set(x *Rat) *Rat {
+	if z != x {
+		z.a.Set(&x.a)
+		z.b = z.b.set(x.b)
+	}
+	return z
+}
+
+// Abs sets z to |x| (the absolute value of x) and returns z.
+func (z *Rat) Abs(x *Rat) *Rat {
+	z.Set(x)
+	z.a.neg = false
+	return z
+}
+
+// Neg sets z to -x and returns z.
+func (z *Rat) Neg(x *Rat) *Rat {
+	z.Set(x)
+	z.a.neg = len(z.a.abs) > 0 && !z.a.neg // 0 has no sign
+	return z
+}
+
+// Inv sets z to 1/x and returns z.
+func (z *Rat) Inv(x *Rat) *Rat {
+	if len(x.a.abs) == 0 {
+		panic("division by zero")
+	}
+	z.Set(x)
+	a := z.b
+	if len(a) == 0 {
+		a = a.setWord(1) // materialize numerator
+	}
+	b := z.a.abs
+	if b.cmp(natOne) == 0 {
+		b = b.make(0) // normalize denominator
+	}
+	z.a.abs, z.b = a, b // sign doesn't change
+	return z
+}
+
+// Sign returns:
+//
+//	-1 if x <  0
+//	 0 if x == 0
+//	+1 if x >  0
+//
+func (x *Rat) Sign() int {
+	return x.a.Sign()
+}
+
+// IsInt returns true if the denominator of x is 1.
+func (x *Rat) IsInt() bool {
+	return len(x.b) == 0 || x.b.cmp(natOne) == 0
+}
+
+// Num returns the numerator of x; it may be <= 0.
+// The result is a reference to x's numerator; it
+// may change if a new value is assigned to x.
+func (x *Rat) Num() *Int {
+	return &x.a
+}
+
+// Denom returns the denominator of x; it is always > 0.
+// The result is a reference to x's denominator; it
+// may change if a new value is assigned to x.
+func (x *Rat) Denom() *Int {
+	if len(x.b) == 0 {
+		return &Int{abs: nat{1}}
+	}
+	return &Int{abs: x.b}
+}
+
+func gcd(x, y nat) nat {
+	// Euclidean algorithm.
+	var a, b nat
+	a = a.set(x)
+	b = b.set(y)
+	for len(b) != 0 {
+		var q, r nat
+		_, r = q.div(r, a, b)
+		a = b
+		b = r
+	}
+	return a
+}
+
+func (z *Rat) norm() *Rat {
+	switch {
+	case len(z.a.abs) == 0:
+		// z == 0 - normalize sign and denominator
+		z.a.neg = false
+		z.b = z.b.make(0)
+	case len(z.b) == 0:
+		// z is normalized int - nothing to do
+	case z.b.cmp(natOne) == 0:
+		// z is int - normalize denominator
+		z.b = z.b.make(0)
+	default:
+		if f := gcd(z.a.abs, z.b); f.cmp(natOne) != 0 {
+			z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f)
+			z.b, _ = z.b.div(nil, z.b, f)
+		}
+	}
+	return z
+}
+
+// mulDenom sets z to the denominator product x*y (by taking into
+// account that 0 values for x or y must be interpreted as 1) and
+// returns z.
+func mulDenom(z, x, y nat) nat {
+	switch {
+	case len(x) == 0:
+		return z.set(y)
+	case len(y) == 0:
+		return z.set(x)
+	}
+	return z.mul(x, y)
+}
+
+// scaleDenom computes x*f.
+// If f == 0 (zero value of denominator), the result is (a copy of) x.
+func scaleDenom(x *Int, f nat) *Int {
+	var z Int
+	if len(f) == 0 {
+		return z.Set(x)
+	}
+	z.abs = z.abs.mul(x.abs, f)
+	z.neg = x.neg
+	return &z
+}
+
+// Cmp compares x and y and returns:
+//
+//   -1 if x <  y
+//    0 if x == y
+//   +1 if x >  y
+//
+func (x *Rat) Cmp(y *Rat) int {
+	return scaleDenom(&x.a, y.b).Cmp(scaleDenom(&y.a, x.b))
+}
+
+// Add sets z to the sum x+y and returns z.
+func (z *Rat) Add(x, y *Rat) *Rat {
+	a1 := scaleDenom(&x.a, y.b)
+	a2 := scaleDenom(&y.a, x.b)
+	z.a.Add(a1, a2)
+	z.b = mulDenom(z.b, x.b, y.b)
+	return z.norm()
+}
+
+// Sub sets z to the difference x-y and returns z.
+func (z *Rat) Sub(x, y *Rat) *Rat {
+	a1 := scaleDenom(&x.a, y.b)
+	a2 := scaleDenom(&y.a, x.b)
+	z.a.Sub(a1, a2)
+	z.b = mulDenom(z.b, x.b, y.b)
+	return z.norm()
+}
+
+// Mul sets z to the product x*y and returns z.
+func (z *Rat) Mul(x, y *Rat) *Rat {
+	z.a.Mul(&x.a, &y.a)
+	z.b = mulDenom(z.b, x.b, y.b)
+	return z.norm()
+}
+
+// Quo sets z to the quotient x/y and returns z.
+// If y == 0, a division-by-zero run-time panic occurs.
+func (z *Rat) Quo(x, y *Rat) *Rat {
+	if len(y.a.abs) == 0 {
+		panic("division by zero")
+	}
+	a := scaleDenom(&x.a, y.b)
+	b := scaleDenom(&y.a, x.b)
+	z.a.abs = a.abs
+	z.b = b.abs
+	z.a.neg = a.neg != b.neg
+	return z.norm()
+}
+
+func ratTok(ch rune) bool {
+	return strings.IndexRune("+-/0123456789.eE", ch) >= 0
+}
+
+// Scan is a support routine for fmt.Scanner. It accepts the formats
+// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
+func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
+	tok, err := s.Token(true, ratTok)
+	if err != nil {
+		return err
+	}
+	if strings.IndexRune("efgEFGv", ch) < 0 {
+		return errors.New("Rat.Scan: invalid verb")
+	}
+	if _, ok := z.SetString(string(tok)); !ok {
+		return errors.New("Rat.Scan: invalid syntax")
+	}
+	return nil
+}
+
+// SetString sets z to the value of s and returns z and a boolean indicating
+// success. s can be given as a fraction "a/b" or as a floating-point number
+// optionally followed by an exponent. If the operation failed, the value of
+// z is undefined but the returned value is nil.
+func (z *Rat) SetString(s string) (*Rat, bool) {
+	if len(s) == 0 {
+		return nil, false
+	}
+
+	// check for a quotient
+	sep := strings.Index(s, "/")
+	if sep >= 0 {
+		if _, ok := z.a.SetString(s[0:sep], 10); !ok {
+			return nil, false
+		}
+		s = s[sep+1:]
+		var err error
+		if z.b, _, err = z.b.scan(strings.NewReader(s), 10); err != nil {
+			return nil, false
+		}
+		return z.norm(), true
+	}
+
+	// check for a decimal point
+	sep = strings.Index(s, ".")
+	// check for an exponent
+	e := strings.IndexAny(s, "eE")
+	var exp Int
+	if e >= 0 {
+		if e < sep {
+			// The E must come after the decimal point.
+			return nil, false
+		}
+		if _, ok := exp.SetString(s[e+1:], 10); !ok {
+			return nil, false
+		}
+		s = s[0:e]
+	}
+	if sep >= 0 {
+		s = s[0:sep] + s[sep+1:]
+		exp.Sub(&exp, NewInt(int64(len(s)-sep)))
+	}
+
+	if _, ok := z.a.SetString(s, 10); !ok {
+		return nil, false
+	}
+	powTen := nat(nil).expNN(natTen, exp.abs, nil)
+	if exp.neg {
+		z.b = powTen
+		z.norm()
+	} else {
+		z.a.abs = z.a.abs.mul(z.a.abs, powTen)
+		z.b = z.b.make(0)
+	}
+
+	return z, true
+}
+
+// String returns a string representation of z in the form "a/b" (even if b == 1).
+func (z *Rat) String() string {
+	s := "/1"
+	if len(z.b) != 0 {
+		s = "/" + z.b.decimalString()
+	}
+	return z.a.String() + s
+}
+
+// RatString returns a string representation of z in the form "a/b" if b != 1,
+// and in the form "a" if b == 1.
+func (z *Rat) RatString() string {
+	if z.IsInt() {
+		return z.a.String()
+	}
+	return z.String()
+}
+
+// FloatString returns a string representation of z in decimal form with prec
+// digits of precision after the decimal point and the last digit rounded.
+func (z *Rat) FloatString(prec int) string {
+	if z.IsInt() {
+		s := z.a.String()
+		if prec > 0 {
+			s += "." + strings.Repeat("0", prec)
+		}
+		return s
+	}
+	// z.b != 0
+
+	q, r := nat(nil).div(nat(nil), z.a.abs, z.b)
+
+	p := natOne
+	if prec > 0 {
+		p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
+	}
+
+	r = r.mul(r, p)
+	r, r2 := r.div(nat(nil), r, z.b)
+
+	// see if we need to round up
+	r2 = r2.add(r2, r2)
+	if z.b.cmp(r2) <= 0 {
+		r = r.add(r, natOne)
+		if r.cmp(p) >= 0 {
+			q = nat(nil).add(q, natOne)
+			r = nat(nil).sub(r, p)
+		}
+	}
+
+	s := q.decimalString()
+	if z.a.neg {
+		s = "-" + s
+	}
+
+	if prec > 0 {
+		rs := r.decimalString()
+		leadingZeros := prec - len(rs)
+		s += "." + strings.Repeat("0", leadingZeros) + rs
+	}
+
+	return s
+}
+
+// Gob codec version. Permits backward-compatible changes to the encoding.
+const ratGobVersion byte = 1
+
+// GobEncode implements the gob.GobEncoder interface.
+func (z *Rat) GobEncode() ([]byte, error) {
+	buf := make([]byte, 1+4+(len(z.a.abs)+len(z.b))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
+	i := z.b.bytes(buf)
+	j := z.a.abs.bytes(buf[0:i])
+	n := i - j
+	if int(uint32(n)) != n {
+		// this should never happen
+		return nil, errors.New("Rat.GobEncode: numerator too large")
+	}
+	binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
+	j -= 1 + 4
+	b := ratGobVersion << 1 // make space for sign bit
+	if z.a.neg {
+		b |= 1
+	}
+	buf[j] = b
+	return buf[j:], nil
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (z *Rat) GobDecode(buf []byte) error {
+	if len(buf) == 0 {
+		return errors.New("Rat.GobDecode: no data")
+	}
+	b := buf[0]
+	if b>>1 != ratGobVersion {
+		return errors.New(fmt.Sprintf("Rat.GobDecode: encoding version %d not supported", b>>1))
+	}
+	const j = 1 + 4
+	i := j + binary.BigEndian.Uint32(buf[j-4:j])
+	z.a.neg = b&1 != 0
+	z.a.abs = z.a.abs.setBytes(buf[j:i])
+	z.b = z.b.setBytes(buf[i:])
+	return nil
+}
diff --git a/src/pkg/math/big/rat_test.go b/src/pkg/math/big/rat_test.go
new file mode 100644
index 0000000..f7f31ae
--- /dev/null
+++ b/src/pkg/math/big/rat_test.go
@@ -0,0 +1,456 @@
+// Copyright 2010 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 big
+
+import (
+	"bytes"
+	"encoding/gob"
+	"fmt"
+	"testing"
+)
+
+func TestZeroRat(t *testing.T) {
+	var x, y, z Rat
+	y.SetFrac64(0, 42)
+
+	if x.Cmp(&y) != 0 {
+		t.Errorf("x and y should be both equal and zero")
+	}
+
+	if s := x.String(); s != "0/1" {
+		t.Errorf("got x = %s, want 0/1", s)
+	}
+
+	if s := x.RatString(); s != "0" {
+		t.Errorf("got x = %s, want 0", s)
+	}
+
+	z.Add(&x, &y)
+	if s := z.RatString(); s != "0" {
+		t.Errorf("got x+y = %s, want 0", s)
+	}
+
+	z.Sub(&x, &y)
+	if s := z.RatString(); s != "0" {
+		t.Errorf("got x-y = %s, want 0", s)
+	}
+
+	z.Mul(&x, &y)
+	if s := z.RatString(); s != "0" {
+		t.Errorf("got x*y = %s, want 0", s)
+	}
+
+	// check for division by zero
+	defer func() {
+		if s := recover(); s == nil || s.(string) != "division by zero" {
+			panic(s)
+		}
+	}()
+	z.Quo(&x, &y)
+}
+
+var setStringTests = []struct {
+	in, out string
+	ok      bool
+}{
+	{"0", "0", true},
+	{"-0", "0", true},
+	{"1", "1", true},
+	{"-1", "-1", true},
+	{"1.", "1", true},
+	{"1e0", "1", true},
+	{"1.e1", "10", true},
+	{in: "1e", ok: false},
+	{in: "1.e", ok: false},
+	{in: "1e+14e-5", ok: false},
+	{in: "1e4.5", ok: false},
+	{in: "r", ok: false},
+	{in: "a/b", ok: false},
+	{in: "a.b", ok: false},
+	{"-0.1", "-1/10", true},
+	{"-.1", "-1/10", true},
+	{"2/4", "1/2", true},
+	{".25", "1/4", true},
+	{"-1/5", "-1/5", true},
+	{"8129567.7690E14", "812956776900000000000", true},
+	{"78189e+4", "781890000", true},
+	{"553019.8935e+8", "55301989350000", true},
+	{"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
+	{"9877861857500000E-7", "3951144743/4", true},
+	{"2169378.417e-3", "2169378417/1000000", true},
+	{"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
+	{"53/70893980658822810696", "53/70893980658822810696", true},
+	{"106/141787961317645621392", "53/70893980658822810696", true},
+	{"204211327800791583.81095", "4084226556015831676219/20000", true},
+}
+
+func TestRatSetString(t *testing.T) {
+	for i, test := range setStringTests {
+		x, ok := new(Rat).SetString(test.in)
+
+		if ok {
+			if !test.ok {
+				t.Errorf("#%d SetString(%q) expected failure", i, test.in)
+			} else if x.RatString() != test.out {
+				t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
+			}
+		} else if x != nil {
+			t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
+		}
+	}
+}
+
+func TestRatScan(t *testing.T) {
+	var buf bytes.Buffer
+	for i, test := range setStringTests {
+		x := new(Rat)
+		buf.Reset()
+		buf.WriteString(test.in)
+
+		_, err := fmt.Fscanf(&buf, "%v", x)
+		if err == nil != test.ok {
+			if test.ok {
+				t.Errorf("#%d error: %s", i, err)
+			} else {
+				t.Errorf("#%d expected error", i)
+			}
+			continue
+		}
+		if err == nil && x.RatString() != test.out {
+			t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
+		}
+	}
+}
+
+var floatStringTests = []struct {
+	in   string
+	prec int
+	out  string
+}{
+	{"0", 0, "0"},
+	{"0", 4, "0.0000"},
+	{"1", 0, "1"},
+	{"1", 2, "1.00"},
+	{"-1", 0, "-1"},
+	{".25", 2, "0.25"},
+	{".25", 1, "0.3"},
+	{".25", 3, "0.250"},
+	{"-1/3", 3, "-0.333"},
+	{"-2/3", 4, "-0.6667"},
+	{"0.96", 1, "1.0"},
+	{"0.999", 2, "1.00"},
+	{"0.9", 0, "1"},
+	{".25", -1, "0"},
+	{".55", -1, "1"},
+}
+
+func TestFloatString(t *testing.T) {
+	for i, test := range floatStringTests {
+		x, _ := new(Rat).SetString(test.in)
+
+		if x.FloatString(test.prec) != test.out {
+			t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
+		}
+	}
+}
+
+func TestRatSign(t *testing.T) {
+	zero := NewRat(0, 1)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		s := x.Sign()
+		e := x.Cmp(zero)
+		if s != e {
+			t.Errorf("got %d; want %d for z = %v", s, e, &x)
+		}
+	}
+}
+
+var ratCmpTests = []struct {
+	rat1, rat2 string
+	out        int
+}{
+	{"0", "0/1", 0},
+	{"1/1", "1", 0},
+	{"-1", "-2/2", 0},
+	{"1", "0", 1},
+	{"0/1", "1/1", -1},
+	{"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
+	{"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
+	{"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
+	{"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
+}
+
+func TestRatCmp(t *testing.T) {
+	for i, test := range ratCmpTests {
+		x, _ := new(Rat).SetString(test.rat1)
+		y, _ := new(Rat).SetString(test.rat2)
+
+		out := x.Cmp(y)
+		if out != test.out {
+			t.Errorf("#%d got out = %v; want %v", i, out, test.out)
+		}
+	}
+}
+
+func TestIsInt(t *testing.T) {
+	one := NewInt(1)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		i := x.IsInt()
+		e := x.Denom().Cmp(one) == 0
+		if i != e {
+			t.Errorf("got IsInt(%v) == %v; want %v", x, i, e)
+		}
+	}
+}
+
+func TestRatAbs(t *testing.T) {
+	zero := new(Rat)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		e := new(Rat).Set(x)
+		if e.Cmp(zero) < 0 {
+			e.Sub(zero, e)
+		}
+		z := new(Rat).Abs(x)
+		if z.Cmp(e) != 0 {
+			t.Errorf("got Abs(%v) = %v; want %v", x, z, e)
+		}
+	}
+}
+
+func TestRatNeg(t *testing.T) {
+	zero := new(Rat)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		e := new(Rat).Sub(zero, x)
+		z := new(Rat).Neg(x)
+		if z.Cmp(e) != 0 {
+			t.Errorf("got Neg(%v) = %v; want %v", x, z, e)
+		}
+	}
+}
+
+func TestRatInv(t *testing.T) {
+	zero := new(Rat)
+	for _, a := range setStringTests {
+		x, ok := new(Rat).SetString(a.in)
+		if !ok {
+			continue
+		}
+		if x.Cmp(zero) == 0 {
+			continue // avoid division by zero
+		}
+		e := new(Rat).SetFrac(x.Denom(), x.Num())
+		z := new(Rat).Inv(x)
+		if z.Cmp(e) != 0 {
+			t.Errorf("got Inv(%v) = %v; want %v", x, z, e)
+		}
+	}
+}
+
+type ratBinFun func(z, x, y *Rat) *Rat
+type ratBinArg struct {
+	x, y, z string
+}
+
+func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) {
+	x, _ := new(Rat).SetString(a.x)
+	y, _ := new(Rat).SetString(a.y)
+	z, _ := new(Rat).SetString(a.z)
+	out := f(new(Rat), x, y)
+
+	if out.Cmp(z) != 0 {
+		t.Errorf("%s #%d got %s want %s", name, i, out, z)
+	}
+}
+
+var ratBinTests = []struct {
+	x, y      string
+	sum, prod string
+}{
+	{"0", "0", "0", "0"},
+	{"0", "1", "1", "0"},
+	{"-1", "0", "-1", "0"},
+	{"-1", "1", "0", "-1"},
+	{"1", "1", "2", "1"},
+	{"1/2", "1/2", "1", "1/4"},
+	{"1/4", "1/3", "7/12", "1/12"},
+	{"2/5", "-14/3", "-64/15", "-28/15"},
+	{"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"},
+	{"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"},
+	{"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"},
+	{"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"},
+	{"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"},
+	{"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"},
+	{"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"},
+	{"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"},
+	{"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"},
+	{"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"},
+}
+
+func TestRatBin(t *testing.T) {
+	for i, test := range ratBinTests {
+		arg := ratBinArg{test.x, test.y, test.sum}
+		testRatBin(t, i, "Add", (*Rat).Add, arg)
+
+		arg = ratBinArg{test.y, test.x, test.sum}
+		testRatBin(t, i, "Add symmetric", (*Rat).Add, arg)
+
+		arg = ratBinArg{test.sum, test.x, test.y}
+		testRatBin(t, i, "Sub", (*Rat).Sub, arg)
+
+		arg = ratBinArg{test.sum, test.y, test.x}
+		testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg)
+
+		arg = ratBinArg{test.x, test.y, test.prod}
+		testRatBin(t, i, "Mul", (*Rat).Mul, arg)
+
+		arg = ratBinArg{test.y, test.x, test.prod}
+		testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg)
+
+		if test.x != "0" {
+			arg = ratBinArg{test.prod, test.x, test.y}
+			testRatBin(t, i, "Quo", (*Rat).Quo, arg)
+		}
+
+		if test.y != "0" {
+			arg = ratBinArg{test.prod, test.y, test.x}
+			testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg)
+		}
+	}
+}
+
+func TestIssue820(t *testing.T) {
+	x := NewRat(3, 1)
+	y := NewRat(2, 1)
+	z := y.Quo(x, y)
+	q := NewRat(3, 2)
+	if z.Cmp(q) != 0 {
+		t.Errorf("got %s want %s", z, q)
+	}
+
+	y = NewRat(3, 1)
+	x = NewRat(2, 1)
+	z = y.Quo(x, y)
+	q = NewRat(2, 3)
+	if z.Cmp(q) != 0 {
+		t.Errorf("got %s want %s", z, q)
+	}
+
+	x = NewRat(3, 1)
+	z = x.Quo(x, x)
+	q = NewRat(3, 3)
+	if z.Cmp(q) != 0 {
+		t.Errorf("got %s want %s", z, q)
+	}
+}
+
+var setFrac64Tests = []struct {
+	a, b int64
+	out  string
+}{
+	{0, 1, "0"},
+	{0, -1, "0"},
+	{1, 1, "1"},
+	{-1, 1, "-1"},
+	{1, -1, "-1"},
+	{-1, -1, "1"},
+	{-9223372036854775808, -9223372036854775808, "1"},
+}
+
+func TestRatSetFrac64Rat(t *testing.T) {
+	for i, test := range setFrac64Tests {
+		x := new(Rat).SetFrac64(test.a, test.b)
+		if x.RatString() != test.out {
+			t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
+		}
+	}
+}
+
+func TestRatGobEncoding(t *testing.T) {
+	var medium bytes.Buffer
+	enc := gob.NewEncoder(&medium)
+	dec := gob.NewDecoder(&medium)
+	for i, test := range gobEncodingTests {
+		for j := 0; j < 4; j++ {
+			medium.Reset() // empty buffer for each test case (in case of failures)
+			stest := test
+			if j&1 != 0 {
+				// negative numbers
+				stest = "-" + test
+			}
+			if j%2 != 0 {
+				// fractions
+				stest = stest + "." + test
+			}
+			var tx Rat
+			tx.SetString(stest)
+			if err := enc.Encode(&tx); err != nil {
+				t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
+			}
+			var rx Rat
+			if err := dec.Decode(&rx); err != nil {
+				t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
+			}
+		}
+	}
+}
+
+func TestIssue2379(t *testing.T) {
+	// 1) no aliasing
+	q := NewRat(3, 2)
+	x := new(Rat)
+	x.SetFrac(NewInt(3), NewInt(2))
+	if x.Cmp(q) != 0 {
+		t.Errorf("1) got %s want %s", x, q)
+	}
+
+	// 2) aliasing of numerator
+	x = NewRat(2, 3)
+	x.SetFrac(NewInt(3), x.Num())
+	if x.Cmp(q) != 0 {
+		t.Errorf("2) got %s want %s", x, q)
+	}
+
+	// 3) aliasing of denominator
+	x = NewRat(2, 3)
+	x.SetFrac(x.Denom(), NewInt(2))
+	if x.Cmp(q) != 0 {
+		t.Errorf("3) got %s want %s", x, q)
+	}
+
+	// 4) aliasing of numerator and denominator
+	x = NewRat(2, 3)
+	x.SetFrac(x.Denom(), x.Num())
+	if x.Cmp(q) != 0 {
+		t.Errorf("4) got %s want %s", x, q)
+	}
+
+	// 5) numerator and denominator are the same
+	q = NewRat(1, 1)
+	x = new(Rat)
+	n := NewInt(7)
+	x.SetFrac(n, n)
+	if x.Cmp(q) != 0 {
+		t.Errorf("5) got %s want %s", x, q)
+	}
+}
diff --git a/src/pkg/math/bits.go b/src/pkg/math/bits.go
index a1dca3e..1cf60ce 100644
--- a/src/pkg/math/bits.go
+++ b/src/pkg/math/bits.go
@@ -52,7 +52,7 @@ func IsInf(f float64, sign int) bool {
 // satisfying x == y × 2**exp. It assumes x is finite and non-zero.
 func normalize(x float64) (y float64, exp int) {
 	const SmallestNormal = 2.2250738585072014e-308 // 2**-1022
-	if Fabs(x) < SmallestNormal {
+	if Abs(x) < SmallestNormal {
 		return x * (1 << 52), -52
 	}
 	return x, 0
diff --git a/src/pkg/math/cbrt.go b/src/pkg/math/cbrt.go
index d2b7e91..09edc0e 100644
--- a/src/pkg/math/cbrt.go
+++ b/src/pkg/math/cbrt.go
@@ -45,22 +45,21 @@ func Cbrt(x float64) float64 {
 		x = -x
 		sign = true
 	}
-	// Reduce argument
-	f, e := Frexp(x)
+	// Reduce argument and estimate cube root
+	f, e := Frexp(x) // 0.5 <= f < 1.0
 	m := e % 3
 	if m > 0 {
 		m -= 3
 		e -= m // e is multiple of 3
 	}
-	f = Ldexp(f, m) // 0.125 <= f < 1.0
-
-	// Estimate cube root
 	switch m {
 	case 0: // 0.5 <= f < 1.0
 		f = A1*f + A2 - A3/(A4+f)
-	case -1: // 0.25 <= f < 0.5
+	case -1:
+		f *= 0.5 // 0.25 <= f < 0.5
 		f = B1*f + B2 - B3/(B4+f)
-	default: // 0.125 <= f < 0.25
+	default: // m == -2
+		f *= 0.25 // 0.125 <= f < 0.25
 		f = C1*f + C2 - C3/(C4+f)
 	}
 	y := Ldexp(f, e/3) // e/3 = exponent of cube root
diff --git a/src/pkg/math/cmplx/Makefile b/src/pkg/math/cmplx/Makefile
new file mode 100644
index 0000000..b6e8aa3
--- /dev/null
+++ b/src/pkg/math/cmplx/Makefile
@@ -0,0 +1,25 @@
+# Copyright 2010 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=math/cmplx
+
+GOFILES=\
+	abs.go\
+	asin.go\
+	conj.go\
+	exp.go\
+	isinf.go\
+	isnan.go\
+	log.go\
+	phase.go\
+	polar.go\
+	pow.go\
+	rect.go\
+	sin.go\
+	sqrt.go\
+	tan.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/math/cmplx/abs.go b/src/pkg/math/cmplx/abs.go
new file mode 100644
index 0000000..f3cd107
--- /dev/null
+++ b/src/pkg/math/cmplx/abs.go
@@ -0,0 +1,12 @@
+// Copyright 2010 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 cmplx provides basic constants and mathematical functions for
+// complex numbers.
+package cmplx
+
+import "math"
+
+// Abs returns the absolute value (also called the modulus) of x.
+func Abs(x complex128) float64 { return math.Hypot(real(x), imag(x)) }
diff --git a/src/pkg/math/cmplx/asin.go b/src/pkg/math/cmplx/asin.go
new file mode 100644
index 0000000..61880a2
--- /dev/null
+++ b/src/pkg/math/cmplx/asin.go
@@ -0,0 +1,170 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// Complex circular arc sine
+//
+// DESCRIPTION:
+//
+// Inverse complex sine:
+//                               2
+// w = -i clog( iz + csqrt( 1 - z ) ).
+//
+// casin(z) = -i casinh(iz)
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10     10100       2.1e-15     3.4e-16
+//    IEEE      -10,+10     30000       2.2e-14     2.7e-15
+// Larger relative error can be observed for z near zero.
+// Also tested by csin(casin(z)) = z.
+
+// Asin returns the inverse sine of x.
+func Asin(x complex128) complex128 {
+	if imag(x) == 0 {
+		if math.Abs(real(x)) > 1 {
+			return complex(math.Pi/2, 0) // DOMAIN error
+		}
+		return complex(math.Asin(real(x)), 0)
+	}
+	ct := complex(-imag(x), real(x)) // i * x
+	xx := x * x
+	x1 := complex(1-real(xx), -imag(xx)) // 1 - x*x
+	x2 := Sqrt(x1)                       // x2 = sqrt(1 - x*x)
+	w := Log(ct + x2)
+	return complex(imag(w), -real(w)) // -i * w
+}
+
+// Asinh returns the inverse hyperbolic sine of x.
+func Asinh(x complex128) complex128 {
+	// TODO check range
+	if imag(x) == 0 {
+		if math.Abs(real(x)) > 1 {
+			return complex(math.Pi/2, 0) // DOMAIN error
+		}
+		return complex(math.Asinh(real(x)), 0)
+	}
+	xx := x * x
+	x1 := complex(1+real(xx), imag(xx)) // 1 + x*x
+	return Log(x + Sqrt(x1))            // log(x + sqrt(1 + x*x))
+}
+
+// Complex circular arc cosine
+//
+// DESCRIPTION:
+//
+// w = arccos z  =  PI/2 - arcsin z.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      5200      1.6e-15      2.8e-16
+//    IEEE      -10,+10     30000      1.8e-14      2.2e-15
+
+// Acos returns the inverse cosine of x.
+func Acos(x complex128) complex128 {
+	w := Asin(x)
+	return complex(math.Pi/2-real(w), -imag(w))
+}
+
+// Acosh returns the inverse hyperbolic cosine of x.
+func Acosh(x complex128) complex128 {
+	w := Acos(x)
+	if imag(w) <= 0 {
+		return complex(-imag(w), real(w)) // i * w
+	}
+	return complex(imag(w), -real(w)) // -i * w
+}
+
+// Complex circular arc tangent
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//          1       (    2x     )
+// Re w  =  - arctan(-----------)  +  k PI
+//          2       (     2    2)
+//                  (1 - x  - y )
+//
+//               ( 2         2)
+//          1    (x  +  (y+1) )
+// Im w  =  - log(------------)
+//          4    ( 2         2)
+//               (x  +  (y-1) )
+//
+// Where k is an arbitrary integer.
+//
+// catan(z) = -i catanh(iz).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      5900       1.3e-16     7.8e-18
+//    IEEE      -10,+10     30000       2.3e-15     8.5e-17
+// The check catan( ctan(z) )  =  z, with |x| and |y| < PI/2,
+// had peak relative error 1.5e-16, rms relative error
+// 2.9e-17.  See also clog().
+
+// Atan returns the inverse tangent of x.
+func Atan(x complex128) complex128 {
+	if real(x) == 0 && imag(x) > 1 {
+		return NaN()
+	}
+
+	x2 := real(x) * real(x)
+	a := 1 - x2 - imag(x)*imag(x)
+	if a == 0 {
+		return NaN()
+	}
+	t := 0.5 * math.Atan2(2*real(x), a)
+	w := reducePi(t)
+
+	t = imag(x) - 1
+	b := x2 + t*t
+	if b == 0 {
+		return NaN()
+	}
+	t = imag(x) + 1
+	c := (x2 + t*t) / b
+	return complex(w, 0.25*math.Log(c))
+}
+
+// Atanh returns the inverse hyperbolic tangent of x.
+func Atanh(x complex128) complex128 {
+	z := complex(-imag(x), real(x)) // z = i * x
+	z = Atan(z)
+	return complex(imag(z), -real(z)) // z = -i * z
+}
diff --git a/src/pkg/math/cmplx/cmath_test.go b/src/pkg/math/cmplx/cmath_test.go
new file mode 100644
index 0000000..610ca8c
--- /dev/null
+++ b/src/pkg/math/cmplx/cmath_test.go
@@ -0,0 +1,853 @@
+// Copyright 2010 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 cmplx
+
+import (
+	"math"
+	"testing"
+)
+
+var vc26 = []complex128{
+	(4.97901192488367350108546816 + 7.73887247457810456552351752i),
+	(7.73887247457810456552351752 - 0.27688005719200159404635997i),
+	(-0.27688005719200159404635997 - 5.01060361827107492160848778i),
+	(-5.01060361827107492160848778 + 9.63629370719841737980004837i),
+	(9.63629370719841737980004837 + 2.92637723924396464525443662i),
+	(2.92637723924396464525443662 + 5.22908343145930665230025625i),
+	(5.22908343145930665230025625 + 2.72793991043601025126008608i),
+	(2.72793991043601025126008608 + 1.82530809168085506044576505i),
+	(1.82530809168085506044576505 - 8.68592476857560136238589621i),
+	(-8.68592476857560136238589621 + 4.97901192488367350108546816i),
+}
+var vc = []complex128{
+	(4.9790119248836735e+00 + 7.7388724745781045e+00i),
+	(7.7388724745781045e+00 - 2.7688005719200159e-01i),
+	(-2.7688005719200159e-01 - 5.0106036182710749e+00i),
+	(-5.0106036182710749e+00 + 9.6362937071984173e+00i),
+	(9.6362937071984173e+00 + 2.9263772392439646e+00i),
+	(2.9263772392439646e+00 + 5.2290834314593066e+00i),
+	(5.2290834314593066e+00 + 2.7279399104360102e+00i),
+	(2.7279399104360102e+00 + 1.8253080916808550e+00i),
+	(1.8253080916808550e+00 - 8.6859247685756013e+00i),
+	(-8.6859247685756013e+00 + 4.9790119248836735e+00i),
+}
+
+// The expected results below were computed by the high precision calculators
+// at http://keisan.casio.com/.  More exact input values (array vc[], above)
+// were obtained by printing them with "%.26f".  The answers were calculated
+// to 26 digits (by using the "Digit number" drop-down control of each
+// calculator).
+
+var abs = []float64{
+	9.2022120669932650313380972e+00,
+	7.7438239742296106616261394e+00,
+	5.0182478202557746902556648e+00,
+	1.0861137372799545160704002e+01,
+	1.0070841084922199607011905e+01,
+	5.9922447613166942183705192e+00,
+	5.8978784056736762299945176e+00,
+	3.2822866700678709020367184e+00,
+	8.8756430028990417290744307e+00,
+	1.0011785496777731986390856e+01,
+}
+
+var acos = []complex128{
+	(1.0017679804707456328694569 - 2.9138232718554953784519807i),
+	(0.03606427612041407369636057 + 2.7358584434576260925091256i),
+	(1.6249365462333796703711823 + 2.3159537454335901187730929i),
+	(2.0485650849650740120660391 - 3.0795576791204117911123886i),
+	(0.29621132089073067282488147 - 3.0007392508200622519398814i),
+	(1.0664555914934156601503632 - 2.4872865024796011364747111i),
+	(0.48681307452231387690013905 - 2.463655912283054555225301i),
+	(0.6116977071277574248407752 - 1.8734458851737055262693056i),
+	(1.3649311280370181331184214 + 2.8793528632328795424123832i),
+	(2.6189310485682988308904501 - 2.9956543302898767795858704i),
+}
+var acosh = []complex128{
+	(2.9138232718554953784519807 + 1.0017679804707456328694569i),
+	(2.7358584434576260925091256 - 0.03606427612041407369636057i),
+	(2.3159537454335901187730929 - 1.6249365462333796703711823i),
+	(3.0795576791204117911123886 + 2.0485650849650740120660391i),
+	(3.0007392508200622519398814 + 0.29621132089073067282488147i),
+	(2.4872865024796011364747111 + 1.0664555914934156601503632i),
+	(2.463655912283054555225301 + 0.48681307452231387690013905i),
+	(1.8734458851737055262693056 + 0.6116977071277574248407752i),
+	(2.8793528632328795424123832 - 1.3649311280370181331184214i),
+	(2.9956543302898767795858704 + 2.6189310485682988308904501i),
+}
+var asin = []complex128{
+	(0.56902834632415098636186476 + 2.9138232718554953784519807i),
+	(1.5347320506744825455349611 - 2.7358584434576260925091256i),
+	(-0.054140219438483051139860579 - 2.3159537454335901187730929i),
+	(-0.47776875817017739283471738 + 3.0795576791204117911123886i),
+	(1.2745850059041659464064402 + 3.0007392508200622519398814i),
+	(0.50434073530148095908095852 + 2.4872865024796011364747111i),
+	(1.0839832522725827423311826 + 2.463655912283054555225301i),
+	(0.9590986196671391943905465 + 1.8734458851737055262693056i),
+	(0.20586519875787848611290031 - 2.8793528632328795424123832i),
+	(-1.0481347217734022116591284 + 2.9956543302898767795858704i),
+}
+var asinh = []complex128{
+	(2.9113760469415295679342185 + 0.99639459545704326759805893i),
+	(2.7441755423994259061579029 - 0.035468308789000500601119392i),
+	(-2.2962136462520690506126678 - 1.5144663565690151885726707i),
+	(-3.0771233459295725965402455 + 1.0895577967194013849422294i),
+	(3.0048366100923647417557027 + 0.29346979169819220036454168i),
+	(2.4800059370795363157364643 + 1.0545868606049165710424232i),
+	(2.4718773838309585611141821 + 0.47502344364250803363708842i),
+	(1.8910743588080159144378396 + 0.56882925572563602341139174i),
+	(2.8735426423367341878069406 - 1.362376149648891420997548i),
+	(-2.9981750586172477217567878 + 0.5183571985225367505624207i),
+}
+var atan = []complex128{
+	(1.5115747079332741358607654 + 0.091324403603954494382276776i),
+	(1.4424504323482602560806727 - 0.0045416132642803911503770933i),
+	(-1.5593488703630532674484026 - 0.20163295409248362456446431i),
+	(-1.5280619472445889867794105 + 0.081721556230672003746956324i),
+	(1.4759909163240799678221039 + 0.028602969320691644358773586i),
+	(1.4877353772046548932715555 + 0.14566877153207281663773599i),
+	(1.4206983927779191889826 + 0.076830486127880702249439993i),
+	(1.3162236060498933364869556 + 0.16031313000467530644933363i),
+	(1.5473450684303703578810093 - 0.11064907507939082484935782i),
+	(-1.4841462340185253987375812 + 0.049341850305024399493142411i),
+}
+var atanh = []complex128{
+	(0.058375027938968509064640438 + 1.4793488495105334458167782i),
+	(0.12977343497790381229915667 - 1.5661009410463561327262499i),
+	(-0.010576456067347252072200088 - 1.3743698658402284549750563i),
+	(-0.042218595678688358882784918 + 1.4891433968166405606692604i),
+	(0.095218997991316722061828397 + 1.5416884098777110330499698i),
+	(0.079965459366890323857556487 + 1.4252510353873192700350435i),
+	(0.15051245471980726221708301 + 1.4907432533016303804884461i),
+	(0.25082072933993987714470373 + 1.392057665392187516442986i),
+	(0.022896108815797135846276662 - 1.4609224989282864208963021i),
+	(-0.08665624101841876130537396 + 1.5207902036935093480142159i),
+}
+var conj = []complex128{
+	(4.9790119248836735e+00 - 7.7388724745781045e+00i),
+	(7.7388724745781045e+00 + 2.7688005719200159e-01i),
+	(-2.7688005719200159e-01 + 5.0106036182710749e+00i),
+	(-5.0106036182710749e+00 - 9.6362937071984173e+00i),
+	(9.6362937071984173e+00 - 2.9263772392439646e+00i),
+	(2.9263772392439646e+00 - 5.2290834314593066e+00i),
+	(5.2290834314593066e+00 - 2.7279399104360102e+00i),
+	(2.7279399104360102e+00 - 1.8253080916808550e+00i),
+	(1.8253080916808550e+00 + 8.6859247685756013e+00i),
+	(-8.6859247685756013e+00 - 4.9790119248836735e+00i),
+}
+var cos = []complex128{
+	(3.024540920601483938336569e+02 + 1.1073797572517071650045357e+03i),
+	(1.192858682649064973252758e-01 + 2.7857554122333065540970207e-01i),
+	(7.2144394304528306603857962e+01 - 2.0500129667076044169954205e+01i),
+	(2.24921952538403984190541e+03 - 7.317363745602773587049329e+03i),
+	(-9.148222970032421760015498e+00 + 1.953124661113563541862227e+00i),
+	(-9.116081175857732248227078e+01 - 1.992669213569952232487371e+01i),
+	(3.795639179042704640002918e+00 + 6.623513350981458399309662e+00i),
+	(-2.9144840732498869560679084e+00 - 1.214620271628002917638748e+00i),
+	(-7.45123482501299743872481e+02 + 2.8641692314488080814066734e+03i),
+	(-5.371977967039319076416747e+01 + 4.893348341339375830564624e+01i),
+}
+var cosh = []complex128{
+	(8.34638383523018249366948e+00 + 7.2181057886425846415112064e+01i),
+	(1.10421967379919366952251e+03 - 3.1379638689277575379469861e+02i),
+	(3.051485206773701584738512e-01 - 2.6805384730105297848044485e-01i),
+	(-7.33294728684187933370938e+01 + 1.574445942284918251038144e+01i),
+	(-7.478643293945957535757355e+03 + 1.6348382209913353929473321e+03i),
+	(4.622316522966235701630926e+00 - 8.088695185566375256093098e+00i),
+	(-8.544333183278877406197712e+01 + 3.7505836120128166455231717e+01i),
+	(-1.934457815021493925115198e+00 + 7.3725859611767228178358673e+00i),
+	(-2.352958770061749348353548e+00 - 2.034982010440878358915409e+00i),
+	(7.79756457532134748165069e+02 + 2.8549350716819176560377717e+03i),
+}
+var exp = []complex128{
+	(1.669197736864670815125146e+01 + 1.4436895109507663689174096e+02i),
+	(2.2084389286252583447276212e+03 - 6.2759289284909211238261917e+02i),
+	(2.227538273122775173434327e-01 + 7.2468284028334191250470034e-01i),
+	(-6.5182985958153548997881627e-03 - 1.39965837915193860879044e-03i),
+	(-1.4957286524084015746110777e+04 + 3.269676455931135688988042e+03i),
+	(9.218158701983105935659273e+00 - 1.6223985291084956009304582e+01i),
+	(-1.7088175716853040841444505e+02 + 7.501382609870410713795546e+01i),
+	(-3.852461315830959613132505e+00 + 1.4808420423156073221970892e+01i),
+	(-4.586775503301407379786695e+00 - 4.178501081246873415144744e+00i),
+	(4.451337963005453491095747e-05 - 1.62977574205442915935263e-04i),
+}
+var log = []complex128{
+	(2.2194438972179194425697051e+00 + 9.9909115046919291062461269e-01i),
+	(2.0468956191154167256337289e+00 - 3.5762575021856971295156489e-02i),
+	(1.6130808329853860438751244e+00 - 1.6259990074019058442232221e+00i),
+	(2.3851910394823008710032651e+00 + 2.0502936359659111755031062e+00i),
+	(2.3096442270679923004800651e+00 + 2.9483213155446756211881774e-01i),
+	(1.7904660933974656106951860e+00 + 1.0605860367252556281902109e+00i),
+	(1.7745926939841751666177512e+00 + 4.8084556083358307819310911e-01i),
+	(1.1885403350045342425648780e+00 + 5.8969634164776659423195222e-01i),
+	(2.1833107837679082586772505e+00 - 1.3636647724582455028314573e+00i),
+	(2.3037629487273259170991671e+00 + 2.6210913895386013290915234e+00i),
+}
+var log10 = []complex128{
+	(9.6389223745559042474184943e-01 + 4.338997735671419492599631e-01i),
+	(8.8895547241376579493490892e-01 - 1.5531488990643548254864806e-02i),
+	(7.0055210462945412305244578e-01 - 7.0616239649481243222248404e-01i),
+	(1.0358753067322445311676952e+00 + 8.9043121238134980156490909e-01i),
+	(1.003065742975330237172029e+00 + 1.2804396782187887479857811e-01i),
+	(7.7758954439739162532085157e-01 + 4.6060666333341810869055108e-01i),
+	(7.7069581462315327037689152e-01 + 2.0882857371769952195512475e-01i),
+	(5.1617650901191156135137239e-01 + 2.5610186717615977620363299e-01i),
+	(9.4819982567026639742663212e-01 - 5.9223208584446952284914289e-01i),
+	(1.0005115362454417135973429e+00 + 1.1383255270407412817250921e+00i),
+}
+
+type ff struct {
+	r, theta float64
+}
+
+var polar = []ff{
+	{9.2022120669932650313380972e+00, 9.9909115046919291062461269e-01},
+	{7.7438239742296106616261394e+00, -3.5762575021856971295156489e-02},
+	{5.0182478202557746902556648e+00, -1.6259990074019058442232221e+00},
+	{1.0861137372799545160704002e+01, 2.0502936359659111755031062e+00},
+	{1.0070841084922199607011905e+01, 2.9483213155446756211881774e-01},
+	{5.9922447613166942183705192e+00, 1.0605860367252556281902109e+00},
+	{5.8978784056736762299945176e+00, 4.8084556083358307819310911e-01},
+	{3.2822866700678709020367184e+00, 5.8969634164776659423195222e-01},
+	{8.8756430028990417290744307e+00, -1.3636647724582455028314573e+00},
+	{1.0011785496777731986390856e+01, 2.6210913895386013290915234e+00},
+}
+var pow = []complex128{
+	(-2.499956739197529585028819e+00 + 1.759751724335650228957144e+00i),
+	(7.357094338218116311191939e+04 - 5.089973412479151648145882e+04i),
+	(1.320777296067768517259592e+01 - 3.165621914333901498921986e+01i),
+	(-3.123287828297300934072149e-07 - 1.9849567521490553032502223E-7i),
+	(8.0622651468477229614813e+04 - 7.80028727944573092944363e+04i),
+	(-1.0268824572103165858577141e+00 - 4.716844738244989776610672e-01i),
+	(-4.35953819012244175753187e+01 + 2.2036445974645306917648585e+02i),
+	(8.3556092283250594950239e-01 - 1.2261571947167240272593282e+01i),
+	(1.582292972120769306069625e+03 + 1.273564263524278244782512e+04i),
+	(6.592208301642122149025369e-08 + 2.584887236651661903526389e-08i),
+}
+var sin = []complex128{
+	(-1.1073801774240233539648544e+03 + 3.024539773002502192425231e+02i),
+	(1.0317037521400759359744682e+00 - 3.2208979799929570242818e-02i),
+	(-2.0501952097271429804261058e+01 - 7.2137981348240798841800967e+01i),
+	(7.3173638080346338642193078e+03 + 2.249219506193664342566248e+03i),
+	(-1.964375633631808177565226e+00 - 9.0958264713870404464159683e+00i),
+	(1.992783647158514838337674e+01 - 9.11555769410191350416942e+01i),
+	(-6.680335650741921444300349e+00 + 3.763353833142432513086117e+00i),
+	(1.2794028166657459148245993e+00 - 2.7669092099795781155109602e+00i),
+	(2.8641693949535259594188879e+03 + 7.451234399649871202841615e+02i),
+	(-4.893811726244659135553033e+01 - 5.371469305562194635957655e+01i),
+}
+var sinh = []complex128{
+	(8.34559353341652565758198e+00 + 7.2187893208650790476628899e+01i),
+	(1.1042192548260646752051112e+03 - 3.1379650595631635858792056e+02i),
+	(-8.239469336509264113041849e-02 + 9.9273668758439489098514519e-01i),
+	(7.332295456982297798219401e+01 - 1.574585908122833444899023e+01i),
+	(-7.4786432301380582103534216e+03 + 1.63483823493980029604071e+03i),
+	(4.595842179016870234028347e+00 - 8.135290105518580753211484e+00i),
+	(-8.543842533574163435246793e+01 + 3.750798997857594068272375e+01i),
+	(-1.918003500809465688017307e+00 + 7.4358344619793504041350251e+00i),
+	(-2.233816733239658031433147e+00 - 2.143519070805995056229335e+00i),
+	(-7.797564130187551181105341e+02 - 2.8549352346594918614806877e+03i),
+}
+var sqrt = []complex128{
+	(2.6628203086086130543813948e+00 + 1.4531345674282185229796902e+00i),
+	(2.7823278427251986247149295e+00 - 4.9756907317005224529115567e-02i),
+	(1.5397025302089642757361015e+00 - 1.6271336573016637535695727e+00i),
+	(1.7103411581506875260277898e+00 + 2.8170677122737589676157029e+00i),
+	(3.1390392472953103383607947e+00 + 4.6612625849858653248980849e-01i),
+	(2.1117080764822417640789287e+00 + 1.2381170223514273234967850e+00i),
+	(2.3587032281672256703926939e+00 + 5.7827111903257349935720172e-01i),
+	(1.7335262588873410476661577e+00 + 5.2647258220721269141550382e-01i),
+	(2.3131094974708716531499282e+00 - 1.8775429304303785570775490e+00i),
+	(8.1420535745048086240947359e-01 + 3.0575897587277248522656113e+00i),
+}
+var tan = []complex128{
+	(-1.928757919086441129134525e-07 + 1.0000003267499169073251826e+00i),
+	(1.242412685364183792138948e+00 - 3.17149693883133370106696e+00i),
+	(-4.6745126251587795225571826e-05 - 9.9992439225263959286114298e-01i),
+	(4.792363401193648192887116e-09 + 1.0000000070589333451557723e+00i),
+	(2.345740824080089140287315e-03 + 9.947733046570988661022763e-01i),
+	(-2.396030789494815566088809e-05 + 9.9994781345418591429826779e-01i),
+	(-7.370204836644931340905303e-03 + 1.0043553413417138987717748e+00i),
+	(-3.691803847992048527007457e-02 + 9.6475071993469548066328894e-01i),
+	(-2.781955256713729368401878e-08 - 1.000000049848910609006646e+00i),
+	(9.4281590064030478879791249e-05 + 9.9999119340863718183758545e-01i),
+}
+var tanh = []complex128{
+	(1.0000921981225144748819918e+00 + 2.160986245871518020231507e-05i),
+	(9.9999967727531993209562591e-01 - 1.9953763222959658873657676e-07i),
+	(-1.765485739548037260789686e+00 + 1.7024216325552852445168471e+00i),
+	(-9.999189442732736452807108e-01 + 3.64906070494473701938098e-05i),
+	(9.9999999224622333738729767e-01 - 3.560088949517914774813046e-09i),
+	(1.0029324933367326862499343e+00 - 4.948790309797102353137528e-03i),
+	(9.9996113064788012488693567e-01 - 4.226995742097032481451259e-05i),
+	(1.0074784189316340029873945e+00 - 4.194050814891697808029407e-03i),
+	(9.9385534229718327109131502e-01 + 5.144217985914355502713437e-02i),
+	(-1.0000000491604982429364892e+00 - 2.901873195374433112227349e-08i),
+}
+
+// special cases
+var vcAbsSC = []complex128{
+	NaN(),
+}
+var absSC = []float64{
+	math.NaN(),
+}
+var vcAcosSC = []complex128{
+	NaN(),
+}
+var acosSC = []complex128{
+	NaN(),
+}
+var vcAcoshSC = []complex128{
+	NaN(),
+}
+var acoshSC = []complex128{
+	NaN(),
+}
+var vcAsinSC = []complex128{
+	NaN(),
+}
+var asinSC = []complex128{
+	NaN(),
+}
+var vcAsinhSC = []complex128{
+	NaN(),
+}
+var asinhSC = []complex128{
+	NaN(),
+}
+var vcAtanSC = []complex128{
+	NaN(),
+}
+var atanSC = []complex128{
+	NaN(),
+}
+var vcAtanhSC = []complex128{
+	NaN(),
+}
+var atanhSC = []complex128{
+	NaN(),
+}
+var vcConjSC = []complex128{
+	NaN(),
+}
+var conjSC = []complex128{
+	NaN(),
+}
+var vcCosSC = []complex128{
+	NaN(),
+}
+var cosSC = []complex128{
+	NaN(),
+}
+var vcCoshSC = []complex128{
+	NaN(),
+}
+var coshSC = []complex128{
+	NaN(),
+}
+var vcExpSC = []complex128{
+	NaN(),
+}
+var expSC = []complex128{
+	NaN(),
+}
+var vcIsNaNSC = []complex128{
+	complex(math.Inf(-1), math.Inf(-1)),
+	complex(math.Inf(-1), math.NaN()),
+	complex(math.NaN(), math.Inf(-1)),
+	complex(0, math.NaN()),
+	complex(math.NaN(), 0),
+	complex(math.Inf(1), math.Inf(1)),
+	complex(math.Inf(1), math.NaN()),
+	complex(math.NaN(), math.Inf(1)),
+	complex(math.NaN(), math.NaN()),
+}
+var isNaNSC = []bool{
+	false,
+	false,
+	false,
+	true,
+	true,
+	false,
+	false,
+	false,
+	true,
+}
+var vcLogSC = []complex128{
+	NaN(),
+}
+var logSC = []complex128{
+	NaN(),
+}
+var vcLog10SC = []complex128{
+	NaN(),
+}
+var log10SC = []complex128{
+	NaN(),
+}
+var vcPolarSC = []complex128{
+	NaN(),
+}
+var polarSC = []ff{
+	{math.NaN(), math.NaN()},
+}
+var vcPowSC = [][2]complex128{
+	{NaN(), NaN()},
+}
+var powSC = []complex128{
+	NaN(),
+}
+var vcSinSC = []complex128{
+	NaN(),
+}
+var sinSC = []complex128{
+	NaN(),
+}
+var vcSinhSC = []complex128{
+	NaN(),
+}
+var sinhSC = []complex128{
+	NaN(),
+}
+var vcSqrtSC = []complex128{
+	NaN(),
+}
+var sqrtSC = []complex128{
+	NaN(),
+}
+var vcTanSC = []complex128{
+	NaN(),
+}
+var tanSC = []complex128{
+	NaN(),
+}
+var vcTanhSC = []complex128{
+	NaN(),
+}
+var tanhSC = []complex128{
+	NaN(),
+}
+
+// functions borrowed from pkg/math/all_test.go
+func tolerance(a, b, e float64) bool {
+	d := a - b
+	if d < 0 {
+		d = -d
+	}
+
+	if a != 0 {
+		e = e * a
+		if e < 0 {
+			e = -e
+		}
+	}
+	return d < e
+}
+func soclose(a, b, e float64) bool { return tolerance(a, b, e) }
+func veryclose(a, b float64) bool  { return tolerance(a, b, 4e-16) }
+func alike(a, b float64) bool {
+	switch {
+	case a != a && b != b: // math.IsNaN(a) && math.IsNaN(b):
+		return true
+	case a == b:
+		return math.Signbit(a) == math.Signbit(b)
+	}
+	return false
+}
+
+func cTolerance(a, b complex128, e float64) bool {
+	d := Abs(a - b)
+	if a != 0 {
+		e = e * Abs(a)
+		if e < 0 {
+			e = -e
+		}
+	}
+	return d < e
+}
+func cSoclose(a, b complex128, e float64) bool { return cTolerance(a, b, e) }
+func cVeryclose(a, b complex128) bool          { return cTolerance(a, b, 4e-16) }
+func cAlike(a, b complex128) bool {
+	switch {
+	case IsNaN(a) && IsNaN(b):
+		return true
+	case a == b:
+		return math.Signbit(real(a)) == math.Signbit(real(b)) && math.Signbit(imag(a)) == math.Signbit(imag(b))
+	}
+	return false
+}
+
+func TestAbs(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Abs(vc[i]); !veryclose(abs[i], f) {
+			t.Errorf("Abs(%g) = %g, want %g", vc[i], f, abs[i])
+		}
+	}
+	for i := 0; i < len(vcAbsSC); i++ {
+		if f := Abs(vcAbsSC[i]); !alike(absSC[i], f) {
+			t.Errorf("Abs(%g) = %g, want %g", vcAbsSC[i], f, absSC[i])
+		}
+	}
+}
+func TestAcos(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Acos(vc[i]); !cSoclose(acos[i], f, 1e-14) {
+			t.Errorf("Acos(%g) = %g, want %g", vc[i], f, acos[i])
+		}
+	}
+	for i := 0; i < len(vcAcosSC); i++ {
+		if f := Acos(vcAcosSC[i]); !cAlike(acosSC[i], f) {
+			t.Errorf("Acos(%g) = %g, want %g", vcAcosSC[i], f, acosSC[i])
+		}
+	}
+}
+func TestAcosh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Acosh(vc[i]); !cSoclose(acosh[i], f, 1e-14) {
+			t.Errorf("Acosh(%g) = %g, want %g", vc[i], f, acosh[i])
+		}
+	}
+	for i := 0; i < len(vcAcoshSC); i++ {
+		if f := Acosh(vcAcoshSC[i]); !cAlike(acoshSC[i], f) {
+			t.Errorf("Acosh(%g) = %g, want %g", vcAcoshSC[i], f, acoshSC[i])
+		}
+	}
+}
+func TestAsin(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Asin(vc[i]); !cSoclose(asin[i], f, 1e-14) {
+			t.Errorf("Asin(%g) = %g, want %g", vc[i], f, asin[i])
+		}
+	}
+	for i := 0; i < len(vcAsinSC); i++ {
+		if f := Asin(vcAsinSC[i]); !cAlike(asinSC[i], f) {
+			t.Errorf("Asin(%g) = %g, want %g", vcAsinSC[i], f, asinSC[i])
+		}
+	}
+}
+func TestAsinh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Asinh(vc[i]); !cSoclose(asinh[i], f, 4e-15) {
+			t.Errorf("Asinh(%g) = %g, want %g", vc[i], f, asinh[i])
+		}
+	}
+	for i := 0; i < len(vcAsinhSC); i++ {
+		if f := Asinh(vcAsinhSC[i]); !cAlike(asinhSC[i], f) {
+			t.Errorf("Asinh(%g) = %g, want %g", vcAsinhSC[i], f, asinhSC[i])
+		}
+	}
+}
+func TestAtan(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Atan(vc[i]); !cVeryclose(atan[i], f) {
+			t.Errorf("Atan(%g) = %g, want %g", vc[i], f, atan[i])
+		}
+	}
+	for i := 0; i < len(vcAtanSC); i++ {
+		if f := Atan(vcAtanSC[i]); !cAlike(atanSC[i], f) {
+			t.Errorf("Atan(%g) = %g, want %g", vcAtanSC[i], f, atanSC[i])
+		}
+	}
+}
+func TestAtanh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Atanh(vc[i]); !cVeryclose(atanh[i], f) {
+			t.Errorf("Atanh(%g) = %g, want %g", vc[i], f, atanh[i])
+		}
+	}
+	for i := 0; i < len(vcAtanhSC); i++ {
+		if f := Atanh(vcAtanhSC[i]); !cAlike(atanhSC[i], f) {
+			t.Errorf("Atanh(%g) = %g, want %g", vcAtanhSC[i], f, atanhSC[i])
+		}
+	}
+}
+func TestConj(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Conj(vc[i]); !cVeryclose(conj[i], f) {
+			t.Errorf("Conj(%g) = %g, want %g", vc[i], f, conj[i])
+		}
+	}
+	for i := 0; i < len(vcConjSC); i++ {
+		if f := Conj(vcConjSC[i]); !cAlike(conjSC[i], f) {
+			t.Errorf("Conj(%g) = %g, want %g", vcConjSC[i], f, conjSC[i])
+		}
+	}
+}
+func TestCos(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Cos(vc[i]); !cSoclose(cos[i], f, 3e-15) {
+			t.Errorf("Cos(%g) = %g, want %g", vc[i], f, cos[i])
+		}
+	}
+	for i := 0; i < len(vcCosSC); i++ {
+		if f := Cos(vcCosSC[i]); !cAlike(cosSC[i], f) {
+			t.Errorf("Cos(%g) = %g, want %g", vcCosSC[i], f, cosSC[i])
+		}
+	}
+}
+func TestCosh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Cosh(vc[i]); !cSoclose(cosh[i], f, 2e-15) {
+			t.Errorf("Cosh(%g) = %g, want %g", vc[i], f, cosh[i])
+		}
+	}
+	for i := 0; i < len(vcCoshSC); i++ {
+		if f := Cosh(vcCoshSC[i]); !cAlike(coshSC[i], f) {
+			t.Errorf("Cosh(%g) = %g, want %g", vcCoshSC[i], f, coshSC[i])
+		}
+	}
+}
+func TestExp(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Exp(vc[i]); !cSoclose(exp[i], f, 1e-15) {
+			t.Errorf("Exp(%g) = %g, want %g", vc[i], f, exp[i])
+		}
+	}
+	for i := 0; i < len(vcExpSC); i++ {
+		if f := Exp(vcExpSC[i]); !cAlike(expSC[i], f) {
+			t.Errorf("Exp(%g) = %g, want %g", vcExpSC[i], f, expSC[i])
+		}
+	}
+}
+func TestIsNaN(t *testing.T) {
+	for i := 0; i < len(vcIsNaNSC); i++ {
+		if f := IsNaN(vcIsNaNSC[i]); isNaNSC[i] != f {
+			t.Errorf("IsNaN(%v) = %v, want %v", vcIsNaNSC[i], f, isNaNSC[i])
+		}
+	}
+}
+func TestLog(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Log(vc[i]); !cVeryclose(log[i], f) {
+			t.Errorf("Log(%g) = %g, want %g", vc[i], f, log[i])
+		}
+	}
+	for i := 0; i < len(vcLogSC); i++ {
+		if f := Log(vcLogSC[i]); !cAlike(logSC[i], f) {
+			t.Errorf("Log(%g) = %g, want %g", vcLogSC[i], f, logSC[i])
+		}
+	}
+}
+func TestLog10(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Log10(vc[i]); !cVeryclose(log10[i], f) {
+			t.Errorf("Log10(%g) = %g, want %g", vc[i], f, log10[i])
+		}
+	}
+	for i := 0; i < len(vcLog10SC); i++ {
+		if f := Log10(vcLog10SC[i]); !cAlike(log10SC[i], f) {
+			t.Errorf("Log10(%g) = %g, want %g", vcLog10SC[i], f, log10SC[i])
+		}
+	}
+}
+func TestPolar(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if r, theta := Polar(vc[i]); !veryclose(polar[i].r, r) && !veryclose(polar[i].theta, theta) {
+			t.Errorf("Polar(%g) = %g, %g want %g, %g", vc[i], r, theta, polar[i].r, polar[i].theta)
+		}
+	}
+	for i := 0; i < len(vcPolarSC); i++ {
+		if r, theta := Polar(vcPolarSC[i]); !alike(polarSC[i].r, r) && !alike(polarSC[i].theta, theta) {
+			t.Errorf("Polar(%g) = %g, %g, want %g, %g", vcPolarSC[i], r, theta, polarSC[i].r, polarSC[i].theta)
+		}
+	}
+}
+func TestPow(t *testing.T) {
+	var a = complex(3.0, 3.0)
+	for i := 0; i < len(vc); i++ {
+		if f := Pow(a, vc[i]); !cSoclose(pow[i], f, 4e-15) {
+			t.Errorf("Pow(%g, %g) = %g, want %g", a, vc[i], f, pow[i])
+		}
+	}
+	for i := 0; i < len(vcPowSC); i++ {
+		if f := Pow(vcPowSC[i][0], vcPowSC[i][0]); !cAlike(powSC[i], f) {
+			t.Errorf("Pow(%g, %g) = %g, want %g", vcPowSC[i][0], vcPowSC[i][0], f, powSC[i])
+		}
+	}
+}
+func TestRect(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Rect(polar[i].r, polar[i].theta); !cVeryclose(vc[i], f) {
+			t.Errorf("Rect(%g, %g) = %g want %g", polar[i].r, polar[i].theta, f, vc[i])
+		}
+	}
+	for i := 0; i < len(vcPolarSC); i++ {
+		if f := Rect(polarSC[i].r, polarSC[i].theta); !cAlike(vcPolarSC[i], f) {
+			t.Errorf("Rect(%g, %g) = %g, want %g", polarSC[i].r, polarSC[i].theta, f, vcPolarSC[i])
+		}
+	}
+}
+func TestSin(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Sin(vc[i]); !cSoclose(sin[i], f, 2e-15) {
+			t.Errorf("Sin(%g) = %g, want %g", vc[i], f, sin[i])
+		}
+	}
+	for i := 0; i < len(vcSinSC); i++ {
+		if f := Sin(vcSinSC[i]); !cAlike(sinSC[i], f) {
+			t.Errorf("Sin(%g) = %g, want %g", vcSinSC[i], f, sinSC[i])
+		}
+	}
+}
+func TestSinh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Sinh(vc[i]); !cSoclose(sinh[i], f, 2e-15) {
+			t.Errorf("Sinh(%g) = %g, want %g", vc[i], f, sinh[i])
+		}
+	}
+	for i := 0; i < len(vcSinhSC); i++ {
+		if f := Sinh(vcSinhSC[i]); !cAlike(sinhSC[i], f) {
+			t.Errorf("Sinh(%g) = %g, want %g", vcSinhSC[i], f, sinhSC[i])
+		}
+	}
+}
+func TestSqrt(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Sqrt(vc[i]); !cVeryclose(sqrt[i], f) {
+			t.Errorf("Sqrt(%g) = %g, want %g", vc[i], f, sqrt[i])
+		}
+	}
+	for i := 0; i < len(vcSqrtSC); i++ {
+		if f := Sqrt(vcSqrtSC[i]); !cAlike(sqrtSC[i], f) {
+			t.Errorf("Sqrt(%g) = %g, want %g", vcSqrtSC[i], f, sqrtSC[i])
+		}
+	}
+}
+func TestTan(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Tan(vc[i]); !cSoclose(tan[i], f, 3e-15) {
+			t.Errorf("Tan(%g) = %g, want %g", vc[i], f, tan[i])
+		}
+	}
+	for i := 0; i < len(vcTanSC); i++ {
+		if f := Tan(vcTanSC[i]); !cAlike(tanSC[i], f) {
+			t.Errorf("Tan(%g) = %g, want %g", vcTanSC[i], f, tanSC[i])
+		}
+	}
+}
+func TestTanh(t *testing.T) {
+	for i := 0; i < len(vc); i++ {
+		if f := Tanh(vc[i]); !cSoclose(tanh[i], f, 2e-15) {
+			t.Errorf("Tanh(%g) = %g, want %g", vc[i], f, tanh[i])
+		}
+	}
+	for i := 0; i < len(vcTanhSC); i++ {
+		if f := Tanh(vcTanhSC[i]); !cAlike(tanhSC[i], f) {
+			t.Errorf("Tanh(%g) = %g, want %g", vcTanhSC[i], f, tanhSC[i])
+		}
+	}
+}
+
+func BenchmarkAbs(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Abs(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAcos(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Acos(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAcosh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Acosh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAsin(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Asin(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAsinh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Asinh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAtan(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Atan(complex(2.5, 3.5))
+	}
+}
+func BenchmarkAtanh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Atanh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkConj(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Conj(complex(2.5, 3.5))
+	}
+}
+func BenchmarkCos(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Cos(complex(2.5, 3.5))
+	}
+}
+func BenchmarkCosh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Cosh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Exp(complex(2.5, 3.5))
+	}
+}
+func BenchmarkLog(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Log(complex(2.5, 3.5))
+	}
+}
+func BenchmarkLog10(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Log10(complex(2.5, 3.5))
+	}
+}
+func BenchmarkPhase(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Phase(complex(2.5, 3.5))
+	}
+}
+func BenchmarkPolar(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Polar(complex(2.5, 3.5))
+	}
+}
+func BenchmarkPow(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Pow(complex(2.5, 3.5), complex(2.5, 3.5))
+	}
+}
+func BenchmarkRect(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Rect(2.5, 1.5)
+	}
+}
+func BenchmarkSin(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sin(complex(2.5, 3.5))
+	}
+}
+func BenchmarkSinh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sinh(complex(2.5, 3.5))
+	}
+}
+func BenchmarkSqrt(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Sqrt(complex(2.5, 3.5))
+	}
+}
+func BenchmarkTan(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Tan(complex(2.5, 3.5))
+	}
+}
+func BenchmarkTanh(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Tanh(complex(2.5, 3.5))
+	}
+}
diff --git a/src/pkg/math/cmplx/conj.go b/src/pkg/math/cmplx/conj.go
new file mode 100644
index 0000000..34a4277
--- /dev/null
+++ b/src/pkg/math/cmplx/conj.go
@@ -0,0 +1,8 @@
+// Copyright 2010 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 cmplx
+
+// Conj returns the complex conjugate of x.
+func Conj(x complex128) complex128 { return complex(real(x), -imag(x)) }
diff --git a/src/pkg/math/cmplx/exp.go b/src/pkg/math/cmplx/exp.go
new file mode 100644
index 0000000..485ed2c
--- /dev/null
+++ b/src/pkg/math/cmplx/exp.go
@@ -0,0 +1,55 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// Complex exponential function
+//
+// DESCRIPTION:
+//
+// Returns the complex exponential of the complex argument z.
+//
+// If
+//     z = x + iy,
+//     r = exp(x),
+// then
+//     w = r cos y + i r sin y.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      8700       3.7e-17     1.1e-17
+//    IEEE      -10,+10     30000       3.0e-16     8.7e-17
+
+// Exp returns e**x, the base-e exponential of x.
+func Exp(x complex128) complex128 {
+	r := math.Exp(real(x))
+	s, c := math.Sincos(imag(x))
+	return complex(r*c, r*s)
+}
diff --git a/src/pkg/math/cmplx/isinf.go b/src/pkg/math/cmplx/isinf.go
new file mode 100644
index 0000000..d5a65b4
--- /dev/null
+++ b/src/pkg/math/cmplx/isinf.go
@@ -0,0 +1,21 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// IsInf returns true if either real(x) or imag(x) is an infinity.
+func IsInf(x complex128) bool {
+	if math.IsInf(real(x), 0) || math.IsInf(imag(x), 0) {
+		return true
+	}
+	return false
+}
+
+// Inf returns a complex infinity, complex(+Inf, +Inf).
+func Inf() complex128 {
+	inf := math.Inf(1)
+	return complex(inf, inf)
+}
diff --git a/src/pkg/math/cmplx/isnan.go b/src/pkg/math/cmplx/isnan.go
new file mode 100644
index 0000000..05d0cce
--- /dev/null
+++ b/src/pkg/math/cmplx/isnan.go
@@ -0,0 +1,25 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// IsNaN returns true if either real(x) or imag(x) is NaN
+// and neither is an infinity.
+func IsNaN(x complex128) bool {
+	switch {
+	case math.IsInf(real(x), 0) || math.IsInf(imag(x), 0):
+		return false
+	case math.IsNaN(real(x)) || math.IsNaN(imag(x)):
+		return true
+	}
+	return false
+}
+
+// NaN returns a complex ``not-a-number'' value.
+func NaN() complex128 {
+	nan := math.NaN()
+	return complex(nan, nan)
+}
diff --git a/src/pkg/math/cmplx/log.go b/src/pkg/math/cmplx/log.go
new file mode 100644
index 0000000..881a064
--- /dev/null
+++ b/src/pkg/math/cmplx/log.go
@@ -0,0 +1,64 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// Complex natural logarithm
+//
+// DESCRIPTION:
+//
+// Returns complex logarithm to the base e (2.718...) of
+// the complex argument z.
+//
+// If
+//       z = x + iy, r = sqrt( x**2 + y**2 ),
+// then
+//       w = log(r) + i arctan(y/x).
+//
+// The arctangent ranges from -PI to +PI.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      7000       8.5e-17     1.9e-17
+//    IEEE      -10,+10     30000       5.0e-15     1.1e-16
+//
+// Larger relative error can be observed for z near 1 +i0.
+// In IEEE arithmetic the peak absolute error is 5.2e-16, rms
+// absolute error 1.0e-16.
+
+// Log returns the natural logarithm of x.
+func Log(x complex128) complex128 {
+	return complex(math.Log(Abs(x)), Phase(x))
+}
+
+// Log10 returns the decimal logarithm of x.
+func Log10(x complex128) complex128 {
+	return math.Log10E * Log(x)
+}
diff --git a/src/pkg/math/cmplx/phase.go b/src/pkg/math/cmplx/phase.go
new file mode 100644
index 0000000..03cece8
--- /dev/null
+++ b/src/pkg/math/cmplx/phase.go
@@ -0,0 +1,11 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// Phase returns the phase (also called the argument) of x.
+// The returned value is in the range [-Pi, Pi].
+func Phase(x complex128) float64 { return math.Atan2(imag(x), real(x)) }
diff --git a/src/pkg/math/cmplx/polar.go b/src/pkg/math/cmplx/polar.go
new file mode 100644
index 0000000..9b192bc
--- /dev/null
+++ b/src/pkg/math/cmplx/polar.go
@@ -0,0 +1,12 @@
+// Copyright 2010 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 cmplx
+
+// Polar returns the absolute value r and phase θ of x,
+// such that x = r * e**θi.
+// The phase is in the range [-Pi, Pi].
+func Polar(x complex128) (r, θ float64) {
+	return Abs(x), Phase(x)
+}
diff --git a/src/pkg/math/cmplx/pow.go b/src/pkg/math/cmplx/pow.go
new file mode 100644
index 0000000..4dbc583
--- /dev/null
+++ b/src/pkg/math/cmplx/pow.go
@@ -0,0 +1,60 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// Complex power function
+//
+// DESCRIPTION:
+//
+// Raises complex A to the complex Zth power.
+// Definition is per AMS55 # 4.2.8,
+// analytically equivalent to cpow(a,z) = cexp(z clog(a)).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -10,+10     30000       9.4e-15     1.5e-15
+
+// Pow returns x**y, the base-x exponential of y.
+func Pow(x, y complex128) complex128 {
+	modulus := Abs(x)
+	if modulus == 0 {
+		return complex(0, 0)
+	}
+	r := math.Pow(modulus, real(y))
+	arg := Phase(x)
+	theta := real(y) * arg
+	if imag(y) != 0 {
+		r *= math.Exp(-imag(y) * arg)
+		theta += imag(y) * math.Log(modulus)
+	}
+	s, c := math.Sincos(theta)
+	return complex(r*c, r*s)
+}
diff --git a/src/pkg/math/cmplx/rect.go b/src/pkg/math/cmplx/rect.go
new file mode 100644
index 0000000..bf94d78
--- /dev/null
+++ b/src/pkg/math/cmplx/rect.go
@@ -0,0 +1,13 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// Rect returns the complex number x with polar coordinates r, θ.
+func Rect(r, θ float64) complex128 {
+	s, c := math.Sincos(θ)
+	return complex(r*c, r*s)
+}
diff --git a/src/pkg/math/cmplx/sin.go b/src/pkg/math/cmplx/sin.go
new file mode 100644
index 0000000..2c57536
--- /dev/null
+++ b/src/pkg/math/cmplx/sin.go
@@ -0,0 +1,132 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// Complex circular sine
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//
+//     w = sin x  cosh y  +  i cos x sinh y.
+//
+// csin(z) = -i csinh(iz).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      8400       5.3e-17     1.3e-17
+//    IEEE      -10,+10     30000       3.8e-16     1.0e-16
+// Also tested by csin(casin(z)) = z.
+
+// Sin returns the sine of x.
+func Sin(x complex128) complex128 {
+	s, c := math.Sincos(real(x))
+	sh, ch := sinhcosh(imag(x))
+	return complex(s*ch, c*sh)
+}
+
+// Complex hyperbolic sine
+//
+// DESCRIPTION:
+//
+// csinh z = (cexp(z) - cexp(-z))/2
+//         = sinh x * cos y  +  i cosh x * sin y .
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -10,+10     30000       3.1e-16     8.2e-17
+
+// Sinh returns the hyperbolic sine of x.
+func Sinh(x complex128) complex128 {
+	s, c := math.Sincos(imag(x))
+	sh, ch := sinhcosh(real(x))
+	return complex(c*sh, s*ch)
+}
+
+// Complex circular cosine
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//
+//     w = cos x  cosh y  -  i sin x sinh y.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      8400       4.5e-17     1.3e-17
+//    IEEE      -10,+10     30000       3.8e-16     1.0e-16
+
+// Cos returns the cosine of x.
+func Cos(x complex128) complex128 {
+	s, c := math.Sincos(real(x))
+	sh, ch := sinhcosh(imag(x))
+	return complex(c*ch, -s*sh)
+}
+
+// Complex hyperbolic cosine
+//
+// DESCRIPTION:
+//
+// ccosh(z) = cosh x  cos y + i sinh x sin y .
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -10,+10     30000       2.9e-16     8.1e-17
+
+// Cosh returns the hyperbolic cosine of x.
+func Cosh(x complex128) complex128 {
+	s, c := math.Sincos(imag(x))
+	sh, ch := sinhcosh(real(x))
+	return complex(c*ch, s*sh)
+}
+
+// calculate sinh and cosh
+func sinhcosh(x float64) (sh, ch float64) {
+	if math.Abs(x) <= 0.5 {
+		return math.Sinh(x), math.Cosh(x)
+	}
+	e := math.Exp(x)
+	ei := 0.5 / e
+	e *= 0.5
+	return e - ei, e + ei
+}
diff --git a/src/pkg/math/cmplx/sqrt.go b/src/pkg/math/cmplx/sqrt.go
new file mode 100644
index 0000000..179b539
--- /dev/null
+++ b/src/pkg/math/cmplx/sqrt.go
@@ -0,0 +1,103 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// Complex square root
+//
+// DESCRIPTION:
+//
+// If z = x + iy,  r = |z|, then
+//
+//                       1/2
+// Re w  =  [ (r + x)/2 ]   ,
+//
+//                       1/2
+// Im w  =  [ (r - x)/2 ]   .
+//
+// Cancellation error in r-x or r+x is avoided by using the
+// identity  2 Re w Im w  =  y.
+//
+// Note that -w is also a square root of z.  The root chosen
+// is always in the right half plane and Im w has the same sign as y.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10     25000       3.2e-17     9.6e-18
+//    IEEE      -10,+10   1,000,000     2.9e-16     6.1e-17
+
+// Sqrt returns the square root of x.
+func Sqrt(x complex128) complex128 {
+	if imag(x) == 0 {
+		if real(x) == 0 {
+			return complex(0, 0)
+		}
+		if real(x) < 0 {
+			return complex(0, math.Sqrt(-real(x)))
+		}
+		return complex(math.Sqrt(real(x)), 0)
+	}
+	if real(x) == 0 {
+		if imag(x) < 0 {
+			r := math.Sqrt(-0.5 * imag(x))
+			return complex(r, -r)
+		}
+		r := math.Sqrt(0.5 * imag(x))
+		return complex(r, r)
+	}
+	a := real(x)
+	b := imag(x)
+	var scale float64
+	// Rescale to avoid internal overflow or underflow.
+	if math.Abs(a) > 4 || math.Abs(b) > 4 {
+		a *= 0.25
+		b *= 0.25
+		scale = 2
+	} else {
+		a *= 1.8014398509481984e16 // 2**54
+		b *= 1.8014398509481984e16
+		scale = 7.450580596923828125e-9 // 2**-27
+	}
+	r := math.Hypot(a, b)
+	var t float64
+	if a > 0 {
+		t = math.Sqrt(0.5*r + 0.5*a)
+		r = scale * math.Abs((0.5*b)/t)
+		t *= scale
+	} else {
+		r = math.Sqrt(0.5*r - 0.5*a)
+		t = scale * math.Abs((0.5*b)/r)
+		r *= scale
+	}
+	if b < 0 {
+		return complex(t, -r)
+	}
+	return complex(t, r)
+}
diff --git a/src/pkg/math/cmplx/tan.go b/src/pkg/math/cmplx/tan.go
new file mode 100644
index 0000000..9485315
--- /dev/null
+++ b/src/pkg/math/cmplx/tan.go
@@ -0,0 +1,184 @@
+// Copyright 2010 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 cmplx
+
+import "math"
+
+// The original C code, the long comment, and the constants
+// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c.
+// The go code is a simplified version of the original C.
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// Complex circular tangent
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//
+//           sin 2x  +  i sinh 2y
+//     w  =  --------------------.
+//            cos 2x  +  cosh 2y
+//
+// On the real axis the denominator is zero at odd multiples
+// of PI/2.  The denominator is evaluated by its Taylor
+// series near these points.
+//
+// ctan(z) = -i ctanh(iz).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      5200       7.1e-17     1.6e-17
+//    IEEE      -10,+10     30000       7.2e-16     1.2e-16
+// Also tested by ctan * ccot = 1 and catan(ctan(z))  =  z.
+
+// Tan returns the tangent of x.
+func Tan(x complex128) complex128 {
+	d := math.Cos(2*real(x)) + math.Cosh(2*imag(x))
+	if math.Abs(d) < 0.25 {
+		d = tanSeries(x)
+	}
+	if d == 0 {
+		return Inf()
+	}
+	return complex(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d)
+}
+
+// Complex hyperbolic tangent
+//
+// DESCRIPTION:
+//
+// tanh z = (sinh 2x  +  i sin 2y) / (cosh 2x + cos 2y) .
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    IEEE      -10,+10     30000       1.7e-14     2.4e-16
+
+// Tanh returns the hyperbolic tangent of x.
+func Tanh(x complex128) complex128 {
+	d := math.Cosh(2*real(x)) + math.Cos(2*imag(x))
+	if d == 0 {
+		return Inf()
+	}
+	return complex(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d)
+}
+
+// Program to subtract nearest integer multiple of PI
+func reducePi(x float64) float64 {
+	const (
+		// extended precision value of PI:
+		DP1 = 3.14159265160560607910E0   // ?? 0x400921fb54000000
+		DP2 = 1.98418714791870343106E-9  // ?? 0x3e210b4610000000
+		DP3 = 1.14423774522196636802E-17 // ?? 0x3c6a62633145c06e
+	)
+	t := x / math.Pi
+	if t >= 0 {
+		t += 0.5
+	} else {
+		t -= 0.5
+	}
+	t = float64(int64(t)) // int64(t) = the multiple
+	return ((x - t*DP1) - t*DP2) - t*DP3
+}
+
+// Taylor series expansion for cosh(2y) - cos(2x)
+func tanSeries(z complex128) float64 {
+	const MACHEP = 1.0 / (1 << 53)
+	x := math.Abs(2 * real(z))
+	y := math.Abs(2 * imag(z))
+	x = reducePi(x)
+	x = x * x
+	y = y * y
+	x2 := 1.0
+	y2 := 1.0
+	f := 1.0
+	rn := 0.0
+	d := 0.0
+	for {
+		rn += 1
+		f *= rn
+		rn += 1
+		f *= rn
+		x2 *= x
+		y2 *= y
+		t := y2 + x2
+		t /= f
+		d += t
+
+		rn += 1
+		f *= rn
+		rn += 1
+		f *= rn
+		x2 *= x
+		y2 *= y
+		t = y2 - x2
+		t /= f
+		d += t
+		if math.Abs(t/d) <= MACHEP {
+			break
+		}
+	}
+	return d
+}
+
+// Complex circular cotangent
+//
+// DESCRIPTION:
+//
+// If
+//     z = x + iy,
+//
+// then
+//
+//           sin 2x  -  i sinh 2y
+//     w  =  --------------------.
+//            cosh 2y  -  cos 2x
+//
+// On the real axis, the denominator has zeros at even
+// multiples of PI/2.  Near these points it is evaluated
+// by a Taylor series.
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC       -10,+10      3000       6.5e-17     1.6e-17
+//    IEEE      -10,+10     30000       9.2e-16     1.2e-16
+// Also tested by ctan * ccot = 1 + i0.
+
+// Cot returns the cotangent of x.
+func Cot(x complex128) complex128 {
+	d := math.Cosh(2*imag(x)) - math.Cos(2*real(x))
+	if math.Abs(d) < 0.25 {
+		d = tanSeries(x)
+	}
+	if d == 0 {
+		return Inf()
+	}
+	return complex(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d)
+}
diff --git a/src/pkg/math/const.go b/src/pkg/math/const.go
index a108d3e..282561f 100644
--- a/src/pkg/math/const.go
+++ b/src/pkg/math/const.go
@@ -49,5 +49,3 @@ const (
 	MaxUint32 = 1<<32 - 1
 	MaxUint64 = 1<<64 - 1
 )
-
-// BUG(rsc): The manual should define the special cases for all of these functions.
diff --git a/src/pkg/math/dim.go b/src/pkg/math/dim.go
new file mode 100644
index 0000000..16363ac
--- /dev/null
+++ b/src/pkg/math/dim.go
@@ -0,0 +1,76 @@
+// Copyright 2010 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 math
+
+// Dim returns the maximum of x-y or 0.
+//
+// Special cases are:
+//	Dim(+Inf, +Inf) = NaN
+//	Dim(-Inf, -Inf) = NaN
+//	Dim(x, NaN) = Dim(NaN, x) = NaN
+func Dim(x, y float64) float64
+
+func dim(x, y float64) float64 {
+	return max(x-y, 0)
+}
+
+// Max returns the larger of x or y.
+//
+// Special cases are:
+//	Max(x, +Inf) = Max(+Inf, x) = +Inf
+//	Max(x, NaN) = Max(NaN, x) = NaN
+//	Max(+0, ±0) = Max(±0, +0) = +0
+//	Max(-0, -0) = -0
+func Max(x, y float64) float64
+
+func max(x, y float64) float64 {
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us
+	// special cases
+	switch {
+	case x > MaxFloat64 || y > MaxFloat64: // IsInf(x, 1) || IsInf(y, 1):
+		return Inf(1)
+	case x != x || y != y: // IsNaN(x) || IsNaN(y):
+		return NaN()
+	case x == 0 && x == y:
+		if Signbit(x) {
+			return y
+		}
+		return x
+	}
+	if x > y {
+		return x
+	}
+	return y
+}
+
+// Min returns the smaller of x or y.
+//
+// Special cases are:
+//	Min(x, -Inf) = Min(-Inf, x) = -Inf
+//	Min(x, NaN) = Min(NaN, x) = NaN
+//	Min(-0, ±0) = Min(±0, -0) = -0
+func Min(x, y float64) float64
+
+func min(x, y float64) float64 {
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us
+	// special cases
+	switch {
+	case x < -MaxFloat64 || y < -MaxFloat64: // IsInf(x, -1) || IsInf(y, -1):
+		return Inf(-1)
+	case x != x || y != y: // IsNaN(x) || IsNaN(y):
+		return NaN()
+	case x == 0 && x == y:
+		if Signbit(x) {
+			return x
+		}
+		return y
+	}
+	if x < y {
+		return x
+	}
+	return y
+}
diff --git a/src/pkg/math/dim_386.s b/src/pkg/math/dim_386.s
new file mode 100644
index 0000000..6a31c75
--- /dev/null
+++ b/src/pkg/math/dim_386.s
@@ -0,0 +1,12 @@
+// Copyright 2011 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.
+
+TEXT ·Dim(SB),7,$0
+	JMP ·dim(SB)
+
+TEXT ·Max(SB),7,$0
+	JMP ·max(SB)
+
+TEXT ·Min(SB),7,$0
+	JMP ·min(SB)
diff --git a/src/pkg/math/dim_amd64.s b/src/pkg/math/dim_amd64.s
new file mode 100644
index 0000000..c867db5
--- /dev/null
+++ b/src/pkg/math/dim_amd64.s
@@ -0,0 +1,142 @@
+// Copyright 2010 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.
+
+#define PosInf 0x7FF0000000000000
+#define NaN    0x7FF0000000000001
+#define NegInf 0xFFF0000000000000
+
+// func Dim(x, y float64) float64
+TEXT ·Dim(SB),7,$0
+	// (+Inf, +Inf) special case
+	MOVQ    x+0(FP), BX
+	MOVQ    y+8(FP), CX
+	MOVQ    $PosInf, AX
+	CMPQ    AX, BX
+	JNE     dim2
+	CMPQ    AX, CX
+	JEQ     bothInf
+dim2:	// (-Inf, -Inf) special case
+	MOVQ    $NegInf, AX
+	CMPQ    AX, BX
+	JNE     dim3
+	CMPQ    AX, CX
+	JEQ     bothInf
+dim3:	// (NaN, x) or (x, NaN)
+	MOVQ    $~(1<<63), DX
+	MOVQ    $NaN, AX
+	ANDQ    DX, BX // x = |x|
+	CMPQ    AX, BX
+	JLE     isDimNaN
+	ANDQ    DX, CX // y = |y|
+	CMPQ    AX, CX
+	JLE     isDimNaN
+
+	MOVSD x+0(FP), X0
+	SUBSD y+8(FP), X0
+	MOVSD $(0.0), X1
+	MAXSD X1, X0
+	MOVSD X0, r+16(FP)
+	RET
+bothInf: // Dim(-Inf, -Inf) or Dim(+Inf, +Inf)
+	MOVQ    $NaN, AX
+isDimNaN:
+	MOVQ    AX, r+16(FP)
+	RET
+
+// func ·Max(x, y float64) float64
+TEXT ·Max(SB),7,$0
+	// +Inf special cases
+	MOVQ    $PosInf, AX
+	MOVQ    x+0(FP), R8
+	CMPQ    AX, R8
+	JEQ     isPosInf
+	MOVQ    y+8(FP), R9
+	CMPQ    AX, R9
+	JEQ     isPosInf
+	// NaN special cases
+	MOVQ    $~(1<<63), DX // bit mask
+	MOVQ    $NaN, AX
+	MOVQ    R8, BX
+	ANDQ    DX, BX // x = |x|
+	CMPQ    AX, BX
+	JLE     isMaxNaN
+	MOVQ    R9, CX
+	ANDQ    DX, CX // y = |y|
+	CMPQ    AX, CX
+	JLE     isMaxNaN
+	// ±0 special cases
+	ORQ     CX, BX
+	JEQ     isMaxZero
+
+	MOVQ    R8, X0
+	MOVQ    R9, X1
+	MAXSD   X1, X0
+	MOVSD   X0, r+16(FP)
+	RET
+isMaxNaN: // return NaN
+isPosInf: // return +Inf
+	MOVQ    AX, r+16(FP)
+	RET
+isMaxZero:
+	MOVQ    $(1<<63), AX // -0.0
+	CMPQ    AX, R8
+	JEQ     +3(PC)
+	MOVQ    R8, r+16(FP) // return 0
+	RET
+	MOVQ    R9, r+16(FP) // return other 0
+	RET
+
+/*
+	MOVQ    $0, AX
+	CMPQ    AX, R8
+	JNE     +3(PC)
+	MOVQ    R8, r+16(FP) // return 0
+	RET
+	MOVQ    R9, r+16(FP) // return other 0
+	RET
+*/
+
+// func Min(x, y float64) float64
+TEXT ·Min(SB),7,$0
+	// -Inf special cases
+	MOVQ    $NegInf, AX
+	MOVQ    x+0(FP), R8
+	CMPQ    AX, R8
+	JEQ     isNegInf
+	MOVQ    y+8(FP), R9
+	CMPQ    AX, R9
+	JEQ     isNegInf
+	// NaN special cases
+	MOVQ    $~(1<<63), DX
+	MOVQ    $NaN, AX
+	MOVQ    R8, BX
+	ANDQ    DX, BX // x = |x|
+	CMPQ    AX, BX
+	JLE     isMinNaN
+	MOVQ    R9, CX
+	ANDQ    DX, CX // y = |y|
+	CMPQ    AX, CX
+	JLE     isMinNaN
+	// ±0 special cases
+	ORQ     CX, BX
+	JEQ     isMinZero
+
+	MOVQ    R8, X0
+	MOVQ    R9, X1
+	MINSD   X1, X0
+	MOVSD X0, r+16(FP)
+	RET
+isMinNaN: // return NaN
+isNegInf: // return -Inf
+	MOVQ    AX, r+16(FP)
+	RET
+isMinZero:
+	MOVQ    $(1<<63), AX // -0.0
+	CMPQ    AX, R8
+	JEQ     +3(PC)
+	MOVQ    R9, r+16(FP) // return other 0
+	RET
+	MOVQ    R8, r+16(FP) // return -0
+	RET
+
diff --git a/src/pkg/math/dim_arm.s b/src/pkg/math/dim_arm.s
new file mode 100644
index 0000000..304fa78
--- /dev/null
+++ b/src/pkg/math/dim_arm.s
@@ -0,0 +1,12 @@
+// Copyright 2011 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.
+
+TEXT ·Dim(SB),7,$0
+	B ·dim(SB)
+
+TEXT ·Min(SB),7,$0
+	B ·min(SB)
+
+TEXT ·Max(SB),7,$0
+	B ·max(SB)
diff --git a/src/pkg/math/exp.go b/src/pkg/math/exp.go
index c519c2c..2a1710a 100644
--- a/src/pkg/math/exp.go
+++ b/src/pkg/math/exp.go
@@ -11,4 +11,185 @@ package math
 //	Exp(NaN) = NaN
 // Very large values overflow to 0 or +Inf.
 // Very small values underflow to 1.
-func Exp(x float64) float64 { return expGo(x) }
+func Exp(x float64) float64
+
+// The original C code, the long comment, and the constants
+// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c
+// and came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+//
+// exp(x)
+// Returns the exponential of x.
+//
+// Method
+//   1. Argument reduction:
+//      Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+//      Given x, find r and integer k such that
+//
+//               x = k*ln2 + r,  |r| <= 0.5*ln2.
+//
+//      Here r will be represented as r = hi-lo for better
+//      accuracy.
+//
+//   2. Approximation of exp(r) by a special rational function on
+//      the interval [0,0.34658]:
+//      Write
+//          R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+//      We use a special Remes algorithm on [0,0.34658] to generate
+//      a polynomial of degree 5 to approximate R. The maximum error
+//      of this polynomial approximation is bounded by 2**-59. In
+//      other words,
+//          R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+//      (where z=r*r, and the values of P1 to P5 are listed below)
+//      and
+//          |                  5          |     -59
+//          | 2.0+P1*z+...+P5*z   -  R(z) | <= 2
+//          |                             |
+//      The computation of exp(r) thus becomes
+//                             2*r
+//              exp(r) = 1 + -------
+//                            R - r
+//                                 r*R1(r)
+//                     = 1 + r + ----------- (for better accuracy)
+//                                2 - R1(r)
+//      where
+//                               2       4             10
+//              R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
+//
+//   3. Scale back to obtain exp(x):
+//      From step 1, we have
+//         exp(x) = 2**k * exp(r)
+//
+// Special cases:
+//      exp(INF) is INF, exp(NaN) is NaN;
+//      exp(-INF) is 0, and
+//      for finite argument, only exp(0)=1 is exact.
+//
+// Accuracy:
+//      according to an error analysis, the error is always less than
+//      1 ulp (unit in the last place).
+//
+// Misc. info.
+//      For IEEE double
+//          if x >  7.09782712893383973096e+02 then exp(x) overflow
+//          if x < -7.45133219101941108420e+02 then exp(x) underflow
+//
+// Constants:
+// The hexadecimal values are the intended ones for the following
+// constants. The decimal values may be used, provided that the
+// compiler will convert from decimal to binary accurately enough
+// to produce the hexadecimal values shown.
+
+func exp(x float64) float64 {
+	const (
+		Ln2Hi = 6.93147180369123816490e-01
+		Ln2Lo = 1.90821492927058770002e-10
+		Log2e = 1.44269504088896338700e+00
+
+		Overflow  = 7.09782712893383973096e+02
+		Underflow = -7.45133219101941108420e+02
+		NearZero  = 1.0 / (1 << 28) // 2**-28
+	)
+
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us
+	// special cases
+	switch {
+	case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
+		return x
+	case x < -MaxFloat64: // IsInf(x, -1):
+		return 0
+	case x > Overflow:
+		return Inf(1)
+	case x < Underflow:
+		return 0
+	case -NearZero < x && x < NearZero:
+		return 1 + x
+	}
+
+	// reduce; computed as r = hi - lo for extra precision.
+	var k int
+	switch {
+	case x < 0:
+		k = int(Log2e*x - 0.5)
+	case x > 0:
+		k = int(Log2e*x + 0.5)
+	}
+	hi := x - float64(k)*Ln2Hi
+	lo := float64(k) * Ln2Lo
+
+	// compute
+	return expmulti(hi, lo, k)
+}
+
+// Exp2 returns 2**x, the base-2 exponential of x.
+//
+// Special cases are the same as Exp.
+func Exp2(x float64) float64
+
+func exp2(x float64) float64 {
+	const (
+		Ln2Hi = 6.93147180369123816490e-01
+		Ln2Lo = 1.90821492927058770002e-10
+
+		Overflow  = 1.0239999999999999e+03
+		Underflow = -1.0740e+03
+	)
+
+	// TODO: remove manual inlining of IsNaN and IsInf
+	// when compiler does it for us
+	// special cases
+	switch {
+	case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
+		return x
+	case x < -MaxFloat64: // IsInf(x, -1):
+		return 0
+	case x > Overflow:
+		return Inf(1)
+	case x < Underflow:
+		return 0
+	}
+
+	// argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2.
+	// computed as r = hi - lo for extra precision.
+	var k int
+	switch {
+	case x > 0:
+		k = int(x + 0.5)
+	case x < 0:
+		k = int(x - 0.5)
+	}
+	t := x - float64(k)
+	hi := t * Ln2Hi
+	lo := -t * Ln2Lo
+
+	// compute
+	return expmulti(hi, lo, k)
+}
+
+// exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
+func expmulti(hi, lo float64, k int) float64 {
+	const (
+		P1 = 1.66666666666666019037e-01  /* 0x3FC55555; 0x5555553E */
+		P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */
+		P3 = 6.61375632143793436117e-05  /* 0x3F11566A; 0xAF25DE2C */
+		P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */
+		P5 = 4.13813679705723846039e-08  /* 0x3E663769; 0x72BEA4D0 */
+	)
+
+	r := hi - lo
+	t := r * r
+	c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
+	y := 1 - ((lo - (r*c)/(2-c)) - hi)
+	// TODO(rsc): make sure Ldexp can handle boundary k
+	return Ldexp(y, k)
+}
diff --git a/src/pkg/math/exp2.go b/src/pkg/math/exp2.go
deleted file mode 100644
index 1cface9..0000000
--- a/src/pkg/math/exp2.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2010 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 math
-
-// Exp2 returns 2**x, the base-2 exponential of x.
-//
-// Special cases are the same as Exp.
-func Exp2(x float64) float64 { return exp2Go(x) }
diff --git a/src/pkg/math/exp2_amd64.s b/src/pkg/math/exp2_amd64.s
new file mode 100644
index 0000000..7bb44f7
--- /dev/null
+++ b/src/pkg/math/exp2_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Exp2(SB),7,$0
+	JMP ·exp2(SB)
diff --git a/src/pkg/math/exp2_arm.s b/src/pkg/math/exp2_arm.s
new file mode 100644
index 0000000..41b63bf
--- /dev/null
+++ b/src/pkg/math/exp2_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Exp2(SB),7,$0
+	B ·exp2(SB)
diff --git a/src/pkg/math/exp2_decl.go b/src/pkg/math/exp2_decl.go
deleted file mode 100644
index cff7411..0000000
--- a/src/pkg/math/exp2_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Exp2(x float64) float64
diff --git a/src/pkg/math/exp_arm.s b/src/pkg/math/exp_arm.s
new file mode 100644
index 0000000..a95fa93
--- /dev/null
+++ b/src/pkg/math/exp_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Exp(SB),7,$0
+	B ·exp(SB)
diff --git a/src/pkg/math/exp_decl.go b/src/pkg/math/exp_decl.go
deleted file mode 100644
index dc8404c..0000000
--- a/src/pkg/math/exp_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Exp(x float64) float64
diff --git a/src/pkg/math/exp_port.go b/src/pkg/math/exp_port.go
deleted file mode 100644
index 618c31a..0000000
--- a/src/pkg/math/exp_port.go
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-// The original C code, the long comment, and the constants
-// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c
-// and came with this notice.  The go code is a simplified
-// version of the original C.
-//
-// ====================================================
-// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
-//
-// Permission to use, copy, modify, and distribute this
-// software is freely granted, provided that this notice
-// is preserved.
-// ====================================================
-//
-//
-// exp(x)
-// Returns the exponential of x.
-//
-// Method
-//   1. Argument reduction:
-//      Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
-//      Given x, find r and integer k such that
-//
-//               x = k*ln2 + r,  |r| <= 0.5*ln2.
-//
-//      Here r will be represented as r = hi-lo for better
-//      accuracy.
-//
-//   2. Approximation of exp(r) by a special rational function on
-//      the interval [0,0.34658]:
-//      Write
-//          R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
-//      We use a special Remes algorithm on [0,0.34658] to generate
-//      a polynomial of degree 5 to approximate R. The maximum error
-//      of this polynomial approximation is bounded by 2**-59. In
-//      other words,
-//          R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
-//      (where z=r*r, and the values of P1 to P5 are listed below)
-//      and
-//          |                  5          |     -59
-//          | 2.0+P1*z+...+P5*z   -  R(z) | <= 2
-//          |                             |
-//      The computation of exp(r) thus becomes
-//                             2*r
-//              exp(r) = 1 + -------
-//                            R - r
-//                                 r*R1(r)
-//                     = 1 + r + ----------- (for better accuracy)
-//                                2 - R1(r)
-//      where
-//                               2       4             10
-//              R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
-//
-//   3. Scale back to obtain exp(x):
-//      From step 1, we have
-//         exp(x) = 2**k * exp(r)
-//
-// Special cases:
-//      exp(INF) is INF, exp(NaN) is NaN;
-//      exp(-INF) is 0, and
-//      for finite argument, only exp(0)=1 is exact.
-//
-// Accuracy:
-//      according to an error analysis, the error is always less than
-//      1 ulp (unit in the last place).
-//
-// Misc. info.
-//      For IEEE double
-//          if x >  7.09782712893383973096e+02 then exp(x) overflow
-//          if x < -7.45133219101941108420e+02 then exp(x) underflow
-//
-// Constants:
-// The hexadecimal values are the intended ones for the following
-// constants. The decimal values may be used, provided that the
-// compiler will convert from decimal to binary accurately enough
-// to produce the hexadecimal values shown.
-
-// Exp returns e**x, the base-e exponential of x.
-//
-// Special cases are:
-//	Exp(+Inf) = +Inf
-//	Exp(NaN) = NaN
-// Very large values overflow to 0 or +Inf.
-// Very small values underflow to 1.
-func expGo(x float64) float64 {
-	const (
-		Ln2Hi = 6.93147180369123816490e-01
-		Ln2Lo = 1.90821492927058770002e-10
-		Log2e = 1.44269504088896338700e+00
-
-		Overflow  = 7.09782712893383973096e+02
-		Underflow = -7.45133219101941108420e+02
-		NearZero  = 1.0 / (1 << 28) // 2**-28
-	)
-
-	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
-	// when compiler does it for us
-	// special cases
-	switch {
-	case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
-		return x
-	case x < -MaxFloat64: // IsInf(x, -1):
-		return 0
-	case x > Overflow:
-		return Inf(1)
-	case x < Underflow:
-		return 0
-	case -NearZero < x && x < NearZero:
-		return 1 + x
-	}
-
-	// reduce; computed as r = hi - lo for extra precision.
-	var k int
-	switch {
-	case x < 0:
-		k = int(Log2e*x - 0.5)
-	case x > 0:
-		k = int(Log2e*x + 0.5)
-	}
-	hi := x - float64(k)*Ln2Hi
-	lo := float64(k) * Ln2Lo
-
-	// compute
-	return exp(hi, lo, k)
-}
-
-// Exp2 returns 2**x, the base-2 exponential of x.
-//
-// Special cases are the same as Exp.
-func exp2Go(x float64) float64 {
-	const (
-		Ln2Hi = 6.93147180369123816490e-01
-		Ln2Lo = 1.90821492927058770002e-10
-
-		Overflow  = 1.0239999999999999e+03
-		Underflow = -1.0740e+03
-	)
-
-	// TODO: remove manual inlining of IsNaN and IsInf
-	// when compiler does it for us
-	// special cases
-	switch {
-	case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1):
-		return x
-	case x < -MaxFloat64: // IsInf(x, -1):
-		return 0
-	case x > Overflow:
-		return Inf(1)
-	case x < Underflow:
-		return 0
-	}
-
-	// argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2.
-	// computed as r = hi - lo for extra precision.
-	var k int
-	switch {
-	case x > 0:
-		k = int(x + 0.5)
-	case x < 0:
-		k = int(x - 0.5)
-	}
-	t := x - float64(k)
-	hi := t * Ln2Hi
-	lo := -t * Ln2Lo
-
-	// compute
-	return exp(hi, lo, k)
-}
-
-// exp returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
-func exp(hi, lo float64, k int) float64 {
-	const (
-		P1 = 1.66666666666666019037e-01  /* 0x3FC55555; 0x5555553E */
-		P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */
-		P3 = 6.61375632143793436117e-05  /* 0x3F11566A; 0xAF25DE2C */
-		P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */
-		P5 = 4.13813679705723846039e-08  /* 0x3E663769; 0x72BEA4D0 */
-	)
-
-	r := hi - lo
-	t := r * r
-	c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))))
-	y := 1 - ((lo - (r*c)/(2-c)) - hi)
-	// TODO(rsc): make sure Ldexp can handle boundary k
-	return Ldexp(y, k)
-}
diff --git a/src/pkg/math/exp_test.go b/src/pkg/math/exp_test.go
deleted file mode 100644
index 7381fd5..0000000
--- a/src/pkg/math/exp_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2010 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 math
-
-// Make expGo and exp2Go available for testing.
-
-func ExpGo(x float64) float64  { return expGo(x) }
-func Exp2Go(x float64) float64 { return exp2Go(x) }
diff --git a/src/pkg/math/expm1.go b/src/pkg/math/expm1.go
index e9f8331..15fc25f 100644
--- a/src/pkg/math/expm1.go
+++ b/src/pkg/math/expm1.go
@@ -121,7 +121,9 @@ package math
 //	Expm1(-Inf) = -1
 //	Expm1(NaN) = NaN
 // Very large values overflow to -1 or +Inf.
-func Expm1(x float64) float64 {
+func Expm1(x float64) float64
+
+func expm1(x float64) float64 {
 	const (
 		Othreshold = 7.09782712893383973096e+02 // 0x40862E42FEFA39EF
 		Ln2X56     = 3.88162421113569373274e+01 // 0x4043687a9f1af2b1
diff --git a/src/pkg/math/expm1_amd64.s b/src/pkg/math/expm1_amd64.s
new file mode 100644
index 0000000..a3b09e2
--- /dev/null
+++ b/src/pkg/math/expm1_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Expm1(SB),7,$0
+	JMP ·expm1(SB)
diff --git a/src/pkg/math/expm1_arm.s b/src/pkg/math/expm1_arm.s
new file mode 100644
index 0000000..e4e4044
--- /dev/null
+++ b/src/pkg/math/expm1_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Expm1(SB),7,$0
+	B ·expm1(SB)
diff --git a/src/pkg/math/expm1_decl.go b/src/pkg/math/expm1_decl.go
deleted file mode 100644
index 4dab70b..0000000
--- a/src/pkg/math/expm1_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Expm1(x float64) float64
diff --git a/src/pkg/math/export_test.go b/src/pkg/math/export_test.go
new file mode 100644
index 0000000..02992d7
--- /dev/null
+++ b/src/pkg/math/export_test.go
@@ -0,0 +1,11 @@
+// Copyright 2011 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 math
+
+// Export internal functions for testing.
+var ExpGo = exp
+var Exp2Go = exp2
+var HypotGo = hypot
+var SqrtGo = sqrt
diff --git a/src/pkg/math/fabs.go b/src/pkg/math/fabs.go
deleted file mode 100644
index 3431231..0000000
--- a/src/pkg/math/fabs.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-// Fabs returns the absolute value of x.
-//
-// Special cases are:
-//	Fabs(+Inf) = +Inf
-//	Fabs(-Inf) = +Inf
-//	Fabs(NaN) = NaN
-func Fabs(x float64) float64 {
-	switch {
-	case x < 0:
-		return -x
-	case x == 0:
-		return 0 // return correctly fabs(-0)
-	}
-	return x
-}
diff --git a/src/pkg/math/fabs_386.s b/src/pkg/math/fabs_386.s
deleted file mode 100644
index 55de4e6..0000000
--- a/src/pkg/math/fabs_386.s
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2010 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.
-
-// func Fabs(x float64) float64
-TEXT ·Fabs(SB),7,$0
-	FMOVD   x+0(FP), F0  // F0=x
-	FABS                 // F0=|x|
-	FMOVDP  F0, r+8(FP)
-	RET
diff --git a/src/pkg/math/fabs_amd64.s b/src/pkg/math/fabs_amd64.s
deleted file mode 100644
index 8a9aedb..0000000
--- a/src/pkg/math/fabs_amd64.s
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2010 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.
-
-// func Fabs(x float64) float64
-TEXT ·Fabs(SB),7,$0
-	MOVQ   $(1<<63), BX
-	MOVQ   BX, X0 // movsd $(-0.0), x0
-	MOVSD  x+0(FP), X1
-	ANDNPD X1, X0
-	MOVSD  X0, r+8(FP)
-	RET
diff --git a/src/pkg/math/fabs_decl.go b/src/pkg/math/fabs_decl.go
deleted file mode 100644
index 9071f49..0000000
--- a/src/pkg/math/fabs_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Fabs(x float64) float64
diff --git a/src/pkg/math/fdim.go b/src/pkg/math/fdim.go
deleted file mode 100644
index 1899313..0000000
--- a/src/pkg/math/fdim.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2010 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 math
-
-// Fdim returns the maximum of x-y or 0.
-func Fdim(x, y float64) float64 {
-	if x > y {
-		return x - y
-	}
-	return 0
-}
-
-// Fmax returns the larger of x or y.
-func Fmax(x, y float64) float64 {
-	if x > y {
-		return x
-	}
-	return y
-}
-
-// Fmin returns the smaller of x or y.
-func Fmin(x, y float64) float64 {
-	if x < y {
-		return x
-	}
-	return y
-}
diff --git a/src/pkg/math/fdim_amd64.s b/src/pkg/math/fdim_amd64.s
deleted file mode 100644
index 1f45ef8..0000000
--- a/src/pkg/math/fdim_amd64.s
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2010 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.
-
-// func Fdim(x, y float64) float64
-TEXT ·Fdim(SB),7,$0
-	MOVSD x+0(FP), X0
-	SUBSD y+8(FP), X0
-	MOVSD $(0.0), X1
-	MAXSD X1, X0
-	MOVSD X0, r+16(FP)
-	RET
-
-// func Fmax(x, y float64) float64
-TEXT ·Fmax(SB),7,$0
-	MOVSD x+0(FP), X0
-	MAXSD y+8(FP), X0
-	MOVSD X0, r+16(FP)
-	RET
-
-// func Fmin(x, y float64) float64
-TEXT ·Fmin(SB),7,$0
-	MOVSD x+0(FP), X0
-	MINSD y+8(FP), X0
-	MOVSD X0, r+16(FP)
-	RET
diff --git a/src/pkg/math/fdim_decl.go b/src/pkg/math/fdim_decl.go
deleted file mode 100644
index 88dea3d..0000000
--- a/src/pkg/math/fdim_decl.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2010 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 math
-
-func Fdim(x, y float64) float64
-func Fmax(x, y float64) float64
-func Fmin(x, y float64) float64
diff --git a/src/pkg/math/floor.go b/src/pkg/math/floor.go
index babbf64..a7090f5 100644
--- a/src/pkg/math/floor.go
+++ b/src/pkg/math/floor.go
@@ -7,10 +7,12 @@ package math
 // Floor returns the greatest integer value less than or equal to x.
 //
 // Special cases are:
-//	Floor(+Inf) = +Inf
-//	Floor(-Inf) = -Inf
+//	Floor(±0) = ±0
+//	Floor(±Inf) = ±Inf
 //	Floor(NaN) = NaN
-func Floor(x float64) float64 {
+func Floor(x float64) float64
+
+func floor(x float64) float64 {
 	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
 	// when compiler does it for us
 	if x == 0 || x != x || x > MaxFloat64 || x < -MaxFloat64 { // x == 0 || IsNaN(x) || IsInf(x, 0)
@@ -30,18 +32,24 @@ func Floor(x float64) float64 {
 // Ceil returns the least integer value greater than or equal to x.
 //
 // Special cases are:
-//	Ceil(+Inf) = +Inf
-//	Ceil(-Inf) = -Inf
+//	Ceil(±0) = ±0
+//	Ceil(±Inf) = ±Inf
 //	Ceil(NaN) = NaN
-func Ceil(x float64) float64 { return -Floor(-x) }
+func Ceil(x float64) float64
+
+func ceil(x float64) float64 {
+	return -Floor(-x)
+}
 
 // Trunc returns the integer value of x.
 //
 // Special cases are:
-//	Trunc(+Inf) = +Inf
-//	Trunc(-Inf) = -Inf
+//	Trunc(±0) = ±0
+//	Trunc(±Inf) = ±Inf
 //	Trunc(NaN) = NaN
-func Trunc(x float64) float64 {
+func Trunc(x float64) float64
+
+func trunc(x float64) float64 {
 	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
 	// when compiler does it for us
 	if x == 0 || x != x || x > MaxFloat64 || x < -MaxFloat64 { // x == 0 || IsNaN(x) || IsInf(x, 0)
diff --git a/src/pkg/math/floor_amd64.s b/src/pkg/math/floor_amd64.s
new file mode 100644
index 0000000..9fc49a5
--- /dev/null
+++ b/src/pkg/math/floor_amd64.s
@@ -0,0 +1,12 @@
+// Copyright 2011 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.
+
+TEXT ·Floor(SB),7,$0
+	JMP	·floor(SB)
+
+TEXT ·Ceil(SB),7,$0
+	JMP	·ceil(SB)
+
+TEXT ·Trunc(SB),7,$0
+	JMP	·trunc(SB)
diff --git a/src/pkg/math/floor_arm.s b/src/pkg/math/floor_arm.s
new file mode 100644
index 0000000..e3ae53f
--- /dev/null
+++ b/src/pkg/math/floor_arm.s
@@ -0,0 +1,12 @@
+// Copyright 2011 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.
+
+TEXT ·Floor(SB),7,$0
+	B	·floor(SB)
+
+TEXT ·Ceil(SB),7,$0
+	B	·ceil(SB)
+
+TEXT ·Trunc(SB),7,$0
+	B	·trunc(SB)
diff --git a/src/pkg/math/floor_decl.go b/src/pkg/math/floor_decl.go
deleted file mode 100644
index 7da4201..0000000
--- a/src/pkg/math/floor_decl.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2010 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 math
-
-func Ceil(x float64) float64
-func Floor(x float64) float64
-func Trunc(x float64) float64
diff --git a/src/pkg/math/fmod.go b/src/pkg/math/fmod.go
deleted file mode 100644
index 75c6146..0000000
--- a/src/pkg/math/fmod.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2009-2010 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 math
-
-/*
-	Floating-point mod function.
-*/
-
-// Fmod returns the floating-point remainder of x/y.
-// The magnitude of the result is less than y and its
-// sign agrees with that of x.
-//
-// Special cases are:
-//	if x is not finite, Fmod returns NaN
-//	if y is 0 or NaN, Fmod returns NaN
-func Fmod(x, y float64) float64 {
-	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
-	// when compiler does it for us.
-	if y == 0 || x > MaxFloat64 || x < -MaxFloat64 || x != x || y != y { // y == 0 || IsInf(x, 0) || IsNaN(x) || IsNan(y)
-		return NaN()
-	}
-	if y < 0 {
-		y = -y
-	}
-
-	yfr, yexp := Frexp(y)
-	sign := false
-	r := x
-	if x < 0 {
-		r = -x
-		sign = true
-	}
-
-	for r >= y {
-		rfr, rexp := Frexp(r)
-		if rfr < yfr {
-			rexp = rexp - 1
-		}
-		r = r - Ldexp(y, rexp-yexp)
-	}
-	if sign {
-		r = -r
-	}
-	return r
-}
diff --git a/src/pkg/math/fmod_386.s b/src/pkg/math/fmod_386.s
deleted file mode 100644
index eb37bef..0000000
--- a/src/pkg/math/fmod_386.s
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2010 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.
-
-// func Fmod(x, y float64) float64
-TEXT ·Fmod(SB),7,$0
-	FMOVD   y+8(FP), F0  // F0=y
-	FMOVD   x+0(FP), F0  // F0=x, F1=y
-	FPREM                // F0=reduced_x, F1=y
-	FSTSW   AX           // AX=status word
-	ANDW    $0x0400, AX
-	JNE     -3(PC)       // jump if reduction incomplete
-	FMOVDP  F0, F1       // F0=x-q*y
-	FMOVDP  F0, r+16(FP)
-	RET
diff --git a/src/pkg/math/fmod_decl.go b/src/pkg/math/fmod_decl.go
deleted file mode 100644
index 8d97cdf..0000000
--- a/src/pkg/math/fmod_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Fmod(x, y float64) float64
diff --git a/src/pkg/math/frexp.go b/src/pkg/math/frexp.go
index 867b78f..b5458d7 100644
--- a/src/pkg/math/frexp.go
+++ b/src/pkg/math/frexp.go
@@ -13,7 +13,9 @@ package math
 //	Frexp(±0) = ±0, 0
 //	Frexp(±Inf) = ±Inf, 0
 //	Frexp(NaN) = NaN, 0
-func Frexp(f float64) (frac float64, exp int) {
+func Frexp(f float64) (frac float64, exp int)
+
+func frexp(f float64) (frac float64, exp int) {
 	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
 	// when compiler does it for us
 	// special cases
diff --git a/src/pkg/math/frexp_amd64.s b/src/pkg/math/frexp_amd64.s
new file mode 100644
index 0000000..bc52b79
--- /dev/null
+++ b/src/pkg/math/frexp_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Frexp(SB),7,$0
+	JMP ·frexp(SB)
diff --git a/src/pkg/math/frexp_arm.s b/src/pkg/math/frexp_arm.s
new file mode 100644
index 0000000..cfd5d0b
--- /dev/null
+++ b/src/pkg/math/frexp_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Frexp(SB),7,$0
+	B ·frexp(SB)
diff --git a/src/pkg/math/frexp_decl.go b/src/pkg/math/frexp_decl.go
deleted file mode 100644
index b36bf2e..0000000
--- a/src/pkg/math/frexp_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Frexp(x float64) (f float64, e int)
diff --git a/src/pkg/math/gamma.go b/src/pkg/math/gamma.go
index 73ca0e5..7365d8e 100644
--- a/src/pkg/math/gamma.go
+++ b/src/pkg/math/gamma.go
@@ -63,7 +63,7 @@ package math
 //   Stephen L. Moshier
 //   moshier at na-net.ornl.gov
 
-var _P = []float64{
+var _gamP = [...]float64{
 	1.60119522476751861407e-04,
 	1.19135147006586384913e-03,
 	1.04213797561761569935e-02,
@@ -72,7 +72,7 @@ var _P = []float64{
 	4.94214826801497100753e-01,
 	9.99999999999999996796e-01,
 }
-var _Q = []float64{
+var _gamQ = [...]float64{
 	-2.31581873324120129819e-05,
 	5.39605580493303397842e-04,
 	-4.45641913851797240494e-03,
@@ -82,7 +82,7 @@ var _Q = []float64{
 	7.14304917030273074085e-02,
 	1.00000000000000000320e+00,
 }
-var _S = []float64{
+var _gamS = [...]float64{
 	7.87311395793093628397e-04,
 	-2.29549961613378126380e-04,
 	-2.68132617805781232825e-03,
@@ -98,7 +98,7 @@ func stirling(x float64) float64 {
 		MaxStirling = 143.01608
 	)
 	w := 1 / x
-	w = 1 + w*((((_S[0]*w+_S[1])*w+_S[2])*w+_S[3])*w+_S[4])
+	w = 1 + w*((((_gamS[0]*w+_gamS[1])*w+_gamS[2])*w+_gamS[3])*w+_gamS[4])
 	y := Exp(x)
 	if x > MaxStirling { // avoid Pow() overflow
 		v := Pow(x, 0.5*x-0.25)
@@ -113,8 +113,7 @@ func stirling(x float64) float64 {
 // Gamma(x) returns the Gamma function of x.
 //
 // Special cases are:
-//	Gamma(Inf) = Inf
-//	Gamma(-Inf) = -Inf
+//	Gamma(±Inf) = ±Inf
 //	Gamma(NaN) = NaN
 // Large values overflow to +Inf.
 // Negative integer values equal ±Inf.
@@ -127,7 +126,7 @@ func Gamma(x float64) float64 {
 	case x < -170.5674972726612 || x > 171.61447887182298:
 		return Inf(1)
 	}
-	q := Fabs(x)
+	q := Abs(x)
 	p := Floor(q)
 	if q > 33 {
 		if x >= 0 {
@@ -146,7 +145,7 @@ func Gamma(x float64) float64 {
 		if z == 0 {
 			return Inf(signgam)
 		}
-		z = Pi / (Fabs(z) * stirling(q))
+		z = Pi / (Abs(z) * stirling(q))
 		return float64(signgam) * z
 	}
 
@@ -176,8 +175,8 @@ func Gamma(x float64) float64 {
 	}
 
 	x = x - 2
-	p = (((((x*_P[0]+_P[1])*x+_P[2])*x+_P[3])*x+_P[4])*x+_P[5])*x + _P[6]
-	q = ((((((x*_Q[0]+_Q[1])*x+_Q[2])*x+_Q[3])*x+_Q[4])*x+_Q[5])*x+_Q[6])*x + _Q[7]
+	p = (((((x*_gamP[0]+_gamP[1])*x+_gamP[2])*x+_gamP[3])*x+_gamP[4])*x+_gamP[5])*x + _gamP[6]
+	q = ((((((x*_gamQ[0]+_gamQ[1])*x+_gamQ[2])*x+_gamQ[3])*x+_gamQ[4])*x+_gamQ[5])*x+_gamQ[6])*x + _gamQ[7]
 	return z * p / q
 
 small:
diff --git a/src/pkg/math/hypot.go b/src/pkg/math/hypot.go
index ecd115d..233257b 100644
--- a/src/pkg/math/hypot.go
+++ b/src/pkg/math/hypot.go
@@ -14,7 +14,9 @@ package math
 // Special cases are:
 //	Hypot(p, q) = +Inf if p or q is infinite
 //	Hypot(p, q) = NaN if p or q is NaN
-func Hypot(p, q float64) float64 {
+func Hypot(p, q float64) float64
+
+func hypot(p, q float64) float64 {
 	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
 	// when compiler does it for us
 	// special cases
diff --git a/src/pkg/math/hypot_arm.s b/src/pkg/math/hypot_arm.s
new file mode 100644
index 0000000..2c599fd
--- /dev/null
+++ b/src/pkg/math/hypot_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Hypot(SB),7,$0
+	B ·hypot(SB)
diff --git a/src/pkg/math/hypot_decl.go b/src/pkg/math/hypot_decl.go
deleted file mode 100644
index 72603c5..0000000
--- a/src/pkg/math/hypot_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Hypot(x, y float64) float64
diff --git a/src/pkg/math/hypot_port.go b/src/pkg/math/hypot_port.go
deleted file mode 100644
index 27f335b..0000000
--- a/src/pkg/math/hypot_port.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2009-2010 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 math
-
-/*
-	Hypot -- sqrt(p*p + q*q), but overflows only if the result does.
-	See:
-		Cleve Moler and Donald Morrison,
-		Replacing Square Roots by Pythagorean Sums
-		IBM Journal of Research and Development,
-		Vol. 27, Number 6, pp. 577-581, Nov. 1983
-*/
-
-// Hypot computes Sqrt(p*p + q*q), taking care to avoid
-// unnecessary overflow and underflow.
-//
-// Special cases are:
-//	Hypot(p, q) = +Inf if p or q is infinite
-//	Hypot(p, q) = NaN if p or q is NaN
-func hypotGo(p, q float64) float64 {
-	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
-	// when compiler does it for us
-	// special cases
-	switch {
-	case p < -MaxFloat64 || p > MaxFloat64 || q < -MaxFloat64 || q > MaxFloat64: // IsInf(p, 0) || IsInf(q, 0):
-		return Inf(1)
-	case p != p || q != q: // IsNaN(p) || IsNaN(q):
-		return NaN()
-	}
-	if p < 0 {
-		p = -p
-	}
-	if q < 0 {
-		q = -q
-	}
-
-	if p < q {
-		p, q = q, p
-	}
-
-	if p == 0 {
-		return 0
-	}
-
-	pfac := p
-	q = q / p
-	r := q
-	p = 1
-	for {
-		r = r * r
-		s := r + 4
-		if s == 4 {
-			return p * pfac
-		}
-		r = r / s
-		p = p + 2*r*p
-		q = q * r
-		r = q / p
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/math/hypot_test.go b/src/pkg/math/hypot_test.go
deleted file mode 100644
index 85ce1d4..0000000
--- a/src/pkg/math/hypot_test.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2010 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 math
-
-// Make hypotGo available for testing.
-
-func HypotGo(x, y float64) float64 { return hypotGo(x, y) }
diff --git a/src/pkg/math/jn.go b/src/pkg/math/jn.go
index 9024af3..1878df5 100644
--- a/src/pkg/math/jn.go
+++ b/src/pkg/math/jn.go
@@ -197,7 +197,7 @@ func Jn(n int, x float64) float64 {
 
 			tmp := float64(n)
 			v := 2 / x
-			tmp = tmp * Log(Fabs(v*tmp))
+			tmp = tmp * Log(Abs(v*tmp))
 			if tmp < 7.09782712893383973096e+02 {
 				for i := n - 1; i > 0; i-- {
 					di := float64(i + i)
diff --git a/src/pkg/math/ldexp.go b/src/pkg/math/ldexp.go
index 96c95ca..9534230 100644
--- a/src/pkg/math/ldexp.go
+++ b/src/pkg/math/ldexp.go
@@ -11,7 +11,9 @@ package math
 //	Ldexp(±0, exp) = ±0
 //	Ldexp(±Inf, exp) = ±Inf
 //	Ldexp(NaN, exp) = NaN
-func Ldexp(frac float64, exp int) float64 {
+func Ldexp(frac float64, exp int) float64
+
+func ldexp(frac float64, exp int) float64 {
 	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
 	// when compiler does it for us
 	// special cases
diff --git a/src/pkg/math/ldexp_amd64.s b/src/pkg/math/ldexp_amd64.s
new file mode 100644
index 0000000..a8d4583
--- /dev/null
+++ b/src/pkg/math/ldexp_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Ldexp(SB),7,$0
+	JMP ·ldexp(SB)
diff --git a/src/pkg/math/ldexp_arm.s b/src/pkg/math/ldexp_arm.s
new file mode 100644
index 0000000..3c42f51
--- /dev/null
+++ b/src/pkg/math/ldexp_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Ldexp(SB),7,$0
+	B ·ldexp(SB)
diff --git a/src/pkg/math/ldexp_decl.go b/src/pkg/math/ldexp_decl.go
deleted file mode 100644
index 40e11e7..0000000
--- a/src/pkg/math/ldexp_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Ldexp(f float64, e int) float64
diff --git a/src/pkg/math/lgamma.go b/src/pkg/math/lgamma.go
index dc30f46..e2bad69 100644
--- a/src/pkg/math/lgamma.go
+++ b/src/pkg/math/lgamma.go
@@ -88,6 +88,81 @@ package math
 //
 //
 
+var _lgamA = [...]float64{
+	7.72156649015328655494e-02, // 0x3FB3C467E37DB0C8
+	3.22467033424113591611e-01, // 0x3FD4A34CC4A60FAD
+	6.73523010531292681824e-02, // 0x3FB13E001A5562A7
+	2.05808084325167332806e-02, // 0x3F951322AC92547B
+	7.38555086081402883957e-03, // 0x3F7E404FB68FEFE8
+	2.89051383673415629091e-03, // 0x3F67ADD8CCB7926B
+	1.19270763183362067845e-03, // 0x3F538A94116F3F5D
+	5.10069792153511336608e-04, // 0x3F40B6C689B99C00
+	2.20862790713908385557e-04, // 0x3F2CF2ECED10E54D
+	1.08011567247583939954e-04, // 0x3F1C5088987DFB07
+	2.52144565451257326939e-05, // 0x3EFA7074428CFA52
+	4.48640949618915160150e-05, // 0x3F07858E90A45837
+}
+var _lgamR = [...]float64{
+	1.0, // placeholder
+	1.39200533467621045958e+00, // 0x3FF645A762C4AB74
+	7.21935547567138069525e-01, // 0x3FE71A1893D3DCDC
+	1.71933865632803078993e-01, // 0x3FC601EDCCFBDF27
+	1.86459191715652901344e-02, // 0x3F9317EA742ED475
+	7.77942496381893596434e-04, // 0x3F497DDACA41A95B
+	7.32668430744625636189e-06, // 0x3EDEBAF7A5B38140
+}
+var _lgamS = [...]float64{
+	-7.72156649015328655494e-02, // 0xBFB3C467E37DB0C8
+	2.14982415960608852501e-01,  // 0x3FCB848B36E20878
+	3.25778796408930981787e-01,  // 0x3FD4D98F4F139F59
+	1.46350472652464452805e-01,  // 0x3FC2BB9CBEE5F2F7
+	2.66422703033638609560e-02,  // 0x3F9B481C7E939961
+	1.84028451407337715652e-03,  // 0x3F5E26B67368F239
+	3.19475326584100867617e-05,  // 0x3F00BFECDD17E945
+}
+var _lgamT = [...]float64{
+	4.83836122723810047042e-01,  // 0x3FDEF72BC8EE38A2
+	-1.47587722994593911752e-01, // 0xBFC2E4278DC6C509
+	6.46249402391333854778e-02,  // 0x3FB08B4294D5419B
+	-3.27885410759859649565e-02, // 0xBFA0C9A8DF35B713
+	1.79706750811820387126e-02,  // 0x3F9266E7970AF9EC
+	-1.03142241298341437450e-02, // 0xBF851F9FBA91EC6A
+	6.10053870246291332635e-03,  // 0x3F78FCE0E370E344
+	-3.68452016781138256760e-03, // 0xBF6E2EFFB3E914D7
+	2.25964780900612472250e-03,  // 0x3F6282D32E15C915
+	-1.40346469989232843813e-03, // 0xBF56FE8EBF2D1AF1
+	8.81081882437654011382e-04,  // 0x3F4CDF0CEF61A8E9
+	-5.38595305356740546715e-04, // 0xBF41A6109C73E0EC
+	3.15632070903625950361e-04,  // 0x3F34AF6D6C0EBBF7
+	-3.12754168375120860518e-04, // 0xBF347F24ECC38C38
+	3.35529192635519073543e-04,  // 0x3F35FD3EE8C2D3F4
+}
+var _lgamU = [...]float64{
+	-7.72156649015328655494e-02, // 0xBFB3C467E37DB0C8
+	6.32827064025093366517e-01,  // 0x3FE4401E8B005DFF
+	1.45492250137234768737e+00,  // 0x3FF7475CD119BD6F
+	9.77717527963372745603e-01,  // 0x3FEF497644EA8450
+	2.28963728064692451092e-01,  // 0x3FCD4EAEF6010924
+	1.33810918536787660377e-02,  // 0x3F8B678BBF2BAB09
+}
+var _lgamV = [...]float64{
+	1.0,
+	2.45597793713041134822e+00, // 0x4003A5D7C2BD619C
+	2.12848976379893395361e+00, // 0x40010725A42B18F5
+	7.69285150456672783825e-01, // 0x3FE89DFBE45050AF
+	1.04222645593369134254e-01, // 0x3FBAAE55D6537C88
+	3.21709242282423911810e-03, // 0x3F6A5ABB57D0CF61
+}
+var _lgamW = [...]float64{
+	4.18938533204672725052e-01,  // 0x3FDACFE390C97D69
+	8.33333333333329678849e-02,  // 0x3FB555555555553B
+	-2.77777777728775536470e-03, // 0xBF66C16C16B02E5C
+	7.93650558643019558500e-04,  // 0x3F4A019F98CF38B6
+	-5.95187557450339963135e-04, // 0xBF4380CB8C0FE741
+	8.36339918996282139126e-04,  // 0x3F4B67BA4CDAD5D1
+	-1.63092934096575273989e-03, // 0xBF5AB89D0B9E43E4
+}
+
 // Lgamma returns the natural logarithm and sign (-1 or +1) of Gamma(x).
 //
 // Special cases are:
@@ -103,68 +178,10 @@ func Lgamma(x float64) (lgamma float64, sign int) {
 		Two53 = 1 << 53                     // 0x4340000000000000 ~9.0072e+15
 		Two58 = 1 << 58                     // 0x4390000000000000 ~2.8823e+17
 		Tiny  = 1.0 / (1 << 70)             // 0x3b90000000000000 ~8.47033e-22
-		A0    = 7.72156649015328655494e-02  // 0x3FB3C467E37DB0C8
-		A1    = 3.22467033424113591611e-01  // 0x3FD4A34CC4A60FAD
-		A2    = 6.73523010531292681824e-02  // 0x3FB13E001A5562A7
-		A3    = 2.05808084325167332806e-02  // 0x3F951322AC92547B
-		A4    = 7.38555086081402883957e-03  // 0x3F7E404FB68FEFE8
-		A5    = 2.89051383673415629091e-03  // 0x3F67ADD8CCB7926B
-		A6    = 1.19270763183362067845e-03  // 0x3F538A94116F3F5D
-		A7    = 5.10069792153511336608e-04  // 0x3F40B6C689B99C00
-		A8    = 2.20862790713908385557e-04  // 0x3F2CF2ECED10E54D
-		A9    = 1.08011567247583939954e-04  // 0x3F1C5088987DFB07
-		A10   = 2.52144565451257326939e-05  // 0x3EFA7074428CFA52
-		A11   = 4.48640949618915160150e-05  // 0x3F07858E90A45837
 		Tc    = 1.46163214496836224576e+00  // 0x3FF762D86356BE3F
 		Tf    = -1.21486290535849611461e-01 // 0xBFBF19B9BCC38A42
 		// Tt = -(tail of Tf)
-		Tt  = -3.63867699703950536541e-18 // 0xBC50C7CAA48A971F
-		T0  = 4.83836122723810047042e-01  // 0x3FDEF72BC8EE38A2
-		T1  = -1.47587722994593911752e-01 // 0xBFC2E4278DC6C509
-		T2  = 6.46249402391333854778e-02  // 0x3FB08B4294D5419B
-		T3  = -3.27885410759859649565e-02 // 0xBFA0C9A8DF35B713
-		T4  = 1.79706750811820387126e-02  // 0x3F9266E7970AF9EC
-		T5  = -1.03142241298341437450e-02 // 0xBF851F9FBA91EC6A
-		T6  = 6.10053870246291332635e-03  // 0x3F78FCE0E370E344
-		T7  = -3.68452016781138256760e-03 // 0xBF6E2EFFB3E914D7
-		T8  = 2.25964780900612472250e-03  // 0x3F6282D32E15C915
-		T9  = -1.40346469989232843813e-03 // 0xBF56FE8EBF2D1AF1
-		T10 = 8.81081882437654011382e-04  // 0x3F4CDF0CEF61A8E9
-		T11 = -5.38595305356740546715e-04 // 0xBF41A6109C73E0EC
-		T12 = 3.15632070903625950361e-04  // 0x3F34AF6D6C0EBBF7
-		T13 = -3.12754168375120860518e-04 // 0xBF347F24ECC38C38
-		T14 = 3.35529192635519073543e-04  // 0x3F35FD3EE8C2D3F4
-		U0  = -7.72156649015328655494e-02 // 0xBFB3C467E37DB0C8
-		U1  = 6.32827064025093366517e-01  // 0x3FE4401E8B005DFF
-		U2  = 1.45492250137234768737e+00  // 0x3FF7475CD119BD6F
-		U3  = 9.77717527963372745603e-01  // 0x3FEF497644EA8450
-		U4  = 2.28963728064692451092e-01  // 0x3FCD4EAEF6010924
-		U5  = 1.33810918536787660377e-02  // 0x3F8B678BBF2BAB09
-		V1  = 2.45597793713041134822e+00  // 0x4003A5D7C2BD619C
-		V2  = 2.12848976379893395361e+00  // 0x40010725A42B18F5
-		V3  = 7.69285150456672783825e-01  // 0x3FE89DFBE45050AF
-		V4  = 1.04222645593369134254e-01  // 0x3FBAAE55D6537C88
-		V5  = 3.21709242282423911810e-03  // 0x3F6A5ABB57D0CF61
-		S0  = -7.72156649015328655494e-02 // 0xBFB3C467E37DB0C8
-		S1  = 2.14982415960608852501e-01  // 0x3FCB848B36E20878
-		S2  = 3.25778796408930981787e-01  // 0x3FD4D98F4F139F59
-		S3  = 1.46350472652464452805e-01  // 0x3FC2BB9CBEE5F2F7
-		S4  = 2.66422703033638609560e-02  // 0x3F9B481C7E939961
-		S5  = 1.84028451407337715652e-03  // 0x3F5E26B67368F239
-		S6  = 3.19475326584100867617e-05  // 0x3F00BFECDD17E945
-		R1  = 1.39200533467621045958e+00  // 0x3FF645A762C4AB74
-		R2  = 7.21935547567138069525e-01  // 0x3FE71A1893D3DCDC
-		R3  = 1.71933865632803078993e-01  // 0x3FC601EDCCFBDF27
-		R4  = 1.86459191715652901344e-02  // 0x3F9317EA742ED475
-		R5  = 7.77942496381893596434e-04  // 0x3F497DDACA41A95B
-		R6  = 7.32668430744625636189e-06  // 0x3EDEBAF7A5B38140
-		W0  = 4.18938533204672725052e-01  // 0x3FDACFE390C97D69
-		W1  = 8.33333333333329678849e-02  // 0x3FB555555555553B
-		W2  = -2.77777777728775536470e-03 // 0xBF66C16C16B02E5C
-		W3  = 7.93650558643019558500e-04  // 0x3F4A019F98CF38B6
-		W4  = -5.95187557450339963135e-04 // 0xBF4380CB8C0FE741
-		W5  = 8.36339918996282139126e-04  // 0x3F4B67BA4CDAD5D1
-		W6  = -1.63092934096575273989e-03 // 0xBF5AB89D0B9E43E4
+		Tt = -3.63867699703950536541e-18 // 0xBC50C7CAA48A971F
 	)
 	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
 	// when compiler does it for us
@@ -206,7 +223,7 @@ func Lgamma(x float64) (lgamma float64, sign int) {
 			lgamma = Inf(1) // -integer
 			return
 		}
-		nadj = Log(Pi / Fabs(t*x))
+		nadj = Log(Pi / Abs(t*x))
 		if t < 0 {
 			sign = -1
 		}
@@ -249,28 +266,28 @@ func Lgamma(x float64) (lgamma float64, sign int) {
 		switch i {
 		case 0:
 			z := y * y
-			p1 := A0 + z*(A2+z*(A4+z*(A6+z*(A8+z*A10))))
-			p2 := z * (A1 + z*(A3+z*(A5+z*(A7+z*(A9+z*A11)))))
+			p1 := _lgamA[0] + z*(_lgamA[2]+z*(_lgamA[4]+z*(_lgamA[6]+z*(_lgamA[8]+z*_lgamA[10]))))
+			p2 := z * (_lgamA[1] + z*(+_lgamA[3]+z*(_lgamA[5]+z*(_lgamA[7]+z*(_lgamA[9]+z*_lgamA[11])))))
 			p := y*p1 + p2
 			lgamma += (p - 0.5*y)
 		case 1:
 			z := y * y
 			w := z * y
-			p1 := T0 + w*(T3+w*(T6+w*(T9+w*T12))) // parallel comp
-			p2 := T1 + w*(T4+w*(T7+w*(T10+w*T13)))
-			p3 := T2 + w*(T5+w*(T8+w*(T11+w*T14)))
+			p1 := _lgamT[0] + w*(_lgamT[3]+w*(_lgamT[6]+w*(_lgamT[9]+w*_lgamT[12]))) // parallel comp
+			p2 := _lgamT[1] + w*(_lgamT[4]+w*(_lgamT[7]+w*(_lgamT[10]+w*_lgamT[13])))
+			p3 := _lgamT[2] + w*(_lgamT[5]+w*(_lgamT[8]+w*(_lgamT[11]+w*_lgamT[14])))
 			p := z*p1 - (Tt - w*(p2+y*p3))
 			lgamma += (Tf + p)
 		case 2:
-			p1 := y * (U0 + y*(U1+y*(U2+y*(U3+y*(U4+y*U5)))))
-			p2 := 1 + y*(V1+y*(V2+y*(V3+y*(V4+y*V5))))
+			p1 := y * (_lgamU[0] + y*(_lgamU[1]+y*(_lgamU[2]+y*(_lgamU[3]+y*(_lgamU[4]+y*_lgamU[5])))))
+			p2 := 1 + y*(_lgamV[1]+y*(_lgamV[2]+y*(_lgamV[3]+y*(_lgamV[4]+y*_lgamV[5]))))
 			lgamma += (-0.5*y + p1/p2)
 		}
 	case x < 8: // 2 <= x < 8
 		i := int(x)
 		y := x - float64(i)
-		p := y * (S0 + y*(S1+y*(S2+y*(S3+y*(S4+y*(S5+y*S6))))))
-		q := 1 + y*(R1+y*(R2+y*(R3+y*(R4+y*(R5+y*R6)))))
+		p := y * (_lgamS[0] + y*(_lgamS[1]+y*(_lgamS[2]+y*(_lgamS[3]+y*(_lgamS[4]+y*(_lgamS[5]+y*_lgamS[6]))))))
+		q := 1 + y*(_lgamR[1]+y*(_lgamR[2]+y*(_lgamR[3]+y*(_lgamR[4]+y*(_lgamR[5]+y*_lgamR[6])))))
 		lgamma = 0.5*y + p/q
 		z := 1.0 // Lgamma(1+s) = Log(s) + Lgamma(s)
 		switch i {
@@ -294,7 +311,7 @@ func Lgamma(x float64) (lgamma float64, sign int) {
 		t := Log(x)
 		z := 1 / x
 		y := z * z
-		w := W0 + z*(W1+y*(W2+y*(W3+y*(W4+y*(W5+y*W6)))))
+		w := _lgamW[0] + z*(_lgamW[1]+y*(_lgamW[2]+y*(_lgamW[3]+y*(_lgamW[4]+y*(_lgamW[5]+y*_lgamW[6])))))
 		lgamma = (x-0.5)*(t-1) + w
 	default: // 2**58 <= x <= Inf
 		lgamma = x * (Log(x) - 1)
@@ -319,7 +336,7 @@ func sinPi(x float64) float64 {
 	z := Floor(x)
 	var n int
 	if z != x { // inexact
-		x = Fmod(x, 2)
+		x = Mod(x, 2)
 		n = int(x * 4)
 	} else {
 		if x >= Two53 { // x must be even
diff --git a/src/pkg/math/log.go b/src/pkg/math/log.go
index a786c8c..1d467fb 100644
--- a/src/pkg/math/log.go
+++ b/src/pkg/math/log.go
@@ -77,7 +77,9 @@ package math
 //	Log(0) = -Inf
 //	Log(x < 0) = NaN
 //	Log(NaN) = NaN
-func Log(x float64) float64 {
+func Log(x float64) float64
+
+func log(x float64) float64 {
 	const (
 		Ln2Hi = 6.93147180369123816490e-01 /* 3fe62e42 fee00000 */
 		Ln2Lo = 1.90821492927058770002e-10 /* 3dea39ef 35793c76 */
diff --git a/src/pkg/math/log10.go b/src/pkg/math/log10.go
index 6d18baa..67c163a 100644
--- a/src/pkg/math/log10.go
+++ b/src/pkg/math/log10.go
@@ -6,8 +6,16 @@ package math
 
 // Log10 returns the decimal logarithm of x.
 // The special cases are the same as for Log.
-func Log10(x float64) float64 { return Log(x) * (1 / Ln10) }
+func Log10(x float64) float64
+
+func log10(x float64) float64 {
+	return Log(x) * (1 / Ln10)
+}
 
 // Log2 returns the binary logarithm of x.
 // The special cases are the same as for Log.
-func Log2(x float64) float64 { return Log(x) * (1 / Ln2) }
+func Log2(x float64) float64
+
+func log2(x float64) float64 {
+	return Log(x) * (1 / Ln2)
+}
diff --git a/src/pkg/math/log10_amd64.s b/src/pkg/math/log10_amd64.s
new file mode 100644
index 0000000..86a3b05
--- /dev/null
+++ b/src/pkg/math/log10_amd64.s
@@ -0,0 +1,9 @@
+// Copyright 2011 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.
+
+TEXT ·Log10(SB),7,$0
+	JMP ·log10(SB)
+
+TEXT ·Log2(SB),7,$0
+	JMP ·log2(SB)
diff --git a/src/pkg/math/log10_arm.s b/src/pkg/math/log10_arm.s
new file mode 100644
index 0000000..619b0fe
--- /dev/null
+++ b/src/pkg/math/log10_arm.s
@@ -0,0 +1,9 @@
+// Copyright 2011 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.
+
+TEXT ·Log10(SB),7,$0
+	B ·log10(SB)
+
+TEXT ·Log2(SB),7,$0
+	B ·log2(SB)
diff --git a/src/pkg/math/log10_decl.go b/src/pkg/math/log10_decl.go
deleted file mode 100644
index 5aec94e..0000000
--- a/src/pkg/math/log10_decl.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2010 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 math
-
-func Log10(x float64) float64
-func Log2(x float64) float64
diff --git a/src/pkg/math/log1p.go b/src/pkg/math/log1p.go
index c25d73b..dee7f2b 100644
--- a/src/pkg/math/log1p.go
+++ b/src/pkg/math/log1p.go
@@ -44,7 +44,7 @@ package math
 //                      2      4      6      8      10      12      14
 //          R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
 //      (the values of Lp1 to Lp7 are listed in the program)
-//      a-0.2929nd
+//      and
 //          |      2          14          |     -58.45
 //          | Lp1*s +...+Lp7*s    -  R(z) | <= 2
 //          |                             |
@@ -88,10 +88,13 @@ package math
 //
 // Special cases are:
 //	Log1p(+Inf) = +Inf
+//	Log1p(±0) = ±0
 //	Log1p(-1) = -Inf
 //	Log1p(x < -1) = NaN
 //	Log1p(NaN) = NaN
-func Log1p(x float64) float64 {
+func Log1p(x float64) float64
+
+func log1p(x float64) float64 {
 	const (
 		Sqrt2M1     = 4.142135623730950488017e-01  // Sqrt(2)-1 = 0x3fda827999fcef34
 		Sqrt2HalfM1 = -2.928932188134524755992e-01 // Sqrt(2)/2-1 = 0xbfd2bec333018866
diff --git a/src/pkg/math/log1p_amd64.s b/src/pkg/math/log1p_amd64.s
new file mode 100644
index 0000000..65c93ad
--- /dev/null
+++ b/src/pkg/math/log1p_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Log1p(SB),7,$0
+	JMP ·log1p(SB)
diff --git a/src/pkg/math/log1p_arm.s b/src/pkg/math/log1p_arm.s
new file mode 100644
index 0000000..0e599aa
--- /dev/null
+++ b/src/pkg/math/log1p_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Log1p(SB),7,$0
+	B ·log1p(SB)
diff --git a/src/pkg/math/log1p_decl.go b/src/pkg/math/log1p_decl.go
deleted file mode 100644
index 84b6030..0000000
--- a/src/pkg/math/log1p_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Log1p(x float64) float64
diff --git a/src/pkg/math/log_arm.s b/src/pkg/math/log_arm.s
new file mode 100644
index 0000000..3dce1e9
--- /dev/null
+++ b/src/pkg/math/log_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Log(SB),7,$0
+	B ·log(SB)
diff --git a/src/pkg/math/log_decl.go b/src/pkg/math/log_decl.go
deleted file mode 100644
index deda305..0000000
--- a/src/pkg/math/log_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Log(x float64) float64
diff --git a/src/pkg/math/mod.go b/src/pkg/math/mod.go
new file mode 100644
index 0000000..c1f244d
--- /dev/null
+++ b/src/pkg/math/mod.go
@@ -0,0 +1,52 @@
+// Copyright 2009-2010 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 math
+
+/*
+	Floating-point mod function.
+*/
+
+// Mod returns the floating-point remainder of x/y.
+// The magnitude of the result is less than y and its
+// sign agrees with that of x.
+//
+// Special cases are:
+//	Mod(±Inf, y) = NaN
+//	Mod(NaN, y) = NaN
+//	Mod(x, 0) = NaN
+//	Mod(x, ±Inf) = x
+//	Mod(x, NaN) = NaN
+func Mod(x, y float64) float64
+
+func mod(x, y float64) float64 {
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us.
+	if y == 0 || x > MaxFloat64 || x < -MaxFloat64 || x != x || y != y { // y == 0 || IsInf(x, 0) || IsNaN(x) || IsNan(y)
+		return NaN()
+	}
+	if y < 0 {
+		y = -y
+	}
+
+	yfr, yexp := Frexp(y)
+	sign := false
+	r := x
+	if x < 0 {
+		r = -x
+		sign = true
+	}
+
+	for r >= y {
+		rfr, rexp := Frexp(r)
+		if rfr < yfr {
+			rexp = rexp - 1
+		}
+		r = r - Ldexp(y, rexp-yexp)
+	}
+	if sign {
+		r = -r
+	}
+	return r
+}
diff --git a/src/pkg/math/mod_386.s b/src/pkg/math/mod_386.s
new file mode 100644
index 0000000..6b9c28d
--- /dev/null
+++ b/src/pkg/math/mod_386.s
@@ -0,0 +1,15 @@
+// Copyright 2010 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.
+
+// func Mod(x, y float64) float64
+TEXT ·Mod(SB),7,$0
+	FMOVD   y+8(FP), F0  // F0=y
+	FMOVD   x+0(FP), F0  // F0=x, F1=y
+	FPREM                // F0=reduced_x, F1=y
+	FSTSW   AX           // AX=status word
+	ANDW    $0x0400, AX
+	JNE     -3(PC)       // jump if reduction incomplete
+	FMOVDP  F0, F1       // F0=x-q*y
+	FMOVDP  F0, r+16(FP)
+	RET
diff --git a/src/pkg/math/mod_amd64.s b/src/pkg/math/mod_amd64.s
new file mode 100644
index 0000000..33b86be
--- /dev/null
+++ b/src/pkg/math/mod_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Mod(SB),7,$0
+	JMP ·mod(SB)
diff --git a/src/pkg/math/mod_arm.s b/src/pkg/math/mod_arm.s
new file mode 100644
index 0000000..47c564b
--- /dev/null
+++ b/src/pkg/math/mod_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Mod(SB),7,$0
+	B ·mod(SB)
diff --git a/src/pkg/math/modf.go b/src/pkg/math/modf.go
index 315174b..1e8376a 100644
--- a/src/pkg/math/modf.go
+++ b/src/pkg/math/modf.go
@@ -8,10 +8,11 @@ package math
 // that sum to f.  Both values have the same sign as f.
 //
 // Special cases are:
-//	Modf(+Inf) = +Inf, NaN
-//	Modf(-Inf) = -Inf, NaN
+//	Modf(±Inf) = ±Inf, NaN
 //	Modf(NaN) = NaN, NaN
-func Modf(f float64) (int float64, frac float64) {
+func Modf(f float64) (int float64, frac float64)
+
+func modf(f float64) (int float64, frac float64) {
 	if f < 1 {
 		if f < 0 {
 			int, frac = Modf(-f)
diff --git a/src/pkg/math/modf_amd64.s b/src/pkg/math/modf_amd64.s
new file mode 100644
index 0000000..2a6d7ea
--- /dev/null
+++ b/src/pkg/math/modf_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Modf(SB),7,$0
+	JMP ·modf(SB)
diff --git a/src/pkg/math/modf_arm.s b/src/pkg/math/modf_arm.s
new file mode 100644
index 0000000..6cef187
--- /dev/null
+++ b/src/pkg/math/modf_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Modf(SB),7,$0
+	B ·modf(SB)
diff --git a/src/pkg/math/modf_decl.go b/src/pkg/math/modf_decl.go
deleted file mode 100644
index 7add2af..0000000
--- a/src/pkg/math/modf_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Modf(f float64) (int float64, frac float64)
diff --git a/src/pkg/math/nextafter.go b/src/pkg/math/nextafter.go
index 8611434..e7723ba 100644
--- a/src/pkg/math/nextafter.go
+++ b/src/pkg/math/nextafter.go
@@ -8,8 +8,8 @@ package math
 // If x == y, then x is returned.
 //
 // Special cases are:
-//	Nextafter(NaN, y) = NaN
-//	Nextafter(x, NaN) = NaN
+//      Nextafter(NaN, y) = NaN
+//      Nextafter(x, NaN) = NaN
 func Nextafter(x, y float64) (r float64) {
 	// TODO(rsc): Remove manual inlining of IsNaN
 	// when compiler does it for us
@@ -25,5 +25,5 @@ func Nextafter(x, y float64) (r float64) {
 	default:
 		r = Float64frombits(Float64bits(x) - 1)
 	}
-	return r
+	return
 }
diff --git a/src/pkg/math/pow.go b/src/pkg/math/pow.go
index 06b1074..f0f52c5 100644
--- a/src/pkg/math/pow.go
+++ b/src/pkg/math/pow.go
@@ -66,7 +66,7 @@ func Pow(x, y float64) float64 {
 		switch {
 		case x == -1:
 			return 1
-		case (Fabs(x) < 1) == IsInf(y, 1):
+		case (Abs(x) < 1) == IsInf(y, 1):
 			return 0
 		default:
 			return Inf(1)
diff --git a/src/pkg/math/pow10.go b/src/pkg/math/pow10.go
index 20f91bc..f5ad28b 100644
--- a/src/pkg/math/pow10.go
+++ b/src/pkg/math/pow10.go
@@ -9,6 +9,10 @@ package math
 var pow10tab [70]float64
 
 // Pow10 returns 10**e, the base-10 exponential of e.
+//
+// Special cases are:
+//	Pow10(e) = +Inf for e > 309
+//	Pow10(e) = 0 for e < -324
 func Pow10(e int) float64 {
 	if e <= -325 {
 		return 0
diff --git a/src/pkg/math/rand/Makefile b/src/pkg/math/rand/Makefile
new file mode 100644
index 0000000..d2903d5
--- /dev/null
+++ b/src/pkg/math/rand/Makefile
@@ -0,0 +1,15 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=math/rand
+GOFILES=\
+	exp.go\
+	normal.go\
+	rand.go\
+	rng.go\
+	zipf.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/rand/exp.go b/src/pkg/math/rand/exp.go
similarity index 100%
rename from src/pkg/rand/exp.go
rename to src/pkg/math/rand/exp.go
diff --git a/src/pkg/rand/normal.go b/src/pkg/math/rand/normal.go
similarity index 100%
rename from src/pkg/rand/normal.go
rename to src/pkg/math/rand/normal.go
diff --git a/src/pkg/math/rand/rand.go b/src/pkg/math/rand/rand.go
new file mode 100644
index 0000000..8955219
--- /dev/null
+++ b/src/pkg/math/rand/rand.go
@@ -0,0 +1,181 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package rand implements pseudo-random number generators.
+package rand
+
+import "sync"
+
+// A Source represents a source of uniformly-distributed
+// pseudo-random int64 values in the range [0, 1<<63).
+type Source interface {
+	Int63() int64
+	Seed(seed int64)
+}
+
+// NewSource returns a new pseudo-random Source seeded with the given value.
+func NewSource(seed int64) Source {
+	var rng rngSource
+	rng.Seed(seed)
+	return &rng
+}
+
+// A Rand is a source of random numbers.
+type Rand struct {
+	src Source
+}
+
+// New returns a new Rand that uses random values from src
+// to generate other random values.
+func New(src Source) *Rand { return &Rand{src} }
+
+// Seed uses the provided seed value to initialize the generator to a deterministic state.
+func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
+func (r *Rand) Int63() int64 { return r.src.Int63() }
+
+// Uint32 returns a pseudo-random 32-bit value as a uint32.
+func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
+
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
+func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
+
+// Int returns a non-negative pseudo-random int.
+func (r *Rand) Int() int {
+	u := uint(r.Int63())
+	return int(u << 1 >> 1) // clear sign bit if int == int32
+}
+
+// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
+func (r *Rand) Int63n(n int64) int64 {
+	if n <= 0 {
+		return 0
+	}
+	max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
+	v := r.Int63()
+	for v > max {
+		v = r.Int63()
+	}
+	return v % n
+}
+
+// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
+func (r *Rand) Int31n(n int32) int32 {
+	if n <= 0 {
+		return 0
+	}
+	max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
+	v := r.Int31()
+	for v > max {
+		v = r.Int31()
+	}
+	return v % n
+}
+
+// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
+func (r *Rand) Intn(n int) int {
+	if n <= 1<<31-1 {
+		return int(r.Int31n(int32(n)))
+	}
+	return int(r.Int63n(int64(n)))
+}
+
+// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
+func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) }
+
+// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
+func (r *Rand) Float32() float32 { return float32(r.Float64()) }
+
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
+func (r *Rand) Perm(n int) []int {
+	m := make([]int, n)
+	for i := 0; i < n; i++ {
+		m[i] = i
+	}
+	for i := 0; i < n; i++ {
+		j := r.Intn(i + 1)
+		m[i], m[j] = m[j], m[i]
+	}
+	return m
+}
+
+/*
+ * Top-level convenience functions
+ */
+
+var globalRand = New(&lockedSource{src: NewSource(1)})
+
+// Seed uses the provided seed value to initialize the generator to a
+// deterministic state. If Seed is not called, the generator behaves as
+// if seeded by Seed(1).
+func Seed(seed int64) { globalRand.Seed(seed) }
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
+func Int63() int64 { return globalRand.Int63() }
+
+// Uint32 returns a pseudo-random 32-bit value as a uint32.
+func Uint32() uint32 { return globalRand.Uint32() }
+
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
+func Int31() int32 { return globalRand.Int31() }
+
+// Int returns a non-negative pseudo-random int.
+func Int() int { return globalRand.Int() }
+
+// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
+func Int63n(n int64) int64 { return globalRand.Int63n(n) }
+
+// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
+func Int31n(n int32) int32 { return globalRand.Int31n(n) }
+
+// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
+func Intn(n int) int { return globalRand.Intn(n) }
+
+// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
+func Float64() float64 { return globalRand.Float64() }
+
+// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
+func Float32() float32 { return globalRand.Float32() }
+
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
+func Perm(n int) []int { return globalRand.Perm(n) }
+
+// NormFloat64 returns a normally distributed float64 in the range
+// [-math.MaxFloat64, +math.MaxFloat64] with
+// standard normal distribution (mean = 0, stddev = 1).
+// To produce a different normal distribution, callers can
+// adjust the output using:
+//
+//  sample = NormFloat64() * desiredStdDev + desiredMean
+//
+func NormFloat64() float64 { return globalRand.NormFloat64() }
+
+// ExpFloat64 returns an exponentially distributed float64 in the range
+// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
+// (lambda) is 1 and whose mean is 1/lambda (1).
+// To produce a distribution with a different rate parameter,
+// callers can adjust the output using:
+//
+//  sample = ExpFloat64() / desiredRateParameter
+//
+func ExpFloat64() float64 { return globalRand.ExpFloat64() }
+
+type lockedSource struct {
+	lk  sync.Mutex
+	src Source
+}
+
+func (r *lockedSource) Int63() (n int64) {
+	r.lk.Lock()
+	n = r.src.Int63()
+	r.lk.Unlock()
+	return
+}
+
+func (r *lockedSource) Seed(seed int64) {
+	r.lk.Lock()
+	r.src.Seed(seed)
+	r.lk.Unlock()
+}
diff --git a/src/pkg/math/rand/rand_test.go b/src/pkg/math/rand/rand_test.go
new file mode 100644
index 0000000..0ba8f98
--- /dev/null
+++ b/src/pkg/math/rand/rand_test.go
@@ -0,0 +1,356 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+import (
+	"errors"
+	"fmt"
+	"math"
+	"testing"
+)
+
+const (
+	numTestSamples = 10000
+)
+
+type statsResults struct {
+	mean        float64
+	stddev      float64
+	closeEnough float64
+	maxError    float64
+}
+
+func max(a, b float64) float64 {
+	if a > b {
+		return a
+	}
+	return b
+}
+
+func nearEqual(a, b, closeEnough, maxError float64) bool {
+	absDiff := math.Abs(a - b)
+	if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero.
+		return true
+	}
+	return absDiff/max(math.Abs(a), math.Abs(b)) < maxError
+}
+
+var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
+
+// checkSimilarDistribution returns success if the mean and stddev of the
+// two statsResults are similar.
+func (this *statsResults) checkSimilarDistribution(expected *statsResults) error {
+	if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) {
+		s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError)
+		fmt.Println(s)
+		return errors.New(s)
+	}
+	if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) {
+		s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError)
+		fmt.Println(s)
+		return errors.New(s)
+	}
+	return nil
+}
+
+func getStatsResults(samples []float64) *statsResults {
+	res := new(statsResults)
+	var sum float64
+	for i := range samples {
+		sum += samples[i]
+	}
+	res.mean = sum / float64(len(samples))
+	var devsum float64
+	for i := range samples {
+		devsum += math.Pow(samples[i]-res.mean, 2)
+	}
+	res.stddev = math.Sqrt(devsum / float64(len(samples)))
+	return res
+}
+
+func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) {
+	actual := getStatsResults(samples)
+	err := actual.checkSimilarDistribution(expected)
+	if err != nil {
+		t.Errorf(err.Error())
+	}
+}
+
+func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) {
+	chunk := len(samples) / nslices
+	for i := 0; i < nslices; i++ {
+		low := i * chunk
+		var high int
+		if i == nslices-1 {
+			high = len(samples) - 1
+		} else {
+			high = (i + 1) * chunk
+		}
+		checkSampleDistribution(t, samples[low:high], expected)
+	}
+}
+
+//
+// Normal distribution tests
+//
+
+func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 {
+	r := New(NewSource(seed))
+	samples := make([]float64, nsamples)
+	for i := range samples {
+		samples[i] = r.NormFloat64()*stddev + mean
+	}
+	return samples
+}
+
+func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) {
+	//fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed);
+
+	samples := generateNormalSamples(nsamples, mean, stddev, seed)
+	errorScale := max(1.0, stddev) // Error scales with stddev
+	expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
+
+	// Make sure that the entire set matches the expected distribution.
+	checkSampleDistribution(t, samples, expected)
+
+	// Make sure that each half of the set matches the expected distribution.
+	checkSampleSliceDistributions(t, samples, 2, expected)
+
+	// Make sure that each 7th of the set matches the expected distribution.
+	checkSampleSliceDistributions(t, samples, 7, expected)
+}
+
+// Actual tests
+
+func TestStandardNormalValues(t *testing.T) {
+	for _, seed := range testSeeds {
+		testNormalDistribution(t, numTestSamples, 0, 1, seed)
+	}
+}
+
+func TestNonStandardNormalValues(t *testing.T) {
+	sdmax := 1000.0
+	mmax := 1000.0
+	if testing.Short() {
+		sdmax = 5
+		mmax = 5
+	}
+	for sd := 0.5; sd < sdmax; sd *= 2 {
+		for m := 0.5; m < mmax; m *= 2 {
+			for _, seed := range testSeeds {
+				testNormalDistribution(t, numTestSamples, m, sd, seed)
+			}
+		}
+	}
+}
+
+//
+// Exponential distribution tests
+//
+
+func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 {
+	r := New(NewSource(seed))
+	samples := make([]float64, nsamples)
+	for i := range samples {
+		samples[i] = r.ExpFloat64() / rate
+	}
+	return samples
+}
+
+func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) {
+	//fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed);
+
+	mean := 1 / rate
+	stddev := mean
+
+	samples := generateExponentialSamples(nsamples, rate, seed)
+	errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate
+	expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale}
+
+	// Make sure that the entire set matches the expected distribution.
+	checkSampleDistribution(t, samples, expected)
+
+	// Make sure that each half of the set matches the expected distribution.
+	checkSampleSliceDistributions(t, samples, 2, expected)
+
+	// Make sure that each 7th of the set matches the expected distribution.
+	checkSampleSliceDistributions(t, samples, 7, expected)
+}
+
+// Actual tests
+
+func TestStandardExponentialValues(t *testing.T) {
+	for _, seed := range testSeeds {
+		testExponentialDistribution(t, numTestSamples, 1, seed)
+	}
+}
+
+func TestNonStandardExponentialValues(t *testing.T) {
+	for rate := 0.05; rate < 10; rate *= 2 {
+		for _, seed := range testSeeds {
+			testExponentialDistribution(t, numTestSamples, rate, seed)
+		}
+	}
+}
+
+//
+// Table generation tests
+//
+
+func initNorm() (testKn []uint32, testWn, testFn []float32) {
+	const m1 = 1 << 31
+	var (
+		dn float64 = rn
+		tn         = dn
+		vn float64 = 9.91256303526217e-3
+	)
+
+	testKn = make([]uint32, 128)
+	testWn = make([]float32, 128)
+	testFn = make([]float32, 128)
+
+	q := vn / math.Exp(-0.5*dn*dn)
+	testKn[0] = uint32((dn / q) * m1)
+	testKn[1] = 0
+	testWn[0] = float32(q / m1)
+	testWn[127] = float32(dn / m1)
+	testFn[0] = 1.0
+	testFn[127] = float32(math.Exp(-0.5 * dn * dn))
+	for i := 126; i >= 1; i-- {
+		dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn)))
+		testKn[i+1] = uint32((dn / tn) * m1)
+		tn = dn
+		testFn[i] = float32(math.Exp(-0.5 * dn * dn))
+		testWn[i] = float32(dn / m1)
+	}
+	return
+}
+
+func initExp() (testKe []uint32, testWe, testFe []float32) {
+	const m2 = 1 << 32
+	var (
+		de float64 = re
+		te         = de
+		ve float64 = 3.9496598225815571993e-3
+	)
+
+	testKe = make([]uint32, 256)
+	testWe = make([]float32, 256)
+	testFe = make([]float32, 256)
+
+	q := ve / math.Exp(-de)
+	testKe[0] = uint32((de / q) * m2)
+	testKe[1] = 0
+	testWe[0] = float32(q / m2)
+	testWe[255] = float32(de / m2)
+	testFe[0] = 1.0
+	testFe[255] = float32(math.Exp(-de))
+	for i := 254; i >= 1; i-- {
+		de = -math.Log(ve/de + math.Exp(-de))
+		testKe[i+1] = uint32((de / te) * m2)
+		te = de
+		testFe[i] = float32(math.Exp(-de))
+		testWe[i] = float32(de / m2)
+	}
+	return
+}
+
+// compareUint32Slices returns the first index where the two slices
+// disagree, or <0 if the lengths are the same and all elements
+// are identical.
+func compareUint32Slices(s1, s2 []uint32) int {
+	if len(s1) != len(s2) {
+		if len(s1) > len(s2) {
+			return len(s2) + 1
+		}
+		return len(s1) + 1
+	}
+	for i := range s1 {
+		if s1[i] != s2[i] {
+			return i
+		}
+	}
+	return -1
+}
+
+// compareFloat32Slices returns the first index where the two slices
+// disagree, or <0 if the lengths are the same and all elements
+// are identical.
+func compareFloat32Slices(s1, s2 []float32) int {
+	if len(s1) != len(s2) {
+		if len(s1) > len(s2) {
+			return len(s2) + 1
+		}
+		return len(s1) + 1
+	}
+	for i := range s1 {
+		if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) {
+			return i
+		}
+	}
+	return -1
+}
+
+func TestNormTables(t *testing.T) {
+	testKn, testWn, testFn := initNorm()
+	if i := compareUint32Slices(kn[0:], testKn); i >= 0 {
+		t.Errorf("kn disagrees at index %v; %v != %v", i, kn[i], testKn[i])
+	}
+	if i := compareFloat32Slices(wn[0:], testWn); i >= 0 {
+		t.Errorf("wn disagrees at index %v; %v != %v", i, wn[i], testWn[i])
+	}
+	if i := compareFloat32Slices(fn[0:], testFn); i >= 0 {
+		t.Errorf("fn disagrees at index %v; %v != %v", i, fn[i], testFn[i])
+	}
+}
+
+func TestExpTables(t *testing.T) {
+	testKe, testWe, testFe := initExp()
+	if i := compareUint32Slices(ke[0:], testKe); i >= 0 {
+		t.Errorf("ke disagrees at index %v; %v != %v", i, ke[i], testKe[i])
+	}
+	if i := compareFloat32Slices(we[0:], testWe); i >= 0 {
+		t.Errorf("we disagrees at index %v; %v != %v", i, we[i], testWe[i])
+	}
+	if i := compareFloat32Slices(fe[0:], testFe); i >= 0 {
+		t.Errorf("fe disagrees at index %v; %v != %v", i, fe[i], testFe[i])
+	}
+}
+
+// Benchmarks
+
+func BenchmarkInt63Threadsafe(b *testing.B) {
+	for n := b.N; n > 0; n-- {
+		Int63()
+	}
+}
+
+func BenchmarkInt63Unthreadsafe(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Int63()
+	}
+}
+
+func BenchmarkIntn1000(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Intn(1000)
+	}
+}
+
+func BenchmarkInt63n1000(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Int63n(1000)
+	}
+}
+
+func BenchmarkInt31n1000(b *testing.B) {
+	r := New(NewSource(1))
+	for n := b.N; n > 0; n-- {
+		r.Int31n(1000)
+	}
+}
diff --git a/src/pkg/rand/rng.go b/src/pkg/math/rand/rng.go
similarity index 100%
rename from src/pkg/rand/rng.go
rename to src/pkg/math/rand/rng.go
diff --git a/src/pkg/rand/zipf.go b/src/pkg/math/rand/zipf.go
similarity index 100%
rename from src/pkg/rand/zipf.go
rename to src/pkg/math/rand/zipf.go
diff --git a/src/pkg/math/remainder.go b/src/pkg/math/remainder.go
index be8724c..69d23e5 100644
--- a/src/pkg/math/remainder.go
+++ b/src/pkg/math/remainder.go
@@ -24,17 +24,19 @@ package math
 //      precision arithmetic, where [x/y] is the (infinite bit)
 //      integer nearest x/y (in half way cases, choose the even one).
 // Method :
-//      Based on fmod() returning  x - [x/y]chopped * y  exactly.
+//      Based on Mod() returning  x - [x/y]chopped * y  exactly.
 
 // Remainder returns the IEEE 754 floating-point remainder of x/y.
 //
 // Special cases are:
-//	Remainder(x, NaN) = NaN
+//	Remainder(±Inf, y) = NaN
 //	Remainder(NaN, y) = NaN
-//	Remainder(Inf, y) = NaN
 //	Remainder(x, 0) = NaN
-//	Remainder(x, Inf) = x
-func Remainder(x, y float64) float64 {
+//	Remainder(x, ±Inf) = x
+//	Remainder(x, NaN) = NaN
+func Remainder(x, y float64) float64
+
+func remainder(x, y float64) float64 {
 	const (
 		Tiny    = 4.45014771701440276618e-308 // 0x0020000000000000
 		HalfMax = MaxFloat64 / 2
@@ -60,7 +62,7 @@ func Remainder(x, y float64) float64 {
 		return 0
 	}
 	if y <= HalfMax {
-		x = Fmod(x, y+y) // now x < 2y
+		x = Mod(x, y+y) // now x < 2y
 	}
 	if y < Tiny {
 		if x+x > y {
diff --git a/src/pkg/math/remainder_amd64.s b/src/pkg/math/remainder_amd64.s
new file mode 100644
index 0000000..f04bd3d
--- /dev/null
+++ b/src/pkg/math/remainder_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Remainder(SB),7,$0
+	JMP ·remainder(SB)
diff --git a/src/pkg/math/remainder_arm.s b/src/pkg/math/remainder_arm.s
new file mode 100644
index 0000000..642af6a
--- /dev/null
+++ b/src/pkg/math/remainder_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Remainder(SB),7,$0
+	B ·remainder(SB)
diff --git a/src/pkg/math/remainder_decl.go b/src/pkg/math/remainder_decl.go
deleted file mode 100644
index 1407d9a..0000000
--- a/src/pkg/math/remainder_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Remainder(x, y float64) float64
diff --git a/src/pkg/math/sin.go b/src/pkg/math/sin.go
index 8a2edd7..176ac22 100644
--- a/src/pkg/math/sin.go
+++ b/src/pkg/math/sin.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2011 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.
 
@@ -6,60 +6,223 @@ package math
 
 /*
 	Floating-point sine and cosine.
-
-	Coefficients are #5077 from Hart & Cheney. (18.80D)
 */
 
-func sinus(x float64, quad int) float64 {
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+//
+//      sin.c
+//
+//      Circular sine
+//
+// SYNOPSIS:
+//
+// double x, y, sin();
+// y = sin( x );
+//
+// DESCRIPTION:
+//
+// Range reduction is into intervals of pi/4.  The reduction error is nearly
+// eliminated by contriving an extended precision modular arithmetic.
+//
+// Two polynomial approximating functions are employed.
+// Between 0 and pi/4 the sine is approximated by
+//      x  +  x**3 P(x**2).
+// Between pi/4 and pi/2 the cosine is represented as
+//      1  -  x**2 Q(x**2).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain      # trials      peak         rms
+//    DEC       0, 10       150000       3.0e-17     7.8e-18
+//    IEEE -1.07e9,+1.07e9  130000       2.1e-16     5.4e-17
+//
+// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9.  The loss
+// is not gradual, but jumps suddenly to about 1 part in 10e7.  Results may
+// be meaningless for x > 2**49 = 5.6e14.
+//
+//      cos.c
+//
+//      Circular cosine
+//
+// SYNOPSIS:
+//
+// double x, y, cos();
+// y = cos( x );
+//
+// DESCRIPTION:
+//
+// Range reduction is into intervals of pi/4.  The reduction error is nearly
+// eliminated by contriving an extended precision modular arithmetic.
+//
+// Two polynomial approximating functions are employed.
+// Between 0 and pi/4 the cosine is approximated by
+//      1  -  x**2 Q(x**2).
+// Between pi/4 and pi/2 the sine is represented as
+//      x  +  x**3 P(x**2).
+//
+// ACCURACY:
+//
+//                      Relative error:
+// arithmetic   domain      # trials      peak         rms
+//    IEEE -1.07e9,+1.07e9  130000       2.1e-16     5.4e-17
+//    DEC        0,+1.07e9   17000       3.0e-17     7.2e-18
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// sin coefficients
+var _sin = [...]float64{
+	1.58962301576546568060E-10, // 0x3de5d8fd1fd19ccd
+	-2.50507477628578072866E-8, // 0xbe5ae5e5a9291f5d
+	2.75573136213857245213E-6,  // 0x3ec71de3567d48a1
+	-1.98412698295895385996E-4, // 0xbf2a01a019bfdf03
+	8.33333333332211858878E-3,  // 0x3f8111111110f7d0
+	-1.66666666666666307295E-1, // 0xbfc5555555555548
+}
+
+// cos coefficients
+var _cos = [...]float64{
+	-1.13585365213876817300E-11, // 0xbda8fa49a0861a9b
+	2.08757008419747316778E-9,   // 0x3e21ee9d7b4e3f05
+	-2.75573141792967388112E-7,  // 0xbe927e4f7eac4bc6
+	2.48015872888517045348E-5,   // 0x3efa01a019c844f5
+	-1.38888888888730564116E-3,  // 0xbf56c16c16c14f91
+	4.16666666666665929218E-2,   // 0x3fa555555555554b
+}
+
+// Cos returns the cosine of x.
+//
+// Special cases are:
+//	Cos(±Inf) = NaN
+//	Cos(NaN) = NaN
+func Cos(x float64) float64
+
+func cos(x float64) float64 {
 	const (
-		P0 = .1357884097877375669092680e8
-		P1 = -.4942908100902844161158627e7
-		P2 = .4401030535375266501944918e6
-		P3 = -.1384727249982452873054457e5
-		P4 = .1459688406665768722226959e3
-		Q0 = .8644558652922534429915149e7
-		Q1 = .4081792252343299749395779e6
-		Q2 = .9463096101538208180571257e4
-		Q3 = .1326534908786136358911494e3
+		PI4A = 7.85398125648498535156E-1                             // 0x3fe921fb40000000, Pi/4 split into three parts
+		PI4B = 3.77489470793079817668E-8                             // 0x3e64442d00000000,
+		PI4C = 2.69515142907905952645E-15                            // 0x3ce8469898cc5170,
+		M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
 	)
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us
+	// special cases
+	switch {
+	case x != x || x < -MaxFloat64 || x > MaxFloat64: // IsNaN(x) || IsInf(x, 0):
+		return NaN()
+	}
+
+	// make argument positive
+	sign := false
 	if x < 0 {
 		x = -x
-		quad = quad + 2
 	}
-	x = x * (2 / Pi) /* underflow? */
-	var y float64
-	if x > 32764 {
-		var e float64
-		e, y = Modf(x)
-		e = e + float64(quad)
-		f, _ := Modf(0.25 * e)
-		quad = int(e - 4*f)
-	} else {
-		k := int32(x)
-		y = x - float64(k)
-		quad = (quad + int(k)) & 3
+
+	j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+	y := float64(j)      // integer part of x/(Pi/4), as float
+
+	// map zeros to origin
+	if j&1 == 1 {
+		j += 1
+		y += 1
+	}
+	j &= 7 // octant modulo 2Pi radians (360 degrees)
+	if j > 3 {
+		j -= 4
+		sign = !sign
+	}
+	if j > 1 {
+		sign = !sign
 	}
 
-	if quad&1 != 0 {
-		y = 1 - y
+	z := ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
+	zz := z * z
+	if j == 1 || j == 2 {
+		y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
+	} else {
+		y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
 	}
-	if quad > 1 {
+	if sign {
 		y = -y
 	}
-
-	yy := y * y
-	temp1 := ((((P4*yy+P3)*yy+P2)*yy+P1)*yy + P0) * y
-	temp2 := ((((yy+Q3)*yy+Q2)*yy+Q1)*yy + Q0)
-	return temp1 / temp2
+	return y
 }
 
-// Cos returns the cosine of x.
-func Cos(x float64) float64 {
+// Sin returns the sine of x.
+//
+// Special cases are:
+//	Sin(±0) = ±0
+//	Sin(±Inf) = NaN
+//	Sin(NaN) = NaN
+func Sin(x float64) float64
+
+func sin(x float64) float64 {
+	const (
+		PI4A = 7.85398125648498535156E-1                             // 0x3fe921fb40000000, Pi/4 split into three parts
+		PI4B = 3.77489470793079817668E-8                             // 0x3e64442d00000000,
+		PI4C = 2.69515142907905952645E-15                            // 0x3ce8469898cc5170,
+		M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
+	)
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us
+	// special cases
+	switch {
+	case x == 0 || x != x: // x == 0 || IsNaN():
+		return x // return ±0 || NaN()
+	case x < -MaxFloat64 || x > MaxFloat64: // IsInf(x, 0):
+		return NaN()
+	}
+
+	// make argument positive but save the sign
+	sign := false
 	if x < 0 {
 		x = -x
+		sign = true
 	}
-	return sinus(x, 1)
-}
 
-// Sin returns the sine of x.
-func Sin(x float64) float64 { return sinus(x, 0) }
+	j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+	y := float64(j)      // integer part of x/(Pi/4), as float
+
+	// map zeros to origin
+	if j&1 == 1 {
+		j += 1
+		y += 1
+	}
+	j &= 7 // octant modulo 2Pi radians (360 degrees)
+	// reflect in x axis
+	if j > 3 {
+		sign = !sign
+		j -= 4
+	}
+
+	z := ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
+	zz := z * z
+	if j == 1 || j == 2 {
+		y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
+	} else {
+		y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
+	}
+	if sign {
+		y = -y
+	}
+	return y
+}
diff --git a/src/pkg/math/sin_amd64.s b/src/pkg/math/sin_amd64.s
new file mode 100644
index 0000000..c9c99e5
--- /dev/null
+++ b/src/pkg/math/sin_amd64.s
@@ -0,0 +1,9 @@
+// Copyright 2010 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.
+
+TEXT ·Sin(SB),7,$0
+	JMP	·sin(SB)
+
+TEXT ·Cos(SB),7,$0
+	JMP	·cos(SB)
diff --git a/src/pkg/math/sin_arm.s b/src/pkg/math/sin_arm.s
new file mode 100644
index 0000000..9447ca2
--- /dev/null
+++ b/src/pkg/math/sin_arm.s
@@ -0,0 +1,9 @@
+// Copyright 2010 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.
+
+TEXT ·Sin(SB),7,$0
+	B	·sin(SB)
+
+TEXT ·Cos(SB),7,$0
+	B	·cos(SB)
diff --git a/src/pkg/math/sin_decl.go b/src/pkg/math/sin_decl.go
deleted file mode 100644
index fc37b03..0000000
--- a/src/pkg/math/sin_decl.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-func Cos(x float64) float64
-func Sin(x float64) float64
diff --git a/src/pkg/math/sincos.go b/src/pkg/math/sincos.go
index 4c1576b..ff6c328 100644
--- a/src/pkg/math/sincos.go
+++ b/src/pkg/math/sincos.go
@@ -4,10 +4,68 @@
 
 package math
 
+// Coefficients _sin[] and _cos[] are found in pkg/math/sin.go.
+
 // Sincos(x) returns Sin(x), Cos(x).
 //
-// Special conditions are:
-//	Sincos(+Inf) = NaN, NaN
-//	Sincos(-Inf) = NaN, NaN
+// Special cases are:
+//	Sincos(±0) = ±0, 1
+//	Sincos(±Inf) = NaN, NaN
 //	Sincos(NaN) = NaN, NaN
-func Sincos(x float64) (sin, cos float64) { return Sin(x), Cos(x) }
+func Sincos(x float64) (sin, cos float64)
+
+func sincos(x float64) (sin, cos float64) {
+	const (
+		PI4A = 7.85398125648498535156E-1                             // 0x3fe921fb40000000, Pi/4 split into three parts
+		PI4B = 3.77489470793079817668E-8                             // 0x3e64442d00000000,
+		PI4C = 2.69515142907905952645E-15                            // 0x3ce8469898cc5170,
+		M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
+	)
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us
+	// special cases
+	switch {
+	case x == 0:
+		return x, 1 // return ±0.0, 1.0
+	case x != x || x < -MaxFloat64 || x > MaxFloat64: // IsNaN(x) || IsInf(x, 0):
+		return NaN(), NaN()
+	}
+
+	// make argument positive
+	sinSign, cosSign := false, false
+	if x < 0 {
+		x = -x
+		sinSign = true
+	}
+
+	j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+	y := float64(j)      // integer part of x/(Pi/4), as float
+
+	if j&1 == 1 { // map zeros to origin
+		j += 1
+		y += 1
+	}
+	j &= 7     // octant modulo 2Pi radians (360 degrees)
+	if j > 3 { // reflect in x axis
+		j -= 4
+		sinSign, cosSign = !sinSign, !cosSign
+	}
+	if j > 1 {
+		cosSign = !cosSign
+	}
+
+	z := ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic
+	zz := z * z
+	cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5])
+	sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5])
+	if j == 1 || j == 2 {
+		sin, cos = cos, sin
+	}
+	if cosSign {
+		cos = -cos
+	}
+	if sinSign {
+		sin = -sin
+	}
+	return
+}
diff --git a/src/pkg/math/sincos_arm.s b/src/pkg/math/sincos_arm.s
new file mode 100644
index 0000000..3e2b0e4
--- /dev/null
+++ b/src/pkg/math/sincos_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Sincos(SB),7,$0
+	B ·sincos(SB)
diff --git a/src/pkg/math/sincos_decl.go b/src/pkg/math/sincos_decl.go
deleted file mode 100644
index 0b40544..0000000
--- a/src/pkg/math/sincos_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Sincos(x float64) (sin, cos float64)
diff --git a/src/pkg/math/sinh.go b/src/pkg/math/sinh.go
index eaf28a5..139b911 100644
--- a/src/pkg/math/sinh.go
+++ b/src/pkg/math/sinh.go
@@ -17,6 +17,11 @@ package math
 */
 
 // Sinh returns the hyperbolic sine of x.
+//
+// Special cases are:
+//	Sinh(±0) = ±0
+//	Sinh(±Inf) = ±Inf
+//	Sinh(NaN) = NaN
 func Sinh(x float64) float64 {
 	// The coefficients are #2029 from Hart & Cheney. (20.36D)
 	const (
@@ -56,6 +61,11 @@ func Sinh(x float64) float64 {
 }
 
 // Cosh returns the hyperbolic cosine of x.
+//
+// Special cases are:
+//	Cosh(±0) = 1
+//	Cosh(±Inf) = +Inf
+//	Cosh(NaN) = NaN
 func Cosh(x float64) float64 {
 	if x < 0 {
 		x = -x
diff --git a/src/pkg/math/sqrt.go b/src/pkg/math/sqrt.go
index ff5cc91..d0b5535 100644
--- a/src/pkg/math/sqrt.go
+++ b/src/pkg/math/sqrt.go
@@ -11,4 +11,142 @@ package math
 //	Sqrt(±0) = ±0
 //	Sqrt(x < 0) = NaN
 //	Sqrt(NaN) = NaN
-func Sqrt(x float64) float64 { return sqrtGo(x) }
+func Sqrt(x float64) float64
+
+// The original C code and the long comment below are
+// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and
+// came with this notice.  The go code is a simplified
+// version of the original C.
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunPro, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// __ieee754_sqrt(x)
+// Return correctly rounded sqrt.
+//           -----------------------------------------
+//           | Use the hardware sqrt if you have one |
+//           -----------------------------------------
+// Method:
+//   Bit by bit method using integer arithmetic. (Slow, but portable)
+//   1. Normalization
+//      Scale x to y in [1,4) with even powers of 2:
+//      find an integer k such that  1 <= (y=x*2**(2k)) < 4, then
+//              sqrt(x) = 2**k * sqrt(y)
+//   2. Bit by bit computation
+//      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
+//           i                                                   0
+//                                     i+1         2
+//          s  = 2*q , and      y  =  2   * ( y - q  ).          (1)
+//           i      i            i                 i
+//
+//      To compute q    from q , one checks whether
+//                  i+1       i
+//
+//                            -(i+1) 2
+//                      (q + 2      )  <= y.                     (2)
+//                        i
+//                                                            -(i+1)
+//      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
+//                             i+1   i             i+1   i
+//
+//      With some algebraic manipulation, it is not difficult to see
+//      that (2) is equivalent to
+//                             -(i+1)
+//                      s  +  2       <= y                       (3)
+//                       i                i
+//
+//      The advantage of (3) is that s  and y  can be computed by
+//                                    i      i
+//      the following recurrence formula:
+//          if (3) is false
+//
+//          s     =  s  ,       y    = y   ;                     (4)
+//           i+1      i          i+1    i
+//
+//      otherwise,
+//                         -i                      -(i+1)
+//          s     =  s  + 2  ,  y    = y  -  s  - 2              (5)
+//           i+1      i          i+1    i     i
+//
+//      One may easily use induction to prove (4) and (5).
+//      Note. Since the left hand side of (3) contain only i+2 bits,
+//            it does not necessary to do a full (53-bit) comparison
+//            in (3).
+//   3. Final rounding
+//      After generating the 53 bits result, we compute one more bit.
+//      Together with the remainder, we can decide whether the
+//      result is exact, bigger than 1/2ulp, or less than 1/2ulp
+//      (it will never equal to 1/2ulp).
+//      The rounding mode can be detected by checking whether
+//      huge + tiny is equal to huge, and whether huge - tiny is
+//      equal to huge for some floating point number "huge" and "tiny".
+//
+//
+// Notes:  Rounding mode detection omitted.  The constants "mask", "shift",
+// and "bias" are found in src/pkg/math/bits.go
+
+// Sqrt returns the square root of x.
+//
+// Special cases are:
+//	Sqrt(+Inf) = +Inf
+//	Sqrt(±0) = ±0
+//	Sqrt(x < 0) = NaN
+//	Sqrt(NaN) = NaN
+func sqrt(x float64) float64 {
+	// special cases
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us
+	switch {
+	case x == 0 || x != x || x > MaxFloat64: // x == 0 || IsNaN(x) || IsInf(x, 1):
+		return x
+	case x < 0:
+		return NaN()
+	}
+	ix := Float64bits(x)
+	// normalize x
+	exp := int((ix >> shift) & mask)
+	if exp == 0 { // subnormal x
+		for ix&1<<shift == 0 {
+			ix <<= 1
+			exp--
+		}
+		exp++
+	}
+	exp -= bias // unbias exponent
+	ix &^= mask << shift
+	ix |= 1 << shift
+	if exp&1 == 1 { // odd exp, double x to make it even
+		ix <<= 1
+	}
+	exp >>= 1 // exp = exp/2, exponent of square root
+	// generate sqrt(x) bit by bit
+	ix <<= 1
+	var q, s uint64               // q = sqrt(x)
+	r := uint64(1 << (shift + 1)) // r = moving bit from MSB to LSB
+	for r != 0 {
+		t := s + r
+		if t <= ix {
+			s = t + r
+			ix -= t
+			q += r
+		}
+		ix <<= 1
+		r >>= 1
+	}
+	// final rounding
+	if ix != 0 { // remainder, result not exact
+		q += q & 1 // round according to extra bit
+	}
+	ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent
+	return Float64frombits(ix)
+}
+
+func sqrtC(f float64, r *float64) {
+	*r = sqrt(f)
+}
diff --git a/src/pkg/math/sqrt_decl.go b/src/pkg/math/sqrt_decl.go
deleted file mode 100644
index e507746..0000000
--- a/src/pkg/math/sqrt_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-func Sqrt(x float64) float64
diff --git a/src/pkg/math/sqrt_port.go b/src/pkg/math/sqrt_port.go
deleted file mode 100644
index 148239b..0000000
--- a/src/pkg/math/sqrt_port.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-/*
-	Floating-point square root.
-*/
-
-// The original C code and the long comment below are
-// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and
-// came with this notice.  The go code is a simplified
-// version of the original C.
-//
-// ====================================================
-// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-//
-// Developed at SunPro, a Sun Microsystems, Inc. business.
-// Permission to use, copy, modify, and distribute this
-// software is freely granted, provided that this notice
-// is preserved.
-// ====================================================
-//
-// __ieee754_sqrt(x)
-// Return correctly rounded sqrt.
-//           -----------------------------------------
-//           | Use the hardware sqrt if you have one |
-//           -----------------------------------------
-// Method:
-//   Bit by bit method using integer arithmetic. (Slow, but portable)
-//   1. Normalization
-//      Scale x to y in [1,4) with even powers of 2:
-//      find an integer k such that  1 <= (y=x*2**(2k)) < 4, then
-//              sqrt(x) = 2**k * sqrt(y)
-//   2. Bit by bit computation
-//      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
-//           i                                                   0
-//                                     i+1         2
-//          s  = 2*q , and      y  =  2   * ( y - q  ).          (1)
-//           i      i            i                 i
-//
-//      To compute q    from q , one checks whether
-//                  i+1       i
-//
-//                            -(i+1) 2
-//                      (q + 2      )  <= y.                     (2)
-//                        i
-//                                                            -(i+1)
-//      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
-//                             i+1   i             i+1   i
-//
-//      With some algebraic manipulation, it is not difficult to see
-//      that (2) is equivalent to
-//                             -(i+1)
-//                      s  +  2       <= y                       (3)
-//                       i                i
-//
-//      The advantage of (3) is that s  and y  can be computed by
-//                                    i      i
-//      the following recurrence formula:
-//          if (3) is false
-//
-//          s     =  s  ,       y    = y   ;                     (4)
-//           i+1      i          i+1    i
-//
-//      otherwise,
-//                         -i                      -(i+1)
-//          s     =  s  + 2  ,  y    = y  -  s  - 2              (5)
-//           i+1      i          i+1    i     i
-//
-//      One may easily use induction to prove (4) and (5).
-//      Note. Since the left hand side of (3) contain only i+2 bits,
-//            it does not necessary to do a full (53-bit) comparison
-//            in (3).
-//   3. Final rounding
-//      After generating the 53 bits result, we compute one more bit.
-//      Together with the remainder, we can decide whether the
-//      result is exact, bigger than 1/2ulp, or less than 1/2ulp
-//      (it will never equal to 1/2ulp).
-//      The rounding mode can be detected by checking whether
-//      huge + tiny is equal to huge, and whether huge - tiny is
-//      equal to huge for some floating point number "huge" and "tiny".
-//
-//
-// Notes:  Rounding mode detection omitted.  The constants "mask", "shift",
-// and "bias" are found in src/pkg/math/bits.go
-
-// Sqrt returns the square root of x.
-//
-// Special cases are:
-//	Sqrt(+Inf) = +Inf
-//	Sqrt(±0) = ±0
-//	Sqrt(x < 0) = NaN
-//	Sqrt(NaN) = NaN
-func sqrtGo(x float64) float64 {
-	// special cases
-	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
-	// when compiler does it for us
-	switch {
-	case x == 0 || x != x || x > MaxFloat64: // x == 0 || IsNaN(x) || IsInf(x, 1):
-		return x
-	case x < 0:
-		return NaN()
-	}
-	ix := Float64bits(x)
-	// normalize x
-	exp := int((ix >> shift) & mask)
-	if exp == 0 { // subnormal x
-		for ix&1<<shift == 0 {
-			ix <<= 1
-			exp--
-		}
-		exp++
-	}
-	exp -= bias // unbias exponent
-	ix &^= mask << shift
-	ix |= 1 << shift
-	if exp&1 == 1 { // odd exp, double x to make it even
-		ix <<= 1
-	}
-	exp >>= 1 // exp = exp/2, exponent of square root
-	// generate sqrt(x) bit by bit
-	ix <<= 1
-	var q, s uint64               // q = sqrt(x)
-	r := uint64(1 << (shift + 1)) // r = moving bit from MSB to LSB
-	for r != 0 {
-		t := s + r
-		if t <= ix {
-			s = t + r
-			ix -= t
-			q += r
-		}
-		ix <<= 1
-		r >>= 1
-	}
-	// final rounding
-	if ix != 0 { // remainder, result not exact
-		q += q & 1 // round according to extra bit
-	}
-	ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent
-	return Float64frombits(ix)
-}
-
-func sqrtGoC(f float64, r *float64) {
-	*r = sqrtGo(f)
-}
diff --git a/src/pkg/math/sqrt_test.go b/src/pkg/math/sqrt_test.go
deleted file mode 100644
index 84cbc16..0000000
--- a/src/pkg/math/sqrt_test.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2010 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 math
-
-// Make sqrtGo available for testing.
-
-func SqrtGo(x float64) float64 { return sqrtGo(x) }
diff --git a/src/pkg/math/tan.go b/src/pkg/math/tan.go
index 6d7a60b..4e722e1 100644
--- a/src/pkg/math/tan.go
+++ b/src/pkg/math/tan.go
@@ -1,64 +1,132 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2011 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 math
 
 /*
-	Floating point tangent.
+	Floating-point tangent.
 */
 
+// The original C code, the long comment, and the constants
+// below were from http://netlib.sandia.gov/cephes/cmath/sin.c,
+// available from http://www.netlib.org/cephes/cmath.tgz.
+// The go code is a simplified version of the original C.
+//
+//      tan.c
+//
+//      Circular tangent
+//
+// SYNOPSIS:
+//
+// double x, y, tan();
+// y = tan( x );
+//
+// DESCRIPTION:
+//
+// Returns the circular tangent of the radian argument x.
+//
+// Range reduction is modulo pi/4.  A rational function
+//       x + x**3 P(x**2)/Q(x**2)
+// is employed in the basic interval [0, pi/4].
+//
+// ACCURACY:
+//                      Relative error:
+// arithmetic   domain     # trials      peak         rms
+//    DEC      +-1.07e9      44000      4.1e-17     1.0e-17
+//    IEEE     +-1.07e9      30000      2.9e-16     8.1e-17
+//
+// Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9.  The loss
+// is not gradual, but jumps suddenly to about 1 part in 10e7.  Results may
+// be meaningless for x > 2**49 = 5.6e14.
+// [Accuracy loss statement from sin.go comments.]
+//
+// Cephes Math Library Release 2.8:  June, 2000
+// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+//
+// The readme file at http://netlib.sandia.gov/cephes/ says:
+//    Some software in this archive may be from the book _Methods and
+// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+// International, 1989) or from the Cephes Mathematical Library, a
+// commercial product. In either event, it is copyrighted by the author.
+// What you see here may be used freely but it comes with no support or
+// guarantee.
+//
+//   The two known misprints in the book are repaired here in the
+// source listings for the gamma function and the incomplete beta
+// integral.
+//
+//   Stephen L. Moshier
+//   moshier at na-net.ornl.gov
+
+// tan coefficients
+var _tanP = [...]float64{
+	-1.30936939181383777646E4, // 0xc0c992d8d24f3f38
+	1.15351664838587416140E6,  // 0x413199eca5fc9ddd
+	-1.79565251976484877988E7, // 0xc1711fead3299176
+}
+var _tanQ = [...]float64{
+	1.00000000000000000000E0,
+	1.36812963470692954678E4,  //0x40cab8a5eeb36572
+	-1.32089234440210967447E6, //0xc13427bc582abc96
+	2.50083801823357915839E7,  //0x4177d98fc2ead8ef
+	-5.38695755929454629881E7, //0xc189afe03cbe5a31
+}
+
 // Tan returns the tangent of x.
-func Tan(x float64) float64 {
-	// Coefficients are #4285 from Hart & Cheney. (19.74D)
+//
+// Special cases are:
+//	Tan(±0) = ±0
+//	Tan(±Inf) = NaN
+//	Tan(NaN) = NaN
+func Tan(x float64) float64
+
+func tan(x float64) float64 {
 	const (
-		P0 = -.1306820264754825668269611177e+5
-		P1 = .1055970901714953193602353981e+4
-		P2 = -.1550685653483266376941705728e+2
-		P3 = .3422554387241003435328470489e-1
-		P4 = .3386638642677172096076369e-4
-		Q0 = -.1663895238947119001851464661e+5
-		Q1 = .4765751362916483698926655581e+4
-		Q2 = -.1555033164031709966900124574e+3
+		PI4A = 7.85398125648498535156E-1                             // 0x3fe921fb40000000, Pi/4 split into three parts
+		PI4B = 3.77489470793079817668E-8                             // 0x3e64442d00000000,
+		PI4C = 2.69515142907905952645E-15                            // 0x3ce8469898cc5170,
+		M4PI = 1.273239544735162542821171882678754627704620361328125 // 4/pi
 	)
+	// TODO(rsc): Remove manual inlining of IsNaN, IsInf
+	// when compiler does it for us
+	// special cases
+	switch {
+	case x == 0 || x != x: // x == 0 || IsNaN():
+		return x // return ±0 || NaN()
+	case x < -MaxFloat64 || x > MaxFloat64: // IsInf(x, 0):
+		return NaN()
+	}
 
-	flag := false
+	// make argument positive but save the sign
 	sign := false
 	if x < 0 {
 		x = -x
 		sign = true
 	}
-	x = x * (4 / Pi) /* overflow? */
-	var e float64
-	e, x = Modf(x)
-	i := int32(e)
 
-	switch i & 3 {
-	case 1:
-		x = 1 - x
-		flag = true
+	j := int64(x * M4PI) // integer part of x/(Pi/4), as integer for tests on the phase angle
+	y := float64(j)      // integer part of x/(Pi/4), as float
 
-	case 2:
-		sign = !sign
-		flag = true
-
-	case 3:
-		x = 1 - x
-		sign = !sign
+	/* map zeros and singularities to origin */
+	if j&1 == 1 {
+		j += 1
+		y += 1
 	}
 
-	xsq := x * x
-	temp := ((((P4*xsq+P3)*xsq+P2)*xsq+P1)*xsq + P0) * x
-	temp = temp / (((xsq+Q2)*xsq+Q1)*xsq + Q0)
+	z := ((x - y*PI4A) - y*PI4B) - y*PI4C
+	zz := z * z
 
-	if flag {
-		if temp == 0 {
-			return NaN()
-		}
-		temp = 1 / temp
+	if zz > 1e-14 {
+		y = z + z*(zz*(((_tanP[0]*zz)+_tanP[1])*zz+_tanP[2])/((((zz+_tanQ[1])*zz+_tanQ[2])*zz+_tanQ[3])*zz+_tanQ[4]))
+	} else {
+		y = z
+	}
+	if j&2 == 2 {
+		y = -1 / y
 	}
 	if sign {
-		temp = -temp
+		y = -y
 	}
-	return temp
+	return y
 }
diff --git a/src/pkg/math/tan_amd64.s b/src/pkg/math/tan_amd64.s
new file mode 100644
index 0000000..823ceb2
--- /dev/null
+++ b/src/pkg/math/tan_amd64.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Tan(SB),7,$0
+	JMP ·tan(SB)
diff --git a/src/pkg/math/tan_arm.s b/src/pkg/math/tan_arm.s
new file mode 100644
index 0000000..4be35c3
--- /dev/null
+++ b/src/pkg/math/tan_arm.s
@@ -0,0 +1,6 @@
+// Copyright 2011 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.
+
+TEXT ·Tan(SB),7,$0
+	B ·tan(SB)
diff --git a/src/pkg/math/tan_decl.go b/src/pkg/math/tan_decl.go
deleted file mode 100644
index 2796b35..0000000
--- a/src/pkg/math/tan_decl.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 math
-
-func Tan(x float64) float64
diff --git a/src/pkg/math/tanh.go b/src/pkg/math/tanh.go
index f4a8a5a..03a641b 100644
--- a/src/pkg/math/tanh.go
+++ b/src/pkg/math/tanh.go
@@ -12,6 +12,11 @@ package math
 */
 
 // Tanh computes the hyperbolic tangent of x.
+//
+// Special cases are:
+//	Tanh(±0) = ±0
+//	Tanh(±Inf) = ±1
+//	Tanh(NaN) = NaN
 func Tanh(x float64) float64 {
 	if x < 0 {
 		x = -x
diff --git a/src/pkg/mime/Makefile b/src/pkg/mime/Makefile
index 901ed6f..38d809c 100644
--- a/src/pkg/mime/Makefile
+++ b/src/pkg/mime/Makefile
@@ -10,4 +10,27 @@ GOFILES=\
 	mediatype.go\
 	type.go\
 
+GOFILES_freebsd=\
+	type_unix.go
+
+GOFILES_darwin=\
+	type_unix.go
+
+GOFILES_linux=\
+	type_unix.go
+
+GOFILES_netbsd=\
+	type_unix.go
+
+GOFILES_openbsd=\
+	type_unix.go
+
+GOFILES_plan9=\
+	type_unix.go
+
+GOFILES_windows=\
+	type_windows.go
+
+GOFILES+=$(GOFILES_$(GOOS))
+
 include ../../Make.pkg
diff --git a/src/pkg/mime/grammar.go b/src/pkg/mime/grammar.go
index 70a94cd..e16a06c 100644
--- a/src/pkg/mime/grammar.go
+++ b/src/pkg/mime/grammar.go
@@ -10,16 +10,16 @@ import (
 
 // isTSpecial returns true if rune is in 'tspecials' as defined by RFC
 // 1521 and RFC 2045.
-func isTSpecial(rune int) bool {
-	return strings.IndexRune(`()<>@,;:\"/[]?=`, rune) != -1
+func isTSpecial(r rune) bool {
+	return strings.IndexRune(`()<>@,;:\"/[]?=`, r) != -1
 }
 
 // IsTokenChar returns true if rune is in 'token' as defined by RFC
 // 1521 and RFC 2045.
-func IsTokenChar(rune int) bool {
+func IsTokenChar(r rune) bool {
 	// token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
 	//             or tspecials>
-	return rune > 0x20 && rune < 0x7f && !isTSpecial(rune)
+	return r > 0x20 && r < 0x7f && !isTSpecial(r)
 }
 
 // IsToken returns true if s is a 'token' as as defined by RFC 1521
@@ -32,14 +32,14 @@ func IsToken(s string) bool {
 }
 
 // IsQText returns true if rune is in 'qtext' as defined by RFC 822.
-func IsQText(rune int) bool {
+func IsQText(r int) bool {
 	// CHAR        =  <any ASCII character>        ; (  0-177,  0.-127.)
 	// qtext       =  <any CHAR excepting <">,     ; => may be folded
 	//                "\" & CR, and including
 	//                linear-white-space>
-	switch rune {
+	switch r {
 	case '"', '\\', '\r':
 		return false
 	}
-	return rune < 0x80
+	return r < 0x80
 }
diff --git a/src/pkg/mime/mediatype.go b/src/pkg/mime/mediatype.go
index b0d3933..41844c2 100644
--- a/src/pkg/mime/mediatype.go
+++ b/src/pkg/mime/mediatype.go
@@ -6,23 +6,28 @@ package mime
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
-	"os"
 	"strings"
 	"unicode"
 )
 
-// FormatMediaType serializes type t, subtype sub and the paramaters
-// param as a media type conform RFC 2045 and RFC 2616.
-// The type, subtype, and parameter names are written in lower-case.
+// FormatMediaType serializes mediatype t and the parameters
+// param as a media type conforming to RFC 2045 and RFC 2616.
+// The type and parameter names are written in lower-case.
 // When any of the arguments result in a standard violation then
 // FormatMediaType returns the empty string.
-func FormatMediaType(t, sub string, param map[string]string) string {
-	if !(IsToken(t) && IsToken(sub)) {
+func FormatMediaType(t string, param map[string]string) string {
+	slash := strings.Index(t, "/")
+	if slash == -1 {
+		return ""
+	}
+	major, sub := t[:slash], t[slash+1:]
+	if !IsToken(major) || !IsToken(sub) {
 		return ""
 	}
 	var b bytes.Buffer
-	b.WriteString(strings.ToLower(t))
+	b.WriteString(strings.ToLower(major))
 	b.WriteByte('/')
 	b.WriteString(strings.ToLower(sub))
 
@@ -57,23 +62,23 @@ func FormatMediaType(t, sub string, param map[string]string) string {
 	return b.String()
 }
 
-func checkMediaTypeDisposition(s string) os.Error {
+func checkMediaTypeDisposition(s string) error {
 	typ, rest := consumeToken(s)
 	if typ == "" {
-		return os.NewError("mime: no media type")
+		return errors.New("mime: no media type")
 	}
 	if rest == "" {
 		return nil
 	}
 	if !strings.HasPrefix(rest, "/") {
-		return os.NewError("mime: expected slash after first token")
+		return errors.New("mime: expected slash after first token")
 	}
 	subtype, rest := consumeToken(rest[1:])
 	if subtype == "" {
-		return os.NewError("mime: expected token after slash")
+		return errors.New("mime: expected token after slash")
 	}
 	if rest != "" {
-		return os.NewError("mime: unexpected content after media subtype")
+		return errors.New("mime: unexpected content after media subtype")
 	}
 	return nil
 }
@@ -85,7 +90,7 @@ func checkMediaTypeDisposition(s string) os.Error {
 // to lowercase and trimmed of white space and a non-nil map.
 // The returned map, params, maps from the lowercase
 // attribute to the attribute value with its case preserved.
-func ParseMediaType(v string) (mediatype string, params map[string]string, err os.Error) {
+func ParseMediaType(v string) (mediatype string, params map[string]string, err error) {
 	i := strings.Index(v, ";")
 	if i == -1 {
 		i = len(v)
@@ -118,7 +123,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err o
 				return
 			}
 			// Parse error.
-			return "", nil, os.NewError("mime: invalid media parameter")
+			return "", nil, errors.New("mime: invalid media parameter")
 		}
 
 		pmap := params
@@ -135,7 +140,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string, err o
 		}
 		if _, exists := pmap[key]; exists {
 			// Duplicate parameter name is bogus.
-			return "", nil, os.NewError("mime: duplicate parameter name")
+			return "", nil, errors.New("mime: duplicate parameter name")
 		}
 		pmap[key] = value
 		v = rest
@@ -199,8 +204,8 @@ func decode2231Enc(v string) string {
 	return encv
 }
 
-func isNotTokenChar(rune int) bool {
-	return !IsTokenChar(rune)
+func isNotTokenChar(r rune) bool {
+	return !IsTokenChar(r)
 }
 
 // consumeToken consumes a token from the beginning of provided
@@ -228,24 +233,25 @@ func consumeValue(v string) (value, rest string) {
 		return consumeToken(v)
 	}
 
-	leadQuote := int(v[0])
+	leadQuote := rune(v[0])
 
 	// parse a quoted-string
 	rest = v[1:] // consume the leading quote
 	buffer := new(bytes.Buffer)
-	var idx, rune int
+	var idx int
+	var r rune
 	var nextIsLiteral bool
-	for idx, rune = range rest {
+	for idx, r = range rest {
 		switch {
 		case nextIsLiteral:
-			buffer.WriteRune(rune)
+			buffer.WriteRune(r)
 			nextIsLiteral = false
-		case rune == leadQuote:
+		case r == leadQuote:
 			return buffer.String(), rest[idx+1:]
-		case rune == '\\':
+		case r == '\\':
 			nextIsLiteral = true
-		case rune != '\r' && rune != '\n':
-			buffer.WriteRune(rune)
+		case r != '\r' && r != '\n':
+			buffer.WriteRune(r)
 		default:
 			return "", v
 		}
@@ -280,7 +286,7 @@ func consumeMediaParam(v string) (param, value, rest string) {
 	return param, value, rest
 }
 
-func percentHexUnescape(s string) (string, os.Error) {
+func percentHexUnescape(s string) (string, error) {
 	// Count %, check that they're well-formed.
 	percents := 0
 	for i := 0; i < len(s); {
diff --git a/src/pkg/mime/mediatype_test.go b/src/pkg/mime/mediatype_test.go
index 884573e..64ab291 100644
--- a/src/pkg/mime/mediatype_test.go
+++ b/src/pkg/mime/mediatype_test.go
@@ -249,7 +249,28 @@ func TestParseMediaTypeBogus(t *testing.T) {
 	if err == nil {
 		t.Fatalf("expected an error parsing invalid media type; got type %q, params %#v", mt, params)
 	}
-	if err.String() != "mime: invalid media parameter" {
+	if err.Error() != "mime: invalid media parameter" {
 		t.Errorf("expected invalid media parameter; got error %q", err)
 	}
 }
+
+type formatTest struct {
+	typ    string
+	params map[string]string
+	want   string
+}
+
+var formatTests = []formatTest{
+	{"noslash", nil, ""},
+	{"foo/BAR", nil, "foo/bar"},
+	{"foo/BAR", map[string]string{"X": "Y"}, "foo/bar; x=Y"},
+}
+
+func TestFormatMediaType(t *testing.T) {
+	for i, tt := range formatTests {
+		got := FormatMediaType(tt.typ, tt.params)
+		if got != tt.want {
+			t.Errorf("%d. FormatMediaType(%q, %v) = %q; want %q", i, tt.typ, tt.params, got, tt.want)
+		}
+	}
+}
diff --git a/src/pkg/mime/multipart/formdata.go b/src/pkg/mime/multipart/formdata.go
index 91404d6..ec643c1 100644
--- a/src/pkg/mime/multipart/formdata.go
+++ b/src/pkg/mime/multipart/formdata.go
@@ -6,6 +6,7 @@ package multipart
 
 import (
 	"bytes"
+	"errors"
 	"io"
 	"io/ioutil"
 	"net/textproto"
@@ -19,7 +20,7 @@ import (
 // a Content-Disposition of "form-data".
 // It stores up to maxMemory bytes of the file parts in memory
 // and the remainder on disk in temporary files.
-func (r *Reader) ReadForm(maxMemory int64) (f *Form, err os.Error) {
+func (r *Reader) ReadForm(maxMemory int64) (f *Form, err error) {
 	form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
 	defer func() {
 		if err != nil {
@@ -30,7 +31,7 @@ func (r *Reader) ReadForm(maxMemory int64) (f *Form, err os.Error) {
 	maxValueBytes := int64(10 << 20) // 10 MB is a lot of text.
 	for {
 		p, err := r.NextPart()
-		if err == os.EOF {
+		if err == io.EOF {
 			break
 		}
 		if err != nil {
@@ -47,13 +48,13 @@ func (r *Reader) ReadForm(maxMemory int64) (f *Form, err os.Error) {
 
 		if filename == "" {
 			// value, store as string in memory
-			n, err := io.Copyn(&b, p, maxValueBytes)
-			if err != nil && err != os.EOF {
+			n, err := io.CopyN(&b, p, maxValueBytes)
+			if err != nil && err != io.EOF {
 				return nil, err
 			}
 			maxValueBytes -= n
 			if maxValueBytes == 0 {
-				return nil, os.NewError("multipart: message too large")
+				return nil, errors.New("multipart: message too large")
 			}
 			form.Value[name] = append(form.Value[name], b.String())
 			continue
@@ -64,8 +65,8 @@ func (r *Reader) ReadForm(maxMemory int64) (f *Form, err os.Error) {
 			Filename: filename,
 			Header:   p.Header,
 		}
-		n, err := io.Copyn(&b, p, maxMemory+1)
-		if err != nil && err != os.EOF {
+		n, err := io.CopyN(&b, p, maxMemory+1)
+		if err != nil && err != io.EOF {
 			return nil, err
 		}
 		if n > maxMemory {
@@ -102,8 +103,8 @@ type Form struct {
 }
 
 // RemoveAll removes any temporary files associated with a Form.
-func (f *Form) RemoveAll() os.Error {
-	var err os.Error
+func (f *Form) RemoveAll() error {
+	var err error
 	for _, fhs := range f.File {
 		for _, fh := range fhs {
 			if fh.tmpfile != "" {
@@ -127,7 +128,7 @@ type FileHeader struct {
 }
 
 // Open opens and returns the FileHeader's associated File.
-func (fh *FileHeader) Open() (File, os.Error) {
+func (fh *FileHeader) Open() (File, error) {
 	if b := fh.content; b != nil {
 		r := io.NewSectionReader(sliceReaderAt(b), 0, int64(len(b)))
 		return sectionReadCloser{r}, nil
@@ -151,15 +152,15 @@ type sectionReadCloser struct {
 	*io.SectionReader
 }
 
-func (rc sectionReadCloser) Close() os.Error {
+func (rc sectionReadCloser) Close() error {
 	return nil
 }
 
 type sliceReaderAt []byte
 
-func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, os.Error) {
+func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, error) {
 	if int(off) >= len(r) || off < 0 {
-		return 0, os.EINVAL
+		return 0, io.ErrUnexpectedEOF
 	}
 	n := copy(b, r[int(off):])
 	return n, nil
diff --git a/src/pkg/mime/multipart/multipart.go b/src/pkg/mime/multipart/multipart.go
index f2b5072..64a11e6 100644
--- a/src/pkg/mime/multipart/multipart.go
+++ b/src/pkg/mime/multipart/multipart.go
@@ -20,7 +20,6 @@ import (
 	"io/ioutil"
 	"mime"
 	"net/textproto"
-	"os"
 )
 
 // TODO(bradfitz): inline these once the compiler can inline them in
@@ -69,7 +68,7 @@ func (p *Part) FileName() string {
 
 func (p *Part) parseContentDisposition() {
 	v := p.Header.Get("Content-Disposition")
-	var err os.Error
+	var err error
 	p.disposition, p.dispositionParams, err = mime.ParseMediaType(v)
 	if err != nil {
 		p.dispositionParams = emptyParams
@@ -90,7 +89,7 @@ func NewReader(reader io.Reader, boundary string) *Reader {
 	}
 }
 
-func newPart(mr *Reader) (*Part, os.Error) {
+func newPart(mr *Reader) (*Part, error) {
 	bp := &Part{
 		Header: make(map[string][]string),
 		mr:     mr,
@@ -102,7 +101,7 @@ func newPart(mr *Reader) (*Part, os.Error) {
 	return bp, nil
 }
 
-func (bp *Part) populateHeaders() os.Error {
+func (bp *Part) populateHeaders() error {
 	r := textproto.NewReader(bp.mr.bufReader)
 	header, err := r.ReadMIMEHeader()
 	if err == nil {
@@ -113,14 +112,14 @@ func (bp *Part) populateHeaders() os.Error {
 
 // Read reads the body of a part, after its headers and before the
 // next part (if any) begins.
-func (bp *Part) Read(p []byte) (n int, err os.Error) {
+func (bp *Part) Read(p []byte) (n int, err error) {
 	if bp.buffer.Len() >= len(p) {
 		// Internal buffer of unconsumed data is large enough for
 		// the read request.  No need to parse more at the moment.
 		return bp.buffer.Read(p)
 	}
 	peek, err := bp.mr.bufReader.Peek(4096) // TODO(bradfitz): add buffer size accessor
-	unexpectedEof := err == os.EOF
+	unexpectedEof := err == io.EOF
 	if err != nil && !unexpectedEof {
 		return 0, fmt.Errorf("multipart: Part Read: %v", err)
 	}
@@ -146,12 +145,12 @@ func (bp *Part) Read(p []byte) (n int, err os.Error) {
 		return 0, io.ErrUnexpectedEOF
 	}
 	if nCopy > 0 {
-		if _, err := io.Copyn(bp.buffer, bp.mr.bufReader, int64(nCopy)); err != nil {
+		if _, err := io.CopyN(bp.buffer, bp.mr.bufReader, int64(nCopy)); err != nil {
 			return 0, err
 		}
 	}
 	n, err = bp.buffer.Read(p)
-	if err == os.EOF && !foundBoundary {
+	if err == io.EOF && !foundBoundary {
 		// If the boundary hasn't been reached there's more to
 		// read, so don't pass through an EOF from the buffer
 		err = nil
@@ -159,7 +158,7 @@ func (bp *Part) Read(p []byte) (n int, err os.Error) {
 	return
 }
 
-func (bp *Part) Close() os.Error {
+func (bp *Part) Close() error {
 	io.Copy(ioutil.Discard, bp)
 	return nil
 }
@@ -177,8 +176,8 @@ type Reader struct {
 }
 
 // NextPart returns the next part in the multipart or an error.
-// When there are no more parts, the error os.EOF is returned.
-func (mr *Reader) NextPart() (*Part, os.Error) {
+// When there are no more parts, the error io.EOF is returned.
+func (mr *Reader) NextPart() (*Part, error) {
 	if mr.currentPart != nil {
 		mr.currentPart.Close()
 	}
@@ -202,7 +201,7 @@ func (mr *Reader) NextPart() (*Part, os.Error) {
 
 		if hasPrefixThenNewline(line, mr.dashBoundaryDash) {
 			// Expected EOF
-			return nil, os.EOF
+			return nil, io.EOF
 		}
 
 		if expectNewPart {
diff --git a/src/pkg/mime/multipart/multipart_test.go b/src/pkg/mime/multipart/multipart_test.go
index 38079e5..89ff5e4 100644
--- a/src/pkg/mime/multipart/multipart_test.go
+++ b/src/pkg/mime/multipart/multipart_test.go
@@ -6,11 +6,10 @@ package multipart
 
 import (
 	"bytes"
+	"encoding/json"
 	"fmt"
 	"io"
 	"io/ioutil"
-	"json"
-	"os"
 	"strings"
 	"testing"
 )
@@ -214,8 +213,8 @@ func testMultipart(t *testing.T, r io.Reader, onlyNewlines bool) {
 	if part != nil {
 		t.Error("Didn't expect a fifth part.")
 	}
-	if err != os.EOF {
-		t.Errorf("On fifth part expected os.EOF; got %v", err)
+	if err != io.EOF {
+		t.Errorf("On fifth part expected io.EOF; got %v", err)
 	}
 }
 
@@ -259,8 +258,8 @@ func TestVariousTextLineEndings(t *testing.T) {
 		if part != nil {
 			t.Errorf("Unexpected part in test %d", testNum)
 		}
-		if err != os.EOF {
-			t.Errorf("On test %d expected os.EOF; got %v", testNum, err)
+		if err != io.EOF {
+			t.Errorf("On test %d expected io.EOF; got %v", testNum, err)
 		}
 
 	}
@@ -273,11 +272,11 @@ type maliciousReader struct {
 
 const maxReadThreshold = 1 << 20
 
-func (mr *maliciousReader) Read(b []byte) (n int, err os.Error) {
+func (mr *maliciousReader) Read(b []byte) (n int, err error) {
 	mr.n += len(b)
 	if mr.n >= maxReadThreshold {
 		mr.t.Fatal("too much was read")
-		return 0, os.EOF
+		return 0, io.EOF
 	}
 	return len(b), nil
 }
@@ -346,7 +345,7 @@ type slowReader struct {
 	r io.Reader
 }
 
-func (s *slowReader) Read(p []byte) (int, os.Error) {
+func (s *slowReader) Read(p []byte) (int, error) {
 	if len(p) == 0 {
 		return s.r.Read(p)
 	}
diff --git a/src/pkg/mime/multipart/writer.go b/src/pkg/mime/multipart/writer.go
index 97a8897..ec70be4 100644
--- a/src/pkg/mime/multipart/writer.go
+++ b/src/pkg/mime/multipart/writer.go
@@ -7,10 +7,10 @@ package multipart
 import (
 	"bytes"
 	"crypto/rand"
+	"errors"
 	"fmt"
 	"io"
 	"net/textproto"
-	"os"
 	"strings"
 )
 
@@ -54,7 +54,7 @@ func randomBoundary() string {
 // header. The body of the part should be written to the returned
 // Writer. After calling CreatePart, any previous part may no longer
 // be written to.
-func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, os.Error) {
+func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error) {
 	if w.lastpart != nil {
 		if err := w.lastpart.close(); err != nil {
 			return nil, err
@@ -85,15 +85,15 @@ func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, os.Error) {
 	return p, nil
 }
 
+var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
+
 func escapeQuotes(s string) string {
-	s = strings.Replace(s, "\\", "\\\\", -1)
-	s = strings.Replace(s, "\"", "\\\"", -1)
-	return s
+	return quoteEscaper.Replace(s)
 }
 
 // CreateFormFile is a convenience wrapper around CreatePart. It creates
 // a new form-data header with the provided field name and file name.
-func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, os.Error) {
+func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error) {
 	h := make(textproto.MIMEHeader)
 	h.Set("Content-Disposition",
 		fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
@@ -104,7 +104,7 @@ func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, os.Error
 
 // CreateFormField calls CreatePart with a header using the
 // given field name.
-func (w *Writer) CreateFormField(fieldname string) (io.Writer, os.Error) {
+func (w *Writer) CreateFormField(fieldname string) (io.Writer, error) {
 	h := make(textproto.MIMEHeader)
 	h.Set("Content-Disposition",
 		fmt.Sprintf(`form-data; name="%s"`, escapeQuotes(fieldname)))
@@ -112,7 +112,7 @@ func (w *Writer) CreateFormField(fieldname string) (io.Writer, os.Error) {
 }
 
 // WriteField calls CreateFormField and then writes the given value.
-func (w *Writer) WriteField(fieldname, value string) os.Error {
+func (w *Writer) WriteField(fieldname, value string) error {
 	p, err := w.CreateFormField(fieldname)
 	if err != nil {
 		return err
@@ -123,7 +123,7 @@ func (w *Writer) WriteField(fieldname, value string) os.Error {
 
 // Close finishes the multipart message and writes the trailing
 // boundary end line to the output.
-func (w *Writer) Close() os.Error {
+func (w *Writer) Close() error {
 	if w.lastpart != nil {
 		if err := w.lastpart.close(); err != nil {
 			return err
@@ -137,17 +137,17 @@ func (w *Writer) Close() os.Error {
 type part struct {
 	mw     *Writer
 	closed bool
-	we     os.Error // last error that occurred writing
+	we     error // last error that occurred writing
 }
 
-func (p *part) close() os.Error {
+func (p *part) close() error {
 	p.closed = true
 	return p.we
 }
 
-func (p *part) Write(d []byte) (n int, err os.Error) {
+func (p *part) Write(d []byte) (n int, err error) {
 	if p.closed {
-		return 0, os.NewError("multipart: can't write to finished part")
+		return 0, errors.New("multipart: can't write to finished part")
 	}
 	n, err = p.mw.w.Write(d)
 	if err != nil {
diff --git a/src/pkg/mime/type.go b/src/pkg/mime/type.go
index 39bf40e..00cff26 100644
--- a/src/pkg/mime/type.go
+++ b/src/pkg/mime/type.go
@@ -6,19 +6,11 @@
 package mime
 
 import (
-	"bufio"
 	"fmt"
-	"os"
 	"strings"
 	"sync"
 )
 
-var typeFiles = []string{
-	"/etc/mime.types",
-	"/etc/apache2/mime.types",
-	"/etc/apache/mime.types",
-}
-
 var mimeTypes = map[string]string{
 	".css":  "text/css; charset=utf-8",
 	".gif":  "image/gif",
@@ -33,46 +25,13 @@ var mimeTypes = map[string]string{
 
 var mimeLock sync.RWMutex
 
-func loadMimeFile(filename string) {
-	f, err := os.Open(filename)
-	if err != nil {
-		return
-	}
-
-	reader := bufio.NewReader(f)
-	for {
-		line, err := reader.ReadString('\n')
-		if err != nil {
-			f.Close()
-			return
-		}
-		fields := strings.Fields(line)
-		if len(fields) <= 1 || fields[0][0] == '#' {
-			continue
-		}
-		mimeType := fields[0]
-		for _, ext := range fields[1:] {
-			if ext[0] == '#' {
-				break
-			}
-			setExtensionType("."+ext, mimeType)
-		}
-	}
-}
-
-func initMime() {
-	for _, filename := range typeFiles {
-		loadMimeFile(filename)
-	}
-}
-
 var once sync.Once
 
 // TypeByExtension returns the MIME type associated with the file extension ext.
 // The extension ext should begin with a leading dot, as in ".html".
 // When ext has no associated type, TypeByExtension returns "".
 //
-// The built-in table is small but is is augmented by the local
+// The built-in table is small but on unix it is augmented by the local
 // system's mime.types file(s) if available under one or more of these
 // names:
 //
@@ -80,6 +39,8 @@ var once sync.Once
 //   /etc/apache2/mime.types
 //   /etc/apache/mime.types
 //
+// Windows system mime types are extracted from registry.
+//
 // Text types have the charset parameter set to "utf-8" by default.
 func TypeByExtension(ext string) string {
 	once.Do(initMime)
@@ -92,7 +53,7 @@ func TypeByExtension(ext string) string {
 // AddExtensionType sets the MIME type associated with
 // the extension ext to typ.  The extension should begin with
 // a leading dot, as in ".html".
-func AddExtensionType(ext, typ string) os.Error {
+func AddExtensionType(ext, typ string) error {
 	if ext == "" || ext[0] != '.' {
 		return fmt.Errorf(`mime: extension "%s" misses dot`, ext)
 	}
@@ -100,22 +61,15 @@ func AddExtensionType(ext, typ string) os.Error {
 	return setExtensionType(ext, typ)
 }
 
-func setExtensionType(extension, mimeType string) os.Error {
-	full, param, err := ParseMediaType(mimeType)
+func setExtensionType(extension, mimeType string) error {
+	_, param, err := ParseMediaType(mimeType)
 	if err != nil {
 		return err
 	}
-	if split := strings.Index(full, "/"); split < 0 {
-		return fmt.Errorf(`mime: malformed MIME type "%s"`, mimeType)
-	} else {
-		main := full[:split]
-		sub := full[split+1:]
-		if main == "text" && param["charset"] == "" {
-			param["charset"] = "utf-8"
-		}
-		mimeType = FormatMediaType(main, sub, param)
+	if strings.HasPrefix(mimeType, "text/") && param["charset"] == "" {
+		param["charset"] = "utf-8"
+		mimeType = FormatMediaType(mimeType, param)
 	}
-
 	mimeLock.Lock()
 	mimeTypes[extension] = mimeType
 	mimeLock.Unlock()
diff --git a/src/pkg/mime/type_test.go b/src/pkg/mime/type_test.go
index 976f853..07e1cd5 100644
--- a/src/pkg/mime/type_test.go
+++ b/src/pkg/mime/type_test.go
@@ -6,15 +6,9 @@ package mime
 
 import "testing"
 
-var typeTests = map[string]string{
-	".t1":  "application/test",
-	".t2":  "text/test; charset=utf-8",
-	".png": "image/png",
-}
+var typeTests = initMimeForTests()
 
 func TestTypeByExtension(t *testing.T) {
-	typeFiles = []string{"test.types"}
-
 	for ext, want := range typeTests {
 		val := TypeByExtension(ext)
 		if val != want {
diff --git a/src/pkg/mime/type_unix.go b/src/pkg/mime/type_unix.go
new file mode 100644
index 0000000..2dab1ea
--- /dev/null
+++ b/src/pkg/mime/type_unix.go
@@ -0,0 +1,61 @@
+// Copyright 2010 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 darwin freebsd linux netbsd openbsd plan9
+
+package mime
+
+import (
+	"bufio"
+	"os"
+	"strings"
+)
+
+var typeFiles = []string{
+	"/etc/mime.types",
+	"/etc/apache2/mime.types",
+	"/etc/apache/mime.types",
+}
+
+func loadMimeFile(filename string) {
+	f, err := os.Open(filename)
+	if err != nil {
+		return
+	}
+
+	reader := bufio.NewReader(f)
+	for {
+		line, err := reader.ReadString('\n')
+		if err != nil {
+			f.Close()
+			return
+		}
+		fields := strings.Fields(line)
+		if len(fields) <= 1 || fields[0][0] == '#' {
+			continue
+		}
+		mimeType := fields[0]
+		for _, ext := range fields[1:] {
+			if ext[0] == '#' {
+				break
+			}
+			setExtensionType("."+ext, mimeType)
+		}
+	}
+}
+
+func initMime() {
+	for _, filename := range typeFiles {
+		loadMimeFile(filename)
+	}
+}
+
+func initMimeForTests() map[string]string {
+	typeFiles = []string{"test.types"}
+	return map[string]string{
+		".t1":  "application/test",
+		".t2":  "text/test; charset=utf-8",
+		".png": "image/png",
+	}
+}
diff --git a/src/pkg/mime/type_windows.go b/src/pkg/mime/type_windows.go
new file mode 100644
index 0000000..bc38889
--- /dev/null
+++ b/src/pkg/mime/type_windows.go
@@ -0,0 +1,61 @@
+// Copyright 2010 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 mime
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+func initMime() {
+	var root syscall.Handle
+	if syscall.RegOpenKeyEx(syscall.HKEY_CLASSES_ROOT, syscall.StringToUTF16Ptr(`\`),
+		0, syscall.KEY_READ, &root) != nil {
+		return
+	}
+	defer syscall.RegCloseKey(root)
+	var count uint32
+	if syscall.RegQueryInfoKey(root, nil, nil, nil, &count, nil, nil, nil, nil, nil, nil, nil) != nil {
+		return
+	}
+	var buf [1 << 10]uint16
+	for i := uint32(0); i < count; i++ {
+		n := uint32(len(buf))
+		if syscall.RegEnumKeyEx(root, i, &buf[0], &n, nil, nil, nil, nil) != nil {
+			continue
+		}
+		ext := syscall.UTF16ToString(buf[:])
+		if len(ext) < 2 || ext[0] != '.' { // looking for extensions only
+			continue
+		}
+		var h syscall.Handle
+		if syscall.RegOpenKeyEx(
+			syscall.HKEY_CLASSES_ROOT, syscall.StringToUTF16Ptr(`\`+ext),
+			0, syscall.KEY_READ, &h) != nil {
+			continue
+		}
+		var typ uint32
+		n = uint32(len(buf) * 2) // api expects array of bytes, not uint16
+		if syscall.RegQueryValueEx(
+			h, syscall.StringToUTF16Ptr("Content Type"),
+			nil, &typ, (*byte)(unsafe.Pointer(&buf[0])), &n) != nil {
+			syscall.RegCloseKey(h)
+			continue
+		}
+		syscall.RegCloseKey(h)
+		if typ != syscall.REG_SZ { // null terminated strings only
+			continue
+		}
+		mimeType := syscall.UTF16ToString(buf[:])
+		setExtensionType(ext, mimeType)
+	}
+}
+
+func initMimeForTests() map[string]string {
+	return map[string]string{
+		".bmp": "image/bmp",
+		".png": "image/png",
+	}
+}
diff --git a/src/pkg/net/Makefile b/src/pkg/net/Makefile
index eba9e26..a02798c 100644
--- a/src/pkg/net/Makefile
+++ b/src/pkg/net/Makefile
@@ -9,6 +9,7 @@ GOFILES=\
 	dial.go\
 	dnsclient.go\
 	dnsmsg.go\
+	doc.go\
 	hosts.go\
 	interface.go\
 	ip.go\
@@ -21,14 +22,14 @@ GOFILES=\
 	udpsock.go\
 	unixsock.go\
 
-GOFILES_freebsd=\
+GOFILES_darwin=\
 	dnsclient_unix.go\
 	dnsconfig.go\
 	fd.go\
 	fd_$(GOOS).go\
 	file.go\
 	interface_bsd.go\
-	interface_freebsd.go\
+	interface_darwin.go\
 	iprawsock_posix.go\
 	ipsock_posix.go\
 	lookup_unix.go\
@@ -37,26 +38,31 @@ GOFILES_freebsd=\
 	sendfile_stub.go\
 	sock.go\
 	sock_bsd.go\
+	sockopt.go\
+	sockopt_bsd.go\
+	sockoptip.go\
+	sockoptip_bsd.go\
+	sockoptip_darwin.go\
 	tcpsock_posix.go\
 	udpsock_posix.go\
 	unixsock_posix.go\
 
 ifeq ($(CGO_ENABLED),1)
-CGOFILES_freebsd=\
+CGOFILES_darwin=\
 	cgo_bsd.go\
 	cgo_unix.go
 else
-GOFILES_freebsd+=cgo_stub.go
+GOFILES_darwin+=cgo_stub.go
 endif
 
-GOFILES_darwin=\
+GOFILES_freebsd=\
 	dnsclient_unix.go\
 	dnsconfig.go\
 	fd.go\
 	fd_$(GOOS).go\
 	file.go\
 	interface_bsd.go\
-	interface_darwin.go\
+	interface_freebsd.go\
 	iprawsock_posix.go\
 	ipsock_posix.go\
 	lookup_unix.go\
@@ -65,16 +71,21 @@ GOFILES_darwin=\
 	sendfile_stub.go\
 	sock.go\
 	sock_bsd.go\
+	sockopt.go\
+	sockopt_bsd.go\
+	sockoptip.go\
+	sockoptip_bsd.go\
+	sockoptip_freebsd.go\
 	tcpsock_posix.go\
 	udpsock_posix.go\
 	unixsock_posix.go\
 
 ifeq ($(CGO_ENABLED),1)
-CGOFILES_darwin=\
+CGOFILES_freebsd=\
 	cgo_bsd.go\
 	cgo_unix.go
 else
-GOFILES_darwin+=cgo_stub.go
+GOFILES_freebsd+=cgo_stub.go
 endif
 
 GOFILES_linux=\
@@ -92,6 +103,10 @@ GOFILES_linux=\
 	sendfile_linux.go\
 	sock.go\
 	sock_linux.go\
+	sockopt.go\
+	sockopt_linux.go\
+	sockoptip.go\
+	sockoptip_linux.go\
 	tcpsock_posix.go\
 	udpsock_posix.go\
 	unixsock_posix.go\
@@ -104,6 +119,32 @@ else
 GOFILES_linux+=cgo_stub.go
 endif
 
+GOFILES_netbsd=\
+	dnsclient_unix.go\
+	dnsconfig.go\
+	fd.go\
+	fd_$(GOOS).go\
+	file.go\
+	interface_bsd.go\
+	interface_netbsd.go\
+	iprawsock_posix.go\
+	ipsock_posix.go\
+	lookup_unix.go\
+	newpollserver.go\
+	port.go\
+	sendfile_stub.go\
+	sock.go\
+	sock_bsd.go\
+	sockopt.go\
+	sockopt_bsd.go\
+	sockoptip.go\
+	sockoptip_bsd.go\
+	sockoptip_netbsd.go\
+	tcpsock_posix.go\
+	udpsock_posix.go\
+	unixsock_posix.go\
+	cgo_stub.go\
+
 GOFILES_openbsd=\
 	dnsclient_unix.go\
 	dnsconfig.go\
@@ -120,6 +161,11 @@ GOFILES_openbsd=\
 	sendfile_stub.go\
 	sock.go\
 	sock_bsd.go\
+	sockopt.go\
+	sockopt_bsd.go\
+	sockoptip.go\
+	sockoptip_bsd.go\
+	sockoptip_openbsd.go\
 	tcpsock_posix.go\
 	udpsock_posix.go\
 	unixsock_posix.go\
@@ -145,6 +191,10 @@ GOFILES_windows=\
 	sendfile_windows.go\
 	sock.go\
 	sock_windows.go\
+	sockopt.go\
+	sockopt_windows.go\
+	sockoptip.go\
+	sockoptip_windows.go\
 	tcpsock_posix.go\
 	udpsock_posix.go\
 	unixsock_posix.go\
diff --git a/src/pkg/net/cgo_stub.go b/src/pkg/net/cgo_stub.go
index 565cbe7..52e57d7 100644
--- a/src/pkg/net/cgo_stub.go
+++ b/src/pkg/net/cgo_stub.go
@@ -2,26 +2,24 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build openbsd
+// +build !cgo
 
 // Stub cgo routines for systems that do not use cgo to do network lookups.
 
 package net
 
-import "os"
-
-func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
+func cgoLookupHost(name string) (addrs []string, err error, completed bool) {
 	return nil, nil, false
 }
 
-func cgoLookupPort(network, service string) (port int, err os.Error, completed bool) {
+func cgoLookupPort(network, service string) (port int, err error, completed bool) {
 	return 0, nil, false
 }
 
-func cgoLookupIP(name string) (addrs []IP, err os.Error, completed bool) {
+func cgoLookupIP(name string) (addrs []IP, err error, completed bool) {
 	return nil, nil, false
 }
 
-func cgoLookupCNAME(name string) (cname string, err os.Error, completed bool) {
+func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
 	return "", nil, false
 }
diff --git a/src/pkg/net/cgo_unix.go b/src/pkg/net/cgo_unix.go
index ec2a393..36a3f3d 100644
--- a/src/pkg/net/cgo_unix.go
+++ b/src/pkg/net/cgo_unix.go
@@ -18,12 +18,11 @@ package net
 import "C"
 
 import (
-	"os"
 	"syscall"
 	"unsafe"
 )
 
-func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
+func cgoLookupHost(name string) (addrs []string, err error, completed bool) {
 	ip, err, completed := cgoLookupIP(name)
 	for _, p := range ip {
 		addrs = append(addrs, p.String())
@@ -31,7 +30,7 @@ func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
 	return
 }
 
-func cgoLookupPort(net, service string) (port int, err os.Error, completed bool) {
+func cgoLookupPort(net, service string) (port int, err error, completed bool) {
 	var res *C.struct_addrinfo
 	var hints C.struct_addrinfo
 
@@ -78,7 +77,7 @@ func cgoLookupPort(net, service string) (port int, err os.Error, completed bool)
 	return 0, &AddrError{"unknown port", net + "/" + service}, true
 }
 
-func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, completed bool) {
+func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, completed bool) {
 	var res *C.struct_addrinfo
 	var hints C.struct_addrinfo
 
@@ -98,11 +97,11 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp
 		if gerrno == C.EAI_NONAME {
 			str = noSuchHost
 		} else if gerrno == C.EAI_SYSTEM {
-			str = err.String()
+			str = err.Error()
 		} else {
 			str = C.GoString(C.gai_strerror(gerrno))
 		}
-		return nil, "", &DNSError{Error: str, Name: name}, true
+		return nil, "", &DNSError{Err: str, Name: name}, true
 	}
 	defer C.freeaddrinfo(res)
 	if res != nil {
@@ -133,12 +132,12 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp
 	return addrs, cname, nil, true
 }
 
-func cgoLookupIP(name string) (addrs []IP, err os.Error, completed bool) {
+func cgoLookupIP(name string) (addrs []IP, err error, completed bool) {
 	addrs, _, err, completed = cgoLookupIPCNAME(name)
 	return
 }
 
-func cgoLookupCNAME(name string) (cname string, err os.Error, completed bool) {
+func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
 	_, cname, err, completed = cgoLookupIPCNAME(name)
 	return
 }
diff --git a/src/pkg/net/dial.go b/src/pkg/net/dial.go
index 10c67dc..5d596bc 100644
--- a/src/pkg/net/dial.go
+++ b/src/pkg/net/dial.go
@@ -4,26 +4,63 @@
 
 package net
 
-import "os"
+import (
+	"time"
+)
 
-func resolveNetAddr(op, net, addr string) (a Addr, err os.Error) {
-	if addr == "" {
-		return nil, &OpError{op, net, nil, errMissingAddress}
+func parseDialNetwork(net string) (afnet string, proto int, err error) {
+	i := last(net, ':')
+	if i < 0 { // no colon
+		switch net {
+		case "tcp", "tcp4", "tcp6":
+		case "udp", "udp4", "udp6":
+		case "unix", "unixgram", "unixpacket":
+		default:
+			return "", 0, UnknownNetworkError(net)
+		}
+		return net, 0, nil
 	}
-	switch net {
-	case "tcp", "tcp4", "tcp6":
-		a, err = ResolveTCPAddr(net, addr)
-	case "udp", "udp4", "udp6":
-		a, err = ResolveUDPAddr(net, addr)
-	case "unix", "unixgram", "unixpacket":
-		a, err = ResolveUnixAddr(net, addr)
+	afnet = net[:i]
+	switch afnet {
 	case "ip", "ip4", "ip6":
-		a, err = ResolveIPAddr(net, addr)
-	default:
-		err = UnknownNetworkError(net)
+		protostr := net[i+1:]
+		proto, i, ok := dtoi(protostr, 0)
+		if !ok || i != len(protostr) {
+			proto, err = lookupProtocol(protostr)
+			if err != nil {
+				return "", 0, err
+			}
+		}
+		return afnet, proto, nil
 	}
+	return "", 0, UnknownNetworkError(net)
+}
+
+func resolveNetAddr(op, net, addr string) (afnet string, a Addr, err error) {
+	afnet, _, err = parseDialNetwork(net)
 	if err != nil {
-		return nil, &OpError{op, net + " " + addr, nil, err}
+		return "", nil, &OpError{op, net, nil, err}
+	}
+	if op == "dial" && addr == "" {
+		return "", nil, &OpError{op, net, nil, errMissingAddress}
+	}
+	switch afnet {
+	case "tcp", "tcp4", "tcp6":
+		if addr != "" {
+			a, err = ResolveTCPAddr(afnet, addr)
+		}
+	case "udp", "udp4", "udp6":
+		if addr != "" {
+			a, err = ResolveUDPAddr(afnet, addr)
+		}
+	case "ip", "ip4", "ip6":
+		if addr != "" {
+			a, err = ResolveIPAddr(afnet, addr)
+		}
+	case "unix", "unixgram", "unixpacket":
+		if addr != "" {
+			a, err = ResolveUnixAddr(afnet, addr)
+		}
 	}
 	return
 }
@@ -32,122 +69,160 @@ func resolveNetAddr(op, net, addr string) (a Addr, err os.Error) {
 //
 // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
 // "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
-// (IPv4-only), "ip6" (IPv6-only), "unix" and "unixgram".
+// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and "unixpacket".
 //
-// For IP networks, addresses have the form host:port.  If host is
-// a literal IPv6 address, it must be enclosed in square brackets.
-// The functions JoinHostPort and SplitHostPort manipulate 
-// addresses in this form.
+// For TCP and UDP networks, addresses have the form host:port.
+// If host is a literal IPv6 address, it must be enclosed
+// in square brackets.  The functions JoinHostPort and SplitHostPort
+// manipulate addresses in this form.
 //
 // Examples:
 //	Dial("tcp", "12.34.56.78:80")
 //	Dial("tcp", "google.com:80")
 //	Dial("tcp", "[de:ad:be:ef::ca:fe]:80")
 //
-func Dial(net, addr string) (c Conn, err os.Error) {
-	addri, err := resolveNetAddr("dial", net, addr)
+// For IP networks, addr must be "ip", "ip4" or "ip6" followed
+// by a colon and a protocol number or name.
+//
+// Examples:
+//	Dial("ip4:1", "127.0.0.1")
+//	Dial("ip6:ospf", "::1")
+//
+func Dial(net, addr string) (Conn, error) {
+	_, addri, err := resolveNetAddr("dial", net, addr)
 	if err != nil {
 		return nil, err
 	}
+	return dialAddr(net, addr, addri)
+}
+
+func dialAddr(net, addr string, addri Addr) (c Conn, err error) {
 	switch ra := addri.(type) {
 	case *TCPAddr:
 		c, err = DialTCP(net, nil, ra)
 	case *UDPAddr:
 		c, err = DialUDP(net, nil, ra)
-	case *UnixAddr:
-		c, err = DialUnix(net, nil, ra)
 	case *IPAddr:
 		c, err = DialIP(net, nil, ra)
+	case *UnixAddr:
+		c, err = DialUnix(net, nil, ra)
 	default:
-		err = UnknownNetworkError(net)
+		err = &OpError{"dial", net + " " + addr, nil, UnknownNetworkError(net)}
 	}
 	if err != nil {
-		return nil, &OpError{"dial", net + " " + addr, nil, err}
+		return nil, err
 	}
 	return
 }
 
+// DialTimeout acts like Dial but takes a timeout.
+// The timeout includes name resolution, if required.
+func DialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
+	// TODO(bradfitz): the timeout should be pushed down into the
+	// net package's event loop, so on timeout to dead hosts we
+	// don't have a goroutine sticking around for the default of
+	// ~3 minutes.
+	t := time.NewTimer(timeout)
+	defer t.Stop()
+	type pair struct {
+		Conn
+		error
+	}
+	ch := make(chan pair, 1)
+	resolvedAddr := make(chan Addr, 1)
+	go func() {
+		_, addri, err := resolveNetAddr("dial", net, addr)
+		if err != nil {
+			ch <- pair{nil, err}
+			return
+		}
+		resolvedAddr <- addri // in case we need it for OpError
+		c, err := dialAddr(net, addr, addri)
+		ch <- pair{c, err}
+	}()
+	select {
+	case <-t.C:
+		// Try to use the real Addr in our OpError, if we resolved it
+		// before the timeout. Otherwise we just use stringAddr.
+		var addri Addr
+		select {
+		case a := <-resolvedAddr:
+			addri = a
+		default:
+			addri = &stringAddr{net, addr}
+		}
+		err := &OpError{
+			Op:   "dial",
+			Net:  net,
+			Addr: addri,
+			Err:  &timeoutError{},
+		}
+		return nil, err
+	case p := <-ch:
+		return p.Conn, p.error
+	}
+	panic("unreachable")
+}
+
+type stringAddr struct {
+	net, addr string
+}
+
+func (a stringAddr) Network() string { return a.net }
+func (a stringAddr) String() string  { return a.addr }
+
 // Listen announces on the local network address laddr.
-// The network string net must be a stream-oriented
-// network: "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
-func Listen(net, laddr string) (l Listener, err os.Error) {
-	switch net {
+// The network string net must be a stream-oriented network:
+// "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
+func Listen(net, laddr string) (Listener, error) {
+	afnet, a, err := resolveNetAddr("listen", net, laddr)
+	if err != nil {
+		return nil, err
+	}
+	switch afnet {
 	case "tcp", "tcp4", "tcp6":
 		var la *TCPAddr
-		if laddr != "" {
-			if la, err = ResolveTCPAddr(net, laddr); err != nil {
-				return nil, err
-			}
-		}
-		l, err := ListenTCP(net, la)
-		if err != nil {
-			return nil, err
+		if a != nil {
+			la = a.(*TCPAddr)
 		}
-		return l, nil
+		return ListenTCP(afnet, la)
 	case "unix", "unixpacket":
 		var la *UnixAddr
-		if laddr != "" {
-			if la, err = ResolveUnixAddr(net, laddr); err != nil {
-				return nil, err
-			}
-		}
-		l, err := ListenUnix(net, la)
-		if err != nil {
-			return nil, err
+		if a != nil {
+			la = a.(*UnixAddr)
 		}
-		return l, nil
+		return ListenUnix(net, la)
 	}
 	return nil, UnknownNetworkError(net)
 }
 
 // ListenPacket announces on the local network address laddr.
 // The network string net must be a packet-oriented network:
-// "udp", "udp4", "udp6", or "unixgram".
-func ListenPacket(net, laddr string) (c PacketConn, err os.Error) {
-	switch net {
+// "udp", "udp4", "udp6", "ip", "ip4", "ip6" or "unixgram".
+func ListenPacket(net, addr string) (PacketConn, error) {
+	afnet, a, err := resolveNetAddr("listen", net, addr)
+	if err != nil {
+		return nil, err
+	}
+	switch afnet {
 	case "udp", "udp4", "udp6":
 		var la *UDPAddr
-		if laddr != "" {
-			if la, err = ResolveUDPAddr(net, laddr); err != nil {
-				return nil, err
-			}
+		if a != nil {
+			la = a.(*UDPAddr)
 		}
-		c, err := ListenUDP(net, la)
-		if err != nil {
-			return nil, err
+		return ListenUDP(net, la)
+	case "ip", "ip4", "ip6":
+		var la *IPAddr
+		if a != nil {
+			la = a.(*IPAddr)
 		}
-		return c, nil
+		return ListenIP(net, la)
 	case "unixgram":
 		var la *UnixAddr
-		if laddr != "" {
-			if la, err = ResolveUnixAddr(net, laddr); err != nil {
-				return nil, err
-			}
-		}
-		c, err := DialUnix(net, la, nil)
-		if err != nil {
-			return nil, err
-		}
-		return c, nil
-	}
-
-	var rawnet string
-	if rawnet, _, err = splitNetProto(net); err != nil {
-		switch rawnet {
-		case "ip", "ip4", "ip6":
-			var la *IPAddr
-			if laddr != "" {
-				if la, err = ResolveIPAddr(rawnet, laddr); err != nil {
-					return nil, err
-				}
-			}
-			c, err := ListenIP(net, la)
-			if err != nil {
-				return nil, err
-			}
-			return c, nil
+		if a != nil {
+			la = a.(*UnixAddr)
 		}
+		return DialUnix(net, la, nil)
 	}
-
 	return nil, UnknownNetworkError(net)
 }
diff --git a/src/pkg/net/dial_test.go b/src/pkg/net/dial_test.go
new file mode 100644
index 0000000..16b7263
--- /dev/null
+++ b/src/pkg/net/dial_test.go
@@ -0,0 +1,88 @@
+// Copyright 2011 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 net
+
+import (
+	"runtime"
+	"testing"
+	"time"
+)
+
+func newLocalListener(t *testing.T) Listener {
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		ln, err = Listen("tcp6", "[::1]:0")
+	}
+	if err != nil {
+		t.Fatal(err)
+	}
+	return ln
+}
+
+func TestDialTimeout(t *testing.T) {
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	errc := make(chan error)
+
+	const SOMAXCONN = 0x80 // copied from syscall, but not always available
+	const numConns = SOMAXCONN + 10
+
+	// TODO(bradfitz): It's hard to test this in a portable
+	// way. This is unforunate, but works for now.
+	switch runtime.GOOS {
+	case "linux":
+		// The kernel will start accepting TCP connections before userspace
+		// gets a chance to not accept them, so fire off a bunch to fill up
+		// the kernel's backlog.  Then we test we get a failure after that.
+		for i := 0; i < numConns; i++ {
+			go func() {
+				_, err := DialTimeout("tcp", ln.Addr().String(), 200*time.Millisecond)
+				errc <- err
+			}()
+		}
+	case "darwin":
+		// At least OS X 10.7 seems to accept any number of
+		// connections, ignoring listen's backlog, so resort
+		// to connecting to a hopefully-dead 127/8 address.
+		go func() {
+			_, err := DialTimeout("tcp", "127.0.71.111:80", 200*time.Millisecond)
+			errc <- err
+		}()
+	default:
+		// TODO(bradfitz): this probably doesn't work on
+		// Windows? SOMAXCONN is huge there.  I'm not sure how
+		// listen works there.
+		// OpenBSD may have a reject route to 10/8.
+		// FreeBSD likely works, but is untested.
+		t.Logf("skipping test on %q; untested.", runtime.GOOS)
+		return
+	}
+
+	connected := 0
+	for {
+		select {
+		case <-time.After(15 * time.Second):
+			t.Fatal("too slow")
+		case err := <-errc:
+			if err == nil {
+				connected++
+				if connected == numConns {
+					t.Fatal("all connections connected; expected some to time out")
+				}
+			} else {
+				terr, ok := err.(timeout)
+				if !ok {
+					t.Fatalf("got error %q; want error with timeout interface", err)
+				}
+				if !terr.Timeout() {
+					t.Fatalf("got error %q; not a timeout", err)
+				}
+				// Pass. We saw a timeout error.
+				return
+			}
+		}
+	}
+}
diff --git a/src/pkg/net/dialgoogle_test.go b/src/pkg/net/dialgoogle_test.go
index 9ad1770..81750a3 100644
--- a/src/pkg/net/dialgoogle_test.go
+++ b/src/pkg/net/dialgoogle_test.go
@@ -19,7 +19,7 @@ var ipv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present")
 // fd is already connected to the destination, port 80.
 // Run an HTTP request to fetch the appropriate page.
 func fetchGoogle(t *testing.T, fd Conn, network, addr string) {
-	req := []byte("GET /intl/en/privacy/ HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
+	req := []byte("GET /robots.txt HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
 	n, err := fd.Write(req)
 
 	buf := make([]byte, 1000)
diff --git a/src/pkg/net/dict/Makefile b/src/pkg/net/dict/Makefile
deleted file mode 100644
index eaa9e65..0000000
--- a/src/pkg/net/dict/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../../../Make.inc
-
-TARG=net/dict
-GOFILES=\
-	dict.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/net/dict/dict.go b/src/pkg/net/dict/dict.go
deleted file mode 100644
index b146ea2..0000000
--- a/src/pkg/net/dict/dict.go
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2010 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 dict implements the Dictionary Server Protocol
-// as defined in RFC 2229.
-package dict
-
-import (
-	"net/textproto"
-	"os"
-	"strconv"
-	"strings"
-)
-
-// A Client represents a client connection to a dictionary server.
-type Client struct {
-	text *textproto.Conn
-}
-
-// Dial returns a new client connected to a dictionary server at
-// addr on the given network.
-func Dial(network, addr string) (*Client, os.Error) {
-	text, err := textproto.Dial(network, addr)
-	if err != nil {
-		return nil, err
-	}
-	_, _, err = text.ReadCodeLine(220)
-	if err != nil {
-		text.Close()
-		return nil, err
-	}
-	return &Client{text: text}, nil
-}
-
-// Close closes the connection to the dictionary server.
-func (c *Client) Close() os.Error {
-	return c.text.Close()
-}
-
-// A Dict represents a dictionary available on the server.
-type Dict struct {
-	Name string // short name of dictionary
-	Desc string // long description
-}
-
-// Dicts returns a list of the dictionaries available on the server.
-func (c *Client) Dicts() ([]Dict, os.Error) {
-	id, err := c.text.Cmd("SHOW DB")
-	if err != nil {
-		return nil, err
-	}
-
-	c.text.StartResponse(id)
-	defer c.text.EndResponse(id)
-
-	_, _, err = c.text.ReadCodeLine(110)
-	if err != nil {
-		return nil, err
-	}
-	lines, err := c.text.ReadDotLines()
-	if err != nil {
-		return nil, err
-	}
-	_, _, err = c.text.ReadCodeLine(250)
-
-	dicts := make([]Dict, len(lines))
-	for i := range dicts {
-		d := &dicts[i]
-		a, _ := fields(lines[i])
-		if len(a) < 2 {
-			return nil, textproto.ProtocolError("invalid dictionary: " + lines[i])
-		}
-		d.Name = a[0]
-		d.Desc = a[1]
-	}
-	return dicts, err
-}
-
-// A Defn represents a definition.
-type Defn struct {
-	Dict Dict   // Dict where definition was found
-	Word string // Word being defined
-	Text []byte // Definition text, typically multiple lines
-}
-
-// Define requests the definition of the given word.
-// The argument dict names the dictionary to use,
-// the Name field of a Dict returned by Dicts.
-//
-// The special dictionary name "*" means to look in all the
-// server's dictionaries.
-// The special dictionary name "!" means to look in all the
-// server's dictionaries in turn, stopping after finding the word
-// in one of them.
-func (c *Client) Define(dict, word string) ([]*Defn, os.Error) {
-	id, err := c.text.Cmd("DEFINE %s %q", dict, word)
-	if err != nil {
-		return nil, err
-	}
-
-	c.text.StartResponse(id)
-	defer c.text.EndResponse(id)
-
-	_, line, err := c.text.ReadCodeLine(150)
-	if err != nil {
-		return nil, err
-	}
-	a, _ := fields(line)
-	if len(a) < 1 {
-		return nil, textproto.ProtocolError("malformed response: " + line)
-	}
-	n, err := strconv.Atoi(a[0])
-	if err != nil {
-		return nil, textproto.ProtocolError("invalid definition count: " + a[0])
-	}
-	def := make([]*Defn, n)
-	for i := 0; i < n; i++ {
-		_, line, err = c.text.ReadCodeLine(151)
-		if err != nil {
-			return nil, err
-		}
-		a, _ := fields(line)
-		if len(a) < 3 {
-			// skip it, to keep protocol in sync
-			i--
-			n--
-			def = def[0:n]
-			continue
-		}
-		d := &Defn{Word: a[0], Dict: Dict{a[1], a[2]}}
-		d.Text, err = c.text.ReadDotBytes()
-		if err != nil {
-			return nil, err
-		}
-		def[i] = d
-	}
-	_, _, err = c.text.ReadCodeLine(250)
-	return def, err
-}
-
-// Fields returns the fields in s.
-// Fields are space separated unquoted words
-// or quoted with single or double quote.
-func fields(s string) ([]string, os.Error) {
-	var v []string
-	i := 0
-	for {
-		for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
-			i++
-		}
-		if i >= len(s) {
-			break
-		}
-		if s[i] == '"' || s[i] == '\'' {
-			q := s[i]
-			// quoted string
-			var j int
-			for j = i + 1; ; j++ {
-				if j >= len(s) {
-					return nil, textproto.ProtocolError("malformed quoted string")
-				}
-				if s[j] == '\\' {
-					j++
-					continue
-				}
-				if s[j] == q {
-					j++
-					break
-				}
-			}
-			v = append(v, unquote(s[i+1:j-1]))
-			i = j
-		} else {
-			// atom
-			var j int
-			for j = i; j < len(s); j++ {
-				if s[j] == ' ' || s[j] == '\t' || s[j] == '\\' || s[j] == '"' || s[j] == '\'' {
-					break
-				}
-			}
-			v = append(v, s[i:j])
-			i = j
-		}
-		if i < len(s) {
-			c := s[i]
-			if c != ' ' && c != '\t' {
-				return nil, textproto.ProtocolError("quotes not on word boundaries")
-			}
-		}
-	}
-	return v, nil
-}
-
-func unquote(s string) string {
-	if strings.Index(s, "\\") < 0 {
-		return s
-	}
-	b := []byte(s)
-	w := 0
-	for r := 0; r < len(b); r++ {
-		c := b[r]
-		if c == '\\' {
-			r++
-			c = b[r]
-		}
-		b[w] = c
-		w++
-	}
-	return string(b[0:w])
-}
diff --git a/src/pkg/net/dnsclient.go b/src/pkg/net/dnsclient.go
index 93c04f6..f4ed8b8 100644
--- a/src/pkg/net/dnsclient.go
+++ b/src/pkg/net/dnsclient.go
@@ -7,20 +7,19 @@ package net
 import (
 	"bytes"
 	"fmt"
-	"os"
-	"rand"
+	"math/rand"
 	"sort"
 )
 
 // DNSError represents a DNS lookup error.
 type DNSError struct {
-	Error     string // description of the error
+	Err       string // description of the error
 	Name      string // name looked for
 	Server    string // server used
 	IsTimeout bool
 }
 
-func (e *DNSError) String() string {
+func (e *DNSError) Error() string {
 	if e == nil {
 		return "<nil>"
 	}
@@ -28,7 +27,7 @@ func (e *DNSError) String() string {
 	if e.Server != "" {
 		s += " on " + e.Server
 	}
-	s += ": " + e.Error
+	s += ": " + e.Err
 	return s
 }
 
@@ -40,10 +39,10 @@ const noSuchHost = "no such host"
 // reverseaddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
 // address addr suitable for rDNS (PTR) record lookup or an error if it fails
 // to parse the IP address.
-func reverseaddr(addr string) (arpa string, err os.Error) {
+func reverseaddr(addr string) (arpa string, err error) {
 	ip := ParseIP(addr)
 	if ip == nil {
-		return "", &DNSError{Error: "unrecognized address", Name: addr}
+		return "", &DNSError{Err: "unrecognized address", Name: addr}
 	}
 	if ip.To4() != nil {
 		return fmt.Sprintf("%d.%d.%d.%d.in-addr.arpa.", ip[15], ip[14], ip[13], ip[12]), nil
@@ -64,18 +63,18 @@ func reverseaddr(addr string) (arpa string, err os.Error) {
 
 // Find answer for name in dns message.
 // On return, if err == nil, addrs != nil.
-func answer(name, server string, dns *dnsMsg, qtype uint16) (cname string, addrs []dnsRR, err os.Error) {
+func answer(name, server string, dns *dnsMsg, qtype uint16) (cname string, addrs []dnsRR, err error) {
 	addrs = make([]dnsRR, 0, len(dns.answer))
 
 	if dns.rcode == dnsRcodeNameError && dns.recursion_available {
-		return "", nil, &DNSError{Error: noSuchHost, Name: name}
+		return "", nil, &DNSError{Err: noSuchHost, Name: name}
 	}
 	if dns.rcode != dnsRcodeSuccess {
 		// None of the error codes make sense
 		// for the query we sent.  If we didn't get
 		// a name error and we didn't get success,
 		// the server is behaving incorrectly.
-		return "", nil, &DNSError{Error: "server misbehaving", Name: name, Server: server}
+		return "", nil, &DNSError{Err: "server misbehaving", Name: name, Server: server}
 	}
 
 	// Look for the name.
@@ -107,12 +106,12 @@ Cname:
 			}
 		}
 		if len(addrs) == 0 {
-			return "", nil, &DNSError{Error: noSuchHost, Name: name, Server: server}
+			return "", nil, &DNSError{Err: noSuchHost, Name: name, Server: server}
 		}
 		return name, addrs, nil
 	}
 
-	return "", nil, &DNSError{Error: "too many redirects", Name: name, Server: server}
+	return "", nil, &DNSError{Err: "too many redirects", Name: name, Server: server}
 }
 
 func isDomainName(s string) bool {
diff --git a/src/pkg/net/dnsclient_unix.go b/src/pkg/net/dnsclient_unix.go
index eb7db5e..18c3936 100644
--- a/src/pkg/net/dnsclient_unix.go
+++ b/src/pkg/net/dnsclient_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 // DNS client: see RFC 1035.
 // Has to be linked into package net for Dial.
@@ -17,27 +17,26 @@
 package net
 
 import (
-	"os"
-	"rand"
+	"math/rand"
 	"sync"
 	"time"
 )
 
 // Send a request on the connection and hope for a reply.
 // Up to cfg.attempts attempts.
-func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, os.Error) {
+func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error) {
 	if len(name) >= 256 {
-		return nil, &DNSError{Error: "name too long", Name: name}
+		return nil, &DNSError{Err: "name too long", Name: name}
 	}
 	out := new(dnsMsg)
-	out.id = uint16(rand.Int()) ^ uint16(time.Nanoseconds())
+	out.id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano())
 	out.question = []dnsQuestion{
 		{name, qtype, dnsClassINET},
 	}
 	out.recursion_desired = true
 	msg, ok := out.Pack()
 	if !ok {
-		return nil, &DNSError{Error: "internal error - cannot pack message", Name: name}
+		return nil, &DNSError{Err: "internal error - cannot pack message", Name: name}
 	}
 
 	for attempt := 0; attempt < cfg.attempts; attempt++ {
@@ -46,7 +45,11 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, os.Er
 			return nil, err
 		}
 
-		c.SetReadTimeout(int64(cfg.timeout) * 1e9) // nanoseconds
+		if cfg.timeout == 0 {
+			c.SetReadDeadline(time.Time{})
+		} else {
+			c.SetReadDeadline(time.Now().Add(time.Duration(cfg.timeout) * time.Second))
+		}
 
 		buf := make([]byte, 2000) // More than enough.
 		n, err = c.Read(buf)
@@ -67,14 +70,14 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, os.Er
 	if a := c.RemoteAddr(); a != nil {
 		server = a.String()
 	}
-	return nil, &DNSError{Error: "no answer from server", Name: name, Server: server, IsTimeout: true}
+	return nil, &DNSError{Err: "no answer from server", Name: name, Server: server, IsTimeout: true}
 }
 
 // Do a lookup for a single name, which must be rooted
 // (otherwise answer will not find the answers).
-func tryOneName(cfg *dnsConfig, name string, qtype uint16) (cname string, addrs []dnsRR, err os.Error) {
+func tryOneName(cfg *dnsConfig, name string, qtype uint16) (cname string, addrs []dnsRR, err error) {
 	if len(cfg.servers) == 0 {
-		return "", nil, &DNSError{Error: "no DNS servers", Name: name}
+		return "", nil, &DNSError{Err: "no DNS servers", Name: name}
 	}
 	for i := 0; i < len(cfg.servers); i++ {
 		// Calling Dial here is scary -- we have to be sure
@@ -96,7 +99,7 @@ func tryOneName(cfg *dnsConfig, name string, qtype uint16) (cname string, addrs
 			continue
 		}
 		cname, addrs, err = answer(name, server, msg, qtype)
-		if err == nil || err.(*DNSError).Error == noSuchHost {
+		if err == nil || err.(*DNSError).Err == noSuchHost {
 			break
 		}
 	}
@@ -123,15 +126,15 @@ func convertRR_AAAA(records []dnsRR) []IP {
 }
 
 var cfg *dnsConfig
-var dnserr os.Error
+var dnserr error
 
 func loadConfig() { cfg, dnserr = dnsReadConfig() }
 
 var onceLoadConfig sync.Once
 
-func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err os.Error) {
+func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err error) {
 	if !isDomainName(name) {
-		return name, nil, &DNSError{Error: "invalid domain name", Name: name}
+		return name, nil, &DNSError{Err: "invalid domain name", Name: name}
 	}
 	onceLoadConfig.Do(loadConfig)
 	if dnserr != nil || cfg == nil {
@@ -186,7 +189,7 @@ func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err os.Erro
 // Normally we let cgo use the C library resolver instead of
 // depending on our lookup code, so that Go and C get the same
 // answers.
-func goLookupHost(name string) (addrs []string, err os.Error) {
+func goLookupHost(name string) (addrs []string, err error) {
 	// Use entries from /etc/hosts if they match.
 	addrs = lookupStaticHost(name)
 	if len(addrs) > 0 {
@@ -214,7 +217,7 @@ func goLookupHost(name string) (addrs []string, err os.Error) {
 // Normally we let cgo use the C library resolver instead of
 // depending on our lookup code, so that Go and C get the same
 // answers.
-func goLookupIP(name string) (addrs []IP, err os.Error) {
+func goLookupIP(name string) (addrs []IP, err error) {
 	// Use entries from /etc/hosts if possible.
 	haddrs := lookupStaticHost(name)
 	if len(haddrs) > 0 {
@@ -260,7 +263,7 @@ func goLookupIP(name string) (addrs []IP, err os.Error) {
 // Normally we let cgo use the C library resolver instead of
 // depending on our lookup code, so that Go and C get the same
 // answers.
-func goLookupCNAME(name string) (cname string, err os.Error) {
+func goLookupCNAME(name string) (cname string, err error) {
 	onceLoadConfig.Do(loadConfig)
 	if dnserr != nil || cfg == nil {
 		err = dnserr
diff --git a/src/pkg/net/dnsconfig.go b/src/pkg/net/dnsconfig.go
index afc0599..c0ab802 100644
--- a/src/pkg/net/dnsconfig.go
+++ b/src/pkg/net/dnsconfig.go
@@ -2,14 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 // Read system DNS config from /etc/resolv.conf
 
 package net
 
-import "os"
-
 type dnsConfig struct {
 	servers  []string // servers to use
 	search   []string // suffixes to append to local name
@@ -19,14 +17,14 @@ type dnsConfig struct {
 	rotate   bool     // round robin among servers
 }
 
-var dnsconfigError os.Error
+var dnsconfigError error
 
 type DNSConfigError struct {
-	Error os.Error
+	Err error
 }
 
-func (e *DNSConfigError) String() string {
-	return "error reading DNS config: " + e.Error.String()
+func (e *DNSConfigError) Error() string {
+	return "error reading DNS config: " + e.Err.Error()
 }
 
 func (e *DNSConfigError) Timeout() bool   { return false }
@@ -36,7 +34,7 @@ func (e *DNSConfigError) Temporary() bool { return false }
 // TODO(rsc): Supposed to call uname() and chop the beginning
 // of the host name to get the default search domain.
 // We assume it's in resolv.conf anyway.
-func dnsReadConfig() (*dnsConfig, os.Error) {
+func dnsReadConfig() (*dnsConfig, error) {
 	file, err := open("/etc/resolv.conf")
 	if err != nil {
 		return nil, &DNSConfigError{err}
diff --git a/src/pkg/net/doc.go b/src/pkg/net/doc.go
new file mode 100644
index 0000000..3a44e52
--- /dev/null
+++ b/src/pkg/net/doc.go
@@ -0,0 +1,59 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+// LookupHost looks up the given host using the local resolver.
+// It returns an array of that host's addresses.
+func LookupHost(host string) (addrs []string, err error) {
+	return lookupHost(host)
+}
+
+// LookupIP looks up host using the local resolver.
+// It returns an array of that host's IPv4 and IPv6 addresses.
+func LookupIP(host string) (addrs []IP, err error) {
+	return lookupIP(host)
+}
+
+// LookupPort looks up the port for the given network and service.
+func LookupPort(network, service string) (port int, err error) {
+	return lookupPort(network, service)
+}
+
+// LookupCNAME returns the canonical DNS host for the given name.
+// Callers that do not care about the canonical name can call
+// LookupHost or LookupIP directly; both take care of resolving
+// the canonical name as part of the lookup.
+func LookupCNAME(name string) (cname string, err error) {
+	return lookupCNAME(name)
+}
+
+// LookupSRV tries to resolve an SRV query of the given service,
+// protocol, and domain name.  The proto is "tcp" or "udp".
+// The returned records are sorted by priority and randomized
+// by weight within a priority.
+//
+// LookupSRV constructs the DNS name to look up following RFC 2782.
+// That is, it looks up _service._proto.name.  To accommodate services
+// publishing SRV records under non-standard names, if both service
+// and proto are empty strings, LookupSRV looks up name directly.
+func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	return lookupSRV(service, proto, name)
+}
+
+// LookupMX returns the DNS MX records for the given domain name sorted by preference.
+func LookupMX(name string) (mx []*MX, err error) {
+	return lookupMX(name)
+}
+
+// LookupTXT returns the DNS TXT records for the given domain name.
+func LookupTXT(name string) (txt []string, err error) {
+	return lookupTXT(name)
+}
+
+// LookupAddr performs a reverse lookup for the given address, returning a list
+// of names mapping to that address.
+func LookupAddr(addr string) (name []string, err error) {
+	return lookupAddr(addr)
+}
diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go
index 9084e88..495ef00 100644
--- a/src/pkg/net/fd.go
+++ b/src/pkg/net/fd.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package net
 
@@ -22,23 +22,22 @@ type netFD struct {
 	closing bool
 
 	// immutable until Close
-	sysfd   int
-	family  int
-	proto   int
-	sysfile *os.File
-	cr      chan bool
-	cw      chan bool
-	net     string
-	laddr   Addr
-	raddr   Addr
+	sysfd       int
+	family      int
+	sotype      int
+	isConnected bool
+	sysfile     *os.File
+	cr          chan bool
+	cw          chan bool
+	net         string
+	laddr       Addr
+	raddr       Addr
 
 	// owned by client
-	rdeadline_delta int64
-	rdeadline       int64
-	rio             sync.Mutex
-	wdeadline_delta int64
-	wdeadline       int64
-	wio             sync.Mutex
+	rdeadline int64
+	rio       sync.Mutex
+	wdeadline int64
+	wio       sync.Mutex
 
 	// owned by fd wait server
 	ncr, ncw int
@@ -46,7 +45,7 @@ type netFD struct {
 
 type InvalidConnError struct{}
 
-func (e *InvalidConnError) String() string  { return "invalid net.Conn" }
+func (e *InvalidConnError) Error() string   { return "invalid net.Conn" }
 func (e *InvalidConnError) Temporary() bool { return false }
 func (e *InvalidConnError) Timeout() bool   { return false }
 
@@ -126,7 +125,7 @@ func (s *pollServer) AddFD(fd *netFD, mode int) {
 
 	wake, err := s.poll.AddFD(intfd, mode, false)
 	if err != nil {
-		panic("pollServer AddFD " + err.String())
+		panic("pollServer AddFD " + err.Error())
 	}
 	if wake {
 		doWakeup = true
@@ -152,7 +151,7 @@ func (s *pollServer) LookupFD(fd int, mode int) *netFD {
 	if !ok {
 		return nil
 	}
-	s.pending[key] = nil, false
+	delete(s.pending, key)
 	return netfd
 }
 
@@ -171,7 +170,7 @@ func (s *pollServer) WakeFD(fd *netFD, mode int) {
 }
 
 func (s *pollServer) Now() int64 {
-	return time.Nanoseconds()
+	return time.Now().UnixNano()
 }
 
 func (s *pollServer) CheckDeadlines() {
@@ -195,7 +194,7 @@ func (s *pollServer) CheckDeadlines() {
 		}
 		if t > 0 {
 			if t <= now {
-				s.pending[key] = nil, false
+				delete(s.pending, key)
 				if mode == 'r' {
 					s.poll.DelFD(fd.sysfd, mode)
 					fd.rdeadline = -1
@@ -227,7 +226,7 @@ func (s *pollServer) Run() {
 		}
 		fd, mode, err := s.poll.WaitFD(s, t)
 		if err != nil {
-			print("pollServer WaitFD: ", err.String(), "\n")
+			print("pollServer WaitFD: ", err.Error(), "\n")
 			return
 		}
 		if fd < 0 {
@@ -271,20 +270,20 @@ var onceStartServer sync.Once
 func startServer() {
 	p, err := newPollServer()
 	if err != nil {
-		print("Start pollServer: ", err.String(), "\n")
+		print("Start pollServer: ", err.Error(), "\n")
 	}
 	pollserver = p
 }
 
-func newFD(fd, family, proto int, net string) (f *netFD, err os.Error) {
+func newFD(fd, family, sotype int, net string) (f *netFD, err error) {
 	onceStartServer.Do(startServer)
-	if e := syscall.SetNonblock(fd, true); e != 0 {
-		return nil, os.Errno(e)
+	if e := syscall.SetNonblock(fd, true); e != nil {
+		return nil, e
 	}
 	f = &netFD{
 		sysfd:  fd,
 		family: family,
-		proto:  proto,
+		sotype: sotype,
 		net:    net,
 	}
 	f.cr = make(chan bool, 1)
@@ -305,20 +304,20 @@ func (fd *netFD) setAddr(laddr, raddr Addr) {
 	fd.sysfile = os.NewFile(fd.sysfd, fd.net+":"+ls+"->"+rs)
 }
 
-func (fd *netFD) connect(ra syscall.Sockaddr) (err os.Error) {
-	e := syscall.Connect(fd.sysfd, ra)
-	if e == syscall.EINPROGRESS {
-		var errno int
+func (fd *netFD) connect(ra syscall.Sockaddr) (err error) {
+	err = syscall.Connect(fd.sysfd, ra)
+	if err == syscall.EINPROGRESS {
 		pollserver.WaitWrite(fd)
-		e, errno = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
-		if errno != 0 {
-			return os.NewSyscallError("getsockopt", errno)
+		var e int
+		e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
+		if err != nil {
+			return os.NewSyscallError("getsockopt", err)
+		}
+		if e != 0 {
+			err = syscall.Errno(e)
 		}
 	}
-	if e != 0 {
-		return os.Errno(e)
-	}
-	return nil
+	return err
 }
 
 // Add a reference to this fd.
@@ -346,7 +345,7 @@ func (fd *netFD) decref() {
 	fd.sysmu.Unlock()
 }
 
-func (fd *netFD) Close() os.Error {
+func (fd *netFD) Close() error {
 	if fd == nil || fd.sysfile == nil {
 		return os.EINVAL
 	}
@@ -358,7 +357,26 @@ func (fd *netFD) Close() os.Error {
 	return nil
 }
 
-func (fd *netFD) Read(p []byte) (n int, err os.Error) {
+func (fd *netFD) shutdown(how int) error {
+	if fd == nil || fd.sysfile == nil {
+		return os.EINVAL
+	}
+	err := syscall.Shutdown(fd.sysfd, how)
+	if err != nil {
+		return &OpError{"shutdown", fd.net, fd.laddr, err}
+	}
+	return nil
+}
+
+func (fd *netFD) CloseRead() error {
+	return fd.shutdown(syscall.SHUT_RD)
+}
+
+func (fd *netFD) CloseWrite() error {
+	return fd.shutdown(syscall.SHUT_WR)
+}
+
+func (fd *netFD) Read(p []byte) (n int, err error) {
 	if fd == nil {
 		return 0, os.EINVAL
 	}
@@ -369,34 +387,29 @@ func (fd *netFD) Read(p []byte) (n int, err os.Error) {
 	if fd.sysfile == nil {
 		return 0, os.EINVAL
 	}
-	if fd.rdeadline_delta > 0 {
-		fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
-	} else {
-		fd.rdeadline = 0
-	}
-	var oserr os.Error
 	for {
-		var errno int
-		n, errno = syscall.Read(fd.sysfile.Fd(), p)
-		if errno == syscall.EAGAIN && fd.rdeadline >= 0 {
-			pollserver.WaitRead(fd)
-			continue
+		n, err = syscall.Read(fd.sysfile.Fd(), p)
+		if err == syscall.EAGAIN {
+			if fd.rdeadline >= 0 {
+				pollserver.WaitRead(fd)
+				continue
+			}
+			err = errTimeout
 		}
-		if errno != 0 {
+		if err != nil {
 			n = 0
-			oserr = os.Errno(errno)
-		} else if n == 0 && errno == 0 && fd.proto != syscall.SOCK_DGRAM {
-			err = os.EOF
+		} else if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM {
+			err = io.EOF
 		}
 		break
 	}
-	if oserr != nil {
-		err = &OpError{"read", fd.net, fd.raddr, oserr}
+	if err != nil && err != io.EOF {
+		err = &OpError{"read", fd.net, fd.raddr, err}
 	}
 	return
 }
 
-func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) {
+func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
 	if fd == nil || fd.sysfile == nil {
 		return 0, nil, os.EINVAL
 	}
@@ -404,32 +417,27 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err os.Error) {
 	defer fd.rio.Unlock()
 	fd.incref()
 	defer fd.decref()
-	if fd.rdeadline_delta > 0 {
-		fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
-	} else {
-		fd.rdeadline = 0
-	}
-	var oserr os.Error
 	for {
-		var errno int
-		n, sa, errno = syscall.Recvfrom(fd.sysfd, p, 0)
-		if errno == syscall.EAGAIN && fd.rdeadline >= 0 {
-			pollserver.WaitRead(fd)
-			continue
+		n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
+		if err == syscall.EAGAIN {
+			if fd.rdeadline >= 0 {
+				pollserver.WaitRead(fd)
+				continue
+			}
+			err = errTimeout
 		}
-		if errno != 0 {
+		if err != nil {
 			n = 0
-			oserr = os.Errno(errno)
 		}
 		break
 	}
-	if oserr != nil {
-		err = &OpError{"read", fd.net, fd.laddr, oserr}
+	if err != nil {
+		err = &OpError{"read", fd.net, fd.laddr, err}
 	}
 	return
 }
 
-func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err os.Error) {
+func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
 	if fd == nil || fd.sysfile == nil {
 		return 0, 0, 0, nil, os.EINVAL
 	}
@@ -437,35 +445,28 @@ func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
 	defer fd.rio.Unlock()
 	fd.incref()
 	defer fd.decref()
-	if fd.rdeadline_delta > 0 {
-		fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
-	} else {
-		fd.rdeadline = 0
-	}
-	var oserr os.Error
 	for {
-		var errno int
-		n, oobn, flags, sa, errno = syscall.Recvmsg(fd.sysfd, p, oob, 0)
-		if errno == syscall.EAGAIN && fd.rdeadline >= 0 {
-			pollserver.WaitRead(fd)
-			continue
-		}
-		if errno != 0 {
-			oserr = os.Errno(errno)
+		n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
+		if err == syscall.EAGAIN {
+			if fd.rdeadline >= 0 {
+				pollserver.WaitRead(fd)
+				continue
+			}
+			err = errTimeout
 		}
-		if n == 0 {
-			oserr = os.EOF
+		if err == nil && n == 0 {
+			err = io.EOF
 		}
 		break
 	}
-	if oserr != nil {
-		err = &OpError{"read", fd.net, fd.laddr, oserr}
+	if err != nil && err != io.EOF {
+		err = &OpError{"read", fd.net, fd.laddr, err}
 		return
 	}
 	return
 }
 
-func (fd *netFD) Write(p []byte) (n int, err os.Error) {
+func (fd *netFD) Write(p []byte) (n int, err error) {
 	if fd == nil {
 		return 0, os.EINVAL
 	}
@@ -476,43 +477,40 @@ func (fd *netFD) Write(p []byte) (n int, err os.Error) {
 	if fd.sysfile == nil {
 		return 0, os.EINVAL
 	}
-	if fd.wdeadline_delta > 0 {
-		fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
-	} else {
-		fd.wdeadline = 0
-	}
 	nn := 0
-	var oserr os.Error
 
 	for {
-		n, errno := syscall.Write(fd.sysfile.Fd(), p[nn:])
+		var n int
+		n, err = syscall.Write(fd.sysfile.Fd(), p[nn:])
 		if n > 0 {
 			nn += n
 		}
 		if nn == len(p) {
 			break
 		}
-		if errno == syscall.EAGAIN && fd.wdeadline >= 0 {
-			pollserver.WaitWrite(fd)
-			continue
+		if err == syscall.EAGAIN {
+			if fd.wdeadline >= 0 {
+				pollserver.WaitWrite(fd)
+				continue
+			}
+			err = errTimeout
 		}
-		if errno != 0 {
+		if err != nil {
 			n = 0
-			oserr = os.Errno(errno)
 			break
 		}
 		if n == 0 {
-			oserr = io.ErrUnexpectedEOF
+			err = io.ErrUnexpectedEOF
 			break
 		}
 	}
-	if oserr != nil {
-		err = &OpError{"write", fd.net, fd.raddr, oserr}
+	if err != nil {
+		err = &OpError{"write", fd.net, fd.raddr, err}
 	}
 	return nn, err
 }
 
-func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err os.Error) {
+func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
 	if fd == nil || fd.sysfile == nil {
 		return 0, os.EINVAL
 	}
@@ -520,32 +518,26 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err os.Error) {
 	defer fd.wio.Unlock()
 	fd.incref()
 	defer fd.decref()
-	if fd.wdeadline_delta > 0 {
-		fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
-	} else {
-		fd.wdeadline = 0
-	}
-	var oserr os.Error
 	for {
-		errno := syscall.Sendto(fd.sysfd, p, 0, sa)
-		if errno == syscall.EAGAIN && fd.wdeadline >= 0 {
-			pollserver.WaitWrite(fd)
-			continue
-		}
-		if errno != 0 {
-			oserr = os.Errno(errno)
+		err = syscall.Sendto(fd.sysfd, p, 0, sa)
+		if err == syscall.EAGAIN {
+			if fd.wdeadline >= 0 {
+				pollserver.WaitWrite(fd)
+				continue
+			}
+			err = errTimeout
 		}
 		break
 	}
-	if oserr == nil {
+	if err == nil {
 		n = len(p)
 	} else {
-		err = &OpError{"write", fd.net, fd.raddr, oserr}
+		err = &OpError{"write", fd.net, fd.raddr, err}
 	}
 	return
 }
 
-func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err os.Error) {
+func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
 	if fd == nil || fd.sysfile == nil {
 		return 0, 0, os.EINVAL
 	}
@@ -553,73 +545,62 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
 	defer fd.wio.Unlock()
 	fd.incref()
 	defer fd.decref()
-	if fd.wdeadline_delta > 0 {
-		fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
-	} else {
-		fd.wdeadline = 0
-	}
-	var oserr os.Error
 	for {
-		var errno int
-		errno = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
-		if errno == syscall.EAGAIN && fd.wdeadline >= 0 {
-			pollserver.WaitWrite(fd)
-			continue
-		}
-		if errno != 0 {
-			oserr = os.Errno(errno)
+		err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
+		if err == syscall.EAGAIN {
+			if fd.wdeadline >= 0 {
+				pollserver.WaitWrite(fd)
+				continue
+			}
+			err = errTimeout
 		}
 		break
 	}
-	if oserr == nil {
+	if err == nil {
 		n = len(p)
 		oobn = len(oob)
 	} else {
-		err = &OpError{"write", fd.net, fd.raddr, oserr}
+		err = &OpError{"write", fd.net, fd.raddr, err}
 	}
 	return
 }
 
-func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
+func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err error) {
 	if fd == nil || fd.sysfile == nil {
 		return nil, os.EINVAL
 	}
 
 	fd.incref()
 	defer fd.decref()
-	if fd.rdeadline_delta > 0 {
-		fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
-	} else {
-		fd.rdeadline = 0
-	}
 
 	// See ../syscall/exec.go for description of ForkLock.
 	// It is okay to hold the lock across syscall.Accept
 	// because we have put fd.sysfd into non-blocking mode.
-	syscall.ForkLock.RLock()
-	var s, e int
+	var s int
 	var rsa syscall.Sockaddr
 	for {
 		if fd.closing {
-			syscall.ForkLock.RUnlock()
 			return nil, os.EINVAL
 		}
-		s, rsa, e = syscall.Accept(fd.sysfd)
-		if e != syscall.EAGAIN || fd.rdeadline < 0 {
-			break
-		}
-		syscall.ForkLock.RUnlock()
-		pollserver.WaitRead(fd)
 		syscall.ForkLock.RLock()
-	}
-	if e != 0 {
-		syscall.ForkLock.RUnlock()
-		return nil, &OpError{"accept", fd.net, fd.laddr, os.Errno(e)}
+		s, rsa, err = syscall.Accept(fd.sysfd)
+		if err != nil {
+			syscall.ForkLock.RUnlock()
+			if err == syscall.EAGAIN {
+				if fd.rdeadline >= 0 {
+					pollserver.WaitRead(fd)
+					continue
+				}
+				err = errTimeout
+			}
+			return nil, &OpError{"accept", fd.net, fd.laddr, err}
+		}
+		break
 	}
 	syscall.CloseOnExec(s)
 	syscall.ForkLock.RUnlock()
 
-	if nfd, err = newFD(s, fd.family, fd.proto, fd.net); err != nil {
+	if nfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
 		syscall.Close(s)
 		return nil, err
 	}
@@ -628,20 +609,20 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
 	return nfd, nil
 }
 
-func (fd *netFD) dup() (f *os.File, err os.Error) {
-	ns, e := syscall.Dup(fd.sysfd)
-	if e != 0 {
-		return nil, &OpError{"dup", fd.net, fd.laddr, os.Errno(e)}
+func (fd *netFD) dup() (f *os.File, err error) {
+	ns, err := syscall.Dup(fd.sysfd)
+	if err != nil {
+		return nil, &OpError{"dup", fd.net, fd.laddr, err}
 	}
 
 	// We want blocking mode for the new fd, hence the double negative.
-	if e = syscall.SetNonblock(ns, false); e != 0 {
-		return nil, &OpError{"setnonblock", fd.net, fd.laddr, os.Errno(e)}
+	if err = syscall.SetNonblock(ns, false); err != nil {
+		return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
 	}
 
 	return os.NewFile(ns, fd.sysfile.Name()), nil
 }
 
-func closesocket(s int) (errno int) {
+func closesocket(s int) error {
 	return syscall.Close(s)
 }
diff --git a/src/pkg/net/fd_darwin.go b/src/pkg/net/fd_darwin.go
index 7e3d549..c6db083 100644
--- a/src/pkg/net/fd_darwin.go
+++ b/src/pkg/net/fd_darwin.go
@@ -7,6 +7,7 @@
 package net
 
 import (
+	"errors"
 	"os"
 	"syscall"
 )
@@ -21,17 +22,17 @@ type pollster struct {
 	kbuf [1]syscall.Kevent_t
 }
 
-func newpollster() (p *pollster, err os.Error) {
+func newpollster() (p *pollster, err error) {
 	p = new(pollster)
-	var e int
-	if p.kq, e = syscall.Kqueue(); e != 0 {
-		return nil, os.NewSyscallError("kqueue", e)
+	if p.kq, err = syscall.Kqueue(); err != nil {
+		return nil, os.NewSyscallError("kqueue", err)
 	}
+	syscall.CloseOnExec(p.kq)
 	p.events = p.eventbuf[0:0]
 	return p, nil
 }
 
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
 	// pollServer is locked.
 
 	var kmode int
@@ -51,15 +52,15 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
 	}
 	syscall.SetKevent(ev, fd, kmode, flags)
 
-	n, e := syscall.Kevent(p.kq, p.kbuf[0:], p.kbuf[0:], nil)
-	if e != 0 {
-		return false, os.NewSyscallError("kevent", e)
+	n, err := syscall.Kevent(p.kq, p.kbuf[0:], p.kbuf[0:], nil)
+	if err != nil {
+		return false, os.NewSyscallError("kevent", err)
 	}
 	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
-		return false, os.NewError("kqueue phase error")
+		return false, errors.New("kqueue phase error")
 	}
 	if ev.Data != 0 {
-		return false, os.Errno(int(ev.Data))
+		return false, syscall.Errno(ev.Data)
 	}
 	return false, nil
 }
@@ -81,7 +82,7 @@ func (p *pollster) DelFD(fd int, mode int) {
 	syscall.Kevent(p.kq, p.kbuf[0:], p.kbuf[0:], nil)
 }
 
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
 	var t *syscall.Timespec
 	for len(p.events) == 0 {
 		if nsec > 0 {
@@ -95,11 +96,11 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
 		nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[0:], t)
 		s.Lock()
 
-		if e != 0 {
+		if e != nil {
 			if e == syscall.EINTR {
 				continue
 			}
-			return -1, 0, os.NewSyscallError("kevent", e)
+			return -1, 0, os.NewSyscallError("kevent", nil)
 		}
 		if nn == 0 {
 			return -1, 0, nil
@@ -117,4 +118,4 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
 	return fd, mode, nil
 }
 
-func (p *pollster) Close() os.Error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
+func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_freebsd.go b/src/pkg/net/fd_freebsd.go
index e50883e..31d0744 100644
--- a/src/pkg/net/fd_freebsd.go
+++ b/src/pkg/net/fd_freebsd.go
@@ -21,17 +21,17 @@ type pollster struct {
 	kbuf [1]syscall.Kevent_t
 }
 
-func newpollster() (p *pollster, err os.Error) {
+func newpollster() (p *pollster, err error) {
 	p = new(pollster)
-	var e int
-	if p.kq, e = syscall.Kqueue(); e != 0 {
-		return nil, os.NewSyscallError("kqueue", e)
+	if p.kq, err = syscall.Kqueue(); err != nil {
+		return nil, os.NewSyscallError("kqueue", err)
 	}
+	syscall.CloseOnExec(p.kq)
 	p.events = p.eventbuf[0:0]
 	return p, nil
 }
 
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
 	// pollServer is locked.
 
 	var kmode int
@@ -50,14 +50,14 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
 	syscall.SetKevent(ev, fd, kmode, flags)
 
 	n, e := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-	if e != 0 {
+	if e != nil {
 		return false, os.NewSyscallError("kevent", e)
 	}
 	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
 		return false, os.NewSyscallError("kqueue phase error", e)
 	}
 	if ev.Data != 0 {
-		return false, os.Errno(int(ev.Data))
+		return false, syscall.Errno(int(ev.Data))
 	}
 	return false, nil
 }
@@ -77,7 +77,7 @@ func (p *pollster) DelFD(fd int, mode int) {
 	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
 }
 
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
 	var t *syscall.Timespec
 	for len(p.events) == 0 {
 		if nsec > 0 {
@@ -91,7 +91,7 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
 		nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
 		s.Lock()
 
-		if e != 0 {
+		if e != nil {
 			if e == syscall.EINTR {
 				continue
 			}
@@ -113,4 +113,4 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
 	return fd, mode, nil
 }
 
-func (p *pollster) Close() os.Error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
+func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_linux.go b/src/pkg/net/fd_linux.go
index 70fc344..c8df9c9 100644
--- a/src/pkg/net/fd_linux.go
+++ b/src/pkg/net/fd_linux.go
@@ -33,21 +33,27 @@ type pollster struct {
 	ctlEvent syscall.EpollEvent
 }
 
-func newpollster() (p *pollster, err os.Error) {
+func newpollster() (p *pollster, err error) {
 	p = new(pollster)
-	var e int
+	var e error
 
-	// The arg to epoll_create is a hint to the kernel
-	// about the number of FDs we will care about.
-	// We don't know, and since 2.6.8 the kernel ignores it anyhow.
-	if p.epfd, e = syscall.EpollCreate(16); e != 0 {
-		return nil, os.NewSyscallError("epoll_create", e)
+	if p.epfd, e = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); e != nil {
+		if e != syscall.ENOSYS {
+			return nil, os.NewSyscallError("epoll_create1", e)
+		}
+		// The arg to epoll_create is a hint to the kernel
+		// about the number of FDs we will care about.
+		// We don't know, and since 2.6.8 the kernel ignores it anyhow.
+		if p.epfd, e = syscall.EpollCreate(16); e != nil {
+			return nil, os.NewSyscallError("epoll_create", e)
+		}
+		syscall.CloseOnExec(p.epfd)
 	}
 	p.events = make(map[int]uint32)
 	return p, nil
 }
 
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
 	// pollServer is locked.
 
 	var already bool
@@ -68,7 +74,7 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
 	} else {
 		op = syscall.EPOLL_CTL_ADD
 	}
-	if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != 0 {
+	if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != nil {
 		return false, os.NewSyscallError("epoll_ctl", e)
 	}
 	p.events[fd] = p.ctlEvent.Events
@@ -97,15 +103,15 @@ func (p *pollster) StopWaiting(fd int, bits uint) {
 	if int32(events)&^syscall.EPOLLONESHOT != 0 {
 		p.ctlEvent.Fd = int32(fd)
 		p.ctlEvent.Events = events
-		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); e != 0 {
-			print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n")
+		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); e != nil {
+			print("Epoll modify fd=", fd, ": ", e.Error(), "\n")
 		}
 		p.events[fd] = events
 	} else {
-		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
-			print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n")
+		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != nil {
+			print("Epoll delete fd=", fd, ": ", e.Error(), "\n")
 		}
-		p.events[fd] = 0, false
+		delete(p.events, fd)
 	}
 }
 
@@ -130,7 +136,7 @@ func (p *pollster) DelFD(fd int, mode int) {
 	}
 }
 
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
 	for len(p.waitEvents) == 0 {
 		var msec int = -1
 		if nsec > 0 {
@@ -141,7 +147,7 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
 		n, e := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
 		s.Lock()
 
-		if e != 0 {
+		if e != nil {
 			if e == syscall.EAGAIN || e == syscall.EINTR {
 				continue
 			}
@@ -177,6 +183,6 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
 	return fd, 'r', nil
 }
 
-func (p *pollster) Close() os.Error {
+func (p *pollster) Close() error {
 	return os.NewSyscallError("close", syscall.Close(p.epfd))
 }
diff --git a/src/pkg/net/fd_netbsd.go b/src/pkg/net/fd_netbsd.go
new file mode 100644
index 0000000..31d0744
--- /dev/null
+++ b/src/pkg/net/fd_netbsd.go
@@ -0,0 +1,116 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Waiting for FDs via kqueue/kevent.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+type pollster struct {
+	kq       int
+	eventbuf [10]syscall.Kevent_t
+	events   []syscall.Kevent_t
+
+	// An event buffer for AddFD/DelFD.
+	// Must hold pollServer lock.
+	kbuf [1]syscall.Kevent_t
+}
+
+func newpollster() (p *pollster, err error) {
+	p = new(pollster)
+	if p.kq, err = syscall.Kqueue(); err != nil {
+		return nil, os.NewSyscallError("kqueue", err)
+	}
+	syscall.CloseOnExec(p.kq)
+	p.events = p.eventbuf[0:0]
+	return p, nil
+}
+
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
+	// pollServer is locked.
+
+	var kmode int
+	if mode == 'r' {
+		kmode = syscall.EVFILT_READ
+	} else {
+		kmode = syscall.EVFILT_WRITE
+	}
+	ev := &p.kbuf[0]
+	// EV_ADD - add event to kqueue list
+	// EV_ONESHOT - delete the event the first time it triggers
+	flags := syscall.EV_ADD
+	if !repeat {
+		flags |= syscall.EV_ONESHOT
+	}
+	syscall.SetKevent(ev, fd, kmode, flags)
+
+	n, e := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
+	if e != nil {
+		return false, os.NewSyscallError("kevent", e)
+	}
+	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
+		return false, os.NewSyscallError("kqueue phase error", e)
+	}
+	if ev.Data != 0 {
+		return false, syscall.Errno(int(ev.Data))
+	}
+	return false, nil
+}
+
+func (p *pollster) DelFD(fd int, mode int) {
+	// pollServer is locked.
+
+	var kmode int
+	if mode == 'r' {
+		kmode = syscall.EVFILT_READ
+	} else {
+		kmode = syscall.EVFILT_WRITE
+	}
+	ev := &p.kbuf[0]
+	// EV_DELETE - delete event from kqueue list
+	syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
+	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
+}
+
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
+	var t *syscall.Timespec
+	for len(p.events) == 0 {
+		if nsec > 0 {
+			if t == nil {
+				t = new(syscall.Timespec)
+			}
+			*t = syscall.NsecToTimespec(nsec)
+		}
+
+		s.Unlock()
+		nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
+		s.Lock()
+
+		if e != nil {
+			if e == syscall.EINTR {
+				continue
+			}
+			return -1, 0, os.NewSyscallError("kevent", e)
+		}
+		if nn == 0 {
+			return -1, 0, nil
+		}
+		p.events = p.eventbuf[0:nn]
+	}
+	ev := &p.events[0]
+	p.events = p.events[1:]
+	fd = int(ev.Ident)
+	if ev.Filter == syscall.EVFILT_READ {
+		mode = 'r'
+	} else {
+		mode = 'w'
+	}
+	return fd, mode, nil
+}
+
+func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_openbsd.go b/src/pkg/net/fd_openbsd.go
index e50883e..31d0744 100644
--- a/src/pkg/net/fd_openbsd.go
+++ b/src/pkg/net/fd_openbsd.go
@@ -21,17 +21,17 @@ type pollster struct {
 	kbuf [1]syscall.Kevent_t
 }
 
-func newpollster() (p *pollster, err os.Error) {
+func newpollster() (p *pollster, err error) {
 	p = new(pollster)
-	var e int
-	if p.kq, e = syscall.Kqueue(); e != 0 {
-		return nil, os.NewSyscallError("kqueue", e)
+	if p.kq, err = syscall.Kqueue(); err != nil {
+		return nil, os.NewSyscallError("kqueue", err)
 	}
+	syscall.CloseOnExec(p.kq)
 	p.events = p.eventbuf[0:0]
 	return p, nil
 }
 
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
+func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
 	// pollServer is locked.
 
 	var kmode int
@@ -50,14 +50,14 @@ func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, os.Error) {
 	syscall.SetKevent(ev, fd, kmode, flags)
 
 	n, e := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
-	if e != 0 {
+	if e != nil {
 		return false, os.NewSyscallError("kevent", e)
 	}
 	if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
 		return false, os.NewSyscallError("kqueue phase error", e)
 	}
 	if ev.Data != 0 {
-		return false, os.Errno(int(ev.Data))
+		return false, syscall.Errno(int(ev.Data))
 	}
 	return false, nil
 }
@@ -77,7 +77,7 @@ func (p *pollster) DelFD(fd int, mode int) {
 	syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
 }
 
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) {
+func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
 	var t *syscall.Timespec
 	for len(p.events) == 0 {
 		if nsec > 0 {
@@ -91,7 +91,7 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
 		nn, e := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
 		s.Lock()
 
-		if e != 0 {
+		if e != nil {
 			if e == syscall.EINTR {
 				continue
 			}
@@ -113,4 +113,4 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
 	return fd, mode, nil
 }
 
-func (p *pollster) Close() os.Error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
+func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index b025bdd..f00459f 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -5,6 +5,7 @@
 package net
 
 import (
+	"io"
 	"os"
 	"runtime"
 	"sync"
@@ -15,21 +16,21 @@ import (
 
 type InvalidConnError struct{}
 
-func (e *InvalidConnError) String() string  { return "invalid net.Conn" }
+func (e *InvalidConnError) Error() string   { return "invalid net.Conn" }
 func (e *InvalidConnError) Temporary() bool { return false }
 func (e *InvalidConnError) Timeout() bool   { return false }
 
-var initErr os.Error
+var initErr error
 
 func init() {
 	var d syscall.WSAData
 	e := syscall.WSAStartup(uint32(0x202), &d)
-	if e != 0 {
+	if e != nil {
 		initErr = os.NewSyscallError("WSAStartup", e)
 	}
 }
 
-func closesocket(s syscall.Handle) (errno int) {
+func closesocket(s syscall.Handle) (err error) {
 	return syscall.Closesocket(s)
 }
 
@@ -37,13 +38,13 @@ func closesocket(s syscall.Handle) (errno int) {
 type anOpIface interface {
 	Op() *anOp
 	Name() string
-	Submit() (errno int)
+	Submit() (err error)
 }
 
 // IO completion result parameters.
 type ioResult struct {
 	qty uint32
-	err int
+	err error
 }
 
 // anOp implements functionality common to all io operations.
@@ -53,7 +54,7 @@ type anOp struct {
 	o syscall.Overlapped
 
 	resultc chan ioResult
-	errnoc  chan int
+	errnoc  chan error
 	fd      *netFD
 }
 
@@ -70,7 +71,7 @@ func (o *anOp) Init(fd *netFD, mode int) {
 	}
 	o.resultc = fd.resultc[i]
 	if fd.errnoc[i] == nil {
-		fd.errnoc[i] = make(chan int)
+		fd.errnoc[i] = make(chan error)
 	}
 	o.errnoc = fd.errnoc[i]
 }
@@ -110,14 +111,14 @@ func (s *resultSrv) Run() {
 	for {
 		r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE)
 		switch {
-		case r.err == 0:
+		case r.err == nil:
 			// Dequeued successfully completed io packet.
-		case r.err == syscall.WAIT_TIMEOUT && o == nil:
+		case r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil:
 			// Wait has timed out (should not happen now, but might be used in the future).
 			panic("GetQueuedCompletionStatus timed out")
 		case o == nil:
 			// Failed to dequeue anything -> report the error.
-			panic("GetQueuedCompletionStatus failed " + syscall.Errstr(r.err))
+			panic("GetQueuedCompletionStatus failed " + r.err.Error())
 		default:
 			// Dequeued failed io packet.
 		}
@@ -149,12 +150,13 @@ func (s *ioSrv) ProcessRemoteIO() {
 }
 
 // ExecIO executes a single io operation. It either executes it
-// inline, or, if timeouts are employed, passes the request onto
+// inline, or, if a deadline is employed, passes the request onto
 // a special goroutine and waits for completion or cancels request.
-func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err os.Error) {
-	var e int
+// deadline is unix nanos.
+func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (n int, err error) {
+	var e error
 	o := oi.Op()
-	if deadline_delta > 0 {
+	if deadline != 0 {
 		// Send request to a special dedicated thread,
 		// so it can stop the io with CancelIO later.
 		s.submchan <- oi
@@ -163,19 +165,25 @@ func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err os.Error)
 		e = oi.Submit()
 	}
 	switch e {
-	case 0:
+	case nil:
 		// IO completed immediately, but we need to get our completion message anyway.
 	case syscall.ERROR_IO_PENDING:
 		// IO started, and we have to wait for its completion.
 	default:
-		return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, os.Errno(e)}
+		return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, e}
 	}
 	// Wait for our request to complete.
 	var r ioResult
-	if deadline_delta > 0 {
+	if deadline != 0 {
+		dt := deadline - time.Now().UnixNano()
+		if dt < 1 {
+			dt = 1
+		}
+		timer := time.NewTimer(time.Duration(dt) * time.Nanosecond)
+		defer timer.Stop()
 		select {
 		case r = <-o.resultc:
-		case <-time.After(deadline_delta):
+		case <-timer.C:
 			s.canchan <- oi
 			<-o.errnoc
 			r = <-o.resultc
@@ -186,8 +194,8 @@ func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err os.Error)
 	} else {
 		r = <-o.resultc
 	}
-	if r.err != 0 {
-		err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, os.Errno(r.err)}
+	if r.err != nil {
+		err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, r.err}
 	}
 	return int(r.qty), err
 }
@@ -199,10 +207,10 @@ var onceStartServer sync.Once
 
 func startServer() {
 	resultsrv = new(resultSrv)
-	var errno int
-	resultsrv.iocp, errno = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1)
-	if errno != 0 {
-		panic("CreateIoCompletionPort failed " + syscall.Errstr(errno))
+	var err error
+	resultsrv.iocp, err = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1)
+	if err != nil {
+		panic("CreateIoCompletionPort: " + err.Error())
 	}
 	go resultsrv.Run()
 
@@ -220,43 +228,42 @@ type netFD struct {
 	closing bool
 
 	// immutable until Close
-	sysfd   syscall.Handle
-	family  int
-	proto   int
-	net     string
-	laddr   Addr
-	raddr   Addr
-	resultc [2]chan ioResult // read/write completion results
-	errnoc  [2]chan int      // read/write submit or cancel operation errors
+	sysfd       syscall.Handle
+	family      int
+	sotype      int
+	isConnected bool
+	net         string
+	laddr       Addr
+	raddr       Addr
+	resultc     [2]chan ioResult // read/write completion results
+	errnoc      [2]chan error    // read/write submit or cancel operation errors
 
 	// owned by client
-	rdeadline_delta int64
-	rdeadline       int64
-	rio             sync.Mutex
-	wdeadline_delta int64
-	wdeadline       int64
-	wio             sync.Mutex
+	rdeadline int64
+	rio       sync.Mutex
+	wdeadline int64
+	wio       sync.Mutex
 }
 
-func allocFD(fd syscall.Handle, family, proto int, net string) (f *netFD) {
+func allocFD(fd syscall.Handle, family, sotype int, net string) (f *netFD) {
 	f = &netFD{
 		sysfd:  fd,
 		family: family,
-		proto:  proto,
+		sotype: sotype,
 		net:    net,
 	}
 	runtime.SetFinalizer(f, (*netFD).Close)
 	return f
 }
 
-func newFD(fd syscall.Handle, family, proto int, net string) (f *netFD, err os.Error) {
+func newFD(fd syscall.Handle, family, proto int, net string) (f *netFD, err error) {
 	if initErr != nil {
 		return nil, initErr
 	}
 	onceStartServer.Do(startServer)
 	// Associate our socket with resultsrv.iocp.
-	if _, e := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); e != 0 {
-		return nil, os.Errno(e)
+	if _, e := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); e != nil {
+		return nil, e
 	}
 	return allocFD(fd, family, proto, net), nil
 }
@@ -266,12 +273,8 @@ func (fd *netFD) setAddr(laddr, raddr Addr) {
 	fd.raddr = raddr
 }
 
-func (fd *netFD) connect(ra syscall.Sockaddr) (err os.Error) {
-	e := syscall.Connect(fd.sysfd, ra)
-	if e != 0 {
-		return os.Errno(e)
-	}
-	return nil
+func (fd *netFD) connect(ra syscall.Sockaddr) (err error) {
+	return syscall.Connect(fd.sysfd, ra)
 }
 
 // Add a reference to this fd.
@@ -300,7 +303,7 @@ func (fd *netFD) decref() {
 	fd.sysmu.Unlock()
 }
 
-func (fd *netFD) Close() os.Error {
+func (fd *netFD) Close() error {
 	if fd == nil || fd.sysfd == syscall.InvalidHandle {
 		return os.EINVAL
 	}
@@ -312,13 +315,32 @@ func (fd *netFD) Close() os.Error {
 	return nil
 }
 
+func (fd *netFD) shutdown(how int) error {
+	if fd == nil || fd.sysfd == syscall.InvalidHandle {
+		return os.EINVAL
+	}
+	err := syscall.Shutdown(fd.sysfd, how)
+	if err != nil {
+		return &OpError{"shutdown", fd.net, fd.laddr, err}
+	}
+	return nil
+}
+
+func (fd *netFD) CloseRead() error {
+	return fd.shutdown(syscall.SHUT_RD)
+}
+
+func (fd *netFD) CloseWrite() error {
+	return fd.shutdown(syscall.SHUT_WR)
+}
+
 // Read from network.
 
 type readOp struct {
 	bufOp
 }
 
-func (o *readOp) Submit() (errno int) {
+func (o *readOp) Submit() (err error) {
 	var d, f uint32
 	return syscall.WSARecv(syscall.Handle(o.fd.sysfd), &o.buf, 1, &d, &f, &o.o, nil)
 }
@@ -327,7 +349,7 @@ func (o *readOp) Name() string {
 	return "WSARecv"
 }
 
-func (fd *netFD) Read(buf []byte) (n int, err os.Error) {
+func (fd *netFD) Read(buf []byte) (n int, err error) {
 	if fd == nil {
 		return 0, os.EINVAL
 	}
@@ -340,9 +362,9 @@ func (fd *netFD) Read(buf []byte) (n int, err os.Error) {
 	}
 	var o readOp
 	o.Init(fd, buf, 'r')
-	n, err = iosrv.ExecIO(&o, fd.rdeadline_delta)
+	n, err = iosrv.ExecIO(&o, fd.rdeadline)
 	if err == nil && n == 0 {
-		err = os.EOF
+		err = io.EOF
 	}
 	return
 }
@@ -355,7 +377,7 @@ type readFromOp struct {
 	rsan int32
 }
 
-func (o *readFromOp) Submit() (errno int) {
+func (o *readFromOp) Submit() (err error) {
 	var d, f uint32
 	return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &d, &f, &o.rsa, &o.rsan, &o.o, nil)
 }
@@ -364,7 +386,7 @@ func (o *readFromOp) Name() string {
 	return "WSARecvFrom"
 }
 
-func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err os.Error) {
+func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
 	if fd == nil {
 		return 0, nil, os.EINVAL
 	}
@@ -381,7 +403,7 @@ func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err os.Error)
 	var o readFromOp
 	o.Init(fd, buf, 'r')
 	o.rsan = int32(unsafe.Sizeof(o.rsa))
-	n, err = iosrv.ExecIO(&o, fd.rdeadline_delta)
+	n, err = iosrv.ExecIO(&o, fd.rdeadline)
 	if err != nil {
 		return 0, nil, err
 	}
@@ -395,7 +417,7 @@ type writeOp struct {
 	bufOp
 }
 
-func (o *writeOp) Submit() (errno int) {
+func (o *writeOp) Submit() (err error) {
 	var d uint32
 	return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &d, 0, &o.o, nil)
 }
@@ -404,7 +426,7 @@ func (o *writeOp) Name() string {
 	return "WSASend"
 }
 
-func (fd *netFD) Write(buf []byte) (n int, err os.Error) {
+func (fd *netFD) Write(buf []byte) (n int, err error) {
 	if fd == nil {
 		return 0, os.EINVAL
 	}
@@ -417,7 +439,7 @@ func (fd *netFD) Write(buf []byte) (n int, err os.Error) {
 	}
 	var o writeOp
 	o.Init(fd, buf, 'w')
-	return iosrv.ExecIO(&o, fd.wdeadline_delta)
+	return iosrv.ExecIO(&o, fd.wdeadline)
 }
 
 // WriteTo to network.
@@ -427,7 +449,7 @@ type writeToOp struct {
 	sa syscall.Sockaddr
 }
 
-func (o *writeToOp) Submit() (errno int) {
+func (o *writeToOp) Submit() (err error) {
 	var d uint32
 	return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &d, 0, o.sa, &o.o, nil)
 }
@@ -436,7 +458,7 @@ func (o *writeToOp) Name() string {
 	return "WSASendto"
 }
 
-func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err os.Error) {
+func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err error) {
 	if fd == nil {
 		return 0, os.EINVAL
 	}
@@ -453,7 +475,7 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err os.Error)
 	var o writeToOp
 	o.Init(fd, buf, 'w')
 	o.sa = sa
-	return iosrv.ExecIO(&o, fd.wdeadline_delta)
+	return iosrv.ExecIO(&o, fd.wdeadline)
 }
 
 // Accept new network connections.
@@ -464,7 +486,7 @@ type acceptOp struct {
 	attrs   [2]syscall.RawSockaddrAny // space for local and remote address only
 }
 
-func (o *acceptOp) Submit() (errno int) {
+func (o *acceptOp) Submit() (err error) {
 	var d uint32
 	l := uint32(unsafe.Sizeof(o.attrs[0]))
 	return syscall.AcceptEx(o.fd.sysfd, o.newsock,
@@ -475,7 +497,7 @@ func (o *acceptOp) Name() string {
 	return "AcceptEx"
 }
 
-func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
+func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err error) {
 	if fd == nil || fd.sysfd == syscall.InvalidHandle {
 		return nil, os.EINVAL
 	}
@@ -485,18 +507,18 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
 	// Get new socket.
 	// See ../syscall/exec.go for description of ForkLock.
 	syscall.ForkLock.RLock()
-	s, e := syscall.Socket(fd.family, fd.proto, 0)
-	if e != 0 {
+	s, e := syscall.Socket(fd.family, fd.sotype, 0)
+	if e != nil {
 		syscall.ForkLock.RUnlock()
-		return nil, os.Errno(e)
+		return nil, e
 	}
 	syscall.CloseOnExec(s)
 	syscall.ForkLock.RUnlock()
 
 	// Associate our new socket with IOCP.
 	onceStartServer.Do(startServer)
-	if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != 0 {
-		return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)}
+	if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != nil {
+		return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, e}
 	}
 
 	// Submit accept request.
@@ -511,9 +533,9 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
 
 	// Inherit properties of the listening socket.
 	e = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
-	if e != 0 {
+	if e != nil {
 		closesocket(s)
-		return nil, err
+		return nil, e
 	}
 
 	// Get local and peer addr out of AcceptEx buffer.
@@ -525,22 +547,22 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
 	lsa, _ := lrsa.Sockaddr()
 	rsa, _ := rrsa.Sockaddr()
 
-	nfd = allocFD(s, fd.family, fd.proto, fd.net)
+	nfd = allocFD(s, fd.family, fd.sotype, fd.net)
 	nfd.setAddr(toAddr(lsa), toAddr(rsa))
 	return nfd, nil
 }
 
 // Unimplemented functions.
 
-func (fd *netFD) dup() (f *os.File, err os.Error) {
+func (fd *netFD) dup() (f *os.File, err error) {
 	// TODO: Implement this
 	return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
 }
 
-func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err os.Error) {
+func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
 	return 0, 0, 0, nil, os.EAFNOSUPPORT
 }
 
-func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err os.Error) {
+func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
 	return 0, 0, os.EAFNOSUPPORT
 }
diff --git a/src/pkg/net/file.go b/src/pkg/net/file.go
index d8528e4..4ac280b 100644
--- a/src/pkg/net/file.go
+++ b/src/pkg/net/file.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package net
 
@@ -11,17 +11,18 @@ import (
 	"syscall"
 )
 
-func newFileFD(f *os.File) (nfd *netFD, err os.Error) {
+func newFileFD(f *os.File) (nfd *netFD, err error) {
 	fd, errno := syscall.Dup(f.Fd())
-	if errno != 0 {
+	if errno != nil {
 		return nil, os.NewSyscallError("dup", errno)
 	}
 
 	proto, errno := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
-	if errno != 0 {
+	if errno != nil {
 		return nil, os.NewSyscallError("getsockopt", errno)
 	}
 
+	family := syscall.AF_UNSPEC
 	toAddr := sockaddrToTCP
 	sa, _ := syscall.Getsockname(fd)
 	switch sa.(type) {
@@ -29,18 +30,21 @@ func newFileFD(f *os.File) (nfd *netFD, err os.Error) {
 		closesocket(fd)
 		return nil, os.EINVAL
 	case *syscall.SockaddrInet4:
+		family = syscall.AF_INET
 		if proto == syscall.SOCK_DGRAM {
 			toAddr = sockaddrToUDP
 		} else if proto == syscall.SOCK_RAW {
 			toAddr = sockaddrToIP
 		}
 	case *syscall.SockaddrInet6:
+		family = syscall.AF_INET6
 		if proto == syscall.SOCK_DGRAM {
 			toAddr = sockaddrToUDP
 		} else if proto == syscall.SOCK_RAW {
 			toAddr = sockaddrToIP
 		}
 	case *syscall.SockaddrUnix:
+		family = syscall.AF_UNIX
 		toAddr = sockaddrToUnix
 		if proto == syscall.SOCK_DGRAM {
 			toAddr = sockaddrToUnixgram
@@ -52,7 +56,7 @@ func newFileFD(f *os.File) (nfd *netFD, err os.Error) {
 	sa, _ = syscall.Getpeername(fd)
 	raddr := toAddr(sa)
 
-	if nfd, err = newFD(fd, 0, proto, laddr.Network()); err != nil {
+	if nfd, err = newFD(fd, family, proto, laddr.Network()); err != nil {
 		return nil, err
 	}
 	nfd.setAddr(laddr, raddr)
@@ -63,7 +67,7 @@ func newFileFD(f *os.File) (nfd *netFD, err os.Error) {
 // the open file f.  It is the caller's responsibility to close f when
 // finished.  Closing c does not affect f, and closing f does not
 // affect c.
-func FileConn(f *os.File) (c Conn, err os.Error) {
+func FileConn(f *os.File) (c Conn, err error) {
 	fd, err := newFileFD(f)
 	if err != nil {
 		return nil, err
@@ -86,7 +90,7 @@ func FileConn(f *os.File) (c Conn, err os.Error) {
 // to the open file f.  It is the caller's responsibility to close l
 // when finished.  Closing c does not affect l, and closing l does not
 // affect c.
-func FileListener(f *os.File) (l Listener, err os.Error) {
+func FileListener(f *os.File) (l Listener, err error) {
 	fd, err := newFileFD(f)
 	if err != nil {
 		return nil, err
@@ -105,7 +109,7 @@ func FileListener(f *os.File) (l Listener, err os.Error) {
 // corresponding to the open file f.  It is the caller's
 // responsibility to close f when finished.  Closing c does not affect
 // f, and closing f does not affect c.
-func FilePacketConn(f *os.File) (c PacketConn, err os.Error) {
+func FilePacketConn(f *os.File) (c PacketConn, err error) {
 	fd, err := newFileFD(f)
 	if err != nil {
 		return nil, err
diff --git a/src/pkg/net/file_plan9.go b/src/pkg/net/file_plan9.go
index a07e743..06d7cc8 100644
--- a/src/pkg/net/file_plan9.go
+++ b/src/pkg/net/file_plan9.go
@@ -12,7 +12,7 @@ import (
 // the open file f.  It is the caller's responsibility to close f when
 // finished.  Closing c does not affect f, and closing f does not
 // affect c.
-func FileConn(f *os.File) (c Conn, err os.Error) {
+func FileConn(f *os.File) (c Conn, err error) {
 	return nil, os.EPLAN9
 }
 
@@ -20,7 +20,7 @@ func FileConn(f *os.File) (c Conn, err os.Error) {
 // to the open file f.  It is the caller's responsibility to close l
 // when finished.  Closing c does not affect l, and closing l does not
 // affect c.
-func FileListener(f *os.File) (l Listener, err os.Error) {
+func FileListener(f *os.File) (l Listener, err error) {
 	return nil, os.EPLAN9
 }
 
@@ -28,6 +28,6 @@ func FileListener(f *os.File) (l Listener, err os.Error) {
 // corresponding to the open file f.  It is the caller's
 // responsibility to close f when finished.  Closing c does not affect
 // f, and closing f does not affect c.
-func FilePacketConn(f *os.File) (c PacketConn, err os.Error) {
+func FilePacketConn(f *os.File) (c PacketConn, err error) {
 	return nil, os.EPLAN9
 }
diff --git a/src/pkg/net/file_test.go b/src/pkg/net/file_test.go
index 9a8c2dc..868388e 100644
--- a/src/pkg/net/file_test.go
+++ b/src/pkg/net/file_test.go
@@ -8,23 +8,22 @@ import (
 	"os"
 	"reflect"
 	"runtime"
-	"syscall"
 	"testing"
 )
 
 type listenerFile interface {
 	Listener
-	File() (f *os.File, err os.Error)
+	File() (f *os.File, err error)
 }
 
 type packetConnFile interface {
 	PacketConn
-	File() (f *os.File, err os.Error)
+	File() (f *os.File, err error)
 }
 
 type connFile interface {
 	Conn
-	File() (f *os.File, err os.Error)
+	File() (f *os.File, err error)
 }
 
 func testFileListener(t *testing.T, net, laddr string) {
@@ -67,13 +66,13 @@ func TestFileListener(t *testing.T) {
 		testFileListener(t, "tcp", "127.0.0.1")
 		testFileListener(t, "tcp", "[::ffff:127.0.0.1]")
 	}
-	if syscall.OS == "linux" {
+	if runtime.GOOS == "linux" {
 		testFileListener(t, "unix", "@gotest/net")
 		testFileListener(t, "unixpacket", "@gotest/net")
 	}
 }
 
-func testFilePacketConn(t *testing.T, pcf packetConnFile) {
+func testFilePacketConn(t *testing.T, pcf packetConnFile, listen bool) {
 	f, err := pcf.File()
 	if err != nil {
 		t.Fatalf("File failed: %v", err)
@@ -85,6 +84,11 @@ func testFilePacketConn(t *testing.T, pcf packetConnFile) {
 	if !reflect.DeepEqual(pcf.LocalAddr(), c.LocalAddr()) {
 		t.Fatalf("LocalAddrs not equal: %#v != %#v", pcf.LocalAddr(), c.LocalAddr())
 	}
+	if listen {
+		if _, err := c.WriteTo([]byte{}, c.LocalAddr()); err != nil {
+			t.Fatalf("WriteTo failed: %v", err)
+		}
+	}
 	if err := c.Close(); err != nil {
 		t.Fatalf("Close failed: %v", err)
 	}
@@ -98,7 +102,7 @@ func testFilePacketConnListen(t *testing.T, net, laddr string) {
 	if err != nil {
 		t.Fatalf("Listen failed: %v", err)
 	}
-	testFilePacketConn(t, l.(packetConnFile))
+	testFilePacketConn(t, l.(packetConnFile), true)
 	if err := l.Close(); err != nil {
 		t.Fatalf("Close failed: %v", err)
 	}
@@ -109,7 +113,7 @@ func testFilePacketConnDial(t *testing.T, net, raddr string) {
 	if err != nil {
 		t.Fatalf("Dial failed: %v", err)
 	}
-	testFilePacketConn(t, c.(packetConnFile))
+	testFilePacketConn(t, c.(packetConnFile), false)
 	if err := c.Close(); err != nil {
 		t.Fatalf("Close failed: %v", err)
 	}
@@ -127,7 +131,7 @@ func TestFilePacketConn(t *testing.T) {
 	if supportsIPv6 && supportsIPv4map {
 		testFilePacketConnDial(t, "udp", "[::ffff:127.0.0.1]:12345")
 	}
-	if syscall.OS == "linux" {
+	if runtime.GOOS == "linux" {
 		testFilePacketConnListen(t, "unixgram", "@gotest1/net")
 	}
 }
diff --git a/src/pkg/net/file_windows.go b/src/pkg/net/file_windows.go
index 94aa583..c50c32e 100644
--- a/src/pkg/net/file_windows.go
+++ b/src/pkg/net/file_windows.go
@@ -9,17 +9,17 @@ import (
 	"syscall"
 )
 
-func FileConn(f *os.File) (c Conn, err os.Error) {
+func FileConn(f *os.File) (c Conn, err error) {
 	// TODO: Implement this
 	return nil, os.NewSyscallError("FileConn", syscall.EWINDOWS)
 }
 
-func FileListener(f *os.File) (l Listener, err os.Error) {
+func FileListener(f *os.File) (l Listener, err error) {
 	// TODO: Implement this
 	return nil, os.NewSyscallError("FileListener", syscall.EWINDOWS)
 }
 
-func FilePacketConn(f *os.File) (c PacketConn, err os.Error) {
+func FilePacketConn(f *os.File) (c PacketConn, err error) {
 	// TODO: Implement this
 	return nil, os.NewSyscallError("FilePacketConn", syscall.EWINDOWS)
 }
diff --git a/src/pkg/net/hosts.go b/src/pkg/net/hosts.go
index d75e9e0..e6674ba 100644
--- a/src/pkg/net/hosts.go
+++ b/src/pkg/net/hosts.go
@@ -7,11 +7,11 @@
 package net
 
 import (
-	"os"
 	"sync"
+	"time"
 )
 
-const cacheMaxAge = int64(300) // 5 minutes.
+const cacheMaxAge = 5 * time.Minute
 
 // hostsPath points to the file with static IP/address entries.
 var hostsPath = "/etc/hosts"
@@ -21,14 +21,14 @@ var hosts struct {
 	sync.Mutex
 	byName map[string][]string
 	byAddr map[string][]string
-	time   int64
+	expire time.Time
 	path   string
 }
 
 func readHosts() {
-	now, _, _ := os.Time()
+	now := time.Now()
 	hp := hostsPath
-	if len(hosts.byName) == 0 || hosts.time+cacheMaxAge <= now || hosts.path != hp {
+	if len(hosts.byName) == 0 || now.After(hosts.expire) || hosts.path != hp {
 		hs := make(map[string][]string)
 		is := make(map[string][]string)
 		var file *file
@@ -51,7 +51,7 @@ func readHosts() {
 			}
 		}
 		// Update the data cache.
-		hosts.time, _, _ = os.Time()
+		hosts.expire = time.Now().Add(cacheMaxAge)
 		hosts.path = hp
 		hosts.byName = hs
 		hosts.byAddr = is
diff --git a/src/pkg/net/http/Makefile b/src/pkg/net/http/Makefile
new file mode 100644
index 0000000..5c351b0
--- /dev/null
+++ b/src/pkg/net/http/Makefile
@@ -0,0 +1,25 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=net/http
+GOFILES=\
+	chunked.go\
+	client.go\
+	cookie.go\
+	filetransport.go\
+	fs.go\
+	header.go\
+	jar.go\
+	lex.go\
+	request.go\
+	response.go\
+	server.go\
+	sniff.go\
+	status.go\
+	transfer.go\
+	transport.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/net/http/cgi/Makefile b/src/pkg/net/http/cgi/Makefile
new file mode 100644
index 0000000..0d6be01
--- /dev/null
+++ b/src/pkg/net/http/cgi/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../../Make.inc
+
+TARG=net/http/cgi
+GOFILES=\
+	child.go\
+	host.go\
+
+include ../../../../Make.pkg
diff --git a/src/pkg/net/http/cgi/child.go b/src/pkg/net/http/cgi/child.go
new file mode 100644
index 0000000..e6c3ef9
--- /dev/null
+++ b/src/pkg/net/http/cgi/child.go
@@ -0,0 +1,192 @@
+// Copyright 2011 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 file implements CGI from the perspective of a child
+// process.
+
+package cgi
+
+import (
+	"bufio"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// Request returns the HTTP request as represented in the current
+// environment. This assumes the current program is being run
+// by a web server in a CGI environment.
+// The returned Request's Body is populated, if applicable.
+func Request() (*http.Request, error) {
+	r, err := RequestFromMap(envMap(os.Environ()))
+	if err != nil {
+		return nil, err
+	}
+	if r.ContentLength > 0 {
+		r.Body = ioutil.NopCloser(io.LimitReader(os.Stdin, r.ContentLength))
+	}
+	return r, nil
+}
+
+func envMap(env []string) map[string]string {
+	m := make(map[string]string)
+	for _, kv := range env {
+		if idx := strings.Index(kv, "="); idx != -1 {
+			m[kv[:idx]] = kv[idx+1:]
+		}
+	}
+	return m
+}
+
+// RequestFromMap creates an http.Request from CGI variables.
+// The returned Request's Body field is not populated.
+func RequestFromMap(params map[string]string) (*http.Request, error) {
+	r := new(http.Request)
+	r.Method = params["REQUEST_METHOD"]
+	if r.Method == "" {
+		return nil, errors.New("cgi: no REQUEST_METHOD in environment")
+	}
+
+	r.Proto = params["SERVER_PROTOCOL"]
+	var ok bool
+	r.ProtoMajor, r.ProtoMinor, ok = http.ParseHTTPVersion(r.Proto)
+	if !ok {
+		return nil, errors.New("cgi: invalid SERVER_PROTOCOL version")
+	}
+
+	r.Close = true
+	r.Trailer = http.Header{}
+	r.Header = http.Header{}
+
+	r.Host = params["HTTP_HOST"]
+
+	if lenstr := params["CONTENT_LENGTH"]; lenstr != "" {
+		clen, err := strconv.ParseInt(lenstr, 10, 64)
+		if err != nil {
+			return nil, errors.New("cgi: bad CONTENT_LENGTH in environment: " + lenstr)
+		}
+		r.ContentLength = clen
+	}
+
+	if ct := params["CONTENT_TYPE"]; ct != "" {
+		r.Header.Set("Content-Type", ct)
+	}
+
+	// Copy "HTTP_FOO_BAR" variables to "Foo-Bar" Headers
+	for k, v := range params {
+		if !strings.HasPrefix(k, "HTTP_") || k == "HTTP_HOST" {
+			continue
+		}
+		r.Header.Add(strings.Replace(k[5:], "_", "-", -1), v)
+	}
+
+	// TODO: cookies.  parsing them isn't exported, though.
+
+	if r.Host != "" {
+		// Hostname is provided, so we can reasonably construct a URL,
+		// even if we have to assume 'http' for the scheme.
+		rawurl := "http://" + r.Host + params["REQUEST_URI"]
+		url, err := url.Parse(rawurl)
+		if err != nil {
+			return nil, errors.New("cgi: failed to parse host and REQUEST_URI into a URL: " + rawurl)
+		}
+		r.URL = url
+	}
+	// Fallback logic if we don't have a Host header or the URL
+	// failed to parse
+	if r.URL == nil {
+		uriStr := params["REQUEST_URI"]
+		url, err := url.Parse(uriStr)
+		if err != nil {
+			return nil, errors.New("cgi: failed to parse REQUEST_URI into a URL: " + uriStr)
+		}
+		r.URL = url
+	}
+
+	// There's apparently a de-facto standard for this.
+	// http://docstore.mik.ua/orelly/linux/cgi/ch03_02.htm#ch03-35636
+	if s := params["HTTPS"]; s == "on" || s == "ON" || s == "1" {
+		r.TLS = &tls.ConnectionState{HandshakeComplete: true}
+	}
+
+	// Request.RemoteAddr has its port set by Go's standard http
+	// server, so we do here too. We don't have one, though, so we
+	// use a dummy one.
+	r.RemoteAddr = net.JoinHostPort(params["REMOTE_ADDR"], "0")
+
+	return r, nil
+}
+
+// Serve executes the provided Handler on the currently active CGI
+// request, if any. If there's no current CGI environment
+// an error is returned. The provided handler may be nil to use
+// http.DefaultServeMux.
+func Serve(handler http.Handler) error {
+	req, err := Request()
+	if err != nil {
+		return err
+	}
+	if handler == nil {
+		handler = http.DefaultServeMux
+	}
+	rw := &response{
+		req:    req,
+		header: make(http.Header),
+		bufw:   bufio.NewWriter(os.Stdout),
+	}
+	handler.ServeHTTP(rw, req)
+	if err = rw.bufw.Flush(); err != nil {
+		return err
+	}
+	return nil
+}
+
+type response struct {
+	req        *http.Request
+	header     http.Header
+	bufw       *bufio.Writer
+	headerSent bool
+}
+
+func (r *response) Flush() {
+	r.bufw.Flush()
+}
+
+func (r *response) Header() http.Header {
+	return r.header
+}
+
+func (r *response) Write(p []byte) (n int, err error) {
+	if !r.headerSent {
+		r.WriteHeader(http.StatusOK)
+	}
+	return r.bufw.Write(p)
+}
+
+func (r *response) WriteHeader(code int) {
+	if r.headerSent {
+		// Note: explicitly using Stderr, as Stdout is our HTTP output.
+		fmt.Fprintf(os.Stderr, "CGI attempted to write header twice on request for %s", r.req.URL)
+		return
+	}
+	r.headerSent = true
+	fmt.Fprintf(r.bufw, "Status: %d %s\r\n", code, http.StatusText(code))
+
+	// Set a default Content-Type
+	if _, hasType := r.header["Content-Type"]; !hasType {
+		r.header.Add("Content-Type", "text/html; charset=utf-8")
+	}
+
+	r.header.Write(r.bufw)
+	r.bufw.WriteString("\r\n")
+	r.bufw.Flush()
+}
diff --git a/src/pkg/net/http/cgi/child_test.go b/src/pkg/net/http/cgi/child_test.go
new file mode 100644
index 0000000..ec53ab8
--- /dev/null
+++ b/src/pkg/net/http/cgi/child_test.go
@@ -0,0 +1,87 @@
+// Copyright 2011 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.
+
+// Tests for CGI (the child process perspective)
+
+package cgi
+
+import (
+	"testing"
+)
+
+func TestRequest(t *testing.T) {
+	env := map[string]string{
+		"SERVER_PROTOCOL": "HTTP/1.1",
+		"REQUEST_METHOD":  "GET",
+		"HTTP_HOST":       "example.com",
+		"HTTP_REFERER":    "elsewhere",
+		"HTTP_USER_AGENT": "goclient",
+		"HTTP_FOO_BAR":    "baz",
+		"REQUEST_URI":     "/path?a=b",
+		"CONTENT_LENGTH":  "123",
+		"CONTENT_TYPE":    "text/xml",
+		"HTTPS":           "1",
+		"REMOTE_ADDR":     "5.6.7.8",
+	}
+	req, err := RequestFromMap(env)
+	if err != nil {
+		t.Fatalf("RequestFromMap: %v", err)
+	}
+	if g, e := req.UserAgent(), "goclient"; e != g {
+		t.Errorf("expected UserAgent %q; got %q", e, g)
+	}
+	if g, e := req.Method, "GET"; e != g {
+		t.Errorf("expected Method %q; got %q", e, g)
+	}
+	if g, e := req.Header.Get("Content-Type"), "text/xml"; e != g {
+		t.Errorf("expected Content-Type %q; got %q", e, g)
+	}
+	if g, e := req.ContentLength, int64(123); e != g {
+		t.Errorf("expected ContentLength %d; got %d", e, g)
+	}
+	if g, e := req.Referer(), "elsewhere"; e != g {
+		t.Errorf("expected Referer %q; got %q", e, g)
+	}
+	if req.Header == nil {
+		t.Fatalf("unexpected nil Header")
+	}
+	if g, e := req.Header.Get("Foo-Bar"), "baz"; e != g {
+		t.Errorf("expected Foo-Bar %q; got %q", e, g)
+	}
+	if g, e := req.URL.String(), "http://example.com/path?a=b"; e != g {
+		t.Errorf("expected URL %q; got %q", e, g)
+	}
+	if g, e := req.FormValue("a"), "b"; e != g {
+		t.Errorf("expected FormValue(a) %q; got %q", e, g)
+	}
+	if req.Trailer == nil {
+		t.Errorf("unexpected nil Trailer")
+	}
+	if req.TLS == nil {
+		t.Errorf("expected non-nil TLS")
+	}
+	if e, g := "5.6.7.8:0", req.RemoteAddr; e != g {
+		t.Errorf("RemoteAddr: got %q; want %q", g, e)
+	}
+}
+
+func TestRequestWithoutHost(t *testing.T) {
+	env := map[string]string{
+		"SERVER_PROTOCOL": "HTTP/1.1",
+		"HTTP_HOST":       "",
+		"REQUEST_METHOD":  "GET",
+		"REQUEST_URI":     "/path?a=b",
+		"CONTENT_LENGTH":  "123",
+	}
+	req, err := RequestFromMap(env)
+	if err != nil {
+		t.Fatalf("RequestFromMap: %v", err)
+	}
+	if req.URL == nil {
+		t.Fatalf("unexpected nil URL")
+	}
+	if g, e := req.URL.String(), "/path?a=b"; e != g {
+		t.Errorf("expected URL %q; got %q", e, g)
+	}
+}
diff --git a/src/pkg/net/http/cgi/host.go b/src/pkg/net/http/cgi/host.go
new file mode 100644
index 0000000..73a9b6e
--- /dev/null
+++ b/src/pkg/net/http/cgi/host.go
@@ -0,0 +1,350 @@
+// Copyright 2011 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 file implements the host side of CGI (being the webserver
+// parent process).
+
+// Package cgi implements CGI (Common Gateway Interface) as specified
+// in RFC 3875.
+//
+// Note that using CGI means starting a new process to handle each
+// request, which is typically less efficient than using a
+// long-running server.  This package is intended primarily for
+// compatibility with existing systems.
+package cgi
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+)
+
+var trailingPort = regexp.MustCompile(`:([0-9]+)$`)
+
+var osDefaultInheritEnv = map[string][]string{
+	"darwin":  {"DYLD_LIBRARY_PATH"},
+	"freebsd": {"LD_LIBRARY_PATH"},
+	"hpux":    {"LD_LIBRARY_PATH", "SHLIB_PATH"},
+	"irix":    {"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"},
+	"linux":   {"LD_LIBRARY_PATH"},
+	"openbsd": {"LD_LIBRARY_PATH"},
+	"solaris": {"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"},
+	"windows": {"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"},
+}
+
+// Handler runs an executable in a subprocess with a CGI environment.
+type Handler struct {
+	Path string // path to the CGI executable
+	Root string // root URI prefix of handler or empty for "/"
+
+	// Dir specifies the CGI executable's working directory.
+	// If Dir is empty, the base directory of Path is used.
+	// If Path has no base directory, the current working
+	// directory is used.
+	Dir string
+
+	Env        []string    // extra environment variables to set, if any, as "key=value"
+	InheritEnv []string    // environment variables to inherit from host, as "key"
+	Logger     *log.Logger // optional log for errors or nil to use log.Print
+	Args       []string    // optional arguments to pass to child process
+
+	// PathLocationHandler specifies the root http Handler that
+	// should handle internal redirects when the CGI process
+	// returns a Location header value starting with a "/", as
+	// specified in RFC 3875 § 6.3.2. This will likely be
+	// http.DefaultServeMux.
+	//
+	// If nil, a CGI response with a local URI path is instead sent
+	// back to the client and not redirected internally.
+	PathLocationHandler http.Handler
+}
+
+// removeLeadingDuplicates remove leading duplicate in environments.
+// It's possible to override environment like following.
+//    cgi.Handler{
+//      ...
+//      Env: []string{"SCRIPT_FILENAME=foo.php"},
+//    }
+func removeLeadingDuplicates(env []string) (ret []string) {
+	n := len(env)
+	for i := 0; i < n; i++ {
+		e := env[i]
+		s := strings.SplitN(e, "=", 2)[0]
+		found := false
+		for j := i + 1; j < n; j++ {
+			if s == strings.SplitN(env[j], "=", 2)[0] {
+				found = true
+				break
+			}
+		}
+		if !found {
+			ret = append(ret, e)
+		}
+	}
+	return
+}
+
+func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+	root := h.Root
+	if root == "" {
+		root = "/"
+	}
+
+	if len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked" {
+		rw.WriteHeader(http.StatusBadRequest)
+		rw.Write([]byte("Chunked request bodies are not supported by CGI."))
+		return
+	}
+
+	pathInfo := req.URL.Path
+	if root != "/" && strings.HasPrefix(pathInfo, root) {
+		pathInfo = pathInfo[len(root):]
+	}
+
+	port := "80"
+	if matches := trailingPort.FindStringSubmatch(req.Host); len(matches) != 0 {
+		port = matches[1]
+	}
+
+	env := []string{
+		"SERVER_SOFTWARE=go",
+		"SERVER_NAME=" + req.Host,
+		"SERVER_PROTOCOL=HTTP/1.1",
+		"HTTP_HOST=" + req.Host,
+		"GATEWAY_INTERFACE=CGI/1.1",
+		"REQUEST_METHOD=" + req.Method,
+		"QUERY_STRING=" + req.URL.RawQuery,
+		"REQUEST_URI=" + req.URL.RequestURI(),
+		"PATH_INFO=" + pathInfo,
+		"SCRIPT_NAME=" + root,
+		"SCRIPT_FILENAME=" + h.Path,
+		"REMOTE_ADDR=" + req.RemoteAddr,
+		"REMOTE_HOST=" + req.RemoteAddr,
+		"SERVER_PORT=" + port,
+	}
+
+	if req.TLS != nil {
+		env = append(env, "HTTPS=on")
+	}
+
+	for k, v := range req.Header {
+		k = strings.Map(upperCaseAndUnderscore, k)
+		joinStr := ", "
+		if k == "COOKIE" {
+			joinStr = "; "
+		}
+		env = append(env, "HTTP_"+k+"="+strings.Join(v, joinStr))
+	}
+
+	if req.ContentLength > 0 {
+		env = append(env, fmt.Sprintf("CONTENT_LENGTH=%d", req.ContentLength))
+	}
+	if ctype := req.Header.Get("Content-Type"); ctype != "" {
+		env = append(env, "CONTENT_TYPE="+ctype)
+	}
+
+	if h.Env != nil {
+		env = append(env, h.Env...)
+	}
+
+	envPath := os.Getenv("PATH")
+	if envPath == "" {
+		envPath = "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
+	}
+	env = append(env, "PATH="+envPath)
+
+	for _, e := range h.InheritEnv {
+		if v := os.Getenv(e); v != "" {
+			env = append(env, e+"="+v)
+		}
+	}
+
+	for _, e := range osDefaultInheritEnv[runtime.GOOS] {
+		if v := os.Getenv(e); v != "" {
+			env = append(env, e+"="+v)
+		}
+	}
+
+	env = removeLeadingDuplicates(env)
+
+	var cwd, path string
+	if h.Dir != "" {
+		path = h.Path
+		cwd = h.Dir
+	} else {
+		cwd, path = filepath.Split(h.Path)
+	}
+	if cwd == "" {
+		cwd = "."
+	}
+
+	internalError := func(err error) {
+		rw.WriteHeader(http.StatusInternalServerError)
+		h.printf("CGI error: %v", err)
+	}
+
+	cmd := &exec.Cmd{
+		Path:   path,
+		Args:   append([]string{h.Path}, h.Args...),
+		Dir:    cwd,
+		Env:    env,
+		Stderr: os.Stderr, // for now
+	}
+	if req.ContentLength != 0 {
+		cmd.Stdin = req.Body
+	}
+	stdoutRead, err := cmd.StdoutPipe()
+	if err != nil {
+		internalError(err)
+		return
+	}
+
+	err = cmd.Start()
+	if err != nil {
+		internalError(err)
+		return
+	}
+	defer cmd.Wait()
+	defer stdoutRead.Close()
+
+	linebody, _ := bufio.NewReaderSize(stdoutRead, 1024)
+	headers := make(http.Header)
+	statusCode := 0
+	for {
+		line, isPrefix, err := linebody.ReadLine()
+		if isPrefix {
+			rw.WriteHeader(http.StatusInternalServerError)
+			h.printf("cgi: long header line from subprocess.")
+			return
+		}
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			rw.WriteHeader(http.StatusInternalServerError)
+			h.printf("cgi: error reading headers: %v", err)
+			return
+		}
+		if len(line) == 0 {
+			break
+		}
+		parts := strings.SplitN(string(line), ":", 2)
+		if len(parts) < 2 {
+			h.printf("cgi: bogus header line: %s", string(line))
+			continue
+		}
+		header, val := parts[0], parts[1]
+		header = strings.TrimSpace(header)
+		val = strings.TrimSpace(val)
+		switch {
+		case header == "Status":
+			if len(val) < 3 {
+				h.printf("cgi: bogus status (short): %q", val)
+				return
+			}
+			code, err := strconv.Atoi(val[0:3])
+			if err != nil {
+				h.printf("cgi: bogus status: %q", val)
+				h.printf("cgi: line was %q", line)
+				return
+			}
+			statusCode = code
+		default:
+			headers.Add(header, val)
+		}
+	}
+
+	if loc := headers.Get("Location"); loc != "" {
+		if strings.HasPrefix(loc, "/") && h.PathLocationHandler != nil {
+			h.handleInternalRedirect(rw, req, loc)
+			return
+		}
+		if statusCode == 0 {
+			statusCode = http.StatusFound
+		}
+	}
+
+	if statusCode == 0 {
+		statusCode = http.StatusOK
+	}
+
+	// Copy headers to rw's headers, after we've decided not to
+	// go into handleInternalRedirect, which won't want its rw
+	// headers to have been touched.
+	for k, vv := range headers {
+		for _, v := range vv {
+			rw.Header().Add(k, v)
+		}
+	}
+
+	rw.WriteHeader(statusCode)
+
+	_, err = io.Copy(rw, linebody)
+	if err != nil {
+		h.printf("cgi: copy error: %v", err)
+	}
+}
+
+func (h *Handler) printf(format string, v ...interface{}) {
+	if h.Logger != nil {
+		h.Logger.Printf(format, v...)
+	} else {
+		log.Printf(format, v...)
+	}
+}
+
+func (h *Handler) handleInternalRedirect(rw http.ResponseWriter, req *http.Request, path string) {
+	url, err := req.URL.Parse(path)
+	if err != nil {
+		rw.WriteHeader(http.StatusInternalServerError)
+		h.printf("cgi: error resolving local URI path %q: %v", path, err)
+		return
+	}
+	// TODO: RFC 3875 isn't clear if only GET is supported, but it
+	// suggests so: "Note that any message-body attached to the
+	// request (such as for a POST request) may not be available
+	// to the resource that is the target of the redirect."  We
+	// should do some tests against Apache to see how it handles
+	// POST, HEAD, etc. Does the internal redirect get the same
+	// method or just GET? What about incoming headers?
+	// (e.g. Cookies) Which headers, if any, are copied into the
+	// second request?
+	newReq := &http.Request{
+		Method:     "GET",
+		URL:        url,
+		Proto:      "HTTP/1.1",
+		ProtoMajor: 1,
+		ProtoMinor: 1,
+		Header:     make(http.Header),
+		Host:       url.Host,
+		RemoteAddr: req.RemoteAddr,
+		TLS:        req.TLS,
+	}
+	h.PathLocationHandler.ServeHTTP(rw, newReq)
+}
+
+func upperCaseAndUnderscore(r rune) rune {
+	switch {
+	case r >= 'a' && r <= 'z':
+		return r - ('a' - 'A')
+	case r == '-':
+		return '_'
+	case r == '=':
+		// Maybe not part of the CGI 'spec' but would mess up
+		// the environment in any case, as Go represents the
+		// environment as a slice of "key=value" strings.
+		return '_'
+	}
+	// TODO: other transformations in spec or practice?
+	return r
+}
diff --git a/src/pkg/net/http/cgi/host_test.go b/src/pkg/net/http/cgi/host_test.go
new file mode 100644
index 0000000..9ef80ea
--- /dev/null
+++ b/src/pkg/net/http/cgi/host_test.go
@@ -0,0 +1,477 @@
+// Copyright 2011 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.
+
+// Tests for package cgi
+
+package cgi
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"net"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+func newRequest(httpreq string) *http.Request {
+	buf := bufio.NewReader(strings.NewReader(httpreq))
+	req, err := http.ReadRequest(buf)
+	if err != nil {
+		panic("cgi: bogus http request in test: " + httpreq)
+	}
+	req.RemoteAddr = "1.2.3.4"
+	return req
+}
+
+func runCgiTest(t *testing.T, h *Handler, httpreq string, expectedMap map[string]string) *httptest.ResponseRecorder {
+	rw := httptest.NewRecorder()
+	req := newRequest(httpreq)
+	h.ServeHTTP(rw, req)
+
+	// Make a map to hold the test map that the CGI returns.
+	m := make(map[string]string)
+	linesRead := 0
+readlines:
+	for {
+		line, err := rw.Body.ReadString('\n')
+		switch {
+		case err == io.EOF:
+			break readlines
+		case err != nil:
+			t.Fatalf("unexpected error reading from CGI: %v", err)
+		}
+		linesRead++
+		trimmedLine := strings.TrimRight(line, "\r\n")
+		split := strings.SplitN(trimmedLine, "=", 2)
+		if len(split) != 2 {
+			t.Fatalf("Unexpected %d parts from invalid line number %v: %q; existing map=%v",
+				len(split), linesRead, line, m)
+		}
+		m[split[0]] = split[1]
+	}
+
+	for key, expected := range expectedMap {
+		if got := m[key]; got != expected {
+			t.Errorf("for key %q got %q; expected %q", key, got, expected)
+		}
+	}
+	return rw
+}
+
+var cgiTested = false
+var cgiWorks bool
+
+func skipTest(t *testing.T) bool {
+	if !cgiTested {
+		cgiTested = true
+		cgiWorks = exec.Command("./testdata/test.cgi").Run() == nil
+	}
+	if !cgiWorks {
+		// No Perl on Windows, needed by test.cgi
+		// TODO: make the child process be Go, not Perl.
+		t.Logf("Skipping test: test.cgi failed.")
+		return true
+	}
+	return false
+}
+
+func TestCGIBasicGet(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"test":                  "Hello CGI",
+		"param-a":               "b",
+		"param-foo":             "bar",
+		"env-GATEWAY_INTERFACE": "CGI/1.1",
+		"env-HTTP_HOST":         "example.com",
+		"env-PATH_INFO":         "",
+		"env-QUERY_STRING":      "foo=bar&a=b",
+		"env-REMOTE_ADDR":       "1.2.3.4",
+		"env-REMOTE_HOST":       "1.2.3.4",
+		"env-REQUEST_METHOD":    "GET",
+		"env-REQUEST_URI":       "/test.cgi?foo=bar&a=b",
+		"env-SCRIPT_FILENAME":   "testdata/test.cgi",
+		"env-SCRIPT_NAME":       "/test.cgi",
+		"env-SERVER_NAME":       "example.com",
+		"env-SERVER_PORT":       "80",
+		"env-SERVER_SOFTWARE":   "go",
+	}
+	replay := runCgiTest(t, h, "GET /test.cgi?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+	if expected, got := "text/html", replay.Header().Get("Content-Type"); got != expected {
+		t.Errorf("got a Content-Type of %q; expected %q", got, expected)
+	}
+	if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
+		t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
+	}
+}
+
+func TestCGIBasicGetAbsPath(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	pwd, err := os.Getwd()
+	if err != nil {
+		t.Fatalf("getwd error: %v", err)
+	}
+	h := &Handler{
+		Path: pwd + "/testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"env-REQUEST_URI":     "/test.cgi?foo=bar&a=b",
+		"env-SCRIPT_FILENAME": pwd + "/testdata/test.cgi",
+		"env-SCRIPT_NAME":     "/test.cgi",
+	}
+	runCgiTest(t, h, "GET /test.cgi?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestPathInfo(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"param-a":             "b",
+		"env-PATH_INFO":       "/extrapath",
+		"env-QUERY_STRING":    "a=b",
+		"env-REQUEST_URI":     "/test.cgi/extrapath?a=b",
+		"env-SCRIPT_FILENAME": "testdata/test.cgi",
+		"env-SCRIPT_NAME":     "/test.cgi",
+	}
+	runCgiTest(t, h, "GET /test.cgi/extrapath?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestPathInfoDirRoot(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/myscript/",
+	}
+	expectedMap := map[string]string{
+		"env-PATH_INFO":       "bar",
+		"env-QUERY_STRING":    "a=b",
+		"env-REQUEST_URI":     "/myscript/bar?a=b",
+		"env-SCRIPT_FILENAME": "testdata/test.cgi",
+		"env-SCRIPT_NAME":     "/myscript/",
+	}
+	runCgiTest(t, h, "GET /myscript/bar?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestDupHeaders(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"env-REQUEST_URI":     "/myscript/bar?a=b",
+		"env-SCRIPT_FILENAME": "testdata/test.cgi",
+		"env-HTTP_COOKIE":     "nom=NOM; yum=YUM",
+		"env-HTTP_X_FOO":      "val1, val2",
+	}
+	runCgiTest(t, h, "GET /myscript/bar?a=b HTTP/1.0\n"+
+		"Cookie: nom=NOM\n"+
+		"Cookie: yum=YUM\n"+
+		"X-Foo: val1\n"+
+		"X-Foo: val2\n"+
+		"Host: example.com\n\n",
+		expectedMap)
+}
+
+func TestPathInfoNoRoot(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "",
+	}
+	expectedMap := map[string]string{
+		"env-PATH_INFO":       "/bar",
+		"env-QUERY_STRING":    "a=b",
+		"env-REQUEST_URI":     "/bar?a=b",
+		"env-SCRIPT_FILENAME": "testdata/test.cgi",
+		"env-SCRIPT_NAME":     "/",
+	}
+	runCgiTest(t, h, "GET /bar?a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestCGIBasicPost(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	postReq := `POST /test.cgi?a=b HTTP/1.0
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+Content-Length: 15
+
+postfoo=postbar`
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{
+		"test":               "Hello CGI",
+		"param-postfoo":      "postbar",
+		"env-REQUEST_METHOD": "POST",
+		"env-CONTENT_LENGTH": "15",
+		"env-REQUEST_URI":    "/test.cgi?a=b",
+	}
+	runCgiTest(t, h, postReq, expectedMap)
+}
+
+func chunk(s string) string {
+	return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
+}
+
+// The CGI spec doesn't allow chunked requests.
+func TestCGIPostChunked(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	postReq := `POST /test.cgi?a=b HTTP/1.1
+Host: example.com
+Content-Type: application/x-www-form-urlencoded
+Transfer-Encoding: chunked
+
+` + chunk("postfoo") + chunk("=") + chunk("postbar") + chunk("")
+
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap := map[string]string{}
+	resp := runCgiTest(t, h, postReq, expectedMap)
+	if got, expected := resp.Code, http.StatusBadRequest; got != expected {
+		t.Fatalf("Expected %v response code from chunked request body; got %d",
+			expected, got)
+	}
+}
+
+func TestRedirect(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	rec := runCgiTest(t, h, "GET /test.cgi?loc=http://foo.com/ HTTP/1.0\nHost: example.com\n\n", nil)
+	if e, g := 302, rec.Code; e != g {
+		t.Errorf("expected status code %d; got %d", e, g)
+	}
+	if e, g := "http://foo.com/", rec.Header().Get("Location"); e != g {
+		t.Errorf("expected Location header of %q; got %q", e, g)
+	}
+}
+
+func TestInternalRedirect(t *testing.T) {
+	if skipTest(t) {
+		return
+	}
+	baseHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+		fmt.Fprintf(rw, "basepath=%s\n", req.URL.Path)
+		fmt.Fprintf(rw, "remoteaddr=%s\n", req.RemoteAddr)
+	})
+	h := &Handler{
+		Path:                "testdata/test.cgi",
+		Root:                "/test.cgi",
+		PathLocationHandler: baseHandler,
+	}
+	expectedMap := map[string]string{
+		"basepath":   "/foo",
+		"remoteaddr": "1.2.3.4",
+	}
+	runCgiTest(t, h, "GET /test.cgi?loc=/foo HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+// TestCopyError tests that we kill the process if there's an error copying
+// its output. (for example, from the client having gone away)
+func TestCopyError(t *testing.T) {
+	if skipTest(t) || runtime.GOOS == "windows" {
+		return
+	}
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	ts := httptest.NewServer(h)
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	req, _ := http.NewRequest("GET", "http://example.com/test.cgi?bigresponse=1", nil)
+	err = req.Write(conn)
+	if err != nil {
+		t.Fatalf("Write: %v", err)
+	}
+
+	res, err := http.ReadResponse(bufio.NewReader(conn), req)
+	if err != nil {
+		t.Fatalf("ReadResponse: %v", err)
+	}
+
+	pidstr := res.Header.Get("X-CGI-Pid")
+	if pidstr == "" {
+		t.Fatalf("expected an X-CGI-Pid header in response")
+	}
+	pid, err := strconv.Atoi(pidstr)
+	if err != nil {
+		t.Fatalf("invalid X-CGI-Pid value")
+	}
+
+	var buf [5000]byte
+	n, err := io.ReadFull(res.Body, buf[:])
+	if err != nil {
+		t.Fatalf("ReadFull: %d bytes, %v", n, err)
+	}
+
+	childRunning := func() bool {
+		p, err := os.FindProcess(pid)
+		if err != nil {
+			return false
+		}
+		return p.Signal(os.UnixSignal(0)) == nil
+	}
+
+	if !childRunning() {
+		t.Fatalf("pre-conn.Close, expected child to be running")
+	}
+	conn.Close()
+
+	tries := 0
+	for tries < 25 && childRunning() {
+		time.Sleep(50 * time.Millisecond * time.Duration(tries))
+		tries++
+	}
+	if childRunning() {
+		t.Fatalf("post-conn.Close, expected child to be gone")
+	}
+}
+
+func TestDirUnix(t *testing.T) {
+	if skipTest(t) || runtime.GOOS == "windows" {
+		return
+	}
+
+	cwd, _ := os.Getwd()
+	h := &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+		Dir:  cwd,
+	}
+	expectedMap := map[string]string{
+		"cwd": cwd,
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+	cwd, _ = os.Getwd()
+	cwd = filepath.Join(cwd, "testdata")
+	h = &Handler{
+		Path: "testdata/test.cgi",
+		Root: "/test.cgi",
+	}
+	expectedMap = map[string]string{
+		"cwd": cwd,
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestDirWindows(t *testing.T) {
+	if skipTest(t) || runtime.GOOS != "windows" {
+		return
+	}
+
+	cgifile, _ := filepath.Abs("testdata/test.cgi")
+
+	var perl string
+	var err error
+	perl, err = exec.LookPath("perl")
+	if err != nil {
+		return
+	}
+	perl, _ = filepath.Abs(perl)
+
+	cwd, _ := os.Getwd()
+	h := &Handler{
+		Path: perl,
+		Root: "/test.cgi",
+		Dir:  cwd,
+		Args: []string{cgifile},
+		Env:  []string{"SCRIPT_FILENAME=" + cgifile},
+	}
+	expectedMap := map[string]string{
+		"cwd": cwd,
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+	// If not specify Dir on windows, working directory should be
+	// base directory of perl.
+	cwd, _ = filepath.Split(perl)
+	if cwd != "" && cwd[len(cwd)-1] == filepath.Separator {
+		cwd = cwd[:len(cwd)-1]
+	}
+	h = &Handler{
+		Path: perl,
+		Root: "/test.cgi",
+		Args: []string{cgifile},
+		Env:  []string{"SCRIPT_FILENAME=" + cgifile},
+	}
+	expectedMap = map[string]string{
+		"cwd": cwd,
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestEnvOverride(t *testing.T) {
+	cgifile, _ := filepath.Abs("testdata/test.cgi")
+
+	var perl string
+	var err error
+	perl, err = exec.LookPath("perl")
+	if err != nil {
+		return
+	}
+	perl, _ = filepath.Abs(perl)
+
+	cwd, _ := os.Getwd()
+	h := &Handler{
+		Path: perl,
+		Root: "/test.cgi",
+		Dir:  cwd,
+		Args: []string{cgifile},
+		Env: []string{
+			"SCRIPT_FILENAME=" + cgifile,
+			"REQUEST_URI=/foo/bar"},
+	}
+	expectedMap := map[string]string{
+		"cwd": cwd,
+		"env-SCRIPT_FILENAME": cgifile,
+		"env-REQUEST_URI":     "/foo/bar",
+	}
+	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
diff --git a/src/pkg/net/http/cgi/matryoshka_test.go b/src/pkg/net/http/cgi/matryoshka_test.go
new file mode 100644
index 0000000..1a44df2
--- /dev/null
+++ b/src/pkg/net/http/cgi/matryoshka_test.go
@@ -0,0 +1,74 @@
+// Copyright 2011 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.
+
+// Tests a Go CGI program running under a Go CGI host process.
+// Further, the two programs are the same binary, just checking
+// their environment to figure out what mode to run in.
+
+package cgi
+
+import (
+	"fmt"
+	"net/http"
+	"os"
+	"testing"
+)
+
+// This test is a CGI host (testing host.go) that runs its own binary
+// as a child process testing the other half of CGI (child.go).
+func TestHostingOurselves(t *testing.T) {
+	h := &Handler{
+		Path: os.Args[0],
+		Root: "/test.go",
+		Args: []string{"-test.run=TestBeChildCGIProcess"},
+	}
+	expectedMap := map[string]string{
+		"test":                  "Hello CGI-in-CGI",
+		"param-a":               "b",
+		"param-foo":             "bar",
+		"env-GATEWAY_INTERFACE": "CGI/1.1",
+		"env-HTTP_HOST":         "example.com",
+		"env-PATH_INFO":         "",
+		"env-QUERY_STRING":      "foo=bar&a=b",
+		"env-REMOTE_ADDR":       "1.2.3.4",
+		"env-REMOTE_HOST":       "1.2.3.4",
+		"env-REQUEST_METHOD":    "GET",
+		"env-REQUEST_URI":       "/test.go?foo=bar&a=b",
+		"env-SCRIPT_FILENAME":   os.Args[0],
+		"env-SCRIPT_NAME":       "/test.go",
+		"env-SERVER_NAME":       "example.com",
+		"env-SERVER_PORT":       "80",
+		"env-SERVER_SOFTWARE":   "go",
+	}
+	replay := runCgiTest(t, h, "GET /test.go?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+	if expected, got := "text/html; charset=utf-8", replay.Header().Get("Content-Type"); got != expected {
+		t.Errorf("got a Content-Type of %q; expected %q", got, expected)
+	}
+	if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
+		t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
+	}
+}
+
+// Note: not actually a test.
+func TestBeChildCGIProcess(t *testing.T) {
+	if os.Getenv("REQUEST_METHOD") == "" {
+		// Not in a CGI environment; skipping test.
+		return
+	}
+	Serve(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+		rw.Header().Set("X-Test-Header", "X-Test-Value")
+		fmt.Fprintf(rw, "test=Hello CGI-in-CGI\n")
+		req.ParseForm()
+		for k, vv := range req.Form {
+			for _, v := range vv {
+				fmt.Fprintf(rw, "param-%s=%s\n", k, v)
+			}
+		}
+		for _, kv := range os.Environ() {
+			fmt.Fprintf(rw, "env-%s\n", kv)
+		}
+	}))
+	os.Exit(0)
+}
diff --git a/src/pkg/http/cgi/testdata/test.cgi b/src/pkg/net/http/cgi/testdata/test.cgi
similarity index 100%
rename from src/pkg/http/cgi/testdata/test.cgi
rename to src/pkg/net/http/cgi/testdata/test.cgi
diff --git a/src/pkg/net/http/chunked.go b/src/pkg/net/http/chunked.go
new file mode 100644
index 0000000..60a478f
--- /dev/null
+++ b/src/pkg/net/http/chunked.go
@@ -0,0 +1,170 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The wire protocol for HTTP's "chunked" Transfer-Encoding.
+
+// This code is duplicated in httputil/chunked.go.
+// Please make any changes in both files.
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"io"
+	"strconv"
+)
+
+const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
+
+var ErrLineTooLong = errors.New("header line too long")
+
+// newChunkedReader returns a new chunkedReader that translates the data read from r
+// out of HTTP "chunked" format before returning it. 
+// The chunkedReader returns io.EOF when the final 0-length chunk is read.
+//
+// newChunkedReader is not needed by normal applications. The http package
+// automatically decodes chunking when reading response bodies.
+func newChunkedReader(r io.Reader) io.Reader {
+	br, ok := r.(*bufio.Reader)
+	if !ok {
+		br = bufio.NewReader(r)
+	}
+	return &chunkedReader{r: br}
+}
+
+type chunkedReader struct {
+	r   *bufio.Reader
+	n   uint64 // unread bytes in chunk
+	err error
+}
+
+func (cr *chunkedReader) beginChunk() {
+	// chunk-size CRLF
+	var line string
+	line, cr.err = readLine(cr.r)
+	if cr.err != nil {
+		return
+	}
+	cr.n, cr.err = strconv.ParseUint(line, 16, 64)
+	if cr.err != nil {
+		return
+	}
+	if cr.n == 0 {
+		cr.err = io.EOF
+	}
+}
+
+func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
+	if cr.err != nil {
+		return 0, cr.err
+	}
+	if cr.n == 0 {
+		cr.beginChunk()
+		if cr.err != nil {
+			return 0, cr.err
+		}
+	}
+	if uint64(len(b)) > cr.n {
+		b = b[0:cr.n]
+	}
+	n, cr.err = cr.r.Read(b)
+	cr.n -= uint64(n)
+	if cr.n == 0 && cr.err == nil {
+		// end of chunk (CRLF)
+		b := make([]byte, 2)
+		if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
+			if b[0] != '\r' || b[1] != '\n' {
+				cr.err = errors.New("malformed chunked encoding")
+			}
+		}
+	}
+	return n, cr.err
+}
+
+// Read a line of bytes (up to \n) from b.
+// Give up if the line exceeds maxLineLength.
+// The returned bytes are a pointer into storage in
+// the bufio, so they are only valid until the next bufio read.
+func readLineBytes(b *bufio.Reader) (p []byte, err error) {
+	if p, err = b.ReadSlice('\n'); err != nil {
+		// We always know when EOF is coming.
+		// If the caller asked for a line, there should be a line.
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		} else if err == bufio.ErrBufferFull {
+			err = ErrLineTooLong
+		}
+		return nil, err
+	}
+	if len(p) >= maxLineLength {
+		return nil, ErrLineTooLong
+	}
+
+	// Chop off trailing white space.
+	p = bytes.TrimRight(p, " \r\t\n")
+
+	return p, nil
+}
+
+// readLineBytes, but convert the bytes into a string.
+func readLine(b *bufio.Reader) (s string, err error) {
+	p, e := readLineBytes(b)
+	if e != nil {
+		return "", e
+	}
+	return string(p), nil
+}
+
+// newChunkedWriter returns a new chunkedWriter that translates writes into HTTP
+// "chunked" format before writing them to w. Closing the returned chunkedWriter
+// sends the final 0-length chunk that marks the end of the stream.
+//
+// newChunkedWriter is not needed by normal applications. The http
+// package adds chunking automatically if handlers don't set a
+// Content-Length header. Using newChunkedWriter inside a handler
+// would result in double chunking or chunking with a Content-Length
+// length, both of which are wrong.
+func newChunkedWriter(w io.Writer) io.WriteCloser {
+	return &chunkedWriter{w}
+}
+
+// Writing to chunkedWriter translates to writing in HTTP chunked Transfer
+// Encoding wire format to the underlying Wire chunkedWriter.
+type chunkedWriter struct {
+	Wire io.Writer
+}
+
+// Write the contents of data as one chunk to Wire.
+// NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
+// a bug since it does not check for success of io.WriteString
+func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
+
+	// Don't send 0-length data. It looks like EOF for chunked encoding.
+	if len(data) == 0 {
+		return 0, nil
+	}
+
+	head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
+
+	if _, err = io.WriteString(cw.Wire, head); err != nil {
+		return 0, err
+	}
+	if n, err = cw.Wire.Write(data); err != nil {
+		return
+	}
+	if n != len(data) {
+		err = io.ErrShortWrite
+		return
+	}
+	_, err = io.WriteString(cw.Wire, "\r\n")
+
+	return
+}
+
+func (cw *chunkedWriter) Close() error {
+	_, err := io.WriteString(cw.Wire, "0\r\n")
+	return err
+}
diff --git a/src/pkg/net/http/chunked_test.go b/src/pkg/net/http/chunked_test.go
new file mode 100644
index 0000000..b77ee2f
--- /dev/null
+++ b/src/pkg/net/http/chunked_test.go
@@ -0,0 +1,39 @@
+// Copyright 2011 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 code is duplicated in httputil/chunked_test.go.
+// Please make any changes in both files.
+
+package http
+
+import (
+	"bytes"
+	"io/ioutil"
+	"testing"
+)
+
+func TestChunk(t *testing.T) {
+	var b bytes.Buffer
+
+	w := newChunkedWriter(&b)
+	const chunk1 = "hello, "
+	const chunk2 = "world! 0123456789abcdef"
+	w.Write([]byte(chunk1))
+	w.Write([]byte(chunk2))
+	w.Close()
+
+	if g, e := b.String(), "7\r\nhello, \r\n17\r\nworld! 0123456789abcdef\r\n0\r\n"; g != e {
+		t.Fatalf("chunk writer wrote %q; want %q", g, e)
+	}
+
+	r := newChunkedReader(&b)
+	data, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Logf(`data: "%s"`, data)
+		t.Fatalf("ReadAll from reader: %v", err)
+	}
+	if g, e := string(data), chunk1+chunk2; g != e {
+		t.Errorf("chunk reader read %q; want %q", g, e)
+	}
+}
diff --git a/src/pkg/net/http/client.go b/src/pkg/net/http/client.go
new file mode 100644
index 0000000..c9f0240
--- /dev/null
+++ b/src/pkg/net/http/client.go
@@ -0,0 +1,326 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// HTTP client. See RFC 2616.
+// 
+// This is the high-level Client interface.
+// The low-level implementation is in transport.go.
+
+package http
+
+import (
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"io"
+	"net/url"
+	"strings"
+)
+
+// A Client is an HTTP client. Its zero value (DefaultClient) is a usable client
+// that uses DefaultTransport.
+//
+// The Client's Transport typically has internal state (cached
+// TCP connections), so Clients should be reused instead of created as
+// needed. Clients are safe for concurrent use by multiple goroutines.
+type Client struct {
+	// Transport specifies the mechanism by which individual
+	// HTTP requests are made.
+	// If nil, DefaultTransport is used.
+	Transport RoundTripper
+
+	// CheckRedirect specifies the policy for handling redirects.
+	// If CheckRedirect is not nil, the client calls it before
+	// following an HTTP redirect. The arguments req and via
+	// are the upcoming request and the requests made already,
+	// oldest first. If CheckRedirect returns an error, the client
+	// returns that error instead of issue the Request req.
+	//
+	// If CheckRedirect is nil, the Client uses its default policy,
+	// which is to stop after 10 consecutive requests.
+	CheckRedirect func(req *Request, via []*Request) error
+
+	// Jar specifies the cookie jar. 
+	// If Jar is nil, cookies are not sent in requests and ignored 
+	// in responses.
+	Jar CookieJar
+}
+
+// DefaultClient is the default Client and is used by Get, Head, and Post.
+var DefaultClient = &Client{}
+
+// RoundTripper is an interface representing the ability to execute a
+// single HTTP transaction, obtaining the Response for a given Request.
+//
+// A RoundTripper must be safe for concurrent use by multiple
+// goroutines.
+type RoundTripper interface {
+	// RoundTrip executes a single HTTP transaction, returning
+	// the Response for the request req.  RoundTrip should not
+	// attempt to interpret the response.  In particular,
+	// RoundTrip must return err == nil if it obtained a response,
+	// regardless of the response's HTTP status code.  A non-nil
+	// err should be reserved for failure to obtain a response.
+	// Similarly, RoundTrip should not attempt to handle
+	// higher-level protocol details such as redirects,
+	// authentication, or cookies.
+	//
+	// RoundTrip should not modify the request, except for
+	// consuming the Body.  The request's URL and Header fields
+	// are guaranteed to be initialized.
+	RoundTrip(*Request) (*Response, error)
+}
+
+// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
+// return true if the string includes a port.
+func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
+
+// Used in Send to implement io.ReadCloser by bundling together the
+// bufio.Reader through which we read the response, and the underlying
+// network connection.
+type readClose struct {
+	io.Reader
+	io.Closer
+}
+
+// Do sends an HTTP request and returns an HTTP response, following
+// policy (e.g. redirects, cookies, auth) as configured on the client.
+//
+// A non-nil response always contains a non-nil resp.Body.
+//
+// Callers should close resp.Body when done reading from it. If
+// resp.Body is not closed, the Client's underlying RoundTripper
+// (typically Transport) may not be able to re-use a persistent TCP
+// connection to the server for a subsequent "keep-alive" request.
+//
+// Generally Get, Post, or PostForm will be used instead of Do.
+func (c *Client) Do(req *Request) (resp *Response, err error) {
+	if req.Method == "GET" || req.Method == "HEAD" {
+		return c.doFollowingRedirects(req)
+	}
+	return send(req, c.Transport)
+}
+
+// send issues an HTTP request.  Caller should close resp.Body when done reading from it.
+func send(req *Request, t RoundTripper) (resp *Response, err error) {
+	if t == nil {
+		t = DefaultTransport
+		if t == nil {
+			err = errors.New("http: no Client.Transport or DefaultTransport")
+			return
+		}
+	}
+
+	if req.URL == nil {
+		return nil, errors.New("http: nil Request.URL")
+	}
+
+	if req.RequestURI != "" {
+		return nil, errors.New("http: Request.RequestURI can't be set in client requests.")
+	}
+
+	// Most the callers of send (Get, Post, et al) don't need
+	// Headers, leaving it uninitialized.  We guarantee to the
+	// Transport that this has been initialized, though.
+	if req.Header == nil {
+		req.Header = make(Header)
+	}
+
+	if u := req.URL.User; u != nil {
+		req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String())))
+	}
+	return t.RoundTrip(req)
+}
+
+// True if the specified HTTP status code is one for which the Get utility should
+// automatically redirect.
+func shouldRedirect(statusCode int) bool {
+	switch statusCode {
+	case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
+		return true
+	}
+	return false
+}
+
+// Get issues a GET to the specified URL.  If the response is one of the following
+// redirect codes, Get follows the redirect, up to a maximum of 10 redirects:
+//
+//    301 (Moved Permanently)
+//    302 (Found)
+//    303 (See Other)
+//    307 (Temporary Redirect)
+//
+// Caller should close r.Body when done reading from it.
+//
+// Get is a wrapper around DefaultClient.Get.
+func Get(url string) (r *Response, err error) {
+	return DefaultClient.Get(url)
+}
+
+// Get issues a GET to the specified URL.  If the response is one of the
+// following redirect codes, Get follows the redirect after calling the
+// Client's CheckRedirect function.
+//
+//    301 (Moved Permanently)
+//    302 (Found)
+//    303 (See Other)
+//    307 (Temporary Redirect)
+//
+// Caller should close r.Body when done reading from it.
+func (c *Client) Get(url string) (r *Response, err error) {
+	req, err := NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	return c.doFollowingRedirects(req)
+}
+
+func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
+	// TODO: if/when we add cookie support, the redirected request shouldn't
+	// necessarily supply the same cookies as the original.
+	var base *url.URL
+	redirectChecker := c.CheckRedirect
+	if redirectChecker == nil {
+		redirectChecker = defaultCheckRedirect
+	}
+	var via []*Request
+
+	if ireq.URL == nil {
+		return nil, errors.New("http: nil Request.URL")
+	}
+
+	jar := c.Jar
+	if jar == nil {
+		jar = blackHoleJar{}
+	}
+
+	req := ireq
+	urlStr := "" // next relative or absolute URL to fetch (after first request)
+	for redirect := 0; ; redirect++ {
+		if redirect != 0 {
+			req = new(Request)
+			req.Method = ireq.Method
+			req.Header = make(Header)
+			req.URL, err = base.Parse(urlStr)
+			if err != nil {
+				break
+			}
+			if len(via) > 0 {
+				// Add the Referer header.
+				lastReq := via[len(via)-1]
+				if lastReq.URL.Scheme != "https" {
+					req.Header.Set("Referer", lastReq.URL.String())
+				}
+
+				err = redirectChecker(req, via)
+				if err != nil {
+					break
+				}
+			}
+		}
+
+		for _, cookie := range jar.Cookies(req.URL) {
+			req.AddCookie(cookie)
+		}
+		urlStr = req.URL.String()
+		if r, err = send(req, c.Transport); err != nil {
+			break
+		}
+		if c := r.Cookies(); len(c) > 0 {
+			jar.SetCookies(req.URL, c)
+		}
+
+		if shouldRedirect(r.StatusCode) {
+			r.Body.Close()
+			if urlStr = r.Header.Get("Location"); urlStr == "" {
+				err = errors.New(fmt.Sprintf("%d response missing Location header", r.StatusCode))
+				break
+			}
+			base = req.URL
+			via = append(via, req)
+			continue
+		}
+		return
+	}
+
+	method := ireq.Method
+	err = &url.Error{method[0:1] + strings.ToLower(method[1:]), urlStr, err}
+	return
+}
+
+func defaultCheckRedirect(req *Request, via []*Request) error {
+	if len(via) >= 10 {
+		return errors.New("stopped after 10 redirects")
+	}
+	return nil
+}
+
+// Post issues a POST to the specified URL.
+//
+// Caller should close r.Body when done reading from it.
+//
+// Post is a wrapper around DefaultClient.Post
+func Post(url string, bodyType string, body io.Reader) (r *Response, err error) {
+	return DefaultClient.Post(url, bodyType, body)
+}
+
+// Post issues a POST to the specified URL.
+//
+// Caller should close r.Body when done reading from it.
+func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err error) {
+	req, err := NewRequest("POST", url, body)
+	if err != nil {
+		return nil, err
+	}
+	req.Header.Set("Content-Type", bodyType)
+	return send(req, c.Transport)
+}
+
+// PostForm issues a POST to the specified URL, 
+// with data's keys and values urlencoded as the request body.
+//
+// Caller should close r.Body when done reading from it.
+//
+// PostForm is a wrapper around DefaultClient.PostForm
+func PostForm(url string, data url.Values) (r *Response, err error) {
+	return DefaultClient.PostForm(url, data)
+}
+
+// PostForm issues a POST to the specified URL, 
+// with data's keys and values urlencoded as the request body.
+//
+// Caller should close r.Body when done reading from it.
+func (c *Client) PostForm(url string, data url.Values) (r *Response, err error) {
+	return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
+
+// Head issues a HEAD to the specified URL.  If the response is one of the
+// following redirect codes, Head follows the redirect after calling the
+// Client's CheckRedirect function.
+//
+//    301 (Moved Permanently)
+//    302 (Found)
+//    303 (See Other)
+//    307 (Temporary Redirect)
+//
+// Head is a wrapper around DefaultClient.Head
+func Head(url string) (r *Response, err error) {
+	return DefaultClient.Head(url)
+}
+
+// Head issues a HEAD to the specified URL.  If the response is one of the
+// following redirect codes, Head follows the redirect after calling the
+// Client's CheckRedirect function.
+//
+//    301 (Moved Permanently)
+//    302 (Found)
+//    303 (See Other)
+//    307 (Temporary Redirect)
+func (c *Client) Head(url string) (r *Response, err error) {
+	req, err := NewRequest("HEAD", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	return c.doFollowingRedirects(req)
+}
diff --git a/src/pkg/net/http/client_test.go b/src/pkg/net/http/client_test.go
new file mode 100644
index 0000000..aa0bf4b
--- /dev/null
+++ b/src/pkg/net/http/client_test.go
@@ -0,0 +1,442 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Tests for client.go
+
+package http_test
+
+import (
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"strconv"
+	"strings"
+	"sync"
+	"testing"
+)
+
+var robotsTxtHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
+	w.Header().Set("Last-Modified", "sometime")
+	fmt.Fprintf(w, "User-agent: go\nDisallow: /something/")
+})
+
+// pedanticReadAll works like ioutil.ReadAll but additionally
+// verifies that r obeys the documented io.Reader contract.
+func pedanticReadAll(r io.Reader) (b []byte, err error) {
+	var bufa [64]byte
+	buf := bufa[:]
+	for {
+		n, err := r.Read(buf)
+		if n == 0 && err == nil {
+			return nil, fmt.Errorf("Read: n=0 with err=nil")
+		}
+		b = append(b, buf[:n]...)
+		if err == io.EOF {
+			n, err := r.Read(buf)
+			if n != 0 || err != io.EOF {
+				return nil, fmt.Errorf("Read: n=%d err=%#v after EOF", n, err)
+			}
+			return b, nil
+		}
+		if err != nil {
+			return b, err
+		}
+	}
+	panic("unreachable")
+}
+
+func TestClient(t *testing.T) {
+	ts := httptest.NewServer(robotsTxtHandler)
+	defer ts.Close()
+
+	r, err := Get(ts.URL)
+	var b []byte
+	if err == nil {
+		b, err = pedanticReadAll(r.Body)
+		r.Body.Close()
+	}
+	if err != nil {
+		t.Error(err)
+	} else if s := string(b); !strings.HasPrefix(s, "User-agent:") {
+		t.Errorf("Incorrect page body (did not begin with User-agent): %q", s)
+	}
+}
+
+func TestClientHead(t *testing.T) {
+	ts := httptest.NewServer(robotsTxtHandler)
+	defer ts.Close()
+
+	r, err := Head(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if _, ok := r.Header["Last-Modified"]; !ok {
+		t.Error("Last-Modified header not found.")
+	}
+}
+
+type recordingTransport struct {
+	req *Request
+}
+
+func (t *recordingTransport) RoundTrip(req *Request) (resp *Response, err error) {
+	t.req = req
+	return nil, errors.New("dummy impl")
+}
+
+func TestGetRequestFormat(t *testing.T) {
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+	url := "http://dummy.faketld/"
+	client.Get(url) // Note: doesn't hit network
+	if tr.req.Method != "GET" {
+		t.Errorf("expected method %q; got %q", "GET", tr.req.Method)
+	}
+	if tr.req.URL.String() != url {
+		t.Errorf("expected URL %q; got %q", url, tr.req.URL.String())
+	}
+	if tr.req.Header == nil {
+		t.Errorf("expected non-nil request Header")
+	}
+}
+
+func TestPostRequestFormat(t *testing.T) {
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+
+	url := "http://dummy.faketld/"
+	json := `{"key":"value"}`
+	b := strings.NewReader(json)
+	client.Post(url, "application/json", b) // Note: doesn't hit network
+
+	if tr.req.Method != "POST" {
+		t.Errorf("got method %q, want %q", tr.req.Method, "POST")
+	}
+	if tr.req.URL.String() != url {
+		t.Errorf("got URL %q, want %q", tr.req.URL.String(), url)
+	}
+	if tr.req.Header == nil {
+		t.Fatalf("expected non-nil request Header")
+	}
+	if tr.req.Close {
+		t.Error("got Close true, want false")
+	}
+	if g, e := tr.req.ContentLength, int64(len(json)); g != e {
+		t.Errorf("got ContentLength %d, want %d", g, e)
+	}
+}
+
+func TestPostFormRequestFormat(t *testing.T) {
+	tr := &recordingTransport{}
+	client := &Client{Transport: tr}
+
+	urlStr := "http://dummy.faketld/"
+	form := make(url.Values)
+	form.Set("foo", "bar")
+	form.Add("foo", "bar2")
+	form.Set("bar", "baz")
+	client.PostForm(urlStr, form) // Note: doesn't hit network
+
+	if tr.req.Method != "POST" {
+		t.Errorf("got method %q, want %q", tr.req.Method, "POST")
+	}
+	if tr.req.URL.String() != urlStr {
+		t.Errorf("got URL %q, want %q", tr.req.URL.String(), urlStr)
+	}
+	if tr.req.Header == nil {
+		t.Fatalf("expected non-nil request Header")
+	}
+	if g, e := tr.req.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; g != e {
+		t.Errorf("got Content-Type %q, want %q", g, e)
+	}
+	if tr.req.Close {
+		t.Error("got Close true, want false")
+	}
+	// Depending on map iteration, body can be either of these.
+	expectedBody := "foo=bar&foo=bar2&bar=baz"
+	expectedBody1 := "bar=baz&foo=bar&foo=bar2"
+	if g, e := tr.req.ContentLength, int64(len(expectedBody)); g != e {
+		t.Errorf("got ContentLength %d, want %d", g, e)
+	}
+	bodyb, err := ioutil.ReadAll(tr.req.Body)
+	if err != nil {
+		t.Fatalf("ReadAll on req.Body: %v", err)
+	}
+	if g := string(bodyb); g != expectedBody && g != expectedBody1 {
+		t.Errorf("got body %q, want %q or %q", g, expectedBody, expectedBody1)
+	}
+}
+
+func TestRedirects(t *testing.T) {
+	var ts *httptest.Server
+	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		n, _ := strconv.Atoi(r.FormValue("n"))
+		// Test Referer header. (7 is arbitrary position to test at)
+		if n == 7 {
+			if g, e := r.Referer(), ts.URL+"/?n=6"; e != g {
+				t.Errorf("on request ?n=7, expected referer of %q; got %q", e, g)
+			}
+		}
+		if n < 15 {
+			Redirect(w, r, fmt.Sprintf("/?n=%d", n+1), StatusFound)
+			return
+		}
+		fmt.Fprintf(w, "n=%d", n)
+	}))
+	defer ts.Close()
+
+	c := &Client{}
+	_, err := c.Get(ts.URL)
+	if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with default client Get, expected error %q, got %q", e, g)
+	}
+
+	// HEAD request should also have the ability to follow redirects.
+	_, err = c.Head(ts.URL)
+	if e, g := "Head /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with default client Head, expected error %q, got %q", e, g)
+	}
+
+	// Do should also follow redirects.
+	greq, _ := NewRequest("GET", ts.URL, nil)
+	_, err = c.Do(greq)
+	if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with default client Do, expected error %q, got %q", e, g)
+	}
+
+	var checkErr error
+	var lastVia []*Request
+	c = &Client{CheckRedirect: func(_ *Request, via []*Request) error {
+		lastVia = via
+		return checkErr
+	}}
+	res, err := c.Get(ts.URL)
+	finalUrl := res.Request.URL.String()
+	if e, g := "<nil>", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with custom client, expected error %q, got %q", e, g)
+	}
+	if !strings.HasSuffix(finalUrl, "/?n=15") {
+		t.Errorf("expected final url to end in /?n=15; got url %q", finalUrl)
+	}
+	if e, g := 15, len(lastVia); e != g {
+		t.Errorf("expected lastVia to have contained %d elements; got %d", e, g)
+	}
+
+	checkErr = errors.New("no redirects allowed")
+	res, err = c.Get(ts.URL)
+	finalUrl = res.Request.URL.String()
+	if e, g := "Get /?n=1: no redirects allowed", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with redirects forbidden, expected error %q, got %q", e, g)
+	}
+}
+
+var expectedCookies = []*Cookie{
+	&Cookie{Name: "ChocolateChip", Value: "tasty"},
+	&Cookie{Name: "First", Value: "Hit"},
+	&Cookie{Name: "Second", Value: "Hit"},
+}
+
+var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
+	for _, cookie := range r.Cookies() {
+		SetCookie(w, cookie)
+	}
+	if r.URL.Path == "/" {
+		SetCookie(w, expectedCookies[1])
+		Redirect(w, r, "/second", StatusMovedPermanently)
+	} else {
+		SetCookie(w, expectedCookies[2])
+		w.Write([]byte("hello"))
+	}
+})
+
+// Just enough correctness for our redirect tests. Uses the URL.Host as the
+// scope of all cookies.
+type TestJar struct {
+	m      sync.Mutex
+	perURL map[string][]*Cookie
+}
+
+func (j *TestJar) SetCookies(u *url.URL, cookies []*Cookie) {
+	j.m.Lock()
+	defer j.m.Unlock()
+	j.perURL[u.Host] = cookies
+}
+
+func (j *TestJar) Cookies(u *url.URL) []*Cookie {
+	j.m.Lock()
+	defer j.m.Unlock()
+	return j.perURL[u.Host]
+}
+
+func TestRedirectCookiesOnRequest(t *testing.T) {
+	var ts *httptest.Server
+	ts = httptest.NewServer(echoCookiesRedirectHandler)
+	defer ts.Close()
+	c := &Client{}
+	req, _ := NewRequest("GET", ts.URL, nil)
+	req.AddCookie(expectedCookies[0])
+	// TODO: Uncomment when an implementation of a RFC6265 cookie jar lands.
+	_ = c
+	// resp, _ := c.Do(req)
+	// matchReturnedCookies(t, expectedCookies, resp.Cookies())
+
+	req, _ = NewRequest("GET", ts.URL, nil)
+	// resp, _ = c.Do(req)
+	// matchReturnedCookies(t, expectedCookies[1:], resp.Cookies())
+}
+
+func TestRedirectCookiesJar(t *testing.T) {
+	var ts *httptest.Server
+	ts = httptest.NewServer(echoCookiesRedirectHandler)
+	defer ts.Close()
+	c := &Client{}
+	c.Jar = &TestJar{perURL: make(map[string][]*Cookie)}
+	u, _ := url.Parse(ts.URL)
+	c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]})
+	resp, _ := c.Get(ts.URL)
+	matchReturnedCookies(t, expectedCookies, resp.Cookies())
+}
+
+func matchReturnedCookies(t *testing.T, expected, given []*Cookie) {
+	t.Logf("Received cookies: %v", given)
+	if len(given) != len(expected) {
+		t.Errorf("Expected %d cookies, got %d", len(expected), len(given))
+	}
+	for _, ec := range expected {
+		foundC := false
+		for _, c := range given {
+			if ec.Name == c.Name && ec.Value == c.Value {
+				foundC = true
+				break
+			}
+		}
+		if !foundC {
+			t.Errorf("Missing cookie %v", ec)
+		}
+	}
+}
+
+func TestStreamingGet(t *testing.T) {
+	say := make(chan string)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.(Flusher).Flush()
+		for str := range say {
+			w.Write([]byte(str))
+			w.(Flusher).Flush()
+		}
+	}))
+	defer ts.Close()
+
+	c := &Client{}
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	var buf [10]byte
+	for _, str := range []string{"i", "am", "also", "known", "as", "comet"} {
+		say <- str
+		n, err := io.ReadFull(res.Body, buf[0:len(str)])
+		if err != nil {
+			t.Fatalf("ReadFull on %q: %v", str, err)
+		}
+		if n != len(str) {
+			t.Fatalf("Receiving %q, only read %d bytes", str, n)
+		}
+		got := string(buf[0:n])
+		if got != str {
+			t.Fatalf("Expected %q, got %q", str, got)
+		}
+	}
+	close(say)
+	_, err = io.ReadFull(res.Body, buf[0:1])
+	if err != io.EOF {
+		t.Fatalf("at end expected EOF, got %v", err)
+	}
+}
+
+type writeCountingConn struct {
+	net.Conn
+	count *int
+}
+
+func (c *writeCountingConn) Write(p []byte) (int, error) {
+	*c.count++
+	return c.Conn.Write(p)
+}
+
+// TestClientWrites verifies that client requests are buffered and we
+// don't send a TCP packet per line of the http request + body.
+func TestClientWrites(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	}))
+	defer ts.Close()
+
+	writes := 0
+	dialer := func(netz string, addr string) (net.Conn, error) {
+		c, err := net.Dial(netz, addr)
+		if err == nil {
+			c = &writeCountingConn{c, &writes}
+		}
+		return c, err
+	}
+	c := &Client{Transport: &Transport{Dial: dialer}}
+
+	_, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if writes != 1 {
+		t.Errorf("Get request did %d Write calls, want 1", writes)
+	}
+
+	writes = 0
+	_, err = c.PostForm(ts.URL, url.Values{"foo": {"bar"}})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if writes != 1 {
+		t.Errorf("Post request did %d Write calls, want 1", writes)
+	}
+}
+
+func TestClientInsecureTransport(t *testing.T) {
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Write([]byte("Hello"))
+	}))
+	defer ts.Close()
+
+	// TODO(bradfitz): add tests for skipping hostname checks too?
+	// would require a new cert for testing, and probably
+	// redundant with these tests.
+	for _, insecure := range []bool{true, false} {
+		tr := &Transport{
+			TLSClientConfig: &tls.Config{
+				InsecureSkipVerify: insecure,
+			},
+		}
+		c := &Client{Transport: tr}
+		_, err := c.Get(ts.URL)
+		if (err == nil) != insecure {
+			t.Errorf("insecure=%v: got unexpected err=%v", insecure, err)
+		}
+	}
+}
+
+func TestClientErrorWithRequestURI(t *testing.T) {
+	req, _ := NewRequest("GET", "http://localhost:1234/", nil)
+	req.RequestURI = "/this/field/is/illegal/and/should/error/"
+	_, err := DefaultClient.Do(req)
+	if err == nil {
+		t.Fatalf("expected an error")
+	}
+	if !strings.Contains(err.Error(), "RequestURI") {
+		t.Errorf("wanted error mentioning RequestURI; got error: %v", err)
+	}
+}
diff --git a/src/pkg/net/http/cookie.go b/src/pkg/net/http/cookie.go
new file mode 100644
index 0000000..2e30bbf
--- /dev/null
+++ b/src/pkg/net/http/cookie.go
@@ -0,0 +1,267 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// This implementation is done according to RFC 6265:
+//
+//    http://tools.ietf.org/html/rfc6265
+
+// A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an
+// HTTP response or the Cookie header of an HTTP request.
+type Cookie struct {
+	Name       string
+	Value      string
+	Path       string
+	Domain     string
+	Expires    time.Time
+	RawExpires string
+
+	// MaxAge=0 means no 'Max-Age' attribute specified. 
+	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
+	// MaxAge>0 means Max-Age attribute present and given in seconds
+	MaxAge   int
+	Secure   bool
+	HttpOnly bool
+	Raw      string
+	Unparsed []string // Raw text of unparsed attribute-value pairs
+}
+
+// readSetCookies parses all "Set-Cookie" values from
+// the header h and returns the successfully parsed Cookies.
+func readSetCookies(h Header) []*Cookie {
+	cookies := []*Cookie{}
+	for _, line := range h["Set-Cookie"] {
+		parts := strings.Split(strings.TrimSpace(line), ";")
+		if len(parts) == 1 && parts[0] == "" {
+			continue
+		}
+		parts[0] = strings.TrimSpace(parts[0])
+		j := strings.Index(parts[0], "=")
+		if j < 0 {
+			continue
+		}
+		name, value := parts[0][:j], parts[0][j+1:]
+		if !isCookieNameValid(name) {
+			continue
+		}
+		value, success := parseCookieValue(value)
+		if !success {
+			continue
+		}
+		c := &Cookie{
+			Name:  name,
+			Value: value,
+			Raw:   line,
+		}
+		for i := 1; i < len(parts); i++ {
+			parts[i] = strings.TrimSpace(parts[i])
+			if len(parts[i]) == 0 {
+				continue
+			}
+
+			attr, val := parts[i], ""
+			if j := strings.Index(attr, "="); j >= 0 {
+				attr, val = attr[:j], attr[j+1:]
+			}
+			lowerAttr := strings.ToLower(attr)
+			parseCookieValueFn := parseCookieValue
+			if lowerAttr == "expires" {
+				parseCookieValueFn = parseCookieExpiresValue
+			}
+			val, success = parseCookieValueFn(val)
+			if !success {
+				c.Unparsed = append(c.Unparsed, parts[i])
+				continue
+			}
+			switch lowerAttr {
+			case "secure":
+				c.Secure = true
+				continue
+			case "httponly":
+				c.HttpOnly = true
+				continue
+			case "domain":
+				c.Domain = val
+				// TODO: Add domain parsing
+				continue
+			case "max-age":
+				secs, err := strconv.Atoi(val)
+				if err != nil || secs != 0 && val[0] == '0' {
+					break
+				}
+				if secs <= 0 {
+					c.MaxAge = -1
+				} else {
+					c.MaxAge = secs
+				}
+				continue
+			case "expires":
+				c.RawExpires = val
+				exptime, err := time.Parse(time.RFC1123, val)
+				if err != nil {
+					exptime, err = time.Parse("Mon, 02-Jan-2006 15:04:05 MST", val)
+					if err != nil {
+						c.Expires = time.Time{}
+						break
+					}
+				}
+				c.Expires = exptime.UTC()
+				continue
+			case "path":
+				c.Path = val
+				// TODO: Add path parsing
+				continue
+			}
+			c.Unparsed = append(c.Unparsed, parts[i])
+		}
+		cookies = append(cookies, c)
+	}
+	return cookies
+}
+
+// SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers.
+func SetCookie(w ResponseWriter, cookie *Cookie) {
+	w.Header().Add("Set-Cookie", cookie.String())
+}
+
+// String returns the serialization of the cookie for use in a Cookie
+// header (if only Name and Value are set) or a Set-Cookie response
+// header (if other fields are set).
+func (c *Cookie) String() string {
+	var b bytes.Buffer
+	fmt.Fprintf(&b, "%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
+	if len(c.Path) > 0 {
+		fmt.Fprintf(&b, "; Path=%s", sanitizeValue(c.Path))
+	}
+	if len(c.Domain) > 0 {
+		fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(c.Domain))
+	}
+	if c.Expires.Unix() > 0 {
+		fmt.Fprintf(&b, "; Expires=%s", c.Expires.UTC().Format(time.RFC1123))
+	}
+	if c.MaxAge > 0 {
+		fmt.Fprintf(&b, "; Max-Age=%d", c.MaxAge)
+	} else if c.MaxAge < 0 {
+		fmt.Fprintf(&b, "; Max-Age=0")
+	}
+	if c.HttpOnly {
+		fmt.Fprintf(&b, "; HttpOnly")
+	}
+	if c.Secure {
+		fmt.Fprintf(&b, "; Secure")
+	}
+	return b.String()
+}
+
+// readCookies parses all "Cookie" values from the header h and
+// returns the successfully parsed Cookies.
+//
+// if filter isn't empty, only cookies of that name are returned
+func readCookies(h Header, filter string) []*Cookie {
+	cookies := []*Cookie{}
+	lines, ok := h["Cookie"]
+	if !ok {
+		return cookies
+	}
+
+	for _, line := range lines {
+		parts := strings.Split(strings.TrimSpace(line), ";")
+		if len(parts) == 1 && parts[0] == "" {
+			continue
+		}
+		// Per-line attributes
+		parsedPairs := 0
+		for i := 0; i < len(parts); i++ {
+			parts[i] = strings.TrimSpace(parts[i])
+			if len(parts[i]) == 0 {
+				continue
+			}
+			name, val := parts[i], ""
+			if j := strings.Index(name, "="); j >= 0 {
+				name, val = name[:j], name[j+1:]
+			}
+			if !isCookieNameValid(name) {
+				continue
+			}
+			if filter != "" && filter != name {
+				continue
+			}
+			val, success := parseCookieValue(val)
+			if !success {
+				continue
+			}
+			cookies = append(cookies, &Cookie{Name: name, Value: val})
+			parsedPairs++
+		}
+	}
+	return cookies
+}
+
+var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
+
+func sanitizeName(n string) string {
+	return cookieNameSanitizer.Replace(n)
+}
+
+var cookieValueSanitizer = strings.NewReplacer("\n", " ", "\r", " ", ";", " ")
+
+func sanitizeValue(v string) string {
+	return cookieValueSanitizer.Replace(v)
+}
+
+func unquoteCookieValue(v string) string {
+	if len(v) > 1 && v[0] == '"' && v[len(v)-1] == '"' {
+		return v[1 : len(v)-1]
+	}
+	return v
+}
+
+func isCookieByte(c byte) bool {
+	switch {
+	case c == 0x21, 0x23 <= c && c <= 0x2b, 0x2d <= c && c <= 0x3a,
+		0x3c <= c && c <= 0x5b, 0x5d <= c && c <= 0x7e:
+		return true
+	}
+	return false
+}
+
+func isCookieExpiresByte(c byte) (ok bool) {
+	return isCookieByte(c) || c == ',' || c == ' '
+}
+
+func parseCookieValue(raw string) (string, bool) {
+	return parseCookieValueUsing(raw, isCookieByte)
+}
+
+func parseCookieExpiresValue(raw string) (string, bool) {
+	return parseCookieValueUsing(raw, isCookieExpiresByte)
+}
+
+func parseCookieValueUsing(raw string, validByte func(byte) bool) (string, bool) {
+	raw = unquoteCookieValue(raw)
+	for i := 0; i < len(raw); i++ {
+		if !validByte(raw[i]) {
+			return "", false
+		}
+	}
+	return raw, true
+}
+
+func isCookieNameValid(raw string) bool {
+	for _, c := range raw {
+		if !isToken(byte(c)) {
+			return false
+		}
+	}
+	return true
+}
diff --git a/src/pkg/net/http/cookie_test.go b/src/pkg/net/http/cookie_test.go
new file mode 100644
index 0000000..712350d
--- /dev/null
+++ b/src/pkg/net/http/cookie_test.go
@@ -0,0 +1,200 @@
+// Copyright 2010 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 http
+
+import (
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"testing"
+	"time"
+)
+
+var writeSetCookiesTests = []struct {
+	Cookie *Cookie
+	Raw    string
+}{
+	{
+		&Cookie{Name: "cookie-1", Value: "v$1"},
+		"cookie-1=v$1",
+	},
+	{
+		&Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600},
+		"cookie-2=two; Max-Age=3600",
+	},
+	{
+		&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
+		"cookie-3=three; Domain=.example.com",
+	},
+	{
+		&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
+		"cookie-4=four; Path=/restricted/",
+	},
+}
+
+func TestWriteSetCookies(t *testing.T) {
+	for i, tt := range writeSetCookiesTests {
+		if g, e := tt.Cookie.String(), tt.Raw; g != e {
+			t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, e, g)
+			continue
+		}
+	}
+}
+
+type headerOnlyResponseWriter Header
+
+func (ho headerOnlyResponseWriter) Header() Header {
+	return Header(ho)
+}
+
+func (ho headerOnlyResponseWriter) Write([]byte) (int, error) {
+	panic("NOIMPL")
+}
+
+func (ho headerOnlyResponseWriter) WriteHeader(int) {
+	panic("NOIMPL")
+}
+
+func TestSetCookie(t *testing.T) {
+	m := make(Header)
+	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-1", Value: "one", Path: "/restricted/"})
+	SetCookie(headerOnlyResponseWriter(m), &Cookie{Name: "cookie-2", Value: "two", MaxAge: 3600})
+	if l := len(m["Set-Cookie"]); l != 2 {
+		t.Fatalf("expected %d cookies, got %d", 2, l)
+	}
+	if g, e := m["Set-Cookie"][0], "cookie-1=one; Path=/restricted/"; g != e {
+		t.Errorf("cookie #1: want %q, got %q", e, g)
+	}
+	if g, e := m["Set-Cookie"][1], "cookie-2=two; Max-Age=3600"; g != e {
+		t.Errorf("cookie #2: want %q, got %q", e, g)
+	}
+}
+
+var addCookieTests = []struct {
+	Cookies []*Cookie
+	Raw     string
+}{
+	{
+		[]*Cookie{},
+		"",
+	},
+	{
+		[]*Cookie{{Name: "cookie-1", Value: "v$1"}},
+		"cookie-1=v$1",
+	},
+	{
+		[]*Cookie{
+			{Name: "cookie-1", Value: "v$1"},
+			{Name: "cookie-2", Value: "v$2"},
+			{Name: "cookie-3", Value: "v$3"},
+		},
+		"cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
+	},
+}
+
+func TestAddCookie(t *testing.T) {
+	for i, tt := range addCookieTests {
+		req, _ := NewRequest("GET", "http://example.com/", nil)
+		for _, c := range tt.Cookies {
+			req.AddCookie(c)
+		}
+		if g := req.Header.Get("Cookie"); g != tt.Raw {
+			t.Errorf("Test %d:\nwant: %s\n got: %s\n", i, tt.Raw, g)
+			continue
+		}
+	}
+}
+
+var readSetCookiesTests = []struct {
+	Header  Header
+	Cookies []*Cookie
+}{
+	{
+		Header{"Set-Cookie": {"Cookie-1=v$1"}},
+		[]*Cookie{{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
+	},
+	{
+		Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
+		[]*Cookie{{
+			Name:       "NID",
+			Value:      "99=YsDT5i3E-CXax-",
+			Path:       "/",
+			Domain:     ".google.ch",
+			HttpOnly:   true,
+			Expires:    time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
+			RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
+			Raw:        "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
+		}},
+	},
+}
+
+func toJSON(v interface{}) string {
+	b, err := json.Marshal(v)
+	if err != nil {
+		return fmt.Sprintf("%#v", v)
+	}
+	return string(b)
+}
+
+func TestReadSetCookies(t *testing.T) {
+	for i, tt := range readSetCookiesTests {
+		for n := 0; n < 2; n++ { // to verify readSetCookies doesn't mutate its input
+			c := readSetCookies(tt.Header)
+			if !reflect.DeepEqual(c, tt.Cookies) {
+				t.Errorf("#%d readSetCookies: have\n%s\nwant\n%s\n", i, toJSON(c), toJSON(tt.Cookies))
+				continue
+			}
+		}
+	}
+}
+
+var readCookiesTests = []struct {
+	Header  Header
+	Filter  string
+	Cookies []*Cookie
+}{
+	{
+		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
+		"",
+		[]*Cookie{
+			{Name: "Cookie-1", Value: "v$1"},
+			{Name: "c2", Value: "v2"},
+		},
+	},
+	{
+		Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
+		"c2",
+		[]*Cookie{
+			{Name: "c2", Value: "v2"},
+		},
+	},
+	{
+		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
+		"",
+		[]*Cookie{
+			{Name: "Cookie-1", Value: "v$1"},
+			{Name: "c2", Value: "v2"},
+		},
+	},
+	{
+		Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
+		"c2",
+		[]*Cookie{
+			{Name: "c2", Value: "v2"},
+		},
+	},
+}
+
+func TestReadCookies(t *testing.T) {
+	for i, tt := range readCookiesTests {
+		for n := 0; n < 2; n++ { // to verify readCookies doesn't mutate its input                                                  
+			c := readCookies(tt.Header, tt.Filter)
+			if !reflect.DeepEqual(c, tt.Cookies) {
+				t.Errorf("#%d readCookies:\nhave: %s\nwant: %s\n", i, toJSON(c), toJSON(tt.Cookies))
+				continue
+			}
+		}
+	}
+}
diff --git a/src/pkg/net/http/doc.go b/src/pkg/net/http/doc.go
new file mode 100644
index 0000000..8962ed3
--- /dev/null
+++ b/src/pkg/net/http/doc.go
@@ -0,0 +1,80 @@
+// Copyright 2011 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 http provides HTTP client and server implementations.
+
+Get, Head, Post, and PostForm make HTTP requests:
+
+	resp, err := http.Get("http://example.com/")
+	...
+	resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
+	...
+	resp, err := http.PostForm("http://example.com/form",
+ 		url.Values{"key": {"Value"}, "id": {"123"}})
+
+The client must close the response body when finished with it:
+
+	resp, err := http.Get("http://example.com/")
+	if err != nil {
+		// handle error
+	}
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	// ...
+
+For control over HTTP client headers, redirect policy, and other
+settings, create a Client:
+
+	client := &http.Client{
+		CheckRedirect: redirectPolicyFunc,
+	}
+
+	resp, err := client.Get("http://example.com")
+	// ...
+
+	req, err := http.NewRequest("GET", "http://example.com", nil)
+	// ...
+	req.Header.Add("If-None-Match", `W/"wyzzy"`)
+	resp, err := client.Do(req)
+	// ...
+
+For control over proxies, TLS configuration, keep-alives,
+compression, and other settings, create a Transport:
+
+	tr := &http.Transport{
+		TLSClientConfig:    &tls.Config{RootCAs: pool},
+		DisableCompression: true,
+	}
+	client := &http.Client{Transport: tr}
+	resp, err := client.Get("https://example.com")
+
+Clients and Transports are safe for concurrent use by multiple
+goroutines and for efficiency should only be created once and re-used.
+
+ListenAndServe starts an HTTP server with a given address and handler.
+The handler is usually nil, which means to use DefaultServeMux.
+Handle and HandleFunc add handlers to DefaultServeMux:
+
+	http.Handle("/foo", fooHandler)
+
+	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
+		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.RawPath))
+	})
+
+	log.Fatal(http.ListenAndServe(":8080", nil))
+
+More control over the server's behavior is available by creating a
+custom Server:
+
+	s := &http.Server{
+		Addr:           ":8080",
+		Handler:        myHandler,
+		ReadTimeout:    10 * time.Second,
+		WriteTimeout:   10 * time.Second,
+		MaxHeaderBytes: 1 << 20,
+	}
+	log.Fatal(s.ListenAndServe())
+*/
+package http
diff --git a/src/pkg/net/http/export_test.go b/src/pkg/net/http/export_test.go
new file mode 100644
index 0000000..13640ca
--- /dev/null
+++ b/src/pkg/net/http/export_test.go
@@ -0,0 +1,43 @@
+// Copyright 2011 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.
+
+// Bridge package to expose http internals to tests in the http_test
+// package.
+
+package http
+
+import "time"
+
+func (t *Transport) IdleConnKeysForTesting() (keys []string) {
+	keys = make([]string, 0)
+	t.lk.Lock()
+	defer t.lk.Unlock()
+	if t.idleConn == nil {
+		return
+	}
+	for key := range t.idleConn {
+		keys = append(keys, key)
+	}
+	return
+}
+
+func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
+	t.lk.Lock()
+	defer t.lk.Unlock()
+	if t.idleConn == nil {
+		return 0
+	}
+	conns, ok := t.idleConn[cacheKey]
+	if !ok {
+		return 0
+	}
+	return len(conns)
+}
+
+func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
+	f := func() <-chan time.Time {
+		return ch
+	}
+	return &timeoutHandler{handler, f, ""}
+}
diff --git a/src/pkg/net/http/fcgi/Makefile b/src/pkg/net/http/fcgi/Makefile
new file mode 100644
index 0000000..9a75f1a
--- /dev/null
+++ b/src/pkg/net/http/fcgi/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../../Make.inc
+
+TARG=net/http/fcgi
+GOFILES=\
+	child.go\
+	fcgi.go\
+
+include ../../../../Make.pkg
diff --git a/src/pkg/net/http/fcgi/child.go b/src/pkg/net/http/fcgi/child.go
new file mode 100644
index 0000000..c94b9a7
--- /dev/null
+++ b/src/pkg/net/http/fcgi/child.go
@@ -0,0 +1,271 @@
+// Copyright 2011 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 fcgi
+
+// This file implements FastCGI from the perspective of a child process.
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"net/http"
+	"net/http/cgi"
+	"os"
+	"time"
+)
+
+// request holds the state for an in-progress request. As soon as it's complete,
+// it's converted to an http.Request.
+type request struct {
+	pw        *io.PipeWriter
+	reqId     uint16
+	params    map[string]string
+	buf       [1024]byte
+	rawParams []byte
+	keepConn  bool
+}
+
+func newRequest(reqId uint16, flags uint8) *request {
+	r := &request{
+		reqId:    reqId,
+		params:   map[string]string{},
+		keepConn: flags&flagKeepConn != 0,
+	}
+	r.rawParams = r.buf[:0]
+	return r
+}
+
+// parseParams reads an encoded []byte into Params.
+func (r *request) parseParams() {
+	text := r.rawParams
+	r.rawParams = nil
+	for len(text) > 0 {
+		keyLen, n := readSize(text)
+		if n == 0 {
+			return
+		}
+		text = text[n:]
+		valLen, n := readSize(text)
+		if n == 0 {
+			return
+		}
+		text = text[n:]
+		key := readString(text, keyLen)
+		text = text[keyLen:]
+		val := readString(text, valLen)
+		text = text[valLen:]
+		r.params[key] = val
+	}
+}
+
+// response implements http.ResponseWriter.
+type response struct {
+	req         *request
+	header      http.Header
+	w           *bufWriter
+	wroteHeader bool
+}
+
+func newResponse(c *child, req *request) *response {
+	return &response{
+		req:    req,
+		header: http.Header{},
+		w:      newWriter(c.conn, typeStdout, req.reqId),
+	}
+}
+
+func (r *response) Header() http.Header {
+	return r.header
+}
+
+func (r *response) Write(data []byte) (int, error) {
+	if !r.wroteHeader {
+		r.WriteHeader(http.StatusOK)
+	}
+	return r.w.Write(data)
+}
+
+func (r *response) WriteHeader(code int) {
+	if r.wroteHeader {
+		return
+	}
+	r.wroteHeader = true
+	if code == http.StatusNotModified {
+		// Must not have body.
+		r.header.Del("Content-Type")
+		r.header.Del("Content-Length")
+		r.header.Del("Transfer-Encoding")
+	} else if r.header.Get("Content-Type") == "" {
+		r.header.Set("Content-Type", "text/html; charset=utf-8")
+	}
+
+	if r.header.Get("Date") == "" {
+		r.header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
+	}
+
+	fmt.Fprintf(r.w, "Status: %d %s\r\n", code, http.StatusText(code))
+	r.header.Write(r.w)
+	r.w.WriteString("\r\n")
+}
+
+func (r *response) Flush() {
+	if !r.wroteHeader {
+		r.WriteHeader(http.StatusOK)
+	}
+	r.w.Flush()
+}
+
+func (r *response) Close() error {
+	r.Flush()
+	return r.w.Close()
+}
+
+type child struct {
+	conn     *conn
+	handler  http.Handler
+	requests map[uint16]*request // keyed by request ID
+}
+
+func newChild(rwc io.ReadWriteCloser, handler http.Handler) *child {
+	return &child{
+		conn:     newConn(rwc),
+		handler:  handler,
+		requests: make(map[uint16]*request),
+	}
+}
+
+func (c *child) serve() {
+	defer c.conn.Close()
+	var rec record
+	for {
+		if err := rec.read(c.conn.rwc); err != nil {
+			return
+		}
+		if err := c.handleRecord(&rec); err != nil {
+			return
+		}
+	}
+}
+
+var errCloseConn = errors.New("fcgi: connection should be closed")
+
+func (c *child) handleRecord(rec *record) error {
+	req, ok := c.requests[rec.h.Id]
+	if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
+		// The spec says to ignore unknown request IDs.
+		return nil
+	}
+	if ok && rec.h.Type == typeBeginRequest {
+		// The server is trying to begin a request with the same ID
+		// as an in-progress request. This is an error.
+		return errors.New("fcgi: received ID that is already in-flight")
+	}
+
+	switch rec.h.Type {
+	case typeBeginRequest:
+		var br beginRequest
+		if err := br.read(rec.content()); err != nil {
+			return err
+		}
+		if br.role != roleResponder {
+			c.conn.writeEndRequest(rec.h.Id, 0, statusUnknownRole)
+			return nil
+		}
+		c.requests[rec.h.Id] = newRequest(rec.h.Id, br.flags)
+	case typeParams:
+		// NOTE(eds): Technically a key-value pair can straddle the boundary
+		// between two packets. We buffer until we've received all parameters.
+		if len(rec.content()) > 0 {
+			req.rawParams = append(req.rawParams, rec.content()...)
+			return nil
+		}
+		req.parseParams()
+	case typeStdin:
+		content := rec.content()
+		if req.pw == nil {
+			var body io.ReadCloser
+			if len(content) > 0 {
+				// body could be an io.LimitReader, but it shouldn't matter
+				// as long as both sides are behaving.
+				body, req.pw = io.Pipe()
+			}
+			go c.serveRequest(req, body)
+		}
+		if len(content) > 0 {
+			// TODO(eds): This blocks until the handler reads from the pipe.
+			// If the handler takes a long time, it might be a problem.
+			req.pw.Write(content)
+		} else if req.pw != nil {
+			req.pw.Close()
+		}
+	case typeGetValues:
+		values := map[string]string{"FCGI_MPXS_CONNS": "1"}
+		c.conn.writePairs(typeGetValuesResult, 0, values)
+	case typeData:
+		// If the filter role is implemented, read the data stream here.
+	case typeAbortRequest:
+		delete(c.requests, rec.h.Id)
+		c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
+		if !req.keepConn {
+			// connection will close upon return
+			return errCloseConn
+		}
+	default:
+		b := make([]byte, 8)
+		b[0] = byte(rec.h.Type)
+		c.conn.writeRecord(typeUnknownType, 0, b)
+	}
+	return nil
+}
+
+func (c *child) serveRequest(req *request, body io.ReadCloser) {
+	r := newResponse(c, req)
+	httpReq, err := cgi.RequestFromMap(req.params)
+	if err != nil {
+		// there was an error reading the request
+		r.WriteHeader(http.StatusInternalServerError)
+		c.conn.writeRecord(typeStderr, req.reqId, []byte(err.Error()))
+	} else {
+		httpReq.Body = body
+		c.handler.ServeHTTP(r, httpReq)
+	}
+	if body != nil {
+		body.Close()
+	}
+	r.Close()
+	c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
+	if !req.keepConn {
+		c.conn.Close()
+	}
+}
+
+// Serve accepts incoming FastCGI connections on the listener l, creating a new
+// service thread for each. The service threads read requests and then call handler
+// to reply to them.
+// If l is nil, Serve accepts connections on stdin.
+// If handler is nil, http.DefaultServeMux is used.
+func Serve(l net.Listener, handler http.Handler) error {
+	if l == nil {
+		var err error
+		l, err = net.FileListener(os.Stdin)
+		if err != nil {
+			return err
+		}
+		defer l.Close()
+	}
+	if handler == nil {
+		handler = http.DefaultServeMux
+	}
+	for {
+		rw, err := l.Accept()
+		if err != nil {
+			return err
+		}
+		c := newChild(rw, handler)
+		go c.serve()
+	}
+	panic("unreachable")
+}
diff --git a/src/pkg/net/http/fcgi/fcgi.go b/src/pkg/net/http/fcgi/fcgi.go
new file mode 100644
index 0000000..d35aa84
--- /dev/null
+++ b/src/pkg/net/http/fcgi/fcgi.go
@@ -0,0 +1,274 @@
+// Copyright 2011 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 fcgi implements the FastCGI protocol.
+// Currently only the responder role is supported.
+// The protocol is defined at http://www.fastcgi.com/drupal/node/6?q=node/22
+package fcgi
+
+// This file defines the raw protocol and some utilities used by the child and
+// the host.
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"io"
+	"sync"
+)
+
+// recType is a record type, as defined by
+// http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S8
+type recType uint8
+
+const (
+	typeBeginRequest    recType = 1
+	typeAbortRequest    recType = 2
+	typeEndRequest      recType = 3
+	typeParams          recType = 4
+	typeStdin           recType = 5
+	typeStdout          recType = 6
+	typeStderr          recType = 7
+	typeData            recType = 8
+	typeGetValues       recType = 9
+	typeGetValuesResult recType = 10
+	typeUnknownType     recType = 11
+)
+
+// keep the connection between web-server and responder open after request
+const flagKeepConn = 1
+
+const (
+	maxWrite = 65535 // maximum record body
+	maxPad   = 255
+)
+
+const (
+	roleResponder = iota + 1 // only Responders are implemented.
+	roleAuthorizer
+	roleFilter
+)
+
+const (
+	statusRequestComplete = iota
+	statusCantMultiplex
+	statusOverloaded
+	statusUnknownRole
+)
+
+const headerLen = 8
+
+type header struct {
+	Version       uint8
+	Type          recType
+	Id            uint16
+	ContentLength uint16
+	PaddingLength uint8
+	Reserved      uint8
+}
+
+type beginRequest struct {
+	role     uint16
+	flags    uint8
+	reserved [5]uint8
+}
+
+func (br *beginRequest) read(content []byte) error {
+	if len(content) != 8 {
+		return errors.New("fcgi: invalid begin request record")
+	}
+	br.role = binary.BigEndian.Uint16(content)
+	br.flags = content[2]
+	return nil
+}
+
+// for padding so we don't have to allocate all the time
+// not synchronized because we don't care what the contents are
+var pad [maxPad]byte
+
+func (h *header) init(recType recType, reqId uint16, contentLength int) {
+	h.Version = 1
+	h.Type = recType
+	h.Id = reqId
+	h.ContentLength = uint16(contentLength)
+	h.PaddingLength = uint8(-contentLength & 7)
+}
+
+// conn sends records over rwc
+type conn struct {
+	mutex sync.Mutex
+	rwc   io.ReadWriteCloser
+
+	// to avoid allocations
+	buf bytes.Buffer
+	h   header
+}
+
+func newConn(rwc io.ReadWriteCloser) *conn {
+	return &conn{rwc: rwc}
+}
+
+func (c *conn) Close() error {
+	c.mutex.Lock()
+	defer c.mutex.Unlock()
+	return c.rwc.Close()
+}
+
+type record struct {
+	h   header
+	buf [maxWrite + maxPad]byte
+}
+
+func (rec *record) read(r io.Reader) (err error) {
+	if err = binary.Read(r, binary.BigEndian, &rec.h); err != nil {
+		return err
+	}
+	if rec.h.Version != 1 {
+		return errors.New("fcgi: invalid header version")
+	}
+	n := int(rec.h.ContentLength) + int(rec.h.PaddingLength)
+	if _, err = io.ReadFull(r, rec.buf[:n]); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (r *record) content() []byte {
+	return r.buf[:r.h.ContentLength]
+}
+
+// writeRecord writes and sends a single record.
+func (c *conn) writeRecord(recType recType, reqId uint16, b []byte) error {
+	c.mutex.Lock()
+	defer c.mutex.Unlock()
+	c.buf.Reset()
+	c.h.init(recType, reqId, len(b))
+	if err := binary.Write(&c.buf, binary.BigEndian, c.h); err != nil {
+		return err
+	}
+	if _, err := c.buf.Write(b); err != nil {
+		return err
+	}
+	if _, err := c.buf.Write(pad[:c.h.PaddingLength]); err != nil {
+		return err
+	}
+	_, err := c.rwc.Write(c.buf.Bytes())
+	return err
+}
+
+func (c *conn) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
+	b := [8]byte{byte(role >> 8), byte(role), flags}
+	return c.writeRecord(typeBeginRequest, reqId, b[:])
+}
+
+func (c *conn) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) error {
+	b := make([]byte, 8)
+	binary.BigEndian.PutUint32(b, uint32(appStatus))
+	b[4] = protocolStatus
+	return c.writeRecord(typeEndRequest, reqId, b)
+}
+
+func (c *conn) writePairs(recType recType, reqId uint16, pairs map[string]string) error {
+	w := newWriter(c, recType, reqId)
+	b := make([]byte, 8)
+	for k, v := range pairs {
+		n := encodeSize(b, uint32(len(k)))
+		n += encodeSize(b[n:], uint32(len(v)))
+		if _, err := w.Write(b[:n]); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(k); err != nil {
+			return err
+		}
+		if _, err := w.WriteString(v); err != nil {
+			return err
+		}
+	}
+	w.Close()
+	return nil
+}
+
+func readSize(s []byte) (uint32, int) {
+	if len(s) == 0 {
+		return 0, 0
+	}
+	size, n := uint32(s[0]), 1
+	if size&(1<<7) != 0 {
+		if len(s) < 4 {
+			return 0, 0
+		}
+		n = 4
+		size = binary.BigEndian.Uint32(s)
+		size &^= 1 << 31
+	}
+	return size, n
+}
+
+func readString(s []byte, size uint32) string {
+	if size > uint32(len(s)) {
+		return ""
+	}
+	return string(s[:size])
+}
+
+func encodeSize(b []byte, size uint32) int {
+	if size > 127 {
+		size |= 1 << 31
+		binary.BigEndian.PutUint32(b, size)
+		return 4
+	}
+	b[0] = byte(size)
+	return 1
+}
+
+// bufWriter encapsulates bufio.Writer but also closes the underlying stream when
+// Closed.
+type bufWriter struct {
+	closer io.Closer
+	*bufio.Writer
+}
+
+func (w *bufWriter) Close() error {
+	if err := w.Writer.Flush(); err != nil {
+		w.closer.Close()
+		return err
+	}
+	return w.closer.Close()
+}
+
+func newWriter(c *conn, recType recType, reqId uint16) *bufWriter {
+	s := &streamWriter{c: c, recType: recType, reqId: reqId}
+	w, _ := bufio.NewWriterSize(s, maxWrite)
+	return &bufWriter{s, w}
+}
+
+// streamWriter abstracts out the separation of a stream into discrete records.
+// It only writes maxWrite bytes at a time.
+type streamWriter struct {
+	c       *conn
+	recType recType
+	reqId   uint16
+}
+
+func (w *streamWriter) Write(p []byte) (int, error) {
+	nn := 0
+	for len(p) > 0 {
+		n := len(p)
+		if n > maxWrite {
+			n = maxWrite
+		}
+		if err := w.c.writeRecord(w.recType, w.reqId, p[:n]); err != nil {
+			return nn, err
+		}
+		nn += n
+		p = p[n:]
+	}
+	return nn, nil
+}
+
+func (w *streamWriter) Close() error {
+	// send empty record to close the stream
+	return w.c.writeRecord(w.recType, w.reqId, nil)
+}
diff --git a/src/pkg/net/http/fcgi/fcgi_test.go b/src/pkg/net/http/fcgi/fcgi_test.go
new file mode 100644
index 0000000..6c7e1a9
--- /dev/null
+++ b/src/pkg/net/http/fcgi/fcgi_test.go
@@ -0,0 +1,150 @@
+// Copyright 2011 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 fcgi
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"testing"
+)
+
+var sizeTests = []struct {
+	size  uint32
+	bytes []byte
+}{
+	{0, []byte{0x00}},
+	{127, []byte{0x7F}},
+	{128, []byte{0x80, 0x00, 0x00, 0x80}},
+	{1000, []byte{0x80, 0x00, 0x03, 0xE8}},
+	{33554431, []byte{0x81, 0xFF, 0xFF, 0xFF}},
+}
+
+func TestSize(t *testing.T) {
+	b := make([]byte, 4)
+	for i, test := range sizeTests {
+		n := encodeSize(b, test.size)
+		if !bytes.Equal(b[:n], test.bytes) {
+			t.Errorf("%d expected %x, encoded %x", i, test.bytes, b)
+		}
+		size, n := readSize(test.bytes)
+		if size != test.size {
+			t.Errorf("%d expected %d, read %d", i, test.size, size)
+		}
+		if len(test.bytes) != n {
+			t.Errorf("%d did not consume all the bytes", i)
+		}
+	}
+}
+
+var streamTests = []struct {
+	desc    string
+	recType recType
+	reqId   uint16
+	content []byte
+	raw     []byte
+}{
+	{"single record", typeStdout, 1, nil,
+		[]byte{1, byte(typeStdout), 0, 1, 0, 0, 0, 0},
+	},
+	// this data will have to be split into two records
+	{"two records", typeStdin, 300, make([]byte, 66000),
+		bytes.Join([][]byte{
+			// header for the first record
+			{1, byte(typeStdin), 0x01, 0x2C, 0xFF, 0xFF, 1, 0},
+			make([]byte, 65536),
+			// header for the second
+			{1, byte(typeStdin), 0x01, 0x2C, 0x01, 0xD1, 7, 0},
+			make([]byte, 472),
+			// header for the empty record
+			{1, byte(typeStdin), 0x01, 0x2C, 0, 0, 0, 0},
+		},
+			nil),
+	},
+}
+
+type nilCloser struct {
+	io.ReadWriter
+}
+
+func (c *nilCloser) Close() error { return nil }
+
+func TestStreams(t *testing.T) {
+	var rec record
+outer:
+	for _, test := range streamTests {
+		buf := bytes.NewBuffer(test.raw)
+		var content []byte
+		for buf.Len() > 0 {
+			if err := rec.read(buf); err != nil {
+				t.Errorf("%s: error reading record: %v", test.desc, err)
+				continue outer
+			}
+			content = append(content, rec.content()...)
+		}
+		if rec.h.Type != test.recType {
+			t.Errorf("%s: got type %d expected %d", test.desc, rec.h.Type, test.recType)
+			continue
+		}
+		if rec.h.Id != test.reqId {
+			t.Errorf("%s: got request ID %d expected %d", test.desc, rec.h.Id, test.reqId)
+			continue
+		}
+		if !bytes.Equal(content, test.content) {
+			t.Errorf("%s: read wrong content", test.desc)
+			continue
+		}
+		buf.Reset()
+		c := newConn(&nilCloser{buf})
+		w := newWriter(c, test.recType, test.reqId)
+		if _, err := w.Write(test.content); err != nil {
+			t.Errorf("%s: error writing record: %v", test.desc, err)
+			continue
+		}
+		if err := w.Close(); err != nil {
+			t.Errorf("%s: error closing stream: %v", test.desc, err)
+			continue
+		}
+		if !bytes.Equal(buf.Bytes(), test.raw) {
+			t.Errorf("%s: wrote wrong content", test.desc)
+		}
+	}
+}
+
+type writeOnlyConn struct {
+	buf []byte
+}
+
+func (c *writeOnlyConn) Write(p []byte) (int, error) {
+	c.buf = append(c.buf, p...)
+	return len(p), nil
+}
+
+func (c *writeOnlyConn) Read(p []byte) (int, error) {
+	return 0, errors.New("conn is write-only")
+}
+
+func (c *writeOnlyConn) Close() error {
+	return nil
+}
+
+func TestGetValues(t *testing.T) {
+	var rec record
+	rec.h.Type = typeGetValues
+
+	wc := new(writeOnlyConn)
+	c := newChild(wc, nil)
+	err := c.handleRecord(&rec)
+	if err != nil {
+		t.Fatalf("handleRecord: %v", err)
+	}
+
+	const want = "\x01\n\x00\x00\x00\x12\x06\x00" +
+		"\x0f\x01FCGI_MPXS_CONNS1" +
+		"\x00\x00\x00\x00\x00\x00\x01\n\x00\x00\x00\x00\x00\x00"
+	if got := string(wc.buf); got != want {
+		t.Errorf(" got: %q\nwant: %q\n", got, want)
+	}
+}
diff --git a/src/pkg/net/http/filetransport.go b/src/pkg/net/http/filetransport.go
new file mode 100644
index 0000000..821787e
--- /dev/null
+++ b/src/pkg/net/http/filetransport.go
@@ -0,0 +1,123 @@
+// Copyright 2011 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 http
+
+import (
+	"fmt"
+	"io"
+)
+
+// fileTransport implements RoundTripper for the 'file' protocol.
+type fileTransport struct {
+	fh fileHandler
+}
+
+// NewFileTransport returns a new RoundTripper, serving the provided
+// FileSystem. The returned RoundTripper ignores the URL host in its
+// incoming requests, as well as most other properties of the
+// request.
+//
+// The typical use case for NewFileTransport is to register the "file"
+// protocol with a Transport, as in:
+//
+//   t := &http.Transport{}
+//   t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
+//   c := &http.Client{Transport: t}
+//   res, err := c.Get("file:///etc/passwd")
+//   ...
+func NewFileTransport(fs FileSystem) RoundTripper {
+	return fileTransport{fileHandler{fs}}
+}
+
+func (t fileTransport) RoundTrip(req *Request) (resp *Response, err error) {
+	// We start ServeHTTP in a goroutine, which may take a long
+	// time if the file is large.  The newPopulateResponseWriter
+	// call returns a channel which either ServeHTTP or finish()
+	// sends our *Response on, once the *Response itself has been
+	// populated (even if the body itself is still being
+	// written to the res.Body, a pipe)
+	rw, resc := newPopulateResponseWriter()
+	go func() {
+		t.fh.ServeHTTP(rw, req)
+		rw.finish()
+	}()
+	return <-resc, nil
+}
+
+func newPopulateResponseWriter() (*populateResponse, <-chan *Response) {
+	pr, pw := io.Pipe()
+	rw := &populateResponse{
+		ch: make(chan *Response),
+		pw: pw,
+		res: &Response{
+			Proto:      "HTTP/1.0",
+			ProtoMajor: 1,
+			Header:     make(Header),
+			Close:      true,
+			Body:       pr,
+		},
+	}
+	return rw, rw.ch
+}
+
+// populateResponse is a ResponseWriter that populates the *Response
+// in res, and writes its body to a pipe connected to the response
+// body. Once writes begin or finish() is called, the response is sent
+// on ch.
+type populateResponse struct {
+	res          *Response
+	ch           chan *Response
+	wroteHeader  bool
+	hasContent   bool
+	sentResponse bool
+	pw           *io.PipeWriter
+}
+
+func (pr *populateResponse) finish() {
+	if !pr.wroteHeader {
+		pr.WriteHeader(500)
+	}
+	if !pr.sentResponse {
+		pr.sendResponse()
+	}
+	pr.pw.Close()
+}
+
+func (pr *populateResponse) sendResponse() {
+	if pr.sentResponse {
+		return
+	}
+	pr.sentResponse = true
+
+	if pr.hasContent {
+		pr.res.ContentLength = -1
+	}
+	pr.ch <- pr.res
+}
+
+func (pr *populateResponse) Header() Header {
+	return pr.res.Header
+}
+
+func (pr *populateResponse) WriteHeader(code int) {
+	if pr.wroteHeader {
+		return
+	}
+	pr.wroteHeader = true
+
+	pr.res.StatusCode = code
+	pr.res.Status = fmt.Sprintf("%d %s", code, StatusText(code))
+}
+
+func (pr *populateResponse) Write(p []byte) (n int, err error) {
+	if !pr.wroteHeader {
+		pr.WriteHeader(StatusOK)
+	}
+	pr.hasContent = true
+	if !pr.sentResponse {
+		pr.sendResponse()
+	}
+	return pr.pw.Write(p)
+}
diff --git a/src/pkg/net/http/filetransport_test.go b/src/pkg/net/http/filetransport_test.go
new file mode 100644
index 0000000..039926b
--- /dev/null
+++ b/src/pkg/net/http/filetransport_test.go
@@ -0,0 +1,65 @@
+// Copyright 2011 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 http_test
+
+import (
+	"io/ioutil"
+	"net/http"
+	"os"
+	"path/filepath"
+	"testing"
+)
+
+func checker(t *testing.T) func(string, error) {
+	return func(call string, err error) {
+		if err == nil {
+			return
+		}
+		t.Fatalf("%s: %v", call, err)
+	}
+}
+
+func TestFileTransport(t *testing.T) {
+	check := checker(t)
+
+	dname, err := ioutil.TempDir("", "")
+	check("TempDir", err)
+	fname := filepath.Join(dname, "foo.txt")
+	err = ioutil.WriteFile(fname, []byte("Bar"), 0644)
+	check("WriteFile", err)
+	defer os.Remove(dname)
+	defer os.Remove(fname)
+
+	tr := &http.Transport{}
+	tr.RegisterProtocol("file", http.NewFileTransport(http.Dir(dname)))
+	c := &http.Client{Transport: tr}
+
+	fooURLs := []string{"file:///foo.txt", "file://../foo.txt"}
+	for _, urlstr := range fooURLs {
+		res, err := c.Get(urlstr)
+		check("Get "+urlstr, err)
+		if res.StatusCode != 200 {
+			t.Errorf("for %s, StatusCode = %d, want 200", urlstr, res.StatusCode)
+		}
+		if res.ContentLength != -1 {
+			t.Errorf("for %s, ContentLength = %d, want -1", urlstr, res.ContentLength)
+		}
+		if res.Body == nil {
+			t.Fatalf("for %s, nil Body", urlstr)
+		}
+		slurp, err := ioutil.ReadAll(res.Body)
+		check("ReadAll "+urlstr, err)
+		if string(slurp) != "Bar" {
+			t.Errorf("for %s, got content %q, want %q", urlstr, string(slurp), "Bar")
+		}
+	}
+
+	const badURL = "file://../no-exist.txt"
+	res, err := c.Get(badURL)
+	check("Get "+badURL, err)
+	if res.StatusCode != 404 {
+		t.Errorf("for %s, StatusCode = %d, want 404", badURL, res.StatusCode)
+	}
+}
diff --git a/src/pkg/net/http/fs.go b/src/pkg/net/http/fs.go
new file mode 100644
index 0000000..1392ca6
--- /dev/null
+++ b/src/pkg/net/http/fs.go
@@ -0,0 +1,330 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// HTTP file system request handler
+
+package http
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"mime"
+	"os"
+	"path"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+	"unicode/utf8"
+)
+
+// A Dir implements http.FileSystem using the native file
+// system restricted to a specific directory tree.
+//
+// An empty Dir is treated as ".".
+type Dir string
+
+func (d Dir) Open(name string) (File, error) {
+	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 {
+		return nil, errors.New("http: invalid character in file path")
+	}
+	dir := string(d)
+	if dir == "" {
+		dir = "."
+	}
+	f, err := os.Open(filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))))
+	if err != nil {
+		return nil, err
+	}
+	return f, nil
+}
+
+// A FileSystem implements access to a collection of named files.
+// The elements in a file path are separated by slash ('/', U+002F)
+// characters, regardless of host operating system convention.
+type FileSystem interface {
+	Open(name string) (File, error)
+}
+
+// A File is returned by a FileSystem's Open method and can be
+// served by the FileServer implementation.
+type File interface {
+	Close() error
+	Stat() (os.FileInfo, error)
+	Readdir(count int) ([]os.FileInfo, error)
+	Read([]byte) (int, error)
+	Seek(offset int64, whence int) (int64, error)
+}
+
+// Heuristic: b is text if it is valid UTF-8 and doesn't
+// contain any unprintable ASCII or Unicode characters.
+func isText(b []byte) bool {
+	for len(b) > 0 && utf8.FullRune(b) {
+		rune, size := utf8.DecodeRune(b)
+		if size == 1 && rune == utf8.RuneError {
+			// decoding error
+			return false
+		}
+		if 0x7F <= rune && rune <= 0x9F {
+			return false
+		}
+		if rune < ' ' {
+			switch rune {
+			case '\n', '\r', '\t':
+				// okay
+			default:
+				// binary garbage
+				return false
+			}
+		}
+		b = b[size:]
+	}
+	return true
+}
+
+func dirList(w ResponseWriter, f File) {
+	w.Header().Set("Content-Type", "text/html; charset=utf-8")
+	fmt.Fprintf(w, "<pre>\n")
+	for {
+		dirs, err := f.Readdir(100)
+		if err != nil || len(dirs) == 0 {
+			break
+		}
+		for _, d := range dirs {
+			name := d.Name()
+			if d.IsDir() {
+				name += "/"
+			}
+			// TODO htmlescape
+			fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", name, name)
+		}
+	}
+	fmt.Fprintf(w, "</pre>\n")
+}
+
+// name is '/'-separated, not filepath.Separator.
+func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
+	const indexPage = "/index.html"
+
+	// redirect .../index.html to .../
+	// can't use Redirect() because that would make the path absolute,
+	// which would be a problem running under StripPrefix
+	if strings.HasSuffix(r.URL.Path, indexPage) {
+		localRedirect(w, r, "./")
+		return
+	}
+
+	f, err := fs.Open(name)
+	if err != nil {
+		// TODO expose actual error?
+		NotFound(w, r)
+		return
+	}
+	defer f.Close()
+
+	d, err1 := f.Stat()
+	if err1 != nil {
+		// TODO expose actual error?
+		NotFound(w, r)
+		return
+	}
+
+	if redirect {
+		// redirect to canonical path: / at end of directory url
+		// r.URL.Path always begins with /
+		url := r.URL.Path
+		if d.IsDir() {
+			if url[len(url)-1] != '/' {
+				localRedirect(w, r, path.Base(url)+"/")
+				return
+			}
+		} else {
+			if url[len(url)-1] == '/' {
+				localRedirect(w, r, "../"+path.Base(url))
+				return
+			}
+		}
+	}
+
+	if t, err := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && !d.ModTime().After(t) {
+		w.WriteHeader(StatusNotModified)
+		return
+	}
+	w.Header().Set("Last-Modified", d.ModTime().UTC().Format(TimeFormat))
+
+	// use contents of index.html for directory, if present
+	if d.IsDir() {
+		index := name + indexPage
+		ff, err := fs.Open(index)
+		if err == nil {
+			defer ff.Close()
+			dd, err := ff.Stat()
+			if err == nil {
+				name = index
+				d = dd
+				f = ff
+			}
+		}
+	}
+
+	if d.IsDir() {
+		dirList(w, f)
+		return
+	}
+
+	// serve file
+	size := d.Size()
+	code := StatusOK
+
+	// If Content-Type isn't set, use the file's extension to find it.
+	if w.Header().Get("Content-Type") == "" {
+		ctype := mime.TypeByExtension(filepath.Ext(name))
+		if ctype == "" {
+			// read a chunk to decide between utf-8 text and binary
+			var buf [1024]byte
+			n, _ := io.ReadFull(f, buf[:])
+			b := buf[:n]
+			if isText(b) {
+				ctype = "text/plain; charset=utf-8"
+			} else {
+				// generic binary
+				ctype = "application/octet-stream"
+			}
+			f.Seek(0, os.SEEK_SET) // rewind to output whole file
+		}
+		w.Header().Set("Content-Type", ctype)
+	}
+
+	// handle Content-Range header.
+	// TODO(adg): handle multiple ranges
+	ranges, err := parseRange(r.Header.Get("Range"), size)
+	if err == nil && len(ranges) > 1 {
+		err = errors.New("multiple ranges not supported")
+	}
+	if err != nil {
+		Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
+		return
+	}
+	if len(ranges) == 1 {
+		ra := ranges[0]
+		if _, err := f.Seek(ra.start, os.SEEK_SET); err != nil {
+			Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
+			return
+		}
+		size = ra.length
+		code = StatusPartialContent
+		w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", ra.start, ra.start+ra.length-1, d.Size()))
+	}
+
+	w.Header().Set("Accept-Ranges", "bytes")
+	if w.Header().Get("Content-Encoding") == "" {
+		w.Header().Set("Content-Length", strconv.FormatInt(size, 10))
+	}
+
+	w.WriteHeader(code)
+
+	if r.Method != "HEAD" {
+		io.CopyN(w, f, size)
+	}
+}
+
+// localRedirect gives a Moved Permanently response.
+// It does not convert relative paths to absolute paths like Redirect does.
+func localRedirect(w ResponseWriter, r *Request, newPath string) {
+	if q := r.URL.RawQuery; q != "" {
+		newPath += "?" + q
+	}
+	w.Header().Set("Location", newPath)
+	w.WriteHeader(StatusMovedPermanently)
+}
+
+// ServeFile replies to the request with the contents of the named file or directory.
+func ServeFile(w ResponseWriter, r *Request, name string) {
+	dir, file := filepath.Split(name)
+	serveFile(w, r, Dir(dir), file, false)
+}
+
+type fileHandler struct {
+	root FileSystem
+}
+
+// FileServer returns a handler that serves HTTP requests
+// with the contents of the file system rooted at root.
+//
+// To use the operating system's file system implementation,
+// use http.Dir:
+//
+//     http.Handle("/", http.FileServer(http.Dir("/tmp")))
+func FileServer(root FileSystem) Handler {
+	return &fileHandler{root}
+}
+
+func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	upath := r.URL.Path
+	if !strings.HasPrefix(upath, "/") {
+		upath = "/" + upath
+		r.URL.Path = upath
+	}
+	serveFile(w, r, f.root, path.Clean(upath), true)
+}
+
+// httpRange specifies the byte range to be sent to the client.
+type httpRange struct {
+	start, length int64
+}
+
+// parseRange parses a Range header string as per RFC 2616.
+func parseRange(s string, size int64) ([]httpRange, error) {
+	if s == "" {
+		return nil, nil // header not present
+	}
+	const b = "bytes="
+	if !strings.HasPrefix(s, b) {
+		return nil, errors.New("invalid range")
+	}
+	var ranges []httpRange
+	for _, ra := range strings.Split(s[len(b):], ",") {
+		i := strings.Index(ra, "-")
+		if i < 0 {
+			return nil, errors.New("invalid range")
+		}
+		start, end := ra[:i], ra[i+1:]
+		var r httpRange
+		if start == "" {
+			// If no start is specified, end specifies the
+			// range start relative to the end of the file.
+			i, err := strconv.ParseInt(end, 10, 64)
+			if err != nil {
+				return nil, errors.New("invalid range")
+			}
+			if i > size {
+				i = size
+			}
+			r.start = size - i
+			r.length = size - r.start
+		} else {
+			i, err := strconv.ParseInt(start, 10, 64)
+			if err != nil || i > size || i < 0 {
+				return nil, errors.New("invalid range")
+			}
+			r.start = i
+			if end == "" {
+				// If no end is specified, range extends to end of the file.
+				r.length = size - r.start
+			} else {
+				i, err := strconv.ParseInt(end, 10, 64)
+				if err != nil || r.start > i {
+					return nil, errors.New("invalid range")
+				}
+				if i >= size {
+					i = size - 1
+				}
+				r.length = i - r.start + 1
+			}
+		}
+		ranges = append(ranges, r)
+	}
+	return ranges, nil
+}
diff --git a/src/pkg/net/http/fs_test.go b/src/pkg/net/http/fs_test.go
new file mode 100644
index 0000000..85cad3e
--- /dev/null
+++ b/src/pkg/net/http/fs_test.go
@@ -0,0 +1,334 @@
+// Copyright 2010 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 http_test
+
+import (
+	"fmt"
+	"io/ioutil"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"os"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+const (
+	testFile       = "testdata/file"
+	testFileLength = 11
+)
+
+var ServeFileRangeTests = []struct {
+	start, end int
+	r          string
+	code       int
+}{
+	{0, testFileLength, "", StatusOK},
+	{0, 5, "0-4", StatusPartialContent},
+	{2, testFileLength, "2-", StatusPartialContent},
+	{testFileLength - 5, testFileLength, "-5", StatusPartialContent},
+	{3, 8, "3-7", StatusPartialContent},
+	{0, 0, "20-", StatusRequestedRangeNotSatisfiable},
+}
+
+func TestServeFile(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ServeFile(w, r, "testdata/file")
+	}))
+	defer ts.Close()
+
+	var err error
+
+	file, err := ioutil.ReadFile(testFile)
+	if err != nil {
+		t.Fatal("reading file:", err)
+	}
+
+	// set up the Request (re-used for all tests)
+	var req Request
+	req.Header = make(Header)
+	if req.URL, err = url.Parse(ts.URL); err != nil {
+		t.Fatal("ParseURL:", err)
+	}
+	req.Method = "GET"
+
+	// straight GET
+	_, body := getBody(t, req)
+	if !equal(body, file) {
+		t.Fatalf("body mismatch: got %q, want %q", body, file)
+	}
+
+	// Range tests
+	for _, rt := range ServeFileRangeTests {
+		req.Header.Set("Range", "bytes="+rt.r)
+		if rt.r == "" {
+			req.Header["Range"] = nil
+		}
+		r, body := getBody(t, req)
+		if r.StatusCode != rt.code {
+			t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
+		}
+		if rt.code == StatusRequestedRangeNotSatisfiable {
+			continue
+		}
+		h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
+		if rt.r == "" {
+			h = ""
+		}
+		cr := r.Header.Get("Content-Range")
+		if cr != h {
+			t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
+		}
+		if !equal(body, file[rt.start:rt.end]) {
+			t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
+		}
+	}
+}
+
+var fsRedirectTestData = []struct {
+	original, redirect string
+}{
+	{"/test/index.html", "/test/"},
+	{"/test/testdata", "/test/testdata/"},
+	{"/test/testdata/file/", "/test/testdata/file"},
+}
+
+func TestFSRedirect(t *testing.T) {
+	ts := httptest.NewServer(StripPrefix("/test", FileServer(Dir("."))))
+	defer ts.Close()
+
+	for _, data := range fsRedirectTestData {
+		res, err := Get(ts.URL + data.original)
+		if err != nil {
+			t.Fatal(err)
+		}
+		res.Body.Close()
+		if g, e := res.Request.URL.Path, data.redirect; g != e {
+			t.Errorf("redirect from %s: got %s, want %s", data.original, g, e)
+		}
+	}
+}
+
+type testFileSystem struct {
+	open func(name string) (File, error)
+}
+
+func (fs *testFileSystem) Open(name string) (File, error) {
+	return fs.open(name)
+}
+
+func TestFileServerCleans(t *testing.T) {
+	ch := make(chan string, 1)
+	fs := FileServer(&testFileSystem{func(name string) (File, error) {
+		ch <- name
+		return nil, os.ENOENT
+	}})
+	tests := []struct {
+		reqPath, openArg string
+	}{
+		{"/foo.txt", "/foo.txt"},
+		{"//foo.txt", "/foo.txt"},
+		{"/../foo.txt", "/foo.txt"},
+	}
+	req, _ := NewRequest("GET", "http://example.com", nil)
+	for n, test := range tests {
+		rec := httptest.NewRecorder()
+		req.URL.Path = test.reqPath
+		fs.ServeHTTP(rec, req)
+		if got := <-ch; got != test.openArg {
+			t.Errorf("test %d: got %q, want %q", n, got, test.openArg)
+		}
+	}
+}
+
+func TestFileServerImplicitLeadingSlash(t *testing.T) {
+	tempDir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatalf("TempDir: %v", err)
+	}
+	defer os.RemoveAll(tempDir)
+	if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
+		t.Fatalf("WriteFile: %v", err)
+	}
+	ts := httptest.NewServer(StripPrefix("/bar/", FileServer(Dir(tempDir))))
+	defer ts.Close()
+	get := func(suffix string) string {
+		res, err := Get(ts.URL + suffix)
+		if err != nil {
+			t.Fatalf("Get %s: %v", suffix, err)
+		}
+		b, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatalf("ReadAll %s: %v", suffix, err)
+		}
+		return string(b)
+	}
+	if s := get("/bar/"); !strings.Contains(s, ">foo.txt<") {
+		t.Logf("expected a directory listing with foo.txt, got %q", s)
+	}
+	if s := get("/bar/foo.txt"); s != "Hello world" {
+		t.Logf("expected %q, got %q", "Hello world", s)
+	}
+}
+
+func TestDirJoin(t *testing.T) {
+	wfi, err := os.Stat("/etc/hosts")
+	if err != nil {
+		t.Logf("skipping test; no /etc/hosts file")
+		return
+	}
+	test := func(d Dir, name string) {
+		f, err := d.Open(name)
+		if err != nil {
+			t.Fatalf("open of %s: %v", name, err)
+		}
+		defer f.Close()
+		gfi, err := f.Stat()
+		if err != nil {
+			t.Fatalf("stat of %s: %v", name, err)
+		}
+		if !gfi.(*os.FileStat).SameFile(wfi.(*os.FileStat)) {
+			t.Errorf("%s got different file", name)
+		}
+	}
+	test(Dir("/etc/"), "/hosts")
+	test(Dir("/etc/"), "hosts")
+	test(Dir("/etc/"), "../../../../hosts")
+	test(Dir("/etc"), "/hosts")
+	test(Dir("/etc"), "hosts")
+	test(Dir("/etc"), "../../../../hosts")
+
+	// Not really directories, but since we use this trick in
+	// ServeFile, test it:
+	test(Dir("/etc/hosts"), "")
+	test(Dir("/etc/hosts"), "/")
+	test(Dir("/etc/hosts"), "../")
+}
+
+func TestEmptyDirOpenCWD(t *testing.T) {
+	test := func(d Dir) {
+		name := "fs_test.go"
+		f, err := d.Open(name)
+		if err != nil {
+			t.Fatalf("open of %s: %v", name, err)
+		}
+		defer f.Close()
+	}
+	test(Dir(""))
+	test(Dir("."))
+	test(Dir("./"))
+}
+
+func TestServeFileContentType(t *testing.T) {
+	const ctype = "icecream/chocolate"
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.FormValue("override") == "1" {
+			w.Header().Set("Content-Type", ctype)
+		}
+		ServeFile(w, r, "testdata/file")
+	}))
+	defer ts.Close()
+	get := func(override, want string) {
+		resp, err := Get(ts.URL + "?override=" + override)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if h := resp.Header.Get("Content-Type"); h != want {
+			t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
+		}
+	}
+	get("0", "text/plain; charset=utf-8")
+	get("1", ctype)
+}
+
+func TestServeFileMimeType(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ServeFile(w, r, "testdata/style.css")
+	}))
+	defer ts.Close()
+	resp, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	want := "text/css; charset=utf-8"
+	if h := resp.Header.Get("Content-Type"); h != want {
+		t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
+	}
+}
+
+func TestServeFileFromCWD(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ServeFile(w, r, "fs_test.go")
+	}))
+	defer ts.Close()
+	r, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if r.StatusCode != 200 {
+		t.Fatalf("expected 200 OK, got %s", r.Status)
+	}
+}
+
+func TestServeFileWithContentEncoding(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Encoding", "foo")
+		ServeFile(w, r, "testdata/file")
+	}))
+	defer ts.Close()
+	resp, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, e := resp.ContentLength, int64(-1); g != e {
+		t.Errorf("Content-Length mismatch: got %d, want %d", g, e)
+	}
+}
+
+func TestServeIndexHtml(t *testing.T) {
+	const want = "index.html says hello\n"
+	ts := httptest.NewServer(FileServer(Dir(".")))
+	defer ts.Close()
+
+	for _, path := range []string{"/testdata/", "/testdata/index.html"} {
+		res, err := Get(ts.URL + path)
+		if err != nil {
+			t.Fatal(err)
+		}
+		defer res.Body.Close()
+		b, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal("reading Body:", err)
+		}
+		if s := string(b); s != want {
+			t.Errorf("for path %q got %q, want %q", path, s, want)
+		}
+	}
+}
+
+func getBody(t *testing.T, req Request) (*Response, []byte) {
+	r, err := DefaultClient.Do(&req)
+	if err != nil {
+		t.Fatal(req.URL.String(), "send:", err)
+	}
+	b, err := ioutil.ReadAll(r.Body)
+	if err != nil {
+		t.Fatal("reading Body:", err)
+	}
+	return r, b
+}
+
+func equal(a, b []byte) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i := range a {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
diff --git a/src/pkg/net/http/header.go b/src/pkg/net/http/header.go
new file mode 100644
index 0000000..b107c31
--- /dev/null
+++ b/src/pkg/net/http/header.go
@@ -0,0 +1,78 @@
+// Copyright 2010 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 http
+
+import (
+	"fmt"
+	"io"
+	"net/textproto"
+	"sort"
+	"strings"
+)
+
+// A Header represents the key-value pairs in an HTTP header.
+type Header map[string][]string
+
+// Add adds the key, value pair to the header.
+// It appends to any existing values associated with key.
+func (h Header) Add(key, value string) {
+	textproto.MIMEHeader(h).Add(key, value)
+}
+
+// Set sets the header entries associated with key to
+// the single element value.  It replaces any existing
+// values associated with key.
+func (h Header) Set(key, value string) {
+	textproto.MIMEHeader(h).Set(key, value)
+}
+
+// Get gets the first value associated with the given key.
+// If there are no values associated with the key, Get returns "".
+// To access multiple values of a key, access the map directly
+// with CanonicalHeaderKey.
+func (h Header) Get(key string) string {
+	return textproto.MIMEHeader(h).Get(key)
+}
+
+// Del deletes the values associated with key.
+func (h Header) Del(key string) {
+	textproto.MIMEHeader(h).Del(key)
+}
+
+// Write writes a header in wire format.
+func (h Header) Write(w io.Writer) error {
+	return h.WriteSubset(w, nil)
+}
+
+var headerNewlineToSpace = strings.NewReplacer("\n", " ", "\r", " ")
+
+// WriteSubset writes a header in wire format.
+// If exclude is not nil, keys where exclude[key] == true are not written.
+func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
+	keys := make([]string, 0, len(h))
+	for k := range h {
+		if exclude == nil || !exclude[k] {
+			keys = append(keys, k)
+		}
+	}
+	sort.Strings(keys)
+	for _, k := range keys {
+		for _, v := range h[k] {
+			v = headerNewlineToSpace.Replace(v)
+			v = strings.TrimSpace(v)
+			if _, err := fmt.Fprintf(w, "%s: %s\r\n", k, v); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+// CanonicalHeaderKey returns the canonical format of the
+// header key s.  The canonicalization converts the first
+// letter and any letter following a hyphen to upper case;
+// the rest are converted to lowercase.  For example, the
+// canonical key for "accept-encoding" is "Accept-Encoding".
+func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
diff --git a/src/pkg/http/header_test.go b/src/pkg/net/http/header_test.go
similarity index 100%
rename from src/pkg/http/header_test.go
rename to src/pkg/net/http/header_test.go
diff --git a/src/pkg/net/http/httptest/Makefile b/src/pkg/net/http/httptest/Makefile
new file mode 100644
index 0000000..3bb4454
--- /dev/null
+++ b/src/pkg/net/http/httptest/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../../Make.inc
+
+TARG=net/http/httptest
+GOFILES=\
+	recorder.go\
+	server.go\
+
+include ../../../../Make.pkg
diff --git a/src/pkg/net/http/httptest/recorder.go b/src/pkg/net/http/httptest/recorder.go
new file mode 100644
index 0000000..9aa0d51
--- /dev/null
+++ b/src/pkg/net/http/httptest/recorder.go
@@ -0,0 +1,58 @@
+// Copyright 2011 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 httptest provides utilities for HTTP testing.
+package httptest
+
+import (
+	"bytes"
+	"net/http"
+)
+
+// ResponseRecorder is an implementation of http.ResponseWriter that
+// records its mutations for later inspection in tests.
+type ResponseRecorder struct {
+	Code      int           // the HTTP response code from WriteHeader
+	HeaderMap http.Header   // the HTTP response headers
+	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
+	Flushed   bool
+}
+
+// NewRecorder returns an initialized ResponseRecorder.
+func NewRecorder() *ResponseRecorder {
+	return &ResponseRecorder{
+		HeaderMap: make(http.Header),
+		Body:      new(bytes.Buffer),
+	}
+}
+
+// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
+// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
+const DefaultRemoteAddr = "1.2.3.4"
+
+// Header returns the response headers.
+func (rw *ResponseRecorder) Header() http.Header {
+	return rw.HeaderMap
+}
+
+// Write always succeeds and writes to rw.Body, if not nil.
+func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
+	if rw.Body != nil {
+		rw.Body.Write(buf)
+	}
+	if rw.Code == 0 {
+		rw.Code = http.StatusOK
+	}
+	return len(buf), nil
+}
+
+// WriteHeader sets rw.Code.
+func (rw *ResponseRecorder) WriteHeader(code int) {
+	rw.Code = code
+}
+
+// Flush sets rw.Flushed to true.
+func (rw *ResponseRecorder) Flush() {
+	rw.Flushed = true
+}
diff --git a/src/pkg/net/http/httptest/server.go b/src/pkg/net/http/httptest/server.go
new file mode 100644
index 0000000..5b02e14
--- /dev/null
+++ b/src/pkg/net/http/httptest/server.go
@@ -0,0 +1,173 @@
+// Copyright 2011 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.
+
+// Implementation of Server
+
+package httptest
+
+import (
+	"crypto/tls"
+	"flag"
+	"fmt"
+	"net"
+	"net/http"
+	"os"
+)
+
+// A Server is an HTTP server listening on a system-chosen port on the
+// local loopback interface, for use in end-to-end HTTP tests.
+type Server struct {
+	URL      string // base URL of form http://ipaddr:port with no trailing slash
+	Listener net.Listener
+	TLS      *tls.Config // nil if not using using TLS
+
+	// Config may be changed after calling NewUnstartedServer and
+	// before Start or StartTLS.
+	Config *http.Server
+}
+
+// historyListener keeps track of all connections that it's ever
+// accepted.
+type historyListener struct {
+	net.Listener
+	history []net.Conn
+}
+
+func (hs *historyListener) Accept() (c net.Conn, err error) {
+	c, err = hs.Listener.Accept()
+	if err == nil {
+		hs.history = append(hs.history, c)
+	}
+	return
+}
+
+func newLocalListener() net.Listener {
+	if *serve != "" {
+		l, err := net.Listen("tcp", *serve)
+		if err != nil {
+			panic(fmt.Sprintf("httptest: failed to listen on %v: %v", *serve, err))
+		}
+		return l
+	}
+	l, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
+			panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
+		}
+	}
+	return l
+}
+
+// When debugging a particular http server-based test,
+// this flag lets you run
+//	gotest -run=BrokenTest -httptest.serve=127.0.0.1:8000
+// to start the broken server so you can interact with it manually.
+var serve = flag.String("httptest.serve", "", "if non-empty, httptest.NewServer serves on this address and blocks")
+
+// NewServer starts and returns a new Server.
+// The caller should call Close when finished, to shut it down.
+func NewServer(handler http.Handler) *Server {
+	ts := NewUnstartedServer(handler)
+	ts.Start()
+	return ts
+}
+
+// NewUnstartedServer returns a new Server but doesn't start it.
+//
+// After changing its configuration, the caller should call Start or
+// StartTLS.
+//
+// The caller should call Close when finished, to shut it down.
+func NewUnstartedServer(handler http.Handler) *Server {
+	return &Server{
+		Listener: newLocalListener(),
+		Config:   &http.Server{Handler: handler},
+	}
+}
+
+// Start starts a server from NewUnstartedServer.
+func (s *Server) Start() {
+	if s.URL != "" {
+		panic("Server already started")
+	}
+	s.Listener = &historyListener{s.Listener, make([]net.Conn, 0)}
+	s.URL = "http://" + s.Listener.Addr().String()
+	go s.Config.Serve(s.Listener)
+	if *serve != "" {
+		fmt.Println(os.Stderr, "httptest: serving on", s.URL)
+		select {}
+	}
+}
+
+// StartTLS starts TLS on a server from NewUnstartedServer.
+func (s *Server) StartTLS() {
+	if s.URL != "" {
+		panic("Server already started")
+	}
+	cert, err := tls.X509KeyPair(localhostCert, localhostKey)
+	if err != nil {
+		panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
+	}
+
+	s.TLS = &tls.Config{
+		NextProtos:   []string{"http/1.1"},
+		Certificates: []tls.Certificate{cert},
+	}
+	tlsListener := tls.NewListener(s.Listener, s.TLS)
+
+	s.Listener = &historyListener{tlsListener, make([]net.Conn, 0)}
+	s.URL = "https://" + s.Listener.Addr().String()
+	go s.Config.Serve(s.Listener)
+}
+
+// NewTLSServer starts and returns a new Server using TLS.
+// The caller should call Close when finished, to shut it down.
+func NewTLSServer(handler http.Handler) *Server {
+	ts := NewUnstartedServer(handler)
+	ts.StartTLS()
+	return ts
+}
+
+// Close shuts down the server.
+func (s *Server) Close() {
+	s.Listener.Close()
+}
+
+// CloseClientConnections closes any currently open HTTP connections
+// to the test Server.
+func (s *Server) CloseClientConnections() {
+	hl, ok := s.Listener.(*historyListener)
+	if !ok {
+		return
+	}
+	for _, conn := range hl.history {
+		conn.Close()
+	}
+}
+
+// localhostCert is a PEM-encoded TLS cert with SAN DNS names
+// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
+// of ASN.1 time).
+var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIBOTCB5qADAgECAgEAMAsGCSqGSIb3DQEBBTAAMB4XDTcwMDEwMTAwMDAwMFoX
+DTQ5MTIzMTIzNTk1OVowADBaMAsGCSqGSIb3DQEBAQNLADBIAkEAsuA5mAFMj6Q7
+qoBzcvKzIq4kzuT5epSp2AkcQfyBHm7K13Ws7u+0b5Vb9gqTf5cAiIKcrtrXVqkL
+8i1UQF6AzwIDAQABo08wTTAOBgNVHQ8BAf8EBAMCACQwDQYDVR0OBAYEBAECAwQw
+DwYDVR0jBAgwBoAEAQIDBDAbBgNVHREEFDASggkxMjcuMC4wLjGCBVs6OjFdMAsG
+CSqGSIb3DQEBBQNBAJH30zjLWRztrWpOCgJL8RQWLaKzhK79pVhAx6q/3NrF16C7
++l1BRZstTwIGdoGId8BRpErK1TXkniFb95ZMynM=
+-----END CERTIFICATE-----
+`)
+
+// localhostKey is the private key for localhostCert.
+var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIBPQIBAAJBALLgOZgBTI+kO6qAc3LysyKuJM7k+XqUqdgJHEH8gR5uytd1rO7v
+tG+VW/YKk3+XAIiCnK7a11apC/ItVEBegM8CAwEAAQJBAI5sxq7naeR9ahyqRkJi
+SIv2iMxLuPEHaezf5CYOPWjSjBPyVhyRevkhtqEjF/WkgL7C2nWpYHsUcBDBQVF0
+3KECIQDtEGB2ulnkZAahl3WuJziXGLB+p8Wgx7wzSM6bHu1c6QIhAMEp++CaS+SJ
+/TrU0zwY/fW4SvQeb49BPZUF3oqR8Xz3AiEA1rAJHBzBgdOQKdE3ksMUPcnvNJSN
+poCcELmz2clVXtkCIQCLytuLV38XHToTipR4yMl6O+6arzAjZ56uq7m7ZRV0TwIh
+AM65XAOw8Dsg9Kq78aYXiOEDc5DL0sbFUu/SlmRcCg93
+-----END RSA PRIVATE KEY-----
+`)
diff --git a/src/pkg/net/http/httputil/Makefile b/src/pkg/net/http/httputil/Makefile
new file mode 100644
index 0000000..8bfc7a0
--- /dev/null
+++ b/src/pkg/net/http/httputil/Makefile
@@ -0,0 +1,14 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../../Make.inc
+
+TARG=net/http/httputil
+GOFILES=\
+	chunked.go\
+	dump.go\
+	persist.go\
+	reverseproxy.go\
+
+include ../../../../Make.pkg
diff --git a/src/pkg/net/http/httputil/chunked.go b/src/pkg/net/http/httputil/chunked.go
new file mode 100644
index 0000000..29eaf34
--- /dev/null
+++ b/src/pkg/net/http/httputil/chunked.go
@@ -0,0 +1,172 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The wire protocol for HTTP's "chunked" Transfer-Encoding.
+
+// This code is a duplicate of ../chunked.go with these edits:
+//	s/newChunked/NewChunked/g
+//	s/package http/package httputil/
+// Please make any changes in both files.
+
+package httputil
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"io"
+	"strconv"
+)
+
+const maxLineLength = 4096 // assumed <= bufio.defaultBufSize
+
+var ErrLineTooLong = errors.New("header line too long")
+
+// NewChunkedReader returns a new chunkedReader that translates the data read from r
+// out of HTTP "chunked" format before returning it. 
+// The chunkedReader returns io.EOF when the final 0-length chunk is read.
+//
+// NewChunkedReader is not needed by normal applications. The http package
+// automatically decodes chunking when reading response bodies.
+func NewChunkedReader(r io.Reader) io.Reader {
+	br, ok := r.(*bufio.Reader)
+	if !ok {
+		br = bufio.NewReader(r)
+	}
+	return &chunkedReader{r: br}
+}
+
+type chunkedReader struct {
+	r   *bufio.Reader
+	n   uint64 // unread bytes in chunk
+	err error
+}
+
+func (cr *chunkedReader) beginChunk() {
+	// chunk-size CRLF
+	var line string
+	line, cr.err = readLine(cr.r)
+	if cr.err != nil {
+		return
+	}
+	cr.n, cr.err = strconv.ParseUint(line, 16, 64)
+	if cr.err != nil {
+		return
+	}
+	if cr.n == 0 {
+		cr.err = io.EOF
+	}
+}
+
+func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
+	if cr.err != nil {
+		return 0, cr.err
+	}
+	if cr.n == 0 {
+		cr.beginChunk()
+		if cr.err != nil {
+			return 0, cr.err
+		}
+	}
+	if uint64(len(b)) > cr.n {
+		b = b[0:cr.n]
+	}
+	n, cr.err = cr.r.Read(b)
+	cr.n -= uint64(n)
+	if cr.n == 0 && cr.err == nil {
+		// end of chunk (CRLF)
+		b := make([]byte, 2)
+		if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
+			if b[0] != '\r' || b[1] != '\n' {
+				cr.err = errors.New("malformed chunked encoding")
+			}
+		}
+	}
+	return n, cr.err
+}
+
+// Read a line of bytes (up to \n) from b.
+// Give up if the line exceeds maxLineLength.
+// The returned bytes are a pointer into storage in
+// the bufio, so they are only valid until the next bufio read.
+func readLineBytes(b *bufio.Reader) (p []byte, err error) {
+	if p, err = b.ReadSlice('\n'); err != nil {
+		// We always know when EOF is coming.
+		// If the caller asked for a line, there should be a line.
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		} else if err == bufio.ErrBufferFull {
+			err = ErrLineTooLong
+		}
+		return nil, err
+	}
+	if len(p) >= maxLineLength {
+		return nil, ErrLineTooLong
+	}
+
+	// Chop off trailing white space.
+	p = bytes.TrimRight(p, " \r\t\n")
+
+	return p, nil
+}
+
+// readLineBytes, but convert the bytes into a string.
+func readLine(b *bufio.Reader) (s string, err error) {
+	p, e := readLineBytes(b)
+	if e != nil {
+		return "", e
+	}
+	return string(p), nil
+}
+
+// NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
+// "chunked" format before writing them to w. Closing the returned chunkedWriter
+// sends the final 0-length chunk that marks the end of the stream.
+//
+// NewChunkedWriter is not needed by normal applications. The http
+// package adds chunking automatically if handlers don't set a
+// Content-Length header. Using NewChunkedWriter inside a handler
+// would result in double chunking or chunking with a Content-Length
+// length, both of which are wrong.
+func NewChunkedWriter(w io.Writer) io.WriteCloser {
+	return &chunkedWriter{w}
+}
+
+// Writing to chunkedWriter translates to writing in HTTP chunked Transfer
+// Encoding wire format to the underlying Wire chunkedWriter.
+type chunkedWriter struct {
+	Wire io.Writer
+}
+
+// Write the contents of data as one chunk to Wire.
+// NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
+// a bug since it does not check for success of io.WriteString
+func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
+
+	// Don't send 0-length data. It looks like EOF for chunked encoding.
+	if len(data) == 0 {
+		return 0, nil
+	}
+
+	head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
+
+	if _, err = io.WriteString(cw.Wire, head); err != nil {
+		return 0, err
+	}
+	if n, err = cw.Wire.Write(data); err != nil {
+		return
+	}
+	if n != len(data) {
+		err = io.ErrShortWrite
+		return
+	}
+	_, err = io.WriteString(cw.Wire, "\r\n")
+
+	return
+}
+
+func (cw *chunkedWriter) Close() error {
+	_, err := io.WriteString(cw.Wire, "0\r\n")
+	return err
+}
diff --git a/src/pkg/net/http/httputil/chunked_test.go b/src/pkg/net/http/httputil/chunked_test.go
new file mode 100644
index 0000000..155a32b
--- /dev/null
+++ b/src/pkg/net/http/httputil/chunked_test.go
@@ -0,0 +1,41 @@
+// Copyright 2011 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 code is a duplicate of ../chunked_test.go with these edits:
+//	s/newChunked/NewChunked/g
+//	s/package http/package httputil/
+// Please make any changes in both files.
+
+package httputil
+
+import (
+	"bytes"
+	"io/ioutil"
+	"testing"
+)
+
+func TestChunk(t *testing.T) {
+	var b bytes.Buffer
+
+	w := NewChunkedWriter(&b)
+	const chunk1 = "hello, "
+	const chunk2 = "world! 0123456789abcdef"
+	w.Write([]byte(chunk1))
+	w.Write([]byte(chunk2))
+	w.Close()
+
+	if g, e := b.String(), "7\r\nhello, \r\n17\r\nworld! 0123456789abcdef\r\n0\r\n"; g != e {
+		t.Fatalf("chunk writer wrote %q; want %q", g, e)
+	}
+
+	r := NewChunkedReader(&b)
+	data, err := ioutil.ReadAll(r)
+	if err != nil {
+		t.Logf(`data: "%s"`, data)
+		t.Fatalf("ReadAll from reader: %v", err)
+	}
+	if g, e := string(data), chunk1+chunk2; g != e {
+		t.Errorf("chunk reader read %q; want %q", g, e)
+	}
+}
diff --git a/src/pkg/net/http/httputil/dump.go b/src/pkg/net/http/httputil/dump.go
new file mode 100644
index 0000000..b8a98ee
--- /dev/null
+++ b/src/pkg/net/http/httputil/dump.go
@@ -0,0 +1,196 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package httputil
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"strings"
+	"time"
+)
+
+// One of the copies, say from b to r2, could be avoided by using a more
+// elaborate trick where the other copy is made during Request/Response.Write.
+// This would complicate things too much, given that these functions are for
+// debugging only.
+func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
+	var buf bytes.Buffer
+	if _, err = buf.ReadFrom(b); err != nil {
+		return nil, nil, err
+	}
+	if err = b.Close(); err != nil {
+		return nil, nil, err
+	}
+	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewBuffer(buf.Bytes())), nil
+}
+
+// dumpConn is a net.Conn which writes to Writer and reads from Reader
+type dumpConn struct {
+	io.Writer
+	io.Reader
+}
+
+func (c *dumpConn) Close() error                       { return nil }
+func (c *dumpConn) LocalAddr() net.Addr                { return nil }
+func (c *dumpConn) RemoteAddr() net.Addr               { return nil }
+func (c *dumpConn) SetDeadline(t time.Time) error      { return nil }
+func (c *dumpConn) SetReadDeadline(t time.Time) error  { return nil }
+func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
+
+// DumpRequestOut is like DumpRequest but includes
+// headers that the standard http.Transport adds,
+// such as User-Agent.
+func DumpRequestOut(req *http.Request, body bool) (dump []byte, err error) {
+	save := req.Body
+	if !body || req.Body == nil {
+		req.Body = nil
+	} else {
+		save, req.Body, err = drainBody(req.Body)
+		if err != nil {
+			return
+		}
+	}
+
+	var b bytes.Buffer
+	dialed := false
+	t := &http.Transport{
+		Dial: func(net, addr string) (c net.Conn, err error) {
+			if dialed {
+				return nil, errors.New("unexpected second dial")
+			}
+			c = &dumpConn{
+				Writer: &b,
+				Reader: strings.NewReader("HTTP/1.1 500 Fake Error\r\n\r\n"),
+			}
+			return
+		},
+	}
+
+	_, err = t.RoundTrip(req)
+
+	req.Body = save
+	if err != nil {
+		return
+	}
+	dump = b.Bytes()
+	return
+}
+
+// Return value if nonempty, def otherwise.
+func valueOrDefault(value, def string) string {
+	if value != "" {
+		return value
+	}
+	return def
+}
+
+var reqWriteExcludeHeaderDump = map[string]bool{
+	"Host":              true, // not in Header map anyway
+	"Content-Length":    true,
+	"Transfer-Encoding": true,
+	"Trailer":           true,
+}
+
+// dumpAsReceived writes req to w in the form as it was received, or
+// at least as accurately as possible from the information retained in
+// the request.
+func dumpAsReceived(req *http.Request, w io.Writer) error {
+	return nil
+}
+
+// DumpRequest returns the as-received wire representation of req,
+// optionally including the request body, for debugging.
+// DumpRequest is semantically a no-op, but in order to
+// dump the body, it reads the body data into memory and
+// changes req.Body to refer to the in-memory copy.
+// The documentation for http.Request.Write details which fields
+// of req are used.
+func DumpRequest(req *http.Request, body bool) (dump []byte, err error) {
+	save := req.Body
+	if !body || req.Body == nil {
+		req.Body = nil
+	} else {
+		save, req.Body, err = drainBody(req.Body)
+		if err != nil {
+			return
+		}
+	}
+
+	var b bytes.Buffer
+
+	fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"),
+		req.URL.RequestURI(), req.ProtoMajor, req.ProtoMinor)
+
+	host := req.Host
+	if host == "" && req.URL != nil {
+		host = req.URL.Host
+	}
+	if host != "" {
+		fmt.Fprintf(&b, "Host: %s\r\n", host)
+	}
+
+	chunked := len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked"
+	if len(req.TransferEncoding) > 0 {
+		fmt.Fprintf(&b, "Transfer-Encoding: %s\r\n", strings.Join(req.TransferEncoding, ","))
+	}
+	if req.Close {
+		fmt.Fprintf(&b, "Connection: close\r\n")
+	}
+
+	err = req.Header.WriteSubset(&b, reqWriteExcludeHeaderDump)
+	if err != nil {
+		return
+	}
+
+	io.WriteString(&b, "\r\n")
+
+	if req.Body != nil {
+		var dest io.Writer = &b
+		if chunked {
+			dest = NewChunkedWriter(dest)
+		}
+		_, err = io.Copy(dest, req.Body)
+		if chunked {
+			dest.(io.Closer).Close()
+			io.WriteString(&b, "\r\n")
+		}
+	}
+
+	req.Body = save
+	if err != nil {
+		return
+	}
+	dump = b.Bytes()
+	return
+}
+
+// DumpResponse is like DumpRequest but dumps a response.
+func DumpResponse(resp *http.Response, body bool) (dump []byte, err error) {
+	var b bytes.Buffer
+	save := resp.Body
+	savecl := resp.ContentLength
+	if !body || resp.Body == nil {
+		resp.Body = nil
+		resp.ContentLength = 0
+	} else {
+		save, resp.Body, err = drainBody(resp.Body)
+		if err != nil {
+			return
+		}
+	}
+	err = resp.Write(&b)
+	resp.Body = save
+	resp.ContentLength = savecl
+	if err != nil {
+		return
+	}
+	dump = b.Bytes()
+	return
+}
diff --git a/src/pkg/net/http/httputil/dump_test.go b/src/pkg/net/http/httputil/dump_test.go
new file mode 100644
index 0000000..819efb5
--- /dev/null
+++ b/src/pkg/net/http/httputil/dump_test.go
@@ -0,0 +1,140 @@
+// Copyright 2011 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 httputil
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"testing"
+)
+
+type dumpTest struct {
+	Req  http.Request
+	Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
+
+	WantDump    string
+	WantDumpOut string
+}
+
+var dumpTests = []dumpTest{
+
+	// HTTP/1.1 => chunked coding; body; empty trailer
+	{
+		Req: http.Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			TransferEncoding: []string{"chunked"},
+		},
+
+		Body: []byte("abcdef"),
+
+		WantDump: "GET /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+	},
+
+	// Verify that DumpRequest preserves the HTTP version number, doesn't add a Host,
+	// and doesn't add a User-Agent.
+	{
+		Req: http.Request{
+			Method:     "GET",
+			URL:        mustParseURL("/foo"),
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Header: http.Header{
+				"X-Foo": []string{"X-Bar"},
+			},
+		},
+
+		WantDump: "GET /foo HTTP/1.0\r\n" +
+			"X-Foo: X-Bar\r\n\r\n",
+	},
+
+	{
+		Req: *mustNewRequest("GET", "http://example.com/foo", nil),
+
+		WantDumpOut: "GET /foo HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Accept-Encoding: gzip\r\n\r\n",
+	},
+}
+
+func TestDumpRequest(t *testing.T) {
+	for i, tt := range dumpTests {
+		setBody := func() {
+			if tt.Body == nil {
+				return
+			}
+			switch b := tt.Body.(type) {
+			case []byte:
+				tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
+			case func() io.ReadCloser:
+				tt.Req.Body = b()
+			}
+		}
+		setBody()
+		if tt.Req.Header == nil {
+			tt.Req.Header = make(http.Header)
+		}
+
+		if tt.WantDump != "" {
+			setBody()
+			dump, err := DumpRequest(&tt.Req, true)
+			if err != nil {
+				t.Errorf("DumpRequest #%d: %s", i, err)
+				continue
+			}
+			if string(dump) != tt.WantDump {
+				t.Errorf("DumpRequest %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantDump, string(dump))
+				continue
+			}
+		}
+
+		if tt.WantDumpOut != "" {
+			setBody()
+			dump, err := DumpRequestOut(&tt.Req, true)
+			if err != nil {
+				t.Errorf("DumpRequestOut #%d: %s", i, err)
+				continue
+			}
+			if string(dump) != tt.WantDumpOut {
+				t.Errorf("DumpRequestOut %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantDumpOut, string(dump))
+				continue
+			}
+		}
+	}
+}
+
+func chunk(s string) string {
+	return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
+}
+
+func mustParseURL(s string) *url.URL {
+	u, err := url.Parse(s)
+	if err != nil {
+		panic(fmt.Sprintf("Error parsing URL %q: %v", s, err))
+	}
+	return u
+}
+
+func mustNewRequest(method, url string, body io.Reader) *http.Request {
+	req, err := http.NewRequest(method, url, body)
+	if err != nil {
+		panic(fmt.Sprintf("NewRequest(%q, %q, %p) err = %v", method, url, body, err))
+	}
+	return req
+}
diff --git a/src/pkg/net/http/httputil/persist.go b/src/pkg/net/http/httputil/persist.go
new file mode 100644
index 0000000..1266bd3
--- /dev/null
+++ b/src/pkg/net/http/httputil/persist.go
@@ -0,0 +1,422 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package httputil provides HTTP utility functions, complementing the
+// more common ones in the net/http package.
+package httputil
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"net"
+	"net/http"
+	"net/textproto"
+	"os"
+	"sync"
+)
+
+var (
+	ErrPersistEOF = &http.ProtocolError{"persistent connection closed"}
+	ErrPipeline   = &http.ProtocolError{"pipeline error"}
+)
+
+// This is an API usage error - the local side is closed.
+// ErrPersistEOF (above) reports that the remote side is closed.
+var errClosed = errors.New("i/o operation on closed connection")
+
+// A ServerConn reads requests and sends responses over an underlying
+// connection, until the HTTP keepalive logic commands an end. ServerConn
+// also allows hijacking the underlying connection by calling Hijack
+// to regain control over the connection. ServerConn supports pipe-lining,
+// i.e. requests can be read out of sync (but in the same order) while the
+// respective responses are sent.
+//
+// ServerConn is low-level and should not be needed by most applications.
+// See Server.
+type ServerConn struct {
+	lk              sync.Mutex // read-write protects the following fields
+	c               net.Conn
+	r               *bufio.Reader
+	re, we          error // read/write errors
+	lastbody        io.ReadCloser
+	nread, nwritten int
+	pipereq         map[*http.Request]uint
+
+	pipe textproto.Pipeline
+}
+
+// NewServerConn returns a new ServerConn reading and writing c.  If r is not
+// nil, it is the buffer to use when reading c.
+func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn {
+	if r == nil {
+		r = bufio.NewReader(c)
+	}
+	return &ServerConn{c: c, r: r, pipereq: make(map[*http.Request]uint)}
+}
+
+// Hijack detaches the ServerConn and returns the underlying connection as well
+// as the read-side bufio which may have some left over data. Hijack may be
+// called before Read has signaled the end of the keep-alive logic. The user
+// should not call Hijack while Read or Write is in progress.
+func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
+	sc.lk.Lock()
+	defer sc.lk.Unlock()
+	c = sc.c
+	r = sc.r
+	sc.c = nil
+	sc.r = nil
+	return
+}
+
+// Close calls Hijack and then also closes the underlying connection
+func (sc *ServerConn) Close() error {
+	c, _ := sc.Hijack()
+	if c != nil {
+		return c.Close()
+	}
+	return nil
+}
+
+// Read returns the next request on the wire. An ErrPersistEOF is returned if
+// it is gracefully determined that there are no more requests (e.g. after the
+// first request on an HTTP/1.0 connection, or after a Connection:close on a
+// HTTP/1.1 connection).
+func (sc *ServerConn) Read() (req *http.Request, err error) {
+
+	// Ensure ordered execution of Reads and Writes
+	id := sc.pipe.Next()
+	sc.pipe.StartRequest(id)
+	defer func() {
+		sc.pipe.EndRequest(id)
+		if req == nil {
+			sc.pipe.StartResponse(id)
+			sc.pipe.EndResponse(id)
+		} else {
+			// Remember the pipeline id of this request
+			sc.lk.Lock()
+			sc.pipereq[req] = id
+			sc.lk.Unlock()
+		}
+	}()
+
+	sc.lk.Lock()
+	if sc.we != nil { // no point receiving if write-side broken or closed
+		defer sc.lk.Unlock()
+		return nil, sc.we
+	}
+	if sc.re != nil {
+		defer sc.lk.Unlock()
+		return nil, sc.re
+	}
+	if sc.r == nil { // connection closed by user in the meantime
+		defer sc.lk.Unlock()
+		return nil, errClosed
+	}
+	r := sc.r
+	lastbody := sc.lastbody
+	sc.lastbody = nil
+	sc.lk.Unlock()
+
+	// Make sure body is fully consumed, even if user does not call body.Close
+	if lastbody != nil {
+		// body.Close is assumed to be idempotent and multiple calls to
+		// it should return the error that its first invocation
+		// returned.
+		err = lastbody.Close()
+		if err != nil {
+			sc.lk.Lock()
+			defer sc.lk.Unlock()
+			sc.re = err
+			return nil, err
+		}
+	}
+
+	req, err = http.ReadRequest(r)
+	sc.lk.Lock()
+	defer sc.lk.Unlock()
+	if err != nil {
+		if err == io.ErrUnexpectedEOF {
+			// A close from the opposing client is treated as a
+			// graceful close, even if there was some unparse-able
+			// data before the close.
+			sc.re = ErrPersistEOF
+			return nil, sc.re
+		} else {
+			sc.re = err
+			return req, err
+		}
+	}
+	sc.lastbody = req.Body
+	sc.nread++
+	if req.Close {
+		sc.re = ErrPersistEOF
+		return req, sc.re
+	}
+	return req, err
+}
+
+// Pending returns the number of unanswered requests
+// that have been received on the connection.
+func (sc *ServerConn) Pending() int {
+	sc.lk.Lock()
+	defer sc.lk.Unlock()
+	return sc.nread - sc.nwritten
+}
+
+// Write writes resp in response to req. To close the connection gracefully, set the
+// Response.Close field to true. Write should be considered operational until
+// it returns an error, regardless of any errors returned on the Read side.
+func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
+
+	// Retrieve the pipeline ID of this request/response pair
+	sc.lk.Lock()
+	id, ok := sc.pipereq[req]
+	delete(sc.pipereq, req)
+	if !ok {
+		sc.lk.Unlock()
+		return ErrPipeline
+	}
+	sc.lk.Unlock()
+
+	// Ensure pipeline order
+	sc.pipe.StartResponse(id)
+	defer sc.pipe.EndResponse(id)
+
+	sc.lk.Lock()
+	if sc.we != nil {
+		defer sc.lk.Unlock()
+		return sc.we
+	}
+	if sc.c == nil { // connection closed by user in the meantime
+		defer sc.lk.Unlock()
+		return os.EBADF
+	}
+	c := sc.c
+	if sc.nread <= sc.nwritten {
+		defer sc.lk.Unlock()
+		return errors.New("persist server pipe count")
+	}
+	if resp.Close {
+		// After signaling a keep-alive close, any pipelined unread
+		// requests will be lost. It is up to the user to drain them
+		// before signaling.
+		sc.re = ErrPersistEOF
+	}
+	sc.lk.Unlock()
+
+	err := resp.Write(c)
+	sc.lk.Lock()
+	defer sc.lk.Unlock()
+	if err != nil {
+		sc.we = err
+		return err
+	}
+	sc.nwritten++
+
+	return nil
+}
+
+// A ClientConn sends request and receives headers over an underlying
+// connection, while respecting the HTTP keepalive logic. ClientConn
+// supports hijacking the connection calling Hijack to
+// regain control of the underlying net.Conn and deal with it as desired.
+//
+// ClientConn is low-level and should not be needed by most applications.
+// See Client.
+type ClientConn struct {
+	lk              sync.Mutex // read-write protects the following fields
+	c               net.Conn
+	r               *bufio.Reader
+	re, we          error // read/write errors
+	lastbody        io.ReadCloser
+	nread, nwritten int
+	pipereq         map[*http.Request]uint
+
+	pipe     textproto.Pipeline
+	writeReq func(*http.Request, io.Writer) error
+}
+
+// NewClientConn returns a new ClientConn reading and writing c.  If r is not
+// nil, it is the buffer to use when reading c.
+func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
+	if r == nil {
+		r = bufio.NewReader(c)
+	}
+	return &ClientConn{
+		c:        c,
+		r:        r,
+		pipereq:  make(map[*http.Request]uint),
+		writeReq: (*http.Request).Write,
+	}
+}
+
+// NewProxyClientConn works like NewClientConn but writes Requests
+// using Request's WriteProxy method.
+func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
+	cc := NewClientConn(c, r)
+	cc.writeReq = (*http.Request).WriteProxy
+	return cc
+}
+
+// Hijack detaches the ClientConn and returns the underlying connection as well
+// as the read-side bufio which may have some left over data. Hijack may be
+// called before the user or Read have signaled the end of the keep-alive
+// logic. The user should not call Hijack while Read or Write is in progress.
+func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
+	cc.lk.Lock()
+	defer cc.lk.Unlock()
+	c = cc.c
+	r = cc.r
+	cc.c = nil
+	cc.r = nil
+	return
+}
+
+// Close calls Hijack and then also closes the underlying connection
+func (cc *ClientConn) Close() error {
+	c, _ := cc.Hijack()
+	if c != nil {
+		return c.Close()
+	}
+	return nil
+}
+
+// Write writes a request. An ErrPersistEOF error is returned if the connection
+// has been closed in an HTTP keepalive sense. If req.Close equals true, the
+// keepalive connection is logically closed after this request and the opposing
+// server is informed. An ErrUnexpectedEOF indicates the remote closed the
+// underlying TCP connection, which is usually considered as graceful close.
+func (cc *ClientConn) Write(req *http.Request) (err error) {
+
+	// Ensure ordered execution of Writes
+	id := cc.pipe.Next()
+	cc.pipe.StartRequest(id)
+	defer func() {
+		cc.pipe.EndRequest(id)
+		if err != nil {
+			cc.pipe.StartResponse(id)
+			cc.pipe.EndResponse(id)
+		} else {
+			// Remember the pipeline id of this request
+			cc.lk.Lock()
+			cc.pipereq[req] = id
+			cc.lk.Unlock()
+		}
+	}()
+
+	cc.lk.Lock()
+	if cc.re != nil { // no point sending if read-side closed or broken
+		defer cc.lk.Unlock()
+		return cc.re
+	}
+	if cc.we != nil {
+		defer cc.lk.Unlock()
+		return cc.we
+	}
+	if cc.c == nil { // connection closed by user in the meantime
+		defer cc.lk.Unlock()
+		return errClosed
+	}
+	c := cc.c
+	if req.Close {
+		// We write the EOF to the write-side error, because there
+		// still might be some pipelined reads
+		cc.we = ErrPersistEOF
+	}
+	cc.lk.Unlock()
+
+	err = cc.writeReq(req, c)
+	cc.lk.Lock()
+	defer cc.lk.Unlock()
+	if err != nil {
+		cc.we = err
+		return err
+	}
+	cc.nwritten++
+
+	return nil
+}
+
+// Pending returns the number of unanswered requests
+// that have been sent on the connection.
+func (cc *ClientConn) Pending() int {
+	cc.lk.Lock()
+	defer cc.lk.Unlock()
+	return cc.nwritten - cc.nread
+}
+
+// Read reads the next response from the wire. A valid response might be
+// returned together with an ErrPersistEOF, which means that the remote
+// requested that this be the last request serviced. Read can be called
+// concurrently with Write, but not with another Read.
+func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
+	// Retrieve the pipeline ID of this request/response pair
+	cc.lk.Lock()
+	id, ok := cc.pipereq[req]
+	delete(cc.pipereq, req)
+	if !ok {
+		cc.lk.Unlock()
+		return nil, ErrPipeline
+	}
+	cc.lk.Unlock()
+
+	// Ensure pipeline order
+	cc.pipe.StartResponse(id)
+	defer cc.pipe.EndResponse(id)
+
+	cc.lk.Lock()
+	if cc.re != nil {
+		defer cc.lk.Unlock()
+		return nil, cc.re
+	}
+	if cc.r == nil { // connection closed by user in the meantime
+		defer cc.lk.Unlock()
+		return nil, errClosed
+	}
+	r := cc.r
+	lastbody := cc.lastbody
+	cc.lastbody = nil
+	cc.lk.Unlock()
+
+	// Make sure body is fully consumed, even if user does not call body.Close
+	if lastbody != nil {
+		// body.Close is assumed to be idempotent and multiple calls to
+		// it should return the error that its first invokation
+		// returned.
+		err = lastbody.Close()
+		if err != nil {
+			cc.lk.Lock()
+			defer cc.lk.Unlock()
+			cc.re = err
+			return nil, err
+		}
+	}
+
+	resp, err = http.ReadResponse(r, req)
+	cc.lk.Lock()
+	defer cc.lk.Unlock()
+	if err != nil {
+		cc.re = err
+		return resp, err
+	}
+	cc.lastbody = resp.Body
+
+	cc.nread++
+
+	if resp.Close {
+		cc.re = ErrPersistEOF // don't send any more requests
+		return resp, cc.re
+	}
+	return resp, err
+}
+
+// Do is convenience method that writes a request and reads a response.
+func (cc *ClientConn) Do(req *http.Request) (resp *http.Response, err error) {
+	err = cc.Write(req)
+	if err != nil {
+		return
+	}
+	return cc.Read(req)
+}
diff --git a/src/pkg/net/http/httputil/reverseproxy.go b/src/pkg/net/http/httputil/reverseproxy.go
new file mode 100644
index 0000000..1072e2e
--- /dev/null
+++ b/src/pkg/net/http/httputil/reverseproxy.go
@@ -0,0 +1,167 @@
+// Copyright 2011 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.
+
+// HTTP reverse proxy handler
+
+package httputil
+
+import (
+	"io"
+	"log"
+	"net"
+	"net/http"
+	"net/url"
+	"strings"
+	"sync"
+	"time"
+)
+
+// ReverseProxy is an HTTP Handler that takes an incoming request and
+// sends it to another server, proxying the response back to the
+// client.
+type ReverseProxy struct {
+	// Director must be a function which modifies
+	// the request into a new request to be sent
+	// using Transport. Its response is then copied
+	// back to the original client unmodified.
+	Director func(*http.Request)
+
+	// The transport used to perform proxy requests.
+	// If nil, http.DefaultTransport is used.
+	Transport http.RoundTripper
+
+	// FlushInterval specifies the flush interval
+	// to flush to the client while copying the
+	// response body.
+	// If zero, no periodic flushing is done.
+	FlushInterval time.Duration
+}
+
+func singleJoiningSlash(a, b string) string {
+	aslash := strings.HasSuffix(a, "/")
+	bslash := strings.HasPrefix(b, "/")
+	switch {
+	case aslash && bslash:
+		return a + b[1:]
+	case !aslash && !bslash:
+		return a + "/" + b
+	}
+	return a + b
+}
+
+// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
+// URLs to the scheme, host, and base path provided in target. If the
+// target's path is "/base" and the incoming request was for "/dir",
+// the target request will be for /base/dir.
+func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
+	director := func(req *http.Request) {
+		req.URL.Scheme = target.Scheme
+		req.URL.Host = target.Host
+		req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
+		req.URL.RawQuery = target.RawQuery
+	}
+	return &ReverseProxy{Director: director}
+}
+
+func copyHeader(dst, src http.Header) {
+	for k, vv := range src {
+		for _, v := range vv {
+			dst.Add(k, v)
+		}
+	}
+}
+
+func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+	transport := p.Transport
+	if transport == nil {
+		transport = http.DefaultTransport
+	}
+
+	outreq := new(http.Request)
+	*outreq = *req // includes shallow copies of maps, but okay
+
+	p.Director(outreq)
+	outreq.Proto = "HTTP/1.1"
+	outreq.ProtoMajor = 1
+	outreq.ProtoMinor = 1
+	outreq.Close = false
+
+	// Remove the connection header to the backend.  We want a
+	// persistent connection, regardless of what the client sent
+	// to us.  This is modifying the same underlying map from req
+	// (shallow copied above) so we only copy it if necessary.
+	if outreq.Header.Get("Connection") != "" {
+		outreq.Header = make(http.Header)
+		copyHeader(outreq.Header, req.Header)
+		outreq.Header.Del("Connection")
+	}
+
+	if clientIp, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
+		outreq.Header.Set("X-Forwarded-For", clientIp)
+	}
+
+	res, err := transport.RoundTrip(outreq)
+	if err != nil {
+		log.Printf("http: proxy error: %v", err)
+		rw.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	copyHeader(rw.Header(), res.Header)
+
+	rw.WriteHeader(res.StatusCode)
+
+	if res.Body != nil {
+		var dst io.Writer = rw
+		if p.FlushInterval != 0 {
+			if wf, ok := rw.(writeFlusher); ok {
+				dst = &maxLatencyWriter{dst: wf, latency: p.FlushInterval}
+			}
+		}
+		io.Copy(dst, res.Body)
+	}
+}
+
+type writeFlusher interface {
+	io.Writer
+	http.Flusher
+}
+
+type maxLatencyWriter struct {
+	dst     writeFlusher
+	latency time.Duration
+
+	lk   sync.Mutex // protects init of done, as well Write + Flush
+	done chan bool
+}
+
+func (m *maxLatencyWriter) Write(p []byte) (n int, err error) {
+	m.lk.Lock()
+	defer m.lk.Unlock()
+	if m.done == nil {
+		m.done = make(chan bool)
+		go m.flushLoop()
+	}
+	n, err = m.dst.Write(p)
+	if err != nil {
+		m.done <- true
+	}
+	return
+}
+
+func (m *maxLatencyWriter) flushLoop() {
+	t := time.NewTicker(m.latency)
+	defer t.Stop()
+	for {
+		select {
+		case <-t.C:
+			m.lk.Lock()
+			m.dst.Flush()
+			m.lk.Unlock()
+		case <-m.done:
+			return
+		}
+	}
+	panic("unreached")
+}
diff --git a/src/pkg/net/http/httputil/reverseproxy_test.go b/src/pkg/net/http/httputil/reverseproxy_test.go
new file mode 100644
index 0000000..655784b
--- /dev/null
+++ b/src/pkg/net/http/httputil/reverseproxy_test.go
@@ -0,0 +1,71 @@
+// Copyright 2011 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.
+
+// Reverse proxy tests.
+
+package httputil
+
+import (
+	"io/ioutil"
+	"net/http"
+	"net/http/httptest"
+	"net/url"
+	"testing"
+)
+
+func TestReverseProxy(t *testing.T) {
+	const backendResponse = "I am the backend"
+	const backendStatus = 404
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if len(r.TransferEncoding) > 0 {
+			t.Errorf("backend got unexpected TransferEncoding: %v", r.TransferEncoding)
+		}
+		if r.Header.Get("X-Forwarded-For") == "" {
+			t.Errorf("didn't get X-Forwarded-For header")
+		}
+		if c := r.Header.Get("Connection"); c != "" {
+			t.Errorf("handler got Connection header value %q", c)
+		}
+		if g, e := r.Host, "some-name"; g != e {
+			t.Errorf("backend got Host header %q, want %q", g, e)
+		}
+		w.Header().Set("X-Foo", "bar")
+		http.SetCookie(w, &http.Cookie{Name: "flavor", Value: "chocolateChip"})
+		w.WriteHeader(backendStatus)
+		w.Write([]byte(backendResponse))
+	}))
+	defer backend.Close()
+	backendURL, err := url.Parse(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	proxyHandler := NewSingleHostReverseProxy(backendURL)
+	frontend := httptest.NewServer(proxyHandler)
+	defer frontend.Close()
+
+	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+	getReq.Host = "some-name"
+	getReq.Header.Set("Connection", "close")
+	getReq.Close = true
+	res, err := http.DefaultClient.Do(getReq)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	if g, e := res.StatusCode, backendStatus; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	if g, e := res.Header.Get("X-Foo"), "bar"; g != e {
+		t.Errorf("got X-Foo %q; expected %q", g, e)
+	}
+	if g, e := len(res.Header["Set-Cookie"]), 1; g != e {
+		t.Fatalf("got %d SetCookies, want %d", g, e)
+	}
+	if cookie := res.Cookies()[0]; cookie.Name != "flavor" {
+		t.Errorf("unexpected cookie %q", cookie.Name)
+	}
+	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(bodyBytes), backendResponse; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+}
diff --git a/src/pkg/net/http/jar.go b/src/pkg/net/http/jar.go
new file mode 100644
index 0000000..2c2caa2
--- /dev/null
+++ b/src/pkg/net/http/jar.go
@@ -0,0 +1,30 @@
+// Copyright 2011 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 http
+
+import (
+	"net/url"
+)
+
+// A CookieJar manages storage and use of cookies in HTTP requests. 
+//
+// Implementations of CookieJar must be safe for concurrent use by multiple
+// goroutines.
+type CookieJar interface {
+	// SetCookies handles the receipt of the cookies in a reply for the 
+	// given URL.  It may or may not choose to save the cookies, depending 
+	// on the jar's policy and implementation. 
+	SetCookies(u *url.URL, cookies []*Cookie)
+
+	// Cookies returns the cookies to send in a request for the given URL.
+	// It is up to the implementation to honor the standard cookie use 
+	// restrictions such as in RFC 6265. 
+	Cookies(u *url.URL) []*Cookie
+}
+
+type blackHoleJar struct{}
+
+func (blackHoleJar) SetCookies(u *url.URL, cookies []*Cookie) {}
+func (blackHoleJar) Cookies(u *url.URL) []*Cookie             { return nil }
diff --git a/src/pkg/http/lex.go b/src/pkg/net/http/lex.go
similarity index 100%
rename from src/pkg/http/lex.go
rename to src/pkg/net/http/lex.go
diff --git a/src/pkg/http/lex_test.go b/src/pkg/net/http/lex_test.go
similarity index 100%
rename from src/pkg/http/lex_test.go
rename to src/pkg/net/http/lex_test.go
diff --git a/src/pkg/net/http/pprof/Makefile b/src/pkg/net/http/pprof/Makefile
new file mode 100644
index 0000000..b78fce8
--- /dev/null
+++ b/src/pkg/net/http/pprof/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2010 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../../Make.inc
+
+TARG=net/http/pprof
+GOFILES=\
+	pprof.go\
+
+include ../../../../Make.pkg
diff --git a/src/pkg/net/http/pprof/pprof.go b/src/pkg/net/http/pprof/pprof.go
new file mode 100644
index 0000000..21eac47
--- /dev/null
+++ b/src/pkg/net/http/pprof/pprof.go
@@ -0,0 +1,133 @@
+// Copyright 2010 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 pprof serves via its HTTP server runtime profiling data
+// in the format expected by the pprof visualization tool.
+// For more information about pprof, see
+// http://code.google.com/p/google-perftools/.
+//
+// The package is typically only imported for the side effect of
+// registering its HTTP handlers.
+// The handled paths all begin with /debug/pprof/.
+//
+// To use pprof, link this package into your program:
+//	import _ "http/pprof"
+//
+// Then use the pprof tool to look at the heap profile:
+//
+//	pprof http://localhost:6060/debug/pprof/heap
+//
+// Or to look at a 30-second CPU profile:
+//
+//	pprof http://localhost:6060/debug/pprof/profile
+//
+package pprof
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"net/http"
+	"os"
+	"runtime"
+	"runtime/pprof"
+	"strconv"
+	"strings"
+	"time"
+)
+
+func init() {
+	http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
+	http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
+	http.Handle("/debug/pprof/heap", http.HandlerFunc(Heap))
+	http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
+}
+
+// Cmdline responds with the running program's
+// command line, with arguments separated by NUL bytes.
+// The package initialization registers it as /debug/pprof/cmdline.
+func Cmdline(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
+}
+
+// Heap responds with the pprof-formatted heap profile.
+// The package initialization registers it as /debug/pprof/heap.
+func Heap(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	pprof.WriteHeapProfile(w)
+}
+
+// Profile responds with the pprof-formatted cpu profile.
+// The package initialization registers it as /debug/pprof/profile.
+func Profile(w http.ResponseWriter, r *http.Request) {
+	sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
+	if sec == 0 {
+		sec = 30
+	}
+
+	// Set Content Type assuming StartCPUProfile will work,
+	// because if it does it starts writing.
+	w.Header().Set("Content-Type", "application/octet-stream")
+	if err := pprof.StartCPUProfile(w); err != nil {
+		// StartCPUProfile failed, so no writes yet.
+		// Can change header back to text content
+		// and send error code.
+		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+		w.WriteHeader(http.StatusInternalServerError)
+		fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err)
+		return
+	}
+	time.Sleep(time.Duration(sec) * time.Second)
+	pprof.StopCPUProfile()
+}
+
+// Symbol looks up the program counters listed in the request,
+// responding with a table mapping program counters to function names.
+// The package initialization registers it as /debug/pprof/symbol.
+func Symbol(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+
+	// We have to read the whole POST body before
+	// writing any output.  Buffer the output here.
+	var buf bytes.Buffer
+
+	// We don't know how many symbols we have, but we
+	// do have symbol information.  Pprof only cares whether
+	// this number is 0 (no symbols available) or > 0.
+	fmt.Fprintf(&buf, "num_symbols: 1\n")
+
+	var b *bufio.Reader
+	if r.Method == "POST" {
+		b = bufio.NewReader(r.Body)
+	} else {
+		b = bufio.NewReader(strings.NewReader(r.URL.RawQuery))
+	}
+
+	for {
+		word, err := b.ReadSlice('+')
+		if err == nil {
+			word = word[0 : len(word)-1] // trim +
+		}
+		pc, _ := strconv.ParseUint(string(word), 0, 64)
+		if pc != 0 {
+			f := runtime.FuncForPC(uintptr(pc))
+			if f != nil {
+				fmt.Fprintf(&buf, "%#x %s\n", pc, f.Name())
+			}
+		}
+
+		// Wait until here to check for err; the last
+		// symbol will have an err because it doesn't end in +.
+		if err != nil {
+			if err != io.EOF {
+				fmt.Fprintf(&buf, "reading request: %v\n", err)
+			}
+			break
+		}
+	}
+
+	w.Write(buf.Bytes())
+}
diff --git a/src/pkg/http/proxy_test.go b/src/pkg/net/http/proxy_test.go
similarity index 100%
rename from src/pkg/http/proxy_test.go
rename to src/pkg/net/http/proxy_test.go
diff --git a/src/pkg/http/range_test.go b/src/pkg/net/http/range_test.go
similarity index 100%
rename from src/pkg/http/range_test.go
rename to src/pkg/net/http/range_test.go
diff --git a/src/pkg/net/http/readrequest_test.go b/src/pkg/net/http/readrequest_test.go
new file mode 100644
index 0000000..2e03c65
--- /dev/null
+++ b/src/pkg/net/http/readrequest_test.go
@@ -0,0 +1,283 @@
+// Copyright 2010 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 http
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"net/url"
+	"reflect"
+	"testing"
+)
+
+type reqTest struct {
+	Raw     string
+	Req     *Request
+	Body    string
+	Trailer Header
+	Error   string
+}
+
+var noError = ""
+var noBody = ""
+var noTrailer Header = nil
+
+var reqTests = []reqTest{
+	// Baseline test; All Request fields included for template use
+	{
+		"GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
+			"Host: www.techcrunch.com\r\n" +
+			"User-Agent: Fake\r\n" +
+			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
+			"Accept-Language: en-us,en;q=0.5\r\n" +
+			"Accept-Encoding: gzip,deflate\r\n" +
+			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
+			"Keep-Alive: 300\r\n" +
+			"Content-Length: 7\r\n" +
+			"Proxy-Connection: keep-alive\r\n\r\n" +
+			"abcdef\n???",
+
+		&Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.techcrunch.com",
+				Path:   "/",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
+				"Accept-Language":  {"en-us,en;q=0.5"},
+				"Accept-Encoding":  {"gzip,deflate"},
+				"Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
+				"Keep-Alive":       {"300"},
+				"Proxy-Connection": {"keep-alive"},
+				"Content-Length":   {"7"},
+				"User-Agent":       {"Fake"},
+			},
+			Close:         false,
+			ContentLength: 7,
+			Host:          "www.techcrunch.com",
+			RequestURI:    "http://www.techcrunch.com/",
+		},
+
+		"abcdef\n",
+
+		noTrailer,
+		noError,
+	},
+
+	// GET request with no body (the normal case)
+	{
+		"GET / HTTP/1.1\r\n" +
+			"Host: foo.com\r\n\r\n",
+
+		&Request{
+			Method: "GET",
+			URL: &url.URL{
+				Path: "/",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "foo.com",
+			RequestURI:    "/",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// Tests that we don't parse a path that looks like a
+	// scheme-relative URI as a scheme-relative URI.
+	{
+		"GET //user at host/is/actually/a/path/ HTTP/1.1\r\n" +
+			"Host: test\r\n\r\n",
+
+		&Request{
+			Method: "GET",
+			URL: &url.URL{
+				Path: "//user at host/is/actually/a/path/",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "test",
+			RequestURI:    "//user at host/is/actually/a/path/",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// Tests a bogus abs_path on the Request-Line (RFC 2616 section 5.1.2)
+	{
+		"GET ../../../../etc/passwd HTTP/1.1\r\n" +
+			"Host: test\r\n\r\n",
+		nil,
+		noBody,
+		noTrailer,
+		"parse ../../../../etc/passwd: invalid URI for request",
+	},
+
+	// Tests missing URL:
+	{
+		"GET  HTTP/1.1\r\n" +
+			"Host: test\r\n\r\n",
+		nil,
+		noBody,
+		noTrailer,
+		"parse : empty url",
+	},
+
+	// Tests chunked body with trailer:
+	{
+		"POST / HTTP/1.1\r\n" +
+			"Host: foo.com\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			"3\r\nfoo\r\n" +
+			"3\r\nbar\r\n" +
+			"0\r\n" +
+			"Trailer-Key: Trailer-Value\r\n" +
+			"\r\n",
+		&Request{
+			Method: "POST",
+			URL: &url.URL{
+				Path: "/",
+			},
+			TransferEncoding: []string{"chunked"},
+			Proto:            "HTTP/1.1",
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Header:           Header{},
+			ContentLength:    -1,
+			Host:             "foo.com",
+			RequestURI:       "/",
+		},
+
+		"foobar",
+		Header{
+			"Trailer-Key": {"Trailer-Value"},
+		},
+		noError,
+	},
+
+	// CONNECT request with domain name:
+	{
+		"CONNECT www.google.com:443 HTTP/1.1\r\n\r\n",
+
+		&Request{
+			Method: "CONNECT",
+			URL: &url.URL{
+				Host: "www.google.com:443",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "www.google.com:443",
+			RequestURI:    "www.google.com:443",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// CONNECT request with IP address:
+	{
+		"CONNECT 127.0.0.1:6060 HTTP/1.1\r\n\r\n",
+
+		&Request{
+			Method: "CONNECT",
+			URL: &url.URL{
+				Host: "127.0.0.1:6060",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "127.0.0.1:6060",
+			RequestURI:    "127.0.0.1:6060",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+
+	// CONNECT request for RPC:
+	{
+		"CONNECT /_goRPC_ HTTP/1.1\r\n\r\n",
+
+		&Request{
+			Method: "CONNECT",
+			URL: &url.URL{
+				Path: "/_goRPC_",
+			},
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         false,
+			ContentLength: 0,
+			Host:          "",
+			RequestURI:    "/_goRPC_",
+		},
+
+		noBody,
+		noTrailer,
+		noError,
+	},
+}
+
+func TestReadRequest(t *testing.T) {
+	for i := range reqTests {
+		tt := &reqTests[i]
+		var braw bytes.Buffer
+		braw.WriteString(tt.Raw)
+		req, err := ReadRequest(bufio.NewReader(&braw))
+		if err != nil {
+			if err.Error() != tt.Error {
+				t.Errorf("#%d: error %q, want error %q", i, err.Error(), tt.Error)
+			}
+			continue
+		}
+		rbody := req.Body
+		req.Body = nil
+		diff(t, fmt.Sprintf("#%d Request", i), req, tt.Req)
+		var bout bytes.Buffer
+		if rbody != nil {
+			_, err := io.Copy(&bout, rbody)
+			if err != nil {
+				t.Fatalf("#%d. copying body: %v", i, err)
+			}
+			rbody.Close()
+		}
+		body := bout.String()
+		if body != tt.Body {
+			t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
+		}
+		if !reflect.DeepEqual(tt.Trailer, req.Trailer) {
+			t.Errorf("#%d. Trailers differ.\n got: %v\nwant: %v", i, req.Trailer, tt.Trailer)
+		}
+	}
+}
diff --git a/src/pkg/net/http/request.go b/src/pkg/net/http/request.go
new file mode 100644
index 0000000..5f8c000
--- /dev/null
+++ b/src/pkg/net/http/request.go
@@ -0,0 +1,741 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// HTTP Request reading and parsing.
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/tls"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"mime"
+	"mime/multipart"
+	"net/textproto"
+	"net/url"
+	"strings"
+)
+
+const (
+	maxValueLength   = 4096
+	maxHeaderLines   = 1024
+	chunkSize        = 4 << 10  // 4 KB chunks
+	defaultMaxMemory = 32 << 20 // 32 MB
+)
+
+// ErrMissingFile is returned by FormFile when the provided file field name
+// is either not present in the request or not a file field.
+var ErrMissingFile = errors.New("http: no such file")
+
+// HTTP request parsing errors.
+type ProtocolError struct {
+	ErrorString string
+}
+
+func (err *ProtocolError) Error() string { return err.ErrorString }
+
+var (
+	ErrHeaderTooLong        = &ProtocolError{"header too long"}
+	ErrShortBody            = &ProtocolError{"entity body too short"}
+	ErrNotSupported         = &ProtocolError{"feature not supported"}
+	ErrUnexpectedTrailer    = &ProtocolError{"trailer header without chunked transfer encoding"}
+	ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
+	ErrNotMultipart         = &ProtocolError{"request Content-Type isn't multipart/form-data"}
+	ErrMissingBoundary      = &ProtocolError{"no multipart boundary param Content-Type"}
+)
+
+type badStringError struct {
+	what string
+	str  string
+}
+
+func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
+
+// Headers that Request.Write handles itself and should be skipped.
+var reqWriteExcludeHeader = map[string]bool{
+	"Host":              true, // not in Header map anyway
+	"User-Agent":        true,
+	"Content-Length":    true,
+	"Transfer-Encoding": true,
+	"Trailer":           true,
+}
+
+// A Request represents an HTTP request received by a server
+// or to be sent by a client.
+type Request struct {
+	Method string // GET, POST, PUT, etc.
+	URL    *url.URL
+
+	// The protocol version for incoming requests.
+	// Outgoing requests always use HTTP/1.1.
+	Proto      string // "HTTP/1.0"
+	ProtoMajor int    // 1
+	ProtoMinor int    // 0
+
+	// A header maps request lines to their values.
+	// If the header says
+	//
+	//	accept-encoding: gzip, deflate
+	//	Accept-Language: en-us
+	//	Connection: keep-alive
+	//
+	// then
+	//
+	//	Header = map[string][]string{
+	//		"Accept-Encoding": {"gzip, deflate"},
+	//		"Accept-Language": {"en-us"},
+	//		"Connection": {"keep-alive"},
+	//	}
+	//
+	// HTTP defines that header names are case-insensitive.
+	// The request parser implements this by canonicalizing the
+	// name, making the first character and any characters
+	// following a hyphen uppercase and the rest lowercase.
+	Header Header
+
+	// The message body.
+	Body io.ReadCloser
+
+	// ContentLength records the length of the associated content.
+	// The value -1 indicates that the length is unknown.
+	// Values >= 0 indicate that the given number of bytes may
+	// be read from Body.
+	// For outgoing requests, a value of 0 means unknown if Body is not nil.
+	ContentLength int64
+
+	// TransferEncoding lists the transfer encodings from outermost to
+	// innermost. An empty list denotes the "identity" encoding.
+	// TransferEncoding can usually be ignored; chunked encoding is
+	// automatically added and removed as necessary when sending and
+	// receiving requests.
+	TransferEncoding []string
+
+	// Close indicates whether to close the connection after
+	// replying to this request.
+	Close bool
+
+	// The host on which the URL is sought.
+	// Per RFC 2616, this is either the value of the Host: header
+	// or the host name given in the URL itself.
+	Host string
+
+	// Form contains the parsed form data, including both the URL
+	// field's query parameters and the POST or PUT form data.
+	// This field is only available after ParseForm is called.
+	// The HTTP client ignores Form and uses Body instead.
+	Form url.Values
+
+	// MultipartForm is the parsed multipart form, including file uploads.
+	// This field is only available after ParseMultipartForm is called.
+	// The HTTP client ignores MultipartForm and uses Body instead.
+	MultipartForm *multipart.Form
+
+	// Trailer maps trailer keys to values.  Like for Header, if the
+	// response has multiple trailer lines with the same key, they will be
+	// concatenated, delimited by commas.
+	// For server requests, Trailer is only populated after Body has been
+	// closed or fully consumed.
+	// Trailer support is only partially complete.
+	Trailer Header
+
+	// RemoteAddr allows HTTP servers and other software to record
+	// the network address that sent the request, usually for
+	// logging. This field is not filled in by ReadRequest and
+	// has no defined format. The HTTP server in this package
+	// sets RemoteAddr to an "IP:port" address before invoking a
+	// handler.
+	// This field is ignored by the HTTP client.
+	RemoteAddr string
+
+	// RequestURI is the unmodified Request-URI of the
+	// Request-Line (RFC 2616, Section 5.1) as sent by the client
+	// to a server. Usually the URL field should be used instead.
+	// It is an error to set this field in an HTTP client request.
+	RequestURI string
+
+	// TLS allows HTTP servers and other software to record
+	// information about the TLS connection on which the request
+	// was received. This field is not filled in by ReadRequest.
+	// The HTTP server in this package sets the field for
+	// TLS-enabled connections before invoking a handler;
+	// otherwise it leaves the field nil.
+	// This field is ignored by the HTTP client.
+	TLS *tls.ConnectionState
+}
+
+// ProtoAtLeast returns whether the HTTP protocol used
+// in the request is at least major.minor.
+func (r *Request) ProtoAtLeast(major, minor int) bool {
+	return r.ProtoMajor > major ||
+		r.ProtoMajor == major && r.ProtoMinor >= minor
+}
+
+// UserAgent returns the client's User-Agent, if sent in the request.
+func (r *Request) UserAgent() string {
+	return r.Header.Get("User-Agent")
+}
+
+// Cookies parses and returns the HTTP cookies sent with the request.
+func (r *Request) Cookies() []*Cookie {
+	return readCookies(r.Header, "")
+}
+
+var ErrNoCookie = errors.New("http: named cookied not present")
+
+// Cookie returns the named cookie provided in the request or
+// ErrNoCookie if not found.
+func (r *Request) Cookie(name string) (*Cookie, error) {
+	for _, c := range readCookies(r.Header, name) {
+		return c, nil
+	}
+	return nil, ErrNoCookie
+}
+
+// AddCookie adds a cookie to the request.  Per RFC 6265 section 5.4,
+// AddCookie does not attach more than one Cookie header field.  That
+// means all cookies, if any, are written into the same line,
+// separated by semicolon.
+func (r *Request) AddCookie(c *Cookie) {
+	s := fmt.Sprintf("%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
+	if c := r.Header.Get("Cookie"); c != "" {
+		r.Header.Set("Cookie", c+"; "+s)
+	} else {
+		r.Header.Set("Cookie", s)
+	}
+}
+
+// Referer returns the referring URL, if sent in the request.
+//
+// Referer is misspelled as in the request itself, a mistake from the
+// earliest days of HTTP.  This value can also be fetched from the
+// Header map as Header["Referer"]; the benefit of making it available
+// as a method is that the compiler can diagnose programs that use the
+// alternate (correct English) spelling req.Referrer() but cannot
+// diagnose programs that use Header["Referrer"].
+func (r *Request) Referer() string {
+	return r.Header.Get("Referer")
+}
+
+// multipartByReader is a sentinel value.
+// Its presence in Request.MultipartForm indicates that parsing of the request
+// body has been handed off to a MultipartReader instead of ParseMultipartFrom.
+var multipartByReader = &multipart.Form{
+	Value: make(map[string][]string),
+	File:  make(map[string][]*multipart.FileHeader),
+}
+
+// MultipartReader returns a MIME multipart reader if this is a
+// multipart/form-data POST request, else returns nil and an error.
+// Use this function instead of ParseMultipartForm to
+// process the request body as a stream.
+func (r *Request) MultipartReader() (*multipart.Reader, error) {
+	if r.MultipartForm == multipartByReader {
+		return nil, errors.New("http: MultipartReader called twice")
+	}
+	if r.MultipartForm != nil {
+		return nil, errors.New("http: multipart handled by ParseMultipartForm")
+	}
+	r.MultipartForm = multipartByReader
+	return r.multipartReader()
+}
+
+func (r *Request) multipartReader() (*multipart.Reader, error) {
+	v := r.Header.Get("Content-Type")
+	if v == "" {
+		return nil, ErrNotMultipart
+	}
+	d, params, err := mime.ParseMediaType(v)
+	if err != nil || d != "multipart/form-data" {
+		return nil, ErrNotMultipart
+	}
+	boundary, ok := params["boundary"]
+	if !ok {
+		return nil, ErrMissingBoundary
+	}
+	return multipart.NewReader(r.Body, boundary), nil
+}
+
+// Return value if nonempty, def otherwise.
+func valueOrDefault(value, def string) string {
+	if value != "" {
+		return value
+	}
+	return def
+}
+
+const defaultUserAgent = "Go http package"
+
+// Write writes an HTTP/1.1 request -- header and body -- in wire format.
+// This method consults the following fields of req:
+//	Host
+//	URL
+//	Method (defaults to "GET")
+//	Header
+//	ContentLength
+//	TransferEncoding
+//	Body
+//
+// If Body is present, Content-Length is <= 0 and TransferEncoding
+// hasn't been set to "identity", Write adds "Transfer-Encoding:
+// chunked" to the header. Body is closed after it is sent.
+func (req *Request) Write(w io.Writer) error {
+	return req.write(w, false, nil)
+}
+
+// WriteProxy is like Write but writes the request in the form
+// expected by an HTTP proxy.  In particular, WriteProxy writes the
+// initial Request-URI line of the request with an absolute URI, per
+// section 5.1.2 of RFC 2616, including the scheme and host. In
+// either case, WriteProxy also writes a Host header, using either
+// req.Host or req.URL.Host.
+func (req *Request) WriteProxy(w io.Writer) error {
+	return req.write(w, true, nil)
+}
+
+// extraHeaders may be nil
+func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) error {
+	host := req.Host
+	if host == "" {
+		if req.URL == nil {
+			return errors.New("http: Request.Write on Request with no Host or URL set")
+		}
+		host = req.URL.Host
+	}
+
+	ruri := req.URL.RequestURI()
+	if usingProxy && req.URL.Scheme != "" && req.URL.Opaque == "" {
+		ruri = req.URL.Scheme + "://" + host + ruri
+	} else if req.Method == "CONNECT" && req.URL.Path == "" {
+		// CONNECT requests normally give just the host and port, not a full URL.
+		ruri = host
+	}
+	// TODO(bradfitz): escape at least newlines in ruri?
+
+	bw := bufio.NewWriter(w)
+	fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), ruri)
+
+	// Header lines
+	fmt.Fprintf(bw, "Host: %s\r\n", host)
+
+	// Use the defaultUserAgent unless the Header contains one, which
+	// may be blank to not send the header.
+	userAgent := defaultUserAgent
+	if req.Header != nil {
+		if ua := req.Header["User-Agent"]; len(ua) > 0 {
+			userAgent = ua[0]
+		}
+	}
+	if userAgent != "" {
+		fmt.Fprintf(bw, "User-Agent: %s\r\n", userAgent)
+	}
+
+	// Process Body,ContentLength,Close,Trailer
+	tw, err := newTransferWriter(req)
+	if err != nil {
+		return err
+	}
+	err = tw.WriteHeader(bw)
+	if err != nil {
+		return err
+	}
+
+	// TODO: split long values?  (If so, should share code with Conn.Write)
+	err = req.Header.WriteSubset(bw, reqWriteExcludeHeader)
+	if err != nil {
+		return err
+	}
+
+	if extraHeaders != nil {
+		err = extraHeaders.Write(bw)
+		if err != nil {
+			return err
+		}
+	}
+
+	io.WriteString(bw, "\r\n")
+
+	// Write body and trailer
+	err = tw.WriteBody(bw)
+	if err != nil {
+		return err
+	}
+
+	return bw.Flush()
+}
+
+// Convert decimal at s[i:len(s)] to integer,
+// returning value, string position where the digits stopped,
+// and whether there was a valid number (digits, not too big).
+func atoi(s string, i int) (n, i1 int, ok bool) {
+	const Big = 1000000
+	if i >= len(s) || s[i] < '0' || s[i] > '9' {
+		return 0, 0, false
+	}
+	n = 0
+	for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
+		n = n*10 + int(s[i]-'0')
+		if n > Big {
+			return 0, 0, false
+		}
+	}
+	return n, i, true
+}
+
+// ParseHTTPVersion parses a HTTP version string.
+// "HTTP/1.0" returns (1, 0, true).
+func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
+	if len(vers) < 5 || vers[0:5] != "HTTP/" {
+		return 0, 0, false
+	}
+	major, i, ok := atoi(vers, 5)
+	if !ok || i >= len(vers) || vers[i] != '.' {
+		return 0, 0, false
+	}
+	minor, i, ok = atoi(vers, i+1)
+	if !ok || i != len(vers) {
+		return 0, 0, false
+	}
+	return major, minor, true
+}
+
+// NewRequest returns a new Request given a method, URL, and optional body.
+func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
+	u, err := url.Parse(urlStr)
+	if err != nil {
+		return nil, err
+	}
+	rc, ok := body.(io.ReadCloser)
+	if !ok && body != nil {
+		rc = ioutil.NopCloser(body)
+	}
+	req := &Request{
+		Method:     method,
+		URL:        u,
+		Proto:      "HTTP/1.1",
+		ProtoMajor: 1,
+		ProtoMinor: 1,
+		Header:     make(Header),
+		Body:       rc,
+		Host:       u.Host,
+	}
+	if body != nil {
+		switch v := body.(type) {
+		case *strings.Reader:
+			req.ContentLength = int64(v.Len())
+		case *bytes.Buffer:
+			req.ContentLength = int64(v.Len())
+		}
+	}
+
+	return req, nil
+}
+
+// SetBasicAuth sets the request's Authorization header to use HTTP
+// Basic Authentication with the provided username and password.
+//
+// With HTTP Basic Authentication the provided username and password
+// are not encrypted.
+func (r *Request) SetBasicAuth(username, password string) {
+	s := username + ":" + password
+	r.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
+}
+
+// ReadRequest reads and parses a request from b.
+func ReadRequest(b *bufio.Reader) (req *Request, err error) {
+
+	tp := textproto.NewReader(b)
+	req = new(Request)
+
+	// First line: GET /index.html HTTP/1.0
+	var s string
+	if s, err = tp.ReadLine(); err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return nil, err
+	}
+
+	var f []string
+	if f = strings.SplitN(s, " ", 3); len(f) < 3 {
+		return nil, &badStringError{"malformed HTTP request", s}
+	}
+	req.Method, req.RequestURI, req.Proto = f[0], f[1], f[2]
+	rawurl := req.RequestURI
+	var ok bool
+	if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
+		return nil, &badStringError{"malformed HTTP version", req.Proto}
+	}
+
+	// CONNECT requests are used two different ways, and neither uses a full URL:
+	// The standard use is to tunnel HTTPS through an HTTP proxy.
+	// It looks like "CONNECT www.google.com:443 HTTP/1.1", and the parameter is
+	// just the authority section of a URL. This information should go in req.URL.Host.
+	//
+	// The net/rpc package also uses CONNECT, but there the parameter is a path
+	// that starts with a slash. It can be parsed with the regular URL parser,
+	// and the path will end up in req.URL.Path, where it needs to be in order for
+	// RPC to work.
+	justAuthority := req.Method == "CONNECT" && !strings.HasPrefix(rawurl, "/")
+	if justAuthority {
+		rawurl = "http://" + rawurl
+	}
+
+	if req.URL, err = url.ParseRequest(rawurl); err != nil {
+		return nil, err
+	}
+
+	if justAuthority {
+		// Strip the bogus "http://" back off.
+		req.URL.Scheme = ""
+	}
+
+	// Subsequent lines: Key: value.
+	mimeHeader, err := tp.ReadMIMEHeader()
+	if err != nil {
+		return nil, err
+	}
+	req.Header = Header(mimeHeader)
+
+	// RFC2616: Must treat
+	//	GET /index.html HTTP/1.1
+	//	Host: www.google.com
+	// and
+	//	GET http://www.google.com/index.html HTTP/1.1
+	//	Host: doesntmatter
+	// the same.  In the second case, any Host line is ignored.
+	req.Host = req.URL.Host
+	if req.Host == "" {
+		req.Host = req.Header.Get("Host")
+	}
+	req.Header.Del("Host")
+
+	fixPragmaCacheControl(req.Header)
+
+	// TODO: Parse specific header values:
+	//	Accept
+	//	Accept-Encoding
+	//	Accept-Language
+	//	Authorization
+	//	Cache-Control
+	//	Connection
+	//	Date
+	//	Expect
+	//	From
+	//	If-Match
+	//	If-Modified-Since
+	//	If-None-Match
+	//	If-Range
+	//	If-Unmodified-Since
+	//	Max-Forwards
+	//	Proxy-Authorization
+	//	Referer [sic]
+	//	TE (transfer-codings)
+	//	Trailer
+	//	Transfer-Encoding
+	//	Upgrade
+	//	User-Agent
+	//	Via
+	//	Warning
+
+	err = readTransfer(req, b)
+	if err != nil {
+		return nil, err
+	}
+
+	return req, nil
+}
+
+// MaxBytesReader is similar to io.LimitReader but is intended for
+// limiting the size of incoming request bodies. In contrast to
+// io.LimitReader, MaxBytesReader's result is a ReadCloser, returns a
+// non-EOF error for a Read beyond the limit, and Closes the
+// underlying reader when its Close method is called.
+//
+// MaxBytesReader prevents clients from accidentally or maliciously
+// sending a large request and wasting server resources.
+func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
+	return &maxBytesReader{w: w, r: r, n: n}
+}
+
+type maxBytesReader struct {
+	w       ResponseWriter
+	r       io.ReadCloser // underlying reader
+	n       int64         // max bytes remaining
+	stopped bool
+}
+
+func (l *maxBytesReader) Read(p []byte) (n int, err error) {
+	if l.n <= 0 {
+		if !l.stopped {
+			l.stopped = true
+			if res, ok := l.w.(*response); ok {
+				res.requestTooLarge()
+			}
+		}
+		return 0, errors.New("http: request body too large")
+	}
+	if int64(len(p)) > l.n {
+		p = p[:l.n]
+	}
+	n, err = l.r.Read(p)
+	l.n -= int64(n)
+	return
+}
+
+func (l *maxBytesReader) Close() error {
+	return l.r.Close()
+}
+
+// ParseForm parses the raw query from the URL.
+//
+// For POST or PUT requests, it also parses the request body as a form.
+// If the request Body's size has not already been limited by MaxBytesReader,
+// the size is capped at 10MB.
+//
+// ParseMultipartForm calls ParseForm automatically.
+// It is idempotent.
+func (r *Request) ParseForm() (err error) {
+	if r.Form != nil {
+		return
+	}
+	if r.URL != nil {
+		r.Form, err = url.ParseQuery(r.URL.RawQuery)
+	}
+	if r.Method == "POST" || r.Method == "PUT" {
+		if r.Body == nil {
+			return errors.New("missing form body")
+		}
+		ct := r.Header.Get("Content-Type")
+		ct, _, err = mime.ParseMediaType(ct)
+		switch {
+		case ct == "application/x-www-form-urlencoded":
+			var reader io.Reader = r.Body
+			maxFormSize := int64(1<<63 - 1)
+			if _, ok := r.Body.(*maxBytesReader); !ok {
+				maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
+				reader = io.LimitReader(r.Body, maxFormSize+1)
+			}
+			b, e := ioutil.ReadAll(reader)
+			if e != nil {
+				if err == nil {
+					err = e
+				}
+				break
+			}
+			if int64(len(b)) > maxFormSize {
+				return errors.New("http: POST too large")
+			}
+			var newValues url.Values
+			newValues, e = url.ParseQuery(string(b))
+			if err == nil {
+				err = e
+			}
+			if r.Form == nil {
+				r.Form = make(url.Values)
+			}
+			// Copy values into r.Form. TODO: make this smoother.
+			for k, vs := range newValues {
+				for _, value := range vs {
+					r.Form.Add(k, value)
+				}
+			}
+		case ct == "multipart/form-data":
+			// handled by ParseMultipartForm (which is calling us, or should be)
+			// TODO(bradfitz): there are too many possible
+			// orders to call too many functions here.
+			// Clean this up and write more tests.
+			// request_test.go contains the start of this,
+			// in TestRequestMultipartCallOrder.
+		}
+	}
+	return err
+}
+
+// ParseMultipartForm parses a request body as multipart/form-data.
+// The whole request body is parsed and up to a total of maxMemory bytes of
+// its file parts are stored in memory, with the remainder stored on
+// disk in temporary files.
+// ParseMultipartForm calls ParseForm if necessary.
+// After one call to ParseMultipartForm, subsequent calls have no effect.
+func (r *Request) ParseMultipartForm(maxMemory int64) error {
+	if r.MultipartForm == multipartByReader {
+		return errors.New("http: multipart handled by MultipartReader")
+	}
+	if r.Form == nil {
+		err := r.ParseForm()
+		if err != nil {
+			return err
+		}
+	}
+	if r.MultipartForm != nil {
+		return nil
+	}
+
+	mr, err := r.multipartReader()
+	if err == ErrNotMultipart {
+		return nil
+	} else if err != nil {
+		return err
+	}
+
+	f, err := mr.ReadForm(maxMemory)
+	if err != nil {
+		return err
+	}
+	for k, v := range f.Value {
+		r.Form[k] = append(r.Form[k], v...)
+	}
+	r.MultipartForm = f
+
+	return nil
+}
+
+// FormValue returns the first value for the named component of the query.
+// FormValue calls ParseMultipartForm and ParseForm if necessary.
+func (r *Request) FormValue(key string) string {
+	if r.Form == nil {
+		r.ParseMultipartForm(defaultMaxMemory)
+	}
+	if vs := r.Form[key]; len(vs) > 0 {
+		return vs[0]
+	}
+	return ""
+}
+
+// FormFile returns the first file for the provided form key.
+// FormFile calls ParseMultipartForm and ParseForm if necessary.
+func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
+	if r.MultipartForm == multipartByReader {
+		return nil, nil, errors.New("http: multipart handled by MultipartReader")
+	}
+	if r.MultipartForm == nil {
+		err := r.ParseMultipartForm(defaultMaxMemory)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+	if r.MultipartForm != nil && r.MultipartForm.File != nil {
+		if fhs := r.MultipartForm.File[key]; len(fhs) > 0 {
+			f, err := fhs[0].Open()
+			return f, fhs[0], err
+		}
+	}
+	return nil, nil, ErrMissingFile
+}
+
+func (r *Request) expectsContinue() bool {
+	return strings.ToLower(r.Header.Get("Expect")) == "100-continue"
+}
+
+func (r *Request) wantsHttp10KeepAlive() bool {
+	if r.ProtoMajor != 1 || r.ProtoMinor != 0 {
+		return false
+	}
+	return strings.Contains(strings.ToLower(r.Header.Get("Connection")), "keep-alive")
+}
diff --git a/src/pkg/net/http/request_test.go b/src/pkg/net/http/request_test.go
new file mode 100644
index 0000000..7a3556d
--- /dev/null
+++ b/src/pkg/net/http/request_test.go
@@ -0,0 +1,283 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http_test
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"mime/multipart"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
+	"testing"
+)
+
+func TestQuery(t *testing.T) {
+	req := &Request{Method: "GET"}
+	req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
+	if q := req.FormValue("q"); q != "foo" {
+		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
+	}
+}
+
+func TestPostQuery(t *testing.T) {
+	req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x",
+		strings.NewReader("z=post&both=y"))
+	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
+
+	if q := req.FormValue("q"); q != "foo" {
+		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
+	}
+	if z := req.FormValue("z"); z != "post" {
+		t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
+	}
+	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"x", "y"}) {
+		t.Errorf(`req.FormValue("both") = %q, want ["x", "y"]`, both)
+	}
+}
+
+type stringMap map[string][]string
+type parseContentTypeTest struct {
+	shouldError bool
+	contentType stringMap
+}
+
+var parseContentTypeTests = []parseContentTypeTest{
+	{false, stringMap{"Content-Type": {"text/plain"}}},
+	// Non-existent keys are not placed. The value nil is illegal.
+	{true, stringMap{}},
+	{true, stringMap{"Content-Type": {"text/plain; boundary="}}},
+	{false, stringMap{"Content-Type": {"application/unknown"}}},
+}
+
+func TestParseFormUnknownContentType(t *testing.T) {
+	for i, test := range parseContentTypeTests {
+		req := &Request{
+			Method: "POST",
+			Header: Header(test.contentType),
+			Body:   ioutil.NopCloser(bytes.NewBufferString("body")),
+		}
+		err := req.ParseForm()
+		switch {
+		case err == nil && test.shouldError:
+			t.Errorf("test %d should have returned error", i)
+		case err != nil && !test.shouldError:
+			t.Errorf("test %d should not have returned error, got %v", i, err)
+		}
+	}
+}
+
+func TestMultipartReader(t *testing.T) {
+	req := &Request{
+		Method: "POST",
+		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
+		Body:   ioutil.NopCloser(new(bytes.Buffer)),
+	}
+	multipart, err := req.MultipartReader()
+	if multipart == nil {
+		t.Errorf("expected multipart; error: %v", err)
+	}
+
+	req.Header = Header{"Content-Type": {"text/plain"}}
+	multipart, err = req.MultipartReader()
+	if multipart != nil {
+		t.Errorf("unexpected multipart for text/plain")
+	}
+}
+
+func TestRedirect(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		switch r.URL.Path {
+		case "/":
+			w.Header().Set("Location", "/foo/")
+			w.WriteHeader(StatusSeeOther)
+		case "/foo/":
+			fmt.Fprintf(w, "foo")
+		default:
+			w.WriteHeader(StatusBadRequest)
+		}
+	}))
+	defer ts.Close()
+
+	var end = regexp.MustCompile("/foo/$")
+	r, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	r.Body.Close()
+	url := r.Request.URL.String()
+	if r.StatusCode != 200 || !end.MatchString(url) {
+		t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
+	}
+}
+
+func TestSetBasicAuth(t *testing.T) {
+	r, _ := NewRequest("GET", "http://example.com/", nil)
+	r.SetBasicAuth("Aladdin", "open sesame")
+	if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e {
+		t.Errorf("got header %q, want %q", g, e)
+	}
+}
+
+func TestMultipartRequest(t *testing.T) {
+	// Test that we can read the values and files of a 
+	// multipart request with FormValue and FormFile,
+	// and that ParseMultipartForm can be called multiple times.
+	req := newTestMultipartRequest(t)
+	if err := req.ParseMultipartForm(25); err != nil {
+		t.Fatal("ParseMultipartForm first call:", err)
+	}
+	defer req.MultipartForm.RemoveAll()
+	validateTestMultipartContents(t, req, false)
+	if err := req.ParseMultipartForm(25); err != nil {
+		t.Fatal("ParseMultipartForm second call:", err)
+	}
+	validateTestMultipartContents(t, req, false)
+}
+
+func TestMultipartRequestAuto(t *testing.T) {
+	// Test that FormValue and FormFile automatically invoke
+	// ParseMultipartForm and return the right values.
+	req := newTestMultipartRequest(t)
+	defer func() {
+		if req.MultipartForm != nil {
+			req.MultipartForm.RemoveAll()
+		}
+	}()
+	validateTestMultipartContents(t, req, true)
+}
+
+func TestEmptyMultipartRequest(t *testing.T) {
+	// Test that FormValue and FormFile automatically invoke
+	// ParseMultipartForm and return the right values.
+	req, err := NewRequest("GET", "/", nil)
+	if err != nil {
+		t.Errorf("NewRequest err = %q", err)
+	}
+	testMissingFile(t, req)
+}
+
+func TestRequestMultipartCallOrder(t *testing.T) {
+	req := newTestMultipartRequest(t)
+	_, err := req.MultipartReader()
+	if err != nil {
+		t.Fatalf("MultipartReader: %v", err)
+	}
+	err = req.ParseMultipartForm(1024)
+	if err == nil {
+		t.Errorf("expected an error from ParseMultipartForm after call to MultipartReader")
+	}
+}
+
+func testMissingFile(t *testing.T, req *Request) {
+	f, fh, err := req.FormFile("missing")
+	if f != nil {
+		t.Errorf("FormFile file = %q, want nil", f)
+	}
+	if fh != nil {
+		t.Errorf("FormFile file header = %q, want nil", fh)
+	}
+	if err != ErrMissingFile {
+		t.Errorf("FormFile err = %q, want ErrMissingFile", err)
+	}
+}
+
+func newTestMultipartRequest(t *testing.T) *Request {
+	b := bytes.NewBufferString(strings.Replace(message, "\n", "\r\n", -1))
+	req, err := NewRequest("POST", "/", b)
+	if err != nil {
+		t.Fatal("NewRequest:", err)
+	}
+	ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
+	req.Header.Set("Content-type", ctype)
+	return req
+}
+
+func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
+	if g, e := req.FormValue("texta"), textaValue; g != e {
+		t.Errorf("texta value = %q, want %q", g, e)
+	}
+	if g, e := req.FormValue("textb"), textbValue; g != e {
+		t.Errorf("textb value = %q, want %q", g, e)
+	}
+	if g := req.FormValue("missing"); g != "" {
+		t.Errorf("missing value = %q, want empty string", g)
+	}
+
+	assertMem := func(n string, fd multipart.File) {
+		if _, ok := fd.(*os.File); ok {
+			t.Error(n, " is *os.File, should not be")
+		}
+	}
+	fda := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
+	defer fda.Close()
+	assertMem("filea", fda)
+	fdb := testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
+	defer fdb.Close()
+	if allMem {
+		assertMem("fileb", fdb)
+	} else {
+		if _, ok := fdb.(*os.File); !ok {
+			t.Errorf("fileb has unexpected underlying type %T", fdb)
+		}
+	}
+
+	testMissingFile(t, req)
+}
+
+func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
+	f, fh, err := req.FormFile(key)
+	if err != nil {
+		t.Fatalf("FormFile(%q): %q", key, err)
+	}
+	if fh.Filename != expectFilename {
+		t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
+	}
+	var b bytes.Buffer
+	_, err = io.Copy(&b, f)
+	if err != nil {
+		t.Fatal("copying contents:", err)
+	}
+	if g := b.String(); g != expectContent {
+		t.Errorf("contents = %q, want %q", g, expectContent)
+	}
+	return f
+}
+
+const (
+	fileaContents = "This is a test file."
+	filebContents = "Another test file."
+	textaValue    = "foo"
+	textbValue    = "bar"
+	boundary      = `MyBoundary`
+)
+
+const message = `
+--MyBoundary
+Content-Disposition: form-data; name="filea"; filename="filea.txt"
+Content-Type: text/plain
+
+` + fileaContents + `
+--MyBoundary
+Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
+Content-Type: text/plain
+
+` + filebContents + `
+--MyBoundary
+Content-Disposition: form-data; name="texta"
+
+` + textaValue + `
+--MyBoundary
+Content-Disposition: form-data; name="textb"
+
+` + textbValue + `
+--MyBoundary--
+`
diff --git a/src/pkg/net/http/requestwrite_test.go b/src/pkg/net/http/requestwrite_test.go
new file mode 100644
index 0000000..fc3186f
--- /dev/null
+++ b/src/pkg/net/http/requestwrite_test.go
@@ -0,0 +1,438 @@
+// Copyright 2010 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 http
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/url"
+	"strings"
+	"testing"
+)
+
+type reqWriteTest struct {
+	Req  Request
+	Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
+
+	// Any of these three may be empty to skip that test.
+	WantWrite string // Request.Write
+	WantProxy string // Request.WriteProxy
+
+	WantError error // wanted error from Request.Write
+}
+
+var reqWriteTests = []reqWriteTest{
+	// HTTP/1.1 => chunked coding; no body; no trailer
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.techcrunch.com",
+				Path:   "/",
+			},
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Header: Header{
+				"Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
+				"Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
+				"Accept-Encoding":  {"gzip,deflate"},
+				"Accept-Language":  {"en-us,en;q=0.5"},
+				"Keep-Alive":       {"300"},
+				"Proxy-Connection": {"keep-alive"},
+				"User-Agent":       {"Fake"},
+			},
+			Body:  nil,
+			Close: false,
+			Host:  "www.techcrunch.com",
+			Form:  map[string][]string{},
+		},
+
+		WantWrite: "GET / HTTP/1.1\r\n" +
+			"Host: www.techcrunch.com\r\n" +
+			"User-Agent: Fake\r\n" +
+			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
+			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
+			"Accept-Encoding: gzip,deflate\r\n" +
+			"Accept-Language: en-us,en;q=0.5\r\n" +
+			"Keep-Alive: 300\r\n" +
+			"Proxy-Connection: keep-alive\r\n\r\n",
+
+		WantProxy: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
+			"Host: www.techcrunch.com\r\n" +
+			"User-Agent: Fake\r\n" +
+			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
+			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
+			"Accept-Encoding: gzip,deflate\r\n" +
+			"Accept-Language: en-us,en;q=0.5\r\n" +
+			"Keep-Alive: 300\r\n" +
+			"Proxy-Connection: keep-alive\r\n\r\n",
+	},
+	// HTTP/1.1 => chunked coding; body; empty trailer
+	{
+		Req: Request{
+			Method: "GET",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Header:           Header{},
+			TransferEncoding: []string{"chunked"},
+		},
+
+		Body: []byte("abcdef"),
+
+		WantWrite: "GET /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+
+		WantProxy: "GET http://www.google.com/search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+	},
+	// HTTP/1.1 POST => chunked coding; body; empty trailer
+	{
+		Req: Request{
+			Method: "POST",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:       1,
+			ProtoMinor:       1,
+			Header:           Header{},
+			Close:            true,
+			TransferEncoding: []string{"chunked"},
+		},
+
+		Body: []byte("abcdef"),
+
+		WantWrite: "POST /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Connection: close\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+
+		WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Connection: close\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("abcdef") + chunk(""),
+	},
+
+	// HTTP/1.1 POST with Content-Length, no chunking
+	{
+		Req: Request{
+			Method: "POST",
+			URL: &url.URL{
+				Scheme: "http",
+				Host:   "www.google.com",
+				Path:   "/search",
+			},
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Close:         true,
+			ContentLength: 6,
+		},
+
+		Body: []byte("abcdef"),
+
+		WantWrite: "POST /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Connection: close\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+
+		WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Connection: close\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+	},
+
+	// HTTP/1.1 POST with Content-Length in headers
+	{
+		Req: Request{
+			Method: "POST",
+			URL:    mustParseURL("http://example.com/"),
+			Host:   "example.com",
+			Header: Header{
+				"Content-Length": []string{"10"}, // ignored
+			},
+			ContentLength: 6,
+		},
+
+		Body: []byte("abcdef"),
+
+		WantWrite: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+
+		WantProxy: "POST http://example.com/ HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Content-Length: 6\r\n" +
+			"\r\n" +
+			"abcdef",
+	},
+
+	// default to HTTP/1.1
+	{
+		Req: Request{
+			Method: "GET",
+			URL:    mustParseURL("/search"),
+			Host:   "www.google.com",
+		},
+
+		WantWrite: "GET /search HTTP/1.1\r\n" +
+			"Host: www.google.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"\r\n",
+	},
+
+	// Request with a 0 ContentLength and a 0 byte body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 0, // as if unset by user
+		},
+
+		Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
+
+		// RFC 2616 Section 14.13 says Content-Length should be specified
+		// unless body is prohibited by the request method.
+		// Also, nginx expects it for POST and PUT.
+		WantWrite: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Content-Length: 0\r\n" +
+			"\r\n",
+
+		WantProxy: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Content-Length: 0\r\n" +
+			"\r\n",
+	},
+
+	// Request with a 0 ContentLength and a 1 byte body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 0, // as if unset by user
+		},
+
+		Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
+
+		WantWrite: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("x") + chunk(""),
+
+		WantProxy: "POST / HTTP/1.1\r\n" +
+			"Host: example.com\r\n" +
+			"User-Agent: Go http package\r\n" +
+			"Transfer-Encoding: chunked\r\n\r\n" +
+			chunk("x") + chunk(""),
+	},
+
+	// Request with a ContentLength of 10 but a 5 byte body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 10, // but we're going to send only 5 bytes
+		},
+		Body:      []byte("12345"),
+		WantError: errors.New("http: Request.ContentLength=10 with Body length 5"),
+	},
+
+	// Request with a ContentLength of 4 but an 8 byte body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 4, // but we're going to try to send 8 bytes
+		},
+		Body:      []byte("12345678"),
+		WantError: errors.New("http: Request.ContentLength=4 with Body length 8"),
+	},
+
+	// Request with a 5 ContentLength and nil body.
+	{
+		Req: Request{
+			Method:        "POST",
+			URL:           mustParseURL("/"),
+			Host:          "example.com",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			ContentLength: 5, // but we'll omit the body
+		},
+		WantError: errors.New("http: Request.ContentLength=5 with nil Body"),
+	},
+
+	// Verify that DumpRequest preserves the HTTP version number, doesn't add a Host,
+	// and doesn't add a User-Agent.
+	{
+		Req: Request{
+			Method:     "GET",
+			URL:        mustParseURL("/foo"),
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Header: Header{
+				"X-Foo": []string{"X-Bar"},
+			},
+		},
+
+		WantWrite: "GET /foo HTTP/1.1\r\n" +
+			"Host: \r\n" +
+			"User-Agent: Go http package\r\n" +
+			"X-Foo: X-Bar\r\n\r\n",
+	},
+}
+
+func TestRequestWrite(t *testing.T) {
+	for i := range reqWriteTests {
+		tt := &reqWriteTests[i]
+
+		setBody := func() {
+			if tt.Body == nil {
+				return
+			}
+			switch b := tt.Body.(type) {
+			case []byte:
+				tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
+			case func() io.ReadCloser:
+				tt.Req.Body = b()
+			}
+		}
+		setBody()
+		if tt.Req.Header == nil {
+			tt.Req.Header = make(Header)
+		}
+
+		var braw bytes.Buffer
+		err := tt.Req.Write(&braw)
+		if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.WantError); g != e {
+			t.Errorf("writing #%d, err = %q, want %q", i, g, e)
+			continue
+		}
+		if err != nil {
+			continue
+		}
+
+		if tt.WantWrite != "" {
+			sraw := braw.String()
+			if sraw != tt.WantWrite {
+				t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantWrite, sraw)
+				continue
+			}
+		}
+
+		if tt.WantProxy != "" {
+			setBody()
+			var praw bytes.Buffer
+			err = tt.Req.WriteProxy(&praw)
+			if err != nil {
+				t.Errorf("WriteProxy #%d: %s", i, err)
+				continue
+			}
+			sraw := praw.String()
+			if sraw != tt.WantProxy {
+				t.Errorf("Test Proxy %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantProxy, sraw)
+				continue
+			}
+		}
+	}
+}
+
+type closeChecker struct {
+	io.Reader
+	closed bool
+}
+
+func (rc *closeChecker) Close() error {
+	rc.closed = true
+	return nil
+}
+
+// TestRequestWriteClosesBody tests that Request.Write does close its request.Body.
+// It also indirectly tests NewRequest and that it doesn't wrap an existing Closer
+// inside a NopCloser, and that it serializes it correctly.
+func TestRequestWriteClosesBody(t *testing.T) {
+	rc := &closeChecker{Reader: strings.NewReader("my body")}
+	req, _ := NewRequest("POST", "http://foo.com/", rc)
+	if req.ContentLength != 0 {
+		t.Errorf("got req.ContentLength %d, want 0", req.ContentLength)
+	}
+	buf := new(bytes.Buffer)
+	req.Write(buf)
+	if !rc.closed {
+		t.Error("body not closed after write")
+	}
+	expected := "POST / HTTP/1.1\r\n" +
+		"Host: foo.com\r\n" +
+		"User-Agent: Go http package\r\n" +
+		"Transfer-Encoding: chunked\r\n\r\n" +
+		// TODO: currently we don't buffer before chunking, so we get a
+		// single "m" chunk before the other chunks, as this was the 1-byte
+		// read from our MultiReader where we stiched the Body back together
+		// after sniffing whether the Body was 0 bytes or not.
+		chunk("m") +
+		chunk("y body") +
+		chunk("")
+	if buf.String() != expected {
+		t.Errorf("write:\n got: %s\nwant: %s", buf.String(), expected)
+	}
+}
+
+func chunk(s string) string {
+	return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
+}
+
+func mustParseURL(s string) *url.URL {
+	u, err := url.Parse(s)
+	if err != nil {
+		panic(fmt.Sprintf("Error parsing URL %q: %v", s, err))
+	}
+	return u
+}
diff --git a/src/pkg/net/http/response.go b/src/pkg/net/http/response.go
new file mode 100644
index 0000000..ae314b5
--- /dev/null
+++ b/src/pkg/net/http/response.go
@@ -0,0 +1,236 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// HTTP Response reading and parsing.
+
+package http
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"net/textproto"
+	"net/url"
+	"strconv"
+	"strings"
+)
+
+var respExcludeHeader = map[string]bool{
+	"Content-Length":    true,
+	"Transfer-Encoding": true,
+	"Trailer":           true,
+}
+
+// Response represents the response from an HTTP request.
+//
+type Response struct {
+	Status     string // e.g. "200 OK"
+	StatusCode int    // e.g. 200
+	Proto      string // e.g. "HTTP/1.0"
+	ProtoMajor int    // e.g. 1
+	ProtoMinor int    // e.g. 0
+
+	// Header maps header keys to values.  If the response had multiple
+	// headers with the same key, they will be concatenated, with comma
+	// delimiters.  (Section 4.2 of RFC 2616 requires that multiple headers
+	// be semantically equivalent to a comma-delimited sequence.) Values
+	// duplicated by other fields in this struct (e.g., ContentLength) are
+	// omitted from Header.
+	//
+	// Keys in the map are canonicalized (see CanonicalHeaderKey).
+	Header Header
+
+	// Body represents the response body.
+	//
+	// The http Client and Transport guarantee that Body is always
+	// non-nil, even on responses without a body or responses with
+	// a zero-lengthed body.
+	Body io.ReadCloser
+
+	// ContentLength records the length of the associated content.  The
+	// value -1 indicates that the length is unknown.  Unless RequestMethod
+	// is "HEAD", values >= 0 indicate that the given number of bytes may
+	// be read from Body.
+	ContentLength int64
+
+	// Contains transfer encodings from outer-most to inner-most. Value is
+	// nil, means that "identity" encoding is used.
+	TransferEncoding []string
+
+	// Close records whether the header directed that the connection be
+	// closed after reading Body.  The value is advice for clients: neither
+	// ReadResponse nor Response.Write ever closes a connection.
+	Close bool
+
+	// Trailer maps trailer keys to values, in the same
+	// format as the header.
+	Trailer Header
+
+	// The Request that was sent to obtain this Response.
+	// Request's Body is nil (having already been consumed).
+	// This is only populated for Client requests.
+	Request *Request
+}
+
+// Cookies parses and returns the cookies set in the Set-Cookie headers.
+func (r *Response) Cookies() []*Cookie {
+	return readSetCookies(r.Header)
+}
+
+var ErrNoLocation = errors.New("http: no Location header in response")
+
+// Location returns the URL of the response's "Location" header,
+// if present.  Relative redirects are resolved relative to
+// the Response's Request.  ErrNoLocation is returned if no
+// Location header is present.
+func (r *Response) Location() (*url.URL, error) {
+	lv := r.Header.Get("Location")
+	if lv == "" {
+		return nil, ErrNoLocation
+	}
+	if r.Request != nil && r.Request.URL != nil {
+		return r.Request.URL.Parse(lv)
+	}
+	return url.Parse(lv)
+}
+
+// ReadResponse reads and returns an HTTP response from r.  The
+// req parameter specifies the Request that corresponds to
+// this Response.  Clients must call resp.Body.Close when finished
+// reading resp.Body.  After that call, clients can inspect
+// resp.Trailer to find key/value pairs included in the response
+// trailer.
+func ReadResponse(r *bufio.Reader, req *Request) (resp *Response, err error) {
+
+	tp := textproto.NewReader(r)
+	resp = new(Response)
+
+	resp.Request = req
+	resp.Request.Method = strings.ToUpper(resp.Request.Method)
+
+	// Parse the first line of the response.
+	line, err := tp.ReadLine()
+	if err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		return nil, err
+	}
+	f := strings.SplitN(line, " ", 3)
+	if len(f) < 2 {
+		return nil, &badStringError{"malformed HTTP response", line}
+	}
+	reasonPhrase := ""
+	if len(f) > 2 {
+		reasonPhrase = f[2]
+	}
+	resp.Status = f[1] + " " + reasonPhrase
+	resp.StatusCode, err = strconv.Atoi(f[1])
+	if err != nil {
+		return nil, &badStringError{"malformed HTTP status code", f[1]}
+	}
+
+	resp.Proto = f[0]
+	var ok bool
+	if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok {
+		return nil, &badStringError{"malformed HTTP version", resp.Proto}
+	}
+
+	// Parse the response headers.
+	mimeHeader, err := tp.ReadMIMEHeader()
+	if err != nil {
+		return nil, err
+	}
+	resp.Header = Header(mimeHeader)
+
+	fixPragmaCacheControl(resp.Header)
+
+	err = readTransfer(resp, r)
+	if err != nil {
+		return nil, err
+	}
+
+	return resp, nil
+}
+
+// RFC2616: Should treat
+//	Pragma: no-cache
+// like
+//	Cache-Control: no-cache
+func fixPragmaCacheControl(header Header) {
+	if hp, ok := header["Pragma"]; ok && len(hp) > 0 && hp[0] == "no-cache" {
+		if _, presentcc := header["Cache-Control"]; !presentcc {
+			header["Cache-Control"] = []string{"no-cache"}
+		}
+	}
+}
+
+// ProtoAtLeast returns whether the HTTP protocol used
+// in the response is at least major.minor.
+func (r *Response) ProtoAtLeast(major, minor int) bool {
+	return r.ProtoMajor > major ||
+		r.ProtoMajor == major && r.ProtoMinor >= minor
+}
+
+// Writes the response (header, body and trailer) in wire format. This method
+// consults the following fields of resp:
+//
+//  StatusCode
+//  ProtoMajor
+//  ProtoMinor
+//  RequestMethod
+//  TransferEncoding
+//  Trailer
+//  Body
+//  ContentLength
+//  Header, values for non-canonical keys will have unpredictable behavior
+//
+func (resp *Response) Write(w io.Writer) error {
+
+	// RequestMethod should be upper-case
+	if resp.Request != nil {
+		resp.Request.Method = strings.ToUpper(resp.Request.Method)
+	}
+
+	// Status line
+	text := resp.Status
+	if text == "" {
+		var ok bool
+		text, ok = statusText[resp.StatusCode]
+		if !ok {
+			text = "status code " + strconv.Itoa(resp.StatusCode)
+		}
+	}
+	io.WriteString(w, "HTTP/"+strconv.Itoa(resp.ProtoMajor)+".")
+	io.WriteString(w, strconv.Itoa(resp.ProtoMinor)+" ")
+	io.WriteString(w, strconv.Itoa(resp.StatusCode)+" "+text+"\r\n")
+
+	// Process Body,ContentLength,Close,Trailer
+	tw, err := newTransferWriter(resp)
+	if err != nil {
+		return err
+	}
+	err = tw.WriteHeader(w)
+	if err != nil {
+		return err
+	}
+
+	// Rest of header
+	err = resp.Header.WriteSubset(w, respExcludeHeader)
+	if err != nil {
+		return err
+	}
+
+	// End-of-header
+	io.WriteString(w, "\r\n")
+
+	// Write body and trailer
+	err = tw.WriteBody(w)
+	if err != nil {
+		return err
+	}
+
+	// Success
+	return nil
+}
diff --git a/src/pkg/net/http/response_test.go b/src/pkg/net/http/response_test.go
new file mode 100644
index 0000000..e5d0169
--- /dev/null
+++ b/src/pkg/net/http/response_test.go
@@ -0,0 +1,448 @@
+// Copyright 2010 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 http
+
+import (
+	"bufio"
+	"bytes"
+	"compress/gzip"
+	"crypto/rand"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/url"
+	"reflect"
+	"testing"
+)
+
+type respTest struct {
+	Raw  string
+	Resp Response
+	Body string
+}
+
+func dummyReq(method string) *Request {
+	return &Request{Method: method}
+}
+
+var respTests = []respTest{
+	// Unchunked response without Content-Length.
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Connection: close\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:     "200 OK",
+			StatusCode: 200,
+			Proto:      "HTTP/1.0",
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Connection": {"close"}, // TODO(rsc): Delete?
+			},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"Body here\n",
+	},
+
+	// Unchunked HTTP/1.1 response without Content-Length or
+	// Connection headers.
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:        "200 OK",
+			StatusCode:    200,
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Request:       dummyReq("GET"),
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"Body here\n",
+	},
+
+	// Unchunked HTTP/1.1 204 response without Content-Length.
+	{
+		"HTTP/1.1 204 No Content\r\n" +
+			"\r\n" +
+			"Body should not be read!\n",
+
+		Response{
+			Status:        "204 No Content",
+			StatusCode:    204,
+			Proto:         "HTTP/1.1",
+			ProtoMajor:    1,
+			ProtoMinor:    1,
+			Header:        Header{},
+			Request:       dummyReq("GET"),
+			Close:         false,
+			ContentLength: 0,
+		},
+
+		"",
+	},
+
+	// Unchunked response with Content-Length.
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Content-Length: 10\r\n" +
+			"Connection: close\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:     "200 OK",
+			StatusCode: 200,
+			Proto:      "HTTP/1.0",
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Connection":     {"close"}, // TODO(rsc): Delete?
+				"Content-Length": {"10"},    // TODO(rsc): Delete?
+			},
+			Close:         true,
+			ContentLength: 10,
+		},
+
+		"Body here\n",
+	},
+
+	// Chunked response without Content-Length.
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Transfer-Encoding: chunked\r\n" +
+			"\r\n" +
+			"0a\r\n" +
+			"Body here\n\r\n" +
+			"09\r\n" +
+			"continued\r\n" +
+			"0\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Request:          dummyReq("GET"),
+			Header:           Header{},
+			Close:            true,
+			ContentLength:    -1,
+			TransferEncoding: []string{"chunked"},
+		},
+
+		"Body here\ncontinued",
+	},
+
+	// Chunked response with Content-Length.
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Transfer-Encoding: chunked\r\n" +
+			"Content-Length: 10\r\n" +
+			"\r\n" +
+			"0a\r\n" +
+			"Body here\n" +
+			"0\r\n" +
+			"\r\n",
+
+		Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Request:          dummyReq("GET"),
+			Header:           Header{},
+			Close:            true,
+			ContentLength:    -1, // TODO(rsc): Fix?
+			TransferEncoding: []string{"chunked"},
+		},
+
+		"Body here\n",
+	},
+
+	// Chunked response in response to a HEAD request (the "chunked" should
+	// be ignored, as HEAD responses never have bodies)
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Transfer-Encoding: chunked\r\n" +
+			"\r\n",
+
+		Response{
+			Status:        "200 OK",
+			StatusCode:    200,
+			Proto:         "HTTP/1.0",
+			ProtoMajor:    1,
+			ProtoMinor:    0,
+			Request:       dummyReq("HEAD"),
+			Header:        Header{},
+			Close:         true,
+			ContentLength: 0,
+		},
+
+		"",
+	},
+
+	// explicit Content-Length of 0.
+	{
+		"HTTP/1.1 200 OK\r\n" +
+			"Content-Length: 0\r\n" +
+			"\r\n",
+
+		Response{
+			Status:     "200 OK",
+			StatusCode: 200,
+			Proto:      "HTTP/1.1",
+			ProtoMajor: 1,
+			ProtoMinor: 1,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Content-Length": {"0"},
+			},
+			Close:         false,
+			ContentLength: 0,
+		},
+
+		"",
+	},
+
+	// Status line without a Reason-Phrase, but trailing space.
+	// (permitted by RFC 2616)
+	{
+		"HTTP/1.0 303 \r\n\r\n",
+		Response{
+			Status:        "303 ",
+			StatusCode:    303,
+			Proto:         "HTTP/1.0",
+			ProtoMajor:    1,
+			ProtoMinor:    0,
+			Request:       dummyReq("GET"),
+			Header:        Header{},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"",
+	},
+
+	// Status line without a Reason-Phrase, and no trailing space.
+	// (not permitted by RFC 2616, but we'll accept it anyway)
+	{
+		"HTTP/1.0 303\r\n\r\n",
+		Response{
+			Status:        "303 ",
+			StatusCode:    303,
+			Proto:         "HTTP/1.0",
+			ProtoMajor:    1,
+			ProtoMinor:    0,
+			Request:       dummyReq("GET"),
+			Header:        Header{},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"",
+	},
+}
+
+func TestReadResponse(t *testing.T) {
+	for i := range respTests {
+		tt := &respTests[i]
+		var braw bytes.Buffer
+		braw.WriteString(tt.Raw)
+		resp, err := ReadResponse(bufio.NewReader(&braw), tt.Resp.Request)
+		if err != nil {
+			t.Errorf("#%d: %s", i, err)
+			continue
+		}
+		rbody := resp.Body
+		resp.Body = nil
+		diff(t, fmt.Sprintf("#%d Response", i), resp, &tt.Resp)
+		var bout bytes.Buffer
+		if rbody != nil {
+			io.Copy(&bout, rbody)
+			rbody.Close()
+		}
+		body := bout.String()
+		if body != tt.Body {
+			t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
+		}
+	}
+}
+
+var readResponseCloseInMiddleTests = []struct {
+	chunked, compressed bool
+}{
+	{false, false},
+	{true, false},
+	{true, true},
+}
+
+// TestReadResponseCloseInMiddle tests that closing a body after
+// reading only part of its contents advances the read to the end of
+// the request, right up until the next request.
+func TestReadResponseCloseInMiddle(t *testing.T) {
+	for _, test := range readResponseCloseInMiddleTests {
+		fatalf := func(format string, args ...interface{}) {
+			args = append([]interface{}{test.chunked, test.compressed}, args...)
+			t.Fatalf("on test chunked=%v, compressed=%v: "+format, args...)
+		}
+		checkErr := func(err error, msg string) {
+			if err == nil {
+				return
+			}
+			fatalf(msg+": %v", err)
+		}
+		var buf bytes.Buffer
+		buf.WriteString("HTTP/1.1 200 OK\r\n")
+		if test.chunked {
+			buf.WriteString("Transfer-Encoding: chunked\r\n")
+		} else {
+			buf.WriteString("Content-Length: 1000000\r\n")
+		}
+		var wr io.Writer = &buf
+		if test.chunked {
+			wr = newChunkedWriter(wr)
+		}
+		if test.compressed {
+			buf.WriteString("Content-Encoding: gzip\r\n")
+			var err error
+			wr, err = gzip.NewWriter(wr)
+			checkErr(err, "gzip.NewWriter")
+		}
+		buf.WriteString("\r\n")
+
+		chunk := bytes.Repeat([]byte{'x'}, 1000)
+		for i := 0; i < 1000; i++ {
+			if test.compressed {
+				// Otherwise this compresses too well.
+				_, err := io.ReadFull(rand.Reader, chunk)
+				checkErr(err, "rand.Reader ReadFull")
+			}
+			wr.Write(chunk)
+		}
+		if test.compressed {
+			err := wr.(*gzip.Compressor).Close()
+			checkErr(err, "compressor close")
+		}
+		if test.chunked {
+			buf.WriteString("0\r\n\r\n")
+		}
+		buf.WriteString("Next Request Here")
+
+		bufr := bufio.NewReader(&buf)
+		resp, err := ReadResponse(bufr, dummyReq("GET"))
+		checkErr(err, "ReadResponse")
+		expectedLength := int64(-1)
+		if !test.chunked {
+			expectedLength = 1000000
+		}
+		if resp.ContentLength != expectedLength {
+			fatalf("expected response length %d, got %d", expectedLength, resp.ContentLength)
+		}
+		if resp.Body == nil {
+			fatalf("nil body")
+		}
+		if test.compressed {
+			gzReader, err := gzip.NewReader(resp.Body)
+			checkErr(err, "gzip.NewReader")
+			resp.Body = &readFirstCloseBoth{gzReader, resp.Body}
+		}
+
+		rbuf := make([]byte, 2500)
+		n, err := io.ReadFull(resp.Body, rbuf)
+		checkErr(err, "2500 byte ReadFull")
+		if n != 2500 {
+			fatalf("ReadFull only read %d bytes", n)
+		}
+		if test.compressed == false && !bytes.Equal(bytes.Repeat([]byte{'x'}, 2500), rbuf) {
+			fatalf("ReadFull didn't read 2500 'x'; got %q", string(rbuf))
+		}
+		resp.Body.Close()
+
+		rest, err := ioutil.ReadAll(bufr)
+		checkErr(err, "ReadAll on remainder")
+		if e, g := "Next Request Here", string(rest); e != g {
+			fatalf("remainder = %q, expected %q", g, e)
+		}
+	}
+}
+
+func diff(t *testing.T, prefix string, have, want interface{}) {
+	hv := reflect.ValueOf(have).Elem()
+	wv := reflect.ValueOf(want).Elem()
+	if hv.Type() != wv.Type() {
+		t.Errorf("%s: type mismatch %v want %v", prefix, hv.Type(), wv.Type())
+	}
+	for i := 0; i < hv.NumField(); i++ {
+		hf := hv.Field(i).Interface()
+		wf := wv.Field(i).Interface()
+		if !reflect.DeepEqual(hf, wf) {
+			t.Errorf("%s: %s = %v want %v", prefix, hv.Type().Field(i).Name, hf, wf)
+		}
+	}
+}
+
+type responseLocationTest struct {
+	location string // Response's Location header or ""
+	requrl   string // Response.Request.URL or ""
+	want     string
+	wantErr  error
+}
+
+var responseLocationTests = []responseLocationTest{
+	{"/foo", "http://bar.com/baz", "http://bar.com/foo", nil},
+	{"http://foo.com/", "http://bar.com/baz", "http://foo.com/", nil},
+	{"", "http://bar.com/baz", "", ErrNoLocation},
+}
+
+func TestLocationResponse(t *testing.T) {
+	for i, tt := range responseLocationTests {
+		res := new(Response)
+		res.Header = make(Header)
+		res.Header.Set("Location", tt.location)
+		if tt.requrl != "" {
+			res.Request = &Request{}
+			var err error
+			res.Request.URL, err = url.Parse(tt.requrl)
+			if err != nil {
+				t.Fatalf("bad test URL %q: %v", tt.requrl, err)
+			}
+		}
+
+		got, err := res.Location()
+		if tt.wantErr != nil {
+			if err == nil {
+				t.Errorf("%d. err=nil; want %q", i, tt.wantErr)
+				continue
+			}
+			if g, e := err.Error(), tt.wantErr.Error(); g != e {
+				t.Errorf("%d. err=%q; want %q", i, g, e)
+				continue
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("%d. err=%q", i, err)
+			continue
+		}
+		if g, e := got.String(), tt.want; g != e {
+			t.Errorf("%d. Location=%q; want %q", i, g, e)
+		}
+	}
+}
diff --git a/src/pkg/http/responsewrite_test.go b/src/pkg/net/http/responsewrite_test.go
similarity index 100%
rename from src/pkg/http/responsewrite_test.go
rename to src/pkg/net/http/responsewrite_test.go
diff --git a/src/pkg/net/http/serve_test.go b/src/pkg/net/http/serve_test.go
new file mode 100644
index 0000000..147c216
--- /dev/null
+++ b/src/pkg/net/http/serve_test.go
@@ -0,0 +1,1182 @@
+// Copyright 2010 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.
+
+// End-to-end serving tests
+
+package http_test
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	. "net/http"
+	"net/http/httptest"
+	"net/http/httputil"
+	"net/url"
+	"os"
+	"reflect"
+	"strings"
+	"syscall"
+	"testing"
+	"time"
+)
+
+type dummyAddr string
+type oneConnListener struct {
+	conn net.Conn
+}
+
+func (l *oneConnListener) Accept() (c net.Conn, err error) {
+	c = l.conn
+	if c == nil {
+		err = io.EOF
+		return
+	}
+	err = nil
+	l.conn = nil
+	return
+}
+
+func (l *oneConnListener) Close() error {
+	return nil
+}
+
+func (l *oneConnListener) Addr() net.Addr {
+	return dummyAddr("test-address")
+}
+
+func (a dummyAddr) Network() string {
+	return string(a)
+}
+
+func (a dummyAddr) String() string {
+	return string(a)
+}
+
+type testConn struct {
+	readBuf  bytes.Buffer
+	writeBuf bytes.Buffer
+}
+
+func (c *testConn) Read(b []byte) (int, error) {
+	return c.readBuf.Read(b)
+}
+
+func (c *testConn) Write(b []byte) (int, error) {
+	return c.writeBuf.Write(b)
+}
+
+func (c *testConn) Close() error {
+	return nil
+}
+
+func (c *testConn) LocalAddr() net.Addr {
+	return dummyAddr("local-addr")
+}
+
+func (c *testConn) RemoteAddr() net.Addr {
+	return dummyAddr("remote-addr")
+}
+
+func (c *testConn) SetDeadline(t time.Time) error {
+	return nil
+}
+
+func (c *testConn) SetReadDeadline(t time.Time) error {
+	return nil
+}
+
+func (c *testConn) SetWriteDeadline(t time.Time) error {
+	return nil
+}
+
+func TestConsumingBodyOnNextConn(t *testing.T) {
+	conn := new(testConn)
+	for i := 0; i < 2; i++ {
+		conn.readBuf.Write([]byte(
+			"POST / HTTP/1.1\r\n" +
+				"Host: test\r\n" +
+				"Content-Length: 11\r\n" +
+				"\r\n" +
+				"foo=1&bar=1"))
+	}
+
+	reqNum := 0
+	ch := make(chan *Request)
+	servech := make(chan error)
+	listener := &oneConnListener{conn}
+	handler := func(res ResponseWriter, req *Request) {
+		reqNum++
+		ch <- req
+	}
+
+	go func() {
+		servech <- Serve(listener, HandlerFunc(handler))
+	}()
+
+	var req *Request
+	req = <-ch
+	if req == nil {
+		t.Fatal("Got nil first request.")
+	}
+	if req.Method != "POST" {
+		t.Errorf("For request #1's method, got %q; expected %q",
+			req.Method, "POST")
+	}
+
+	req = <-ch
+	if req == nil {
+		t.Fatal("Got nil first request.")
+	}
+	if req.Method != "POST" {
+		t.Errorf("For request #2's method, got %q; expected %q",
+			req.Method, "POST")
+	}
+
+	if serveerr := <-servech; serveerr != io.EOF {
+		t.Errorf("Serve returned %q; expected EOF", serveerr)
+	}
+}
+
+type stringHandler string
+
+func (s stringHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	w.Header().Set("Result", string(s))
+}
+
+var handlers = []struct {
+	pattern string
+	msg     string
+}{
+	{"/", "Default"},
+	{"/someDir/", "someDir"},
+	{"someHost.com/someDir/", "someHost.com/someDir"},
+}
+
+var vtests = []struct {
+	url      string
+	expected string
+}{
+	{"http://localhost/someDir/apage", "someDir"},
+	{"http://localhost/otherDir/apage", "Default"},
+	{"http://someHost.com/someDir/apage", "someHost.com/someDir"},
+	{"http://otherHost.com/someDir/apage", "someDir"},
+	{"http://otherHost.com/aDir/apage", "Default"},
+}
+
+func TestHostHandlers(t *testing.T) {
+	for _, h := range handlers {
+		Handle(h.pattern, stringHandler(h.msg))
+	}
+	ts := httptest.NewServer(nil)
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+	cc := httputil.NewClientConn(conn, nil)
+	for _, vt := range vtests {
+		var r *Response
+		var req Request
+		if req.URL, err = url.Parse(vt.url); err != nil {
+			t.Errorf("cannot parse url: %v", err)
+			continue
+		}
+		if err := cc.Write(&req); err != nil {
+			t.Errorf("writing request: %v", err)
+			continue
+		}
+		r, err := cc.Read(&req)
+		if err != nil {
+			t.Errorf("reading response: %v", err)
+			continue
+		}
+		s := r.Header.Get("Result")
+		if s != vt.expected {
+			t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
+		}
+	}
+}
+
+// Tests for http://code.google.com/p/go/issues/detail?id=900
+func TestMuxRedirectLeadingSlashes(t *testing.T) {
+	paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
+	for _, path := range paths {
+		req, err := ReadRequest(bufio.NewReader(bytes.NewBufferString("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n")))
+		if err != nil {
+			t.Errorf("%s", err)
+		}
+		mux := NewServeMux()
+		resp := httptest.NewRecorder()
+
+		mux.ServeHTTP(resp, req)
+
+		if loc, expected := resp.Header().Get("Location"), "/foo.txt"; loc != expected {
+			t.Errorf("Expected Location header set to %q; got %q", expected, loc)
+			return
+		}
+
+		if code, expected := resp.Code, StatusMovedPermanently; code != expected {
+			t.Errorf("Expected response code of StatusMovedPermanently; got %d", code)
+			return
+		}
+	}
+}
+
+func TestServerTimeouts(t *testing.T) {
+	// TODO(bradfitz): convert this to use httptest.Server
+	l, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("listen error: %v", err)
+	}
+	addr, _ := l.Addr().(*net.TCPAddr)
+
+	reqNum := 0
+	handler := HandlerFunc(func(res ResponseWriter, req *Request) {
+		reqNum++
+		fmt.Fprintf(res, "req=%d", reqNum)
+	})
+
+	const second = 1000000000 /* nanos */
+	server := &Server{Handler: handler, ReadTimeout: 0.25 * second, WriteTimeout: 0.25 * second}
+	go server.Serve(l)
+
+	url := fmt.Sprintf("http://%s/", addr)
+
+	// Hit the HTTP server successfully.
+	tr := &Transport{DisableKeepAlives: true} // they interfere with this test
+	c := &Client{Transport: tr}
+	r, err := c.Get(url)
+	if err != nil {
+		t.Fatalf("http Get #1: %v", err)
+	}
+	got, _ := ioutil.ReadAll(r.Body)
+	expected := "req=1"
+	if string(got) != expected {
+		t.Errorf("Unexpected response for request #1; got %q; expected %q",
+			string(got), expected)
+	}
+
+	// Slow client that should timeout.
+	t1 := time.Now()
+	conn, err := net.Dial("tcp", addr.String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	buf := make([]byte, 1)
+	n, err := conn.Read(buf)
+	latency := time.Now().Sub(t1)
+	if n != 0 || err != io.EOF {
+		t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, io.EOF)
+	}
+	if latency < 200*time.Millisecond /* fudge from 0.25 above */ {
+		t.Errorf("got EOF after %s, want >= %s", latency, 200*time.Millisecond)
+	}
+
+	// Hit the HTTP server successfully again, verifying that the
+	// previous slow connection didn't run our handler.  (that we
+	// get "req=2", not "req=3")
+	r, err = Get(url)
+	if err != nil {
+		t.Fatalf("http Get #2: %v", err)
+	}
+	got, _ = ioutil.ReadAll(r.Body)
+	expected = "req=2"
+	if string(got) != expected {
+		t.Errorf("Get #2 got %q, want %q", string(got), expected)
+	}
+
+	l.Close()
+}
+
+// TestIdentityResponse verifies that a handler can unset 
+func TestIdentityResponse(t *testing.T) {
+	handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
+		rw.Header().Set("Content-Length", "3")
+		rw.Header().Set("Transfer-Encoding", req.FormValue("te"))
+		switch {
+		case req.FormValue("overwrite") == "1":
+			_, err := rw.Write([]byte("foo TOO LONG"))
+			if err != ErrContentLength {
+				t.Errorf("expected ErrContentLength; got %v", err)
+			}
+		case req.FormValue("underwrite") == "1":
+			rw.Header().Set("Content-Length", "500")
+			rw.Write([]byte("too short"))
+		default:
+			rw.Write([]byte("foo"))
+		}
+	})
+
+	ts := httptest.NewServer(handler)
+	defer ts.Close()
+
+	// Note: this relies on the assumption (which is true) that
+	// Get sends HTTP/1.1 or greater requests.  Otherwise the
+	// server wouldn't have the choice to send back chunked
+	// responses.
+	for _, te := range []string{"", "identity"} {
+		url := ts.URL + "/?te=" + te
+		res, err := Get(url)
+		if err != nil {
+			t.Fatalf("error with Get of %s: %v", url, err)
+		}
+		if cl, expected := res.ContentLength, int64(3); cl != expected {
+			t.Errorf("for %s expected res.ContentLength of %d; got %d", url, expected, cl)
+		}
+		if cl, expected := res.Header.Get("Content-Length"), "3"; cl != expected {
+			t.Errorf("for %s expected Content-Length header of %q; got %q", url, expected, cl)
+		}
+		if tl, expected := len(res.TransferEncoding), 0; tl != expected {
+			t.Errorf("for %s expected len(res.TransferEncoding) of %d; got %d (%v)",
+				url, expected, tl, res.TransferEncoding)
+		}
+		res.Body.Close()
+	}
+
+	// Verify that ErrContentLength is returned
+	url := ts.URL + "/?overwrite=1"
+	_, err := Get(url)
+	if err != nil {
+		t.Fatalf("error with Get of %s: %v", url, err)
+	}
+	// Verify that the connection is closed when the declared Content-Length
+	// is larger than what the handler wrote.
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("error dialing: %v", err)
+	}
+	_, err = conn.Write([]byte("GET /?underwrite=1 HTTP/1.1\r\nHost: foo\r\n\r\n"))
+	if err != nil {
+		t.Fatalf("error writing: %v", err)
+	}
+
+	// The ReadAll will hang for a failing test, so use a Timer to
+	// fail explicitly.
+	goTimeout(t, 2*time.Second, func() {
+		got, _ := ioutil.ReadAll(conn)
+		expectedSuffix := "\r\n\r\ntoo short"
+		if !strings.HasSuffix(string(got), expectedSuffix) {
+			t.Errorf("Expected output to end with %q; got response body %q",
+				expectedSuffix, string(got))
+		}
+	})
+}
+
+func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
+	s := httptest.NewServer(h)
+	defer s.Close()
+
+	conn, err := net.Dial("tcp", s.Listener.Addr().String())
+	if err != nil {
+		t.Fatal("dial error:", err)
+	}
+	defer conn.Close()
+
+	_, err = fmt.Fprint(conn, req)
+	if err != nil {
+		t.Fatal("print error:", err)
+	}
+
+	r := bufio.NewReader(conn)
+	_, err = ReadResponse(r, &Request{Method: "GET"})
+	if err != nil {
+		t.Fatal("ReadResponse error:", err)
+	}
+
+	success := make(chan bool)
+	go func() {
+		select {
+		case <-time.After(5 * time.Second):
+			t.Fatal("body not closed after 5s")
+		case <-success:
+		}
+	}()
+
+	_, err = ioutil.ReadAll(r)
+	if err != nil {
+		t.Fatal("read error:", err)
+	}
+
+	success <- true
+}
+
+// TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
+func TestServeHTTP10Close(t *testing.T) {
+	testTcpConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+		ServeFile(w, r, "testdata/file")
+	}))
+}
+
+// TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close,
+// even for HTTP/1.1 requests.
+func TestHandlersCanSetConnectionClose11(t *testing.T) {
+	testTcpConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Connection", "close")
+	}))
+}
+
+func TestHandlersCanSetConnectionClose10(t *testing.T) {
+	testTcpConnectionCloses(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Connection", "close")
+	}))
+}
+
+func TestSetsRemoteAddr(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "%s", r.RemoteAddr)
+	}))
+	defer ts.Close()
+
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get error: %v", err)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatalf("ReadAll error: %v", err)
+	}
+	ip := string(body)
+	if !strings.HasPrefix(ip, "127.0.0.1:") && !strings.HasPrefix(ip, "[::1]:") {
+		t.Fatalf("Expected local addr; got %q", ip)
+	}
+}
+
+func TestChunkedResponseHeaders(t *testing.T) {
+	log.SetOutput(ioutil.Discard) // is noisy otherwise
+	defer log.SetOutput(os.Stderr)
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
+		fmt.Fprintf(w, "I am a chunked response.")
+	}))
+	defer ts.Close()
+
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get error: %v", err)
+	}
+	if g, e := res.ContentLength, int64(-1); g != e {
+		t.Errorf("expected ContentLength of %d; got %d", e, g)
+	}
+	if g, e := res.TransferEncoding, []string{"chunked"}; !reflect.DeepEqual(g, e) {
+		t.Errorf("expected TransferEncoding of %v; got %v", e, g)
+	}
+	if _, haveCL := res.Header["Content-Length"]; haveCL {
+		t.Errorf("Unexpected Content-Length")
+	}
+}
+
+// Test304Responses verifies that 304s don't declare that they're
+// chunking in their response headers and aren't allowed to produce
+// output.
+func Test304Responses(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.WriteHeader(StatusNotModified)
+		_, err := w.Write([]byte("illegal body"))
+		if err != ErrBodyNotAllowed {
+			t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
+		}
+	}))
+	defer ts.Close()
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(res.TransferEncoding) > 0 {
+		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(body) > 0 {
+		t.Errorf("got unexpected body %q", string(body))
+	}
+}
+
+// TestHeadResponses verifies that responses to HEAD requests don't
+// declare that they're chunking in their response headers and aren't
+// allowed to produce output.
+func TestHeadResponses(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		_, err := w.Write([]byte("Ignored body"))
+		if err != ErrBodyNotAllowed {
+			t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
+		}
+
+		// Also exercise the ReaderFrom path
+		_, err = io.Copy(w, strings.NewReader("Ignored body"))
+		if err != ErrBodyNotAllowed {
+			t.Errorf("on Copy, expected ErrBodyNotAllowed, got %v", err)
+		}
+	}))
+	defer ts.Close()
+	res, err := Head(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(res.TransferEncoding) > 0 {
+		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(body) > 0 {
+		t.Errorf("got unexpected body %q", string(body))
+	}
+}
+
+func TestTLSHandshakeTimeout(t *testing.T) {
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+	ts.Config.ReadTimeout = 250 * time.Millisecond
+	ts.StartTLS()
+	defer ts.Close()
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer conn.Close()
+	goTimeout(t, 10*time.Second, func() {
+		var buf [1]byte
+		n, err := conn.Read(buf[:])
+		if err == nil || n != 0 {
+			t.Errorf("Read = %d, %v; want an error and no bytes", n, err)
+		}
+	})
+}
+
+func TestTLSServer(t *testing.T) {
+	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.TLS != nil {
+			w.Header().Set("X-TLS-Set", "true")
+			if r.TLS.HandshakeComplete {
+				w.Header().Set("X-TLS-HandshakeComplete", "true")
+			}
+		}
+	}))
+	defer ts.Close()
+
+	// Connect an idle TCP connection to this server before we run
+	// our real tests.  This idle connection used to block forever
+	// in the TLS handshake, preventing future connections from
+	// being accepted. It may prevent future accidental blocking
+	// in newConn.
+	idleConn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer idleConn.Close()
+	goTimeout(t, 10*time.Second, func() {
+		if !strings.HasPrefix(ts.URL, "https://") {
+			t.Errorf("expected test TLS server to start with https://, got %q", ts.URL)
+			return
+		}
+		noVerifyTransport := &Transport{
+			TLSClientConfig: &tls.Config{
+				InsecureSkipVerify: true,
+			},
+		}
+		client := &Client{Transport: noVerifyTransport}
+		res, err := client.Get(ts.URL)
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		if res == nil {
+			t.Errorf("got nil Response")
+			return
+		}
+		defer res.Body.Close()
+		if res.Header.Get("X-TLS-Set") != "true" {
+			t.Errorf("expected X-TLS-Set response header")
+			return
+		}
+		if res.Header.Get("X-TLS-HandshakeComplete") != "true" {
+			t.Errorf("expected X-TLS-HandshakeComplete header")
+		}
+	})
+}
+
+type serverExpectTest struct {
+	contentLength    int    // of request body
+	expectation      string // e.g. "100-continue"
+	readBody         bool   // whether handler should read the body (if false, sends StatusUnauthorized)
+	expectedResponse string // expected substring in first line of http response
+}
+
+var serverExpectTests = []serverExpectTest{
+	// Normal 100-continues, case-insensitive.
+	{100, "100-continue", true, "100 Continue"},
+	{100, "100-cOntInUE", true, "100 Continue"},
+
+	// No 100-continue.
+	{100, "", true, "200 OK"},
+
+	// 100-continue but requesting client to deny us,
+	// so it never reads the body.
+	{100, "100-continue", false, "401 Unauthorized"},
+	// Likewise without 100-continue:
+	{100, "", false, "401 Unauthorized"},
+
+	// Non-standard expectations are failures
+	{0, "a-pony", false, "417 Expectation Failed"},
+
+	// Expect-100 requested but no body
+	{0, "100-continue", true, "400 Bad Request"},
+}
+
+// Tests that the server responds to the "Expect" request header
+// correctly.
+func TestServerExpect(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		// Note using r.FormValue("readbody") because for POST
+		// requests that would read from r.Body, which we only
+		// conditionally want to do.
+		if strings.Contains(r.URL.RawQuery, "readbody=true") {
+			ioutil.ReadAll(r.Body)
+			w.Write([]byte("Hi"))
+		} else {
+			w.WriteHeader(StatusUnauthorized)
+		}
+	}))
+	defer ts.Close()
+
+	runTest := func(test serverExpectTest) {
+		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatalf("Dial: %v", err)
+		}
+		defer conn.Close()
+		sendf := func(format string, args ...interface{}) {
+			_, err := fmt.Fprintf(conn, format, args...)
+			if err != nil {
+				t.Fatalf("On test %#v, error writing %q: %v", test, format, err)
+			}
+		}
+		go func() {
+			sendf("POST /?readbody=%v HTTP/1.1\r\n"+
+				"Connection: close\r\n"+
+				"Content-Length: %d\r\n"+
+				"Expect: %s\r\nHost: foo\r\n\r\n",
+				test.readBody, test.contentLength, test.expectation)
+			if test.contentLength > 0 && strings.ToLower(test.expectation) != "100-continue" {
+				body := strings.Repeat("A", test.contentLength)
+				sendf(body)
+			}
+		}()
+		bufr := bufio.NewReader(conn)
+		line, err := bufr.ReadString('\n')
+		if err != nil {
+			t.Fatalf("ReadString: %v", err)
+		}
+		if !strings.Contains(line, test.expectedResponse) {
+			t.Errorf("for test %#v got first line=%q", test, line)
+		}
+	}
+
+	for _, test := range serverExpectTests {
+		runTest(test)
+	}
+}
+
+// Under a ~256KB (maxPostHandlerReadBytes) threshold, the server
+// should consume client request bodies that a handler didn't read.
+func TestServerUnreadRequestBodyLittle(t *testing.T) {
+	conn := new(testConn)
+	body := strings.Repeat("x", 100<<10)
+	conn.readBuf.Write([]byte(fmt.Sprintf(
+		"POST / HTTP/1.1\r\n"+
+			"Host: test\r\n"+
+			"Content-Length: %d\r\n"+
+			"\r\n", len(body))))
+	conn.readBuf.Write([]byte(body))
+
+	done := make(chan bool)
+
+	ls := &oneConnListener{conn}
+	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+		defer close(done)
+		if conn.readBuf.Len() < len(body)/2 {
+			t.Errorf("on request, read buffer length is %d; expected about 100 KB", conn.readBuf.Len())
+		}
+		rw.WriteHeader(200)
+		if g, e := conn.readBuf.Len(), 0; g != e {
+			t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
+		}
+		if c := rw.Header().Get("Connection"); c != "" {
+			t.Errorf(`Connection header = %q; want ""`, c)
+		}
+	}))
+	<-done
+}
+
+// Over a ~256KB (maxPostHandlerReadBytes) threshold, the server
+// should ignore client request bodies that a handler didn't read
+// and close the connection.
+func TestServerUnreadRequestBodyLarge(t *testing.T) {
+	conn := new(testConn)
+	body := strings.Repeat("x", 1<<20)
+	conn.readBuf.Write([]byte(fmt.Sprintf(
+		"POST / HTTP/1.1\r\n"+
+			"Host: test\r\n"+
+			"Content-Length: %d\r\n"+
+			"\r\n", len(body))))
+	conn.readBuf.Write([]byte(body))
+
+	done := make(chan bool)
+
+	ls := &oneConnListener{conn}
+	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+		defer close(done)
+		if conn.readBuf.Len() < len(body)/2 {
+			t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
+		}
+		rw.WriteHeader(200)
+		if conn.readBuf.Len() < len(body)/2 {
+			t.Errorf("post-WriteHeader, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
+		}
+		if c := rw.Header().Get("Connection"); c != "close" {
+			t.Errorf(`Connection header = %q; want "close"`, c)
+		}
+	}))
+	<-done
+}
+
+func TestTimeoutHandler(t *testing.T) {
+	sendHi := make(chan bool, 1)
+	writeErrors := make(chan error, 1)
+	sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
+		<-sendHi
+		_, werr := w.Write([]byte("hi"))
+		writeErrors <- werr
+	})
+	timeout := make(chan time.Time, 1) // write to this to force timeouts
+	ts := httptest.NewServer(NewTestTimeoutHandler(sayHi, timeout))
+	defer ts.Close()
+
+	// Succeed without timing out:
+	sendHi <- true
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if g, e := res.StatusCode, StatusOK; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	body, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(body), "hi"; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+	if g := <-writeErrors; g != nil {
+		t.Errorf("got unexpected Write error on first request: %v", g)
+	}
+
+	// Times out:
+	timeout <- time.Time{}
+	res, err = Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	body, _ = ioutil.ReadAll(res.Body)
+	if !strings.Contains(string(body), "<title>Timeout</title>") {
+		t.Errorf("expected timeout body; got %q", string(body))
+	}
+
+	// Now make the previously-timed out handler speak again,
+	// which verifies the panic is handled:
+	sendHi <- true
+	if g, e := <-writeErrors, ErrHandlerTimeout; g != e {
+		t.Errorf("expected Write error of %v; got %v", e, g)
+	}
+}
+
+// Verifies we don't path.Clean() on the wrong parts in redirects.
+func TestRedirectMunging(t *testing.T) {
+	req, _ := NewRequest("GET", "http://example.com/", nil)
+
+	resp := httptest.NewRecorder()
+	Redirect(resp, req, "/foo?next=http://bar.com/", 302)
+	if g, e := resp.Header().Get("Location"), "/foo?next=http://bar.com/"; g != e {
+		t.Errorf("Location header was %q; want %q", g, e)
+	}
+
+	resp = httptest.NewRecorder()
+	Redirect(resp, req, "http://localhost:8080/_ah/login?continue=http://localhost:8080/", 302)
+	if g, e := resp.Header().Get("Location"), "http://localhost:8080/_ah/login?continue=http://localhost:8080/"; g != e {
+		t.Errorf("Location header was %q; want %q", g, e)
+	}
+}
+
+// TestZeroLengthPostAndResponse exercises an optimization done by the Transport:
+// when there is no body (either because the method doesn't permit a body, or an
+// explicit Content-Length of zero is present), then the transport can re-use the
+// connection immediately. But when it re-uses the connection, it typically closes
+// the previous request's body, which is not optimal for zero-lengthed bodies,
+// as the client would then see http.ErrBodyReadAfterClose and not 0, io.EOF.
+func TestZeroLengthPostAndResponse(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+		all, err := ioutil.ReadAll(r.Body)
+		if err != nil {
+			t.Fatalf("handler ReadAll: %v", err)
+		}
+		if len(all) != 0 {
+			t.Errorf("handler got %d bytes; expected 0", len(all))
+		}
+		rw.Header().Set("Content-Length", "0")
+	}))
+	defer ts.Close()
+
+	req, err := NewRequest("POST", ts.URL, strings.NewReader(""))
+	if err != nil {
+		t.Fatal(err)
+	}
+	req.ContentLength = 0
+
+	var resp [5]*Response
+	for i := range resp {
+		resp[i], err = DefaultClient.Do(req)
+		if err != nil {
+			t.Fatalf("client post #%d: %v", i, err)
+		}
+	}
+
+	for i := range resp {
+		all, err := ioutil.ReadAll(resp[i].Body)
+		if err != nil {
+			t.Fatalf("req #%d: client ReadAll: %v", i, err)
+		}
+		if len(all) != 0 {
+			t.Errorf("req #%d: client got %d bytes; expected 0", i, len(all))
+		}
+	}
+}
+
+func TestHandlerPanic(t *testing.T) {
+	testHandlerPanic(t, false)
+}
+
+func TestHandlerPanicWithHijack(t *testing.T) {
+	testHandlerPanic(t, true)
+}
+
+func testHandlerPanic(t *testing.T, withHijack bool) {
+	// Unlike the other tests that set the log output to ioutil.Discard
+	// to quiet the output, this test uses a pipe.  The pipe serves three
+	// purposes:
+	//
+	//   1) The log.Print from the http server (generated by the caught
+	//      panic) will go to the pipe instead of stderr, making the
+	//      output quiet.
+	//
+	//   2) We read from the pipe to verify that the handler
+	//      actually caught the panic and logged something.
+	//
+	//   3) The blocking Read call prevents this TestHandlerPanic
+	//      function from exiting before the HTTP server handler
+	//      finishes crashing. If this text function exited too
+	//      early (and its defer log.SetOutput(os.Stderr) ran),
+	//      then the crash output could spill into the next test.
+	pr, pw := io.Pipe()
+	log.SetOutput(pw)
+	defer log.SetOutput(os.Stderr)
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if withHijack {
+			rwc, _, err := w.(Hijacker).Hijack()
+			if err != nil {
+				t.Logf("unexpected error: %v", err)
+			}
+			defer rwc.Close()
+		}
+		panic("intentional death for testing")
+	}))
+	defer ts.Close()
+
+	// Do a blocking read on the log output pipe so its logging
+	// doesn't bleed into the next test.  But wait only 5 seconds
+	// for it.
+	done := make(chan bool, 1)
+	go func() {
+		buf := make([]byte, 4<<10)
+		_, err := pr.Read(buf)
+		pr.Close()
+		if err != nil {
+			t.Fatal(err)
+		}
+		done <- true
+	}()
+
+	_, err := Get(ts.URL)
+	if err == nil {
+		t.Logf("expected an error")
+	}
+
+	select {
+	case <-done:
+		return
+	case <-time.After(5 * time.Second):
+		t.Fatal("expected server handler to log an error")
+	}
+}
+
+func TestNoDate(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header()["Date"] = nil
+	}))
+	defer ts.Close()
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, present := res.Header["Date"]
+	if present {
+		t.Fatalf("Expected no Date header; got %v", res.Header["Date"])
+	}
+}
+
+func TestStripPrefix(t *testing.T) {
+	h := HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("X-Path", r.URL.Path)
+	})
+	ts := httptest.NewServer(StripPrefix("/foo", h))
+	defer ts.Close()
+
+	res, err := Get(ts.URL + "/foo/bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, e := res.Header.Get("X-Path"), "/bar"; g != e {
+		t.Errorf("test 1: got %s, want %s", g, e)
+	}
+
+	res, err = Get(ts.URL + "/bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, e := res.StatusCode, 404; g != e {
+		t.Errorf("test 2: got status %v, want %v", g, e)
+	}
+}
+
+func TestRequestLimit(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		t.Fatalf("didn't expect to get request in Handler")
+	}))
+	defer ts.Close()
+	req, _ := NewRequest("GET", ts.URL, nil)
+	var bytesPerHeader = len("header12345: val12345\r\n")
+	for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ {
+		req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i))
+	}
+	res, err := DefaultClient.Do(req)
+	if err != nil {
+		// Some HTTP clients may fail on this undefined behavior (server replying and
+		// closing the connection while the request is still being written), but
+		// we do support it (at least currently), so we expect a response below.
+		t.Fatalf("Do: %v", err)
+	}
+	if res.StatusCode != 413 {
+		t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status)
+	}
+}
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (n int, err error) {
+	for i := range p {
+		p[i] = byte(b)
+	}
+	return len(p), nil
+}
+
+type countReader struct {
+	r io.Reader
+	n *int64
+}
+
+func (cr countReader) Read(p []byte) (n int, err error) {
+	n, err = cr.r.Read(p)
+	*cr.n += int64(n)
+	return
+}
+
+func TestRequestBodyLimit(t *testing.T) {
+	const limit = 1 << 20
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		r.Body = MaxBytesReader(w, r.Body, limit)
+		n, err := io.Copy(ioutil.Discard, r.Body)
+		if err == nil {
+			t.Errorf("expected error from io.Copy")
+		}
+		if n != limit {
+			t.Errorf("io.Copy = %d, want %d", n, limit)
+		}
+	}))
+	defer ts.Close()
+
+	nWritten := int64(0)
+	req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), &nWritten}, limit*200))
+
+	// Send the POST, but don't care it succeeds or not.  The
+	// remote side is going to reply and then close the TCP
+	// connection, and HTTP doesn't really define if that's
+	// allowed or not.  Some HTTP clients will get the response
+	// and some (like ours, currently) will complain that the
+	// request write failed, without reading the response.
+	//
+	// But that's okay, since what we're really testing is that
+	// the remote side hung up on us before we wrote too much.
+	_, _ = DefaultClient.Do(req)
+
+	if nWritten > limit*100 {
+		t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
+			limit, nWritten)
+	}
+}
+
+// TestClientWriteShutdown tests that if the client shuts down the write
+// side of their TCP connection, the server doesn't send a 400 Bad Request.
+func TestClientWriteShutdown(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+	defer ts.Close()
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	err = conn.(*net.TCPConn).CloseWrite()
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	donec := make(chan bool)
+	go func() {
+		defer close(donec)
+		bs, err := ioutil.ReadAll(conn)
+		if err != nil {
+			t.Fatalf("ReadAll: %v", err)
+		}
+		got := string(bs)
+		if got != "" {
+			t.Errorf("read %q from server; want nothing", got)
+		}
+	}()
+	select {
+	case <-donec:
+	case <-time.After(10 * time.Second):
+		t.Fatalf("timeout")
+	}
+}
+
+// Tests that chunked server responses that write 1 byte at a time are
+// buffered before chunk headers are added, not after chunk headers.
+func TestServerBufferedChunking(t *testing.T) {
+	if true {
+		t.Logf("Skipping known broken test; see Issue 2357")
+		return
+	}
+	conn := new(testConn)
+	conn.readBuf.Write([]byte("GET / HTTP/1.1\r\n\r\n"))
+	done := make(chan bool)
+	ls := &oneConnListener{conn}
+	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+		defer close(done)
+		rw.Header().Set("Content-Type", "text/plain") // prevent sniffing, which buffers
+		rw.Write([]byte{'x'})
+		rw.Write([]byte{'y'})
+		rw.Write([]byte{'z'})
+	}))
+	<-done
+	if !bytes.HasSuffix(conn.writeBuf.Bytes(), []byte("\r\n\r\n3\r\nxyz\r\n0\r\n\r\n")) {
+		t.Errorf("response didn't end with a single 3 byte 'xyz' chunk; got:\n%q",
+			conn.writeBuf.Bytes())
+	}
+}
+
+// goTimeout runs f, failing t if f takes more than ns to complete.
+func goTimeout(t *testing.T, d time.Duration, f func()) {
+	ch := make(chan bool, 2)
+	timer := time.AfterFunc(d, func() {
+		t.Errorf("Timeout expired after %v", d)
+		ch <- true
+	})
+	defer timer.Stop()
+	go func() {
+		defer func() { ch <- true }()
+		f()
+	}()
+	<-ch
+}
+
+type errorListener struct {
+	errs []error
+}
+
+func (l *errorListener) Accept() (c net.Conn, err error) {
+	if len(l.errs) == 0 {
+		return nil, io.EOF
+	}
+	err = l.errs[0]
+	l.errs = l.errs[1:]
+	return
+}
+
+func (l *errorListener) Close() error {
+	return nil
+}
+
+func (l *errorListener) Addr() net.Addr {
+	return dummyAddr("test-address")
+}
+
+func TestAcceptMaxFds(t *testing.T) {
+	log.SetOutput(ioutil.Discard) // is noisy otherwise
+	defer log.SetOutput(os.Stderr)
+
+	ln := &errorListener{[]error{
+		&net.OpError{
+			Op:  "accept",
+			Err: syscall.EMFILE,
+		}}}
+	err := Serve(ln, HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})))
+	if err != io.EOF {
+		t.Errorf("got error %v, want EOF", err)
+	}
+}
+
+func BenchmarkClientServer(b *testing.B) {
+	b.StopTimer()
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+		fmt.Fprintf(rw, "Hello world.\n")
+	}))
+	defer ts.Close()
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		res, err := Get(ts.URL)
+		if err != nil {
+			b.Fatal("Get:", err)
+		}
+		all, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			b.Fatal("ReadAll:", err)
+		}
+		body := string(all)
+		if body != "Hello world.\n" {
+			b.Fatal("Got body:", body)
+		}
+	}
+
+	b.StopTimer()
+}
diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go
new file mode 100644
index 0000000..bad3bcb
--- /dev/null
+++ b/src/pkg/net/http/server.go
@@ -0,0 +1,1191 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// HTTP server.  See RFC 2616.
+
+// TODO(rsc):
+//	logging
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/rand"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/url"
+	"path"
+	"runtime/debug"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+// Errors introduced by the HTTP server.
+var (
+	ErrWriteAfterFlush = errors.New("Conn.Write called after Flush")
+	ErrBodyNotAllowed  = errors.New("http: response status code does not allow body")
+	ErrHijacked        = errors.New("Conn has been hijacked")
+	ErrContentLength   = errors.New("Conn.Write wrote more than the declared Content-Length")
+)
+
+// Objects implementing the Handler interface can be
+// registered to serve a particular path or subtree
+// in the HTTP server.
+//
+// ServeHTTP should write reply headers and data to the ResponseWriter
+// and then return.  Returning signals that the request is finished
+// and that the HTTP server can move on to the next request on
+// the connection.
+type Handler interface {
+	ServeHTTP(ResponseWriter, *Request)
+}
+
+// A ResponseWriter interface is used by an HTTP handler to
+// construct an HTTP response.
+type ResponseWriter interface {
+	// Header returns the header map that will be sent by WriteHeader.
+	// Changing the header after a call to WriteHeader (or Write) has
+	// no effect.
+	Header() Header
+
+	// Write writes the data to the connection as part of an HTTP reply.
+	// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
+	// before writing the data.
+	Write([]byte) (int, error)
+
+	// WriteHeader sends an HTTP response header with status code.
+	// If WriteHeader is not called explicitly, the first call to Write
+	// will trigger an implicit WriteHeader(http.StatusOK).
+	// Thus explicit calls to WriteHeader are mainly used to
+	// send error codes.
+	WriteHeader(int)
+}
+
+// The Flusher interface is implemented by ResponseWriters that allow
+// an HTTP handler to flush buffered data to the client.
+//
+// Note that even for ResponseWriters that support Flush,
+// if the client is connected through an HTTP proxy,
+// the buffered data may not reach the client until the response
+// completes.
+type Flusher interface {
+	// Flush sends any buffered data to the client.
+	Flush()
+}
+
+// The Hijacker interface is implemented by ResponseWriters that allow
+// an HTTP handler to take over the connection.
+type Hijacker interface {
+	// Hijack lets the caller take over the connection.
+	// After a call to Hijack(), the HTTP server library
+	// will not do anything else with the connection.
+	// It becomes the caller's responsibility to manage
+	// and close the connection.
+	Hijack() (net.Conn, *bufio.ReadWriter, error)
+}
+
+// A conn represents the server side of an HTTP connection.
+type conn struct {
+	remoteAddr string               // network address of remote side
+	server     *Server              // the Server on which the connection arrived
+	rwc        net.Conn             // i/o connection
+	lr         *io.LimitedReader    // io.LimitReader(rwc)
+	buf        *bufio.ReadWriter    // buffered(lr,rwc), reading from bufio->limitReader->rwc
+	hijacked   bool                 // connection has been hijacked by handler
+	tlsState   *tls.ConnectionState // or nil when not using TLS
+	body       []byte
+}
+
+// A response represents the server side of an HTTP response.
+type response struct {
+	conn          *conn
+	req           *Request // request for this response
+	chunking      bool     // using chunked transfer encoding for reply body
+	wroteHeader   bool     // reply header has been written
+	wroteContinue bool     // 100 Continue response was written
+	header        Header   // reply header parameters
+	written       int64    // number of bytes written in body
+	contentLength int64    // explicitly-declared Content-Length; or -1
+	status        int      // status code passed to WriteHeader
+	needSniff     bool     // need to sniff to find Content-Type
+
+	// close connection after this reply.  set on request and
+	// updated after response from handler if there's a
+	// "Connection: keep-alive" response header and a
+	// Content-Length.
+	closeAfterReply bool
+
+	// requestBodyLimitHit is set by requestTooLarge when
+	// maxBytesReader hits its max size. It is checked in
+	// WriteHeader, to make sure we don't consume the the
+	// remaining request body to try to advance to the next HTTP
+	// request. Instead, when this is set, we stop doing
+	// subsequent requests on this connection and stop reading
+	// input from it.
+	requestBodyLimitHit bool
+}
+
+// requestTooLarge is called by maxBytesReader when too much input has
+// been read from the client.
+func (w *response) requestTooLarge() {
+	w.closeAfterReply = true
+	w.requestBodyLimitHit = true
+	if !w.wroteHeader {
+		w.Header().Set("Connection", "close")
+	}
+}
+
+type writerOnly struct {
+	io.Writer
+}
+
+func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
+	// Call WriteHeader before checking w.chunking if it hasn't
+	// been called yet, since WriteHeader is what sets w.chunking.
+	if !w.wroteHeader {
+		w.WriteHeader(StatusOK)
+	}
+	if !w.chunking && w.bodyAllowed() && !w.needSniff {
+		w.Flush()
+		if rf, ok := w.conn.rwc.(io.ReaderFrom); ok {
+			n, err = rf.ReadFrom(src)
+			w.written += n
+			return
+		}
+	}
+	// Fall back to default io.Copy implementation.
+	// Use wrapper to hide w.ReadFrom from io.Copy.
+	return io.Copy(writerOnly{w}, src)
+}
+
+// noLimit is an effective infinite upper bound for io.LimitedReader
+const noLimit int64 = (1 << 63) - 1
+
+// Create new connection from rwc.
+func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
+	c = new(conn)
+	c.remoteAddr = rwc.RemoteAddr().String()
+	c.server = srv
+	c.rwc = rwc
+	c.body = make([]byte, sniffLen)
+	c.lr = io.LimitReader(rwc, noLimit).(*io.LimitedReader)
+	br := bufio.NewReader(c.lr)
+	bw := bufio.NewWriter(rwc)
+	c.buf = bufio.NewReadWriter(br, bw)
+	return c, nil
+}
+
+// DefaultMaxHeaderBytes is the maximum permitted size of the headers
+// in an HTTP request.
+// This can be overridden by setting Server.MaxHeaderBytes.
+const DefaultMaxHeaderBytes = 1 << 20 // 1 MB
+
+func (srv *Server) maxHeaderBytes() int {
+	if srv.MaxHeaderBytes > 0 {
+		return srv.MaxHeaderBytes
+	}
+	return DefaultMaxHeaderBytes
+}
+
+// wrapper around io.ReaderCloser which on first read, sends an
+// HTTP/1.1 100 Continue header
+type expectContinueReader struct {
+	resp       *response
+	readCloser io.ReadCloser
+	closed     bool
+}
+
+func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
+	if ecr.closed {
+		return 0, errors.New("http: Read after Close on request Body")
+	}
+	if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked {
+		ecr.resp.wroteContinue = true
+		io.WriteString(ecr.resp.conn.buf, "HTTP/1.1 100 Continue\r\n\r\n")
+		ecr.resp.conn.buf.Flush()
+	}
+	return ecr.readCloser.Read(p)
+}
+
+func (ecr *expectContinueReader) Close() error {
+	ecr.closed = true
+	return ecr.readCloser.Close()
+}
+
+// TimeFormat is the time format to use with
+// time.Parse and time.Time.Format when parsing
+// or generating times in HTTP headers.
+// It is like time.RFC1123 but hard codes GMT as the time zone.
+const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
+
+var errTooLarge = errors.New("http: request too large")
+
+// Read next request from connection.
+func (c *conn) readRequest() (w *response, err error) {
+	if c.hijacked {
+		return nil, ErrHijacked
+	}
+	c.lr.N = int64(c.server.maxHeaderBytes()) + 4096 /* bufio slop */
+	var req *Request
+	if req, err = ReadRequest(c.buf.Reader); err != nil {
+		if c.lr.N == 0 {
+			return nil, errTooLarge
+		}
+		return nil, err
+	}
+	c.lr.N = noLimit
+
+	req.RemoteAddr = c.remoteAddr
+	req.TLS = c.tlsState
+
+	w = new(response)
+	w.conn = c
+	w.req = req
+	w.header = make(Header)
+	w.contentLength = -1
+	c.body = c.body[:0]
+	return w, nil
+}
+
+func (w *response) Header() Header {
+	return w.header
+}
+
+// maxPostHandlerReadBytes is the max number of Request.Body bytes not
+// consumed by a handler that the server will read from the client
+// in order to keep a connection alive.  If there are more bytes than
+// this then the server to be paranoid instead sends a "Connection:
+// close" response.
+//
+// This number is approximately what a typical machine's TCP buffer
+// size is anyway.  (if we have the bytes on the machine, we might as
+// well read them)
+const maxPostHandlerReadBytes = 256 << 10
+
+func (w *response) WriteHeader(code int) {
+	if w.conn.hijacked {
+		log.Print("http: response.WriteHeader on hijacked connection")
+		return
+	}
+	if w.wroteHeader {
+		log.Print("http: multiple response.WriteHeader calls")
+		return
+	}
+	w.wroteHeader = true
+	w.status = code
+
+	// Check for a explicit (and valid) Content-Length header.
+	var hasCL bool
+	var contentLength int64
+	if clenStr := w.header.Get("Content-Length"); clenStr != "" {
+		var err error
+		contentLength, err = strconv.ParseInt(clenStr, 10, 64)
+		if err == nil {
+			hasCL = true
+		} else {
+			log.Printf("http: invalid Content-Length of %q sent", clenStr)
+			w.header.Del("Content-Length")
+		}
+	}
+
+	if w.req.wantsHttp10KeepAlive() && (w.req.Method == "HEAD" || hasCL) {
+		_, connectionHeaderSet := w.header["Connection"]
+		if !connectionHeaderSet {
+			w.header.Set("Connection", "keep-alive")
+		}
+	} else if !w.req.ProtoAtLeast(1, 1) {
+		// Client did not ask to keep connection alive.
+		w.closeAfterReply = true
+	}
+
+	if w.header.Get("Connection") == "close" {
+		w.closeAfterReply = true
+	}
+
+	// Per RFC 2616, we should consume the request body before
+	// replying, if the handler hasn't already done so.  But we
+	// don't want to do an unbounded amount of reading here for
+	// DoS reasons, so we only try up to a threshold.
+	if w.req.ContentLength != 0 && !w.closeAfterReply {
+		ecr, isExpecter := w.req.Body.(*expectContinueReader)
+		if !isExpecter || ecr.resp.wroteContinue {
+			n, _ := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1)
+			if n >= maxPostHandlerReadBytes {
+				w.requestTooLarge()
+				w.header.Set("Connection", "close")
+			} else {
+				w.req.Body.Close()
+			}
+		}
+	}
+
+	if code == StatusNotModified {
+		// Must not have body.
+		for _, header := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
+			if w.header.Get(header) != "" {
+				// TODO: return an error if WriteHeader gets a return parameter
+				// or set a flag on w to make future Writes() write an error page?
+				// for now just log and drop the header.
+				log.Printf("http: StatusNotModified response with header %q defined", header)
+				w.header.Del(header)
+			}
+		}
+	} else {
+		// If no content type, apply sniffing algorithm to body.
+		if w.header.Get("Content-Type") == "" {
+			w.needSniff = true
+		}
+	}
+
+	if _, ok := w.header["Date"]; !ok {
+		w.Header().Set("Date", time.Now().UTC().Format(TimeFormat))
+	}
+
+	te := w.header.Get("Transfer-Encoding")
+	hasTE := te != ""
+	if hasCL && hasTE && te != "identity" {
+		// TODO: return an error if WriteHeader gets a return parameter
+		// For now just ignore the Content-Length.
+		log.Printf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
+			te, contentLength)
+		w.header.Del("Content-Length")
+		hasCL = false
+	}
+
+	if w.req.Method == "HEAD" || code == StatusNotModified {
+		// do nothing
+	} else if hasCL {
+		w.contentLength = contentLength
+		w.header.Del("Transfer-Encoding")
+	} else if w.req.ProtoAtLeast(1, 1) {
+		// HTTP/1.1 or greater: use chunked transfer encoding
+		// to avoid closing the connection at EOF.
+		// TODO: this blows away any custom or stacked Transfer-Encoding they
+		// might have set.  Deal with that as need arises once we have a valid
+		// use case.
+		w.chunking = true
+		w.header.Set("Transfer-Encoding", "chunked")
+	} else {
+		// HTTP version < 1.1: cannot do chunked transfer
+		// encoding and we don't know the Content-Length so
+		// signal EOF by closing connection.
+		w.closeAfterReply = true
+		w.header.Del("Transfer-Encoding") // in case already set
+	}
+
+	// Cannot use Content-Length with non-identity Transfer-Encoding.
+	if w.chunking {
+		w.header.Del("Content-Length")
+	}
+	if !w.req.ProtoAtLeast(1, 0) {
+		return
+	}
+	proto := "HTTP/1.0"
+	if w.req.ProtoAtLeast(1, 1) {
+		proto = "HTTP/1.1"
+	}
+	codestring := strconv.Itoa(code)
+	text, ok := statusText[code]
+	if !ok {
+		text = "status code " + codestring
+	}
+	io.WriteString(w.conn.buf, proto+" "+codestring+" "+text+"\r\n")
+	w.header.Write(w.conn.buf)
+
+	// If we need to sniff the body, leave the header open.
+	// Otherwise, end it here.
+	if !w.needSniff {
+		io.WriteString(w.conn.buf, "\r\n")
+	}
+}
+
+// sniff uses the first block of written data,
+// stored in w.conn.body, to decide the Content-Type
+// for the HTTP body.
+func (w *response) sniff() {
+	if !w.needSniff {
+		return
+	}
+	w.needSniff = false
+
+	data := w.conn.body
+	fmt.Fprintf(w.conn.buf, "Content-Type: %s\r\n\r\n", DetectContentType(data))
+
+	if len(data) == 0 {
+		return
+	}
+	if w.chunking {
+		fmt.Fprintf(w.conn.buf, "%x\r\n", len(data))
+	}
+	_, err := w.conn.buf.Write(data)
+	if w.chunking && err == nil {
+		io.WriteString(w.conn.buf, "\r\n")
+	}
+}
+
+// bodyAllowed returns true if a Write is allowed for this response type.
+// It's illegal to call this before the header has been flushed.
+func (w *response) bodyAllowed() bool {
+	if !w.wroteHeader {
+		panic("")
+	}
+	return w.status != StatusNotModified && w.req.Method != "HEAD"
+}
+
+func (w *response) Write(data []byte) (n int, err error) {
+	if w.conn.hijacked {
+		log.Print("http: response.Write on hijacked connection")
+		return 0, ErrHijacked
+	}
+	if !w.wroteHeader {
+		w.WriteHeader(StatusOK)
+	}
+	if len(data) == 0 {
+		return 0, nil
+	}
+	if !w.bodyAllowed() {
+		return 0, ErrBodyNotAllowed
+	}
+
+	w.written += int64(len(data)) // ignoring errors, for errorKludge
+	if w.contentLength != -1 && w.written > w.contentLength {
+		return 0, ErrContentLength
+	}
+
+	var m int
+	if w.needSniff {
+		// We need to sniff the beginning of the output to
+		// determine the content type.  Accumulate the
+		// initial writes in w.conn.body.
+		// Cap m so that append won't allocate.
+		m = cap(w.conn.body) - len(w.conn.body)
+		if m > len(data) {
+			m = len(data)
+		}
+		w.conn.body = append(w.conn.body, data[:m]...)
+		data = data[m:]
+		if len(data) == 0 {
+			// Copied everything into the buffer.
+			// Wait for next write.
+			return m, nil
+		}
+
+		// Filled the buffer; more data remains.
+		// Sniff the content (flushes the buffer)
+		// and then proceed with the remainder
+		// of the data as a normal Write.
+		// Calling sniff clears needSniff.
+		w.sniff()
+	}
+
+	// TODO(rsc): if chunking happened after the buffering,
+	// then there would be fewer chunk headers.
+	// On the other hand, it would make hijacking more difficult.
+	if w.chunking {
+		fmt.Fprintf(w.conn.buf, "%x\r\n", len(data)) // TODO(rsc): use strconv not fmt
+	}
+	n, err = w.conn.buf.Write(data)
+	if err == nil && w.chunking {
+		if n != len(data) {
+			err = io.ErrShortWrite
+		}
+		if err == nil {
+			io.WriteString(w.conn.buf, "\r\n")
+		}
+	}
+
+	return m + n, err
+}
+
+func (w *response) finishRequest() {
+	// If this was an HTTP/1.0 request with keep-alive and we sent a Content-Length
+	// back, we can make this a keep-alive response ...
+	if w.req.wantsHttp10KeepAlive() {
+		sentLength := w.header.Get("Content-Length") != ""
+		if sentLength && w.header.Get("Connection") == "keep-alive" {
+			w.closeAfterReply = false
+		}
+	}
+	if !w.wroteHeader {
+		w.WriteHeader(StatusOK)
+	}
+	if w.needSniff {
+		w.sniff()
+	}
+	if w.chunking {
+		io.WriteString(w.conn.buf, "0\r\n")
+		// trailer key/value pairs, followed by blank line
+		io.WriteString(w.conn.buf, "\r\n")
+	}
+	w.conn.buf.Flush()
+	// Close the body, unless we're about to close the whole TCP connection
+	// anyway.
+	if !w.closeAfterReply {
+		w.req.Body.Close()
+	}
+	if w.req.MultipartForm != nil {
+		w.req.MultipartForm.RemoveAll()
+	}
+
+	if w.contentLength != -1 && w.contentLength != w.written {
+		// Did not write enough. Avoid getting out of sync.
+		w.closeAfterReply = true
+	}
+}
+
+func (w *response) Flush() {
+	if !w.wroteHeader {
+		w.WriteHeader(StatusOK)
+	}
+	w.sniff()
+	w.conn.buf.Flush()
+}
+
+// Close the connection.
+func (c *conn) close() {
+	if c.buf != nil {
+		c.buf.Flush()
+		c.buf = nil
+	}
+	if c.rwc != nil {
+		c.rwc.Close()
+		c.rwc = nil
+	}
+}
+
+// Serve a new connection.
+func (c *conn) serve() {
+	defer func() {
+		err := recover()
+		if err == nil {
+			return
+		}
+
+		var buf bytes.Buffer
+		fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
+		buf.Write(debug.Stack())
+		log.Print(buf.String())
+
+		if c.rwc != nil { // may be nil if connection hijacked
+			c.rwc.Close()
+		}
+	}()
+
+	if tlsConn, ok := c.rwc.(*tls.Conn); ok {
+		if err := tlsConn.Handshake(); err != nil {
+			c.close()
+			return
+		}
+		c.tlsState = new(tls.ConnectionState)
+		*c.tlsState = tlsConn.ConnectionState()
+	}
+
+	for {
+		w, err := c.readRequest()
+		if err != nil {
+			msg := "400 Bad Request"
+			if err == errTooLarge {
+				// Their HTTP client may or may not be
+				// able to read this if we're
+				// responding to them and hanging up
+				// while they're still writing their
+				// request.  Undefined behavior.
+				msg = "413 Request Entity Too Large"
+			} else if err == io.ErrUnexpectedEOF {
+				break // Don't reply
+			} else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
+				break // Don't reply
+			}
+			fmt.Fprintf(c.rwc, "HTTP/1.1 %s\r\n\r\n", msg)
+			break
+		}
+
+		// Expect 100 Continue support
+		req := w.req
+		if req.expectsContinue() {
+			if req.ProtoAtLeast(1, 1) {
+				// Wrap the Body reader with one that replies on the connection
+				req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
+			}
+			if req.ContentLength == 0 {
+				w.Header().Set("Connection", "close")
+				w.WriteHeader(StatusBadRequest)
+				w.finishRequest()
+				break
+			}
+			req.Header.Del("Expect")
+		} else if req.Header.Get("Expect") != "" {
+			// TODO(bradfitz): let ServeHTTP handlers handle
+			// requests with non-standard expectation[s]? Seems
+			// theoretical at best, and doesn't fit into the
+			// current ServeHTTP model anyway.  We'd need to
+			// make the ResponseWriter an optional
+			// "ExpectReplier" interface or something.
+			//
+			// For now we'll just obey RFC 2616 14.20 which says
+			// "If a server receives a request containing an
+			// Expect field that includes an expectation-
+			// extension that it does not support, it MUST
+			// respond with a 417 (Expectation Failed) status."
+			w.Header().Set("Connection", "close")
+			w.WriteHeader(StatusExpectationFailed)
+			w.finishRequest()
+			break
+		}
+
+		handler := c.server.Handler
+		if handler == nil {
+			handler = DefaultServeMux
+		}
+
+		// HTTP cannot have multiple simultaneous active requests.[*]
+		// Until the server replies to this request, it can't read another,
+		// so we might as well run the handler in this goroutine.
+		// [*] Not strictly true: HTTP pipelining.  We could let them all process
+		// in parallel even if their responses need to be serialized.
+		handler.ServeHTTP(w, w.req)
+		if c.hijacked {
+			return
+		}
+		w.finishRequest()
+		if w.closeAfterReply {
+			break
+		}
+	}
+	c.close()
+}
+
+// Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter
+// and a Hijacker.
+func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
+	if w.conn.hijacked {
+		return nil, nil, ErrHijacked
+	}
+	w.conn.hijacked = true
+	rwc = w.conn.rwc
+	buf = w.conn.buf
+	w.conn.rwc = nil
+	w.conn.buf = nil
+	return
+}
+
+// The HandlerFunc type is an adapter to allow the use of
+// ordinary functions as HTTP handlers.  If f is a function
+// with the appropriate signature, HandlerFunc(f) is a
+// Handler object that calls f.
+type HandlerFunc func(ResponseWriter, *Request)
+
+// ServeHTTP calls f(w, r).
+func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
+	f(w, r)
+}
+
+// Helper handlers
+
+// Error replies to the request with the specified error message and HTTP code.
+func Error(w ResponseWriter, error string, code int) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	w.WriteHeader(code)
+	fmt.Fprintln(w, error)
+}
+
+// NotFound replies to the request with an HTTP 404 not found error.
+func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
+
+// NotFoundHandler returns a simple request handler
+// that replies to each request with a ``404 page not found'' reply.
+func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
+
+// StripPrefix returns a handler that serves HTTP requests
+// by removing the given prefix from the request URL's Path
+// and invoking the handler h. StripPrefix handles a
+// request for a path that doesn't begin with prefix by
+// replying with an HTTP 404 not found error.
+func StripPrefix(prefix string, h Handler) Handler {
+	return HandlerFunc(func(w ResponseWriter, r *Request) {
+		if !strings.HasPrefix(r.URL.Path, prefix) {
+			NotFound(w, r)
+			return
+		}
+		r.URL.Path = r.URL.Path[len(prefix):]
+		h.ServeHTTP(w, r)
+	})
+}
+
+// Redirect replies to the request with a redirect to url,
+// which may be a path relative to the request path.
+func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
+	if u, err := url.Parse(urlStr); err == nil {
+		// If url was relative, make absolute by
+		// combining with request path.
+		// The browser would probably do this for us,
+		// but doing it ourselves is more reliable.
+
+		// NOTE(rsc): RFC 2616 says that the Location
+		// line must be an absolute URI, like
+		// "http://www.google.com/redirect/",
+		// not a path like "/redirect/".
+		// Unfortunately, we don't know what to
+		// put in the host name section to get the
+		// client to connect to us again, so we can't
+		// know the right absolute URI to send back.
+		// Because of this problem, no one pays attention
+		// to the RFC; they all send back just a new path.
+		// So do we.
+		oldpath := r.URL.Path
+		if oldpath == "" { // should not happen, but avoid a crash if it does
+			oldpath = "/"
+		}
+		if u.Scheme == "" {
+			// no leading http://server
+			if urlStr == "" || urlStr[0] != '/' {
+				// make relative path absolute
+				olddir, _ := path.Split(oldpath)
+				urlStr = olddir + urlStr
+			}
+
+			var query string
+			if i := strings.Index(urlStr, "?"); i != -1 {
+				urlStr, query = urlStr[:i], urlStr[i:]
+			}
+
+			// clean up but preserve trailing slash
+			trailing := urlStr[len(urlStr)-1] == '/'
+			urlStr = path.Clean(urlStr)
+			if trailing && urlStr[len(urlStr)-1] != '/' {
+				urlStr += "/"
+			}
+			urlStr += query
+		}
+	}
+
+	w.Header().Set("Location", urlStr)
+	w.WriteHeader(code)
+
+	// RFC2616 recommends that a short note "SHOULD" be included in the
+	// response because older user agents may not understand 301/307.
+	// Shouldn't send the response for POST or HEAD; that leaves GET.
+	if r.Method == "GET" {
+		note := "<a href=\"" + htmlEscape(urlStr) + "\">" + statusText[code] + "</a>.\n"
+		fmt.Fprintln(w, note)
+	}
+}
+
+var htmlReplacer = strings.NewReplacer(
+	"&", "&",
+	"<", "<",
+	">", ">",
+	`"`, """,
+	"'", "'",
+)
+
+func htmlEscape(s string) string {
+	return htmlReplacer.Replace(s)
+}
+
+// Redirect to a fixed URL
+type redirectHandler struct {
+	url  string
+	code int
+}
+
+func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	Redirect(w, r, rh.url, rh.code)
+}
+
+// RedirectHandler returns a request handler that redirects
+// each request it receives to the given url using the given
+// status code.
+func RedirectHandler(url string, code int) Handler {
+	return &redirectHandler{url, code}
+}
+
+// ServeMux is an HTTP request multiplexer.
+// It matches the URL of each incoming request against a list of registered
+// patterns and calls the handler for the pattern that
+// most closely matches the URL.
+//
+// Patterns named fixed, rooted paths, like "/favicon.ico",
+// or rooted subtrees, like "/images/" (note the trailing slash).
+// Longer patterns take precedence over shorter ones, so that
+// if there are handlers registered for both "/images/"
+// and "/images/thumbnails/", the latter handler will be
+// called for paths beginning "/images/thumbnails/" and the
+// former will receiver requests for any other paths in the
+// "/images/" subtree.
+//
+// Patterns may optionally begin with a host name, restricting matches to
+// URLs on that host only.  Host-specific patterns take precedence over
+// general patterns, so that a handler might register for the two patterns
+// "/codesearch" and "codesearch.google.com/" without also taking over
+// requests for "http://www.google.com/".
+//
+// ServeMux also takes care of sanitizing the URL request path,
+// redirecting any request containing . or .. elements to an
+// equivalent .- and ..-free URL.
+type ServeMux struct {
+	m map[string]Handler
+}
+
+// NewServeMux allocates and returns a new ServeMux.
+func NewServeMux() *ServeMux { return &ServeMux{make(map[string]Handler)} }
+
+// DefaultServeMux is the default ServeMux used by Serve.
+var DefaultServeMux = NewServeMux()
+
+// Does path match pattern?
+func pathMatch(pattern, path string) bool {
+	if len(pattern) == 0 {
+		// should not happen
+		return false
+	}
+	n := len(pattern)
+	if pattern[n-1] != '/' {
+		return pattern == path
+	}
+	return len(path) >= n && path[0:n] == pattern
+}
+
+// Return the canonical path for p, eliminating . and .. elements.
+func cleanPath(p string) string {
+	if p == "" {
+		return "/"
+	}
+	if p[0] != '/' {
+		p = "/" + p
+	}
+	np := path.Clean(p)
+	// path.Clean removes trailing slash except for root;
+	// put the trailing slash back if necessary.
+	if p[len(p)-1] == '/' && np != "/" {
+		np += "/"
+	}
+	return np
+}
+
+// Find a handler on a handler map given a path string
+// Most-specific (longest) pattern wins
+func (mux *ServeMux) match(path string) Handler {
+	var h Handler
+	var n = 0
+	for k, v := range mux.m {
+		if !pathMatch(k, path) {
+			continue
+		}
+		if h == nil || len(k) > n {
+			n = len(k)
+			h = v
+		}
+	}
+	return h
+}
+
+// ServeHTTP dispatches the request to the handler whose
+// pattern most closely matches the request URL.
+func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
+	// Clean path to canonical form and redirect.
+	if p := cleanPath(r.URL.Path); p != r.URL.Path {
+		w.Header().Set("Location", p)
+		w.WriteHeader(StatusMovedPermanently)
+		return
+	}
+	// Host-specific pattern takes precedence over generic ones
+	h := mux.match(r.Host + r.URL.Path)
+	if h == nil {
+		h = mux.match(r.URL.Path)
+	}
+	if h == nil {
+		h = NotFoundHandler()
+	}
+	h.ServeHTTP(w, r)
+}
+
+// Handle registers the handler for the given pattern.
+func (mux *ServeMux) Handle(pattern string, handler Handler) {
+	if pattern == "" {
+		panic("http: invalid pattern " + pattern)
+	}
+
+	mux.m[pattern] = handler
+
+	// Helpful behavior:
+	// If pattern is /tree/, insert permanent redirect for /tree.
+	n := len(pattern)
+	if n > 0 && pattern[n-1] == '/' {
+		mux.m[pattern[0:n-1]] = RedirectHandler(pattern, StatusMovedPermanently)
+	}
+}
+
+// HandleFunc registers the handler function for the given pattern.
+func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
+	mux.Handle(pattern, HandlerFunc(handler))
+}
+
+// Handle registers the handler for the given pattern
+// in the DefaultServeMux.
+// The documentation for ServeMux explains how patterns are matched.
+func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
+
+// HandleFunc registers the handler function for the given pattern
+// in the DefaultServeMux.
+// The documentation for ServeMux explains how patterns are matched.
+func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
+	DefaultServeMux.HandleFunc(pattern, handler)
+}
+
+// Serve accepts incoming HTTP connections on the listener l,
+// creating a new service thread for each.  The service threads
+// read requests and then call handler to reply to them.
+// Handler is typically nil, in which case the DefaultServeMux is used.
+func Serve(l net.Listener, handler Handler) error {
+	srv := &Server{Handler: handler}
+	return srv.Serve(l)
+}
+
+// A Server defines parameters for running an HTTP server.
+type Server struct {
+	Addr           string        // TCP address to listen on, ":http" if empty
+	Handler        Handler       // handler to invoke, http.DefaultServeMux if nil
+	ReadTimeout    time.Duration // maximum duration before timing out read of the request
+	WriteTimeout   time.Duration // maximum duration before timing out write of the response
+	MaxHeaderBytes int           // maximum size of request headers, DefaultMaxHeaderBytes if 0
+}
+
+// ListenAndServe listens on the TCP network address srv.Addr and then
+// calls Serve to handle requests on incoming connections.  If
+// srv.Addr is blank, ":http" is used.
+func (srv *Server) ListenAndServe() error {
+	addr := srv.Addr
+	if addr == "" {
+		addr = ":http"
+	}
+	l, e := net.Listen("tcp", addr)
+	if e != nil {
+		return e
+	}
+	return srv.Serve(l)
+}
+
+// Serve accepts incoming connections on the Listener l, creating a
+// new service thread for each.  The service threads read requests and
+// then call srv.Handler to reply to them.
+func (srv *Server) Serve(l net.Listener) error {
+	defer l.Close()
+	for {
+		rw, e := l.Accept()
+		if e != nil {
+			if ne, ok := e.(net.Error); ok && ne.Temporary() {
+				log.Printf("http: Accept error: %v", e)
+				continue
+			}
+			return e
+		}
+		if srv.ReadTimeout != 0 {
+			rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout))
+		}
+		if srv.WriteTimeout != 0 {
+			rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
+		}
+		c, err := srv.newConn(rw)
+		if err != nil {
+			continue
+		}
+		go c.serve()
+	}
+	panic("not reached")
+}
+
+// ListenAndServe listens on the TCP network address addr
+// and then calls Serve with handler to handle requests
+// on incoming connections.  Handler is typically nil,
+// in which case the DefaultServeMux is used.
+//
+// A trivial example server is:
+//
+//	package main
+//
+//	import (
+//		"io"
+//		"net/http"
+//		"log"
+//	)
+//
+//	// hello world, the web server
+//	func HelloServer(w http.ResponseWriter, req *http.Request) {
+//		io.WriteString(w, "hello, world!\n")
+//	}
+//
+//	func main() {
+//		http.HandleFunc("/hello", HelloServer)
+//		err := http.ListenAndServe(":12345", nil)
+//		if err != nil {
+//			log.Fatal("ListenAndServe: ", err)
+//		}
+//	}
+func ListenAndServe(addr string, handler Handler) error {
+	server := &Server{Addr: addr, Handler: handler}
+	return server.ListenAndServe()
+}
+
+// ListenAndServeTLS acts identically to ListenAndServe, except that it
+// expects HTTPS connections. Additionally, files containing a certificate and
+// matching private key for the server must be provided. If the certificate
+// is signed by a certificate authority, the certFile should be the concatenation
+// of the server's certificate followed by the CA's certificate.
+//
+// A trivial example server is:
+//
+//	import (
+//		"log"
+//		"net/http"
+//	)
+//
+//	func handler(w http.ResponseWriter, req *http.Request) {
+//		w.Header().Set("Content-Type", "text/plain")
+//		w.Write([]byte("This is an example server.\n"))
+//	}
+//
+//	func main() {
+//		http.HandleFunc("/", handler)
+//		log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
+//		err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
+//		if err != nil {
+//			log.Fatal(err)
+//		}
+//	}
+//
+// One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
+func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error {
+	server := &Server{Addr: addr, Handler: handler}
+	return server.ListenAndServeTLS(certFile, keyFile)
+}
+
+// ListenAndServeTLS listens on the TCP network address srv.Addr and
+// then calls Serve to handle requests on incoming TLS connections.
+//
+// Filenames containing a certificate and matching private key for
+// the server must be provided. If the certificate is signed by a
+// certificate authority, the certFile should be the concatenation
+// of the server's certificate followed by the CA's certificate.
+//
+// If srv.Addr is blank, ":https" is used.
+func (s *Server) ListenAndServeTLS(certFile, keyFile string) error {
+	addr := s.Addr
+	if addr == "" {
+		addr = ":https"
+	}
+	config := &tls.Config{
+		Rand:       rand.Reader,
+		NextProtos: []string{"http/1.1"},
+	}
+
+	var err error
+	config.Certificates = make([]tls.Certificate, 1)
+	config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
+	if err != nil {
+		return err
+	}
+
+	conn, err := net.Listen("tcp", addr)
+	if err != nil {
+		return err
+	}
+
+	tlsListener := tls.NewListener(conn, config)
+	return s.Serve(tlsListener)
+}
+
+// TimeoutHandler returns a Handler that runs h with the given time limit.
+//
+// The new Handler calls h.ServeHTTP to handle each request, but if a
+// call runs for more than ns nanoseconds, the handler responds with
+// a 503 Service Unavailable error and the given message in its body.
+// (If msg is empty, a suitable default message will be sent.)
+// After such a timeout, writes by h to its ResponseWriter will return
+// ErrHandlerTimeout.
+func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {
+	f := func() <-chan time.Time {
+		return time.After(dt)
+	}
+	return &timeoutHandler{h, f, msg}
+}
+
+// ErrHandlerTimeout is returned on ResponseWriter Write calls
+// in handlers which have timed out.
+var ErrHandlerTimeout = errors.New("http: Handler timeout")
+
+type timeoutHandler struct {
+	handler Handler
+	timeout func() <-chan time.Time // returns channel producing a timeout
+	body    string
+}
+
+func (h *timeoutHandler) errorBody() string {
+	if h.body != "" {
+		return h.body
+	}
+	return "<html><head><title>Timeout</title></head><body><h1>Timeout</h1></body></html>"
+}
+
+func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
+	done := make(chan bool)
+	tw := &timeoutWriter{w: w}
+	go func() {
+		h.handler.ServeHTTP(tw, r)
+		done <- true
+	}()
+	select {
+	case <-done:
+		return
+	case <-h.timeout():
+		tw.mu.Lock()
+		defer tw.mu.Unlock()
+		if !tw.wroteHeader {
+			tw.w.WriteHeader(StatusServiceUnavailable)
+			tw.w.Write([]byte(h.errorBody()))
+		}
+		tw.timedOut = true
+	}
+}
+
+type timeoutWriter struct {
+	w ResponseWriter
+
+	mu          sync.Mutex
+	timedOut    bool
+	wroteHeader bool
+}
+
+func (tw *timeoutWriter) Header() Header {
+	return tw.w.Header()
+}
+
+func (tw *timeoutWriter) Write(p []byte) (int, error) {
+	tw.mu.Lock()
+	timedOut := tw.timedOut
+	tw.mu.Unlock()
+	if timedOut {
+		return 0, ErrHandlerTimeout
+	}
+	return tw.w.Write(p)
+}
+
+func (tw *timeoutWriter) WriteHeader(code int) {
+	tw.mu.Lock()
+	if tw.timedOut || tw.wroteHeader {
+		tw.mu.Unlock()
+		return
+	}
+	tw.wroteHeader = true
+	tw.mu.Unlock()
+	tw.w.WriteHeader(code)
+}
diff --git a/src/pkg/net/http/sniff.go b/src/pkg/net/http/sniff.go
new file mode 100644
index 0000000..c1c78e2
--- /dev/null
+++ b/src/pkg/net/http/sniff.go
@@ -0,0 +1,214 @@
+// Copyright 2011 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 http
+
+import (
+	"bytes"
+	"encoding/binary"
+)
+
+// Content-type sniffing algorithm.
+// References in this file refer to this draft specification:
+//   http://mimesniff.spec.whatwg.org/
+
+// The algorithm prefers to use sniffLen bytes to make its decision.
+const sniffLen = 512
+
+// DetectContentType returns the sniffed Content-Type string
+// for the given data. This function always returns a valid MIME type.
+func DetectContentType(data []byte) string {
+	if len(data) > sniffLen {
+		data = data[:sniffLen]
+	}
+
+	// Index of the first non-whitespace byte in data.
+	firstNonWS := 0
+	for ; firstNonWS < len(data) && isWS(data[firstNonWS]); firstNonWS++ {
+	}
+
+	for _, sig := range sniffSignatures {
+		if ct := sig.match(data, firstNonWS); ct != "" {
+			return ct
+		}
+	}
+
+	return "application/octet-stream" // fallback
+}
+
+func isWS(b byte) bool {
+	return bytes.IndexByte([]byte("\t\n\x0C\r "), b) != -1
+}
+
+type sniffSig interface {
+	// match returns the MIME type of the data, or "" if unknown.
+	match(data []byte, firstNonWS int) string
+}
+
+// Data matching the table in section 6.
+var sniffSignatures = []sniffSig{
+	htmlSig("<!DOCTYPE HTML"),
+	htmlSig("<HTML"),
+	htmlSig("<HEAD"),
+	htmlSig("<SCRIPT"),
+	htmlSig("<IFRAME"),
+	htmlSig("<H1"),
+	htmlSig("<DIV"),
+	htmlSig("<FONT"),
+	htmlSig("<TABLE"),
+	htmlSig("<A"),
+	htmlSig("<STYLE"),
+	htmlSig("<TITLE"),
+	htmlSig("<B"),
+	htmlSig("<BODY"),
+	htmlSig("<BR"),
+	htmlSig("<P"),
+	htmlSig("<!--"),
+
+	&maskedSig{mask: []byte("\xFF\xFF\xFF\xFF\xFF"), pat: []byte("<?xml"), skipWS: true, ct: "text/xml; charset=utf-8"},
+
+	&exactSig{[]byte("%PDF-"), "application/pdf"},
+	&exactSig{[]byte("%!PS-Adobe-"), "application/postscript"},
+
+	// UTF BOMs.
+	&maskedSig{mask: []byte("\xFF\xFF\x00\x00"), pat: []byte("\xFE\xFF\x00\x00"), ct: "text/plain; charset=utf-16be"},
+	&maskedSig{mask: []byte("\xFF\xFF\x00\x00"), pat: []byte("\xFF\xFE\x00\x00"), ct: "text/plain; charset=utf-16le"},
+	&maskedSig{mask: []byte("\xFF\xFF\xFF\x00"), pat: []byte("\xEF\xBB\xBF\x00"), ct: "text/plain; charset=utf-8"},
+
+	&exactSig{[]byte("GIF87a"), "image/gif"},
+	&exactSig{[]byte("GIF89a"), "image/gif"},
+	&exactSig{[]byte("\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"), "image/png"},
+	&exactSig{[]byte("\xFF\xD8\xFF"), "image/jpeg"},
+	&exactSig{[]byte("BM"), "image/bmp"},
+	&maskedSig{
+		mask: []byte("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"),
+		pat:  []byte("RIFF\x00\x00\x00\x00WEBPVP"),
+		ct:   "image/webp",
+	},
+	&exactSig{[]byte("\x00\x00\x01\x00"), "image/vnd.microsoft.icon"},
+	&exactSig{[]byte("\x4F\x67\x67\x53\x00"), "application/ogg"},
+	&maskedSig{
+		mask: []byte("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF"),
+		pat:  []byte("RIFF\x00\x00\x00\x00WAVE"),
+		ct:   "audio/wave",
+	},
+	&exactSig{[]byte("\x1A\x45\xDF\xA3"), "video/webm"},
+	&exactSig{[]byte("\x52\x61\x72\x20\x1A\x07\x00"), "application/x-rar-compressed"},
+	&exactSig{[]byte("\x50\x4B\x03\x04"), "application/zip"},
+	&exactSig{[]byte("\x1F\x8B\x08"), "application/x-gzip"},
+
+	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
+	//mp4Sig(0),
+
+	textSig(0), // should be last
+}
+
+type exactSig struct {
+	sig []byte
+	ct  string
+}
+
+func (e *exactSig) match(data []byte, firstNonWS int) string {
+	if bytes.HasPrefix(data, e.sig) {
+		return e.ct
+	}
+	return ""
+}
+
+type maskedSig struct {
+	mask, pat []byte
+	skipWS    bool
+	ct        string
+}
+
+func (m *maskedSig) match(data []byte, firstNonWS int) string {
+	if m.skipWS {
+		data = data[firstNonWS:]
+	}
+	if len(data) < len(m.mask) {
+		return ""
+	}
+	for i, mask := range m.mask {
+		db := data[i] & mask
+		if db != m.pat[i] {
+			return ""
+		}
+	}
+	return m.ct
+}
+
+type htmlSig []byte
+
+func (h htmlSig) match(data []byte, firstNonWS int) string {
+	data = data[firstNonWS:]
+	if len(data) < len(h)+1 {
+		return ""
+	}
+	for i, b := range h {
+		db := data[i]
+		if 'A' <= b && b <= 'Z' {
+			db &= 0xDF
+		}
+		if b != db {
+			return ""
+		}
+	}
+	// Next byte must be space or right angle bracket.
+	if db := data[len(h)]; db != ' ' && db != '>' {
+		return ""
+	}
+	return "text/html; charset=utf-8"
+}
+
+type mp4Sig int
+
+func (mp4Sig) match(data []byte, firstNonWS int) string {
+	// c.f. section 6.1.
+	if len(data) < 8 {
+		return ""
+	}
+	boxSize := int(binary.BigEndian.Uint32(data[:4]))
+	if boxSize%4 != 0 || len(data) < boxSize {
+		return ""
+	}
+	if !bytes.Equal(data[4:8], []byte("ftyp")) {
+		return ""
+	}
+	for st := 8; st < boxSize; st += 4 {
+		if st == 12 {
+			// minor version number
+			continue
+		}
+		seg := string(data[st : st+3])
+		switch seg {
+		case "mp4", "iso", "M4V", "M4P", "M4B":
+			return "video/mp4"
+			/* The remainder are not in the spec.
+			case "M4A":
+				return "audio/mp4"
+			case "3gp":
+				return "video/3gpp"
+			case "jp2":
+				return "image/jp2" // JPEG 2000
+			*/
+		}
+	}
+	return ""
+}
+
+type textSig int
+
+func (textSig) match(data []byte, firstNonWS int) string {
+	// c.f. section 5, step 4.
+	for _, b := range data[firstNonWS:] {
+		switch {
+		case 0x00 <= b && b <= 0x08,
+			b == 0x0B,
+			0x0E <= b && b <= 0x1A,
+			0x1C <= b && b <= 0x1F:
+			return ""
+		}
+	}
+	return "text/plain; charset=utf-8"
+}
diff --git a/src/pkg/net/http/sniff_test.go b/src/pkg/net/http/sniff_test.go
new file mode 100644
index 0000000..6efa8ce
--- /dev/null
+++ b/src/pkg/net/http/sniff_test.go
@@ -0,0 +1,137 @@
+// Copyright 2011 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 http_test
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	. "net/http"
+	"net/http/httptest"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+var sniffTests = []struct {
+	desc        string
+	data        []byte
+	contentType string
+}{
+	// Some nonsense.
+	{"Empty", []byte{}, "text/plain; charset=utf-8"},
+	{"Binary", []byte{1, 2, 3}, "application/octet-stream"},
+
+	{"HTML document #1", []byte(`<HtMl><bOdY>blah blah blah</body></html>`), "text/html; charset=utf-8"},
+	{"HTML document #2", []byte(`<HTML></HTML>`), "text/html; charset=utf-8"},
+	{"HTML document #3 (leading whitespace)", []byte(`   <!DOCTYPE HTML>...`), "text/html; charset=utf-8"},
+	{"HTML document #4 (leading CRLF)", []byte("\r\n<html>..."), "text/html; charset=utf-8"},
+
+	{"Plain text", []byte(`This is not HTML. It has ☃ though.`), "text/plain; charset=utf-8"},
+
+	{"XML", []byte("\n<?xml!"), "text/xml; charset=utf-8"},
+
+	// Image types.
+	{"GIF 87a", []byte(`GIF87a`), "image/gif"},
+	{"GIF 89a", []byte(`GIF89a...`), "image/gif"},
+
+	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
+	//{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
+	//{"MP4 audio", []byte("\x00\x00\x00\x20ftypM4A \x00\x00\x00\x00M4A mp42isom\x00\x00\x00\x00"), "audio/mp4"},
+}
+
+func TestDetectContentType(t *testing.T) {
+	for _, tt := range sniffTests {
+		ct := DetectContentType(tt.data)
+		if ct != tt.contentType {
+			t.Errorf("%v: DetectContentType = %q, want %q", tt.desc, ct, tt.contentType)
+		}
+	}
+}
+
+func TestServerContentType(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		i, _ := strconv.Atoi(r.FormValue("i"))
+		tt := sniffTests[i]
+		n, err := w.Write(tt.data)
+		if n != len(tt.data) || err != nil {
+			log.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt.desc, tt.data, n, err, len(tt.data))
+		}
+	}))
+	defer ts.Close()
+
+	for i, tt := range sniffTests {
+		resp, err := Get(ts.URL + "/?i=" + strconv.Itoa(i))
+		if err != nil {
+			t.Errorf("%v: %v", tt.desc, err)
+			continue
+		}
+		if ct := resp.Header.Get("Content-Type"); ct != tt.contentType {
+			t.Errorf("%v: Content-Type = %q, want %q", tt.desc, ct, tt.contentType)
+		}
+		data, err := ioutil.ReadAll(resp.Body)
+		if err != nil {
+			t.Errorf("%v: reading body: %v", tt.desc, err)
+		} else if !bytes.Equal(data, tt.data) {
+			t.Errorf("%v: data is %q, want %q", tt.desc, data, tt.data)
+		}
+		resp.Body.Close()
+	}
+}
+
+func TestContentTypeWithCopy(t *testing.T) {
+	const (
+		input    = "\n<html>\n\t<head>\n"
+		expected = "text/html; charset=utf-8"
+	)
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		// Use io.Copy from a bytes.Buffer to trigger ReadFrom.
+		buf := bytes.NewBuffer([]byte(input))
+		n, err := io.Copy(w, buf)
+		if int(n) != len(input) || err != nil {
+			t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
+		}
+	}))
+	defer ts.Close()
+
+	resp, err := Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	if ct := resp.Header.Get("Content-Type"); ct != expected {
+		t.Errorf("Content-Type = %q, want %q", ct, expected)
+	}
+	data, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		t.Errorf("reading body: %v", err)
+	} else if !bytes.Equal(data, []byte(input)) {
+		t.Errorf("data is %q, want %q", data, input)
+	}
+	resp.Body.Close()
+}
+
+func TestSniffWriteSize(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		size, _ := strconv.Atoi(r.FormValue("size"))
+		written, err := io.WriteString(w, strings.Repeat("a", size))
+		if err != nil {
+			t.Errorf("write of %d bytes: %v", size, err)
+			return
+		}
+		if written != size {
+			t.Errorf("write of %d bytes wrote %d bytes", size, written)
+		}
+	}))
+	defer ts.Close()
+	for _, size := range []int{0, 1, 200, 600, 999, 1000, 1023, 1024, 512 << 10, 1 << 20} {
+		_, err := Get(fmt.Sprintf("%s/?size=%d", ts.URL, size))
+		if err != nil {
+			t.Fatalf("size %d: %v", size, err)
+		}
+	}
+}
diff --git a/src/pkg/http/status.go b/src/pkg/net/http/status.go
similarity index 100%
rename from src/pkg/http/status.go
rename to src/pkg/net/http/status.go
diff --git a/src/pkg/http/testdata/file b/src/pkg/net/http/testdata/file
similarity index 100%
rename from src/pkg/http/testdata/file
rename to src/pkg/net/http/testdata/file
diff --git a/src/pkg/http/testdata/index.html b/src/pkg/net/http/testdata/index.html
similarity index 100%
rename from src/pkg/http/testdata/index.html
rename to src/pkg/net/http/testdata/index.html
diff --git a/src/pkg/http/testdata/style.css b/src/pkg/net/http/testdata/style.css
similarity index 100%
rename from src/pkg/http/testdata/style.css
rename to src/pkg/net/http/testdata/style.css
diff --git a/src/pkg/net/http/transfer.go b/src/pkg/net/http/transfer.go
new file mode 100644
index 0000000..ef9564a
--- /dev/null
+++ b/src/pkg/net/http/transfer.go
@@ -0,0 +1,630 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/textproto"
+	"strconv"
+	"strings"
+)
+
+// transferWriter inspects the fields of a user-supplied Request or Response,
+// sanitizes them without changing the user object and provides methods for
+// writing the respective header, body and trailer in wire format.
+type transferWriter struct {
+	Method           string
+	Body             io.Reader
+	BodyCloser       io.Closer
+	ResponseToHEAD   bool
+	ContentLength    int64 // -1 means unknown, 0 means exactly none
+	Close            bool
+	TransferEncoding []string
+	Trailer          Header
+}
+
+func newTransferWriter(r interface{}) (t *transferWriter, err error) {
+	t = &transferWriter{}
+
+	// Extract relevant fields
+	atLeastHTTP11 := false
+	switch rr := r.(type) {
+	case *Request:
+		if rr.ContentLength != 0 && rr.Body == nil {
+			return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
+		}
+		t.Method = rr.Method
+		t.Body = rr.Body
+		t.BodyCloser = rr.Body
+		t.ContentLength = rr.ContentLength
+		t.Close = rr.Close
+		t.TransferEncoding = rr.TransferEncoding
+		t.Trailer = rr.Trailer
+		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
+		if t.Body != nil && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
+			if t.ContentLength == 0 {
+				// Test to see if it's actually zero or just unset.
+				var buf [1]byte
+				n, _ := io.ReadFull(t.Body, buf[:])
+				if n == 1 {
+					// Oh, guess there is data in this Body Reader after all.
+					// The ContentLength field just wasn't set.
+					// Stich the Body back together again, re-attaching our
+					// consumed byte.
+					t.ContentLength = -1
+					t.Body = io.MultiReader(bytes.NewBuffer(buf[:]), t.Body)
+				} else {
+					// Body is actually empty.
+					t.Body = nil
+					t.BodyCloser = nil
+				}
+			}
+			if t.ContentLength < 0 {
+				t.TransferEncoding = []string{"chunked"}
+			}
+		}
+	case *Response:
+		t.Method = rr.Request.Method
+		t.Body = rr.Body
+		t.BodyCloser = rr.Body
+		t.ContentLength = rr.ContentLength
+		t.Close = rr.Close
+		t.TransferEncoding = rr.TransferEncoding
+		t.Trailer = rr.Trailer
+		atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
+		t.ResponseToHEAD = noBodyExpected(rr.Request.Method)
+	}
+
+	// Sanitize Body,ContentLength,TransferEncoding
+	if t.ResponseToHEAD {
+		t.Body = nil
+		t.TransferEncoding = nil
+		// ContentLength is expected to hold Content-Length
+		if t.ContentLength < 0 {
+			return nil, ErrMissingContentLength
+		}
+	} else {
+		if !atLeastHTTP11 || t.Body == nil {
+			t.TransferEncoding = nil
+		}
+		if chunked(t.TransferEncoding) {
+			t.ContentLength = -1
+		} else if t.Body == nil { // no chunking, no body
+			t.ContentLength = 0
+		}
+	}
+
+	// Sanitize Trailer
+	if !chunked(t.TransferEncoding) {
+		t.Trailer = nil
+	}
+
+	return t, nil
+}
+
+func noBodyExpected(requestMethod string) bool {
+	return requestMethod == "HEAD"
+}
+
+func (t *transferWriter) shouldSendContentLength() bool {
+	if chunked(t.TransferEncoding) {
+		return false
+	}
+	if t.ContentLength > 0 {
+		return true
+	}
+	if t.ResponseToHEAD {
+		return true
+	}
+	// Many servers expect a Content-Length for these methods
+	if t.Method == "POST" || t.Method == "PUT" {
+		return true
+	}
+	if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
+		return true
+	}
+
+	return false
+}
+
+func (t *transferWriter) WriteHeader(w io.Writer) (err error) {
+	if t.Close {
+		_, err = io.WriteString(w, "Connection: close\r\n")
+		if err != nil {
+			return
+		}
+	}
+
+	// Write Content-Length and/or Transfer-Encoding whose values are a
+	// function of the sanitized field triple (Body, ContentLength,
+	// TransferEncoding)
+	if t.shouldSendContentLength() {
+		io.WriteString(w, "Content-Length: ")
+		_, err = io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n")
+		if err != nil {
+			return
+		}
+	} else if chunked(t.TransferEncoding) {
+		_, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
+		if err != nil {
+			return
+		}
+	}
+
+	// Write Trailer header
+	if t.Trailer != nil {
+		// TODO: At some point, there should be a generic mechanism for
+		// writing long headers, using HTTP line splitting
+		io.WriteString(w, "Trailer: ")
+		needComma := false
+		for k := range t.Trailer {
+			k = CanonicalHeaderKey(k)
+			switch k {
+			case "Transfer-Encoding", "Trailer", "Content-Length":
+				return &badStringError{"invalid Trailer key", k}
+			}
+			if needComma {
+				io.WriteString(w, ",")
+			}
+			io.WriteString(w, k)
+			needComma = true
+		}
+		_, err = io.WriteString(w, "\r\n")
+	}
+
+	return
+}
+
+func (t *transferWriter) WriteBody(w io.Writer) (err error) {
+	var ncopy int64
+
+	// Write body
+	if t.Body != nil {
+		if chunked(t.TransferEncoding) {
+			cw := newChunkedWriter(w)
+			_, err = io.Copy(cw, t.Body)
+			if err == nil {
+				err = cw.Close()
+			}
+		} else if t.ContentLength == -1 {
+			ncopy, err = io.Copy(w, t.Body)
+		} else {
+			ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
+			nextra, err := io.Copy(ioutil.Discard, t.Body)
+			if err != nil {
+				return err
+			}
+			ncopy += nextra
+		}
+		if err != nil {
+			return err
+		}
+		if err = t.BodyCloser.Close(); err != nil {
+			return err
+		}
+	}
+
+	if t.ContentLength != -1 && t.ContentLength != ncopy {
+		return fmt.Errorf("http: Request.ContentLength=%d with Body length %d",
+			t.ContentLength, ncopy)
+	}
+
+	// TODO(petar): Place trailer writer code here.
+	if chunked(t.TransferEncoding) {
+		// Last chunk, empty trailer
+		_, err = io.WriteString(w, "\r\n")
+	}
+
+	return
+}
+
+type transferReader struct {
+	// Input
+	Header        Header
+	StatusCode    int
+	RequestMethod string
+	ProtoMajor    int
+	ProtoMinor    int
+	// Output
+	Body             io.ReadCloser
+	ContentLength    int64
+	TransferEncoding []string
+	Close            bool
+	Trailer          Header
+}
+
+// bodyAllowedForStatus returns whether a given response status code
+// permits a body.  See RFC2616, section 4.4.
+func bodyAllowedForStatus(status int) bool {
+	switch {
+	case status >= 100 && status <= 199:
+		return false
+	case status == 204:
+		return false
+	case status == 304:
+		return false
+	}
+	return true
+}
+
+// msg is *Request or *Response.
+func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
+	t := &transferReader{}
+
+	// Unify input
+	isResponse := false
+	switch rr := msg.(type) {
+	case *Response:
+		t.Header = rr.Header
+		t.StatusCode = rr.StatusCode
+		t.RequestMethod = rr.Request.Method
+		t.ProtoMajor = rr.ProtoMajor
+		t.ProtoMinor = rr.ProtoMinor
+		t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header)
+		isResponse = true
+	case *Request:
+		t.Header = rr.Header
+		t.ProtoMajor = rr.ProtoMajor
+		t.ProtoMinor = rr.ProtoMinor
+		// Transfer semantics for Requests are exactly like those for
+		// Responses with status code 200, responding to a GET method
+		t.StatusCode = 200
+		t.RequestMethod = "GET"
+	default:
+		panic("unexpected type")
+	}
+
+	// Default to HTTP/1.1
+	if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
+		t.ProtoMajor, t.ProtoMinor = 1, 1
+	}
+
+	// Transfer encoding, content length
+	t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header)
+	if err != nil {
+		return err
+	}
+
+	t.ContentLength, err = fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
+	if err != nil {
+		return err
+	}
+
+	// Trailer
+	t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
+	if err != nil {
+		return err
+	}
+
+	// If there is no Content-Length or chunked Transfer-Encoding on a *Response
+	// and the status is not 1xx, 204 or 304, then the body is unbounded.
+	// See RFC2616, section 4.4.
+	switch msg.(type) {
+	case *Response:
+		if t.ContentLength == -1 &&
+			!chunked(t.TransferEncoding) &&
+			bodyAllowedForStatus(t.StatusCode) {
+			// Unbounded body.
+			t.Close = true
+		}
+	}
+
+	// Prepare body reader.  ContentLength < 0 means chunked encoding
+	// or close connection when finished, since multipart is not supported yet
+	switch {
+	case chunked(t.TransferEncoding):
+		t.Body = &body{Reader: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
+	case t.ContentLength >= 0:
+		// TODO: limit the Content-Length. This is an easy DoS vector.
+		t.Body = &body{Reader: io.LimitReader(r, t.ContentLength), closing: t.Close}
+	default:
+		// t.ContentLength < 0, i.e. "Content-Length" not mentioned in header
+		if t.Close {
+			// Close semantics (i.e. HTTP/1.0)
+			t.Body = &body{Reader: r, closing: t.Close}
+		} else {
+			// Persistent connection (i.e. HTTP/1.1)
+			t.Body = &body{Reader: io.LimitReader(r, 0), closing: t.Close}
+		}
+	}
+
+	// Unify output
+	switch rr := msg.(type) {
+	case *Request:
+		rr.Body = t.Body
+		rr.ContentLength = t.ContentLength
+		rr.TransferEncoding = t.TransferEncoding
+		rr.Close = t.Close
+		rr.Trailer = t.Trailer
+	case *Response:
+		rr.Body = t.Body
+		rr.ContentLength = t.ContentLength
+		rr.TransferEncoding = t.TransferEncoding
+		rr.Close = t.Close
+		rr.Trailer = t.Trailer
+	}
+
+	return nil
+}
+
+// Checks whether chunked is part of the encodings stack
+func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
+
+// Checks whether the encoding is explicitly "identity".
+func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
+
+// Sanitize transfer encoding
+func fixTransferEncoding(requestMethod string, header Header) ([]string, error) {
+	raw, present := header["Transfer-Encoding"]
+	if !present {
+		return nil, nil
+	}
+
+	delete(header, "Transfer-Encoding")
+
+	// Head responses have no bodies, so the transfer encoding
+	// should be ignored.
+	if requestMethod == "HEAD" {
+		return nil, nil
+	}
+
+	encodings := strings.Split(raw[0], ",")
+	te := make([]string, 0, len(encodings))
+	// TODO: Even though we only support "identity" and "chunked"
+	// encodings, the loop below is designed with foresight. One
+	// invariant that must be maintained is that, if present,
+	// chunked encoding must always come first.
+	for _, encoding := range encodings {
+		encoding = strings.ToLower(strings.TrimSpace(encoding))
+		// "identity" encoding is not recored
+		if encoding == "identity" {
+			break
+		}
+		if encoding != "chunked" {
+			return nil, &badStringError{"unsupported transfer encoding", encoding}
+		}
+		te = te[0 : len(te)+1]
+		te[len(te)-1] = encoding
+	}
+	if len(te) > 1 {
+		return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")}
+	}
+	if len(te) > 0 {
+		// Chunked encoding trumps Content-Length. See RFC 2616
+		// Section 4.4. Currently len(te) > 0 implies chunked
+		// encoding.
+		delete(header, "Content-Length")
+		return te, nil
+	}
+
+	return nil, nil
+}
+
+// Determine the expected body length, using RFC 2616 Section 4.4. This
+// function is not a method, because ultimately it should be shared by
+// ReadResponse and ReadRequest.
+func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) {
+
+	// Logic based on response type or status
+	if noBodyExpected(requestMethod) {
+		return 0, nil
+	}
+	if status/100 == 1 {
+		return 0, nil
+	}
+	switch status {
+	case 204, 304:
+		return 0, nil
+	}
+
+	// Logic based on Transfer-Encoding
+	if chunked(te) {
+		return -1, nil
+	}
+
+	// Logic based on Content-Length
+	cl := strings.TrimSpace(header.Get("Content-Length"))
+	if cl != "" {
+		n, err := strconv.ParseInt(cl, 10, 64)
+		if err != nil || n < 0 {
+			return -1, &badStringError{"bad Content-Length", cl}
+		}
+		return n, nil
+	} else {
+		header.Del("Content-Length")
+	}
+
+	if !isResponse && requestMethod == "GET" {
+		// RFC 2616 doesn't explicitly permit nor forbid an
+		// entity-body on a GET request so we permit one if
+		// declared, but we default to 0 here (not -1 below)
+		// if there's no mention of a body.
+		return 0, nil
+	}
+
+	// Logic based on media type. The purpose of the following code is just
+	// to detect whether the unsupported "multipart/byteranges" is being
+	// used. A proper Content-Type parser is needed in the future.
+	if strings.Contains(strings.ToLower(header.Get("Content-Type")), "multipart/byteranges") {
+		return -1, ErrNotSupported
+	}
+
+	// Body-EOF logic based on other methods (like closing, or chunked coding)
+	return -1, nil
+}
+
+// Determine whether to hang up after sending a request and body, or
+// receiving a response and body
+// 'header' is the request headers
+func shouldClose(major, minor int, header Header) bool {
+	if major < 1 {
+		return true
+	} else if major == 1 && minor == 0 {
+		if !strings.Contains(strings.ToLower(header.Get("Connection")), "keep-alive") {
+			return true
+		}
+		return false
+	} else {
+		// TODO: Should split on commas, toss surrounding white space,
+		// and check each field.
+		if strings.ToLower(header.Get("Connection")) == "close" {
+			header.Del("Connection")
+			return true
+		}
+	}
+	return false
+}
+
+// Parse the trailer header
+func fixTrailer(header Header, te []string) (Header, error) {
+	raw := header.Get("Trailer")
+	if raw == "" {
+		return nil, nil
+	}
+
+	header.Del("Trailer")
+	trailer := make(Header)
+	keys := strings.Split(raw, ",")
+	for _, key := range keys {
+		key = CanonicalHeaderKey(strings.TrimSpace(key))
+		switch key {
+		case "Transfer-Encoding", "Trailer", "Content-Length":
+			return nil, &badStringError{"bad trailer key", key}
+		}
+		trailer.Del(key)
+	}
+	if len(trailer) == 0 {
+		return nil, nil
+	}
+	if !chunked(te) {
+		// Trailer and no chunking
+		return nil, ErrUnexpectedTrailer
+	}
+	return trailer, nil
+}
+
+// body turns a Reader into a ReadCloser.
+// Close ensures that the body has been fully read
+// and then reads the trailer if necessary.
+type body struct {
+	io.Reader
+	hdr     interface{}   // non-nil (Response or Request) value means read trailer
+	r       *bufio.Reader // underlying wire-format reader for the trailer
+	closing bool          // is the connection to be closed after reading body?
+	closed  bool
+
+	res *response // response writer for server requests, else nil
+}
+
+// ErrBodyReadAfterClose is returned when reading a Request Body after
+// the body has been closed. This typically happens when the body is
+// read after an HTTP Handler calls WriteHeader or Write on its
+// ResponseWriter.
+var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed request Body")
+
+func (b *body) Read(p []byte) (n int, err error) {
+	if b.closed {
+		return 0, ErrBodyReadAfterClose
+	}
+	n, err = b.Reader.Read(p)
+
+	// Read the final trailer once we hit EOF.
+	if err == io.EOF && b.hdr != nil {
+		if e := b.readTrailer(); e != nil {
+			err = e
+		}
+		b.hdr = nil
+	}
+	return n, err
+}
+
+var (
+	singleCRLF = []byte("\r\n")
+	doubleCRLF = []byte("\r\n\r\n")
+)
+
+func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
+	for peekSize := 4; ; peekSize++ {
+		// This loop stops when Peek returns an error,
+		// which it does when r's buffer has been filled.
+		buf, err := r.Peek(peekSize)
+		if bytes.HasSuffix(buf, doubleCRLF) {
+			return true
+		}
+		if err != nil {
+			break
+		}
+	}
+	return false
+}
+
+func (b *body) readTrailer() error {
+	// The common case, since nobody uses trailers.
+	buf, _ := b.r.Peek(2)
+	if bytes.Equal(buf, singleCRLF) {
+		b.r.ReadByte()
+		b.r.ReadByte()
+		return nil
+	}
+
+	// Make sure there's a header terminator coming up, to prevent
+	// a DoS with an unbounded size Trailer.  It's not easy to
+	// slip in a LimitReader here, as textproto.NewReader requires
+	// a concrete *bufio.Reader.  Also, we can't get all the way
+	// back up to our conn's LimitedReader that *might* be backing
+	// this bufio.Reader.  Instead, a hack: we iteratively Peek up
+	// to the bufio.Reader's max size, looking for a double CRLF.
+	// This limits the trailer to the underlying buffer size, typically 4kB.
+	if !seeUpcomingDoubleCRLF(b.r) {
+		return errors.New("http: suspiciously long trailer after chunked body")
+	}
+
+	hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
+	if err != nil {
+		return err
+	}
+	switch rr := b.hdr.(type) {
+	case *Request:
+		rr.Trailer = Header(hdr)
+	case *Response:
+		rr.Trailer = Header(hdr)
+	}
+	return nil
+}
+
+func (b *body) Close() error {
+	if b.closed {
+		return nil
+	}
+	defer func() {
+		b.closed = true
+	}()
+	if b.hdr == nil && b.closing {
+		// no trailer and closing the connection next.
+		// no point in reading to EOF.
+		return nil
+	}
+
+	// In a server request, don't continue reading from the client
+	// if we've already hit the maximum body size set by the
+	// handler. If this is set, that also means the TCP connection
+	// is about to be closed, so getting to the next HTTP request
+	// in the stream is not necessary.
+	if b.res != nil && b.res.requestBodyLimitHit {
+		return nil
+	}
+
+	// Fully consume the body, which will also lead to us reading
+	// the trailer headers after the body, if present.
+	if _, err := io.Copy(ioutil.Discard, b); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/src/pkg/net/http/transport.go b/src/pkg/net/http/transport.go
new file mode 100644
index 0000000..4de070f
--- /dev/null
+++ b/src/pkg/net/http/transport.go
@@ -0,0 +1,736 @@
+// Copyright 2011 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.
+
+// HTTP client implementation. See RFC 2616.
+// 
+// This is the low-level Transport implementation of RoundTripper.
+// The high-level interface is in client.go.
+
+package http
+
+import (
+	"bufio"
+	"compress/gzip"
+	"crypto/tls"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/url"
+	"os"
+	"strings"
+	"sync"
+)
+
+// DefaultTransport is the default implementation of Transport and is
+// used by DefaultClient.  It establishes a new network connection for
+// each call to Do and uses HTTP proxies as directed by the
+// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy)
+// environment variables.
+var DefaultTransport RoundTripper = &Transport{Proxy: ProxyFromEnvironment}
+
+// DefaultMaxIdleConnsPerHost is the default value of Transport's
+// MaxIdleConnsPerHost.
+const DefaultMaxIdleConnsPerHost = 2
+
+// Transport is an implementation of RoundTripper that supports http,
+// https, and http proxies (for either http or https with CONNECT).
+// Transport can also cache connections for future re-use.
+type Transport struct {
+	lk       sync.Mutex
+	idleConn map[string][]*persistConn
+	altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
+
+	// TODO: tunable on global max cached connections
+	// TODO: tunable on timeout on cached connections
+	// TODO: optional pipelining
+
+	// Proxy specifies a function to return a proxy for a given
+	// Request. If the function returns a non-nil error, the
+	// request is aborted with the provided error.
+	// If Proxy is nil or returns a nil *URL, no proxy is used.
+	Proxy func(*Request) (*url.URL, error)
+
+	// Dial specifies the dial function for creating TCP
+	// connections.
+	// If Dial is nil, net.Dial is used.
+	Dial func(net, addr string) (c net.Conn, err error)
+
+	// TLSClientConfig specifies the TLS configuration to use with
+	// tls.Client. If nil, the default configuration is used.
+	TLSClientConfig *tls.Config
+
+	DisableKeepAlives  bool
+	DisableCompression bool
+
+	// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
+	// (keep-alive) to keep to keep per-host.  If zero,
+	// DefaultMaxIdleConnsPerHost is used.
+	MaxIdleConnsPerHost int
+}
+
+// ProxyFromEnvironment returns the URL of the proxy to use for a
+// given request, as indicated by the environment variables
+// $HTTP_PROXY and $NO_PROXY (or $http_proxy and $no_proxy).
+// Either URL or an error is returned.
+func ProxyFromEnvironment(req *Request) (*url.URL, error) {
+	proxy := getenvEitherCase("HTTP_PROXY")
+	if proxy == "" {
+		return nil, nil
+	}
+	if !useProxy(canonicalAddr(req.URL)) {
+		return nil, nil
+	}
+	proxyURL, err := url.ParseRequest(proxy)
+	if err != nil {
+		return nil, errors.New("invalid proxy address")
+	}
+	if proxyURL.Host == "" {
+		proxyURL, err = url.ParseRequest("http://" + proxy)
+		if err != nil {
+			return nil, errors.New("invalid proxy address")
+		}
+	}
+	return proxyURL, nil
+}
+
+// ProxyURL returns a proxy function (for use in a Transport)
+// that always returns the same URL.
+func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error) {
+	return func(*Request) (*url.URL, error) {
+		return fixedURL, nil
+	}
+}
+
+// transportRequest is a wrapper around a *Request that adds
+// optional extra headers to write.
+type transportRequest struct {
+	*Request        // original request, not to be mutated
+	extra    Header // extra headers to write, or nil
+}
+
+func (tr *transportRequest) extraHeaders() Header {
+	if tr.extra == nil {
+		tr.extra = make(Header)
+	}
+	return tr.extra
+}
+
+// RoundTrip implements the RoundTripper interface.
+func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
+	if req.URL == nil {
+		return nil, errors.New("http: nil Request.URL")
+	}
+	if req.Header == nil {
+		return nil, errors.New("http: nil Request.Header")
+	}
+	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
+		t.lk.Lock()
+		var rt RoundTripper
+		if t.altProto != nil {
+			rt = t.altProto[req.URL.Scheme]
+		}
+		t.lk.Unlock()
+		if rt == nil {
+			return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
+		}
+		return rt.RoundTrip(req)
+	}
+	treq := &transportRequest{Request: req}
+	cm, err := t.connectMethodForRequest(treq)
+	if err != nil {
+		return nil, err
+	}
+
+	// Get the cached or newly-created connection to either the
+	// host (for http or https), the http proxy, or the http proxy
+	// pre-CONNECTed to https server.  In any case, we'll be ready
+	// to send it requests.
+	pconn, err := t.getConn(cm)
+	if err != nil {
+		return nil, err
+	}
+
+	return pconn.roundTrip(treq)
+}
+
+// RegisterProtocol registers a new protocol with scheme.
+// The Transport will pass requests using the given scheme to rt.
+// It is rt's responsibility to simulate HTTP request semantics.
+//
+// RegisterProtocol can be used by other packages to provide
+// implementations of protocol schemes like "ftp" or "file".
+func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
+	if scheme == "http" || scheme == "https" {
+		panic("protocol " + scheme + " already registered")
+	}
+	t.lk.Lock()
+	defer t.lk.Unlock()
+	if t.altProto == nil {
+		t.altProto = make(map[string]RoundTripper)
+	}
+	if _, exists := t.altProto[scheme]; exists {
+		panic("protocol " + scheme + " already registered")
+	}
+	t.altProto[scheme] = rt
+}
+
+// CloseIdleConnections closes any connections which were previously
+// connected from previous requests but are now sitting idle in
+// a "keep-alive" state. It does not interrupt any connections currently
+// in use.
+func (t *Transport) CloseIdleConnections() {
+	t.lk.Lock()
+	defer t.lk.Unlock()
+	if t.idleConn == nil {
+		return
+	}
+	for _, conns := range t.idleConn {
+		for _, pconn := range conns {
+			pconn.close()
+		}
+	}
+	t.idleConn = nil
+}
+
+//
+// Private implementation past this point.
+//
+
+func getenvEitherCase(k string) string {
+	if v := os.Getenv(strings.ToUpper(k)); v != "" {
+		return v
+	}
+	return os.Getenv(strings.ToLower(k))
+}
+
+func (t *Transport) connectMethodForRequest(treq *transportRequest) (*connectMethod, error) {
+	cm := &connectMethod{
+		targetScheme: treq.URL.Scheme,
+		targetAddr:   canonicalAddr(treq.URL),
+	}
+	if t.Proxy != nil {
+		var err error
+		cm.proxyURL, err = t.Proxy(treq.Request)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return cm, nil
+}
+
+// proxyAuth returns the Proxy-Authorization header to set
+// on requests, if applicable.
+func (cm *connectMethod) proxyAuth() string {
+	if cm.proxyURL == nil {
+		return ""
+	}
+	if u := cm.proxyURL.User; u != nil {
+		return "Basic " + base64.URLEncoding.EncodeToString([]byte(u.String()))
+	}
+	return ""
+}
+
+func (t *Transport) putIdleConn(pconn *persistConn) {
+	t.lk.Lock()
+	defer t.lk.Unlock()
+	if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
+		pconn.close()
+		return
+	}
+	if pconn.isBroken() {
+		return
+	}
+	key := pconn.cacheKey
+	max := t.MaxIdleConnsPerHost
+	if max == 0 {
+		max = DefaultMaxIdleConnsPerHost
+	}
+	if len(t.idleConn[key]) >= max {
+		pconn.close()
+		return
+	}
+	t.idleConn[key] = append(t.idleConn[key], pconn)
+}
+
+func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
+	t.lk.Lock()
+	defer t.lk.Unlock()
+	if t.idleConn == nil {
+		t.idleConn = make(map[string][]*persistConn)
+	}
+	key := cm.String()
+	for {
+		pconns, ok := t.idleConn[key]
+		if !ok {
+			return nil
+		}
+		if len(pconns) == 1 {
+			pconn = pconns[0]
+			delete(t.idleConn, key)
+		} else {
+			// 2 or more cached connections; pop last
+			// TODO: queue?
+			pconn = pconns[len(pconns)-1]
+			t.idleConn[key] = pconns[0 : len(pconns)-1]
+		}
+		if !pconn.isBroken() {
+			return
+		}
+	}
+	return
+}
+
+func (t *Transport) dial(network, addr string) (c net.Conn, err error) {
+	if t.Dial != nil {
+		return t.Dial(network, addr)
+	}
+	return net.Dial(network, addr)
+}
+
+// getConn dials and creates a new persistConn to the target as
+// specified in the connectMethod.  This includes doing a proxy CONNECT
+// and/or setting up TLS.  If this doesn't return an error, the persistConn
+// is ready to write requests to.
+func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
+	if pc := t.getIdleConn(cm); pc != nil {
+		return pc, nil
+	}
+
+	conn, err := t.dial("tcp", cm.addr())
+	if err != nil {
+		if cm.proxyURL != nil {
+			err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
+		}
+		return nil, err
+	}
+
+	pa := cm.proxyAuth()
+
+	pconn := &persistConn{
+		t:        t,
+		cacheKey: cm.String(),
+		conn:     conn,
+		reqch:    make(chan requestAndChan, 50),
+	}
+
+	switch {
+	case cm.proxyURL == nil:
+		// Do nothing.
+	case cm.targetScheme == "http":
+		pconn.isProxy = true
+		if pa != "" {
+			pconn.mutateHeaderFunc = func(h Header) {
+				h.Set("Proxy-Authorization", pa)
+			}
+		}
+	case cm.targetScheme == "https":
+		connectReq := &Request{
+			Method: "CONNECT",
+			URL:    &url.URL{Opaque: cm.targetAddr},
+			Host:   cm.targetAddr,
+			Header: make(Header),
+		}
+		if pa != "" {
+			connectReq.Header.Set("Proxy-Authorization", pa)
+		}
+		connectReq.Write(conn)
+
+		// Read response.
+		// Okay to use and discard buffered reader here, because
+		// TLS server will not speak until spoken to.
+		br := bufio.NewReader(conn)
+		resp, err := ReadResponse(br, connectReq)
+		if err != nil {
+			conn.Close()
+			return nil, err
+		}
+		if resp.StatusCode != 200 {
+			f := strings.SplitN(resp.Status, " ", 2)
+			conn.Close()
+			return nil, errors.New(f[1])
+		}
+	}
+
+	if cm.targetScheme == "https" {
+		// Initiate TLS and check remote host name against certificate.
+		conn = tls.Client(conn, t.TLSClientConfig)
+		if err = conn.(*tls.Conn).Handshake(); err != nil {
+			return nil, err
+		}
+		if t.TLSClientConfig == nil || !t.TLSClientConfig.InsecureSkipVerify {
+			if err = conn.(*tls.Conn).VerifyHostname(cm.tlsHost()); err != nil {
+				return nil, err
+			}
+		}
+		pconn.conn = conn
+	}
+
+	pconn.br = bufio.NewReader(pconn.conn)
+	pconn.bw = bufio.NewWriter(pconn.conn)
+	go pconn.readLoop()
+	return pconn, nil
+}
+
+// useProxy returns true if requests to addr should use a proxy,
+// according to the NO_PROXY or no_proxy environment variable.
+// addr is always a canonicalAddr with a host and port.
+func useProxy(addr string) bool {
+	if len(addr) == 0 {
+		return true
+	}
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return false
+	}
+	if host == "localhost" {
+		return false
+	}
+	if ip := net.ParseIP(host); ip != nil {
+		if ip.IsLoopback() {
+			return false
+		}
+	}
+
+	no_proxy := getenvEitherCase("NO_PROXY")
+	if no_proxy == "*" {
+		return false
+	}
+
+	addr = strings.ToLower(strings.TrimSpace(addr))
+	if hasPort(addr) {
+		addr = addr[:strings.LastIndex(addr, ":")]
+	}
+
+	for _, p := range strings.Split(no_proxy, ",") {
+		p = strings.ToLower(strings.TrimSpace(p))
+		if len(p) == 0 {
+			continue
+		}
+		if hasPort(p) {
+			p = p[:strings.LastIndex(p, ":")]
+		}
+		if addr == p || (p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:])) {
+			return false
+		}
+	}
+	return true
+}
+
+// connectMethod is the map key (in its String form) for keeping persistent
+// TCP connections alive for subsequent HTTP requests.
+//
+// A connect method may be of the following types:
+//
+// Cache key form                Description
+// -----------------             -------------------------
+// ||http|foo.com                http directly to server, no proxy
+// ||https|foo.com               https directly to server, no proxy
+// http://proxy.com|https|foo.com  http to proxy, then CONNECT to foo.com
+// http://proxy.com|http           http to proxy, http to anywhere after that
+//
+// Note: no support to https to the proxy yet.
+//
+type connectMethod struct {
+	proxyURL     *url.URL // nil for no proxy, else full proxy URL
+	targetScheme string   // "http" or "https"
+	targetAddr   string   // Not used if proxy + http targetScheme (4th example in table)
+}
+
+func (ck *connectMethod) String() string {
+	proxyStr := ""
+	if ck.proxyURL != nil {
+		proxyStr = ck.proxyURL.String()
+	}
+	return strings.Join([]string{proxyStr, ck.targetScheme, ck.targetAddr}, "|")
+}
+
+// addr returns the first hop "host:port" to which we need to TCP connect.
+func (cm *connectMethod) addr() string {
+	if cm.proxyURL != nil {
+		return canonicalAddr(cm.proxyURL)
+	}
+	return cm.targetAddr
+}
+
+// tlsHost returns the host name to match against the peer's
+// TLS certificate.
+func (cm *connectMethod) tlsHost() string {
+	h := cm.targetAddr
+	if hasPort(h) {
+		h = h[:strings.LastIndex(h, ":")]
+	}
+	return h
+}
+
+// persistConn wraps a connection, usually a persistent one
+// (but may be used for non-keep-alive requests as well)
+type persistConn struct {
+	t        *Transport
+	cacheKey string // its connectMethod.String()
+	conn     net.Conn
+	br       *bufio.Reader       // from conn
+	bw       *bufio.Writer       // to conn
+	reqch    chan requestAndChan // written by roundTrip(); read by readLoop()
+	isProxy  bool
+
+	// mutateHeaderFunc is an optional func to modify extra
+	// headers on each outbound request before it's written. (the
+	// original Request given to RoundTrip is not modified)
+	mutateHeaderFunc func(Header)
+
+	lk                   sync.Mutex // guards numExpectedResponses and broken
+	numExpectedResponses int
+	broken               bool // an error has happened on this connection; marked broken so it's not reused.
+}
+
+func (pc *persistConn) isBroken() bool {
+	pc.lk.Lock()
+	defer pc.lk.Unlock()
+	return pc.broken
+}
+
+var remoteSideClosedFunc func(error) bool // or nil to use default
+
+func remoteSideClosed(err error) bool {
+	if err == io.EOF {
+		return true
+	}
+	if remoteSideClosedFunc != nil {
+		return remoteSideClosedFunc(err)
+	}
+	return false
+}
+
+func (pc *persistConn) readLoop() {
+	alive := true
+	var lastbody io.ReadCloser // last response body, if any, read on this connection
+
+	for alive {
+		pb, err := pc.br.Peek(1)
+
+		pc.lk.Lock()
+		if pc.numExpectedResponses == 0 {
+			pc.closeLocked()
+			pc.lk.Unlock()
+			if len(pb) > 0 {
+				log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
+					string(pb), err)
+			}
+			return
+		}
+		pc.lk.Unlock()
+
+		rc := <-pc.reqch
+
+		// Advance past the previous response's body, if the
+		// caller hasn't done so.
+		if lastbody != nil {
+			lastbody.Close() // assumed idempotent
+			lastbody = nil
+		}
+		resp, err := ReadResponse(pc.br, rc.req)
+
+		if err == nil {
+			hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0
+			if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" {
+				resp.Header.Del("Content-Encoding")
+				resp.Header.Del("Content-Length")
+				resp.ContentLength = -1
+				gzReader, zerr := gzip.NewReader(resp.Body)
+				if zerr != nil {
+					pc.close()
+					err = zerr
+				} else {
+					resp.Body = &readFirstCloseBoth{&discardOnCloseReadCloser{gzReader}, resp.Body}
+				}
+			}
+			resp.Body = &bodyEOFSignal{body: resp.Body}
+		}
+
+		if err != nil || resp.Close || rc.req.Close {
+			alive = false
+		}
+
+		hasBody := resp != nil && resp.ContentLength != 0
+		var waitForBodyRead chan bool
+		if alive {
+			if hasBody {
+				lastbody = resp.Body
+				waitForBodyRead = make(chan bool)
+				resp.Body.(*bodyEOFSignal).fn = func() {
+					pc.t.putIdleConn(pc)
+					waitForBodyRead <- true
+				}
+			} else {
+				// When there's no response body, we immediately
+				// reuse the TCP connection (putIdleConn), but
+				// we need to prevent ClientConn.Read from
+				// closing the Response.Body on the next
+				// loop, otherwise it might close the body
+				// before the client code has had a chance to
+				// read it (even though it'll just be 0, EOF).
+				lastbody = nil
+
+				pc.t.putIdleConn(pc)
+			}
+		}
+
+		rc.ch <- responseAndError{resp, err}
+
+		// Wait for the just-returned response body to be fully consumed
+		// before we race and peek on the underlying bufio reader.
+		if waitForBodyRead != nil {
+			<-waitForBodyRead
+		}
+	}
+}
+
+type responseAndError struct {
+	res *Response
+	err error
+}
+
+type requestAndChan struct {
+	req *Request
+	ch  chan responseAndError
+
+	// did the Transport (as opposed to the client code) add an
+	// Accept-Encoding gzip header? only if it we set it do
+	// we transparently decode the gzip.
+	addedGzip bool
+}
+
+func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
+	if pc.mutateHeaderFunc != nil {
+		pc.mutateHeaderFunc(req.extraHeaders())
+	}
+
+	// Ask for a compressed version if the caller didn't set their
+	// own value for Accept-Encoding. We only attempted to
+	// uncompress the gzip stream if we were the layer that
+	// requested it.
+	requestedGzip := false
+	if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" {
+		// Request gzip only, not deflate. Deflate is ambiguous and 
+		// not as universally supported anyway.
+		// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
+		requestedGzip = true
+		req.extraHeaders().Set("Accept-Encoding", "gzip")
+	}
+
+	pc.lk.Lock()
+	pc.numExpectedResponses++
+	pc.lk.Unlock()
+
+	err = req.Request.write(pc.bw, pc.isProxy, req.extra)
+	if err != nil {
+		pc.close()
+		return
+	}
+	pc.bw.Flush()
+
+	ch := make(chan responseAndError, 1)
+	pc.reqch <- requestAndChan{req.Request, ch, requestedGzip}
+	re := <-ch
+	pc.lk.Lock()
+	pc.numExpectedResponses--
+	pc.lk.Unlock()
+
+	return re.res, re.err
+}
+
+func (pc *persistConn) close() {
+	pc.lk.Lock()
+	defer pc.lk.Unlock()
+	pc.closeLocked()
+}
+
+func (pc *persistConn) closeLocked() {
+	pc.broken = true
+	pc.conn.Close()
+	pc.mutateHeaderFunc = nil
+}
+
+var portMap = map[string]string{
+	"http":  "80",
+	"https": "443",
+}
+
+// canonicalAddr returns url.Host but always with a ":port" suffix
+func canonicalAddr(url *url.URL) string {
+	addr := url.Host
+	if !hasPort(addr) {
+		return addr + ":" + portMap[url.Scheme]
+	}
+	return addr
+}
+
+func responseIsKeepAlive(res *Response) bool {
+	// TODO: implement.  for now just always shutting down the connection.
+	return false
+}
+
+// bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
+// once, right before the final Read() or Close() call returns, but after
+// EOF has been seen.
+type bodyEOFSignal struct {
+	body     io.ReadCloser
+	fn       func()
+	isClosed bool
+}
+
+func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
+	n, err = es.body.Read(p)
+	if es.isClosed && n > 0 {
+		panic("http: unexpected bodyEOFSignal Read after Close; see issue 1725")
+	}
+	if err == io.EOF && es.fn != nil {
+		es.fn()
+		es.fn = nil
+	}
+	return
+}
+
+func (es *bodyEOFSignal) Close() (err error) {
+	if es.isClosed {
+		return nil
+	}
+	es.isClosed = true
+	err = es.body.Close()
+	if err == nil && es.fn != nil {
+		es.fn()
+		es.fn = nil
+	}
+	return
+}
+
+type readFirstCloseBoth struct {
+	io.ReadCloser
+	io.Closer
+}
+
+func (r *readFirstCloseBoth) Close() error {
+	if err := r.ReadCloser.Close(); err != nil {
+		r.Closer.Close()
+		return err
+	}
+	if err := r.Closer.Close(); err != nil {
+		return err
+	}
+	return nil
+}
+
+// discardOnCloseReadCloser consumes all its input on Close.
+type discardOnCloseReadCloser struct {
+	io.ReadCloser
+}
+
+func (d *discardOnCloseReadCloser) Close() error {
+	io.Copy(ioutil.Discard, d.ReadCloser) // ignore errors; likely invalid or already closed
+	return d.ReadCloser.Close()
+}
diff --git a/src/pkg/net/http/transport_test.go b/src/pkg/net/http/transport_test.go
new file mode 100644
index 0000000..321da52
--- /dev/null
+++ b/src/pkg/net/http/transport_test.go
@@ -0,0 +1,695 @@
+// Copyright 2011 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.
+
+// Tests for transport.go
+
+package http_test
+
+import (
+	"bytes"
+	"compress/gzip"
+	"crypto/rand"
+	"fmt"
+	"io"
+	"io/ioutil"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+// TODO: test 5 pipelined requests with responses: 1) OK, 2) OK, Connection: Close
+//       and then verify that the final 2 responses get errors back.
+
+// hostPortHandler writes back the client's "host:port".
+var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
+	if r.FormValue("close") == "true" {
+		w.Header().Set("Connection", "close")
+	}
+	w.Write([]byte(r.RemoteAddr))
+})
+
+// Two subsequent requests and verify their response is the same.
+// The response from the server is our own IP:port
+func TestTransportKeepAlives(t *testing.T) {
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	for _, disableKeepAlive := range []bool{false, true} {
+		tr := &Transport{DisableKeepAlives: disableKeepAlive}
+		c := &Client{Transport: tr}
+
+		fetch := func(n int) string {
+			res, err := c.Get(ts.URL)
+			if err != nil {
+				t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
+			}
+			body, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err)
+			}
+			return string(body)
+		}
+
+		body1 := fetch(1)
+		body2 := fetch(2)
+
+		bodiesDiffer := body1 != body2
+		if bodiesDiffer != disableKeepAlive {
+			t.Errorf("error in disableKeepAlive=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
+				disableKeepAlive, bodiesDiffer, body1, body2)
+		}
+	}
+}
+
+func TestTransportConnectionCloseOnResponse(t *testing.T) {
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	for _, connectionClose := range []bool{false, true} {
+		tr := &Transport{}
+		c := &Client{Transport: tr}
+
+		fetch := func(n int) string {
+			req := new(Request)
+			var err error
+			req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose))
+			if err != nil {
+				t.Fatalf("URL parse error: %v", err)
+			}
+			req.Method = "GET"
+			req.Proto = "HTTP/1.1"
+			req.ProtoMajor = 1
+			req.ProtoMinor = 1
+
+			res, err := c.Do(req)
+			if err != nil {
+				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
+			}
+			body, err := ioutil.ReadAll(res.Body)
+			defer res.Body.Close()
+			if err != nil {
+				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
+			}
+			return string(body)
+		}
+
+		body1 := fetch(1)
+		body2 := fetch(2)
+		bodiesDiffer := body1 != body2
+		if bodiesDiffer != connectionClose {
+			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
+				connectionClose, bodiesDiffer, body1, body2)
+		}
+	}
+}
+
+func TestTransportConnectionCloseOnRequest(t *testing.T) {
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	for _, connectionClose := range []bool{false, true} {
+		tr := &Transport{}
+		c := &Client{Transport: tr}
+
+		fetch := func(n int) string {
+			req := new(Request)
+			var err error
+			req.URL, err = url.Parse(ts.URL)
+			if err != nil {
+				t.Fatalf("URL parse error: %v", err)
+			}
+			req.Method = "GET"
+			req.Proto = "HTTP/1.1"
+			req.ProtoMajor = 1
+			req.ProtoMinor = 1
+			req.Close = connectionClose
+
+			res, err := c.Do(req)
+			if err != nil {
+				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
+			}
+			body, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
+			}
+			return string(body)
+		}
+
+		body1 := fetch(1)
+		body2 := fetch(2)
+		bodiesDiffer := body1 != body2
+		if bodiesDiffer != connectionClose {
+			t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
+				connectionClose, bodiesDiffer, body1, body2)
+		}
+	}
+}
+
+func TestTransportIdleCacheKeys(t *testing.T) {
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	c := &Client{Transport: tr}
+
+	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
+		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
+	}
+
+	resp, err := c.Get(ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	ioutil.ReadAll(resp.Body)
+
+	keys := tr.IdleConnKeysForTesting()
+	if e, g := 1, len(keys); e != g {
+		t.Fatalf("After Get expected %d idle conn cache keys; got %d", e, g)
+	}
+
+	if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
+		t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
+	}
+
+	tr.CloseIdleConnections()
+	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
+		t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
+	}
+}
+
+func TestTransportMaxPerHostIdleConns(t *testing.T) {
+	resch := make(chan string)
+	gotReq := make(chan bool)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		gotReq <- true
+		msg := <-resch
+		_, err := w.Write([]byte(msg))
+		if err != nil {
+			t.Fatalf("Write: %v", err)
+		}
+	}))
+	defer ts.Close()
+	maxIdleConns := 2
+	tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns}
+	c := &Client{Transport: tr}
+
+	// Start 3 outstanding requests and wait for the server to get them.
+	// Their responses will hang until we we write to resch, though.
+	donech := make(chan bool)
+	doReq := func() {
+		resp, err := c.Get(ts.URL)
+		if err != nil {
+			t.Error(err)
+		}
+		_, err = ioutil.ReadAll(resp.Body)
+		if err != nil {
+			t.Fatalf("ReadAll: %v", err)
+		}
+		donech <- true
+	}
+	go doReq()
+	<-gotReq
+	go doReq()
+	<-gotReq
+	go doReq()
+	<-gotReq
+
+	if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
+		t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
+	}
+
+	resch <- "res1"
+	<-donech
+	keys := tr.IdleConnKeysForTesting()
+	if e, g := 1, len(keys); e != g {
+		t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
+	}
+	cacheKey := "|http|" + ts.Listener.Addr().String()
+	if keys[0] != cacheKey {
+		t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
+	}
+	if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g {
+		t.Errorf("after first response, expected %d idle conns; got %d", e, g)
+	}
+
+	resch <- "res2"
+	<-donech
+	if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g {
+		t.Errorf("after second response, expected %d idle conns; got %d", e, g)
+	}
+
+	resch <- "res3"
+	<-donech
+	if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g {
+		t.Errorf("after third response, still expected %d idle conns; got %d", e, g)
+	}
+}
+
+func TestTransportServerClosingUnexpectedly(t *testing.T) {
+	ts := httptest.NewServer(hostPortHandler)
+	defer ts.Close()
+
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+
+	fetch := func(n, retries int) string {
+		condFatalf := func(format string, arg ...interface{}) {
+			if retries <= 0 {
+				t.Fatalf(format, arg...)
+			}
+			t.Logf("retrying shortly after expected error: "+format, arg...)
+			time.Sleep(time.Second / time.Duration(retries))
+		}
+		for retries >= 0 {
+			retries--
+			res, err := c.Get(ts.URL)
+			if err != nil {
+				condFatalf("error in req #%d, GET: %v", n, err)
+				continue
+			}
+			body, err := ioutil.ReadAll(res.Body)
+			if err != nil {
+				condFatalf("error in req #%d, ReadAll: %v", n, err)
+				continue
+			}
+			res.Body.Close()
+			return string(body)
+		}
+		panic("unreachable")
+	}
+
+	body1 := fetch(1, 0)
+	body2 := fetch(2, 0)
+
+	ts.CloseClientConnections() // surprise!
+
+	// This test has an expected race. Sleeping for 25 ms prevents
+	// it on most fast machines, causing the next fetch() call to
+	// succeed quickly.  But if we do get errors, fetch() will retry 5
+	// times with some delays between.
+	time.Sleep(25 * time.Millisecond)
+
+	body3 := fetch(3, 5)
+
+	if body1 != body2 {
+		t.Errorf("expected body1 and body2 to be equal")
+	}
+	if body2 == body3 {
+		t.Errorf("expected body2 and body3 to be different")
+	}
+}
+
+// Test for http://golang.org/issue/2616 (appropriate issue number)
+// This fails pretty reliably with GOMAXPROCS=100 or something high.
+func TestStressSurpriseServerCloses(t *testing.T) {
+	if testing.Short() {
+		t.Logf("skipping test in short mode")
+		return
+	}
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", "5")
+		w.Header().Set("Content-Type", "text/plain")
+		w.Write([]byte("Hello"))
+		w.(Flusher).Flush()
+		conn, buf, _ := w.(Hijacker).Hijack()
+		buf.Flush()
+		conn.Close()
+	}))
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	c := &Client{Transport: tr}
+
+	// Do a bunch of traffic from different goroutines. Send to activityc
+	// after each request completes, regardless of whether it failed.
+	const (
+		numClients    = 50
+		reqsPerClient = 250
+	)
+	activityc := make(chan bool)
+	for i := 0; i < numClients; i++ {
+		go func() {
+			for i := 0; i < reqsPerClient; i++ {
+				res, err := c.Get(ts.URL)
+				if err == nil {
+					// We expect errors since the server is
+					// hanging up on us after telling us to
+					// send more requests, so we don't
+					// actually care what the error is.
+					// But we want to close the body in cases
+					// where we won the race.
+					res.Body.Close()
+				}
+				activityc <- true
+			}
+		}()
+	}
+
+	// Make sure all the request come back, one way or another.
+	for i := 0; i < numClients*reqsPerClient; i++ {
+		select {
+		case <-activityc:
+		case <-time.After(5 * time.Second):
+			t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile")
+		}
+	}
+}
+
+// TestTransportHeadResponses verifies that we deal with Content-Lengths
+// with no bodies properly
+func TestTransportHeadResponses(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.Method != "HEAD" {
+			panic("expected HEAD; got " + r.Method)
+		}
+		w.Header().Set("Content-Length", "123")
+		w.WriteHeader(200)
+	}))
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	c := &Client{Transport: tr}
+	for i := 0; i < 2; i++ {
+		res, err := c.Head(ts.URL)
+		if err != nil {
+			t.Errorf("error on loop %d: %v", i, err)
+		}
+		if e, g := "123", res.Header.Get("Content-Length"); e != g {
+			t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g)
+		}
+		if e, g := int64(0), res.ContentLength; e != g {
+			t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
+		}
+	}
+}
+
+// TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
+// on responses to HEAD requests.
+func TestTransportHeadChunkedResponse(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		if r.Method != "HEAD" {
+			panic("expected HEAD; got " + r.Method)
+		}
+		w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
+		w.Header().Set("x-client-ipport", r.RemoteAddr)
+		w.WriteHeader(200)
+	}))
+	defer ts.Close()
+
+	tr := &Transport{DisableKeepAlives: false}
+	c := &Client{Transport: tr}
+
+	res1, err := c.Head(ts.URL)
+	if err != nil {
+		t.Fatalf("request 1 error: %v", err)
+	}
+	res2, err := c.Head(ts.URL)
+	if err != nil {
+		t.Fatalf("request 2 error: %v", err)
+	}
+	if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
+		t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
+	}
+}
+
+var roundTripTests = []struct {
+	accept       string
+	expectAccept string
+	compressed   bool
+}{
+	// Requests with no accept-encoding header use transparent compression
+	{"", "gzip", false},
+	// Requests with other accept-encoding should pass through unmodified
+	{"foo", "foo", false},
+	// Requests with accept-encoding == gzip should be passed through
+	{"gzip", "gzip", true},
+}
+
+// Test that the modification made to the Request by the RoundTripper is cleaned up
+func TestRoundTripGzip(t *testing.T) {
+	const responseBody = "test response body"
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		accept := req.Header.Get("Accept-Encoding")
+		if expect := req.FormValue("expect_accept"); accept != expect {
+			t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q",
+				req.FormValue("testnum"), accept, expect)
+		}
+		if accept == "gzip" {
+			rw.Header().Set("Content-Encoding", "gzip")
+			gz, _ := gzip.NewWriter(rw)
+			gz.Write([]byte(responseBody))
+			gz.Close()
+		} else {
+			rw.Header().Set("Content-Encoding", accept)
+			rw.Write([]byte(responseBody))
+		}
+	}))
+	defer ts.Close()
+
+	for i, test := range roundTripTests {
+		// Test basic request (no accept-encoding)
+		req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil)
+		if test.accept != "" {
+			req.Header.Set("Accept-Encoding", test.accept)
+		}
+		res, err := DefaultTransport.RoundTrip(req)
+		var body []byte
+		if test.compressed {
+			gzip, _ := gzip.NewReader(res.Body)
+			body, err = ioutil.ReadAll(gzip)
+			res.Body.Close()
+		} else {
+			body, err = ioutil.ReadAll(res.Body)
+		}
+		if err != nil {
+			t.Errorf("%d. Error: %q", i, err)
+			continue
+		}
+		if g, e := string(body), responseBody; g != e {
+			t.Errorf("%d. body = %q; want %q", i, g, e)
+		}
+		if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e {
+			t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e)
+		}
+		if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e {
+			t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e)
+		}
+	}
+
+}
+
+func TestTransportGzip(t *testing.T) {
+	const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+	const nRandBytes = 1024 * 1024
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e {
+			t.Errorf("Accept-Encoding = %q, want %q", g, e)
+		}
+		rw.Header().Set("Content-Encoding", "gzip")
+		if req.Method == "HEAD" {
+			return
+		}
+
+		var w io.Writer = rw
+		var buf bytes.Buffer
+		if req.FormValue("chunked") == "0" {
+			w = &buf
+			defer io.Copy(rw, &buf)
+			defer func() {
+				rw.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
+			}()
+		}
+		gz, _ := gzip.NewWriter(w)
+		gz.Write([]byte(testString))
+		if req.FormValue("body") == "large" {
+			io.CopyN(gz, rand.Reader, nRandBytes)
+		}
+		gz.Close()
+	}))
+	defer ts.Close()
+
+	for _, chunked := range []string{"1", "0"} {
+		c := &Client{Transport: &Transport{}}
+
+		// First fetch something large, but only read some of it.
+		res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked)
+		if err != nil {
+			t.Fatalf("large get: %v", err)
+		}
+		buf := make([]byte, len(testString))
+		n, err := io.ReadFull(res.Body, buf)
+		if err != nil {
+			t.Fatalf("partial read of large response: size=%d, %v", n, err)
+		}
+		if e, g := testString, string(buf); e != g {
+			t.Errorf("partial read got %q, expected %q", g, e)
+		}
+		res.Body.Close()
+		// Read on the body, even though it's closed
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected error post-closed large Read; got = %d, %v", n, err)
+		}
+
+		// Then something small.
+		res, err = c.Get(ts.URL + "/?chunked=" + chunked)
+		if err != nil {
+			t.Fatal(err)
+		}
+		body, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if g, e := string(body), testString; g != e {
+			t.Fatalf("body = %q; want %q", g, e)
+		}
+		if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
+			t.Fatalf("Content-Encoding = %q; want %q", g, e)
+		}
+
+		// Read on the body after it's been fully read:
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected Read error after exhausted reads; got %d, %v", n, err)
+		}
+		res.Body.Close()
+		n, err = res.Body.Read(buf)
+		if n != 0 || err == nil {
+			t.Errorf("expected Read error after Close; got %d, %v", n, err)
+		}
+	}
+
+	// And a HEAD request too, because they're always weird.
+	c := &Client{Transport: &Transport{}}
+	res, err := c.Head(ts.URL)
+	if err != nil {
+		t.Fatalf("Head: %v", err)
+	}
+	if res.StatusCode != 200 {
+		t.Errorf("Head status=%d; want=200", res.StatusCode)
+	}
+}
+
+func TestTransportProxy(t *testing.T) {
+	ch := make(chan string, 1)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ch <- "real server"
+	}))
+	defer ts.Close()
+	proxy := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		ch <- "proxy for " + r.URL.String()
+	}))
+	defer proxy.Close()
+
+	pu, err := url.Parse(proxy.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	c := &Client{Transport: &Transport{Proxy: ProxyURL(pu)}}
+	c.Head(ts.URL)
+	got := <-ch
+	want := "proxy for " + ts.URL + "/"
+	if got != want {
+		t.Errorf("want %q, got %q", want, got)
+	}
+}
+
+// TestTransportGzipRecursive sends a gzip quine and checks that the
+// client gets the same value back. This is more cute than anything,
+// but checks that we don't recurse forever, and checks that
+// Content-Encoding is removed.
+func TestTransportGzipRecursive(t *testing.T) {
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Encoding", "gzip")
+		w.Write(rgz)
+	}))
+	defer ts.Close()
+
+	c := &Client{Transport: &Transport{}}
+	res, err := c.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !bytes.Equal(body, rgz) {
+		t.Fatalf("Incorrect result from recursive gz:\nhave=%x\nwant=%x",
+			body, rgz)
+	}
+	if g, e := res.Header.Get("Content-Encoding"), ""; g != e {
+		t.Fatalf("Content-Encoding = %q; want %q", g, e)
+	}
+}
+
+type fooProto struct{}
+
+func (fooProto) RoundTrip(req *Request) (*Response, error) {
+	res := &Response{
+		Status:     "200 OK",
+		StatusCode: 200,
+		Header:     make(Header),
+		Body:       ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())),
+	}
+	return res, nil
+}
+
+func TestTransportAltProto(t *testing.T) {
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+	tr.RegisterProtocol("foo", fooProto{})
+	res, err := c.Get("foo://bar.com/path")
+	if err != nil {
+		t.Fatal(err)
+	}
+	bodyb, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	body := string(bodyb)
+	if e := "You wanted foo://bar.com/path"; body != e {
+		t.Errorf("got response %q, want %q", body, e)
+	}
+}
+
+// rgz is a gzip quine that uncompresses to itself.
+var rgz = []byte{
+	0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73,
+	0x69, 0x76, 0x65, 0x00, 0x92, 0xef, 0xe6, 0xe0,
+	0x60, 0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2,
+	0xe2, 0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17,
+	0x00, 0xe8, 0xff, 0x92, 0xef, 0xe6, 0xe0, 0x60,
+	0x00, 0x83, 0xa2, 0xd4, 0xe4, 0xd2, 0xa2, 0xe2,
+	0xcc, 0xb2, 0x54, 0x06, 0x00, 0x00, 0x17, 0x00,
+	0xe8, 0xff, 0x42, 0x12, 0x46, 0x16, 0x06, 0x00,
+	0x05, 0x00, 0xfa, 0xff, 0x42, 0x12, 0x46, 0x16,
+	0x06, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00, 0x05,
+	0x00, 0xfa, 0xff, 0x00, 0x14, 0x00, 0xeb, 0xff,
+	0x42, 0x12, 0x46, 0x16, 0x06, 0x00, 0x05, 0x00,
+	0xfa, 0xff, 0x00, 0x05, 0x00, 0xfa, 0xff, 0x00,
+	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
+	0x00, 0x00, 0x14, 0x00, 0xeb, 0xff, 0x42, 0x88,
+	0x21, 0xc4, 0x00, 0x00, 0x14, 0x00, 0xeb, 0xff,
+	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x14, 0x00,
+	0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4, 0x00, 0x00,
+	0x14, 0x00, 0xeb, 0xff, 0x42, 0x88, 0x21, 0xc4,
+	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+	0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0xe8, 0xff,
+	0x42, 0x88, 0x21, 0xc4, 0x00, 0x00, 0x00, 0x00,
+	0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
+	0x17, 0x00, 0xe8, 0xff, 0x42, 0x12, 0x46, 0x16,
+	0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08,
+	0x00, 0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa,
+	0x00, 0x00, 0x00, 0x42, 0x12, 0x46, 0x16, 0x06,
+	0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x08, 0x00,
+	0xf7, 0xff, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
+	0x00, 0x00, 0x3d, 0xb1, 0x20, 0x85, 0xfa, 0x00,
+	0x00, 0x00,
+}
diff --git a/src/pkg/net/http/triv.go b/src/pkg/net/http/triv.go
new file mode 100644
index 0000000..994fc0e
--- /dev/null
+++ b/src/pkg/net/http/triv.go
@@ -0,0 +1,149 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"bytes"
+	"expvar"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"strconv"
+)
+
+// hello world, the web server
+var helloRequests = expvar.NewInt("hello-requests")
+
+func HelloServer(w http.ResponseWriter, req *http.Request) {
+	helloRequests.Add(1)
+	io.WriteString(w, "hello, world!\n")
+}
+
+// Simple counter server. POSTing to it will set the value.
+type Counter struct {
+	n int
+}
+
+// This makes Counter satisfy the expvar.Var interface, so we can export
+// it directly.
+func (ctr *Counter) String() string { return fmt.Sprintf("%d", ctr.n) }
+
+func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	switch req.Method {
+	case "GET":
+		ctr.n++
+	case "POST":
+		buf := new(bytes.Buffer)
+		io.Copy(buf, req.Body)
+		body := buf.String()
+		if n, err := strconv.Atoi(body); err != nil {
+			fmt.Fprintf(w, "bad POST: %v\nbody: [%v]\n", err, body)
+		} else {
+			ctr.n = n
+			fmt.Fprint(w, "counter reset\n")
+		}
+	}
+	fmt.Fprintf(w, "counter = %d\n", ctr.n)
+}
+
+// simple flag server
+var booleanflag = flag.Bool("boolean", true, "another flag for testing")
+
+func FlagServer(w http.ResponseWriter, req *http.Request) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	fmt.Fprint(w, "Flags:\n")
+	flag.VisitAll(func(f *flag.Flag) {
+		if f.Value.String() != f.DefValue {
+			fmt.Fprintf(w, "%s = %s [default = %s]\n", f.Name, f.Value.String(), f.DefValue)
+		} else {
+			fmt.Fprintf(w, "%s = %s\n", f.Name, f.Value.String())
+		}
+	})
+}
+
+// simple argument server
+func ArgServer(w http.ResponseWriter, req *http.Request) {
+	for _, s := range os.Args {
+		fmt.Fprint(w, s, " ")
+	}
+}
+
+// a channel (just for the fun of it)
+type Chan chan int
+
+func ChanCreate() Chan {
+	c := make(Chan)
+	go func(c Chan) {
+		for x := 0; ; x++ {
+			c <- x
+		}
+	}(c)
+	return c
+}
+
+func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	io.WriteString(w, fmt.Sprintf("channel send #%d\n", <-ch))
+}
+
+// exec a program, redirecting output
+func DateServer(rw http.ResponseWriter, req *http.Request) {
+	rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	r, w, err := os.Pipe()
+	if err != nil {
+		fmt.Fprintf(rw, "pipe: %s\n", err)
+		return
+	}
+
+	p, err := os.StartProcess("/bin/date", []string{"date"}, &os.ProcAttr{Files: []*os.File{nil, w, w}})
+	defer r.Close()
+	w.Close()
+	if err != nil {
+		fmt.Fprintf(rw, "fork/exec: %s\n", err)
+		return
+	}
+	defer p.Release()
+	io.Copy(rw, r)
+	wait, err := p.Wait(0)
+	if err != nil {
+		fmt.Fprintf(rw, "wait: %s\n", err)
+		return
+	}
+	if !wait.Exited() || wait.ExitStatus() != 0 {
+		fmt.Fprintf(rw, "date: %v\n", wait)
+		return
+	}
+}
+
+func Logger(w http.ResponseWriter, req *http.Request) {
+	log.Print(req.URL.Raw)
+	w.WriteHeader(404)
+	w.Write([]byte("oops"))
+}
+
+var webroot = flag.String("root", "/home/rsc", "web root directory")
+
+func main() {
+	flag.Parse()
+
+	// The counter is published as a variable directly.
+	ctr := new(Counter)
+	http.Handle("/counter", ctr)
+	expvar.Publish("counter", ctr)
+
+	http.Handle("/", http.HandlerFunc(Logger))
+	http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot))))
+	http.Handle("/flags", http.HandlerFunc(FlagServer))
+	http.Handle("/args", http.HandlerFunc(ArgServer))
+	http.Handle("/go/hello", http.HandlerFunc(HelloServer))
+	http.Handle("/chan", ChanCreate())
+	http.Handle("/date", http.HandlerFunc(DateServer))
+	err := http.ListenAndServe(":12345", nil)
+	if err != nil {
+		log.Panicln("ListenAndServe:", err)
+	}
+}
diff --git a/src/pkg/net/interface.go b/src/pkg/net/interface.go
index 2696b7f..5e7b352 100644
--- a/src/pkg/net/interface.go
+++ b/src/pkg/net/interface.go
@@ -8,8 +8,16 @@ package net
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
-	"os"
+)
+
+var (
+	errInvalidInterface         = errors.New("net: invalid interface")
+	errInvalidInterfaceIndex    = errors.New("net: invalid interface index")
+	errInvalidInterfaceName     = errors.New("net: invalid interface name")
+	errNoSuchInterface          = errors.New("net: no such interface")
+	errNoSuchMulticastInterface = errors.New("net: no such multicast interface")
 )
 
 // A HardwareAddr represents a physical hardware address.
@@ -34,7 +42,7 @@ func (a HardwareAddr) String() string {
 //   01-23-45-67-89-ab-cd-ef
 //   0123.4567.89ab
 //   0123.4567.89ab.cdef
-func ParseMAC(s string) (hw HardwareAddr, err os.Error) {
+func ParseMAC(s string) (hw HardwareAddr, err error) {
 	if len(s) < 14 {
 		goto error
 	}
@@ -80,7 +88,7 @@ func ParseMAC(s string) (hw HardwareAddr, err os.Error) {
 	return hw, nil
 
 error:
-	return nil, os.NewError("invalid MAC address: " + s)
+	return nil, errors.New("invalid MAC address: " + s)
 }
 
 // Interface represents a mapping between network interface name
@@ -129,37 +137,37 @@ func (f Flags) String() string {
 }
 
 // Addrs returns interface addresses for a specific interface.
-func (ifi *Interface) Addrs() ([]Addr, os.Error) {
+func (ifi *Interface) Addrs() ([]Addr, error) {
 	if ifi == nil {
-		return nil, os.NewError("net: invalid interface")
+		return nil, errInvalidInterface
 	}
 	return interfaceAddrTable(ifi.Index)
 }
 
 // MulticastAddrs returns multicast, joined group addresses for
 // a specific interface.
-func (ifi *Interface) MulticastAddrs() ([]Addr, os.Error) {
+func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
 	if ifi == nil {
-		return nil, os.NewError("net: invalid interface")
+		return nil, errInvalidInterface
 	}
 	return interfaceMulticastAddrTable(ifi.Index)
 }
 
 // Interfaces returns a list of the systems's network interfaces.
-func Interfaces() ([]Interface, os.Error) {
+func Interfaces() ([]Interface, error) {
 	return interfaceTable(0)
 }
 
 // InterfaceAddrs returns a list of the system's network interface
 // addresses.
-func InterfaceAddrs() ([]Addr, os.Error) {
+func InterfaceAddrs() ([]Addr, error) {
 	return interfaceAddrTable(0)
 }
 
 // InterfaceByIndex returns the interface specified by index.
-func InterfaceByIndex(index int) (*Interface, os.Error) {
+func InterfaceByIndex(index int) (*Interface, error) {
 	if index <= 0 {
-		return nil, os.NewError("net: invalid interface index")
+		return nil, errInvalidInterfaceIndex
 	}
 	ift, err := interfaceTable(index)
 	if err != nil {
@@ -168,13 +176,13 @@ func InterfaceByIndex(index int) (*Interface, os.Error) {
 	for _, ifi := range ift {
 		return &ifi, nil
 	}
-	return nil, os.NewError("net: no such interface")
+	return nil, errNoSuchInterface
 }
 
 // InterfaceByName returns the interface specified by name.
-func InterfaceByName(name string) (*Interface, os.Error) {
+func InterfaceByName(name string) (*Interface, error) {
 	if name == "" {
-		return nil, os.NewError("net: invalid interface name")
+		return nil, errInvalidInterfaceName
 	}
 	ift, err := interfaceTable(0)
 	if err != nil {
@@ -185,5 +193,5 @@ func InterfaceByName(name string) (*Interface, os.Error) {
 			return &ifi, nil
 		}
 	}
-	return nil, os.NewError("net: no such interface")
+	return nil, errNoSuchInterface
 }
diff --git a/src/pkg/net/interface_bsd.go b/src/pkg/net/interface_bsd.go
index 9171827..907f80a 100644
--- a/src/pkg/net/interface_bsd.go
+++ b/src/pkg/net/interface_bsd.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd openbsd
+// +build darwin freebsd netbsd openbsd
 
 // Network interface identification for BSD variants
 
@@ -17,22 +17,17 @@ import (
 // If the ifindex is zero, interfaceTable returns mappings of all
 // network interfaces.  Otheriwse it returns a mapping of a specific
 // interface.
-func interfaceTable(ifindex int) ([]Interface, os.Error) {
-	var (
-		tab  []byte
-		e    int
-		msgs []syscall.RoutingMessage
-		ift  []Interface
-	)
-
-	tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
-	if e != 0 {
-		return nil, os.NewSyscallError("route rib", e)
+func interfaceTable(ifindex int) ([]Interface, error) {
+	var ift []Interface
+
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
+	if err != nil {
+		return nil, os.NewSyscallError("route rib", err)
 	}
 
-	msgs, e = syscall.ParseRoutingMessage(tab)
-	if e != 0 {
-		return nil, os.NewSyscallError("route message", e)
+	msgs, err := syscall.ParseRoutingMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("route message", err)
 	}
 
 	for _, m := range msgs {
@@ -51,12 +46,12 @@ func interfaceTable(ifindex int) ([]Interface, os.Error) {
 	return ift, nil
 }
 
-func newLink(m *syscall.InterfaceMessage) ([]Interface, os.Error) {
+func newLink(m *syscall.InterfaceMessage) ([]Interface, error) {
 	var ift []Interface
 
-	sas, e := syscall.ParseRoutingSockaddr(m)
-	if e != 0 {
-		return nil, os.NewSyscallError("route sockaddr", e)
+	sas, err := syscall.ParseRoutingSockaddr(m)
+	if err != nil {
+		return nil, os.NewSyscallError("route sockaddr", err)
 	}
 
 	for _, s := range sas {
@@ -107,22 +102,17 @@ func linkFlags(rawFlags int32) Flags {
 // If the ifindex is zero, interfaceAddrTable returns addresses
 // for all network interfaces.  Otherwise it returns addresses
 // for a specific interface.
-func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
-	var (
-		tab  []byte
-		e    int
-		msgs []syscall.RoutingMessage
-		ifat []Addr
-	)
-
-	tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
-	if e != 0 {
-		return nil, os.NewSyscallError("route rib", e)
+func interfaceAddrTable(ifindex int) ([]Addr, error) {
+	var ifat []Addr
+
+	tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
+	if err != nil {
+		return nil, os.NewSyscallError("route rib", err)
 	}
 
-	msgs, e = syscall.ParseRoutingMessage(tab)
-	if e != 0 {
-		return nil, os.NewSyscallError("route message", e)
+	msgs, err := syscall.ParseRoutingMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("route message", err)
 	}
 
 	for _, m := range msgs {
@@ -133,7 +123,7 @@ func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
 				if err != nil {
 					return nil, err
 				}
-				ifat = append(ifat, ifa...)
+				ifat = append(ifat, ifa)
 			}
 		}
 	}
@@ -141,33 +131,41 @@ func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
 	return ifat, nil
 }
 
-func newAddr(m *syscall.InterfaceAddrMessage) ([]Addr, os.Error) {
-	var ifat []Addr
+func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) {
+	ifa := &IPNet{}
 
-	sas, e := syscall.ParseRoutingSockaddr(m)
-	if e != 0 {
-		return nil, os.NewSyscallError("route sockaddr", e)
+	sas, err := syscall.ParseRoutingSockaddr(m)
+	if err != nil {
+		return nil, os.NewSyscallError("route sockaddr", err)
 	}
 
-	for _, s := range sas {
-
+	for i, s := range sas {
 		switch v := s.(type) {
 		case *syscall.SockaddrInet4:
-			ifa := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
-			ifat = append(ifat, ifa.toAddr())
+			switch i {
+			case 0:
+				ifa.Mask = IPv4Mask(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
+			case 1:
+				ifa.IP = IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
+			}
 		case *syscall.SockaddrInet6:
-			ifa := &IPAddr{IP: make(IP, IPv6len)}
-			copy(ifa.IP, v.Addr[:])
-			// NOTE: KAME based IPv6 protcol stack usually embeds
-			// the interface index in the interface-local or link-
-			// local address as the kernel-internal form.
-			if ifa.IP.IsLinkLocalUnicast() {
-				// remove embedded scope zone ID
-				ifa.IP[2], ifa.IP[3] = 0, 0
+			switch i {
+			case 0:
+				ifa.Mask = make(IPMask, IPv6len)
+				copy(ifa.Mask, v.Addr[:])
+			case 1:
+				ifa.IP = make(IP, IPv6len)
+				copy(ifa.IP, v.Addr[:])
+				// NOTE: KAME based IPv6 protcol stack usually embeds
+				// the interface index in the interface-local or link-
+				// local address as the kernel-internal form.
+				if ifa.IP.IsLinkLocalUnicast() {
+					// remove embedded scope zone ID
+					ifa.IP[2], ifa.IP[3] = 0, 0
+				}
 			}
-			ifat = append(ifat, ifa.toAddr())
 		}
 	}
 
-	return ifat, nil
+	return ifa, nil
 }
diff --git a/src/pkg/net/interface_darwin.go b/src/pkg/net/interface_darwin.go
index a7b68ad..2da447a 100644
--- a/src/pkg/net/interface_darwin.go
+++ b/src/pkg/net/interface_darwin.go
@@ -14,21 +14,21 @@ import (
 // If the ifindex is zero, interfaceMulticastAddrTable returns
 // addresses for all network interfaces.  Otherwise it returns
 // addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
 	var (
 		tab   []byte
-		e     int
+		e     error
 		msgs  []syscall.RoutingMessage
 		ifmat []Addr
 	)
 
 	tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifindex)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("route rib", e)
 	}
 
 	msgs, e = syscall.ParseRoutingMessage(tab)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("route message", e)
 	}
 
@@ -48,11 +48,11 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
 	return ifmat, nil
 }
 
-func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, os.Error) {
+func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
 	var ifmat []Addr
 
 	sas, e := syscall.ParseRoutingSockaddr(m)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("route sockaddr", e)
 	}
 
diff --git a/src/pkg/net/interface_freebsd.go b/src/pkg/net/interface_freebsd.go
index 20f506b..a12877e 100644
--- a/src/pkg/net/interface_freebsd.go
+++ b/src/pkg/net/interface_freebsd.go
@@ -14,21 +14,21 @@ import (
 // If the ifindex is zero, interfaceMulticastAddrTable returns
 // addresses for all network interfaces.  Otherwise it returns
 // addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
 	var (
 		tab   []byte
-		e     int
+		e     error
 		msgs  []syscall.RoutingMessage
 		ifmat []Addr
 	)
 
 	tab, e = syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifindex)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("route rib", e)
 	}
 
 	msgs, e = syscall.ParseRoutingMessage(tab)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("route message", e)
 	}
 
@@ -48,11 +48,11 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
 	return ifmat, nil
 }
 
-func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, os.Error) {
+func newMulticastAddr(m *syscall.InterfaceMulticastAddrMessage) ([]Addr, error) {
 	var ifmat []Addr
 
 	sas, e := syscall.ParseRoutingSockaddr(m)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("route sockaddr", e)
 	}
 
diff --git a/src/pkg/net/interface_linux.go b/src/pkg/net/interface_linux.go
index 3d2a0bb..c0887c5 100644
--- a/src/pkg/net/interface_linux.go
+++ b/src/pkg/net/interface_linux.go
@@ -16,22 +16,17 @@ import (
 // If the ifindex is zero, interfaceTable returns mappings of all
 // network interfaces.  Otheriwse it returns a mapping of a specific
 // interface.
-func interfaceTable(ifindex int) ([]Interface, os.Error) {
-	var (
-		ift  []Interface
-		tab  []byte
-		msgs []syscall.NetlinkMessage
-		e    int
-	)
+func interfaceTable(ifindex int) ([]Interface, error) {
+	var ift []Interface
 
-	tab, e = syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
-	if e != 0 {
-		return nil, os.NewSyscallError("netlink rib", e)
+	tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
+	if err != nil {
+		return nil, os.NewSyscallError("netlink rib", err)
 	}
 
-	msgs, e = syscall.ParseNetlinkMessage(tab)
-	if e != 0 {
-		return nil, os.NewSyscallError("netlink message", e)
+	msgs, err := syscall.ParseNetlinkMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("netlink message", err)
 	}
 
 	for _, m := range msgs {
@@ -41,11 +36,11 @@ func interfaceTable(ifindex int) ([]Interface, os.Error) {
 		case syscall.RTM_NEWLINK:
 			ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
 			if ifindex == 0 || ifindex == int(ifim.Index) {
-				attrs, e := syscall.ParseNetlinkRouteAttr(&m)
-				if e != 0 {
-					return nil, os.NewSyscallError("netlink routeattr", e)
+				attrs, err := syscall.ParseNetlinkRouteAttr(&m)
+				if err != nil {
+					return nil, os.NewSyscallError("netlink routeattr", err)
 				}
-				ifi := newLink(attrs, ifim)
+				ifi := newLink(ifim, attrs)
 				ift = append(ift, ifi)
 			}
 		}
@@ -55,7 +50,7 @@ done:
 	return ift, nil
 }
 
-func newLink(attrs []syscall.NetlinkRouteAttr, ifim *syscall.IfInfomsg) Interface {
+func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) Interface {
 	ifi := Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)}
 	for _, a := range attrs {
 		switch a.Attr.Type {
@@ -101,47 +96,26 @@ func linkFlags(rawFlags uint32) Flags {
 // If the ifindex is zero, interfaceAddrTable returns addresses
 // for all network interfaces.  Otherwise it returns addresses
 // for a specific interface.
-func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
-	var (
-		tab   []byte
-		e     int
-		err   os.Error
-		ifat4 []Addr
-		ifat6 []Addr
-		msgs4 []syscall.NetlinkMessage
-		msgs6 []syscall.NetlinkMessage
-	)
-
-	tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET)
-	if e != 0 {
-		return nil, os.NewSyscallError("netlink rib", e)
-	}
-	msgs4, e = syscall.ParseNetlinkMessage(tab)
-	if e != 0 {
-		return nil, os.NewSyscallError("netlink message", e)
-	}
-	ifat4, err = addrTable(msgs4, ifindex)
+func interfaceAddrTable(ifindex int) ([]Addr, error) {
+	tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
 	if err != nil {
-		return nil, err
+		return nil, os.NewSyscallError("netlink rib", err)
 	}
 
-	tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET6)
-	if e != 0 {
-		return nil, os.NewSyscallError("netlink rib", e)
-	}
-	msgs6, e = syscall.ParseNetlinkMessage(tab)
-	if e != 0 {
-		return nil, os.NewSyscallError("netlink message", e)
+	msgs, err := syscall.ParseNetlinkMessage(tab)
+	if err != nil {
+		return nil, os.NewSyscallError("netlink message", err)
 	}
-	ifat6, err = addrTable(msgs6, ifindex)
+
+	ifat, err := addrTable(msgs, ifindex)
 	if err != nil {
 		return nil, err
 	}
 
-	return append(ifat4, ifat6...), nil
+	return ifat, nil
 }
 
-func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, os.Error) {
+func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, error) {
 	var ifat []Addr
 
 	for _, m := range msgs {
@@ -151,11 +125,11 @@ func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, os.Error) {
 		case syscall.RTM_NEWADDR:
 			ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
 			if ifindex == 0 || ifindex == int(ifam.Index) {
-				attrs, e := syscall.ParseNetlinkRouteAttr(&m)
-				if e != 0 {
-					return nil, os.NewSyscallError("netlink routeattr", e)
+				attrs, err := syscall.ParseNetlinkRouteAttr(&m)
+				if err != nil {
+					return nil, os.NewSyscallError("netlink routeattr", err)
 				}
-				ifat = append(ifat, newAddr(attrs, int(ifam.Family))...)
+				ifat = append(ifat, newAddr(attrs, int(ifam.Family), int(ifam.Prefixlen)))
 			}
 		}
 	}
@@ -164,34 +138,32 @@ done:
 	return ifat, nil
 }
 
-func newAddr(attrs []syscall.NetlinkRouteAttr, family int) []Addr {
-	var ifat []Addr
-
+func newAddr(attrs []syscall.NetlinkRouteAttr, family, pfxlen int) Addr {
+	ifa := &IPNet{}
 	for _, a := range attrs {
 		switch a.Attr.Type {
 		case syscall.IFA_ADDRESS:
 			switch family {
 			case syscall.AF_INET:
-				ifa := &IPAddr{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3])}
-				ifat = append(ifat, ifa.toAddr())
+				ifa.IP = IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3])
+				ifa.Mask = CIDRMask(pfxlen, 8*IPv4len)
 			case syscall.AF_INET6:
-				ifa := &IPAddr{IP: make(IP, IPv6len)}
+				ifa.IP = make(IP, IPv6len)
 				copy(ifa.IP, a.Value[:])
-				ifat = append(ifat, ifa.toAddr())
+				ifa.Mask = CIDRMask(pfxlen, 8*IPv6len)
 			}
 		}
 	}
-
-	return ifat
+	return ifa
 }
 
 // If the ifindex is zero, interfaceMulticastAddrTable returns
 // addresses for all network interfaces.  Otherwise it returns
 // addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
 	var (
+		err error
 		ifi *Interface
-		err os.Error
 	)
 
 	if ifindex > 0 {
diff --git a/src/pkg/net/interface_netbsd.go b/src/pkg/net/interface_netbsd.go
new file mode 100644
index 0000000..4150e9a
--- /dev/null
+++ b/src/pkg/net/interface_netbsd.go
@@ -0,0 +1,14 @@
+// Copyright 2011 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.
+
+// Network interface identification for NetBSD
+
+package net
+
+// If the ifindex is zero, interfaceMulticastAddrTable returns
+// addresses for all network interfaces.  Otherwise it returns
+// addresses for a specific interface.
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
+	return nil, nil
+}
diff --git a/src/pkg/net/interface_openbsd.go b/src/pkg/net/interface_openbsd.go
index f181493..d8adb46 100644
--- a/src/pkg/net/interface_openbsd.go
+++ b/src/pkg/net/interface_openbsd.go
@@ -6,11 +6,9 @@
 
 package net
 
-import "os"
-
 // If the ifindex is zero, interfaceMulticastAddrTable returns
 // addresses for all network interfaces.  Otherwise it returns
 // addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
 	return nil, nil
 }
diff --git a/src/pkg/net/interface_stub.go b/src/pkg/net/interface_stub.go
index 282b38b..4876b3a 100644
--- a/src/pkg/net/interface_stub.go
+++ b/src/pkg/net/interface_stub.go
@@ -8,25 +8,23 @@
 
 package net
 
-import "os"
-
 // If the ifindex is zero, interfaceTable returns mappings of all
 // network interfaces.  Otheriwse it returns a mapping of a specific
 // interface.
-func interfaceTable(ifindex int) ([]Interface, os.Error) {
+func interfaceTable(ifindex int) ([]Interface, error) {
 	return nil, nil
 }
 
 // If the ifindex is zero, interfaceAddrTable returns addresses
 // for all network interfaces.  Otherwise it returns addresses
 // for a specific interface.
-func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
+func interfaceAddrTable(ifindex int) ([]Addr, error) {
 	return nil, nil
 }
 
 // If the ifindex is zero, interfaceMulticastAddrTable returns
 // addresses for all network interfaces.  Otherwise it returns
 // addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
 	return nil, nil
 }
diff --git a/src/pkg/net/interface_test.go b/src/pkg/net/interface_test.go
index c918f24..4ce01dc 100644
--- a/src/pkg/net/interface_test.go
+++ b/src/pkg/net/interface_test.go
@@ -6,7 +6,6 @@ package net
 
 import (
 	"bytes"
-	"os"
 	"reflect"
 	"strings"
 	"testing"
@@ -25,7 +24,7 @@ func sameInterface(i, j *Interface) bool {
 func TestInterfaces(t *testing.T) {
 	ift, err := Interfaces()
 	if err != nil {
-		t.Fatalf("Interfaces() failed: %v", err)
+		t.Fatalf("Interfaces failed: %v", err)
 	}
 	t.Logf("table: len/cap = %v/%v\n", len(ift), cap(ift))
 
@@ -44,34 +43,57 @@ func TestInterfaces(t *testing.T) {
 		if !sameInterface(ifxn, &ifi) {
 			t.Fatalf("InterfaceByName(%#q) = %v, want %v", ifi.Name, *ifxn, ifi)
 		}
-		ifat, err := ifi.Addrs()
-		if err != nil {
-			t.Fatalf("Interface.Addrs() failed: %v", err)
-		}
-		ifmat, err := ifi.MulticastAddrs()
-		if err != nil {
-			t.Fatalf("Interface.MulticastAddrs() failed: %v", err)
-		}
 		t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
-		for _, ifa := range ifat {
-			t.Logf("\tinterface address %q\n", ifa.String())
-		}
-		for _, ifma := range ifmat {
-			t.Logf("\tjoined group address %q\n", ifma.String())
-		}
 		t.Logf("\thardware address %q", ifi.HardwareAddr.String())
+		testInterfaceAddrs(t, &ifi)
+		testInterfaceMulticastAddrs(t, &ifi)
 	}
 }
 
 func TestInterfaceAddrs(t *testing.T) {
 	ifat, err := InterfaceAddrs()
 	if err != nil {
-		t.Fatalf("InterfaceAddrs() failed: %v", err)
+		t.Fatalf("InterfaceAddrs failed: %v", err)
 	}
 	t.Logf("table: len/cap = %v/%v\n", len(ifat), cap(ifat))
+	testAddrs(t, ifat)
+}
+
+func testInterfaceAddrs(t *testing.T, ifi *Interface) {
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		t.Fatalf("Interface.Addrs failed: %v", err)
+	}
+	testAddrs(t, ifat)
+}
+
+func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) {
+	ifmat, err := ifi.MulticastAddrs()
+	if err != nil {
+		t.Fatalf("Interface.MulticastAddrs failed: %v", err)
+	}
+	testMulticastAddrs(t, ifmat)
+}
 
+func testAddrs(t *testing.T, ifat []Addr) {
 	for _, ifa := range ifat {
-		t.Logf("interface address %q\n", ifa.String())
+		switch ifa.(type) {
+		case *IPAddr, *IPNet:
+			t.Logf("\tinterface address %q\n", ifa.String())
+		default:
+			t.Errorf("\tunexpected type: %T", ifa)
+		}
+	}
+}
+
+func testMulticastAddrs(t *testing.T, ifmat []Addr) {
+	for _, ifma := range ifmat {
+		switch ifma.(type) {
+		case *IPAddr:
+			t.Logf("\tjoined group address %q\n", ifma.String())
+		default:
+			t.Errorf("\tunexpected type: %T", ifma)
+		}
 	}
 }
 
@@ -101,11 +123,11 @@ var mactests = []struct {
 	{"0123.4567.89AB.CDEF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
 }
 
-func match(err os.Error, s string) bool {
+func match(err error, s string) bool {
 	if s == "" {
 		return err == nil
 	}
-	return err != nil && strings.Contains(err.String(), s)
+	return err != nil && strings.Contains(err.Error(), s)
 }
 
 func TestParseMAC(t *testing.T) {
diff --git a/src/pkg/net/interface_windows.go b/src/pkg/net/interface_windows.go
index 7f5169c..add3dd3 100644
--- a/src/pkg/net/interface_windows.go
+++ b/src/pkg/net/interface_windows.go
@@ -21,7 +21,7 @@ func bytePtrToString(p *uint8) string {
 	return string(a[:i])
 }
 
-func getAdapterList() (*syscall.IpAdapterInfo, os.Error) {
+func getAdapterList() (*syscall.IpAdapterInfo, error) {
 	b := make([]byte, 1000)
 	l := uint32(len(b))
 	a := (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
@@ -31,15 +31,15 @@ func getAdapterList() (*syscall.IpAdapterInfo, os.Error) {
 		a = (*syscall.IpAdapterInfo)(unsafe.Pointer(&b[0]))
 		e = syscall.GetAdaptersInfo(a, &l)
 	}
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("GetAdaptersInfo", e)
 	}
 	return a, nil
 }
 
-func getInterfaceList() ([]syscall.InterfaceInfo, os.Error) {
+func getInterfaceList() ([]syscall.InterfaceInfo, error) {
 	s, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("Socket", e)
 	}
 	defer syscall.Closesocket(s)
@@ -48,7 +48,7 @@ func getInterfaceList() ([]syscall.InterfaceInfo, os.Error) {
 	ret := uint32(0)
 	size := uint32(unsafe.Sizeof(ii))
 	e = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("WSAIoctl", e)
 	}
 	c := ret / uint32(unsafe.Sizeof(ii[0]))
@@ -58,7 +58,7 @@ func getInterfaceList() ([]syscall.InterfaceInfo, os.Error) {
 // If the ifindex is zero, interfaceTable returns mappings of all
 // network interfaces.  Otheriwse it returns a mapping of a specific
 // interface.
-func interfaceTable(ifindex int) ([]Interface, os.Error) {
+func interfaceTable(ifindex int) ([]Interface, error) {
 	ai, e := getAdapterList()
 	if e != nil {
 		return nil, e
@@ -77,7 +77,7 @@ func interfaceTable(ifindex int) ([]Interface, os.Error) {
 
 			row := syscall.MibIfRow{Index: index}
 			e := syscall.GetIfEntry(&row)
-			if e != 0 {
+			if e != nil {
 				return nil, os.NewSyscallError("GetIfEntry", e)
 			}
 
@@ -129,7 +129,7 @@ func interfaceTable(ifindex int) ([]Interface, os.Error) {
 // If the ifindex is zero, interfaceAddrTable returns addresses
 // for all network interfaces.  Otherwise it returns addresses
 // for a specific interface.
-func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
+func interfaceAddrTable(ifindex int) ([]Addr, error) {
 	ai, e := getAdapterList()
 	if e != nil {
 		return nil, e
@@ -153,6 +153,6 @@ func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
 // If the ifindex is zero, interfaceMulticastAddrTable returns
 // addresses for all network interfaces.  Otherwise it returns
 // addresses for a specific interface.
-func interfaceMulticastAddrTable(ifindex int) ([]Addr, os.Error) {
+func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
 	return nil, nil
 }
diff --git a/src/pkg/net/ip.go b/src/pkg/net/ip.go
index 61dc3be..979d7ac 100644
--- a/src/pkg/net/ip.go
+++ b/src/pkg/net/ip.go
@@ -12,8 +12,6 @@
 
 package net
 
-import "os"
-
 // IP address lengths (bytes).
 const (
 	IPv4len = 4
@@ -452,6 +450,9 @@ func (n *IPNet) String() string {
 	return nn.String() + "/" + itod(uint(l))
 }
 
+// Network returns the address's network name, "ip+net".
+func (n *IPNet) Network() string { return "ip+net" }
+
 // Parse IPv4 address (d.d.d.d).
 func parseIPv4(s string) IP {
 	var p [IPv4len]byte
@@ -594,7 +595,7 @@ type ParseError struct {
 	Text string
 }
 
-func (e *ParseError) String() string {
+func (e *ParseError) Error() string {
 	return "invalid " + e.Type + ": " + e.Text
 }
 
@@ -627,7 +628,7 @@ func ParseIP(s string) IP {
 // It returns the IP address and the network implied by the IP
 // and mask.  For example, ParseCIDR("192.168.100.1/16") returns
 // the IP address 192.168.100.1 and the network 192.168.0.0/16.
-func ParseCIDR(s string) (IP, *IPNet, os.Error) {
+func ParseCIDR(s string) (IP, *IPNet, error) {
 	i := byteIndex(s, '/')
 	if i < 0 {
 		return nil, nil, &ParseError{"CIDR address", s}
diff --git a/src/pkg/net/ip_test.go b/src/pkg/net/ip_test.go
index 07e627a..df647ef 100644
--- a/src/pkg/net/ip_test.go
+++ b/src/pkg/net/ip_test.go
@@ -7,9 +7,8 @@ package net
 import (
 	"bytes"
 	"reflect"
-	"testing"
-	"os"
 	"runtime"
+	"testing"
 )
 
 func isEqual(a, b []byte) bool {
@@ -113,7 +112,7 @@ var parsecidrtests = []struct {
 	in  string
 	ip  IP
 	net *IPNet
-	err os.Error
+	err error
 }{
 	{"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 255)}, nil},
 	{"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IPv4(0, 0, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
diff --git a/src/pkg/net/ipraw_test.go b/src/pkg/net/ipraw_test.go
index 6894ce6..f9401c1 100644
--- a/src/pkg/net/ipraw_test.go
+++ b/src/pkg/net/ipraw_test.go
@@ -2,119 +2,191 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// TODO(cw): ListenPacket test, Read() test, ipv6 test &
-// Dial()/Listen() level tests
-
 package net
 
 import (
 	"bytes"
-	"flag"
 	"os"
 	"testing"
+	"time"
 )
 
-const ICMP_ECHO_REQUEST = 8
-const ICMP_ECHO_REPLY = 0
-
-// returns a suitable 'ping request' packet, with id & seq and a
-// payload length of pktlen
-func makePingRequest(id, seq, pktlen int, filler []byte) []byte {
-	p := make([]byte, pktlen)
-	copy(p[8:], bytes.Repeat(filler, (pktlen-8)/len(filler)+1))
-
-	p[0] = ICMP_ECHO_REQUEST // type
-	p[1] = 0                 // code
-	p[2] = 0                 // cksum
-	p[3] = 0                 // cksum
-	p[4] = uint8(id >> 8)    // id
-	p[5] = uint8(id & 0xff)  // id
-	p[6] = uint8(seq >> 8)   // sequence
-	p[7] = uint8(seq & 0xff) // sequence
-
-	// calculate icmp checksum
-	cklen := len(p)
-	s := uint32(0)
-	for i := 0; i < (cklen - 1); i += 2 {
-		s += uint32(p[i+1])<<8 | uint32(p[i])
-	}
-	if cklen&1 == 1 {
-		s += uint32(p[cklen-1])
-	}
-	s = (s >> 16) + (s & 0xffff)
-	s = s + (s >> 16)
-
-	// place checksum back in header; using ^= avoids the
-	// assumption the checksum bytes are zero
-	p[2] ^= uint8(^s & 0xff)
-	p[3] ^= uint8(^s >> 8)
-
-	return p
-}
-
-func parsePingReply(p []byte) (id, seq int) {
-	id = int(p[4])<<8 | int(p[5])
-	seq = int(p[6])<<8 | int(p[7])
-	return
+var icmpTests = []struct {
+	net   string
+	laddr string
+	raddr string
+	ipv6  bool
+}{
+	{"ip4:icmp", "", "127.0.0.1", false},
+	{"ip6:icmp", "", "::1", true},
 }
 
-var srchost = flag.String("srchost", "", "Source of the ICMP ECHO request")
-// 127.0.0.1 because this is an IPv4-specific test.
-var dsthost = flag.String("dsthost", "127.0.0.1", "Destination for the ICMP ECHO request")
-
-// test (raw) IP socket using ICMP
 func TestICMP(t *testing.T) {
 	if os.Getuid() != 0 {
 		t.Logf("test disabled; must be root")
 		return
 	}
 
-	var (
-		laddr *IPAddr
-		err   os.Error
-	)
-	if *srchost != "" {
-		laddr, err = ResolveIPAddr("ip4", *srchost)
-		if err != nil {
-			t.Fatalf(`net.ResolveIPAddr("ip4", %v") = %v, %v`, *srchost, laddr, err)
+	seqnum := 61455
+	for _, tt := range icmpTests {
+		if tt.ipv6 && !supportsIPv6 {
+			continue
 		}
+		id := os.Getpid() & 0xffff
+		seqnum++
+		echo := newICMPEchoRequest(tt.ipv6, id, seqnum, 128, []byte("Go Go Gadget Ping!!!"))
+		exchangeICMPEcho(t, tt.net, tt.laddr, tt.raddr, tt.ipv6, echo)
 	}
+}
 
-	raddr, err := ResolveIPAddr("ip4", *dsthost)
+func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, ipv6 bool, echo []byte) {
+	c, err := ListenPacket(net, laddr)
 	if err != nil {
-		t.Fatalf(`net.ResolveIPAddr("ip4", %v") = %v, %v`, *dsthost, raddr, err)
+		t.Errorf("ListenPacket(%#q, %#q) failed: %v", net, laddr, err)
+		return
 	}
+	c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	defer c.Close()
 
-	c, err := ListenIP("ip4:icmp", laddr)
+	ra, err := ResolveIPAddr(net, raddr)
 	if err != nil {
-		t.Fatalf(`net.ListenIP("ip4:icmp", %v) = %v, %v`, *srchost, c, err)
+		t.Errorf("ResolveIPAddr(%#q, %#q) failed: %v", net, raddr, err)
+		return
 	}
 
-	sendid := os.Getpid() & 0xffff
-	const sendseq = 61455
-	const pingpktlen = 128
-	sendpkt := makePingRequest(sendid, sendseq, pingpktlen, []byte("Go Go Gadget Ping!!!"))
+	waitForReady := make(chan bool)
+	go icmpEchoTransponder(t, net, raddr, ipv6, waitForReady)
+	<-waitForReady
 
-	n, err := c.WriteToIP(sendpkt, raddr)
-	if err != nil || n != pingpktlen {
-		t.Fatalf(`net.WriteToIP(..., %v) = %v, %v`, raddr, n, err)
+	_, err = c.WriteTo(echo, ra)
+	if err != nil {
+		t.Errorf("WriteTo failed: %v", err)
+		return
 	}
 
-	c.SetTimeout(100e6)
-	resp := make([]byte, 1024)
+	reply := make([]byte, 256)
 	for {
-		n, from, err := c.ReadFrom(resp)
+		_, _, err := c.ReadFrom(reply)
 		if err != nil {
-			t.Fatalf(`ReadFrom(...) = %v, %v, %v`, n, from, err)
+			t.Errorf("ReadFrom failed: %v", err)
+			return
 		}
-		if resp[0] != ICMP_ECHO_REPLY {
+		if !ipv6 && reply[0] != ICMP4_ECHO_REPLY {
 			continue
 		}
-		rcvid, rcvseq := parsePingReply(resp)
-		if rcvid != sendid || rcvseq != sendseq {
-			t.Fatalf(`Ping reply saw id,seq=0x%x,0x%x (expected 0x%x, 0x%x)`, rcvid, rcvseq, sendid, sendseq)
+		if ipv6 && reply[0] != ICMP6_ECHO_REPLY {
+			continue
+		}
+		xid, xseqnum := parseICMPEchoReply(echo)
+		rid, rseqnum := parseICMPEchoReply(reply)
+		if rid != xid || rseqnum != xseqnum {
+			t.Errorf("ID = %v, Seqnum = %v, want ID = %v, Seqnum = %v", rid, rseqnum, xid, xseqnum)
+			return
 		}
+		break
+	}
+}
+
+func icmpEchoTransponder(t *testing.T, net, raddr string, ipv6 bool, waitForReady chan bool) {
+	c, err := Dial(net, raddr)
+	if err != nil {
+		waitForReady <- true
+		t.Errorf("Dial(%#q, %#q) failed: %v", net, raddr, err)
 		return
 	}
-	t.Fatalf("saw no ping return")
+	c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	defer c.Close()
+	waitForReady <- true
+
+	echo := make([]byte, 256)
+	var nr int
+	for {
+		nr, err = c.Read(echo)
+		if err != nil {
+			t.Errorf("Read failed: %v", err)
+			return
+		}
+		if !ipv6 && echo[0] != ICMP4_ECHO_REQUEST {
+			continue
+		}
+		if ipv6 && echo[0] != ICMP6_ECHO_REQUEST {
+			continue
+		}
+		break
+	}
+
+	if !ipv6 {
+		echo[0] = ICMP4_ECHO_REPLY
+	} else {
+		echo[0] = ICMP6_ECHO_REPLY
+	}
+
+	_, err = c.Write(echo[:nr])
+	if err != nil {
+		t.Errorf("Write failed: %v", err)
+		return
+	}
+}
+
+const (
+	ICMP4_ECHO_REQUEST = 8
+	ICMP4_ECHO_REPLY   = 0
+	ICMP6_ECHO_REQUEST = 128
+	ICMP6_ECHO_REPLY   = 129
+)
+
+func newICMPEchoRequest(ipv6 bool, id, seqnum, msglen int, filler []byte) []byte {
+	if !ipv6 {
+		return newICMPv4EchoRequest(id, seqnum, msglen, filler)
+	}
+	return newICMPv6EchoRequest(id, seqnum, msglen, filler)
+}
+
+func newICMPv4EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
+	b := newICMPInfoMessage(id, seqnum, msglen, filler)
+	b[0] = ICMP4_ECHO_REQUEST
+
+	// calculate ICMP checksum
+	cklen := len(b)
+	s := uint32(0)
+	for i := 0; i < cklen-1; i += 2 {
+		s += uint32(b[i+1])<<8 | uint32(b[i])
+	}
+	if cklen&1 == 1 {
+		s += uint32(b[cklen-1])
+	}
+	s = (s >> 16) + (s & 0xffff)
+	s = s + (s >> 16)
+	// place checksum back in header; using ^= avoids the
+	// assumption the checksum bytes are zero
+	b[2] ^= uint8(^s & 0xff)
+	b[3] ^= uint8(^s >> 8)
+
+	return b
+}
+
+func newICMPv6EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
+	b := newICMPInfoMessage(id, seqnum, msglen, filler)
+	b[0] = ICMP6_ECHO_REQUEST
+	return b
+}
+
+func newICMPInfoMessage(id, seqnum, msglen int, filler []byte) []byte {
+	b := make([]byte, msglen)
+	copy(b[8:], bytes.Repeat(filler, (msglen-8)/len(filler)+1))
+	b[0] = 0                    // type
+	b[1] = 0                    // code
+	b[2] = 0                    // checksum
+	b[3] = 0                    // checksum
+	b[4] = uint8(id >> 8)       // identifier
+	b[5] = uint8(id & 0xff)     // identifier
+	b[6] = uint8(seqnum >> 8)   // sequence number
+	b[7] = uint8(seqnum & 0xff) // sequence number
+	return b
+}
+
+func parseICMPEchoReply(b []byte) (id, seqnum int) {
+	id = int(b[4])<<8 | int(b[5])
+	seqnum = int(b[6])<<8 | int(b[7])
+	return
 }
diff --git a/src/pkg/net/iprawsock.go b/src/pkg/net/iprawsock.go
index 662b9f5..b23213e 100644
--- a/src/pkg/net/iprawsock.go
+++ b/src/pkg/net/iprawsock.go
@@ -6,10 +6,6 @@
 
 package net
 
-import (
-	"os"
-)
-
 // IPAddr represents the address of a IP end point.
 type IPAddr struct {
 	IP IP
@@ -29,7 +25,7 @@ func (a *IPAddr) String() string {
 // names to numeric addresses on the network net, which must be
 // "ip", "ip4" or "ip6".  A literal IPv6 host address must be
 // enclosed in square brackets, as in "[::]".
-func ResolveIPAddr(net, addr string) (*IPAddr, os.Error) {
+func ResolveIPAddr(net, addr string) (*IPAddr, error) {
 	ip, err := hostToIP(net, addr)
 	if err != nil {
 		return nil, err
@@ -38,7 +34,7 @@ func ResolveIPAddr(net, addr string) (*IPAddr, os.Error) {
 }
 
 // Convert "host" into IP address.
-func hostToIP(net, host string) (ip IP, err os.Error) {
+func hostToIP(net, host string) (ip IP, err error) {
 	var addr IP
 	// Try as an IP address.
 	addr = ParseIP(host)
diff --git a/src/pkg/net/iprawsock_plan9.go b/src/pkg/net/iprawsock_plan9.go
index 808e179..859153c 100644
--- a/src/pkg/net/iprawsock_plan9.go
+++ b/src/pkg/net/iprawsock_plan9.go
@@ -8,26 +8,42 @@ package net
 
 import (
 	"os"
+	"time"
 )
 
 // IPConn is the implementation of the Conn and PacketConn
 // interfaces for IP network connections.
 type IPConn bool
 
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *IPConn) SetDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *IPConn) SetReadDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *IPConn) SetWriteDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
 // Implementation of the Conn interface - see Conn for documentation.
 
-// Read implements the net.Conn Read method.
-func (c *IPConn) Read(b []byte) (n int, err os.Error) {
+// Read implements the Conn Read method.
+func (c *IPConn) Read(b []byte) (int, error) {
 	return 0, os.EPLAN9
 }
 
-// Write implements the net.Conn Write method.
-func (c *IPConn) Write(b []byte) (n int, err os.Error) {
+// Write implements the Conn Write method.
+func (c *IPConn) Write(b []byte) (int, error) {
 	return 0, os.EPLAN9
 }
 
 // Close closes the IP connection.
-func (c *IPConn) Close() os.Error {
+func (c *IPConn) Close() error {
 	return os.EPLAN9
 }
 
@@ -41,52 +57,42 @@ func (c *IPConn) RemoteAddr() Addr {
 	return nil
 }
 
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *IPConn) SetTimeout(nsec int64) os.Error {
-	return os.EPLAN9
-}
-
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *IPConn) SetReadTimeout(nsec int64) os.Error {
-	return os.EPLAN9
-}
+// IP-specific methods.
 
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *IPConn) SetWriteTimeout(nsec int64) os.Error {
-	return os.EPLAN9
+// ReadFromIP reads a IP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
+	return 0, nil, os.EPLAN9
 }
 
-// IP-specific methods.
-
-// ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
-	err = os.EPLAN9
-	return
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
+	return 0, nil, os.EPLAN9
 }
 
 // WriteToIP writes a IP packet to addr via c, copying the payload from b.
 //
 // WriteToIP can be made to time out and return
 // an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
 // On packet-oriented connections, write timeouts are rare.
-func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err os.Error) {
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
 	return 0, os.EPLAN9
 }
 
-// WriteTo implements the net.PacketConn WriteTo method.
-func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
 	return 0, os.EPLAN9
 }
 
-func splitNetProto(netProto string) (net string, proto int, err os.Error) {
-	err = os.EPLAN9
-	return
-}
-
-// DialIP connects to the remote address raddr on the network net,
-// which must be "ip", "ip4", or "ip6".
-func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) {
+// DialIP connects to the remote address raddr on the network protocol netProto,
+// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
 	return nil, os.EPLAN9
 }
 
@@ -94,6 +100,6 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) {
 // local address laddr.  The returned connection c's ReadFrom
 // and WriteTo methods can be used to receive and send IP
 // packets with per-packet addressing.
-func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err os.Error) {
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
 	return nil, os.EPLAN9
 }
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go
index 35aceb2..c34ffeb 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/pkg/net/iprawsock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 // (Raw) IP sockets
 
@@ -10,12 +10,10 @@ package net
 
 import (
 	"os"
-	"sync"
 	"syscall"
+	"time"
 )
 
-var onceReadProtocols sync.Once
-
 func sockaddrToIP(sa syscall.Sockaddr) Addr {
 	switch sa := sa.(type) {
 	case *syscall.SockaddrInet4:
@@ -36,7 +34,7 @@ func (a *IPAddr) family() int {
 	return syscall.AF_INET6
 }
 
-func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) {
+func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
 	return ipToSockaddr(family, a.IP, 0)
 }
 
@@ -59,14 +57,14 @@ func (c *IPConn) ok() bool { return c != nil && c.fd != nil }
 
 // Implementation of the Conn interface - see Conn for documentation.
 
-// Read implements the net.Conn Read method.
-func (c *IPConn) Read(b []byte) (n int, err os.Error) {
-	n, _, err = c.ReadFrom(b)
-	return
+// Read implements the Conn Read method.
+func (c *IPConn) Read(b []byte) (int, error) {
+	n, _, err := c.ReadFrom(b)
+	return n, err
 }
 
-// Write implements the net.Conn Write method.
-func (c *IPConn) Write(b []byte) (n int, err os.Error) {
+// Write implements the Conn Write method.
+func (c *IPConn) Write(b []byte) (int, error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -74,7 +72,7 @@ func (c *IPConn) Write(b []byte) (n int, err os.Error) {
 }
 
 // Close closes the IP connection.
-func (c *IPConn) Close() os.Error {
+func (c *IPConn) Close() error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -99,33 +97,33 @@ func (c *IPConn) RemoteAddr() Addr {
 	return c.fd.raddr
 }
 
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *IPConn) SetTimeout(nsec int64) os.Error {
+// SetDeadline implements the Conn SetDeadline method.
+func (c *IPConn) SetDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setTimeout(c.fd, nsec)
+	return setDeadline(c.fd, t)
 }
 
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *IPConn) SetReadTimeout(nsec int64) os.Error {
+// SetReadDeadline implements the Conn SetReadDeadline method.
+func (c *IPConn) SetReadDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setReadTimeout(c.fd, nsec)
+	return setReadDeadline(c.fd, t)
 }
 
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *IPConn) SetWriteTimeout(nsec int64) os.Error {
+// SetWriteDeadline implements the Conn SetWriteDeadline method.
+func (c *IPConn) SetWriteDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setWriteTimeout(c.fd, nsec)
+	return setWriteDeadline(c.fd, t)
 }
 
 // SetReadBuffer sets the size of the operating system's
 // receive buffer associated with the connection.
-func (c *IPConn) SetReadBuffer(bytes int) os.Error {
+func (c *IPConn) SetReadBuffer(bytes int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -134,7 +132,7 @@ func (c *IPConn) SetReadBuffer(bytes int) os.Error {
 
 // SetWriteBuffer sets the size of the operating system's
 // transmit buffer associated with the connection.
-func (c *IPConn) SetWriteBuffer(bytes int) os.Error {
+func (c *IPConn) SetWriteBuffer(bytes int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -148,14 +146,15 @@ func (c *IPConn) SetWriteBuffer(bytes int) os.Error {
 // that was on the packet.
 //
 // ReadFromIP can be made to time out and return an error with
-// Timeout() == true after a fixed time limit; see SetTimeout and
-// SetReadTimeout.
-func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err os.Error) {
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
 	if !c.ok() {
 		return 0, nil, os.EINVAL
 	}
 	// TODO(cw,rsc): consider using readv if we know the family
 	// type to avoid the header trim/copy
+	var addr *IPAddr
 	n, sa, err := c.fd.ReadFrom(b)
 	switch sa := sa.(type) {
 	case *syscall.SockaddrInet4:
@@ -168,11 +167,11 @@ func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err os.Error) {
 	case *syscall.SockaddrInet6:
 		addr = &IPAddr{sa.Addr[0:]}
 	}
-	return
+	return n, addr, err
 }
 
-// ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
 	if !c.ok() {
 		return 0, nil, os.EINVAL
 	}
@@ -184,81 +183,37 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
 //
 // WriteToIP can be made to time out and return
 // an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
 // On packet-oriented connections, write timeouts are rare.
-func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err os.Error) {
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
-	sa, err1 := addr.sockaddr(c.fd.family)
-	if err1 != nil {
-		return 0, &OpError{Op: "write", Net: "ip", Addr: addr, Error: err1}
+	sa, err := addr.sockaddr(c.fd.family)
+	if err != nil {
+		return 0, &OpError{"write", c.fd.net, addr, err}
 	}
 	return c.fd.WriteTo(b, sa)
 }
 
-// WriteTo implements the net.PacketConn WriteTo method.
-func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
 	a, ok := addr.(*IPAddr)
 	if !ok {
-		return 0, &OpError{"writeto", "ip", addr, os.EINVAL}
+		return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
 	}
 	return c.WriteToIP(b, a)
 }
 
-var protocols map[string]int
-
-func readProtocols() {
-	protocols = make(map[string]int)
-	if file, err := open("/etc/protocols"); err == nil {
-		for line, ok := file.readLine(); ok; line, ok = file.readLine() {
-			// tcp    6   TCP    # transmission control protocol
-			if i := byteIndex(line, '#'); i >= 0 {
-				line = line[0:i]
-			}
-			f := getFields(line)
-			if len(f) < 2 {
-				continue
-			}
-			if proto, _, ok := dtoi(f[1], 0); ok {
-				protocols[f[0]] = proto
-				for _, alias := range f[2:] {
-					protocols[alias] = proto
-				}
-			}
-		}
-		file.close()
-	}
-}
-
-func splitNetProto(netProto string) (net string, proto int, err os.Error) {
-	onceReadProtocols.Do(readProtocols)
-	i := last(netProto, ':')
-	if i < 0 { // no colon
-		return "", 0, os.NewError("no IP protocol specified")
-	}
-	net = netProto[0:i]
-	protostr := netProto[i+1:]
-	proto, i, ok := dtoi(protostr, 0)
-	if !ok || i != len(protostr) {
-		// lookup by name
-		proto, ok = protocols[protostr]
-		if ok {
-			return
-		}
-	}
-	return
-}
-
-// DialIP connects to the remote address raddr on the network net,
-// which must be "ip", "ip4", or "ip6".
-func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) {
-	net, proto, err := splitNetProto(netProto)
+// DialIP connects to the remote address raddr on the network protocol netProto,
+// which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
+	net, proto, err := parseDialNetwork(netProto)
 	if err != nil {
-		return
+		return nil, err
 	}
 	switch net {
 	case "ip", "ip4", "ip6":
@@ -266,11 +221,11 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) {
 		return nil, UnknownNetworkError(net)
 	}
 	if raddr == nil {
-		return nil, &OpError{"dial", "ip", nil, errMissingAddress}
+		return nil, &OpError{"dial", netProto, nil, errMissingAddress}
 	}
-	fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
-	if e != nil {
-		return nil, e
+	fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
+	if err != nil {
+		return nil, err
 	}
 	return newIPConn(fd), nil
 }
@@ -279,29 +234,24 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err os.Error) {
 // local address laddr.  The returned connection c's ReadFrom
 // and WriteTo methods can be used to receive and send IP
 // packets with per-packet addressing.
-func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err os.Error) {
-	net, proto, err := splitNetProto(netProto)
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
+	net, proto, err := parseDialNetwork(netProto)
 	if err != nil {
-		return
+		return nil, err
 	}
 	switch net {
 	case "ip", "ip4", "ip6":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
-	fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
-	if e != nil {
-		return nil, e
+	fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
+	if err != nil {
+		return nil, err
 	}
 	return newIPConn(fd), nil
 }
 
-// BindToDevice binds an IPConn to a network interface.
-func (c *IPConn) BindToDevice(device string) os.Error {
-	if !c.ok() {
-		return os.EINVAL
-	}
-	c.fd.incref()
-	defer c.fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device))
-}
+// File returns a copy of the underlying os.File, set to blocking mode.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *IPConn) File() (f *os.File, err error) { return c.fd.dup() }
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index 4e2a562..9234f5a 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -6,14 +6,10 @@
 
 package net
 
-import (
-	"os"
-)
-
 var supportsIPv6, supportsIPv4map = probeIPv6Stack()
 
 func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
-	if filter == anyaddr {
+	if filter == nil {
 		// We'll take any IP address, but since the dialing code
 		// does not yet try multiple addresses, prefer to use
 		// an IPv4 address if possible.  This is especially relevant
@@ -61,14 +57,14 @@ func ipv6only(x IP) IP {
 
 type InvalidAddrError string
 
-func (e InvalidAddrError) String() string  { return string(e) }
+func (e InvalidAddrError) Error() string   { return string(e) }
 func (e InvalidAddrError) Timeout() bool   { return false }
 func (e InvalidAddrError) Temporary() bool { return false }
 
 // SplitHostPort splits a network address of the form
 // "host:port" or "[host]:port" into host and port.
 // The latter form must be used when host contains a colon.
-func SplitHostPort(hostport string) (host, port string, err os.Error) {
+func SplitHostPort(hostport string) (host, port string, err error) {
 	// The port starts after the last colon.
 	i := last(hostport, ':')
 	if i < 0 {
@@ -102,7 +98,7 @@ func JoinHostPort(host, port string) string {
 }
 
 // Convert "host:port" into IP address and port.
-func hostPortToIP(net, hostport string) (ip IP, iport int, err os.Error) {
+func hostPortToIP(net, hostport string) (ip IP, iport int, err error) {
 	var (
 		addr IP
 		p, i int
@@ -117,7 +113,7 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err os.Error) {
 		// Try as an IP address.
 		addr = ParseIP(host)
 		if addr == nil {
-			filter := anyaddr
+			var filter func(IP) IP
 			if net != "" && net[len(net)-1] == '4' {
 				filter = ipv4only
 			}
diff --git a/src/pkg/net/ipsock_plan9.go b/src/pkg/net/ipsock_plan9.go
index 9e5da6d..09d8d6b 100644
--- a/src/pkg/net/ipsock_plan9.go
+++ b/src/pkg/net/ipsock_plan9.go
@@ -7,7 +7,10 @@
 package net
 
 import (
+	"errors"
+	"io"
 	"os"
+	"time"
 )
 
 // probeIPv6Stack returns two boolean values.  If the first boolean value is
@@ -18,7 +21,7 @@ func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
 }
 
 // parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80).
-func parsePlan9Addr(s string) (ip IP, iport int, err os.Error) {
+func parsePlan9Addr(s string) (ip IP, iport int, err error) {
 	var (
 		addr IP
 		p, i int
@@ -29,13 +32,13 @@ func parsePlan9Addr(s string) (ip IP, iport int, err os.Error) {
 	if i >= 0 {
 		addr = ParseIP(s[:i])
 		if addr == nil {
-			err = os.NewError("net: parsing IP failed")
+			err = errors.New("net: parsing IP failed")
 			goto Error
 		}
 	}
 	p, _, ok = dtoi(s[i+1:], 0)
 	if !ok {
-		err = os.NewError("net: parsing port failed")
+		err = errors.New("net: parsing port failed")
 		goto Error
 	}
 	if p < 0 || p > 0xFFFF {
@@ -48,7 +51,7 @@ Error:
 	return nil, 0, err
 }
 
-func readPlan9Addr(proto, filename string) (addr Addr, err os.Error) {
+func readPlan9Addr(proto, filename string) (addr Addr, err error) {
 	var buf [128]byte
 
 	f, err := os.Open(filename)
@@ -69,7 +72,7 @@ func readPlan9Addr(proto, filename string) (addr Addr, err os.Error) {
 	case "udp":
 		addr = &UDPAddr{ip, port}
 	default:
-		return nil, os.NewError("unknown protocol " + proto)
+		return nil, errors.New("unknown protocol " + proto)
 	}
 	return addr, nil
 }
@@ -89,7 +92,7 @@ func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil }
 // Implementation of the Conn interface - see Conn for documentation.
 
 // Read implements the net.Conn Read method.
-func (c *plan9Conn) Read(b []byte) (n int, err os.Error) {
+func (c *plan9Conn) Read(b []byte) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -100,7 +103,7 @@ func (c *plan9Conn) Read(b []byte) (n int, err os.Error) {
 		}
 	}
 	n, err = c.data.Read(b)
-	if c.proto == "udp" && err == os.EOF {
+	if c.proto == "udp" && err == io.EOF {
 		n = 0
 		err = nil
 	}
@@ -108,7 +111,7 @@ func (c *plan9Conn) Read(b []byte) (n int, err os.Error) {
 }
 
 // Write implements the net.Conn Write method.
-func (c *plan9Conn) Write(b []byte) (n int, err os.Error) {
+func (c *plan9Conn) Write(b []byte) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -122,7 +125,7 @@ func (c *plan9Conn) Write(b []byte) (n int, err os.Error) {
 }
 
 // Close closes the connection.
-func (c *plan9Conn) Close() os.Error {
+func (c *plan9Conn) Close() error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -154,31 +157,22 @@ func (c *plan9Conn) RemoteAddr() Addr {
 	return c.raddr
 }
 
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *plan9Conn) SetTimeout(nsec int64) os.Error {
-	if !c.ok() {
-		return os.EINVAL
-	}
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *plan9Conn) SetDeadline(t time.Time) error {
 	return os.EPLAN9
 }
 
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *plan9Conn) SetReadTimeout(nsec int64) os.Error {
-	if !c.ok() {
-		return os.EINVAL
-	}
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *plan9Conn) SetReadDeadline(t time.Time) error {
 	return os.EPLAN9
 }
 
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *plan9Conn) SetWriteTimeout(nsec int64) os.Error {
-	if !c.ok() {
-		return os.EINVAL
-	}
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *plan9Conn) SetWriteDeadline(t time.Time) error {
 	return os.EPLAN9
 }
 
-func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err os.Error) {
+func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err error) {
 	var (
 		ip   IP
 		port int
@@ -213,7 +207,7 @@ func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string,
 	return f, dest, proto, string(buf[:n]), nil
 }
 
-func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err os.Error) {
+func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err error) {
 	f, dest, proto, name, err := startPlan9(net, raddr)
 	if err != nil {
 		return
@@ -239,7 +233,7 @@ type plan9Listener struct {
 	laddr            Addr
 }
 
-func listenPlan9(net string, laddr Addr) (l *plan9Listener, err os.Error) {
+func listenPlan9(net string, laddr Addr) (l *plan9Listener, err error) {
 	f, dest, proto, name, err := startPlan9(net, laddr)
 	if err != nil {
 		return
@@ -265,7 +259,7 @@ func (l *plan9Listener) plan9Conn() *plan9Conn {
 	return newPlan9Conn(l.proto, l.name, l.ctl, l.laddr, nil)
 }
 
-func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err os.Error) {
+func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err error) {
 	f, err := os.Open(l.dir + "/listen")
 	if err != nil {
 		return
@@ -287,7 +281,7 @@ func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err os.Error) {
 	return newPlan9Conn(l.proto, name, f, laddr, raddr), nil
 }
 
-func (l *plan9Listener) Accept() (c Conn, err os.Error) {
+func (l *plan9Listener) Accept() (c Conn, err error) {
 	c1, err := l.acceptPlan9()
 	if err != nil {
 		return
@@ -295,7 +289,7 @@ func (l *plan9Listener) Accept() (c Conn, err os.Error) {
 	return c1, nil
 }
 
-func (l *plan9Listener) Close() os.Error {
+func (l *plan9Listener) Close() error {
 	if l == nil || l.ctl == nil {
 		return os.EINVAL
 	}
diff --git a/src/pkg/net/ipsock_posix.go b/src/pkg/net/ipsock_posix.go
index 049df9e..3a059f5 100644
--- a/src/pkg/net/ipsock_posix.go
+++ b/src/pkg/net/ipsock_posix.go
@@ -2,14 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 package net
 
-import (
-	"os"
-	"syscall"
-)
+import "syscall"
 
 // Should we try to use the IPv4 socket interface if we're
 // only dealing with IPv4 sockets?  As long as the host system
@@ -36,8 +33,8 @@ func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
 	}
 
 	for i := range probes {
-		s, errno := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
-		if errno != 0 {
+		s, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
+		if err != nil {
 			continue
 		}
 		defer closesocket(s)
@@ -45,8 +42,8 @@ func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
 		if err != nil {
 			continue
 		}
-		errno = syscall.Bind(s, sa)
-		if errno != 0 {
+		err = syscall.Bind(s, sa)
+		if err != nil {
 			continue
 		}
 		probes[i].ok = true
@@ -94,23 +91,18 @@ func favoriteAddrFamily(net string, raddr, laddr sockaddr, mode string) int {
 	return syscall.AF_INET6
 }
 
-// TODO(rsc): if syscall.OS == "linux", we're supposed to read
-// /proc/sys/net/core/somaxconn,
-// to take advantage of kernels that have raised the limit.
-func listenBacklog() int { return syscall.SOMAXCONN }
-
 // Internet sockets (TCP, UDP)
 
 // A sockaddr represents a TCP or UDP network address that can
 // be converted into a syscall.Sockaddr.
 type sockaddr interface {
 	Addr
-	sockaddr(family int) (syscall.Sockaddr, os.Error)
+	sockaddr(family int) (syscall.Sockaddr, error)
 	family() int
 }
 
-func internetSocket(net string, laddr, raddr sockaddr, socktype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) {
-	var oserr os.Error
+func internetSocket(net string, laddr, raddr sockaddr, sotype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+	var oserr error
 	var la, ra syscall.Sockaddr
 	family := favoriteAddrFamily(net, raddr, laddr, mode)
 	if laddr != nil {
@@ -123,7 +115,7 @@ func internetSocket(net string, laddr, raddr sockaddr, socktype, proto int, mode
 			goto Error
 		}
 	}
-	fd, oserr = socket(net, family, socktype, proto, la, ra, toAddr)
+	fd, oserr = socket(net, family, sotype, proto, la, ra, toAddr)
 	if oserr != nil {
 		goto Error
 	}
@@ -137,7 +129,7 @@ Error:
 	return nil, &OpError{mode, net, addr, oserr}
 }
 
-func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, os.Error) {
+func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, error) {
 	switch family {
 	case syscall.AF_INET:
 		if len(ip) == 0 {
diff --git a/src/pkg/net/lookup_plan9.go b/src/pkg/net/lookup_plan9.go
index ee0c9e8..c0bb922 100644
--- a/src/pkg/net/lookup_plan9.go
+++ b/src/pkg/net/lookup_plan9.go
@@ -5,10 +5,11 @@
 package net
 
 import (
+	"errors"
 	"os"
 )
 
-func query(filename, query string, bufSize int) (res []string, err os.Error) {
+func query(filename, query string, bufSize int) (res []string, err error) {
 	file, err := os.OpenFile(filename, os.O_RDWR, 0)
 	if err != nil {
 		return
@@ -34,7 +35,7 @@ func query(filename, query string, bufSize int) (res []string, err os.Error) {
 	return
 }
 
-func queryCS(net, host, service string) (res []string, err os.Error) {
+func queryCS(net, host, service string) (res []string, err error) {
 	switch net {
 	case "tcp4", "tcp6":
 		net = "tcp"
@@ -47,9 +48,9 @@ func queryCS(net, host, service string) (res []string, err os.Error) {
 	return query("/net/cs", net+"!"+host+"!"+service, 128)
 }
 
-func queryCS1(net string, ip IP, port int) (clone, dest string, err os.Error) {
+func queryCS1(net string, ip IP, port int) (clone, dest string, err error) {
 	ips := "*"
-	if !ip.IsUnspecified() {
+	if len(ip) != 0 && !ip.IsUnspecified() {
 		ips = ip.String()
 	}
 	lines, err := queryCS(net, ips, itoa(port))
@@ -58,19 +59,22 @@ func queryCS1(net string, ip IP, port int) (clone, dest string, err os.Error) {
 	}
 	f := getFields(lines[0])
 	if len(f) < 2 {
-		return "", "", os.NewError("net: bad response from ndb/cs")
+		return "", "", errors.New("net: bad response from ndb/cs")
 	}
 	clone, dest = f[0], f[1]
 	return
 }
 
-func queryDNS(addr string, typ string) (res []string, err os.Error) {
+func queryDNS(addr string, typ string) (res []string, err error) {
 	return query("/net/dns", addr+" "+typ, 1024)
 }
 
-// LookupHost looks up the given host using the local resolver.
-// It returns an array of that host's addresses.
-func LookupHost(host string) (addrs []string, err os.Error) {
+func lookupProtocol(name string) (proto int, err error) {
+	// TODO: Implement this
+	return 0, os.EPLAN9
+}
+
+func lookupHost(host string) (addrs []string, err error) {
 	// Use /net/cs insead of /net/dns because cs knows about
 	// host names in local network (e.g. from /lib/ndb/local)
 	lines, err := queryCS("tcp", host, "1")
@@ -94,9 +98,7 @@ func LookupHost(host string) (addrs []string, err os.Error) {
 	return
 }
 
-// LookupIP looks up host using the local resolver.
-// It returns an array of that host's IPv4 and IPv6 addresses.
-func LookupIP(host string) (ips []IP, err os.Error) {
+func lookupIP(host string) (ips []IP, err error) {
 	addrs, err := LookupHost(host)
 	if err != nil {
 		return
@@ -109,8 +111,7 @@ func LookupIP(host string) (ips []IP, err os.Error) {
 	return
 }
 
-// LookupPort looks up the port for the given network and service.
-func LookupPort(network, service string) (port int, err os.Error) {
+func lookupPort(network, service string) (port int, err error) {
 	switch network {
 	case "tcp4", "tcp6":
 		network = "tcp"
@@ -139,11 +140,7 @@ func LookupPort(network, service string) (port int, err os.Error) {
 	return 0, unknownPortError
 }
 
-// LookupCNAME returns the canonical DNS host for the given name.
-// Callers that do not care about the canonical name can call
-// LookupHost or LookupIP directly; both take care of resolving
-// the canonical name as part of the lookup.
-func LookupCNAME(name string) (cname string, err os.Error) {
+func lookupCNAME(name string) (cname string, err error) {
 	lines, err := queryDNS(name, "cname")
 	if err != nil {
 		return
@@ -153,16 +150,16 @@ func LookupCNAME(name string) (cname string, err os.Error) {
 			return f[2] + ".", nil
 		}
 	}
-	return "", os.NewError("net: bad response from ndb/dns")
+	return "", errors.New("net: bad response from ndb/dns")
 }
 
-// LookupSRV tries to resolve an SRV query of the given service,
-// protocol, and domain name, as specified in RFC 2782. In most cases
-// the proto argument can be the same as the corresponding
-// Addr.Network(). The returned records are sorted by priority 
-// and randomized by weight within a priority.
-func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
-	target := "_" + service + "._" + proto + "." + name
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	var target string
+	if service == "" && proto == "" {
+		target = name
+	} else {
+		target = "_" + service + "._" + proto + "." + name
+	}
 	lines, err := queryDNS(target, "srv")
 	if err != nil {
 		return
@@ -185,8 +182,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
 	return
 }
 
-// LookupMX returns the DNS MX records for the given domain name sorted by preference.
-func LookupMX(name string) (mx []*MX, err os.Error) {
+func lookupMX(name string) (mx []*MX, err error) {
 	lines, err := queryDNS(name, "mx")
 	if err != nil {
 		return
@@ -204,14 +200,20 @@ func LookupMX(name string) (mx []*MX, err os.Error) {
 	return
 }
 
-// LookupTXT returns the DNS TXT records for the given domain name.
-func LookupTXT(name string) (txt []string, err os.Error) {
-	return nil, os.NewError("net.LookupTXT is not implemented on Plan 9")
+func lookupTXT(name string) (txt []string, err error) {
+	lines, err := queryDNS(name, "txt")
+	if err != nil {
+		return
+	}
+	for _, line := range lines {
+		if i := byteIndex(line, '\t'); i >= 0 {
+			txt = append(txt, line[i+1:])
+		}
+	}
+	return
 }
 
-// LookupAddr performs a reverse lookup for the given address, returning a list
-// of names mapping to that address.
-func LookupAddr(addr string) (name []string, err os.Error) {
+func lookupAddr(addr string) (name []string, err error) {
 	arpa, err := reverseaddr(addr)
 	if err != nil {
 		return
diff --git a/src/pkg/net/lookup_test.go b/src/pkg/net/lookup_test.go
index 41066fe..9a39ca8 100644
--- a/src/pkg/net/lookup_test.go
+++ b/src/pkg/net/lookup_test.go
@@ -26,6 +26,15 @@ func TestGoogleSRV(t *testing.T) {
 	if len(addrs) == 0 {
 		t.Errorf("no results")
 	}
+
+	// Non-standard back door.
+	_, addrs, err = LookupSRV("", "", "_xmpp-server._tcp.google.com")
+	if err != nil {
+		t.Errorf("back door failed: %s", err)
+	}
+	if len(addrs) == 0 {
+		t.Errorf("back door no results")
+	}
 }
 
 func TestGmailMX(t *testing.T) {
@@ -43,10 +52,6 @@ func TestGmailMX(t *testing.T) {
 }
 
 func TestGmailTXT(t *testing.T) {
-	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
-		t.Logf("LookupTXT is not implemented on Windows or Plan 9")
-		return
-	}
 	if testing.Short() || avoidMacFirewall {
 		t.Logf("skipping test to avoid external network")
 		return
diff --git a/src/pkg/net/lookup_unix.go b/src/pkg/net/lookup_unix.go
index 7368b75..d500a12 100644
--- a/src/pkg/net/lookup_unix.go
+++ b/src/pkg/net/lookup_unix.go
@@ -2,17 +2,57 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package net
 
 import (
-	"os"
+	"errors"
+	"sync"
 )
 
-// LookupHost looks up the given host using the local resolver.
-// It returns an array of that host's addresses.
-func LookupHost(host string) (addrs []string, err os.Error) {
+var (
+	protocols         map[string]int
+	onceReadProtocols sync.Once
+)
+
+// readProtocols loads contents of /etc/protocols into protocols map
+// for quick access.
+func readProtocols() {
+	protocols = make(map[string]int)
+	if file, err := open("/etc/protocols"); err == nil {
+		for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+			// tcp    6   TCP    # transmission control protocol
+			if i := byteIndex(line, '#'); i >= 0 {
+				line = line[0:i]
+			}
+			f := getFields(line)
+			if len(f) < 2 {
+				continue
+			}
+			if proto, _, ok := dtoi(f[1], 0); ok {
+				protocols[f[0]] = proto
+				for _, alias := range f[2:] {
+					protocols[alias] = proto
+				}
+			}
+		}
+		file.close()
+	}
+}
+
+// lookupProtocol looks up IP protocol name in /etc/protocols and
+// returns correspondent protocol number.
+func lookupProtocol(name string) (proto int, err error) {
+	onceReadProtocols.Do(readProtocols)
+	proto, found := protocols[name]
+	if !found {
+		return 0, errors.New("unknown IP protocol specified: " + name)
+	}
+	return
+}
+
+func lookupHost(host string) (addrs []string, err error) {
 	addrs, err, ok := cgoLookupHost(host)
 	if !ok {
 		addrs, err = goLookupHost(host)
@@ -20,9 +60,7 @@ func LookupHost(host string) (addrs []string, err os.Error) {
 	return
 }
 
-// LookupIP looks up host using the local resolver.
-// It returns an array of that host's IPv4 and IPv6 addresses.
-func LookupIP(host string) (addrs []IP, err os.Error) {
+func lookupIP(host string) (addrs []IP, err error) {
 	addrs, err, ok := cgoLookupIP(host)
 	if !ok {
 		addrs, err = goLookupIP(host)
@@ -30,8 +68,7 @@ func LookupIP(host string) (addrs []IP, err os.Error) {
 	return
 }
 
-// LookupPort looks up the port for the given network and service.
-func LookupPort(network, service string) (port int, err os.Error) {
+func lookupPort(network, service string) (port int, err error) {
 	port, err, ok := cgoLookupPort(network, service)
 	if !ok {
 		port, err = goLookupPort(network, service)
@@ -39,11 +76,7 @@ func LookupPort(network, service string) (port int, err os.Error) {
 	return
 }
 
-// LookupCNAME returns the canonical DNS host for the given name.
-// Callers that do not care about the canonical name can call
-// LookupHost or LookupIP directly; both take care of resolving
-// the canonical name as part of the lookup.
-func LookupCNAME(name string) (cname string, err os.Error) {
+func lookupCNAME(name string) (cname string, err error) {
 	cname, err, ok := cgoLookupCNAME(name)
 	if !ok {
 		cname, err = goLookupCNAME(name)
@@ -51,13 +84,13 @@ func LookupCNAME(name string) (cname string, err os.Error) {
 	return
 }
 
-// LookupSRV tries to resolve an SRV query of the given service,
-// protocol, and domain name, as specified in RFC 2782. In most cases
-// the proto argument can be the same as the corresponding
-// Addr.Network(). The returned records are sorted by priority
-// and randomized by weight within a priority.
-func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
-	target := "_" + service + "._" + proto + "." + name
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	var target string
+	if service == "" && proto == "" {
+		target = name
+	} else {
+		target = "_" + service + "._" + proto + "." + name
+	}
 	var records []dnsRR
 	cname, records, err = lookup(target, dnsTypeSRV)
 	if err != nil {
@@ -72,8 +105,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
 	return
 }
 
-// LookupMX returns the DNS MX records for the given domain name sorted by preference.
-func LookupMX(name string) (mx []*MX, err os.Error) {
+func lookupMX(name string) (mx []*MX, err error) {
 	_, records, err := lookup(name, dnsTypeMX)
 	if err != nil {
 		return
@@ -87,8 +119,7 @@ func LookupMX(name string) (mx []*MX, err os.Error) {
 	return
 }
 
-// LookupTXT returns the DNS TXT records for the given domain name.
-func LookupTXT(name string) (txt []string, err os.Error) {
+func lookupTXT(name string) (txt []string, err error) {
 	_, records, err := lookup(name, dnsTypeTXT)
 	if err != nil {
 		return
@@ -100,9 +131,7 @@ func LookupTXT(name string) (txt []string, err os.Error) {
 	return
 }
 
-// LookupAddr performs a reverse lookup for the given address, returning a list
-// of names mapping to that address.
-func LookupAddr(addr string) (name []string, err os.Error) {
+func lookupAddr(addr string) (name []string, err error) {
 	name = lookupStaticAddr(addr)
 	if len(name) > 0 {
 		return
diff --git a/src/pkg/net/lookup_windows.go b/src/pkg/net/lookup_windows.go
index b33c7f9..dfe2ff6 100644
--- a/src/pkg/net/lookup_windows.go
+++ b/src/pkg/net/lookup_windows.go
@@ -5,16 +5,30 @@
 package net
 
 import (
-	"syscall"
-	"unsafe"
 	"os"
 	"sync"
+	"syscall"
+	"unsafe"
 )
 
-var hostentLock sync.Mutex
-var serventLock sync.Mutex
+var (
+	protoentLock sync.Mutex
+	hostentLock  sync.Mutex
+	serventLock  sync.Mutex
+)
+
+// lookupProtocol looks up IP protocol name and returns correspondent protocol number.
+func lookupProtocol(name string) (proto int, err error) {
+	protoentLock.Lock()
+	defer protoentLock.Unlock()
+	p, e := syscall.GetProtoByName(name)
+	if e != nil {
+		return 0, os.NewSyscallError("GetProtoByName", e)
+	}
+	return int(p.Proto), nil
+}
 
-func LookupHost(name string) (addrs []string, err os.Error) {
+func lookupHost(name string) (addrs []string, err error) {
 	ips, err := LookupIP(name)
 	if err != nil {
 		return
@@ -26,11 +40,11 @@ func LookupHost(name string) (addrs []string, err os.Error) {
 	return
 }
 
-func LookupIP(name string) (addrs []IP, err os.Error) {
+func lookupIP(name string) (addrs []IP, err error) {
 	hostentLock.Lock()
 	defer hostentLock.Unlock()
 	h, e := syscall.GetHostByName(name)
-	if e != 0 {
+	if e != nil {
 		return nil, os.NewSyscallError("GetHostByName", e)
 	}
 	switch h.AddrType {
@@ -47,7 +61,7 @@ func LookupIP(name string) (addrs []IP, err os.Error) {
 	return addrs, nil
 }
 
-func LookupPort(network, service string) (port int, err os.Error) {
+func lookupPort(network, service string) (port int, err error) {
 	switch network {
 	case "tcp4", "tcp6":
 		network = "tcp"
@@ -57,17 +71,17 @@ func LookupPort(network, service string) (port int, err os.Error) {
 	serventLock.Lock()
 	defer serventLock.Unlock()
 	s, e := syscall.GetServByName(service, network)
-	if e != 0 {
+	if e != nil {
 		return 0, os.NewSyscallError("GetServByName", e)
 	}
 	return int(syscall.Ntohs(s.Port)), nil
 }
 
-func LookupCNAME(name string) (cname string, err os.Error) {
+func lookupCNAME(name string) (cname string, err error) {
 	var r *syscall.DNSRecord
 	e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
-	if int(e) != 0 {
-		return "", os.NewSyscallError("LookupCNAME", int(e))
+	if e != nil {
+		return "", os.NewSyscallError("LookupCNAME", e)
 	}
 	defer syscall.DnsRecordListFree(r, 1)
 	if r != nil && r.Type == syscall.DNS_TYPE_CNAME {
@@ -77,12 +91,17 @@ func LookupCNAME(name string) (cname string, err os.Error) {
 	return
 }
 
-func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
+func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+	var target string
+	if service == "" && proto == "" {
+		target = name
+	} else {
+		target = "_" + service + "._" + proto + "." + name
+	}
 	var r *syscall.DNSRecord
-	target := "_" + service + "._" + proto + "." + name
 	e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil)
-	if int(e) != 0 {
-		return "", nil, os.NewSyscallError("LookupSRV", int(e))
+	if e != nil {
+		return "", nil, os.NewSyscallError("LookupSRV", e)
 	}
 	defer syscall.DnsRecordListFree(r, 1)
 	addrs = make([]*SRV, 0, 10)
@@ -94,11 +113,11 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
 	return name, addrs, nil
 }
 
-func LookupMX(name string) (mx []*MX, err os.Error) {
+func lookupMX(name string) (mx []*MX, err error) {
 	var r *syscall.DNSRecord
 	e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil)
-	if int(e) != 0 {
-		return nil, os.NewSyscallError("LookupMX", int(e))
+	if e != nil {
+		return nil, os.NewSyscallError("LookupMX", e)
 	}
 	defer syscall.DnsRecordListFree(r, 1)
 	mx = make([]*MX, 0, 10)
@@ -110,19 +129,33 @@ func LookupMX(name string) (mx []*MX, err os.Error) {
 	return mx, nil
 }
 
-func LookupTXT(name string) (txt []string, err os.Error) {
-	return nil, os.NewError("net.LookupTXT is not implemented on Windows")
+func lookupTXT(name string) (txt []string, err error) {
+	var r *syscall.DNSRecord
+	e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil)
+	if e != nil {
+		return nil, os.NewSyscallError("LookupTXT", e)
+	}
+	defer syscall.DnsRecordListFree(r, 1)
+	txt = make([]string, 0, 10)
+	if r != nil && r.Type == syscall.DNS_TYPE_TEXT {
+		d := (*syscall.DNSTXTData)(unsafe.Pointer(&r.Data[0]))
+		for _, v := range (*[1 << 10]*uint16)(unsafe.Pointer(&(d.StringArray[0])))[:d.StringCount] {
+			s := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(v))[:])
+			txt = append(txt, s)
+		}
+	}
+	return
 }
 
-func LookupAddr(addr string) (name []string, err os.Error) {
+func lookupAddr(addr string) (name []string, err error) {
 	arpa, err := reverseaddr(addr)
 	if err != nil {
 		return nil, err
 	}
 	var r *syscall.DNSRecord
 	e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil)
-	if int(e) != 0 {
-		return nil, os.NewSyscallError("LookupAddr", int(e))
+	if e != nil {
+		return nil, os.NewSyscallError("LookupAddr", e)
 	}
 	defer syscall.DnsRecordListFree(r, 1)
 	name = make([]string, 0, 10)
diff --git a/src/pkg/net/mail/Makefile b/src/pkg/net/mail/Makefile
new file mode 100644
index 0000000..acb1c2a
--- /dev/null
+++ b/src/pkg/net/mail/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=net/mail
+GOFILES=\
+	message.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/net/mail/message.go b/src/pkg/net/mail/message.go
new file mode 100644
index 0000000..bf22c71
--- /dev/null
+++ b/src/pkg/net/mail/message.go
@@ -0,0 +1,524 @@
+// Copyright 2011 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 mail implements parsing of mail messages.
+
+For the most part, this package follows the syntax as specified by RFC 5322.
+Notable divergences:
+	* Obsolete address formats are not parsed, including addresses with
+	  embedded route information.
+	* Group addresses are not parsed.
+	* The full range of spacing (the CFWS syntax element) is not supported,
+	  such as breaking addresses across lines.
+*/
+package mail
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net/textproto"
+	"strconv"
+	"strings"
+	"time"
+)
+
+var debug = debugT(false)
+
+type debugT bool
+
+func (d debugT) Printf(format string, args ...interface{}) {
+	if d {
+		log.Printf(format, args...)
+	}
+}
+
+// A Message represents a parsed mail message.
+type Message struct {
+	Header Header
+	Body   io.Reader
+}
+
+// ReadMessage reads a message from r.
+// The headers are parsed, and the body of the message will be reading from r.
+func ReadMessage(r io.Reader) (msg *Message, err error) {
+	tp := textproto.NewReader(bufio.NewReader(r))
+
+	hdr, err := tp.ReadMIMEHeader()
+	if err != nil {
+		return nil, err
+	}
+
+	return &Message{
+		Header: Header(hdr),
+		Body:   tp.R,
+	}, nil
+}
+
+// Layouts suitable for passing to time.Parse.
+// These are tried in order.
+var dateLayouts []string
+
+func init() {
+	// Generate layouts based on RFC 5322, section 3.3.
+
+	dows := [...]string{"", "Mon, "}     // day-of-week
+	days := [...]string{"2", "02"}       // day = 1*2DIGIT
+	years := [...]string{"2006", "06"}   // year = 4*DIGIT / 2*DIGIT
+	seconds := [...]string{":05", ""}    // second
+	zones := [...]string{"-0700", "MST"} // zone = (("+" / "-") 4DIGIT) / "GMT" / ...
+
+	for _, dow := range dows {
+		for _, day := range days {
+			for _, year := range years {
+				for _, second := range seconds {
+					for _, zone := range zones {
+						s := dow + day + " Jan " + year + " 15:04" + second + " " + zone
+						dateLayouts = append(dateLayouts, s)
+					}
+				}
+			}
+		}
+	}
+}
+
+func parseDate(date string) (time.Time, error) {
+	for _, layout := range dateLayouts {
+		t, err := time.Parse(layout, date)
+		if err == nil {
+			return t, nil
+		}
+	}
+	return time.Time{}, errors.New("mail: header could not be parsed")
+}
+
+// A Header represents the key-value pairs in a mail message header.
+type Header map[string][]string
+
+// Get gets the first value associated with the given key.
+// If there are no values associated with the key, Get returns "".
+func (h Header) Get(key string) string {
+	return textproto.MIMEHeader(h).Get(key)
+}
+
+var ErrHeaderNotPresent = errors.New("mail: header not in message")
+
+// Date parses the Date header field.
+func (h Header) Date() (time.Time, error) {
+	hdr := h.Get("Date")
+	if hdr == "" {
+		return time.Time{}, ErrHeaderNotPresent
+	}
+	return parseDate(hdr)
+}
+
+// AddressList parses the named header field as a list of addresses.
+func (h Header) AddressList(key string) ([]*Address, error) {
+	hdr := h.Get(key)
+	if hdr == "" {
+		return nil, ErrHeaderNotPresent
+	}
+	return newAddrParser(hdr).parseAddressList()
+}
+
+// Address represents a single mail address.
+// An address such as "Barry Gibbs <bg at example.com>" is represented
+// as Address{Name: "Barry Gibbs", Address: "bg at example.com"}.
+type Address struct {
+	Name    string // Proper name; may be empty.
+	Address string // user at domain
+}
+
+// String formats the address as a valid RFC 5322 address.
+// If the address's name contains non-ASCII characters
+// the name will be rendered according to RFC 2047.
+func (a *Address) String() string {
+	s := "<" + a.Address + ">"
+	if a.Name == "" {
+		return s
+	}
+	// If every character is printable ASCII, quoting is simple.
+	allPrintable := true
+	for i := 0; i < len(a.Name); i++ {
+		if !isVchar(a.Name[i]) {
+			allPrintable = false
+			break
+		}
+	}
+	if allPrintable {
+		b := bytes.NewBufferString(`"`)
+		for i := 0; i < len(a.Name); i++ {
+			if !isQtext(a.Name[i]) {
+				b.WriteByte('\\')
+			}
+			b.WriteByte(a.Name[i])
+		}
+		b.WriteString(`" `)
+		b.WriteString(s)
+		return b.String()
+	}
+
+	// UTF-8 "Q" encoding
+	b := bytes.NewBufferString("=?utf-8?q?")
+	for i := 0; i < len(a.Name); i++ {
+		switch c := a.Name[i]; {
+		case c == ' ':
+			b.WriteByte('_')
+		case isVchar(c) && c != '=' && c != '?' && c != '_':
+			b.WriteByte(c)
+		default:
+			fmt.Fprintf(b, "=%02X", c)
+		}
+	}
+	b.WriteString("?= ")
+	b.WriteString(s)
+	return b.String()
+}
+
+type addrParser []byte
+
+func newAddrParser(s string) *addrParser {
+	p := addrParser(s)
+	return &p
+}
+
+func (p *addrParser) parseAddressList() ([]*Address, error) {
+	var list []*Address
+	for {
+		p.skipSpace()
+		addr, err := p.parseAddress()
+		if err != nil {
+			return nil, err
+		}
+		list = append(list, addr)
+
+		p.skipSpace()
+		if p.empty() {
+			break
+		}
+		if !p.consume(',') {
+			return nil, errors.New("mail: expected comma")
+		}
+	}
+	return list, nil
+}
+
+// parseAddress parses a single RFC 5322 address at the start of p.
+func (p *addrParser) parseAddress() (addr *Address, err error) {
+	debug.Printf("parseAddress: %q", *p)
+	p.skipSpace()
+	if p.empty() {
+		return nil, errors.New("mail: no address")
+	}
+
+	// address = name-addr / addr-spec
+	// TODO(dsymonds): Support parsing group address.
+
+	// addr-spec has a more restricted grammar than name-addr,
+	// so try parsing it first, and fallback to name-addr.
+	// TODO(dsymonds): Is this really correct?
+	spec, err := p.consumeAddrSpec()
+	if err == nil {
+		return &Address{
+			Address: spec,
+		}, err
+	}
+	debug.Printf("parseAddress: not an addr-spec: %v", err)
+	debug.Printf("parseAddress: state is now %q", *p)
+
+	// display-name
+	var displayName string
+	if p.peek() != '<' {
+		displayName, err = p.consumePhrase()
+		if err != nil {
+			return nil, err
+		}
+	}
+	debug.Printf("parseAddress: displayName=%q", displayName)
+
+	// angle-addr = "<" addr-spec ">"
+	p.skipSpace()
+	if !p.consume('<') {
+		return nil, errors.New("mail: no angle-addr")
+	}
+	spec, err = p.consumeAddrSpec()
+	if err != nil {
+		return nil, err
+	}
+	if !p.consume('>') {
+		return nil, errors.New("mail: unclosed angle-addr")
+	}
+	debug.Printf("parseAddress: spec=%q", spec)
+
+	return &Address{
+		Name:    displayName,
+		Address: spec,
+	}, nil
+}
+
+// consumeAddrSpec parses a single RFC 5322 addr-spec at the start of p.
+func (p *addrParser) consumeAddrSpec() (spec string, err error) {
+	debug.Printf("consumeAddrSpec: %q", *p)
+
+	orig := *p
+	defer func() {
+		if err != nil {
+			*p = orig
+		}
+	}()
+
+	// local-part = dot-atom / quoted-string
+	var localPart string
+	p.skipSpace()
+	if p.empty() {
+		return "", errors.New("mail: no addr-spec")
+	}
+	if p.peek() == '"' {
+		// quoted-string
+		debug.Printf("consumeAddrSpec: parsing quoted-string")
+		localPart, err = p.consumeQuotedString()
+	} else {
+		// dot-atom
+		debug.Printf("consumeAddrSpec: parsing dot-atom")
+		localPart, err = p.consumeAtom(true)
+	}
+	if err != nil {
+		debug.Printf("consumeAddrSpec: failed: %v", err)
+		return "", err
+	}
+
+	if !p.consume('@') {
+		return "", errors.New("mail: missing @ in addr-spec")
+	}
+
+	// domain = dot-atom / domain-literal
+	var domain string
+	p.skipSpace()
+	if p.empty() {
+		return "", errors.New("mail: no domain in addr-spec")
+	}
+	// TODO(dsymonds): Handle domain-literal
+	domain, err = p.consumeAtom(true)
+	if err != nil {
+		return "", err
+	}
+
+	return localPart + "@" + domain, nil
+}
+
+// consumePhrase parses the RFC 5322 phrase at the start of p.
+func (p *addrParser) consumePhrase() (phrase string, err error) {
+	debug.Printf("consumePhrase: [%s]", *p)
+	// phrase = 1*word
+	var words []string
+	for {
+		// word = atom / quoted-string
+		var word string
+		p.skipSpace()
+		if p.empty() {
+			return "", errors.New("mail: missing phrase")
+		}
+		if p.peek() == '"' {
+			// quoted-string
+			word, err = p.consumeQuotedString()
+		} else {
+			// atom
+			word, err = p.consumeAtom(false)
+		}
+
+		// RFC 2047 encoded-word starts with =?, ends with ?=, and has two other ?s.
+		if err == nil && strings.HasPrefix(word, "=?") && strings.HasSuffix(word, "?=") && strings.Count(word, "?") == 4 {
+			word, err = decodeRFC2047Word(word)
+		}
+
+		if err != nil {
+			break
+		}
+		debug.Printf("consumePhrase: consumed %q", word)
+		words = append(words, word)
+	}
+	// Ignore any error if we got at least one word.
+	if err != nil && len(words) == 0 {
+		debug.Printf("consumePhrase: hit err: %v", err)
+		return "", errors.New("mail: missing word in phrase")
+	}
+	phrase = strings.Join(words, " ")
+	return phrase, nil
+}
+
+// consumeQuotedString parses the quoted string at the start of p.
+func (p *addrParser) consumeQuotedString() (qs string, err error) {
+	// Assume first byte is '"'.
+	i := 1
+	qsb := make([]byte, 0, 10)
+Loop:
+	for {
+		if i >= p.len() {
+			return "", errors.New("mail: unclosed quoted-string")
+		}
+		switch c := (*p)[i]; {
+		case c == '"':
+			break Loop
+		case c == '\\':
+			if i+1 == p.len() {
+				return "", errors.New("mail: unclosed quoted-string")
+			}
+			qsb = append(qsb, (*p)[i+1])
+			i += 2
+		case isQtext(c), c == ' ' || c == '\t':
+			// qtext (printable US-ASCII excluding " and \), or
+			// FWS (almost; we're ignoring CRLF)
+			qsb = append(qsb, c)
+			i++
+		default:
+			return "", fmt.Errorf("mail: bad character in quoted-string: %q", c)
+		}
+	}
+	*p = (*p)[i+1:]
+	return string(qsb), nil
+}
+
+// consumeAtom parses an RFC 5322 atom at the start of p.
+// If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
+func (p *addrParser) consumeAtom(dot bool) (atom string, err error) {
+	if !isAtext(p.peek(), false) {
+		return "", errors.New("mail: invalid string")
+	}
+	i := 1
+	for ; i < p.len() && isAtext((*p)[i], dot); i++ {
+	}
+	// TODO(dsymonds): Remove the []byte() conversion here when 6g doesn't need it.
+	atom, *p = string([]byte((*p)[:i])), (*p)[i:]
+	return atom, nil
+}
+
+func (p *addrParser) consume(c byte) bool {
+	if p.empty() || p.peek() != c {
+		return false
+	}
+	*p = (*p)[1:]
+	return true
+}
+
+// skipSpace skips the leading space and tab characters.
+func (p *addrParser) skipSpace() {
+	*p = bytes.TrimLeft(*p, " \t")
+}
+
+func (p *addrParser) peek() byte {
+	return (*p)[0]
+}
+
+func (p *addrParser) empty() bool {
+	return p.len() == 0
+}
+
+func (p *addrParser) len() int {
+	return len(*p)
+}
+
+func decodeRFC2047Word(s string) (string, error) {
+	fields := strings.Split(s, "?")
+	if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" {
+		return "", errors.New("mail: address not RFC 2047 encoded")
+	}
+	charset, enc := strings.ToLower(fields[1]), strings.ToLower(fields[2])
+	if charset != "iso-8859-1" && charset != "utf-8" {
+		return "", fmt.Errorf("mail: charset not supported: %q", charset)
+	}
+
+	in := bytes.NewBufferString(fields[3])
+	var r io.Reader
+	switch enc {
+	case "b":
+		r = base64.NewDecoder(base64.StdEncoding, in)
+	case "q":
+		r = qDecoder{r: in}
+	default:
+		return "", fmt.Errorf("mail: RFC 2047 encoding not supported: %q", enc)
+	}
+
+	dec, err := ioutil.ReadAll(r)
+	if err != nil {
+		return "", err
+	}
+
+	switch charset {
+	case "iso-8859-1":
+		b := new(bytes.Buffer)
+		for _, c := range dec {
+			b.WriteRune(rune(c))
+		}
+		return b.String(), nil
+	case "utf-8":
+		return string(dec), nil
+	}
+	panic("unreachable")
+}
+
+type qDecoder struct {
+	r       io.Reader
+	scratch [2]byte
+}
+
+func (qd qDecoder) Read(p []byte) (n int, err error) {
+	// This method writes at most one byte into p.
+	if len(p) == 0 {
+		return 0, nil
+	}
+	if _, err := qd.r.Read(qd.scratch[:1]); err != nil {
+		return 0, err
+	}
+	switch c := qd.scratch[0]; {
+	case c == '=':
+		if _, err := io.ReadFull(qd.r, qd.scratch[:2]); err != nil {
+			return 0, err
+		}
+		x, err := strconv.ParseInt(string(qd.scratch[:2]), 16, 64)
+		if err != nil {
+			return 0, fmt.Errorf("mail: invalid RFC 2047 encoding: %q", qd.scratch[:2])
+		}
+		p[0] = byte(x)
+	case c == '_':
+		p[0] = ' '
+	default:
+		p[0] = c
+	}
+	return 1, nil
+}
+
+var atextChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+	"abcdefghijklmnopqrstuvwxyz" +
+	"0123456789" +
+	"!#$%&'*+-/=?^_`{|}~")
+
+// isAtext returns true if c is an RFC 5322 atext character.
+// If dot is true, period is included.
+func isAtext(c byte, dot bool) bool {
+	if dot && c == '.' {
+		return true
+	}
+	return bytes.IndexByte(atextChars, c) >= 0
+}
+
+// isQtext returns true if c is an RFC 5322 qtest character.
+func isQtext(c byte) bool {
+	// Printable US-ASCII, excluding backslash or quote.
+	if c == '\\' || c == '"' {
+		return false
+	}
+	return '!' <= c && c <= '~'
+}
+
+// isVchar returns true if c is an RFC 5322 VCHAR character.
+func isVchar(c byte) bool {
+	// Visible (printing) characters.
+	return '!' <= c && c <= '~'
+}
diff --git a/src/pkg/net/mail/message_test.go b/src/pkg/net/mail/message_test.go
new file mode 100644
index 0000000..671ff2e
--- /dev/null
+++ b/src/pkg/net/mail/message_test.go
@@ -0,0 +1,261 @@
+// Copyright 2011 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 mail
+
+import (
+	"bytes"
+	"io/ioutil"
+	"reflect"
+	"testing"
+	"time"
+)
+
+var parseTests = []struct {
+	in     string
+	header Header
+	body   string
+}{
+	{
+		// RFC 5322, Appendix A.1.1
+		in: `From: John Doe <jdoe at machine.example>
+To: Mary Smith <mary at example.net>
+Subject: Saying Hello
+Date: Fri, 21 Nov 1997 09:55:06 -0600
+Message-ID: <1234 at local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+`,
+		header: Header{
+			"From":       []string{"John Doe <jdoe at machine.example>"},
+			"To":         []string{"Mary Smith <mary at example.net>"},
+			"Subject":    []string{"Saying Hello"},
+			"Date":       []string{"Fri, 21 Nov 1997 09:55:06 -0600"},
+			"Message-Id": []string{"<1234 at local.machine.example>"},
+		},
+		body: "This is a message just to say hello.\nSo, \"Hello\".\n",
+	},
+}
+
+func TestParsing(t *testing.T) {
+	for i, test := range parseTests {
+		msg, err := ReadMessage(bytes.NewBuffer([]byte(test.in)))
+		if err != nil {
+			t.Errorf("test #%d: Failed parsing message: %v", i, err)
+			continue
+		}
+		if !headerEq(msg.Header, test.header) {
+			t.Errorf("test #%d: Incorrectly parsed message header.\nGot:\n%+v\nWant:\n%+v",
+				i, msg.Header, test.header)
+		}
+		body, err := ioutil.ReadAll(msg.Body)
+		if err != nil {
+			t.Errorf("test #%d: Failed reading body: %v", i, err)
+			continue
+		}
+		bodyStr := string(body)
+		if bodyStr != test.body {
+			t.Errorf("test #%d: Incorrectly parsed message body.\nGot:\n%+v\nWant:\n%+v",
+				i, bodyStr, test.body)
+		}
+	}
+}
+
+func headerEq(a, b Header) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for k, as := range a {
+		bs, ok := b[k]
+		if !ok {
+			return false
+		}
+		if !reflect.DeepEqual(as, bs) {
+			return false
+		}
+	}
+	return true
+}
+
+func TestDateParsing(t *testing.T) {
+	tests := []struct {
+		dateStr string
+		exp     time.Time
+	}{
+		// RFC 5322, Appendix A.1.1
+		{
+			"Fri, 21 Nov 1997 09:55:06 -0600",
+			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)),
+		},
+		// RFC5322, Appendix A.6.2
+		// Obsolete date.
+		{
+			"21 Nov 97 09:55:06 GMT",
+			time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("GMT", 0)),
+		},
+	}
+	for _, test := range tests {
+		hdr := Header{
+			"Date": []string{test.dateStr},
+		}
+		date, err := hdr.Date()
+		if err != nil {
+			t.Errorf("Failed parsing %q: %v", test.dateStr, err)
+			continue
+		}
+		if !date.Equal(test.exp) {
+			t.Errorf("Parse of %q: got %+v, want %+v", test.dateStr, date, test.exp)
+		}
+	}
+}
+
+func TestAddressParsing(t *testing.T) {
+	tests := []struct {
+		addrsStr string
+		exp      []*Address
+	}{
+		// Bare address
+		{
+			`jdoe at machine.example`,
+			[]*Address{{
+				Address: "jdoe at machine.example",
+			}},
+		},
+		// RFC 5322, Appendix A.1.1
+		{
+			`John Doe <jdoe at machine.example>`,
+			[]*Address{{
+				Name:    "John Doe",
+				Address: "jdoe at machine.example",
+			}},
+		},
+		// RFC 5322, Appendix A.1.2
+		{
+			`"Joe Q. Public" <john.q.public at example.com>`,
+			[]*Address{{
+				Name:    "Joe Q. Public",
+				Address: "john.q.public at example.com",
+			}},
+		},
+		{
+			`Mary Smith <mary at x.test>, jdoe at example.org, Who? <one at y.test>`,
+			[]*Address{
+				{
+					Name:    "Mary Smith",
+					Address: "mary at x.test",
+				},
+				{
+					Address: "jdoe at example.org",
+				},
+				{
+					Name:    "Who?",
+					Address: "one at y.test",
+				},
+			},
+		},
+		{
+			`<boss at nil.test>, "Giant; \"Big\" Box" <sysservices at example.net>`,
+			[]*Address{
+				{
+					Address: "boss at nil.test",
+				},
+				{
+					Name:    `Giant; "Big" Box`,
+					Address: "sysservices at example.net",
+				},
+			},
+		},
+		// RFC 5322, Appendix A.1.3
+		// TODO(dsymonds): Group addresses.
+
+		// RFC 2047 "Q"-encoded ISO-8859-1 address.
+		{
+			`=?iso-8859-1?q?J=F6rg_Doe?= <joerg at example.com>`,
+			[]*Address{
+				{
+					Name:    `Jörg Doe`,
+					Address: "joerg at example.com",
+				},
+			},
+		},
+		// RFC 2047 "Q"-encoded UTF-8 address.
+		{
+			`=?utf-8?q?J=C3=B6rg_Doe?= <joerg at example.com>`,
+			[]*Address{
+				{
+					Name:    `Jörg Doe`,
+					Address: "joerg at example.com",
+				},
+			},
+		},
+		// RFC 2047, Section 8.
+		{
+			`=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD at vm1.ulg.ac.be>`,
+			[]*Address{
+				{
+					Name:    `André Pirard`,
+					Address: "PIRARD at vm1.ulg.ac.be",
+				},
+			},
+		},
+		// Custom example of RFC 2047 "B"-encoded ISO-8859-1 address.
+		{
+			`=?ISO-8859-1?B?SvZyZw==?= <joerg at example.com>`,
+			[]*Address{
+				{
+					Name:    `Jörg`,
+					Address: "joerg at example.com",
+				},
+			},
+		},
+		// Custom example of RFC 2047 "B"-encoded UTF-8 address.
+		{
+			`=?UTF-8?B?SsO2cmc=?= <joerg at example.com>`,
+			[]*Address{
+				{
+					Name:    `Jörg`,
+					Address: "joerg at example.com",
+				},
+			},
+		},
+	}
+	for _, test := range tests {
+		addrs, err := newAddrParser(test.addrsStr).parseAddressList()
+		if err != nil {
+			t.Errorf("Failed parsing %q: %v", test.addrsStr, err)
+			continue
+		}
+		if !reflect.DeepEqual(addrs, test.exp) {
+			t.Errorf("Parse of %q: got %+v, want %+v", test.addrsStr, addrs, test.exp)
+		}
+	}
+}
+
+func TestAddressFormatting(t *testing.T) {
+	tests := []struct {
+		addr *Address
+		exp  string
+	}{
+		{
+			&Address{Address: "bob at example.com"},
+			"<bob at example.com>",
+		},
+		{
+			&Address{Name: "Bob", Address: "bob at example.com"},
+			`"Bob" <bob at example.com>`,
+		},
+		{
+			// note the ö (o with an umlaut)
+			&Address{Name: "Böb", Address: "bob at example.com"},
+			`=?utf-8?q?B=C3=B6b?= <bob at example.com>`,
+		},
+	}
+	for _, test := range tests {
+		s := test.addr.String()
+		if s != test.exp {
+			t.Errorf("Address%+v.String() = %v, want %v", *test.addr, s, test.exp)
+		}
+	}
+}
diff --git a/src/pkg/net/multicast_test.go b/src/pkg/net/multicast_test.go
index a66250c..183d5a8 100644
--- a/src/pkg/net/multicast_test.go
+++ b/src/pkg/net/multicast_test.go
@@ -13,7 +13,7 @@ import (
 
 var multicast = flag.Bool("multicast", false, "enable multicast tests")
 
-var joinAndLeaveGroupUDPTests = []struct {
+var multicastUDPTests = []struct {
 	net   string
 	laddr IP
 	gaddr IP
@@ -32,8 +32,8 @@ var joinAndLeaveGroupUDPTests = []struct {
 	{"udp6", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true},
 }
 
-func TestJoinAndLeaveGroupUDP(t *testing.T) {
-	if runtime.GOOS == "windows" {
+func TestMulticastUDP(t *testing.T) {
+	if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
 		return
 	}
 	if !*multicast {
@@ -41,7 +41,7 @@ func TestJoinAndLeaveGroupUDP(t *testing.T) {
 		return
 	}
 
-	for _, tt := range joinAndLeaveGroupUDPTests {
+	for _, tt := range multicastUDPTests {
 		var (
 			ifi   *Interface
 			found bool
@@ -51,7 +51,7 @@ func TestJoinAndLeaveGroupUDP(t *testing.T) {
 		}
 		ift, err := Interfaces()
 		if err != nil {
-			t.Fatalf("Interfaces() failed: %v", err)
+			t.Fatalf("Interfaces failed: %v", err)
 		}
 		for _, x := range ift {
 			if x.Flags&tt.flags == tt.flags {
@@ -65,15 +65,20 @@ func TestJoinAndLeaveGroupUDP(t *testing.T) {
 		}
 		c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr})
 		if err != nil {
-			t.Fatal(err)
+			t.Fatalf("ListenUDP failed: %v", err)
 		}
 		defer c.Close()
 		if err := c.JoinGroup(ifi, tt.gaddr); err != nil {
-			t.Fatal(err)
+			t.Fatalf("JoinGroup failed: %v", err)
+		}
+		if !tt.ipv6 {
+			testIPv4MulticastSocketOptions(t, c.fd, ifi)
+		} else {
+			testIPv6MulticastSocketOptions(t, c.fd, ifi)
 		}
 		ifmat, err := ifi.MulticastAddrs()
 		if err != nil {
-			t.Fatalf("MulticastAddrs() failed: %v", err)
+			t.Fatalf("MulticastAddrs failed: %v", err)
 		}
 		for _, ifma := range ifmat {
 			if ifma.(*IPAddr).IP.Equal(tt.gaddr) {
@@ -85,7 +90,114 @@ func TestJoinAndLeaveGroupUDP(t *testing.T) {
 			t.Fatalf("%q not found in RIB", tt.gaddr.String())
 		}
 		if err := c.LeaveGroup(ifi, tt.gaddr); err != nil {
-			t.Fatal(err)
+			t.Fatalf("LeaveGroup failed: %v", err)
+		}
+	}
+}
+
+func TestSimpleMulticastUDP(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		return
+	}
+	if !*multicast {
+		t.Logf("test disabled; use --multicast to enable")
+		return
+	}
+
+	for _, tt := range multicastUDPTests {
+		var ifi *Interface
+		if tt.ipv6 {
+			continue
+		}
+		tt.flags = FlagUp | FlagMulticast
+		ift, err := Interfaces()
+		if err != nil {
+			t.Fatalf("Interfaces failed: %v", err)
+		}
+		for _, x := range ift {
+			if x.Flags&tt.flags == tt.flags {
+				ifi = &x
+				break
+			}
+		}
+		if ifi == nil {
+			t.Logf("an appropriate multicast interface not found")
+			return
+		}
+		c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr})
+		if err != nil {
+			t.Fatalf("ListenUDP failed: %v", err)
+		}
+		defer c.Close()
+		if err := c.JoinGroup(ifi, tt.gaddr); err != nil {
+			t.Fatalf("JoinGroup failed: %v", err)
+		}
+		if err := c.LeaveGroup(ifi, tt.gaddr); err != nil {
+			t.Fatalf("LeaveGroup failed: %v", err)
 		}
 	}
 }
+
+func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
+	ifmc, err := ipv4MulticastInterface(fd)
+	if err != nil {
+		t.Fatalf("ipv4MulticastInterface failed: %v", err)
+	}
+	t.Logf("IPv4 multicast interface: %v", ifmc)
+	err = setIPv4MulticastInterface(fd, ifi)
+	if err != nil {
+		t.Fatalf("setIPv4MulticastInterface failed: %v", err)
+	}
+
+	ttl, err := ipv4MulticastTTL(fd)
+	if err != nil {
+		t.Fatalf("ipv4MulticastTTL failed: %v", err)
+	}
+	t.Logf("IPv4 multicast TTL: %v", ttl)
+	err = setIPv4MulticastTTL(fd, 1)
+	if err != nil {
+		t.Fatalf("setIPv4MulticastTTL failed: %v", err)
+	}
+
+	loop, err := ipv4MulticastLoopback(fd)
+	if err != nil {
+		t.Fatalf("ipv4MulticastLoopback failed: %v", err)
+	}
+	t.Logf("IPv4 multicast loopback: %v", loop)
+	err = setIPv4MulticastLoopback(fd, false)
+	if err != nil {
+		t.Fatalf("setIPv4MulticastLoopback failed: %v", err)
+	}
+}
+
+func testIPv6MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
+	ifmc, err := ipv6MulticastInterface(fd)
+	if err != nil {
+		t.Fatalf("ipv6MulticastInterface failed: %v", err)
+	}
+	t.Logf("IPv6 multicast interface: %v", ifmc)
+	err = setIPv6MulticastInterface(fd, ifi)
+	if err != nil {
+		t.Fatalf("setIPv6MulticastInterface failed: %v", err)
+	}
+
+	hoplim, err := ipv6MulticastHopLimit(fd)
+	if err != nil {
+		t.Fatalf("ipv6MulticastHopLimit failed: %v", err)
+	}
+	t.Logf("IPv6 multicast hop limit: %v", hoplim)
+	err = setIPv6MulticastHopLimit(fd, 1)
+	if err != nil {
+		t.Fatalf("setIPv6MulticastHopLimit failed: %v", err)
+	}
+
+	loop, err := ipv6MulticastLoopback(fd)
+	if err != nil {
+		t.Fatalf("ipv6MulticastLoopback failed: %v", err)
+	}
+	t.Logf("IPv6 multicast loopback: %v", loop)
+	err = setIPv6MulticastLoopback(fd, false)
+	if err != nil {
+		t.Fatalf("setIPv6MulticastLoopback failed: %v", err)
+	}
+}
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index 5c84d34..609fee2 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -9,7 +9,10 @@ package net
 // TODO(rsc):
 //	support for raw ethernet sockets
 
-import "os"
+import (
+	"errors"
+	"time"
+)
 
 // Addr represents a network end point address.
 type Addr interface {
@@ -21,16 +24,16 @@ type Addr interface {
 type Conn interface {
 	// Read reads data from the connection.
 	// Read can be made to time out and return a net.Error with Timeout() == true
-	// after a fixed time limit; see SetTimeout and SetReadTimeout.
-	Read(b []byte) (n int, err os.Error)
+	// after a fixed time limit; see SetDeadline and SetReadDeadline.
+	Read(b []byte) (n int, err error)
 
 	// Write writes data to the connection.
 	// Write can be made to time out and return a net.Error with Timeout() == true
-	// after a fixed time limit; see SetTimeout and SetWriteTimeout.
-	Write(b []byte) (n int, err os.Error)
+	// after a fixed time limit; see SetDeadline and SetWriteDeadline.
+	Write(b []byte) (n int, err error)
 
 	// Close closes the connection.
-	Close() os.Error
+	Close() error
 
 	// LocalAddr returns the local network address.
 	LocalAddr() Addr
@@ -38,26 +41,28 @@ type Conn interface {
 	// RemoteAddr returns the remote network address.
 	RemoteAddr() Addr
 
-	// SetTimeout sets the read and write deadlines associated
+	// SetDeadline sets the read and write deadlines associated
 	// with the connection.
-	SetTimeout(nsec int64) os.Error
-
-	// SetReadTimeout sets the time (in nanoseconds) that
-	// Read will wait for data before returning an error with Timeout() == true.
-	// Setting nsec == 0 (the default) disables the deadline.
-	SetReadTimeout(nsec int64) os.Error
-
-	// SetWriteTimeout sets the time (in nanoseconds) that
-	// Write will wait to send its data before returning an error with Timeout() == true.
-	// Setting nsec == 0 (the default) disables the deadline.
+	SetDeadline(t time.Time) error
+
+	// SetReadDeadline sets the deadline for all Read calls to return.
+	// If the deadline is reached, Read will fail with a timeout
+	// (see type Error) instead of blocking.
+	// A zero value for t means Read will not time out.
+	SetReadDeadline(t time.Time) error
+
+	// SetWriteDeadline sets the deadline for all Write calls to return.
+	// If the deadline is reached, Write will fail with a timeout
+	// (see type Error) instead of blocking.
+	// A zero value for t means Write will not time out.
 	// Even if write times out, it may return n > 0, indicating that
 	// some of the data was successfully written.
-	SetWriteTimeout(nsec int64) os.Error
+	SetWriteDeadline(t time.Time) error
 }
 
 // An Error represents a network error.
 type Error interface {
-	os.Error
+	error
 	Timeout() bool   // Is the error a timeout?
 	Temporary() bool // Is the error temporary?
 }
@@ -70,61 +75,63 @@ type PacketConn interface {
 	// was on the packet.
 	// ReadFrom can be made to time out and return
 	// an error with Timeout() == true after a fixed time limit;
-	// see SetTimeout and SetReadTimeout.
-	ReadFrom(b []byte) (n int, addr Addr, err os.Error)
+	// see SetDeadline and SetReadDeadline.
+	ReadFrom(b []byte) (n int, addr Addr, err error)
 
 	// WriteTo writes a packet with payload b to addr.
 	// WriteTo can be made to time out and return
 	// an error with Timeout() == true after a fixed time limit;
-	// see SetTimeout and SetWriteTimeout.
+	// see SetDeadline and SetWriteDeadline.
 	// On packet-oriented connections, write timeouts are rare.
-	WriteTo(b []byte, addr Addr) (n int, err os.Error)
+	WriteTo(b []byte, addr Addr) (n int, err error)
 
 	// Close closes the connection.
-	Close() os.Error
+	Close() error
 
 	// LocalAddr returns the local network address.
 	LocalAddr() Addr
 
-	// SetTimeout sets the read and write deadlines associated
+	// SetDeadline sets the read and write deadlines associated
 	// with the connection.
-	SetTimeout(nsec int64) os.Error
-
-	// SetReadTimeout sets the time (in nanoseconds) that
-	// Read will wait for data before returning an error with Timeout() == true.
-	// Setting nsec == 0 (the default) disables the deadline.
-	SetReadTimeout(nsec int64) os.Error
-
-	// SetWriteTimeout sets the time (in nanoseconds) that
-	// Write will wait to send its data before returning an error with Timeout() == true.
-	// Setting nsec == 0 (the default) disables the deadline.
+	SetDeadline(t time.Time) error
+
+	// SetReadDeadline sets the deadline for all Read calls to return.
+	// If the deadline is reached, Read will fail with a timeout
+	// (see type Error) instead of blocking.
+	// A zero value for t means Read will not time out.
+	SetReadDeadline(t time.Time) error
+
+	// SetWriteDeadline sets the deadline for all Write calls to return.
+	// If the deadline is reached, Write will fail with a timeout
+	// (see type Error) instead of blocking.
+	// A zero value for t means Write will not time out.
 	// Even if write times out, it may return n > 0, indicating that
 	// some of the data was successfully written.
-	SetWriteTimeout(nsec int64) os.Error
+	SetWriteDeadline(t time.Time) error
 }
 
 // A Listener is a generic network listener for stream-oriented protocols.
 type Listener interface {
 	// Accept waits for and returns the next connection to the listener.
-	Accept() (c Conn, err os.Error)
+	Accept() (c Conn, err error)
 
 	// Close closes the listener.
-	Close() os.Error
+	Close() error
 
 	// Addr returns the listener's network address.
 	Addr() Addr
 }
 
-var errMissingAddress = os.NewError("missing address")
+var errMissingAddress = errors.New("missing address")
 
 type OpError struct {
-	Op    string
-	Net   string
-	Addr  Addr
-	Error os.Error
+	Op   string
+	Net  string
+	Addr Addr
+	Err  error
 }
 
-func (e *OpError) String() string {
+func (e *OpError) Error() string {
 	if e == nil {
 		return "<nil>"
 	}
@@ -135,7 +142,7 @@ func (e *OpError) String() string {
 	if e.Addr != nil {
 		s += " " + e.Addr.String()
 	}
-	s += ": " + e.Error.String()
+	s += ": " + e.Err.Error()
 	return s
 }
 
@@ -144,7 +151,7 @@ type temporary interface {
 }
 
 func (e *OpError) Temporary() bool {
-	t, ok := e.Error.(temporary)
+	t, ok := e.Err.(temporary)
 	return ok && t.Temporary()
 }
 
@@ -153,20 +160,28 @@ type timeout interface {
 }
 
 func (e *OpError) Timeout() bool {
-	t, ok := e.Error.(timeout)
+	t, ok := e.Err.(timeout)
 	return ok && t.Timeout()
 }
 
+type timeoutError struct{}
+
+func (e *timeoutError) Error() string   { return "i/o timeout" }
+func (e *timeoutError) Timeout() bool   { return true }
+func (e *timeoutError) Temporary() bool { return true }
+
+var errTimeout error = &timeoutError{}
+
 type AddrError struct {
-	Error string
-	Addr  string
+	Err  string
+	Addr string
 }
 
-func (e *AddrError) String() string {
+func (e *AddrError) Error() string {
 	if e == nil {
 		return "<nil>"
 	}
-	s := e.Error
+	s := e.Err
 	if e.Addr != "" {
 		s += " " + e.Addr
 	}
@@ -183,6 +198,6 @@ func (e *AddrError) Timeout() bool {
 
 type UnknownNetworkError string
 
-func (e UnknownNetworkError) String() string  { return "unknown network " + string(e) }
+func (e UnknownNetworkError) Error() string   { return "unknown network " + string(e) }
 func (e UnknownNetworkError) Temporary() bool { return false }
 func (e UnknownNetworkError) Timeout() bool   { return false }
diff --git a/src/pkg/net/net_test.go b/src/pkg/net/net_test.go
index 698a845..0dc8669 100644
--- a/src/pkg/net/net_test.go
+++ b/src/pkg/net/net_test.go
@@ -6,7 +6,9 @@ package net
 
 import (
 	"flag"
+	"io"
 	"regexp"
+	"runtime"
 	"testing"
 )
 
@@ -61,6 +63,8 @@ var dialErrorTests = []DialErrorTest{
 	},
 }
 
+var duplicateErrorPattern = `dial (.*) dial (.*)`
+
 func TestDialError(t *testing.T) {
 	if !*runErrorTest {
 		t.Logf("test disabled; use --run_error_test to enable")
@@ -75,11 +79,15 @@ func TestDialError(t *testing.T) {
 			t.Errorf("#%d: nil error, want match for %#q", i, tt.Pattern)
 			continue
 		}
-		s := e.String()
+		s := e.Error()
 		match, _ := regexp.MatchString(tt.Pattern, s)
 		if !match {
 			t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern)
 		}
+		match, _ = regexp.MatchString(duplicateErrorPattern, s)
+		if match {
+			t.Errorf("#%d: %q, duplicate error return from Dial", i, s)
+		}
 	}
 }
 
@@ -111,11 +119,57 @@ func TestReverseAddress(t *testing.T) {
 		if len(tt.ErrPrefix) == 0 && e != nil {
 			t.Errorf("#%d: expected <nil>, got %q (error)", i, e)
 		}
-		if e != nil && e.(*DNSError).Error != tt.ErrPrefix {
-			t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, e.(*DNSError).Error)
+		if e != nil && e.(*DNSError).Err != tt.ErrPrefix {
+			t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, e.(*DNSError).Err)
 		}
 		if a != tt.Reverse {
 			t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
 		}
 	}
 }
+
+func TestShutdown(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		return
+	}
+	l, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		if l, err = Listen("tcp6", "[::1]:0"); err != nil {
+			t.Fatalf("ListenTCP on :0: %v", err)
+		}
+	}
+
+	go func() {
+		c, err := l.Accept()
+		if err != nil {
+			t.Fatalf("Accept: %v", err)
+		}
+		var buf [10]byte
+		n, err := c.Read(buf[:])
+		if n != 0 || err != io.EOF {
+			t.Fatalf("server Read = %d, %v; want 0, io.EOF", n, err)
+		}
+		c.Write([]byte("response"))
+		c.Close()
+	}()
+
+	c, err := Dial("tcp", l.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+
+	err = c.(*TCPConn).CloseWrite()
+	if err != nil {
+		t.Fatalf("CloseWrite: %v", err)
+	}
+	var buf [10]byte
+	n, err := c.Read(buf[:])
+	if err != nil {
+		t.Fatalf("client Read: %d, %v", n, err)
+	}
+	got := string(buf[:n])
+	if got != "response" {
+		t.Errorf("read = %q, want \"response\"", got)
+	}
+}
diff --git a/src/pkg/net/newpollserver.go b/src/pkg/net/newpollserver.go
index 3c9a6da..a410bb6 100644
--- a/src/pkg/net/newpollserver.go
+++ b/src/pkg/net/newpollserver.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package net
 
@@ -11,18 +11,17 @@ import (
 	"syscall"
 )
 
-func newPollServer() (s *pollServer, err os.Error) {
+func newPollServer() (s *pollServer, err error) {
 	s = new(pollServer)
 	s.cr = make(chan *netFD, 1)
 	s.cw = make(chan *netFD, 1)
 	if s.pr, s.pw, err = os.Pipe(); err != nil {
 		return nil, err
 	}
-	var e int
-	if e = syscall.SetNonblock(s.pr.Fd(), true); e != 0 {
+	if err = syscall.SetNonblock(s.pr.Fd(), true); err != nil {
 		goto Errno
 	}
-	if e = syscall.SetNonblock(s.pw.Fd(), true); e != 0 {
+	if err = syscall.SetNonblock(s.pw.Fd(), true); err != nil {
 		goto Errno
 	}
 	if s.poll, err = newpollster(); err != nil {
@@ -37,7 +36,7 @@ func newPollServer() (s *pollServer, err os.Error) {
 	return s, nil
 
 Errno:
-	err = &os.PathError{"setnonblock", s.pr.Name(), os.Errno(e)}
+	err = &os.PathError{"setnonblock", s.pr.Name(), err}
 Error:
 	s.pr.Close()
 	s.pw.Close()
diff --git a/src/pkg/net/parse.go b/src/pkg/net/parse.go
index 0d30a7a..4c4200a 100644
--- a/src/pkg/net/parse.go
+++ b/src/pkg/net/parse.go
@@ -54,7 +54,7 @@ func (f *file) readLine() (s string, ok bool) {
 		if n >= 0 {
 			f.data = f.data[0 : ln+n]
 		}
-		if err == os.EOF {
+		if err == io.EOF {
 			f.atEOF = true
 		}
 	}
@@ -62,7 +62,7 @@ func (f *file) readLine() (s string, ok bool) {
 	return
 }
 
-func open(name string) (*file, os.Error) {
+func open(name string) (*file, error) {
 	fd, err := os.Open(name)
 	if err != nil {
 		return nil, err
diff --git a/src/pkg/net/parse_test.go b/src/pkg/net/parse_test.go
index 8d51eba..dfbaba4 100644
--- a/src/pkg/net/parse_test.go
+++ b/src/pkg/net/parse_test.go
@@ -7,8 +7,8 @@ package net
 import (
 	"bufio"
 	"os"
-	"testing"
 	"runtime"
+	"testing"
 )
 
 func TestReadLine(t *testing.T) {
diff --git a/src/pkg/net/pipe.go b/src/pkg/net/pipe.go
index c0bbd35..f1a2eca 100644
--- a/src/pkg/net/pipe.go
+++ b/src/pkg/net/pipe.go
@@ -1,8 +1,13 @@
+// Copyright 2010 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 net
 
 import (
+	"errors"
 	"io"
-	"os"
+	"time"
 )
 
 // Pipe creates a synchronous, in-memory, full duplex
@@ -32,7 +37,7 @@ func (pipeAddr) String() string {
 	return "pipe"
 }
 
-func (p *pipe) Close() os.Error {
+func (p *pipe) Close() error {
 	err := p.PipeReader.Close()
 	err1 := p.PipeWriter.Close()
 	if err == nil {
@@ -49,14 +54,14 @@ func (p *pipe) RemoteAddr() Addr {
 	return pipeAddr(0)
 }
 
-func (p *pipe) SetTimeout(nsec int64) os.Error {
-	return os.NewError("net.Pipe does not support timeouts")
+func (p *pipe) SetDeadline(t time.Time) error {
+	return errors.New("net.Pipe does not support deadlines")
 }
 
-func (p *pipe) SetReadTimeout(nsec int64) os.Error {
-	return os.NewError("net.Pipe does not support timeouts")
+func (p *pipe) SetReadDeadline(t time.Time) error {
+	return errors.New("net.Pipe does not support deadlines")
 }
 
-func (p *pipe) SetWriteTimeout(nsec int64) os.Error {
-	return os.NewError("net.Pipe does not support timeouts")
+func (p *pipe) SetWriteDeadline(t time.Time) error {
+	return errors.New("net.Pipe does not support deadlines")
 }
diff --git a/src/pkg/net/pipe_test.go b/src/pkg/net/pipe_test.go
index 7e4c6db..afe4f24 100644
--- a/src/pkg/net/pipe_test.go
+++ b/src/pkg/net/pipe_test.go
@@ -7,7 +7,6 @@ package net
 import (
 	"bytes"
 	"io"
-	"os"
 	"testing"
 )
 
@@ -22,7 +21,7 @@ func checkWrite(t *testing.T, w io.Writer, data []byte, c chan int) {
 	c <- 0
 }
 
-func checkRead(t *testing.T, r io.Reader, data []byte, wantErr os.Error) {
+func checkRead(t *testing.T, r io.Reader, data []byte, wantErr error) {
 	buf := make([]byte, len(data)+10)
 	n, err := r.Read(buf)
 	if err != wantErr {
@@ -52,6 +51,6 @@ func TestPipe(t *testing.T) {
 	checkRead(t, srv, []byte("a third line"), nil)
 	<-c
 	go srv.Close()
-	checkRead(t, cli, nil, os.EOF)
+	checkRead(t, cli, nil, io.EOF)
 	cli.Close()
 }
diff --git a/src/pkg/net/port.go b/src/pkg/net/port.go
index a8ca60c..16780da 100644
--- a/src/pkg/net/port.go
+++ b/src/pkg/net/port.go
@@ -2,19 +2,16 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 // Read system port mappings from /etc/services
 
 package net
 
-import (
-	"os"
-	"sync"
-)
+import "sync"
 
 var services map[string]map[string]int
-var servicesError os.Error
+var servicesError error
 var onceReadServices sync.Once
 
 func readServices() {
@@ -53,7 +50,7 @@ func readServices() {
 }
 
 // goLookupPort is the native Go implementation of LookupPort.
-func goLookupPort(network, service string) (port int, err os.Error) {
+func goLookupPort(network, service string) (port int, err error) {
 	onceReadServices.Do(readServices)
 
 	switch network {
diff --git a/src/pkg/net/rpc/Makefile b/src/pkg/net/rpc/Makefile
new file mode 100644
index 0000000..0e6c984
--- /dev/null
+++ b/src/pkg/net/rpc/Makefile
@@ -0,0 +1,13 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=net/rpc
+GOFILES=\
+	client.go\
+	debug.go\
+	server.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/net/rpc/client.go b/src/pkg/net/rpc/client.go
new file mode 100644
index 0000000..abc1e59
--- /dev/null
+++ b/src/pkg/net/rpc/client.go
@@ -0,0 +1,288 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rpc
+
+import (
+	"bufio"
+	"encoding/gob"
+	"errors"
+	"io"
+	"log"
+	"net"
+	"net/http"
+	"sync"
+)
+
+// ServerError represents an error that has been returned from
+// the remote side of the RPC connection.
+type ServerError string
+
+func (e ServerError) Error() string {
+	return string(e)
+}
+
+var ErrShutdown = errors.New("connection is shut down")
+
+// Call represents an active RPC.
+type Call struct {
+	ServiceMethod string      // The name of the service and method to call.
+	Args          interface{} // The argument to the function (*struct).
+	Reply         interface{} // The reply from the function (*struct).
+	Error         error       // After completion, the error status.
+	Done          chan *Call  // Strobes when call is complete; value is the error status.
+	seq           uint64
+}
+
+// Client represents an RPC Client.
+// There may be multiple outstanding Calls associated
+// with a single Client.
+type Client struct {
+	mutex    sync.Mutex // protects pending, seq, request
+	sending  sync.Mutex
+	request  Request
+	seq      uint64
+	codec    ClientCodec
+	pending  map[uint64]*Call
+	closing  bool
+	shutdown bool
+}
+
+// A ClientCodec implements writing of RPC requests and
+// reading of RPC responses for the client side of an RPC session.
+// The client calls WriteRequest to write a request to the connection
+// and calls ReadResponseHeader and ReadResponseBody in pairs
+// to read responses.  The client calls Close when finished with the
+// connection. ReadResponseBody may be called with a nil
+// argument to force the body of the response to be read and then
+// discarded.
+type ClientCodec interface {
+	WriteRequest(*Request, interface{}) error
+	ReadResponseHeader(*Response) error
+	ReadResponseBody(interface{}) error
+
+	Close() error
+}
+
+func (client *Client) send(c *Call) {
+	// Register this call.
+	client.mutex.Lock()
+	if client.shutdown {
+		c.Error = ErrShutdown
+		client.mutex.Unlock()
+		c.done()
+		return
+	}
+	c.seq = client.seq
+	client.seq++
+	client.pending[c.seq] = c
+	client.mutex.Unlock()
+
+	// Encode and send the request.
+	client.sending.Lock()
+	defer client.sending.Unlock()
+	client.request.Seq = c.seq
+	client.request.ServiceMethod = c.ServiceMethod
+	if err := client.codec.WriteRequest(&client.request, c.Args); err != nil {
+		c.Error = err
+		c.done()
+	}
+}
+
+func (client *Client) input() {
+	var err error
+	var response Response
+	for err == nil {
+		response = Response{}
+		err = client.codec.ReadResponseHeader(&response)
+		if err != nil {
+			if err == io.EOF && !client.closing {
+				err = io.ErrUnexpectedEOF
+			}
+			break
+		}
+		seq := response.Seq
+		client.mutex.Lock()
+		c := client.pending[seq]
+		delete(client.pending, seq)
+		client.mutex.Unlock()
+
+		if response.Error == "" {
+			err = client.codec.ReadResponseBody(c.Reply)
+			if err != nil {
+				c.Error = errors.New("reading body " + err.Error())
+			}
+		} else {
+			// We've got an error response. Give this to the request;
+			// any subsequent requests will get the ReadResponseBody
+			// error if there is one.
+			c.Error = ServerError(response.Error)
+			err = client.codec.ReadResponseBody(nil)
+			if err != nil {
+				err = errors.New("reading error body: " + err.Error())
+			}
+		}
+		c.done()
+	}
+	// Terminate pending calls.
+	client.mutex.Lock()
+	client.shutdown = true
+	for _, call := range client.pending {
+		call.Error = err
+		call.done()
+	}
+	client.mutex.Unlock()
+	if err != io.EOF || !client.closing {
+		log.Println("rpc: client protocol error:", err)
+	}
+}
+
+func (call *Call) done() {
+	select {
+	case call.Done <- call:
+		// ok
+	default:
+		// We don't want to block here.  It is the caller's responsibility to make
+		// sure the channel has enough buffer space. See comment in Go().
+		log.Println("rpc: discarding Call reply due to insufficient Done chan capacity")
+	}
+}
+
+// NewClient returns a new Client to handle requests to the
+// set of services at the other end of the connection.
+// It adds a buffer to the write side of the connection so
+// the header and payload are sent as a unit.
+func NewClient(conn io.ReadWriteCloser) *Client {
+	encBuf := bufio.NewWriter(conn)
+	client := &gobClientCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(encBuf), encBuf}
+	return NewClientWithCodec(client)
+}
+
+// NewClientWithCodec is like NewClient but uses the specified
+// codec to encode requests and decode responses.
+func NewClientWithCodec(codec ClientCodec) *Client {
+	client := &Client{
+		codec:   codec,
+		pending: make(map[uint64]*Call),
+	}
+	go client.input()
+	return client
+}
+
+type gobClientCodec struct {
+	rwc    io.ReadWriteCloser
+	dec    *gob.Decoder
+	enc    *gob.Encoder
+	encBuf *bufio.Writer
+}
+
+func (c *gobClientCodec) WriteRequest(r *Request, body interface{}) (err error) {
+	if err = c.enc.Encode(r); err != nil {
+		return
+	}
+	if err = c.enc.Encode(body); err != nil {
+		return
+	}
+	return c.encBuf.Flush()
+}
+
+func (c *gobClientCodec) ReadResponseHeader(r *Response) error {
+	return c.dec.Decode(r)
+}
+
+func (c *gobClientCodec) ReadResponseBody(body interface{}) error {
+	return c.dec.Decode(body)
+}
+
+func (c *gobClientCodec) Close() error {
+	return c.rwc.Close()
+}
+
+// DialHTTP connects to an HTTP RPC server at the specified network address
+// listening on the default HTTP RPC path.
+func DialHTTP(network, address string) (*Client, error) {
+	return DialHTTPPath(network, address, DefaultRPCPath)
+}
+
+// DialHTTPPath connects to an HTTP RPC server 
+// at the specified network address and path.
+func DialHTTPPath(network, address, path string) (*Client, error) {
+	var err error
+	conn, err := net.Dial(network, address)
+	if err != nil {
+		return nil, err
+	}
+	io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n")
+
+	// Require successful HTTP response
+	// before switching to RPC protocol.
+	resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
+	if err == nil && resp.Status == connected {
+		return NewClient(conn), nil
+	}
+	if err == nil {
+		err = errors.New("unexpected HTTP response: " + resp.Status)
+	}
+	conn.Close()
+	return nil, &net.OpError{"dial-http", network + " " + address, nil, err}
+}
+
+// Dial connects to an RPC server at the specified network address.
+func Dial(network, address string) (*Client, error) {
+	conn, err := net.Dial(network, address)
+	if err != nil {
+		return nil, err
+	}
+	return NewClient(conn), nil
+}
+
+func (client *Client) Close() error {
+	client.mutex.Lock()
+	if client.shutdown || client.closing {
+		client.mutex.Unlock()
+		return ErrShutdown
+	}
+	client.closing = true
+	client.mutex.Unlock()
+	return client.codec.Close()
+}
+
+// Go invokes the function asynchronously.  It returns the Call structure representing
+// the invocation.  The done channel will signal when the call is complete by returning
+// the same Call object.  If done is nil, Go will allocate a new channel.
+// If non-nil, done must be buffered or Go will deliberately crash.
+func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
+	call := new(Call)
+	call.ServiceMethod = serviceMethod
+	call.Args = args
+	call.Reply = reply
+	if done == nil {
+		done = make(chan *Call, 10) // buffered.
+	} else {
+		// If caller passes done != nil, it must arrange that
+		// done has enough buffer for the number of simultaneous
+		// RPCs that will be using that channel.  If the channel
+		// is totally unbuffered, it's best not to run at all.
+		if cap(done) == 0 {
+			log.Panic("rpc: done channel is unbuffered")
+		}
+	}
+	call.Done = done
+	if client.shutdown {
+		call.Error = ErrShutdown
+		call.done()
+		return call
+	}
+	client.send(call)
+	return call
+}
+
+// Call invokes the named function, waits for it to complete, and returns its error status.
+func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error {
+	if client.shutdown {
+		return ErrShutdown
+	}
+	call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done
+	return call.Error
+}
diff --git a/src/pkg/net/rpc/debug.go b/src/pkg/net/rpc/debug.go
new file mode 100644
index 0000000..663663f
--- /dev/null
+++ b/src/pkg/net/rpc/debug.go
@@ -0,0 +1,90 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rpc
+
+/*
+	Some HTML presented at http://machine:port/debug/rpc
+	Lists services, their methods, and some statistics, still rudimentary.
+*/
+
+import (
+	"fmt"
+	"net/http"
+	"sort"
+	"text/template"
+)
+
+const debugText = `<html>
+	<body>
+	<title>Services</title>
+	{{range .}}
+	<hr>
+	Service {{.Name}}
+	<hr>
+		<table>
+		<th align=center>Method</th><th align=center>Calls</th>
+		{{range .Method}}
+			<tr>
+			<td align=left font=fixed>{{.Name}}({{.Type.ArgType}}, {{.Type.ReplyType}}) error</td>
+			<td align=center>{{.Type.NumCalls}}</td>
+			</tr>
+		{{end}}
+		</table>
+	{{end}}
+	</body>
+	</html>`
+
+var debug = template.Must(template.New("RPC debug").Parse(debugText))
+
+type debugMethod struct {
+	Type *methodType
+	Name string
+}
+
+type methodArray []debugMethod
+
+type debugService struct {
+	Service *service
+	Name    string
+	Method  methodArray
+}
+
+type serviceArray []debugService
+
+func (s serviceArray) Len() int           { return len(s) }
+func (s serviceArray) Less(i, j int) bool { return s[i].Name < s[j].Name }
+func (s serviceArray) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+
+func (m methodArray) Len() int           { return len(m) }
+func (m methodArray) Less(i, j int) bool { return m[i].Name < m[j].Name }
+func (m methodArray) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
+
+type debugHTTP struct {
+	*Server
+}
+
+// Runs at /debug/rpc
+func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	// Build a sorted version of the data.
+	var services = make(serviceArray, len(server.serviceMap))
+	i := 0
+	server.mu.Lock()
+	for sname, service := range server.serviceMap {
+		services[i] = debugService{service, sname, make(methodArray, len(service.method))}
+		j := 0
+		for mname, method := range service.method {
+			services[i].Method[j] = debugMethod{method, mname}
+			j++
+		}
+		sort.Sort(services[i].Method)
+		i++
+	}
+	server.mu.Unlock()
+	sort.Sort(services)
+	err := debug.Execute(w, services)
+	if err != nil {
+		fmt.Fprintln(w, "rpc: error executing template:", err.Error())
+	}
+}
diff --git a/src/pkg/net/rpc/jsonrpc/Makefile b/src/pkg/net/rpc/jsonrpc/Makefile
new file mode 100644
index 0000000..c5ea537
--- /dev/null
+++ b/src/pkg/net/rpc/jsonrpc/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2010 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../../Make.inc
+
+TARG=net/rpc/jsonrpc
+GOFILES=\
+	client.go\
+	server.go\
+
+include ../../../../Make.pkg
diff --git a/src/pkg/net/rpc/jsonrpc/all_test.go b/src/pkg/net/rpc/jsonrpc/all_test.go
new file mode 100644
index 0000000..e6c7441
--- /dev/null
+++ b/src/pkg/net/rpc/jsonrpc/all_test.go
@@ -0,0 +1,221 @@
+// Copyright 2010 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 jsonrpc
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"net/rpc"
+	"testing"
+)
+
+type Args struct {
+	A, B int
+}
+
+type Reply struct {
+	C int
+}
+
+type Arith int
+
+func (t *Arith) Add(args *Args, reply *Reply) error {
+	reply.C = args.A + args.B
+	return nil
+}
+
+func (t *Arith) Mul(args *Args, reply *Reply) error {
+	reply.C = args.A * args.B
+	return nil
+}
+
+func (t *Arith) Div(args *Args, reply *Reply) error {
+	if args.B == 0 {
+		return errors.New("divide by zero")
+	}
+	reply.C = args.A / args.B
+	return nil
+}
+
+func (t *Arith) Error(args *Args, reply *Reply) error {
+	panic("ERROR")
+}
+
+func init() {
+	rpc.Register(new(Arith))
+}
+
+func TestServer(t *testing.T) {
+	type addResp struct {
+		Id     interface{} `json:"id"`
+		Result Reply       `json:"result"`
+		Error  interface{} `json:"error"`
+	}
+
+	cli, srv := net.Pipe()
+	defer cli.Close()
+	go ServeConn(srv)
+	dec := json.NewDecoder(cli)
+
+	// Send hand-coded requests to server, parse responses.
+	for i := 0; i < 10; i++ {
+		fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i, i, i+1)
+		var resp addResp
+		err := dec.Decode(&resp)
+		if err != nil {
+			t.Fatalf("Decode: %s", err)
+		}
+		if resp.Error != nil {
+			t.Fatalf("resp.Error: %s", resp.Error)
+		}
+		if resp.Id.(string) != string(i) {
+			t.Fatalf("resp: bad id %q want %q", resp.Id.(string), string(i))
+		}
+		if resp.Result.C != 2*i+1 {
+			t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
+		}
+	}
+
+	fmt.Fprintf(cli, "{}\n")
+	var resp addResp
+	if err := dec.Decode(&resp); err != nil {
+		t.Fatalf("Decode after empty: %s", err)
+	}
+	if resp.Error == nil {
+		t.Fatalf("Expected error, got nil")
+	}
+}
+
+func TestClient(t *testing.T) {
+	// Assume server is okay (TestServer is above).
+	// Test client against server.
+	cli, srv := net.Pipe()
+	go ServeConn(srv)
+
+	client := NewClient(cli)
+	defer client.Close()
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err := client.Call("Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+
+	args = &Args{7, 8}
+	reply = new(Reply)
+	err = client.Call("Arith.Mul", args, reply)
+	if err != nil {
+		t.Errorf("Mul: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A*args.B {
+		t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
+	}
+
+	// Out of order.
+	args = &Args{7, 8}
+	mulReply := new(Reply)
+	mulCall := client.Go("Arith.Mul", args, mulReply, nil)
+	addReply := new(Reply)
+	addCall := client.Go("Arith.Add", args, addReply, nil)
+
+	addCall = <-addCall.Done
+	if addCall.Error != nil {
+		t.Errorf("Add: expected no error but got string %q", addCall.Error.Error())
+	}
+	if addReply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
+	}
+
+	mulCall = <-mulCall.Done
+	if mulCall.Error != nil {
+		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error())
+	}
+	if mulReply.C != args.A*args.B {
+		t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
+	}
+
+	// Error test
+	args = &Args{7, 0}
+	reply = new(Reply)
+	err = client.Call("Arith.Div", args, reply)
+	// expect an error: zero divide
+	if err == nil {
+		t.Error("Div: expected error")
+	} else if err.Error() != "divide by zero" {
+		t.Error("Div: expected divide by zero error; got", err)
+	}
+}
+
+func TestMalformedInput(t *testing.T) {
+	cli, srv := net.Pipe()
+	go cli.Write([]byte(`{id:1}`)) // invalid json
+	ServeConn(srv)                 // must return, not loop
+}
+
+func TestUnexpectedError(t *testing.T) {
+	cli, srv := myPipe()
+	go cli.PipeWriter.CloseWithError(errors.New("unexpected error!")) // reader will get this error
+	ServeConn(srv)                                                    // must return, not loop
+}
+
+// Copied from package net.
+func myPipe() (*pipe, *pipe) {
+	r1, w1 := io.Pipe()
+	r2, w2 := io.Pipe()
+
+	return &pipe{r1, w2}, &pipe{r2, w1}
+}
+
+type pipe struct {
+	*io.PipeReader
+	*io.PipeWriter
+}
+
+type pipeAddr int
+
+func (pipeAddr) Network() string {
+	return "pipe"
+}
+
+func (pipeAddr) String() string {
+	return "pipe"
+}
+
+func (p *pipe) Close() error {
+	err := p.PipeReader.Close()
+	err1 := p.PipeWriter.Close()
+	if err == nil {
+		err = err1
+	}
+	return err
+}
+
+func (p *pipe) LocalAddr() net.Addr {
+	return pipeAddr(0)
+}
+
+func (p *pipe) RemoteAddr() net.Addr {
+	return pipeAddr(0)
+}
+
+func (p *pipe) SetTimeout(nsec int64) error {
+	return errors.New("net.Pipe does not support timeouts")
+}
+
+func (p *pipe) SetReadTimeout(nsec int64) error {
+	return errors.New("net.Pipe does not support timeouts")
+}
+
+func (p *pipe) SetWriteTimeout(nsec int64) error {
+	return errors.New("net.Pipe does not support timeouts")
+}
diff --git a/src/pkg/net/rpc/jsonrpc/client.go b/src/pkg/net/rpc/jsonrpc/client.go
new file mode 100644
index 0000000..3fa8cbf
--- /dev/null
+++ b/src/pkg/net/rpc/jsonrpc/client.go
@@ -0,0 +1,123 @@
+// Copyright 2010 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 jsonrpc implements a JSON-RPC ClientCodec and ServerCodec
+// for the rpc package.
+package jsonrpc
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"net"
+	"net/rpc"
+	"sync"
+)
+
+type clientCodec struct {
+	dec *json.Decoder // for reading JSON values
+	enc *json.Encoder // for writing JSON values
+	c   io.Closer
+
+	// temporary work space
+	req  clientRequest
+	resp clientResponse
+
+	// JSON-RPC responses include the request id but not the request method.
+	// Package rpc expects both.
+	// We save the request method in pending when sending a request
+	// and then look it up by request ID when filling out the rpc Response.
+	mutex   sync.Mutex        // protects pending
+	pending map[uint64]string // map request id to method name
+}
+
+// NewClientCodec returns a new rpc.ClientCodec using JSON-RPC on conn.
+func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec {
+	return &clientCodec{
+		dec:     json.NewDecoder(conn),
+		enc:     json.NewEncoder(conn),
+		c:       conn,
+		pending: make(map[uint64]string),
+	}
+}
+
+type clientRequest struct {
+	Method string         `json:"method"`
+	Params [1]interface{} `json:"params"`
+	Id     uint64         `json:"id"`
+}
+
+func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) error {
+	c.mutex.Lock()
+	c.pending[r.Seq] = r.ServiceMethod
+	c.mutex.Unlock()
+	c.req.Method = r.ServiceMethod
+	c.req.Params[0] = param
+	c.req.Id = r.Seq
+	return c.enc.Encode(&c.req)
+}
+
+type clientResponse struct {
+	Id     uint64           `json:"id"`
+	Result *json.RawMessage `json:"result"`
+	Error  interface{}      `json:"error"`
+}
+
+func (r *clientResponse) reset() {
+	r.Id = 0
+	r.Result = nil
+	r.Error = nil
+}
+
+func (c *clientCodec) ReadResponseHeader(r *rpc.Response) error {
+	c.resp.reset()
+	if err := c.dec.Decode(&c.resp); err != nil {
+		return err
+	}
+
+	c.mutex.Lock()
+	r.ServiceMethod = c.pending[c.resp.Id]
+	delete(c.pending, c.resp.Id)
+	c.mutex.Unlock()
+
+	r.Error = ""
+	r.Seq = c.resp.Id
+	if c.resp.Error != nil {
+		x, ok := c.resp.Error.(string)
+		if !ok {
+			return fmt.Errorf("invalid error %v", c.resp.Error)
+		}
+		if x == "" {
+			x = "unspecified error"
+		}
+		r.Error = x
+	}
+	return nil
+}
+
+func (c *clientCodec) ReadResponseBody(x interface{}) error {
+	if x == nil {
+		return nil
+	}
+	return json.Unmarshal(*c.resp.Result, x)
+}
+
+func (c *clientCodec) Close() error {
+	return c.c.Close()
+}
+
+// NewClient returns a new rpc.Client to handle requests to the
+// set of services at the other end of the connection.
+func NewClient(conn io.ReadWriteCloser) *rpc.Client {
+	return rpc.NewClientWithCodec(NewClientCodec(conn))
+}
+
+// Dial connects to a JSON-RPC server at the specified network address.
+func Dial(network, address string) (*rpc.Client, error) {
+	conn, err := net.Dial(network, address)
+	if err != nil {
+		return nil, err
+	}
+	return NewClient(conn), err
+}
diff --git a/src/pkg/net/rpc/jsonrpc/server.go b/src/pkg/net/rpc/jsonrpc/server.go
new file mode 100644
index 0000000..4c54553
--- /dev/null
+++ b/src/pkg/net/rpc/jsonrpc/server.go
@@ -0,0 +1,136 @@
+// Copyright 2010 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 jsonrpc
+
+import (
+	"encoding/json"
+	"errors"
+	"io"
+	"net/rpc"
+	"sync"
+)
+
+type serverCodec struct {
+	dec *json.Decoder // for reading JSON values
+	enc *json.Encoder // for writing JSON values
+	c   io.Closer
+
+	// temporary work space
+	req  serverRequest
+	resp serverResponse
+
+	// JSON-RPC clients can use arbitrary json values as request IDs.
+	// Package rpc expects uint64 request IDs.
+	// We assign uint64 sequence numbers to incoming requests
+	// but save the original request ID in the pending map.
+	// When rpc responds, we use the sequence number in
+	// the response to find the original request ID.
+	mutex   sync.Mutex // protects seq, pending
+	seq     uint64
+	pending map[uint64]*json.RawMessage
+}
+
+// NewServerCodec returns a new rpc.ServerCodec using JSON-RPC on conn.
+func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {
+	return &serverCodec{
+		dec:     json.NewDecoder(conn),
+		enc:     json.NewEncoder(conn),
+		c:       conn,
+		pending: make(map[uint64]*json.RawMessage),
+	}
+}
+
+type serverRequest struct {
+	Method string           `json:"method"`
+	Params *json.RawMessage `json:"params"`
+	Id     *json.RawMessage `json:"id"`
+}
+
+func (r *serverRequest) reset() {
+	r.Method = ""
+	if r.Params != nil {
+		*r.Params = (*r.Params)[0:0]
+	}
+	if r.Id != nil {
+		*r.Id = (*r.Id)[0:0]
+	}
+}
+
+type serverResponse struct {
+	Id     *json.RawMessage `json:"id"`
+	Result interface{}      `json:"result"`
+	Error  interface{}      `json:"error"`
+}
+
+func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error {
+	c.req.reset()
+	if err := c.dec.Decode(&c.req); err != nil {
+		return err
+	}
+	r.ServiceMethod = c.req.Method
+
+	// JSON request id can be any JSON value;
+	// RPC package expects uint64.  Translate to
+	// internal uint64 and save JSON on the side.
+	c.mutex.Lock()
+	c.seq++
+	c.pending[c.seq] = c.req.Id
+	c.req.Id = nil
+	r.Seq = c.seq
+	c.mutex.Unlock()
+
+	return nil
+}
+
+func (c *serverCodec) ReadRequestBody(x interface{}) error {
+	if x == nil {
+		return nil
+	}
+	// JSON params is array value.
+	// RPC params is struct.
+	// Unmarshal into array containing struct for now.
+	// Should think about making RPC more general.
+	var params [1]interface{}
+	params[0] = x
+	return json.Unmarshal(*c.req.Params, &params)
+}
+
+var null = json.RawMessage([]byte("null"))
+
+func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error {
+	var resp serverResponse
+	c.mutex.Lock()
+	b, ok := c.pending[r.Seq]
+	if !ok {
+		c.mutex.Unlock()
+		return errors.New("invalid sequence number in response")
+	}
+	delete(c.pending, r.Seq)
+	c.mutex.Unlock()
+
+	if b == nil {
+		// Invalid request so no id.  Use JSON null.
+		b = &null
+	}
+	resp.Id = b
+	resp.Result = x
+	if r.Error == "" {
+		resp.Error = nil
+	} else {
+		resp.Error = r.Error
+	}
+	return c.enc.Encode(resp)
+}
+
+func (c *serverCodec) Close() error {
+	return c.c.Close()
+}
+
+// ServeConn runs the JSON-RPC server on a single connection.
+// ServeConn blocks, serving the connection until the client hangs up.
+// The caller typically invokes ServeConn in a go statement.
+func ServeConn(conn io.ReadWriteCloser) {
+	rpc.ServeCodec(NewServerCodec(conn))
+}
diff --git a/src/pkg/net/rpc/server.go b/src/pkg/net/rpc/server.go
new file mode 100644
index 0000000..920ae91
--- /dev/null
+++ b/src/pkg/net/rpc/server.go
@@ -0,0 +1,640 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+	Package rpc provides access to the exported methods of an object across a
+	network or other I/O connection.  A server registers an object, making it visible
+	as a service with the name of the type of the object.  After registration, exported
+	methods of the object will be accessible remotely.  A server may register multiple
+	objects (services) of different types but it is an error to register multiple
+	objects of the same type.
+
+	Only methods that satisfy these criteria will be made available for remote access;
+	other methods will be ignored:
+
+		- the method name is exported, that is, begins with an upper case letter.
+		- the method receiver is exported or local (defined in the package
+		  registering the service).
+		- the method has two arguments, both exported or local types.
+		- the method's second argument is a pointer.
+		- the method has return type error.
+
+	The method's first argument represents the arguments provided by the caller; the
+	second argument represents the result parameters to be returned to the caller.
+	The method's return value, if non-nil, is passed back as a string that the client
+	sees as if created by errors.New.
+
+	The server may handle requests on a single connection by calling ServeConn.  More
+	typically it will create a network listener and call Accept or, for an HTTP
+	listener, HandleHTTP and http.Serve.
+
+	A client wishing to use the service establishes a connection and then invokes
+	NewClient on the connection.  The convenience function Dial (DialHTTP) performs
+	both steps for a raw network connection (an HTTP connection).  The resulting
+	Client object has two methods, Call and Go, that specify the service and method to
+	call, a pointer containing the arguments, and a pointer to receive the result
+	parameters.
+
+	Call waits for the remote call to complete; Go launches the call asynchronously
+	and returns a channel that will signal completion.
+
+	Package "gob" is used to transport the data.
+
+	Here is a simple example.  A server wishes to export an object of type Arith:
+
+		package server
+
+		type Args struct {
+			A, B int
+		}
+
+		type Quotient struct {
+			Quo, Rem int
+		}
+
+		type Arith int
+
+		func (t *Arith) Multiply(args *Args, reply *int) error {
+			*reply = args.A * args.B
+			return nil
+		}
+
+		func (t *Arith) Divide(args *Args, quo *Quotient) error {
+			if args.B == 0 {
+				return errors.New("divide by zero")
+			}
+			quo.Quo = args.A / args.B
+			quo.Rem = args.A % args.B
+			return nil
+		}
+
+	The server calls (for HTTP service):
+
+		arith := new(Arith)
+		rpc.Register(arith)
+		rpc.HandleHTTP()
+		l, e := net.Listen("tcp", ":1234")
+		if e != nil {
+			log.Fatal("listen error:", e)
+		}
+		go http.Serve(l, nil)
+
+	At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
+	"Arith.Divide".  To invoke one, a client first dials the server:
+
+		client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
+		if err != nil {
+			log.Fatal("dialing:", err)
+		}
+
+	Then it can make a remote call:
+
+		// Synchronous call
+		args := &server.Args{7,8}
+		var reply int
+		err = client.Call("Arith.Multiply", args, &reply)
+		if err != nil {
+			log.Fatal("arith error:", err)
+		}
+		fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
+
+	or
+
+		// Asynchronous call
+		quotient := new(Quotient)
+		divCall := client.Go("Arith.Divide", args, &quotient, nil)
+		replyCall := <-divCall.Done	// will be equal to divCall
+		// check errors, print, etc.
+
+	A server implementation will often provide a simple, type-safe wrapper for the
+	client.
+*/
+package rpc
+
+import (
+	"bufio"
+	"encoding/gob"
+	"errors"
+	"io"
+	"log"
+	"net"
+	"net/http"
+	"reflect"
+	"strings"
+	"sync"
+	"unicode"
+	"unicode/utf8"
+)
+
+const (
+	// Defaults used by HandleHTTP
+	DefaultRPCPath   = "/_goRPC_"
+	DefaultDebugPath = "/debug/rpc"
+)
+
+// Precompute the reflect type for error.  Can't use error directly
+// because Typeof takes an empty interface value.  This is annoying.
+var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
+
+type methodType struct {
+	sync.Mutex // protects counters
+	method     reflect.Method
+	ArgType    reflect.Type
+	ReplyType  reflect.Type
+	numCalls   uint
+}
+
+type service struct {
+	name   string                 // name of service
+	rcvr   reflect.Value          // receiver of methods for the service
+	typ    reflect.Type           // type of the receiver
+	method map[string]*methodType // registered methods
+}
+
+// Request is a header written before every RPC call.  It is used internally
+// but documented here as an aid to debugging, such as when analyzing
+// network traffic.
+type Request struct {
+	ServiceMethod string   // format: "Service.Method"
+	Seq           uint64   // sequence number chosen by client
+	next          *Request // for free list in Server
+}
+
+// Response is a header written before every RPC return.  It is used internally
+// but documented here as an aid to debugging, such as when analyzing
+// network traffic.
+type Response struct {
+	ServiceMethod string    // echoes that of the Request
+	Seq           uint64    // echoes that of the request
+	Error         string    // error, if any.
+	next          *Response // for free list in Server
+}
+
+// Server represents an RPC Server.
+type Server struct {
+	mu         sync.Mutex // protects the serviceMap
+	serviceMap map[string]*service
+	reqLock    sync.Mutex // protects freeReq
+	freeReq    *Request
+	respLock   sync.Mutex // protects freeResp
+	freeResp   *Response
+}
+
+// NewServer returns a new Server.
+func NewServer() *Server {
+	return &Server{serviceMap: make(map[string]*service)}
+}
+
+// DefaultServer is the default instance of *Server.
+var DefaultServer = NewServer()
+
+// Is this an exported - upper case - name?
+func isExported(name string) bool {
+	rune, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(rune)
+}
+
+// Is this type exported or a builtin?
+func isExportedOrBuiltinType(t reflect.Type) bool {
+	for t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+	// PkgPath will be non-empty even for an exported type,
+	// so we need to check the type name as well.
+	return isExported(t.Name()) || t.PkgPath() == ""
+}
+
+// Register publishes in the server the set of methods of the
+// receiver value that satisfy the following conditions:
+//	- exported method
+//	- two arguments, both pointers to exported structs
+//	- one return value, of type error
+// It returns an error if the receiver is not an exported type or has no
+// suitable methods.
+// The client accesses each method using a string of the form "Type.Method",
+// where Type is the receiver's concrete type.
+func (server *Server) Register(rcvr interface{}) error {
+	return server.register(rcvr, "", false)
+}
+
+// RegisterName is like Register but uses the provided name for the type 
+// instead of the receiver's concrete type.
+func (server *Server) RegisterName(name string, rcvr interface{}) error {
+	return server.register(rcvr, name, true)
+}
+
+func (server *Server) register(rcvr interface{}, name string, useName bool) error {
+	server.mu.Lock()
+	defer server.mu.Unlock()
+	if server.serviceMap == nil {
+		server.serviceMap = make(map[string]*service)
+	}
+	s := new(service)
+	s.typ = reflect.TypeOf(rcvr)
+	s.rcvr = reflect.ValueOf(rcvr)
+	sname := reflect.Indirect(s.rcvr).Type().Name()
+	if useName {
+		sname = name
+	}
+	if sname == "" {
+		log.Fatal("rpc: no service name for type", s.typ.String())
+	}
+	if !isExported(sname) && !useName {
+		s := "rpc Register: type " + sname + " is not exported"
+		log.Print(s)
+		return errors.New(s)
+	}
+	if _, present := server.serviceMap[sname]; present {
+		return errors.New("rpc: service already defined: " + sname)
+	}
+	s.name = sname
+	s.method = make(map[string]*methodType)
+
+	// Install the methods
+	for m := 0; m < s.typ.NumMethod(); m++ {
+		method := s.typ.Method(m)
+		mtype := method.Type
+		mname := method.Name
+		if method.PkgPath != "" {
+			continue
+		}
+		// Method needs three ins: receiver, *args, *reply.
+		if mtype.NumIn() != 3 {
+			log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
+			continue
+		}
+		// First arg need not be a pointer.
+		argType := mtype.In(1)
+		if !isExportedOrBuiltinType(argType) {
+			log.Println(mname, "argument type not exported or local:", argType)
+			continue
+		}
+		// Second arg must be a pointer.
+		replyType := mtype.In(2)
+		if replyType.Kind() != reflect.Ptr {
+			log.Println("method", mname, "reply type not a pointer:", replyType)
+			continue
+		}
+		if !isExportedOrBuiltinType(replyType) {
+			log.Println("method", mname, "reply type not exported or local:", replyType)
+			continue
+		}
+		// Method needs one out: error.
+		if mtype.NumOut() != 1 {
+			log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
+			continue
+		}
+		if returnType := mtype.Out(0); returnType != typeOfError {
+			log.Println("method", mname, "returns", returnType.String(), "not error")
+			continue
+		}
+		s.method[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
+	}
+
+	if len(s.method) == 0 {
+		s := "rpc Register: type " + sname + " has no exported methods of suitable type"
+		log.Print(s)
+		return errors.New(s)
+	}
+	server.serviceMap[s.name] = s
+	return nil
+}
+
+// A value sent as a placeholder for the response when the server receives an invalid request.
+type InvalidRequest struct{}
+
+var invalidRequest = InvalidRequest{}
+
+func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
+	resp := server.getResponse()
+	// Encode the response header
+	resp.ServiceMethod = req.ServiceMethod
+	if errmsg != "" {
+		resp.Error = errmsg
+		reply = invalidRequest
+	}
+	resp.Seq = req.Seq
+	sending.Lock()
+	err := codec.WriteResponse(resp, reply)
+	if err != nil {
+		log.Println("rpc: writing response:", err)
+	}
+	sending.Unlock()
+	server.freeResponse(resp)
+}
+
+func (m *methodType) NumCalls() (n uint) {
+	m.Lock()
+	n = m.numCalls
+	m.Unlock()
+	return n
+}
+
+func (s *service) call(server *Server, sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
+	mtype.Lock()
+	mtype.numCalls++
+	mtype.Unlock()
+	function := mtype.method.Func
+	// Invoke the method, providing a new value for the reply.
+	returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
+	// The return value for the method is an error.
+	errInter := returnValues[0].Interface()
+	errmsg := ""
+	if errInter != nil {
+		errmsg = errInter.(error).Error()
+	}
+	server.sendResponse(sending, req, replyv.Interface(), codec, errmsg)
+	server.freeRequest(req)
+}
+
+type gobServerCodec struct {
+	rwc    io.ReadWriteCloser
+	dec    *gob.Decoder
+	enc    *gob.Encoder
+	encBuf *bufio.Writer
+}
+
+func (c *gobServerCodec) ReadRequestHeader(r *Request) error {
+	return c.dec.Decode(r)
+}
+
+func (c *gobServerCodec) ReadRequestBody(body interface{}) error {
+	return c.dec.Decode(body)
+}
+
+func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err error) {
+	if err = c.enc.Encode(r); err != nil {
+		return
+	}
+	if err = c.enc.Encode(body); err != nil {
+		return
+	}
+	return c.encBuf.Flush()
+}
+
+func (c *gobServerCodec) Close() error {
+	return c.rwc.Close()
+}
+
+// ServeConn runs the server on a single connection.
+// ServeConn blocks, serving the connection until the client hangs up.
+// The caller typically invokes ServeConn in a go statement.
+// ServeConn uses the gob wire format (see package gob) on the
+// connection.  To use an alternate codec, use ServeCodec.
+func (server *Server) ServeConn(conn io.ReadWriteCloser) {
+	buf := bufio.NewWriter(conn)
+	srv := &gobServerCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(buf), buf}
+	server.ServeCodec(srv)
+}
+
+// ServeCodec is like ServeConn but uses the specified codec to
+// decode requests and encode responses.
+func (server *Server) ServeCodec(codec ServerCodec) {
+	sending := new(sync.Mutex)
+	for {
+		service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
+		if err != nil {
+			if err != io.EOF {
+				log.Println("rpc:", err)
+			}
+			if !keepReading {
+				break
+			}
+			// send a response if we actually managed to read a header.
+			if req != nil {
+				server.sendResponse(sending, req, invalidRequest, codec, err.Error())
+				server.freeRequest(req)
+			}
+			continue
+		}
+		go service.call(server, sending, mtype, req, argv, replyv, codec)
+	}
+	codec.Close()
+}
+
+// ServeRequest is like ServeCodec but synchronously serves a single request.
+// It does not close the codec upon completion.
+func (server *Server) ServeRequest(codec ServerCodec) error {
+	sending := new(sync.Mutex)
+	service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
+	if err != nil {
+		if !keepReading {
+			return err
+		}
+		// send a response if we actually managed to read a header.
+		if req != nil {
+			server.sendResponse(sending, req, invalidRequest, codec, err.Error())
+			server.freeRequest(req)
+		}
+		return err
+	}
+	service.call(server, sending, mtype, req, argv, replyv, codec)
+	return nil
+}
+
+func (server *Server) getRequest() *Request {
+	server.reqLock.Lock()
+	req := server.freeReq
+	if req == nil {
+		req = new(Request)
+	} else {
+		server.freeReq = req.next
+		*req = Request{}
+	}
+	server.reqLock.Unlock()
+	return req
+}
+
+func (server *Server) freeRequest(req *Request) {
+	server.reqLock.Lock()
+	req.next = server.freeReq
+	server.freeReq = req
+	server.reqLock.Unlock()
+}
+
+func (server *Server) getResponse() *Response {
+	server.respLock.Lock()
+	resp := server.freeResp
+	if resp == nil {
+		resp = new(Response)
+	} else {
+		server.freeResp = resp.next
+		*resp = Response{}
+	}
+	server.respLock.Unlock()
+	return resp
+}
+
+func (server *Server) freeResponse(resp *Response) {
+	server.respLock.Lock()
+	resp.next = server.freeResp
+	server.freeResp = resp
+	server.respLock.Unlock()
+}
+
+func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, keepReading bool, err error) {
+	service, mtype, req, keepReading, err = server.readRequestHeader(codec)
+	if err != nil {
+		if !keepReading {
+			return
+		}
+		// discard body
+		codec.ReadRequestBody(nil)
+		return
+	}
+
+	// Decode the argument value.
+	argIsValue := false // if true, need to indirect before calling.
+	if mtype.ArgType.Kind() == reflect.Ptr {
+		argv = reflect.New(mtype.ArgType.Elem())
+	} else {
+		argv = reflect.New(mtype.ArgType)
+		argIsValue = true
+	}
+	// argv guaranteed to be a pointer now.
+	if err = codec.ReadRequestBody(argv.Interface()); err != nil {
+		return
+	}
+	if argIsValue {
+		argv = argv.Elem()
+	}
+
+	replyv = reflect.New(mtype.ReplyType.Elem())
+	return
+}
+
+func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, keepReading bool, err error) {
+	// Grab the request header.
+	req = server.getRequest()
+	err = codec.ReadRequestHeader(req)
+	if err != nil {
+		req = nil
+		if err == io.EOF || err == io.ErrUnexpectedEOF {
+			return
+		}
+		err = errors.New("rpc: server cannot decode request: " + err.Error())
+		return
+	}
+
+	// We read the header successfully.  If we see an error now,
+	// we can still recover and move on to the next request.
+	keepReading = true
+
+	serviceMethod := strings.Split(req.ServiceMethod, ".")
+	if len(serviceMethod) != 2 {
+		err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod)
+		return
+	}
+	// Look up the request.
+	server.mu.Lock()
+	service = server.serviceMap[serviceMethod[0]]
+	server.mu.Unlock()
+	if service == nil {
+		err = errors.New("rpc: can't find service " + req.ServiceMethod)
+		return
+	}
+	mtype = service.method[serviceMethod[1]]
+	if mtype == nil {
+		err = errors.New("rpc: can't find method " + req.ServiceMethod)
+	}
+	return
+}
+
+// Accept accepts connections on the listener and serves requests
+// for each incoming connection.  Accept blocks; the caller typically
+// invokes it in a go statement.
+func (server *Server) Accept(lis net.Listener) {
+	for {
+		conn, err := lis.Accept()
+		if err != nil {
+			log.Fatal("rpc.Serve: accept:", err.Error()) // TODO(r): exit?
+		}
+		go server.ServeConn(conn)
+	}
+}
+
+// Register publishes the receiver's methods in the DefaultServer.
+func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }
+
+// RegisterName is like Register but uses the provided name for the type 
+// instead of the receiver's concrete type.
+func RegisterName(name string, rcvr interface{}) error {
+	return DefaultServer.RegisterName(name, rcvr)
+}
+
+// A ServerCodec implements reading of RPC requests and writing of
+// RPC responses for the server side of an RPC session.
+// The server calls ReadRequestHeader and ReadRequestBody in pairs
+// to read requests from the connection, and it calls WriteResponse to
+// write a response back.  The server calls Close when finished with the
+// connection. ReadRequestBody may be called with a nil
+// argument to force the body of the request to be read and discarded.
+type ServerCodec interface {
+	ReadRequestHeader(*Request) error
+	ReadRequestBody(interface{}) error
+	WriteResponse(*Response, interface{}) error
+
+	Close() error
+}
+
+// ServeConn runs the DefaultServer on a single connection.
+// ServeConn blocks, serving the connection until the client hangs up.
+// The caller typically invokes ServeConn in a go statement.
+// ServeConn uses the gob wire format (see package gob) on the
+// connection.  To use an alternate codec, use ServeCodec.
+func ServeConn(conn io.ReadWriteCloser) {
+	DefaultServer.ServeConn(conn)
+}
+
+// ServeCodec is like ServeConn but uses the specified codec to
+// decode requests and encode responses.
+func ServeCodec(codec ServerCodec) {
+	DefaultServer.ServeCodec(codec)
+}
+
+// ServeRequest is like ServeCodec but synchronously serves a single request.
+// It does not close the codec upon completion.
+func ServeRequest(codec ServerCodec) error {
+	return DefaultServer.ServeRequest(codec)
+}
+
+// Accept accepts connections on the listener and serves requests
+// to DefaultServer for each incoming connection.  
+// Accept blocks; the caller typically invokes it in a go statement.
+func Accept(lis net.Listener) { DefaultServer.Accept(lis) }
+
+// Can connect to RPC service using HTTP CONNECT to rpcPath.
+var connected = "200 Connected to Go RPC"
+
+// ServeHTTP implements an http.Handler that answers RPC requests.
+func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	if req.Method != "CONNECT" {
+		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+		w.WriteHeader(http.StatusMethodNotAllowed)
+		io.WriteString(w, "405 must CONNECT\n")
+		return
+	}
+	conn, _, err := w.(http.Hijacker).Hijack()
+	if err != nil {
+		log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error())
+		return
+	}
+	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
+	server.ServeConn(conn)
+}
+
+// HandleHTTP registers an HTTP handler for RPC messages on rpcPath,
+// and a debugging handler on debugPath.
+// It is still necessary to invoke http.Serve(), typically in a go statement.
+func (server *Server) HandleHTTP(rpcPath, debugPath string) {
+	http.Handle(rpcPath, server)
+	http.Handle(debugPath, debugHTTP{server})
+}
+
+// HandleHTTP registers an HTTP handler for RPC messages to DefaultServer
+// on DefaultRPCPath and a debugging handler on DefaultDebugPath.
+// It is still necessary to invoke http.Serve(), typically in a go statement.
+func HandleHTTP() {
+	DefaultServer.HandleHTTP(DefaultRPCPath, DefaultDebugPath)
+}
diff --git a/src/pkg/net/rpc/server_test.go b/src/pkg/net/rpc/server_test.go
new file mode 100644
index 0000000..b05c63c
--- /dev/null
+++ b/src/pkg/net/rpc/server_test.go
@@ -0,0 +1,596 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rpc
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net"
+	"net/http/httptest"
+	"runtime"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"testing"
+	"time"
+)
+
+var (
+	newServer                 *Server
+	serverAddr, newServerAddr string
+	httpServerAddr            string
+	once, newOnce, httpOnce   sync.Once
+)
+
+const (
+	newHttpPath = "/foo"
+)
+
+type Args struct {
+	A, B int
+}
+
+type Reply struct {
+	C int
+}
+
+type Arith int
+
+// Some of Arith's methods have value args, some have pointer args. That's deliberate.
+
+func (t *Arith) Add(args Args, reply *Reply) error {
+	reply.C = args.A + args.B
+	return nil
+}
+
+func (t *Arith) Mul(args *Args, reply *Reply) error {
+	reply.C = args.A * args.B
+	return nil
+}
+
+func (t *Arith) Div(args Args, reply *Reply) error {
+	if args.B == 0 {
+		return errors.New("divide by zero")
+	}
+	reply.C = args.A / args.B
+	return nil
+}
+
+func (t *Arith) String(args *Args, reply *string) error {
+	*reply = fmt.Sprintf("%d+%d=%d", args.A, args.B, args.A+args.B)
+	return nil
+}
+
+func (t *Arith) Scan(args string, reply *Reply) (err error) {
+	_, err = fmt.Sscan(args, &reply.C)
+	return
+}
+
+func (t *Arith) Error(args *Args, reply *Reply) error {
+	panic("ERROR")
+}
+
+func listenTCP() (net.Listener, string) {
+	l, e := net.Listen("tcp", "127.0.0.1:0") // any available address
+	if e != nil {
+		log.Fatalf("net.Listen tcp :0: %v", e)
+	}
+	return l, l.Addr().String()
+}
+
+func startServer() {
+	Register(new(Arith))
+
+	var l net.Listener
+	l, serverAddr = listenTCP()
+	log.Println("Test RPC server listening on", serverAddr)
+	go Accept(l)
+
+	HandleHTTP()
+	httpOnce.Do(startHttpServer)
+}
+
+func startNewServer() {
+	newServer = NewServer()
+	newServer.Register(new(Arith))
+
+	var l net.Listener
+	l, newServerAddr = listenTCP()
+	log.Println("NewServer test RPC server listening on", newServerAddr)
+	go Accept(l)
+
+	newServer.HandleHTTP(newHttpPath, "/bar")
+	httpOnce.Do(startHttpServer)
+}
+
+func startHttpServer() {
+	server := httptest.NewServer(nil)
+	httpServerAddr = server.Listener.Addr().String()
+	log.Println("Test HTTP RPC server listening on", httpServerAddr)
+}
+
+func TestRPC(t *testing.T) {
+	once.Do(startServer)
+	testRPC(t, serverAddr)
+	newOnce.Do(startNewServer)
+	testRPC(t, newServerAddr)
+}
+
+func testRPC(t *testing.T, addr string) {
+	client, err := Dial("tcp", addr)
+	if err != nil {
+		t.Fatal("dialing", err)
+	}
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err = client.Call("Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+
+	// Nonexistent method
+	args = &Args{7, 0}
+	reply = new(Reply)
+	err = client.Call("Arith.BadOperation", args, reply)
+	// expect an error
+	if err == nil {
+		t.Error("BadOperation: expected error")
+	} else if !strings.HasPrefix(err.Error(), "rpc: can't find method ") {
+		t.Errorf("BadOperation: expected can't find method error; got %q", err)
+	}
+
+	// Unknown service
+	args = &Args{7, 8}
+	reply = new(Reply)
+	err = client.Call("Arith.Unknown", args, reply)
+	if err == nil {
+		t.Error("expected error calling unknown service")
+	} else if strings.Index(err.Error(), "method") < 0 {
+		t.Error("expected error about method; got", err)
+	}
+
+	// Out of order.
+	args = &Args{7, 8}
+	mulReply := new(Reply)
+	mulCall := client.Go("Arith.Mul", args, mulReply, nil)
+	addReply := new(Reply)
+	addCall := client.Go("Arith.Add", args, addReply, nil)
+
+	addCall = <-addCall.Done
+	if addCall.Error != nil {
+		t.Errorf("Add: expected no error but got string %q", addCall.Error.Error())
+	}
+	if addReply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
+	}
+
+	mulCall = <-mulCall.Done
+	if mulCall.Error != nil {
+		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error())
+	}
+	if mulReply.C != args.A*args.B {
+		t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
+	}
+
+	// Error test
+	args = &Args{7, 0}
+	reply = new(Reply)
+	err = client.Call("Arith.Div", args, reply)
+	// expect an error: zero divide
+	if err == nil {
+		t.Error("Div: expected error")
+	} else if err.Error() != "divide by zero" {
+		t.Error("Div: expected divide by zero error; got", err)
+	}
+
+	// Bad type.
+	reply = new(Reply)
+	err = client.Call("Arith.Add", reply, reply) // args, reply would be the correct thing to use
+	if err == nil {
+		t.Error("expected error calling Arith.Add with wrong arg type")
+	} else if strings.Index(err.Error(), "type") < 0 {
+		t.Error("expected error about type; got", err)
+	}
+
+	// Non-struct argument
+	const Val = 12345
+	str := fmt.Sprint(Val)
+	reply = new(Reply)
+	err = client.Call("Arith.Scan", &str, reply)
+	if err != nil {
+		t.Errorf("Scan: expected no error but got string %q", err.Error())
+	} else if reply.C != Val {
+		t.Errorf("Scan: expected %d got %d", Val, reply.C)
+	}
+
+	// Non-struct reply
+	args = &Args{27, 35}
+	str = ""
+	err = client.Call("Arith.String", args, &str)
+	if err != nil {
+		t.Errorf("String: expected no error but got string %q", err.Error())
+	}
+	expect := fmt.Sprintf("%d+%d=%d", args.A, args.B, args.A+args.B)
+	if str != expect {
+		t.Errorf("String: expected %s got %s", expect, str)
+	}
+
+	args = &Args{7, 8}
+	reply = new(Reply)
+	err = client.Call("Arith.Mul", args, reply)
+	if err != nil {
+		t.Errorf("Mul: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A*args.B {
+		t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
+	}
+}
+
+func TestHTTP(t *testing.T) {
+	once.Do(startServer)
+	testHTTPRPC(t, "")
+	newOnce.Do(startNewServer)
+	testHTTPRPC(t, newHttpPath)
+}
+
+func testHTTPRPC(t *testing.T, path string) {
+	var client *Client
+	var err error
+	if path == "" {
+		client, err = DialHTTP("tcp", httpServerAddr)
+	} else {
+		client, err = DialHTTPPath("tcp", httpServerAddr, path)
+	}
+	if err != nil {
+		t.Fatal("dialing", err)
+	}
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err = client.Call("Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+}
+
+// CodecEmulator provides a client-like api and a ServerCodec interface.
+// Can be used to test ServeRequest.
+type CodecEmulator struct {
+	server        *Server
+	serviceMethod string
+	args          *Args
+	reply         *Reply
+	err           error
+}
+
+func (codec *CodecEmulator) Call(serviceMethod string, args *Args, reply *Reply) error {
+	codec.serviceMethod = serviceMethod
+	codec.args = args
+	codec.reply = reply
+	codec.err = nil
+	var serverError error
+	if codec.server == nil {
+		serverError = ServeRequest(codec)
+	} else {
+		serverError = codec.server.ServeRequest(codec)
+	}
+	if codec.err == nil && serverError != nil {
+		codec.err = serverError
+	}
+	return codec.err
+}
+
+func (codec *CodecEmulator) ReadRequestHeader(req *Request) error {
+	req.ServiceMethod = codec.serviceMethod
+	req.Seq = 0
+	return nil
+}
+
+func (codec *CodecEmulator) ReadRequestBody(argv interface{}) error {
+	if codec.args == nil {
+		return io.ErrUnexpectedEOF
+	}
+	*(argv.(*Args)) = *codec.args
+	return nil
+}
+
+func (codec *CodecEmulator) WriteResponse(resp *Response, reply interface{}) error {
+	if resp.Error != "" {
+		codec.err = errors.New(resp.Error)
+	} else {
+		*codec.reply = *(reply.(*Reply))
+	}
+	return nil
+}
+
+func (codec *CodecEmulator) Close() error {
+	return nil
+}
+
+func TestServeRequest(t *testing.T) {
+	once.Do(startServer)
+	testServeRequest(t, nil)
+	newOnce.Do(startNewServer)
+	testServeRequest(t, newServer)
+}
+
+func testServeRequest(t *testing.T, server *Server) {
+	client := CodecEmulator{server: server}
+
+	args := &Args{7, 8}
+	reply := new(Reply)
+	err := client.Call("Arith.Add", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+
+	err = client.Call("Arith.Add", nil, reply)
+	if err == nil {
+		t.Errorf("expected error calling Arith.Add with nil arg")
+	}
+}
+
+type ReplyNotPointer int
+type ArgNotPublic int
+type ReplyNotPublic int
+type local struct{}
+
+func (t *ReplyNotPointer) ReplyNotPointer(args *Args, reply Reply) error {
+	return nil
+}
+
+func (t *ArgNotPublic) ArgNotPublic(args *local, reply *Reply) error {
+	return nil
+}
+
+func (t *ReplyNotPublic) ReplyNotPublic(args *Args, reply *local) error {
+	return nil
+}
+
+// Check that registration handles lots of bad methods and a type with no suitable methods.
+func TestRegistrationError(t *testing.T) {
+	err := Register(new(ReplyNotPointer))
+	if err == nil {
+		t.Errorf("expected error registering ReplyNotPointer")
+	}
+	err = Register(new(ArgNotPublic))
+	if err == nil {
+		t.Errorf("expected error registering ArgNotPublic")
+	}
+	err = Register(new(ReplyNotPublic))
+	if err == nil {
+		t.Errorf("expected error registering ReplyNotPublic")
+	}
+}
+
+type WriteFailCodec int
+
+func (WriteFailCodec) WriteRequest(*Request, interface{}) error {
+	// the panic caused by this error used to not unlock a lock.
+	return errors.New("fail")
+}
+
+func (WriteFailCodec) ReadResponseHeader(*Response) error {
+	time.Sleep(120 * time.Second)
+	panic("unreachable")
+}
+
+func (WriteFailCodec) ReadResponseBody(interface{}) error {
+	time.Sleep(120 * time.Second)
+	panic("unreachable")
+}
+
+func (WriteFailCodec) Close() error {
+	return nil
+}
+
+func TestSendDeadlock(t *testing.T) {
+	client := NewClientWithCodec(WriteFailCodec(0))
+
+	done := make(chan bool)
+	go func() {
+		testSendDeadlock(client)
+		testSendDeadlock(client)
+		done <- true
+	}()
+	select {
+	case <-done:
+		return
+	case <-time.After(5 * time.Second):
+		t.Fatal("deadlock")
+	}
+}
+
+func testSendDeadlock(client *Client) {
+	defer func() {
+		recover()
+	}()
+	args := &Args{7, 8}
+	reply := new(Reply)
+	client.Call("Arith.Add", args, reply)
+}
+
+func dialDirect() (*Client, error) {
+	return Dial("tcp", serverAddr)
+}
+
+func dialHTTP() (*Client, error) {
+	return DialHTTP("tcp", httpServerAddr)
+}
+
+func countMallocs(dial func() (*Client, error), t *testing.T) uint64 {
+	once.Do(startServer)
+	client, err := dial()
+	if err != nil {
+		t.Fatal("error dialing", err)
+	}
+	args := &Args{7, 8}
+	reply := new(Reply)
+	runtime.UpdateMemStats()
+	mallocs := 0 - runtime.MemStats.Mallocs
+	const count = 100
+	for i := 0; i < count; i++ {
+		err := client.Call("Arith.Add", args, reply)
+		if err != nil {
+			t.Errorf("Add: expected no error but got string %q", err.Error())
+		}
+		if reply.C != args.A+args.B {
+			t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+		}
+	}
+	runtime.UpdateMemStats()
+	mallocs += runtime.MemStats.Mallocs
+	return mallocs / count
+}
+
+func TestCountMallocs(t *testing.T) {
+	fmt.Printf("mallocs per rpc round trip: %d\n", countMallocs(dialDirect, t))
+}
+
+func TestCountMallocsOverHTTP(t *testing.T) {
+	fmt.Printf("mallocs per HTTP rpc round trip: %d\n", countMallocs(dialHTTP, t))
+}
+
+type writeCrasher struct {
+	done chan bool
+}
+
+func (writeCrasher) Close() error {
+	return nil
+}
+
+func (w *writeCrasher) Read(p []byte) (int, error) {
+	<-w.done
+	return 0, io.EOF
+}
+
+func (writeCrasher) Write(p []byte) (int, error) {
+	return 0, errors.New("fake write failure")
+}
+
+func TestClientWriteError(t *testing.T) {
+	w := &writeCrasher{done: make(chan bool)}
+	c := NewClient(w)
+	res := false
+	err := c.Call("foo", 1, &res)
+	if err == nil {
+		t.Fatal("expected error")
+	}
+	if err.Error() != "fake write failure" {
+		t.Error("unexpected value of error:", err)
+	}
+	w.done <- true
+}
+
+func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
+	b.StopTimer()
+	once.Do(startServer)
+	client, err := dial()
+	if err != nil {
+		b.Fatal("error dialing:", err)
+	}
+
+	// Synchronous calls
+	args := &Args{7, 8}
+	procs := runtime.GOMAXPROCS(-1)
+	N := int32(b.N)
+	var wg sync.WaitGroup
+	wg.Add(procs)
+	b.StartTimer()
+
+	for p := 0; p < procs; p++ {
+		go func() {
+			reply := new(Reply)
+			for atomic.AddInt32(&N, -1) >= 0 {
+				err := client.Call("Arith.Add", args, reply)
+				if err != nil {
+					b.Fatalf("rpc error: Add: expected no error but got string %q", err.Error())
+				}
+				if reply.C != args.A+args.B {
+					b.Fatalf("rpc error: Add: expected %d got %d", reply.C, args.A+args.B)
+				}
+			}
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func benchmarkEndToEndAsync(dial func() (*Client, error), b *testing.B) {
+	const MaxConcurrentCalls = 100
+	b.StopTimer()
+	once.Do(startServer)
+	client, err := dial()
+	if err != nil {
+		b.Fatal("error dialing:", err)
+	}
+
+	// Asynchronous calls
+	args := &Args{7, 8}
+	procs := 4 * runtime.GOMAXPROCS(-1)
+	send := int32(b.N)
+	recv := int32(b.N)
+	var wg sync.WaitGroup
+	wg.Add(procs)
+	gate := make(chan bool, MaxConcurrentCalls)
+	res := make(chan *Call, MaxConcurrentCalls)
+	b.StartTimer()
+
+	for p := 0; p < procs; p++ {
+		go func() {
+			for atomic.AddInt32(&send, -1) >= 0 {
+				gate <- true
+				reply := new(Reply)
+				client.Go("Arith.Add", args, reply, res)
+			}
+		}()
+		go func() {
+			for call := range res {
+				A := call.Args.(*Args).A
+				B := call.Args.(*Args).B
+				C := call.Reply.(*Reply).C
+				if A+B != C {
+					b.Fatalf("incorrect reply: Add: expected %d got %d", A+B, C)
+				}
+				<-gate
+				if atomic.AddInt32(&recv, -1) == 0 {
+					close(res)
+				}
+			}
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func BenchmarkEndToEnd(b *testing.B) {
+	benchmarkEndToEnd(dialDirect, b)
+}
+
+func BenchmarkEndToEndHTTP(b *testing.B) {
+	benchmarkEndToEnd(dialHTTP, b)
+}
+
+func BenchmarkEndToEndAsync(b *testing.B) {
+	benchmarkEndToEndAsync(dialDirect, b)
+}
+
+func BenchmarkEndToEndAsyncHTTP(b *testing.B) {
+	benchmarkEndToEndAsync(dialHTTP, b)
+}
diff --git a/src/pkg/net/sendfile_linux.go b/src/pkg/net/sendfile_linux.go
index 6a5a06c..e9ab066 100644
--- a/src/pkg/net/sendfile_linux.go
+++ b/src/pkg/net/sendfile_linux.go
@@ -21,7 +21,7 @@ const maxSendfileSize int = 4 << 20
 // non-EOF error.
 //
 // if handled == false, sendFile performed no work.
-func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool) {
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
 	var remain int64 = 1 << 62 // by default, copy until EOF
 
 	lr, ok := r.(*io.LimitedReader)
@@ -40,15 +40,6 @@ func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool)
 	defer c.wio.Unlock()
 	c.incref()
 	defer c.decref()
-	if c.wdeadline_delta > 0 {
-		// This is a little odd that we're setting the timeout
-		// for the entire file but Write has the same issue
-		// (if one slurps the whole file into memory and
-		// do one large Write). At least they're consistent.
-		c.wdeadline = pollserver.Now() + c.wdeadline_delta
-	} else {
-		c.wdeadline = 0
-	}
 
 	dst := c.sysfd
 	src := f.Fd()
@@ -62,18 +53,18 @@ func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool)
 			written += int64(n)
 			remain -= int64(n)
 		}
-		if n == 0 && errno == 0 {
+		if n == 0 && errno == nil {
 			break
 		}
 		if errno == syscall.EAGAIN && c.wdeadline >= 0 {
 			pollserver.WaitWrite(c)
 			continue
 		}
-		if errno != 0 {
+		if errno != nil {
 			// This includes syscall.ENOSYS (no kernel
 			// support) and syscall.EINVAL (fd types which
 			// don't implement sendfile together)
-			err = &OpError{"sendfile", c.net, c.raddr, os.Errno(errno)}
+			err = &OpError{"sendfile", c.net, c.raddr, errno}
 			break
 		}
 	}
diff --git a/src/pkg/net/sendfile_stub.go b/src/pkg/net/sendfile_stub.go
index c55be6c..ff76ab9 100644
--- a/src/pkg/net/sendfile_stub.go
+++ b/src/pkg/net/sendfile_stub.go
@@ -2,15 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd openbsd
+// +build darwin freebsd netbsd openbsd
 
 package net
 
-import (
-	"io"
-	"os"
-)
+import "io"
 
-func sendFile(c *netFD, r io.Reader) (n int64, err os.Error, handled bool) {
+func sendFile(c *netFD, r io.Reader) (n int64, err error, handled bool) {
 	return 0, nil, false
 }
diff --git a/src/pkg/net/sendfile_windows.go b/src/pkg/net/sendfile_windows.go
index d9c2f53..ee7ff8b 100644
--- a/src/pkg/net/sendfile_windows.go
+++ b/src/pkg/net/sendfile_windows.go
@@ -16,7 +16,7 @@ type sendfileOp struct {
 	n   uint32
 }
 
-func (o *sendfileOp) Submit() (errno int) {
+func (o *sendfileOp) Submit() (err error) {
 	return syscall.TransmitFile(o.fd.sysfd, o.src, o.n, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
 }
 
@@ -33,7 +33,7 @@ func (o *sendfileOp) Name() string {
 // if handled == false, sendFile performed no work.
 //
 // Note that sendfile for windows does not suppport >2GB file.
-func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool) {
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
 	var n int64 = 0 // by default, copy until EOF
 
 	lr, ok := r.(*io.LimitedReader)
diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go
index a2ff218..b0b546b 100644
--- a/src/pkg/net/server_test.go
+++ b/src/pkg/net/server_test.go
@@ -8,10 +8,10 @@ import (
 	"flag"
 	"io"
 	"os"
+	"runtime"
 	"strings"
-	"syscall"
 	"testing"
-	"runtime"
+	"time"
 )
 
 // Do not test empty datagrams by default.
@@ -55,7 +55,7 @@ func runServe(t *testing.T, network, addr string, listening chan<- string, done
 
 func connect(t *testing.T, network, addr string, isEmpty bool) {
 	var fd Conn
-	var err os.Error
+	var err error
 	if network == "unixgram" {
 		fd, err = DialUnix(network, &UnixAddr{addr + ".local", network}, &UnixAddr{addr, network})
 	} else {
@@ -64,7 +64,7 @@ func connect(t *testing.T, network, addr string, isEmpty bool) {
 	if err != nil {
 		t.Fatalf("net.Dial(%q, %q) = _, %v", network, addr, err)
 	}
-	fd.SetReadTimeout(1e9) // 1s
+	fd.SetReadDeadline(time.Now().Add(1 * time.Second))
 
 	var b []byte
 	if !isEmpty {
@@ -92,7 +92,7 @@ func connect(t *testing.T, network, addr string, isEmpty bool) {
 }
 
 func doTest(t *testing.T, network, listenaddr, dialaddr string) {
-	t.Logf("Test %q %q %q\n", network, listenaddr, dialaddr)
+	t.Logf("Test %q %q %q", network, listenaddr, dialaddr)
 	switch listenaddr {
 	case "", "0.0.0.0", "[::]", "[::ffff:0.0.0.0]":
 		if testing.Short() || avoidMacFirewall {
@@ -115,7 +115,7 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) {
 }
 
 func TestTCPServer(t *testing.T) {
-	if syscall.OS != "openbsd" {
+	if runtime.GOOS != "openbsd" {
 		doTest(t, "tcp", "", "127.0.0.1")
 	}
 	doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
@@ -155,7 +155,7 @@ func TestUnixServer(t *testing.T) {
 	os.Remove("/tmp/gotest.net")
 	doTest(t, "unix", "/tmp/gotest.net", "/tmp/gotest.net")
 	os.Remove("/tmp/gotest.net")
-	if syscall.OS == "linux" {
+	if runtime.GOOS == "linux" {
 		doTest(t, "unixpacket", "/tmp/gotest.net", "/tmp/gotest.net")
 		os.Remove("/tmp/gotest.net")
 		// Test abstract unix domain socket, a Linux-ism
@@ -170,10 +170,10 @@ func runPacket(t *testing.T, network, addr string, listening chan<- string, done
 		t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
 	}
 	listening <- c.LocalAddr().String()
-	c.SetReadTimeout(10e6) // 10ms
 	var buf [1000]byte
 Run:
 	for {
+		c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
 		n, addr, err := c.ReadFrom(buf[0:])
 		if e, ok := err.(Error); ok && e.Timeout() {
 			select {
@@ -195,7 +195,7 @@ Run:
 }
 
 func doTestPacket(t *testing.T, network, listenaddr, dialaddr string, isEmpty bool) {
-	t.Logf("TestPacket %s %s %s\n", network, listenaddr, dialaddr)
+	t.Logf("TestPacket %q %q %q", network, listenaddr, dialaddr)
 	listening := make(chan string)
 	done := make(chan int)
 	if network == "udp" {
@@ -237,7 +237,7 @@ func TestUnixDatagramServer(t *testing.T) {
 		doTestPacket(t, "unixgram", "/tmp/gotest1.net", "/tmp/gotest1.net", isEmpty)
 		os.Remove("/tmp/gotest1.net")
 		os.Remove("/tmp/gotest1.net.local")
-		if syscall.OS == "linux" {
+		if runtime.GOOS == "linux" {
 			// Test abstract unix domain socket, a Linux-ism
 			doTestPacket(t, "unixgram", "@gotest1/net", "@gotest1/net", isEmpty)
 		}
diff --git a/src/pkg/net/smtp/Makefile b/src/pkg/net/smtp/Makefile
new file mode 100644
index 0000000..d9812d5
--- /dev/null
+++ b/src/pkg/net/smtp/Makefile
@@ -0,0 +1,12 @@
+# Copyright 2010 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=net/smtp
+GOFILES=\
+	auth.go\
+	smtp.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/net/smtp/auth.go b/src/pkg/net/smtp/auth.go
new file mode 100644
index 0000000..d401e3c
--- /dev/null
+++ b/src/pkg/net/smtp/auth.go
@@ -0,0 +1,98 @@
+// Copyright 2010 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 smtp
+
+import (
+	"crypto/hmac"
+	"crypto/md5"
+	"errors"
+	"fmt"
+)
+
+// Auth is implemented by an SMTP authentication mechanism.
+type Auth interface {
+	// Start begins an authentication with a server.
+	// It returns the name of the authentication protocol
+	// and optionally data to include in the initial AUTH message
+	// sent to the server. It can return proto == "" to indicate
+	// that the authentication should be skipped.
+	// If it returns a non-nil error, the SMTP client aborts
+	// the authentication attempt and closes the connection.
+	Start(server *ServerInfo) (proto string, toServer []byte, err error)
+
+	// Next continues the authentication. The server has just sent
+	// the fromServer data. If more is true, the server expects a
+	// response, which Next should return as toServer; otherwise
+	// Next should return toServer == nil.
+	// If Next returns a non-nil error, the SMTP client aborts
+	// the authentication attempt and closes the connection.
+	Next(fromServer []byte, more bool) (toServer []byte, err error)
+}
+
+// ServerInfo records information about an SMTP server.
+type ServerInfo struct {
+	Name string   // SMTP server name
+	TLS  bool     // using TLS, with valid certificate for Name
+	Auth []string // advertised authentication mechanisms
+}
+
+type plainAuth struct {
+	identity, username, password string
+	host                         string
+}
+
+// PlainAuth returns an Auth that implements the PLAIN authentication
+// mechanism as defined in RFC 4616.
+// The returned Auth uses the given username and password to authenticate
+// on TLS connections to host and act as identity. Usually identity will be
+// left blank to act as username.
+func PlainAuth(identity, username, password, host string) Auth {
+	return &plainAuth{identity, username, password, host}
+}
+
+func (a *plainAuth) Start(server *ServerInfo) (string, []byte, error) {
+	if !server.TLS {
+		return "", nil, errors.New("unencrypted connection")
+	}
+	if server.Name != a.host {
+		return "", nil, errors.New("wrong host name")
+	}
+	resp := []byte(a.identity + "\x00" + a.username + "\x00" + a.password)
+	return "PLAIN", resp, nil
+}
+
+func (a *plainAuth) Next(fromServer []byte, more bool) ([]byte, error) {
+	if more {
+		// We've already sent everything.
+		return nil, errors.New("unexpected server challenge")
+	}
+	return nil, nil
+}
+
+type cramMD5Auth struct {
+	username, secret string
+}
+
+// CRAMMD5Auth returns an Auth that implements the CRAM-MD5 authentication
+// mechanism as defined in RFC 2195.
+// The returned Auth uses the given username and secret to authenticate
+// to the server using the challenge-response mechanism.
+func CRAMMD5Auth(username, secret string) Auth {
+	return &cramMD5Auth{username, secret}
+}
+
+func (a *cramMD5Auth) Start(server *ServerInfo) (string, []byte, error) {
+	return "CRAM-MD5", nil, nil
+}
+
+func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) {
+	if more {
+		d := hmac.New(md5.New, []byte(a.secret))
+		d.Write(fromServer)
+		s := make([]byte, 0, d.Size())
+		return []byte(fmt.Sprintf("%s %x", a.username, d.Sum(s))), nil
+	}
+	return nil, nil
+}
diff --git a/src/pkg/net/smtp/smtp.go b/src/pkg/net/smtp/smtp.go
new file mode 100644
index 0000000..8d935ff
--- /dev/null
+++ b/src/pkg/net/smtp/smtp.go
@@ -0,0 +1,293 @@
+// Copyright 2010 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 smtp implements the Simple Mail Transfer Protocol as defined in RFC 5321.
+// It also implements the following extensions:
+//	8BITMIME  RFC 1652
+//	AUTH      RFC 2554
+//	STARTTLS  RFC 3207
+// Additional extensions may be handled by clients.
+package smtp
+
+import (
+	"crypto/tls"
+	"encoding/base64"
+	"io"
+	"net"
+	"net/textproto"
+	"strings"
+)
+
+// A Client represents a client connection to an SMTP server.
+type Client struct {
+	// Text is the textproto.Conn used by the Client. It is exported to allow for
+	// clients to add extensions.
+	Text *textproto.Conn
+	// keep a reference to the connection so it can be used to create a TLS
+	// connection later
+	conn net.Conn
+	// whether the Client is using TLS
+	tls        bool
+	serverName string
+	// map of supported extensions
+	ext map[string]string
+	// supported auth mechanisms
+	auth []string
+}
+
+// Dial returns a new Client connected to an SMTP server at addr.
+func Dial(addr string) (*Client, error) {
+	conn, err := net.Dial("tcp", addr)
+	if err != nil {
+		return nil, err
+	}
+	host := addr[:strings.Index(addr, ":")]
+	return NewClient(conn, host)
+}
+
+// NewClient returns a new Client using an existing connection and host as a
+// server name to be used when authenticating.
+func NewClient(conn net.Conn, host string) (*Client, error) {
+	text := textproto.NewConn(conn)
+	_, msg, err := text.ReadResponse(220)
+	if err != nil {
+		text.Close()
+		return nil, err
+	}
+	c := &Client{Text: text, conn: conn, serverName: host}
+	if strings.Contains(msg, "ESMTP") {
+		err = c.ehlo()
+	} else {
+		err = c.helo()
+	}
+	return c, err
+}
+
+// cmd is a convenience function that sends a command and returns the response
+func (c *Client) cmd(expectCode int, format string, args ...interface{}) (int, string, error) {
+	id, err := c.Text.Cmd(format, args...)
+	if err != nil {
+		return 0, "", err
+	}
+	c.Text.StartResponse(id)
+	defer c.Text.EndResponse(id)
+	code, msg, err := c.Text.ReadResponse(expectCode)
+	return code, msg, err
+}
+
+// helo sends the HELO greeting to the server. It should be used only when the
+// server does not support ehlo.
+func (c *Client) helo() error {
+	c.ext = nil
+	_, _, err := c.cmd(250, "HELO localhost")
+	return err
+}
+
+// ehlo sends the EHLO (extended hello) greeting to the server. It
+// should be the preferred greeting for servers that support it.
+func (c *Client) ehlo() error {
+	_, msg, err := c.cmd(250, "EHLO localhost")
+	if err != nil {
+		return err
+	}
+	ext := make(map[string]string)
+	extList := strings.Split(msg, "\n")
+	if len(extList) > 1 {
+		extList = extList[1:]
+		for _, line := range extList {
+			args := strings.SplitN(line, " ", 2)
+			if len(args) > 1 {
+				ext[args[0]] = args[1]
+			} else {
+				ext[args[0]] = ""
+			}
+		}
+	}
+	if mechs, ok := ext["AUTH"]; ok {
+		c.auth = strings.Split(mechs, " ")
+	}
+	c.ext = ext
+	return err
+}
+
+// StartTLS sends the STARTTLS command and encrypts all further communication.
+// Only servers that advertise the STARTTLS extension support this function.
+func (c *Client) StartTLS(config *tls.Config) error {
+	_, _, err := c.cmd(220, "STARTTLS")
+	if err != nil {
+		return err
+	}
+	c.conn = tls.Client(c.conn, config)
+	c.Text = textproto.NewConn(c.conn)
+	c.tls = true
+	return c.ehlo()
+}
+
+// Verify checks the validity of an email address on the server.
+// If Verify returns nil, the address is valid. A non-nil return
+// does not necessarily indicate an invalid address. Many servers
+// will not verify addresses for security reasons.
+func (c *Client) Verify(addr string) error {
+	_, _, err := c.cmd(250, "VRFY %s", addr)
+	return err
+}
+
+// Auth authenticates a client using the provided authentication mechanism.
+// A failed authentication closes the connection.
+// Only servers that advertise the AUTH extension support this function.
+func (c *Client) Auth(a Auth) error {
+	encoding := base64.StdEncoding
+	mech, resp, err := a.Start(&ServerInfo{c.serverName, c.tls, c.auth})
+	if err != nil {
+		c.Quit()
+		return err
+	}
+	resp64 := make([]byte, encoding.EncodedLen(len(resp)))
+	encoding.Encode(resp64, resp)
+	code, msg64, err := c.cmd(0, "AUTH %s %s", mech, resp64)
+	for err == nil {
+		var msg []byte
+		switch code {
+		case 334:
+			msg, err = encoding.DecodeString(msg64)
+		case 235:
+			// the last message isn't base64 because it isn't a challenge
+			msg = []byte(msg64)
+		default:
+			err = &textproto.Error{code, msg64}
+		}
+		resp, err = a.Next(msg, code == 334)
+		if err != nil {
+			// abort the AUTH
+			c.cmd(501, "*")
+			c.Quit()
+			break
+		}
+		if resp == nil {
+			break
+		}
+		resp64 = make([]byte, encoding.EncodedLen(len(resp)))
+		encoding.Encode(resp64, resp)
+		code, msg64, err = c.cmd(0, string(resp64))
+	}
+	return err
+}
+
+// Mail issues a MAIL command to the server using the provided email address.
+// If the server supports the 8BITMIME extension, Mail adds the BODY=8BITMIME
+// parameter.
+// This initiates a mail transaction and is followed by one or more Rcpt calls.
+func (c *Client) Mail(from string) error {
+	cmdStr := "MAIL FROM:<%s>"
+	if c.ext != nil {
+		if _, ok := c.ext["8BITMIME"]; ok {
+			cmdStr += " BODY=8BITMIME"
+		}
+	}
+	_, _, err := c.cmd(250, cmdStr, from)
+	return err
+}
+
+// Rcpt issues a RCPT command to the server using the provided email address.
+// A call to Rcpt must be preceded by a call to Mail and may be followed by
+// a Data call or another Rcpt call.
+func (c *Client) Rcpt(to string) error {
+	_, _, err := c.cmd(25, "RCPT TO:<%s>", to)
+	return err
+}
+
+type dataCloser struct {
+	c *Client
+	io.WriteCloser
+}
+
+func (d *dataCloser) Close() error {
+	d.WriteCloser.Close()
+	_, _, err := d.c.Text.ReadResponse(250)
+	return err
+}
+
+// Data issues a DATA command to the server and returns a writer that
+// can be used to write the data. The caller should close the writer
+// before calling any more methods on c.
+// A call to Data must be preceded by one or more calls to Rcpt.
+func (c *Client) Data() (io.WriteCloser, error) {
+	_, _, err := c.cmd(354, "DATA")
+	if err != nil {
+		return nil, err
+	}
+	return &dataCloser{c, c.Text.DotWriter()}, nil
+}
+
+// SendMail connects to the server at addr, switches to TLS if possible,
+// authenticates with mechanism a if possible, and then sends an email from
+// address from, to addresses to, with message msg.
+func SendMail(addr string, a Auth, from string, to []string, msg []byte) error {
+	c, err := Dial(addr)
+	if err != nil {
+		return err
+	}
+	if ok, _ := c.Extension("STARTTLS"); ok {
+		if err = c.StartTLS(nil); err != nil {
+			return err
+		}
+	}
+	if a != nil && c.ext != nil {
+		if _, ok := c.ext["AUTH"]; ok {
+			if err = c.Auth(a); err != nil {
+				return err
+			}
+		}
+	}
+	if err = c.Mail(from); err != nil {
+		return err
+	}
+	for _, addr := range to {
+		if err = c.Rcpt(addr); err != nil {
+			return err
+		}
+	}
+	w, err := c.Data()
+	if err != nil {
+		return err
+	}
+	_, err = w.Write(msg)
+	if err != nil {
+		return err
+	}
+	err = w.Close()
+	if err != nil {
+		return err
+	}
+	return c.Quit()
+}
+
+// Extension reports whether an extension is support by the server.
+// The extension name is case-insensitive. If the extension is supported,
+// Extension also returns a string that contains any parameters the
+// server specifies for the extension.
+func (c *Client) Extension(ext string) (bool, string) {
+	if c.ext == nil {
+		return false, ""
+	}
+	ext = strings.ToUpper(ext)
+	param, ok := c.ext[ext]
+	return ok, param
+}
+
+// Reset sends the RSET command to the server, aborting the current mail
+// transaction.
+func (c *Client) Reset() error {
+	_, _, err := c.cmd(250, "RSET")
+	return err
+}
+
+// Quit sends the QUIT command and closes the connection to the server.
+func (c *Client) Quit() error {
+	_, _, err := c.cmd(221, "QUIT")
+	if err != nil {
+		return err
+	}
+	return c.Text.Close()
+}
diff --git a/src/pkg/net/smtp/smtp_test.go b/src/pkg/net/smtp/smtp_test.go
new file mode 100644
index 0000000..ce88782
--- /dev/null
+++ b/src/pkg/net/smtp/smtp_test.go
@@ -0,0 +1,182 @@
+// Copyright 2010 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 smtp
+
+import (
+	"bufio"
+	"bytes"
+	"io"
+	"net/textproto"
+	"strings"
+	"testing"
+)
+
+type authTest struct {
+	auth       Auth
+	challenges []string
+	name       string
+	responses  []string
+}
+
+var authTests = []authTest{
+	{PlainAuth("", "user", "pass", "testserver"), []string{}, "PLAIN", []string{"\x00user\x00pass"}},
+	{PlainAuth("foo", "bar", "baz", "testserver"), []string{}, "PLAIN", []string{"foo\x00bar\x00baz"}},
+	{CRAMMD5Auth("user", "pass"), []string{"<123456.1322876914 at testserver>"}, "CRAM-MD5", []string{"", "user 287eb355114cf5c471c26a875f1ca4ae"}},
+}
+
+func TestAuth(t *testing.T) {
+testLoop:
+	for i, test := range authTests {
+		name, resp, err := test.auth.Start(&ServerInfo{"testserver", true, nil})
+		if name != test.name {
+			t.Errorf("#%d got name %s, expected %s", i, name, test.name)
+		}
+		if !bytes.Equal(resp, []byte(test.responses[0])) {
+			t.Errorf("#%d got response %s, expected %s", i, resp, test.responses[0])
+		}
+		if err != nil {
+			t.Errorf("#%d error: %s", i, err)
+		}
+		for j := range test.challenges {
+			challenge := []byte(test.challenges[j])
+			expected := []byte(test.responses[j+1])
+			resp, err := test.auth.Next(challenge, true)
+			if err != nil {
+				t.Errorf("#%d error: %s", i, err)
+				continue testLoop
+			}
+			if !bytes.Equal(resp, expected) {
+				t.Errorf("#%d got %s, expected %s", i, resp, expected)
+				continue testLoop
+			}
+		}
+	}
+}
+
+type faker struct {
+	io.ReadWriter
+}
+
+func (f faker) Close() error {
+	return nil
+}
+
+func TestBasic(t *testing.T) {
+	basicServer = strings.Join(strings.Split(basicServer, "\n"), "\r\n")
+	basicClient = strings.Join(strings.Split(basicClient, "\n"), "\r\n")
+
+	var cmdbuf bytes.Buffer
+	bcmdbuf := bufio.NewWriter(&cmdbuf)
+	var fake faker
+	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(basicServer)), bcmdbuf)
+	c := &Client{Text: textproto.NewConn(fake)}
+
+	if err := c.helo(); err != nil {
+		t.Fatalf("HELO failed: %s", err)
+	}
+	if err := c.ehlo(); err == nil {
+		t.Fatalf("Expected first EHLO to fail")
+	}
+	if err := c.ehlo(); err != nil {
+		t.Fatalf("Second EHLO failed: %s", err)
+	}
+
+	if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" {
+		t.Fatalf("Expected AUTH supported")
+	}
+	if ok, _ := c.Extension("DSN"); ok {
+		t.Fatalf("Shouldn't support DSN")
+	}
+
+	if err := c.Mail("user at gmail.com"); err == nil {
+		t.Fatalf("MAIL should require authentication")
+	}
+
+	if err := c.Verify("user1 at gmail.com"); err == nil {
+		t.Fatalf("First VRFY: expected no verification")
+	}
+	if err := c.Verify("user2 at gmail.com"); err != nil {
+		t.Fatalf("Second VRFY: expected verification, got %s", err)
+	}
+
+	// fake TLS so authentication won't complain
+	c.tls = true
+	c.serverName = "smtp.google.com"
+	if err := c.Auth(PlainAuth("", "user", "pass", "smtp.google.com")); err != nil {
+		t.Fatalf("AUTH failed: %s", err)
+	}
+
+	if err := c.Mail("user at gmail.com"); err != nil {
+		t.Fatalf("MAIL failed: %s", err)
+	}
+	if err := c.Rcpt("golang-nuts at googlegroups.com"); err != nil {
+		t.Fatalf("RCPT failed: %s", err)
+	}
+	msg := `From: user at gmail.com
+To: golang-nuts at googlegroups.com
+Subject: Hooray for Go
+
+Line 1
+.Leading dot line .
+Goodbye.`
+	w, err := c.Data()
+	if err != nil {
+		t.Fatalf("DATA failed: %s", err)
+	}
+	if _, err := w.Write([]byte(msg)); err != nil {
+		t.Fatalf("Data write failed: %s", err)
+	}
+	if err := w.Close(); err != nil {
+		t.Fatalf("Bad data response: %s", err)
+	}
+
+	if err := c.Quit(); err != nil {
+		t.Fatalf("QUIT failed: %s", err)
+	}
+
+	bcmdbuf.Flush()
+	actualcmds := cmdbuf.String()
+	if basicClient != actualcmds {
+		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, basicClient)
+	}
+}
+
+var basicServer = `250 mx.google.com at your service
+502 Unrecognized command.
+250-mx.google.com at your service
+250-SIZE 35651584
+250-AUTH LOGIN PLAIN
+250 8BITMIME
+530 Authentication required
+252 Send some mail, I'll try my best
+250 User is valid
+235 Accepted
+250 Sender OK
+250 Receiver OK
+354 Go ahead
+250 Data OK
+221 OK
+`
+
+var basicClient = `HELO localhost
+EHLO localhost
+EHLO localhost
+MAIL FROM:<user at gmail.com> BODY=8BITMIME
+VRFY user1 at gmail.com
+VRFY user2 at gmail.com
+AUTH PLAIN AHVzZXIAcGFzcw==
+MAIL FROM:<user at gmail.com> BODY=8BITMIME
+RCPT TO:<golang-nuts at googlegroups.com>
+DATA
+From: user at gmail.com
+To: golang-nuts at googlegroups.com
+Subject: Hooray for Go
+
+Line 1
+..Leading dot line .
+Goodbye.
+.
+QUIT
+`
diff --git a/src/pkg/net/sock.go b/src/pkg/net/sock.go
index 366e050..867e328 100644
--- a/src/pkg/net/sock.go
+++ b/src/pkg/net/sock.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 // Sockets
 
@@ -10,51 +10,46 @@ package net
 
 import (
 	"io"
-	"os"
 	"reflect"
 	"syscall"
 )
 
-// Boolean to int.
-func boolint(b bool) int {
-	if b {
-		return 1
-	}
-	return 0
-}
+var listenerBacklog = maxListenerBacklog()
 
 // Generic socket creation.
-func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) {
+func socket(net string, f, t, p int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
 	// See ../syscall/exec.go for description of ForkLock.
 	syscall.ForkLock.RLock()
-	s, e := syscall.Socket(f, p, t)
-	if e != 0 {
+	s, err := syscall.Socket(f, t, p)
+	if err != nil {
 		syscall.ForkLock.RUnlock()
-		return nil, os.Errno(e)
+		return nil, err
 	}
 	syscall.CloseOnExec(s)
 	syscall.ForkLock.RUnlock()
 
-	setKernelSpecificSockopt(s, f)
+	setDefaultSockopts(s, f, t)
 
 	if la != nil {
-		e = syscall.Bind(s, la)
-		if e != 0 {
+		err = syscall.Bind(s, la)
+		if err != nil {
 			closesocket(s)
-			return nil, os.Errno(e)
+			return nil, err
 		}
 	}
 
-	if fd, err = newFD(s, f, p, net); err != nil {
+	if fd, err = newFD(s, f, t, net); err != nil {
 		closesocket(s)
 		return nil, err
 	}
 
 	if ra != nil {
 		if err = fd.connect(ra); err != nil {
+			closesocket(s)
 			fd.Close()
 			return nil, err
 		}
+		fd.isConnected = true
 	}
 
 	sa, _ := syscall.Getsockname(s)
@@ -66,93 +61,11 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
 	return fd, nil
 }
 
-func setsockoptInt(fd *netFD, level, opt int, value int) os.Error {
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, level, opt, value))
-}
-
-func setsockoptNsec(fd *netFD, level, opt int, nsec int64) os.Error {
-	var tv = syscall.NsecToTimeval(nsec)
-	return os.NewSyscallError("setsockopt", syscall.SetsockoptTimeval(fd.sysfd, level, opt, &tv))
-}
-
-func setReadBuffer(fd *netFD, bytes int) os.Error {
-	fd.incref()
-	defer fd.decref()
-	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
-}
-
-func setWriteBuffer(fd *netFD, bytes int) os.Error {
-	fd.incref()
-	defer fd.decref()
-	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
-}
-
-func setReadTimeout(fd *netFD, nsec int64) os.Error {
-	fd.rdeadline_delta = nsec
-	return nil
-}
-
-func setWriteTimeout(fd *netFD, nsec int64) os.Error {
-	fd.wdeadline_delta = nsec
-	return nil
-}
-
-func setTimeout(fd *netFD, nsec int64) os.Error {
-	if e := setReadTimeout(fd, nsec); e != nil {
-		return e
-	}
-	return setWriteTimeout(fd, nsec)
-}
-
-func setReuseAddr(fd *netFD, reuse bool) os.Error {
-	fd.incref()
-	defer fd.decref()
-	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))
-}
-
-func bindToDevice(fd *netFD, dev string) os.Error {
-	// TODO(rsc): call setsockopt with null-terminated string pointer
-	return os.EINVAL
-}
-
-func setDontRoute(fd *netFD, dontroute bool) os.Error {
-	fd.incref()
-	defer fd.decref()
-	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))
-}
-
-func setKeepAlive(fd *netFD, keepalive bool) os.Error {
-	fd.incref()
-	defer fd.decref()
-	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
-}
-
-func setNoDelay(fd *netFD, noDelay bool) os.Error {
-	fd.incref()
-	defer fd.decref()
-	return setsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))
-}
-
-func setLinger(fd *netFD, sec int) os.Error {
-	var l syscall.Linger
-	if sec >= 0 {
-		l.Onoff = 1
-		l.Linger = int32(sec)
-	} else {
-		l.Onoff = 0
-		l.Linger = 0
-	}
-	fd.incref()
-	defer fd.decref()
-	e := syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
-	return os.NewSyscallError("setsockopt", e)
-}
-
 type UnknownSocketError struct {
 	sa syscall.Sockaddr
 }
 
-func (e *UnknownSocketError) String() string {
+func (e *UnknownSocketError) Error() string {
 	return "unknown socket address type " + reflect.TypeOf(e.sa).String()
 }
 
@@ -162,7 +75,7 @@ type writerOnly struct {
 
 // Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
 // applicable.
-func genericReadFrom(w io.Writer, r io.Reader) (n int64, err os.Error) {
+func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
 	// Use wrapper to hide existing r.ReadFrom from io.Copy.
 	return io.Copy(writerOnly{w}, r)
 }
diff --git a/src/pkg/net/sock_bsd.go b/src/pkg/net/sock_bsd.go
index c59802f..630a91e 100644
--- a/src/pkg/net/sock_bsd.go
+++ b/src/pkg/net/sock_bsd.go
@@ -1,33 +1,33 @@
-// Copyright 2011 The Go Authors.  All rights reserved.
+// Copyright 2009 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd
+// +build darwin freebsd netbsd openbsd
 
 // Sockets for BSD variants
 
 package net
 
 import (
+	"runtime"
 	"syscall"
 )
 
-func setKernelSpecificSockopt(s, f int) {
-	// Allow reuse of recently-used addresses.
-	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
-
-	// Allow reuse of recently-used ports.
-	// This option is supported only in descendants of 4.4BSD,
-	// to make an effective multicast application and an application
-	// that requires quick draw possible.
-	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
-
-	// Allow broadcast.
-	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
-
-	if f == syscall.AF_INET6 {
-		// using ip, tcp, udp, etc.
-		// allow both protocols even if the OS default is otherwise.
-		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
+func maxListenerBacklog() int {
+	var (
+		n   uint32
+		err error
+	)
+	switch runtime.GOOS {
+	case "darwin", "freebsd":
+		n, err = syscall.SysctlUint32("kern.ipc.somaxconn")
+	case "netbsd":
+		// NOTE: NetBSD has no somaxconn-like kernel state so far
+	case "openbsd":
+		n, err = syscall.SysctlUint32("kern.somaxconn")
+	}
+	if n == 0 || err != nil {
+		return syscall.SOMAXCONN
 	}
+	return int(n)
 }
diff --git a/src/pkg/net/sock_linux.go b/src/pkg/net/sock_linux.go
index ec31e80..2cbc34f 100644
--- a/src/pkg/net/sock_linux.go
+++ b/src/pkg/net/sock_linux.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors.  All rights reserved.
+// Copyright 2009 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -6,20 +6,22 @@
 
 package net
 
-import (
-	"syscall"
-)
+import "syscall"
 
-func setKernelSpecificSockopt(s, f int) {
-	// Allow reuse of recently-used addresses.
-	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
-
-	// Allow broadcast.
-	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
-
-	if f == syscall.AF_INET6 {
-		// using ip, tcp, udp, etc.
-		// allow both protocols even if the OS default is otherwise.
-		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
+func maxListenerBacklog() int {
+	fd, err := open("/proc/sys/net/core/somaxconn")
+	if err != nil {
+		return syscall.SOMAXCONN
+	}
+	defer fd.close()
+	l, ok := fd.readLine()
+	if !ok {
+		return syscall.SOMAXCONN
+	}
+	f := getFields(l)
+	n, _, ok := dtoi(f[0], 0)
+	if n == 0 || !ok {
+		return syscall.SOMAXCONN
 	}
+	return n
 }
diff --git a/src/pkg/net/sock_windows.go b/src/pkg/net/sock_windows.go
index c6dbd04..2d803de 100644
--- a/src/pkg/net/sock_windows.go
+++ b/src/pkg/net/sock_windows.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors.  All rights reserved.
+// Copyright 2009 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
@@ -6,20 +6,9 @@
 
 package net
 
-import (
-	"syscall"
-)
+import "syscall"
 
-func setKernelSpecificSockopt(s syscall.Handle, f int) {
-	// Allow reuse of recently-used addresses and ports.
-	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
-
-	// Allow broadcast.
-	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
-
-	if f == syscall.AF_INET6 {
-		// using ip, tcp, udp, etc.
-		// allow both protocols even if the OS default is otherwise.
-		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
-	}
+func maxListenerBacklog() int {
+	// TODO: Implement this
+	return syscall.SOMAXCONN
 }
diff --git a/src/pkg/net/sockopt.go b/src/pkg/net/sockopt.go
new file mode 100644
index 0000000..3d0f8dd
--- /dev/null
+++ b/src/pkg/net/sockopt.go
@@ -0,0 +1,180 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd windows
+
+// Socket options
+
+package net
+
+import (
+	"bytes"
+	"os"
+	"syscall"
+	"time"
+)
+
+// Boolean to int.
+func boolint(b bool) int {
+	if b {
+		return 1
+	}
+	return 0
+}
+
+func ipv4AddrToInterface(ip IP) (*Interface, error) {
+	ift, err := Interfaces()
+	if err != nil {
+		return nil, err
+	}
+	for _, ifi := range ift {
+		ifat, err := ifi.Addrs()
+		if err != nil {
+			return nil, err
+		}
+		for _, ifa := range ifat {
+			switch v := ifa.(type) {
+			case *IPAddr:
+				if ip.Equal(v.IP) {
+					return &ifi, nil
+				}
+			case *IPNet:
+				if ip.Equal(v.IP) {
+					return &ifi, nil
+				}
+			}
+		}
+	}
+	if ip.Equal(IPv4zero) {
+		return nil, nil
+	}
+	return nil, errNoSuchInterface
+}
+
+func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
+	if ifi == nil {
+		return IPv4zero, nil
+	}
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		return nil, err
+	}
+	for _, ifa := range ifat {
+		switch v := ifa.(type) {
+		case *IPAddr:
+			if v.IP.To4() != nil {
+				return v.IP, nil
+			}
+		case *IPNet:
+			if v.IP.To4() != nil {
+				return v.IP, nil
+			}
+		}
+	}
+	return nil, errNoSuchInterface
+}
+
+func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
+	if ifi == nil {
+		return nil
+	}
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		return err
+	}
+	for _, ifa := range ifat {
+		switch v := ifa.(type) {
+		case *IPAddr:
+			if a := v.IP.To4(); a != nil {
+				copy(mreq.Interface[:], a)
+				goto done
+			}
+		case *IPNet:
+			if a := v.IP.To4(); a != nil {
+				copy(mreq.Interface[:], a)
+				goto done
+			}
+		}
+	}
+done:
+	if bytes.Equal(mreq.Multiaddr[:], IPv4zero.To4()) {
+		return errNoSuchMulticastInterface
+	}
+	return nil
+}
+
+func setReadBuffer(fd *netFD, bytes int) error {
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes))
+}
+
+func setWriteBuffer(fd *netFD, bytes int) error {
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
+}
+
+func setReadDeadline(fd *netFD, t time.Time) error {
+	if t.IsZero() {
+		fd.rdeadline = 0
+	} else {
+		fd.rdeadline = t.UnixNano()
+	}
+	return nil
+}
+
+func setWriteDeadline(fd *netFD, t time.Time) error {
+	if t.IsZero() {
+		fd.wdeadline = 0
+	} else {
+		fd.wdeadline = t.UnixNano()
+	}
+	return nil
+}
+
+func setDeadline(fd *netFD, t time.Time) error {
+	if e := setReadDeadline(fd, t); e != nil {
+		return e
+	}
+	return setWriteDeadline(fd, t)
+}
+
+func setReuseAddr(fd *netFD, reuse bool) error {
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse)))
+}
+
+func setDontRoute(fd *netFD, dontroute bool) error {
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute)))
+}
+
+func setKeepAlive(fd *netFD, keepalive bool) error {
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
+}
+
+func setNoDelay(fd *netFD, noDelay bool) error {
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
+}
+
+func setLinger(fd *netFD, sec int) error {
+	var l syscall.Linger
+	if sec >= 0 {
+		l.Onoff = 1
+		l.Linger = int32(sec)
+	} else {
+		l.Onoff = 0
+		l.Linger = 0
+	}
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))
+}
diff --git a/src/pkg/net/sockopt_bsd.go b/src/pkg/net/sockopt_bsd.go
new file mode 100644
index 0000000..2093e08
--- /dev/null
+++ b/src/pkg/net/sockopt_bsd.go
@@ -0,0 +1,45 @@
+// Copyright 2011 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 darwin freebsd netbsd openbsd
+
+// Socket options for BSD variants
+
+package net
+
+import (
+	"syscall"
+)
+
+func setDefaultSockopts(s, f, t int) {
+	switch f {
+	case syscall.AF_INET6:
+		// Allow both IP versions even if the OS default is otherwise.
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
+	}
+
+	if f == syscall.AF_UNIX ||
+		(f == syscall.AF_INET || f == syscall.AF_INET6) && t == syscall.SOCK_STREAM {
+		// Allow reuse of recently-used addresses.
+		syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+
+		// Allow reuse of recently-used ports.
+		// This option is supported only in descendants of 4.4BSD,
+		// to make an effective multicast application and an application
+		// that requires quick draw possible.
+		syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
+	}
+
+	// Allow broadcast.
+	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+}
+
+func setDefaultMulticastSockopts(fd *netFD) {
+	fd.incref()
+	defer fd.decref()
+	// Allow multicast UDP and raw IP datagram sockets to listen
+	// concurrently across multiple listeners.
+	syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+	syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
+}
diff --git a/src/pkg/net/sockopt_linux.go b/src/pkg/net/sockopt_linux.go
new file mode 100644
index 0000000..9dbb4e5
--- /dev/null
+++ b/src/pkg/net/sockopt_linux.go
@@ -0,0 +1,37 @@
+// Copyright 2011 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.
+
+// Socket options for Linux
+
+package net
+
+import (
+	"syscall"
+)
+
+func setDefaultSockopts(s, f, t int) {
+	switch f {
+	case syscall.AF_INET6:
+		// Allow both IP versions even if the OS default is otherwise.
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
+	}
+
+	if f == syscall.AF_UNIX ||
+		(f == syscall.AF_INET || f == syscall.AF_INET6) && t == syscall.SOCK_STREAM {
+		// Allow reuse of recently-used addresses.
+		syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+	}
+
+	// Allow broadcast.
+	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+
+}
+
+func setDefaultMulticastSockopts(fd *netFD) {
+	fd.incref()
+	defer fd.decref()
+	// Allow multicast UDP and raw IP datagram sockets to listen
+	// concurrently across multiple listeners.
+	syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+}
diff --git a/src/pkg/net/sockopt_windows.go b/src/pkg/net/sockopt_windows.go
new file mode 100644
index 0000000..a7b5606
--- /dev/null
+++ b/src/pkg/net/sockopt_windows.go
@@ -0,0 +1,38 @@
+// Copyright 2011 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.
+
+// Socket options for Windows
+
+package net
+
+import (
+	"syscall"
+)
+
+func setDefaultSockopts(s syscall.Handle, f, t int) {
+	switch f {
+	case syscall.AF_INET6:
+		// Allow both IP versions even if the OS default is otherwise.
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
+	}
+
+	// Windows will reuse recently-used addresses by default.
+	// SO_REUSEADDR should not be used here, as it allows
+	// a socket to forcibly bind to a port in use by another socket.
+	// This could lead to a non-deterministic behavior, where
+	// connection requests over the port cannot be guaranteed
+	// to be handled by the correct socket.
+
+	// Allow broadcast.
+	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+
+}
+
+func setDefaultMulticastSockopts(fd *netFD) {
+	fd.incref()
+	defer fd.decref()
+	// Allow multicast UDP and raw IP datagram sockets to listen
+	// concurrently across multiple listeners.
+	syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+}
diff --git a/src/pkg/net/sockoptip.go b/src/pkg/net/sockoptip.go
new file mode 100644
index 0000000..90b6f75
--- /dev/null
+++ b/src/pkg/net/sockoptip.go
@@ -0,0 +1,187 @@
+// Copyright 2011 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 darwin freebsd linux netbsd openbsd windows
+
+// IP-level socket options
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func ipv4TOS(fd *netFD) (int, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS)
+	if err != nil {
+		return -1, os.NewSyscallError("getsockopt", err)
+	}
+	return v, nil
+}
+
+func setIPv4TOS(fd *netFD, v int) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4TTL(fd *netFD) (int, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL)
+	if err != nil {
+		return -1, os.NewSyscallError("getsockopt", err)
+	}
+	return v, nil
+}
+
+func setIPv4TTL(fd *netFD, v int) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+	mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+	if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
+		return err
+	}
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
+}
+
+func leaveIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+	mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+	if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
+		return err
+	}
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
+}
+
+func ipv6HopLimit(fd *netFD) (int, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS)
+	if err != nil {
+		return -1, os.NewSyscallError("getsockopt", err)
+	}
+	return v, nil
+}
+
+func setIPv6HopLimit(fd *netFD, v int) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv6MulticastInterface(fd *netFD) (*Interface, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF)
+	if err != nil {
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+	if v == 0 {
+		return nil, nil
+	}
+	ifi, err := InterfaceByIndex(v)
+	if err != nil {
+		return nil, err
+	}
+	return ifi, nil
+}
+
+func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
+	var v int
+	if ifi != nil {
+		v = ifi.Index
+	}
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv6MulticastHopLimit(fd *netFD) (int, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS)
+	if err != nil {
+		return -1, os.NewSyscallError("getsockopt", err)
+	}
+	return v, nil
+}
+
+func setIPv6MulticastHopLimit(fd *netFD, v int) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv6MulticastLoopback(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv6MulticastLoopback(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
+	mreq := &syscall.IPv6Mreq{}
+	copy(mreq.Multiaddr[:], ip)
+	if ifi != nil {
+		mreq.Interface = uint32(ifi.Index)
+	}
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
+}
+
+func leaveIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
+	mreq := &syscall.IPv6Mreq{}
+	copy(mreq.Multiaddr[:], ip)
+	if ifi != nil {
+		mreq.Interface = uint32(ifi.Index)
+	}
+	fd.incref()
+	defer fd.decref()
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq))
+}
diff --git a/src/pkg/net/sockoptip_bsd.go b/src/pkg/net/sockoptip_bsd.go
new file mode 100644
index 0000000..5f7dff2
--- /dev/null
+++ b/src/pkg/net/sockoptip_bsd.go
@@ -0,0 +1,54 @@
+// Copyright 2011 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 darwin freebsd netbsd openbsd
+
+// IP-level socket options for BSD variants
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func ipv4MulticastTTL(fd *netFD) (int, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
+	if err != nil {
+		return -1, os.NewSyscallError("getsockopt", err)
+	}
+	return int(v), nil
+}
+
+func setIPv4MulticastTTL(fd *netFD, v int) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, byte(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv6TrafficClass(fd *netFD) (int, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
+	if err != nil {
+		return -1, os.NewSyscallError("getsockopt", err)
+	}
+	return v, nil
+}
+
+func setIPv6TrafficClass(fd *netFD, v int) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
diff --git a/src/pkg/net/sockoptip_darwin.go b/src/pkg/net/sockoptip_darwin.go
new file mode 100644
index 0000000..dedfd6f
--- /dev/null
+++ b/src/pkg/net/sockoptip_darwin.go
@@ -0,0 +1,78 @@
+// Copyright 2011 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.
+
+// IP-level socket options for Darwin
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+	fd.incref()
+	defer fd.decref()
+	a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+	if err != nil {
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+	return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	ip, err := interfaceToIPv4Addr(ifi)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	var x [4]byte
+	copy(x[:], ip.To4())
+	fd.incref()
+	defer fd.decref()
+	err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
diff --git a/src/pkg/net/sockoptip_freebsd.go b/src/pkg/net/sockoptip_freebsd.go
new file mode 100644
index 0000000..55f7b1a
--- /dev/null
+++ b/src/pkg/net/sockoptip_freebsd.go
@@ -0,0 +1,80 @@
+// Copyright 2011 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.
+
+// IP-level socket options for FreeBSD
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+	fd.incref()
+	defer fd.decref()
+	mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+	if err != nil {
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+	if int(mreq.Ifindex) == 0 {
+		return nil, nil
+	}
+	return InterfaceByIndex(int(mreq.Ifindex))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	var v int32
+	if ifi != nil {
+		v = int32(ifi.Index)
+	}
+	mreq := &syscall.IPMreqn{Ifindex: v}
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
diff --git a/src/pkg/net/sockoptip_linux.go b/src/pkg/net/sockoptip_linux.go
new file mode 100644
index 0000000..360f8de
--- /dev/null
+++ b/src/pkg/net/sockoptip_linux.go
@@ -0,0 +1,120 @@
+// Copyright 2011 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.
+
+// IP-level socket options for Linux
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+	fd.incref()
+	defer fd.decref()
+	mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+	if err != nil {
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+	if int(mreq.Ifindex) == 0 {
+		return nil, nil
+	}
+	return InterfaceByIndex(int(mreq.Ifindex))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	var v int32
+	if ifi != nil {
+		v = int32(ifi.Index)
+	}
+	mreq := &syscall.IPMreqn{Ifindex: v}
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4MulticastTTL(fd *netFD) (int, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
+	if err != nil {
+		return -1, os.NewSyscallError("getsockopt", err)
+	}
+	return v, nil
+}
+
+func setIPv4MulticastTTL(fd *netFD, v int) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv6TrafficClass(fd *netFD) (int, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
+	if err != nil {
+		return -1, os.NewSyscallError("getsockopt", err)
+	}
+	return v, nil
+}
+
+func setIPv6TrafficClass(fd *netFD, v int) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
diff --git a/src/pkg/net/sockoptip_openbsd.go b/src/pkg/net/sockoptip_openbsd.go
new file mode 100644
index 0000000..89b8e45
--- /dev/null
+++ b/src/pkg/net/sockoptip_openbsd.go
@@ -0,0 +1,78 @@
+// Copyright 2011 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.
+
+// IP-level socket options for OpenBSD
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+	fd.incref()
+	defer fd.decref()
+	a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
+	if err != nil {
+		return nil, os.NewSyscallError("getsockopt", err)
+	}
+	return ipv4AddrToInterface(IPv4(a[0], a[1], a[2], a[3]))
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	ip, err := interfaceToIPv4Addr(ifi)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	var x [4]byte
+	copy(x[:], ip.To4())
+	fd.incref()
+	defer fd.decref()
+	err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+	fd.incref()
+	defer fd.decref()
+	v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
+	if err != nil {
+		return false, os.NewSyscallError("getsockopt", err)
+	}
+	return v == 1, nil
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+	fd.incref()
+	defer fd.decref()
+	err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
+	if err != nil {
+		return os.NewSyscallError("setsockopt", err)
+	}
+	return nil
+}
diff --git a/src/pkg/net/sockoptip_windows.go b/src/pkg/net/sockoptip_windows.go
new file mode 100644
index 0000000..3320e76
--- /dev/null
+++ b/src/pkg/net/sockoptip_windows.go
@@ -0,0 +1,61 @@
+// Copyright 2011 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.
+
+// IP-level socket options for Windows
+
+package net
+
+import (
+	"syscall"
+)
+
+func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
+	// TODO: Implement this
+	return nil, syscall.EWINDOWS
+}
+
+func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
+	// TODO: Implement this
+	return syscall.EWINDOWS
+}
+
+func ipv4MulticastTTL(fd *netFD) (int, error) {
+	// TODO: Implement this
+	return -1, syscall.EWINDOWS
+}
+
+func setIPv4MulticastTTL(fd *netFD, v int) error {
+	// TODO: Implement this
+	return syscall.EWINDOWS
+}
+
+func ipv4MulticastLoopback(fd *netFD) (bool, error) {
+	// TODO: Implement this
+	return false, syscall.EWINDOWS
+}
+
+func setIPv4MulticastLoopback(fd *netFD, v bool) error {
+	// TODO: Implement this
+	return syscall.EWINDOWS
+}
+
+func ipv4ReceiveInterface(fd *netFD) (bool, error) {
+	// TODO: Implement this
+	return false, syscall.EWINDOWS
+}
+
+func setIPv4ReceiveInterface(fd *netFD, v bool) error {
+	// TODO: Implement this
+	return syscall.EWINDOWS
+}
+
+func ipv6TrafficClass(fd *netFD) (int, error) {
+	// TODO: Implement this
+	return 0, syscall.EWINDOWS
+}
+
+func setIPv6TrafficClass(fd *netFD, v int) error {
+	// TODO: Implement this
+	return syscall.EWINDOWS
+}
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index f5c0a27..47fbf29 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -6,10 +6,6 @@
 
 package net
 
-import (
-	"os"
-)
-
 // TCPAddr represents the address of a TCP end point.
 type TCPAddr struct {
 	IP   IP
@@ -31,7 +27,7 @@ func (a *TCPAddr) String() string {
 // numeric addresses on the network net, which must be "tcp",
 // "tcp4" or "tcp6".  A literal IPv6 host address must be
 // enclosed in square brackets, as in "[::]:80".
-func ResolveTCPAddr(net, addr string) (*TCPAddr, os.Error) {
+func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
 	ip, port, err := hostPortToIP(net, addr)
 	if err != nil {
 		return nil, err
diff --git a/src/pkg/net/tcpsock_plan9.go b/src/pkg/net/tcpsock_plan9.go
index f4f6e9f..f2444a4 100644
--- a/src/pkg/net/tcpsock_plan9.go
+++ b/src/pkg/net/tcpsock_plan9.go
@@ -8,6 +8,7 @@ package net
 
 import (
 	"os"
+	"time"
 )
 
 // TCPConn is an implementation of the Conn interface
@@ -16,17 +17,50 @@ type TCPConn struct {
 	plan9Conn
 }
 
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *TCPConn) SetDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *TCPConn) SetReadDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *TCPConn) SetWriteDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
+// CloseRead shuts down the reading side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseRead() error {
+	if !c.ok() {
+		return os.EINVAL
+	}
+	return os.EPLAN9
+}
+
+// CloseWrite shuts down the writing side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseWrite() error {
+	if !c.ok() {
+		return os.EINVAL
+	}
+	return os.EPLAN9
+}
+
 // DialTCP connects to the remote address raddr on the network net,
 // which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
 // as the local address for the connection.
-func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error) {
+func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
 	if raddr == nil {
-		return nil, &OpError{"dial", "tcp", nil, errMissingAddress}
+		return nil, &OpError{"dial", net, nil, errMissingAddress}
 	}
 	c1, err := dialPlan9(net, laddr, raddr)
 	if err != nil {
@@ -46,14 +80,14 @@ type TCPListener struct {
 // Net must be "tcp", "tcp4", or "tcp6".
 // If laddr has a port of 0, it means to listen on some available port.
 // The caller can use l.Addr() to retrieve the chosen address.
-func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) {
+func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
 	switch net {
 	case "tcp", "tcp4", "tcp6":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
 	if laddr == nil {
-		return nil, &OpError{"listen", "tcp", nil, errMissingAddress}
+		return nil, &OpError{"listen", net, nil, errMissingAddress}
 	}
 	l1, err := listenPlan9(net, laddr)
 	if err != nil {
diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go
index 35d536c..65ec493 100644
--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/pkg/net/tcpsock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 // TCP sockets
 
@@ -12,6 +12,7 @@ import (
 	"io"
 	"os"
 	"syscall"
+	"time"
 )
 
 // BUG(rsc): On OpenBSD, listening on the "tcp" network does not listen for
@@ -39,7 +40,7 @@ func (a *TCPAddr) family() int {
 	return syscall.AF_INET6
 }
 
-func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) {
+func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
 	return ipToSockaddr(family, a.IP, a.Port)
 }
 
@@ -67,7 +68,7 @@ func (c *TCPConn) ok() bool { return c != nil && c.fd != nil }
 // Implementation of the Conn interface - see Conn for documentation.
 
 // Read implements the net.Conn Read method.
-func (c *TCPConn) Read(b []byte) (n int, err os.Error) {
+func (c *TCPConn) Read(b []byte) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -75,7 +76,7 @@ func (c *TCPConn) Read(b []byte) (n int, err os.Error) {
 }
 
 // ReadFrom implements the io.ReaderFrom ReadFrom method.
-func (c *TCPConn) ReadFrom(r io.Reader) (int64, os.Error) {
+func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
 	if n, err, handled := sendFile(c.fd, r); handled {
 		return n, err
 	}
@@ -83,7 +84,7 @@ func (c *TCPConn) ReadFrom(r io.Reader) (int64, os.Error) {
 }
 
 // Write implements the net.Conn Write method.
-func (c *TCPConn) Write(b []byte) (n int, err os.Error) {
+func (c *TCPConn) Write(b []byte) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -91,7 +92,7 @@ func (c *TCPConn) Write(b []byte) (n int, err os.Error) {
 }
 
 // Close closes the TCP connection.
-func (c *TCPConn) Close() os.Error {
+func (c *TCPConn) Close() error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -100,6 +101,24 @@ func (c *TCPConn) Close() os.Error {
 	return err
 }
 
+// CloseRead shuts down the reading side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseRead() error {
+	if !c.ok() {
+		return os.EINVAL
+	}
+	return c.fd.CloseRead()
+}
+
+// CloseWrite shuts down the writing side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseWrite() error {
+	if !c.ok() {
+		return os.EINVAL
+	}
+	return c.fd.CloseWrite()
+}
+
 // LocalAddr returns the local network address, a *TCPAddr.
 func (c *TCPConn) LocalAddr() Addr {
 	if !c.ok() {
@@ -116,33 +135,33 @@ func (c *TCPConn) RemoteAddr() Addr {
 	return c.fd.raddr
 }
 
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *TCPConn) SetTimeout(nsec int64) os.Error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *TCPConn) SetDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setTimeout(c.fd, nsec)
+	return setDeadline(c.fd, t)
 }
 
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *TCPConn) SetReadTimeout(nsec int64) os.Error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *TCPConn) SetReadDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setReadTimeout(c.fd, nsec)
+	return setReadDeadline(c.fd, t)
 }
 
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *TCPConn) SetWriteTimeout(nsec int64) os.Error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *TCPConn) SetWriteDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setWriteTimeout(c.fd, nsec)
+	return setWriteDeadline(c.fd, t)
 }
 
 // SetReadBuffer sets the size of the operating system's
 // receive buffer associated with the connection.
-func (c *TCPConn) SetReadBuffer(bytes int) os.Error {
+func (c *TCPConn) SetReadBuffer(bytes int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -151,7 +170,7 @@ func (c *TCPConn) SetReadBuffer(bytes int) os.Error {
 
 // SetWriteBuffer sets the size of the operating system's
 // transmit buffer associated with the connection.
-func (c *TCPConn) SetWriteBuffer(bytes int) os.Error {
+func (c *TCPConn) SetWriteBuffer(bytes int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -169,7 +188,7 @@ func (c *TCPConn) SetWriteBuffer(bytes int) os.Error {
 //
 // If sec > 0, Close blocks for at most sec seconds waiting for
 // data to be sent and acknowledged.
-func (c *TCPConn) SetLinger(sec int) os.Error {
+func (c *TCPConn) SetLinger(sec int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -178,7 +197,7 @@ func (c *TCPConn) SetLinger(sec int) os.Error {
 
 // SetKeepAlive sets whether the operating system should send
 // keepalive messages on the connection.
-func (c *TCPConn) SetKeepAlive(keepalive bool) os.Error {
+func (c *TCPConn) SetKeepAlive(keepalive bool) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -189,7 +208,7 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) os.Error {
 // packet transmission in hopes of sending fewer packets
 // (Nagle's algorithm).  The default is true (no delay), meaning
 // that data is sent as soon as possible after a Write.
-func (c *TCPConn) SetNoDelay(noDelay bool) os.Error {
+func (c *TCPConn) SetNoDelay(noDelay bool) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -199,14 +218,14 @@ func (c *TCPConn) SetNoDelay(noDelay bool) os.Error {
 // File returns a copy of the underlying os.File, set to blocking mode.
 // It is the caller's responsibility to close f when finished.
 // Closing c does not affect f, and closing f does not affect c.
-func (c *TCPConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
+func (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() }
 
 // DialTCP connects to the remote address raddr on the network net,
 // which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
 // as the local address for the connection.
-func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error) {
+func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
 	if raddr == nil {
-		return nil, &OpError{"dial", "tcp", nil, errMissingAddress}
+		return nil, &OpError{"dial", net, nil, errMissingAddress}
 	}
 	fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
 	if e != nil {
@@ -226,15 +245,15 @@ type TCPListener struct {
 // Net must be "tcp", "tcp4", or "tcp6".
 // If laddr has a port of 0, it means to listen on some available port.
 // The caller can use l.Addr() to retrieve the chosen address.
-func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) {
+func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
 	fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
 	if err != nil {
 		return nil, err
 	}
-	errno := syscall.Listen(fd.sysfd, listenBacklog())
-	if errno != 0 {
+	err = syscall.Listen(fd.sysfd, listenerBacklog)
+	if err != nil {
 		closesocket(fd.sysfd)
-		return nil, &OpError{"listen", "tcp", laddr, os.Errno(errno)}
+		return nil, &OpError{"listen", net, laddr, err}
 	}
 	l = new(TCPListener)
 	l.fd = fd
@@ -243,7 +262,7 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error) {
 
 // AcceptTCP accepts the next incoming call and returns the new connection
 // and the remote address.
-func (l *TCPListener) AcceptTCP() (c *TCPConn, err os.Error) {
+func (l *TCPListener) AcceptTCP() (c *TCPConn, err error) {
 	if l == nil || l.fd == nil || l.fd.sysfd < 0 {
 		return nil, os.EINVAL
 	}
@@ -256,7 +275,7 @@ func (l *TCPListener) AcceptTCP() (c *TCPConn, err os.Error) {
 
 // Accept implements the Accept method in the Listener interface;
 // it waits for the next call and returns a generic Conn.
-func (l *TCPListener) Accept() (c Conn, err os.Error) {
+func (l *TCPListener) Accept() (c Conn, err error) {
 	c1, err := l.AcceptTCP()
 	if err != nil {
 		return nil, err
@@ -266,7 +285,7 @@ func (l *TCPListener) Accept() (c Conn, err os.Error) {
 
 // Close stops listening on the TCP address.
 // Already Accepted connections are not closed.
-func (l *TCPListener) Close() os.Error {
+func (l *TCPListener) Close() error {
 	if l == nil || l.fd == nil {
 		return os.EINVAL
 	}
@@ -276,15 +295,16 @@ func (l *TCPListener) Close() os.Error {
 // Addr returns the listener's network address, a *TCPAddr.
 func (l *TCPListener) Addr() Addr { return l.fd.laddr }
 
-// SetTimeout sets the deadline associated with the listener
-func (l *TCPListener) SetTimeout(nsec int64) os.Error {
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *TCPListener) SetDeadline(t time.Time) error {
 	if l == nil || l.fd == nil {
 		return os.EINVAL
 	}
-	return setTimeout(l.fd, nsec)
+	return setDeadline(l.fd, t)
 }
 
 // File returns a copy of the underlying os.File, set to blocking mode.
 // It is the caller's responsibility to close f when finished.
 // Closing c does not affect f, and closing f does not affect c.
-func (l *TCPListener) File() (f *os.File, err os.Error) { return l.fd.dup() }
+func (l *TCPListener) File() (f *os.File, err error) { return l.fd.dup() }
diff --git a/src/pkg/net/textproto/header.go b/src/pkg/net/textproto/header.go
index 288deb2..7fb32f8 100644
--- a/src/pkg/net/textproto/header.go
+++ b/src/pkg/net/textproto/header.go
@@ -39,5 +39,5 @@ func (h MIMEHeader) Get(key string) string {
 
 // Del deletes the values associated with key.
 func (h MIMEHeader) Del(key string) {
-	h[CanonicalMIMEHeaderKey(key)] = nil, false
+	delete(h, CanonicalMIMEHeaderKey(key))
 }
diff --git a/src/pkg/net/textproto/pipeline.go b/src/pkg/net/textproto/pipeline.go
index 8c25884..ca50edd 100644
--- a/src/pkg/net/textproto/pipeline.go
+++ b/src/pkg/net/textproto/pipeline.go
@@ -108,7 +108,7 @@ func (s *sequencer) End(id uint) {
 	}
 	c, ok := s.wait[id]
 	if ok {
-		s.wait[id] = nil, false
+		delete(s.wait, id)
 	}
 	s.mu.Unlock()
 	if ok {
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go
index a404f47..862cd53 100644
--- a/src/pkg/net/textproto/reader.go
+++ b/src/pkg/net/textproto/reader.go
@@ -9,7 +9,6 @@ import (
 	"bytes"
 	"io"
 	"io/ioutil"
-	"os"
 	"strconv"
 	"strings"
 )
@@ -23,6 +22,7 @@ import (
 type Reader struct {
 	R   *bufio.Reader
 	dot *dotReader
+	buf []byte // a re-usable buffer for readContinuedLineSlice
 }
 
 // NewReader returns a new Reader reading from r.
@@ -32,13 +32,13 @@ func NewReader(r *bufio.Reader) *Reader {
 
 // ReadLine reads a single line from r,
 // eliding the final \n or \r\n from the returned string.
-func (r *Reader) ReadLine() (string, os.Error) {
+func (r *Reader) ReadLine() (string, error) {
 	line, err := r.readLineSlice()
 	return string(line), err
 }
 
 // ReadLineBytes is like ReadLine but returns a []byte instead of a string.
-func (r *Reader) ReadLineBytes() ([]byte, os.Error) {
+func (r *Reader) ReadLineBytes() ([]byte, error) {
 	line, err := r.readLineSlice()
 	if line != nil {
 		buf := make([]byte, len(line))
@@ -48,10 +48,24 @@ func (r *Reader) ReadLineBytes() ([]byte, os.Error) {
 	return line, err
 }
 
-func (r *Reader) readLineSlice() ([]byte, os.Error) {
+func (r *Reader) readLineSlice() ([]byte, error) {
 	r.closeDot()
-	line, _, err := r.R.ReadLine()
-	return line, err
+	var line []byte
+	for {
+		l, more, err := r.R.ReadLine()
+		if err != nil {
+			return nil, err
+		}
+		// Avoid the copy if the first call produced a full line.
+		if line == nil && !more {
+			return l, nil
+		}
+		line = append(line, l...)
+		if !more {
+			break
+		}
+	}
+	return line, nil
 }
 
 // ReadContinuedLine reads a possibly continued line from r,
@@ -73,7 +87,7 @@ func (r *Reader) readLineSlice() ([]byte, os.Error) {
 //
 // A line consisting of only white space is never continued.
 //
-func (r *Reader) ReadContinuedLine() (string, os.Error) {
+func (r *Reader) ReadContinuedLine() (string, error) {
 	line, err := r.readContinuedLineSlice()
 	return string(line), err
 }
@@ -94,7 +108,7 @@ func trim(s []byte) []byte {
 
 // ReadContinuedLineBytes is like ReadContinuedLine but
 // returns a []byte instead of a string.
-func (r *Reader) ReadContinuedLineBytes() ([]byte, os.Error) {
+func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
 	line, err := r.readContinuedLineSlice()
 	if line != nil {
 		buf := make([]byte, len(line))
@@ -104,81 +118,51 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, os.Error) {
 	return line, err
 }
 
-func (r *Reader) readContinuedLineSlice() ([]byte, os.Error) {
+func (r *Reader) readContinuedLineSlice() ([]byte, error) {
 	// Read the first line.
 	line, err := r.readLineSlice()
 	if err != nil {
-		return line, err
+		return nil, err
 	}
 	if len(line) == 0 { // blank line - no continuation
 		return line, nil
 	}
-	line = trim(line)
 
-	copied := false
-	if r.R.Buffered() < 1 {
-		// ReadByte will flush the buffer; make a copy of the slice.
-		copied = true
-		line = append([]byte(nil), line...)
-	}
-
-	// Look for a continuation line.
-	c, err := r.R.ReadByte()
-	if err != nil {
-		// Delay err until we read the byte next time.
-		return line, nil
-	}
-	if c != ' ' && c != '\t' {
-		// Not a continuation.
-		r.R.UnreadByte()
-		return line, nil
-	}
-
-	if !copied {
-		// The next readLineSlice will invalidate the previous one.
-		line = append(make([]byte, 0, len(line)*2), line...)
-	}
+	// ReadByte or the next readLineSlice will flush the read buffer;
+	// copy the slice into buf.
+	r.buf = append(r.buf[:0], trim(line)...)
 
 	// Read continuation lines.
-	for {
-		// Consume leading spaces; one already gone.
-		for {
-			c, err = r.R.ReadByte()
-			if err != nil {
-				break
-			}
-			if c != ' ' && c != '\t' {
-				r.R.UnreadByte()
-				break
-			}
-		}
-		var cont []byte
-		cont, err = r.readLineSlice()
-		cont = trim(cont)
-		line = append(line, ' ')
-		line = append(line, cont...)
+	for r.skipSpace() > 0 {
+		line, err := r.readLineSlice()
 		if err != nil {
 			break
 		}
+		r.buf = append(r.buf, ' ')
+		r.buf = append(r.buf, line...)
+	}
+	return r.buf, nil
+}
 
-		// Check for leading space on next line.
-		if c, err = r.R.ReadByte(); err != nil {
+// skipSpace skips R over all spaces and returns the number of bytes skipped.
+func (r *Reader) skipSpace() int {
+	n := 0
+	for {
+		c, err := r.R.ReadByte()
+		if err != nil {
+			// Bufio will keep err until next read.
 			break
 		}
 		if c != ' ' && c != '\t' {
 			r.R.UnreadByte()
 			break
 		}
+		n++
 	}
-
-	// Delay error until next call.
-	if len(line) > 0 {
-		err = nil
-	}
-	return line, err
+	return n
 }
 
-func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message string, err os.Error) {
+func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message string, err error) {
 	line, err := r.ReadLine()
 	if err != nil {
 		return
@@ -186,7 +170,7 @@ func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message
 	return parseCodeLine(line, expectCode)
 }
 
-func parseCodeLine(line string, expectCode int) (code int, continued bool, message string, err os.Error) {
+func parseCodeLine(line string, expectCode int) (code int, continued bool, message string, err error) {
 	if len(line) < 4 || line[3] != ' ' && line[3] != '-' {
 		err = ProtocolError("short response: " + line)
 		return
@@ -221,7 +205,7 @@ func parseCodeLine(line string, expectCode int) (code int, continued bool, messa
 //
 // An expectCode <= 0 disables the check of the status code.
 //
-func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err os.Error) {
+func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err error) {
 	code, continued, message, err := r.readCodeLine(expectCode)
 	if err == nil && continued {
 		err = ProtocolError("unexpected multi-line response: " + message)
@@ -251,12 +235,12 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err os.
 //
 // An expectCode <= 0 disables the check of the status code.
 //
-func (r *Reader) ReadResponse(expectCode int) (code int, message string, err os.Error) {
+func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
 	code, continued, message, err := r.readCodeLine(expectCode)
 	for err == nil && continued {
 		line, err := r.ReadLine()
 		if err != nil {
-			return
+			return 0, "", err
 		}
 
 		var code2 int
@@ -286,7 +270,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err os.
 //
 // The decoded form returned by the Reader's Read method
 // rewrites the "\r\n" line endings into the simpler "\n",
-// removes leading dot escapes if present, and stops with error os.EOF
+// removes leading dot escapes if present, and stops with error io.EOF
 // after consuming (and discarding) the end-of-sequence line.
 func (r *Reader) DotReader() io.Reader {
 	r.closeDot()
@@ -300,7 +284,7 @@ type dotReader struct {
 }
 
 // Read satisfies reads by decoding dot-encoded data read from d.r.
-func (d *dotReader) Read(b []byte) (n int, err os.Error) {
+func (d *dotReader) Read(b []byte) (n int, err error) {
 	// Run data through a simple state machine to
 	// elide leading dots, rewrite trailing \r\n into \n,
 	// and detect ending .\r\n line.
@@ -317,7 +301,7 @@ func (d *dotReader) Read(b []byte) (n int, err os.Error) {
 		var c byte
 		c, err = br.ReadByte()
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				err = io.ErrUnexpectedEOF
 			}
 			break
@@ -379,7 +363,7 @@ func (d *dotReader) Read(b []byte) (n int, err os.Error) {
 		n++
 	}
 	if err == nil && d.state == stateEOF {
-		err = os.EOF
+		err = io.EOF
 	}
 	if err != nil && d.r.dot == d {
 		d.r.dot = nil
@@ -404,7 +388,7 @@ func (r *Reader) closeDot() {
 // ReadDotBytes reads a dot-encoding and returns the decoded data.
 //
 // See the documentation for the DotReader method for details about dot-encoding.
-func (r *Reader) ReadDotBytes() ([]byte, os.Error) {
+func (r *Reader) ReadDotBytes() ([]byte, error) {
 	return ioutil.ReadAll(r.DotReader())
 }
 
@@ -412,17 +396,17 @@ func (r *Reader) ReadDotBytes() ([]byte, os.Error) {
 // containing the decoded lines, with the final \r\n or \n elided from each.
 //
 // See the documentation for the DotReader method for details about dot-encoding.
-func (r *Reader) ReadDotLines() ([]string, os.Error) {
+func (r *Reader) ReadDotLines() ([]string, error) {
 	// We could use ReadDotBytes and then Split it,
 	// but reading a line at a time avoids needing a
 	// large contiguous block of memory and is simpler.
 	var v []string
-	var err os.Error
+	var err error
 	for {
 		var line string
 		line, err = r.ReadLine()
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				err = io.ErrUnexpectedEOF
 			}
 			break
@@ -460,7 +444,7 @@ func (r *Reader) ReadDotLines() ([]string, os.Error) {
 //		"Long-Key": {"Even Longer Value"},
 //	}
 //
-func (r *Reader) ReadMIMEHeader() (MIMEHeader, os.Error) {
+func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
 	m := make(MIMEHeader)
 	for {
 		kv, err := r.readContinuedLineSlice()
diff --git a/src/pkg/net/textproto/reader_test.go b/src/pkg/net/textproto/reader_test.go
index 23ebc3f..4d03691 100644
--- a/src/pkg/net/textproto/reader_test.go
+++ b/src/pkg/net/textproto/reader_test.go
@@ -7,7 +7,6 @@ package textproto
 import (
 	"bufio"
 	"io"
-	"os"
 	"reflect"
 	"strings"
 	"testing"
@@ -49,7 +48,7 @@ func TestReadLine(t *testing.T) {
 		t.Fatalf("Line 2: %s, %v", s, err)
 	}
 	s, err = r.ReadLine()
-	if s != "" || err != os.EOF {
+	if s != "" || err != io.EOF {
 		t.Fatalf("EOF: %s, %v", s, err)
 	}
 }
@@ -69,7 +68,7 @@ func TestReadContinuedLine(t *testing.T) {
 		t.Fatalf("Line 3: %s, %v", s, err)
 	}
 	s, err = r.ReadContinuedLine()
-	if s != "" || err != os.EOF {
+	if s != "" || err != io.EOF {
 		t.Fatalf("EOF: %s, %v", s, err)
 	}
 }
@@ -92,7 +91,7 @@ func TestReadCodeLine(t *testing.T) {
 		t.Fatalf("Line 3: wrong error %v\n", err)
 	}
 	code, msg, err = r.ReadCodeLine(1)
-	if code != 0 || msg != "" || err != os.EOF {
+	if code != 0 || msg != "" || err != io.EOF {
 		t.Fatalf("EOF: %d, %s, %v", code, msg, err)
 	}
 }
@@ -139,6 +138,32 @@ func TestReadMIMEHeader(t *testing.T) {
 	}
 }
 
+func TestReadMIMEHeaderSingle(t *testing.T) {
+	r := reader("Foo: bar\n\n")
+	m, err := r.ReadMIMEHeader()
+	want := MIMEHeader{"Foo": {"bar"}}
+	if !reflect.DeepEqual(m, want) || err != nil {
+		t.Fatalf("ReadMIMEHeader: %v, %v; want %v", m, err, want)
+	}
+}
+
+func TestLargeReadMIMEHeader(t *testing.T) {
+	data := make([]byte, 16*1024)
+	for i := 0; i < len(data); i++ {
+		data[i] = 'x'
+	}
+	sdata := string(data)
+	r := reader("Cookie: " + sdata + "\r\n\n")
+	m, err := r.ReadMIMEHeader()
+	if err != nil {
+		t.Fatalf("ReadMIMEHeader: %v", err)
+	}
+	cookie := m.Get("Cookie")
+	if cookie != sdata {
+		t.Fatalf("ReadMIMEHeader: %v bytes, want %v bytes", len(cookie), len(sdata))
+	}
+}
+
 type readResponseTest struct {
 	in       string
 	inCode   int
@@ -187,7 +212,7 @@ func TestRFC959Lines(t *testing.T) {
 			t.Errorf("#%d: code=%d, want %d", i, code, tt.wantCode)
 		}
 		if msg != tt.wantMsg {
-			t.Errorf("%#d: msg=%q, want %q", i, msg, tt.wantMsg)
+			t.Errorf("#%d: msg=%q, want %q", i, msg, tt.wantMsg)
 		}
 	}
 }
diff --git a/src/pkg/net/textproto/textproto.go b/src/pkg/net/textproto/textproto.go
index 9f19b54..317ec72 100644
--- a/src/pkg/net/textproto/textproto.go
+++ b/src/pkg/net/textproto/textproto.go
@@ -27,7 +27,6 @@ import (
 	"fmt"
 	"io"
 	"net"
-	"os"
 )
 
 // An Error represents a numeric error response from a server.
@@ -36,7 +35,7 @@ type Error struct {
 	Msg  string
 }
 
-func (e *Error) String() string {
+func (e *Error) Error() string {
 	return fmt.Sprintf("%03d %s", e.Code, e.Msg)
 }
 
@@ -44,7 +43,7 @@ func (e *Error) String() string {
 // as an invalid response or a hung-up connection.
 type ProtocolError string
 
-func (p ProtocolError) String() string {
+func (p ProtocolError) Error() string {
 	return string(p)
 }
 
@@ -70,13 +69,13 @@ func NewConn(conn io.ReadWriteCloser) *Conn {
 }
 
 // Close closes the connection.
-func (c *Conn) Close() os.Error {
+func (c *Conn) Close() error {
 	return c.conn.Close()
 }
 
 // Dial connects to the given address on the given network using net.Dial
 // and then returns a new Conn for the connection.
-func Dial(network, addr string) (*Conn, os.Error) {
+func Dial(network, addr string) (*Conn, error) {
 	c, err := net.Dial(network, addr)
 	if err != nil {
 		return nil, err
@@ -109,7 +108,7 @@ func Dial(network, addr string) (*Conn, os.Error) {
 //	}
 //	return c.ReadCodeLine(250)
 //
-func (c *Conn) Cmd(format string, args ...interface{}) (id uint, err os.Error) {
+func (c *Conn) Cmd(format string, args ...interface{}) (id uint, err error) {
 	id = c.Next()
 	c.StartRequest(id)
 	err = c.PrintfLine(format, args...)
diff --git a/src/pkg/net/textproto/writer.go b/src/pkg/net/textproto/writer.go
index 4e705f6..03e2fd6 100644
--- a/src/pkg/net/textproto/writer.go
+++ b/src/pkg/net/textproto/writer.go
@@ -8,7 +8,6 @@ import (
 	"bufio"
 	"fmt"
 	"io"
-	"os"
 )
 
 // A Writer implements convenience methods for writing
@@ -27,7 +26,7 @@ var crnl = []byte{'\r', '\n'}
 var dotcrnl = []byte{'.', '\r', '\n'}
 
 // PrintfLine writes the formatted output followed by \r\n.
-func (w *Writer) PrintfLine(format string, args ...interface{}) os.Error {
+func (w *Writer) PrintfLine(format string, args ...interface{}) error {
 	w.closeDot()
 	fmt.Fprintf(w.W, format, args...)
 	w.W.Write(crnl)
@@ -64,7 +63,7 @@ const (
 	wstateData             // writing data in middle of line
 )
 
-func (d *dotWriter) Write(b []byte) (n int, err os.Error) {
+func (d *dotWriter) Write(b []byte) (n int, err error) {
 	bw := d.w.W
 	for n < len(b) {
 		c := b[n]
@@ -100,7 +99,7 @@ func (d *dotWriter) Write(b []byte) (n int, err os.Error) {
 	return
 }
 
-func (d *dotWriter) Close() os.Error {
+func (d *dotWriter) Close() error {
 	if d.w.dot == d {
 		d.w.dot = nil
 	}
diff --git a/src/pkg/net/timeout_test.go b/src/pkg/net/timeout_test.go
index 0dbab58..bae37c8 100644
--- a/src/pkg/net/timeout_test.go
+++ b/src/pkg/net/timeout_test.go
@@ -5,7 +5,8 @@
 package net
 
 import (
-	"os"
+	"fmt"
+	"runtime"
 	"testing"
 	"time"
 )
@@ -17,35 +18,56 @@ func testTimeout(t *testing.T, network, addr string, readFrom bool) {
 		return
 	}
 	defer fd.Close()
-	t0 := time.Nanoseconds()
-	fd.SetReadTimeout(1e8) // 100ms
-	var b [100]byte
-	var n int
-	var err1 os.Error
-	if readFrom {
-		n, _, err1 = fd.(PacketConn).ReadFrom(b[0:])
-	} else {
-		n, err1 = fd.Read(b[0:])
-	}
-	t1 := time.Nanoseconds()
 	what := "Read"
 	if readFrom {
 		what = "ReadFrom"
 	}
-	if n != 0 || err1 == nil || !err1.(Error).Timeout() {
-		t.Errorf("fd.%s on %s %s did not return 0, timeout: %v, %v", what, network, addr, n, err1)
-	}
-	if t1-t0 < 0.5e8 || t1-t0 > 1.5e8 {
-		t.Errorf("fd.%s on %s %s took %f seconds, expected 0.1", what, network, addr, float64(t1-t0)/1e9)
+
+	errc := make(chan error, 1)
+	go func() {
+		t0 := time.Now()
+		fd.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+		var b [100]byte
+		var n int
+		var err1 error
+		if readFrom {
+			n, _, err1 = fd.(PacketConn).ReadFrom(b[0:])
+		} else {
+			n, err1 = fd.Read(b[0:])
+		}
+		t1 := time.Now()
+		if n != 0 || err1 == nil || !err1.(Error).Timeout() {
+			errc <- fmt.Errorf("fd.%s on %s %s did not return 0, timeout: %v, %v", what, network, addr, n, err1)
+			return
+		}
+		if dt := t1.Sub(t0); dt < 50*time.Millisecond || dt > 250*time.Millisecond {
+			errc <- fmt.Errorf("fd.%s on %s %s took %s, expected 0.1s", what, network, addr, dt)
+			return
+		}
+		errc <- nil
+	}()
+	select {
+	case err := <-errc:
+		if err != nil {
+			t.Error(err)
+		}
+	case <-time.After(1 * time.Second):
+		t.Errorf("%s on %s %s took over 1 second, expected 0.1s", what, network, addr)
 	}
 }
 
 func TestTimeoutUDP(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		return
+	}
 	testTimeout(t, "udp", "127.0.0.1:53", false)
 	testTimeout(t, "udp", "127.0.0.1:53", true)
 }
 
 func TestTimeoutTCP(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		return
+	}
 	// set up a listener that won't talk back
 	listening := make(chan string)
 	done := make(chan int)
@@ -55,3 +77,30 @@ func TestTimeoutTCP(t *testing.T) {
 	testTimeout(t, "tcp", addr, false)
 	<-done
 }
+
+func TestDeadlineReset(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		return
+	}
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+	tl := ln.(*TCPListener)
+	tl.SetDeadline(time.Now().Add(1 * time.Minute))
+	tl.SetDeadline(time.Time{}) // reset it
+	errc := make(chan error, 1)
+	go func() {
+		_, err := ln.Accept()
+		errc <- err
+	}()
+	select {
+	case <-time.After(50 * time.Millisecond):
+		// Pass.
+	case err := <-errc:
+		// Accept should never return; we never
+		// connected to it.
+		t.Errorf("unexpected return from Accept; err=%v", err)
+	}
+}
diff --git a/src/pkg/net/udp_test.go b/src/pkg/net/udp_test.go
new file mode 100644
index 0000000..6ba762b
--- /dev/null
+++ b/src/pkg/net/udp_test.go
@@ -0,0 +1,87 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+	"runtime"
+	"testing"
+)
+
+func TestWriteToUDP(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		return
+	}
+
+	l, err := ListenPacket("udp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+	defer l.Close()
+
+	testWriteToConn(t, l.LocalAddr().String())
+	testWriteToPacketConn(t, l.LocalAddr().String())
+}
+
+func testWriteToConn(t *testing.T, raddr string) {
+	c, err := Dial("udp", raddr)
+	if err != nil {
+		t.Fatalf("Dial failed: %v", err)
+	}
+	defer c.Close()
+
+	ra, err := ResolveUDPAddr("udp", raddr)
+	if err != nil {
+		t.Fatalf("ResolveUDPAddr failed: %v", err)
+	}
+
+	_, err = c.(*UDPConn).WriteToUDP([]byte("Connection-oriented mode socket"), ra)
+	if err == nil {
+		t.Fatal("WriteToUDP should be failed")
+	}
+	if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+		t.Fatalf("WriteToUDP should be failed as ErrWriteToConnected: %v", err)
+	}
+
+	_, err = c.(*UDPConn).WriteTo([]byte("Connection-oriented mode socket"), ra)
+	if err == nil {
+		t.Fatal("WriteTo should be failed")
+	}
+	if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+		t.Fatalf("WriteTo should be failed as ErrWriteToConnected: %v", err)
+	}
+
+	_, err = c.Write([]byte("Connection-oriented mode socket"))
+	if err != nil {
+		t.Fatalf("Write failed: %v", err)
+	}
+}
+
+func testWriteToPacketConn(t *testing.T, raddr string) {
+	c, err := ListenPacket("udp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("ListenPacket failed: %v", err)
+	}
+	defer c.Close()
+
+	ra, err := ResolveUDPAddr("udp", raddr)
+	if err != nil {
+		t.Fatalf("ResolveUDPAddr failed: %v", err)
+	}
+
+	_, err = c.(*UDPConn).WriteToUDP([]byte("Connection-less mode socket"), ra)
+	if err != nil {
+		t.Fatalf("WriteToUDP failed: %v", err)
+	}
+
+	_, err = c.WriteTo([]byte("Connection-less mode socket"), ra)
+	if err != nil {
+		t.Fatalf("WriteTo failed: %v", err)
+	}
+
+	_, err = c.(*UDPConn).Write([]byte("Connection-less mode socket"))
+	if err == nil {
+		t.Fatal("Write should be failed")
+	}
+}
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index 3dfa716..b3520cf 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -6,10 +6,6 @@
 
 package net
 
-import (
-	"os"
-)
-
 // UDPAddr represents the address of a UDP end point.
 type UDPAddr struct {
 	IP   IP
@@ -31,7 +27,7 @@ func (a *UDPAddr) String() string {
 // numeric addresses on the network net, which must be "udp",
 // "udp4" or "udp6".  A literal IPv6 host address must be
 // enclosed in square brackets, as in "[::]:80".
-func ResolveUDPAddr(net, addr string) (*UDPAddr, os.Error) {
+func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
 	ip, port, err := hostPortToIP(net, addr)
 	if err != nil {
 		return nil, err
diff --git a/src/pkg/net/udpsock_plan9.go b/src/pkg/net/udpsock_plan9.go
index d5c6ccb..573438f 100644
--- a/src/pkg/net/udpsock_plan9.go
+++ b/src/pkg/net/udpsock_plan9.go
@@ -7,7 +7,9 @@
 package net
 
 import (
+	"errors"
 	"os"
+	"time"
 )
 
 // UDPConn is the implementation of the Conn and PacketConn
@@ -16,6 +18,21 @@ type UDPConn struct {
 	plan9Conn
 }
 
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UDPConn) SetDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UDPConn) SetReadDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UDPConn) SetWriteDeadline(t time.Time) error {
+	return os.EPLAN9
+}
+
 // UDP-specific methods.
 
 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
@@ -23,8 +40,8 @@ type UDPConn struct {
 // that was on the packet.
 //
 // ReadFromUDP can be made to time out and return an error with Timeout() == true
-// after a fixed time limit; see SetTimeout and SetReadTimeout.
-func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) {
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
+func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
 	if !c.ok() {
 		return 0, nil, os.EINVAL
 	}
@@ -40,7 +57,7 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) {
 		return
 	}
 	if m < udpHeaderSize {
-		return 0, nil, os.NewError("short read reading UDP header")
+		return 0, nil, errors.New("short read reading UDP header")
 	}
 	buf = buf[:m]
 
@@ -50,7 +67,7 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) {
 }
 
 // ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
+func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
 	if !c.ok() {
 		return 0, nil, os.EINVAL
 	}
@@ -61,9 +78,9 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
 //
 // WriteToUDP can be made to time out and return
 // an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
 // On packet-oriented connections, write timeouts are rare.
-func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err os.Error) {
+func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -87,13 +104,13 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err os.Error) {
 }
 
 // WriteTo implements the net.PacketConn WriteTo method.
-func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
+func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
 	a, ok := addr.(*UDPAddr)
 	if !ok {
-		return 0, &OpError{"writeto", "udp", addr, os.EINVAL}
+		return 0, &OpError{"write", c.dir, addr, os.EINVAL}
 	}
 	return c.WriteToUDP(b, a)
 }
@@ -101,14 +118,14 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
 // DialUDP connects to the remote address raddr on the network net,
 // which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is used
 // as the local address for the connection.
-func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err os.Error) {
+func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
 	if raddr == nil {
-		return nil, &OpError{"dial", "udp", nil, errMissingAddress}
+		return nil, &OpError{"dial", net, nil, errMissingAddress}
 	}
 	c1, err := dialPlan9(net, laddr, raddr)
 	if err != nil {
@@ -149,14 +166,14 @@ func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
 // local address laddr.  The returned connection c's ReadFrom
 // and WriteTo methods can be used to receive and send UDP
 // packets with per-packet addressing.
-func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error) {
+func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
 	if laddr == nil {
-		return nil, &OpError{"listen", "udp", nil, errMissingAddress}
+		return nil, &OpError{"listen", net, nil, errMissingAddress}
 	}
 	l, err := listenPlan9(net, laddr)
 	if err != nil {
@@ -172,7 +189,7 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error) {
 // JoinGroup joins the IP multicast group named by addr on ifi,
 // which specifies the interface to join.  JoinGroup uses the
 // default multicast interface if ifi is nil.
-func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) os.Error {
+func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -180,7 +197,7 @@ func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) os.Error {
 }
 
 // LeaveGroup exits the IP multicast group named by addr on ifi.
-func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) os.Error {
+func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go
index 06298ee..fa3d29a 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -2,18 +2,21 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 // UDP sockets
 
 package net
 
 import (
-	"bytes"
+	"errors"
 	"os"
 	"syscall"
+	"time"
 )
 
+var ErrWriteToConnected = errors.New("use of WriteTo with pre-connected UDP")
+
 func sockaddrToUDP(sa syscall.Sockaddr) Addr {
 	switch sa := sa.(type) {
 	case *syscall.SockaddrInet4:
@@ -34,7 +37,7 @@ func (a *UDPAddr) family() int {
 	return syscall.AF_INET6
 }
 
-func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, os.Error) {
+func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
 	return ipToSockaddr(family, a.IP, a.Port)
 }
 
@@ -58,7 +61,7 @@ func (c *UDPConn) ok() bool { return c != nil && c.fd != nil }
 // Implementation of the Conn interface - see Conn for documentation.
 
 // Read implements the net.Conn Read method.
-func (c *UDPConn) Read(b []byte) (n int, err os.Error) {
+func (c *UDPConn) Read(b []byte) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -66,7 +69,7 @@ func (c *UDPConn) Read(b []byte) (n int, err os.Error) {
 }
 
 // Write implements the net.Conn Write method.
-func (c *UDPConn) Write(b []byte) (n int, err os.Error) {
+func (c *UDPConn) Write(b []byte) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -74,7 +77,7 @@ func (c *UDPConn) Write(b []byte) (n int, err os.Error) {
 }
 
 // Close closes the UDP connection.
-func (c *UDPConn) Close() os.Error {
+func (c *UDPConn) Close() error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -99,33 +102,33 @@ func (c *UDPConn) RemoteAddr() Addr {
 	return c.fd.raddr
 }
 
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *UDPConn) SetTimeout(nsec int64) os.Error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UDPConn) SetDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setTimeout(c.fd, nsec)
+	return setDeadline(c.fd, t)
 }
 
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *UDPConn) SetReadTimeout(nsec int64) os.Error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UDPConn) SetReadDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setReadTimeout(c.fd, nsec)
+	return setReadDeadline(c.fd, t)
 }
 
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *UDPConn) SetWriteTimeout(nsec int64) os.Error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UDPConn) SetWriteDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setWriteTimeout(c.fd, nsec)
+	return setWriteDeadline(c.fd, t)
 }
 
 // SetReadBuffer sets the size of the operating system's
 // receive buffer associated with the connection.
-func (c *UDPConn) SetReadBuffer(bytes int) os.Error {
+func (c *UDPConn) SetReadBuffer(bytes int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -134,7 +137,7 @@ func (c *UDPConn) SetReadBuffer(bytes int) os.Error {
 
 // SetWriteBuffer sets the size of the operating system's
 // transmit buffer associated with the connection.
-func (c *UDPConn) SetWriteBuffer(bytes int) os.Error {
+func (c *UDPConn) SetWriteBuffer(bytes int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -148,8 +151,8 @@ func (c *UDPConn) SetWriteBuffer(bytes int) os.Error {
 // that was on the packet.
 //
 // ReadFromUDP can be made to time out and return an error with Timeout() == true
-// after a fixed time limit; see SetTimeout and SetReadTimeout.
-func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) {
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
+func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
 	if !c.ok() {
 		return 0, nil, os.EINVAL
 	}
@@ -164,7 +167,7 @@ func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) {
 }
 
 // ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
+func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
 	if !c.ok() {
 		return 0, nil, os.EINVAL
 	}
@@ -176,27 +179,30 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
 //
 // WriteToUDP can be made to time out and return
 // an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
 // On packet-oriented connections, write timeouts are rare.
-func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err os.Error) {
+func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
-	sa, err1 := addr.sockaddr(c.fd.family)
-	if err1 != nil {
-		return 0, &OpError{Op: "write", Net: "udp", Addr: addr, Error: err1}
+	if c.fd.isConnected {
+		return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
+	}
+	sa, err := addr.sockaddr(c.fd.family)
+	if err != nil {
+		return 0, &OpError{"write", c.fd.net, addr, err}
 	}
 	return c.fd.WriteTo(b, sa)
 }
 
 // WriteTo implements the net.PacketConn WriteTo method.
-func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
+func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
 	a, ok := addr.(*UDPAddr)
 	if !ok {
-		return 0, &OpError{"writeto", "udp", addr, os.EINVAL}
+		return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
 	}
 	return c.WriteToUDP(b, a)
 }
@@ -204,14 +210,14 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
 // DialUDP connects to the remote address raddr on the network net,
 // which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is used
 // as the local address for the connection.
-func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err os.Error) {
+func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
 	if raddr == nil {
-		return nil, &OpError{"dial", "udp", nil, errMissingAddress}
+		return nil, &OpError{"dial", net, nil, errMissingAddress}
 	}
 	fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
 	if e != nil {
@@ -224,44 +230,35 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err os.Error) {
 // local address laddr.  The returned connection c's ReadFrom
 // and WriteTo methods can be used to receive and send UDP
 // packets with per-packet addressing.
-func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error) {
+func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
 	if laddr == nil {
-		return nil, &OpError{"listen", "udp", nil, errMissingAddress}
+		return nil, &OpError{"listen", net, nil, errMissingAddress}
 	}
-	fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
-	if e != nil {
-		return nil, e
+	fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+	if err != nil {
+		return nil, err
 	}
 	return newUDPConn(fd), nil
 }
 
-// BindToDevice binds a UDPConn to a network interface.
-func (c *UDPConn) BindToDevice(device string) os.Error {
-	if !c.ok() {
-		return os.EINVAL
-	}
-	c.fd.incref()
-	defer c.fd.decref()
-	return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device))
-}
-
 // File returns a copy of the underlying os.File, set to blocking mode.
 // It is the caller's responsibility to close f when finished.
 // Closing c does not affect f, and closing f does not affect c.
-func (c *UDPConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
+func (c *UDPConn) File() (f *os.File, err error) { return c.fd.dup() }
 
 // JoinGroup joins the IP multicast group named by addr on ifi,
 // which specifies the interface to join.  JoinGroup uses the
 // default multicast interface if ifi is nil.
-func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) os.Error {
+func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
+	setDefaultMulticastSockopts(c.fd)
 	ip := addr.To4()
 	if ip != nil {
 		return joinIPv4GroupUDP(c, ifi, ip)
@@ -270,7 +267,7 @@ func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) os.Error {
 }
 
 // LeaveGroup exits the IP multicast group named by addr on ifi.
-func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) os.Error {
+func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -281,68 +278,34 @@ func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) os.Error {
 	return leaveIPv6GroupUDP(c, ifi, addr)
 }
 
-func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) os.Error {
-	mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
-	if err := setIPv4InterfaceToJoin(mreq, ifi); err != nil {
-		return &OpError{"joinipv4group", "udp", &IPAddr{ip}, err}
-	}
-	if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)); err != nil {
-		return &OpError{"joinipv4group", "udp", &IPAddr{ip}, err}
-	}
-	return nil
-}
-
-func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) os.Error {
-	mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
-	if err := setIPv4InterfaceToJoin(mreq, ifi); err != nil {
-		return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
-	}
-	if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq)); err != nil {
-		return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
+func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
+	err := joinIPv4Group(c.fd, ifi, ip)
+	if err != nil {
+		return &OpError{"joinipv4group", c.fd.net, &IPAddr{ip}, err}
 	}
 	return nil
 }
 
-func setIPv4InterfaceToJoin(mreq *syscall.IPMreq, ifi *Interface) os.Error {
-	if ifi == nil {
-		return nil
-	}
-	ifat, err := ifi.Addrs()
+func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
+	err := leaveIPv4Group(c.fd, ifi, ip)
 	if err != nil {
-		return err
-	}
-	for _, ifa := range ifat {
-		if x := ifa.(*IPAddr).IP.To4(); x != nil {
-			copy(mreq.Interface[:], x)
-			break
-		}
-	}
-	if bytes.Equal(mreq.Multiaddr[:], IPv4zero) {
-		return os.EINVAL
+		return &OpError{"leaveipv4group", c.fd.net, &IPAddr{ip}, err}
 	}
 	return nil
 }
 
-func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) os.Error {
-	mreq := &syscall.IPv6Mreq{}
-	copy(mreq.Multiaddr[:], ip)
-	if ifi != nil {
-		mreq.Interface = uint32(ifi.Index)
-	}
-	if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(c.fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq)); err != nil {
-		return &OpError{"joinipv6group", "udp", &IPAddr{ip}, err}
+func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
+	err := joinIPv6Group(c.fd, ifi, ip)
+	if err != nil {
+		return &OpError{"joinipv6group", c.fd.net, &IPAddr{ip}, err}
 	}
 	return nil
 }
 
-func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) os.Error {
-	mreq := &syscall.IPv6Mreq{}
-	copy(mreq.Multiaddr[:], ip)
-	if ifi != nil {
-		mreq.Interface = uint32(ifi.Index)
-	}
-	if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(c.fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq)); err != nil {
-		return &OpError{"leaveipv6group", "udp", &IPAddr{ip}, err}
+func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
+	err := leaveIPv6Group(c.fd, ifi, ip)
+	if err != nil {
+		return &OpError{"leaveipv6group", c.fd.net, &IPAddr{ip}, err}
 	}
 	return nil
 }
diff --git a/src/pkg/net/unicast_test.go b/src/pkg/net/unicast_test.go
new file mode 100644
index 0000000..297276d
--- /dev/null
+++ b/src/pkg/net/unicast_test.go
@@ -0,0 +1,111 @@
+// Copyright 2011 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 net
+
+import (
+	"io"
+	"runtime"
+	"testing"
+)
+
+var unicastTests = []struct {
+	net    string
+	laddr  string
+	ipv6   bool
+	packet bool
+}{
+	{net: "tcp4", laddr: "127.0.0.1:0"},
+	{net: "tcp4", laddr: "previous"},
+	{net: "tcp6", laddr: "[::1]:0", ipv6: true},
+	{net: "tcp6", laddr: "previous", ipv6: true},
+	{net: "udp4", laddr: "127.0.0.1:0", packet: true},
+	{net: "udp6", laddr: "[::1]:0", ipv6: true, packet: true},
+}
+
+func TestUnicastTCPAndUDP(t *testing.T) {
+	if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
+		return
+	}
+
+	prevladdr := ""
+	for _, tt := range unicastTests {
+		if tt.ipv6 && !supportsIPv6 {
+			continue
+		}
+		var (
+			fd     *netFD
+			closer io.Closer
+		)
+		if !tt.packet {
+			if tt.laddr == "previous" {
+				tt.laddr = prevladdr
+			}
+			l, err := Listen(tt.net, tt.laddr)
+			if err != nil {
+				t.Fatalf("Listen failed: %v", err)
+			}
+			prevladdr = l.Addr().String()
+			closer = l
+			fd = l.(*TCPListener).fd
+		} else {
+			c, err := ListenPacket(tt.net, tt.laddr)
+			if err != nil {
+				t.Fatalf("ListenPacket failed: %v", err)
+			}
+			closer = c
+			fd = c.(*UDPConn).fd
+		}
+		if !tt.ipv6 {
+			testIPv4UnicastSocketOptions(t, fd)
+		} else {
+			testIPv6UnicastSocketOptions(t, fd)
+		}
+		closer.Close()
+	}
+}
+
+func testIPv4UnicastSocketOptions(t *testing.T, fd *netFD) {
+	tos, err := ipv4TOS(fd)
+	if err != nil {
+		t.Fatalf("ipv4TOS failed: %v", err)
+	}
+	t.Logf("IPv4 TOS: %v", tos)
+	err = setIPv4TOS(fd, 1)
+	if err != nil {
+		t.Fatalf("setIPv4TOS failed: %v", err)
+	}
+
+	ttl, err := ipv4TTL(fd)
+	if err != nil {
+		t.Fatalf("ipv4TTL failed: %v", err)
+	}
+	t.Logf("IPv4 TTL: %v", ttl)
+	err = setIPv4TTL(fd, 1)
+	if err != nil {
+		t.Fatalf("setIPv4TTL failed: %v", err)
+	}
+}
+
+func testIPv6UnicastSocketOptions(t *testing.T, fd *netFD) {
+	tos, err := ipv6TrafficClass(fd)
+	if err != nil {
+		t.Fatalf("ipv6TrafficClass failed: %v", err)
+	}
+	t.Logf("IPv6 TrafficClass: %v", tos)
+	err = setIPv6TrafficClass(fd, 1)
+	if err != nil {
+		t.Fatalf("setIPv6TrafficClass failed: %v", err)
+	}
+
+	hoplim, err := ipv6HopLimit(fd)
+	if err != nil {
+		t.Fatalf("ipv6HopLimit failed: %v", err)
+	}
+	t.Logf("IPv6 HopLimit: %v", hoplim)
+	err = setIPv6HopLimit(fd, 1)
+	if err != nil {
+		t.Fatalf("setIPv6HopLimit failed: %v", err)
+	}
+}
diff --git a/src/pkg/net/unixsock.go b/src/pkg/net/unixsock.go
index d5040f9..ae09569 100644
--- a/src/pkg/net/unixsock.go
+++ b/src/pkg/net/unixsock.go
@@ -6,10 +6,6 @@
 
 package net
 
-import (
-	"os"
-)
-
 // UnixAddr represents the address of a Unix domain socket end point.
 type UnixAddr struct {
 	Name string
@@ -38,7 +34,7 @@ func (a *UnixAddr) toAddr() Addr {
 // ResolveUnixAddr parses addr as a Unix domain socket address.
 // The string net gives the network name, "unix", "unixgram" or
 // "unixpacket".
-func ResolveUnixAddr(net, addr string) (*UnixAddr, os.Error) {
+func ResolveUnixAddr(net, addr string) (*UnixAddr, error) {
 	switch net {
 	case "unix":
 	case "unixpacket":
diff --git a/src/pkg/net/unixsock_plan9.go b/src/pkg/net/unixsock_plan9.go
index 7e212df..e8087d0 100644
--- a/src/pkg/net/unixsock_plan9.go
+++ b/src/pkg/net/unixsock_plan9.go
@@ -8,6 +8,7 @@ package net
 
 import (
 	"os"
+	"time"
 )
 
 // UnixConn is an implementation of the Conn interface
@@ -17,17 +18,17 @@ type UnixConn bool
 // Implementation of the Conn interface - see Conn for documentation.
 
 // Read implements the net.Conn Read method.
-func (c *UnixConn) Read(b []byte) (n int, err os.Error) {
+func (c *UnixConn) Read(b []byte) (n int, err error) {
 	return 0, os.EPLAN9
 }
 
 // Write implements the net.Conn Write method.
-func (c *UnixConn) Write(b []byte) (n int, err os.Error) {
+func (c *UnixConn) Write(b []byte) (n int, err error) {
 	return 0, os.EPLAN9
 }
 
 // Close closes the Unix domain connection.
-func (c *UnixConn) Close() os.Error {
+func (c *UnixConn) Close() error {
 	return os.EPLAN9
 }
 
@@ -44,29 +45,29 @@ func (c *UnixConn) RemoteAddr() Addr {
 	return nil
 }
 
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *UnixConn) SetTimeout(nsec int64) os.Error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UnixConn) SetDeadline(t time.Time) error {
 	return os.EPLAN9
 }
 
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *UnixConn) SetReadTimeout(nsec int64) os.Error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UnixConn) SetReadDeadline(t time.Time) error {
 	return os.EPLAN9
 }
 
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *UnixConn) SetWriteTimeout(nsec int64) os.Error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UnixConn) SetWriteDeadline(t time.Time) error {
 	return os.EPLAN9
 }
 
 // ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
+func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
 	err = os.EPLAN9
 	return
 }
 
 // WriteTo implements the net.PacketConn WriteTo method.
-func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
+func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
 	err = os.EPLAN9
 	return
 }
@@ -74,7 +75,7 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
 // DialUnix connects to the remote address raddr on the network net,
 // which must be "unix" or "unixgram".  If laddr is not nil, it is used
 // as the local address for the connection.
-func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err os.Error) {
+func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error) {
 	return nil, os.EPLAN9
 }
 
@@ -85,19 +86,19 @@ type UnixListener bool
 
 // ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
 // Net must be "unix" (stream sockets).
-func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
+func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err error) {
 	return nil, os.EPLAN9
 }
 
 // Accept implements the Accept method in the Listener interface;
 // it waits for the next call and returns a generic Conn.
-func (l *UnixListener) Accept() (c Conn, err os.Error) {
+func (l *UnixListener) Accept() (c Conn, err error) {
 	return nil, os.EPLAN9
 }
 
 // Close stops listening on the Unix address.
 // Already accepted connections are not closed.
-func (l *UnixListener) Close() os.Error {
+func (l *UnixListener) Close() error {
 	return os.EPLAN9
 }
 
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index fccf018..e500ddb 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 // Unix domain sockets
 
@@ -11,19 +11,20 @@ package net
 import (
 	"os"
 	"syscall"
+	"time"
 )
 
-func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err os.Error) {
-	var proto int
+func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err error) {
+	var sotype int
 	switch net {
 	default:
 		return nil, UnknownNetworkError(net)
 	case "unix":
-		proto = syscall.SOCK_STREAM
+		sotype = syscall.SOCK_STREAM
 	case "unixgram":
-		proto = syscall.SOCK_DGRAM
+		sotype = syscall.SOCK_DGRAM
 	case "unixpacket":
-		proto = syscall.SOCK_SEQPACKET
+		sotype = syscall.SOCK_SEQPACKET
 	}
 
 	var la, ra syscall.Sockaddr
@@ -37,8 +38,8 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
 		}
 		if raddr != nil {
 			ra = &syscall.SockaddrUnix{Name: raddr.Name}
-		} else if proto != syscall.SOCK_DGRAM || laddr == nil {
-			return nil, &OpError{Op: mode, Net: net, Error: errMissingAddress}
+		} else if sotype != syscall.SOCK_DGRAM || laddr == nil {
+			return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
 		}
 
 	case "listen":
@@ -47,18 +48,18 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err
 		}
 		la = &syscall.SockaddrUnix{Name: laddr.Name}
 		if raddr != nil {
-			return nil, &OpError{Op: mode, Net: net, Addr: raddr, Error: &AddrError{Error: "unexpected remote address", Addr: raddr.String()}}
+			return nil, &OpError{Op: mode, Net: net, Addr: raddr, Err: &AddrError{Err: "unexpected remote address", Addr: raddr.String()}}
 		}
 	}
 
 	f := sockaddrToUnix
-	if proto == syscall.SOCK_DGRAM {
+	if sotype == syscall.SOCK_DGRAM {
 		f = sockaddrToUnixgram
-	} else if proto == syscall.SOCK_SEQPACKET {
+	} else if sotype == syscall.SOCK_SEQPACKET {
 		f = sockaddrToUnixpacket
 	}
 
-	fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f)
+	fd, oserr := socket(net, syscall.AF_UNIX, sotype, 0, la, ra, f)
 	if oserr != nil {
 		goto Error
 	}
@@ -69,7 +70,7 @@ Error:
 	if mode == "listen" {
 		addr = laddr
 	}
-	return nil, &OpError{Op: mode, Net: net, Addr: addr, Error: oserr}
+	return nil, &OpError{Op: mode, Net: net, Addr: addr, Err: oserr}
 }
 
 func sockaddrToUnix(sa syscall.Sockaddr) Addr {
@@ -93,8 +94,8 @@ func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
 	return nil
 }
 
-func protoToNet(proto int) string {
-	switch proto {
+func sotypeToNet(sotype int) string {
+	switch sotype {
 	case syscall.SOCK_STREAM:
 		return "unix"
 	case syscall.SOCK_SEQPACKET:
@@ -102,7 +103,7 @@ func protoToNet(proto int) string {
 	case syscall.SOCK_DGRAM:
 		return "unixgram"
 	default:
-		panic("protoToNet unknown protocol")
+		panic("sotypeToNet unknown socket type")
 	}
 	return ""
 }
@@ -120,7 +121,7 @@ func (c *UnixConn) ok() bool { return c != nil && c.fd != nil }
 // Implementation of the Conn interface - see Conn for documentation.
 
 // Read implements the net.Conn Read method.
-func (c *UnixConn) Read(b []byte) (n int, err os.Error) {
+func (c *UnixConn) Read(b []byte) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -128,7 +129,7 @@ func (c *UnixConn) Read(b []byte) (n int, err os.Error) {
 }
 
 // Write implements the net.Conn Write method.
-func (c *UnixConn) Write(b []byte) (n int, err os.Error) {
+func (c *UnixConn) Write(b []byte) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
@@ -136,7 +137,7 @@ func (c *UnixConn) Write(b []byte) (n int, err os.Error) {
 }
 
 // Close closes the Unix domain connection.
-func (c *UnixConn) Close() os.Error {
+func (c *UnixConn) Close() error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -164,33 +165,33 @@ func (c *UnixConn) RemoteAddr() Addr {
 	return c.fd.raddr
 }
 
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *UnixConn) SetTimeout(nsec int64) os.Error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UnixConn) SetDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setTimeout(c.fd, nsec)
+	return setDeadline(c.fd, t)
 }
 
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *UnixConn) SetReadTimeout(nsec int64) os.Error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UnixConn) SetReadDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setReadTimeout(c.fd, nsec)
+	return setReadDeadline(c.fd, t)
 }
 
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *UnixConn) SetWriteTimeout(nsec int64) os.Error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UnixConn) SetWriteDeadline(t time.Time) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
-	return setWriteTimeout(c.fd, nsec)
+	return setWriteDeadline(c.fd, t)
 }
 
 // SetReadBuffer sets the size of the operating system's
 // receive buffer associated with the connection.
-func (c *UnixConn) SetReadBuffer(bytes int) os.Error {
+func (c *UnixConn) SetReadBuffer(bytes int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -199,7 +200,7 @@ func (c *UnixConn) SetReadBuffer(bytes int) os.Error {
 
 // SetWriteBuffer sets the size of the operating system's
 // transmit buffer associated with the connection.
-func (c *UnixConn) SetWriteBuffer(bytes int) os.Error {
+func (c *UnixConn) SetWriteBuffer(bytes int) error {
 	if !c.ok() {
 		return os.EINVAL
 	}
@@ -212,21 +213,21 @@ func (c *UnixConn) SetWriteBuffer(bytes int) os.Error {
 //
 // ReadFromUnix can be made to time out and return
 // an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetReadTimeout.
-func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err os.Error) {
+// see SetDeadline and SetReadDeadline.
+func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
 	if !c.ok() {
 		return 0, nil, os.EINVAL
 	}
 	n, sa, err := c.fd.ReadFrom(b)
 	switch sa := sa.(type) {
 	case *syscall.SockaddrUnix:
-		addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
+		addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
 	}
 	return
 }
 
 // ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
+func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
 	if !c.ok() {
 		return 0, nil, os.EINVAL
 	}
@@ -238,13 +239,13 @@ func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
 //
 // WriteToUnix can be made to time out and return
 // an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
 // On packet-oriented connections, write timeouts are rare.
-func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) {
+func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
-	if addr.Net != protoToNet(c.fd.proto) {
+	if addr.Net != sotypeToNet(c.fd.sotype) {
 		return 0, os.EAFNOSUPPORT
 	}
 	sa := &syscall.SockaddrUnix{Name: addr.Name}
@@ -252,35 +253,35 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) {
 }
 
 // WriteTo implements the net.PacketConn WriteTo method.
-func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
+func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
 	if !c.ok() {
 		return 0, os.EINVAL
 	}
 	a, ok := addr.(*UnixAddr)
 	if !ok {
-		return 0, &OpError{"writeto", "unix", addr, os.EINVAL}
+		return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
 	}
 	return c.WriteToUnix(b, a)
 }
 
-func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err os.Error) {
+func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
 	if !c.ok() {
 		return 0, 0, 0, nil, os.EINVAL
 	}
 	n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
 	switch sa := sa.(type) {
 	case *syscall.SockaddrUnix:
-		addr = &UnixAddr{sa.Name, protoToNet(c.fd.proto)}
+		addr = &UnixAddr{sa.Name, sotypeToNet(c.fd.sotype)}
 	}
 	return
 }
 
-func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err os.Error) {
+func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
 	if !c.ok() {
 		return 0, 0, os.EINVAL
 	}
 	if addr != nil {
-		if addr.Net != protoToNet(c.fd.proto) {
+		if addr.Net != sotypeToNet(c.fd.sotype) {
 			return 0, 0, os.EAFNOSUPPORT
 		}
 		sa := &syscall.SockaddrUnix{Name: addr.Name}
@@ -292,12 +293,12 @@ func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err
 // File returns a copy of the underlying os.File, set to blocking mode.
 // It is the caller's responsibility to close f when finished.
 // Closing c does not affect f, and closing f does not affect c.
-func (c *UnixConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
+func (c *UnixConn) File() (f *os.File, err error) { return c.fd.dup() }
 
 // DialUnix connects to the remote address raddr on the network net,
 // which must be "unix" or "unixgram".  If laddr is not nil, it is used
 // as the local address for the connection.
-func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err os.Error) {
+func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error) {
 	fd, e := unixSocket(net, laddr, raddr, "dial")
 	if e != nil {
 		return nil, e
@@ -315,7 +316,7 @@ type UnixListener struct {
 
 // ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
 // Net must be "unix" (stream sockets).
-func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
+func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
 	if net != "unix" && net != "unixgram" && net != "unixpacket" {
 		return nil, UnknownNetworkError(net)
 	}
@@ -326,17 +327,17 @@ func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
 	if err != nil {
 		return nil, err
 	}
-	e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog());
-	if e1 != 0 {
+	err = syscall.Listen(fd.sysfd, listenerBacklog)
+	if err != nil {
 		closesocket(fd.sysfd)
-		return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Error: os.Errno(e1)}
+		return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
 	}
 	return &UnixListener{fd, laddr.Name}, nil
 }
 
 // AcceptUnix accepts the next incoming call and returns the new connection
 // and the remote address.
-func (l *UnixListener) AcceptUnix() (c *UnixConn, err os.Error) {
+func (l *UnixListener) AcceptUnix() (c *UnixConn, err error) {
 	if l == nil || l.fd == nil {
 		return nil, os.EINVAL
 	}
@@ -350,7 +351,7 @@ func (l *UnixListener) AcceptUnix() (c *UnixConn, err os.Error) {
 
 // Accept implements the Accept method in the Listener interface;
 // it waits for the next call and returns a generic Conn.
-func (l *UnixListener) Accept() (c Conn, err os.Error) {
+func (l *UnixListener) Accept() (c Conn, err error) {
 	c1, err := l.AcceptUnix()
 	if err != nil {
 		return nil, err
@@ -360,7 +361,7 @@ func (l *UnixListener) Accept() (c Conn, err os.Error) {
 
 // Close stops listening on the Unix address.
 // Already accepted connections are not closed.
-func (l *UnixListener) Close() os.Error {
+func (l *UnixListener) Close() error {
 	if l == nil || l.fd == nil {
 		return os.EINVAL
 	}
@@ -386,31 +387,32 @@ func (l *UnixListener) Close() os.Error {
 // Addr returns the listener's network address.
 func (l *UnixListener) Addr() Addr { return l.fd.laddr }
 
-// SetTimeout sets the deadline associated wuth the listener
-func (l *UnixListener) SetTimeout(nsec int64) (err os.Error) {
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *UnixListener) SetDeadline(t time.Time) (err error) {
 	if l == nil || l.fd == nil {
 		return os.EINVAL
 	}
-	return setTimeout(l.fd, nsec)
+	return setDeadline(l.fd, t)
 }
 
 // File returns a copy of the underlying os.File, set to blocking mode.
 // It is the caller's responsibility to close f when finished.
 // Closing c does not affect f, and closing f does not affect c.
-func (l *UnixListener) File() (f *os.File, err os.Error) { return l.fd.dup() }
+func (l *UnixListener) File() (f *os.File, err error) { return l.fd.dup() }
 
 // ListenUnixgram listens for incoming Unix datagram packets addressed to the
 // local address laddr.  The returned connection c's ReadFrom
 // and WriteTo methods can be used to receive and send UDP
 // packets with per-packet addressing.  The network net must be "unixgram".
-func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err os.Error) {
+func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err error) {
 	switch net {
 	case "unixgram":
 	default:
 		return nil, UnknownNetworkError(net)
 	}
 	if laddr == nil {
-		return nil, &OpError{"listen", "unixgram", nil, errMissingAddress}
+		return nil, &OpError{"listen", net, nil, errMissingAddress}
 	}
 	fd, e := unixSocket(net, laddr, nil, "listen")
 	if e != nil {
diff --git a/src/pkg/net/url/Makefile b/src/pkg/net/url/Makefile
new file mode 100644
index 0000000..bef0647
--- /dev/null
+++ b/src/pkg/net/url/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=net/url
+GOFILES=\
+	url.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/net/url/url.go b/src/pkg/net/url/url.go
new file mode 100644
index 0000000..0068e98
--- /dev/null
+++ b/src/pkg/net/url/url.go
@@ -0,0 +1,664 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package URL parses URLs and implements query escaping.
+// See RFC 3986.
+package url
+
+import (
+	"errors"
+	"strconv"
+	"strings"
+)
+
+// Error reports an error and the operation and URL that caused it.
+type Error struct {
+	Op  string
+	URL string
+	Err error
+}
+
+func (e *Error) Error() string { return e.Op + " " + e.URL + ": " + e.Err.Error() }
+
+func ishex(c byte) bool {
+	switch {
+	case '0' <= c && c <= '9':
+		return true
+	case 'a' <= c && c <= 'f':
+		return true
+	case 'A' <= c && c <= 'F':
+		return true
+	}
+	return false
+}
+
+func unhex(c byte) byte {
+	switch {
+	case '0' <= c && c <= '9':
+		return c - '0'
+	case 'a' <= c && c <= 'f':
+		return c - 'a' + 10
+	case 'A' <= c && c <= 'F':
+		return c - 'A' + 10
+	}
+	return 0
+}
+
+type encoding int
+
+const (
+	encodePath encoding = 1 + iota
+	encodeUserPassword
+	encodeQueryComponent
+	encodeFragment
+)
+
+type EscapeError string
+
+func (e EscapeError) Error() string {
+	return "invalid URL escape " + strconv.Quote(string(e))
+}
+
+// Return true if the specified character should be escaped when
+// appearing in a URL string, according to RFC 2396.
+// When 'all' is true the full range of reserved characters are matched.
+func shouldEscape(c byte, mode encoding) bool {
+	// RFC 2396 §2.3 Unreserved characters (alphanum)
+	if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' {
+		return false
+	}
+	// TODO: Update the character sets after RFC 3986.
+	switch c {
+	case '-', '_', '.', '!', '~', '*', '\'', '(', ')': // §2.3 Unreserved characters (mark)
+		return false
+
+	case '$', '&', '+', ',', '/', ':', ';', '=', '?', '@': // §2.2 Reserved characters (reserved)
+		// Different sections of the URL allow a few of
+		// the reserved characters to appear unescaped.
+		switch mode {
+		case encodePath: // §3.3
+			// The RFC allows : @ & = + $ but saves / ; , for assigning
+			// meaning to individual path segments. This package
+			// only manipulates the path as a whole, so we allow those
+			// last two as well. That leaves only ? to escape.
+			return c == '?'
+
+		case encodeUserPassword: // §3.2.2
+			// The RFC allows ; : & = + $ , in userinfo, so we must escape only @ and /.
+			// The parsing of userinfo treats : as special so we must escape that too.
+			return c == '@' || c == '/' || c == ':'
+
+		case encodeQueryComponent: // §3.4
+			// The RFC reserves (so we must escape) everything.
+			return true
+
+		case encodeFragment: // §4.1
+			// The RFC text is silent but the grammar allows
+			// everything, so escape nothing.
+			return false
+		}
+	}
+
+	// Everything else must be escaped.
+	return true
+}
+
+// QueryUnescape does the inverse transformation of QueryEscape, converting
+// %AB into the byte 0xAB and '+' into ' ' (space). It returns an error if
+// any % is not followed by two hexadecimal digits.
+func QueryUnescape(s string) (string, error) {
+	return unescape(s, encodeQueryComponent)
+}
+
+// unescape unescapes a string; the mode specifies
+// which section of the URL string is being unescaped.
+func unescape(s string, mode encoding) (string, error) {
+	// Count %, check that they're well-formed.
+	n := 0
+	hasPlus := false
+	for i := 0; i < len(s); {
+		switch s[i] {
+		case '%':
+			n++
+			if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
+				s = s[i:]
+				if len(s) > 3 {
+					s = s[0:3]
+				}
+				return "", EscapeError(s)
+			}
+			i += 3
+		case '+':
+			hasPlus = mode == encodeQueryComponent
+			i++
+		default:
+			i++
+		}
+	}
+
+	if n == 0 && !hasPlus {
+		return s, nil
+	}
+
+	t := make([]byte, len(s)-2*n)
+	j := 0
+	for i := 0; i < len(s); {
+		switch s[i] {
+		case '%':
+			t[j] = unhex(s[i+1])<<4 | unhex(s[i+2])
+			j++
+			i += 3
+		case '+':
+			if mode == encodeQueryComponent {
+				t[j] = ' '
+			} else {
+				t[j] = '+'
+			}
+			j++
+			i++
+		default:
+			t[j] = s[i]
+			j++
+			i++
+		}
+	}
+	return string(t), nil
+}
+
+// QueryEscape escapes the string so it can be safely placed
+// inside a URL query.
+func QueryEscape(s string) string {
+	return escape(s, encodeQueryComponent)
+}
+
+func escape(s string, mode encoding) string {
+	spaceCount, hexCount := 0, 0
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if shouldEscape(c, mode) {
+			if c == ' ' && mode == encodeQueryComponent {
+				spaceCount++
+			} else {
+				hexCount++
+			}
+		}
+	}
+
+	if spaceCount == 0 && hexCount == 0 {
+		return s
+	}
+
+	t := make([]byte, len(s)+2*hexCount)
+	j := 0
+	for i := 0; i < len(s); i++ {
+		switch c := s[i]; {
+		case c == ' ' && mode == encodeQueryComponent:
+			t[j] = '+'
+			j++
+		case shouldEscape(c, mode):
+			t[j] = '%'
+			t[j+1] = "0123456789ABCDEF"[c>>4]
+			t[j+2] = "0123456789ABCDEF"[c&15]
+			j += 3
+		default:
+			t[j] = s[i]
+			j++
+		}
+	}
+	return string(t)
+}
+
+// A URL represents a parsed URL (technically, a URI reference).
+// The general form represented is:
+//
+//	scheme://[userinfo@]host/path[?query][#fragment]
+//
+// URLs that do not start with a slash after the scheme are interpreted as:
+//
+//	scheme:opaque[?query][#fragment]
+//
+type URL struct {
+	Scheme   string
+	Opaque   string    // encoded opaque data
+	User     *Userinfo // username and password information
+	Host     string
+	Path     string
+	RawQuery string // encoded query values, without '?'
+	Fragment string // fragment for references, without '#'
+}
+
+// User returns a Userinfo containing the provided username
+// and no password set.
+func User(username string) *Userinfo {
+	return &Userinfo{username, "", false}
+}
+
+// UserPassword returns a Userinfo containing the provided username
+// and password.
+// This functionality should only be used with legacy web sites.
+// RFC 2396 warns that interpreting Userinfo this way
+// ``is NOT RECOMMENDED, because the passing of authentication
+// information in clear text (such as URI) has proven to be a
+// security risk in almost every case where it has been used.''
+func UserPassword(username, password string) *Userinfo {
+	return &Userinfo{username, password, true}
+}
+
+// The Userinfo type is an immutable encapsulation of username and
+// password details for a URL. An existing Userinfo value is guaranteed
+// to have a username set (potentially empty, as allowed by RFC 2396),
+// and optionally a password.
+type Userinfo struct {
+	username    string
+	password    string
+	passwordSet bool
+}
+
+// Username returns the username.
+func (u *Userinfo) Username() string {
+	return u.username
+}
+
+// Password returns the password in case it is set, and whether it is set.
+func (u *Userinfo) Password() (string, bool) {
+	if u.passwordSet {
+		return u.password, true
+	}
+	return "", false
+}
+
+// String returns the encoded userinfo information in the standard form
+// of "username[:password]".
+func (u *Userinfo) String() string {
+	s := escape(u.username, encodeUserPassword)
+	if u.passwordSet {
+		s += ":" + escape(u.password, encodeUserPassword)
+	}
+	return s
+}
+
+// Maybe rawurl is of the form scheme:path.
+// (Scheme must be [a-zA-Z][a-zA-Z0-9+-.]*)
+// If so, return scheme, path; else return "", rawurl.
+func getscheme(rawurl string) (scheme, path string, err error) {
+	for i := 0; i < len(rawurl); i++ {
+		c := rawurl[i]
+		switch {
+		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+		// do nothing
+		case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.':
+			if i == 0 {
+				return "", rawurl, nil
+			}
+		case c == ':':
+			if i == 0 {
+				return "", "", errors.New("missing protocol scheme")
+			}
+			return rawurl[0:i], rawurl[i+1:], nil
+		default:
+			// we have encountered an invalid character,
+			// so there is no valid scheme
+			return "", rawurl, nil
+		}
+	}
+	return "", rawurl, nil
+}
+
+// Maybe s is of the form t c u.
+// If so, return t, c u (or t, u if cutc == true).
+// If not, return s, "".
+func split(s string, c byte, cutc bool) (string, string) {
+	for i := 0; i < len(s); i++ {
+		if s[i] == c {
+			if cutc {
+				return s[0:i], s[i+1:]
+			}
+			return s[0:i], s[i:]
+		}
+	}
+	return s, ""
+}
+
+// Parse parses rawurl into a URL structure.
+// The string rawurl is assumed not to have a #fragment suffix.
+// (Web browsers strip #fragment before sending the URL to a web server.)
+// The rawurl may be relative or absolute.
+func Parse(rawurl string) (url *URL, err error) {
+	return parse(rawurl, false)
+}
+
+// ParseRequest parses rawurl into a URL structure.  It assumes that
+// rawurl was received from an HTTP request, so the rawurl is interpreted
+// only as an absolute URI or an absolute path.
+// The string rawurl is assumed not to have a #fragment suffix.
+// (Web browsers strip #fragment before sending the URL to a web server.)
+func ParseRequest(rawurl string) (url *URL, err error) {
+	return parse(rawurl, true)
+}
+
+// parse parses a URL from a string in one of two contexts.  If
+// viaRequest is true, the URL is assumed to have arrived via an HTTP request,
+// in which case only absolute URLs or path-absolute relative URLs are allowed.
+// If viaRequest is false, all forms of relative URLs are allowed.
+func parse(rawurl string, viaRequest bool) (url *URL, err error) {
+	var rest string
+
+	if rawurl == "" {
+		err = errors.New("empty url")
+		goto Error
+	}
+	url = new(URL)
+
+	// Split off possible leading "http:", "mailto:", etc.
+	// Cannot contain escaped characters.
+	if url.Scheme, rest, err = getscheme(rawurl); err != nil {
+		goto Error
+	}
+
+	rest, url.RawQuery = split(rest, '?', true)
+
+	if !strings.HasPrefix(rest, "/") {
+		if url.Scheme != "" {
+			// We consider rootless paths per RFC 3986 as opaque.
+			url.Opaque = rest
+			return url, nil
+		}
+		if viaRequest {
+			err = errors.New("invalid URI for request")
+			goto Error
+		}
+	}
+
+	if (url.Scheme != "" || !viaRequest) && strings.HasPrefix(rest, "//") && !strings.HasPrefix(rest, "///") {
+		var authority string
+		authority, rest = split(rest[2:], '/', false)
+		url.User, url.Host, err = parseAuthority(authority)
+		if err != nil {
+			goto Error
+		}
+		if strings.Contains(url.Host, "%") {
+			err = errors.New("hexadecimal escape in host")
+			goto Error
+		}
+	}
+	if url.Path, err = unescape(rest, encodePath); err != nil {
+		goto Error
+	}
+	return url, nil
+
+Error:
+	return nil, &Error{"parse", rawurl, err}
+}
+
+func parseAuthority(authority string) (user *Userinfo, host string, err error) {
+	if strings.Index(authority, "@") < 0 {
+		host = authority
+		return
+	}
+	userinfo, host := split(authority, '@', true)
+	if strings.Index(userinfo, ":") < 0 {
+		if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
+			return
+		}
+		user = User(userinfo)
+	} else {
+		username, password := split(userinfo, ':', true)
+		if username, err = unescape(username, encodeUserPassword); err != nil {
+			return
+		}
+		if password, err = unescape(password, encodeUserPassword); err != nil {
+			return
+		}
+		user = UserPassword(username, password)
+	}
+	return
+}
+
+// ParseWithReference is like Parse but allows a trailing #fragment.
+func ParseWithReference(rawurlref string) (url *URL, err error) {
+	// Cut off #frag
+	rawurl, frag := split(rawurlref, '#', true)
+	if url, err = Parse(rawurl); err != nil {
+		return nil, err
+	}
+	if frag == "" {
+		return url, nil
+	}
+	if url.Fragment, err = unescape(frag, encodeFragment); err != nil {
+		return nil, &Error{"parse", rawurlref, err}
+	}
+	return url, nil
+}
+
+// String reassembles url into a valid URL string.
+func (url *URL) String() string {
+	// TODO: Rewrite to use bytes.Buffer
+	result := ""
+	if url.Scheme != "" {
+		result += url.Scheme + ":"
+	}
+	if url.Opaque != "" {
+		result += url.Opaque
+	} else {
+		if url.Host != "" || url.User != nil {
+			result += "//"
+			if u := url.User; u != nil {
+				result += u.String() + "@"
+			}
+			result += url.Host
+		}
+		result += escape(url.Path, encodePath)
+	}
+	if url.RawQuery != "" {
+		result += "?" + url.RawQuery
+	}
+	if url.Fragment != "" {
+		result += "#" + escape(url.Fragment, encodeFragment)
+	}
+	return result
+}
+
+// Values maps a string key to a list of values.
+// It is typically used for query parameters and form values.
+// Unlike in the http.Header map, the keys in a Values map
+// are case-sensitive.
+type Values map[string][]string
+
+// Get gets the first value associated with the given key.
+// If there are no values associated with the key, Get returns
+// the empty string. To access multiple values, use the map
+// directly.
+func (v Values) Get(key string) string {
+	if v == nil {
+		return ""
+	}
+	vs, ok := v[key]
+	if !ok || len(vs) == 0 {
+		return ""
+	}
+	return vs[0]
+}
+
+// Set sets the key to value. It replaces any existing
+// values.
+func (v Values) Set(key, value string) {
+	v[key] = []string{value}
+}
+
+// Add adds the key to value. It appends to any existing
+// values associated with key.
+func (v Values) Add(key, value string) {
+	v[key] = append(v[key], value)
+}
+
+// Del deletes the values associated with key.
+func (v Values) Del(key string) {
+	delete(v, key)
+}
+
+// ParseQuery parses the URL-encoded query string and returns
+// a map listing the values specified for each key.
+// ParseQuery always returns a non-nil map containing all the
+// valid query parameters found; err describes the first decoding error
+// encountered, if any.
+func ParseQuery(query string) (m Values, err error) {
+	m = make(Values)
+	err = parseQuery(m, query)
+	return
+}
+
+func parseQuery(m Values, query string) (err error) {
+	for query != "" {
+		key := query
+		if i := strings.IndexAny(key, "&;"); i >= 0 {
+			key, query = key[:i], key[i+1:]
+		} else {
+			query = ""
+		}
+		if key == "" {
+			continue
+		}
+		value := ""
+		if i := strings.Index(key, "="); i >= 0 {
+			key, value = key[:i], key[i+1:]
+		}
+		key, err1 := QueryUnescape(key)
+		if err1 != nil {
+			err = err1
+			continue
+		}
+		value, err1 = QueryUnescape(value)
+		if err1 != nil {
+			err = err1
+			continue
+		}
+		m[key] = append(m[key], value)
+	}
+	return err
+}
+
+// Encode encodes the values into ``URL encoded'' form.
+// e.g. "foo=bar&bar=baz"
+func (v Values) Encode() string {
+	if v == nil {
+		return ""
+	}
+	parts := make([]string, 0, len(v)) // will be large enough for most uses
+	for k, vs := range v {
+		prefix := QueryEscape(k) + "="
+		for _, v := range vs {
+			parts = append(parts, prefix+QueryEscape(v))
+		}
+	}
+	return strings.Join(parts, "&")
+}
+
+// resolvePath applies special path segments from refs and applies
+// them to base, per RFC 2396.
+func resolvePath(basepath string, refpath string) string {
+	base := strings.Split(basepath, "/")
+	refs := strings.Split(refpath, "/")
+	if len(base) == 0 {
+		base = []string{""}
+	}
+	for idx, ref := range refs {
+		switch {
+		case ref == ".":
+			base[len(base)-1] = ""
+		case ref == "..":
+			newLen := len(base) - 1
+			if newLen < 1 {
+				newLen = 1
+			}
+			base = base[0:newLen]
+			base[len(base)-1] = ""
+		default:
+			if idx == 0 || base[len(base)-1] == "" {
+				base[len(base)-1] = ref
+			} else {
+				base = append(base, ref)
+			}
+		}
+	}
+	return strings.Join(base, "/")
+}
+
+// IsAbs returns true if the URL is absolute.
+func (url *URL) IsAbs() bool {
+	return url.Scheme != ""
+}
+
+// Parse parses a URL in the context of a base URL.  The URL in ref
+// may be relative or absolute.  Parse returns nil, err on parse
+// failure, otherwise its return value is the same as ResolveReference.
+func (base *URL) Parse(ref string) (*URL, error) {
+	refurl, err := Parse(ref)
+	if err != nil {
+		return nil, err
+	}
+	return base.ResolveReference(refurl), nil
+}
+
+// ResolveReference resolves a URI reference to an absolute URI from
+// an absolute base URI, per RFC 2396 Section 5.2.  The URI reference
+// may be relative or absolute.  ResolveReference always returns a new
+// URL instance, even if the returned URL is identical to either the
+// base or reference. If ref is an absolute URL, then ResolveReference
+// ignores base and returns a copy of ref.
+func (base *URL) ResolveReference(ref *URL) *URL {
+	if ref.IsAbs() {
+		url := *ref
+		return &url
+	}
+	// relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
+	url := *base
+	url.RawQuery = ref.RawQuery
+	url.Fragment = ref.Fragment
+	if ref.Opaque != "" {
+		url.Opaque = ref.Opaque
+		url.User = nil
+		url.Host = ""
+		url.Path = ""
+		return &url
+	}
+	if ref.Host != "" || ref.User != nil {
+		// The "net_path" case.
+		url.Host = ref.Host
+		url.User = ref.User
+	}
+	if strings.HasPrefix(ref.Path, "/") {
+		// The "abs_path" case.
+		url.Path = ref.Path
+	} else {
+		// The "rel_path" case.
+		path := resolvePath(base.Path, ref.Path)
+		if !strings.HasPrefix(path, "/") {
+			path = "/" + path
+		}
+		url.Path = path
+	}
+	return &url
+}
+
+// Query parses RawQuery and returns the corresponding values.
+func (u *URL) Query() Values {
+	v, _ := ParseQuery(u.RawQuery)
+	return v
+}
+
+// RequestURI returns the encoded path?query or opaque?query
+// string that would be used in an HTTP request for u.
+func (u *URL) RequestURI() string {
+	result := u.Opaque
+	if result == "" {
+		result = escape(u.Path, encodePath)
+		if result == "" {
+			result = "/"
+		}
+	}
+	if u.RawQuery != "" {
+		result += "?" + u.RawQuery
+	}
+	return result
+}
diff --git a/src/pkg/net/url/url_test.go b/src/pkg/net/url/url_test.go
new file mode 100644
index 0000000..9fe5ff8
--- /dev/null
+++ b/src/pkg/net/url/url_test.go
@@ -0,0 +1,771 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package url
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+)
+
+type URLTest struct {
+	in        string
+	out       *URL
+	roundtrip string // expected result of reserializing the URL; empty means same as "in".
+}
+
+var urltests = []URLTest{
+	// no path
+	{
+		"http://www.google.com",
+		&URL{
+			Scheme: "http",
+			Host:   "www.google.com",
+		},
+		"",
+	},
+	// path
+	{
+		"http://www.google.com/",
+		&URL{
+			Scheme: "http",
+			Host:   "www.google.com",
+			Path:   "/",
+		},
+		"",
+	},
+	// path with hex escaping
+	{
+		"http://www.google.com/file%20one%26two",
+		&URL{
+			Scheme: "http",
+			Host:   "www.google.com",
+			Path:   "/file one&two",
+		},
+		"http://www.google.com/file%20one&two",
+	},
+	// user
+	{
+		"ftp://webmaster@www.google.com/",
+		&URL{
+			Scheme: "ftp",
+			User:   User("webmaster"),
+			Host:   "www.google.com",
+			Path:   "/",
+		},
+		"",
+	},
+	// escape sequence in username
+	{
+		"ftp://john%20doe@www.google.com/",
+		&URL{
+			Scheme: "ftp",
+			User:   User("john doe"),
+			Host:   "www.google.com",
+			Path:   "/",
+		},
+		"ftp://john%20doe@www.google.com/",
+	},
+	// query
+	{
+		"http://www.google.com/?q=go+language",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go+language",
+		},
+		"",
+	},
+	// query with hex escaping: NOT parsed
+	{
+		"http://www.google.com/?q=go%20language",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go%20language",
+		},
+		"",
+	},
+	// %20 outside query
+	{
+		"http://www.google.com/a%20b?q=c+d",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/a b",
+			RawQuery: "q=c+d",
+		},
+		"",
+	},
+	// path without leading /, so no parsing
+	{
+		"http:www.google.com/?q=go+language",
+		&URL{
+			Scheme:   "http",
+			Opaque:   "www.google.com/",
+			RawQuery: "q=go+language",
+		},
+		"http:www.google.com/?q=go+language",
+	},
+	// path without leading /, so no parsing
+	{
+		"http:%2f%2fwww.google.com/?q=go+language",
+		&URL{
+			Scheme:   "http",
+			Opaque:   "%2f%2fwww.google.com/",
+			RawQuery: "q=go+language",
+		},
+		"http:%2f%2fwww.google.com/?q=go+language",
+	},
+	// non-authority
+	{
+		"mailto:/webmaster at golang.org",
+		&URL{
+			Scheme: "mailto",
+			Path:   "/webmaster at golang.org",
+		},
+		"",
+	},
+	// non-authority
+	{
+		"mailto:webmaster at golang.org",
+		&URL{
+			Scheme: "mailto",
+			Opaque: "webmaster at golang.org",
+		},
+		"",
+	},
+	// unescaped :// in query should not create a scheme
+	{
+		"/foo?query=http://bad",
+		&URL{
+			Path:     "/foo",
+			RawQuery: "query=http://bad",
+		},
+		"",
+	},
+	// leading // without scheme should create an authority
+	{
+		"//foo",
+		&URL{
+			Host: "foo",
+		},
+		"",
+	},
+	// leading // without scheme, with userinfo, path, and query
+	{
+		"//user at foo/path?a=b",
+		&URL{
+			User:     User("user"),
+			Host:     "foo",
+			Path:     "/path",
+			RawQuery: "a=b",
+		},
+		"",
+	},
+	// Three leading slashes isn't an authority, but doesn't return an error.
+	// (We can't return an error, as this code is also used via
+	// ServeHTTP -> ReadRequest -> Parse, which is arguably a
+	// different URL parsing context, but currently shares the
+	// same codepath)
+	{
+		"///threeslashes",
+		&URL{
+			Path: "///threeslashes",
+		},
+		"",
+	},
+	{
+		"http://user:password@google.com",
+		&URL{
+			Scheme: "http",
+			User:   UserPassword("user", "password"),
+			Host:   "google.com",
+		},
+		"http://user:password@google.com",
+	},
+}
+
+var urlnofragtests = []URLTest{
+	{
+		"http://www.google.com/?q=go+language#foo",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go+language#foo",
+		},
+		"",
+	},
+}
+
+var urlfragtests = []URLTest{
+	{
+		"http://www.google.com/?q=go+language#foo",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go+language",
+			Fragment: "foo",
+		},
+		"",
+	},
+	{
+		"http://www.google.com/?q=go+language#foo%26bar",
+		&URL{
+			Scheme:   "http",
+			Host:     "www.google.com",
+			Path:     "/",
+			RawQuery: "q=go+language",
+			Fragment: "foo&bar",
+		},
+		"http://www.google.com/?q=go+language#foo&bar",
+	},
+}
+
+// more useful string for debugging than fmt's struct printer
+func ufmt(u *URL) string {
+	var user, pass interface{}
+	if u.User != nil {
+		user = u.User.Username()
+		if p, ok := u.User.Password(); ok {
+			pass = p
+		}
+	}
+	return fmt.Sprintf("opaque=%q, scheme=%q, user=%#v, pass=%#v, host=%q, path=%q, rawq=%q, frag=%q",
+		u.Opaque, u.Scheme, user, pass, u.Host, u.Path, u.RawQuery, u.Fragment)
+}
+
+func DoTest(t *testing.T, parse func(string) (*URL, error), name string, tests []URLTest) {
+	for _, tt := range tests {
+		u, err := parse(tt.in)
+		if err != nil {
+			t.Errorf("%s(%q) returned error %s", name, tt.in, err)
+			continue
+		}
+		if !reflect.DeepEqual(u, tt.out) {
+			t.Errorf("%s(%q):\n\thave %v\n\twant %v\n",
+				name, tt.in, ufmt(u), ufmt(tt.out))
+		}
+	}
+}
+
+func TestParse(t *testing.T) {
+	DoTest(t, Parse, "Parse", urltests)
+	DoTest(t, Parse, "Parse", urlnofragtests)
+}
+
+func TestParseWithReference(t *testing.T) {
+	DoTest(t, ParseWithReference, "ParseWithReference", urltests)
+	DoTest(t, ParseWithReference, "ParseWithReference", urlfragtests)
+}
+
+const pathThatLooksSchemeRelative = "//not.a.user at not.a.host/just/a/path"
+
+var parseRequestUrlTests = []struct {
+	url           string
+	expectedValid bool
+}{
+	{"http://foo.com", true},
+	{"http://foo.com/", true},
+	{"http://foo.com/path", true},
+	{"/", true},
+	{pathThatLooksSchemeRelative, true},
+	{"//not.a.user@%66%6f%6f.com/just/a/path/also", true},
+	{"foo.html", false},
+	{"../dir/", false},
+}
+
+func TestParseRequest(t *testing.T) {
+	for _, test := range parseRequestUrlTests {
+		_, err := ParseRequest(test.url)
+		valid := err == nil
+		if valid != test.expectedValid {
+			t.Errorf("Expected valid=%v for %q; got %v", test.expectedValid, test.url, valid)
+		}
+	}
+
+	url, err := ParseRequest(pathThatLooksSchemeRelative)
+	if err != nil {
+		t.Fatalf("Unexpected error %v", err)
+	}
+	if url.Path != pathThatLooksSchemeRelative {
+		t.Errorf("Expected path %q; got %q", pathThatLooksSchemeRelative, url.Path)
+	}
+}
+
+func DoTestString(t *testing.T, parse func(string) (*URL, error), name string, tests []URLTest) {
+	for _, tt := range tests {
+		u, err := parse(tt.in)
+		if err != nil {
+			t.Errorf("%s(%q) returned error %s", name, tt.in, err)
+			continue
+		}
+		expected := tt.in
+		if len(tt.roundtrip) > 0 {
+			expected = tt.roundtrip
+		}
+		s := u.String()
+		if s != expected {
+			t.Errorf("%s(%q).String() == %q (expected %q)", name, tt.in, s, expected)
+		}
+	}
+}
+
+func TestURLString(t *testing.T) {
+	DoTestString(t, Parse, "Parse", urltests)
+	DoTestString(t, Parse, "Parse", urlnofragtests)
+	DoTestString(t, ParseWithReference, "ParseWithReference", urltests)
+	DoTestString(t, ParseWithReference, "ParseWithReference", urlfragtests)
+}
+
+type EscapeTest struct {
+	in  string
+	out string
+	err error
+}
+
+var unescapeTests = []EscapeTest{
+	{
+		"",
+		"",
+		nil,
+	},
+	{
+		"abc",
+		"abc",
+		nil,
+	},
+	{
+		"1%41",
+		"1A",
+		nil,
+	},
+	{
+		"1%41%42%43",
+		"1ABC",
+		nil,
+	},
+	{
+		"%4a",
+		"J",
+		nil,
+	},
+	{
+		"%6F",
+		"o",
+		nil,
+	},
+	{
+		"%", // not enough characters after %
+		"",
+		EscapeError("%"),
+	},
+	{
+		"%a", // not enough characters after %
+		"",
+		EscapeError("%a"),
+	},
+	{
+		"%1", // not enough characters after %
+		"",
+		EscapeError("%1"),
+	},
+	{
+		"123%45%6", // not enough characters after %
+		"",
+		EscapeError("%6"),
+	},
+	{
+		"%zzzzz", // invalid hex digits
+		"",
+		EscapeError("%zz"),
+	},
+}
+
+func TestUnescape(t *testing.T) {
+	for _, tt := range unescapeTests {
+		actual, err := QueryUnescape(tt.in)
+		if actual != tt.out || (err != nil) != (tt.err != nil) {
+			t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", tt.in, actual, err, tt.out, tt.err)
+		}
+	}
+}
+
+var escapeTests = []EscapeTest{
+	{
+		"",
+		"",
+		nil,
+	},
+	{
+		"abc",
+		"abc",
+		nil,
+	},
+	{
+		"one two",
+		"one+two",
+		nil,
+	},
+	{
+		"10%",
+		"10%25",
+		nil,
+	},
+	{
+		" ?&=#+%!<>#\"{}|\\^[]`☺\t",
+		"+%3F%26%3D%23%2B%25!%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09",
+		nil,
+	},
+}
+
+func TestEscape(t *testing.T) {
+	for _, tt := range escapeTests {
+		actual := QueryEscape(tt.in)
+		if tt.out != actual {
+			t.Errorf("QueryEscape(%q) = %q, want %q", tt.in, actual, tt.out)
+		}
+
+		// for bonus points, verify that escape:unescape is an identity.
+		roundtrip, err := QueryUnescape(actual)
+		if roundtrip != tt.in || err != nil {
+			t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", actual, roundtrip, err, tt.in, "[no error]")
+		}
+	}
+}
+
+//var userinfoTests = []UserinfoTest{
+//	{"user", "password", "user:password"},
+//	{"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
+//		"foo%3Abar:~!%40%23$%25%5E&*()_+%7B%7D%7C%5B%5D%5C-=%60%3A;'%22%3C%3E?,.%2F"},
+//}
+
+type EncodeQueryTest struct {
+	m         Values
+	expected  string
+	expected1 string
+}
+
+var encodeQueryTests = []EncodeQueryTest{
+	{nil, "", ""},
+	{Values{"q": {"puppies"}, "oe": {"utf8"}}, "q=puppies&oe=utf8", "oe=utf8&q=puppies"},
+	{Values{"q": {"dogs", "&", "7"}}, "q=dogs&q=%26&q=7", "q=dogs&q=%26&q=7"},
+}
+
+func TestEncodeQuery(t *testing.T) {
+	for _, tt := range encodeQueryTests {
+		if q := tt.m.Encode(); q != tt.expected && q != tt.expected1 {
+			t.Errorf(`EncodeQuery(%+v) = %q, want %q`, tt.m, q, tt.expected)
+		}
+	}
+}
+
+var resolvePathTests = []struct {
+	base, ref, expected string
+}{
+	{"a/b", ".", "a/"},
+	{"a/b", "c", "a/c"},
+	{"a/b", "..", ""},
+	{"a/", "..", ""},
+	{"a/", "../..", ""},
+	{"a/b/c", "..", "a/"},
+	{"a/b/c", "../d", "a/d"},
+	{"a/b/c", ".././d", "a/d"},
+	{"a/b", "./..", ""},
+	{"a/./b", ".", "a/./"},
+	{"a/../", ".", "a/../"},
+	{"a/.././b", "c", "a/.././c"},
+}
+
+func TestResolvePath(t *testing.T) {
+	for _, test := range resolvePathTests {
+		got := resolvePath(test.base, test.ref)
+		if got != test.expected {
+			t.Errorf("For %q + %q got %q; expected %q", test.base, test.ref, got, test.expected)
+		}
+	}
+}
+
+var resolveReferenceTests = []struct {
+	base, rel, expected string
+}{
+	// Absolute URL references
+	{"http://foo.com?a=b", "https://bar.com/", "https://bar.com/"},
+	{"http://foo.com/", "https://bar.com/?a=b", "https://bar.com/?a=b"},
+	{"http://foo.com/bar", "mailto:foo at example.com", "mailto:foo at example.com"},
+
+	// Path-absolute references
+	{"http://foo.com/bar", "/baz", "http://foo.com/baz"},
+	{"http://foo.com/bar?a=b#f", "/baz", "http://foo.com/baz"},
+	{"http://foo.com/bar?a=b", "/baz?c=d", "http://foo.com/baz?c=d"},
+
+	// Scheme-relative
+	{"https://foo.com/bar?a=b", "//bar.com/quux", "https://bar.com/quux"},
+
+	// Path-relative references:
+
+	// ... current directory
+	{"http://foo.com", ".", "http://foo.com/"},
+	{"http://foo.com/bar", ".", "http://foo.com/"},
+	{"http://foo.com/bar/", ".", "http://foo.com/bar/"},
+
+	// ... going down
+	{"http://foo.com", "bar", "http://foo.com/bar"},
+	{"http://foo.com/", "bar", "http://foo.com/bar"},
+	{"http://foo.com/bar/baz", "quux", "http://foo.com/bar/quux"},
+
+	// ... going up
+	{"http://foo.com/bar/baz", "../quux", "http://foo.com/quux"},
+	{"http://foo.com/bar/baz", "../../../../../quux", "http://foo.com/quux"},
+	{"http://foo.com/bar", "..", "http://foo.com/"},
+	{"http://foo.com/bar/baz", "./..", "http://foo.com/"},
+
+	// "." and ".." in the base aren't special
+	{"http://foo.com/dot/./dotdot/../foo/bar", "../baz", "http://foo.com/dot/./dotdot/../baz"},
+
+	// Triple dot isn't special
+	{"http://foo.com/bar", "...", "http://foo.com/..."},
+
+	// Fragment
+	{"http://foo.com/bar", ".#frag", "http://foo.com/#frag"},
+}
+
+func TestResolveReference(t *testing.T) {
+	mustParse := func(url string) *URL {
+		u, err := ParseWithReference(url)
+		if err != nil {
+			t.Fatalf("Expected URL to parse: %q, got error: %v", url, err)
+		}
+		return u
+	}
+	for _, test := range resolveReferenceTests {
+		base := mustParse(test.base)
+		rel := mustParse(test.rel)
+		url := base.ResolveReference(rel)
+		urlStr := url.String()
+		if urlStr != test.expected {
+			t.Errorf("Resolving %q + %q != %q; got %q", test.base, test.rel, test.expected, urlStr)
+		}
+	}
+
+	// Test that new instances are returned.
+	base := mustParse("http://foo.com/")
+	abs := base.ResolveReference(mustParse("."))
+	if base == abs {
+		t.Errorf("Expected no-op reference to return new URL instance.")
+	}
+	barRef := mustParse("http://bar.com/")
+	abs = base.ResolveReference(barRef)
+	if abs == barRef {
+		t.Errorf("Expected resolution of absolute reference to return new URL instance.")
+	}
+
+	// Test the convenience wrapper too
+	base = mustParse("http://foo.com/path/one/")
+	abs, _ = base.Parse("../two")
+	expected := "http://foo.com/path/two"
+	if abs.String() != expected {
+		t.Errorf("Parse wrapper got %q; expected %q", abs.String(), expected)
+	}
+	_, err := base.Parse("")
+	if err == nil {
+		t.Errorf("Expected an error from Parse wrapper parsing an empty string.")
+	}
+
+	// Ensure Opaque resets the URL.
+	base = mustParse("scheme://user@foo.com/bar")
+	abs = base.ResolveReference(&URL{Opaque: "opaque"})
+	want := mustParse("scheme:opaque")
+	if *abs != *want {
+		t.Errorf("ResolveReference failed to resolve opaque URL: want %#v, got %#v", abs, want)
+	}
+}
+
+func TestResolveReferenceOpaque(t *testing.T) {
+	mustParse := func(url string) *URL {
+		u, err := ParseWithReference(url)
+		if err != nil {
+			t.Fatalf("Expected URL to parse: %q, got error: %v", url, err)
+		}
+		return u
+	}
+	for _, test := range resolveReferenceTests {
+		base := mustParse(test.base)
+		rel := mustParse(test.rel)
+		url := base.ResolveReference(rel)
+		urlStr := url.String()
+		if urlStr != test.expected {
+			t.Errorf("Resolving %q + %q != %q; got %q", test.base, test.rel, test.expected, urlStr)
+		}
+	}
+
+	// Test that new instances are returned.
+	base := mustParse("http://foo.com/")
+	abs := base.ResolveReference(mustParse("."))
+	if base == abs {
+		t.Errorf("Expected no-op reference to return new URL instance.")
+	}
+	barRef := mustParse("http://bar.com/")
+	abs = base.ResolveReference(barRef)
+	if abs == barRef {
+		t.Errorf("Expected resolution of absolute reference to return new URL instance.")
+	}
+
+	// Test the convenience wrapper too
+	base = mustParse("http://foo.com/path/one/")
+	abs, _ = base.Parse("../two")
+	expected := "http://foo.com/path/two"
+	if abs.String() != expected {
+		t.Errorf("Parse wrapper got %q; expected %q", abs.String(), expected)
+	}
+	_, err := base.Parse("")
+	if err == nil {
+		t.Errorf("Expected an error from Parse wrapper parsing an empty string.")
+	}
+
+}
+
+func TestQueryValues(t *testing.T) {
+	u, _ := Parse("http://x.com?foo=bar&bar=1&bar=2")
+	v := u.Query()
+	if len(v) != 2 {
+		t.Errorf("got %d keys in Query values, want 2", len(v))
+	}
+	if g, e := v.Get("foo"), "bar"; g != e {
+		t.Errorf("Get(foo) = %q, want %q", g, e)
+	}
+	// Case sensitive:
+	if g, e := v.Get("Foo"), ""; g != e {
+		t.Errorf("Get(Foo) = %q, want %q", g, e)
+	}
+	if g, e := v.Get("bar"), "1"; g != e {
+		t.Errorf("Get(bar) = %q, want %q", g, e)
+	}
+	if g, e := v.Get("baz"), ""; g != e {
+		t.Errorf("Get(baz) = %q, want %q", g, e)
+	}
+	v.Del("bar")
+	if g, e := v.Get("bar"), ""; g != e {
+		t.Errorf("second Get(bar) = %q, want %q", g, e)
+	}
+}
+
+type parseTest struct {
+	query string
+	out   Values
+}
+
+var parseTests = []parseTest{
+	{
+		query: "a=1&b=2",
+		out:   Values{"a": []string{"1"}, "b": []string{"2"}},
+	},
+	{
+		query: "a=1&a=2&a=banana",
+		out:   Values{"a": []string{"1", "2", "banana"}},
+	},
+	{
+		query: "ascii=%3Ckey%3A+0x90%3E",
+		out:   Values{"ascii": []string{"<key: 0x90>"}},
+	},
+	{
+		query: "a=1;b=2",
+		out:   Values{"a": []string{"1"}, "b": []string{"2"}},
+	},
+	{
+		query: "a=1&a=2;a=banana",
+		out:   Values{"a": []string{"1", "2", "banana"}},
+	},
+}
+
+func TestParseQuery(t *testing.T) {
+	for i, test := range parseTests {
+		form, err := ParseQuery(test.query)
+		if err != nil {
+			t.Errorf("test %d: Unexpected error: %v", i, err)
+			continue
+		}
+		if len(form) != len(test.out) {
+			t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out))
+		}
+		for k, evs := range test.out {
+			vs, ok := form[k]
+			if !ok {
+				t.Errorf("test %d: Missing key %q", i, k)
+				continue
+			}
+			if len(vs) != len(evs) {
+				t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs))
+				continue
+			}
+			for j, ev := range evs {
+				if v := vs[j]; v != ev {
+					t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev)
+				}
+			}
+		}
+	}
+}
+
+type RequestURITest struct {
+	url *URL
+	out string
+}
+
+var requritests = []RequestURITest{
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Path:   "",
+		},
+		"/",
+	},
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Path:   "/a b",
+		},
+		"/a%20b",
+	},
+	{
+		&URL{
+			Scheme:   "http",
+			Host:     "example.com",
+			Path:     "/a b",
+			RawQuery: "q=go+language",
+		},
+		"/a%20b?q=go+language",
+	},
+	{
+		&URL{
+			Scheme: "myschema",
+			Opaque: "opaque",
+		},
+		"opaque",
+	},
+	{
+		&URL{
+			Scheme:   "myschema",
+			Opaque:   "opaque",
+			RawQuery: "q=go+language",
+		},
+		"opaque?q=go+language",
+	},
+}
+
+func TestRequestURI(t *testing.T) {
+	for _, tt := range requritests {
+		s := tt.url.RequestURI()
+		if s != tt.out {
+			t.Errorf("%#v.RequestURI() == %q (expected %q)", tt.url, s, tt.out)
+		}
+	}
+}
diff --git a/src/pkg/netchan/Makefile b/src/pkg/netchan/Makefile
deleted file mode 100644
index 9b9fdcf..0000000
--- a/src/pkg/netchan/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=netchan
-GOFILES=\
-	common.go\
-	export.go\
-	import.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/netchan/common.go b/src/pkg/netchan/common.go
deleted file mode 100644
index ac1ca12..0000000
--- a/src/pkg/netchan/common.go
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2010 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 netchan
-
-import (
-	"gob"
-	"io"
-	"os"
-	"reflect"
-	"sync"
-	"time"
-)
-
-// The direction of a connection from the client's perspective.
-type Dir int
-
-const (
-	Recv Dir = iota
-	Send
-)
-
-func (dir Dir) String() string {
-	switch dir {
-	case Recv:
-		return "Recv"
-	case Send:
-		return "Send"
-	}
-	return "???"
-}
-
-// Payload types
-const (
-	payRequest = iota // request structure follows
-	payError          // error structure follows
-	payData           // user payload follows
-	payAck            // acknowledgement; no payload
-	payClosed         // channel is now closed
-	payAckSend        // payload has been delivered.
-)
-
-// A header is sent as a prefix to every transmission.  It will be followed by
-// a request structure, an error structure, or an arbitrary user payload structure.
-type header struct {
-	Id          int
-	PayloadType int
-	SeqNum      int64
-}
-
-// Sent with a header once per channel from importer to exporter to report
-// that it wants to bind to a channel with the specified direction for count
-// messages, with space for size buffered values. If count is -1, it means unlimited.
-type request struct {
-	Name  string
-	Count int64
-	Size  int
-	Dir   Dir
-}
-
-// Sent with a header to report an error.
-type error struct {
-	Error string
-}
-
-// Used to unify management of acknowledgements for import and export.
-type unackedCounter interface {
-	unackedCount() int64
-	ack() int64
-	seq() int64
-}
-
-// A channel and its direction.
-type chanDir struct {
-	ch  reflect.Value
-	dir Dir
-}
-
-// clientSet contains the objects and methods needed for tracking
-// clients of an exporter and draining outstanding messages.
-type clientSet struct {
-	mu      sync.Mutex // protects access to channel and client maps
-	names   map[string]*chanDir
-	clients map[unackedCounter]bool
-}
-
-// Mutex-protected encoder and decoder pair.
-type encDec struct {
-	decLock sync.Mutex
-	dec     *gob.Decoder
-	encLock sync.Mutex
-	enc     *gob.Encoder
-}
-
-func newEncDec(conn io.ReadWriter) *encDec {
-	return &encDec{
-		dec: gob.NewDecoder(conn),
-		enc: gob.NewEncoder(conn),
-	}
-}
-
-// Decode an item from the connection.
-func (ed *encDec) decode(value reflect.Value) os.Error {
-	ed.decLock.Lock()
-	err := ed.dec.DecodeValue(value)
-	if err != nil {
-		// TODO: tear down connection?
-	}
-	ed.decLock.Unlock()
-	return err
-}
-
-// Encode a header and payload onto the connection.
-func (ed *encDec) encode(hdr *header, payloadType int, payload interface{}) os.Error {
-	ed.encLock.Lock()
-	hdr.PayloadType = payloadType
-	err := ed.enc.Encode(hdr)
-	if err == nil {
-		if payload != nil {
-			err = ed.enc.Encode(payload)
-		}
-	}
-	if err != nil {
-		// TODO: tear down connection if there is an error?
-	}
-	ed.encLock.Unlock()
-	return err
-}
-
-// See the comment for Exporter.Drain.
-func (cs *clientSet) drain(timeout int64) os.Error {
-	startTime := time.Nanoseconds()
-	for {
-		pending := false
-		cs.mu.Lock()
-		// Any messages waiting for a client?
-		for _, chDir := range cs.names {
-			if chDir.ch.Len() > 0 {
-				pending = true
-			}
-		}
-		// Any unacknowledged messages?
-		for client := range cs.clients {
-			n := client.unackedCount()
-			if n > 0 { // Check for > rather than != just to be safe.
-				pending = true
-				break
-			}
-		}
-		cs.mu.Unlock()
-		if !pending {
-			break
-		}
-		if timeout > 0 && time.Nanoseconds()-startTime >= timeout {
-			return os.NewError("timeout")
-		}
-		time.Sleep(100 * 1e6) // 100 milliseconds
-	}
-	return nil
-}
-
-// See the comment for Exporter.Sync.
-func (cs *clientSet) sync(timeout int64) os.Error {
-	startTime := time.Nanoseconds()
-	// seq remembers the clients and their seqNum at point of entry.
-	seq := make(map[unackedCounter]int64)
-	for client := range cs.clients {
-		seq[client] = client.seq()
-	}
-	for {
-		pending := false
-		cs.mu.Lock()
-		// Any unacknowledged messages?  Look only at clients that existed
-		// when we started and are still in this client set.
-		for client := range seq {
-			if _, ok := cs.clients[client]; ok {
-				if client.ack() < seq[client] {
-					pending = true
-					break
-				}
-			}
-		}
-		cs.mu.Unlock()
-		if !pending {
-			break
-		}
-		if timeout > 0 && time.Nanoseconds()-startTime >= timeout {
-			return os.NewError("timeout")
-		}
-		time.Sleep(100 * 1e6) // 100 milliseconds
-	}
-	return nil
-}
-
-// A netChan represents a channel imported or exported
-// on a single connection. Flow is controlled by the receiving
-// side by sending payAckSend messages when values
-// are delivered into the local channel.
-type netChan struct {
-	*chanDir
-	name   string
-	id     int
-	size   int // buffer size of channel.
-	closed bool
-
-	// sender-specific state
-	ackCh chan bool // buffered with space for all the acks we need
-	space int       // available space.
-
-	// receiver-specific state
-	sendCh chan reflect.Value // buffered channel of values received from other end.
-	ed     *encDec            // so that we can send acks.
-	count  int64              // number of values still to receive.
-}
-
-// Create a new netChan with the given name (only used for
-// messages), id, direction, buffer size, and count.
-// The connection to the other side is represented by ed.
-func newNetChan(name string, id int, ch *chanDir, ed *encDec, size int, count int64) *netChan {
-	c := &netChan{chanDir: ch, name: name, id: id, size: size, ed: ed, count: count}
-	if c.dir == Send {
-		c.ackCh = make(chan bool, size)
-		c.space = size
-	}
-	return c
-}
-
-// Close the channel.
-func (nch *netChan) close() {
-	if nch.closed {
-		return
-	}
-	if nch.dir == Recv {
-		if nch.sendCh != nil {
-			// If the sender goroutine is active, close the channel to it.
-			// It will close nch.ch when it can.
-			close(nch.sendCh)
-		} else {
-			nch.ch.Close()
-		}
-	} else {
-		nch.ch.Close()
-		close(nch.ackCh)
-	}
-	nch.closed = true
-}
-
-// Send message from remote side to local receiver.
-func (nch *netChan) send(val reflect.Value) {
-	if nch.dir != Recv {
-		panic("send on wrong direction of channel")
-	}
-	if nch.sendCh == nil {
-		// If possible, do local send directly and ack immediately.
-		if nch.ch.TrySend(val) {
-			nch.sendAck()
-			return
-		}
-		// Start sender goroutine to manage delayed delivery of values.
-		nch.sendCh = make(chan reflect.Value, nch.size)
-		go nch.sender()
-	}
-	select {
-	case nch.sendCh <- val:
-		// ok
-	default:
-		// TODO: should this be more resilient?
-		panic("netchan: remote sender sent more values than allowed")
-	}
-}
-
-// sendAck sends an acknowledgment that a message has left
-// the channel's buffer. If the messages remaining to be sent
-// will fit in the channel's buffer, then we don't
-// need to send an ack.
-func (nch *netChan) sendAck() {
-	if nch.count < 0 || nch.count > int64(nch.size) {
-		nch.ed.encode(&header{Id: nch.id}, payAckSend, nil)
-	}
-	if nch.count > 0 {
-		nch.count--
-	}
-}
-
-// The sender process forwards items from the sending queue
-// to the destination channel, acknowledging each item.
-func (nch *netChan) sender() {
-	if nch.dir != Recv {
-		panic("sender on wrong direction of channel")
-	}
-	// When Exporter.Hangup is called, the underlying channel is closed,
-	// and so we may get a "too many operations on closed channel" error
-	// if there are outstanding messages in sendCh.
-	// Make sure that this doesn't panic the whole program.
-	defer func() {
-		if r := recover(); r != nil {
-			// TODO check that r is "too many operations", otherwise re-panic.
-		}
-	}()
-	for v := range nch.sendCh {
-		nch.ch.Send(v)
-		nch.sendAck()
-	}
-	nch.ch.Close()
-}
-
-// Receive value from local side for sending to remote side.
-func (nch *netChan) recv() (val reflect.Value, ok bool) {
-	if nch.dir != Send {
-		panic("recv on wrong direction of channel")
-	}
-
-	if nch.space == 0 {
-		// Wait for buffer space.
-		<-nch.ackCh
-		nch.space++
-	}
-	nch.space--
-	return nch.ch.Recv()
-}
-
-// acked is called when the remote side indicates that
-// a value has been delivered.
-func (nch *netChan) acked() {
-	if nch.dir != Send {
-		panic("recv on wrong direction of channel")
-	}
-	select {
-	case nch.ackCh <- true:
-		// ok
-	default:
-		// TODO: should this be more resilient?
-		panic("netchan: remote receiver sent too many acks")
-	}
-}
diff --git a/src/pkg/netchan/export.go b/src/pkg/netchan/export.go
deleted file mode 100644
index 7df7365..0000000
--- a/src/pkg/netchan/export.go
+++ /dev/null
@@ -1,400 +0,0 @@
-// Copyright 2010 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 netchan implements type-safe networked channels:
-	it allows the two ends of a channel to appear on different
-	computers connected by a network.  It does this by transporting
-	data sent to a channel on one machine so it can be recovered
-	by a receive of a channel of the same type on the other.
-
-	An exporter publishes a set of channels by name.  An importer
-	connects to the exporting machine and imports the channels
-	by name. After importing the channels, the two machines can
-	use the channels in the usual way.
-
-	Networked channels are not synchronized; they always behave
-	as if they are buffered channels of at least one element.
-*/
-package netchan
-
-// BUG: can't use range clause to receive when using ImportNValues to limit the count.
-
-import (
-	"log"
-	"io"
-	"net"
-	"os"
-	"reflect"
-	"strconv"
-	"sync"
-)
-
-// Export
-
-// expLog is a logging convenience function.  The first argument must be a string.
-func expLog(args ...interface{}) {
-	args[0] = "netchan export: " + args[0].(string)
-	log.Print(args...)
-}
-
-// An Exporter allows a set of channels to be published on a single
-// network port.  A single machine may have multiple Exporters
-// but they must use different ports.
-type Exporter struct {
-	*clientSet
-}
-
-type expClient struct {
-	*encDec
-	exp     *Exporter
-	chans   map[int]*netChan // channels in use by client
-	mu      sync.Mutex       // protects remaining fields
-	errored bool             // client has been sent an error
-	seqNum  int64            // sequences messages sent to client; has value of highest sent
-	ackNum  int64            // highest sequence number acknowledged
-	seqLock sync.Mutex       // guarantees messages are in sequence, only locked under mu
-}
-
-func newClient(exp *Exporter, conn io.ReadWriter) *expClient {
-	client := new(expClient)
-	client.exp = exp
-	client.encDec = newEncDec(conn)
-	client.seqNum = 0
-	client.ackNum = 0
-	client.chans = make(map[int]*netChan)
-	return client
-}
-
-func (client *expClient) sendError(hdr *header, err string) {
-	error := &error{err}
-	expLog("sending error to client:", error.Error)
-	client.encode(hdr, payError, error) // ignore any encode error, hope client gets it
-	client.mu.Lock()
-	client.errored = true
-	client.mu.Unlock()
-}
-
-func (client *expClient) newChan(hdr *header, dir Dir, name string, size int, count int64) *netChan {
-	exp := client.exp
-	exp.mu.Lock()
-	ech, ok := exp.names[name]
-	exp.mu.Unlock()
-	if !ok {
-		client.sendError(hdr, "no such channel: "+name)
-		return nil
-	}
-	if ech.dir != dir {
-		client.sendError(hdr, "wrong direction for channel: "+name)
-		return nil
-	}
-	nch := newNetChan(name, hdr.Id, ech, client.encDec, size, count)
-	client.chans[hdr.Id] = nch
-	return nch
-}
-
-func (client *expClient) getChan(hdr *header, dir Dir) *netChan {
-	nch := client.chans[hdr.Id]
-	if nch == nil {
-		return nil
-	}
-	if nch.dir != dir {
-		client.sendError(hdr, "wrong direction for channel: "+nch.name)
-	}
-	return nch
-}
-
-// The function run manages sends and receives for a single client.  For each
-// (client Recv) request, this will launch a serveRecv goroutine to deliver
-// the data for that channel, while (client Send) requests are handled as
-// data arrives from the client.
-func (client *expClient) run() {
-	hdr := new(header)
-	hdrValue := reflect.ValueOf(hdr)
-	req := new(request)
-	reqValue := reflect.ValueOf(req)
-	error := new(error)
-	for {
-		*hdr = header{}
-		if err := client.decode(hdrValue); err != nil {
-			if err != os.EOF {
-				expLog("error decoding client header:", err)
-			}
-			break
-		}
-		switch hdr.PayloadType {
-		case payRequest:
-			*req = request{}
-			if err := client.decode(reqValue); err != nil {
-				expLog("error decoding client request:", err)
-				break
-			}
-			if req.Size < 1 {
-				panic("netchan: remote requested " + strconv.Itoa(req.Size) + " values")
-			}
-			switch req.Dir {
-			case Recv:
-				// look up channel before calling serveRecv to
-				// avoid a lock around client.chans.
-				if nch := client.newChan(hdr, Send, req.Name, req.Size, req.Count); nch != nil {
-					go client.serveRecv(nch, *hdr, req.Count)
-				}
-			case Send:
-				client.newChan(hdr, Recv, req.Name, req.Size, req.Count)
-				// The actual sends will have payload type payData.
-				// TODO: manage the count?
-			default:
-				error.Error = "request: can't handle channel direction"
-				expLog(error.Error, req.Dir)
-				client.encode(hdr, payError, error)
-			}
-		case payData:
-			client.serveSend(*hdr)
-		case payClosed:
-			client.serveClosed(*hdr)
-		case payAck:
-			client.mu.Lock()
-			if client.ackNum != hdr.SeqNum-1 {
-				// Since the sequence number is incremented and the message is sent
-				// in a single instance of locking client.mu, the messages are guaranteed
-				// to be sent in order.  Therefore receipt of acknowledgement N means
-				// all messages <=N have been seen by the recipient.  We check anyway.
-				expLog("sequence out of order:", client.ackNum, hdr.SeqNum)
-			}
-			if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count. 
-				client.ackNum = hdr.SeqNum
-			}
-			client.mu.Unlock()
-		case payAckSend:
-			if nch := client.getChan(hdr, Send); nch != nil {
-				nch.acked()
-			}
-		default:
-			log.Fatal("netchan export: unknown payload type", hdr.PayloadType)
-		}
-	}
-	client.exp.delClient(client)
-}
-
-// Send all the data on a single channel to a client asking for a Recv.
-// The header is passed by value to avoid issues of overwriting.
-func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) {
-	for {
-		val, ok := nch.recv()
-		if !ok {
-			if err := client.encode(&hdr, payClosed, nil); err != nil {
-				expLog("error encoding server closed message:", err)
-			}
-			break
-		}
-		// We hold the lock during transmission to guarantee messages are
-		// sent in sequence number order.  Also, we increment first so the
-		// value of client.SeqNum is the value of the highest used sequence
-		// number, not one beyond.
-		client.mu.Lock()
-		client.seqNum++
-		hdr.SeqNum = client.seqNum
-		client.seqLock.Lock() // guarantee ordering of messages
-		client.mu.Unlock()
-		err := client.encode(&hdr, payData, val.Interface())
-		client.seqLock.Unlock()
-		if err != nil {
-			expLog("error encoding client response:", err)
-			client.sendError(&hdr, err.String())
-			break
-		}
-		// Negative count means run forever.
-		if count >= 0 {
-			if count--; count <= 0 {
-				break
-			}
-		}
-	}
-}
-
-// Receive and deliver locally one item from a client asking for a Send
-// The header is passed by value to avoid issues of overwriting.
-func (client *expClient) serveSend(hdr header) {
-	nch := client.getChan(&hdr, Recv)
-	if nch == nil {
-		return
-	}
-	// Create a new value for each received item.
-	val := reflect.New(nch.ch.Type().Elem()).Elem()
-	if err := client.decode(val); err != nil {
-		expLog("value decode:", err, "; type ", nch.ch.Type())
-		return
-	}
-	nch.send(val)
-}
-
-// Report that client has closed the channel that is sending to us.
-// The header is passed by value to avoid issues of overwriting.
-func (client *expClient) serveClosed(hdr header) {
-	nch := client.getChan(&hdr, Recv)
-	if nch == nil {
-		return
-	}
-	nch.close()
-}
-
-func (client *expClient) unackedCount() int64 {
-	client.mu.Lock()
-	n := client.seqNum - client.ackNum
-	client.mu.Unlock()
-	return n
-}
-
-func (client *expClient) seq() int64 {
-	client.mu.Lock()
-	n := client.seqNum
-	client.mu.Unlock()
-	return n
-}
-
-func (client *expClient) ack() int64 {
-	client.mu.Lock()
-	n := client.seqNum
-	client.mu.Unlock()
-	return n
-}
-
-// Serve waits for incoming connections on the listener
-// and serves the Exporter's channels on each.
-// It blocks until the listener is closed.
-func (exp *Exporter) Serve(listener net.Listener) {
-	for {
-		conn, err := listener.Accept()
-		if err != nil {
-			expLog("listen:", err)
-			break
-		}
-		go exp.ServeConn(conn)
-	}
-}
-
-// ServeConn exports the Exporter's channels on conn.
-// It blocks until the connection is terminated.
-func (exp *Exporter) ServeConn(conn io.ReadWriter) {
-	exp.addClient(conn).run()
-}
-
-// NewExporter creates a new Exporter that exports a set of channels.
-func NewExporter() *Exporter {
-	e := &Exporter{
-		clientSet: &clientSet{
-			names:   make(map[string]*chanDir),
-			clients: make(map[unackedCounter]bool),
-		},
-	}
-	return e
-}
-
-// ListenAndServe exports the exporter's channels through the
-// given network and local address defined as in net.Listen.
-func (exp *Exporter) ListenAndServe(network, localaddr string) os.Error {
-	listener, err := net.Listen(network, localaddr)
-	if err != nil {
-		return err
-	}
-	go exp.Serve(listener)
-	return nil
-}
-
-// addClient creates a new expClient and records its existence
-func (exp *Exporter) addClient(conn io.ReadWriter) *expClient {
-	client := newClient(exp, conn)
-	exp.mu.Lock()
-	exp.clients[client] = true
-	exp.mu.Unlock()
-	return client
-}
-
-// delClient forgets the client existed
-func (exp *Exporter) delClient(client *expClient) {
-	exp.mu.Lock()
-	exp.clients[client] = false, false
-	exp.mu.Unlock()
-}
-
-// Drain waits until all messages sent from this exporter/importer, including
-// those not yet sent to any client and possibly including those sent while
-// Drain was executing, have been received by the importer.  In short, it
-// waits until all the exporter's messages have been received by a client.
-// If the timeout (measured in nanoseconds) is positive and Drain takes
-// longer than that to complete, an error is returned.
-func (exp *Exporter) Drain(timeout int64) os.Error {
-	// This wrapper function is here so the method's comment will appear in godoc.
-	return exp.clientSet.drain(timeout)
-}
-
-// Sync waits until all clients of the exporter have received the messages
-// that were sent at the time Sync was invoked.  Unlike Drain, it does not
-// wait for messages sent while it is running or messages that have not been
-// dispatched to any client.  If the timeout (measured in nanoseconds) is
-// positive and Sync takes longer than that to complete, an error is
-// returned.
-func (exp *Exporter) Sync(timeout int64) os.Error {
-	// This wrapper function is here so the method's comment will appear in godoc.
-	return exp.clientSet.sync(timeout)
-}
-
-func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
-	chanType := reflect.TypeOf(chT)
-	if chanType.Kind() != reflect.Chan {
-		return reflect.Value{}, os.NewError("not a channel")
-	}
-	if dir != Send && dir != Recv {
-		return reflect.Value{}, os.NewError("unknown channel direction")
-	}
-	switch chanType.ChanDir() {
-	case reflect.BothDir:
-	case reflect.SendDir:
-		if dir != Recv {
-			return reflect.Value{}, os.NewError("to import/export with Send, must provide <-chan")
-		}
-	case reflect.RecvDir:
-		if dir != Send {
-			return reflect.Value{}, os.NewError("to import/export with Recv, must provide chan<-")
-		}
-	}
-	return reflect.ValueOf(chT), nil
-}
-
-// Export exports a channel of a given type and specified direction.  The
-// channel to be exported is provided in the call and may be of arbitrary
-// channel type.
-// Despite the literal signature, the effective signature is
-//	Export(name string, chT chan T, dir Dir)
-func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error {
-	ch, err := checkChan(chT, dir)
-	if err != nil {
-		return err
-	}
-	exp.mu.Lock()
-	defer exp.mu.Unlock()
-	_, present := exp.names[name]
-	if present {
-		return os.NewError("channel name already being exported:" + name)
-	}
-	exp.names[name] = &chanDir{ch, dir}
-	return nil
-}
-
-// Hangup disassociates the named channel from the Exporter and closes
-// the channel.  Messages in flight for the channel may be dropped.
-func (exp *Exporter) Hangup(name string) os.Error {
-	exp.mu.Lock()
-	chDir, ok := exp.names[name]
-	if ok {
-		exp.names[name] = nil, false
-	}
-	// TODO drop all instances of channel from client sets
-	exp.mu.Unlock()
-	if !ok {
-		return os.NewError("netchan export: hangup: no such channel: " + name)
-	}
-	chDir.ch.Close()
-	return nil
-}
diff --git a/src/pkg/netchan/import.go b/src/pkg/netchan/import.go
deleted file mode 100644
index ec17d97..0000000
--- a/src/pkg/netchan/import.go
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2010 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 netchan
-
-import (
-	"io"
-	"log"
-	"net"
-	"os"
-	"reflect"
-	"sync"
-	"time"
-)
-
-// Import
-
-// impLog is a logging convenience function.  The first argument must be a string.
-func impLog(args ...interface{}) {
-	args[0] = "netchan import: " + args[0].(string)
-	log.Print(args...)
-}
-
-// An Importer allows a set of channels to be imported from a single
-// remote machine/network port.  A machine may have multiple
-// importers, even from the same machine/network port.
-type Importer struct {
-	*encDec
-	chanLock sync.Mutex // protects access to channel map
-	names    map[string]*netChan
-	chans    map[int]*netChan
-	errors   chan os.Error
-	maxId    int
-	mu       sync.Mutex // protects remaining fields
-	unacked  int64      // number of unacknowledged sends.
-	seqLock  sync.Mutex // guarantees messages are in sequence, only locked under mu
-}
-
-// NewImporter creates a new Importer object to import a set of channels
-// from the given connection. The Exporter must be available and serving when
-// the Importer is created.
-func NewImporter(conn io.ReadWriter) *Importer {
-	imp := new(Importer)
-	imp.encDec = newEncDec(conn)
-	imp.chans = make(map[int]*netChan)
-	imp.names = make(map[string]*netChan)
-	imp.errors = make(chan os.Error, 10)
-	imp.unacked = 0
-	go imp.run()
-	return imp
-}
-
-// Import imports a set of channels from the given network and address.
-func Import(network, remoteaddr string) (*Importer, os.Error) {
-	conn, err := net.Dial(network, remoteaddr)
-	if err != nil {
-		return nil, err
-	}
-	return NewImporter(conn), nil
-}
-
-// shutdown closes all channels for which we are receiving data from the remote side.
-func (imp *Importer) shutdown() {
-	imp.chanLock.Lock()
-	for _, ich := range imp.chans {
-		if ich.dir == Recv {
-			ich.close()
-		}
-	}
-	imp.chanLock.Unlock()
-}
-
-// Handle the data from a single imported data stream, which will
-// have the form
-//	(response, data)*
-// The response identifies by name which channel is transmitting data.
-func (imp *Importer) run() {
-	// Loop on responses; requests are sent by ImportNValues()
-	hdr := new(header)
-	hdrValue := reflect.ValueOf(hdr)
-	ackHdr := new(header)
-	err := new(error)
-	errValue := reflect.ValueOf(err)
-	for {
-		*hdr = header{}
-		if e := imp.decode(hdrValue); e != nil {
-			if e != os.EOF {
-				impLog("header:", e)
-				imp.shutdown()
-			}
-			return
-		}
-		switch hdr.PayloadType {
-		case payData:
-			// done lower in loop
-		case payError:
-			if e := imp.decode(errValue); e != nil {
-				impLog("error:", e)
-				return
-			}
-			if err.Error != "" {
-				impLog("response error:", err.Error)
-				select {
-				case imp.errors <- os.NewError(err.Error):
-					continue // errors are not acknowledged
-				default:
-					imp.shutdown()
-					return
-				}
-			}
-		case payClosed:
-			nch := imp.getChan(hdr.Id, false)
-			if nch != nil {
-				nch.close()
-			}
-			continue // closes are not acknowledged.
-		case payAckSend:
-			// we can receive spurious acks if the channel is
-			// hung up, so we ask getChan to ignore any errors.
-			nch := imp.getChan(hdr.Id, true)
-			if nch != nil {
-				nch.acked()
-				imp.mu.Lock()
-				imp.unacked--
-				imp.mu.Unlock()
-			}
-			continue
-		default:
-			impLog("unexpected payload type:", hdr.PayloadType)
-			return
-		}
-		nch := imp.getChan(hdr.Id, false)
-		if nch == nil {
-			continue
-		}
-		if nch.dir != Recv {
-			impLog("cannot happen: receive from non-Recv channel")
-			return
-		}
-		// Acknowledge receipt
-		ackHdr.Id = hdr.Id
-		ackHdr.SeqNum = hdr.SeqNum
-		imp.encode(ackHdr, payAck, nil)
-		// Create a new value for each received item.
-		value := reflect.New(nch.ch.Type().Elem()).Elem()
-		if e := imp.decode(value); e != nil {
-			impLog("importer value decode:", e)
-			return
-		}
-		nch.send(value)
-	}
-}
-
-func (imp *Importer) getChan(id int, errOk bool) *netChan {
-	imp.chanLock.Lock()
-	ich := imp.chans[id]
-	imp.chanLock.Unlock()
-	if ich == nil {
-		if !errOk {
-			impLog("unknown id in netchan request: ", id)
-		}
-		return nil
-	}
-	return ich
-}
-
-// Errors returns a channel from which transmission and protocol errors
-// can be read. Clients of the importer are not required to read the error
-// channel for correct execution. However, if too many errors occur
-// without being read from the error channel, the importer will shut down.
-func (imp *Importer) Errors() chan os.Error {
-	return imp.errors
-}
-
-// Import imports a channel of the given type, size and specified direction.
-// It is equivalent to ImportNValues with a count of -1, meaning unbounded.
-func (imp *Importer) Import(name string, chT interface{}, dir Dir, size int) os.Error {
-	return imp.ImportNValues(name, chT, dir, size, -1)
-}
-
-// ImportNValues imports a channel of the given type and specified
-// direction and then receives or transmits up to n values on that
-// channel.  A value of n==-1 implies an unbounded number of values.  The
-// channel will have buffer space for size values, or 1 value if size < 1.
-// The channel to be bound to the remote site's channel is provided
-// in the call and may be of arbitrary channel type.
-// Despite the literal signature, the effective signature is
-//	ImportNValues(name string, chT chan T, dir Dir, size, n int) os.Error
-// Example usage:
-//	imp, err := NewImporter("tcp", "netchanserver.mydomain.com:1234")
-//	if err != nil { log.Fatal(err) }
-//	ch := make(chan myType)
-//	err = imp.ImportNValues("name", ch, Recv, 1, 1)
-//	if err != nil { log.Fatal(err) }
-//	fmt.Printf("%+v\n", <-ch)
-func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, size, n int) os.Error {
-	ch, err := checkChan(chT, dir)
-	if err != nil {
-		return err
-	}
-	imp.chanLock.Lock()
-	defer imp.chanLock.Unlock()
-	_, present := imp.names[name]
-	if present {
-		return os.NewError("channel name already being imported:" + name)
-	}
-	if size < 1 {
-		size = 1
-	}
-	id := imp.maxId
-	imp.maxId++
-	nch := newNetChan(name, id, &chanDir{ch, dir}, imp.encDec, size, int64(n))
-	imp.names[name] = nch
-	imp.chans[id] = nch
-	// Tell the other side about this channel.
-	hdr := &header{Id: id}
-	req := &request{Name: name, Count: int64(n), Dir: dir, Size: size}
-	if err = imp.encode(hdr, payRequest, req); err != nil {
-		impLog("request encode:", err)
-		return err
-	}
-	if dir == Send {
-		go func() {
-			for i := 0; n == -1 || i < n; i++ {
-				val, ok := nch.recv()
-				if !ok {
-					if err = imp.encode(hdr, payClosed, nil); err != nil {
-						impLog("error encoding client closed message:", err)
-					}
-					return
-				}
-				// We hold the lock during transmission to guarantee messages are
-				// sent in order.
-				imp.mu.Lock()
-				imp.unacked++
-				imp.seqLock.Lock()
-				imp.mu.Unlock()
-				if err = imp.encode(hdr, payData, val.Interface()); err != nil {
-					impLog("error encoding client send:", err)
-					return
-				}
-				imp.seqLock.Unlock()
-			}
-		}()
-	}
-	return nil
-}
-
-// Hangup disassociates the named channel from the Importer and closes
-// the channel.  Messages in flight for the channel may be dropped.
-func (imp *Importer) Hangup(name string) os.Error {
-	imp.chanLock.Lock()
-	defer imp.chanLock.Unlock()
-	nc := imp.names[name]
-	if nc == nil {
-		return os.NewError("netchan import: hangup: no such channel: " + name)
-	}
-	imp.names[name] = nil, false
-	imp.chans[nc.id] = nil, false
-	nc.close()
-	return nil
-}
-
-func (imp *Importer) unackedCount() int64 {
-	imp.mu.Lock()
-	n := imp.unacked
-	imp.mu.Unlock()
-	return n
-}
-
-// Drain waits until all messages sent from this exporter/importer, including
-// those not yet sent to any server and possibly including those sent while
-// Drain was executing, have been received by the exporter.  In short, it
-// waits until all the importer's messages have been received.
-// If the timeout (measured in nanoseconds) is positive and Drain takes
-// longer than that to complete, an error is returned.
-func (imp *Importer) Drain(timeout int64) os.Error {
-	startTime := time.Nanoseconds()
-	for imp.unackedCount() > 0 {
-		if timeout > 0 && time.Nanoseconds()-startTime >= timeout {
-			return os.NewError("timeout")
-		}
-		time.Sleep(100 * 1e6)
-	}
-	return nil
-}
diff --git a/src/pkg/netchan/netchan_test.go b/src/pkg/netchan/netchan_test.go
deleted file mode 100644
index 8c0f9a6..0000000
--- a/src/pkg/netchan/netchan_test.go
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright 2010 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 netchan
-
-import (
-	"net"
-	"strings"
-	"testing"
-	"time"
-)
-
-const count = 10     // number of items in most tests
-const closeCount = 5 // number of items when sender closes early
-
-const base = 23
-
-func exportSend(exp *Exporter, n int, t *testing.T, done chan bool) {
-	ch := make(chan int)
-	err := exp.Export("exportedSend", ch, Send)
-	if err != nil {
-		t.Fatal("exportSend:", err)
-	}
-	go func() {
-		for i := 0; i < n; i++ {
-			ch <- base + i
-		}
-		close(ch)
-		if done != nil {
-			done <- true
-		}
-	}()
-}
-
-func exportReceive(exp *Exporter, t *testing.T, expDone chan bool) {
-	ch := make(chan int)
-	err := exp.Export("exportedRecv", ch, Recv)
-	expDone <- true
-	if err != nil {
-		t.Fatal("exportReceive:", err)
-	}
-	for i := 0; i < count; i++ {
-		v, ok := <-ch
-		if !ok {
-			if i != closeCount {
-				t.Errorf("exportReceive expected close at %d; got one at %d", closeCount, i)
-			}
-			break
-		}
-		if v != base+i {
-			t.Errorf("export Receive: bad value: expected %d+%d=%d; got %d", base, i, base+i, v)
-		}
-	}
-}
-
-func importSend(imp *Importer, n int, t *testing.T, done chan bool) {
-	ch := make(chan int)
-	err := imp.ImportNValues("exportedRecv", ch, Send, 3, -1)
-	if err != nil {
-		t.Fatal("importSend:", err)
-	}
-	go func() {
-		for i := 0; i < n; i++ {
-			ch <- base + i
-		}
-		close(ch)
-		if done != nil {
-			done <- true
-		}
-	}()
-}
-
-func importReceive(imp *Importer, t *testing.T, done chan bool) {
-	ch := make(chan int)
-	err := imp.ImportNValues("exportedSend", ch, Recv, 3, count)
-	if err != nil {
-		t.Fatal("importReceive:", err)
-	}
-	for i := 0; i < count; i++ {
-		v, ok := <-ch
-		if !ok {
-			if i != closeCount {
-				t.Errorf("importReceive expected close at %d; got one at %d", closeCount, i)
-			}
-			break
-		}
-		if v != base+i {
-			t.Errorf("importReceive: bad value: expected %d+%d=%d; got %+d", base, i, base+i, v)
-		}
-	}
-	if done != nil {
-		done <- true
-	}
-}
-
-func TestExportSendImportReceive(t *testing.T) {
-	exp, imp := pair(t)
-	exportSend(exp, count, t, nil)
-	importReceive(imp, t, nil)
-}
-
-func TestExportReceiveImportSend(t *testing.T) {
-	exp, imp := pair(t)
-	expDone := make(chan bool)
-	done := make(chan bool)
-	go func() {
-		exportReceive(exp, t, expDone)
-		done <- true
-	}()
-	<-expDone
-	importSend(imp, count, t, nil)
-	<-done
-}
-
-func TestClosingExportSendImportReceive(t *testing.T) {
-	exp, imp := pair(t)
-	exportSend(exp, closeCount, t, nil)
-	importReceive(imp, t, nil)
-}
-
-func TestClosingImportSendExportReceive(t *testing.T) {
-	exp, imp := pair(t)
-	expDone := make(chan bool)
-	done := make(chan bool)
-	go func() {
-		exportReceive(exp, t, expDone)
-		done <- true
-	}()
-	<-expDone
-	importSend(imp, closeCount, t, nil)
-	<-done
-}
-
-func TestErrorForIllegalChannel(t *testing.T) {
-	exp, imp := pair(t)
-	// Now export a channel.
-	ch := make(chan int, 1)
-	err := exp.Export("aChannel", ch, Send)
-	if err != nil {
-		t.Fatal("export:", err)
-	}
-	ch <- 1234
-	close(ch)
-	// Now try to import a different channel.
-	ch = make(chan int)
-	err = imp.Import("notAChannel", ch, Recv, 1)
-	if err != nil {
-		t.Fatal("import:", err)
-	}
-	// Expect an error now.  Start a timeout.
-	timeout := make(chan bool, 1) // buffered so closure will not hang around.
-	go func() {
-		time.Sleep(10e9) // very long, to give even really slow machines a chance.
-		timeout <- true
-	}()
-	select {
-	case err = <-imp.Errors():
-		if strings.Index(err.String(), "no such channel") < 0 {
-			t.Error("wrong error for nonexistent channel:", err)
-		}
-	case <-timeout:
-		t.Error("import of nonexistent channel did not receive an error")
-	}
-}
-
-// Not a great test but it does at least invoke Drain.
-func TestExportDrain(t *testing.T) {
-	exp, imp := pair(t)
-	done := make(chan bool)
-	go func() {
-		exportSend(exp, closeCount, t, nil)
-		done <- true
-	}()
-	<-done
-	go importReceive(imp, t, done)
-	exp.Drain(0)
-	<-done
-}
-
-// Not a great test but it does at least invoke Drain.
-func TestImportDrain(t *testing.T) {
-	exp, imp := pair(t)
-	expDone := make(chan bool)
-	go exportReceive(exp, t, expDone)
-	<-expDone
-	importSend(imp, closeCount, t, nil)
-	imp.Drain(0)
-}
-
-// Not a great test but it does at least invoke Sync.
-func TestExportSync(t *testing.T) {
-	exp, imp := pair(t)
-	done := make(chan bool)
-	exportSend(exp, closeCount, t, nil)
-	go importReceive(imp, t, done)
-	exp.Sync(0)
-	<-done
-}
-
-// Test hanging up the send side of an export.
-// TODO: test hanging up the receive side of an export.
-func TestExportHangup(t *testing.T) {
-	exp, imp := pair(t)
-	ech := make(chan int)
-	err := exp.Export("exportedSend", ech, Send)
-	if err != nil {
-		t.Fatal("export:", err)
-	}
-	// Prepare to receive two values. We'll actually deliver only one.
-	ich := make(chan int)
-	err = imp.ImportNValues("exportedSend", ich, Recv, 1, 2)
-	if err != nil {
-		t.Fatal("import exportedSend:", err)
-	}
-	// Send one value, receive it.
-	const Value = 1234
-	ech <- Value
-	v := <-ich
-	if v != Value {
-		t.Fatal("expected", Value, "got", v)
-	}
-	// Now hang up the channel.  Importer should see it close.
-	exp.Hangup("exportedSend")
-	v, ok := <-ich
-	if ok {
-		t.Fatal("expected channel to be closed; got value", v)
-	}
-}
-
-// Test hanging up the send side of an import.
-// TODO: test hanging up the receive side of an import.
-func TestImportHangup(t *testing.T) {
-	exp, imp := pair(t)
-	ech := make(chan int)
-	err := exp.Export("exportedRecv", ech, Recv)
-	if err != nil {
-		t.Fatal("export:", err)
-	}
-	// Prepare to Send two values. We'll actually deliver only one.
-	ich := make(chan int)
-	err = imp.ImportNValues("exportedRecv", ich, Send, 1, 2)
-	if err != nil {
-		t.Fatal("import exportedRecv:", err)
-	}
-	// Send one value, receive it.
-	const Value = 1234
-	ich <- Value
-	v := <-ech
-	if v != Value {
-		t.Fatal("expected", Value, "got", v)
-	}
-	// Now hang up the channel.  Exporter should see it close.
-	imp.Hangup("exportedRecv")
-	v, ok := <-ech
-	if ok {
-		t.Fatal("expected channel to be closed; got value", v)
-	}
-}
-
-// loop back exportedRecv to exportedSend,
-// but receive a value from ctlch before starting the loop.
-func exportLoopback(exp *Exporter, t *testing.T) {
-	inch := make(chan int)
-	if err := exp.Export("exportedRecv", inch, Recv); err != nil {
-		t.Fatal("exportRecv")
-	}
-
-	outch := make(chan int)
-	if err := exp.Export("exportedSend", outch, Send); err != nil {
-		t.Fatal("exportSend")
-	}
-
-	ctlch := make(chan int)
-	if err := exp.Export("exportedCtl", ctlch, Recv); err != nil {
-		t.Fatal("exportRecv")
-	}
-
-	go func() {
-		<-ctlch
-		for i := 0; i < count; i++ {
-			x := <-inch
-			if x != base+i {
-				t.Errorf("exportLoopback expected %d; got %d", i, x)
-			}
-			outch <- x
-		}
-	}()
-}
-
-// This test checks that channel operations can proceed
-// even when other concurrent operations are blocked.
-func TestIndependentSends(t *testing.T) {
-	exp, imp := pair(t)
-
-	exportLoopback(exp, t)
-
-	importSend(imp, count, t, nil)
-	done := make(chan bool)
-	go importReceive(imp, t, done)
-
-	// wait for export side to try to deliver some values.
-	time.Sleep(0.25e9)
-
-	ctlch := make(chan int)
-	if err := imp.ImportNValues("exportedCtl", ctlch, Send, 1, 1); err != nil {
-		t.Fatal("importSend:", err)
-	}
-	ctlch <- 0
-
-	<-done
-}
-
-// This test cross-connects a pair of exporter/importer pairs.
-type value struct {
-	I      int
-	Source string
-}
-
-func TestCrossConnect(t *testing.T) {
-	e1, i1 := pair(t)
-	e2, i2 := pair(t)
-
-	crossExport(e1, e2, t)
-	crossImport(i1, i2, t)
-}
-
-// Export side of cross-traffic.
-func crossExport(e1, e2 *Exporter, t *testing.T) {
-	s := make(chan value)
-	err := e1.Export("exportedSend", s, Send)
-	if err != nil {
-		t.Fatal("exportSend:", err)
-	}
-
-	r := make(chan value)
-	err = e2.Export("exportedReceive", r, Recv)
-	if err != nil {
-		t.Fatal("exportReceive:", err)
-	}
-
-	go crossLoop("export", s, r, t)
-}
-
-// Import side of cross-traffic.
-func crossImport(i1, i2 *Importer, t *testing.T) {
-	s := make(chan value)
-	err := i2.Import("exportedReceive", s, Send, 2)
-	if err != nil {
-		t.Fatal("import of exportedReceive:", err)
-	}
-
-	r := make(chan value)
-	err = i1.Import("exportedSend", r, Recv, 2)
-	if err != nil {
-		t.Fatal("import of exported Send:", err)
-	}
-
-	crossLoop("import", s, r, t)
-}
-
-// Cross-traffic: send and receive 'count' numbers.
-func crossLoop(name string, s, r chan value, t *testing.T) {
-	for si, ri := 0, 0; si < count && ri < count; {
-		select {
-		case s <- value{si, name}:
-			si++
-		case v := <-r:
-			if v.I != ri {
-				t.Errorf("loop: bad value: expected %d, hello; got %+v", ri, v)
-			}
-			ri++
-		}
-	}
-}
-
-const flowCount = 100
-
-// test flow control from exporter to importer.
-func TestExportFlowControl(t *testing.T) {
-	exp, imp := pair(t)
-
-	sendDone := make(chan bool, 1)
-	exportSend(exp, flowCount, t, sendDone)
-
-	ch := make(chan int)
-	err := imp.ImportNValues("exportedSend", ch, Recv, 20, -1)
-	if err != nil {
-		t.Fatal("importReceive:", err)
-	}
-
-	testFlow(sendDone, ch, flowCount, t)
-}
-
-// test flow control from importer to exporter.
-func TestImportFlowControl(t *testing.T) {
-	exp, imp := pair(t)
-
-	ch := make(chan int)
-	err := exp.Export("exportedRecv", ch, Recv)
-	if err != nil {
-		t.Fatal("importReceive:", err)
-	}
-
-	sendDone := make(chan bool, 1)
-	importSend(imp, flowCount, t, sendDone)
-	testFlow(sendDone, ch, flowCount, t)
-}
-
-func testFlow(sendDone chan bool, ch <-chan int, N int, t *testing.T) {
-	go func() {
-		time.Sleep(0.5e9)
-		sendDone <- false
-	}()
-
-	if <-sendDone {
-		t.Fatal("send did not block")
-	}
-	n := 0
-	for i := range ch {
-		t.Log("after blocking, got value ", i)
-		n++
-	}
-	if n != N {
-		t.Fatalf("expected %d values; got %d", N, n)
-	}
-}
-
-func pair(t *testing.T) (*Exporter, *Importer) {
-	c0, c1 := net.Pipe()
-	exp := NewExporter()
-	go exp.ServeConn(c0)
-	imp := NewImporter(c1)
-	return exp, imp
-}
diff --git a/src/pkg/old/netchan/Makefile b/src/pkg/old/netchan/Makefile
new file mode 100644
index 0000000..c8f4125
--- /dev/null
+++ b/src/pkg/old/netchan/Makefile
@@ -0,0 +1,13 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=old/netchan
+GOFILES=\
+	common.go\
+	export.go\
+	import.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/old/netchan/common.go b/src/pkg/old/netchan/common.go
new file mode 100644
index 0000000..d0daf53
--- /dev/null
+++ b/src/pkg/old/netchan/common.go
@@ -0,0 +1,338 @@
+// Copyright 2010 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 netchan
+
+import (
+	"encoding/gob"
+	"errors"
+	"io"
+	"reflect"
+	"sync"
+	"time"
+)
+
+// The direction of a connection from the client's perspective.
+type Dir int
+
+const (
+	Recv Dir = iota
+	Send
+)
+
+func (dir Dir) String() string {
+	switch dir {
+	case Recv:
+		return "Recv"
+	case Send:
+		return "Send"
+	}
+	return "???"
+}
+
+// Payload types
+const (
+	payRequest = iota // request structure follows
+	payError          // error structure follows
+	payData           // user payload follows
+	payAck            // acknowledgement; no payload
+	payClosed         // channel is now closed
+	payAckSend        // payload has been delivered.
+)
+
+// A header is sent as a prefix to every transmission.  It will be followed by
+// a request structure, an error structure, or an arbitrary user payload structure.
+type header struct {
+	Id          int
+	PayloadType int
+	SeqNum      int64
+}
+
+// Sent with a header once per channel from importer to exporter to report
+// that it wants to bind to a channel with the specified direction for count
+// messages, with space for size buffered values. If count is -1, it means unlimited.
+type request struct {
+	Name  string
+	Count int64
+	Size  int
+	Dir   Dir
+}
+
+// Sent with a header to report an error.
+type error_ struct {
+	Error string
+}
+
+// Used to unify management of acknowledgements for import and export.
+type unackedCounter interface {
+	unackedCount() int64
+	ack() int64
+	seq() int64
+}
+
+// A channel and its direction.
+type chanDir struct {
+	ch  reflect.Value
+	dir Dir
+}
+
+// clientSet contains the objects and methods needed for tracking
+// clients of an exporter and draining outstanding messages.
+type clientSet struct {
+	mu      sync.Mutex // protects access to channel and client maps
+	names   map[string]*chanDir
+	clients map[unackedCounter]bool
+}
+
+// Mutex-protected encoder and decoder pair.
+type encDec struct {
+	decLock sync.Mutex
+	dec     *gob.Decoder
+	encLock sync.Mutex
+	enc     *gob.Encoder
+}
+
+func newEncDec(conn io.ReadWriter) *encDec {
+	return &encDec{
+		dec: gob.NewDecoder(conn),
+		enc: gob.NewEncoder(conn),
+	}
+}
+
+// Decode an item from the connection.
+func (ed *encDec) decode(value reflect.Value) error {
+	ed.decLock.Lock()
+	err := ed.dec.DecodeValue(value)
+	if err != nil {
+		// TODO: tear down connection?
+	}
+	ed.decLock.Unlock()
+	return err
+}
+
+// Encode a header and payload onto the connection.
+func (ed *encDec) encode(hdr *header, payloadType int, payload interface{}) error {
+	ed.encLock.Lock()
+	hdr.PayloadType = payloadType
+	err := ed.enc.Encode(hdr)
+	if err == nil {
+		if payload != nil {
+			err = ed.enc.Encode(payload)
+		}
+	}
+	if err != nil {
+		// TODO: tear down connection if there is an error?
+	}
+	ed.encLock.Unlock()
+	return err
+}
+
+// See the comment for Exporter.Drain.
+func (cs *clientSet) drain(timeout time.Duration) error {
+	deadline := time.Now().Add(timeout)
+	for {
+		pending := false
+		cs.mu.Lock()
+		// Any messages waiting for a client?
+		for _, chDir := range cs.names {
+			if chDir.ch.Len() > 0 {
+				pending = true
+			}
+		}
+		// Any unacknowledged messages?
+		for client := range cs.clients {
+			n := client.unackedCount()
+			if n > 0 { // Check for > rather than != just to be safe.
+				pending = true
+				break
+			}
+		}
+		cs.mu.Unlock()
+		if !pending {
+			break
+		}
+		if timeout > 0 && time.Now().After(deadline) {
+			return errors.New("timeout")
+		}
+		time.Sleep(100 * time.Millisecond)
+	}
+	return nil
+}
+
+// See the comment for Exporter.Sync.
+func (cs *clientSet) sync(timeout time.Duration) error {
+	deadline := time.Now().Add(timeout)
+	// seq remembers the clients and their seqNum at point of entry.
+	seq := make(map[unackedCounter]int64)
+	cs.mu.Lock()
+	for client := range cs.clients {
+		seq[client] = client.seq()
+	}
+	cs.mu.Unlock()
+	for {
+		pending := false
+		cs.mu.Lock()
+		// Any unacknowledged messages?  Look only at clients that existed
+		// when we started and are still in this client set.
+		for client := range seq {
+			if _, ok := cs.clients[client]; ok {
+				if client.ack() < seq[client] {
+					pending = true
+					break
+				}
+			}
+		}
+		cs.mu.Unlock()
+		if !pending {
+			break
+		}
+		if timeout > 0 && time.Now().After(deadline) {
+			return errors.New("timeout")
+		}
+		time.Sleep(100 * time.Millisecond)
+	}
+	return nil
+}
+
+// A netChan represents a channel imported or exported
+// on a single connection. Flow is controlled by the receiving
+// side by sending payAckSend messages when values
+// are delivered into the local channel.
+type netChan struct {
+	*chanDir
+	name   string
+	id     int
+	size   int // buffer size of channel.
+	closed bool
+
+	// sender-specific state
+	ackCh chan bool // buffered with space for all the acks we need
+	space int       // available space.
+
+	// receiver-specific state
+	sendCh chan reflect.Value // buffered channel of values received from other end.
+	ed     *encDec            // so that we can send acks.
+	count  int64              // number of values still to receive.
+}
+
+// Create a new netChan with the given name (only used for
+// messages), id, direction, buffer size, and count.
+// The connection to the other side is represented by ed.
+func newNetChan(name string, id int, ch *chanDir, ed *encDec, size int, count int64) *netChan {
+	c := &netChan{chanDir: ch, name: name, id: id, size: size, ed: ed, count: count}
+	if c.dir == Send {
+		c.ackCh = make(chan bool, size)
+		c.space = size
+	}
+	return c
+}
+
+// Close the channel.
+func (nch *netChan) close() {
+	if nch.closed {
+		return
+	}
+	if nch.dir == Recv {
+		if nch.sendCh != nil {
+			// If the sender goroutine is active, close the channel to it.
+			// It will close nch.ch when it can.
+			close(nch.sendCh)
+		} else {
+			nch.ch.Close()
+		}
+	} else {
+		nch.ch.Close()
+		close(nch.ackCh)
+	}
+	nch.closed = true
+}
+
+// Send message from remote side to local receiver.
+func (nch *netChan) send(val reflect.Value) {
+	if nch.dir != Recv {
+		panic("send on wrong direction of channel")
+	}
+	if nch.sendCh == nil {
+		// If possible, do local send directly and ack immediately.
+		if nch.ch.TrySend(val) {
+			nch.sendAck()
+			return
+		}
+		// Start sender goroutine to manage delayed delivery of values.
+		nch.sendCh = make(chan reflect.Value, nch.size)
+		go nch.sender()
+	}
+	select {
+	case nch.sendCh <- val:
+		// ok
+	default:
+		// TODO: should this be more resilient?
+		panic("netchan: remote sender sent more values than allowed")
+	}
+}
+
+// sendAck sends an acknowledgment that a message has left
+// the channel's buffer. If the messages remaining to be sent
+// will fit in the channel's buffer, then we don't
+// need to send an ack.
+func (nch *netChan) sendAck() {
+	if nch.count < 0 || nch.count > int64(nch.size) {
+		nch.ed.encode(&header{Id: nch.id}, payAckSend, nil)
+	}
+	if nch.count > 0 {
+		nch.count--
+	}
+}
+
+// The sender process forwards items from the sending queue
+// to the destination channel, acknowledging each item.
+func (nch *netChan) sender() {
+	if nch.dir != Recv {
+		panic("sender on wrong direction of channel")
+	}
+	// When Exporter.Hangup is called, the underlying channel is closed,
+	// and so we may get a "too many operations on closed channel" error
+	// if there are outstanding messages in sendCh.
+	// Make sure that this doesn't panic the whole program.
+	defer func() {
+		if r := recover(); r != nil {
+			// TODO check that r is "too many operations", otherwise re-panic.
+		}
+	}()
+	for v := range nch.sendCh {
+		nch.ch.Send(v)
+		nch.sendAck()
+	}
+	nch.ch.Close()
+}
+
+// Receive value from local side for sending to remote side.
+func (nch *netChan) recv() (val reflect.Value, ok bool) {
+	if nch.dir != Send {
+		panic("recv on wrong direction of channel")
+	}
+
+	if nch.space == 0 {
+		// Wait for buffer space.
+		<-nch.ackCh
+		nch.space++
+	}
+	nch.space--
+	return nch.ch.Recv()
+}
+
+// acked is called when the remote side indicates that
+// a value has been delivered.
+func (nch *netChan) acked() {
+	if nch.dir != Send {
+		panic("recv on wrong direction of channel")
+	}
+	select {
+	case nch.ackCh <- true:
+		// ok
+	default:
+		// TODO: should this be more resilient?
+		panic("netchan: remote receiver sent too many acks")
+	}
+}
diff --git a/src/pkg/old/netchan/export.go b/src/pkg/old/netchan/export.go
new file mode 100644
index 0000000..d94c4b1
--- /dev/null
+++ b/src/pkg/old/netchan/export.go
@@ -0,0 +1,400 @@
+// Copyright 2010 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 netchan implements type-safe networked channels:
+	it allows the two ends of a channel to appear on different
+	computers connected by a network.  It does this by transporting
+	data sent to a channel on one machine so it can be recovered
+	by a receive of a channel of the same type on the other.
+
+	An exporter publishes a set of channels by name.  An importer
+	connects to the exporting machine and imports the channels
+	by name. After importing the channels, the two machines can
+	use the channels in the usual way.
+
+	Networked channels are not synchronized; they always behave
+	as if they are buffered channels of at least one element.
+*/
+package netchan
+
+// BUG: can't use range clause to receive when using ImportNValues to limit the count.
+
+import (
+	"errors"
+	"io"
+	"log"
+	"net"
+	"reflect"
+	"strconv"
+	"sync"
+	"time"
+)
+
+// Export
+
+// expLog is a logging convenience function.  The first argument must be a string.
+func expLog(args ...interface{}) {
+	args[0] = "netchan export: " + args[0].(string)
+	log.Print(args...)
+}
+
+// An Exporter allows a set of channels to be published on a single
+// network port.  A single machine may have multiple Exporters
+// but they must use different ports.
+type Exporter struct {
+	*clientSet
+}
+
+type expClient struct {
+	*encDec
+	exp     *Exporter
+	chans   map[int]*netChan // channels in use by client
+	mu      sync.Mutex       // protects remaining fields
+	errored bool             // client has been sent an error
+	seqNum  int64            // sequences messages sent to client; has value of highest sent
+	ackNum  int64            // highest sequence number acknowledged
+	seqLock sync.Mutex       // guarantees messages are in sequence, only locked under mu
+}
+
+func newClient(exp *Exporter, conn io.ReadWriter) *expClient {
+	client := new(expClient)
+	client.exp = exp
+	client.encDec = newEncDec(conn)
+	client.seqNum = 0
+	client.ackNum = 0
+	client.chans = make(map[int]*netChan)
+	return client
+}
+
+func (client *expClient) sendError(hdr *header, err string) {
+	error := &error_{err}
+	expLog("sending error to client:", error.Error)
+	client.encode(hdr, payError, error) // ignore any encode error, hope client gets it
+	client.mu.Lock()
+	client.errored = true
+	client.mu.Unlock()
+}
+
+func (client *expClient) newChan(hdr *header, dir Dir, name string, size int, count int64) *netChan {
+	exp := client.exp
+	exp.mu.Lock()
+	ech, ok := exp.names[name]
+	exp.mu.Unlock()
+	if !ok {
+		client.sendError(hdr, "no such channel: "+name)
+		return nil
+	}
+	if ech.dir != dir {
+		client.sendError(hdr, "wrong direction for channel: "+name)
+		return nil
+	}
+	nch := newNetChan(name, hdr.Id, ech, client.encDec, size, count)
+	client.chans[hdr.Id] = nch
+	return nch
+}
+
+func (client *expClient) getChan(hdr *header, dir Dir) *netChan {
+	nch := client.chans[hdr.Id]
+	if nch == nil {
+		return nil
+	}
+	if nch.dir != dir {
+		client.sendError(hdr, "wrong direction for channel: "+nch.name)
+	}
+	return nch
+}
+
+// The function run manages sends and receives for a single client.  For each
+// (client Recv) request, this will launch a serveRecv goroutine to deliver
+// the data for that channel, while (client Send) requests are handled as
+// data arrives from the client.
+func (client *expClient) run() {
+	hdr := new(header)
+	hdrValue := reflect.ValueOf(hdr)
+	req := new(request)
+	reqValue := reflect.ValueOf(req)
+	error := new(error_)
+	for {
+		*hdr = header{}
+		if err := client.decode(hdrValue); err != nil {
+			if err != io.EOF {
+				expLog("error decoding client header:", err)
+			}
+			break
+		}
+		switch hdr.PayloadType {
+		case payRequest:
+			*req = request{}
+			if err := client.decode(reqValue); err != nil {
+				expLog("error decoding client request:", err)
+				break
+			}
+			if req.Size < 1 {
+				panic("netchan: remote requested " + strconv.Itoa(req.Size) + " values")
+			}
+			switch req.Dir {
+			case Recv:
+				// look up channel before calling serveRecv to
+				// avoid a lock around client.chans.
+				if nch := client.newChan(hdr, Send, req.Name, req.Size, req.Count); nch != nil {
+					go client.serveRecv(nch, *hdr, req.Count)
+				}
+			case Send:
+				client.newChan(hdr, Recv, req.Name, req.Size, req.Count)
+				// The actual sends will have payload type payData.
+				// TODO: manage the count?
+			default:
+				error.Error = "request: can't handle channel direction"
+				expLog(error.Error, req.Dir)
+				client.encode(hdr, payError, error)
+			}
+		case payData:
+			client.serveSend(*hdr)
+		case payClosed:
+			client.serveClosed(*hdr)
+		case payAck:
+			client.mu.Lock()
+			if client.ackNum != hdr.SeqNum-1 {
+				// Since the sequence number is incremented and the message is sent
+				// in a single instance of locking client.mu, the messages are guaranteed
+				// to be sent in order.  Therefore receipt of acknowledgement N means
+				// all messages <=N have been seen by the recipient.  We check anyway.
+				expLog("sequence out of order:", client.ackNum, hdr.SeqNum)
+			}
+			if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count. 
+				client.ackNum = hdr.SeqNum
+			}
+			client.mu.Unlock()
+		case payAckSend:
+			if nch := client.getChan(hdr, Send); nch != nil {
+				nch.acked()
+			}
+		default:
+			log.Fatal("netchan export: unknown payload type", hdr.PayloadType)
+		}
+	}
+	client.exp.delClient(client)
+}
+
+// Send all the data on a single channel to a client asking for a Recv.
+// The header is passed by value to avoid issues of overwriting.
+func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) {
+	for {
+		val, ok := nch.recv()
+		if !ok {
+			if err := client.encode(&hdr, payClosed, nil); err != nil {
+				expLog("error encoding server closed message:", err)
+			}
+			break
+		}
+		// We hold the lock during transmission to guarantee messages are
+		// sent in sequence number order.  Also, we increment first so the
+		// value of client.SeqNum is the value of the highest used sequence
+		// number, not one beyond.
+		client.mu.Lock()
+		client.seqNum++
+		hdr.SeqNum = client.seqNum
+		client.seqLock.Lock() // guarantee ordering of messages
+		client.mu.Unlock()
+		err := client.encode(&hdr, payData, val.Interface())
+		client.seqLock.Unlock()
+		if err != nil {
+			expLog("error encoding client response:", err)
+			client.sendError(&hdr, err.Error())
+			break
+		}
+		// Negative count means run forever.
+		if count >= 0 {
+			if count--; count <= 0 {
+				break
+			}
+		}
+	}
+}
+
+// Receive and deliver locally one item from a client asking for a Send
+// The header is passed by value to avoid issues of overwriting.
+func (client *expClient) serveSend(hdr header) {
+	nch := client.getChan(&hdr, Recv)
+	if nch == nil {
+		return
+	}
+	// Create a new value for each received item.
+	val := reflect.New(nch.ch.Type().Elem()).Elem()
+	if err := client.decode(val); err != nil {
+		expLog("value decode:", err, "; type ", nch.ch.Type())
+		return
+	}
+	nch.send(val)
+}
+
+// Report that client has closed the channel that is sending to us.
+// The header is passed by value to avoid issues of overwriting.
+func (client *expClient) serveClosed(hdr header) {
+	nch := client.getChan(&hdr, Recv)
+	if nch == nil {
+		return
+	}
+	nch.close()
+}
+
+func (client *expClient) unackedCount() int64 {
+	client.mu.Lock()
+	n := client.seqNum - client.ackNum
+	client.mu.Unlock()
+	return n
+}
+
+func (client *expClient) seq() int64 {
+	client.mu.Lock()
+	n := client.seqNum
+	client.mu.Unlock()
+	return n
+}
+
+func (client *expClient) ack() int64 {
+	client.mu.Lock()
+	n := client.seqNum
+	client.mu.Unlock()
+	return n
+}
+
+// Serve waits for incoming connections on the listener
+// and serves the Exporter's channels on each.
+// It blocks until the listener is closed.
+func (exp *Exporter) Serve(listener net.Listener) {
+	for {
+		conn, err := listener.Accept()
+		if err != nil {
+			expLog("listen:", err)
+			break
+		}
+		go exp.ServeConn(conn)
+	}
+}
+
+// ServeConn exports the Exporter's channels on conn.
+// It blocks until the connection is terminated.
+func (exp *Exporter) ServeConn(conn io.ReadWriter) {
+	exp.addClient(conn).run()
+}
+
+// NewExporter creates a new Exporter that exports a set of channels.
+func NewExporter() *Exporter {
+	e := &Exporter{
+		clientSet: &clientSet{
+			names:   make(map[string]*chanDir),
+			clients: make(map[unackedCounter]bool),
+		},
+	}
+	return e
+}
+
+// ListenAndServe exports the exporter's channels through the
+// given network and local address defined as in net.Listen.
+func (exp *Exporter) ListenAndServe(network, localaddr string) error {
+	listener, err := net.Listen(network, localaddr)
+	if err != nil {
+		return err
+	}
+	go exp.Serve(listener)
+	return nil
+}
+
+// addClient creates a new expClient and records its existence
+func (exp *Exporter) addClient(conn io.ReadWriter) *expClient {
+	client := newClient(exp, conn)
+	exp.mu.Lock()
+	exp.clients[client] = true
+	exp.mu.Unlock()
+	return client
+}
+
+// delClient forgets the client existed
+func (exp *Exporter) delClient(client *expClient) {
+	exp.mu.Lock()
+	delete(exp.clients, client)
+	exp.mu.Unlock()
+}
+
+// Drain waits until all messages sent from this exporter/importer, including
+// those not yet sent to any client and possibly including those sent while
+// Drain was executing, have been received by the importer.  In short, it
+// waits until all the exporter's messages have been received by a client.
+// If the timeout is positive and Drain takes longer than that to complete,
+// an error is returned.
+func (exp *Exporter) Drain(timeout time.Duration) error {
+	// This wrapper function is here so the method's comment will appear in godoc.
+	return exp.clientSet.drain(timeout)
+}
+
+// Sync waits until all clients of the exporter have received the messages
+// that were sent at the time Sync was invoked.  Unlike Drain, it does not
+// wait for messages sent while it is running or messages that have not been
+// dispatched to any client.  If the timeout is positive and Sync takes longer
+// than that to complete, an error is returned.
+func (exp *Exporter) Sync(timeout time.Duration) error {
+	// This wrapper function is here so the method's comment will appear in godoc.
+	return exp.clientSet.sync(timeout)
+}
+
+func checkChan(chT interface{}, dir Dir) (reflect.Value, error) {
+	chanType := reflect.TypeOf(chT)
+	if chanType.Kind() != reflect.Chan {
+		return reflect.Value{}, errors.New("not a channel")
+	}
+	if dir != Send && dir != Recv {
+		return reflect.Value{}, errors.New("unknown channel direction")
+	}
+	switch chanType.ChanDir() {
+	case reflect.BothDir:
+	case reflect.SendDir:
+		if dir != Recv {
+			return reflect.Value{}, errors.New("to import/export with Send, must provide <-chan")
+		}
+	case reflect.RecvDir:
+		if dir != Send {
+			return reflect.Value{}, errors.New("to import/export with Recv, must provide chan<-")
+		}
+	}
+	return reflect.ValueOf(chT), nil
+}
+
+// Export exports a channel of a given type and specified direction.  The
+// channel to be exported is provided in the call and may be of arbitrary
+// channel type.
+// Despite the literal signature, the effective signature is
+//	Export(name string, chT chan T, dir Dir)
+func (exp *Exporter) Export(name string, chT interface{}, dir Dir) error {
+	ch, err := checkChan(chT, dir)
+	if err != nil {
+		return err
+	}
+	exp.mu.Lock()
+	defer exp.mu.Unlock()
+	_, present := exp.names[name]
+	if present {
+		return errors.New("channel name already being exported:" + name)
+	}
+	exp.names[name] = &chanDir{ch, dir}
+	return nil
+}
+
+// Hangup disassociates the named channel from the Exporter and closes
+// the channel.  Messages in flight for the channel may be dropped.
+func (exp *Exporter) Hangup(name string) error {
+	exp.mu.Lock()
+	chDir, ok := exp.names[name]
+	if ok {
+		delete(exp.names, name)
+	}
+	// TODO drop all instances of channel from client sets
+	exp.mu.Unlock()
+	if !ok {
+		return errors.New("netchan export: hangup: no such channel: " + name)
+	}
+	chDir.ch.Close()
+	return nil
+}
diff --git a/src/pkg/old/netchan/import.go b/src/pkg/old/netchan/import.go
new file mode 100644
index 0000000..50abaa9
--- /dev/null
+++ b/src/pkg/old/netchan/import.go
@@ -0,0 +1,287 @@
+// Copyright 2010 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 netchan
+
+import (
+	"errors"
+	"io"
+	"log"
+	"net"
+	"reflect"
+	"sync"
+	"time"
+)
+
+// Import
+
+// impLog is a logging convenience function.  The first argument must be a string.
+func impLog(args ...interface{}) {
+	args[0] = "netchan import: " + args[0].(string)
+	log.Print(args...)
+}
+
+// An Importer allows a set of channels to be imported from a single
+// remote machine/network port.  A machine may have multiple
+// importers, even from the same machine/network port.
+type Importer struct {
+	*encDec
+	chanLock sync.Mutex // protects access to channel map
+	names    map[string]*netChan
+	chans    map[int]*netChan
+	errors   chan error
+	maxId    int
+	mu       sync.Mutex // protects remaining fields
+	unacked  int64      // number of unacknowledged sends.
+	seqLock  sync.Mutex // guarantees messages are in sequence, only locked under mu
+}
+
+// NewImporter creates a new Importer object to import a set of channels
+// from the given connection. The Exporter must be available and serving when
+// the Importer is created.
+func NewImporter(conn io.ReadWriter) *Importer {
+	imp := new(Importer)
+	imp.encDec = newEncDec(conn)
+	imp.chans = make(map[int]*netChan)
+	imp.names = make(map[string]*netChan)
+	imp.errors = make(chan error, 10)
+	imp.unacked = 0
+	go imp.run()
+	return imp
+}
+
+// Import imports a set of channels from the given network and address.
+func Import(network, remoteaddr string) (*Importer, error) {
+	conn, err := net.Dial(network, remoteaddr)
+	if err != nil {
+		return nil, err
+	}
+	return NewImporter(conn), nil
+}
+
+// shutdown closes all channels for which we are receiving data from the remote side.
+func (imp *Importer) shutdown() {
+	imp.chanLock.Lock()
+	for _, ich := range imp.chans {
+		if ich.dir == Recv {
+			ich.close()
+		}
+	}
+	imp.chanLock.Unlock()
+}
+
+// Handle the data from a single imported data stream, which will
+// have the form
+//	(response, data)*
+// The response identifies by name which channel is transmitting data.
+func (imp *Importer) run() {
+	// Loop on responses; requests are sent by ImportNValues()
+	hdr := new(header)
+	hdrValue := reflect.ValueOf(hdr)
+	ackHdr := new(header)
+	err := new(error_)
+	errValue := reflect.ValueOf(err)
+	for {
+		*hdr = header{}
+		if e := imp.decode(hdrValue); e != nil {
+			if e != io.EOF {
+				impLog("header:", e)
+				imp.shutdown()
+			}
+			return
+		}
+		switch hdr.PayloadType {
+		case payData:
+			// done lower in loop
+		case payError:
+			if e := imp.decode(errValue); e != nil {
+				impLog("error:", e)
+				return
+			}
+			if err.Error != "" {
+				impLog("response error:", err.Error)
+				select {
+				case imp.errors <- errors.New(err.Error):
+					continue // errors are not acknowledged
+				default:
+					imp.shutdown()
+					return
+				}
+			}
+		case payClosed:
+			nch := imp.getChan(hdr.Id, false)
+			if nch != nil {
+				nch.close()
+			}
+			continue // closes are not acknowledged.
+		case payAckSend:
+			// we can receive spurious acks if the channel is
+			// hung up, so we ask getChan to ignore any errors.
+			nch := imp.getChan(hdr.Id, true)
+			if nch != nil {
+				nch.acked()
+				imp.mu.Lock()
+				imp.unacked--
+				imp.mu.Unlock()
+			}
+			continue
+		default:
+			impLog("unexpected payload type:", hdr.PayloadType)
+			return
+		}
+		nch := imp.getChan(hdr.Id, false)
+		if nch == nil {
+			continue
+		}
+		if nch.dir != Recv {
+			impLog("cannot happen: receive from non-Recv channel")
+			return
+		}
+		// Acknowledge receipt
+		ackHdr.Id = hdr.Id
+		ackHdr.SeqNum = hdr.SeqNum
+		imp.encode(ackHdr, payAck, nil)
+		// Create a new value for each received item.
+		value := reflect.New(nch.ch.Type().Elem()).Elem()
+		if e := imp.decode(value); e != nil {
+			impLog("importer value decode:", e)
+			return
+		}
+		nch.send(value)
+	}
+}
+
+func (imp *Importer) getChan(id int, errOk bool) *netChan {
+	imp.chanLock.Lock()
+	ich := imp.chans[id]
+	imp.chanLock.Unlock()
+	if ich == nil {
+		if !errOk {
+			impLog("unknown id in netchan request: ", id)
+		}
+		return nil
+	}
+	return ich
+}
+
+// Errors returns a channel from which transmission and protocol errors
+// can be read. Clients of the importer are not required to read the error
+// channel for correct execution. However, if too many errors occur
+// without being read from the error channel, the importer will shut down.
+func (imp *Importer) Errors() chan error {
+	return imp.errors
+}
+
+// Import imports a channel of the given type, size and specified direction.
+// It is equivalent to ImportNValues with a count of -1, meaning unbounded.
+func (imp *Importer) Import(name string, chT interface{}, dir Dir, size int) error {
+	return imp.ImportNValues(name, chT, dir, size, -1)
+}
+
+// ImportNValues imports a channel of the given type and specified
+// direction and then receives or transmits up to n values on that
+// channel.  A value of n==-1 implies an unbounded number of values.  The
+// channel will have buffer space for size values, or 1 value if size < 1.
+// The channel to be bound to the remote site's channel is provided
+// in the call and may be of arbitrary channel type.
+// Despite the literal signature, the effective signature is
+//	ImportNValues(name string, chT chan T, dir Dir, size, n int) error
+// Example usage:
+//	imp, err := NewImporter("tcp", "netchanserver.mydomain.com:1234")
+//	if err != nil { log.Fatal(err) }
+//	ch := make(chan myType)
+//	err = imp.ImportNValues("name", ch, Recv, 1, 1)
+//	if err != nil { log.Fatal(err) }
+//	fmt.Printf("%+v\n", <-ch)
+func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, size, n int) error {
+	ch, err := checkChan(chT, dir)
+	if err != nil {
+		return err
+	}
+	imp.chanLock.Lock()
+	defer imp.chanLock.Unlock()
+	_, present := imp.names[name]
+	if present {
+		return errors.New("channel name already being imported:" + name)
+	}
+	if size < 1 {
+		size = 1
+	}
+	id := imp.maxId
+	imp.maxId++
+	nch := newNetChan(name, id, &chanDir{ch, dir}, imp.encDec, size, int64(n))
+	imp.names[name] = nch
+	imp.chans[id] = nch
+	// Tell the other side about this channel.
+	hdr := &header{Id: id}
+	req := &request{Name: name, Count: int64(n), Dir: dir, Size: size}
+	if err = imp.encode(hdr, payRequest, req); err != nil {
+		impLog("request encode:", err)
+		return err
+	}
+	if dir == Send {
+		go func() {
+			for i := 0; n == -1 || i < n; i++ {
+				val, ok := nch.recv()
+				if !ok {
+					if err = imp.encode(hdr, payClosed, nil); err != nil {
+						impLog("error encoding client closed message:", err)
+					}
+					return
+				}
+				// We hold the lock during transmission to guarantee messages are
+				// sent in order.
+				imp.mu.Lock()
+				imp.unacked++
+				imp.seqLock.Lock()
+				imp.mu.Unlock()
+				if err = imp.encode(hdr, payData, val.Interface()); err != nil {
+					impLog("error encoding client send:", err)
+					return
+				}
+				imp.seqLock.Unlock()
+			}
+		}()
+	}
+	return nil
+}
+
+// Hangup disassociates the named channel from the Importer and closes
+// the channel.  Messages in flight for the channel may be dropped.
+func (imp *Importer) Hangup(name string) error {
+	imp.chanLock.Lock()
+	defer imp.chanLock.Unlock()
+	nc := imp.names[name]
+	if nc == nil {
+		return errors.New("netchan import: hangup: no such channel: " + name)
+	}
+	delete(imp.names, name)
+	delete(imp.chans, nc.id)
+	nc.close()
+	return nil
+}
+
+func (imp *Importer) unackedCount() int64 {
+	imp.mu.Lock()
+	n := imp.unacked
+	imp.mu.Unlock()
+	return n
+}
+
+// Drain waits until all messages sent from this exporter/importer, including
+// those not yet sent to any server and possibly including those sent while
+// Drain was executing, have been received by the exporter.  In short, it
+// waits until all the importer's messages have been received.
+// If the timeout (measured in nanoseconds) is positive and Drain takes
+// longer than that to complete, an error is returned.
+func (imp *Importer) Drain(timeout int64) error {
+	deadline := time.Now().Add(time.Duration(timeout))
+	for imp.unackedCount() > 0 {
+		if timeout > 0 && time.Now().After(deadline) {
+			return errors.New("timeout")
+		}
+		time.Sleep(100 * time.Millisecond)
+	}
+	return nil
+}
diff --git a/src/pkg/old/netchan/netchan_test.go b/src/pkg/old/netchan/netchan_test.go
new file mode 100644
index 0000000..53f0f78
--- /dev/null
+++ b/src/pkg/old/netchan/netchan_test.go
@@ -0,0 +1,435 @@
+// Copyright 2010 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 netchan
+
+import (
+	"net"
+	"strings"
+	"testing"
+	"time"
+)
+
+const count = 10     // number of items in most tests
+const closeCount = 5 // number of items when sender closes early
+
+const base = 23
+
+func exportSend(exp *Exporter, n int, t *testing.T, done chan bool) {
+	ch := make(chan int)
+	err := exp.Export("exportedSend", ch, Send)
+	if err != nil {
+		t.Fatal("exportSend:", err)
+	}
+	go func() {
+		for i := 0; i < n; i++ {
+			ch <- base + i
+		}
+		close(ch)
+		if done != nil {
+			done <- true
+		}
+	}()
+}
+
+func exportReceive(exp *Exporter, t *testing.T, expDone chan bool) {
+	ch := make(chan int)
+	err := exp.Export("exportedRecv", ch, Recv)
+	expDone <- true
+	if err != nil {
+		t.Fatal("exportReceive:", err)
+	}
+	for i := 0; i < count; i++ {
+		v, ok := <-ch
+		if !ok {
+			if i != closeCount {
+				t.Errorf("exportReceive expected close at %d; got one at %d", closeCount, i)
+			}
+			break
+		}
+		if v != base+i {
+			t.Errorf("export Receive: bad value: expected %d+%d=%d; got %d", base, i, base+i, v)
+		}
+	}
+}
+
+func importSend(imp *Importer, n int, t *testing.T, done chan bool) {
+	ch := make(chan int)
+	err := imp.ImportNValues("exportedRecv", ch, Send, 3, -1)
+	if err != nil {
+		t.Fatal("importSend:", err)
+	}
+	go func() {
+		for i := 0; i < n; i++ {
+			ch <- base + i
+		}
+		close(ch)
+		if done != nil {
+			done <- true
+		}
+	}()
+}
+
+func importReceive(imp *Importer, t *testing.T, done chan bool) {
+	ch := make(chan int)
+	err := imp.ImportNValues("exportedSend", ch, Recv, 3, count)
+	if err != nil {
+		t.Fatal("importReceive:", err)
+	}
+	for i := 0; i < count; i++ {
+		v, ok := <-ch
+		if !ok {
+			if i != closeCount {
+				t.Errorf("importReceive expected close at %d; got one at %d", closeCount, i)
+			}
+			break
+		}
+		if v != base+i {
+			t.Errorf("importReceive: bad value: expected %d+%d=%d; got %+d", base, i, base+i, v)
+		}
+	}
+	if done != nil {
+		done <- true
+	}
+}
+
+func TestExportSendImportReceive(t *testing.T) {
+	exp, imp := pair(t)
+	exportSend(exp, count, t, nil)
+	importReceive(imp, t, nil)
+}
+
+func TestExportReceiveImportSend(t *testing.T) {
+	exp, imp := pair(t)
+	expDone := make(chan bool)
+	done := make(chan bool)
+	go func() {
+		exportReceive(exp, t, expDone)
+		done <- true
+	}()
+	<-expDone
+	importSend(imp, count, t, nil)
+	<-done
+}
+
+func TestClosingExportSendImportReceive(t *testing.T) {
+	exp, imp := pair(t)
+	exportSend(exp, closeCount, t, nil)
+	importReceive(imp, t, nil)
+}
+
+func TestClosingImportSendExportReceive(t *testing.T) {
+	exp, imp := pair(t)
+	expDone := make(chan bool)
+	done := make(chan bool)
+	go func() {
+		exportReceive(exp, t, expDone)
+		done <- true
+	}()
+	<-expDone
+	importSend(imp, closeCount, t, nil)
+	<-done
+}
+
+func TestErrorForIllegalChannel(t *testing.T) {
+	exp, imp := pair(t)
+	// Now export a channel.
+	ch := make(chan int, 1)
+	err := exp.Export("aChannel", ch, Send)
+	if err != nil {
+		t.Fatal("export:", err)
+	}
+	ch <- 1234
+	close(ch)
+	// Now try to import a different channel.
+	ch = make(chan int)
+	err = imp.Import("notAChannel", ch, Recv, 1)
+	if err != nil {
+		t.Fatal("import:", err)
+	}
+	// Expect an error now.  Start a timeout.
+	timeout := make(chan bool, 1) // buffered so closure will not hang around.
+	go func() {
+		time.Sleep(10 * time.Second) // very long, to give even really slow machines a chance.
+		timeout <- true
+	}()
+	select {
+	case err = <-imp.Errors():
+		if strings.Index(err.Error(), "no such channel") < 0 {
+			t.Error("wrong error for nonexistent channel:", err)
+		}
+	case <-timeout:
+		t.Error("import of nonexistent channel did not receive an error")
+	}
+}
+
+// Not a great test but it does at least invoke Drain.
+func TestExportDrain(t *testing.T) {
+	exp, imp := pair(t)
+	done := make(chan bool)
+	go func() {
+		exportSend(exp, closeCount, t, nil)
+		done <- true
+	}()
+	<-done
+	go importReceive(imp, t, done)
+	exp.Drain(0)
+	<-done
+}
+
+// Not a great test but it does at least invoke Drain.
+func TestImportDrain(t *testing.T) {
+	exp, imp := pair(t)
+	expDone := make(chan bool)
+	go exportReceive(exp, t, expDone)
+	<-expDone
+	importSend(imp, closeCount, t, nil)
+	imp.Drain(0)
+}
+
+// Not a great test but it does at least invoke Sync.
+func TestExportSync(t *testing.T) {
+	exp, imp := pair(t)
+	done := make(chan bool)
+	exportSend(exp, closeCount, t, nil)
+	go importReceive(imp, t, done)
+	exp.Sync(0)
+	<-done
+}
+
+// Test hanging up the send side of an export.
+// TODO: test hanging up the receive side of an export.
+func TestExportHangup(t *testing.T) {
+	exp, imp := pair(t)
+	ech := make(chan int)
+	err := exp.Export("exportedSend", ech, Send)
+	if err != nil {
+		t.Fatal("export:", err)
+	}
+	// Prepare to receive two values. We'll actually deliver only one.
+	ich := make(chan int)
+	err = imp.ImportNValues("exportedSend", ich, Recv, 1, 2)
+	if err != nil {
+		t.Fatal("import exportedSend:", err)
+	}
+	// Send one value, receive it.
+	const Value = 1234
+	ech <- Value
+	v := <-ich
+	if v != Value {
+		t.Fatal("expected", Value, "got", v)
+	}
+	// Now hang up the channel.  Importer should see it close.
+	exp.Hangup("exportedSend")
+	v, ok := <-ich
+	if ok {
+		t.Fatal("expected channel to be closed; got value", v)
+	}
+}
+
+// Test hanging up the send side of an import.
+// TODO: test hanging up the receive side of an import.
+func TestImportHangup(t *testing.T) {
+	exp, imp := pair(t)
+	ech := make(chan int)
+	err := exp.Export("exportedRecv", ech, Recv)
+	if err != nil {
+		t.Fatal("export:", err)
+	}
+	// Prepare to Send two values. We'll actually deliver only one.
+	ich := make(chan int)
+	err = imp.ImportNValues("exportedRecv", ich, Send, 1, 2)
+	if err != nil {
+		t.Fatal("import exportedRecv:", err)
+	}
+	// Send one value, receive it.
+	const Value = 1234
+	ich <- Value
+	v := <-ech
+	if v != Value {
+		t.Fatal("expected", Value, "got", v)
+	}
+	// Now hang up the channel.  Exporter should see it close.
+	imp.Hangup("exportedRecv")
+	v, ok := <-ech
+	if ok {
+		t.Fatal("expected channel to be closed; got value", v)
+	}
+}
+
+// loop back exportedRecv to exportedSend,
+// but receive a value from ctlch before starting the loop.
+func exportLoopback(exp *Exporter, t *testing.T) {
+	inch := make(chan int)
+	if err := exp.Export("exportedRecv", inch, Recv); err != nil {
+		t.Fatal("exportRecv")
+	}
+
+	outch := make(chan int)
+	if err := exp.Export("exportedSend", outch, Send); err != nil {
+		t.Fatal("exportSend")
+	}
+
+	ctlch := make(chan int)
+	if err := exp.Export("exportedCtl", ctlch, Recv); err != nil {
+		t.Fatal("exportRecv")
+	}
+
+	go func() {
+		<-ctlch
+		for i := 0; i < count; i++ {
+			x := <-inch
+			if x != base+i {
+				t.Errorf("exportLoopback expected %d; got %d", i, x)
+			}
+			outch <- x
+		}
+	}()
+}
+
+// This test checks that channel operations can proceed
+// even when other concurrent operations are blocked.
+func TestIndependentSends(t *testing.T) {
+	exp, imp := pair(t)
+
+	exportLoopback(exp, t)
+
+	importSend(imp, count, t, nil)
+	done := make(chan bool)
+	go importReceive(imp, t, done)
+
+	// wait for export side to try to deliver some values.
+	time.Sleep(250 * time.Millisecond)
+
+	ctlch := make(chan int)
+	if err := imp.ImportNValues("exportedCtl", ctlch, Send, 1, 1); err != nil {
+		t.Fatal("importSend:", err)
+	}
+	ctlch <- 0
+
+	<-done
+}
+
+// This test cross-connects a pair of exporter/importer pairs.
+type value struct {
+	I      int
+	Source string
+}
+
+func TestCrossConnect(t *testing.T) {
+	e1, i1 := pair(t)
+	e2, i2 := pair(t)
+
+	crossExport(e1, e2, t)
+	crossImport(i1, i2, t)
+}
+
+// Export side of cross-traffic.
+func crossExport(e1, e2 *Exporter, t *testing.T) {
+	s := make(chan value)
+	err := e1.Export("exportedSend", s, Send)
+	if err != nil {
+		t.Fatal("exportSend:", err)
+	}
+
+	r := make(chan value)
+	err = e2.Export("exportedReceive", r, Recv)
+	if err != nil {
+		t.Fatal("exportReceive:", err)
+	}
+
+	go crossLoop("export", s, r, t)
+}
+
+// Import side of cross-traffic.
+func crossImport(i1, i2 *Importer, t *testing.T) {
+	s := make(chan value)
+	err := i2.Import("exportedReceive", s, Send, 2)
+	if err != nil {
+		t.Fatal("import of exportedReceive:", err)
+	}
+
+	r := make(chan value)
+	err = i1.Import("exportedSend", r, Recv, 2)
+	if err != nil {
+		t.Fatal("import of exported Send:", err)
+	}
+
+	crossLoop("import", s, r, t)
+}
+
+// Cross-traffic: send and receive 'count' numbers.
+func crossLoop(name string, s, r chan value, t *testing.T) {
+	for si, ri := 0, 0; si < count && ri < count; {
+		select {
+		case s <- value{si, name}:
+			si++
+		case v := <-r:
+			if v.I != ri {
+				t.Errorf("loop: bad value: expected %d, hello; got %+v", ri, v)
+			}
+			ri++
+		}
+	}
+}
+
+const flowCount = 100
+
+// test flow control from exporter to importer.
+func TestExportFlowControl(t *testing.T) {
+	exp, imp := pair(t)
+
+	sendDone := make(chan bool, 1)
+	exportSend(exp, flowCount, t, sendDone)
+
+	ch := make(chan int)
+	err := imp.ImportNValues("exportedSend", ch, Recv, 20, -1)
+	if err != nil {
+		t.Fatal("importReceive:", err)
+	}
+
+	testFlow(sendDone, ch, flowCount, t)
+}
+
+// test flow control from importer to exporter.
+func TestImportFlowControl(t *testing.T) {
+	exp, imp := pair(t)
+
+	ch := make(chan int)
+	err := exp.Export("exportedRecv", ch, Recv)
+	if err != nil {
+		t.Fatal("importReceive:", err)
+	}
+
+	sendDone := make(chan bool, 1)
+	importSend(imp, flowCount, t, sendDone)
+	testFlow(sendDone, ch, flowCount, t)
+}
+
+func testFlow(sendDone chan bool, ch <-chan int, N int, t *testing.T) {
+	go func() {
+		time.Sleep(500 * time.Millisecond)
+		sendDone <- false
+	}()
+
+	if <-sendDone {
+		t.Fatal("send did not block")
+	}
+	n := 0
+	for i := range ch {
+		t.Log("after blocking, got value ", i)
+		n++
+	}
+	if n != N {
+		t.Fatalf("expected %d values; got %d", N, n)
+	}
+}
+
+func pair(t *testing.T) (*Exporter, *Importer) {
+	c0, c1 := net.Pipe()
+	exp := NewExporter()
+	go exp.ServeConn(c0)
+	imp := NewImporter(c1)
+	return exp, imp
+}
diff --git a/src/pkg/old/regexp/Makefile b/src/pkg/old/regexp/Makefile
new file mode 100644
index 0000000..ccf99d1
--- /dev/null
+++ b/src/pkg/old/regexp/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=old/regexp
+GOFILES=\
+	regexp.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/old/regexp/all_test.go b/src/pkg/old/regexp/all_test.go
new file mode 100644
index 0000000..180dac4
--- /dev/null
+++ b/src/pkg/old/regexp/all_test.go
@@ -0,0 +1,421 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package regexp
+
+import (
+	"strings"
+	"testing"
+)
+
+var good_re = []string{
+	``,
+	`.`,
+	`^.$`,
+	`a`,
+	`a*`,
+	`a+`,
+	`a?`,
+	`a|b`,
+	`a*|b*`,
+	`(a*|b)(c*|d)`,
+	`[a-z]`,
+	`[a-abc-c\-\]\[]`,
+	`[a-z]+`,
+	`[]`,
+	`[abc]`,
+	`[^1234]`,
+	`[^\n]`,
+	`\!\\`,
+}
+
+type stringError struct {
+	re  string
+	err error
+}
+
+var bad_re = []stringError{
+	{`*`, ErrBareClosure},
+	{`+`, ErrBareClosure},
+	{`?`, ErrBareClosure},
+	{`(abc`, ErrUnmatchedLpar},
+	{`abc)`, ErrUnmatchedRpar},
+	{`x[a-z`, ErrUnmatchedLbkt},
+	{`abc]`, ErrUnmatchedRbkt},
+	{`[z-a]`, ErrBadRange},
+	{`abc\`, ErrExtraneousBackslash},
+	{`a**`, ErrBadClosure},
+	{`a*+`, ErrBadClosure},
+	{`a??`, ErrBadClosure},
+	{`\x`, ErrBadBackslash},
+}
+
+func compileTest(t *testing.T, expr string, error error) *Regexp {
+	re, err := Compile(expr)
+	if err != error {
+		t.Error("compiling `", expr, "`; unexpected error: ", err.Error())
+	}
+	return re
+}
+
+func TestGoodCompile(t *testing.T) {
+	for i := 0; i < len(good_re); i++ {
+		compileTest(t, good_re[i], nil)
+	}
+}
+
+func TestBadCompile(t *testing.T) {
+	for i := 0; i < len(bad_re); i++ {
+		compileTest(t, bad_re[i].re, bad_re[i].err)
+	}
+}
+
+func matchTest(t *testing.T, test *FindTest) {
+	re := compileTest(t, test.pat, nil)
+	if re == nil {
+		return
+	}
+	m := re.MatchString(test.text)
+	if m != (len(test.matches) > 0) {
+		t.Errorf("MatchString failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+	// now try bytes
+	m = re.Match([]byte(test.text))
+	if m != (len(test.matches) > 0) {
+		t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+}
+
+func TestMatch(t *testing.T) {
+	for _, test := range findTests {
+		matchTest(t, &test)
+	}
+}
+
+func matchFunctionTest(t *testing.T, test *FindTest) {
+	m, err := MatchString(test.pat, test.text)
+	if err == nil {
+		return
+	}
+	if m != (len(test.matches) > 0) {
+		t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+	}
+}
+
+func TestMatchFunction(t *testing.T) {
+	for _, test := range findTests {
+		matchFunctionTest(t, &test)
+	}
+}
+
+type ReplaceTest struct {
+	pattern, replacement, input, output string
+}
+
+var replaceTests = []ReplaceTest{
+	// Test empty input and/or replacement, with pattern that matches the empty string.
+	{"", "", "", ""},
+	{"", "x", "", "x"},
+	{"", "", "abc", "abc"},
+	{"", "x", "abc", "xaxbxcx"},
+
+	// Test empty input and/or replacement, with pattern that does not match the empty string.
+	{"b", "", "", ""},
+	{"b", "x", "", ""},
+	{"b", "", "abc", "ac"},
+	{"b", "x", "abc", "axc"},
+	{"y", "", "", ""},
+	{"y", "x", "", ""},
+	{"y", "", "abc", "abc"},
+	{"y", "x", "abc", "abc"},
+
+	// Multibyte characters -- verify that we don't try to match in the middle
+	// of a character.
+	{"[a-c]*", "x", "\u65e5", "x\u65e5x"},
+	{"[^\u65e5]", "x", "abc\u65e5def", "xxx\u65e5xxx"},
+
+	// Start and end of a string.
+	{"^[a-c]*", "x", "abcdabc", "xdabc"},
+	{"[a-c]*$", "x", "abcdabc", "abcdx"},
+	{"^[a-c]*$", "x", "abcdabc", "abcdabc"},
+	{"^[a-c]*", "x", "abc", "x"},
+	{"[a-c]*$", "x", "abc", "x"},
+	{"^[a-c]*$", "x", "abc", "x"},
+	{"^[a-c]*", "x", "dabce", "xdabce"},
+	{"[a-c]*$", "x", "dabce", "dabcex"},
+	{"^[a-c]*$", "x", "dabce", "dabce"},
+	{"^[a-c]*", "x", "", "x"},
+	{"[a-c]*$", "x", "", "x"},
+	{"^[a-c]*$", "x", "", "x"},
+
+	{"^[a-c]+", "x", "abcdabc", "xdabc"},
+	{"[a-c]+$", "x", "abcdabc", "abcdx"},
+	{"^[a-c]+$", "x", "abcdabc", "abcdabc"},
+	{"^[a-c]+", "x", "abc", "x"},
+	{"[a-c]+$", "x", "abc", "x"},
+	{"^[a-c]+$", "x", "abc", "x"},
+	{"^[a-c]+", "x", "dabce", "dabce"},
+	{"[a-c]+$", "x", "dabce", "dabce"},
+	{"^[a-c]+$", "x", "dabce", "dabce"},
+	{"^[a-c]+", "x", "", ""},
+	{"[a-c]+$", "x", "", ""},
+	{"^[a-c]+$", "x", "", ""},
+
+	// Other cases.
+	{"abc", "def", "abcdefg", "defdefg"},
+	{"bc", "BC", "abcbcdcdedef", "aBCBCdcdedef"},
+	{"abc", "", "abcdabc", "d"},
+	{"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"},
+	{"abc", "d", "", ""},
+	{"abc", "d", "abc", "d"},
+	{".+", "x", "abc", "x"},
+	{"[a-c]*", "x", "def", "xdxexfx"},
+	{"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"},
+	{"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"},
+}
+
+type ReplaceFuncTest struct {
+	pattern       string
+	replacement   func(string) string
+	input, output string
+}
+
+var replaceFuncTests = []ReplaceFuncTest{
+	{"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"},
+	{"[a-c]+", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxabcydef"},
+	{"[a-c]*", func(s string) string { return "x" + s + "y" }, "defabcdef", "xydxyexyfxabcydxyexyfxy"},
+}
+
+func TestReplaceAll(t *testing.T) {
+	for _, tc := range replaceTests {
+		re, err := Compile(tc.pattern)
+		if err != nil {
+			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+			continue
+		}
+		actual := re.ReplaceAllString(tc.input, tc.replacement)
+		if actual != tc.output {
+			t.Errorf("%q.Replace(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+		// now try bytes
+		actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replacement)))
+		if actual != tc.output {
+			t.Errorf("%q.Replace(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+	}
+}
+
+func TestReplaceAllFunc(t *testing.T) {
+	for _, tc := range replaceFuncTests {
+		re, err := Compile(tc.pattern)
+		if err != nil {
+			t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+			continue
+		}
+		actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+		// now try bytes
+		actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) }))
+		if actual != tc.output {
+			t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
+				tc.pattern, tc.input, tc.replacement, actual, tc.output)
+		}
+	}
+}
+
+type MetaTest struct {
+	pattern, output, literal string
+	isLiteral                bool
+}
+
+var metaTests = []MetaTest{
+	{``, ``, ``, true},
+	{`foo`, `foo`, `foo`, true},
+	{`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
+	{`foo.\$`, `foo\.\\\$`, `foo`, false},     // has escaped operators and real operators
+	{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`, `!@#`, false},
+}
+
+func TestQuoteMeta(t *testing.T) {
+	for _, tc := range metaTests {
+		// Verify that QuoteMeta returns the expected string.
+		quoted := QuoteMeta(tc.pattern)
+		if quoted != tc.output {
+			t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
+				tc.pattern, quoted, tc.output)
+			continue
+		}
+
+		// Verify that the quoted string is in fact treated as expected
+		// by Compile -- i.e. that it matches the original, unquoted string.
+		if tc.pattern != "" {
+			re, err := Compile(quoted)
+			if err != nil {
+				t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
+				continue
+			}
+			src := "abc" + tc.pattern + "def"
+			repl := "xyz"
+			replaced := re.ReplaceAllString(src, repl)
+			expected := "abcxyzdef"
+			if replaced != expected {
+				t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
+					tc.pattern, src, repl, replaced, expected)
+			}
+		}
+	}
+}
+
+func TestLiteralPrefix(t *testing.T) {
+	for _, tc := range metaTests {
+		// Literal method needs to scan the pattern.
+		re := MustCompile(tc.pattern)
+		str, complete := re.LiteralPrefix()
+		if complete != tc.isLiteral {
+			t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
+		}
+		if str != tc.literal {
+			t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
+		}
+	}
+}
+
+type numSubexpCase struct {
+	input    string
+	expected int
+}
+
+var numSubexpCases = []numSubexpCase{
+	{``, 0},
+	{`.*`, 0},
+	{`abba`, 0},
+	{`ab(b)a`, 1},
+	{`ab(.*)a`, 1},
+	{`(.*)ab(.*)a`, 2},
+	{`(.*)(ab)(.*)a`, 3},
+	{`(.*)((a)b)(.*)a`, 4},
+	{`(.*)(\(ab)(.*)a`, 3},
+	{`(.*)(\(a\)b)(.*)a`, 3},
+}
+
+func TestNumSubexp(t *testing.T) {
+	for _, c := range numSubexpCases {
+		re := MustCompile(c.input)
+		n := re.NumSubexp()
+		if n != c.expected {
+			t.Errorf("NumSubexp for %q returned %d, expected %d", c.input, n, c.expected)
+		}
+	}
+}
+
+func BenchmarkLiteral(b *testing.B) {
+	x := strings.Repeat("x", 50) + "y"
+	b.StopTimer()
+	re := MustCompile("y")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatal("no match!")
+		}
+	}
+}
+
+func BenchmarkNotLiteral(b *testing.B) {
+	x := strings.Repeat("x", 50) + "y"
+	b.StopTimer()
+	re := MustCompile(".y")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatal("no match!")
+		}
+	}
+}
+
+func BenchmarkMatchClass(b *testing.B) {
+	b.StopTimer()
+	x := strings.Repeat("xxxx", 20) + "w"
+	re := MustCompile("[abcdw]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatal("no match!")
+		}
+	}
+}
+
+func BenchmarkMatchClass_InRange(b *testing.B) {
+	b.StopTimer()
+	// 'b' is between 'a' and 'c', so the charclass
+	// range checking is no help here.
+	x := strings.Repeat("bbbb", 20) + "c"
+	re := MustCompile("[ac]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		if !re.MatchString(x) {
+			b.Fatal("no match!")
+		}
+	}
+}
+
+func BenchmarkReplaceAll(b *testing.B) {
+	x := "abcdefghijklmnopqrstuvwxyz"
+	b.StopTimer()
+	re := MustCompile("[cjrw]")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.ReplaceAllString(x, "")
+	}
+}
+
+func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	re := MustCompile("^zbc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	for i := 0; i < 15; i++ {
+		x = append(x, x...)
+	}
+	re := MustCompile("^zbc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredShortMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	re := MustCompile("^.bc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
+
+func BenchmarkAnchoredLongMatch(b *testing.B) {
+	b.StopTimer()
+	x := []byte("abcdefghijklmnopqrstuvwxyz")
+	for i := 0; i < 15; i++ {
+		x = append(x, x...)
+	}
+	re := MustCompile("^.bc(d|e)")
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		re.Match(x)
+	}
+}
diff --git a/src/pkg/regexp/find_test.go b/src/pkg/old/regexp/find_test.go
similarity index 100%
copy from src/pkg/regexp/find_test.go
copy to src/pkg/old/regexp/find_test.go
diff --git a/src/pkg/old/regexp/regexp.go b/src/pkg/old/regexp/regexp.go
new file mode 100644
index 0000000..d3044d0
--- /dev/null
+++ b/src/pkg/old/regexp/regexp.go
@@ -0,0 +1,1488 @@
+// Copyright 2010 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 regexp implements a simple regular expression library.
+//
+// The syntax of the regular expressions accepted is:
+//
+//	regexp:
+//		concatenation { '|' concatenation }
+//	concatenation:
+//		{ closure }
+//	closure:
+//		term [ '*' | '+' | '?' ]
+//	term:
+//		'^'
+//		'$'
+//		'.'
+//		character
+//		'[' [ '^' ] { character-range } ']'
+//		'(' regexp ')'
+//	character-range:
+//		character [ '-' character ]
+//
+// All characters are UTF-8-encoded code points.  Backslashes escape special
+// characters, including inside character classes.  The standard Go character
+// escapes are also recognized: \a \b \f \n \r \t \v.
+//
+// There are 16 methods of Regexp that match a regular expression and identify
+// the matched text.  Their names are matched by this regular expression:
+//
+//	Find(All)?(String)?(Submatch)?(Index)?
+//
+// If 'All' is present, the routine matches successive non-overlapping
+// matches of the entire expression.  Empty matches abutting a preceding
+// match are ignored.  The return value is a slice containing the successive
+// return values of the corresponding non-'All' routine.  These routines take
+// an extra integer argument, n; if n >= 0, the function returns at most n
+// matches/submatches.
+//
+// If 'String' is present, the argument is a string; otherwise it is a slice
+// of bytes; return values are adjusted as appropriate.
+//
+// If 'Submatch' is present, the return value is a slice identifying the
+// successive submatches of the expression.  Submatches are matches of
+// parenthesized subexpressions within the regular expression, numbered from
+// left to right in order of opening parenthesis.  Submatch 0 is the match of
+// the entire expression, submatch 1 the match of the first parenthesized
+// subexpression, and so on.
+//
+// If 'Index' is present, matches and submatches are identified by byte index
+// pairs within the input string: result[2*n:2*n+1] identifies the indexes of
+// the nth submatch.  The pair for n==0 identifies the match of the entire
+// expression.  If 'Index' is not present, the match is identified by the
+// text of the match/submatch.  If an index is negative, it means that
+// subexpression did not match any string in the input.
+//
+// There is also a subset of the methods that can be applied to text read
+// from a RuneReader:
+//
+//	MatchReader, FindReaderIndex, FindReaderSubmatchIndex
+//
+// This set may grow.  Note that regular expression matches may need to
+// examine text beyond the text returned by a match, so the methods that
+// match text from a RuneReader may read arbitrarily far into the input
+// before returning.
+//
+// (There are a few other methods that do not match this pattern.)
+//
+package regexp
+
+import (
+	"bytes"
+	"io"
+	"strings"
+	"unicode/utf8"
+)
+
+var debug = false
+
+// Error is the local type for a parsing error.
+type Error string
+
+func (e Error) Error() string {
+	return string(e)
+}
+
+// Error codes returned by failures to parse an expression.
+var (
+	ErrInternal            = Error("regexp: internal error")
+	ErrUnmatchedLpar       = Error("regexp: unmatched '('")
+	ErrUnmatchedRpar       = Error("regexp: unmatched ')'")
+	ErrUnmatchedLbkt       = Error("regexp: unmatched '['")
+	ErrUnmatchedRbkt       = Error("regexp: unmatched ']'")
+	ErrBadRange            = Error("regexp: bad range in character class")
+	ErrExtraneousBackslash = Error("regexp: extraneous backslash")
+	ErrBadClosure          = Error("regexp: repeated closure (**, ++, etc.)")
+	ErrBareClosure         = Error("regexp: closure applies to nothing")
+	ErrBadBackslash        = Error("regexp: illegal backslash escape")
+)
+
+const (
+	iStart     = iota // beginning of program
+	iEnd              // end of program: success
+	iBOT              // '^' beginning of text
+	iEOT              // '$' end of text
+	iChar             // 'a' regular character
+	iCharClass        // [a-z] character class
+	iAny              // '.' any character including newline
+	iNotNL            // [^\n] special case: any character but newline
+	iBra              // '(' parenthesized expression: 2*braNum for left, 2*braNum+1 for right
+	iAlt              // '|' alternation
+	iNop              // do nothing; makes it easy to link without patching
+)
+
+// An instruction executed by the NFA
+type instr struct {
+	kind  int    // the type of this instruction: iChar, iAny, etc.
+	index int    // used only in debugging; could be eliminated
+	next  *instr // the instruction to execute after this one
+	// Special fields valid only for some items.
+	char   rune       // iChar
+	braNum int        // iBra, iEbra
+	cclass *charClass // iCharClass
+	left   *instr     // iAlt, other branch
+}
+
+func (i *instr) print() {
+	switch i.kind {
+	case iStart:
+		print("start")
+	case iEnd:
+		print("end")
+	case iBOT:
+		print("bot")
+	case iEOT:
+		print("eot")
+	case iChar:
+		print("char ", string(i.char))
+	case iCharClass:
+		i.cclass.print()
+	case iAny:
+		print("any")
+	case iNotNL:
+		print("notnl")
+	case iBra:
+		if i.braNum&1 == 0 {
+			print("bra", i.braNum/2)
+		} else {
+			print("ebra", i.braNum/2)
+		}
+	case iAlt:
+		print("alt(", i.left.index, ")")
+	case iNop:
+		print("nop")
+	}
+}
+
+// Regexp is the representation of a compiled regular expression.
+// The public interface is entirely through methods.
+// A Regexp is safe for concurrent use by multiple goroutines.
+type Regexp struct {
+	expr        string // the original expression
+	prefix      string // initial plain text string
+	prefixBytes []byte // initial plain text bytes
+	inst        []*instr
+	start       *instr // first instruction of machine
+	prefixStart *instr // where to start if there is a prefix
+	nbra        int    // number of brackets in expression, for subexpressions
+}
+
+type charClass struct {
+	negate bool // is character class negated? ([^a-z])
+	// slice of int, stored pairwise: [a-z] is (a,z); x is (x,x):
+	ranges     []rune
+	cmin, cmax rune
+}
+
+func (cclass *charClass) print() {
+	print("charclass")
+	if cclass.negate {
+		print(" (negated)")
+	}
+	for i := 0; i < len(cclass.ranges); i += 2 {
+		l := cclass.ranges[i]
+		r := cclass.ranges[i+1]
+		if l == r {
+			print(" [", string(l), "]")
+		} else {
+			print(" [", string(l), "-", string(r), "]")
+		}
+	}
+}
+
+func (cclass *charClass) addRange(a, b rune) {
+	// range is a through b inclusive
+	cclass.ranges = append(cclass.ranges, a, b)
+	if a < cclass.cmin {
+		cclass.cmin = a
+	}
+	if b > cclass.cmax {
+		cclass.cmax = b
+	}
+}
+
+func (cclass *charClass) matches(c rune) bool {
+	if c < cclass.cmin || c > cclass.cmax {
+		return cclass.negate
+	}
+	ranges := cclass.ranges
+	for i := 0; i < len(ranges); i = i + 2 {
+		if ranges[i] <= c && c <= ranges[i+1] {
+			return !cclass.negate
+		}
+	}
+	return cclass.negate
+}
+
+func newCharClass() *instr {
+	i := &instr{kind: iCharClass}
+	i.cclass = new(charClass)
+	i.cclass.ranges = make([]rune, 0, 4)
+	i.cclass.cmin = 0x10FFFF + 1 // MaxRune + 1
+	i.cclass.cmax = -1
+	return i
+}
+
+func (re *Regexp) add(i *instr) *instr {
+	i.index = len(re.inst)
+	re.inst = append(re.inst, i)
+	return i
+}
+
+type parser struct {
+	re    *Regexp
+	nlpar int // number of unclosed lpars
+	pos   int
+	ch    rune
+}
+
+func (p *parser) error(err Error) {
+	panic(err)
+}
+
+const endOfText = -1
+
+func (p *parser) c() rune { return p.ch }
+
+func (p *parser) nextc() rune {
+	if p.pos >= len(p.re.expr) {
+		p.ch = endOfText
+	} else {
+		c, w := utf8.DecodeRuneInString(p.re.expr[p.pos:])
+		p.ch = c
+		p.pos += w
+	}
+	return p.ch
+}
+
+func newParser(re *Regexp) *parser {
+	p := new(parser)
+	p.re = re
+	p.nextc() // load p.ch
+	return p
+}
+
+func special(c rune) bool {
+	for _, r := range `\.+*?()|[]^$` {
+		if c == r {
+			return true
+		}
+	}
+	return false
+}
+
+func ispunct(c rune) bool {
+	for _, r := range "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" {
+		if c == r {
+			return true
+		}
+	}
+	return false
+}
+
+var escapes = []byte("abfnrtv")
+var escaped = []byte("\a\b\f\n\r\t\v")
+
+func escape(c rune) int {
+	for i, b := range escapes {
+		if rune(b) == c {
+			return i
+		}
+	}
+	return -1
+}
+
+func (p *parser) checkBackslash() rune {
+	c := p.c()
+	if c == '\\' {
+		c = p.nextc()
+		switch {
+		case c == endOfText:
+			p.error(ErrExtraneousBackslash)
+		case ispunct(c):
+			// c is as delivered
+		case escape(c) >= 0:
+			c = rune(escaped[escape(c)])
+		default:
+			p.error(ErrBadBackslash)
+		}
+	}
+	return c
+}
+
+func (p *parser) charClass() *instr {
+	i := newCharClass()
+	cc := i.cclass
+	if p.c() == '^' {
+		cc.negate = true
+		p.nextc()
+	}
+	left := rune(-1)
+	for {
+		switch c := p.c(); c {
+		case ']', endOfText:
+			if left >= 0 {
+				p.error(ErrBadRange)
+			}
+			// Is it [^\n]?
+			if cc.negate && len(cc.ranges) == 2 &&
+				cc.ranges[0] == '\n' && cc.ranges[1] == '\n' {
+				nl := &instr{kind: iNotNL}
+				p.re.add(nl)
+				return nl
+			}
+			// Special common case: "[a]" -> "a"
+			if !cc.negate && len(cc.ranges) == 2 && cc.ranges[0] == cc.ranges[1] {
+				c := &instr{kind: iChar, char: cc.ranges[0]}
+				p.re.add(c)
+				return c
+			}
+			p.re.add(i)
+			return i
+		case '-': // do this before backslash processing
+			p.error(ErrBadRange)
+		default:
+			c = p.checkBackslash()
+			p.nextc()
+			switch {
+			case left < 0: // first of pair
+				if p.c() == '-' { // range
+					p.nextc()
+					left = c
+				} else { // single char
+					cc.addRange(c, c)
+				}
+			case left <= c: // second of pair
+				cc.addRange(left, c)
+				left = -1
+			default:
+				p.error(ErrBadRange)
+			}
+		}
+	}
+	panic("unreachable")
+}
+
+func (p *parser) term() (start, end *instr) {
+	switch c := p.c(); c {
+	case '|', endOfText:
+		return nil, nil
+	case '*', '+', '?':
+		p.error(ErrBareClosure)
+	case ')':
+		if p.nlpar == 0 {
+			p.error(ErrUnmatchedRpar)
+		}
+		return nil, nil
+	case ']':
+		p.error(ErrUnmatchedRbkt)
+	case '^':
+		p.nextc()
+		start = p.re.add(&instr{kind: iBOT})
+		return start, start
+	case '$':
+		p.nextc()
+		start = p.re.add(&instr{kind: iEOT})
+		return start, start
+	case '.':
+		p.nextc()
+		start = p.re.add(&instr{kind: iAny})
+		return start, start
+	case '[':
+		p.nextc()
+		start = p.charClass()
+		if p.c() != ']' {
+			p.error(ErrUnmatchedLbkt)
+		}
+		p.nextc()
+		return start, start
+	case '(':
+		p.nextc()
+		p.nlpar++
+		p.re.nbra++ // increment first so first subexpr is \1
+		nbra := p.re.nbra
+		start, end = p.regexp()
+		if p.c() != ')' {
+			p.error(ErrUnmatchedLpar)
+		}
+		p.nlpar--
+		p.nextc()
+		bra := &instr{kind: iBra, braNum: 2 * nbra}
+		p.re.add(bra)
+		ebra := &instr{kind: iBra, braNum: 2*nbra + 1}
+		p.re.add(ebra)
+		if start == nil {
+			if end == nil {
+				p.error(ErrInternal)
+				return
+			}
+			start = ebra
+		} else {
+			end.next = ebra
+		}
+		bra.next = start
+		return bra, ebra
+	default:
+		c = p.checkBackslash()
+		p.nextc()
+		start = &instr{kind: iChar, char: c}
+		p.re.add(start)
+		return start, start
+	}
+	panic("unreachable")
+}
+
+func (p *parser) closure() (start, end *instr) {
+	start, end = p.term()
+	if start == nil {
+		return
+	}
+	switch p.c() {
+	case '*':
+		// (start,end)*:
+		alt := &instr{kind: iAlt}
+		p.re.add(alt)
+		end.next = alt   // after end, do alt
+		alt.left = start // alternate brach: return to start
+		start = alt      // alt becomes new (start, end)
+		end = alt
+	case '+':
+		// (start,end)+:
+		alt := &instr{kind: iAlt}
+		p.re.add(alt)
+		end.next = alt   // after end, do alt
+		alt.left = start // alternate brach: return to start
+		end = alt        // start is unchanged; end is alt
+	case '?':
+		// (start,end)?:
+		alt := &instr{kind: iAlt}
+		p.re.add(alt)
+		nop := &instr{kind: iNop}
+		p.re.add(nop)
+		alt.left = start // alternate branch is start
+		alt.next = nop   // follow on to nop
+		end.next = nop   // after end, go to nop
+		start = alt      // start is now alt
+		end = nop        // end is nop pointed to by both branches
+	default:
+		return
+	}
+	switch p.nextc() {
+	case '*', '+', '?':
+		p.error(ErrBadClosure)
+	}
+	return
+}
+
+func (p *parser) concatenation() (start, end *instr) {
+	for {
+		nstart, nend := p.closure()
+		switch {
+		case nstart == nil: // end of this concatenation
+			if start == nil { // this is the empty string
+				nop := p.re.add(&instr{kind: iNop})
+				return nop, nop
+			}
+			return
+		case start == nil: // this is first element of concatenation
+			start, end = nstart, nend
+		default:
+			end.next = nstart
+			end = nend
+		}
+	}
+	panic("unreachable")
+}
+
+func (p *parser) regexp() (start, end *instr) {
+	start, end = p.concatenation()
+	for {
+		switch p.c() {
+		default:
+			return
+		case '|':
+			p.nextc()
+			nstart, nend := p.concatenation()
+			alt := &instr{kind: iAlt}
+			p.re.add(alt)
+			alt.left = start
+			alt.next = nstart
+			nop := &instr{kind: iNop}
+			p.re.add(nop)
+			end.next = nop
+			nend.next = nop
+			start, end = alt, nop
+		}
+	}
+	panic("unreachable")
+}
+
+func unNop(i *instr) *instr {
+	for i.kind == iNop {
+		i = i.next
+	}
+	return i
+}
+
+func (re *Regexp) eliminateNops() {
+	for _, inst := range re.inst {
+		if inst.kind == iEnd {
+			continue
+		}
+		inst.next = unNop(inst.next)
+		if inst.kind == iAlt {
+			inst.left = unNop(inst.left)
+		}
+	}
+}
+
+func (re *Regexp) dump() {
+	print("prefix <", re.prefix, ">\n")
+	for _, inst := range re.inst {
+		print(inst.index, ": ")
+		inst.print()
+		if inst.kind != iEnd {
+			print(" -> ", inst.next.index)
+		}
+		print("\n")
+	}
+}
+
+func (re *Regexp) doParse() {
+	p := newParser(re)
+	start := &instr{kind: iStart}
+	re.add(start)
+	s, e := p.regexp()
+	start.next = s
+	re.start = start
+	e.next = re.add(&instr{kind: iEnd})
+
+	if debug {
+		re.dump()
+		println()
+	}
+
+	re.eliminateNops()
+	if debug {
+		re.dump()
+		println()
+	}
+	re.setPrefix()
+	if debug {
+		re.dump()
+		println()
+	}
+}
+
+// Extract regular text from the beginning of the pattern,
+// possibly after a leading iBOT.
+// That text can be used by doExecute to speed up matching.
+func (re *Regexp) setPrefix() {
+	var b []byte
+	var utf = make([]byte, utf8.UTFMax)
+	var inst *instr
+	// First instruction is start; skip that.  Also skip any initial iBOT.
+	inst = re.inst[0].next
+	for inst.kind == iBOT {
+		inst = inst.next
+	}
+Loop:
+	for ; inst.kind != iEnd; inst = inst.next {
+		// stop if this is not a char
+		if inst.kind != iChar {
+			break
+		}
+		// stop if this char can be followed by a match for an empty string,
+		// which includes closures, ^, and $.
+		switch inst.next.kind {
+		case iBOT, iEOT, iAlt:
+			break Loop
+		}
+		n := utf8.EncodeRune(utf, inst.char)
+		b = append(b, utf[0:n]...)
+	}
+	// point prefixStart instruction to first non-CHAR after prefix
+	re.prefixStart = inst
+	re.prefixBytes = b
+	re.prefix = string(b)
+}
+
+// String returns the source text used to compile the regular expression.
+func (re *Regexp) String() string {
+	return re.expr
+}
+
+// Compile parses a regular expression and returns, if successful, a Regexp
+// object that can be used to match against text.
+func Compile(str string) (regexp *Regexp, error error) {
+	regexp = new(Regexp)
+	// doParse will panic if there is a parse error.
+	defer func() {
+		if e := recover(); e != nil {
+			regexp = nil
+			error = e.(Error) // Will re-panic if error was not an Error, e.g. nil-pointer exception
+		}
+	}()
+	regexp.expr = str
+	regexp.inst = make([]*instr, 0, 10)
+	regexp.doParse()
+	return
+}
+
+// MustCompile is like Compile but panics if the expression cannot be parsed.
+// It simplifies safe initialization of global variables holding compiled regular
+// expressions.
+func MustCompile(str string) *Regexp {
+	regexp, error := Compile(str)
+	if error != nil {
+		panic(`regexp: compiling "` + str + `": ` + error.Error())
+	}
+	return regexp
+}
+
+// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
+func (re *Regexp) NumSubexp() int { return re.nbra }
+
+// The match arena allows us to reduce the garbage generated by tossing
+// match vectors away as we execute.  Matches are ref counted and returned
+// to a free list when no longer active.  Increases a simple benchmark by 22X.
+type matchArena struct {
+	head  *matchVec
+	len   int // length of match vector
+	pos   int
+	atBOT bool // whether we're at beginning of text
+	atEOT bool // whether we're at end of text
+}
+
+type matchVec struct {
+	m    []int // pairs of bracketing submatches. 0th is start,end
+	ref  int
+	next *matchVec
+}
+
+func (a *matchArena) new() *matchVec {
+	if a.head == nil {
+		const N = 10
+		block := make([]matchVec, N)
+		for i := 0; i < N; i++ {
+			b := &block[i]
+			b.next = a.head
+			a.head = b
+		}
+	}
+	m := a.head
+	a.head = m.next
+	m.ref = 0
+	if m.m == nil {
+		m.m = make([]int, a.len)
+	}
+	return m
+}
+
+func (a *matchArena) free(m *matchVec) {
+	m.ref--
+	if m.ref == 0 {
+		m.next = a.head
+		a.head = m
+	}
+}
+
+func (a *matchArena) copy(m *matchVec) *matchVec {
+	m1 := a.new()
+	copy(m1.m, m.m)
+	return m1
+}
+
+func (a *matchArena) noMatch() *matchVec {
+	m := a.new()
+	for i := range m.m {
+		m.m[i] = -1 // no match seen; catches cases like "a(b)?c" on "ac"
+	}
+	m.ref = 1
+	return m
+}
+
+type state struct {
+	inst     *instr // next instruction to execute
+	prefixed bool   // this match began with a fixed prefix
+	match    *matchVec
+}
+
+// Append new state to to-do list.  Leftmost-longest wins so avoid
+// adding a state that's already active.  The matchVec will be inc-ref'ed
+// if it is assigned to a state.
+func (a *matchArena) addState(s []state, inst *instr, prefixed bool, match *matchVec) []state {
+	switch inst.kind {
+	case iBOT:
+		if a.atBOT {
+			s = a.addState(s, inst.next, prefixed, match)
+		}
+		return s
+	case iEOT:
+		if a.atEOT {
+			s = a.addState(s, inst.next, prefixed, match)
+		}
+		return s
+	case iBra:
+		match.m[inst.braNum] = a.pos
+		s = a.addState(s, inst.next, prefixed, match)
+		return s
+	}
+	l := len(s)
+	// States are inserted in order so it's sufficient to see if we have the same
+	// instruction; no need to see if existing match is earlier (it is).
+	for i := 0; i < l; i++ {
+		if s[i].inst == inst {
+			return s
+		}
+	}
+	s = append(s, state{inst, prefixed, match})
+	match.ref++
+	if inst.kind == iAlt {
+		s = a.addState(s, inst.left, prefixed, a.copy(match))
+		// give other branch a copy of this match vector
+		s = a.addState(s, inst.next, prefixed, a.copy(match))
+	}
+	return s
+}
+
+// input abstracts different representations of the input text. It provides
+// one-character lookahead.
+type input interface {
+	step(pos int) (r rune, width int) // advance one rune
+	canCheckPrefix() bool             // can we look ahead without losing info?
+	hasPrefix(re *Regexp) bool
+	index(re *Regexp, pos int) int
+}
+
+// inputString scans a string.
+type inputString struct {
+	str string
+}
+
+func newInputString(str string) *inputString {
+	return &inputString{str: str}
+}
+
+func (i *inputString) step(pos int) (rune, int) {
+	if pos < len(i.str) {
+		return utf8.DecodeRuneInString(i.str[pos:len(i.str)])
+	}
+	return endOfText, 0
+}
+
+func (i *inputString) canCheckPrefix() bool {
+	return true
+}
+
+func (i *inputString) hasPrefix(re *Regexp) bool {
+	return strings.HasPrefix(i.str, re.prefix)
+}
+
+func (i *inputString) index(re *Regexp, pos int) int {
+	return strings.Index(i.str[pos:], re.prefix)
+}
+
+// inputBytes scans a byte slice.
+type inputBytes struct {
+	str []byte
+}
+
+func newInputBytes(str []byte) *inputBytes {
+	return &inputBytes{str: str}
+}
+
+func (i *inputBytes) step(pos int) (rune, int) {
+	if pos < len(i.str) {
+		return utf8.DecodeRune(i.str[pos:len(i.str)])
+	}
+	return endOfText, 0
+}
+
+func (i *inputBytes) canCheckPrefix() bool {
+	return true
+}
+
+func (i *inputBytes) hasPrefix(re *Regexp) bool {
+	return bytes.HasPrefix(i.str, re.prefixBytes)
+}
+
+func (i *inputBytes) index(re *Regexp, pos int) int {
+	return bytes.Index(i.str[pos:], re.prefixBytes)
+}
+
+// inputReader scans a RuneReader.
+type inputReader struct {
+	r     io.RuneReader
+	atEOT bool
+	pos   int
+}
+
+func newInputReader(r io.RuneReader) *inputReader {
+	return &inputReader{r: r}
+}
+
+func (i *inputReader) step(pos int) (rune, int) {
+	if !i.atEOT && pos != i.pos {
+		return endOfText, 0
+
+	}
+	r, w, err := i.r.ReadRune()
+	if err != nil {
+		i.atEOT = true
+		return endOfText, 0
+	}
+	i.pos += w
+	return r, w
+}
+
+func (i *inputReader) canCheckPrefix() bool {
+	return false
+}
+
+func (i *inputReader) hasPrefix(re *Regexp) bool {
+	return false
+}
+
+func (i *inputReader) index(re *Regexp, pos int) int {
+	return -1
+}
+
+// Search match starting from pos bytes into the input.
+func (re *Regexp) doExecute(i input, pos int) []int {
+	var s [2][]state
+	s[0] = make([]state, 0, 10)
+	s[1] = make([]state, 0, 10)
+	in, out := 0, 1
+	var final state
+	found := false
+	anchored := re.inst[0].next.kind == iBOT
+	if anchored && pos > 0 {
+		return nil
+	}
+	// fast check for initial plain substring
+	if i.canCheckPrefix() && re.prefix != "" {
+		advance := 0
+		if anchored {
+			if !i.hasPrefix(re) {
+				return nil
+			}
+		} else {
+			advance = i.index(re, pos)
+			if advance == -1 {
+				return nil
+			}
+		}
+		pos += advance
+	}
+	// We look one character ahead so we can match $, which checks whether
+	// we are at EOT.
+	nextChar, nextWidth := i.step(pos)
+	arena := &matchArena{
+		len:   2 * (re.nbra + 1),
+		pos:   pos,
+		atBOT: pos == 0,
+		atEOT: nextChar == endOfText,
+	}
+	for c, startPos := rune(0), pos; c != endOfText; {
+		if !found && (pos == startPos || !anchored) {
+			// prime the pump if we haven't seen a match yet
+			match := arena.noMatch()
+			match.m[0] = pos
+			s[out] = arena.addState(s[out], re.start.next, false, match)
+			arena.free(match) // if addState saved it, ref was incremented
+		} else if len(s[out]) == 0 {
+			// machine has completed
+			break
+		}
+		in, out = out, in // old out state is new in state
+		// clear out old state
+		old := s[out]
+		for _, state := range old {
+			arena.free(state.match)
+		}
+		s[out] = old[0:0] // truncate state vector
+		c = nextChar
+		thisPos := pos
+		pos += nextWidth
+		nextChar, nextWidth = i.step(pos)
+		arena.atEOT = nextChar == endOfText
+		arena.atBOT = false
+		arena.pos = pos
+		for _, st := range s[in] {
+			switch st.inst.kind {
+			case iBOT:
+			case iEOT:
+			case iChar:
+				if c == st.inst.char {
+					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+				}
+			case iCharClass:
+				if st.inst.cclass.matches(c) {
+					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+				}
+			case iAny:
+				if c != endOfText {
+					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+				}
+			case iNotNL:
+				if c != endOfText && c != '\n' {
+					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+				}
+			case iBra:
+			case iAlt:
+			case iEnd:
+				// choose leftmost longest
+				if !found || // first
+					st.match.m[0] < final.match.m[0] || // leftmost
+					(st.match.m[0] == final.match.m[0] && thisPos > final.match.m[1]) { // longest
+					if final.match != nil {
+						arena.free(final.match)
+					}
+					final = st
+					final.match.ref++
+					final.match.m[1] = thisPos
+				}
+				found = true
+			default:
+				st.inst.print()
+				panic("unknown instruction in execute")
+			}
+		}
+	}
+	if final.match == nil {
+		return nil
+	}
+	// if match found, back up start of match by width of prefix.
+	if final.prefixed && len(final.match.m) > 0 {
+		final.match.m[0] -= len(re.prefix)
+	}
+	return final.match.m
+}
+
+// LiteralPrefix returns a literal string that must begin any match
+// of the regular expression re.  It returns the boolean true if the
+// literal string comprises the entire regular expression.
+func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
+	c := make([]rune, len(re.inst)-2) // minus start and end.
+	// First instruction is start; skip that.
+	i := 0
+	for inst := re.inst[0].next; inst.kind != iEnd; inst = inst.next {
+		// stop if this is not a char
+		if inst.kind != iChar {
+			return string(c[:i]), false
+		}
+		c[i] = inst.char
+		i++
+	}
+	return string(c[:i]), true
+}
+
+// MatchReader returns whether the Regexp matches the text read by the
+// RuneReader.  The return value is a boolean: true for match, false for no
+// match.
+func (re *Regexp) MatchReader(r io.RuneReader) bool {
+	return len(re.doExecute(newInputReader(r), 0)) > 0
+}
+
+// MatchString returns whether the Regexp matches the string s.
+// The return value is a boolean: true for match, false for no match.
+func (re *Regexp) MatchString(s string) bool { return len(re.doExecute(newInputString(s), 0)) > 0 }
+
+// Match returns whether the Regexp matches the byte slice b.
+// The return value is a boolean: true for match, false for no match.
+func (re *Regexp) Match(b []byte) bool { return len(re.doExecute(newInputBytes(b), 0)) > 0 }
+
+// MatchReader checks whether a textual regular expression matches the text
+// read by the RuneReader.  More complicated queries need to use Compile and
+// the full Regexp interface.
+func MatchReader(pattern string, r io.RuneReader) (matched bool, error error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.MatchReader(r), nil
+}
+
+// MatchString checks whether a textual regular expression
+// matches a string.  More complicated queries need
+// to use Compile and the full Regexp interface.
+func MatchString(pattern string, s string) (matched bool, error error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.MatchString(s), nil
+}
+
+// Match checks whether a textual regular expression
+// matches a byte slice.  More complicated queries need
+// to use Compile and the full Regexp interface.
+func Match(pattern string, b []byte) (matched bool, error error) {
+	re, err := Compile(pattern)
+	if err != nil {
+		return false, err
+	}
+	return re.Match(b), nil
+}
+
+// ReplaceAllString returns a copy of src in which all matches for the Regexp
+// have been replaced by repl.  No support is provided for expressions
+// (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllString(src, repl string) string {
+	return re.ReplaceAllStringFunc(src, func(string) string { return repl })
+}
+
+// ReplaceAllStringFunc returns a copy of src in which all matches for the
+// Regexp have been replaced by the return value of of function repl (whose
+// first argument is the matched string).  No support is provided for
+// expressions (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
+	lastMatchEnd := 0 // end position of the most recent match
+	searchPos := 0    // position where we next look for a match
+	buf := new(bytes.Buffer)
+	for searchPos <= len(src) {
+		a := re.doExecute(newInputString(src), searchPos)
+		if len(a) == 0 {
+			break // no more matches
+		}
+
+		// Copy the unmatched characters before this match.
+		io.WriteString(buf, src[lastMatchEnd:a[0]])
+
+		// Now insert a copy of the replacement string, but not for a
+		// match of the empty string immediately after another match.
+		// (Otherwise, we get double replacement for patterns that
+		// match both empty and nonempty strings.)
+		if a[1] > lastMatchEnd || a[0] == 0 {
+			io.WriteString(buf, repl(src[a[0]:a[1]]))
+		}
+		lastMatchEnd = a[1]
+
+		// Advance past this match; always advance at least one character.
+		_, width := utf8.DecodeRuneInString(src[searchPos:])
+		if searchPos+width > a[1] {
+			searchPos += width
+		} else if searchPos+1 > a[1] {
+			// This clause is only needed at the end of the input
+			// string.  In that case, DecodeRuneInString returns width=0.
+			searchPos++
+		} else {
+			searchPos = a[1]
+		}
+	}
+
+	// Copy the unmatched characters after the last match.
+	io.WriteString(buf, src[lastMatchEnd:])
+
+	return buf.String()
+}
+
+// ReplaceAll returns a copy of src in which all matches for the Regexp
+// have been replaced by repl.  No support is provided for expressions
+// (e.g. \1 or $1) in the replacement text.
+func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
+	return re.ReplaceAllFunc(src, func([]byte) []byte { return repl })
+}
+
+// ReplaceAllFunc returns a copy of src in which all matches for the
+// Regexp have been replaced by the return value of of function repl (whose
+// first argument is the matched []byte).  No support is provided for
+// expressions (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
+	lastMatchEnd := 0 // end position of the most recent match
+	searchPos := 0    // position where we next look for a match
+	buf := new(bytes.Buffer)
+	for searchPos <= len(src) {
+		a := re.doExecute(newInputBytes(src), searchPos)
+		if len(a) == 0 {
+			break // no more matches
+		}
+
+		// Copy the unmatched characters before this match.
+		buf.Write(src[lastMatchEnd:a[0]])
+
+		// Now insert a copy of the replacement string, but not for a
+		// match of the empty string immediately after another match.
+		// (Otherwise, we get double replacement for patterns that
+		// match both empty and nonempty strings.)
+		if a[1] > lastMatchEnd || a[0] == 0 {
+			buf.Write(repl(src[a[0]:a[1]]))
+		}
+		lastMatchEnd = a[1]
+
+		// Advance past this match; always advance at least one character.
+		_, width := utf8.DecodeRune(src[searchPos:])
+		if searchPos+width > a[1] {
+			searchPos += width
+		} else if searchPos+1 > a[1] {
+			// This clause is only needed at the end of the input
+			// string.  In that case, DecodeRuneInString returns width=0.
+			searchPos++
+		} else {
+			searchPos = a[1]
+		}
+	}
+
+	// Copy the unmatched characters after the last match.
+	buf.Write(src[lastMatchEnd:])
+
+	return buf.Bytes()
+}
+
+// QuoteMeta returns a string that quotes all regular expression metacharacters
+// inside the argument text; the returned string is a regular expression matching
+// the literal text.  For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
+func QuoteMeta(s string) string {
+	b := make([]byte, 2*len(s))
+
+	// A byte loop is correct because all metacharacters are ASCII.
+	j := 0
+	for i := 0; i < len(s); i++ {
+		if special(rune(s[i])) {
+			b[j] = '\\'
+			j++
+		}
+		b[j] = s[i]
+		j++
+	}
+	return string(b[0:j])
+}
+
+// Find matches in slice b if b is non-nil, otherwise find matches in string s.
+func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
+	var end int
+	if b == nil {
+		end = len(s)
+	} else {
+		end = len(b)
+	}
+
+	for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
+		var in input
+		if b == nil {
+			in = newInputString(s)
+		} else {
+			in = newInputBytes(b)
+		}
+		matches := re.doExecute(in, pos)
+		if len(matches) == 0 {
+			break
+		}
+
+		accept := true
+		if matches[1] == pos {
+			// We've found an empty match.
+			if matches[0] == prevMatchEnd {
+				// We don't allow an empty match right
+				// after a previous match, so ignore it.
+				accept = false
+			}
+			var width int
+			// TODO: use step()
+			if b == nil {
+				_, width = utf8.DecodeRuneInString(s[pos:end])
+			} else {
+				_, width = utf8.DecodeRune(b[pos:end])
+			}
+			if width > 0 {
+				pos += width
+			} else {
+				pos = end + 1
+			}
+		} else {
+			pos = matches[1]
+		}
+		prevMatchEnd = matches[1]
+
+		if accept {
+			deliver(matches)
+			i++
+		}
+	}
+}
+
+// Find returns a slice holding the text of the leftmost match in b of the regular expression.
+// A return value of nil indicates no match.
+func (re *Regexp) Find(b []byte) []byte {
+	a := re.doExecute(newInputBytes(b), 0)
+	if a == nil {
+		return nil
+	}
+	return b[a[0]:a[1]]
+}
+
+// FindIndex returns a two-element slice of integers defining the location of
+// the leftmost match in b of the regular expression.  The match itself is at
+// b[loc[0]:loc[1]].
+// A return value of nil indicates no match.
+func (re *Regexp) FindIndex(b []byte) (loc []int) {
+	a := re.doExecute(newInputBytes(b), 0)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindString returns a string holding the text of the leftmost match in s of the regular
+// expression.  If there is no match, the return value is an empty string,
+// but it will also be empty if the regular expression successfully matches
+// an empty string.  Use FindStringIndex or FindStringSubmatch if it is
+// necessary to distinguish these cases.
+func (re *Regexp) FindString(s string) string {
+	a := re.doExecute(newInputString(s), 0)
+	if a == nil {
+		return ""
+	}
+	return s[a[0]:a[1]]
+}
+
+// FindStringIndex returns a two-element slice of integers defining the
+// location of the leftmost match in s of the regular expression.  The match
+// itself is at s[loc[0]:loc[1]].
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringIndex(s string) []int {
+	a := re.doExecute(newInputString(s), 0)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindReaderIndex returns a two-element slice of integers defining the
+// location of the leftmost match of the regular expression in text read from
+// the RuneReader.  The match itself is at s[loc[0]:loc[1]].  A return
+// value of nil indicates no match.
+func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
+	a := re.doExecute(newInputReader(r), 0)
+	if a == nil {
+		return nil
+	}
+	return a[0:2]
+}
+
+// FindSubmatch returns a slice of slices holding the text of the leftmost
+// match of the regular expression in b and the matches, if any, of its
+// subexpressions, as defined by the 'Submatch' descriptions in the package
+// comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindSubmatch(b []byte) [][]byte {
+	a := re.doExecute(newInputBytes(b), 0)
+	if a == nil {
+		return nil
+	}
+	ret := make([][]byte, len(a)/2)
+	for i := range ret {
+		if a[2*i] >= 0 {
+			ret[i] = b[a[2*i]:a[2*i+1]]
+		}
+	}
+	return ret
+}
+
+// FindSubmatchIndex returns a slice holding the index pairs identifying the
+// leftmost match of the regular expression in b and the matches, if any, of
+// its subexpressions, as defined by the 'Submatch' and 'Index' descriptions
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindSubmatchIndex(b []byte) []int {
+	return re.doExecute(newInputBytes(b), 0)
+}
+
+// FindStringSubmatch returns a slice of strings holding the text of the
+// leftmost match of the regular expression in s and the matches, if any, of
+// its subexpressions, as defined by the 'Submatch' description in the
+// package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringSubmatch(s string) []string {
+	a := re.doExecute(newInputString(s), 0)
+	if a == nil {
+		return nil
+	}
+	ret := make([]string, len(a)/2)
+	for i := range ret {
+		if a[2*i] >= 0 {
+			ret[i] = s[a[2*i]:a[2*i+1]]
+		}
+	}
+	return ret
+}
+
+// FindStringSubmatchIndex returns a slice holding the index pairs
+// identifying the leftmost match of the regular expression in s and the
+// matches, if any, of its subexpressions, as defined by the 'Submatch' and
+// 'Index' descriptions in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringSubmatchIndex(s string) []int {
+	return re.doExecute(newInputString(s), 0)
+}
+
+// FindReaderSubmatchIndex returns a slice holding the index pairs
+// identifying the leftmost match of the regular expression of text read by
+// the RuneReader, and the matches, if any, of its subexpressions, as defined
+// by the 'Submatch' and 'Index' descriptions in the package comment.  A
+// return value of nil indicates no match.
+func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
+	return re.doExecute(newInputReader(r), 0)
+}
+
+const startSize = 10 // The size at which to start a slice in the 'All' routines.
+
+// FindAll is the 'All' version of Find; it returns a slice of all successive
+// matches of the expression, as defined by the 'All' description in the
+// package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAll(b []byte, n int) [][]byte {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]byte, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, b[match[0]:match[1]])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllIndex is the 'All' version of FindIndex; it returns a slice of all
+// successive matches of the expression, as defined by the 'All' description
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllIndex(b []byte, n int) [][]int {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, match[0:2])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllString is the 'All' version of FindString; it returns a slice of all
+// successive matches of the expression, as defined by the 'All' description
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllString(s string, n int) []string {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([]string, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, s[match[0]:match[1]])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringIndex is the 'All' version of FindStringIndex; it returns a
+// slice of all successive matches of the expression, as defined by the 'All'
+// description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringIndex(s string, n int) [][]int {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, match[0:2])
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice
+// of all successive matches of the expression, as defined by the 'All'
+// description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][][]byte, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		slice := make([][]byte, len(match)/2)
+		for j := range slice {
+			if match[2*j] >= 0 {
+				slice[j] = b[match[2*j]:match[2*j+1]]
+			}
+		}
+		result = append(result, slice)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns
+// a slice of all successive matches of the expression, as defined by the
+// 'All' description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int {
+	if n < 0 {
+		n = len(b) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches("", b, n, func(match []int) {
+		result = append(result, match)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it
+// returns a slice of all successive matches of the expression, as defined by
+// the 'All' description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]string, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		slice := make([]string, len(match)/2)
+		for j := range slice {
+			if match[2*j] >= 0 {
+				slice[j] = s[match[2*j]:match[2*j+1]]
+			}
+		}
+		result = append(result, slice)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
+
+// FindAllStringSubmatchIndex is the 'All' version of
+// FindStringSubmatchIndex; it returns a slice of all successive matches of
+// the expression, as defined by the 'All' description in the package
+// comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
+	if n < 0 {
+		n = len(s) + 1
+	}
+	result := make([][]int, 0, startSize)
+	re.allMatches(s, nil, n, func(match []int) {
+		result = append(result, match)
+	})
+	if len(result) == 0 {
+		return nil
+	}
+	return result
+}
diff --git a/src/pkg/old/template/parse.go b/src/pkg/old/template/parse.go
index dedf9ad..e1bfa47 100644
--- a/src/pkg/old/template/parse.go
+++ b/src/pkg/old/template/parse.go
@@ -10,12 +10,11 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
-	"os"
 	"reflect"
 	"strconv"
 	"strings"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 // Errors returned during parsing and execution.  Users may extract the information and reformat
@@ -25,11 +24,11 @@ type Error struct {
 	Msg  string
 }
 
-func (e *Error) String() string { return fmt.Sprintf("line %d: %s", e.Line, e.Msg) }
+func (e *Error) Error() string { return fmt.Sprintf("line %d: %s", e.Line, e.Msg) }
 
 // checkError is a deferred function to turn a panic with type *Error into a plain error return.
 // Other panics are unexpected and so are re-enabled.
-func checkError(error *os.Error) {
+func checkError(error *error) {
 	if v := recover(); v != nil {
 		if e, ok := v.(*Error); ok {
 			*error = e
@@ -146,8 +145,8 @@ func (t *Template) parseError(err string, args ...interface{}) {
 
 // Is this an exported - upper case - name?
 func isExported(name string) bool {
-	rune, _ := utf8.DecodeRuneInString(name)
-	return unicode.IsUpper(rune)
+	r, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(r)
 }
 
 // -- Lexical analysis
@@ -414,22 +413,22 @@ func (t *Template) newVariable(words []string) *variableElement {
 
 	// Build argument list, processing any literals
 	for i, word := range words {
-		var lerr os.Error
+		var lerr error
 		switch word[0] {
 		case '"', '`', '\'':
 			v, err := strconv.Unquote(word)
 			if err == nil && word[0] == '\'' {
-				args[i] = []int(v)[0]
+				args[i], _ = utf8.DecodeRuneInString(v)
 			} else {
 				args[i], lerr = v, err
 			}
 
 		case '.', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
-			v, err := strconv.Btoi64(word, 0)
+			v, err := strconv.ParseInt(word, 0, 64)
 			if err == nil {
 				args[i] = v
 			} else {
-				v, err := strconv.Atof64(word)
+				v, err := strconv.ParseFloat(word, 64)
 				args[i], lerr = v, err
 			}
 
@@ -650,7 +649,7 @@ func (t *Template) parse() {
 // Parse initializes a Template by parsing its definition.  The string
 // s contains the template text.  If any errors occur, Parse returns
 // the error.
-func (t *Template) Parse(s string) (err os.Error) {
+func (t *Template) Parse(s string) (err error) {
 	if t.elems == nil {
 		return &Error{1, "template not allocated with New"}
 	}
@@ -667,7 +666,7 @@ func (t *Template) Parse(s string) (err os.Error) {
 
 // ParseFile is like Parse but reads the template definition from the
 // named file.
-func (t *Template) ParseFile(filename string) (err os.Error) {
+func (t *Template) ParseFile(filename string) (err error) {
 	b, err := ioutil.ReadFile(filename)
 	if err != nil {
 		return err
@@ -677,7 +676,7 @@ func (t *Template) ParseFile(filename string) (err os.Error) {
 
 // Execute applies a parsed template to the specified data object,
 // generating output to wr.
-func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) {
+func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
 	// Extract the driver data.
 	val := reflect.ValueOf(data)
 	defer checkError(&err)
@@ -701,7 +700,7 @@ func (t *Template) SetDelims(left, right string) {
 // the formatter map fmap, which may be nil, defines auxiliary functions
 // for formatting variables.  The template is returned. If any errors
 // occur, err will be non-nil.
-func Parse(s string, fmap FormatterMap) (t *Template, err os.Error) {
+func Parse(s string, fmap FormatterMap) (t *Template, err error) {
 	t = New(fmap)
 	err = t.Parse(s)
 	if err != nil {
@@ -715,7 +714,7 @@ func Parse(s string, fmap FormatterMap) (t *Template, err os.Error) {
 // a file containing the template text, while the formatter map fmap, which
 // may be nil, defines auxiliary functions for formatting variables.
 // The template is returned. If any errors occur, err will be non-nil.
-func ParseFile(filename string, fmap FormatterMap) (t *Template, err os.Error) {
+func ParseFile(filename string, fmap FormatterMap) (t *Template, err error) {
 	b, err := ioutil.ReadFile(filename)
 	if err != nil {
 		return nil, err
@@ -727,7 +726,7 @@ func ParseFile(filename string, fmap FormatterMap) (t *Template, err os.Error) {
 func MustParse(s string, fmap FormatterMap) *Template {
 	t, err := Parse(s, fmap)
 	if err != nil {
-		panic("template.MustParse error: " + err.String())
+		panic("template.MustParse error: " + err.Error())
 	}
 	return t
 }
@@ -737,7 +736,7 @@ func MustParse(s string, fmap FormatterMap) *Template {
 func MustParseFile(filename string, fmap FormatterMap) *Template {
 	b, err := ioutil.ReadFile(filename)
 	if err != nil {
-		panic("template.MustParseFile error: " + err.String())
+		panic("template.MustParseFile error: " + err.Error())
 	}
 	return MustParse(string(b), fmap)
 }
diff --git a/src/pkg/old/template/template_test.go b/src/pkg/old/template/template_test.go
index eae8011..f42a61a 100644
--- a/src/pkg/old/template/template_test.go
+++ b/src/pkg/old/template/template_test.go
@@ -6,11 +6,10 @@ package template
 
 import (
 	"bytes"
-	"container/vector"
+	"encoding/json"
 	"fmt"
 	"io"
 	"io/ioutil"
-	"json"
 	"os"
 	"strings"
 	"testing"
@@ -42,7 +41,7 @@ type S struct {
 	Empty         []*T
 	Emptystring   string
 	Null          []*T
-	Vec           *vector.Vector
+	Vec           []interface{}
 	True          bool
 	False         bool
 	Mp            map[string]string
@@ -107,108 +106,108 @@ var formatters = FormatterMap{
 
 var tests = []*Test{
 	// Simple
-	&Test{"", "", ""},
-	&Test{"abc", "abc", ""},
-	&Test{"abc\ndef\n", "abc\ndef\n", ""},
-	&Test{" {.meta-left}   \n", "{", ""},
-	&Test{" {.meta-right}   \n", "}", ""},
-	&Test{" {.space}   \n", " ", ""},
-	&Test{" {.tab}   \n", "\t", ""},
-	&Test{"     {#comment}   \n", "", ""},
-	&Test{"\tSome Text\t\n", "\tSome Text\t\n", ""},
-	&Test{" {.meta-right} {.meta-right} {.meta-right} \n", " } } } \n", ""},
+	{"", "", ""},
+	{"abc", "abc", ""},
+	{"abc\ndef\n", "abc\ndef\n", ""},
+	{" {.meta-left}   \n", "{", ""},
+	{" {.meta-right}   \n", "}", ""},
+	{" {.space}   \n", " ", ""},
+	{" {.tab}   \n", "\t", ""},
+	{"     {#comment}   \n", "", ""},
+	{"\tSome Text\t\n", "\tSome Text\t\n", ""},
+	{" {.meta-right} {.meta-right} {.meta-right} \n", " } } } \n", ""},
 
 	// Variables at top level
-	&Test{
+	{
 		in: "{Header}={Integer}\n",
 
 		out: "Header=77\n",
 	},
 
-	&Test{
+	{
 		in: "Pointers: {*HeaderPtr}={*IntegerPtr}\n",
 
 		out: "Pointers: Header=77\n",
 	},
 
-	&Test{
+	{
 		in: "Stars but not pointers: {*Header}={*Integer}\n",
 
 		out: "Stars but not pointers: Header=77\n",
 	},
 
-	&Test{
+	{
 		in: "nil pointer: {*NilPtr}={*Integer}\n",
 
 		out: "nil pointer: <nil>=77\n",
 	},
 
-	&Test{
+	{
 		in: `{"Strings" ":"} {""} {"|"} {"\t\u0123 \x23\\"} {"\"}{\\"}`,
 
 		out: "Strings:  | \t\u0123 \x23\\ \"}{\\",
 	},
 
-	&Test{
+	{
 		in: "{`Raw strings` `:`} {``} {`|`} {`\\t\\u0123 \\x23\\`} {`}{\\`}",
 
 		out: "Raw strings:  | \\t\\u0123 \\x23\\ }{\\",
 	},
 
-	&Test{
+	{
 		in: "Characters: {'a'} {'\\u0123'} {' '} {'{'} {'|'} {'}'}",
 
 		out: "Characters: 97 291 32 123 124 125",
 	},
 
-	&Test{
+	{
 		in: "Integers: {1} {-2} {+42} {0777} {0x0a}",
 
 		out: "Integers: 1 -2 42 511 10",
 	},
 
-	&Test{
+	{
 		in: "Floats: {.5} {-.5} {1.1} {-2.2} {+42.1} {1e10} {1.2e-3} {1.2e3} {-1.2e3}",
 
 		out: "Floats: 0.5 -0.5 1.1 -2.2 42.1 1e+10 0.0012 1200 -1200",
 	},
 
 	// Method at top level
-	&Test{
+	{
 		in: "ptrmethod={PointerMethod}\n",
 
 		out: "ptrmethod=ptrmethod!\n",
 	},
 
-	&Test{
+	{
 		in: "valmethod={ValueMethod}\n",
 
 		out: "valmethod=valmethod!\n",
 	},
 
 	// Section
-	&Test{
+	{
 		in: "{.section Data }\n" +
 			"some text for the section\n" +
 			"{.end}\n",
 
 		out: "some text for the section\n",
 	},
-	&Test{
+	{
 		in: "{.section Data }\n" +
 			"{Header}={Integer}\n" +
 			"{.end}\n",
 
 		out: "Header=77\n",
 	},
-	&Test{
+	{
 		in: "{.section Pdata }\n" +
 			"{Header}={Integer}\n" +
 			"{.end}\n",
 
 		out: "Header=77\n",
 	},
-	&Test{
+	{
 		in: "{.section Pdata }\n" +
 			"data present\n" +
 			"{.or}\n" +
@@ -217,7 +216,7 @@ var tests = []*Test{
 
 		out: "data present\n",
 	},
-	&Test{
+	{
 		in: "{.section Empty }\n" +
 			"data present\n" +
 			"{.or}\n" +
@@ -226,7 +225,7 @@ var tests = []*Test{
 
 		out: "data not present\n",
 	},
-	&Test{
+	{
 		in: "{.section Null }\n" +
 			"data present\n" +
 			"{.or}\n" +
@@ -235,7 +234,7 @@ var tests = []*Test{
 
 		out: "data not present\n",
 	},
-	&Test{
+	{
 		in: "{.section Pdata }\n" +
 			"{Header}={Integer}\n" +
 			"{.section @ }\n" +
@@ -247,20 +246,20 @@ var tests = []*Test{
 			"Header=77\n",
 	},
 
-	&Test{
+	{
 		in: "{.section Data}{.end} {Header}\n",
 
 		out: " Header\n",
 	},
 
-	&Test{
+	{
 		in: "{.section Integer}{@}{.end}",
 
 		out: "77",
 	},
 
 	// Repeated
-	&Test{
+	{
 		in: "{.section Pdata }\n" +
 			"{.repeated section @ }\n" +
 			"{Item}={Value}\n" +
@@ -270,7 +269,7 @@ var tests = []*Test{
 		out: "ItemNumber1=ValueNumber1\n" +
 			"ItemNumber2=ValueNumber2\n",
 	},
-	&Test{
+	{
 		in: "{.section Pdata }\n" +
 			"{.repeated section @ }\n" +
 			"{Item}={Value}\n" +
@@ -282,7 +281,7 @@ var tests = []*Test{
 		out: "ItemNumber1=ValueNumber1\n" +
 			"ItemNumber2=ValueNumber2\n",
 	},
-	&Test{
+	{
 		in: "{.section @ }\n" +
 			"{.repeated section Empty }\n" +
 			"{Item}={Value}\n" +
@@ -293,7 +292,7 @@ var tests = []*Test{
 
 		out: "this should appear: empty field\n",
 	},
-	&Test{
+	{
 		in: "{.repeated section Pdata }\n" +
 			"{Item}\n" +
 			"{.alternates with}\n" +
@@ -304,7 +303,7 @@ var tests = []*Test{
 			"is\nover\nmultiple\nlines\n" +
 			"ItemNumber2\n",
 	},
-	&Test{
+	{
 		in: "{.repeated section Pdata }\n" +
 			"{Item}\n" +
 			"{.alternates with}\n" +
@@ -315,7 +314,7 @@ var tests = []*Test{
 			"is\nover\nmultiple\nlines\n" +
 			"ItemNumber2\n",
 	},
-	&Test{
+	{
 		in: "{.section Pdata }\n" +
 			"{.repeated section @ }\n" +
 			"{Item}={Value}\n" +
@@ -329,7 +328,7 @@ var tests = []*Test{
 			"DIVIDER\n" +
 			"ItemNumber2=ValueNumber2\n",
 	},
-	&Test{
+	{
 		in: "{.repeated section Vec }\n" +
 			"{@}\n" +
 			"{.end}\n",
@@ -338,27 +337,27 @@ var tests = []*Test{
 			"elt2\n",
 	},
 	// Same but with a space before {.end}: was a bug.
-	&Test{
+	{
 		in: "{.repeated section Vec }\n" +
 			"{@} {.end}\n",
 
 		out: "elt1 elt2 \n",
 	},
-	&Test{
+	{
 		in: "{.repeated section Integer}{.end}",
 
 		err: "line 1: .repeated: cannot repeat Integer (type int)",
 	},
 
 	// Nested names
-	&Test{
+	{
 		in: "{.section @ }\n" +
 			"{InnerT.Item}={InnerT.Value}\n" +
 			"{.end}",
 
 		out: "ItemNumber1=ValueNumber1\n",
 	},
-	&Test{
+	{
 		in: "{.section @ }\n" +
 			"{InnerT.Item}={.section InnerT}{.section Value}{@}{.end}{.end}\n" +
 			"{.end}",
@@ -366,14 +365,14 @@ var tests = []*Test{
 		out: "ItemNumber1=ValueNumber1\n",
 	},
 
-	&Test{
+	{
 		in: "{.section Emptystring}emptystring{.end}\n" +
 			"{.section Header}header{.end}\n",
 
 		out: "\nheader\n",
 	},
 
-	&Test{
+	{
 		in: "{.section True}1{.or}2{.end}\n" +
 			"{.section False}3{.or}4{.end}\n",
 
@@ -382,32 +381,32 @@ var tests = []*Test{
 
 	// Maps
 
-	&Test{
+	{
 		in: "{Mp.mapkey}\n",
 
 		out: "Ahoy!\n",
 	},
-	&Test{
+	{
 		in: "{Innermap.Mp.innerkey}\n",
 
 		out: "55\n",
 	},
-	&Test{
+	{
 		in: "{.section Innermap}{.section Mp}{innerkey}{.end}{.end}\n",
 
 		out: "55\n",
 	},
-	&Test{
+	{
 		in: "{.section JSON}{.repeated section maps}{a}{b}{.end}{.end}\n",
 
 		out: "1234\n",
 	},
-	&Test{
+	{
 		in: "{Stringmap.stringkey1}\n",
 
 		out: "stringresult\n",
 	},
-	&Test{
+	{
 		in: "{.repeated section Stringmap}\n" +
 			"{@}\n" +
 			"{.end}",
@@ -415,7 +414,7 @@ var tests = []*Test{
 		out: "stringresult\n" +
 			"stringresult\n",
 	},
-	&Test{
+	{
 		in: "{.repeated section Stringmap}\n" +
 			"\t{@}\n" +
 			"{.end}",
@@ -423,12 +422,12 @@ var tests = []*Test{
 		out: "\tstringresult\n" +
 			"\tstringresult\n",
 	},
-	&Test{
+	{
 		in: "{*Ptrmap.stringkey1}\n",
 
 		out: "pointedToString\n",
 	},
-	&Test{
+	{
 		in: "{.repeated section Ptrmap}\n" +
 			"{*@}\n" +
 			"{.end}",
@@ -439,22 +438,22 @@ var tests = []*Test{
 
 	// Interface values
 
-	&Test{
+	{
 		in: "{Iface}",
 
 		out: "[1 2 3]",
 	},
-	&Test{
+	{
 		in: "{.repeated section Iface}{@}{.alternates with} {.end}",
 
 		out: "1 2 3",
 	},
-	&Test{
+	{
 		in: "{.section Iface}{@}{.end}",
 
 		out: "[1 2 3]",
 	},
-	&Test{
+	{
 		in: "{.section Ifaceptr}{Item} {Value}{.end}",
 
 		out: "Item Value",
@@ -463,29 +462,38 @@ var tests = []*Test{
 
 func TestAll(t *testing.T) {
 	// Parse
-	testAll(t, func(test *Test) (*Template, os.Error) { return Parse(test.in, formatters) })
+	testAll(t, func(test *Test) (*Template, error) { return Parse(test.in, formatters) })
 	// ParseFile
-	testAll(t, func(test *Test) (*Template, os.Error) {
-		err := ioutil.WriteFile("_test/test.tmpl", []byte(test.in), 0600)
+	f, err := ioutil.TempFile("", "template-test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		name := f.Name()
+		f.Close()
+		os.Remove(name)
+	}()
+	testAll(t, func(test *Test) (*Template, error) {
+		err := ioutil.WriteFile(f.Name(), []byte(test.in), 0600)
 		if err != nil {
 			t.Error("unexpected write error:", err)
 			return nil, err
 		}
-		return ParseFile("_test/test.tmpl", formatters)
+		return ParseFile(f.Name(), formatters)
 	})
 	// tmpl.ParseFile
-	testAll(t, func(test *Test) (*Template, os.Error) {
-		err := ioutil.WriteFile("_test/test.tmpl", []byte(test.in), 0600)
+	testAll(t, func(test *Test) (*Template, error) {
+		err := ioutil.WriteFile(f.Name(), []byte(test.in), 0600)
 		if err != nil {
 			t.Error("unexpected write error:", err)
 			return nil, err
 		}
 		tmpl := New(formatters)
-		return tmpl, tmpl.ParseFile("_test/test.tmpl")
+		return tmpl, tmpl.ParseFile(f.Name())
 	})
 }
 
-func testAll(t *testing.T, parseFunc func(*Test) (*Template, os.Error)) {
+func testAll(t *testing.T, parseFunc func(*Test) (*Template, error)) {
 	s := new(S)
 	// initialized by hand for clarity.
 	s.Header = "Header"
@@ -497,9 +505,7 @@ func testAll(t *testing.T, parseFunc func(*Test) (*Template, os.Error)) {
 	s.Pdata = []*T{&t1, &t2}
 	s.Empty = []*T{}
 	s.Null = nil
-	s.Vec = new(vector.Vector)
-	s.Vec.Push("elt1")
-	s.Vec.Push("elt2")
+	s.Vec = []interface{}{"elt1", "elt2"}
 	s.True = true
 	s.False = false
 	s.Mp = make(map[string]string)
@@ -533,8 +539,8 @@ func testAll(t *testing.T, parseFunc func(*Test) (*Template, os.Error)) {
 		} else {
 			if err == nil {
 				t.Errorf("expected execute error %q, got nil", test.err)
-			} else if err.String() != test.err {
-				t.Errorf("expected execute error %q, got %q", test.err, err.String())
+			} else if err.Error() != test.err {
+				t.Errorf("expected execute error %q, got %q", test.err, err.Error())
 			}
 		}
 		if buf.String() != test.out {
@@ -706,7 +712,7 @@ func TestReferenceToUnexported(t *testing.T) {
 	if err == nil {
 		t.Fatal("expected execute error, got none")
 	}
-	if strings.Index(err.String(), "not exported") < 0 {
+	if strings.Index(err.Error(), "not exported") < 0 {
 		t.Fatal("expected unexported error; got", err)
 	}
 }
@@ -780,8 +786,8 @@ func TestFormatters(t *testing.T) {
 				t.Error("unexpected parse error:", err)
 				continue
 			}
-			if strings.Index(err.String(), c.err) < 0 {
-				t.Errorf("unexpected error: expected %q, got %q", c.err, err.String())
+			if strings.Index(err.Error(), c.err) < 0 {
+				t.Errorf("unexpected error: expected %q, got %q", c.err, err.Error())
 				continue
 			}
 		} else {
diff --git a/src/pkg/os/Makefile b/src/pkg/os/Makefile
index 8923a8b..9f8d527 100644
--- a/src/pkg/os/Makefile
+++ b/src/pkg/os/Makefile
@@ -6,6 +6,7 @@ include ../../Make.inc
 
 TARG=os
 GOFILES=\
+	doc.go\
 	error.go\
 	env.go\
 	exec.go\
@@ -20,67 +21,72 @@ GOFILES=\
 GOFILES_freebsd=\
 	dir_unix.go\
 	error_posix.go\
-	env_unix.go\
 	file_posix.go\
 	file_unix.go\
 	path_unix.go\
 	sys_bsd.go\
 	exec_posix.go\
 	exec_unix.go\
-	signal_unix.go\
+	zsignal_$(GOOS)_$(GOARCH).go\
 
 GOFILES_darwin=\
 	dir_unix.go\
 	error_posix.go\
-	env_unix.go\
 	file_posix.go\
 	file_unix.go\
 	path_unix.go\
 	sys_bsd.go\
 	exec_posix.go\
 	exec_unix.go\
-	signal_unix.go\
+	zsignal_$(GOOS)_$(GOARCH).go\
 
 GOFILES_linux=\
 	dir_unix.go\
 	error_posix.go\
-	env_unix.go\
 	file_posix.go\
 	file_unix.go\
 	path_unix.go\
 	sys_linux.go\
 	exec_posix.go\
 	exec_unix.go\
-	signal_unix.go\
+	zsignal_$(GOOS)_$(GOARCH).go\
+
+GOFILES_netbsd=\
+	dir_unix.go\
+	error_posix.go\
+	file_posix.go\
+	file_unix.go\
+	path_unix.go\
+	sys_bsd.go\
+	exec_posix.go\
+	exec_unix.go\
+	zsignal_$(GOOS)_$(GOARCH).go\
 
 GOFILES_openbsd=\
 	dir_unix.go\
 	error_posix.go\
-	env_unix.go\
 	file_posix.go\
 	file_unix.go\
 	path_unix.go\
 	sys_bsd.go\
 	exec_posix.go\
 	exec_unix.go\
-	signal_unix.go\
+	zsignal_$(GOOS)_$(GOARCH).go\
 
 GOFILES_windows=\
 	dir_windows.go\
 	error_posix.go\
-	env_windows.go\
 	file_posix.go\
 	file_windows.go\
 	path_windows.go\
 	sys_windows.go\
 	exec_posix.go\
 	exec_windows.go\
-	signal_windows.go\
+	zsignal_$(GOOS)_$(GOARCH).go\
 
 GOFILES_plan9=\
 	dir_plan9.go\
 	error_plan9.go\
-	env_plan9.go\
 	file_plan9.go\
 	path_plan9.go\
 	sys_plan9.go\
@@ -89,12 +95,4 @@ GOFILES_plan9=\
 
 GOFILES+=$(GOFILES_$(GOOS))
 
-CLEANFILES+=signal_unix.go signal_windows.go
-
 include ../../Make.pkg
-
-signal_unix.go: ../syscall/zerrors_$(GOOS)_$(GOARCH).go
-	./mkunixsignals.sh $< > $@ || rm -f $@
-
-signal_windows.go: ../syscall/ztypes_$(GOOS).go
-	./mkunixsignals.sh $< > $@ || rm -f $@
diff --git a/src/pkg/os/dir_plan9.go b/src/pkg/os/dir_plan9.go
index bbc2cb6..f2dc154 100644
--- a/src/pkg/os/dir_plan9.go
+++ b/src/pkg/os/dir_plan9.go
@@ -5,25 +5,12 @@
 package os
 
 import (
+	"errors"
+	"io"
 	"syscall"
 )
 
-// Readdir reads the contents of the directory associated with file and
-// returns an array of up to n FileInfo structures, as would be returned
-// by Lstat, in directory order. Subsequent calls on the same file will yield
-// further FileInfos.
-//
-// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
-// Readdirnames returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is os.EOF.
-//
-// If n <= 0, Readdir returns all the FileInfo from the directory in
-// a single slice. In this case, if Readdir succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil os.Error. If it encounters an error before the end of the
-// directory, Readdir returns the FileInfo read until that point
-// and a non-nil error.
-func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
+func (file *File) readdir(n int) (fi []FileInfo, err error) {
 	// If this file has no dirinfo, create one.
 	if file.dirinfo == nil {
 		file.dirinfo = new(dirInfo)
@@ -39,12 +26,12 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
 		// Refill the buffer if necessary
 		if d.bufp >= d.nbuf {
 			d.bufp = 0
-			var e Error
+			var e error
 			d.nbuf, e = file.Read(d.buf[:])
-			if e != nil && e != EOF {
+			if e != nil && e != io.EOF {
 				return result, &PathError{"readdir", file.name, e}
 			}
-			if e == EOF {
+			if e == io.EOF {
 				break
 			}
 			if d.nbuf < syscall.STATFIXLEN {
@@ -62,37 +49,23 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
 		if e != nil {
 			return result, &PathError{"readdir", file.name, e}
 		}
-		var f FileInfo
-		fileInfoFromStat(&f, dir)
-		result = append(result, f)
+		result = append(result, fileInfoFromStat(dir))
 
 		d.bufp += int(m)
 		n--
 	}
 
 	if n >= 0 && len(result) == 0 {
-		return result, EOF
+		return result, io.EOF
 	}
 	return result, nil
 }
 
-// Readdirnames reads and returns a slice of names from the directory f.
-//
-// If n > 0, Readdirnames returns at most n names. In this case, if
-// Readdirnames returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is os.EOF.
-//
-// If n <= 0, Readdirnames returns all the names from the directory in
-// a single slice. In this case, if Readdirnames succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil os.Error. If it encounters an error before the end of the
-// directory, Readdirnames returns the names read until that point and
-// a non-nil error.
-func (file *File) Readdirnames(n int) (names []string, err Error) {
+func (file *File) readdirnames(n int) (names []string, err error) {
 	fi, err := file.Readdir(n)
 	names = make([]string, len(fi))
 	for i := range fi {
-		names[i] = fi[i].Name
+		names[i] = fi[i].Name()
 	}
 	return
 }
@@ -160,7 +133,7 @@ func pdir(b []byte, d *Dir) []byte {
 
 // UnmarshalDir reads a 9P Stat message from a 9P protocol message stored in b,
 // returning the corresponding Dir struct.
-func UnmarshalDir(b []byte) (d *Dir, err Error) {
+func UnmarshalDir(b []byte) (d *Dir, err error) {
 	n := uint16(0)
 	n, b = gbit16(b)
 
@@ -292,9 +265,9 @@ func pbit64(b []byte, x uint64) []byte {
 // pstring appends a Go string s to a 9P message b.
 func pstring(b []byte, s string) []byte {
 	if len(s) >= 1<<16 {
-		panic(NewError("string too long"))
+		panic(errors.New("string too long"))
 	}
 	b = pbit16(b, uint16(len(s)))
-	b = append(b, []byte(s)...)
+	b = append(b, s...)
 	return b
 }
diff --git a/src/pkg/os/dir_unix.go b/src/pkg/os/dir_unix.go
index 5295933..f41f939 100644
--- a/src/pkg/os/dir_unix.go
+++ b/src/pkg/os/dir_unix.go
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package os
 
 import (
+	"io"
 	"syscall"
 )
 
@@ -14,19 +15,7 @@ const (
 	blockSize = 4096
 )
 
-// Readdirnames reads and returns a slice of names from the directory f.
-//
-// If n > 0, Readdirnames returns at most n names. In this case, if
-// Readdirnames returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is os.EOF.
-//
-// If n <= 0, Readdirnames returns all the names from the directory in
-// a single slice. In this case, if Readdirnames succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil os.Error. If it encounters an error before the end of the
-// directory, Readdirnames returns the names read until that point and
-// a non-nil error.
-func (f *File) Readdirnames(n int) (names []string, err Error) {
+func (f *File) readdirnames(n int) (names []string, err error) {
 	// If this file has no dirinfo, create one.
 	if f.dirinfo == nil {
 		f.dirinfo = new(dirInfo)
@@ -46,9 +35,9 @@ func (f *File) Readdirnames(n int) (names []string, err Error) {
 		// Refill the buffer if necessary
 		if d.bufp >= d.nbuf {
 			d.bufp = 0
-			var errno int
+			var errno error
 			d.nbuf, errno = syscall.ReadDirent(f.fd, d.buf)
-			if errno != 0 {
+			if errno != nil {
 				return names, NewSyscallError("readdirent", errno)
 			}
 			if d.nbuf <= 0 {
@@ -63,7 +52,7 @@ func (f *File) Readdirnames(n int) (names []string, err Error) {
 		n -= nc
 	}
 	if n >= 0 && len(names) == 0 {
-		return names, EOF
+		return names, io.EOF
 	}
 	return names, nil
 }
diff --git a/src/pkg/os/dir_windows.go b/src/pkg/os/dir_windows.go
index d76e88f..9313160 100644
--- a/src/pkg/os/dir_windows.go
+++ b/src/pkg/os/dir_windows.go
@@ -4,11 +4,11 @@
 
 package os
 
-func (file *File) Readdirnames(n int) (names []string, err Error) {
+func (file *File) readdirnames(n int) (names []string, err error) {
 	fis, err := file.Readdir(n)
 	names = make([]string, len(fis))
 	for i, fi := range fis {
-		names[i] = fi.Name
+		names[i] = fi.Name()
 	}
 	return names, err
 }
diff --git a/src/pkg/os/doc.go b/src/pkg/os/doc.go
new file mode 100644
index 0000000..ef857c0
--- /dev/null
+++ b/src/pkg/os/doc.go
@@ -0,0 +1,52 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+// FindProcess looks for a running process by its pid.
+// The Process it returns can be used to obtain information
+// about the underlying operating system process.
+func FindProcess(pid int) (p *Process, err error) {
+	return findProcess(pid)
+}
+
+// Hostname returns the host name reported by the kernel.
+func Hostname() (name string, err error) {
+	return hostname()
+}
+
+// Readdir reads the contents of the directory associated with file and
+// returns an array of up to n FileInfo values, as would be returned
+// by Lstat, in directory order. Subsequent calls on the same file will yield
+// further FileInfos.
+//
+// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
+// Readdir returns an empty slice, it will return a non-nil error
+// explaining why. At the end of a directory, the error is io.EOF.
+//
+// If n <= 0, Readdir returns all the FileInfo from the directory in
+// a single slice. In this case, if Readdir succeeds (reads all
+// the way to the end of the directory), it returns the slice and a
+// nil error. If it encounters an error before the end of the
+// directory, Readdir returns the FileInfo read until that point
+// and a non-nil error.
+func (f *File) Readdir(n int) (fi []FileInfo, err error) {
+	return f.readdir(n)
+}
+
+// Readdirnames reads and returns a slice of names from the directory f.
+//
+// If n > 0, Readdirnames returns at most n names. In this case, if
+// Readdirnames returns an empty slice, it will return a non-nil error
+// explaining why. At the end of a directory, the error is io.EOF.
+//
+// If n <= 0, Readdirnames returns all the names from the directory in
+// a single slice. In this case, if Readdirnames succeeds (reads all
+// the way to the end of the directory), it returns the slice and a
+// nil error. If it encounters an error before the end of the
+// directory, Readdirnames returns the names read until that point and
+// a non-nil error.
+func (f *File) Readdirnames(n int) (names []string, err error) {
+	return f.readdirnames(n)
+}
diff --git a/src/pkg/os/env.go b/src/pkg/os/env.go
index 3772c09..7e3f525 100644
--- a/src/pkg/os/env.go
+++ b/src/pkg/os/env.go
@@ -6,7 +6,10 @@
 
 package os
 
-func setenv_c(k, v string)
+import (
+	"errors"
+	"syscall"
+)
 
 // Expand replaces ${var} or $var in the string based on the mapping function.
 // Invocations of undefined variables are replaced with the empty string.
@@ -16,9 +19,9 @@ func Expand(s string, mapping func(string) string) string {
 	i := 0
 	for j := 0; j < len(s); j++ {
 		if s[j] == '$' && j+1 < len(s) {
-			buf = append(buf, []byte(s[i:j])...)
+			buf = append(buf, s[i:j]...)
 			name, w := getShellName(s[j+1:])
-			buf = append(buf, []byte(mapping(name))...)
+			buf = append(buf, mapping(name)...)
 			j += w
 			i = j + 1
 		}
@@ -73,3 +76,47 @@ func getShellName(s string) (string, int) {
 	}
 	return s[:i], i
 }
+
+// ENOENV is the error indicating that an environment variable does not exist.
+var ENOENV = errors.New("no such environment variable")
+
+// Getenverror retrieves the value of the environment variable named by the key.
+// It returns the value and an error, if any.
+func Getenverror(key string) (value string, err error) {
+	if len(key) == 0 {
+		return "", EINVAL
+	}
+	val, found := syscall.Getenv(key)
+	if !found {
+		return "", ENOENV
+	}
+	return val, nil
+}
+
+// Getenv retrieves the value of the environment variable named by the key.
+// It returns the value, which will be empty if the variable is not present.
+func Getenv(key string) string {
+	v, _ := Getenverror(key)
+	return v
+}
+
+// Setenv sets the value of the environment variable named by the key.
+// It returns an error, if any.
+func Setenv(key, value string) error {
+	err := syscall.Setenv(key, value)
+	if err != nil {
+		return NewSyscallError("setenv", err)
+	}
+	return nil
+}
+
+// Clearenv deletes all environment variables.
+func Clearenv() {
+	syscall.Clearenv()
+}
+
+// Environ returns an array of strings representing the environment,
+// in the form "key=value".
+func Environ() []string {
+	return syscall.Environ()
+}
diff --git a/src/pkg/os/env_plan9.go b/src/pkg/os/env_plan9.go
deleted file mode 100644
index 1fed89f..0000000
--- a/src/pkg/os/env_plan9.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2011 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.
-
-// Plan 9 environment variables.
-
-package os
-
-import "syscall"
-
-// ENOENV is the Error indicating that an environment variable does not exist.
-var ENOENV = NewError("no such environment variable")
-
-// Getenverror retrieves the value of the environment variable named by the key.
-// It returns the value and an error, if any.
-func Getenverror(key string) (value string, err Error) {
-	if len(key) == 0 {
-		return "", EINVAL
-	}
-	f, e := Open("/env/" + key)
-	if iserror(e) {
-		return "", ENOENV
-	}
-	defer f.Close()
-
-	l, _ := f.Seek(0, 2)
-	f.Seek(0, 0)
-	buf := make([]byte, l)
-	n, e := f.Read(buf)
-	if iserror(e) {
-		return "", ENOENV
-	}
-
-	if n > 0 && buf[n-1] == 0 {
-		buf = buf[:n-1]
-	}
-	return string(buf), nil
-}
-
-// Getenv retrieves the value of the environment variable named by the key.
-// It returns the value, which will be empty if the variable is not present.
-func Getenv(key string) string {
-	v, _ := Getenverror(key)
-	return v
-}
-
-// Setenv sets the value of the environment variable named by the key.
-// It returns an Error, if any.
-func Setenv(key, value string) Error {
-	if len(key) == 0 {
-		return EINVAL
-	}
-
-	f, e := Create("/env/" + key)
-	if iserror(e) {
-		return e
-	}
-	defer f.Close()
-
-	_, e = f.Write([]byte(value))
-	return nil
-}
-
-// Clearenv deletes all environment variables.
-func Clearenv() {
-	syscall.RawSyscall(syscall.SYS_RFORK, syscall.RFCENVG, 0, 0)
-}
-
-// Environ returns an array of strings representing the environment,
-// in the form "key=value".
-func Environ() []string {
-	env := make([]string, 0, 100)
-
-	f, e := Open("/env")
-	if iserror(e) {
-		panic(e)
-	}
-	defer f.Close()
-
-	names, e := f.Readdirnames(-1)
-	if iserror(e) {
-		panic(e)
-	}
-
-	for _, k := range names {
-		if v, e := Getenverror(k); !iserror(e) {
-			env = append(env, k+"="+v)
-		}
-	}
-	return env[0:len(env)]
-}
-
-// TempDir returns the default directory to use for temporary files.
-func TempDir() string {
-	return "/tmp"
-}
diff --git a/src/pkg/os/env_test.go b/src/pkg/os/env_test.go
index 04ff390..991fa4d 100644
--- a/src/pkg/os/env_test.go
+++ b/src/pkg/os/env_test.go
@@ -6,6 +6,7 @@ package os_test
 
 import (
 	. "os"
+	"reflect"
 	"testing"
 )
 
@@ -57,3 +58,13 @@ func TestExpand(t *testing.T) {
 		}
 	}
 }
+
+func TestConsistentEnviron(t *testing.T) {
+	e0 := Environ()
+	for i := 0; i < 10; i++ {
+		e1 := Environ()
+		if !reflect.DeepEqual(e0, e1) {
+			t.Fatalf("environment changed")
+		}
+	}
+}
diff --git a/src/pkg/os/env_unix.go b/src/pkg/os/env_unix.go
deleted file mode 100644
index 8dd84ae..0000000
--- a/src/pkg/os/env_unix.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2010 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 darwin freebsd linux openbsd
-
-// Unix environment variables.
-
-package os
-
-import (
-	"sync"
-)
-
-// ENOENV is the Error indicating that an environment variable does not exist.
-var ENOENV = NewError("no such environment variable")
-
-var env map[string]string
-var once sync.Once
-
-func copyenv() {
-	env = make(map[string]string)
-	for _, s := range Envs {
-		for j := 0; j < len(s); j++ {
-			if s[j] == '=' {
-				env[s[0:j]] = s[j+1:]
-				break
-			}
-		}
-	}
-}
-
-var envLock sync.RWMutex
-
-// Getenverror retrieves the value of the environment variable named by the key.
-// It returns the value and an error, if any.
-func Getenverror(key string) (value string, err Error) {
-	once.Do(copyenv)
-
-	if len(key) == 0 {
-		return "", EINVAL
-	}
-
-	envLock.RLock()
-	defer envLock.RUnlock()
-
-	v, ok := env[key]
-	if !ok {
-		return "", ENOENV
-	}
-	return v, nil
-}
-
-// Getenv retrieves the value of the environment variable named by the key.
-// It returns the value, which will be empty if the variable is not present.
-func Getenv(key string) string {
-	v, _ := Getenverror(key)
-	return v
-}
-
-// Setenv sets the value of the environment variable named by the key.
-// It returns an Error, if any.
-func Setenv(key, value string) Error {
-	once.Do(copyenv)
-	if len(key) == 0 {
-		return EINVAL
-	}
-
-	envLock.Lock()
-	defer envLock.Unlock()
-
-	env[key] = value
-	setenv_c(key, value) // is a no-op if cgo isn't loaded
-	return nil
-}
-
-// Clearenv deletes all environment variables.
-func Clearenv() {
-	once.Do(copyenv) // prevent copyenv in Getenv/Setenv
-
-	envLock.Lock()
-	defer envLock.Unlock()
-
-	env = make(map[string]string)
-
-	// TODO(bradfitz): pass through to C
-}
-
-// Environ returns an array of strings representing the environment,
-// in the form "key=value".
-func Environ() []string {
-	once.Do(copyenv)
-	envLock.RLock()
-	defer envLock.RUnlock()
-	a := make([]string, len(env))
-	i := 0
-	for k, v := range env {
-		a[i] = k + "=" + v
-		i++
-	}
-	return a
-}
-
-// TempDir returns the default directory to use for temporary files.
-func TempDir() string {
-	dir := Getenv("TMPDIR")
-	if dir == "" {
-		dir = "/tmp"
-	}
-	return dir
-}
diff --git a/src/pkg/os/env_windows.go b/src/pkg/os/env_windows.go
deleted file mode 100644
index e6ddc40..0000000
--- a/src/pkg/os/env_windows.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2010 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.
-
-// Windows environment variables.
-
-package os
-
-import (
-	"syscall"
-	"utf16"
-	"unsafe"
-)
-
-// ENOENV is the Error indicating that an environment variable does not exist.
-var ENOENV = NewError("no such environment variable")
-
-// Getenverror retrieves the value of the environment variable named by the key.
-// It returns the value and an error, if any.
-func Getenverror(key string) (value string, err Error) {
-	b := make([]uint16, 100)
-	n, e := syscall.GetEnvironmentVariable(syscall.StringToUTF16Ptr(key), &b[0], uint32(len(b)))
-	if n == 0 && e == syscall.ERROR_ENVVAR_NOT_FOUND {
-		return "", ENOENV
-	}
-	if n > uint32(len(b)) {
-		b = make([]uint16, n)
-		n, e = syscall.GetEnvironmentVariable(syscall.StringToUTF16Ptr(key), &b[0], uint32(len(b)))
-		if n > uint32(len(b)) {
-			n = 0
-		}
-	}
-	if n == 0 {
-		return "", NewSyscallError("GetEnvironmentVariable", e)
-	}
-	return string(utf16.Decode(b[0:n])), nil
-}
-
-// Getenv retrieves the value of the environment variable named by the key.
-// It returns the value, which will be empty if the variable is not present.
-func Getenv(key string) string {
-	v, _ := Getenverror(key)
-	return v
-}
-
-// Setenv sets the value of the environment variable named by the key.
-// It returns an Error, if any.
-func Setenv(key, value string) Error {
-	var v *uint16
-	if len(value) > 0 {
-		v = syscall.StringToUTF16Ptr(value)
-	}
-	e := syscall.SetEnvironmentVariable(syscall.StringToUTF16Ptr(key), v)
-	if e != 0 {
-		return NewSyscallError("SetEnvironmentVariable", e)
-	}
-	return nil
-}
-
-// Clearenv deletes all environment variables.
-func Clearenv() {
-	for _, s := range Environ() {
-		// Environment variables can begin with =
-		// so start looking for the separator = at j=1.
-		// http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
-		for j := 1; j < len(s); j++ {
-			if s[j] == '=' {
-				Setenv(s[0:j], "")
-				break
-			}
-		}
-	}
-}
-
-// Environ returns an array of strings representing the environment,
-// in the form "key=value".
-func Environ() []string {
-	s, e := syscall.GetEnvironmentStrings()
-	if e != 0 {
-		return nil
-	}
-	defer syscall.FreeEnvironmentStrings(s)
-	r := make([]string, 0, 50) // Empty with room to grow.
-	for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(s)); true; i++ {
-		if p[i] == 0 {
-			// empty string marks the end
-			if i <= from {
-				break
-			}
-			r = append(r, string(utf16.Decode(p[from:i])))
-			from = i + 1
-		}
-	}
-	return r
-}
-
-// TempDir returns the default directory to use for temporary files.
-func TempDir() string {
-	const pathSep = '\\'
-	dirw := make([]uint16, syscall.MAX_PATH)
-	n, _ := syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
-	if n > uint32(len(dirw)) {
-		dirw = make([]uint16, n)
-		n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
-		if n > uint32(len(dirw)) {
-			n = 0
-		}
-	}
-	if n > 0 && dirw[n-1] == pathSep {
-		n--
-	}
-	return string(utf16.Decode(dirw[0:n]))
-}
-
-func init() {
-	var argc int32
-	cmd := syscall.GetCommandLine()
-	argv, e := syscall.CommandLineToArgv(cmd, &argc)
-	if e != 0 {
-		return
-	}
-	defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv))))
-	Args = make([]string, argc)
-	for i, v := range (*argv)[:argc] {
-		Args[i] = string(syscall.UTF16ToString((*v)[:]))
-	}
-}
diff --git a/src/pkg/os/error.go b/src/pkg/os/error.go
index b4511dd..c3dd06f 100644
--- a/src/pkg/os/error.go
+++ b/src/pkg/os/error.go
@@ -4,28 +4,11 @@
 
 package os
 
-// An Error can represent any printable error condition.
-type Error interface {
-	String() string
-}
-
-// // errorString is a helper type used by NewError.
-type errorString string
-
-func (e errorString) String() string { return string(e) }
-
-// Note: If the name of the function NewError changes,
-// pkg/go/doc/doc.go should be adjusted since it hardwires
-// this name in a heuristic.
-
-// // NewError returns a new error with error.String() == s.
-func NewError(s string) Error { return errorString(s) }
-
 // PathError records an error and the operation and file path that caused it.
 type PathError struct {
-	Op    string
-	Path  string
-	Error Error
+	Op   string
+	Path string
+	Err  error
 }
 
-func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
+func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
diff --git a/src/pkg/os/error_plan9.go b/src/pkg/os/error_plan9.go
index 91ace6d..3c727b2 100644
--- a/src/pkg/os/error_plan9.go
+++ b/src/pkg/os/error_plan9.go
@@ -4,7 +4,10 @@
 
 package os
 
-import syscall "syscall"
+import (
+	"errors"
+	"syscall"
+)
 
 // SyscallError records an error from a specific system call.
 type SyscallError struct {
@@ -12,32 +15,28 @@ type SyscallError struct {
 	Err     string
 }
 
-func (e *SyscallError) String() string { return e.Syscall + ": " + e.Err }
-
-// Note: If the name of the function NewSyscallError changes,
-// pkg/go/doc/doc.go should be adjusted since it hardwires
-// this name in a heuristic.
+func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err }
 
-// NewSyscallError returns, as an Error, a new SyscallError
+// NewSyscallError returns, as an error, a new SyscallError
 // with the given system call name and error details.
 // As a convenience, if err is nil, NewSyscallError returns nil.
-func NewSyscallError(syscall string, err syscall.Error) Error {
+func NewSyscallError(syscall string, err error) error {
 	if err == nil {
 		return nil
 	}
-	return &SyscallError{syscall, err.String()}
+	return &SyscallError{syscall, err.Error()}
 }
 
 var (
-	Eshortstat = NewError("stat buffer too small")
-	Ebadstat   = NewError("malformed stat buffer")
-	Ebadfd     = NewError("fd out of range or not open")
-	Ebadarg    = NewError("bad arg in system call")
-	Enotdir    = NewError("not a directory")
-	Enonexist  = NewError("file does not exist")
-	Eexist     = NewError("file already exists")
-	Eio        = NewError("i/o error")
-	Eperm      = NewError("permission denied")
+	Eshortstat = errors.New("stat buffer too small")
+	Ebadstat   = errors.New("malformed stat buffer")
+	Ebadfd     = errors.New("fd out of range or not open")
+	Ebadarg    = errors.New("bad arg in system call")
+	Enotdir    = errors.New("not a directory")
+	Enonexist  = errors.New("file does not exist")
+	Eexist     = errors.New("file already exists")
+	Eio        = errors.New("i/o error")
+	Eperm      = errors.New("permission denied")
 
 	EINVAL  = Ebadarg
 	ENOTDIR = Enotdir
@@ -48,15 +47,9 @@ var (
 	EPERM   = Eperm
 	EISDIR  = syscall.EISDIR
 
-	EBADF        = NewError("bad file descriptor")
-	ENAMETOOLONG = NewError("file name too long")
-	ERANGE       = NewError("math result not representable")
-	EPIPE        = NewError("Broken Pipe")
-	EPLAN9       = NewError("not supported by plan 9")
+	EBADF        = errors.New("bad file descriptor")
+	ENAMETOOLONG = errors.New("file name too long")
+	ERANGE       = errors.New("math result not representable")
+	EPIPE        = errors.New("Broken Pipe")
+	EPLAN9       = errors.New("not supported by plan 9")
 )
-
-func iserror(err syscall.Error) bool {
-	return err != nil
-}
-
-func Errno(e syscall.Error) syscall.Error { return e }
diff --git a/src/pkg/os/error_posix.go b/src/pkg/os/error_posix.go
index 9dc258a..1a08627 100644
--- a/src/pkg/os/error_posix.go
+++ b/src/pkg/os/error_posix.go
@@ -2,91 +2,69 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 package os
 
 import syscall "syscall"
 
-// Errno is the Unix error number.  Names such as EINVAL are simple
-// wrappers to convert the error number into an Error.
-type Errno int64
-
-func (e Errno) String() string { return syscall.Errstr(int(e)) }
-
-func (e Errno) Temporary() bool {
-	return e == Errno(syscall.EINTR) || e == Errno(syscall.EMFILE) || e.Timeout()
-}
-
-func (e Errno) Timeout() bool {
-	return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK) || e == Errno(syscall.ETIMEDOUT)
-}
-
 // Commonly known Unix errors.
 var (
-	EPERM        Error = Errno(syscall.EPERM)
-	ENOENT       Error = Errno(syscall.ENOENT)
-	ESRCH        Error = Errno(syscall.ESRCH)
-	EINTR        Error = Errno(syscall.EINTR)
-	EIO          Error = Errno(syscall.EIO)
-	ENXIO        Error = Errno(syscall.ENXIO)
-	E2BIG        Error = Errno(syscall.E2BIG)
-	ENOEXEC      Error = Errno(syscall.ENOEXEC)
-	EBADF        Error = Errno(syscall.EBADF)
-	ECHILD       Error = Errno(syscall.ECHILD)
-	EDEADLK      Error = Errno(syscall.EDEADLK)
-	ENOMEM       Error = Errno(syscall.ENOMEM)
-	EACCES       Error = Errno(syscall.EACCES)
-	EFAULT       Error = Errno(syscall.EFAULT)
-	EBUSY        Error = Errno(syscall.EBUSY)
-	EEXIST       Error = Errno(syscall.EEXIST)
-	EXDEV        Error = Errno(syscall.EXDEV)
-	ENODEV       Error = Errno(syscall.ENODEV)
-	ENOTDIR      Error = Errno(syscall.ENOTDIR)
-	EISDIR       Error = Errno(syscall.EISDIR)
-	EINVAL       Error = Errno(syscall.EINVAL)
-	ENFILE       Error = Errno(syscall.ENFILE)
-	EMFILE       Error = Errno(syscall.EMFILE)
-	ENOTTY       Error = Errno(syscall.ENOTTY)
-	EFBIG        Error = Errno(syscall.EFBIG)
-	ENOSPC       Error = Errno(syscall.ENOSPC)
-	ESPIPE       Error = Errno(syscall.ESPIPE)
-	EROFS        Error = Errno(syscall.EROFS)
-	EMLINK       Error = Errno(syscall.EMLINK)
-	EPIPE        Error = Errno(syscall.EPIPE)
-	EAGAIN       Error = Errno(syscall.EAGAIN)
-	EDOM         Error = Errno(syscall.EDOM)
-	ERANGE       Error = Errno(syscall.ERANGE)
-	EADDRINUSE   Error = Errno(syscall.EADDRINUSE)
-	ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
-	ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
-	EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
-	ETIMEDOUT    Error = Errno(syscall.ETIMEDOUT)
-	ENOTCONN     Error = Errno(syscall.ENOTCONN)
+	EPERM        error = syscall.EPERM
+	ENOENT       error = syscall.ENOENT
+	ESRCH        error = syscall.ESRCH
+	EINTR        error = syscall.EINTR
+	EIO          error = syscall.EIO
+	ENXIO        error = syscall.ENXIO
+	E2BIG        error = syscall.E2BIG
+	ENOEXEC      error = syscall.ENOEXEC
+	EBADF        error = syscall.EBADF
+	ECHILD       error = syscall.ECHILD
+	EDEADLK      error = syscall.EDEADLK
+	ENOMEM       error = syscall.ENOMEM
+	EACCES       error = syscall.EACCES
+	EFAULT       error = syscall.EFAULT
+	EBUSY        error = syscall.EBUSY
+	EEXIST       error = syscall.EEXIST
+	EXDEV        error = syscall.EXDEV
+	ENODEV       error = syscall.ENODEV
+	ENOTDIR      error = syscall.ENOTDIR
+	EISDIR       error = syscall.EISDIR
+	EINVAL       error = syscall.EINVAL
+	ENFILE       error = syscall.ENFILE
+	EMFILE       error = syscall.EMFILE
+	ENOTTY       error = syscall.ENOTTY
+	EFBIG        error = syscall.EFBIG
+	ENOSPC       error = syscall.ENOSPC
+	ESPIPE       error = syscall.ESPIPE
+	EROFS        error = syscall.EROFS
+	EMLINK       error = syscall.EMLINK
+	EPIPE        error = syscall.EPIPE
+	EAGAIN       error = syscall.EAGAIN
+	EDOM         error = syscall.EDOM
+	ERANGE       error = syscall.ERANGE
+	EADDRINUSE   error = syscall.EADDRINUSE
+	ECONNREFUSED error = syscall.ECONNREFUSED
+	ENAMETOOLONG error = syscall.ENAMETOOLONG
+	EAFNOSUPPORT error = syscall.EAFNOSUPPORT
+	ETIMEDOUT    error = syscall.ETIMEDOUT
+	ENOTCONN     error = syscall.ENOTCONN
 )
 
 // SyscallError records an error from a specific system call.
 type SyscallError struct {
 	Syscall string
-	Errno   Errno
+	Errno   error
 }
 
-func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
-
-// Note: If the name of the function NewSyscallError changes,
-// pkg/go/doc/doc.go should be adjusted since it hardwires
-// this name in a heuristic.
+func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Errno.Error() }
 
-// NewSyscallError returns, as an Error, a new SyscallError
+// NewSyscallError returns, as an error, a new SyscallError
 // with the given system call name and error details.
-// As a convenience, if errno is 0, NewSyscallError returns nil.
-func NewSyscallError(syscall string, errno int) Error {
-	if errno == 0 {
+// As a convenience, if err is nil, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err error) error {
+	if err == nil {
 		return nil
 	}
-	return &SyscallError{syscall, Errno(errno)}
-}
-
-func iserror(errno int) bool {
-	return errno != 0
+	return &SyscallError{syscall, err}
 }
diff --git a/src/pkg/os/exec/Makefile b/src/pkg/os/exec/Makefile
new file mode 100644
index 0000000..e67dfba
--- /dev/null
+++ b/src/pkg/os/exec/Makefile
@@ -0,0 +1,34 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=os/exec
+GOFILES=\
+	exec.go\
+
+GOFILES_freebsd=\
+	lp_unix.go\
+
+GOFILES_darwin=\
+	lp_unix.go\
+
+GOFILES_linux=\
+	lp_unix.go\
+
+GOFILES_netbsd=\
+	lp_unix.go\
+
+GOFILES_openbsd=\
+	lp_unix.go\
+
+GOFILES_windows=\
+	lp_windows.go\
+
+GOFILES_plan9=\
+	lp_plan9.go\
+
+GOFILES+=$(GOFILES_$(GOOS))
+
+include ../../../Make.pkg
diff --git a/src/pkg/os/exec/exec.go b/src/pkg/os/exec/exec.go
new file mode 100644
index 0000000..a00fdad
--- /dev/null
+++ b/src/pkg/os/exec/exec.go
@@ -0,0 +1,396 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package exec runs external commands. It wraps os.StartProcess to make it
+// easier to remap stdin and stdout, connect I/O with pipes, and do other
+// adjustments.
+package exec
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"os"
+	"strconv"
+	"syscall"
+)
+
+// Error records the name of a binary that failed to be be executed
+// and the reason it failed.
+type Error struct {
+	Name string
+	Err  error
+}
+
+func (e *Error) Error() string {
+	return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error()
+}
+
+// Cmd represents an external command being prepared or run.
+type Cmd struct {
+	// Path is the path of the command to run.
+	//
+	// This is the only field that must be set to a non-zero
+	// value.
+	Path string
+
+	// Args holds command line arguments, including the command as Args[0].
+	// If the Args field is empty or nil, Run uses {Path}.
+	// 
+	// In typical use, both Path and Args are set by calling Command.
+	Args []string
+
+	// Env specifies the environment of the process.
+	// If Env is nil, Run uses the current process's environment.
+	Env []string
+
+	// Dir specifies the working directory of the command.
+	// If Dir is the empty string, Run runs the command in the
+	// calling process's current directory.
+	Dir string
+
+	// Stdin specifies the process's standard input. If Stdin is
+	// nil, the process reads from the null device (os.DevNull).
+	Stdin io.Reader
+
+	// Stdout and Stderr specify the process's standard output and error.
+	//
+	// If either is nil, Run connects the corresponding file descriptor
+	// to the null device (os.DevNull).
+	//
+	// If Stdout and Stderr are are the same writer, at most one
+	// goroutine at a time will call Write.
+	Stdout io.Writer
+	Stderr io.Writer
+
+	// ExtraFiles specifies additional open files to be inherited by the
+	// new process. It does not include standard input, standard output, or
+	// standard error. If non-nil, entry i becomes file descriptor 3+i.
+	//
+	// BUG: on OS X 10.6, child processes may sometimes inherit extra fds.
+	// http://golang.org/issue/2603
+	ExtraFiles []*os.File
+
+	// SysProcAttr holds optional, operating system-specific attributes.
+	// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
+	SysProcAttr *syscall.SysProcAttr
+
+	// Process is the underlying process, once started.
+	Process *os.Process
+
+	err             error // last error (from LookPath, stdin, stdout, stderr)
+	finished        bool  // when Wait was called
+	childFiles      []*os.File
+	closeAfterStart []io.Closer
+	closeAfterWait  []io.Closer
+	goroutine       []func() error
+	errch           chan error // one send per goroutine
+}
+
+// Command returns the Cmd struct to execute the named program with
+// the given arguments.
+//
+// It sets Path and Args in the returned structure and zeroes the
+// other fields.
+//
+// If name contains no path separators, Command uses LookPath to
+// resolve the path to a complete name if possible. Otherwise it uses
+// name directly.
+//
+// The returned Cmd's Args field is constructed from the command name
+// followed by the elements of arg, so arg should not include the
+// command name itself. For example, Command("echo", "hello")
+func Command(name string, arg ...string) *Cmd {
+	aname, err := LookPath(name)
+	if err != nil {
+		aname = name
+	}
+	return &Cmd{
+		Path: aname,
+		Args: append([]string{name}, arg...),
+		err:  err,
+	}
+}
+
+// interfaceEqual protects against panics from doing equality tests on
+// two interfaces with non-comparable underlying types
+func interfaceEqual(a, b interface{}) bool {
+	defer func() {
+		recover()
+	}()
+	return a == b
+}
+
+func (c *Cmd) envv() []string {
+	if c.Env != nil {
+		return c.Env
+	}
+	return os.Environ()
+}
+
+func (c *Cmd) argv() []string {
+	if len(c.Args) > 0 {
+		return c.Args
+	}
+	return []string{c.Path}
+}
+
+func (c *Cmd) stdin() (f *os.File, err error) {
+	if c.Stdin == nil {
+		f, err = os.Open(os.DevNull)
+		c.closeAfterStart = append(c.closeAfterStart, f)
+		return
+	}
+
+	if f, ok := c.Stdin.(*os.File); ok {
+		return f, nil
+	}
+
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return
+	}
+
+	c.closeAfterStart = append(c.closeAfterStart, pr)
+	c.closeAfterWait = append(c.closeAfterWait, pw)
+	c.goroutine = append(c.goroutine, func() error {
+		_, err := io.Copy(pw, c.Stdin)
+		if err1 := pw.Close(); err == nil {
+			err = err1
+		}
+		return err
+	})
+	return pr, nil
+}
+
+func (c *Cmd) stdout() (f *os.File, err error) {
+	return c.writerDescriptor(c.Stdout)
+}
+
+func (c *Cmd) stderr() (f *os.File, err error) {
+	if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
+		return c.childFiles[1], nil
+	}
+	return c.writerDescriptor(c.Stderr)
+}
+
+func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) {
+	if w == nil {
+		f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
+		c.closeAfterStart = append(c.closeAfterStart, f)
+		return
+	}
+
+	if f, ok := w.(*os.File); ok {
+		return f, nil
+	}
+
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return
+	}
+
+	c.closeAfterStart = append(c.closeAfterStart, pw)
+	c.closeAfterWait = append(c.closeAfterWait, pr)
+	c.goroutine = append(c.goroutine, func() error {
+		_, err := io.Copy(w, pr)
+		return err
+	})
+	return pw, nil
+}
+
+// Run starts the specified command and waits for it to complete.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the command fails to run or doesn't complete successfully, the
+// error is of type *ExitError. Other error types may be
+// returned for I/O problems.
+func (c *Cmd) Run() error {
+	if err := c.Start(); err != nil {
+		return err
+	}
+	return c.Wait()
+}
+
+// Start starts the specified command but does not wait for it to complete.
+func (c *Cmd) Start() error {
+	if c.err != nil {
+		return c.err
+	}
+	if c.Process != nil {
+		return errors.New("exec: already started")
+	}
+
+	type F func(*Cmd) (*os.File, error)
+	for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
+		fd, err := setupFd(c)
+		if err != nil {
+			return err
+		}
+		c.childFiles = append(c.childFiles, fd)
+	}
+	c.childFiles = append(c.childFiles, c.ExtraFiles...)
+
+	var err error
+	c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
+		Dir:   c.Dir,
+		Files: c.childFiles,
+		Env:   c.envv(),
+		Sys:   c.SysProcAttr,
+	})
+	if err != nil {
+		return err
+	}
+
+	for _, fd := range c.closeAfterStart {
+		fd.Close()
+	}
+
+	c.errch = make(chan error, len(c.goroutine))
+	for _, fn := range c.goroutine {
+		go func(fn func() error) {
+			c.errch <- fn()
+		}(fn)
+	}
+
+	return nil
+}
+
+// An ExitError reports an unsuccessful exit by a command.
+type ExitError struct {
+	*os.Waitmsg
+}
+
+func (e *ExitError) Error() string {
+	return e.Waitmsg.String()
+}
+
+// Wait waits for the command to exit.
+// It must have been started by Start.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the command fails to run or doesn't complete successfully, the
+// error is of type *ExitError. Other error types may be
+// returned for I/O problems.
+func (c *Cmd) Wait() error {
+	if c.Process == nil {
+		return errors.New("exec: not started")
+	}
+	if c.finished {
+		return errors.New("exec: Wait was already called")
+	}
+	c.finished = true
+	msg, err := c.Process.Wait(0)
+
+	var copyError error
+	for _ = range c.goroutine {
+		if err := <-c.errch; err != nil && copyError == nil {
+			copyError = err
+		}
+	}
+
+	for _, fd := range c.closeAfterWait {
+		fd.Close()
+	}
+
+	if err != nil {
+		return err
+	} else if !msg.Exited() || msg.ExitStatus() != 0 {
+		return &ExitError{msg}
+	}
+
+	return copyError
+}
+
+// Output runs the command and returns its standard output.
+func (c *Cmd) Output() ([]byte, error) {
+	if c.Stdout != nil {
+		return nil, errors.New("exec: Stdout already set")
+	}
+	var b bytes.Buffer
+	c.Stdout = &b
+	err := c.Run()
+	return b.Bytes(), err
+}
+
+// CombinedOutput runs the command and returns its combined standard
+// output and standard error.
+func (c *Cmd) CombinedOutput() ([]byte, error) {
+	if c.Stdout != nil {
+		return nil, errors.New("exec: Stdout already set")
+	}
+	if c.Stderr != nil {
+		return nil, errors.New("exec: Stderr already set")
+	}
+	var b bytes.Buffer
+	c.Stdout = &b
+	c.Stderr = &b
+	err := c.Run()
+	return b.Bytes(), err
+}
+
+// StdinPipe returns a pipe that will be connected to the command's
+// standard input when the command starts.
+func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
+	if c.Stdin != nil {
+		return nil, errors.New("exec: Stdin already set")
+	}
+	if c.Process != nil {
+		return nil, errors.New("exec: StdinPipe after process started")
+	}
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return nil, err
+	}
+	c.Stdin = pr
+	c.closeAfterStart = append(c.closeAfterStart, pr)
+	c.closeAfterWait = append(c.closeAfterWait, pw)
+	return pw, nil
+}
+
+// StdoutPipe returns a pipe that will be connected to the command's
+// standard output when the command starts.
+// The pipe will be closed automatically after Wait sees the command exit.
+func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
+	if c.Stdout != nil {
+		return nil, errors.New("exec: Stdout already set")
+	}
+	if c.Process != nil {
+		return nil, errors.New("exec: StdoutPipe after process started")
+	}
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return nil, err
+	}
+	c.Stdout = pw
+	c.closeAfterStart = append(c.closeAfterStart, pw)
+	c.closeAfterWait = append(c.closeAfterWait, pr)
+	return pr, nil
+}
+
+// StderrPipe returns a pipe that will be connected to the command's
+// standard error when the command starts.
+// The pipe will be closed automatically after Wait sees the command exit.
+func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
+	if c.Stderr != nil {
+		return nil, errors.New("exec: Stderr already set")
+	}
+	if c.Process != nil {
+		return nil, errors.New("exec: StderrPipe after process started")
+	}
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		return nil, err
+	}
+	c.Stderr = pw
+	c.closeAfterStart = append(c.closeAfterStart, pw)
+	c.closeAfterWait = append(c.closeAfterWait, pr)
+	return pr, nil
+}
diff --git a/src/pkg/os/exec/exec_test.go b/src/pkg/os/exec/exec_test.go
new file mode 100644
index 0000000..c684980
--- /dev/null
+++ b/src/pkg/os/exec/exec_test.go
@@ -0,0 +1,303 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package exec
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"runtime"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func helperCommand(s ...string) *Cmd {
+	cs := []string{"-test.run=TestHelperProcess", "--"}
+	cs = append(cs, s...)
+	cmd := Command(os.Args[0], cs...)
+	cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
+	return cmd
+}
+
+func TestEcho(t *testing.T) {
+	bs, err := helperCommand("echo", "foo bar", "baz").Output()
+	if err != nil {
+		t.Errorf("echo: %v", err)
+	}
+	if g, e := string(bs), "foo bar baz\n"; g != e {
+		t.Errorf("echo: want %q, got %q", e, g)
+	}
+}
+
+func TestCatStdin(t *testing.T) {
+	// Cat, testing stdin and stdout.
+	input := "Input string\nLine 2"
+	p := helperCommand("cat")
+	p.Stdin = strings.NewReader(input)
+	bs, err := p.Output()
+	if err != nil {
+		t.Errorf("cat: %v", err)
+	}
+	s := string(bs)
+	if s != input {
+		t.Errorf("cat: want %q, got %q", input, s)
+	}
+}
+
+func TestCatGoodAndBadFile(t *testing.T) {
+	// Testing combined output and error values.
+	bs, err := helperCommand("cat", "/bogus/file.foo", "exec_test.go").CombinedOutput()
+	if _, ok := err.(*ExitError); !ok {
+		t.Errorf("expected *ExitError from cat combined; got %T: %v", err, err)
+	}
+	s := string(bs)
+	sp := strings.SplitN(s, "\n", 2)
+	if len(sp) != 2 {
+		t.Fatalf("expected two lines from cat; got %q", s)
+	}
+	errLine, body := sp[0], sp[1]
+	if !strings.HasPrefix(errLine, "Error: open /bogus/file.foo") {
+		t.Errorf("expected stderr to complain about file; got %q", errLine)
+	}
+	if !strings.Contains(body, "func TestHelperProcess(t *testing.T)") {
+		t.Errorf("expected test code; got %q (len %d)", body, len(body))
+	}
+}
+
+func TestNoExistBinary(t *testing.T) {
+	// Can't run a non-existent binary
+	err := Command("/no-exist-binary").Run()
+	if err == nil {
+		t.Error("expected error from /no-exist-binary")
+	}
+}
+
+func TestExitStatus(t *testing.T) {
+	// Test that exit values are returned correctly
+	err := helperCommand("exit", "42").Run()
+	if werr, ok := err.(*ExitError); ok {
+		if s, e := werr.Error(), "exit status 42"; s != e {
+			t.Errorf("from exit 42 got exit %q, want %q", s, e)
+		}
+	} else {
+		t.Fatalf("expected *ExitError from exit 42; got %T: %v", err, err)
+	}
+}
+
+func TestPipes(t *testing.T) {
+	check := func(what string, err error) {
+		if err != nil {
+			t.Fatalf("%s: %v", what, err)
+		}
+	}
+	// Cat, testing stdin and stdout.
+	c := helperCommand("pipetest")
+	stdin, err := c.StdinPipe()
+	check("StdinPipe", err)
+	stdout, err := c.StdoutPipe()
+	check("StdoutPipe", err)
+	stderr, err := c.StderrPipe()
+	check("StderrPipe", err)
+
+	outbr := bufio.NewReader(stdout)
+	errbr := bufio.NewReader(stderr)
+	line := func(what string, br *bufio.Reader) string {
+		line, _, err := br.ReadLine()
+		if err != nil {
+			t.Fatalf("%s: %v", what, err)
+		}
+		return string(line)
+	}
+
+	err = c.Start()
+	check("Start", err)
+
+	_, err = stdin.Write([]byte("O:I am output\n"))
+	check("first stdin Write", err)
+	if g, e := line("first output line", outbr), "O:I am output"; g != e {
+		t.Errorf("got %q, want %q", g, e)
+	}
+
+	_, err = stdin.Write([]byte("E:I am error\n"))
+	check("second stdin Write", err)
+	if g, e := line("first error line", errbr), "E:I am error"; g != e {
+		t.Errorf("got %q, want %q", g, e)
+	}
+
+	_, err = stdin.Write([]byte("O:I am output2\n"))
+	check("third stdin Write 3", err)
+	if g, e := line("second output line", outbr), "O:I am output2"; g != e {
+		t.Errorf("got %q, want %q", g, e)
+	}
+
+	stdin.Close()
+	err = c.Wait()
+	check("Wait", err)
+}
+
+func TestExtraFiles(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Logf("no operating system support; skipping")
+		return
+	}
+
+	// Force network usage, to verify the epoll (or whatever) fd
+	// doesn't leak to the child,
+	ln, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer ln.Close()
+
+	// Force TLS root certs to be loaded (which might involve
+	// cgo), to make sure none of that potential C code leaks fds.
+	ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Write([]byte("Hello"))
+	}))
+	defer ts.Close()
+	http.Get(ts.URL) // ignore result; just calling to force root cert loading
+
+	tf, err := ioutil.TempFile("", "")
+	if err != nil {
+		t.Fatalf("TempFile: %v", err)
+	}
+	defer os.Remove(tf.Name())
+	defer tf.Close()
+
+	const text = "Hello, fd 3!"
+	_, err = tf.Write([]byte(text))
+	if err != nil {
+		t.Fatalf("Write: %v", err)
+	}
+	_, err = tf.Seek(0, os.SEEK_SET)
+	if err != nil {
+		t.Fatalf("Seek: %v", err)
+	}
+
+	c := helperCommand("read3")
+	c.ExtraFiles = []*os.File{tf}
+	bs, err := c.CombinedOutput()
+	if err != nil {
+		t.Fatalf("CombinedOutput: %v; output %q", err, bs)
+	}
+	if string(bs) != text {
+		t.Errorf("got %q; want %q", string(bs), text)
+	}
+}
+
+// TestHelperProcess isn't a real test. It's used as a helper process
+// for TestParameterRun.
+func TestHelperProcess(*testing.T) {
+	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
+		return
+	}
+	defer os.Exit(0)
+
+	args := os.Args
+	for len(args) > 0 {
+		if args[0] == "--" {
+			args = args[1:]
+			break
+		}
+		args = args[1:]
+	}
+	if len(args) == 0 {
+		fmt.Fprintf(os.Stderr, "No command\n")
+		os.Exit(2)
+	}
+
+	cmd, args := args[0], args[1:]
+	switch cmd {
+	case "echo":
+		iargs := []interface{}{}
+		for _, s := range args {
+			iargs = append(iargs, s)
+		}
+		fmt.Println(iargs...)
+	case "cat":
+		if len(args) == 0 {
+			io.Copy(os.Stdout, os.Stdin)
+			return
+		}
+		exit := 0
+		for _, fn := range args {
+			f, err := os.Open(fn)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+				exit = 2
+			} else {
+				defer f.Close()
+				io.Copy(os.Stdout, f)
+			}
+		}
+		os.Exit(exit)
+	case "pipetest":
+		bufr := bufio.NewReader(os.Stdin)
+		for {
+			line, _, err := bufr.ReadLine()
+			if err == io.EOF {
+				break
+			} else if err != nil {
+				os.Exit(1)
+			}
+			if bytes.HasPrefix(line, []byte("O:")) {
+				os.Stdout.Write(line)
+				os.Stdout.Write([]byte{'\n'})
+			} else if bytes.HasPrefix(line, []byte("E:")) {
+				os.Stderr.Write(line)
+				os.Stderr.Write([]byte{'\n'})
+			} else {
+				os.Exit(1)
+			}
+		}
+	case "read3": // read fd 3
+		fd3 := os.NewFile(3, "fd3")
+		bs, err := ioutil.ReadAll(fd3)
+		if err != nil {
+			fmt.Printf("ReadAll from fd 3: %v", err)
+			os.Exit(1)
+		}
+		switch runtime.GOOS {
+		case "darwin":
+			// TODO(bradfitz): broken? Sometimes.
+			// http://golang.org/issue/2603
+			// Skip this additional part of the test for now.
+		default:
+			// Now verify that there are no other open fds.
+			var files []*os.File
+			for wantfd := os.Stderr.Fd() + 2; wantfd <= 100; wantfd++ {
+				f, err := os.Open(os.Args[0])
+				if err != nil {
+					fmt.Printf("error opening file with expected fd %d: %v", wantfd, err)
+					os.Exit(1)
+				}
+				if got := f.Fd(); got != wantfd {
+					fmt.Printf("leaked parent file. fd = %d; want %d\n", got, wantfd)
+					out, _ := Command("lsof", "-p", fmt.Sprint(os.Getpid())).CombinedOutput()
+					fmt.Print(string(out))
+					os.Exit(1)
+				}
+				files = append(files, f)
+			}
+			for _, f := range files {
+				f.Close()
+			}
+		}
+		os.Stderr.Write(bs)
+	case "exit":
+		n, _ := strconv.Atoi(args[0])
+		os.Exit(n)
+	default:
+		fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
+		os.Exit(2)
+	}
+}
diff --git a/src/pkg/os/exec/lp_plan9.go b/src/pkg/os/exec/lp_plan9.go
new file mode 100644
index 0000000..d88cd0d
--- /dev/null
+++ b/src/pkg/os/exec/lp_plan9.go
@@ -0,0 +1,52 @@
+// Copyright 2011 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 exec
+
+import (
+	"errors"
+	"os"
+	"strings"
+)
+
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+var ErrNotFound = errors.New("executable file not found in $path")
+
+func findExecutable(file string) error {
+	d, err := os.Stat(file)
+	if err != nil {
+		return err
+	}
+	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
+		return nil
+	}
+	return os.EPERM
+}
+
+// LookPath searches for an executable binary named file
+// in the directories named by the path environment variable.
+// If file begins with "/", "#", "./", or "../", it is tried
+// directly and the path is not consulted.
+func LookPath(file string) (string, error) {
+	// skip the path lookup for these prefixes
+	skip := []string{"/", "#", "./", "../"}
+
+	for _, p := range skip {
+		if strings.HasPrefix(file, p) {
+			err := findExecutable(file)
+			if err == nil {
+				return file, nil
+			}
+			return "", &Error{file, err}
+		}
+	}
+
+	path := os.Getenv("path")
+	for _, dir := range strings.Split(path, "\000") {
+		if err := findExecutable(dir + "/" + file); err == nil {
+			return dir + "/" + file, nil
+		}
+	}
+	return "", &Error{file, ErrNotFound}
+}
diff --git a/src/pkg/exec/lp_test.go b/src/pkg/os/exec/lp_test.go
similarity index 100%
rename from src/pkg/exec/lp_test.go
rename to src/pkg/os/exec/lp_test.go
diff --git a/src/pkg/os/exec/lp_unix.go b/src/pkg/os/exec/lp_unix.go
new file mode 100644
index 0000000..2d3a919
--- /dev/null
+++ b/src/pkg/os/exec/lp_unix.go
@@ -0,0 +1,56 @@
+// Copyright 2010 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 darwin freebsd linux netbsd openbsd
+
+package exec
+
+import (
+	"errors"
+	"os"
+	"strings"
+)
+
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+var ErrNotFound = errors.New("executable file not found in $PATH")
+
+func findExecutable(file string) error {
+	d, err := os.Stat(file)
+	if err != nil {
+		return err
+	}
+	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
+		return nil
+	}
+	return os.EPERM
+}
+
+// LookPath searches for an executable binary named file
+// in the directories named by the PATH environment variable.
+// If file contains a slash, it is tried directly and the PATH is not consulted.
+func LookPath(file string) (string, error) {
+	// NOTE(rsc): I wish we could use the Plan 9 behavior here
+	// (only bypass the path if file begins with / or ./ or ../)
+	// but that would not match all the Unix shells.
+
+	if strings.Contains(file, "/") {
+		err := findExecutable(file)
+		if err == nil {
+			return file, nil
+		}
+		return "", &Error{file, err}
+	}
+	pathenv := os.Getenv("PATH")
+	for _, dir := range strings.Split(pathenv, ":") {
+		if dir == "" {
+			// Unix shell semantics: path element "" means "."
+			dir = "."
+		}
+		path := dir + "/" + file
+		if err := findExecutable(path); err == nil {
+			return path, nil
+		}
+	}
+	return "", &Error{file, ErrNotFound}
+}
diff --git a/src/pkg/os/exec/lp_windows.go b/src/pkg/os/exec/lp_windows.go
new file mode 100644
index 0000000..b7efcd6
--- /dev/null
+++ b/src/pkg/os/exec/lp_windows.go
@@ -0,0 +1,82 @@
+// Copyright 2010 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 exec
+
+import (
+	"errors"
+	"os"
+	"strings"
+)
+
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+var ErrNotFound = errors.New("executable file not found in %PATH%")
+
+func chkStat(file string) error {
+	d, err := os.Stat(file)
+	if err != nil {
+		return err
+	}
+	if d.IsDir() {
+		return os.EPERM
+	}
+	return nil
+}
+
+func findExecutable(file string, exts []string) (string, error) {
+	if len(exts) == 0 {
+		return file, chkStat(file)
+	}
+	f := strings.ToLower(file)
+	for _, e := range exts {
+		if strings.HasSuffix(f, e) {
+			return file, chkStat(file)
+		}
+	}
+	for _, e := range exts {
+		if f := file + e; chkStat(f) == nil {
+			return f, nil
+		}
+	}
+	return ``, os.ENOENT
+}
+
+// LookPath searches for an executable binary named file
+// in the directories named by the PATH environment variable.
+// If file contains a slash, it is tried directly and the PATH is not consulted.
+// LookPath also uses PATHEXT environment variable to match
+// a suitable candidate.
+func LookPath(file string) (f string, err error) {
+	x := os.Getenv(`PATHEXT`)
+	if x == `` {
+		x = `.COM;.EXE;.BAT;.CMD`
+	}
+	exts := []string{}
+	for _, e := range strings.Split(strings.ToLower(x), `;`) {
+		if e == "" {
+			continue
+		}
+		if e[0] != '.' {
+			e = "." + e
+		}
+		exts = append(exts, e)
+	}
+	if strings.IndexAny(file, `:\/`) != -1 {
+		if f, err = findExecutable(file, exts); err == nil {
+			return
+		}
+		return ``, &Error{file, err}
+	}
+	if f, err = findExecutable(`.\`+file, exts); err == nil {
+		return
+	}
+	if pathenv := os.Getenv(`PATH`); pathenv != `` {
+		for _, dir := range strings.Split(pathenv, `;`) {
+			if f, err = findExecutable(dir+`\`+file, exts); err == nil {
+				return
+			}
+		}
+	}
+	return ``, &Error{file, ErrNotFound}
+}
diff --git a/src/pkg/os/exec_plan9.go b/src/pkg/os/exec_plan9.go
index 6f0722a..879d4d2 100644
--- a/src/pkg/os/exec_plan9.go
+++ b/src/pkg/os/exec_plan9.go
@@ -5,13 +5,14 @@
 package os
 
 import (
+	"errors"
 	"runtime"
 	"syscall"
 )
 
 // StartProcess starts a new process with the program, arguments and attributes
 // specified by name, argv and attr.
-func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
 	sysattr := &syscall.ProcAttr{
 		Dir: attr.Dir,
 		Env: attr.Env,
@@ -31,7 +32,7 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err E
 	sysattr.Files = intfd
 
 	pid, h, e := syscall.StartProcess(name, argv, sysattr)
-	if iserror(e) {
+	if e != nil {
 		return nil, &PathError{"fork/exec", name, e}
 	}
 
@@ -45,13 +46,13 @@ func (note Plan9Note) String() string {
 	return string(note)
 }
 
-func (p *Process) Signal(sig Signal) Error {
+func (p *Process) Signal(sig Signal) error {
 	if p.done {
-		return NewError("os: process already finished")
+		return errors.New("os: process already finished")
 	}
 
 	f, e := OpenFile("/proc/"+itoa(p.Pid)+"/note", O_WRONLY, 0)
-	if iserror(e) {
+	if e != nil {
 		return NewSyscallError("signal", e)
 	}
 	defer f.Close()
@@ -60,9 +61,9 @@ func (p *Process) Signal(sig Signal) Error {
 }
 
 // Kill causes the Process to exit immediately.
-func (p *Process) Kill() Error {
+func (p *Process) Kill() error {
 	f, e := OpenFile("/proc/"+itoa(p.Pid)+"/ctl", O_WRONLY, 0)
-	if iserror(e) {
+	if e != nil {
 		return NewSyscallError("kill", e)
 	}
 	defer f.Close()
@@ -72,11 +73,11 @@ func (p *Process) Kill() Error {
 
 // Exec replaces the current process with an execution of the
 // named binary, with arguments argv and environment envv.
-// If successful, Exec never returns.  If it fails, it returns an Error.
+// If successful, Exec never returns.  If it fails, it returns an error.
 // ForkExec is almost always a better way to execute a program.
-func Exec(name string, argv []string, envv []string) Error {
+func Exec(name string, argv []string, envv []string) error {
 	e := syscall.Exec(name, argv, envv)
-	if iserror(e) {
+	if e != nil {
 		return &PathError{"exec", name, e}
 	}
 
@@ -89,9 +90,9 @@ type Waitmsg struct {
 }
 
 // Wait waits for the Process to exit or stop, and then returns a
-// Waitmsg describing its status and an Error, if any. The options
+// Waitmsg describing its status and an error, if any. The options
 // (WNOHANG etc.) affect the behavior of the Wait call.
-func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
+func (p *Process) Wait(options int) (w *Waitmsg, err error) {
 	var waitmsg syscall.Waitmsg
 
 	if p.Pid == -1 {
@@ -101,7 +102,7 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
 	for true {
 		err = syscall.Await(&waitmsg)
 
-		if iserror(err) {
+		if err != nil {
 			return nil, NewSyscallError("wait", err)
 		}
 
@@ -115,11 +116,11 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
 }
 
 // Wait waits for process pid to exit or stop, and then returns a
-// Waitmsg describing its status and an Error, if any. The options
+// Waitmsg describing its status and an error, if any. The options
 // (WNOHANG etc.) affect the behavior of the Wait call.
 // Wait is equivalent to calling FindProcess and then Wait
 // and Release on the result.
-func Wait(pid int, options int) (w *Waitmsg, err Error) {
+func Wait(pid int, options int) (w *Waitmsg, err error) {
 	p, e := FindProcess(pid)
 	if e != nil {
 		return nil, e
@@ -129,7 +130,7 @@ func Wait(pid int, options int) (w *Waitmsg, err Error) {
 }
 
 // Release releases any resources associated with the Process.
-func (p *Process) Release() Error {
+func (p *Process) Release() error {
 	// NOOP for Plan 9.
 	p.Pid = -1
 	// no need for a finalizer anymore
@@ -137,10 +138,7 @@ func (p *Process) Release() Error {
 	return nil
 }
 
-// FindProcess looks for a running process by its pid.
-// The Process it returns can be used to obtain information
-// about the underlying operating system process.
-func FindProcess(pid int) (p *Process, err Error) {
+func findProcess(pid int) (p *Process, err error) {
 	// NOOP for Plan 9.
 	return newProcess(pid, 0), nil
 }
diff --git a/src/pkg/os/exec_posix.go b/src/pkg/os/exec_posix.go
index 035b156..218b8cd 100644
--- a/src/pkg/os/exec_posix.go
+++ b/src/pkg/os/exec_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 package os
 
@@ -24,9 +24,9 @@ func (sig UnixSignal) String() string {
 // StartProcess starts a new process with the program, arguments and attributes
 // specified by name, argv and attr.
 //
-// StartProcess is a low-level interface. The exec package provides
+// StartProcess is a low-level interface. The os/exec package provides
 // higher-level interfaces.
-func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
 	sysattr := &syscall.ProcAttr{
 		Dir: attr.Dir,
 		Env: attr.Env,
@@ -40,30 +40,30 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err E
 	}
 
 	pid, h, e := syscall.StartProcess(name, argv, sysattr)
-	if iserror(e) {
-		return nil, &PathError{"fork/exec", name, Errno(e)}
+	if e != nil {
+		return nil, &PathError{"fork/exec", name, e}
 	}
 	return newProcess(pid, h), nil
 }
 
 // Kill causes the Process to exit immediately.
-func (p *Process) Kill() Error {
+func (p *Process) Kill() error {
 	return p.Signal(SIGKILL)
 }
 
 // Exec replaces the current process with an execution of the
 // named binary, with arguments argv and environment envv.
-// If successful, Exec never returns.  If it fails, it returns an Error.
+// If successful, Exec never returns.  If it fails, it returns an error.
 //
 // To run a child process, see StartProcess (for a low-level interface)
-// or the exec package (for higher-level interfaces).
-func Exec(name string, argv []string, envv []string) Error {
+// or the os/exec package (for higher-level interfaces).
+func Exec(name string, argv []string, envv []string) error {
 	if envv == nil {
 		envv = Environ()
 	}
 	e := syscall.Exec(name, argv, envv)
-	if iserror(e) {
-		return &PathError{"exec", name, Errno(e)}
+	if e != nil {
+		return &PathError{"exec", name, e}
 	}
 	return nil
 }
@@ -83,11 +83,11 @@ type Waitmsg struct {
 }
 
 // Wait waits for process pid to exit or stop, and then returns a
-// Waitmsg describing its status and an Error, if any. The options
+// Waitmsg describing its status and an error, if any. The options
 // (WNOHANG etc.) affect the behavior of the Wait call.
 // Wait is equivalent to calling FindProcess and then Wait
 // and Release on the result.
-func Wait(pid int, options int) (w *Waitmsg, err Error) {
+func Wait(pid int, options int) (w *Waitmsg, err error) {
 	p, e := FindProcess(pid)
 	if e != nil {
 		return nil, e
diff --git a/src/pkg/os/exec_unix.go b/src/pkg/os/exec_unix.go
index e1adb20..6c11b63 100644
--- a/src/pkg/os/exec_unix.go
+++ b/src/pkg/os/exec_unix.go
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package os
 
 import (
+	"errors"
 	"runtime"
 	"syscall"
 )
@@ -24,9 +25,9 @@ const (
 // the options
 
 // Wait waits for the Process to exit or stop, and then returns a
-// Waitmsg describing its status and an Error, if any. The options
+// Waitmsg describing its status and an error, if any. The options
 // (WNOHANG etc.) affect the behavior of the Wait call.
-func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
+func (p *Process) Wait(options int) (w *Waitmsg, err error) {
 	if p.Pid == -1 {
 		return nil, EINVAL
 	}
@@ -37,7 +38,7 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
 		options ^= WRUSAGE
 	}
 	pid1, e := syscall.Wait4(p.Pid, &status, options, rusage)
-	if e != 0 {
+	if e != nil {
 		return nil, NewSyscallError("wait", e)
 	}
 	// With WNOHANG pid is 0 if child has not exited.
@@ -52,18 +53,18 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
 }
 
 // Signal sends a signal to the Process.
-func (p *Process) Signal(sig Signal) Error {
+func (p *Process) Signal(sig Signal) error {
 	if p.done {
-		return NewError("os: process already finished")
+		return errors.New("os: process already finished")
 	}
-	if e := syscall.Kill(p.Pid, int(sig.(UnixSignal))); e != 0 {
-		return Errno(e)
+	if e := syscall.Kill(p.Pid, int(sig.(UnixSignal))); e != nil {
+		return e
 	}
 	return nil
 }
 
 // Release releases any resources associated with the Process.
-func (p *Process) Release() Error {
+func (p *Process) Release() error {
 	// NOOP for unix.
 	p.Pid = -1
 	// no need for a finalizer anymore
@@ -71,10 +72,7 @@ func (p *Process) Release() Error {
 	return nil
 }
 
-// FindProcess looks for a running process by its pid.
-// The Process it returns can be used to obtain information
-// about the underlying operating system process.
-func FindProcess(pid int) (p *Process, err Error) {
+func findProcess(pid int) (p *Process, err error) {
 	// NOOP for unix.
 	return newProcess(pid, 0), nil
 }
diff --git a/src/pkg/os/exec_windows.go b/src/pkg/os/exec_windows.go
index 65e94ac..7eb7d19 100644
--- a/src/pkg/os/exec_windows.go
+++ b/src/pkg/os/exec_windows.go
@@ -5,11 +5,15 @@
 package os
 
 import (
+	"errors"
 	"runtime"
 	"syscall"
+	"unsafe"
 )
 
-func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
+// Wait waits for the Process to exit or stop, and then returns a
+// Waitmsg describing its status and an error, if any.
+func (p *Process) Wait(options int) (w *Waitmsg, err error) {
 	s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE)
 	switch s {
 	case syscall.WAIT_OBJECT_0:
@@ -17,11 +21,11 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
 	case syscall.WAIT_FAILED:
 		return nil, NewSyscallError("WaitForSingleObject", e)
 	default:
-		return nil, NewError("os: unexpected result from WaitForSingleObject")
+		return nil, errors.New("os: unexpected result from WaitForSingleObject")
 	}
 	var ec uint32
 	e = syscall.GetExitCodeProcess(syscall.Handle(p.handle), &ec)
-	if e != 0 {
+	if e != nil {
 		return nil, NewSyscallError("GetExitCodeProcess", e)
 	}
 	p.done = true
@@ -29,24 +33,25 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
 }
 
 // Signal sends a signal to the Process.
-func (p *Process) Signal(sig Signal) Error {
+func (p *Process) Signal(sig Signal) error {
 	if p.done {
-		return NewError("os: process already finished")
+		return errors.New("os: process already finished")
 	}
 	switch sig.(UnixSignal) {
 	case SIGKILL:
 		e := syscall.TerminateProcess(syscall.Handle(p.handle), 1)
 		return NewSyscallError("TerminateProcess", e)
 	}
-	return Errno(syscall.EWINDOWS)
+	return syscall.Errno(syscall.EWINDOWS)
 }
 
-func (p *Process) Release() Error {
+// Release releases any resources associated with the Process.
+func (p *Process) Release() error {
 	if p.handle == -1 {
 		return EINVAL
 	}
 	e := syscall.CloseHandle(syscall.Handle(p.handle))
-	if e != 0 {
+	if e != nil {
 		return NewSyscallError("CloseHandle", e)
 	}
 	p.handle = -1
@@ -55,12 +60,26 @@ func (p *Process) Release() Error {
 	return nil
 }
 
-func FindProcess(pid int) (p *Process, err Error) {
+func findProcess(pid int) (p *Process, err error) {
 	const da = syscall.STANDARD_RIGHTS_READ |
 		syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
 	h, e := syscall.OpenProcess(da, false, uint32(pid))
-	if e != 0 {
+	if e != nil {
 		return nil, NewSyscallError("OpenProcess", e)
 	}
 	return newProcess(pid, int(h)), nil
 }
+
+func init() {
+	var argc int32
+	cmd := syscall.GetCommandLine()
+	argv, e := syscall.CommandLineToArgv(cmd, &argc)
+	if e != nil {
+		return
+	}
+	defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv))))
+	Args = make([]string, argc)
+	for i, v := range (*argv)[:argc] {
+		Args[i] = string(syscall.UTF16ToString((*v)[:]))
+	}
+}
diff --git a/src/pkg/os/export_test.go b/src/pkg/os/export_test.go
new file mode 100644
index 0000000..9c6ef42
--- /dev/null
+++ b/src/pkg/os/export_test.go
@@ -0,0 +1,9 @@
+// Copyright 2011 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 os
+
+// Export for testing.
+
+var Atime = atime
diff --git a/src/pkg/os/file.go b/src/pkg/os/file.go
index 4335d45..3efa650 100644
--- a/src/pkg/os/file.go
+++ b/src/pkg/os/file.go
@@ -9,11 +9,12 @@
 package os
 
 import (
+	"io"
 	"syscall"
 )
 
 // Name returns the name of the file as presented to Open.
-func (file *File) Name() string { return file.name }
+func (f *File) Name() string { return f.name }
 
 // Stdin, Stdout, and Stderr are open Files pointing to the standard input,
 // standard output, and standard error file descriptors.
@@ -47,52 +48,41 @@ const (
 	SEEK_END int = 2 // seek relative to the end
 )
 
-type eofError int
-
-func (eofError) String() string { return "EOF" }
-
-// EOF is the Error returned by Read when no more input is available.
-// Functions should return EOF only to signal a graceful end of input.
-// If the EOF occurs unexpectedly in a structured data stream,
-// the appropriate error is either io.ErrUnexpectedEOF or some other error
-// giving more detail.
-var EOF Error = eofError(0)
-
 // Read reads up to len(b) bytes from the File.
-// It returns the number of bytes read and an Error, if any.
-// EOF is signaled by a zero count with err set to EOF.
-func (file *File) Read(b []byte) (n int, err Error) {
-	if file == nil {
+// It returns the number of bytes read and an error, if any.
+// EOF is signaled by a zero count with err set to io.EOF.
+func (f *File) Read(b []byte) (n int, err error) {
+	if f == nil {
 		return 0, EINVAL
 	}
-	n, e := file.read(b)
+	n, e := f.read(b)
 	if n < 0 {
 		n = 0
 	}
-	if n == 0 && !iserror(e) {
-		return 0, EOF
+	if n == 0 && len(b) > 0 && e == nil {
+		return 0, io.EOF
 	}
-	if iserror(e) {
-		err = &PathError{"read", file.name, Errno(e)}
+	if e != nil {
+		err = &PathError{"read", f.name, e}
 	}
 	return n, err
 }
 
 // ReadAt reads len(b) bytes from the File starting at byte offset off.
-// It returns the number of bytes read and the Error, if any.
-// EOF is signaled by a zero count with err set to EOF.
-// ReadAt always returns a non-nil Error when n != len(b).
-func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
-	if file == nil {
+// It returns the number of bytes read and the error, if any.
+// ReadAt always returns a non-nil error when n < len(b).
+// At end of file, that error is io.EOF.
+func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
+	if f == nil {
 		return 0, EINVAL
 	}
 	for len(b) > 0 {
-		m, e := file.pread(b, off)
-		if m == 0 && !iserror(e) {
-			return n, EOF
+		m, e := f.pread(b, off)
+		if m == 0 && e == nil {
+			return n, io.EOF
 		}
-		if iserror(e) {
-			err = &PathError{"read", file.name, Errno(e)}
+		if e != nil {
+			err = &PathError{"read", f.name, e}
 			break
 		}
 		n += m
@@ -103,36 +93,36 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
 }
 
 // Write writes len(b) bytes to the File.
-// It returns the number of bytes written and an Error, if any.
-// Write returns a non-nil Error when n != len(b).
-func (file *File) Write(b []byte) (n int, err Error) {
-	if file == nil {
+// It returns the number of bytes written and an error, if any.
+// Write returns a non-nil error when n != len(b).
+func (f *File) Write(b []byte) (n int, err error) {
+	if f == nil {
 		return 0, EINVAL
 	}
-	n, e := file.write(b)
+	n, e := f.write(b)
 	if n < 0 {
 		n = 0
 	}
 
-	epipecheck(file, e)
+	epipecheck(f, e)
 
-	if iserror(e) {
-		err = &PathError{"write", file.name, Errno(e)}
+	if e != nil {
+		err = &PathError{"write", f.name, e}
 	}
 	return n, err
 }
 
 // WriteAt writes len(b) bytes to the File starting at byte offset off.
-// It returns the number of bytes written and an Error, if any.
-// WriteAt returns a non-nil Error when n != len(b).
-func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
-	if file == nil {
+// It returns the number of bytes written and an error, if any.
+// WriteAt returns a non-nil error when n != len(b).
+func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
+	if f == nil {
 		return 0, EINVAL
 	}
 	for len(b) > 0 {
-		m, e := file.pwrite(b, off)
-		if iserror(e) {
-			err = &PathError{"write", file.name, Errno(e)}
+		m, e := f.pwrite(b, off)
+		if e != nil {
+			err = &PathError{"write", f.name, e}
 			break
 		}
 		n += m
@@ -145,50 +135,50 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
 // Seek sets the offset for the next Read or Write on file to offset, interpreted
 // according to whence: 0 means relative to the origin of the file, 1 means
 // relative to the current offset, and 2 means relative to the end.
-// It returns the new offset and an Error, if any.
-func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
-	r, e := file.seek(offset, whence)
-	if !iserror(e) && file.dirinfo != nil && r != 0 {
+// It returns the new offset and an error, if any.
+func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
+	r, e := f.seek(offset, whence)
+	if e == nil && f.dirinfo != nil && r != 0 {
 		e = syscall.EISDIR
 	}
-	if iserror(e) {
-		return 0, &PathError{"seek", file.name, Errno(e)}
+	if e != nil {
+		return 0, &PathError{"seek", f.name, e}
 	}
 	return r, nil
 }
 
 // WriteString is like Write, but writes the contents of string s rather than
 // an array of bytes.
-func (file *File) WriteString(s string) (ret int, err Error) {
-	if file == nil {
+func (f *File) WriteString(s string) (ret int, err error) {
+	if f == nil {
 		return 0, EINVAL
 	}
-	return file.Write([]byte(s))
+	return f.Write([]byte(s))
 }
 
 // Mkdir creates a new directory with the specified name and permission bits.
 // It returns an error, if any.
-func Mkdir(name string, perm uint32) Error {
-	e := syscall.Mkdir(name, perm)
-	if iserror(e) {
-		return &PathError{"mkdir", name, Errno(e)}
+func Mkdir(name string, perm FileMode) error {
+	e := syscall.Mkdir(name, syscallMode(perm))
+	if e != nil {
+		return &PathError{"mkdir", name, e}
 	}
 	return nil
 }
 
 // Chdir changes the current working directory to the named directory.
-func Chdir(dir string) Error {
-	if e := syscall.Chdir(dir); iserror(e) {
-		return &PathError{"chdir", dir, Errno(e)}
+func Chdir(dir string) error {
+	if e := syscall.Chdir(dir); e != nil {
+		return &PathError{"chdir", dir, e}
 	}
 	return nil
 }
 
 // Chdir changes the current working directory to the file,
 // which must be a directory.
-func (f *File) Chdir() Error {
-	if e := syscall.Fchdir(f.fd); iserror(e) {
-		return &PathError{"chdir", f.name, Errno(e)}
+func (f *File) Chdir() error {
+	if e := syscall.Fchdir(f.fd); e != nil {
+		return &PathError{"chdir", f.name, e}
 	}
 	return nil
 }
@@ -196,8 +186,8 @@ func (f *File) Chdir() Error {
 // Open opens the named file for reading.  If successful, methods on
 // the returned file can be used for reading; the associated file
 // descriptor has mode O_RDONLY.
-// It returns the File and an Error, if any.
-func Open(name string) (file *File, err Error) {
+// It returns the File and an error, if any.
+func Open(name string) (file *File, err error) {
 	return OpenFile(name, O_RDONLY, 0)
 }
 
@@ -205,7 +195,7 @@ func Open(name string) (file *File, err Error) {
 // it if it already exists.  If successful, methods on the returned
 // File can be used for I/O; the associated file descriptor has mode
 // O_RDWR.
-// It returns the File and an Error, if any.
-func Create(name string) (file *File, err Error) {
+// It returns the File and an error, if any.
+func Create(name string) (file *File, err error) {
 	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
 }
diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go
index 1e94fb7..7d136eb 100644
--- a/src/pkg/os/file_plan9.go
+++ b/src/pkg/os/file_plan9.go
@@ -7,10 +7,19 @@ package os
 import (
 	"runtime"
 	"syscall"
+	"time"
 )
 
 // File represents an open file descriptor.
 type File struct {
+	*file
+}
+
+// file is the real representation of *File.
+// The extra level of indirection ensures that no clients of os
+// can overwrite this data, which could cause the finalizer
+// to close the wrong file descriptor.
+type file struct {
 	fd      int
 	name    string
 	dirinfo *dirInfo // nil unless directory being read
@@ -29,8 +38,8 @@ func NewFile(fd int, name string) *File {
 	if fd < 0 {
 		return nil
 	}
-	f := &File{fd: fd, name: name}
-	runtime.SetFinalizer(f, (*File).Close)
+	f := &File{&file{fd: fd, name: name}}
+	runtime.SetFinalizer(f.file, (*file).close)
 	return f
 }
 
@@ -41,22 +50,37 @@ type dirInfo struct {
 	bufp int                   // location of next record in buf.
 }
 
-func epipecheck(file *File, e syscall.Error) {
+func epipecheck(file *File, e error) {
 }
 
 // DevNull is the name of the operating system's ``null device.''
 // On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
 const DevNull = "/dev/null"
 
+// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
+func syscallMode(i FileMode) (o uint32) {
+	o |= uint32(i.Perm())
+	if i&ModeAppend != 0 {
+		o |= syscall.DMAPPEND
+	}
+	if i&ModeExclusive != 0 {
+		o |= syscall.DMEXCL
+	}
+	if i&ModeTemporary != 0 {
+		o |= syscall.DMTMP
+	}
+	return
+}
+
 // OpenFile is the generalized open call; most users will use Open
 // or Create instead.  It opens the named file with specified flag
 // (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
 // methods on the returned File can be used for I/O.
-// It returns the File and an Error, if any.
-func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
+// It returns the File and an error, if any.
+func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
 	var (
 		fd     int
-		e      syscall.Error
+		e      error
 		create bool
 		excl   bool
 		trunc  bool
@@ -81,12 +105,12 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
 
 	syscall.ForkLock.RLock()
 	if (create && trunc) || excl {
-		fd, e = syscall.Create(name, flag, perm)
+		fd, e = syscall.Create(name, flag, syscallMode(perm))
 	} else {
 		fd, e = syscall.Open(name, flag)
 		if e != nil && create {
-			var e1 syscall.Error
-			fd, e1 = syscall.Create(name, flag, perm)
+			var e1 error
+			fd, e1 = syscall.Create(name, flag, syscallMode(perm))
 			if e1 == nil {
 				e = nil
 			}
@@ -108,12 +132,16 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
 }
 
 // Close closes the File, rendering it unusable for I/O.
-// It returns an Error, if any.
-func (file *File) Close() Error {
+// It returns an error, if any.
+func (file *File) Close() error {
+	return file.file.close()
+}
+
+func (file *file) close() error {
 	if file == nil || file.fd < 0 {
 		return Ebadfd
 	}
-	var err Error
+	var err error
 	syscall.ForkLock.RLock()
 	if e := syscall.Close(file.fd); e != nil {
 		err = &PathError{"close", file.name, e}
@@ -128,41 +156,41 @@ func (file *File) Close() Error {
 
 // Stat returns the FileInfo structure describing file.
 // It returns the FileInfo and an error, if any.
-func (f *File) Stat() (fi *FileInfo, err Error) {
+func (f *File) Stat() (FileInfo, error) {
 	d, err := dirstat(f)
-	if iserror(err) {
+	if err != nil {
 		return nil, err
 	}
-	return fileInfoFromStat(new(FileInfo), d), err
+	return fileInfoFromStat(d), nil
 }
 
 // Truncate changes the size of the file.
 // It does not change the I/O offset.
-func (f *File) Truncate(size int64) Error {
+func (f *File) Truncate(size int64) error {
 	var d Dir
 	d.Null()
 
 	d.Length = uint64(size)
 
-	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
 		return &PathError{"truncate", f.name, e}
 	}
 	return nil
 }
 
+const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm)
+
 // Chmod changes the mode of the file to mode.
-func (f *File) Chmod(mode uint32) Error {
+func (f *File) Chmod(mode FileMode) error {
 	var d Dir
-	var mask = ^uint32(0777)
 
-	d.Null()
 	odir, e := dirstat(f)
-	if iserror(e) {
+	if e != nil {
 		return &PathError{"chmod", f.name, e}
 	}
-
-	d.Mode = (odir.Mode & mask) | (mode &^ mask)
-	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+	d.Null()
+	d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
+	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
 		return &PathError{"chmod", f.name, e}
 	}
 	return nil
@@ -171,7 +199,7 @@ func (f *File) Chmod(mode uint32) Error {
 // Sync commits the current contents of the file to stable storage.
 // Typically, this means flushing the file system's in-memory copy
 // of recently written data to disk.
-func (f *File) Sync() (err Error) {
+func (f *File) Sync() (err error) {
 	if f == nil {
 		return EINVAL
 	}
@@ -179,7 +207,7 @@ func (f *File) Sync() (err Error) {
 	var d Dir
 	d.Null()
 
-	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+	if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
 		return NewSyscallError("fsync", e)
 	}
 	return nil
@@ -187,26 +215,26 @@ func (f *File) Sync() (err Error) {
 
 // read reads up to len(b) bytes from the File.
 // It returns the number of bytes read and an error, if any.
-func (f *File) read(b []byte) (n int, err syscall.Error) {
+func (f *File) read(b []byte) (n int, err error) {
 	return syscall.Read(f.fd, b)
 }
 
 // pread reads len(b) bytes from the File starting at byte offset off.
 // It returns the number of bytes read and the error, if any.
 // EOF is signaled by a zero count with err set to nil.
-func (f *File) pread(b []byte, off int64) (n int, err syscall.Error) {
+func (f *File) pread(b []byte, off int64) (n int, err error) {
 	return syscall.Pread(f.fd, b, off)
 }
 
 // write writes len(b) bytes to the File.
 // It returns the number of bytes written and an error, if any.
-func (f *File) write(b []byte) (n int, err syscall.Error) {
+func (f *File) write(b []byte) (n int, err error) {
 	return syscall.Write(f.fd, b)
 }
 
 // pwrite writes len(b) bytes to the File starting at byte offset off.
 // It returns the number of bytes written and an error, if any.
-func (f *File) pwrite(b []byte, off int64) (n int, err syscall.Error) {
+func (f *File) pwrite(b []byte, off int64) (n int, err error) {
 	return syscall.Pwrite(f.fd, b, off)
 }
 
@@ -214,58 +242,56 @@ func (f *File) pwrite(b []byte, off int64) (n int, err syscall.Error) {
 // according to whence: 0 means relative to the origin of the file, 1 means
 // relative to the current offset, and 2 means relative to the end.
 // It returns the new offset and an error, if any.
-func (f *File) seek(offset int64, whence int) (ret int64, err syscall.Error) {
+func (f *File) seek(offset int64, whence int) (ret int64, err error) {
 	return syscall.Seek(f.fd, offset, whence)
 }
 
 // Truncate changes the size of the named file.
 // If the file is a symbolic link, it changes the size of the link's target.
-func Truncate(name string, size int64) Error {
+func Truncate(name string, size int64) error {
 	var d Dir
 	d.Null()
 
 	d.Length = uint64(size)
 
-	if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+	if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
 		return &PathError{"truncate", name, e}
 	}
 	return nil
 }
 
 // Remove removes the named file or directory.
-func Remove(name string) Error {
-	if e := syscall.Remove(name); iserror(e) {
+func Remove(name string) error {
+	if e := syscall.Remove(name); e != nil {
 		return &PathError{"remove", name, e}
 	}
 	return nil
 }
 
 // Rename renames a file.
-func Rename(oldname, newname string) Error {
+func Rename(oldname, newname string) error {
 	var d Dir
 	d.Null()
 
 	d.Name = newname
 
-	if e := syscall.Wstat(oldname, pdir(nil, &d)); iserror(e) {
+	if e := syscall.Wstat(oldname, pdir(nil, &d)); e != nil {
 		return &PathError{"rename", oldname, e}
 	}
 	return nil
 }
 
 // Chmod changes the mode of the named file to mode.
-func Chmod(name string, mode uint32) Error {
+func Chmod(name string, mode FileMode) error {
 	var d Dir
-	var mask = ^uint32(0777)
 
-	d.Null()
 	odir, e := dirstat(name)
-	if iserror(e) {
+	if e != nil {
 		return &PathError{"chmod", name, e}
 	}
-
-	d.Mode = (odir.Mode & mask) | (mode &^ mask)
-	if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+	d.Null()
+	d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
+	if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
 		return &PathError{"chmod", name, e}
 	}
 	return nil
@@ -274,27 +300,26 @@ func Chmod(name string, mode uint32) Error {
 // Chtimes changes the access and modification times of the named
 // file, similar to the Unix utime() or utimes() functions.
 //
-// The argument times are in nanoseconds, although the underlying
-// filesystem may truncate or round the values to a more
-// coarse time unit.
-func Chtimes(name string, atimeNs int64, mtimeNs int64) Error {
+// The underlying filesystem may truncate or round the values to a
+// less precise time unit.
+func Chtimes(name string, atime time.Time, mtime time.Time) error {
 	var d Dir
 	d.Null()
 
-	d.Atime = uint32(atimeNs / 1e9)
-	d.Mtime = uint32(mtimeNs / 1e9)
+	d.Atime = uint32(atime.Unix())
+	d.Mtime = uint32(mtime.Unix())
 
-	if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+	if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
 		return &PathError{"chtimes", name, e}
 	}
 	return nil
 }
 
-func Pipe() (r *File, w *File, err Error) {
+func Pipe() (r *File, w *File, err error) {
 	var p [2]int
 
 	syscall.ForkLock.RLock()
-	if e := syscall.Pipe(p[0:]); iserror(e) {
+	if e := syscall.Pipe(p[0:]); e != nil {
 		syscall.ForkLock.RUnlock()
 		return nil, nil, NewSyscallError("pipe", e)
 	}
@@ -306,26 +331,31 @@ func Pipe() (r *File, w *File, err Error) {
 // not supported on Plan 9
 
 // Link creates a hard link.
-func Link(oldname, newname string) Error {
+func Link(oldname, newname string) error {
 	return EPLAN9
 }
 
-func Symlink(oldname, newname string) Error {
+func Symlink(oldname, newname string) error {
 	return EPLAN9
 }
 
-func Readlink(name string) (string, Error) {
+func Readlink(name string) (string, error) {
 	return "", EPLAN9
 }
 
-func Chown(name string, uid, gid int) Error {
+func Chown(name string, uid, gid int) error {
 	return EPLAN9
 }
 
-func Lchown(name string, uid, gid int) Error {
+func Lchown(name string, uid, gid int) error {
 	return EPLAN9
 }
 
-func (f *File) Chown(uid, gid int) Error {
+func (f *File) Chown(uid, gid int) error {
 	return EPLAN9
 }
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+	return "/tmp"
+}
diff --git a/src/pkg/os/file_posix.go b/src/pkg/os/file_posix.go
index 5269149..86ac1ca 100644
--- a/src/pkg/os/file_posix.go
+++ b/src/pkg/os/file_posix.go
@@ -2,17 +2,18 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd windows
+// +build darwin freebsd linux netbsd openbsd windows
 
 package os
 
 import (
 	"syscall"
+	"time"
 )
 
 func sigpipe() // implemented in package runtime
 
-func epipecheck(file *File, e int) {
+func epipecheck(file *File, e error) {
 	if e == syscall.EPIPE {
 		file.nepipe++
 		if file.nepipe >= 10 {
@@ -23,78 +24,45 @@ func epipecheck(file *File, e int) {
 	}
 }
 
-// Remove removes the named file or directory.
-func Remove(name string) Error {
-	// System call interface forces us to know
-	// whether name is a file or directory.
-	// Try both: it is cheaper on average than
-	// doing a Stat plus the right one.
-	e := syscall.Unlink(name)
-	if !iserror(e) {
-		return nil
-	}
-	e1 := syscall.Rmdir(name)
-	if !iserror(e1) {
-		return nil
-	}
-
-	// Both failed: figure out which error to return.
-	// OS X and Linux differ on whether unlink(dir)
-	// returns EISDIR, so can't use that.  However,
-	// both agree that rmdir(file) returns ENOTDIR,
-	// so we can use that to decide which error is real.
-	// Rmdir might also return ENOTDIR if given a bad
-	// file path, like /etc/passwd/foo, but in that case,
-	// both errors will be ENOTDIR, so it's okay to
-	// use the error from unlink.
-	// For windows syscall.ENOTDIR is set
-	// to syscall.ERROR_PATH_NOT_FOUND, hopefully it should
-	// do the trick.
-	if e1 != syscall.ENOTDIR {
-		e = e1
-	}
-	return &PathError{"remove", name, Errno(e)}
-}
-
 // LinkError records an error during a link or symlink or rename
 // system call and the paths that caused it.
 type LinkError struct {
-	Op    string
-	Old   string
-	New   string
-	Error Error
+	Op  string
+	Old string
+	New string
+	Err error
 }
 
-func (e *LinkError) String() string {
-	return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
+func (e *LinkError) Error() string {
+	return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error()
 }
 
 // Link creates a hard link.
-func Link(oldname, newname string) Error {
+func Link(oldname, newname string) error {
 	e := syscall.Link(oldname, newname)
-	if iserror(e) {
-		return &LinkError{"link", oldname, newname, Errno(e)}
+	if e != nil {
+		return &LinkError{"link", oldname, newname, e}
 	}
 	return nil
 }
 
 // Symlink creates a symbolic link.
-func Symlink(oldname, newname string) Error {
+func Symlink(oldname, newname string) error {
 	e := syscall.Symlink(oldname, newname)
-	if iserror(e) {
-		return &LinkError{"symlink", oldname, newname, Errno(e)}
+	if e != nil {
+		return &LinkError{"symlink", oldname, newname, e}
 	}
 	return nil
 }
 
 // Readlink reads the contents of a symbolic link: the destination of
-// the link.  It returns the contents and an Error, if any.
-func Readlink(name string) (string, Error) {
+// the link.  It returns the contents and an error, if any.
+func Readlink(name string) (string, error) {
 	for len := 128; ; len *= 2 {
 		b := make([]byte, len)
 		n, e := syscall.Readlink(name, b)
-		if iserror(e) {
-			return "", &PathError{"readlink", name, Errno(e)}
+		if e != nil {
+			return "", &PathError{"readlink", name, e}
 		}
 		if n < len {
 			return string(b[0:n]), nil
@@ -105,62 +73,78 @@ func Readlink(name string) (string, Error) {
 }
 
 // Rename renames a file.
-func Rename(oldname, newname string) Error {
+func Rename(oldname, newname string) error {
 	e := syscall.Rename(oldname, newname)
-	if iserror(e) {
-		return &LinkError{"rename", oldname, newname, Errno(e)}
+	if e != nil {
+		return &LinkError{"rename", oldname, newname, e}
 	}
 	return nil
 }
 
+// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
+func syscallMode(i FileMode) (o uint32) {
+	o |= uint32(i.Perm())
+	if i&ModeSetuid != 0 {
+		o |= syscall.S_ISUID
+	}
+	if i&ModeSetgid != 0 {
+		o |= syscall.S_ISGID
+	}
+	if i&ModeSticky != 0 {
+		o |= syscall.S_ISVTX
+	}
+	// No mapping for Go's ModeTemporary (plan9 only).
+	return
+}
+
 // Chmod changes the mode of the named file to mode.
 // If the file is a symbolic link, it changes the mode of the link's target.
-func Chmod(name string, mode uint32) Error {
-	if e := syscall.Chmod(name, mode); iserror(e) {
-		return &PathError{"chmod", name, Errno(e)}
+func Chmod(name string, mode FileMode) error {
+	if e := syscall.Chmod(name, syscallMode(mode)); e != nil {
+		return &PathError{"chmod", name, e}
 	}
 	return nil
 }
 
 // Chmod changes the mode of the file to mode.
-func (f *File) Chmod(mode uint32) Error {
-	if e := syscall.Fchmod(f.fd, mode); iserror(e) {
-		return &PathError{"chmod", f.name, Errno(e)}
+func (f *File) Chmod(mode FileMode) error {
+	if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil {
+		return &PathError{"chmod", f.name, e}
 	}
 	return nil
 }
 
 // Chown changes the numeric uid and gid of the named file.
 // If the file is a symbolic link, it changes the uid and gid of the link's target.
-func Chown(name string, uid, gid int) Error {
-	if e := syscall.Chown(name, uid, gid); iserror(e) {
-		return &PathError{"chown", name, Errno(e)}
+func Chown(name string, uid, gid int) error {
+	if e := syscall.Chown(name, uid, gid); e != nil {
+		return &PathError{"chown", name, e}
 	}
 	return nil
 }
 
 // Lchown changes the numeric uid and gid of the named file.
 // If the file is a symbolic link, it changes the uid and gid of the link itself.
-func Lchown(name string, uid, gid int) Error {
-	if e := syscall.Lchown(name, uid, gid); iserror(e) {
-		return &PathError{"lchown", name, Errno(e)}
+func Lchown(name string, uid, gid int) error {
+	if e := syscall.Lchown(name, uid, gid); e != nil {
+		return &PathError{"lchown", name, e}
 	}
 	return nil
 }
 
 // Chown changes the numeric uid and gid of the named file.
-func (f *File) Chown(uid, gid int) Error {
-	if e := syscall.Fchown(f.fd, uid, gid); iserror(e) {
-		return &PathError{"chown", f.name, Errno(e)}
+func (f *File) Chown(uid, gid int) error {
+	if e := syscall.Fchown(f.fd, uid, gid); e != nil {
+		return &PathError{"chown", f.name, e}
 	}
 	return nil
 }
 
 // Truncate changes the size of the file.
 // It does not change the I/O offset.
-func (f *File) Truncate(size int64) Error {
-	if e := syscall.Ftruncate(f.fd, size); iserror(e) {
-		return &PathError{"truncate", f.name, Errno(e)}
+func (f *File) Truncate(size int64) error {
+	if e := syscall.Ftruncate(f.fd, size); e != nil {
+		return &PathError{"truncate", f.name, e}
 	}
 	return nil
 }
@@ -168,11 +152,11 @@ func (f *File) Truncate(size int64) Error {
 // Sync commits the current contents of the file to stable storage.
 // Typically, this means flushing the file system's in-memory copy
 // of recently written data to disk.
-func (file *File) Sync() (err Error) {
-	if file == nil {
+func (f *File) Sync() (err error) {
+	if f == nil {
 		return EINVAL
 	}
-	if e := syscall.Fsync(file.fd); iserror(e) {
+	if e := syscall.Fsync(f.fd); e != nil {
 		return NewSyscallError("fsync", e)
 	}
 	return nil
@@ -181,15 +165,16 @@ func (file *File) Sync() (err Error) {
 // Chtimes changes the access and modification times of the named
 // file, similar to the Unix utime() or utimes() functions.
 //
-// The argument times are in nanoseconds, although the underlying
-// filesystem may truncate or round the values to a more
-// coarse time unit.
-func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
+// The underlying filesystem may truncate or round the values to a
+// less precise time unit.
+func Chtimes(name string, atime time.Time, mtime time.Time) error {
 	var utimes [2]syscall.Timeval
+	atime_ns := atime.Unix()*1e9 + int64(atime.Nanosecond())
+	mtime_ns := mtime.Unix()*1e9 + int64(mtime.Nanosecond())
 	utimes[0] = syscall.NsecToTimeval(atime_ns)
 	utimes[1] = syscall.NsecToTimeval(mtime_ns)
-	if e := syscall.Utimes(name, utimes[0:]); iserror(e) {
-		return &PathError{"chtimes", name, Errno(e)}
+	if e := syscall.Utimes(name, utimes[0:]); e != nil {
+		return &PathError{"chtimes", name, e}
 	}
 	return nil
 }
diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go
index a4470f1..ae5e908 100644
--- a/src/pkg/os/file_unix.go
+++ b/src/pkg/os/file_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package os
 
@@ -13,6 +13,14 @@ import (
 
 // File represents an open file descriptor.
 type File struct {
+	*file
+}
+
+// file is the real representation of *File.
+// The extra level of indirection ensures that no clients of os
+// can overwrite this data, which could cause the finalizer
+// to close the wrong file descriptor.
+type file struct {
 	fd      int
 	name    string
 	dirinfo *dirInfo // nil unless directory being read
@@ -20,11 +28,11 @@ type File struct {
 }
 
 // Fd returns the integer Unix file descriptor referencing the open file.
-func (file *File) Fd() int {
-	if file == nil {
+func (f *File) Fd() int {
+	if f == nil {
 		return -1
 	}
-	return file.fd
+	return f.fd
 }
 
 // NewFile returns a new File with the given file descriptor and name.
@@ -32,8 +40,8 @@ func NewFile(fd int, name string) *File {
 	if fd < 0 {
 		return nil
 	}
-	f := &File{fd: fd, name: name}
-	runtime.SetFinalizer(f, (*File).Close)
+	f := &File{&file{fd: fd, name: name}}
+	runtime.SetFinalizer(f.file, (*file).close)
 	return f
 }
 
@@ -52,16 +60,21 @@ const DevNull = "/dev/null"
 // or Create instead.  It opens the named file with specified flag
 // (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
 // methods on the returned File can be used for I/O.
-// It returns the File and an Error, if any.
-func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
-	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm)
-	if e != 0 {
-		return nil, &PathError{"open", name, Errno(e)}
+// It returns the File and an error, if any.
+func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
+	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
+	if e != nil {
+		return nil, &PathError{"open", name, e}
 	}
 
 	// There's a race here with fork/exec, which we are
-	// content to live with.  See ../syscall/exec.go
-	if syscall.O_CLOEXEC == 0 { // O_CLOEXEC not supported
+	// content to live with.  See ../syscall/exec_unix.go.
+	// On OS X 10.6, the O_CLOEXEC flag is not respected.
+	// On OS X 10.7, the O_CLOEXEC flag works.
+	// Without a cheap & reliable way to detect 10.6 vs 10.7 at
+	// runtime, we just always call syscall.CloseOnExec on Darwin.
+	// Once >=10.7 is prevalent, this extra call can removed.
+	if syscall.O_CLOEXEC == 0 || runtime.GOOS == "darwin" { // O_CLOEXEC not supported
 		syscall.CloseOnExec(r)
 	}
 
@@ -69,14 +82,18 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
 }
 
 // Close closes the File, rendering it unusable for I/O.
-// It returns an Error, if any.
-func (file *File) Close() Error {
+// It returns an error, if any.
+func (f *File) Close() error {
+	return f.file.close()
+}
+
+func (file *file) close() error {
 	if file == nil || file.fd < 0 {
 		return EINVAL
 	}
-	var err Error
-	if e := syscall.Close(file.fd); e != 0 {
-		err = &PathError{"close", file.name, Errno(e)}
+	var err error
+	if e := syscall.Close(file.fd); e != nil {
+		err = &PathError{"close", file.name, e}
 	}
 	file.fd = -1 // so it can't be closed again
 
@@ -87,104 +104,82 @@ func (file *File) Close() Error {
 
 // Stat returns the FileInfo structure describing file.
 // It returns the FileInfo and an error, if any.
-func (file *File) Stat() (fi *FileInfo, err Error) {
+func (f *File) Stat() (fi FileInfo, err error) {
 	var stat syscall.Stat_t
-	e := syscall.Fstat(file.fd, &stat)
-	if e != 0 {
-		return nil, &PathError{"stat", file.name, Errno(e)}
+	err = syscall.Fstat(f.fd, &stat)
+	if err != nil {
+		return nil, &PathError{"stat", f.name, err}
 	}
-	return fileInfoFromStat(file.name, new(FileInfo), &stat, &stat), nil
+	return fileInfoFromStat(&stat, f.name), nil
 }
 
-// Stat returns a FileInfo structure describing the named file and an error, if any.
+// Stat returns a FileInfo describing the named file and an error, if any.
 // If name names a valid symbolic link, the returned FileInfo describes
 // the file pointed at by the link and has fi.FollowedSymlink set to true.
 // If name names an invalid symbolic link, the returned FileInfo describes
 // the link itself and has fi.FollowedSymlink set to false.
-func Stat(name string) (fi *FileInfo, err Error) {
-	var lstat, stat syscall.Stat_t
-	e := syscall.Lstat(name, &lstat)
-	if iserror(e) {
-		return nil, &PathError{"stat", name, Errno(e)}
-	}
-	statp := &lstat
-	if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
-		e := syscall.Stat(name, &stat)
-		if !iserror(e) {
-			statp = &stat
-		}
+func Stat(name string) (fi FileInfo, err error) {
+	var stat syscall.Stat_t
+	err = syscall.Stat(name, &stat)
+	if err != nil {
+		return nil, &PathError{"stat", name, err}
 	}
-	return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
+	return fileInfoFromStat(&stat, name), nil
 }
 
-// Lstat returns the FileInfo structure describing the named file and an
+// Lstat returns a FileInfo describing the named file and an
 // error, if any.  If the file is a symbolic link, the returned FileInfo
 // describes the symbolic link.  Lstat makes no attempt to follow the link.
-func Lstat(name string) (fi *FileInfo, err Error) {
+func Lstat(name string) (fi FileInfo, err error) {
 	var stat syscall.Stat_t
-	e := syscall.Lstat(name, &stat)
-	if iserror(e) {
-		return nil, &PathError{"lstat", name, Errno(e)}
-	}
-	return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
-}
-
-// Readdir reads the contents of the directory associated with file and
-// returns an array of up to n FileInfo structures, as would be returned
-// by Lstat, in directory order. Subsequent calls on the same file will yield
-// further FileInfos.
-//
-// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
-// Readdir returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is os.EOF.
-//
-// If n <= 0, Readdir returns all the FileInfo from the directory in
-// a single slice. In this case, if Readdir succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil os.Error. If it encounters an error before the end of the
-// directory, Readdir returns the FileInfo read until that point
-// and a non-nil error.
-func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
-	dirname := file.name
+	err = syscall.Lstat(name, &stat)
+	if err != nil {
+		return nil, &PathError{"lstat", name, err}
+	}
+	return fileInfoFromStat(&stat, name), nil
+}
+
+func (f *File) readdir(n int) (fi []FileInfo, err error) {
+	dirname := f.name
 	if dirname == "" {
 		dirname = "."
 	}
 	dirname += "/"
-	names, err := file.Readdirnames(n)
+	names, err := f.Readdirnames(n)
 	fi = make([]FileInfo, len(names))
 	for i, filename := range names {
 		fip, err := Lstat(dirname + filename)
-		if fip == nil || err != nil {
-			fi[i].Name = filename // rest is already zeroed out
+		if err == nil {
+			fi[i] = fip
 		} else {
-			fi[i] = *fip
+			fi[i] = &FileStat{name: filename}
 		}
 	}
-	return
+	return fi, err
 }
 
 // read reads up to len(b) bytes from the File.
 // It returns the number of bytes read and an error, if any.
-func (f *File) read(b []byte) (n int, err int) {
+func (f *File) read(b []byte) (n int, err error) {
 	return syscall.Read(f.fd, b)
 }
 
 // pread reads len(b) bytes from the File starting at byte offset off.
 // It returns the number of bytes read and the error, if any.
 // EOF is signaled by a zero count with err set to 0.
-func (f *File) pread(b []byte, off int64) (n int, err int) {
+func (f *File) pread(b []byte, off int64) (n int, err error) {
 	return syscall.Pread(f.fd, b, off)
 }
 
 // write writes len(b) bytes to the File.
 // It returns the number of bytes written and an error, if any.
-func (f *File) write(b []byte) (n int, err int) {
+func (f *File) write(b []byte) (n int, err error) {
 	return syscall.Write(f.fd, b)
 }
 
 // pwrite writes len(b) bytes to the File starting at byte offset off.
 // It returns the number of bytes written and an error, if any.
-func (f *File) pwrite(b []byte, off int64) (n int, err int) {
+func (f *File) pwrite(b []byte, off int64) (n int, err error) {
 	return syscall.Pwrite(f.fd, b, off)
 }
 
@@ -192,19 +187,49 @@ func (f *File) pwrite(b []byte, off int64) (n int, err int) {
 // according to whence: 0 means relative to the origin of the file, 1 means
 // relative to the current offset, and 2 means relative to the end.
 // It returns the new offset and an error, if any.
-func (f *File) seek(offset int64, whence int) (ret int64, err int) {
+func (f *File) seek(offset int64, whence int) (ret int64, err error) {
 	return syscall.Seek(f.fd, offset, whence)
 }
 
 // Truncate changes the size of the named file.
 // If the file is a symbolic link, it changes the size of the link's target.
-func Truncate(name string, size int64) Error {
-	if e := syscall.Truncate(name, size); e != 0 {
-		return &PathError{"truncate", name, Errno(e)}
+func Truncate(name string, size int64) error {
+	if e := syscall.Truncate(name, size); e != nil {
+		return &PathError{"truncate", name, e}
 	}
 	return nil
 }
 
+// Remove removes the named file or directory.
+func Remove(name string) error {
+	// System call interface forces us to know
+	// whether name is a file or directory.
+	// Try both: it is cheaper on average than
+	// doing a Stat plus the right one.
+	e := syscall.Unlink(name)
+	if e == nil {
+		return nil
+	}
+	e1 := syscall.Rmdir(name)
+	if e1 == nil {
+		return nil
+	}
+
+	// Both failed: figure out which error to return.
+	// OS X and Linux differ on whether unlink(dir)
+	// returns EISDIR, so can't use that.  However,
+	// both agree that rmdir(file) returns ENOTDIR,
+	// so we can use that to decide which error is real.
+	// Rmdir might also return ENOTDIR if given a bad
+	// file path, like /etc/passwd/foo, but in that case,
+	// both errors will be ENOTDIR, so it's okay to
+	// use the error from unlink.
+	if e1 != syscall.ENOTDIR {
+		e = e1
+	}
+	return &PathError{"remove", name, e}
+}
+
 // basename removes trailing slashes and the leading directory name from path name
 func basename(name string) string {
 	i := len(name) - 1
@@ -224,14 +249,14 @@ func basename(name string) string {
 }
 
 // Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an Error, if any.
-func Pipe() (r *File, w *File, err Error) {
+// It returns the files and an error, if any.
+func Pipe() (r *File, w *File, err error) {
 	var p [2]int
 
 	// See ../syscall/exec.go for description of lock.
 	syscall.ForkLock.RLock()
 	e := syscall.Pipe(p[0:])
-	if iserror(e) {
+	if e != nil {
 		syscall.ForkLock.RUnlock()
 		return nil, nil, NewSyscallError("pipe", e)
 	}
@@ -241,3 +266,12 @@ func Pipe() (r *File, w *File, err Error) {
 
 	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
 }
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+	dir := Getenv("TMPDIR")
+	if dir == "" {
+		dir = "/tmp"
+	}
+	return dir
+}
diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go
index a3f5b44..7d39fdd 100644
--- a/src/pkg/os/file_windows.go
+++ b/src/pkg/os/file_windows.go
@@ -5,13 +5,23 @@
 package os
 
 import (
+	"io"
 	"runtime"
 	"sync"
 	"syscall"
+	"unicode/utf16"
 )
 
 // File represents an open file descriptor.
 type File struct {
+	*file
+}
+
+// file is the real representation of *File.
+// The extra level of indirection ensures that no clients of os
+// can overwrite this data, which could cause the finalizer
+// to close the wrong file descriptor.
+type file struct {
 	fd      syscall.Handle
 	name    string
 	dirinfo *dirInfo   // nil unless directory being read
@@ -32,8 +42,8 @@ func NewFile(fd syscall.Handle, name string) *File {
 	if fd < 0 {
 		return nil
 	}
-	f := &File{fd: fd, name: name}
-	runtime.SetFinalizer(f, (*File).Close)
+	f := &File{&file{fd: fd, name: name}}
+	runtime.SetFinalizer(f.file, (*file).close)
 	return f
 }
 
@@ -45,12 +55,12 @@ type dirInfo struct {
 
 const DevNull = "NUL"
 
-func (file *File) isdir() bool { return file != nil && file.dirinfo != nil }
+func (f *file) isdir() bool { return f != nil && f.dirinfo != nil }
 
-func openFile(name string, flag int, perm uint32) (file *File, err Error) {
-	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm)
-	if e != 0 {
-		return nil, &PathError{"open", name, Errno(e)}
+func openFile(name string, flag int, perm FileMode) (file *File, err error) {
+	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
+	if e != nil {
+		return nil, &PathError{"open", name, e}
 	}
 
 	// There's a race here with fork/exec, which we are
@@ -62,11 +72,11 @@ func openFile(name string, flag int, perm uint32) (file *File, err Error) {
 	return NewFile(r, name), nil
 }
 
-func openDir(name string) (file *File, err Error) {
+func openDir(name string) (file *File, err error) {
 	d := new(dirInfo)
 	r, e := syscall.FindFirstFile(syscall.StringToUTF16Ptr(name+`\*`), &d.data)
-	if e != 0 {
-		return nil, &PathError{"open", name, Errno(e)}
+	if e != nil {
+		return nil, &PathError{"open", name, e}
 	}
 	f := NewFile(r, name)
 	f.dirinfo = d
@@ -77,8 +87,11 @@ func openDir(name string) (file *File, err Error) {
 // or Create instead.  It opens the named file with specified flag
 // (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
 // methods on the returned File can be used for I/O.
-// It returns the File and an Error, if any.
-func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
+// It returns the File and an error, if any.
+func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
+	if name == "" {
+		return nil, &PathError{"open", name, syscall.ENOENT}
+	}
 	// TODO(brainman): not sure about my logic of assuming it is dir first, then fall back to file
 	r, e := openDir(name)
 	if e == nil {
@@ -96,20 +109,24 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
 }
 
 // Close closes the File, rendering it unusable for I/O.
-// It returns an Error, if any.
-func (file *File) Close() Error {
+// It returns an error, if any.
+func (file *File) Close() error {
+	return file.file.close()
+}
+
+func (file *file) close() error {
 	if file == nil || file.fd < 0 {
 		return EINVAL
 	}
-	var e int
+	var e error
 	if file.isdir() {
 		e = syscall.FindClose(syscall.Handle(file.fd))
 	} else {
 		e = syscall.CloseHandle(syscall.Handle(file.fd))
 	}
-	var err Error
-	if e != 0 {
-		err = &PathError{"close", file.name, Errno(e)}
+	var err error
+	if e != nil {
+		err = &PathError{"close", file.name, e}
 	}
 	file.fd = syscall.InvalidHandle // so it can't be closed again
 
@@ -118,22 +135,7 @@ func (file *File) Close() Error {
 	return err
 }
 
-// Readdir reads the contents of the directory associated with file and
-// returns an array of up to n FileInfo structures, as would be returned
-// by Lstat, in directory order. Subsequent calls on the same file will yield
-// further FileInfos.
-//
-// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
-// Readdir returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is os.EOF.
-//
-// If n <= 0, Readdir returns all the FileInfo from the directory in
-// a single slice. In this case, if Readdir succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil os.Error. If it encounters an error before the end of the
-// directory, Readdir returns the FileInfo read until that point
-// and a non-nil error.
-func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
+func (file *File) readdir(n int) (fi []FileInfo, err error) {
 	if file == nil || file.fd < 0 {
 		return nil, EINVAL
 	}
@@ -151,11 +153,11 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
 	for n != 0 {
 		if file.dirinfo.needdata {
 			e := syscall.FindNextFile(syscall.Handle(file.fd), d)
-			if e != 0 {
+			if e != nil {
 				if e == syscall.ERROR_NO_MORE_FILES {
 					break
 				} else {
-					err = &PathError{"FindNextFile", file.name, Errno(e)}
+					err = &PathError{"FindNextFile", file.name, e}
 					if !wantAll {
 						fi = nil
 					}
@@ -163,24 +165,24 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
 				}
 			}
 		}
-		var f FileInfo
-		setFileInfo(&f, string(syscall.UTF16ToString(d.FileName[0:])), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime)
 		file.dirinfo.needdata = true
-		if f.Name == "." || f.Name == ".." { // Useless names
+		name := string(syscall.UTF16ToString(d.FileName[0:]))
+		if name == "." || name == ".." { // Useless names
 			continue
 		}
+		f := toFileInfo(name, d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime)
 		n--
 		fi = append(fi, f)
 	}
 	if !wantAll && len(fi) == 0 {
-		return fi, EOF
+		return fi, io.EOF
 	}
 	return fi, nil
 }
 
 // read reads up to len(b) bytes from the File.
 // It returns the number of bytes read and an error, if any.
-func (f *File) read(b []byte) (n int, err int) {
+func (f *File) read(b []byte) (n int, err error) {
 	f.l.Lock()
 	defer f.l.Unlock()
 	return syscall.Read(f.fd, b)
@@ -189,11 +191,11 @@ func (f *File) read(b []byte) (n int, err int) {
 // pread reads len(b) bytes from the File starting at byte offset off.
 // It returns the number of bytes read and the error, if any.
 // EOF is signaled by a zero count with err set to 0.
-func (f *File) pread(b []byte, off int64) (n int, err int) {
+func (f *File) pread(b []byte, off int64) (n int, err error) {
 	f.l.Lock()
 	defer f.l.Unlock()
 	curoffset, e := syscall.Seek(f.fd, 0, 1)
-	if e != 0 {
+	if e != nil {
 		return 0, e
 	}
 	defer syscall.Seek(f.fd, curoffset, 0)
@@ -203,15 +205,15 @@ func (f *File) pread(b []byte, off int64) (n int, err int) {
 	}
 	var done uint32
 	e = syscall.ReadFile(syscall.Handle(f.fd), b, &done, &o)
-	if e != 0 {
+	if e != nil {
 		return 0, e
 	}
-	return int(done), 0
+	return int(done), nil
 }
 
 // write writes len(b) bytes to the File.
 // It returns the number of bytes written and an error, if any.
-func (f *File) write(b []byte) (n int, err int) {
+func (f *File) write(b []byte) (n int, err error) {
 	f.l.Lock()
 	defer f.l.Unlock()
 	return syscall.Write(f.fd, b)
@@ -219,11 +221,11 @@ func (f *File) write(b []byte) (n int, err int) {
 
 // pwrite writes len(b) bytes to the File starting at byte offset off.
 // It returns the number of bytes written and an error, if any.
-func (f *File) pwrite(b []byte, off int64) (n int, err int) {
+func (f *File) pwrite(b []byte, off int64) (n int, err error) {
 	f.l.Lock()
 	defer f.l.Unlock()
 	curoffset, e := syscall.Seek(f.fd, 0, 1)
-	if e != 0 {
+	if e != nil {
 		return 0, e
 	}
 	defer syscall.Seek(f.fd, curoffset, 0)
@@ -233,17 +235,17 @@ func (f *File) pwrite(b []byte, off int64) (n int, err int) {
 	}
 	var done uint32
 	e = syscall.WriteFile(syscall.Handle(f.fd), b, &done, &o)
-	if e != 0 {
+	if e != nil {
 		return 0, e
 	}
-	return int(done), 0
+	return int(done), nil
 }
 
 // seek sets the offset for the next Read or Write on file to offset, interpreted
 // according to whence: 0 means relative to the origin of the file, 1 means
 // relative to the current offset, and 2 means relative to the end.
 // It returns the new offset and an error, if any.
-func (f *File) seek(offset int64, whence int) (ret int64, err int) {
+func (f *File) seek(offset int64, whence int) (ret int64, err error) {
 	f.l.Lock()
 	defer f.l.Unlock()
 	return syscall.Seek(f.fd, offset, whence)
@@ -251,7 +253,7 @@ func (f *File) seek(offset int64, whence int) (ret int64, err int) {
 
 // Truncate changes the size of the named file.
 // If the file is a symbolic link, it changes the size of the link's target.
-func Truncate(name string, size int64) Error {
+func Truncate(name string, size int64) error {
 	f, e := OpenFile(name, O_WRONLY|O_CREATE, 0666)
 	if e != nil {
 		return e
@@ -264,15 +266,44 @@ func Truncate(name string, size int64) Error {
 	return nil
 }
 
+// Remove removes the named file or directory.
+func Remove(name string) error {
+	p := &syscall.StringToUTF16(name)[0]
+
+	// Go file interface forces us to know whether
+	// name is a file or directory. Try both.
+	e := syscall.DeleteFile(p)
+	if e == nil {
+		return nil
+	}
+	e1 := syscall.RemoveDirectory(p)
+	if e1 == nil {
+		return nil
+	}
+
+	// Both failed: figure out which error to return.
+	if e1 != e {
+		a, e2 := syscall.GetFileAttributes(p)
+		if e2 != nil {
+			e = e2
+		} else {
+			if a&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
+				e = e1
+			}
+		}
+	}
+	return &PathError{"remove", name, e}
+}
+
 // Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an Error, if any.
-func Pipe() (r *File, w *File, err Error) {
+// It returns the files and an error, if any.
+func Pipe() (r *File, w *File, err error) {
 	var p [2]syscall.Handle
 
 	// See ../syscall/exec.go for description of lock.
 	syscall.ForkLock.RLock()
 	e := syscall.Pipe(p[0:])
-	if iserror(e) {
+	if e != nil {
 		syscall.ForkLock.RUnlock()
 		return nil, nil, NewSyscallError("pipe", e)
 	}
@@ -282,3 +313,21 @@ func Pipe() (r *File, w *File, err Error) {
 
 	return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
 }
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+	const pathSep = '\\'
+	dirw := make([]uint16, syscall.MAX_PATH)
+	n, _ := syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
+	if n > uint32(len(dirw)) {
+		dirw = make([]uint16, n)
+		n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
+		if n > uint32(len(dirw)) {
+			n = 0
+		}
+	}
+	if n > 0 && dirw[n-1] == pathSep {
+		n--
+	}
+	return string(utf16.Decode(dirw[0:n]))
+}
diff --git a/src/pkg/os/getwd.go b/src/pkg/os/getwd.go
index 4c142ad..a0d3c99 100644
--- a/src/pkg/os/getwd.go
+++ b/src/pkg/os/getwd.go
@@ -12,7 +12,7 @@ import (
 // current directory.  If the current directory can be
 // reached via multiple paths (due to symbolic links),
 // Getwd may return any one of them.
-func Getwd() (string, Error) {
+func Getwd() (pwd string, err error) {
 	// If the operating system provides a Getwd call, use it.
 	if syscall.ImplementsGetwd {
 		s, e := syscall.Getwd()
@@ -27,10 +27,10 @@ func Getwd() (string, Error) {
 
 	// Clumsy but widespread kludge:
 	// if $PWD is set and matches ".", use it.
-	pwd := Getenv("PWD")
+	pwd = Getenv("PWD")
 	if len(pwd) > 0 && pwd[0] == '/' {
 		d, err := Stat(pwd)
-		if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino {
+		if err == nil && dot.(*FileStat).SameFile(d.(*FileStat)) {
 			return pwd, nil
 		}
 	}
@@ -42,7 +42,7 @@ func Getwd() (string, Error) {
 		// Can't stat root - no hope.
 		return "", err
 	}
-	if root.Dev == dot.Dev && root.Ino == dot.Ino {
+	if root.(*FileStat).SameFile(dot.(*FileStat)) {
 		return "/", nil
 	}
 
@@ -67,7 +67,7 @@ func Getwd() (string, Error) {
 			}
 			for _, name := range names {
 				d, _ := Lstat(parent + "/" + name)
-				if d.Dev == dot.Dev && d.Ino == dot.Ino {
+				if d.(*FileStat).SameFile(dot.(*FileStat)) {
 					pwd = "/" + name + pwd
 					goto Found
 				}
@@ -82,7 +82,7 @@ func Getwd() (string, Error) {
 			return "", err
 		}
 		fd.Close()
-		if pd.Dev == root.Dev && pd.Ino == root.Ino {
+		if pd.(*FileStat).SameFile(root.(*FileStat)) {
 			break
 		}
 		// Set up for next round.
diff --git a/src/pkg/os/inotify/Makefile b/src/pkg/os/inotify/Makefile
deleted file mode 100644
index 90e18da..0000000
--- a/src/pkg/os/inotify/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=os/inotify
-
-GOFILES_linux=\
-	inotify_linux.go\
-
-GOFILES+=$(GOFILES_$(GOOS))
-
-include ../../../Make.pkg
diff --git a/src/pkg/os/inotify/inotify_linux.go b/src/pkg/os/inotify/inotify_linux.go
deleted file mode 100644
index 99fa516..0000000
--- a/src/pkg/os/inotify/inotify_linux.go
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright 2010 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 inotify implements a wrapper for the Linux inotify system.
-
-Example:
-    watcher, err := inotify.NewWatcher()
-    if err != nil {
-        log.Fatal(err)
-    }
-    err = watcher.Watch("/tmp")
-    if err != nil {
-        log.Fatal(err)
-    }
-    for {
-        select {
-        case ev := <-watcher.Event:
-            log.Println("event:", ev)
-        case err := <-watcher.Error:
-            log.Println("error:", err)
-        }
-    }
-
-*/
-package inotify
-
-import (
-	"fmt"
-	"os"
-	"strings"
-	"syscall"
-	"unsafe"
-)
-
-type Event struct {
-	Mask   uint32 // Mask of events
-	Cookie uint32 // Unique cookie associating related events (for rename(2))
-	Name   string // File name (optional)
-}
-
-type watch struct {
-	wd    uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
-	flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
-}
-
-type Watcher struct {
-	fd       int               // File descriptor (as returned by the inotify_init() syscall)
-	watches  map[string]*watch // Map of inotify watches (key: path)
-	paths    map[int]string    // Map of watched paths (key: watch descriptor)
-	Error    chan os.Error     // Errors are sent on this channel
-	Event    chan *Event       // Events are returned on this channel
-	done     chan bool         // Channel for sending a "quit message" to the reader goroutine
-	isClosed bool              // Set to true when Close() is first called
-}
-
-// NewWatcher creates and returns a new inotify instance using inotify_init(2)
-func NewWatcher() (*Watcher, os.Error) {
-	fd, errno := syscall.InotifyInit()
-	if fd == -1 {
-		return nil, os.NewSyscallError("inotify_init", errno)
-	}
-	w := &Watcher{
-		fd:      fd,
-		watches: make(map[string]*watch),
-		paths:   make(map[int]string),
-		Event:   make(chan *Event),
-		Error:   make(chan os.Error),
-		done:    make(chan bool, 1),
-	}
-
-	go w.readEvents()
-	return w, nil
-}
-
-// Close closes an inotify watcher instance
-// It sends a message to the reader goroutine to quit and removes all watches
-// associated with the inotify instance
-func (w *Watcher) Close() os.Error {
-	if w.isClosed {
-		return nil
-	}
-	w.isClosed = true
-
-	// Send "quit" message to the reader goroutine
-	w.done <- true
-	for path := range w.watches {
-		w.RemoveWatch(path)
-	}
-
-	return nil
-}
-
-// AddWatch adds path to the watched file set.
-// The flags are interpreted as described in inotify_add_watch(2).
-func (w *Watcher) AddWatch(path string, flags uint32) os.Error {
-	if w.isClosed {
-		return os.NewError("inotify instance already closed")
-	}
-
-	watchEntry, found := w.watches[path]
-	if found {
-		watchEntry.flags |= flags
-		flags |= syscall.IN_MASK_ADD
-	}
-	wd, errno := syscall.InotifyAddWatch(w.fd, path, flags)
-	if wd == -1 {
-		return &os.PathError{"inotify_add_watch", path, os.Errno(errno)}
-	}
-
-	if !found {
-		w.watches[path] = &watch{wd: uint32(wd), flags: flags}
-		w.paths[wd] = path
-	}
-	return nil
-}
-
-// Watch adds path to the watched file set, watching all events.
-func (w *Watcher) Watch(path string) os.Error {
-	return w.AddWatch(path, IN_ALL_EVENTS)
-}
-
-// RemoveWatch removes path from the watched file set.
-func (w *Watcher) RemoveWatch(path string) os.Error {
-	watch, ok := w.watches[path]
-	if !ok {
-		return os.NewError(fmt.Sprintf("can't remove non-existent inotify watch for: %s", path))
-	}
-	success, errno := syscall.InotifyRmWatch(w.fd, watch.wd)
-	if success == -1 {
-		return os.NewSyscallError("inotify_rm_watch", errno)
-	}
-	w.watches[path] = nil, false
-	return nil
-}
-
-// readEvents reads from the inotify file descriptor, converts the
-// received events into Event objects and sends them via the Event channel
-func (w *Watcher) readEvents() {
-	var (
-		buf   [syscall.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
-		n     int                                     // Number of bytes read with read()
-		errno int                                     // Syscall errno
-	)
-
-	for {
-		n, errno = syscall.Read(w.fd, buf[0:])
-		// See if there is a message on the "done" channel
-		var done bool
-		select {
-		case done = <-w.done:
-		default:
-		}
-
-		// If EOF or a "done" message is received
-		if n == 0 || done {
-			errno := syscall.Close(w.fd)
-			if errno == -1 {
-				w.Error <- os.NewSyscallError("close", errno)
-			}
-			close(w.Event)
-			close(w.Error)
-			return
-		}
-		if n < 0 {
-			w.Error <- os.NewSyscallError("read", errno)
-			continue
-		}
-		if n < syscall.SizeofInotifyEvent {
-			w.Error <- os.NewError("inotify: short read in readEvents()")
-			continue
-		}
-
-		var offset uint32 = 0
-		// We don't know how many events we just read into the buffer
-		// While the offset points to at least one whole event...
-		for offset <= uint32(n-syscall.SizeofInotifyEvent) {
-			// Point "raw" to the event in the buffer
-			raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
-			event := new(Event)
-			event.Mask = uint32(raw.Mask)
-			event.Cookie = uint32(raw.Cookie)
-			nameLen := uint32(raw.Len)
-			// If the event happened to the watched directory or the watched file, the kernel
-			// doesn't append the filename to the event, but we would like to always fill the
-			// the "Name" field with a valid filename. We retrieve the path of the watch from
-			// the "paths" map.
-			event.Name = w.paths[int(raw.Wd)]
-			if nameLen > 0 {
-				// Point "bytes" at the first byte of the filename
-				bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))
-				// The filename is padded with NUL bytes. TrimRight() gets rid of those.
-				event.Name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
-			}
-			// Send the event on the events channel
-			w.Event <- event
-
-			// Move to the next event in the buffer
-			offset += syscall.SizeofInotifyEvent + nameLen
-		}
-	}
-}
-
-// String formats the event e in the form
-// "filename: 0xEventMask = IN_ACCESS|IN_ATTRIB_|..."
-func (e *Event) String() string {
-	var events string = ""
-
-	m := e.Mask
-	for _, b := range eventBits {
-		if m&b.Value != 0 {
-			m &^= b.Value
-			events += "|" + b.Name
-		}
-	}
-
-	if m != 0 {
-		events += fmt.Sprintf("|%#x", m)
-	}
-	if len(events) > 0 {
-		events = " == " + events[1:]
-	}
-
-	return fmt.Sprintf("%q: %#x%s", e.Name, e.Mask, events)
-}
-
-const (
-	// Options for inotify_init() are not exported
-	// IN_CLOEXEC    uint32 = syscall.IN_CLOEXEC
-	// IN_NONBLOCK   uint32 = syscall.IN_NONBLOCK
-
-	// Options for AddWatch
-	IN_DONT_FOLLOW uint32 = syscall.IN_DONT_FOLLOW
-	IN_ONESHOT     uint32 = syscall.IN_ONESHOT
-	IN_ONLYDIR     uint32 = syscall.IN_ONLYDIR
-
-	// The "IN_MASK_ADD" option is not exported, as AddWatch
-	// adds it automatically, if there is already a watch for the given path
-	// IN_MASK_ADD      uint32 = syscall.IN_MASK_ADD
-
-	// Events
-	IN_ACCESS        uint32 = syscall.IN_ACCESS
-	IN_ALL_EVENTS    uint32 = syscall.IN_ALL_EVENTS
-	IN_ATTRIB        uint32 = syscall.IN_ATTRIB
-	IN_CLOSE         uint32 = syscall.IN_CLOSE
-	IN_CLOSE_NOWRITE uint32 = syscall.IN_CLOSE_NOWRITE
-	IN_CLOSE_WRITE   uint32 = syscall.IN_CLOSE_WRITE
-	IN_CREATE        uint32 = syscall.IN_CREATE
-	IN_DELETE        uint32 = syscall.IN_DELETE
-	IN_DELETE_SELF   uint32 = syscall.IN_DELETE_SELF
-	IN_MODIFY        uint32 = syscall.IN_MODIFY
-	IN_MOVE          uint32 = syscall.IN_MOVE
-	IN_MOVED_FROM    uint32 = syscall.IN_MOVED_FROM
-	IN_MOVED_TO      uint32 = syscall.IN_MOVED_TO
-	IN_MOVE_SELF     uint32 = syscall.IN_MOVE_SELF
-	IN_OPEN          uint32 = syscall.IN_OPEN
-
-	// Special events
-	IN_ISDIR      uint32 = syscall.IN_ISDIR
-	IN_IGNORED    uint32 = syscall.IN_IGNORED
-	IN_Q_OVERFLOW uint32 = syscall.IN_Q_OVERFLOW
-	IN_UNMOUNT    uint32 = syscall.IN_UNMOUNT
-)
-
-var eventBits = []struct {
-	Value uint32
-	Name  string
-}{
-	{IN_ACCESS, "IN_ACCESS"},
-	{IN_ATTRIB, "IN_ATTRIB"},
-	{IN_CLOSE, "IN_CLOSE"},
-	{IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE"},
-	{IN_CLOSE_WRITE, "IN_CLOSE_WRITE"},
-	{IN_CREATE, "IN_CREATE"},
-	{IN_DELETE, "IN_DELETE"},
-	{IN_DELETE_SELF, "IN_DELETE_SELF"},
-	{IN_MODIFY, "IN_MODIFY"},
-	{IN_MOVE, "IN_MOVE"},
-	{IN_MOVED_FROM, "IN_MOVED_FROM"},
-	{IN_MOVED_TO, "IN_MOVED_TO"},
-	{IN_MOVE_SELF, "IN_MOVE_SELF"},
-	{IN_OPEN, "IN_OPEN"},
-	{IN_ISDIR, "IN_ISDIR"},
-	{IN_IGNORED, "IN_IGNORED"},
-	{IN_Q_OVERFLOW, "IN_Q_OVERFLOW"},
-	{IN_UNMOUNT, "IN_UNMOUNT"},
-}
diff --git a/src/pkg/os/inotify/inotify_linux_test.go b/src/pkg/os/inotify/inotify_linux_test.go
deleted file mode 100644
index aa72604..0000000
--- a/src/pkg/os/inotify/inotify_linux_test.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2010 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 inotify
-
-import (
-	"os"
-	"time"
-	"testing"
-)
-
-func TestInotifyEvents(t *testing.T) {
-	// Create an inotify watcher instance and initialize it
-	watcher, err := NewWatcher()
-	if err != nil {
-		t.Fatalf("NewWatcher() failed: %s", err)
-	}
-
-	// Add a watch for "_test"
-	err = watcher.Watch("_test")
-	if err != nil {
-		t.Fatalf("Watcher.Watch() failed: %s", err)
-	}
-
-	// Receive errors on the error channel on a separate goroutine
-	go func() {
-		for err := range watcher.Error {
-			t.Fatalf("error received: %s", err)
-		}
-	}()
-
-	const testFile string = "_test/TestInotifyEvents.testfile"
-
-	// Receive events on the event channel on a separate goroutine
-	eventstream := watcher.Event
-	var eventsReceived = 0
-	done := make(chan bool)
-	go func() {
-		for event := range eventstream {
-			// Only count relevant events
-			if event.Name == testFile {
-				eventsReceived++
-				t.Logf("event received: %s", event)
-			} else {
-				t.Logf("unexpected event received: %s", event)
-			}
-		}
-		done <- true
-	}()
-
-	// Create a file
-	// This should add at least one event to the inotify event queue
-	_, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
-	if err != nil {
-		t.Fatalf("creating test file failed: %s", err)
-	}
-
-	// We expect this event to be received almost immediately, but let's wait 1 s to be sure
-	time.Sleep(1000e6) // 1000 ms
-	if eventsReceived == 0 {
-		t.Fatal("inotify event hasn't been received after 1 second")
-	}
-
-	// Try closing the inotify instance
-	t.Log("calling Close()")
-	watcher.Close()
-	t.Log("waiting for the event channel to become closed...")
-	select {
-	case <-done:
-		t.Log("event channel closed")
-	case <-time.After(1e9):
-		t.Fatal("event stream was not closed after 1 second")
-	}
-}
-
-func TestInotifyClose(t *testing.T) {
-	watcher, _ := NewWatcher()
-	watcher.Close()
-
-	done := false
-	go func() {
-		watcher.Close()
-		done = true
-	}()
-
-	time.Sleep(50e6) // 50 ms
-	if !done {
-		t.Fatal("double Close() test failed: second Close() call didn't return")
-	}
-
-	err := watcher.Watch("_test")
-	if err == nil {
-		t.Fatal("expected error on Watch() after Close(), got nil")
-	}
-}
diff --git a/src/pkg/os/mksignals.sh b/src/pkg/os/mksignals.sh
new file mode 100755
index 0000000..401e39f
--- /dev/null
+++ b/src/pkg/os/mksignals.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+for targ in \
+	darwin_386 \
+	darwin_amd64 \
+	freebsd_386 \
+	freebsd_amd64 \
+	linux_386 \
+	linux_amd64 \
+	linux_arm \
+	netbsd_386 \
+	netbsd_amd64 \
+	openbsd_386 \
+	openbsd_amd64 \
+; do
+	./mkunixsignals.sh ../syscall/zerrors_$targ.go |gofmt >zsignal_$targ.go
+done
+
+for targ in \
+	windows_386 \
+	windows_amd64 \
+; do
+	./mkunixsignals.sh ../syscall/ztypes_windows.go |gofmt >zsignal_$targ.go
+done
diff --git a/src/pkg/os/mkunixsignals.sh b/src/pkg/os/mkunixsignals.sh
index df32362..ec62f1d 100755
--- a/src/pkg/os/mkunixsignals.sh
+++ b/src/pkg/os/mkunixsignals.sh
@@ -3,8 +3,11 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-echo '// ./mkunixsignals.sh' "$1"
-echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'
+echo '// MACHINE GENERATED; DO NOT EDIT'
+echo '// To regenerate, run'
+echo '//	./mksignals.sh'
+echo '// which, for this file, will run'
+echo '//	./mkunixsignals.sh' "$1"
 echo
 
 cat <<EOH
diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go
index f9baceb..ec8c509 100644
--- a/src/pkg/os/os_test.go
+++ b/src/pkg/os/os_test.go
@@ -11,14 +11,15 @@ import (
 	"io/ioutil"
 	. "os"
 	"path/filepath"
+	"runtime"
 	"strings"
-	"syscall"
 	"testing"
+	"time"
 )
 
 var dot = []string{
 	"dir_unix.go",
-	"env_unix.go",
+	"env.go",
 	"error.go",
 	"file.go",
 	"os_test.go",
@@ -34,7 +35,7 @@ type sysDir struct {
 }
 
 var sysdir = func() (sd *sysDir) {
-	switch syscall.OS {
+	switch runtime.GOOS {
 	case "windows":
 		sd = &sysDir{
 			Getenv("SystemRoot") + "\\system32\\drivers\\etc",
@@ -77,7 +78,7 @@ func size(name string, t *testing.T) int64 {
 	for {
 		n, e := file.Read(buf[0:])
 		len += n
-		if e == EOF {
+		if e == io.EOF {
 			break
 		}
 		if e != nil {
@@ -88,7 +89,7 @@ func size(name string, t *testing.T) int64 {
 }
 
 func equal(name1, name2 string) (r bool) {
-	switch syscall.OS {
+	switch runtime.GOOS {
 	case "windows":
 		r = strings.ToLower(name1) == strings.ToLower(name2)
 	default:
@@ -102,7 +103,7 @@ func newFile(testName string, t *testing.T) (f *File) {
 	// On Unix, override $TMPDIR in case the user
 	// has it set to an NFS-mounted directory.
 	dir := ""
-	if syscall.OS != "windows" {
+	if runtime.GOOS != "windows" {
 		dir = "/tmp"
 	}
 	f, err := ioutil.TempFile(dir, "_Go_"+testName)
@@ -121,12 +122,12 @@ func TestStat(t *testing.T) {
 	if err != nil {
 		t.Fatal("stat failed:", err)
 	}
-	if !equal(sfname, dir.Name) {
-		t.Error("name should be ", sfname, "; is", dir.Name)
+	if !equal(sfname, dir.Name()) {
+		t.Error("name should be ", sfname, "; is", dir.Name())
 	}
 	filesize := size(path, t)
-	if dir.Size != filesize {
-		t.Error("size should be", filesize, "; is", dir.Size)
+	if dir.Size() != filesize {
+		t.Error("size should be", filesize, "; is", dir.Size())
 	}
 }
 
@@ -141,12 +142,12 @@ func TestFstat(t *testing.T) {
 	if err2 != nil {
 		t.Fatal("fstat failed:", err2)
 	}
-	if !equal(sfname, dir.Name) {
-		t.Error("name should be ", sfname, "; is", dir.Name)
+	if !equal(sfname, dir.Name()) {
+		t.Error("name should be ", sfname, "; is", dir.Name())
 	}
 	filesize := size(path, t)
-	if dir.Size != filesize {
-		t.Error("size should be", filesize, "; is", dir.Size)
+	if dir.Size() != filesize {
+		t.Error("size should be", filesize, "; is", dir.Size())
 	}
 }
 
@@ -156,12 +157,33 @@ func TestLstat(t *testing.T) {
 	if err != nil {
 		t.Fatal("lstat failed:", err)
 	}
-	if !equal(sfname, dir.Name) {
-		t.Error("name should be ", sfname, "; is", dir.Name)
+	if !equal(sfname, dir.Name()) {
+		t.Error("name should be ", sfname, "; is", dir.Name())
 	}
 	filesize := size(path, t)
-	if dir.Size != filesize {
-		t.Error("size should be", filesize, "; is", dir.Size)
+	if dir.Size() != filesize {
+		t.Error("size should be", filesize, "; is", dir.Size())
+	}
+}
+
+// Read with length 0 should not return EOF.
+func TestRead0(t *testing.T) {
+	path := sfdir + "/" + sfname
+	f, err := Open(path)
+	if err != nil {
+		t.Fatal("open failed:", err)
+	}
+	defer f.Close()
+
+	b := make([]byte, 0)
+	n, err := f.Read(b)
+	if n != 0 || err != nil {
+		t.Errorf("Read(0) = %d, %v, want 0, nil", n, err)
+	}
+	b = make([]byte, 100)
+	n, err = f.Read(b)
+	if n <= 0 || err != nil {
+		t.Errorf("Read(100) = %d, %v, want >0, nil", n, err)
 	}
 }
 
@@ -207,7 +229,7 @@ func testReaddir(dir string, contents []string, t *testing.T) {
 	for _, m := range contents {
 		found := false
 		for _, n := range s {
-			if equal(m, n.Name) {
+			if equal(m, n.Name()) {
 				if found {
 					t.Error("present twice:", m)
 				}
@@ -236,7 +258,7 @@ func smallReaddirnames(file *File, length int, t *testing.T) []string {
 	count := 0
 	for {
 		d, err := file.Readdirnames(1)
-		if err == EOF {
+		if err == io.EOF {
 			break
 		}
 		if err != nil {
@@ -256,7 +278,7 @@ func smallReaddirnames(file *File, length int, t *testing.T) []string {
 func TestReaddirnamesOneAtATime(t *testing.T) {
 	// big directory that doesn't change often.
 	dir := "/usr/bin"
-	switch syscall.OS {
+	switch runtime.GOOS {
 	case "windows":
 		dir = Getenv("SystemRoot") + "\\system32"
 	case "plan9":
@@ -307,14 +329,14 @@ func TestReaddirNValues(t *testing.T) {
 
 	var d *File
 	openDir := func() {
-		var err Error
+		var err error
 		d, err = Open(dir)
 		if err != nil {
 			t.Fatalf("Open directory: %v", err)
 		}
 	}
 
-	readDirExpect := func(n, want int, wantErr Error) {
+	readDirExpect := func(n, want int, wantErr error) {
 		fi, err := d.Readdir(n)
 		if err != wantErr {
 			t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr)
@@ -324,7 +346,7 @@ func TestReaddirNValues(t *testing.T) {
 		}
 	}
 
-	readDirNamesExpect := func(n, want int, wantErr Error) {
+	readDirNamesExpect := func(n, want int, wantErr error) {
 		fi, err := d.Readdirnames(n)
 		if err != wantErr {
 			t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr)
@@ -334,7 +356,7 @@ func TestReaddirNValues(t *testing.T) {
 		}
 	}
 
-	for _, fn := range []func(int, int, Error){readDirExpect, readDirNamesExpect} {
+	for _, fn := range []func(int, int, error){readDirExpect, readDirNamesExpect} {
 		// Test the slurp case
 		openDir()
 		fn(0, 105, nil)
@@ -353,14 +375,14 @@ func TestReaddirNValues(t *testing.T) {
 		fn(1, 1, nil)
 		fn(2, 2, nil)
 		fn(105, 102, nil) // and tests buffer >100 case
-		fn(3, 0, EOF)
+		fn(3, 0, io.EOF)
 		d.Close()
 	}
 }
 
 func TestHardLink(t *testing.T) {
 	// Hardlinks are not supported under windows or Plan 9.
-	if syscall.OS == "windows" || syscall.OS == "plan9" {
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
 		return
 	}
 	from, to := "hardlinktestfrom", "hardlinktestto"
@@ -386,14 +408,14 @@ func TestHardLink(t *testing.T) {
 	if err != nil {
 		t.Fatalf("stat %q failed: %v", from, err)
 	}
-	if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino {
+	if !tostat.(*FileStat).SameFile(fromstat.(*FileStat)) {
 		t.Errorf("link %q, %q did not create hard link", to, from)
 	}
 }
 
 func TestSymLink(t *testing.T) {
 	// Symlinks are not supported under windows or Plan 9.
-	if syscall.OS == "windows" || syscall.OS == "plan9" {
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
 		return
 	}
 	from, to := "symlinktestfrom", "symlinktestto"
@@ -411,32 +433,32 @@ func TestSymLink(t *testing.T) {
 		t.Fatalf("symlink %q, %q failed: %v", to, from, err)
 	}
 	defer Remove(from)
-	tostat, err := Stat(to)
+	tostat, err := Lstat(to)
 	if err != nil {
 		t.Fatalf("stat %q failed: %v", to, err)
 	}
-	if tostat.FollowedSymlink {
-		t.Fatalf("stat %q claims to have followed a symlink", to)
+	if tostat.Mode()&ModeSymlink != 0 {
+		t.Fatalf("stat %q claims to have found a symlink", to)
 	}
 	fromstat, err := Stat(from)
 	if err != nil {
 		t.Fatalf("stat %q failed: %v", from, err)
 	}
-	if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino {
+	if !tostat.(*FileStat).SameFile(fromstat.(*FileStat)) {
 		t.Errorf("symlink %q, %q did not create symlink", to, from)
 	}
 	fromstat, err = Lstat(from)
 	if err != nil {
 		t.Fatalf("lstat %q failed: %v", from, err)
 	}
-	if !fromstat.IsSymlink() {
+	if fromstat.Mode()&ModeSymlink == 0 {
 		t.Fatalf("symlink %q, %q did not create symlink", to, from)
 	}
 	fromstat, err = Stat(from)
 	if err != nil {
 		t.Fatalf("stat %q failed: %v", from, err)
 	}
-	if !fromstat.FollowedSymlink {
+	if fromstat.Mode()&ModeSymlink != 0 {
 		t.Fatalf("stat %q did not follow symlink", from)
 	}
 	s, err := Readlink(from)
@@ -455,7 +477,7 @@ func TestSymLink(t *testing.T) {
 
 func TestLongSymlink(t *testing.T) {
 	// Symlinks are not supported under windows or Plan 9.
-	if syscall.OS == "windows" || syscall.OS == "plan9" {
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
 		return
 	}
 	s := "0123456789abcdef"
@@ -525,7 +547,7 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
 func TestStartProcess(t *testing.T) {
 	var dir, cmd, le string
 	var args []string
-	if syscall.OS == "windows" {
+	if runtime.GOOS == "windows" {
 		le = "\r\n"
 		cmd = Getenv("COMSPEC")
 		dir = Getenv("SystemRoot")
@@ -544,19 +566,19 @@ func TestStartProcess(t *testing.T) {
 	exec(t, cmddir, cmdbase, args, filepath.Clean(cmddir)+le)
 }
 
-func checkMode(t *testing.T, path string, mode uint32) {
+func checkMode(t *testing.T, path string, mode FileMode) {
 	dir, err := Stat(path)
 	if err != nil {
 		t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
 	}
-	if dir.Mode&0777 != mode {
-		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode, mode)
+	if dir.Mode()&0777 != mode {
+		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode)
 	}
 }
 
 func TestChmod(t *testing.T) {
 	// Chmod is not supported under windows.
-	if syscall.OS == "windows" {
+	if runtime.GOOS == "windows" {
 		return
 	}
 	f := newFile("TestChmod", t)
@@ -574,73 +596,13 @@ func TestChmod(t *testing.T) {
 	checkMode(t, f.Name(), 0123)
 }
 
-func checkUidGid(t *testing.T, path string, uid, gid int) {
-	dir, err := Stat(path)
-	if err != nil {
-		t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err)
-	}
-	if dir.Uid != uid {
-		t.Errorf("Stat %q: uid %d want %d", path, dir.Uid, uid)
-	}
-	if dir.Gid != gid {
-		t.Errorf("Stat %q: gid %d want %d", path, dir.Gid, gid)
-	}
-}
-
-func TestChown(t *testing.T) {
-	// Chown is not supported under windows or Plan 9.
-	// Plan9 provides a native ChownPlan9 version instead.
-	if syscall.OS == "windows" || syscall.OS == "plan9" {
-		return
-	}
-	// Use TempDir() to make sure we're on a local file system,
-	// so that the group ids returned by Getgroups will be allowed
-	// on the file.  On NFS, the Getgroups groups are
-	// basically useless.
-	f := newFile("TestChown", t)
-	defer Remove(f.Name())
-	defer f.Close()
-	dir, err := f.Stat()
-	if err != nil {
-		t.Fatalf("stat %s: %s", f.Name(), err)
-	}
-
-	// Can't change uid unless root, but can try
-	// changing the group id.  First try our current group.
-	gid := Getgid()
-	t.Log("gid:", gid)
-	if err = Chown(f.Name(), -1, gid); err != nil {
-		t.Fatalf("chown %s -1 %d: %s", f.Name(), gid, err)
-	}
-	checkUidGid(t, f.Name(), dir.Uid, gid)
-
-	// Then try all the auxiliary groups.
-	groups, err := Getgroups()
-	if err != nil {
-		t.Fatalf("getgroups: %s", err)
-	}
-	t.Log("groups: ", groups)
-	for _, g := range groups {
-		if err = Chown(f.Name(), -1, g); err != nil {
-			t.Fatalf("chown %s -1 %d: %s", f.Name(), g, err)
-		}
-		checkUidGid(t, f.Name(), dir.Uid, g)
-
-		// change back to gid to test fd.Chown
-		if err = f.Chown(-1, gid); err != nil {
-			t.Fatalf("fchown %s -1 %d: %s", f.Name(), gid, err)
-		}
-		checkUidGid(t, f.Name(), dir.Uid, gid)
-	}
-}
-
 func checkSize(t *testing.T, f *File, size int64) {
 	dir, err := f.Stat()
 	if err != nil {
 		t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
 	}
-	if dir.Size != size {
-		t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size, size)
+	if dir.Size() != size {
+		t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)
 	}
 }
 
@@ -692,43 +654,44 @@ func TestChtimes(t *testing.T) {
 	f.Write([]byte("hello, world\n"))
 	f.Close()
 
-	preStat, err := Stat(f.Name())
+	st, err := Stat(f.Name())
 	if err != nil {
 		t.Fatalf("Stat %s: %s", f.Name(), err)
 	}
+	preStat := st.(*FileStat)
 
 	// Move access and modification time back a second
-	const OneSecond = 1e9 // in nanoseconds
-	err = Chtimes(f.Name(), preStat.Atime_ns-OneSecond, preStat.Mtime_ns-OneSecond)
+	at := Atime(preStat)
+	mt := preStat.ModTime()
+	err = Chtimes(f.Name(), at.Add(-time.Second), mt.Add(-time.Second))
 	if err != nil {
 		t.Fatalf("Chtimes %s: %s", f.Name(), err)
 	}
 
-	postStat, err := Stat(f.Name())
+	st, err = Stat(f.Name())
 	if err != nil {
 		t.Fatalf("second Stat %s: %s", f.Name(), err)
 	}
+	postStat := st.(*FileStat)
 
 	/* Plan 9:
 		Mtime is the time of the last change of content.  Similarly, atime is set whenever the
 	    contents are accessed; also, it is set whenever mtime is set.
 	*/
-	if postStat.Atime_ns >= preStat.Atime_ns && syscall.OS != "plan9" {
-		t.Errorf("Atime_ns didn't go backwards; was=%d, after=%d",
-			preStat.Atime_ns,
-			postStat.Atime_ns)
+	pat := Atime(postStat)
+	pmt := postStat.ModTime()
+	if !pat.Before(at) && runtime.GOOS != "plan9" {
+		t.Errorf("AccessTime didn't go backwards; was=%d, after=%d", at, pat)
 	}
 
-	if postStat.Mtime_ns >= preStat.Mtime_ns {
-		t.Errorf("Mtime_ns didn't go backwards; was=%d, after=%d",
-			preStat.Mtime_ns,
-			postStat.Mtime_ns)
+	if !pmt.Before(mt) {
+		t.Errorf("ModTime didn't go backwards; was=%d, after=%d", mt, pmt)
 	}
 }
 
 func TestChdirAndGetwd(t *testing.T) {
 	// TODO(brainman): file.Chdir() is not implemented on windows.
-	if syscall.OS == "windows" {
+	if runtime.GOOS == "windows" {
 		return
 	}
 	fd, err := Open(".")
@@ -739,7 +702,7 @@ func TestChdirAndGetwd(t *testing.T) {
 	// (unlike, say, /var, /etc, and /tmp).
 	dirs := []string{"/", "/usr/bin"}
 	// /usr/bin does not usually exist on Plan 9.
-	if syscall.OS == "plan9" {
+	if runtime.GOOS == "plan9" {
 		dirs = []string{"/", "/usr"}
 	}
 	for mode := 0; mode < 2; mode++ {
@@ -820,7 +783,7 @@ func TestSeek(t *testing.T) {
 	for i, tt := range tests {
 		off, err := f.Seek(tt.in, tt.whence)
 		if off != tt.out || err != nil {
-			if e, ok := err.(*PathError); ok && e.Error == EINVAL && tt.out > 1<<32 {
+			if e, ok := err.(*PathError); ok && e.Err == EINVAL && tt.out > 1<<32 {
 				// Reiserfs rejects the big seeks.
 				// http://code.google.com/p/go/issues/detail?id=91
 				break
@@ -833,7 +796,7 @@ func TestSeek(t *testing.T) {
 type openErrorTest struct {
 	path  string
 	mode  int
-	error Error
+	error error
 }
 
 var openErrorTests = []openErrorTest{
@@ -864,22 +827,30 @@ func TestOpenError(t *testing.T) {
 		}
 		perr, ok := err.(*PathError)
 		if !ok {
-			t.Errorf("Open(%q, %d) returns error of %T type; want *os.PathError", tt.path, tt.mode, err)
+			t.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt.path, tt.mode, err)
 		}
-		if perr.Error != tt.error {
-			if syscall.OS == "plan9" {
-				syscallErrStr := perr.Error.String()
-				expectedErrStr := strings.Replace(tt.error.String(), "file ", "", 1)
+		if perr.Err != tt.error {
+			if runtime.GOOS == "plan9" {
+				syscallErrStr := perr.Err.Error()
+				expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1)
 				if !strings.HasSuffix(syscallErrStr, expectedErrStr) {
 					t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr)
 				}
 			} else {
-				t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Error.String(), tt.error.String())
+				t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error())
 			}
 		}
 	}
 }
 
+func TestOpenNoName(t *testing.T) {
+	f, err := Open("")
+	if err == nil {
+		t.Fatal(`Open("") succeeded`)
+		f.Close()
+	}
+}
+
 func run(t *testing.T, cmd []string) string {
 	// Run /bin/hostname and collect output.
 	r, w, err := Pipe()
@@ -917,12 +888,7 @@ func run(t *testing.T, cmd []string) string {
 func TestHostname(t *testing.T) {
 	// There is no other way to fetch hostname on windows, but via winapi.
 	// On Plan 9 it is can be taken from #c/sysname as Hostname() does.
-	if syscall.OS == "windows" || syscall.OS == "plan9" {
-		return
-	}
-
-	// TODO(jsing): Fix nametomib() on OpenBSD
-	if syscall.OS == "openbsd" {
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
 		return
 	}
 
@@ -953,7 +919,7 @@ func TestReadAt(t *testing.T) {
 	b := make([]byte, 5)
 	n, err := f.ReadAt(b, 7)
 	if err != nil || n != len(b) {
-		t.Fatalf("ReadAt 7: %d, %r", n, err)
+		t.Fatalf("ReadAt 7: %d, %v", n, err)
 	}
 	if string(b) != "world" {
 		t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
diff --git a/src/pkg/os/os_unix_test.go b/src/pkg/os/os_unix_test.go
new file mode 100644
index 0000000..1bdcd74
--- /dev/null
+++ b/src/pkg/os/os_unix_test.go
@@ -0,0 +1,76 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+package os_test
+
+import (
+	. "os"
+	"runtime"
+	"syscall"
+	"testing"
+)
+
+func checkUidGid(t *testing.T, path string, uid, gid int) {
+	dir, err := Stat(path)
+	if err != nil {
+		t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err)
+	}
+	sys := dir.(*FileStat).Sys.(*syscall.Stat_t)
+	if int(sys.Uid) != uid {
+		t.Errorf("Stat %q: uid %d want %d", path, sys.Uid, uid)
+	}
+	if int(sys.Gid) != gid {
+		t.Errorf("Stat %q: gid %d want %d", path, sys.Gid, gid)
+	}
+}
+
+func TestChown(t *testing.T) {
+	// Chown is not supported under windows or Plan 9.
+	// Plan9 provides a native ChownPlan9 version instead.
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+		return
+	}
+	// Use TempDir() to make sure we're on a local file system,
+	// so that the group ids returned by Getgroups will be allowed
+	// on the file.  On NFS, the Getgroups groups are
+	// basically useless.
+	f := newFile("TestChown", t)
+	defer Remove(f.Name())
+	defer f.Close()
+	dir, err := f.Stat()
+	if err != nil {
+		t.Fatalf("stat %s: %s", f.Name(), err)
+	}
+
+	// Can't change uid unless root, but can try
+	// changing the group id.  First try our current group.
+	gid := Getgid()
+	t.Log("gid:", gid)
+	if err = Chown(f.Name(), -1, gid); err != nil {
+		t.Fatalf("chown %s -1 %d: %s", f.Name(), gid, err)
+	}
+	sys := dir.(*FileStat).Sys.(*syscall.Stat_t)
+	checkUidGid(t, f.Name(), int(sys.Uid), gid)
+
+	// Then try all the auxiliary groups.
+	groups, err := Getgroups()
+	if err != nil {
+		t.Fatalf("getgroups: %s", err)
+	}
+	t.Log("groups: ", groups)
+	for _, g := range groups {
+		if err = Chown(f.Name(), -1, g); err != nil {
+			t.Fatalf("chown %s -1 %d: %s", f.Name(), g, err)
+		}
+		checkUidGid(t, f.Name(), int(sys.Uid), g)
+
+		// change back to gid to test fd.Chown
+		if err = f.Chown(-1, gid); err != nil {
+			t.Fatalf("fchown %s -1 %d: %s", f.Name(), gid, err)
+		}
+		checkUidGid(t, f.Name(), int(sys.Uid), gid)
+	}
+}
diff --git a/src/pkg/os/path.go b/src/pkg/os/path.go
index b190c51..e962f3e 100644
--- a/src/pkg/os/path.go
+++ b/src/pkg/os/path.go
@@ -4,6 +4,8 @@
 
 package os
 
+import "io"
+
 // MkdirAll creates a directory named path,
 // along with any necessary parents, and returns nil,
 // or else returns an error.
@@ -11,11 +13,11 @@ package os
 // directories that MkdirAll creates.
 // If path is already a directory, MkdirAll does nothing
 // and returns nil.
-func MkdirAll(path string, perm uint32) Error {
+func MkdirAll(path string, perm FileMode) error {
 	// If path exists, stop with success or error.
 	dir, err := Stat(path)
 	if err == nil {
-		if dir.IsDirectory() {
+		if dir.IsDir() {
 			return nil
 		}
 		return &PathError{"mkdir", path, ENOTDIR}
@@ -46,7 +48,7 @@ func MkdirAll(path string, perm uint32) Error {
 		// Handle arguments like "foo/." by
 		// double-checking that directory doesn't exist.
 		dir, err1 := Lstat(path)
-		if err1 == nil && dir.IsDirectory() {
+		if err1 == nil && dir.IsDir() {
 			return nil
 		}
 		return err
@@ -58,7 +60,7 @@ func MkdirAll(path string, perm uint32) Error {
 // It removes everything it can but returns the first error
 // it encounters.  If the path does not exist, RemoveAll
 // returns nil (no error).
-func RemoveAll(path string) Error {
+func RemoveAll(path string) error {
 	// Simple case: if Remove works, we're done.
 	err := Remove(path)
 	if err == nil {
@@ -68,12 +70,12 @@ func RemoveAll(path string) Error {
 	// Otherwise, is this a directory we need to recurse into?
 	dir, serr := Lstat(path)
 	if serr != nil {
-		if serr, ok := serr.(*PathError); ok && (serr.Error == ENOENT || serr.Error == ENOTDIR) {
+		if serr, ok := serr.(*PathError); ok && (serr.Err == ENOENT || serr.Err == ENOTDIR) {
 			return nil
 		}
 		return serr
 	}
-	if !dir.IsDirectory() {
+	if !dir.IsDir() {
 		// Not a directory; return the error from Remove.
 		return err
 	}
@@ -94,7 +96,7 @@ func RemoveAll(path string) Error {
 				err = err1
 			}
 		}
-		if err1 == EOF {
+		if err1 == io.EOF {
 			break
 		}
 		// If Readdirnames returned an error, use it.
diff --git a/src/pkg/os/path_test.go b/src/pkg/os/path_test.go
index 31acbaa..18634ba 100644
--- a/src/pkg/os/path_test.go
+++ b/src/pkg/os/path_test.go
@@ -7,9 +7,8 @@ package os_test
 import (
 	. "os"
 	"path/filepath"
-	"testing"
 	"runtime"
-	"syscall"
+	"testing"
 )
 
 func TestMkdirAll(t *testing.T) {
@@ -63,7 +62,7 @@ func TestMkdirAll(t *testing.T) {
 		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
 	}
 
-	if syscall.OS == "windows" {
+	if runtime.GOOS == "windows" {
 		path := `_test\_TestMkdirAll_\dir\.\dir2\`
 		err := MkdirAll(path, 0777)
 		if err != nil {
@@ -117,7 +116,7 @@ func TestRemoveAll(t *testing.T) {
 
 	// Determine if we should run the following test.
 	testit := true
-	if syscall.OS == "windows" {
+	if runtime.GOOS == "windows" {
 		// Chmod is not supported under windows.
 		testit = false
 	} else {
@@ -199,7 +198,7 @@ func TestMkdirAllAtSlash(t *testing.T) {
 	if err != nil {
 		pathErr, ok := err.(*PathError)
 		// common for users not to be able to write to /
-		if ok && pathErr.Error == EACCES {
+		if ok && pathErr.Err == EACCES {
 			return
 		}
 		t.Fatalf(`MkdirAll "/_go_os_test/dir": %v`, err)
diff --git a/src/pkg/os/path_unix.go b/src/pkg/os/path_unix.go
index 33045b6..30a167b 100644
--- a/src/pkg/os/path_unix.go
+++ b/src/pkg/os/path_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package os
 
diff --git a/src/pkg/os/proc.go b/src/pkg/os/proc.go
index dfe388f..61545f4 100644
--- a/src/pkg/os/proc.go
+++ b/src/pkg/os/proc.go
@@ -8,8 +8,8 @@ package os
 
 import "syscall"
 
-var Args []string // provided by runtime
-var Envs []string // provided by runtime
+// Args hold the command-line arguments, starting with the program name.
+var Args []string
 
 // Getuid returns the numeric user id of the caller.
 func Getuid() int { return syscall.Getuid() }
@@ -24,7 +24,7 @@ func Getgid() int { return syscall.Getgid() }
 func Getegid() int { return syscall.Getegid() }
 
 // Getgroups returns a list of the numeric ids of groups that the caller belongs to.
-func Getgroups() ([]int, Error) {
+func Getgroups() ([]int, error) {
 	gids, e := syscall.Getgroups()
 	return gids, NewSyscallError("getgroups", e)
 }
diff --git a/src/pkg/os/signal/signal.go b/src/pkg/os/signal/signal.go
index 520f3f8..bce4530 100644
--- a/src/pkg/os/signal/signal.go
+++ b/src/pkg/os/signal/signal.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build darwin freebsd linux netbsd openbsd
+
 // Package signal implements operating system-independent signal handling.
 package signal
 
@@ -31,3 +33,5 @@ func init() {
 	Incoming = ch
 	go process(ch)
 }
+
+// BUG(rsc): This package is unavailable on Plan 9 and Windows.
diff --git a/src/pkg/os/signal/signal_test.go b/src/pkg/os/signal/signal_test.go
index 00eb295..4568aa9 100644
--- a/src/pkg/os/signal/signal_test.go
+++ b/src/pkg/os/signal/signal_test.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build darwin freebsd linux netbsd openbsd
+
 package signal
 
 import (
diff --git a/src/pkg/os/stat_darwin.go b/src/pkg/os/stat_darwin.go
index 0661a6d..e1f93fa 100644
--- a/src/pkg/os/stat_darwin.go
+++ b/src/pkg/os/stat_darwin.go
@@ -4,29 +4,58 @@
 
 package os
 
-import "syscall"
+import (
+	"syscall"
+	"time"
+)
 
-func isSymlink(stat *syscall.Stat_t) bool {
-	return stat.Mode&syscall.S_IFMT == syscall.S_IFLNK
+func sameFile(fs1, fs2 *FileStat) bool {
+	sys1 := fs1.Sys.(*syscall.Stat_t)
+	sys2 := fs2.Sys.(*syscall.Stat_t)
+	return sys1.Dev == sys2.Dev && sys1.Ino == sys2.Ino
 }
 
-func fileInfoFromStat(name string, fi *FileInfo, lstat, stat *syscall.Stat_t) *FileInfo {
-	fi.Dev = uint64(stat.Dev)
-	fi.Ino = stat.Ino
-	fi.Nlink = uint64(stat.Nlink)
-	fi.Mode = uint32(stat.Mode)
-	fi.Uid = int(stat.Uid)
-	fi.Gid = int(stat.Gid)
-	fi.Rdev = uint64(stat.Rdev)
-	fi.Size = stat.Size
-	fi.Blksize = int64(stat.Blksize)
-	fi.Blocks = stat.Blocks
-	fi.Atime_ns = syscall.TimespecToNsec(stat.Atimespec)
-	fi.Mtime_ns = syscall.TimespecToNsec(stat.Mtimespec)
-	fi.Ctime_ns = syscall.TimespecToNsec(stat.Ctimespec)
-	fi.Name = basename(name)
-	if isSymlink(lstat) && !isSymlink(stat) {
-		fi.FollowedSymlink = true
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &FileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtimespec),
+		Sys:     st,
 	}
-	return fi
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK, syscall.S_IFWHT:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.(*FileStat).Sys.(*syscall.Stat_t).Atimespec)
 }
diff --git a/src/pkg/os/stat_freebsd.go b/src/pkg/os/stat_freebsd.go
index 454165d..4c1c197 100644
--- a/src/pkg/os/stat_freebsd.go
+++ b/src/pkg/os/stat_freebsd.go
@@ -4,29 +4,58 @@
 
 package os
 
-import "syscall"
+import (
+	"syscall"
+	"time"
+)
 
-func isSymlink(stat *syscall.Stat_t) bool {
-	return stat.Mode&syscall.S_IFMT == syscall.S_IFLNK
+func sameFile(fs1, fs2 *FileStat) bool {
+	sys1 := fs1.Sys.(*syscall.Stat_t)
+	sys2 := fs2.Sys.(*syscall.Stat_t)
+	return sys1.Dev == sys2.Dev && sys1.Ino == sys2.Ino
 }
 
-func fileInfoFromStat(name string, fi *FileInfo, lstat, stat *syscall.Stat_t) *FileInfo {
-	fi.Dev = uint64(stat.Dev)
-	fi.Ino = uint64(stat.Ino)
-	fi.Nlink = uint64(stat.Nlink)
-	fi.Mode = uint32(stat.Mode)
-	fi.Uid = int(stat.Uid)
-	fi.Gid = int(stat.Gid)
-	fi.Rdev = uint64(stat.Rdev)
-	fi.Size = int64(stat.Size)
-	fi.Blksize = int64(stat.Blksize)
-	fi.Blocks = stat.Blocks
-	fi.Atime_ns = syscall.TimespecToNsec(stat.Atimespec)
-	fi.Mtime_ns = syscall.TimespecToNsec(stat.Mtimespec)
-	fi.Ctime_ns = syscall.TimespecToNsec(stat.Ctimespec)
-	fi.Name = basename(name)
-	if isSymlink(lstat) && !isSymlink(stat) {
-		fi.FollowedSymlink = true
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &FileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtimespec),
+		Sys:     st,
 	}
-	return fi
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.(*FileStat).Sys.(*syscall.Stat_t).Atimespec)
 }
diff --git a/src/pkg/os/stat_linux.go b/src/pkg/os/stat_linux.go
index 7a3cf79..8d1323a 100644
--- a/src/pkg/os/stat_linux.go
+++ b/src/pkg/os/stat_linux.go
@@ -4,29 +4,58 @@
 
 package os
 
-import "syscall"
+import (
+	"syscall"
+	"time"
+)
 
-func isSymlink(stat *syscall.Stat_t) bool {
-	return stat.Mode&syscall.S_IFMT == syscall.S_IFLNK
+func sameFile(fs1, fs2 *FileStat) bool {
+	sys1 := fs1.Sys.(*syscall.Stat_t)
+	sys2 := fs2.Sys.(*syscall.Stat_t)
+	return sys1.Dev == sys2.Dev && sys1.Ino == sys2.Ino
 }
 
-func fileInfoFromStat(name string, fi *FileInfo, lstat, stat *syscall.Stat_t) *FileInfo {
-	fi.Dev = stat.Dev
-	fi.Ino = stat.Ino
-	fi.Nlink = uint64(stat.Nlink)
-	fi.Mode = stat.Mode
-	fi.Uid = int(stat.Uid)
-	fi.Gid = int(stat.Gid)
-	fi.Rdev = stat.Rdev
-	fi.Size = stat.Size
-	fi.Blksize = int64(stat.Blksize)
-	fi.Blocks = stat.Blocks
-	fi.Atime_ns = syscall.TimespecToNsec(stat.Atim)
-	fi.Mtime_ns = syscall.TimespecToNsec(stat.Mtim)
-	fi.Ctime_ns = syscall.TimespecToNsec(stat.Ctim)
-	fi.Name = basename(name)
-	if isSymlink(lstat) && !isSymlink(stat) {
-		fi.FollowedSymlink = true
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &FileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtim),
+		Sys:     st,
 	}
-	return fi
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.(*FileStat).Sys.(*syscall.Stat_t).Atim)
 }
diff --git a/src/pkg/os/stat_netbsd.go b/src/pkg/os/stat_netbsd.go
new file mode 100644
index 0000000..8d1323a
--- /dev/null
+++ b/src/pkg/os/stat_netbsd.go
@@ -0,0 +1,61 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *FileStat) bool {
+	sys1 := fs1.Sys.(*syscall.Stat_t)
+	sys2 := fs2.Sys.(*syscall.Stat_t)
+	return sys1.Dev == sys2.Dev && sys1.Ino == sys2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &FileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtim),
+		Sys:     st,
+	}
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.(*FileStat).Sys.(*syscall.Stat_t).Atim)
+}
diff --git a/src/pkg/os/stat_openbsd.go b/src/pkg/os/stat_openbsd.go
index 6d3a381..8d1323a 100644
--- a/src/pkg/os/stat_openbsd.go
+++ b/src/pkg/os/stat_openbsd.go
@@ -4,29 +4,58 @@
 
 package os
 
-import "syscall"
+import (
+	"syscall"
+	"time"
+)
 
-func isSymlink(stat *syscall.Stat_t) bool {
-	return stat.Mode&syscall.S_IFMT == syscall.S_IFLNK
+func sameFile(fs1, fs2 *FileStat) bool {
+	sys1 := fs1.Sys.(*syscall.Stat_t)
+	sys2 := fs2.Sys.(*syscall.Stat_t)
+	return sys1.Dev == sys2.Dev && sys1.Ino == sys2.Ino
 }
 
-func fileInfoFromStat(name string, fi *FileInfo, lstat, stat *syscall.Stat_t) *FileInfo {
-	fi.Dev = uint64(stat.Dev)
-	fi.Ino = uint64(stat.Ino)
-	fi.Nlink = uint64(stat.Nlink)
-	fi.Mode = uint32(stat.Mode)
-	fi.Uid = int(stat.Uid)
-	fi.Gid = int(stat.Gid)
-	fi.Rdev = uint64(stat.Rdev)
-	fi.Size = int64(stat.Size)
-	fi.Blksize = int64(stat.Blksize)
-	fi.Blocks = stat.Blocks
-	fi.Atime_ns = syscall.TimespecToNsec(stat.Atim)
-	fi.Mtime_ns = syscall.TimespecToNsec(stat.Mtim)
-	fi.Ctime_ns = syscall.TimespecToNsec(stat.Ctim)
-	fi.Name = basename(name)
-	if isSymlink(lstat) && !isSymlink(stat) {
-		fi.FollowedSymlink = true
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &FileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtim),
+		Sys:     st,
 	}
-	return fi
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.(*FileStat).Sys.(*syscall.Stat_t).Atim)
 }
diff --git a/src/pkg/os/stat_plan9.go b/src/pkg/os/stat_plan9.go
index 173a23f..f731e43 100644
--- a/src/pkg/os/stat_plan9.go
+++ b/src/pkg/os/stat_plan9.go
@@ -4,87 +4,101 @@
 
 package os
 
-import "syscall"
-
-func fileInfoFromStat(fi *FileInfo, d *Dir) *FileInfo {
-	fi.Dev = uint64(d.Qid.Vers) | uint64(d.Qid.Type<<32)
-	fi.Ino = d.Qid.Path
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *FileStat) bool {
+	a := fs1.Sys.(*Dir)
+	b := fs2.Sys.(*Dir)
+	return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev
+}
 
-	fi.Mode = uint32(d.Mode) & 0777
-	if (d.Mode & syscall.DMDIR) == syscall.DMDIR {
-		fi.Mode |= syscall.S_IFDIR
-	} else {
-		fi.Mode |= syscall.S_IFREG
+func fileInfoFromStat(d *Dir) FileInfo {
+	fs := &FileStat{
+		name:    d.Name,
+		size:    int64(d.Length),
+		modTime: time.Unix(int64(d.Mtime), 0),
+		Sys:     d,
 	}
-
-	fi.Size = int64(d.Length)
-	fi.Atime_ns = 1e9 * int64(d.Atime)
-	fi.Mtime_ns = 1e9 * int64(d.Mtime)
-	fi.Name = d.Name
-	fi.FollowedSymlink = false
-	return fi
+	fs.mode = FileMode(d.Mode & 0777)
+	if d.Mode&syscall.DMDIR != 0 {
+		fs.mode |= ModeDir
+	}
+	if d.Mode&syscall.DMAPPEND != 0 {
+		fs.mode |= ModeAppend
+	}
+	if d.Mode&syscall.DMEXCL != 0 {
+		fs.mode |= ModeExclusive
+	}
+	if d.Mode&syscall.DMTMP != 0 {
+		fs.mode |= ModeTemporary
+	}
+	return fs
 }
 
 // arg is an open *File or a path string. 
-func dirstat(arg interface{}) (d *Dir, err Error) {
+func dirstat(arg interface{}) (d *Dir, err error) {
 	var name string
-	nd := syscall.STATFIXLEN + 16*4
 
-	for i := 0; i < 2; i++ { /* should work by the second try */
-		buf := make([]byte, nd)
+	// This is big enough for most stat messages
+	// and rounded to a multiple of 128 bytes.
+	size := (syscall.STATFIXLEN + 16*4 + 128) &^ 128
 
-		var n int
-		var e syscall.Error
+	for i := 0; i < 2; i++ {
+		buf := make([]byte, size)
 
-		switch syscallArg := arg.(type) {
+		var n int
+		switch a := arg.(type) {
 		case *File:
-			name = syscallArg.name
-			n, e = syscall.Fstat(syscallArg.fd, buf)
+			name = a.name
+			n, err = syscall.Fstat(a.fd, buf)
 		case string:
-			name = syscallArg
-			n, e = syscall.Stat(name, buf)
+			name = a
+			n, err = syscall.Stat(name, buf)
 		}
-
-		if e != nil {
-			return nil, &PathError{"stat", name, e}
+		if err != nil {
+			return nil, &PathError{"stat", name, err}
 		}
-
 		if n < syscall.STATFIXLEN {
 			return nil, &PathError{"stat", name, Eshortstat}
 		}
 
-		ntmp, _ := gbit16(buf)
-		nd = int(ntmp)
-
-		if nd <= n {
-			d, e := UnmarshalDir(buf[:n])
+		// Pull the real size out of the stat message.
+		s, _ := gbit16(buf)
+		size = int(s)
 
-			if e != nil {
-				return nil, &PathError{"stat", name, e}
+		// If the stat message is larger than our buffer we will
+		// go around the loop and allocate one that is big enough.
+		if size <= n {
+			d, err = UnmarshalDir(buf[:n])
+			if err != nil {
+				return nil, &PathError{"stat", name, err}
 			}
-			return d, e
+			return
 		}
 	}
-
 	return nil, &PathError{"stat", name, Ebadstat}
 }
 
 // Stat returns a FileInfo structure describing the named file and an error, if any.
-func Stat(name string) (fi *FileInfo, err Error) {
+func Stat(name string) (FileInfo, error) {
 	d, err := dirstat(name)
-	if iserror(err) {
+	if err != nil {
 		return nil, err
 	}
-	return fileInfoFromStat(new(FileInfo), d), err
+	return fileInfoFromStat(d), nil
 }
 
 // Lstat returns the FileInfo structure describing the named file and an
 // error, if any.  If the file is a symbolic link (though Plan 9 does not have symbolic links), 
 // the returned FileInfo describes the symbolic link.  Lstat makes no attempt to follow the link.
-func Lstat(name string) (fi *FileInfo, err Error) {
-	d, err := dirstat(name)
-	if iserror(err) {
-		return nil, err
-	}
-	return fileInfoFromStat(new(FileInfo), d), err
+func Lstat(name string) (FileInfo, error) {
+	return Stat(name)
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return time.Unix(int64(fi.(*FileStat).Sys.(*Dir).Atime), 0)
 }
diff --git a/src/pkg/os/stat_windows.go b/src/pkg/os/stat_windows.go
index 2009d1f..e599583 100644
--- a/src/pkg/os/stat_windows.go
+++ b/src/pkg/os/stat_windows.go
@@ -5,13 +5,14 @@
 package os
 
 import (
-	"unsafe"
 	"syscall"
+	"time"
+	"unsafe"
 )
 
 // Stat returns the FileInfo structure describing file.
 // It returns the FileInfo and an error, if any.
-func (file *File) Stat() (fi *FileInfo, err Error) {
+func (file *File) Stat() (fi FileInfo, err error) {
 	if file == nil || file.fd < 0 {
 		return nil, EINVAL
 	}
@@ -21,10 +22,10 @@ func (file *File) Stat() (fi *FileInfo, err Error) {
 	}
 	var d syscall.ByHandleFileInformation
 	e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &d)
-	if e != 0 {
-		return nil, &PathError{"GetFileInformationByHandle", file.name, Errno(e)}
+	if e != nil {
+		return nil, &PathError{"GetFileInformationByHandle", file.name, e}
 	}
-	return setFileInfo(new(FileInfo), basename(file.name), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime), nil
+	return toFileInfo(basename(file.name), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime), nil
 }
 
 // Stat returns a FileInfo structure describing the named file and an error, if any.
@@ -32,22 +33,22 @@ func (file *File) Stat() (fi *FileInfo, err Error) {
 // the file pointed at by the link and has fi.FollowedSymlink set to true.
 // If name names an invalid symbolic link, the returned FileInfo describes
 // the link itself and has fi.FollowedSymlink set to false.
-func Stat(name string) (fi *FileInfo, err Error) {
+func Stat(name string) (fi FileInfo, err error) {
 	if len(name) == 0 {
-		return nil, &PathError{"Stat", name, Errno(syscall.ERROR_PATH_NOT_FOUND)}
+		return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
 	}
 	var d syscall.Win32FileAttributeData
 	e := syscall.GetFileAttributesEx(syscall.StringToUTF16Ptr(name), syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&d)))
-	if e != 0 {
-		return nil, &PathError{"GetFileAttributesEx", name, Errno(e)}
+	if e != nil {
+		return nil, &PathError{"GetFileAttributesEx", name, e}
 	}
-	return setFileInfo(new(FileInfo), basename(name), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime), nil
+	return toFileInfo(basename(name), d.FileAttributes, d.FileSizeHigh, d.FileSizeLow, d.CreationTime, d.LastAccessTime, d.LastWriteTime), nil
 }
 
 // Lstat returns the FileInfo structure describing the named file and an
 // error, if any.  If the file is a symbolic link, the returned FileInfo
 // describes the symbolic link.  Lstat makes no attempt to follow the link.
-func Lstat(name string) (fi *FileInfo, err Error) {
+func Lstat(name string) (fi FileInfo, err error) {
 	// No links on Windows
 	return Stat(name)
 }
@@ -76,23 +77,37 @@ func basename(name string) string {
 	return name
 }
 
-func setFileInfo(fi *FileInfo, name string, fa, sizehi, sizelo uint32, ctime, atime, wtime syscall.Filetime) *FileInfo {
-	fi.Mode = 0
+type winTimes struct {
+	atime, ctime syscall.Filetime
+}
+
+func toFileInfo(name string, fa, sizehi, sizelo uint32, ctime, atime, mtime syscall.Filetime) FileInfo {
+	fs := new(FileStat)
+	fs.mode = 0
 	if fa&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
-		fi.Mode = fi.Mode | syscall.S_IFDIR
-	} else {
-		fi.Mode = fi.Mode | syscall.S_IFREG
+		fs.mode |= ModeDir
 	}
 	if fa&syscall.FILE_ATTRIBUTE_READONLY != 0 {
-		fi.Mode = fi.Mode | 0444
+		fs.mode |= 0444
 	} else {
-		fi.Mode = fi.Mode | 0666
+		fs.mode |= 0666
 	}
-	fi.Size = int64(sizehi)<<32 + int64(sizelo)
-	fi.Name = name
-	fi.FollowedSymlink = false
-	fi.Atime_ns = atime.Nanoseconds()
-	fi.Mtime_ns = wtime.Nanoseconds()
-	fi.Ctime_ns = ctime.Nanoseconds()
-	return fi
+	fs.size = int64(sizehi)<<32 + int64(sizelo)
+	fs.name = name
+	fs.modTime = time.Unix(0, mtime.Nanoseconds())
+	fs.Sys = &winTimes{atime, ctime}
+	return fs
+}
+
+func sameFile(fs1, fs2 *FileStat) bool {
+	// TODO(rsc): Do better than this, but this matches what
+	// used to happen when code compared .Dev and .Ino,
+	// which were both always zero.  Obviously not all files
+	// are the same.
+	return true
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return time.Unix(0, fi.(*FileStat).Sys.(*winTimes).atime.Nanoseconds())
 }
diff --git a/src/pkg/os/sys_bsd.go b/src/pkg/os/sys_bsd.go
index b0d097a..0f263f1 100644
--- a/src/pkg/os/sys_bsd.go
+++ b/src/pkg/os/sys_bsd.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd openbsd
+// +build darwin freebsd netbsd openbsd
 
 // os code shared between *BSD systems including OS X (Darwin)
 // and FreeBSD.
@@ -11,11 +11,10 @@ package os
 
 import "syscall"
 
-func Hostname() (name string, err Error) {
-	var errno int
-	name, errno = syscall.Sysctl("kern.hostname")
-	if errno != 0 {
-		return "", NewSyscallError("sysctl kern.hostname", errno)
+func hostname() (name string, err error) {
+	name, err = syscall.Sysctl("kern.hostname")
+	if err != nil {
+		return "", NewSyscallError("sysctl kern.hostname", err)
 	}
 	return name, nil
 }
diff --git a/src/pkg/os/sys_linux.go b/src/pkg/os/sys_linux.go
index 2accd6c..76cdf50 100644
--- a/src/pkg/os/sys_linux.go
+++ b/src/pkg/os/sys_linux.go
@@ -6,8 +6,7 @@
 
 package os
 
-// Hostname returns the host name reported by the kernel.
-func Hostname() (name string, err Error) {
+func hostname() (name string, err error) {
 	f, err := Open("/proc/sys/kernel/hostname")
 	if err != nil {
 		return "", err
diff --git a/src/pkg/os/sys_plan9.go b/src/pkg/os/sys_plan9.go
index c24cde0..07a7905 100644
--- a/src/pkg/os/sys_plan9.go
+++ b/src/pkg/os/sys_plan9.go
@@ -6,7 +6,7 @@
 
 package os
 
-func Hostname() (name string, err Error) {
+func hostname() (name string, err error) {
 	f, err := Open("#c/sysname")
 	if err != nil {
 		return "", err
diff --git a/src/pkg/os/sys_windows.go b/src/pkg/os/sys_windows.go
index a787984..92617de 100644
--- a/src/pkg/os/sys_windows.go
+++ b/src/pkg/os/sys_windows.go
@@ -6,9 +6,9 @@ package os
 
 import "syscall"
 
-func Hostname() (name string, err Error) {
+func hostname() (name string, err error) {
 	s, e := syscall.ComputerName()
-	if e != 0 {
+	if e != nil {
 		return "", NewSyscallError("ComputerName", e)
 	}
 	return s, nil
diff --git a/src/pkg/os/time.go b/src/pkg/os/time.go
index 949574d..eb564e5 100644
--- a/src/pkg/os/time.go
+++ b/src/pkg/os/time.go
@@ -7,12 +7,12 @@ package os
 import "syscall"
 
 // Time returns the current time, in whole seconds and
-// fractional nanoseconds, plus an Error if any. The current
+// fractional nanoseconds, plus an error if any. The current
 // time is thus 1e9*sec+nsec, in nanoseconds.  The zero of
 // time is the Unix epoch.
-func Time() (sec int64, nsec int64, err Error) {
+func Time() (sec int64, nsec int64, err error) {
 	var tv syscall.Timeval
-	if e := syscall.Gettimeofday(&tv); iserror(e) {
+	if e := syscall.Gettimeofday(&tv); e != nil {
 		return 0, 0, NewSyscallError("gettimeofday", e)
 	}
 	return int64(tv.Sec), int64(tv.Usec) * 1000, err
diff --git a/src/pkg/os/types.go b/src/pkg/os/types.go
index df57b59..a3f187c 100644
--- a/src/pkg/os/types.go
+++ b/src/pkg/os/types.go
@@ -4,53 +4,116 @@
 
 package os
 
-import "syscall"
-
-// An operating-system independent representation of Unix data structures.
-// OS-specific routines in this directory convert the OS-local versions to these.
+import (
+	"syscall"
+	"time"
+)
 
 // Getpagesize returns the underlying system's memory page size.
 func Getpagesize() int { return syscall.Getpagesize() }
 
-// A FileInfo describes a file and is returned by Stat, Fstat, and Lstat
-type FileInfo struct {
-	Dev             uint64 // device number of file system holding file.
-	Ino             uint64 // inode number.
-	Nlink           uint64 // number of hard links.
-	Mode            uint32 // permission and mode bits.
-	Uid             int    // user id of owner.
-	Gid             int    // group id of owner.
-	Rdev            uint64 // device type for special file.
-	Size            int64  // length in bytes.
-	Blksize         int64  // size of blocks, in bytes.
-	Blocks          int64  // number of blocks allocated for file.
-	Atime_ns        int64  // access time; nanoseconds since epoch.
-	Mtime_ns        int64  // modified time; nanoseconds since epoch.
-	Ctime_ns        int64  // status change time; nanoseconds since epoch.
-	Name            string // base name of the file name provided in Open, Stat, etc.
-	FollowedSymlink bool   // followed a symlink to get this information
+// A FileInfo describes a file and is returned by Stat and Lstat
+type FileInfo interface {
+	Name() string       // base name of the file
+	Size() int64        // length in bytes
+	Mode() FileMode     // file mode bits
+	ModTime() time.Time // modification time
+	IsDir() bool        // abbreviation for Mode().IsDir()
 }
 
-// IsFifo reports whether the FileInfo describes a FIFO file.
-func (f *FileInfo) IsFifo() bool { return (f.Mode & syscall.S_IFMT) == syscall.S_IFIFO }
+// A FileMode represents a file's mode and permission bits.
+// The bits have the same definition on all systems, so that
+// information about files can be moved from one system
+// to another portably.  Not all bits apply to all systems.
+// The only required bit is ModeDir for directories.
+type FileMode uint32
 
-// IsChar reports whether the FileInfo describes a character special file.
-func (f *FileInfo) IsChar() bool { return (f.Mode & syscall.S_IFMT) == syscall.S_IFCHR }
+// The defined file mode bits are the most significant bits of the FileMode.
+// The nine least-significant bits are the standard Unix rwxrwxrwx permissions.
+// The values of these bits should be considered part of the public API and
+// may be used in wire protocols or disk representations: they must not be
+// changed, although new bits might be added.
+const (
+	// The single letters are the abbreviations
+	// used by the String method's formatting.
+	ModeDir        FileMode = 1 << (32 - 1 - iota) // d: is a directory
+	ModeAppend                                     // a: append-only
+	ModeExclusive                                  // l: exclusive use
+	ModeTemporary                                  // T: temporary file (not backed up)
+	ModeSymlink                                    // L: symbolic link
+	ModeDevice                                     // D: device file
+	ModeNamedPipe                                  // p: named pipe (FIFO)
+	ModeSocket                                     // S: Unix domain socket
+	ModeSetuid                                     // u: setuid
+	ModeSetgid                                     // g: setgid
+	ModeCharDevice                                 // c: Unix character device, when ModeDevice is set
+	ModeSticky                                     // t: sticky
 
-// IsDirectory reports whether the FileInfo describes a directory.
-func (f *FileInfo) IsDirectory() bool { return (f.Mode & syscall.S_IFMT) == syscall.S_IFDIR }
+	// Mask for the type bits. For regular files, none will be set.
+	ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
 
-// IsBlock reports whether the FileInfo describes a block special file.
-func (f *FileInfo) IsBlock() bool { return (f.Mode & syscall.S_IFMT) == syscall.S_IFBLK }
+	ModePerm FileMode = 0777 // permission bits
+)
 
-// IsRegular reports whether the FileInfo describes a regular file.
-func (f *FileInfo) IsRegular() bool { return (f.Mode & syscall.S_IFMT) == syscall.S_IFREG }
+func (m FileMode) String() string {
+	const str = "dalTLDpSugct"
+	var buf [20]byte
+	w := 0
+	for i, c := range str {
+		if m&(1<<uint(32-1-i)) != 0 {
+			buf[w] = byte(c)
+			w++
+		}
+	}
+	if w == 0 {
+		buf[w] = '-'
+		w++
+	}
+	const rwx = "rwxrwxrwx"
+	for i, c := range rwx {
+		if m&(1<<uint(9-1-i)) != 0 {
+			buf[w] = byte(c)
+		} else {
+			buf[w] = '-'
+		}
+		w++
+	}
+	return string(buf[:w])
+}
 
-// IsSymlink reports whether the FileInfo describes a symbolic link.
-func (f *FileInfo) IsSymlink() bool { return (f.Mode & syscall.S_IFMT) == syscall.S_IFLNK }
+// IsDir reports whether m describes a directory.
+// That is, it tests for the ModeDir bit being set in m.
+func (m FileMode) IsDir() bool {
+	return m&ModeDir != 0
+}
+
+// Perm returns the Unix permission bits in m.
+func (m FileMode) Perm() FileMode {
+	return m & ModePerm
+}
 
-// IsSocket reports whether the FileInfo describes a socket.
-func (f *FileInfo) IsSocket() bool { return (f.Mode & syscall.S_IFMT) == syscall.S_IFSOCK }
+// A FileStat is the implementation of FileInfo returned by Stat and Lstat.
+// Clients that need access to the underlying system-specific stat information
+// can test for *os.FileStat and then consult the Sys field.
+type FileStat struct {
+	name    string
+	size    int64
+	mode    FileMode
+	modTime time.Time
 
-// Permission returns the file permission bits.
-func (f *FileInfo) Permission() uint32 { return f.Mode & 0777 }
+	Sys interface{}
+}
+
+func (fs *FileStat) Name() string       { return fs.name }
+func (fs *FileStat) Size() int64        { return fs.size }
+func (fs *FileStat) Mode() FileMode     { return fs.mode }
+func (fs *FileStat) ModTime() time.Time { return fs.modTime }
+func (fs *FileStat) IsDir() bool        { return fs.mode.IsDir() }
+
+// SameFile reports whether fs and other describe the same file.
+// For example, on Unix this means that the device and inode fields
+// of the two underlying structures are identical; on other systems
+// the decision may be based on the path names.
+func (fs *FileStat) SameFile(other *FileStat) bool {
+	return sameFile(fs, other)
+}
diff --git a/src/pkg/os/user/lookup_stubs.go b/src/pkg/os/user/lookup_stubs.go
index 2d2de98..10f5170 100644
--- a/src/pkg/os/user/lookup_stubs.go
+++ b/src/pkg/os/user/lookup_stubs.go
@@ -2,20 +2,19 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build openbsd plan9 windows
+// +build !cgo windows
 
 package user
 
 import (
 	"fmt"
-	"os"
 	"runtime"
 )
 
-func Lookup(username string) (*User, os.Error) {
+func Lookup(username string) (*User, error) {
 	return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 }
 
-func LookupId(int) (*User, os.Error) {
+func LookupId(int) (*User, error) {
 	return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
 }
diff --git a/src/pkg/os/user/lookup_unix.go b/src/pkg/os/user/lookup_unix.go
index 817eb79..21c8346 100644
--- a/src/pkg/os/user/lookup_unix.go
+++ b/src/pkg/os/user/lookup_unix.go
@@ -3,14 +3,15 @@
 // license that can be found in the LICENSE file.
 
 // +build darwin freebsd linux
+// +build cgo
 
 package user
 
 import (
 	"fmt"
-	"os"
 	"runtime"
 	"strings"
+	"syscall"
 	"unsafe"
 )
 
@@ -33,17 +34,17 @@ func init() {
 
 // Lookup looks up a user by username. If the user cannot be found,
 // the returned error is of type UnknownUserError.
-func Lookup(username string) (*User, os.Error) {
+func Lookup(username string) (*User, error) {
 	return lookup(-1, username, true)
 }
 
 // LookupId looks up a user by userid. If the user cannot be found,
 // the returned error is of type UnknownUserIdError.
-func LookupId(uid int) (*User, os.Error) {
+func LookupId(uid int) (*User, error) {
 	return lookup(uid, "", false)
 }
 
-func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
+func lookup(uid int, username string, lookupByName bool) (*User, error) {
 	var pwd C.struct_passwd
 	var result *C.struct_passwd
 
@@ -71,7 +72,7 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
 			C.size_t(bufSize),
 			&result)
 		if rv != 0 {
-			return nil, fmt.Errorf("user: lookup username %s: %s", username, os.Errno(rv))
+			return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.Errno(rv))
 		}
 		if result == nil {
 			return nil, UnknownUserError(username)
@@ -86,7 +87,7 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
 			C.size_t(bufSize),
 			&result)
 		if rv != 0 {
-			return nil, fmt.Errorf("user: lookup userid %d: %s", uid, os.Errno(rv))
+			return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.Errno(rv))
 		}
 		if result == nil {
 			return nil, UnknownUserIdError(uid)
diff --git a/src/pkg/os/user/user.go b/src/pkg/os/user/user.go
index f71e11d..a019537 100644
--- a/src/pkg/os/user/user.go
+++ b/src/pkg/os/user/user.go
@@ -24,7 +24,7 @@ type User struct {
 // a user cannot be found.
 type UnknownUserIdError int
 
-func (e UnknownUserIdError) String() string {
+func (e UnknownUserIdError) Error() string {
 	return "user: unknown userid " + strconv.Itoa(int(e))
 }
 
@@ -32,6 +32,6 @@ func (e UnknownUserIdError) String() string {
 // a user cannot be found.
 type UnknownUserError string
 
-func (e UnknownUserError) String() string {
+func (e UnknownUserError) Error() string {
 	return "user: unknown user " + string(e)
 }
diff --git a/src/pkg/os/user/user_test.go b/src/pkg/os/user/user_test.go
index 59f15e4..f9f44af 100644
--- a/src/pkg/os/user/user_test.go
+++ b/src/pkg/os/user/user_test.go
@@ -41,8 +41,8 @@ func TestLookup(t *testing.T) {
 		t.Errorf("expected Uid of %d; got %d", e, g)
 	}
 	fi, err := os.Stat(u.HomeDir)
-	if err != nil || !fi.IsDirectory() {
-		t.Errorf("expected a valid HomeDir; stat(%q): err=%v, IsDirectory=%v", u.HomeDir, err, fi.IsDirectory())
+	if err != nil || !fi.IsDir() {
+		t.Errorf("expected a valid HomeDir; stat(%q): err=%v, IsDir=%v", u.HomeDir, err, fi.IsDir())
 	}
 	if u.Username == "" {
 		t.Fatalf("didn't get a username")
diff --git a/src/pkg/os/zsignal_darwin_386.go b/src/pkg/os/zsignal_darwin_386.go
new file mode 100644
index 0000000..8251113
--- /dev/null
+++ b/src/pkg/os/zsignal_darwin_386.go
@@ -0,0 +1,48 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_darwin_386.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGEMT    = UnixSignal(syscall.SIGEMT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINFO   = UnixSignal(syscall.SIGINFO)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_darwin_amd64.go b/src/pkg/os/zsignal_darwin_amd64.go
new file mode 100644
index 0000000..7c64af8
--- /dev/null
+++ b/src/pkg/os/zsignal_darwin_amd64.go
@@ -0,0 +1,48 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_darwin_amd64.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGEMT    = UnixSignal(syscall.SIGEMT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINFO   = UnixSignal(syscall.SIGINFO)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_freebsd_386.go b/src/pkg/os/zsignal_freebsd_386.go
new file mode 100644
index 0000000..029e63f
--- /dev/null
+++ b/src/pkg/os/zsignal_freebsd_386.go
@@ -0,0 +1,50 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_freebsd_386.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGEMT    = UnixSignal(syscall.SIGEMT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINFO   = UnixSignal(syscall.SIGINFO)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGLWP    = UnixSignal(syscall.SIGLWP)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTHR    = UnixSignal(syscall.SIGTHR)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_freebsd_amd64.go b/src/pkg/os/zsignal_freebsd_amd64.go
new file mode 100644
index 0000000..ba2e2e4
--- /dev/null
+++ b/src/pkg/os/zsignal_freebsd_amd64.go
@@ -0,0 +1,50 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_freebsd_amd64.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGEMT    = UnixSignal(syscall.SIGEMT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINFO   = UnixSignal(syscall.SIGINFO)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGLWP    = UnixSignal(syscall.SIGLWP)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTHR    = UnixSignal(syscall.SIGTHR)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_linux_386.go b/src/pkg/os/zsignal_linux_386.go
new file mode 100644
index 0000000..74cd029
--- /dev/null
+++ b/src/pkg/os/zsignal_linux_386.go
@@ -0,0 +1,51 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_linux_386.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCLD    = UnixSignal(syscall.SIGCLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPOLL   = UnixSignal(syscall.SIGPOLL)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGPWR    = UnixSignal(syscall.SIGPWR)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTKFLT = UnixSignal(syscall.SIGSTKFLT)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGUNUSED = UnixSignal(syscall.SIGUNUSED)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_linux_amd64.go b/src/pkg/os/zsignal_linux_amd64.go
new file mode 100644
index 0000000..0416e0c
--- /dev/null
+++ b/src/pkg/os/zsignal_linux_amd64.go
@@ -0,0 +1,51 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_linux_amd64.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCLD    = UnixSignal(syscall.SIGCLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPOLL   = UnixSignal(syscall.SIGPOLL)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGPWR    = UnixSignal(syscall.SIGPWR)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTKFLT = UnixSignal(syscall.SIGSTKFLT)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGUNUSED = UnixSignal(syscall.SIGUNUSED)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_linux_arm.go b/src/pkg/os/zsignal_linux_arm.go
new file mode 100644
index 0000000..40cb686
--- /dev/null
+++ b/src/pkg/os/zsignal_linux_arm.go
@@ -0,0 +1,51 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_linux_arm.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCLD    = UnixSignal(syscall.SIGCLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPOLL   = UnixSignal(syscall.SIGPOLL)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGPWR    = UnixSignal(syscall.SIGPWR)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTKFLT = UnixSignal(syscall.SIGSTKFLT)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGUNUSED = UnixSignal(syscall.SIGUNUSED)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_netbsd_386.go b/src/pkg/os/zsignal_netbsd_386.go
new file mode 100644
index 0000000..07d4692
--- /dev/null
+++ b/src/pkg/os/zsignal_netbsd_386.go
@@ -0,0 +1,49 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_netbsd_386.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGEMT    = UnixSignal(syscall.SIGEMT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINFO   = UnixSignal(syscall.SIGINFO)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTHR    = UnixSignal(syscall.SIGTHR)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_netbsd_amd64.go b/src/pkg/os/zsignal_netbsd_amd64.go
new file mode 100644
index 0000000..6c0d996
--- /dev/null
+++ b/src/pkg/os/zsignal_netbsd_amd64.go
@@ -0,0 +1,49 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_netbsd_amd64.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGEMT    = UnixSignal(syscall.SIGEMT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINFO   = UnixSignal(syscall.SIGINFO)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTHR    = UnixSignal(syscall.SIGTHR)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_openbsd_386.go b/src/pkg/os/zsignal_openbsd_386.go
new file mode 100644
index 0000000..90e1137
--- /dev/null
+++ b/src/pkg/os/zsignal_openbsd_386.go
@@ -0,0 +1,49 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_openbsd_386.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGEMT    = UnixSignal(syscall.SIGEMT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINFO   = UnixSignal(syscall.SIGINFO)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTHR    = UnixSignal(syscall.SIGTHR)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_openbsd_amd64.go b/src/pkg/os/zsignal_openbsd_amd64.go
new file mode 100644
index 0000000..7f4dc6d
--- /dev/null
+++ b/src/pkg/os/zsignal_openbsd_amd64.go
@@ -0,0 +1,49 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/zerrors_openbsd_amd64.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGABRT   = UnixSignal(syscall.SIGABRT)
+	SIGALRM   = UnixSignal(syscall.SIGALRM)
+	SIGBUS    = UnixSignal(syscall.SIGBUS)
+	SIGCHLD   = UnixSignal(syscall.SIGCHLD)
+	SIGCONT   = UnixSignal(syscall.SIGCONT)
+	SIGEMT    = UnixSignal(syscall.SIGEMT)
+	SIGFPE    = UnixSignal(syscall.SIGFPE)
+	SIGHUP    = UnixSignal(syscall.SIGHUP)
+	SIGILL    = UnixSignal(syscall.SIGILL)
+	SIGINFO   = UnixSignal(syscall.SIGINFO)
+	SIGINT    = UnixSignal(syscall.SIGINT)
+	SIGIO     = UnixSignal(syscall.SIGIO)
+	SIGIOT    = UnixSignal(syscall.SIGIOT)
+	SIGKILL   = UnixSignal(syscall.SIGKILL)
+	SIGPIPE   = UnixSignal(syscall.SIGPIPE)
+	SIGPROF   = UnixSignal(syscall.SIGPROF)
+	SIGQUIT   = UnixSignal(syscall.SIGQUIT)
+	SIGSEGV   = UnixSignal(syscall.SIGSEGV)
+	SIGSTOP   = UnixSignal(syscall.SIGSTOP)
+	SIGSYS    = UnixSignal(syscall.SIGSYS)
+	SIGTERM   = UnixSignal(syscall.SIGTERM)
+	SIGTHR    = UnixSignal(syscall.SIGTHR)
+	SIGTRAP   = UnixSignal(syscall.SIGTRAP)
+	SIGTSTP   = UnixSignal(syscall.SIGTSTP)
+	SIGTTIN   = UnixSignal(syscall.SIGTTIN)
+	SIGTTOU   = UnixSignal(syscall.SIGTTOU)
+	SIGURG    = UnixSignal(syscall.SIGURG)
+	SIGUSR1   = UnixSignal(syscall.SIGUSR1)
+	SIGUSR2   = UnixSignal(syscall.SIGUSR2)
+	SIGVTALRM = UnixSignal(syscall.SIGVTALRM)
+	SIGWINCH  = UnixSignal(syscall.SIGWINCH)
+	SIGXCPU   = UnixSignal(syscall.SIGXCPU)
+	SIGXFSZ   = UnixSignal(syscall.SIGXFSZ)
+)
diff --git a/src/pkg/os/zsignal_windows_386.go b/src/pkg/os/zsignal_windows_386.go
new file mode 100644
index 0000000..b4b88dc
--- /dev/null
+++ b/src/pkg/os/zsignal_windows_386.go
@@ -0,0 +1,29 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/ztypes_windows.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGHUP  = UnixSignal(syscall.SIGHUP)
+	SIGINT  = UnixSignal(syscall.SIGINT)
+	SIGQUIT = UnixSignal(syscall.SIGQUIT)
+	SIGILL  = UnixSignal(syscall.SIGILL)
+	SIGTRAP = UnixSignal(syscall.SIGTRAP)
+	SIGABRT = UnixSignal(syscall.SIGABRT)
+	SIGBUS  = UnixSignal(syscall.SIGBUS)
+	SIGFPE  = UnixSignal(syscall.SIGFPE)
+	SIGKILL = UnixSignal(syscall.SIGKILL)
+	SIGSEGV = UnixSignal(syscall.SIGSEGV)
+	SIGPIPE = UnixSignal(syscall.SIGPIPE)
+	SIGALRM = UnixSignal(syscall.SIGALRM)
+	SIGTERM = UnixSignal(syscall.SIGTERM)
+)
diff --git a/src/pkg/os/zsignal_windows_amd64.go b/src/pkg/os/zsignal_windows_amd64.go
new file mode 100644
index 0000000..b4b88dc
--- /dev/null
+++ b/src/pkg/os/zsignal_windows_amd64.go
@@ -0,0 +1,29 @@
+// MACHINE GENERATED; DO NOT EDIT
+// To regenerate, run
+//	./mksignals.sh
+// which, for this file, will run
+//	./mkunixsignals.sh ../syscall/ztypes_windows.go
+
+package os
+
+import (
+	"syscall"
+)
+
+var _ = syscall.Open // in case there are zero signals
+
+const (
+	SIGHUP  = UnixSignal(syscall.SIGHUP)
+	SIGINT  = UnixSignal(syscall.SIGINT)
+	SIGQUIT = UnixSignal(syscall.SIGQUIT)
+	SIGILL  = UnixSignal(syscall.SIGILL)
+	SIGTRAP = UnixSignal(syscall.SIGTRAP)
+	SIGABRT = UnixSignal(syscall.SIGABRT)
+	SIGBUS  = UnixSignal(syscall.SIGBUS)
+	SIGFPE  = UnixSignal(syscall.SIGFPE)
+	SIGKILL = UnixSignal(syscall.SIGKILL)
+	SIGSEGV = UnixSignal(syscall.SIGSEGV)
+	SIGPIPE = UnixSignal(syscall.SIGPIPE)
+	SIGALRM = UnixSignal(syscall.SIGALRM)
+	SIGTERM = UnixSignal(syscall.SIGTERM)
+)
diff --git a/src/pkg/patch/Makefile b/src/pkg/patch/Makefile
deleted file mode 100644
index 32db7bd..0000000
--- a/src/pkg/patch/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2009 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=patch
-GOFILES=\
-	apply.go\
-	git.go\
-	patch.go\
-	textdiff.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/patch/apply.go b/src/pkg/patch/apply.go
deleted file mode 100644
index 0dd9080..0000000
--- a/src/pkg/patch/apply.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package patch
-
-import "os"
-
-// An Op is a single operation to execute to apply a patch.
-type Op struct {
-	Verb Verb   // action
-	Src  string // source file
-	Dst  string // destination file
-	Mode int    // mode for destination (if non-zero)
-	Data []byte // data for destination (if non-nil)
-}
-
-// Apply applies the patch set to the files named in the patch set,
-// constructing an in-memory copy of the new file state.
-// It is the client's job to write the changes to the file system
-// if desired.
-//
-// The function readFile should return the contents of the named file.
-// Typically this function will be io.ReadFile.
-//
-func (set *Set) Apply(readFile func(string) ([]byte, os.Error)) ([]Op, os.Error) {
-	op := make([]Op, len(set.File))
-
-	for i, f := range set.File {
-		o := &op[i]
-		o.Verb = f.Verb
-		o.Src = f.Src
-		o.Dst = f.Dst
-		o.Mode = f.NewMode
-		if f.Diff != NoDiff || o.Verb != Edit {
-			// Clients assume o.Data == nil means no data diff.
-			// Start with a non-nil data.
-			var old []byte = make([]byte, 0) // not nil
-			var err os.Error
-			if f.Src != "" {
-				old, err = readFile(f.Src)
-				if err != nil {
-					return nil, &os.PathError{string(f.Verb), f.Src, err}
-				}
-			}
-			o.Data, err = f.Diff.Apply(old)
-			if err != nil {
-				return nil, &os.PathError{string(f.Verb), f.Src, err}
-			}
-		}
-	}
-
-	return op, nil
-}
diff --git a/src/pkg/patch/git.go b/src/pkg/patch/git.go
deleted file mode 100644
index 6516097..0000000
--- a/src/pkg/patch/git.go
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package patch
-
-import (
-	"bytes"
-	"compress/zlib"
-	"crypto/sha1"
-	"encoding/git85"
-	"fmt"
-	"io"
-	"os"
-)
-
-func gitSHA1(data []byte) []byte {
-	if len(data) == 0 {
-		// special case: 0 length is all zeros sum
-		return make([]byte, 20)
-	}
-	h := sha1.New()
-	fmt.Fprintf(h, "blob %d\x00", len(data))
-	h.Write(data)
-	return h.Sum()
-}
-
-// BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
-
-// GitBinaryLiteral represents a Git binary literal diff.
-type GitBinaryLiteral struct {
-	OldSHA1 []byte // if non-empty, the SHA1 hash of the original
-	New     []byte // the new contents
-}
-
-// Apply implements the Diff interface's Apply method.
-func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, os.Error) {
-	if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) {
-		return nil, ErrPatchFailure
-	}
-	return d.New, nil
-}
-
-func unhex(c byte) uint8 {
-	switch {
-	case '0' <= c && c <= '9':
-		return c - '0'
-	case 'a' <= c && c <= 'f':
-		return c - 'a' + 10
-	case 'A' <= c && c <= 'F':
-		return c - 'A' + 10
-	}
-	return 255
-}
-
-func getHex(s []byte) (data []byte, rest []byte) {
-	n := 0
-	for n < len(s) && unhex(s[n]) != 255 {
-		n++
-	}
-	n &^= 1 // Only take an even number of hex digits.
-	data = make([]byte, n/2)
-	for i := range data {
-		data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1])
-	}
-	rest = s[n:]
-	return
-}
-
-// ParseGitBinary parses raw as a Git binary patch.
-func ParseGitBinary(raw []byte) (Diff, os.Error) {
-	var oldSHA1, newSHA1 []byte
-	var sawBinary bool
-
-	for {
-		var first []byte
-		first, raw, _ = getLine(raw, 1)
-		first = bytes.TrimSpace(first)
-		if s, ok := skip(first, "index "); ok {
-			oldSHA1, s = getHex(s)
-			if s, ok = skip(s, ".."); !ok {
-				continue
-			}
-			newSHA1, s = getHex(s)
-			continue
-		}
-		if _, ok := skip(first, "GIT binary patch"); ok {
-			sawBinary = true
-			continue
-		}
-		if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary {
-			data := make([]byte, n)
-			d := git85.NewDecoder(bytes.NewBuffer(raw))
-			z, err := zlib.NewReader(d)
-			if err != nil {
-				return nil, err
-			}
-			defer z.Close()
-			if _, err = io.ReadFull(z, data); err != nil {
-				if err == os.EOF {
-					err = io.ErrUnexpectedEOF
-				}
-				return nil, err
-			}
-			var buf [1]byte
-			m, err := z.Read(buf[0:])
-			if m != 0 || err != os.EOF {
-				return nil, os.NewError("Git binary literal longer than expected")
-			}
-
-			if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) {
-				return nil, os.NewError("Git binary literal SHA1 mismatch")
-			}
-			return &GitBinaryLiteral{oldSHA1, data}, nil
-		}
-		if !sawBinary {
-			return nil, os.NewError("unexpected Git patch header: " + string(first))
-		}
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/patch/patch.go b/src/pkg/patch/patch.go
deleted file mode 100644
index fcc8307..0000000
--- a/src/pkg/patch/patch.go
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package patch implements parsing and execution of the textual and
-// binary patch descriptions used by version control tools such as
-// CVS, Git, Mercurial, and Subversion.
-package patch
-
-import (
-	"bytes"
-	"os"
-	"path"
-	"strings"
-)
-
-// A Set represents a set of patches to be applied as a single atomic unit.
-// Patch sets are often preceded by a descriptive header.
-type Set struct {
-	Header string // free-form text
-	File   []*File
-}
-
-// A File represents a collection of changes to be made to a single file.
-type File struct {
-	Verb             Verb
-	Src              string // source for Verb == Copy, Verb == Rename
-	Dst              string
-	OldMode, NewMode int // 0 indicates not used
-	Diff                 // changes to data; == NoDiff if operation does not edit file
-}
-
-// A Verb is an action performed on a file.
-type Verb string
-
-const (
-	Add    Verb = "add"
-	Copy   Verb = "copy"
-	Delete Verb = "delete"
-	Edit   Verb = "edit"
-	Rename Verb = "rename"
-)
-
-// A Diff is any object that describes changes to transform
-// an old byte stream to a new one.
-type Diff interface {
-	// Apply applies the changes listed in the diff
-	// to the string s, returning the new version of the string.
-	// Note that the string s need not be a text string.
-	Apply(old []byte) (new []byte, err os.Error)
-}
-
-// NoDiff is a no-op Diff implementation: it passes the
-// old data through unchanged.
-var NoDiff Diff = noDiffType(0)
-
-type noDiffType int
-
-func (noDiffType) Apply(old []byte) ([]byte, os.Error) {
-	return old, nil
-}
-
-// A SyntaxError represents a syntax error encountered while parsing a patch.
-type SyntaxError string
-
-func (e SyntaxError) String() string { return string(e) }
-
-var newline = []byte{'\n'}
-
-// Parse patches the patch text to create a patch Set.
-// The patch text typically comprises a textual header and a sequence
-// of file patches, as would be generated by CVS, Subversion,
-// Mercurial, or Git.
-func Parse(text []byte) (*Set, os.Error) {
-	// Split text into files.
-	// CVS and Subversion begin new files with
-	//	Index: file name.
-	//	==================
-	//	diff -u blah blah
-	//
-	// Mercurial and Git use
-	//	diff [--git] a/file/path b/file/path.
-	//
-	// First look for Index: lines.  If none, fall back on diff lines.
-	text, files := sections(text, "Index: ")
-	if len(files) == 0 {
-		text, files = sections(text, "diff ")
-	}
-
-	set := &Set{string(text), make([]*File, len(files))}
-
-	// Parse file header and then
-	// parse files into patch chunks.
-	// Each chunk begins with @@.
-	for i, raw := range files {
-		p := new(File)
-		set.File[i] = p
-
-		// First line of hdr is the Index: that
-		// begins the section.  After that is the file name.
-		s, raw, _ := getLine(raw, 1)
-		if hasPrefix(s, "Index: ") {
-			p.Dst = string(bytes.TrimSpace(s[7:]))
-			goto HaveName
-		} else if hasPrefix(s, "diff ") {
-			str := string(bytes.TrimSpace(s))
-			i := strings.LastIndex(str, " b/")
-			if i >= 0 {
-				p.Dst = str[i+3:]
-				goto HaveName
-			}
-		}
-		return nil, SyntaxError("unexpected patch header line: " + string(s))
-	HaveName:
-		p.Dst = path.Clean(p.Dst)
-		if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") {
-			return nil, SyntaxError("invalid path: " + p.Dst)
-		}
-
-		// Parse header lines giving file information:
-		//	new file mode %o	- file created
-		//	deleted file mode %o	- file deleted
-		//	old file mode %o	- file mode changed
-		//	new file mode %o	- file mode changed
-		//	rename from %s	- file renamed from other file
-		//	rename to %s
-		//	copy from %s		- file copied from other file
-		//	copy to %s
-		p.Verb = Edit
-		for len(raw) > 0 {
-			oldraw := raw
-			var l []byte
-			l, raw, _ = getLine(raw, 1)
-			l = bytes.TrimSpace(l)
-			if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 {
-				p.NewMode = m
-				p.Verb = Add
-				continue
-			}
-			if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 {
-				p.OldMode = m
-				p.Verb = Delete
-				p.Src = p.Dst
-				p.Dst = ""
-				continue
-			}
-			if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 {
-				// usually implies p.Verb = "rename" or "copy"
-				// but we'll get that from the rename or copy line.
-				p.OldMode = m
-				continue
-			}
-			if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 {
-				p.OldMode = m
-				continue
-			}
-			if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 {
-				p.NewMode = m
-				continue
-			}
-			if s, ok := skip(l, "rename from "); ok && len(s) > 0 {
-				p.Src = string(s)
-				p.Verb = Rename
-				continue
-			}
-			if s, ok := skip(l, "rename to "); ok && len(s) > 0 {
-				p.Verb = Rename
-				continue
-			}
-			if s, ok := skip(l, "copy from "); ok && len(s) > 0 {
-				p.Src = string(s)
-				p.Verb = Copy
-				continue
-			}
-			if s, ok := skip(l, "copy to "); ok && len(s) > 0 {
-				p.Verb = Copy
-				continue
-			}
-			if s, ok := skip(l, "Binary file "); ok && len(s) > 0 {
-				// Hg prints
-				//	Binary file foo has changed
-				// when deleting a binary file.
-				continue
-			}
-			if s, ok := skip(l, "RCS file: "); ok && len(s) > 0 {
-				// CVS prints
-				//	RCS file: /cvs/plan9/bin/yesterday,v
-				//	retrieving revision 1.1
-				// for each file.
-				continue
-			}
-			if s, ok := skip(l, "retrieving revision "); ok && len(s) > 0 {
-				// CVS prints
-				//	RCS file: /cvs/plan9/bin/yesterday,v
-				//	retrieving revision 1.1
-				// for each file.
-				continue
-			}
-			if hasPrefix(l, "===") || hasPrefix(l, "---") || hasPrefix(l, "+++") || hasPrefix(l, "diff ") {
-				continue
-			}
-			if hasPrefix(l, "@@ -") {
-				diff, err := ParseTextDiff(oldraw)
-				if err != nil {
-					return nil, err
-				}
-				p.Diff = diff
-				break
-			}
-			if hasPrefix(l, "GIT binary patch") || (hasPrefix(l, "index ") && !hasPrefix(raw, "--- ")) {
-				diff, err := ParseGitBinary(oldraw)
-				if err != nil {
-					return nil, err
-				}
-				p.Diff = diff
-				break
-			}
-			if hasPrefix(l, "index ") {
-				continue
-			}
-			return nil, SyntaxError("unexpected patch header line: " + string(l))
-		}
-		if p.Diff == nil {
-			p.Diff = NoDiff
-		}
-		if p.Verb == Edit {
-			p.Src = p.Dst
-		}
-	}
-
-	return set, nil
-}
-
-// getLine returns the first n lines of data and the remainder.
-// If data has no newline, getLine returns data, nil, false
-func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
-	rest = data
-	ok = true
-	for ; n > 0; n-- {
-		nl := bytes.Index(rest, newline)
-		if nl < 0 {
-			rest = nil
-			ok = false
-			break
-		}
-		rest = rest[nl+1:]
-	}
-	first = data[0 : len(data)-len(rest)]
-	return
-}
-
-// sections returns a collection of file sections,
-// each of which begins with a line satisfying prefix.
-// text before the first instance of such a line is
-// returned separately.
-func sections(text []byte, prefix string) ([]byte, [][]byte) {
-	n := 0
-	for b := text; ; {
-		if hasPrefix(b, prefix) {
-			n++
-		}
-		nl := bytes.Index(b, newline)
-		if nl < 0 {
-			break
-		}
-		b = b[nl+1:]
-	}
-
-	sect := make([][]byte, n+1)
-	n = 0
-	for b := text; ; {
-		if hasPrefix(b, prefix) {
-			sect[n] = text[0 : len(text)-len(b)]
-			n++
-			text = b
-		}
-		nl := bytes.Index(b, newline)
-		if nl < 0 {
-			sect[n] = text
-			break
-		}
-		b = b[nl+1:]
-	}
-	return sect[0], sect[1:]
-}
-
-// if s begins with the prefix t, skip returns
-// s with that prefix removed and ok == true.
-func skip(s []byte, t string) (ss []byte, ok bool) {
-	if len(s) < len(t) || string(s[0:len(t)]) != t {
-		return nil, false
-	}
-	return s[len(t):], true
-}
-
-// if s begins with the prefix t and then is a sequence
-// of digits in the given base, atoi returns the number
-// represented by the digits and s with the
-// prefix and the digits removed.
-func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) {
-	if s, ok = skip(s, t); !ok {
-		return
-	}
-	var i int
-	for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ {
-		n = n*base + int(s[i]-'0')
-	}
-	if i == 0 {
-		return
-	}
-	return n, s[i:], true
-}
-
-// hasPrefix returns true if s begins with t.
-func hasPrefix(s []byte, t string) bool {
-	_, ok := skip(s, t)
-	return ok
-}
-
-// splitLines returns the result of splitting s into lines.
-// The \n on each line is preserved.
-func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline) }
diff --git a/src/pkg/patch/patch_test.go b/src/pkg/patch/patch_test.go
deleted file mode 100644
index 0a4aef7..0000000
--- a/src/pkg/patch/patch_test.go
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package patch
-
-// TODO(rsc): test Apply
-
-import "testing"
-
-type Test struct {
-	in   string
-	out  string
-	diff string
-}
-
-func TestFileApply(t *testing.T) {
-	for i, test := range tests {
-		set, err := Parse([]byte(test.diff))
-		if err != nil {
-			t.Errorf("#%d: Parse: %s", i, err)
-			continue
-		}
-		if len(set.File) != 1 {
-			t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File))
-			continue
-		}
-		new, err := set.File[0].Apply([]byte(test.in))
-		if err != nil {
-			t.Errorf("#%d: Apply: %s", i, err)
-			continue
-		}
-		if s := string(new); s != test.out {
-			t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out)
-		}
-	}
-}
-
-var tests = []Test{
-	{
-		"hello, world\n",
-		"goodbye, world\n",
-		"Index: a\n" +
-			"--- a/a\n" +
-			"+++ b/b\n" +
-			"@@ -1 +1 @@\n" +
-			"-hello, world\n" +
-			"+goodbye, world\n",
-	},
-	{
-		"hello, world\n",
-		"goodbye, world\n",
-		"Index: a\n" +
-			"index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f\n" +
-			"--- a/a\n" +
-			"+++ b/b\n" +
-			"@@ -1 +1 @@\n" +
-			"-hello, world\n" +
-			"+goodbye, world\n",
-	},
-	{
-		"hello, world\n",
-		"goodbye, world\n",
-		"diff a/a b/b\n" +
-			"--- a/a\n" +
-			"+++ b/b\n" +
-			"@@ -1,1 +1,1 @@\n" +
-			"-hello, world\n" +
-			"+goodbye, world\n",
-	},
-	{
-		"hello, world",
-		"goodbye, world\n",
-		"diff --git a/a b/b\n" +
-			"--- a/a\n" +
-			"+++ b/b\n" +
-			"@@ -1 +1 @@\n" +
-			"-hello, world\n" +
-			"\\ No newline at end of file\n" +
-			"+goodbye, world\n",
-	},
-	{
-		"hello, world\n",
-		"goodbye, world",
-		"Index: a\n" +
-			"--- a/a\n" +
-			"+++ b/b\n" +
-			"@@ -1 +1 @@\n" +
-			"-hello, world\n" +
-			"+goodbye, world\n" +
-			"\\ No newline at end of file\n",
-	},
-	{
-		"hello, world",
-		"goodbye, world",
-		"Index: a\n" +
-			"--- a/a\n" +
-			"+++ b/b\n" +
-			"@@ -1 +1 @@\n" +
-			"-hello, world\n" +
-			"\\ No newline at end of file\n" +
-			"+goodbye, world\n" +
-			"\\ No newline at end of file\n",
-	},
-	{
-		"a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\n",
-		"a\nB\nC\nD\ne\nf\ng\nj\nk\nl\nm\nN\n",
-		"Index: a\n" +
-			"--- a/a\n" +
-			"+++ b/b\n" +
-			"@@ -1,14 +1,12 @@\n" +
-			" a\n" +
-			"-b\n" +
-			"-c\n" +
-			"-d\n" +
-			"+B\n" +
-			"+C\n" +
-			"+D\n" +
-			" e\n" +
-			" f\n" +
-			" g\n" +
-			"-h\n" +
-			"-i\n" +
-			" j\n" +
-			" k\n" +
-			" l\n" +
-			" m\n" +
-			"-n\n" +
-			"+N\n",
-	},
-	{
-		"a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
-		"a\nb\nc\ng\nh\ni\nj\nk\nl\nm\nN\nO\np\nq\nr\ns\nt\nu\nv\nw\nd\ne\nf\nx\n",
-		"Index: a\n" +
-			"--- a/a\n" +
-			"+++ b/b\n" +
-			"@@ -1,9 +1,6 @@\n" +
-			" a\n" +
-			" b\n" +
-			" c\n" +
-			"-d\n" +
-			"-e\n" +
-			"-f\n" +
-			" g\n" +
-			" h\n" +
-			" i\n" +
-			"@@ -11,8 +8,8 @@ j\n" +
-			" k\n" +
-			" l\n" +
-			" m\n" +
-			"-n\n" +
-			"-o\n" +
-			"+N\n" +
-			"+O\n" +
-			" p\n" +
-			" q\n" +
-			" r\n" +
-			"\n" +
-			"@@ -21,6 +18,7 @@ t\n" +
-			" u\n" +
-			" v\n" +
-			" w\n" +
-			"+d\n" +
-			"+e\n" +
-			"+f\n" +
-			" x\n" +
-			"-y\n" +
-			"-z\n",
-	},
-	{
-		"a\nb\nc\ng\nh\ni\nj\nk\nl\nm\nN\nO\np\nq\nr\ns\nt\nu\nv\nw\nd\ne\nf\nx\n",
-		"a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
-		"Index: a\n" +
-			"--- a/b\n" +
-			"+++ b/a\n" +
-			"@@ -1,6 +1,9 @@\n" +
-			" a\n" +
-			" b\n" +
-			" c\n" +
-			"+d\n" +
-			"+e\n" +
-			"+f\n" +
-			" g\n" +
-			" h\n" +
-			" i\n" +
-			"@@ -8,8 +11,8 @@ j\n" +
-			" k\n" +
-			" l\n" +
-			" m\n" +
-			"-N\n" +
-			"-O\n" +
-			"+n\n" +
-			"+o\n" +
-			" p\n" +
-			" q\n" +
-			" r\n" +
-			"@@ -18,7 +21,6 @@ t\n" +
-			" u\n" +
-			" v\n" +
-			" w\n" +
-			"-d\n" +
-			"-e\n" +
-			"-f\n" +
-			" x\n" +
-			"+y\n" +
-			"+z\n",
-	},
-	{
-		"a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
-		"",
-		"Index: a\n" +
-			"deleted file mode 100644\n" +
-			"--- a/a\n" +
-			"+++ /dev/null\n" +
-			"@@ -1,26 +0,0 @@\n" +
-			"-a\n" +
-			"-b\n" +
-			"-c\n" +
-			"-d\n" +
-			"-e\n" +
-			"-f\n" +
-			"-g\n" +
-			"-h\n" +
-			"-i\n" +
-			"-j\n" +
-			"-k\n" +
-			"-l\n" +
-			"-m\n" +
-			"-n\n" +
-			"-o\n" +
-			"-p\n" +
-			"-q\n" +
-			"-r\n" +
-			"-s\n" +
-			"-t\n" +
-			"-u\n" +
-			"-v\n" +
-			"-w\n" +
-			"-x\n" +
-			"-y\n" +
-			"-z\n",
-	},
-	{
-		"",
-		"a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
-		"Index: a\n" +
-			"new file mode 100644\n" +
-			"--- /dev/null\n" +
-			"+++ b/a\n" +
-			"@@ -0,0 +1,26 @@\n" +
-			"+a\n" +
-			"+b\n" +
-			"+c\n" +
-			"+d\n" +
-			"+e\n" +
-			"+f\n" +
-			"+g\n" +
-			"+h\n" +
-			"+i\n" +
-			"+j\n" +
-			"+k\n" +
-			"+l\n" +
-			"+m\n" +
-			"+n\n" +
-			"+o\n" +
-			"+p\n" +
-			"+q\n" +
-			"+r\n" +
-			"+s\n" +
-			"+t\n" +
-			"+u\n" +
-			"+v\n" +
-			"+w\n" +
-			"+x\n" +
-			"+y\n" +
-			"+z\n",
-	},
-	{
-		"\xc2\xd8\xf9\x63\x8c\xf7\xc6\x9b\xb0\x3c\x39\xfa\x08\x8e\x42\x8f" +
-			"\x1c\x7c\xaf\x54\x22\x87\xc3\xc5\x68\x9b\xe1\xbd\xbc\xc3\xe0\xda" +
-			"\xcc\xe3\x96\xda\xc2\xaf\xbb\x75\x79\x64\x86\x60\x8a\x43\x9e\x07" +
-			"\x9c\xaa\x92\x88\xd4\x30\xb9\x8b\x95\x04\x60\x71\xc7\xbb\x2d\x93" +
-			"\x66\x73\x01\x24\xf3\x63\xbf\xe6\x1d\x38\x15\x56\x98\xc4\x1f\x85" +
-			"\xc3\x60\x39\x3a\x0d\x57\x53\x0c\x29\x3f\xbb\x44\x7e\x56\x56\x9d" +
-			"\x87\xcf\xf6\x88\xe8\x98\x05\x85\xf8\xfe\x44\x21\xfa\x33\xc9\xa4" +
-			"\x22\xbe\x89\x05\x8b\x82\x76\xc9\x7c\xaf\x48\x28\xc4\x86\x15\x89" +
-			"\xb9\x98\xfa\x41\xfc\x3d\x8d\x80\x29\x33\x17\x45\xa5\x7f\x67\x79" +
-			"\x7f\x92\x3b\x2e\x4c\xc1\xd2\x1b\x9e\xcf\xed\x53\x56\xb2\x49\x58" +
-			"\xd8\xe9\x9f\x98\xa3\xfe\x78\xe1\xe8\x74\x71\x04\x1a\x87\xd9\x68" +
-			"\x18\x68\xd0\xae\x7b\xa4\x25\xe3\x06\x03\x7e\x8b\xd3\x50\x1f\xb1" +
-			"\x67\x08\xe3\x93\xf4\x4f\xa1\xfb\x31\xcf\x99\x5a\x43\x9f\x4b\xc4" +
-			"\xaa\x68\x1a\xf9\x8e\x97\x02\x80\x17\xf1\x25\x21\xdf\x94\xbf\x41" +
-			"\x08\x59\x3d\xea\x36\x23\x03\xb5\x62\x4d\xb6\x8f\x9e\xdf\x1f\x03" +
-			"\x7d\x70\xe0\x6f\x46\x08\x96\x79\x72\xb7\xae\x41\x2b\xbd\x2a\x95",
-
-		"\x8e\x5f\xf8\x79\x36\x8d\xbe\x68\xc4\x2c\x78\x8a\x46\x28\x40\x3e" +
-			"\xcf\x3b\xb9\x14\xaf\xfa\x04\x9e\x4b\xa2\x52\x51\x51\xf0\xad\xd3" +
-			"\x03\x1c\x03\x79\x5f\x53\xc7\x1a\xd5\x28\xe2\xd9\x19\x37\xa4\xfa" +
-			"\xdd\xff\xac\xb5\xa9\x42\x4e\x17\xeb\xb4\x0d\x20\x67\x08\x43\x21" +
-			"\x7d\x12\x27\xfa\x96\x7a\x85\xf8\x04\x5f\xf4\xfe\xda\x9f\x66\xf2" +
-			"\xba\x04\x39\x00\xab\x3f\x23\x20\x84\x53\xb4\x88\xb6\xee\xa2\x9e" +
-			"\xc1\xca\xd4\x09\x2a\x27\x89\x2f\xcb\xba\xa6\x41\xb6\xe9\xc5\x08" +
-			"\xff\xf5\x95\x35\xab\xbb\x5c\x62\x96\xe7\x7c\x8f\xf2\x40\x12\xc9" +
-			"\x2d\xfe\xff\x75\x4f\x70\x47\xc9\xcd\x15\x0a\x1c\x23\xe7\x0f\x15" +
-			"\x95\x75\x30\x8f\x6e\x9f\x7e\xa5\x9d\xd1\x65\x1c\x4d\x4e\xf4\x32" +
-			"\x49\x9b\xa1\x30\x44\x62\x6f\xe2\xe6\x69\x09\xf8\x7c\x7c\xbe\x07" +
-			"\xa9\xb6\x14\x7a\x6b\x85\xe4\xbf\x48\xbe\x5b\x3b\x70\xb3\x79\x3b" +
-			"\xc4\x35\x9d\x86\xf1\xfe\x2b\x6f\x80\x74\x50\xf3\x96\x59\x53\x1a" +
-			"\x75\x46\x9d\x57\x72\xb3\xb1\x26\xf5\x81\xcd\x96\x08\xbc\x2b\x10" +
-			"\xdc\x80\xbd\xd0\xdf\x03\x6d\x8d\xec\x30\x2b\x4c\xdb\x4d\x3b\xef" +
-			"\x7d\x3a\x39\xc8\x5a\xc4\xcc\x24\x37\xde\xe2\x95\x2b\x04\x97\xb0",
-
-		// From git diff --binary
-		"Index: a\n" +
-			"index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f 100644\n" +
-			"GIT binary patch\n" +
-			"literal 256\n" +
-			"zcmV+b0ssDvU-)@8jlO8aEO?4WC_p~XJGm6E`UIX!qEb;&@U7DW90Pe at Q^y+BDB{@}\n" +
-			"zH>CRA|E#sCLQWU!v<)C<2ty%#5-0kWdWHA|U-bUkpJwv91UUe!KO-Q7Q?!V-?xLQ-\n" +
-			"z%G3!eCy6i1x~4(4>BR{D^_4ZNyIf+H=X{UyKoZF<{{MAPa7W3_6$%_9=MNQ?buf=^\n" +
-			"zpMIsC(PbP>PV_QKo1rj7VsGN+X$kmze7*;%wiJ46h2+0TzFRwRvw1tjHJyg>{wr^Q\n" +
-			"zbWrn_SyLKyMx9r3v#}=ifz6f(yekmgfW6S)18t4$Fe^;kO*`*>IyuN%#LOf&-r|)j\n" +
-			"G1edVN^?m&S\n" +
-			"\n" +
-			"literal 256\n" +
-			"zcmV+b0ssEO*!g3O_r{yBJURLZjzW(de6Lg at hr`8ao8i5@!{FM?<CfaOue)`5WQJgh\n" +
-			"zL!Jkms*;G*Fu9AB1YmK;yDgJua{(mtW54DdI2Bfy#2<yjU^zMsS5pirKf6SJR#u&d\n" +
-			"z&-RGum<5IS{zM`AGs&bPzKI2kf_BM#uSh7wh82mqnEFBdJ&k}VGZ#gre`k4rk~=O;\n" +
-			"z!O|O^&+SuIvPoFj>7SUR{&?Z&ba4b4huLTtXwa^Eq$T491AdFsP#>{p2;-CVPoeuU\n" +
-			"z&zV|7pG(B5Xd3yBmjZwn at g*VOl)pg;Sv~4DBLlT!O}3Ao-yZ{gaNuu72$p$rx2{1e\n" +
-			"Gy(*Pb;D3Ms\n" +
-			"\n",
-	},
-	{
-		"\xc2\xd8\xf9\x63\x8c\xf7\xc6\x9b\xb0\x3c\x39\xfa\x08\x8e\x42\x8f" +
-			"\x1c\x7c\xaf\x54\x22\x87\xc3\xc5\x68\x9b\xe1\xbd\xbc\xc3\xe0\xda" +
-			"\xcc\xe3\x96\xda\xc2\xaf\xbb\x75\x79\x64\x86\x60\x8a\x43\x9e\x07" +
-			"\x9c\xaa\x92\x88\xd4\x30\xb9\x8b\x95\x04\x60\x71\xc7\xbb\x2d\x93" +
-			"\x66\x73\x01\x24\xf3\x63\xbf\xe6\x1d\x38\x15\x56\x98\xc4\x1f\x85" +
-			"\xc3\x60\x39\x3a\x0d\x57\x53\x0c\x29\x3f\xbb\x44\x7e\x56\x56\x9d" +
-			"\x87\xcf\xf6\x88\xe8\x98\x05\x85\xf8\xfe\x44\x21\xfa\x33\xc9\xa4" +
-			"\x22\xbe\x89\x05\x8b\x82\x76\xc9\x7c\xaf\x48\x28\xc4\x86\x15\x89" +
-			"\xb9\x98\xfa\x41\xfc\x3d\x8d\x80\x29\x33\x17\x45\xa5\x7f\x67\x79" +
-			"\x7f\x92\x3b\x2e\x4c\xc1\xd2\x1b\x9e\xcf\xed\x53\x56\xb2\x49\x58" +
-			"\xd8\xe9\x9f\x98\xa3\xfe\x78\xe1\xe8\x74\x71\x04\x1a\x87\xd9\x68" +
-			"\x18\x68\xd0\xae\x7b\xa4\x25\xe3\x06\x03\x7e\x8b\xd3\x50\x1f\xb1" +
-			"\x67\x08\xe3\x93\xf4\x4f\xa1\xfb\x31\xcf\x99\x5a\x43\x9f\x4b\xc4" +
-			"\xaa\x68\x1a\xf9\x8e\x97\x02\x80\x17\xf1\x25\x21\xdf\x94\xbf\x41" +
-			"\x08\x59\x3d\xea\x36\x23\x03\xb5\x62\x4d\xb6\x8f\x9e\xdf\x1f\x03" +
-			"\x7d\x70\xe0\x6f\x46\x08\x96\x79\x72\xb7\xae\x41\x2b\xbd\x2a\x95",
-
-		"\x8e\x5f\xf8\x79\x36\x8d\xbe\x68\xc4\x2c\x78\x8a\x46\x28\x40\x3e" +
-			"\xcf\x3b\xb9\x14\xaf\xfa\x04\x9e\x4b\xa2\x52\x51\x51\xf0\xad\xd3" +
-			"\x03\x1c\x03\x79\x5f\x53\xc7\x1a\xd5\x28\xe2\xd9\x19\x37\xa4\xfa" +
-			"\xdd\xff\xac\xb5\xa9\x42\x4e\x17\xeb\xb4\x0d\x20\x67\x08\x43\x21" +
-			"\x7d\x12\x27\xfa\x96\x7a\x85\xf8\x04\x5f\xf4\xfe\xda\x9f\x66\xf2" +
-			"\xba\x04\x39\x00\xab\x3f\x23\x20\x84\x53\xb4\x88\xb6\xee\xa2\x9e" +
-			"\xc1\xca\xd4\x09\x2a\x27\x89\x2f\xcb\xba\xa6\x41\xb6\xe9\xc5\x08" +
-			"\xff\xf5\x95\x35\xab\xbb\x5c\x62\x96\xe7\x7c\x8f\xf2\x40\x12\xc9" +
-			"\x2d\xfe\xff\x75\x4f\x70\x47\xc9\xcd\x15\x0a\x1c\x23\xe7\x0f\x15" +
-			"\x95\x75\x30\x8f\x6e\x9f\x7e\xa5\x9d\xd1\x65\x1c\x4d\x4e\xf4\x32" +
-			"\x49\x9b\xa1\x30\x44\x62\x6f\xe2\xe6\x69\x09\xf8\x7c\x7c\xbe\x07" +
-			"\xa9\xb6\x14\x7a\x6b\x85\xe4\xbf\x48\xbe\x5b\x3b\x70\xb3\x79\x3b" +
-			"\xc4\x35\x9d\x86\xf1\xfe\x2b\x6f\x80\x74\x50\xf3\x96\x59\x53\x1a" +
-			"\x75\x46\x9d\x57\x72\xb3\xb1\x26\xf5\x81\xcd\x96\x08\xbc\x2b\x10" +
-			"\xdc\x80\xbd\xd0\xdf\x03\x6d\x8d\xec\x30\x2b\x4c\xdb\x4d\x3b\xef" +
-			"\x7d\x3a\x39\xc8\x5a\xc4\xcc\x24\x37\xde\xe2\x95\x2b\x04\x97\xb0",
-
-		// From hg diff --git
-		"Index: a\n" +
-			"index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f\n" +
-			"GIT binary patch\n" +
-			"literal 256\n" +
-			"zc$@(M0ssDvU-)@8jlO8aEO?4WC_p~XJGm6E`UIX!qEb;&@U7DW90Pe at Q^y+BDB{@}\n" +
-			"zH>CRA|E#sCLQWU!v<)C<2ty%#5-0kWdWHA|U-bUkpJwv91UUe!KO-Q7Q?!V-?xLQ-\n" +
-			"z%G3!eCy6i1x~4(4>BR{D^_4ZNyIf+H=X{UyKoZF<{{MAPa7W3_6$%_9=MNQ?buf=^\n" +
-			"zpMIsC(PbP>PV_QKo1rj7VsGN+X$kmze7*;%wiJ46h2+0TzFRwRvw1tjHJyg>{wr^Q\n" +
-			"zbWrn_SyLKyMx9r3v#}=ifz6f(yekmgfW6S)18t4$Fe^;kO*`*>IyuN%#LOf&-r|)j\n" +
-			"G1edVN^?m&S\n" +
-			"\n",
-	},
-	{
-		"",
-		"",
-		"Index: hello\n" +
-			"===================================================================\n" +
-			"old mode 100644\n" +
-			"new mode 100755\n",
-	},
-}
diff --git a/src/pkg/patch/textdiff.go b/src/pkg/patch/textdiff.go
deleted file mode 100644
index 482bd67..0000000
--- a/src/pkg/patch/textdiff.go
+++ /dev/null
@@ -1,175 +0,0 @@
-package patch
-
-import (
-	"bytes"
-	"os"
-)
-
-type TextDiff []TextChunk
-
-// A TextChunk specifies an edit to a section of a file:
-// the text beginning at Line, which should be exactly Old,
-// is to be replaced with New.
-type TextChunk struct {
-	Line int
-	Old  []byte
-	New  []byte
-}
-
-func ParseTextDiff(raw []byte) (TextDiff, os.Error) {
-	var chunkHeader []byte
-
-	// Copy raw so it is safe to keep references to slices.
-	_, chunks := sections(raw, "@@ -")
-	delta := 0
-	diff := make(TextDiff, len(chunks))
-	for i, raw := range chunks {
-		c := &diff[i]
-
-		// Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk
-		chunk := splitLines(raw)
-		chunkHeader = chunk[0]
-		var ok bool
-		var oldLine, oldCount, newLine, newCount int
-		s := chunkHeader
-		if oldLine, s, ok = atoi(s, "@@ -", 10); !ok {
-			goto ErrChunkHdr
-		}
-		if len(s) == 0 || s[0] != ',' {
-			oldCount = 1
-		} else if oldCount, s, ok = atoi(s, ",", 10); !ok {
-			goto ErrChunkHdr
-		}
-		if newLine, s, ok = atoi(s, " +", 10); !ok {
-			goto ErrChunkHdr
-		}
-		if len(s) == 0 || s[0] != ',' {
-			newCount = 1
-		} else if newCount, s, ok = atoi(s, ",", 10); !ok {
-			goto ErrChunkHdr
-		}
-		if !hasPrefix(s, " @@") {
-			goto ErrChunkHdr
-		}
-
-		// Special case: for created or deleted files, the empty half
-		// is given as starting at line 0.  Translate to line 1.
-		if oldCount == 0 && oldLine == 0 {
-			oldLine = 1
-		}
-		if newCount == 0 && newLine == 0 {
-			newLine = 1
-		}
-
-		// Count lines in text
-		var dropOldNL, dropNewNL bool
-		var nold, nnew int
-		var lastch byte
-		chunk = chunk[1:]
-		for _, l := range chunk {
-			if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') {
-				if len(bytes.TrimSpace(l)) != 0 {
-					return nil, SyntaxError("too many chunk lines")
-				}
-				continue
-			}
-			if len(l) == 0 {
-				return nil, SyntaxError("empty chunk line")
-			}
-			switch l[0] {
-			case '+':
-				nnew++
-			case '-':
-				nold++
-			case ' ':
-				nnew++
-				nold++
-			case '\\':
-				if _, ok := skip(l, "\\ No newline at end of file"); ok {
-					switch lastch {
-					case '-':
-						dropOldNL = true
-					case '+':
-						dropNewNL = true
-					case ' ':
-						dropOldNL = true
-						dropNewNL = true
-					default:
-						return nil, SyntaxError("message `\\ No newline at end of file' out of context")
-					}
-					break
-				}
-				fallthrough
-			default:
-				return nil, SyntaxError("unexpected chunk line: " + string(l))
-			}
-			lastch = l[0]
-		}
-
-		// Does it match the header?
-		if nold != oldCount || nnew != newCount {
-			return nil, SyntaxError("chunk header does not match line count: " + string(chunkHeader))
-		}
-		if oldLine+delta != newLine {
-			return nil, SyntaxError("chunk delta is out of sync with previous chunks")
-		}
-		delta += nnew - nold
-		c.Line = oldLine
-
-		var old, new bytes.Buffer
-		nold = 0
-		nnew = 0
-		for _, l := range chunk {
-			if nold == oldCount && nnew == newCount {
-				break
-			}
-			ch, l := l[0], l[1:]
-			if ch == '\\' {
-				continue
-			}
-			if ch != '+' {
-				old.Write(l)
-				nold++
-			}
-			if ch != '-' {
-				new.Write(l)
-				nnew++
-			}
-		}
-		c.Old = old.Bytes()
-		c.New = new.Bytes()
-		if dropOldNL {
-			c.Old = c.Old[0 : len(c.Old)-1]
-		}
-		if dropNewNL {
-			c.New = c.New[0 : len(c.New)-1]
-		}
-	}
-	return diff, nil
-
-ErrChunkHdr:
-	return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader))
-}
-
-var ErrPatchFailure = os.NewError("patch did not apply cleanly")
-
-// Apply applies the changes listed in the diff
-// to the data, returning the new version.
-func (d TextDiff) Apply(data []byte) ([]byte, os.Error) {
-	var buf bytes.Buffer
-	line := 1
-	for _, c := range d {
-		var ok bool
-		var prefix []byte
-		prefix, data, ok = getLine(data, c.Line-line)
-		if !ok || !bytes.HasPrefix(data, c.Old) {
-			return nil, ErrPatchFailure
-		}
-		buf.Write(prefix)
-		data = data[len(c.Old):]
-		buf.Write(c.New)
-		line = c.Line + bytes.Count(c.Old, newline)
-	}
-	buf.Write(data)
-	return buf.Bytes(), nil
-}
diff --git a/src/pkg/path/example_test.go b/src/pkg/path/example_test.go
new file mode 100644
index 0000000..82ddfab
--- /dev/null
+++ b/src/pkg/path/example_test.go
@@ -0,0 +1,61 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package path_test
+
+import (
+	"fmt"
+	"path"
+)
+
+// b
+func ExampleBase() {
+	fmt.Println(path.Base("/a/b"))
+}
+
+// Clean("a/c") = "a/c"
+// Clean("a//c") = "a/c"
+// Clean("a/c/.") = "a/c"
+// Clean("a/c/b/..") = "a/c"
+// Clean("/../a/c") = "/a/c"
+// Clean("/../a/b/../././/c") = "/a/c"
+func ExampleClean() {
+	paths := []string{
+		"a/c",
+		"a//c",
+		"a/c/.",
+		"a/c/b/..",
+		"/../a/c",
+		"/../a/b/../././/c",
+	}
+
+	for _, p := range paths {
+		fmt.Printf("Clean(%q) = %q\n", p, path.Clean(p))
+	}
+}
+
+// /a/b
+func ExampleDir() {
+	fmt.Println(path.Dir("/a/b/c"))
+}
+
+// .css
+func ExampleExt() {
+	fmt.Println(path.Ext("/a/b/c/bar.css"))
+}
+
+// true
+func ExampleIsAbs() {
+	fmt.Println(path.IsAbs("/dev/null"))
+}
+
+// a/b/c
+func ExampleJoin() {
+	fmt.Println(path.Join("a", "b", "c"))
+}
+
+// static/ myfile.css
+func ExampleSplit() {
+	fmt.Println(path.Split("static/myfile.css"))
+}
diff --git a/src/pkg/path/filepath/Makefile b/src/pkg/path/filepath/Makefile
index af250ab..7f8ea30 100644
--- a/src/pkg/path/filepath/Makefile
+++ b/src/pkg/path/filepath/Makefile
@@ -18,6 +18,9 @@ GOFILES_darwin=\
 GOFILES_linux=\
 	path_unix.go
 
+GOFILES_netbsd=\
+	path_unix.go
+
 GOFILES_openbsd=\
 	path_unix.go
 
diff --git a/src/pkg/path/filepath/match.go b/src/pkg/path/filepath/match.go
index 0ccc87e..c3678f5 100644
--- a/src/pkg/path/filepath/match.go
+++ b/src/pkg/path/filepath/match.go
@@ -5,13 +5,14 @@
 package filepath
 
 import (
+	"errors"
 	"os"
 	"sort"
 	"strings"
-	"utf8"
+	"unicode/utf8"
 )
 
-var ErrBadPattern = os.NewError("syntax error in pattern")
+var ErrBadPattern = errors.New("syntax error in pattern")
 
 // Match returns true if name matches the shell file name pattern.
 // The pattern syntax is:
@@ -34,7 +35,7 @@ var ErrBadPattern = os.NewError("syntax error in pattern")
 // Match requires pattern to match all of name, not just a substring.
 // The only possible error return occurs when the pattern is malformed.
 //
-func Match(pattern, name string) (matched bool, err os.Error) {
+func Match(pattern, name string) (matched bool, err error) {
 Pattern:
 	for len(pattern) > 0 {
 		var star bool
@@ -112,7 +113,7 @@ Scan:
 // matchChunk checks whether chunk matches the beginning of s.
 // If so, it returns the remainder of s (after the match).
 // Chunk is all single-character operators: literals, char classes, and ?.
-func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) {
+func matchChunk(chunk, s string) (rest string, ok bool, err error) {
 	for len(chunk) > 0 {
 		if len(s) == 0 {
 			return
@@ -136,7 +137,7 @@ func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) {
 					chunk = chunk[1:]
 					break
 				}
-				var lo, hi int
+				var lo, hi rune
 				if lo, chunk, err = getEsc(chunk); err != nil {
 					return
 				}
@@ -183,7 +184,7 @@ func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) {
 }
 
 // getEsc gets a possibly-escaped character from chunk, for a character class.
-func getEsc(chunk string) (r int, nchunk string, err os.Error) {
+func getEsc(chunk string) (r rune, nchunk string, err error) {
 	if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' {
 		err = ErrBadPattern
 		return
@@ -212,7 +213,7 @@ func getEsc(chunk string) (r int, nchunk string, err os.Error) {
 // /usr/*/bin/ed (assuming the Separator is '/').
 // The only possible error return occurs when the pattern is malformed.
 //
-func Glob(pattern string) (matches []string, err os.Error) {
+func Glob(pattern string) (matches []string, err error) {
 	if !hasMeta(pattern) {
 		if _, err = os.Stat(pattern); err != nil {
 			return nil, nil
@@ -253,13 +254,13 @@ func Glob(pattern string) (matches []string, err os.Error) {
 // opened, it returns the existing matches. New matches are
 // added in lexicographical order.
 // The only possible error return occurs when the pattern is malformed.
-func glob(dir, pattern string, matches []string) (m []string, e os.Error) {
+func glob(dir, pattern string, matches []string) (m []string, e error) {
 	m = matches
 	fi, err := os.Stat(dir)
 	if err != nil {
 		return
 	}
-	if !fi.IsDirectory() {
+	if !fi.IsDir() {
 		return
 	}
 	d, err := os.Open(dir)
diff --git a/src/pkg/path/filepath/match_test.go b/src/pkg/path/filepath/match_test.go
index 711e835..7bdc449 100644
--- a/src/pkg/path/filepath/match_test.go
+++ b/src/pkg/path/filepath/match_test.go
@@ -5,16 +5,15 @@
 package filepath_test
 
 import (
-	"os"
 	. "path/filepath"
-	"testing"
 	"runtime"
+	"testing"
 )
 
 type MatchTest struct {
 	pattern, s string
 	match      bool
-	err        os.Error
+	err        error
 }
 
 var matchTests = []MatchTest{
@@ -69,11 +68,11 @@ var matchTests = []MatchTest{
 	{"*x", "xxx", true, nil},
 }
 
-func errp(e os.Error) string {
+func errp(e error) string {
 	if e == nil {
 		return "<nil>"
 	}
-	return e.String()
+	return e.Error()
 }
 
 func TestMatch(t *testing.T) {
diff --git a/src/pkg/path/filepath/path.go b/src/pkg/path/filepath/path.go
index c40d9ff..3dc52aa 100644
--- a/src/pkg/path/filepath/path.go
+++ b/src/pkg/path/filepath/path.go
@@ -8,6 +8,7 @@ package filepath
 
 import (
 	"bytes"
+	"errors"
 	"os"
 	"runtime"
 	"sort"
@@ -146,6 +147,7 @@ func SplitList(path string) []string {
 // separating it into a directory and file name component.
 // If there is no Separator in path, Split returns an empty dir
 // and file set to path.
+// The returned values have the property that path = dir+file.
 func Split(path string) (dir, file string) {
 	vol := VolumeName(path)
 	i := len(path) - 1
@@ -182,7 +184,7 @@ func Ext(path string) string {
 // EvalSymlinks returns the path name after the evaluation of any symbolic
 // links.
 // If path is relative it will be evaluated relative to the current directory.
-func EvalSymlinks(path string) (string, os.Error) {
+func EvalSymlinks(path string) (string, error) {
 	if runtime.GOOS == "windows" {
 		// Symlinks are not supported under windows.
 		_, err := os.Lstat(path)
@@ -198,7 +200,7 @@ func EvalSymlinks(path string) (string, os.Error) {
 	var b bytes.Buffer
 	for n := 0; path != ""; n++ {
 		if n > maxIter {
-			return "", os.NewError("EvalSymlinks: too many links in " + originalPath)
+			return "", errors.New("EvalSymlinks: too many links in " + originalPath)
 		}
 
 		// find next path component, p
@@ -222,7 +224,7 @@ func EvalSymlinks(path string) (string, os.Error) {
 		if err != nil {
 			return "", err
 		}
-		if !fi.IsSymlink() {
+		if fi.Mode()&os.ModeSymlink == 0 {
 			b.WriteString(p)
 			if path != "" {
 				b.WriteRune(Separator)
@@ -247,7 +249,7 @@ func EvalSymlinks(path string) (string, os.Error) {
 // If the path is not absolute it will be joined with the current
 // working directory to turn it into an absolute path.  The absolute
 // path name for a given file is not guaranteed to be unique.
-func Abs(path string) (string, os.Error) {
+func Abs(path string) (string, error) {
 	if IsAbs(path) {
 		return Clean(path), nil
 	}
@@ -258,10 +260,85 @@ func Abs(path string) (string, os.Error) {
 	return Join(wd, path), nil
 }
 
+// Rel returns a relative path that is lexically equivalent to targpath when
+// joined to basepath with an intervening separator. That is,
+// Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself.
+// On success, the returned path will always be relative to basepath,
+// even if basepath and targpath share no elements.
+// An error is returned if targpath can't be made relative to basepath or if
+// knowing the current working directory would be necessary to compute it.
+func Rel(basepath, targpath string) (string, error) {
+	baseVol := VolumeName(basepath)
+	targVol := VolumeName(targpath)
+	base := Clean(basepath)
+	targ := Clean(targpath)
+	if targ == base {
+		return ".", nil
+	}
+	base = base[len(baseVol):]
+	targ = targ[len(targVol):]
+	if base == "." {
+		base = ""
+	}
+	// Can't use IsAbs - `\a` and `a` are both relative in Windows.
+	baseSlashed := len(base) > 0 && base[0] == Separator
+	targSlashed := len(targ) > 0 && targ[0] == Separator
+	if baseSlashed != targSlashed || baseVol != targVol {
+		return "", errors.New("Rel: can't make " + targ + " relative to " + base)
+	}
+	// Position base[b0:bi] and targ[t0:ti] at the first differing elements.
+	bl := len(base)
+	tl := len(targ)
+	var b0, bi, t0, ti int
+	for {
+		for bi < bl && base[bi] != Separator {
+			bi++
+		}
+		for ti < tl && targ[ti] != Separator {
+			ti++
+		}
+		if targ[t0:ti] != base[b0:bi] {
+			break
+		}
+		if bi < bl {
+			bi++
+		}
+		if ti < tl {
+			ti++
+		}
+		b0 = bi
+		t0 = ti
+	}
+	if base[b0:bi] == ".." {
+		return "", errors.New("Rel: can't make " + targ + " relative to " + base)
+	}
+	if b0 != bl {
+		// Base elements left. Must go up before going down.
+		seps := strings.Count(base[b0:bl], string(Separator))
+		size := 2 + seps*3
+		if tl != t0 {
+			size += 1 + tl - t0
+		}
+		buf := make([]byte, size)
+		n := copy(buf, "..")
+		for i := 0; i < seps; i++ {
+			buf[n] = Separator
+			copy(buf[n+1:], "..")
+			n += 3
+		}
+		if t0 != tl {
+			buf[n] = Separator
+			copy(buf[n+1:], targ[t0:])
+		}
+		return string(buf), nil
+	}
+	return targ[t0:], nil
+}
+
 // SkipDir is used as a return value from WalkFuncs to indicate that
 // the directory named in the call is to be skipped. It is not returned
 // as an error by any function.
-var SkipDir = os.NewError("skip this directory")
+var SkipDir = errors.New("skip this directory")
 
 // WalkFunc is the type of the function called for each file or directory
 // visited by Walk.  If there was a problem walking to the file or directory
@@ -271,19 +348,19 @@ var SkipDir = os.NewError("skip this directory")
 // sole exception is that if path is a directory and the function returns the
 // special value SkipDir, the contents of the directory are skipped
 // and processing continues as usual on the next file.
-type WalkFunc func(path string, info *os.FileInfo, err os.Error) os.Error
+type WalkFunc func(path string, info os.FileInfo, err error) error
 
 // walk recursively descends path, calling w.
-func walk(path string, info *os.FileInfo, walkFn WalkFunc) os.Error {
+func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
 	err := walkFn(path, info, nil)
 	if err != nil {
-		if info.IsDirectory() && err == SkipDir {
+		if info.IsDir() && err == SkipDir {
 			return nil
 		}
 		return err
 	}
 
-	if !info.IsDirectory() {
+	if !info.IsDir() {
 		return nil
 	}
 
@@ -293,7 +370,7 @@ func walk(path string, info *os.FileInfo, walkFn WalkFunc) os.Error {
 	}
 
 	for _, fileInfo := range list {
-		if err = walk(Join(path, fileInfo.Name), fileInfo, walkFn); err != nil {
+		if err = walk(Join(path, fileInfo.Name()), fileInfo, walkFn); err != nil {
 			return err
 		}
 	}
@@ -305,7 +382,7 @@ func walk(path string, info *os.FileInfo, walkFn WalkFunc) os.Error {
 // and directories are filtered by walkFn. The files are walked in lexical
 // order, which makes the output deterministic but means that for very
 // large directories Walk can be inefficient.
-func Walk(root string, walkFn WalkFunc) os.Error {
+func Walk(root string, walkFn WalkFunc) error {
 	info, err := os.Lstat(root)
 	if err != nil {
 		return walkFn(root, nil, err)
@@ -316,7 +393,7 @@ func Walk(root string, walkFn WalkFunc) os.Error {
 // readDir reads the directory named by dirname and returns
 // a sorted list of directory entries.
 // Copied from io/ioutil to avoid the circular import.
-func readDir(dirname string) ([]*os.FileInfo, os.Error) {
+func readDir(dirname string) ([]os.FileInfo, error) {
 	f, err := os.Open(dirname)
 	if err != nil {
 		return nil, err
@@ -326,20 +403,16 @@ func readDir(dirname string) ([]*os.FileInfo, os.Error) {
 	if err != nil {
 		return nil, err
 	}
-	fi := make(fileInfoList, len(list))
-	for i := range list {
-		fi[i] = &list[i]
-	}
-	sort.Sort(fi)
-	return fi, nil
+	sort.Sort(byName(list))
+	return list, nil
 }
 
-// A dirList implements sort.Interface.
-type fileInfoList []*os.FileInfo
+// byName implements sort.Interface.
+type byName []os.FileInfo
 
-func (f fileInfoList) Len() int           { return len(f) }
-func (f fileInfoList) Less(i, j int) bool { return f[i].Name < f[j].Name }
-func (f fileInfoList) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
+func (f byName) Len() int           { return len(f) }
+func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
+func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
 
 // Base returns the last element of path.
 // Trailing path separators are removed before extracting the last element.
@@ -353,6 +426,8 @@ func Base(path string) string {
 	for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
 		path = path[0 : len(path)-1]
 	}
+	// Throw away volume name
+	path = path[len(VolumeName(path)):]
 	// Find the last element
 	i := len(path) - 1
 	for i >= 0 && !os.IsPathSeparator(path[i]) {
@@ -367,3 +442,25 @@ func Base(path string) string {
 	}
 	return path
 }
+
+// Dir returns the all but the last element of path, typically the path's directory.
+// Trailing path separators are removed before processing.
+// If the path is empty, Dir returns ".".
+// If the path consists entirely of separators, Dir returns a single separator.
+// The returned path does not end in a separator unless it is the root directory.
+func Dir(path string) string {
+	vol := VolumeName(path)
+	i := len(path) - 1
+	for i >= len(vol) && !os.IsPathSeparator(path[i]) {
+		i--
+	}
+	dir := Clean(path[len(vol) : i+1])
+	last := len(dir) - 1
+	if last > 0 && os.IsPathSeparator(dir[last]) {
+		dir = dir[:last]
+	}
+	if dir == "" {
+		dir = "."
+	}
+	return vol + dir
+}
diff --git a/src/pkg/path/filepath/path_test.go b/src/pkg/path/filepath/path_test.go
index 850ead8..11b636c 100644
--- a/src/pkg/path/filepath/path_test.go
+++ b/src/pkg/path/filepath/path_test.go
@@ -260,19 +260,19 @@ type Node struct {
 var tree = &Node{
 	"testdata",
 	[]*Node{
-		&Node{"a", nil, 0},
-		&Node{"b", []*Node{}, 0},
-		&Node{"c", nil, 0},
-		&Node{
+		{"a", nil, 0},
+		{"b", []*Node{}, 0},
+		{"c", nil, 0},
+		{
 			"d",
 			[]*Node{
-				&Node{"x", nil, 0},
-				&Node{"y", []*Node{}, 0},
-				&Node{
+				{"x", nil, 0},
+				{"y", []*Node{}, 0},
+				{
 					"z",
 					[]*Node{
-						&Node{"u", nil, 0},
-						&Node{"v", nil, 0},
+						{"u", nil, 0},
+						{"v", nil, 0},
 					},
 					0,
 				},
@@ -296,6 +296,7 @@ func makeTree(t *testing.T) {
 			fd, err := os.Create(path)
 			if err != nil {
 				t.Errorf("makeTree: %v", err)
+				return
 			}
 			fd.Close()
 		} else {
@@ -318,7 +319,7 @@ func checkMarks(t *testing.T, report bool) {
 // Assumes that each node name is unique. Good enough for a test.
 // If clear is true, any incoming error is cleared before return. The errors
 // are always accumulated, though.
-func mark(path string, info *os.FileInfo, err os.Error, errors *[]os.Error, clear bool) os.Error {
+func mark(path string, info os.FileInfo, err error, errors *[]error, clear bool) error {
 	if err != nil {
 		*errors = append(*errors, err)
 		if clear {
@@ -326,8 +327,9 @@ func mark(path string, info *os.FileInfo, err os.Error, errors *[]os.Error, clea
 		}
 		return err
 	}
+	name := info.Name()
 	walkTree(tree, tree.name, func(path string, n *Node) {
-		if n.name == info.Name {
+		if n.name == name {
 			n.mark++
 		}
 	})
@@ -336,18 +338,18 @@ func mark(path string, info *os.FileInfo, err os.Error, errors *[]os.Error, clea
 
 func TestWalk(t *testing.T) {
 	makeTree(t)
-	errors := make([]os.Error, 0, 10)
+	errors := make([]error, 0, 10)
 	clear := true
-	markFn := func(path string, info *os.FileInfo, err os.Error) os.Error {
+	markFn := func(path string, info os.FileInfo, err error) error {
 		return mark(path, info, err, &errors, clear)
 	}
 	// Expect no errors.
 	err := filepath.Walk(tree.name, markFn)
 	if err != nil {
-		t.Errorf("no error expected, found: %s", err)
+		t.Fatalf("no error expected, found: %s", err)
 	}
 	if len(errors) != 0 {
-		t.Errorf("unexpected errors: %s", errors)
+		t.Fatalf("unexpected errors: %s", errors)
 	}
 	checkMarks(t, true)
 	errors = errors[0:0]
@@ -369,7 +371,7 @@ func TestWalk(t *testing.T) {
 		tree.entries[3].mark--
 		err := filepath.Walk(tree.name, markFn)
 		if err != nil {
-			t.Errorf("expected no error return from Walk, %s", err)
+			t.Fatalf("expected no error return from Walk, got %s", err)
 		}
 		if len(errors) != 2 {
 			t.Errorf("expected 2 errors, got %d: %s", len(errors), errors)
@@ -388,7 +390,7 @@ func TestWalk(t *testing.T) {
 		clear = false // error will stop processing
 		err = filepath.Walk(tree.name, markFn)
 		if err == nil {
-			t.Errorf("expected error return from Walk")
+			t.Fatalf("expected error return from Walk")
 		}
 		if len(errors) != 1 {
 			t.Errorf("expected 1 error, got %d: %s", len(errors), errors)
@@ -422,14 +424,77 @@ var basetests = []PathTest{
 	{"a/b/c.x", "c.x"},
 }
 
+var winbasetests = []PathTest{
+	{`c:\`, `\`},
+	{`c:.`, `.`},
+	{`c:\a\b`, `b`},
+	{`c:a\b`, `b`},
+	{`c:a\b\c`, `c`},
+	{`\\host\share\`, `\`},
+	{`\\host\share\a`, `a`},
+	{`\\host\share\a\b`, `b`},
+}
+
 func TestBase(t *testing.T) {
-	for _, test := range basetests {
-		if s := filepath.ToSlash(filepath.Base(test.path)); s != test.result {
+	tests := basetests
+	if runtime.GOOS == "windows" {
+		// make unix tests work on windows
+		for i, _ := range tests {
+			tests[i].result = filepath.Clean(tests[i].result)
+		}
+		// add windows specific tests
+		tests = append(tests, winbasetests...)
+	}
+	for _, test := range tests {
+		if s := filepath.Base(test.path); s != test.result {
 			t.Errorf("Base(%q) = %q, want %q", test.path, s, test.result)
 		}
 	}
 }
 
+var dirtests = []PathTest{
+	{"", "."},
+	{".", "."},
+	{"/.", "/"},
+	{"/", "/"},
+	{"////", "/"},
+	{"/foo", "/"},
+	{"x/", "x"},
+	{"abc", "."},
+	{"abc/def", "abc"},
+	{"a/b/.x", "a/b"},
+	{"a/b/c.", "a/b"},
+	{"a/b/c.x", "a/b"},
+}
+
+var windirtests = []PathTest{
+	{`c:\`, `c:\`},
+	{`c:.`, `c:.`},
+	{`c:\a\b`, `c:\a`},
+	{`c:a\b`, `c:a`},
+	{`c:a\b\c`, `c:a\b`},
+	{`\\host\share\`, `\\host\share\`},
+	{`\\host\share\a`, `\\host\share\`},
+	{`\\host\share\a\b`, `\\host\share\a`},
+}
+
+func TestDir(t *testing.T) {
+	tests := dirtests
+	if runtime.GOOS == "windows" {
+		// make unix tests work on windows
+		for i, _ := range tests {
+			tests[i].result = filepath.Clean(tests[i].result)
+		}
+		// add windows specific tests
+		tests = append(tests, windirtests...)
+	}
+	for _, test := range tests {
+		if s := filepath.Dir(test.path); s != test.result {
+			t.Errorf("Dir(%q) = %q, want %q", test.path, s, test.result)
+		}
+	}
+}
+
 type IsAbsTest struct {
 	path  string
 	isAbs bool
@@ -523,7 +588,7 @@ func testEvalSymlinks(t *testing.T, tests []EvalSymlinksTest) {
 func TestEvalSymlinks(t *testing.T) {
 	defer os.RemoveAll("test")
 	for _, d := range EvalSymlinksTestDirs {
-		var err os.Error
+		var err error
 		if d.dest == "" {
 			err = os.Mkdir(d.path, 0755)
 		} else {
@@ -572,16 +637,17 @@ var abstests = []string{
 	"pkg/../../AUTHORS",
 	"Make.pkg",
 	"pkg/Makefile",
-
-	// Already absolute
+	".",
 	"$GOROOT/src/Make.pkg",
 	"$GOROOT/src/../src/Make.pkg",
+	"$GOROOT/misc/cgo",
+	"$GOROOT",
 }
 
 func TestAbs(t *testing.T) {
 	oldwd, err := os.Getwd()
 	if err != nil {
-		t.Fatal("Getwd failed: " + err.String())
+		t.Fatal("Getwd failed: " + err.Error())
 	}
 	defer os.Chdir(oldwd)
 	goroot := os.Getenv("GOROOT")
@@ -589,16 +655,19 @@ func TestAbs(t *testing.T) {
 	os.Chdir(cwd)
 	for _, path := range abstests {
 		path = strings.Replace(path, "$GOROOT", goroot, -1)
-		abspath, err := filepath.Abs(path)
-		if err != nil {
-			t.Errorf("Abs(%q) error: %v", path, err)
-		}
 		info, err := os.Stat(path)
 		if err != nil {
 			t.Errorf("%s: %s", path, err)
+			continue
+		}
+
+		abspath, err := filepath.Abs(path)
+		if err != nil {
+			t.Errorf("Abs(%q) error: %v", path, err)
+			continue
 		}
 		absinfo, err := os.Stat(abspath)
-		if err != nil || absinfo.Ino != info.Ino {
+		if err != nil || !absinfo.(*os.FileStat).SameFile(info.(*os.FileStat)) {
 			t.Errorf("Abs(%q)=%q, not the same file", path, abspath)
 		}
 		if !filepath.IsAbs(abspath) {
@@ -610,6 +679,85 @@ func TestAbs(t *testing.T) {
 	}
 }
 
+type RelTests struct {
+	root, path, want string
+}
+
+var reltests = []RelTests{
+	{"a/b", "a/b", "."},
+	{"a/b/.", "a/b", "."},
+	{"a/b", "a/b/.", "."},
+	{"./a/b", "a/b", "."},
+	{"a/b", "./a/b", "."},
+	{"ab/cd", "ab/cde", "../cde"},
+	{"ab/cd", "ab/c", "../c"},
+	{"a/b", "a/b/c/d", "c/d"},
+	{"a/b", "a/b/../c", "../c"},
+	{"a/b/../c", "a/b", "../b"},
+	{"a/b/c", "a/c/d", "../../c/d"},
+	{"a/b", "c/d", "../../c/d"},
+	{"a/b/c/d", "a/b", "../.."},
+	{"a/b/c/d", "a/b/", "../.."},
+	{"a/b/c/d/", "a/b", "../.."},
+	{"a/b/c/d/", "a/b/", "../.."},
+	{"../../a/b", "../../a/b/c/d", "c/d"},
+	{"/a/b", "/a/b", "."},
+	{"/a/b/.", "/a/b", "."},
+	{"/a/b", "/a/b/.", "."},
+	{"/ab/cd", "/ab/cde", "../cde"},
+	{"/ab/cd", "/ab/c", "../c"},
+	{"/a/b", "/a/b/c/d", "c/d"},
+	{"/a/b", "/a/b/../c", "../c"},
+	{"/a/b/../c", "/a/b", "../b"},
+	{"/a/b/c", "/a/c/d", "../../c/d"},
+	{"/a/b", "/c/d", "../../c/d"},
+	{"/a/b/c/d", "/a/b", "../.."},
+	{"/a/b/c/d", "/a/b/", "../.."},
+	{"/a/b/c/d/", "/a/b", "../.."},
+	{"/a/b/c/d/", "/a/b/", "../.."},
+	{"/../../a/b", "/../../a/b/c/d", "c/d"},
+	{".", "a/b", "a/b"},
+	{".", "..", ".."},
+
+	// can't do purely lexically
+	{"..", ".", "err"},
+	{"..", "a", "err"},
+	{"../..", "..", "err"},
+	{"a", "/a", "err"},
+	{"/a", "a", "err"},
+}
+
+var winreltests = []RelTests{
+	{`C:a\b\c`, `C:a/b/d`, `..\d`},
+	{`C:\`, `D:\`, `err`},
+	{`C:`, `D:`, `err`},
+}
+
+func TestRel(t *testing.T) {
+	tests := append([]RelTests{}, reltests...)
+	if runtime.GOOS == "windows" {
+		for i := range tests {
+			tests[i].want = filepath.FromSlash(tests[i].want)
+		}
+		tests = append(tests, winreltests...)
+	}
+	for _, test := range tests {
+		got, err := filepath.Rel(test.root, test.path)
+		if test.want == "err" {
+			if err == nil {
+				t.Errorf("Rel(%q, %q)=%q, want error", test.root, test.path, got)
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("Rel(%q, %q): want %q, got error: %s", test.root, test.path, test.want, err)
+		}
+		if got != test.want {
+			t.Errorf("Rel(%q, %q)=%q, want %q", test.root, test.path, got, test.want)
+		}
+	}
+}
+
 type VolumeNameTest struct {
 	path string
 	vol  string
diff --git a/src/pkg/path/filepath/path_unix.go b/src/pkg/path/filepath/path_unix.go
index daf0eb2..c5ac71e 100644
--- a/src/pkg/path/filepath/path_unix.go
+++ b/src/pkg/path/filepath/path_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package filepath
 
diff --git a/src/pkg/path/match.go b/src/pkg/path/match.go
index efb8c5c..ba7e4de 100644
--- a/src/pkg/path/match.go
+++ b/src/pkg/path/match.go
@@ -5,12 +5,12 @@
 package path
 
 import (
-	"os"
+	"errors"
 	"strings"
-	"utf8"
+	"unicode/utf8"
 )
 
-var ErrBadPattern = os.NewError("syntax error in pattern")
+var ErrBadPattern = errors.New("syntax error in pattern")
 
 // Match returns true if name matches the shell file name pattern.
 // The pattern syntax is:
@@ -33,7 +33,7 @@ var ErrBadPattern = os.NewError("syntax error in pattern")
 // Match requires pattern to match all of name, not just a substring.
 // The only possible error return is when pattern is malformed.
 //
-func Match(pattern, name string) (matched bool, err os.Error) {
+func Match(pattern, name string) (matched bool, err error) {
 Pattern:
 	for len(pattern) > 0 {
 		var star bool
@@ -111,7 +111,7 @@ Scan:
 // matchChunk checks whether chunk matches the beginning of s.
 // If so, it returns the remainder of s (after the match).
 // Chunk is all single-character operators: literals, char classes, and ?.
-func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) {
+func matchChunk(chunk, s string) (rest string, ok bool, err error) {
 	for len(chunk) > 0 {
 		if len(s) == 0 {
 			return
@@ -136,7 +136,7 @@ func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) {
 					chunk = chunk[1:]
 					break
 				}
-				var lo, hi int
+				var lo, hi rune
 				if lo, chunk, err = getEsc(chunk); err != nil {
 					return
 				}
@@ -183,7 +183,7 @@ func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) {
 }
 
 // getEsc gets a possibly-escaped character from chunk, for a character class.
-func getEsc(chunk string) (r int, nchunk string, err os.Error) {
+func getEsc(chunk string) (r rune, nchunk string, err error) {
 	if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' {
 		err = ErrBadPattern
 		return
diff --git a/src/pkg/path/match_test.go b/src/pkg/path/match_test.go
index f377f10..730b6b9 100644
--- a/src/pkg/path/match_test.go
+++ b/src/pkg/path/match_test.go
@@ -4,15 +4,12 @@
 
 package path
 
-import (
-	"os"
-	"testing"
-)
+import "testing"
 
 type MatchTest struct {
 	pattern, s string
 	match      bool
-	err        os.Error
+	err        error
 }
 
 var matchTests = []MatchTest{
diff --git a/src/pkg/path/path.go b/src/pkg/path/path.go
index 2353846..20d89c9 100644
--- a/src/pkg/path/path.go
+++ b/src/pkg/path/path.go
@@ -160,3 +160,21 @@ func Base(path string) string {
 func IsAbs(path string) bool {
 	return len(path) > 0 && path[0] == '/'
 }
+
+// Dir returns the all but the last element of path, typically the path's directory.
+// Trailing path separators are removed before processing.
+// If the path is empty, Dir returns ".".
+// If the path consists entirely of separators, Dir returns a single separator.
+// The returned path does not end in a separator unless it is the root directory.
+func Dir(path string) string {
+	dir, _ := Split(path)
+	dir = Clean(dir)
+	last := len(dir) - 1
+	if last > 0 && dir[last] == '/' {
+		dir = dir[:last]
+	}
+	if dir == "" {
+		dir = "."
+	}
+	return dir
+}
diff --git a/src/pkg/path/path_test.go b/src/pkg/path/path_test.go
index 1fd57cc..77f0804 100644
--- a/src/pkg/path/path_test.go
+++ b/src/pkg/path/path_test.go
@@ -8,11 +8,11 @@ import (
 	"testing"
 )
 
-type CleanTest struct {
-	path, clean string
+type PathTest struct {
+	path, result string
 }
 
-var cleantests = []CleanTest{
+var cleantests = []PathTest{
 	// Already clean
 	{"", "."},
 	{"abc", "abc"},
@@ -64,8 +64,8 @@ var cleantests = []CleanTest{
 
 func TestClean(t *testing.T) {
 	for _, test := range cleantests {
-		if s := Clean(test.path); s != test.clean {
-			t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.clean)
+		if s := Clean(test.path); s != test.result {
+			t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.result)
 		}
 	}
 }
@@ -148,7 +148,7 @@ func TestExt(t *testing.T) {
 	}
 }
 
-var basetests = []CleanTest{
+var basetests = []PathTest{
 	// Already clean
 	{"", "."},
 	{".", "."},
@@ -165,8 +165,31 @@ var basetests = []CleanTest{
 
 func TestBase(t *testing.T) {
 	for _, test := range basetests {
-		if s := Base(test.path); s != test.clean {
-			t.Errorf("Base(%q) = %q, want %q", test.path, s, test.clean)
+		if s := Base(test.path); s != test.result {
+			t.Errorf("Base(%q) = %q, want %q", test.path, s, test.result)
+		}
+	}
+}
+
+var dirtests = []PathTest{
+	{"", "."},
+	{".", "."},
+	{"/.", "/"},
+	{"/", "/"},
+	{"////", "/"},
+	{"/foo", "/"},
+	{"x/", "x"},
+	{"abc", "."},
+	{"abc/def", "abc"},
+	{"a/b/.x", "a/b"},
+	{"a/b/c.", "a/b"},
+	{"a/b/c.x", "a/b"},
+}
+
+func TestDir(t *testing.T) {
+	for _, test := range dirtests {
+		if s := Dir(test.path); s != test.result {
+			t.Errorf("Dir(%q) = %q, want %q", test.path, s, test.result)
 		}
 	}
 }
diff --git a/src/pkg/rand/Makefile b/src/pkg/rand/Makefile
deleted file mode 100644
index ec3b341..0000000
--- a/src/pkg/rand/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=rand
-GOFILES=\
-	exp.go\
-	normal.go\
-	rand.go\
-	rng.go\
-	zipf.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/rand/rand.go b/src/pkg/rand/rand.go
deleted file mode 100644
index 459aed1..0000000
--- a/src/pkg/rand/rand.go
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package rand implements pseudo-random number generators.
-package rand
-
-import "sync"
-
-// A Source represents a source of uniformly-distributed
-// pseudo-random int64 values in the range [0, 1<<63).
-type Source interface {
-	Int63() int64
-	Seed(seed int64)
-}
-
-// NewSource returns a new pseudo-random Source seeded with the given value.
-func NewSource(seed int64) Source {
-	var rng rngSource
-	rng.Seed(seed)
-	return &rng
-}
-
-// A Rand is a source of random numbers.
-type Rand struct {
-	src Source
-}
-
-// New returns a new Rand that uses random values from src
-// to generate other random values.
-func New(src Source) *Rand { return &Rand{src} }
-
-// Seed uses the provided seed value to initialize the generator to a deterministic state.
-func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }
-
-// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
-func (r *Rand) Int63() int64 { return r.src.Int63() }
-
-// Uint32 returns a pseudo-random 32-bit value as a uint32.
-func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
-
-// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
-func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
-
-// Int returns a non-negative pseudo-random int.
-func (r *Rand) Int() int {
-	u := uint(r.Int63())
-	return int(u << 1 >> 1) // clear sign bit if int == int32
-}
-
-// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
-func (r *Rand) Int63n(n int64) int64 {
-	if n <= 0 {
-		return 0
-	}
-	max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
-	v := r.Int63()
-	for v > max {
-		v = r.Int63()
-	}
-	return v % n
-}
-
-// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
-func (r *Rand) Int31n(n int32) int32 {
-	if n <= 0 {
-		return 0
-	}
-	max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
-	v := r.Int31()
-	for v > max {
-		v = r.Int31()
-	}
-	return v % n
-}
-
-// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
-func (r *Rand) Intn(n int) int {
-	if n <= 1<<31-1 {
-		return int(r.Int31n(int32(n)))
-	}
-	return int(r.Int63n(int64(n)))
-}
-
-// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
-func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) }
-
-// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
-func (r *Rand) Float32() float32 { return float32(r.Float64()) }
-
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
-func (r *Rand) Perm(n int) []int {
-	m := make([]int, n)
-	for i := 0; i < n; i++ {
-		m[i] = i
-	}
-	for i := 0; i < n; i++ {
-		j := r.Intn(i + 1)
-		m[i], m[j] = m[j], m[i]
-	}
-	return m
-}
-
-/*
- * Top-level convenience functions
- */
-
-var globalRand = New(&lockedSource{src: NewSource(1)})
-
-// Seed uses the provided seed value to initialize the generator to a deterministic state.
-func Seed(seed int64) { globalRand.Seed(seed) }
-
-// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
-func Int63() int64 { return globalRand.Int63() }
-
-// Uint32 returns a pseudo-random 32-bit value as a uint32.
-func Uint32() uint32 { return globalRand.Uint32() }
-
-// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
-func Int31() int32 { return globalRand.Int31() }
-
-// Int returns a non-negative pseudo-random int.
-func Int() int { return globalRand.Int() }
-
-// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
-func Int63n(n int64) int64 { return globalRand.Int63n(n) }
-
-// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
-func Int31n(n int32) int32 { return globalRand.Int31n(n) }
-
-// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
-func Intn(n int) int { return globalRand.Intn(n) }
-
-// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
-func Float64() float64 { return globalRand.Float64() }
-
-// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
-func Float32() float32 { return globalRand.Float32() }
-
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
-func Perm(n int) []int { return globalRand.Perm(n) }
-
-// NormFloat64 returns a normally distributed float64 in the range
-// [-math.MaxFloat64, +math.MaxFloat64] with
-// standard normal distribution (mean = 0, stddev = 1).
-// To produce a different normal distribution, callers can
-// adjust the output using:
-//
-//  sample = NormFloat64() * desiredStdDev + desiredMean
-//
-func NormFloat64() float64 { return globalRand.NormFloat64() }
-
-// ExpFloat64 returns an exponentially distributed float64 in the range
-// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
-// (lambda) is 1 and whose mean is 1/lambda (1).
-// To produce a distribution with a different rate parameter,
-// callers can adjust the output using:
-//
-//  sample = ExpFloat64() / desiredRateParameter
-//
-func ExpFloat64() float64 { return globalRand.ExpFloat64() }
-
-type lockedSource struct {
-	lk  sync.Mutex
-	src Source
-}
-
-func (r *lockedSource) Int63() (n int64) {
-	r.lk.Lock()
-	n = r.src.Int63()
-	r.lk.Unlock()
-	return
-}
-
-func (r *lockedSource) Seed(seed int64) {
-	r.lk.Lock()
-	r.src.Seed(seed)
-	r.lk.Unlock()
-}
diff --git a/src/pkg/rand/rand_test.go b/src/pkg/rand/rand_test.go
deleted file mode 100644
index 3ebc114..0000000
--- a/src/pkg/rand/rand_test.go
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package rand
-
-import (
-	"math"
-	"fmt"
-	"os"
-	"testing"
-)
-
-const (
-	numTestSamples = 10000
-)
-
-type statsResults struct {
-	mean        float64
-	stddev      float64
-	closeEnough float64
-	maxError    float64
-}
-
-func max(a, b float64) float64 {
-	if a > b {
-		return a
-	}
-	return b
-}
-
-func nearEqual(a, b, closeEnough, maxError float64) bool {
-	absDiff := math.Fabs(a - b)
-	if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero.
-		return true
-	}
-	return absDiff/max(math.Fabs(a), math.Fabs(b)) < maxError
-}
-
-var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
-
-// checkSimilarDistribution returns success if the mean and stddev of the
-// two statsResults are similar.
-func (this *statsResults) checkSimilarDistribution(expected *statsResults) os.Error {
-	if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) {
-		s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError)
-		fmt.Println(s)
-		return os.NewError(s)
-	}
-	if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) {
-		s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError)
-		fmt.Println(s)
-		return os.NewError(s)
-	}
-	return nil
-}
-
-func getStatsResults(samples []float64) *statsResults {
-	res := new(statsResults)
-	var sum float64
-	for i := range samples {
-		sum += samples[i]
-	}
-	res.mean = sum / float64(len(samples))
-	var devsum float64
-	for i := range samples {
-		devsum += math.Pow(samples[i]-res.mean, 2)
-	}
-	res.stddev = math.Sqrt(devsum / float64(len(samples)))
-	return res
-}
-
-func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) {
-	actual := getStatsResults(samples)
-	err := actual.checkSimilarDistribution(expected)
-	if err != nil {
-		t.Errorf(err.String())
-	}
-}
-
-func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) {
-	chunk := len(samples) / nslices
-	for i := 0; i < nslices; i++ {
-		low := i * chunk
-		var high int
-		if i == nslices-1 {
-			high = len(samples) - 1
-		} else {
-			high = (i + 1) * chunk
-		}
-		checkSampleDistribution(t, samples[low:high], expected)
-	}
-}
-
-//
-// Normal distribution tests
-//
-
-func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 {
-	r := New(NewSource(seed))
-	samples := make([]float64, nsamples)
-	for i := range samples {
-		samples[i] = r.NormFloat64()*stddev + mean
-	}
-	return samples
-}
-
-func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) {
-	//fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed);
-
-	samples := generateNormalSamples(nsamples, mean, stddev, seed)
-	errorScale := max(1.0, stddev) // Error scales with stddev
-	expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
-
-	// Make sure that the entire set matches the expected distribution.
-	checkSampleDistribution(t, samples, expected)
-
-	// Make sure that each half of the set matches the expected distribution.
-	checkSampleSliceDistributions(t, samples, 2, expected)
-
-	// Make sure that each 7th of the set matches the expected distribution.
-	checkSampleSliceDistributions(t, samples, 7, expected)
-}
-
-// Actual tests
-
-func TestStandardNormalValues(t *testing.T) {
-	for _, seed := range testSeeds {
-		testNormalDistribution(t, numTestSamples, 0, 1, seed)
-	}
-}
-
-func TestNonStandardNormalValues(t *testing.T) {
-	for sd := 0.5; sd < 1000; sd *= 2 {
-		for m := 0.5; m < 1000; m *= 2 {
-			for _, seed := range testSeeds {
-				testNormalDistribution(t, numTestSamples, m, sd, seed)
-			}
-		}
-	}
-}
-
-//
-// Exponential distribution tests
-//
-
-func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 {
-	r := New(NewSource(seed))
-	samples := make([]float64, nsamples)
-	for i := range samples {
-		samples[i] = r.ExpFloat64() / rate
-	}
-	return samples
-}
-
-func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) {
-	//fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed);
-
-	mean := 1 / rate
-	stddev := mean
-
-	samples := generateExponentialSamples(nsamples, rate, seed)
-	errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate
-	expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale}
-
-	// Make sure that the entire set matches the expected distribution.
-	checkSampleDistribution(t, samples, expected)
-
-	// Make sure that each half of the set matches the expected distribution.
-	checkSampleSliceDistributions(t, samples, 2, expected)
-
-	// Make sure that each 7th of the set matches the expected distribution.
-	checkSampleSliceDistributions(t, samples, 7, expected)
-}
-
-// Actual tests
-
-func TestStandardExponentialValues(t *testing.T) {
-	for _, seed := range testSeeds {
-		testExponentialDistribution(t, numTestSamples, 1, seed)
-	}
-}
-
-func TestNonStandardExponentialValues(t *testing.T) {
-	for rate := 0.05; rate < 10; rate *= 2 {
-		for _, seed := range testSeeds {
-			testExponentialDistribution(t, numTestSamples, rate, seed)
-		}
-	}
-}
-
-//
-// Table generation tests
-//
-
-func initNorm() (testKn []uint32, testWn, testFn []float32) {
-	const m1 = 1 << 31
-	var (
-		dn float64 = rn
-		tn         = dn
-		vn float64 = 9.91256303526217e-3
-	)
-
-	testKn = make([]uint32, 128)
-	testWn = make([]float32, 128)
-	testFn = make([]float32, 128)
-
-	q := vn / math.Exp(-0.5*dn*dn)
-	testKn[0] = uint32((dn / q) * m1)
-	testKn[1] = 0
-	testWn[0] = float32(q / m1)
-	testWn[127] = float32(dn / m1)
-	testFn[0] = 1.0
-	testFn[127] = float32(math.Exp(-0.5 * dn * dn))
-	for i := 126; i >= 1; i-- {
-		dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn)))
-		testKn[i+1] = uint32((dn / tn) * m1)
-		tn = dn
-		testFn[i] = float32(math.Exp(-0.5 * dn * dn))
-		testWn[i] = float32(dn / m1)
-	}
-	return
-}
-
-func initExp() (testKe []uint32, testWe, testFe []float32) {
-	const m2 = 1 << 32
-	var (
-		de float64 = re
-		te         = de
-		ve float64 = 3.9496598225815571993e-3
-	)
-
-	testKe = make([]uint32, 256)
-	testWe = make([]float32, 256)
-	testFe = make([]float32, 256)
-
-	q := ve / math.Exp(-de)
-	testKe[0] = uint32((de / q) * m2)
-	testKe[1] = 0
-	testWe[0] = float32(q / m2)
-	testWe[255] = float32(de / m2)
-	testFe[0] = 1.0
-	testFe[255] = float32(math.Exp(-de))
-	for i := 254; i >= 1; i-- {
-		de = -math.Log(ve/de + math.Exp(-de))
-		testKe[i+1] = uint32((de / te) * m2)
-		te = de
-		testFe[i] = float32(math.Exp(-de))
-		testWe[i] = float32(de / m2)
-	}
-	return
-}
-
-// compareUint32Slices returns the first index where the two slices
-// disagree, or <0 if the lengths are the same and all elements
-// are identical.
-func compareUint32Slices(s1, s2 []uint32) int {
-	if len(s1) != len(s2) {
-		if len(s1) > len(s2) {
-			return len(s2) + 1
-		}
-		return len(s1) + 1
-	}
-	for i := range s1 {
-		if s1[i] != s2[i] {
-			return i
-		}
-	}
-	return -1
-}
-
-// compareFloat32Slices returns the first index where the two slices
-// disagree, or <0 if the lengths are the same and all elements
-// are identical.
-func compareFloat32Slices(s1, s2 []float32) int {
-	if len(s1) != len(s2) {
-		if len(s1) > len(s2) {
-			return len(s2) + 1
-		}
-		return len(s1) + 1
-	}
-	for i := range s1 {
-		if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) {
-			return i
-		}
-	}
-	return -1
-}
-
-func TestNormTables(t *testing.T) {
-	testKn, testWn, testFn := initNorm()
-	if i := compareUint32Slices(kn[0:], testKn); i >= 0 {
-		t.Errorf("kn disagrees at index %v; %v != %v", i, kn[i], testKn[i])
-	}
-	if i := compareFloat32Slices(wn[0:], testWn); i >= 0 {
-		t.Errorf("wn disagrees at index %v; %v != %v", i, wn[i], testWn[i])
-	}
-	if i := compareFloat32Slices(fn[0:], testFn); i >= 0 {
-		t.Errorf("fn disagrees at index %v; %v != %v", i, fn[i], testFn[i])
-	}
-}
-
-func TestExpTables(t *testing.T) {
-	testKe, testWe, testFe := initExp()
-	if i := compareUint32Slices(ke[0:], testKe); i >= 0 {
-		t.Errorf("ke disagrees at index %v; %v != %v", i, ke[i], testKe[i])
-	}
-	if i := compareFloat32Slices(we[0:], testWe); i >= 0 {
-		t.Errorf("we disagrees at index %v; %v != %v", i, we[i], testWe[i])
-	}
-	if i := compareFloat32Slices(fe[0:], testFe); i >= 0 {
-		t.Errorf("fe disagrees at index %v; %v != %v", i, fe[i], testFe[i])
-	}
-}
-
-// Benchmarks
-
-func BenchmarkInt63Threadsafe(b *testing.B) {
-	for n := b.N; n > 0; n-- {
-		Int63()
-	}
-}
-
-func BenchmarkInt63Unthreadsafe(b *testing.B) {
-	r := New(NewSource(1))
-	for n := b.N; n > 0; n-- {
-		r.Int63()
-	}
-}
-
-func BenchmarkIntn1000(b *testing.B) {
-	r := New(NewSource(1))
-	for n := b.N; n > 0; n-- {
-		r.Intn(1000)
-	}
-}
-
-func BenchmarkInt63n1000(b *testing.B) {
-	r := New(NewSource(1))
-	for n := b.N; n > 0; n-- {
-		r.Int63n(1000)
-	}
-}
-
-func BenchmarkInt31n1000(b *testing.B) {
-	r := New(NewSource(1))
-	for n := b.N; n > 0; n-- {
-		r.Int31n(1000)
-	}
-}
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index 610ba4b..63b127d 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -16,6 +16,13 @@ import (
 	"unsafe"
 )
 
+func TestBool(t *testing.T) {
+	v := ValueOf(true)
+	if v.Bool() != true {
+		t.Fatal("ValueOf(true).Bool() = false")
+	}
+}
+
 type integer int
 type T struct {
 	a int
@@ -57,7 +64,7 @@ var typeTests = []pair{
 	{struct{ x (**integer) }{}, "**reflect_test.integer"},
 	{struct{ x ([32]int32) }{}, "[32]int32"},
 	{struct{ x ([]int8) }{}, "[]int8"},
-	{struct{ x (map[string]int32) }{}, "map[string] int32"},
+	{struct{ x (map[string]int32) }{}, "map[string]int32"},
 	{struct{ x (chan<- string) }{}, "chan<- string"},
 	{struct {
 		x struct {
@@ -173,7 +180,7 @@ var valueTests = []pair{
 	{new(**int8), "**int8(0)"},
 	{new([5]int32), "[5]int32{0, 0, 0, 0, 0}"},
 	{new(**integer), "**reflect_test.integer(0)"},
-	{new(map[string]int32), "map[string] int32{<can't iterate on maps>}"},
+	{new(map[string]int32), "map[string]int32{<can't iterate on maps>}"},
 	{new(chan<- string), "chan<- string"},
 	{new(func(a int8, b int32)), "func(int8, int32)(0)"},
 	{new(struct {
@@ -215,7 +222,8 @@ func TestTypes(t *testing.T) {
 
 func TestSet(t *testing.T) {
 	for i, tt := range valueTests {
-		v := ValueOf(tt.i).Elem()
+		v := ValueOf(tt.i)
+		v = v.Elem()
 		switch v.Kind() {
 		case Int:
 			v.SetInt(132)
@@ -411,7 +419,7 @@ func TestAll(t *testing.T) {
 	testType(t, 8, typ.Elem(), "int32")
 
 	typ = TypeOf((map[string]*int32)(nil))
-	testType(t, 9, typ, "map[string] *int32")
+	testType(t, 9, typ, "map[string]*int32")
 	mtyp := typ
 	testType(t, 10, mtyp.Key(), "string")
 	testType(t, 11, mtyp.Elem(), "*int32")
@@ -434,7 +442,7 @@ func TestInterfaceGet(t *testing.T) {
 	inter.E = 123.456
 	v1 := ValueOf(&inter)
 	v2 := v1.Elem().Field(0)
-	assert(t, v2.Type().String(), "interface { }")
+	assert(t, v2.Type().String(), "interface {}")
 	i2 := v2.Interface()
 	v3 := ValueOf(i2)
 	assert(t, v3.Type().String(), "float64")
@@ -447,7 +455,7 @@ func TestInterfaceValue(t *testing.T) {
 	inter.E = 123.456
 	v1 := ValueOf(&inter)
 	v2 := v1.Elem().Field(0)
-	assert(t, v2.Type().String(), "interface { }")
+	assert(t, v2.Type().String(), "interface {}")
 	v3 := v2.Elem()
 	assert(t, v3.Type().String(), "float64")
 
@@ -460,8 +468,8 @@ func TestInterfaceValue(t *testing.T) {
 func TestFunctionValue(t *testing.T) {
 	var x interface{} = func() {}
 	v := ValueOf(x)
-	if v.Interface() != v.Interface() || v.Interface() != x {
-		t.Fatalf("TestFunction != itself")
+	if fmt.Sprint(v.Interface()) != fmt.Sprint(x) {
+		t.Fatalf("TestFunction returned wrong pointer")
 	}
 	assert(t, v.Type().String(), "func()")
 }
@@ -631,7 +639,7 @@ var deepEqualTests = []DeepEqualTest{
 	{make([]int, 10), make([]int, 10), true},
 	{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
 	{Basic{1, 0.5}, Basic{1, 0.5}, true},
-	{os.Error(nil), os.Error(nil), true},
+	{error(nil), error(nil), true},
 	{map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
 
 	// Inequalities
@@ -651,6 +659,14 @@ var deepEqualTests = []DeepEqualTest{
 	{nil, 1, false},
 	{1, nil, false},
 
+	// Nil vs empty: not the same.
+	{[]int{}, []int(nil), false},
+	{[]int{}, []int{}, true},
+	{[]int(nil), []int(nil), true},
+	{map[int]int{}, map[int]int(nil), false},
+	{map[int]int{}, map[int]int{}, true},
+	{map[int]int(nil), map[int]int(nil), true},
+
 	// Mismatched types
 	{1, 1.0, false},
 	{int32(1), int64(1), false},
@@ -853,13 +869,13 @@ func TestIsNil(t *testing.T) {
 
 func TestInterfaceExtraction(t *testing.T) {
 	var s struct {
-		w io.Writer
+		W io.Writer
 	}
 
-	s.w = os.Stdout
+	s.W = os.Stdout
 	v := Indirect(ValueOf(&s)).Field(0).Interface()
-	if v != s.w.(interface{}) {
-		t.Error("Interface() on interface: ", v, s.w)
+	if v != s.W.(interface{}) {
+		t.Error("Interface() on interface: ", v, s.W)
 	}
 }
 
@@ -877,19 +893,20 @@ func TestMap(t *testing.T) {
 		t.Errorf("Len = %d, want %d", n, len(m))
 	}
 	keys := mv.MapKeys()
-	i := 0
 	newmap := MakeMap(mv.Type())
 	for k, v := range m {
 		// Check that returned Keys match keys in range.
-		// These aren't required to be in the same order,
-		// but they are in this implementation, which makes
-		// the test easier.
-		if i >= len(keys) {
-			t.Errorf("Missing key #%d %q", i, k)
-		} else if kv := keys[i]; kv.String() != k {
-			t.Errorf("Keys[%q] = %d, want %d", i, kv.Int(), k)
+		// These aren't required to be in the same order.
+		seen := false
+		for _, kv := range keys {
+			if kv.String() == k {
+				seen = true
+				break
+			}
+		}
+		if !seen {
+			t.Errorf("Missing key %q", k)
 		}
-		i++
 
 		// Check that value lookup is correct.
 		vv := mv.MapIndex(ValueOf(k))
@@ -1091,21 +1108,38 @@ func TestMethod(t *testing.T) {
 	}
 
 	// Curried method of value.
-	i = ValueOf(p).Method(1).Call([]Value{ValueOf(10)})[0].Int()
+	tfunc := TypeOf(func(int) int(nil))
+	v := ValueOf(p).Method(1)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Value Method returned %d; want 250", i)
 	}
-	i = ValueOf(p).MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int()
+	v = ValueOf(p).MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Value MethodByName returned %d; want 250", i)
 	}
 
 	// Curried method of pointer.
-	i = ValueOf(&p).Method(1).Call([]Value{ValueOf(10)})[0].Int()
+	v = ValueOf(&p).Method(1)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Pointer Value Method returned %d; want 250", i)
 	}
-	i = ValueOf(&p).MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int()
+	v = ValueOf(&p).MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Pointer Value MethodByName returned %d; want 250", i)
 	}
@@ -1120,11 +1154,19 @@ func TestMethod(t *testing.T) {
 		}
 	}{p}
 	pv := ValueOf(s).Field(0)
-	i = pv.Method(0).Call([]Value{ValueOf(10)})[0].Int()
+	v = pv.Method(0)
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Interface Method returned %d; want 250", i)
 	}
-	i = pv.MethodByName("Dist").Call([]Value{ValueOf(10)})[0].Int()
+	v = pv.MethodByName("Dist")
+	if tt := v.Type(); tt != tfunc {
+		t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
+	}
+	i = v.Call([]Value{ValueOf(10)})[0].Int()
 	if i != 250 {
 		t.Errorf("Interface MethodByName returned %d; want 250", i)
 	}
@@ -1190,18 +1232,18 @@ type D2 struct {
 }
 
 type S0 struct {
-	a, b, c int
+	A, B, C int
 	D1
 	D2
 }
 
 type S1 struct {
-	b int
+	B int
 	S0
 }
 
 type S2 struct {
-	a int
+	A int
 	*S1
 }
 
@@ -1216,36 +1258,36 @@ type S1y struct {
 type S3 struct {
 	S1x
 	S2
-	d, e int
+	D, E int
 	*S1y
 }
 
 type S4 struct {
 	*S4
-	a int
+	A int
 }
 
 var fieldTests = []FTest{
 	{struct{}{}, "", nil, 0},
-	{struct{}{}, "foo", nil, 0},
-	{S0{a: 'a'}, "a", []int{0}, 'a'},
-	{S0{}, "d", nil, 0},
-	{S1{S0: S0{a: 'a'}}, "a", []int{1, 0}, 'a'},
-	{S1{b: 'b'}, "b", []int{0}, 'b'},
+	{struct{}{}, "Foo", nil, 0},
+	{S0{A: 'a'}, "A", []int{0}, 'a'},
+	{S0{}, "D", nil, 0},
+	{S1{S0: S0{A: 'a'}}, "A", []int{1, 0}, 'a'},
+	{S1{B: 'b'}, "B", []int{0}, 'b'},
 	{S1{}, "S0", []int{1}, 0},
-	{S1{S0: S0{c: 'c'}}, "c", []int{1, 2}, 'c'},
-	{S2{a: 'a'}, "a", []int{0}, 'a'},
+	{S1{S0: S0{C: 'c'}}, "C", []int{1, 2}, 'c'},
+	{S2{A: 'a'}, "A", []int{0}, 'a'},
 	{S2{}, "S1", []int{1}, 0},
-	{S2{S1: &S1{b: 'b'}}, "b", []int{1, 0}, 'b'},
-	{S2{S1: &S1{S0: S0{c: 'c'}}}, "c", []int{1, 1, 2}, 'c'},
-	{S2{}, "d", nil, 0},
+	{S2{S1: &S1{B: 'b'}}, "B", []int{1, 0}, 'b'},
+	{S2{S1: &S1{S0: S0{C: 'c'}}}, "C", []int{1, 1, 2}, 'c'},
+	{S2{}, "D", nil, 0},
 	{S3{}, "S1", nil, 0},
-	{S3{S2: S2{a: 'a'}}, "a", []int{1, 0}, 'a'},
-	{S3{}, "b", nil, 0},
-	{S3{d: 'd'}, "d", []int{2}, 0},
-	{S3{e: 'e'}, "e", []int{3}, 'e'},
-	{S4{a: 'a'}, "a", []int{1}, 'a'},
-	{S4{}, "b", nil, 0},
+	{S3{S2: S2{A: 'a'}}, "A", []int{1, 0}, 'a'},
+	{S3{}, "B", nil, 0},
+	{S3{D: 'd'}, "D", []int{2}, 0},
+	{S3{E: 'e'}, "E", []int{3}, 'e'},
+	{S4{A: 'a'}, "A", []int{1}, 'a'},
+	{S4{}, "B", nil, 0},
 }
 
 func TestFieldByIndex(t *testing.T) {
@@ -1322,8 +1364,19 @@ func TestFieldByName(t *testing.T) {
 }
 
 func TestImportPath(t *testing.T) {
-	if path := TypeOf(&base64.Encoding{}).Elem().PkgPath(); path != "encoding/base64" {
-		t.Errorf(`TypeOf(&base64.Encoding{}).Elem().PkgPath() = %q, want "encoding/base64"`, path)
+	tests := []struct {
+		t    Type
+		path string
+	}{
+		{TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"},
+		{TypeOf(uint(0)), ""},
+		{TypeOf(map[string]int{}), ""},
+		{TypeOf((*error)(nil)).Elem(), ""},
+	}
+	for _, test := range tests {
+		if path := test.t.PkgPath(); path != test.path {
+			t.Errorf("%v.PkgPath() = %q, want %q", test.t, path, test.path)
+		}
 	}
 }
 
@@ -1515,14 +1568,26 @@ func TestSmallNegativeInt(t *testing.T) {
 func TestSlice(t *testing.T) {
 	xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
 	v := ValueOf(xs).Slice(3, 5).Interface().([]int)
-	if len(v) != 2 || v[0] != 4 || v[1] != 5 {
-		t.Errorf("xs.Slice(3, 5) = %v", v)
+	if len(v) != 2 {
+		t.Errorf("len(xs.Slice(3, 5)) = %d", len(v))
+	}
+	if cap(v) != 5 {
+		t.Errorf("cap(xs.Slice(3, 5)) = %d", cap(v))
+	}
+	if !DeepEqual(v[0:5], xs[3:]) {
+		t.Errorf("xs.Slice(3, 5)[0:5] = %v", v[0:5])
 	}
 
-	xa := [7]int{10, 20, 30, 40, 50, 60, 70}
+	xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
 	v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)
-	if len(v) != 3 || v[0] != 30 || v[1] != 40 || v[2] != 50 {
-		t.Errorf("xa.Slice(2, 5) = %v", v)
+	if len(v) != 3 {
+		t.Errorf("len(xa.Slice(2, 5)) = %d", len(v))
+	}
+	if cap(v) != 6 {
+		t.Errorf("cap(xa.Slice(2, 5)) = %d", cap(v))
+	}
+	if !DeepEqual(v[0:6], xa[2:]) {
+		t.Errorf("xs.Slice(2, 5)[0:6] = %v", v[0:6])
 	}
 }
 
@@ -1587,3 +1652,68 @@ func TestSetBytes(t *testing.T) {
 		t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
 	}
 }
+
+type Private struct {
+	x int
+	y **int
+}
+
+func (p *Private) m() {
+}
+
+type Public struct {
+	X int
+	Y **int
+}
+
+func (p *Public) M() {
+}
+
+func TestUnexported(t *testing.T) {
+	var pub Public
+	v := ValueOf(&pub)
+	isValid(v.Elem().Field(0))
+	isValid(v.Elem().Field(1))
+	isValid(v.Elem().FieldByName("X"))
+	isValid(v.Elem().FieldByName("Y"))
+	isValid(v.Type().Method(0).Func)
+	isNonNil(v.Elem().Field(0).Interface())
+	isNonNil(v.Elem().Field(1).Interface())
+	isNonNil(v.Elem().FieldByName("X").Interface())
+	isNonNil(v.Elem().FieldByName("Y").Interface())
+	isNonNil(v.Type().Method(0).Func.Interface())
+
+	var priv Private
+	v = ValueOf(&priv)
+	isValid(v.Elem().Field(0))
+	isValid(v.Elem().Field(1))
+	isValid(v.Elem().FieldByName("x"))
+	isValid(v.Elem().FieldByName("y"))
+	isValid(v.Type().Method(0).Func)
+	shouldPanic(func() { v.Elem().Field(0).Interface() })
+	shouldPanic(func() { v.Elem().Field(1).Interface() })
+	shouldPanic(func() { v.Elem().FieldByName("x").Interface() })
+	shouldPanic(func() { v.Elem().FieldByName("y").Interface() })
+	shouldPanic(func() { v.Type().Method(0).Func.Interface() })
+}
+
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("did not panic")
+		}
+	}()
+	f()
+}
+
+func isNonNil(x interface{}) {
+	if x == nil {
+		panic("nil interface")
+	}
+}
+
+func isValid(v Value) {
+	if !v.IsValid() {
+		panic("zero Value")
+	}
+}
diff --git a/src/pkg/reflect/deepequal.go b/src/pkg/reflect/deepequal.go
index a483135..df5ec0a 100644
--- a/src/pkg/reflect/deepequal.go
+++ b/src/pkg/reflect/deepequal.go
@@ -69,6 +69,9 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
 		}
 		return true
 	case Slice:
+		if v1.IsNil() != v2.IsNil() {
+			return false
+		}
 		if v1.Len() != v2.Len() {
 			return false
 		}
@@ -93,6 +96,9 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
 		}
 		return true
 	case Map:
+		if v1.IsNil() != v2.IsNil() {
+			return false
+		}
 		if v1.Len() != v2.Len() {
 			return false
 		}
@@ -104,7 +110,7 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
 		return true
 	default:
 		// Normal equality suffices
-		return v1.Interface() == v2.Interface()
+		return valueInterface(v1, false) == valueInterface(v2, false)
 	}
 
 	panic("Not reached")
diff --git a/src/pkg/reflect/tostring_test.go b/src/pkg/reflect/tostring_test.go
index 5f5c52b..7486a9b 100644
--- a/src/pkg/reflect/tostring_test.go
+++ b/src/pkg/reflect/tostring_test.go
@@ -23,14 +23,14 @@ func valueToString(val Value) string {
 	typ := val.Type()
 	switch val.Kind() {
 	case Int, Int8, Int16, Int32, Int64:
-		return strconv.Itoa64(val.Int())
+		return strconv.FormatInt(val.Int(), 10)
 	case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
-		return strconv.Uitoa64(val.Uint())
+		return strconv.FormatUint(val.Uint(), 10)
 	case Float32, Float64:
-		return strconv.Ftoa64(val.Float(), 'g', -1)
+		return strconv.FormatFloat(val.Float(), 'g', -1, 64)
 	case Complex64, Complex128:
 		c := val.Complex()
-		return strconv.Ftoa64(real(c), 'g', -1) + "+" + strconv.Ftoa64(imag(c), 'g', -1) + "i"
+		return strconv.FormatFloat(real(c), 'g', -1, 64) + "+" + strconv.FormatFloat(imag(c), 'g', -1, 64) + "i"
 	case String:
 		return val.String()
 	case Bool:
@@ -88,7 +88,7 @@ func valueToString(val Value) string {
 		return typ.String() + "(" + valueToString(val.Elem()) + ")"
 	case Func:
 		v := val
-		return typ.String() + "(" + strconv.Uitoa64(uint64(v.Pointer())) + ")"
+		return typ.String() + "(" + strconv.FormatUint(uint64(v.Pointer()), 10) + ")"
 	default:
 		panic("valueToString: can't print type " + typ.String())
 	}
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index 3630069..15b32ef 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -69,7 +69,7 @@ type Type interface {
 
 	// PkgPath returns the type's package path.
 	// The package path is a full package import path like "encoding/base64".
-	// PkgPath returns an empty string for unnamed types.
+	// PkgPath returns an empty string for unnamed or predeclared types.
 	PkgPath() string
 
 	// Size returns the number of bytes needed to store
@@ -188,7 +188,7 @@ type Type interface {
 
 // A Kind represents the specific kind of type that a Type represents.
 // The zero Kind is not a valid kind.
-type Kind uint8
+type Kind uint
 
 const (
 	Invalid Kind = iota
@@ -241,10 +241,11 @@ const (
 type commonType struct {
 	size       uintptr
 	hash       uint32
-	alg        uint8
+	_          uint8
 	align      uint8
 	fieldAlign uint8
 	kind       uint8
+	alg        *uintptr
 	string     *string
 	*uncommonType
 	ptrToThis *runtime.Type
@@ -455,14 +456,15 @@ func (t *uncommonType) Method(i int) (m Method) {
 	if p.name != nil {
 		m.Name = *p.name
 	}
-	flag := uint32(0)
+	fl := flag(Func) << flagKindShift
 	if p.pkgPath != nil {
 		m.PkgPath = *p.pkgPath
-		flag |= flagRO
+		fl |= flagRO
 	}
-	m.Type = toType(p.typ)
+	mt := toCommonType(p.typ)
+	m.Type = mt
 	fn := p.tfn
-	m.Func = valueFromIword(flag, m.Type, iword(fn))
+	m.Func = Value{mt, fn, fl}
 	m.Index = i
 	return
 }
@@ -768,7 +770,7 @@ func (t *structType) Field(i int) (f StructField) {
 	if i < 0 || i >= len(t.fields) {
 		return
 	}
-	p := t.fields[i]
+	p := &t.fields[i]
 	f.Type = toType(p.typ)
 	if p.name != nil {
 		f.Name = *p.name
@@ -867,16 +869,18 @@ L:
 
 	if n == 1 {
 		// Found matching field.
-		if len(ff.Index) <= depth {
+		if depth >= len(ff.Index) {
 			ff.Index = make([]int, depth+1)
 		}
-		ff.Index[depth] = fi
+		if len(ff.Index) > 1 {
+			ff.Index[depth] = fi
+		}
 	} else {
 		// None or more than one matching field found.
 		fd = inf
 	}
 
-	mark[t] = false, false
+	delete(mark, t)
 	return
 }
 
@@ -906,9 +910,6 @@ func toCommonType(p *runtime.Type) *commonType {
 		t commonType
 	}
 	x := unsafe.Pointer(p)
-	if uintptr(x)&reflectFlags != 0 {
-		panic("reflect: invalid interface value")
-	}
 	return &(*hdr)(x).t
 }
 
@@ -944,10 +945,12 @@ func (t *commonType) runtimeType() *runtime.Type {
 // PtrTo returns the pointer type with element t.
 // For example, if t represents type Foo, PtrTo(t) represents *Foo.
 func PtrTo(t Type) Type {
-	// If t records its pointer-to type, use it.
-	ct := t.(*commonType)
+	return t.(*commonType).ptrTo()
+}
+
+func (ct *commonType) ptrTo() *commonType {
 	if p := ct.ptrToThis; p != nil {
-		return toType(p)
+		return toCommonType(p)
 	}
 
 	// Otherwise, synthesize one.
@@ -959,7 +962,7 @@ func PtrTo(t Type) Type {
 	if m := ptrMap.m; m != nil {
 		if p := m[ct]; p != nil {
 			ptrMap.RUnlock()
-			return p.commonType.toType()
+			return &p.commonType
 		}
 	}
 	ptrMap.RUnlock()
@@ -971,7 +974,7 @@ func PtrTo(t Type) Type {
 	if p != nil {
 		// some other goroutine won the race and created it
 		ptrMap.Unlock()
-		return p
+		return &p.commonType
 	}
 
 	var rt struct {
@@ -1003,7 +1006,7 @@ func PtrTo(t Type) Type {
 
 	ptrMap.m[ct] = p
 	ptrMap.Unlock()
-	return p.commonType.toType()
+	return &p.commonType
 }
 
 func (t *commonType) Implements(u Type) bool {
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index 1cace3f..92c10ba 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -11,6 +11,7 @@ import (
 	"unsafe"
 )
 
+const bigEndian = false // can be smarter if we find a big-endian machine
 const ptrSize = unsafe.Sizeof((*byte)(nil))
 const cannotSet = "cannot set value obtained from unexported struct field"
 
@@ -53,14 +54,54 @@ func memmove(adst, asrc unsafe.Pointer, n uintptr) {
 // its String method returns "<invalid Value>", and all other methods panic.
 // Most functions and methods never return an invalid value.
 // If one does, its documentation states the conditions explicitly.
-//
-// The fields of Value are exported so that clients can copy and
-// pass Values around, but they should not be edited or inspected
-// directly.  A future language change may make it possible not to
-// export these fields while still keeping Values usable as values.
 type Value struct {
-	Internal       interface{}
-	InternalMethod int
+	// typ holds the type of the value represented by a Value.
+	typ *commonType
+
+	// val holds the 1-word representation of the value.
+	// If flag's flagIndir bit is set, then val is a pointer to the data.
+	// Otherwise val is a word holding the actual data.
+	// When the data is smaller than a word, it begins at
+	// the first byte (in the memory address sense) of val.
+	// We use unsafe.Pointer so that the garbage collector
+	// knows that val could be a pointer.
+	val unsafe.Pointer
+
+	// flag holds metadata about the value.
+	// The lowest bits are flag bits:
+	//	- flagRO: obtained via unexported field, so read-only
+	//	- flagIndir: val holds a pointer to the data
+	//	- flagAddr: v.CanAddr is true (implies flagIndir)
+	//	- flagMethod: v is a method value.
+	// The next five bits give the Kind of the value.
+	// This repeats typ.Kind() except for method values.
+	// The remaining 23+ bits give a method number for method values.
+	// If flag.kind() != Func, code can assume that flagMethod is unset.
+	// If typ.size > ptrSize, code can assume that flagIndir is set.
+	flag
+
+	// A method value represents a curried method invocation
+	// like r.Read for some receiver r.  The typ+val+flag bits describe
+	// the receiver r, but the flag's Kind bits say Func (methods are
+	// functions), and the top bits of the flag give the method number
+	// in r's type's method table.
+}
+
+type flag uintptr
+
+const (
+	flagRO flag = 1 << iota
+	flagIndir
+	flagAddr
+	flagMethod
+	flagKindShift        = iota
+	flagKindWidth        = 5 // there are 27 kinds
+	flagKindMask    flag = 1<<flagKindWidth - 1
+	flagMethodShift      = flagKindShift + flagKindWidth
+)
+
+func (f flag) kind() Kind {
+	return Kind((f >> flagKindShift) & flagKindMask)
 }
 
 // A ValueError occurs when a Value method is invoked on
@@ -71,7 +112,7 @@ type ValueError struct {
 	Kind   Kind
 }
 
-func (e *ValueError) String() string {
+func (e *ValueError) Error() string {
 	if e.Kind == 0 {
 		return "reflect: call of " + e.Method + " on zero Value"
 	}
@@ -92,17 +133,30 @@ func methodName() string {
 // An iword is the word that would be stored in an
 // interface to represent a given value v.  Specifically, if v is
 // bigger than a pointer, its word is a pointer to v's data.
-// Otherwise, its word is a zero uintptr with the data stored
-// in the leading bytes.
-type iword uintptr
+// Otherwise, its word holds the data stored
+// in its leading bytes (so is not a pointer).
+// Because the value sometimes holds a pointer, we use
+// unsafe.Pointer to represent it, so that if iword appears
+// in a struct, the garbage collector knows that might be
+// a pointer.
+type iword unsafe.Pointer
+
+func (v Value) iword() iword {
+	if v.flag&flagIndir != 0 && v.typ.size <= ptrSize {
+		// Have indirect but want direct word.
+		return loadIword(v.val, v.typ.size)
+	}
+	return iword(v.val)
+}
 
-func loadIword(p unsafe.Pointer, size uintptr) iword {
+// loadIword loads n bytes at p from memory into an iword.
+func loadIword(p unsafe.Pointer, n uintptr) iword {
 	// Run the copy ourselves instead of calling memmove
-	// to avoid moving v to the heap.
-	w := iword(0)
-	switch size {
+	// to avoid moving w to the heap.
+	var w iword
+	switch n {
 	default:
-		panic("reflect: internal error: loadIword of " + strconv.Itoa(int(size)) + "-byte value")
+		panic("reflect: internal error: loadIword of " + strconv.Itoa(int(n)) + "-byte value")
 	case 0:
 	case 1:
 		*(*uint8)(unsafe.Pointer(&w)) = *(*uint8)(p)
@@ -124,12 +178,13 @@ func loadIword(p unsafe.Pointer, size uintptr) iword {
 	return w
 }
 
-func storeIword(p unsafe.Pointer, w iword, size uintptr) {
+// storeIword stores n bytes from w into p.
+func storeIword(p unsafe.Pointer, w iword, n uintptr) {
 	// Run the copy ourselves instead of calling memmove
-	// to avoid moving v to the heap.
-	switch size {
+	// to avoid moving w to the heap.
+	switch n {
 	default:
-		panic("reflect: internal error: storeIword of " + strconv.Itoa(int(size)) + "-byte value")
+		panic("reflect: internal error: storeIword of " + strconv.Itoa(int(n)) + "-byte value")
 	case 0:
 	case 1:
 		*(*uint8)(p) = *(*uint8)(unsafe.Pointer(&w))
@@ -170,232 +225,42 @@ type nonEmptyInterface struct {
 	word iword
 }
 
-// Regarding the implementation of Value:
-//
-// The Internal interface is a true interface value in the Go sense,
-// but it also serves as a (type, address) pair in which one cannot
-// be changed separately from the other.  That is, it serves as a way
-// to prevent unsafe mutations of the Internal state even though
-// we cannot (yet?) hide the field while preserving the ability for
-// clients to make copies of Values.
-//
-// The internal method converts a Value into the expanded internalValue struct.
-// If we could avoid exporting fields we'd probably make internalValue the
-// definition of Value.
-//
-// If a Value is addressable (CanAddr returns true), then the Internal
-// interface value holds a pointer to the actual field data, and Set stores
-// through that pointer.  If a Value is not addressable (CanAddr returns false),
-// then the Internal interface value holds the actual value.
-//
-// In addition to whether a value is addressable, we track whether it was
-// obtained by using an unexported struct field.  Such values are allowed
-// to be read, mainly to make fmt.Print more useful, but they are not
-// allowed to be written.  We call such values read-only.
-//
-// A Value can be set (via the Set, SetUint, etc. methods) only if it is both
-// addressable and not read-only.
-//
-// The two permission bits - addressable and read-only - are stored in
-// the bottom two bits of the type pointer in the interface value.
-//
-//	ordinary value: Internal = value
-//	addressable value: Internal = value, Internal.typ |= flagAddr
-//	read-only value: Internal = value, Internal.typ |= flagRO
-//	addressable, read-only value: Internal = value, Internal.typ |= flagAddr | flagRO
-//
-// It is important that the read-only values have the extra bit set
-// (as opposed to using the bit to mean writable), because client code
-// can grab the interface field and try to use it.  Having the extra bit
-// set makes the type pointer compare not equal to any real type,
-// so that a client cannot, say, write through v.Internal.(*int).
-// The runtime routines that access interface types reject types with
-// low bits set.
-//
-// If a Value fv = v.Method(i), then fv = v with the InternalMethod
-// field set to i+1.  Methods are never addressable.
-//
-// All in all, this is a lot of effort just to avoid making this new API
-// depend on a language change we'll probably do anyway, but
-// it's helpful to keep the two separate, and much of the logic is
-// necessary to implement the Interface method anyway.
-
-const (
-	flagAddr uint32 = 1 << iota // holds address of value
-	flagRO                      // read-only
-
-	reflectFlags = 3
-)
-
-// An internalValue is the unpacked form of a Value.
-// The zero Value unpacks to a zero internalValue
-type internalValue struct {
-	typ       *commonType // type of value
-	kind      Kind        // kind of value
-	flag      uint32
-	word      iword
-	addr      unsafe.Pointer
-	rcvr      iword
-	method    bool
-	nilmethod bool
-}
-
-func (v Value) internal() internalValue {
-	var iv internalValue
-	eface := *(*emptyInterface)(unsafe.Pointer(&v.Internal))
-	p := uintptr(unsafe.Pointer(eface.typ))
-	iv.typ = toCommonType((*runtime.Type)(unsafe.Pointer(p &^ reflectFlags)))
-	if iv.typ == nil {
-		return iv
-	}
-	iv.flag = uint32(p & reflectFlags)
-	iv.word = eface.word
-	if iv.flag&flagAddr != 0 {
-		iv.addr = unsafe.Pointer(iv.word)
-		iv.typ = iv.typ.Elem().common()
-		if iv.typ.size <= ptrSize {
-			iv.word = loadIword(iv.addr, iv.typ.size)
-		}
-	} else {
-		if iv.typ.size > ptrSize {
-			iv.addr = unsafe.Pointer(iv.word)
-		}
-	}
-	iv.kind = iv.typ.Kind()
-
-	// Is this a method?  If so, iv describes the receiver.
-	// Rewrite to describe the method function.
-	if v.InternalMethod != 0 {
-		// If this Value is a method value (x.Method(i) for some Value x)
-		// then we will invoke it using the interface form of the method,
-		// which always passes the receiver as a single word.
-		// Record that information.
-		i := v.InternalMethod - 1
-		if iv.kind == Interface {
-			it := (*interfaceType)(unsafe.Pointer(iv.typ))
-			if i < 0 || i >= len(it.methods) {
-				panic("reflect: broken Value")
-			}
-			m := &it.methods[i]
-			if m.pkgPath != nil {
-				iv.flag |= flagRO
-			}
-			iv.typ = toCommonType(m.typ)
-			iface := (*nonEmptyInterface)(iv.addr)
-			if iface.itab == nil {
-				iv.word = 0
-				iv.nilmethod = true
-			} else {
-				iv.word = iword(iface.itab.fun[i])
-			}
-			iv.rcvr = iface.word
-		} else {
-			ut := iv.typ.uncommon()
-			if ut == nil || i < 0 || i >= len(ut.methods) {
-				panic("reflect: broken Value")
-			}
-			m := &ut.methods[i]
-			if m.pkgPath != nil {
-				iv.flag |= flagRO
-			}
-			iv.typ = toCommonType(m.mtyp)
-			iv.rcvr = iv.word
-			iv.word = iword(m.ifn)
-		}
-		iv.kind = Func
-		iv.method = true
-		iv.flag &^= flagAddr
-		iv.addr = nil
+// mustBe panics if f's kind is not expected.
+// Making this a method on flag instead of on Value
+// (and embedding flag in Value) means that we can write
+// the very clear v.mustBe(Bool) and have it compile into
+// v.flag.mustBe(Bool), which will only bother to copy the
+// single important word for the receiver.
+func (f flag) mustBe(expected Kind) {
+	k := f.kind()
+	if k != expected {
+		panic(&ValueError{methodName(), k})
 	}
-
-	return iv
 }
 
-// packValue returns a Value with the given flag bits, type, and interface word.
-func packValue(flag uint32, typ *runtime.Type, word iword) Value {
-	if typ == nil {
-		panic("packValue")
+// mustBeExported panics if f records that the value was obtained using
+// an unexported field.
+func (f flag) mustBeExported() {
+	if f == 0 {
+		panic(&ValueError{methodName(), 0})
 	}
-	t := uintptr(unsafe.Pointer(typ))
-	t |= uintptr(flag)
-	eface := emptyInterface{(*runtime.Type)(unsafe.Pointer(t)), word}
-	return Value{Internal: *(*interface{})(unsafe.Pointer(&eface))}
-}
-
-var dummy struct {
-	b bool
-	x interface{}
-}
-
-// Dummy annotation marking that the value x escapes,
-// for use in cases where the reflect code is so clever that
-// the compiler cannot follow.
-func escapes(x interface{}) {
-	if dummy.b {
-		dummy.x = x
-	}
-}
-
-// valueFromAddr returns a Value using the given type and address.
-func valueFromAddr(flag uint32, typ Type, addr unsafe.Pointer) Value {
-	// TODO(rsc): Eliminate this terrible hack.
-	// The escape analysis knows that addr is a pointer
-	// but it doesn't see addr get passed to anything
-	// that keeps it.  packValue keeps it, but packValue
-	// takes a uintptr (iword(addr)), and integers (non-pointers)
-	// are assumed not to matter.  The escapes function works
-	// because return values always escape (for now).
-	escapes(addr)
-
-	if flag&flagAddr != 0 {
-		// Addressable, so the internal value is
-		// an interface containing a pointer to the real value.
-		return packValue(flag, PtrTo(typ).runtimeType(), iword(addr))
-	}
-
-	var w iword
-	if n := typ.Size(); n <= ptrSize {
-		// In line, so the interface word is the actual value.
-		w = loadIword(addr, n)
-	} else {
-		// Not in line: the interface word is the address.
-		w = iword(addr)
-	}
-	return packValue(flag, typ.runtimeType(), w)
-}
-
-// valueFromIword returns a Value using the given type and interface word.
-func valueFromIword(flag uint32, typ Type, w iword) Value {
-	if flag&flagAddr != 0 {
-		panic("reflect: internal error: valueFromIword addressable")
-	}
-	return packValue(flag, typ.runtimeType(), w)
-}
-
-func (iv internalValue) mustBe(want Kind) {
-	if iv.kind != want {
-		panic(&ValueError{methodName(), iv.kind})
-	}
-}
-
-func (iv internalValue) mustBeExported() {
-	if iv.kind == 0 {
-		panic(&ValueError{methodName(), iv.kind})
-	}
-	if iv.flag&flagRO != 0 {
+	if f&flagRO != 0 {
 		panic(methodName() + " using value obtained using unexported field")
 	}
 }
 
-func (iv internalValue) mustBeAssignable() {
-	if iv.kind == 0 {
-		panic(&ValueError{methodName(), iv.kind})
+// mustBeAssignable panics if f records that the value is not assignable,
+// which is to say that either it was obtained using an unexported field
+// or it is not addressable.
+func (f flag) mustBeAssignable() {
+	if f == 0 {
+		panic(&ValueError{methodName(), Invalid})
 	}
 	// Assignable if addressable and not read-only.
-	if iv.flag&flagRO != 0 {
+	if f&flagRO != 0 {
 		panic(methodName() + " using value obtained using unexported field")
 	}
-	if iv.flag&flagAddr == 0 {
+	if f&flagAddr == 0 {
 		panic(methodName() + " using unaddressable value")
 	}
 }
@@ -406,31 +271,31 @@ func (iv internalValue) mustBeAssignable() {
 // or slice element in order to call a method that requires a
 // pointer receiver.
 func (v Value) Addr() Value {
-	iv := v.internal()
-	if iv.flag&flagAddr == 0 {
+	if v.flag&flagAddr == 0 {
 		panic("reflect.Value.Addr of unaddressable value")
 	}
-	return valueFromIword(iv.flag&flagRO, PtrTo(iv.typ.toType()), iword(iv.addr))
+	return Value{v.typ.ptrTo(), v.val, (v.flag & flagRO) | flag(Ptr)<<flagKindShift}
 }
 
 // Bool returns v's underlying value.
 // It panics if v's kind is not Bool.
 func (v Value) Bool() bool {
-	iv := v.internal()
-	iv.mustBe(Bool)
-	return *(*bool)(unsafe.Pointer(&iv.word))
+	v.mustBe(Bool)
+	if v.flag&flagIndir != 0 {
+		return *(*bool)(v.val)
+	}
+	return *(*bool)(unsafe.Pointer(&v.val))
 }
 
 // Bytes returns v's underlying value.
 // It panics if v's underlying value is not a slice of bytes.
 func (v Value) Bytes() []byte {
-	iv := v.internal()
-	iv.mustBe(Slice)
-	typ := iv.typ.toType()
-	if typ.Elem().Kind() != Uint8 {
+	v.mustBe(Slice)
+	if v.typ.Elem().Kind() != Uint8 {
 		panic("reflect.Value.Bytes of non-byte slice")
 	}
-	return *(*[]byte)(iv.addr)
+	// Slice is always bigger than a word; assume flagIndir.
+	return *(*[]byte)(v.val)
 }
 
 // CanAddr returns true if the value's address can be obtained with Addr.
@@ -439,8 +304,7 @@ func (v Value) Bytes() []byte {
 // a field of an addressable struct, or the result of dereferencing a pointer.
 // If CanAddr returns false, calling Addr will panic.
 func (v Value) CanAddr() bool {
-	iv := v.internal()
-	return iv.flag&flagAddr != 0
+	return v.flag&flagAddr != 0
 }
 
 // CanSet returns true if the value of v can be changed.
@@ -449,8 +313,7 @@ func (v Value) CanAddr() bool {
 // If CanSet returns false, calling Set or any type-specific
 // setter (e.g., SetBool, SetInt64) will panic.
 func (v Value) CanSet() bool {
-	iv := v.internal()
-	return iv.flag&(flagAddr|flagRO) == flagAddr
+	return v.flag&(flagAddr|flagRO) == flagAddr
 }
 
 // Call calls the function v with the input arguments in.
@@ -462,10 +325,9 @@ func (v Value) CanSet() bool {
 // If v is a variadic function, Call creates the variadic slice parameter
 // itself, copying in the corresponding values.
 func (v Value) Call(in []Value) []Value {
-	iv := v.internal()
-	iv.mustBe(Func)
-	iv.mustBeExported()
-	return iv.call("Call", in)
+	v.mustBe(Func)
+	v.mustBeExported()
+	return v.call("Call", in)
 }
 
 // CallSlice calls the variadic function v with the input arguments in,
@@ -476,22 +338,60 @@ func (v Value) Call(in []Value) []Value {
 // As in Go, each input argument must be assignable to the
 // type of the function's corresponding input parameter.
 func (v Value) CallSlice(in []Value) []Value {
-	iv := v.internal()
-	iv.mustBe(Func)
-	iv.mustBeExported()
-	return iv.call("CallSlice", in)
-}
-
-func (iv internalValue) call(method string, in []Value) []Value {
-	if iv.word == 0 {
-		if iv.nilmethod {
-			panic("reflect.Value.Call: call of method on nil interface value")
+	v.mustBe(Func)
+	v.mustBeExported()
+	return v.call("CallSlice", in)
+}
+
+func (v Value) call(method string, in []Value) []Value {
+	// Get function pointer, type.
+	t := v.typ
+	var (
+		fn   unsafe.Pointer
+		rcvr iword
+	)
+	if v.flag&flagMethod != 0 {
+		i := int(v.flag) >> flagMethodShift
+		if v.typ.Kind() == Interface {
+			tt := (*interfaceType)(unsafe.Pointer(v.typ))
+			if i < 0 || i >= len(tt.methods) {
+				panic("reflect: broken Value")
+			}
+			m := &tt.methods[i]
+			if m.pkgPath != nil {
+				panic(method + " of unexported method")
+			}
+			t = toCommonType(m.typ)
+			iface := (*nonEmptyInterface)(v.val)
+			if iface.itab == nil {
+				panic(method + " of method on nil interface value")
+			}
+			fn = iface.itab.fun[i]
+			rcvr = iface.word
+		} else {
+			ut := v.typ.uncommon()
+			if ut == nil || i < 0 || i >= len(ut.methods) {
+				panic("reflect: broken Value")
+			}
+			m := &ut.methods[i]
+			if m.pkgPath != nil {
+				panic(method + " of unexported method")
+			}
+			fn = m.ifn
+			t = toCommonType(m.mtyp)
+			rcvr = v.iword()
 		}
+	} else if v.flag&flagIndir != 0 {
+		fn = *(*unsafe.Pointer)(v.val)
+	} else {
+		fn = v.val
+	}
+
+	if fn == nil {
 		panic("reflect.Value.Call: call of nil function")
 	}
 
 	isSlice := method == "CallSlice"
-	t := iv.typ
 	n := t.NumIn()
 	if isSlice {
 		if !t.IsVariadic() {
@@ -553,8 +453,8 @@ func (iv internalValue) call(method string, in []Value) []Value {
 	// and probably wrong for gccgo, but so
 	// is most of this function.
 	size := uintptr(0)
-	if iv.method {
-		// extra word for interface value
+	if v.flag&flagMethod != 0 {
+		// extra word for receiver interface word
 		size += ptrSize
 	}
 	for i := 0; i < nin; i++ {
@@ -591,31 +491,30 @@ func (iv internalValue) call(method string, in []Value) []Value {
 	args := make([]*int, size/ptrSize)
 	ptr := uintptr(unsafe.Pointer(&args[0]))
 	off := uintptr(0)
-	if iv.method {
+	if v.flag&flagMethod != 0 {
 		// Hard-wired first argument.
-		*(*iword)(unsafe.Pointer(ptr)) = iv.rcvr
+		*(*iword)(unsafe.Pointer(ptr)) = rcvr
 		off = ptrSize
 	}
 	for i, v := range in {
-		iv := v.internal()
-		iv.mustBeExported()
+		v.mustBeExported()
 		targ := t.In(i).(*commonType)
 		a := uintptr(targ.align)
 		off = (off + a - 1) &^ (a - 1)
 		n := targ.size
 		addr := unsafe.Pointer(ptr + off)
-		iv = convertForAssignment("reflect.Value.Call", addr, targ, iv)
-		if iv.addr == nil {
-			storeIword(addr, iv.word, n)
+		v = v.assignTo("reflect.Value.Call", targ, (*interface{})(addr))
+		if v.flag&flagIndir == 0 {
+			storeIword(addr, iword(v.val), n)
 		} else {
-			memmove(addr, iv.addr, n)
+			memmove(addr, v.val, n)
 		}
 		off += n
 	}
 	off = (off + ptrSize - 1) &^ (ptrSize - 1)
 
 	// Call.
-	call(unsafe.Pointer(iv.word), unsafe.Pointer(ptr), uint32(size))
+	call(fn, unsafe.Pointer(ptr), uint32(size))
 
 	// Copy return values out of args.
 	//
@@ -625,7 +524,8 @@ func (iv internalValue) call(method string, in []Value) []Value {
 		tv := t.Out(i)
 		a := uintptr(tv.Align())
 		off = (off + a - 1) &^ (a - 1)
-		ret[i] = valueFromAddr(0, tv, unsafe.Pointer(ptr+off))
+		fl := flagIndir | flag(tv.Kind())<<flagKindShift
+		ret[i] = Value{tv.common(), unsafe.Pointer(ptr + off), fl}
 		off += tv.Size()
 	}
 
@@ -635,42 +535,42 @@ func (iv internalValue) call(method string, in []Value) []Value {
 // Cap returns v's capacity.
 // It panics if v's Kind is not Array, Chan, or Slice.
 func (v Value) Cap() int {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Array:
-		return iv.typ.Len()
+		return v.typ.Len()
 	case Chan:
-		return int(chancap(iv.word))
+		return int(chancap(v.iword()))
 	case Slice:
-		return (*SliceHeader)(iv.addr).Cap
+		// Slice is always bigger than a word; assume flagIndir.
+		return (*SliceHeader)(v.val).Cap
 	}
-	panic(&ValueError{"reflect.Value.Cap", iv.kind})
+	panic(&ValueError{"reflect.Value.Cap", k})
 }
 
 // Close closes the channel v.
 // It panics if v's Kind is not Chan.
 func (v Value) Close() {
-	iv := v.internal()
-	iv.mustBe(Chan)
-	iv.mustBeExported()
-	ch := iv.word
-	chanclose(ch)
+	v.mustBe(Chan)
+	v.mustBeExported()
+	chanclose(v.iword())
 }
 
 // Complex returns v's underlying value, as a complex128.
 // It panics if v's Kind is not Complex64 or Complex128
 func (v Value) Complex() complex128 {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Complex64:
-		if iv.addr == nil {
-			return complex128(*(*complex64)(unsafe.Pointer(&iv.word)))
+		if v.flag&flagIndir != 0 {
+			return complex128(*(*complex64)(v.val))
 		}
-		return complex128(*(*complex64)(iv.addr))
+		return complex128(*(*complex64)(unsafe.Pointer(&v.val)))
 	case Complex128:
-		return *(*complex128)(iv.addr)
+		// complex128 is always bigger than a word; assume flagIndir.
+		return *(*complex128)(v.val)
 	}
-	panic(&ValueError{"reflect.Value.Complex", iv.kind})
+	panic(&ValueError{"reflect.Value.Complex", k})
 }
 
 // Elem returns the value that the interface v contains
@@ -678,90 +578,94 @@ func (v Value) Complex() complex128 {
 // It panics if v's Kind is not Interface or Ptr.
 // It returns the zero Value if v is nil.
 func (v Value) Elem() Value {
-	iv := v.internal()
-	return iv.Elem()
-}
-
-func (iv internalValue) Elem() Value {
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Interface:
-		// Empty interface and non-empty interface have different layouts.
-		// Convert to empty interface.
-		var eface emptyInterface
-		if iv.typ.NumMethod() == 0 {
-			eface = *(*emptyInterface)(iv.addr)
+		var (
+			typ *commonType
+			val unsafe.Pointer
+		)
+		if v.typ.NumMethod() == 0 {
+			eface := (*emptyInterface)(v.val)
+			if eface.typ == nil {
+				// nil interface value
+				return Value{}
+			}
+			typ = toCommonType(eface.typ)
+			val = unsafe.Pointer(eface.word)
 		} else {
-			iface := (*nonEmptyInterface)(iv.addr)
-			if iface.itab != nil {
-				eface.typ = iface.itab.typ
+			iface := (*nonEmptyInterface)(v.val)
+			if iface.itab == nil {
+				// nil interface value
+				return Value{}
 			}
-			eface.word = iface.word
+			typ = toCommonType(iface.itab.typ)
+			val = unsafe.Pointer(iface.word)
 		}
-		if eface.typ == nil {
-			return Value{}
+		fl := v.flag & flagRO
+		fl |= flag(typ.Kind()) << flagKindShift
+		if typ.size > ptrSize {
+			fl |= flagIndir
 		}
-		return valueFromIword(iv.flag&flagRO, toType(eface.typ), eface.word)
+		return Value{typ, val, fl}
 
 	case Ptr:
+		val := v.val
+		if v.flag&flagIndir != 0 {
+			val = *(*unsafe.Pointer)(val)
+		}
 		// The returned value's address is v's value.
-		if iv.word == 0 {
+		if val == nil {
 			return Value{}
 		}
-		return valueFromAddr(iv.flag&flagRO|flagAddr, iv.typ.Elem(), unsafe.Pointer(iv.word))
+		tt := (*ptrType)(unsafe.Pointer(v.typ))
+		typ := toCommonType(tt.elem)
+		fl := v.flag&flagRO | flagIndir | flagAddr
+		fl |= flag(typ.Kind() << flagKindShift)
+		return Value{typ, val, fl}
 	}
-	panic(&ValueError{"reflect.Value.Elem", iv.kind})
+	panic(&ValueError{"reflect.Value.Elem", k})
 }
 
 // Field returns the i'th field of the struct v.
 // It panics if v's Kind is not Struct or i is out of range.
 func (v Value) Field(i int) Value {
-	iv := v.internal()
-	iv.mustBe(Struct)
-	t := iv.typ.toType()
-	if i < 0 || i >= t.NumField() {
+	v.mustBe(Struct)
+	tt := (*structType)(unsafe.Pointer(v.typ))
+	if i < 0 || i >= len(tt.fields) {
 		panic("reflect: Field index out of range")
 	}
-	f := t.Field(i)
+	field := &tt.fields[i]
+	typ := toCommonType(field.typ)
 
 	// Inherit permission bits from v.
-	flag := iv.flag
+	fl := v.flag & (flagRO | flagIndir | flagAddr)
 	// Using an unexported field forces flagRO.
-	if f.PkgPath != "" {
-		flag |= flagRO
+	if field.pkgPath != nil {
+		fl |= flagRO
 	}
-	return valueFromValueOffset(flag, f.Type, iv, f.Offset)
-}
+	fl |= flag(typ.Kind()) << flagKindShift
 
-// valueFromValueOffset returns a sub-value of outer
-// (outer is an array or a struct) with the given flag and type
-// starting at the given byte offset into outer.
-func valueFromValueOffset(flag uint32, typ Type, outer internalValue, offset uintptr) Value {
-	if outer.addr != nil {
-		return valueFromAddr(flag, typ, unsafe.Pointer(uintptr(outer.addr)+offset))
+	var val unsafe.Pointer
+	switch {
+	case fl&flagIndir != 0:
+		// Indirect.  Just bump pointer.
+		val = unsafe.Pointer(uintptr(v.val) + field.offset)
+	case bigEndian:
+		// Direct.  Discard leading bytes.
+		val = unsafe.Pointer(uintptr(v.val) << (field.offset * 8))
+	default:
+		// Direct.  Discard leading bytes.
+		val = unsafe.Pointer(uintptr(v.val) >> (field.offset * 8))
 	}
 
-	// outer is so tiny it is in line.
-	// We have to use outer.word and derive
-	// the new word (it cannot possibly be bigger).
-	// In line, so not addressable.
-	if flag&flagAddr != 0 {
-		panic("reflect: internal error: misuse of valueFromValueOffset")
-	}
-	b := *(*[ptrSize]byte)(unsafe.Pointer(&outer.word))
-	for i := uintptr(0); i < typ.Size(); i++ {
-		b[i] = b[offset+i]
-	}
-	for i := typ.Size(); i < ptrSize; i++ {
-		b[i] = 0
-	}
-	w := *(*iword)(unsafe.Pointer(&b))
-	return valueFromIword(flag, typ, w)
+	return Value{typ, val, fl}
 }
 
 // FieldByIndex returns the nested field corresponding to index.
 // It panics if v's Kind is not struct.
 func (v Value) FieldByIndex(index []int) Value {
-	v.internal().mustBe(Struct)
+	v.mustBe(Struct)
 	for i, x := range index {
 		if i > 0 {
 			if v.Kind() == Ptr && v.Elem().Kind() == Struct {
@@ -777,9 +681,8 @@ func (v Value) FieldByIndex(index []int) Value {
 // It returns the zero Value if no field was found.
 // It panics if v's Kind is not struct.
 func (v Value) FieldByName(name string) Value {
-	iv := v.internal()
-	iv.mustBe(Struct)
-	if f, ok := iv.typ.FieldByName(name); ok {
+	v.mustBe(Struct)
+	if f, ok := v.typ.FieldByName(name); ok {
 		return v.FieldByIndex(f.Index)
 	}
 	return Value{}
@@ -790,8 +693,8 @@ func (v Value) FieldByName(name string) Value {
 // It panics if v's Kind is not struct.
 // It returns the zero Value if no field was found.
 func (v Value) FieldByNameFunc(match func(string) bool) Value {
-	v.internal().mustBe(Struct)
-	if f, ok := v.Type().FieldByNameFunc(match); ok {
+	v.mustBe(Struct)
+	if f, ok := v.typ.FieldByNameFunc(match); ok {
 		return v.FieldByIndex(f.Index)
 	}
 	return Value{}
@@ -800,90 +703,101 @@ func (v Value) FieldByNameFunc(match func(string) bool) Value {
 // Float returns v's underlying value, as an float64.
 // It panics if v's Kind is not Float32 or Float64
 func (v Value) Float() float64 {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Float32:
-		return float64(*(*float32)(unsafe.Pointer(&iv.word)))
+		if v.flag&flagIndir != 0 {
+			return float64(*(*float32)(v.val))
+		}
+		return float64(*(*float32)(unsafe.Pointer(&v.val)))
 	case Float64:
-		// If the pointer width can fit an entire float64,
-		// the value is in line when stored in an interface.
-		if iv.addr == nil {
-			return *(*float64)(unsafe.Pointer(&iv.word))
+		if v.flag&flagIndir != 0 {
+			return *(*float64)(v.val)
 		}
-		// Otherwise we have a pointer.
-		return *(*float64)(iv.addr)
+		return *(*float64)(unsafe.Pointer(&v.val))
 	}
-	panic(&ValueError{"reflect.Value.Float", iv.kind})
+	panic(&ValueError{"reflect.Value.Float", k})
 }
 
 // Index returns v's i'th element.
 // It panics if v's Kind is not Array or Slice or i is out of range.
 func (v Value) Index(i int) Value {
-	iv := v.internal()
-	switch iv.kind {
-	default:
-		panic(&ValueError{"reflect.Value.Index", iv.kind})
+	k := v.kind()
+	switch k {
 	case Array:
-		flag := iv.flag // element flag same as overall array
-		t := iv.typ.toType()
-		if i < 0 || i > t.Len() {
+		tt := (*arrayType)(unsafe.Pointer(v.typ))
+		if i < 0 || i > int(tt.len) {
 			panic("reflect: array index out of range")
 		}
-		typ := t.Elem()
-		return valueFromValueOffset(flag, typ, iv, uintptr(i)*typ.Size())
+		typ := toCommonType(tt.elem)
+		fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as overall array
+		fl |= flag(typ.Kind()) << flagKindShift
+		offset := uintptr(i) * typ.size
+
+		var val unsafe.Pointer
+		switch {
+		case fl&flagIndir != 0:
+			// Indirect.  Just bump pointer.
+			val = unsafe.Pointer(uintptr(v.val) + offset)
+		case bigEndian:
+			// Direct.  Discard leading bytes.
+			val = unsafe.Pointer(uintptr(v.val) << (offset * 8))
+		default:
+			// Direct.  Discard leading bytes.
+			val = unsafe.Pointer(uintptr(v.val) >> (offset * 8))
+		}
+		return Value{typ, val, fl}
 
 	case Slice:
 		// Element flag same as Elem of Ptr.
-		// Addressable, possibly read-only.
-		flag := iv.flag&flagRO | flagAddr
-		s := (*SliceHeader)(iv.addr)
+		// Addressable, indirect, possibly read-only.
+		fl := flagAddr | flagIndir | v.flag&flagRO
+		s := (*SliceHeader)(v.val)
 		if i < 0 || i >= s.Len {
 			panic("reflect: slice index out of range")
 		}
-		typ := iv.typ.Elem()
-		addr := unsafe.Pointer(s.Data + uintptr(i)*typ.Size())
-		return valueFromAddr(flag, typ, addr)
+		tt := (*sliceType)(unsafe.Pointer(v.typ))
+		typ := toCommonType(tt.elem)
+		fl |= flag(typ.Kind()) << flagKindShift
+		val := unsafe.Pointer(s.Data + uintptr(i)*typ.size)
+		return Value{typ, val, fl}
 	}
-
-	panic("not reached")
+	panic(&ValueError{"reflect.Value.Index", k})
 }
 
 // Int returns v's underlying value, as an int64.
 // It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
 func (v Value) Int() int64 {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	var p unsafe.Pointer
+	if v.flag&flagIndir != 0 {
+		p = v.val
+	} else {
+		// The escape analysis is good enough that &v.val
+		// does not trigger a heap allocation.
+		p = unsafe.Pointer(&v.val)
+	}
+	switch k {
 	case Int:
-		return int64(*(*int)(unsafe.Pointer(&iv.word)))
+		return int64(*(*int)(p))
 	case Int8:
-		return int64(*(*int8)(unsafe.Pointer(&iv.word)))
+		return int64(*(*int8)(p))
 	case Int16:
-		return int64(*(*int16)(unsafe.Pointer(&iv.word)))
+		return int64(*(*int16)(p))
 	case Int32:
-		return int64(*(*int32)(unsafe.Pointer(&iv.word)))
+		return int64(*(*int32)(p))
 	case Int64:
-		if iv.addr == nil {
-			return *(*int64)(unsafe.Pointer(&iv.word))
-		}
-		return *(*int64)(iv.addr)
+		return int64(*(*int64)(p))
 	}
-	panic(&ValueError{"reflect.Value.Int", iv.kind})
+	panic(&ValueError{"reflect.Value.Int", k})
 }
 
 // CanInterface returns true if Interface can be used without panicking.
 func (v Value) CanInterface() bool {
-	iv := v.internal()
-	if iv.kind == Invalid {
-		panic(&ValueError{"reflect.Value.CanInterface", iv.kind})
+	if v.flag == 0 {
+		panic(&ValueError{"reflect.Value.CanInterface", Invalid})
 	}
-	// TODO(rsc): Check flagRO too.  Decide what to do about asking for
-	// interface for a value obtained via an unexported field.
-	// If the field were of a known type, say chan int or *sync.Mutex,
-	// the caller could interfere with the data after getting the
-	// interface.  But fmt.Print depends on being able to look.
-	// Now that reflect is more efficient the special cases in fmt
-	// might be less important.
-	return v.InternalMethod == 0
+	return v.flag&(flagMethod|flagRO) == 0
 }
 
 // Interface returns v's value as an interface{}.
@@ -891,68 +805,76 @@ func (v Value) CanInterface() bool {
 // (as opposed to Type.Method), Interface cannot return an
 // interface value, so it panics.
 func (v Value) Interface() interface{} {
-	return v.internal().Interface()
+	return valueInterface(v, true)
 }
 
-func (iv internalValue) Interface() interface{} {
-	if iv.kind == 0 {
-		panic(&ValueError{"reflect.Value.Interface", iv.kind})
+func valueInterface(v Value, safe bool) interface{} {
+	if v.flag == 0 {
+		panic(&ValueError{"reflect.Value.Interface", 0})
 	}
-	if iv.method {
+	if v.flag&flagMethod != 0 {
 		panic("reflect.Value.Interface: cannot create interface value for method with bound receiver")
 	}
-	/*
-		if v.flag()&noExport != 0 {
-			panic("reflect.Value.Interface: cannot return value obtained from unexported struct field")
-		}
-	*/
 
-	if iv.kind == Interface {
+	if safe && v.flag&flagRO != 0 {
+		// Do not allow access to unexported values via Interface,
+		// because they might be pointers that should not be 
+		// writable or methods or function that should not be callable.
+		panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
+	}
+
+	k := v.kind()
+	if k == Interface {
 		// Special case: return the element inside the interface.
-		// Won't recurse further because an interface cannot contain an interface.
-		if iv.IsNil() {
-			return nil
+		// Empty interface has one layout, all interfaces with
+		// methods have a second layout.
+		if v.NumMethod() == 0 {
+			return *(*interface{})(v.val)
 		}
-		return iv.Elem().Interface()
+		return *(*interface {
+			M()
+		})(v.val)
 	}
 
 	// Non-interface value.
 	var eface emptyInterface
-	eface.typ = iv.typ.runtimeType()
-	eface.word = iv.word
+	eface.typ = v.typ.runtimeType()
+	eface.word = v.iword()
 	return *(*interface{})(unsafe.Pointer(&eface))
 }
 
 // InterfaceData returns the interface v's value as a uintptr pair.
 // It panics if v's Kind is not Interface.
 func (v Value) InterfaceData() [2]uintptr {
-	iv := v.internal()
-	iv.mustBe(Interface)
+	v.mustBe(Interface)
 	// We treat this as a read operation, so we allow
 	// it even for unexported data, because the caller
 	// has to import "unsafe" to turn it into something
 	// that can be abused.
-	return *(*[2]uintptr)(iv.addr)
+	// Interface value is always bigger than a word; assume flagIndir.
+	return *(*[2]uintptr)(v.val)
 }
 
 // IsNil returns true if v is a nil value.
 // It panics if v's Kind is not Chan, Func, Interface, Map, Ptr, or Slice.
 func (v Value) IsNil() bool {
-	return v.internal().IsNil()
-}
-
-func (iv internalValue) IsNil() bool {
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Chan, Func, Map, Ptr:
-		if iv.method {
+		if v.flag&flagMethod != 0 {
 			panic("reflect: IsNil of method Value")
 		}
-		return iv.word == 0
+		ptr := v.val
+		if v.flag&flagIndir != 0 {
+			ptr = *(*unsafe.Pointer)(ptr)
+		}
+		return ptr == nil
 	case Interface, Slice:
 		// Both interface and slice are nil if first word is 0.
-		return *(*uintptr)(iv.addr) == 0
+		// Both are always bigger than a word; assume flagIndir.
+		return *(*unsafe.Pointer)(v.val) == nil
 	}
-	panic(&ValueError{"reflect.Value.IsNil", iv.kind})
+	panic(&ValueError{"reflect.Value.IsNil", k})
 }
 
 // IsValid returns true if v represents a value.
@@ -961,32 +883,35 @@ func (iv internalValue) IsNil() bool {
 // Most functions and methods never return an invalid value.
 // If one does, its documentation states the conditions explicitly.
 func (v Value) IsValid() bool {
-	return v.Internal != nil
+	return v.flag != 0
 }
 
 // Kind returns v's Kind.
 // If v is the zero Value (IsValid returns false), Kind returns Invalid.
 func (v Value) Kind() Kind {
-	return v.internal().kind
+	return v.kind()
 }
 
 // Len returns v's length.
 // It panics if v's Kind is not Array, Chan, Map, Slice, or String.
 func (v Value) Len() int {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Array:
-		return iv.typ.Len()
+		tt := (*arrayType)(unsafe.Pointer(v.typ))
+		return int(tt.len)
 	case Chan:
-		return int(chanlen(iv.word))
+		return int(chanlen(v.iword()))
 	case Map:
-		return int(maplen(iv.word))
+		return int(maplen(v.iword()))
 	case Slice:
-		return (*SliceHeader)(iv.addr).Len
+		// Slice is bigger than a word; assume flagIndir.
+		return (*SliceHeader)(v.val).Len
 	case String:
-		return (*StringHeader)(iv.addr).Len
+		// String is bigger than a word; assume flagIndir.
+		return (*StringHeader)(v.val).Len
 	}
-	panic(&ValueError{"reflect.Value.Len", iv.kind})
+	panic(&ValueError{"reflect.Value.Len", k})
 }
 
 // MapIndex returns the value associated with key in the map v.
@@ -994,29 +919,29 @@ func (v Value) Len() int {
 // It returns the zero Value if key is not found in the map or if v represents a nil map.
 // As in Go, the key's value must be assignable to the map's key type.
 func (v Value) MapIndex(key Value) Value {
-	iv := v.internal()
-	iv.mustBe(Map)
-	typ := iv.typ.toType()
+	v.mustBe(Map)
+	tt := (*mapType)(unsafe.Pointer(v.typ))
 
-	// Do not require ikey to be exported, so that DeepEqual
+	// Do not require key to be exported, so that DeepEqual
 	// and other programs can use all the keys returned by
 	// MapKeys as arguments to MapIndex.  If either the map
 	// or the key is unexported, though, the result will be
-	// considered unexported.
-
-	ikey := key.internal()
-	ikey = convertForAssignment("reflect.Value.MapIndex", nil, typ.Key(), ikey)
-	if iv.word == 0 {
-		return Value{}
-	}
+	// considered unexported.  This is consistent with the
+	// behavior for structs, which allow read but not write
+	// of unexported fields.
+	key = key.assignTo("reflect.Value.MapIndex", toCommonType(tt.key), nil)
 
-	flag := (iv.flag | ikey.flag) & flagRO
-	elemType := typ.Elem()
-	elemWord, ok := mapaccess(typ.runtimeType(), iv.word, ikey.word)
+	word, ok := mapaccess(v.typ.runtimeType(), v.iword(), key.iword())
 	if !ok {
 		return Value{}
 	}
-	return valueFromIword(flag, elemType, elemWord)
+	typ := toCommonType(tt.elem)
+	fl := (v.flag | key.flag) & flagRO
+	if typ.size > ptrSize {
+		fl |= flagIndir
+	}
+	fl |= flag(typ.Kind()) << flagKindShift
+	return Value{typ, unsafe.Pointer(word), fl}
 }
 
 // MapKeys returns a slice containing all the keys present in the map,
@@ -1024,17 +949,22 @@ func (v Value) MapIndex(key Value) Value {
 // It panics if v's Kind is not Map.
 // It returns an empty slice if v represents a nil map.
 func (v Value) MapKeys() []Value {
-	iv := v.internal()
-	iv.mustBe(Map)
-	keyType := iv.typ.Key()
+	v.mustBe(Map)
+	tt := (*mapType)(unsafe.Pointer(v.typ))
+	keyType := toCommonType(tt.key)
 
-	flag := iv.flag & flagRO
-	m := iv.word
+	fl := v.flag & flagRO
+	fl |= flag(keyType.Kind()) << flagKindShift
+	if keyType.size > ptrSize {
+		fl |= flagIndir
+	}
+
+	m := v.iword()
 	mlen := int32(0)
-	if m != 0 {
+	if m != nil {
 		mlen = maplen(m)
 	}
-	it := mapiterinit(iv.typ.runtimeType(), m)
+	it := mapiterinit(v.typ.runtimeType(), m)
 	a := make([]Value, mlen)
 	var i int
 	for i = 0; i < len(a); i++ {
@@ -1042,7 +972,7 @@ func (v Value) MapKeys() []Value {
 		if !ok {
 			break
 		}
-		a[i] = valueFromIword(flag, keyType, keyWord)
+		a[i] = Value{keyType, unsafe.Pointer(keyWord), fl}
 		mapiternext(it)
 	}
 	return a[:i]
@@ -1053,23 +983,27 @@ func (v Value) MapKeys() []Value {
 // a receiver; the returned function will always use v as the receiver.
 // Method panics if i is out of range.
 func (v Value) Method(i int) Value {
-	iv := v.internal()
-	if iv.kind == Invalid {
+	if v.typ == nil {
 		panic(&ValueError{"reflect.Value.Method", Invalid})
 	}
-	if i < 0 || i >= iv.typ.NumMethod() {
+	if v.flag&flagMethod != 0 || i < 0 || i >= v.typ.NumMethod() {
 		panic("reflect: Method index out of range")
 	}
-	return Value{v.Internal, i + 1}
+	fl := v.flag & (flagRO | flagAddr | flagIndir)
+	fl |= flag(Func) << flagKindShift
+	fl |= flag(i)<<flagMethodShift | flagMethod
+	return Value{v.typ, v.val, fl}
 }
 
 // NumMethod returns the number of methods in the value's method set.
 func (v Value) NumMethod() int {
-	iv := v.internal()
-	if iv.kind == Invalid {
+	if v.typ == nil {
 		panic(&ValueError{"reflect.Value.NumMethod", Invalid})
 	}
-	return iv.typ.NumMethod()
+	if v.flag&flagMethod != 0 {
+		return 0
+	}
+	return v.typ.NumMethod()
 }
 
 // MethodByName returns a function value corresponding to the method
@@ -1078,49 +1012,51 @@ func (v Value) NumMethod() int {
 // a receiver; the returned function will always use v as the receiver.
 // It returns the zero Value if no method was found.
 func (v Value) MethodByName(name string) Value {
-	iv := v.internal()
-	if iv.kind == Invalid {
+	if v.typ == nil {
 		panic(&ValueError{"reflect.Value.MethodByName", Invalid})
 	}
-	m, ok := iv.typ.MethodByName(name)
-	if ok {
-		return Value{v.Internal, m.Index + 1}
+	if v.flag&flagMethod != 0 {
+		return Value{}
 	}
-	return Value{}
+	m, ok := v.typ.MethodByName(name)
+	if !ok {
+		return Value{}
+	}
+	return v.Method(m.Index)
 }
 
 // NumField returns the number of fields in the struct v.
 // It panics if v's Kind is not Struct.
 func (v Value) NumField() int {
-	iv := v.internal()
-	iv.mustBe(Struct)
-	return iv.typ.NumField()
+	v.mustBe(Struct)
+	tt := (*structType)(unsafe.Pointer(v.typ))
+	return len(tt.fields)
 }
 
 // OverflowComplex returns true if the complex128 x cannot be represented by v's type.
 // It panics if v's Kind is not Complex64 or Complex128.
 func (v Value) OverflowComplex(x complex128) bool {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Complex64:
 		return overflowFloat32(real(x)) || overflowFloat32(imag(x))
 	case Complex128:
 		return false
 	}
-	panic(&ValueError{"reflect.Value.OverflowComplex", iv.kind})
+	panic(&ValueError{"reflect.Value.OverflowComplex", k})
 }
 
 // OverflowFloat returns true if the float64 x cannot be represented by v's type.
 // It panics if v's Kind is not Float32 or Float64.
 func (v Value) OverflowFloat(x float64) bool {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Float32:
 		return overflowFloat32(x)
 	case Float64:
 		return false
 	}
-	panic(&ValueError{"reflect.Value.OverflowFloat", iv.kind})
+	panic(&ValueError{"reflect.Value.OverflowFloat", k})
 }
 
 func overflowFloat32(x float64) bool {
@@ -1133,27 +1069,27 @@ func overflowFloat32(x float64) bool {
 // OverflowInt returns true if the int64 x cannot be represented by v's type.
 // It panics if v's Kind is not Int, Int8, int16, Int32, or Int64.
 func (v Value) OverflowInt(x int64) bool {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Int, Int8, Int16, Int32, Int64:
-		bitSize := iv.typ.size * 8
+		bitSize := v.typ.size * 8
 		trunc := (x << (64 - bitSize)) >> (64 - bitSize)
 		return x != trunc
 	}
-	panic(&ValueError{"reflect.Value.OverflowInt", iv.kind})
+	panic(&ValueError{"reflect.Value.OverflowInt", k})
 }
 
 // OverflowUint returns true if the uint64 x cannot be represented by v's type.
 // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
 func (v Value) OverflowUint(x uint64) bool {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
-		bitSize := iv.typ.size * 8
+		bitSize := v.typ.size * 8
 		trunc := (x << (64 - bitSize)) >> (64 - bitSize)
 		return x != trunc
 	}
-	panic(&ValueError{"reflect.Value.OverflowUint", iv.kind})
+	panic(&ValueError{"reflect.Value.OverflowUint", k})
 }
 
 // Pointer returns v's value as a uintptr.
@@ -1162,17 +1098,21 @@ func (v Value) OverflowUint(x uint64) bool {
 // without importing the unsafe package explicitly.
 // It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer.
 func (v Value) Pointer() uintptr {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	switch k {
 	case Chan, Func, Map, Ptr, UnsafePointer:
-		if iv.kind == Func && v.InternalMethod != 0 {
+		if k == Func && v.flag&flagMethod != 0 {
 			panic("reflect.Value.Pointer of method Value")
 		}
-		return uintptr(iv.word)
+		p := v.val
+		if v.flag&flagIndir != 0 {
+			p = *(*unsafe.Pointer)(p)
+		}
+		return uintptr(p)
 	case Slice:
-		return (*SliceHeader)(iv.addr).Data
+		return (*SliceHeader)(v.val).Data
 	}
-	panic(&ValueError{"reflect.Value.Pointer", iv.kind})
+	panic(&ValueError{"reflect.Value.Pointer", k})
 }
 
 // Recv receives and returns a value from the channel v.
@@ -1181,25 +1121,26 @@ func (v Value) Pointer() uintptr {
 // The boolean value ok is true if the value x corresponds to a send
 // on the channel, false if it is a zero value received because the channel is closed.
 func (v Value) Recv() (x Value, ok bool) {
-	iv := v.internal()
-	iv.mustBe(Chan)
-	iv.mustBeExported()
-	return iv.recv(false)
+	v.mustBe(Chan)
+	v.mustBeExported()
+	return v.recv(false)
 }
 
-// internal recv, possibly non-blocking (nb)
-func (iv internalValue) recv(nb bool) (val Value, ok bool) {
-	t := iv.typ.toType()
-	if t.ChanDir()&RecvDir == 0 {
+// internal recv, possibly non-blocking (nb).
+// v is known to be a channel.
+func (v Value) recv(nb bool) (val Value, ok bool) {
+	tt := (*chanType)(unsafe.Pointer(v.typ))
+	if ChanDir(tt.dir)&RecvDir == 0 {
 		panic("recv on send-only channel")
 	}
-	ch := iv.word
-	if ch == 0 {
-		panic("recv on nil channel")
-	}
-	valWord, selected, ok := chanrecv(iv.typ.runtimeType(), ch, nb)
+	word, selected, ok := chanrecv(v.typ.runtimeType(), v.iword(), nb)
 	if selected {
-		val = valueFromIword(0, t.Elem(), valWord)
+		typ := toCommonType(tt.elem)
+		fl := flag(typ.Kind()) << flagKindShift
+		if typ.size > ptrSize {
+			fl |= flagIndir
+		}
+		val = Value{typ, unsafe.Pointer(word), fl}
 	}
 	return
 }
@@ -1208,128 +1149,114 @@ func (iv internalValue) recv(nb bool) (val Value, ok bool) {
 // It panics if v's kind is not Chan or if x's type is not the same type as v's element type.
 // As in Go, x's value must be assignable to the channel's element type.
 func (v Value) Send(x Value) {
-	iv := v.internal()
-	iv.mustBe(Chan)
-	iv.mustBeExported()
-	iv.send(x, false)
+	v.mustBe(Chan)
+	v.mustBeExported()
+	v.send(x, false)
 }
 
-// internal send, possibly non-blocking
-func (iv internalValue) send(x Value, nb bool) (selected bool) {
-	t := iv.typ.toType()
-	if t.ChanDir()&SendDir == 0 {
+// internal send, possibly non-blocking.
+// v is known to be a channel.
+func (v Value) send(x Value, nb bool) (selected bool) {
+	tt := (*chanType)(unsafe.Pointer(v.typ))
+	if ChanDir(tt.dir)&SendDir == 0 {
 		panic("send on recv-only channel")
 	}
-	ix := x.internal()
-	ix.mustBeExported() // do not let unexported x leak
-	ix = convertForAssignment("reflect.Value.Send", nil, t.Elem(), ix)
-	ch := iv.word
-	if ch == 0 {
-		panic("send on nil channel")
-	}
-	return chansend(iv.typ.runtimeType(), ch, ix.word, nb)
+	x.mustBeExported()
+	x = x.assignTo("reflect.Value.Send", toCommonType(tt.elem), nil)
+	return chansend(v.typ.runtimeType(), v.iword(), x.iword(), nb)
 }
 
 // Set assigns x to the value v.
 // It panics if CanSet returns false.
 // As in Go, x's value must be assignable to v's type.
 func (v Value) Set(x Value) {
-	iv := v.internal()
-	ix := x.internal()
-
-	iv.mustBeAssignable()
-	ix.mustBeExported() // do not let unexported x leak
-
-	ix = convertForAssignment("reflect.Set", iv.addr, iv.typ, ix)
-
-	n := ix.typ.size
-	if n <= ptrSize {
-		storeIword(iv.addr, ix.word, n)
+	v.mustBeAssignable()
+	x.mustBeExported() // do not let unexported x leak
+	var target *interface{}
+	if v.kind() == Interface {
+		target = (*interface{})(v.val)
+	}
+	x = x.assignTo("reflect.Set", v.typ, target)
+	if x.flag&flagIndir != 0 {
+		memmove(v.val, x.val, v.typ.size)
 	} else {
-		memmove(iv.addr, ix.addr, n)
+		storeIword(v.val, iword(x.val), v.typ.size)
 	}
 }
 
 // SetBool sets v's underlying value.
 // It panics if v's Kind is not Bool or if CanSet() is false.
 func (v Value) SetBool(x bool) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	iv.mustBe(Bool)
-	*(*bool)(iv.addr) = x
+	v.mustBeAssignable()
+	v.mustBe(Bool)
+	*(*bool)(v.val) = x
 }
 
 // SetBytes sets v's underlying value.
 // It panics if v's underlying value is not a slice of bytes.
 func (v Value) SetBytes(x []byte) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	iv.mustBe(Slice)
-	typ := iv.typ.toType()
-	if typ.Elem().Kind() != Uint8 {
+	v.mustBeAssignable()
+	v.mustBe(Slice)
+	if v.typ.Elem().Kind() != Uint8 {
 		panic("reflect.Value.SetBytes of non-byte slice")
 	}
-	*(*[]byte)(iv.addr) = x
+	*(*[]byte)(v.val) = x
 }
 
 // SetComplex sets v's underlying value to x.
 // It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
 func (v Value) SetComplex(x complex128) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	switch iv.kind {
+	v.mustBeAssignable()
+	switch k := v.kind(); k {
 	default:
-		panic(&ValueError{"reflect.Value.SetComplex", iv.kind})
+		panic(&ValueError{"reflect.Value.SetComplex", k})
 	case Complex64:
-		*(*complex64)(iv.addr) = complex64(x)
+		*(*complex64)(v.val) = complex64(x)
 	case Complex128:
-		*(*complex128)(iv.addr) = x
+		*(*complex128)(v.val) = x
 	}
 }
 
 // SetFloat sets v's underlying value to x.
 // It panics if v's Kind is not Float32 or Float64, or if CanSet() is false.
 func (v Value) SetFloat(x float64) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	switch iv.kind {
+	v.mustBeAssignable()
+	switch k := v.kind(); k {
 	default:
-		panic(&ValueError{"reflect.Value.SetFloat", iv.kind})
+		panic(&ValueError{"reflect.Value.SetFloat", k})
 	case Float32:
-		*(*float32)(iv.addr) = float32(x)
+		*(*float32)(v.val) = float32(x)
 	case Float64:
-		*(*float64)(iv.addr) = x
+		*(*float64)(v.val) = x
 	}
 }
 
 // SetInt sets v's underlying value to x.
 // It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64, or if CanSet() is false.
 func (v Value) SetInt(x int64) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	switch iv.kind {
+	v.mustBeAssignable()
+	switch k := v.kind(); k {
 	default:
-		panic(&ValueError{"reflect.Value.SetInt", iv.kind})
+		panic(&ValueError{"reflect.Value.SetInt", k})
 	case Int:
-		*(*int)(iv.addr) = int(x)
+		*(*int)(v.val) = int(x)
 	case Int8:
-		*(*int8)(iv.addr) = int8(x)
+		*(*int8)(v.val) = int8(x)
 	case Int16:
-		*(*int16)(iv.addr) = int16(x)
+		*(*int16)(v.val) = int16(x)
 	case Int32:
-		*(*int32)(iv.addr) = int32(x)
+		*(*int32)(v.val) = int32(x)
 	case Int64:
-		*(*int64)(iv.addr) = x
+		*(*int64)(v.val) = x
 	}
 }
 
 // SetLen sets v's length to n.
 // It panics if v's Kind is not Slice.
 func (v Value) SetLen(n int) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	iv.mustBe(Slice)
-	s := (*SliceHeader)(iv.addr)
+	v.mustBeAssignable()
+	v.mustBe(Slice)
+	s := (*SliceHeader)(v.val)
 	if n < 0 || n > int(s.Cap) {
 		panic("reflect: slice length out of range in SetLen")
 	}
@@ -1342,94 +1269,97 @@ func (v Value) SetLen(n int) {
 // As in Go, key's value must be assignable to the map's key type,
 // and val's value must be assignable to the map's value type.
 func (v Value) SetMapIndex(key, val Value) {
-	iv := v.internal()
-	ikey := key.internal()
-	ival := val.internal()
-
-	iv.mustBe(Map)
-	iv.mustBeExported()
-
-	ikey.mustBeExported()
-	ikey = convertForAssignment("reflect.Value.SetMapIndex", nil, iv.typ.Key(), ikey)
-
-	if ival.kind != Invalid {
-		ival.mustBeExported()
-		ival = convertForAssignment("reflect.Value.SetMapIndex", nil, iv.typ.Elem(), ival)
+	v.mustBe(Map)
+	v.mustBeExported()
+	key.mustBeExported()
+	tt := (*mapType)(unsafe.Pointer(v.typ))
+	key = key.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.key), nil)
+	if val.typ != nil {
+		val.mustBeExported()
+		val = val.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.elem), nil)
 	}
-
-	mapassign(iv.typ.runtimeType(), iv.word, ikey.word, ival.word, ival.kind != Invalid)
+	mapassign(v.typ.runtimeType(), v.iword(), key.iword(), val.iword(), val.typ != nil)
 }
 
 // SetUint sets v's underlying value to x.
 // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64, or if CanSet() is false.
 func (v Value) SetUint(x uint64) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	switch iv.kind {
+	v.mustBeAssignable()
+	switch k := v.kind(); k {
 	default:
-		panic(&ValueError{"reflect.Value.SetUint", iv.kind})
+		panic(&ValueError{"reflect.Value.SetUint", k})
 	case Uint:
-		*(*uint)(iv.addr) = uint(x)
+		*(*uint)(v.val) = uint(x)
 	case Uint8:
-		*(*uint8)(iv.addr) = uint8(x)
+		*(*uint8)(v.val) = uint8(x)
 	case Uint16:
-		*(*uint16)(iv.addr) = uint16(x)
+		*(*uint16)(v.val) = uint16(x)
 	case Uint32:
-		*(*uint32)(iv.addr) = uint32(x)
+		*(*uint32)(v.val) = uint32(x)
 	case Uint64:
-		*(*uint64)(iv.addr) = x
+		*(*uint64)(v.val) = x
 	case Uintptr:
-		*(*uintptr)(iv.addr) = uintptr(x)
+		*(*uintptr)(v.val) = uintptr(x)
 	}
 }
 
 // SetPointer sets the unsafe.Pointer value v to x.
 // It panics if v's Kind is not UnsafePointer.
 func (v Value) SetPointer(x unsafe.Pointer) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	iv.mustBe(UnsafePointer)
-	*(*unsafe.Pointer)(iv.addr) = x
+	v.mustBeAssignable()
+	v.mustBe(UnsafePointer)
+	*(*unsafe.Pointer)(v.val) = x
 }
 
 // SetString sets v's underlying value to x.
 // It panics if v's Kind is not String or if CanSet() is false.
 func (v Value) SetString(x string) {
-	iv := v.internal()
-	iv.mustBeAssignable()
-	iv.mustBe(String)
-	*(*string)(iv.addr) = x
+	v.mustBeAssignable()
+	v.mustBe(String)
+	*(*string)(v.val) = x
 }
 
 // Slice returns a slice of v.
 // It panics if v's Kind is not Array or Slice.
 func (v Value) Slice(beg, end int) Value {
-	iv := v.internal()
-	if iv.kind != Array && iv.kind != Slice {
-		panic(&ValueError{"reflect.Value.Slice", iv.kind})
-	}
-	cap := v.Cap()
-	if beg < 0 || end < beg || end > cap {
-		panic("reflect.Value.Slice: slice index out of bounds")
-	}
-	var typ Type
-	var base uintptr
-	switch iv.kind {
+	var (
+		cap  int
+		typ  *sliceType
+		base unsafe.Pointer
+	)
+	switch k := v.kind(); k {
+	default:
+		panic(&ValueError{"reflect.Value.Slice", k})
 	case Array:
-		if iv.flag&flagAddr == 0 {
+		if v.flag&flagAddr == 0 {
 			panic("reflect.Value.Slice: slice of unaddressable array")
 		}
-		typ = toType((*arrayType)(unsafe.Pointer(iv.typ)).slice)
-		base = uintptr(iv.addr)
+		tt := (*arrayType)(unsafe.Pointer(v.typ))
+		cap = int(tt.len)
+		typ = (*sliceType)(unsafe.Pointer(toCommonType(tt.slice)))
+		base = v.val
 	case Slice:
-		typ = iv.typ.toType()
-		base = (*SliceHeader)(iv.addr).Data
+		typ = (*sliceType)(unsafe.Pointer(v.typ))
+		s := (*SliceHeader)(v.val)
+		base = unsafe.Pointer(s.Data)
+		cap = s.Cap
+
+	}
+	if beg < 0 || end < beg || end > cap {
+		panic("reflect.Value.Slice: slice index out of bounds")
 	}
-	s := new(SliceHeader)
-	s.Data = base + uintptr(beg)*typ.Elem().Size()
+
+	// Declare slice so that gc can see the base pointer in it.
+	var x []byte
+
+	// Reinterpret as *SliceHeader to edit.
+	s := (*SliceHeader)(unsafe.Pointer(&x))
+	s.Data = uintptr(base) + uintptr(beg)*toCommonType(typ.elem).Size()
 	s.Len = end - beg
 	s.Cap = cap - beg
-	return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))
+
+	fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
+	return Value{typ.common(), unsafe.Pointer(&x), fl}
 }
 
 // String returns the string v's underlying value, as a string.
@@ -1437,16 +1367,15 @@ func (v Value) Slice(beg, end int) Value {
 // Unlike the other getters, it does not panic if v's Kind is not String.
 // Instead, it returns a string of the form "<T value>" where T is v's type.
 func (v Value) String() string {
-	iv := v.internal()
-	switch iv.kind {
+	switch k := v.kind(); k {
 	case Invalid:
 		return "<invalid Value>"
 	case String:
-		return *(*string)(iv.addr)
+		return *(*string)(v.val)
 	}
 	// If you call String on a reflect.Value of other type, it's better to
 	// print something than to panic. Useful in debugging.
-	return "<" + iv.typ.String() + " Value>"
+	return "<" + v.typ.String() + " Value>"
 }
 
 // TryRecv attempts to receive a value from the channel v but will not block.
@@ -1455,10 +1384,9 @@ func (v Value) String() string {
 // The boolean ok is true if the value x corresponds to a send
 // on the channel, false if it is a zero value received because the channel is closed.
 func (v Value) TryRecv() (x Value, ok bool) {
-	iv := v.internal()
-	iv.mustBe(Chan)
-	iv.mustBeExported()
-	return iv.recv(true)
+	v.mustBe(Chan)
+	v.mustBeExported()
+	return v.recv(true)
 }
 
 // TrySend attempts to send x on the channel v but will not block.
@@ -1466,57 +1394,83 @@ func (v Value) TryRecv() (x Value, ok bool) {
 // It returns true if the value was sent, false otherwise.
 // As in Go, x's value must be assignable to the channel's element type.
 func (v Value) TrySend(x Value) bool {
-	iv := v.internal()
-	iv.mustBe(Chan)
-	iv.mustBeExported()
-	return iv.send(x, true)
+	v.mustBe(Chan)
+	v.mustBeExported()
+	return v.send(x, true)
 }
 
 // Type returns v's type.
 func (v Value) Type() Type {
-	t := v.internal().typ
-	if t == nil {
+	f := v.flag
+	if f == 0 {
 		panic(&ValueError{"reflect.Value.Type", Invalid})
 	}
-	return t.toType()
+	if f&flagMethod == 0 {
+		// Easy case
+		return v.typ
+	}
+
+	// Method value.
+	// v.typ describes the receiver, not the method type.
+	i := int(v.flag) >> flagMethodShift
+	if v.typ.Kind() == Interface {
+		// Method on interface.
+		tt := (*interfaceType)(unsafe.Pointer(v.typ))
+		if i < 0 || i >= len(tt.methods) {
+			panic("reflect: broken Value")
+		}
+		m := &tt.methods[i]
+		return toCommonType(m.typ)
+	}
+	// Method on concrete type.
+	ut := v.typ.uncommon()
+	if ut == nil || i < 0 || i >= len(ut.methods) {
+		panic("reflect: broken Value")
+	}
+	m := &ut.methods[i]
+	return toCommonType(m.mtyp)
 }
 
 // Uint returns v's underlying value, as a uint64.
 // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
 func (v Value) Uint() uint64 {
-	iv := v.internal()
-	switch iv.kind {
+	k := v.kind()
+	var p unsafe.Pointer
+	if v.flag&flagIndir != 0 {
+		p = v.val
+	} else {
+		// The escape analysis is good enough that &v.val
+		// does not trigger a heap allocation.
+		p = unsafe.Pointer(&v.val)
+	}
+	switch k {
 	case Uint:
-		return uint64(*(*uint)(unsafe.Pointer(&iv.word)))
+		return uint64(*(*uint)(p))
 	case Uint8:
-		return uint64(*(*uint8)(unsafe.Pointer(&iv.word)))
+		return uint64(*(*uint8)(p))
 	case Uint16:
-		return uint64(*(*uint16)(unsafe.Pointer(&iv.word)))
+		return uint64(*(*uint16)(p))
 	case Uint32:
-		return uint64(*(*uint32)(unsafe.Pointer(&iv.word)))
-	case Uintptr:
-		return uint64(*(*uintptr)(unsafe.Pointer(&iv.word)))
+		return uint64(*(*uint32)(p))
 	case Uint64:
-		if iv.addr == nil {
-			return *(*uint64)(unsafe.Pointer(&iv.word))
-		}
-		return *(*uint64)(iv.addr)
+		return uint64(*(*uint64)(p))
+	case Uintptr:
+		return uint64(*(*uintptr)(p))
 	}
-	panic(&ValueError{"reflect.Value.Uint", iv.kind})
+	panic(&ValueError{"reflect.Value.Uint", k})
 }
 
 // UnsafeAddr returns a pointer to v's data.
 // It is for advanced clients that also import the "unsafe" package.
 // It panics if v is not addressable.
 func (v Value) UnsafeAddr() uintptr {
-	iv := v.internal()
-	if iv.kind == Invalid {
-		panic(&ValueError{"reflect.Value.UnsafeAddr", iv.kind})
+	if v.typ == nil {
+		panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
 	}
-	if iv.flag&flagAddr == 0 {
+	if v.flag&flagAddr == 0 {
 		panic("reflect.Value.UnsafeAddr of unaddressable value")
 	}
-	return uintptr(iv.addr)
+	return uintptr(v.val)
 }
 
 // StringHeader is the runtime representation of a string.
@@ -1536,7 +1490,7 @@ type SliceHeader struct {
 
 func typesMustMatch(what string, t1, t2 Type) {
 	if t1 != t2 {
-		panic("reflect: " + what + ": " + t1.String() + " != " + t2.String())
+		panic(what + ": " + t1.String() + " != " + t2.String())
 	}
 }
 
@@ -1571,7 +1525,7 @@ func grow(s Value, extra int) (Value, int, int) {
 // Append appends the values x to a slice s and returns the resulting slice.
 // As in Go, each x's value must be assignable to the slice's element type.
 func Append(s Value, x ...Value) Value {
-	s.internal().mustBe(Slice)
+	s.mustBe(Slice)
 	s, i0, i1 := grow(s, len(x))
 	for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
 		s.Index(i).Set(x[j])
@@ -1582,8 +1536,8 @@ func Append(s Value, x ...Value) Value {
 // AppendSlice appends a slice t to a slice s and returns the resulting slice.
 // The slices s and t must have the same element type.
 func AppendSlice(s, t Value) Value {
-	s.internal().mustBe(Slice)
-	t.internal().mustBe(Slice)
+	s.mustBe(Slice)
+	t.mustBe(Slice)
 	typesMustMatch("reflect.AppendSlice", s.Type().Elem(), t.Type().Elem())
 	s, i0, i1 := grow(s, t.Len())
 	Copy(s.Slice(i0, i1), t)
@@ -1596,23 +1550,23 @@ func AppendSlice(s, t Value) Value {
 // Dst and src each must have kind Slice or Array, and
 // dst and src must have the same element type.
 func Copy(dst, src Value) int {
-	idst := dst.internal()
-	isrc := src.internal()
-
-	if idst.kind != Array && idst.kind != Slice {
-		panic(&ValueError{"reflect.Copy", idst.kind})
+	dk := dst.kind()
+	if dk != Array && dk != Slice {
+		panic(&ValueError{"reflect.Copy", dk})
 	}
-	if idst.kind == Array {
-		idst.mustBeAssignable()
+	if dk == Array {
+		dst.mustBeAssignable()
 	}
-	idst.mustBeExported()
-	if isrc.kind != Array && isrc.kind != Slice {
-		panic(&ValueError{"reflect.Copy", isrc.kind})
+	dst.mustBeExported()
+
+	sk := src.kind()
+	if sk != Array && sk != Slice {
+		panic(&ValueError{"reflect.Copy", sk})
 	}
-	isrc.mustBeExported()
+	src.mustBeExported()
 
-	de := idst.typ.Elem()
-	se := isrc.typ.Elem()
+	de := dst.typ.Elem()
+	se := src.typ.Elem()
 	typesMustMatch("reflect.Copy", de, se)
 
 	n := dst.Len()
@@ -1622,7 +1576,7 @@ func Copy(dst, src Value) int {
 
 	// If sk is an in-line array, cannot take its address.
 	// Instead, copy element by element.
-	if isrc.addr == nil {
+	if src.flag&flagIndir == 0 {
 		for i := 0; i < n; i++ {
 			dst.Index(i).Set(src.Index(i))
 		}
@@ -1631,15 +1585,15 @@ func Copy(dst, src Value) int {
 
 	// Copy via memmove.
 	var da, sa unsafe.Pointer
-	if idst.kind == Array {
-		da = idst.addr
+	if dk == Array {
+		da = dst.val
 	} else {
-		da = unsafe.Pointer((*SliceHeader)(idst.addr).Data)
+		da = unsafe.Pointer((*SliceHeader)(dst.val).Data)
 	}
-	if isrc.kind == Array {
-		sa = isrc.addr
+	if sk == Array {
+		sa = src.val
 	} else {
-		sa = unsafe.Pointer((*SliceHeader)(isrc.addr).Data)
+		sa = unsafe.Pointer((*SliceHeader)(src.val).Data)
 	}
 	memmove(da, sa, uintptr(n)*de.Size())
 	return n
@@ -1653,38 +1607,43 @@ func Copy(dst, src Value) int {
 // for the specified slice type, length, and capacity.
 func MakeSlice(typ Type, len, cap int) Value {
 	if typ.Kind() != Slice {
-		panic("reflect: MakeSlice of non-slice type")
-	}
-	s := &SliceHeader{
-		Data: uintptr(unsafe.NewArray(typ.Elem(), cap)),
-		Len:  len,
-		Cap:  cap,
+		panic("reflect.MakeSlice of non-slice type")
 	}
-	return valueFromAddr(0, typ, unsafe.Pointer(s))
+
+	// Declare slice so that gc can see the base pointer in it.
+	var x []byte
+
+	// Reinterpret as *SliceHeader to edit.
+	s := (*SliceHeader)(unsafe.Pointer(&x))
+	s.Data = uintptr(unsafe.NewArray(typ.Elem(), cap))
+	s.Len = len
+	s.Cap = cap
+
+	return Value{typ.common(), unsafe.Pointer(&x), flagIndir | flag(Slice)<<flagKindShift}
 }
 
 // MakeChan creates a new channel with the specified type and buffer size.
 func MakeChan(typ Type, buffer int) Value {
 	if typ.Kind() != Chan {
-		panic("reflect: MakeChan of non-chan type")
+		panic("reflect.MakeChan of non-chan type")
 	}
 	if buffer < 0 {
-		panic("MakeChan: negative buffer size")
+		panic("reflect.MakeChan: negative buffer size")
 	}
 	if typ.ChanDir() != BothDir {
-		panic("MakeChan: unidirectional channel type")
+		panic("reflect.MakeChan: unidirectional channel type")
 	}
 	ch := makechan(typ.runtimeType(), uint32(buffer))
-	return valueFromIword(0, typ, ch)
+	return Value{typ.common(), unsafe.Pointer(ch), flag(Chan) << flagKindShift}
 }
 
 // MakeMap creates a new map of the specified type.
 func MakeMap(typ Type) Value {
 	if typ.Kind() != Map {
-		panic("reflect: MakeMap of non-map type")
+		panic("reflect.MakeMap of non-map type")
 	}
 	m := makemap(typ.runtimeType())
-	return valueFromIword(0, typ, m)
+	return Value{typ.common(), unsafe.Pointer(m), flag(Map) << flagKindShift}
 }
 
 // Indirect returns the value that v points to.
@@ -1714,7 +1673,12 @@ func ValueOf(i interface{}) Value {
 	// For an interface value with the noAddr bit set,
 	// the representation is identical to an empty interface.
 	eface := *(*emptyInterface)(unsafe.Pointer(&i))
-	return packValue(0, eface.typ, eface.word)
+	typ := toCommonType(eface.typ)
+	fl := flag(typ.Kind()) << flagKindShift
+	if typ.size > ptrSize {
+		fl |= flagIndir
+	}
+	return Value{typ, unsafe.Pointer(eface.word), fl}
 }
 
 // Zero returns a Value representing a zero value for the specified type.
@@ -1725,10 +1689,12 @@ func Zero(typ Type) Value {
 	if typ == nil {
 		panic("reflect: Zero(nil)")
 	}
-	if typ.Size() <= ptrSize {
-		return valueFromIword(0, typ, 0)
+	t := typ.common()
+	fl := flag(t.Kind()) << flagKindShift
+	if t.size <= ptrSize {
+		return Value{t, nil, fl}
 	}
-	return valueFromAddr(0, typ, unsafe.New(typ))
+	return Value{t, unsafe.New(typ), fl | flagIndir}
 }
 
 // New returns a Value representing a pointer to a new zero value
@@ -1738,40 +1704,42 @@ func New(typ Type) Value {
 		panic("reflect: New(nil)")
 	}
 	ptr := unsafe.New(typ)
-	return valueFromIword(0, PtrTo(typ), iword(ptr))
+	fl := flag(Ptr) << flagKindShift
+	return Value{typ.common().ptrTo(), ptr, fl}
 }
 
-// convertForAssignment 
-func convertForAssignment(what string, addr unsafe.Pointer, dst Type, iv internalValue) internalValue {
-	if iv.method {
-		panic(what + ": cannot assign method value to type " + dst.String())
+// assignTo returns a value v that can be assigned directly to typ.
+// It panics if v is not assignable to typ.
+// For a conversion to an interface type, target is a suggested scratch space to use.
+func (v Value) assignTo(context string, dst *commonType, target *interface{}) Value {
+	if v.flag&flagMethod != 0 {
+		panic(context + ": cannot assign method value to type " + dst.String())
 	}
 
-	dst1 := dst.(*commonType)
-	if directlyAssignable(dst1, iv.typ) {
+	switch {
+	case directlyAssignable(dst, v.typ):
 		// Overwrite type so that they match.
 		// Same memory layout, so no harm done.
-		iv.typ = dst1
-		return iv
-	}
-	if implements(dst1, iv.typ) {
-		if addr == nil {
-			addr = unsafe.Pointer(new(interface{}))
+		v.typ = dst
+		fl := v.flag & (flagRO | flagAddr | flagIndir)
+		fl |= flag(dst.Kind()) << flagKindShift
+		return Value{dst, v.val, fl}
+
+	case implements(dst, v.typ):
+		if target == nil {
+			target = new(interface{})
 		}
-		x := iv.Interface()
+		x := valueInterface(v, false)
 		if dst.NumMethod() == 0 {
-			*(*interface{})(addr) = x
+			*target = x
 		} else {
-			ifaceE2I(dst1.runtimeType(), x, addr)
+			ifaceE2I(dst.runtimeType(), x, unsafe.Pointer(target))
 		}
-		iv.addr = addr
-		iv.word = iword(addr)
-		iv.typ = dst1
-		return iv
+		return Value{dst, unsafe.Pointer(target), flagIndir | flag(Interface)<<flagKindShift}
 	}
 
 	// Failed.
-	panic(what + ": value of type " + iv.typ.String() + " is not assignable to type " + dst.String())
+	panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
 }
 
 // implemented in ../pkg/runtime
@@ -1782,7 +1750,7 @@ func chanrecv(t *runtime.Type, ch iword, nb bool) (val iword, selected, received
 func chansend(t *runtime.Type, ch iword, val iword, nb bool) bool
 
 func makechan(typ *runtime.Type, size uint32) (ch iword)
-func makemap(t *runtime.Type) iword
+func makemap(t *runtime.Type) (m iword)
 func mapaccess(t *runtime.Type, m iword, key iword) (val iword, ok bool)
 func mapassign(t *runtime.Type, m iword, key, val iword, ok bool)
 func mapiterinit(t *runtime.Type, m iword) *byte
@@ -1792,3 +1760,17 @@ func maplen(m iword) int32
 
 func call(fn, arg unsafe.Pointer, n uint32)
 func ifaceE2I(t *runtime.Type, src interface{}, dst unsafe.Pointer)
+
+// Dummy annotation marking that the value x escapes,
+// for use in cases where the reflect code is so clever that
+// the compiler cannot follow.
+func escapes(x interface{}) {
+	if dummy.b {
+		dummy.x = x
+	}
+}
+
+var dummy struct {
+	b bool
+	x interface{}
+}
diff --git a/src/pkg/regexp/Makefile b/src/pkg/regexp/Makefile
index 9024e66..60406c7 100644
--- a/src/pkg/regexp/Makefile
+++ b/src/pkg/regexp/Makefile
@@ -1,4 +1,4 @@
-# Copyright 2009 The Go Authors. All rights reserved.
+# Copyright 2011 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.
 
@@ -6,6 +6,7 @@ include ../../Make.inc
 
 TARG=regexp
 GOFILES=\
+	exec.go\
 	regexp.go\
 
 include ../../Make.pkg
diff --git a/src/pkg/regexp/all_test.go b/src/pkg/regexp/all_test.go
index 71edc4d..107dfe3 100644
--- a/src/pkg/regexp/all_test.go
+++ b/src/pkg/regexp/all_test.go
@@ -5,7 +5,6 @@
 package regexp
 
 import (
-	"os"
 	"strings"
 	"testing"
 )
@@ -24,16 +23,16 @@ var good_re = []string{
 	`[a-z]`,
 	`[a-abc-c\-\]\[]`,
 	`[a-z]+`,
-	`[]`,
 	`[abc]`,
 	`[^1234]`,
 	`[^\n]`,
 	`\!\\`,
 }
 
+/*
 type stringError struct {
 	re  string
-	err os.Error
+	err error
 }
 
 var bad_re = []stringError{
@@ -51,11 +50,12 @@ var bad_re = []stringError{
 	{`a??`, ErrBadClosure},
 	{`\x`, ErrBadBackslash},
 }
+*/
 
-func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
+func compileTest(t *testing.T, expr string, error error) *Regexp {
 	re, err := Compile(expr)
 	if err != error {
-		t.Error("compiling `", expr, "`; unexpected error: ", err.String())
+		t.Error("compiling `", expr, "`; unexpected error: ", err.Error())
 	}
 	return re
 }
@@ -66,11 +66,13 @@ func TestGoodCompile(t *testing.T) {
 	}
 }
 
+/*
 func TestBadCompile(t *testing.T) {
 	for i := 0; i < len(bad_re); i++ {
 		compileTest(t, bad_re[i].re, bad_re[i].err)
 	}
 }
+*/
 
 func matchTest(t *testing.T, test *FindTest) {
 	re := compileTest(t, test.pat, nil)
@@ -240,7 +242,7 @@ var metaTests = []MetaTest{
 	{`foo`, `foo`, `foo`, true},
 	{`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
 	{`foo.\$`, `foo\.\\\$`, `foo`, false},     // has escaped operators and real operators
-	{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`, `!@#`, false},
+	{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false},
 }
 
 func TestQuoteMeta(t *testing.T) {
@@ -287,30 +289,45 @@ func TestLiteralPrefix(t *testing.T) {
 	}
 }
 
-type numSubexpCase struct {
-	input    string
-	expected int
+type subexpCase struct {
+	input string
+	num   int
+	names []string
 }
 
-var numSubexpCases = []numSubexpCase{
-	{``, 0},
-	{`.*`, 0},
-	{`abba`, 0},
-	{`ab(b)a`, 1},
-	{`ab(.*)a`, 1},
-	{`(.*)ab(.*)a`, 2},
-	{`(.*)(ab)(.*)a`, 3},
-	{`(.*)((a)b)(.*)a`, 4},
-	{`(.*)(\(ab)(.*)a`, 3},
-	{`(.*)(\(a\)b)(.*)a`, 3},
+var subexpCases = []subexpCase{
+	{``, 0, nil},
+	{`.*`, 0, nil},
+	{`abba`, 0, nil},
+	{`ab(b)a`, 1, []string{"", ""}},
+	{`ab(.*)a`, 1, []string{"", ""}},
+	{`(.*)ab(.*)a`, 2, []string{"", "", ""}},
+	{`(.*)(ab)(.*)a`, 3, []string{"", "", "", ""}},
+	{`(.*)((a)b)(.*)a`, 4, []string{"", "", "", "", ""}},
+	{`(.*)(\(ab)(.*)a`, 3, []string{"", "", "", ""}},
+	{`(.*)(\(a\)b)(.*)a`, 3, []string{"", "", "", ""}},
+	{`(?P<foo>.*)(?P<bar>(a)b)(?P<foo>.*)a`, 4, []string{"", "foo", "bar", "", "foo"}},
 }
 
-func TestNumSubexp(t *testing.T) {
-	for _, c := range numSubexpCases {
+func TestSubexp(t *testing.T) {
+	for _, c := range subexpCases {
 		re := MustCompile(c.input)
 		n := re.NumSubexp()
-		if n != c.expected {
-			t.Errorf("NumSubexp for %q returned %d, expected %d", c.input, n, c.expected)
+		if n != c.num {
+			t.Errorf("%q: NumSubexp = %d, want %d", c.input, n, c.num)
+			continue
+		}
+		names := re.SubexpNames()
+		if len(names) != 1+n {
+			t.Errorf("%q: len(SubexpNames) = %d, want %d", c.input, len(names), n)
+			continue
+		}
+		if c.names != nil {
+			for i := 0; i < 1+n; i++ {
+				if names[i] != c.names[i] {
+					t.Errorf("%q: SubexpNames[%d] = %q, want %q", c.input, i, names[i], c.names[i])
+				}
+			}
 		}
 	}
 }
@@ -322,8 +339,7 @@ func BenchmarkLiteral(b *testing.B) {
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
 		if !re.MatchString(x) {
-			println("no match!")
-			break
+			b.Fatalf("no match!")
 		}
 	}
 }
@@ -335,8 +351,7 @@ func BenchmarkNotLiteral(b *testing.B) {
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
 		if !re.MatchString(x) {
-			println("no match!")
-			break
+			b.Fatalf("no match!")
 		}
 	}
 }
@@ -348,8 +363,7 @@ func BenchmarkMatchClass(b *testing.B) {
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
 		if !re.MatchString(x) {
-			println("no match!")
-			break
+			b.Fatalf("no match!")
 		}
 	}
 }
@@ -363,8 +377,7 @@ func BenchmarkMatchClass_InRange(b *testing.B) {
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
 		if !re.MatchString(x) {
-			println("no match!")
-			break
+			b.Fatalf("no match!")
 		}
 	}
 }
diff --git a/src/pkg/regexp/exec.go b/src/pkg/regexp/exec.go
new file mode 100644
index 0000000..333ca25
--- /dev/null
+++ b/src/pkg/regexp/exec.go
@@ -0,0 +1,345 @@
+// Copyright 2011 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 regexp
+
+import (
+	"io"
+	"regexp/syntax"
+)
+
+// A queue is a 'sparse array' holding pending threads of execution.
+// See http://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html
+type queue struct {
+	sparse []uint32
+	dense  []entry
+}
+
+// A entry is an entry on a queue.
+// It holds both the instruction pc and the actual thread.
+// Some queue entries are just place holders so that the machine
+// knows it has considered that pc.  Such entries have t == nil.
+type entry struct {
+	pc uint32
+	t  *thread
+}
+
+// A thread is the state of a single path through the machine:
+// an instruction and a corresponding capture array.
+// See http://swtch.com/~rsc/regexp/regexp2.html
+type thread struct {
+	inst *syntax.Inst
+	cap  []int
+}
+
+// A machine holds all the state during an NFA simulation for p.
+type machine struct {
+	re       *Regexp      // corresponding Regexp
+	p        *syntax.Prog // compiled program
+	q0, q1   queue        // two queues for runq, nextq
+	pool     []*thread    // pool of available threads
+	matched  bool         // whether a match was found
+	matchcap []int        // capture information for the match
+
+	// cached inputs, to avoid allocation
+	inputBytes  inputBytes
+	inputString inputString
+	inputReader inputReader
+}
+
+func (m *machine) newInputBytes(b []byte) input {
+	m.inputBytes.str = b
+	return &m.inputBytes
+}
+
+func (m *machine) newInputString(s string) input {
+	m.inputString.str = s
+	return &m.inputString
+}
+
+func (m *machine) newInputReader(r io.RuneReader) input {
+	m.inputReader.r = r
+	m.inputReader.atEOT = false
+	m.inputReader.pos = 0
+	return &m.inputReader
+}
+
+// progMachine returns a new machine running the prog p.
+func progMachine(p *syntax.Prog) *machine {
+	m := &machine{p: p}
+	n := len(m.p.Inst)
+	m.q0 = queue{make([]uint32, n), make([]entry, 0, n)}
+	m.q1 = queue{make([]uint32, n), make([]entry, 0, n)}
+	ncap := p.NumCap
+	if ncap < 2 {
+		ncap = 2
+	}
+	m.matchcap = make([]int, ncap)
+	return m
+}
+
+func (m *machine) init(ncap int) {
+	for _, t := range m.pool {
+		t.cap = t.cap[:ncap]
+	}
+	m.matchcap = m.matchcap[:ncap]
+}
+
+// alloc allocates a new thread with the given instruction.
+// It uses the free pool if possible.
+func (m *machine) alloc(i *syntax.Inst) *thread {
+	var t *thread
+	if n := len(m.pool); n > 0 {
+		t = m.pool[n-1]
+		m.pool = m.pool[:n-1]
+	} else {
+		t = new(thread)
+		t.cap = make([]int, len(m.matchcap), cap(m.matchcap))
+	}
+	t.inst = i
+	return t
+}
+
+// free returns t to the free pool.
+func (m *machine) free(t *thread) {
+	m.inputBytes.str = nil
+	m.inputString.str = ""
+	m.inputReader.r = nil
+	m.pool = append(m.pool, t)
+}
+
+// match runs the machine over the input starting at pos.
+// It reports whether a match was found.
+// If so, m.matchcap holds the submatch information.
+func (m *machine) match(i input, pos int) bool {
+	startCond := m.re.cond
+	if startCond == ^syntax.EmptyOp(0) { // impossible
+		return false
+	}
+	m.matched = false
+	for i := range m.matchcap {
+		m.matchcap[i] = -1
+	}
+	runq, nextq := &m.q0, &m.q1
+	r, r1 := endOfText, endOfText
+	width, width1 := 0, 0
+	r, width = i.step(pos)
+	if r != endOfText {
+		r1, width1 = i.step(pos + width)
+	}
+	var flag syntax.EmptyOp
+	if pos == 0 {
+		flag = syntax.EmptyOpContext(-1, r)
+	} else {
+		flag = i.context(pos)
+	}
+	for {
+		if len(runq.dense) == 0 {
+			if startCond&syntax.EmptyBeginText != 0 && pos != 0 {
+				// Anchored match, past beginning of text.
+				break
+			}
+			if m.matched {
+				// Have match; finished exploring alternatives.
+				break
+			}
+			if len(m.re.prefix) > 0 && r1 != m.re.prefixRune && i.canCheckPrefix() {
+				// Match requires literal prefix; fast search for it.
+				advance := i.index(m.re, pos)
+				if advance < 0 {
+					break
+				}
+				pos += advance
+				r, width = i.step(pos)
+				r1, width1 = i.step(pos + width)
+			}
+		}
+		if !m.matched {
+			if len(m.matchcap) > 0 {
+				m.matchcap[0] = pos
+			}
+			m.add(runq, uint32(m.p.Start), pos, m.matchcap, flag, nil)
+		}
+		flag = syntax.EmptyOpContext(r, r1)
+		m.step(runq, nextq, pos, pos+width, r, flag)
+		if width == 0 {
+			break
+		}
+		if len(m.matchcap) == 0 && m.matched {
+			// Found a match and not paying attention
+			// to where it is, so any match will do.
+			break
+		}
+		pos += width
+		r, width = r1, width1
+		if r != endOfText {
+			r1, width1 = i.step(pos + width)
+		}
+		runq, nextq = nextq, runq
+	}
+	m.clear(nextq)
+	return m.matched
+}
+
+// clear frees all threads on the thread queue.
+func (m *machine) clear(q *queue) {
+	for _, d := range q.dense {
+		if d.t != nil {
+			// m.free(d.t)
+			m.pool = append(m.pool, d.t)
+		}
+	}
+	q.dense = q.dense[:0]
+}
+
+// step executes one step of the machine, running each of the threads
+// on runq and appending new threads to nextq.
+// The step processes the rune c (which may be endOfText),
+// which starts at position pos and ends at nextPos.
+// nextCond gives the setting for the empty-width flags after c.
+func (m *machine) step(runq, nextq *queue, pos, nextPos int, c rune, nextCond syntax.EmptyOp) {
+	longest := m.re.longest
+	for j := 0; j < len(runq.dense); j++ {
+		d := &runq.dense[j]
+		t := d.t
+		if t == nil {
+			continue
+		}
+		if longest && m.matched && len(t.cap) > 0 && m.matchcap[0] < t.cap[0] {
+			// m.free(t)
+			m.pool = append(m.pool, t)
+			continue
+		}
+		i := t.inst
+		add := false
+		switch i.Op {
+		default:
+			panic("bad inst")
+
+		case syntax.InstMatch:
+			if len(t.cap) > 0 && (!longest || !m.matched || m.matchcap[1] < pos) {
+				t.cap[1] = pos
+				copy(m.matchcap, t.cap)
+			}
+			if !longest {
+				// First-match mode: cut off all lower-priority threads.
+				for _, d := range runq.dense[j+1:] {
+					if d.t != nil {
+						// m.free(d.t)
+						m.pool = append(m.pool, d.t)
+					}
+				}
+				runq.dense = runq.dense[:0]
+			}
+			m.matched = true
+
+		case syntax.InstRune:
+			add = i.MatchRune(c)
+		case syntax.InstRune1:
+			add = c == i.Rune[0]
+		case syntax.InstRuneAny:
+			add = true
+		case syntax.InstRuneAnyNotNL:
+			add = c != '\n'
+		}
+		if add {
+			t = m.add(nextq, i.Out, nextPos, t.cap, nextCond, t)
+		}
+		if t != nil {
+			// m.free(t)
+			m.pool = append(m.pool, t)
+		}
+	}
+	runq.dense = runq.dense[:0]
+}
+
+// add adds an entry to q for pc, unless the q already has such an entry.
+// It also recursively adds an entry for all instructions reachable from pc by following
+// empty-width conditions satisfied by cond.  pos gives the current position
+// in the input.
+func (m *machine) add(q *queue, pc uint32, pos int, cap []int, cond syntax.EmptyOp, t *thread) *thread {
+	if pc == 0 {
+		return t
+	}
+	if j := q.sparse[pc]; j < uint32(len(q.dense)) && q.dense[j].pc == pc {
+		return t
+	}
+
+	j := len(q.dense)
+	q.dense = q.dense[:j+1]
+	d := &q.dense[j]
+	d.t = nil
+	d.pc = pc
+	q.sparse[pc] = uint32(j)
+
+	i := &m.p.Inst[pc]
+	switch i.Op {
+	default:
+		panic("unhandled")
+	case syntax.InstFail:
+		// nothing
+	case syntax.InstAlt, syntax.InstAltMatch:
+		t = m.add(q, i.Out, pos, cap, cond, t)
+		t = m.add(q, i.Arg, pos, cap, cond, t)
+	case syntax.InstEmptyWidth:
+		if syntax.EmptyOp(i.Arg)&^cond == 0 {
+			t = m.add(q, i.Out, pos, cap, cond, t)
+		}
+	case syntax.InstNop:
+		t = m.add(q, i.Out, pos, cap, cond, t)
+	case syntax.InstCapture:
+		if int(i.Arg) < len(cap) {
+			opos := cap[i.Arg]
+			cap[i.Arg] = pos
+			m.add(q, i.Out, pos, cap, cond, nil)
+			cap[i.Arg] = opos
+		} else {
+			t = m.add(q, i.Out, pos, cap, cond, t)
+		}
+	case syntax.InstMatch, syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
+		if t == nil {
+			t = m.alloc(i)
+		} else {
+			t.inst = i
+		}
+		if len(cap) > 0 && &t.cap[0] != &cap[0] {
+			copy(t.cap, cap)
+		}
+		d.t = t
+		t = nil
+	}
+	return t
+}
+
+// empty is a non-nil 0-element slice,
+// so doExecute can avoid an allocation
+// when 0 captures are requested from a successful match.
+var empty = make([]int, 0)
+
+// doExecute finds the leftmost match in the input and returns
+// the position of its subexpressions.
+func (re *Regexp) doExecute(r io.RuneReader, b []byte, s string, pos int, ncap int) []int {
+	m := re.get()
+	var i input
+	if r != nil {
+		i = m.newInputReader(r)
+	} else if b != nil {
+		i = m.newInputBytes(b)
+	} else {
+		i = m.newInputString(s)
+	}
+	m.init(ncap)
+	if !m.match(i, pos) {
+		re.put(m)
+		return nil
+	}
+	if ncap == 0 {
+		re.put(m)
+		return empty // empty but not nil
+	}
+	cap := make([]int, ncap)
+	copy(cap, m.matchcap)
+	re.put(m)
+	return cap
+}
diff --git a/src/pkg/regexp/exec_test.go b/src/pkg/regexp/exec_test.go
new file mode 100644
index 0000000..e668574
--- /dev/null
+++ b/src/pkg/regexp/exec_test.go
@@ -0,0 +1,709 @@
+// Copyright 2010 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 regexp
+
+import (
+	"bufio"
+	"compress/bzip2"
+	"fmt"
+	"io"
+	"math/rand"
+	"os"
+	"path/filepath"
+	"regexp/syntax"
+	"strconv"
+	"strings"
+	"testing"
+	"unicode/utf8"
+)
+
+// TestRE2 tests this package's regexp API against test cases
+// considered during RE2's exhaustive tests, which run all possible
+// regexps over a given set of atoms and operators, up to a given
+// complexity, over all possible strings over a given alphabet,
+// up to a given size.  Rather than try to link with RE2, we read a
+// log file containing the test cases and the expected matches.
+// The log file, re2.txt, is generated by running 'make exhaustive-log'
+// in the open source RE2 distribution.  http://code.google.com/p/re2/
+//
+// The test file format is a sequence of stanzas like:
+//
+//	strings
+//	"abc"
+//	"123x"
+//	regexps
+//	"[a-z]+"
+//	0-3;0-3
+//	-;-
+//	"([0-9])([0-9])([0-9])"
+//	-;-
+//	-;0-3 0-1 1-2 2-3
+//
+// The stanza begins by defining a set of strings, quoted
+// using Go double-quote syntax, one per line.  Then the
+// regexps section gives a sequence of regexps to run on
+// the strings.  In the block that follows a regexp, each line
+// gives the semicolon-separated match results of running
+// the regexp on the corresponding string.
+// Each match result is either a single -, meaning no match, or a
+// space-separated sequence of pairs giving the match and
+// submatch indices.  An unmatched subexpression formats
+// its pair as a single - (not illustrated above).  For now
+// each regexp run produces two match results, one for a
+// ``full match'' that restricts the regexp to matching the entire
+// string or nothing, and one for a ``partial match'' that gives
+// the leftmost first match found in the string.
+//
+// Lines beginning with # are comments.  Lines beginning with
+// a capital letter are test names printed during RE2's test suite
+// and are echoed into t but otherwise ignored.
+//
+// At time of writing, re2.txt is 32 MB but compresses to 760 kB,
+// so we store re2.txt.gz in the repository and decompress it on the fly.
+//
+func TestRE2Search(t *testing.T) {
+	testRE2(t, "testdata/re2-search.txt")
+}
+
+func TestRE2Exhaustive(t *testing.T) {
+	if testing.Short() {
+		t.Log("skipping TestRE2Exhaustive during short test")
+		return
+	}
+	testRE2(t, "testdata/re2-exhaustive.txt.bz2")
+}
+
+func testRE2(t *testing.T, file string) {
+	f, err := os.Open(file)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+	var txt io.Reader
+	if strings.HasSuffix(file, ".bz2") {
+		z := bzip2.NewReader(f)
+		txt = z
+		file = file[:len(file)-len(".bz2")] // for error messages
+	} else {
+		txt = f
+	}
+	lineno := 0
+	r := bufio.NewReader(txt)
+	var (
+		str       []string
+		input     []string
+		inStrings bool
+		re        *Regexp
+		refull    *Regexp
+		nfail     int
+		ncase     int
+	)
+	for {
+		line, err := r.ReadString('\n')
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			t.Fatalf("%s:%d: %v", file, lineno, err)
+		}
+		line = line[:len(line)-1] // chop \n
+		lineno++
+		switch {
+		case line == "":
+			t.Fatalf("%s:%d: unexpected blank line", file, lineno)
+		case line[0] == '#':
+			continue
+		case 'A' <= line[0] && line[0] <= 'Z':
+			// Test name.
+			t.Logf("%s\n", line)
+			continue
+		case line == "strings":
+			str = str[:0]
+			inStrings = true
+		case line == "regexps":
+			inStrings = false
+		case line[0] == '"':
+			q, err := strconv.Unquote(line)
+			if err != nil {
+				// Fatal because we'll get out of sync.
+				t.Fatalf("%s:%d: unquote %s: %v", file, lineno, line, err)
+			}
+			if inStrings {
+				str = append(str, q)
+				continue
+			}
+			// Is a regexp.
+			if len(input) != 0 {
+				t.Fatalf("%s:%d: out of sync: have %d strings left before %#q", file, lineno, len(input), q)
+			}
+			re, err = tryCompile(q)
+			if err != nil {
+				if err.Error() == "error parsing regexp: invalid escape sequence: `\\C`" {
+					// We don't and likely never will support \C; keep going.
+					continue
+				}
+				t.Errorf("%s:%d: compile %#q: %v", file, lineno, q, err)
+				if nfail++; nfail >= 100 {
+					t.Fatalf("stopping after %d errors", nfail)
+				}
+				continue
+			}
+			full := `\A(?:` + q + `)\z`
+			refull, err = tryCompile(full)
+			if err != nil {
+				// Fatal because q worked, so this should always work.
+				t.Fatalf("%s:%d: compile full %#q: %v", file, lineno, full, err)
+			}
+			input = str
+		case line[0] == '-' || '0' <= line[0] && line[0] <= '9':
+			// A sequence of match results.
+			ncase++
+			if re == nil {
+				// Failed to compile: skip results.
+				continue
+			}
+			if len(input) == 0 {
+				t.Fatalf("%s:%d: out of sync: no input remaining", file, lineno)
+			}
+			var text string
+			text, input = input[0], input[1:]
+			if !isSingleBytes(text) && strings.Contains(re.String(), `\B`) {
+				// RE2's \B considers every byte position,
+				// so it sees 'not word boundary' in the
+				// middle of UTF-8 sequences.  This package
+				// only considers the positions between runes,
+				// so it disagrees.  Skip those cases.
+				continue
+			}
+			res := strings.Split(line, ";")
+			if len(res) != len(run) {
+				t.Fatalf("%s:%d: have %d test results, want %d", file, lineno, len(res), len(run))
+			}
+			for i := range res {
+				have, suffix := run[i](re, refull, text)
+				want := parseResult(t, file, lineno, res[i])
+				if !same(have, want) {
+					t.Errorf("%s:%d: %#q%s.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, re, suffix, text, have, want)
+					if nfail++; nfail >= 100 {
+						t.Fatalf("stopping after %d errors", nfail)
+					}
+					continue
+				}
+				b, suffix := match[i](re, refull, text)
+				if b != (want != nil) {
+					t.Errorf("%s:%d: %#q%s.MatchString(%#q) = %v, want %v", file, lineno, re, suffix, text, b, !b)
+					if nfail++; nfail >= 100 {
+						t.Fatalf("stopping after %d errors", nfail)
+					}
+					continue
+				}
+			}
+
+		default:
+			t.Fatalf("%s:%d: out of sync: %s\n", file, lineno, line)
+		}
+	}
+	if len(input) != 0 {
+		t.Fatalf("%s:%d: out of sync: have %d strings left at EOF", file, lineno, len(input))
+	}
+	t.Logf("%d cases tested", ncase)
+}
+
+var run = []func(*Regexp, *Regexp, string) ([]int, string){
+	runFull,
+	runPartial,
+	runFullLongest,
+	runPartialLongest,
+}
+
+func runFull(re, refull *Regexp, text string) ([]int, string) {
+	refull.longest = false
+	return refull.FindStringSubmatchIndex(text), "[full]"
+}
+
+func runPartial(re, refull *Regexp, text string) ([]int, string) {
+	re.longest = false
+	return re.FindStringSubmatchIndex(text), ""
+}
+
+func runFullLongest(re, refull *Regexp, text string) ([]int, string) {
+	refull.longest = true
+	return refull.FindStringSubmatchIndex(text), "[full,longest]"
+}
+
+func runPartialLongest(re, refull *Regexp, text string) ([]int, string) {
+	re.longest = true
+	return re.FindStringSubmatchIndex(text), "[longest]"
+}
+
+var match = []func(*Regexp, *Regexp, string) (bool, string){
+	matchFull,
+	matchPartial,
+	matchFullLongest,
+	matchPartialLongest,
+}
+
+func matchFull(re, refull *Regexp, text string) (bool, string) {
+	refull.longest = false
+	return refull.MatchString(text), "[full]"
+}
+
+func matchPartial(re, refull *Regexp, text string) (bool, string) {
+	re.longest = false
+	return re.MatchString(text), ""
+}
+
+func matchFullLongest(re, refull *Regexp, text string) (bool, string) {
+	refull.longest = true
+	return refull.MatchString(text), "[full,longest]"
+}
+
+func matchPartialLongest(re, refull *Regexp, text string) (bool, string) {
+	re.longest = true
+	return re.MatchString(text), "[longest]"
+}
+
+func isSingleBytes(s string) bool {
+	for _, c := range s {
+		if c >= utf8.RuneSelf {
+			return false
+		}
+	}
+	return true
+}
+
+func tryCompile(s string) (re *Regexp, err error) {
+	// Protect against panic during Compile.
+	defer func() {
+		if r := recover(); r != nil {
+			err = fmt.Errorf("panic: %v", r)
+		}
+	}()
+	return Compile(s)
+}
+
+func parseResult(t *testing.T, file string, lineno int, res string) []int {
+	// A single - indicates no match.
+	if res == "-" {
+		return nil
+	}
+	// Otherwise, a space-separated list of pairs.
+	n := 1
+	for j := 0; j < len(res); j++ {
+		if res[j] == ' ' {
+			n++
+		}
+	}
+	out := make([]int, 2*n)
+	i := 0
+	n = 0
+	for j := 0; j <= len(res); j++ {
+		if j == len(res) || res[j] == ' ' {
+			// Process a single pair.  - means no submatch.
+			pair := res[i:j]
+			if pair == "-" {
+				out[n] = -1
+				out[n+1] = -1
+			} else {
+				k := strings.Index(pair, "-")
+				if k < 0 {
+					t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
+				}
+				lo, err1 := strconv.Atoi(pair[:k])
+				hi, err2 := strconv.Atoi(pair[k+1:])
+				if err1 != nil || err2 != nil || lo > hi {
+					t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
+				}
+				out[n] = lo
+				out[n+1] = hi
+			}
+			n += 2
+			i = j + 1
+		}
+	}
+	return out
+}
+
+func same(x, y []int) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, xi := range x {
+		if xi != y[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// TestFowler runs this package's regexp API against the
+// POSIX regular expression tests collected by Glenn Fowler
+// at http://www2.research.att.com/~gsf/testregex/.
+func TestFowler(t *testing.T) {
+	files, err := filepath.Glob("testdata/*.dat")
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, file := range files {
+		t.Log(file)
+		testFowler(t, file)
+	}
+}
+
+var notab = MustCompilePOSIX(`[^\t]+`)
+
+func testFowler(t *testing.T, file string) {
+	f, err := os.Open(file)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	defer f.Close()
+	b := bufio.NewReader(f)
+	lineno := 0
+	lastRegexp := ""
+Reading:
+	for {
+		lineno++
+		line, err := b.ReadString('\n')
+		if err != nil {
+			if err != io.EOF {
+				t.Errorf("%s:%d: %v", file, lineno, err)
+			}
+			break Reading
+		}
+
+		// http://www2.research.att.com/~gsf/man/man1/testregex.html
+		//
+		// INPUT FORMAT
+		//   Input lines may be blank, a comment beginning with #, or a test
+		//   specification. A specification is five fields separated by one
+		//   or more tabs. NULL denotes the empty string and NIL denotes the
+		//   0 pointer.
+		if line[0] == '#' || line[0] == '\n' {
+			continue Reading
+		}
+		line = line[:len(line)-1]
+		field := notab.FindAllString(line, -1)
+		for i, f := range field {
+			if f == "NULL" {
+				field[i] = ""
+			}
+			if f == "NIL" {
+				t.Logf("%s:%d: skip: %s", file, lineno, line)
+				continue Reading
+			}
+		}
+		if len(field) == 0 {
+			continue Reading
+		}
+
+		//   Field 1: the regex(3) flags to apply, one character per REG_feature
+		//   flag. The test is skipped if REG_feature is not supported by the
+		//   implementation. If the first character is not [BEASKLP] then the
+		//   specification is a global control line. One or more of [BEASKLP] may be
+		//   specified; the test will be repeated for each mode.
+		// 
+		//     B 	basic			BRE	(grep, ed, sed)
+		//     E 	REG_EXTENDED		ERE	(egrep)
+		//     A	REG_AUGMENTED		ARE	(egrep with negation)
+		//     S	REG_SHELL		SRE	(sh glob)
+		//     K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)
+		//     L	REG_LITERAL		LRE	(fgrep)
+		// 
+		//     a	REG_LEFT|REG_RIGHT	implicit ^...$
+		//     b	REG_NOTBOL		lhs does not match ^
+		//     c	REG_COMMENT		ignore space and #...\n
+		//     d	REG_SHELL_DOT		explicit leading . match
+		//     e	REG_NOTEOL		rhs does not match $
+		//     f	REG_MULTIPLE		multiple \n separated patterns
+		//     g	FNM_LEADING_DIR		testfnmatch only -- match until /
+		//     h	REG_MULTIREF		multiple digit backref
+		//     i	REG_ICASE		ignore case
+		//     j	REG_SPAN		. matches \n
+		//     k	REG_ESCAPE		\ to ecape [...] delimiter
+		//     l	REG_LEFT		implicit ^...
+		//     m	REG_MINIMAL		minimal match
+		//     n	REG_NEWLINE		explicit \n match
+		//     o	REG_ENCLOSED		(|&) magic inside [@|&](...)
+		//     p	REG_SHELL_PATH		explicit / match
+		//     q	REG_DELIMITED		delimited pattern
+		//     r	REG_RIGHT		implicit ...$
+		//     s	REG_SHELL_ESCAPED	\ not special
+		//     t	REG_MUSTDELIM		all delimiters must be specified
+		//     u	standard unspecified behavior -- errors not counted
+		//     v	REG_CLASS_ESCAPE	\ special inside [...]
+		//     w	REG_NOSUB		no subexpression match array
+		//     x	REG_LENIENT		let some errors slide
+		//     y	REG_LEFT		regexec() implicit ^...
+		//     z	REG_NULL		NULL subexpressions ok
+		//     $	                        expand C \c escapes in fields 2 and 3
+		//     /	                        field 2 is a regsubcomp() expression
+		//     =	                        field 3 is a regdecomp() expression
+		// 
+		//   Field 1 control lines:
+		// 
+		//     C		set LC_COLLATE and LC_CTYPE to locale in field 2
+		// 
+		//     ?test ...	output field 5 if passed and != EXPECTED, silent otherwise
+		//     &test ...	output field 5 if current and previous passed
+		//     |test ...	output field 5 if current passed and previous failed
+		//     ; ...	output field 2 if previous failed
+		//     {test ...	skip if failed until }
+		//     }		end of skip
+		// 
+		//     : comment		comment copied as output NOTE
+		//     :comment:test	:comment: ignored
+		//     N[OTE] comment	comment copied as output NOTE
+		//     T[EST] comment	comment
+		// 
+		//     number		use number for nmatch (20 by default)
+		flag := field[0]
+		switch flag[0] {
+		case '?', '&', '|', ';', '{', '}':
+			// Ignore all the control operators.
+			// Just run everything.
+			flag = flag[1:]
+			if flag == "" {
+				continue Reading
+			}
+		case ':':
+			i := strings.Index(flag[1:], ":")
+			if i < 0 {
+				t.Logf("skip: %s", line)
+				continue Reading
+			}
+			flag = flag[1+i+1:]
+		case 'C', 'N', 'T', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			t.Logf("skip: %s", line)
+			continue Reading
+		}
+
+		// Can check field count now that we've handled the myriad comment formats.
+		if len(field) < 4 {
+			t.Errorf("%s:%d: too few fields: %s", file, lineno, line)
+			continue Reading
+		}
+
+		// Expand C escapes (a.k.a. Go escapes).
+		if strings.Contains(flag, "$") {
+			f := `"` + field[1] + `"`
+			if field[1], err = strconv.Unquote(f); err != nil {
+				t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
+			}
+			f = `"` + field[2] + `"`
+			if field[2], err = strconv.Unquote(f); err != nil {
+				t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
+			}
+		}
+
+		//   Field 2: the regular expression pattern; SAME uses the pattern from
+		//     the previous specification.
+		// 
+		if field[1] == "SAME" {
+			field[1] = lastRegexp
+		}
+		lastRegexp = field[1]
+
+		//   Field 3: the string to match.
+		text := field[2]
+
+		//   Field 4: the test outcome...
+		ok, shouldCompile, shouldMatch, pos := parseFowlerResult(field[3])
+		if !ok {
+			t.Errorf("%s:%d: cannot parse result %#q", file, lineno, field[3])
+			continue Reading
+		}
+
+		//   Field 5: optional comment appended to the report.
+
+	Testing:
+		// Run test once for each specified capital letter mode that we support.
+		for _, c := range flag {
+			pattern := field[1]
+			syn := syntax.POSIX | syntax.ClassNL
+			switch c {
+			default:
+				continue Testing
+			case 'E':
+				// extended regexp (what we support)
+			case 'L':
+				// literal
+				pattern = QuoteMeta(pattern)
+			}
+
+			for _, c := range flag {
+				switch c {
+				case 'i':
+					syn |= syntax.FoldCase
+				}
+			}
+
+			re, err := compile(pattern, syn, true)
+			if err != nil {
+				if shouldCompile {
+					t.Errorf("%s:%d: %#q did not compile", file, lineno, pattern)
+				}
+				continue Testing
+			}
+			if !shouldCompile {
+				t.Errorf("%s:%d: %#q should not compile", file, lineno, pattern)
+				continue Testing
+			}
+			match := re.MatchString(text)
+			if match != shouldMatch {
+				t.Errorf("%s:%d: %#q.Match(%#q) = %v, want %v", file, lineno, pattern, text, match, shouldMatch)
+				continue Testing
+			}
+			have := re.FindStringSubmatchIndex(text)
+			if (len(have) > 0) != match {
+				t.Errorf("%s:%d: %#q.Match(%#q) = %v, but %#q.FindSubmatchIndex(%#q) = %v", file, lineno, pattern, text, match, pattern, text, have)
+				continue Testing
+			}
+			if len(have) > len(pos) {
+				have = have[:len(pos)]
+			}
+			if !same(have, pos) {
+				t.Errorf("%s:%d: %#q.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, pattern, text, have, pos)
+			}
+		}
+	}
+}
+
+func parseFowlerResult(s string) (ok, compiled, matched bool, pos []int) {
+	//   Field 4: the test outcome. This is either one of the posix error
+	//     codes (with REG_ omitted) or the match array, a list of (m,n)
+	//     entries with m and n being first and last+1 positions in the
+	//     field 3 string, or NULL if REG_NOSUB is in effect and success
+	//     is expected. BADPAT is acceptable in place of any regcomp(3)
+	//     error code. The match[] array is initialized to (-2,-2) before
+	//     each test. All array elements from 0 to nmatch-1 must be specified
+	//     in the outcome. Unspecified endpoints (offset -1) are denoted by ?.
+	//     Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a
+	//     matched (?{...}) expression, where x is the text enclosed by {...},
+	//     o is the expression ordinal counting from 1, and n is the length of
+	//     the unmatched portion of the subject string. If x starts with a
+	//     number then that is the return value of re_execf(), otherwise 0 is
+	//     returned.
+	switch {
+	case s == "":
+		// Match with no position information.
+		ok = true
+		compiled = true
+		matched = true
+		return
+	case s == "NOMATCH":
+		// Match failure.
+		ok = true
+		compiled = true
+		matched = false
+		return
+	case 'A' <= s[0] && s[0] <= 'Z':
+		// All the other error codes are compile errors.
+		ok = true
+		compiled = false
+		return
+	}
+	compiled = true
+
+	var x []int
+	for s != "" {
+		var end byte = ')'
+		if len(x)%2 == 0 {
+			if s[0] != '(' {
+				ok = false
+				return
+			}
+			s = s[1:]
+			end = ','
+		}
+		i := 0
+		for i < len(s) && s[i] != end {
+			i++
+		}
+		if i == 0 || i == len(s) {
+			ok = false
+			return
+		}
+		var v = -1
+		var err error
+		if s[:i] != "?" {
+			v, err = strconv.Atoi(s[:i])
+			if err != nil {
+				ok = false
+				return
+			}
+		}
+		x = append(x, v)
+		s = s[i+1:]
+	}
+	if len(x)%2 != 0 {
+		ok = false
+		return
+	}
+	ok = true
+	matched = true
+	pos = x
+	return
+}
+
+var text []byte
+
+func makeText(n int) []byte {
+	if len(text) >= n {
+		return text[:n]
+	}
+	text = make([]byte, n)
+	for i := range text {
+		if rand.Intn(30) == 0 {
+			text[i] = '\n'
+		} else {
+			text[i] = byte(rand.Intn(0x7E+1-0x20) + 0x20)
+		}
+	}
+	return text
+}
+
+func benchmark(b *testing.B, re string, n int) {
+	r := MustCompile(re)
+	t := makeText(n)
+	b.ResetTimer()
+	b.SetBytes(int64(n))
+	for i := 0; i < b.N; i++ {
+		if r.Match(t) {
+			b.Fatal("match!")
+		}
+	}
+}
+
+const (
+	easy0  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+	easy1  = "A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$"
+	medium = "[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+	hard   = "[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+	parens = "([ -~])*(A)(B)(C)(D)(E)(F)(G)(H)(I)(J)(K)(L)(M)" +
+		"(N)(O)(P)(Q)(R)(S)(T)(U)(V)(W)(X)(Y)(Z)$"
+)
+
+func BenchmarkMatchEasy0_32(b *testing.B)   { benchmark(b, easy0, 32<<0) }
+func BenchmarkMatchEasy0_1K(b *testing.B)   { benchmark(b, easy0, 1<<10) }
+func BenchmarkMatchEasy0_32K(b *testing.B)  { benchmark(b, easy0, 32<<10) }
+func BenchmarkMatchEasy0_1M(b *testing.B)   { benchmark(b, easy0, 1<<20) }
+func BenchmarkMatchEasy0_32M(b *testing.B)  { benchmark(b, easy0, 32<<20) }
+func BenchmarkMatchEasy1_32(b *testing.B)   { benchmark(b, easy1, 32<<0) }
+func BenchmarkMatchEasy1_1K(b *testing.B)   { benchmark(b, easy1, 1<<10) }
+func BenchmarkMatchEasy1_32K(b *testing.B)  { benchmark(b, easy1, 32<<10) }
+func BenchmarkMatchEasy1_1M(b *testing.B)   { benchmark(b, easy1, 1<<20) }
+func BenchmarkMatchEasy1_32M(b *testing.B)  { benchmark(b, easy1, 32<<20) }
+func BenchmarkMatchMedium_32(b *testing.B)  { benchmark(b, medium, 1<<0) }
+func BenchmarkMatchMedium_1K(b *testing.B)  { benchmark(b, medium, 1<<10) }
+func BenchmarkMatchMedium_32K(b *testing.B) { benchmark(b, medium, 32<<10) }
+func BenchmarkMatchMedium_1M(b *testing.B)  { benchmark(b, medium, 1<<20) }
+func BenchmarkMatchMedium_32M(b *testing.B) { benchmark(b, medium, 32<<20) }
+func BenchmarkMatchHard_32(b *testing.B)    { benchmark(b, hard, 32<<0) }
+func BenchmarkMatchHard_1K(b *testing.B)    { benchmark(b, hard, 1<<10) }
+func BenchmarkMatchHard_32K(b *testing.B)   { benchmark(b, hard, 32<<10) }
+func BenchmarkMatchHard_1M(b *testing.B)    { benchmark(b, hard, 1<<20) }
+func BenchmarkMatchHard_32M(b *testing.B)   { benchmark(b, hard, 32<<20) }
diff --git a/src/pkg/regexp/find_test.go b/src/pkg/regexp/find_test.go
index 83b249e..e07eb7d 100644
--- a/src/pkg/regexp/find_test.go
+++ b/src/pkg/regexp/find_test.go
@@ -58,8 +58,8 @@ var findTests = []FindTest{
 	{`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)},
 	{`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)},
 	{`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
-	{`\a\b\f\n\r\t\v`, "\a\b\f\n\r\t\v", build(1, 0, 7)},
-	{`[\a\b\f\n\r\t\v]+`, "\a\b\f\n\r\t\v", build(1, 0, 7)},
+	{`\a\f\n\r\t\v`, "\a\f\n\r\t\v", build(1, 0, 6)},
+	{`[\a\f\n\r\t\v]+`, "\a\f\n\r\t\v", build(1, 0, 6)},
 
 	{`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)},
 	{`(.*).*`, "ab", build(1, 0, 2, 0, 2)},
@@ -80,6 +80,32 @@ var findTests = []FindTest{
 	{`data`, "daXY data", build(1, 5, 9)},
 	{`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
 	{`zx+`, "zzx", build(1, 1, 3)},
+	{`ab$`, "abcab", build(1, 3, 5)},
+	{`(aa)*$`, "a", build(1, 1, 1, -1, -1)},
+	{`(?:.|(?:.a))`, "", nil},
+	{`(?:A(?:A|a))`, "Aa", build(1, 0, 2)},
+	{`(?:A|(?:A|a))`, "a", build(1, 0, 1)},
+	{`(a){0}`, "", build(1, 0, 0, -1, -1)},
+	{`(?-s)(?:(?:^).)`, "\n", nil},
+	{`(?s)(?:(?:^).)`, "\n", build(1, 0, 1)},
+	{`(?:(?:^).)`, "\n", nil},
+	{`\b`, "x", build(2, 0, 0, 1, 1)},
+	{`\b`, "xx", build(2, 0, 0, 2, 2)},
+	{`\b`, "x y", build(4, 0, 0, 1, 1, 2, 2, 3, 3)},
+	{`\b`, "xx yy", build(4, 0, 0, 2, 2, 3, 3, 5, 5)},
+	{`\B`, "x", nil},
+	{`\B`, "xx", build(1, 1, 1)},
+	{`\B`, "x y", nil},
+	{`\B`, "xx yy", build(2, 1, 1, 4, 4)},
+
+	// RE2 tests
+	{`[^\S\s]`, "abcd", nil},
+	{`[^\S[:space:]]`, "abcd", nil},
+	{`[^\D\d]`, "abcd", nil},
+	{`[^\D[:digit:]]`, "abcd", nil},
+	{`(?i)\W`, "x", nil},
+	{`(?i)\W`, "k", nil},
+	{`(?i)\W`, "s", nil},
 
 	// can backslash-escape any punctuation
 	{`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
@@ -209,7 +235,7 @@ func TestFindAll(t *testing.T) {
 		case test.matches == nil && result != nil:
 			t.Errorf("expected no match; got one: %s", test)
 		case test.matches != nil && result == nil:
-			t.Errorf("expected match; got none: %s", test)
+			t.Fatalf("expected match; got none: %s", test)
 		case test.matches != nil && result != nil:
 			if len(test.matches) != len(result) {
 				t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
diff --git a/src/pkg/regexp/regexp.go b/src/pkg/regexp/regexp.go
index e8d4c08..7aebd37 100644
--- a/src/pkg/regexp/regexp.go
+++ b/src/pkg/regexp/regexp.go
@@ -1,29 +1,15 @@
+// Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package regexp implements a simple regular expression library.
+// Package regexp implements regular expression search.
 //
-// The syntax of the regular expressions accepted is:
+// The syntax of the regular expressions accepted is the same
+// general syntax used by Perl, Python, and other languages.
+// More precisely, it is the syntax accepted by RE2 and described at
+// http://code.google.com/p/re2/wiki/Syntax, except for \C.
 //
-//	regexp:
-//		concatenation { '|' concatenation }
-//	concatenation:
-//		{ closure }
-//	closure:
-//		term [ '*' | '+' | '?' ]
-//	term:
-//		'^'
-//		'$'
-//		'.'
-//		character
-//		'[' [ '^' ] { character-range } ']'
-//		'(' regexp ')'
-//	character-range:
-//		character [ '-' character ]
-//
-// All characters are UTF-8-encoded code points.  Backslashes escape special
-// characters, including inside character classes.  The standard Go character
-// escapes are also recognized: \a \b \f \n \r \t \v.
+// All characters are UTF-8-encoded code points.
 //
 // There are 16 methods of Regexp that match a regular expression and identify
 // the matched text.  Their names are matched by this regular expression:
@@ -71,542 +57,34 @@ package regexp
 import (
 	"bytes"
 	"io"
-	"os"
+	"regexp/syntax"
+	"strconv"
 	"strings"
-	"utf8"
+	"sync"
+	"unicode/utf8"
 )
 
 var debug = false
 
-// Error is the local type for a parsing error.
-type Error string
-
-func (e Error) String() string {
-	return string(e)
-}
-
-// Error codes returned by failures to parse an expression.
-var (
-	ErrInternal            = Error("regexp: internal error")
-	ErrUnmatchedLpar       = Error("regexp: unmatched '('")
-	ErrUnmatchedRpar       = Error("regexp: unmatched ')'")
-	ErrUnmatchedLbkt       = Error("regexp: unmatched '['")
-	ErrUnmatchedRbkt       = Error("regexp: unmatched ']'")
-	ErrBadRange            = Error("regexp: bad range in character class")
-	ErrExtraneousBackslash = Error("regexp: extraneous backslash")
-	ErrBadClosure          = Error("regexp: repeated closure (**, ++, etc.)")
-	ErrBareClosure         = Error("regexp: closure applies to nothing")
-	ErrBadBackslash        = Error("regexp: illegal backslash escape")
-)
-
-const (
-	iStart     = iota // beginning of program
-	iEnd              // end of program: success
-	iBOT              // '^' beginning of text
-	iEOT              // '$' end of text
-	iChar             // 'a' regular character
-	iCharClass        // [a-z] character class
-	iAny              // '.' any character including newline
-	iNotNL            // [^\n] special case: any character but newline
-	iBra              // '(' parenthesized expression: 2*braNum for left, 2*braNum+1 for right
-	iAlt              // '|' alternation
-	iNop              // do nothing; makes it easy to link without patching
-)
-
-// An instruction executed by the NFA
-type instr struct {
-	kind  int    // the type of this instruction: iChar, iAny, etc.
-	index int    // used only in debugging; could be eliminated
-	next  *instr // the instruction to execute after this one
-	// Special fields valid only for some items.
-	char   int        // iChar
-	braNum int        // iBra, iEbra
-	cclass *charClass // iCharClass
-	left   *instr     // iAlt, other branch
-}
-
-func (i *instr) print() {
-	switch i.kind {
-	case iStart:
-		print("start")
-	case iEnd:
-		print("end")
-	case iBOT:
-		print("bot")
-	case iEOT:
-		print("eot")
-	case iChar:
-		print("char ", string(i.char))
-	case iCharClass:
-		i.cclass.print()
-	case iAny:
-		print("any")
-	case iNotNL:
-		print("notnl")
-	case iBra:
-		if i.braNum&1 == 0 {
-			print("bra", i.braNum/2)
-		} else {
-			print("ebra", i.braNum/2)
-		}
-	case iAlt:
-		print("alt(", i.left.index, ")")
-	case iNop:
-		print("nop")
-	}
-}
-
 // Regexp is the representation of a compiled regular expression.
 // The public interface is entirely through methods.
 // A Regexp is safe for concurrent use by multiple goroutines.
 type Regexp struct {
-	expr        string // the original expression
-	prefix      string // initial plain text string
-	prefixBytes []byte // initial plain text bytes
-	inst        []*instr
-	start       *instr // first instruction of machine
-	prefixStart *instr // where to start if there is a prefix
-	nbra        int    // number of brackets in expression, for subexpressions
-}
-
-type charClass struct {
-	negate bool // is character class negated? ([^a-z])
-	// slice of int, stored pairwise: [a-z] is (a,z); x is (x,x):
-	ranges     []int
-	cmin, cmax int
-}
-
-func (cclass *charClass) print() {
-	print("charclass")
-	if cclass.negate {
-		print(" (negated)")
-	}
-	for i := 0; i < len(cclass.ranges); i += 2 {
-		l := cclass.ranges[i]
-		r := cclass.ranges[i+1]
-		if l == r {
-			print(" [", string(l), "]")
-		} else {
-			print(" [", string(l), "-", string(r), "]")
-		}
-	}
-}
-
-func (cclass *charClass) addRange(a, b int) {
-	// range is a through b inclusive
-	cclass.ranges = append(cclass.ranges, a, b)
-	if a < cclass.cmin {
-		cclass.cmin = a
-	}
-	if b > cclass.cmax {
-		cclass.cmax = b
-	}
-}
-
-func (cclass *charClass) matches(c int) bool {
-	if c < cclass.cmin || c > cclass.cmax {
-		return cclass.negate
-	}
-	ranges := cclass.ranges
-	for i := 0; i < len(ranges); i = i + 2 {
-		if ranges[i] <= c && c <= ranges[i+1] {
-			return !cclass.negate
-		}
-	}
-	return cclass.negate
-}
-
-func newCharClass() *instr {
-	i := &instr{kind: iCharClass}
-	i.cclass = new(charClass)
-	i.cclass.ranges = make([]int, 0, 4)
-	i.cclass.cmin = 0x10FFFF + 1 // MaxRune + 1
-	i.cclass.cmax = -1
-	return i
-}
-
-func (re *Regexp) add(i *instr) *instr {
-	i.index = len(re.inst)
-	re.inst = append(re.inst, i)
-	return i
-}
-
-type parser struct {
-	re    *Regexp
-	nlpar int // number of unclosed lpars
-	pos   int
-	ch    int
-}
-
-func (p *parser) error(err Error) {
-	panic(err)
-}
-
-const endOfText = -1
-
-func (p *parser) c() int { return p.ch }
-
-func (p *parser) nextc() int {
-	if p.pos >= len(p.re.expr) {
-		p.ch = endOfText
-	} else {
-		c, w := utf8.DecodeRuneInString(p.re.expr[p.pos:])
-		p.ch = c
-		p.pos += w
-	}
-	return p.ch
-}
-
-func newParser(re *Regexp) *parser {
-	p := new(parser)
-	p.re = re
-	p.nextc() // load p.ch
-	return p
-}
-
-func special(c int) bool {
-	for _, r := range `\.+*?()|[]^$` {
-		if c == r {
-			return true
-		}
-	}
-	return false
-}
-
-func ispunct(c int) bool {
-	for _, r := range "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" {
-		if c == r {
-			return true
-		}
-	}
-	return false
-}
-
-var escapes = []byte("abfnrtv")
-var escaped = []byte("\a\b\f\n\r\t\v")
-
-func escape(c int) int {
-	for i, b := range escapes {
-		if int(b) == c {
-			return i
-		}
-	}
-	return -1
-}
-
-func (p *parser) checkBackslash() int {
-	c := p.c()
-	if c == '\\' {
-		c = p.nextc()
-		switch {
-		case c == endOfText:
-			p.error(ErrExtraneousBackslash)
-		case ispunct(c):
-			// c is as delivered
-		case escape(c) >= 0:
-			c = int(escaped[escape(c)])
-		default:
-			p.error(ErrBadBackslash)
-		}
-	}
-	return c
-}
-
-func (p *parser) charClass() *instr {
-	i := newCharClass()
-	cc := i.cclass
-	if p.c() == '^' {
-		cc.negate = true
-		p.nextc()
-	}
-	left := -1
-	for {
-		switch c := p.c(); c {
-		case ']', endOfText:
-			if left >= 0 {
-				p.error(ErrBadRange)
-			}
-			// Is it [^\n]?
-			if cc.negate && len(cc.ranges) == 2 &&
-				cc.ranges[0] == '\n' && cc.ranges[1] == '\n' {
-				nl := &instr{kind: iNotNL}
-				p.re.add(nl)
-				return nl
-			}
-			// Special common case: "[a]" -> "a"
-			if !cc.negate && len(cc.ranges) == 2 && cc.ranges[0] == cc.ranges[1] {
-				c := &instr{kind: iChar, char: cc.ranges[0]}
-				p.re.add(c)
-				return c
-			}
-			p.re.add(i)
-			return i
-		case '-': // do this before backslash processing
-			p.error(ErrBadRange)
-		default:
-			c = p.checkBackslash()
-			p.nextc()
-			switch {
-			case left < 0: // first of pair
-				if p.c() == '-' { // range
-					p.nextc()
-					left = c
-				} else { // single char
-					cc.addRange(c, c)
-				}
-			case left <= c: // second of pair
-				cc.addRange(left, c)
-				left = -1
-			default:
-				p.error(ErrBadRange)
-			}
-		}
-	}
-	panic("unreachable")
-}
-
-func (p *parser) term() (start, end *instr) {
-	switch c := p.c(); c {
-	case '|', endOfText:
-		return nil, nil
-	case '*', '+', '?':
-		p.error(ErrBareClosure)
-	case ')':
-		if p.nlpar == 0 {
-			p.error(ErrUnmatchedRpar)
-		}
-		return nil, nil
-	case ']':
-		p.error(ErrUnmatchedRbkt)
-	case '^':
-		p.nextc()
-		start = p.re.add(&instr{kind: iBOT})
-		return start, start
-	case '$':
-		p.nextc()
-		start = p.re.add(&instr{kind: iEOT})
-		return start, start
-	case '.':
-		p.nextc()
-		start = p.re.add(&instr{kind: iAny})
-		return start, start
-	case '[':
-		p.nextc()
-		start = p.charClass()
-		if p.c() != ']' {
-			p.error(ErrUnmatchedLbkt)
-		}
-		p.nextc()
-		return start, start
-	case '(':
-		p.nextc()
-		p.nlpar++
-		p.re.nbra++ // increment first so first subexpr is \1
-		nbra := p.re.nbra
-		start, end = p.regexp()
-		if p.c() != ')' {
-			p.error(ErrUnmatchedLpar)
-		}
-		p.nlpar--
-		p.nextc()
-		bra := &instr{kind: iBra, braNum: 2 * nbra}
-		p.re.add(bra)
-		ebra := &instr{kind: iBra, braNum: 2*nbra + 1}
-		p.re.add(ebra)
-		if start == nil {
-			if end == nil {
-				p.error(ErrInternal)
-				return
-			}
-			start = ebra
-		} else {
-			end.next = ebra
-		}
-		bra.next = start
-		return bra, ebra
-	default:
-		c = p.checkBackslash()
-		p.nextc()
-		start = &instr{kind: iChar, char: c}
-		p.re.add(start)
-		return start, start
-	}
-	panic("unreachable")
-}
-
-func (p *parser) closure() (start, end *instr) {
-	start, end = p.term()
-	if start == nil {
-		return
-	}
-	switch p.c() {
-	case '*':
-		// (start,end)*:
-		alt := &instr{kind: iAlt}
-		p.re.add(alt)
-		end.next = alt   // after end, do alt
-		alt.left = start // alternate brach: return to start
-		start = alt      // alt becomes new (start, end)
-		end = alt
-	case '+':
-		// (start,end)+:
-		alt := &instr{kind: iAlt}
-		p.re.add(alt)
-		end.next = alt   // after end, do alt
-		alt.left = start // alternate brach: return to start
-		end = alt        // start is unchanged; end is alt
-	case '?':
-		// (start,end)?:
-		alt := &instr{kind: iAlt}
-		p.re.add(alt)
-		nop := &instr{kind: iNop}
-		p.re.add(nop)
-		alt.left = start // alternate branch is start
-		alt.next = nop   // follow on to nop
-		end.next = nop   // after end, go to nop
-		start = alt      // start is now alt
-		end = nop        // end is nop pointed to by both branches
-	default:
-		return
-	}
-	switch p.nextc() {
-	case '*', '+', '?':
-		p.error(ErrBadClosure)
-	}
-	return
-}
-
-func (p *parser) concatenation() (start, end *instr) {
-	for {
-		nstart, nend := p.closure()
-		switch {
-		case nstart == nil: // end of this concatenation
-			if start == nil { // this is the empty string
-				nop := p.re.add(&instr{kind: iNop})
-				return nop, nop
-			}
-			return
-		case start == nil: // this is first element of concatenation
-			start, end = nstart, nend
-		default:
-			end.next = nstart
-			end = nend
-		}
-	}
-	panic("unreachable")
-}
-
-func (p *parser) regexp() (start, end *instr) {
-	start, end = p.concatenation()
-	for {
-		switch p.c() {
-		default:
-			return
-		case '|':
-			p.nextc()
-			nstart, nend := p.concatenation()
-			alt := &instr{kind: iAlt}
-			p.re.add(alt)
-			alt.left = start
-			alt.next = nstart
-			nop := &instr{kind: iNop}
-			p.re.add(nop)
-			end.next = nop
-			nend.next = nop
-			start, end = alt, nop
-		}
-	}
-	panic("unreachable")
-}
-
-func unNop(i *instr) *instr {
-	for i.kind == iNop {
-		i = i.next
-	}
-	return i
-}
-
-func (re *Regexp) eliminateNops() {
-	for _, inst := range re.inst {
-		if inst.kind == iEnd {
-			continue
-		}
-		inst.next = unNop(inst.next)
-		if inst.kind == iAlt {
-			inst.left = unNop(inst.left)
-		}
-	}
-}
-
-func (re *Regexp) dump() {
-	print("prefix <", re.prefix, ">\n")
-	for _, inst := range re.inst {
-		print(inst.index, ": ")
-		inst.print()
-		if inst.kind != iEnd {
-			print(" -> ", inst.next.index)
-		}
-		print("\n")
-	}
-}
-
-func (re *Regexp) doParse() {
-	p := newParser(re)
-	start := &instr{kind: iStart}
-	re.add(start)
-	s, e := p.regexp()
-	start.next = s
-	re.start = start
-	e.next = re.add(&instr{kind: iEnd})
-
-	if debug {
-		re.dump()
-		println()
-	}
-
-	re.eliminateNops()
-	if debug {
-		re.dump()
-		println()
-	}
-	re.setPrefix()
-	if debug {
-		re.dump()
-		println()
-	}
-}
-
-// Extract regular text from the beginning of the pattern,
-// possibly after a leading iBOT.
-// That text can be used by doExecute to speed up matching.
-func (re *Regexp) setPrefix() {
-	var b []byte
-	var utf = make([]byte, utf8.UTFMax)
-	var inst *instr
-	// First instruction is start; skip that.  Also skip any initial iBOT.
-	inst = re.inst[0].next
-	for inst.kind == iBOT {
-		inst = inst.next
-	}
-Loop:
-	for ; inst.kind != iEnd; inst = inst.next {
-		// stop if this is not a char
-		if inst.kind != iChar {
-			break
-		}
-		// stop if this char can be followed by a match for an empty string,
-		// which includes closures, ^, and $.
-		switch inst.next.kind {
-		case iBOT, iEOT, iAlt:
-			break Loop
-		}
-		n := utf8.EncodeRune(utf, inst.char)
-		b = append(b, utf[0:n]...)
-	}
-	// point prefixStart instruction to first non-CHAR after prefix
-	re.prefixStart = inst
-	re.prefixBytes = b
-	re.prefix = string(b)
+	// read-only after Compile
+	expr           string         // as passed to Compile
+	prog           *syntax.Prog   // compiled program
+	prefix         string         // required prefix in unanchored matches
+	prefixBytes    []byte         // prefix, as a []byte
+	prefixComplete bool           // prefix is the entire regexp
+	prefixRune     rune           // first rune in prefix
+	cond           syntax.EmptyOp // empty-width conditions required at start of match
+	numSubexp      int
+	subexpNames    []string
+	longest        bool
+
+	// cache of machines for running regexp
+	mu      sync.Mutex
+	machine []*machine
 }
 
 // String returns the source text used to compile the regular expression.
@@ -614,21 +92,99 @@ func (re *Regexp) String() string {
 	return re.expr
 }
 
-// Compile parses a regular expression and returns, if successful, a Regexp
-// object that can be used to match against text.
-func Compile(str string) (regexp *Regexp, error os.Error) {
-	regexp = new(Regexp)
-	// doParse will panic if there is a parse error.
-	defer func() {
-		if e := recover(); e != nil {
-			regexp = nil
-			error = e.(Error) // Will re-panic if error was not an Error, e.g. nil-pointer exception
-		}
-	}()
-	regexp.expr = str
-	regexp.inst = make([]*instr, 0, 10)
-	regexp.doParse()
-	return
+// Compile parses a regular expression and returns, if successful,
+// a Regexp object that can be used to match against text.
+//
+// When matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses the one that a backtracking search would have found first.
+// This so-called leftmost-first matching is the same semantics
+// that Perl, Python, and other implementations use, although this
+// package implements it without the expense of backtracking.
+// For POSIX leftmost-longest matching, see CompilePOSIX.
+func Compile(expr string) (*Regexp, error) {
+	return compile(expr, syntax.Perl, false)
+}
+
+// CompilePOSIX is like Compile but restricts the regular expression
+// to POSIX ERE (egrep) syntax and changes the match semantics to
+// leftmost-longest.
+//
+// That is, when matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses a match that is as long as possible.
+// This so-called leftmost-longest matching is the same semantics
+// that early regular expression implementations used and that POSIX
+// specifies.
+//
+// However, there can be multiple leftmost-longest matches, with different
+// submatch choices, and here this package diverges from POSIX.
+// Among the possible leftmost-longest matches, this package chooses
+// the one that a backtracking search would have found first, while POSIX
+// specifies that the match be chosen to maximize the length of the first
+// subexpression, then the second, and so on from left to right.
+// The POSIX rule is computationally prohibitive and not even well-defined.
+// See http://swtch.com/~rsc/regexp/regexp2.html#posix for details.
+func CompilePOSIX(expr string) (*Regexp, error) {
+	return compile(expr, syntax.POSIX, true)
+}
+
+func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, error) {
+	re, err := syntax.Parse(expr, mode)
+	if err != nil {
+		return nil, err
+	}
+	maxCap := re.MaxCap()
+	capNames := re.CapNames()
+
+	re = re.Simplify()
+	prog, err := syntax.Compile(re)
+	if err != nil {
+		return nil, err
+	}
+	regexp := &Regexp{
+		expr:        expr,
+		prog:        prog,
+		numSubexp:   maxCap,
+		subexpNames: capNames,
+		cond:        prog.StartCond(),
+		longest:     longest,
+	}
+	regexp.prefix, regexp.prefixComplete = prog.Prefix()
+	if regexp.prefix != "" {
+		// TODO(rsc): Remove this allocation by adding
+		// IndexString to package bytes.
+		regexp.prefixBytes = []byte(regexp.prefix)
+		regexp.prefixRune, _ = utf8.DecodeRuneInString(regexp.prefix)
+	}
+	return regexp, nil
+}
+
+// get returns a machine to use for matching re.
+// It uses the re's machine cache if possible, to avoid
+// unnecessary allocation.
+func (re *Regexp) get() *machine {
+	re.mu.Lock()
+	if n := len(re.machine); n > 0 {
+		z := re.machine[n-1]
+		re.machine = re.machine[:n-1]
+		re.mu.Unlock()
+		return z
+	}
+	re.mu.Unlock()
+	z := progMachine(re.prog)
+	z.re = re
+	return z
+}
+
+// put returns a machine to the re's machine cache.
+// There is no attempt to limit the size of the cache, so it will
+// grow to the maximum number of simultaneous matches
+// run using re.  (The cache empties when re gets garbage collected.)
+func (re *Regexp) put(z *machine) {
+	re.mu.Lock()
+	re.machine = append(re.machine, z)
+	re.mu.Unlock()
 }
 
 // MustCompile is like Compile but panics if the expression cannot be parsed.
@@ -637,124 +193,53 @@ func Compile(str string) (regexp *Regexp, error os.Error) {
 func MustCompile(str string) *Regexp {
 	regexp, error := Compile(str)
 	if error != nil {
-		panic(`regexp: compiling "` + str + `": ` + error.String())
+		panic(`regexp: Compile(` + quote(str) + `): ` + error.Error())
 	}
 	return regexp
 }
 
-// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
-func (re *Regexp) NumSubexp() int { return re.nbra }
-
-// The match arena allows us to reduce the garbage generated by tossing
-// match vectors away as we execute.  Matches are ref counted and returned
-// to a free list when no longer active.  Increases a simple benchmark by 22X.
-type matchArena struct {
-	head  *matchVec
-	len   int // length of match vector
-	pos   int
-	atBOT bool // whether we're at beginning of text
-	atEOT bool // whether we're at end of text
-}
-
-type matchVec struct {
-	m    []int // pairs of bracketing submatches. 0th is start,end
-	ref  int
-	next *matchVec
-}
-
-func (a *matchArena) new() *matchVec {
-	if a.head == nil {
-		const N = 10
-		block := make([]matchVec, N)
-		for i := 0; i < N; i++ {
-			b := &block[i]
-			b.next = a.head
-			a.head = b
-		}
-	}
-	m := a.head
-	a.head = m.next
-	m.ref = 0
-	if m.m == nil {
-		m.m = make([]int, a.len)
+// MustCompilePOSIX is like CompilePOSIX but panics if the expression cannot be parsed.
+// It simplifies safe initialization of global variables holding compiled regular
+// expressions.
+func MustCompilePOSIX(str string) *Regexp {
+	regexp, error := CompilePOSIX(str)
+	if error != nil {
+		panic(`regexp: CompilePOSIX(` + quote(str) + `): ` + error.Error())
 	}
-	return m
+	return regexp
 }
 
-func (a *matchArena) free(m *matchVec) {
-	m.ref--
-	if m.ref == 0 {
-		m.next = a.head
-		a.head = m
+func quote(s string) string {
+	if strconv.CanBackquote(s) {
+		return "`" + s + "`"
 	}
+	return strconv.Quote(s)
 }
 
-func (a *matchArena) copy(m *matchVec) *matchVec {
-	m1 := a.new()
-	copy(m1.m, m.m)
-	return m1
-}
-
-func (a *matchArena) noMatch() *matchVec {
-	m := a.new()
-	for i := range m.m {
-		m.m[i] = -1 // no match seen; catches cases like "a(b)?c" on "ac"
-	}
-	m.ref = 1
-	return m
+// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
+func (re *Regexp) NumSubexp() int {
+	return re.numSubexp
 }
 
-type state struct {
-	inst     *instr // next instruction to execute
-	prefixed bool   // this match began with a fixed prefix
-	match    *matchVec
+// SubexpNames returns the names of the parenthesized subexpressions
+// in this Regexp.  The name for the first sub-expression is names[1],
+// so that if m is a match slice, the name for m[i] is SubexpNames()[i].
+// Since the Regexp as a whole cannot be named, names[0] is always
+// the empty string.  The slice should not be modified.
+func (re *Regexp) SubexpNames() []string {
+	return re.subexpNames
 }
 
-// Append new state to to-do list.  Leftmost-longest wins so avoid
-// adding a state that's already active.  The matchVec will be inc-ref'ed
-// if it is assigned to a state.
-func (a *matchArena) addState(s []state, inst *instr, prefixed bool, match *matchVec) []state {
-	switch inst.kind {
-	case iBOT:
-		if a.atBOT {
-			s = a.addState(s, inst.next, prefixed, match)
-		}
-		return s
-	case iEOT:
-		if a.atEOT {
-			s = a.addState(s, inst.next, prefixed, match)
-		}
-		return s
-	case iBra:
-		match.m[inst.braNum] = a.pos
-		s = a.addState(s, inst.next, prefixed, match)
-		return s
-	}
-	l := len(s)
-	// States are inserted in order so it's sufficient to see if we have the same
-	// instruction; no need to see if existing match is earlier (it is).
-	for i := 0; i < l; i++ {
-		if s[i].inst == inst {
-			return s
-		}
-	}
-	s = append(s, state{inst, prefixed, match})
-	match.ref++
-	if inst.kind == iAlt {
-		s = a.addState(s, inst.left, prefixed, a.copy(match))
-		// give other branch a copy of this match vector
-		s = a.addState(s, inst.next, prefixed, a.copy(match))
-	}
-	return s
-}
+const endOfText rune = -1
 
 // input abstracts different representations of the input text. It provides
 // one-character lookahead.
 type input interface {
-	step(pos int) (rune int, width int) // advance one rune
-	canCheckPrefix() bool               // can we look ahead without losing info?
+	step(pos int) (r rune, width int) // advance one rune
+	canCheckPrefix() bool             // can we look ahead without losing info?
 	hasPrefix(re *Regexp) bool
 	index(re *Regexp, pos int) int
+	context(pos int) syntax.EmptyOp
 }
 
 // inputString scans a string.
@@ -762,13 +247,13 @@ type inputString struct {
 	str string
 }
 
-func newInputString(str string) *inputString {
-	return &inputString{str: str}
-}
-
-func (i *inputString) step(pos int) (int, int) {
+func (i *inputString) step(pos int) (rune, int) {
 	if pos < len(i.str) {
-		return utf8.DecodeRuneInString(i.str[pos:len(i.str)])
+		c := i.str[pos]
+		if c < utf8.RuneSelf {
+			return rune(c), 1
+		}
+		return utf8.DecodeRuneInString(i.str[pos:])
 	}
 	return endOfText, 0
 }
@@ -785,18 +270,29 @@ func (i *inputString) index(re *Regexp, pos int) int {
 	return strings.Index(i.str[pos:], re.prefix)
 }
 
+func (i *inputString) context(pos int) syntax.EmptyOp {
+	r1, r2 := endOfText, endOfText
+	if pos > 0 && pos <= len(i.str) {
+		r1, _ = utf8.DecodeLastRuneInString(i.str[:pos])
+	}
+	if pos < len(i.str) {
+		r2, _ = utf8.DecodeRuneInString(i.str[pos:])
+	}
+	return syntax.EmptyOpContext(r1, r2)
+}
+
 // inputBytes scans a byte slice.
 type inputBytes struct {
 	str []byte
 }
 
-func newInputBytes(str []byte) *inputBytes {
-	return &inputBytes{str: str}
-}
-
-func (i *inputBytes) step(pos int) (int, int) {
+func (i *inputBytes) step(pos int) (rune, int) {
 	if pos < len(i.str) {
-		return utf8.DecodeRune(i.str[pos:len(i.str)])
+		c := i.str[pos]
+		if c < utf8.RuneSelf {
+			return rune(c), 1
+		}
+		return utf8.DecodeRune(i.str[pos:])
 	}
 	return endOfText, 0
 }
@@ -813,6 +309,17 @@ func (i *inputBytes) index(re *Regexp, pos int) int {
 	return bytes.Index(i.str[pos:], re.prefixBytes)
 }
 
+func (i *inputBytes) context(pos int) syntax.EmptyOp {
+	r1, r2 := endOfText, endOfText
+	if pos > 0 && pos <= len(i.str) {
+		r1, _ = utf8.DecodeLastRune(i.str[:pos])
+	}
+	if pos < len(i.str) {
+		r2, _ = utf8.DecodeRune(i.str[pos:])
+	}
+	return syntax.EmptyOpContext(r1, r2)
+}
+
 // inputReader scans a RuneReader.
 type inputReader struct {
 	r     io.RuneReader
@@ -820,11 +327,7 @@ type inputReader struct {
 	pos   int
 }
 
-func newInputReader(r io.RuneReader) *inputReader {
-	return &inputReader{r: r}
-}
-
-func (i *inputReader) step(pos int) (int, int) {
+func (i *inputReader) step(pos int) (rune, int) {
 	if !i.atEOT && pos != i.pos {
 		return endOfText, 0
 
@@ -850,155 +353,40 @@ func (i *inputReader) index(re *Regexp, pos int) int {
 	return -1
 }
 
-// Search match starting from pos bytes into the input.
-func (re *Regexp) doExecute(i input, pos int) []int {
-	var s [2][]state
-	s[0] = make([]state, 0, 10)
-	s[1] = make([]state, 0, 10)
-	in, out := 0, 1
-	var final state
-	found := false
-	anchored := re.inst[0].next.kind == iBOT
-	if anchored && pos > 0 {
-		return nil
-	}
-	// fast check for initial plain substring
-	if i.canCheckPrefix() && re.prefix != "" {
-		advance := 0
-		if anchored {
-			if !i.hasPrefix(re) {
-				return nil
-			}
-		} else {
-			advance = i.index(re, pos)
-			if advance == -1 {
-				return nil
-			}
-		}
-		pos += advance
-	}
-	// We look one character ahead so we can match $, which checks whether
-	// we are at EOT.
-	nextChar, nextWidth := i.step(pos)
-	arena := &matchArena{
-		len:   2 * (re.nbra + 1),
-		pos:   pos,
-		atBOT: pos == 0,
-		atEOT: nextChar == endOfText,
-	}
-	for c, startPos := 0, pos; c != endOfText; {
-		if !found && (pos == startPos || !anchored) {
-			// prime the pump if we haven't seen a match yet
-			match := arena.noMatch()
-			match.m[0] = pos
-			s[out] = arena.addState(s[out], re.start.next, false, match)
-			arena.free(match) // if addState saved it, ref was incremented
-		} else if len(s[out]) == 0 {
-			// machine has completed
-			break
-		}
-		in, out = out, in // old out state is new in state
-		// clear out old state
-		old := s[out]
-		for _, state := range old {
-			arena.free(state.match)
-		}
-		s[out] = old[0:0] // truncate state vector
-		c = nextChar
-		thisPos := pos
-		pos += nextWidth
-		nextChar, nextWidth = i.step(pos)
-		arena.atEOT = nextChar == endOfText
-		arena.atBOT = false
-		arena.pos = pos
-		for _, st := range s[in] {
-			switch st.inst.kind {
-			case iBOT:
-			case iEOT:
-			case iChar:
-				if c == st.inst.char {
-					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
-				}
-			case iCharClass:
-				if st.inst.cclass.matches(c) {
-					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
-				}
-			case iAny:
-				if c != endOfText {
-					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
-				}
-			case iNotNL:
-				if c != endOfText && c != '\n' {
-					s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
-				}
-			case iBra:
-			case iAlt:
-			case iEnd:
-				// choose leftmost longest
-				if !found || // first
-					st.match.m[0] < final.match.m[0] || // leftmost
-					(st.match.m[0] == final.match.m[0] && thisPos > final.match.m[1]) { // longest
-					if final.match != nil {
-						arena.free(final.match)
-					}
-					final = st
-					final.match.ref++
-					final.match.m[1] = thisPos
-				}
-				found = true
-			default:
-				st.inst.print()
-				panic("unknown instruction in execute")
-			}
-		}
-	}
-	if final.match == nil {
-		return nil
-	}
-	// if match found, back up start of match by width of prefix.
-	if final.prefixed && len(final.match.m) > 0 {
-		final.match.m[0] -= len(re.prefix)
-	}
-	return final.match.m
+func (i *inputReader) context(pos int) syntax.EmptyOp {
+	return 0
 }
 
 // LiteralPrefix returns a literal string that must begin any match
 // of the regular expression re.  It returns the boolean true if the
 // literal string comprises the entire regular expression.
 func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
-	c := make([]int, len(re.inst)-2) // minus start and end.
-	// First instruction is start; skip that.
-	i := 0
-	for inst := re.inst[0].next; inst.kind != iEnd; inst = inst.next {
-		// stop if this is not a char
-		if inst.kind != iChar {
-			return string(c[:i]), false
-		}
-		c[i] = inst.char
-		i++
-	}
-	return string(c[:i]), true
+	return re.prefix, re.prefixComplete
 }
 
 // MatchReader returns whether the Regexp matches the text read by the
 // RuneReader.  The return value is a boolean: true for match, false for no
 // match.
 func (re *Regexp) MatchReader(r io.RuneReader) bool {
-	return len(re.doExecute(newInputReader(r), 0)) > 0
+	return re.doExecute(r, nil, "", 0, 0) != nil
 }
 
 // MatchString returns whether the Regexp matches the string s.
 // The return value is a boolean: true for match, false for no match.
-func (re *Regexp) MatchString(s string) bool { return len(re.doExecute(newInputString(s), 0)) > 0 }
+func (re *Regexp) MatchString(s string) bool {
+	return re.doExecute(nil, nil, s, 0, 0) != nil
+}
 
 // Match returns whether the Regexp matches the byte slice b.
 // The return value is a boolean: true for match, false for no match.
-func (re *Regexp) Match(b []byte) bool { return len(re.doExecute(newInputBytes(b), 0)) > 0 }
+func (re *Regexp) Match(b []byte) bool {
+	return re.doExecute(nil, b, "", 0, 0) != nil
+}
 
 // MatchReader checks whether a textual regular expression matches the text
 // read by the RuneReader.  More complicated queries need to use Compile and
 // the full Regexp interface.
-func MatchReader(pattern string, r io.RuneReader) (matched bool, error os.Error) {
+func MatchReader(pattern string, r io.RuneReader) (matched bool, error error) {
 	re, err := Compile(pattern)
 	if err != nil {
 		return false, err
@@ -1009,7 +397,7 @@ func MatchReader(pattern string, r io.RuneReader) (matched bool, error os.Error)
 // MatchString checks whether a textual regular expression
 // matches a string.  More complicated queries need
 // to use Compile and the full Regexp interface.
-func MatchString(pattern string, s string) (matched bool, error os.Error) {
+func MatchString(pattern string, s string) (matched bool, error error) {
 	re, err := Compile(pattern)
 	if err != nil {
 		return false, err
@@ -1020,7 +408,7 @@ func MatchString(pattern string, s string) (matched bool, error os.Error) {
 // Match checks whether a textual regular expression
 // matches a byte slice.  More complicated queries need
 // to use Compile and the full Regexp interface.
-func Match(pattern string, b []byte) (matched bool, error os.Error) {
+func Match(pattern string, b []byte) (matched bool, error error) {
 	re, err := Compile(pattern)
 	if err != nil {
 		return false, err
@@ -1044,7 +432,7 @@ func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) str
 	searchPos := 0    // position where we next look for a match
 	buf := new(bytes.Buffer)
 	for searchPos <= len(src) {
-		a := re.doExecute(newInputString(src), searchPos)
+		a := re.doExecute(nil, nil, src, searchPos, 2)
 		if len(a) == 0 {
 			break // no more matches
 		}
@@ -1096,7 +484,7 @@ func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
 	searchPos := 0    // position where we next look for a match
 	buf := new(bytes.Buffer)
 	for searchPos <= len(src) {
-		a := re.doExecute(newInputBytes(src), searchPos)
+		a := re.doExecute(nil, src, "", searchPos, 2)
 		if len(a) == 0 {
 			break // no more matches
 		}
@@ -1132,6 +520,12 @@ func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
 	return buf.Bytes()
 }
 
+var specialBytes = []byte(`\.+*?()|[]{}^$`)
+
+func special(b byte) bool {
+	return bytes.IndexByte(specialBytes, b) >= 0
+}
+
 // QuoteMeta returns a string that quotes all regular expression metacharacters
 // inside the argument text; the returned string is a regular expression matching
 // the literal text.  For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
@@ -1141,7 +535,7 @@ func QuoteMeta(s string) string {
 	// A byte loop is correct because all metacharacters are ASCII.
 	j := 0
 	for i := 0; i < len(s); i++ {
-		if special(int(s[i])) {
+		if special(s[i]) {
 			b[j] = '\\'
 			j++
 		}
@@ -1151,6 +545,23 @@ func QuoteMeta(s string) string {
 	return string(b[0:j])
 }
 
+// The number of capture values in the program may correspond
+// to fewer capturing expressions than are in the regexp.
+// For example, "(a){0}" turns into an empty program, so the
+// maximum capture in the program is 0 but we need to return
+// an expression for \1.  Pad appends -1s to the slice a as needed.
+func (re *Regexp) pad(a []int) []int {
+	if a == nil {
+		// No match.
+		return nil
+	}
+	n := (1 + re.numSubexp) * 2
+	for len(a) < n {
+		a = append(a, -1)
+	}
+	return a
+}
+
 // Find matches in slice b if b is non-nil, otherwise find matches in string s.
 func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
 	var end int
@@ -1161,13 +572,7 @@ func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
 	}
 
 	for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
-		var in input
-		if b == nil {
-			in = newInputString(s)
-		} else {
-			in = newInputBytes(b)
-		}
-		matches := re.doExecute(in, pos)
+		matches := re.doExecute(nil, b, s, pos, re.prog.NumCap)
 		if len(matches) == 0 {
 			break
 		}
@@ -1198,7 +603,7 @@ func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
 		prevMatchEnd = matches[1]
 
 		if accept {
-			deliver(matches)
+			deliver(re.pad(matches))
 			i++
 		}
 	}
@@ -1207,7 +612,7 @@ func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
 // Find returns a slice holding the text of the leftmost match in b of the regular expression.
 // A return value of nil indicates no match.
 func (re *Regexp) Find(b []byte) []byte {
-	a := re.doExecute(newInputBytes(b), 0)
+	a := re.doExecute(nil, b, "", 0, 2)
 	if a == nil {
 		return nil
 	}
@@ -1219,7 +624,7 @@ func (re *Regexp) Find(b []byte) []byte {
 // b[loc[0]:loc[1]].
 // A return value of nil indicates no match.
 func (re *Regexp) FindIndex(b []byte) (loc []int) {
-	a := re.doExecute(newInputBytes(b), 0)
+	a := re.doExecute(nil, b, "", 0, 2)
 	if a == nil {
 		return nil
 	}
@@ -1232,7 +637,7 @@ func (re *Regexp) FindIndex(b []byte) (loc []int) {
 // an empty string.  Use FindStringIndex or FindStringSubmatch if it is
 // necessary to distinguish these cases.
 func (re *Regexp) FindString(s string) string {
-	a := re.doExecute(newInputString(s), 0)
+	a := re.doExecute(nil, nil, s, 0, 2)
 	if a == nil {
 		return ""
 	}
@@ -1244,7 +649,7 @@ func (re *Regexp) FindString(s string) string {
 // itself is at s[loc[0]:loc[1]].
 // A return value of nil indicates no match.
 func (re *Regexp) FindStringIndex(s string) []int {
-	a := re.doExecute(newInputString(s), 0)
+	a := re.doExecute(nil, nil, s, 0, 2)
 	if a == nil {
 		return nil
 	}
@@ -1256,7 +661,7 @@ func (re *Regexp) FindStringIndex(s string) []int {
 // the RuneReader.  The match itself is at s[loc[0]:loc[1]].  A return
 // value of nil indicates no match.
 func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
-	a := re.doExecute(newInputReader(r), 0)
+	a := re.doExecute(r, nil, "", 0, 2)
 	if a == nil {
 		return nil
 	}
@@ -1269,13 +674,13 @@ func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
 // comment.
 // A return value of nil indicates no match.
 func (re *Regexp) FindSubmatch(b []byte) [][]byte {
-	a := re.doExecute(newInputBytes(b), 0)
+	a := re.doExecute(nil, b, "", 0, re.prog.NumCap)
 	if a == nil {
 		return nil
 	}
-	ret := make([][]byte, len(a)/2)
+	ret := make([][]byte, 1+re.numSubexp)
 	for i := range ret {
-		if a[2*i] >= 0 {
+		if 2*i < len(a) && a[2*i] >= 0 {
 			ret[i] = b[a[2*i]:a[2*i+1]]
 		}
 	}
@@ -1288,7 +693,7 @@ func (re *Regexp) FindSubmatch(b []byte) [][]byte {
 // in the package comment.
 // A return value of nil indicates no match.
 func (re *Regexp) FindSubmatchIndex(b []byte) []int {
-	return re.doExecute(newInputBytes(b), 0)
+	return re.pad(re.doExecute(nil, b, "", 0, re.prog.NumCap))
 }
 
 // FindStringSubmatch returns a slice of strings holding the text of the
@@ -1297,13 +702,13 @@ func (re *Regexp) FindSubmatchIndex(b []byte) []int {
 // package comment.
 // A return value of nil indicates no match.
 func (re *Regexp) FindStringSubmatch(s string) []string {
-	a := re.doExecute(newInputString(s), 0)
+	a := re.doExecute(nil, nil, s, 0, re.prog.NumCap)
 	if a == nil {
 		return nil
 	}
-	ret := make([]string, len(a)/2)
+	ret := make([]string, 1+re.numSubexp)
 	for i := range ret {
-		if a[2*i] >= 0 {
+		if 2*i < len(a) && a[2*i] >= 0 {
 			ret[i] = s[a[2*i]:a[2*i+1]]
 		}
 	}
@@ -1316,7 +721,7 @@ func (re *Regexp) FindStringSubmatch(s string) []string {
 // 'Index' descriptions in the package comment.
 // A return value of nil indicates no match.
 func (re *Regexp) FindStringSubmatchIndex(s string) []int {
-	return re.doExecute(newInputString(s), 0)
+	return re.pad(re.doExecute(nil, nil, s, 0, re.prog.NumCap))
 }
 
 // FindReaderSubmatchIndex returns a slice holding the index pairs
@@ -1325,7 +730,7 @@ func (re *Regexp) FindStringSubmatchIndex(s string) []int {
 // by the 'Submatch' and 'Index' descriptions in the package comment.  A
 // return value of nil indicates no match.
 func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
-	return re.doExecute(newInputReader(r), 0)
+	return re.pad(re.doExecute(r, nil, "", 0, re.prog.NumCap))
 }
 
 const startSize = 10 // The size at which to start a slice in the 'All' routines.
diff --git a/src/pkg/regexp/syntax/Makefile b/src/pkg/regexp/syntax/Makefile
new file mode 100644
index 0000000..0b3764e
--- /dev/null
+++ b/src/pkg/regexp/syntax/Makefile
@@ -0,0 +1,16 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=regexp/syntax
+GOFILES=\
+	compile.go\
+	parse.go\
+	perl_groups.go\
+	prog.go\
+	regexp.go\
+	simplify.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/regexp/syntax/compile.go b/src/pkg/regexp/syntax/compile.go
new file mode 100644
index 0000000..41955bf
--- /dev/null
+++ b/src/pkg/regexp/syntax/compile.go
@@ -0,0 +1,289 @@
+// Copyright 2011 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 syntax
+
+import "unicode"
+
+// A patchList is a list of instruction pointers that need to be filled in (patched).
+// Because the pointers haven't been filled in yet, we can reuse their storage
+// to hold the list.  It's kind of sleazy, but works well in practice.
+// See http://swtch.com/~rsc/regexp/regexp1.html for inspiration.
+// 
+// These aren't really pointers: they're integers, so we can reinterpret them
+// this way without using package unsafe.  A value l denotes
+// p.inst[l>>1].Out (l&1==0) or .Arg (l&1==1). 
+// l == 0 denotes the empty list, okay because we start every program
+// with a fail instruction, so we'll never want to point at its output link.
+type patchList uint32
+
+func (l patchList) next(p *Prog) patchList {
+	i := &p.Inst[l>>1]
+	if l&1 == 0 {
+		return patchList(i.Out)
+	}
+	return patchList(i.Arg)
+}
+
+func (l patchList) patch(p *Prog, val uint32) {
+	for l != 0 {
+		i := &p.Inst[l>>1]
+		if l&1 == 0 {
+			l = patchList(i.Out)
+			i.Out = val
+		} else {
+			l = patchList(i.Arg)
+			i.Arg = val
+		}
+	}
+}
+
+func (l1 patchList) append(p *Prog, l2 patchList) patchList {
+	if l1 == 0 {
+		return l2
+	}
+	if l2 == 0 {
+		return l1
+	}
+
+	last := l1
+	for {
+		next := last.next(p)
+		if next == 0 {
+			break
+		}
+		last = next
+	}
+
+	i := &p.Inst[last>>1]
+	if last&1 == 0 {
+		i.Out = uint32(l2)
+	} else {
+		i.Arg = uint32(l2)
+	}
+	return l1
+}
+
+// A frag represents a compiled program fragment.
+type frag struct {
+	i   uint32    // index of first instruction
+	out patchList // where to record end instruction
+}
+
+type compiler struct {
+	p *Prog
+}
+
+// Compile compiles the regexp into a program to be executed.
+// The regexp should have been simplified already (returned from re.Simplify).
+func Compile(re *Regexp) (*Prog, error) {
+	var c compiler
+	c.init()
+	f := c.compile(re)
+	f.out.patch(c.p, c.inst(InstMatch).i)
+	c.p.Start = int(f.i)
+	return c.p, nil
+}
+
+func (c *compiler) init() {
+	c.p = new(Prog)
+	c.p.NumCap = 2 // implicit ( and ) for whole match $0
+	c.inst(InstFail)
+}
+
+var anyRuneNotNL = []rune{0, '\n' - 1, '\n' + 1, unicode.MaxRune}
+var anyRune = []rune{0, unicode.MaxRune}
+
+func (c *compiler) compile(re *Regexp) frag {
+	switch re.Op {
+	case OpNoMatch:
+		return c.fail()
+	case OpEmptyMatch:
+		return c.nop()
+	case OpLiteral:
+		if len(re.Rune) == 0 {
+			return c.nop()
+		}
+		var f frag
+		for j := range re.Rune {
+			f1 := c.rune(re.Rune[j:j+1], re.Flags)
+			if j == 0 {
+				f = f1
+			} else {
+				f = c.cat(f, f1)
+			}
+		}
+		return f
+	case OpCharClass:
+		return c.rune(re.Rune, re.Flags)
+	case OpAnyCharNotNL:
+		return c.rune(anyRuneNotNL, 0)
+	case OpAnyChar:
+		return c.rune(anyRune, 0)
+	case OpBeginLine:
+		return c.empty(EmptyBeginLine)
+	case OpEndLine:
+		return c.empty(EmptyEndLine)
+	case OpBeginText:
+		return c.empty(EmptyBeginText)
+	case OpEndText:
+		return c.empty(EmptyEndText)
+	case OpWordBoundary:
+		return c.empty(EmptyWordBoundary)
+	case OpNoWordBoundary:
+		return c.empty(EmptyNoWordBoundary)
+	case OpCapture:
+		bra := c.cap(uint32(re.Cap << 1))
+		sub := c.compile(re.Sub[0])
+		ket := c.cap(uint32(re.Cap<<1 | 1))
+		return c.cat(c.cat(bra, sub), ket)
+	case OpStar:
+		return c.star(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+	case OpPlus:
+		return c.plus(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+	case OpQuest:
+		return c.quest(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+	case OpConcat:
+		if len(re.Sub) == 0 {
+			return c.nop()
+		}
+		var f frag
+		for i, sub := range re.Sub {
+			if i == 0 {
+				f = c.compile(sub)
+			} else {
+				f = c.cat(f, c.compile(sub))
+			}
+		}
+		return f
+	case OpAlternate:
+		var f frag
+		for _, sub := range re.Sub {
+			f = c.alt(f, c.compile(sub))
+		}
+		return f
+	}
+	panic("regexp: unhandled case in compile")
+}
+
+func (c *compiler) inst(op InstOp) frag {
+	// TODO: impose length limit
+	f := frag{i: uint32(len(c.p.Inst))}
+	c.p.Inst = append(c.p.Inst, Inst{Op: op})
+	return f
+}
+
+func (c *compiler) nop() frag {
+	f := c.inst(InstNop)
+	f.out = patchList(f.i << 1)
+	return f
+}
+
+func (c *compiler) fail() frag {
+	return frag{}
+}
+
+func (c *compiler) cap(arg uint32) frag {
+	f := c.inst(InstCapture)
+	f.out = patchList(f.i << 1)
+	c.p.Inst[f.i].Arg = arg
+
+	if c.p.NumCap < int(arg)+1 {
+		c.p.NumCap = int(arg) + 1
+	}
+	return f
+}
+
+func (c *compiler) cat(f1, f2 frag) frag {
+	// concat of failure is failure
+	if f1.i == 0 || f2.i == 0 {
+		return frag{}
+	}
+
+	// TODO: elide nop
+
+	f1.out.patch(c.p, f2.i)
+	return frag{f1.i, f2.out}
+}
+
+func (c *compiler) alt(f1, f2 frag) frag {
+	// alt of failure is other
+	if f1.i == 0 {
+		return f2
+	}
+	if f2.i == 0 {
+		return f1
+	}
+
+	f := c.inst(InstAlt)
+	i := &c.p.Inst[f.i]
+	i.Out = f1.i
+	i.Arg = f2.i
+	f.out = f1.out.append(c.p, f2.out)
+	return f
+}
+
+func (c *compiler) quest(f1 frag, nongreedy bool) frag {
+	f := c.inst(InstAlt)
+	i := &c.p.Inst[f.i]
+	if nongreedy {
+		i.Arg = f1.i
+		f.out = patchList(f.i << 1)
+	} else {
+		i.Out = f1.i
+		f.out = patchList(f.i<<1 | 1)
+	}
+	f.out = f.out.append(c.p, f1.out)
+	return f
+}
+
+func (c *compiler) star(f1 frag, nongreedy bool) frag {
+	f := c.inst(InstAlt)
+	i := &c.p.Inst[f.i]
+	if nongreedy {
+		i.Arg = f1.i
+		f.out = patchList(f.i << 1)
+	} else {
+		i.Out = f1.i
+		f.out = patchList(f.i<<1 | 1)
+	}
+	f1.out.patch(c.p, f.i)
+	return f
+}
+
+func (c *compiler) plus(f1 frag, nongreedy bool) frag {
+	return frag{f1.i, c.star(f1, nongreedy).out}
+}
+
+func (c *compiler) empty(op EmptyOp) frag {
+	f := c.inst(InstEmptyWidth)
+	c.p.Inst[f.i].Arg = uint32(op)
+	f.out = patchList(f.i << 1)
+	return f
+}
+
+func (c *compiler) rune(r []rune, flags Flags) frag {
+	f := c.inst(InstRune)
+	i := &c.p.Inst[f.i]
+	i.Rune = r
+	flags &= FoldCase // only relevant flag is FoldCase
+	if len(r) != 1 || unicode.SimpleFold(r[0]) == r[0] {
+		// and sometimes not even that
+		flags &^= FoldCase
+	}
+	i.Arg = uint32(flags)
+	f.out = patchList(f.i << 1)
+
+	// Special cases for exec machine.
+	switch {
+	case flags&FoldCase == 0 && (len(r) == 1 || len(r) == 2 && r[0] == r[1]):
+		i.Op = InstRune1
+	case len(r) == 2 && r[0] == 0 && r[1] == unicode.MaxRune:
+		i.Op = InstRuneAny
+	case len(r) == 4 && r[0] == 0 && r[1] == '\n'-1 && r[2] == '\n'+1 && r[3] == unicode.MaxRune:
+		i.Op = InstRuneAnyNotNL
+	}
+
+	return f
+}
diff --git a/src/pkg/regexp/syntax/make_perl_groups.pl b/src/pkg/regexp/syntax/make_perl_groups.pl
new file mode 100755
index 0000000..d024f50
--- /dev/null
+++ b/src/pkg/regexp/syntax/make_perl_groups.pl
@@ -0,0 +1,103 @@
+#!/usr/bin/perl
+# Copyright 2008 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.
+
+# Modified version of RE2's make_perl_groups.pl.
+
+# Generate table entries giving character ranges
+# for POSIX/Perl character classes.  Rather than
+# figure out what the definition is, it is easier to ask
+# Perl about each letter from 0-128 and write down
+# its answer.
+
+ at posixclasses = (
+	"[:alnum:]",
+	"[:alpha:]",
+	"[:ascii:]",
+	"[:blank:]",
+	"[:cntrl:]",
+	"[:digit:]",
+	"[:graph:]",
+	"[:lower:]",
+	"[:print:]",
+	"[:punct:]",
+	"[:space:]",
+	"[:upper:]",
+	"[:word:]",
+	"[:xdigit:]",
+);
+
+ at perlclasses = (
+	"\\d",
+	"\\s",
+	"\\w",
+);
+
+sub ComputeClass($) {
+  my @ranges;
+  my ($class) = @_;
+  my $regexp = "[$class]";
+  my $start = -1;
+  for (my $i=0; $i<=129; $i++) {
+    if ($i == 129) { $i = 256; }
+    if ($i <= 128 && chr($i) =~ $regexp) {
+      if ($start < 0) {
+        $start = $i;
+      }
+    } else {
+      if ($start >= 0) {
+        push @ranges, [$start, $i-1];
+      }
+      $start = -1;
+    }
+  }
+  return @ranges;
+}
+
+sub PrintClass($$@) {
+  my ($cname, $name, @ranges) = @_;
+  print "var code$cname = []rune{  /* $name */\n";
+  for (my $i=0; $i<@ranges; $i++) {
+    my @a = @{$ranges[$i]};
+    printf "\t0x%x, 0x%x,\n", $a[0], $a[1];
+  }
+  print "}\n\n";
+  my $n = @ranges;
+  $negname = $name;
+  if ($negname =~ /:/) {
+    $negname =~ s/:/:^/;
+  } else {
+    $negname =~ y/a-z/A-Z/;
+  }
+  return "\t`$name`: {+1, code$cname},\n" .
+  	"\t`$negname`: {-1, code$cname},\n";
+}
+
+my $gen = 0;
+
+sub PrintClasses($@) {
+  my ($cname, @classes) = @_;
+  my @entries;
+  foreach my $cl (@classes) {
+    my @ranges = ComputeClass($cl);
+    push @entries, PrintClass(++$gen, $cl, @ranges);
+  }
+  print "var ${cname}Group = map[string]charGroup{\n";
+  foreach my $e (@entries) {
+    print $e;
+  }
+  print "}\n";
+  my $count = @entries;
+}
+
+print <<EOF;
+// GENERATED BY make_perl_groups.pl; DO NOT EDIT.
+// make_perl_groups.pl >perl_groups.go
+
+package syntax
+
+EOF
+
+PrintClasses("perl", @perlclasses);
+PrintClasses("posix", @posixclasses);
diff --git a/src/pkg/regexp/syntax/parse.go b/src/pkg/regexp/syntax/parse.go
new file mode 100644
index 0000000..6f8acbb
--- /dev/null
+++ b/src/pkg/regexp/syntax/parse.go
@@ -0,0 +1,1860 @@
+// Copyright 2011 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 syntax
+
+import (
+	"sort"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// An Error describes a failure to parse a regular expression
+// and gives the offending expression.
+type Error struct {
+	Code ErrorCode
+	Expr string
+}
+
+func (e *Error) Error() string {
+	return "error parsing regexp: " + e.Code.String() + ": `" + e.Expr + "`"
+}
+
+// An ErrorCode describes a failure to parse a regular expression.
+type ErrorCode string
+
+const (
+	// Unexpected error
+	ErrInternalError ErrorCode = "regexp/syntax: internal error"
+
+	// Parse errors
+	ErrInvalidCharClass      ErrorCode = "invalid character class"
+	ErrInvalidCharRange      ErrorCode = "invalid character class range"
+	ErrInvalidEscape         ErrorCode = "invalid escape sequence"
+	ErrInvalidNamedCapture   ErrorCode = "invalid named capture"
+	ErrInvalidPerlOp         ErrorCode = "invalid or unsupported Perl syntax"
+	ErrInvalidRepeatOp       ErrorCode = "invalid nested repetition operator"
+	ErrInvalidRepeatSize     ErrorCode = "invalid repeat count"
+	ErrInvalidUTF8           ErrorCode = "invalid UTF-8"
+	ErrMissingBracket        ErrorCode = "missing closing ]"
+	ErrMissingParen          ErrorCode = "missing closing )"
+	ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator"
+	ErrTrailingBackslash     ErrorCode = "trailing backslash at end of expression"
+)
+
+func (e ErrorCode) String() string {
+	return string(e)
+}
+
+// Flags control the behavior of the parser and record information about regexp context.
+type Flags uint16
+
+const (
+	FoldCase      Flags = 1 << iota // case-insensitive match
+	Literal                         // treat pattern as literal string
+	ClassNL                         // allow character classes like [^a-z] and [[:space:]] to match newline
+	DotNL                           // allow . to match newline
+	OneLine                         // treat ^ and $ as only matching at beginning and end of text
+	NonGreedy                       // make repetition operators default to non-greedy
+	PerlX                           // allow Perl extensions
+	UnicodeGroups                   // allow \p{Han}, \P{Han} for Unicode group and negation
+	WasDollar                       // regexp OpEndText was $, not \z
+	Simple                          // regexp contains no counted repetition
+
+	MatchNL = ClassNL | DotNL
+
+	Perl        = ClassNL | OneLine | PerlX | UnicodeGroups // as close to Perl as possible
+	POSIX Flags = 0                                         // POSIX syntax
+)
+
+// Pseudo-ops for parsing stack.
+const (
+	opLeftParen = opPseudo + iota
+	opVerticalBar
+)
+
+type parser struct {
+	flags       Flags     // parse mode flags
+	stack       []*Regexp // stack of parsed expressions
+	free        *Regexp
+	numCap      int // number of capturing groups seen
+	wholeRegexp string
+	tmpClass    []rune // temporary char class work space
+}
+
+func (p *parser) newRegexp(op Op) *Regexp {
+	re := p.free
+	if re != nil {
+		p.free = re.Sub0[0]
+		*re = Regexp{}
+	} else {
+		re = new(Regexp)
+	}
+	re.Op = op
+	return re
+}
+
+func (p *parser) reuse(re *Regexp) {
+	re.Sub0[0] = p.free
+	p.free = re
+}
+
+// Parse stack manipulation.
+
+// push pushes the regexp re onto the parse stack and returns the regexp.
+func (p *parser) push(re *Regexp) *Regexp {
+	if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
+		// Single rune.
+		if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
+			return nil
+		}
+		re.Op = OpLiteral
+		re.Rune = re.Rune[:1]
+		re.Flags = p.flags &^ FoldCase
+	} else if re.Op == OpCharClass && len(re.Rune) == 4 &&
+		re.Rune[0] == re.Rune[1] && re.Rune[2] == re.Rune[3] &&
+		unicode.SimpleFold(re.Rune[0]) == re.Rune[2] &&
+		unicode.SimpleFold(re.Rune[2]) == re.Rune[0] ||
+		re.Op == OpCharClass && len(re.Rune) == 2 &&
+			re.Rune[0]+1 == re.Rune[1] &&
+			unicode.SimpleFold(re.Rune[0]) == re.Rune[1] &&
+			unicode.SimpleFold(re.Rune[1]) == re.Rune[0] {
+		// Case-insensitive rune like [Aa] or [Δδ].
+		if p.maybeConcat(re.Rune[0], p.flags|FoldCase) {
+			return nil
+		}
+
+		// Rewrite as (case-insensitive) literal.
+		re.Op = OpLiteral
+		re.Rune = re.Rune[:1]
+		re.Flags = p.flags | FoldCase
+	} else {
+		// Incremental concatenation.
+		p.maybeConcat(-1, 0)
+	}
+
+	p.stack = append(p.stack, re)
+	return re
+}
+
+// maybeConcat implements incremental concatenation
+// of literal runes into string nodes.  The parser calls this
+// before each push, so only the top fragment of the stack
+// might need processing.  Since this is called before a push,
+// the topmost literal is no longer subject to operators like *
+// (Otherwise ab* would turn into (ab)*.)
+// If r >= 0 and there's a node left over, maybeConcat uses it
+// to push r with the given flags.
+// maybeConcat reports whether r was pushed.
+func (p *parser) maybeConcat(r rune, flags Flags) bool {
+	n := len(p.stack)
+	if n < 2 {
+		return false
+	}
+
+	re1 := p.stack[n-1]
+	re2 := p.stack[n-2]
+	if re1.Op != OpLiteral || re2.Op != OpLiteral || re1.Flags&FoldCase != re2.Flags&FoldCase {
+		return false
+	}
+
+	// Push re1 into re2.
+	re2.Rune = append(re2.Rune, re1.Rune...)
+
+	// Reuse re1 if possible.
+	if r >= 0 {
+		re1.Rune = re1.Rune0[:1]
+		re1.Rune[0] = r
+		re1.Flags = flags
+		return true
+	}
+
+	p.stack = p.stack[:n-1]
+	p.reuse(re1)
+	return false // did not push r
+}
+
+// newLiteral returns a new OpLiteral Regexp with the given flags
+func (p *parser) newLiteral(r rune, flags Flags) *Regexp {
+	re := p.newRegexp(OpLiteral)
+	re.Flags = flags
+	if flags&FoldCase != 0 {
+		r = minFoldRune(r)
+	}
+	re.Rune0[0] = r
+	re.Rune = re.Rune0[:1]
+	return re
+}
+
+// minFoldRune returns the minimum rune fold-equivalent to r.
+func minFoldRune(r rune) rune {
+	if r < minFold || r > maxFold {
+		return r
+	}
+	min := r
+	r0 := r
+	for r = unicode.SimpleFold(r); r != r0; r = unicode.SimpleFold(r) {
+		if min > r {
+			min = r
+		}
+	}
+	return min
+}
+
+// literal pushes a literal regexp for the rune r on the stack
+// and returns that regexp.
+func (p *parser) literal(r rune) {
+	p.push(p.newLiteral(r, p.flags))
+}
+
+// op pushes a regexp with the given op onto the stack
+// and returns that regexp.
+func (p *parser) op(op Op) *Regexp {
+	re := p.newRegexp(op)
+	re.Flags = p.flags
+	return p.push(re)
+}
+
+// repeat replaces the top stack element with itself repeated according to op, min, max.
+// before is the regexp suffix starting at the repetition operator.
+// after is the regexp suffix following after the repetition operator.
+// repeat returns an updated 'after' and an error, if any.
+func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (string, error) {
+	flags := p.flags
+	if p.flags&PerlX != 0 {
+		if len(after) > 0 && after[0] == '?' {
+			after = after[1:]
+			flags ^= NonGreedy
+		}
+		if lastRepeat != "" {
+			// In Perl it is not allowed to stack repetition operators:
+			// a** is a syntax error, not a doubled star, and a++ means
+			// something else entirely, which we don't support!
+			return "", &Error{ErrInvalidRepeatOp, lastRepeat[:len(lastRepeat)-len(after)]}
+		}
+	}
+	n := len(p.stack)
+	if n == 0 {
+		return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
+	}
+	sub := p.stack[n-1]
+	if sub.Op >= opPseudo {
+		return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
+	}
+	re := p.newRegexp(op)
+	re.Min = min
+	re.Max = max
+	re.Flags = flags
+	re.Sub = re.Sub0[:1]
+	re.Sub[0] = sub
+	p.stack[n-1] = re
+	return after, nil
+}
+
+// concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation.
+func (p *parser) concat() *Regexp {
+	p.maybeConcat(-1, 0)
+
+	// Scan down to find pseudo-operator | or (.
+	i := len(p.stack)
+	for i > 0 && p.stack[i-1].Op < opPseudo {
+		i--
+	}
+	subs := p.stack[i:]
+	p.stack = p.stack[:i]
+
+	// Empty concatenation is special case.
+	if len(subs) == 0 {
+		return p.push(p.newRegexp(OpEmptyMatch))
+	}
+
+	return p.push(p.collapse(subs, OpConcat))
+}
+
+// alternate replaces the top of the stack (above the topmost '(') with its alternation.
+func (p *parser) alternate() *Regexp {
+	// Scan down to find pseudo-operator (.
+	// There are no | above (.
+	i := len(p.stack)
+	for i > 0 && p.stack[i-1].Op < opPseudo {
+		i--
+	}
+	subs := p.stack[i:]
+	p.stack = p.stack[:i]
+
+	// Make sure top class is clean.
+	// All the others already are (see swapVerticalBar).
+	if len(subs) > 0 {
+		cleanAlt(subs[len(subs)-1])
+	}
+
+	// Empty alternate is special case
+	// (shouldn't happen but easy to handle).
+	if len(subs) == 0 {
+		return p.push(p.newRegexp(OpNoMatch))
+	}
+
+	return p.push(p.collapse(subs, OpAlternate))
+}
+
+// cleanAlt cleans re for eventual inclusion in an alternation.
+func cleanAlt(re *Regexp) {
+	switch re.Op {
+	case OpCharClass:
+		re.Rune = cleanClass(&re.Rune)
+		if len(re.Rune) == 2 && re.Rune[0] == 0 && re.Rune[1] == unicode.MaxRune {
+			re.Rune = nil
+			re.Op = OpAnyChar
+			return
+		}
+		if len(re.Rune) == 4 && re.Rune[0] == 0 && re.Rune[1] == '\n'-1 && re.Rune[2] == '\n'+1 && re.Rune[3] == unicode.MaxRune {
+			re.Rune = nil
+			re.Op = OpAnyCharNotNL
+			return
+		}
+		if cap(re.Rune)-len(re.Rune) > 100 {
+			// re.Rune will not grow any more.
+			// Make a copy or inline to reclaim storage.
+			re.Rune = append(re.Rune0[:0], re.Rune...)
+		}
+	}
+}
+
+// collapse returns the result of applying op to sub.
+// If sub contains op nodes, they all get hoisted up
+// so that there is never a concat of a concat or an
+// alternate of an alternate.
+func (p *parser) collapse(subs []*Regexp, op Op) *Regexp {
+	if len(subs) == 1 {
+		return subs[0]
+	}
+	re := p.newRegexp(op)
+	re.Sub = re.Sub0[:0]
+	for _, sub := range subs {
+		if sub.Op == op {
+			re.Sub = append(re.Sub, sub.Sub...)
+			p.reuse(sub)
+		} else {
+			re.Sub = append(re.Sub, sub)
+		}
+	}
+	if op == OpAlternate {
+		re.Sub = p.factor(re.Sub, re.Flags)
+		if len(re.Sub) == 1 {
+			old := re
+			re = re.Sub[0]
+			p.reuse(old)
+		}
+	}
+	return re
+}
+
+// factor factors common prefixes from the alternation list sub.
+// It returns a replacement list that reuses the same storage and
+// frees (passes to p.reuse) any removed *Regexps.
+//
+// For example,
+//     ABC|ABD|AEF|BCX|BCY
+// simplifies by literal prefix extraction to
+//     A(B(C|D)|EF)|BC(X|Y)
+// which simplifies by character class introduction to
+//     A(B[CD]|EF)|BC[XY]
+//
+func (p *parser) factor(sub []*Regexp, flags Flags) []*Regexp {
+	if len(sub) < 2 {
+		return sub
+	}
+
+	// Round 1: Factor out common literal prefixes.
+	var str []rune
+	var strflags Flags
+	start := 0
+	out := sub[:0]
+	for i := 0; i <= len(sub); i++ {
+		// Invariant: the Regexps that were in sub[0:start] have been
+		// used or marked for reuse, and the slice space has been reused
+		// for out (len(out) <= start).
+		//
+		// Invariant: sub[start:i] consists of regexps that all begin
+		// with str as modified by strflags.
+		var istr []rune
+		var iflags Flags
+		if i < len(sub) {
+			istr, iflags = p.leadingString(sub[i])
+			if iflags == strflags {
+				same := 0
+				for same < len(str) && same < len(istr) && str[same] == istr[same] {
+					same++
+				}
+				if same > 0 {
+					// Matches at least one rune in current range.
+					// Keep going around.
+					str = str[:same]
+					continue
+				}
+			}
+		}
+
+		// Found end of a run with common leading literal string:
+		// sub[start:i] all begin with str[0:len(str)], but sub[i]
+		// does not even begin with str[0].
+		//
+		// Factor out common string and append factored expression to out.
+		if i == start {
+			// Nothing to do - run of length 0.
+		} else if i == start+1 {
+			// Just one: don't bother factoring.
+			out = append(out, sub[start])
+		} else {
+			// Construct factored form: prefix(suffix1|suffix2|...)
+			prefix := p.newRegexp(OpLiteral)
+			prefix.Flags = strflags
+			prefix.Rune = append(prefix.Rune[:0], str...)
+
+			for j := start; j < i; j++ {
+				sub[j] = p.removeLeadingString(sub[j], len(str))
+			}
+			suffix := p.collapse(sub[start:i], OpAlternate) // recurse
+
+			re := p.newRegexp(OpConcat)
+			re.Sub = append(re.Sub[:0], prefix, suffix)
+			out = append(out, re)
+		}
+
+		// Prepare for next iteration.
+		start = i
+		str = istr
+		strflags = iflags
+	}
+	sub = out
+
+	// Round 2: Factor out common complex prefixes,
+	// just the first piece of each concatenation,
+	// whatever it is.  This is good enough a lot of the time.
+	start = 0
+	out = sub[:0]
+	var first *Regexp
+	for i := 0; i <= len(sub); i++ {
+		// Invariant: the Regexps that were in sub[0:start] have been
+		// used or marked for reuse, and the slice space has been reused
+		// for out (len(out) <= start).
+		//
+		// Invariant: sub[start:i] consists of regexps that all begin with ifirst.
+		var ifirst *Regexp
+		if i < len(sub) {
+			ifirst = p.leadingRegexp(sub[i])
+			if first != nil && first.Equal(ifirst) {
+				continue
+			}
+		}
+
+		// Found end of a run with common leading regexp:
+		// sub[start:i] all begin with first but sub[i] does not.
+		//
+		// Factor out common regexp and append factored expression to out.
+		if i == start {
+			// Nothing to do - run of length 0.
+		} else if i == start+1 {
+			// Just one: don't bother factoring.
+			out = append(out, sub[start])
+		} else {
+			// Construct factored form: prefix(suffix1|suffix2|...)
+			prefix := first
+			for j := start; j < i; j++ {
+				reuse := j != start // prefix came from sub[start] 
+				sub[j] = p.removeLeadingRegexp(sub[j], reuse)
+			}
+			suffix := p.collapse(sub[start:i], OpAlternate) // recurse
+
+			re := p.newRegexp(OpConcat)
+			re.Sub = append(re.Sub[:0], prefix, suffix)
+			out = append(out, re)
+		}
+
+		// Prepare for next iteration.
+		start = i
+		first = ifirst
+	}
+	sub = out
+
+	// Round 3: Collapse runs of single literals into character classes.
+	start = 0
+	out = sub[:0]
+	for i := 0; i <= len(sub); i++ {
+		// Invariant: the Regexps that were in sub[0:start] have been
+		// used or marked for reuse, and the slice space has been reused
+		// for out (len(out) <= start).
+		//
+		// Invariant: sub[start:i] consists of regexps that are either
+		// literal runes or character classes.
+		if i < len(sub) && isCharClass(sub[i]) {
+			continue
+		}
+
+		// sub[i] is not a char or char class;
+		// emit char class for sub[start:i]...
+		if i == start {
+			// Nothing to do - run of length 0.
+		} else if i == start+1 {
+			out = append(out, sub[start])
+		} else {
+			// Make new char class.
+			// Start with most complex regexp in sub[start].
+			max := start
+			for j := start + 1; j < i; j++ {
+				if sub[max].Op < sub[j].Op || sub[max].Op == sub[j].Op && len(sub[max].Rune) < len(sub[j].Rune) {
+					max = j
+				}
+			}
+			sub[start], sub[max] = sub[max], sub[start]
+
+			for j := start + 1; j < i; j++ {
+				mergeCharClass(sub[start], sub[j])
+				p.reuse(sub[j])
+			}
+			cleanAlt(sub[start])
+			out = append(out, sub[start])
+		}
+
+		// ... and then emit sub[i].
+		if i < len(sub) {
+			out = append(out, sub[i])
+		}
+		start = i + 1
+	}
+	sub = out
+
+	// Round 4: Collapse runs of empty matches into a single empty match.
+	start = 0
+	out = sub[:0]
+	for i := range sub {
+		if i+1 < len(sub) && sub[i].Op == OpEmptyMatch && sub[i+1].Op == OpEmptyMatch {
+			continue
+		}
+		out = append(out, sub[i])
+	}
+	sub = out
+
+	return sub
+}
+
+// leadingString returns the leading literal string that re begins with.
+// The string refers to storage in re or its children.
+func (p *parser) leadingString(re *Regexp) ([]rune, Flags) {
+	if re.Op == OpConcat && len(re.Sub) > 0 {
+		re = re.Sub[0]
+	}
+	if re.Op != OpLiteral {
+		return nil, 0
+	}
+	return re.Rune, re.Flags & FoldCase
+}
+
+// removeLeadingString removes the first n leading runes
+// from the beginning of re.  It returns the replacement for re.
+func (p *parser) removeLeadingString(re *Regexp, n int) *Regexp {
+	if re.Op == OpConcat && len(re.Sub) > 0 {
+		// Removing a leading string in a concatenation
+		// might simplify the concatenation.
+		sub := re.Sub[0]
+		sub = p.removeLeadingString(sub, n)
+		re.Sub[0] = sub
+		if sub.Op == OpEmptyMatch {
+			p.reuse(sub)
+			switch len(re.Sub) {
+			case 0, 1:
+				// Impossible but handle.
+				re.Op = OpEmptyMatch
+				re.Sub = nil
+			case 2:
+				old := re
+				re = re.Sub[1]
+				p.reuse(old)
+			default:
+				copy(re.Sub, re.Sub[1:])
+				re.Sub = re.Sub[:len(re.Sub)-1]
+			}
+		}
+		return re
+	}
+
+	if re.Op == OpLiteral {
+		re.Rune = re.Rune[:copy(re.Rune, re.Rune[n:])]
+		if len(re.Rune) == 0 {
+			re.Op = OpEmptyMatch
+		}
+	}
+	return re
+}
+
+// leadingRegexp returns the leading regexp that re begins with.
+// The regexp refers to storage in re or its children.
+func (p *parser) leadingRegexp(re *Regexp) *Regexp {
+	if re.Op == OpEmptyMatch {
+		return nil
+	}
+	if re.Op == OpConcat && len(re.Sub) > 0 {
+		sub := re.Sub[0]
+		if sub.Op == OpEmptyMatch {
+			return nil
+		}
+		return sub
+	}
+	return re
+}
+
+// removeLeadingRegexp removes the leading regexp in re.
+// It returns the replacement for re.
+// If reuse is true, it passes the removed regexp (if no longer needed) to p.reuse.
+func (p *parser) removeLeadingRegexp(re *Regexp, reuse bool) *Regexp {
+	if re.Op == OpConcat && len(re.Sub) > 0 {
+		if reuse {
+			p.reuse(re.Sub[0])
+		}
+		re.Sub = re.Sub[:copy(re.Sub, re.Sub[1:])]
+		switch len(re.Sub) {
+		case 0:
+			re.Op = OpEmptyMatch
+			re.Sub = nil
+		case 1:
+			old := re
+			re = re.Sub[0]
+			p.reuse(old)
+		}
+		return re
+	}
+	if reuse {
+		p.reuse(re)
+	}
+	return p.newRegexp(OpEmptyMatch)
+}
+
+func literalRegexp(s string, flags Flags) *Regexp {
+	re := &Regexp{Op: OpLiteral}
+	re.Flags = flags
+	re.Rune = re.Rune0[:0] // use local storage for small strings
+	for _, c := range s {
+		if len(re.Rune) >= cap(re.Rune) {
+			// string is too long to fit in Rune0.  let Go handle it
+			re.Rune = []rune(s)
+			break
+		}
+		re.Rune = append(re.Rune, c)
+	}
+	return re
+}
+
+// Parsing.
+
+func Parse(s string, flags Flags) (*Regexp, error) {
+	if flags&Literal != 0 {
+		// Trivial parser for literal string.
+		if err := checkUTF8(s); err != nil {
+			return nil, err
+		}
+		return literalRegexp(s, flags), nil
+	}
+
+	// Otherwise, must do real work.
+	var (
+		p          parser
+		err        error
+		c          rune
+		op         Op
+		lastRepeat string
+		min, max   int
+	)
+	p.flags = flags
+	p.wholeRegexp = s
+	t := s
+	for t != "" {
+		repeat := ""
+	BigSwitch:
+		switch t[0] {
+		default:
+			if c, t, err = nextRune(t); err != nil {
+				return nil, err
+			}
+			p.literal(c)
+
+		case '(':
+			if p.flags&PerlX != 0 && len(t) >= 2 && t[1] == '?' {
+				// Flag changes and non-capturing groups.
+				if t, err = p.parsePerlFlags(t); err != nil {
+					return nil, err
+				}
+				break
+			}
+			p.numCap++
+			p.op(opLeftParen).Cap = p.numCap
+			t = t[1:]
+		case '|':
+			if err = p.parseVerticalBar(); err != nil {
+				return nil, err
+			}
+			t = t[1:]
+		case ')':
+			if err = p.parseRightParen(); err != nil {
+				return nil, err
+			}
+			t = t[1:]
+		case '^':
+			if p.flags&OneLine != 0 {
+				p.op(OpBeginText)
+			} else {
+				p.op(OpBeginLine)
+			}
+			t = t[1:]
+		case '$':
+			if p.flags&OneLine != 0 {
+				p.op(OpEndText).Flags |= WasDollar
+			} else {
+				p.op(OpEndLine)
+			}
+			t = t[1:]
+		case '.':
+			if p.flags&DotNL != 0 {
+				p.op(OpAnyChar)
+			} else {
+				p.op(OpAnyCharNotNL)
+			}
+			t = t[1:]
+		case '[':
+			if t, err = p.parseClass(t); err != nil {
+				return nil, err
+			}
+		case '*', '+', '?':
+			before := t
+			switch t[0] {
+			case '*':
+				op = OpStar
+			case '+':
+				op = OpPlus
+			case '?':
+				op = OpQuest
+			}
+			after := t[1:]
+			if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil {
+				return nil, err
+			}
+			repeat = before
+			t = after
+		case '{':
+			op = OpRepeat
+			before := t
+			min, max, after, ok := p.parseRepeat(t)
+			if !ok {
+				// If the repeat cannot be parsed, { is a literal.
+				p.literal('{')
+				t = t[1:]
+				break
+			}
+			if min < 0 || min > 1000 || max > 1000 || max >= 0 && min > max {
+				// Numbers were too big, or max is present and min > max.
+				return nil, &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
+			}
+			if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil {
+				return nil, err
+			}
+			repeat = before
+			t = after
+		case '\\':
+			if p.flags&PerlX != 0 && len(t) >= 2 {
+				switch t[1] {
+				case 'A':
+					p.op(OpBeginText)
+					t = t[2:]
+					break BigSwitch
+				case 'b':
+					p.op(OpWordBoundary)
+					t = t[2:]
+					break BigSwitch
+				case 'B':
+					p.op(OpNoWordBoundary)
+					t = t[2:]
+					break BigSwitch
+				case 'C':
+					// any byte; not supported
+					return nil, &Error{ErrInvalidEscape, t[:2]}
+				case 'Q':
+					// \Q ... \E: the ... is always literals
+					var lit string
+					if i := strings.Index(t, `\E`); i < 0 {
+						lit = t[2:]
+						t = ""
+					} else {
+						lit = t[2:i]
+						t = t[i+2:]
+					}
+					p.push(literalRegexp(lit, p.flags))
+					break BigSwitch
+				case 'z':
+					p.op(OpEndText)
+					t = t[2:]
+					break BigSwitch
+				}
+			}
+
+			re := p.newRegexp(OpCharClass)
+			re.Flags = p.flags
+
+			// Look for Unicode character group like \p{Han}
+			if len(t) >= 2 && (t[1] == 'p' || t[1] == 'P') {
+				r, rest, err := p.parseUnicodeClass(t, re.Rune0[:0])
+				if err != nil {
+					return nil, err
+				}
+				if r != nil {
+					re.Rune = r
+					t = rest
+					p.push(re)
+					break BigSwitch
+				}
+			}
+
+			// Perl character class escape.
+			if r, rest := p.parsePerlClassEscape(t, re.Rune0[:0]); r != nil {
+				re.Rune = r
+				t = rest
+				p.push(re)
+				break BigSwitch
+			}
+			p.reuse(re)
+
+			// Ordinary single-character escape.
+			if c, t, err = p.parseEscape(t); err != nil {
+				return nil, err
+			}
+			p.literal(c)
+		}
+		lastRepeat = repeat
+	}
+
+	p.concat()
+	if p.swapVerticalBar() {
+		// pop vertical bar
+		p.stack = p.stack[:len(p.stack)-1]
+	}
+	p.alternate()
+
+	n := len(p.stack)
+	if n != 1 {
+		return nil, &Error{ErrMissingParen, s}
+	}
+	return p.stack[0], nil
+}
+
+// parseRepeat parses {min} (max=min) or {min,} (max=-1) or {min,max}.
+// If s is not of that form, it returns ok == false.
+// If s has the right form but the values are too big, it returns min == -1, ok == true.
+func (p *parser) parseRepeat(s string) (min, max int, rest string, ok bool) {
+	if s == "" || s[0] != '{' {
+		return
+	}
+	s = s[1:]
+	var ok1 bool
+	if min, s, ok1 = p.parseInt(s); !ok1 {
+		return
+	}
+	if s == "" {
+		return
+	}
+	if s[0] != ',' {
+		max = min
+	} else {
+		s = s[1:]
+		if s == "" {
+			return
+		}
+		if s[0] == '}' {
+			max = -1
+		} else if max, s, ok1 = p.parseInt(s); !ok1 {
+			return
+		} else if max < 0 {
+			// parseInt found too big a number
+			min = -1
+		}
+	}
+	if s == "" || s[0] != '}' {
+		return
+	}
+	rest = s[1:]
+	ok = true
+	return
+}
+
+// parsePerlFlags parses a Perl flag setting or non-capturing group or both,
+// like (?i) or (?: or (?i:.  It removes the prefix from s and updates the parse state.
+// The caller must have ensured that s begins with "(?".
+func (p *parser) parsePerlFlags(s string) (rest string, err error) {
+	t := s
+
+	// Check for named captures, first introduced in Python's regexp library.
+	// As usual, there are three slightly different syntaxes:
+	//
+	//   (?P<name>expr)   the original, introduced by Python
+	//   (?<name>expr)    the .NET alteration, adopted by Perl 5.10
+	//   (?'name'expr)    another .NET alteration, adopted by Perl 5.10
+	//
+	// Perl 5.10 gave in and implemented the Python version too,
+	// but they claim that the last two are the preferred forms.
+	// PCRE and languages based on it (specifically, PHP and Ruby)
+	// support all three as well.  EcmaScript 4 uses only the Python form.
+	//
+	// In both the open source world (via Code Search) and the
+	// Google source tree, (?P<expr>name) is the dominant form,
+	// so that's the one we implement.  One is enough.
+	if len(t) > 4 && t[2] == 'P' && t[3] == '<' {
+		// Pull out name.
+		end := strings.IndexRune(t, '>')
+		if end < 0 {
+			if err = checkUTF8(t); err != nil {
+				return "", err
+			}
+			return "", &Error{ErrInvalidNamedCapture, s}
+		}
+
+		capture := t[:end+1] // "(?P<name>"
+		name := t[4:end]     // "name"
+		if err = checkUTF8(name); err != nil {
+			return "", err
+		}
+		if !isValidCaptureName(name) {
+			return "", &Error{ErrInvalidNamedCapture, capture}
+		}
+
+		// Like ordinary capture, but named.
+		p.numCap++
+		re := p.op(opLeftParen)
+		re.Cap = p.numCap
+		re.Name = name
+		return t[end+1:], nil
+	}
+
+	// Non-capturing group.  Might also twiddle Perl flags.
+	var c rune
+	t = t[2:] // skip (?
+	flags := p.flags
+	sign := +1
+	sawFlag := false
+Loop:
+	for t != "" {
+		if c, t, err = nextRune(t); err != nil {
+			return "", err
+		}
+		switch c {
+		default:
+			break Loop
+
+		// Flags.
+		case 'i':
+			flags |= FoldCase
+			sawFlag = true
+		case 'm':
+			flags &^= OneLine
+			sawFlag = true
+		case 's':
+			flags |= DotNL
+			sawFlag = true
+		case 'U':
+			flags |= NonGreedy
+			sawFlag = true
+
+		// Switch to negation.
+		case '-':
+			if sign < 0 {
+				break Loop
+			}
+			sign = -1
+			// Invert flags so that | above turn into &^ and vice versa.
+			// We'll invert flags again before using it below.
+			flags = ^flags
+			sawFlag = false
+
+		// End of flags, starting group or not.
+		case ':', ')':
+			if sign < 0 {
+				if !sawFlag {
+					break Loop
+				}
+				flags = ^flags
+			}
+			if c == ':' {
+				// Open new group
+				p.op(opLeftParen)
+			}
+			p.flags = flags
+			return t, nil
+		}
+	}
+
+	return "", &Error{ErrInvalidPerlOp, s[:len(s)-len(t)]}
+}
+
+// isValidCaptureName reports whether name
+// is a valid capture name: [A-Za-z0-9_]+.
+// PCRE limits names to 32 bytes.
+// Python rejects names starting with digits.
+// We don't enforce either of those.
+func isValidCaptureName(name string) bool {
+	if name == "" {
+		return false
+	}
+	for _, c := range name {
+		if c != '_' && !isalnum(c) {
+			return false
+		}
+	}
+	return true
+}
+
+// parseInt parses a decimal integer.
+func (p *parser) parseInt(s string) (n int, rest string, ok bool) {
+	if s == "" || s[0] < '0' || '9' < s[0] {
+		return
+	}
+	// Disallow leading zeros.
+	if len(s) >= 2 && s[0] == '0' && '0' <= s[1] && s[1] <= '9' {
+		return
+	}
+	t := s
+	for s != "" && '0' <= s[0] && s[0] <= '9' {
+		s = s[1:]
+	}
+	rest = s
+	ok = true
+	// Have digits, compute value.
+	t = t[:len(t)-len(s)]
+	for i := 0; i < len(t); i++ {
+		// Avoid overflow.
+		if n >= 1e8 {
+			n = -1
+			break
+		}
+		n = n*10 + int(t[i]) - '0'
+	}
+	return
+}
+
+// can this be represented as a character class?
+// single-rune literal string, char class, ., and .|\n.
+func isCharClass(re *Regexp) bool {
+	return re.Op == OpLiteral && len(re.Rune) == 1 ||
+		re.Op == OpCharClass ||
+		re.Op == OpAnyCharNotNL ||
+		re.Op == OpAnyChar
+}
+
+// does re match r?
+func matchRune(re *Regexp, r rune) bool {
+	switch re.Op {
+	case OpLiteral:
+		return len(re.Rune) == 1 && re.Rune[0] == r
+	case OpCharClass:
+		for i := 0; i < len(re.Rune); i += 2 {
+			if re.Rune[i] <= r && r <= re.Rune[i+1] {
+				return true
+			}
+		}
+		return false
+	case OpAnyCharNotNL:
+		return r != '\n'
+	case OpAnyChar:
+		return true
+	}
+	return false
+}
+
+// parseVerticalBar handles a | in the input.
+func (p *parser) parseVerticalBar() error {
+	p.concat()
+
+	// The concatenation we just parsed is on top of the stack.
+	// If it sits above an opVerticalBar, swap it below
+	// (things below an opVerticalBar become an alternation).
+	// Otherwise, push a new vertical bar.
+	if !p.swapVerticalBar() {
+		p.op(opVerticalBar)
+	}
+
+	return nil
+}
+
+// mergeCharClass makes dst = dst|src.
+// The caller must ensure that dst.Op >= src.Op,
+// to reduce the amount of copying.
+func mergeCharClass(dst, src *Regexp) {
+	switch dst.Op {
+	case OpAnyChar:
+		// src doesn't add anything.
+	case OpAnyCharNotNL:
+		// src might add \n
+		if matchRune(src, '\n') {
+			dst.Op = OpAnyChar
+		}
+	case OpCharClass:
+		// src is simpler, so either literal or char class
+		if src.Op == OpLiteral {
+			dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
+		} else {
+			dst.Rune = appendClass(dst.Rune, src.Rune)
+		}
+	case OpLiteral:
+		// both literal
+		if src.Rune[0] == dst.Rune[0] && src.Flags == dst.Flags {
+			break
+		}
+		dst.Op = OpCharClass
+		dst.Rune = appendLiteral(dst.Rune[:0], dst.Rune[0], dst.Flags)
+		dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
+	}
+}
+
+// If the top of the stack is an element followed by an opVerticalBar
+// swapVerticalBar swaps the two and returns true.
+// Otherwise it returns false.
+func (p *parser) swapVerticalBar() bool {
+	// If above and below vertical bar are literal or char class,
+	// can merge into a single char class.
+	n := len(p.stack)
+	if n >= 3 && p.stack[n-2].Op == opVerticalBar && isCharClass(p.stack[n-1]) && isCharClass(p.stack[n-3]) {
+		re1 := p.stack[n-1]
+		re3 := p.stack[n-3]
+		// Make re3 the more complex of the two.
+		if re1.Op > re3.Op {
+			re1, re3 = re3, re1
+			p.stack[n-3] = re3
+		}
+		mergeCharClass(re3, re1)
+		p.reuse(re1)
+		p.stack = p.stack[:n-1]
+		return true
+	}
+
+	if n >= 2 {
+		re1 := p.stack[n-1]
+		re2 := p.stack[n-2]
+		if re2.Op == opVerticalBar {
+			if n >= 3 {
+				// Now out of reach.
+				// Clean opportunistically.
+				cleanAlt(p.stack[n-3])
+			}
+			p.stack[n-2] = re1
+			p.stack[n-1] = re2
+			return true
+		}
+	}
+	return false
+}
+
+// parseRightParen handles a ) in the input.
+func (p *parser) parseRightParen() error {
+	p.concat()
+	if p.swapVerticalBar() {
+		// pop vertical bar
+		p.stack = p.stack[:len(p.stack)-1]
+	}
+	p.alternate()
+
+	n := len(p.stack)
+	if n < 2 {
+		return &Error{ErrInternalError, ""}
+	}
+	re1 := p.stack[n-1]
+	re2 := p.stack[n-2]
+	p.stack = p.stack[:n-2]
+	if re2.Op != opLeftParen {
+		return &Error{ErrMissingParen, p.wholeRegexp}
+	}
+	// Restore flags at time of paren.
+	p.flags = re2.Flags
+	if re2.Cap == 0 {
+		// Just for grouping.
+		p.push(re1)
+	} else {
+		re2.Op = OpCapture
+		re2.Sub = re2.Sub0[:1]
+		re2.Sub[0] = re1
+		p.push(re2)
+	}
+	return nil
+}
+
+// parseEscape parses an escape sequence at the beginning of s
+// and returns the rune.
+func (p *parser) parseEscape(s string) (r rune, rest string, err error) {
+	t := s[1:]
+	if t == "" {
+		return 0, "", &Error{ErrTrailingBackslash, ""}
+	}
+	c, t, err := nextRune(t)
+	if err != nil {
+		return 0, "", err
+	}
+
+Switch:
+	switch c {
+	default:
+		if c < utf8.RuneSelf && !isalnum(c) {
+			// Escaped non-word characters are always themselves.
+			// PCRE is not quite so rigorous: it accepts things like
+			// \q, but we don't.  We once rejected \_, but too many
+			// programs and people insist on using it, so allow \_.
+			return c, t, nil
+		}
+
+	// Octal escapes.
+	case '1', '2', '3', '4', '5', '6', '7':
+		// Single non-zero digit is a backreference; not supported
+		if t == "" || t[0] < '0' || t[0] > '7' {
+			break
+		}
+		fallthrough
+	case '0':
+		// Consume up to three octal digits; already have one.
+		r = c - '0'
+		for i := 1; i < 3; i++ {
+			if t == "" || t[0] < '0' || t[0] > '7' {
+				break
+			}
+			r = r*8 + rune(t[0]) - '0'
+			t = t[1:]
+		}
+		return r, t, nil
+
+	// Hexadecimal escapes.
+	case 'x':
+		if t == "" {
+			break
+		}
+		if c, t, err = nextRune(t); err != nil {
+			return 0, "", err
+		}
+		if c == '{' {
+			// Any number of digits in braces.
+			// Perl accepts any text at all; it ignores all text
+			// after the first non-hex digit.  We require only hex digits,
+			// and at least one.
+			nhex := 0
+			r = 0
+			for {
+				if t == "" {
+					break Switch
+				}
+				if c, t, err = nextRune(t); err != nil {
+					return 0, "", err
+				}
+				if c == '}' {
+					break
+				}
+				v := unhex(c)
+				if v < 0 {
+					break Switch
+				}
+				r = r*16 + v
+				if r > unicode.MaxRune {
+					break Switch
+				}
+				nhex++
+			}
+			if nhex == 0 {
+				break Switch
+			}
+			return r, t, nil
+		}
+
+		// Easy case: two hex digits.
+		x := unhex(c)
+		if c, t, err = nextRune(t); err != nil {
+			return 0, "", err
+		}
+		y := unhex(c)
+		if x < 0 || y < 0 {
+			break
+		}
+		return x*16 + y, t, nil
+
+	// C escapes.  There is no case 'b', to avoid misparsing
+	// the Perl word-boundary \b as the C backspace \b
+	// when in POSIX mode.  In Perl, /\b/ means word-boundary
+	// but /[\b]/ means backspace.  We don't support that.
+	// If you want a backspace, embed a literal backspace
+	// character or use \x08.
+	case 'a':
+		return '\a', t, err
+	case 'f':
+		return '\f', t, err
+	case 'n':
+		return '\n', t, err
+	case 'r':
+		return '\r', t, err
+	case 't':
+		return '\t', t, err
+	case 'v':
+		return '\v', t, err
+	}
+	return 0, "", &Error{ErrInvalidEscape, s[:len(s)-len(t)]}
+}
+
+// parseClassChar parses a character class character at the beginning of s
+// and returns it.
+func (p *parser) parseClassChar(s, wholeClass string) (r rune, rest string, err error) {
+	if s == "" {
+		return 0, "", &Error{Code: ErrMissingBracket, Expr: wholeClass}
+	}
+
+	// Allow regular escape sequences even though
+	// many need not be escaped in this context.
+	if s[0] == '\\' {
+		return p.parseEscape(s)
+	}
+
+	return nextRune(s)
+}
+
+type charGroup struct {
+	sign  int
+	class []rune
+}
+
+// parsePerlClassEscape parses a leading Perl character class escape like \d
+// from the beginning of s.  If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parsePerlClassEscape(s string, r []rune) (out []rune, rest string) {
+	if p.flags&PerlX == 0 || len(s) < 2 || s[0] != '\\' {
+		return
+	}
+	g := perlGroup[s[0:2]]
+	if g.sign == 0 {
+		return
+	}
+	return p.appendGroup(r, g), s[2:]
+}
+
+// parseNamedClass parses a leading POSIX named character class like [:alnum:]
+// from the beginning of s.  If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parseNamedClass(s string, r []rune) (out []rune, rest string, err error) {
+	if len(s) < 2 || s[0] != '[' || s[1] != ':' {
+		return
+	}
+
+	i := strings.Index(s[2:], ":]")
+	if i < 0 {
+		return
+	}
+	i += 2
+	name, s := s[0:i+2], s[i+2:]
+	g := posixGroup[name]
+	if g.sign == 0 {
+		return nil, "", &Error{ErrInvalidCharRange, name}
+	}
+	return p.appendGroup(r, g), s, nil
+}
+
+func (p *parser) appendGroup(r []rune, g charGroup) []rune {
+	if p.flags&FoldCase == 0 {
+		if g.sign < 0 {
+			r = appendNegatedClass(r, g.class)
+		} else {
+			r = appendClass(r, g.class)
+		}
+	} else {
+		tmp := p.tmpClass[:0]
+		tmp = appendFoldedClass(tmp, g.class)
+		p.tmpClass = tmp
+		tmp = cleanClass(&p.tmpClass)
+		if g.sign < 0 {
+			r = appendNegatedClass(r, tmp)
+		} else {
+			r = appendClass(r, tmp)
+		}
+	}
+	return r
+}
+
+var anyTable = &unicode.RangeTable{
+	[]unicode.Range16{{0, 1<<16 - 1, 1}},
+	[]unicode.Range32{{1 << 16, unicode.MaxRune, 1}},
+}
+
+// unicodeTable returns the unicode.RangeTable identified by name
+// and the table of additional fold-equivalent code points.
+func unicodeTable(name string) (*unicode.RangeTable, *unicode.RangeTable) {
+	// Special case: "Any" means any.
+	if name == "Any" {
+		return anyTable, anyTable
+	}
+	if t := unicode.Categories[name]; t != nil {
+		return t, unicode.FoldCategory[name]
+	}
+	if t := unicode.Scripts[name]; t != nil {
+		return t, unicode.FoldScript[name]
+	}
+	return nil, nil
+}
+
+// parseUnicodeClass parses a leading Unicode character class like \p{Han}
+// from the beginning of s.  If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parseUnicodeClass(s string, r []rune) (out []rune, rest string, err error) {
+	if p.flags&UnicodeGroups == 0 || len(s) < 2 || s[0] != '\\' || s[1] != 'p' && s[1] != 'P' {
+		return
+	}
+
+	// Committed to parse or return error.
+	sign := +1
+	if s[1] == 'P' {
+		sign = -1
+	}
+	t := s[2:]
+	c, t, err := nextRune(t)
+	if err != nil {
+		return
+	}
+	var seq, name string
+	if c != '{' {
+		// Single-letter name.
+		seq = s[:len(s)-len(t)]
+		name = seq[2:]
+	} else {
+		// Name is in braces.
+		end := strings.IndexRune(s, '}')
+		if end < 0 {
+			if err = checkUTF8(s); err != nil {
+				return
+			}
+			return nil, "", &Error{ErrInvalidCharRange, s}
+		}
+		seq, t = s[:end+1], s[end+1:]
+		name = s[3:end]
+		if err = checkUTF8(name); err != nil {
+			return
+		}
+	}
+
+	// Group can have leading negation too.  \p{^Han} == \P{Han}, \P{^Han} == \p{Han}.
+	if name != "" && name[0] == '^' {
+		sign = -sign
+		name = name[1:]
+	}
+
+	tab, fold := unicodeTable(name)
+	if tab == nil {
+		return nil, "", &Error{ErrInvalidCharRange, seq}
+	}
+
+	if p.flags&FoldCase == 0 || fold == nil {
+		if sign > 0 {
+			r = appendTable(r, tab)
+		} else {
+			r = appendNegatedTable(r, tab)
+		}
+	} else {
+		// Merge and clean tab and fold in a temporary buffer.
+		// This is necessary for the negative case and just tidy
+		// for the positive case.
+		tmp := p.tmpClass[:0]
+		tmp = appendTable(tmp, tab)
+		tmp = appendTable(tmp, fold)
+		p.tmpClass = tmp
+		tmp = cleanClass(&p.tmpClass)
+		if sign > 0 {
+			r = appendClass(r, tmp)
+		} else {
+			r = appendNegatedClass(r, tmp)
+		}
+	}
+	return r, t, nil
+}
+
+// parseClass parses a character class at the beginning of s
+// and pushes it onto the parse stack.
+func (p *parser) parseClass(s string) (rest string, err error) {
+	t := s[1:] // chop [
+	re := p.newRegexp(OpCharClass)
+	re.Flags = p.flags
+	re.Rune = re.Rune0[:0]
+
+	sign := +1
+	if t != "" && t[0] == '^' {
+		sign = -1
+		t = t[1:]
+
+		// If character class does not match \n, add it here,
+		// so that negation later will do the right thing.
+		if p.flags&ClassNL == 0 {
+			re.Rune = append(re.Rune, '\n', '\n')
+		}
+	}
+
+	class := re.Rune
+	first := true // ] and - are okay as first char in class
+	for t == "" || t[0] != ']' || first {
+		// POSIX: - is only okay unescaped as first or last in class.
+		// Perl: - is okay anywhere.
+		if t != "" && t[0] == '-' && p.flags&PerlX == 0 && !first && (len(t) == 1 || t[1] != ']') {
+			_, size := utf8.DecodeRuneInString(t[1:])
+			return "", &Error{Code: ErrInvalidCharRange, Expr: t[:1+size]}
+		}
+		first = false
+
+		// Look for POSIX [:alnum:] etc.
+		if len(t) > 2 && t[0] == '[' && t[1] == ':' {
+			nclass, nt, err := p.parseNamedClass(t, class)
+			if err != nil {
+				return "", err
+			}
+			if nclass != nil {
+				class, t = nclass, nt
+				continue
+			}
+		}
+
+		// Look for Unicode character group like \p{Han}.
+		nclass, nt, err := p.parseUnicodeClass(t, class)
+		if err != nil {
+			return "", err
+		}
+		if nclass != nil {
+			class, t = nclass, nt
+			continue
+		}
+
+		// Look for Perl character class symbols (extension).
+		if nclass, nt := p.parsePerlClassEscape(t, class); nclass != nil {
+			class, t = nclass, nt
+			continue
+		}
+
+		// Single character or simple range.
+		rng := t
+		var lo, hi rune
+		if lo, t, err = p.parseClassChar(t, s); err != nil {
+			return "", err
+		}
+		hi = lo
+		// [a-] means (a|-) so check for final ].
+		if len(t) >= 2 && t[0] == '-' && t[1] != ']' {
+			t = t[1:]
+			if hi, t, err = p.parseClassChar(t, s); err != nil {
+				return "", err
+			}
+			if hi < lo {
+				rng = rng[:len(rng)-len(t)]
+				return "", &Error{Code: ErrInvalidCharRange, Expr: rng}
+			}
+		}
+		if p.flags&FoldCase == 0 {
+			class = appendRange(class, lo, hi)
+		} else {
+			class = appendFoldedRange(class, lo, hi)
+		}
+	}
+	t = t[1:] // chop ]
+
+	// Use &re.Rune instead of &class to avoid allocation.
+	re.Rune = class
+	class = cleanClass(&re.Rune)
+	if sign < 0 {
+		class = negateClass(class)
+	}
+	re.Rune = class
+	p.push(re)
+	return t, nil
+}
+
+// cleanClass sorts the ranges (pairs of elements of r),
+// merges them, and eliminates duplicates.
+func cleanClass(rp *[]rune) []rune {
+
+	// Sort by lo increasing, hi decreasing to break ties.
+	sort.Sort(ranges{rp})
+
+	r := *rp
+	if len(r) < 2 {
+		return r
+	}
+
+	// Merge abutting, overlapping.
+	w := 2 // write index
+	for i := 2; i < len(r); i += 2 {
+		lo, hi := r[i], r[i+1]
+		if lo <= r[w-1]+1 {
+			// merge with previous range
+			if hi > r[w-1] {
+				r[w-1] = hi
+			}
+			continue
+		}
+		// new disjoint range
+		r[w] = lo
+		r[w+1] = hi
+		w += 2
+	}
+
+	return r[:w]
+}
+
+// appendLiteral returns the result of appending the literal x to the class r.
+func appendLiteral(r []rune, x rune, flags Flags) []rune {
+	if flags&FoldCase != 0 {
+		return appendFoldedRange(r, x, x)
+	}
+	return appendRange(r, x, x)
+}
+
+// appendRange returns the result of appending the range lo-hi to the class r.
+func appendRange(r []rune, lo, hi rune) []rune {
+	// Expand last range or next to last range if it overlaps or abuts.
+	// Checking two ranges helps when appending case-folded
+	// alphabets, so that one range can be expanding A-Z and the
+	// other expanding a-z.
+	n := len(r)
+	for i := 2; i <= 4; i += 2 { // twice, using i=2, i=4
+		if n >= i {
+			rlo, rhi := r[n-i], r[n-i+1]
+			if lo <= rhi+1 && rlo <= hi+1 {
+				if lo < rlo {
+					r[n-i] = lo
+				}
+				if hi > rhi {
+					r[n-i+1] = hi
+				}
+				return r
+			}
+		}
+	}
+
+	return append(r, lo, hi)
+}
+
+const (
+	// minimum and maximum runes involved in folding.
+	// checked during test.
+	minFold = 0x0041
+	maxFold = 0x1044f
+)
+
+// appendFoldedRange returns the result of appending the range lo-hi
+// and its case folding-equivalent runes to the class r.
+func appendFoldedRange(r []rune, lo, hi rune) []rune {
+	// Optimizations.
+	if lo <= minFold && hi >= maxFold {
+		// Range is full: folding can't add more.
+		return appendRange(r, lo, hi)
+	}
+	if hi < minFold || lo > maxFold {
+		// Range is outside folding possibilities.
+		return appendRange(r, lo, hi)
+	}
+	if lo < minFold {
+		// [lo, minFold-1] needs no folding.
+		r = appendRange(r, lo, minFold-1)
+		lo = minFold
+	}
+	if hi > maxFold {
+		// [maxFold+1, hi] needs no folding.
+		r = appendRange(r, maxFold+1, hi)
+		hi = maxFold
+	}
+
+	// Brute force.  Depend on appendRange to coalesce ranges on the fly.
+	for c := lo; c <= hi; c++ {
+		r = appendRange(r, c, c)
+		f := unicode.SimpleFold(c)
+		for f != c {
+			r = appendRange(r, f, f)
+			f = unicode.SimpleFold(f)
+		}
+	}
+	return r
+}
+
+// appendClass returns the result of appending the class x to the class r.
+// It assume x is clean.
+func appendClass(r []rune, x []rune) []rune {
+	for i := 0; i < len(x); i += 2 {
+		r = appendRange(r, x[i], x[i+1])
+	}
+	return r
+}
+
+// appendFolded returns the result of appending the case folding of the class x to the class r.
+func appendFoldedClass(r []rune, x []rune) []rune {
+	for i := 0; i < len(x); i += 2 {
+		r = appendFoldedRange(r, x[i], x[i+1])
+	}
+	return r
+}
+
+// appendNegatedClass returns the result of appending the negation of the class x to the class r.
+// It assumes x is clean.
+func appendNegatedClass(r []rune, x []rune) []rune {
+	nextLo := '\u0000'
+	for i := 0; i < len(x); i += 2 {
+		lo, hi := x[i], x[i+1]
+		if nextLo <= lo-1 {
+			r = appendRange(r, nextLo, lo-1)
+		}
+		nextLo = hi + 1
+	}
+	if nextLo <= unicode.MaxRune {
+		r = appendRange(r, nextLo, unicode.MaxRune)
+	}
+	return r
+}
+
+// appendTable returns the result of appending x to the class r.
+func appendTable(r []rune, x *unicode.RangeTable) []rune {
+	for _, xr := range x.R16 {
+		lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
+		if stride == 1 {
+			r = appendRange(r, lo, hi)
+			continue
+		}
+		for c := lo; c <= hi; c += stride {
+			r = appendRange(r, c, c)
+		}
+	}
+	for _, xr := range x.R32 {
+		lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
+		if stride == 1 {
+			r = appendRange(r, lo, hi)
+			continue
+		}
+		for c := lo; c <= hi; c += stride {
+			r = appendRange(r, c, c)
+		}
+	}
+	return r
+}
+
+// appendNegatedTable returns the result of appending the negation of x to the class r.
+func appendNegatedTable(r []rune, x *unicode.RangeTable) []rune {
+	nextLo := '\u0000' // lo end of next class to add
+	for _, xr := range x.R16 {
+		lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
+		if stride == 1 {
+			if nextLo <= lo-1 {
+				r = appendRange(r, nextLo, lo-1)
+			}
+			nextLo = hi + 1
+			continue
+		}
+		for c := lo; c <= hi; c += stride {
+			if nextLo <= c-1 {
+				r = appendRange(r, nextLo, c-1)
+			}
+			nextLo = c + 1
+		}
+	}
+	for _, xr := range x.R32 {
+		lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
+		if stride == 1 {
+			if nextLo <= lo-1 {
+				r = appendRange(r, nextLo, lo-1)
+			}
+			nextLo = hi + 1
+			continue
+		}
+		for c := lo; c <= hi; c += stride {
+			if nextLo <= c-1 {
+				r = appendRange(r, nextLo, c-1)
+			}
+			nextLo = c + 1
+		}
+	}
+	if nextLo <= unicode.MaxRune {
+		r = appendRange(r, nextLo, unicode.MaxRune)
+	}
+	return r
+}
+
+// negateClass overwrites r and returns r's negation.
+// It assumes the class r is already clean.
+func negateClass(r []rune) []rune {
+	nextLo := '\u0000' // lo end of next class to add
+	w := 0             // write index
+	for i := 0; i < len(r); i += 2 {
+		lo, hi := r[i], r[i+1]
+		if nextLo <= lo-1 {
+			r[w] = nextLo
+			r[w+1] = lo - 1
+			w += 2
+		}
+		nextLo = hi + 1
+	}
+	r = r[:w]
+	if nextLo <= unicode.MaxRune {
+		// It's possible for the negation to have one more
+		// range - this one - than the original class, so use append.
+		r = append(r, nextLo, unicode.MaxRune)
+	}
+	return r
+}
+
+// ranges implements sort.Interface on a []rune.
+// The choice of receiver type definition is strange
+// but avoids an allocation since we already have
+// a *[]rune.
+type ranges struct {
+	p *[]rune
+}
+
+func (ra ranges) Less(i, j int) bool {
+	p := *ra.p
+	i *= 2
+	j *= 2
+	return p[i] < p[j] || p[i] == p[j] && p[i+1] > p[j+1]
+}
+
+func (ra ranges) Len() int {
+	return len(*ra.p) / 2
+}
+
+func (ra ranges) Swap(i, j int) {
+	p := *ra.p
+	i *= 2
+	j *= 2
+	p[i], p[i+1], p[j], p[j+1] = p[j], p[j+1], p[i], p[i+1]
+}
+
+func checkUTF8(s string) error {
+	for s != "" {
+		rune, size := utf8.DecodeRuneInString(s)
+		if rune == utf8.RuneError && size == 1 {
+			return &Error{Code: ErrInvalidUTF8, Expr: s}
+		}
+		s = s[size:]
+	}
+	return nil
+}
+
+func nextRune(s string) (c rune, t string, err error) {
+	c, size := utf8.DecodeRuneInString(s)
+	if c == utf8.RuneError && size == 1 {
+		return 0, "", &Error{Code: ErrInvalidUTF8, Expr: s}
+	}
+	return c, s[size:], nil
+}
+
+func isalnum(c rune) bool {
+	return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
+}
+
+func unhex(c rune) rune {
+	if '0' <= c && c <= '9' {
+		return c - '0'
+	}
+	if 'a' <= c && c <= 'f' {
+		return c - 'a' + 10
+	}
+	if 'A' <= c && c <= 'F' {
+		return c - 'A' + 10
+	}
+	return -1
+}
diff --git a/src/pkg/regexp/syntax/parse_test.go b/src/pkg/regexp/syntax/parse_test.go
new file mode 100644
index 0000000..c6e6339
--- /dev/null
+++ b/src/pkg/regexp/syntax/parse_test.go
@@ -0,0 +1,551 @@
+// Copyright 2011 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 syntax
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+	"unicode"
+)
+
+type parseTest struct {
+	Regexp string
+	Dump   string
+}
+
+var parseTests = []parseTest{
+	// Base cases
+	{`a`, `lit{a}`},
+	{`a.`, `cat{lit{a}dot{}}`},
+	{`a.b`, `cat{lit{a}dot{}lit{b}}`},
+	{`ab`, `str{ab}`},
+	{`a.b.c`, `cat{lit{a}dot{}lit{b}dot{}lit{c}}`},
+	{`abc`, `str{abc}`},
+	{`a|^`, `alt{lit{a}bol{}}`},
+	{`a|b`, `cc{0x61-0x62}`},
+	{`(a)`, `cap{lit{a}}`},
+	{`(a)|b`, `alt{cap{lit{a}}lit{b}}`},
+	{`a*`, `star{lit{a}}`},
+	{`a+`, `plus{lit{a}}`},
+	{`a?`, `que{lit{a}}`},
+	{`a{2}`, `rep{2,2 lit{a}}`},
+	{`a{2,3}`, `rep{2,3 lit{a}}`},
+	{`a{2,}`, `rep{2,-1 lit{a}}`},
+	{`a*?`, `nstar{lit{a}}`},
+	{`a+?`, `nplus{lit{a}}`},
+	{`a??`, `nque{lit{a}}`},
+	{`a{2}?`, `nrep{2,2 lit{a}}`},
+	{`a{2,3}?`, `nrep{2,3 lit{a}}`},
+	{`a{2,}?`, `nrep{2,-1 lit{a}}`},
+	// Malformed { } are treated as literals.
+	{`x{1001`, `str{x{1001}`},
+	{`x{9876543210`, `str{x{9876543210}`},
+	{`x{9876543210,`, `str{x{9876543210,}`},
+	{`x{2,1`, `str{x{2,1}`},
+	{`x{1,9876543210`, `str{x{1,9876543210}`},
+	{``, `emp{}`},
+	{`|`, `emp{}`}, // alt{emp{}emp{}} but got factored
+	{`|x|`, `alt{emp{}lit{x}emp{}}`},
+	{`.`, `dot{}`},
+	{`^`, `bol{}`},
+	{`$`, `eol{}`},
+	{`\|`, `lit{|}`},
+	{`\(`, `lit{(}`},
+	{`\)`, `lit{)}`},
+	{`\*`, `lit{*}`},
+	{`\+`, `lit{+}`},
+	{`\?`, `lit{?}`},
+	{`{`, `lit{{}`},
+	{`}`, `lit{}}`},
+	{`\.`, `lit{.}`},
+	{`\^`, `lit{^}`},
+	{`\$`, `lit{$}`},
+	{`\\`, `lit{\}`},
+	{`[ace]`, `cc{0x61 0x63 0x65}`},
+	{`[abc]`, `cc{0x61-0x63}`},
+	{`[a-z]`, `cc{0x61-0x7a}`},
+	{`[a]`, `lit{a}`},
+	{`\-`, `lit{-}`},
+	{`-`, `lit{-}`},
+	{`\_`, `lit{_}`},
+	{`abc`, `str{abc}`},
+	{`abc|def`, `alt{str{abc}str{def}}`},
+	{`abc|def|ghi`, `alt{str{abc}str{def}str{ghi}}`},
+
+	// Posix and Perl extensions
+	{`[[:lower:]]`, `cc{0x61-0x7a}`},
+	{`[a-z]`, `cc{0x61-0x7a}`},
+	{`[^[:lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
+	{`[[:^lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
+	{`(?i)[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+	{`(?i)[a-z]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+	{`(?i)[^[:lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+	{`(?i)[[:^lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+	{`\d`, `cc{0x30-0x39}`},
+	{`\D`, `cc{0x0-0x2f 0x3a-0x10ffff}`},
+	{`\s`, `cc{0x9-0xa 0xc-0xd 0x20}`},
+	{`\S`, `cc{0x0-0x8 0xb 0xe-0x1f 0x21-0x10ffff}`},
+	{`\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a}`},
+	{`\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x10ffff}`},
+	{`(?i)\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a 0x17f 0x212a}`},
+	{`(?i)\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+	{`[^\\]`, `cc{0x0-0x5b 0x5d-0x10ffff}`},
+	//	{ `\C`, `byte{}` },  // probably never
+
+	// Unicode, negatives, and a double negative.
+	{`\p{Braille}`, `cc{0x2800-0x28ff}`},
+	{`\P{Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+	{`\p{^Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+	{`\P{^Braille}`, `cc{0x2800-0x28ff}`},
+	{`\pZ`, `cc{0x20 0xa0 0x1680 0x180e 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
+	{`[\p{Braille}]`, `cc{0x2800-0x28ff}`},
+	{`[\P{Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+	{`[\p{^Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+	{`[\P{^Braille}]`, `cc{0x2800-0x28ff}`},
+	{`[\pZ]`, `cc{0x20 0xa0 0x1680 0x180e 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
+	{`\p{Lu}`, mkCharClass(unicode.IsUpper)},
+	{`[\p{Lu}]`, mkCharClass(unicode.IsUpper)},
+	{`(?i)[\p{Lu}]`, mkCharClass(isUpperFold)},
+	{`\p{Any}`, `dot{}`},
+	{`\p{^Any}`, `cc{}`},
+
+	// Hex, octal.
+	{`[\012-\234]\141`, `cat{cc{0xa-0x9c}lit{a}}`},
+	{`[\x{41}-\x7a]\x61`, `cat{cc{0x41-0x7a}lit{a}}`},
+
+	// More interesting regular expressions.
+	{`a{,2}`, `str{a{,2}}`},
+	{`\.\^\$\\`, `str{.^$\}`},
+	{`[a-zABC]`, `cc{0x41-0x43 0x61-0x7a}`},
+	{`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
+	{`[α-ε☺]`, `cc{0x3b1-0x3b5 0x263a}`}, // utf-8
+	{`a*{`, `cat{star{lit{a}}lit{{}}`},
+
+	// Test precedences
+	{`(?:ab)*`, `star{str{ab}}`},
+	{`(ab)*`, `star{cap{str{ab}}}`},
+	{`ab|cd`, `alt{str{ab}str{cd}}`},
+	{`a(b|c)d`, `cat{lit{a}cap{cc{0x62-0x63}}lit{d}}`},
+
+	// Test flattening.
+	{`(?:a)`, `lit{a}`},
+	{`(?:ab)(?:cd)`, `str{abcd}`},
+	{`(?:a+b+)(?:c+d+)`, `cat{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
+	{`(?:a+|b+)|(?:c+|d+)`, `alt{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
+	{`(?:a|b)|(?:c|d)`, `cc{0x61-0x64}`},
+	{`a|.`, `dot{}`},
+	{`.|a`, `dot{}`},
+	{`(?:[abc]|A|Z|hello|world)`, `alt{cc{0x41 0x5a 0x61-0x63}str{hello}str{world}}`},
+	{`(?:[abc]|A|Z)`, `cc{0x41 0x5a 0x61-0x63}`},
+
+	// Test Perl quoted literals
+	{`\Q+|*?{[\E`, `str{+|*?{[}`},
+	{`\Q+\E+`, `plus{lit{+}}`},
+	{`\Q\\E`, `lit{\}`},
+	{`\Q\\\E`, `str{\\}`},
+
+	// Test Perl \A and \z
+	{`(?m)^`, `bol{}`},
+	{`(?m)$`, `eol{}`},
+	{`(?-m)^`, `bot{}`},
+	{`(?-m)$`, `eot{}`},
+	{`(?m)\A`, `bot{}`},
+	{`(?m)\z`, `eot{\z}`},
+	{`(?-m)\A`, `bot{}`},
+	{`(?-m)\z`, `eot{\z}`},
+
+	// Test named captures
+	{`(?P<name>a)`, `cap{name:lit{a}}`},
+
+	// Case-folded literals
+	{`[Aa]`, `litfold{A}`},
+	{`[\x{100}\x{101}]`, `litfold{Ä€}`},
+	{`[Δδ]`, `litfold{Δ}`},
+
+	// Strings
+	{`abcde`, `str{abcde}`},
+	{`[Aa][Bb]cd`, `cat{strfold{AB}str{cd}}`},
+
+	// Factoring.
+	{`abc|abd|aef|bcx|bcy`, `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}cat{str{bc}cc{0x78-0x79}}}`},
+	{`ax+y|ax+z|ay+w`, `cat{lit{a}alt{cat{plus{lit{x}}cc{0x79-0x7a}}cat{plus{lit{y}}lit{w}}}}`},
+
+	// Bug fixes.
+	{`(?:.)`, `dot{}`},
+	{`(?:x|(?:xa))`, `cat{lit{x}alt{emp{}lit{a}}}`},
+	{`(?:.|(?:.a))`, `cat{dot{}alt{emp{}lit{a}}}`},
+	{`(?:A(?:A|a))`, `cat{lit{A}litfold{A}}`},
+	{`(?:A|a)`, `litfold{A}`},
+	{`A|(?:A|a)`, `litfold{A}`},
+	{`(?s).`, `dot{}`},
+	{`(?-s).`, `dnl{}`},
+	{`(?:(?:^).)`, `cat{bol{}dot{}}`},
+	{`(?-s)(?:(?:^).)`, `cat{bol{}dnl{}}`},
+
+	// RE2 prefix_tests
+	{`abc|abd`, `cat{str{ab}cc{0x63-0x64}}`},
+	{`a(?:b)c|abd`, `cat{str{ab}cc{0x63-0x64}}`},
+	{`abc|abd|aef|bcx|bcy`,
+		`alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}` +
+			`cat{str{bc}cc{0x78-0x79}}}`},
+	{`abc|x|abd`, `alt{str{abc}lit{x}str{abd}}`},
+	{`(?i)abc|ABD`, `cat{strfold{AB}cc{0x43-0x44 0x63-0x64}}`},
+	{`[ab]c|[ab]d`, `cat{cc{0x61-0x62}cc{0x63-0x64}}`},
+	{`(?:xx|yy)c|(?:xx|yy)d`,
+		`cat{alt{str{xx}str{yy}}cc{0x63-0x64}}`},
+	{`x{2}|x{2}[0-9]`,
+		`cat{rep{2,2 lit{x}}alt{emp{}cc{0x30-0x39}}}`},
+	{`x{2}y|x{2}[0-9]y`,
+		`cat{rep{2,2 lit{x}}alt{lit{y}cat{cc{0x30-0x39}lit{y}}}}`},
+}
+
+const testFlags = MatchNL | PerlX | UnicodeGroups
+
+func TestParseSimple(t *testing.T) {
+	testParseDump(t, parseTests, testFlags)
+}
+
+var foldcaseTests = []parseTest{
+	{`AbCdE`, `strfold{ABCDE}`},
+	{`[Aa]`, `litfold{A}`},
+	{`a`, `litfold{A}`},
+
+	// 0x17F is an old English long s (looks like an f) and folds to s.
+	// 0x212A is the Kelvin symbol and folds to k.
+	{`A[F-g]`, `cat{litfold{A}cc{0x41-0x7a 0x17f 0x212a}}`}, // [Aa][A-z...]
+	{`[[:upper:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+	{`[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+}
+
+func TestParseFoldCase(t *testing.T) {
+	testParseDump(t, foldcaseTests, FoldCase)
+}
+
+var literalTests = []parseTest{
+	{"(|)^$.[*+?]{5,10},\\", "str{(|)^$.[*+?]{5,10},\\}"},
+}
+
+func TestParseLiteral(t *testing.T) {
+	testParseDump(t, literalTests, Literal)
+}
+
+var matchnlTests = []parseTest{
+	{`.`, `dot{}`},
+	{"\n", "lit{\n}"},
+	{`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
+	{`[a\n]`, `cc{0xa 0x61}`},
+}
+
+func TestParseMatchNL(t *testing.T) {
+	testParseDump(t, matchnlTests, MatchNL)
+}
+
+var nomatchnlTests = []parseTest{
+	{`.`, `dnl{}`},
+	{"\n", "lit{\n}"},
+	{`[^a]`, `cc{0x0-0x9 0xb-0x60 0x62-0x10ffff}`},
+	{`[a\n]`, `cc{0xa 0x61}`},
+}
+
+func TestParseNoMatchNL(t *testing.T) {
+	testParseDump(t, nomatchnlTests, 0)
+}
+
+// Test Parse -> Dump.
+func testParseDump(t *testing.T, tests []parseTest, flags Flags) {
+	for _, tt := range tests {
+		re, err := Parse(tt.Regexp, flags)
+		if err != nil {
+			t.Errorf("Parse(%#q): %v", tt.Regexp, err)
+			continue
+		}
+		d := dump(re)
+		if d != tt.Dump {
+			t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
+		}
+	}
+}
+
+// dump prints a string representation of the regexp showing
+// the structure explicitly.
+func dump(re *Regexp) string {
+	var b bytes.Buffer
+	dumpRegexp(&b, re)
+	return b.String()
+}
+
+var opNames = []string{
+	OpNoMatch:        "no",
+	OpEmptyMatch:     "emp",
+	OpLiteral:        "lit",
+	OpCharClass:      "cc",
+	OpAnyCharNotNL:   "dnl",
+	OpAnyChar:        "dot",
+	OpBeginLine:      "bol",
+	OpEndLine:        "eol",
+	OpBeginText:      "bot",
+	OpEndText:        "eot",
+	OpWordBoundary:   "wb",
+	OpNoWordBoundary: "nwb",
+	OpCapture:        "cap",
+	OpStar:           "star",
+	OpPlus:           "plus",
+	OpQuest:          "que",
+	OpRepeat:         "rep",
+	OpConcat:         "cat",
+	OpAlternate:      "alt",
+}
+
+// dumpRegexp writes an encoding of the syntax tree for the regexp re to b.
+// It is used during testing to distinguish between parses that might print
+// the same using re's String method.
+func dumpRegexp(b *bytes.Buffer, re *Regexp) {
+	if int(re.Op) >= len(opNames) || opNames[re.Op] == "" {
+		fmt.Fprintf(b, "op%d", re.Op)
+	} else {
+		switch re.Op {
+		default:
+			b.WriteString(opNames[re.Op])
+		case OpStar, OpPlus, OpQuest, OpRepeat:
+			if re.Flags&NonGreedy != 0 {
+				b.WriteByte('n')
+			}
+			b.WriteString(opNames[re.Op])
+		case OpLiteral:
+			if len(re.Rune) > 1 {
+				b.WriteString("str")
+			} else {
+				b.WriteString("lit")
+			}
+			if re.Flags&FoldCase != 0 {
+				for _, r := range re.Rune {
+					if unicode.SimpleFold(r) != r {
+						b.WriteString("fold")
+						break
+					}
+				}
+			}
+		}
+	}
+	b.WriteByte('{')
+	switch re.Op {
+	case OpEndText:
+		if re.Flags&WasDollar == 0 {
+			b.WriteString(`\z`)
+		}
+	case OpLiteral:
+		for _, r := range re.Rune {
+			b.WriteRune(r)
+		}
+	case OpConcat, OpAlternate:
+		for _, sub := range re.Sub {
+			dumpRegexp(b, sub)
+		}
+	case OpStar, OpPlus, OpQuest:
+		dumpRegexp(b, re.Sub[0])
+	case OpRepeat:
+		fmt.Fprintf(b, "%d,%d ", re.Min, re.Max)
+		dumpRegexp(b, re.Sub[0])
+	case OpCapture:
+		if re.Name != "" {
+			b.WriteString(re.Name)
+			b.WriteByte(':')
+		}
+		dumpRegexp(b, re.Sub[0])
+	case OpCharClass:
+		sep := ""
+		for i := 0; i < len(re.Rune); i += 2 {
+			b.WriteString(sep)
+			sep = " "
+			lo, hi := re.Rune[i], re.Rune[i+1]
+			if lo == hi {
+				fmt.Fprintf(b, "%#x", lo)
+			} else {
+				fmt.Fprintf(b, "%#x-%#x", lo, hi)
+			}
+		}
+	}
+	b.WriteByte('}')
+}
+
+func mkCharClass(f func(rune) bool) string {
+	re := &Regexp{Op: OpCharClass}
+	lo := rune(-1)
+	for i := rune(0); i <= unicode.MaxRune; i++ {
+		if f(i) {
+			if lo < 0 {
+				lo = i
+			}
+		} else {
+			if lo >= 0 {
+				re.Rune = append(re.Rune, lo, i-1)
+				lo = -1
+			}
+		}
+	}
+	if lo >= 0 {
+		re.Rune = append(re.Rune, lo, unicode.MaxRune)
+	}
+	return dump(re)
+}
+
+func isUpperFold(r rune) bool {
+	if unicode.IsUpper(r) {
+		return true
+	}
+	c := unicode.SimpleFold(r)
+	for c != r {
+		if unicode.IsUpper(c) {
+			return true
+		}
+		c = unicode.SimpleFold(c)
+	}
+	return false
+}
+
+func TestFoldConstants(t *testing.T) {
+	last := rune(-1)
+	for i := rune(0); i <= unicode.MaxRune; i++ {
+		if unicode.SimpleFold(i) == i {
+			continue
+		}
+		if last == -1 && minFold != i {
+			t.Errorf("minFold=%#U should be %#U", minFold, i)
+		}
+		last = i
+	}
+	if maxFold != last {
+		t.Errorf("maxFold=%#U should be %#U", maxFold, last)
+	}
+}
+
+func TestAppendRangeCollapse(t *testing.T) {
+	// AppendRange should collapse each of the new ranges
+	// into the earlier ones (it looks back two ranges), so that
+	// the slice never grows very large.
+	// Note that we are not calling cleanClass.
+	var r []rune
+	for i := rune('A'); i <= 'Z'; i++ {
+		r = appendRange(r, i, i)
+		r = appendRange(r, i+'a'-'A', i+'a'-'A')
+	}
+	if string(r) != "AZaz" {
+		t.Errorf("appendRange interlaced A-Z a-z = %s, want AZaz", string(r))
+	}
+}
+
+var invalidRegexps = []string{
+	`(`,
+	`)`,
+	`(a`,
+	`(a|b|`,
+	`(a|b`,
+	`[a-z`,
+	`([a-z)`,
+	`x{1001}`,
+	`x{9876543210}`,
+	`x{2,1}`,
+	`x{1,9876543210}`,
+	"\xff", // Invalid UTF-8
+	"[\xff]",
+	"[\\\xff]",
+	"\\\xff",
+	`(?P<name>a`,
+	`(?P<name>`,
+	`(?P<name`,
+	`(?P<x y>a)`,
+	`(?P<>a)`,
+	`[a-Z]`,
+	`(?i)[a-Z]`,
+	`a{100000}`,
+	`a{100000,}`,
+}
+
+var onlyPerl = []string{
+	`[a-b-c]`,
+	`\Qabc\E`,
+	`\Q*+?{[\E`,
+	`\Q\\E`,
+	`\Q\\\E`,
+	`\Q\\\\E`,
+	`\Q\\\\\E`,
+	`(?:a)`,
+	`(?P<name>a)`,
+}
+
+var onlyPOSIX = []string{
+	"a++",
+	"a**",
+	"a?*",
+	"a+*",
+	"a{1}*",
+	".{1}{2}.{3}",
+}
+
+func TestParseInvalidRegexps(t *testing.T) {
+	for _, regexp := range invalidRegexps {
+		if re, err := Parse(regexp, Perl); err == nil {
+			t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re))
+		}
+		if re, err := Parse(regexp, POSIX); err == nil {
+			t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re))
+		}
+	}
+	for _, regexp := range onlyPerl {
+		if _, err := Parse(regexp, Perl); err != nil {
+			t.Errorf("Parse(%#q, Perl): %v", regexp, err)
+		}
+		if re, err := Parse(regexp, POSIX); err == nil {
+			t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re))
+		}
+	}
+	for _, regexp := range onlyPOSIX {
+		if re, err := Parse(regexp, Perl); err == nil {
+			t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re))
+		}
+		if _, err := Parse(regexp, POSIX); err != nil {
+			t.Errorf("Parse(%#q, POSIX): %v", regexp, err)
+		}
+	}
+}
+
+func TestToStringEquivalentParse(t *testing.T) {
+	for _, tt := range parseTests {
+		re, err := Parse(tt.Regexp, testFlags)
+		if err != nil {
+			t.Errorf("Parse(%#q): %v", tt.Regexp, err)
+			continue
+		}
+		d := dump(re)
+		if d != tt.Dump {
+			t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
+			continue
+		}
+
+		s := re.String()
+		if s != tt.Regexp {
+			// If ToString didn't return the original regexp,
+			// it must have found one with fewer parens.
+			// Unfortunately we can't check the length here, because
+			// ToString produces "\\{" for a literal brace,
+			// but "{" is a shorter equivalent in some contexts.
+			nre, err := Parse(s, testFlags)
+			if err != nil {
+				t.Errorf("Parse(%#q.String() = %#q): %v", tt.Regexp, t, err)
+				continue
+			}
+			nd := dump(nre)
+			if d != nd {
+				t.Errorf("Parse(%#q) -> %#q; %#q vs %#q", tt.Regexp, s, d, nd)
+			}
+
+			ns := nre.String()
+			if s != ns {
+				t.Errorf("Parse(%#q) -> %#q -> %#q", tt.Regexp, s, ns)
+			}
+		}
+	}
+}
diff --git a/src/pkg/regexp/syntax/perl_groups.go b/src/pkg/regexp/syntax/perl_groups.go
new file mode 100644
index 0000000..1a11ca6
--- /dev/null
+++ b/src/pkg/regexp/syntax/perl_groups.go
@@ -0,0 +1,130 @@
+// GENERATED BY make_perl_groups.pl; DO NOT EDIT.
+// make_perl_groups.pl >perl_groups.go
+
+package syntax
+
+var code1 = []rune{ /* \d */
+	0x30, 0x39,
+}
+
+var code2 = []rune{ /* \s */
+	0x9, 0xa,
+	0xc, 0xd,
+	0x20, 0x20,
+}
+
+var code3 = []rune{ /* \w */
+	0x30, 0x39,
+	0x41, 0x5a,
+	0x5f, 0x5f,
+	0x61, 0x7a,
+}
+
+var perlGroup = map[string]charGroup{
+	`\d`: {+1, code1},
+	`\D`: {-1, code1},
+	`\s`: {+1, code2},
+	`\S`: {-1, code2},
+	`\w`: {+1, code3},
+	`\W`: {-1, code3},
+}
+var code4 = []rune{ /* [:alnum:] */
+	0x30, 0x39,
+	0x41, 0x5a,
+	0x61, 0x7a,
+}
+
+var code5 = []rune{ /* [:alpha:] */
+	0x41, 0x5a,
+	0x61, 0x7a,
+}
+
+var code6 = []rune{ /* [:ascii:] */
+	0x0, 0x7f,
+}
+
+var code7 = []rune{ /* [:blank:] */
+	0x9, 0x9,
+	0x20, 0x20,
+}
+
+var code8 = []rune{ /* [:cntrl:] */
+	0x0, 0x1f,
+	0x7f, 0x7f,
+}
+
+var code9 = []rune{ /* [:digit:] */
+	0x30, 0x39,
+}
+
+var code10 = []rune{ /* [:graph:] */
+	0x21, 0x7e,
+}
+
+var code11 = []rune{ /* [:lower:] */
+	0x61, 0x7a,
+}
+
+var code12 = []rune{ /* [:print:] */
+	0x20, 0x7e,
+}
+
+var code13 = []rune{ /* [:punct:] */
+	0x21, 0x2f,
+	0x3a, 0x40,
+	0x5b, 0x60,
+	0x7b, 0x7e,
+}
+
+var code14 = []rune{ /* [:space:] */
+	0x9, 0xd,
+	0x20, 0x20,
+}
+
+var code15 = []rune{ /* [:upper:] */
+	0x41, 0x5a,
+}
+
+var code16 = []rune{ /* [:word:] */
+	0x30, 0x39,
+	0x41, 0x5a,
+	0x5f, 0x5f,
+	0x61, 0x7a,
+}
+
+var code17 = []rune{ /* [:xdigit:] */
+	0x30, 0x39,
+	0x41, 0x46,
+	0x61, 0x66,
+}
+
+var posixGroup = map[string]charGroup{
+	`[:alnum:]`:   {+1, code4},
+	`[:^alnum:]`:  {-1, code4},
+	`[:alpha:]`:   {+1, code5},
+	`[:^alpha:]`:  {-1, code5},
+	`[:ascii:]`:   {+1, code6},
+	`[:^ascii:]`:  {-1, code6},
+	`[:blank:]`:   {+1, code7},
+	`[:^blank:]`:  {-1, code7},
+	`[:cntrl:]`:   {+1, code8},
+	`[:^cntrl:]`:  {-1, code8},
+	`[:digit:]`:   {+1, code9},
+	`[:^digit:]`:  {-1, code9},
+	`[:graph:]`:   {+1, code10},
+	`[:^graph:]`:  {-1, code10},
+	`[:lower:]`:   {+1, code11},
+	`[:^lower:]`:  {-1, code11},
+	`[:print:]`:   {+1, code12},
+	`[:^print:]`:  {-1, code12},
+	`[:punct:]`:   {+1, code13},
+	`[:^punct:]`:  {-1, code13},
+	`[:space:]`:   {+1, code14},
+	`[:^space:]`:  {-1, code14},
+	`[:upper:]`:   {+1, code15},
+	`[:^upper:]`:  {-1, code15},
+	`[:word:]`:    {+1, code16},
+	`[:^word:]`:   {-1, code16},
+	`[:xdigit:]`:  {+1, code17},
+	`[:^xdigit:]`: {-1, code17},
+}
diff --git a/src/pkg/regexp/syntax/prog.go b/src/pkg/regexp/syntax/prog.go
new file mode 100644
index 0000000..902d3b3
--- /dev/null
+++ b/src/pkg/regexp/syntax/prog.go
@@ -0,0 +1,310 @@
+// Copyright 2011 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 syntax
+
+import (
+	"bytes"
+	"strconv"
+	"unicode"
+)
+
+// Compiled program.
+// May not belong in this package, but convenient for now.
+
+// A Prog is a compiled regular expression program.
+type Prog struct {
+	Inst   []Inst
+	Start  int // index of start instruction
+	NumCap int // number of InstCapture insts in re
+}
+
+// An InstOp is an instruction opcode.
+type InstOp uint8
+
+const (
+	InstAlt InstOp = iota
+	InstAltMatch
+	InstCapture
+	InstEmptyWidth
+	InstMatch
+	InstFail
+	InstNop
+	InstRune
+	InstRune1
+	InstRuneAny
+	InstRuneAnyNotNL
+)
+
+// An EmptyOp specifies a kind or mixture of zero-width assertions.
+type EmptyOp uint8
+
+const (
+	EmptyBeginLine EmptyOp = 1 << iota
+	EmptyEndLine
+	EmptyBeginText
+	EmptyEndText
+	EmptyWordBoundary
+	EmptyNoWordBoundary
+)
+
+// EmptyOpContext returns the zero-width assertions
+// satisfied at the position between the runes r1 and r2.
+// Passing r1 == -1 indicates that the position is
+// at the beginning of the text.
+// Passing r2 == -1 indicates that the position is
+// at the end of the text.
+func EmptyOpContext(r1, r2 rune) EmptyOp {
+	var op EmptyOp
+	if r1 < 0 {
+		op |= EmptyBeginText | EmptyBeginLine
+	}
+	if r1 == '\n' {
+		op |= EmptyBeginLine
+	}
+	if r2 < 0 {
+		op |= EmptyEndText | EmptyEndLine
+	}
+	if r2 == '\n' {
+		op |= EmptyEndLine
+	}
+	if IsWordChar(r1) != IsWordChar(r2) {
+		op |= EmptyWordBoundary
+	} else {
+		op |= EmptyNoWordBoundary
+	}
+	return op
+}
+
+// IsWordChar reports whether r is consider a ``word character''
+// during the evaluation of the \b and \B zero-width assertions.
+// These assertions are ASCII-only: the word characters are [A-Za-z0-9_].
+func IsWordChar(r rune) bool {
+	return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_'
+}
+
+// An Inst is a single instruction in a regular expression program.
+type Inst struct {
+	Op   InstOp
+	Out  uint32 // all but InstMatch, InstFail
+	Arg  uint32 // InstAlt, InstAltMatch, InstCapture, InstEmptyWidth
+	Rune []rune
+}
+
+func (p *Prog) String() string {
+	var b bytes.Buffer
+	dumpProg(&b, p)
+	return b.String()
+}
+
+// skipNop follows any no-op or capturing instructions
+// and returns the resulting pc.
+func (p *Prog) skipNop(pc uint32) *Inst {
+	i := &p.Inst[pc]
+	for i.Op == InstNop || i.Op == InstCapture {
+		pc = i.Out
+		i = &p.Inst[pc]
+	}
+	return i
+}
+
+// op returns i.Op but merges all the Rune special cases into InstRune
+func (i *Inst) op() InstOp {
+	op := i.Op
+	switch op {
+	case InstRune1, InstRuneAny, InstRuneAnyNotNL:
+		op = InstRune
+	}
+	return op
+}
+
+// Prefix returns a literal string that all matches for the
+// regexp must start with.  Complete is true if the prefix
+// is the entire match.
+func (p *Prog) Prefix() (prefix string, complete bool) {
+	i := p.skipNop(uint32(p.Start))
+
+	// Avoid allocation of buffer if prefix is empty.
+	if i.op() != InstRune || len(i.Rune) != 1 {
+		return "", i.Op == InstMatch
+	}
+
+	// Have prefix; gather characters.
+	var buf bytes.Buffer
+	for i.op() == InstRune && len(i.Rune) == 1 && Flags(i.Arg)&FoldCase == 0 {
+		buf.WriteRune(i.Rune[0])
+		i = p.skipNop(i.Out)
+	}
+	return buf.String(), i.Op == InstMatch
+}
+
+// StartCond returns the leading empty-width conditions that must
+// be true in any match.  It returns ^EmptyOp(0) if no matches are possible.
+func (p *Prog) StartCond() EmptyOp {
+	var flag EmptyOp
+	pc := uint32(p.Start)
+	i := &p.Inst[pc]
+Loop:
+	for {
+		switch i.Op {
+		case InstEmptyWidth:
+			flag |= EmptyOp(i.Arg)
+		case InstFail:
+			return ^EmptyOp(0)
+		case InstCapture, InstNop:
+			// skip
+		default:
+			break Loop
+		}
+		pc = i.Out
+		i = &p.Inst[pc]
+	}
+	return flag
+}
+
+// MatchRune returns true if the instruction matches (and consumes) r.
+// It should only be called when i.Op == InstRune.
+func (i *Inst) MatchRune(r rune) bool {
+	rune := i.Rune
+
+	// Special case: single-rune slice is from literal string, not char class.
+	if len(rune) == 1 {
+		r0 := rune[0]
+		if r == r0 {
+			return true
+		}
+		if Flags(i.Arg)&FoldCase != 0 {
+			for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) {
+				if r == r1 {
+					return true
+				}
+			}
+		}
+		return false
+	}
+
+	// Peek at the first few pairs.
+	// Should handle ASCII well.
+	for j := 0; j < len(rune) && j <= 8; j += 2 {
+		if r < rune[j] {
+			return false
+		}
+		if r <= rune[j+1] {
+			return true
+		}
+	}
+
+	// Otherwise binary search.
+	lo := 0
+	hi := len(rune) / 2
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		if c := rune[2*m]; c <= r {
+			if r <= rune[2*m+1] {
+				return true
+			}
+			lo = m + 1
+		} else {
+			hi = m
+		}
+	}
+	return false
+}
+
+// As per re2's Prog::IsWordChar. Determines whether rune is an ASCII word char.
+// Since we act on runes, it would be easy to support Unicode here.
+func wordRune(r rune) bool {
+	return r == '_' ||
+		('A' <= r && r <= 'Z') ||
+		('a' <= r && r <= 'z') ||
+		('0' <= r && r <= '9')
+}
+
+// MatchEmptyWidth returns true if the instruction matches
+// an empty string between the runes before and after.
+// It should only be called when i.Op == InstEmptyWidth.
+func (i *Inst) MatchEmptyWidth(before rune, after rune) bool {
+	switch EmptyOp(i.Arg) {
+	case EmptyBeginLine:
+		return before == '\n' || before == -1
+	case EmptyEndLine:
+		return after == '\n' || after == -1
+	case EmptyBeginText:
+		return before == -1
+	case EmptyEndText:
+		return after == -1
+	case EmptyWordBoundary:
+		return wordRune(before) != wordRune(after)
+	case EmptyNoWordBoundary:
+		return wordRune(before) == wordRune(after)
+	}
+	panic("unknown empty width arg")
+}
+
+func (i *Inst) String() string {
+	var b bytes.Buffer
+	dumpInst(&b, i)
+	return b.String()
+}
+
+func bw(b *bytes.Buffer, args ...string) {
+	for _, s := range args {
+		b.WriteString(s)
+	}
+}
+
+func dumpProg(b *bytes.Buffer, p *Prog) {
+	for j := range p.Inst {
+		i := &p.Inst[j]
+		pc := strconv.Itoa(j)
+		if len(pc) < 3 {
+			b.WriteString("   "[len(pc):])
+		}
+		if j == p.Start {
+			pc += "*"
+		}
+		bw(b, pc, "\t")
+		dumpInst(b, i)
+		bw(b, "\n")
+	}
+}
+
+func u32(i uint32) string {
+	return strconv.FormatUint(uint64(i), 10)
+}
+
+func dumpInst(b *bytes.Buffer, i *Inst) {
+	switch i.Op {
+	case InstAlt:
+		bw(b, "alt -> ", u32(i.Out), ", ", u32(i.Arg))
+	case InstAltMatch:
+		bw(b, "altmatch -> ", u32(i.Out), ", ", u32(i.Arg))
+	case InstCapture:
+		bw(b, "cap ", u32(i.Arg), " -> ", u32(i.Out))
+	case InstEmptyWidth:
+		bw(b, "empty ", u32(i.Arg), " -> ", u32(i.Out))
+	case InstMatch:
+		bw(b, "match")
+	case InstFail:
+		bw(b, "fail")
+	case InstNop:
+		bw(b, "nop -> ", u32(i.Out))
+	case InstRune:
+		if i.Rune == nil {
+			// shouldn't happen
+			bw(b, "rune <nil>")
+		}
+		bw(b, "rune ", strconv.QuoteToASCII(string(i.Rune)))
+		if Flags(i.Arg)&FoldCase != 0 {
+			bw(b, "/i")
+		}
+		bw(b, " -> ", u32(i.Out))
+	case InstRune1:
+		bw(b, "rune1 ", strconv.QuoteToASCII(string(i.Rune)), " -> ", u32(i.Out))
+	case InstRuneAny:
+		bw(b, "any -> ", u32(i.Out))
+	case InstRuneAnyNotNL:
+		bw(b, "anynotnl -> ", u32(i.Out))
+	}
+}
diff --git a/src/pkg/regexp/syntax/prog_test.go b/src/pkg/regexp/syntax/prog_test.go
new file mode 100644
index 0000000..663d5a8
--- /dev/null
+++ b/src/pkg/regexp/syntax/prog_test.go
@@ -0,0 +1,105 @@
+// Copyright 2011 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 syntax
+
+import (
+	"testing"
+)
+
+var compileTests = []struct {
+	Regexp string
+	Prog   string
+}{
+	{"a", `  0	fail
+  1*	rune1 "a" -> 2
+  2	match
+`},
+	{"[A-M][n-z]", `  0	fail
+  1*	rune "AM" -> 2
+  2	rune "nz" -> 3
+  3	match
+`},
+	{"", `  0	fail
+  1*	nop -> 2
+  2	match
+`},
+	{"a?", `  0	fail
+  1	rune1 "a" -> 3
+  2*	alt -> 1, 3
+  3	match
+`},
+	{"a??", `  0	fail
+  1	rune1 "a" -> 3
+  2*	alt -> 3, 1
+  3	match
+`},
+	{"a+", `  0	fail
+  1*	rune1 "a" -> 2
+  2	alt -> 1, 3
+  3	match
+`},
+	{"a+?", `  0	fail
+  1*	rune1 "a" -> 2
+  2	alt -> 3, 1
+  3	match
+`},
+	{"a*", `  0	fail
+  1	rune1 "a" -> 2
+  2*	alt -> 1, 3
+  3	match
+`},
+	{"a*?", `  0	fail
+  1	rune1 "a" -> 2
+  2*	alt -> 3, 1
+  3	match
+`},
+	{"a+b+", `  0	fail
+  1*	rune1 "a" -> 2
+  2	alt -> 1, 3
+  3	rune1 "b" -> 4
+  4	alt -> 3, 5
+  5	match
+`},
+	{"(a+)(b+)", `  0	fail
+  1*	cap 2 -> 2
+  2	rune1 "a" -> 3
+  3	alt -> 2, 4
+  4	cap 3 -> 5
+  5	cap 4 -> 6
+  6	rune1 "b" -> 7
+  7	alt -> 6, 8
+  8	cap 5 -> 9
+  9	match
+`},
+	{"a+|b+", `  0	fail
+  1	rune1 "a" -> 2
+  2	alt -> 1, 6
+  3	rune1 "b" -> 4
+  4	alt -> 3, 6
+  5*	alt -> 1, 3
+  6	match
+`},
+	{"A[Aa]", `  0	fail
+  1*	rune1 "A" -> 2
+  2	rune "A"/i -> 3
+  3	match
+`},
+	{"(?:(?:^).)", `  0	fail
+  1*	empty 4 -> 2
+  2	anynotnl -> 3
+  3	match
+`},
+}
+
+func TestCompile(t *testing.T) {
+	for _, tt := range compileTests {
+		re, _ := Parse(tt.Regexp, Perl)
+		p, _ := Compile(re)
+		s := p.String()
+		if s != tt.Prog {
+			t.Errorf("compiled %#q:\n--- have\n%s---\n--- want\n%s---", tt.Regexp, s, tt.Prog)
+		}
+	}
+}
diff --git a/src/pkg/regexp/syntax/regexp.go b/src/pkg/regexp/syntax/regexp.go
new file mode 100644
index 0000000..668a077
--- /dev/null
+++ b/src/pkg/regexp/syntax/regexp.go
@@ -0,0 +1,321 @@
+// Copyright 2011 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 syntax parses regular expressions into syntax trees.
+// WORK IN PROGRESS.
+package syntax
+
+// Note to implementers:
+// In this package, re is always a *Regexp and r is always a rune.
+
+import (
+	"bytes"
+	"strconv"
+	"strings"
+	"unicode"
+)
+
+// A Regexp is a node in a regular expression syntax tree.
+type Regexp struct {
+	Op       Op // operator
+	Flags    Flags
+	Sub      []*Regexp  // subexpressions, if any
+	Sub0     [1]*Regexp // storage for short Sub
+	Rune     []rune     // matched runes, for OpLiteral, OpCharClass
+	Rune0    [2]rune    // storage for short Rune
+	Min, Max int        // min, max for OpRepeat
+	Cap      int        // capturing index, for OpCapture
+	Name     string     // capturing name, for OpCapture
+}
+
+// An Op is a single regular expression operator.
+type Op uint8
+
+// Operators are listed in precedence order, tightest binding to weakest.
+// Character class operators are listed simplest to most complex
+// (OpLiteral, OpCharClass, OpAnyCharNotNL, OpAnyChar).
+
+const (
+	OpNoMatch        Op = 1 + iota // matches no strings
+	OpEmptyMatch                   // matches empty string
+	OpLiteral                      // matches Runes sequence
+	OpCharClass                    // matches Runes interpreted as range pair list
+	OpAnyCharNotNL                 // matches any character
+	OpAnyChar                      // matches any character
+	OpBeginLine                    // matches empty string at beginning of line
+	OpEndLine                      // matches empty string at end of line
+	OpBeginText                    // matches empty string at beginning of text
+	OpEndText                      // matches empty string at end of text
+	OpWordBoundary                 // matches word boundary `\b`
+	OpNoWordBoundary               // matches word non-boundary `\B`
+	OpCapture                      // capturing subexpression with index Cap, optional name Name
+	OpStar                         // matches Sub[0] zero or more times
+	OpPlus                         // matches Sub[0] one or more times
+	OpQuest                        // matches Sub[0] zero or one times
+	OpRepeat                       // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit)
+	OpConcat                       // matches concatenation of Subs
+	OpAlternate                    // matches alternation of Subs
+)
+
+const opPseudo Op = 128 // where pseudo-ops start
+
+// Equal returns true if x and y have identical structure.
+func (x *Regexp) Equal(y *Regexp) bool {
+	if x == nil || y == nil {
+		return x == y
+	}
+	if x.Op != y.Op {
+		return false
+	}
+	switch x.Op {
+	case OpEndText:
+		// The parse flags remember whether this is \z or \Z.
+		if x.Flags&WasDollar != y.Flags&WasDollar {
+			return false
+		}
+
+	case OpLiteral, OpCharClass:
+		if len(x.Rune) != len(y.Rune) {
+			return false
+		}
+		for i, r := range x.Rune {
+			if r != y.Rune[i] {
+				return false
+			}
+		}
+
+	case OpAlternate, OpConcat:
+		if len(x.Sub) != len(y.Sub) {
+			return false
+		}
+		for i, sub := range x.Sub {
+			if !sub.Equal(y.Sub[i]) {
+				return false
+			}
+		}
+
+	case OpStar, OpPlus, OpQuest:
+		if x.Flags&NonGreedy != y.Flags&NonGreedy || !x.Sub[0].Equal(y.Sub[0]) {
+			return false
+		}
+
+	case OpRepeat:
+		if x.Flags&NonGreedy != y.Flags&NonGreedy || x.Min != y.Min || x.Max != y.Max || !x.Sub[0].Equal(y.Sub[0]) {
+			return false
+		}
+
+	case OpCapture:
+		if x.Cap != y.Cap || x.Name != y.Name || !x.Sub[0].Equal(y.Sub[0]) {
+			return false
+		}
+	}
+	return true
+}
+
+// writeRegexp writes the Perl syntax for the regular expression re to b.
+func writeRegexp(b *bytes.Buffer, re *Regexp) {
+	switch re.Op {
+	default:
+		b.WriteString("<invalid op" + strconv.Itoa(int(re.Op)) + ">")
+	case OpNoMatch:
+		b.WriteString(`[^\x00-\x{10FFFF}]`)
+	case OpEmptyMatch:
+		b.WriteString(`(?:)`)
+	case OpLiteral:
+		if re.Flags&FoldCase != 0 {
+			b.WriteString(`(?i:`)
+		}
+		for _, r := range re.Rune {
+			escape(b, r, false)
+		}
+		if re.Flags&FoldCase != 0 {
+			b.WriteString(`)`)
+		}
+	case OpCharClass:
+		if len(re.Rune)%2 != 0 {
+			b.WriteString(`[invalid char class]`)
+			break
+		}
+		b.WriteRune('[')
+		if len(re.Rune) == 0 {
+			b.WriteString(`^\x00-\x{10FFFF}`)
+		} else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune {
+			// Contains 0 and MaxRune.  Probably a negated class.
+			// Print the gaps.
+			b.WriteRune('^')
+			for i := 1; i < len(re.Rune)-1; i += 2 {
+				lo, hi := re.Rune[i]+1, re.Rune[i+1]-1
+				escape(b, lo, lo == '-')
+				if lo != hi {
+					b.WriteRune('-')
+					escape(b, hi, hi == '-')
+				}
+			}
+		} else {
+			for i := 0; i < len(re.Rune); i += 2 {
+				lo, hi := re.Rune[i], re.Rune[i+1]
+				escape(b, lo, lo == '-')
+				if lo != hi {
+					b.WriteRune('-')
+					escape(b, hi, hi == '-')
+				}
+			}
+		}
+		b.WriteRune(']')
+	case OpAnyCharNotNL:
+		b.WriteString(`(?-s:.)`)
+	case OpAnyChar:
+		b.WriteString(`(?s:.)`)
+	case OpBeginLine:
+		b.WriteRune('^')
+	case OpEndLine:
+		b.WriteRune('$')
+	case OpBeginText:
+		b.WriteString(`\A`)
+	case OpEndText:
+		if re.Flags&WasDollar != 0 {
+			b.WriteString(`(?-m:$)`)
+		} else {
+			b.WriteString(`\z`)
+		}
+	case OpWordBoundary:
+		b.WriteString(`\b`)
+	case OpNoWordBoundary:
+		b.WriteString(`\B`)
+	case OpCapture:
+		if re.Name != "" {
+			b.WriteString(`(?P<`)
+			b.WriteString(re.Name)
+			b.WriteRune('>')
+		} else {
+			b.WriteRune('(')
+		}
+		if re.Sub[0].Op != OpEmptyMatch {
+			writeRegexp(b, re.Sub[0])
+		}
+		b.WriteRune(')')
+	case OpStar, OpPlus, OpQuest, OpRepeat:
+		if sub := re.Sub[0]; sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 {
+			b.WriteString(`(?:`)
+			writeRegexp(b, sub)
+			b.WriteString(`)`)
+		} else {
+			writeRegexp(b, sub)
+		}
+		switch re.Op {
+		case OpStar:
+			b.WriteRune('*')
+		case OpPlus:
+			b.WriteRune('+')
+		case OpQuest:
+			b.WriteRune('?')
+		case OpRepeat:
+			b.WriteRune('{')
+			b.WriteString(strconv.Itoa(re.Min))
+			if re.Max != re.Min {
+				b.WriteRune(',')
+				if re.Max >= 0 {
+					b.WriteString(strconv.Itoa(re.Max))
+				}
+			}
+			b.WriteRune('}')
+		}
+		if re.Flags&NonGreedy != 0 {
+			b.WriteRune('?')
+		}
+	case OpConcat:
+		for _, sub := range re.Sub {
+			if sub.Op == OpAlternate {
+				b.WriteString(`(?:`)
+				writeRegexp(b, sub)
+				b.WriteString(`)`)
+			} else {
+				writeRegexp(b, sub)
+			}
+		}
+	case OpAlternate:
+		for i, sub := range re.Sub {
+			if i > 0 {
+				b.WriteRune('|')
+			}
+			writeRegexp(b, sub)
+		}
+	}
+}
+
+func (re *Regexp) String() string {
+	var b bytes.Buffer
+	writeRegexp(&b, re)
+	return b.String()
+}
+
+const meta = `\.+*?()|[]{}^$`
+
+func escape(b *bytes.Buffer, r rune, force bool) {
+	if unicode.IsPrint(r) {
+		if strings.IndexRune(meta, r) >= 0 || force {
+			b.WriteRune('\\')
+		}
+		b.WriteRune(r)
+		return
+	}
+
+	switch r {
+	case '\a':
+		b.WriteString(`\a`)
+	case '\f':
+		b.WriteString(`\f`)
+	case '\n':
+		b.WriteString(`\n`)
+	case '\r':
+		b.WriteString(`\r`)
+	case '\t':
+		b.WriteString(`\t`)
+	case '\v':
+		b.WriteString(`\v`)
+	default:
+		if r < 0x100 {
+			b.WriteString(`\x`)
+			s := strconv.FormatInt(int64(r), 16)
+			if len(s) == 1 {
+				b.WriteRune('0')
+			}
+			b.WriteString(s)
+			break
+		}
+		b.WriteString(`\x{`)
+		b.WriteString(strconv.FormatInt(int64(r), 16))
+		b.WriteString(`}`)
+	}
+}
+
+// MaxCap walks the regexp to find the maximum capture index.
+func (re *Regexp) MaxCap() int {
+	m := 0
+	if re.Op == OpCapture {
+		m = re.Cap
+	}
+	for _, sub := range re.Sub {
+		if n := sub.MaxCap(); m < n {
+			m = n
+		}
+	}
+	return m
+}
+
+// CapNames walks the regexp to find the names of capturing groups.
+func (re *Regexp) CapNames() []string {
+	names := make([]string, re.MaxCap()+1)
+	re.capNames(names)
+	return names
+}
+
+func (re *Regexp) capNames(names []string) {
+	if re.Op == OpCapture {
+		names[re.Cap] = re.Name
+	}
+	for _, sub := range re.Sub {
+		sub.capNames(names)
+	}
+}
diff --git a/src/pkg/exp/regexp/syntax/simplify.go b/src/pkg/regexp/syntax/simplify.go
similarity index 100%
rename from src/pkg/exp/regexp/syntax/simplify.go
rename to src/pkg/regexp/syntax/simplify.go
diff --git a/src/pkg/exp/regexp/syntax/simplify_test.go b/src/pkg/regexp/syntax/simplify_test.go
similarity index 100%
rename from src/pkg/exp/regexp/syntax/simplify_test.go
rename to src/pkg/regexp/syntax/simplify_test.go
diff --git a/src/pkg/exp/regexp/testdata/README b/src/pkg/regexp/testdata/README
similarity index 100%
rename from src/pkg/exp/regexp/testdata/README
rename to src/pkg/regexp/testdata/README
diff --git a/src/pkg/exp/regexp/testdata/basic.dat b/src/pkg/regexp/testdata/basic.dat
similarity index 100%
rename from src/pkg/exp/regexp/testdata/basic.dat
rename to src/pkg/regexp/testdata/basic.dat
diff --git a/src/pkg/exp/regexp/testdata/nullsubexpr.dat b/src/pkg/regexp/testdata/nullsubexpr.dat
similarity index 100%
rename from src/pkg/exp/regexp/testdata/nullsubexpr.dat
rename to src/pkg/regexp/testdata/nullsubexpr.dat
diff --git a/src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2 b/src/pkg/regexp/testdata/re2-exhaustive.txt.bz2
similarity index 100%
rename from src/pkg/exp/regexp/testdata/re2-exhaustive.txt.bz2
rename to src/pkg/regexp/testdata/re2-exhaustive.txt.bz2
diff --git a/src/pkg/exp/regexp/testdata/re2-search.txt b/src/pkg/regexp/testdata/re2-search.txt
similarity index 100%
rename from src/pkg/exp/regexp/testdata/re2-search.txt
rename to src/pkg/regexp/testdata/re2-search.txt
diff --git a/src/pkg/exp/regexp/testdata/repetition.dat b/src/pkg/regexp/testdata/repetition.dat
similarity index 100%
rename from src/pkg/exp/regexp/testdata/repetition.dat
rename to src/pkg/regexp/testdata/repetition.dat
diff --git a/src/pkg/exp/regexp/testdata/testregex.c b/src/pkg/regexp/testdata/testregex.c
similarity index 100%
rename from src/pkg/exp/regexp/testdata/testregex.c
rename to src/pkg/regexp/testdata/testregex.c
diff --git a/src/pkg/rpc/Makefile b/src/pkg/rpc/Makefile
deleted file mode 100644
index 191b10d..0000000
--- a/src/pkg/rpc/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=rpc
-GOFILES=\
-	client.go\
-	debug.go\
-	server.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/rpc/client.go b/src/pkg/rpc/client.go
deleted file mode 100644
index 4acfdf6..0000000
--- a/src/pkg/rpc/client.go
+++ /dev/null
@@ -1,286 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package rpc
-
-import (
-	"bufio"
-	"gob"
-	"http"
-	"io"
-	"log"
-	"net"
-	"os"
-	"sync"
-)
-
-// ServerError represents an error that has been returned from
-// the remote side of the RPC connection.
-type ServerError string
-
-func (e ServerError) String() string {
-	return string(e)
-}
-
-var ErrShutdown = os.NewError("connection is shut down")
-
-// Call represents an active RPC.
-type Call struct {
-	ServiceMethod string      // The name of the service and method to call.
-	Args          interface{} // The argument to the function (*struct).
-	Reply         interface{} // The reply from the function (*struct).
-	Error         os.Error    // After completion, the error status.
-	Done          chan *Call  // Strobes when call is complete; value is the error status.
-	seq           uint64
-}
-
-// Client represents an RPC Client.
-// There may be multiple outstanding Calls associated
-// with a single Client.
-type Client struct {
-	mutex    sync.Mutex // protects pending, seq, request
-	sending  sync.Mutex
-	request  Request
-	seq      uint64
-	codec    ClientCodec
-	pending  map[uint64]*Call
-	closing  bool
-	shutdown bool
-}
-
-// A ClientCodec implements writing of RPC requests and
-// reading of RPC responses for the client side of an RPC session.
-// The client calls WriteRequest to write a request to the connection
-// and calls ReadResponseHeader and ReadResponseBody in pairs
-// to read responses.  The client calls Close when finished with the
-// connection. ReadResponseBody may be called with a nil
-// argument to force the body of the response to be read and then
-// discarded.
-type ClientCodec interface {
-	WriteRequest(*Request, interface{}) os.Error
-	ReadResponseHeader(*Response) os.Error
-	ReadResponseBody(interface{}) os.Error
-
-	Close() os.Error
-}
-
-func (client *Client) send(c *Call) {
-	// Register this call.
-	client.mutex.Lock()
-	if client.shutdown {
-		c.Error = ErrShutdown
-		client.mutex.Unlock()
-		c.done()
-		return
-	}
-	c.seq = client.seq
-	client.seq++
-	client.pending[c.seq] = c
-	client.mutex.Unlock()
-
-	// Encode and send the request.
-	client.sending.Lock()
-	defer client.sending.Unlock()
-	client.request.Seq = c.seq
-	client.request.ServiceMethod = c.ServiceMethod
-	if err := client.codec.WriteRequest(&client.request, c.Args); err != nil {
-		panic("rpc: client encode error: " + err.String())
-	}
-}
-
-func (client *Client) input() {
-	var err os.Error
-	var response Response
-	for err == nil {
-		response = Response{}
-		err = client.codec.ReadResponseHeader(&response)
-		if err != nil {
-			if err == os.EOF && !client.closing {
-				err = io.ErrUnexpectedEOF
-			}
-			break
-		}
-		seq := response.Seq
-		client.mutex.Lock()
-		c := client.pending[seq]
-		client.pending[seq] = c, false
-		client.mutex.Unlock()
-
-		if response.Error == "" {
-			err = client.codec.ReadResponseBody(c.Reply)
-			if err != nil {
-				c.Error = os.NewError("reading body " + err.String())
-			}
-		} else {
-			// We've got an error response. Give this to the request;
-			// any subsequent requests will get the ReadResponseBody
-			// error if there is one.
-			c.Error = ServerError(response.Error)
-			err = client.codec.ReadResponseBody(nil)
-			if err != nil {
-				err = os.NewError("reading error body: " + err.String())
-			}
-		}
-		c.done()
-	}
-	// Terminate pending calls.
-	client.mutex.Lock()
-	client.shutdown = true
-	for _, call := range client.pending {
-		call.Error = err
-		call.done()
-	}
-	client.mutex.Unlock()
-	if err != os.EOF || !client.closing {
-		log.Println("rpc: client protocol error:", err)
-	}
-}
-
-func (call *Call) done() {
-	select {
-	case call.Done <- call:
-		// ok
-	default:
-		// We don't want to block here.  It is the caller's responsibility to make
-		// sure the channel has enough buffer space. See comment in Go().
-	}
-}
-
-// NewClient returns a new Client to handle requests to the
-// set of services at the other end of the connection.
-// It adds a buffer to the write side of the connection so
-// the header and payload are sent as a unit.
-func NewClient(conn io.ReadWriteCloser) *Client {
-	encBuf := bufio.NewWriter(conn)
-	client := &gobClientCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(encBuf), encBuf}
-	return NewClientWithCodec(client)
-}
-
-// NewClientWithCodec is like NewClient but uses the specified
-// codec to encode requests and decode responses.
-func NewClientWithCodec(codec ClientCodec) *Client {
-	client := &Client{
-		codec:   codec,
-		pending: make(map[uint64]*Call),
-	}
-	go client.input()
-	return client
-}
-
-type gobClientCodec struct {
-	rwc    io.ReadWriteCloser
-	dec    *gob.Decoder
-	enc    *gob.Encoder
-	encBuf *bufio.Writer
-}
-
-func (c *gobClientCodec) WriteRequest(r *Request, body interface{}) (err os.Error) {
-	if err = c.enc.Encode(r); err != nil {
-		return
-	}
-	if err = c.enc.Encode(body); err != nil {
-		return
-	}
-	return c.encBuf.Flush()
-}
-
-func (c *gobClientCodec) ReadResponseHeader(r *Response) os.Error {
-	return c.dec.Decode(r)
-}
-
-func (c *gobClientCodec) ReadResponseBody(body interface{}) os.Error {
-	return c.dec.Decode(body)
-}
-
-func (c *gobClientCodec) Close() os.Error {
-	return c.rwc.Close()
-}
-
-// DialHTTP connects to an HTTP RPC server at the specified network address
-// listening on the default HTTP RPC path.
-func DialHTTP(network, address string) (*Client, os.Error) {
-	return DialHTTPPath(network, address, DefaultRPCPath)
-}
-
-// DialHTTPPath connects to an HTTP RPC server 
-// at the specified network address and path.
-func DialHTTPPath(network, address, path string) (*Client, os.Error) {
-	var err os.Error
-	conn, err := net.Dial(network, address)
-	if err != nil {
-		return nil, err
-	}
-	io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n")
-
-	// Require successful HTTP response
-	// before switching to RPC protocol.
-	resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
-	if err == nil && resp.Status == connected {
-		return NewClient(conn), nil
-	}
-	if err == nil {
-		err = os.NewError("unexpected HTTP response: " + resp.Status)
-	}
-	conn.Close()
-	return nil, &net.OpError{"dial-http", network + " " + address, nil, err}
-}
-
-// Dial connects to an RPC server at the specified network address.
-func Dial(network, address string) (*Client, os.Error) {
-	conn, err := net.Dial(network, address)
-	if err != nil {
-		return nil, err
-	}
-	return NewClient(conn), nil
-}
-
-func (client *Client) Close() os.Error {
-	client.mutex.Lock()
-	if client.shutdown || client.closing {
-		client.mutex.Unlock()
-		return ErrShutdown
-	}
-	client.closing = true
-	client.mutex.Unlock()
-	return client.codec.Close()
-}
-
-// Go invokes the function asynchronously.  It returns the Call structure representing
-// the invocation.  The done channel will signal when the call is complete by returning
-// the same Call object.  If done is nil, Go will allocate a new channel.
-// If non-nil, done must be buffered or Go will deliberately crash.
-func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
-	c := new(Call)
-	c.ServiceMethod = serviceMethod
-	c.Args = args
-	c.Reply = reply
-	if done == nil {
-		done = make(chan *Call, 10) // buffered.
-	} else {
-		// If caller passes done != nil, it must arrange that
-		// done has enough buffer for the number of simultaneous
-		// RPCs that will be using that channel.  If the channel
-		// is totally unbuffered, it's best not to run at all.
-		if cap(done) == 0 {
-			log.Panic("rpc: done channel is unbuffered")
-		}
-	}
-	c.Done = done
-	if client.shutdown {
-		c.Error = ErrShutdown
-		c.done()
-		return c
-	}
-	client.send(c)
-	return c
-}
-
-// Call invokes the named function, waits for it to complete, and returns its error status.
-func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) os.Error {
-	if client.shutdown {
-		return ErrShutdown
-	}
-	call := <-client.Go(serviceMethod, args, reply, make(chan *Call, 1)).Done
-	return call.Error
-}
diff --git a/src/pkg/rpc/debug.go b/src/pkg/rpc/debug.go
deleted file mode 100644
index 7e3e6f6..0000000
--- a/src/pkg/rpc/debug.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package rpc
-
-/*
-	Some HTML presented at http://machine:port/debug/rpc
-	Lists services, their methods, and some statistics, still rudimentary.
-*/
-
-import (
-	"fmt"
-	"http"
-	"sort"
-	"template"
-)
-
-const debugText = `<html>
-	<body>
-	<title>Services</title>
-	{{range .}}
-	<hr>
-	Service {{.Name}}
-	<hr>
-		<table>
-		<th align=center>Method</th><th align=center>Calls</th>
-		{{range .Method}}
-			<tr>
-			<td align=left font=fixed>{{.Name}}({{.Type.ArgType}}, {{.Type.ReplyType}}) os.Error</td>
-			<td align=center>{{.Type.NumCalls}}</td>
-			</tr>
-		{{end}}
-		</table>
-	{{end}}
-	</body>
-	</html>`
-
-var debug = template.Must(template.New("RPC debug").Parse(debugText))
-
-type debugMethod struct {
-	Type *methodType
-	Name string
-}
-
-type methodArray []debugMethod
-
-type debugService struct {
-	Service *service
-	Name    string
-	Method  methodArray
-}
-
-type serviceArray []debugService
-
-func (s serviceArray) Len() int           { return len(s) }
-func (s serviceArray) Less(i, j int) bool { return s[i].Name < s[j].Name }
-func (s serviceArray) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-
-func (m methodArray) Len() int           { return len(m) }
-func (m methodArray) Less(i, j int) bool { return m[i].Name < m[j].Name }
-func (m methodArray) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
-
-type debugHTTP struct {
-	*Server
-}
-
-// Runs at /debug/rpc
-func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) {
-	// Build a sorted version of the data.
-	var services = make(serviceArray, len(server.serviceMap))
-	i := 0
-	server.mu.Lock()
-	for sname, service := range server.serviceMap {
-		services[i] = debugService{service, sname, make(methodArray, len(service.method))}
-		j := 0
-		for mname, method := range service.method {
-			services[i].Method[j] = debugMethod{method, mname}
-			j++
-		}
-		sort.Sort(services[i].Method)
-		i++
-	}
-	server.mu.Unlock()
-	sort.Sort(services)
-	err := debug.Execute(w, services)
-	if err != nil {
-		fmt.Fprintln(w, "rpc: error executing template:", err.String())
-	}
-}
diff --git a/src/pkg/rpc/jsonrpc/Makefile b/src/pkg/rpc/jsonrpc/Makefile
deleted file mode 100644
index b9a1ac2..0000000
--- a/src/pkg/rpc/jsonrpc/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=rpc/jsonrpc
-GOFILES=\
-	client.go\
-	server.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/rpc/jsonrpc/all_test.go b/src/pkg/rpc/jsonrpc/all_test.go
deleted file mode 100644
index c1a9e8e..0000000
--- a/src/pkg/rpc/jsonrpc/all_test.go
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2010 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 jsonrpc
-
-import (
-	"fmt"
-	"json"
-	"net"
-	"os"
-	"rpc"
-	"testing"
-)
-
-type Args struct {
-	A, B int
-}
-
-type Reply struct {
-	C int
-}
-
-type Arith int
-
-func (t *Arith) Add(args *Args, reply *Reply) os.Error {
-	reply.C = args.A + args.B
-	return nil
-}
-
-func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
-	reply.C = args.A * args.B
-	return nil
-}
-
-func (t *Arith) Div(args *Args, reply *Reply) os.Error {
-	if args.B == 0 {
-		return os.NewError("divide by zero")
-	}
-	reply.C = args.A / args.B
-	return nil
-}
-
-func (t *Arith) Error(args *Args, reply *Reply) os.Error {
-	panic("ERROR")
-}
-
-func init() {
-	rpc.Register(new(Arith))
-}
-
-func TestServer(t *testing.T) {
-	type addResp struct {
-		Id     interface{} `json:"id"`
-		Result Reply       `json:"result"`
-		Error  interface{} `json:"error"`
-	}
-
-	cli, srv := net.Pipe()
-	defer cli.Close()
-	go ServeConn(srv)
-	dec := json.NewDecoder(cli)
-
-	// Send hand-coded requests to server, parse responses.
-	for i := 0; i < 10; i++ {
-		fmt.Fprintf(cli, `{"method": "Arith.Add", "id": "\u%04d", "params": [{"A": %d, "B": %d}]}`, i, i, i+1)
-		var resp addResp
-		err := dec.Decode(&resp)
-		if err != nil {
-			t.Fatalf("Decode: %s", err)
-		}
-		if resp.Error != nil {
-			t.Fatalf("resp.Error: %s", resp.Error)
-		}
-		if resp.Id.(string) != string(i) {
-			t.Fatalf("resp: bad id %q want %q", resp.Id.(string), string(i))
-		}
-		if resp.Result.C != 2*i+1 {
-			t.Fatalf("resp: bad result: %d+%d=%d", i, i+1, resp.Result.C)
-		}
-	}
-
-	fmt.Fprintf(cli, "{}\n")
-	var resp addResp
-	if err := dec.Decode(&resp); err != nil {
-		t.Fatalf("Decode after empty: %s", err)
-	}
-	if resp.Error == nil {
-		t.Fatalf("Expected error, got nil")
-	}
-}
-
-func TestClient(t *testing.T) {
-	// Assume server is okay (TestServer is above).
-	// Test client against server.
-	cli, srv := net.Pipe()
-	go ServeConn(srv)
-
-	client := NewClient(cli)
-	defer client.Close()
-
-	// Synchronous calls
-	args := &Args{7, 8}
-	reply := new(Reply)
-	err := client.Call("Arith.Add", args, reply)
-	if err != nil {
-		t.Errorf("Add: expected no error but got string %q", err.String())
-	}
-	if reply.C != args.A+args.B {
-		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
-	}
-
-	args = &Args{7, 8}
-	reply = new(Reply)
-	err = client.Call("Arith.Mul", args, reply)
-	if err != nil {
-		t.Errorf("Mul: expected no error but got string %q", err.String())
-	}
-	if reply.C != args.A*args.B {
-		t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
-	}
-
-	// Out of order.
-	args = &Args{7, 8}
-	mulReply := new(Reply)
-	mulCall := client.Go("Arith.Mul", args, mulReply, nil)
-	addReply := new(Reply)
-	addCall := client.Go("Arith.Add", args, addReply, nil)
-
-	addCall = <-addCall.Done
-	if addCall.Error != nil {
-		t.Errorf("Add: expected no error but got string %q", addCall.Error.String())
-	}
-	if addReply.C != args.A+args.B {
-		t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
-	}
-
-	mulCall = <-mulCall.Done
-	if mulCall.Error != nil {
-		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String())
-	}
-	if mulReply.C != args.A*args.B {
-		t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
-	}
-
-	// Error test
-	args = &Args{7, 0}
-	reply = new(Reply)
-	err = client.Call("Arith.Div", args, reply)
-	// expect an error: zero divide
-	if err == nil {
-		t.Error("Div: expected error")
-	} else if err.String() != "divide by zero" {
-		t.Error("Div: expected divide by zero error; got", err)
-	}
-}
diff --git a/src/pkg/rpc/jsonrpc/client.go b/src/pkg/rpc/jsonrpc/client.go
deleted file mode 100644
index 577d0ce..0000000
--- a/src/pkg/rpc/jsonrpc/client.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2010 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 jsonrpc implements a JSON-RPC ClientCodec and ServerCodec
-// for the rpc package.
-package jsonrpc
-
-import (
-	"fmt"
-	"io"
-	"json"
-	"net"
-	"os"
-	"rpc"
-	"sync"
-)
-
-type clientCodec struct {
-	dec *json.Decoder // for reading JSON values
-	enc *json.Encoder // for writing JSON values
-	c   io.Closer
-
-	// temporary work space
-	req  clientRequest
-	resp clientResponse
-
-	// JSON-RPC responses include the request id but not the request method.
-	// Package rpc expects both.
-	// We save the request method in pending when sending a request
-	// and then look it up by request ID when filling out the rpc Response.
-	mutex   sync.Mutex        // protects pending
-	pending map[uint64]string // map request id to method name
-}
-
-// NewClientCodec returns a new rpc.ClientCodec using JSON-RPC on conn.
-func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec {
-	return &clientCodec{
-		dec:     json.NewDecoder(conn),
-		enc:     json.NewEncoder(conn),
-		c:       conn,
-		pending: make(map[uint64]string),
-	}
-}
-
-type clientRequest struct {
-	Method string         `json:"method"`
-	Params [1]interface{} `json:"params"`
-	Id     uint64         `json:"id"`
-}
-
-func (c *clientCodec) WriteRequest(r *rpc.Request, param interface{}) os.Error {
-	c.mutex.Lock()
-	c.pending[r.Seq] = r.ServiceMethod
-	c.mutex.Unlock()
-	c.req.Method = r.ServiceMethod
-	c.req.Params[0] = param
-	c.req.Id = r.Seq
-	return c.enc.Encode(&c.req)
-}
-
-type clientResponse struct {
-	Id     uint64           `json:"id"`
-	Result *json.RawMessage `json:"result"`
-	Error  interface{}      `json:"error"`
-}
-
-func (r *clientResponse) reset() {
-	r.Id = 0
-	r.Result = nil
-	r.Error = nil
-}
-
-func (c *clientCodec) ReadResponseHeader(r *rpc.Response) os.Error {
-	c.resp.reset()
-	if err := c.dec.Decode(&c.resp); err != nil {
-		return err
-	}
-
-	c.mutex.Lock()
-	r.ServiceMethod = c.pending[c.resp.Id]
-	c.pending[c.resp.Id] = "", false
-	c.mutex.Unlock()
-
-	r.Error = ""
-	r.Seq = c.resp.Id
-	if c.resp.Error != nil {
-		x, ok := c.resp.Error.(string)
-		if !ok {
-			return fmt.Errorf("invalid error %v", c.resp.Error)
-		}
-		if x == "" {
-			x = "unspecified error"
-		}
-		r.Error = x
-	}
-	return nil
-}
-
-func (c *clientCodec) ReadResponseBody(x interface{}) os.Error {
-	if x == nil {
-		return nil
-	}
-	return json.Unmarshal(*c.resp.Result, x)
-}
-
-func (c *clientCodec) Close() os.Error {
-	return c.c.Close()
-}
-
-// NewClient returns a new rpc.Client to handle requests to the
-// set of services at the other end of the connection.
-func NewClient(conn io.ReadWriteCloser) *rpc.Client {
-	return rpc.NewClientWithCodec(NewClientCodec(conn))
-}
-
-// Dial connects to a JSON-RPC server at the specified network address.
-func Dial(network, address string) (*rpc.Client, os.Error) {
-	conn, err := net.Dial(network, address)
-	if err != nil {
-		return nil, err
-	}
-	return NewClient(conn), err
-}
diff --git a/src/pkg/rpc/jsonrpc/server.go b/src/pkg/rpc/jsonrpc/server.go
deleted file mode 100644
index 9801fdf..0000000
--- a/src/pkg/rpc/jsonrpc/server.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2010 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 jsonrpc
-
-import (
-	"io"
-	"json"
-	"os"
-	"rpc"
-	"sync"
-)
-
-type serverCodec struct {
-	dec *json.Decoder // for reading JSON values
-	enc *json.Encoder // for writing JSON values
-	c   io.Closer
-
-	// temporary work space
-	req  serverRequest
-	resp serverResponse
-
-	// JSON-RPC clients can use arbitrary json values as request IDs.
-	// Package rpc expects uint64 request IDs.
-	// We assign uint64 sequence numbers to incoming requests
-	// but save the original request ID in the pending map.
-	// When rpc responds, we use the sequence number in
-	// the response to find the original request ID.
-	mutex   sync.Mutex // protects seq, pending
-	seq     uint64
-	pending map[uint64]*json.RawMessage
-}
-
-// NewServerCodec returns a new rpc.ServerCodec using JSON-RPC on conn.
-func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {
-	return &serverCodec{
-		dec:     json.NewDecoder(conn),
-		enc:     json.NewEncoder(conn),
-		c:       conn,
-		pending: make(map[uint64]*json.RawMessage),
-	}
-}
-
-type serverRequest struct {
-	Method string           `json:"method"`
-	Params *json.RawMessage `json:"params"`
-	Id     *json.RawMessage `json:"id"`
-}
-
-func (r *serverRequest) reset() {
-	r.Method = ""
-	if r.Params != nil {
-		*r.Params = (*r.Params)[0:0]
-	}
-	if r.Id != nil {
-		*r.Id = (*r.Id)[0:0]
-	}
-}
-
-type serverResponse struct {
-	Id     *json.RawMessage `json:"id"`
-	Result interface{}      `json:"result"`
-	Error  interface{}      `json:"error"`
-}
-
-func (c *serverCodec) ReadRequestHeader(r *rpc.Request) os.Error {
-	c.req.reset()
-	if err := c.dec.Decode(&c.req); err != nil {
-		return err
-	}
-	r.ServiceMethod = c.req.Method
-
-	// JSON request id can be any JSON value;
-	// RPC package expects uint64.  Translate to
-	// internal uint64 and save JSON on the side.
-	c.mutex.Lock()
-	c.seq++
-	c.pending[c.seq] = c.req.Id
-	c.req.Id = nil
-	r.Seq = c.seq
-	c.mutex.Unlock()
-
-	return nil
-}
-
-func (c *serverCodec) ReadRequestBody(x interface{}) os.Error {
-	if x == nil {
-		return nil
-	}
-	// JSON params is array value.
-	// RPC params is struct.
-	// Unmarshal into array containing struct for now.
-	// Should think about making RPC more general.
-	var params [1]interface{}
-	params[0] = x
-	return json.Unmarshal(*c.req.Params, &params)
-}
-
-var null = json.RawMessage([]byte("null"))
-
-func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) os.Error {
-	var resp serverResponse
-	c.mutex.Lock()
-	b, ok := c.pending[r.Seq]
-	if !ok {
-		c.mutex.Unlock()
-		return os.NewError("invalid sequence number in response")
-	}
-	c.pending[r.Seq] = nil, false
-	c.mutex.Unlock()
-
-	if b == nil {
-		// Invalid request so no id.  Use JSON null.
-		b = &null
-	}
-	resp.Id = b
-	resp.Result = x
-	if r.Error == "" {
-		resp.Error = nil
-	} else {
-		resp.Error = r.Error
-	}
-	return c.enc.Encode(resp)
-}
-
-func (c *serverCodec) Close() os.Error {
-	return c.c.Close()
-}
-
-// ServeConn runs the JSON-RPC server on a single connection.
-// ServeConn blocks, serving the connection until the client hangs up.
-// The caller typically invokes ServeConn in a go statement.
-func ServeConn(conn io.ReadWriteCloser) {
-	rpc.ServeCodec(NewServerCodec(conn))
-}
diff --git a/src/pkg/rpc/server.go b/src/pkg/rpc/server.go
deleted file mode 100644
index 7450744..0000000
--- a/src/pkg/rpc/server.go
+++ /dev/null
@@ -1,637 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-	Package rpc provides access to the exported methods of an object across a
-	network or other I/O connection.  A server registers an object, making it visible
-	as a service with the name of the type of the object.  After registration, exported
-	methods of the object will be accessible remotely.  A server may register multiple
-	objects (services) of different types but it is an error to register multiple
-	objects of the same type.
-
-	Only methods that satisfy these criteria will be made available for remote access;
-	other methods will be ignored:
-
-		- the method name is exported, that is, begins with an upper case letter.
-		- the method receiver is exported or local (defined in the package
-		  registering the service).
-		- the method has two arguments, both exported or local types.
-		- the method's second argument is a pointer.
-		- the method has return type os.Error.
-
-	The method's first argument represents the arguments provided by the caller; the
-	second argument represents the result parameters to be returned to the caller.
-	The method's return value, if non-nil, is passed back as a string that the client
-	sees as an os.ErrorString.
-
-	The server may handle requests on a single connection by calling ServeConn.  More
-	typically it will create a network listener and call Accept or, for an HTTP
-	listener, HandleHTTP and http.Serve.
-
-	A client wishing to use the service establishes a connection and then invokes
-	NewClient on the connection.  The convenience function Dial (DialHTTP) performs
-	both steps for a raw network connection (an HTTP connection).  The resulting
-	Client object has two methods, Call and Go, that specify the service and method to
-	call, a pointer containing the arguments, and a pointer to receive the result
-	parameters.
-
-	Call waits for the remote call to complete; Go launches the call asynchronously
-	and returns a channel that will signal completion.
-
-	Package "gob" is used to transport the data.
-
-	Here is a simple example.  A server wishes to export an object of type Arith:
-
-		package server
-
-		type Args struct {
-			A, B int
-		}
-
-		type Quotient struct {
-			Quo, Rem int
-		}
-
-		type Arith int
-
-		func (t *Arith) Multiply(args *Args, reply *int) os.Error {
-			*reply = args.A * args.B
-			return nil
-		}
-
-		func (t *Arith) Divide(args *Args, quo *Quotient) os.Error {
-			if args.B == 0 {
-				return os.ErrorString("divide by zero")
-			}
-			quo.Quo = args.A / args.B
-			quo.Rem = args.A % args.B
-			return nil
-		}
-
-	The server calls (for HTTP service):
-
-		arith := new(Arith)
-		rpc.Register(arith)
-		rpc.HandleHTTP()
-		l, e := net.Listen("tcp", ":1234")
-		if e != nil {
-			log.Fatal("listen error:", e)
-		}
-		go http.Serve(l, nil)
-
-	At this point, clients can see a service "Arith" with methods "Arith.Multiply" and
-	"Arith.Divide".  To invoke one, a client first dials the server:
-
-		client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
-		if err != nil {
-			log.Fatal("dialing:", err)
-		}
-
-	Then it can make a remote call:
-
-		// Synchronous call
-		args := &server.Args{7,8}
-		var reply int
-		err = client.Call("Arith.Multiply", args, &reply)
-		if err != nil {
-			log.Fatal("arith error:", err)
-		}
-		fmt.Printf("Arith: %d*%d=%d", args.A, args.B, *reply)
-
-	or
-
-		// Asynchronous call
-		quotient := new(Quotient)
-		divCall := client.Go("Arith.Divide", args, &quotient, nil)
-		replyCall := <-divCall.Done	// will be equal to divCall
-		// check errors, print, etc.
-
-	A server implementation will often provide a simple, type-safe wrapper for the
-	client.
-*/
-package rpc
-
-import (
-	"bufio"
-	"gob"
-	"http"
-	"log"
-	"io"
-	"net"
-	"os"
-	"reflect"
-	"strings"
-	"sync"
-	"unicode"
-	"utf8"
-)
-
-const (
-	// Defaults used by HandleHTTP
-	DefaultRPCPath   = "/_goRPC_"
-	DefaultDebugPath = "/debug/rpc"
-)
-
-// Precompute the reflect type for os.Error.  Can't use os.Error directly
-// because Typeof takes an empty interface value.  This is annoying.
-var unusedError *os.Error
-var typeOfOsError = reflect.TypeOf(unusedError).Elem()
-
-type methodType struct {
-	sync.Mutex // protects counters
-	method     reflect.Method
-	ArgType    reflect.Type
-	ReplyType  reflect.Type
-	numCalls   uint
-}
-
-type service struct {
-	name   string                 // name of service
-	rcvr   reflect.Value          // receiver of methods for the service
-	typ    reflect.Type           // type of the receiver
-	method map[string]*methodType // registered methods
-}
-
-// Request is a header written before every RPC call.  It is used internally
-// but documented here as an aid to debugging, such as when analyzing
-// network traffic.
-type Request struct {
-	ServiceMethod string   // format: "Service.Method"
-	Seq           uint64   // sequence number chosen by client
-	next          *Request // for free list in Server
-}
-
-// Response is a header written before every RPC return.  It is used internally
-// but documented here as an aid to debugging, such as when analyzing
-// network traffic.
-type Response struct {
-	ServiceMethod string    // echoes that of the Request
-	Seq           uint64    // echoes that of the request
-	Error         string    // error, if any.
-	next          *Response // for free list in Server
-}
-
-// Server represents an RPC Server.
-type Server struct {
-	mu         sync.Mutex // protects the serviceMap
-	serviceMap map[string]*service
-	reqLock    sync.Mutex // protects freeReq
-	freeReq    *Request
-	respLock   sync.Mutex // protects freeResp
-	freeResp   *Response
-}
-
-// NewServer returns a new Server.
-func NewServer() *Server {
-	return &Server{serviceMap: make(map[string]*service)}
-}
-
-// DefaultServer is the default instance of *Server.
-var DefaultServer = NewServer()
-
-// Is this an exported - upper case - name?
-func isExported(name string) bool {
-	rune, _ := utf8.DecodeRuneInString(name)
-	return unicode.IsUpper(rune)
-}
-
-// Is this type exported or a builtin?
-func isExportedOrBuiltinType(t reflect.Type) bool {
-	for t.Kind() == reflect.Ptr {
-		t = t.Elem()
-	}
-	// PkgPath will be non-empty even for an exported type,
-	// so we need to check the type name as well.
-	return isExported(t.Name()) || t.PkgPath() == ""
-}
-
-// Register publishes in the server the set of methods of the
-// receiver value that satisfy the following conditions:
-//	- exported method
-//	- two arguments, both pointers to exported structs
-//	- one return value, of type os.Error
-// It returns an error if the receiver is not an exported type or has no
-// suitable methods.
-// The client accesses each method using a string of the form "Type.Method",
-// where Type is the receiver's concrete type.
-func (server *Server) Register(rcvr interface{}) os.Error {
-	return server.register(rcvr, "", false)
-}
-
-// RegisterName is like Register but uses the provided name for the type 
-// instead of the receiver's concrete type.
-func (server *Server) RegisterName(name string, rcvr interface{}) os.Error {
-	return server.register(rcvr, name, true)
-}
-
-func (server *Server) register(rcvr interface{}, name string, useName bool) os.Error {
-	server.mu.Lock()
-	defer server.mu.Unlock()
-	if server.serviceMap == nil {
-		server.serviceMap = make(map[string]*service)
-	}
-	s := new(service)
-	s.typ = reflect.TypeOf(rcvr)
-	s.rcvr = reflect.ValueOf(rcvr)
-	sname := reflect.Indirect(s.rcvr).Type().Name()
-	if useName {
-		sname = name
-	}
-	if sname == "" {
-		log.Fatal("rpc: no service name for type", s.typ.String())
-	}
-	if !isExported(sname) && !useName {
-		s := "rpc Register: type " + sname + " is not exported"
-		log.Print(s)
-		return os.NewError(s)
-	}
-	if _, present := server.serviceMap[sname]; present {
-		return os.NewError("rpc: service already defined: " + sname)
-	}
-	s.name = sname
-	s.method = make(map[string]*methodType)
-
-	// Install the methods
-	for m := 0; m < s.typ.NumMethod(); m++ {
-		method := s.typ.Method(m)
-		mtype := method.Type
-		mname := method.Name
-		if method.PkgPath != "" {
-			continue
-		}
-		// Method needs three ins: receiver, *args, *reply.
-		if mtype.NumIn() != 3 {
-			log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
-			continue
-		}
-		// First arg need not be a pointer.
-		argType := mtype.In(1)
-		if !isExportedOrBuiltinType(argType) {
-			log.Println(mname, "argument type not exported or local:", argType)
-			continue
-		}
-		// Second arg must be a pointer.
-		replyType := mtype.In(2)
-		if replyType.Kind() != reflect.Ptr {
-			log.Println("method", mname, "reply type not a pointer:", replyType)
-			continue
-		}
-		if !isExportedOrBuiltinType(replyType) {
-			log.Println("method", mname, "reply type not exported or local:", replyType)
-			continue
-		}
-		// Method needs one out: os.Error.
-		if mtype.NumOut() != 1 {
-			log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
-			continue
-		}
-		if returnType := mtype.Out(0); returnType != typeOfOsError {
-			log.Println("method", mname, "returns", returnType.String(), "not os.Error")
-			continue
-		}
-		s.method[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
-	}
-
-	if len(s.method) == 0 {
-		s := "rpc Register: type " + sname + " has no exported methods of suitable type"
-		log.Print(s)
-		return os.NewError(s)
-	}
-	server.serviceMap[s.name] = s
-	return nil
-}
-
-// A value sent as a placeholder for the response when the server receives an invalid request.
-type InvalidRequest struct{}
-
-var invalidRequest = InvalidRequest{}
-
-func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec ServerCodec, errmsg string) {
-	resp := server.getResponse()
-	// Encode the response header
-	resp.ServiceMethod = req.ServiceMethod
-	if errmsg != "" {
-		resp.Error = errmsg
-		reply = invalidRequest
-	}
-	resp.Seq = req.Seq
-	sending.Lock()
-	err := codec.WriteResponse(resp, reply)
-	if err != nil {
-		log.Println("rpc: writing response:", err)
-	}
-	sending.Unlock()
-	server.freeResponse(resp)
-}
-
-func (m *methodType) NumCalls() (n uint) {
-	m.Lock()
-	n = m.numCalls
-	m.Unlock()
-	return n
-}
-
-func (s *service) call(server *Server, sending *sync.Mutex, mtype *methodType, req *Request, argv, replyv reflect.Value, codec ServerCodec) {
-	mtype.Lock()
-	mtype.numCalls++
-	mtype.Unlock()
-	function := mtype.method.Func
-	// Invoke the method, providing a new value for the reply.
-	returnValues := function.Call([]reflect.Value{s.rcvr, argv, replyv})
-	// The return value for the method is an os.Error.
-	errInter := returnValues[0].Interface()
-	errmsg := ""
-	if errInter != nil {
-		errmsg = errInter.(os.Error).String()
-	}
-	server.sendResponse(sending, req, replyv.Interface(), codec, errmsg)
-	server.freeRequest(req)
-}
-
-type gobServerCodec struct {
-	rwc    io.ReadWriteCloser
-	dec    *gob.Decoder
-	enc    *gob.Encoder
-	encBuf *bufio.Writer
-}
-
-func (c *gobServerCodec) ReadRequestHeader(r *Request) os.Error {
-	return c.dec.Decode(r)
-}
-
-func (c *gobServerCodec) ReadRequestBody(body interface{}) os.Error {
-	return c.dec.Decode(body)
-}
-
-func (c *gobServerCodec) WriteResponse(r *Response, body interface{}) (err os.Error) {
-	if err = c.enc.Encode(r); err != nil {
-		return
-	}
-	if err = c.enc.Encode(body); err != nil {
-		return
-	}
-	return c.encBuf.Flush()
-}
-
-func (c *gobServerCodec) Close() os.Error {
-	return c.rwc.Close()
-}
-
-// ServeConn runs the server on a single connection.
-// ServeConn blocks, serving the connection until the client hangs up.
-// The caller typically invokes ServeConn in a go statement.
-// ServeConn uses the gob wire format (see package gob) on the
-// connection.  To use an alternate codec, use ServeCodec.
-func (server *Server) ServeConn(conn io.ReadWriteCloser) {
-	buf := bufio.NewWriter(conn)
-	srv := &gobServerCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(buf), buf}
-	server.ServeCodec(srv)
-}
-
-// ServeCodec is like ServeConn but uses the specified codec to
-// decode requests and encode responses.
-func (server *Server) ServeCodec(codec ServerCodec) {
-	sending := new(sync.Mutex)
-	for {
-		service, mtype, req, argv, replyv, err := server.readRequest(codec)
-		if err != nil {
-			if err != os.EOF {
-				log.Println("rpc:", err)
-			}
-			if err == os.EOF || err == io.ErrUnexpectedEOF {
-				break
-			}
-			// send a response if we actually managed to read a header.
-			if req != nil {
-				server.sendResponse(sending, req, invalidRequest, codec, err.String())
-				server.freeRequest(req)
-			}
-			continue
-		}
-		go service.call(server, sending, mtype, req, argv, replyv, codec)
-	}
-	codec.Close()
-}
-
-// ServeRequest is like ServeCodec but synchronously serves a single request.
-// It does not close the codec upon completion.
-func (server *Server) ServeRequest(codec ServerCodec) os.Error {
-	sending := new(sync.Mutex)
-	service, mtype, req, argv, replyv, err := server.readRequest(codec)
-	if err != nil {
-		if err == os.EOF || err == io.ErrUnexpectedEOF {
-			return err
-		}
-		// send a response if we actually managed to read a header.
-		if req != nil {
-			server.sendResponse(sending, req, invalidRequest, codec, err.String())
-			server.freeRequest(req)
-		}
-		return err
-	}
-	service.call(server, sending, mtype, req, argv, replyv, codec)
-	return nil
-}
-
-func (server *Server) getRequest() *Request {
-	server.reqLock.Lock()
-	req := server.freeReq
-	if req == nil {
-		req = new(Request)
-	} else {
-		server.freeReq = req.next
-		*req = Request{}
-	}
-	server.reqLock.Unlock()
-	return req
-}
-
-func (server *Server) freeRequest(req *Request) {
-	server.reqLock.Lock()
-	req.next = server.freeReq
-	server.freeReq = req
-	server.reqLock.Unlock()
-}
-
-func (server *Server) getResponse() *Response {
-	server.respLock.Lock()
-	resp := server.freeResp
-	if resp == nil {
-		resp = new(Response)
-	} else {
-		server.freeResp = resp.next
-		*resp = Response{}
-	}
-	server.respLock.Unlock()
-	return resp
-}
-
-func (server *Server) freeResponse(resp *Response) {
-	server.respLock.Lock()
-	resp.next = server.freeResp
-	server.freeResp = resp
-	server.respLock.Unlock()
-}
-
-func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, err os.Error) {
-	service, mtype, req, err = server.readRequestHeader(codec)
-	if err != nil {
-		if err == os.EOF || err == io.ErrUnexpectedEOF {
-			return
-		}
-		// discard body
-		codec.ReadRequestBody(nil)
-		return
-	}
-
-	// Decode the argument value.
-	argIsValue := false // if true, need to indirect before calling.
-	if mtype.ArgType.Kind() == reflect.Ptr {
-		argv = reflect.New(mtype.ArgType.Elem())
-	} else {
-		argv = reflect.New(mtype.ArgType)
-		argIsValue = true
-	}
-	// argv guaranteed to be a pointer now.
-	if err = codec.ReadRequestBody(argv.Interface()); err != nil {
-		return
-	}
-	if argIsValue {
-		argv = argv.Elem()
-	}
-
-	replyv = reflect.New(mtype.ReplyType.Elem())
-	return
-}
-
-func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, err os.Error) {
-	// Grab the request header.
-	req = server.getRequest()
-	err = codec.ReadRequestHeader(req)
-	if err != nil {
-		req = nil
-		if err == os.EOF || err == io.ErrUnexpectedEOF {
-			return
-		}
-		err = os.NewError("rpc: server cannot decode request: " + err.String())
-		return
-	}
-
-	serviceMethod := strings.Split(req.ServiceMethod, ".")
-	if len(serviceMethod) != 2 {
-		err = os.NewError("rpc: service/method request ill-formed: " + req.ServiceMethod)
-		return
-	}
-	// Look up the request.
-	server.mu.Lock()
-	service = server.serviceMap[serviceMethod[0]]
-	server.mu.Unlock()
-	if service == nil {
-		err = os.NewError("rpc: can't find service " + req.ServiceMethod)
-		return
-	}
-	mtype = service.method[serviceMethod[1]]
-	if mtype == nil {
-		err = os.NewError("rpc: can't find method " + req.ServiceMethod)
-	}
-	return
-}
-
-// Accept accepts connections on the listener and serves requests
-// for each incoming connection.  Accept blocks; the caller typically
-// invokes it in a go statement.
-func (server *Server) Accept(lis net.Listener) {
-	for {
-		conn, err := lis.Accept()
-		if err != nil {
-			log.Fatal("rpc.Serve: accept:", err.String()) // TODO(r): exit?
-		}
-		go server.ServeConn(conn)
-	}
-}
-
-// Register publishes the receiver's methods in the DefaultServer.
-func Register(rcvr interface{}) os.Error { return DefaultServer.Register(rcvr) }
-
-// RegisterName is like Register but uses the provided name for the type 
-// instead of the receiver's concrete type.
-func RegisterName(name string, rcvr interface{}) os.Error {
-	return DefaultServer.RegisterName(name, rcvr)
-}
-
-// A ServerCodec implements reading of RPC requests and writing of
-// RPC responses for the server side of an RPC session.
-// The server calls ReadRequestHeader and ReadRequestBody in pairs
-// to read requests from the connection, and it calls WriteResponse to
-// write a response back.  The server calls Close when finished with the
-// connection. ReadRequestBody may be called with a nil
-// argument to force the body of the request to be read and discarded.
-type ServerCodec interface {
-	ReadRequestHeader(*Request) os.Error
-	ReadRequestBody(interface{}) os.Error
-	WriteResponse(*Response, interface{}) os.Error
-
-	Close() os.Error
-}
-
-// ServeConn runs the DefaultServer on a single connection.
-// ServeConn blocks, serving the connection until the client hangs up.
-// The caller typically invokes ServeConn in a go statement.
-// ServeConn uses the gob wire format (see package gob) on the
-// connection.  To use an alternate codec, use ServeCodec.
-func ServeConn(conn io.ReadWriteCloser) {
-	DefaultServer.ServeConn(conn)
-}
-
-// ServeCodec is like ServeConn but uses the specified codec to
-// decode requests and encode responses.
-func ServeCodec(codec ServerCodec) {
-	DefaultServer.ServeCodec(codec)
-}
-
-// ServeRequest is like ServeCodec but synchronously serves a single request.
-// It does not close the codec upon completion.
-func ServeRequest(codec ServerCodec) os.Error {
-	return DefaultServer.ServeRequest(codec)
-}
-
-// Accept accepts connections on the listener and serves requests
-// to DefaultServer for each incoming connection.  
-// Accept blocks; the caller typically invokes it in a go statement.
-func Accept(lis net.Listener) { DefaultServer.Accept(lis) }
-
-// Can connect to RPC service using HTTP CONNECT to rpcPath.
-var connected = "200 Connected to Go RPC"
-
-// ServeHTTP implements an http.Handler that answers RPC requests.
-func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
-	if req.Method != "CONNECT" {
-		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-		w.WriteHeader(http.StatusMethodNotAllowed)
-		io.WriteString(w, "405 must CONNECT\n")
-		return
-	}
-	conn, _, err := w.(http.Hijacker).Hijack()
-	if err != nil {
-		log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.String())
-		return
-	}
-	io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n")
-	server.ServeConn(conn)
-}
-
-// HandleHTTP registers an HTTP handler for RPC messages on rpcPath,
-// and a debugging handler on debugPath.
-// It is still necessary to invoke http.Serve(), typically in a go statement.
-func (server *Server) HandleHTTP(rpcPath, debugPath string) {
-	http.Handle(rpcPath, server)
-	http.Handle(debugPath, debugHTTP{server})
-}
-
-// HandleHTTP registers an HTTP handler for RPC messages to DefaultServer
-// on DefaultRPCPath and a debugging handler on DefaultDebugPath.
-// It is still necessary to invoke http.Serve(), typically in a go statement.
-func HandleHTTP() {
-	DefaultServer.HandleHTTP(DefaultRPCPath, DefaultDebugPath)
-}
diff --git a/src/pkg/rpc/server_test.go b/src/pkg/rpc/server_test.go
deleted file mode 100644
index cb2db2a..0000000
--- a/src/pkg/rpc/server_test.go
+++ /dev/null
@@ -1,570 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package rpc
-
-import (
-	"fmt"
-	"http/httptest"
-	"io"
-	"log"
-	"net"
-	"os"
-	"runtime"
-	"strings"
-	"sync"
-	"sync/atomic"
-	"testing"
-	"time"
-)
-
-var (
-	newServer                 *Server
-	serverAddr, newServerAddr string
-	httpServerAddr            string
-	once, newOnce, httpOnce   sync.Once
-)
-
-const (
-	second      = 1e9
-	newHttpPath = "/foo"
-)
-
-type Args struct {
-	A, B int
-}
-
-type Reply struct {
-	C int
-}
-
-type Arith int
-
-// Some of Arith's methods have value args, some have pointer args. That's deliberate.
-
-func (t *Arith) Add(args Args, reply *Reply) os.Error {
-	reply.C = args.A + args.B
-	return nil
-}
-
-func (t *Arith) Mul(args *Args, reply *Reply) os.Error {
-	reply.C = args.A * args.B
-	return nil
-}
-
-func (t *Arith) Div(args Args, reply *Reply) os.Error {
-	if args.B == 0 {
-		return os.NewError("divide by zero")
-	}
-	reply.C = args.A / args.B
-	return nil
-}
-
-func (t *Arith) String(args *Args, reply *string) os.Error {
-	*reply = fmt.Sprintf("%d+%d=%d", args.A, args.B, args.A+args.B)
-	return nil
-}
-
-func (t *Arith) Scan(args string, reply *Reply) (err os.Error) {
-	_, err = fmt.Sscan(args, &reply.C)
-	return
-}
-
-func (t *Arith) Error(args *Args, reply *Reply) os.Error {
-	panic("ERROR")
-}
-
-func listenTCP() (net.Listener, string) {
-	l, e := net.Listen("tcp", "127.0.0.1:0") // any available address
-	if e != nil {
-		log.Fatalf("net.Listen tcp :0: %v", e)
-	}
-	return l, l.Addr().String()
-}
-
-func startServer() {
-	Register(new(Arith))
-
-	var l net.Listener
-	l, serverAddr = listenTCP()
-	log.Println("Test RPC server listening on", serverAddr)
-	go Accept(l)
-
-	HandleHTTP()
-	httpOnce.Do(startHttpServer)
-}
-
-func startNewServer() {
-	newServer = NewServer()
-	newServer.Register(new(Arith))
-
-	var l net.Listener
-	l, newServerAddr = listenTCP()
-	log.Println("NewServer test RPC server listening on", newServerAddr)
-	go Accept(l)
-
-	newServer.HandleHTTP(newHttpPath, "/bar")
-	httpOnce.Do(startHttpServer)
-}
-
-func startHttpServer() {
-	server := httptest.NewServer(nil)
-	httpServerAddr = server.Listener.Addr().String()
-	log.Println("Test HTTP RPC server listening on", httpServerAddr)
-}
-
-func TestRPC(t *testing.T) {
-	once.Do(startServer)
-	testRPC(t, serverAddr)
-	newOnce.Do(startNewServer)
-	testRPC(t, newServerAddr)
-}
-
-func testRPC(t *testing.T, addr string) {
-	client, err := Dial("tcp", addr)
-	if err != nil {
-		t.Fatal("dialing", err)
-	}
-
-	// Synchronous calls
-	args := &Args{7, 8}
-	reply := new(Reply)
-	err = client.Call("Arith.Add", args, reply)
-	if err != nil {
-		t.Errorf("Add: expected no error but got string %q", err.String())
-	}
-	if reply.C != args.A+args.B {
-		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
-	}
-
-	// Nonexistent method
-	args = &Args{7, 0}
-	reply = new(Reply)
-	err = client.Call("Arith.BadOperation", args, reply)
-	// expect an error
-	if err == nil {
-		t.Error("BadOperation: expected error")
-	} else if !strings.HasPrefix(err.String(), "rpc: can't find method ") {
-		t.Errorf("BadOperation: expected can't find method error; got %q", err)
-	}
-
-	// Unknown service
-	args = &Args{7, 8}
-	reply = new(Reply)
-	err = client.Call("Arith.Unknown", args, reply)
-	if err == nil {
-		t.Error("expected error calling unknown service")
-	} else if strings.Index(err.String(), "method") < 0 {
-		t.Error("expected error about method; got", err)
-	}
-
-	// Out of order.
-	args = &Args{7, 8}
-	mulReply := new(Reply)
-	mulCall := client.Go("Arith.Mul", args, mulReply, nil)
-	addReply := new(Reply)
-	addCall := client.Go("Arith.Add", args, addReply, nil)
-
-	addCall = <-addCall.Done
-	if addCall.Error != nil {
-		t.Errorf("Add: expected no error but got string %q", addCall.Error.String())
-	}
-	if addReply.C != args.A+args.B {
-		t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
-	}
-
-	mulCall = <-mulCall.Done
-	if mulCall.Error != nil {
-		t.Errorf("Mul: expected no error but got string %q", mulCall.Error.String())
-	}
-	if mulReply.C != args.A*args.B {
-		t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
-	}
-
-	// Error test
-	args = &Args{7, 0}
-	reply = new(Reply)
-	err = client.Call("Arith.Div", args, reply)
-	// expect an error: zero divide
-	if err == nil {
-		t.Error("Div: expected error")
-	} else if err.String() != "divide by zero" {
-		t.Error("Div: expected divide by zero error; got", err)
-	}
-
-	// Bad type.
-	reply = new(Reply)
-	err = client.Call("Arith.Add", reply, reply) // args, reply would be the correct thing to use
-	if err == nil {
-		t.Error("expected error calling Arith.Add with wrong arg type")
-	} else if strings.Index(err.String(), "type") < 0 {
-		t.Error("expected error about type; got", err)
-	}
-
-	// Non-struct argument
-	const Val = 12345
-	str := fmt.Sprint(Val)
-	reply = new(Reply)
-	err = client.Call("Arith.Scan", &str, reply)
-	if err != nil {
-		t.Errorf("Scan: expected no error but got string %q", err.String())
-	} else if reply.C != Val {
-		t.Errorf("Scan: expected %d got %d", Val, reply.C)
-	}
-
-	// Non-struct reply
-	args = &Args{27, 35}
-	str = ""
-	err = client.Call("Arith.String", args, &str)
-	if err != nil {
-		t.Errorf("String: expected no error but got string %q", err.String())
-	}
-	expect := fmt.Sprintf("%d+%d=%d", args.A, args.B, args.A+args.B)
-	if str != expect {
-		t.Errorf("String: expected %s got %s", expect, str)
-	}
-
-	args = &Args{7, 8}
-	reply = new(Reply)
-	err = client.Call("Arith.Mul", args, reply)
-	if err != nil {
-		t.Errorf("Mul: expected no error but got string %q", err.String())
-	}
-	if reply.C != args.A*args.B {
-		t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
-	}
-}
-
-func TestHTTP(t *testing.T) {
-	once.Do(startServer)
-	testHTTPRPC(t, "")
-	newOnce.Do(startNewServer)
-	testHTTPRPC(t, newHttpPath)
-}
-
-func testHTTPRPC(t *testing.T, path string) {
-	var client *Client
-	var err os.Error
-	if path == "" {
-		client, err = DialHTTP("tcp", httpServerAddr)
-	} else {
-		client, err = DialHTTPPath("tcp", httpServerAddr, path)
-	}
-	if err != nil {
-		t.Fatal("dialing", err)
-	}
-
-	// Synchronous calls
-	args := &Args{7, 8}
-	reply := new(Reply)
-	err = client.Call("Arith.Add", args, reply)
-	if err != nil {
-		t.Errorf("Add: expected no error but got string %q", err.String())
-	}
-	if reply.C != args.A+args.B {
-		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
-	}
-}
-
-// CodecEmulator provides a client-like api and a ServerCodec interface.
-// Can be used to test ServeRequest.
-type CodecEmulator struct {
-	server        *Server
-	serviceMethod string
-	args          *Args
-	reply         *Reply
-	err           os.Error
-}
-
-func (codec *CodecEmulator) Call(serviceMethod string, args *Args, reply *Reply) os.Error {
-	codec.serviceMethod = serviceMethod
-	codec.args = args
-	codec.reply = reply
-	codec.err = nil
-	var serverError os.Error
-	if codec.server == nil {
-		serverError = ServeRequest(codec)
-	} else {
-		serverError = codec.server.ServeRequest(codec)
-	}
-	if codec.err == nil && serverError != nil {
-		codec.err = serverError
-	}
-	return codec.err
-}
-
-func (codec *CodecEmulator) ReadRequestHeader(req *Request) os.Error {
-	req.ServiceMethod = codec.serviceMethod
-	req.Seq = 0
-	return nil
-}
-
-func (codec *CodecEmulator) ReadRequestBody(argv interface{}) os.Error {
-	if codec.args == nil {
-		return io.ErrUnexpectedEOF
-	}
-	*(argv.(*Args)) = *codec.args
-	return nil
-}
-
-func (codec *CodecEmulator) WriteResponse(resp *Response, reply interface{}) os.Error {
-	if resp.Error != "" {
-		codec.err = os.NewError(resp.Error)
-	}
-	*codec.reply = *(reply.(*Reply))
-	return nil
-}
-
-func (codec *CodecEmulator) Close() os.Error {
-	return nil
-}
-
-func TestServeRequest(t *testing.T) {
-	once.Do(startServer)
-	testServeRequest(t, nil)
-	newOnce.Do(startNewServer)
-	testServeRequest(t, newServer)
-}
-
-func testServeRequest(t *testing.T, server *Server) {
-	client := CodecEmulator{server: server}
-
-	args := &Args{7, 8}
-	reply := new(Reply)
-	err := client.Call("Arith.Add", args, reply)
-	if err != nil {
-		t.Errorf("Add: expected no error but got string %q", err.String())
-	}
-	if reply.C != args.A+args.B {
-		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
-	}
-
-	err = client.Call("Arith.Add", nil, reply)
-	if err == nil {
-		t.Errorf("expected error calling Arith.Add with nil arg")
-	}
-}
-
-type ReplyNotPointer int
-type ArgNotPublic int
-type ReplyNotPublic int
-type local struct{}
-
-func (t *ReplyNotPointer) ReplyNotPointer(args *Args, reply Reply) os.Error {
-	return nil
-}
-
-func (t *ArgNotPublic) ArgNotPublic(args *local, reply *Reply) os.Error {
-	return nil
-}
-
-func (t *ReplyNotPublic) ReplyNotPublic(args *Args, reply *local) os.Error {
-	return nil
-}
-
-// Check that registration handles lots of bad methods and a type with no suitable methods.
-func TestRegistrationError(t *testing.T) {
-	err := Register(new(ReplyNotPointer))
-	if err == nil {
-		t.Errorf("expected error registering ReplyNotPointer")
-	}
-	err = Register(new(ArgNotPublic))
-	if err == nil {
-		t.Errorf("expected error registering ArgNotPublic")
-	}
-	err = Register(new(ReplyNotPublic))
-	if err == nil {
-		t.Errorf("expected error registering ReplyNotPublic")
-	}
-}
-
-type WriteFailCodec int
-
-func (WriteFailCodec) WriteRequest(*Request, interface{}) os.Error {
-	// the panic caused by this error used to not unlock a lock.
-	return os.NewError("fail")
-}
-
-func (WriteFailCodec) ReadResponseHeader(*Response) os.Error {
-	time.Sleep(120e9)
-	panic("unreachable")
-}
-
-func (WriteFailCodec) ReadResponseBody(interface{}) os.Error {
-	time.Sleep(120e9)
-	panic("unreachable")
-}
-
-func (WriteFailCodec) Close() os.Error {
-	return nil
-}
-
-func TestSendDeadlock(t *testing.T) {
-	client := NewClientWithCodec(WriteFailCodec(0))
-
-	done := make(chan bool)
-	go func() {
-		testSendDeadlock(client)
-		testSendDeadlock(client)
-		done <- true
-	}()
-	select {
-	case <-done:
-		return
-	case <-time.After(5e9):
-		t.Fatal("deadlock")
-	}
-}
-
-func testSendDeadlock(client *Client) {
-	defer func() {
-		recover()
-	}()
-	args := &Args{7, 8}
-	reply := new(Reply)
-	client.Call("Arith.Add", args, reply)
-}
-
-func dialDirect() (*Client, os.Error) {
-	return Dial("tcp", serverAddr)
-}
-
-func dialHTTP() (*Client, os.Error) {
-	return DialHTTP("tcp", httpServerAddr)
-}
-
-func countMallocs(dial func() (*Client, os.Error), t *testing.T) uint64 {
-	once.Do(startServer)
-	client, err := dial()
-	if err != nil {
-		t.Fatal("error dialing", err)
-	}
-	args := &Args{7, 8}
-	reply := new(Reply)
-	runtime.UpdateMemStats()
-	mallocs := 0 - runtime.MemStats.Mallocs
-	const count = 100
-	for i := 0; i < count; i++ {
-		err := client.Call("Arith.Add", args, reply)
-		if err != nil {
-			t.Errorf("Add: expected no error but got string %q", err.String())
-		}
-		if reply.C != args.A+args.B {
-			t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
-		}
-	}
-	runtime.UpdateMemStats()
-	mallocs += runtime.MemStats.Mallocs
-	return mallocs / count
-}
-
-func TestCountMallocs(t *testing.T) {
-	fmt.Printf("mallocs per rpc round trip: %d\n", countMallocs(dialDirect, t))
-}
-
-func TestCountMallocsOverHTTP(t *testing.T) {
-	fmt.Printf("mallocs per HTTP rpc round trip: %d\n", countMallocs(dialHTTP, t))
-}
-
-func benchmarkEndToEnd(dial func() (*Client, os.Error), b *testing.B) {
-	b.StopTimer()
-	once.Do(startServer)
-	client, err := dial()
-	if err != nil {
-		fmt.Println("error dialing", err)
-		return
-	}
-
-	// Synchronous calls
-	args := &Args{7, 8}
-	procs := runtime.GOMAXPROCS(-1)
-	N := int32(b.N)
-	var wg sync.WaitGroup
-	wg.Add(procs)
-	b.StartTimer()
-
-	for p := 0; p < procs; p++ {
-		go func() {
-			reply := new(Reply)
-			for atomic.AddInt32(&N, -1) >= 0 {
-				err = client.Call("Arith.Add", args, reply)
-				if err != nil {
-					fmt.Printf("Add: expected no error but got string %q", err.String())
-					panic("rpc error")
-				}
-				if reply.C != args.A+args.B {
-					fmt.Printf("Add: expected %d got %d", reply.C, args.A+args.B)
-					panic("rpc error")
-				}
-			}
-			wg.Done()
-		}()
-	}
-	wg.Wait()
-}
-
-func benchmarkEndToEndAsync(dial func() (*Client, os.Error), b *testing.B) {
-	const MaxConcurrentCalls = 100
-	b.StopTimer()
-	once.Do(startServer)
-	client, err := dial()
-	if err != nil {
-		fmt.Println("error dialing", err)
-		return
-	}
-
-	// Asynchronous calls
-	args := &Args{7, 8}
-	procs := 4 * runtime.GOMAXPROCS(-1)
-	send := int32(b.N)
-	recv := int32(b.N)
-	var wg sync.WaitGroup
-	wg.Add(procs)
-	gate := make(chan bool, MaxConcurrentCalls)
-	res := make(chan *Call, MaxConcurrentCalls)
-	b.StartTimer()
-
-	for p := 0; p < procs; p++ {
-		go func() {
-			for atomic.AddInt32(&send, -1) >= 0 {
-				gate <- true
-				reply := new(Reply)
-				client.Go("Arith.Add", args, reply, res)
-			}
-		}()
-		go func() {
-			for call := range res {
-				a := call.Args.(*Args).A
-				b := call.Args.(*Args).B
-				c := call.Reply.(*Reply).C
-				if a+b != c {
-					fmt.Printf("Add: expected %d got %d", a+b, c)
-					panic("incorrect reply")
-				}
-				<-gate
-				if atomic.AddInt32(&recv, -1) == 0 {
-					close(res)
-				}
-			}
-			wg.Done()
-		}()
-	}
-	wg.Wait()
-}
-
-func BenchmarkEndToEnd(b *testing.B) {
-	benchmarkEndToEnd(dialDirect, b)
-}
-
-func BenchmarkEndToEndHTTP(b *testing.B) {
-	benchmarkEndToEnd(dialHTTP, b)
-}
-
-func BenchmarkEndToEndAsync(b *testing.B) {
-	benchmarkEndToEndAsync(dialDirect, b)
-}
-
-func BenchmarkEndToEndAsyncHTTP(b *testing.B) {
-	benchmarkEndToEndAsync(dialHTTP, b)
-}
diff --git a/src/pkg/runtime/386/arch.h b/src/pkg/runtime/386/arch.h
deleted file mode 100644
index d95c7aa..0000000
--- a/src/pkg/runtime/386/arch.h
+++ /dev/null
@@ -1,3 +0,0 @@
-enum {
-	thechar = '8'
-};
diff --git a/src/pkg/runtime/386/asm.s b/src/pkg/runtime/386/asm.s
deleted file mode 100644
index c64e78f..0000000
--- a/src/pkg/runtime/386/asm.s
+++ /dev/null
@@ -1,549 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "386/asm.h"
-
-TEXT _rt0_386(SB),7,$0
-	// Linux, Windows start the FPU in extended double precision.
-	// Other operating systems use double precision.
-	// Change to double precision to match them,
-	// and to match other hardware that only has double.
-	PUSHL $0x27F
-	FLDCW	0(SP)
-	POPL AX
-
-	// copy arguments forward on an even stack
-	MOVL	0(SP), AX		// argc
-	LEAL	4(SP), BX		// argv
-	SUBL	$128, SP		// plenty of scratch
-	ANDL	$~15, SP
-	MOVL	AX, 120(SP)		// save argc, argv away
-	MOVL	BX, 124(SP)
-
-	// if there is an initcgo, call it to let it
-	// initialize and to set up GS.  if not,
-	// we set up GS ourselves.
-	MOVL	initcgo(SB), AX
-	TESTL	AX, AX
-	JZ	4(PC)
-	CALL	AX
-	// skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows
-	CMPL runtime·iswindows(SB), $0
-	JEQ ok
-
-	// skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases
-	CMPL	runtime·isplan9(SB), $1
-	JEQ	ok
-
-	// set up %gs
-	CALL	runtime·ldt0setup(SB)
-
-	// store through it, to make sure it works
-	get_tls(BX)
-	MOVL	$0x123, g(BX)
-	MOVL	runtime·tls0(SB), AX
-	CMPL	AX, $0x123
-	JEQ	ok
-	MOVL	AX, 0	// abort
-ok:
-	// set up m and g "registers"
-	get_tls(BX)
-	LEAL	runtime·g0(SB), CX
-	MOVL	CX, g(BX)
-	LEAL	runtime·m0(SB), AX
-	MOVL	AX, m(BX)
-
-	// save m->g0 = g0
-	MOVL	CX, m_g0(AX)
-
-	// create istack out of the OS stack
-	LEAL	(-64*1024+104)(SP), AX	// TODO: 104?
-	MOVL	AX, g_stackguard(CX)
-	MOVL	SP, g_stackbase(CX)
-	CALL	runtime·emptyfunc(SB)	// fault if stack check is wrong
-
-	// convention is D is always cleared
-	CLD
-
-	CALL	runtime·check(SB)
-
-	// saved argc, argv
-	MOVL	120(SP), AX
-	MOVL	AX, 0(SP)
-	MOVL	124(SP), AX
-	MOVL	AX, 4(SP)
-	CALL	runtime·args(SB)
-	CALL	runtime·osinit(SB)
-	CALL	runtime·schedinit(SB)
-
-	// create a new goroutine to start program
-	PUSHL	$runtime·mainstart(SB)	// entry
-	PUSHL	$0	// arg size
-	CALL	runtime·newproc(SB)
-	POPL	AX
-	POPL	AX
-
-	// start this M
-	CALL	runtime·mstart(SB)
-
-	INT $3
-	RET
-
-TEXT runtime·mainstart(SB),7,$0
-	CALL	main·init(SB)
-	CALL	runtime·initdone(SB)
-	CALL	main·main(SB)
-	PUSHL	$0
-	CALL	runtime·exit(SB)
-	POPL	AX
-	INT $3
-	RET
-
-TEXT runtime·breakpoint(SB),7,$0
-	INT $3
-	RET
-
-/*
- *  go-routine
- */
-
-// void gosave(Gobuf*)
-// save state in Gobuf; setjmp
-TEXT runtime·gosave(SB), 7, $0
-	MOVL	4(SP), AX		// gobuf
-	LEAL	4(SP), BX		// caller's SP
-	MOVL	BX, gobuf_sp(AX)
-	MOVL	0(SP), BX		// caller's PC
-	MOVL	BX, gobuf_pc(AX)
-	get_tls(CX)
-	MOVL	g(CX), BX
-	MOVL	BX, gobuf_g(AX)
-	RET
-
-// void gogo(Gobuf*, uintptr)
-// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), 7, $0
-	MOVL	8(SP), AX		// return 2nd arg
-	MOVL	4(SP), BX		// gobuf
-	MOVL	gobuf_g(BX), DX
-	MOVL	0(DX), CX		// make sure g != nil
-	get_tls(CX)
-	MOVL	DX, g(CX)
-	MOVL	gobuf_sp(BX), SP	// restore SP
-	MOVL	gobuf_pc(BX), BX
-	JMP	BX
-
-// void gogocall(Gobuf*, void (*fn)(void))
-// restore state from Gobuf but then call fn.
-// (call fn, returning to state in Gobuf)
-TEXT runtime·gogocall(SB), 7, $0
-	MOVL	8(SP), AX		// fn
-	MOVL	4(SP), BX		// gobuf
-	MOVL	gobuf_g(BX), DX
-	get_tls(CX)
-	MOVL	DX, g(CX)
-	MOVL	0(DX), CX		// make sure g != nil
-	MOVL	gobuf_sp(BX), SP	// restore SP
-	MOVL	gobuf_pc(BX), BX
-	PUSHL	BX
-	JMP	AX
-	POPL	BX	// not reached
-
-// void mcall(void (*fn)(G*))
-// Switch to m->g0's stack, call fn(g).
-// Fn must never return.  It should gogo(&g->sched)
-// to keep running g.
-TEXT runtime·mcall(SB), 7, $0
-	MOVL	fn+0(FP), DI
-	
-	get_tls(CX)
-	MOVL	g(CX), AX	// save state in g->gobuf
-	MOVL	0(SP), BX	// caller's PC
-	MOVL	BX, (g_sched+gobuf_pc)(AX)
-	LEAL	4(SP), BX	// caller's SP
-	MOVL	BX, (g_sched+gobuf_sp)(AX)
-	MOVL	AX, (g_sched+gobuf_g)(AX)
-
-	// switch to m->g0 & its stack, call fn
-	MOVL	m(CX), BX
-	MOVL	m_g0(BX), SI
-	CMPL	SI, AX	// if g == m->g0 call badmcall
-	JNE	2(PC)
-	CALL	runtime·badmcall(SB)
-	MOVL	SI, g(CX)	// g = m->g0
-	MOVL	(g_sched+gobuf_sp)(SI), SP	// sp = m->g0->gobuf.sp
-	PUSHL	AX
-	CALL	DI
-	POPL	AX
-	CALL	runtime·badmcall2(SB)
-	RET
-
-/*
- * support for morestack
- */
-
-// Called during function prolog when more stack is needed.
-TEXT runtime·morestack(SB),7,$0
-	// Cannot grow scheduler stack (m->g0).
-	get_tls(CX)
-	MOVL	m(CX), BX
-	MOVL	m_g0(BX), SI
-	CMPL	g(CX), SI
-	JNE	2(PC)
-	INT	$3
-
-	// frame size in DX
-	// arg size in AX
-	// Save in m.
-	MOVL	DX, m_moreframesize(BX)
-	MOVL	AX, m_moreargsize(BX)
-
-	// Called from f.
-	// Set m->morebuf to f's caller.
-	MOVL	4(SP), DI	// f's caller's PC
-	MOVL	DI, (m_morebuf+gobuf_pc)(BX)
-	LEAL	8(SP), CX	// f's caller's SP
-	MOVL	CX, (m_morebuf+gobuf_sp)(BX)
-	MOVL	CX, m_moreargp(BX)
-	get_tls(CX)
-	MOVL	g(CX), SI
-	MOVL	SI, (m_morebuf+gobuf_g)(BX)
-
-	// Set m->morepc to f's PC.
-	MOVL	0(SP), AX
-	MOVL	AX, m_morepc(BX)
-
-	// Call newstack on m->g0's stack.
-	MOVL	m_g0(BX), BP
-	MOVL	BP, g(CX)
-	MOVL	(g_sched+gobuf_sp)(BP), AX
-	MOVL	-4(AX), BX	// fault if CALL would, before smashing SP
-	MOVL	AX, SP
-	CALL	runtime·newstack(SB)
-	MOVL	$0, 0x1003	// crash if newstack returns
-	RET
-
-// Called from reflection library.  Mimics morestack,
-// reuses stack growth code to create a frame
-// with the desired args running the desired function.
-//
-// func call(fn *byte, arg *byte, argsize uint32).
-TEXT reflect·call(SB), 7, $0
-	get_tls(CX)
-	MOVL	m(CX), BX
-
-	// Save our caller's state as the PC and SP to
-	// restore when returning from f.
-	MOVL	0(SP), AX	// our caller's PC
-	MOVL	AX, (m_morebuf+gobuf_pc)(BX)
-	LEAL	4(SP), AX	// our caller's SP
-	MOVL	AX, (m_morebuf+gobuf_sp)(BX)
-	MOVL	g(CX), AX
-	MOVL	AX, (m_morebuf+gobuf_g)(BX)
-
-	// Set up morestack arguments to call f on a new stack.
-	// We set f's frame size to 1, as a hint to newstack
-	// that this is a call from reflect·call.
-	// If it turns out that f needs a larger frame than
-	// the default stack, f's usual stack growth prolog will
-	// allocate a new segment (and recopy the arguments).
-	MOVL	4(SP), AX	// fn
-	MOVL	8(SP), DX	// arg frame
-	MOVL	12(SP), CX	// arg size
-
-	MOVL	AX, m_morepc(BX)	// f's PC
-	MOVL	DX, m_moreargp(BX)	// f's argument pointer
-	MOVL	CX, m_moreargsize(BX)	// f's argument size
-	MOVL	$1, m_moreframesize(BX)	// f's frame size
-
-	// Call newstack on m->g0's stack.
-	MOVL	m_g0(BX), BP
-	get_tls(CX)
-	MOVL	BP, g(CX)
-	MOVL	(g_sched+gobuf_sp)(BP), SP
-	CALL	runtime·newstack(SB)
-	MOVL	$0, 0x1103	// crash if newstack returns
-	RET
-
-
-// Return point when leaving stack.
-TEXT runtime·lessstack(SB), 7, $0
-	// Save return value in m->cret
-	get_tls(CX)
-	MOVL	m(CX), BX
-	MOVL	AX, m_cret(BX)
-
-	// Call oldstack on m->g0's stack.
-	MOVL	m_g0(BX), BP
-	MOVL	BP, g(CX)
-	MOVL	(g_sched+gobuf_sp)(BP), SP
-	CALL	runtime·oldstack(SB)
-	MOVL	$0, 0x1004	// crash if oldstack returns
-	RET
-
-
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	}else
-//		return 0;
-TEXT runtime·cas(SB), 7, $0
-	MOVL	4(SP), BX
-	MOVL	8(SP), AX
-	MOVL	12(SP), CX
-	LOCK
-	CMPXCHGL	CX, 0(BX)
-	JZ 3(PC)
-	MOVL	$0, AX
-	RET
-	MOVL	$1, AX
-	RET
-
-// bool casp(void **p, void *old, void *new)
-// Atomically:
-//	if(*p == old){
-//		*p = new;
-//		return 1;
-//	}else
-//		return 0;
-TEXT runtime·casp(SB), 7, $0
-	MOVL	4(SP), BX
-	MOVL	8(SP), AX
-	MOVL	12(SP), CX
-	LOCK
-	CMPXCHGL	CX, 0(BX)
-	JZ 3(PC)
-	MOVL	$0, AX
-	RET
-	MOVL	$1, AX
-	RET
-
-// uint32 xadd(uint32 volatile *val, int32 delta)
-// Atomically:
-//	*val += delta;
-//	return *val;
-TEXT runtime·xadd(SB), 7, $0
-	MOVL	4(SP), BX
-	MOVL	8(SP), AX
-	MOVL	AX, CX
-	LOCK
-	XADDL	AX, 0(BX)
-	ADDL	CX, AX
-	RET
-
-TEXT runtime·xchg(SB), 7, $0
-	MOVL	4(SP), BX
-	MOVL	8(SP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-TEXT runtime·procyield(SB),7,$0
-	MOVL	4(SP), AX
-again:
-	PAUSE
-	SUBL	$1, AX
-	JNZ	again
-	RET
-
-TEXT runtime·atomicstorep(SB), 7, $0
-	MOVL	4(SP), BX
-	MOVL	8(SP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-TEXT runtime·atomicstore(SB), 7, $0
-	MOVL	4(SP), BX
-	MOVL	8(SP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-// void jmpdefer(fn, sp);
-// called from deferreturn.
-// 1. pop the caller
-// 2. sub 5 bytes from the callers return
-// 3. jmp to the argument
-TEXT runtime·jmpdefer(SB), 7, $0
-	MOVL	4(SP), AX	// fn
-	MOVL	8(SP), BX	// caller sp
-	LEAL	-4(BX), SP	// caller sp after CALL
-	SUBL	$5, (SP)	// return to CALL again
-	JMP	AX	// but first run the deferred function
-
-// Dummy function to use in saved gobuf.PC,
-// to match SP pointing at a return address.
-// The gobuf.PC is unused by the contortions here
-// but setting it to return will make the traceback code work.
-TEXT return<>(SB),7,$0
-	RET
-
-// asmcgocall(void(*fn)(void*), void *arg)
-// Call fn(arg) on the scheduler stack,
-// aligned appropriately for the gcc ABI.
-// See cgocall.c for more details.
-TEXT runtime·asmcgocall(SB),7,$0
-	MOVL	fn+0(FP), AX
-	MOVL	arg+4(FP), BX
-	MOVL	SP, DX
-
-	// Figure out if we need to switch to m->g0 stack.
-	// We get called to create new OS threads too, and those
-	// come in on the m->g0 stack already.
-	get_tls(CX)
-	MOVL	m(CX), BP
-	MOVL	m_g0(BP), SI
-	MOVL	g(CX), DI
-	CMPL	SI, DI
-	JEQ	6(PC)
-	MOVL	SP, (g_sched+gobuf_sp)(DI)
-	MOVL	$return<>(SB), (g_sched+gobuf_pc)(DI)
-	MOVL	DI, (g_sched+gobuf_g)(DI)
-	MOVL	SI, g(CX)
-	MOVL	(g_sched+gobuf_sp)(SI), SP
-
-	// Now on a scheduling stack (a pthread-created stack).
-	SUBL	$32, SP
-	ANDL	$~15, SP	// alignment, perhaps unnecessary
-	MOVL	DI, 8(SP)	// save g
-	MOVL	DX, 4(SP)	// save SP
-	MOVL	BX, 0(SP)	// first argument in x86-32 ABI
-	CALL	AX
-
-	// Restore registers, g, stack pointer.
-	get_tls(CX)
-	MOVL	8(SP), DI
-	MOVL	DI, g(CX)
-	MOVL	4(SP), SP
-	RET
-
-// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
-// See cgocall.c for more details.
-TEXT runtime·cgocallback(SB),7,$12
-	MOVL	fn+0(FP), AX
-	MOVL	frame+4(FP), BX
-	MOVL	framesize+8(FP), DX
-
-	// Save current m->g0->sched.sp on stack and then set it to SP.
-	get_tls(CX)
-	MOVL	m(CX), BP
-	MOVL	m_g0(BP), SI
-	PUSHL	(g_sched+gobuf_sp)(SI)
-	MOVL	SP, (g_sched+gobuf_sp)(SI)
-
-	// Switch to m->curg stack and call runtime.cgocallbackg
-	// with the three arguments.  Because we are taking over
-	// the execution of m->curg but *not* resuming what had
-	// been running, we need to save that information (m->curg->gobuf)
-	// so that we can restore it when we're done. 
-	// We can restore m->curg->gobuf.sp easily, because calling
-	// runtime.cgocallbackg leaves SP unchanged upon return.
-	// To save m->curg->gobuf.pc, we push it onto the stack.
-	// This has the added benefit that it looks to the traceback
-	// routine like cgocallbackg is going to return to that
-	// PC (because we defined cgocallbackg to have
-	// a frame size of 12, the same amount that we use below),
-	// so that the traceback will seamlessly trace back into
-	// the earlier calls.
-	MOVL	m_curg(BP), SI
-	MOVL	SI, g(CX)
-	MOVL	(g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
-
-	// Push gobuf.pc
-	MOVL	(g_sched+gobuf_pc)(SI), BP
-	SUBL	$4, DI
-	MOVL	BP, 0(DI)
-
-	// Push arguments to cgocallbackg.
-	// Frame size here must match the frame size above
-	// to trick traceback routines into doing the right thing.
-	SUBL	$12, DI
-	MOVL	AX, 0(DI)
-	MOVL	BX, 4(DI)
-	MOVL	DX, 8(DI)
-	
-	// Switch stack and make the call.
-	MOVL	DI, SP
-	CALL	runtime·cgocallbackg(SB)
-
-	// Restore g->gobuf (== m->curg->gobuf) from saved values.
-	get_tls(CX)
-	MOVL	g(CX), SI
-	MOVL	12(SP), BP
-	MOVL	BP, (g_sched+gobuf_pc)(SI)
-	LEAL	(12+4)(SP), DI
-	MOVL	DI, (g_sched+gobuf_sp)(SI)
-
-	// Switch back to m->g0's stack and restore m->g0->sched.sp.
-	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
-	// so we do not have to restore it.)
-	MOVL	m(CX), BP
-	MOVL	m_g0(BP), SI
-	MOVL	SI, g(CX)
-	MOVL	(g_sched+gobuf_sp)(SI), SP
-	POPL	(g_sched+gobuf_sp)(SI)
-
-	// Done!
-	RET
-
-// check that SP is in range [g->stackbase, g->stackguard)
-TEXT runtime·stackcheck(SB), 7, $0
-	get_tls(CX)
-	MOVL	g(CX), AX
-	CMPL	g_stackbase(AX), SP
-	JHI	2(PC)
-	INT	$3
-	CMPL	SP, g_stackguard(AX)
-	JHI	2(PC)
-	INT	$3
-	RET
-
-TEXT runtime·memclr(SB),7,$0
-	MOVL	4(SP), DI		// arg 1 addr
-	MOVL	8(SP), CX		// arg 2 count
-	MOVL	CX, BX
-	ANDL	$3, BX
-	SHRL	$2, CX
-	MOVL	$0, AX
-	CLD
-	REP
-	STOSL
-	MOVL	BX, CX
-	REP
-	STOSB
-	RET
-
-TEXT runtime·getcallerpc(SB),7,$0
-	MOVL	x+0(FP),AX		// addr of first arg
-	MOVL	-4(AX),AX		// get calling pc
-	RET
-
-TEXT runtime·setcallerpc(SB),7,$0
-	MOVL	x+0(FP),AX		// addr of first arg
-	MOVL	x+4(FP), BX
-	MOVL	BX, -4(AX)		// set calling pc
-	RET
-
-TEXT runtime·getcallersp(SB), 7, $0
-	MOVL	sp+0(FP), AX
-	RET
-
-TEXT runtime·ldt0setup(SB),7,$16
-	// set up ldt 7 to point at tls0
-	// ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go.
-	// the entry number is just a hint.  setldt will set up GS with what it used.
-	MOVL	$7, 0(SP)
-	LEAL	runtime·tls0(SB), AX
-	MOVL	AX, 4(SP)
-	MOVL	$32, 8(SP)	// sizeof(tls array)
-	CALL	runtime·setldt(SB)
-	RET
-
-TEXT runtime·emptyfunc(SB),0,$0
-	RET
-
-TEXT runtime·abort(SB),7,$0
-	INT $0x3
-
-GLOBL runtime·tls0(SB), $32
diff --git a/src/pkg/runtime/Makefile b/src/pkg/runtime/Makefile
index 725c2b0..50d0515 100644
--- a/src/pkg/runtime/Makefile
+++ b/src/pkg/runtime/Makefile
@@ -6,15 +6,6 @@ include ../../Make.inc
 
 TARG=runtime
 
-# Set SIZE to 32 or 64.
-SIZE_386=32
-SIZE_amd64=64
-SIZE_arm=32
-SIZE=$(SIZE_$(GOARCH))
-
-CFLAGS_windows=-D__WINDOWS__
-CFLAGS=-I$(GOOS) -I$(GOARCH) -I$(GOOS)/$(GOARCH) -FVw $(CFLAGS_$(GOARCH)) $(CFLAGS_$(GOOS))
-
 GOFILES=\
 	debug.go\
 	error.go\
@@ -23,68 +14,99 @@ GOFILES=\
 	sig.go\
 	softfloat64.go\
 	type.go\
-	version.go\
-	version_$(GOOS).go\
-	version_$(GOARCH).go\
-	runtime_defs.go\
+	zgoarch_$(GOARCH).go\
+	zgoos_$(GOOS).go\
+	zruntime_defs_$(GOOS)_$(GOARCH).go\
+	zversion.go\
+
+OFILES_darwin=\
+	lock_sema.$O\
+
+OFILES_freebsd=\
+	lock_futex.$O\
+
+OFILES_linux=\
+	lock_futex.$O\
+
+OFILES_netbsd=\
+	lock_sema.$O\
+
+OFILES_openbsd=\
+	lock_sema.$O\
 
-CLEANFILES+=version.go version_*.go
+OFILES_plan9=\
+	lock_sema.$O\
 
 OFILES_windows=\
-	callback.$O\
-	syscall.$O\
+	callback_windows_$(GOARCH).$O\
+	lock_sema.$O\
+	zsyscall_windows_$(GOARCH).$O\
 
 # 386-specific object files
 OFILES_386=\
-	vlop.$O\
-	vlrt.$O\
+	vlop_386.$O\
+	vlrt_386.$O\
+	traceback_x86.$O\
+
+# amd64-specific object files
+OFILES_amd64=\
+	traceback_x86.$O\
 
 # arm-specific object files
 OFILES_arm=\
-	memset.$O\
-	softfloat.$O\
-	vlop.$O\
-	vlrt.$O\
+	memset_arm.$O\
+	softfloat_arm.$O\
+	vlop_arm.$O\
+	vlrt_arm.$O\
+	traceback_arm.$O\
 
 OFILES=\
-	asm.$O\
-	atomic.$O\
+	$(OFILES_$(GOARCH))\
+	$(OFILES_$(GOOS))\
+	alg.$O\
+	asm_$(GOARCH).$O\
+	atomic_$(GOARCH).$O\
 	cgocall.$O\
 	chan.$O\
-	closure.$O\
+	closure_$(GOARCH).$O\
+	complex.$O\
 	cpuprof.$O\
 	float.$O\
-	complex.$O\
 	hashmap.$O\
 	iface.$O\
-	malloc.$O\
 	mcache.$O\
 	mcentral.$O\
-	mem.$O\
-	memmove.$O\
+	mem_$(GOOS).$O\
+	memmove_$(GOARCH).$O\
 	mfinal.$O\
 	mfixalloc.$O\
 	mgc0.$O\
 	mheap.$O\
-	mprof.$O\
 	msize.$O\
 	print.$O\
 	proc.$O\
+	rt0_$(GOOS)_$(GOARCH).$O\
 	rune.$O\
 	runtime.$O\
-	runtime1.$O\
-	rt0.$O\
-	sema.$O\
-	signal.$O\
-	sigqueue.$O\
+	signal_$(GOOS)_$(GOARCH).$O\
 	slice.$O\
-	string.$O\
 	symtab.$O\
-	sys.$O\
-	thread.$O\
-	traceback.$O\
-	$(OFILES_$(GOARCH))\
-	$(OFILES_$(GOOS))\
+	sys_$(GOOS)_$(GOARCH).$O\
+	thread_$(GOOS).$O\
+	zmalloc_$(GOARCH).$O\
+	zmprof_$(GOARCH).$O\
+	zruntime1_$(GOARCH).$O\
+	zsema_$(GOARCH).$O\
+	zsigqueue_$(GOARCH).$O\
+	zstring_$(GOARCH).$O\
+	ztime_$(GOARCH).$O\
+
+AUTOHFILES=\
+	arch_GOARCH.h\
+	os_GOOS.h\
+	signals_GOOS.h\
+	defs_GOOS_GOARCH.h\
+	zasm_GOOS_GOARCH.h\
 
 HFILES=\
 	cgocall.h\
@@ -92,16 +114,17 @@ HFILES=\
 	hashmap.h\
 	malloc.h\
 	stack.h\
-	$(GOARCH)/asm.h\
-	$(GOOS)/os.h\
-	$(GOOS)/signals.h\
-	$(GOOS)/$(GOARCH)/defs.h\
+	$(AUTOHFILES)\
 
 GOFILES+=$(GOFILES_$(GOOS))
 
 # For use by cgo.
 INSTALLFILES=$(pkgdir)/runtime.h $(pkgdir)/cgocall.h
 
+# Go tool will do this for package runtime.
+AFLAGS+=-DGOOS_$(GOOS) -DGOARCH_$(GOARCH)
+CFLAGS+=-DGOOS_$(GOOS) -DGOARCH_$(GOARCH)
+
 # special, out of the way compiler flag that means "add runtime metadata to output"
 GC+= -+
 
@@ -114,56 +137,19 @@ $(pkgdir)/%.h: %.h
 clean: clean-local
 
 clean-local:
-	rm -f goc2c mkversion version.go */asm.h runtime.acid.* runtime_defs.go $$(ls *.goc | sed 's/goc$$/c/')
-
-$(GOARCH)/asm.h: mkasmh.sh runtime.acid.$(GOARCH)
-	./mkasmh.sh >$@.x
-	mv -f $@.x $@
-
-goc2c: goc2c.c
-	quietgcc -o $@ -I "$(GOROOT)/include" $< "$(GOROOT)/lib/lib9.a"
-
-mkversion: mkversion.c
-	quietgcc -o $@ -I "$(GOROOT)/include" $< "$(GOROOT)/lib/lib9.a"
-
-version.go: mkversion
-	GOROOT="$(GOROOT_FINAL)" ./mkversion >version.go
-
-version_$(GOARCH).go:
-	(echo 'package runtime'; echo 'const theGoarch = "$(GOARCH)"') >$@
-
-version_$(GOOS).go:
-	(echo 'package runtime'; echo 'const theGoos = "$(GOOS)"') >$@
-
-%.c:	%.goc goc2c
-	./goc2c "`pwd`/$<" > $@.tmp
-	mv -f $@.tmp $@
-
-%.$O:	$(GOARCH)/%.c $(HFILES)
-	$(CC) $(CFLAGS) $<
-
-%.$O:	$(GOOS)/%.c $(HFILES)
-	$(CC) $(CFLAGS) $<
-
-%.$O:	$(GOOS)/$(GOARCH)/%.c $(HFILES)
-	$(CC) $(CFLAGS) $<
+	rm -f $(AUTOHFILES) runtime_defs.go version*.go asm_*.h
 
-%.$O:	$(GOARCH)/%.s $(GOARCH)/asm.h
-	$(AS) $<
+arch_GOARCH.h: arch_$(GOARCH).h
+	cp $^ $@
 
-%.$O:	$(GOOS)/$(GOARCH)/%.s $(GOARCH)/asm.h
-	$(AS) $<
+defs_GOOS_GOARCH.h: defs_$(GOOS)_$(GOARCH).h
+	cp $^ $@
 
-# for discovering offsets inside structs when debugging
-runtime.acid.$(GOARCH): runtime.h proc.c
-	$(CC) $(CFLAGS) -a proc.c >$@
+os_GOOS.h: os_$(GOOS).h
+	cp $^ $@
 
-# 386 traceback is really amd64 traceback
-ifeq ($(GOARCH),386)
-traceback.$O:	amd64/traceback.c
-	$(CC) $(CFLAGS) $<
-endif
+signals_GOOS.h: signals_$(GOOS).h
+	cp $^ $@
 
-runtime_defs.go: proc.c iface.c hashmap.c chan.c
-	CC="$(CC)" CFLAGS="$(CFLAGS)" ./mkgodefs.sh $^ > $@.x
-	mv -f $@.x $@
+zasm_GOOS_GOARCH.h: zasm_$(GOOS)_$(GOARCH).h
+	cp $^ $@
diff --git a/src/pkg/runtime/alg.c b/src/pkg/runtime/alg.c
new file mode 100644
index 0000000..56ec2d6
--- /dev/null
+++ b/src/pkg/runtime/alg.c
@@ -0,0 +1,484 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "type.h"
+
+/*
+ * map and chan helpers for
+ * dealing with unknown types
+ */
+void
+runtime·memhash(uintptr *h, uintptr s, void *a)
+{
+	byte *b;
+	uintptr hash;
+
+	b = a;
+	if(sizeof(hash) == 4)
+		hash = 2860486313U;
+	else
+		hash = 33054211828000289ULL;
+	while(s > 0) {
+		if(sizeof(hash) == 4)
+			hash = (hash ^ *b) * 3267000013UL;
+		else
+			hash = (hash ^ *b) * 23344194077549503ULL;
+		b++;
+		s--;
+	}
+	*h ^= hash;
+}
+
+void
+runtime·memequal(bool *eq, uintptr s, void *a, void *b)
+{
+	byte *ba, *bb, *aend;
+
+	if(a == b) {
+		*eq = 1;
+		return;
+	}
+	ba = a;
+	bb = b;
+	aend = ba+s;
+	while(ba != aend) {
+		if(*ba != *bb) {
+			*eq = 0;
+			return;
+		}
+		ba++;
+		bb++;
+	}
+	*eq = 1;
+	return;
+}
+
+void
+runtime·memprint(uintptr s, void *a)
+{
+	uint64 v;
+
+	v = 0xbadb00b;
+	switch(s) {
+	case 1:
+		v = *(uint8*)a;
+		break;
+	case 2:
+		v = *(uint16*)a;
+		break;
+	case 4:
+		v = *(uint32*)a;
+		break;
+	case 8:
+		v = *(uint64*)a;
+		break;
+	}
+	runtime·printint(v);
+}
+
+void
+runtime·memcopy(uintptr s, void *a, void *b)
+{
+	if(b == nil) {
+		runtime·memclr(a, s);
+		return;
+	}
+	runtime·memmove(a, b, s);
+}
+
+void
+runtime·memequal0(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	USED(a);
+	USED(b);
+	*eq = true;
+}
+
+void
+runtime·memcopy0(uintptr s, void *a, void *b)
+{
+	USED(s);
+	USED(a);
+	USED(b);
+}
+
+void
+runtime·memequal8(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = *(uint8*)a == *(uint8*)b;
+}
+
+void
+runtime·memcopy8(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		*(uint8*)a = 0;
+		return;
+	}
+	*(uint8*)a = *(uint8*)b;
+}
+
+void
+runtime·memequal16(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = *(uint16*)a == *(uint16*)b;
+}
+
+void
+runtime·memcopy16(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		*(uint16*)a = 0;
+		return;
+	}
+	*(uint16*)a = *(uint16*)b;
+}
+
+void
+runtime·memequal32(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = *(uint32*)a == *(uint32*)b;
+}
+
+void
+runtime·memcopy32(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		*(uint32*)a = 0;
+		return;
+	}
+	*(uint32*)a = *(uint32*)b;
+}
+
+void
+runtime·memequal64(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = *(uint64*)a == *(uint64*)b;
+}
+
+void
+runtime·memcopy64(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		*(uint64*)a = 0;
+		return;
+	}
+	*(uint64*)a = *(uint64*)b;
+}
+
+void
+runtime·memequal128(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = ((uint64*)a)[0] == ((uint64*)b)[0] && ((uint64*)a)[1] == ((uint64*)b)[1];
+}
+
+void
+runtime·memcopy128(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		((uint64*)a)[0] = 0;
+		((uint64*)a)[1] = 0;
+		return;
+	}
+	((uint64*)a)[0] = ((uint64*)b)[0];
+	((uint64*)a)[1] = ((uint64*)b)[1];
+}
+
+void
+runtime·f32equal(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = *(float32*)a == *(float32*)b;
+}
+
+void
+runtime·f64equal(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = *(float64*)a == *(float64*)b;
+}
+
+void
+runtime·c64equal(bool *eq, uintptr s, void *a, void *b)
+{	
+	Complex64 *ca, *cb;
+	
+	USED(s);
+	ca = a;
+	cb = b;
+	*eq = ca->real == cb->real && ca->imag == cb->imag;
+}
+
+void
+runtime·c128equal(bool *eq, uintptr s, void *a, void *b)
+{	
+	Complex128 *ca, *cb;
+	
+	USED(s);
+	ca = a;
+	cb = b;
+	*eq = ca->real == cb->real && ca->imag == cb->imag;
+}
+
+// NOTE: Because NaN != NaN, a map can contain any
+// number of (mostly useless) entries keyed with NaNs.
+// To avoid long hash chains, we assign a random number
+// as the hash value for a NaN.
+
+void
+runtime·f32hash(uintptr *h, uintptr s, void *a)
+{
+	uintptr hash;
+	float32 f;
+
+	USED(s);
+	f = *(float32*)a;
+	if(f == 0)
+		hash = 0;  // +0, -0
+	else if(f != f)
+		hash = runtime·fastrand1();  // any kind of NaN
+	else
+		hash = *(uint32*)a;
+	*h ^= (*h ^ hash ^ 2860486313U) * 3267000013U;
+}
+
+void
+runtime·f64hash(uintptr *h, uintptr s, void *a)
+{
+	uintptr hash;
+	float64 f;
+	uint64 u;
+
+	USED(s);
+	f = *(float32*)a;
+	if(f == 0)
+		hash = 0;	// +0, -0
+	else if(f != f)
+		hash = runtime·fastrand1();  // any kind of NaN
+	else {
+		u = *(uint64*)a;
+		if(sizeof(uintptr) == 4)
+			hash = ((uint32)(u>>32) ^ 2860486313) * (uint32)u;
+		else
+			hash = u;
+	}
+	if(sizeof(uintptr) == 4)
+		*h = (*h ^ hash ^ 2860486313U) * 3267000013U;
+	else
+		*h = (*h ^ hash ^ 33054211828000289ULL) * 23344194077549503ULL;
+}
+
+void
+runtime·c64hash(uintptr *h, uintptr s, void *a)
+{
+	USED(s);
+	runtime·f32hash(h, 0, a);
+	runtime·f32hash(h, 0, (float32*)a+1);
+}
+
+void
+runtime·c128hash(uintptr *h, uintptr s, void *a)
+{
+	USED(s);
+	runtime·f64hash(h, 0, a);
+	runtime·f64hash(h, 0, (float64*)a+1);
+}
+
+void
+runtime·slicecopy(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		((Slice*)a)->array = 0;
+		((Slice*)a)->len = 0;
+		((Slice*)a)->cap = 0;
+		return;
+	}
+	((Slice*)a)->array = ((Slice*)b)->array;
+	((Slice*)a)->len = ((Slice*)b)->len;
+	((Slice*)a)->cap = ((Slice*)b)->cap;
+}
+
+void
+runtime·strhash(uintptr *h, uintptr s, void *a)
+{
+	USED(s);
+	runtime·memhash(h, ((String*)a)->len, ((String*)a)->str);
+}
+
+void
+runtime·strequal(bool *eq, uintptr s, void *a, void *b)
+{
+	int32 alen;
+
+	USED(s);
+	alen = ((String*)a)->len;
+	if(alen != ((String*)b)->len) {
+		*eq = false;
+		return;
+	}
+	runtime·memequal(eq, alen, ((String*)a)->str, ((String*)b)->str);
+}
+
+void
+runtime·strprint(uintptr s, void *a)
+{
+	USED(s);
+	runtime·printstring(*(String*)a);
+}
+
+void
+runtime·strcopy(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		((String*)a)->str = 0;
+		((String*)a)->len = 0;
+		return;
+	}
+	((String*)a)->str = ((String*)b)->str;
+	((String*)a)->len = ((String*)b)->len;
+}
+
+void
+runtime·interhash(uintptr *h, uintptr s, void *a)
+{
+	USED(s);
+	*h ^= runtime·ifacehash(*(Iface*)a);
+}
+
+void
+runtime·interprint(uintptr s, void *a)
+{
+	USED(s);
+	runtime·printiface(*(Iface*)a);
+}
+
+void
+runtime·interequal(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = runtime·ifaceeq_c(*(Iface*)a, *(Iface*)b);
+}
+
+void
+runtime·intercopy(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		((Iface*)a)->tab = 0;
+		((Iface*)a)->data = 0;
+		return;
+	}
+	((Iface*)a)->tab = ((Iface*)b)->tab;
+	((Iface*)a)->data = ((Iface*)b)->data;
+}
+
+void
+runtime·nilinterhash(uintptr *h, uintptr s, void *a)
+{
+	USED(s);
+	*h ^= runtime·efacehash(*(Eface*)a);
+}
+
+void
+runtime·nilinterprint(uintptr s, void *a)
+{
+	USED(s);
+	runtime·printeface(*(Eface*)a);
+}
+
+void
+runtime·nilinterequal(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	*eq = runtime·efaceeq_c(*(Eface*)a, *(Eface*)b);
+}
+
+void
+runtime·nilintercopy(uintptr s, void *a, void *b)
+{
+	USED(s);
+	if(b == nil) {
+		((Eface*)a)->type = 0;
+		((Eface*)a)->data = 0;
+		return;
+	}
+	((Eface*)a)->type = ((Eface*)b)->type;
+	((Eface*)a)->data = ((Eface*)b)->data;
+}
+
+void
+runtime·nohash(uintptr *h, uintptr s, void *a)
+{
+	USED(s);
+	USED(a);
+	USED(h);
+	runtime·panicstring("hash of unhashable type");
+}
+
+void
+runtime·noequal(bool *eq, uintptr s, void *a, void *b)
+{
+	USED(s);
+	USED(a);
+	USED(b);
+	USED(eq);
+	runtime·panicstring("comparing uncomparable types");
+}
+
+Alg
+runtime·algarray[] =
+{
+[AMEM]		{ runtime·memhash, runtime·memequal, runtime·memprint, runtime·memcopy },
+[ANOEQ]		{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy },
+[ASTRING]	{ runtime·strhash, runtime·strequal, runtime·strprint, runtime·strcopy },
+[AINTER]	{ runtime·interhash, runtime·interequal, runtime·interprint, runtime·intercopy },
+[ANILINTER]	{ runtime·nilinterhash, runtime·nilinterequal, runtime·nilinterprint, runtime·nilintercopy },
+[ASLICE]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·slicecopy },
+[AFLOAT32]	{ runtime·f32hash, runtime·f32equal, runtime·memprint, runtime·memcopy },
+[AFLOAT64]	{ runtime·f64hash, runtime·f64equal, runtime·memprint, runtime·memcopy },
+[ACPLX64]	{ runtime·c64hash, runtime·c64equal, runtime·memprint, runtime·memcopy },
+[ACPLX128]	{ runtime·c128hash, runtime·c128equal, runtime·memprint, runtime·memcopy },
+[AMEM0]		{ runtime·memhash, runtime·memequal0, runtime·memprint, runtime·memcopy0 },
+[AMEM8]		{ runtime·memhash, runtime·memequal8, runtime·memprint, runtime·memcopy8 },
+[AMEM16]	{ runtime·memhash, runtime·memequal16, runtime·memprint, runtime·memcopy16 },
+[AMEM32]	{ runtime·memhash, runtime·memequal32, runtime·memprint, runtime·memcopy32 },
+[AMEM64]	{ runtime·memhash, runtime·memequal64, runtime·memprint, runtime·memcopy64 },
+[AMEM128]	{ runtime·memhash, runtime·memequal128, runtime·memprint, runtime·memcopy128 },
+[ANOEQ0]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy0 },
+[ANOEQ8]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy8 },
+[ANOEQ16]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy16 },
+[ANOEQ32]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy32 },
+[ANOEQ64]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy64 },
+[ANOEQ128]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy128 },
+};
+
+// Runtime helpers.
+
+// func equal(t *Type, x T, y T) (ret bool)
+#pragma textflag 7
+void
+runtime·equal(Type *t, ...)
+{
+	byte *x, *y;
+	bool *ret;
+	
+	x = (byte*)(&t+1);
+	y = x + t->size;
+	ret = (bool*)(y + t->size);
+	t->alg->equal(ret, t->size, x, y);
+}
diff --git a/src/pkg/runtime/amd64/arch.h b/src/pkg/runtime/amd64/arch.h
deleted file mode 100644
index fe10fd8..0000000
--- a/src/pkg/runtime/amd64/arch.h
+++ /dev/null
@@ -1,3 +0,0 @@
-enum {
-	thechar = '6'
-};
diff --git a/src/pkg/runtime/amd64/asm.s b/src/pkg/runtime/amd64/asm.s
deleted file mode 100644
index a881e3b..0000000
--- a/src/pkg/runtime/amd64/asm.s
+++ /dev/null
@@ -1,577 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "amd64/asm.h"
-
-TEXT _rt0_amd64(SB),7,$-8
-	// copy arguments forward on an even stack
-	MOVQ	0(DI), AX		// argc
-	LEAQ	8(DI), BX		// argv
-	SUBQ	$(4*8+7), SP		// 2args 2auto
-	ANDQ	$~15, SP
-	MOVQ	AX, 16(SP)
-	MOVQ	BX, 24(SP)
-
-	// if there is an initcgo, call it.
-	MOVQ	initcgo(SB), AX
-	TESTQ	AX, AX
-	JZ	needtls
-	CALL	AX
-	CMPL	runtime·iswindows(SB), $0
-	JEQ ok
-
-needtls:
-	LEAQ	runtime·tls0(SB), DI
-	CALL	runtime·settls(SB)
-
-	// store through it, to make sure it works
-	get_tls(BX)
-	MOVQ	$0x123, g(BX)
-	MOVQ	runtime·tls0(SB), AX
-	CMPQ	AX, $0x123
-	JEQ 2(PC)
-	MOVL	AX, 0	// abort
-ok:
-	// set the per-goroutine and per-mach "registers"
-	get_tls(BX)
-	LEAQ	runtime·g0(SB), CX
-	MOVQ	CX, g(BX)
-	LEAQ	runtime·m0(SB), AX
-	MOVQ	AX, m(BX)
-
-	// save m->g0 = g0
-	MOVQ	CX, m_g0(AX)
-
-	// create istack out of the given (operating system) stack
-	LEAQ	(-8192+104)(SP), AX
-	MOVQ	AX, g_stackguard(CX)
-	MOVQ	SP, g_stackbase(CX)
-
-	CLD				// convention is D is always left cleared
-	CALL	runtime·check(SB)
-
-	MOVL	16(SP), AX		// copy argc
-	MOVL	AX, 0(SP)
-	MOVQ	24(SP), AX		// copy argv
-	MOVQ	AX, 8(SP)
-	CALL	runtime·args(SB)
-	CALL	runtime·osinit(SB)
-	CALL	runtime·schedinit(SB)
-
-	// create a new goroutine to start program
-	PUSHQ	$runtime·mainstart(SB)		// entry
-	PUSHQ	$0			// arg size
-	CALL	runtime·newproc(SB)
-	POPQ	AX
-	POPQ	AX
-
-	// start this M
-	CALL	runtime·mstart(SB)
-
-	CALL	runtime·notok(SB)		// never returns
-	RET
-
-TEXT runtime·mainstart(SB),7,$0
-	CALL	main·init(SB)
-	CALL	runtime·initdone(SB)
-	CALL	main·main(SB)
-	PUSHQ	$0
-	CALL	runtime·exit(SB)
-	POPQ	AX
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·breakpoint(SB),7,$0
-	BYTE	$0xcc
-	RET
-
-/*
- *  go-routine
- */
-
-// void gosave(Gobuf*)
-// save state in Gobuf; setjmp
-TEXT runtime·gosave(SB), 7, $0
-	MOVQ	8(SP), AX		// gobuf
-	LEAQ	8(SP), BX		// caller's SP
-	MOVQ	BX, gobuf_sp(AX)
-	MOVQ	0(SP), BX		// caller's PC
-	MOVQ	BX, gobuf_pc(AX)
-	get_tls(CX)
-	MOVQ	g(CX), BX
-	MOVQ	BX, gobuf_g(AX)
-	RET
-
-// void gogo(Gobuf*, uintptr)
-// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), 7, $0
-	MOVQ	16(SP), AX		// return 2nd arg
-	MOVQ	8(SP), BX		// gobuf
-	MOVQ	gobuf_g(BX), DX
-	MOVQ	0(DX), CX		// make sure g != nil
-	get_tls(CX)
-	MOVQ	DX, g(CX)
-	MOVQ	gobuf_sp(BX), SP	// restore SP
-	MOVQ	gobuf_pc(BX), BX
-	JMP	BX
-
-// void gogocall(Gobuf*, void (*fn)(void))
-// restore state from Gobuf but then call fn.
-// (call fn, returning to state in Gobuf)
-TEXT runtime·gogocall(SB), 7, $0
-	MOVQ	16(SP), AX		// fn
-	MOVQ	8(SP), BX		// gobuf
-	MOVQ	gobuf_g(BX), DX
-	get_tls(CX)
-	MOVQ	DX, g(CX)
-	MOVQ	0(DX), CX	// make sure g != nil
-	MOVQ	gobuf_sp(BX), SP	// restore SP
-	MOVQ	gobuf_pc(BX), BX
-	PUSHQ	BX
-	JMP	AX
-	POPQ	BX	// not reached
-
-// void mcall(void (*fn)(G*))
-// Switch to m->g0's stack, call fn(g).
-// Fn must never return.  It should gogo(&g->sched)
-// to keep running g.
-TEXT runtime·mcall(SB), 7, $0
-	MOVQ	fn+0(FP), DI
-	
-	get_tls(CX)
-	MOVQ	g(CX), AX	// save state in g->gobuf
-	MOVQ	0(SP), BX	// caller's PC
-	MOVQ	BX, (g_sched+gobuf_pc)(AX)
-	LEAQ	8(SP), BX	// caller's SP
-	MOVQ	BX, (g_sched+gobuf_sp)(AX)
-	MOVQ	AX, (g_sched+gobuf_g)(AX)
-
-	// switch to m->g0 & its stack, call fn
-	MOVQ	m(CX), BX
-	MOVQ	m_g0(BX), SI
-	CMPQ	SI, AX	// if g == m->g0 call badmcall
-	JNE	2(PC)
-	CALL	runtime·badmcall(SB)
-	MOVQ	SI, g(CX)	// g = m->g0
-	MOVQ	(g_sched+gobuf_sp)(SI), SP	// sp = m->g0->gobuf.sp
-	PUSHQ	AX
-	CALL	DI
-	POPQ	AX
-	CALL	runtime·badmcall2(SB)
-	RET
-
-/*
- * support for morestack
- */
-
-// Called during function prolog when more stack is needed.
-// Caller has already done get_tls(CX); MOVQ m(CX), BX.
-TEXT runtime·morestack(SB),7,$0
-	// Cannot grow scheduler stack (m->g0).
-	MOVQ	m_g0(BX), SI
-	CMPQ	g(CX), SI
-	JNE	2(PC)
-	INT	$3
-
-	// Called from f.
-	// Set m->morebuf to f's caller.
-	MOVQ	8(SP), AX	// f's caller's PC
-	MOVQ	AX, (m_morebuf+gobuf_pc)(BX)
-	LEAQ	16(SP), AX	// f's caller's SP
-	MOVQ	AX, (m_morebuf+gobuf_sp)(BX)
-	MOVQ	AX, m_moreargp(BX)
-	get_tls(CX)
-	MOVQ	g(CX), SI
-	MOVQ	SI, (m_morebuf+gobuf_g)(BX)
-
-	// Set m->morepc to f's PC.
-	MOVQ	0(SP), AX
-	MOVQ	AX, m_morepc(BX)
-
-	// Call newstack on m->g0's stack.
-	MOVQ	m_g0(BX), BP
-	MOVQ	BP, g(CX)
-	MOVQ	(g_sched+gobuf_sp)(BP), SP
-	CALL	runtime·newstack(SB)
-	MOVQ	$0, 0x1003	// crash if newstack returns
-	RET
-
-// Called from reflection library.  Mimics morestack,
-// reuses stack growth code to create a frame
-// with the desired args running the desired function.
-//
-// func call(fn *byte, arg *byte, argsize uint32).
-TEXT reflect·call(SB), 7, $0
-	get_tls(CX)
-	MOVQ	m(CX), BX
-
-	// Save our caller's state as the PC and SP to
-	// restore when returning from f.
-	MOVQ	0(SP), AX	// our caller's PC
-	MOVQ	AX, (m_morebuf+gobuf_pc)(BX)
-	LEAQ	8(SP), AX	// our caller's SP
-	MOVQ	AX, (m_morebuf+gobuf_sp)(BX)
-	MOVQ	g(CX), AX
-	MOVQ	AX, (m_morebuf+gobuf_g)(BX)
-
-	// Set up morestack arguments to call f on a new stack.
-	// We set f's frame size to 1, as a hint to newstack
-	// that this is a call from reflect·call.
-	// If it turns out that f needs a larger frame than
-	// the default stack, f's usual stack growth prolog will
-	// allocate a new segment (and recopy the arguments).
-	MOVQ	8(SP), AX	// fn
-	MOVQ	16(SP), DX	// arg frame
-	MOVL	24(SP), CX	// arg size
-
-	MOVQ	AX, m_morepc(BX)	// f's PC
-	MOVQ	DX, m_moreargp(BX)	// argument frame pointer
-	MOVL	CX, m_moreargsize(BX)	// f's argument size
-	MOVL	$1, m_moreframesize(BX)	// f's frame size
-
-	// Call newstack on m->g0's stack.
-	MOVQ	m_g0(BX), BP
-	get_tls(CX)
-	MOVQ	BP, g(CX)
-	MOVQ	(g_sched+gobuf_sp)(BP), SP
-	CALL	runtime·newstack(SB)
-	MOVQ	$0, 0x1103	// crash if newstack returns
-	RET
-
-// Return point when leaving stack.
-TEXT runtime·lessstack(SB), 7, $0
-	// Save return value in m->cret
-	get_tls(CX)
-	MOVQ	m(CX), BX
-	MOVQ	AX, m_cret(BX)
-
-	// Call oldstack on m->g0's stack.
-	MOVQ	m_g0(BX), BP
-	MOVQ	BP, g(CX)
-	MOVQ	(g_sched+gobuf_sp)(BP), SP
-	CALL	runtime·oldstack(SB)
-	MOVQ	$0, 0x1004	// crash if oldstack returns
-	RET
-
-// morestack trampolines
-TEXT runtime·morestack00(SB),7,$0
-	get_tls(CX)
-	MOVQ	m(CX), BX
-	MOVQ	$0, AX
-	MOVQ	AX, m_moreframesize(BX)
-	MOVQ	$runtime·morestack(SB), AX
-	JMP	AX
-
-TEXT runtime·morestack01(SB),7,$0
-	get_tls(CX)
-	MOVQ	m(CX), BX
-	SHLQ	$32, AX
-	MOVQ	AX, m_moreframesize(BX)
-	MOVQ	$runtime·morestack(SB), AX
-	JMP	AX
-
-TEXT runtime·morestack10(SB),7,$0
-	get_tls(CX)
-	MOVQ	m(CX), BX
-	MOVLQZX	AX, AX
-	MOVQ	AX, m_moreframesize(BX)
-	MOVQ	$runtime·morestack(SB), AX
-	JMP	AX
-
-TEXT runtime·morestack11(SB),7,$0
-	get_tls(CX)
-	MOVQ	m(CX), BX
-	MOVQ	AX, m_moreframesize(BX)
-	MOVQ	$runtime·morestack(SB), AX
-	JMP	AX
-
-// subcases of morestack01
-// with const of 8,16,...48
-TEXT runtime·morestack8(SB),7,$0
-	PUSHQ	$1
-	MOVQ	$morestack<>(SB), AX
-	JMP	AX
-
-TEXT runtime·morestack16(SB),7,$0
-	PUSHQ	$2
-	MOVQ	$morestack<>(SB), AX
-	JMP	AX
-
-TEXT runtime·morestack24(SB),7,$0
-	PUSHQ	$3
-	MOVQ	$morestack<>(SB), AX
-	JMP	AX
-
-TEXT runtime·morestack32(SB),7,$0
-	PUSHQ	$4
-	MOVQ	$morestack<>(SB), AX
-	JMP	AX
-
-TEXT runtime·morestack40(SB),7,$0
-	PUSHQ	$5
-	MOVQ	$morestack<>(SB), AX
-	JMP	AX
-
-TEXT runtime·morestack48(SB),7,$0
-	PUSHQ	$6
-	MOVQ	$morestack<>(SB), AX
-	JMP	AX
-
-TEXT morestack<>(SB),7,$0
-	get_tls(CX)
-	MOVQ	m(CX), BX
-	POPQ	AX
-	SHLQ	$35, AX
-	MOVQ	AX, m_moreframesize(BX)
-	MOVQ	$runtime·morestack(SB), AX
-	JMP	AX
-
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·cas(SB), 7, $0
-	MOVQ	8(SP), BX
-	MOVL	16(SP), AX
-	MOVL	20(SP), CX
-	LOCK
-	CMPXCHGL	CX, 0(BX)
-	JZ 3(PC)
-	MOVL	$0, AX
-	RET
-	MOVL	$1, AX
-	RET
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·casp(SB), 7, $0
-	MOVQ	8(SP), BX
-	MOVQ	16(SP), AX
-	MOVQ	24(SP), CX
-	LOCK
-	CMPXCHGQ	CX, 0(BX)
-	JZ 3(PC)
-	MOVL	$0, AX
-	RET
-	MOVL	$1, AX
-	RET
-
-// uint32 xadd(uint32 volatile *val, int32 delta)
-// Atomically:
-//	*val += delta;
-//	return *val;
-TEXT runtime·xadd(SB), 7, $0
-	MOVQ	8(SP), BX
-	MOVL	16(SP), AX
-	MOVL	AX, CX
-	LOCK
-	XADDL	AX, 0(BX)
-	ADDL	CX, AX
-	RET
-
-TEXT runtime·xchg(SB), 7, $0
-	MOVQ	8(SP), BX
-	MOVL	16(SP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-TEXT runtime·procyield(SB),7,$0
-	MOVL	8(SP), AX
-again:
-	PAUSE
-	SUBL	$1, AX
-	JNZ	again
-	RET
-
-TEXT runtime·atomicstorep(SB), 7, $0
-	MOVQ	8(SP), BX
-	MOVQ	16(SP), AX
-	XCHGQ	AX, 0(BX)
-	RET
-
-TEXT runtime·atomicstore(SB), 7, $0
-	MOVQ	8(SP), BX
-	MOVL	16(SP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-// void jmpdefer(fn, sp);
-// called from deferreturn.
-// 1. pop the caller
-// 2. sub 5 bytes from the callers return
-// 3. jmp to the argument
-TEXT runtime·jmpdefer(SB), 7, $0
-	MOVQ	8(SP), AX	// fn
-	MOVQ	16(SP), BX	// caller sp
-	LEAQ	-8(BX), SP	// caller sp after CALL
-	SUBQ	$5, (SP)	// return to CALL again
-	JMP	AX	// but first run the deferred function
-
-// Dummy function to use in saved gobuf.PC,
-// to match SP pointing at a return address.
-// The gobuf.PC is unused by the contortions here
-// but setting it to return will make the traceback code work.
-TEXT return<>(SB),7,$0
-	RET
-
-// asmcgocall(void(*fn)(void*), void *arg)
-// Call fn(arg) on the scheduler stack,
-// aligned appropriately for the gcc ABI.
-// See cgocall.c for more details.
-TEXT runtime·asmcgocall(SB),7,$0
-	MOVQ	fn+0(FP), AX
-	MOVQ	arg+8(FP), BX
-	MOVQ	SP, DX
-
-	// Figure out if we need to switch to m->g0 stack.
-	// We get called to create new OS threads too, and those
-	// come in on the m->g0 stack already.
-	get_tls(CX)
-	MOVQ	m(CX), BP
-	MOVQ	m_g0(BP), SI
-	MOVQ	g(CX), DI
-	CMPQ	SI, DI
-	JEQ	6(PC)
-	MOVQ	SP, (g_sched+gobuf_sp)(DI)
-	MOVQ	$return<>(SB), (g_sched+gobuf_pc)(DI)
-	MOVQ	DI, (g_sched+gobuf_g)(DI)
-	MOVQ	SI, g(CX)
-	MOVQ	(g_sched+gobuf_sp)(SI), SP
-
-	// Now on a scheduling stack (a pthread-created stack).
-	SUBQ	$48, SP
-	ANDQ	$~15, SP	// alignment for gcc ABI
-	MOVQ	DI, 32(SP)	// save g
-	MOVQ	DX, 24(SP)	// save SP
-	MOVQ	BX, DI		// DI = first argument in AMD64 ABI
-	MOVQ	BX, CX		// CX = first argument in Win64
-	CALL	AX
-
-	// Restore registers, g, stack pointer.
-	get_tls(CX)
-	MOVQ	32(SP), DI
-	MOVQ	DI, g(CX)
-	MOVQ	24(SP), SP
-	RET
-
-// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
-// See cgocall.c for more details.
-TEXT runtime·cgocallback(SB),7,$24
-	MOVQ	fn+0(FP), AX
-	MOVQ	frame+8(FP), BX
-	MOVQ	framesize+16(FP), DX
-
-	// Save current m->g0->sched.sp on stack and then set it to SP.
-	get_tls(CX)
-	MOVQ	m(CX), BP
-	MOVQ	m_g0(BP), SI
-	PUSHQ	(g_sched+gobuf_sp)(SI)
-	MOVQ	SP, (g_sched+gobuf_sp)(SI)
-
-	// Switch to m->curg stack and call runtime.cgocallbackg
-	// with the three arguments.  Because we are taking over
-	// the execution of m->curg but *not* resuming what had
-	// been running, we need to save that information (m->curg->gobuf)
-	// so that we can restore it when we're done. 
-	// We can restore m->curg->gobuf.sp easily, because calling
-	// runtime.cgocallbackg leaves SP unchanged upon return.
-	// To save m->curg->gobuf.pc, we push it onto the stack.
-	// This has the added benefit that it looks to the traceback
-	// routine like cgocallbackg is going to return to that
-	// PC (because we defined cgocallbackg to have
-	// a frame size of 24, the same amount that we use below),
-	// so that the traceback will seamlessly trace back into
-	// the earlier calls.
-	MOVQ	m_curg(BP), SI
-	MOVQ	SI, g(CX)
-	MOVQ	(g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
-
-	// Push gobuf.pc
-	MOVQ	(g_sched+gobuf_pc)(SI), BP
-	SUBQ	$8, DI
-	MOVQ	BP, 0(DI)
-
-	// Push arguments to cgocallbackg.
-	// Frame size here must match the frame size above
-	// to trick traceback routines into doing the right thing.
-	SUBQ	$24, DI
-	MOVQ	AX, 0(DI)
-	MOVQ	BX, 8(DI)
-	MOVQ	DX, 16(DI)
-	
-	// Switch stack and make the call.
-	MOVQ	DI, SP
-	CALL	runtime·cgocallbackg(SB)
-
-	// Restore g->gobuf (== m->curg->gobuf) from saved values.
-	get_tls(CX)
-	MOVQ	g(CX), SI
-	MOVQ	24(SP), BP
-	MOVQ	BP, (g_sched+gobuf_pc)(SI)
-	LEAQ	(24+8)(SP), DI
-	MOVQ	DI, (g_sched+gobuf_sp)(SI)
-
-	// Switch back to m->g0's stack and restore m->g0->sched.sp.
-	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
-	// so we do not have to restore it.)
-	MOVQ	m(CX), BP
-	MOVQ	m_g0(BP), SI
-	MOVQ	SI, g(CX)
-	MOVQ	(g_sched+gobuf_sp)(SI), SP
-	POPQ	(g_sched+gobuf_sp)(SI)
-
-	// Done!
-	RET
-
-// check that SP is in range [g->stackbase, g->stackguard)
-TEXT runtime·stackcheck(SB), 7, $0
-	get_tls(CX)
-	MOVQ	g(CX), AX
-	CMPQ	g_stackbase(AX), SP
-	JHI	2(PC)
-	INT	$3
-	CMPQ	SP, g_stackguard(AX)
-	JHI	2(PC)
-	INT	$3
-	RET
-
-TEXT runtime·memclr(SB),7,$0
-	MOVQ	8(SP), DI		// arg 1 addr
-	MOVQ	16(SP), CX		// arg 2 count
-	MOVQ	CX, BX
-	ANDQ	$7, BX
-	SHRQ	$3, CX
-	MOVQ	$0, AX
-	CLD
-	REP
-	STOSQ
-	MOVQ	BX, CX
-	REP
-	STOSB
-	RET
-
-TEXT runtime·getcallerpc(SB),7,$0
-	MOVQ	x+0(FP),AX		// addr of first arg
-	MOVQ	-8(AX),AX		// get calling pc
-	RET
-
-TEXT runtime·setcallerpc(SB),7,$0
-	MOVQ	x+0(FP),AX		// addr of first arg
-	MOVQ	x+8(FP), BX
-	MOVQ	BX, -8(AX)		// set calling pc
-	RET
-
-TEXT runtime·getcallersp(SB),7,$0
-	MOVQ	sp+0(FP), AX
-	RET
-
-GLOBL runtime·tls0(SB), $64
diff --git a/src/pkg/runtime/amd64/traceback.c b/src/pkg/runtime/amd64/traceback.c
deleted file mode 100644
index c03a6f7..0000000
--- a/src/pkg/runtime/amd64/traceback.c
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "malloc.h"
-
-static uintptr isclosureentry(uintptr);
-void runtime·deferproc(void);
-void runtime·newproc(void);
-void runtime·newstack(void);
-void runtime·morestack(void);
-void runtime·sigpanic(void);
-
-// This code is also used for the 386 tracebacks.
-// Use uintptr for an appropriate word-sized integer.
-
-// Generic traceback.  Handles runtime stack prints (pcbuf == nil)
-// as well as the runtime.Callers function (pcbuf != nil).
-// A little clunky to merge the two but avoids duplicating
-// the code and all its subtlety.
-int32
-runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 max)
-{
-	byte *p;
-	int32 i, n, iter, sawnewstack;
-	uintptr pc, lr, tracepc;
-	byte *fp;
-	Stktop *stk;
-	Func *f;
-	bool waspanic;
-
-	USED(lr0);
-	pc = (uintptr)pc0;
-	lr = 0;
-	fp = nil;
-	waspanic = false;
-	
-	// If the PC is goexit, the goroutine hasn't started yet.
-	if(pc0 == g->sched.pc && sp == g->sched.sp && pc0 == (byte*)runtime·goexit) {
-		fp = sp;
-		lr = pc;
-		pc = (uintptr)g->entry;
-	}
-	
-	// If the PC is zero, it's likely a nil function call.
-	// Start in the caller's frame.
-	if(pc == 0) {
-		pc = lr;
-		lr = 0;
-	}
-
-	// If the PC is zero, it's likely a nil function call.
-	// Start in the caller's frame.
-	if(pc == 0) {
-		pc = *(uintptr*)sp;
-		sp += sizeof(uintptr);
-	}
-
-	n = 0;
-	sawnewstack = 0;
-	stk = (Stktop*)g->stackbase;
-	for(iter = 0; iter < 100 && n < max; iter++) {	// iter avoids looping forever
-		// Typically:
-		//	pc is the PC of the running function.
-		//	sp is the stack pointer at that program counter.
-		//	fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown.
-		//	stk is the stack containing sp.
-		//	The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp.
-	
-		if(pc == (uintptr)runtime·lessstack) {
-			// Hit top of stack segment.  Unwind to next segment.
-			pc = (uintptr)stk->gobuf.pc;
-			sp = stk->gobuf.sp;
-			lr = 0;
-			fp = nil;
-			if(pcbuf == nil)
-				runtime·printf("----- stack segment boundary -----\n");
-			stk = (Stktop*)stk->stackbase;
-			continue;
-		}
-		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
-			// Dangerous, but worthwhile: see if this is a closure:
-			//	ADDQ $wwxxyyzz, SP; RET
-			//	[48] 81 c4 zz yy xx ww c3
-			// The 0x48 byte is only on amd64.
-			p = (byte*)pc;
-			// We check p < p+8 to avoid wrapping and faulting if we lose track.
-			if(runtime·mheap.arena_start < p && p < p+8 && p+8 < runtime·mheap.arena_used &&  // pointer in allocated memory
-			   (sizeof(uintptr) != 8 || *p++ == 0x48) &&  // skip 0x48 byte on amd64
-			   p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
-				sp += *(uint32*)(p+2);
-				pc = *(uintptr*)sp;
-				sp += sizeof(uintptr);
-				lr = 0;
-				fp = nil;
-				continue;
-			}
-			
-			// Closure at top of stack, not yet started.
-			if(lr == (uintptr)runtime·goexit && (pc = isclosureentry(pc)) != 0) {
-				fp = sp;
-				continue;
-			}
-
-			// Unknown pc: stop.
-			break;
-		}
-
-		// Found an actual function.
-		if(fp == nil) {
-			fp = sp;
-			if(pc > f->entry && f->frame >= sizeof(uintptr))
-				fp += f->frame - sizeof(uintptr);
-			if(lr == 0)
-				lr = *(uintptr*)fp;
-			fp += sizeof(uintptr);
-		} else if(lr == 0)
-			lr = *(uintptr*)fp;
-
-		if(skip > 0)
-			skip--;
-		else if(pcbuf != nil)
-			pcbuf[n++] = pc;
-		else {
-			if(runtime·showframe(f)) {
-				// Print during crash.
-				//	main(0x1, 0x2, 0x3)
-				//		/home/rsc/go/src/runtime/x.go:23 +0xf
-				//		
-				tracepc = pc;	// back up to CALL instruction for funcline.
-				if(n > 0 && pc > f->entry && !waspanic)
-					tracepc--;
-				runtime·printf("%S(", f->name);
-				for(i = 0; i < f->args; i++) {
-					if(i != 0)
-						runtime·prints(", ");
-					runtime·printhex(((uintptr*)fp)[i]);
-					if(i >= 4) {
-						runtime·prints(", ...");
-						break;
-					}
-				}
-				runtime·prints(")\n");
-				runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc));
-				if(pc > f->entry)
-					runtime·printf(" +%p", (uintptr)(pc - f->entry));
-				runtime·printf("\n");
-			}
-			n++;
-		}
-		
-		waspanic = f->entry == (uintptr)runtime·sigpanic;
-
-		if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
-			fp += 2*sizeof(uintptr);
-
-		if(f->entry == (uintptr)runtime·newstack)
-			sawnewstack = 1;
-
-		if(pcbuf == nil && f->entry == (uintptr)runtime·morestack && g == m->g0 && sawnewstack) {
-			// The fact that we saw newstack means that morestack
-			// has managed to record its information in m, so we can
-			// use it to keep unwinding the stack.
-			runtime·printf("----- morestack called from goroutine %d -----\n", m->curg->goid);
-			pc = (uintptr)m->morepc;
-			sp = m->morebuf.sp - sizeof(void*);
-			lr = (uintptr)m->morebuf.pc;
-			fp = m->morebuf.sp;
-			sawnewstack = 0;
-			g = m->curg;
-			stk = (Stktop*)g->stackbase;
-			continue;
-		}
-
-		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && g == m->g0) {
-			// Lessstack is running on scheduler stack.  Switch to original goroutine.
-			runtime·printf("----- lessstack called from goroutine %d -----\n", m->curg->goid);
-			g = m->curg;
-			stk = (Stktop*)g->stackbase;
-			sp = stk->gobuf.sp;
-			pc = (uintptr)stk->gobuf.pc;
-			fp = nil;
-			lr = 0;
-			continue;
-		}
-
-		// Unwind to next frame.
-		pc = lr;
-		lr = 0;
-		sp = fp;
-		fp = nil;
-	}
-	
-	// Show what created goroutine, except main goroutine (goid 1).
-	if(pcbuf == nil && (pc = g->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && g->goid != 1) {
-		runtime·printf("created by %S\n", f->name);
-		tracepc = pc;	// back up to CALL instruction for funcline.
-		if(n > 0 && pc > f->entry)
-			tracepc--;
-		runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc));
-		if(pc > f->entry)
-			runtime·printf(" +%p", (uintptr)(pc - f->entry));
-		runtime·printf("\n");
-	}
-		
-	return n;
-}
-
-void
-runtime·traceback(byte *pc0, byte *sp, byte*, G *g)
-{
-	runtime·gentraceback(pc0, sp, nil, g, 0, nil, 100);
-}
-
-int32
-runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
-{
-	byte *pc, *sp;
-
-	// our caller's pc, sp.
-	sp = (byte*)&skip;
-	pc = runtime·getcallerpc(&skip);
-
-	return runtime·gentraceback(pc, sp, nil, g, skip, pcbuf, m);
-}
-
-static uintptr
-isclosureentry(uintptr pc)
-{
-	byte *p;
-	int32 i, siz;
-	
-	p = (byte*)pc;
-	if(p < runtime·mheap.arena_start || p+32 > runtime·mheap.arena_used)
-		return 0;
-
-	if(*p == 0xe8) {
-		// CALL fn
-		return pc+5+*(int32*)(p+1);
-	}
-	
-	if(sizeof(uintptr) == 8 && p[0] == 0x48 && p[1] == 0xb9 && p[10] == 0xff && p[11] == 0xd1) {
-		// MOVQ $fn, CX; CALL *CX
-		return *(uintptr*)(p+2);
-	}
-
-	// SUBQ $siz, SP
-	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0x81 || *p++ != 0xec)
-		return 0;
-	siz = *(uint32*)p;
-	p += 4;
-	
-	// MOVQ $q, SI
-	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xbe)
-		return 0;
-	p += sizeof(uintptr);
-
-	// MOVQ SP, DI
-	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0x89 || *p++ != 0xe7)
-		return 0;
-
-	// CLD on 32-bit
-	if(sizeof(uintptr) == 4 && *p++ != 0xfc)
-		return 0;
-
-	if(siz <= 4*sizeof(uintptr)) {
-		// MOVSQ...
-		for(i=0; i<siz; i+=sizeof(uintptr))
-			if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xa5)
-				return 0;
-	} else {
-		// MOVQ $(siz/8), CX  [32-bit immediate siz/8]
-		if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xc7 || *p++ != 0xc1)
-			return 0;
-		p += 4;
-		
-		// REP MOVSQ
-		if(*p++ != 0xf3 || (sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xa5)
-			return 0;
-	}
-	
-	// CALL fn
-	if(*p == 0xe8) {
-		p++;
-		return (uintptr)p+4 + *(int32*)p;
-	}
-	
-	// MOVQ $fn, CX; CALL *CX
-	if(sizeof(uintptr) != 8 || *p++ != 0x48 || *p++ != 0xb9)
-		return 0;
-
-	pc = *(uintptr*)p;
-	p += 8;
-	
-	if(*p++ != 0xff || *p != 0xd1)
-		return 0;
-
-	return pc;
-}
diff --git a/src/pkg/runtime/arch_386.h b/src/pkg/runtime/arch_386.h
new file mode 100644
index 0000000..a0798f9
--- /dev/null
+++ b/src/pkg/runtime/arch_386.h
@@ -0,0 +1,4 @@
+enum {
+	thechar = '8',
+	CacheLineSize = 64
+};
diff --git a/src/pkg/runtime/arch_amd64.h b/src/pkg/runtime/arch_amd64.h
new file mode 100644
index 0000000..dd1cfc1
--- /dev/null
+++ b/src/pkg/runtime/arch_amd64.h
@@ -0,0 +1,4 @@
+enum {
+	thechar = '6',
+	CacheLineSize = 64
+};
diff --git a/src/pkg/runtime/arch_arm.h b/src/pkg/runtime/arch_arm.h
new file mode 100644
index 0000000..c1a7a0f
--- /dev/null
+++ b/src/pkg/runtime/arch_arm.h
@@ -0,0 +1,4 @@
+enum {
+	thechar = '5',
+	CacheLineSize = 32
+};
diff --git a/src/pkg/runtime/arm/arch.h b/src/pkg/runtime/arm/arch.h
deleted file mode 100644
index 3ddb626..0000000
--- a/src/pkg/runtime/arm/arch.h
+++ /dev/null
@@ -1,3 +0,0 @@
-enum {
-	thechar = '5'
-};
diff --git a/src/pkg/runtime/arm/asm.s b/src/pkg/runtime/arm/asm.s
deleted file mode 100644
index 6315365..0000000
--- a/src/pkg/runtime/arm/asm.s
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "arm/asm.h"
-
-// using frame size $-4 means do not save LR on stack.
-TEXT _rt0_arm(SB),7,$-4
-	MOVW	$0xcafebabe, R12
-
-	// copy arguments forward on an even stack
-	// use R13 instead of SP to avoid linker rewriting the offsets
-	MOVW	0(R13), R0		// argc
-	MOVW	$4(R13), R1		// argv
-	SUB	$64, R13		// plenty of scratch
-	AND	$~7, R13
-	MOVW	R0, 60(R13)		// save argc, argv away
-	MOVW	R1, 64(R13)
-
-	// set up m and g registers
-	// g is R10, m is R9
-	MOVW	$runtime·g0(SB), g
-	MOVW	$runtime·m0(SB), m
-
-	// save m->g0 = g0
-	MOVW	g, m_g0(m)
-
-	// create istack out of the OS stack
-	MOVW	$(-8192+104)(R13), R0
-	MOVW	R0, g_stackguard(g)	// (w 104b guard)
-	MOVW	R13, g_stackbase(g)
-	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
-
-	BL	runtime·check(SB)
-
-	// saved argc, argv
-	MOVW	60(R13), R0
-	MOVW	R0, 4(R13)
-	MOVW	64(R13), R1
-	MOVW	R1, 8(R13)
-	BL	runtime·args(SB)
-	BL	runtime·osinit(SB)
-	BL	runtime·schedinit(SB)
-
-	// create a new goroutine to start program
-	MOVW	$runtime·mainstart(SB), R0
-	MOVW.W	R0, -4(R13)
-	MOVW	$8, R0
-	MOVW.W	R0, -4(R13)
-	MOVW	$0, R0
-	MOVW.W	R0, -4(R13)	// push $0 as guard
-	BL	runtime·newproc(SB)
-	MOVW	$12(R13), R13	// pop args and LR
-
-	// start this M
-	BL	runtime·mstart(SB)
-
-	MOVW	$1234, R0
-	MOVW	$1000, R1
-	MOVW	R0, (R1)	// fail hard
-	B	runtime·_dep_dummy(SB)	// Never reached
-
-
-TEXT runtime·mainstart(SB),7,$4
-	BL	main·init(SB)
-	BL	runtime·initdone(SB)
-	EOR	R0, R0
-	MOVW	R0, 0(R13)
-	BL	main·main(SB)
-	MOVW	$0, R0
-	MOVW	R0, 4(SP)
-	BL	runtime·exit(SB)
-	MOVW	$1234, R0
-	MOVW	$1001, R1
-	MOVW	R0, (R1)	// fail hard
-	RET
-
-// TODO(kaib): remove these once i actually understand how the linker removes symbols
-// pull in dummy dependencies
-TEXT runtime·_dep_dummy(SB),7,$0
-	BL	_div(SB)
-	BL	_divu(SB)
-	BL	_mod(SB)
-	BL	_modu(SB)
-	BL	_modu(SB)
-	BL	_sfloat(SB)
-
-TEXT runtime·breakpoint(SB),7,$0
-	// no breakpoint yet; let program exit
-	RET
-
-/*
- *  go-routine
- */
-
-// void gosave(Gobuf*)
-// save state in Gobuf; setjmp
-TEXT runtime·gosave(SB), 7, $-4
-	MOVW	0(FP), R0		// gobuf
-	MOVW	SP, gobuf_sp(R0)
-	MOVW	LR, gobuf_pc(R0)
-	MOVW	g, gobuf_g(R0)
-	RET
-
-// void gogo(Gobuf*, uintptr)
-// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), 7, $-4
-	MOVW	0(FP), R1		// gobuf
-	MOVW	4(FP), R0		// return 2nd arg
-	MOVW	gobuf_g(R1), g
-	MOVW	0(g), R2		// make sure g != nil
-	MOVW	gobuf_sp(R1), SP	// restore SP
-	MOVW	gobuf_pc(R1), PC
-
-// void gogocall(Gobuf*, void (*fn)(void))
-// restore state from Gobuf but then call fn.
-// (call fn, returning to state in Gobuf)
-// using frame size $-4 means do not save LR on stack.
-TEXT runtime·gogocall(SB), 7, $-4
-	MOVW	0(FP), R0		// gobuf
-	MOVW	4(FP), R1		// fn
-	MOVW	8(FP), R2		// fp offset
-	MOVW	gobuf_g(R0), g
-	MOVW	0(g), R3		// make sure g != nil
-	MOVW	gobuf_sp(R0), SP	// restore SP
-	MOVW	gobuf_pc(R0), LR
-	MOVW	R1, PC
-
-// void mcall(void (*fn)(G*))
-// Switch to m->g0's stack, call fn(g).
-// Fn must never return.  It should gogo(&g->sched)
-// to keep running g.
-TEXT runtime·mcall(SB), 7, $-4
-	MOVW	fn+0(FP), R0
-
-	// Save caller state in g->gobuf.
-	MOVW	SP, (g_sched+gobuf_sp)(g)
-	MOVW	LR, (g_sched+gobuf_pc)(g)
-	MOVW	g, (g_sched+gobuf_g)(g)
-
-	// Switch to m->g0 & its stack, call fn.
-	MOVW	g, R1
-	MOVW	m_g0(m), g
-	CMP	g, R1
-	BL.EQ	runtime·badmcall(SB)
-	MOVW	(g_sched+gobuf_sp)(g), SP
-	SUB	$8, SP
-	MOVW	R1, 4(SP)
-	BL	(R0)
-	BL	runtime·badmcall2(SB)
-	RET
-
-/*
- * support for morestack
- */
-
-// Called during function prolog when more stack is needed.
-// R1 frame size
-// R2 arg size
-// R3 prolog's LR
-// NB. we do not save R0 because we've forced 5c to pass all arguments
-// on the stack.
-// using frame size $-4 means do not save LR on stack.
-TEXT runtime·morestack(SB),7,$-4
-	// Cannot grow scheduler stack (m->g0).
-	MOVW	m_g0(m), R4
-	CMP	g, R4
-	BL.EQ	runtime·abort(SB)
-
-	// Save in m.
-	MOVW	R1, m_moreframesize(m)
-	MOVW	R2, m_moreargsize(m)
-
-	// Called from f.
-	// Set m->morebuf to f's caller.
-	MOVW	R3, (m_morebuf+gobuf_pc)(m)	// f's caller's PC
-	MOVW	SP, (m_morebuf+gobuf_sp)(m)	// f's caller's SP
-	MOVW	$4(SP), R3			// f's argument pointer
-	MOVW	R3, m_moreargp(m)	
-	MOVW	g, (m_morebuf+gobuf_g)(m)
-
-	// Set m->morepc to f's PC.
-	MOVW	LR, m_morepc(m)
-
-	// Call newstack on m->g0's stack.
-	MOVW	m_g0(m), g
-	MOVW	(g_sched+gobuf_sp)(g), SP
-	B	runtime·newstack(SB)
-
-// Called from reflection library.  Mimics morestack,
-// reuses stack growth code to create a frame
-// with the desired args running the desired function.
-//
-// func call(fn *byte, arg *byte, argsize uint32).
-TEXT reflect·call(SB), 7, $-4
-	// Save our caller's state as the PC and SP to
-	// restore when returning from f.
-	MOVW	LR, (m_morebuf+gobuf_pc)(m)	// our caller's PC
-	MOVW	SP, (m_morebuf+gobuf_sp)(m)	// our caller's SP
-	MOVW	g,  (m_morebuf+gobuf_g)(m)
-
-	// Set up morestack arguments to call f on a new stack.
-	// We set f's frame size to 1, as a hint to newstack
-	// that this is a call from reflect·call.
-	// If it turns out that f needs a larger frame than
-	// the default stack, f's usual stack growth prolog will
-	// allocate a new segment (and recopy the arguments).
-	MOVW	4(SP), R0			// fn
-	MOVW	8(SP), R1			// arg frame
-	MOVW	12(SP), R2			// arg size
-
-	MOVW	R0, m_morepc(m)			// f's PC
-	MOVW	R1, m_moreargp(m)		// f's argument pointer
-	MOVW	R2, m_moreargsize(m)		// f's argument size
-	MOVW	$1, R3
-	MOVW	R3, m_moreframesize(m)		// f's frame size
-
-	// Call newstack on m->g0's stack.
-	MOVW	m_g0(m), g
-	MOVW	(g_sched+gobuf_sp)(g), SP
-	B	runtime·newstack(SB)
-
-// Return point when leaving stack.
-// using frame size $-4 means do not save LR on stack.
-TEXT runtime·lessstack(SB), 7, $-4
-	// Save return value in m->cret
-	MOVW	R0, m_cret(m)
-
-	// Call oldstack on m->g0's stack.
-	MOVW	m_g0(m), g
-	MOVW	(g_sched+gobuf_sp)(g), SP
-	B	runtime·oldstack(SB)
-
-// void jmpdefer(fn, sp);
-// called from deferreturn.
-// 1. grab stored LR for caller
-// 2. sub 4 bytes to get back to BL deferreturn
-// 3. B to fn
-TEXT runtime·jmpdefer(SB), 7, $0
-	MOVW	0(SP), LR
-	MOVW	$-4(LR), LR	// BL deferreturn
-	MOVW	fn+0(FP), R0
-	MOVW	argp+4(FP), SP
-	MOVW	$-4(SP), SP	// SP is 4 below argp, due to saved LR
-	B		(R0)
-
-TEXT	runtime·asmcgocall(SB),7,$0
-	B	runtime·cgounimpl(SB)
-
-TEXT	runtime·cgocallback(SB),7,$0
-	B	runtime·cgounimpl(SB)
-
-TEXT runtime·memclr(SB),7,$20
-	MOVW	0(FP), R0
-	MOVW	$0, R1		// c = 0
-	MOVW	R1, -16(SP)
-	MOVW	4(FP), R1	// n
-	MOVW	R1, -12(SP)
-	MOVW	m, -8(SP)	// Save m and g
-	MOVW	g, -4(SP)
-	BL	runtime·memset(SB)
-	MOVW	-8(SP), m	// Restore m and g, memset clobbers them
-	MOVW	-4(SP), g
-	RET
-
-TEXT runtime·getcallerpc(SB),7,$-4
-	MOVW	0(SP), R0
-	RET
-
-TEXT runtime·setcallerpc(SB),7,$-4
-	MOVW	x+4(FP), R0
-	MOVW	R0, 0(SP)
-	RET
-
-TEXT runtime·getcallersp(SB),7,$-4
-	MOVW	0(FP), R0
-	MOVW	$-4(R0), R0
-	RET
-
-TEXT runtime·emptyfunc(SB),0,$0
-	RET
-
-TEXT runtime·abort(SB),7,$-4
-	MOVW	$0, R0
-	MOVW	(R0), R1
-
-// bool armcas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	}else
-//		return 0;
-//
-// To implement runtime·cas in ../$GOOS/arm/sys.s
-// using the native instructions, use:
-//
-//	TEXT runtime·cas(SB),7,$0
-//		B	runtime·armcas(SB)
-//
-TEXT runtime·armcas(SB),7,$0
-	MOVW	valptr+0(FP), R1
-	MOVW	old+4(FP), R2
-	MOVW	new+8(FP), R3
-casl:
-	LDREX	(R1), R0
-	CMP		R0, R2
-	BNE		casfail
-	STREX	R3, (R1), R0
-	CMP		$0, R0
-	BNE		casl
-	MOVW	$1, R0
-	RET
-casfail:
-	MOVW	$0, R0
-	RET
diff --git a/src/pkg/runtime/arm/softfloat.c b/src/pkg/runtime/arm/softfloat.c
deleted file mode 100644
index 0a071da..0000000
--- a/src/pkg/runtime/arm/softfloat.c
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Software floating point interpretaton of ARM 7500 FP instructions.
-// The interpretation is not bit compatible with the 7500.
-// It uses true little-endian doubles, while the 7500 used mixed-endian.
-
-#include "runtime.h"
-
-#define CPSR 14
-#define FLAGS_N (1 << 31)
-#define FLAGS_Z (1 << 30)
-#define FLAGS_C (1 << 29)
-#define FLAGS_V (1 << 28)
-
-void	runtime·abort(void);
-void	math·sqrtGoC(uint64, uint64*);
-
-static	uint32	trace = 0;
-
-static void
-fabort(void)
-{
-	if (1) {
-		runtime·printf("Unsupported floating point instruction\n");
-		runtime·abort();
-	}
-}
-
-static void
-putf(uint32 reg, uint32 val)
-{
-	m->freglo[reg] = val;
-}
-
-static void
-putd(uint32 reg, uint64 val)
-{
-	m->freglo[reg] = (uint32)val;
-	m->freghi[reg] = (uint32)(val>>32);
-}
-
-static uint64
-getd(uint32 reg)
-{
-	return (uint64)m->freglo[reg] | ((uint64)m->freghi[reg]<<32);
-}
-
-static void
-fprint(void)
-{
-	uint32 i;
-	for (i = 0; i < 16; i++) {
-		runtime·printf("\tf%d:\t%X %X\n", i, m->freghi[i], m->freglo[i]);
-	}
-}
-
-static uint32
-d2f(uint64 d)
-{
-	uint32 x;
-
-	runtime·f64to32c(d, &x);
-	return x;
-}
-
-static uint64
-f2d(uint32 f)
-{
-	uint64 x;
-
-	runtime·f32to64c(f, &x);
-	return x;
-}
-
-static uint32
-fstatus(bool nan, int32 cmp)
-{
-	if(nan)
-		return FLAGS_C | FLAGS_V;
-	if(cmp == 0)
-		return FLAGS_Z | FLAGS_C;
-	if(cmp < 0)
-		return FLAGS_N;
-	return FLAGS_C;
-}
-
-// returns number of words that the fp instruction
-// is occupying, 0 if next instruction isn't float.
-static uint32
-stepflt(uint32 *pc, uint32 *regs)
-{
-	uint32 i, regd, regm, regn;
-	int32 delta;
-	uint32 *addr;
-	uint64 uval;
-	int64 sval;
-	bool nan, ok;
-	int32 cmp;
-
-	i = *pc;
-
-	if(trace)
-		runtime·printf("stepflt %p %x\n", pc, i);
-
-	// special cases
-	if((i&0xfffff000) == 0xe59fb000) {
-		// load r11 from pc-relative address.
-		// might be part of a floating point move
-		// (or might not, but no harm in simulating
-		// one instruction too many).
-		addr = (uint32*)((uint8*)pc + (i&0xfff) + 8);
-		regs[11] = addr[0];
-
-		if(trace)
-			runtime·printf("*** cpu R[%d] = *(%p) %x\n",
-				11, addr, regs[11]);
-		return 1;
-	}
-	if(i == 0xe08bb00d) {
-		// add sp to r11.
-		// might be part of a large stack offset address
-		// (or might not, but again no harm done).
-		regs[11] += regs[13];
-
-		if(trace)
-			runtime·printf("*** cpu R[%d] += R[%d] %x\n",
-				11, 13, regs[11]);
-		return 1;
-	}
-	if(i == 0xeef1fa10) {
-		regs[CPSR] = (regs[CPSR]&0x0fffffff) | m->fflag;
-
-		if(trace)
-			runtime·printf("*** fpsr R[CPSR] = F[CPSR] %x\n", regs[CPSR]);
-		return 1;
-	}
-	if((i&0xff000000) == 0xea000000) {
-		// unconditional branch
-		// can happen in the middle of floating point
-		// if the linker decides it is time to lay down
-		// a sequence of instruction stream constants.
-		delta = i&0xffffff;
-		delta = (delta<<8) >> 8;	// sign extend
-
-		if(trace)
-			runtime·printf("*** cpu PC += %x\n", (delta+2)*4);
-		return delta+2;
-	}
-
-	goto stage1;
-
-stage1:	// load/store regn is cpureg, regm is 8bit offset
-	regd = i>>12 & 0xf;
-	regn = i>>16 & 0xf;
-	regm = (i & 0xff) << 2;	// PLUS or MINUS ??
-
-	switch(i & 0xfff00f00) {
-	default:
-		goto stage2;
-
-	case 0xed900a00:	// single load
-		addr = (uint32*)(regs[regn] + regm);
-		m->freglo[regd] = addr[0];
-
-		if(trace)
-			runtime·printf("*** load F[%d] = %x\n",
-				regd, m->freglo[regd]);
-		break;
-
-	case 0xed900b00:	// double load
-		addr = (uint32*)(regs[regn] + regm);
-		m->freglo[regd] = addr[0];
-		m->freghi[regd] = addr[1];
-
-		if(trace)
-			runtime·printf("*** load D[%d] = %x-%x\n",
-				regd, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xed800a00:	// single store
-		addr = (uint32*)(regs[regn] + regm);
-		addr[0] = m->freglo[regd];
-
-		if(trace)
-			runtime·printf("*** *(%p) = %x\n",
-				addr, addr[0]);
-		break;
-
-	case 0xed800b00:	// double store
-		addr = (uint32*)(regs[regn] + regm);
-		addr[0] = m->freglo[regd];
-		addr[1] = m->freghi[regd];
-
-		if(trace)
-			runtime·printf("*** *(%p) = %x-%x\n",
-				addr, addr[1], addr[0]);
-		break;
-	}
-	return 1;
-
-stage2:	// regd, regm, regn are 4bit variables
-	regm = i>>0 & 0xf;
-	switch(i & 0xfff00ff0) {
-	default:
-		goto stage3;
-
-	case 0xf3000110:	// veor
-		m->freglo[regd] = m->freglo[regm]^m->freglo[regn];
-		m->freghi[regd] = m->freghi[regm]^m->freghi[regn];
-
-		if(trace)
-			runtime·printf("*** veor D[%d] = %x-%x\n",
-				regd, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeeb00b00:	// D[regd] = const(regn,regm)
-		regn = (regn<<4) | regm;
-		regm = 0x40000000UL;
-		if(regn & 0x80)
-			regm |= 0x80000000UL;
-		if(regn & 0x40)
-			regm ^= 0x7fc00000UL;
-		regm |= (regn & 0x3f) << 16;
-		m->freglo[regd] = 0;
-		m->freghi[regd] = regm;
-
-		if(trace)
-			runtime·printf("*** immed D[%d] = %x-%x\n",
-				regd, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeeb00a00:	// F[regd] = const(regn,regm)
-		regn = (regn<<4) | regm;
-		regm = 0x40000000UL;
-		if(regn & 0x80)
-			regm |= 0x80000000UL;
-		if(regn & 0x40)
-			regm ^= 0x7e000000UL;
-		regm |= (regn & 0x3f) << 19;
-		m->freglo[regd] = regm;
-
-		if(trace)
-			runtime·printf("*** immed D[%d] = %x\n",
-				regd, m->freglo[regd]);
-		break;
-
-	case 0xee300b00:	// D[regd] = D[regn]+D[regm]
-		runtime·fadd64c(getd(regn), getd(regm), &uval);
-		putd(regd, uval);
-
-		if(trace)
-			runtime·printf("*** add D[%d] = D[%d]+D[%d] %x-%x\n",
-				regd, regn, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xee300a00:	// F[regd] = F[regn]+F[regm]
-		runtime·fadd64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
-		m->freglo[regd] = d2f(uval);
-
-		if(trace)
-			runtime·printf("*** add F[%d] = F[%d]+F[%d] %x\n",
-				regd, regn, regm, m->freglo[regd]);
-		break;
-
-	case 0xee300b40:	// D[regd] = D[regn]-D[regm]
-		runtime·fsub64c(getd(regn), getd(regm), &uval);
-		putd(regd, uval);
-
-		if(trace)
-			runtime·printf("*** sub D[%d] = D[%d]-D[%d] %x-%x\n",
-				regd, regn, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xee300a40:	// F[regd] = F[regn]-F[regm]
-		runtime·fsub64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
-		m->freglo[regd] = d2f(uval);
-
-		if(trace)
-			runtime·printf("*** sub F[%d] = F[%d]-F[%d] %x\n",
-				regd, regn, regm, m->freglo[regd]);
-		break;
-
-	case 0xee200b00:	// D[regd] = D[regn]*D[regm]
-		runtime·fmul64c(getd(regn), getd(regm), &uval);
-		putd(regd, uval);
-
-		if(trace)
-			runtime·printf("*** mul D[%d] = D[%d]*D[%d] %x-%x\n",
-				regd, regn, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xee200a00:	// F[regd] = F[regn]*F[regm]
-		runtime·fmul64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
-		m->freglo[regd] = d2f(uval);
-
-		if(trace)
-			runtime·printf("*** mul F[%d] = F[%d]*F[%d] %x\n",
-				regd, regn, regm, m->freglo[regd]);
-		break;
-
-	case 0xee800b00:	// D[regd] = D[regn]/D[regm]
-		runtime·fdiv64c(getd(regn), getd(regm), &uval);
-		putd(regd, uval);
-
-		if(trace)
-			runtime·printf("*** div D[%d] = D[%d]/D[%d] %x-%x\n",
-				regd, regn, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xee800a00:	// F[regd] = F[regn]/F[regm]
-		runtime·fdiv64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
-		m->freglo[regd] = d2f(uval);
-
-		if(trace)
-			runtime·printf("*** div F[%d] = F[%d]/F[%d] %x\n",
-				regd, regn, regm, m->freglo[regd]);
-		break;
-
-	case 0xee000b10:	// S[regn] = R[regd] (MOVW) (regm ignored)
-		m->freglo[regn] = regs[regd];
-
-		if(trace)
-			runtime·printf("*** cpy S[%d] = R[%d] %x\n",
-				regn, regd, m->freglo[regn]);
-		break;
-
-	case 0xee100b10:	// R[regd] = S[regn] (MOVW) (regm ignored)
-		regs[regd] = m->freglo[regn];
-
-		if(trace)
-			runtime·printf("*** cpy R[%d] = S[%d] %x\n",
-				regd, regn, regs[regd]);
-		break;
-	}
-	return 1;
-
-stage3:	// regd, regm are 4bit variables
-	switch(i & 0xffff0ff0) {
-	default:
-		goto done;
-
-	case 0xeeb00a40:	// F[regd] = F[regm] (MOVF)
-		m->freglo[regd] = m->freglo[regm];
-
-		if(trace)
-			runtime·printf("*** F[%d] = F[%d] %x\n",
-				regd, regm, m->freglo[regd]);
-		break;
-
-	case 0xeeb00b40:	// D[regd] = D[regm] (MOVD)
-		m->freglo[regd] = m->freglo[regm];
-		m->freghi[regd] = m->freghi[regm];
-
-		if(trace)
-			runtime·printf("*** D[%d] = D[%d] %x-%x\n",
-				regd, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeeb10bc0:	// D[regd] = sqrt D[regm]
-		math·sqrtGoC(getd(regm), &uval);
-		putd(regd, uval);
-
-		if(trace)
-			runtime·printf("*** D[%d] = sqrt D[%d] %x-%x\n",
-				regd, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeeb40bc0:	// D[regd] :: D[regm] (CMPD)
-		runtime·fcmp64c(getd(regd), getd(regm), &cmp, &nan);
-		m->fflag = fstatus(nan, cmp);
-
-		if(trace)
-			runtime·printf("*** cmp D[%d]::D[%d] %x\n",
-				regd, regm, m->fflag);
-		break;
-
-	case 0xeeb40ac0:	// F[regd] :: F[regm] (CMPF)
-		runtime·fcmp64c(f2d(m->freglo[regd]), f2d(m->freglo[regm]), &cmp, &nan);
-		m->fflag = fstatus(nan, cmp);
-
-		if(trace)
-			runtime·printf("*** cmp F[%d]::F[%d] %x\n",
-				regd, regm, m->fflag);
-		break;
-
-	case 0xeeb70ac0:	// D[regd] = F[regm] (MOVFD)
-		putd(regd, f2d(m->freglo[regm]));
-
-		if(trace)
-			runtime·printf("*** f2d D[%d]=F[%d] %x-%x\n",
-				regd, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeeb70bc0:	// F[regd] = D[regm] (MOVDF)
-		m->freglo[regd] = d2f(getd(regm));
-
-		if(trace)
-			runtime·printf("*** d2f F[%d]=D[%d] %x-%x\n",
-				regd, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeebd0ac0:	// S[regd] = F[regm] (MOVFW)
-		runtime·f64tointc(f2d(m->freglo[regm]), &sval, &ok);
-		if(!ok || (int32)sval != sval)
-			sval = 0;
-		m->freglo[regd] = sval;
-
-		if(trace)
-			runtime·printf("*** fix S[%d]=F[%d] %x\n",
-				regd, regm, m->freglo[regd]);
-		break;
-
-	case 0xeebc0ac0:	// S[regd] = F[regm] (MOVFW.U)
-		runtime·f64tointc(f2d(m->freglo[regm]), &sval, &ok);
-		if(!ok || (uint32)sval != sval)
-			sval = 0;
-		m->freglo[regd] = sval;
-
-		if(trace)
-			runtime·printf("*** fix unsigned S[%d]=F[%d] %x\n",
-				regd, regm, m->freglo[regd]);
-		break;
-
-	case 0xeebd0bc0:	// S[regd] = D[regm] (MOVDW)
-		runtime·f64tointc(getd(regm), &sval, &ok);
-		if(!ok || (int32)sval != sval)
-			sval = 0;
-		m->freglo[regd] = sval;
-
-		if(trace)
-			runtime·printf("*** fix S[%d]=D[%d] %x\n",
-				regd, regm, m->freglo[regd]);
-		break;
-
-	case 0xeebc0bc0:	// S[regd] = D[regm] (MOVDW.U)
-		runtime·f64tointc(getd(regm), &sval, &ok);
-		if(!ok || (uint32)sval != sval)
-			sval = 0;
-		m->freglo[regd] = sval;
-
-		if(trace)
-			runtime·printf("*** fix unsigned S[%d]=D[%d] %x\n",
-				regd, regm, m->freglo[regd]);
-		break;
-
-	case 0xeeb80ac0:	// D[regd] = S[regm] (MOVWF)
-		cmp = m->freglo[regm];
-		if(cmp < 0) {
-			runtime·fintto64c(-cmp, &uval);
-			putf(regd, d2f(uval));
-			m->freglo[regd] ^= 0x80000000;
-		} else {
-			runtime·fintto64c(cmp, &uval);
-			putf(regd, d2f(uval));
-		}
-
-		if(trace)
-			runtime·printf("*** float D[%d]=S[%d] %x-%x\n",
-				regd, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeeb80a40:	// D[regd] = S[regm] (MOVWF.U)
-		runtime·fintto64c(m->freglo[regm], &uval);
-		putf(regd, d2f(uval));
-
-		if(trace)
-			runtime·printf("*** float unsigned D[%d]=S[%d] %x-%x\n",
-				regd, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeeb80bc0:	// D[regd] = S[regm] (MOVWD)
-		cmp = m->freglo[regm];
-		if(cmp < 0) {
-			runtime·fintto64c(-cmp, &uval);
-			putd(regd, uval);
-			m->freghi[regd] ^= 0x80000000;
-		} else {
-			runtime·fintto64c(cmp, &uval);
-			putd(regd, uval);
-		}
-
-		if(trace)
-			runtime·printf("*** float D[%d]=S[%d] %x-%x\n",
-				regd, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-
-	case 0xeeb80b40:	// D[regd] = S[regm] (MOVWD.U)
-		runtime·fintto64c(m->freglo[regm], &uval);
-		putd(regd, uval);
-
-		if(trace)
-			runtime·printf("*** float unsigned D[%d]=S[%d] %x-%x\n",
-				regd, regm, m->freghi[regd], m->freglo[regd]);
-		break;
-	}
-	return 1;
-
-done:
-	if((i&0xff000000) == 0xee000000 ||
-	   (i&0xff000000) == 0xed000000) {
-		runtime·printf("stepflt %p %x\n", pc, i);
-		fabort();
-	}
-	return 0;
-}
-
-#pragma textflag 7
-uint32*
-runtime·_sfloat2(uint32 *lr, uint32 r0)
-{
-	uint32 skip;
-
-	skip = stepflt(lr, &r0);
-	if(skip == 0) {
-		runtime·printf("sfloat2 %p %x\n", lr, *lr);
-		fabort(); // not ok to fail first instruction
-	}
-
-	lr += skip;
-	while(skip = stepflt(lr, &r0))
-		lr += skip;
-	return lr;
-}
diff --git a/src/pkg/runtime/arm/traceback.c b/src/pkg/runtime/arm/traceback.c
deleted file mode 100644
index 6352810..0000000
--- a/src/pkg/runtime/arm/traceback.c
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "malloc.h"
-
-void runtime·deferproc(void);
-void runtime·newproc(void);
-void runtime·newstack(void);
-void runtime·morestack(void);
-void runtime·sigpanic(void);
-void _div(void);
-void _mod(void);
-void _divu(void);
-void _modu(void);
-
-int32
-runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 max)
-{
-	int32 i, n, iter;
-	uintptr pc, lr, tracepc, x;
-	byte *fp, *p;
-	bool waspanic;
-	Stktop *stk;
-	Func *f;
-	
-	pc = (uintptr)pc0;
-	lr = (uintptr)lr0;
-	fp = nil;
-	waspanic = false;
-
-	// If the PC is goexit, the goroutine hasn't started yet.
-	if(pc == (uintptr)runtime·goexit) {
-		pc = (uintptr)g->entry;
-		lr = (uintptr)runtime·goexit;
-	}
-
-	// If the PC is zero, it's likely a nil function call.
-	// Start in the caller's frame.
-	if(pc == 0) {
-		pc = lr;
-		lr = 0;
-	}
-
-	n = 0;
-	stk = (Stktop*)g->stackbase;
-	for(iter = 0; iter < 100 && n < max; iter++) {	// iter avoids looping forever
-		// Typically:
-		//	pc is the PC of the running function.
-		//	sp is the stack pointer at that program counter.
-		//	fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown.
-		//	stk is the stack containing sp.
-		//	The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp.
-		
-		if(pc == (uintptr)runtime·lessstack) {
-			// Hit top of stack segment.  Unwind to next segment.
-			pc = (uintptr)stk->gobuf.pc;
-			sp = stk->gobuf.sp;
-			lr = 0;
-			fp = nil;
-			if(pcbuf == nil)
-				runtime·printf("----- stack segment boundary -----\n");
-			stk = (Stktop*)stk->stackbase;
-			continue;
-		}
-		
-		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
-			// Dangerous, but worthwhile: see if this is a closure by
-			// decoding the instruction stream.
-			//
-			// We check p < p+4 to avoid wrapping and faulting if
-			// we have lost track of where we are.
-			p = (byte*)pc;
-			if((pc&3) == 0 && p < p+4 &&
-			   runtime·mheap.arena_start < p &&
-			   p+4 < runtime·mheap.arena_used) {
-			   	x = *(uintptr*)p;
-				if((x&0xfffff000) == 0xe49df000) {
-					// End of closure:
-					// MOVW.P frame(R13), R15
-					pc = *(uintptr*)sp;
-					lr = 0;
-					sp += x & 0xfff;
-					fp = nil;
-					continue;
-				}
-				if((x&0xfffff000) == 0xe52de000 && lr == (uintptr)runtime·goexit) {
-					// Beginning of closure.
-					// Closure at top of stack, not yet started.
-					p += 5*4;
-					if((x&0xfff) != 4) {
-						// argument copying
-						p += 7*4;
-					}
-					if((byte*)pc < p && p < p+4 && p+4 < runtime·mheap.arena_used) {
-						pc = *(uintptr*)p;
-						fp = nil;
-						continue;
-					}
-				}
-			}
-			break;
-		}
-		
-		// Found an actual function.
-		if(lr == 0)
-			lr = *(uintptr*)sp;
-		if(fp == nil) {
-			fp = sp;
-			if(pc > f->entry && f->frame >= 0)
-				fp += f->frame;
-		}
-
-		if(skip > 0)
-			skip--;
-		else if(pcbuf != nil)
-			pcbuf[n++] = pc;
-		else {
-			if(runtime·showframe(f)) {
-				// Print during crash.
-				//	main(0x1, 0x2, 0x3)
-				//		/home/rsc/go/src/runtime/x.go:23 +0xf
-				tracepc = pc;	// back up to CALL instruction for funcline.
-				if(n > 0 && pc > f->entry && !waspanic)
-					tracepc -= sizeof(uintptr);
-				runtime·printf("%S(", f->name);
-				for(i = 0; i < f->args; i++) {
-					if(i != 0)
-						runtime·prints(", ");
-					runtime·printhex(((uintptr*)fp)[1+i]);
-					if(i >= 4) {
-						runtime·prints(", ...");
-						break;
-					}
-				}
-				runtime·prints(")\n");
-				runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc));
-				if(pc > f->entry)
-					runtime·printf(" +%p", (uintptr)(pc - f->entry));
-				runtime·printf("\n");
-			}
-			n++;
-		}
-		
-		waspanic = f->entry == (uintptr)runtime·sigpanic;
-
-		if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && g == m->g0) {
-			runtime·printf("----- newstack called from goroutine %d -----\n", m->curg->goid);
-			pc = (uintptr)m->morepc;
-			sp = (byte*)m->moreargp - sizeof(void*);
-			lr = (uintptr)m->morebuf.pc;
-			fp = m->morebuf.sp;
-			g = m->curg;
-			stk = (Stktop*)g->stackbase;
-			continue;
-		}
-		
-		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && g == m->g0) {
-			runtime·printf("----- lessstack called from goroutine %d -----\n", m->curg->goid);
-			g = m->curg;
-			stk = (Stktop*)g->stackbase;
-			sp = stk->gobuf.sp;
-			pc = (uintptr)stk->gobuf.pc;
-			fp = nil;
-			lr = 0;
-			continue;
-		}	
-		
-		// Unwind to next frame.
-		pc = lr;
-		lr = 0;
-		sp = fp;
-		fp = nil;
-		
-		// If this was div or divu or mod or modu, the caller had
-		// an extra 8 bytes on its stack.  Adjust sp.
-		if(f->entry == (uintptr)_div || f->entry == (uintptr)_divu || f->entry == (uintptr)_mod || f->entry == (uintptr)_modu)
-			sp += 8;
-		
-		// If this was deferproc or newproc, the caller had an extra 12.
-		if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
-			sp += 12;
-	}
-	
-	if(pcbuf == nil && (pc = g->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && g->goid != 1) {
-		runtime·printf("created by %S\n", f->name);
-		tracepc = pc;	// back up to CALL instruction for funcline.
-		if(n > 0 && pc > f->entry)
-			tracepc -= sizeof(uintptr);
-		runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc));
-		if(pc > f->entry)
-			runtime·printf(" +%p", (uintptr)(pc - f->entry));
-		runtime·printf("\n");
-	}
-
-	return n;		
-}
-
-void
-runtime·traceback(byte *pc0, byte *sp, byte *lr, G *g)
-{
-	runtime·gentraceback(pc0, sp, lr, g, 0, nil, 100);
-}
-
-// func caller(n int) (pc uintptr, file string, line int, ok bool)
-int32
-runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
-{
-	byte *pc, *sp;
-	
-	sp = runtime·getcallersp(&skip);
-	pc = runtime·getcallerpc(&skip);
-
-	return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m);
-}
diff --git a/src/pkg/runtime/asm_386.s b/src/pkg/runtime/asm_386.s
new file mode 100644
index 0000000..5240063
--- /dev/null
+++ b/src/pkg/runtime/asm_386.s
@@ -0,0 +1,544 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "zasm_GOOS_GOARCH.h"
+
+TEXT _rt0_386(SB),7,$0
+	// Linux, Windows start the FPU in extended double precision.
+	// Other operating systems use double precision.
+	// Change to double precision to match them,
+	// and to match other hardware that only has double.
+	PUSHL $0x27F
+	FLDCW	0(SP)
+	POPL AX
+
+	// copy arguments forward on an even stack
+	MOVL	0(SP), AX		// argc
+	LEAL	4(SP), BX		// argv
+	SUBL	$128, SP		// plenty of scratch
+	ANDL	$~15, SP
+	MOVL	AX, 120(SP)		// save argc, argv away
+	MOVL	BX, 124(SP)
+
+	// set default stack bounds.
+	// initcgo may update stackguard.
+	MOVL	$runtime·g0(SB), BP
+	LEAL	(-64*1024+104)(SP), BX
+	MOVL	BX, g_stackguard(BP)
+	MOVL	SP, g_stackbase(BP)
+	
+	// if there is an initcgo, call it to let it
+	// initialize and to set up GS.  if not,
+	// we set up GS ourselves.
+	MOVL	initcgo(SB), AX
+	TESTL	AX, AX
+	JZ	needtls
+	PUSHL	BP
+	CALL	AX
+	POPL	BP
+	// skip runtime·ldt0setup(SB) and tls test after initcgo for non-windows
+	CMPL runtime·iswindows(SB), $0
+	JEQ ok
+needtls:
+	// skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases
+	CMPL	runtime·isplan9(SB), $1
+	JEQ	ok
+
+	// set up %gs
+	CALL	runtime·ldt0setup(SB)
+
+	// store through it, to make sure it works
+	get_tls(BX)
+	MOVL	$0x123, g(BX)
+	MOVL	runtime·tls0(SB), AX
+	CMPL	AX, $0x123
+	JEQ	ok
+	MOVL	AX, 0	// abort
+ok:
+	// set up m and g "registers"
+	get_tls(BX)
+	LEAL	runtime·g0(SB), CX
+	MOVL	CX, g(BX)
+	LEAL	runtime·m0(SB), AX
+	MOVL	AX, m(BX)
+
+	// save m->g0 = g0
+	MOVL	CX, m_g0(AX)
+
+	CALL	runtime·emptyfunc(SB)	// fault if stack check is wrong
+
+	// convention is D is always cleared
+	CLD
+
+	CALL	runtime·check(SB)
+
+	// saved argc, argv
+	MOVL	120(SP), AX
+	MOVL	AX, 0(SP)
+	MOVL	124(SP), AX
+	MOVL	AX, 4(SP)
+	CALL	runtime·args(SB)
+	CALL	runtime·osinit(SB)
+	CALL	runtime·schedinit(SB)
+
+	// create a new goroutine to start program
+	PUSHL	$runtime·main(SB)	// entry
+	PUSHL	$0	// arg size
+	CALL	runtime·newproc(SB)
+	POPL	AX
+	POPL	AX
+
+	// start this M
+	CALL	runtime·mstart(SB)
+
+	INT $3
+	RET
+
+TEXT runtime·breakpoint(SB),7,$0
+	INT $3
+	RET
+
+/*
+ *  go-routine
+ */
+
+// void gosave(Gobuf*)
+// save state in Gobuf; setjmp
+TEXT runtime·gosave(SB), 7, $0
+	MOVL	4(SP), AX		// gobuf
+	LEAL	4(SP), BX		// caller's SP
+	MOVL	BX, gobuf_sp(AX)
+	MOVL	0(SP), BX		// caller's PC
+	MOVL	BX, gobuf_pc(AX)
+	get_tls(CX)
+	MOVL	g(CX), BX
+	MOVL	BX, gobuf_g(AX)
+	RET
+
+// void gogo(Gobuf*, uintptr)
+// restore state from Gobuf; longjmp
+TEXT runtime·gogo(SB), 7, $0
+	MOVL	8(SP), AX		// return 2nd arg
+	MOVL	4(SP), BX		// gobuf
+	MOVL	gobuf_g(BX), DX
+	MOVL	0(DX), CX		// make sure g != nil
+	get_tls(CX)
+	MOVL	DX, g(CX)
+	MOVL	gobuf_sp(BX), SP	// restore SP
+	MOVL	gobuf_pc(BX), BX
+	JMP	BX
+
+// void gogocall(Gobuf*, void (*fn)(void))
+// restore state from Gobuf but then call fn.
+// (call fn, returning to state in Gobuf)
+TEXT runtime·gogocall(SB), 7, $0
+	MOVL	8(SP), AX		// fn
+	MOVL	4(SP), BX		// gobuf
+	MOVL	gobuf_g(BX), DX
+	get_tls(CX)
+	MOVL	DX, g(CX)
+	MOVL	0(DX), CX		// make sure g != nil
+	MOVL	gobuf_sp(BX), SP	// restore SP
+	MOVL	gobuf_pc(BX), BX
+	PUSHL	BX
+	JMP	AX
+	POPL	BX	// not reached
+
+// void mcall(void (*fn)(G*))
+// Switch to m->g0's stack, call fn(g).
+// Fn must never return.  It should gogo(&g->sched)
+// to keep running g.
+TEXT runtime·mcall(SB), 7, $0
+	MOVL	fn+0(FP), DI
+	
+	get_tls(CX)
+	MOVL	g(CX), AX	// save state in g->gobuf
+	MOVL	0(SP), BX	// caller's PC
+	MOVL	BX, (g_sched+gobuf_pc)(AX)
+	LEAL	4(SP), BX	// caller's SP
+	MOVL	BX, (g_sched+gobuf_sp)(AX)
+	MOVL	AX, (g_sched+gobuf_g)(AX)
+
+	// switch to m->g0 & its stack, call fn
+	MOVL	m(CX), BX
+	MOVL	m_g0(BX), SI
+	CMPL	SI, AX	// if g == m->g0 call badmcall
+	JNE	2(PC)
+	CALL	runtime·badmcall(SB)
+	MOVL	SI, g(CX)	// g = m->g0
+	MOVL	(g_sched+gobuf_sp)(SI), SP	// sp = m->g0->gobuf.sp
+	PUSHL	AX
+	CALL	DI
+	POPL	AX
+	CALL	runtime·badmcall2(SB)
+	RET
+
+/*
+ * support for morestack
+ */
+
+// Called during function prolog when more stack is needed.
+TEXT runtime·morestack(SB),7,$0
+	// Cannot grow scheduler stack (m->g0).
+	get_tls(CX)
+	MOVL	m(CX), BX
+	MOVL	m_g0(BX), SI
+	CMPL	g(CX), SI
+	JNE	2(PC)
+	INT	$3
+
+	// frame size in DX
+	// arg size in AX
+	// Save in m.
+	MOVL	DX, m_moreframesize(BX)
+	MOVL	AX, m_moreargsize(BX)
+
+	// Called from f.
+	// Set m->morebuf to f's caller.
+	MOVL	4(SP), DI	// f's caller's PC
+	MOVL	DI, (m_morebuf+gobuf_pc)(BX)
+	LEAL	8(SP), CX	// f's caller's SP
+	MOVL	CX, (m_morebuf+gobuf_sp)(BX)
+	MOVL	CX, m_moreargp(BX)
+	get_tls(CX)
+	MOVL	g(CX), SI
+	MOVL	SI, (m_morebuf+gobuf_g)(BX)
+
+	// Set m->morepc to f's PC.
+	MOVL	0(SP), AX
+	MOVL	AX, m_morepc(BX)
+
+	// Call newstack on m->g0's stack.
+	MOVL	m_g0(BX), BP
+	MOVL	BP, g(CX)
+	MOVL	(g_sched+gobuf_sp)(BP), AX
+	MOVL	-4(AX), BX	// fault if CALL would, before smashing SP
+	MOVL	AX, SP
+	CALL	runtime·newstack(SB)
+	MOVL	$0, 0x1003	// crash if newstack returns
+	RET
+
+// Called from reflection library.  Mimics morestack,
+// reuses stack growth code to create a frame
+// with the desired args running the desired function.
+//
+// func call(fn *byte, arg *byte, argsize uint32).
+TEXT reflect·call(SB), 7, $0
+	get_tls(CX)
+	MOVL	m(CX), BX
+
+	// Save our caller's state as the PC and SP to
+	// restore when returning from f.
+	MOVL	0(SP), AX	// our caller's PC
+	MOVL	AX, (m_morebuf+gobuf_pc)(BX)
+	LEAL	4(SP), AX	// our caller's SP
+	MOVL	AX, (m_morebuf+gobuf_sp)(BX)
+	MOVL	g(CX), AX
+	MOVL	AX, (m_morebuf+gobuf_g)(BX)
+
+	// Set up morestack arguments to call f on a new stack.
+	// We set f's frame size to 1, as a hint to newstack
+	// that this is a call from reflect·call.
+	// If it turns out that f needs a larger frame than
+	// the default stack, f's usual stack growth prolog will
+	// allocate a new segment (and recopy the arguments).
+	MOVL	4(SP), AX	// fn
+	MOVL	8(SP), DX	// arg frame
+	MOVL	12(SP), CX	// arg size
+
+	MOVL	AX, m_morepc(BX)	// f's PC
+	MOVL	DX, m_moreargp(BX)	// f's argument pointer
+	MOVL	CX, m_moreargsize(BX)	// f's argument size
+	MOVL	$1, m_moreframesize(BX)	// f's frame size
+
+	// Call newstack on m->g0's stack.
+	MOVL	m_g0(BX), BP
+	get_tls(CX)
+	MOVL	BP, g(CX)
+	MOVL	(g_sched+gobuf_sp)(BP), SP
+	CALL	runtime·newstack(SB)
+	MOVL	$0, 0x1103	// crash if newstack returns
+	RET
+
+
+// Return point when leaving stack.
+TEXT runtime·lessstack(SB), 7, $0
+	// Save return value in m->cret
+	get_tls(CX)
+	MOVL	m(CX), BX
+	MOVL	AX, m_cret(BX)
+
+	// Call oldstack on m->g0's stack.
+	MOVL	m_g0(BX), BP
+	MOVL	BP, g(CX)
+	MOVL	(g_sched+gobuf_sp)(BP), SP
+	CALL	runtime·oldstack(SB)
+	MOVL	$0, 0x1004	// crash if oldstack returns
+	RET
+
+
+// bool cas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	}else
+//		return 0;
+TEXT runtime·cas(SB), 7, $0
+	MOVL	4(SP), BX
+	MOVL	8(SP), AX
+	MOVL	12(SP), CX
+	LOCK
+	CMPXCHGL	CX, 0(BX)
+	JZ 3(PC)
+	MOVL	$0, AX
+	RET
+	MOVL	$1, AX
+	RET
+
+// bool casp(void **p, void *old, void *new)
+// Atomically:
+//	if(*p == old){
+//		*p = new;
+//		return 1;
+//	}else
+//		return 0;
+TEXT runtime·casp(SB), 7, $0
+	MOVL	4(SP), BX
+	MOVL	8(SP), AX
+	MOVL	12(SP), CX
+	LOCK
+	CMPXCHGL	CX, 0(BX)
+	JZ 3(PC)
+	MOVL	$0, AX
+	RET
+	MOVL	$1, AX
+	RET
+
+// uint32 xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+//	*val += delta;
+//	return *val;
+TEXT runtime·xadd(SB), 7, $0
+	MOVL	4(SP), BX
+	MOVL	8(SP), AX
+	MOVL	AX, CX
+	LOCK
+	XADDL	AX, 0(BX)
+	ADDL	CX, AX
+	RET
+
+TEXT runtime·xchg(SB), 7, $0
+	MOVL	4(SP), BX
+	MOVL	8(SP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+TEXT runtime·procyield(SB),7,$0
+	MOVL	4(SP), AX
+again:
+	PAUSE
+	SUBL	$1, AX
+	JNZ	again
+	RET
+
+TEXT runtime·atomicstorep(SB), 7, $0
+	MOVL	4(SP), BX
+	MOVL	8(SP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+TEXT runtime·atomicstore(SB), 7, $0
+	MOVL	4(SP), BX
+	MOVL	8(SP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+// void jmpdefer(fn, sp);
+// called from deferreturn.
+// 1. pop the caller
+// 2. sub 5 bytes from the callers return
+// 3. jmp to the argument
+TEXT runtime·jmpdefer(SB), 7, $0
+	MOVL	4(SP), AX	// fn
+	MOVL	8(SP), BX	// caller sp
+	LEAL	-4(BX), SP	// caller sp after CALL
+	SUBL	$5, (SP)	// return to CALL again
+	JMP	AX	// but first run the deferred function
+
+// Dummy function to use in saved gobuf.PC,
+// to match SP pointing at a return address.
+// The gobuf.PC is unused by the contortions here
+// but setting it to return will make the traceback code work.
+TEXT return<>(SB),7,$0
+	RET
+
+// asmcgocall(void(*fn)(void*), void *arg)
+// Call fn(arg) on the scheduler stack,
+// aligned appropriately for the gcc ABI.
+// See cgocall.c for more details.
+TEXT runtime·asmcgocall(SB),7,$0
+	MOVL	fn+0(FP), AX
+	MOVL	arg+4(FP), BX
+	MOVL	SP, DX
+
+	// Figure out if we need to switch to m->g0 stack.
+	// We get called to create new OS threads too, and those
+	// come in on the m->g0 stack already.
+	get_tls(CX)
+	MOVL	m(CX), BP
+	MOVL	m_g0(BP), SI
+	MOVL	g(CX), DI
+	CMPL	SI, DI
+	JEQ	6(PC)
+	MOVL	SP, (g_sched+gobuf_sp)(DI)
+	MOVL	$return<>(SB), (g_sched+gobuf_pc)(DI)
+	MOVL	DI, (g_sched+gobuf_g)(DI)
+	MOVL	SI, g(CX)
+	MOVL	(g_sched+gobuf_sp)(SI), SP
+
+	// Now on a scheduling stack (a pthread-created stack).
+	SUBL	$32, SP
+	ANDL	$~15, SP	// alignment, perhaps unnecessary
+	MOVL	DI, 8(SP)	// save g
+	MOVL	DX, 4(SP)	// save SP
+	MOVL	BX, 0(SP)	// first argument in x86-32 ABI
+	CALL	AX
+
+	// Restore registers, g, stack pointer.
+	get_tls(CX)
+	MOVL	8(SP), DI
+	MOVL	DI, g(CX)
+	MOVL	4(SP), SP
+	RET
+
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// See cgocall.c for more details.
+TEXT runtime·cgocallback(SB),7,$12
+	MOVL	fn+0(FP), AX
+	MOVL	frame+4(FP), BX
+	MOVL	framesize+8(FP), DX
+
+	// Save current m->g0->sched.sp on stack and then set it to SP.
+	get_tls(CX)
+	MOVL	m(CX), BP
+	MOVL	m_g0(BP), SI
+	PUSHL	(g_sched+gobuf_sp)(SI)
+	MOVL	SP, (g_sched+gobuf_sp)(SI)
+
+	// Switch to m->curg stack and call runtime.cgocallbackg
+	// with the three arguments.  Because we are taking over
+	// the execution of m->curg but *not* resuming what had
+	// been running, we need to save that information (m->curg->gobuf)
+	// so that we can restore it when we're done. 
+	// We can restore m->curg->gobuf.sp easily, because calling
+	// runtime.cgocallbackg leaves SP unchanged upon return.
+	// To save m->curg->gobuf.pc, we push it onto the stack.
+	// This has the added benefit that it looks to the traceback
+	// routine like cgocallbackg is going to return to that
+	// PC (because we defined cgocallbackg to have
+	// a frame size of 12, the same amount that we use below),
+	// so that the traceback will seamlessly trace back into
+	// the earlier calls.
+	MOVL	m_curg(BP), SI
+	MOVL	SI, g(CX)
+	MOVL	(g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
+
+	// Push gobuf.pc
+	MOVL	(g_sched+gobuf_pc)(SI), BP
+	SUBL	$4, DI
+	MOVL	BP, 0(DI)
+
+	// Push arguments to cgocallbackg.
+	// Frame size here must match the frame size above
+	// to trick traceback routines into doing the right thing.
+	SUBL	$12, DI
+	MOVL	AX, 0(DI)
+	MOVL	BX, 4(DI)
+	MOVL	DX, 8(DI)
+	
+	// Switch stack and make the call.
+	MOVL	DI, SP
+	CALL	runtime·cgocallbackg(SB)
+
+	// Restore g->gobuf (== m->curg->gobuf) from saved values.
+	get_tls(CX)
+	MOVL	g(CX), SI
+	MOVL	12(SP), BP
+	MOVL	BP, (g_sched+gobuf_pc)(SI)
+	LEAL	(12+4)(SP), DI
+	MOVL	DI, (g_sched+gobuf_sp)(SI)
+
+	// Switch back to m->g0's stack and restore m->g0->sched.sp.
+	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
+	// so we do not have to restore it.)
+	MOVL	m(CX), BP
+	MOVL	m_g0(BP), SI
+	MOVL	SI, g(CX)
+	MOVL	(g_sched+gobuf_sp)(SI), SP
+	POPL	(g_sched+gobuf_sp)(SI)
+
+	// Done!
+	RET
+
+// check that SP is in range [g->stackbase, g->stackguard)
+TEXT runtime·stackcheck(SB), 7, $0
+	get_tls(CX)
+	MOVL	g(CX), AX
+	CMPL	g_stackbase(AX), SP
+	JHI	2(PC)
+	INT	$3
+	CMPL	SP, g_stackguard(AX)
+	JHI	2(PC)
+	INT	$3
+	RET
+
+TEXT runtime·memclr(SB),7,$0
+	MOVL	4(SP), DI		// arg 1 addr
+	MOVL	8(SP), CX		// arg 2 count
+	MOVL	CX, BX
+	ANDL	$3, BX
+	SHRL	$2, CX
+	MOVL	$0, AX
+	CLD
+	REP
+	STOSL
+	MOVL	BX, CX
+	REP
+	STOSB
+	RET
+
+TEXT runtime·getcallerpc(SB),7,$0
+	MOVL	x+0(FP),AX		// addr of first arg
+	MOVL	-4(AX),AX		// get calling pc
+	RET
+
+TEXT runtime·setcallerpc(SB),7,$0
+	MOVL	x+0(FP),AX		// addr of first arg
+	MOVL	x+4(FP), BX
+	MOVL	BX, -4(AX)		// set calling pc
+	RET
+
+TEXT runtime·getcallersp(SB), 7, $0
+	MOVL	sp+0(FP), AX
+	RET
+
+TEXT runtime·ldt0setup(SB),7,$16
+	// set up ldt 7 to point at tls0
+	// ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go.
+	// the entry number is just a hint.  setldt will set up GS with what it used.
+	MOVL	$7, 0(SP)
+	LEAL	runtime·tls0(SB), AX
+	MOVL	AX, 4(SP)
+	MOVL	$32, 8(SP)	// sizeof(tls array)
+	CALL	runtime·setldt(SB)
+	RET
+
+TEXT runtime·emptyfunc(SB),0,$0
+	RET
+
+TEXT runtime·abort(SB),7,$0
+	INT $0x3
+
+GLOBL runtime·tls0(SB), $32
diff --git a/src/pkg/runtime/asm_amd64.s b/src/pkg/runtime/asm_amd64.s
new file mode 100644
index 0000000..308a660
--- /dev/null
+++ b/src/pkg/runtime/asm_amd64.s
@@ -0,0 +1,571 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "zasm_GOOS_GOARCH.h"
+
+TEXT _rt0_amd64(SB),7,$-8
+	// copy arguments forward on an even stack
+	MOVQ	0(DI), AX		// argc
+	LEAQ	8(DI), BX		// argv
+	SUBQ	$(4*8+7), SP		// 2args 2auto
+	ANDQ	$~15, SP
+	MOVQ	AX, 16(SP)
+	MOVQ	BX, 24(SP)
+	
+	// create istack out of the given (operating system) stack.
+	// initcgo may update stackguard.
+	MOVQ	$runtime·g0(SB), DI
+	LEAQ	(-64*1024+104)(SP), BX
+	MOVQ	BX, g_stackguard(DI)
+	MOVQ	SP, g_stackbase(DI)
+
+	// if there is an initcgo, call it.
+	MOVQ	initcgo(SB), AX
+	TESTQ	AX, AX
+	JZ	needtls
+	// g0 already in DI
+	MOVQ	DI, CX	// Win64 uses CX for first parameter
+	CALL	AX
+	CMPL	runtime·iswindows(SB), $0
+	JEQ ok
+
+needtls:
+	LEAQ	runtime·tls0(SB), DI
+	CALL	runtime·settls(SB)
+
+	// store through it, to make sure it works
+	get_tls(BX)
+	MOVQ	$0x123, g(BX)
+	MOVQ	runtime·tls0(SB), AX
+	CMPQ	AX, $0x123
+	JEQ 2(PC)
+	MOVL	AX, 0	// abort
+ok:
+	// set the per-goroutine and per-mach "registers"
+	get_tls(BX)
+	LEAQ	runtime·g0(SB), CX
+	MOVQ	CX, g(BX)
+	LEAQ	runtime·m0(SB), AX
+	MOVQ	AX, m(BX)
+
+	// save m->g0 = g0
+	MOVQ	CX, m_g0(AX)
+
+	CLD				// convention is D is always left cleared
+	CALL	runtime·check(SB)
+
+	MOVL	16(SP), AX		// copy argc
+	MOVL	AX, 0(SP)
+	MOVQ	24(SP), AX		// copy argv
+	MOVQ	AX, 8(SP)
+	CALL	runtime·args(SB)
+	CALL	runtime·osinit(SB)
+	CALL	runtime·schedinit(SB)
+
+	// create a new goroutine to start program
+	PUSHQ	$runtime·main(SB)		// entry
+	PUSHQ	$0			// arg size
+	CALL	runtime·newproc(SB)
+	POPQ	AX
+	POPQ	AX
+
+	// start this M
+	CALL	runtime·mstart(SB)
+
+	CALL	runtime·notok(SB)		// never returns
+	RET
+
+TEXT runtime·breakpoint(SB),7,$0
+	BYTE	$0xcc
+	RET
+
+/*
+ *  go-routine
+ */
+
+// void gosave(Gobuf*)
+// save state in Gobuf; setjmp
+TEXT runtime·gosave(SB), 7, $0
+	MOVQ	8(SP), AX		// gobuf
+	LEAQ	8(SP), BX		// caller's SP
+	MOVQ	BX, gobuf_sp(AX)
+	MOVQ	0(SP), BX		// caller's PC
+	MOVQ	BX, gobuf_pc(AX)
+	get_tls(CX)
+	MOVQ	g(CX), BX
+	MOVQ	BX, gobuf_g(AX)
+	RET
+
+// void gogo(Gobuf*, uintptr)
+// restore state from Gobuf; longjmp
+TEXT runtime·gogo(SB), 7, $0
+	MOVQ	16(SP), AX		// return 2nd arg
+	MOVQ	8(SP), BX		// gobuf
+	MOVQ	gobuf_g(BX), DX
+	MOVQ	0(DX), CX		// make sure g != nil
+	get_tls(CX)
+	MOVQ	DX, g(CX)
+	MOVQ	gobuf_sp(BX), SP	// restore SP
+	MOVQ	gobuf_pc(BX), BX
+	JMP	BX
+
+// void gogocall(Gobuf*, void (*fn)(void))
+// restore state from Gobuf but then call fn.
+// (call fn, returning to state in Gobuf)
+TEXT runtime·gogocall(SB), 7, $0
+	MOVQ	16(SP), AX		// fn
+	MOVQ	8(SP), BX		// gobuf
+	MOVQ	gobuf_g(BX), DX
+	get_tls(CX)
+	MOVQ	DX, g(CX)
+	MOVQ	0(DX), CX	// make sure g != nil
+	MOVQ	gobuf_sp(BX), SP	// restore SP
+	MOVQ	gobuf_pc(BX), BX
+	PUSHQ	BX
+	JMP	AX
+	POPQ	BX	// not reached
+
+// void mcall(void (*fn)(G*))
+// Switch to m->g0's stack, call fn(g).
+// Fn must never return.  It should gogo(&g->sched)
+// to keep running g.
+TEXT runtime·mcall(SB), 7, $0
+	MOVQ	fn+0(FP), DI
+	
+	get_tls(CX)
+	MOVQ	g(CX), AX	// save state in g->gobuf
+	MOVQ	0(SP), BX	// caller's PC
+	MOVQ	BX, (g_sched+gobuf_pc)(AX)
+	LEAQ	8(SP), BX	// caller's SP
+	MOVQ	BX, (g_sched+gobuf_sp)(AX)
+	MOVQ	AX, (g_sched+gobuf_g)(AX)
+
+	// switch to m->g0 & its stack, call fn
+	MOVQ	m(CX), BX
+	MOVQ	m_g0(BX), SI
+	CMPQ	SI, AX	// if g == m->g0 call badmcall
+	JNE	2(PC)
+	CALL	runtime·badmcall(SB)
+	MOVQ	SI, g(CX)	// g = m->g0
+	MOVQ	(g_sched+gobuf_sp)(SI), SP	// sp = m->g0->gobuf.sp
+	PUSHQ	AX
+	CALL	DI
+	POPQ	AX
+	CALL	runtime·badmcall2(SB)
+	RET
+
+/*
+ * support for morestack
+ */
+
+// Called during function prolog when more stack is needed.
+// Caller has already done get_tls(CX); MOVQ m(CX), BX.
+TEXT runtime·morestack(SB),7,$0
+	// Cannot grow scheduler stack (m->g0).
+	MOVQ	m_g0(BX), SI
+	CMPQ	g(CX), SI
+	JNE	2(PC)
+	INT	$3
+
+	// Called from f.
+	// Set m->morebuf to f's caller.
+	MOVQ	8(SP), AX	// f's caller's PC
+	MOVQ	AX, (m_morebuf+gobuf_pc)(BX)
+	LEAQ	16(SP), AX	// f's caller's SP
+	MOVQ	AX, (m_morebuf+gobuf_sp)(BX)
+	MOVQ	AX, m_moreargp(BX)
+	get_tls(CX)
+	MOVQ	g(CX), SI
+	MOVQ	SI, (m_morebuf+gobuf_g)(BX)
+
+	// Set m->morepc to f's PC.
+	MOVQ	0(SP), AX
+	MOVQ	AX, m_morepc(BX)
+
+	// Call newstack on m->g0's stack.
+	MOVQ	m_g0(BX), BP
+	MOVQ	BP, g(CX)
+	MOVQ	(g_sched+gobuf_sp)(BP), SP
+	CALL	runtime·newstack(SB)
+	MOVQ	$0, 0x1003	// crash if newstack returns
+	RET
+
+// Called from reflection library.  Mimics morestack,
+// reuses stack growth code to create a frame
+// with the desired args running the desired function.
+//
+// func call(fn *byte, arg *byte, argsize uint32).
+TEXT reflect·call(SB), 7, $0
+	get_tls(CX)
+	MOVQ	m(CX), BX
+
+	// Save our caller's state as the PC and SP to
+	// restore when returning from f.
+	MOVQ	0(SP), AX	// our caller's PC
+	MOVQ	AX, (m_morebuf+gobuf_pc)(BX)
+	LEAQ	8(SP), AX	// our caller's SP
+	MOVQ	AX, (m_morebuf+gobuf_sp)(BX)
+	MOVQ	g(CX), AX
+	MOVQ	AX, (m_morebuf+gobuf_g)(BX)
+
+	// Set up morestack arguments to call f on a new stack.
+	// We set f's frame size to 1, as a hint to newstack
+	// that this is a call from reflect·call.
+	// If it turns out that f needs a larger frame than
+	// the default stack, f's usual stack growth prolog will
+	// allocate a new segment (and recopy the arguments).
+	MOVQ	8(SP), AX	// fn
+	MOVQ	16(SP), DX	// arg frame
+	MOVL	24(SP), CX	// arg size
+
+	MOVQ	AX, m_morepc(BX)	// f's PC
+	MOVQ	DX, m_moreargp(BX)	// argument frame pointer
+	MOVL	CX, m_moreargsize(BX)	// f's argument size
+	MOVL	$1, m_moreframesize(BX)	// f's frame size
+
+	// Call newstack on m->g0's stack.
+	MOVQ	m_g0(BX), BP
+	get_tls(CX)
+	MOVQ	BP, g(CX)
+	MOVQ	(g_sched+gobuf_sp)(BP), SP
+	CALL	runtime·newstack(SB)
+	MOVQ	$0, 0x1103	// crash if newstack returns
+	RET
+
+// Return point when leaving stack.
+TEXT runtime·lessstack(SB), 7, $0
+	// Save return value in m->cret
+	get_tls(CX)
+	MOVQ	m(CX), BX
+	MOVQ	AX, m_cret(BX)
+
+	// Call oldstack on m->g0's stack.
+	MOVQ	m_g0(BX), BP
+	MOVQ	BP, g(CX)
+	MOVQ	(g_sched+gobuf_sp)(BP), SP
+	CALL	runtime·oldstack(SB)
+	MOVQ	$0, 0x1004	// crash if oldstack returns
+	RET
+
+// morestack trampolines
+TEXT runtime·morestack00(SB),7,$0
+	get_tls(CX)
+	MOVQ	m(CX), BX
+	MOVQ	$0, AX
+	MOVQ	AX, m_moreframesize(BX)
+	MOVQ	$runtime·morestack(SB), AX
+	JMP	AX
+
+TEXT runtime·morestack01(SB),7,$0
+	get_tls(CX)
+	MOVQ	m(CX), BX
+	SHLQ	$32, AX
+	MOVQ	AX, m_moreframesize(BX)
+	MOVQ	$runtime·morestack(SB), AX
+	JMP	AX
+
+TEXT runtime·morestack10(SB),7,$0
+	get_tls(CX)
+	MOVQ	m(CX), BX
+	MOVLQZX	AX, AX
+	MOVQ	AX, m_moreframesize(BX)
+	MOVQ	$runtime·morestack(SB), AX
+	JMP	AX
+
+TEXT runtime·morestack11(SB),7,$0
+	get_tls(CX)
+	MOVQ	m(CX), BX
+	MOVQ	AX, m_moreframesize(BX)
+	MOVQ	$runtime·morestack(SB), AX
+	JMP	AX
+
+// subcases of morestack01
+// with const of 8,16,...48
+TEXT runtime·morestack8(SB),7,$0
+	PUSHQ	$1
+	MOVQ	$morestack<>(SB), AX
+	JMP	AX
+
+TEXT runtime·morestack16(SB),7,$0
+	PUSHQ	$2
+	MOVQ	$morestack<>(SB), AX
+	JMP	AX
+
+TEXT runtime·morestack24(SB),7,$0
+	PUSHQ	$3
+	MOVQ	$morestack<>(SB), AX
+	JMP	AX
+
+TEXT runtime·morestack32(SB),7,$0
+	PUSHQ	$4
+	MOVQ	$morestack<>(SB), AX
+	JMP	AX
+
+TEXT runtime·morestack40(SB),7,$0
+	PUSHQ	$5
+	MOVQ	$morestack<>(SB), AX
+	JMP	AX
+
+TEXT runtime·morestack48(SB),7,$0
+	PUSHQ	$6
+	MOVQ	$morestack<>(SB), AX
+	JMP	AX
+
+TEXT morestack<>(SB),7,$0
+	get_tls(CX)
+	MOVQ	m(CX), BX
+	POPQ	AX
+	SHLQ	$35, AX
+	MOVQ	AX, m_moreframesize(BX)
+	MOVQ	$runtime·morestack(SB), AX
+	JMP	AX
+
+// bool cas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime·cas(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVL	16(SP), AX
+	MOVL	20(SP), CX
+	LOCK
+	CMPXCHGL	CX, 0(BX)
+	JZ 3(PC)
+	MOVL	$0, AX
+	RET
+	MOVL	$1, AX
+	RET
+
+// bool casp(void **val, void *old, void *new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime·casp(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVQ	16(SP), AX
+	MOVQ	24(SP), CX
+	LOCK
+	CMPXCHGQ	CX, 0(BX)
+	JZ 3(PC)
+	MOVL	$0, AX
+	RET
+	MOVL	$1, AX
+	RET
+
+// uint32 xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+//	*val += delta;
+//	return *val;
+TEXT runtime·xadd(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVL	16(SP), AX
+	MOVL	AX, CX
+	LOCK
+	XADDL	AX, 0(BX)
+	ADDL	CX, AX
+	RET
+
+TEXT runtime·xchg(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVL	16(SP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+TEXT runtime·procyield(SB),7,$0
+	MOVL	8(SP), AX
+again:
+	PAUSE
+	SUBL	$1, AX
+	JNZ	again
+	RET
+
+TEXT runtime·atomicstorep(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVQ	16(SP), AX
+	XCHGQ	AX, 0(BX)
+	RET
+
+TEXT runtime·atomicstore(SB), 7, $0
+	MOVQ	8(SP), BX
+	MOVL	16(SP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+// void jmpdefer(fn, sp);
+// called from deferreturn.
+// 1. pop the caller
+// 2. sub 5 bytes from the callers return
+// 3. jmp to the argument
+TEXT runtime·jmpdefer(SB), 7, $0
+	MOVQ	8(SP), AX	// fn
+	MOVQ	16(SP), BX	// caller sp
+	LEAQ	-8(BX), SP	// caller sp after CALL
+	SUBQ	$5, (SP)	// return to CALL again
+	JMP	AX	// but first run the deferred function
+
+// Dummy function to use in saved gobuf.PC,
+// to match SP pointing at a return address.
+// The gobuf.PC is unused by the contortions here
+// but setting it to return will make the traceback code work.
+TEXT return<>(SB),7,$0
+	RET
+
+// asmcgocall(void(*fn)(void*), void *arg)
+// Call fn(arg) on the scheduler stack,
+// aligned appropriately for the gcc ABI.
+// See cgocall.c for more details.
+TEXT runtime·asmcgocall(SB),7,$0
+	MOVQ	fn+0(FP), AX
+	MOVQ	arg+8(FP), BX
+	MOVQ	SP, DX
+
+	// Figure out if we need to switch to m->g0 stack.
+	// We get called to create new OS threads too, and those
+	// come in on the m->g0 stack already.
+	get_tls(CX)
+	MOVQ	m(CX), BP
+	MOVQ	m_g0(BP), SI
+	MOVQ	g(CX), DI
+	CMPQ	SI, DI
+	JEQ	6(PC)
+	MOVQ	SP, (g_sched+gobuf_sp)(DI)
+	MOVQ	$return<>(SB), (g_sched+gobuf_pc)(DI)
+	MOVQ	DI, (g_sched+gobuf_g)(DI)
+	MOVQ	SI, g(CX)
+	MOVQ	(g_sched+gobuf_sp)(SI), SP
+
+	// Now on a scheduling stack (a pthread-created stack).
+	SUBQ	$48, SP
+	ANDQ	$~15, SP	// alignment for gcc ABI
+	MOVQ	DI, 32(SP)	// save g
+	MOVQ	DX, 24(SP)	// save SP
+	MOVQ	BX, DI		// DI = first argument in AMD64 ABI
+	MOVQ	BX, CX		// CX = first argument in Win64
+	CALL	AX
+
+	// Restore registers, g, stack pointer.
+	get_tls(CX)
+	MOVQ	32(SP), DI
+	MOVQ	DI, g(CX)
+	MOVQ	24(SP), SP
+	RET
+
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// See cgocall.c for more details.
+TEXT runtime·cgocallback(SB),7,$24
+	MOVQ	fn+0(FP), AX
+	MOVQ	frame+8(FP), BX
+	MOVQ	framesize+16(FP), DX
+
+	// Save current m->g0->sched.sp on stack and then set it to SP.
+	get_tls(CX)
+	MOVQ	m(CX), BP
+	MOVQ	m_g0(BP), SI
+	PUSHQ	(g_sched+gobuf_sp)(SI)
+	MOVQ	SP, (g_sched+gobuf_sp)(SI)
+
+	// Switch to m->curg stack and call runtime.cgocallbackg
+	// with the three arguments.  Because we are taking over
+	// the execution of m->curg but *not* resuming what had
+	// been running, we need to save that information (m->curg->gobuf)
+	// so that we can restore it when we're done. 
+	// We can restore m->curg->gobuf.sp easily, because calling
+	// runtime.cgocallbackg leaves SP unchanged upon return.
+	// To save m->curg->gobuf.pc, we push it onto the stack.
+	// This has the added benefit that it looks to the traceback
+	// routine like cgocallbackg is going to return to that
+	// PC (because we defined cgocallbackg to have
+	// a frame size of 24, the same amount that we use below),
+	// so that the traceback will seamlessly trace back into
+	// the earlier calls.
+	MOVQ	m_curg(BP), SI
+	MOVQ	SI, g(CX)
+	MOVQ	(g_sched+gobuf_sp)(SI), DI  // prepare stack as DI
+
+	// Push gobuf.pc
+	MOVQ	(g_sched+gobuf_pc)(SI), BP
+	SUBQ	$8, DI
+	MOVQ	BP, 0(DI)
+
+	// Push arguments to cgocallbackg.
+	// Frame size here must match the frame size above
+	// to trick traceback routines into doing the right thing.
+	SUBQ	$24, DI
+	MOVQ	AX, 0(DI)
+	MOVQ	BX, 8(DI)
+	MOVQ	DX, 16(DI)
+	
+	// Switch stack and make the call.
+	MOVQ	DI, SP
+	CALL	runtime·cgocallbackg(SB)
+
+	// Restore g->gobuf (== m->curg->gobuf) from saved values.
+	get_tls(CX)
+	MOVQ	g(CX), SI
+	MOVQ	24(SP), BP
+	MOVQ	BP, (g_sched+gobuf_pc)(SI)
+	LEAQ	(24+8)(SP), DI
+	MOVQ	DI, (g_sched+gobuf_sp)(SI)
+
+	// Switch back to m->g0's stack and restore m->g0->sched.sp.
+	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
+	// so we do not have to restore it.)
+	MOVQ	m(CX), BP
+	MOVQ	m_g0(BP), SI
+	MOVQ	SI, g(CX)
+	MOVQ	(g_sched+gobuf_sp)(SI), SP
+	POPQ	(g_sched+gobuf_sp)(SI)
+
+	// Done!
+	RET
+
+// check that SP is in range [g->stackbase, g->stackguard)
+TEXT runtime·stackcheck(SB), 7, $0
+	get_tls(CX)
+	MOVQ	g(CX), AX
+	CMPQ	g_stackbase(AX), SP
+	JHI	2(PC)
+	INT	$3
+	CMPQ	SP, g_stackguard(AX)
+	JHI	2(PC)
+	INT	$3
+	RET
+
+TEXT runtime·memclr(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 addr
+	MOVQ	16(SP), CX		// arg 2 count
+	MOVQ	CX, BX
+	ANDQ	$7, BX
+	SHRQ	$3, CX
+	MOVQ	$0, AX
+	CLD
+	REP
+	STOSQ
+	MOVQ	BX, CX
+	REP
+	STOSB
+	RET
+
+TEXT runtime·getcallerpc(SB),7,$0
+	MOVQ	x+0(FP),AX		// addr of first arg
+	MOVQ	-8(AX),AX		// get calling pc
+	RET
+
+TEXT runtime·setcallerpc(SB),7,$0
+	MOVQ	x+0(FP),AX		// addr of first arg
+	MOVQ	x+8(FP), BX
+	MOVQ	BX, -8(AX)		// set calling pc
+	RET
+
+TEXT runtime·getcallersp(SB),7,$0
+	MOVQ	sp+0(FP), AX
+	RET
+
+GLOBL runtime·tls0(SB), $64
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s
new file mode 100644
index 0000000..42c7677
--- /dev/null
+++ b/src/pkg/runtime/asm_arm.s
@@ -0,0 +1,301 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "zasm_GOOS_GOARCH.h"
+
+// using frame size $-4 means do not save LR on stack.
+TEXT _rt0_arm(SB),7,$-4
+	MOVW	$0xcafebabe, R12
+
+	// copy arguments forward on an even stack
+	// use R13 instead of SP to avoid linker rewriting the offsets
+	MOVW	0(R13), R0		// argc
+	MOVW	$4(R13), R1		// argv
+	SUB	$64, R13		// plenty of scratch
+	AND	$~7, R13
+	MOVW	R0, 60(R13)		// save argc, argv away
+	MOVW	R1, 64(R13)
+
+	// set up m and g registers
+	// g is R10, m is R9
+	MOVW	$runtime·g0(SB), g
+	MOVW	$runtime·m0(SB), m
+
+	// save m->g0 = g0
+	MOVW	g, m_g0(m)
+
+	// create istack out of the OS stack
+	MOVW	$(-8192+104)(R13), R0
+	MOVW	R0, g_stackguard(g)	// (w 104b guard)
+	MOVW	R13, g_stackbase(g)
+	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
+
+	BL	runtime·check(SB)
+
+	// saved argc, argv
+	MOVW	60(R13), R0
+	MOVW	R0, 4(R13)
+	MOVW	64(R13), R1
+	MOVW	R1, 8(R13)
+	BL	runtime·args(SB)
+	BL	runtime·osinit(SB)
+	BL	runtime·schedinit(SB)
+
+	// create a new goroutine to start program
+	MOVW	$runtime·main(SB), R0
+	MOVW.W	R0, -4(R13)
+	MOVW	$8, R0
+	MOVW.W	R0, -4(R13)
+	MOVW	$0, R0
+	MOVW.W	R0, -4(R13)	// push $0 as guard
+	BL	runtime·newproc(SB)
+	MOVW	$12(R13), R13	// pop args and LR
+
+	// start this M
+	BL	runtime·mstart(SB)
+
+	MOVW	$1234, R0
+	MOVW	$1000, R1
+	MOVW	R0, (R1)	// fail hard
+	B	runtime·_dep_dummy(SB)	// Never reached
+
+// TODO(kaib): remove these once i actually understand how the linker removes symbols
+// pull in dummy dependencies
+TEXT runtime·_dep_dummy(SB),7,$0
+	BL	_div(SB)
+	BL	_divu(SB)
+	BL	_mod(SB)
+	BL	_modu(SB)
+	BL	_modu(SB)
+	BL	_sfloat(SB)
+
+TEXT runtime·breakpoint(SB),7,$0
+	// no breakpoint yet; let program exit
+	RET
+
+/*
+ *  go-routine
+ */
+
+// void gosave(Gobuf*)
+// save state in Gobuf; setjmp
+TEXT runtime·gosave(SB), 7, $-4
+	MOVW	0(FP), R0		// gobuf
+	MOVW	SP, gobuf_sp(R0)
+	MOVW	LR, gobuf_pc(R0)
+	MOVW	g, gobuf_g(R0)
+	RET
+
+// void gogo(Gobuf*, uintptr)
+// restore state from Gobuf; longjmp
+TEXT runtime·gogo(SB), 7, $-4
+	MOVW	0(FP), R1		// gobuf
+	MOVW	4(FP), R0		// return 2nd arg
+	MOVW	gobuf_g(R1), g
+	MOVW	0(g), R2		// make sure g != nil
+	MOVW	gobuf_sp(R1), SP	// restore SP
+	MOVW	gobuf_pc(R1), PC
+
+// void gogocall(Gobuf*, void (*fn)(void))
+// restore state from Gobuf but then call fn.
+// (call fn, returning to state in Gobuf)
+// using frame size $-4 means do not save LR on stack.
+TEXT runtime·gogocall(SB), 7, $-4
+	MOVW	0(FP), R0		// gobuf
+	MOVW	4(FP), R1		// fn
+	MOVW	8(FP), R2		// fp offset
+	MOVW	gobuf_g(R0), g
+	MOVW	0(g), R3		// make sure g != nil
+	MOVW	gobuf_sp(R0), SP	// restore SP
+	MOVW	gobuf_pc(R0), LR
+	MOVW	R1, PC
+
+// void mcall(void (*fn)(G*))
+// Switch to m->g0's stack, call fn(g).
+// Fn must never return.  It should gogo(&g->sched)
+// to keep running g.
+TEXT runtime·mcall(SB), 7, $-4
+	MOVW	fn+0(FP), R0
+
+	// Save caller state in g->gobuf.
+	MOVW	SP, (g_sched+gobuf_sp)(g)
+	MOVW	LR, (g_sched+gobuf_pc)(g)
+	MOVW	g, (g_sched+gobuf_g)(g)
+
+	// Switch to m->g0 & its stack, call fn.
+	MOVW	g, R1
+	MOVW	m_g0(m), g
+	CMP	g, R1
+	BL.EQ	runtime·badmcall(SB)
+	MOVW	(g_sched+gobuf_sp)(g), SP
+	SUB	$8, SP
+	MOVW	R1, 4(SP)
+	BL	(R0)
+	BL	runtime·badmcall2(SB)
+	RET
+
+/*
+ * support for morestack
+ */
+
+// Called during function prolog when more stack is needed.
+// R1 frame size
+// R2 arg size
+// R3 prolog's LR
+// NB. we do not save R0 because we've forced 5c to pass all arguments
+// on the stack.
+// using frame size $-4 means do not save LR on stack.
+TEXT runtime·morestack(SB),7,$-4
+	// Cannot grow scheduler stack (m->g0).
+	MOVW	m_g0(m), R4
+	CMP	g, R4
+	BL.EQ	runtime·abort(SB)
+
+	// Save in m.
+	MOVW	R1, m_moreframesize(m)
+	MOVW	R2, m_moreargsize(m)
+
+	// Called from f.
+	// Set m->morebuf to f's caller.
+	MOVW	R3, (m_morebuf+gobuf_pc)(m)	// f's caller's PC
+	MOVW	SP, (m_morebuf+gobuf_sp)(m)	// f's caller's SP
+	MOVW	$4(SP), R3			// f's argument pointer
+	MOVW	R3, m_moreargp(m)	
+	MOVW	g, (m_morebuf+gobuf_g)(m)
+
+	// Set m->morepc to f's PC.
+	MOVW	LR, m_morepc(m)
+
+	// Call newstack on m->g0's stack.
+	MOVW	m_g0(m), g
+	MOVW	(g_sched+gobuf_sp)(g), SP
+	B	runtime·newstack(SB)
+
+// Called from reflection library.  Mimics morestack,
+// reuses stack growth code to create a frame
+// with the desired args running the desired function.
+//
+// func call(fn *byte, arg *byte, argsize uint32).
+TEXT reflect·call(SB), 7, $-4
+	// Save our caller's state as the PC and SP to
+	// restore when returning from f.
+	MOVW	LR, (m_morebuf+gobuf_pc)(m)	// our caller's PC
+	MOVW	SP, (m_morebuf+gobuf_sp)(m)	// our caller's SP
+	MOVW	g,  (m_morebuf+gobuf_g)(m)
+
+	// Set up morestack arguments to call f on a new stack.
+	// We set f's frame size to 1, as a hint to newstack
+	// that this is a call from reflect·call.
+	// If it turns out that f needs a larger frame than
+	// the default stack, f's usual stack growth prolog will
+	// allocate a new segment (and recopy the arguments).
+	MOVW	4(SP), R0			// fn
+	MOVW	8(SP), R1			// arg frame
+	MOVW	12(SP), R2			// arg size
+
+	MOVW	R0, m_morepc(m)			// f's PC
+	MOVW	R1, m_moreargp(m)		// f's argument pointer
+	MOVW	R2, m_moreargsize(m)		// f's argument size
+	MOVW	$1, R3
+	MOVW	R3, m_moreframesize(m)		// f's frame size
+
+	// Call newstack on m->g0's stack.
+	MOVW	m_g0(m), g
+	MOVW	(g_sched+gobuf_sp)(g), SP
+	B	runtime·newstack(SB)
+
+// Return point when leaving stack.
+// using frame size $-4 means do not save LR on stack.
+TEXT runtime·lessstack(SB), 7, $-4
+	// Save return value in m->cret
+	MOVW	R0, m_cret(m)
+
+	// Call oldstack on m->g0's stack.
+	MOVW	m_g0(m), g
+	MOVW	(g_sched+gobuf_sp)(g), SP
+	B	runtime·oldstack(SB)
+
+// void jmpdefer(fn, sp);
+// called from deferreturn.
+// 1. grab stored LR for caller
+// 2. sub 4 bytes to get back to BL deferreturn
+// 3. B to fn
+TEXT runtime·jmpdefer(SB), 7, $0
+	MOVW	0(SP), LR
+	MOVW	$-4(LR), LR	// BL deferreturn
+	MOVW	fn+0(FP), R0
+	MOVW	argp+4(FP), SP
+	MOVW	$-4(SP), SP	// SP is 4 below argp, due to saved LR
+	B		(R0)
+
+TEXT	runtime·asmcgocall(SB),7,$0
+	B	runtime·cgounimpl(SB)
+
+TEXT	runtime·cgocallback(SB),7,$0
+	B	runtime·cgounimpl(SB)
+
+TEXT runtime·memclr(SB),7,$20
+	MOVW	0(FP), R0
+	MOVW	$0, R1		// c = 0
+	MOVW	R1, -16(SP)
+	MOVW	4(FP), R1	// n
+	MOVW	R1, -12(SP)
+	MOVW	m, -8(SP)	// Save m and g
+	MOVW	g, -4(SP)
+	BL	runtime·memset(SB)
+	MOVW	-8(SP), m	// Restore m and g, memset clobbers them
+	MOVW	-4(SP), g
+	RET
+
+TEXT runtime·getcallerpc(SB),7,$-4
+	MOVW	0(SP), R0
+	RET
+
+TEXT runtime·setcallerpc(SB),7,$-4
+	MOVW	x+4(FP), R0
+	MOVW	R0, 0(SP)
+	RET
+
+TEXT runtime·getcallersp(SB),7,$-4
+	MOVW	0(FP), R0
+	MOVW	$-4(R0), R0
+	RET
+
+TEXT runtime·emptyfunc(SB),0,$0
+	RET
+
+TEXT runtime·abort(SB),7,$-4
+	MOVW	$0, R0
+	MOVW	(R0), R1
+
+// bool armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	}else
+//		return 0;
+//
+// To implement runtime·cas in sys_$GOOS_arm.s
+// using the native instructions, use:
+//
+//	TEXT runtime·cas(SB),7,$0
+//		B	runtime·armcas(SB)
+//
+TEXT runtime·armcas(SB),7,$0
+	MOVW	valptr+0(FP), R1
+	MOVW	old+4(FP), R2
+	MOVW	new+8(FP), R3
+casl:
+	LDREX	(R1), R0
+	CMP		R0, R2
+	BNE		casfail
+	STREX	R3, (R1), R0
+	CMP		$0, R0
+	BNE		casl
+	MOVW	$1, R0
+	RET
+casfail:
+	MOVW	$0, R0
+	RET
diff --git a/src/pkg/runtime/386/atomic.c b/src/pkg/runtime/atomic_386.c
similarity index 100%
rename from src/pkg/runtime/386/atomic.c
rename to src/pkg/runtime/atomic_386.c
diff --git a/src/pkg/runtime/amd64/atomic.c b/src/pkg/runtime/atomic_amd64.c
similarity index 100%
rename from src/pkg/runtime/amd64/atomic.c
rename to src/pkg/runtime/atomic_amd64.c
diff --git a/src/pkg/runtime/arm/atomic.c b/src/pkg/runtime/atomic_arm.c
similarity index 100%
rename from src/pkg/runtime/arm/atomic.c
rename to src/pkg/runtime/atomic_arm.c
diff --git a/src/pkg/runtime/autogen.sh b/src/pkg/runtime/autogen.sh
new file mode 100755
index 0000000..ca443ba
--- /dev/null
+++ b/src/pkg/runtime/autogen.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+# Copyright 2011 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 script generates the various derived files involved in
+# building package runtime. 
+#
+#	autogen.sh rebuilds everything
+#	autogen.sh -clean deletes the generated files
+
+. ../../buildinfo.sh
+
+HELPERS="goc2c mkversion"
+
+rm -f $HELPERS z*
+
+if [ "$1" = "-clean" ]; then
+	exit 0
+fi
+
+set -e
+
+if [ "$GOROOT" = "" ]; then
+	echo "$0"': $GOROOT must be set' >&2
+	exit 2
+fi
+
+# Use goc2c to translate .goc files into arch-specific .c files.
+quietgcc -o goc2c -I "$GOROOT/include" goc2c.c "$GOROOT/lib/lib9.a"
+for file in *.goc
+do
+	for arch in $GOARCHES
+	do
+		base=$(echo $file | sed 's/\.goc$//')
+		GOARCH=$arch ./goc2c $file >z.tmp
+		mv -f z.tmp z${base}_$arch.c
+	done
+done
+
+# Version constants.
+quietgcc -o mkversion -I "$GOROOT/include" mkversion.c "$GOROOT/lib/lib9.a"
+GOROOT="$GOROOT_FINAL" ./mkversion >z.tmp
+mv z.tmp zversion.go
+
+for arch in $GOARCHES
+do
+	(
+		echo '// AUTO-GENERATED by autogen.sh; DO NOT EDIT'
+		echo
+		echo 'package runtime'
+		echo
+		echo 'const theGoarch = "'$arch'"'
+	) >zgoarch_$arch.go
+done
+
+for os in $GOOSES
+do
+	(
+		echo '// AUTO-GENERATED by autogen.sh; DO NOT EDIT'
+		echo
+		echo 'package runtime'
+		echo
+		echo 'const theGoos = "'$os'"'
+	) >zgoos_$os.go
+done
+
+# Definitions of runtime structs, translated from C to Go.
+for osarch in $GOOSARCHES
+do
+	./mkgodefs.sh $osarch proc.c iface.c hashmap.c chan.c >z.tmp
+	mv -f z.tmp zruntime_defs_$osarch.go
+done
+
+# Struct field offsets, for use by assembly files.
+for osarch in $GOOSARCHES
+do
+	./mkasmh.sh $osarch proc.c defs.h >z.tmp
+	mv -f z.tmp zasm_$osarch.h
+done
+
+rm -f $HELPERS
diff --git a/src/pkg/runtime/callback_windows_386.c b/src/pkg/runtime/callback_windows_386.c
new file mode 100644
index 0000000..fcd292f
--- /dev/null
+++ b/src/pkg/runtime/callback_windows_386.c
@@ -0,0 +1,107 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "type.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+// Will keep all callbacks in a linked list, so they don't get garbage collected.
+typedef	struct	Callback	Callback;
+struct	Callback {
+	Callback*	link;
+	void*		gobody;
+	byte		asmbody;
+};
+
+typedef	struct	Callbacks	Callbacks;
+struct	Callbacks {
+	Lock;
+	Callback*	link;
+	int32		n;
+};
+
+static	Callbacks	cbs;
+
+// Call back from windows dll into go.
+byte *
+runtime·compilecallback(Eface fn, bool cleanstack)
+{
+	FuncType *ft;
+	Type *t;
+	int32 argsize, i, n;
+	byte *p;
+	Callback *c;
+
+	if(fn.type == nil || fn.type->kind != KindFunc)
+		runtime·panicstring("compilecallback: not a function");
+	ft = (FuncType*)fn.type;
+	if(ft->out.len != 1)
+		runtime·panicstring("compilecallback: function must have one output parameter");
+	if(((Type**)ft->out.array)[0]->size != sizeof(uintptr))
+		runtime·panicstring("compilecallback: output parameter size is wrong");
+	argsize = 0;
+	for(i=0; i<ft->in.len; i++) {
+		t = ((Type**)ft->in.array)[i];
+		if(t->size > sizeof(uintptr))
+			runtime·panicstring("compilecallback: input parameter size is wrong");
+		argsize += sizeof(uintptr);
+	}
+
+	// compute size of new fn.
+	// must match code laid out below.
+	n = 1+4;		// MOVL fn, AX
+	n += 1+4;		// MOVL argsize, DX
+	n += 1+4;		// MOVL callbackasm, CX
+	n += 2;			// CALL CX
+	n += 1;			// RET
+	if(cleanstack && argsize!=0)
+		n += 2;		// ... argsize
+
+	runtime·lock(&cbs);
+	for(c = cbs.link; c != nil; c = c->link) {
+		if(c->gobody == fn.data) {
+			runtime·unlock(&cbs);
+			return &c->asmbody;
+		}
+	}
+	if(cbs.n >= 2000)
+		runtime·throw("too many callback functions");
+	c = runtime·mal(sizeof *c + n);
+	c->gobody = fn.data;
+	c->link = cbs.link;
+	cbs.link = c;
+	cbs.n++;
+	runtime·unlock(&cbs);
+
+	p = &c->asmbody;
+
+	// MOVL fn, AX
+	*p++ = 0xb8;
+	*(uint32*)p = (uint32)fn.data;
+	p += 4;
+
+	// MOVL argsize, DX
+	*p++ = 0xba;
+	*(uint32*)p = argsize;
+	p += 4;
+
+	// MOVL callbackasm, CX
+	*p++ = 0xb9;
+	*(uint32*)p = (uint32)runtime·callbackasm;
+	p += 4;
+
+	// CALL CX
+	*p++ = 0xff;
+	*p++ = 0xd1;
+
+	// RET argsize?
+	if(cleanstack && argsize!=0) {
+		*p++ = 0xc2;
+		*(uint16*)p = argsize;
+	} else
+		*p = 0xc3;
+
+	return &c->asmbody;
+}
diff --git a/src/pkg/runtime/callback_windows_amd64.c b/src/pkg/runtime/callback_windows_amd64.c
new file mode 100644
index 0000000..99d7cb9
--- /dev/null
+++ b/src/pkg/runtime/callback_windows_amd64.c
@@ -0,0 +1,104 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "type.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+// Will keep all callbacks in a linked list, so they don't get garbage collected.
+typedef	struct	Callback	Callback;
+struct	Callback {
+	Callback*	link;
+	void*		gobody;
+	byte		asmbody;
+};
+
+typedef	struct	Callbacks	Callbacks;
+struct	Callbacks {
+	Lock;
+	Callback*	link;
+	int32		n;
+};
+
+static	Callbacks	cbs;
+
+// Call back from windows dll into go.
+byte *
+runtime·compilecallback(Eface fn, bool /*cleanstack*/)
+{
+	FuncType *ft;
+	Type *t;
+	int32 argsize, i, n;
+	byte *p;
+	Callback *c;
+
+	if(fn.type == nil || fn.type->kind != KindFunc)
+		runtime·panicstring("compilecallback: not a function");
+	ft = (FuncType*)fn.type;
+	if(ft->out.len != 1)
+		runtime·panicstring("compilecallback: function must have one output parameter");
+	if(((Type**)ft->out.array)[0]->size != sizeof(uintptr))
+		runtime·panicstring("compilecallback: output parameter size is wrong");
+	argsize = 0;
+	for(i=0; i<ft->in.len; i++) {
+		t = ((Type**)ft->in.array)[i];
+		if(t->size > sizeof(uintptr))
+			runtime·panicstring("compilecallback: input parameter size is wrong");
+		argsize += sizeof(uintptr);
+	}
+
+	// compute size of new fn.
+	// must match code laid out below.
+	n  = 2+8+1; // MOVQ fn, AX           / PUSHQ AX
+	n += 2+8+1; // MOVQ argsize, AX      / PUSHQ AX
+	n += 2+8;   // MOVQ callbackasm, AX
+	n += 2;     // JMP  AX
+
+	runtime·lock(&cbs);
+	for(c = cbs.link; c != nil; c = c->link) {
+		if(c->gobody == fn.data) {
+			runtime·unlock(&cbs);
+			return &c->asmbody;
+		}
+	}
+	if(cbs.n >= 2000)
+		runtime·throw("too many callback functions");
+	c = runtime·mal(sizeof *c + n);
+	c->gobody = fn.data;
+	c->link = cbs.link;
+	cbs.link = c;
+	cbs.n++;
+	runtime·unlock(&cbs);
+
+	p = &c->asmbody;
+
+	// MOVQ fn, AX
+	*p++ = 0x48;
+	*p++ = 0xb8;
+	*(uint64*)p = (uint64)fn.data;
+	p += 8;
+	// PUSH AX
+	*p++ = 0x50;
+
+	// MOVQ argsize, AX
+	*p++ = 0x48;
+	*p++ = 0xb8;
+	*(uint64*)p = argsize;
+	p += 8;
+	// PUSH AX
+	*p++ = 0x50;
+
+	// MOVQ callbackasm, AX
+	*p++ = 0x48;
+	*p++ = 0xb8;
+	*(uint64*)p = (uint64)runtime·callbackasm;
+	p += 8;
+
+	// JMP AX
+	*p++ = 0xFF;
+	*p = 0xE0;
+
+	return &c->asmbody;
+}
diff --git a/src/pkg/runtime/cgo/Makefile b/src/pkg/runtime/cgo/Makefile
index 7667947..05c7eba 100644
--- a/src/pkg/runtime/cgo/Makefile
+++ b/src/pkg/runtime/cgo/Makefile
@@ -14,15 +14,15 @@ ifeq ($(CGO_ENABLED),1)
 # Unwarranted chumminess with Make.pkg's cgo rules.
 # Do not try this at home.
 CGO_OFILES=\
-	$(GOARCH).o\
-	$(GOOS)_$(GOARCH).o\
-	util.o\
+	gcc_$(GOARCH).o\
+	gcc_$(GOOS)_$(GOARCH).o\
+	gcc_util.o\
 
 ifeq ($(GOOS),windows)
 CGO_LDFLAGS=-lm -mthreads
 else
 CGO_LDFLAGS=-lpthread
-CGO_OFILES+=setenv.o\
+CGO_OFILES+=gcc_setenv.o\
 
 endif
 
@@ -50,11 +50,11 @@ _cgo_main.c:
 	echo 'int main() { return 0; }' >$@
 endif
 
-$(GOARCH).o: $(GOARCH).S
+gcc_$(GOARCH).o: gcc_$(GOARCH).S
 	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -O2 -fPIC -o $@ -c $^
 
-$(GOOS)_$(GOARCH).o: $(GOOS)_$(GOARCH).c
+gcc_$(GOOS)_$(GOARCH).o: gcc_$(GOOS)_$(GOARCH).c
 	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -O2 -fPIC -o $@ -c $^
 
-%.o: %.c
+gcc_%.o: gcc_%.c
 	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -g -O2 -fPIC -o $@ -c $^
diff --git a/src/pkg/runtime/cgo/amd64.S b/src/pkg/runtime/cgo/amd64.S
deleted file mode 100644
index 6c1a4c8..0000000
--- a/src/pkg/runtime/cgo/amd64.S
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Apple still insists on underscore prefixes for C function names.
- */
-#if defined(__APPLE__) || defined(_WIN32)
-#define EXT(s) _##s
-#else
-#define EXT(s) s
-#endif
-
-/*
- * void crosscall_amd64(void (*fn)(void))
- *
- * Calling into the 6c tool chain, where all registers are caller save.
- * Called from standard x86-64 ABI, where %rbx, %rbp, %r12-%r15
- * are callee-save so they must be saved explicitly.
- * The standard x86-64 ABI passes the three arguments m, g, fn
- * in %rdi, %rsi, %rdx.
- *
- * Also need to set %r15 to g and %r14 to m (see ../pkg/runtime/mkasmh.sh)
- * during the call.
- */
-.globl EXT(crosscall_amd64)
-EXT(crosscall_amd64):
-	pushq %rbx
-	pushq %rbp
-	pushq %r12
-	pushq %r13
-	pushq %r14
-	pushq %r15
-
-#if defined(_WIN64)
-	call *%rcx	/* fn */
-#else
-	call *%rdi	/* fn */
-#endif
-
-	popq %r15
-	popq %r14
-	popq %r13
-	popq %r12
-	popq %rbp
-	popq %rbx
-	ret
-
-/*
- * void crosscall2(void (*fn)(void*, int32), void *arg, int32 argsize)
- *
- * Save registers and call fn with two arguments.  fn is a Go function
- * which takes parameters on the stack rather than in registers.
- */
-.globl EXT(crosscall2)
-EXT(crosscall2):
-	subq  $0x58, %rsp	/* keeps stack pointer 32-byte aligned */
-	movq  %rbx, 0x10(%rsp)
-	movq  %rbp, 0x18(%rsp)
-	movq  %r12, 0x20(%rsp)
-	movq  %r13, 0x28(%rsp)
-	movq  %r14, 0x30(%rsp)
-	movq  %r15, 0x38(%rsp)
-
-#if defined(_WIN64)
-	// Win64 save RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15
-	movq	%rdi, 0x40(%rsp)
-	movq	%rsi, 0x48(%rsp)
-
-	movq  %rdx, 0(%rsp)	/* arg */
-	movq  %r8, 8(%rsp)	/* argsize (includes padding) */
-	
-	call %rcx	/* fn */
-#else
-	movq  %rsi, 0(%rsp)	/* arg */
-	movq  %rdx, 8(%rsp)	/* argsize (includes padding) */
-
-	call *%rdi	/* fn */
-#endif
-
-	movq  0x10(%rsp), %rbx
-	movq  0x18(%rsp), %rbp
-	movq  0x20(%rsp), %r12
-	movq  0x28(%rsp), %r13
-	movq  0x30(%rsp), %r14
-	movq  0x38(%rsp), %r15
-#if defined(__WIN64)
-	movq	0x40(%rsp), %rdi
-	movq	0x48(%rsp), %rsi
-#endif	
-	addq  $0x58, %rsp
-	ret
diff --git a/src/pkg/runtime/cgo/darwin_386.c b/src/pkg/runtime/cgo/darwin_386.c
deleted file mode 100644
index 6d4e259..0000000
--- a/src/pkg/runtime/cgo/darwin_386.c
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <pthread.h>
-#include "libcgo.h"
-
-static void* threadentry(void*);
-static pthread_key_t k1, k2;
-
-#define magic1 (0x23581321U)
-
-static void
-inittls(void)
-{
-	uint32 x, y;
-	pthread_key_t tofree[128], k;
-	int i, ntofree;
-	int havek1, havek2;
-
-	/*
-	 * Allocate thread-local storage slots for m, g.
-	 * The key numbers start at 0x100, and we expect to be
-	 * one of the early calls to pthread_key_create, so we
-	 * should be able to get pretty low numbers.
-	 *
-	 * In Darwin/386 pthreads, %gs points at the thread
-	 * structure, and each key is an index into the thread-local
-	 * storage array that begins at offset 0x48 within in that structure.
-	 * It may happen that we are not quite the first function to try
-	 * to allocate thread-local storage keys, so instead of depending
-	 * on getting 0x100 and 0x101, we try for 0x108 and 0x109,
-	 * allocating keys until we get the ones we want and then freeing
-	 * the ones we didn't want.
-	 *
-	 * Thus the final offsets to use in %gs references are
-	 * 0x48+4*0x108 = 0x468 and 0x48+4*0x109 = 0x46c.
-	 *
-	 * The linker and runtime hard-code these constant offsets
-	 * from %gs where we expect to find m and g.
-	 * Known to ../cmd/8l/obj.c:/468
-	 * and to ../pkg/runtime/darwin/386/sys.s:/468
-	 *
-	 * This is truly disgusting and a bit fragile, but taking care
-	 * of it here protects the rest of the system from damage.
-	 * The alternative would be to use a global variable that
-	 * held the offset and refer to that variable each time we
-	 * need a %gs variable (m or g).  That approach would
-	 * require an extra instruction and memory reference in
-	 * every stack growth prolog and would also require
-	 * rewriting the code that 8c generates for extern registers.
-	 *
-	 * Things get more disgusting on OS X 10.7 Lion.
-	 * The 0x48 base mentioned above is the offset of the tsd
-	 * array within the per-thread structure on Leopard and Snow Leopard.
-	 * On Lion, the base moved a little, so while the math above
-	 * still applies, the base is different.  Thus, we cannot
-	 * look for specific key values if we want to build binaries
-	 * that run on both systems.  Instead, forget about the
-	 * specific key values and just allocate and initialize per-thread
-	 * storage until we find a key that writes to the memory location
-	 * we want.  Then keep that key.
-	 */
-	havek1 = 0;
-	havek2 = 0;
-	ntofree = 0;
-	while(!havek1 || !havek2) {
-		if(pthread_key_create(&k, nil) < 0) {
-			fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
-			abort();
-		}
-		pthread_setspecific(k, (void*)magic1);
-		asm volatile("movl %%gs:0x468, %0" : "=r"(x));
-		asm volatile("movl %%gs:0x46c, %0" : "=r"(y));
-		if(x == magic1) {
-			havek1 = 1;
-			k1 = k;
-		} else if(y == magic1) {
-			havek2 = 1;
-			k2 = k;
-		} else {
-			if(ntofree >= nelem(tofree)) {
-				fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
-				fprintf(stderr, "\ttried");
-				for(i=0; i<ntofree; i++)
-					fprintf(stderr, " %#x", (unsigned)tofree[i]);
-				fprintf(stderr, "\n");
-				abort();
-			}
-			tofree[ntofree++] = k;
-		}
-		pthread_setspecific(k, 0);
-	}
-
-	/*
-	 * We got the keys we wanted.  Free the others.
-	 */
-	for(i=0; i<ntofree; i++)
-		pthread_key_delete(tofree[i]);
-}
-
-static void
-xinitcgo(void)
-{
-	inittls();
-}
-
-void (*initcgo)(void) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	pthread_attr_t attr;
-	pthread_t p;
-	size_t size;
-	int err;
-
-	pthread_attr_init(&attr);
-	pthread_attr_getstacksize(&attr, &size);
-	ts->g->stackguard = size;
-	err = pthread_create(&p, &attr, threadentry, ts);
-	if (err != 0) {
-		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
-		abort();
-	}
-}
-
-static void*
-threadentry(void *v)
-{
-	ThreadStart ts;
-
-	ts = *(ThreadStart*)v;
-	free(v);
-
-	ts.g->stackbase = (uintptr)&ts;
-
-	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
-	 * change to actual guard pointer.
-	 */
-	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
-	pthread_setspecific(k1, (void*)ts.g);
-	pthread_setspecific(k2, (void*)ts.m);
-
-	crosscall_386(ts.fn);
-	return nil;
-}
diff --git a/src/pkg/runtime/cgo/darwin_amd64.c b/src/pkg/runtime/cgo/darwin_amd64.c
deleted file mode 100644
index 3471044..0000000
--- a/src/pkg/runtime/cgo/darwin_amd64.c
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <pthread.h>
-#include "libcgo.h"
-
-static void* threadentry(void*);
-static pthread_key_t k1, k2;
-
-#define magic1 (0x23581321345589ULL)
-
-static void
-inittls(void)
-{
-	uint64 x, y;
-	pthread_key_t tofree[128], k;
-	int i, ntofree;
-	int havek1, havek2;
-
-	/*
-	 * Same logic, code as darwin_386.c:/inittls, except that words
-	 * are 8 bytes long now, and the thread-local storage starts
-	 * at 0x60 on Leopard / Snow Leopard. So the offsets are
-	 * 0x60+8*0x108 = 0x8a0 and 0x60+8*0x109 = 0x8a8.
-	 *
-	 * The linker and runtime hard-code these constant offsets
-	 * from %gs where we expect to find m and g.
-	 * Known to ../cmd/6l/obj.c:/8a0
-	 * and to ../pkg/runtime/darwin/amd64/sys.s:/8a0
-	 *
-	 * As disgusting as on the 386; same justification.
-	 */
-	havek1 = 0;
-	havek2 = 0;
-	ntofree = 0;
-	while(!havek1 || !havek2) {
-		if(pthread_key_create(&k, nil) < 0) {
-			fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
-			abort();
-		}
-		pthread_setspecific(k, (void*)magic1);
-		asm volatile("movq %%gs:0x8a0, %0" : "=r"(x));
-		asm volatile("movq %%gs:0x8a8, %0" : "=r"(y));
-		if(x == magic1) {
-			havek1 = 1;
-			k1 = k;
-		} else if(y == magic1) {
-			havek2 = 1;
-			k2 = k;
-		} else {
-			if(ntofree >= nelem(tofree)) {
-				fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
-				fprintf(stderr, "\ttried");
-				for(i=0; i<ntofree; i++)
-					fprintf(stderr, " %#x", (unsigned)tofree[i]);
-				fprintf(stderr, "\n");
-				abort();
-			}
-			tofree[ntofree++] = k;
-		}
-		pthread_setspecific(k, 0);
-	}
-
-	/*
-	 * We got the keys we wanted.  Free the others.
-	 */
-	for(i=0; i<ntofree; i++)
-		pthread_key_delete(tofree[i]);
-}
-
-void
-xinitcgo(void)
-{
-	inittls();
-}
-
-void (*initcgo) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	pthread_attr_t attr;
-	pthread_t p;
-	size_t size;
-	int err;
-
-	pthread_attr_init(&attr);
-	pthread_attr_getstacksize(&attr, &size);
-	ts->g->stackguard = size;
-	err = pthread_create(&p, &attr, threadentry, ts);
-	if (err != 0) {
-		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
-		abort();
-	}
-}
-
-static void*
-threadentry(void *v)
-{
-	ThreadStart ts;
-
-	ts = *(ThreadStart*)v;
-	free(v);
-
-	ts.g->stackbase = (uintptr)&ts;
-
-	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
-	 * change to actual guard pointer.
-	 */
-	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
-	pthread_setspecific(k1, (void*)ts.g);
-	pthread_setspecific(k2, (void*)ts.m);
-
-	crosscall_amd64(ts.fn);
-	return nil;
-}
diff --git a/src/pkg/runtime/cgo/freebsd_386.c b/src/pkg/runtime/cgo/freebsd_386.c
deleted file mode 100644
index ae53201..0000000
--- a/src/pkg/runtime/cgo/freebsd_386.c
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <pthread.h>
-#include "libcgo.h"
-
-static void* threadentry(void*);
-
-static void
-xinitcgo(void)
-{
-}
-
-void (*initcgo)(void) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	pthread_attr_t attr;
-	pthread_t p;
-	size_t size;
-	int err;
-
-	pthread_attr_init(&attr);
-	pthread_attr_getstacksize(&attr, &size);
-	ts->g->stackguard = size;
-	err = pthread_create(&p, &attr, threadentry, ts);
-	if (err != 0) {
-		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
-		abort();
-	}
-}
-
-static void*
-threadentry(void *v)
-{
-	ThreadStart ts;
-
-	ts = *(ThreadStart*)v;
-	free(v);
-
-	ts.g->stackbase = (uintptr)&ts;
-
-	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
-	 * change to actual guard pointer.
-	 */
-	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
-	/*
-	 * Set specific keys.  On FreeBSD/ELF, the thread local storage
-	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
-	 * for the two words g and m at %gs:-8 and %gs:-4.
-	 */
-	asm volatile (
-		"movl %0, %%gs:-8\n"	// MOVL g, -8(GS)
-		"movl %1, %%gs:-4\n"	// MOVL m, -4(GS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
-
-	crosscall_386(ts.fn);
-	return nil;
-}
diff --git a/src/pkg/runtime/cgo/freebsd_amd64.c b/src/pkg/runtime/cgo/freebsd_amd64.c
deleted file mode 100644
index 5afc1df..0000000
--- a/src/pkg/runtime/cgo/freebsd_amd64.c
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <pthread.h>
-#include "libcgo.h"
-
-static void* threadentry(void*);
-
-static void
-xinitcgo(void)
-{
-}
-
-void (*initcgo)(void) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	pthread_attr_t attr;
-	pthread_t p;
-	size_t size;
-	int err;
-
-	pthread_attr_init(&attr);
-	pthread_attr_getstacksize(&attr, &size);
-	ts->g->stackguard = size;
-	err = pthread_create(&p, &attr, threadentry, ts);
-	if (err != 0) {
-		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
-		abort();
-	}
-}
-
-static void*
-threadentry(void *v)
-{
-	ThreadStart ts;
-
-	ts = *(ThreadStart*)v;
-	free(v);
-
-	ts.g->stackbase = (uintptr)&ts;
-
-	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
-	 * change to actual guard pointer.
-	 */
-	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
-	/*
-	 * Set specific keys.  On FreeBSD/ELF, the thread local storage
-	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
-	 * for the two words g and m at %fs:-16 and %fs:-8.
-	 */
-	asm volatile (
-		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
-		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
-	crosscall_amd64(ts.fn);
-	return nil;
-}
diff --git a/src/pkg/runtime/cgo/386.S b/src/pkg/runtime/cgo/gcc_386.S
old mode 100755
new mode 100644
similarity index 100%
rename from src/pkg/runtime/cgo/386.S
rename to src/pkg/runtime/cgo/gcc_386.S
diff --git a/src/pkg/runtime/cgo/gcc_amd64.S b/src/pkg/runtime/cgo/gcc_amd64.S
new file mode 100644
index 0000000..8e6d506
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_amd64.S
@@ -0,0 +1,92 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ * Apple still insists on underscore prefixes for C function names.
+ */
+#if defined(__APPLE__)
+#define EXT(s) _##s
+#else
+#define EXT(s) s
+#endif
+
+/*
+ * void crosscall_amd64(void (*fn)(void))
+ *
+ * Calling into the 6c tool chain, where all registers are caller save.
+ * Called from standard x86-64 ABI, where %rbx, %rbp, %r12-%r15
+ * are callee-save so they must be saved explicitly.
+ * The standard x86-64 ABI passes the three arguments m, g, fn
+ * in %rdi, %rsi, %rdx.
+ *
+ * Also need to set %r15 to g and %r14 to m (see ../pkg/runtime/mkasmh.sh)
+ * during the call.
+ */
+.globl EXT(crosscall_amd64)
+EXT(crosscall_amd64):
+	pushq %rbx
+	pushq %rbp
+	pushq %r12
+	pushq %r13
+	pushq %r14
+	pushq %r15
+
+#if defined(_WIN64)
+	call *%rcx	/* fn */
+#else
+	call *%rdi	/* fn */
+#endif
+
+	popq %r15
+	popq %r14
+	popq %r13
+	popq %r12
+	popq %rbp
+	popq %rbx
+	ret
+
+/*
+ * void crosscall2(void (*fn)(void*, int32), void *arg, int32 argsize)
+ *
+ * Save registers and call fn with two arguments.  fn is a Go function
+ * which takes parameters on the stack rather than in registers.
+ */
+.globl EXT(crosscall2)
+EXT(crosscall2):
+	subq  $0x58, %rsp	/* keeps stack pointer 32-byte aligned */
+	movq  %rbx, 0x10(%rsp)
+	movq  %rbp, 0x18(%rsp)
+	movq  %r12, 0x20(%rsp)
+	movq  %r13, 0x28(%rsp)
+	movq  %r14, 0x30(%rsp)
+	movq  %r15, 0x38(%rsp)
+
+#if defined(_WIN64)
+	// Win64 save RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15
+	movq	%rdi, 0x40(%rsp)
+	movq	%rsi, 0x48(%rsp)
+
+	movq  %rdx, 0(%rsp)	/* arg */
+	movq  %r8, 8(%rsp)	/* argsize (includes padding) */
+	
+	call %rcx	/* fn */
+#else
+	movq  %rsi, 0(%rsp)	/* arg */
+	movq  %rdx, 8(%rsp)	/* argsize (includes padding) */
+
+	call *%rdi	/* fn */
+#endif
+
+	movq  0x10(%rsp), %rbx
+	movq  0x18(%rsp), %rbp
+	movq  0x20(%rsp), %r12
+	movq  0x28(%rsp), %r13
+	movq  0x30(%rsp), %r14
+	movq  0x38(%rsp), %r15
+#if defined(__WIN64)
+	movq	0x40(%rsp), %rdi
+	movq	0x48(%rsp), %rsi
+#endif	
+	addq  $0x58, %rsp
+	ret
diff --git a/src/pkg/runtime/cgo/arm.S b/src/pkg/runtime/cgo/gcc_arm.S
similarity index 100%
rename from src/pkg/runtime/cgo/arm.S
rename to src/pkg/runtime/cgo/gcc_arm.S
diff --git a/src/pkg/runtime/cgo/gcc_darwin_386.c b/src/pkg/runtime/cgo/gcc_darwin_386.c
new file mode 100644
index 0000000..d9f2534
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_darwin_386.c
@@ -0,0 +1,158 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <string.h> /* for strerror */
+#include <pthread.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+static pthread_key_t k1, k2;
+
+#define magic1 (0x23581321U)
+
+static void
+inittls(void)
+{
+	uint32 x, y;
+	pthread_key_t tofree[128], k;
+	int i, ntofree;
+	int havek1, havek2;
+
+	/*
+	 * Allocate thread-local storage slots for m, g.
+	 * The key numbers start at 0x100, and we expect to be
+	 * one of the early calls to pthread_key_create, so we
+	 * should be able to get pretty low numbers.
+	 *
+	 * In Darwin/386 pthreads, %gs points at the thread
+	 * structure, and each key is an index into the thread-local
+	 * storage array that begins at offset 0x48 within in that structure.
+	 * It may happen that we are not quite the first function to try
+	 * to allocate thread-local storage keys, so instead of depending
+	 * on getting 0x100 and 0x101, we try for 0x108 and 0x109,
+	 * allocating keys until we get the ones we want and then freeing
+	 * the ones we didn't want.
+	 *
+	 * Thus the final offsets to use in %gs references are
+	 * 0x48+4*0x108 = 0x468 and 0x48+4*0x109 = 0x46c.
+	 *
+	 * The linker and runtime hard-code these constant offsets
+	 * from %gs where we expect to find m and g.
+	 * Known to ../../../cmd/8l/obj.c:/468
+	 * and to ../sys_darwin_386.s:/468
+	 *
+	 * This is truly disgusting and a bit fragile, but taking care
+	 * of it here protects the rest of the system from damage.
+	 * The alternative would be to use a global variable that
+	 * held the offset and refer to that variable each time we
+	 * need a %gs variable (m or g).  That approach would
+	 * require an extra instruction and memory reference in
+	 * every stack growth prolog and would also require
+	 * rewriting the code that 8c generates for extern registers.
+	 *
+	 * Things get more disgusting on OS X 10.7 Lion.
+	 * The 0x48 base mentioned above is the offset of the tsd
+	 * array within the per-thread structure on Leopard and Snow Leopard.
+	 * On Lion, the base moved a little, so while the math above
+	 * still applies, the base is different.  Thus, we cannot
+	 * look for specific key values if we want to build binaries
+	 * that run on both systems.  Instead, forget about the
+	 * specific key values and just allocate and initialize per-thread
+	 * storage until we find a key that writes to the memory location
+	 * we want.  Then keep that key.
+	 */
+	havek1 = 0;
+	havek2 = 0;
+	ntofree = 0;
+	while(!havek1 || !havek2) {
+		if(pthread_key_create(&k, nil) < 0) {
+			fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
+			abort();
+		}
+		pthread_setspecific(k, (void*)magic1);
+		asm volatile("movl %%gs:0x468, %0" : "=r"(x));
+		asm volatile("movl %%gs:0x46c, %0" : "=r"(y));
+		if(x == magic1) {
+			havek1 = 1;
+			k1 = k;
+		} else if(y == magic1) {
+			havek2 = 1;
+			k2 = k;
+		} else {
+			if(ntofree >= nelem(tofree)) {
+				fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
+				fprintf(stderr, "\ttried");
+				for(i=0; i<ntofree; i++)
+					fprintf(stderr, " %#x", (unsigned)tofree[i]);
+				fprintf(stderr, "\n");
+				abort();
+			}
+			tofree[ntofree++] = k;
+		}
+		pthread_setspecific(k, 0);
+	}
+
+	/*
+	 * We got the keys we wanted.  Free the others.
+	 */
+	for(i=0; i<ntofree; i++)
+		pthread_key_delete(tofree[i]);
+}
+
+static void
+xinitcgo(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+
+	inittls();
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	ts.g->stackbase = (uintptr)&ts;
+
+	/*
+	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * change to actual guard pointer.
+	 */
+	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
+
+	pthread_setspecific(k1, (void*)ts.g);
+	pthread_setspecific(k2, (void*)ts.m);
+
+	crosscall_386(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_darwin_amd64.c b/src/pkg/runtime/cgo/gcc_darwin_amd64.c
new file mode 100644
index 0000000..a0b026e
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_darwin_amd64.c
@@ -0,0 +1,128 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <string.h> /* for strerror */
+#include <pthread.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+static pthread_key_t k1, k2;
+
+#define magic1 (0x23581321345589ULL)
+
+static void
+inittls(void)
+{
+	uint64 x, y;
+	pthread_key_t tofree[128], k;
+	int i, ntofree;
+	int havek1, havek2;
+
+	/*
+	 * Same logic, code as darwin_386.c:/inittls, except that words
+	 * are 8 bytes long now, and the thread-local storage starts
+	 * at 0x60 on Leopard / Snow Leopard. So the offsets are
+	 * 0x60+8*0x108 = 0x8a0 and 0x60+8*0x109 = 0x8a8.
+	 *
+	 * The linker and runtime hard-code these constant offsets
+	 * from %gs where we expect to find m and g.
+	 * Known to ../../../cmd/6l/obj.c:/8a0
+	 * and to ../sys_darwin_amd64.s:/8a0
+	 *
+	 * As disgusting as on the 386; same justification.
+	 */
+	havek1 = 0;
+	havek2 = 0;
+	ntofree = 0;
+	while(!havek1 || !havek2) {
+		if(pthread_key_create(&k, nil) < 0) {
+			fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
+			abort();
+		}
+		pthread_setspecific(k, (void*)magic1);
+		asm volatile("movq %%gs:0x8a0, %0" : "=r"(x));
+		asm volatile("movq %%gs:0x8a8, %0" : "=r"(y));
+		if(x == magic1) {
+			havek1 = 1;
+			k1 = k;
+		} else if(y == magic1) {
+			havek2 = 1;
+			k2 = k;
+		} else {
+			if(ntofree >= nelem(tofree)) {
+				fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
+				fprintf(stderr, "\ttried");
+				for(i=0; i<ntofree; i++)
+					fprintf(stderr, " %#x", (unsigned)tofree[i]);
+				fprintf(stderr, "\n");
+				abort();
+			}
+			tofree[ntofree++] = k;
+		}
+		pthread_setspecific(k, 0);
+	}
+
+	/*
+	 * We got the keys we wanted.  Free the others.
+	 */
+	for(i=0; i<ntofree; i++)
+		pthread_key_delete(tofree[i]);
+}
+
+void
+xinitcgo(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+
+	inittls();
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	ts.g->stackbase = (uintptr)&ts;
+
+	/*
+	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * change to actual guard pointer.
+	 */
+	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
+
+	pthread_setspecific(k1, (void*)ts.g);
+	pthread_setspecific(k2, (void*)ts.m);
+
+	crosscall_amd64(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_386.c b/src/pkg/runtime/cgo/gcc_freebsd_386.c
new file mode 100644
index 0000000..ad94687
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_freebsd_386.c
@@ -0,0 +1,71 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <pthread.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+
+static void
+xinitcgo(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	ts.g->stackbase = (uintptr)&ts;
+
+	/*
+	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * change to actual guard pointer.
+	 */
+	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
+
+	/*
+	 * Set specific keys.  On FreeBSD/ELF, the thread local storage
+	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
+	 * for the two words g and m at %gs:-8 and %gs:-4.
+	 */
+	asm volatile (
+		"movl %0, %%gs:-8\n"	// MOVL g, -8(GS)
+		"movl %1, %%gs:-4\n"	// MOVL m, -4(GS)
+		:: "r"(ts.g), "r"(ts.m)
+	);
+
+	crosscall_386(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c b/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
new file mode 100644
index 0000000..b18d1bc
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_freebsd_amd64.c
@@ -0,0 +1,70 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <pthread.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+
+static void
+xinitcgo(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	ts.g->stackbase = (uintptr)&ts;
+
+	/*
+	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * change to actual guard pointer.
+	 */
+	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
+
+	/*
+	 * Set specific keys.  On FreeBSD/ELF, the thread local storage
+	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
+	 * for the two words g and m at %fs:-16 and %fs:-8.
+	 */
+	asm volatile (
+		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
+		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
+		:: "r"(ts.g), "r"(ts.m)
+	);
+	crosscall_amd64(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_linux_386.c b/src/pkg/runtime/cgo/gcc_linux_386.c
new file mode 100644
index 0000000..8401a75
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_linux_386.c
@@ -0,0 +1,80 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <pthread.h>
+#include <string.h>
+#include "libcgo.h"
+
+static void *threadentry(void*);
+
+static void
+xinitcgo(G *g)
+{
+	pthread_attr_t attr;
+	size_t size;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	// Not sure why the memset is necessary here,
+	// but without it, we get a bogus stack size
+	// out of pthread_attr_getstacksize.  C'est la Linux.
+	memset(&attr, 0, sizeof attr);
+	pthread_attr_init(&attr);
+	size = 0;
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	ts.g->stackbase = (uintptr)&ts;
+
+	/*
+	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * change to actual guard pointer.
+	 */
+	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
+
+	/*
+	 * Set specific keys.  On Linux/ELF, the thread local storage
+	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
+	 * for the two words g and m at %gs:-8 and %gs:-4.
+	 * Xen requires us to access those words indirect from %gs:0
+	 * which points at itself.
+	 */
+	asm volatile (
+		"movl %%gs:0, %%eax\n"		// MOVL 0(GS), tmp
+		"movl %0, -8(%%eax)\n"	// MOVL g, -8(GS)
+		"movl %1, -4(%%eax)\n"	// MOVL m, -4(GS)
+		:: "r"(ts.g), "r"(ts.m) : "%eax"
+	);
+
+	crosscall_386(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_linux_amd64.c b/src/pkg/runtime/cgo/gcc_linux_amd64.c
new file mode 100644
index 0000000..6ce3333
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_linux_amd64.c
@@ -0,0 +1,71 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <pthread.h>
+#include <string.h> // strerror
+#include "libcgo.h"
+
+static void* threadentry(void*);
+
+void
+xinitcgo(G* g)
+{
+	pthread_attr_t attr;
+	size_t size;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	g->stackguard = (uintptr)&attr - size + 4096;
+	pthread_attr_destroy(&attr);
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	pthread_attr_t attr;
+	pthread_t p;
+	size_t size;
+	int err;
+
+	pthread_attr_init(&attr);
+	pthread_attr_getstacksize(&attr, &size);
+	ts->g->stackguard = size;
+	err = pthread_create(&p, &attr, threadentry, ts);
+	if (err != 0) {
+		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
+		abort();
+	}
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	ts.g->stackbase = (uintptr)&ts;
+
+	/*
+	 * libcgo_sys_thread_start set stackguard to stack size;
+	 * change to actual guard pointer.
+	 */
+	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
+
+	/*
+	 * Set specific keys.  On Linux/ELF, the thread local storage
+	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
+	 * for the two words g and m at %fs:-16 and %fs:-8.
+	 */
+	asm volatile (
+		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
+		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
+		:: "r"(ts.g), "r"(ts.m)
+	);
+	crosscall_amd64(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_linux_arm.c b/src/pkg/runtime/cgo/gcc_linux_arm.c
new file mode 100644
index 0000000..8397c75
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_linux_arm.c
@@ -0,0 +1,20 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "libcgo.h"
+
+static void
+xinitcgo(G *g)
+{
+	// unimplemented
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	// unimplemented
+	*(int*)0 = 0;
+}
diff --git a/src/pkg/runtime/cgo/gcc_setenv.c b/src/pkg/runtime/cgo/gcc_setenv.c
new file mode 100644
index 0000000..7da4ad9
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_setenv.c
@@ -0,0 +1,18 @@
+// Copyright 20111 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 darwin freebsd linux netbsd openbsd
+
+#include "libcgo.h"
+
+#include <stdlib.h>
+
+/* Stub for calling setenv */
+static void
+xlibcgo_setenv(char **arg)
+{
+	setenv(arg[0], arg[1], 1);
+}
+
+void (*libcgo_setenv)(char**) = xlibcgo_setenv;
diff --git a/src/pkg/runtime/cgo/util.c b/src/pkg/runtime/cgo/gcc_util.c
similarity index 100%
rename from src/pkg/runtime/cgo/util.c
rename to src/pkg/runtime/cgo/gcc_util.c
diff --git a/src/pkg/runtime/cgo/gcc_windows_386.c b/src/pkg/runtime/cgo/gcc_windows_386.c
new file mode 100644
index 0000000..2b940d3
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_windows_386.c
@@ -0,0 +1,59 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include "libcgo.h"
+
+static void *threadentry(void*);
+
+/* 1MB is default stack size for 32-bit Windows.
+   Allocation granularity on Windows is typically 64 KB.
+   The constant is also hardcoded in cmd/ld/pe.c (keep synchronized). */
+#define STACKSIZE (1*1024*1024)
+
+static void
+xinitcgo(G *g)
+{
+	int tmp;
+	g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024;
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	_beginthread(threadentry, 0, ts);
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+	void *tls0;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	ts.g->stackbase = (uintptr)&ts;
+	ts.g->stackguard = (uintptr)&ts - STACKSIZE + 8*1024;
+
+	/*
+	 * Set specific keys in thread local storage.
+	 */
+	tls0 = (void*)LocalAlloc(LPTR, 32);
+	asm volatile (
+		"movl %0, %%fs:0x14\n"	// MOVL tls0, 0x14(FS)
+		"movl %%fs:0x14, %%eax\n"	// MOVL 0x14(FS), tmp
+		"movl %1, 0(%%eax)\n"	// MOVL g, 0(FS)
+		"movl %2, 4(%%eax)\n"	// MOVL m, 4(FS)
+		:: "r"(tls0), "r"(ts.g), "r"(ts.m) : "%eax"
+	);
+	
+	crosscall_386(ts.fn);
+	
+	LocalFree(tls0);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/gcc_windows_amd64.c b/src/pkg/runtime/cgo/gcc_windows_amd64.c
new file mode 100644
index 0000000..0d2f5d2
--- /dev/null
+++ b/src/pkg/runtime/cgo/gcc_windows_amd64.c
@@ -0,0 +1,57 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define WIN64_LEAN_AND_MEAN
+#include <windows.h>
+#include "libcgo.h"
+
+static void *threadentry(void*);
+
+/* 2MB is default stack size for 64-bit Windows.
+   Allocation granularity on Windows is typically 64 KB.
+   The constant is also hardcoded in cmd/ld/pe.c (keep synchronized). */
+#define STACKSIZE (2*1024*1024)
+
+static void
+xinitcgo(G *g)
+{
+	int tmp;
+	g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024;
+}
+
+void (*initcgo)(G*) = xinitcgo;
+
+void
+libcgo_sys_thread_start(ThreadStart *ts)
+{
+	_beginthread(threadentry, 0, ts);
+}
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+	void *tls0;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	ts.g->stackbase = (uintptr)&ts;
+	ts.g->stackguard = (uintptr)&ts - STACKSIZE + 8*1024;
+
+	/*
+	 * Set specific keys in thread local storage.
+	 */
+	tls0 = (void*)LocalAlloc(LPTR, 64);
+	asm volatile (
+	  "movq %0, %%gs:0x28\n"	// MOVL tls0, 0x28(GS)
+	  "movq %%gs:0x28, %%rax\n" // MOVQ 0x28(GS), tmp
+	  "movq %1, 0(%%rax)\n" // MOVQ g, 0(GS)
+	  "movq %2, 8(%%rax)\n" // MOVQ m, 8(GS)
+	  :: "r"(tls0), "r"(ts.g), "r"(ts.m) : "%rax"
+	);
+
+	crosscall_amd64(ts.fn);
+	return nil;
+}
diff --git a/src/pkg/runtime/cgo/libcgo.h b/src/pkg/runtime/cgo/libcgo.h
index 9103295..c31d19d 100644
--- a/src/pkg/runtime/cgo/libcgo.h
+++ b/src/pkg/runtime/cgo/libcgo.h
@@ -42,7 +42,7 @@ struct ThreadStart
  * Makes a local copy of the ThreadStart and
  * calls libcgo_sys_thread_start(ts).
  */
-void (*libcgo_thread_start)(ThreadStart *ts);
+extern void (*libcgo_thread_start)(ThreadStart *ts);
 
 /*
  * Creates the new operating system thread (OS, arch dependent).
diff --git a/src/pkg/runtime/cgo/linux_386.c b/src/pkg/runtime/cgo/linux_386.c
deleted file mode 100644
index e9df5ff..0000000
--- a/src/pkg/runtime/cgo/linux_386.c
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <pthread.h>
-#include <string.h>
-#include "libcgo.h"
-
-static void *threadentry(void*);
-
-static void
-xinitcgo(void)
-{
-}
-
-void (*initcgo) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	pthread_attr_t attr;
-	pthread_t p;
-	size_t size;
-	int err;
-
-	// Not sure why the memset is necessary here,
-	// but without it, we get a bogus stack size
-	// out of pthread_attr_getstacksize.  C'est la Linux.
-	memset(&attr, 0, sizeof attr);
-	pthread_attr_init(&attr);
-	size = 0;
-	pthread_attr_getstacksize(&attr, &size);
-	ts->g->stackguard = size;
-	err = pthread_create(&p, &attr, threadentry, ts);
-	if (err != 0) {
-		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
-		abort();
-	}
-}
-
-static void*
-threadentry(void *v)
-{
-	ThreadStart ts;
-
-	ts = *(ThreadStart*)v;
-	free(v);
-
-	ts.g->stackbase = (uintptr)&ts;
-
-	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
-	 * change to actual guard pointer.
-	 */
-	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
-	/*
-	 * Set specific keys.  On Linux/ELF, the thread local storage
-	 * is just before %gs:0.  Our dynamic 8.out's reserve 8 bytes
-	 * for the two words g and m at %gs:-8 and %gs:-4.
-	 * Xen requires us to access those words indirect from %gs:0
-	 * which points at itself.
-	 */
-	asm volatile (
-		"movl %%gs:0, %%eax\n"		// MOVL 0(GS), tmp
-		"movl %0, -8(%%eax)\n"	// MOVL g, -8(GS)
-		"movl %1, -4(%%eax)\n"	// MOVL m, -4(GS)
-		:: "r"(ts.g), "r"(ts.m) : "%eax"
-	);
-
-	crosscall_386(ts.fn);
-	return nil;
-}
diff --git a/src/pkg/runtime/cgo/linux_amd64.c b/src/pkg/runtime/cgo/linux_amd64.c
deleted file mode 100644
index d9b8b37..0000000
--- a/src/pkg/runtime/cgo/linux_amd64.c
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <pthread.h>
-#include "libcgo.h"
-
-static void* threadentry(void*);
-
-void
-xinitcgo(void)
-{
-}
-
-void (*initcgo)(void) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	pthread_attr_t attr;
-	pthread_t p;
-	size_t size;
-	int err;
-
-	pthread_attr_init(&attr);
-	pthread_attr_getstacksize(&attr, &size);
-	ts->g->stackguard = size;
-	err = pthread_create(&p, &attr, threadentry, ts);
-	if (err != 0) {
-		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
-		abort();
-	}
-}
-
-static void*
-threadentry(void *v)
-{
-	ThreadStart ts;
-
-	ts = *(ThreadStart*)v;
-	free(v);
-
-	ts.g->stackbase = (uintptr)&ts;
-
-	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
-	 * change to actual guard pointer.
-	 */
-	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
-	/*
-	 * Set specific keys.  On Linux/ELF, the thread local storage
-	 * is just before %fs:0.  Our dynamic 6.out's reserve 16 bytes
-	 * for the two words g and m at %fs:-16 and %fs:-8.
-	 */
-	asm volatile (
-		"movq %0, %%fs:-16\n"	// MOVL g, -16(FS)
-		"movq %1, %%fs:-8\n"	// MOVL m, -8(FS)
-		:: "r"(ts.g), "r"(ts.m)
-	);
-	crosscall_amd64(ts.fn);
-	return nil;
-}
diff --git a/src/pkg/runtime/cgo/linux_arm.c b/src/pkg/runtime/cgo/linux_arm.c
deleted file mode 100644
index e556c43..0000000
--- a/src/pkg/runtime/cgo/linux_arm.c
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "libcgo.h"
-
-static void
-xinitcgo(void)
-{
-}
-
-void (*initcgo)(void) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	// unimplemented
-	*(int*)0 = 0;
-}
diff --git a/src/pkg/runtime/cgo/setenv.c b/src/pkg/runtime/cgo/setenv.c
deleted file mode 100644
index c911b83..0000000
--- a/src/pkg/runtime/cgo/setenv.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 20111 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "libcgo.h"
-
-#include <stdlib.h>
-
-/* Stub for calling setenv */
-static void
-xlibcgo_setenv(char **arg)
-{
-	setenv(arg[0], arg[1], 1);
-}
-
-void (*libcgo_setenv)(char**) = xlibcgo_setenv;
diff --git a/src/pkg/runtime/cgo/trigger.go b/src/pkg/runtime/cgo/trigger.go
new file mode 100644
index 0000000..a778811
--- /dev/null
+++ b/src/pkg/runtime/cgo/trigger.go
@@ -0,0 +1,20 @@
+// Copyright 2011 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 tells the go tool that this package builds using cgo.
+// TODO: Once we stop using Make, this import can move into cgo.go.
+
+package cgo
+
+/*
+
+#cgo darwin LDFLAGS: -lpthread
+#cgo freebsd LDFLAGS: -lpthread
+#cgo linux LDFLAGS: -lpthread
+#cgo netbsd LDFLAGS: -lpthread
+#cgo openbsd LDFLAGS: -lpthread
+#cgo windows LDFLAGS: -lm -mthreads
+
+*/
+import "C"
diff --git a/src/pkg/runtime/cgo/windows_386.c b/src/pkg/runtime/cgo/windows_386.c
deleted file mode 100755
index f39309c..0000000
--- a/src/pkg/runtime/cgo/windows_386.c
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include "libcgo.h"
-
-static void *threadentry(void*);
-
-/* From what I've read 1MB is default for 32-bit Linux. 
-   Allocation granularity on Windows is typically 64 KB. */
-#define STACKSIZE (1*1024*1024)
-
-static void
-xinitcgo(void)
-{
-}
-
-void (*initcgo)(void) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	ts->g->stackguard = STACKSIZE;
-	_beginthread(threadentry, STACKSIZE, ts);
-}
-
-static void*
-threadentry(void *v)
-{
-	ThreadStart ts;
-	void *tls0;
-
-	ts = *(ThreadStart*)v;
-	free(v);
-
-	ts.g->stackbase = (uintptr)&ts;
-
-	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
-	 * change to actual guard pointer.
-	 */
-	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
-	/*
-	 * Set specific keys in thread local storage.
-	 */
-	tls0 = (void*)LocalAlloc(LPTR, 32);
-	asm volatile (
-		"movl %0, %%fs:0x2c\n"	// MOVL tls0, 0x2c(FS)
-		"movl %%fs:0x2c, %%eax\n"	// MOVL 0x2c(FS), tmp
-		"movl %1, 0(%%eax)\n"	// MOVL g, 0(FS)
-		"movl %2, 4(%%eax)\n"	// MOVL m, 4(FS)
-		:: "r"(tls0), "r"(ts.g), "r"(ts.m) : "%eax"
-	);
-	
-	crosscall_386(ts.fn);
-	
-	LocalFree(tls0);
-	return nil;
-}
diff --git a/src/pkg/runtime/cgo/windows_amd64.c b/src/pkg/runtime/cgo/windows_amd64.c
deleted file mode 100755
index e8313e2..0000000
--- a/src/pkg/runtime/cgo/windows_amd64.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define WIN64_LEAN_AND_MEAN
-#include <windows.h>
-#include "libcgo.h"
-
-static void *threadentry(void*);
-
-/* From what I've read 2MB is default for 64-bit Linux. 
-   Allocation granularity on Windows is typically 64 KB. */
-#define STACKSIZE (2*1024*1024)
-
-static void
-xinitcgo(void)
-{
-}
-
-void (*initcgo)(void) = xinitcgo;
-
-void
-libcgo_sys_thread_start(ThreadStart *ts)
-{
-	ts->g->stackguard = STACKSIZE;
-	_beginthread(threadentry, STACKSIZE, ts);
-}
-
-static void*
-threadentry(void *v)
-{
-	ThreadStart ts;
-	void *tls0;
-
-	ts = *(ThreadStart*)v;
-	free(v);
-
-	ts.g->stackbase = (uintptr)&ts;
-
-	/*
-	 * libcgo_sys_thread_start set stackguard to stack size;
-	 * change to actual guard pointer.
-	 */
-	ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096;
-
-	/*
-	 * Set specific keys in thread local storage.
-	 */
-	tls0 = (void*)LocalAlloc(LPTR, 64);
-	asm volatile (
-	  "movq %0, %%gs:0x58\n"	// MOVL tls0, 0x58(GS)
-	  "movq %%gs:0x58, %%rax\n" // MOVQ 0x58(GS), tmp
-	  "movq %1, 0(%%rax)\n" // MOVQ g, 0(GS)
-	  "movq %2, 8(%%rax)\n" // MOVQ m, 8(GS)
-	  :: "r"(tls0), "r"(ts.g), "r"(ts.m) : "%rax"
-	);
-
-	crosscall_amd64(ts.fn);
-	return nil;
-}
diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c
index 4fdb912..756eff3 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
-#include "arch.h"
+#include "arch_GOARCH.h"
 #include "stack.h"
 #include "cgocall.h"
 
@@ -17,7 +17,7 @@
 // so as not to block other goroutines or the garbage collector,
 // and then calls runtime.asmcgocall(_cgo_Cfunc_f, frame). 
 //
-// runtime.asmcgocall (in $GOARCH/asm.s) switches to the m->g0 stack
+// runtime.asmcgocall (in asm_$GOARCH.s) switches to the m->g0 stack
 // (assumed to be an operating system-allocated stack, so safe to run
 // gcc-compiled code on) and calls _cgo_Cfunc_f(frame).
 //
@@ -55,7 +55,7 @@
 // with 6c instead of gcc, can refer to dotted names like
 // runtime.cgocallback and p.GoF.)
 //
-// runtime.cgocallback (in $GOOS/asm.s) switches from m->g0's
+// runtime.cgocallback (in asm_$GOARCH.s) switches from m->g0's
 // stack to the original g (m->curg)'s stack, on which it calls
 // runtime.cgocallbackg(p.GoF, frame, framesize).
 // As part of the stack switch, runtime.cgocallback saves the current
diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c
index eac2098..bea1a34 100644
--- a/src/pkg/runtime/chan.c
+++ b/src/pkg/runtime/chan.c
@@ -92,11 +92,6 @@ runtime·makechan_c(ChanType *t, int64 hint)
 	if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
 		runtime·panicstring("makechan: size out of range");
 
-	if(elem->alg >= nelem(runtime·algarray)) {
-		runtime·printf("chan(alg=%d)\n", elem->alg);
-		runtime·throw("runtime.makechan: unsupported elem type");
-	}
-
 	// calculate rounded size of Hchan
 	n = sizeof(*c);
 	while(n & MAXALIGN)
@@ -104,16 +99,13 @@ runtime·makechan_c(ChanType *t, int64 hint)
 
 	// allocate memory in one call
 	c = (Hchan*)runtime·mal(n + hint*elem->size);
-	if(runtime·destroylock)
-		runtime·addfinalizer(c, (void*)destroychan, 0);
-
 	c->elemsize = elem->size;
-	c->elemalg = &runtime·algarray[elem->alg];
+	c->elemalg = elem->alg;
 	c->elemalign = elem->align;
 	c->dataqsiz = hint;
 
 	if(debug)
-		runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%d; elemalign=%d; dataqsiz=%d\n",
+		runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%d\n",
 			c, (int64)elem->size, elem->alg, elem->align, c->dataqsiz);
 
 	return c;
@@ -128,13 +120,6 @@ reflect·makechan(ChanType *t, uint32 size, Hchan *c)
 	FLUSH(&c);
 }
 
-static void
-destroychan(Hchan *c)
-{
-	runtime·destroylock(&c->Lock);
-}
-
-
 // makechan(t *ChanType, hint int64) (hchan *chan any);
 void
 runtime·makechan(ChanType *t, int64 hint, Hchan *ret)
@@ -1024,7 +1009,8 @@ syncsend:
 	selunlock(sel);
 	if(debug)
 		runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
-	c->elemalg->copy(c->elemsize, sg->elem, cas->sg.elem);
+	if(sg->elem != nil)
+		c->elemalg->copy(c->elemsize, sg->elem, cas->sg.elem);
 	gp = sg->g;
 	gp->param = sg;
 	runtime·ready(gp);
@@ -1051,6 +1037,9 @@ runtime·closechan(Hchan *c)
 	SudoG *sg;
 	G* gp;
 
+	if(c == nil)
+		runtime·panicstring("close of nil channel");
+
 	if(runtime·gcwaiting)
 		runtime·gosched();
 
diff --git a/src/pkg/runtime/chan_test.go b/src/pkg/runtime/chan_test.go
index 7cea906..eb2c7c6 100644
--- a/src/pkg/runtime/chan_test.go
+++ b/src/pkg/runtime/chan_test.go
@@ -371,3 +371,12 @@ func BenchmarkChanCreation(b *testing.B) {
 		<-c
 	}
 }
+
+func BenchmarkChanSem(b *testing.B) {
+	type Empty struct{}
+	c := make(chan Empty, 1)
+	for i := 0; i < b.N; i++ {
+		c <- Empty{}
+		<-c
+	}
+}
diff --git a/src/pkg/runtime/386/closure.c b/src/pkg/runtime/closure_386.c
similarity index 100%
rename from src/pkg/runtime/386/closure.c
rename to src/pkg/runtime/closure_386.c
diff --git a/src/pkg/runtime/amd64/closure.c b/src/pkg/runtime/closure_amd64.c
similarity index 100%
rename from src/pkg/runtime/amd64/closure.c
rename to src/pkg/runtime/closure_amd64.c
diff --git a/src/pkg/runtime/arm/closure.c b/src/pkg/runtime/closure_arm.c
similarity index 100%
rename from src/pkg/runtime/arm/closure.c
rename to src/pkg/runtime/closure_arm.c
diff --git a/src/pkg/runtime/cpuprof.c b/src/pkg/runtime/cpuprof.c
index 74b795b..05fa0cf 100644
--- a/src/pkg/runtime/cpuprof.c
+++ b/src/pkg/runtime/cpuprof.c
@@ -49,6 +49,7 @@
 // in the situation when normally the goroutine "owns" handoff.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 
 enum
diff --git a/src/pkg/runtime/darwin/386/defs.h b/src/pkg/runtime/darwin/386/defs.h
deleted file mode 100644
index bb70207..0000000
--- a/src/pkg/runtime/darwin/386/defs.h
+++ /dev/null
@@ -1,289 +0,0 @@
-// godefs -f -m32 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	MACH_MSG_TYPE_MOVE_RECEIVE = 0x10,
-	MACH_MSG_TYPE_MOVE_SEND = 0x11,
-	MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12,
-	MACH_MSG_TYPE_COPY_SEND = 0x13,
-	MACH_MSG_TYPE_MAKE_SEND = 0x14,
-	MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15,
-	MACH_MSG_TYPE_COPY_RECEIVE = 0x16,
-	MACH_MSG_PORT_DESCRIPTOR = 0,
-	MACH_MSG_OOL_DESCRIPTOR = 0x1,
-	MACH_MSG_OOL_PORTS_DESCRIPTOR = 0x2,
-	MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3,
-	MACH_MSGH_BITS_COMPLEX = 0x80000000,
-	MACH_SEND_MSG = 0x1,
-	MACH_RCV_MSG = 0x2,
-	MACH_RCV_LARGE = 0x4,
-	MACH_SEND_TIMEOUT = 0x10,
-	MACH_SEND_INTERRUPT = 0x40,
-	MACH_SEND_CANCEL = 0x80,
-	MACH_SEND_ALWAYS = 0x10000,
-	MACH_SEND_TRAILER = 0x20000,
-	MACH_RCV_TIMEOUT = 0x100,
-	MACH_RCV_NOTIFY = 0x200,
-	MACH_RCV_INTERRUPT = 0x400,
-	MACH_RCV_OVERWRITE = 0x1000,
-	NDR_PROTOCOL_2_0 = 0,
-	NDR_INT_BIG_ENDIAN = 0,
-	NDR_INT_LITTLE_ENDIAN = 0x1,
-	NDR_FLOAT_IEEE = 0,
-	NDR_CHAR_ASCII = 0,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	SA_USERTRAMP = 0x100,
-	SA_64REGSET = 0x200,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x7,
-	FPE_INTOVF = 0x8,
-	FPE_FLTDIV = 0x1,
-	FPE_FLTOVF = 0x2,
-	FPE_FLTUND = 0x3,
-	FPE_FLTRES = 0x4,
-	FPE_FLTINV = 0x5,
-	FPE_FLTSUB = 0x6,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
-
-// Types
-#pragma pack on
-
-typedef struct MachBody MachBody;
-struct MachBody {
-	uint32 msgh_descriptor_count;
-};
-
-typedef struct MachHeader MachHeader;
-struct MachHeader {
-	uint32 msgh_bits;
-	uint32 msgh_size;
-	uint32 msgh_remote_port;
-	uint32 msgh_local_port;
-	uint32 msgh_reserved;
-	int32 msgh_id;
-};
-
-typedef struct MachNDR MachNDR;
-struct MachNDR {
-	uint8 mig_vers;
-	uint8 if_vers;
-	uint8 reserved1;
-	uint8 mig_encoding;
-	uint8 int_rep;
-	uint8 char_rep;
-	uint8 float_rep;
-	uint8 reserved2;
-};
-
-typedef struct MachPort MachPort;
-struct MachPort {
-	uint32 name;
-	uint32 pad1;
-	uint16 pad2;
-	uint8 disposition;
-	uint8 type;
-};
-
-typedef struct StackT StackT;
-struct StackT {
-	void *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
-};
-
-typedef union Sighandler Sighandler;
-union Sighandler {
-	uint32 __sa_handler;
-	uint32 __sa_sigaction;
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
-	Sighandler __sigaction_u;
-	uint32 sa_tramp;
-	uint32 sa_mask;
-	int32 sa_flags;
-};
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	int32 si_pid;
-	uint32 si_uid;
-	int32 si_status;
-	void *si_addr;
-	Sigval si_value;
-	int32 si_band;
-	uint32 __pad[7];
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int32 tv_sec;
-	int32 tv_usec;
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-
-typedef struct FPControl FPControl;
-struct FPControl {
-	byte pad_godefs_0[2];
-};
-
-typedef struct FPStatus FPStatus;
-struct FPStatus {
-	byte pad_godefs_0[2];
-};
-
-typedef struct RegMMST RegMMST;
-struct RegMMST {
-	int8 mmst_reg[10];
-	int8 mmst_rsrv[6];
-};
-
-typedef struct RegXMM RegXMM;
-struct RegXMM {
-	int8 xmm_reg[16];
-};
-
-typedef struct Regs Regs;
-struct Regs {
-	uint32 eax;
-	uint32 ebx;
-	uint32 ecx;
-	uint32 edx;
-	uint32 edi;
-	uint32 esi;
-	uint32 ebp;
-	uint32 esp;
-	uint32 ss;
-	uint32 eflags;
-	uint32 eip;
-	uint32 cs;
-	uint32 ds;
-	uint32 es;
-	uint32 fs;
-	uint32 gs;
-};
-
-typedef struct FloatState FloatState;
-struct FloatState {
-	uint64 fpu_reserved;
-	FPControl fpu_fcw;
-	FPStatus fpu_fsw;
-	uint8 fpu_ftw;
-	uint8 fpu_rsrv1;
-	uint16 fpu_fop;
-	uint32 fpu_ip;
-	uint16 fpu_cs;
-	uint16 fpu_rsrv2;
-	uint32 fpu_dp;
-	uint16 fpu_ds;
-	uint16 fpu_rsrv3;
-	uint32 fpu_mxcsr;
-	uint32 fpu_mxcsrmask;
-	RegMMST fpu_stmm0;
-	RegMMST fpu_stmm1;
-	RegMMST fpu_stmm2;
-	RegMMST fpu_stmm3;
-	RegMMST fpu_stmm4;
-	RegMMST fpu_stmm5;
-	RegMMST fpu_stmm6;
-	RegMMST fpu_stmm7;
-	RegXMM fpu_xmm0;
-	RegXMM fpu_xmm1;
-	RegXMM fpu_xmm2;
-	RegXMM fpu_xmm3;
-	RegXMM fpu_xmm4;
-	RegXMM fpu_xmm5;
-	RegXMM fpu_xmm6;
-	RegXMM fpu_xmm7;
-	int8 fpu_rsrv4[224];
-	int32 fpu_reserved1;
-};
-
-typedef struct ExceptionState ExceptionState;
-struct ExceptionState {
-	uint32 trapno;
-	uint32 err;
-	uint32 faultvaddr;
-};
-
-typedef struct Mcontext Mcontext;
-struct Mcontext {
-	ExceptionState es;
-	Regs ss;
-	FloatState fs;
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
-	int32 uc_onstack;
-	uint32 uc_sigmask;
-	StackT uc_stack;
-	uint32 uc_link;
-	uint32 uc_mcsize;
-	Mcontext *uc_mcontext;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/darwin/386/signal.c b/src/pkg/runtime/darwin/386/signal.c
deleted file mode 100644
index 29170b6..0000000
--- a/src/pkg/runtime/darwin/386/signal.c
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "signals.h"
-
-void
-runtime·dumpregs(Regs *r)
-{
-	runtime·printf("eax     %x\n", r->eax);
-	runtime·printf("ebx     %x\n", r->ebx);
-	runtime·printf("ecx     %x\n", r->ecx);
-	runtime·printf("edx     %x\n", r->edx);
-	runtime·printf("edi     %x\n", r->edi);
-	runtime·printf("esi     %x\n", r->esi);
-	runtime·printf("ebp     %x\n", r->ebp);
-	runtime·printf("esp     %x\n", r->esp);
-	runtime·printf("eip     %x\n", r->eip);
-	runtime·printf("eflags  %x\n", r->eflags);
-	runtime·printf("cs      %x\n", r->cs);
-	runtime·printf("fs      %x\n", r->fs);
-	runtime·printf("gs      %x\n", r->gs);
-}
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Ucontext *uc;
-	Mcontext *mc;
-	Regs *r;
-	uintptr *sp;
-	byte *pc;
-
-	uc = context;
-	mc = uc->uc_mcontext;
-	r = &mc->ss;
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Work around Leopard bug that doesn't set FPE_INTDIV.
-		// Look at instruction to see if it is a divide.
-		// Not necessary in Snow Leopard (si_code will be != 0).
-		if(sig == SIGFPE && info->si_code == 0) {
-			pc = (byte*)r->eip;
-			if(pc[0] == 0x66)	// 16-bit instruction prefix
-				pc++;
-			if(pc[0] == 0xF6 || pc[0] == 0xF7)
-				info->si_code = FPE_INTDIV;
-		}
-		
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = (uintptr)info->si_addr;
-		gp->sigpc = r->eip;
-
-		// Only push runtime·sigpanic if r->eip != 0.
-		// If r->eip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->eip != 0) {
-			sp = (uintptr*)r->esp;
-			*--sp = r->eip;
-			r->esp = (uintptr)sp;
-		}
-		r->eip = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG){
-		runtime·printf("Signal %d\n", sig);
-	}else{
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-	}
-
-	runtime·printf("pc: %x\n", r->eip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-}
-
-void
-runtime·sigignore(int32, Siginfo*, void*)
-{
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	StackT st;
-
-	st.ss_sp = p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0U;
-	sa.sa_tramp = (uintptr)runtime·sigtramp;	// runtime·sigtramp's job is to call into real handler
-	sa.__sigaction_u.__sa_sigaction = (uintptr)fn;
-	runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
diff --git a/src/pkg/runtime/darwin/386/sys.s b/src/pkg/runtime/darwin/386/sys.s
deleted file mode 100644
index 87fbdbb..0000000
--- a/src/pkg/runtime/darwin/386/sys.s
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// System calls and other sys.stuff for 386, Darwin
-// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
-// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
-
-#include "386/asm.h"
-
-TEXT runtime·notok(SB),7,$0
-	MOVL	$0xf1, 0xf1
-	RET
-
-// Exit the entire program (like C exit)
-TEXT runtime·exit(SB),7,$0
-	MOVL	$1, AX
-	INT	$0x80
-	CALL	runtime·notok(SB)
-	RET
-
-// Exit this OS thread (like pthread_exit, which eventually
-// calls __bsdthread_terminate).
-TEXT runtime·exit1(SB),7,$0
-	MOVL	$361, AX
-	INT	$0x80
-	JAE 2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·write(SB),7,$0
-	MOVL	$4, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·raisesigpipe(SB),7,$8
-	get_tls(CX)
-	MOVL	m(CX), DX
-	MOVL	m_procid(DX), DX
-	MOVL	DX, 0(SP)	// thread_port
-	MOVL	$13, 4(SP)	// signal: SIGPIPE
-	MOVL	$328, AX	// __pthread_kill
-	INT	$0x80
-	RET
-
-TEXT runtime·mmap(SB),7,$0
-	MOVL	$197, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·munmap(SB),7,$0
-	MOVL	$73, AX
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·setitimer(SB),7,$0
-	MOVL	$83, AX
-	INT	$0x80
-	RET
-
-// void gettime(int64 *sec, int32 *usec)
-TEXT runtime·gettime(SB), 7, $32
-	LEAL	12(SP), AX	// must be non-nil, unused
-	MOVL	AX, 4(SP)
-	MOVL	$0, 8(SP)	// time zone pointer
-	MOVL	$116, AX
-	INT	$0x80
-
-	MOVL	sec+0(FP), DI
-	MOVL	AX, (DI)
-	MOVL	$0, 4(DI)	// zero extend 32 -> 64
-
-	MOVL	usec+4(FP), DI
-	MOVL	DX, (DI)
-	RET
-
-TEXT runtime·sigaction(SB),7,$0
-	MOVL	$46, AX
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-// Sigtramp's job is to call the actual signal handler.
-// It is called with the following arguments on the stack:
-//	0(FP)	"return address" - ignored
-//	4(FP)	actual handler
-//	8(FP)	siginfo style - ignored
-//	12(FP)	signal number
-//	16(FP)	siginfo
-//	20(FP)	context
-TEXT runtime·sigtramp(SB),7,$40
-	get_tls(CX)
-
-	// save g
-	MOVL	g(CX), DI
-	MOVL	DI, 20(SP)
-	
-	// g = m->gsignal
-	MOVL	m(CX), BP
-	MOVL	m_gsignal(BP), BP
-	MOVL	BP, g(CX)
-
-	// copy arguments to sighandler
-	MOVL	sig+8(FP), BX
-	MOVL	BX, 0(SP)
-	MOVL	info+12(FP), BX
-	MOVL	BX, 4(SP)
-	MOVL	context+16(FP), BX
-	MOVL	BX, 8(SP)
-	MOVL	DI, 12(SP)
-	
-	MOVL	handler+0(FP), BX
-	CALL	BX
-
-	// restore g
-	get_tls(CX)
-	MOVL	20(SP), DI
-	MOVL	DI, g(CX)
-
-	// call sigreturn
-	MOVL	context+16(FP), CX
-	MOVL	style+4(FP), BX
-	MOVL	$0, 0(SP)	// "caller PC" - ignored
-	MOVL	CX, 4(SP)
-	MOVL	BX, 8(SP)
-	MOVL	$184, AX	// sigreturn(ucontext, infostyle)
-	INT	$0x80
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·sigaltstack(SB),7,$0
-	MOVL	$53, AX
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
-// System call args are: func arg stack pthread flags.
-TEXT runtime·bsdthread_create(SB),7,$32
-	MOVL	$360, AX
-	// 0(SP) is where the caller PC would be; kernel skips it
-	MOVL	func+12(FP), BX
-	MOVL	BX, 4(SP)	// func
-	MOVL	mm+4(FP), BX
-	MOVL	BX, 8(SP)	// arg
-	MOVL	stk+0(FP), BX
-	MOVL	BX, 12(SP)	// stack
-	MOVL	gg+8(FP), BX
-	MOVL	BX, 16(SP)	// pthread
-	MOVL	$0x1000000, 20(SP)	// flags = PTHREAD_START_CUSTOM
-	INT	$0x80
-	JAE	3(PC)
-	NEGL	AX
-	RET
-	MOVL	$0, AX
-	RET
-
-// The thread that bsdthread_create creates starts executing here,
-// because we registered this function using bsdthread_register
-// at startup.
-//	AX = "pthread" (= g)
-//	BX = mach thread port
-//	CX = "func" (= fn)
-//	DX = "arg" (= m)
-//	DI = stack top
-//	SI = flags (= 0x1000000)
-//	SP = stack - C_32_STK_ALIGN
-TEXT runtime·bsdthread_start(SB),7,$0
-	// set up ldt 7+id to point at m->tls.
-	// m->tls is at m+40.  newosproc left
-	// the m->id in tls[0].
-	LEAL	m_tls(DX), BP
-	MOVL	0(BP), DI
-	ADDL	$7, DI	// m0 is LDT#7. count up.
-	// setldt(tls#, &tls, sizeof tls)
-	PUSHAL	// save registers
-	PUSHL	$32	// sizeof tls
-	PUSHL	BP	// &tls
-	PUSHL	DI	// tls #
-	CALL	runtime·setldt(SB)
-	POPL	AX
-	POPL	AX
-	POPL	AX
-	POPAL
-
-	// Now segment is established.  Initialize m, g.
-	get_tls(BP)
-	MOVL	AX, g(BP)
-	MOVL	DX, m(BP)
-	MOVL	BX, m_procid(DX)	// m->procid = thread port (for debuggers)
-	CALL	runtime·stackcheck(SB)		// smashes AX
-	CALL	CX	// fn()
-	CALL	runtime·exit1(SB)
-	RET
-
-// void bsdthread_register(void)
-// registers callbacks for threadstart (see bsdthread_create above
-// and wqthread and pthsize (not used).  returns 0 on success.
-TEXT runtime·bsdthread_register(SB),7,$40
-	MOVL	$366, AX
-	// 0(SP) is where kernel expects caller PC; ignored
-	MOVL	$runtime·bsdthread_start(SB), 4(SP)	// threadstart
-	MOVL	$0, 8(SP)	// wqthread, not used by us
-	MOVL	$0, 12(SP)	// pthsize, not used by us
-	MOVL	$0, 16(SP)	// dummy_value [sic]
-	MOVL	$0, 20(SP)	// targetconc_ptr
-	MOVL	$0, 24(SP)	// dispatchqueue_offset
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-// Invoke Mach system call.
-// Assumes system call number in AX,
-// caller PC on stack, caller's caller PC next,
-// and then the system call arguments.
-//
-// Can be used for BSD too, but we don't,
-// because if you use this interface the BSD
-// system call numbers need an extra field
-// in the high 16 bits that seems to be the
-// argument count in bytes but is not always.
-// INT $0x80 works fine for those.
-TEXT runtime·sysenter(SB),7,$0
-	POPL	DX
-	MOVL	SP, CX
-	BYTE $0x0F; BYTE $0x34;  // SYSENTER
-	// returns to DX with SP set to CX
-
-TEXT runtime·mach_msg_trap(SB),7,$0
-	MOVL	$-31, AX
-	CALL	runtime·sysenter(SB)
-	RET
-
-TEXT runtime·mach_reply_port(SB),7,$0
-	MOVL	$-26, AX
-	CALL	runtime·sysenter(SB)
-	RET
-
-TEXT runtime·mach_task_self(SB),7,$0
-	MOVL	$-28, AX
-	CALL	runtime·sysenter(SB)
-	RET
-
-// Mach provides trap versions of the semaphore ops,
-// instead of requiring the use of RPC.
-
-// uint32 mach_semaphore_wait(uint32)
-TEXT runtime·mach_semaphore_wait(SB),7,$0
-	MOVL	$-36, AX
-	CALL	runtime·sysenter(SB)
-	RET
-
-// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
-TEXT runtime·mach_semaphore_timedwait(SB),7,$0
-	MOVL	$-38, AX
-	CALL	runtime·sysenter(SB)
-	RET
-
-// uint32 mach_semaphore_signal(uint32)
-TEXT runtime·mach_semaphore_signal(SB),7,$0
-	MOVL	$-33, AX
-	CALL	runtime·sysenter(SB)
-	RET
-
-// uint32 mach_semaphore_signal_all(uint32)
-TEXT runtime·mach_semaphore_signal_all(SB),7,$0
-	MOVL	$-34, AX
-	CALL	runtime·sysenter(SB)
-	RET
-
-// setldt(int entry, int address, int limit)
-// entry and limit are ignored.
-TEXT runtime·setldt(SB),7,$32
-	MOVL	address+4(FP), BX	// aka base
-
-	/*
-	 * When linking against the system libraries,
-	 * we use its pthread_create and let it set up %gs
-	 * for us.  When we do that, the private storage
-	 * we get is not at 0(GS) but at 0x468(GS).
-	 * To insulate the rest of the tool chain from this ugliness,
-	 * 8l rewrites 0(GS) into 0x468(GS) for us.
-	 * To accommodate that rewrite, we translate the
-	 * address and limit here so that 0x468(GS) maps to 0(address).
-	 *
-	 * See ../../../../libcgo/darwin_386.c for the derivation
-	 * of the constant.
-	 */
-	SUBL	$0x468, BX
-
-	/*
-	 * Must set up as USER_CTHREAD segment because
-	 * Darwin forces that value into %gs for signal handlers,
-	 * and if we don't set one up, we'll get a recursive
-	 * fault trying to get into the signal handler.
-	 * Since we have to set one up anyway, it might as
-	 * well be the value we want.  So don't bother with
-	 * i386_set_ldt.
-	 */
-	MOVL	BX, 4(SP)
-	MOVL	$3, AX	// thread_fast_set_cthread_self - machdep call #3
-	INT	$0x82	// sic: 0x82, not 0x80, for machdep call
-
-	XORL	AX, AX
-	MOVW	GS, AX
-	RET
diff --git a/src/pkg/runtime/darwin/amd64/defs.h b/src/pkg/runtime/darwin/amd64/defs.h
deleted file mode 100644
index 90f798e..0000000
--- a/src/pkg/runtime/darwin/amd64/defs.h
+++ /dev/null
@@ -1,305 +0,0 @@
-// godefs -f -m64 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	MACH_MSG_TYPE_MOVE_RECEIVE = 0x10,
-	MACH_MSG_TYPE_MOVE_SEND = 0x11,
-	MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12,
-	MACH_MSG_TYPE_COPY_SEND = 0x13,
-	MACH_MSG_TYPE_MAKE_SEND = 0x14,
-	MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15,
-	MACH_MSG_TYPE_COPY_RECEIVE = 0x16,
-	MACH_MSG_PORT_DESCRIPTOR = 0,
-	MACH_MSG_OOL_DESCRIPTOR = 0x1,
-	MACH_MSG_OOL_PORTS_DESCRIPTOR = 0x2,
-	MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3,
-	MACH_MSGH_BITS_COMPLEX = 0x80000000,
-	MACH_SEND_MSG = 0x1,
-	MACH_RCV_MSG = 0x2,
-	MACH_RCV_LARGE = 0x4,
-	MACH_SEND_TIMEOUT = 0x10,
-	MACH_SEND_INTERRUPT = 0x40,
-	MACH_SEND_CANCEL = 0x80,
-	MACH_SEND_ALWAYS = 0x10000,
-	MACH_SEND_TRAILER = 0x20000,
-	MACH_RCV_TIMEOUT = 0x100,
-	MACH_RCV_NOTIFY = 0x200,
-	MACH_RCV_INTERRUPT = 0x400,
-	MACH_RCV_OVERWRITE = 0x1000,
-	NDR_PROTOCOL_2_0 = 0,
-	NDR_INT_BIG_ENDIAN = 0,
-	NDR_INT_LITTLE_ENDIAN = 0x1,
-	NDR_FLOAT_IEEE = 0,
-	NDR_CHAR_ASCII = 0,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	SA_USERTRAMP = 0x100,
-	SA_64REGSET = 0x200,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x7,
-	FPE_INTOVF = 0x8,
-	FPE_FLTDIV = 0x1,
-	FPE_FLTOVF = 0x2,
-	FPE_FLTUND = 0x3,
-	FPE_FLTRES = 0x4,
-	FPE_FLTINV = 0x5,
-	FPE_FLTSUB = 0x6,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
-
-// Types
-#pragma pack on
-
-typedef struct MachBody MachBody;
-struct MachBody {
-	uint32 msgh_descriptor_count;
-};
-
-typedef struct MachHeader MachHeader;
-struct MachHeader {
-	uint32 msgh_bits;
-	uint32 msgh_size;
-	uint32 msgh_remote_port;
-	uint32 msgh_local_port;
-	uint32 msgh_reserved;
-	int32 msgh_id;
-};
-
-typedef struct MachNDR MachNDR;
-struct MachNDR {
-	uint8 mig_vers;
-	uint8 if_vers;
-	uint8 reserved1;
-	uint8 mig_encoding;
-	uint8 int_rep;
-	uint8 char_rep;
-	uint8 float_rep;
-	uint8 reserved2;
-};
-
-typedef struct MachPort MachPort;
-struct MachPort {
-	uint32 name;
-	uint32 pad1;
-	uint16 pad2;
-	uint8 disposition;
-	uint8 type;
-};
-
-typedef struct StackT StackT;
-struct StackT {
-	void *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
-};
-
-typedef union Sighandler Sighandler;
-union Sighandler {
-	uint64 __sa_handler;
-	uint64 __sa_sigaction;
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
-	Sighandler __sigaction_u;
-	uint64 sa_tramp;
-	uint32 sa_mask;
-	int32 sa_flags;
-};
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	int32 si_pid;
-	uint32 si_uid;
-	int32 si_status;
-	void *si_addr;
-	Sigval si_value;
-	int64 si_band;
-	uint64 __pad[7];
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int64 tv_sec;
-	int32 tv_usec;
-	byte pad_godefs_0[4];
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-
-typedef struct FPControl FPControl;
-struct FPControl {
-	byte pad_godefs_0[2];
-};
-
-typedef struct FPStatus FPStatus;
-struct FPStatus {
-	byte pad_godefs_0[2];
-};
-
-typedef struct RegMMST RegMMST;
-struct RegMMST {
-	int8 mmst_reg[10];
-	int8 mmst_rsrv[6];
-};
-
-typedef struct RegXMM RegXMM;
-struct RegXMM {
-	int8 xmm_reg[16];
-};
-
-typedef struct Regs Regs;
-struct Regs {
-	uint64 rax;
-	uint64 rbx;
-	uint64 rcx;
-	uint64 rdx;
-	uint64 rdi;
-	uint64 rsi;
-	uint64 rbp;
-	uint64 rsp;
-	uint64 r8;
-	uint64 r9;
-	uint64 r10;
-	uint64 r11;
-	uint64 r12;
-	uint64 r13;
-	uint64 r14;
-	uint64 r15;
-	uint64 rip;
-	uint64 rflags;
-	uint64 cs;
-	uint64 fs;
-	uint64 gs;
-};
-
-typedef struct FloatState FloatState;
-struct FloatState {
-	uint64 fpu_reserved;
-	FPControl fpu_fcw;
-	FPStatus fpu_fsw;
-	uint8 fpu_ftw;
-	uint8 fpu_rsrv1;
-	uint16 fpu_fop;
-	uint32 fpu_ip;
-	uint16 fpu_cs;
-	uint16 fpu_rsrv2;
-	uint32 fpu_dp;
-	uint16 fpu_ds;
-	uint16 fpu_rsrv3;
-	uint32 fpu_mxcsr;
-	uint32 fpu_mxcsrmask;
-	RegMMST fpu_stmm0;
-	RegMMST fpu_stmm1;
-	RegMMST fpu_stmm2;
-	RegMMST fpu_stmm3;
-	RegMMST fpu_stmm4;
-	RegMMST fpu_stmm5;
-	RegMMST fpu_stmm6;
-	RegMMST fpu_stmm7;
-	RegXMM fpu_xmm0;
-	RegXMM fpu_xmm1;
-	RegXMM fpu_xmm2;
-	RegXMM fpu_xmm3;
-	RegXMM fpu_xmm4;
-	RegXMM fpu_xmm5;
-	RegXMM fpu_xmm6;
-	RegXMM fpu_xmm7;
-	RegXMM fpu_xmm8;
-	RegXMM fpu_xmm9;
-	RegXMM fpu_xmm10;
-	RegXMM fpu_xmm11;
-	RegXMM fpu_xmm12;
-	RegXMM fpu_xmm13;
-	RegXMM fpu_xmm14;
-	RegXMM fpu_xmm15;
-	int8 fpu_rsrv4[96];
-	int32 fpu_reserved1;
-};
-
-typedef struct ExceptionState ExceptionState;
-struct ExceptionState {
-	uint32 trapno;
-	uint32 err;
-	uint64 faultvaddr;
-};
-
-typedef struct Mcontext Mcontext;
-struct Mcontext {
-	ExceptionState es;
-	Regs ss;
-	FloatState fs;
-	byte pad_godefs_0[4];
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
-	int32 uc_onstack;
-	uint32 uc_sigmask;
-	StackT uc_stack;
-	uint64 uc_link;
-	uint64 uc_mcsize;
-	Mcontext *uc_mcontext;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/darwin/amd64/signal.c b/src/pkg/runtime/darwin/amd64/signal.c
deleted file mode 100644
index 036a3ac..0000000
--- a/src/pkg/runtime/darwin/amd64/signal.c
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "signals.h"
-
-void
-runtime·dumpregs(Regs *r)
-{
-	runtime·printf("rax     %X\n", r->rax);
-	runtime·printf("rbx     %X\n", r->rbx);
-	runtime·printf("rcx     %X\n", r->rcx);
-	runtime·printf("rdx     %X\n", r->rdx);
-	runtime·printf("rdi     %X\n", r->rdi);
-	runtime·printf("rsi     %X\n", r->rsi);
-	runtime·printf("rbp     %X\n", r->rbp);
-	runtime·printf("rsp     %X\n", r->rsp);
-	runtime·printf("r8      %X\n", r->r8 );
-	runtime·printf("r9      %X\n", r->r9 );
-	runtime·printf("r10     %X\n", r->r10);
-	runtime·printf("r11     %X\n", r->r11);
-	runtime·printf("r12     %X\n", r->r12);
-	runtime·printf("r13     %X\n", r->r13);
-	runtime·printf("r14     %X\n", r->r14);
-	runtime·printf("r15     %X\n", r->r15);
-	runtime·printf("rip     %X\n", r->rip);
-	runtime·printf("rflags  %X\n", r->rflags);
-	runtime·printf("cs      %X\n", r->cs);
-	runtime·printf("fs      %X\n", r->fs);
-	runtime·printf("gs      %X\n", r->gs);
-}
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Ucontext *uc;
-	Mcontext *mc;
-	Regs *r;
-	uintptr *sp;
-	byte *pc;
-
-	uc = context;
-	mc = uc->uc_mcontext;
-	r = &mc->ss;
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Work around Leopard bug that doesn't set FPE_INTDIV.
-		// Look at instruction to see if it is a divide.
-		// Not necessary in Snow Leopard (si_code will be != 0).
-		if(sig == SIGFPE && info->si_code == 0) {
-			pc = (byte*)r->rip;
-			if((pc[0]&0xF0) == 0x40)	// 64-bit REX prefix
-				pc++;
-			else if(pc[0] == 0x66)	// 16-bit instruction prefix
-				pc++;
-			if(pc[0] == 0xF6 || pc[0] == 0xF7)
-				info->si_code = FPE_INTDIV;
-		}
-		
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = (uintptr)info->si_addr;
-		gp->sigpc = r->rip;
-		
-		// Only push runtime·sigpanic if r->rip != 0.
-		// If r->rip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->rip != 0) {
-			sp = (uintptr*)r->rsp;
-			*--sp = r->rip;
-			r->rsp = (uintptr)sp;
-		}
-		r->rip = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG){
-		runtime·printf("Signal %d\n", sig);
-	}else{
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-	}
-
-	runtime·printf("pc: %X\n", r->rip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-}
-
-void
-runtime·sigignore(int32, Siginfo*, void*)
-{
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	StackT st;
-
-	st.ss_sp = p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	sa.sa_tramp = (uintptr)runtime·sigtramp;	// runtime·sigtramp's job is to call into real handler
-	sa.__sigaction_u.__sa_sigaction = (uintptr)fn;
-	runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
diff --git a/src/pkg/runtime/darwin/amd64/sys.s b/src/pkg/runtime/darwin/amd64/sys.s
deleted file mode 100644
index 8d1b20f..0000000
--- a/src/pkg/runtime/darwin/amd64/sys.s
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//
-// System calls and other sys.stuff for AMD64, Darwin
-// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
-// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
-//
-// The low 24 bits are the system call number.
-// The high 8 bits specify the kind of system call: 1=Mach, 2=BSD, 3=Machine-Dependent.
-//
-
-#include "amd64/asm.h"
-
-// Exit the entire program (like C exit)
-TEXT runtime·exit(SB),7,$0
-	MOVL	8(SP), DI		// arg 1 exit status
-	MOVL	$(0x2000000+1), AX	// syscall entry
-	SYSCALL
-	CALL	runtime·notok(SB)
-	RET
-
-// Exit this OS thread (like pthread_exit, which eventually
-// calls __bsdthread_terminate).
-TEXT runtime·exit1(SB),7,$0
-	MOVL	8(SP), DI		// arg 1 exit status
-	MOVL	$(0x2000000+361), AX	// syscall entry
-	SYSCALL
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·write(SB),7,$0
-	MOVL	8(SP), DI		// arg 1 fd
-	MOVQ	16(SP), SI		// arg 2 buf
-	MOVL	24(SP), DX		// arg 3 count
-	MOVL	$(0x2000000+4), AX	// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·raisesigpipe(SB),7,$24
-	get_tls(CX)
-	MOVQ	m(CX), DX
-	MOVL	$13, DI	// arg 1 SIGPIPE
-	MOVQ	m_procid(DX), SI	// arg 2 thread_port
-	MOVL	$(0x2000000+328), AX	// syscall entry __pthread_kill
-	SYSCALL
-	RET
-
-TEXT runtime·setitimer(SB), 7, $0
-	MOVL	8(SP), DI
-	MOVQ	16(SP), SI
-	MOVQ	24(SP), DX
-	MOVL	$(0x2000000+83), AX	// syscall entry
-	SYSCALL
-	RET
-
-// void gettime(int64 *sec, int32 *usec)
-TEXT runtime·gettime(SB), 7, $32
-	MOVQ	SP, DI	// must be non-nil, unused
-	MOVQ	$0, SI
-	MOVL	$(0x2000000+116), AX
-	SYSCALL
-	MOVQ	sec+0(FP), DI
-	MOVQ	AX, (DI)
-	MOVQ	usec+8(FP), DI
-	MOVL	DX, (DI)
-	RET
-
-TEXT runtime·sigaction(SB),7,$0
-	MOVL	8(SP), DI		// arg 1 sig
-	MOVQ	16(SP), SI		// arg 2 act
-	MOVQ	24(SP), DX		// arg 3 oact
-	MOVQ	24(SP), CX		// arg 3 oact
-	MOVQ	24(SP), R10		// arg 3 oact
-	MOVL	$(0x2000000+46), AX	// syscall entry
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·sigtramp(SB),7,$64
-	get_tls(BX)
-	
-	// save g
-	MOVQ	g(BX), R10
-	MOVQ	R10, 48(SP)
-	
-	// g = m->gsignal
-	MOVQ	m(BX), BP
-	MOVQ	m_gsignal(BP), BP
-	MOVQ	BP, g(BX)
-
-	MOVL	DX, 0(SP)
-	MOVQ	CX, 8(SP)
-	MOVQ	R8, 16(SP)
-	MOVQ	R10, 24(SP)
-
-	MOVQ	R8, 32(SP)	// save ucontext
-	MOVQ	SI, 40(SP)	// save infostyle
-	CALL	DI
-
-	// restore g
-	get_tls(BX)
-	MOVQ	48(SP), R10
-	MOVQ	R10, g(BX)
-
-	// call sigreturn
-	MOVL	$(0x2000000+184), AX	// sigreturn(ucontext, infostyle)
-	MOVQ	32(SP), DI	// saved ucontext
-	MOVQ	40(SP), SI	// saved infostyle
-	SYSCALL
-	INT $3	// not reached
-
-TEXT runtime·mmap(SB),7,$0
-	MOVQ	8(SP), DI		// arg 1 addr
-	MOVQ	16(SP), SI		// arg 2 len
-	MOVL	24(SP), DX		// arg 3 prot
-	MOVL	28(SP), R10		// arg 4 flags
-	MOVL	32(SP), R8		// arg 5 fid
-	MOVL	36(SP), R9		// arg 6 offset
-	MOVL	$(0x2000000+197), AX	// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·munmap(SB),7,$0
-	MOVQ	8(SP), DI		// arg 1 addr
-	MOVQ	16(SP), SI		// arg 2 len
-	MOVL	$(0x2000000+73), AX	// syscall entry
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·notok(SB),7,$0
-	MOVL	$0xf1, BP
-	MOVQ	BP, (BP)
-	RET
-
-TEXT runtime·sigaltstack(SB),7,$0
-	MOVQ	new+8(SP), DI
-	MOVQ	old+16(SP), SI
-	MOVQ	$(0x2000000+53), AX
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
-TEXT runtime·bsdthread_create(SB),7,$0
-	// Set up arguments to bsdthread_create system call.
-	// The ones in quotes pass through to the thread callback
-	// uninterpreted, so we can put whatever we want there.
-	MOVQ	fn+32(SP), DI	// "func"
-	MOVQ	mm+16(SP), SI	// "arg"
-	MOVQ	stk+8(SP), DX	// stack
-	MOVQ	gg+24(SP), R10	// "pthread"
-	MOVQ	$0x01000000, R8	// flags = PTHREAD_START_CUSTOM
-	MOVQ	$0, R9	// paranoia
-	MOVQ	$(0x2000000+360), AX	// bsdthread_create
-	SYSCALL
-	JCC 3(PC)
-	NEGL	AX
-	RET
-	MOVL	$0, AX
-	RET
-
-// The thread that bsdthread_create creates starts executing here,
-// because we registered this function using bsdthread_register
-// at startup.
-//	DI = "pthread"
-//	SI = mach thread port
-//	DX = "func" (= fn)
-//	CX = "arg" (= m)
-//	R8 = stack
-//	R9 = flags (= 0)
-//	SP = stack - C_64_REDZONE_LEN (= stack - 128)
-TEXT runtime·bsdthread_start(SB),7,$0
-	MOVQ	R8, SP		// empirically, SP is very wrong but R8 is right
-
-	PUSHQ	DX
-	PUSHQ	CX
-	PUSHQ	SI
-
-	// set up thread local storage pointing at m->tls.
-	LEAQ	m_tls(CX), DI
-	CALL	runtime·settls(SB)
-
-	POPQ	SI
-	POPQ	CX
-	POPQ	DX
-	
-	get_tls(BX)
-	MOVQ	CX, m(BX)
-	MOVQ	SI, m_procid(CX)	// thread port is m->procid
-	MOVQ	m_g0(CX), AX
-	MOVQ	AX, g(BX)
-	CALL	runtime·stackcheck(SB)	// smashes AX, CX
-	CALL	DX	// fn
-	CALL	runtime·exit1(SB)
-	RET
-
-// void bsdthread_register(void)
-// registers callbacks for threadstart (see bsdthread_create above
-// and wqthread and pthsize (not used).  returns 0 on success.
-TEXT runtime·bsdthread_register(SB),7,$0
-	MOVQ	$runtime·bsdthread_start(SB), DI	// threadstart
-	MOVQ	$0, SI	// wqthread, not used by us
-	MOVQ	$0, DX	// pthsize, not used by us
-	MOVQ	$0, R10	// dummy_value [sic]
-	MOVQ	$0, R8	// targetconc_ptr
-	MOVQ	$0, R9	// dispatchqueue_offset
-	MOVQ	$(0x2000000+366), AX	// bsdthread_register
-	SYSCALL
-	JCC 2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-// Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
-
-// uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
-TEXT runtime·mach_msg_trap(SB),7,$0
-	MOVQ	8(SP), DI
-	MOVL	16(SP), SI
-	MOVL	20(SP), DX
-	MOVL	24(SP), R10
-	MOVL	28(SP), R8
-	MOVL	32(SP), R9
-	MOVL	36(SP), R11
-	PUSHQ	R11	// seventh arg, on stack
-	MOVL	$(0x1000000+31), AX	// mach_msg_trap
-	SYSCALL
-	POPQ	R11
-	RET
-
-TEXT runtime·mach_task_self(SB),7,$0
-	MOVL	$(0x1000000+28), AX	// task_self_trap
-	SYSCALL
-	RET
-
-TEXT runtime·mach_thread_self(SB),7,$0
-	MOVL	$(0x1000000+27), AX	// thread_self_trap
-	SYSCALL
-	RET
-
-TEXT runtime·mach_reply_port(SB),7,$0
-	MOVL	$(0x1000000+26), AX	// mach_reply_port
-	SYSCALL
-	RET
-
-// Mach provides trap versions of the semaphore ops,
-// instead of requiring the use of RPC.
-
-// uint32 mach_semaphore_wait(uint32)
-TEXT runtime·mach_semaphore_wait(SB),7,$0
-	MOVL	8(SP), DI
-	MOVL	$(0x1000000+36), AX	// semaphore_wait_trap
-	SYSCALL
-	RET
-
-// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
-TEXT runtime·mach_semaphore_timedwait(SB),7,$0
-	MOVL	8(SP), DI
-	MOVL	12(SP), SI
-	MOVL	16(SP), DX
-	MOVL	$(0x1000000+38), AX	// semaphore_timedwait_trap
-	SYSCALL
-	RET
-
-// uint32 mach_semaphore_signal(uint32)
-TEXT runtime·mach_semaphore_signal(SB),7,$0
-	MOVL	8(SP), DI
-	MOVL	$(0x1000000+33), AX	// semaphore_signal_trap
-	SYSCALL
-	RET
-
-// uint32 mach_semaphore_signal_all(uint32)
-TEXT runtime·mach_semaphore_signal_all(SB),7,$0
-	MOVL	8(SP), DI
-	MOVL	$(0x1000000+34), AX	// semaphore_signal_all_trap
-	SYSCALL
-	RET
-
-// set tls base to DI
-TEXT runtime·settls(SB),7,$32
-	/*
-	* Same as in ../386/sys.s:/ugliness, different constant.
-	* See ../../../../libcgo/darwin_amd64.c for the derivation
-	* of the constant.
-	*/
-	SUBQ $0x8a0, DI
-
-	MOVL	$(0x3000000+3), AX	// thread_fast_set_cthread_self - machdep call #3
-	SYSCALL
-	RET
diff --git a/src/pkg/runtime/darwin/defs.c b/src/pkg/runtime/darwin/defs.c
deleted file mode 100644
index 032a6bc..0000000
--- a/src/pkg/runtime/darwin/defs.c
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Input to godefs.
- *
-	godefs -f -m64 defs.c >amd64/defs.h
-	godefs -f -m32 defs.c >386/defs.h
- */
-
-#define __DARWIN_UNIX03 0
-
-#include <mach/mach.h>
-#include <mach/message.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <sys/mman.h>
-
-enum {
-	$PROT_NONE = PROT_NONE,
-	$PROT_READ = PROT_READ,
-	$PROT_WRITE = PROT_WRITE,
-	$PROT_EXEC = PROT_EXEC,
-
-	$MAP_ANON = MAP_ANON,
-	$MAP_PRIVATE = MAP_PRIVATE,
-	$MAP_FIXED = MAP_FIXED,
-
-	$MACH_MSG_TYPE_MOVE_RECEIVE = MACH_MSG_TYPE_MOVE_RECEIVE,
-	$MACH_MSG_TYPE_MOVE_SEND = MACH_MSG_TYPE_MOVE_SEND,
-	$MACH_MSG_TYPE_MOVE_SEND_ONCE = MACH_MSG_TYPE_MOVE_SEND_ONCE,
-	$MACH_MSG_TYPE_COPY_SEND = MACH_MSG_TYPE_COPY_SEND,
-	$MACH_MSG_TYPE_MAKE_SEND = MACH_MSG_TYPE_MAKE_SEND,
-	$MACH_MSG_TYPE_MAKE_SEND_ONCE = MACH_MSG_TYPE_MAKE_SEND_ONCE,
-	$MACH_MSG_TYPE_COPY_RECEIVE = MACH_MSG_TYPE_COPY_RECEIVE,
-
-	$MACH_MSG_PORT_DESCRIPTOR = MACH_MSG_PORT_DESCRIPTOR,
-	$MACH_MSG_OOL_DESCRIPTOR = MACH_MSG_OOL_DESCRIPTOR,
-	$MACH_MSG_OOL_PORTS_DESCRIPTOR = MACH_MSG_OOL_PORTS_DESCRIPTOR,
-	$MACH_MSG_OOL_VOLATILE_DESCRIPTOR = MACH_MSG_OOL_VOLATILE_DESCRIPTOR,
-
-	$MACH_MSGH_BITS_COMPLEX = MACH_MSGH_BITS_COMPLEX,
-
-	$MACH_SEND_MSG = MACH_SEND_MSG,
-	$MACH_RCV_MSG = MACH_RCV_MSG,
-	$MACH_RCV_LARGE = MACH_RCV_LARGE,
-
-	$MACH_SEND_TIMEOUT = MACH_SEND_TIMEOUT,
-	$MACH_SEND_INTERRUPT = MACH_SEND_INTERRUPT,
-	$MACH_SEND_CANCEL = MACH_SEND_CANCEL,
-	$MACH_SEND_ALWAYS = MACH_SEND_ALWAYS,
-	$MACH_SEND_TRAILER = MACH_SEND_TRAILER,
-	$MACH_RCV_TIMEOUT = MACH_RCV_TIMEOUT,
-	$MACH_RCV_NOTIFY = MACH_RCV_NOTIFY,
-	$MACH_RCV_INTERRUPT = MACH_RCV_INTERRUPT,
-	$MACH_RCV_OVERWRITE = MACH_RCV_OVERWRITE,
-
-	$NDR_PROTOCOL_2_0 = NDR_PROTOCOL_2_0,
-	$NDR_INT_BIG_ENDIAN = NDR_INT_BIG_ENDIAN,
-	$NDR_INT_LITTLE_ENDIAN = NDR_INT_LITTLE_ENDIAN,
-	$NDR_FLOAT_IEEE = NDR_FLOAT_IEEE,
-	$NDR_CHAR_ASCII = NDR_CHAR_ASCII,
-
-	$SA_SIGINFO = SA_SIGINFO,
-	$SA_RESTART = SA_RESTART,
-	$SA_ONSTACK = SA_ONSTACK,
-	$SA_USERTRAMP = SA_USERTRAMP,
-	$SA_64REGSET = SA_64REGSET,
-	
-	$SIGHUP = SIGHUP,
-	$SIGINT = SIGINT,
-	$SIGQUIT = SIGQUIT,
-	$SIGILL = SIGILL,
-	$SIGTRAP = SIGTRAP,
-	$SIGABRT = SIGABRT,
-	$SIGEMT = SIGEMT,
-	$SIGFPE = SIGFPE,
-	$SIGKILL = SIGKILL,
-	$SIGBUS = SIGBUS,
-	$SIGSEGV = SIGSEGV,
-	$SIGSYS = SIGSYS,
-	$SIGPIPE = SIGPIPE,
-	$SIGALRM = SIGALRM,
-	$SIGTERM = SIGTERM,
-	$SIGURG = SIGURG,
-	$SIGSTOP = SIGSTOP,
-	$SIGTSTP = SIGTSTP,
-	$SIGCONT = SIGCONT,
-	$SIGCHLD = SIGCHLD,
-	$SIGTTIN = SIGTTIN,
-	$SIGTTOU = SIGTTOU,
-	$SIGIO = SIGIO,
-	$SIGXCPU = SIGXCPU,
-	$SIGXFSZ = SIGXFSZ,
-	$SIGVTALRM = SIGVTALRM,
-	$SIGPROF = SIGPROF,
-	$SIGWINCH = SIGWINCH,
-	$SIGINFO = SIGINFO,
-	$SIGUSR1 = SIGUSR1,
-	$SIGUSR2 = SIGUSR2,
-	
-	$FPE_INTDIV = FPE_INTDIV,
-	$FPE_INTOVF = FPE_INTOVF,
-	$FPE_FLTDIV = FPE_FLTDIV,
-	$FPE_FLTOVF = FPE_FLTOVF,
-	$FPE_FLTUND = FPE_FLTUND,
-	$FPE_FLTRES = FPE_FLTRES,
-	$FPE_FLTINV = FPE_FLTINV,
-	$FPE_FLTSUB = FPE_FLTSUB,
-	
-	$BUS_ADRALN = BUS_ADRALN,
-	$BUS_ADRERR = BUS_ADRERR,
-	$BUS_OBJERR = BUS_OBJERR,
-	
-	$SEGV_MAPERR = SEGV_MAPERR,
-	$SEGV_ACCERR = SEGV_ACCERR,
-	
-	$ITIMER_REAL = ITIMER_REAL,
-	$ITIMER_VIRTUAL = ITIMER_VIRTUAL,
-	$ITIMER_PROF = ITIMER_PROF,
-};
-
-typedef mach_msg_body_t	$MachBody;
-typedef mach_msg_header_t	$MachHeader;
-typedef NDR_record_t		$MachNDR;
-typedef mach_msg_port_descriptor_t	$MachPort;
-
-typedef stack_t	$StackT;
-typedef union __sigaction_u	$Sighandler;
-
-typedef struct __sigaction	$Sigaction;	// used in syscalls
-// typedef struct sigaction	$Sigaction;	// used by the C library
-typedef union sigval $Sigval;
-typedef siginfo_t $Siginfo;
-typedef struct timeval	$Timeval;
-typedef struct itimerval	$Itimerval;
-
-typedef struct fp_control $FPControl;
-typedef struct fp_status $FPStatus;
-typedef struct mmst_reg $RegMMST;
-typedef struct xmm_reg $RegXMM;
-
-#ifdef __LP64__
-// amd64
-typedef x86_thread_state64_t	$Regs;
-typedef x86_float_state64_t $FloatState;
-typedef x86_exception_state64_t $ExceptionState;
-typedef struct mcontext64 $Mcontext;
-#else
-// 386
-typedef x86_thread_state32_t	$Regs;
-typedef x86_float_state32_t $FloatState;
-typedef x86_exception_state32_t $ExceptionState;
-typedef struct mcontext32 $Mcontext;
-#endif
-
-typedef ucontext_t	$Ucontext;
diff --git a/src/pkg/runtime/darwin/mem.c b/src/pkg/runtime/darwin/mem.c
deleted file mode 100644
index 935c032..0000000
--- a/src/pkg/runtime/darwin/mem.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "malloc.h"
-
-void*
-runtime·SysAlloc(uintptr n)
-{
-	void *v;
-
-	mstats.sys += n;
-	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
-	if(v < (void*)4096)
-		return nil;
-	return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-	USED(v);
-	USED(n);
-	// TODO(rsc): call madvise MADV_DONTNEED
-}
-
-void
-runtime·SysFree(void *v, uintptr n)
-{
-	mstats.sys -= n;
-	runtime·munmap(v, n);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n)
-{
-	return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-}
-
-enum
-{
-	ENOMEM = 12,
-};
-
-void
-runtime·SysMap(void *v, uintptr n)
-{
-	void *p;
-	
-	mstats.sys += n;
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
-	if(p == (void*)-ENOMEM)
-		runtime·throw("runtime: out of memory");
-	if(p != v)
-		runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/pkg/runtime/darwin/os.h b/src/pkg/runtime/darwin/os.h
deleted file mode 100644
index db3c2e8..0000000
--- a/src/pkg/runtime/darwin/os.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_DFL ((void*)0)
-#define SIG_IGN ((void*)1)
-
-int32	runtime·bsdthread_create(void*, M*, G*, void(*)(void));
-void	runtime·bsdthread_register(void);
-int32	runtime·mach_msg_trap(MachHeader*, int32, uint32, uint32, uint32, uint32, uint32);
-uint32	runtime·mach_reply_port(void);
-void	runtime·mach_semacquire(uint32);
-uint32	runtime·mach_semcreate(void);
-void	runtime·mach_semdestroy(uint32);
-void	runtime·mach_semrelease(uint32);
-void	runtime·mach_semreset(uint32);
-uint32	runtime·mach_task_self(void);
-uint32	runtime·mach_task_self(void);
-uint32	runtime·mach_thread_self(void);
-uint32	runtime·mach_thread_self(void);
-
-struct Sigaction;
-void	runtime·sigaction(uintptr, struct Sigaction*, struct Sigaction*);
-
-struct StackT;
-void	runtime·sigaltstack(struct StackT*, struct StackT*);
-void	runtime·sigtramp(void);
-void	runtime·sigpanic(void);
-void	runtime·setitimer(int32, Itimerval*, Itimerval*);
-
-void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/darwin/thread.c b/src/pkg/runtime/darwin/thread.c
deleted file mode 100644
index 6733e81..0000000
--- a/src/pkg/runtime/darwin/thread.c
+++ /dev/null
@@ -1,484 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "stack.h"
-
-extern SigTab runtime·sigtab[];
-
-static void
-unimplemented(int8 *name)
-{
-	runtime·prints(name);
-	runtime·prints(" not implemented\n");
-	*(int32*)1231 = 1231;
-}
-
-// Thread-safe allocation of a semaphore.
-// Psema points at a kernel semaphore key.
-// It starts out zero, meaning no semaphore.
-// Fill it in, being careful of others calling initsema
-// simultaneously.
-static void
-initsema(uint32 *psema)
-{
-	uint32 sema;
-
-	if(*psema != 0)	// already have one
-		return;
-
-	sema = runtime·mach_semcreate();
-	if(!runtime·cas(psema, 0, sema)){
-		// Someone else filled it in.  Use theirs.
-		runtime·mach_semdestroy(sema);
-		return;
-	}
-}
-
-
-// Blocking locks.
-
-// Implement Locks, using semaphores.
-// l->key is the number of threads who want the lock.
-// In a race, one thread increments l->key from 0 to 1
-// and the others increment it from >0 to >1.  The thread
-// who does the 0->1 increment gets the lock, and the
-// others wait on the semaphore.  When the 0->1 thread
-// releases the lock by decrementing l->key, l->key will
-// be >0, so it will increment the semaphore to wake up
-// one of the others.  This is the same algorithm used
-// in Plan 9's user-level locks.
-
-void
-runtime·lock(Lock *l)
-{
-	if(m->locks < 0)
-		runtime·throw("lock count");
-	m->locks++;
-
-	if(runtime·xadd(&l->key, 1) > 1) {	// someone else has it; wait
-		// Allocate semaphore if needed.
-		if(l->sema == 0)
-			initsema(&l->sema);
-		runtime·mach_semacquire(l->sema);
-	}
-}
-
-void
-runtime·unlock(Lock *l)
-{
-	m->locks--;
-	if(m->locks < 0)
-		runtime·throw("lock count");
-
-	if(runtime·xadd(&l->key, -1) > 0) {	// someone else is waiting
-		// Allocate semaphore if needed.
-		if(l->sema == 0)
-			initsema(&l->sema);
-		runtime·mach_semrelease(l->sema);
-	}
-}
-
-static void
-destroylock(Lock *l)
-{
-	if(l->sema != 0) {
-		runtime·mach_semdestroy(l->sema);
-		l->sema = 0;
-	}
-}
-
-// User-level semaphore implementation:
-// try to do the operations in user space on u,
-// but when it's time to block, fall back on the kernel semaphore k.
-// This is the same algorithm used in Plan 9.
-void
-runtime·usemacquire(Usema *s)
-{
-	if((int32)runtime·xadd(&s->u, -1) < 0) {
-		if(s->k == 0)
-			initsema(&s->k);
-		runtime·mach_semacquire(s->k);
-	}
-}
-
-void
-runtime·usemrelease(Usema *s)
-{
-	if((int32)runtime·xadd(&s->u, 1) <= 0) {
-		if(s->k == 0)
-			initsema(&s->k);
-		runtime·mach_semrelease(s->k);
-	}
-}
-
-
-// Event notifications.
-void
-runtime·noteclear(Note *n)
-{
-	n->wakeup = 0;
-}
-
-void
-runtime·notesleep(Note *n)
-{
-	while(!n->wakeup)
-		runtime·usemacquire(&n->sema);
-}
-
-void
-runtime·notewakeup(Note *n)
-{
-	n->wakeup = 1;
-	runtime·usemrelease(&n->sema);
-}
-
-
-// BSD interface for threading.
-void
-runtime·osinit(void)
-{
-	// Register our thread-creation callback (see {amd64,386}/sys.s)
-	// but only if we're not using cgo.  If we are using cgo we need
-	// to let the C pthread libary install its own thread-creation callback.
-	if(!runtime·iscgo)
-		runtime·bsdthread_register();
-	runtime·destroylock = destroylock;
-}
-
-void
-runtime·goenvs(void)
-{
-	runtime·goenvs_unix();
-}
-
-void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
-{
-	int32 errno;
-
-	m->tls[0] = m->id;	// so 386 asm can find it
-	if(0){
-		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, m->id, m->tls[0], &m);
-	}
-	if((errno = runtime·bsdthread_create(stk, m, g, fn)) < 0) {
-		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -errno);
-		runtime·throw("runtime.newosproc");
-	}
-}
-
-// Called to initialize a new m (including the bootstrap m).
-void
-runtime·minit(void)
-{
-	// Initialize signal handling.
-	m->gsignal = runtime·malg(32*1024);	// OS X wants >=8K, Linux >=2K
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
-}
-
-// Mach IPC, to get at semaphores
-// Definitions are in /usr/include/mach on a Mac.
-
-static void
-macherror(int32 r, int8 *fn)
-{
-	runtime·printf("mach error %s: %d\n", fn, r);
-	runtime·throw("mach error");
-}
-
-enum
-{
-	DebugMach = 0
-};
-
-static MachNDR zerondr;
-
-#define MACH_MSGH_BITS(a, b) ((a) | ((b)<<8))
-
-static int32
-mach_msg(MachHeader *h,
-	int32 op,
-	uint32 send_size,
-	uint32 rcv_size,
-	uint32 rcv_name,
-	uint32 timeout,
-	uint32 notify)
-{
-	// TODO: Loop on interrupt.
-	return runtime·mach_msg_trap(h, op, send_size, rcv_size, rcv_name, timeout, notify);
-}
-
-// Mach RPC (MIG)
-
-enum
-{
-	MinMachMsg = 48,
-	Reply = 100,
-};
-
-#pragma pack on
-typedef struct CodeMsg CodeMsg;
-struct CodeMsg
-{
-	MachHeader h;
-	MachNDR NDR;
-	int32 code;
-};
-#pragma pack off
-
-static int32
-machcall(MachHeader *h, int32 maxsize, int32 rxsize)
-{
-	uint32 *p;
-	int32 i, ret, id;
-	uint32 port;
-	CodeMsg *c;
-
-	if((port = m->machport) == 0){
-		port = runtime·mach_reply_port();
-		m->machport = port;
-	}
-
-	h->msgh_bits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
-	h->msgh_local_port = port;
-	h->msgh_reserved = 0;
-	id = h->msgh_id;
-
-	if(DebugMach){
-		p = (uint32*)h;
-		runtime·prints("send:\t");
-		for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
-			runtime·prints(" ");
-			runtime·printpointer((void*)p[i]);
-			if(i%8 == 7)
-				runtime·prints("\n\t");
-		}
-		if(i%8)
-			runtime·prints("\n");
-	}
-
-	ret = mach_msg(h, MACH_SEND_MSG|MACH_RCV_MSG,
-		h->msgh_size, maxsize, port, 0, 0);
-	if(ret != 0){
-		if(DebugMach){
-			runtime·prints("mach_msg error ");
-			runtime·printint(ret);
-			runtime·prints("\n");
-		}
-		return ret;
-	}
-
-	if(DebugMach){
-		p = (uint32*)h;
-		runtime·prints("recv:\t");
-		for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
-			runtime·prints(" ");
-			runtime·printpointer((void*)p[i]);
-			if(i%8 == 7)
-				runtime·prints("\n\t");
-		}
-		if(i%8)
-			runtime·prints("\n");
-	}
-
-	if(h->msgh_id != id+Reply){
-		if(DebugMach){
-			runtime·prints("mach_msg reply id mismatch ");
-			runtime·printint(h->msgh_id);
-			runtime·prints(" != ");
-			runtime·printint(id+Reply);
-			runtime·prints("\n");
-		}
-		return -303;	// MIG_REPLY_MISMATCH
-	}
-
-	// Look for a response giving the return value.
-	// Any call can send this back with an error,
-	// and some calls only have return values so they
-	// send it back on success too.  I don't quite see how
-	// you know it's one of these and not the full response
-	// format, so just look if the message is right.
-	c = (CodeMsg*)h;
-	if(h->msgh_size == sizeof(CodeMsg)
-	&& !(h->msgh_bits & MACH_MSGH_BITS_COMPLEX)){
-		if(DebugMach){
-			runtime·prints("mig result ");
-			runtime·printint(c->code);
-			runtime·prints("\n");
-		}
-		return c->code;
-	}
-
-	if(h->msgh_size != rxsize){
-		if(DebugMach){
-			runtime·prints("mach_msg reply size mismatch ");
-			runtime·printint(h->msgh_size);
-			runtime·prints(" != ");
-			runtime·printint(rxsize);
-			runtime·prints("\n");
-		}
-		return -307;	// MIG_ARRAY_TOO_LARGE
-	}
-
-	return 0;
-}
-
-
-// Semaphores!
-
-enum
-{
-	Tmach_semcreate = 3418,
-	Rmach_semcreate = Tmach_semcreate + Reply,
-
-	Tmach_semdestroy = 3419,
-	Rmach_semdestroy = Tmach_semdestroy + Reply,
-
-	// Mach calls that get interrupted by Unix signals
-	// return this error code.  We retry them.
-	KERN_ABORTED = 14,
-};
-
-typedef struct Tmach_semcreateMsg Tmach_semcreateMsg;
-typedef struct Rmach_semcreateMsg Rmach_semcreateMsg;
-typedef struct Tmach_semdestroyMsg Tmach_semdestroyMsg;
-// Rmach_semdestroyMsg = CodeMsg
-
-#pragma pack on
-struct Tmach_semcreateMsg
-{
-	MachHeader h;
-	MachNDR ndr;
-	int32 policy;
-	int32 value;
-};
-
-struct Rmach_semcreateMsg
-{
-	MachHeader h;
-	MachBody body;
-	MachPort semaphore;
-};
-
-struct Tmach_semdestroyMsg
-{
-	MachHeader h;
-	MachBody body;
-	MachPort semaphore;
-};
-#pragma pack off
-
-uint32
-runtime·mach_semcreate(void)
-{
-	union {
-		Tmach_semcreateMsg tx;
-		Rmach_semcreateMsg rx;
-		uint8 pad[MinMachMsg];
-	} m;
-	int32 r;
-
-	m.tx.h.msgh_bits = 0;
-	m.tx.h.msgh_size = sizeof(m.tx);
-	m.tx.h.msgh_remote_port = runtime·mach_task_self();
-	m.tx.h.msgh_id = Tmach_semcreate;
-	m.tx.ndr = zerondr;
-
-	m.tx.policy = 0;	// 0 = SYNC_POLICY_FIFO
-	m.tx.value = 0;
-
-	while((r = machcall(&m.tx.h, sizeof m, sizeof(m.rx))) != 0){
-		if(r == KERN_ABORTED)	// interrupted
-			continue;
-		macherror(r, "semaphore_create");
-	}
-	if(m.rx.body.msgh_descriptor_count != 1)
-		unimplemented("mach_semcreate desc count");
-	return m.rx.semaphore.name;
-}
-
-void
-runtime·mach_semdestroy(uint32 sem)
-{
-	union {
-		Tmach_semdestroyMsg tx;
-		uint8 pad[MinMachMsg];
-	} m;
-	int32 r;
-
-	m.tx.h.msgh_bits = MACH_MSGH_BITS_COMPLEX;
-	m.tx.h.msgh_size = sizeof(m.tx);
-	m.tx.h.msgh_remote_port = runtime·mach_task_self();
-	m.tx.h.msgh_id = Tmach_semdestroy;
-	m.tx.body.msgh_descriptor_count = 1;
-	m.tx.semaphore.name = sem;
-	m.tx.semaphore.disposition = MACH_MSG_TYPE_MOVE_SEND;
-	m.tx.semaphore.type = 0;
-
-	while((r = machcall(&m.tx.h, sizeof m, 0)) != 0){
-		if(r == KERN_ABORTED)	// interrupted
-			continue;
-		macherror(r, "semaphore_destroy");
-	}
-}
-
-// The other calls have simple system call traps in sys.s
-int32 runtime·mach_semaphore_wait(uint32 sema);
-int32 runtime·mach_semaphore_timedwait(uint32 sema, uint32 sec, uint32 nsec);
-int32 runtime·mach_semaphore_signal(uint32 sema);
-int32 runtime·mach_semaphore_signal_all(uint32 sema);
-
-void
-runtime·mach_semacquire(uint32 sem)
-{
-	int32 r;
-
-	while((r = runtime·mach_semaphore_wait(sem)) != 0) {
-		if(r == KERN_ABORTED)	// interrupted
-			continue;
-		macherror(r, "semaphore_wait");
-	}
-}
-
-void
-runtime·mach_semrelease(uint32 sem)
-{
-	int32 r;
-
-	while((r = runtime·mach_semaphore_signal(sem)) != 0) {
-		if(r == KERN_ABORTED)	// interrupted
-			continue;
-		macherror(r, "semaphore_signal");
-	}
-}
-
-void
-runtime·sigpanic(void)
-{
-	switch(g->sig) {
-	case SIGBUS:
-		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case SIGSEGV:
-		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case SIGFPE:
-		switch(g->sigcode0) {
-		case FPE_INTDIV:
-			runtime·panicstring("integer divide by zero");
-		case FPE_INTOVF:
-			runtime·panicstring("integer overflow");
-		}
-		runtime·panicstring("floating point error");
-	}
-	runtime·panicstring(runtime·sigtab[g->sig].name);
-}
diff --git a/src/pkg/runtime/debug.go b/src/pkg/runtime/debug.go
index 6370a57..4f09146 100644
--- a/src/pkg/runtime/debug.go
+++ b/src/pkg/runtime/debug.go
@@ -10,7 +10,6 @@ func Breakpoint()
 // LockOSThread wires the calling goroutine to its current operating system thread.
 // Until the calling goroutine exits or calls UnlockOSThread, it will always
 // execute in that thread, and no other goroutine can.
-// LockOSThread cannot be used during init functions.
 func LockOSThread()
 
 // UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
@@ -20,9 +19,13 @@ func UnlockOSThread()
 // GOMAXPROCS sets the maximum number of CPUs that can be executing
 // simultaneously and returns the previous setting.  If n < 1, it does not
 // change the current setting.
+// The number of logical CPUs on the local machine can be queried with NumCPU.
 // This call will go away when the scheduler improves.
 func GOMAXPROCS(n int) int
 
+// NumCPU returns the number of logical CPUs on the local machine.
+func NumCPU() int
+
 // Cgocalls returns the number of cgo calls made by the current process.
 func Cgocalls() int64
 
diff --git a/src/pkg/runtime/defs1_linux.go b/src/pkg/runtime/defs1_linux.go
new file mode 100644
index 0000000..451817a
--- /dev/null
+++ b/src/pkg/runtime/defs1_linux.go
@@ -0,0 +1,37 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo -cdefs
+
+GOARCH=amd64 cgo -cdefs defs.go defs1.go >amd64/defs.h
+*/
+
+package runtime
+
+/*
+#include <ucontext.h>
+#include <fcntl.h>
+*/
+import "C"
+
+const (
+	O_RDONLY  = C.O_RDONLY
+	O_CLOEXEC = C.O_CLOEXEC
+)
+
+type Usigset C.__sigset_t
+type Fpxreg C.struct__libc_fpxreg
+type Xmmreg C.struct__libc_xmmreg
+type Fpstate C.struct__libc_fpstate
+type Fpxreg1 C.struct__fpxreg
+type Xmmreg1 C.struct__xmmreg
+type Fpstate1 C.struct__fpstate
+type Fpreg1 C.struct__fpreg
+type Sigaltstack C.struct_sigaltstack
+type Mcontext C.mcontext_t
+type Ucontext C.ucontext_t
+type Sigcontext C.struct_sigcontext
diff --git a/src/pkg/runtime/defs2_linux.go b/src/pkg/runtime/defs2_linux.go
new file mode 100644
index 0000000..9b07029
--- /dev/null
+++ b/src/pkg/runtime/defs2_linux.go
@@ -0,0 +1,126 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+ * Input to cgo -cdefs
+
+GOARCH=386 cgo -cdefs defs2.go >386/defs.h
+
+The asm header tricks we have to use for Linux on amd64
+(see defs.c and defs1.c) don't work here, so this is yet another
+file.  Sigh.
+*/
+
+package runtime
+
+/*
+#cgo CFLAGS: -I/home/rsc/pub/linux-2.6/arch/x86/include -I/home/rsc/pub/linux-2.6/include -D_LOOSE_KERNEL_NAMES -D__ARCH_SI_UID_T=__kernel_uid32_t
+
+#define size_t __kernel_size_t
+#include <asm/signal.h>
+#include <asm/mman.h>
+#include <asm/sigcontext.h>
+#include <asm/ucontext.h>
+#include <asm/siginfo.h>
+#include <asm-generic/fcntl.h>
+
+// This is the sigaction structure from the Linux 2.1.68 kernel which
+//   is used with the rt_sigaction system call.  For 386 this is not
+//   defined in any public header file.
+
+struct kernel_sigaction {
+	__sighandler_t k_sa_handler;
+	unsigned long sa_flags;
+	void (*sa_restorer) (void);
+	sigset_t sa_mask;
+};
+*/
+import "C"
+
+const (
+	PROT_NONE  = C.PROT_NONE
+	PROT_READ  = C.PROT_READ
+	PROT_WRITE = C.PROT_WRITE
+	PROT_EXEC  = C.PROT_EXEC
+
+	MAP_ANON    = C.MAP_ANONYMOUS
+	MAP_PRIVATE = C.MAP_PRIVATE
+	MAP_FIXED   = C.MAP_FIXED
+
+	MADV_DONTNEED = C.MADV_DONTNEED
+
+	SA_RESTART  = C.SA_RESTART
+	SA_ONSTACK  = C.SA_ONSTACK
+	SA_RESTORER = C.SA_RESTORER
+	SA_SIGINFO  = C.SA_SIGINFO
+
+	SIGHUP    = C.SIGHUP
+	SIGINT    = C.SIGINT
+	SIGQUIT   = C.SIGQUIT
+	SIGILL    = C.SIGILL
+	SIGTRAP   = C.SIGTRAP
+	SIGABRT   = C.SIGABRT
+	SIGBUS    = C.SIGBUS
+	SIGFPE    = C.SIGFPE
+	SIGKILL   = C.SIGKILL
+	SIGUSR1   = C.SIGUSR1
+	SIGSEGV   = C.SIGSEGV
+	SIGUSR2   = C.SIGUSR2
+	SIGPIPE   = C.SIGPIPE
+	SIGALRM   = C.SIGALRM
+	SIGSTKFLT = C.SIGSTKFLT
+	SIGCHLD   = C.SIGCHLD
+	SIGCONT   = C.SIGCONT
+	SIGSTOP   = C.SIGSTOP
+	SIGTSTP   = C.SIGTSTP
+	SIGTTIN   = C.SIGTTIN
+	SIGTTOU   = C.SIGTTOU
+	SIGURG    = C.SIGURG
+	SIGXCPU   = C.SIGXCPU
+	SIGXFSZ   = C.SIGXFSZ
+	SIGVTALRM = C.SIGVTALRM
+	SIGPROF   = C.SIGPROF
+	SIGWINCH  = C.SIGWINCH
+	SIGIO     = C.SIGIO
+	SIGPWR    = C.SIGPWR
+	SIGSYS    = C.SIGSYS
+
+	FPE_INTDIV = C.FPE_INTDIV
+	FPE_INTOVF = C.FPE_INTOVF
+	FPE_FLTDIV = C.FPE_FLTDIV
+	FPE_FLTOVF = C.FPE_FLTOVF
+	FPE_FLTUND = C.FPE_FLTUND
+	FPE_FLTRES = C.FPE_FLTRES
+	FPE_FLTINV = C.FPE_FLTINV
+	FPE_FLTSUB = C.FPE_FLTSUB
+
+	BUS_ADRALN = C.BUS_ADRALN
+	BUS_ADRERR = C.BUS_ADRERR
+	BUS_OBJERR = C.BUS_OBJERR
+
+	SEGV_MAPERR = C.SEGV_MAPERR
+	SEGV_ACCERR = C.SEGV_ACCERR
+
+	ITIMER_REAL    = C.ITIMER_REAL
+	ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+	ITIMER_PROF    = C.ITIMER_PROF
+
+	O_RDONLY  = C.O_RDONLY
+	O_CLOEXEC = C.O_CLOEXEC
+)
+
+type Fpreg C.struct__fpreg
+type Fpxreg C.struct__fpxreg
+type Xmmreg C.struct__xmmreg
+type Fpstate C.struct__fpstate
+type Timespec C.struct_timespec
+type Timeval C.struct_timeval
+type Sigaction C.struct_kernel_sigaction
+type Siginfo C.siginfo_t
+type Sigaltstack C.struct_sigaltstack
+type Sigcontext C.struct_sigcontext
+type Ucontext C.struct_ucontext
+type Itimerval C.struct_itimerval
diff --git a/src/pkg/runtime/defs_arm_linux.go b/src/pkg/runtime/defs_arm_linux.go
new file mode 100644
index 0000000..2063efb
--- /dev/null
+++ b/src/pkg/runtime/defs_arm_linux.go
@@ -0,0 +1,125 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo.
+On a Debian Lenny arm linux distribution:
+
+cgo -cdefs defs_arm.c >arm/defs.h
+*/
+
+package runtime
+
+/*
+#cgo CFLAGS: -I/usr/src/linux-headers-2.6.26-2-versatile/include
+
+#define __ARCH_SI_UID_T int
+#include <asm/signal.h>
+#include <asm/mman.h>
+#include <asm/sigcontext.h>
+#include <asm/ucontext.h>
+#include <asm/siginfo.h>
+#include <linux/time.h>
+
+struct xsiginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+	char _sifields[4];
+};
+
+#undef sa_handler
+#undef sa_flags
+#undef sa_restorer
+#undef sa_mask
+
+struct xsigaction {
+	void (*sa_handler)(void);
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	unsigned int sa_mask;		// mask last for extensibility
+};
+*/
+import "C"
+
+const (
+	PROT_NONE  = C.PROT_NONE
+	PROT_READ  = C.PROT_READ
+	PROT_WRITE = C.PROT_WRITE
+	PROT_EXEC  = C.PROT_EXEC
+
+	MAP_ANON    = C.MAP_ANONYMOUS
+	MAP_PRIVATE = C.MAP_PRIVATE
+	MAP_FIXED   = C.MAP_FIXED
+
+	MADV_DONTNEED = C.MADV_DONTNEED
+
+	SA_RESTART  = C.SA_RESTART
+	SA_ONSTACK  = C.SA_ONSTACK
+	SA_RESTORER = C.SA_RESTORER
+	SA_SIGINFO  = C.SA_SIGINFO
+
+	SIGHUP    = C.SIGHUP
+	SIGINT    = C.SIGINT
+	SIGQUIT   = C.SIGQUIT
+	SIGILL    = C.SIGILL
+	SIGTRAP   = C.SIGTRAP
+	SIGABRT   = C.SIGABRT
+	SIGBUS    = C.SIGBUS
+	SIGFPE    = C.SIGFPE
+	SIGKILL   = C.SIGKILL
+	SIGUSR1   = C.SIGUSR1
+	SIGSEGV   = C.SIGSEGV
+	SIGUSR2   = C.SIGUSR2
+	SIGPIPE   = C.SIGPIPE
+	SIGALRM   = C.SIGALRM
+	SIGSTKFLT = C.SIGSTKFLT
+	SIGCHLD   = C.SIGCHLD
+	SIGCONT   = C.SIGCONT
+	SIGSTOP   = C.SIGSTOP
+	SIGTSTP   = C.SIGTSTP
+	SIGTTIN   = C.SIGTTIN
+	SIGTTOU   = C.SIGTTOU
+	SIGURG    = C.SIGURG
+	SIGXCPU   = C.SIGXCPU
+	SIGXFSZ   = C.SIGXFSZ
+	SIGVTALRM = C.SIGVTALRM
+	SIGPROF   = C.SIGPROF
+	SIGWINCH  = C.SIGWINCH
+	SIGIO     = C.SIGIO
+	SIGPWR    = C.SIGPWR
+	SIGSYS    = C.SIGSYS
+
+	FPE_INTDIV = C.FPE_INTDIV & 0xFFFF
+	FPE_INTOVF = C.FPE_INTOVF & 0xFFFF
+	FPE_FLTDIV = C.FPE_FLTDIV & 0xFFFF
+	FPE_FLTOVF = C.FPE_FLTOVF & 0xFFFF
+	FPE_FLTUND = C.FPE_FLTUND & 0xFFFF
+	FPE_FLTRES = C.FPE_FLTRES & 0xFFFF
+	FPE_FLTINV = C.FPE_FLTINV & 0xFFFF
+	FPE_FLTSUB = C.FPE_FLTSUB & 0xFFFF
+
+	BUS_ADRALN = C.BUS_ADRALN & 0xFFFF
+	BUS_ADRERR = C.BUS_ADRERR & 0xFFFF
+	BUS_OBJERR = C.BUS_OBJERR & 0xFFFF
+
+	SEGV_MAPERR = C.SEGV_MAPERR & 0xFFFF
+	SEGV_ACCERR = C.SEGV_ACCERR & 0xFFFF
+
+	ITIMER_REAL    = C.ITIMER_REAL
+	ITIMER_PROF    = C.ITIMER_PROF
+	ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+)
+
+type Sigset C.sigset_t
+type Timespec C.struct_timespec
+type Sigaltstack C.struct_sigaltstack
+type Sigcontext C.struct_sigcontext
+type Ucontext C.struct_ucontext
+type Timeval C.struct_timeval
+type Itimerval C.struct_itimerval
+type Siginfo C.struct_xsiginfo
+type Sigaction C.struct_xsigaction
diff --git a/src/pkg/runtime/defs_darwin.go b/src/pkg/runtime/defs_darwin.go
new file mode 100644
index 0000000..7f22b0b
--- /dev/null
+++ b/src/pkg/runtime/defs_darwin.go
@@ -0,0 +1,163 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo.
+
+GOARCH=amd64 cgo -cdefs defs_darwin.go >defs_darwin_amd64.h
+GOARCH=386 cgo -cdefs defs_darwin.go >defs_darwin_386.h
+*/
+
+package runtime
+
+/*
+#define __DARWIN_UNIX03 0
+#include <mach/mach.h>
+#include <mach/message.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <sys/mman.h>
+*/
+import "C"
+
+const (
+	PROT_NONE  = C.PROT_NONE
+	PROT_READ  = C.PROT_READ
+	PROT_WRITE = C.PROT_WRITE
+	PROT_EXEC  = C.PROT_EXEC
+
+	MAP_ANON    = C.MAP_ANON
+	MAP_PRIVATE = C.MAP_PRIVATE
+	MAP_FIXED   = C.MAP_FIXED
+
+	MADV_DONTNEED = C.MADV_DONTNEED
+	MADV_FREE     = C.MADV_FREE
+
+	MACH_MSG_TYPE_MOVE_RECEIVE   = C.MACH_MSG_TYPE_MOVE_RECEIVE
+	MACH_MSG_TYPE_MOVE_SEND      = C.MACH_MSG_TYPE_MOVE_SEND
+	MACH_MSG_TYPE_MOVE_SEND_ONCE = C.MACH_MSG_TYPE_MOVE_SEND_ONCE
+	MACH_MSG_TYPE_COPY_SEND      = C.MACH_MSG_TYPE_COPY_SEND
+	MACH_MSG_TYPE_MAKE_SEND      = C.MACH_MSG_TYPE_MAKE_SEND
+	MACH_MSG_TYPE_MAKE_SEND_ONCE = C.MACH_MSG_TYPE_MAKE_SEND_ONCE
+	MACH_MSG_TYPE_COPY_RECEIVE   = C.MACH_MSG_TYPE_COPY_RECEIVE
+
+	MACH_MSG_PORT_DESCRIPTOR         = C.MACH_MSG_PORT_DESCRIPTOR
+	MACH_MSG_OOL_DESCRIPTOR          = C.MACH_MSG_OOL_DESCRIPTOR
+	MACH_MSG_OOL_PORTS_DESCRIPTOR    = C.MACH_MSG_OOL_PORTS_DESCRIPTOR
+	MACH_MSG_OOL_VOLATILE_DESCRIPTOR = C.MACH_MSG_OOL_VOLATILE_DESCRIPTOR
+
+	MACH_MSGH_BITS_COMPLEX = C.MACH_MSGH_BITS_COMPLEX
+
+	MACH_SEND_MSG  = C.MACH_SEND_MSG
+	MACH_RCV_MSG   = C.MACH_RCV_MSG
+	MACH_RCV_LARGE = C.MACH_RCV_LARGE
+
+	MACH_SEND_TIMEOUT   = C.MACH_SEND_TIMEOUT
+	MACH_SEND_INTERRUPT = C.MACH_SEND_INTERRUPT
+	MACH_SEND_ALWAYS    = C.MACH_SEND_ALWAYS
+	MACH_SEND_TRAILER   = C.MACH_SEND_TRAILER
+	MACH_RCV_TIMEOUT    = C.MACH_RCV_TIMEOUT
+	MACH_RCV_NOTIFY     = C.MACH_RCV_NOTIFY
+	MACH_RCV_INTERRUPT  = C.MACH_RCV_INTERRUPT
+	MACH_RCV_OVERWRITE  = C.MACH_RCV_OVERWRITE
+
+	NDR_PROTOCOL_2_0      = C.NDR_PROTOCOL_2_0
+	NDR_INT_BIG_ENDIAN    = C.NDR_INT_BIG_ENDIAN
+	NDR_INT_LITTLE_ENDIAN = C.NDR_INT_LITTLE_ENDIAN
+	NDR_FLOAT_IEEE        = C.NDR_FLOAT_IEEE
+	NDR_CHAR_ASCII        = C.NDR_CHAR_ASCII
+
+	SA_SIGINFO   = C.SA_SIGINFO
+	SA_RESTART   = C.SA_RESTART
+	SA_ONSTACK   = C.SA_ONSTACK
+	SA_USERTRAMP = C.SA_USERTRAMP
+	SA_64REGSET  = C.SA_64REGSET
+
+	SIGHUP    = C.SIGHUP
+	SIGINT    = C.SIGINT
+	SIGQUIT   = C.SIGQUIT
+	SIGILL    = C.SIGILL
+	SIGTRAP   = C.SIGTRAP
+	SIGABRT   = C.SIGABRT
+	SIGEMT    = C.SIGEMT
+	SIGFPE    = C.SIGFPE
+	SIGKILL   = C.SIGKILL
+	SIGBUS    = C.SIGBUS
+	SIGSEGV   = C.SIGSEGV
+	SIGSYS    = C.SIGSYS
+	SIGPIPE   = C.SIGPIPE
+	SIGALRM   = C.SIGALRM
+	SIGTERM   = C.SIGTERM
+	SIGURG    = C.SIGURG
+	SIGSTOP   = C.SIGSTOP
+	SIGTSTP   = C.SIGTSTP
+	SIGCONT   = C.SIGCONT
+	SIGCHLD   = C.SIGCHLD
+	SIGTTIN   = C.SIGTTIN
+	SIGTTOU   = C.SIGTTOU
+	SIGIO     = C.SIGIO
+	SIGXCPU   = C.SIGXCPU
+	SIGXFSZ   = C.SIGXFSZ
+	SIGVTALRM = C.SIGVTALRM
+	SIGPROF   = C.SIGPROF
+	SIGWINCH  = C.SIGWINCH
+	SIGINFO   = C.SIGINFO
+	SIGUSR1   = C.SIGUSR1
+	SIGUSR2   = C.SIGUSR2
+
+	FPE_INTDIV = C.FPE_INTDIV
+	FPE_INTOVF = C.FPE_INTOVF
+	FPE_FLTDIV = C.FPE_FLTDIV
+	FPE_FLTOVF = C.FPE_FLTOVF
+	FPE_FLTUND = C.FPE_FLTUND
+	FPE_FLTRES = C.FPE_FLTRES
+	FPE_FLTINV = C.FPE_FLTINV
+	FPE_FLTSUB = C.FPE_FLTSUB
+
+	BUS_ADRALN = C.BUS_ADRALN
+	BUS_ADRERR = C.BUS_ADRERR
+	BUS_OBJERR = C.BUS_OBJERR
+
+	SEGV_MAPERR = C.SEGV_MAPERR
+	SEGV_ACCERR = C.SEGV_ACCERR
+
+	ITIMER_REAL    = C.ITIMER_REAL
+	ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+	ITIMER_PROF    = C.ITIMER_PROF
+)
+
+type MachBody C.mach_msg_body_t
+type MachHeader C.mach_msg_header_t
+type MachNDR C.NDR_record_t
+type MachPort C.mach_msg_port_descriptor_t
+
+type StackT C.struct_sigaltstack
+type Sighandler C.union___sigaction_u
+
+type Sigaction C.struct___sigaction // used in syscalls
+// type Sigaction C.struct_sigaction	// used by the C library
+type Sigval C.union_sigval
+type Siginfo C.siginfo_t
+type Timeval C.struct_timeval
+type Itimerval C.struct_itimerval
+
+type FPControl C.struct_fp_control
+type FPStatus C.struct_fp_status
+type RegMMST C.struct_mmst_reg
+type RegXMM C.struct_xmm_reg
+
+type Regs64 C.struct_x86_thread_state64
+type FloatState64 C.struct_x86_float_state64
+type ExceptionState64 C.struct_x86_exception_state64
+type Mcontext64 C.struct_mcontext64
+
+type Regs32 C.struct_i386_thread_state
+type FloatState32 C.struct_i386_float_state
+type ExceptionState32 C.struct_i386_exception_state
+type Mcontext32 C.struct_mcontext32
+
+type Ucontext C.struct_ucontext
diff --git a/src/pkg/runtime/defs_darwin_386.h b/src/pkg/runtime/defs_darwin_386.h
new file mode 100644
index 0000000..92732f4
--- /dev/null
+++ b/src/pkg/runtime/defs_darwin_386.h
@@ -0,0 +1,366 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_darwin.go
+
+
+enum {
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_DONTNEED	= 0x4,
+	MADV_FREE	= 0x5,
+
+	MACH_MSG_TYPE_MOVE_RECEIVE	= 0x10,
+	MACH_MSG_TYPE_MOVE_SEND		= 0x11,
+	MACH_MSG_TYPE_MOVE_SEND_ONCE	= 0x12,
+	MACH_MSG_TYPE_COPY_SEND		= 0x13,
+	MACH_MSG_TYPE_MAKE_SEND		= 0x14,
+	MACH_MSG_TYPE_MAKE_SEND_ONCE	= 0x15,
+	MACH_MSG_TYPE_COPY_RECEIVE	= 0x16,
+
+	MACH_MSG_PORT_DESCRIPTOR		= 0x0,
+	MACH_MSG_OOL_DESCRIPTOR			= 0x1,
+	MACH_MSG_OOL_PORTS_DESCRIPTOR		= 0x2,
+	MACH_MSG_OOL_VOLATILE_DESCRIPTOR	= 0x3,
+
+	MACH_MSGH_BITS_COMPLEX	= 0x80000000,
+
+	MACH_SEND_MSG	= 0x1,
+	MACH_RCV_MSG	= 0x2,
+	MACH_RCV_LARGE	= 0x4,
+
+	MACH_SEND_TIMEOUT	= 0x10,
+	MACH_SEND_INTERRUPT	= 0x40,
+	MACH_SEND_ALWAYS	= 0x10000,
+	MACH_SEND_TRAILER	= 0x20000,
+	MACH_RCV_TIMEOUT	= 0x100,
+	MACH_RCV_NOTIFY		= 0x200,
+	MACH_RCV_INTERRUPT	= 0x400,
+	MACH_RCV_OVERWRITE	= 0x1000,
+
+	NDR_PROTOCOL_2_0	= 0x0,
+	NDR_INT_BIG_ENDIAN	= 0x0,
+	NDR_INT_LITTLE_ENDIAN	= 0x1,
+	NDR_FLOAT_IEEE		= 0x0,
+	NDR_CHAR_ASCII		= 0x0,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+	SA_USERTRAMP	= 0x100,
+	SA_64REGSET	= 0x200,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x7,
+	FPE_INTOVF	= 0x8,
+	FPE_FLTDIV	= 0x1,
+	FPE_FLTOVF	= 0x2,
+	FPE_FLTUND	= 0x3,
+	FPE_FLTRES	= 0x4,
+	FPE_FLTINV	= 0x5,
+	FPE_FLTSUB	= 0x6,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
+};
+
+typedef struct MachBody MachBody;
+typedef struct MachHeader MachHeader;
+typedef struct MachNDR MachNDR;
+typedef struct MachPort MachPort;
+typedef struct StackT StackT;
+typedef struct Sigaction Sigaction;
+typedef struct Siginfo Siginfo;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+typedef struct FPControl FPControl;
+typedef struct FPStatus FPStatus;
+typedef struct RegMMST RegMMST;
+typedef struct RegXMM RegXMM;
+typedef struct Regs64 Regs64;
+typedef struct FloatState64 FloatState64;
+typedef struct ExceptionState64 ExceptionState64;
+typedef struct Mcontext64 Mcontext64;
+typedef struct Regs32 Regs32;
+typedef struct FloatState32 FloatState32;
+typedef struct ExceptionState32 ExceptionState32;
+typedef struct Mcontext32 Mcontext32;
+typedef struct Ucontext Ucontext;
+
+#pragma pack on
+
+struct MachBody {
+	uint32	msgh_descriptor_count;
+};
+struct MachHeader {
+	uint32	msgh_bits;
+	uint32	msgh_size;
+	uint32	msgh_remote_port;
+	uint32	msgh_local_port;
+	uint32	msgh_reserved;
+	int32	msgh_id;
+};
+struct MachNDR {
+	uint8	mig_vers;
+	uint8	if_vers;
+	uint8	reserved1;
+	uint8	mig_encoding;
+	uint8	int_rep;
+	uint8	char_rep;
+	uint8	float_rep;
+	uint8	reserved2;
+};
+struct MachPort {
+	uint32	name;
+	uint32	pad1;
+	uint16	pad2;
+	uint8	disposition;
+	uint8	type;
+};
+
+struct StackT {
+	byte	*ss_sp;
+	uint32	ss_size;
+	int32	ss_flags;
+};
+typedef	byte	Sighandler[4];
+
+struct Sigaction {
+	Sighandler	__sigaction_u;
+	void	*sa_tramp;
+	uint32	sa_mask;
+	int32	sa_flags;
+};
+
+typedef	byte	Sigval[4];
+struct Siginfo {
+	int32	si_signo;
+	int32	si_errno;
+	int32	si_code;
+	int32	si_pid;
+	uint32	si_uid;
+	int32	si_status;
+	byte	*si_addr;
+	Sigval	si_value;
+	int32	si_band;
+	uint32	__pad[7];
+};
+struct Timeval {
+	int32	tv_sec;
+	int32	tv_usec;
+};
+struct Itimerval {
+	Timeval	it_interval;
+	Timeval	it_value;
+};
+
+struct FPControl {
+	byte	Pad_cgo_0[2];
+};
+struct FPStatus {
+	byte	Pad_cgo_0[2];
+};
+struct RegMMST {
+	int8	mmst_reg[10];
+	int8	mmst_rsrv[6];
+};
+struct RegXMM {
+	int8	xmm_reg[16];
+};
+
+struct Regs64 {
+	uint64	rax;
+	uint64	rbx;
+	uint64	rcx;
+	uint64	rdx;
+	uint64	rdi;
+	uint64	rsi;
+	uint64	rbp;
+	uint64	rsp;
+	uint64	r8;
+	uint64	r9;
+	uint64	r10;
+	uint64	r11;
+	uint64	r12;
+	uint64	r13;
+	uint64	r14;
+	uint64	r15;
+	uint64	rip;
+	uint64	rflags;
+	uint64	cs;
+	uint64	fs;
+	uint64	gs;
+};
+struct FloatState64 {
+	int32	fpu_reserved[2];
+	FPControl	fpu_fcw;
+	FPStatus	fpu_fsw;
+	uint8	fpu_ftw;
+	uint8	fpu_rsrv1;
+	uint16	fpu_fop;
+	uint32	fpu_ip;
+	uint16	fpu_cs;
+	uint16	fpu_rsrv2;
+	uint32	fpu_dp;
+	uint16	fpu_ds;
+	uint16	fpu_rsrv3;
+	uint32	fpu_mxcsr;
+	uint32	fpu_mxcsrmask;
+	RegMMST	fpu_stmm0;
+	RegMMST	fpu_stmm1;
+	RegMMST	fpu_stmm2;
+	RegMMST	fpu_stmm3;
+	RegMMST	fpu_stmm4;
+	RegMMST	fpu_stmm5;
+	RegMMST	fpu_stmm6;
+	RegMMST	fpu_stmm7;
+	RegXMM	fpu_xmm0;
+	RegXMM	fpu_xmm1;
+	RegXMM	fpu_xmm2;
+	RegXMM	fpu_xmm3;
+	RegXMM	fpu_xmm4;
+	RegXMM	fpu_xmm5;
+	RegXMM	fpu_xmm6;
+	RegXMM	fpu_xmm7;
+	RegXMM	fpu_xmm8;
+	RegXMM	fpu_xmm9;
+	RegXMM	fpu_xmm10;
+	RegXMM	fpu_xmm11;
+	RegXMM	fpu_xmm12;
+	RegXMM	fpu_xmm13;
+	RegXMM	fpu_xmm14;
+	RegXMM	fpu_xmm15;
+	int8	fpu_rsrv4[96];
+	int32	fpu_reserved1;
+};
+struct ExceptionState64 {
+	uint16	trapno;
+	uint16	cpu;
+	uint32	err;
+	uint64	faultvaddr;
+};
+struct Mcontext64 {
+	ExceptionState64	es;
+	Regs64	ss;
+	FloatState64	fs;
+};
+
+struct Regs32 {
+	uint32	eax;
+	uint32	ebx;
+	uint32	ecx;
+	uint32	edx;
+	uint32	edi;
+	uint32	esi;
+	uint32	ebp;
+	uint32	esp;
+	uint32	ss;
+	uint32	eflags;
+	uint32	eip;
+	uint32	cs;
+	uint32	ds;
+	uint32	es;
+	uint32	fs;
+	uint32	gs;
+};
+struct FloatState32 {
+	int32	fpu_reserved[2];
+	FPControl	fpu_fcw;
+	FPStatus	fpu_fsw;
+	uint8	fpu_ftw;
+	uint8	fpu_rsrv1;
+	uint16	fpu_fop;
+	uint32	fpu_ip;
+	uint16	fpu_cs;
+	uint16	fpu_rsrv2;
+	uint32	fpu_dp;
+	uint16	fpu_ds;
+	uint16	fpu_rsrv3;
+	uint32	fpu_mxcsr;
+	uint32	fpu_mxcsrmask;
+	RegMMST	fpu_stmm0;
+	RegMMST	fpu_stmm1;
+	RegMMST	fpu_stmm2;
+	RegMMST	fpu_stmm3;
+	RegMMST	fpu_stmm4;
+	RegMMST	fpu_stmm5;
+	RegMMST	fpu_stmm6;
+	RegMMST	fpu_stmm7;
+	RegXMM	fpu_xmm0;
+	RegXMM	fpu_xmm1;
+	RegXMM	fpu_xmm2;
+	RegXMM	fpu_xmm3;
+	RegXMM	fpu_xmm4;
+	RegXMM	fpu_xmm5;
+	RegXMM	fpu_xmm6;
+	RegXMM	fpu_xmm7;
+	int8	fpu_rsrv4[224];
+	int32	fpu_reserved1;
+};
+struct ExceptionState32 {
+	uint16	trapno;
+	uint16	cpu;
+	uint32	err;
+	uint32	faultvaddr;
+};
+struct Mcontext32 {
+	ExceptionState32	es;
+	Regs32	ss;
+	FloatState32	fs;
+};
+
+struct Ucontext {
+	int32	uc_onstack;
+	uint32	uc_sigmask;
+	StackT	uc_stack;
+	Ucontext	*uc_link;
+	uint32	uc_mcsize;
+	Mcontext32	*uc_mcontext;
+};
+
+
+#pragma pack off
diff --git a/src/pkg/runtime/defs_darwin_amd64.h b/src/pkg/runtime/defs_darwin_amd64.h
new file mode 100644
index 0000000..d4fbfef
--- /dev/null
+++ b/src/pkg/runtime/defs_darwin_amd64.h
@@ -0,0 +1,369 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_darwin.go
+
+
+enum {
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x1000,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_DONTNEED	= 0x4,
+	MADV_FREE	= 0x5,
+
+	MACH_MSG_TYPE_MOVE_RECEIVE	= 0x10,
+	MACH_MSG_TYPE_MOVE_SEND		= 0x11,
+	MACH_MSG_TYPE_MOVE_SEND_ONCE	= 0x12,
+	MACH_MSG_TYPE_COPY_SEND		= 0x13,
+	MACH_MSG_TYPE_MAKE_SEND		= 0x14,
+	MACH_MSG_TYPE_MAKE_SEND_ONCE	= 0x15,
+	MACH_MSG_TYPE_COPY_RECEIVE	= 0x16,
+
+	MACH_MSG_PORT_DESCRIPTOR		= 0x0,
+	MACH_MSG_OOL_DESCRIPTOR			= 0x1,
+	MACH_MSG_OOL_PORTS_DESCRIPTOR		= 0x2,
+	MACH_MSG_OOL_VOLATILE_DESCRIPTOR	= 0x3,
+
+	MACH_MSGH_BITS_COMPLEX	= 0x80000000,
+
+	MACH_SEND_MSG	= 0x1,
+	MACH_RCV_MSG	= 0x2,
+	MACH_RCV_LARGE	= 0x4,
+
+	MACH_SEND_TIMEOUT	= 0x10,
+	MACH_SEND_INTERRUPT	= 0x40,
+	MACH_SEND_ALWAYS	= 0x10000,
+	MACH_SEND_TRAILER	= 0x20000,
+	MACH_RCV_TIMEOUT	= 0x100,
+	MACH_RCV_NOTIFY		= 0x200,
+	MACH_RCV_INTERRUPT	= 0x400,
+	MACH_RCV_OVERWRITE	= 0x1000,
+
+	NDR_PROTOCOL_2_0	= 0x0,
+	NDR_INT_BIG_ENDIAN	= 0x0,
+	NDR_INT_LITTLE_ENDIAN	= 0x1,
+	NDR_FLOAT_IEEE		= 0x0,
+	NDR_CHAR_ASCII		= 0x0,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x2,
+	SA_ONSTACK	= 0x1,
+	SA_USERTRAMP	= 0x100,
+	SA_64REGSET	= 0x200,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGEMT		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x10,
+	SIGSTOP		= 0x11,
+	SIGTSTP		= 0x12,
+	SIGCONT		= 0x13,
+	SIGCHLD		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGIO		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGINFO		= 0x1d,
+	SIGUSR1		= 0x1e,
+	SIGUSR2		= 0x1f,
+
+	FPE_INTDIV	= 0x7,
+	FPE_INTOVF	= 0x8,
+	FPE_FLTDIV	= 0x1,
+	FPE_FLTOVF	= 0x2,
+	FPE_FLTUND	= 0x3,
+	FPE_FLTRES	= 0x4,
+	FPE_FLTINV	= 0x5,
+	FPE_FLTSUB	= 0x6,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
+};
+
+typedef struct MachBody MachBody;
+typedef struct MachHeader MachHeader;
+typedef struct MachNDR MachNDR;
+typedef struct MachPort MachPort;
+typedef struct StackT StackT;
+typedef struct Sigaction Sigaction;
+typedef struct Siginfo Siginfo;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+typedef struct FPControl FPControl;
+typedef struct FPStatus FPStatus;
+typedef struct RegMMST RegMMST;
+typedef struct RegXMM RegXMM;
+typedef struct Regs64 Regs64;
+typedef struct FloatState64 FloatState64;
+typedef struct ExceptionState64 ExceptionState64;
+typedef struct Mcontext64 Mcontext64;
+typedef struct Regs32 Regs32;
+typedef struct FloatState32 FloatState32;
+typedef struct ExceptionState32 ExceptionState32;
+typedef struct Mcontext32 Mcontext32;
+typedef struct Ucontext Ucontext;
+
+#pragma pack on
+
+struct MachBody {
+	uint32	msgh_descriptor_count;
+};
+struct MachHeader {
+	uint32	msgh_bits;
+	uint32	msgh_size;
+	uint32	msgh_remote_port;
+	uint32	msgh_local_port;
+	uint32	msgh_reserved;
+	int32	msgh_id;
+};
+struct MachNDR {
+	uint8	mig_vers;
+	uint8	if_vers;
+	uint8	reserved1;
+	uint8	mig_encoding;
+	uint8	int_rep;
+	uint8	char_rep;
+	uint8	float_rep;
+	uint8	reserved2;
+};
+struct MachPort {
+	uint32	name;
+	uint32	pad1;
+	uint16	pad2;
+	uint8	disposition;
+	uint8	type;
+};
+
+struct StackT {
+	byte	*ss_sp;
+	uint64	ss_size;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
+};
+typedef	byte	Sighandler[8];
+
+struct Sigaction {
+	Sighandler	__sigaction_u;
+	void	*sa_tramp;
+	uint32	sa_mask;
+	int32	sa_flags;
+};
+
+typedef	byte	Sigval[8];
+struct Siginfo {
+	int32	si_signo;
+	int32	si_errno;
+	int32	si_code;
+	int32	si_pid;
+	uint32	si_uid;
+	int32	si_status;
+	byte	*si_addr;
+	Sigval	si_value;
+	int64	si_band;
+	uint64	__pad[7];
+};
+struct Timeval {
+	int64	tv_sec;
+	int32	tv_usec;
+	byte	Pad_cgo_0[4];
+};
+struct Itimerval {
+	Timeval	it_interval;
+	Timeval	it_value;
+};
+
+struct FPControl {
+	byte	Pad_cgo_0[2];
+};
+struct FPStatus {
+	byte	Pad_cgo_0[2];
+};
+struct RegMMST {
+	int8	mmst_reg[10];
+	int8	mmst_rsrv[6];
+};
+struct RegXMM {
+	int8	xmm_reg[16];
+};
+
+struct Regs64 {
+	uint64	rax;
+	uint64	rbx;
+	uint64	rcx;
+	uint64	rdx;
+	uint64	rdi;
+	uint64	rsi;
+	uint64	rbp;
+	uint64	rsp;
+	uint64	r8;
+	uint64	r9;
+	uint64	r10;
+	uint64	r11;
+	uint64	r12;
+	uint64	r13;
+	uint64	r14;
+	uint64	r15;
+	uint64	rip;
+	uint64	rflags;
+	uint64	cs;
+	uint64	fs;
+	uint64	gs;
+};
+struct FloatState64 {
+	int32	fpu_reserved[2];
+	FPControl	fpu_fcw;
+	FPStatus	fpu_fsw;
+	uint8	fpu_ftw;
+	uint8	fpu_rsrv1;
+	uint16	fpu_fop;
+	uint32	fpu_ip;
+	uint16	fpu_cs;
+	uint16	fpu_rsrv2;
+	uint32	fpu_dp;
+	uint16	fpu_ds;
+	uint16	fpu_rsrv3;
+	uint32	fpu_mxcsr;
+	uint32	fpu_mxcsrmask;
+	RegMMST	fpu_stmm0;
+	RegMMST	fpu_stmm1;
+	RegMMST	fpu_stmm2;
+	RegMMST	fpu_stmm3;
+	RegMMST	fpu_stmm4;
+	RegMMST	fpu_stmm5;
+	RegMMST	fpu_stmm6;
+	RegMMST	fpu_stmm7;
+	RegXMM	fpu_xmm0;
+	RegXMM	fpu_xmm1;
+	RegXMM	fpu_xmm2;
+	RegXMM	fpu_xmm3;
+	RegXMM	fpu_xmm4;
+	RegXMM	fpu_xmm5;
+	RegXMM	fpu_xmm6;
+	RegXMM	fpu_xmm7;
+	RegXMM	fpu_xmm8;
+	RegXMM	fpu_xmm9;
+	RegXMM	fpu_xmm10;
+	RegXMM	fpu_xmm11;
+	RegXMM	fpu_xmm12;
+	RegXMM	fpu_xmm13;
+	RegXMM	fpu_xmm14;
+	RegXMM	fpu_xmm15;
+	int8	fpu_rsrv4[96];
+	int32	fpu_reserved1;
+};
+struct ExceptionState64 {
+	uint16	trapno;
+	uint16	cpu;
+	uint32	err;
+	uint64	faultvaddr;
+};
+struct Mcontext64 {
+	ExceptionState64	es;
+	Regs64	ss;
+	FloatState64	fs;
+	byte	Pad_cgo_0[4];
+};
+
+struct Regs32 {
+	uint32	eax;
+	uint32	ebx;
+	uint32	ecx;
+	uint32	edx;
+	uint32	edi;
+	uint32	esi;
+	uint32	ebp;
+	uint32	esp;
+	uint32	ss;
+	uint32	eflags;
+	uint32	eip;
+	uint32	cs;
+	uint32	ds;
+	uint32	es;
+	uint32	fs;
+	uint32	gs;
+};
+struct FloatState32 {
+	int32	fpu_reserved[2];
+	FPControl	fpu_fcw;
+	FPStatus	fpu_fsw;
+	uint8	fpu_ftw;
+	uint8	fpu_rsrv1;
+	uint16	fpu_fop;
+	uint32	fpu_ip;
+	uint16	fpu_cs;
+	uint16	fpu_rsrv2;
+	uint32	fpu_dp;
+	uint16	fpu_ds;
+	uint16	fpu_rsrv3;
+	uint32	fpu_mxcsr;
+	uint32	fpu_mxcsrmask;
+	RegMMST	fpu_stmm0;
+	RegMMST	fpu_stmm1;
+	RegMMST	fpu_stmm2;
+	RegMMST	fpu_stmm3;
+	RegMMST	fpu_stmm4;
+	RegMMST	fpu_stmm5;
+	RegMMST	fpu_stmm6;
+	RegMMST	fpu_stmm7;
+	RegXMM	fpu_xmm0;
+	RegXMM	fpu_xmm1;
+	RegXMM	fpu_xmm2;
+	RegXMM	fpu_xmm3;
+	RegXMM	fpu_xmm4;
+	RegXMM	fpu_xmm5;
+	RegXMM	fpu_xmm6;
+	RegXMM	fpu_xmm7;
+	int8	fpu_rsrv4[224];
+	int32	fpu_reserved1;
+};
+struct ExceptionState32 {
+	uint16	trapno;
+	uint16	cpu;
+	uint32	err;
+	uint32	faultvaddr;
+};
+struct Mcontext32 {
+	ExceptionState32	es;
+	Regs32	ss;
+	FloatState32	fs;
+};
+
+struct Ucontext {
+	int32	uc_onstack;
+	uint32	uc_sigmask;
+	StackT	uc_stack;
+	Ucontext	*uc_link;
+	uint64	uc_mcsize;
+	Mcontext64	*uc_mcontext;
+};
+
+
+#pragma pack off
diff --git a/src/pkg/runtime/defs_freebsd.go b/src/pkg/runtime/defs_freebsd.go
new file mode 100644
index 0000000..306e321
--- /dev/null
+++ b/src/pkg/runtime/defs_freebsd.go
@@ -0,0 +1,117 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo.
+
+GOARCH=amd64 cgo -cdefs defs.go >amd64/defs.h
+GOARCH=386 cgo -cdefs defs.go >386/defs.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/ucontext.h>
+#include <sys/umtx.h>
+#include <sys/rtprio.h>
+#include <sys/thr.h>
+#include <sys/_sigset.h>
+#include <sys/unistd.h>
+*/
+import "C"
+
+const (
+	PROT_NONE  = C.PROT_NONE
+	PROT_READ  = C.PROT_READ
+	PROT_WRITE = C.PROT_WRITE
+	PROT_EXEC  = C.PROT_EXEC
+
+	MAP_ANON    = C.MAP_ANON
+	MAP_PRIVATE = C.MAP_PRIVATE
+	MAP_FIXED   = C.MAP_FIXED
+
+	SA_SIGINFO = C.SA_SIGINFO
+	SA_RESTART = C.SA_RESTART
+	SA_ONSTACK = C.SA_ONSTACK
+
+	UMTX_OP_WAIT = C.UMTX_OP_WAIT
+	UMTX_OP_WAKE = C.UMTX_OP_WAKE
+
+	EINTR = C.EINTR
+
+	SIGHUP    = C.SIGHUP
+	SIGINT    = C.SIGINT
+	SIGQUIT   = C.SIGQUIT
+	SIGILL    = C.SIGILL
+	SIGTRAP   = C.SIGTRAP
+	SIGABRT   = C.SIGABRT
+	SIGEMT    = C.SIGEMT
+	SIGFPE    = C.SIGFPE
+	SIGKILL   = C.SIGKILL
+	SIGBUS    = C.SIGBUS
+	SIGSEGV   = C.SIGSEGV
+	SIGSYS    = C.SIGSYS
+	SIGPIPE   = C.SIGPIPE
+	SIGALRM   = C.SIGALRM
+	SIGTERM   = C.SIGTERM
+	SIGURG    = C.SIGURG
+	SIGSTOP   = C.SIGSTOP
+	SIGTSTP   = C.SIGTSTP
+	SIGCONT   = C.SIGCONT
+	SIGCHLD   = C.SIGCHLD
+	SIGTTIN   = C.SIGTTIN
+	SIGTTOU   = C.SIGTTOU
+	SIGIO     = C.SIGIO
+	SIGXCPU   = C.SIGXCPU
+	SIGXFSZ   = C.SIGXFSZ
+	SIGVTALRM = C.SIGVTALRM
+	SIGPROF   = C.SIGPROF
+	SIGWINCH  = C.SIGWINCH
+	SIGINFO   = C.SIGINFO
+	SIGUSR1   = C.SIGUSR1
+	SIGUSR2   = C.SIGUSR2
+
+	FPE_INTDIV = C.FPE_INTDIV
+	FPE_INTOVF = C.FPE_INTOVF
+	FPE_FLTDIV = C.FPE_FLTDIV
+	FPE_FLTOVF = C.FPE_FLTOVF
+	FPE_FLTUND = C.FPE_FLTUND
+	FPE_FLTRES = C.FPE_FLTRES
+	FPE_FLTINV = C.FPE_FLTINV
+	FPE_FLTSUB = C.FPE_FLTSUB
+
+	BUS_ADRALN = C.BUS_ADRALN
+	BUS_ADRERR = C.BUS_ADRERR
+	BUS_OBJERR = C.BUS_OBJERR
+
+	SEGV_MAPERR = C.SEGV_MAPERR
+	SEGV_ACCERR = C.SEGV_ACCERR
+
+	ITIMER_REAL    = C.ITIMER_REAL
+	ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+	ITIMER_PROF    = C.ITIMER_PROF
+)
+
+type Rtprio C.struct_rtprio
+type ThrParam C.struct_thr_param
+type Sigaltstack C.struct_sigaltstack
+type Sigset C.struct___sigset
+type Sigval C.union_sigval
+type StackT C.stack_t
+
+type Siginfo C.siginfo_t
+
+type Mcontext C.mcontext_t
+type Ucontext C.ucontext_t
+
+type Timespec C.struct_timespec
+type Timeval C.struct_timeval
+type Itimerval C.struct_itimerval
diff --git a/src/pkg/runtime/defs_freebsd_386.h b/src/pkg/runtime/defs_freebsd_386.h
new file mode 100644
index 0000000..29fcb8b
--- /dev/null
+++ b/src/pkg/runtime/defs_freebsd_386.h
@@ -0,0 +1,193 @@
+// godefs -f -m32 defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1000,
+	MAP_PRIVATE = 0x2,
+	MAP_FIXED = 0x10,
+	SA_SIGINFO = 0x40,
+	SA_RESTART = 0x2,
+	SA_ONSTACK = 0x1,
+	UMTX_OP_WAIT = 0x2,
+	UMTX_OP_WAKE = 0x3,
+	EINTR = 0x4,
+	SIGHUP = 0x1,
+	SIGINT = 0x2,
+	SIGQUIT = 0x3,
+	SIGILL = 0x4,
+	SIGTRAP = 0x5,
+	SIGABRT = 0x6,
+	SIGEMT = 0x7,
+	SIGFPE = 0x8,
+	SIGKILL = 0x9,
+	SIGBUS = 0xa,
+	SIGSEGV = 0xb,
+	SIGSYS = 0xc,
+	SIGPIPE = 0xd,
+	SIGALRM = 0xe,
+	SIGTERM = 0xf,
+	SIGURG = 0x10,
+	SIGSTOP = 0x11,
+	SIGTSTP = 0x12,
+	SIGCONT = 0x13,
+	SIGCHLD = 0x14,
+	SIGTTIN = 0x15,
+	SIGTTOU = 0x16,
+	SIGIO = 0x17,
+	SIGXCPU = 0x18,
+	SIGXFSZ = 0x19,
+	SIGVTALRM = 0x1a,
+	SIGPROF = 0x1b,
+	SIGWINCH = 0x1c,
+	SIGINFO = 0x1d,
+	SIGUSR1 = 0x1e,
+	SIGUSR2 = 0x1f,
+	FPE_INTDIV = 0x2,
+	FPE_INTOVF = 0x1,
+	FPE_FLTDIV = 0x3,
+	FPE_FLTOVF = 0x4,
+	FPE_FLTUND = 0x5,
+	FPE_FLTRES = 0x6,
+	FPE_FLTINV = 0x7,
+	FPE_FLTSUB = 0x8,
+	BUS_ADRALN = 0x1,
+	BUS_ADRERR = 0x2,
+	BUS_OBJERR = 0x3,
+	SEGV_MAPERR = 0x1,
+	SEGV_ACCERR = 0x2,
+	ITIMER_REAL = 0,
+	ITIMER_VIRTUAL = 0x1,
+	ITIMER_PROF = 0x2,
+};
+
+// Types
+#pragma pack on
+
+typedef struct Rtprio Rtprio;
+struct Rtprio {
+	uint16 type;
+	uint16 prio;
+};
+
+typedef struct ThrParam ThrParam;
+struct ThrParam {
+	void *start_func;
+	void *arg;
+	int8 *stack_base;
+	uint32 stack_size;
+	int8 *tls_base;
+	uint32 tls_size;
+	int32 *child_tid;
+	int32 *parent_tid;
+	int32 flags;
+	Rtprio *rtp;
+	void* spare[3];
+};
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+	int8 *ss_sp;
+	uint32 ss_size;
+	int32 ss_flags;
+};
+
+typedef struct Sigset Sigset;
+struct Sigset {
+	uint32 __bits[4];
+};
+
+typedef union Sigval Sigval;
+union Sigval {
+	int32 sival_int;
+	void *sival_ptr;
+	int32 sigval_int;
+	void *sigval_ptr;
+};
+
+typedef struct StackT StackT;
+struct StackT {
+	int8 *ss_sp;
+	uint32 ss_size;
+	int32 ss_flags;
+};
+
+typedef struct Siginfo Siginfo;
+struct Siginfo {
+	int32 si_signo;
+	int32 si_errno;
+	int32 si_code;
+	int32 si_pid;
+	uint32 si_uid;
+	int32 si_status;
+	void *si_addr;
+	Sigval si_value;
+	byte _reason[32];
+};
+
+typedef struct Mcontext Mcontext;
+struct Mcontext {
+	int32 mc_onstack;
+	int32 mc_gs;
+	int32 mc_fs;
+	int32 mc_es;
+	int32 mc_ds;
+	int32 mc_edi;
+	int32 mc_esi;
+	int32 mc_ebp;
+	int32 mc_isp;
+	int32 mc_ebx;
+	int32 mc_edx;
+	int32 mc_ecx;
+	int32 mc_eax;
+	int32 mc_trapno;
+	int32 mc_err;
+	int32 mc_eip;
+	int32 mc_cs;
+	int32 mc_eflags;
+	int32 mc_esp;
+	int32 mc_ss;
+	int32 mc_len;
+	int32 mc_fpformat;
+	int32 mc_ownedfp;
+	int32 mc_spare1[1];
+	int32 mc_fpstate[128];
+	int32 mc_fsbase;
+	int32 mc_gsbase;
+	int32 mc_spare2[6];
+};
+
+typedef struct Ucontext Ucontext;
+struct Ucontext {
+	Sigset uc_sigmask;
+	Mcontext uc_mcontext;
+	Ucontext *uc_link;
+	StackT uc_stack;
+	int32 uc_flags;
+	int32 __spare__[4];
+	byte pad_godefs_0[12];
+};
+
+typedef struct Timespec Timespec;
+struct Timespec {
+	int32 tv_sec;
+	int32 tv_nsec;
+};
+
+typedef struct Timeval Timeval;
+struct Timeval {
+	int32 tv_sec;
+	int32 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+	Timeval it_interval;
+	Timeval it_value;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/defs_freebsd_amd64.h b/src/pkg/runtime/defs_freebsd_amd64.h
new file mode 100644
index 0000000..8a222dc
--- /dev/null
+++ b/src/pkg/runtime/defs_freebsd_amd64.h
@@ -0,0 +1,204 @@
+// godefs -f -m64 defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1000,
+	MAP_PRIVATE = 0x2,
+	MAP_FIXED = 0x10,
+	SA_SIGINFO = 0x40,
+	SA_RESTART = 0x2,
+	SA_ONSTACK = 0x1,
+	UMTX_OP_WAIT = 0x2,
+	UMTX_OP_WAKE = 0x3,
+	EINTR = 0x4,
+	SIGHUP = 0x1,
+	SIGINT = 0x2,
+	SIGQUIT = 0x3,
+	SIGILL = 0x4,
+	SIGTRAP = 0x5,
+	SIGABRT = 0x6,
+	SIGEMT = 0x7,
+	SIGFPE = 0x8,
+	SIGKILL = 0x9,
+	SIGBUS = 0xa,
+	SIGSEGV = 0xb,
+	SIGSYS = 0xc,
+	SIGPIPE = 0xd,
+	SIGALRM = 0xe,
+	SIGTERM = 0xf,
+	SIGURG = 0x10,
+	SIGSTOP = 0x11,
+	SIGTSTP = 0x12,
+	SIGCONT = 0x13,
+	SIGCHLD = 0x14,
+	SIGTTIN = 0x15,
+	SIGTTOU = 0x16,
+	SIGIO = 0x17,
+	SIGXCPU = 0x18,
+	SIGXFSZ = 0x19,
+	SIGVTALRM = 0x1a,
+	SIGPROF = 0x1b,
+	SIGWINCH = 0x1c,
+	SIGINFO = 0x1d,
+	SIGUSR1 = 0x1e,
+	SIGUSR2 = 0x1f,
+	FPE_INTDIV = 0x2,
+	FPE_INTOVF = 0x1,
+	FPE_FLTDIV = 0x3,
+	FPE_FLTOVF = 0x4,
+	FPE_FLTUND = 0x5,
+	FPE_FLTRES = 0x6,
+	FPE_FLTINV = 0x7,
+	FPE_FLTSUB = 0x8,
+	BUS_ADRALN = 0x1,
+	BUS_ADRERR = 0x2,
+	BUS_OBJERR = 0x3,
+	SEGV_MAPERR = 0x1,
+	SEGV_ACCERR = 0x2,
+	ITIMER_REAL = 0,
+	ITIMER_VIRTUAL = 0x1,
+	ITIMER_PROF = 0x2,
+};
+
+// Types
+#pragma pack on
+
+typedef struct Rtprio Rtprio;
+struct Rtprio {
+	uint16 type;
+	uint16 prio;
+};
+
+typedef struct ThrParam ThrParam;
+struct ThrParam {
+	void *start_func;
+	void *arg;
+	int8 *stack_base;
+	uint64 stack_size;
+	int8 *tls_base;
+	uint64 tls_size;
+	int64 *child_tid;
+	int64 *parent_tid;
+	int32 flags;
+	byte pad_godefs_0[4];
+	Rtprio *rtp;
+	void* spare[3];
+};
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+	int8 *ss_sp;
+	uint64 ss_size;
+	int32 ss_flags;
+	byte pad_godefs_0[4];
+};
+
+typedef struct Sigset Sigset;
+struct Sigset {
+	uint32 __bits[4];
+};
+
+typedef union Sigval Sigval;
+union Sigval {
+	int32 sival_int;
+	void *sival_ptr;
+	int32 sigval_int;
+	void *sigval_ptr;
+};
+
+typedef struct StackT StackT;
+struct StackT {
+	int8 *ss_sp;
+	uint64 ss_size;
+	int32 ss_flags;
+	byte pad_godefs_0[4];
+};
+
+typedef struct Siginfo Siginfo;
+struct Siginfo {
+	int32 si_signo;
+	int32 si_errno;
+	int32 si_code;
+	int32 si_pid;
+	uint32 si_uid;
+	int32 si_status;
+	void *si_addr;
+	Sigval si_value;
+	byte _reason[40];
+};
+
+typedef struct Mcontext Mcontext;
+struct Mcontext {
+	int64 mc_onstack;
+	int64 mc_rdi;
+	int64 mc_rsi;
+	int64 mc_rdx;
+	int64 mc_rcx;
+	int64 mc_r8;
+	int64 mc_r9;
+	int64 mc_rax;
+	int64 mc_rbx;
+	int64 mc_rbp;
+	int64 mc_r10;
+	int64 mc_r11;
+	int64 mc_r12;
+	int64 mc_r13;
+	int64 mc_r14;
+	int64 mc_r15;
+	uint32 mc_trapno;
+	uint16 mc_fs;
+	uint16 mc_gs;
+	int64 mc_addr;
+	uint32 mc_flags;
+	uint16 mc_es;
+	uint16 mc_ds;
+	int64 mc_err;
+	int64 mc_rip;
+	int64 mc_cs;
+	int64 mc_rflags;
+	int64 mc_rsp;
+	int64 mc_ss;
+	int64 mc_len;
+	int64 mc_fpformat;
+	int64 mc_ownedfp;
+	int64 mc_fpstate[64];
+	int64 mc_fsbase;
+	int64 mc_gsbase;
+	int64 mc_spare[6];
+};
+
+typedef struct Ucontext Ucontext;
+struct Ucontext {
+	Sigset uc_sigmask;
+	Mcontext uc_mcontext;
+	Ucontext *uc_link;
+	StackT uc_stack;
+	int32 uc_flags;
+	int32 __spare__[4];
+	byte pad_godefs_0[12];
+};
+
+typedef struct Timespec Timespec;
+struct Timespec {
+	int64 tv_sec;
+	int64 tv_nsec;
+};
+
+typedef struct Timeval Timeval;
+struct Timeval {
+	int64 tv_sec;
+	int64 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+	Timeval it_interval;
+	Timeval it_value;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/defs_linux.go b/src/pkg/runtime/defs_linux.go
new file mode 100644
index 0000000..c0275e1
--- /dev/null
+++ b/src/pkg/runtime/defs_linux.go
@@ -0,0 +1,104 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo -cdefs
+
+GOARCH=amd64 cgo -cdefs defs.go defs1.go >amd64/defs.h
+*/
+
+package runtime
+
+/*
+// Linux glibc and Linux kernel define different and conflicting
+// definitions for struct sigaction, struct timespec, etc.
+// We want the kernel ones, which are in the asm/* headers.
+// But then we'd get conflicts when we include the system
+// headers for things like ucontext_t, so that happens in
+// a separate file, defs1.go.
+
+#include <asm/posix_types.h>
+#define size_t __kernel_size_t
+#include <asm/signal.h>
+#include <asm/siginfo.h>
+#include <asm/mman.h>
+*/
+import "C"
+
+const (
+	PROT_NONE  = C.PROT_NONE
+	PROT_READ  = C.PROT_READ
+	PROT_WRITE = C.PROT_WRITE
+	PROT_EXEC  = C.PROT_EXEC
+
+	MAP_ANON    = C.MAP_ANONYMOUS
+	MAP_PRIVATE = C.MAP_PRIVATE
+	MAP_FIXED   = C.MAP_FIXED
+
+	MADV_DONTNEED = C.MADV_DONTNEED
+
+	SA_RESTART  = C.SA_RESTART
+	SA_ONSTACK  = C.SA_ONSTACK
+	SA_RESTORER = C.SA_RESTORER
+	SA_SIGINFO  = C.SA_SIGINFO
+
+	SIGHUP    = C.SIGHUP
+	SIGINT    = C.SIGINT
+	SIGQUIT   = C.SIGQUIT
+	SIGILL    = C.SIGILL
+	SIGTRAP   = C.SIGTRAP
+	SIGABRT   = C.SIGABRT
+	SIGBUS    = C.SIGBUS
+	SIGFPE    = C.SIGFPE
+	SIGKILL   = C.SIGKILL
+	SIGUSR1   = C.SIGUSR1
+	SIGSEGV   = C.SIGSEGV
+	SIGUSR2   = C.SIGUSR2
+	SIGPIPE   = C.SIGPIPE
+	SIGALRM   = C.SIGALRM
+	SIGSTKFLT = C.SIGSTKFLT
+	SIGCHLD   = C.SIGCHLD
+	SIGCONT   = C.SIGCONT
+	SIGSTOP   = C.SIGSTOP
+	SIGTSTP   = C.SIGTSTP
+	SIGTTIN   = C.SIGTTIN
+	SIGTTOU   = C.SIGTTOU
+	SIGURG    = C.SIGURG
+	SIGXCPU   = C.SIGXCPU
+	SIGXFSZ   = C.SIGXFSZ
+	SIGVTALRM = C.SIGVTALRM
+	SIGPROF   = C.SIGPROF
+	SIGWINCH  = C.SIGWINCH
+	SIGIO     = C.SIGIO
+	SIGPWR    = C.SIGPWR
+	SIGSYS    = C.SIGSYS
+
+	FPE_INTDIV = C.FPE_INTDIV
+	FPE_INTOVF = C.FPE_INTOVF
+	FPE_FLTDIV = C.FPE_FLTDIV
+	FPE_FLTOVF = C.FPE_FLTOVF
+	FPE_FLTUND = C.FPE_FLTUND
+	FPE_FLTRES = C.FPE_FLTRES
+	FPE_FLTINV = C.FPE_FLTINV
+	FPE_FLTSUB = C.FPE_FLTSUB
+
+	BUS_ADRALN = C.BUS_ADRALN
+	BUS_ADRERR = C.BUS_ADRERR
+	BUS_OBJERR = C.BUS_OBJERR
+
+	SEGV_MAPERR = C.SEGV_MAPERR
+	SEGV_ACCERR = C.SEGV_ACCERR
+
+	ITIMER_REAL    = C.ITIMER_REAL
+	ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+	ITIMER_PROF    = C.ITIMER_PROF
+)
+
+type Timespec C.struct_timespec
+type Timeval C.struct_timeval
+type Sigaction C.struct_sigaction
+type Siginfo C.siginfo_t
+type Itimerval C.struct_itimerval
diff --git a/src/pkg/runtime/defs_linux_386.h b/src/pkg/runtime/defs_linux_386.h
new file mode 100644
index 0000000..02760f9
--- /dev/null
+++ b/src/pkg/runtime/defs_linux_386.h
@@ -0,0 +1,191 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs2.go
+
+
+enum {
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x20,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_DONTNEED	= 0x4,
+
+	SA_RESTART	= 0x10000000,
+	SA_ONSTACK	= 0x8000000,
+	SA_RESTORER	= 0x4000000,
+	SA_SIGINFO	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGBUS		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGUSR1		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGUSR2		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGSTKFLT	= 0x10,
+	SIGCHLD		= 0x11,
+	SIGCONT		= 0x12,
+	SIGSTOP		= 0x13,
+	SIGTSTP		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGURG		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGIO		= 0x1d,
+	SIGPWR		= 0x1e,
+	SIGSYS		= 0x1f,
+
+	FPE_INTDIV	= 0x1,
+	FPE_INTOVF	= 0x2,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
+
+	O_RDONLY	= 0x0,
+	O_CLOEXEC	= 0x80000,
+};
+
+typedef struct Fpreg Fpreg;
+typedef struct Fpxreg Fpxreg;
+typedef struct Xmmreg Xmmreg;
+typedef struct Fpstate Fpstate;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Sigaction Sigaction;
+typedef struct Siginfo Siginfo;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigcontext Sigcontext;
+typedef struct Ucontext Ucontext;
+typedef struct Itimerval Itimerval;
+
+#pragma pack on
+
+struct Fpreg {
+	uint16	significand[4];
+	uint16	exponent;
+};
+struct Fpxreg {
+	uint16	significand[4];
+	uint16	exponent;
+	uint16	padding[3];
+};
+struct Xmmreg {
+	uint32	element[4];
+};
+struct Fpstate {
+	uint32	cw;
+	uint32	sw;
+	uint32	tag;
+	uint32	ipoff;
+	uint32	cssel;
+	uint32	dataoff;
+	uint32	datasel;
+	Fpreg	_st[8];
+	uint16	status;
+	uint16	magic;
+	uint32	_fxsr_env[6];
+	uint32	mxcsr;
+	uint32	reserved;
+	Fpxreg	_fxsr_st[8];
+	Xmmreg	_xmm[8];
+	uint32	padding1[44];
+	byte	anon0[48];
+};
+struct Timespec {
+	int32	tv_sec;
+	int32	tv_nsec;
+};
+struct Timeval {
+	int32	tv_sec;
+	int32	tv_usec;
+};
+struct Sigaction {
+	void	*k_sa_handler;
+	uint32	sa_flags;
+	void	*sa_restorer;
+	uint32	sa_mask;
+};
+struct Siginfo {
+	int32	si_signo;
+	int32	si_errno;
+	int32	si_code;
+	byte	_sifields[116];
+};
+struct Sigaltstack {
+	byte	*ss_sp;
+	int32	ss_flags;
+	uint32	ss_size;
+};
+struct Sigcontext {
+	uint16	gs;
+	uint16	__gsh;
+	uint16	fs;
+	uint16	__fsh;
+	uint16	es;
+	uint16	__esh;
+	uint16	ds;
+	uint16	__dsh;
+	uint32	edi;
+	uint32	esi;
+	uint32	ebp;
+	uint32	esp;
+	uint32	ebx;
+	uint32	edx;
+	uint32	ecx;
+	uint32	eax;
+	uint32	trapno;
+	uint32	err;
+	uint32	eip;
+	uint16	cs;
+	uint16	__csh;
+	uint32	eflags;
+	uint32	esp_at_signal;
+	uint16	ss;
+	uint16	__ssh;
+	Fpstate	*fpstate;
+	uint32	oldmask;
+	uint32	cr2;
+};
+struct Ucontext {
+	uint32	uc_flags;
+	Ucontext	*uc_link;
+	Sigaltstack	uc_stack;
+	Sigcontext	uc_mcontext;
+	uint32	uc_sigmask;
+};
+struct Itimerval {
+	Timeval	it_interval;
+	Timeval	it_value;
+};
+
+
+#pragma pack off
diff --git a/src/pkg/runtime/defs_linux_amd64.h b/src/pkg/runtime/defs_linux_amd64.h
new file mode 100644
index 0000000..bf5f79b
--- /dev/null
+++ b/src/pkg/runtime/defs_linux_amd64.h
@@ -0,0 +1,234 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs.go defs1.go
+
+
+enum {
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x20,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x10,
+
+	MADV_DONTNEED	= 0x4,
+
+	SA_RESTART	= 0x10000000,
+	SA_ONSTACK	= 0x8000000,
+	SA_RESTORER	= 0x4000000,
+	SA_SIGINFO	= 0x4,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x5,
+	SIGABRT		= 0x6,
+	SIGBUS		= 0x7,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGUSR1		= 0xa,
+	SIGSEGV		= 0xb,
+	SIGUSR2		= 0xc,
+	SIGPIPE		= 0xd,
+	SIGALRM		= 0xe,
+	SIGSTKFLT	= 0x10,
+	SIGCHLD		= 0x11,
+	SIGCONT		= 0x12,
+	SIGSTOP		= 0x13,
+	SIGTSTP		= 0x14,
+	SIGTTIN		= 0x15,
+	SIGTTOU		= 0x16,
+	SIGURG		= 0x17,
+	SIGXCPU		= 0x18,
+	SIGXFSZ		= 0x19,
+	SIGVTALRM	= 0x1a,
+	SIGPROF		= 0x1b,
+	SIGWINCH	= 0x1c,
+	SIGIO		= 0x1d,
+	SIGPWR		= 0x1e,
+	SIGSYS		= 0x1f,
+
+	FPE_INTDIV	= 0x1,
+	FPE_INTOVF	= 0x2,
+	FPE_FLTDIV	= 0x3,
+	FPE_FLTOVF	= 0x4,
+	FPE_FLTUND	= 0x5,
+	FPE_FLTRES	= 0x6,
+	FPE_FLTINV	= 0x7,
+	FPE_FLTSUB	= 0x8,
+
+	BUS_ADRALN	= 0x1,
+	BUS_ADRERR	= 0x2,
+	BUS_OBJERR	= 0x3,
+
+	SEGV_MAPERR	= 0x1,
+	SEGV_ACCERR	= 0x2,
+
+	ITIMER_REAL	= 0x0,
+	ITIMER_VIRTUAL	= 0x1,
+	ITIMER_PROF	= 0x2,
+};
+
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Sigaction Sigaction;
+typedef struct Siginfo Siginfo;
+typedef struct Itimerval Itimerval;
+
+#pragma pack on
+
+struct Timespec {
+	int64	tv_sec;
+	int64	tv_nsec;
+};
+struct Timeval {
+	int64	tv_sec;
+	int64	tv_usec;
+};
+struct Sigaction {
+	void	*sa_handler;
+	uint64	sa_flags;
+	void	*sa_restorer;
+	uint64	sa_mask;
+};
+struct Siginfo {
+	int32	si_signo;
+	int32	si_errno;
+	int32	si_code;
+	byte	Pad_cgo_0[4];
+	byte	_sifields[112];
+};
+struct Itimerval {
+	Timeval	it_interval;
+	Timeval	it_value;
+};
+
+
+#pragma pack off
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs.go defs1.go
+
+
+enum {
+	O_RDONLY	= 0x0,
+	O_CLOEXEC	= 0x80000,
+};
+
+typedef struct Usigset Usigset;
+typedef struct Fpxreg Fpxreg;
+typedef struct Xmmreg Xmmreg;
+typedef struct Fpstate Fpstate;
+typedef struct Fpxreg1 Fpxreg1;
+typedef struct Xmmreg1 Xmmreg1;
+typedef struct Fpstate1 Fpstate1;
+typedef struct Fpreg1 Fpreg1;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Mcontext Mcontext;
+typedef struct Ucontext Ucontext;
+typedef struct Sigcontext Sigcontext;
+
+#pragma pack on
+
+struct Usigset {
+	uint64	__val[16];
+};
+struct Fpxreg {
+	uint16	significand[4];
+	uint16	exponent;
+	uint16	padding[3];
+};
+struct Xmmreg {
+	uint32	element[4];
+};
+struct Fpstate {
+	uint16	cwd;
+	uint16	swd;
+	uint16	ftw;
+	uint16	fop;
+	uint64	rip;
+	uint64	rdp;
+	uint32	mxcsr;
+	uint32	mxcr_mask;
+	Fpxreg	_st[8];
+	Xmmreg	_xmm[16];
+	uint32	padding[24];
+};
+struct Fpxreg1 {
+	uint16	significand[4];
+	uint16	exponent;
+	uint16	padding[3];
+};
+struct Xmmreg1 {
+	uint32	element[4];
+};
+struct Fpstate1 {
+	uint16	cwd;
+	uint16	swd;
+	uint16	ftw;
+	uint16	fop;
+	uint64	rip;
+	uint64	rdp;
+	uint32	mxcsr;
+	uint32	mxcr_mask;
+	Fpxreg1	_st[8];
+	Xmmreg1	_xmm[16];
+	uint32	padding[24];
+};
+struct Fpreg1 {
+	uint16	significand[4];
+	uint16	exponent;
+};
+struct Sigaltstack {
+	byte	*ss_sp;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
+	uint64	ss_size;
+};
+struct Mcontext {
+	int64	gregs[23];
+	Fpstate	*fpregs;
+	uint64	__reserved1[8];
+};
+struct Ucontext {
+	uint64	uc_flags;
+	Ucontext	*uc_link;
+	Sigaltstack	uc_stack;
+	Mcontext	uc_mcontext;
+	Usigset	uc_sigmask;
+	Fpstate	__fpregs_mem;
+};
+struct Sigcontext {
+	uint64	r8;
+	uint64	r9;
+	uint64	r10;
+	uint64	r11;
+	uint64	r12;
+	uint64	r13;
+	uint64	r14;
+	uint64	r15;
+	uint64	rdi;
+	uint64	rsi;
+	uint64	rbp;
+	uint64	rbx;
+	uint64	rdx;
+	uint64	rax;
+	uint64	rcx;
+	uint64	rsp;
+	uint64	rip;
+	uint64	eflags;
+	uint16	cs;
+	uint16	gs;
+	uint16	fs;
+	uint16	__pad0;
+	uint64	err;
+	uint64	trapno;
+	uint64	oldmask;
+	uint64	cr2;
+	Fpstate1	*fpstate;
+	uint64	__reserved1[8];
+};
+
+
+#pragma pack off
diff --git a/src/pkg/runtime/defs_linux_arm.h b/src/pkg/runtime/defs_linux_arm.h
new file mode 100644
index 0000000..da97a84
--- /dev/null
+++ b/src/pkg/runtime/defs_linux_arm.h
@@ -0,0 +1,150 @@
+// godefs -f-I/usr/src/linux-headers-2.6.26-2-versatile/include defs_arm.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x20,
+	MAP_PRIVATE = 0x2,
+	MAP_FIXED = 0x10,
+	MADV_DONTNEED = 0x4,
+	SA_RESTART = 0x10000000,
+	SA_ONSTACK = 0x8000000,
+	SA_RESTORER = 0x4000000,
+	SA_SIGINFO = 0x4,
+	SIGHUP = 0x1,
+	SIGINT = 0x2,
+	SIGQUIT = 0x3,
+	SIGILL = 0x4,
+	SIGTRAP = 0x5,
+	SIGABRT = 0x6,
+	SIGBUS = 0x7,
+	SIGFPE = 0x8,
+	SIGKILL = 0x9,
+	SIGUSR1 = 0xa,
+	SIGSEGV = 0xb,
+	SIGUSR2 = 0xc,
+	SIGPIPE = 0xd,
+	SIGALRM = 0xe,
+	SIGSTKFLT = 0x10,
+	SIGCHLD = 0x11,
+	SIGCONT = 0x12,
+	SIGSTOP = 0x13,
+	SIGTSTP = 0x14,
+	SIGTTIN = 0x15,
+	SIGTTOU = 0x16,
+	SIGURG = 0x17,
+	SIGXCPU = 0x18,
+	SIGXFSZ = 0x19,
+	SIGVTALRM = 0x1a,
+	SIGPROF = 0x1b,
+	SIGWINCH = 0x1c,
+	SIGIO = 0x1d,
+	SIGPWR = 0x1e,
+	SIGSYS = 0x1f,
+	FPE_INTDIV = 0x1,
+	FPE_INTOVF = 0x2,
+	FPE_FLTDIV = 0x3,
+	FPE_FLTOVF = 0x4,
+	FPE_FLTUND = 0x5,
+	FPE_FLTRES = 0x6,
+	FPE_FLTINV = 0x7,
+	FPE_FLTSUB = 0x8,
+	BUS_ADRALN = 0x1,
+	BUS_ADRERR = 0x2,
+	BUS_OBJERR = 0x3,
+	SEGV_MAPERR = 0x1,
+	SEGV_ACCERR = 0x2,
+	ITIMER_REAL = 0,
+	ITIMER_PROF = 0x2,
+	ITIMER_VIRTUAL = 0x1,
+	O_RDONLY = 0,
+	O_CLOEXEC = 02000000,
+};
+
+// Types
+#pragma pack on
+
+typedef uint32 Sigset;
+
+typedef struct Timespec Timespec;
+struct Timespec {
+	int32 tv_sec;
+	int32 tv_nsec;
+};
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+	void *ss_sp;
+	int32 ss_flags;
+	uint32 ss_size;
+};
+
+typedef struct Sigcontext Sigcontext;
+struct Sigcontext {
+	uint32 trap_no;
+	uint32 error_code;
+	uint32 oldmask;
+	uint32 arm_r0;
+	uint32 arm_r1;
+	uint32 arm_r2;
+	uint32 arm_r3;
+	uint32 arm_r4;
+	uint32 arm_r5;
+	uint32 arm_r6;
+	uint32 arm_r7;
+	uint32 arm_r8;
+	uint32 arm_r9;
+	uint32 arm_r10;
+	uint32 arm_fp;
+	uint32 arm_ip;
+	uint32 arm_sp;
+	uint32 arm_lr;
+	uint32 arm_pc;
+	uint32 arm_cpsr;
+	uint32 fault_address;
+};
+
+typedef struct Ucontext Ucontext;
+struct Ucontext {
+	uint32 uc_flags;
+	Ucontext *uc_link;
+	Sigaltstack uc_stack;
+	Sigcontext uc_mcontext;
+	uint32 uc_sigmask;
+	int32 __unused[31];
+	uint32 uc_regspace[128];
+};
+
+typedef struct Timeval Timeval;
+struct Timeval {
+	int32 tv_sec;
+	int32 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+	Timeval it_interval;
+	Timeval it_value;
+};
+
+typedef struct Siginfo Siginfo;
+struct Siginfo {
+	int32 si_signo;
+	int32 si_errno;
+	int32 si_code;
+	uint8 _sifields[4];
+};
+
+typedef struct Sigaction Sigaction;
+struct Sigaction {
+	void *sa_handler;
+	uint32 sa_flags;
+	void *sa_restorer;
+	uint32 sa_mask;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/defs_netbsd.go b/src/pkg/runtime/defs_netbsd.go
new file mode 100644
index 0000000..47c30cf
--- /dev/null
+++ b/src/pkg/runtime/defs_netbsd.go
@@ -0,0 +1,111 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo.
+
+GOARCH=amd64 cgo -cdefs defs.go >amd64/defs.h
+GOARCH=386 cgo -cdefs defs.go >386/defs.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/unistd.h>
+#include <sys/signal.h>
+#include <errno.h>
+#include <signal.h>
+*/
+import "C"
+
+const (
+	PROT_NONE  = C.PROT_NONE
+	PROT_READ  = C.PROT_READ
+	PROT_WRITE = C.PROT_WRITE
+	PROT_EXEC  = C.PROT_EXEC
+
+	MAP_ANON    = C.MAP_ANON
+	MAP_PRIVATE = C.MAP_PRIVATE
+	MAP_FIXED   = C.MAP_FIXED
+
+	SA_SIGINFO = C.SA_SIGINFO
+	SA_RESTART = C.SA_RESTART
+	SA_ONSTACK = C.SA_ONSTACK
+
+	EINTR = C.EINTR
+
+	SIGHUP    = C.SIGHUP
+	SIGINT    = C.SIGINT
+	SIGQUIT   = C.SIGQUIT
+	SIGILL    = C.SIGILL
+	SIGTRAP   = C.SIGTRAP
+	SIGABRT   = C.SIGABRT
+	SIGEMT    = C.SIGEMT
+	SIGFPE    = C.SIGFPE
+	SIGKILL   = C.SIGKILL
+	SIGBUS    = C.SIGBUS
+	SIGSEGV   = C.SIGSEGV
+	SIGSYS    = C.SIGSYS
+	SIGPIPE   = C.SIGPIPE
+	SIGALRM   = C.SIGALRM
+	SIGTERM   = C.SIGTERM
+	SIGURG    = C.SIGURG
+	SIGSTOP   = C.SIGSTOP
+	SIGTSTP   = C.SIGTSTP
+	SIGCONT   = C.SIGCONT
+	SIGCHLD   = C.SIGCHLD
+	SIGTTIN   = C.SIGTTIN
+	SIGTTOU   = C.SIGTTOU
+	SIGIO     = C.SIGIO
+	SIGXCPU   = C.SIGXCPU
+	SIGXFSZ   = C.SIGXFSZ
+	SIGVTALRM = C.SIGVTALRM
+	SIGPROF   = C.SIGPROF
+	SIGWINCH  = C.SIGWINCH
+	SIGINFO   = C.SIGINFO
+	SIGUSR1   = C.SIGUSR1
+	SIGUSR2   = C.SIGUSR2
+
+	FPE_INTDIV = C.FPE_INTDIV
+	FPE_INTOVF = C.FPE_INTOVF
+	FPE_FLTDIV = C.FPE_FLTDIV
+	FPE_FLTOVF = C.FPE_FLTOVF
+	FPE_FLTUND = C.FPE_FLTUND
+	FPE_FLTRES = C.FPE_FLTRES
+	FPE_FLTINV = C.FPE_FLTINV
+	FPE_FLTSUB = C.FPE_FLTSUB
+
+	BUS_ADRALN = C.BUS_ADRALN
+	BUS_ADRERR = C.BUS_ADRERR
+	BUS_OBJERR = C.BUS_OBJERR
+
+	SEGV_MAPERR = C.SEGV_MAPERR
+	SEGV_ACCERR = C.SEGV_ACCERR
+
+	ITIMER_REAL    = C.ITIMER_REAL
+	ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+	ITIMER_PROF    = C.ITIMER_PROF
+)
+
+type Sigaltstack C.struct_sigaltstack
+type Sigset C.sigset_t
+type Siginfo C.siginfo_t
+type Sigval C.union_sigval
+
+type StackT C.stack_t
+
+type Timespec C.struct_timespec
+type Timeval C.struct_timeval
+type Itimerval C.struct_itimerval
+
+// This is a hack to avoid pulling in machine/fpu.h.
+type sfxsave64 struct{}
+type usavefpu struct{}
+
+type Sigcontext C.struct_sigcontext
diff --git a/src/pkg/runtime/defs_netbsd_386.h b/src/pkg/runtime/defs_netbsd_386.h
new file mode 100644
index 0000000..aff87fb
--- /dev/null
+++ b/src/pkg/runtime/defs_netbsd_386.h
@@ -0,0 +1,146 @@
+// godefs -f -m32 defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1000,
+	MAP_PRIVATE = 0x2,
+	MAP_FIXED = 0x10,
+	SA_SIGINFO = 0x40,
+	SA_RESTART = 0x2,
+	SA_ONSTACK = 0x1,
+	EINTR = 0x4,
+	SIGHUP = 0x1,
+	SIGINT = 0x2,
+	SIGQUIT = 0x3,
+	SIGILL = 0x4,
+	SIGTRAP = 0x5,
+	SIGABRT = 0x6,
+	SIGEMT = 0x7,
+	SIGFPE = 0x8,
+	SIGKILL = 0x9,
+	SIGBUS = 0xa,
+	SIGSEGV = 0xb,
+	SIGSYS = 0xc,
+	SIGPIPE = 0xd,
+	SIGALRM = 0xe,
+	SIGTERM = 0xf,
+	SIGURG = 0x10,
+	SIGSTOP = 0x11,
+	SIGTSTP = 0x12,
+	SIGCONT = 0x13,
+	SIGCHLD = 0x14,
+	SIGTTIN = 0x15,
+	SIGTTOU = 0x16,
+	SIGIO = 0x17,
+	SIGXCPU = 0x18,
+	SIGXFSZ = 0x19,
+	SIGVTALRM = 0x1a,
+	SIGPROF = 0x1b,
+	SIGWINCH = 0x1c,
+	SIGINFO = 0x1d,
+	SIGUSR1 = 0x1e,
+	SIGUSR2 = 0x1f,
+	FPE_INTDIV = 0x1,
+	FPE_INTOVF = 0x2,
+	FPE_FLTDIV = 0x3,
+	FPE_FLTOVF = 0x4,
+	FPE_FLTUND = 0x5,
+	FPE_FLTRES = 0x6,
+	FPE_FLTINV = 0x7,
+	FPE_FLTSUB = 0x8,
+	BUS_ADRALN = 0x1,
+	BUS_ADRERR = 0x2,
+	BUS_OBJERR = 0x3,
+	SEGV_MAPERR = 0x1,
+	SEGV_ACCERR = 0x2,
+	ITIMER_REAL = 0,
+	ITIMER_VIRTUAL = 0x1,
+	ITIMER_PROF = 0x2,
+};
+
+// Types
+#pragma pack on
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+	void *ss_sp;
+	uint32 ss_size;
+	int32 ss_flags;
+};
+
+typedef uint32 Sigset;
+
+typedef struct Siginfo Siginfo;
+struct Siginfo {
+	int32 si_signo;
+	int32 si_code;
+	int32 si_errno;
+	byte _data[116];
+};
+
+typedef union Sigval Sigval;
+union Sigval {
+	int32 sival_int;
+	void *sival_ptr;
+};
+
+typedef struct StackT StackT;
+struct StackT {
+	void *ss_sp;
+	uint32 ss_size;
+	int32 ss_flags;
+};
+
+typedef struct Timespec Timespec;
+struct Timespec {
+	int32 tv_sec;
+	int32 tv_nsec;
+};
+
+typedef struct Timeval Timeval;
+struct Timeval {
+	int32 tv_sec;
+	int32 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+	Timeval it_interval;
+	Timeval it_value;
+};
+
+typedef void sfxsave64;
+
+typedef void usavefpu;
+
+typedef struct Sigcontext Sigcontext;
+struct Sigcontext {
+	int32 sc_gs;
+	int32 sc_fs;
+	int32 sc_es;
+	int32 sc_ds;
+	int32 sc_edi;
+	int32 sc_esi;
+	int32 sc_ebp;
+	int32 sc_ebx;
+	int32 sc_edx;
+	int32 sc_ecx;
+	int32 sc_eax;
+	int32 sc_eip;
+	int32 sc_cs;
+	int32 sc_eflags;
+	int32 sc_esp;
+	int32 sc_ss;
+	int32 sc_onstack;
+	int32 sc_mask;
+	int32 sc_trapno;
+	int32 sc_err;
+	usavefpu *sc_fpstate;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/defs_netbsd_amd64.h b/src/pkg/runtime/defs_netbsd_amd64.h
new file mode 100644
index 0000000..27bf4b9
--- /dev/null
+++ b/src/pkg/runtime/defs_netbsd_amd64.h
@@ -0,0 +1,158 @@
+// godefs -f -m64 defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1000,
+	MAP_PRIVATE = 0x2,
+	MAP_FIXED = 0x10,
+	SA_SIGINFO = 0x40,
+	SA_RESTART = 0x2,
+	SA_ONSTACK = 0x1,
+	EINTR = 0x4,
+	SIGHUP = 0x1,
+	SIGINT = 0x2,
+	SIGQUIT = 0x3,
+	SIGILL = 0x4,
+	SIGTRAP = 0x5,
+	SIGABRT = 0x6,
+	SIGEMT = 0x7,
+	SIGFPE = 0x8,
+	SIGKILL = 0x9,
+	SIGBUS = 0xa,
+	SIGSEGV = 0xb,
+	SIGSYS = 0xc,
+	SIGPIPE = 0xd,
+	SIGALRM = 0xe,
+	SIGTERM = 0xf,
+	SIGURG = 0x10,
+	SIGSTOP = 0x11,
+	SIGTSTP = 0x12,
+	SIGCONT = 0x13,
+	SIGCHLD = 0x14,
+	SIGTTIN = 0x15,
+	SIGTTOU = 0x16,
+	SIGIO = 0x17,
+	SIGXCPU = 0x18,
+	SIGXFSZ = 0x19,
+	SIGVTALRM = 0x1a,
+	SIGPROF = 0x1b,
+	SIGWINCH = 0x1c,
+	SIGINFO = 0x1d,
+	SIGUSR1 = 0x1e,
+	SIGUSR2 = 0x1f,
+	FPE_INTDIV = 0x1,
+	FPE_INTOVF = 0x2,
+	FPE_FLTDIV = 0x3,
+	FPE_FLTOVF = 0x4,
+	FPE_FLTUND = 0x5,
+	FPE_FLTRES = 0x6,
+	FPE_FLTINV = 0x7,
+	FPE_FLTSUB = 0x8,
+	BUS_ADRALN = 0x1,
+	BUS_ADRERR = 0x2,
+	BUS_OBJERR = 0x3,
+	SEGV_MAPERR = 0x1,
+	SEGV_ACCERR = 0x2,
+	ITIMER_REAL = 0,
+	ITIMER_VIRTUAL = 0x1,
+	ITIMER_PROF = 0x2,
+};
+
+// Types
+#pragma pack on
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+	void *ss_sp;
+	uint64 ss_size;
+	int32 ss_flags;
+	byte pad_godefs_0[4];
+};
+
+typedef uint32 Sigset;
+
+typedef struct Siginfo Siginfo;
+struct Siginfo {
+	int32 si_signo;
+	int32 si_code;
+	int32 si_errno;
+	byte pad_godefs_0[4];
+	byte _data[120];
+};
+
+typedef union Sigval Sigval;
+union Sigval {
+	int32 sival_int;
+	void *sival_ptr;
+};
+
+typedef struct StackT StackT;
+struct StackT {
+	void *ss_sp;
+	uint64 ss_size;
+	int32 ss_flags;
+	byte pad_godefs_0[4];
+};
+
+typedef struct Timespec Timespec;
+struct Timespec {
+	int32 tv_sec;
+	byte pad_godefs_0[4];
+	int64 tv_nsec;
+};
+
+typedef struct Timeval Timeval;
+struct Timeval {
+	int64 tv_sec;
+	int64 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+	Timeval it_interval;
+	Timeval it_value;
+};
+
+typedef void sfxsave64;
+
+typedef void usavefpu;
+
+typedef struct Sigcontext Sigcontext;
+struct Sigcontext {
+	int64 sc_rdi;
+	int64 sc_rsi;
+	int64 sc_rdx;
+	int64 sc_rcx;
+	int64 sc_r8;
+	int64 sc_r9;
+	int64 sc_r10;
+	int64 sc_r11;
+	int64 sc_r12;
+	int64 sc_r13;
+	int64 sc_r14;
+	int64 sc_r15;
+	int64 sc_rbp;
+	int64 sc_rbx;
+	int64 sc_rax;
+	int64 sc_gs;
+	int64 sc_fs;
+	int64 sc_es;
+	int64 sc_ds;
+	int64 sc_trapno;
+	int64 sc_err;
+	int64 sc_rip;
+	int64 sc_cs;
+	int64 sc_rflags;
+	int64 sc_rsp;
+	int64 sc_ss;
+	sfxsave64 *sc_fpstate;
+	int32 sc_onstack;
+	int32 sc_mask;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/defs_openbsd.go b/src/pkg/runtime/defs_openbsd.go
new file mode 100644
index 0000000..47c30cf
--- /dev/null
+++ b/src/pkg/runtime/defs_openbsd.go
@@ -0,0 +1,111 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo.
+
+GOARCH=amd64 cgo -cdefs defs.go >amd64/defs.h
+GOARCH=386 cgo -cdefs defs.go >386/defs.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/unistd.h>
+#include <sys/signal.h>
+#include <errno.h>
+#include <signal.h>
+*/
+import "C"
+
+const (
+	PROT_NONE  = C.PROT_NONE
+	PROT_READ  = C.PROT_READ
+	PROT_WRITE = C.PROT_WRITE
+	PROT_EXEC  = C.PROT_EXEC
+
+	MAP_ANON    = C.MAP_ANON
+	MAP_PRIVATE = C.MAP_PRIVATE
+	MAP_FIXED   = C.MAP_FIXED
+
+	SA_SIGINFO = C.SA_SIGINFO
+	SA_RESTART = C.SA_RESTART
+	SA_ONSTACK = C.SA_ONSTACK
+
+	EINTR = C.EINTR
+
+	SIGHUP    = C.SIGHUP
+	SIGINT    = C.SIGINT
+	SIGQUIT   = C.SIGQUIT
+	SIGILL    = C.SIGILL
+	SIGTRAP   = C.SIGTRAP
+	SIGABRT   = C.SIGABRT
+	SIGEMT    = C.SIGEMT
+	SIGFPE    = C.SIGFPE
+	SIGKILL   = C.SIGKILL
+	SIGBUS    = C.SIGBUS
+	SIGSEGV   = C.SIGSEGV
+	SIGSYS    = C.SIGSYS
+	SIGPIPE   = C.SIGPIPE
+	SIGALRM   = C.SIGALRM
+	SIGTERM   = C.SIGTERM
+	SIGURG    = C.SIGURG
+	SIGSTOP   = C.SIGSTOP
+	SIGTSTP   = C.SIGTSTP
+	SIGCONT   = C.SIGCONT
+	SIGCHLD   = C.SIGCHLD
+	SIGTTIN   = C.SIGTTIN
+	SIGTTOU   = C.SIGTTOU
+	SIGIO     = C.SIGIO
+	SIGXCPU   = C.SIGXCPU
+	SIGXFSZ   = C.SIGXFSZ
+	SIGVTALRM = C.SIGVTALRM
+	SIGPROF   = C.SIGPROF
+	SIGWINCH  = C.SIGWINCH
+	SIGINFO   = C.SIGINFO
+	SIGUSR1   = C.SIGUSR1
+	SIGUSR2   = C.SIGUSR2
+
+	FPE_INTDIV = C.FPE_INTDIV
+	FPE_INTOVF = C.FPE_INTOVF
+	FPE_FLTDIV = C.FPE_FLTDIV
+	FPE_FLTOVF = C.FPE_FLTOVF
+	FPE_FLTUND = C.FPE_FLTUND
+	FPE_FLTRES = C.FPE_FLTRES
+	FPE_FLTINV = C.FPE_FLTINV
+	FPE_FLTSUB = C.FPE_FLTSUB
+
+	BUS_ADRALN = C.BUS_ADRALN
+	BUS_ADRERR = C.BUS_ADRERR
+	BUS_OBJERR = C.BUS_OBJERR
+
+	SEGV_MAPERR = C.SEGV_MAPERR
+	SEGV_ACCERR = C.SEGV_ACCERR
+
+	ITIMER_REAL    = C.ITIMER_REAL
+	ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+	ITIMER_PROF    = C.ITIMER_PROF
+)
+
+type Sigaltstack C.struct_sigaltstack
+type Sigset C.sigset_t
+type Siginfo C.siginfo_t
+type Sigval C.union_sigval
+
+type StackT C.stack_t
+
+type Timespec C.struct_timespec
+type Timeval C.struct_timeval
+type Itimerval C.struct_itimerval
+
+// This is a hack to avoid pulling in machine/fpu.h.
+type sfxsave64 struct{}
+type usavefpu struct{}
+
+type Sigcontext C.struct_sigcontext
diff --git a/src/pkg/runtime/defs_openbsd_386.h b/src/pkg/runtime/defs_openbsd_386.h
new file mode 100644
index 0000000..aff87fb
--- /dev/null
+++ b/src/pkg/runtime/defs_openbsd_386.h
@@ -0,0 +1,146 @@
+// godefs -f -m32 defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1000,
+	MAP_PRIVATE = 0x2,
+	MAP_FIXED = 0x10,
+	SA_SIGINFO = 0x40,
+	SA_RESTART = 0x2,
+	SA_ONSTACK = 0x1,
+	EINTR = 0x4,
+	SIGHUP = 0x1,
+	SIGINT = 0x2,
+	SIGQUIT = 0x3,
+	SIGILL = 0x4,
+	SIGTRAP = 0x5,
+	SIGABRT = 0x6,
+	SIGEMT = 0x7,
+	SIGFPE = 0x8,
+	SIGKILL = 0x9,
+	SIGBUS = 0xa,
+	SIGSEGV = 0xb,
+	SIGSYS = 0xc,
+	SIGPIPE = 0xd,
+	SIGALRM = 0xe,
+	SIGTERM = 0xf,
+	SIGURG = 0x10,
+	SIGSTOP = 0x11,
+	SIGTSTP = 0x12,
+	SIGCONT = 0x13,
+	SIGCHLD = 0x14,
+	SIGTTIN = 0x15,
+	SIGTTOU = 0x16,
+	SIGIO = 0x17,
+	SIGXCPU = 0x18,
+	SIGXFSZ = 0x19,
+	SIGVTALRM = 0x1a,
+	SIGPROF = 0x1b,
+	SIGWINCH = 0x1c,
+	SIGINFO = 0x1d,
+	SIGUSR1 = 0x1e,
+	SIGUSR2 = 0x1f,
+	FPE_INTDIV = 0x1,
+	FPE_INTOVF = 0x2,
+	FPE_FLTDIV = 0x3,
+	FPE_FLTOVF = 0x4,
+	FPE_FLTUND = 0x5,
+	FPE_FLTRES = 0x6,
+	FPE_FLTINV = 0x7,
+	FPE_FLTSUB = 0x8,
+	BUS_ADRALN = 0x1,
+	BUS_ADRERR = 0x2,
+	BUS_OBJERR = 0x3,
+	SEGV_MAPERR = 0x1,
+	SEGV_ACCERR = 0x2,
+	ITIMER_REAL = 0,
+	ITIMER_VIRTUAL = 0x1,
+	ITIMER_PROF = 0x2,
+};
+
+// Types
+#pragma pack on
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+	void *ss_sp;
+	uint32 ss_size;
+	int32 ss_flags;
+};
+
+typedef uint32 Sigset;
+
+typedef struct Siginfo Siginfo;
+struct Siginfo {
+	int32 si_signo;
+	int32 si_code;
+	int32 si_errno;
+	byte _data[116];
+};
+
+typedef union Sigval Sigval;
+union Sigval {
+	int32 sival_int;
+	void *sival_ptr;
+};
+
+typedef struct StackT StackT;
+struct StackT {
+	void *ss_sp;
+	uint32 ss_size;
+	int32 ss_flags;
+};
+
+typedef struct Timespec Timespec;
+struct Timespec {
+	int32 tv_sec;
+	int32 tv_nsec;
+};
+
+typedef struct Timeval Timeval;
+struct Timeval {
+	int32 tv_sec;
+	int32 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+	Timeval it_interval;
+	Timeval it_value;
+};
+
+typedef void sfxsave64;
+
+typedef void usavefpu;
+
+typedef struct Sigcontext Sigcontext;
+struct Sigcontext {
+	int32 sc_gs;
+	int32 sc_fs;
+	int32 sc_es;
+	int32 sc_ds;
+	int32 sc_edi;
+	int32 sc_esi;
+	int32 sc_ebp;
+	int32 sc_ebx;
+	int32 sc_edx;
+	int32 sc_ecx;
+	int32 sc_eax;
+	int32 sc_eip;
+	int32 sc_cs;
+	int32 sc_eflags;
+	int32 sc_esp;
+	int32 sc_ss;
+	int32 sc_onstack;
+	int32 sc_mask;
+	int32 sc_trapno;
+	int32 sc_err;
+	usavefpu *sc_fpstate;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/defs_openbsd_amd64.h b/src/pkg/runtime/defs_openbsd_amd64.h
new file mode 100644
index 0000000..27bf4b9
--- /dev/null
+++ b/src/pkg/runtime/defs_openbsd_amd64.h
@@ -0,0 +1,158 @@
+// godefs -f -m64 defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1000,
+	MAP_PRIVATE = 0x2,
+	MAP_FIXED = 0x10,
+	SA_SIGINFO = 0x40,
+	SA_RESTART = 0x2,
+	SA_ONSTACK = 0x1,
+	EINTR = 0x4,
+	SIGHUP = 0x1,
+	SIGINT = 0x2,
+	SIGQUIT = 0x3,
+	SIGILL = 0x4,
+	SIGTRAP = 0x5,
+	SIGABRT = 0x6,
+	SIGEMT = 0x7,
+	SIGFPE = 0x8,
+	SIGKILL = 0x9,
+	SIGBUS = 0xa,
+	SIGSEGV = 0xb,
+	SIGSYS = 0xc,
+	SIGPIPE = 0xd,
+	SIGALRM = 0xe,
+	SIGTERM = 0xf,
+	SIGURG = 0x10,
+	SIGSTOP = 0x11,
+	SIGTSTP = 0x12,
+	SIGCONT = 0x13,
+	SIGCHLD = 0x14,
+	SIGTTIN = 0x15,
+	SIGTTOU = 0x16,
+	SIGIO = 0x17,
+	SIGXCPU = 0x18,
+	SIGXFSZ = 0x19,
+	SIGVTALRM = 0x1a,
+	SIGPROF = 0x1b,
+	SIGWINCH = 0x1c,
+	SIGINFO = 0x1d,
+	SIGUSR1 = 0x1e,
+	SIGUSR2 = 0x1f,
+	FPE_INTDIV = 0x1,
+	FPE_INTOVF = 0x2,
+	FPE_FLTDIV = 0x3,
+	FPE_FLTOVF = 0x4,
+	FPE_FLTUND = 0x5,
+	FPE_FLTRES = 0x6,
+	FPE_FLTINV = 0x7,
+	FPE_FLTSUB = 0x8,
+	BUS_ADRALN = 0x1,
+	BUS_ADRERR = 0x2,
+	BUS_OBJERR = 0x3,
+	SEGV_MAPERR = 0x1,
+	SEGV_ACCERR = 0x2,
+	ITIMER_REAL = 0,
+	ITIMER_VIRTUAL = 0x1,
+	ITIMER_PROF = 0x2,
+};
+
+// Types
+#pragma pack on
+
+typedef struct Sigaltstack Sigaltstack;
+struct Sigaltstack {
+	void *ss_sp;
+	uint64 ss_size;
+	int32 ss_flags;
+	byte pad_godefs_0[4];
+};
+
+typedef uint32 Sigset;
+
+typedef struct Siginfo Siginfo;
+struct Siginfo {
+	int32 si_signo;
+	int32 si_code;
+	int32 si_errno;
+	byte pad_godefs_0[4];
+	byte _data[120];
+};
+
+typedef union Sigval Sigval;
+union Sigval {
+	int32 sival_int;
+	void *sival_ptr;
+};
+
+typedef struct StackT StackT;
+struct StackT {
+	void *ss_sp;
+	uint64 ss_size;
+	int32 ss_flags;
+	byte pad_godefs_0[4];
+};
+
+typedef struct Timespec Timespec;
+struct Timespec {
+	int32 tv_sec;
+	byte pad_godefs_0[4];
+	int64 tv_nsec;
+};
+
+typedef struct Timeval Timeval;
+struct Timeval {
+	int64 tv_sec;
+	int64 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+	Timeval it_interval;
+	Timeval it_value;
+};
+
+typedef void sfxsave64;
+
+typedef void usavefpu;
+
+typedef struct Sigcontext Sigcontext;
+struct Sigcontext {
+	int64 sc_rdi;
+	int64 sc_rsi;
+	int64 sc_rdx;
+	int64 sc_rcx;
+	int64 sc_r8;
+	int64 sc_r9;
+	int64 sc_r10;
+	int64 sc_r11;
+	int64 sc_r12;
+	int64 sc_r13;
+	int64 sc_r14;
+	int64 sc_r15;
+	int64 sc_rbp;
+	int64 sc_rbx;
+	int64 sc_rax;
+	int64 sc_gs;
+	int64 sc_fs;
+	int64 sc_es;
+	int64 sc_ds;
+	int64 sc_trapno;
+	int64 sc_err;
+	int64 sc_rip;
+	int64 sc_cs;
+	int64 sc_rflags;
+	int64 sc_rsp;
+	int64 sc_ss;
+	sfxsave64 *sc_fpstate;
+	int32 sc_onstack;
+	int32 sc_mask;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/plan9/386/defs.h b/src/pkg/runtime/defs_plan9_386.h
similarity index 100%
rename from src/pkg/runtime/plan9/386/defs.h
rename to src/pkg/runtime/defs_plan9_386.h
diff --git a/src/pkg/runtime/defs_windows.go b/src/pkg/runtime/defs_windows.go
new file mode 100644
index 0000000..0d525b9
--- /dev/null
+++ b/src/pkg/runtime/defs_windows.go
@@ -0,0 +1,66 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo.
+
+GOARCH=amd64 cgo -cdefs defs.go >amd64/defs.h
+GOARCH=386 cgo -cdefs defs.go >386/defs.h
+*/
+
+package runtime
+
+/*
+#include <signal.h>
+#include <stdarg.h>
+#include <windef.h>
+#include <winbase.h>
+#include <wincon.h>
+
+#ifndef _X86_
+typedef struct {} FLOATING_SAVE_AREA;
+#endif
+#ifndef _AMD64_
+typedef struct {} M128A;
+#endif
+*/
+import "C"
+
+const (
+	PROT_NONE  = 0
+	PROT_READ  = 1
+	PROT_WRITE = 2
+	PROT_EXEC  = 4
+
+	MAP_ANON    = 1
+	MAP_PRIVATE = 2
+
+	DUPLICATE_SAME_ACCESS   = C.DUPLICATE_SAME_ACCESS
+	THREAD_PRIORITY_HIGHEST = C.THREAD_PRIORITY_HIGHEST
+
+	SIGINT           = C.SIGINT
+	CTRL_C_EVENT     = C.CTRL_C_EVENT
+	CTRL_BREAK_EVENT = C.CTRL_BREAK_EVENT
+
+	CONTEXT_CONTROL = C.CONTEXT_CONTROL
+	CONTEXT_FULL    = C.CONTEXT_FULL
+
+	EXCEPTION_ACCESS_VIOLATION     = C.STATUS_ACCESS_VIOLATION
+	EXCEPTION_BREAKPOINT           = C.STATUS_BREAKPOINT
+	EXCEPTION_FLT_DENORMAL_OPERAND = C.STATUS_FLOAT_DENORMAL_OPERAND
+	EXCEPTION_FLT_DIVIDE_BY_ZERO   = C.STATUS_FLOAT_DIVIDE_BY_ZERO
+	EXCEPTION_FLT_INEXACT_RESULT   = C.STATUS_FLOAT_INEXACT_RESULT
+	EXCEPTION_FLT_OVERFLOW         = C.STATUS_FLOAT_OVERFLOW
+	EXCEPTION_FLT_UNDERFLOW        = C.STATUS_FLOAT_UNDERFLOW
+	EXCEPTION_INT_DIVIDE_BY_ZERO   = C.STATUS_INTEGER_DIVIDE_BY_ZERO
+	EXCEPTION_INT_OVERFLOW         = C.STATUS_INTEGER_OVERFLOW
+)
+
+type SystemInfo C.SYSTEM_INFO
+type ExceptionRecord C.EXCEPTION_RECORD
+type FloatingSaveArea C.FLOATING_SAVE_AREA
+type M128a C.M128A
+type Context C.CONTEXT
diff --git a/src/pkg/runtime/defs_windows_386.h b/src/pkg/runtime/defs_windows_386.h
new file mode 100644
index 0000000..e64a82f
--- /dev/null
+++ b/src/pkg/runtime/defs_windows_386.h
@@ -0,0 +1,99 @@
+// c:\Users\Hector\Code\go\bin\godefs.exe defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1,
+	MAP_PRIVATE = 0x2,
+	DUPLICATE_SAME_ACCESS = 0x2,
+	THREAD_PRIORITY_HIGHEST = 0x2,
+	SIGINT = 0x2,
+	CTRL_C_EVENT = 0,
+	CTRL_BREAK_EVENT = 0x1,
+	CONTEXT_CONTROL = 0x10001,
+	CONTEXT_FULL = 0x10007,
+	EXCEPTION_ACCESS_VIOLATION = 0xc0000005,
+	EXCEPTION_BREAKPOINT = 0x80000003,
+	EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d,
+	EXCEPTION_FLT_DIVIDE_BY_ZERO = 0xc000008e,
+	EXCEPTION_FLT_INEXACT_RESULT = 0xc000008f,
+	EXCEPTION_FLT_OVERFLOW = 0xc0000091,
+	EXCEPTION_FLT_UNDERFLOW = 0xc0000093,
+	EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094,
+	EXCEPTION_INT_OVERFLOW = 0xc0000095,
+};
+
+// Types
+#pragma pack on
+
+typedef struct SystemInfo SystemInfo;
+struct SystemInfo {
+	byte Pad_godefs_0[4];
+	uint32 dwPageSize;
+	void *lpMinimumApplicationAddress;
+	void *lpMaximumApplicationAddress;
+	uint32 dwActiveProcessorMask;
+	uint32 dwNumberOfProcessors;
+	uint32 dwProcessorType;
+	uint32 dwAllocationGranularity;
+	uint16 wProcessorLevel;
+	uint16 wProcessorRevision;
+};
+
+typedef struct ExceptionRecord ExceptionRecord;
+struct ExceptionRecord {
+	uint32 ExceptionCode;
+	uint32 ExceptionFlags;
+	ExceptionRecord *ExceptionRecord;
+	void *ExceptionAddress;
+	uint32 NumberParameters;
+	uint32 ExceptionInformation[15];
+};
+
+typedef struct FloatingSaveArea FloatingSaveArea;
+struct FloatingSaveArea {
+	uint32 ControlWord;
+	uint32 StatusWord;
+	uint32 TagWord;
+	uint32 ErrorOffset;
+	uint32 ErrorSelector;
+	uint32 DataOffset;
+	uint32 DataSelector;
+	uint8 RegisterArea[80];
+	uint32 Cr0NpxState;
+};
+
+typedef struct Context Context;
+struct Context {
+	uint32 ContextFlags;
+	uint32 Dr0;
+	uint32 Dr1;
+	uint32 Dr2;
+	uint32 Dr3;
+	uint32 Dr6;
+	uint32 Dr7;
+	FloatingSaveArea FloatSave;
+	uint32 SegGs;
+	uint32 SegFs;
+	uint32 SegEs;
+	uint32 SegDs;
+	uint32 Edi;
+	uint32 Esi;
+	uint32 Ebx;
+	uint32 Edx;
+	uint32 Ecx;
+	uint32 Eax;
+	uint32 Ebp;
+	uint32 Eip;
+	uint32 SegCs;
+	uint32 EFlags;
+	uint32 Esp;
+	uint32 SegSs;
+	uint8 ExtendedRegisters[512];
+};
+#pragma pack off
diff --git a/src/pkg/runtime/defs_windows_amd64.h b/src/pkg/runtime/defs_windows_amd64.h
new file mode 100644
index 0000000..da4c19d
--- /dev/null
+++ b/src/pkg/runtime/defs_windows_amd64.h
@@ -0,0 +1,114 @@
+// c:\go\bin\godefs.exe -f -m64 defs.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+// Constants
+enum {
+	PROT_NONE = 0,
+	PROT_READ = 0x1,
+	PROT_WRITE = 0x2,
+	PROT_EXEC = 0x4,
+	MAP_ANON = 0x1,
+	MAP_PRIVATE = 0x2,
+	DUPLICATE_SAME_ACCESS = 0x2,
+	THREAD_PRIORITY_HIGHEST = 0x2,
+	SIGINT = 0x2,
+	CTRL_C_EVENT = 0,
+	CTRL_BREAK_EVENT = 0x1,
+	CONTEXT_CONTROL = 0x100001,
+	CONTEXT_FULL = 0x10000b,
+	EXCEPTION_ACCESS_VIOLATION = 0xc0000005,
+	EXCEPTION_BREAKPOINT = 0x80000003,
+	EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d,
+	EXCEPTION_FLT_DIVIDE_BY_ZERO = 0xc000008e,
+	EXCEPTION_FLT_INEXACT_RESULT = 0xc000008f,
+	EXCEPTION_FLT_OVERFLOW = 0xc0000091,
+	EXCEPTION_FLT_UNDERFLOW = 0xc0000093,
+	EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094,
+	EXCEPTION_INT_OVERFLOW = 0xc0000095,
+};
+
+// Types
+#pragma pack on
+
+typedef struct SystemInfo SystemInfo;
+struct SystemInfo {
+	byte Pad_godefs_0[4];
+	uint32 dwPageSize;
+	void *lpMinimumApplicationAddress;
+	void *lpMaximumApplicationAddress;
+	uint64 dwActiveProcessorMask;
+	uint32 dwNumberOfProcessors;
+	uint32 dwProcessorType;
+	uint32 dwAllocationGranularity;
+	uint16 wProcessorLevel;
+	uint16 wProcessorRevision;
+};
+
+typedef struct ExceptionRecord ExceptionRecord;
+struct ExceptionRecord {
+	uint32 ExceptionCode;
+	uint32 ExceptionFlags;
+	ExceptionRecord *ExceptionRecord;
+	void *ExceptionAddress;
+	uint32 NumberParameters;
+	byte pad_godefs_0[4];
+	uint64 ExceptionInformation[15];
+};
+
+typedef struct M128a M128a;
+struct M128a {
+	uint64 Low;
+	int64 High;
+};
+
+typedef struct Context Context;
+struct Context {
+	uint64 P1Home;
+	uint64 P2Home;
+	uint64 P3Home;
+	uint64 P4Home;
+	uint64 P5Home;
+	uint64 P6Home;
+	uint32 ContextFlags;
+	uint32 MxCsr;
+	uint16 SegCs;
+	uint16 SegDs;
+	uint16 SegEs;
+	uint16 SegFs;
+	uint16 SegGs;
+	uint16 SegSs;
+	uint32 EFlags;
+	uint64 Dr0;
+	uint64 Dr1;
+	uint64 Dr2;
+	uint64 Dr3;
+	uint64 Dr6;
+	uint64 Dr7;
+	uint64 Rax;
+	uint64 Rcx;
+	uint64 Rdx;
+	uint64 Rbx;
+	uint64 Rsp;
+	uint64 Rbp;
+	uint64 Rsi;
+	uint64 Rdi;
+	uint64 R8;
+	uint64 R9;
+	uint64 R10;
+	uint64 R11;
+	uint64 R12;
+	uint64 R13;
+	uint64 R14;
+	uint64 R15;
+	uint64 Rip;
+	byte Pad_godefs_0[512];
+	M128a VectorRegister[26];
+	uint64 VectorControl;
+	uint64 DebugControl;
+	uint64 LastBranchToRip;
+	uint64 LastBranchFromRip;
+	uint64 LastExceptionToRip;
+	uint64 LastExceptionFromRip;
+};
+#pragma pack off
diff --git a/src/pkg/runtime/error.go b/src/pkg/runtime/error.go
index 6c37f88..4b0ee49 100644
--- a/src/pkg/runtime/error.go
+++ b/src/pkg/runtime/error.go
@@ -6,11 +6,11 @@ package runtime
 
 // The Error interface identifies a run time error.
 type Error interface {
-	String() string
+	error
 
 	// RuntimeError is a no-op function but
 	// serves to distinguish types that are runtime
-	// errors from ordinary os.Errors: a type is a
+	// errors from ordinary errors: a type is a
 	// runtime error if it has a RuntimeError method.
 	RuntimeError()
 }
@@ -28,7 +28,7 @@ type TypeAssertionError struct {
 
 func (*TypeAssertionError) RuntimeError() {}
 
-func (e *TypeAssertionError) String() string {
+func (e *TypeAssertionError) Error() string {
 	inter := e.interfaceString
 	if inter == "" {
 		inter = "interface"
@@ -98,7 +98,7 @@ type errorString string
 
 func (e errorString) RuntimeError() {}
 
-func (e errorString) String() string {
+func (e errorString) Error() string {
 	return "runtime error: " + string(e)
 }
 
@@ -123,6 +123,8 @@ func printany(i interface{}) {
 		print("nil")
 	case stringer:
 		print(v.String())
+	case error:
+		print(v.Error())
 	case int:
 		print(v)
 	case string:
diff --git a/src/pkg/runtime/export_test.go b/src/pkg/runtime/export_test.go
index 53c5fcb..c603e1b 100644
--- a/src/pkg/runtime/export_test.go
+++ b/src/pkg/runtime/export_test.go
@@ -18,6 +18,8 @@ var F64toint = f64toint
 
 func entersyscall()
 func exitsyscall()
+func golockedOSThread() bool
 
 var Entersyscall = entersyscall
 var Exitsyscall = exitsyscall
+var LockedOSThread = golockedOSThread
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go
index 9da3423..eafa2f1 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/pkg/runtime/extern.go
@@ -19,15 +19,15 @@ func Gosched()
 func Goexit()
 
 // Caller reports file and line number information about function invocations on
-// the calling goroutine's stack.  The argument skip is the number of stack frames to
-// ascend, with 0 identifying the the caller of Caller.  The return values report the
+// the calling goroutine's stack.  The argument skip is the number of stack frames
+// to ascend, with 0 identifying the caller of Caller.  The return values report the
 // program counter, file name, and line number within the file of the corresponding
 // call.  The boolean ok is false if it was not possible to recover the information.
 func Caller(skip int) (pc uintptr, file string, line int, ok bool)
 
 // Callers fills the slice pc with the program counters of function invocations
 // on the calling goroutine's stack.  The argument skip is the number of stack frames
-// to skip before recording in pc, with 0 starting at the caller of Caller.
+// to skip before recording in pc, with 0 starting at the caller of Callers.
 // It returns the number of entries written to pc.
 func Callers(skip int, pc []uintptr) int
 
@@ -59,51 +59,12 @@ func (f *Func) Entry() uintptr { return f.entry }
 // The result will not be accurate if pc is not a program
 // counter within f.
 func (f *Func) FileLine(pc uintptr) (file string, line int) {
-	// NOTE(rsc): If you edit this function, also edit
-	// symtab.c:/^funcline.  That function also has the
-	// comments explaining the logic.
-	targetpc := pc
-
-	var pcQuant uintptr = 1
-	if GOARCH == "arm" {
-		pcQuant = 4
-	}
-
-	p := f.pcln
-	pc = f.pc0
-	line = int(f.ln0)
-	i := 0
-	//print("FileLine start pc=", pc, " targetpc=", targetpc, " line=", line,
-	//	" tab=", p, " ", p[0], " quant=", pcQuant, " GOARCH=", GOARCH, "\n")
-	for {
-		for i < len(p) && p[i] > 128 {
-			pc += pcQuant * uintptr(p[i]-128)
-			i++
-		}
-		//print("pc<", pc, " targetpc=", targetpc, " line=", line, "\n")
-		if pc > targetpc || i >= len(p) {
-			break
-		}
-		if p[i] == 0 {
-			if i+5 > len(p) {
-				break
-			}
-			line += int(p[i+1]<<24) | int(p[i+2]<<16) | int(p[i+3]<<8) | int(p[i+4])
-			i += 5
-		} else if p[i] <= 64 {
-			line += int(p[i])
-			i++
-		} else {
-			line -= int(p[i] - 64)
-			i++
-		}
-		//print("pc=", pc, " targetpc=", targetpc, " line=", line, "\n")
-		pc += pcQuant
-	}
-	file = f.src
-	return
+	return funcline_go(f, pc)
 }
 
+// implemented in symtab.c
+func funcline_go(*Func, uintptr) (string, int)
+
 // mid returns the current os thread (m) id.
 func mid() uint32
 
@@ -131,8 +92,8 @@ func Semrelease(s *uint32)
 // The argument x must be a pointer to an object allocated by
 // calling new or by taking the address of a composite literal.
 // The argument f must be a function that takes a single argument
-// of x's type and returns no arguments.  If either of these is not
-// true, SetFinalizer aborts the program.
+// of x's type and can have arbitrary ignored return values.
+// If either of these is not true, SetFinalizer aborts the program.
 //
 // Finalizers are run in dependency order: if A points at B, both have
 // finalizers, and they are otherwise unreachable, only the finalizer
@@ -156,9 +117,6 @@ func Semrelease(s *uint32)
 // A single goroutine runs all finalizers for a program, sequentially.
 // If a finalizer must run for a long time, it should do so by starting
 // a new goroutine.
-//
-// TODO(rsc): allow f to have (ignored) return values
-//
 func SetFinalizer(x, f interface{})
 
 func getgoroot() string
diff --git a/src/pkg/runtime/freebsd/386/defs.h b/src/pkg/runtime/freebsd/386/defs.h
deleted file mode 100644
index ae12b20..0000000
--- a/src/pkg/runtime/freebsd/386/defs.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// godefs -f -m32 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	UMTX_OP_WAIT = 0x2,
-	UMTX_OP_WAKE = 0x3,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x2,
-	FPE_INTOVF = 0x1,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Rtprio Rtprio;
-struct Rtprio {
-	uint16 type;
-	uint16 prio;
-};
-
-typedef struct ThrParam ThrParam;
-struct ThrParam {
-	void *start_func;
-	void *arg;
-	int8 *stack_base;
-	uint32 stack_size;
-	int8 *tls_base;
-	uint32 tls_size;
-	int32 *child_tid;
-	int32 *parent_tid;
-	int32 flags;
-	Rtprio *rtp;
-	void* spare[3];
-};
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	int8 *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
-};
-
-typedef struct Sigset Sigset;
-struct Sigset {
-	uint32 __bits[4];
-};
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
-	int32 sigval_int;
-	void *sigval_ptr;
-};
-
-typedef struct StackT StackT;
-struct StackT {
-	int8 *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	int32 si_pid;
-	uint32 si_uid;
-	int32 si_status;
-	void *si_addr;
-	Sigval si_value;
-	byte _reason[32];
-};
-
-typedef struct Mcontext Mcontext;
-struct Mcontext {
-	int32 mc_onstack;
-	int32 mc_gs;
-	int32 mc_fs;
-	int32 mc_es;
-	int32 mc_ds;
-	int32 mc_edi;
-	int32 mc_esi;
-	int32 mc_ebp;
-	int32 mc_isp;
-	int32 mc_ebx;
-	int32 mc_edx;
-	int32 mc_ecx;
-	int32 mc_eax;
-	int32 mc_trapno;
-	int32 mc_err;
-	int32 mc_eip;
-	int32 mc_cs;
-	int32 mc_eflags;
-	int32 mc_esp;
-	int32 mc_ss;
-	int32 mc_len;
-	int32 mc_fpformat;
-	int32 mc_ownedfp;
-	int32 mc_spare1[1];
-	int32 mc_fpstate[128];
-	int32 mc_fsbase;
-	int32 mc_gsbase;
-	int32 mc_spare2[6];
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
-	Sigset uc_sigmask;
-	Mcontext uc_mcontext;
-	Ucontext *uc_link;
-	StackT uc_stack;
-	int32 uc_flags;
-	int32 __spare__[4];
-	byte pad_godefs_0[12];
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int32 tv_sec;
-	int32 tv_usec;
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/freebsd/386/signal.c b/src/pkg/runtime/freebsd/386/signal.c
deleted file mode 100644
index 2fe7ecd..0000000
--- a/src/pkg/runtime/freebsd/386/signal.c
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
-	union {
-		void    (*__sa_handler)(int32);
-		void    (*__sa_sigaction)(int32, Siginfo*, void *);
-	} __sigaction_u;		/* signal handler */
-	int32	sa_flags;		/* see signal options below */
-	int64	sa_mask;		/* signal mask to apply */
-} Sigaction;
-
-void
-runtime·dumpregs(Mcontext *r)
-{
-	runtime·printf("eax     %x\n", r->mc_eax);
-	runtime·printf("ebx     %x\n", r->mc_ebx);
-	runtime·printf("ecx     %x\n", r->mc_ecx);
-	runtime·printf("edx     %x\n", r->mc_edx);
-	runtime·printf("edi     %x\n", r->mc_edi);
-	runtime·printf("esi     %x\n", r->mc_esi);
-	runtime·printf("ebp     %x\n", r->mc_ebp);
-	runtime·printf("esp     %x\n", r->mc_esp);
-	runtime·printf("eip     %x\n", r->mc_eip);
-	runtime·printf("eflags  %x\n", r->mc_eflags);
-	runtime·printf("cs      %x\n", r->mc_cs);
-	runtime·printf("fs      %x\n", r->mc_fs);
-	runtime·printf("gs      %x\n", r->mc_gs);
-}
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Ucontext *uc;
-	Mcontext *r;
-	uintptr *sp;
-
-	uc = context;
-	r = &uc->uc_mcontext;
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->mc_eip, (uint8*)r->mc_esp, nil, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = (uintptr)info->si_addr;
-		gp->sigpc = r->mc_eip;
-
-		// Only push runtime·sigpanic if r->mc_eip != 0.
-		// If r->mc_eip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->mc_eip != 0) {
-			sp = (uintptr*)r->mc_esp;
-			*--sp = r->mc_eip;
-			r->mc_esp = (uintptr)sp;
-		}
-		r->mc_eip = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG)
-		runtime·printf("Signal %d\n", sig);
-	else
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-
-	runtime·printf("PC=%X\n", r->mc_eip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->mc_eip, (void*)r->mc_esp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-}
-
-// Called from kernel on signal stack, so no stack split.
-#pragma textflag 7
-void
-runtime·sigignore(void)
-{
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	Sigaltstack st;
-
-	st.ss_sp = (int8*)p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	if (fn == runtime·sighandler)
-		fn = (void*)runtime·sigtramp;
-	sa.__sigaction_u.__sa_sigaction = (void*)fn;
-	runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
diff --git a/src/pkg/runtime/freebsd/386/sys.s b/src/pkg/runtime/freebsd/386/sys.s
deleted file mode 100644
index 765e2fc..0000000
--- a/src/pkg/runtime/freebsd/386/sys.s
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// System calls and other sys.stuff for 386, FreeBSD
-// /usr/src/sys/kern/syscalls.master for syscall numbers.
-//
-
-#include "386/asm.h"
-	
-TEXT runtime·sys_umtx_op(SB),7,$-4
-	MOVL	$454, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·thr_new(SB),7,$-4
-	MOVL	$455, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·thr_start(SB),7,$0
-	MOVL	mm+0(FP), AX
-	MOVL	m_g0(AX), BX
-	LEAL	m_tls(AX), BP
-	MOVL	0(BP), DI
-	ADDL	$7, DI
-	PUSHAL
-	PUSHL	$32
-	PUSHL	BP
-	PUSHL	DI
-	CALL	runtime·setldt(SB)
-	POPL	AX
-	POPL	AX
-	POPL	AX
-	POPAL
-	get_tls(CX)
-	MOVL	BX, g(CX)
-	
-	MOVL	AX, m(CX)
-	CALL	runtime·stackcheck(SB)		// smashes AX
-	CALL	runtime·mstart(SB)
-	MOVL	0, AX			// crash (not reached)
-
-// Exit the entire program (like C exit)
-TEXT runtime·exit(SB),7,$-4
-	MOVL	$1, AX
-	INT	$0x80
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·exit1(SB),7,$-4
-	MOVL	$431, AX
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·write(SB),7,$-4
-	MOVL	$4, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·raisesigpipe(SB),7,$12
-	// thr_self(&8(SP))
-	LEAL	8(SP), AX
-	MOVL	AX, 0(SP)
-	MOVL	$432, AX
-	INT	$0x80
-	// thr_kill(self, SIGPIPE)
-	MOVL	8(SP), AX
-	MOVL	AX, 0(SP)
-	MOVL	$13, 4(SP)
-	MOVL	$433, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·notok(SB),7,$0
-	MOVL	$0xf1, 0xf1
-	RET
-
-TEXT runtime·mmap(SB),7,$32
-	LEAL arg0+0(FP), SI
-	LEAL	4(SP), DI
-	CLD
-	MOVSL
-	MOVSL
-	MOVSL
-	MOVSL
-	MOVSL
-	MOVSL
-	MOVL	$0, AX	// top 64 bits of file offset
-	STOSL
-	MOVL	$477, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·munmap(SB),7,$-4
-	MOVL	$73, AX
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·setitimer(SB), 7, $-4
-	MOVL	$83, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·gettime(SB), 7, $32
-	MOVL	$116, AX
-	LEAL	12(SP), BX
-	MOVL	BX, 4(SP)
-	MOVL	$0, 8(SP)
-	INT	$0x80
-
-	MOVL	12(SP), BX	// sec
-	MOVL	sec+0(FP), DI
-	MOVL	BX, (DI)
-	MOVL	$0, 4(DI)	// zero extend 32 -> 64 bits
-
-	MOVL	16(SP), BX	// usec
-	MOVL	usec+4(FP), DI
-	MOVL	BX, (DI)
-	RET
-
-TEXT runtime·sigaction(SB),7,$-4
-	MOVL	$416, AX
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·sigtramp(SB),7,$44
-	get_tls(CX)
-
-	// save g
-	MOVL	g(CX), DI
-	MOVL	DI, 20(SP)
-	
-	// g = m->gsignal
-	MOVL	m(CX), BX
-	MOVL	m_gsignal(BX), BX
-	MOVL	BX, g(CX)
-
-	// copy arguments for call to sighandler
-	MOVL	signo+0(FP), BX
-	MOVL	BX, 0(SP)
-	MOVL	info+4(FP), BX
-	MOVL	BX, 4(SP)
-	MOVL	context+8(FP), BX
-	MOVL	BX, 8(SP)
-	MOVL	DI, 12(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(CX)
-	MOVL	20(SP), BX
-	MOVL	BX, g(CX)
-	
-	// call sigreturn
-	MOVL	context+8(FP), AX
-	MOVL	$0, 0(SP)	// syscall gap
-	MOVL	AX, 4(SP)
-	MOVL	$417, AX	// sigreturn(ucontext)
-	INT	$0x80
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·sigaltstack(SB),7,$0
-	MOVL	$53, AX
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-/*
-descriptor entry format for system call
-is the native machine format, ugly as it is:
-
-	2-byte limit
-	3-byte base
-	1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type
-	1-byte: 0x80=limit is *4k, 0x40=32-bit operand size,
-		0x0F=4 more bits of limit
-	1 byte: 8 more bits of base
-
-int i386_get_ldt(int, union ldt_entry *, int);
-int i386_set_ldt(int, const union ldt_entry *, int);
-
-*/
-
-// setldt(int entry, int address, int limit)
-TEXT runtime·setldt(SB),7,$32
-	MOVL	address+4(FP), BX	// aka base
-	// see comment in linux/386/sys.s; freebsd is similar
-	ADDL	$0x8, BX
-
-	// set up data_desc
-	LEAL	16(SP), AX	// struct data_desc
-	MOVL	$0, 0(AX)
-	MOVL	$0, 4(AX)
-
-	MOVW	BX, 2(AX)
-	SHRL	$16, BX
-	MOVB	BX, 4(AX)
-	SHRL	$8, BX
-	MOVB	BX, 7(AX)
-
-	MOVW	$0xffff, 0(AX)
-	MOVB	$0xCF, 6(AX)	// 32-bit operand, 4k limit unit, 4 more bits of limit
-
-	MOVB	$0xF2, 5(AX)	// r/w data descriptor, dpl=3, present
-
-	// call i386_set_ldt(entry, desc, 1)
-	MOVL	$0xffffffff, 0(SP)	// auto-allocate entry and return in AX
-	MOVL	AX, 4(SP)
-	MOVL	$1, 8(SP)
-	CALL	runtime·i386_set_ldt(SB)
-
-	// compute segment selector - (entry*8+7)
-	SHLL	$3, AX
-	ADDL	$7, AX
-	MOVW	AX, GS
-	RET
-
-TEXT runtime·i386_set_ldt(SB),7,$16
-	LEAL	args+0(FP), AX	// 0(FP) == 4(SP) before SP got moved
-	MOVL	$0, 0(SP)	// syscall gap
-	MOVL	$1, 4(SP)
-	MOVL	AX, 8(SP)
-	MOVL	$165, AX
-	INT	$0x80
-	CMPL	AX, $0xfffff001
-	JLS	2(PC)
-	INT	$3
-	RET
-
-GLOBL runtime·tlsoffset(SB),$4
diff --git a/src/pkg/runtime/freebsd/amd64/defs.h b/src/pkg/runtime/freebsd/amd64/defs.h
deleted file mode 100644
index b101b19..0000000
--- a/src/pkg/runtime/freebsd/amd64/defs.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// godefs -f -m64 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	UMTX_OP_WAIT = 0x2,
-	UMTX_OP_WAKE = 0x3,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x2,
-	FPE_INTOVF = 0x1,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Rtprio Rtprio;
-struct Rtprio {
-	uint16 type;
-	uint16 prio;
-};
-
-typedef struct ThrParam ThrParam;
-struct ThrParam {
-	void *start_func;
-	void *arg;
-	int8 *stack_base;
-	uint64 stack_size;
-	int8 *tls_base;
-	uint64 tls_size;
-	int64 *child_tid;
-	int64 *parent_tid;
-	int32 flags;
-	byte pad_godefs_0[4];
-	Rtprio *rtp;
-	void* spare[3];
-};
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	int8 *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
-};
-
-typedef struct Sigset Sigset;
-struct Sigset {
-	uint32 __bits[4];
-};
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
-	int32 sigval_int;
-	void *sigval_ptr;
-};
-
-typedef struct StackT StackT;
-struct StackT {
-	int8 *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	int32 si_pid;
-	uint32 si_uid;
-	int32 si_status;
-	void *si_addr;
-	Sigval si_value;
-	byte _reason[40];
-};
-
-typedef struct Mcontext Mcontext;
-struct Mcontext {
-	int64 mc_onstack;
-	int64 mc_rdi;
-	int64 mc_rsi;
-	int64 mc_rdx;
-	int64 mc_rcx;
-	int64 mc_r8;
-	int64 mc_r9;
-	int64 mc_rax;
-	int64 mc_rbx;
-	int64 mc_rbp;
-	int64 mc_r10;
-	int64 mc_r11;
-	int64 mc_r12;
-	int64 mc_r13;
-	int64 mc_r14;
-	int64 mc_r15;
-	uint32 mc_trapno;
-	uint16 mc_fs;
-	uint16 mc_gs;
-	int64 mc_addr;
-	uint32 mc_flags;
-	uint16 mc_es;
-	uint16 mc_ds;
-	int64 mc_err;
-	int64 mc_rip;
-	int64 mc_cs;
-	int64 mc_rflags;
-	int64 mc_rsp;
-	int64 mc_ss;
-	int64 mc_len;
-	int64 mc_fpformat;
-	int64 mc_ownedfp;
-	int64 mc_fpstate[64];
-	int64 mc_fsbase;
-	int64 mc_gsbase;
-	int64 mc_spare[6];
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
-	Sigset uc_sigmask;
-	Mcontext uc_mcontext;
-	Ucontext *uc_link;
-	StackT uc_stack;
-	int32 uc_flags;
-	int32 __spare__[4];
-	byte pad_godefs_0[12];
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int64 tv_sec;
-	int64 tv_usec;
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/freebsd/amd64/signal.c b/src/pkg/runtime/freebsd/amd64/signal.c
deleted file mode 100644
index 8015e36..0000000
--- a/src/pkg/runtime/freebsd/amd64/signal.c
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
-	union {
-		void    (*__sa_handler)(int32);
-		void    (*__sa_sigaction)(int32, Siginfo*, void *);
-	} __sigaction_u;		/* signal handler */
-	int32	sa_flags;		/* see signal options below */
-	int64	sa_mask;		/* signal mask to apply */
-} Sigaction;
-
-void
-runtime·dumpregs(Mcontext *r)
-{
-	runtime·printf("rax     %X\n", r->mc_rax);
-	runtime·printf("rbx     %X\n", r->mc_rbx);
-	runtime·printf("rcx     %X\n", r->mc_rcx);
-	runtime·printf("rdx     %X\n", r->mc_rdx);
-	runtime·printf("rdi     %X\n", r->mc_rdi);
-	runtime·printf("rsi     %X\n", r->mc_rsi);
-	runtime·printf("rbp     %X\n", r->mc_rbp);
-	runtime·printf("rsp     %X\n", r->mc_rsp);
-	runtime·printf("r8      %X\n", r->mc_r8 );
-	runtime·printf("r9      %X\n", r->mc_r9 );
-	runtime·printf("r10     %X\n", r->mc_r10);
-	runtime·printf("r11     %X\n", r->mc_r11);
-	runtime·printf("r12     %X\n", r->mc_r12);
-	runtime·printf("r13     %X\n", r->mc_r13);
-	runtime·printf("r14     %X\n", r->mc_r14);
-	runtime·printf("r15     %X\n", r->mc_r15);
-	runtime·printf("rip     %X\n", r->mc_rip);
-	runtime·printf("rflags  %X\n", r->mc_flags);
-	runtime·printf("cs      %X\n", r->mc_cs);
-	runtime·printf("fs      %X\n", r->mc_fs);
-	runtime·printf("gs      %X\n", r->mc_gs);
-}
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Ucontext *uc;
-	Mcontext *r;
-	uintptr *sp;
-
-	uc = context;
-	r = &uc->uc_mcontext;
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->mc_rip, (uint8*)r->mc_rsp, nil, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = (uintptr)info->si_addr;
-		gp->sigpc = r->mc_rip;
-
-		// Only push runtime·sigpanic if r->mc_rip != 0.
-		// If r->mc_rip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->mc_rip != 0) {
-			sp = (uintptr*)r->mc_rsp;
-			*--sp = r->mc_rip;
-			r->mc_rsp = (uintptr)sp;
-		}
-		r->mc_rip = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG)
-		runtime·printf("Signal %d\n", sig);
-	else
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-
-	runtime·printf("PC=%X\n", r->mc_rip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->mc_rip, (void*)r->mc_rsp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-}
-
-// Called from kernel on signal stack, so no stack split.
-#pragma textflag 7
-void
-runtime·sigignore(void)
-{
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	Sigaltstack st;
-
-	st.ss_sp = (int8*)p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	if (fn == runtime·sighandler)
-		fn = (void*)runtime·sigtramp;
-	sa.__sigaction_u.__sa_sigaction = (void*)fn;
-	runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
diff --git a/src/pkg/runtime/freebsd/amd64/sys.s b/src/pkg/runtime/freebsd/amd64/sys.s
deleted file mode 100644
index c5cc082..0000000
--- a/src/pkg/runtime/freebsd/amd64/sys.s
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// System calls and other sys.stuff for AMD64, FreeBSD
-// /usr/src/sys/kern/syscalls.master for syscall numbers.
-//
-
-#include "amd64/asm.h"
-	
-TEXT runtime·sys_umtx_op(SB),7,$0
-	MOVQ 8(SP), DI
-	MOVL 16(SP), SI
-	MOVL 20(SP), DX
-	MOVQ 24(SP), R10
-	MOVQ 32(SP), R8
-	MOVL $454, AX
-	SYSCALL
-	RET
-
-TEXT runtime·thr_new(SB),7,$0
-	MOVQ 8(SP), DI
-	MOVQ 16(SP), SI
-	MOVL $455, AX
-	SYSCALL
-	RET
-
-TEXT runtime·thr_start(SB),7,$0
-	MOVQ	DI, R13	// m
-
-	// set up FS to point at m->tls
-	LEAQ	m_tls(R13), DI
-	CALL	runtime·settls(SB)	// smashes DI
-
-	// set up m, g
-	get_tls(CX)
-	MOVQ	R13, m(CX)
-	MOVQ	m_g0(R13), DI
-	MOVQ	DI, g(CX)
-
-	CALL runtime·stackcheck(SB)
-	CALL runtime·mstart(SB)
-	MOVQ 0, AX			// crash (not reached)
-
-// Exit the entire program (like C exit)
-TEXT runtime·exit(SB),7,$-8
-	MOVL	8(SP), DI		// arg 1 exit status
-	MOVL	$1, AX
-	SYSCALL
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·exit1(SB),7,$-8
-	MOVQ	8(SP), DI		// arg 1 exit status
-	MOVL	$431, AX
-	SYSCALL
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·write(SB),7,$-8
-	MOVL	8(SP), DI		// arg 1 fd
-	MOVQ	16(SP), SI		// arg 2 buf
-	MOVL	24(SP), DX		// arg 3 count
-	MOVL	$4, AX
-	SYSCALL
-	RET
-
-TEXT runtime·raisesigpipe(SB),7,$16
-	// thr_self(&8(SP))
-	LEAQ	8(SP), DI	// arg 1 &8(SP)
-	MOVL	$432, AX
-	SYSCALL
-	// thr_kill(self, SIGPIPE)
-	MOVQ	8(SP), DI	// arg 1 id
-	MOVQ	$13, SI	// arg 2 SIGPIPE
-	MOVL	$433, AX
-	SYSCALL
-	RET
-
-TEXT runtime·setitimer(SB), 7, $-8
-	MOVL	8(SP), DI
-	MOVQ	16(SP), SI
-	MOVQ	24(SP), DX
-	MOVL	$83, AX
-	SYSCALL
-	RET
-
-TEXT runtime·gettime(SB), 7, $32
-	MOVL	$116, AX
-	LEAQ	8(SP), DI
-	MOVQ	$0, SI
-	SYSCALL
-
-	MOVQ	8(SP), BX	// sec
-	MOVQ	sec+0(FP), DI
-	MOVQ	BX, (DI)
-
-	MOVL	16(SP), BX	// usec
-	MOVQ	usec+8(FP), DI
-	MOVL	BX, (DI)
-	RET
-
-TEXT runtime·sigaction(SB),7,$-8
-	MOVL	8(SP), DI		// arg 1 sig
-	MOVQ	16(SP), SI		// arg 2 act
-	MOVQ	24(SP), DX		// arg 3 oact
-	MOVL	$416, AX
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·sigtramp(SB),7,$64
-	get_tls(BX)
-	
-	// save g
-	MOVQ	g(BX), R10
-	MOVQ	R10, 40(SP)
-	
-	// g = m->signal
-	MOVQ	m(BX), BP
-	MOVQ	m_gsignal(BP), BP
-	MOVQ	BP, g(BX)
-	
-	MOVQ	DI, 0(SP)
-	MOVQ	SI, 8(SP)
-	MOVQ	DX, 16(SP)
-	MOVQ	R10, 24(SP)
-	
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(BX)
-	MOVQ	40(SP), R10
-	MOVQ	R10, g(BX)
-	RET
-
-TEXT runtime·mmap(SB),7,$0
-	MOVQ	8(SP), DI		// arg 1 addr
-	MOVQ	16(SP), SI		// arg 2 len
-	MOVL	24(SP), DX		// arg 3 prot
-	MOVL	28(SP), R10		// arg 4 flags
-	MOVL	32(SP), R8		// arg 5 fid
-	MOVL	36(SP), R9		// arg 6 offset
-	MOVL	$477, AX
-	SYSCALL
-	RET
-
-TEXT runtime·munmap(SB),7,$0
-	MOVQ	8(SP), DI		// arg 1 addr
-	MOVQ	16(SP), SI		// arg 2 len
-	MOVL	$73, AX
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·notok(SB),7,$-8
-	MOVL	$0xf1, BP
-	MOVQ	BP, (BP)
-	RET
-
-TEXT runtime·sigaltstack(SB),7,$-8
-	MOVQ	new+8(SP), DI
-	MOVQ	old+16(SP), SI
-	MOVQ	$53, AX
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-// set tls base to DI
-TEXT runtime·settls(SB),7,$8
-	ADDQ	$16, DI	// adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
-	MOVQ	DI, 0(SP)
-	MOVQ	SP, SI
-	MOVQ	$129, DI	// AMD64_SET_FSBASE
-	MOVQ	$165, AX	// sysarch
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
diff --git a/src/pkg/runtime/freebsd/defs.c b/src/pkg/runtime/freebsd/defs.c
deleted file mode 100644
index 2ce4fdc..0000000
--- a/src/pkg/runtime/freebsd/defs.c
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Input to godefs.
- *
-	godefs -f -m64 defs.c >amd64/defs.h
-	godefs -f -m32 defs.c >386/defs.h
- */
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <sys/ucontext.h>
-#include <sys/umtx.h>
-#include <sys/rtprio.h>
-#include <sys/thr.h>
-#include <sys/_sigset.h>
-#include <sys/unistd.h>
-
-enum {
-	$PROT_NONE = PROT_NONE,
-	$PROT_READ = PROT_READ,
-	$PROT_WRITE = PROT_WRITE,
-	$PROT_EXEC = PROT_EXEC,
-
-	$MAP_ANON = MAP_ANON,
-	$MAP_PRIVATE = MAP_PRIVATE,
-	$MAP_FIXED = MAP_FIXED,
-
-	$SA_SIGINFO = SA_SIGINFO,
-	$SA_RESTART = SA_RESTART,
-	$SA_ONSTACK = SA_ONSTACK,
-
-	$UMTX_OP_WAIT = UMTX_OP_WAIT,
-	$UMTX_OP_WAKE = UMTX_OP_WAKE,
-
-	$EINTR = EINTR,
-	
-	$SIGHUP = SIGHUP,
-	$SIGINT = SIGINT,
-	$SIGQUIT = SIGQUIT,
-	$SIGILL = SIGILL,
-	$SIGTRAP = SIGTRAP,
-	$SIGABRT = SIGABRT,
-	$SIGEMT = SIGEMT,
-	$SIGFPE = SIGFPE,
-	$SIGKILL = SIGKILL,
-	$SIGBUS = SIGBUS,
-	$SIGSEGV = SIGSEGV,
-	$SIGSYS = SIGSYS,
-	$SIGPIPE = SIGPIPE,
-	$SIGALRM = SIGALRM,
-	$SIGTERM = SIGTERM,
-	$SIGURG = SIGURG,
-	$SIGSTOP = SIGSTOP,
-	$SIGTSTP = SIGTSTP,
-	$SIGCONT = SIGCONT,
-	$SIGCHLD = SIGCHLD,
-	$SIGTTIN = SIGTTIN,
-	$SIGTTOU = SIGTTOU,
-	$SIGIO = SIGIO,
-	$SIGXCPU = SIGXCPU,
-	$SIGXFSZ = SIGXFSZ,
-	$SIGVTALRM = SIGVTALRM,
-	$SIGPROF = SIGPROF,
-	$SIGWINCH = SIGWINCH,
-	$SIGINFO = SIGINFO,
-	$SIGUSR1 = SIGUSR1,
-	$SIGUSR2 = SIGUSR2,
-	
-	$FPE_INTDIV = FPE_INTDIV,
-	$FPE_INTOVF = FPE_INTOVF,
-	$FPE_FLTDIV = FPE_FLTDIV,
-	$FPE_FLTOVF = FPE_FLTOVF,
-	$FPE_FLTUND = FPE_FLTUND,
-	$FPE_FLTRES = FPE_FLTRES,
-	$FPE_FLTINV = FPE_FLTINV,
-	$FPE_FLTSUB = FPE_FLTSUB,
-	
-	$BUS_ADRALN = BUS_ADRALN,
-	$BUS_ADRERR = BUS_ADRERR,
-	$BUS_OBJERR = BUS_OBJERR,
-	
-	$SEGV_MAPERR = SEGV_MAPERR,
-	$SEGV_ACCERR = SEGV_ACCERR,
-	
-	$ITIMER_REAL = ITIMER_REAL,
-	$ITIMER_VIRTUAL = ITIMER_VIRTUAL,
-	$ITIMER_PROF = ITIMER_PROF,
-};
-
-typedef struct rtprio	$Rtprio;
-typedef struct thr_param $ThrParam;
-typedef struct sigaltstack $Sigaltstack;
-typedef struct __sigset $Sigset;
-typedef union sigval $Sigval;
-typedef stack_t	$StackT;
-
-typedef siginfo_t $Siginfo;
-
-typedef mcontext_t $Mcontext;
-typedef ucontext_t $Ucontext;
-typedef struct timeval $Timeval;
-typedef struct itimerval $Itimerval;
diff --git a/src/pkg/runtime/freebsd/mem.c b/src/pkg/runtime/freebsd/mem.c
deleted file mode 100644
index 07abf2c..0000000
--- a/src/pkg/runtime/freebsd/mem.c
+++ /dev/null
@@ -1,74 +0,0 @@
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "malloc.h"
-
-void*
-runtime·SysAlloc(uintptr n)
-{
-	void *v;
-
-	mstats.sys += n;
-	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
-	if(v < (void*)4096)
-		return nil;
-	return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-	USED(v);
-	USED(n);
-	// TODO(rsc): call madvise MADV_DONTNEED
-}
-
-void
-runtime·SysFree(void *v, uintptr n)
-{
-	mstats.sys -= n;
-	runtime·munmap(v, n);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n)
-{
-	// On 64-bit, people with ulimit -v set complain if we reserve too
-	// much address space.  Instead, assume that the reservation is okay
-	// and check the assumption in SysMap.
-	if(sizeof(void*) == 8)
-		return v;
-	
-	return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-}
-
-enum
-{
-	ENOMEM = 12,
-};
-
-void
-runtime·SysMap(void *v, uintptr n)
-{
-	void *p;
-	
-	mstats.sys += n;
-
-	// On 64-bit, we don't actually have v reserved, so tread carefully.
-	if(sizeof(void*) == 8) {
-		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
-		if(p == (void*)-ENOMEM)
-			runtime·throw("runtime: out of memory");
-		if(p != v) {
-			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-			runtime·throw("runtime: address space conflict");
-		}
-		return;
-	}
-
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
-	if(p == (void*)-ENOMEM)
-		runtime·throw("runtime: out of memory");
-	if(p != v)
-		runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/pkg/runtime/freebsd/os.h b/src/pkg/runtime/freebsd/os.h
deleted file mode 100644
index 007856c..0000000
--- a/src/pkg/runtime/freebsd/os.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#define SIG_DFL ((void*)0)
-#define SIG_IGN ((void*)1)
-
-int32 runtime·thr_new(ThrParam*, int32);
-void runtime·sigpanic(void);
-void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
-struct sigaction;
-void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void	runtiem·setitimerval(int32, Itimerval*, Itimerval*);
-void	runtime·setitimer(int32, Itimerval*, Itimerval*);
-
-void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/freebsd/thread.c b/src/pkg/runtime/freebsd/thread.c
deleted file mode 100644
index f8c550f..0000000
--- a/src/pkg/runtime/freebsd/thread.c
+++ /dev/null
@@ -1,201 +0,0 @@
-// Use of this source file is governed by a BSD-style
-// license that can be found in the LICENSE file.`
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "stack.h"
-
-extern SigTab runtime·sigtab[];
-extern int32 runtime·sys_umtx_op(uint32*, int32, uint32, void*, void*);
-
-// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
-// thus the code is largely similar. See linux/thread.c for comments.
-
-static void
-umtx_wait(uint32 *addr, uint32 val)
-{
-	int32 ret;
-
-	ret = runtime·sys_umtx_op(addr, UMTX_OP_WAIT, val, nil, nil);
-	if(ret >= 0 || ret == -EINTR)
-		return;
-
-	runtime·printf("umtx_wait addr=%p val=%d ret=%d\n", addr, val, ret);
-	*(int32*)0x1005 = 0x1005;
-}
-
-static void
-umtx_wake(uint32 *addr)
-{
-	int32 ret;
-
-	ret = runtime·sys_umtx_op(addr, UMTX_OP_WAKE, 1, nil, nil);
-	if(ret >= 0)
-		return;
-
-	runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret);
-	*(int32*)0x1006 = 0x1006;
-}
-
-// See linux/thread.c for comments about the algorithm.
-static void
-umtx_lock(Lock *l)
-{
-	uint32 v;
-
-again:
-	v = l->key;
-	if((v&1) == 0){
-		if(runtime·cas(&l->key, v, v|1))
-			return;
-		goto again;
-	}
-
-	if(!runtime·cas(&l->key, v, v+2))
-		goto again;
-
-	umtx_wait(&l->key, v+2);
-
-	for(;;){
-		v = l->key;
-		if(v < 2)
-			runtime·throw("bad lock key");
-		if(runtime·cas(&l->key, v, v-2))
-			break;
-	}
-
-	goto again;
-}
-
-static void
-umtx_unlock(Lock *l)
-{
-	uint32 v;
-
-again:
-	v = l->key;
-	if((v&1) == 0)
-		runtime·throw("unlock of unlocked lock");
-	if(!runtime·cas(&l->key, v, v&~1))
-		goto again;
-
-	if(v&~1)
-		umtx_wake(&l->key);
-}
-
-void
-runtime·lock(Lock *l)
-{
-	if(m->locks < 0)
-		runtime·throw("lock count");
-	m->locks++;
-	umtx_lock(l);
-}
-
-void 
-runtime·unlock(Lock *l)
-{
-	m->locks--;
-	if(m->locks < 0)
-		runtime·throw("lock count");
-	umtx_unlock(l);
-}
-
-// Event notifications.
-void
-runtime·noteclear(Note *n)
-{
-	n->lock.key = 0;
-	umtx_lock(&n->lock);
-}
-
-void
-runtime·notesleep(Note *n)
-{
-	umtx_lock(&n->lock);
-	umtx_unlock(&n->lock);
-}
-
-void
-runtime·notewakeup(Note *n)
-{
-	umtx_unlock(&n->lock);
-}
-
-void runtime·thr_start(void*);
-
-void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
-{
-	ThrParam param;
-
-	USED(fn);	// thr_start assumes fn == mstart
-	USED(g);	// thr_start assumes g == m->g0
-
-	if(0){
-		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, m->id, m->tls[0], &m);
-	}
-
-	runtime·memclr((byte*)&param, sizeof param);
-
-	param.start_func = runtime·thr_start;
-	param.arg = m;
-	param.stack_base = (int8*)g->stackbase;
-	param.stack_size = (byte*)stk - (byte*)g->stackbase;
-	param.child_tid = (intptr*)&m->procid;
-	param.parent_tid = nil;
-	param.tls_base = (int8*)&m->tls[0];
-	param.tls_size = sizeof m->tls;
-
-	m->tls[0] = m->id;	// so 386 asm can find it
-
-	runtime·thr_new(&param, sizeof param);
-}
-
-void
-runtime·osinit(void)
-{
-}
-
-void
-runtime·goenvs(void)
-{
-	runtime·goenvs_unix();
-}
-
-// Called to initialize a new m (including the bootstrap m).
-void
-runtime·minit(void)
-{
-	// Initialize signal handling
-	m->gsignal = runtime·malg(32*1024);
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
-}
-
-void
-runtime·sigpanic(void)
-{
-	switch(g->sig) {
-	case SIGBUS:
-		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case SIGSEGV:
-		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case SIGFPE:
-		switch(g->sigcode0) {
-		case FPE_INTDIV:
-			runtime·panicstring("integer divide by zero");
-		case FPE_INTOVF:
-			runtime·panicstring("integer overflow");
-		}
-		runtime·panicstring("floating point error");
-	}
-	runtime·panicstring(runtime·sigtab[g->sig].name);
-}
diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go
new file mode 100644
index 0000000..00b3a04
--- /dev/null
+++ b/src/pkg/runtime/gc_test.go
@@ -0,0 +1,36 @@
+// Copyright 2011 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 runtime_test
+
+import (
+	"runtime"
+	"testing"
+)
+
+func TestGcSys(t *testing.T) {
+	runtime.GC()
+	runtime.UpdateMemStats()
+	sys := runtime.MemStats.Sys
+
+	for i := 0; i < 1000000; i++ {
+		workthegc()
+	}
+
+	// Should only be using a few MB.
+	runtime.UpdateMemStats()
+	if sys > runtime.MemStats.Sys {
+		sys = 0
+	} else {
+		sys = runtime.MemStats.Sys - sys
+	}
+	t.Logf("used %d extra bytes", sys)
+	if sys > 4<<20 {
+		t.Fatalf("using too much memory: %d bytes", sys)
+	}
+}
+
+func workthegc() []byte {
+	return make([]byte, 1029)
+}
diff --git a/src/pkg/runtime/goc2c.c b/src/pkg/runtime/goc2c.c
index fcac9c0..b59a69c 100644
--- a/src/pkg/runtime/goc2c.c
+++ b/src/pkg/runtime/goc2c.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
  * Translate a .goc file into a .c file.  A .goc file is a combination
  * of a limited form of Go with C.
@@ -742,6 +744,7 @@ main(int argc, char **argv)
 		}
 	}
 
+	printf("// AUTO-GENERATED by autogen.sh; DO NOT EDIT\n\n");
 	process_file();
 	exits(0);
 }
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index 0c0e3e4..642995d 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -6,41 +6,14 @@
 #include "hashmap.h"
 #include "type.h"
 
-/* Return a pointer to the struct/union of type "type"
-   whose "field" field is addressed by pointer "p". */
-
 struct Hmap {	   /* a hash table; initialize with hash_init() */
 	uint32 count;	  /* elements in table - must be first */
-
 	uint8 datasize;   /* amount of data to store in entry */
 	uint8 max_power;  /* max power of 2 to create sub-tables */
-	uint8 max_probes; /* max entries to probe before rehashing */
-	uint8 indirectval; /* storing pointers to values */
+	uint8 indirectval;	/* storing pointers to values */
+	uint8 valoff;	/* offset of value in key+value data block */
 	int32 changes;	      /* inc'ed whenever a subtable is created/grown */
-	hash_hash_t (*data_hash) (uint32, void *a);  /* return hash of *a */
-	uint32 (*data_eq) (uint32, void *a, void *b);   /* return whether *a == *b */
-	void (*data_del) (uint32, void *arg, void *data);  /* invoked on deletion */
 	struct hash_subtable *st;    /* first-level table */
-
-	uint32	keysize;
-	uint32	valsize;
-	uint32	datavo;
-
-	// three sets of offsets: the digit counts how many
-	// of key, value are passed as inputs:
-	//	0 = func() (key, value)
-	//	1 = func(key) (value)
-	//	2 = func(key, value)
-	uint32	ko0;
-	uint32	vo0;
-	uint32	ko1;
-	uint32	vo1;
-	uint32	po1;
-	uint32	ko2;
-	uint32	vo2;
-	uint32	po2;
-	Alg*	keyalg;
-	Alg*	valalg;
 };
 
 struct hash_entry {
@@ -54,11 +27,11 @@ struct hash_subtable {
 	uint8 datasize;      /* bytes of client data in an entry */
 	uint8 max_probes;    /* max number of probes when searching */
 	int16 limit_bytes;	   /* max_probes * (datasize+sizeof (hash_hash_t)) */
-	struct hash_entry *end;      /* points just past end of entry[] */
+	struct hash_entry *last;      /* points to last element of entry[] */
 	struct hash_entry entry[1];  /* 2**power+max_probes-1 elements of elemsize bytes */
 };
 
-#define HASH_DATA_EQ(h,x,y) ((*h->data_eq) (h->keysize, (x), (y)))
+#define HASH_DATA_EQ(eq, t, h,x,y) ((eq)=0, (*t->key->alg->equal) (&(eq), t->key->size, (x), (y)), (eq))
 
 #define HASH_REHASH 0x2       /* an internal flag */
 /* the number of bits used is stored in the flags word too */
@@ -79,6 +52,7 @@ struct hash_subtable {
 #define HASH_OFFSET(base, byte_offset) \
 	  ((struct hash_entry *) (((byte *) (base)) + (byte_offset)))
 
+#define HASH_MAX_PROBES	15 /* max entries to probe before rehashing */
 
 /* return a hash layer with 2**power empty entries */
 static struct hash_subtable *
@@ -87,8 +61,8 @@ hash_subtable_new (Hmap *h, int32 power, int32 used)
 	int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
 	int32 bytes = elemsize << power;
 	struct hash_subtable *st;
-	int32 limit_bytes = h->max_probes * elemsize;
-	int32 max_probes = h->max_probes;
+	int32 limit_bytes = HASH_MAX_PROBES * elemsize;
+	int32 max_probes = HASH_MAX_PROBES;
 
 	if (bytes < limit_bytes) {
 		limit_bytes = bytes;
@@ -101,7 +75,7 @@ hash_subtable_new (Hmap *h, int32 power, int32 used)
 	st->datasize = h->datasize;
 	st->max_probes = max_probes;
 	st->limit_bytes = limit_bytes;
-	st->end = HASH_OFFSET (st->entry, bytes);
+	st->last = HASH_OFFSET (st->entry, bytes) - 1;
 	memset (st->entry, HASH_NIL_MEMSET, bytes);
 	return (st);
 }
@@ -127,12 +101,7 @@ init_sizes (int64 hint, int32 *init_power, int32 *max_power)
 }
 
 static void
-hash_init (Hmap *h,
-		int32 datasize,
-		hash_hash_t (*data_hash) (uint32, void *),
-		uint32 (*data_eq) (uint32, void *, void *),
-		void (*data_del) (uint32, void *, void *),
-		int64 hint)
+hash_init (Hmap *h, int32 datasize, int64 hint)
 {
 	int32 init_power;
 	int32 max_power;
@@ -143,15 +112,11 @@ hash_init (Hmap *h,
 	init_sizes (hint, &init_power, &max_power);
 	h->datasize = datasize;
 	h->max_power = max_power;
-	h->max_probes = 15;
 	assert (h->datasize == datasize);
 	assert (h->max_power == max_power);
 	assert (sizeof (void *) <= h->datasize || h->max_power == 255);
 	h->count = 0;
 	h->changes = 0;
-	h->data_hash = data_hash;
-	h->data_eq = data_eq;
-	h->data_del = data_del;
 	h->st = hash_subtable_new (h, init_power, 0);
 }
 
@@ -160,7 +125,7 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
 {
 	int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
 	struct hash_entry *src_e = HASH_OFFSET (dst_e, n * elemsize);
-	struct hash_entry *end_e = st->end;
+	struct hash_entry *last_e = st->last;
 	int32 shift = HASH_BITS - (st->power + st->used);
 	int32 index_mask = (((hash_hash_t)1) << st->power) - 1;
 	int32 dst_i = (((byte *) dst_e) - ((byte *) st->entry)) / elemsize;
@@ -170,10 +135,10 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
 	int32 bytes;
 
 	while (dst_e != src_e) {
-		if (src_e != end_e) {
+		if (src_e <= last_e) {
 			struct hash_entry *cp_e = src_e;
 			int32 save_dst_i = dst_i;
-			while (cp_e != end_e && (hash = cp_e->hash) != HASH_NIL &&
+			while (cp_e <= last_e && (hash = cp_e->hash) != HASH_NIL &&
 			     ((hash >> shift) & index_mask) <= dst_i) {
 				cp_e = HASH_OFFSET (cp_e, elemsize);
 				dst_i++;
@@ -183,7 +148,7 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
 			dst_e = HASH_OFFSET (dst_e, bytes);
 			src_e = cp_e;
 			src_i += dst_i - save_dst_i;
-			if (src_e != end_e && (hash = src_e->hash) != HASH_NIL) {
+			if (src_e <= last_e && (hash = src_e->hash) != HASH_NIL) {
 				skip = ((hash >> shift) & index_mask) - dst_i;
 			} else {
 				skip = src_i - dst_i;
@@ -199,11 +164,11 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
 }
 
 static int32
-hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
+hash_insert_internal (MapType*, struct hash_subtable **pst, int32 flags, hash_hash_t hash,
 		Hmap *h, void *data, void **pres);
 
 static void
-hash_conv (Hmap *h,
+hash_conv (MapType *t, Hmap *h,
 		struct hash_subtable *st, int32 flags,
 		hash_hash_t hash,
 		struct hash_entry *e)
@@ -224,7 +189,7 @@ hash_conv (Hmap *h,
 	}
 
 	de = e;
-	while (e != st->end &&
+	while (e <= st->last &&
 	    (e_hash = e->hash) != HASH_NIL &&
 	    (e_hash & HASH_MASK) != HASH_SUBHASH) {
 		struct hash_entry *target_e = HASH_OFFSET (st->entry, ((e_hash >> shift) & index_mask) * elemsize);
@@ -235,16 +200,16 @@ hash_conv (Hmap *h,
 			de = target_e;
 		}
 		if ((hash & prefix_mask) == current ||
-		   (ne != st->end && (e_hash = ne->hash) != HASH_NIL &&
+		   (ne <= st->last && (e_hash = ne->hash) != HASH_NIL &&
 		   (e_hash & prefix_mask) == current)) {
 			struct hash_subtable *new_st = hash_subtable_new (h, 1, HASH_USED (new_flags));
-			int32 rc = hash_insert_internal (&new_st, new_flags, e->hash, h, e->data, &dummy_result);
+			int32 rc = hash_insert_internal (t, &new_st, new_flags, e->hash, h, e->data, &dummy_result);
 			assert (rc == 0);
 			memcpy(dummy_result, e->data, h->datasize);
 			e = ne;
-			while (e != st->end && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) {
+			while (e <= st->last && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) {
 				assert ((e_hash & HASH_MASK) != HASH_SUBHASH);
-				rc = hash_insert_internal (&new_st, new_flags, e_hash, h, e->data, &dummy_result);
+				rc = hash_insert_internal (t, &new_st, new_flags, e_hash, h, e->data, &dummy_result);
 				assert (rc == 0);
 				memcpy(dummy_result, e->data, h->datasize);
 				e = HASH_OFFSET (e, elemsize);
@@ -266,21 +231,21 @@ hash_conv (Hmap *h,
 }
 
 static void
-hash_grow (Hmap *h, struct hash_subtable **pst, int32 flags)
+hash_grow (MapType *t, Hmap *h, struct hash_subtable **pst, int32 flags)
 {
 	struct hash_subtable *old_st = *pst;
 	int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
 	*pst = hash_subtable_new (h, old_st->power + 1, HASH_USED (flags));
-	struct hash_entry *end_e = old_st->end;
+	struct hash_entry *last_e = old_st->last;
 	struct hash_entry *e;
 	void *dummy_result;
 	int32 used = 0;
 
 	flags |= HASH_REHASH;
-	for (e = old_st->entry; e != end_e; e = HASH_OFFSET (e, elemsize)) {
+	for (e = old_st->entry; e <= last_e; e = HASH_OFFSET (e, elemsize)) {
 		hash_hash_t hash = e->hash;
 		if (hash != HASH_NIL) {
-			int32 rc = hash_insert_internal (pst, flags, e->hash, h, e->data, &dummy_result);
+			int32 rc = hash_insert_internal (t, pst, flags, e->hash, h, e->data, &dummy_result);
 			assert (rc == 0);
 			memcpy(dummy_result, e->data, h->datasize);
 			used++;
@@ -290,16 +255,20 @@ hash_grow (Hmap *h, struct hash_subtable **pst, int32 flags)
 }
 
 static int32
-hash_lookup (Hmap *h, void *data, void **pres)
+hash_lookup (MapType *t, Hmap *h, void *data, void **pres)
 {
 	int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
-	hash_hash_t hash = (*h->data_hash) (h->keysize, data) & ~HASH_MASK;
+	hash_hash_t hash;
 	struct hash_subtable *st = h->st;
 	int32 used = 0;
 	hash_hash_t e_hash;
 	struct hash_entry *e;
 	struct hash_entry *end_e;
-
+	bool eq;
+	
+	hash = 0;
+	(*t->key->alg->hash) (&hash, t->key->size, data);
+	hash &= ~HASH_MASK;
 	hash += HASH_ADJUST (hash);
 	for (;;) {
 		int32 shift = HASH_BITS - (st->power + used);
@@ -319,7 +288,7 @@ hash_lookup (Hmap *h, void *data, void **pres)
 		e = HASH_OFFSET (e, elemsize);
 	}
 	while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
-		if (HASH_DATA_EQ (h, data, e->data)) {    /* a match */
+		if (HASH_DATA_EQ (eq, t, h, data, e->data)) {    /* a match */
 			*pres = e->data;
 			return (1);
 		}
@@ -331,16 +300,20 @@ hash_lookup (Hmap *h, void *data, void **pres)
 }
 
 static int32
-hash_remove (Hmap *h, void *data, void *arg)
+hash_remove (MapType *t, Hmap *h, void *data)
 {
 	int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
-	hash_hash_t hash = (*h->data_hash) (h->keysize, data) & ~HASH_MASK;
+	hash_hash_t hash;
 	struct hash_subtable *st = h->st;
 	int32 used = 0;
 	hash_hash_t e_hash;
 	struct hash_entry *e;
 	struct hash_entry *end_e;
+	bool eq;
 
+	hash = 0;
+	(*t->key->alg->hash) (&hash, t->key->size, data);
+	hash &= ~HASH_MASK;
 	hash += HASH_ADJUST (hash);
 	for (;;) {
 		int32 shift = HASH_BITS - (st->power + used);
@@ -360,8 +333,9 @@ hash_remove (Hmap *h, void *data, void *arg)
 		e = HASH_OFFSET (e, elemsize);
 	}
 	while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
-		if (HASH_DATA_EQ (h, data, e->data)) {    /* a match */
-			(*h->data_del) (h->datavo, arg, e->data);
+		if (HASH_DATA_EQ (eq, t, h, data, e->data)) {    /* a match */
+			if (h->indirectval)
+				free (*(void**)((byte*)e->data + h->valoff));
 			hash_remove_n (st, e, 1);
 			h->count--;
 			return (1);
@@ -373,10 +347,11 @@ hash_remove (Hmap *h, void *data, void *arg)
 }
 
 static int32
-hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
+hash_insert_internal (MapType *t, struct hash_subtable **pst, int32 flags, hash_hash_t hash,
 				 Hmap *h, void *data, void **pres)
 {
 	int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
+	bool eq;
 
 	if ((flags & HASH_REHASH) == 0) {
 		hash += HASH_ADJUST (hash);
@@ -409,7 +384,7 @@ hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
 			int32 ins_i = i;
 			hash_hash_t ins_e_hash;
 			while (ins_e != end_e && ((e_hash = ins_e->hash) ^ hash) < HASH_SUBHASH) {
-				if (HASH_DATA_EQ (h, data, ins_e->data)) {    /* a match */
+				if (HASH_DATA_EQ (eq, t, h, data, ins_e->data)) {    /* a match */
 					*pres = ins_e->data;
 					return (1);
 				}
@@ -428,13 +403,13 @@ hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
 			ins_e_hash = 0;
 			/* move ins_e to point at the end of the contiguous block, but
 			   stop if any element can't be moved by one up */
-			while (ins_e != st->end && (ins_e_hash = ins_e->hash) != HASH_NIL &&
+			while (ins_e <= st->last && (ins_e_hash = ins_e->hash) != HASH_NIL &&
 			       ins_i + 1 - ((ins_e_hash >> shift) & index_mask) < st->max_probes &&
 			       (ins_e_hash & HASH_MASK) != HASH_SUBHASH) {
 				ins_e = HASH_OFFSET (ins_e, elemsize);
 				ins_i++;
 			}
-			if (e == end_e || ins_e == st->end || ins_e_hash != HASH_NIL) {
+			if (e == end_e || ins_e > st->last || ins_e_hash != HASH_NIL) {
 				e = end_e;    /* can't insert; must grow or convert to subtable */
 			} else {	      /* make space for element */
 				memmove (HASH_OFFSET (e, elemsize), e, ((byte *) ins_e) - (byte *) e);
@@ -447,17 +422,22 @@ hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
 		}
 		h->changes++;
 		if (st->power < h->max_power) {
-			hash_grow (h, pst, flags);
+			hash_grow (t, h, pst, flags);
 		} else {
-			hash_conv (h, st, flags, hash, start_e);
+			hash_conv (t, h, st, flags, hash, start_e);
 		}
 	}
 }
 
 static int32
-hash_insert (Hmap *h, void *data, void **pres)
+hash_insert (MapType *t, Hmap *h, void *data, void **pres)
 {
-	int32 rc = hash_insert_internal (&h->st, 0, (*h->data_hash) (h->keysize, data), h, data, pres);
+	uintptr hash;
+	int32 rc;
+	
+	hash = 0;
+	(*t->key->alg->hash) (&hash, t->key->size, data);
+	rc = hash_insert_internal (t, &h->st, 0, hash, h, data, pres);
 
 	h->count += (rc == 0);    /* increment count if element didn't previously exist */
 	return (rc);
@@ -477,17 +457,17 @@ iter_restart (struct hash_iter *it, struct hash_subtable *st, int32 used)
 	struct hash_entry *e;
 	hash_hash_t e_hash;
 	struct hash_iter_sub *sub = &it->subtable_state[it->i];
-	struct hash_entry *end;
+	struct hash_entry *last;
 
 	for (;;) {
 		int32 shift = HASH_BITS - (st->power + used);
 		int32 index_mask = (1 << st->power) - 1;
 		int32 i = (last_hash >> shift) & index_mask;
 
-		end = st->end;
+		last = st->last;
 		e = HASH_OFFSET (st->entry, i * elemsize);
 		sub->start = st->entry;
-		sub->end = end;
+		sub->last = last;
 
 		if ((e->hash & HASH_MASK) != HASH_SUBHASH) {
 			break;
@@ -497,7 +477,7 @@ iter_restart (struct hash_iter *it, struct hash_subtable *st, int32 used)
 		used += st->power;
 		st = *(struct hash_subtable **)e->data;
 	}
-	while (e != end && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
+	while (e <= last && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
 		e = HASH_OFFSET (e, elemsize);
 	}
 	sub->e = e;
@@ -506,22 +486,29 @@ iter_restart (struct hash_iter *it, struct hash_subtable *st, int32 used)
 static void *
 hash_next (struct hash_iter *it)
 {
-	int32 elemsize = it->elemsize;
-	struct hash_iter_sub *sub = &it->subtable_state[it->i];
-	struct hash_entry *e = sub->e;
-	struct hash_entry *end = sub->end;
-	hash_hash_t e_hash = 0;
+	int32 elemsize;
+	struct hash_iter_sub *sub;
+	struct hash_entry *e;
+	struct hash_entry *last;
+	hash_hash_t e_hash;
 
 	if (it->changes != it->h->changes) {    /* hash table's structure changed; recompute */
+		if (~it->last_hash == 0)
+			return (0);
 		it->changes = it->h->changes;
 		it->i = 0;
 		iter_restart (it, it->h->st, 0);
-		sub = &it->subtable_state[it->i];
-		e = sub->e;
-		end = sub->end;
 	}
+	elemsize = it->elemsize;
+
+Again:
+	e_hash = 0;
+	sub = &it->subtable_state[it->i];
+	e = sub->e;
+	last = sub->last;
+
 	if (e != sub->start && it->last_hash != HASH_OFFSET (e, -elemsize)->hash) {
-		struct hash_entry *start = HASH_OFFSET (e, -(elemsize * it->h->max_probes));
+		struct hash_entry *start = HASH_OFFSET (e, -(elemsize * HASH_MAX_PROBES));
 		struct hash_entry *pe = HASH_OFFSET (e, -elemsize);
 		hash_hash_t last_hash = it->last_hash;
 		if (start < sub->start) {
@@ -531,27 +518,48 @@ hash_next (struct hash_iter *it)
 			e = pe;
 			pe = HASH_OFFSET (pe, -elemsize);
 		}
-		while (e != end && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
+		while (e <= last && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
 			e = HASH_OFFSET (e, elemsize);
 		}
 	}
 
 	for (;;) {
-		while (e != end && (e_hash = e->hash) == HASH_NIL) {
+		while (e <= last && (e_hash = e->hash) == HASH_NIL) {
 			e = HASH_OFFSET (e, elemsize);
 		}
-		if (e == end) {
+		if (e > last) {
 			if (it->i == 0) {
-				it->last_hash = HASH_OFFSET (e, -elemsize)->hash;
-				sub->e = e;
+				if(!it->cycled) {
+					// Wrap to zero and iterate up until it->cycle.
+					it->cycled = true;
+					it->last_hash = 0;
+					it->subtable_state[0].e = it->h->st->entry;
+					it->subtable_state[0].start = it->h->st->entry;
+					it->subtable_state[0].last = it->h->st->last;
+					goto Again;
+				}
+				// Set last_hash to impossible value and
+				// break it->changes, so that check at top of
+				// hash_next will be used if we get called again.
+				it->last_hash = ~(uintptr_t)0;
+				it->changes--;
 				return (0);
 			} else {
 				it->i--;
 				sub = &it->subtable_state[it->i];
 				e = sub->e;
-				end = sub->end;
+				last = sub->last;
 			}
 		} else if ((e_hash & HASH_MASK) != HASH_SUBHASH) {
+			if(it->cycled && e->hash > it->cycle) {
+				// Already returned this.
+				// Set last_hash to impossible value and
+				// break it->changes, so that check at top of
+				// hash_next will be used if we get called again.
+				it->last_hash = ~(uintptr_t)0;
+				it->changes--;
+				return (0);
+			}
 			it->last_hash = e->hash;
 			sub->e = HASH_OFFSET (e, elemsize);
 			return (e->data);
@@ -565,22 +573,34 @@ hash_next (struct hash_iter *it)
 			sub = &it->subtable_state[it->i];
 			sub->e = e = st->entry;
 			sub->start = st->entry;
-			sub->end = end = st->end;
+			sub->last = last = st->last;
 		}
 	}
 }
 
 static void
-hash_iter_init (Hmap *h, struct hash_iter *it)
+hash_iter_init (MapType *t, Hmap *h, struct hash_iter *it)
 {
 	it->elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
 	it->changes = h->changes;
 	it->i = 0;
 	it->h = h;
+	it->t = t;
 	it->last_hash = 0;
 	it->subtable_state[0].e = h->st->entry;
 	it->subtable_state[0].start = h->st->entry;
-	it->subtable_state[0].end = h->st->end;
+	it->subtable_state[0].last = h->st->last;
+	
+	// fastrand1 returns 31 useful bits.
+	// We don't care about not having a bottom bit but we
+	// do want top bits.
+	if(sizeof(void*) == 8)
+		it->cycle = (uint64)runtime·fastrand1()<<33 | (uint64)runtime·fastrand1()<<2;
+	else
+		it->cycle = runtime·fastrand1()<<1;
+	it->cycled = false;
+	it->last_hash = it->cycle;
+	iter_restart(it, it->h->st, 0);
 }
 
 static void
@@ -588,11 +608,11 @@ clean_st (struct hash_subtable *st, int32 *slots, int32 *used)
 {
 	int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
 	struct hash_entry *e = st->entry;
-	struct hash_entry *end = st->end;
-	int32 lslots = (((byte *) end) - (byte *) e) / elemsize;
+	struct hash_entry *last = st->last;
+	int32 lslots = (((byte *) (last+1)) - (byte *) e) / elemsize;
 	int32 lused = 0;
 
-	while (e != end) {
+	while (e <= last) {
 		hash_hash_t hash = e->hash;
 		if ((hash & HASH_MASK) == HASH_SUBHASH) {
 			clean_st (*(struct hash_subtable **)e->data, slots, used);
@@ -627,7 +647,7 @@ hash_visit_internal (struct hash_subtable *st,
 	int32 shift = HASH_BITS - (used + st->power);
 	int32 i = 0;
 
-	while (e != st->end) {
+	while (e <= st->last) {
 		int32 index = ((e->hash >> (shift - 1)) >> 1) & ((1 << st->power) - 1);
 		if ((e->hash & HASH_MASK) == HASH_SUBHASH) {
 			  (*data_visit) (arg, level, e->data);
@@ -662,24 +682,6 @@ enum {
 	MaxValsize = 256 - 64
 };
 
-static void
-donothing(uint32 s, void *a, void *b)
-{
-	USED(s);
-	USED(a);
-	USED(b);
-}
-
-static void
-freedata(uint32 datavo, void *a, void *b)
-{
-	void *p;
-
-	USED(a);
-	p = *(void**)((byte*)b + datavo);
-	free(p);
-}
-
 static void**
 hash_indirect(Hmap *h, void *p)
 {
@@ -695,8 +697,7 @@ Hmap*
 runtime·makemap_c(MapType *typ, int64 hint)
 {
 	Hmap *h;
-	int32 keyalg, valalg, keysize, valsize, valsize_in_hash;
-	void (*data_del)(uint32, void*, void*);
+	int32 valsize_in_hash;
 	Type *key, *val;
 	
 	key = typ->key;
@@ -705,68 +706,30 @@ runtime·makemap_c(MapType *typ, int64 hint)
 	if(hint < 0 || (int32)hint != hint)
 		runtime·panicstring("makemap: size out of range");
 
-	keyalg = key->alg;
-	valalg = val->alg;
-	keysize = key->size;
-	valsize = val->size;
-
-	if(keyalg >= nelem(runtime·algarray) || runtime·algarray[keyalg].hash == runtime·nohash) {
-		runtime·printf("map(keyalg=%d)\n", keyalg);
+	if(key->alg->hash == runtime·nohash)
 		runtime·throw("runtime.makemap: unsupported map key type");
-	}
-
-	if(valalg >= nelem(runtime·algarray)) {
-		runtime·printf("map(valalg=%d)\n", valalg);
-		runtime·throw("runtime.makemap: unsupported map value type");
-	}
 
 	h = runtime·mal(sizeof(*h));
 
-	valsize_in_hash = valsize;
-	data_del = donothing;
-	if (valsize > MaxValsize) {
+	valsize_in_hash = val->size;
+	if (val->size > MaxValsize) {
 		h->indirectval = 1;
-		data_del = freedata;
 		valsize_in_hash = sizeof(void*);
 	} 
 
-	// align value inside data so that mark-sweep gc can find it.
-	// might remove in the future and just assume datavo == keysize.
-	h->datavo = keysize;
+	// Align value inside data so that mark-sweep gc can find it.
+	h->valoff = key->size;
 	if(valsize_in_hash >= sizeof(void*))
-		h->datavo = runtime·rnd(keysize, sizeof(void*));
-
-	hash_init(h, h->datavo+valsize_in_hash,
-		runtime·algarray[keyalg].hash,
-		runtime·algarray[keyalg].equal,
-		data_del,
-		hint);
+		h->valoff = runtime·rnd(key->size, sizeof(void*));
 
-	h->keysize = keysize;
-	h->valsize = valsize;
-	h->keyalg = &runtime·algarray[keyalg];
-	h->valalg = &runtime·algarray[valalg];
+	hash_init(h, h->valoff+valsize_in_hash, hint);
 
 	// these calculations are compiler dependent.
 	// figure out offsets of map call arguments.
 
-	// func() (key, val)
-	h->ko0 = runtime·rnd(sizeof(h), Structrnd);
-	h->vo0 = runtime·rnd(h->ko0+keysize, val->align);
-
-	// func(key) (val[, pres])
-	h->ko1 = runtime·rnd(sizeof(h), key->align);
-	h->vo1 = runtime·rnd(h->ko1+keysize, Structrnd);
-	h->po1 = h->vo1 + valsize;
-
-	// func(key, val[, pres])
-	h->ko2 = runtime·rnd(sizeof(h), key->align);
-	h->vo2 = runtime·rnd(h->ko2+keysize, val->align);
-	h->po2 = h->vo2 + valsize;
-
 	if(debug) {
-		runtime·printf("makemap: map=%p; keysize=%d; valsize=%d; keyalg=%d; valalg=%d; offsets=%d,%d; %d,%d,%d; %d,%d,%d\n",
-			h, keysize, valsize, keyalg, valalg, h->ko0, h->vo0, h->ko1, h->vo1, h->po1, h->ko2, h->vo2, h->po2);
+		runtime·printf("makemap: map=%p; keysize=%p; valsize=%p; keyalg=%p; valalg=%p\n",
+			h, key->size, val->size, key->alg, val->alg);
 	}
 
 	return h;
@@ -795,9 +758,9 @@ runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres)
 	byte *res;
 	Type *elem;
 
+	elem = t->elem;
 	if(h == nil) {
-		elem = t->elem;
-		runtime·algarray[elem->alg].copy(elem->size, av, nil);
+		elem->alg->copy(elem->size, av, nil);
 		*pres = false;
 		return;
 	}
@@ -806,12 +769,12 @@ runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres)
 		runtime·gosched();
 
 	res = nil;
-	if(hash_lookup(h, ak, (void**)&res)) {
+	if(hash_lookup(t, h, ak, (void**)&res)) {
 		*pres = true;
-		h->valalg->copy(h->valsize, av, hash_indirect(h, res+h->datavo));
+		elem->alg->copy(elem->size, av, hash_indirect(h, res+h->valoff));
 	} else {
 		*pres = false;
-		h->valalg->copy(h->valsize, av, nil);
+		elem->alg->copy(elem->size, av, nil);
 	}
 }
 
@@ -823,13 +786,8 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
 	byte *ak, *av;
 	bool pres;
 
-	if(h == nil) {
-		ak = (byte*)(&h + 1);
-		av = ak + runtime·rnd(t->key->size, Structrnd);
-	} else {
-		ak = (byte*)&h + h->ko1;
-		av = (byte*)&h + h->vo1;
-	}
+	ak = (byte*)(&h + 1);
+	av = ak + runtime·rnd(t->key->size, Structrnd);
 
 	runtime·mapaccess(t, h, ak, av, &pres);
 
@@ -837,9 +795,9 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
 		runtime·prints("runtime.mapaccess1: map=");
 		runtime·printpointer(h);
 		runtime·prints("; key=");
-		h->keyalg->print(h->keysize, ak);
+		t->key->alg->print(t->key->size, ak);
 		runtime·prints("; val=");
-		h->valalg->print(h->valsize, av);
+		t->elem->alg->print(t->elem->size, av);
 		runtime·prints("; pres=");
 		runtime·printbool(pres);
 		runtime·prints("\n");
@@ -853,15 +811,9 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...)
 {
 	byte *ak, *av, *ap;
 
-	if(h == nil) {
-		ak = (byte*)(&h + 1);
-		av = ak + runtime·rnd(t->key->size, Structrnd);
-		ap = av + t->elem->size;
-	} else {
-		ak = (byte*)&h + h->ko1;
-		av = (byte*)&h + h->vo1;
-		ap = (byte*)&h + h->po1;
-	}
+	ak = (byte*)(&h + 1);
+	av = ak + runtime·rnd(t->key->size, Structrnd);
+	ap = av + t->elem->size;
 
 	runtime·mapaccess(t, h, ak, av, ap);
 
@@ -869,9 +821,9 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...)
 		runtime·prints("runtime.mapaccess2: map=");
 		runtime·printpointer(h);
 		runtime·prints("; key=");
-		h->keyalg->print(h->keysize, ak);
+		t->key->alg->print(t->key->size, ak);
 		runtime·prints("; val=");
-		h->valalg->print(h->valsize, av);
+		t->elem->alg->print(t->key->size, av);
 		runtime·prints("; pres=");
 		runtime·printbool(*ap);
 		runtime·prints("\n");
@@ -910,33 +862,31 @@ runtime·mapassign(MapType *t, Hmap *h, byte *ak, byte *av)
 	byte *res;
 	int32 hit;
 
-	USED(t);
-
 	if(h == nil)
 		runtime·panicstring("assignment to entry in nil map");
 
 	if(runtime·gcwaiting)
 		runtime·gosched();
 
-	res = nil;
 	if(av == nil) {
-		hash_remove(h, ak, (void**)&res);
+		hash_remove(t, h, ak);
 		return;
 	}
 
-	hit = hash_insert(h, ak, (void**)&res);
+	res = nil;
+	hit = hash_insert(t, h, ak, (void**)&res);
 	if(!hit && h->indirectval)
-		*(void**)(res+h->datavo) = runtime·mal(h->valsize);
-	h->keyalg->copy(h->keysize, res, ak);
-	h->valalg->copy(h->valsize, hash_indirect(h, res+h->datavo), av);
+		*(void**)(res+h->valoff) = runtime·mal(t->elem->size);
+	t->key->alg->copy(t->key->size, res, ak);
+	t->elem->alg->copy(t->elem->size, hash_indirect(h, res+h->valoff), av);
 
 	if(debug) {
 		runtime·prints("mapassign: map=");
 		runtime·printpointer(h);
 		runtime·prints("; key=");
-		h->keyalg->print(h->keysize, ak);
+		t->key->alg->print(t->key->size, ak);
 		runtime·prints("; val=");
-		h->valalg->print(h->valsize, av);
+		t->elem->alg->print(t->elem->size, av);
 		runtime·prints("; hit=");
 		runtime·printint(hit);
 		runtime·prints("; res=");
@@ -955,36 +905,30 @@ runtime·mapassign1(MapType *t, Hmap *h, ...)
 	if(h == nil)
 		runtime·panicstring("assignment to entry in nil map");
 
-	ak = (byte*)&h + h->ko2;
-	av = (byte*)&h + h->vo2;
+	ak = (byte*)(&h + 1);
+	av = ak + runtime·rnd(t->key->size, t->elem->align);
 
 	runtime·mapassign(t, h, ak, av);
 }
 
-// mapassign2(mapType *type, hmap *map[any]any, key any, val any, pres bool);
+// mapdelete(mapType *type, hmap *map[any]any, key any)
 #pragma textflag 7
 void
-runtime·mapassign2(MapType *t, Hmap *h, ...)
+runtime·mapdelete(MapType *t, Hmap *h, ...)
 {
-	byte *ak, *av, *ap;
+	byte *ak;
 
 	if(h == nil)
-		runtime·panicstring("assignment to entry in nil map");
-
-	ak = (byte*)&h + h->ko2;
-	av = (byte*)&h + h->vo2;
-	ap = (byte*)&h + h->po2;
+		runtime·panicstring("deletion of entry in nil map");
 
-	if(*ap == false)
-		av = nil;	// delete
-
-	runtime·mapassign(t, h, ak, av);
+	ak = (byte*)(&h + 1);
+	runtime·mapassign(t, h, ak, nil);
 
 	if(debug) {
-		runtime·prints("mapassign2: map=");
+		runtime·prints("mapdelete: map=");
 		runtime·printpointer(h);
 		runtime·prints("; key=");
-		h->keyalg->print(h->keysize, ak);
+		t->key->alg->print(t->key->size, ak);
 		runtime·prints("\n");
 	}
 }
@@ -1000,11 +944,11 @@ reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
 
 	if(h == nil)
 		runtime·panicstring("assignment to entry in nil map");
-	if(h->keysize <= sizeof(key))
+	if(t->key->size <= sizeof(key))
 		ak = (byte*)&key;
 	else
 		ak = (byte*)key;
-	if(h->valsize <= sizeof(val))
+	if(t->elem->size <= sizeof(val))
 		av = (byte*)&val;
 	else
 		av = (byte*)val;
@@ -1015,13 +959,13 @@ reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
 
 // mapiterinit(mapType *type, hmap *map[any]any, hiter *any);
 void
-runtime·mapiterinit(MapType*, Hmap *h, struct hash_iter *it)
+runtime·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
 {
 	if(h == nil) {
 		it->data = nil;
 		return;
 	}
-	hash_iter_init(h, it);
+	hash_iter_init(t, h, it);
 	it->data = hash_next(it);
 	if(debug) {
 		runtime·prints("runtime.mapiterinit: map=");
@@ -1076,15 +1020,17 @@ runtime·mapiter1(struct hash_iter *it, ...)
 {
 	Hmap *h;
 	byte *ak, *res;
+	Type *key;
 
 	h = it->h;
-	ak = (byte*)&it + h->ko0;
+	ak = (byte*)(&it + 1);
 
 	res = it->data;
 	if(res == nil)
 		runtime·throw("runtime.mapiter1: key:val nil pointer");
 
-	h->keyalg->copy(h->keysize, ak, res);
+	key = it->t->key;
+	key->alg->copy(key->size, ak, res);
 
 	if(debug) {
 		runtime·prints("mapiter2: iter=");
@@ -1098,14 +1044,14 @@ runtime·mapiter1(struct hash_iter *it, ...)
 bool
 runtime·mapiterkey(struct hash_iter *it, void *ak)
 {
-	Hmap *h;
 	byte *res;
+	Type *key;
 
-	h = it->h;
 	res = it->data;
 	if(res == nil)
 		return false;
-	h->keyalg->copy(h->keysize, ak, res);
+	key = it->t->key;
+	key->alg->copy(key->size, ak, res);
 	return true;
 }
 
@@ -1116,20 +1062,20 @@ runtime·mapiterkey(struct hash_iter *it, void *ak)
 void
 reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok)
 {
-	Hmap *h;
 	byte *res;
+	Type *tkey;
 
 	key = 0;
 	ok = false;
-	h = it->h;
 	res = it->data;
 	if(res == nil) {
 		key = 0;
 		ok = false;
 	} else {
+		tkey = it->t->key;
 		key = 0;
-		if(h->keysize <= sizeof(key))
-			h->keyalg->copy(h->keysize, (byte*)&key, res);
+		if(tkey->size <= sizeof(key))
+			tkey->alg->copy(tkey->size, (byte*)&key, res);
 		else
 			key = (uintptr)res;
 		ok = true;
@@ -1158,17 +1104,19 @@ runtime·mapiter2(struct hash_iter *it, ...)
 {
 	Hmap *h;
 	byte *ak, *av, *res;
+	MapType *t;
 
-	h = it->h;
-	ak = (byte*)&it + h->ko0;
-	av = (byte*)&it + h->vo0;
+	t = it->t;
+	ak = (byte*)(&it + 1);
+	av = ak + runtime·rnd(t->key->size, t->elem->align);
 
 	res = it->data;
 	if(res == nil)
 		runtime·throw("runtime.mapiter2: key:val nil pointer");
 
-	h->keyalg->copy(h->keysize, ak, res);
-	h->valalg->copy(h->valsize, av, hash_indirect(h, res+h->datavo));
+	h = it->h;
+	t->key->alg->copy(t->key->size, ak, res);
+	t->elem->alg->copy(t->elem->size, av, hash_indirect(h, res+h->valoff));
 
 	if(debug) {
 		runtime·prints("mapiter2: iter=");
diff --git a/src/pkg/runtime/hashmap.h b/src/pkg/runtime/hashmap.h
index 19ff416..4c10cf6 100644
--- a/src/pkg/runtime/hashmap.h
+++ b/src/pkg/runtime/hashmap.h
@@ -66,7 +66,7 @@
 #define	malloc		runtime·mal
 #define	memset(a,b,c)	runtime·memclr((byte*)(a), (uint32)(c))
 #define	memcpy(a,b,c)	runtime·memmove((byte*)(a),(byte*)(b),(uint32)(c))
-#define	assert(a)	if(!(a)) runtime·throw("assert")
+#define	assert(a)	if(!(a)) runtime·throw("hashmap assert")
 #define free(x)	runtime·free(x)
 #define memmove(a,b,c)	runtime·memmove(a, b, c)
 
@@ -82,12 +82,15 @@ struct hash_iter {
 	int32	elemsize;	/* size of elements in table */
 	int32	changes;	/* number of changes observed last time */
 	int32	i;		/* stack pointer in subtable_state */
+	bool cycled;		/* have reached the end and wrapped to 0 */
 	hash_hash_t last_hash;	/* last hash value returned */
+	hash_hash_t cycle;	/* hash value where we started */
 	struct Hmap *h;		/* the hash table */
+	MapType *t;			/* the map type */
 	struct hash_iter_sub {
 		struct hash_entry *e;		/* pointer into subtable */
 		struct hash_entry *start;	/* start of subtable */
-		struct hash_entry *end;		/* end of subtable */
+		struct hash_entry *last;		/* last entry in subtable */
 	} subtable_state[4];	/* Should be large enough unless the hashing is
 				   so bad that many distinct data values hash
 				   to the same hash value.  */
diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c
index 000f834..9f70935 100644
--- a/src/pkg/runtime/iface.c
+++ b/src/pkg/runtime/iface.c
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "type.h"
 #include "malloc.h"
 
@@ -158,17 +159,18 @@ out:
 static void
 copyin(Type *t, void *src, void **dst)
 {
-	int32 wid, alg;
+	uintptr size;
 	void *p;
+	Alg *alg;
 
-	wid = t->size;
+	size = t->size;
 	alg = t->alg;
 
-	if(wid <= sizeof(*dst))
-		runtime·algarray[alg].copy(wid, dst, src);
+	if(size <= sizeof(*dst))
+		alg->copy(size, dst, src);
 	else {
-		p = runtime·mal(wid);
-		runtime·algarray[alg].copy(wid, p, src);
+		p = runtime·mal(size);
+		alg->copy(size, p, src);
 		*dst = p;
 	}
 }
@@ -176,15 +178,16 @@ copyin(Type *t, void *src, void **dst)
 static void
 copyout(Type *t, void **src, void *dst)
 {
-	int32 wid, alg;
+	uintptr size;
+	Alg *alg;
 
-	wid = t->size;
+	size = t->size;
 	alg = t->alg;
 
-	if(wid <= sizeof(*src))
-		runtime·algarray[alg].copy(wid, dst, src);
+	if(size <= sizeof(*src))
+		alg->copy(size, dst, src);
 	else
-		runtime·algarray[alg].copy(wid, dst, *src);
+		alg->copy(size, dst, *src);
 }
 
 // func convT2I(typ *byte, typ2 *byte, elem any) (ret any)
@@ -547,23 +550,27 @@ runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok)
 static uintptr
 ifacehash1(void *data, Type *t)
 {
-	int32 alg, wid;
+	Alg *alg;
+	uintptr size, h;
 	Eface err;
 
 	if(t == nil)
 		return 0;
 
 	alg = t->alg;
-	wid = t->size;
-	if(runtime·algarray[alg].hash == runtime·nohash) {
+	size = t->size;
+	if(alg->hash == runtime·nohash) {
 		// calling nohash will panic too,
 		// but we can print a better error.
 		runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err);
 		runtime·panic(err);
 	}
-	if(wid <= sizeof(data))
-		return runtime·algarray[alg].hash(wid, &data);
-	return runtime·algarray[alg].hash(wid, data);
+	h = 0;
+	if(size <= sizeof(data))
+		alg->hash(&h, size, &data);
+	else
+		alg->hash(&h, size, data);
+	return h;
 }
 
 uintptr
@@ -583,22 +590,27 @@ runtime·efacehash(Eface a)
 static bool
 ifaceeq1(void *data1, void *data2, Type *t)
 {
-	int32 alg, wid;
+	uintptr size;
+	Alg *alg;
 	Eface err;
+	bool eq;
 
 	alg = t->alg;
-	wid = t->size;
+	size = t->size;
 
-	if(runtime·algarray[alg].equal == runtime·noequal) {
+	if(alg->equal == runtime·noequal) {
 		// calling noequal will panic too,
 		// but we can print a better error.
 		runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err);
 		runtime·panic(err);
 	}
 
-	if(wid <= sizeof(data1))
-		return runtime·algarray[alg].equal(wid, &data1, &data2);
-	return runtime·algarray[alg].equal(wid, data1, data2);
+	eq = 0;
+	if(size <= sizeof(data1))
+		alg->equal(&eq, size, &data1, &data2);
+	else
+		alg->equal(&eq, size, data1, data2);
+	return eq;
 }
 
 bool
@@ -700,7 +712,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
 		if(e.type->size <= sizeof(uintptr)) {
 			// Copy data into x ...
 			x = 0;
-			runtime·algarray[e.type->alg].copy(e.type->size, &x, &e.data);
+			e.type->alg->copy(e.type->size, &x, &e.data);
 
 			// but then build pointer to x so that Reflect
 			// always returns pointer to data.
@@ -710,7 +722,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
 			// Already a pointer, but still make a copy,
 			// to preserve value semantics for interface data.
 			p = runtime·mal(e.type->size);
-			runtime·algarray[e.type->alg].copy(e.type->size, p, e.data);
+			e.type->alg->copy(e.type->size, p, e.data);
 		}
 		retaddr = p;
 	}
@@ -733,7 +745,7 @@ unsafe·Unreflect(Eface typ, void *addr, Eface e)
 	// Interface holds either pointer to data
 	// or copy of original data.
 	if(e.type->size <= sizeof(uintptr))
-		runtime·algarray[e.type->alg].copy(e.type->size, &e.data, addr);
+		e.type->alg->copy(e.type->size, &e.data, addr);
 	else {
 		// Easier: already a pointer to data.
 		// TODO(rsc): Should this make a copy?
diff --git a/src/pkg/runtime/linux/386/defs.h b/src/pkg/runtime/linux/386/defs.h
deleted file mode 100644
index 73fe23e..0000000
--- a/src/pkg/runtime/linux/386/defs.h
+++ /dev/null
@@ -1,191 +0,0 @@
-// godefs -f -m32 -f -I/home/rsc/pub/linux-2.6/arch/x86/include -f -I/home/rsc/pub/linux-2.6/include -f -D_LOOSE_KERNEL_NAMES -f -D__ARCH_SI_UID_T=__kernel_uid32_t defs2.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x20,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_RESTART = 0x10000000,
-	SA_ONSTACK = 0x8000000,
-	SA_RESTORER = 0x4000000,
-	SA_SIGINFO = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGBUS = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGUSR1 = 0xa,
-	SIGSEGV = 0xb,
-	SIGUSR2 = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGSTKFLT = 0x10,
-	SIGCHLD = 0x11,
-	SIGCONT = 0x12,
-	SIGSTOP = 0x13,
-	SIGTSTP = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGURG = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGIO = 0x1d,
-	SIGPWR = 0x1e,
-	SIGSYS = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-	O_RDONLY = 0,
-	O_CLOEXEC = 02000000,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Fpreg Fpreg;
-struct Fpreg {
-	uint16 significand[4];
-	uint16 exponent;
-};
-
-typedef struct Fpxreg Fpxreg;
-struct Fpxreg {
-	uint16 significand[4];
-	uint16 exponent;
-	uint16 padding[3];
-};
-
-typedef struct Xmmreg Xmmreg;
-struct Xmmreg {
-	uint32 element[4];
-};
-
-typedef struct Fpstate Fpstate;
-struct Fpstate {
-	uint32 cw;
-	uint32 sw;
-	uint32 tag;
-	uint32 ipoff;
-	uint32 cssel;
-	uint32 dataoff;
-	uint32 datasel;
-	Fpreg _st[8];
-	uint16 status;
-	uint16 magic;
-	uint32 _fxsr_env[6];
-	uint32 mxcsr;
-	uint32 reserved;
-	Fpxreg _fxsr_st[8];
-	Xmmreg _xmm[8];
-	uint32 padding1[44];
-	byte Pad_godefs_0[48];
-};
-
-typedef struct Timespec Timespec;
-struct Timespec {
-	int32 tv_sec;
-	int32 tv_nsec;
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int32 tv_sec;
-	int32 tv_usec;
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
-	void *k_sa_handler;
-	uint32 sa_flags;
-	void *sa_restorer;
-	uint32 sa_mask;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	byte _sifields[116];
-};
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	void *ss_sp;
-	int32 ss_flags;
-	uint32 ss_size;
-};
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	uint16 gs;
-	uint16 __gsh;
-	uint16 fs;
-	uint16 __fsh;
-	uint16 es;
-	uint16 __esh;
-	uint16 ds;
-	uint16 __dsh;
-	uint32 edi;
-	uint32 esi;
-	uint32 ebp;
-	uint32 esp;
-	uint32 ebx;
-	uint32 edx;
-	uint32 ecx;
-	uint32 eax;
-	uint32 trapno;
-	uint32 err;
-	uint32 eip;
-	uint16 cs;
-	uint16 __csh;
-	uint32 eflags;
-	uint32 esp_at_signal;
-	uint16 ss;
-	uint16 __ssh;
-	Fpstate *fpstate;
-	uint32 oldmask;
-	uint32 cr2;
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
-	uint32 uc_flags;
-	Ucontext *uc_link;
-	Sigaltstack uc_stack;
-	Sigcontext uc_mcontext;
-	uint32 uc_sigmask;
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/linux/386/signal.c b/src/pkg/runtime/linux/386/signal.c
deleted file mode 100644
index 4045b2e..0000000
--- a/src/pkg/runtime/linux/386/signal.c
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
-	runtime·printf("eax     %x\n", r->eax);
-	runtime·printf("ebx     %x\n", r->ebx);
-	runtime·printf("ecx     %x\n", r->ecx);
-	runtime·printf("edx     %x\n", r->edx);
-	runtime·printf("edi     %x\n", r->edi);
-	runtime·printf("esi     %x\n", r->esi);
-	runtime·printf("ebp     %x\n", r->ebp);
-	runtime·printf("esp     %x\n", r->esp);
-	runtime·printf("eip     %x\n", r->eip);
-	runtime·printf("eflags  %x\n", r->eflags);
-	runtime·printf("cs      %x\n", r->cs);
-	runtime·printf("fs      %x\n", r->fs);
-	runtime·printf("gs      %x\n", r->gs);
-}
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void runtime·sigtramp(void);
-extern void runtime·sigignore(void);	// just returns
-extern void runtime·sigreturn(void);	// calls runtime·sigreturn
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Ucontext *uc;
-	Sigcontext *r;
-	uintptr *sp;
-
-	uc = context;
-	r = &uc->uc_mcontext;
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = ((uintptr*)info)[3];
-		gp->sigpc = r->eip;
-
-		// Only push runtime·sigpanic if r->eip != 0.
-		// If r->eip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->eip != 0) {
-			sp = (uintptr*)r->esp;
-			*--sp = r->eip;
-			r->esp = (uintptr)sp;
-		}
-		r->eip = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG)
-		runtime·printf("Signal %d\n", sig);
-	else
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-
-	runtime·printf("PC=%X\n", r->eip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	Sigaltstack st;
-
-	st.ss_sp = p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	sa.sa_restorer = (void*)runtime·sigreturn;
-	if(fn == runtime·sighandler)
-		fn = (void*)runtime·sigtramp;
-	sa.k_sa_handler = fn;
-	runtime·rt_sigaction(i, &sa, nil, 8);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
-
-#define AT_NULL		0
-#define AT_SYSINFO	32
-extern uint32 runtime·_vdso;
-
-#pragma textflag 7
-void runtime·linux_setup_vdso(int32 argc, void *argv_list)
-{
-	byte **argv = &argv_list;
-	byte **envp;
-	uint32 *auxv;
-
-	// skip envp to get to ELF auxiliary vector.
-	for(envp = &argv[argc+1]; *envp != nil; envp++)
-		;
-	envp++;
-	
-	for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
-		if(auxv[0] == AT_SYSINFO) {
-			runtime·_vdso = auxv[1];
-			break;
-		}
-	}		
-}
diff --git a/src/pkg/runtime/linux/386/sys.s b/src/pkg/runtime/linux/386/sys.s
deleted file mode 100644
index f87420f..0000000
--- a/src/pkg/runtime/linux/386/sys.s
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//
-// System calls and other sys.stuff for 386, Linux
-//
-
-#include "386/asm.h"
-
-TEXT runtime·exit(SB),7,$0
-	MOVL	$252, AX	// syscall number
-	MOVL	4(SP), BX
-	CALL	*runtime·_vdso(SB)
-	INT $3	// not reached
-	RET
-
-TEXT runtime·exit1(SB),7,$0
-	MOVL	$1, AX	// exit - exit the current os thread
-	MOVL	4(SP), BX
-	CALL	*runtime·_vdso(SB)
-	INT $3	// not reached
-	RET
-
-TEXT runtime·open(SB),7,$0
-	MOVL	$5, AX		// syscall - open
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	MOVL	12(SP), DX
-	CALL	*runtime·_vdso(SB)
-	RET
-
-TEXT runtime·close(SB),7,$0
-	MOVL	$6, AX		// syscall - close
-	MOVL	4(SP), BX
-	CALL	*runtime·_vdso(SB)
-	RET
-
-TEXT runtime·write(SB),7,$0
-	MOVL	$4, AX		// syscall - write
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	MOVL	12(SP), DX
-	CALL	*runtime·_vdso(SB)
-	RET
-
-TEXT runtime·read(SB),7,$0
-	MOVL	$3, AX		// syscall - read
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	MOVL	12(SP), DX
-	CALL	*runtime·_vdso(SB)
-	RET
-
-TEXT runtime·raisesigpipe(SB),7,$12
-	MOVL	$224, AX	// syscall - gettid
-	CALL	*runtime·_vdso(SB)
-	MOVL	AX, 0(SP)	// arg 1 tid
-	MOVL	$13, 4(SP)	// arg 2 SIGPIPE
-	MOVL	$238, AX	// syscall - tkill
-	CALL	*runtime·_vdso(SB)
-	RET
-
-TEXT runtime·setitimer(SB),7,$0-24
-	MOVL	$104, AX			// syscall - setitimer
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	MOVL	12(SP), DX
-	CALL	*runtime·_vdso(SB)
-	RET
-
-TEXT runtime·mincore(SB),7,$0-24
-	MOVL	$218, AX			// syscall - mincore
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	MOVL	12(SP), DX
-	CALL	*runtime·_vdso(SB)
-	RET
-
-TEXT runtime·gettime(SB), 7, $32
-	MOVL	$78, AX			// syscall - gettimeofday
-	LEAL	8(SP), BX
-	MOVL	$0, CX
-	MOVL	$0, DX
-	CALL	*runtime·_vdso(SB)
-
-	MOVL	8(SP), BX	// sec
-	MOVL	sec+0(FP), DI
-	MOVL	BX, (DI)
-	MOVL	$0, 4(DI)	// zero extend 32 -> 64 bits
-
-	MOVL	12(SP), BX	// usec
-	MOVL	usec+4(FP), DI
-	MOVL	BX, (DI)
-	RET
-
-TEXT runtime·rt_sigaction(SB),7,$0
-	MOVL	$174, AX		// syscall - rt_sigaction
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	MOVL	12(SP), DX
-	MOVL	16(SP), SI
-	CALL	*runtime·_vdso(SB)
-	RET
-
-TEXT runtime·sigtramp(SB),7,$44
-	get_tls(CX)
-	
-	// save g
-	MOVL	g(CX), DI
-	MOVL	DI, 20(SP)
-	
-	// g = m->gsignal
-	MOVL	m(CX), BX
-	MOVL	m_gsignal(BX), BX
-	MOVL	BX, g(CX)
-	
-	// copy arguments for call to sighandler
-	MOVL	sig+0(FP), BX
-	MOVL	BX, 0(SP)
-	MOVL	info+4(FP), BX
-	MOVL	BX, 4(SP)
-	MOVL	context+8(FP), BX
-	MOVL	BX, 8(SP)
-	MOVL	DI, 12(SP)
-
-	CALL	runtime·sighandler(SB)
-	
-	// restore g
-	get_tls(CX)
-	MOVL	20(SP), BX
-	MOVL	BX, g(CX)
-	
-	RET
-
-TEXT runtime·sigignore(SB),7,$0
-	RET
-
-TEXT runtime·sigreturn(SB),7,$0
-	MOVL	$173, AX	// rt_sigreturn
-	// Sigreturn expects same SP as signal handler,
-	// so cannot CALL *runtime._vsdo(SB) here.
-	INT	$0x80
-	INT $3	// not reached
-	RET
-
-TEXT runtime·mmap(SB),7,$0
-	MOVL	$192, AX	// mmap2
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	MOVL	12(SP), DX
-	MOVL	16(SP), SI
-	MOVL	20(SP), DI
-	MOVL	24(SP), BP
-	SHRL	$12, BP
-	CALL	*runtime·_vdso(SB)
-	CMPL	AX, $0xfffff001
-	JLS	3(PC)
-	NOTL	AX
-	INCL	AX
-	RET
-
-TEXT runtime·munmap(SB),7,$0
-	MOVL	$91, AX	// munmap
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	CALL	*runtime·_vdso(SB)
-	CMPL	AX, $0xfffff001
-	JLS	2(PC)
-	INT $3
-	RET
-
-// int32 futex(int32 *uaddr, int32 op, int32 val,
-//	struct timespec *timeout, int32 *uaddr2, int32 val2);
-TEXT runtime·futex(SB),7,$0
-	MOVL	$240, AX	// futex
-	MOVL	4(SP), BX
-	MOVL	8(SP), CX
-	MOVL	12(SP), DX
-	MOVL	16(SP), SI
-	MOVL	20(SP), DI
-	MOVL	24(SP), BP
-	CALL	*runtime·_vdso(SB)
-	RET
-
-// int32 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·clone(SB),7,$0
-	MOVL	$120, AX	// clone
-	MOVL	flags+4(SP), BX
-	MOVL	stack+8(SP), CX
-	MOVL	$0, DX	// parent tid ptr
-	MOVL	$0, DI	// child tid ptr
-
-	// Copy m, g, fn off parent stack for use by child.
-	SUBL	$16, CX
-	MOVL	mm+12(SP), SI
-	MOVL	SI, 0(CX)
-	MOVL	gg+16(SP), SI
-	MOVL	SI, 4(CX)
-	MOVL	fn+20(SP), SI
-	MOVL	SI, 8(CX)
-	MOVL	$1234, 12(CX)
-
-	// cannot use CALL *runtime·_vdso(SB) here, because
-	// the stack changes during the system call (after 
-	// CALL *runtime·_vdso(SB), the child is still using
-	// the parent's stack when executing its RET instruction).
-	INT	$0x80
-
-	// In parent, return.
-	CMPL	AX, $0
-	JEQ	2(PC)
-	RET
-
-	// Paranoia: check that SP is as we expect.
-	MOVL	12(SP), BP
-	CMPL	BP, $1234
-	JEQ	2(PC)
-	INT	$3
-
-	// Initialize AX to Linux tid
-	MOVL	$224, AX
-	CALL	*runtime·_vdso(SB)
-
-	// In child on new stack.  Reload registers (paranoia).
-	MOVL	0(SP), BX	// m
-	MOVL	4(SP), DX	// g
-	MOVL	8(SP), SI	// fn
-
-	MOVL	AX, m_procid(BX)	// save tid as m->procid
-
-	// set up ldt 7+id to point at m->tls.
-	// newosproc left the id in tls[0].
-	LEAL	m_tls(BX), BP
-	MOVL	0(BP), DI
-	ADDL	$7, DI	// m0 is LDT#7. count up.
-	// setldt(tls#, &tls, sizeof tls)
-	PUSHAL	// save registers
-	PUSHL	$32	// sizeof tls
-	PUSHL	BP	// &tls
-	PUSHL	DI	// tls #
-	CALL	runtime·setldt(SB)
-	POPL	AX
-	POPL	AX
-	POPL	AX
-	POPAL
-
-	// Now segment is established.  Initialize m, g.
-	get_tls(AX)
-	MOVL	DX, g(AX)
-	MOVL	BX, m(AX)
-
-	CALL	runtime·stackcheck(SB)	// smashes AX, CX
-	MOVL	0(DX), DX	// paranoia; check they are not nil
-	MOVL	0(BX), BX
-
-	// more paranoia; check that stack splitting code works
-	PUSHAL
-	CALL	runtime·emptyfunc(SB)
-	POPAL
-
-	CALL	SI	// fn()
-	CALL	runtime·exit1(SB)
-	MOVL	$0x1234, 0x1005
-	RET
-
-TEXT runtime·sigaltstack(SB),7,$-8
-	MOVL	$186, AX	// sigaltstack
-	MOVL	new+4(SP), BX
-	MOVL	old+8(SP), CX
-	CALL	*runtime·_vdso(SB)
-	CMPL	AX, $0xfffff001
-	JLS	2(PC)
-	INT	$3
-	RET
-
-// <asm-i386/ldt.h>
-// struct user_desc {
-//	unsigned int  entry_number;
-//	unsigned long base_addr;
-//	unsigned int  limit;
-//	unsigned int  seg_32bit:1;
-//	unsigned int  contents:2;
-//	unsigned int  read_exec_only:1;
-//	unsigned int  limit_in_pages:1;
-//	unsigned int  seg_not_present:1;
-//	unsigned int  useable:1;
-// };
-#define SEG_32BIT 0x01
-// contents are the 2 bits 0x02 and 0x04.
-#define CONTENTS_DATA 0x00
-#define CONTENTS_STACK 0x02
-#define CONTENTS_CODE 0x04
-#define READ_EXEC_ONLY 0x08
-#define LIMIT_IN_PAGES 0x10
-#define SEG_NOT_PRESENT 0x20
-#define USEABLE 0x40
-
-// setldt(int entry, int address, int limit)
-TEXT runtime·setldt(SB),7,$32
-	MOVL	entry+0(FP), BX	// entry
-	MOVL	address+4(FP), CX	// base address
-
-	/*
-	 * When linking against the system libraries,
-	 * we use its pthread_create and let it set up %gs
-	 * for us.  When we do that, the private storage
-	 * we get is not at 0(GS), 4(GS), but -8(GS), -4(GS).
-	 * To insulate the rest of the tool chain from this
-	 * ugliness, 8l rewrites 0(GS) into -8(GS) for us.
-	 * To accommodate that rewrite, we translate
-	 * the address here and bump the limit to 0xffffffff (no limit)
-	 * so that -8(GS) maps to 0(address).
-	 * Also, the final 0(GS) (current 8(CX)) has to point
-	 * to itself, to mimic ELF.
-	 */
-	ADDL	$0x8, CX	// address
-	MOVL	CX, 0(CX)
-
-	// set up user_desc
-	LEAL	16(SP), AX	// struct user_desc
-	MOVL	BX, 0(AX)
-	MOVL	CX, 4(AX)
-	MOVL	$0xfffff, 8(AX)
-	MOVL	$(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX)	// flag bits
-
-	// call modify_ldt
-	MOVL	$1, BX	// func = 1 (write)
-	MOVL	AX, CX	// user_desc
-	MOVL	$16, DX	// sizeof(user_desc)
-	MOVL	$123, AX	// syscall - modify_ldt
-	CALL	*runtime·_vdso(SB)
-
-	// breakpoint on error
-	CMPL AX, $0xfffff001
-	JLS 2(PC)
-	INT $3
-
-	// compute segment selector - (entry*8+7)
-	MOVL	entry+0(FP), AX
-	SHLL	$3, AX
-	ADDL	$7, AX
-	MOVW	AX, GS
-
-	RET
-
-TEXT runtime·osyield(SB),7,$0
-	MOVL	$158, AX
-	CALL	*runtime·_vdso(SB)
-	RET
diff --git a/src/pkg/runtime/linux/amd64/defs.h b/src/pkg/runtime/linux/amd64/defs.h
deleted file mode 100644
index 8053dd1..0000000
--- a/src/pkg/runtime/linux/amd64/defs.h
+++ /dev/null
@@ -1,236 +0,0 @@
-// godefs -f -m64 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x20,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_RESTART = 0x10000000,
-	SA_ONSTACK = 0x8000000,
-	SA_RESTORER = 0x4000000,
-	SA_SIGINFO = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGBUS = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGUSR1 = 0xa,
-	SIGSEGV = 0xb,
-	SIGUSR2 = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGSTKFLT = 0x10,
-	SIGCHLD = 0x11,
-	SIGCONT = 0x12,
-	SIGSTOP = 0x13,
-	SIGTSTP = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGURG = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGIO = 0x1d,
-	SIGPWR = 0x1e,
-	SIGSYS = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-	O_RDONLY = 0,
-	O_CLOEXEC = 02000000,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Timespec Timespec;
-struct Timespec {
-	int64 tv_sec;
-	int64 tv_nsec;
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int64 tv_sec;
-	int64 tv_usec;
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
-	void *sa_handler;
-	uint64 sa_flags;
-	void *sa_restorer;
-	uint64 sa_mask;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	byte pad_godefs_0[4];
-	byte _sifields[112];
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-#pragma pack off
-// godefs -f -m64 defs1.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-
-// Types
-#pragma pack on
-
-typedef struct Usigset Usigset;
-struct Usigset {
-	uint64 __val[16];
-};
-
-typedef struct Fpxreg Fpxreg;
-struct Fpxreg {
-	uint16 significand[4];
-	uint16 exponent;
-	uint16 padding[3];
-};
-
-typedef struct Xmmreg Xmmreg;
-struct Xmmreg {
-	uint32 element[4];
-};
-
-typedef struct Fpstate Fpstate;
-struct Fpstate {
-	uint16 cwd;
-	uint16 swd;
-	uint16 ftw;
-	uint16 fop;
-	uint64 rip;
-	uint64 rdp;
-	uint32 mxcsr;
-	uint32 mxcr_mask;
-	Fpxreg _st[8];
-	Xmmreg _xmm[16];
-	uint32 padding[24];
-};
-
-typedef struct Fpxreg1 Fpxreg1;
-struct Fpxreg1 {
-	uint16 significand[4];
-	uint16 exponent;
-	uint16 padding[3];
-};
-
-typedef struct Xmmreg1 Xmmreg1;
-struct Xmmreg1 {
-	uint32 element[4];
-};
-
-typedef struct Fpstate1 Fpstate1;
-struct Fpstate1 {
-	uint16 cwd;
-	uint16 swd;
-	uint16 ftw;
-	uint16 fop;
-	uint64 rip;
-	uint64 rdp;
-	uint32 mxcsr;
-	uint32 mxcr_mask;
-	Fpxreg1 _st[8];
-	Xmmreg1 _xmm[16];
-	uint32 padding[24];
-};
-
-typedef struct Fpreg1 Fpreg1;
-struct Fpreg1 {
-	uint16 significand[4];
-	uint16 exponent;
-};
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	void *ss_sp;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
-	uint64 ss_size;
-};
-
-typedef struct Mcontext Mcontext;
-struct Mcontext {
-	int64 gregs[23];
-	Fpstate *fpregs;
-	uint64 __reserved1[8];
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
-	uint64 uc_flags;
-	Ucontext *uc_link;
-	Sigaltstack uc_stack;
-	Mcontext uc_mcontext;
-	Usigset uc_sigmask;
-	Fpstate __fpregs_mem;
-};
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	uint64 r8;
-	uint64 r9;
-	uint64 r10;
-	uint64 r11;
-	uint64 r12;
-	uint64 r13;
-	uint64 r14;
-	uint64 r15;
-	uint64 rdi;
-	uint64 rsi;
-	uint64 rbp;
-	uint64 rbx;
-	uint64 rdx;
-	uint64 rax;
-	uint64 rcx;
-	uint64 rsp;
-	uint64 rip;
-	uint64 eflags;
-	uint16 cs;
-	uint16 gs;
-	uint16 fs;
-	uint16 __pad0;
-	uint64 err;
-	uint64 trapno;
-	uint64 oldmask;
-	uint64 cr2;
-	Fpstate1 *fpstate;
-	uint64 __reserved1[8];
-};
-#pragma pack off
diff --git a/src/pkg/runtime/linux/amd64/signal.c b/src/pkg/runtime/linux/amd64/signal.c
deleted file mode 100644
index ee90271..0000000
--- a/src/pkg/runtime/linux/amd64/signal.c
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
-	runtime·printf("rax     %X\n", r->rax);
-	runtime·printf("rbx     %X\n", r->rbx);
-	runtime·printf("rcx     %X\n", r->rcx);
-	runtime·printf("rdx     %X\n", r->rdx);
-	runtime·printf("rdi     %X\n", r->rdi);
-	runtime·printf("rsi     %X\n", r->rsi);
-	runtime·printf("rbp     %X\n", r->rbp);
-	runtime·printf("rsp     %X\n", r->rsp);
-	runtime·printf("r8      %X\n", r->r8 );
-	runtime·printf("r9      %X\n", r->r9 );
-	runtime·printf("r10     %X\n", r->r10);
-	runtime·printf("r11     %X\n", r->r11);
-	runtime·printf("r12     %X\n", r->r12);
-	runtime·printf("r13     %X\n", r->r13);
-	runtime·printf("r14     %X\n", r->r14);
-	runtime·printf("r15     %X\n", r->r15);
-	runtime·printf("rip     %X\n", r->rip);
-	runtime·printf("rflags  %X\n", r->eflags);
-	runtime·printf("cs      %X\n", (uint64)r->cs);
-	runtime·printf("fs      %X\n", (uint64)r->fs);
-	runtime·printf("gs      %X\n", (uint64)r->gs);
-}
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void runtime·sigtramp(void);
-extern void runtime·sigignore(void);	// just returns
-extern void runtime·sigreturn(void);	// calls runtime·sigreturn
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Ucontext *uc;
-	Mcontext *mc;
-	Sigcontext *r;
-	uintptr *sp;
-
-	uc = context;
-	mc = &uc->uc_mcontext;
-	r = (Sigcontext*)mc;	// same layout, more conveient names
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = ((uintptr*)info)[2];
-		gp->sigpc = r->rip;
-
-		// Only push runtime·sigpanic if r->rip != 0.
-		// If r->rip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->rip != 0) {
-			sp = (uintptr*)r->rsp;
-			*--sp = r->rip;
-			r->rsp = (uintptr)sp;
-		}
-		r->rip = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG)
-		runtime·printf("Signal %d\n", sig);
-	else
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-
-	runtime·printf("PC=%X\n", r->rip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	Sigaltstack st;
-
-	st.ss_sp = p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	sa.sa_restorer = (void*)runtime·sigreturn;
-	if(fn == runtime·sighandler)
-		fn = (void*)runtime·sigtramp;
-	sa.sa_handler = fn;
-	runtime·rt_sigaction(i, &sa, nil, 8);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
diff --git a/src/pkg/runtime/linux/amd64/sys.s b/src/pkg/runtime/linux/amd64/sys.s
deleted file mode 100644
index 8b4dcd9..0000000
--- a/src/pkg/runtime/linux/amd64/sys.s
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//
-// System calls and other sys.stuff for AMD64, Linux
-//
-
-#include "amd64/asm.h"
-
-TEXT runtime·exit(SB),7,$0-8
-	MOVL	8(SP), DI
-	MOVL	$231, AX	// exitgroup - force all os threads to exit
-	SYSCALL
-	RET
-
-TEXT runtime·exit1(SB),7,$0-8
-	MOVL	8(SP), DI
-	MOVL	$60, AX	// exit - exit the current os thread
-	SYSCALL
-	RET
-
-TEXT runtime·open(SB),7,$0-16
-	MOVQ	8(SP), DI
-	MOVL	16(SP), SI
-	MOVL	20(SP), DX
-	MOVL	$2, AX			// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·close(SB),7,$0-16
-	MOVL	8(SP), DI
-	MOVL	$3, AX			// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·write(SB),7,$0-24
-	MOVL	8(SP), DI
-	MOVQ	16(SP), SI
-	MOVL	24(SP), DX
-	MOVL	$1, AX			// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·read(SB),7,$0-24
-	MOVL	8(SP), DI
-	MOVQ	16(SP), SI
-	MOVL	24(SP), DX
-	MOVL	$0, AX			// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·raisesigpipe(SB),7,$12
-	MOVL	$186, AX	// syscall - gettid
-	SYSCALL
-	MOVL	AX, DI	// arg 1 tid
-	MOVL	$13, SI	// arg 2 SIGPIPE
-	MOVL	$200, AX	// syscall - tkill
-	SYSCALL
-	RET
-
-TEXT runtime·setitimer(SB),7,$0-24
-	MOVL	8(SP), DI
-	MOVQ	16(SP), SI
-	MOVQ	24(SP), DX
-	MOVL	$38, AX			// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·mincore(SB),7,$0-24
-	MOVQ	8(SP), DI
-	MOVQ	16(SP), SI
-	MOVQ	24(SP), DX
-	MOVL	$27, AX			// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·gettime(SB), 7, $32
-	LEAQ	8(SP), DI
-	MOVQ	$0, SI
-	MOVQ	$0xffffffffff600000, AX
-	CALL	AX
-
-	MOVQ	8(SP), BX	// sec
-	MOVQ	sec+0(FP), DI
-	MOVQ	BX, (DI)
-
-	MOVL	16(SP), BX	// usec
-	MOVQ	usec+8(FP), DI
-	MOVL	BX, (DI)
-	RET
-
-TEXT runtime·rt_sigaction(SB),7,$0-32
-	MOVL	8(SP), DI
-	MOVQ	16(SP), SI
-	MOVQ	24(SP), DX
-	MOVQ	32(SP), R10
-	MOVL	$13, AX			// syscall entry
-	SYSCALL
-	RET
-
-TEXT runtime·sigtramp(SB),7,$64
-	get_tls(BX)
-
-	// save g
-	MOVQ	g(BX), R10
-	MOVQ	R10, 40(SP)
-
-	// g = m->gsignal
-	MOVQ	m(BX), BP
-	MOVQ	m_gsignal(BP), BP
-	MOVQ	BP, g(BX)
-
-	MOVQ	DI, 0(SP)
-	MOVQ	SI, 8(SP)
-	MOVQ	DX, 16(SP)
-	MOVQ	R10, 24(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(BX)
-	MOVQ	40(SP), R10
-	MOVQ	R10, g(BX)
-	RET
-
-TEXT runtime·sigignore(SB),7,$0
-	RET
-
-TEXT runtime·sigreturn(SB),7,$0
-	MOVL	$15, AX	// rt_sigreturn
-	SYSCALL
-	INT $3	// not reached
-
-TEXT runtime·mmap(SB),7,$0
-	MOVQ	8(SP), DI
-	MOVQ	$0, SI
-	MOVQ	16(SP), SI
-	MOVL	24(SP), DX
-	MOVL	28(SP), R10
-	MOVL	32(SP), R8
-	MOVL	36(SP), R9
-
-	MOVL	$9, AX			// mmap
-	SYSCALL
-	CMPQ	AX, $0xfffffffffffff001
-	JLS	3(PC)
-	NOTQ	AX
-	INCQ	AX
-	RET
-
-TEXT runtime·munmap(SB),7,$0
-	MOVQ	8(SP), DI
-	MOVQ	16(SP), SI
-	MOVQ	$11, AX	// munmap
-	SYSCALL
-	CMPQ	AX, $0xfffffffffffff001
-	JLS	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·notok(SB),7,$0
-	MOVQ	$0xf1, BP
-	MOVQ	BP, (BP)
-	RET
-
-// int64 futex(int32 *uaddr, int32 op, int32 val,
-//	struct timespec *timeout, int32 *uaddr2, int32 val2);
-TEXT runtime·futex(SB),7,$0
-	MOVQ	8(SP), DI
-	MOVL	16(SP), SI
-	MOVL	20(SP), DX
-	MOVQ	24(SP), R10
-	MOVQ	32(SP), R8
-	MOVL	40(SP), R9
-	MOVL	$202, AX
-	SYSCALL
-	RET
-
-// int64 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·clone(SB),7,$0
-	MOVL	flags+8(SP), DI
-	MOVQ	stack+16(SP), SI
-
-	// Copy m, g, fn off parent stack for use by child.
-	// Careful: Linux system call clobbers CX and R11.
-	MOVQ	mm+24(SP), R8
-	MOVQ	gg+32(SP), R9
-	MOVQ	fn+40(SP), R12
-
-	MOVL	$56, AX
-	SYSCALL
-
-	// In parent, return.
-	CMPQ	AX, $0
-	JEQ	2(PC)
-	RET
-	
-	// In child, on new stack.
-	MOVQ	SI, SP
-	
-	// Initialize m->procid to Linux tid
-	MOVL	$186, AX	// gettid
-	SYSCALL
-	MOVQ	AX, m_procid(R8)
-
-	// Set FS to point at m->tls.
-	LEAQ	m_tls(R8), DI
-	CALL	runtime·settls(SB)
-
-	// In child, set up new stack
-	get_tls(CX)
-	MOVQ	R8, m(CX)
-	MOVQ	R9, g(CX)
-	CALL	runtime·stackcheck(SB)
-
-	// Call fn
-	CALL	R12
-
-	// It shouldn't return.  If it does, exit
-	MOVL	$111, DI
-	MOVL	$60, AX
-	SYSCALL
-	JMP	-3(PC)	// keep exiting
-
-TEXT runtime·sigaltstack(SB),7,$-8
-	MOVQ	new+8(SP), DI
-	MOVQ	old+16(SP), SI
-	MOVQ	$131, AX
-	SYSCALL
-	CMPQ	AX, $0xfffffffffffff001
-	JLS	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-// set tls base to DI
-TEXT runtime·settls(SB),7,$32
-	ADDQ	$16, DI	// ELF wants to use -16(FS), -8(FS)
-
-	MOVQ	DI, SI
-	MOVQ	$0x1002, DI	// ARCH_SET_FS
-	MOVQ	$158, AX	// arch_prctl
-	SYSCALL
-	CMPQ	AX, $0xfffffffffffff001
-	JLS	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·osyield(SB),7,$0
-	MOVL	$24, AX
-	SYSCALL
-	RET
diff --git a/src/pkg/runtime/linux/arm/defs.h b/src/pkg/runtime/linux/arm/defs.h
deleted file mode 100644
index 09b558e..0000000
--- a/src/pkg/runtime/linux/arm/defs.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// godefs -f-I/usr/src/linux-headers-2.6.26-2-versatile/include defs_arm.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x20,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_RESTART = 0x10000000,
-	SA_ONSTACK = 0x8000000,
-	SA_RESTORER = 0x4000000,
-	SA_SIGINFO = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGBUS = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGUSR1 = 0xa,
-	SIGSEGV = 0xb,
-	SIGUSR2 = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGSTKFLT = 0x10,
-	SIGCHLD = 0x11,
-	SIGCONT = 0x12,
-	SIGSTOP = 0x13,
-	SIGTSTP = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGURG = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGIO = 0x1d,
-	SIGPWR = 0x1e,
-	SIGSYS = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_PROF = 0x2,
-	ITIMER_VIRTUAL = 0x1,
-	O_RDONLY = 0,
-	O_CLOEXEC = 02000000,
-};
-
-// Types
-#pragma pack on
-
-typedef uint32 Sigset;
-
-typedef struct Timespec Timespec;
-struct Timespec {
-	int32 tv_sec;
-	int32 tv_nsec;
-};
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	void *ss_sp;
-	int32 ss_flags;
-	uint32 ss_size;
-};
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	uint32 trap_no;
-	uint32 error_code;
-	uint32 oldmask;
-	uint32 arm_r0;
-	uint32 arm_r1;
-	uint32 arm_r2;
-	uint32 arm_r3;
-	uint32 arm_r4;
-	uint32 arm_r5;
-	uint32 arm_r6;
-	uint32 arm_r7;
-	uint32 arm_r8;
-	uint32 arm_r9;
-	uint32 arm_r10;
-	uint32 arm_fp;
-	uint32 arm_ip;
-	uint32 arm_sp;
-	uint32 arm_lr;
-	uint32 arm_pc;
-	uint32 arm_cpsr;
-	uint32 fault_address;
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
-	uint32 uc_flags;
-	Ucontext *uc_link;
-	Sigaltstack uc_stack;
-	Sigcontext uc_mcontext;
-	uint32 uc_sigmask;
-	int32 __unused[31];
-	uint32 uc_regspace[128];
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int32 tv_sec;
-	int32 tv_usec;
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_errno;
-	int32 si_code;
-	uint8 _sifields[4];
-};
-
-typedef struct Sigaction Sigaction;
-struct Sigaction {
-	void *sa_handler;
-	uint32 sa_flags;
-	void *sa_restorer;
-	uint32 sa_mask;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/linux/arm/signal.c b/src/pkg/runtime/linux/arm/signal.c
deleted file mode 100644
index 88a84d1..0000000
--- a/src/pkg/runtime/linux/arm/signal.c
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
-	runtime·printf("trap    %x\n", r->trap_no);
-	runtime·printf("error   %x\n", r->error_code);
-	runtime·printf("oldmask %x\n", r->oldmask);
-	runtime·printf("r0      %x\n", r->arm_r0);
-	runtime·printf("r1      %x\n", r->arm_r1);
-	runtime·printf("r2      %x\n", r->arm_r2);
-	runtime·printf("r3      %x\n", r->arm_r3);
-	runtime·printf("r4      %x\n", r->arm_r4);
-	runtime·printf("r5      %x\n", r->arm_r5);
-	runtime·printf("r6      %x\n", r->arm_r6);
-	runtime·printf("r7      %x\n", r->arm_r7);
-	runtime·printf("r8      %x\n", r->arm_r8);
-	runtime·printf("r9      %x\n", r->arm_r9);
-	runtime·printf("r10     %x\n", r->arm_r10);
-	runtime·printf("fp      %x\n", r->arm_fp);
-	runtime·printf("ip      %x\n", r->arm_ip);
-	runtime·printf("sp      %x\n", r->arm_sp);
-	runtime·printf("lr      %x\n", r->arm_lr);
-	runtime·printf("pc      %x\n", r->arm_pc);
-	runtime·printf("cpsr    %x\n", r->arm_cpsr);
-	runtime·printf("fault   %x\n", r->fault_address);
-}
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void runtime·sigtramp(void);
-extern void runtime·sigignore(void);	// just returns
-extern void runtime·sigreturn(void);	// calls runtime·sigreturn
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Ucontext *uc;
-	Sigcontext *r;
-
-	uc = context;
-	r = &uc->uc_mcontext;
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = r->fault_address;
-		gp->sigpc = r->arm_pc;
-
-		// If this is a leaf function, we do smash LR,
-		// but we're not going back there anyway.
-		// Don't bother smashing if r->arm_pc is 0,
-		// which is probably a call to a nil func: the
-		// old link register is more useful in the stack trace.
-		if(r->arm_pc != 0)
-			r->arm_lr = r->arm_pc;
-		r->arm_pc = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG)
-		runtime·printf("Signal %d\n", sig);
-	else
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-
-	runtime·printf("PC=%x\n", r->arm_pc);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp);
-		runtime·tracebackothers(gp);
-		runtime·printf("\n");
-		runtime·dumpregs(r);
-	}
-
-//	breakpoint();
-	runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	Sigaltstack st;
-
-	st.ss_sp = p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	sa.sa_restorer = (void*)runtime·sigreturn;
-	if(fn == runtime·sighandler)
-		fn = (void*)runtime·sigtramp;
-	sa.sa_handler = fn;
-	runtime·rt_sigaction(i, &sa, nil, 8);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
diff --git a/src/pkg/runtime/linux/arm/sys.s b/src/pkg/runtime/linux/arm/sys.s
deleted file mode 100644
index 8619f09..0000000
--- a/src/pkg/runtime/linux/arm/sys.s
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//
-// System calls and other sys.stuff for arm, Linux
-//
-
-#include "arm/asm.h"
-
-// OABI
-//#define SYS_BASE 0x00900000
-
-// EABI
-#define SYS_BASE 0x0
-
-#define SYS_exit (SYS_BASE + 1)
-#define SYS_read (SYS_BASE + 3)
-#define SYS_write (SYS_BASE + 4)
-#define SYS_open (SYS_BASE + 5)
-#define SYS_close (SYS_BASE + 6)
-#define SYS_gettimeofday (SYS_BASE + 78)
-#define SYS_clone (SYS_BASE + 120)
-#define SYS_rt_sigreturn (SYS_BASE + 173)
-#define SYS_rt_sigaction (SYS_BASE + 174)
-#define SYS_sigaltstack (SYS_BASE + 186)
-#define SYS_mmap2 (SYS_BASE + 192)
-#define SYS_futex (SYS_BASE + 240)
-#define SYS_exit_group (SYS_BASE + 248)
-#define SYS_munmap (SYS_BASE + 91)
-#define SYS_setitimer (SYS_BASE + 104)
-#define SYS_mincore (SYS_BASE + 219)
-#define SYS_gettid (SYS_BASE + 224)
-#define SYS_tkill (SYS_BASE + 238)
-#define SYS_sched_yield (SYS_BASE + 158)
-
-#define ARM_BASE (SYS_BASE + 0x0f0000)
-#define SYS_ARM_cacheflush (ARM_BASE + 2)
-
-TEXT runtime·open(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	8(FP), R2
-	MOVW	$SYS_open, R7
-	SWI	$0
-	RET
-
-TEXT runtime·close(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	$SYS_close, R7
-	SWI	$0
-	RET
-
-TEXT runtime·write(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	8(FP), R2
-	MOVW	$SYS_write, R7
-	SWI	$0
-	RET
-
-TEXT runtime·read(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	8(FP), R2
-	MOVW	$SYS_read, R7
-	SWI	$0
-	RET
-
-TEXT runtime·exit(SB),7,$-4
-	MOVW	0(FP), R0
-	MOVW	$SYS_exit_group, R7
-	SWI	$0
-	MOVW	$1234, R0
-	MOVW	$1002, R1
-	MOVW	R0, (R1)	// fail hard
-
-TEXT runtime·exit1(SB),7,$-4
-	MOVW	0(FP), R0
-	MOVW	$SYS_exit, R7
-	SWI	$0
-	MOVW	$1234, R0
-	MOVW	$1003, R1
-	MOVW	R0, (R1)	// fail hard
-
-TEXT	runtime·raisesigpipe(SB),7,$-4
-	MOVW	$SYS_gettid, R7
-	SWI	$0
-	// arg 1 tid already in R0 from gettid
-	MOVW	$13, R1	// arg 2 SIGPIPE
-	MOVW	$SYS_tkill, R7
-	SWI	$0
-	RET
-
-TEXT runtime·mmap(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	8(FP), R2
-	MOVW	12(FP), R3
-	MOVW	16(FP), R4
-	MOVW	20(FP), R5
-	MOVW	$SYS_mmap2, R7
-	SWI	$0
-	RET
-
-TEXT runtime·munmap(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	$SYS_munmap, R7
-	SWI	$0
-	RET
-
-TEXT runtime·setitimer(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	8(FP), R2
-	MOVW	$SYS_setitimer, R7
-	SWI	$0
-	RET
-
-TEXT runtime·mincore(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	8(FP), R2
-	MOVW	$SYS_mincore, R7
-	SWI	$0
-	RET
-
-TEXT runtime·gettime(SB),7,$32
-	/* dummy version - return 0,0 */
-	MOVW	$0, R1
-	MOVW	0(FP), R0
-	MOVW	R1, 0(R0)
-	MOVW	R1, 4(R0)
-	MOVW	4(FP), R0
-	MOVW	R1, 0(R0)
-
-/*
-	attempt at real version - seg faults
-
-	MOVW	$8(SP), R0
-	MOVW	$0, R1
-	MOVW	$SYS_gettimeofday, R7
-	SWI	$0
-
-	MOVW	0(FP), R0	// sec
-	MOVW	8(SP), R1
-	MOVW	R1, 0(R0)
-
-	MOVW	4(FP), R0	// usec
-	MOVW	12(SP), R1
-	MOVW	R1, 0(R0)
-*/
-	RET
-
-// int32 futex(int32 *uaddr, int32 op, int32 val,
-//	struct timespec *timeout, int32 *uaddr2, int32 val2);
-TEXT runtime·futex(SB),7,$0
-	MOVW	4(SP), R0
-	MOVW	8(SP), R1
-	MOVW	12(SP), R2
-	MOVW	16(SP), R3
-	MOVW	20(SP), R4
-	MOVW	24(SP), R5
-	MOVW	$SYS_futex, R7
-	SWI	$0
-	RET
-
-
-// int32 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·clone(SB),7,$0
-	MOVW	flags+0(FP), R0
-	MOVW	stack+4(FP), R1
-	MOVW	$0, R2	// parent tid ptr
-	MOVW	$0, R3	// tls_val
-	MOVW	$0, R4	// child tid ptr
-	MOVW	$0, R5
-
-	// Copy m, g, fn off parent stack for use by child.
-	// TODO(kaib): figure out which registers are clobbered by clone and avoid stack copying
-	MOVW	$-16(R1), R1
-	MOVW	mm+8(FP), R6
-	MOVW	R6, 0(R1)
-	MOVW	gg+12(FP), R6
-	MOVW	R6, 4(R1)
-	MOVW	fn+16(FP), R6
-	MOVW	R6, 8(R1)
-	MOVW	$1234, R6
-	MOVW	R6, 12(R1)
-
-	MOVW	$SYS_clone, R7
-	SWI	$0
-
-	// In parent, return.
-	CMP	$0, R0
-	BEQ	2(PC)
-	RET
-
-	// Paranoia: check that SP is as we expect. Use R13 to avoid linker 'fixup'
-	MOVW	12(R13), R0
-	MOVW	$1234, R1
-	CMP	R0, R1
-	BEQ	2(PC)
-	BL	runtime·abort(SB)
-
-	MOVW	0(R13), m
-	MOVW	4(R13), g
-
-	// paranoia; check they are not nil
-	MOVW	0(m), R0
-	MOVW	0(g), R0
-
-	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
-
-	// Initialize m->procid to Linux tid
-	MOVW	$SYS_gettid, R7
-	SWI	$0
-	MOVW	R0, m_procid(m)
-
-	// Call fn
-	MOVW	8(R13), R0
-	MOVW	$16(R13), R13
-	BL	(R0)
-
-	MOVW	$0, R0
-	MOVW	R0, 4(R13)
-	BL	runtime·exit1(SB)
-
-	// It shouldn't return
-	MOVW	$1234, R0
-	MOVW	$1005, R1
-	MOVW	R0, (R1)
-
-
-TEXT runtime·cacheflush(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	$0, R2
-	MOVW	$SYS_ARM_cacheflush, R7
-	SWI	$0
-	RET
-
-TEXT runtime·sigaltstack(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	$SYS_sigaltstack, R7
-	SWI	$0
-	RET
-
-TEXT runtime·sigignore(SB),7,$0
-	RET
-
-TEXT runtime·sigtramp(SB),7,$24
-	// save g
-	MOVW	g, R3
-	MOVW	g, 20(R13)
-	
-	// g = m->gsignal
-	MOVW	m_gsignal(m), g
-
-	// copy arguments for call to sighandler
-	MOVW	R0, 4(R13)
-	MOVW	R1, 8(R13)
-	MOVW	R2, 12(R13)
-	MOVW	R3, 16(R13)
-
-	BL	runtime·sighandler(SB)
-	
-	// restore g
-	MOVW	20(R13), g
-
-	RET
-
-TEXT runtime·rt_sigaction(SB),7,$0
-	MOVW	0(FP), R0
-	MOVW	4(FP), R1
-	MOVW	8(FP), R2
-	MOVW	12(FP), R3
-	MOVW	$SYS_rt_sigaction, R7
-	SWI	$0
-	RET
-
-TEXT runtime·sigreturn(SB),7,$0
-	MOVW	$SYS_rt_sigreturn, R7
-	SWI	$0
-	RET
-
-// Use kernel version instead of native armcas in ../../arm.s.
-// See ../../../sync/atomic/asm_linux_arm.s for details.
-TEXT cas<>(SB),7,$0
-	MOVW	$0xffff0fc0, PC
-
-TEXT runtime·cas(SB),7,$0
-	MOVW	valptr+0(FP), R2
-	MOVW	old+4(FP), R0
-casagain:
-	MOVW	new+8(FP), R1
-	BL	cas<>(SB)
-	BCC	cascheck
-	MOVW $1, R0
-	RET
-cascheck:
-	// Kernel lies; double-check.
-	MOVW	valptr+0(FP), R2
-	MOVW	old+4(FP), R0
-	MOVW	0(R2), R3
-	CMP	R0, R3
-	BEQ	casagain
-	MOVW $0, R0
-	RET
-
-
-TEXT runtime·casp(SB),7,$0
-	B	runtime·cas(SB)
-
-TEXT runtime·osyield(SB),7,$0
-	MOVW	$SYS_sched_yield, R7
-	SWI	$0
-	RET
diff --git a/src/pkg/runtime/linux/defs.c b/src/pkg/runtime/linux/defs.c
deleted file mode 100644
index 5dda787..0000000
--- a/src/pkg/runtime/linux/defs.c
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Input to godefs
-	godefs -f -m64 defs.c >amd64/defs.h
-	godefs -f -m64 defs1.c >>amd64/defs.h
- */
-
-// Linux glibc and Linux kernel define different and conflicting
-// definitions for struct sigaction, struct timespec, etc.
-// We want the kernel ones, which are in the asm/* headers.
-// But then we'd get conflicts when we include the system
-// headers for things like ucontext_t, so that happens in
-// a separate file, defs1.c.
-
-#include <asm/posix_types.h>
-#define size_t __kernel_size_t
-#include <asm/signal.h>
-#include <asm/siginfo.h>
-#include <asm/mman.h>
-
-enum {
-	$PROT_NONE = PROT_NONE,
-	$PROT_READ = PROT_READ,
-	$PROT_WRITE = PROT_WRITE,
-	$PROT_EXEC = PROT_EXEC,
-
-	$MAP_ANON = MAP_ANONYMOUS,
-	$MAP_PRIVATE = MAP_PRIVATE,
-	$MAP_FIXED = MAP_FIXED,
-
-	$SA_RESTART = SA_RESTART,
-	$SA_ONSTACK = SA_ONSTACK,
-	$SA_RESTORER = SA_RESTORER,
-	$SA_SIGINFO = SA_SIGINFO,
-	
-	$SIGHUP = SIGHUP,
-	$SIGINT = SIGINT,
-	$SIGQUIT = SIGQUIT,
-	$SIGILL = SIGILL,
-	$SIGTRAP = SIGTRAP,
-	$SIGABRT = SIGABRT,
-	$SIGBUS = SIGBUS,
-	$SIGFPE = SIGFPE,
-	$SIGKILL = SIGKILL,
-	$SIGUSR1 = SIGUSR1,
-	$SIGSEGV = SIGSEGV,
-	$SIGUSR2 = SIGUSR2,
-	$SIGPIPE = SIGPIPE,
-	$SIGALRM = SIGALRM,
-	$SIGSTKFLT = SIGSTKFLT,
-	$SIGCHLD = SIGCHLD,
-	$SIGCONT = SIGCONT,
-	$SIGSTOP = SIGSTOP,
-	$SIGTSTP = SIGTSTP,
-	$SIGTTIN = SIGTTIN,
-	$SIGTTOU = SIGTTOU,
-	$SIGURG = SIGURG,
-	$SIGXCPU = SIGXCPU,
-	$SIGXFSZ = SIGXFSZ,
-	$SIGVTALRM = SIGVTALRM,
-	$SIGPROF = SIGPROF,
-	$SIGWINCH = SIGWINCH,
-	$SIGIO = SIGIO,
-	$SIGPWR = SIGPWR,
-	$SIGSYS = SIGSYS,
-	
-	$FPE_INTDIV = FPE_INTDIV,
-	$FPE_INTOVF = FPE_INTOVF,
-	$FPE_FLTDIV = FPE_FLTDIV,
-	$FPE_FLTOVF = FPE_FLTOVF,
-	$FPE_FLTUND = FPE_FLTUND,
-	$FPE_FLTRES = FPE_FLTRES,
-	$FPE_FLTINV = FPE_FLTINV,
-	$FPE_FLTSUB = FPE_FLTSUB,
-	
-	$BUS_ADRALN = BUS_ADRALN,
-	$BUS_ADRERR = BUS_ADRERR,
-	$BUS_OBJERR = BUS_OBJERR,
-	
-	$SEGV_MAPERR = SEGV_MAPERR,
-	$SEGV_ACCERR = SEGV_ACCERR,
-	
-	$ITIMER_REAL = ITIMER_REAL,
-	$ITIMER_VIRTUAL = ITIMER_VIRTUAL,
-	$ITIMER_PROF = ITIMER_PROF,
-};
-
-typedef struct timespec $Timespec;
-typedef struct timeval $Timeval;
-typedef struct sigaction $Sigaction;
-typedef siginfo_t $Siginfo;
-typedef struct itimerval $Itimerval;
diff --git a/src/pkg/runtime/linux/defs1.c b/src/pkg/runtime/linux/defs1.c
deleted file mode 100644
index e737f8e..0000000
--- a/src/pkg/runtime/linux/defs1.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Input to godefs
-	godefs -f -m64 defs.c >amd64/defs.h
-	godefs -f -m64 defs1.c >>amd64/defs.h
- */
-
-#include <ucontext.h>
-
-typedef __sigset_t $Usigset;
-typedef struct _libc_fpxreg $Fpxreg;
-typedef struct _libc_xmmreg $Xmmreg;
-typedef struct _libc_fpstate $Fpstate;
-typedef struct _fpxreg $Fpxreg1;
-typedef struct _xmmreg $Xmmreg1;
-typedef struct _fpstate $Fpstate1;
-typedef struct _fpreg $Fpreg1;
-typedef struct sigaltstack $Sigaltstack;
-typedef mcontext_t $Mcontext;
-typedef ucontext_t $Ucontext;
-typedef struct sigcontext $Sigcontext;
diff --git a/src/pkg/runtime/linux/defs2.c b/src/pkg/runtime/linux/defs2.c
deleted file mode 100644
index ff641ff..0000000
--- a/src/pkg/runtime/linux/defs2.c
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Input to godefs
-	godefs -f -m32 \
-		-f -I/home/rsc/pub/linux-2.6/arch/x86/include \
-		-f -I/home/rsc/pub/linux-2.6/include \
-		-f -D_LOOSE_KERNEL_NAMES \
-		-f -D__ARCH_SI_UID_T'='__kernel_uid32_t \
-		defs2.c >386/defs.h
-
- * The asm header tricks we have to use for Linux on amd64
- * (see defs.c and defs1.c) don't work here, so this is yet another
- * file.  Sigh.
- */
-
-#include <asm/signal.h>
-#include <asm/mman.h>
-#include <asm/sigcontext.h>
-#include <asm/ucontext.h>
-#include <asm/siginfo.h>
-
-/*
-#include <sys/signal.h>
-#include <sys/mman.h>
-#include <ucontext.h>
-*/
-
-/* This is the sigaction structure from the Linux 2.1.68 kernel which
-   is used with the rt_sigaction system call.  For 386 this is not
-   defined in any public header file.  */
-
-struct kernel_sigaction {
-	__sighandler_t k_sa_handler;
-	unsigned long sa_flags;
-	void (*sa_restorer) (void);
-	sigset_t sa_mask;
-};
-
-enum {
-	$PROT_NONE = PROT_NONE,
-	$PROT_READ = PROT_READ,
-	$PROT_WRITE = PROT_WRITE,
-	$PROT_EXEC = PROT_EXEC,
-
-	$MAP_ANON = MAP_ANONYMOUS,
-	$MAP_PRIVATE = MAP_PRIVATE,
-	$MAP_FIXED = MAP_FIXED,
-
-	$SA_RESTART = SA_RESTART,
-	$SA_ONSTACK = SA_ONSTACK,
-	$SA_RESTORER = SA_RESTORER,
-	$SA_SIGINFO = SA_SIGINFO,
-
-	$SIGHUP = SIGHUP,
-	$SIGINT = SIGINT,
-	$SIGQUIT = SIGQUIT,
-	$SIGILL = SIGILL,
-	$SIGTRAP = SIGTRAP,
-	$SIGABRT = SIGABRT,
-	$SIGBUS = SIGBUS,
-	$SIGFPE = SIGFPE,
-	$SIGKILL = SIGKILL,
-	$SIGUSR1 = SIGUSR1,
-	$SIGSEGV = SIGSEGV,
-	$SIGUSR2 = SIGUSR2,
-	$SIGPIPE = SIGPIPE,
-	$SIGALRM = SIGALRM,
-	$SIGSTKFLT = SIGSTKFLT,
-	$SIGCHLD = SIGCHLD,
-	$SIGCONT = SIGCONT,
-	$SIGSTOP = SIGSTOP,
-	$SIGTSTP = SIGTSTP,
-	$SIGTTIN = SIGTTIN,
-	$SIGTTOU = SIGTTOU,
-	$SIGURG = SIGURG,
-	$SIGXCPU = SIGXCPU,
-	$SIGXFSZ = SIGXFSZ,
-	$SIGVTALRM = SIGVTALRM,
-	$SIGPROF = SIGPROF,
-	$SIGWINCH = SIGWINCH,
-	$SIGIO = SIGIO,
-	$SIGPWR = SIGPWR,
-	$SIGSYS = SIGSYS,
-	
-	$FPE_INTDIV = FPE_INTDIV,
-	$FPE_INTOVF = FPE_INTOVF,
-	$FPE_FLTDIV = FPE_FLTDIV,
-	$FPE_FLTOVF = FPE_FLTOVF,
-	$FPE_FLTUND = FPE_FLTUND,
-	$FPE_FLTRES = FPE_FLTRES,
-	$FPE_FLTINV = FPE_FLTINV,
-	$FPE_FLTSUB = FPE_FLTSUB,
-	
-	$BUS_ADRALN = BUS_ADRALN,
-	$BUS_ADRERR = BUS_ADRERR,
-	$BUS_OBJERR = BUS_OBJERR,
-	
-	$SEGV_MAPERR = SEGV_MAPERR,
-	$SEGV_ACCERR = SEGV_ACCERR,
-	
-	$ITIMER_REAL = ITIMER_REAL,
-	$ITIMER_VIRTUAL = ITIMER_VIRTUAL,
-	$ITIMER_PROF = ITIMER_PROF,
-};
-
-typedef struct _fpreg $Fpreg;
-typedef struct _fpxreg $Fpxreg;
-typedef struct _xmmreg $Xmmreg;
-typedef struct _fpstate $Fpstate;
-typedef struct timespec $Timespec;
-typedef struct timeval $Timeval;
-typedef struct kernel_sigaction $Sigaction;
-typedef siginfo_t $Siginfo;
-typedef struct sigaltstack $Sigaltstack;
-typedef struct sigcontext $Sigcontext;
-typedef struct ucontext $Ucontext;
-typedef struct itimerval $Itimerval;
diff --git a/src/pkg/runtime/linux/defs_arm.c b/src/pkg/runtime/linux/defs_arm.c
deleted file mode 100644
index 1f93504..0000000
--- a/src/pkg/runtime/linux/defs_arm.c
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Input to godefs
- * On a Debian Lenny arm linux distribution:
-	godefs -f-I/usr/src/linux-headers-2.6.26-2-versatile/include defs_arm.c
- */
-
-#define __ARCH_SI_UID_T int
-
-#include <asm/signal.h>
-#include <asm/mman.h>
-#include <asm/sigcontext.h>
-#include <asm/ucontext.h>
-#include <asm/siginfo.h>
-#include <linux/time.h>
-
-/*
-#include <sys/signal.h>
-#include <sys/mman.h>
-#include <ucontext.h>
-*/
-
-enum {
-	$PROT_NONE = PROT_NONE,
-	$PROT_READ = PROT_READ,
-	$PROT_WRITE = PROT_WRITE,
-	$PROT_EXEC = PROT_EXEC,
-
-	$MAP_ANON = MAP_ANONYMOUS,
-	$MAP_PRIVATE = MAP_PRIVATE,
-	$MAP_FIXED = MAP_FIXED,
-
-	$SA_RESTART = SA_RESTART,
-	$SA_ONSTACK = SA_ONSTACK,
-	$SA_RESTORER = SA_RESTORER,
-	$SA_SIGINFO = SA_SIGINFO,
-
-	$SIGHUP = SIGHUP,
-	$SIGINT = SIGINT,
-	$SIGQUIT = SIGQUIT,
-	$SIGILL = SIGILL,
-	$SIGTRAP = SIGTRAP,
-	$SIGABRT = SIGABRT,
-	$SIGBUS = SIGBUS,
-	$SIGFPE = SIGFPE,
-	$SIGKILL = SIGKILL,
-	$SIGUSR1 = SIGUSR1,
-	$SIGSEGV = SIGSEGV,
-	$SIGUSR2 = SIGUSR2,
-	$SIGPIPE = SIGPIPE,
-	$SIGALRM = SIGALRM,
-	$SIGSTKFLT = SIGSTKFLT,
-	$SIGCHLD = SIGCHLD,
-	$SIGCONT = SIGCONT,
-	$SIGSTOP = SIGSTOP,
-	$SIGTSTP = SIGTSTP,
-	$SIGTTIN = SIGTTIN,
-	$SIGTTOU = SIGTTOU,
-	$SIGURG = SIGURG,
-	$SIGXCPU = SIGXCPU,
-	$SIGXFSZ = SIGXFSZ,
-	$SIGVTALRM = SIGVTALRM,
-	$SIGPROF = SIGPROF,
-	$SIGWINCH = SIGWINCH,
-	$SIGIO = SIGIO,
-	$SIGPWR = SIGPWR,
-	$SIGSYS = SIGSYS,
-
-	$FPE_INTDIV = FPE_INTDIV & 0xFFFF,
-	$FPE_INTOVF = FPE_INTOVF & 0xFFFF,
-	$FPE_FLTDIV = FPE_FLTDIV & 0xFFFF,
-	$FPE_FLTOVF = FPE_FLTOVF & 0xFFFF,
-	$FPE_FLTUND = FPE_FLTUND & 0xFFFF,
-	$FPE_FLTRES = FPE_FLTRES & 0xFFFF,
-	$FPE_FLTINV = FPE_FLTINV & 0xFFFF,
-	$FPE_FLTSUB = FPE_FLTSUB & 0xFFFF,
-	
-	$BUS_ADRALN = BUS_ADRALN & 0xFFFF,
-	$BUS_ADRERR = BUS_ADRERR & 0xFFFF,
-	$BUS_OBJERR = BUS_OBJERR & 0xFFFF,
-	
-	$SEGV_MAPERR = SEGV_MAPERR & 0xFFFF,
-	$SEGV_ACCERR = SEGV_ACCERR & 0xFFFF,
-
-	$ITIMER_REAL = ITIMER_REAL,
-	$ITIMER_PROF = ITIMER_PROF,
-	$ITIMER_VIRTUAL = ITIMER_VIRTUAL,
-};
-
-typedef sigset_t $Sigset;
-typedef struct timespec $Timespec;
-typedef struct sigaltstack $Sigaltstack;
-typedef struct sigcontext $Sigcontext;
-typedef struct ucontext $Ucontext;
-typedef struct timeval $Timeval;
-typedef struct itimerval $Itimerval;
-
-struct xsiginfo {
-	int si_signo;
-	int si_errno;
-	int si_code;
-	char _sifields[4];
-};
-
-typedef struct xsiginfo $Siginfo;
-
-#undef sa_handler
-#undef sa_flags
-#undef sa_restorer
-#undef sa_mask
-
-struct xsigaction {
-	void (*sa_handler)(void);
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-	unsigned int sa_mask;		/* mask last for extensibility */
-};
-
-typedef struct xsigaction $Sigaction;
diff --git a/src/pkg/runtime/linux/mem.c b/src/pkg/runtime/linux/mem.c
deleted file mode 100644
index 6c5c908..0000000
--- a/src/pkg/runtime/linux/mem.c
+++ /dev/null
@@ -1,116 +0,0 @@
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "malloc.h"
-
-enum
-{
-	ENOMEM = 12,
-	_PAGE_SIZE = 4096,
-};
-
-static int32
-addrspace_free(void *v, uintptr n)
-{
-	int32 errval;
-	uintptr chunk;
-	uintptr off;
-	static byte vec[4096];
-
-	for(off = 0; off < n; off += chunk) {
-		chunk = _PAGE_SIZE * sizeof vec;
-		if(chunk > (n - off))
-			chunk = n - off;
-		errval = runtime·mincore((int8*)v + off, chunk, vec);
-		// errval is 0 if success, or -(error_code) if error.
-		if (errval == 0 || errval != -ENOMEM)
-			return 0;
-	}
-	return 1;
-}
-
-
-void*
-runtime·SysAlloc(uintptr n)
-{
-	void *p;
-
-	mstats.sys += n;
-	p = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
-	if(p < (void*)4096) {
-		if(p == (void*)EACCES) {
-			runtime·printf("runtime: mmap: access denied\n");
-			runtime·printf("if you're running SELinux, enable execmem for this process.\n");
-			runtime·exit(2);
-		}
-		return nil;
-	}
-	return p;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-	USED(v);
-	USED(n);
-	// TODO(rsc): call madvise MADV_DONTNEED
-}
-
-void
-runtime·SysFree(void *v, uintptr n)
-{
-	mstats.sys -= n;
-	runtime·munmap(v, n);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n)
-{
-	void *p;
-
-	// On 64-bit, people with ulimit -v set complain if we reserve too
-	// much address space.  Instead, assume that the reservation is okay
-	// and check the assumption in SysMap.
-	if(sizeof(void*) == 8)
-		return v;
-	
-	p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-	if((uintptr)p < 4096 || -(uintptr)p < 4096) {
-		return nil;
-	}
-	return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n)
-{
-	void *p;
-	
-	mstats.sys += n;
-
-	// On 64-bit, we don't actually have v reserved, so tread carefully.
-	if(sizeof(void*) == 8) {
-		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
-		if(p != v && addrspace_free(v, n)) {
-			// On some systems, mmap ignores v without
-			// MAP_FIXED, so retry if the address space is free.
-			if(p > (void*)4096) {
-				runtime·munmap(p, n);
-			}
-			p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
-		}
-		if(p == (void*)ENOMEM)
-			runtime·throw("runtime: out of memory");
-		if(p != v) {
-			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-			runtime·throw("runtime: address space conflict");
-		}
-		return;
-	}
-
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
-	if(p == (void*)ENOMEM)
-		runtime·throw("runtime: out of memory");
-	if(p != v)
-		runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/pkg/runtime/linux/signals.h b/src/pkg/runtime/linux/signals.h
deleted file mode 100644
index 919b80e..0000000
--- a/src/pkg/runtime/linux/signals.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define C SigCatch
-#define I SigIgnore
-#define R SigRestart
-#define Q SigQueue
-#define P SigPanic
-
-SigTab runtime·sigtab[] = {
-	/* 0 */	0, "SIGNONE: no trap",
-	/* 1 */	Q+R, "SIGHUP: terminal line hangup",
-	/* 2 */	Q+R, "SIGINT: interrupt",
-	/* 3 */	C, "SIGQUIT: quit",
-	/* 4 */	C+P, "SIGILL: illegal instruction",
-	/* 5 */	C, "SIGTRAP: trace trap",
-	/* 6 */	C, "SIGABRT: abort",
-	/* 7 */	C+P, "SIGBUS: bus error",
-	/* 8 */	C+P, "SIGFPE: floating-point exception",
-	/* 9 */	0, "SIGKILL: kill",
-	/* 10 */	Q+I+R, "SIGUSR1: user-defined signal 1",
-	/* 11 */	C+P, "SIGSEGV: segmentation violation",
-	/* 12 */	Q+I+R, "SIGUSR2: user-defined signal 2",
-	/* 13 */	I, "SIGPIPE: write to broken pipe",
-	/* 14 */	Q+I+R, "SIGALRM: alarm clock",
-	/* 15 */	Q+R, "SIGTERM: termination",
-	/* 16 */	C, "SIGSTKFLT: stack fault",
-	/* 17 */	Q+I+R, "SIGCHLD: child status has changed",
-	/* 18 */	0, "SIGCONT: continue",
-	/* 19 */	0, "SIGSTOP: stop, unblockable",
-	/* 20 */	Q+I+R, "SIGTSTP: keyboard stop",
-	/* 21 */	Q+I+R, "SIGTTIN: background read from tty",
-	/* 22 */	Q+I+R, "SIGTTOU: background write to tty",
-	/* 23 */	Q+I+R, "SIGURG: urgent condition on socket",
-	/* 24 */	Q+I+R, "SIGXCPU: cpu limit exceeded",
-	/* 25 */	Q+I+R, "SIGXFSZ: file size limit exceeded",
-	/* 26 */	Q+I+R, "SIGVTALRM: virtual alarm clock",
-	/* 27 */	Q+I+R, "SIGPROF: profiling alarm clock",
-	/* 28 */	Q+I+R, "SIGWINCH: window size change",
-	/* 29 */	Q+I+R, "SIGIO: i/o now possible",
-	/* 30 */	Q+I+R, "SIGPWR: power failure restart",
-	/* 31 */	C, "SIGSYS: bad system call",
-};
-#undef C
-#undef I
-#undef R
-#undef Q
-#undef P
-
-#define	NSIG 32
diff --git a/src/pkg/runtime/linux/thread.c b/src/pkg/runtime/linux/thread.c
deleted file mode 100644
index 4878a00..0000000
--- a/src/pkg/runtime/linux/thread.c
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "stack.h"
-
-extern SigTab runtime·sigtab[];
-static int32 proccount;
-
-int32 runtime·open(uint8*, int32, int32);
-int32 runtime·close(int32);
-int32 runtime·read(int32, void*, int32);
-
-// Linux futex.
-//
-//	futexsleep(uint32 *addr, uint32 val)
-//	futexwakeup(uint32 *addr)
-//
-// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
-// Futexwakeup wakes up threads sleeping on addr.
-// Futexsleep is allowed to wake up spuriously.
-
-enum
-{
-	MUTEX_UNLOCKED = 0,
-	MUTEX_LOCKED = 1,
-	MUTEX_SLEEPING = 2,
-
-	ACTIVE_SPIN = 4,
-	ACTIVE_SPIN_CNT = 30,
-	PASSIVE_SPIN = 1,
-
-	FUTEX_WAIT = 0,
-	FUTEX_WAKE = 1,
-
-	EINTR = 4,
-	EAGAIN = 11,
-};
-
-// TODO(rsc): I tried using 1<<40 here but futex woke up (-ETIMEDOUT).
-// I wonder if the timespec that gets to the kernel
-// actually has two 32-bit numbers in it, so that
-// a 64-bit 1<<40 ends up being 0 seconds,
-// 1<<8 nanoseconds.
-static Timespec longtime =
-{
-	1<<30,	// 34 years
-	0
-};
-
-// Atomically,
-//	if(*addr == val) sleep
-// Might be woken up spuriously; that's allowed.
-static void
-futexsleep(uint32 *addr, uint32 val)
-{
-	// Some Linux kernels have a bug where futex of
-	// FUTEX_WAIT returns an internal error code
-	// as an errno.  Libpthread ignores the return value
-	// here, and so can we: as it says a few lines up,
-	// spurious wakeups are allowed.
-	runtime·futex(addr, FUTEX_WAIT, val, &longtime, nil, 0);
-}
-
-// If any procs are sleeping on addr, wake up at most cnt.
-static void
-futexwakeup(uint32 *addr, uint32 cnt)
-{
-	int64 ret;
-
-	ret = runtime·futex(addr, FUTEX_WAKE, cnt, nil, nil, 0);
-
-	if(ret >= 0)
-		return;
-
-	// I don't know that futex wakeup can return
-	// EAGAIN or EINTR, but if it does, it would be
-	// safe to loop and call futex again.
-	runtime·printf("futexwakeup addr=%p returned %D\n", addr, ret);
-	*(int32*)0x1006 = 0x1006;
-}
-
-static int32
-getproccount(void)
-{
-	int32 fd, rd, cnt, cpustrlen;
-	byte *cpustr, *pos, *bufpos;
-	byte buf[256];
-
-	fd = runtime·open((byte*)"/proc/stat", O_RDONLY|O_CLOEXEC, 0);
-	if(fd == -1)
-		return 1;
-	cnt = 0;
-	bufpos = buf;
-	cpustr = (byte*)"\ncpu";
-	cpustrlen = runtime·findnull(cpustr);
-	for(;;) {
-		rd = runtime·read(fd, bufpos, sizeof(buf)-cpustrlen);
-		if(rd == -1)
-			break;
-		bufpos[rd] = 0;
-		for(pos=buf; pos=runtime·strstr(pos, cpustr); cnt++, pos++) {
-		}
-		if(rd < cpustrlen)
-			break;
-		runtime·memmove(buf, bufpos+rd-cpustrlen+1, cpustrlen-1);
-		bufpos = buf+cpustrlen-1;
-	}
-	runtime·close(fd);
-	return cnt ? cnt : 1;
-}
-
-// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
-// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
-// Note that there can be spinning threads during all states - they do not
-// affect mutex's state.
-static void
-futexlock(Lock *l)
-{
-	uint32 i, v, wait, spin;
-
-	// Speculative grab for lock.
-	v = runtime·xchg(&l->key, MUTEX_LOCKED);
-	if(v == MUTEX_UNLOCKED)
-		return;
-
-	// wait is either MUTEX_LOCKED or MUTEX_SLEEPING
-	// depending on whether there is a thread sleeping
-	// on this mutex.  If we ever change l->key from
-	// MUTEX_SLEEPING to some other value, we must be
-	// careful to change it back to MUTEX_SLEEPING before
-	// returning, to ensure that the sleeping thread gets
-	// its wakeup call.
-	wait = v;
-
-	if(proccount == 0)
-		proccount = getproccount();
-
-	// On uniprocessor's, no point spinning.
-	// On multiprocessors, spin for ACTIVE_SPIN attempts.
-	spin = 0;
-	if(proccount > 1)
-		spin = ACTIVE_SPIN;
-
-	for(;;) {
-		// Try for lock, spinning.
-		for(i = 0; i < spin; i++) {
-			while(l->key == MUTEX_UNLOCKED)
-				if(runtime·cas(&l->key, MUTEX_UNLOCKED, wait))
-						return;
-			runtime·procyield(ACTIVE_SPIN_CNT);
-		}
-
-		// Try for lock, rescheduling.
-		for(i=0; i < PASSIVE_SPIN; i++) {
-			while(l->key == MUTEX_UNLOCKED)
-				if(runtime·cas(&l->key, MUTEX_UNLOCKED, wait))
-					return;
-			runtime·osyield();
-		}
-
-		// Sleep.
-		v = runtime·xchg(&l->key, MUTEX_SLEEPING);
-		if(v == MUTEX_UNLOCKED)
-			return;
-		wait = MUTEX_SLEEPING;
-		futexsleep(&l->key, MUTEX_SLEEPING);
-	}
-}
-
-static void
-futexunlock(Lock *l)
-{
-	uint32 v;
-
-	v = runtime·xchg(&l->key, MUTEX_UNLOCKED);
-	if(v == MUTEX_UNLOCKED)
-		runtime·throw("unlock of unlocked lock");
-	if(v == MUTEX_SLEEPING)
-		futexwakeup(&l->key, 1);
-}
-
-void
-runtime·lock(Lock *l)
-{
-	if(m->locks++ < 0)
-		runtime·throw("runtime·lock: lock count");
-	futexlock(l);
-}
-
-void
-runtime·unlock(Lock *l)
-{
-	if(--m->locks < 0)
-		runtime·throw("runtime·unlock: lock count");
-	futexunlock(l);
-}
-
-
-// One-time notifications.
-void
-runtime·noteclear(Note *n)
-{
-	n->state = 0;
-}
-
-void
-runtime·notewakeup(Note *n)
-{
-	runtime·xchg(&n->state, 1);
-	futexwakeup(&n->state, 1<<30);
-}
-
-void
-runtime·notesleep(Note *n)
-{
-	while(runtime·atomicload(&n->state) == 0)
-		futexsleep(&n->state, 0);
-}
-
-
-// Clone, the Linux rfork.
-enum
-{
-	CLONE_VM = 0x100,
-	CLONE_FS = 0x200,
-	CLONE_FILES = 0x400,
-	CLONE_SIGHAND = 0x800,
-	CLONE_PTRACE = 0x2000,
-	CLONE_VFORK = 0x4000,
-	CLONE_PARENT = 0x8000,
-	CLONE_THREAD = 0x10000,
-	CLONE_NEWNS = 0x20000,
-	CLONE_SYSVSEM = 0x40000,
-	CLONE_SETTLS = 0x80000,
-	CLONE_PARENT_SETTID = 0x100000,
-	CLONE_CHILD_CLEARTID = 0x200000,
-	CLONE_UNTRACED = 0x800000,
-	CLONE_CHILD_SETTID = 0x1000000,
-	CLONE_STOPPED = 0x2000000,
-	CLONE_NEWUTS = 0x4000000,
-	CLONE_NEWIPC = 0x8000000,
-};
-
-void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
-{
-	int32 ret;
-	int32 flags;
-
-	/*
-	 * note: strace gets confused if we use CLONE_PTRACE here.
-	 */
-	flags = CLONE_VM	/* share memory */
-		| CLONE_FS	/* share cwd, etc */
-		| CLONE_FILES	/* share fd table */
-		| CLONE_SIGHAND	/* share sig handler table */
-		| CLONE_THREAD	/* revisit - okay for now */
-		;
-
-	m->tls[0] = m->id;	// so 386 asm can find it
-	if(0){
-		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p clone=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, runtime·clone, m->id, m->tls[0], &m);
-	}
-
-	if((ret = runtime·clone(flags, stk, m, g, fn)) < 0) {
-		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -ret);
-		runtime·throw("runtime.newosproc");
-	}
-}
-
-void
-runtime·osinit(void)
-{
-}
-
-void
-runtime·goenvs(void)
-{
-	runtime·goenvs_unix();
-}
-
-// Called to initialize a new m (including the bootstrap m).
-void
-runtime·minit(void)
-{
-	// Initialize signal handling.
-	m->gsignal = runtime·malg(32*1024);	// OS X wants >=8K, Linux >=2K
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
-}
-
-void
-runtime·sigpanic(void)
-{
-	switch(g->sig) {
-	case SIGBUS:
-		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case SIGSEGV:
-		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case SIGFPE:
-		switch(g->sigcode0) {
-		case FPE_INTDIV:
-			runtime·panicstring("integer divide by zero");
-		case FPE_INTOVF:
-			runtime·panicstring("integer overflow");
-		}
-		runtime·panicstring("floating point error");
-	}
-	runtime·panicstring(runtime·sigtab[g->sig].name);
-}
diff --git a/src/pkg/runtime/lock_futex.c b/src/pkg/runtime/lock_futex.c
new file mode 100644
index 0000000..6ec4aee
--- /dev/null
+++ b/src/pkg/runtime/lock_futex.c
@@ -0,0 +1,148 @@
+// Copyright 2011 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 freebsd linux
+
+#include "runtime.h"
+
+// This implementation depends on OS-specific implementations of
+//
+//	runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
+//		Atomically,
+//			if(*addr == val) sleep
+//		Might be woken up spuriously; that's allowed.
+//		Don't sleep longer than ns; ns < 0 means forever.
+//
+//	runtime·futexwakeup(uint32 *addr, uint32 cnt)
+//		If any procs are sleeping on addr, wake up at most cnt.
+
+enum
+{
+	MUTEX_UNLOCKED = 0,
+	MUTEX_LOCKED = 1,
+	MUTEX_SLEEPING = 2,
+
+	ACTIVE_SPIN = 4,
+	ACTIVE_SPIN_CNT = 30,
+	PASSIVE_SPIN = 1,
+};
+
+// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
+// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
+// Note that there can be spinning threads during all states - they do not
+// affect mutex's state.
+void
+runtime·lock(Lock *l)
+{
+	uint32 i, v, wait, spin;
+
+	if(m->locks++ < 0)
+		runtime·throw("runtime·lock: lock count");
+
+	// Speculative grab for lock.
+	v = runtime·xchg(&l->key, MUTEX_LOCKED);
+	if(v == MUTEX_UNLOCKED)
+		return;
+
+	// wait is either MUTEX_LOCKED or MUTEX_SLEEPING
+	// depending on whether there is a thread sleeping
+	// on this mutex.  If we ever change l->key from
+	// MUTEX_SLEEPING to some other value, we must be
+	// careful to change it back to MUTEX_SLEEPING before
+	// returning, to ensure that the sleeping thread gets
+	// its wakeup call.
+	wait = v;
+
+	// On uniprocessor's, no point spinning.
+	// On multiprocessors, spin for ACTIVE_SPIN attempts.
+	spin = 0;
+	if(runtime·ncpu > 1)
+		spin = ACTIVE_SPIN;
+
+	for(;;) {
+		// Try for lock, spinning.
+		for(i = 0; i < spin; i++) {
+			while(l->key == MUTEX_UNLOCKED)
+				if(runtime·cas(&l->key, MUTEX_UNLOCKED, wait))
+					return;
+			runtime·procyield(ACTIVE_SPIN_CNT);
+		}
+
+		// Try for lock, rescheduling.
+		for(i=0; i < PASSIVE_SPIN; i++) {
+			while(l->key == MUTEX_UNLOCKED)
+				if(runtime·cas(&l->key, MUTEX_UNLOCKED, wait))
+					return;
+			runtime·osyield();
+		}
+
+		// Sleep.
+		v = runtime·xchg(&l->key, MUTEX_SLEEPING);
+		if(v == MUTEX_UNLOCKED)
+			return;
+		wait = MUTEX_SLEEPING;
+		runtime·futexsleep(&l->key, MUTEX_SLEEPING, -1);
+	}
+}
+
+void
+runtime·unlock(Lock *l)
+{
+	uint32 v;
+
+	if(--m->locks < 0)
+		runtime·throw("runtime·unlock: lock count");
+
+	v = runtime·xchg(&l->key, MUTEX_UNLOCKED);
+	if(v == MUTEX_UNLOCKED)
+		runtime·throw("unlock of unlocked lock");
+	if(v == MUTEX_SLEEPING)
+		runtime·futexwakeup(&l->key, 1);
+}
+
+// One-time notifications.
+void
+runtime·noteclear(Note *n)
+{
+	n->key = 0;
+}
+
+void
+runtime·notewakeup(Note *n)
+{
+	runtime·xchg(&n->key, 1);
+	runtime·futexwakeup(&n->key, 1);
+}
+
+void
+runtime·notesleep(Note *n)
+{
+	while(runtime·atomicload(&n->key) == 0)
+		runtime·futexsleep(&n->key, 0, -1);
+}
+
+void
+runtime·notetsleep(Note *n, int64 ns)
+{
+	int64 deadline, now;
+
+	if(ns < 0) {
+		runtime·notesleep(n);
+		return;
+	}
+
+	if(runtime·atomicload(&n->key) != 0)
+		return;
+
+	deadline = runtime·nanotime() + ns;
+	for(;;) {
+		runtime·futexsleep(&n->key, 0, ns);
+		if(runtime·atomicload(&n->key) != 0)
+			return;
+		now = runtime·nanotime();
+		if(now >= deadline)
+			return;
+		ns = deadline - now;
+	}
+}
diff --git a/src/pkg/runtime/lock_sema.c b/src/pkg/runtime/lock_sema.c
new file mode 100644
index 0000000..28d2c32
--- /dev/null
+++ b/src/pkg/runtime/lock_sema.c
@@ -0,0 +1,219 @@
+// Copyright 2011 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 darwin netbsd openbsd plan9 windows
+
+#include "runtime.h"
+
+// This implementation depends on OS-specific implementations of
+//
+//	uintptr runtime·semacreate(void)
+//		Create a semaphore, which will be assigned to m->waitsema.
+//		The zero value is treated as absence of any semaphore,
+//		so be sure to return a non-zero value.
+//
+//	int32 runtime·semasleep(int64 ns)
+//		If ns < 0, acquire m->waitsema and return 0.
+//		If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds.
+//		Return 0 if the semaphore was acquired, -1 if interrupted or timed out.
+//
+//	int32 runtime·semawakeup(M *mp)
+//		Wake up mp, which is or will soon be sleeping on mp->waitsema.
+//
+
+enum
+{
+	LOCKED = 1,
+
+	ACTIVE_SPIN = 4,
+	ACTIVE_SPIN_CNT = 30,
+	PASSIVE_SPIN = 1,
+};
+
+void
+runtime·lock(Lock *l)
+{
+	uintptr v;
+	uint32 i, spin;
+
+	if(m->locks++ < 0)
+		runtime·throw("runtime·lock: lock count");
+
+	// Speculative grab for lock.
+	if(runtime·casp(&l->waitm, nil, (void*)LOCKED))
+		return;
+
+	if(m->waitsema == 0)
+		m->waitsema = runtime·semacreate();
+
+	// On uniprocessor's, no point spinning.
+	// On multiprocessors, spin for ACTIVE_SPIN attempts.
+	spin = 0;
+	if(runtime·ncpu > 1)
+		spin = ACTIVE_SPIN;
+
+	for(i=0;; i++) {
+		v = (uintptr)runtime·atomicloadp(&l->waitm);
+		if((v&LOCKED) == 0) {
+unlocked:
+			if(runtime·casp(&l->waitm, (void*)v, (void*)(v|LOCKED)))
+				return;
+			i = 0;
+		}
+		if(i<spin)
+			runtime·procyield(ACTIVE_SPIN_CNT);
+		else if(i<spin+PASSIVE_SPIN)
+			runtime·osyield();
+		else {
+			// Someone else has it.
+			// l->waitm points to a linked list of M's waiting
+			// for this lock, chained through m->nextwaitm.
+			// Queue this M.
+			for(;;) {
+				m->nextwaitm = (void*)(v&~LOCKED);
+				if(runtime·casp(&l->waitm, (void*)v, (void*)((uintptr)m|LOCKED)))
+					break;
+				v = (uintptr)runtime·atomicloadp(&l->waitm);
+				if((v&LOCKED) == 0)
+					goto unlocked;
+			}
+			if(v&LOCKED) {
+				// Queued.  Wait.
+				runtime·semasleep(-1);
+				i = 0;
+			}
+		}
+	}
+}
+
+void
+runtime·unlock(Lock *l)
+{
+	uintptr v;
+	M *mp;
+
+	if(--m->locks < 0)
+		runtime·throw("runtime·unlock: lock count");
+
+	for(;;) {
+		v = (uintptr)runtime·atomicloadp(&l->waitm);
+		if(v == LOCKED) {
+			if(runtime·casp(&l->waitm, (void*)LOCKED, nil))
+				break;
+		} else {
+			// Other M's are waiting for the lock.
+			// Dequeue an M.
+			mp = (void*)(v&~LOCKED);
+			if(runtime·casp(&l->waitm, (void*)v, mp->nextwaitm)) {
+				// Dequeued an M.  Wake it.
+				runtime·semawakeup(mp);
+				break;
+			}
+		}
+	}
+}
+
+// One-time notifications.
+void
+runtime·noteclear(Note *n)
+{
+	n->waitm = nil;
+}
+
+void
+runtime·notewakeup(Note *n)
+{
+	M *mp;
+
+	do
+		mp = runtime·atomicloadp(&n->waitm);
+	while(!runtime·casp(&n->waitm, mp, (void*)LOCKED));
+
+	// Successfully set waitm to LOCKED.
+	// What was it before?
+	if(mp == nil) {
+		// Nothing was waiting.  Done.
+	} else if(mp == (M*)LOCKED) {
+		// Two notewakeups!  Not allowed.
+		runtime·throw("notewakeup - double wakeup");
+	} else {
+		// Must be the waiting m.  Wake it up.
+		runtime·semawakeup(mp);
+	}
+}
+
+void
+runtime·notesleep(Note *n)
+{
+	if(m->waitsema == 0)
+		m->waitsema = runtime·semacreate();
+	if(!runtime·casp(&n->waitm, nil, m)) {  // must be LOCKED (got wakeup)
+		if(n->waitm != (void*)LOCKED)
+			runtime·throw("notesleep - waitm out of sync");
+		return;
+	}
+	// Queued.  Sleep.
+	runtime·semasleep(-1);
+}
+
+void
+runtime·notetsleep(Note *n, int64 ns)
+{
+	M *mp;
+	int64 deadline, now;
+
+	if(ns < 0) {
+		runtime·notesleep(n);
+		return;
+	}
+
+	if(m->waitsema == 0)
+		m->waitsema = runtime·semacreate();
+
+	// Register for wakeup on n->waitm.
+	if(!runtime·casp(&n->waitm, nil, m)) {  // must be LOCKED (got wakeup already)
+		if(n->waitm != (void*)LOCKED)
+			runtime·throw("notetsleep - waitm out of sync");
+		return;
+	}
+
+	deadline = runtime·nanotime() + ns;
+	for(;;) {
+		// Registered.  Sleep.
+		if(runtime·semasleep(ns) >= 0) {
+			// Acquired semaphore, semawakeup unregistered us.
+			// Done.
+			return;
+		}
+
+		// Interrupted or timed out.  Still registered.  Semaphore not acquired.
+		now = runtime·nanotime();
+		if(now >= deadline)
+			break;
+
+		// Deadline hasn't arrived.  Keep sleeping.
+		ns = deadline - now;
+	}
+
+	// Deadline arrived.  Still registered.  Semaphore not acquired.
+	// Want to give up and return, but have to unregister first,
+	// so that any notewakeup racing with the return does not
+	// try to grant us the semaphore when we don't expect it.
+	for(;;) {
+		mp = runtime·atomicloadp(&n->waitm);
+		if(mp == m) {
+			// No wakeup yet; unregister if possible.
+			if(runtime·casp(&n->waitm, mp, nil))
+				return;
+		} else if(mp == (M*)LOCKED) {
+			// Wakeup happened so semaphore is available.
+			// Grab it to avoid getting out of sync.
+			if(runtime·semasleep(-1) < 0)
+				runtime·throw("runtime: unable to acquire - semaphore out of sync");
+			return;
+		} else {
+			runtime·throw("runtime: unexpected waitm - semaphore out of sync");
+		}
+	}
+}
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index 84e0ac4..f1509cd 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -8,9 +8,10 @@
 
 package runtime
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "stack.h"
 #include "malloc.h"
-#include "defs.h"
+#include "defs_GOOS_GOARCH.h"
 #include "type.h"
 
 MHeap runtime·mheap;
@@ -80,11 +81,12 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 			m->mcache->next_sample -= size;
 		else {
 			// pick next profile time
+			// If you change this, also change allocmcache.
 			if(rate > 0x3fffffff)	// make 2*rate not overflow
 				rate = 0x3fffffff;
 			m->mcache->next_sample = runtime·fastrand1() % (2*rate);
 		profile:
-			runtime·setblockspecial(v);
+			runtime·setblockspecial(v, true);
 			runtime·MProf_Malloc(v, size);
 		}
 	}
@@ -113,7 +115,7 @@ runtime·free(void *v)
 	if(v == nil)
 		return;
 	
-	// If you change this also change mgc0.c:/^sweepspan,
+	// If you change this also change mgc0.c:/^sweep,
 	// which has a copy of the guts of free.
 
 	if(m->mallocing)
@@ -205,6 +207,7 @@ runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
 MCache*
 runtime·allocmcache(void)
 {
+	int32 rate;
 	MCache *c;
 
 	runtime·lock(&runtime·mheap);
@@ -212,6 +215,14 @@ runtime·allocmcache(void)
 	mstats.mcache_inuse = runtime·mheap.cachealloc.inuse;
 	mstats.mcache_sys = runtime·mheap.cachealloc.sys;
 	runtime·unlock(&runtime·mheap);
+
+	// Set first allocation sample size.
+	rate = runtime·MemProfileRate;
+	if(rate > 0x3fffffff)	// make 2*rate not overflow
+		rate = 0x3fffffff;
+	if(rate != 0)
+		c->next_sample = runtime·fastrand1() % (2*rate);
+
 	return c;
 }
 
@@ -383,8 +394,10 @@ runtime·mal(uintptr n)
 	return runtime·mallocgc(n, 0, 1, 1);
 }
 
-func new(n uint32) (ret *uint8) {
-	ret = runtime·mal(n);
+func new(typ *Type) (ret *uint8) {
+	uint32 flag = typ->kind&KindNoPointers ? FlagNoPointers : 0;
+	ret = runtime·mallocgc(typ->size, flag, 1, 1);
+	FLUSH(&ret);
 }
 
 void*
@@ -448,8 +461,7 @@ func SetFinalizer(obj Eface, finalizer Eface) {
 
 	if(obj.type == nil) {
 		runtime·printf("runtime.SetFinalizer: first argument is nil interface\n");
-	throw:
-		runtime·throw("runtime.SetFinalizer");
+		goto throw;
 	}
 	if(obj.type->kind != KindPtr) {
 		runtime·printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.type->string);
@@ -461,11 +473,8 @@ func SetFinalizer(obj Eface, finalizer Eface) {
 	}
 	nret = 0;
 	if(finalizer.type != nil) {
-		if(finalizer.type->kind != KindFunc) {
-		badfunc:
-			runtime·printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.type->string, *obj.type->string);
-			goto throw;
-		}
+		if(finalizer.type->kind != KindFunc)
+			goto badfunc;
 		ft = (FuncType*)finalizer.type;
 		if(ft->dotdotdot || ft->in.len != 1 || *(Type**)ft->in.array != obj.type)
 			goto badfunc;
@@ -477,11 +486,16 @@ func SetFinalizer(obj Eface, finalizer Eface) {
 			nret += t->size;
 		}
 		nret = (nret + sizeof(void*)-1) & ~(sizeof(void*)-1);
-
-		if(runtime·getfinalizer(obj.data, 0)) {
-			runtime·printf("runtime.SetFinalizer: finalizer already set\n");
-			goto throw;
-		}
 	}
-	runtime·addfinalizer(obj.data, finalizer.data, nret);
+	
+	if(!runtime·addfinalizer(obj.data, finalizer.data, nret)) {
+		runtime·printf("runtime.SetFinalizer: finalizer already set\n");
+		goto throw;
+	}
+	return;
+
+badfunc:
+	runtime·printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.type->string, *obj.type->string);
+throw:
+	runtime·throw("runtime.SetFinalizer");
 }
diff --git a/src/pkg/runtime/malloc.h b/src/pkg/runtime/malloc.h
index 5bc80f4..a85e1af 100644
--- a/src/pkg/runtime/malloc.h
+++ b/src/pkg/runtime/malloc.h
@@ -120,6 +120,12 @@ enum
 #else
 	MHeapMap_Bits = 20,
 #endif
+
+	// Max number of threads to run garbage collection.
+	// 2, 3, and 4 are all plausible maximums depending
+	// on the hardware details of the machine.  The garbage
+	// collector scales well to 4 cpus.
+	MaxGcproc = 4,
 };
 
 // A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
@@ -192,7 +198,7 @@ struct MStats
 	uint64	nlookup;	// number of pointer lookups
 	uint64	nmalloc;	// number of mallocs
 	uint64	nfree;  // number of frees
-	
+
 	// Statistics about malloc heap.
 	// protected by mheap.Lock
 	uint64	heap_alloc;	// bytes allocated and still in use
@@ -210,7 +216,7 @@ struct MStats
 	uint64	mcache_inuse;	// MCache structures
 	uint64	mcache_sys;
 	uint64	buckhash_sys;	// profiling bucket hash table
-	
+
 	// Statistics about garbage collector.
 	// Protected by stopping the world during GC.
 	uint64	next_gc;	// next GC (in heap_alloc time)
@@ -219,7 +225,7 @@ struct MStats
 	uint32	numgc;
 	bool	enablegc;
 	bool	debuggc;
-	
+
 	// Statistics about allocation size classes.
 	struct {
 		uint32 size;
@@ -240,7 +246,7 @@ extern MStats mstats;
 //
 // class_to_size[i] = largest size in class i
 // class_to_allocnpages[i] = number of pages to allocate when
-// 	making new objects in class i
+//	making new objects in class i
 // class_to_transfercount[i] = number of objects to move when
 //	taking a bunch of objects out of the central lists
 //	and putting them in the thread free list.
@@ -279,7 +285,7 @@ struct MCache
 		int64 nmalloc;
 		int64 nfree;
 	} local_by_size[NumSizeClasses];
-	
+
 };
 
 void*	runtime·MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed);
@@ -352,14 +358,14 @@ struct MHeap
 	byte *arena_start;
 	byte *arena_used;
 	byte *arena_end;
-	
+
 	// central free lists for small size classes.
 	// the union makes sure that the MCentrals are
-	// spaced 64 bytes apart, so that each MCentral.Lock
+	// spaced CacheLineSize bytes apart, so that each MCentral.Lock
 	// gets its own cache line.
 	union {
 		MCentral;
-		byte pad[64];
+		byte pad[CacheLineSize];
 	} central[NumSizeClasses];
 
 	FixAlloc spanalloc;	// allocator for Span*
@@ -387,7 +393,7 @@ int32	runtime·checking;
 void	runtime·markspan(void *v, uintptr size, uintptr n, bool leftover);
 void	runtime·unmarkspan(void *v, uintptr size);
 bool	runtime·blockspecial(void*);
-void	runtime·setblockspecial(void*);
+void	runtime·setblockspecial(void*, bool);
 void	runtime·purgecachedstats(M*);
 
 enum
@@ -400,6 +406,8 @@ enum
 
 void	runtime·MProf_Malloc(void*, uintptr);
 void	runtime·MProf_Free(void*, uintptr);
+int32	runtime·helpgc(bool*);
+void	runtime·gchelper(void);
 
 // Malloc profiling settings.
 // Must match definition in extern.go.
@@ -410,13 +418,5 @@ enum {
 };
 extern int32 runtime·malloc_profile;
 
-typedef struct Finalizer Finalizer;
-struct Finalizer
-{
-	Finalizer *next;	// for use by caller of getfinalizer
-	void (*fn)(void*);
-	void *arg;
-	int32 nret;
-};
-
-Finalizer*	runtime·getfinalizer(void*, bool);
+bool	runtime·getfinalizer(void *p, bool del, void (**fn)(void*), int32 *nret);
+void	runtime·walkfintab(void (*fn)(void*));
diff --git a/src/pkg/runtime/mcache.c b/src/pkg/runtime/mcache.c
index 711e938..518e00c 100644
--- a/src/pkg/runtime/mcache.c
+++ b/src/pkg/runtime/mcache.c
@@ -7,6 +7,7 @@
 // See malloc.h for an overview.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 
 void*
diff --git a/src/pkg/runtime/mcentral.c b/src/pkg/runtime/mcentral.c
index 29b03b5..ff0c2d1 100644
--- a/src/pkg/runtime/mcentral.c
+++ b/src/pkg/runtime/mcentral.c
@@ -15,6 +15,7 @@
 // so that it is faster to move those lists between MCaches and MCentrals.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 
 static bool MCentral_Grow(MCentral *c);
diff --git a/src/pkg/runtime/mem_darwin.c b/src/pkg/runtime/mem_darwin.c
new file mode 100644
index 0000000..cde5601
--- /dev/null
+++ b/src/pkg/runtime/mem_darwin.c
@@ -0,0 +1,59 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "malloc.h"
+
+void*
+runtime·SysAlloc(uintptr n)
+{
+	void *v;
+
+	mstats.sys += n;
+	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if(v < (void*)4096)
+		return nil;
+	return v;
+}
+
+void
+runtime·SysUnused(void *v, uintptr n)
+{
+	// Linux's MADV_DONTNEED is like BSD's MADV_FREE.
+	runtime·madvise(v, n, MADV_FREE);
+}
+
+void
+runtime·SysFree(void *v, uintptr n)
+{
+	mstats.sys -= n;
+	runtime·munmap(v, n);
+}
+
+void*
+runtime·SysReserve(void *v, uintptr n)
+{
+	return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+}
+
+enum
+{
+	ENOMEM = 12,
+};
+
+void
+runtime·SysMap(void *v, uintptr n)
+{
+	void *p;
+	
+	mstats.sys += n;
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)-ENOMEM)
+		runtime·throw("runtime: out of memory");
+	if(p != v)
+		runtime·throw("runtime: cannot map pages in arena address space");
+}
diff --git a/src/pkg/runtime/mem_freebsd.c b/src/pkg/runtime/mem_freebsd.c
new file mode 100644
index 0000000..d1c2258
--- /dev/null
+++ b/src/pkg/runtime/mem_freebsd.c
@@ -0,0 +1,79 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "malloc.h"
+
+void*
+runtime·SysAlloc(uintptr n)
+{
+	void *v;
+
+	mstats.sys += n;
+	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if(v < (void*)4096)
+		return nil;
+	return v;
+}
+
+void
+runtime·SysUnused(void *v, uintptr n)
+{
+	USED(v);
+	USED(n);
+	// TODO(rsc): call madvise MADV_DONTNEED
+}
+
+void
+runtime·SysFree(void *v, uintptr n)
+{
+	mstats.sys -= n;
+	runtime·munmap(v, n);
+}
+
+void*
+runtime·SysReserve(void *v, uintptr n)
+{
+	// On 64-bit, people with ulimit -v set complain if we reserve too
+	// much address space.  Instead, assume that the reservation is okay
+	// and check the assumption in SysMap.
+	if(sizeof(void*) == 8)
+		return v;
+	
+	return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+}
+
+enum
+{
+	ENOMEM = 12,
+};
+
+void
+runtime·SysMap(void *v, uintptr n)
+{
+	void *p;
+	
+	mstats.sys += n;
+
+	// On 64-bit, we don't actually have v reserved, so tread carefully.
+	if(sizeof(void*) == 8) {
+		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		if(p == (void*)-ENOMEM)
+			runtime·throw("runtime: out of memory");
+		if(p != v) {
+			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
+			runtime·throw("runtime: address space conflict");
+		}
+		return;
+	}
+
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)-ENOMEM)
+		runtime·throw("runtime: out of memory");
+	if(p != v)
+		runtime·throw("runtime: cannot map pages in arena address space");
+}
diff --git a/src/pkg/runtime/mem_linux.c b/src/pkg/runtime/mem_linux.c
new file mode 100644
index 0000000..fdf02c2
--- /dev/null
+++ b/src/pkg/runtime/mem_linux.c
@@ -0,0 +1,119 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "malloc.h"
+
+enum
+{
+	ENOMEM = 12,
+	_PAGE_SIZE = 4096,
+};
+
+static int32
+addrspace_free(void *v, uintptr n)
+{
+	int32 errval;
+	uintptr chunk;
+	uintptr off;
+	static byte vec[4096];
+
+	for(off = 0; off < n; off += chunk) {
+		chunk = _PAGE_SIZE * sizeof vec;
+		if(chunk > (n - off))
+			chunk = n - off;
+		errval = runtime·mincore((int8*)v + off, chunk, vec);
+		// errval is 0 if success, or -(error_code) if error.
+		if (errval == 0 || errval != -ENOMEM)
+			return 0;
+	}
+	return 1;
+}
+
+
+void*
+runtime·SysAlloc(uintptr n)
+{
+	void *p;
+
+	mstats.sys += n;
+	p = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if(p < (void*)4096) {
+		if(p == (void*)EACCES) {
+			runtime·printf("runtime: mmap: access denied\n");
+			runtime·printf("if you're running SELinux, enable execmem for this process.\n");
+			runtime·exit(2);
+		}
+		return nil;
+	}
+	return p;
+}
+
+void
+runtime·SysUnused(void *v, uintptr n)
+{
+	runtime·madvise(v, n, MADV_DONTNEED);
+}
+
+void
+runtime·SysFree(void *v, uintptr n)
+{
+	mstats.sys -= n;
+	runtime·munmap(v, n);
+}
+
+void*
+runtime·SysReserve(void *v, uintptr n)
+{
+	void *p;
+
+	// On 64-bit, people with ulimit -v set complain if we reserve too
+	// much address space.  Instead, assume that the reservation is okay
+	// and check the assumption in SysMap.
+	if(sizeof(void*) == 8)
+		return v;
+	
+	p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if((uintptr)p < 4096 || -(uintptr)p < 4096) {
+		return nil;
+	}
+	return p;
+}
+
+void
+runtime·SysMap(void *v, uintptr n)
+{
+	void *p;
+	
+	mstats.sys += n;
+
+	// On 64-bit, we don't actually have v reserved, so tread carefully.
+	if(sizeof(void*) == 8) {
+		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		if(p != v && addrspace_free(v, n)) {
+			// On some systems, mmap ignores v without
+			// MAP_FIXED, so retry if the address space is free.
+			if(p > (void*)4096) {
+				runtime·munmap(p, n);
+			}
+			p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+		}
+		if(p == (void*)ENOMEM)
+			runtime·throw("runtime: out of memory");
+		if(p != v) {
+			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
+			runtime·throw("runtime: address space conflict");
+		}
+		return;
+	}
+
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)ENOMEM)
+		runtime·throw("runtime: out of memory");
+	if(p != v)
+		runtime·throw("runtime: cannot map pages in arena address space");
+}
diff --git a/src/pkg/runtime/mem_netbsd.c b/src/pkg/runtime/mem_netbsd.c
new file mode 100644
index 0000000..34ff31d
--- /dev/null
+++ b/src/pkg/runtime/mem_netbsd.c
@@ -0,0 +1,85 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "malloc.h"
+
+enum
+{
+	ENOMEM = 12,
+};
+
+void*
+runtime·SysAlloc(uintptr n)
+{
+	void *v;
+
+	mstats.sys += n;
+	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if(v < (void*)4096)
+		return nil;
+	return v;
+}
+
+void
+runtime·SysUnused(void *v, uintptr n)
+{
+	USED(v);
+	USED(n);
+	// TODO(rsc): call madvise MADV_DONTNEED
+}
+
+void
+runtime·SysFree(void *v, uintptr n)
+{
+	mstats.sys -= n;
+	runtime·munmap(v, n);
+}
+
+void*
+runtime·SysReserve(void *v, uintptr n)
+{
+	void *p;
+
+	// On 64-bit, people with ulimit -v set complain if we reserve too
+	// much address space.  Instead, assume that the reservation is okay
+	// and check the assumption in SysMap.
+	if(sizeof(void*) == 8)
+		return v;
+
+	p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if (p == ((void *)-ENOMEM))
+		return nil;
+	else
+		return p;
+}
+
+void
+runtime·SysMap(void *v, uintptr n)
+{
+	void *p;
+	
+	mstats.sys += n;
+
+	// On 64-bit, we don't actually have v reserved, so tread carefully.
+	if(sizeof(void*) == 8) {
+		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		if(p == (void*)-ENOMEM)
+			runtime·throw("runtime: out of memory");
+		if(p != v) {
+			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
+			runtime·throw("runtime: address space conflict");
+		}
+		return;
+	}
+
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)-ENOMEM)
+		runtime·throw("runtime: out of memory");
+	if(p != v)
+		runtime·throw("runtime: cannot map pages in arena address space");
+}
diff --git a/src/pkg/runtime/mem_openbsd.c b/src/pkg/runtime/mem_openbsd.c
new file mode 100644
index 0000000..34ff31d
--- /dev/null
+++ b/src/pkg/runtime/mem_openbsd.c
@@ -0,0 +1,85 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "malloc.h"
+
+enum
+{
+	ENOMEM = 12,
+};
+
+void*
+runtime·SysAlloc(uintptr n)
+{
+	void *v;
+
+	mstats.sys += n;
+	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if(v < (void*)4096)
+		return nil;
+	return v;
+}
+
+void
+runtime·SysUnused(void *v, uintptr n)
+{
+	USED(v);
+	USED(n);
+	// TODO(rsc): call madvise MADV_DONTNEED
+}
+
+void
+runtime·SysFree(void *v, uintptr n)
+{
+	mstats.sys -= n;
+	runtime·munmap(v, n);
+}
+
+void*
+runtime·SysReserve(void *v, uintptr n)
+{
+	void *p;
+
+	// On 64-bit, people with ulimit -v set complain if we reserve too
+	// much address space.  Instead, assume that the reservation is okay
+	// and check the assumption in SysMap.
+	if(sizeof(void*) == 8)
+		return v;
+
+	p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if (p == ((void *)-ENOMEM))
+		return nil;
+	else
+		return p;
+}
+
+void
+runtime·SysMap(void *v, uintptr n)
+{
+	void *p;
+	
+	mstats.sys += n;
+
+	// On 64-bit, we don't actually have v reserved, so tread carefully.
+	if(sizeof(void*) == 8) {
+		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+		if(p == (void*)-ENOMEM)
+			runtime·throw("runtime: out of memory");
+		if(p != v) {
+			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
+			runtime·throw("runtime: address space conflict");
+		}
+		return;
+	}
+
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)-ENOMEM)
+		runtime·throw("runtime: out of memory");
+	if(p != v)
+		runtime·throw("runtime: cannot map pages in arena address space");
+}
diff --git a/src/pkg/runtime/mem_plan9.c b/src/pkg/runtime/mem_plan9.c
new file mode 100644
index 0000000..15cbc17
--- /dev/null
+++ b/src/pkg/runtime/mem_plan9.c
@@ -0,0 +1,68 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+#include "os_GOOS.h"
+
+extern byte end[];
+static byte *bloc = { end };
+static Lock memlock;
+
+enum
+{
+	Round = 4095
+};
+
+void*
+runtime·SysAlloc(uintptr nbytes)
+{
+	uintptr bl;
+	
+	runtime·lock(&memlock);
+	mstats.sys += nbytes;
+	// Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
+	bl = ((uintptr)bloc + Round) & ~Round;
+	if(runtime·brk_((void*)(bl + nbytes)) < 0) {
+		runtime·unlock(&memlock);
+		return nil;
+	}
+	bloc = (byte*)bl + nbytes;
+	runtime·unlock(&memlock);
+	return (void*)bl;
+}
+
+void
+runtime·SysFree(void *v, uintptr nbytes)
+{
+	runtime·lock(&memlock);
+	mstats.sys -= nbytes;
+	// from tiny/mem.c
+	// Push pointer back if this is a free
+	// of the most recent SysAlloc.
+	nbytes += (nbytes + Round) & ~Round;
+	if(bloc == (byte*)v+nbytes)
+		bloc -= nbytes;	
+	runtime·unlock(&memlock);
+}
+
+void
+runtime·SysUnused(void *v, uintptr nbytes)
+{
+	USED(v, nbytes);
+}
+
+void
+runtime·SysMap(void *v, uintptr nbytes)
+{
+	USED(v, nbytes);
+}
+
+void*
+runtime·SysReserve(void *v, uintptr nbytes)
+{
+	USED(v);
+	return runtime·SysAlloc(nbytes);
+}
diff --git a/src/pkg/runtime/mem_windows.c b/src/pkg/runtime/mem_windows.c
new file mode 100644
index 0000000..7840daa
--- /dev/null
+++ b/src/pkg/runtime/mem_windows.c
@@ -0,0 +1,71 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "os_GOOS.h"
+#include "defs_GOOS_GOARCH.h"
+#include "malloc.h"
+
+enum {
+	MEM_COMMIT = 0x1000,
+	MEM_RESERVE = 0x2000,
+	MEM_RELEASE = 0x8000,
+	
+	PAGE_EXECUTE_READWRITE = 0x40,
+};
+
+#pragma dynimport runtime·VirtualAlloc VirtualAlloc "kernel32.dll"
+#pragma dynimport runtime·VirtualFree VirtualFree "kernel32.dll"
+extern void *runtime·VirtualAlloc;
+extern void *runtime·VirtualFree;
+
+void*
+runtime·SysAlloc(uintptr n)
+{
+	mstats.sys += n;
+	return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)(MEM_COMMIT|MEM_RESERVE), (uintptr)PAGE_EXECUTE_READWRITE);
+}
+
+void
+runtime·SysUnused(void *v, uintptr n)
+{
+	USED(v);
+	USED(n);
+}
+
+void
+runtime·SysFree(void *v, uintptr n)
+{
+	uintptr r;
+
+	mstats.sys -= n;
+	r = (uintptr)runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_RELEASE);
+	if(r == 0)
+		runtime·throw("runtime: failed to release pages");
+}
+
+void*
+runtime·SysReserve(void *v, uintptr n)
+{
+	// v is just a hint.
+	// First try at v.
+	v = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_EXECUTE_READWRITE);
+	if(v != nil)
+		return v;
+	
+	// Next let the kernel choose the address.
+	return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_EXECUTE_READWRITE);
+}
+
+void
+runtime·SysMap(void *v, uintptr n)
+{
+	void *p;
+	
+	mstats.sys += n;
+	p = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_EXECUTE_READWRITE);
+	if(p != v)
+		runtime·throw("runtime: cannot map pages in arena address space");
+}
diff --git a/src/pkg/runtime/386/memmove.s b/src/pkg/runtime/memmove_386.s
similarity index 100%
rename from src/pkg/runtime/386/memmove.s
rename to src/pkg/runtime/memmove_386.s
diff --git a/src/pkg/runtime/amd64/memmove.s b/src/pkg/runtime/memmove_amd64.s
similarity index 100%
rename from src/pkg/runtime/amd64/memmove.s
rename to src/pkg/runtime/memmove_amd64.s
diff --git a/src/pkg/runtime/arm/memmove.s b/src/pkg/runtime/memmove_arm.s
similarity index 100%
rename from src/pkg/runtime/arm/memmove.s
rename to src/pkg/runtime/memmove_arm.s
diff --git a/src/pkg/runtime/arm/memset.s b/src/pkg/runtime/memset_arm.s
similarity index 100%
rename from src/pkg/runtime/arm/memset.s
rename to src/pkg/runtime/memset_arm.s
diff --git a/src/pkg/runtime/mfinal.c b/src/pkg/runtime/mfinal.c
index f313814..c6f2b54 100644
--- a/src/pkg/runtime/mfinal.c
+++ b/src/pkg/runtime/mfinal.c
@@ -3,12 +3,17 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 
-// Lock to protect finalizer data structures.
-// Cannot reuse mheap.Lock because the finalizer
-// maintenance requires allocation.
-static Lock finlock;
+enum { debug = 0 };
+
+typedef struct Fin Fin;
+struct Fin
+{
+	void (*fn)(void*);
+	int32 nret;
+};
 
 // Finalizer hash table.  Direct hash, linear scan, at most 3/4 full.
 // Table size is power of 3 so that hash can be key % max.
@@ -20,15 +25,24 @@ static Lock finlock;
 typedef struct Fintab Fintab;
 struct Fintab
 {
+	Lock;
 	void **key;
-	Finalizer **val;
+	Fin *val;
 	int32 nkey;	// number of non-nil entries in key
 	int32 ndead;	// number of dead (-1) entries in key
 	int32 max;	// size of key, val allocations
 };
 
+#define TABSZ 17
+#define TAB(p) (&fintab[((uintptr)(p)>>3)%TABSZ])
+
+static struct {
+	Fintab;
+	uint8 pad[CacheLineSize - sizeof(Fintab)];	
+} fintab[TABSZ];
+
 static void
-addfintab(Fintab *t, void *k, Finalizer *v)
+addfintab(Fintab *t, void *k, void (*fn)(void*), int32 nret)
 {
 	int32 i, j;
 
@@ -51,29 +65,31 @@ addfintab(Fintab *t, void *k, Finalizer *v)
 
 ret:
 	t->key[i] = k;
-	t->val[i] = v;
+	t->val[i].fn = fn;
+	t->val[i].nret = nret;
 }
 
-static Finalizer*
-lookfintab(Fintab *t, void *k, bool del)
+static bool
+lookfintab(Fintab *t, void *k, bool del, Fin *f)
 {
 	int32 i, j;
-	Finalizer *v;
 
 	if(t->max == 0)
-		return nil;
+		return false;
 	i = (uintptr)k % (uintptr)t->max;
 	for(j=0; j<t->max; j++) {
 		if(t->key[i] == nil)
-			return nil;
+			return false;
 		if(t->key[i] == k) {
-			v = t->val[i];
+			if(f)
+				*f = t->val[i];
 			if(del) {
 				t->key[i] = (void*)-1;
-				t->val[i] = nil;
+				t->val[i].fn = nil;
+				t->val[i].nret = 0;
 				t->ndead++;
 			}
-			return v;
+			return true;
 		}
 		if(++i == t->max)
 			i = 0;
@@ -81,88 +97,100 @@ lookfintab(Fintab *t, void *k, bool del)
 
 	// cannot happen - table is known to be non-full
 	runtime·throw("finalizer table inconsistent");
-	return nil;
+	return false;
 }
 
-static Fintab fintab;
-
-// add finalizer; caller is responsible for making sure not already in table
-void
-runtime·addfinalizer(void *p, void (*f)(void*), int32 nret)
+static void
+resizefintab(Fintab *tab)
 {
 	Fintab newtab;
+	void *k;
 	int32 i;
-	byte *base;
-	Finalizer *e;
+
+	runtime·memclr((byte*)&newtab, sizeof newtab);
+	newtab.max = tab->max;
+	if(newtab.max == 0)
+		newtab.max = 3*3*3;
+	else if(tab->ndead < tab->nkey/2) {
+		// grow table if not many dead values.
+		// otherwise just rehash into table of same size.
+		newtab.max *= 3;
+	}
 	
-	e = nil;
-	if(f != nil) {
-		e = runtime·mal(sizeof *e);
-		e->fn = f;
-		e->nret = nret;
+	newtab.key = runtime·mallocgc(newtab.max*sizeof newtab.key[0], FlagNoPointers, 0, 1);
+	newtab.val = runtime·mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
+	
+	for(i=0; i<tab->max; i++) {
+		k = tab->key[i];
+		if(k != nil && k != (void*)-1)
+			addfintab(&newtab, k, tab->val[i].fn, tab->val[i].nret);
 	}
+	
+	runtime·free(tab->key);
+	runtime·free(tab->val);
+	
+	tab->key = newtab.key;
+	tab->val = newtab.val;
+	tab->nkey = newtab.nkey;
+	tab->ndead = newtab.ndead;
+	tab->max = newtab.max;
+}
 
-	runtime·lock(&finlock);
-	if(!runtime·mlookup(p, &base, nil, nil) || p != base) {
-		runtime·unlock(&finlock);
-		runtime·throw("addfinalizer on invalid pointer");
+bool
+runtime·addfinalizer(void *p, void (*f)(void*), int32 nret)
+{
+	Fintab *tab;
+	byte *base;
+	
+	if(debug) {
+		if(!runtime·mlookup(p, &base, nil, nil) || p != base)
+			runtime·throw("addfinalizer on invalid pointer");
 	}
+	
+	tab = TAB(p);
+	runtime·lock(tab);
 	if(f == nil) {
-		lookfintab(&fintab, p, 1);
-		runtime·unlock(&finlock);
-		return;
+		if(lookfintab(tab, p, true, nil))
+			runtime·setblockspecial(p, false);
+		runtime·unlock(tab);
+		return true;
 	}
 
-	if(lookfintab(&fintab, p, 0)) {
-		runtime·unlock(&finlock);
-		runtime·throw("double finalizer");
+	if(lookfintab(tab, p, false, nil)) {
+		runtime·unlock(tab);
+		return false;
 	}
-	runtime·setblockspecial(p);
 
-	if(fintab.nkey >= fintab.max/2+fintab.max/4) {
+	if(tab->nkey >= tab->max/2+tab->max/4) {
 		// keep table at most 3/4 full:
 		// allocate new table and rehash.
-
-		runtime·memclr((byte*)&newtab, sizeof newtab);
-		newtab.max = fintab.max;
-		if(newtab.max == 0)
-			newtab.max = 3*3*3;
-		else if(fintab.ndead < fintab.nkey/2) {
-			// grow table if not many dead values.
-			// otherwise just rehash into table of same size.
-			newtab.max *= 3;
-		}
-
-		newtab.key = runtime·mallocgc(newtab.max*sizeof newtab.key[0], FlagNoPointers, 0, 1);
-		newtab.val = runtime·mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
-
-		for(i=0; i<fintab.max; i++) {
-			void *k;
-
-			k = fintab.key[i];
-			if(k != nil && k != (void*)-1)
-				addfintab(&newtab, k, fintab.val[i]);
-		}
-		runtime·free(fintab.key);
-		runtime·free(fintab.val);
-		fintab = newtab;
+		resizefintab(tab);
 	}
 
-	addfintab(&fintab, p, e);
-	runtime·unlock(&finlock);
+	addfintab(tab, p, f, nret);
+	runtime·setblockspecial(p, true);
+	runtime·unlock(tab);
+	return true;
 }
 
 // get finalizer; if del, delete finalizer.
-// caller is responsible for updating RefHasFinalizer bit.
-Finalizer*
-runtime·getfinalizer(void *p, bool del)
+// caller is responsible for updating RefHasFinalizer (special) bit.
+bool
+runtime·getfinalizer(void *p, bool del, void (**fn)(void*), int32 *nret)
 {
-	Finalizer *f;
+	Fintab *tab;
+	bool res;
+	Fin f;
 	
-	runtime·lock(&finlock);
-	f = lookfintab(&fintab, p, del);
-	runtime·unlock(&finlock);
-	return f;
+	tab = TAB(p);
+	runtime·lock(tab);
+	res = lookfintab(tab, p, del, &f);
+	runtime·unlock(tab);
+	if(res==false)
+		return false;
+	*fn = f.fn;
+	*nret = f.nret;
+	return true;
 }
 
 void
@@ -170,12 +198,15 @@ runtime·walkfintab(void (*fn)(void*))
 {
 	void **key;
 	void **ekey;
+	int32 i;
 
-	runtime·lock(&finlock);
-	key = fintab.key;
-	ekey = key + fintab.max;
-	for(; key < ekey; key++)
-		if(*key != nil && *key != ((void*)-1))
-			fn(*key);
-	runtime·unlock(&finlock);
+	for(i=0; i<TABSZ; i++) {
+		runtime·lock(&fintab[i]);
+		key = fintab[i].key;
+		ekey = key + fintab[i].max;
+		for(; key < ekey; key++)
+			if(*key != nil && *key != ((void*)-1))
+				fn(*key);
+		runtime·unlock(&fintab[i]);
+	}
 }
diff --git a/src/pkg/runtime/mfinal_test.go b/src/pkg/runtime/mfinal_test.go
new file mode 100644
index 0000000..de63271
--- /dev/null
+++ b/src/pkg/runtime/mfinal_test.go
@@ -0,0 +1,64 @@
+// Copyright 2011 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 runtime_test
+
+import (
+	"runtime"
+	"sync"
+	"sync/atomic"
+	"testing"
+)
+
+func fin(v *int) {
+}
+
+func BenchmarkFinalizer(b *testing.B) {
+	const CallsPerSched = 1000
+	procs := runtime.GOMAXPROCS(-1)
+	N := int32(b.N / CallsPerSched)
+	var wg sync.WaitGroup
+	wg.Add(procs)
+	for p := 0; p < procs; p++ {
+		go func() {
+			var data [CallsPerSched]*int
+			for i := 0; i < CallsPerSched; i++ {
+				data[i] = new(int)
+			}
+			for atomic.AddInt32(&N, -1) >= 0 {
+				runtime.Gosched()
+				for i := 0; i < CallsPerSched; i++ {
+					runtime.SetFinalizer(data[i], fin)
+				}
+				for i := 0; i < CallsPerSched; i++ {
+					runtime.SetFinalizer(data[i], nil)
+				}
+			}
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func BenchmarkFinalizerRun(b *testing.B) {
+	const CallsPerSched = 1000
+	procs := runtime.GOMAXPROCS(-1)
+	N := int32(b.N / CallsPerSched)
+	var wg sync.WaitGroup
+	wg.Add(procs)
+	for p := 0; p < procs; p++ {
+		go func() {
+			for atomic.AddInt32(&N, -1) >= 0 {
+				runtime.Gosched()
+				for i := 0; i < CallsPerSched; i++ {
+					v := new(int)
+					runtime.SetFinalizer(v, fin)
+				}
+				runtime.GC()
+			}
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
diff --git a/src/pkg/runtime/mfixalloc.c b/src/pkg/runtime/mfixalloc.c
index ab9df31..c916d58 100644
--- a/src/pkg/runtime/mfixalloc.c
+++ b/src/pkg/runtime/mfixalloc.c
@@ -7,6 +7,7 @@
 // See malloc.h for overview.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 
 // Initialize f to allocate objects of the given size,
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index 03d6f7d..78daa78 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -5,14 +5,15 @@
 // Garbage collector.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 #include "stack.h"
 
 enum {
 	Debug = 0,
-	UseCas = 1,
 	PtrSize = sizeof(void*),
-	
+	DebugMark = 0,  // run second pass to check mark
+
 	// Four bits per word (see #defines below).
 	wordsPerBitmapWord = sizeof(void*)*8/4,
 	bitShift = sizeof(void*)*8/4,
@@ -51,17 +52,35 @@ enum {
 
 #define bitMask (bitBlockBoundary | bitAllocated | bitMarked | bitSpecial)
 
-static uint64 nlookup;
-static uint64 nsizelookup;
-static uint64 naddrlookup;
+// TODO: Make these per-M.
+static uint64 nhandoff;
+
 static int32 gctrace;
 
 typedef struct Workbuf Workbuf;
 struct Workbuf
 {
 	Workbuf *next;
-	uintptr nw;
-	byte *w[2048-2];
+	uintptr nobj;
+	byte *obj[512-2];
+};
+
+typedef struct Finalizer Finalizer;
+struct Finalizer
+{
+	void (*fn)(void*);
+	void *arg;
+	int32 nret;
+};
+
+typedef struct FinBlock FinBlock;
+struct FinBlock
+{
+	FinBlock *alllink;
+	FinBlock *next;
+	int32 cnt;
+	int32 cap;
+	Finalizer fin[1];
 };
 
 extern byte data[];
@@ -69,12 +88,35 @@ extern byte etext[];
 extern byte end[];
 
 static G *fing;
-static Finalizer *finq;
+static FinBlock *finq; // list of finalizers that are to be executed
+static FinBlock *finc; // cache of free blocks
+static FinBlock *allfin; // list of all blocks
+static Lock finlock;
 static int32 fingwait;
 
 static void runfinq(void);
 static Workbuf* getempty(Workbuf*);
 static Workbuf* getfull(Workbuf*);
+static void	putempty(Workbuf*);
+static Workbuf* handoff(Workbuf*);
+
+static struct {
+	Lock fmu;
+	Workbuf	*full;
+	Lock emu;
+	Workbuf	*empty;
+	uint32	nproc;
+	volatile uint32	nwait;
+	volatile uint32	ndone;
+	Note	alldone;
+	Lock	markgate;
+	Lock	sweepgate;
+	MSpan	*spans;
+
+	Lock;
+	byte	*chunk;
+	uintptr	nchunk;
+} work;
 
 // scanblock scans a block of n bytes starting at pointer b for references
 // to other objects, scanning any it finds recursively until there are no
@@ -85,13 +127,14 @@ static Workbuf* getfull(Workbuf*);
 static void
 scanblock(byte *b, int64 n)
 {
-	byte *obj, *arena_start, *p;
+	byte *obj, *arena_start, *arena_used, *p;
 	void **vp;
-	uintptr size, *bitp, bits, shift, i, j, x, xbits, off;
+	uintptr size, *bitp, bits, shift, i, j, x, xbits, off, nobj, nproc;
 	MSpan *s;
 	PageID k;
-	void **bw, **w, **ew;
+	void **wp;
 	Workbuf *wbuf;
+	bool keepworking;
 
 	if((int64)(uintptr)n != n || n < 0) {
 		runtime·printf("scanblock %p %D\n", b, n);
@@ -100,11 +143,19 @@ scanblock(byte *b, int64 n)
 
 	// Memory arena parameters.
 	arena_start = runtime·mheap.arena_start;
-	
+	arena_used = runtime·mheap.arena_used;
+	nproc = work.nproc;
+
 	wbuf = nil;  // current work buffer
-	ew = nil;  // end of work buffer
-	bw = nil;  // beginning of work buffer
-	w = nil;  // current pointer into work buffer
+	wp = nil;  // storage for next queued pointer (write pointer)
+	nobj = 0;  // number of queued objects
+
+	// Scanblock helpers pass b==nil.
+	// The main proc needs to return to make more
+	// calls to scanblock.  But if work.nproc==1 then
+	// might as well process blocks as soon as we
+	// have them.
+	keepworking = b == nil || work.nproc == 1;
 
 	// Align b to a word boundary.
 	off = (uintptr)b & (PtrSize-1);
@@ -120,17 +171,17 @@ scanblock(byte *b, int64 n)
 			runtime·printf("scanblock %p %D\n", b, n);
 
 		vp = (void**)b;
-		n /= PtrSize;
+		n >>= (2+PtrSize/8);  /* n /= PtrSize (4 or 8) */
 		for(i=0; i<n; i++) {
 			obj = (byte*)vp[i];
-			
+
 			// Words outside the arena cannot be pointers.
-			if((byte*)obj < arena_start || (byte*)obj >= runtime·mheap.arena_used)
+			if((byte*)obj < arena_start || (byte*)obj >= arena_used)
 				continue;
-			
+
 			// obj may be a pointer to a live object.
 			// Try to find the beginning of the object.
-			
+
 			// Round down to word boundary.
 			obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
 
@@ -158,8 +209,6 @@ scanblock(byte *b, int64 n)
 
 			// Otherwise consult span table to find beginning.
 			// (Manually inlined copy of MHeap_LookupMaybe.)
-			nlookup++;
-			naddrlookup++;
 			k = (uintptr)obj>>PageShift;
 			x = k;
 			if(sizeof(void*) == 8)
@@ -188,83 +237,67 @@ scanblock(byte *b, int64 n)
 		found:
 			// Now we have bits, bitp, and shift correct for
 			// obj pointing at the base of the object.
-			// If not allocated or already marked, done.
-			if((bits & bitAllocated) == 0 || (bits & bitMarked) != 0)
+			// Only care about allocated and not marked.
+			if((bits & (bitAllocated|bitMarked)) != bitAllocated)
 				continue;
-			*bitp |= bitMarked<<shift;
+			if(nproc == 1)
+				*bitp |= bitMarked<<shift;
+			else {
+				for(;;) {
+					x = *bitp;
+					if(x & (bitMarked<<shift))
+						goto continue_obj;
+					if(runtime·casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
+						break;
+				}
+			}
 
 			// If object has no pointers, don't need to scan further.
 			if((bits & bitNoPointers) != 0)
 				continue;
 
+			// If another proc wants a pointer, give it some.
+			if(nobj > 4 && work.nwait > 0 && work.full == nil) {
+				wbuf->nobj = nobj;
+				wbuf = handoff(wbuf);
+				nobj = wbuf->nobj;
+				wp = wbuf->obj + nobj;
+			}
+
 			// If buffer is full, get a new one.
-			if(w >= ew) {
+			if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
+				if(wbuf != nil)
+					wbuf->nobj = nobj;
 				wbuf = getempty(wbuf);
-				bw = wbuf->w;
-				w = bw;
-				ew = bw + nelem(wbuf->w);
+				wp = wbuf->obj;
+				nobj = 0;
 			}
-			*w++ = obj;
+			*wp++ = obj;
+			nobj++;
+		continue_obj:;
 		}
-		
+
 		// Done scanning [b, b+n).  Prepare for the next iteration of
 		// the loop by setting b and n to the parameters for the next block.
 
-		// Fetch b from the work buffers.
-		if(w <= bw) {
+		// Fetch b from the work buffer.
+		if(nobj == 0) {
+			if(!keepworking) {
+				putempty(wbuf);
+				return;
+			}
 			// Emptied our buffer: refill.
 			wbuf = getfull(wbuf);
 			if(wbuf == nil)
-				break;
-			bw = wbuf->w;
-			ew = wbuf->w + nelem(wbuf->w);
-			w = bw+wbuf->nw;
-		}
-		b = *--w;
-	
-		// Figure out n = size of b.  Start by loading bits for b.
-		off = (uintptr*)b - (uintptr*)arena_start;
-		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
-		shift = off % wordsPerBitmapWord;
-		xbits = *bitp;
-		bits = xbits >> shift;
-		
-		// Might be small; look for nearby block boundary.
-		// A block boundary is marked by either bitBlockBoundary
-		// or bitAllocated being set (see notes near their definition).
-		enum {
-			boundary = bitBlockBoundary|bitAllocated
-		};
-		// Look for a block boundary both after and before b
-		// in the same bitmap word.
-		//
-		// A block boundary j words after b is indicated by
-		//	bits>>j & boundary
-		// assuming shift+j < bitShift.  (If shift+j >= bitShift then
-		// we'll be bleeding other bit types like bitMarked into our test.)
-		// Instead of inserting the conditional shift+j < bitShift into the loop,
-		// we can let j range from 1 to bitShift as long as we first
-		// apply a mask to keep only the bits corresponding
-		// to shift+j < bitShift aka j < bitShift-shift.
-		bits &= (boundary<<(bitShift-shift)) - boundary;
-		
-		// A block boundary j words before b is indicated by
-		//	xbits>>(shift-j) & boundary
-		// (assuming shift >= j).  There is no cleverness here
-		// avoid the test, because when j gets too large the shift
-		// turns negative, which is undefined in C.		
-
-		for(j=1; j<bitShift; j++) {
-			if(((bits>>j)&boundary) != 0 || shift>=j && ((xbits>>(shift-j))&boundary) != 0) {
-				n = j*PtrSize;
-				goto scan;
-			}
+				return;
+			nobj = wbuf->nobj;
+			wp = wbuf->obj + wbuf->nobj;
 		}
-		
-		// Fall back to asking span about size class.
+		b = *--wp;
+		nobj--;
+
+		// Ask span about size class.
 		// (Manually inlined copy of MHeap_Lookup.)
-		nlookup++;
-		nsizelookup++;
 		x = (uintptr)b>>PageShift;
 		if(sizeof(void*) == 8)
 			x -= (uintptr)arena_start>>PageShift;
@@ -273,33 +306,126 @@ scanblock(byte *b, int64 n)
 			n = s->npages<<PageShift;
 		else
 			n = runtime·class_to_size[s->sizeclass];
-	scan:;
 	}
 }
 
-static struct {
-	Workbuf	*full;
-	Workbuf	*empty;
-	byte	*chunk;
-	uintptr	nchunk;
-} work;
+// debug_scanblock is the debug copy of scanblock.
+// it is simpler, slower, single-threaded, recursive,
+// and uses bitSpecial as the mark bit.
+static void
+debug_scanblock(byte *b, int64 n)
+{
+	byte *obj, *p;
+	void **vp;
+	uintptr size, *bitp, bits, shift, i, xbits, off;
+	MSpan *s;
+
+	if(!DebugMark)
+		runtime·throw("debug_scanblock without DebugMark");
+
+	if((int64)(uintptr)n != n || n < 0) {
+		runtime·printf("debug_scanblock %p %D\n", b, n);
+		runtime·throw("debug_scanblock");
+	}
+
+	// Align b to a word boundary.
+	off = (uintptr)b & (PtrSize-1);
+	if(off != 0) {
+		b += PtrSize - off;
+		n -= PtrSize - off;
+	}
+
+	vp = (void**)b;
+	n /= PtrSize;
+	for(i=0; i<n; i++) {
+		obj = (byte*)vp[i];
+
+		// Words outside the arena cannot be pointers.
+		if((byte*)obj < runtime·mheap.arena_start || (byte*)obj >= runtime·mheap.arena_used)
+			continue;
+
+		// Round down to word boundary.
+		obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
+
+		// Consult span table to find beginning.
+		s = runtime·MHeap_LookupMaybe(&runtime·mheap, obj);
+		if(s == nil)
+			continue;
+
+
+		p =  (byte*)((uintptr)s->start<<PageShift);
+		if(s->sizeclass == 0) {
+			obj = p;
+			size = (uintptr)s->npages<<PageShift;
+		} else {
+			if((byte*)obj >= (byte*)s->limit)
+				continue;
+			size = runtime·class_to_size[s->sizeclass];
+			int32 i = ((byte*)obj - p)/size;
+			obj = p+i*size;
+		}
+
+		// Now that we know the object header, reload bits.
+		off = (uintptr*)obj - (uintptr*)runtime·mheap.arena_start;
+		bitp = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		xbits = *bitp;
+		bits = xbits >> shift;
+
+		// Now we have bits, bitp, and shift correct for
+		// obj pointing at the base of the object.
+		// If not allocated or already marked, done.
+		if((bits & bitAllocated) == 0 || (bits & bitSpecial) != 0)  // NOTE: bitSpecial not bitMarked
+			continue;
+		*bitp |= bitSpecial<<shift;
+		if(!(bits & bitMarked))
+			runtime·printf("found unmarked block %p in %p\n", obj, vp+i);
+
+		// If object has no pointers, don't need to scan further.
+		if((bits & bitNoPointers) != 0)
+			continue;
+
+		debug_scanblock(obj, size);
+	}
+}
 
 // Get an empty work buffer off the work.empty list,
 // allocating new buffers as needed.
 static Workbuf*
 getempty(Workbuf *b)
 {
-	if(b != nil) {
-		b->nw = nelem(b->w);
-		b->next = work.full;
-		work.full = b;
-	}
-	b = work.empty;
-	if(b != nil) {
-		work.empty = b->next;
-		return b;
+	if(work.nproc == 1) {
+		// Put b on full list.
+		if(b != nil) {
+			b->next = work.full;
+			work.full = b;
+		}
+		// Grab from empty list if possible.
+		b = work.empty;
+		if(b != nil) {
+			work.empty = b->next;
+			goto haveb;
+		}
+	} else {
+		// Put b on full list.
+		if(b != nil) {
+			runtime·lock(&work.fmu);
+			b->next = work.full;
+			work.full = b;
+			runtime·unlock(&work.fmu);
+		}
+		// Grab from empty list if possible.
+		runtime·lock(&work.emu);
+		b = work.empty;
+		if(b != nil)
+			work.empty = b->next;
+		runtime·unlock(&work.emu);
+		if(b != nil)
+			goto haveb;
 	}
-	
+
+	// Need to allocate.
+	runtime·lock(&work);
 	if(work.nchunk < sizeof *b) {
 		work.nchunk = 1<<20;
 		work.chunk = runtime·SysAlloc(work.nchunk);
@@ -307,28 +433,124 @@ getempty(Workbuf *b)
 	b = (Workbuf*)work.chunk;
 	work.chunk += sizeof *b;
 	work.nchunk -= sizeof *b;
+	runtime·unlock(&work);
+
+haveb:
+	b->nobj = 0;
 	return b;
 }
 
+static void
+putempty(Workbuf *b)
+{
+	if(b == nil)
+		return;
+
+	if(work.nproc == 1) {
+		b->next = work.empty;
+		work.empty = b;
+		return;
+	}
+
+	runtime·lock(&work.emu);
+	b->next = work.empty;
+	work.empty = b;
+	runtime·unlock(&work.emu);
+}
+
 // Get a full work buffer off the work.full list, or return nil.
 static Workbuf*
 getfull(Workbuf *b)
 {
-	if(b != nil) {
-		b->nw = 0;
-		b->next = work.empty;
-		work.empty = b;
+	int32 i;
+	Workbuf *b1;
+
+	if(work.nproc == 1) {
+		// Put b on empty list.
+		if(b != nil) {
+			b->next = work.empty;
+			work.empty = b;
+		}
+		// Grab from full list if possible.
+		// Since work.nproc==1, no one else is
+		// going to give us work.
+		b = work.full;
+		if(b != nil)
+			work.full = b->next;
+		return b;
 	}
-	b = work.full;
-	if(b != nil)
-		work.full = b->next;
-	return b;
+
+	putempty(b);
+
+	// Grab buffer from full list if possible.
+	for(;;) {
+		b1 = work.full;
+		if(b1 == nil)
+			break;
+		runtime·lock(&work.fmu);
+		if(work.full != nil) {
+			b1 = work.full;
+			work.full = b1->next;
+			runtime·unlock(&work.fmu);
+			return b1;
+		}
+		runtime·unlock(&work.fmu);
+	}
+
+	runtime·xadd(&work.nwait, +1);
+	for(i=0;; i++) {
+		b1 = work.full;
+		if(b1 != nil) {
+			runtime·lock(&work.fmu);
+			if(work.full != nil) {
+				runtime·xadd(&work.nwait, -1);
+				b1 = work.full;
+				work.full = b1->next;
+				runtime·unlock(&work.fmu);
+				return b1;
+			}
+			runtime·unlock(&work.fmu);
+			continue;
+		}
+		if(work.nwait == work.nproc)
+			return nil;
+		if(i < 10)
+			runtime·procyield(20);
+		else if(i < 20)
+			runtime·osyield();
+		else
+			runtime·usleep(100);
+	}
+}
+
+static Workbuf*
+handoff(Workbuf *b)
+{
+	int32 n;
+	Workbuf *b1;
+
+	// Make new buffer with half of b's pointers.
+	b1 = getempty(nil);
+	n = b->nobj/2;
+	b->nobj -= n;
+	b1->nobj = n;
+	runtime·memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
+	nhandoff += n;
+
+	// Put b on full list - let first half of b get stolen.
+	runtime·lock(&work.fmu);
+	b->next = work.full;
+	work.full = b;
+	runtime·unlock(&work.fmu);
+
+	return b1;
 }
 
 // Scanstack calls scanblock on each of gp's stack segments.
 static void
-scanstack(G *gp)
+scanstack(void (*scanblock)(byte*, int64), G *gp)
 {
+	M *mp;
 	int32 n;
 	Stktop *stk;
 	byte *sp, *guard;
@@ -339,6 +561,9 @@ scanstack(G *gp)
 	if(gp == g) {
 		// Scanning our own stack: start at &gp.
 		sp = (byte*)&gp;
+	} else if((mp = gp->m) != nil && mp->helpgc) {
+		// gchelper's stack is in active use and has no interesting pointers.
+		return;
 	} else {
 		// Scanning another goroutine's stack.
 		// The goroutine is usually asleep (the world is stopped).
@@ -387,17 +612,28 @@ markfin(void *v)
 	scanblock(v, size);
 }
 
-// Mark 
 static void
-mark(void)
+debug_markfin(void *v)
+{
+	uintptr size;
+
+	if(!runtime·mlookup(v, &v, &size, nil))
+		runtime·throw("debug_mark - finalizer inconsistency");
+	debug_scanblock(v, size);
+}
+
+// Mark
+static void
+mark(void (*scan)(byte*, int64))
 {
 	G *gp;
+	FinBlock *fb;
 
 	// mark data+bss.
 	// skip runtime·mheap itself, which has no interesting pointers
 	// and is mostly zeroed and would not otherwise be paged in.
-	scanblock(data, (byte*)&runtime·mheap - data);
-	scanblock((byte*)(&runtime·mheap+1), end - (byte*)(&runtime·mheap+1));
+	scan(data, (byte*)&runtime·mheap - data);
+	scan((byte*)(&runtime·mheap+1), end - (byte*)(&runtime·mheap+1));
 
 	// mark stacks
 	for(gp=runtime·allg; gp!=nil; gp=gp->alllink) {
@@ -410,21 +646,66 @@ mark(void)
 		case Grunning:
 			if(gp != g)
 				runtime·throw("mark - world not stopped");
-			scanstack(gp);
+			scanstack(scan, gp);
 			break;
 		case Grunnable:
 		case Gsyscall:
 		case Gwaiting:
-			scanstack(gp);
+			scanstack(scan, gp);
 			break;
 		}
 	}
 
 	// mark things pointed at by objects with finalizers
-	runtime·walkfintab(markfin);
+	if(scan == debug_scanblock)
+		runtime·walkfintab(debug_markfin);
+	else
+		runtime·walkfintab(markfin);
+
+	for(fb=allfin; fb; fb=fb->alllink)
+		scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]));
+
+	// in multiproc mode, join in the queued work.
+	scan(nil, 0);
+}
+
+static bool
+handlespecial(byte *p, uintptr size)
+{
+	void (*fn)(void*);
+	int32 nret;
+	FinBlock *block;
+	Finalizer *f;
+	
+	if(!runtime·getfinalizer(p, true, &fn, &nret)) {
+		runtime·setblockspecial(p, false);
+		runtime·MProf_Free(p, size);
+		return false;
+	}
+
+	runtime·lock(&finlock);
+	if(finq == nil || finq->cnt == finq->cap) {
+		if(finc == nil) {
+			finc = runtime·SysAlloc(PageSize);
+			finc->cap = (PageSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
+			finc->alllink = allfin;
+			allfin = finc;
+		}
+		block = finc;
+		finc = block->next;
+		block->next = finq;
+		finq = block;
+	}
+	f = &finq->fin[finq->cnt];
+	finq->cnt++;
+	f->fn = fn;
+	f->nret = nret;
+	f->arg = p;
+	runtime·unlock(&finlock); 
+	return true;
 }
 
-// Sweep frees or calls finalizers for blocks not marked in the mark phase.
+// Sweep frees or collects finalizers for blocks not marked in the mark phase.
 // It clears the mark bits in preparation for the next GC round.
 static void
 sweep(void)
@@ -434,9 +715,17 @@ sweep(void)
 	uintptr size;
 	byte *p;
 	MCache *c;
-	Finalizer *f;
+	byte *arena_start;
+
+	arena_start = runtime·mheap.arena_start;
+
+	for(;;) {
+		s = work.spans;
+		if(s == nil)
+			break;
+		if(!runtime·casp(&work.spans, s, s->allnext))
+			continue;
 
-	for(s = runtime·mheap.allspans; s != nil; s = s->allnext) {
 		if(s->state != MSpanInUse)
 			continue;
 
@@ -451,13 +740,15 @@ sweep(void)
 			npages = runtime·class_to_allocnpages[cl];
 			n = (npages << PageShift) / size;
 		}
-	
-		// sweep through n objects of given size starting at p.
+
+		// Sweep through n objects of given size starting at p.
+		// This thread owns the span now, so it can manipulate
+		// the block bitmap without atomic operations.
 		for(; n > 0; n--, p += size) {
 			uintptr off, *bitp, shift, bits;
 
-			off = (uintptr*)p - (uintptr*)runtime·mheap.arena_start;
-			bitp = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
+			off = (uintptr*)p - (uintptr*)arena_start;
+			bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
 			shift = off % wordsPerBitmapWord;
 			bits = *bitp>>shift;
 
@@ -465,20 +756,21 @@ sweep(void)
 				continue;
 
 			if((bits & bitMarked) != 0) {
+				if(DebugMark) {
+					if(!(bits & bitSpecial))
+						runtime·printf("found spurious mark on %p\n", p);
+					*bitp &= ~(bitSpecial<<shift);
+				}
 				*bitp &= ~(bitMarked<<shift);
 				continue;
 			}
 
-			if((bits & bitSpecial) != 0) {
-				// Special means it has a finalizer or is being profiled.
-				f = runtime·getfinalizer(p, 1);
-				if(f != nil) {
-					f->arg = p;
-					f->next = finq;
-					finq = f;
+			// Special means it has a finalizer or is being profiled.
+			// In DebugMark mode, the bit has been coopted so
+			// we have to assume all blocks are special.
+			if(DebugMark || (bits & bitSpecial) != 0) {
+				if(handlespecial(p, size))
 					continue;
-				}
-				runtime·MProf_Free(p, size);
 			}
 
 			// Mark freed; restore block boundary bit.
@@ -503,6 +795,23 @@ sweep(void)
 	}
 }
 
+void
+runtime·gchelper(void)
+{
+	// Wait until main proc is ready for mark help.
+	runtime·lock(&work.markgate);
+	runtime·unlock(&work.markgate);
+	scanblock(nil, 0);
+
+	// Wait until main proc is ready for sweep help.
+	runtime·lock(&work.sweepgate);
+	runtime·unlock(&work.sweepgate);
+	sweep();
+
+	if(runtime·xadd(&work.ndone, +1) == work.nproc-1)
+		runtime·notewakeup(&work.alldone);
+}
+
 // Semaphore, not Lock, so that the goroutine
 // reschedules when there is contention rather
 // than spinning.
@@ -523,7 +832,7 @@ static void
 stealcache(void)
 {
 	M *m;
-	
+
 	for(m=runtime·allm; m; m=m->alllink)
 		runtime·MCache_ReleaseAll(m->mcache);
 }
@@ -561,7 +870,7 @@ runtime·gc(int32 force)
 	int64 t0, t1, t2, t3;
 	uint64 heap0, heap1, obj0, obj1;
 	byte *p;
-	Finalizer *fp;
+	bool extra;
 
 	// The gc is turned off (via enablegc) until
 	// the bootstrap has completed.
@@ -582,7 +891,7 @@ runtime·gc(int32 force)
 			gcpercent = -1;
 		else
 			gcpercent = runtime·atoi(p);
-		
+
 		p = runtime·getenv("GOGCTRACE");
 		if(p != nil)
 			gctrace = runtime·atoi(p);
@@ -597,9 +906,7 @@ runtime·gc(int32 force)
 	}
 
 	t0 = runtime·nanotime();
-	nlookup = 0;
-	nsizelookup = 0;
-	naddrlookup = 0;
+	nhandoff = 0;
 
 	m->gcing = 1;
 	runtime·stoptheworld();
@@ -608,10 +915,31 @@ runtime·gc(int32 force)
 	heap0 = mstats.heap_alloc;
 	obj0 = mstats.nmalloc - mstats.nfree;
 
-	mark();
+	runtime·lock(&work.markgate);
+	runtime·lock(&work.sweepgate);
+
+	extra = false;
+	work.nproc = 1;
+	if(runtime·gomaxprocs > 1 && runtime·ncpu > 1) {
+		runtime·noteclear(&work.alldone);
+		work.nproc += runtime·helpgc(&extra);
+	}
+	work.nwait = 0;
+	work.ndone = 0;
+
+	runtime·unlock(&work.markgate);  // let the helpers in
+	mark(scanblock);
+	if(DebugMark)
+		mark(debug_scanblock);
 	t1 = runtime·nanotime();
+
+	work.spans = runtime·mheap.allspans;
+	runtime·unlock(&work.sweepgate);  // let the helpers in
 	sweep();
+	if(work.nproc > 1)
+		runtime·notesleep(&work.alldone);
 	t2 = runtime·nanotime();
+
 	stealcache();
 	cachestats();
 
@@ -619,8 +947,7 @@ runtime·gc(int32 force)
 	m->gcing = 0;
 
 	m->locks++;	// disable gc during the mallocs in newproc
-	fp = finq;
-	if(fp != nil) {
+	if(finq != nil) {
 		// kick off or wake up goroutine to run queued finalizers
 		if(fing == nil)
 			fing = runtime·newproc1((byte*)runfinq, nil, 0, 0, runtime·gc);
@@ -641,22 +968,30 @@ runtime·gc(int32 force)
 	mstats.numgc++;
 	if(mstats.debuggc)
 		runtime·printf("pause %D\n", t3-t0);
-	
+
 	if(gctrace) {
-		runtime·printf("gc%d: %D+%D+%D ms %D -> %D MB %D -> %D (%D-%D) objects %D pointer lookups (%D size, %D addr)\n",
-			mstats.numgc, (t1-t0)/1000000, (t2-t1)/1000000, (t3-t2)/1000000,
+		runtime·printf("gc%d(%d): %D+%D+%D ms %D -> %D MB %D -> %D (%D-%D) objects %D handoff\n",
+			mstats.numgc, work.nproc, (t1-t0)/1000000, (t2-t1)/1000000, (t3-t2)/1000000,
 			heap0>>20, heap1>>20, obj0, obj1,
 			mstats.nmalloc, mstats.nfree,
-			nlookup, nsizelookup, naddrlookup);
+			nhandoff);
 	}
 
 	runtime·semrelease(&gcsema);
-	runtime·starttheworld();
-	
-	// give the queued finalizers, if any, a chance to run
-	if(fp != nil)
+
+	// If we could have used another helper proc, start one now,
+	// in the hope that it will be available next time.
+	// It would have been even better to start it before the collection,
+	// but doing so requires allocating memory, so it's tricky to
+	// coordinate.  This lazy approach works out in practice:
+	// we don't mind if the first couple gc rounds don't have quite
+	// the maximum number of procs.
+	runtime·starttheworld(extra);
+
+	// give the queued finalizers, if any, a chance to run	
+	if(finq != nil)	
 		runtime·gosched();
-	
+
 	if(gctrace > 1 && !force)
 		runtime·gc(1);
 }
@@ -674,15 +1009,19 @@ runtime·UpdateMemStats(void)
 	cachestats();
 	m->gcing = 0;
 	runtime·semrelease(&gcsema);
-	runtime·starttheworld();
+	runtime·starttheworld(false);
 }
 
 static void
 runfinq(void)
 {
-	Finalizer *f, *next;
+	Finalizer *f;
+	FinBlock *fb, *next;
 	byte *frame;
+	uint32 framesz, framecap, i;
 
+	frame = nil;
+	framecap = 0;
 	for(;;) {
 		// There's no need for a lock in this section
 		// because it only conflicts with the garbage
@@ -690,25 +1029,34 @@ runfinq(void)
 		// runs when everyone else is stopped, and
 		// runfinq only stops at the gosched() or
 		// during the calls in the for loop.
-		f = finq;
+		fb = finq;
 		finq = nil;
-		if(f == nil) {
+		if(fb == nil) {
 			fingwait = 1;
 			g->status = Gwaiting;
 			g->waitreason = "finalizer wait";
 			runtime·gosched();
 			continue;
 		}
-		for(; f; f=next) {
-			next = f->next;
-			frame = runtime·mal(sizeof(uintptr) + f->nret);
-			*(void**)frame = f->arg;
-			reflect·call((byte*)f->fn, frame, sizeof(uintptr) + f->nret);
-			runtime·free(frame);
-			f->fn = nil;
-			f->arg = nil;
-			f->next = nil;
-			runtime·free(f);
+		for(; fb; fb=next) {
+			next = fb->next;
+			for(i=0; i<fb->cnt; i++) {
+				f = &fb->fin[i];
+				framesz = sizeof(uintptr) + f->nret;
+				if(framecap < framesz) {
+					runtime·free(frame);
+					frame = runtime·mal(framesz);
+					framecap = framesz;
+				}
+				*(void**)frame = f->arg;
+				runtime·setblockspecial(f->arg, false);
+				reflect·call((byte*)f->fn, frame, sizeof(uintptr) + f->nret);
+				f->fn = nil;
+				f->arg = nil;
+			}
+			fb->cnt = 0;
+			fb->next = finc;
+			finc = fb;
 		}
 		runtime·gc(1);	// trigger another gc to clean up the finalized objects, if possible
 	}
@@ -858,6 +1206,9 @@ runtime·blockspecial(void *v)
 {
 	uintptr *b, off, shift;
 
+	if(DebugMark)
+		return true;
+
 	off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;
 	b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
@@ -866,17 +1217,23 @@ runtime·blockspecial(void *v)
 }
 
 void
-runtime·setblockspecial(void *v)
+runtime·setblockspecial(void *v, bool s)
 {
 	uintptr *b, off, shift, bits, obits;
 
+	if(DebugMark)
+		return;
+
 	off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;
 	b = (uintptr*)runtime·mheap.arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
 
 	for(;;) {
 		obits = *b;
-		bits = obits | (bitSpecial<<shift);
+		if(s)
+			bits = obits | (bitSpecial<<shift);
+		else
+			bits = obits & ~(bitSpecial<<shift);
 		if(runtime·singleproc) {
 			*b = bits;
 			break;
@@ -887,7 +1244,7 @@ runtime·setblockspecial(void *v)
 		}
 	}
 }
- 
+
 void
 runtime·MHeap_MapBits(MHeap *h)
 {
@@ -898,7 +1255,7 @@ runtime·MHeap_MapBits(MHeap *h)
 		bitmapChunk = 8192
 	};
 	uintptr n;
-	
+
 	n = (h->arena_used - h->arena_start) / wordsPerBitmapWord;
 	n = (n+bitmapChunk-1) & ~(bitmapChunk-1);
 	if(h->bitmap_mapped >= n)
diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c
index 7d24a65..d75c18d 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -13,6 +13,7 @@
 // and heapmap(i) == span for all s->start <= i < s->start+s->npages.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 
 static MSpan *MHeap_AllocLocked(MHeap*, uintptr, int32);
diff --git a/src/pkg/runtime/mkasmh.sh b/src/pkg/runtime/mkasmh.sh
index 920e79a..26a1263 100755
--- a/src/pkg/runtime/mkasmh.sh
+++ b/src/pkg/runtime/mkasmh.sh
@@ -5,21 +5,44 @@
 
 set -e
 
+SYS=$1
+export GOOS=$(echo $SYS | sed 's/_.*//')
+export GOARCH=$(echo $SYS | sed 's/.*_//')
+shift
+
+case "$GOARCH" in
+386) CC=8c;;
+amd64) CC=6c;;
+arm) CC=5c;;
+esac
+export CC
+
+export CFLAGS="-Dos_$GOOS -Darch_$GOARCH"
+
+cp arch_$GOARCH.h arch_GOARCH.h
+cp defs_${GOOS}_$GOARCH.h defs_GOOS_GOARCH.h
+cp os_$GOOS.h os_GOOS.h
+cp signals_$GOOS.h signals_GOOS.h
+
 cat <<'EOF'
 // Assembly constants.
-// AUTOMATICALLY GENERATED BY mkasmh.sh DURING BUILD
+// AUTO-GENERATED by autogen.sh; DO NOT EDIT
 
 EOF
+if [ ! -x "${GOBIN:=$GOROOT/bin}/$CC" ]; then
+	echo "// dummy file for cmd/go to correctly generate buildscript"
+	exit
+fi
 
 case "$GOARCH" in
 386)
 	# The offsets 0 and 4 are also known to:
 	#	../../cmd/8l/pass.c:/D_GS
-	#	../../libcgo/linux_386.c:/^threadentry
-	#	../../libcgo/darwin_386.c:/^threadentry
+	#	cgo/gcc_linux_386.c:/^threadentry
+	#	cgo/gcc_darwin_386.c:/^threadentry
 	case "$GOOS" in
 	windows)
-		echo '#define	get_tls(r)	MOVL 0x2c(FS), r'
+		echo '#define	get_tls(r)	MOVL 0x14(FS), r'
 		echo '#define	g(r)	0(r)'
 		echo '#define	m(r)	4(r)'
 		;;
@@ -63,15 +86,15 @@ case "$GOARCH" in
 amd64)
 	case "$GOOS" in
 	windows)
-		echo '#define	get_tls(r) MOVQ 0x58(GS), r'
+		echo '#define	get_tls(r) MOVQ 0x28(GS), r'
 		echo '#define	g(r) 0(r)'
 		echo '#define	m(r) 8(r)'
 		;;
 	*)
 		# The offsets 0 and 8 are known to:
 		#	../../cmd/6l/pass.c:/D_GS
-		#	../../libcgo/linux_amd64.c:/^threadentry
-		#	../../libcgo/darwin_amd64.c:/^threadentry
+		#	cgo/gcc_linux_amd64.c:/^threadentry
+		#	cgo/gcc_darwin_amd64.c:/^threadentry
 		#
 		echo '#define	get_tls(r)'
 		echo '#define	g(r) 0(GS)'
@@ -91,6 +114,7 @@ arm)
 esac
 echo
 
+$GOBIN/$CC $CFLAGS -a proc.c |
 awk '
 { gsub(/\r/, ""); }
 /^aggr G$/ { aggr="g" }
@@ -109,5 +133,6 @@ aggr != "" && /^	/ {
 	offset=$(NF-1);
 	printf("#define %s_%s %s\n", aggr, name, offset);
 }
-' runtime.acid.$GOARCH
+'
 
+rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h
diff --git a/src/pkg/runtime/mkgodefs.sh b/src/pkg/runtime/mkgodefs.sh
index b6e9721..b7cd229 100755
--- a/src/pkg/runtime/mkgodefs.sh
+++ b/src/pkg/runtime/mkgodefs.sh
@@ -5,11 +5,36 @@
 
 set -e
 
+SYS=$1
+export GOOS=$(echo $SYS | sed 's/_.*//')
+export GOARCH=$(echo $SYS | sed 's/.*_//')
+shift
+
+case "$GOARCH" in
+386) CC=8c;;
+amd64) CC=6c;;
+arm) CC=5c;;
+esac
+export CC
+
+export CFLAGS="-DGOOS_$GOOS -DGOARCH_$GOARCH"
+
+cp arch_$GOARCH.h arch_GOARCH.h
+cp defs_${GOOS}_$GOARCH.h defs_GOOS_GOARCH.h
+cp os_$GOOS.h os_GOOS.h
+cp signals_$GOOS.h signals_GOOS.h
+
 cat <<EOF
 // Go definitions for C variables and types.
-// AUTOMATICALLY GENERATED BY THE FOLLOWING COMMAND. DO NOT EDIT.
-// CC="$CC" CFLAGS="$CFLAGS" ./mkgodefs.sh $@
+// AUTO-GENERATED by autogen.sh; DO NOT EDIT
+EOF
+if [ ! -x "${GOBIN:=$GOROOT/bin}/$CC" ]; then
+	echo "// dummy file for cmd/go to correctly generate buildscript"
+	echo "package runtime"
+	exit
+fi
 
+cat <<EOF
 package runtime
 import "unsafe"
 var _ unsafe.Pointer
@@ -17,7 +42,7 @@ var _ unsafe.Pointer
 EOF
 
 for i in "$@"; do
-	$CC $CFLAGS -q $i
+	$GOBIN/$CC $CFLAGS -q $i
 done | awk '
 /^func/ { next }
 /^const/ { next }
@@ -37,3 +62,5 @@ skip {
 
 {print}
 '
+
+rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h
diff --git a/src/pkg/runtime/mkversion.c b/src/pkg/runtime/mkversion.c
index 0d96aa3..94ad0d9 100644
--- a/src/pkg/runtime/mkversion.c
+++ b/src/pkg/runtime/mkversion.c
@@ -1,8 +1,14 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
 #include <u.h>
 #include <libc.h>
 
 char *template =
-	"// generated by mkversion.c; do not edit.\n"
+	"// AUTO-GENERATED by autogen.sh; DO NOT EDIT\n\n"
 	"package runtime\n"
 	"const defaultGoroot = `%s`\n"
 	"const theVersion = \"%s\"\n";
diff --git a/src/pkg/runtime/mprof.goc b/src/pkg/runtime/mprof.goc
index 517f96a..b297d41 100644
--- a/src/pkg/runtime/mprof.goc
+++ b/src/pkg/runtime/mprof.goc
@@ -7,8 +7,9 @@
 
 package runtime
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
-#include "defs.h"
+#include "defs_GOOS_GOARCH.h"
 #include "type.h"
 
 // NOTE(rsc): Everything here could use cas if contention became an issue.
diff --git a/src/pkg/runtime/msize.c b/src/pkg/runtime/msize.c
index 770ef38..e6cfcdb 100644
--- a/src/pkg/runtime/msize.c
+++ b/src/pkg/runtime/msize.c
@@ -26,6 +26,7 @@
 // TODO(rsc): Compute max waste for any given size.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 
 int32 runtime·class_to_size[NumSizeClasses];
diff --git a/src/pkg/runtime/openbsd/386/defs.h b/src/pkg/runtime/openbsd/386/defs.h
deleted file mode 100644
index d61462c..0000000
--- a/src/pkg/runtime/openbsd/386/defs.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// godefs -f -m32 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	void *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
-};
-
-typedef uint32 Sigset;
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_code;
-	int32 si_errno;
-	byte _data[116];
-};
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
-};
-
-typedef struct StackT StackT;
-struct StackT {
-	void *ss_sp;
-	uint32 ss_size;
-	int32 ss_flags;
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int32 tv_sec;
-	int32 tv_usec;
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-
-typedef void sfxsave64;
-
-typedef void usavefpu;
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	int32 sc_gs;
-	int32 sc_fs;
-	int32 sc_es;
-	int32 sc_ds;
-	int32 sc_edi;
-	int32 sc_esi;
-	int32 sc_ebp;
-	int32 sc_ebx;
-	int32 sc_edx;
-	int32 sc_ecx;
-	int32 sc_eax;
-	int32 sc_eip;
-	int32 sc_cs;
-	int32 sc_eflags;
-	int32 sc_esp;
-	int32 sc_ss;
-	int32 sc_onstack;
-	int32 sc_mask;
-	int32 sc_trapno;
-	int32 sc_err;
-	usavefpu *sc_fpstate;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/openbsd/386/signal.c b/src/pkg/runtime/openbsd/386/signal.c
deleted file mode 100644
index 8b0d4ac..0000000
--- a/src/pkg/runtime/openbsd/386/signal.c
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
-	union {
-		void    (*__sa_handler)(int32);
-		void    (*__sa_sigaction)(int32, Siginfo*, void *);
-	} __sigaction_u;		/* signal handler */
-	uint32	sa_mask;		/* signal mask to apply */
-	int32	sa_flags;		/* see signal options below */
-} Sigaction;
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
-	runtime·printf("eax     %x\n", r->sc_eax);
-	runtime·printf("ebx     %x\n", r->sc_ebx);
-	runtime·printf("ecx     %x\n", r->sc_ecx);
-	runtime·printf("edx     %x\n", r->sc_edx);
-	runtime·printf("edi     %x\n", r->sc_edi);
-	runtime·printf("esi     %x\n", r->sc_esi);
-	runtime·printf("ebp     %x\n", r->sc_ebp);
-	runtime·printf("esp     %x\n", r->sc_esp);
-	runtime·printf("eip     %x\n", r->sc_eip);
-	runtime·printf("eflags  %x\n", r->sc_eflags);
-	runtime·printf("cs      %x\n", r->sc_cs);
-	runtime·printf("fs      %x\n", r->sc_fs);
-	runtime·printf("gs      %x\n", r->sc_gs);
-}
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Sigcontext *r = context;
-	uintptr *sp;
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->sc_eip, (uint8*)r->sc_esp, nil, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = *(uintptr*)((byte*)info + 12); /* si_addr */
-		gp->sigpc = r->sc_eip;
-
-		// Only push runtime·sigpanic if r->sc_eip != 0.
-		// If r->sc_eip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->sc_eip != 0) {
-			sp = (uintptr*)r->sc_esp;
-			*--sp = r->sc_eip;
-			r->sc_esp = (uintptr)sp;
-		}
-		r->sc_eip = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG)
-		runtime·printf("Signal %d\n", sig);
-	else
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-
-	runtime·printf("PC=%X\n", r->sc_eip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->sc_eip, (void*)r->sc_esp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-}
-
-// Called from kernel on signal stack, so no stack split.
-#pragma textflag 7
-void
-runtime·sigignore(void)
-{
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	Sigaltstack st;
-
-	st.ss_sp = (int8*)p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	if (fn == runtime·sighandler)
-		fn = (void*)runtime·sigtramp;
-	sa.__sigaction_u.__sa_sigaction = (void*)fn;
-	runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
diff --git a/src/pkg/runtime/openbsd/386/sys.s b/src/pkg/runtime/openbsd/386/sys.s
deleted file mode 100644
index 3a78679..0000000
--- a/src/pkg/runtime/openbsd/386/sys.s
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// System calls and other sys.stuff for 386, OpenBSD
-// /usr/src/sys/kern/syscalls.master for syscall numbers.
-//
-
-#include "386/asm.h"
-
-// Exit the entire program (like C exit)
-TEXT runtime·exit(SB),7,$-4
-	MOVL	$1, AX
-	INT	$0x80
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·exit1(SB),7,$-4
-	MOVL	$302, AX		// sys_threxit
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·write(SB),7,$-4
-	MOVL	$4, AX			// sys_write
-	INT	$0x80
-	RET
-
-TEXT runtime·raisesigpipe(SB),7,$12
-	MOVL	$299, AX		// sys_getthrid
-	INT	$0x80
-	MOVL	$0, 0(SP)
-	MOVL	AX, 4(SP)		// arg 1 - pid
-	MOVL	$13, 8(SP)		// arg 2 - signum == SIGPIPE
-	MOVL	$37, AX			// sys_kill
-	INT	$0x80
-	RET
-
-TEXT runtime·notok(SB),7,$0
-	MOVL	$0xf1, 0xf1
-	RET
-
-TEXT runtime·mmap(SB),7,$36
-	LEAL	arg0+0(FP), SI
-	LEAL	4(SP), DI
-	CLD
-	MOVSL				// arg 1 - addr
-	MOVSL				// arg 2 - len
-	MOVSL				// arg 3 - prot
-	MOVSL				// arg 4 - flags
-	MOVSL				// arg 5 - fd
-	MOVL	$0, AX
-	STOSL				// arg 6 - pad
-	MOVSL				// arg 7 - offset
-	MOVL	$0, AX			// top 64 bits of file offset
-	STOSL
-	MOVL	$197, AX		// sys_mmap
-	INT	$0x80
-	JCC	2(PC)
-	NEGL	AX
-	RET
-
-TEXT runtime·munmap(SB),7,$-4
-	MOVL	$73, AX			// sys_munmap
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·setitimer(SB),7,$-4
-	MOVL	$83, AX
-	INT	$0x80
-	RET
-
-TEXT runtime·gettime(SB),7,$32
-	MOVL	$116, AX
-	LEAL	12(SP), BX
-	MOVL	BX, 4(SP)
-	MOVL	$0, 8(SP)
-	INT	$0x80
-
-	MOVL	12(SP), BX		// sec
-	MOVL	sec+0(FP), DI
-	MOVL	BX, (DI)
-	MOVL	$0, 4(DI)		// zero extend 32 -> 64 bits
-
-	MOVL	16(SP), BX		// usec
-	MOVL	usec+4(FP), DI
-	MOVL	BX, (DI)
-	RET
-
-TEXT runtime·sigaction(SB),7,$-4
-	MOVL	$46, AX			// sys_sigaction
-	INT	$0x80
-	JAE	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·sigtramp(SB),7,$44
-	get_tls(CX)
-
-	// save g
-	MOVL	g(CX), DI
-	MOVL	DI, 20(SP)
-	
-	// g = m->gsignal
-	MOVL	m(CX), BX
-	MOVL	m_gsignal(BX), BX
-	MOVL	BX, g(CX)
-
-	// copy arguments for call to sighandler
-	MOVL	signo+0(FP), BX
-	MOVL	BX, 0(SP)
-	MOVL	info+4(FP), BX
-	MOVL	BX, 4(SP)
-	MOVL	context+8(FP), BX
-	MOVL	BX, 8(SP)
-	MOVL	DI, 12(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(CX)
-	MOVL	20(SP), BX
-	MOVL	BX, g(CX)
-	
-	// call sigreturn
-	MOVL	context+8(FP), AX
-	MOVL	$0, 0(SP)		// syscall gap
-	MOVL	AX, 4(SP)		// arg 1 - sigcontext
-	MOVL	$103, AX		// sys_sigreturn
-	INT	$0x80
-	CALL	runtime·notok(SB)
-	RET
-
-// int32 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·rfork_thread(SB),7,$8
-	MOVL	flags+8(SP), AX
-	MOVL	stack+12(SP), CX
-
-	// Copy m, g, fn off parent stack for use by child.
-	SUBL	$16, CX
-	MOVL	mm+16(SP), SI
-	MOVL	SI, 0(CX)
-	MOVL	gg+20(SP), SI
-	MOVL	SI, 4(CX)
-	MOVL	fn+24(SP), SI
-	MOVL	SI, 8(CX)
-	MOVL	$1234, 12(CX)
-	MOVL	CX, SI
-
-	MOVL	$0, 0(SP)		// syscall gap
-	MOVL	AX, 4(SP)		// arg 1 - flags
-	MOVL	$251, AX		// sys_rfork
-	INT	$0x80
-
-	// Return if rfork syscall failed
-	JCC	4(PC)
-	NEGL	AX
-	MOVL	AX, 48(SP)
-	RET
-
-	// In parent, return.
-	CMPL	AX, $0
-	JEQ	3(PC)
-	MOVL	AX, 48(SP)
-	RET
-
-	// In child, on new stack.
-	MOVL    SI, SP
-
-	// Paranoia: check that SP is as we expect.
-	MOVL	12(SP), BP
-	CMPL	BP, $1234
-	JEQ	2(PC)
-	INT	$3
-
-	// Reload registers
-	MOVL	0(SP), BX		// m
-	MOVL	4(SP), DX		// g
-	MOVL	8(SP), SI		// fn
-
-	// Initialize m->procid to thread ID
-	MOVL	$299, AX		// sys_getthrid
-	INT	$0x80
-	MOVL	AX, m_procid(BX)
-
-	// Set FS to point at m->tls
-	LEAL	m_tls(BX), BP
-	PUSHAL				// save registers
-	PUSHL	BP
-	CALL	runtime·settls(SB)
-	POPL	AX
-	POPAL
-	
-	// Now segment is established.  Initialize m, g.
-	get_tls(AX)
-	MOVL	DX, g(AX)
-	MOVL	BX, m(AX)
-
-	CALL	runtime·stackcheck(SB)	// smashes AX, CX
-	MOVL	0(DX), DX		// paranoia; check they are not nil
-	MOVL	0(BX), BX
-
-	// more paranoia; check that stack splitting code works
-	PUSHAL
-	CALL	runtime·emptyfunc(SB)
-	POPAL
-
-	// Call fn
-	CALL	SI
-
-	CALL	runtime·exit1(SB)
-	MOVL	$0x1234, 0x1005
-	RET
-
-TEXT runtime·sigaltstack(SB),7,$-8
-	MOVL	$288, AX		// sys_sigaltstack
-	MOVL	new+4(SP), BX
-	MOVL	old+8(SP), CX
-	INT	$0x80
-	CMPL	AX, $0xfffff001
-	JLS	2(PC)
-	INT	$3
-	RET
-
-TEXT runtime·setldt(SB),7,$8
-	// Under OpenBSD we set the GS base instead of messing with the LDT.
-	MOVL	16(SP), AX		// tls0
-	MOVL	AX, 0(SP)
-	CALL	runtime·settls(SB)
-	RET
-
-TEXT runtime·settls(SB),7,$16
-	// adjust for ELF: wants to use -8(GS) and -4(GS) for g and m
-	MOVL	20(SP), CX
-	ADDL	$8, CX
-	MOVL	CX, 0(CX)
-	MOVL	$0, 0(SP)		// syscall gap
-	MOVL	$9, 4(SP)		// I386_SET_GSBASE (machine/sysarch.h)
-	MOVL	CX, 8(SP)		// pointer to base
-	MOVL	$165, AX		// sys_sysarch
-	INT	$0x80
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·osyield(SB),7,$-4
-	MOVL	$298, AX		// sys_sched_yield
-	INT	$0x80
-	RET
-
-GLOBL runtime·tlsoffset(SB),$4
diff --git a/src/pkg/runtime/openbsd/amd64/defs.h b/src/pkg/runtime/openbsd/amd64/defs.h
deleted file mode 100644
index 4eb5cd2..0000000
--- a/src/pkg/runtime/openbsd/amd64/defs.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// godefs -f -m64 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1000,
-	MAP_PRIVATE = 0x2,
-	MAP_FIXED = 0x10,
-	SA_SIGINFO = 0x40,
-	SA_RESTART = 0x2,
-	SA_ONSTACK = 0x1,
-	EINTR = 0x4,
-	SIGHUP = 0x1,
-	SIGINT = 0x2,
-	SIGQUIT = 0x3,
-	SIGILL = 0x4,
-	SIGTRAP = 0x5,
-	SIGABRT = 0x6,
-	SIGEMT = 0x7,
-	SIGFPE = 0x8,
-	SIGKILL = 0x9,
-	SIGBUS = 0xa,
-	SIGSEGV = 0xb,
-	SIGSYS = 0xc,
-	SIGPIPE = 0xd,
-	SIGALRM = 0xe,
-	SIGTERM = 0xf,
-	SIGURG = 0x10,
-	SIGSTOP = 0x11,
-	SIGTSTP = 0x12,
-	SIGCONT = 0x13,
-	SIGCHLD = 0x14,
-	SIGTTIN = 0x15,
-	SIGTTOU = 0x16,
-	SIGIO = 0x17,
-	SIGXCPU = 0x18,
-	SIGXFSZ = 0x19,
-	SIGVTALRM = 0x1a,
-	SIGPROF = 0x1b,
-	SIGWINCH = 0x1c,
-	SIGINFO = 0x1d,
-	SIGUSR1 = 0x1e,
-	SIGUSR2 = 0x1f,
-	FPE_INTDIV = 0x1,
-	FPE_INTOVF = 0x2,
-	FPE_FLTDIV = 0x3,
-	FPE_FLTOVF = 0x4,
-	FPE_FLTUND = 0x5,
-	FPE_FLTRES = 0x6,
-	FPE_FLTINV = 0x7,
-	FPE_FLTSUB = 0x8,
-	BUS_ADRALN = 0x1,
-	BUS_ADRERR = 0x2,
-	BUS_OBJERR = 0x3,
-	SEGV_MAPERR = 0x1,
-	SEGV_ACCERR = 0x2,
-	ITIMER_REAL = 0,
-	ITIMER_VIRTUAL = 0x1,
-	ITIMER_PROF = 0x2,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Sigaltstack Sigaltstack;
-struct Sigaltstack {
-	void *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
-};
-
-typedef uint32 Sigset;
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-	int32 si_signo;
-	int32 si_code;
-	int32 si_errno;
-	byte pad_godefs_0[4];
-	byte _data[120];
-};
-
-typedef union Sigval Sigval;
-union Sigval {
-	int32 sival_int;
-	void *sival_ptr;
-};
-
-typedef struct StackT StackT;
-struct StackT {
-	void *ss_sp;
-	uint64 ss_size;
-	int32 ss_flags;
-	byte pad_godefs_0[4];
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-	int64 tv_sec;
-	int64 tv_usec;
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-	Timeval it_interval;
-	Timeval it_value;
-};
-
-typedef void sfxsave64;
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-	int64 sc_rdi;
-	int64 sc_rsi;
-	int64 sc_rdx;
-	int64 sc_rcx;
-	int64 sc_r8;
-	int64 sc_r9;
-	int64 sc_r10;
-	int64 sc_r11;
-	int64 sc_r12;
-	int64 sc_r13;
-	int64 sc_r14;
-	int64 sc_r15;
-	int64 sc_rbp;
-	int64 sc_rbx;
-	int64 sc_rax;
-	int64 sc_gs;
-	int64 sc_fs;
-	int64 sc_es;
-	int64 sc_ds;
-	int64 sc_trapno;
-	int64 sc_err;
-	int64 sc_rip;
-	int64 sc_cs;
-	int64 sc_rflags;
-	int64 sc_rsp;
-	int64 sc_ss;
-	sfxsave64 *sc_fpstate;
-	int32 sc_onstack;
-	int32 sc_mask;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/openbsd/amd64/signal.c b/src/pkg/runtime/openbsd/amd64/signal.c
deleted file mode 100644
index 01bc76d..0000000
--- a/src/pkg/runtime/openbsd/amd64/signal.c
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "signals.h"
-#include "os.h"
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
-	union {
-		void    (*__sa_handler)(int32);
-		void    (*__sa_sigaction)(int32, Siginfo*, void *);
-	} __sigaction_u;		/* signal handler */
-	uint32	sa_mask;		/* signal mask to apply */
-	int32	sa_flags;		/* see signal options below */
-} Sigaction;
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
-	runtime·printf("rax     %X\n", r->sc_rax);
-	runtime·printf("rbx     %X\n", r->sc_rbx);
-	runtime·printf("rcx     %X\n", r->sc_rcx);
-	runtime·printf("rdx     %X\n", r->sc_rdx);
-	runtime·printf("rdi     %X\n", r->sc_rdi);
-	runtime·printf("rsi     %X\n", r->sc_rsi);
-	runtime·printf("rbp     %X\n", r->sc_rbp);
-	runtime·printf("rsp     %X\n", r->sc_rsp);
-	runtime·printf("r8      %X\n", r->sc_r8);
-	runtime·printf("r9      %X\n", r->sc_r9);
-	runtime·printf("r10     %X\n", r->sc_r10);
-	runtime·printf("r11     %X\n", r->sc_r11);
-	runtime·printf("r12     %X\n", r->sc_r12);
-	runtime·printf("r13     %X\n", r->sc_r13);
-	runtime·printf("r14     %X\n", r->sc_r14);
-	runtime·printf("r15     %X\n", r->sc_r15);
-	runtime·printf("rip     %X\n", r->sc_rip);
-	runtime·printf("rflags  %X\n", r->sc_rflags);
-	runtime·printf("cs      %X\n", r->sc_cs);
-	runtime·printf("fs      %X\n", r->sc_fs);
-	runtime·printf("gs      %X\n", r->sc_gs);
-}
-
-String
-runtime·signame(int32 sig)
-{
-	if(sig < 0 || sig >= NSIG)
-		return runtime·emptystring;
-	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
-	Sigcontext *r = context;
-	uintptr *sp;
-
-	if(sig == SIGPROF) {
-		runtime·sigprof((uint8*)r->sc_rip,
-			(uint8*)r->sc_rsp, nil, gp);
-		return;
-	}
-
-	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = sig;
-		gp->sigcode0 = info->si_code;
-		gp->sigcode1 = *(uintptr*)((byte*)info + 16); /* si_addr */
-		gp->sigpc = r->sc_rip;
-
-		// Only push runtime·sigpanic if r->mc_rip != 0.
-		// If r->mc_rip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->sc_rip != 0) {
-			sp = (uintptr*)r->sc_rsp;
-			*--sp = r->sc_rip;
-			r->sc_rsp = (uintptr)sp;
-		}
-		r->sc_rip = (uintptr)runtime·sigpanic;
-		return;
-	}
-
-	if(runtime·sigtab[sig].flags & SigQueue) {
-		if(runtime·sigsend(sig)
-		|| (runtime·sigtab[sig].flags & SigIgnore))
-			return;
-		runtime·exit(2);	// SIGINT, SIGTERM, etc
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	if(sig < 0 || sig >= NSIG)
-		runtime·printf("Signal %d\n", sig);
-	else
-		runtime·printf("%s\n", runtime·sigtab[sig].name);
-
-	runtime·printf("PC=%X\n", r->sc_rip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->sc_rip, (void*)r->sc_rsp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-}
-
-// Called from kernel on signal stack, so no stack split.
-#pragma textflag 7
-void
-runtime·sigignore(void)
-{
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-	Sigaltstack st;
-
-	st.ss_sp = (int8*)p;
-	st.ss_size = n;
-	st.ss_flags = 0;
-	runtime·sigaltstack(&st, nil);
-}
-
-static void
-sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
-	Sigaction sa;
-
-	runtime·memclr((byte*)&sa, sizeof sa);
-	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-	if(restart)
-		sa.sa_flags |= SA_RESTART;
-	sa.sa_mask = ~0ULL;
-	if (fn == runtime·sighandler)
-		fn = (void*)runtime·sigtramp;
-	sa.__sigaction_u.__sa_sigaction = (void*)fn;
-	runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·initsig(int32 queue)
-{
-	int32 i;
-	void *fn;
-
-	runtime·siginit();
-
-	for(i = 0; i<NSIG; i++) {
-		if(runtime·sigtab[i].flags) {
-			if((runtime·sigtab[i].flags & SigQueue) != queue)
-				continue;
-			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
-				fn = runtime·sighandler;
-			else
-				fn = runtime·sigignore;
-			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	Itimerval it;
-	
-	runtime·memclr((byte*)&it, sizeof it);
-	if(hz == 0) {
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-		sigaction(SIGPROF, SIG_IGN, true);
-	} else {
-		sigaction(SIGPROF, runtime·sighandler, true);
-		it.it_interval.tv_sec = 0;
-		it.it_interval.tv_usec = 1000000 / hz;
-		it.it_value = it.it_interval;
-		runtime·setitimer(ITIMER_PROF, &it, nil);
-	}
-	m->profilehz = hz;
-}
-
-void
-os·sigpipe(void)
-{
-	sigaction(SIGPIPE, SIG_DFL, false);
-	runtime·raisesigpipe();
-}
diff --git a/src/pkg/runtime/openbsd/amd64/sys.s b/src/pkg/runtime/openbsd/amd64/sys.s
deleted file mode 100644
index 38b3dbc..0000000
--- a/src/pkg/runtime/openbsd/amd64/sys.s
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// System calls and other sys.stuff for AMD64, OpenBSD
-// /usr/src/sys/kern/syscalls.master for syscall numbers.
-//
-
-#include "amd64/asm.h"
-
-// int64 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-TEXT runtime·rfork_thread(SB),7,$0
-	MOVL	flags+8(SP), DI
-	MOVQ	stack+16(SP), SI
-
-	// Copy m, g, fn off parent stack for use by child.
-	MOVQ	mm+24(SP), R8
-	MOVQ	gg+32(SP), R9
-	MOVQ	fn+40(SP), R12
-
-	MOVL	$251, AX		// sys_rfork
-	SYSCALL
-
-	// Return if rfork syscall failed
-	JCC	3(PC)
-	NEGL	AX
-	RET
-
-	// In parent, return.
-	CMPL	AX, $0
-	JEQ	2(PC)
-	RET
-
-	// In child, on new stack.
-	MOVQ	SI, SP
-
-	// Initialize m->procid to thread ID
-	MOVL	$299, AX		// sys_getthrid
-	SYSCALL
-	MOVQ	AX, m_procid(R8)
-
-	// Set FS to point at m->tls.
-	LEAQ	m_tls(R8), DI
-	CALL	runtime·settls(SB)
-
-	// In child, set up new stack
-	get_tls(CX)
-	MOVQ	R8, m(CX)
-	MOVQ	R9, g(CX)
-	CALL	runtime·stackcheck(SB)
-
-	// Call fn
-	CALL	R12
-
-	// It shouldn't return.  If it does, exit
-	MOVL	$302, AX		// sys_threxit
-	SYSCALL
-	JMP	-3(PC)			// keep exiting
-
-TEXT runtime·osyield(SB),7,$0
-	MOVL $298, AX			// sys_sched_yield
-	SYSCALL
-	RET
-
-TEXT runtime·sys_thrsleep(SB),7,$0
-	MOVQ 8(SP), DI
-	MOVL 16(SP), SI
-	MOVQ 24(SP), DX
-	MOVQ 32(SP), R10
-	MOVL $300, AX
-	SYSCALL
-	RET
-
-TEXT runtime·sys_thrwakeup(SB),7,$0
-	MOVQ 8(SP), DI
-	MOVL 16(SP), SI
-	MOVL $301, AX
-	SYSCALL
-	RET
-
-// Exit the entire program (like C exit)
-TEXT runtime·exit(SB),7,$-8
-	MOVL	8(SP), DI		// arg 1 - exit status
-	MOVL	$1, AX			// sys_exit
-	SYSCALL
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·exit1(SB),7,$-8
-	MOVL	$302, AX		// sys_threxit
-	SYSCALL
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·write(SB),7,$-8
-	MOVL	8(SP), DI		// arg 1 - fd
-	MOVQ	16(SP), SI		// arg 2 - buf
-	MOVL	24(SP), DX		// arg 3 - nbyte
-	MOVL	$4, AX			// sys_write
-	SYSCALL
-	RET
-
-TEXT runtime·raisesigpipe(SB),7,$16
-	MOVL	$299, AX		// sys_getthrid
-	SYSCALL
-	MOVQ	AX, DI			// arg 1 - pid
-	MOVQ	$13, SI			// arg 2 - signum == SIGPIPE
-	MOVL	$37, AX			// sys_kill
-	SYSCALL
-	RET
-
-TEXT runtime·setitimer(SB),7,$-8
-	MOVL	8(SP), DI		// arg 1 - which
-	MOVQ	16(SP), SI		// arg 2 - itv
-	MOVQ	24(SP), DX		// arg 3 - oitv
-	MOVL	$83, AX			// sys_setitimer
-	SYSCALL
-	RET
-
-TEXT runtime·gettime(SB),7,$32
-	LEAQ	8(SP), DI		// arg 1 - tp
-	MOVQ	$0, SI			// arg 2 - tzp
-	MOVL	$116, AX		// sys_gettimeofday
-	SYSCALL
-
-	MOVQ	8(SP), BX		// sec
-	MOVQ	sec+0(FP), DI
-	MOVQ	BX, (DI)
-
-	MOVL	16(SP), BX		// usec
-	MOVQ	usec+8(FP), DI
-	MOVL	BX, (DI)
-	RET
-
-TEXT runtime·sigaction(SB),7,$-8
-	MOVL	8(SP), DI		// arg 1 - signum
-	MOVQ	16(SP), SI		// arg 2 - nsa
-	MOVQ	24(SP), DX		// arg 3 - osa
-	MOVL	$46, AX
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·sigtramp(SB),7,$64
-	get_tls(BX)
-	
-	// save g
-	MOVQ	g(BX), R10
-	MOVQ	R10, 40(SP)
-	
-	// g = m->signal
-	MOVQ	m(BX), BP
-	MOVQ	m_gsignal(BP), BP
-	MOVQ	BP, g(BX)
-	
-	MOVQ	DI, 0(SP)
-	MOVQ	SI, 8(SP)
-	MOVQ	DX, 16(SP)
-	MOVQ	R10, 24(SP)
-	
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(BX)
-	MOVQ	40(SP), R10
-	MOVQ	R10, g(BX)
-	RET
-
-TEXT runtime·mmap(SB),7,$0
-	MOVQ	8(SP), DI		// arg 1 - addr
-	MOVQ	16(SP), SI		// arg 2 - len
-	MOVL	24(SP), DX		// arg 3 - prot
-	MOVL	28(SP), R10		// arg 4 - flags
-	MOVL	32(SP), R8		// arg 5 - fd
-	MOVQ	36(SP), R9
-	SUBQ	$16, SP
-	MOVQ	R9, 8(SP)		// arg 7 - offset (passed on stack)
-	MOVQ	$0, R9			// arg 6 - pad
-	MOVL	$197, AX
-	SYSCALL
-	JCC	2(PC)
-	NEGL	AX
-	ADDQ	$16, SP
-	RET
-
-TEXT runtime·munmap(SB),7,$0
-	MOVQ	8(SP), DI		// arg 1 - addr
-	MOVQ	16(SP), SI		// arg 2 - len
-	MOVL	$73, AX			// sys_munmap
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-TEXT runtime·notok(SB),7,$-8
-	MOVL	$0xf1, BP
-	MOVQ	BP, (BP)
-	RET
-
-TEXT runtime·sigaltstack(SB),7,$-8
-	MOVQ	new+8(SP), DI		// arg 1 - nss
-	MOVQ	old+16(SP), SI		// arg 2 - oss
-	MOVQ	$288, AX		// sys_sigaltstack
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
-
-// set tls base to DI
-TEXT runtime·settls(SB),7,$8
-	// adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
-	ADDQ	$16, DI
-	MOVQ	DI, 0(SP)
-	MOVQ	SP, SI
-	MOVQ	$12, DI			// AMD64_SET_FSBASE (machine/sysarch.h)
-	MOVQ	$165, AX		// sys_sysarch
-	SYSCALL
-	JCC	2(PC)
-	CALL	runtime·notok(SB)
-	RET
diff --git a/src/pkg/runtime/openbsd/defs.c b/src/pkg/runtime/openbsd/defs.c
deleted file mode 100644
index d0e0a19..0000000
--- a/src/pkg/runtime/openbsd/defs.c
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Input to godefs.
- *
-	godefs -f -m64 defs.c >amd64/defs.h
-	godefs -f -m32 defs.c >386/defs.h
- */
-
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/unistd.h>
-#include <sys/signal.h>
-#include <errno.h>
-#include <signal.h>
-
-enum {
-	$PROT_NONE = PROT_NONE,
-	$PROT_READ = PROT_READ,
-	$PROT_WRITE = PROT_WRITE,
-	$PROT_EXEC = PROT_EXEC,
-
-	$MAP_ANON = MAP_ANON,
-	$MAP_PRIVATE = MAP_PRIVATE,
-	$MAP_FIXED = MAP_FIXED,
-
-	$SA_SIGINFO = SA_SIGINFO,
-	$SA_RESTART = SA_RESTART,
-	$SA_ONSTACK = SA_ONSTACK,
-
-	$EINTR = EINTR,
-	
-	$SIGHUP = SIGHUP,
-	$SIGINT = SIGINT,
-	$SIGQUIT = SIGQUIT,
-	$SIGILL = SIGILL,
-	$SIGTRAP = SIGTRAP,
-	$SIGABRT = SIGABRT,
-	$SIGEMT = SIGEMT,
-	$SIGFPE = SIGFPE,
-	$SIGKILL = SIGKILL,
-	$SIGBUS = SIGBUS,
-	$SIGSEGV = SIGSEGV,
-	$SIGSYS = SIGSYS,
-	$SIGPIPE = SIGPIPE,
-	$SIGALRM = SIGALRM,
-	$SIGTERM = SIGTERM,
-	$SIGURG = SIGURG,
-	$SIGSTOP = SIGSTOP,
-	$SIGTSTP = SIGTSTP,
-	$SIGCONT = SIGCONT,
-	$SIGCHLD = SIGCHLD,
-	$SIGTTIN = SIGTTIN,
-	$SIGTTOU = SIGTTOU,
-	$SIGIO = SIGIO,
-	$SIGXCPU = SIGXCPU,
-	$SIGXFSZ = SIGXFSZ,
-	$SIGVTALRM = SIGVTALRM,
-	$SIGPROF = SIGPROF,
-	$SIGWINCH = SIGWINCH,
-	$SIGINFO = SIGINFO,
-	$SIGUSR1 = SIGUSR1,
-	$SIGUSR2 = SIGUSR2,
-	
-	$FPE_INTDIV = FPE_INTDIV,
-	$FPE_INTOVF = FPE_INTOVF,
-	$FPE_FLTDIV = FPE_FLTDIV,
-	$FPE_FLTOVF = FPE_FLTOVF,
-	$FPE_FLTUND = FPE_FLTUND,
-	$FPE_FLTRES = FPE_FLTRES,
-	$FPE_FLTINV = FPE_FLTINV,
-	$FPE_FLTSUB = FPE_FLTSUB,
-	
-	$BUS_ADRALN = BUS_ADRALN,
-	$BUS_ADRERR = BUS_ADRERR,
-	$BUS_OBJERR = BUS_OBJERR,
-	
-	$SEGV_MAPERR = SEGV_MAPERR,
-	$SEGV_ACCERR = SEGV_ACCERR,
-	
-	$ITIMER_REAL = ITIMER_REAL,
-	$ITIMER_VIRTUAL = ITIMER_VIRTUAL,
-	$ITIMER_PROF = ITIMER_PROF,
-};
-
-typedef struct sigaltstack $Sigaltstack;
-typedef sigset_t $Sigset;
-typedef siginfo_t $Siginfo;
-typedef union sigval $Sigval;
-
-typedef stack_t $StackT;
-
-typedef struct timeval $Timeval;
-typedef struct itimerval $Itimerval;
-
-// This is a hack to avoid pulling in machine/fpu.h.
-typedef void $sfxsave64;
-typedef void $usavefpu;
-
-typedef struct sigcontext $Sigcontext;
diff --git a/src/pkg/runtime/openbsd/mem.c b/src/pkg/runtime/openbsd/mem.c
deleted file mode 100644
index 46b6b07..0000000
--- a/src/pkg/runtime/openbsd/mem.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "malloc.h"
-
-enum
-{
-	ENOMEM = 12,
-};
-
-void*
-runtime·SysAlloc(uintptr n)
-{
-	void *v;
-
-	mstats.sys += n;
-	v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
-	if(v < (void*)4096)
-		return nil;
-	return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-	USED(v);
-	USED(n);
-	// TODO(rsc): call madvise MADV_DONTNEED
-}
-
-void
-runtime·SysFree(void *v, uintptr n)
-{
-	mstats.sys -= n;
-	runtime·munmap(v, n);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n)
-{
-	void *p;
-
-	// On 64-bit, people with ulimit -v set complain if we reserve too
-	// much address space.  Instead, assume that the reservation is okay
-	// and check the assumption in SysMap.
-	if(sizeof(void*) == 8)
-		return v;
-
-	p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-	if (p == ((void *)-ENOMEM))
-		return nil;
-	else
-		return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n)
-{
-	void *p;
-	
-	mstats.sys += n;
-
-	// On 64-bit, we don't actually have v reserved, so tread carefully.
-	if(sizeof(void*) == 8) {
-		p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
-		if(p == (void*)-ENOMEM)
-			runtime·throw("runtime: out of memory");
-		if(p != v) {
-			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-			runtime·throw("runtime: address space conflict");
-		}
-		return;
-	}
-
-	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
-	if(p == (void*)-ENOMEM)
-		runtime·throw("runtime: out of memory");
-	if(p != v)
-		runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/pkg/runtime/openbsd/os.h b/src/pkg/runtime/openbsd/os.h
deleted file mode 100644
index eba53b7..0000000
--- a/src/pkg/runtime/openbsd/os.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#define SIG_DFL ((void*)0)
-#define SIG_IGN ((void*)1)
-
-struct sigaction;
-
-void	runtime·sigpanic(void);
-void	runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
-void	runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void	runtime·setitimerval(int32, Itimerval*, Itimerval*);
-void	runtime·setitimer(int32, Itimerval*, Itimerval*);
-
-void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/openbsd/thread.c b/src/pkg/runtime/openbsd/thread.c
deleted file mode 100644
index 909db8c..0000000
--- a/src/pkg/runtime/openbsd/thread.c
+++ /dev/null
@@ -1,156 +0,0 @@
-// Use of this source file is governed by a BSD-style
-// license that can be found in the LICENSE file.`
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "stack.h"
-
-extern SigTab runtime·sigtab[];
-
-extern int64 runtime·rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
-
-enum
-{
-	ENOTSUP = 91,
-};
-
-// Basic spinlocks using CAS. We can improve on these later.
-static void
-lock(Lock *l)
-{
-	for(;;) {
-		if(runtime·cas(&l->key, 0, 1))
-			return;
-		runtime·osyield();
-	}
-}
-
-static void
-unlock(Lock *l)
-{
-	uint32 v;
-
-	for (;;) {
-		v = l->key;
-		if((v&1) == 0)
-			runtime·throw("unlock of unlocked lock");
-		if(runtime·cas(&l->key, v, 0))
-			break;
-	}
-}
-
-void
-runtime·lock(Lock *l)
-{
-	if(m->locks < 0)
-		runtime·throw("lock count");
-	m->locks++;
-	lock(l);
-}
-
-void 
-runtime·unlock(Lock *l)
-{
-	m->locks--;
-	if(m->locks < 0)
-		runtime·throw("lock count");
-	unlock(l);
-}
-
-// Event notifications.
-void
-runtime·noteclear(Note *n)
-{
-	n->lock.key = 0;
-	lock(&n->lock);
-}
-
-void
-runtime·notesleep(Note *n)
-{
-	lock(&n->lock);
-	unlock(&n->lock);
-}
-
-void
-runtime·notewakeup(Note *n)
-{
-	unlock(&n->lock);
-}
-
-// From OpenBSD's sys/param.h
-#define RFPROC		(1<<4)  /* change child (else changes curproc) */
-#define RFMEM		(1<<5)  /* share `address space' */
-#define RFNOWAIT	(1<<6)  /* parent need not wait() on child */
-#define RFTHREAD	(1<<13) /* create a thread, not a process */
-
-void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
-{
-	int32 flags;
-	int32 ret;
-
-	flags = RFPROC | RFTHREAD | RFMEM | RFNOWAIT;
-
-	if (0) {
-		runtime·printf(
-			"newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, m->id, m->tls[0], &m);
-	}
-
-	m->tls[0] = m->id;	// so 386 asm can find it
-
-	if((ret = runtime·rfork_thread(flags, stk, m, g, fn)) < 0) {
-		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
-		if (ret == -ENOTSUP)
-			runtime·printf("runtime: is kern.rthreads disabled?\n");
-		runtime·throw("runtime.newosproc");
-	}
-}
-
-void
-runtime·osinit(void)
-{
-}
-
-void
-runtime·goenvs(void)
-{
-	runtime·goenvs_unix();
-}
-
-// Called to initialize a new m (including the bootstrap m).
-void
-runtime·minit(void)
-{
-	// Initialize signal handling
-	m->gsignal = runtime·malg(32*1024);
-	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
-}
-
-void
-runtime·sigpanic(void)
-{
-	switch(g->sig) {
-	case SIGBUS:
-		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case SIGSEGV:
-		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case SIGFPE:
-		switch(g->sigcode0) {
-		case FPE_INTDIV:
-			runtime·panicstring("integer divide by zero");
-		case FPE_INTOVF:
-			runtime·panicstring("integer overflow");
-		}
-		runtime·panicstring("floating point error");
-	}
-	runtime·panicstring(runtime·sigtab[g->sig].name);
-}
diff --git a/src/pkg/runtime/os_darwin.h b/src/pkg/runtime/os_darwin.h
new file mode 100644
index 0000000..3e96071
--- /dev/null
+++ b/src/pkg/runtime/os_darwin.h
@@ -0,0 +1,32 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_DFL ((void*)0)
+#define SIG_IGN ((void*)1)
+
+int32	runtime·bsdthread_create(void*, M*, G*, void(*)(void));
+void	runtime·bsdthread_register(void);
+int32	runtime·mach_msg_trap(MachHeader*, int32, uint32, uint32, uint32, uint32, uint32);
+uint32	runtime·mach_reply_port(void);
+int32	runtime·mach_semacquire(uint32, int64);
+uint32	runtime·mach_semcreate(void);
+void	runtime·mach_semdestroy(uint32);
+void	runtime·mach_semrelease(uint32);
+void	runtime·mach_semreset(uint32);
+uint32	runtime·mach_task_self(void);
+uint32	runtime·mach_task_self(void);
+uint32	runtime·mach_thread_self(void);
+uint32	runtime·mach_thread_self(void);
+int32	runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+
+struct Sigaction;
+void	runtime·sigaction(uintptr, struct Sigaction*, struct Sigaction*);
+
+struct StackT;
+void	runtime·sigaltstack(struct StackT*, struct StackT*);
+void	runtime·sigtramp(void);
+void	runtime·sigpanic(void);
+void	runtime·setitimer(int32, Itimerval*, Itimerval*);
+
+void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/os_freebsd.h b/src/pkg/runtime/os_freebsd.h
new file mode 100644
index 0000000..8ef4c39
--- /dev/null
+++ b/src/pkg/runtime/os_freebsd.h
@@ -0,0 +1,13 @@
+#define SIG_DFL ((void*)0)
+#define SIG_IGN ((void*)1)
+
+int32	runtime·thr_new(ThrParam*, int32);
+void	runtime·sigpanic(void);
+void	runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+struct	sigaction;
+void	runtime·sigaction(int32, struct sigaction*, struct sigaction*);
+void	runtiem·setitimerval(int32, Itimerval*, Itimerval*);
+void	runtime·setitimer(int32, Itimerval*, Itimerval*);
+int32	runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+
+void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/linux/os.h b/src/pkg/runtime/os_linux.h
similarity index 100%
rename from src/pkg/runtime/linux/os.h
rename to src/pkg/runtime/os_linux.h
diff --git a/src/pkg/runtime/os_netbsd.h b/src/pkg/runtime/os_netbsd.h
new file mode 100644
index 0000000..cf35402
--- /dev/null
+++ b/src/pkg/runtime/os_netbsd.h
@@ -0,0 +1,17 @@
+// Copyright 2010 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.
+
+#define SIG_DFL ((void*)0)
+#define SIG_IGN ((void*)1)
+
+struct sigaction;
+
+void	runtime·sigpanic(void);
+void	runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+void	runtime·sigaction(int32, struct sigaction*, struct sigaction*);
+void	runtime·setitimerval(int32, Itimerval*, Itimerval*);
+void	runtime·setitimer(int32, Itimerval*, Itimerval*);
+int32	runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+
+void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/os_openbsd.h b/src/pkg/runtime/os_openbsd.h
new file mode 100644
index 0000000..cf35402
--- /dev/null
+++ b/src/pkg/runtime/os_openbsd.h
@@ -0,0 +1,17 @@
+// Copyright 2010 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.
+
+#define SIG_DFL ((void*)0)
+#define SIG_IGN ((void*)1)
+
+struct sigaction;
+
+void	runtime·sigpanic(void);
+void	runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+void	runtime·sigaction(int32, struct sigaction*, struct sigaction*);
+void	runtime·setitimerval(int32, Itimerval*, Itimerval*);
+void	runtime·setitimer(int32, Itimerval*, Itimerval*);
+int32	runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+
+void	runtime·raisesigpipe(void);
diff --git a/src/pkg/runtime/os_plan9.h b/src/pkg/runtime/os_plan9.h
new file mode 100644
index 0000000..b7b8383
--- /dev/null
+++ b/src/pkg/runtime/os_plan9.h
@@ -0,0 +1,68 @@
+// Copyright 2010 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.
+
+// Plan 9-specific system calls
+int32	runtime·open(uint8 *file, int32 mode);
+int32	runtime·pread(int32 fd, void *buf, int32 nbytes, int64 offset);
+int32	runtime·pwrite(int32 fd, void *buf, int32 nbytes, int64 offset);
+int32	runtime·read(int32 fd, void *buf, int32 nbytes);
+int32	runtime·close(int32 fd);
+void	runtime·exits(int8* msg);
+int32	runtime·brk_(void*);
+int32	runtime·sleep(int32 ms);
+int32	runtime·rfork(int32 flags, void *stk, M *m, G *g, void (*fn)(void));
+int32	runtime·plan9_semacquire(uint32 *addr, int32 block);
+int32 	runtime·plan9_semrelease(uint32 *addr, int32 count);
+
+/* open */
+enum
+{
+	OREAD	= 0,
+	OWRITE	= 1,
+	ORDWR	= 2,
+	OEXEC	= 3,
+	OTRUNC	= 16,
+	OCEXEC	= 32,
+	ORCLOSE	= 64,
+	OEXCL	= 0x1000
+};
+
+/* rfork */
+enum
+{
+	RFNAMEG         = (1<<0),
+	RFENVG          = (1<<1),
+	RFFDG           = (1<<2),
+	RFNOTEG         = (1<<3),
+	RFPROC          = (1<<4),
+	RFMEM           = (1<<5),
+	RFNOWAIT        = (1<<6),
+	RFCNAMEG        = (1<<10),
+	RFCENVG         = (1<<11),
+	RFCFDG          = (1<<12),
+	RFREND          = (1<<13),
+	RFNOMNT         = (1<<14)
+};
+
+typedef struct Tos Tos;
+typedef intptr Plink;
+
+struct Tos {
+	struct			/* Per process profiling */
+	{
+		Plink	*pp;	/* known to be 0(ptr) */
+		Plink	*next;	/* known to be 4(ptr) */
+		Plink	*last;
+		Plink	*first;
+		uint32	pid;
+		uint32	what;
+	} prof;
+	uint64	cyclefreq;	/* cycle clock frequency if there is one, 0 otherwise */
+	int64	kcycles;	/* cycles spent in kernel */
+	int64	pcycles;	/* cycles spent in process (kernel + user) */
+	uint32	pid;		/* might as well put the pid here */
+	uint32	clock;
+	/* top of stack is here */
+};
+
diff --git a/src/pkg/runtime/os_windows.h b/src/pkg/runtime/os_windows.h
new file mode 100644
index 0000000..2ad95d9
--- /dev/null
+++ b/src/pkg/runtime/os_windows.h
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+extern void *runtime·LoadLibrary;
+extern void *runtime·GetProcAddress;
+
+// Call a Windows function with stdcall conventions,
+// and switch to os stack during the call.
+#pragma	varargck	countpos	runtime·stdcall	2
+#pragma	varargck	type		runtime·stdcall	void*
+#pragma	varargck	type		runtime·stdcall	uintptr
+void runtime·asmstdcall(void *c);
+void *runtime·stdcall(void *fn, int32 count, ...);
+
+uint32 runtime·getlasterror(void);
+void runtime·setlasterror(uint32 err);
+
+// Function to be called by windows CreateThread
+// to start new os thread.
+uint32 runtime·tstart_stdcall(M *newm);
+
+uint32 runtime·issigpanic(uint32);
+void runtime·sigpanic(void);
+uint32 runtime·ctrlhandler(uint32 type);
+
+// Windows dll function to go callback entry.
+byte *runtime·compilecallback(Eface fn, bool cleanstack);
+void *runtime·callbackasm(void);
diff --git a/src/pkg/runtime/plan9/386/signal.c b/src/pkg/runtime/plan9/386/signal.c
deleted file mode 100644
index 364fd1c..0000000
--- a/src/pkg/runtime/plan9/386/signal.c
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file. 
-
-#include "runtime.h"
-
-void
-runtime·gettime(int64*, int32*) 
-{
-}
-
-String
-runtime·signame(int32)
-{
-	return runtime·emptystring;
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	// TODO: Enable profiling interrupts.
-	
-	m->profilehz = hz;
-}
diff --git a/src/pkg/runtime/plan9/386/sys.s b/src/pkg/runtime/plan9/386/sys.s
deleted file mode 100644
index 1cb570b..0000000
--- a/src/pkg/runtime/plan9/386/sys.s
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "defs.h"
-#include "386/asm.h"
-
-// setldt(int entry, int address, int limit)
-TEXT runtime·setldt(SB),7,$0
-	RET
-
-TEXT runtime·open(SB),7,$0
-	MOVL    $14, AX
-	INT     $64
-	RET
-
-TEXT runtime·write(SB),7,$0
-	MOVL    $20, AX
-	INT     $64
-	RET
-
-TEXT runtime·exits(SB),7,$0
-	MOVL    $8, AX
-	INT     $64
-	RET
-
-TEXT runtime·brk_(SB),7,$0
-	MOVL    $24, AX
-	INT     $64
-	RET
-
-TEXT runtime·plan9_semacquire(SB),7,$0
-	MOVL	$37, AX
-	INT	$64
-	RET
-	
-TEXT runtime·plan9_semrelease(SB),7,$0
-	MOVL	$38, AX
-	INT	$64
-	RET
-	
-TEXT runtime·rfork(SB),7,$0
-	MOVL    $19, AX // rfork
-	INT     $64
-
-	// In parent, return.
-	CMPL	AX, $0
-	JEQ	2(PC)
-	RET
-
-	// In child on old stack.
-	MOVL	mm+12(SP), BX	// m
-	MOVL	gg+16(SP), DX	// g
-	MOVL	fn+20(SP), SI	// fn
-
-	// set SP to be on the new child stack
-	MOVL	stack+8(SP), CX
-	MOVL	CX, SP
-
-	// Initialize m, g.
-	get_tls(AX)
-	MOVL	DX, g(AX)
-	MOVL	BX, m(AX)
-
-	// Initialize AX from _tos->pid
-	MOVL	_tos(SB), AX
-	MOVL	tos_pid(AX), AX
-	MOVL	AX, m_procid(BX)	// save pid as m->procid
-	
-	CALL	runtime·stackcheck(SB)	// smashes AX, CX
-	
-	MOVL	0(DX), DX	// paranoia; check they are not nil
-	MOVL	0(BX), BX
-	
-	// more paranoia; check that stack splitting code works
-	PUSHAL
-	CALL	runtime·emptyfunc(SB)
-	POPAL
-	
-	CALL	SI	// fn()
-	CALL	runtime·exit(SB)
-	RET
diff --git a/src/pkg/runtime/plan9/mem.c b/src/pkg/runtime/plan9/mem.c
deleted file mode 100644
index f795b2c..0000000
--- a/src/pkg/runtime/plan9/mem.c
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "malloc.h"
-#include "os.h"
-
-extern byte end[];
-static byte *bloc = { end };
-static Lock memlock;
-
-enum
-{
-	Round = 4095
-};
-
-void*
-runtime·SysAlloc(uintptr nbytes)
-{
-	uintptr bl;
-	
-	runtime·lock(&memlock);
-	mstats.sys += nbytes;
-	// Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
-	bl = ((uintptr)bloc + Round) & ~Round;
-	if(runtime·brk_((void*)(bl + nbytes)) < 0) {
-		runtime·unlock(&memlock);
-		return (void*)-1;
-	}
-	bloc = (byte*)bl + nbytes;
-	runtime·unlock(&memlock);
-	return (void*)bl;
-}
-
-void
-runtime·SysFree(void *v, uintptr nbytes)
-{
-	runtime·lock(&memlock);
-	mstats.sys -= nbytes;
-	// from tiny/mem.c
-	// Push pointer back if this is a free
-	// of the most recent SysAlloc.
-	nbytes += (nbytes + Round) & ~Round;
-	if(bloc == (byte*)v+nbytes)
-		bloc -= nbytes;	
-	runtime·unlock(&memlock);
-}
-
-void
-runtime·SysUnused(void *v, uintptr nbytes)
-{
-	USED(v, nbytes);
-}
-
-void
-runtime·SysMap(void *v, uintptr nbytes)
-{
-	USED(v, nbytes);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr nbytes)
-{
-	USED(v);
-	return runtime·SysAlloc(nbytes);
-}
diff --git a/src/pkg/runtime/plan9/os.h b/src/pkg/runtime/plan9/os.h
deleted file mode 100644
index b2f7357..0000000
--- a/src/pkg/runtime/plan9/os.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2010 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.
-
-extern int32 runtime·write(int32 fd, void* buffer, int32 nbytes);
-extern void runtime·exits(int8* msg);
-extern int32 runtime·brk_(void*);
-
-/* open */
-enum
-{
-	OREAD			= 0,
-	OWRITE			= 1,
-	ORDWR			= 2
-};
-
-/* rfork */
-enum
-{
-	RFNAMEG         = (1<<0),
-	RFENVG          = (1<<1),
-	RFFDG           = (1<<2),
-	RFNOTEG         = (1<<3),
-	RFPROC          = (1<<4),
-	RFMEM           = (1<<5),
-	RFNOWAIT        = (1<<6),
-	RFCNAMEG        = (1<<10),
-	RFCENVG         = (1<<11),
-	RFCFDG          = (1<<12),
-	RFREND          = (1<<13),
-	RFNOMNT         = (1<<14)
-};
-
-typedef struct Tos Tos;
-typedef intptr Plink;
-
-struct Tos {
-	struct			/* Per process profiling */
-	{
-		Plink	*pp;	/* known to be 0(ptr) */
-		Plink	*next;	/* known to be 4(ptr) */
-		Plink	*last;
-		Plink	*first;
-		uint32	pid;
-		uint32	what;
-	} prof;
-	uint64	cyclefreq;	/* cycle clock frequency if there is one, 0 otherwise */
-	int64	kcycles;	/* cycles spent in kernel */
-	int64	pcycles;	/* cycles spent in process (kernel + user) */
-	uint32	pid;		/* might as well put the pid here */
-	uint32	clock;
-	/* top of stack is here */
-};
-
-extern int32 runtime·rfork(int32 flags, void *stk, M *m, G *g, void (*fn)(void));
-extern int32 runtime·plan9_semacquire(uint32 *addr, int32 block);
-extern int32 runtime·plan9_semrelease(uint32 *addr, int32 count);
diff --git a/src/pkg/runtime/plan9/thread.c b/src/pkg/runtime/plan9/thread.c
deleted file mode 100644
index 7769892..0000000
--- a/src/pkg/runtime/plan9/thread.c
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "os.h"
-
-int8 *goos = "plan9";
-
-void
-runtime·minit(void)
-{
-}
-
-void
-runtime·osinit(void)
-{
-}
-
-void
-runtime·goenvs(void)
-{
-}
-
-void
-runtime·initsig(int32 queue)
-{
-}
-
-extern Tos *_tos;
-void
-runtime·exit(int32)
-{
-	int32 fd;
-	uint8 buf[128];
-	uint8 tmp[16];
-	uint8 *p, *q;
-	int32 pid;
-	
-	runtime·memclr(buf, sizeof buf);
-	runtime·memclr(tmp, sizeof tmp);
-	pid = _tos->pid;
-
-	/* build path string /proc/pid/notepg */
-	for(q=tmp; pid > 0;) {
-		*q++ = '0' + (pid%10);
-		pid = pid/10;
-	}
-	p = buf;
-	runtime·memmove((void*)p, (void*)"/proc/", 6);
-	p += 6;
-	for(q--; q >= tmp;)
-		*p++ = *q--;
-	runtime·memmove((void*)p, (void*)"/notepg", 7);
-	
-	/* post interrupt note */
-	fd = runtime·open(buf, OWRITE);
-	runtime·write(fd, "interrupt", 9);
-	runtime·exits(nil);
-}
-
-void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
-{
-	m->tls[0] = m->id;	// so 386 asm can find it
-	if(0){
-		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=%p\n",
-			stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m);
-	}        
-	
-	if (runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0 )
-		runtime·throw("newosproc: rfork failed");
-}
-
-// Blocking locks.
-
-// Implement Locks, using semaphores.
-// l->key is the number of threads who want the lock.
-// In a race, one thread increments l->key from 0 to 1
-// and the others increment it from >0 to >1.  The thread
-// who does the 0->1 increment gets the lock, and the
-// others wait on the semaphore.  When the 0->1 thread
-// releases the lock by decrementing l->key, l->key will
-// be >0, so it will increment the semaphore to wake up
-// one of the others.  This is the same algorithm used
-// in Plan 9's user-level locks.
-
-void
-runtime·lock(Lock *l)
-{
-	if(m->locks < 0)
-		runtime·throw("lock count");
-	m->locks++;
-	
-	if(runtime·xadd(&l->key, 1) == 1)
-		return; // changed from 0 -> 1; we hold lock
-	// otherwise wait in kernel
-	while(runtime·plan9_semacquire(&l->sema, 1) < 0) {
-		/* interrupted; try again */
-	}
-}
-
-void
-runtime·unlock(Lock *l)
-{
-	m->locks--;
-	if(m->locks < 0)
-		runtime·throw("lock count");
-
-	if(runtime·xadd(&l->key, -1) == 0)
-		return; // changed from 1 -> 0: no contention
-	
-	runtime·plan9_semrelease(&l->sema, 1);
-}
-
-
-// User-level semaphore implementation:
-// try to do the operations in user space on u,
-// but when it's time to block, fall back on the kernel semaphore k.
-// This is the same algorithm used in Plan 9.
-void
-runtime·usemacquire(Usema *s)
-{
-	if((int32)runtime·xadd(&s->u, -1) < 0)
-		while(runtime·plan9_semacquire(&s->k, 1) < 0) {
-			/* interrupted; try again */
-		}
-}
-
-void
-runtime·usemrelease(Usema *s)
-{
-	if((int32)runtime·xadd(&s->u, 1) <= 0)
-		runtime·plan9_semrelease(&s->k, 1);
-}
-
-
-// Event notifications.
-void
-runtime·noteclear(Note *n)
-{
-	n->wakeup = 0;
-}
-
-void
-runtime·notesleep(Note *n)
-{
-	while(!n->wakeup)
-		runtime·usemacquire(&n->sema);
-}
-
-void
-runtime·notewakeup(Note *n)
-{
-	n->wakeup = 1;
-	runtime·usemrelease(&n->sema);
-}
-
-void
-os·sigpipe(void)
-{
-	runtime·throw("too many writes on closed pipe");
-}
-
-/*
- * placeholder - once notes are implemented,
- * a signal generating a panic must appear as
- * a call to this function for correct handling by
- * traceback.
- */
-void
-runtime·sigpanic(void)
-{
-}
diff --git a/src/pkg/runtime/pprof/pprof.go b/src/pkg/runtime/pprof/pprof.go
index fdeceb4..d14bb14 100644
--- a/src/pkg/runtime/pprof/pprof.go
+++ b/src/pkg/runtime/pprof/pprof.go
@@ -12,15 +12,17 @@ import (
 	"bufio"
 	"fmt"
 	"io"
-	"os"
 	"runtime"
 	"sync"
 )
 
+// BUG(rsc): CPU profiling is broken on OS X, due to an Apple kernel bug.
+// For details, see http://code.google.com/p/go/source/detail?r=35b716c94225.
+
 // WriteHeapProfile writes a pprof-formatted heap profile to w.
 // If a write to w returns an error, WriteHeapProfile returns that error.
 // Otherwise, WriteHeapProfile returns nil.
-func WriteHeapProfile(w io.Writer) os.Error {
+func WriteHeapProfile(w io.Writer) error {
 	// Find out how many records there are (MemProfile(nil, false)),
 	// allocate that many records, and get the data.
 	// There's a race—more records might be added between
@@ -116,7 +118,7 @@ var cpu struct {
 // StartCPUProfile enables CPU profiling for the current process.
 // While profiling, the profile will be buffered and written to w.
 // StartCPUProfile returns an error if profiling is already enabled.
-func StartCPUProfile(w io.Writer) os.Error {
+func StartCPUProfile(w io.Writer) error {
 	// The runtime routines allow a variable profiling rate,
 	// but in practice operating systems cannot trigger signals
 	// at more than about 500 Hz, and our processing of the
diff --git a/src/pkg/runtime/print.c b/src/pkg/runtime/print.c
index 3ce7794..0d8caaf 100644
--- a/src/pkg/runtime/print.c
+++ b/src/pkg/runtime/print.c
@@ -51,7 +51,7 @@ vprintf(int8 *s, byte *base)
 	uintptr arg, narg;
 	byte *v;
 
-//	lock(&debuglock);
+	//runtime·lock(&debuglock);
 
 	lp = p = s;
 	arg = 0;
@@ -152,7 +152,7 @@ vprintf(int8 *s, byte *base)
 	if(p > lp)
 		runtime·write(2, lp, p-lp);
 
-//	unlock(&debuglock);
+	//runtime·unlock(&debuglock);
 }
 
 #pragma textflag 7
@@ -348,4 +348,4 @@ runtime·typestring(Eface e, String s)
 	s = *e.type->string;
 	FLUSH(&s);
 }
-	
+
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index cc07574..cb45a0c 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -3,18 +3,16 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
-#include "arch.h"
-#include "defs.h"
+#include "arch_GOARCH.h"
+#include "defs_GOOS_GOARCH.h"
 #include "malloc.h"
-#include "os.h"
+#include "os_GOOS.h"
 #include "stack.h"
 
 bool	runtime·iscgo;
 
 static void unwindstack(G*, byte*);
 static void schedule(G*);
-static void acquireproc(void);
-static void releaseproc(void);
 
 typedef struct Sched Sched;
 
@@ -70,9 +68,11 @@ struct Sched {
 
 	volatile uint32 atomic;	// atomic scheduling word (see below)
 
-	int32 predawn;		// running initialization, don't run new g's.
 	int32 profilehz;	// cpu profiling rate
 
+	bool init;  // running initialization
+	bool lockmain;  // init called runtime.LockOSThread
+
 	Note	stopped;	// one g can set waitstop and wait here for m's to stop
 };
 
@@ -128,6 +128,8 @@ Sched runtime·sched;
 int32 runtime·gomaxprocs;
 bool runtime·singleproc;
 
+static bool canaddmcpu(void);
+
 // An m that is waiting for notewakeup(&m->havenextg).  This may
 // only be accessed while the scheduler lock is held.  This is used to
 // minimize the number of times we call notewakeup while the scheduler
@@ -169,11 +171,7 @@ setmcpumax(uint32 n)
 //	make & queue new G
 //	call runtime·mstart
 //
-// The new G does:
-//
-//	call main·init_function
-//	call initdone
-//	call main·main
+// The new G calls runtime·main.
 void
 runtime·schedinit(void)
 {
@@ -201,11 +199,41 @@ runtime·schedinit(void)
 	}
 	setmcpumax(runtime·gomaxprocs);
 	runtime·singleproc = runtime·gomaxprocs == 1;
-	runtime·sched.predawn = 1;
 
+	canaddmcpu();	// mcpu++ to account for bootstrap m
+	m->helpgc = 1;	// flag to tell schedule() to mcpu--
+	runtime·sched.grunning++;
+
+	mstats.enablegc = 1;
 	m->nomemprof--;
 }
 
+extern void main·init(void);
+extern void main·main(void);
+
+// The main goroutine.
+void
+runtime·main(void)
+{
+	// Lock the main goroutine onto this, the main OS thread,
+	// during initialization.  Most programs won't care, but a few
+	// do require certain calls to be made by the main thread.
+	// Those can arrange for main.main to run in the main thread
+	// by calling runtime.LockOSThread during initialization
+	// to preserve the lock.
+	runtime·LockOSThread();
+	runtime·sched.init = true;
+	main·init();
+	runtime·sched.init = false;
+	if(!runtime·sched.lockmain)
+		runtime·UnlockOSThread();
+
+	main·main();
+	runtime·exit(0);
+	for(;;)
+		*(int32*)runtime·main = 0;
+}
+
 // Lock the scheduler.
 static void
 schedlock(void)
@@ -226,22 +254,6 @@ schedunlock(void)
 		runtime·notewakeup(&m->havenextg);
 }
 
-// Called after main·init_function; main·main will be called on return.
-void
-runtime·initdone(void)
-{
-	// Let's go.
-	runtime·sched.predawn = 0;
-	mstats.enablegc = 1;
-
-	// If main·init_function started other goroutines,
-	// kick off new m's to handle them, like ready
-	// would have, had it not been pre-dawn.
-	schedlock();
-	matchmg();
-	schedunlock();
-}
-
 void
 runtime·goexit(void)
 {
@@ -323,6 +335,9 @@ mcommoninit(M *m)
 	m->fastrand = 0x49f6428aUL + m->id;
 	m->stackalloc = runtime·malloc(sizeof(*m->stackalloc));
 	runtime·FixAlloc_Init(m->stackalloc, FixedStack, runtime·SysAlloc, nil, nil);
+
+	if(m->mcache == nil)
+		m->mcache = runtime·allocmcache();
 }
 
 // Try to increment mcpu.  Report whether succeeded.
@@ -422,7 +437,7 @@ mget(G *g)
 	M *m;
 
 	// if g has its own m, use it.
-	if((m = g->lockedm) != nil)
+	if(g && (m = g->lockedm) != nil)
 		return m;
 
 	// otherwise use general m pool.
@@ -463,8 +478,7 @@ readylocked(G *g)
 	g->status = Grunnable;
 
 	gput(g);
-	if(!runtime·sched.predawn)
-		matchmg();
+	matchmg();
 }
 
 static void
@@ -507,6 +521,7 @@ nextgandunlock(void)
 	G *gp;
 	uint32 v;
 
+top:
 	if(atomic_mcpu(runtime·sched.atomic) >= maxgomaxprocs)
 		runtime·throw("negative mcpu");
 
@@ -584,12 +599,50 @@ nextgandunlock(void)
 	schedunlock();
 
 	runtime·notesleep(&m->havenextg);
+	if(m->helpgc) {
+		runtime·gchelper();
+		m->helpgc = 0;
+		runtime·lock(&runtime·sched);
+		goto top;
+	}
 	if((gp = m->nextg) == nil)
 		runtime·throw("bad m->nextg in nextgoroutine");
 	m->nextg = nil;
 	return gp;
 }
 
+int32
+runtime·helpgc(bool *extra)
+{
+	M *mp;
+	int32 n, max;
+
+	// Figure out how many CPUs to use.
+	// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
+	max = runtime·gomaxprocs;
+	if(max > runtime·ncpu)
+		max = runtime·ncpu;
+	if(max > MaxGcproc)
+		max = MaxGcproc;
+
+	// We're going to use one CPU no matter what.
+	// Figure out the max number of additional CPUs.
+	max--;
+
+	runtime·lock(&runtime·sched);
+	n = 0;
+	while(n < max && (mp = mget(nil)) != nil) {
+		n++;
+		mp->helpgc = 1;
+		mp->waitnextg = 0;
+		runtime·notewakeup(&mp->havenextg);
+	}
+	runtime·unlock(&runtime·sched);
+	if(extra)
+		*extra = n != max;
+	return n;
+}
+
 void
 runtime·stoptheworld(void)
 {
@@ -626,15 +679,29 @@ runtime·stoptheworld(void)
 	schedunlock();
 }
 
-// TODO(rsc): Remove. This is only temporary,
-// for the mark and sweep collector.
 void
-runtime·starttheworld(void)
+runtime·starttheworld(bool extra)
 {
+	M *m;
+
 	schedlock();
 	runtime·gcwaiting = 0;
 	setmcpumax(runtime·gomaxprocs);
 	matchmg();
+	if(extra && canaddmcpu()) {
+		// Start a new m that will (we hope) be idle
+		// and so available to help when the next
+		// garbage collection happens.
+		// canaddmcpu above did mcpu++
+		// (necessary, because m will be doing various
+		// initialization work so is definitely running),
+		// but m is not running a specific goroutine,
+		// so set the helpgc flag as a signal to m's
+		// first schedule(nil) to mcpu-- and grunning--.
+		m = runtime·newm();
+		m->helpgc = 1;
+		runtime·sched.grunning++;
+	}
 	schedunlock();
 }
 
@@ -644,8 +711,6 @@ runtime·mstart(void)
 {
 	if(g != m->g0)
 		runtime·throw("bad runtime·mstart");
-	if(m->mcache == nil)
-		m->mcache = runtime·allocmcache();
 
 	// Record top of stack for use by mcall.
 	// Once we call schedule we're never coming back,
@@ -671,50 +736,58 @@ struct CgoThreadStart
 };
 
 // Kick off new m's as needed (up to mcpumax).
-// There are already `other' other cpus that will
-// start looking for goroutines shortly.
 // Sched is locked.
 static void
 matchmg(void)
 {
-	G *g;
+	G *gp;
+	M *mp;
 
 	if(m->mallocing || m->gcing)
 		return;
 
 	while(haveg() && canaddmcpu()) {
-		g = gget();
-		if(g == nil)
+		gp = gget();
+		if(gp == nil)
 			runtime·throw("gget inconsistency");
 
-		// Find the m that will run g.
-		M *m;
-		if((m = mget(g)) == nil){
-			m = runtime·malloc(sizeof(M));
-			mcommoninit(m);
-
-			if(runtime·iscgo) {
-				CgoThreadStart ts;
-
-				if(libcgo_thread_start == nil)
-					runtime·throw("libcgo_thread_start missing");
-				// pthread_create will make us a stack.
-				m->g0 = runtime·malg(-1);
-				ts.m = m;
-				ts.g = m->g0;
-				ts.fn = runtime·mstart;
-				runtime·asmcgocall(libcgo_thread_start, &ts);
-			} else {
-				if(Windows)
-					// windows will layout sched stack on os stack
-					m->g0 = runtime·malg(-1);
-				else
-					m->g0 = runtime·malg(8192);
-				runtime·newosproc(m, m->g0, m->g0->stackbase, runtime·mstart);
-			}
-		}
-		mnextg(m, g);
+		// Find the m that will run gp.
+		if((mp = mget(gp)) == nil)
+			mp = runtime·newm();
+		mnextg(mp, gp);
+	}
+}
+
+// Create a new m.  It will start off with a call to runtime·mstart.
+M*
+runtime·newm(void)
+{
+	M *m;
+
+	m = runtime·malloc(sizeof(M));
+	mcommoninit(m);
+
+	if(runtime·iscgo) {
+		CgoThreadStart ts;
+
+		if(libcgo_thread_start == nil)
+			runtime·throw("libcgo_thread_start missing");
+		// pthread_create will make us a stack.
+		m->g0 = runtime·malg(-1);
+		ts.m = m;
+		ts.g = m->g0;
+		ts.fn = runtime·mstart;
+		runtime·asmcgocall(libcgo_thread_start, &ts);
+	} else {
+		if(Windows)
+			// windows will layout sched stack on os stack
+			m->g0 = runtime·malg(-1);
+		else
+			m->g0 = runtime·malg(8192);
+		runtime·newosproc(m, m->g0, m->g0->stackbase, runtime·mstart);
 	}
+
+	return m;
 }
 
 // One round of scheduler: find a goroutine and run it.
@@ -729,9 +802,6 @@ schedule(G *gp)
 
 	schedlock();
 	if(gp != nil) {
-		if(runtime·sched.predawn)
-			runtime·throw("init rescheduling");
-
 		// Just finished running gp.
 		gp->m = nil;
 		runtime·sched.grunning--;
@@ -767,6 +837,19 @@ schedule(G *gp)
 			gp->readyonstop = 0;
 			readylocked(gp);
 		}
+	} else if(m->helpgc) {
+		// Bootstrap m or new m started by starttheworld.
+		// atomic { mcpu-- }
+		v = runtime·xadd(&runtime·sched.atomic, -1<<mcpuShift);
+		if(atomic_mcpu(v) > maxgomaxprocs)
+			runtime·throw("negative mcpu in scheduler");
+		// Compensate for increment in starttheworld().
+		runtime·sched.grunning--;
+		m->helpgc = 0;
+	} else if(m->nextg != nil) {
+		// New m started by matchmg.
+	} else {
+		runtime·throw("invalid m state in scheduler");
 	}
 
 	// Find (or wait for) g to run.  Unlocks runtime·sched.
@@ -821,9 +904,6 @@ runtime·entersyscall(void)
 {
 	uint32 v;
 
-	if(runtime·sched.predawn)
-		return;
-
 	// Leave SP around for gc and traceback.
 	runtime·gosave(&g->sched);
 	g->gcsp = g->sched.sp;
@@ -875,9 +955,6 @@ runtime·exitsyscall(void)
 {
 	uint32 v;
 
-	if(runtime·sched.predawn)
-		return;
-
 	// Fast path.
 	// If we can do the mcpu++ bookkeeping and
 	// find that we still have mcpu <= mcpumax, then we can
@@ -914,6 +991,9 @@ runtime·exitsyscall(void)
 	g->gcstack = nil;
 }
 
+// Called from runtime·lessstack when returning from a function which
+// allocated a new stack segment.  The function's return value is in
+// m->cret.
 void
 runtime·oldstack(void)
 {
@@ -945,6 +1025,11 @@ runtime·oldstack(void)
 	runtime·gogo(&old.gobuf, m->cret);
 }
 
+// Called from reflect·call or from runtime·morestack when a new
+// stack segment is needed.  Allocate a new stack big enough for
+// m->moreframesize bytes, copy m->moreargsize bytes to the new frame,
+// and then act as though runtime·lessstack called the function at
+// m->morepc.
 void
 runtime·newstack(void)
 {
@@ -1032,6 +1117,10 @@ runtime·newstack(void)
 	*(int32*)345 = 123;	// never return
 }
 
+// Hook used by runtime·malg to call runtime·stackalloc on the
+// scheduler stack.  This exists because runtime·stackalloc insists
+// on being called on the scheduler stack, to avoid trying to grow
+// the stack while allocating a new stack segment.
 static void
 mstackalloc(G *gp)
 {
@@ -1039,6 +1128,7 @@ mstackalloc(G *gp)
 	runtime·gogo(&gp->sched, 0);
 }
 
+// Allocate a new g, with a stack big enough for stacksize bytes.
 G*
 runtime·malg(int32 stacksize)
 {
@@ -1065,15 +1155,13 @@ runtime·malg(int32 stacksize)
 	return newg;
 }
 
-/*
- * Newproc and deferproc need to be textflag 7
- * (no possible stack split when nearing overflow)
- * because they assume that the arguments to fn
- * are available sequentially beginning at &arg0.
- * If a stack split happened, only the one word
- * arg0 would be copied.  It's okay if any functions
- * they call split the stack below the newproc frame.
- */
+// Create a new g running fn with siz bytes of arguments.
+// Put it on the queue of g's waiting to run.
+// The compiler turns a go statement into a call to this.
+// Cannot split the stack because it assumes that the arguments
+// are available sequentially after &fn; they would not be
+// copied if a stack split occurred.  It's OK for this to call
+// functions that split the stack.
 #pragma textflag 7
 void
 runtime·newproc(int32 siz, byte* fn, ...)
@@ -1087,6 +1175,10 @@ runtime·newproc(int32 siz, byte* fn, ...)
 	runtime·newproc1(fn, argp, siz, 0, runtime·getcallerpc(&siz));
 }
 
+// Create a new g running fn with narg bytes of arguments starting
+// at argp and returning nret bytes of results.  callerpc is the
+// address of the go statement that created this.  The new g is put
+// on the queue of g's waiting to run.
 G*
 runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
 {
@@ -1097,7 +1189,7 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
 //printf("newproc1 %p %p narg=%d nret=%d\n", fn, argp, narg, nret);
 	siz = narg + nret;
 	siz = (siz+7) & ~7;
-	
+
 	// We could instead create a secondary stack frame
 	// and make it look like goexit was on the original but
 	// the call to the actual goroutine function was split.
@@ -1147,6 +1239,12 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
 //printf(" goid=%d\n", newg->goid);
 }
 
+// Create a new deferred function fn with siz bytes of arguments.
+// The compiler turns a defer statement into a call to this.
+// Cannot split the stack because it assumes that the arguments
+// are available sequentially after &fn; they would not be
+// copied if a stack split occurred.  It's OK for this to call
+// functions that split the stack.
 #pragma textflag 7
 uintptr
 runtime·deferproc(int32 siz, byte* fn, ...)
@@ -1175,6 +1273,16 @@ runtime·deferproc(int32 siz, byte* fn, ...)
 	return 0;
 }
 
+// Run a deferred function if there is one.
+// The compiler inserts a call to this at the end of any
+// function which calls defer.
+// If there is a deferred function, this will call runtime·jmpdefer,
+// which will jump to the deferred function such that it appears
+// to have been called by the caller of deferreturn at the point
+// just before deferreturn was called.  The effect is that deferreturn
+// is called again and again until there are no more deferred functions.
+// Cannot split the stack because we reuse the caller's frame to
+// call the deferred function.
 #pragma textflag 7
 void
 runtime·deferreturn(uintptr arg0)
@@ -1196,6 +1304,7 @@ runtime·deferreturn(uintptr arg0)
 	runtime·jmpdefer(fn, argp);
 }
 
+// Run all deferred functions for the current goroutine.
 static void
 rundefer(void)
 {
@@ -1237,6 +1346,7 @@ unwindstack(G *gp, byte *sp)
 	}
 }
 
+// Print all currently active panics.  Used when crashing.
 static void
 printpanics(Panic *p)
 {
@@ -1253,6 +1363,7 @@ printpanics(Panic *p)
 
 static void recovery(G*);
 
+// The implementation of the predeclared function panic.
 void
 runtime·panic(Eface e)
 {
@@ -1295,6 +1406,9 @@ runtime·panic(Eface e)
 	runtime·dopanic(0);
 }
 
+// Unwind the stack after a deferred function calls recover
+// after a panic.  Then arrange to continue running as though
+// the caller of the deferred function returned normally.
 static void
 recovery(G *gp)
 {
@@ -1326,7 +1440,10 @@ recovery(G *gp)
 	runtime·gogo(&gp->sched, 1);
 }
 
-#pragma textflag 7	/* no split, or else g->stackguard is not the stack for fp */
+// The implementation of the predeclared function recover.
+// Cannot split the stack because it needs to reliably
+// find the stack segment of its caller.
+#pragma textflag 7
 void
 runtime·recover(byte *argp, Eface ret)
 {
@@ -1438,15 +1555,7 @@ runtime·Gosched(void)
 	runtime·gosched();
 }
 
-void
-runtime·LockOSThread(void)
-{
-	if(runtime·sched.predawn)
-		runtime·throw("cannot wire during init");
-	m->lockedg = g;
-	g->lockedm = m;
-}
-
+// Implementation of runtime.GOMAXPROCS.
 // delete when scheduler is stronger
 int32
 runtime·gomaxprocsfunc(int32 n)
@@ -1487,8 +1596,23 @@ runtime·gomaxprocsfunc(int32 n)
 }
 
 void
+runtime·LockOSThread(void)
+{
+	if(m == &runtime·m0 && runtime·sched.init) {
+		runtime·sched.lockmain = true;
+		return;
+	}
+	m->lockedg = g;
+	g->lockedm = m;
+}
+
+void
 runtime·UnlockOSThread(void)
 {
+	if(m == &runtime·m0 && runtime·sched.init) {
+		runtime·sched.lockmain = false;
+		return;
+	}
 	m->lockedg = nil;
 	g->lockedm = nil;
 }
@@ -1499,6 +1623,14 @@ runtime·lockedOSThread(void)
 	return g->lockedm != nil && m->lockedg != nil;
 }
 
+// for testing of callbacks
+void
+runtime·golockedOSThread(bool ret)
+{
+	ret = runtime·lockedOSThread();
+	FLUSH(&ret);
+}
+
 // for testing of wire, unwire
 void
 runtime·mid(uint32 ret)
@@ -1539,6 +1671,7 @@ static struct {
 	uintptr pcbuf[100];
 } prof;
 
+// Called if we receive a SIGPROF signal.
 void
 runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
 {
@@ -1558,6 +1691,7 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
 	runtime·unlock(&prof);
 }
 
+// Arrange to call fn with a traceback hz times a second.
 void
 runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
 {
@@ -1588,8 +1722,10 @@ runtime·setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
 
 void (*libcgo_setenv)(byte**);
 
+// Update the C environment if cgo is loaded.
+// Called from syscall.Setenv.
 void
-os·setenv_c(String k, String v)
+syscall·setenv_c(String k, String v)
 {
 	byte *arg[2];
 
diff --git a/src/pkg/runtime/darwin/386/rt0.s b/src/pkg/runtime/rt0_darwin_386.s
similarity index 100%
rename from src/pkg/runtime/darwin/386/rt0.s
rename to src/pkg/runtime/rt0_darwin_386.s
diff --git a/src/pkg/runtime/darwin/amd64/rt0.s b/src/pkg/runtime/rt0_darwin_amd64.s
similarity index 100%
rename from src/pkg/runtime/darwin/amd64/rt0.s
rename to src/pkg/runtime/rt0_darwin_amd64.s
diff --git a/src/pkg/runtime/freebsd/386/rt0.s b/src/pkg/runtime/rt0_freebsd_386.s
similarity index 100%
rename from src/pkg/runtime/freebsd/386/rt0.s
rename to src/pkg/runtime/rt0_freebsd_386.s
diff --git a/src/pkg/runtime/freebsd/amd64/rt0.s b/src/pkg/runtime/rt0_freebsd_amd64.s
similarity index 100%
rename from src/pkg/runtime/freebsd/amd64/rt0.s
rename to src/pkg/runtime/rt0_freebsd_amd64.s
diff --git a/src/pkg/runtime/linux/386/rt0.s b/src/pkg/runtime/rt0_linux_386.s
similarity index 100%
rename from src/pkg/runtime/linux/386/rt0.s
rename to src/pkg/runtime/rt0_linux_386.s
diff --git a/src/pkg/runtime/linux/amd64/rt0.s b/src/pkg/runtime/rt0_linux_amd64.s
similarity index 100%
rename from src/pkg/runtime/linux/amd64/rt0.s
rename to src/pkg/runtime/rt0_linux_amd64.s
diff --git a/src/pkg/runtime/linux/arm/rt0.s b/src/pkg/runtime/rt0_linux_arm.s
similarity index 100%
rename from src/pkg/runtime/linux/arm/rt0.s
rename to src/pkg/runtime/rt0_linux_arm.s
diff --git a/src/pkg/runtime/rt0_netbsd_386.s b/src/pkg/runtime/rt0_netbsd_386.s
new file mode 100644
index 0000000..829e413
--- /dev/null
+++ b/src/pkg/runtime/rt0_netbsd_386.s
@@ -0,0 +1,6 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+TEXT _rt0_386_netbsd(SB),7,$0
+	JMP     _rt0_386(SB)
diff --git a/src/pkg/runtime/rt0_netbsd_amd64.s b/src/pkg/runtime/rt0_netbsd_amd64.s
new file mode 100644
index 0000000..85482b9
--- /dev/null
+++ b/src/pkg/runtime/rt0_netbsd_amd64.s
@@ -0,0 +1,8 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+TEXT _rt0_amd64_netbsd(SB),7,$-8
+	MOVQ	$_rt0_amd64(SB), DX
+	MOVQ	SP, DI
+	JMP	DX
diff --git a/src/pkg/runtime/openbsd/386/rt0.s b/src/pkg/runtime/rt0_openbsd_386.s
similarity index 100%
rename from src/pkg/runtime/openbsd/386/rt0.s
rename to src/pkg/runtime/rt0_openbsd_386.s
diff --git a/src/pkg/runtime/openbsd/amd64/rt0.s b/src/pkg/runtime/rt0_openbsd_amd64.s
similarity index 100%
rename from src/pkg/runtime/openbsd/amd64/rt0.s
rename to src/pkg/runtime/rt0_openbsd_amd64.s
diff --git a/src/pkg/runtime/plan9/386/rt0.s b/src/pkg/runtime/rt0_plan9_386.s
similarity index 100%
rename from src/pkg/runtime/plan9/386/rt0.s
rename to src/pkg/runtime/rt0_plan9_386.s
diff --git a/src/pkg/runtime/windows/386/rt0.s b/src/pkg/runtime/rt0_windows_386.s
similarity index 100%
rename from src/pkg/runtime/windows/386/rt0.s
rename to src/pkg/runtime/rt0_windows_386.s
diff --git a/src/pkg/runtime/rt0_windows_amd64.s b/src/pkg/runtime/rt0_windows_amd64.s
new file mode 100644
index 0000000..dc1408a
--- /dev/null
+++ b/src/pkg/runtime/rt0_windows_amd64.s
@@ -0,0 +1,13 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "zasm_GOOS_GOARCH.h"
+
+TEXT	_rt0_amd64_windows(SB),7,$-8
+	MOVQ	$_rt0_amd64(SB), AX
+	MOVQ	SP, DI
+	JMP	AX
+
+DATA  runtime·iswindows(SB)/4, $1
+GLOBL runtime·iswindows(SB), $4
diff --git a/src/pkg/runtime/runtime-gdb.py b/src/pkg/runtime/runtime-gdb.py
index a96f3f3..dff4e2b 100644
--- a/src/pkg/runtime/runtime-gdb.py
+++ b/src/pkg/runtime/runtime-gdb.py
@@ -91,8 +91,8 @@ class MapTypePrinter:
 
 	def traverse_hash(self, stab):
 		ptr = stab['entry'].address
-		end = stab['end']
-		while ptr < end:
+		last = stab['last']
+		while ptr <= last:
 			v = ptr.dereference()
 			ptr = ptr + 1
 			if v['hash'] == 0: continue
@@ -122,8 +122,8 @@ class ChanTypePrinter:
 		return str(self.val.type)
 
 	def children(self):
-		# see chan.c chanbuf()
-		et = [x.type for x in self.val['free'].type.target().fields() if x.name == 'elem'][0]
+		# see chan.c chanbuf().  et is the type stolen from hchan<T>::recvq->first->elem
+		et = [x.type for x in self.val['recvq']['first'].type.target().fields() if x.name == 'elem'][0]
                 ptr = (self.val.address + 1).cast(et.pointer())
                 for i in range(self.val["qcount"]):
 			j = (self.val["recvx"] + i) % self.val["dataqsiz"]
@@ -187,6 +187,8 @@ def lookup_type(name):
 
 def iface_dtype(obj):
 	"Decode type of the data field of an eface or iface struct."
+        # known issue: dtype_name decoded from runtime.commonType is "nested.Foo"
+        # but the dwarf table lists it as "full/path/to/nested.Foo"
 
 	if is_iface(obj):
 		go_type_ptr = obj['tab']['_type']
@@ -198,13 +200,30 @@ def iface_dtype(obj):
 	ct = gdb.lookup_type("struct runtime.commonType").pointer()
 	dynamic_go_type = go_type_ptr['ptr'].cast(ct).dereference()
 	dtype_name = dynamic_go_type['string'].dereference()['str'].string()
-	type_size = int(dynamic_go_type['size'])
-	uintptr_size = int(dynamic_go_type['size'].type.sizeof)  # size is itself an uintptr
+
 	dynamic_gdb_type = lookup_type(dtype_name)
-	if type_size > uintptr_size:
-		dynamic_gdb_type = dynamic_gdb_type.pointer()
+        if dynamic_gdb_type:
+		type_size = int(dynamic_go_type['size'])
+                uintptr_size = int(dynamic_go_type['size'].type.sizeof)  # size is itself an uintptr
+		if type_size > uintptr_size:
+			dynamic_gdb_type = dynamic_gdb_type.pointer()
+
 	return dynamic_gdb_type
 
+def iface_dtype_name(obj):
+	"Decode type name of the data field of an eface or iface struct."
+
+	if is_iface(obj):
+		go_type_ptr = obj['tab']['_type']
+	elif is_eface(obj):
+		go_type_ptr = obj['_type']
+	else:
+		return
+
+	ct = gdb.lookup_type("struct runtime.commonType").pointer()
+	dynamic_go_type = go_type_ptr['ptr'].cast(ct).dereference()
+	return dynamic_go_type['string'].dereference()['str'].string()
+
 
 class IfacePrinter:
 	"""Pretty print interface values
@@ -224,6 +243,10 @@ class IfacePrinter:
 			dtype = iface_dtype(self.val)
 		except:
 			return "<bad dynamic type>"
+
+                if not dtype:  # trouble looking up, print something reasonable
+			return "(%s)%s" % (iface_dtype_name(self.val), self.val['data'])
+
 		try:
 			return self.val['data'].cast(dtype).dereference()
 		except:
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c
index ae6fd87..81cacca 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/pkg/runtime/runtime.c
@@ -172,7 +172,7 @@ static int32	argc;
 static uint8**	argv;
 
 Slice os·Args;
-Slice os·Envs;
+Slice syscall·envs;
 
 void
 runtime·args(int32 c, uint8 **v)
@@ -214,9 +214,9 @@ runtime·goenvs_unix(void)
 	s = runtime·malloc(n*sizeof s[0]);
 	for(i=0; i<n; i++)
 		s[i] = runtime·gostringnocopy(argv[argc+1+i]);
-	os·Envs.array = (byte*)s;
-	os·Envs.len = n;
-	os·Envs.cap = n;
+	syscall·envs.array = (byte*)s;
+	syscall·envs.len = n;
+	syscall·envs.cap = n;
 }
 
 byte*
@@ -229,8 +229,8 @@ runtime·getenv(int8 *s)
 
 	bs = (byte*)s;
 	len = runtime·findnull(bs);
-	envv = (String*)os·Envs.array;
-	envc = os·Envs.len;
+	envv = (String*)syscall·envs.array;
+	envc = syscall·envs.len;
 	for(i=0; i<envc; i++){
 		if(envv[i].len <= len)
 			continue;
@@ -278,8 +278,8 @@ runtime·check(void)
 	uint32 f;
 	int64 g;
 	uint64 h;
-	float32 i;
-	float64 j;
+	float32 i, i1;
+	float64 j, j1;
 	void* k;
 	uint16* l;
 	struct x1 {
@@ -319,351 +319,31 @@ runtime·check(void)
 	if(z != 4)
 		runtime·throw("cas4");
 
-	runtime·initsig(0);
-}
-
-/*
- * map and chan helpers for
- * dealing with unknown types
- */
-static uintptr
-memhash(uint32 s, void *a)
-{
-	byte *b;
-	uintptr hash;
-
-	b = a;
-	if(sizeof(hash) == 4)
-		hash = 2860486313U;
-	else
-		hash = 33054211828000289ULL;
-	while(s > 0) {
-		if(sizeof(hash) == 4)
-			hash = (hash ^ *b) * 3267000013UL;
-		else
-			hash = (hash ^ *b) * 23344194077549503ULL;
-		b++;
-		s--;
-	}
-	return hash;
-}
-
-static uint32
-memequal(uint32 s, void *a, void *b)
-{
-	byte *ba, *bb, *aend;
-
-	if(a == b)
-	  return 1;
-	ba = a;
-	bb = b;
-	aend = ba+s;
-	while(ba != aend) {
-		if(*ba != *bb)
-			return 0;
-		ba++;
-		bb++;
-	}
-	return 1;
-}
-
-static void
-memprint(uint32 s, void *a)
-{
-	uint64 v;
-
-	v = 0xbadb00b;
-	switch(s) {
-	case 1:
-		v = *(uint8*)a;
-		break;
-	case 2:
-		v = *(uint16*)a;
-		break;
-	case 4:
-		v = *(uint32*)a;
-		break;
-	case 8:
-		v = *(uint64*)a;
-		break;
-	}
-	runtime·printint(v);
-}
-
-static void
-memcopy(uint32 s, void *a, void *b)
-{
-	if(b == nil) {
-		runtime·memclr(a,s);
-		return;
-	}
-	runtime·memmove(a,b,s);
-}
-
-static uint32
-memequal8(uint32 s, uint8 *a, uint8 *b)
-{
-	USED(s);
-	return *a == *b;
-}
-
-static void
-memcopy8(uint32 s, uint8 *a, uint8 *b)
-{
-	USED(s);
-	if(b == nil) {
-		*a = 0;
-		return;
-	}
-	*a = *b;
-}
-
-static uint32
-memequal16(uint32 s, uint16 *a, uint16 *b)
-{
-	USED(s);
-	return *a == *b;
-}
-
-static void
-memcopy16(uint32 s, uint16 *a, uint16 *b)
-{
-	USED(s);
-	if(b == nil) {
-		*a = 0;
-		return;
-	}
-	*a = *b;
-}
-
-static uint32
-memequal32(uint32 s, uint32 *a, uint32 *b)
-{
-	USED(s);
-	return *a == *b;
-}
-
-static void
-memcopy32(uint32 s, uint32 *a, uint32 *b)
-{
-	USED(s);
-	if(b == nil) {
-		*a = 0;
-		return;
-	}
-	*a = *b;
-}
-
-static uint32
-memequal64(uint32 s, uint64 *a, uint64 *b)
-{
-	USED(s);
-	return *a == *b;
-}
-
-static void
-memcopy64(uint32 s, uint64 *a, uint64 *b)
-{
-	USED(s);
-	if(b == nil) {
-		*a = 0;
-		return;
-	}
-	*a = *b;
-}
-
-static uint32
-memequal128(uint32 s, uint64 *a, uint64 *b)
-{
-	USED(s);
-	return a[0] == b[0] && a[1] == b[1];
-}
-
-static void
-memcopy128(uint32 s, uint64 *a, uint64 *b)
-{
-	USED(s);
-	if(b == nil) {
-		a[0] = 0;
-		a[1] = 0;
-		return;
-	}
-	a[0] = b[0];
-	a[1] = b[1];
-}
+	*(uint64*)&j = ~0ULL;
+	if(j == j)
+		runtime·throw("float64nan");
+	if(!(j != j))
+		runtime·throw("float64nan1");
+
+	*(uint64*)&j1 = ~1ULL;
+	if(j == j1)
+		runtime·throw("float64nan2");
+	if(!(j != j1))
+		runtime·throw("float64nan3");
+
+	*(uint32*)&i = ~0UL;
+	if(i == i)
+		runtime·throw("float32nan");
+	if(!(i != i))
+		runtime·throw("float32nan1");
+
+	*(uint32*)&i1 = ~1UL;
+	if(i == i1)
+		runtime·throw("float32nan2");
+	if(!(i != i1))
+		runtime·throw("float32nan3");
 
-static void
-slicecopy(uint32 s, Slice *a, Slice *b)
-{
-	USED(s);
-	if(b == nil) {
-		a->array = 0;
-		a->len = 0;
-		a->cap = 0;
-		return;
-	}
-	a->array = b->array;
-	a->len = b->len;
-	a->cap = b->cap;
-}
-
-static uintptr
-strhash(uint32 s, String *a)
-{
-	USED(s);
-	return memhash((*a).len, (*a).str);
-}
-
-static uint32
-strequal(uint32 s, String *a, String *b)
-{
-	int32 alen;
-
-	USED(s);
-	alen = a->len;
-	if(alen != b->len)
-		return false;
-	return memequal(alen, a->str, b->str);
-}
-
-static void
-strprint(uint32 s, String *a)
-{
-	USED(s);
-	runtime·printstring(*a);
-}
-
-static void
-strcopy(uint32 s, String *a, String *b)
-{
-	USED(s);
-	if(b == nil) {
-		a->str = 0;
-		a->len = 0;
-		return;
-	}
-	a->str = b->str;
-	a->len = b->len;
-}
-
-static uintptr
-interhash(uint32 s, Iface *a)
-{
-	USED(s);
-	return runtime·ifacehash(*a);
-}
-
-static void
-interprint(uint32 s, Iface *a)
-{
-	USED(s);
-	runtime·printiface(*a);
-}
-
-static uint32
-interequal(uint32 s, Iface *a, Iface *b)
-{
-	USED(s);
-	return runtime·ifaceeq_c(*a, *b);
-}
-
-static void
-intercopy(uint32 s, Iface *a, Iface *b)
-{
-	USED(s);
-	if(b == nil) {
-		a->tab = 0;
-		a->data = 0;
-		return;
-	}
-	a->tab = b->tab;
-	a->data = b->data;
-}
-
-static uintptr
-nilinterhash(uint32 s, Eface *a)
-{
-	USED(s);
-	return runtime·efacehash(*a);
-}
-
-static void
-nilinterprint(uint32 s, Eface *a)
-{
-	USED(s);
-	runtime·printeface(*a);
-}
-
-static uint32
-nilinterequal(uint32 s, Eface *a, Eface *b)
-{
-	USED(s);
-	return runtime·efaceeq_c(*a, *b);
-}
-
-static void
-nilintercopy(uint32 s, Eface *a, Eface *b)
-{
-	USED(s);
-	if(b == nil) {
-		a->type = 0;
-		a->data = 0;
-		return;
-	}
-	a->type = b->type;
-	a->data = b->data;
-}
-
-uintptr
-runtime·nohash(uint32 s, void *a)
-{
-	USED(s);
-	USED(a);
-	runtime·panicstring("hash of unhashable type");
-	return 0;
-}
-
-uint32
-runtime·noequal(uint32 s, void *a, void *b)
-{
-	USED(s);
-	USED(a);
-	USED(b);
-	runtime·panicstring("comparing uncomparable types");
-	return 0;
-}
-
-Alg
-runtime·algarray[] =
-{
-[AMEM]	{ memhash, memequal, memprint, memcopy },
-[ANOEQ]	{ runtime·nohash, runtime·noequal, memprint, memcopy },
-[ASTRING]	{ (void*)strhash, (void*)strequal, (void*)strprint, (void*)strcopy },
-[AINTER]		{ (void*)interhash, (void*)interequal, (void*)interprint, (void*)intercopy },
-[ANILINTER]	{ (void*)nilinterhash, (void*)nilinterequal, (void*)nilinterprint, (void*)nilintercopy },
-[ASLICE]	{ (void*)runtime·nohash, (void*)runtime·noequal, (void*)memprint, (void*)slicecopy },
-[AMEM8]		{ memhash, (void*)memequal8, memprint, (void*)memcopy8 },
-[AMEM16]	{ memhash, (void*)memequal16, memprint, (void*)memcopy16 },
-[AMEM32]	{ memhash, (void*)memequal32, memprint, (void*)memcopy32 },
-[AMEM64]	{ memhash, (void*)memequal64, memprint, (void*)memcopy64 },
-[AMEM128]	{ memhash, (void*)memequal128, memprint, (void*)memcopy128 },
-[ANOEQ8]	{ runtime·nohash, runtime·noequal, memprint, (void*)memcopy8 },
-[ANOEQ16]	{ runtime·nohash, runtime·noequal, memprint, (void*)memcopy16 },
-[ANOEQ32]	{ runtime·nohash, runtime·noequal, memprint, (void*)memcopy32 },
-[ANOEQ64]	{ runtime·nohash, runtime·noequal, memprint, (void*)memcopy64 },
-[ANOEQ128]	{ runtime·nohash, runtime·noequal, memprint, (void*)memcopy128 },
-};
-
-int64
-runtime·nanotime(void)
-{
-	int64 sec;
-	int32 usec;
-
-	sec = 0;
-	usec = 0;
-	runtime·gettime(&sec, &usec);
-	return sec*1000000000 + (int64)usec*1000;
+	runtime·initsig(0);
 }
 
 void
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 999511a..df2cd14 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -43,21 +43,19 @@ typedef int32		intptr;
  */
 typedef	uint8			bool;
 typedef	uint8			byte;
-typedef	struct	Alg		Alg;
 typedef	struct	Func		Func;
 typedef	struct	G		G;
 typedef	struct	Gobuf		Gobuf;
-typedef	struct	Lock		Lock;
+typedef	union	Lock		Lock;
 typedef	struct	M		M;
 typedef	struct	Mem		Mem;
 typedef	union	Note		Note;
 typedef	struct	Slice		Slice;
 typedef	struct	Stktop		Stktop;
 typedef	struct	String		String;
-typedef	struct	Usema		Usema;
 typedef	struct	SigTab		SigTab;
 typedef	struct	MCache		MCache;
-typedef struct	FixAlloc	FixAlloc;
+typedef	struct	FixAlloc	FixAlloc;
 typedef	struct	Iface		Iface;
 typedef	struct	Itab		Itab;
 typedef	struct	Eface		Eface;
@@ -71,6 +69,8 @@ typedef	struct	Hchan		Hchan;
 typedef	struct	Complex64	Complex64;
 typedef	struct	Complex128	Complex128;
 typedef	struct	WinCall		WinCall;
+typedef	struct	Timers		Timers;
+typedef	struct	Timer		Timer;
 
 /*
  * per-cpu declaration.
@@ -117,32 +117,15 @@ enum
 /*
  * structures
  */
-struct	Lock
-{
-#ifdef __WINDOWS__
-	M*	waitm;	// linked list of waiting M's
-#else
-	uint32	key;
-	uint32	sema;	// for OS X
-#endif
-};
-struct	Usema
+union	Lock
 {
-	uint32	u;
-	uint32	k;
+	uint32	key;	// futex-based impl
+	M*	waitm;	// linked list of waiting M's (sema-based impl)
 };
 union	Note
 {
-	struct {	// Linux
-		uint32	state;
-	};
-	struct {	// Windows
-		Lock lock;
-	};
-	struct {	// OS X
-		int32	wakeup;
-		Usema	sema;
-	};
+	uint32	key;	// futex-based impl
+	M*	waitm;	// waiting M (sema-based impl)
 };
 struct String
 {
@@ -185,8 +168,8 @@ struct	Gobuf
 };
 struct	G
 {
-	byte*	stackguard;	// cannot move - also known to linker, libmach, libcgo
-	byte*	stackbase;	// cannot move - also known to libmach, libcgo
+	byte*	stackguard;	// cannot move - also known to linker, libmach, runtime/cgo
+	byte*	stackbase;	// cannot move - also known to libmach, runtime/cgo
 	Defer*	defer;
 	Panic*	panic;
 	Gobuf	sched;
@@ -238,6 +221,7 @@ struct	M
 	int32	waitnextg;
 	int32	dying;
 	int32	profilehz;
+	int32	helpgc;
 	uint32	fastrand;
 	uint64	ncgocall;
 	Note	havenextg;
@@ -252,11 +236,13 @@ struct	M
 	uint32	freglo[16];	// D[i] lsb and F[i]
 	uint32	freghi[16];	// D[i] msb and F[i+16]
 	uint32	fflag;		// floating point compare flags
+	M*	nextwaitm;	// next M waiting for lock
+	uintptr	waitsema;	// semaphore for parking on locks
+	uint32	waitsemacount;
+	uint32	waitsemalock;
 
-#ifdef __WINDOWS__
+#ifdef GOOS_windows
 	void*	thread;		// thread handle
-	void*	event;		// event for signalling
-	M*	nextwaitm;	// next M waiting for lock
 #endif
 	uintptr	end[];
 };
@@ -273,13 +259,6 @@ struct	Stktop
 	uintptr	free;	// if free>0, call stackfree using free as size
 	bool	panic;	// is this frame the top of a panic?
 };
-struct	Alg
-{
-	uintptr	(*hash)(uint32, void*);
-	uint32	(*equal)(uint32, void*, void*);
-	void	(*print)(uint32, void*);
-	void	(*copy)(uint32, void*, void*);
-};
 struct	SigTab
 {
 	int32	flags;
@@ -320,7 +299,7 @@ struct	WinCall
 	uintptr	err;	// error number
 };
 
-#ifdef __WINDOWS__
+#ifdef GOOS_windows
 enum {
    Windows = 1
 };
@@ -330,6 +309,33 @@ enum {
 };
 #endif
 
+struct	Timers
+{
+	Lock;
+	G	*timerproc;
+	bool		sleeping;
+	bool		rescheduling;
+	Note	waitnote;
+	Timer	**t;
+	int32	len;
+	int32	cap;
+};
+
+// Package time knows the layout of this structure.
+// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
+struct	Timer
+{
+	int32	i;		// heap index
+
+	// Timer wakes up at when, and then at when+period, ... (period > 0 only)
+	// each time calling f(now, arg) in the timer goroutine, so f must be
+	// a well-behaved function and not block.
+	int64	when;
+	int64	period;
+	void	(*f)(int64, Eface);
+	Eface	arg;
+};
+
 /*
  * defined macros
  *    you need super-gopher-guru privilege
@@ -342,31 +348,78 @@ enum {
 /*
  * known to compiler
  */
+enum {
+	Structrnd = sizeof(uintptr)
+};
+
+/*
+ * type algorithms - known to compiler
+ */
 enum
 {
 	AMEM,
-	ANOEQ,
-	ASTRING,
-	AINTER,
-	ANILINTER,
-	ASLICE,
+	AMEM0,
 	AMEM8,
 	AMEM16,
 	AMEM32,
 	AMEM64,
 	AMEM128,
+	ANOEQ,
+	ANOEQ0,
 	ANOEQ8,
 	ANOEQ16,
 	ANOEQ32,
 	ANOEQ64,
 	ANOEQ128,
+	ASTRING,
+	AINTER,
+	ANILINTER,
+	ASLICE,
+	AFLOAT32,
+	AFLOAT64,
+	ACPLX64,
+	ACPLX128,
 	Amax
 };
+typedef	struct	Alg		Alg;
+struct	Alg
+{
+	void	(*hash)(uintptr*, uintptr, void*);
+	void	(*equal)(bool*, uintptr, void*, void*);
+	void	(*print)(uintptr, void*);
+	void	(*copy)(uintptr, void*, void*);
+};
 
+extern	Alg	runtime·algarray[Amax];
 
-enum {
-	Structrnd = sizeof(uintptr)
-};
+void	runtime·memhash(uintptr*, uintptr, void*);
+void	runtime·nohash(uintptr*, uintptr, void*);
+void	runtime·strhash(uintptr*, uintptr, void*);
+void	runtime·interhash(uintptr*, uintptr, void*);
+void	runtime·nilinterhash(uintptr*, uintptr, void*);
+
+void	runtime·memequal(bool*, uintptr, void*, void*);
+void	runtime·noequal(bool*, uintptr, void*, void*);
+void	runtime·strequal(bool*, uintptr, void*, void*);
+void	runtime·interequal(bool*, uintptr, void*, void*);
+void	runtime·nilinterequal(bool*, uintptr, void*, void*);
+
+void	runtime·memprint(uintptr, void*);
+void	runtime·strprint(uintptr, void*);
+void	runtime·interprint(uintptr, void*);
+void	runtime·nilinterprint(uintptr, void*);
+
+void	runtime·memcopy(uintptr, void*, void*);
+void	runtime·memcopy8(uintptr, void*, void*);
+void	runtime·memcopy16(uintptr, void*, void*);
+void	runtime·memcopy32(uintptr, void*, void*);
+void	runtime·memcopy64(uintptr, void*, void*);
+void	runtime·memcopy128(uintptr, void*, void*);
+void	runtime·memcopy(uintptr, void*, void*);
+void	runtime·strcopy(uintptr, void*, void*);
+void	runtime·algslicecopy(uintptr, void*, void*);
+void	runtime·intercopy(uintptr, void*, void*);
+void	runtime·nilintercopy(uintptr, void*, void*);
 
 /*
  * deferred subroutine calls
@@ -396,7 +449,6 @@ struct Panic
 /*
  * external data
  */
-extern	Alg	runtime·algarray[Amax];
 extern	String	runtime·emptystring;
 G*	runtime·allg;
 G*	runtime·lastg;
@@ -406,8 +458,8 @@ extern	bool	runtime·singleproc;
 extern	uint32	runtime·panicking;
 extern	int32	runtime·gcwaiting;		// gc is waiting to run
 int8*	runtime·goos;
+int32	runtime·ncpu;
 extern	bool	runtime·iscgo;
-extern	void	(*runtime·destroylock)(Lock*);
 
 /*
  * common functions and data
@@ -484,12 +536,9 @@ bool	runtime·ifaceeq_c(Iface, Iface);
 bool	runtime·efaceeq_c(Eface, Eface);
 uintptr	runtime·ifacehash(Iface);
 uintptr	runtime·efacehash(Eface);
-uintptr	runtime·nohash(uint32, void*);
-uint32	runtime·noequal(uint32, void*, void*);
 void*	runtime·malloc(uintptr size);
 void	runtime·free(void *v);
-void	runtime·addfinalizer(void*, void(*fn)(void*), int32);
-void	runtime·walkfintab(void (*fn)(void*));
+bool	runtime·addfinalizer(void*, void(*fn)(void*), int32);
 void	runtime·runpanic(Panic*);
 void*	runtime·getcallersp(void*);
 int32	runtime·mcount(void);
@@ -499,6 +548,8 @@ uint32	runtime·fastrand1(void);
 void	runtime·exit(int32);
 void	runtime·breakpoint(void);
 void	runtime·gosched(void);
+void	runtime·tsleep(int64);
+M*	runtime·newm(void);
 void	runtime·goexit(void);
 void	runtime·asmcgocall(void (*fn)(void*), void*);
 void	runtime·entersyscall(void);
@@ -506,7 +557,6 @@ void	runtime·exitsyscall(void);
 G*	runtime·newproc1(byte*, byte*, int32, int32, void*);
 void	runtime·siginit(void);
 bool	runtime·sigsend(int32 sig);
-void	runtime·gettime(int64*, int32*);
 int32	runtime·callers(int32, uintptr*, int32);
 int32	runtime·gentraceback(byte*, byte*, byte*, G*, int32, uintptr*, int32);
 int64	runtime·nanotime(void);
@@ -515,6 +565,7 @@ void	runtime·startpanic(void);
 void	runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp);
 void	runtime·resetcpuprofiler(int32);
 void	runtime·setcpuprofilerate(void(*)(uintptr*, int32), int32);
+void	runtime·usleep(uint32);
 
 #pragma	varargck	argpos	runtime·printf	1
 #pragma	varargck	type	"d"	int32
@@ -534,7 +585,7 @@ void	runtime·setcpuprofilerate(void(*)(uintptr*, int32), int32);
 // TODO(rsc): Remove. These are only temporary,
 // for the mark and sweep collector.
 void	runtime·stoptheworld(void);
-void	runtime·starttheworld(void);
+void	runtime·starttheworld(bool);
 
 /*
  * mutual exclusion locks.  in the uncontended case,
@@ -556,10 +607,28 @@ void	runtime·unlock(Lock*);
  * subsequent noteclear must be called only after
  * previous notesleep has returned, e.g. it's disallowed
  * to call noteclear straight after notewakeup.
+ *
+ * notetsleep is like notesleep but wakes up after
+ * a given number of nanoseconds even if the event
+ * has not yet happened.  if a goroutine uses notetsleep to
+ * wake up early, it must wait to call noteclear until it
+ * can be sure that no other goroutine is calling
+ * notewakeup.
  */
 void	runtime·noteclear(Note*);
 void	runtime·notesleep(Note*);
 void	runtime·notewakeup(Note*);
+void	runtime·notetsleep(Note*, int64);
+
+/*
+ * low-level synchronization for implementing the above
+ */
+uintptr	runtime·semacreate(void);
+int32	runtime·semasleep(int64);
+void	runtime·semawakeup(M*);
+// or
+void	runtime·futexsleep(uint32*, uint32, int64);
+void	runtime·futexwakeup(uint32*, uint32);
 
 /*
  * This is consistent across Linux and BSD.
@@ -572,7 +641,8 @@ void	runtime·notewakeup(Note*);
  * low level C-called
  */
 uint8*	runtime·mmap(byte*, uintptr, int32, int32, int32, uint32);
-void	runtime·munmap(uint8*, uintptr);
+void	runtime·munmap(byte*, uintptr);
+void	runtime·madvise(byte*, uintptr, int32);
 void	runtime·memclr(byte*, uintptr);
 void	runtime·setcallerpc(void*, void*);
 void*	runtime·getcallerpc(void*);
@@ -635,6 +705,8 @@ String	runtime·signame(int32 sig);
 int32	runtime·gomaxprocsfunc(int32 n);
 void	runtime·procyield(uint32);
 void	runtime·osyield(void);
+void	runtime·LockOSThread(void);
+void	runtime·UnlockOSThread(void);
 
 void	runtime·mapassign(MapType*, Hmap*, byte*, byte*);
 void	runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*);
diff --git a/src/pkg/runtime/runtime1.goc b/src/pkg/runtime/runtime1.goc
index da2d0c5..667131c 100644
--- a/src/pkg/runtime/runtime1.goc
+++ b/src/pkg/runtime/runtime1.goc
@@ -8,3 +8,7 @@ package runtime
 func GOMAXPROCS(n int32) (ret int32) {
 	ret = runtime·gomaxprocsfunc(n);
 }
+
+func NumCPU() (ret int32) {
+	ret = runtime·ncpu;
+}
diff --git a/src/pkg/runtime/sema.goc b/src/pkg/runtime/sema.goc
index d202a9d..67c9035 100644
--- a/src/pkg/runtime/sema.goc
+++ b/src/pkg/runtime/sema.goc
@@ -19,6 +19,7 @@
 
 package runtime
 #include "runtime.h"
+#include "arch_GOARCH.h"
 
 typedef struct Sema Sema;
 struct Sema
@@ -45,11 +46,7 @@ struct SemaRoot
 static union
 {
 	SemaRoot;
-	// Modern processors tend to have 64-byte cache lines,
-	// potentially with 128-byte effective cache line size for reading.
-	// While there are hypothetical architectures
-	// with 16-4096 byte cache lines, 128 looks like a good compromise.
-	uint8 pad[128];
+	uint8 pad[CacheLineSize];
 } semtable[SEMTABLESZ];
 
 static SemaRoot*
diff --git a/src/pkg/runtime/signal_darwin_386.c b/src/pkg/runtime/signal_darwin_386.c
new file mode 100644
index 0000000..14f9911
--- /dev/null
+++ b/src/pkg/runtime/signal_darwin_386.c
@@ -0,0 +1,194 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signals_GOOS.h"
+
+void
+runtime·dumpregs(Regs32 *r)
+{
+	runtime·printf("eax     %x\n", r->eax);
+	runtime·printf("ebx     %x\n", r->ebx);
+	runtime·printf("ecx     %x\n", r->ecx);
+	runtime·printf("edx     %x\n", r->edx);
+	runtime·printf("edi     %x\n", r->edi);
+	runtime·printf("esi     %x\n", r->esi);
+	runtime·printf("ebp     %x\n", r->ebp);
+	runtime·printf("esp     %x\n", r->esp);
+	runtime·printf("eip     %x\n", r->eip);
+	runtime·printf("eflags  %x\n", r->eflags);
+	runtime·printf("cs      %x\n", r->cs);
+	runtime·printf("fs      %x\n", r->fs);
+	runtime·printf("gs      %x\n", r->gs);
+}
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Ucontext *uc;
+	Mcontext32 *mc;
+	Regs32 *r;
+	uintptr *sp;
+	byte *pc;
+
+	uc = context;
+	mc = uc->uc_mcontext;
+	r = &mc->ss;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Work around Leopard bug that doesn't set FPE_INTDIV.
+		// Look at instruction to see if it is a divide.
+		// Not necessary in Snow Leopard (si_code will be != 0).
+		if(sig == SIGFPE && info->si_code == 0) {
+			pc = (byte*)r->eip;
+			if(pc[0] == 0x66)	// 16-bit instruction prefix
+				pc++;
+			if(pc[0] == 0xF6 || pc[0] == 0xF7)
+				info->si_code = FPE_INTDIV;
+		}
+		
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = (uintptr)info->si_addr;
+		gp->sigpc = r->eip;
+
+		// Only push runtime·sigpanic if r->eip != 0.
+		// If r->eip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->eip != 0) {
+			sp = (uintptr*)r->esp;
+			*--sp = r->eip;
+			r->esp = (uintptr)sp;
+		}
+		r->eip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG){
+		runtime·printf("Signal %d\n", sig);
+	}else{
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+	}
+
+	runtime·printf("pc: %x\n", r->eip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+void
+runtime·sigignore(int32, Siginfo*, void*)
+{
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	StackT st;
+
+	st.ss_sp = p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0U;
+	sa.sa_tramp = (void*)runtime·sigtramp;	// runtime·sigtramp's job is to call into real handler
+	*(uintptr*)sa.__sigaction_u = (uintptr)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_darwin_amd64.c b/src/pkg/runtime/signal_darwin_amd64.c
new file mode 100644
index 0000000..c7621dd
--- /dev/null
+++ b/src/pkg/runtime/signal_darwin_amd64.c
@@ -0,0 +1,204 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signals_GOOS.h"
+
+void
+runtime·dumpregs(Regs64 *r)
+{
+	runtime·printf("rax     %X\n", r->rax);
+	runtime·printf("rbx     %X\n", r->rbx);
+	runtime·printf("rcx     %X\n", r->rcx);
+	runtime·printf("rdx     %X\n", r->rdx);
+	runtime·printf("rdi     %X\n", r->rdi);
+	runtime·printf("rsi     %X\n", r->rsi);
+	runtime·printf("rbp     %X\n", r->rbp);
+	runtime·printf("rsp     %X\n", r->rsp);
+	runtime·printf("r8      %X\n", r->r8 );
+	runtime·printf("r9      %X\n", r->r9 );
+	runtime·printf("r10     %X\n", r->r10);
+	runtime·printf("r11     %X\n", r->r11);
+	runtime·printf("r12     %X\n", r->r12);
+	runtime·printf("r13     %X\n", r->r13);
+	runtime·printf("r14     %X\n", r->r14);
+	runtime·printf("r15     %X\n", r->r15);
+	runtime·printf("rip     %X\n", r->rip);
+	runtime·printf("rflags  %X\n", r->rflags);
+	runtime·printf("cs      %X\n", r->cs);
+	runtime·printf("fs      %X\n", r->fs);
+	runtime·printf("gs      %X\n", r->gs);
+}
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Ucontext *uc;
+	Mcontext64 *mc;
+	Regs64 *r;
+	uintptr *sp;
+	byte *pc;
+
+	uc = context;
+	mc = uc->uc_mcontext;
+	r = &mc->ss;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Work around Leopard bug that doesn't set FPE_INTDIV.
+		// Look at instruction to see if it is a divide.
+		// Not necessary in Snow Leopard (si_code will be != 0).
+		if(sig == SIGFPE && info->si_code == 0) {
+			pc = (byte*)r->rip;
+			if((pc[0]&0xF0) == 0x40)	// 64-bit REX prefix
+				pc++;
+			else if(pc[0] == 0x66)	// 16-bit instruction prefix
+				pc++;
+			if(pc[0] == 0xF6 || pc[0] == 0xF7)
+				info->si_code = FPE_INTDIV;
+		}
+		
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = (uintptr)info->si_addr;
+		gp->sigpc = r->rip;
+		
+		// Only push runtime·sigpanic if r->rip != 0.
+		// If r->rip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->rip != 0) {
+			sp = (uintptr*)r->rsp;
+			*--sp = r->rip;
+			r->rsp = (uintptr)sp;
+		}
+		r->rip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG){
+		runtime·printf("Signal %d\n", sig);
+	}else{
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+	}
+
+	runtime·printf("pc: %X\n", r->rip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+void
+runtime·sigignore(int32, Siginfo*, void*)
+{
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	StackT st;
+
+	st.ss_sp = p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	sa.sa_tramp = runtime·sigtramp;	// runtime·sigtramp's job is to call into real handler
+	*(uintptr*)sa.__sigaction_u = (uintptr)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_freebsd_386.c b/src/pkg/runtime/signal_freebsd_386.c
new file mode 100644
index 0000000..ff4aaab
--- /dev/null
+++ b/src/pkg/runtime/signal_freebsd_386.c
@@ -0,0 +1,193 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*__sa_handler)(int32);
+		void    (*__sa_sigaction)(int32, Siginfo*, void *);
+	} __sigaction_u;		/* signal handler */
+	int32	sa_flags;		/* see signal options below */
+	int64	sa_mask;		/* signal mask to apply */
+} Sigaction;
+
+void
+runtime·dumpregs(Mcontext *r)
+{
+	runtime·printf("eax     %x\n", r->mc_eax);
+	runtime·printf("ebx     %x\n", r->mc_ebx);
+	runtime·printf("ecx     %x\n", r->mc_ecx);
+	runtime·printf("edx     %x\n", r->mc_edx);
+	runtime·printf("edi     %x\n", r->mc_edi);
+	runtime·printf("esi     %x\n", r->mc_esi);
+	runtime·printf("ebp     %x\n", r->mc_ebp);
+	runtime·printf("esp     %x\n", r->mc_esp);
+	runtime·printf("eip     %x\n", r->mc_eip);
+	runtime·printf("eflags  %x\n", r->mc_eflags);
+	runtime·printf("cs      %x\n", r->mc_cs);
+	runtime·printf("fs      %x\n", r->mc_fs);
+	runtime·printf("gs      %x\n", r->mc_gs);
+}
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Ucontext *uc;
+	Mcontext *r;
+	uintptr *sp;
+
+	uc = context;
+	r = &uc->uc_mcontext;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->mc_eip, (uint8*)r->mc_esp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = (uintptr)info->si_addr;
+		gp->sigpc = r->mc_eip;
+
+		// Only push runtime·sigpanic if r->mc_eip != 0.
+		// If r->mc_eip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->mc_eip != 0) {
+			sp = (uintptr*)r->mc_esp;
+			*--sp = r->mc_eip;
+			r->mc_esp = (uintptr)sp;
+		}
+		r->mc_eip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%X\n", r->mc_eip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->mc_eip, (void*)r->mc_esp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+// Called from kernel on signal stack, so no stack split.
+#pragma textflag 7
+void
+runtime·sigignore(void)
+{
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (int8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	if (fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_freebsd_amd64.c b/src/pkg/runtime/signal_freebsd_amd64.c
new file mode 100644
index 0000000..2683f4f
--- /dev/null
+++ b/src/pkg/runtime/signal_freebsd_amd64.c
@@ -0,0 +1,201 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*__sa_handler)(int32);
+		void    (*__sa_sigaction)(int32, Siginfo*, void *);
+	} __sigaction_u;		/* signal handler */
+	int32	sa_flags;		/* see signal options below */
+	int64	sa_mask;		/* signal mask to apply */
+} Sigaction;
+
+void
+runtime·dumpregs(Mcontext *r)
+{
+	runtime·printf("rax     %X\n", r->mc_rax);
+	runtime·printf("rbx     %X\n", r->mc_rbx);
+	runtime·printf("rcx     %X\n", r->mc_rcx);
+	runtime·printf("rdx     %X\n", r->mc_rdx);
+	runtime·printf("rdi     %X\n", r->mc_rdi);
+	runtime·printf("rsi     %X\n", r->mc_rsi);
+	runtime·printf("rbp     %X\n", r->mc_rbp);
+	runtime·printf("rsp     %X\n", r->mc_rsp);
+	runtime·printf("r8      %X\n", r->mc_r8 );
+	runtime·printf("r9      %X\n", r->mc_r9 );
+	runtime·printf("r10     %X\n", r->mc_r10);
+	runtime·printf("r11     %X\n", r->mc_r11);
+	runtime·printf("r12     %X\n", r->mc_r12);
+	runtime·printf("r13     %X\n", r->mc_r13);
+	runtime·printf("r14     %X\n", r->mc_r14);
+	runtime·printf("r15     %X\n", r->mc_r15);
+	runtime·printf("rip     %X\n", r->mc_rip);
+	runtime·printf("rflags  %X\n", r->mc_flags);
+	runtime·printf("cs      %X\n", r->mc_cs);
+	runtime·printf("fs      %X\n", r->mc_fs);
+	runtime·printf("gs      %X\n", r->mc_gs);
+}
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Ucontext *uc;
+	Mcontext *r;
+	uintptr *sp;
+
+	uc = context;
+	r = &uc->uc_mcontext;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->mc_rip, (uint8*)r->mc_rsp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = (uintptr)info->si_addr;
+		gp->sigpc = r->mc_rip;
+
+		// Only push runtime·sigpanic if r->mc_rip != 0.
+		// If r->mc_rip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->mc_rip != 0) {
+			sp = (uintptr*)r->mc_rsp;
+			*--sp = r->mc_rip;
+			r->mc_rsp = (uintptr)sp;
+		}
+		r->mc_rip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%X\n", r->mc_rip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->mc_rip, (void*)r->mc_rsp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+// Called from kernel on signal stack, so no stack split.
+#pragma textflag 7
+void
+runtime·sigignore(void)
+{
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (int8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	if (fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_linux_386.c b/src/pkg/runtime/signal_linux_386.c
new file mode 100644
index 0000000..4f3abce
--- /dev/null
+++ b/src/pkg/runtime/signal_linux_386.c
@@ -0,0 +1,208 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+void
+runtime·dumpregs(Sigcontext *r)
+{
+	runtime·printf("eax     %x\n", r->eax);
+	runtime·printf("ebx     %x\n", r->ebx);
+	runtime·printf("ecx     %x\n", r->ecx);
+	runtime·printf("edx     %x\n", r->edx);
+	runtime·printf("edi     %x\n", r->edi);
+	runtime·printf("esi     %x\n", r->esi);
+	runtime·printf("ebp     %x\n", r->ebp);
+	runtime·printf("esp     %x\n", r->esp);
+	runtime·printf("eip     %x\n", r->eip);
+	runtime·printf("eflags  %x\n", r->eflags);
+	runtime·printf("cs      %x\n", r->cs);
+	runtime·printf("fs      %x\n", r->fs);
+	runtime·printf("gs      %x\n", r->gs);
+}
+
+/*
+ * This assembler routine takes the args from registers, puts them on the stack,
+ * and calls sighandler().
+ */
+extern void runtime·sigtramp(void);
+extern void runtime·sigignore(void);	// just returns
+extern void runtime·sigreturn(void);	// calls runtime·sigreturn
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Ucontext *uc;
+	Sigcontext *r;
+	uintptr *sp;
+
+	uc = context;
+	r = &uc->uc_mcontext;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = ((uintptr*)info)[3];
+		gp->sigpc = r->eip;
+
+		// Only push runtime·sigpanic if r->eip != 0.
+		// If r->eip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->eip != 0) {
+			sp = (uintptr*)r->esp;
+			*--sp = r->eip;
+			r->esp = (uintptr)sp;
+		}
+		r->eip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%X\n", r->eip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	sa.sa_restorer = (void*)runtime·sigreturn;
+	if(fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.k_sa_handler = fn;
+	runtime·rt_sigaction(i, &sa, nil, 8);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
+
+#define AT_NULL		0
+#define AT_SYSINFO	32
+extern uint32 runtime·_vdso;
+
+#pragma textflag 7
+void runtime·linux_setup_vdso(int32 argc, void *argv_list)
+{
+	byte **argv = &argv_list;
+	byte **envp;
+	uint32 *auxv;
+
+	// skip envp to get to ELF auxiliary vector.
+	for(envp = &argv[argc+1]; *envp != nil; envp++)
+		;
+	envp++;
+	
+	for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
+		if(auxv[0] == AT_SYSINFO) {
+			runtime·_vdso = auxv[1];
+			break;
+		}
+	}		
+}
diff --git a/src/pkg/runtime/signal_linux_amd64.c b/src/pkg/runtime/signal_linux_amd64.c
new file mode 100644
index 0000000..937d5c3
--- /dev/null
+++ b/src/pkg/runtime/signal_linux_amd64.c
@@ -0,0 +1,194 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+void
+runtime·dumpregs(Sigcontext *r)
+{
+	runtime·printf("rax     %X\n", r->rax);
+	runtime·printf("rbx     %X\n", r->rbx);
+	runtime·printf("rcx     %X\n", r->rcx);
+	runtime·printf("rdx     %X\n", r->rdx);
+	runtime·printf("rdi     %X\n", r->rdi);
+	runtime·printf("rsi     %X\n", r->rsi);
+	runtime·printf("rbp     %X\n", r->rbp);
+	runtime·printf("rsp     %X\n", r->rsp);
+	runtime·printf("r8      %X\n", r->r8 );
+	runtime·printf("r9      %X\n", r->r9 );
+	runtime·printf("r10     %X\n", r->r10);
+	runtime·printf("r11     %X\n", r->r11);
+	runtime·printf("r12     %X\n", r->r12);
+	runtime·printf("r13     %X\n", r->r13);
+	runtime·printf("r14     %X\n", r->r14);
+	runtime·printf("r15     %X\n", r->r15);
+	runtime·printf("rip     %X\n", r->rip);
+	runtime·printf("rflags  %X\n", r->eflags);
+	runtime·printf("cs      %X\n", (uint64)r->cs);
+	runtime·printf("fs      %X\n", (uint64)r->fs);
+	runtime·printf("gs      %X\n", (uint64)r->gs);
+}
+
+/*
+ * This assembler routine takes the args from registers, puts them on the stack,
+ * and calls sighandler().
+ */
+extern void runtime·sigtramp(void);
+extern void runtime·sigignore(void);	// just returns
+extern void runtime·sigreturn(void);	// calls runtime·sigreturn
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Ucontext *uc;
+	Mcontext *mc;
+	Sigcontext *r;
+	uintptr *sp;
+
+	uc = context;
+	mc = &uc->uc_mcontext;
+	r = (Sigcontext*)mc;	// same layout, more conveient names
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = ((uintptr*)info)[2];
+		gp->sigpc = r->rip;
+
+		// Only push runtime·sigpanic if r->rip != 0.
+		// If r->rip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->rip != 0) {
+			sp = (uintptr*)r->rsp;
+			*--sp = r->rip;
+			r->rsp = (uintptr)sp;
+		}
+		r->rip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%X\n", r->rip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	sa.sa_restorer = (void*)runtime·sigreturn;
+	if(fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.sa_handler = fn;
+	runtime·rt_sigaction(i, &sa, nil, 8);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_linux_arm.c b/src/pkg/runtime/signal_linux_arm.c
new file mode 100644
index 0000000..b32ec7a
--- /dev/null
+++ b/src/pkg/runtime/signal_linux_arm.c
@@ -0,0 +1,189 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+void
+runtime·dumpregs(Sigcontext *r)
+{
+	runtime·printf("trap    %x\n", r->trap_no);
+	runtime·printf("error   %x\n", r->error_code);
+	runtime·printf("oldmask %x\n", r->oldmask);
+	runtime·printf("r0      %x\n", r->arm_r0);
+	runtime·printf("r1      %x\n", r->arm_r1);
+	runtime·printf("r2      %x\n", r->arm_r2);
+	runtime·printf("r3      %x\n", r->arm_r3);
+	runtime·printf("r4      %x\n", r->arm_r4);
+	runtime·printf("r5      %x\n", r->arm_r5);
+	runtime·printf("r6      %x\n", r->arm_r6);
+	runtime·printf("r7      %x\n", r->arm_r7);
+	runtime·printf("r8      %x\n", r->arm_r8);
+	runtime·printf("r9      %x\n", r->arm_r9);
+	runtime·printf("r10     %x\n", r->arm_r10);
+	runtime·printf("fp      %x\n", r->arm_fp);
+	runtime·printf("ip      %x\n", r->arm_ip);
+	runtime·printf("sp      %x\n", r->arm_sp);
+	runtime·printf("lr      %x\n", r->arm_lr);
+	runtime·printf("pc      %x\n", r->arm_pc);
+	runtime·printf("cpsr    %x\n", r->arm_cpsr);
+	runtime·printf("fault   %x\n", r->fault_address);
+}
+
+/*
+ * This assembler routine takes the args from registers, puts them on the stack,
+ * and calls sighandler().
+ */
+extern void runtime·sigtramp(void);
+extern void runtime·sigignore(void);	// just returns
+extern void runtime·sigreturn(void);	// calls runtime·sigreturn
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Ucontext *uc;
+	Sigcontext *r;
+
+	uc = context;
+	r = &uc->uc_mcontext;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = r->fault_address;
+		gp->sigpc = r->arm_pc;
+
+		// If this is a leaf function, we do smash LR,
+		// but we're not going back there anyway.
+		// Don't bother smashing if r->arm_pc is 0,
+		// which is probably a call to a nil func: the
+		// old link register is more useful in the stack trace.
+		if(r->arm_pc != 0)
+			r->arm_lr = r->arm_pc;
+		r->arm_pc = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%x\n", r->arm_pc);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp);
+		runtime·tracebackothers(gp);
+		runtime·printf("\n");
+		runtime·dumpregs(r);
+	}
+
+//	breakpoint();
+	runtime·exit(2);
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	sa.sa_restorer = (void*)runtime·sigreturn;
+	if(fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.sa_handler = fn;
+	runtime·rt_sigaction(i, &sa, nil, 8);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_netbsd_386.c b/src/pkg/runtime/signal_netbsd_386.c
new file mode 100644
index 0000000..74fa1d4
--- /dev/null
+++ b/src/pkg/runtime/signal_netbsd_386.c
@@ -0,0 +1,189 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*__sa_handler)(int32);
+		void    (*__sa_sigaction)(int32, Siginfo*, void *);
+	} __sigaction_u;		/* signal handler */
+	uint32	sa_mask;		/* signal mask to apply */
+	int32	sa_flags;		/* see signal options below */
+} Sigaction;
+
+void
+runtime·dumpregs(Sigcontext *r)
+{
+	runtime·printf("eax     %x\n", r->sc_eax);
+	runtime·printf("ebx     %x\n", r->sc_ebx);
+	runtime·printf("ecx     %x\n", r->sc_ecx);
+	runtime·printf("edx     %x\n", r->sc_edx);
+	runtime·printf("edi     %x\n", r->sc_edi);
+	runtime·printf("esi     %x\n", r->sc_esi);
+	runtime·printf("ebp     %x\n", r->sc_ebp);
+	runtime·printf("esp     %x\n", r->sc_esp);
+	runtime·printf("eip     %x\n", r->sc_eip);
+	runtime·printf("eflags  %x\n", r->sc_eflags);
+	runtime·printf("cs      %x\n", r->sc_cs);
+	runtime·printf("fs      %x\n", r->sc_fs);
+	runtime·printf("gs      %x\n", r->sc_gs);
+}
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Sigcontext *r = context;
+	uintptr *sp;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->sc_eip, (uint8*)r->sc_esp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = *(uintptr*)((byte*)info + 12); /* si_addr */
+		gp->sigpc = r->sc_eip;
+
+		// Only push runtime·sigpanic if r->sc_eip != 0.
+		// If r->sc_eip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->sc_eip != 0) {
+			sp = (uintptr*)r->sc_esp;
+			*--sp = r->sc_eip;
+			r->sc_esp = (uintptr)sp;
+		}
+		r->sc_eip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%X\n", r->sc_eip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->sc_eip, (void*)r->sc_esp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+// Called from kernel on signal stack, so no stack split.
+#pragma textflag 7
+void
+runtime·sigignore(void)
+{
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (int8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	if (fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_netbsd_amd64.c b/src/pkg/runtime/signal_netbsd_amd64.c
new file mode 100644
index 0000000..6c69fa7
--- /dev/null
+++ b/src/pkg/runtime/signal_netbsd_amd64.c
@@ -0,0 +1,199 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*__sa_handler)(int32);
+		void    (*__sa_sigaction)(int32, Siginfo*, void *);
+	} __sigaction_u;		/* signal handler */
+	uint32	sa_mask;		/* signal mask to apply */
+	int32	sa_flags;		/* see signal options below */
+} Sigaction;
+
+void
+runtime·dumpregs(Sigcontext *r)
+{
+	runtime·printf("rax     %X\n", r->sc_rax);
+	runtime·printf("rbx     %X\n", r->sc_rbx);
+	runtime·printf("rcx     %X\n", r->sc_rcx);
+	runtime·printf("rdx     %X\n", r->sc_rdx);
+	runtime·printf("rdi     %X\n", r->sc_rdi);
+	runtime·printf("rsi     %X\n", r->sc_rsi);
+	runtime·printf("rbp     %X\n", r->sc_rbp);
+	runtime·printf("rsp     %X\n", r->sc_rsp);
+	runtime·printf("r8      %X\n", r->sc_r8);
+	runtime·printf("r9      %X\n", r->sc_r9);
+	runtime·printf("r10     %X\n", r->sc_r10);
+	runtime·printf("r11     %X\n", r->sc_r11);
+	runtime·printf("r12     %X\n", r->sc_r12);
+	runtime·printf("r13     %X\n", r->sc_r13);
+	runtime·printf("r14     %X\n", r->sc_r14);
+	runtime·printf("r15     %X\n", r->sc_r15);
+	runtime·printf("rip     %X\n", r->sc_rip);
+	runtime·printf("rflags  %X\n", r->sc_rflags);
+	runtime·printf("cs      %X\n", r->sc_cs);
+	runtime·printf("fs      %X\n", r->sc_fs);
+	runtime·printf("gs      %X\n", r->sc_gs);
+}
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Sigcontext *r = context;
+	uintptr *sp;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->sc_rip,
+			(uint8*)r->sc_rsp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = *(uintptr*)((byte*)info + 16); /* si_addr */
+		gp->sigpc = r->sc_rip;
+
+		// Only push runtime·sigpanic if r->mc_rip != 0.
+		// If r->mc_rip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->sc_rip != 0) {
+			sp = (uintptr*)r->sc_rsp;
+			*--sp = r->sc_rip;
+			r->sc_rsp = (uintptr)sp;
+		}
+		r->sc_rip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig)
+		|| (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%X\n", r->sc_rip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->sc_rip, (void*)r->sc_rsp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+// Called from kernel on signal stack, so no stack split.
+#pragma textflag 7
+void
+runtime·sigignore(void)
+{
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (int8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	if (fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_openbsd_386.c b/src/pkg/runtime/signal_openbsd_386.c
new file mode 100644
index 0000000..74fa1d4
--- /dev/null
+++ b/src/pkg/runtime/signal_openbsd_386.c
@@ -0,0 +1,189 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*__sa_handler)(int32);
+		void    (*__sa_sigaction)(int32, Siginfo*, void *);
+	} __sigaction_u;		/* signal handler */
+	uint32	sa_mask;		/* signal mask to apply */
+	int32	sa_flags;		/* see signal options below */
+} Sigaction;
+
+void
+runtime·dumpregs(Sigcontext *r)
+{
+	runtime·printf("eax     %x\n", r->sc_eax);
+	runtime·printf("ebx     %x\n", r->sc_ebx);
+	runtime·printf("ecx     %x\n", r->sc_ecx);
+	runtime·printf("edx     %x\n", r->sc_edx);
+	runtime·printf("edi     %x\n", r->sc_edi);
+	runtime·printf("esi     %x\n", r->sc_esi);
+	runtime·printf("ebp     %x\n", r->sc_ebp);
+	runtime·printf("esp     %x\n", r->sc_esp);
+	runtime·printf("eip     %x\n", r->sc_eip);
+	runtime·printf("eflags  %x\n", r->sc_eflags);
+	runtime·printf("cs      %x\n", r->sc_cs);
+	runtime·printf("fs      %x\n", r->sc_fs);
+	runtime·printf("gs      %x\n", r->sc_gs);
+}
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Sigcontext *r = context;
+	uintptr *sp;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->sc_eip, (uint8*)r->sc_esp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = *(uintptr*)((byte*)info + 12); /* si_addr */
+		gp->sigpc = r->sc_eip;
+
+		// Only push runtime·sigpanic if r->sc_eip != 0.
+		// If r->sc_eip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->sc_eip != 0) {
+			sp = (uintptr*)r->sc_esp;
+			*--sp = r->sc_eip;
+			r->sc_esp = (uintptr)sp;
+		}
+		r->sc_eip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig) || (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%X\n", r->sc_eip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->sc_eip, (void*)r->sc_esp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+// Called from kernel on signal stack, so no stack split.
+#pragma textflag 7
+void
+runtime·sigignore(void)
+{
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (int8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	if (fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_openbsd_amd64.c b/src/pkg/runtime/signal_openbsd_amd64.c
new file mode 100644
index 0000000..6c69fa7
--- /dev/null
+++ b/src/pkg/runtime/signal_openbsd_amd64.c
@@ -0,0 +1,199 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+	union {
+		void    (*__sa_handler)(int32);
+		void    (*__sa_sigaction)(int32, Siginfo*, void *);
+	} __sigaction_u;		/* signal handler */
+	uint32	sa_mask;		/* signal mask to apply */
+	int32	sa_flags;		/* see signal options below */
+} Sigaction;
+
+void
+runtime·dumpregs(Sigcontext *r)
+{
+	runtime·printf("rax     %X\n", r->sc_rax);
+	runtime·printf("rbx     %X\n", r->sc_rbx);
+	runtime·printf("rcx     %X\n", r->sc_rcx);
+	runtime·printf("rdx     %X\n", r->sc_rdx);
+	runtime·printf("rdi     %X\n", r->sc_rdi);
+	runtime·printf("rsi     %X\n", r->sc_rsi);
+	runtime·printf("rbp     %X\n", r->sc_rbp);
+	runtime·printf("rsp     %X\n", r->sc_rsp);
+	runtime·printf("r8      %X\n", r->sc_r8);
+	runtime·printf("r9      %X\n", r->sc_r9);
+	runtime·printf("r10     %X\n", r->sc_r10);
+	runtime·printf("r11     %X\n", r->sc_r11);
+	runtime·printf("r12     %X\n", r->sc_r12);
+	runtime·printf("r13     %X\n", r->sc_r13);
+	runtime·printf("r14     %X\n", r->sc_r14);
+	runtime·printf("r15     %X\n", r->sc_r15);
+	runtime·printf("rip     %X\n", r->sc_rip);
+	runtime·printf("rflags  %X\n", r->sc_rflags);
+	runtime·printf("cs      %X\n", r->sc_cs);
+	runtime·printf("fs      %X\n", r->sc_fs);
+	runtime·printf("gs      %X\n", r->sc_gs);
+}
+
+String
+runtime·signame(int32 sig)
+{
+	if(sig < 0 || sig >= NSIG)
+		return runtime·emptystring;
+	return runtime·gostringnocopy((byte*)runtime·sigtab[sig].name);
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+	Sigcontext *r = context;
+	uintptr *sp;
+
+	if(sig == SIGPROF) {
+		runtime·sigprof((uint8*)r->sc_rip,
+			(uint8*)r->sc_rsp, nil, gp);
+		return;
+	}
+
+	if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = sig;
+		gp->sigcode0 = info->si_code;
+		gp->sigcode1 = *(uintptr*)((byte*)info + 16); /* si_addr */
+		gp->sigpc = r->sc_rip;
+
+		// Only push runtime·sigpanic if r->mc_rip != 0.
+		// If r->mc_rip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->sc_rip != 0) {
+			sp = (uintptr*)r->sc_rsp;
+			*--sp = r->sc_rip;
+			r->sc_rsp = (uintptr)sp;
+		}
+		r->sc_rip = (uintptr)runtime·sigpanic;
+		return;
+	}
+
+	if(runtime·sigtab[sig].flags & SigQueue) {
+		if(runtime·sigsend(sig)
+		|| (runtime·sigtab[sig].flags & SigIgnore))
+			return;
+		runtime·exit(2);	// SIGINT, SIGTERM, etc
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	if(sig < 0 || sig >= NSIG)
+		runtime·printf("Signal %d\n", sig);
+	else
+		runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+	runtime·printf("PC=%X\n", r->sc_rip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->sc_rip, (void*)r->sc_rsp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+}
+
+// Called from kernel on signal stack, so no stack split.
+#pragma textflag 7
+void
+runtime·sigignore(void)
+{
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	Sigaltstack st;
+
+	st.ss_sp = (int8*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	runtime·sigaltstack(&st, nil);
+}
+
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+	Sigaction sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~0ULL;
+	if (fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	sa.__sigaction_u.__sa_sigaction = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·initsig(int32 queue)
+{
+	int32 i;
+	void *fn;
+
+	runtime·siginit();
+
+	for(i = 0; i<NSIG; i++) {
+		if(runtime·sigtab[i].flags) {
+			if((runtime·sigtab[i].flags & SigQueue) != queue)
+				continue;
+			if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+				fn = runtime·sighandler;
+			else
+				fn = runtime·sigignore;
+			sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	Itimerval it;
+	
+	runtime·memclr((byte*)&it, sizeof it);
+	if(hz == 0) {
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+		sigaction(SIGPROF, SIG_IGN, true);
+	} else {
+		sigaction(SIGPROF, runtime·sighandler, true);
+		it.it_interval.tv_sec = 0;
+		it.it_interval.tv_usec = 1000000 / hz;
+		it.it_value = it.it_interval;
+		runtime·setitimer(ITIMER_PROF, &it, nil);
+	}
+	m->profilehz = hz;
+}
+
+void
+os·sigpipe(void)
+{
+	sigaction(SIGPIPE, SIG_DFL, false);
+	runtime·raisesigpipe();
+}
diff --git a/src/pkg/runtime/signal_plan9_386.c b/src/pkg/runtime/signal_plan9_386.c
new file mode 100644
index 0000000..c0b759c
--- /dev/null
+++ b/src/pkg/runtime/signal_plan9_386.c
@@ -0,0 +1,19 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file. 
+
+#include "runtime.h"
+
+String
+runtime·signame(int32)
+{
+	return runtime·emptystring;
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	// TODO: Enable profiling interrupts.
+	
+	m->profilehz = hz;
+}
diff --git a/src/pkg/runtime/signal_windows_386.c b/src/pkg/runtime/signal_windows_386.c
new file mode 100644
index 0000000..48d2a8b
--- /dev/null
+++ b/src/pkg/runtime/signal_windows_386.c
@@ -0,0 +1,93 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+void
+runtime·dumpregs(Context *r)
+{
+	runtime·printf("eax     %x\n", r->Eax);
+	runtime·printf("ebx     %x\n", r->Ebx);
+	runtime·printf("ecx     %x\n", r->Ecx);
+	runtime·printf("edx     %x\n", r->Edx);
+	runtime·printf("edi     %x\n", r->Edi);
+	runtime·printf("esi     %x\n", r->Esi);
+	runtime·printf("ebp     %x\n", r->Ebp);
+	runtime·printf("esp     %x\n", r->Esp);
+	runtime·printf("eip     %x\n", r->Eip);
+	runtime·printf("eflags  %x\n", r->EFlags);
+	runtime·printf("cs      %x\n", r->SegCs);
+	runtime·printf("fs      %x\n", r->SegFs);
+	runtime·printf("gs      %x\n", r->SegGs);
+}
+
+void
+runtime·initsig(int32)
+{
+	runtime·siginit();
+}
+
+uint32
+runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
+{
+	uintptr *sp;
+
+	switch(info->ExceptionCode) {
+	case EXCEPTION_BREAKPOINT:
+		r->Eip--;	// because 8l generates 2 bytes for INT3
+		return 1;
+	}
+
+	if(gp != nil && runtime·issigpanic(info->ExceptionCode)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = info->ExceptionCode;
+		gp->sigcode0 = info->ExceptionInformation[0];
+		gp->sigcode1 = info->ExceptionInformation[1];
+		gp->sigpc = r->Eip;
+
+		// Only push runtime·sigpanic if r->eip != 0.
+		// If r->eip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->Eip != 0) {
+			sp = (uintptr*)r->Esp;
+			*--sp = r->Eip;
+			r->Esp = (uintptr)sp;
+		}
+		r->Eip = (uintptr)runtime·sigpanic;
+		return 0;
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	runtime·printf("Exception %x %p %p\n", info->ExceptionCode,
+		info->ExceptionInformation[0], info->ExceptionInformation[1]);
+
+	runtime·printf("PC=%x\n", r->Eip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, m->curg);
+		runtime·tracebackothers(m->curg);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+	return 0;
+}
+
+void
+runtime·dosigprof(Context *r, G *gp)
+{
+	runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp);
+}
diff --git a/src/pkg/runtime/signal_windows_amd64.c b/src/pkg/runtime/signal_windows_amd64.c
new file mode 100644
index 0000000..92cdb80
--- /dev/null
+++ b/src/pkg/runtime/signal_windows_amd64.c
@@ -0,0 +1,106 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+extern void *runtime·sigtramp;
+
+void
+runtime·dumpregs(Context *r)
+{
+	runtime·printf("rax     %X\n", r->Rax);
+	runtime·printf("rbx     %X\n", r->Rbx);
+	runtime·printf("rcx     %X\n", r->Rcx);
+	runtime·printf("rdx     %X\n", r->Rdx);
+	runtime·printf("rdi     %X\n", r->Rdi);
+	runtime·printf("rsi     %X\n", r->Rsi);
+	runtime·printf("rbp     %X\n", r->Rbp);
+	runtime·printf("rsp     %X\n", r->Rsp);
+	runtime·printf("r8      %X\n", r->R8 );
+	runtime·printf("r9      %X\n", r->R9 );
+	runtime·printf("r10     %X\n", r->R10);
+	runtime·printf("r11     %X\n", r->R11);
+	runtime·printf("r12     %X\n", r->R12);
+	runtime·printf("r13     %X\n", r->R13);
+	runtime·printf("r14     %X\n", r->R14);
+	runtime·printf("r15     %X\n", r->R15);
+	runtime·printf("rip     %X\n", r->Rip);
+	runtime·printf("rflags  %X\n", r->EFlags);
+	runtime·printf("cs      %X\n", (uint64)r->SegCs);
+	runtime·printf("fs      %X\n", (uint64)r->SegFs);
+	runtime·printf("gs      %X\n", (uint64)r->SegGs);
+}
+
+void
+runtime·initsig(int32)
+{
+	runtime·siginit();
+	// following line keeps sigtramp alive at link stage
+	// if there's a better way please write it here
+	void *p = runtime·sigtramp;
+	USED(p);
+}
+
+uint32
+runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
+{
+	uintptr *sp;
+
+	switch(info->ExceptionCode) {
+	case EXCEPTION_BREAKPOINT:
+		return 1;
+	}
+
+	if(gp != nil && runtime·issigpanic(info->ExceptionCode)) {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp->sig = info->ExceptionCode;
+		gp->sigcode0 = info->ExceptionInformation[0];
+		gp->sigcode1 = info->ExceptionInformation[1];
+		gp->sigpc = r->Rip;
+
+		// Only push runtime·sigpanic if r->rip != 0.
+		// If r->rip == 0, probably panicked because of a
+		// call to a nil func.  Not pushing that onto sp will
+		// make the trace look like a call to runtime·sigpanic instead.
+		// (Otherwise the trace will end at runtime·sigpanic and we
+		// won't get to see who faulted.)
+		if(r->Rip != 0) {
+			sp = (uintptr*)r->Rsp;
+			*--sp = r->Rip;
+			r->Rsp = (uintptr)sp;
+		}
+		r->Rip = (uintptr)runtime·sigpanic;
+		return 0;
+	}
+
+	if(runtime·panicking)	// traceback already printed
+		runtime·exit(2);
+	runtime·panicking = 1;
+
+	runtime·printf("Exception %x %p %p\n", info->ExceptionCode,
+		info->ExceptionInformation[0], info->ExceptionInformation[1]);
+
+	runtime·printf("PC=%X\n", r->Rip);
+	runtime·printf("\n");
+
+	if(runtime·gotraceback()){
+		runtime·traceback((void*)r->Rip, (void*)r->Rsp, 0, gp);
+		runtime·tracebackothers(gp);
+		runtime·dumpregs(r);
+	}
+
+	runtime·exit(2);
+	return 0;
+}
+
+void
+runtime·dosigprof(Context *r, G *gp)
+{
+	runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp);
+}
diff --git a/src/pkg/runtime/darwin/signals.h b/src/pkg/runtime/signals_darwin.h
similarity index 100%
rename from src/pkg/runtime/darwin/signals.h
rename to src/pkg/runtime/signals_darwin.h
diff --git a/src/pkg/runtime/freebsd/signals.h b/src/pkg/runtime/signals_freebsd.h
similarity index 100%
copy from src/pkg/runtime/freebsd/signals.h
copy to src/pkg/runtime/signals_freebsd.h
diff --git a/src/pkg/runtime/signals_linux.h b/src/pkg/runtime/signals_linux.h
new file mode 100644
index 0000000..1fc5f8c
--- /dev/null
+++ b/src/pkg/runtime/signals_linux.h
@@ -0,0 +1,51 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define C SigCatch
+#define I SigIgnore
+#define R SigRestart
+#define Q SigQueue
+#define P SigPanic
+
+SigTab runtime·sigtab[] = {
+	/* 0 */	0, "SIGNONE: no trap",
+	/* 1 */	Q+R, "SIGHUP: terminal line hangup",
+	/* 2 */	Q+R, "SIGINT: interrupt",
+	/* 3 */	C, "SIGQUIT: quit",
+	/* 4 */	C, "SIGILL: illegal instruction",
+	/* 5 */	C, "SIGTRAP: trace trap",
+	/* 6 */	C, "SIGABRT: abort",
+	/* 7 */	C+P, "SIGBUS: bus error",
+	/* 8 */	C+P, "SIGFPE: floating-point exception",
+	/* 9 */	0, "SIGKILL: kill",
+	/* 10 */	Q+I+R, "SIGUSR1: user-defined signal 1",
+	/* 11 */	C+P, "SIGSEGV: segmentation violation",
+	/* 12 */	Q+I+R, "SIGUSR2: user-defined signal 2",
+	/* 13 */	I, "SIGPIPE: write to broken pipe",
+	/* 14 */	Q+I+R, "SIGALRM: alarm clock",
+	/* 15 */	Q+R, "SIGTERM: termination",
+	/* 16 */	C, "SIGSTKFLT: stack fault",
+	/* 17 */	Q+I+R, "SIGCHLD: child status has changed",
+	/* 18 */	0, "SIGCONT: continue",
+	/* 19 */	0, "SIGSTOP: stop, unblockable",
+	/* 20 */	Q+I+R, "SIGTSTP: keyboard stop",
+	/* 21 */	Q+I+R, "SIGTTIN: background read from tty",
+	/* 22 */	Q+I+R, "SIGTTOU: background write to tty",
+	/* 23 */	Q+I+R, "SIGURG: urgent condition on socket",
+	/* 24 */	Q+I+R, "SIGXCPU: cpu limit exceeded",
+	/* 25 */	Q+I+R, "SIGXFSZ: file size limit exceeded",
+	/* 26 */	Q+I+R, "SIGVTALRM: virtual alarm clock",
+	/* 27 */	Q+I+R, "SIGPROF: profiling alarm clock",
+	/* 28 */	Q+I+R, "SIGWINCH: window size change",
+	/* 29 */	Q+I+R, "SIGIO: i/o now possible",
+	/* 30 */	Q+I+R, "SIGPWR: power failure restart",
+	/* 31 */	C, "SIGSYS: bad system call",
+};
+#undef C
+#undef I
+#undef R
+#undef Q
+#undef P
+
+#define	NSIG 32
diff --git a/src/pkg/runtime/openbsd/signals.h b/src/pkg/runtime/signals_netbsd.h
similarity index 100%
rename from src/pkg/runtime/openbsd/signals.h
rename to src/pkg/runtime/signals_netbsd.h
diff --git a/src/pkg/runtime/freebsd/signals.h b/src/pkg/runtime/signals_openbsd.h
similarity index 100%
rename from src/pkg/runtime/freebsd/signals.h
rename to src/pkg/runtime/signals_openbsd.h
diff --git a/src/pkg/runtime/plan9/signals.h b/src/pkg/runtime/signals_plan9.h
similarity index 100%
rename from src/pkg/runtime/plan9/signals.h
rename to src/pkg/runtime/signals_plan9.h
diff --git a/src/pkg/runtime/windows/signals.h b/src/pkg/runtime/signals_windows.h
similarity index 100%
rename from src/pkg/runtime/windows/signals.h
rename to src/pkg/runtime/signals_windows.h
diff --git a/src/pkg/runtime/sigqueue.goc b/src/pkg/runtime/sigqueue.goc
index 504590a..3c12e5c 100644
--- a/src/pkg/runtime/sigqueue.goc
+++ b/src/pkg/runtime/sigqueue.goc
@@ -38,7 +38,7 @@
 
 package runtime
 #include "runtime.h"
-#include "defs.h"
+#include "defs_GOOS_GOARCH.h"
 
 static struct {
 	Note;
diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c
index 7053427..e5726c9 100644
--- a/src/pkg/runtime/slice.c
+++ b/src/pkg/runtime/slice.c
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "type.h"
 #include "malloc.h"
 
@@ -10,8 +11,7 @@ static	int32	debug	= 0;
 
 static	void	makeslice1(SliceType*, int32, int32, Slice*);
 static	void	growslice1(SliceType*, Slice, int32, Slice *);
-static	void	appendslice1(SliceType*, Slice, Slice, Slice*);
-	void	runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret);
+	void	runtime·copy(Slice to, Slice fm, uintptr width, int32 ret);
 
 // see also unsafe·NewArray
 // makeslice(typ *Type, len, cap int64) (ary []any);
@@ -28,13 +28,18 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
 	if(debug) {
 		runtime·printf("makeslice(%S, %D, %D); ret=",
 			*t->string, len, cap);
- 		runtime·printslice(ret);
+		runtime·printslice(ret);
 	}
 }
 
+// Dummy word to use as base pointer for make([]T, 0).
+// Since you cannot take the address of such a slice,
+// you can't tell that they all have the same base pointer.
+static uintptr zerobase;
+
 static void
 makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
-{	
+{
 	uintptr size;
 
 	size = cap*t->elem->size;
@@ -42,7 +47,9 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
 	ret->len = len;
 	ret->cap = cap;
 
-	if((t->elem->kind&KindNoPointers))
+	if(cap == 0)
+		ret->array = (byte*)&zerobase;
+	else if((t->elem->kind&KindNoPointers))
 		ret->array = runtime·mallocgc(size, FlagNoPointers, 1, 1);
 	else
 		ret->array = runtime·mal(size);
@@ -52,14 +59,31 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
 void
 runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
 {
-	appendslice1(t, x, y, &ret);
+	int32 m;
+	uintptr w;
+
+	m = x.len+y.len;
+
+	if(m < x.len)
+		runtime·throw("append: slice overflow");
+
+	if(m > x.cap)
+		growslice1(t, x, m, &ret);
+	else
+		ret = x;
+
+	w = t->elem->size;
+	runtime·memmove(ret.array + ret.len*w, y.array, y.len*w);
+	ret.len += y.len;
+	FLUSH(&ret);
 }
 
-static void
-appendslice1(SliceType *t, Slice x, Slice y, Slice *ret)
+
+// appendstr([]byte, string) []byte
+void
+runtime·appendstr(SliceType *t, Slice x, String y, Slice ret)
 {
 	int32 m;
-	uintptr w;
 
 	m = x.len+y.len;
 
@@ -67,15 +91,16 @@ appendslice1(SliceType *t, Slice x, Slice y, Slice *ret)
 		runtime·throw("append: slice overflow");
 
 	if(m > x.cap)
-		growslice1(t, x, m, ret);
+		growslice1(t, x, m, &ret);
 	else
-		*ret = x;
+		ret = x;
 
-	w = t->elem->size;
-	runtime·memmove(ret->array + ret->len*w, y.array, y.len*w);
-	ret->len += y.len;
+	runtime·memmove(ret.array + ret.len, y.str, y.len);
+	ret.len += y.len;
+	FLUSH(&ret);
 }
 
+
 // growslice(type *Type, x, []T, n int64) []T
 void
 runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
@@ -96,9 +121,9 @@ runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
 
 	if(debug) {
 		runtime·printf("growslice(%S,", *t->string);
- 		runtime·printslice(old);
+		runtime·printslice(old);
 		runtime·printf(", new cap=%D) =", cap);
- 		runtime·printslice(ret);
+		runtime·printslice(ret);
 	}
 }
 
@@ -265,9 +290,9 @@ runtime·slicearray(byte* old, uint64 nel, uint64 lb, uint64 hb, uint64 width, S
 	}
 }
 
-// slicecopy(to any, fr any, wid uint32) int
+// copy(to any, fr any, wid uint32) int
 void
-runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret)
+runtime·copy(Slice to, Slice fm, uintptr width, int32 ret)
 {
 	if(fm.len == 0 || to.len == 0 || width == 0) {
 		ret = 0;
@@ -307,11 +332,11 @@ runtime·slicestringcopy(Slice to, String fm, int32 ret)
 		ret = 0;
 		goto out;
 	}
-	
+
 	ret = fm.len;
 	if(to.len < ret)
 		ret = to.len;
-	
+
 	runtime·memmove(to.array, fm.str, ret);
 
 out:
diff --git a/src/pkg/runtime/softfloat64_test.go b/src/pkg/runtime/softfloat64_test.go
index fb7f3d3..df63010 100644
--- a/src/pkg/runtime/softfloat64_test.go
+++ b/src/pkg/runtime/softfloat64_test.go
@@ -6,7 +6,7 @@ package runtime_test
 
 import (
 	"math"
-	"rand"
+	"math/rand"
 	. "runtime"
 	"testing"
 )
diff --git a/src/pkg/runtime/softfloat_arm.c b/src/pkg/runtime/softfloat_arm.c
new file mode 100644
index 0000000..fbe0b04
--- /dev/null
+++ b/src/pkg/runtime/softfloat_arm.c
@@ -0,0 +1,525 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Software floating point interpretaton of ARM 7500 FP instructions.
+// The interpretation is not bit compatible with the 7500.
+// It uses true little-endian doubles, while the 7500 used mixed-endian.
+
+#include "runtime.h"
+
+#define CPSR 14
+#define FLAGS_N (1 << 31)
+#define FLAGS_Z (1 << 30)
+#define FLAGS_C (1 << 29)
+#define FLAGS_V (1 << 28)
+
+void	runtime·abort(void);
+void	math·sqrtC(uint64, uint64*);
+
+static	uint32	trace = 0;
+
+static void
+fabort(void)
+{
+	if (1) {
+		runtime·printf("Unsupported floating point instruction\n");
+		runtime·abort();
+	}
+}
+
+static void
+putf(uint32 reg, uint32 val)
+{
+	m->freglo[reg] = val;
+}
+
+static void
+putd(uint32 reg, uint64 val)
+{
+	m->freglo[reg] = (uint32)val;
+	m->freghi[reg] = (uint32)(val>>32);
+}
+
+static uint64
+getd(uint32 reg)
+{
+	return (uint64)m->freglo[reg] | ((uint64)m->freghi[reg]<<32);
+}
+
+static void
+fprint(void)
+{
+	uint32 i;
+	for (i = 0; i < 16; i++) {
+		runtime·printf("\tf%d:\t%X %X\n", i, m->freghi[i], m->freglo[i]);
+	}
+}
+
+static uint32
+d2f(uint64 d)
+{
+	uint32 x;
+
+	runtime·f64to32c(d, &x);
+	return x;
+}
+
+static uint64
+f2d(uint32 f)
+{
+	uint64 x;
+
+	runtime·f32to64c(f, &x);
+	return x;
+}
+
+static uint32
+fstatus(bool nan, int32 cmp)
+{
+	if(nan)
+		return FLAGS_C | FLAGS_V;
+	if(cmp == 0)
+		return FLAGS_Z | FLAGS_C;
+	if(cmp < 0)
+		return FLAGS_N;
+	return FLAGS_C;
+}
+
+// returns number of words that the fp instruction
+// is occupying, 0 if next instruction isn't float.
+static uint32
+stepflt(uint32 *pc, uint32 *regs)
+{
+	uint32 i, regd, regm, regn;
+	int32 delta;
+	uint32 *addr;
+	uint64 uval;
+	int64 sval;
+	bool nan, ok;
+	int32 cmp;
+
+	i = *pc;
+
+	if(trace)
+		runtime·printf("stepflt %p %x\n", pc, i);
+
+	// special cases
+	if((i&0xfffff000) == 0xe59fb000) {
+		// load r11 from pc-relative address.
+		// might be part of a floating point move
+		// (or might not, but no harm in simulating
+		// one instruction too many).
+		addr = (uint32*)((uint8*)pc + (i&0xfff) + 8);
+		regs[11] = addr[0];
+
+		if(trace)
+			runtime·printf("*** cpu R[%d] = *(%p) %x\n",
+				11, addr, regs[11]);
+		return 1;
+	}
+	if(i == 0xe08bb00d) {
+		// add sp to r11.
+		// might be part of a large stack offset address
+		// (or might not, but again no harm done).
+		regs[11] += regs[13];
+
+		if(trace)
+			runtime·printf("*** cpu R[%d] += R[%d] %x\n",
+				11, 13, regs[11]);
+		return 1;
+	}
+	if(i == 0xeef1fa10) {
+		regs[CPSR] = (regs[CPSR]&0x0fffffff) | m->fflag;
+
+		if(trace)
+			runtime·printf("*** fpsr R[CPSR] = F[CPSR] %x\n", regs[CPSR]);
+		return 1;
+	}
+	if((i&0xff000000) == 0xea000000) {
+		// unconditional branch
+		// can happen in the middle of floating point
+		// if the linker decides it is time to lay down
+		// a sequence of instruction stream constants.
+		delta = i&0xffffff;
+		delta = (delta<<8) >> 8;	// sign extend
+
+		if(trace)
+			runtime·printf("*** cpu PC += %x\n", (delta+2)*4);
+		return delta+2;
+	}
+
+	goto stage1;
+
+stage1:	// load/store regn is cpureg, regm is 8bit offset
+	regd = i>>12 & 0xf;
+	regn = i>>16 & 0xf;
+	regm = (i & 0xff) << 2;	// PLUS or MINUS ??
+
+	switch(i & 0xfff00f00) {
+	default:
+		goto stage2;
+
+	case 0xed900a00:	// single load
+		addr = (uint32*)(regs[regn] + regm);
+		m->freglo[regd] = addr[0];
+
+		if(trace)
+			runtime·printf("*** load F[%d] = %x\n",
+				regd, m->freglo[regd]);
+		break;
+
+	case 0xed900b00:	// double load
+		addr = (uint32*)(regs[regn] + regm);
+		m->freglo[regd] = addr[0];
+		m->freghi[regd] = addr[1];
+
+		if(trace)
+			runtime·printf("*** load D[%d] = %x-%x\n",
+				regd, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xed800a00:	// single store
+		addr = (uint32*)(regs[regn] + regm);
+		addr[0] = m->freglo[regd];
+
+		if(trace)
+			runtime·printf("*** *(%p) = %x\n",
+				addr, addr[0]);
+		break;
+
+	case 0xed800b00:	// double store
+		addr = (uint32*)(regs[regn] + regm);
+		addr[0] = m->freglo[regd];
+		addr[1] = m->freghi[regd];
+
+		if(trace)
+			runtime·printf("*** *(%p) = %x-%x\n",
+				addr, addr[1], addr[0]);
+		break;
+	}
+	return 1;
+
+stage2:	// regd, regm, regn are 4bit variables
+	regm = i>>0 & 0xf;
+	switch(i & 0xfff00ff0) {
+	default:
+		goto stage3;
+
+	case 0xf3000110:	// veor
+		m->freglo[regd] = m->freglo[regm]^m->freglo[regn];
+		m->freghi[regd] = m->freghi[regm]^m->freghi[regn];
+
+		if(trace)
+			runtime·printf("*** veor D[%d] = %x-%x\n",
+				regd, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb00b00:	// D[regd] = const(regn,regm)
+		regn = (regn<<4) | regm;
+		regm = 0x40000000UL;
+		if(regn & 0x80)
+			regm |= 0x80000000UL;
+		if(regn & 0x40)
+			regm ^= 0x7fc00000UL;
+		regm |= (regn & 0x3f) << 16;
+		m->freglo[regd] = 0;
+		m->freghi[regd] = regm;
+
+		if(trace)
+			runtime·printf("*** immed D[%d] = %x-%x\n",
+				regd, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb00a00:	// F[regd] = const(regn,regm)
+		regn = (regn<<4) | regm;
+		regm = 0x40000000UL;
+		if(regn & 0x80)
+			regm |= 0x80000000UL;
+		if(regn & 0x40)
+			regm ^= 0x7e000000UL;
+		regm |= (regn & 0x3f) << 19;
+		m->freglo[regd] = regm;
+
+		if(trace)
+			runtime·printf("*** immed D[%d] = %x\n",
+				regd, m->freglo[regd]);
+		break;
+
+	case 0xee300b00:	// D[regd] = D[regn]+D[regm]
+		runtime·fadd64c(getd(regn), getd(regm), &uval);
+		putd(regd, uval);
+
+		if(trace)
+			runtime·printf("*** add D[%d] = D[%d]+D[%d] %x-%x\n",
+				regd, regn, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xee300a00:	// F[regd] = F[regn]+F[regm]
+		runtime·fadd64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
+		m->freglo[regd] = d2f(uval);
+
+		if(trace)
+			runtime·printf("*** add F[%d] = F[%d]+F[%d] %x\n",
+				regd, regn, regm, m->freglo[regd]);
+		break;
+
+	case 0xee300b40:	// D[regd] = D[regn]-D[regm]
+		runtime·fsub64c(getd(regn), getd(regm), &uval);
+		putd(regd, uval);
+
+		if(trace)
+			runtime·printf("*** sub D[%d] = D[%d]-D[%d] %x-%x\n",
+				regd, regn, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xee300a40:	// F[regd] = F[regn]-F[regm]
+		runtime·fsub64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
+		m->freglo[regd] = d2f(uval);
+
+		if(trace)
+			runtime·printf("*** sub F[%d] = F[%d]-F[%d] %x\n",
+				regd, regn, regm, m->freglo[regd]);
+		break;
+
+	case 0xee200b00:	// D[regd] = D[regn]*D[regm]
+		runtime·fmul64c(getd(regn), getd(regm), &uval);
+		putd(regd, uval);
+
+		if(trace)
+			runtime·printf("*** mul D[%d] = D[%d]*D[%d] %x-%x\n",
+				regd, regn, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xee200a00:	// F[regd] = F[regn]*F[regm]
+		runtime·fmul64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
+		m->freglo[regd] = d2f(uval);
+
+		if(trace)
+			runtime·printf("*** mul F[%d] = F[%d]*F[%d] %x\n",
+				regd, regn, regm, m->freglo[regd]);
+		break;
+
+	case 0xee800b00:	// D[regd] = D[regn]/D[regm]
+		runtime·fdiv64c(getd(regn), getd(regm), &uval);
+		putd(regd, uval);
+
+		if(trace)
+			runtime·printf("*** div D[%d] = D[%d]/D[%d] %x-%x\n",
+				regd, regn, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xee800a00:	// F[regd] = F[regn]/F[regm]
+		runtime·fdiv64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
+		m->freglo[regd] = d2f(uval);
+
+		if(trace)
+			runtime·printf("*** div F[%d] = F[%d]/F[%d] %x\n",
+				regd, regn, regm, m->freglo[regd]);
+		break;
+
+	case 0xee000b10:	// S[regn] = R[regd] (MOVW) (regm ignored)
+		m->freglo[regn] = regs[regd];
+
+		if(trace)
+			runtime·printf("*** cpy S[%d] = R[%d] %x\n",
+				regn, regd, m->freglo[regn]);
+		break;
+
+	case 0xee100b10:	// R[regd] = S[regn] (MOVW) (regm ignored)
+		regs[regd] = m->freglo[regn];
+
+		if(trace)
+			runtime·printf("*** cpy R[%d] = S[%d] %x\n",
+				regd, regn, regs[regd]);
+		break;
+	}
+	return 1;
+
+stage3:	// regd, regm are 4bit variables
+	switch(i & 0xffff0ff0) {
+	default:
+		goto done;
+
+	case 0xeeb00a40:	// F[regd] = F[regm] (MOVF)
+		m->freglo[regd] = m->freglo[regm];
+
+		if(trace)
+			runtime·printf("*** F[%d] = F[%d] %x\n",
+				regd, regm, m->freglo[regd]);
+		break;
+
+	case 0xeeb00b40:	// D[regd] = D[regm] (MOVD)
+		m->freglo[regd] = m->freglo[regm];
+		m->freghi[regd] = m->freghi[regm];
+
+		if(trace)
+			runtime·printf("*** D[%d] = D[%d] %x-%x\n",
+				regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb10bc0:	// D[regd] = sqrt D[regm]
+		math·sqrtC(getd(regm), &uval);
+		putd(regd, uval);
+
+		if(trace)
+			runtime·printf("*** D[%d] = sqrt D[%d] %x-%x\n",
+				regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb40bc0:	// D[regd] :: D[regm] (CMPD)
+		runtime·fcmp64c(getd(regd), getd(regm), &cmp, &nan);
+		m->fflag = fstatus(nan, cmp);
+
+		if(trace)
+			runtime·printf("*** cmp D[%d]::D[%d] %x\n",
+				regd, regm, m->fflag);
+		break;
+
+	case 0xeeb40ac0:	// F[regd] :: F[regm] (CMPF)
+		runtime·fcmp64c(f2d(m->freglo[regd]), f2d(m->freglo[regm]), &cmp, &nan);
+		m->fflag = fstatus(nan, cmp);
+
+		if(trace)
+			runtime·printf("*** cmp F[%d]::F[%d] %x\n",
+				regd, regm, m->fflag);
+		break;
+
+	case 0xeeb70ac0:	// D[regd] = F[regm] (MOVFD)
+		putd(regd, f2d(m->freglo[regm]));
+
+		if(trace)
+			runtime·printf("*** f2d D[%d]=F[%d] %x-%x\n",
+				regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb70bc0:	// F[regd] = D[regm] (MOVDF)
+		m->freglo[regd] = d2f(getd(regm));
+
+		if(trace)
+			runtime·printf("*** d2f F[%d]=D[%d] %x-%x\n",
+				regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeebd0ac0:	// S[regd] = F[regm] (MOVFW)
+		runtime·f64tointc(f2d(m->freglo[regm]), &sval, &ok);
+		if(!ok || (int32)sval != sval)
+			sval = 0;
+		m->freglo[regd] = sval;
+
+		if(trace)
+			runtime·printf("*** fix S[%d]=F[%d] %x\n",
+				regd, regm, m->freglo[regd]);
+		break;
+
+	case 0xeebc0ac0:	// S[regd] = F[regm] (MOVFW.U)
+		runtime·f64tointc(f2d(m->freglo[regm]), &sval, &ok);
+		if(!ok || (uint32)sval != sval)
+			sval = 0;
+		m->freglo[regd] = sval;
+
+		if(trace)
+			runtime·printf("*** fix unsigned S[%d]=F[%d] %x\n",
+				regd, regm, m->freglo[regd]);
+		break;
+
+	case 0xeebd0bc0:	// S[regd] = D[regm] (MOVDW)
+		runtime·f64tointc(getd(regm), &sval, &ok);
+		if(!ok || (int32)sval != sval)
+			sval = 0;
+		m->freglo[regd] = sval;
+
+		if(trace)
+			runtime·printf("*** fix S[%d]=D[%d] %x\n",
+				regd, regm, m->freglo[regd]);
+		break;
+
+	case 0xeebc0bc0:	// S[regd] = D[regm] (MOVDW.U)
+		runtime·f64tointc(getd(regm), &sval, &ok);
+		if(!ok || (uint32)sval != sval)
+			sval = 0;
+		m->freglo[regd] = sval;
+
+		if(trace)
+			runtime·printf("*** fix unsigned S[%d]=D[%d] %x\n",
+				regd, regm, m->freglo[regd]);
+		break;
+
+	case 0xeeb80ac0:	// D[regd] = S[regm] (MOVWF)
+		cmp = m->freglo[regm];
+		if(cmp < 0) {
+			runtime·fintto64c(-cmp, &uval);
+			putf(regd, d2f(uval));
+			m->freglo[regd] ^= 0x80000000;
+		} else {
+			runtime·fintto64c(cmp, &uval);
+			putf(regd, d2f(uval));
+		}
+
+		if(trace)
+			runtime·printf("*** float D[%d]=S[%d] %x-%x\n",
+				regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb80a40:	// D[regd] = S[regm] (MOVWF.U)
+		runtime·fintto64c(m->freglo[regm], &uval);
+		putf(regd, d2f(uval));
+
+		if(trace)
+			runtime·printf("*** float unsigned D[%d]=S[%d] %x-%x\n",
+				regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb80bc0:	// D[regd] = S[regm] (MOVWD)
+		cmp = m->freglo[regm];
+		if(cmp < 0) {
+			runtime·fintto64c(-cmp, &uval);
+			putd(regd, uval);
+			m->freghi[regd] ^= 0x80000000;
+		} else {
+			runtime·fintto64c(cmp, &uval);
+			putd(regd, uval);
+		}
+
+		if(trace)
+			runtime·printf("*** float D[%d]=S[%d] %x-%x\n",
+				regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+
+	case 0xeeb80b40:	// D[regd] = S[regm] (MOVWD.U)
+		runtime·fintto64c(m->freglo[regm], &uval);
+		putd(regd, uval);
+
+		if(trace)
+			runtime·printf("*** float unsigned D[%d]=S[%d] %x-%x\n",
+				regd, regm, m->freghi[regd], m->freglo[regd]);
+		break;
+	}
+	return 1;
+
+done:
+	if((i&0xff000000) == 0xee000000 ||
+	   (i&0xff000000) == 0xed000000) {
+		runtime·printf("stepflt %p %x\n", pc, i);
+		fabort();
+	}
+	return 0;
+}
+
+#pragma textflag 7
+uint32*
+runtime·_sfloat2(uint32 *lr, uint32 r0)
+{
+	uint32 skip;
+
+	skip = stepflt(lr, &r0);
+	if(skip == 0) {
+		runtime·printf("sfloat2 %p %x\n", lr, *lr);
+		fabort(); // not ok to fail first instruction
+	}
+
+	lr += skip;
+	while(skip = stepflt(lr, &r0))
+		lr += skip;
+	return lr;
+}
diff --git a/src/pkg/runtime/stack.h b/src/pkg/runtime/stack.h
index 4832338..f56dac1 100644
--- a/src/pkg/runtime/stack.h
+++ b/src/pkg/runtime/stack.h
@@ -57,7 +57,7 @@ enum {
 	// to each stack below the usual guard area for OS-specific
 	// purposes like signal handling. Used on Windows because
 	// it does not use a separate stack.
-#ifdef __WINDOWS__
+#ifdef GOOS_windows
 	StackSystem = 512 * sizeof(uintptr),
 #else
 	StackSystem = 0,
diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc
index 322706c..7e1f8a1 100644
--- a/src/pkg/runtime/string.goc
+++ b/src/pkg/runtime/string.goc
@@ -4,6 +4,7 @@
 
 package runtime
 #include "runtime.h"
+#include "arch_GOARCH.h"
 #include "malloc.h"
 
 String	runtime·emptystring;
@@ -34,16 +35,18 @@ runtime·findnullw(uint16 *s)
 
 uint32 runtime·maxstring = 256;
 
-String
-runtime·gostringsize(int32 l)
+static String
+gostringsize(int32 l)
 {
 	String s;
 	uint32 ms;
 
 	if(l == 0)
 		return runtime·emptystring;
-	s.str = runtime·mal(l+1);	// leave room for NUL for C runtime (e.g., callers of getenv)
+	// leave room for NUL for C runtime (e.g., callers of getenv)
+	s.str = runtime·mallocgc(l+1, FlagNoPointers, 1, 0);
 	s.len = l;
+	s.str[l] = 0;
 	for(;;) {
 		ms = runtime·maxstring;
 		if((uint32)l <= ms || runtime·cas(&runtime·maxstring, ms, (uint32)l))
@@ -59,7 +62,7 @@ runtime·gostring(byte *str)
 	String s;
 
 	l = runtime·findnull(str);
-	s = runtime·gostringsize(l);
+	s = gostringsize(l);
 	runtime·memmove(s.str, str, l);
 	return s;
 }
@@ -69,7 +72,7 @@ runtime·gostringn(byte *str, int32 l)
 {
 	String s;
 
-	s = runtime·gostringsize(l);
+	s = gostringsize(l);
 	runtime·memmove(s.str, str, l);
 	return s;
 }
@@ -99,18 +102,23 @@ runtime·gostringnocopy(byte *str)
 String
 runtime·gostringw(uint16 *str)
 {
-	int32 n, i;
+	int32 n1, n2, i;
 	byte buf[8];
 	String s;
 
-	n = 0;
-	for(i=0; str[i]; i++)
-		n += runtime·runetochar(buf, str[i]);
-	s = runtime·gostringsize(n+4);
-	n = 0;
+	n1 = 0;
 	for(i=0; str[i]; i++)
-		n += runtime·runetochar(s.str+n, str[i]);
-	s.len = n;
+		n1 += runtime·runetochar(buf, str[i]);
+	s = gostringsize(n1+4);
+	n2 = 0;
+	for(i=0; str[i]; i++) {
+		// check for race
+		if(n2 >= n1)
+			break;
+		n2 += runtime·runetochar(s.str+n2, str[i]);
+	}
+	s.len = n2;
+	s.str[s.len] = 0;
 	return s;
 }
 
@@ -124,7 +132,7 @@ runtime·catstring(String s1, String s2)
 	if(s2.len == 0)
 		return s1;
 
-	s3 = runtime·gostringsize(s1.len + s2.len);
+	s3 = gostringsize(s1.len + s2.len);
 	runtime·memmove(s3.str, s1.str, s1.len);
 	runtime·memmove(s3.str+s1.len, s2.str, s2.len);
 	return s3;
@@ -143,7 +151,7 @@ concatstring(int32 n, String *s)
 		l += s[i].len;
 	}
 	
-	out = runtime·gostringsize(l);
+	out = gostringsize(l);
 	l = 0;
 	for(i=0; i<n; i++) {
 		runtime·memmove(out.str+l, s[i].str, s[i].len);
@@ -253,23 +261,24 @@ func slicestring1(si String, lindex int32) (so String) {
 }
 
 func intstring(v int64) (s String) {
-	s = runtime·gostringsize(8);
+	s = gostringsize(8);
 	s.len = runtime·runetochar(s.str, v);
+	s.str[s.len] = 0;
 }
 
 func slicebytetostring(b Slice) (s String) {
-	s = runtime·gostringsize(b.len);
+	s = gostringsize(b.len);
 	runtime·memmove(s.str, b.array, s.len);
 }
 
 func stringtoslicebyte(s String) (b Slice) {
-	b.array = runtime·mallocgc(s.len, FlagNoPointers, 1, 1);
+	b.array = runtime·mallocgc(s.len, FlagNoPointers, 1, 0);
 	b.len = s.len;
 	b.cap = s.len;
 	runtime·memmove(b.array, s.str, s.len);
 }
 
-func sliceinttostring(b Slice) (s String) {
+func slicerunetostring(b Slice) (s String) {
 	int32 siz1, siz2, i;
 	int32 *a;
 	byte dum[8];
@@ -280,7 +289,7 @@ func sliceinttostring(b Slice) (s String) {
 		siz1 += runtime·runetochar(dum, a[i]);
 	}
 
-	s = runtime·gostringsize(siz1+4);
+	s = gostringsize(siz1+4);
 	siz2 = 0;
 	for(i=0; i<b.len; i++) {
 		// check for race
@@ -289,15 +298,16 @@ func sliceinttostring(b Slice) (s String) {
 		siz2 += runtime·runetochar(s.str+siz2, a[i]);
 	}
 	s.len = siz2;
+	s.str[s.len] = 0;
 }
 
-func stringtosliceint(s String) (b Slice) {
+func stringtoslicerune(s String) (b Slice) {
 	int32 n;
 	int32 dum, *r;
 	uint8 *p, *ep;
 
 	// two passes.
-	// unlike sliceinttostring, no race because strings are immutable.
+	// unlike slicerunetostring, no race because strings are immutable.
 	p = s.str;
 	ep = s.str+s.len;
 	n = 0;
@@ -306,7 +316,7 @@ func stringtosliceint(s String) (b Slice) {
 		n++;
 	}
 
-	b.array = runtime·mallocgc(n*sizeof(r[0]), FlagNoPointers, 1, 1);
+	b.array = runtime·mallocgc(n*sizeof(r[0]), FlagNoPointers, 1, 0);
 	b.len = n;
 	b.cap = n;
 	p = s.str;
diff --git a/src/pkg/runtime/symtab.c b/src/pkg/runtime/symtab.c
index d0468c6..0346a42 100644
--- a/src/pkg/runtime/symtab.c
+++ b/src/pkg/runtime/symtab.c
@@ -13,9 +13,9 @@
 // and figure out exactly what we want.
 
 #include "runtime.h"
-#include "defs.h"
-#include "os.h"
-#include "arch.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "arch_GOARCH.h"
 
 extern byte pclntab[], epclntab[], symtab[], esymtab[];
 
@@ -381,6 +381,15 @@ runtime·funcline(Func *f, uintptr targetpc)
 	return line;
 }
 
+void
+runtime·funcline_go(Func *f, uintptr targetpc, String retfile, int32 retline)
+{
+	retfile = f->src;
+	retline = runtime·funcline(f, targetpc);
+	FLUSH(&retfile);
+	FLUSH(&retline);
+}
+
 static void
 buildfuncs(void)
 {
diff --git a/src/pkg/runtime/sys_darwin_386.s b/src/pkg/runtime/sys_darwin_386.s
new file mode 100644
index 0000000..24eac76
--- /dev/null
+++ b/src/pkg/runtime/sys_darwin_386.s
@@ -0,0 +1,370 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// System calls and other sys.stuff for 386, Darwin
+// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
+// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
+
+#include "zasm_GOOS_GOARCH.h"
+
+TEXT runtime·notok(SB),7,$0
+	MOVL	$0xf1, 0xf1
+	RET
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$0
+	MOVL	$1, AX
+	INT	$0x80
+	CALL	runtime·notok(SB)
+	RET
+
+// Exit this OS thread (like pthread_exit, which eventually
+// calls __bsdthread_terminate).
+TEXT runtime·exit1(SB),7,$0
+	MOVL	$361, AX
+	INT	$0x80
+	JAE 2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·write(SB),7,$0
+	MOVL	$4, AX
+	INT	$0x80
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$8
+	get_tls(CX)
+	MOVL	m(CX), DX
+	MOVL	m_procid(DX), DX
+	MOVL	DX, 0(SP)	// thread_port
+	MOVL	$13, 4(SP)	// signal: SIGPIPE
+	MOVL	$328, AX	// __pthread_kill
+	INT	$0x80
+	RET
+
+TEXT runtime·mmap(SB),7,$0
+	MOVL	$197, AX
+	INT	$0x80
+	RET
+
+TEXT runtime·madvise(SB),7,$0
+	MOVL	$75, AX
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVL	$73, AX
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·setitimer(SB),7,$0
+	MOVL	$83, AX
+	INT	$0x80
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	LEAL	12(SP), AX	// must be non-nil, unused
+	MOVL	AX, 4(SP)
+	MOVL	$0, 8(SP)	// time zone pointer
+	MOVL	$116, AX
+	INT	$0x80
+	MOVL	DX, BX
+
+	// sec is in AX, usec in BX
+	MOVL	AX, sec+0(FP)
+	MOVL	$0, sec+4(FP)
+	IMULL	$1000, BX
+	MOVL	BX, nsec+8(FP)
+	RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
+	LEAL	12(SP), AX	// must be non-nil, unused
+	MOVL	AX, 4(SP)
+	MOVL	$0, 8(SP)	// time zone pointer
+	MOVL	$116, AX
+	INT	$0x80
+	MOVL	DX, BX
+
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
+	RET
+
+TEXT runtime·sigaction(SB),7,$0
+	MOVL	$46, AX
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+// Sigtramp's job is to call the actual signal handler.
+// It is called with the following arguments on the stack:
+//	0(FP)	"return address" - ignored
+//	4(FP)	actual handler
+//	8(FP)	siginfo style - ignored
+//	12(FP)	signal number
+//	16(FP)	siginfo
+//	20(FP)	context
+TEXT runtime·sigtramp(SB),7,$40
+	get_tls(CX)
+
+	// save g
+	MOVL	g(CX), DI
+	MOVL	DI, 20(SP)
+
+	// g = m->gsignal
+	MOVL	m(CX), BP
+	MOVL	m_gsignal(BP), BP
+	MOVL	BP, g(CX)
+
+	// copy arguments to sighandler
+	MOVL	sig+8(FP), BX
+	MOVL	BX, 0(SP)
+	MOVL	info+12(FP), BX
+	MOVL	BX, 4(SP)
+	MOVL	context+16(FP), BX
+	MOVL	BX, 8(SP)
+	MOVL	DI, 12(SP)
+
+	MOVL	handler+0(FP), BX
+	CALL	BX
+
+	// restore g
+	get_tls(CX)
+	MOVL	20(SP), DI
+	MOVL	DI, g(CX)
+
+	// call sigreturn
+	MOVL	context+16(FP), CX
+	MOVL	style+4(FP), BX
+	MOVL	$0, 0(SP)	// "caller PC" - ignored
+	MOVL	CX, 4(SP)
+	MOVL	BX, 8(SP)
+	MOVL	$184, AX	// sigreturn(ucontext, infostyle)
+	INT	$0x80
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$0
+	MOVL	$53, AX
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·usleep(SB),7,$32
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVL	AX, 24(SP)  // sec
+	MOVL	DX, 28(SP)  // usec
+
+	// select(0, 0, 0, 0, &tv)
+	MOVL	$0, 0(SP)  // "return PC" - ignored
+	MOVL	$0, 4(SP)
+	MOVL	$0, 8(SP)
+	MOVL	$0, 12(SP)
+	MOVL	$0, 16(SP)
+	LEAL	24(SP), AX
+	MOVL	AX, 20(SP)
+	MOVL	$93, AX
+	INT	$0x80
+	RET
+
+// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
+// System call args are: func arg stack pthread flags.
+TEXT runtime·bsdthread_create(SB),7,$32
+	MOVL	$360, AX
+	// 0(SP) is where the caller PC would be; kernel skips it
+	MOVL	func+12(FP), BX
+	MOVL	BX, 4(SP)	// func
+	MOVL	mm+4(FP), BX
+	MOVL	BX, 8(SP)	// arg
+	MOVL	stk+0(FP), BX
+	MOVL	BX, 12(SP)	// stack
+	MOVL	gg+8(FP), BX
+	MOVL	BX, 16(SP)	// pthread
+	MOVL	$0x1000000, 20(SP)	// flags = PTHREAD_START_CUSTOM
+	INT	$0x80
+	JAE	3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
+
+// The thread that bsdthread_create creates starts executing here,
+// because we registered this function using bsdthread_register
+// at startup.
+//	AX = "pthread" (= g)
+//	BX = mach thread port
+//	CX = "func" (= fn)
+//	DX = "arg" (= m)
+//	DI = stack top
+//	SI = flags (= 0x1000000)
+//	SP = stack - C_32_STK_ALIGN
+TEXT runtime·bsdthread_start(SB),7,$0
+	// set up ldt 7+id to point at m->tls.
+	// m->tls is at m+40.  newosproc left
+	// the m->id in tls[0].
+	LEAL	m_tls(DX), BP
+	MOVL	0(BP), DI
+	ADDL	$7, DI	// m0 is LDT#7. count up.
+	// setldt(tls#, &tls, sizeof tls)
+	PUSHAL	// save registers
+	PUSHL	$32	// sizeof tls
+	PUSHL	BP	// &tls
+	PUSHL	DI	// tls #
+	CALL	runtime·setldt(SB)
+	POPL	AX
+	POPL	AX
+	POPL	AX
+	POPAL
+
+	// Now segment is established.  Initialize m, g.
+	get_tls(BP)
+	MOVL	AX, g(BP)
+	MOVL	DX, m(BP)
+	MOVL	BX, m_procid(DX)	// m->procid = thread port (for debuggers)
+	CALL	runtime·stackcheck(SB)		// smashes AX
+	CALL	CX	// fn()
+	CALL	runtime·exit1(SB)
+	RET
+
+// void bsdthread_register(void)
+// registers callbacks for threadstart (see bsdthread_create above
+// and wqthread and pthsize (not used).  returns 0 on success.
+TEXT runtime·bsdthread_register(SB),7,$40
+	MOVL	$366, AX
+	// 0(SP) is where kernel expects caller PC; ignored
+	MOVL	$runtime·bsdthread_start(SB), 4(SP)	// threadstart
+	MOVL	$0, 8(SP)	// wqthread, not used by us
+	MOVL	$0, 12(SP)	// pthsize, not used by us
+	MOVL	$0, 16(SP)	// dummy_value [sic]
+	MOVL	$0, 20(SP)	// targetconc_ptr
+	MOVL	$0, 24(SP)	// dispatchqueue_offset
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+// Invoke Mach system call.
+// Assumes system call number in AX,
+// caller PC on stack, caller's caller PC next,
+// and then the system call arguments.
+//
+// Can be used for BSD too, but we don't,
+// because if you use this interface the BSD
+// system call numbers need an extra field
+// in the high 16 bits that seems to be the
+// argument count in bytes but is not always.
+// INT $0x80 works fine for those.
+TEXT runtime·sysenter(SB),7,$0
+	POPL	DX
+	MOVL	SP, CX
+	BYTE $0x0F; BYTE $0x34;  // SYSENTER
+	// returns to DX with SP set to CX
+
+TEXT runtime·mach_msg_trap(SB),7,$0
+	MOVL	$-31, AX
+	CALL	runtime·sysenter(SB)
+	RET
+
+TEXT runtime·mach_reply_port(SB),7,$0
+	MOVL	$-26, AX
+	CALL	runtime·sysenter(SB)
+	RET
+
+TEXT runtime·mach_task_self(SB),7,$0
+	MOVL	$-28, AX
+	CALL	runtime·sysenter(SB)
+	RET
+
+// Mach provides trap versions of the semaphore ops,
+// instead of requiring the use of RPC.
+
+// uint32 mach_semaphore_wait(uint32)
+TEXT runtime·mach_semaphore_wait(SB),7,$0
+	MOVL	$-36, AX
+	CALL	runtime·sysenter(SB)
+	RET
+
+// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
+TEXT runtime·mach_semaphore_timedwait(SB),7,$0
+	MOVL	$-38, AX
+	CALL	runtime·sysenter(SB)
+	RET
+
+// uint32 mach_semaphore_signal(uint32)
+TEXT runtime·mach_semaphore_signal(SB),7,$0
+	MOVL	$-33, AX
+	CALL	runtime·sysenter(SB)
+	RET
+
+// uint32 mach_semaphore_signal_all(uint32)
+TEXT runtime·mach_semaphore_signal_all(SB),7,$0
+	MOVL	$-34, AX
+	CALL	runtime·sysenter(SB)
+	RET
+
+// setldt(int entry, int address, int limit)
+// entry and limit are ignored.
+TEXT runtime·setldt(SB),7,$32
+	MOVL	address+4(FP), BX	// aka base
+
+	/*
+	 * When linking against the system libraries,
+	 * we use its pthread_create and let it set up %gs
+	 * for us.  When we do that, the private storage
+	 * we get is not at 0(GS) but at 0x468(GS).
+	 * To insulate the rest of the tool chain from this ugliness,
+	 * 8l rewrites 0(GS) into 0x468(GS) for us.
+	 * To accommodate that rewrite, we translate the
+	 * address and limit here so that 0x468(GS) maps to 0(address).
+	 *
+	 * See cgo/gcc_darwin_386.c:/468 for the derivation
+	 * of the constant.
+	 */
+	SUBL	$0x468, BX
+
+	/*
+	 * Must set up as USER_CTHREAD segment because
+	 * Darwin forces that value into %gs for signal handlers,
+	 * and if we don't set one up, we'll get a recursive
+	 * fault trying to get into the signal handler.
+	 * Since we have to set one up anyway, it might as
+	 * well be the value we want.  So don't bother with
+	 * i386_set_ldt.
+	 */
+	MOVL	BX, 4(SP)
+	MOVL	$3, AX	// thread_fast_set_cthread_self - machdep call #3
+	INT	$0x82	// sic: 0x82, not 0x80, for machdep call
+
+	XORL	AX, AX
+	MOVW	GS, AX
+	RET
+
+TEXT runtime·sysctl(SB),7,$0
+	MOVL	$202, AX
+	INT	$0x80
+	JAE	3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
diff --git a/src/pkg/runtime/sys_darwin_amd64.s b/src/pkg/runtime/sys_darwin_amd64.s
new file mode 100644
index 0000000..9d2ecbe
--- /dev/null
+++ b/src/pkg/runtime/sys_darwin_amd64.s
@@ -0,0 +1,353 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//
+// System calls and other sys.stuff for AMD64, Darwin
+// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
+// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
+//
+// The low 24 bits are the system call number.
+// The high 8 bits specify the kind of system call: 1=Mach, 2=BSD, 3=Machine-Dependent.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$0
+	MOVL	8(SP), DI		// arg 1 exit status
+	MOVL	$(0x2000000+1), AX	// syscall entry
+	SYSCALL
+	CALL	runtime·notok(SB)
+	RET
+
+// Exit this OS thread (like pthread_exit, which eventually
+// calls __bsdthread_terminate).
+TEXT runtime·exit1(SB),7,$0
+	MOVL	8(SP), DI		// arg 1 exit status
+	MOVL	$(0x2000000+361), AX	// syscall entry
+	SYSCALL
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·write(SB),7,$0
+	MOVL	8(SP), DI		// arg 1 fd
+	MOVQ	16(SP), SI		// arg 2 buf
+	MOVL	24(SP), DX		// arg 3 count
+	MOVL	$(0x2000000+4), AX	// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$24
+	get_tls(CX)
+	MOVQ	m(CX), DX
+	MOVL	$13, DI	// arg 1 SIGPIPE
+	MOVQ	m_procid(DX), SI	// arg 2 thread_port
+	MOVL	$(0x2000000+328), AX	// syscall entry __pthread_kill
+	SYSCALL
+	RET
+
+TEXT runtime·setitimer(SB), 7, $0
+	MOVL	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVL	$(0x2000000+83), AX	// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·madvise(SB), 7, $0
+	MOVQ	8(SP), DI		// arg 1 addr
+	MOVQ	16(SP), SI		// arg 2 len
+	MOVL	24(SP), DX		// arg 3 advice
+	MOVL	$(0x2000000+75), AX	// syscall entry madvise
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	MOVQ	SP, DI	// must be non-nil, unused
+	MOVQ	$0, SI
+	MOVL	$(0x2000000+116), AX
+	SYSCALL
+
+	// sec is in AX, usec in DX
+	MOVQ	AX, sec+0(FP)
+	IMULQ	$1000, DX
+	MOVL	DX, nsec+8(FP)
+	RET
+
+// int64 nanotime(void)
+TEXT runtime·nanotime(SB), 7, $32
+	MOVQ	SP, DI	// must be non-nil, unused
+	MOVQ	$0, SI
+	MOVL	$(0x2000000+116), AX
+	SYSCALL
+
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
+	RET
+
+TEXT runtime·sigaction(SB),7,$0
+	MOVL	8(SP), DI		// arg 1 sig
+	MOVQ	16(SP), SI		// arg 2 act
+	MOVQ	24(SP), DX		// arg 3 oact
+	MOVQ	24(SP), CX		// arg 3 oact
+	MOVQ	24(SP), R10		// arg 3 oact
+	MOVL	$(0x2000000+46), AX	// syscall entry
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$64
+	get_tls(BX)
+
+	// save g
+	MOVQ	g(BX), R10
+	MOVQ	R10, 48(SP)
+
+	// g = m->gsignal
+	MOVQ	m(BX), BP
+	MOVQ	m_gsignal(BP), BP
+	MOVQ	BP, g(BX)
+
+	MOVL	DX, 0(SP)
+	MOVQ	CX, 8(SP)
+	MOVQ	R8, 16(SP)
+	MOVQ	R10, 24(SP)
+
+	MOVQ	R8, 32(SP)	// save ucontext
+	MOVQ	SI, 40(SP)	// save infostyle
+	CALL	DI
+
+	// restore g
+	get_tls(BX)
+	MOVQ	48(SP), R10
+	MOVQ	R10, g(BX)
+
+	// call sigreturn
+	MOVL	$(0x2000000+184), AX	// sigreturn(ucontext, infostyle)
+	MOVQ	32(SP), DI	// saved ucontext
+	MOVQ	40(SP), SI	// saved infostyle
+	SYSCALL
+	INT $3	// not reached
+
+TEXT runtime·mmap(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 addr
+	MOVQ	16(SP), SI		// arg 2 len
+	MOVL	24(SP), DX		// arg 3 prot
+	MOVL	28(SP), R10		// arg 4 flags
+	MOVL	32(SP), R8		// arg 5 fid
+	MOVL	36(SP), R9		// arg 6 offset
+	MOVL	$(0x2000000+197), AX	// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 addr
+	MOVQ	16(SP), SI		// arg 2 len
+	MOVL	$(0x2000000+73), AX	// syscall entry
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·notok(SB),7,$0
+	MOVL	$0xf1, BP
+	MOVQ	BP, (BP)
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$0
+	MOVQ	new+8(SP), DI
+	MOVQ	old+16(SP), SI
+	MOVQ	$(0x2000000+53), AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·usleep(SB),7,$16
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVQ	AX, 0(SP)  // sec
+	MOVL	DX, 8(SP)  // usec
+
+	// select(0, 0, 0, 0, &tv)
+	MOVL	$0, DI
+	MOVL	$0, SI
+	MOVL	$0, DX
+	MOVL	$0, R10
+	MOVQ	SP, R8
+	MOVL	$(0x2000000+93), AX
+	SYSCALL
+	RET
+
+// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
+TEXT runtime·bsdthread_create(SB),7,$0
+	// Set up arguments to bsdthread_create system call.
+	// The ones in quotes pass through to the thread callback
+	// uninterpreted, so we can put whatever we want there.
+	MOVQ	fn+32(SP), DI	// "func"
+	MOVQ	mm+16(SP), SI	// "arg"
+	MOVQ	stk+8(SP), DX	// stack
+	MOVQ	gg+24(SP), R10	// "pthread"
+	MOVQ	$0x01000000, R8	// flags = PTHREAD_START_CUSTOM
+	MOVQ	$0, R9	// paranoia
+	MOVQ	$(0x2000000+360), AX	// bsdthread_create
+	SYSCALL
+	JCC 3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
+
+// The thread that bsdthread_create creates starts executing here,
+// because we registered this function using bsdthread_register
+// at startup.
+//	DI = "pthread"
+//	SI = mach thread port
+//	DX = "func" (= fn)
+//	CX = "arg" (= m)
+//	R8 = stack
+//	R9 = flags (= 0)
+//	SP = stack - C_64_REDZONE_LEN (= stack - 128)
+TEXT runtime·bsdthread_start(SB),7,$0
+	MOVQ	R8, SP		// empirically, SP is very wrong but R8 is right
+
+	PUSHQ	DX
+	PUSHQ	CX
+	PUSHQ	SI
+
+	// set up thread local storage pointing at m->tls.
+	LEAQ	m_tls(CX), DI
+	CALL	runtime·settls(SB)
+
+	POPQ	SI
+	POPQ	CX
+	POPQ	DX
+
+	get_tls(BX)
+	MOVQ	CX, m(BX)
+	MOVQ	SI, m_procid(CX)	// thread port is m->procid
+	MOVQ	m_g0(CX), AX
+	MOVQ	AX, g(BX)
+	CALL	runtime·stackcheck(SB)	// smashes AX, CX
+	CALL	DX	// fn
+	CALL	runtime·exit1(SB)
+	RET
+
+// void bsdthread_register(void)
+// registers callbacks for threadstart (see bsdthread_create above
+// and wqthread and pthsize (not used).  returns 0 on success.
+TEXT runtime·bsdthread_register(SB),7,$0
+	MOVQ	$runtime·bsdthread_start(SB), DI	// threadstart
+	MOVQ	$0, SI	// wqthread, not used by us
+	MOVQ	$0, DX	// pthsize, not used by us
+	MOVQ	$0, R10	// dummy_value [sic]
+	MOVQ	$0, R8	// targetconc_ptr
+	MOVQ	$0, R9	// dispatchqueue_offset
+	MOVQ	$(0x2000000+366), AX	// bsdthread_register
+	SYSCALL
+	JCC 2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+// Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
+
+// uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
+TEXT runtime·mach_msg_trap(SB),7,$0
+	MOVQ	8(SP), DI
+	MOVL	16(SP), SI
+	MOVL	20(SP), DX
+	MOVL	24(SP), R10
+	MOVL	28(SP), R8
+	MOVL	32(SP), R9
+	MOVL	36(SP), R11
+	PUSHQ	R11	// seventh arg, on stack
+	MOVL	$(0x1000000+31), AX	// mach_msg_trap
+	SYSCALL
+	POPQ	R11
+	RET
+
+TEXT runtime·mach_task_self(SB),7,$0
+	MOVL	$(0x1000000+28), AX	// task_self_trap
+	SYSCALL
+	RET
+
+TEXT runtime·mach_thread_self(SB),7,$0
+	MOVL	$(0x1000000+27), AX	// thread_self_trap
+	SYSCALL
+	RET
+
+TEXT runtime·mach_reply_port(SB),7,$0
+	MOVL	$(0x1000000+26), AX	// mach_reply_port
+	SYSCALL
+	RET
+
+// Mach provides trap versions of the semaphore ops,
+// instead of requiring the use of RPC.
+
+// uint32 mach_semaphore_wait(uint32)
+TEXT runtime·mach_semaphore_wait(SB),7,$0
+	MOVL	8(SP), DI
+	MOVL	$(0x1000000+36), AX	// semaphore_wait_trap
+	SYSCALL
+	RET
+
+// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
+TEXT runtime·mach_semaphore_timedwait(SB),7,$0
+	MOVL	8(SP), DI
+	MOVL	12(SP), SI
+	MOVL	16(SP), DX
+	MOVL	$(0x1000000+38), AX	// semaphore_timedwait_trap
+	SYSCALL
+	RET
+
+// uint32 mach_semaphore_signal(uint32)
+TEXT runtime·mach_semaphore_signal(SB),7,$0
+	MOVL	8(SP), DI
+	MOVL	$(0x1000000+33), AX	// semaphore_signal_trap
+	SYSCALL
+	RET
+
+// uint32 mach_semaphore_signal_all(uint32)
+TEXT runtime·mach_semaphore_signal_all(SB),7,$0
+	MOVL	8(SP), DI
+	MOVL	$(0x1000000+34), AX	// semaphore_signal_all_trap
+	SYSCALL
+	RET
+
+// set tls base to DI
+TEXT runtime·settls(SB),7,$32
+	/*
+	* Same as in sys_darwin_386.s:/ugliness, different constant.
+	* See cgo/gcc_darwin_amd64.c for the derivation
+	* of the constant.
+	*/
+	SUBQ $0x8a0, DI
+
+	MOVL	$(0x3000000+3), AX	// thread_fast_set_cthread_self - machdep call #3
+	SYSCALL
+	RET
+
+TEXT runtime·sysctl(SB),7,$0
+	MOVQ	8(SP), DI
+	MOVL	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVQ	32(SP), R10
+	MOVQ	40(SP), R8
+	MOVQ	48(SP), R9
+	MOVL	$(0x2000000+202), AX	// syscall entry
+	SYSCALL
+	JCC 3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
diff --git a/src/pkg/runtime/sys_freebsd_386.s b/src/pkg/runtime/sys_freebsd_386.s
new file mode 100644
index 0000000..d8dc40d
--- /dev/null
+++ b/src/pkg/runtime/sys_freebsd_386.s
@@ -0,0 +1,303 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// System calls and other sys.stuff for 386, FreeBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+	
+TEXT runtime·sys_umtx_op(SB),7,$-4
+	MOVL	$454, AX
+	INT	$0x80
+	RET
+
+TEXT runtime·thr_new(SB),7,$-4
+	MOVL	$455, AX
+	INT	$0x80
+	RET
+
+TEXT runtime·thr_start(SB),7,$0
+	MOVL	mm+0(FP), AX
+	MOVL	m_g0(AX), BX
+	LEAL	m_tls(AX), BP
+	MOVL	0(BP), DI
+	ADDL	$7, DI
+	PUSHAL
+	PUSHL	$32
+	PUSHL	BP
+	PUSHL	DI
+	CALL	runtime·setldt(SB)
+	POPL	AX
+	POPL	AX
+	POPL	AX
+	POPAL
+	get_tls(CX)
+	MOVL	BX, g(CX)
+	
+	MOVL	AX, m(CX)
+	CALL	runtime·stackcheck(SB)		// smashes AX
+	CALL	runtime·mstart(SB)
+	MOVL	0, AX			// crash (not reached)
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-4
+	MOVL	$1, AX
+	INT	$0x80
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·exit1(SB),7,$-4
+	MOVL	$431, AX
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·write(SB),7,$-4
+	MOVL	$4, AX
+	INT	$0x80
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$12
+	// thr_self(&8(SP))
+	LEAL	8(SP), AX
+	MOVL	AX, 0(SP)
+	MOVL	$432, AX
+	INT	$0x80
+	// thr_kill(self, SIGPIPE)
+	MOVL	8(SP), AX
+	MOVL	AX, 0(SP)
+	MOVL	$13, 4(SP)
+	MOVL	$433, AX
+	INT	$0x80
+	RET
+
+TEXT runtime·notok(SB),7,$0
+	MOVL	$0xf1, 0xf1
+	RET
+
+TEXT runtime·mmap(SB),7,$32
+	LEAL arg0+0(FP), SI
+	LEAL	4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVL	$0, AX	// top 64 bits of file offset
+	STOSL
+	MOVL	$477, AX
+	INT	$0x80
+	RET
+
+TEXT runtime·munmap(SB),7,$-4
+	MOVL	$73, AX
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·setitimer(SB), 7, $-4
+	MOVL	$83, AX
+	INT	$0x80
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	MOVL	$116, AX
+	LEAL	12(SP), BX
+	MOVL	BX, 4(SP)
+	MOVL	$0, 8(SP)
+	INT	$0x80
+	MOVL	12(SP), AX	// sec
+	MOVL	16(SP), BX	// usec
+
+	// sec is in AX, usec in BX
+	MOVL	AX, sec+0(FP)
+	MOVL	$0, sec+4(FP)
+	IMULL	$1000, BX
+	MOVL	BX, nsec+8(FP)
+	RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
+	MOVL	$116, AX
+	LEAL	12(SP), BX
+	MOVL	BX, 4(SP)
+	MOVL	$0, 8(SP)
+	INT	$0x80
+	MOVL	12(SP), AX	// sec
+	MOVL	16(SP), BX	// usec
+
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
+	RET
+
+
+TEXT runtime·sigaction(SB),7,$-4
+	MOVL	$416, AX
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$44
+	get_tls(CX)
+
+	// save g
+	MOVL	g(CX), DI
+	MOVL	DI, 20(SP)
+	
+	// g = m->gsignal
+	MOVL	m(CX), BX
+	MOVL	m_gsignal(BX), BX
+	MOVL	BX, g(CX)
+
+	// copy arguments for call to sighandler
+	MOVL	signo+0(FP), BX
+	MOVL	BX, 0(SP)
+	MOVL	info+4(FP), BX
+	MOVL	BX, 4(SP)
+	MOVL	context+8(FP), BX
+	MOVL	BX, 8(SP)
+	MOVL	DI, 12(SP)
+
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(CX)
+	MOVL	20(SP), BX
+	MOVL	BX, g(CX)
+	
+	// call sigreturn
+	MOVL	context+8(FP), AX
+	MOVL	$0, 0(SP)	// syscall gap
+	MOVL	AX, 4(SP)
+	MOVL	$417, AX	// sigreturn(ucontext)
+	INT	$0x80
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$0
+	MOVL	$53, AX
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·usleep(SB),7,$20
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVL	AX, 12(SP)		// tv_sec
+	MOVL	$1000, AX
+	MULL	DX
+	MOVL	AX, 16(SP)		// tv_nsec
+
+	MOVL	$0, 0(SP)
+	LEAL	12(SP), AX
+	MOVL	AX, 4(SP)		// arg 1 - rqtp
+	MOVL	$0, 8(SP)		// arg 2 - rmtp
+	MOVL	$240, AX		// sys_nanosleep
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+/*
+descriptor entry format for system call
+is the native machine format, ugly as it is:
+
+	2-byte limit
+	3-byte base
+	1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type
+	1-byte: 0x80=limit is *4k, 0x40=32-bit operand size,
+		0x0F=4 more bits of limit
+	1 byte: 8 more bits of base
+
+int i386_get_ldt(int, union ldt_entry *, int);
+int i386_set_ldt(int, const union ldt_entry *, int);
+
+*/
+
+// setldt(int entry, int address, int limit)
+TEXT runtime·setldt(SB),7,$32
+	MOVL	address+4(FP), BX	// aka base
+	// see comment in sys_linux_386.s; freebsd is similar
+	ADDL	$0x8, BX
+
+	// set up data_desc
+	LEAL	16(SP), AX	// struct data_desc
+	MOVL	$0, 0(AX)
+	MOVL	$0, 4(AX)
+
+	MOVW	BX, 2(AX)
+	SHRL	$16, BX
+	MOVB	BX, 4(AX)
+	SHRL	$8, BX
+	MOVB	BX, 7(AX)
+
+	MOVW	$0xffff, 0(AX)
+	MOVB	$0xCF, 6(AX)	// 32-bit operand, 4k limit unit, 4 more bits of limit
+
+	MOVB	$0xF2, 5(AX)	// r/w data descriptor, dpl=3, present
+
+	// call i386_set_ldt(entry, desc, 1)
+	MOVL	$0xffffffff, 0(SP)	// auto-allocate entry and return in AX
+	MOVL	AX, 4(SP)
+	MOVL	$1, 8(SP)
+	CALL	runtime·i386_set_ldt(SB)
+
+	// compute segment selector - (entry*8+7)
+	SHLL	$3, AX
+	ADDL	$7, AX
+	MOVW	AX, GS
+	RET
+
+TEXT runtime·i386_set_ldt(SB),7,$16
+	LEAL	args+0(FP), AX	// 0(FP) == 4(SP) before SP got moved
+	MOVL	$0, 0(SP)	// syscall gap
+	MOVL	$1, 4(SP)
+	MOVL	AX, 8(SP)
+	MOVL	$165, AX
+	INT	$0x80
+	CMPL	AX, $0xfffff001
+	JLS	2(PC)
+	INT	$3
+	RET
+
+TEXT runtime·sysctl(SB),7,$28
+	LEAL	arg0+0(FP), SI
+	LEAL	4(SP), DI
+	CLD
+	MOVSL				// arg 1 - name
+	MOVSL				// arg 2 - namelen
+	MOVSL				// arg 3 - oldp
+	MOVSL				// arg 4 - oldlenp
+	MOVSL				// arg 5 - newp
+	MOVSL				// arg 6 - newlen
+	MOVL	$202, AX		// sys___sysctl
+	INT	$0x80
+	JCC	3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
+
+
+GLOBL runtime·tlsoffset(SB),$4
diff --git a/src/pkg/runtime/sys_freebsd_amd64.s b/src/pkg/runtime/sys_freebsd_amd64.s
new file mode 100644
index 0000000..dcd5585
--- /dev/null
+++ b/src/pkg/runtime/sys_freebsd_amd64.s
@@ -0,0 +1,231 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// System calls and other sys.stuff for AMD64, FreeBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+	
+TEXT runtime·sys_umtx_op(SB),7,$0
+	MOVQ 8(SP), DI
+	MOVL 16(SP), SI
+	MOVL 20(SP), DX
+	MOVQ 24(SP), R10
+	MOVQ 32(SP), R8
+	MOVL $454, AX
+	SYSCALL
+	RET
+
+TEXT runtime·thr_new(SB),7,$0
+	MOVQ 8(SP), DI
+	MOVQ 16(SP), SI
+	MOVL $455, AX
+	SYSCALL
+	RET
+
+TEXT runtime·thr_start(SB),7,$0
+	MOVQ	DI, R13	// m
+
+	// set up FS to point at m->tls
+	LEAQ	m_tls(R13), DI
+	CALL	runtime·settls(SB)	// smashes DI
+
+	// set up m, g
+	get_tls(CX)
+	MOVQ	R13, m(CX)
+	MOVQ	m_g0(R13), DI
+	MOVQ	DI, g(CX)
+
+	CALL runtime·stackcheck(SB)
+	CALL runtime·mstart(SB)
+	MOVQ 0, AX			// crash (not reached)
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 exit status
+	MOVL	$1, AX
+	SYSCALL
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·exit1(SB),7,$-8
+	MOVQ	8(SP), DI		// arg 1 exit status
+	MOVL	$431, AX
+	SYSCALL
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·write(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 fd
+	MOVQ	16(SP), SI		// arg 2 buf
+	MOVL	24(SP), DX		// arg 3 count
+	MOVL	$4, AX
+	SYSCALL
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$16
+	// thr_self(&8(SP))
+	LEAQ	8(SP), DI	// arg 1 &8(SP)
+	MOVL	$432, AX
+	SYSCALL
+	// thr_kill(self, SIGPIPE)
+	MOVQ	8(SP), DI	// arg 1 id
+	MOVQ	$13, SI	// arg 2 SIGPIPE
+	MOVL	$433, AX
+	SYSCALL
+	RET
+
+TEXT runtime·setitimer(SB), 7, $-8
+	MOVL	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVL	$83, AX
+	SYSCALL
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	MOVL	$116, AX
+	LEAQ	8(SP), DI
+	MOVQ	$0, SI
+	SYSCALL
+	MOVQ	8(SP), AX	// sec
+	MOVL	16(SP), DX	// usec
+
+	// sec is in AX, usec in DX
+	MOVQ	AX, sec+0(FP)
+	IMULQ	$1000, DX
+	MOVL	DX, nsec+8(FP)
+	RET
+
+TEXT runtime·nanotime(SB), 7, $32
+	MOVL	$116, AX
+	LEAQ	8(SP), DI
+	MOVQ	$0, SI
+	SYSCALL
+	MOVQ	8(SP), AX	// sec
+	MOVL	16(SP), DX	// usec
+
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
+	RET
+
+TEXT runtime·sigaction(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 sig
+	MOVQ	16(SP), SI		// arg 2 act
+	MOVQ	24(SP), DX		// arg 3 oact
+	MOVL	$416, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$64
+	get_tls(BX)
+	
+	// save g
+	MOVQ	g(BX), R10
+	MOVQ	R10, 40(SP)
+	
+	// g = m->signal
+	MOVQ	m(BX), BP
+	MOVQ	m_gsignal(BP), BP
+	MOVQ	BP, g(BX)
+	
+	MOVQ	DI, 0(SP)
+	MOVQ	SI, 8(SP)
+	MOVQ	DX, 16(SP)
+	MOVQ	R10, 24(SP)
+	
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(BX)
+	MOVQ	40(SP), R10
+	MOVQ	R10, g(BX)
+	RET
+
+TEXT runtime·mmap(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 addr
+	MOVQ	16(SP), SI		// arg 2 len
+	MOVL	24(SP), DX		// arg 3 prot
+	MOVL	28(SP), R10		// arg 4 flags
+	MOVL	32(SP), R8		// arg 5 fid
+	MOVL	36(SP), R9		// arg 6 offset
+	MOVL	$477, AX
+	SYSCALL
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 addr
+	MOVQ	16(SP), SI		// arg 2 len
+	MOVL	$73, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·notok(SB),7,$-8
+	MOVL	$0xf1, BP
+	MOVQ	BP, (BP)
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$-8
+	MOVQ	new+8(SP), DI
+	MOVQ	old+16(SP), SI
+	MOVQ	$53, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·usleep(SB),7,$16
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVQ	AX, 0(SP)		// tv_sec
+	MOVL	$1000, AX
+	MULL	DX
+	MOVQ	AX, 8(SP)		// tv_nsec
+
+	MOVQ	SP, DI			// arg 1 - rqtp
+	MOVQ	$0, SI			// arg 2 - rmtp
+	MOVL	$240, AX		// sys_nanosleep
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+// set tls base to DI
+TEXT runtime·settls(SB),7,$8
+	ADDQ	$16, DI	// adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
+	MOVQ	DI, 0(SP)
+	MOVQ	SP, SI
+	MOVQ	$129, DI	// AMD64_SET_FSBASE
+	MOVQ	$165, AX	// sysarch
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sysctl(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - name
+	MOVL	16(SP), SI		// arg 2 - namelen
+	MOVQ	24(SP), DX		// arg 3 - oldp
+	MOVQ	32(SP), R10		// arg 4 - oldlenp
+	MOVQ	40(SP), R8		// arg 5 - newp
+	MOVQ	48(SP), R9		// arg 6 - newlen
+	MOVQ	$202, AX		// sys___sysctl
+	SYSCALL
+	JCC 3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
+
diff --git a/src/pkg/runtime/sys_linux_386.s b/src/pkg/runtime/sys_linux_386.s
new file mode 100644
index 0000000..b745bc5
--- /dev/null
+++ b/src/pkg/runtime/sys_linux_386.s
@@ -0,0 +1,403 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//
+// System calls and other sys.stuff for 386, Linux
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+TEXT runtime·exit(SB),7,$0
+	MOVL	$252, AX	// syscall number
+	MOVL	4(SP), BX
+	CALL	*runtime·_vdso(SB)
+	INT $3	// not reached
+	RET
+
+TEXT runtime·exit1(SB),7,$0
+	MOVL	$1, AX	// exit - exit the current os thread
+	MOVL	4(SP), BX
+	CALL	*runtime·_vdso(SB)
+	INT $3	// not reached
+	RET
+
+TEXT runtime·open(SB),7,$0
+	MOVL	$5, AX		// syscall - open
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	CALL	*runtime·_vdso(SB)
+	RET
+
+TEXT runtime·close(SB),7,$0
+	MOVL	$6, AX		// syscall - close
+	MOVL	4(SP), BX
+	CALL	*runtime·_vdso(SB)
+	RET
+
+TEXT runtime·write(SB),7,$0
+	MOVL	$4, AX		// syscall - write
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	CALL	*runtime·_vdso(SB)
+	RET
+
+TEXT runtime·read(SB),7,$0
+	MOVL	$3, AX		// syscall - read
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	CALL	*runtime·_vdso(SB)
+	RET
+
+TEXT runtime·usleep(SB),7,$8
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVL	AX, 0(SP)
+	MOVL	DX, 4(SP)
+
+	// select(0, 0, 0, 0, &tv)
+	MOVL	$142, AX
+	MOVL	$0, BX
+	MOVL	$0, CX
+	MOVL	$0, DX
+	MOVL	$0, SI
+	LEAL	0(SP), DI
+	CALL	*runtime·_vdso(SB)
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$12
+	MOVL	$224, AX	// syscall - gettid
+	CALL	*runtime·_vdso(SB)
+	MOVL	AX, 0(SP)	// arg 1 tid
+	MOVL	$13, 4(SP)	// arg 2 SIGPIPE
+	MOVL	$238, AX	// syscall - tkill
+	CALL	*runtime·_vdso(SB)
+	RET
+
+TEXT runtime·setitimer(SB),7,$0-24
+	MOVL	$104, AX			// syscall - setitimer
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	CALL	*runtime·_vdso(SB)
+	RET
+
+TEXT runtime·mincore(SB),7,$0-24
+	MOVL	$218, AX			// syscall - mincore
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	CALL	*runtime·_vdso(SB)
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	MOVL	$78, AX			// syscall - gettimeofday
+	LEAL	8(SP), BX
+	MOVL	$0, CX
+	MOVL	$0, DX
+	CALL	*runtime·_vdso(SB)
+	MOVL	8(SP), AX	// sec
+	MOVL	12(SP), BX	// usec
+
+	// sec is in AX, usec in BX
+	MOVL	AX, sec+0(FP)
+	MOVL	$0, sec+4(FP)
+	IMULL	$1000, BX
+	MOVL	BX, nsec+8(FP)
+	RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB), 7, $32
+	MOVL	$78, AX			// syscall - gettimeofday
+	LEAL	8(SP), BX
+	MOVL	$0, CX
+	MOVL	$0, DX
+	CALL	*runtime·_vdso(SB)
+	MOVL	8(SP), AX	// sec
+	MOVL	12(SP), BX	// usec
+
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
+	RET
+
+TEXT runtime·rt_sigaction(SB),7,$0
+	MOVL	$174, AX		// syscall - rt_sigaction
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	MOVL	16(SP), SI
+	CALL	*runtime·_vdso(SB)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$44
+	get_tls(CX)
+
+	// save g
+	MOVL	g(CX), DI
+	MOVL	DI, 20(SP)
+
+	// g = m->gsignal
+	MOVL	m(CX), BX
+	MOVL	m_gsignal(BX), BX
+	MOVL	BX, g(CX)
+
+	// copy arguments for call to sighandler
+	MOVL	sig+0(FP), BX
+	MOVL	BX, 0(SP)
+	MOVL	info+4(FP), BX
+	MOVL	BX, 4(SP)
+	MOVL	context+8(FP), BX
+	MOVL	BX, 8(SP)
+	MOVL	DI, 12(SP)
+
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(CX)
+	MOVL	20(SP), BX
+	MOVL	BX, g(CX)
+
+	RET
+
+TEXT runtime·sigignore(SB),7,$0
+	RET
+
+TEXT runtime·sigreturn(SB),7,$0
+	MOVL	$173, AX	// rt_sigreturn
+	// Sigreturn expects same SP as signal handler,
+	// so cannot CALL *runtime._vsdo(SB) here.
+	INT	$0x80
+	INT $3	// not reached
+	RET
+
+TEXT runtime·mmap(SB),7,$0
+	MOVL	$192, AX	// mmap2
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	MOVL	16(SP), SI
+	MOVL	20(SP), DI
+	MOVL	24(SP), BP
+	SHRL	$12, BP
+	CALL	*runtime·_vdso(SB)
+	CMPL	AX, $0xfffff001
+	JLS	3(PC)
+	NOTL	AX
+	INCL	AX
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVL	$91, AX	// munmap
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	CALL	*runtime·_vdso(SB)
+	CMPL	AX, $0xfffff001
+	JLS	2(PC)
+	INT $3
+	RET
+
+TEXT runtime·madvise(SB),7,$0
+	MOVL	$219, AX	// madvise
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	CALL	*runtime·_vdso(SB)
+	CMPL	AX, $0xfffff001
+	JLS	2(PC)
+	INT $3
+	RET
+
+// int32 futex(int32 *uaddr, int32 op, int32 val,
+//	struct timespec *timeout, int32 *uaddr2, int32 val2);
+TEXT runtime·futex(SB),7,$0
+	MOVL	$240, AX	// futex
+	MOVL	4(SP), BX
+	MOVL	8(SP), CX
+	MOVL	12(SP), DX
+	MOVL	16(SP), SI
+	MOVL	20(SP), DI
+	MOVL	24(SP), BP
+	CALL	*runtime·_vdso(SB)
+	RET
+
+// int32 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+TEXT runtime·clone(SB),7,$0
+	MOVL	$120, AX	// clone
+	MOVL	flags+4(SP), BX
+	MOVL	stack+8(SP), CX
+	MOVL	$0, DX	// parent tid ptr
+	MOVL	$0, DI	// child tid ptr
+
+	// Copy m, g, fn off parent stack for use by child.
+	SUBL	$16, CX
+	MOVL	mm+12(SP), SI
+	MOVL	SI, 0(CX)
+	MOVL	gg+16(SP), SI
+	MOVL	SI, 4(CX)
+	MOVL	fn+20(SP), SI
+	MOVL	SI, 8(CX)
+	MOVL	$1234, 12(CX)
+
+	// cannot use CALL *runtime·_vdso(SB) here, because
+	// the stack changes during the system call (after
+	// CALL *runtime·_vdso(SB), the child is still using
+	// the parent's stack when executing its RET instruction).
+	INT	$0x80
+
+	// In parent, return.
+	CMPL	AX, $0
+	JEQ	2(PC)
+	RET
+
+	// Paranoia: check that SP is as we expect.
+	MOVL	12(SP), BP
+	CMPL	BP, $1234
+	JEQ	2(PC)
+	INT	$3
+
+	// Initialize AX to Linux tid
+	MOVL	$224, AX
+	CALL	*runtime·_vdso(SB)
+
+	// In child on new stack.  Reload registers (paranoia).
+	MOVL	0(SP), BX	// m
+	MOVL	4(SP), DX	// g
+	MOVL	8(SP), SI	// fn
+
+	MOVL	AX, m_procid(BX)	// save tid as m->procid
+
+	// set up ldt 7+id to point at m->tls.
+	// newosproc left the id in tls[0].
+	LEAL	m_tls(BX), BP
+	MOVL	0(BP), DI
+	ADDL	$7, DI	// m0 is LDT#7. count up.
+	// setldt(tls#, &tls, sizeof tls)
+	PUSHAL	// save registers
+	PUSHL	$32	// sizeof tls
+	PUSHL	BP	// &tls
+	PUSHL	DI	// tls #
+	CALL	runtime·setldt(SB)
+	POPL	AX
+	POPL	AX
+	POPL	AX
+	POPAL
+
+	// Now segment is established.  Initialize m, g.
+	get_tls(AX)
+	MOVL	DX, g(AX)
+	MOVL	BX, m(AX)
+
+	CALL	runtime·stackcheck(SB)	// smashes AX, CX
+	MOVL	0(DX), DX	// paranoia; check they are not nil
+	MOVL	0(BX), BX
+
+	// more paranoia; check that stack splitting code works
+	PUSHAL
+	CALL	runtime·emptyfunc(SB)
+	POPAL
+
+	CALL	SI	// fn()
+	CALL	runtime·exit1(SB)
+	MOVL	$0x1234, 0x1005
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$-8
+	MOVL	$186, AX	// sigaltstack
+	MOVL	new+4(SP), BX
+	MOVL	old+8(SP), CX
+	CALL	*runtime·_vdso(SB)
+	CMPL	AX, $0xfffff001
+	JLS	2(PC)
+	INT	$3
+	RET
+
+// <asm-i386/ldt.h>
+// struct user_desc {
+//	unsigned int  entry_number;
+//	unsigned long base_addr;
+//	unsigned int  limit;
+//	unsigned int  seg_32bit:1;
+//	unsigned int  contents:2;
+//	unsigned int  read_exec_only:1;
+//	unsigned int  limit_in_pages:1;
+//	unsigned int  seg_not_present:1;
+//	unsigned int  useable:1;
+// };
+#define SEG_32BIT 0x01
+// contents are the 2 bits 0x02 and 0x04.
+#define CONTENTS_DATA 0x00
+#define CONTENTS_STACK 0x02
+#define CONTENTS_CODE 0x04
+#define READ_EXEC_ONLY 0x08
+#define LIMIT_IN_PAGES 0x10
+#define SEG_NOT_PRESENT 0x20
+#define USEABLE 0x40
+
+// setldt(int entry, int address, int limit)
+TEXT runtime·setldt(SB),7,$32
+	MOVL	entry+0(FP), BX	// entry
+	MOVL	address+4(FP), CX	// base address
+
+	/*
+	 * When linking against the system libraries,
+	 * we use its pthread_create and let it set up %gs
+	 * for us.  When we do that, the private storage
+	 * we get is not at 0(GS), 4(GS), but -8(GS), -4(GS).
+	 * To insulate the rest of the tool chain from this
+	 * ugliness, 8l rewrites 0(GS) into -8(GS) for us.
+	 * To accommodate that rewrite, we translate
+	 * the address here and bump the limit to 0xffffffff (no limit)
+	 * so that -8(GS) maps to 0(address).
+	 * Also, the final 0(GS) (current 8(CX)) has to point
+	 * to itself, to mimic ELF.
+	 */
+	ADDL	$0x8, CX	// address
+	MOVL	CX, 0(CX)
+
+	// set up user_desc
+	LEAL	16(SP), AX	// struct user_desc
+	MOVL	BX, 0(AX)
+	MOVL	CX, 4(AX)
+	MOVL	$0xfffff, 8(AX)
+	MOVL	$(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX)	// flag bits
+
+	// call modify_ldt
+	MOVL	$1, BX	// func = 1 (write)
+	MOVL	AX, CX	// user_desc
+	MOVL	$16, DX	// sizeof(user_desc)
+	MOVL	$123, AX	// syscall - modify_ldt
+	CALL	*runtime·_vdso(SB)
+
+	// breakpoint on error
+	CMPL AX, $0xfffff001
+	JLS 2(PC)
+	INT $3
+
+	// compute segment selector - (entry*8+7)
+	MOVL	entry+0(FP), AX
+	SHLL	$3, AX
+	ADDL	$7, AX
+	MOVW	AX, GS
+
+	RET
+
+TEXT runtime·osyield(SB),7,$0
+	MOVL	$158, AX
+	CALL	*runtime·_vdso(SB)
+	RET
diff --git a/src/pkg/runtime/sys_linux_amd64.s b/src/pkg/runtime/sys_linux_amd64.s
new file mode 100644
index 0000000..ef7bb28
--- /dev/null
+++ b/src/pkg/runtime/sys_linux_amd64.s
@@ -0,0 +1,296 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//
+// System calls and other sys.stuff for AMD64, Linux
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+TEXT runtime·exit(SB),7,$0-8
+	MOVL	8(SP), DI
+	MOVL	$231, AX	// exitgroup - force all os threads to exit
+	SYSCALL
+	RET
+
+TEXT runtime·exit1(SB),7,$0-8
+	MOVL	8(SP), DI
+	MOVL	$60, AX	// exit - exit the current os thread
+	SYSCALL
+	RET
+
+TEXT runtime·open(SB),7,$0-16
+	MOVQ	8(SP), DI
+	MOVL	16(SP), SI
+	MOVL	20(SP), DX
+	MOVL	$2, AX			// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·close(SB),7,$0-16
+	MOVL	8(SP), DI
+	MOVL	$3, AX			// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·write(SB),7,$0-24
+	MOVL	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVL	24(SP), DX
+	MOVL	$1, AX			// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·read(SB),7,$0-24
+	MOVL	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVL	24(SP), DX
+	MOVL	$0, AX			// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·usleep(SB),7,$16
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVQ	AX, 0(SP)
+	MOVQ	DX, 8(SP)
+
+	// select(0, 0, 0, 0, &tv)
+	MOVL	$0, DI
+	MOVL	$0, SI
+	MOVL	$0, DX
+	MOVL	$0, R10
+	MOVQ	SP, R8
+	MOVL	$23, AX
+	SYSCALL
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$12
+	MOVL	$186, AX	// syscall - gettid
+	SYSCALL
+	MOVL	AX, DI	// arg 1 tid
+	MOVL	$13, SI	// arg 2 SIGPIPE
+	MOVL	$200, AX	// syscall - tkill
+	SYSCALL
+	RET
+
+TEXT runtime·setitimer(SB),7,$0-24
+	MOVL	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVL	$38, AX			// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·mincore(SB),7,$0-24
+	MOVQ	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVL	$27, AX			// syscall entry
+	SYSCALL
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	LEAQ	8(SP), DI
+	MOVQ	$0, SI
+	MOVQ	$0xffffffffff600000, AX
+	CALL	AX
+	MOVQ	8(SP), AX	// sec
+	MOVL	16(SP), DX	// usec
+
+	// sec is in AX, usec in DX
+	MOVQ	AX, sec+0(FP)
+	IMULQ	$1000, DX
+	MOVL	DX, nsec+8(FP)
+	RET
+
+TEXT runtime·nanotime(SB), 7, $32
+	LEAQ	8(SP), DI
+	MOVQ	$0, SI
+	MOVQ	$0xffffffffff600000, AX
+	CALL	AX
+	MOVQ	8(SP), AX	// sec
+	MOVL	16(SP), DX	// usec
+
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
+	RET
+
+TEXT runtime·rt_sigaction(SB),7,$0-32
+	MOVL	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVQ	32(SP), R10
+	MOVL	$13, AX			// syscall entry
+	SYSCALL
+	RET
+
+TEXT runtime·sigtramp(SB),7,$64
+	get_tls(BX)
+
+	// save g
+	MOVQ	g(BX), R10
+	MOVQ	R10, 40(SP)
+
+	// g = m->gsignal
+	MOVQ	m(BX), BP
+	MOVQ	m_gsignal(BP), BP
+	MOVQ	BP, g(BX)
+
+	MOVQ	DI, 0(SP)
+	MOVQ	SI, 8(SP)
+	MOVQ	DX, 16(SP)
+	MOVQ	R10, 24(SP)
+
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(BX)
+	MOVQ	40(SP), R10
+	MOVQ	R10, g(BX)
+	RET
+
+TEXT runtime·sigignore(SB),7,$0
+	RET
+
+TEXT runtime·sigreturn(SB),7,$0
+	MOVL	$15, AX	// rt_sigreturn
+	SYSCALL
+	INT $3	// not reached
+
+TEXT runtime·mmap(SB),7,$0
+	MOVQ	8(SP), DI
+	MOVQ	$0, SI
+	MOVQ	16(SP), SI
+	MOVL	24(SP), DX
+	MOVL	28(SP), R10
+	MOVL	32(SP), R8
+	MOVL	36(SP), R9
+
+	MOVL	$9, AX			// mmap
+	SYSCALL
+	CMPQ	AX, $0xfffffffffffff001
+	JLS	3(PC)
+	NOTQ	AX
+	INCQ	AX
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVQ	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	$11, AX	// munmap
+	SYSCALL
+	CMPQ	AX, $0xfffffffffffff001
+	JLS	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·madvise(SB),7,$0
+	MOVQ	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVQ	$28, AX	// madvise
+	SYSCALL
+	CMPQ	AX, $0xfffffffffffff001
+	JLS	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·notok(SB),7,$0
+	MOVQ	$0xf1, BP
+	MOVQ	BP, (BP)
+	RET
+
+// int64 futex(int32 *uaddr, int32 op, int32 val,
+//	struct timespec *timeout, int32 *uaddr2, int32 val2);
+TEXT runtime·futex(SB),7,$0
+	MOVQ	8(SP), DI
+	MOVL	16(SP), SI
+	MOVL	20(SP), DX
+	MOVQ	24(SP), R10
+	MOVQ	32(SP), R8
+	MOVL	40(SP), R9
+	MOVL	$202, AX
+	SYSCALL
+	RET
+
+// int64 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+TEXT runtime·clone(SB),7,$0
+	MOVL	flags+8(SP), DI
+	MOVQ	stack+16(SP), SI
+
+	// Copy m, g, fn off parent stack for use by child.
+	// Careful: Linux system call clobbers CX and R11.
+	MOVQ	mm+24(SP), R8
+	MOVQ	gg+32(SP), R9
+	MOVQ	fn+40(SP), R12
+
+	MOVL	$56, AX
+	SYSCALL
+
+	// In parent, return.
+	CMPQ	AX, $0
+	JEQ	2(PC)
+	RET
+
+	// In child, on new stack.
+	MOVQ	SI, SP
+
+	// Initialize m->procid to Linux tid
+	MOVL	$186, AX	// gettid
+	SYSCALL
+	MOVQ	AX, m_procid(R8)
+
+	// Set FS to point at m->tls.
+	LEAQ	m_tls(R8), DI
+	CALL	runtime·settls(SB)
+
+	// In child, set up new stack
+	get_tls(CX)
+	MOVQ	R8, m(CX)
+	MOVQ	R9, g(CX)
+	CALL	runtime·stackcheck(SB)
+
+	// Call fn
+	CALL	R12
+
+	// It shouldn't return.  If it does, exit
+	MOVL	$111, DI
+	MOVL	$60, AX
+	SYSCALL
+	JMP	-3(PC)	// keep exiting
+
+TEXT runtime·sigaltstack(SB),7,$-8
+	MOVQ	new+8(SP), DI
+	MOVQ	old+16(SP), SI
+	MOVQ	$131, AX
+	SYSCALL
+	CMPQ	AX, $0xfffffffffffff001
+	JLS	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+// set tls base to DI
+TEXT runtime·settls(SB),7,$32
+	ADDQ	$16, DI	// ELF wants to use -16(FS), -8(FS)
+
+	MOVQ	DI, SI
+	MOVQ	$0x1002, DI	// ARCH_SET_FS
+	MOVQ	$158, AX	// arch_prctl
+	SYSCALL
+	CMPQ	AX, $0xfffffffffffff001
+	JLS	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·osyield(SB),7,$0
+	MOVL	$24, AX
+	SYSCALL
+	RET
diff --git a/src/pkg/runtime/sys_linux_arm.s b/src/pkg/runtime/sys_linux_arm.s
new file mode 100644
index 0000000..c3a828a
--- /dev/null
+++ b/src/pkg/runtime/sys_linux_arm.s
@@ -0,0 +1,360 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//
+// System calls and other sys.stuff for arm, Linux
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+// OABI
+//#define SYS_BASE 0x00900000
+
+// EABI
+#define SYS_BASE 0x0
+
+#define SYS_exit (SYS_BASE + 1)
+#define SYS_read (SYS_BASE + 3)
+#define SYS_write (SYS_BASE + 4)
+#define SYS_open (SYS_BASE + 5)
+#define SYS_close (SYS_BASE + 6)
+#define SYS_gettimeofday (SYS_BASE + 78)
+#define SYS_clone (SYS_BASE + 120)
+#define SYS_rt_sigreturn (SYS_BASE + 173)
+#define SYS_rt_sigaction (SYS_BASE + 174)
+#define SYS_sigaltstack (SYS_BASE + 186)
+#define SYS_mmap2 (SYS_BASE + 192)
+#define SYS_futex (SYS_BASE + 240)
+#define SYS_exit_group (SYS_BASE + 248)
+#define SYS_munmap (SYS_BASE + 91)
+#define SYS_madvise (SYS_BASE + 220)
+#define SYS_setitimer (SYS_BASE + 104)
+#define SYS_mincore (SYS_BASE + 219)
+#define SYS_gettid (SYS_BASE + 224)
+#define SYS_tkill (SYS_BASE + 238)
+#define SYS_sched_yield (SYS_BASE + 158)
+#define SYS_select (SYS_BASE + 142) // newselect
+
+#define ARM_BASE (SYS_BASE + 0x0f0000)
+#define SYS_ARM_cacheflush (ARM_BASE + 2)
+
+TEXT runtime·open(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	$SYS_open, R7
+	SWI	$0
+	RET
+
+TEXT runtime·close(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	$SYS_close, R7
+	SWI	$0
+	RET
+
+TEXT runtime·write(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	$SYS_write, R7
+	SWI	$0
+	RET
+
+TEXT runtime·read(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	$SYS_read, R7
+	SWI	$0
+	RET
+
+TEXT runtime·exit(SB),7,$-4
+	MOVW	0(FP), R0
+	MOVW	$SYS_exit_group, R7
+	SWI	$0
+	MOVW	$1234, R0
+	MOVW	$1002, R1
+	MOVW	R0, (R1)	// fail hard
+
+TEXT runtime·exit1(SB),7,$-4
+	MOVW	0(FP), R0
+	MOVW	$SYS_exit, R7
+	SWI	$0
+	MOVW	$1234, R0
+	MOVW	$1003, R1
+	MOVW	R0, (R1)	// fail hard
+
+TEXT	runtime·raisesigpipe(SB),7,$-4
+	MOVW	$SYS_gettid, R7
+	SWI	$0
+	// arg 1 tid already in R0 from gettid
+	MOVW	$13, R1	// arg 2 SIGPIPE
+	MOVW	$SYS_tkill, R7
+	SWI	$0
+	RET
+
+TEXT runtime·mmap(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	12(FP), R3
+	MOVW	16(FP), R4
+	MOVW	20(FP), R5
+	MOVW	$SYS_mmap2, R7
+	SWI	$0
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	$SYS_munmap, R7
+	SWI	$0
+	RET
+
+TEXT runtime·madvise(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	$SYS_madvise, R7
+	SWI	$0
+	RET
+
+TEXT runtime·setitimer(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	$SYS_setitimer, R7
+	SWI	$0
+	RET
+
+TEXT runtime·mincore(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	$SYS_mincore, R7
+	SWI	$0
+	RET
+
+TEXT time·now(SB), 7, $32
+	MOVW	$8(R13), R0  // timeval
+	MOVW	$0, R1  // zone
+	MOVW	$SYS_gettimeofday, R7
+	SWI	$0
+	
+	MOVW	8(R13), R0  // sec
+	MOVW	12(R13), R2  // usec
+	
+	MOVW	R0, 0(FP)
+	MOVW	$0, R1
+	MOVW	R1, 4(FP)
+	MOVW	$1000, R3
+	MUL	R3, R2
+	MOVW	R2, 8(FP)
+	RET	
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB),7,$32
+	MOVW	$8(R13), R0  // timeval
+	MOVW	$0, R1  // zone
+	MOVW	$SYS_gettimeofday, R7
+	SWI	$0
+	
+	MOVW	8(R13), R0  // sec
+	MOVW	12(R13), R2  // usec
+	
+	MOVW	$1000000000, R3
+	MULLU	R0, R3, (R1, R0)
+	MOVW	$1000, R3
+	MOVW	$0, R4
+	MUL	R3, R2
+	ADD.S	R2, R0
+	ADC	R4, R1
+	
+	MOVW	0(FP), R3
+	MOVW	R0, 0(R3)
+	MOVW	R1, 4(R3)
+	RET
+
+// int32 futex(int32 *uaddr, int32 op, int32 val,
+//	struct timespec *timeout, int32 *uaddr2, int32 val2);
+TEXT runtime·futex(SB),7,$0
+	MOVW	4(SP), R0
+	MOVW	8(SP), R1
+	MOVW	12(SP), R2
+	MOVW	16(SP), R3
+	MOVW	20(SP), R4
+	MOVW	24(SP), R5
+	MOVW	$SYS_futex, R7
+	SWI	$0
+	RET
+
+
+// int32 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+TEXT runtime·clone(SB),7,$0
+	MOVW	flags+0(FP), R0
+	MOVW	stack+4(FP), R1
+	MOVW	$0, R2	// parent tid ptr
+	MOVW	$0, R3	// tls_val
+	MOVW	$0, R4	// child tid ptr
+	MOVW	$0, R5
+
+	// Copy m, g, fn off parent stack for use by child.
+	// TODO(kaib): figure out which registers are clobbered by clone and avoid stack copying
+	MOVW	$-16(R1), R1
+	MOVW	mm+8(FP), R6
+	MOVW	R6, 0(R1)
+	MOVW	gg+12(FP), R6
+	MOVW	R6, 4(R1)
+	MOVW	fn+16(FP), R6
+	MOVW	R6, 8(R1)
+	MOVW	$1234, R6
+	MOVW	R6, 12(R1)
+
+	MOVW	$SYS_clone, R7
+	SWI	$0
+
+	// In parent, return.
+	CMP	$0, R0
+	BEQ	2(PC)
+	RET
+
+	// Paranoia: check that SP is as we expect. Use R13 to avoid linker 'fixup'
+	MOVW	12(R13), R0
+	MOVW	$1234, R1
+	CMP	R0, R1
+	BEQ	2(PC)
+	BL	runtime·abort(SB)
+
+	MOVW	0(R13), m
+	MOVW	4(R13), g
+
+	// paranoia; check they are not nil
+	MOVW	0(m), R0
+	MOVW	0(g), R0
+
+	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
+
+	// Initialize m->procid to Linux tid
+	MOVW	$SYS_gettid, R7
+	SWI	$0
+	MOVW	R0, m_procid(m)
+
+	// Call fn
+	MOVW	8(R13), R0
+	MOVW	$16(R13), R13
+	BL	(R0)
+
+	MOVW	$0, R0
+	MOVW	R0, 4(R13)
+	BL	runtime·exit1(SB)
+
+	// It shouldn't return
+	MOVW	$1234, R0
+	MOVW	$1005, R1
+	MOVW	R0, (R1)
+
+
+TEXT runtime·cacheflush(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	$0, R2
+	MOVW	$SYS_ARM_cacheflush, R7
+	SWI	$0
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	$SYS_sigaltstack, R7
+	SWI	$0
+	RET
+
+TEXT runtime·sigignore(SB),7,$0
+	RET
+
+TEXT runtime·sigtramp(SB),7,$24
+	// save g
+	MOVW	g, R3
+	MOVW	g, 20(R13)
+
+	// g = m->gsignal
+	MOVW	m_gsignal(m), g
+
+	// copy arguments for call to sighandler
+	MOVW	R0, 4(R13)
+	MOVW	R1, 8(R13)
+	MOVW	R2, 12(R13)
+	MOVW	R3, 16(R13)
+
+	BL	runtime·sighandler(SB)
+
+	// restore g
+	MOVW	20(R13), g
+
+	RET
+
+TEXT runtime·rt_sigaction(SB),7,$0
+	MOVW	0(FP), R0
+	MOVW	4(FP), R1
+	MOVW	8(FP), R2
+	MOVW	12(FP), R3
+	MOVW	$SYS_rt_sigaction, R7
+	SWI	$0
+	RET
+
+TEXT runtime·sigreturn(SB),7,$0
+	MOVW	$SYS_rt_sigreturn, R7
+	SWI	$0
+	RET
+
+TEXT runtime·usleep(SB),7,$12
+	MOVW	usec+0(FP), R0
+	MOVW	R0, R1
+	MOVW	$1000000, R2
+	DIV	R2, R0
+	MOD	R2, R1
+	MOVW	R0, 4(SP)
+	MOVW	R1, 8(SP)
+	MOVW	$0, R0
+	MOVW	$0, R1
+	MOVW	$0, R2
+	MOVW	$0, R3
+	MOVW	$4(SP), R4
+	MOVW	$SYS_select, R7
+	SWI	$0
+	RET
+
+// Use kernel version instead of native armcas in ../../arm.s.
+// See ../../../sync/atomic/asm_linux_arm.s for details.
+TEXT cas<>(SB),7,$0
+	MOVW	$0xffff0fc0, PC
+
+TEXT runtime·cas(SB),7,$0
+	MOVW	valptr+0(FP), R2
+	MOVW	old+4(FP), R0
+casagain:
+	MOVW	new+8(FP), R1
+	BL	cas<>(SB)
+	BCC	cascheck
+	MOVW $1, R0
+	RET
+cascheck:
+	// Kernel lies; double-check.
+	MOVW	valptr+0(FP), R2
+	MOVW	old+4(FP), R0
+	MOVW	0(R2), R3
+	CMP	R0, R3
+	BEQ	casagain
+	MOVW $0, R0
+	RET
+
+
+TEXT runtime·casp(SB),7,$0
+	B	runtime·cas(SB)
+
+TEXT runtime·osyield(SB),7,$0
+	MOVW	$SYS_sched_yield, R7
+	SWI	$0
+	RET
diff --git a/src/pkg/runtime/sys_netbsd_386.s b/src/pkg/runtime/sys_netbsd_386.s
new file mode 100644
index 0000000..6322861
--- /dev/null
+++ b/src/pkg/runtime/sys_netbsd_386.s
@@ -0,0 +1,324 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// System calls and other sys.stuff for 386, NetBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-4
+	MOVL	$1, AX
+	INT	$0x80
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·exit1(SB),7,$-4
+	MOVL	$302, AX		// sys_threxit
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·write(SB),7,$-4
+	MOVL	$4, AX			// sys_write
+	INT	$0x80
+	RET
+
+TEXT runtime·usleep(SB),7,$20
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVL	AX, 12(SP)		// tv_sec
+	MOVL	$1000, AX
+	MULL	DX
+	MOVL	AX, 16(SP)		// tv_nsec
+
+	MOVL	$0, 0(SP)
+	LEAL	12(SP), AX
+	MOVL	AX, 4(SP)		// arg 1 - rqtp
+	MOVL	$0, 8(SP)		// arg 2 - rmtp
+	MOVL	$240, AX		// sys_nanosleep
+	INT	$0x80
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$12
+	MOVL	$299, AX		// sys_getthrid
+	INT	$0x80
+	MOVL	$0, 0(SP)
+	MOVL	AX, 4(SP)		// arg 1 - pid
+	MOVL	$13, 8(SP)		// arg 2 - signum == SIGPIPE
+	MOVL	$37, AX			// sys_kill
+	INT	$0x80
+	RET
+
+TEXT runtime·notok(SB),7,$0
+	MOVL	$0xf1, 0xf1
+	RET
+
+TEXT runtime·mmap(SB),7,$36
+	LEAL	arg0+0(FP), SI
+	LEAL	4(SP), DI
+	CLD
+	MOVSL				// arg 1 - addr
+	MOVSL				// arg 2 - len
+	MOVSL				// arg 3 - prot
+	MOVSL				// arg 4 - flags
+	MOVSL				// arg 5 - fd
+	MOVL	$0, AX
+	STOSL				// arg 6 - pad
+	MOVSL				// arg 7 - offset
+	MOVL	$0, AX			// top 64 bits of file offset
+	STOSL
+	MOVL	$197, AX		// sys_mmap
+	INT	$0x80
+	JCC	2(PC)
+	NEGL	AX
+	RET
+
+TEXT runtime·munmap(SB),7,$-4
+	MOVL	$73, AX			// sys_munmap
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·setitimer(SB),7,$-4
+	MOVL	$83, AX
+	INT	$0x80
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	MOVL	$116, AX
+	LEAL	12(SP), BX
+	MOVL	BX, 4(SP)
+	MOVL	$0, 8(SP)
+	INT	$0x80
+	MOVL	12(SP), AX		// sec
+	MOVL	16(SP), BX		// usec
+
+	// sec is in AX, usec in BX
+	MOVL	AX, sec+0(FP)
+	MOVL	$0, sec+4(FP)
+	IMULL	$1000, BX
+	MOVL	BX, nsec+8(FP)
+	RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB),7,$32
+	MOVL	$116, AX
+	LEAL	12(SP), BX
+	MOVL	BX, 4(SP)
+	MOVL	$0, 8(SP)
+	INT	$0x80
+	MOVL	12(SP), AX		// sec
+	MOVL	16(SP), BX		// usec
+
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
+	RET
+
+TEXT runtime·sigaction(SB),7,$-4
+	MOVL	$46, AX			// sys_sigaction
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$44
+	get_tls(CX)
+
+	// save g
+	MOVL	g(CX), DI
+	MOVL	DI, 20(SP)
+	
+	// g = m->gsignal
+	MOVL	m(CX), BX
+	MOVL	m_gsignal(BX), BX
+	MOVL	BX, g(CX)
+
+	// copy arguments for call to sighandler
+	MOVL	signo+0(FP), BX
+	MOVL	BX, 0(SP)
+	MOVL	info+4(FP), BX
+	MOVL	BX, 4(SP)
+	MOVL	context+8(FP), BX
+	MOVL	BX, 8(SP)
+	MOVL	DI, 12(SP)
+
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(CX)
+	MOVL	20(SP), BX
+	MOVL	BX, g(CX)
+	
+	// call sigreturn
+	MOVL	context+8(FP), AX
+	MOVL	$0, 0(SP)		// syscall gap
+	MOVL	AX, 4(SP)		// arg 1 - sigcontext
+	MOVL	$103, AX		// sys_sigreturn
+	INT	$0x80
+	CALL	runtime·notok(SB)
+	RET
+
+// int32 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+TEXT runtime·rfork_thread(SB),7,$8
+	MOVL	flags+8(SP), AX
+	MOVL	stack+12(SP), CX
+
+	// Copy m, g, fn off parent stack for use by child.
+	SUBL	$16, CX
+	MOVL	mm+16(SP), SI
+	MOVL	SI, 0(CX)
+	MOVL	gg+20(SP), SI
+	MOVL	SI, 4(CX)
+	MOVL	fn+24(SP), SI
+	MOVL	SI, 8(CX)
+	MOVL	$1234, 12(CX)
+	MOVL	CX, SI
+
+	MOVL	$0, 0(SP)		// syscall gap
+	MOVL	AX, 4(SP)		// arg 1 - flags
+	MOVL	$251, AX		// sys_rfork
+	INT	$0x80
+
+	// Return if rfork syscall failed
+	JCC	4(PC)
+	NEGL	AX
+	MOVL	AX, 48(SP)
+	RET
+
+	// In parent, return.
+	CMPL	AX, $0
+	JEQ	3(PC)
+	MOVL	AX, 48(SP)
+	RET
+
+	// In child, on new stack.
+	MOVL    SI, SP
+
+	// Paranoia: check that SP is as we expect.
+	MOVL	12(SP), BP
+	CMPL	BP, $1234
+	JEQ	2(PC)
+	INT	$3
+
+	// Reload registers
+	MOVL	0(SP), BX		// m
+	MOVL	4(SP), DX		// g
+	MOVL	8(SP), SI		// fn
+
+	// Initialize m->procid to thread ID
+	MOVL	$299, AX		// sys_getthrid
+	INT	$0x80
+	MOVL	AX, m_procid(BX)
+
+	// Set FS to point at m->tls
+	LEAL	m_tls(BX), BP
+	PUSHAL				// save registers
+	PUSHL	BP
+	CALL	runtime·settls(SB)
+	POPL	AX
+	POPAL
+	
+	// Now segment is established.  Initialize m, g.
+	get_tls(AX)
+	MOVL	DX, g(AX)
+	MOVL	BX, m(AX)
+
+	CALL	runtime·stackcheck(SB)	// smashes AX, CX
+	MOVL	0(DX), DX		// paranoia; check they are not nil
+	MOVL	0(BX), BX
+
+	// more paranoia; check that stack splitting code works
+	PUSHAL
+	CALL	runtime·emptyfunc(SB)
+	POPAL
+
+	// Call fn
+	CALL	SI
+
+	CALL	runtime·exit1(SB)
+	MOVL	$0x1234, 0x1005
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$-8
+	MOVL	$288, AX		// sys_sigaltstack
+	MOVL	new+4(SP), BX
+	MOVL	old+8(SP), CX
+	INT	$0x80
+	CMPL	AX, $0xfffff001
+	JLS	2(PC)
+	INT	$3
+	RET
+
+TEXT runtime·setldt(SB),7,$8
+	// Under NetBSD we set the GS base instead of messing with the LDT.
+	MOVL	16(SP), AX		// tls0
+	MOVL	AX, 0(SP)
+	CALL	runtime·settls(SB)
+	RET
+
+TEXT runtime·settls(SB),7,$16
+	// adjust for ELF: wants to use -8(GS) and -4(GS) for g and m
+	MOVL	20(SP), CX
+	ADDL	$8, CX
+	MOVL	CX, 0(CX)
+	MOVL	$0, 0(SP)		// syscall gap
+	MOVL	$9, 4(SP)		// I386_SET_GSBASE (machine/sysarch.h)
+	MOVL	CX, 8(SP)		// pointer to base
+	MOVL	$165, AX		// sys_sysarch
+	INT	$0x80
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·osyield(SB),7,$-4
+	MOVL	$298, AX		// sys_sched_yield
+	INT	$0x80
+	RET
+
+TEXT runtime·thrsleep(SB),7,$-4
+	MOVL	$300, AX		// sys_thrsleep
+	INT	$0x80
+	RET
+
+TEXT runtime·thrwakeup(SB),7,$-4
+	MOVL	$301, AX		// sys_thrwakeup
+	INT	$0x80
+	RET
+
+TEXT runtime·sysctl(SB),7,$28
+	LEAL	arg0+0(FP), SI
+	LEAL	4(SP), DI
+	CLD
+	MOVSL				// arg 1 - name
+	MOVSL				// arg 2 - namelen
+	MOVSL				// arg 3 - oldp
+	MOVSL				// arg 4 - oldlenp
+	MOVSL				// arg 5 - newp
+	MOVSL				// arg 6 - newlen
+	MOVL	$202, AX		// sys___sysctl
+	INT	$0x80
+	JCC	3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
+
+GLOBL runtime·tlsoffset(SB),$4
diff --git a/src/pkg/runtime/sys_netbsd_amd64.s b/src/pkg/runtime/sys_netbsd_amd64.s
new file mode 100644
index 0000000..7abeb15
--- /dev/null
+++ b/src/pkg/runtime/sys_netbsd_amd64.s
@@ -0,0 +1,268 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// System calls and other sys.stuff for AMD64, NetBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+// int64 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+TEXT runtime·rfork_thread(SB),7,$0
+	MOVL	flags+8(SP), DI
+	MOVQ	stack+16(SP), SI
+
+	// Copy m, g, fn off parent stack for use by child.
+	MOVQ	mm+24(SP), R8
+	MOVQ	gg+32(SP), R9
+	MOVQ	fn+40(SP), R12
+
+	MOVL	$251, AX		// sys_rfork
+	SYSCALL
+
+	// Return if rfork syscall failed
+	JCC	3(PC)
+	NEGL	AX
+	RET
+
+	// In parent, return.
+	CMPL	AX, $0
+	JEQ	2(PC)
+	RET
+
+	// In child, on new stack.
+	MOVQ	SI, SP
+
+	// Initialize m->procid to thread ID
+	MOVL	$299, AX		// sys_getthrid
+	SYSCALL
+	MOVQ	AX, m_procid(R8)
+
+	// Set FS to point at m->tls.
+	LEAQ	m_tls(R8), DI
+	CALL	runtime·settls(SB)
+
+	// In child, set up new stack
+	get_tls(CX)
+	MOVQ	R8, m(CX)
+	MOVQ	R9, g(CX)
+	CALL	runtime·stackcheck(SB)
+
+	// Call fn
+	CALL	R12
+
+	// It shouldn't return.  If it does, exit
+	MOVL	$302, AX		// sys_threxit
+	SYSCALL
+	JMP	-3(PC)			// keep exiting
+
+TEXT runtime·osyield(SB),7,$0
+	MOVL $298, AX			// sys_sched_yield
+	SYSCALL
+	RET
+
+TEXT runtime·thrsleep(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - ident
+	MOVL	16(SP), SI		// arg 2 - clock_id
+	MOVQ	24(SP), DX		// arg 3 - tp
+	MOVQ	32(SP), R10		// arg 4 - lock
+	MOVL	$300, AX		// sys_thrsleep
+	SYSCALL
+	RET
+
+TEXT runtime·thrwakeup(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - ident
+	MOVL	16(SP), SI		// arg 2 - n
+	MOVL	$301, AX		// sys_thrwakeup
+	SYSCALL
+	RET
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 - exit status
+	MOVL	$1, AX			// sys_exit
+	SYSCALL
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·exit1(SB),7,$-8
+	MOVL	$302, AX		// sys_threxit
+	SYSCALL
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·write(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 - fd
+	MOVQ	16(SP), SI		// arg 2 - buf
+	MOVL	24(SP), DX		// arg 3 - nbyte
+	MOVL	$4, AX			// sys_write
+	SYSCALL
+	RET
+
+TEXT runtime·usleep(SB),7,$16
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVQ	AX, 0(SP)		// tv_sec
+	MOVL	$1000, AX
+	MULL	DX
+	MOVQ	AX, 8(SP)		// tv_nsec
+
+	MOVQ	SP, DI			// arg 1 - rqtp
+	MOVQ	$0, SI			// arg 2 - rmtp
+	MOVL	$240, AX		// sys_nanosleep
+	SYSCALL
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$16
+	MOVL	$299, AX		// sys_getthrid
+	SYSCALL
+	MOVQ	AX, DI			// arg 1 - pid
+	MOVQ	$13, SI			// arg 2 - signum == SIGPIPE
+	MOVL	$37, AX			// sys_kill
+	SYSCALL
+	RET
+
+TEXT runtime·setitimer(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 - which
+	MOVQ	16(SP), SI		// arg 2 - itv
+	MOVQ	24(SP), DX		// arg 3 - oitv
+	MOVL	$83, AX			// sys_setitimer
+	SYSCALL
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	LEAQ	8(SP), DI		// arg 1 - tp
+	MOVQ	$0, SI			// arg 2 - tzp
+	MOVL	$116, AX		// sys_gettimeofday
+	SYSCALL
+	MOVQ	8(SP), AX		// sec
+	MOVL	16(SP), DX	// usec
+
+	// sec is in AX, usec in DX
+	MOVQ	AX, sec+0(FP)
+	IMULQ	$1000, DX
+	MOVL	DX, nsec+8(FP)
+	RET
+
+TEXT runtime·nanotime(SB),7,$32
+	LEAQ	8(SP), DI		// arg 1 - tp
+	MOVQ	$0, SI			// arg 2 - tzp
+	MOVL	$116, AX		// sys_gettimeofday
+	SYSCALL
+	MOVQ	8(SP), AX		// sec
+	MOVL	16(SP), DX	// usec
+
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
+	RET
+
+TEXT runtime·sigaction(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 - signum
+	MOVQ	16(SP), SI		// arg 2 - nsa
+	MOVQ	24(SP), DX		// arg 3 - osa
+	MOVL	$46, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$64
+	get_tls(BX)
+	
+	// save g
+	MOVQ	g(BX), R10
+	MOVQ	R10, 40(SP)
+	
+	// g = m->signal
+	MOVQ	m(BX), BP
+	MOVQ	m_gsignal(BP), BP
+	MOVQ	BP, g(BX)
+	
+	MOVQ	DI, 0(SP)
+	MOVQ	SI, 8(SP)
+	MOVQ	DX, 16(SP)
+	MOVQ	R10, 24(SP)
+	
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(BX)
+	MOVQ	40(SP), R10
+	MOVQ	R10, g(BX)
+	RET
+
+TEXT runtime·mmap(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - addr
+	MOVQ	16(SP), SI		// arg 2 - len
+	MOVL	24(SP), DX		// arg 3 - prot
+	MOVL	28(SP), R10		// arg 4 - flags
+	MOVL	32(SP), R8		// arg 5 - fd
+	MOVQ	36(SP), R9
+	SUBQ	$16, SP
+	MOVQ	R9, 8(SP)		// arg 7 - offset (passed on stack)
+	MOVQ	$0, R9			// arg 6 - pad
+	MOVL	$197, AX
+	SYSCALL
+	JCC	2(PC)
+	NEGL	AX
+	ADDQ	$16, SP
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - addr
+	MOVQ	16(SP), SI		// arg 2 - len
+	MOVL	$73, AX			// sys_munmap
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·notok(SB),7,$-8
+	MOVL	$0xf1, BP
+	MOVQ	BP, (BP)
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$-8
+	MOVQ	new+8(SP), DI		// arg 1 - nss
+	MOVQ	old+16(SP), SI		// arg 2 - oss
+	MOVQ	$288, AX		// sys_sigaltstack
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+// set tls base to DI
+TEXT runtime·settls(SB),7,$8
+	// adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
+	ADDQ	$16, DI
+	MOVQ	DI, 0(SP)
+	MOVQ	SP, SI
+	MOVQ	$12, DI			// AMD64_SET_FSBASE (machine/sysarch.h)
+	MOVQ	$165, AX		// sys_sysarch
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sysctl(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - name
+	MOVL	16(SP), SI		// arg 2 - namelen
+	MOVQ	24(SP), DX		// arg 3 - oldp
+	MOVQ	32(SP), R10		// arg 4 - oldlenp
+	MOVQ	40(SP), R8		// arg 5 - newp
+	MOVQ	48(SP), R9		// arg 6 - newlen
+	MOVQ	$202, AX		// sys___sysctl
+	SYSCALL
+	JCC 3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
+
diff --git a/src/pkg/runtime/sys_openbsd_386.s b/src/pkg/runtime/sys_openbsd_386.s
new file mode 100644
index 0000000..d49d32b
--- /dev/null
+++ b/src/pkg/runtime/sys_openbsd_386.s
@@ -0,0 +1,324 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// System calls and other sys.stuff for 386, OpenBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-4
+	MOVL	$1, AX
+	INT	$0x80
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·exit1(SB),7,$-4
+	MOVL	$302, AX		// sys_threxit
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·write(SB),7,$-4
+	MOVL	$4, AX			// sys_write
+	INT	$0x80
+	RET
+
+TEXT runtime·usleep(SB),7,$20
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVL	AX, 12(SP)		// tv_sec
+	MOVL	$1000, AX
+	MULL	DX
+	MOVL	AX, 16(SP)		// tv_nsec
+
+	MOVL	$0, 0(SP)
+	LEAL	12(SP), AX
+	MOVL	AX, 4(SP)		// arg 1 - rqtp
+	MOVL	$0, 8(SP)		// arg 2 - rmtp
+	MOVL	$240, AX		// sys_nanosleep
+	INT	$0x80
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$12
+	MOVL	$299, AX		// sys_getthrid
+	INT	$0x80
+	MOVL	$0, 0(SP)
+	MOVL	AX, 4(SP)		// arg 1 - pid
+	MOVL	$13, 8(SP)		// arg 2 - signum == SIGPIPE
+	MOVL	$37, AX			// sys_kill
+	INT	$0x80
+	RET
+
+TEXT runtime·notok(SB),7,$0
+	MOVL	$0xf1, 0xf1
+	RET
+
+TEXT runtime·mmap(SB),7,$36
+	LEAL	arg0+0(FP), SI
+	LEAL	4(SP), DI
+	CLD
+	MOVSL				// arg 1 - addr
+	MOVSL				// arg 2 - len
+	MOVSL				// arg 3 - prot
+	MOVSL				// arg 4 - flags
+	MOVSL				// arg 5 - fd
+	MOVL	$0, AX
+	STOSL				// arg 6 - pad
+	MOVSL				// arg 7 - offset
+	MOVL	$0, AX			// top 64 bits of file offset
+	STOSL
+	MOVL	$197, AX		// sys_mmap
+	INT	$0x80
+	JCC	2(PC)
+	NEGL	AX
+	RET
+
+TEXT runtime·munmap(SB),7,$-4
+	MOVL	$73, AX			// sys_munmap
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·setitimer(SB),7,$-4
+	MOVL	$83, AX
+	INT	$0x80
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	MOVL	$116, AX
+	LEAL	12(SP), BX
+	MOVL	BX, 4(SP)
+	MOVL	$0, 8(SP)
+	INT	$0x80
+	MOVL	12(SP), AX		// sec
+	MOVL	16(SP), BX		// usec
+
+	// sec is in AX, usec in BX
+	MOVL	AX, sec+0(FP)
+	MOVL	$0, sec+4(FP)
+	IMULL	$1000, BX
+	MOVL	BX, nsec+8(FP)
+	RET
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB),7,$32
+	MOVL	$116, AX
+	LEAL	12(SP), BX
+	MOVL	BX, 4(SP)
+	MOVL	$0, 8(SP)
+	INT	$0x80
+	MOVL	12(SP), AX		// sec
+	MOVL	16(SP), BX		// usec
+
+	// sec is in AX, usec in BX
+	// convert to DX:AX nsec
+	MOVL	$1000000000, CX
+	MULL	CX
+	IMULL	$1000, BX
+	ADDL	BX, AX
+	ADCL	$0, DX
+	
+	MOVL	ret+0(FP), DI
+	MOVL	AX, 0(DI)
+	MOVL	DX, 4(DI)
+	RET
+
+TEXT runtime·sigaction(SB),7,$-4
+	MOVL	$46, AX			// sys_sigaction
+	INT	$0x80
+	JAE	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$44
+	get_tls(CX)
+
+	// save g
+	MOVL	g(CX), DI
+	MOVL	DI, 20(SP)
+	
+	// g = m->gsignal
+	MOVL	m(CX), BX
+	MOVL	m_gsignal(BX), BX
+	MOVL	BX, g(CX)
+
+	// copy arguments for call to sighandler
+	MOVL	signo+0(FP), BX
+	MOVL	BX, 0(SP)
+	MOVL	info+4(FP), BX
+	MOVL	BX, 4(SP)
+	MOVL	context+8(FP), BX
+	MOVL	BX, 8(SP)
+	MOVL	DI, 12(SP)
+
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(CX)
+	MOVL	20(SP), BX
+	MOVL	BX, g(CX)
+	
+	// call sigreturn
+	MOVL	context+8(FP), AX
+	MOVL	$0, 0(SP)		// syscall gap
+	MOVL	AX, 4(SP)		// arg 1 - sigcontext
+	MOVL	$103, AX		// sys_sigreturn
+	INT	$0x80
+	CALL	runtime·notok(SB)
+	RET
+
+// int32 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+TEXT runtime·rfork_thread(SB),7,$8
+	MOVL	flags+8(SP), AX
+	MOVL	stack+12(SP), CX
+
+	// Copy m, g, fn off parent stack for use by child.
+	SUBL	$16, CX
+	MOVL	mm+16(SP), SI
+	MOVL	SI, 0(CX)
+	MOVL	gg+20(SP), SI
+	MOVL	SI, 4(CX)
+	MOVL	fn+24(SP), SI
+	MOVL	SI, 8(CX)
+	MOVL	$1234, 12(CX)
+	MOVL	CX, SI
+
+	MOVL	$0, 0(SP)		// syscall gap
+	MOVL	AX, 4(SP)		// arg 1 - flags
+	MOVL	$251, AX		// sys_rfork
+	INT	$0x80
+
+	// Return if rfork syscall failed
+	JCC	4(PC)
+	NEGL	AX
+	MOVL	AX, 48(SP)
+	RET
+
+	// In parent, return.
+	CMPL	AX, $0
+	JEQ	3(PC)
+	MOVL	AX, 48(SP)
+	RET
+
+	// In child, on new stack.
+	MOVL    SI, SP
+
+	// Paranoia: check that SP is as we expect.
+	MOVL	12(SP), BP
+	CMPL	BP, $1234
+	JEQ	2(PC)
+	INT	$3
+
+	// Reload registers
+	MOVL	0(SP), BX		// m
+	MOVL	4(SP), DX		// g
+	MOVL	8(SP), SI		// fn
+
+	// Initialize m->procid to thread ID
+	MOVL	$299, AX		// sys_getthrid
+	INT	$0x80
+	MOVL	AX, m_procid(BX)
+
+	// Set FS to point at m->tls
+	LEAL	m_tls(BX), BP
+	PUSHAL				// save registers
+	PUSHL	BP
+	CALL	runtime·settls(SB)
+	POPL	AX
+	POPAL
+	
+	// Now segment is established.  Initialize m, g.
+	get_tls(AX)
+	MOVL	DX, g(AX)
+	MOVL	BX, m(AX)
+
+	CALL	runtime·stackcheck(SB)	// smashes AX, CX
+	MOVL	0(DX), DX		// paranoia; check they are not nil
+	MOVL	0(BX), BX
+
+	// more paranoia; check that stack splitting code works
+	PUSHAL
+	CALL	runtime·emptyfunc(SB)
+	POPAL
+
+	// Call fn
+	CALL	SI
+
+	CALL	runtime·exit1(SB)
+	MOVL	$0x1234, 0x1005
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$-8
+	MOVL	$288, AX		// sys_sigaltstack
+	MOVL	new+4(SP), BX
+	MOVL	old+8(SP), CX
+	INT	$0x80
+	CMPL	AX, $0xfffff001
+	JLS	2(PC)
+	INT	$3
+	RET
+
+TEXT runtime·setldt(SB),7,$8
+	// Under OpenBSD we set the GS base instead of messing with the LDT.
+	MOVL	16(SP), AX		// tls0
+	MOVL	AX, 0(SP)
+	CALL	runtime·settls(SB)
+	RET
+
+TEXT runtime·settls(SB),7,$16
+	// adjust for ELF: wants to use -8(GS) and -4(GS) for g and m
+	MOVL	20(SP), CX
+	ADDL	$8, CX
+	MOVL	CX, 0(CX)
+	MOVL	$0, 0(SP)		// syscall gap
+	MOVL	$9, 4(SP)		// I386_SET_GSBASE (machine/sysarch.h)
+	MOVL	CX, 8(SP)		// pointer to base
+	MOVL	$165, AX		// sys_sysarch
+	INT	$0x80
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·osyield(SB),7,$-4
+	MOVL	$298, AX		// sys_sched_yield
+	INT	$0x80
+	RET
+
+TEXT runtime·thrsleep(SB),7,$-4
+	MOVL	$300, AX		// sys_thrsleep
+	INT	$0x80
+	RET
+
+TEXT runtime·thrwakeup(SB),7,$-4
+	MOVL	$301, AX		// sys_thrwakeup
+	INT	$0x80
+	RET
+
+TEXT runtime·sysctl(SB),7,$28
+	LEAL	arg0+0(FP), SI
+	LEAL	4(SP), DI
+	CLD
+	MOVSL				// arg 1 - name
+	MOVSL				// arg 2 - namelen
+	MOVSL				// arg 3 - oldp
+	MOVSL				// arg 4 - oldlenp
+	MOVSL				// arg 5 - newp
+	MOVSL				// arg 6 - newlen
+	MOVL	$202, AX		// sys___sysctl
+	INT	$0x80
+	JCC	3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
+
+GLOBL runtime·tlsoffset(SB),$4
diff --git a/src/pkg/runtime/sys_openbsd_amd64.s b/src/pkg/runtime/sys_openbsd_amd64.s
new file mode 100644
index 0000000..5bf2e81
--- /dev/null
+++ b/src/pkg/runtime/sys_openbsd_amd64.s
@@ -0,0 +1,268 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// System calls and other sys.stuff for AMD64, OpenBSD
+// /usr/src/sys/kern/syscalls.master for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+
+// int64 rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+TEXT runtime·rfork_thread(SB),7,$0
+	MOVL	flags+8(SP), DI
+	MOVQ	stack+16(SP), SI
+
+	// Copy m, g, fn off parent stack for use by child.
+	MOVQ	mm+24(SP), R8
+	MOVQ	gg+32(SP), R9
+	MOVQ	fn+40(SP), R12
+
+	MOVL	$251, AX		// sys_rfork
+	SYSCALL
+
+	// Return if rfork syscall failed
+	JCC	3(PC)
+	NEGL	AX
+	RET
+
+	// In parent, return.
+	CMPL	AX, $0
+	JEQ	2(PC)
+	RET
+
+	// In child, on new stack.
+	MOVQ	SI, SP
+
+	// Initialize m->procid to thread ID
+	MOVL	$299, AX		// sys_getthrid
+	SYSCALL
+	MOVQ	AX, m_procid(R8)
+
+	// Set FS to point at m->tls.
+	LEAQ	m_tls(R8), DI
+	CALL	runtime·settls(SB)
+
+	// In child, set up new stack
+	get_tls(CX)
+	MOVQ	R8, m(CX)
+	MOVQ	R9, g(CX)
+	CALL	runtime·stackcheck(SB)
+
+	// Call fn
+	CALL	R12
+
+	// It shouldn't return.  If it does, exit
+	MOVL	$302, AX		// sys_threxit
+	SYSCALL
+	JMP	-3(PC)			// keep exiting
+
+TEXT runtime·osyield(SB),7,$0
+	MOVL $298, AX			// sys_sched_yield
+	SYSCALL
+	RET
+
+TEXT runtime·thrsleep(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - ident
+	MOVL	16(SP), SI		// arg 2 - clock_id
+	MOVQ	24(SP), DX		// arg 3 - tp
+	MOVQ	32(SP), R10		// arg 4 - lock
+	MOVL	$300, AX		// sys_thrsleep
+	SYSCALL
+	RET
+
+TEXT runtime·thrwakeup(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - ident
+	MOVL	16(SP), SI		// arg 2 - n
+	MOVL	$301, AX		// sys_thrwakeup
+	SYSCALL
+	RET
+
+// Exit the entire program (like C exit)
+TEXT runtime·exit(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 - exit status
+	MOVL	$1, AX			// sys_exit
+	SYSCALL
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·exit1(SB),7,$-8
+	MOVL	$302, AX		// sys_threxit
+	SYSCALL
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·write(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 - fd
+	MOVQ	16(SP), SI		// arg 2 - buf
+	MOVL	24(SP), DX		// arg 3 - nbyte
+	MOVL	$4, AX			// sys_write
+	SYSCALL
+	RET
+
+TEXT runtime·usleep(SB),7,$16
+	MOVL	$0, DX
+	MOVL	usec+0(FP), AX
+	MOVL	$1000000, CX
+	DIVL	CX
+	MOVQ	AX, 0(SP)		// tv_sec
+	MOVL	$1000, AX
+	MULL	DX
+	MOVQ	AX, 8(SP)		// tv_nsec
+
+	MOVQ	SP, DI			// arg 1 - rqtp
+	MOVQ	$0, SI			// arg 2 - rmtp
+	MOVL	$240, AX		// sys_nanosleep
+	SYSCALL
+	RET
+
+TEXT runtime·raisesigpipe(SB),7,$16
+	MOVL	$299, AX		// sys_getthrid
+	SYSCALL
+	MOVQ	AX, DI			// arg 1 - pid
+	MOVQ	$13, SI			// arg 2 - signum == SIGPIPE
+	MOVL	$37, AX			// sys_kill
+	SYSCALL
+	RET
+
+TEXT runtime·setitimer(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 - which
+	MOVQ	16(SP), SI		// arg 2 - itv
+	MOVQ	24(SP), DX		// arg 3 - oitv
+	MOVL	$83, AX			// sys_setitimer
+	SYSCALL
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB), 7, $32
+	LEAQ	8(SP), DI		// arg 1 - tp
+	MOVQ	$0, SI			// arg 2 - tzp
+	MOVL	$116, AX		// sys_gettimeofday
+	SYSCALL
+	MOVQ	8(SP), AX		// sec
+	MOVL	16(SP), DX	// usec
+
+	// sec is in AX, usec in DX
+	MOVQ	AX, sec+0(FP)
+	IMULQ	$1000, DX
+	MOVL	DX, nsec+8(FP)
+	RET
+
+TEXT runtime·nanotime(SB),7,$32
+	LEAQ	8(SP), DI		// arg 1 - tp
+	MOVQ	$0, SI			// arg 2 - tzp
+	MOVL	$116, AX		// sys_gettimeofday
+	SYSCALL
+	MOVQ	8(SP), AX		// sec
+	MOVL	16(SP), DX	// usec
+
+	// sec is in AX, usec in DX
+	// return nsec in AX
+	IMULQ	$1000000000, AX
+	IMULQ	$1000, DX
+	ADDQ	DX, AX
+	RET
+
+TEXT runtime·sigaction(SB),7,$-8
+	MOVL	8(SP), DI		// arg 1 - signum
+	MOVQ	16(SP), SI		// arg 2 - nsa
+	MOVQ	24(SP), DX		// arg 3 - osa
+	MOVL	$46, AX
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$64
+	get_tls(BX)
+	
+	// save g
+	MOVQ	g(BX), R10
+	MOVQ	R10, 40(SP)
+	
+	// g = m->signal
+	MOVQ	m(BX), BP
+	MOVQ	m_gsignal(BP), BP
+	MOVQ	BP, g(BX)
+	
+	MOVQ	DI, 0(SP)
+	MOVQ	SI, 8(SP)
+	MOVQ	DX, 16(SP)
+	MOVQ	R10, 24(SP)
+	
+	CALL	runtime·sighandler(SB)
+
+	// restore g
+	get_tls(BX)
+	MOVQ	40(SP), R10
+	MOVQ	R10, g(BX)
+	RET
+
+TEXT runtime·mmap(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - addr
+	MOVQ	16(SP), SI		// arg 2 - len
+	MOVL	24(SP), DX		// arg 3 - prot
+	MOVL	28(SP), R10		// arg 4 - flags
+	MOVL	32(SP), R8		// arg 5 - fd
+	MOVQ	36(SP), R9
+	SUBQ	$16, SP
+	MOVQ	R9, 8(SP)		// arg 7 - offset (passed on stack)
+	MOVQ	$0, R9			// arg 6 - pad
+	MOVL	$197, AX
+	SYSCALL
+	JCC	2(PC)
+	NEGL	AX
+	ADDQ	$16, SP
+	RET
+
+TEXT runtime·munmap(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - addr
+	MOVQ	16(SP), SI		// arg 2 - len
+	MOVL	$73, AX			// sys_munmap
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·notok(SB),7,$-8
+	MOVL	$0xf1, BP
+	MOVQ	BP, (BP)
+	RET
+
+TEXT runtime·sigaltstack(SB),7,$-8
+	MOVQ	new+8(SP), DI		// arg 1 - nss
+	MOVQ	old+16(SP), SI		// arg 2 - oss
+	MOVQ	$288, AX		// sys_sigaltstack
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+// set tls base to DI
+TEXT runtime·settls(SB),7,$8
+	// adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
+	ADDQ	$16, DI
+	MOVQ	DI, 0(SP)
+	MOVQ	SP, SI
+	MOVQ	$12, DI			// AMD64_SET_FSBASE (machine/sysarch.h)
+	MOVQ	$165, AX		// sys_sysarch
+	SYSCALL
+	JCC	2(PC)
+	CALL	runtime·notok(SB)
+	RET
+
+TEXT runtime·sysctl(SB),7,$0
+	MOVQ	8(SP), DI		// arg 1 - name
+	MOVL	16(SP), SI		// arg 2 - namelen
+	MOVQ	24(SP), DX		// arg 3 - oldp
+	MOVQ	32(SP), R10		// arg 4 - oldlenp
+	MOVQ	40(SP), R8		// arg 5 - newp
+	MOVQ	48(SP), R9		// arg 6 - newlen
+	MOVQ	$202, AX		// sys___sysctl
+	SYSCALL
+	JCC 3(PC)
+	NEGL	AX
+	RET
+	MOVL	$0, AX
+	RET
+
diff --git a/src/pkg/runtime/sys_plan9_386.s b/src/pkg/runtime/sys_plan9_386.s
new file mode 100644
index 0000000..94c36aa
--- /dev/null
+++ b/src/pkg/runtime/sys_plan9_386.s
@@ -0,0 +1,97 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "defs_GOOS_GOARCH.h"
+#include "zasm_GOOS_GOARCH.h"
+
+// setldt(int entry, int address, int limit)
+TEXT runtime·setldt(SB),7,$0
+	RET
+
+TEXT runtime·open(SB),7,$0
+	MOVL    $14, AX
+	INT     $64
+	RET
+
+TEXT runtime·pread(SB),7,$0
+	MOVL    $50, AX
+	INT     $64
+	RET
+
+TEXT runtime·pwrite(SB),7,$0
+	MOVL    $51, AX
+	INT     $64
+	RET
+
+TEXT runtime·close(SB),7,$0
+	MOVL	$4, AX
+	INT		$64
+	RET
+
+TEXT runtime·exits(SB),7,$0
+	MOVL    $8, AX
+	INT     $64
+	RET
+
+TEXT runtime·brk_(SB),7,$0
+	MOVL    $24, AX
+	INT     $64
+	RET
+
+TEXT runtime·sleep(SB),7,$0
+	MOVL    $17, AX
+	INT     $64
+	RET
+
+TEXT runtime·plan9_semacquire(SB),7,$0
+	MOVL	$37, AX
+	INT	$64
+	RET
+	
+TEXT runtime·plan9_semrelease(SB),7,$0
+	MOVL	$38, AX
+	INT	$64
+	RET
+	
+TEXT runtime·rfork(SB),7,$0
+	MOVL    $19, AX // rfork
+	INT     $64
+
+	// In parent, return.
+	CMPL	AX, $0
+	JEQ	2(PC)
+	RET
+
+	// In child on old stack.
+	MOVL	mm+12(SP), BX	// m
+	MOVL	gg+16(SP), DX	// g
+	MOVL	fn+20(SP), SI	// fn
+
+	// set SP to be on the new child stack
+	MOVL	stack+8(SP), CX
+	MOVL	CX, SP
+
+	// Initialize m, g.
+	get_tls(AX)
+	MOVL	DX, g(AX)
+	MOVL	BX, m(AX)
+
+	// Initialize AX from _tos->pid
+	MOVL	_tos(SB), AX
+	MOVL	tos_pid(AX), AX
+	MOVL	AX, m_procid(BX)	// save pid as m->procid
+	
+	CALL	runtime·stackcheck(SB)	// smashes AX, CX
+	
+	MOVL	0(DX), DX	// paranoia; check they are not nil
+	MOVL	0(BX), BX
+	
+	// more paranoia; check that stack splitting code works
+	PUSHL	SI
+	CALL	runtime·emptyfunc(SB)
+	POPL	SI
+	
+	CALL	SI	// fn()
+	CALL	runtime·exit(SB)
+	RET
diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s
new file mode 100644
index 0000000..5290f60
--- /dev/null
+++ b/src/pkg/runtime/sys_windows_386.s
@@ -0,0 +1,250 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "zasm_GOOS_GOARCH.h"
+
+// void runtime·asmstdcall(void *c);
+TEXT runtime·asmstdcall(SB),7,$0
+	MOVL	c+0(FP), BX
+
+	// SetLastError(0).
+	MOVL	$0, 0x34(FS)
+
+	// Copy args to the stack.
+	MOVL	SP, BP
+	MOVL	wincall_n(BX), CX	// words
+	MOVL	CX, AX
+	SALL	$2, AX
+	SUBL	AX, SP			// room for args
+	MOVL	SP, DI
+	MOVL	wincall_args(BX), SI
+	CLD
+	REP; MOVSL
+
+	// Call stdcall or cdecl function.
+	// DI SI BP BX are preserved, SP is not
+	CALL	wincall_fn(BX)
+	MOVL	BP, SP
+
+	// Return result.
+	MOVL	c+0(FP), BX
+	MOVL	AX, wincall_r1(BX)
+	MOVL	DX, wincall_r2(BX)
+
+	// GetLastError().
+	MOVL	0x34(FS), AX
+	MOVL	AX, wincall_err(BX)
+
+	RET
+
+// faster get/set last error
+TEXT runtime·getlasterror(SB),7,$0
+	MOVL	0x34(FS), AX
+	RET
+
+TEXT runtime·setlasterror(SB),7,$0
+	MOVL	err+0(FP), AX
+	MOVL	AX, 0x34(FS)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$28
+	// unwinding?
+	MOVL	info+0(FP), CX
+	TESTL	$6, 4(CX)		// exception flags
+	MOVL	$1, AX
+	JNZ	sigdone
+
+	// copy arguments for call to sighandler
+	MOVL	CX, 0(SP)
+	MOVL	context+8(FP), CX
+	MOVL	CX, 4(SP)
+	get_tls(CX)
+	MOVL	g(CX), CX
+	MOVL	CX, 8(SP)
+
+	MOVL	BX, 12(SP)
+	MOVL	BP, 16(SP)
+	MOVL	SI, 20(SP)
+	MOVL	DI, 24(SP)
+
+	CALL	runtime·sighandler(SB)
+	// AX is set to report result back to Windows
+
+	MOVL	24(SP), DI
+	MOVL	20(SP), SI
+	MOVL	16(SP), BP
+	MOVL	12(SP), BX
+sigdone:
+	RET
+
+TEXT runtime·ctrlhandler(SB),7,$0
+	PUSHL	$runtime·ctrlhandler1(SB)
+	CALL	runtime·externalthreadhandler(SB)
+	MOVL	4(SP), CX
+	ADDL	$12, SP
+	JMP	CX
+
+TEXT runtime·profileloop(SB),7,$0
+	PUSHL	$runtime·profileloop1(SB)
+	CALL	runtime·externalthreadhandler(SB)
+	MOVL	4(SP), CX
+	ADDL	$12, SP
+	JMP	CX
+
+TEXT runtime·externalthreadhandler(SB),7,$0
+	PUSHL	BP
+	MOVL	SP, BP
+	PUSHL	BX
+	PUSHL	SI
+	PUSHL	DI
+	PUSHL	0x14(FS)
+	MOVL	SP, DX
+
+	// setup dummy m, g
+	SUBL	$m_end, SP		// space for M
+	MOVL	SP, 0(SP)
+	MOVL	$m_end, 4(SP)
+	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
+
+	LEAL	m_tls(SP), CX
+	MOVL	CX, 0x14(FS)
+	MOVL	SP, m(CX)
+	MOVL	SP, BX
+	SUBL	$g_end, SP		// space for G
+	MOVL	SP, g(CX)
+	MOVL	SP, m_g0(BX)
+
+	MOVL	SP, 0(SP)
+	MOVL	$g_end, 4(SP)
+	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
+	LEAL	-4096(SP), CX
+	MOVL	CX, g_stackguard(SP)
+	MOVL	DX, g_stackbase(SP)
+
+	PUSHL	16(BP)			// arg for handler
+	CALL	8(BP)
+	POPL	CX
+
+	get_tls(CX)
+	MOVL	g(CX), CX
+	MOVL	g_stackbase(CX), SP
+	POPL	0x14(FS)
+	POPL	DI
+	POPL	SI
+	POPL	BX
+	POPL	BP
+	RET
+
+// Called from dynamic function created by ../thread.c compilecallback,
+// running on Windows stack (not Go stack).
+// BX, BP, SI, DI registers and DF flag are preserved
+// as required by windows callback convention.
+// AX = address of go func we need to call
+// DX = total size of arguments
+//
+TEXT runtime·callbackasm+0(SB),7,$0
+	// preserve whatever's at the memory location that
+	// the callback will use to store the return value
+	LEAL	8(SP), CX
+	PUSHL	0(CX)(DX*1)
+	ADDL	$4, DX			// extend argsize by size of return value
+
+	// save registers as required for windows callback
+	PUSHL	DI
+	PUSHL	SI
+	PUSHL	BP
+	PUSHL	BX
+
+	// set up SEH frame again
+	PUSHL	$runtime·sigtramp(SB)
+	PUSHL	0(FS)
+	MOVL	SP, 0(FS)
+
+	// callback parameters
+	PUSHL	DX
+	PUSHL	CX
+	PUSHL	AX
+
+	CLD
+
+	CALL	runtime·cgocallback(SB)
+
+	POPL	AX
+	POPL	CX
+	POPL	DX
+
+	// pop SEH frame
+	POPL	0(FS)
+	POPL	BX
+
+	// restore registers as required for windows callback
+	POPL	BX
+	POPL	BP
+	POPL	SI
+	POPL	DI
+
+	CLD
+
+	MOVL	-4(CX)(DX*1), AX
+	POPL	-4(CX)(DX*1)
+	RET
+
+// void tstart(M *newm);
+TEXT runtime·tstart(SB),7,$0
+	MOVL	newm+4(SP), CX		// m
+	MOVL	m_g0(CX), DX		// g
+
+	// Set up SEH frame
+	PUSHL	$runtime·sigtramp(SB)
+	PUSHL	0(FS)
+	MOVL	SP, 0(FS)
+
+	// Layout new m scheduler stack on os stack.
+	MOVL	SP, AX
+	MOVL	AX, g_stackbase(DX)
+	SUBL	$(64*1024), AX		// stack size
+	MOVL	AX, g_stackguard(DX)
+
+	// Set up tls.
+	LEAL	m_tls(CX), SI
+	MOVL	SI, 0x14(FS)
+	MOVL	CX, m(SI)
+	MOVL	DX, g(SI)
+
+	// Someday the convention will be D is always cleared.
+	CLD
+
+	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
+
+	CALL	runtime·mstart(SB)
+
+	// Pop SEH frame
+	MOVL	0(FS), SP
+	POPL	0(FS)
+	POPL	CX
+
+	RET
+
+// uint32 tstart_stdcall(M *newm);
+TEXT runtime·tstart_stdcall(SB),7,$0
+	MOVL	newm+4(SP), BX
+
+	PUSHL	BX
+	CALL	runtime·tstart(SB)
+	POPL	BX
+
+	// Adjust stack for stdcall to return properly.
+	MOVL	(SP), AX		// save return address
+	ADDL	$4, SP			// remove single parameter
+	MOVL	AX, (SP)		// restore return address
+
+	XORL	AX, AX			// return 0 == success
+
+	RET
+
+// setldt(int entry, int address, int limit)
+TEXT runtime·setldt(SB),7,$0
+	MOVL	address+4(FP), CX
+	MOVL	CX, 0x14(FS)
+	RET
diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s
new file mode 100644
index 0000000..76b5ee5
--- /dev/null
+++ b/src/pkg/runtime/sys_windows_amd64.s
@@ -0,0 +1,280 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "zasm_GOOS_GOARCH.h"
+
+// maxargs should be divisible by 2, as Windows stack
+// must be kept 16-byte aligned on syscall entry.
+#define maxargs 16
+
+// void runtime·asmstdcall(void *c);
+TEXT runtime·asmstdcall(SB),7,$0
+	// asmcgocall will put first argument into CX.
+	PUSHQ	CX			// save for later
+	MOVQ	wincall_fn(CX), AX
+	MOVQ	wincall_args(CX), SI
+	MOVQ	wincall_n(CX), CX
+
+	// SetLastError(0).
+	MOVQ	0x30(GS), DI
+	MOVL	$0, 0x68(DI)
+
+	SUBQ	$(maxargs*8), SP	// room for args
+
+	// Fast version, do not store args on the stack.
+	CMPL	CX, $4
+	JLE	loadregs
+
+	// Check we have enough room for args.
+	CMPL	CX, $maxargs
+	JLE	2(PC)
+	INT	$3			// not enough room -> crash
+
+	// Copy args to the stack.
+	MOVQ	SP, DI
+	CLD
+	REP; MOVSQ
+	MOVQ	SP, SI
+
+loadregs:
+	// Load first 4 args into correspondent registers.
+	MOVQ	0(SI), CX
+	MOVQ	8(SI), DX
+	MOVQ	16(SI), R8
+	MOVQ	24(SI), R9
+
+	// Call stdcall function.
+	CALL	AX
+
+	ADDQ	$(maxargs*8), SP
+
+	// Return result.
+	POPQ	CX
+	MOVQ	AX, wincall_r1(CX)
+
+	// GetLastError().
+	MOVQ	0x30(GS), DI
+	MOVL	0x68(DI), AX
+	MOVQ	AX, wincall_err(CX)
+
+	RET
+
+// faster get/set last error
+TEXT runtime·getlasterror(SB),7,$0
+	MOVQ	0x30(GS), AX
+	MOVL	0x68(AX), AX
+	RET
+
+TEXT runtime·setlasterror(SB),7,$0
+	MOVL	err+0(FP), AX
+	MOVQ	0x30(GS),	CX
+	MOVL	AX, 0x68(CX)
+	RET
+
+TEXT runtime·sigtramp(SB),7,$56
+	// CX: exception record
+	// R8: context
+
+	// unwinding?
+	TESTL	$6, 4(CX)		// exception flags
+	MOVL	$1, AX
+	JNZ	sigdone
+
+	// copy arguments for call to sighandler
+	MOVQ	CX, 0(SP)
+	MOVQ	R8, 8(SP)
+	get_tls(CX)
+	MOVQ	g(CX), CX
+	MOVQ	CX, 16(SP)
+
+	MOVQ	BX, 24(SP)
+	MOVQ	BP, 32(SP)
+	MOVQ	SI, 40(SP)
+	MOVQ	DI, 48(SP)
+
+	CALL	runtime·sighandler(SB)
+
+	MOVQ	24(SP), BX
+	MOVQ	32(SP), BP
+	MOVQ	40(SP), SI
+	MOVQ	48(SP), DI
+sigdone:
+	RET
+
+TEXT runtime·ctrlhandler(SB),7,$8
+	MOVQ	CX, 16(SP)		// spill
+	MOVQ	$runtime·ctrlhandler1(SB), CX
+	MOVQ	CX, 0(SP)
+	CALL	runtime·externalthreadhandler(SB)
+	RET
+
+TEXT runtime·profileloop(SB),7,$8
+	MOVQ	$runtime·profileloop1(SB), CX
+	MOVQ	CX, 0(SP)
+	CALL	runtime·externalthreadhandler(SB)
+	RET
+
+TEXT runtime·externalthreadhandler(SB),7,$0
+	PUSHQ	BP
+	MOVQ	SP, BP
+	PUSHQ	BX
+	PUSHQ	SI
+	PUSHQ	DI
+	PUSHQ	0x28(GS)
+	MOVQ	SP, DX
+
+	// setup dummy m, g
+	SUBQ	$m_end, SP		// space for M
+	MOVQ	SP, 0(SP)
+	MOVQ	$m_end, 8(SP)
+	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
+
+	LEAQ	m_tls(SP), CX
+	MOVQ	CX, 0x28(GS)
+	MOVQ	SP, m(CX)
+	MOVQ	SP, BX
+	SUBQ	$g_end, SP		// space for G
+	MOVQ	SP, g(CX)
+	MOVQ	SP, m_g0(BX)
+
+	MOVQ	SP, 0(SP)
+	MOVQ	$g_end, 8(SP)
+	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
+	LEAQ	-8192(SP), CX
+	MOVQ	CX, g_stackguard(SP)
+	MOVQ	DX, g_stackbase(SP)
+
+	PUSHQ	32(BP)			// arg for handler
+	CALL	16(BP)
+	POPQ	CX
+
+	get_tls(CX)
+	MOVQ	g(CX), CX
+	MOVQ	g_stackbase(CX), SP
+	POPQ	0x28(GS)
+	POPQ	DI
+	POPQ	SI
+	POPQ	BX
+	POPQ	BP
+	RET
+
+// Continuation of thunk function created for each callback by ../thread.c compilecallback,
+// runs on Windows stack (not Go stack).
+// Thunk code designed to have minimal size for it is copied many (up to thousands) times.
+//
+// thunk:
+//	MOVQ	$fn, AX
+//	PUSHQ	AX
+//	MOVQ	$argsize, AX
+//	PUSHQ	AX
+//	MOVQ	$runtime·callbackasm, AX
+//	JMP	AX
+TEXT runtime·callbackasm(SB),7,$0
+	// Construct args vector for cgocallback().
+	// By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
+	// args from the 5th on are on the stack.
+	// In any case, even if function has 0,1,2,3,4 args, there is reserved
+	// but uninitialized "shadow space" for the first 4 args.
+	// The values are in registers.
+  	MOVQ	CX, (24+0)(SP)
+  	MOVQ	DX, (24+8)(SP)
+  	MOVQ	R8, (24+16)(SP)
+  	MOVQ	R9, (24+24)(SP)
+	// 6l does not accept writing POPQs here issuing a warning "unbalanced PUSH/POP"
+  	MOVQ	0(SP), DX	// POPQ DX
+  	MOVQ	8(SP), AX	// POPQ AX
+	ADDQ	$16, SP
+
+	// preserve whatever's at the memory location that
+	// the callback will use to store the return value
+	LEAQ	8(SP), CX       // args vector, skip return address
+	PUSHQ	0(CX)(DX*1)     // store 8 bytes from just after the args array
+	ADDQ	$8, DX          // extend argsize by size of return value
+
+	// DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
+	// as required by windows callback convention.
+	// 6l does not allow writing many PUSHQs here issuing a warning "nosplit stack overflow"
+	// the warning has no sense as this code uses os thread stack
+	PUSHFQ
+	SUBQ	$64, SP
+	MOVQ	DI, 56(SP)
+	MOVQ	SI, 48(SP)
+	MOVQ	BP, 40(SP)
+	MOVQ	BX, 32(SP)
+	MOVQ	R12, 24(SP)
+	MOVQ	R13, 16(SP)
+	MOVQ	R14, 8(SP)
+	MOVQ	R15, 0(SP)
+
+	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+	PUSHQ	DX    // uintptr framesize
+	PUSHQ	CX    // void *frame
+	PUSHQ	AX    // void (*fn)(void*)
+	CLD
+	CALL  runtime·cgocallback(SB)
+	POPQ	AX
+	POPQ	CX
+	POPQ	DX
+
+	// restore registers as required for windows callback
+	// 6l does not allow writing many POPs here issuing a warning "nosplit stack overflow"
+	MOVQ	0(SP), R15
+	MOVQ	8(SP), R14
+	MOVQ	16(SP), R13
+	MOVQ	24(SP), R12
+	MOVQ	32(SP), BX
+	MOVQ	40(SP), BP
+	MOVQ	48(SP), SI
+	MOVQ	56(SP), DI
+	ADDQ	$64, SP
+	POPFQ
+
+	MOVL	-8(CX)(DX*1), AX  // return value
+	POPQ	-8(CX)(DX*1)      // restore bytes just after the args
+	RET
+
+TEXT runtime·setstacklimits(SB),7,$0
+	MOVQ	0x30(GS), CX
+	MOVQ	$0, 0x10(CX)
+	MOVQ	$0xffffffffffff, AX
+	MOVQ	AX, 0x08(CX)
+	RET
+
+// uint32 tstart_stdcall(M *newm);
+TEXT runtime·tstart_stdcall(SB),7,$0
+	// CX contains first arg newm
+	MOVQ	m_g0(CX), DX		// g
+
+	// Layout new m scheduler stack on os stack.
+	MOVQ	SP, AX
+	MOVQ	AX, g_stackbase(DX)
+	SUBQ	$(64*1024), AX		// stack size
+	MOVQ	AX, g_stackguard(DX)
+
+	// Set up tls.
+	LEAQ	m_tls(CX), SI
+	MOVQ	SI, 0x28(GS)
+	MOVQ	CX, m(SI)
+	MOVQ	DX, g(SI)
+
+	// Someday the convention will be D is always cleared.
+	CLD
+
+	CALL	runtime·setstacklimits(SB)
+	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
+	CALL	runtime·mstart(SB)
+
+	XORL	AX, AX			// return 0 == success
+	RET
+
+TEXT runtime·notok(SB),7,$0
+	MOVQ	$0xf1, BP
+	MOVQ	BP, (BP)
+	RET
+
+// set tls base to DI
+TEXT runtime·settls(SB),7,$0
+	CALL	runtime·setstacklimits(SB)
+	MOVQ	DI, 0x28(GS)
+	RET
diff --git a/src/pkg/runtime/syscall_windows.goc b/src/pkg/runtime/syscall_windows.goc
new file mode 100644
index 0000000..781ec90
--- /dev/null
+++ b/src/pkg/runtime/syscall_windows.goc
@@ -0,0 +1,145 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+#include "runtime.h"
+#include "os_GOOS.h"
+#include "cgocall.h"
+
+func loadlibrary(filename *uint16) (handle uintptr, err uintptr) {
+	WinCall c;
+
+	c.fn = runtime·LoadLibrary;
+	c.n = 1;
+	c.args = &filename;
+	runtime·cgocall(runtime·asmstdcall, &c);
+	handle = c.r1;
+	if(handle == 0)
+		err = c.err;
+	else
+		err = 0;
+}
+
+func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err uintptr) {
+	WinCall c;
+
+	USED(procname);
+	c.fn = runtime·GetProcAddress;
+	c.n = 2;
+	c.args = &handle;
+	runtime·cgocall(runtime·asmstdcall, &c);
+	proc = c.r1;
+	if(proc == 0)
+		err = c.err;
+	else
+		err = 0;
+}
+
+func NewCallback(fn Eface) (code uintptr) {
+	code = (uintptr)runtime·compilecallback(fn, true);
+}
+
+func NewCallbackCDecl(fn Eface) (code uintptr) {
+	code = (uintptr)runtime·compilecallback(fn, false);
+}
+
+func Syscall(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+	WinCall c;
+
+	USED(a2);
+	USED(a3);
+	c.fn = (void*)fn;
+	c.n = nargs;
+	c.args = &a1;
+	runtime·cgocall(runtime·asmstdcall, &c);
+	err = c.err;
+	r1 = c.r1;
+	r2 = c.r2;
+}
+
+func Syscall6(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+	WinCall c;
+
+	USED(a2);
+	USED(a3);
+	USED(a4);
+	USED(a5);
+	USED(a6);
+	c.fn = (void*)fn;
+	c.n = nargs;
+	c.args = &a1;
+	runtime·cgocall(runtime·asmstdcall, &c);
+	err = c.err;
+	r1 = c.r1;
+	r2 = c.r2;
+}
+
+func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+	WinCall c;
+
+	USED(a2);
+	USED(a3);
+	USED(a4);
+	USED(a5);
+	USED(a6);
+	USED(a7);
+	USED(a8);
+	USED(a9);
+	c.fn = (void*)fn;
+	c.n = nargs;
+	c.args = &a1;
+	runtime·cgocall(runtime·asmstdcall, &c);
+	err = c.err;
+	r1 = c.r1;
+	r2 = c.r2;
+}
+
+func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+	WinCall c;
+
+	USED(a2);
+	USED(a3);
+	USED(a4);
+	USED(a5);
+	USED(a6);
+	USED(a7);
+	USED(a8);
+	USED(a9);
+	USED(a10);
+	USED(a11);
+	USED(a12);
+	c.fn = (void*)fn;
+	c.n = nargs;
+	c.args = &a1;
+	runtime·cgocall(runtime·asmstdcall, &c);
+	err = c.err;
+	r1 = c.r1;
+	r2 = c.r2;
+}
+
+func Syscall15(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr, a13 uintptr, a14 uintptr, a15 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+	WinCall c;
+
+	USED(a2);
+	USED(a3);
+	USED(a4);
+	USED(a5);
+	USED(a6);
+	USED(a7);
+	USED(a8);
+	USED(a9);
+	USED(a10);
+	USED(a11);
+	USED(a12);
+	USED(a13);
+	USED(a14);
+	USED(a15);
+	c.fn = (void*)fn;
+	c.n = nargs;
+	c.args = &a1;
+	runtime·cgocall(runtime·asmstdcall, &c);
+	err = c.err;
+	r1 = c.r1;
+	r2 = c.r2;
+}
diff --git a/src/pkg/runtime/syscall_windows_test.go b/src/pkg/runtime/syscall_windows_test.go
index 32eb053..c8327fd 100644
--- a/src/pkg/runtime/syscall_windows_test.go
+++ b/src/pkg/runtime/syscall_windows_test.go
@@ -5,29 +5,40 @@
 package runtime_test
 
 import (
+	"runtime"
 	"syscall"
-	"unsafe"
 	"testing"
+	"unsafe"
 )
 
-func TestStdCall(t *testing.T) {
-	type Rect struct {
-		left, top, right, bottom int32
-	}
+type DLL struct {
+	*syscall.DLL
+	t *testing.T
+}
 
-	h, e := syscall.LoadLibrary("user32.dll")
-	if e != 0 {
-		t.Fatal("LoadLibrary(USER32)")
+func GetDLL(t *testing.T, name string) *DLL {
+	d, e := syscall.LoadDLL(name)
+	if e != nil {
+		t.Fatal(e)
 	}
-	p, e := syscall.GetProcAddress(h, "UnionRect")
-	if e != 0 {
-		t.Fatal("GetProcAddress(USER32.UnionRect)")
+	return &DLL{DLL: d, t: t}
+}
+
+func (d *DLL) Proc(name string) *syscall.Proc {
+	p, e := d.FindProc(name)
+	if e != nil {
+		d.t.Fatal(e)
 	}
+	return p
+}
 
+func TestStdCall(t *testing.T) {
+	type Rect struct {
+		left, top, right, bottom int32
+	}
 	res := Rect{}
 	expected := Rect{1, 1, 40, 60}
-	a, _, _ := syscall.Syscall(uintptr(p),
-		3,
+	a, _, _ := GetDLL(t, "user32.dll").Proc("UnionRect").Call(
 		uintptr(unsafe.Pointer(&res)),
 		uintptr(unsafe.Pointer(&Rect{10, 1, 14, 60})),
 		uintptr(unsafe.Pointer(&Rect{1, 2, 40, 50})))
@@ -57,7 +68,7 @@ func Test64BitReturnStdCall(t *testing.T) {
 		VER_LESS          = 4
 		VER_LESS_EQUAL    = 5
 
-		ERROR_OLD_WIN_VERSION = 1150
+		ERROR_OLD_WIN_VERSION syscall.Errno = 1150
 	)
 
 	type OSVersionInfoEx struct {
@@ -74,24 +85,14 @@ func Test64BitReturnStdCall(t *testing.T) {
 		Reserve           byte
 	}
 
-	kernel32, e := syscall.LoadLibrary("kernel32.dll")
-	if e != 0 {
-		t.Fatalf("LoadLibrary(kernel32.dll) failed: %s", syscall.Errstr(e))
-	}
-	setMask, e := syscall.GetProcAddress(kernel32, "VerSetConditionMask")
-	if e != 0 {
-		t.Fatalf("GetProcAddress(kernel32.dll, VerSetConditionMask) failed: %s", syscall.Errstr(e))
-	}
-	verifyVersion, e := syscall.GetProcAddress(kernel32, "VerifyVersionInfoW")
-	if e != 0 {
-		t.Fatalf("GetProcAddress(kernel32.dll, VerifyVersionInfoW) failed: %s", syscall.Errstr(e))
-	}
+	d := GetDLL(t, "kernel32.dll")
 
 	var m1, m2 uintptr
-	m1, m2, _ = syscall.Syscall6(setMask, 4, m1, m2, VER_MAJORVERSION, VER_GREATER_EQUAL, 0, 0)
-	m1, m2, _ = syscall.Syscall6(setMask, 4, m1, m2, VER_MINORVERSION, VER_GREATER_EQUAL, 0, 0)
-	m1, m2, _ = syscall.Syscall6(setMask, 4, m1, m2, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL, 0, 0)
-	m1, m2, _ = syscall.Syscall6(setMask, 4, m1, m2, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL, 0, 0)
+	VerSetConditionMask := d.Proc("VerSetConditionMask")
+	m1, m2, _ = VerSetConditionMask.Call(m1, m2, VER_MAJORVERSION, VER_GREATER_EQUAL)
+	m1, m2, _ = VerSetConditionMask.Call(m1, m2, VER_MINORVERSION, VER_GREATER_EQUAL)
+	m1, m2, _ = VerSetConditionMask.Call(m1, m2, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)
+	m1, m2, _ = VerSetConditionMask.Call(m1, m2, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL)
 
 	vi := OSVersionInfoEx{
 		MajorVersion:     5,
@@ -100,63 +101,42 @@ func Test64BitReturnStdCall(t *testing.T) {
 		ServicePackMinor: 0,
 	}
 	vi.OSVersionInfoSize = uint32(unsafe.Sizeof(vi))
-	r, _, e2 := syscall.Syscall6(verifyVersion,
-		4,
+	r, _, e2 := d.Proc("VerifyVersionInfoW").Call(
 		uintptr(unsafe.Pointer(&vi)),
 		VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR|VER_SERVICEPACKMINOR,
-		m1, m2, 0, 0)
+		m1, m2)
 	if r == 0 && e2 != ERROR_OLD_WIN_VERSION {
-		t.Errorf("VerifyVersionInfo failed: (%d) %s", e2, syscall.Errstr(int(e2)))
+		t.Errorf("VerifyVersionInfo failed: %s", e2)
 	}
 }
 
 func TestCDecl(t *testing.T) {
-	h, e := syscall.LoadLibrary("user32.dll")
-	if e != 0 {
-		t.Fatal("LoadLibrary(USER32)")
-	}
-	p, e := syscall.GetProcAddress(h, "wsprintfA")
-	if e != 0 {
-		t.Fatal("GetProcAddress(USER32.wsprintfA)")
-	}
-
 	var buf [50]byte
-	a, _, _ := syscall.Syscall6(uintptr(p),
-		5,
+	a, _, _ := GetDLL(t, "user32.dll").Proc("wsprintfA").Call(
 		uintptr(unsafe.Pointer(&buf[0])),
 		uintptr(unsafe.Pointer(syscall.StringBytePtr("%d %d %d"))),
-		1000, 2000, 3000, 0)
+		1000, 2000, 3000)
 	if string(buf[:a]) != "1000 2000 3000" {
 		t.Error("cdecl USER32.wsprintfA returns", a, "buf=", buf[:a])
 	}
 }
 
-func TestCallback(t *testing.T) {
-	h, e := syscall.LoadLibrary("user32.dll")
-	if e != 0 {
-		t.Fatal("LoadLibrary(USER32)")
-	}
-	pEnumWindows, e := syscall.GetProcAddress(h, "EnumWindows")
-	if e != 0 {
-		t.Fatal("GetProcAddress(USER32.EnumWindows)")
-	}
-	pIsWindow, e := syscall.GetProcAddress(h, "IsWindow")
-	if e != 0 {
-		t.Fatal("GetProcAddress(USER32.IsWindow)")
-	}
+func TestEnumWindows(t *testing.T) {
+	d := GetDLL(t, "user32.dll")
+	isWindows := d.Proc("IsWindow")
 	counter := 0
 	cb := syscall.NewCallback(func(hwnd syscall.Handle, lparam uintptr) uintptr {
 		if lparam != 888 {
 			t.Error("lparam was not passed to callback")
 		}
-		b, _, _ := syscall.Syscall(uintptr(pIsWindow), 1, uintptr(hwnd), 0, 0)
+		b, _, _ := isWindows.Call(uintptr(hwnd))
 		if b == 0 {
 			t.Error("USER32.IsWindow returns FALSE")
 		}
 		counter++
 		return 1 // continue enumeration
 	})
-	a, _, _ := syscall.Syscall(uintptr(pEnumWindows), 2, cb, 888, 0)
+	a, _, _ := d.Proc("EnumWindows").Call(cb, 888)
 	if a == 0 {
 		t.Error("USER32.EnumWindows returns FALSE")
 	}
@@ -165,6 +145,99 @@ func TestCallback(t *testing.T) {
 	}
 }
 
+func callback(hwnd syscall.Handle, lparam uintptr) uintptr {
+	(*(*func())(unsafe.Pointer(&lparam)))()
+	return 0 // stop enumeration
+}
+
+// nestedCall calls into Windows, back into Go, and finally to f.
+func nestedCall(t *testing.T, f func()) {
+	c := syscall.NewCallback(callback)
+	d := GetDLL(t, "user32.dll")
+	defer d.Release()
+	d.Proc("EnumWindows").Call(c, uintptr(*(*unsafe.Pointer)(unsafe.Pointer(&f))))
+}
+
+func TestCallback(t *testing.T) {
+	var x = false
+	nestedCall(t, func() { x = true })
+	if !x {
+		t.Fatal("nestedCall did not call func")
+	}
+}
+
+func TestCallbackGC(t *testing.T) {
+	nestedCall(t, runtime.GC)
+}
+
+func TestCallbackPanic(t *testing.T) {
+	// Make sure panic during callback unwinds properly.
+	if runtime.LockedOSThread() {
+		t.Fatal("locked OS thread on entry to TestCallbackPanic")
+	}
+	defer func() {
+		s := recover()
+		if s == nil {
+			t.Fatal("did not panic")
+		}
+		if s.(string) != "callback panic" {
+			t.Fatal("wrong panic:", s)
+		}
+		if runtime.LockedOSThread() {
+			t.Fatal("locked OS thread on exit from TestCallbackPanic")
+		}
+	}()
+	nestedCall(t, func() { panic("callback panic") })
+	panic("nestedCall returned")
+}
+
+func TestCallbackPanicLoop(t *testing.T) {
+	// Make sure we don't blow out m->g0 stack.
+	for i := 0; i < 100000; i++ {
+		TestCallbackPanic(t)
+	}
+}
+
+func TestCallbackPanicLocked(t *testing.T) {
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
+	if !runtime.LockedOSThread() {
+		t.Fatal("runtime.LockOSThread didn't")
+	}
+	defer func() {
+		s := recover()
+		if s == nil {
+			t.Fatal("did not panic")
+		}
+		if s.(string) != "callback panic" {
+			t.Fatal("wrong panic:", s)
+		}
+		if !runtime.LockedOSThread() {
+			t.Fatal("lost lock on OS thread after panic")
+		}
+	}()
+	nestedCall(t, func() { panic("callback panic") })
+	panic("nestedCall returned")
+}
+
+func TestBlockingCallback(t *testing.T) {
+	c := make(chan int)
+	go func() {
+		for i := 0; i < 10; i++ {
+			c <- <-c
+		}
+	}()
+	nestedCall(t, func() {
+		for i := 0; i < 10; i++ {
+			c <- i
+			if j := <-c; j != i {
+				t.Errorf("out of sync %d != %d", j, i)
+			}
+		}
+	})
+}
+
 func TestCallbackInAnotherThread(t *testing.T) {
 	// TODO: test a function which calls back in another thread: QueueUserAPC() or CreateThread()
 }
diff --git a/src/pkg/runtime/thread_darwin.c b/src/pkg/runtime/thread_darwin.c
new file mode 100644
index 0000000..832c74b
--- /dev/null
+++ b/src/pkg/runtime/thread_darwin.c
@@ -0,0 +1,416 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "stack.h"
+
+extern SigTab runtime·sigtab[];
+
+static void
+unimplemented(int8 *name)
+{
+	runtime·prints(name);
+	runtime·prints(" not implemented\n");
+	*(int32*)1231 = 1231;
+}
+
+int32
+runtime·semasleep(int64 ns)
+{
+	return runtime·mach_semacquire(m->waitsema, ns);
+}
+
+void
+runtime·semawakeup(M *mp)
+{
+	runtime·mach_semrelease(mp->waitsema);
+}
+
+uintptr
+runtime·semacreate(void)
+{
+	return runtime·mach_semcreate();
+}
+
+// BSD interface for threading.
+void
+runtime·osinit(void)
+{
+	// Register our thread-creation callback (see sys_darwin_{amd64,386}.s)
+	// but only if we're not using cgo.  If we are using cgo we need
+	// to let the C pthread libary install its own thread-creation callback.
+	if(!runtime·iscgo)
+		runtime·bsdthread_register();
+
+	// Use sysctl to fetch hw.ncpu.
+	uint32 mib[2];
+	uint32 out;
+	int32 ret;
+	uintptr nout;
+
+	mib[0] = 6;
+	mib[1] = 3;
+	nout = sizeof out;
+	out = 0;
+	ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
+	if(ret >= 0)
+		runtime·ncpu = out;
+}
+
+void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
+void
+runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+	int32 errno;
+
+	m->tls[0] = m->id;	// so 386 asm can find it
+	if(0){
+		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
+			stk, m, g, fn, m->id, m->tls[0], &m);
+	}
+	if((errno = runtime·bsdthread_create(stk, m, g, fn)) < 0) {
+		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -errno);
+		runtime·throw("runtime.newosproc");
+	}
+}
+
+// Called to initialize a new m (including the bootstrap m).
+void
+runtime·minit(void)
+{
+	// Initialize signal handling.
+	m->gsignal = runtime·malg(32*1024);	// OS X wants >=8K, Linux >=2K
+	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+}
+
+// Mach IPC, to get at semaphores
+// Definitions are in /usr/include/mach on a Mac.
+
+static void
+macherror(int32 r, int8 *fn)
+{
+	runtime·printf("mach error %s: %d\n", fn, r);
+	runtime·throw("mach error");
+}
+
+enum
+{
+	DebugMach = 0
+};
+
+static MachNDR zerondr;
+
+#define MACH_MSGH_BITS(a, b) ((a) | ((b)<<8))
+
+static int32
+mach_msg(MachHeader *h,
+	int32 op,
+	uint32 send_size,
+	uint32 rcv_size,
+	uint32 rcv_name,
+	uint32 timeout,
+	uint32 notify)
+{
+	// TODO: Loop on interrupt.
+	return runtime·mach_msg_trap(h, op, send_size, rcv_size, rcv_name, timeout, notify);
+}
+
+// Mach RPC (MIG)
+
+enum
+{
+	MinMachMsg = 48,
+	Reply = 100,
+};
+
+#pragma pack on
+typedef struct CodeMsg CodeMsg;
+struct CodeMsg
+{
+	MachHeader h;
+	MachNDR NDR;
+	int32 code;
+};
+#pragma pack off
+
+static int32
+machcall(MachHeader *h, int32 maxsize, int32 rxsize)
+{
+	uint32 *p;
+	int32 i, ret, id;
+	uint32 port;
+	CodeMsg *c;
+
+	if((port = m->machport) == 0){
+		port = runtime·mach_reply_port();
+		m->machport = port;
+	}
+
+	h->msgh_bits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
+	h->msgh_local_port = port;
+	h->msgh_reserved = 0;
+	id = h->msgh_id;
+
+	if(DebugMach){
+		p = (uint32*)h;
+		runtime·prints("send:\t");
+		for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
+			runtime·prints(" ");
+			runtime·printpointer((void*)p[i]);
+			if(i%8 == 7)
+				runtime·prints("\n\t");
+		}
+		if(i%8)
+			runtime·prints("\n");
+	}
+
+	ret = mach_msg(h, MACH_SEND_MSG|MACH_RCV_MSG,
+		h->msgh_size, maxsize, port, 0, 0);
+	if(ret != 0){
+		if(DebugMach){
+			runtime·prints("mach_msg error ");
+			runtime·printint(ret);
+			runtime·prints("\n");
+		}
+		return ret;
+	}
+
+	if(DebugMach){
+		p = (uint32*)h;
+		runtime·prints("recv:\t");
+		for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
+			runtime·prints(" ");
+			runtime·printpointer((void*)p[i]);
+			if(i%8 == 7)
+				runtime·prints("\n\t");
+		}
+		if(i%8)
+			runtime·prints("\n");
+	}
+
+	if(h->msgh_id != id+Reply){
+		if(DebugMach){
+			runtime·prints("mach_msg reply id mismatch ");
+			runtime·printint(h->msgh_id);
+			runtime·prints(" != ");
+			runtime·printint(id+Reply);
+			runtime·prints("\n");
+		}
+		return -303;	// MIG_REPLY_MISMATCH
+	}
+
+	// Look for a response giving the return value.
+	// Any call can send this back with an error,
+	// and some calls only have return values so they
+	// send it back on success too.  I don't quite see how
+	// you know it's one of these and not the full response
+	// format, so just look if the message is right.
+	c = (CodeMsg*)h;
+	if(h->msgh_size == sizeof(CodeMsg)
+	&& !(h->msgh_bits & MACH_MSGH_BITS_COMPLEX)){
+		if(DebugMach){
+			runtime·prints("mig result ");
+			runtime·printint(c->code);
+			runtime·prints("\n");
+		}
+		return c->code;
+	}
+
+	if(h->msgh_size != rxsize){
+		if(DebugMach){
+			runtime·prints("mach_msg reply size mismatch ");
+			runtime·printint(h->msgh_size);
+			runtime·prints(" != ");
+			runtime·printint(rxsize);
+			runtime·prints("\n");
+		}
+		return -307;	// MIG_ARRAY_TOO_LARGE
+	}
+
+	return 0;
+}
+
+
+// Semaphores!
+
+enum
+{
+	Tmach_semcreate = 3418,
+	Rmach_semcreate = Tmach_semcreate + Reply,
+
+	Tmach_semdestroy = 3419,
+	Rmach_semdestroy = Tmach_semdestroy + Reply,
+
+	// Mach calls that get interrupted by Unix signals
+	// return this error code.  We retry them.
+	KERN_ABORTED = 14,
+	KERN_OPERATION_TIMED_OUT = 49,
+};
+
+typedef struct Tmach_semcreateMsg Tmach_semcreateMsg;
+typedef struct Rmach_semcreateMsg Rmach_semcreateMsg;
+typedef struct Tmach_semdestroyMsg Tmach_semdestroyMsg;
+// Rmach_semdestroyMsg = CodeMsg
+
+#pragma pack on
+struct Tmach_semcreateMsg
+{
+	MachHeader h;
+	MachNDR ndr;
+	int32 policy;
+	int32 value;
+};
+
+struct Rmach_semcreateMsg
+{
+	MachHeader h;
+	MachBody body;
+	MachPort semaphore;
+};
+
+struct Tmach_semdestroyMsg
+{
+	MachHeader h;
+	MachBody body;
+	MachPort semaphore;
+};
+#pragma pack off
+
+uint32
+runtime·mach_semcreate(void)
+{
+	union {
+		Tmach_semcreateMsg tx;
+		Rmach_semcreateMsg rx;
+		uint8 pad[MinMachMsg];
+	} m;
+	int32 r;
+
+	m.tx.h.msgh_bits = 0;
+	m.tx.h.msgh_size = sizeof(m.tx);
+	m.tx.h.msgh_remote_port = runtime·mach_task_self();
+	m.tx.h.msgh_id = Tmach_semcreate;
+	m.tx.ndr = zerondr;
+
+	m.tx.policy = 0;	// 0 = SYNC_POLICY_FIFO
+	m.tx.value = 0;
+
+	while((r = machcall(&m.tx.h, sizeof m, sizeof(m.rx))) != 0){
+		if(r == KERN_ABORTED)	// interrupted
+			continue;
+		macherror(r, "semaphore_create");
+	}
+	if(m.rx.body.msgh_descriptor_count != 1)
+		unimplemented("mach_semcreate desc count");
+	return m.rx.semaphore.name;
+}
+
+void
+runtime·mach_semdestroy(uint32 sem)
+{
+	union {
+		Tmach_semdestroyMsg tx;
+		uint8 pad[MinMachMsg];
+	} m;
+	int32 r;
+
+	m.tx.h.msgh_bits = MACH_MSGH_BITS_COMPLEX;
+	m.tx.h.msgh_size = sizeof(m.tx);
+	m.tx.h.msgh_remote_port = runtime·mach_task_self();
+	m.tx.h.msgh_id = Tmach_semdestroy;
+	m.tx.body.msgh_descriptor_count = 1;
+	m.tx.semaphore.name = sem;
+	m.tx.semaphore.disposition = MACH_MSG_TYPE_MOVE_SEND;
+	m.tx.semaphore.type = 0;
+
+	while((r = machcall(&m.tx.h, sizeof m, 0)) != 0){
+		if(r == KERN_ABORTED)	// interrupted
+			continue;
+		macherror(r, "semaphore_destroy");
+	}
+}
+
+// The other calls have simple system call traps in sys_darwin_{amd64,386}.s
+int32 runtime·mach_semaphore_wait(uint32 sema);
+int32 runtime·mach_semaphore_timedwait(uint32 sema, uint32 sec, uint32 nsec);
+int32 runtime·mach_semaphore_signal(uint32 sema);
+int32 runtime·mach_semaphore_signal_all(uint32 sema);
+
+int32
+runtime·mach_semacquire(uint32 sem, int64 ns)
+{
+	int32 r;
+
+	if(ns >= 0) {
+		r = runtime·mach_semaphore_timedwait(sem, ns/1000000000LL, ns%1000000000LL);
+		if(r == KERN_ABORTED || r == KERN_OPERATION_TIMED_OUT)
+			return -1;
+		if(r != 0)
+			macherror(r, "semaphore_wait");
+		return 0;
+	}
+	while((r = runtime·mach_semaphore_wait(sem)) != 0) {
+		if(r == KERN_ABORTED)	// interrupted
+			continue;
+		macherror(r, "semaphore_wait");
+	}
+	return 0;
+}
+
+void
+runtime·mach_semrelease(uint32 sem)
+{
+	int32 r;
+
+	while((r = runtime·mach_semaphore_signal(sem)) != 0) {
+		if(r == KERN_ABORTED)	// interrupted
+			continue;
+		macherror(r, "semaphore_signal");
+	}
+}
+
+void
+runtime·sigpanic(void)
+{
+	switch(g->sig) {
+	case SIGBUS:
+		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGSEGV:
+		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGFPE:
+		switch(g->sigcode0) {
+		case FPE_INTDIV:
+			runtime·panicstring("integer divide by zero");
+		case FPE_INTOVF:
+			runtime·panicstring("integer overflow");
+		}
+		runtime·panicstring("floating point error");
+	}
+	runtime·panicstring(runtime·sigtab[g->sig].name);
+}
+
+// TODO(rsc): place holder to fix build.
+void
+runtime·osyield(void)
+{
+}
diff --git a/src/pkg/runtime/thread_freebsd.c b/src/pkg/runtime/thread_freebsd.c
new file mode 100644
index 0000000..1c48865
--- /dev/null
+++ b/src/pkg/runtime/thread_freebsd.c
@@ -0,0 +1,162 @@
+// Use of this source file is governed by a BSD-style
+// license that can be found in the LICENSE file.`
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "stack.h"
+
+extern SigTab runtime·sigtab[];
+extern int32 runtime·sys_umtx_op(uint32*, int32, uint32, void*, void*);
+
+// From FreeBSD's <sys/sysctl.h>
+#define	CTL_HW	6
+#define	HW_NCPU	3
+
+static int32
+getncpu(void)
+{
+	uint32 mib[2];
+	uint32 out;
+	int32 ret;
+	uintptr nout;
+
+	// Fetch hw.ncpu via sysctl.
+	mib[0] = CTL_HW;
+	mib[1] = HW_NCPU;
+	nout = sizeof out;
+	out = 0;
+	ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
+	if(ret >= 0)
+		return out;
+	else
+		return 1;
+}
+
+// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
+// thus the code is largely similar. See linux/thread.c and lock_futex.c for comments.
+
+void
+runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
+{
+	int32 ret;
+	Timespec ts, *tsp;
+
+	if(ns < 0)
+		tsp = nil;
+	else {
+		ts.tv_sec = ns / 1000000000LL;
+		ts.tv_nsec = ns % 1000000000LL;
+		tsp = &ts;
+	}
+
+	ret = runtime·sys_umtx_op(addr, UMTX_OP_WAIT, val, nil, tsp);
+	if(ret >= 0 || ret == -EINTR)
+		return;
+
+	runtime·printf("umtx_wait addr=%p val=%d ret=%d\n", addr, val, ret);
+	*(int32*)0x1005 = 0x1005;
+}
+
+void
+runtime·futexwakeup(uint32 *addr, uint32 cnt)
+{
+	int32 ret;
+
+	ret = runtime·sys_umtx_op(addr, UMTX_OP_WAKE, cnt, nil, nil);
+	if(ret >= 0)
+		return;
+
+	runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret);
+	*(int32*)0x1006 = 0x1006;
+}
+
+void runtime·thr_start(void*);
+
+void
+runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+	ThrParam param;
+
+	USED(fn);	// thr_start assumes fn == mstart
+	USED(g);	// thr_start assumes g == m->g0
+
+	if(0){
+		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
+			stk, m, g, fn, m->id, m->tls[0], &m);
+	}
+
+	runtime·memclr((byte*)&param, sizeof param);
+
+	param.start_func = runtime·thr_start;
+	param.arg = m;
+	param.stack_base = (int8*)g->stackbase;
+	param.stack_size = (byte*)stk - (byte*)g->stackbase;
+	param.child_tid = (intptr*)&m->procid;
+	param.parent_tid = nil;
+	param.tls_base = (int8*)&m->tls[0];
+	param.tls_size = sizeof m->tls;
+
+	m->tls[0] = m->id;	// so 386 asm can find it
+
+	runtime·thr_new(&param, sizeof param);
+}
+
+void
+runtime·osinit(void)
+{
+	runtime·ncpu = getncpu();
+}
+
+void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
+// Called to initialize a new m (including the bootstrap m).
+void
+runtime·minit(void)
+{
+	// Initialize signal handling
+	m->gsignal = runtime·malg(32*1024);
+	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+}
+
+void
+runtime·sigpanic(void)
+{
+	switch(g->sig) {
+	case SIGBUS:
+		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGSEGV:
+		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGFPE:
+		switch(g->sigcode0) {
+		case FPE_INTDIV:
+			runtime·panicstring("integer divide by zero");
+		case FPE_INTOVF:
+			runtime·panicstring("integer overflow");
+		}
+		runtime·panicstring("floating point error");
+	}
+	runtime·panicstring(runtime·sigtab[g->sig].name);
+}
+
+// TODO: fill this in properly.
+void
+runtime·osyield(void)
+{
+}
diff --git a/src/pkg/runtime/thread_linux.c b/src/pkg/runtime/thread_linux.c
new file mode 100644
index 0000000..d185741
--- /dev/null
+++ b/src/pkg/runtime/thread_linux.c
@@ -0,0 +1,212 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "stack.h"
+
+extern SigTab runtime·sigtab[];
+
+int32 runtime·open(uint8*, int32, int32);
+int32 runtime·close(int32);
+int32 runtime·read(int32, void*, int32);
+
+// Linux futex.
+//
+//	futexsleep(uint32 *addr, uint32 val)
+//	futexwakeup(uint32 *addr)
+//
+// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
+// Futexwakeup wakes up threads sleeping on addr.
+// Futexsleep is allowed to wake up spuriously.
+
+enum
+{
+	FUTEX_WAIT = 0,
+	FUTEX_WAKE = 1,
+
+	EINTR = 4,
+	EAGAIN = 11,
+};
+
+// Atomically,
+//	if(*addr == val) sleep
+// Might be woken up spuriously; that's allowed.
+// Don't sleep longer than ns; ns < 0 means forever.
+void
+runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
+{
+	Timespec ts, *tsp;
+
+	if(ns < 0)
+		tsp = nil;
+	else {
+		ts.tv_sec = ns/1000000000LL;
+		ts.tv_nsec = ns%1000000000LL;
+		// Avoid overflow
+		if(ts.tv_sec > 1<<30)
+			ts.tv_sec = 1<<30;
+		tsp = &ts;
+	}
+
+	// Some Linux kernels have a bug where futex of
+	// FUTEX_WAIT returns an internal error code
+	// as an errno.  Libpthread ignores the return value
+	// here, and so can we: as it says a few lines up,
+	// spurious wakeups are allowed.
+	runtime·futex(addr, FUTEX_WAIT, val, tsp, nil, 0);
+}
+
+// If any procs are sleeping on addr, wake up at most cnt.
+void
+runtime·futexwakeup(uint32 *addr, uint32 cnt)
+{
+	int64 ret;
+
+	ret = runtime·futex(addr, FUTEX_WAKE, cnt, nil, nil, 0);
+
+	if(ret >= 0)
+		return;
+
+	// I don't know that futex wakeup can return
+	// EAGAIN or EINTR, but if it does, it would be
+	// safe to loop and call futex again.
+	runtime·printf("futexwakeup addr=%p returned %D\n", addr, ret);
+	*(int32*)0x1006 = 0x1006;
+}
+
+static int32
+getproccount(void)
+{
+	int32 fd, rd, cnt, cpustrlen;
+	byte *cpustr, *pos, *bufpos;
+	byte buf[256];
+
+	fd = runtime·open((byte*)"/proc/stat", O_RDONLY|O_CLOEXEC, 0);
+	if(fd == -1)
+		return 1;
+	cnt = 0;
+	bufpos = buf;
+	cpustr = (byte*)"\ncpu";
+	cpustrlen = runtime·findnull(cpustr);
+	for(;;) {
+		rd = runtime·read(fd, bufpos, sizeof(buf)-cpustrlen);
+		if(rd == -1)
+			break;
+		bufpos[rd] = 0;
+		for(pos=buf; pos=runtime·strstr(pos, cpustr); cnt++, pos++) {
+		}
+		if(rd < cpustrlen)
+			break;
+		runtime·memmove(buf, bufpos+rd-cpustrlen+1, cpustrlen-1);
+		bufpos = buf+cpustrlen-1;
+	}
+	runtime·close(fd);
+	return cnt ? cnt : 1;
+}
+
+// Clone, the Linux rfork.
+enum
+{
+	CLONE_VM = 0x100,
+	CLONE_FS = 0x200,
+	CLONE_FILES = 0x400,
+	CLONE_SIGHAND = 0x800,
+	CLONE_PTRACE = 0x2000,
+	CLONE_VFORK = 0x4000,
+	CLONE_PARENT = 0x8000,
+	CLONE_THREAD = 0x10000,
+	CLONE_NEWNS = 0x20000,
+	CLONE_SYSVSEM = 0x40000,
+	CLONE_SETTLS = 0x80000,
+	CLONE_PARENT_SETTID = 0x100000,
+	CLONE_CHILD_CLEARTID = 0x200000,
+	CLONE_UNTRACED = 0x800000,
+	CLONE_CHILD_SETTID = 0x1000000,
+	CLONE_STOPPED = 0x2000000,
+	CLONE_NEWUTS = 0x4000000,
+	CLONE_NEWIPC = 0x8000000,
+};
+
+void
+runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+	int32 ret;
+	int32 flags;
+
+	/*
+	 * note: strace gets confused if we use CLONE_PTRACE here.
+	 */
+	flags = CLONE_VM	/* share memory */
+		| CLONE_FS	/* share cwd, etc */
+		| CLONE_FILES	/* share fd table */
+		| CLONE_SIGHAND	/* share sig handler table */
+		| CLONE_THREAD	/* revisit - okay for now */
+		;
+
+	m->tls[0] = m->id;	// so 386 asm can find it
+	if(0){
+		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p clone=%p id=%d/%d ostk=%p\n",
+			stk, m, g, fn, runtime·clone, m->id, m->tls[0], &m);
+	}
+
+	if((ret = runtime·clone(flags, stk, m, g, fn)) < 0) {
+		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -ret);
+		runtime·throw("runtime.newosproc");
+	}
+}
+
+void
+runtime·osinit(void)
+{
+	runtime·ncpu = getproccount();
+}
+
+void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
+// Called to initialize a new m (including the bootstrap m).
+void
+runtime·minit(void)
+{
+	// Initialize signal handling.
+	m->gsignal = runtime·malg(32*1024);	// OS X wants >=8K, Linux >=2K
+	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+}
+
+void
+runtime·sigpanic(void)
+{
+	switch(g->sig) {
+	case SIGBUS:
+		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			}
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGSEGV:
+		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGFPE:
+		switch(g->sigcode0) {
+		case FPE_INTDIV:
+			runtime·panicstring("integer divide by zero");
+		case FPE_INTOVF:
+			runtime·panicstring("integer overflow");
+		}
+		runtime·panicstring("floating point error");
+	}
+	runtime·panicstring(runtime·sigtab[g->sig].name);
+}
diff --git a/src/pkg/runtime/thread_netbsd.c b/src/pkg/runtime/thread_netbsd.c
new file mode 100644
index 0000000..cba7ade
--- /dev/null
+++ b/src/pkg/runtime/thread_netbsd.c
@@ -0,0 +1,203 @@
+// Use of this source file is governed by a BSD-style
+// license that can be found in the LICENSE file.`
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "stack.h"
+
+enum
+{
+	ESRCH = 3,
+	ENOTSUP = 91,
+
+	// From NetBSD's sys/time.h
+	CLOCK_REALTIME = 0,
+	CLOCK_VIRTUAL = 1,
+	CLOCK_PROF = 2,
+	CLOCK_MONOTONIC = 3
+};
+
+extern SigTab runtime·sigtab[];
+
+extern int64 runtime·rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+extern int32 runtime·thrsleep(void *ident, int32 clock_id, void *tsp, void *lock);
+extern int32 runtime·thrwakeup(void *ident, int32 n);
+
+// From NetBSD's <sys/sysctl.h>
+#define	CTL_HW	6
+#define	HW_NCPU	3
+
+static int32
+getncpu(void)
+{
+	uint32 mib[2];
+	uint32 out;
+	int32 ret;
+	uintptr nout;
+
+	// Fetch hw.ncpu via sysctl.
+	mib[0] = CTL_HW;
+	mib[1] = HW_NCPU;
+	nout = sizeof out;
+	out = 0;
+	ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
+	if(ret >= 0)
+		return out;
+	else
+		return 1;
+}
+
+uintptr
+runtime·semacreate(void)
+{
+	return 1;
+}
+
+int32
+runtime·semasleep(int64 ns)
+{
+	Timespec ts;
+
+	// spin-mutex lock
+	while(runtime·xchg(&m->waitsemalock, 1))
+		runtime·osyield();
+
+	for(;;) {
+		// lock held
+		if(m->waitsemacount == 0) {
+			// sleep until semaphore != 0 or timeout.
+			// thrsleep unlocks m->waitsemalock.
+			if(ns < 0)
+				runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock);
+			else {
+				ns += runtime·nanotime();
+				ts.tv_sec = ns/1000000000LL;
+				ts.tv_nsec = ns%1000000000LL;
+				runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock);
+			}
+			// reacquire lock
+			while(runtime·xchg(&m->waitsemalock, 1))
+				runtime·osyield();
+		}
+
+		// lock held (again)
+		if(m->waitsemacount != 0) {
+			// semaphore is available.
+			m->waitsemacount--;
+			// spin-mutex unlock
+			runtime·atomicstore(&m->waitsemalock, 0);
+			return 0;  // semaphore acquired
+		}
+
+		// semaphore not available.
+		// if there is a timeout, stop now.
+		// otherwise keep trying.
+		if(ns >= 0)
+			break;
+	}
+
+	// lock held but giving up
+	// spin-mutex unlock
+	runtime·atomicstore(&m->waitsemalock, 0);
+	return -1;
+}
+
+void
+runtime·semawakeup(M *mp)
+{
+	uint32 ret;
+
+	// spin-mutex lock
+	while(runtime·xchg(&mp->waitsemalock, 1))
+		runtime·osyield();
+	mp->waitsemacount++;
+	ret = runtime·thrwakeup(&mp->waitsemacount, 1);
+	if(ret != 0 && ret != ESRCH)
+		runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
+	// spin-mutex unlock
+	runtime·atomicstore(&mp->waitsemalock, 0);
+}
+
+// From NetBSD's sys/param.h
+#define	RFPROC		(1<<4)	/* change child (else changes curproc) */
+#define	RFMEM		(1<<5)	/* share `address space' */
+#define	RFNOWAIT	(1<<6)	/* parent need not wait() on child */
+#define	RFTHREAD	(1<<13)	/* create a thread, not a process */
+
+void
+runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+	int32 flags;
+	int32 ret;
+
+	flags = RFPROC | RFTHREAD | RFMEM | RFNOWAIT;
+
+	if (0) {
+		runtime·printf(
+			"newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
+			stk, m, g, fn, m->id, m->tls[0], &m);
+	}
+
+	m->tls[0] = m->id;	// so 386 asm can find it
+
+	if((ret = runtime·rfork_thread(flags, stk, m, g, fn)) < 0) {
+		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
+		if (ret == -ENOTSUP)
+			runtime·printf("runtime: is kern.rthreads disabled?\n");
+		runtime·throw("runtime.newosproc");
+	}
+}
+
+void
+runtime·osinit(void)
+{
+	runtime·ncpu = getncpu();
+}
+
+void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
+// Called to initialize a new m (including the bootstrap m).
+void
+runtime·minit(void)
+{
+	// Initialize signal handling
+	m->gsignal = runtime·malg(32*1024);
+	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+}
+
+void
+runtime·sigpanic(void)
+{
+	switch(g->sig) {
+	case SIGBUS:
+		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGSEGV:
+		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGFPE:
+		switch(g->sigcode0) {
+		case FPE_INTDIV:
+			runtime·panicstring("integer divide by zero");
+		case FPE_INTOVF:
+			runtime·panicstring("integer overflow");
+		}
+		runtime·panicstring("floating point error");
+	}
+	runtime·panicstring(runtime·sigtab[g->sig].name);
+}
diff --git a/src/pkg/runtime/thread_openbsd.c b/src/pkg/runtime/thread_openbsd.c
new file mode 100644
index 0000000..efe03e3
--- /dev/null
+++ b/src/pkg/runtime/thread_openbsd.c
@@ -0,0 +1,203 @@
+// Use of this source file is governed by a BSD-style
+// license that can be found in the LICENSE file.`
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "stack.h"
+
+enum
+{
+	ESRCH = 3,
+	ENOTSUP = 91,
+
+	// From OpenBSD's sys/time.h
+	CLOCK_REALTIME = 0,
+	CLOCK_VIRTUAL = 1,
+	CLOCK_PROF = 2,
+	CLOCK_MONOTONIC = 3
+};
+
+extern SigTab runtime·sigtab[];
+
+extern int64 runtime·rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
+extern int32 runtime·thrsleep(void *ident, int32 clock_id, void *tsp, void *lock);
+extern int32 runtime·thrwakeup(void *ident, int32 n);
+
+// From OpenBSD's <sys/sysctl.h>
+#define	CTL_HW	6
+#define	HW_NCPU	3
+
+static int32
+getncpu(void)
+{
+	uint32 mib[2];
+	uint32 out;
+	int32 ret;
+	uintptr nout;
+
+	// Fetch hw.ncpu via sysctl.
+	mib[0] = CTL_HW;
+	mib[1] = HW_NCPU;
+	nout = sizeof out;
+	out = 0;
+	ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
+	if(ret >= 0)
+		return out;
+	else
+		return 1;
+}
+
+uintptr
+runtime·semacreate(void)
+{
+	return 1;
+}
+
+int32
+runtime·semasleep(int64 ns)
+{
+	Timespec ts;
+
+	// spin-mutex lock
+	while(runtime·xchg(&m->waitsemalock, 1))
+		runtime·osyield();
+
+	for(;;) {
+		// lock held
+		if(m->waitsemacount == 0) {
+			// sleep until semaphore != 0 or timeout.
+			// thrsleep unlocks m->waitsemalock.
+			if(ns < 0)
+				runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock);
+			else {
+				ns += runtime·nanotime();
+				ts.tv_sec = ns/1000000000LL;
+				ts.tv_nsec = ns%1000000000LL;
+				runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock);
+			}
+			// reacquire lock
+			while(runtime·xchg(&m->waitsemalock, 1))
+				runtime·osyield();
+		}
+
+		// lock held (again)
+		if(m->waitsemacount != 0) {
+			// semaphore is available.
+			m->waitsemacount--;
+			// spin-mutex unlock
+			runtime·atomicstore(&m->waitsemalock, 0);
+			return 0;  // semaphore acquired
+		}
+
+		// semaphore not available.
+		// if there is a timeout, stop now.
+		// otherwise keep trying.
+		if(ns >= 0)
+			break;
+	}
+
+	// lock held but giving up
+	// spin-mutex unlock
+	runtime·atomicstore(&m->waitsemalock, 0);
+	return -1;
+}
+
+void
+runtime·semawakeup(M *mp)
+{
+	uint32 ret;
+
+	// spin-mutex lock
+	while(runtime·xchg(&mp->waitsemalock, 1))
+		runtime·osyield();
+	mp->waitsemacount++;
+	ret = runtime·thrwakeup(&mp->waitsemacount, 1);
+	if(ret != 0 && ret != ESRCH)
+		runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
+	// spin-mutex unlock
+	runtime·atomicstore(&mp->waitsemalock, 0);
+}
+
+// From OpenBSD's sys/param.h
+#define	RFPROC		(1<<4)	/* change child (else changes curproc) */
+#define	RFMEM		(1<<5)	/* share `address space' */
+#define	RFNOWAIT	(1<<6)	/* parent need not wait() on child */
+#define	RFTHREAD	(1<<13)	/* create a thread, not a process */
+
+void
+runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+	int32 flags;
+	int32 ret;
+
+	flags = RFPROC | RFTHREAD | RFMEM | RFNOWAIT;
+
+	if (0) {
+		runtime·printf(
+			"newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
+			stk, m, g, fn, m->id, m->tls[0], &m);
+	}
+
+	m->tls[0] = m->id;	// so 386 asm can find it
+
+	if((ret = runtime·rfork_thread(flags, stk, m, g, fn)) < 0) {
+		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
+		if (ret == -ENOTSUP)
+			runtime·printf("runtime: is kern.rthreads disabled?\n");
+		runtime·throw("runtime.newosproc");
+	}
+}
+
+void
+runtime·osinit(void)
+{
+	runtime·ncpu = getncpu();
+}
+
+void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
+// Called to initialize a new m (including the bootstrap m).
+void
+runtime·minit(void)
+{
+	// Initialize signal handling
+	m->gsignal = runtime·malg(32*1024);
+	runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
+}
+
+void
+runtime·sigpanic(void)
+{
+	switch(g->sig) {
+	case SIGBUS:
+		if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGSEGV:
+		if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case SIGFPE:
+		switch(g->sigcode0) {
+		case FPE_INTDIV:
+			runtime·panicstring("integer divide by zero");
+		case FPE_INTOVF:
+			runtime·panicstring("integer overflow");
+		}
+		runtime·panicstring("floating point error");
+	}
+	runtime·panicstring(runtime·sigtab[g->sig].name);
+}
diff --git a/src/pkg/runtime/thread_plan9.c b/src/pkg/runtime/thread_plan9.c
new file mode 100644
index 0000000..a9b156d
--- /dev/null
+++ b/src/pkg/runtime/thread_plan9.c
@@ -0,0 +1,237 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "os_GOOS.h"
+#include "arch_GOARCH.h"
+
+int8 *goos = "plan9";
+
+void
+runtime·minit(void)
+{
+}
+
+static int32
+getproccount(void)
+{
+	int32 fd, i, n, ncpu;
+	byte buf[2048];
+
+	fd = runtime·open((byte*)"/dev/sysstat", OREAD);
+	if(fd < 0)
+		return 1;
+	ncpu = 0;
+	for(;;) {
+		n = runtime·read(fd, buf, sizeof buf);
+		if(n <= 0)
+			break;
+		for(i = 0; i < n; i++) {
+			if(buf[i] == '\n')
+				ncpu++;
+		}
+	}
+	runtime·close(fd);
+	return ncpu > 0 ? ncpu : 1;
+}
+
+void
+runtime·osinit(void)
+{
+	runtime·ncpu = getproccount();
+}
+
+void
+runtime·goenvs(void)
+{
+}
+
+void
+runtime·initsig(int32)
+{
+}
+
+void
+runtime·osyield(void)
+{
+	runtime·sleep(0);
+}
+
+void
+runtime·usleep(uint32 µs)
+{
+	uint32 ms;
+
+	ms = µs/1000;
+	if(ms == 0)
+		ms = 1;
+	runtime·sleep(ms);
+}
+
+int64
+runtime·nanotime(void)
+{
+	static int32 fd = -1;
+	byte b[8];
+	uint32 hi, lo;
+
+	// As long as all goroutines share the same file
+	// descriptor table we can get away with using
+	// just a static fd.  Without a lock the file can
+	// be opened twice but that's okay.
+	//
+	// Using /dev/bintime gives us a latency on the
+	// order of ten microseconds between two calls.
+	//
+	// The naïve implementation (without the cached
+	// file descriptor) is roughly four times slower
+	// in 9vx on a 2.16 GHz Intel Core 2 Duo.
+	
+	if(fd < 0 && (fd = runtime·open((byte*)"/dev/bintime", OREAD|OCEXEC)) < 0)
+		return 0;
+	if(runtime·pread(fd, b, sizeof b, 0) != sizeof b)
+		return 0;
+	hi = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
+	lo = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
+	return (int64)hi<<32 | (int64)lo;
+}
+
+void
+time·now(int64 sec, int32 nsec)
+{
+	int64 ns;
+
+	ns = runtime·nanotime();
+	sec = ns / 1000000000LL;
+	nsec = ns - sec * 1000000000LL;
+	FLUSH(&sec);
+	FLUSH(&nsec);
+}
+
+extern Tos *_tos;
+void
+runtime·exit(int32)
+{
+	int32 fd;
+	uint8 buf[128];
+	uint8 tmp[16];
+	uint8 *p, *q;
+	int32 pid;
+
+	runtime·memclr(buf, sizeof buf);
+	runtime·memclr(tmp, sizeof tmp);
+	pid = _tos->pid;
+
+	/* build path string /proc/pid/notepg */
+	for(q=tmp; pid > 0;) {
+		*q++ = '0' + (pid%10);
+		pid = pid/10;
+	}
+	p = buf;
+	runtime·memmove((void*)p, (void*)"/proc/", 6);
+	p += 6;
+	for(q--; q >= tmp;)
+		*p++ = *q--;
+	runtime·memmove((void*)p, (void*)"/notepg", 7);
+
+	/* post interrupt note */
+	fd = runtime·open(buf, OWRITE);
+	runtime·write(fd, "interrupt", 9);
+	runtime·exits(nil);
+}
+
+void
+runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+	m->tls[0] = m->id;	// so 386 asm can find it
+	if(0){
+		runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=%p\n",
+			stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m);
+	}
+
+	if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0)
+		runtime·throw("newosproc: rfork failed");
+}
+
+uintptr
+runtime·semacreate(void)
+{
+	return 1;
+}
+
+int32
+runtime·semasleep(int64 ns)
+{
+	int32 ret;
+	int32 ms;
+
+	if(ns >= 0) {
+		// TODO: Plan 9 needs a new system call, tsemacquire.
+		// The kernel implementation is the same as semacquire
+		// except with a tsleep and check for timeout.
+		// It would be great if the implementation returned the
+		// value that was added to the semaphore, so that on
+		// timeout the return value would be 0, on success 1.
+		// Then the error string does not have to be parsed
+		// to detect timeout.
+		//
+		// If a negative time indicates no timeout, then
+		// semacquire can be implemented (in the kernel)
+		// as tsemacquire(p, v, -1).
+		runtime·throw("semasleep: timed sleep not implemented on Plan 9");
+
+		/*
+		if(ns < 0)
+			ms = -1;
+		else if(ns/1000 > 0x7fffffffll)
+			ms = 0x7fffffff;
+		else
+			ms = ns/1000;
+		ret = runtime·plan9_tsemacquire(&m->waitsemacount, 1, ms);
+		if(ret == 1)
+			return 0;  // success
+		return -1;  // timeout or interrupted
+		*/
+	}
+
+	while(runtime·plan9_semacquire(&m->waitsemacount, 1) < 0) {
+		/* interrupted; try again */
+	}
+	return 0;  // success
+}
+
+void
+runtime·semawakeup(M *mp)
+{
+	runtime·plan9_semrelease(&mp->waitsemacount, 1);
+}
+
+void
+os·sigpipe(void)
+{
+	runtime·throw("too many writes on closed pipe");
+}
+
+/*
+ * placeholder - once notes are implemented,
+ * a signal generating a panic must appear as
+ * a call to this function for correct handling by
+ * traceback.
+ */
+void
+runtime·sigpanic(void)
+{
+}
+
+int32
+runtime·read(int32 fd, void *buf, int32 nbytes)
+{
+	return runtime·pread(fd, buf, nbytes, -1LL);
+}
+
+int32
+runtime·write(int32 fd, void *buf, int32 nbytes)
+{
+	return runtime·pwrite(fd, buf, nbytes, -1LL);
+}
diff --git a/src/pkg/runtime/thread_windows.c b/src/pkg/runtime/thread_windows.c
new file mode 100644
index 0000000..516d1d0
--- /dev/null
+++ b/src/pkg/runtime/thread_windows.c
@@ -0,0 +1,416 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "type.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
+#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
+#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
+#pragma dynimport runtime·CreateWaitableTimer CreateWaitableTimerA "kernel32.dll"
+#pragma dynimport runtime·DuplicateHandle DuplicateHandle "kernel32.dll"
+#pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll"
+#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
+#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
+#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll"
+#pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll"
+#pragma dynimport runtime·GetSystemInfo GetSystemInfo "kernel32.dll"
+#pragma dynimport runtime·GetSystemTimeAsFileTime GetSystemTimeAsFileTime "kernel32.dll"
+#pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll"
+#pragma dynimport runtime·LoadLibrary LoadLibraryW "kernel32.dll"
+#pragma dynimport runtime·ResumeThread ResumeThread "kernel32.dll"
+#pragma dynimport runtime·SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll"
+#pragma dynimport runtime·SetEvent SetEvent "kernel32.dll"
+#pragma dynimport runtime·SetThreadPriority SetThreadPriority "kernel32.dll"
+#pragma dynimport runtime·SetWaitableTimer SetWaitableTimer "kernel32.dll"
+#pragma dynimport runtime·Sleep Sleep "kernel32.dll"
+#pragma dynimport runtime·SuspendThread SuspendThread "kernel32.dll"
+#pragma dynimport runtime·timeBeginPeriod timeBeginPeriod "winmm.dll"
+#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll"
+#pragma dynimport runtime·WriteFile WriteFile "kernel32.dll"
+
+extern void *runtime·CloseHandle;
+extern void *runtime·CreateEvent;
+extern void *runtime·CreateThread;
+extern void *runtime·CreateWaitableTimer;
+extern void *runtime·DuplicateHandle;
+extern void *runtime·ExitProcess;
+extern void *runtime·FreeEnvironmentStringsW;
+extern void *runtime·GetEnvironmentStringsW;
+extern void *runtime·GetProcAddress;
+extern void *runtime·GetStdHandle;
+extern void *runtime·GetSystemInfo;
+extern void *runtime·GetSystemTimeAsFileTime;
+extern void *runtime·GetThreadContext;
+extern void *runtime·LoadLibrary;
+extern void *runtime·ResumeThread;
+extern void *runtime·SetConsoleCtrlHandler;
+extern void *runtime·SetEvent;
+extern void *runtime·SetThreadPriority;
+extern void *runtime·SetWaitableTimer;
+extern void *runtime·Sleep;
+extern void *runtime·SuspendThread;
+extern void *runtime·timeBeginPeriod;
+extern void *runtime·WaitForSingleObject;
+extern void *runtime·WriteFile;
+
+static int32
+getproccount(void)
+{
+	SystemInfo info;
+
+	runtime·stdcall(runtime·GetSystemInfo, 1, &info);
+	return info.dwNumberOfProcessors;
+}
+
+void
+runtime·osinit(void)
+{
+	// -1 = current process, -2 = current thread
+	runtime·stdcall(runtime·DuplicateHandle, 7,
+		(uintptr)-1, (uintptr)-2, (uintptr)-1, &m->thread,
+		(uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS);
+	runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1);
+	runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1);
+	runtime·ncpu = getproccount();
+}
+
+void
+runtime·goenvs(void)
+{
+	extern Slice syscall·envs;
+
+	uint16 *env;
+	String *s;
+	int32 i, n;
+	uint16 *p;
+
+	env = runtime·stdcall(runtime·GetEnvironmentStringsW, 0);
+
+	n = 0;
+	for(p=env; *p; n++)
+		p += runtime·findnullw(p)+1;
+
+	s = runtime·malloc(n*sizeof s[0]);
+
+	p = env;
+	for(i=0; i<n; i++) {
+		s[i] = runtime·gostringw(p);
+		p += runtime·findnullw(p)+1;
+	}
+	syscall·envs.array = (byte*)s;
+	syscall·envs.len = n;
+	syscall·envs.cap = n;
+
+	runtime·stdcall(runtime·FreeEnvironmentStringsW, 1, env);
+}
+
+void
+runtime·exit(int32 code)
+{
+	runtime·stdcall(runtime·ExitProcess, 1, (uintptr)code);
+}
+
+int32
+runtime·write(int32 fd, void *buf, int32 n)
+{
+	void *handle;
+	uint32 written;
+
+	written = 0;
+	switch(fd) {
+	case 1:
+		handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-11);
+		break;
+	case 2:
+		handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-12);
+		break;
+	default:
+		return -1;
+	}
+	runtime·stdcall(runtime·WriteFile, 5, handle, buf, (uintptr)n, &written, (uintptr)0);
+	return written;
+}
+
+void
+runtime·osyield(void)
+{
+	runtime·stdcall(runtime·Sleep, 1, (uintptr)0);
+}
+
+void
+runtime·usleep(uint32 us)
+{
+	us /= 1000;
+	if(us == 0)
+		us = 1;
+	runtime·stdcall(runtime·Sleep, 1, (uintptr)us);
+}
+
+#define INFINITE ((uintptr)0xFFFFFFFF)
+
+int32
+runtime·semasleep(int64 ns)
+{
+	uintptr ms;
+
+	if(ns < 0)
+		ms = INFINITE;
+	else if(ns/1000000 > 0x7fffffffLL)
+		ms = 0x7fffffff;
+	else {
+		ms = ns/1000000;
+		if(ms == 0)
+			ms = 1;
+	}
+	if(runtime·stdcall(runtime·WaitForSingleObject, 2, m->waitsema, ms) != 0)
+		return -1;  // timeout
+	return 0;
+}
+
+void
+runtime·semawakeup(M *mp)
+{
+	runtime·stdcall(runtime·SetEvent, 1, mp->waitsema);
+}
+
+uintptr
+runtime·semacreate(void)
+{
+	return (uintptr)runtime·stdcall(runtime·CreateEvent, 4, (uintptr)0, (uintptr)0, (uintptr)0, (uintptr)0);
+}
+
+#define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000)
+
+void
+runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+	void *thandle;
+
+	USED(stk);
+	USED(g);	// assuming g = m->g0
+	USED(fn);	// assuming fn = mstart
+
+	thandle = runtime·stdcall(runtime·CreateThread, 6,
+		nil, (uintptr)0x20000, runtime·tstart_stdcall, m,
+		STACK_SIZE_PARAM_IS_A_RESERVATION, nil);
+	if(thandle == nil) {
+		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror());
+		runtime·throw("runtime.newosproc");
+	}
+	runtime·atomicstorep(&m->thread, thandle);
+}
+
+// Called to initialize a new m (including the bootstrap m).
+void
+runtime·minit(void)
+{
+}
+
+int64
+runtime·nanotime(void)
+{
+	int64 filetime;
+
+	runtime·stdcall(runtime·GetSystemTimeAsFileTime, 1, &filetime);
+
+	// Filetime is 100s of nanoseconds since January 1, 1601.
+	// Convert to nanoseconds since January 1, 1970.
+	return (filetime - 116444736000000000LL) * 100LL;
+}
+
+void
+time·now(int64 sec, int32 usec)
+{
+	int64 ns;
+	
+	ns = runtime·nanotime();
+	sec = ns / 1000000000LL;
+	usec = ns - sec * 1000000000LL;
+	FLUSH(&sec);
+	FLUSH(&usec);
+}
+
+// Calling stdcall on os stack.
+#pragma textflag 7
+void *
+runtime·stdcall(void *fn, int32 count, ...)
+{
+	WinCall c;
+
+	c.fn = fn;
+	c.n = count;
+	c.args = (uintptr*)&count + 1;
+	runtime·asmcgocall(runtime·asmstdcall, &c);
+	return (void*)c.r1;
+}
+
+uint32
+runtime·issigpanic(uint32 code)
+{
+	switch(code) {
+	case EXCEPTION_ACCESS_VIOLATION:
+	case EXCEPTION_INT_DIVIDE_BY_ZERO:
+	case EXCEPTION_INT_OVERFLOW:
+	case EXCEPTION_FLT_DENORMAL_OPERAND:
+	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+	case EXCEPTION_FLT_INEXACT_RESULT:
+	case EXCEPTION_FLT_OVERFLOW:
+	case EXCEPTION_FLT_UNDERFLOW:
+		return 1;
+	}
+	return 0;
+}
+
+void
+runtime·sigpanic(void)
+{
+	switch(g->sig) {
+	case EXCEPTION_ACCESS_VIOLATION:
+		if(g->sigcode1 < 0x1000) {
+			if(g->sigpc == 0)
+				runtime·panicstring("call of nil func value");
+			runtime·panicstring("invalid memory address or nil pointer dereference");
+		}
+		runtime·printf("unexpected fault address %p\n", g->sigcode1);
+		runtime·throw("fault");
+	case EXCEPTION_INT_DIVIDE_BY_ZERO:
+		runtime·panicstring("integer divide by zero");
+	case EXCEPTION_INT_OVERFLOW:
+		runtime·panicstring("integer overflow");
+	case EXCEPTION_FLT_DENORMAL_OPERAND:
+	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+	case EXCEPTION_FLT_INEXACT_RESULT:
+	case EXCEPTION_FLT_OVERFLOW:
+	case EXCEPTION_FLT_UNDERFLOW:
+		runtime·panicstring("floating point error");
+	}
+	runtime·throw("fault");
+}
+
+String
+runtime·signame(int32 sig)
+{
+	int8 *s;
+
+	switch(sig) {
+	case SIGINT:
+		s = "SIGINT: interrupt";
+		break;
+	default:
+		return runtime·emptystring;
+	}
+	return runtime·gostringnocopy((byte*)s);
+}
+
+uint32
+runtime·ctrlhandler1(uint32 type)
+{
+	int32 s;
+
+	switch(type) {
+	case CTRL_C_EVENT:
+	case CTRL_BREAK_EVENT:
+		s = SIGINT;
+		break;
+	default:
+		return 0;
+	}
+
+	if(runtime·sigsend(s))
+		return 1;
+	runtime·exit(2);	// SIGINT, SIGTERM, etc
+	return 0;
+}
+
+extern void runtime·dosigprof(Context *r, G *gp);
+extern void runtime·profileloop(void);
+static void *profiletimer;
+
+static void
+profilem(M *mp)
+{
+	extern M runtime·m0;
+	extern uint32 runtime·tls0[];
+	byte rbuf[sizeof(Context)+15];
+	Context *r;
+	void *tls;
+	G *gp;
+
+	tls = mp->tls;
+	if(mp == &runtime·m0)
+		tls = runtime·tls0;
+	gp = *(G**)tls;
+
+	if(gp != nil && gp != mp->g0 && gp->status != Gsyscall) {
+		// align Context to 16 bytes
+		r = (Context*)((uintptr)(&rbuf[15]) & ~15);
+		r->ContextFlags = CONTEXT_CONTROL;
+		runtime·stdcall(runtime·GetThreadContext, 2, mp->thread, r);
+		runtime·dosigprof(r, gp);
+	}
+}
+
+void
+runtime·profileloop1(void)
+{
+	M *mp, *allm;
+	void *thread;
+
+	runtime·stdcall(runtime·SetThreadPriority, 2,
+		(uintptr)-2, (uintptr)THREAD_PRIORITY_HIGHEST);
+
+	for(;;) {
+		runtime·stdcall(runtime·WaitForSingleObject, 2, profiletimer, (uintptr)-1);
+		allm = runtime·atomicloadp(&runtime·allm);
+		for(mp = allm; mp != nil; mp = mp->alllink) {
+			thread = runtime·atomicloadp(&mp->thread);
+			if(thread == nil)
+				continue;
+			runtime·stdcall(runtime·SuspendThread, 1, thread);
+			if(mp->profilehz != 0)
+				profilem(mp);
+			runtime·stdcall(runtime·ResumeThread, 1, thread);
+		}
+	}
+}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+	static Lock lock;
+	void *timer, *thread;
+	int32 ms;
+	int64 due;
+
+	runtime·lock(&lock);
+	if(profiletimer == nil) {
+		timer = runtime·stdcall(runtime·CreateWaitableTimer, 3, nil, nil, nil);
+		runtime·atomicstorep(&profiletimer, timer);
+		thread = runtime·stdcall(runtime·CreateThread, 6,
+			nil, nil, runtime·profileloop, nil, nil, nil);
+		runtime·stdcall(runtime·CloseHandle, 1, thread);
+	}
+	runtime·unlock(&lock);
+
+	ms = 0;
+	due = 1LL<<63;
+	if(hz > 0) {
+		ms = 1000 / hz;
+		if(ms == 0)
+			ms = 1;
+		due = ms * -10000;
+	}
+	runtime·stdcall(runtime·SetWaitableTimer, 6,
+		profiletimer, &due, (uintptr)ms, nil, nil, nil);
+	runtime·atomicstore((uint32*)&m->profilehz, hz);
+}
+
+void
+os·sigpipe(void)
+{
+	runtime·throw("too many writes on closed pipe");
+}
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc
new file mode 100644
index 0000000..a6b8352
--- /dev/null
+++ b/src/pkg/runtime/time.goc
@@ -0,0 +1,253 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Time-related runtime and pieces of package time.
+
+package time
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+
+static Timers timers;
+static void addtimer(Timer*);
+static bool deltimer(Timer*);
+
+// Package time APIs.
+// Godoc uses the comments in package time, not these.
+
+// time.now is implemented in assembly.
+
+// Sleep puts the current goroutine to sleep for at least ns nanoseconds.
+func Sleep(ns int64) {
+	g->status = Gwaiting;
+	g->waitreason = "sleep";
+	runtime·tsleep(ns);
+}
+
+// startTimer adds t to the timer heap.
+func startTimer(t *Timer) {
+	addtimer(t);
+}
+
+// stopTimer removes t from the timer heap if it is there.
+// It returns true if t was removed, false if t wasn't even there.
+func stopTimer(t *Timer) (stopped bool) {
+	stopped = deltimer(t);
+}
+
+// C runtime.
+
+static void timerproc(void);
+static void siftup(int32);
+static void siftdown(int32);
+
+// Ready the goroutine e.data.
+static void
+ready(int64 now, Eface e)
+{
+	USED(now);
+
+	runtime·ready(e.data);
+}
+
+// Put the current goroutine to sleep for ns nanoseconds.
+// The caller must have set g->status and g->waitreason.
+void
+runtime·tsleep(int64 ns)
+{
+	Timer t;
+
+	if(ns <= 0)
+		return;
+
+	t.when = runtime·nanotime() + ns;
+	t.period = 0;
+	t.f = ready;
+	t.arg.data = g;
+	addtimer(&t);
+	runtime·gosched();
+}
+
+// Add a timer to the heap and start or kick the timer proc
+// if the new timer is earlier than any of the others.
+static void
+addtimer(Timer *t)
+{
+	int32 n;
+	Timer **nt;
+
+	runtime·lock(&timers);
+	if(timers.len >= timers.cap) {
+		// Grow slice.
+		n = 16;
+		if(n <= timers.cap)
+			n = timers.cap*3 / 2;
+		nt = runtime·malloc(n*sizeof nt[0]);
+		runtime·memmove(nt, timers.t, timers.len*sizeof nt[0]);
+		runtime·free(timers.t);
+		timers.t = nt;
+		timers.cap = n;
+	}
+	t->i = timers.len++;
+	timers.t[t->i] = t;
+	siftup(t->i);
+	if(t->i == 0) {
+		// siftup moved to top: new earliest deadline.
+		if(timers.sleeping) {
+			timers.sleeping = false;
+			runtime·notewakeup(&timers.waitnote);
+		}
+		if(timers.rescheduling) {
+			timers.rescheduling = false;
+			runtime·ready(timers.timerproc);
+		}
+	}
+	if(timers.timerproc == nil)
+		timers.timerproc = runtime·newproc1((byte*)timerproc, nil, 0, 0, addtimer);
+	runtime·unlock(&timers);
+}
+
+// Delete timer t from the heap.
+// Do not need to update the timerproc:
+// if it wakes up early, no big deal.
+static bool
+deltimer(Timer *t)
+{
+	int32 i;
+
+	runtime·lock(&timers);
+
+	// t may not be registered anymore and may have
+	// a bogus i (typically 0, if generated by Go).
+	// Verify it before proceeding.
+	i = t->i;
+	if(i < 0 || i >= timers.len || timers.t[i] != t) {
+		runtime·unlock(&timers);
+		return false;
+	}
+
+	timers.len--;
+	if(i == timers.len) {
+		timers.t[i] = nil;
+	} else {
+		timers.t[i] = timers.t[timers.len];
+		timers.t[timers.len] = nil;
+		timers.t[i]->i = i;
+		siftup(i);
+		siftdown(i);
+	}
+	runtime·unlock(&timers);
+	return true;
+}
+
+// Timerproc runs the time-driven events.
+// It sleeps until the next event in the timers heap.
+// If addtimer inserts a new earlier event, addtimer
+// wakes timerproc early.
+static void
+timerproc(void)
+{
+	int64 delta, now;
+	Timer *t;
+	void (*f)(int64, Eface);
+	Eface arg;
+
+	for(;;) {
+		runtime·lock(&timers);
+		now = runtime·nanotime();
+		for(;;) {
+			if(timers.len == 0) {
+				delta = -1;
+				break;
+			}
+			t = timers.t[0];
+			delta = t->when - now;
+			if(delta > 0)
+				break;
+			if(t->period > 0) {
+				// leave in heap but adjust next time to fire
+				t->when += t->period * (1 + -delta/t->period);
+				siftdown(0);
+			} else {
+				// remove from heap
+				timers.t[0] = timers.t[--timers.len];
+				timers.t[0]->i = 0;
+				siftdown(0);
+				t->i = -1;  // mark as removed
+			}
+			f = t->f;
+			arg = t->arg;
+			runtime·unlock(&timers);
+			f(now, arg);
+			runtime·lock(&timers);
+		}
+		if(delta < 0) {
+			// No timers left - put goroutine to sleep.
+			timers.rescheduling = true;
+			g->status = Gwaiting;
+			g->waitreason = "timer goroutine (idle)";
+			runtime·unlock(&timers);
+			runtime·gosched();
+			continue;
+		}
+		// At least one timer pending.  Sleep until then.
+		timers.sleeping = true;
+		runtime·noteclear(&timers.waitnote);
+		runtime·unlock(&timers);
+		runtime·entersyscall();
+		runtime·notetsleep(&timers.waitnote, delta);
+		runtime·exitsyscall();
+	}
+}
+
+// heap maintenance algorithms.
+
+static void
+siftup(int32 i)
+{
+	int32 p;
+	Timer **t, *tmp;
+
+	t = timers.t;
+	while(i > 0) {
+		p = (i-1)/2;  // parent
+		if(t[i]->when >= t[p]->when)
+			break;
+		tmp = t[i];
+		t[i] = t[p];
+		t[p] = tmp;
+		t[i]->i = i;
+		t[p]->i = p;
+		i = p;
+	}
+}
+
+static void
+siftdown(int32 i)
+{
+	int32 c, len;
+	Timer **t, *tmp;
+
+	t = timers.t;
+	len = timers.len;
+	for(;;) {
+		c = i*2 + 1;  // left child
+		if(c >= len) {
+			break;
+		}
+		if(c+1 < len && t[c+1]->when < t[c]->when)
+			c++;
+		if(t[c]->when >= t[i]->when)
+			break;
+		tmp = t[i];
+		t[i] = t[c];
+		t[c] = tmp;
+		t[i]->i = i;
+		t[c]->i = c;
+		i = c;
+	}
+}
diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c
new file mode 100644
index 0000000..22e0bc3
--- /dev/null
+++ b/src/pkg/runtime/traceback_arm.c
@@ -0,0 +1,217 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+
+void runtime·deferproc(void);
+void runtime·newproc(void);
+void runtime·newstack(void);
+void runtime·morestack(void);
+void runtime·sigpanic(void);
+void _div(void);
+void _mod(void);
+void _divu(void);
+void _modu(void);
+
+int32
+runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 max)
+{
+	int32 i, n, iter;
+	uintptr pc, lr, tracepc, x;
+	byte *fp, *p;
+	bool waspanic;
+	Stktop *stk;
+	Func *f;
+	
+	pc = (uintptr)pc0;
+	lr = (uintptr)lr0;
+	fp = nil;
+	waspanic = false;
+
+	// If the PC is goexit, the goroutine hasn't started yet.
+	if(pc == (uintptr)runtime·goexit) {
+		pc = (uintptr)g->entry;
+		lr = (uintptr)runtime·goexit;
+	}
+
+	// If the PC is zero, it's likely a nil function call.
+	// Start in the caller's frame.
+	if(pc == 0) {
+		pc = lr;
+		lr = 0;
+	}
+
+	n = 0;
+	stk = (Stktop*)g->stackbase;
+	for(iter = 0; iter < 100 && n < max; iter++) {	// iter avoids looping forever
+		// Typically:
+		//	pc is the PC of the running function.
+		//	sp is the stack pointer at that program counter.
+		//	fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown.
+		//	stk is the stack containing sp.
+		//	The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp.
+		
+		if(pc == (uintptr)runtime·lessstack) {
+			// Hit top of stack segment.  Unwind to next segment.
+			pc = (uintptr)stk->gobuf.pc;
+			sp = stk->gobuf.sp;
+			lr = 0;
+			fp = nil;
+			if(pcbuf == nil)
+				runtime·printf("----- stack segment boundary -----\n");
+			stk = (Stktop*)stk->stackbase;
+			continue;
+		}
+		
+		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
+			// Dangerous, but worthwhile: see if this is a closure by
+			// decoding the instruction stream.
+			//
+			// We check p < p+4 to avoid wrapping and faulting if
+			// we have lost track of where we are.
+			p = (byte*)pc;
+			if((pc&3) == 0 && p < p+4 &&
+			   runtime·mheap.arena_start < p &&
+			   p+4 < runtime·mheap.arena_used) {
+			   	x = *(uintptr*)p;
+				if((x&0xfffff000) == 0xe49df000) {
+					// End of closure:
+					// MOVW.P frame(R13), R15
+					pc = *(uintptr*)sp;
+					lr = 0;
+					sp += x & 0xfff;
+					fp = nil;
+					continue;
+				}
+				if((x&0xfffff000) == 0xe52de000 && lr == (uintptr)runtime·goexit) {
+					// Beginning of closure.
+					// Closure at top of stack, not yet started.
+					p += 5*4;
+					if((x&0xfff) != 4) {
+						// argument copying
+						p += 7*4;
+					}
+					if((byte*)pc < p && p < p+4 && p+4 < runtime·mheap.arena_used) {
+						pc = *(uintptr*)p;
+						fp = nil;
+						continue;
+					}
+				}
+			}
+			break;
+		}
+		
+		// Found an actual function.
+		if(lr == 0)
+			lr = *(uintptr*)sp;
+		if(fp == nil) {
+			fp = sp;
+			if(pc > f->entry && f->frame >= 0)
+				fp += f->frame;
+		}
+
+		if(skip > 0)
+			skip--;
+		else if(pcbuf != nil)
+			pcbuf[n++] = pc;
+		else {
+			if(runtime·showframe(f)) {
+				// Print during crash.
+				//	main(0x1, 0x2, 0x3)
+				//		/home/rsc/go/src/runtime/x.go:23 +0xf
+				tracepc = pc;	// back up to CALL instruction for funcline.
+				if(n > 0 && pc > f->entry && !waspanic)
+					tracepc -= sizeof(uintptr);
+				runtime·printf("%S(", f->name);
+				for(i = 0; i < f->args; i++) {
+					if(i != 0)
+						runtime·prints(", ");
+					runtime·printhex(((uintptr*)fp)[1+i]);
+					if(i >= 4) {
+						runtime·prints(", ...");
+						break;
+					}
+				}
+				runtime·prints(")\n");
+				runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc));
+				if(pc > f->entry)
+					runtime·printf(" +%p", (uintptr)(pc - f->entry));
+				runtime·printf("\n");
+			}
+			n++;
+		}
+		
+		waspanic = f->entry == (uintptr)runtime·sigpanic;
+
+		if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && g == m->g0) {
+			runtime·printf("----- newstack called from goroutine %d -----\n", m->curg->goid);
+			pc = (uintptr)m->morepc;
+			sp = (byte*)m->moreargp - sizeof(void*);
+			lr = (uintptr)m->morebuf.pc;
+			fp = m->morebuf.sp;
+			g = m->curg;
+			stk = (Stktop*)g->stackbase;
+			continue;
+		}
+		
+		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && g == m->g0) {
+			runtime·printf("----- lessstack called from goroutine %d -----\n", m->curg->goid);
+			g = m->curg;
+			stk = (Stktop*)g->stackbase;
+			sp = stk->gobuf.sp;
+			pc = (uintptr)stk->gobuf.pc;
+			fp = nil;
+			lr = 0;
+			continue;
+		}	
+		
+		// Unwind to next frame.
+		pc = lr;
+		lr = 0;
+		sp = fp;
+		fp = nil;
+		
+		// If this was div or divu or mod or modu, the caller had
+		// an extra 8 bytes on its stack.  Adjust sp.
+		if(f->entry == (uintptr)_div || f->entry == (uintptr)_divu || f->entry == (uintptr)_mod || f->entry == (uintptr)_modu)
+			sp += 8;
+		
+		// If this was deferproc or newproc, the caller had an extra 12.
+		if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
+			sp += 12;
+	}
+	
+	if(pcbuf == nil && (pc = g->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && g->goid != 1) {
+		runtime·printf("created by %S\n", f->name);
+		tracepc = pc;	// back up to CALL instruction for funcline.
+		if(n > 0 && pc > f->entry)
+			tracepc -= sizeof(uintptr);
+		runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc));
+		if(pc > f->entry)
+			runtime·printf(" +%p", (uintptr)(pc - f->entry));
+		runtime·printf("\n");
+	}
+
+	return n;		
+}
+
+void
+runtime·traceback(byte *pc0, byte *sp, byte *lr, G *g)
+{
+	runtime·gentraceback(pc0, sp, lr, g, 0, nil, 100);
+}
+
+// func caller(n int) (pc uintptr, file string, line int, ok bool)
+int32
+runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
+{
+	byte *pc, *sp;
+	
+	sp = runtime·getcallersp(&skip);
+	pc = runtime·getcallerpc(&skip);
+
+	return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m);
+}
diff --git a/src/pkg/runtime/traceback_x86.c b/src/pkg/runtime/traceback_x86.c
new file mode 100644
index 0000000..be35bab
--- /dev/null
+++ b/src/pkg/runtime/traceback_x86.c
@@ -0,0 +1,303 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64 386
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+
+static uintptr isclosureentry(uintptr);
+void runtime·deferproc(void);
+void runtime·newproc(void);
+void runtime·newstack(void);
+void runtime·morestack(void);
+void runtime·sigpanic(void);
+
+// This code is also used for the 386 tracebacks.
+// Use uintptr for an appropriate word-sized integer.
+
+// Generic traceback.  Handles runtime stack prints (pcbuf == nil)
+// as well as the runtime.Callers function (pcbuf != nil).
+// A little clunky to merge the two but avoids duplicating
+// the code and all its subtlety.
+int32
+runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 max)
+{
+	byte *p;
+	int32 i, n, iter, sawnewstack;
+	uintptr pc, lr, tracepc;
+	byte *fp;
+	Stktop *stk;
+	Func *f;
+	bool waspanic;
+
+	USED(lr0);
+	pc = (uintptr)pc0;
+	lr = 0;
+	fp = nil;
+	waspanic = false;
+	
+	// If the PC is goexit, the goroutine hasn't started yet.
+	if(pc0 == g->sched.pc && sp == g->sched.sp && pc0 == (byte*)runtime·goexit) {
+		fp = sp;
+		lr = pc;
+		pc = (uintptr)g->entry;
+	}
+	
+	// If the PC is zero, it's likely a nil function call.
+	// Start in the caller's frame.
+	if(pc == 0) {
+		pc = lr;
+		lr = 0;
+	}
+
+	// If the PC is zero, it's likely a nil function call.
+	// Start in the caller's frame.
+	if(pc == 0) {
+		pc = *(uintptr*)sp;
+		sp += sizeof(uintptr);
+	}
+
+	n = 0;
+	sawnewstack = 0;
+	stk = (Stktop*)g->stackbase;
+	for(iter = 0; iter < 100 && n < max; iter++) {	// iter avoids looping forever
+		// Typically:
+		//	pc is the PC of the running function.
+		//	sp is the stack pointer at that program counter.
+		//	fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown.
+		//	stk is the stack containing sp.
+		//	The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp.
+	
+		if(pc == (uintptr)runtime·lessstack) {
+			// Hit top of stack segment.  Unwind to next segment.
+			pc = (uintptr)stk->gobuf.pc;
+			sp = stk->gobuf.sp;
+			lr = 0;
+			fp = nil;
+			if(pcbuf == nil)
+				runtime·printf("----- stack segment boundary -----\n");
+			stk = (Stktop*)stk->stackbase;
+			continue;
+		}
+		if(pc <= 0x1000 || (f = runtime·findfunc(pc)) == nil) {
+			// Dangerous, but worthwhile: see if this is a closure:
+			//	ADDQ $wwxxyyzz, SP; RET
+			//	[48] 81 c4 zz yy xx ww c3
+			// The 0x48 byte is only on amd64.
+			p = (byte*)pc;
+			// We check p < p+8 to avoid wrapping and faulting if we lose track.
+			if(runtime·mheap.arena_start < p && p < p+8 && p+8 < runtime·mheap.arena_used &&  // pointer in allocated memory
+			   (sizeof(uintptr) != 8 || *p++ == 0x48) &&  // skip 0x48 byte on amd64
+			   p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
+				sp += *(uint32*)(p+2);
+				pc = *(uintptr*)sp;
+				sp += sizeof(uintptr);
+				lr = 0;
+				fp = nil;
+				continue;
+			}
+			
+			// Closure at top of stack, not yet started.
+			if(lr == (uintptr)runtime·goexit && (pc = isclosureentry(pc)) != 0) {
+				fp = sp;
+				continue;
+			}
+
+			// Unknown pc: stop.
+			break;
+		}
+
+		// Found an actual function.
+		if(fp == nil) {
+			fp = sp;
+			if(pc > f->entry && f->frame >= sizeof(uintptr))
+				fp += f->frame - sizeof(uintptr);
+			if(lr == 0)
+				lr = *(uintptr*)fp;
+			fp += sizeof(uintptr);
+		} else if(lr == 0)
+			lr = *(uintptr*)fp;
+
+		if(skip > 0)
+			skip--;
+		else if(pcbuf != nil)
+			pcbuf[n++] = pc;
+		else {
+			if(runtime·showframe(f)) {
+				// Print during crash.
+				//	main(0x1, 0x2, 0x3)
+				//		/home/rsc/go/src/runtime/x.go:23 +0xf
+				//		
+				tracepc = pc;	// back up to CALL instruction for funcline.
+				if(n > 0 && pc > f->entry && !waspanic)
+					tracepc--;
+				runtime·printf("%S(", f->name);
+				for(i = 0; i < f->args; i++) {
+					if(i != 0)
+						runtime·prints(", ");
+					runtime·printhex(((uintptr*)fp)[i]);
+					if(i >= 4) {
+						runtime·prints(", ...");
+						break;
+					}
+				}
+				runtime·prints(")\n");
+				runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc));
+				if(pc > f->entry)
+					runtime·printf(" +%p", (uintptr)(pc - f->entry));
+				runtime·printf("\n");
+			}
+			n++;
+		}
+		
+		waspanic = f->entry == (uintptr)runtime·sigpanic;
+
+		if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
+			fp += 2*sizeof(uintptr);
+
+		if(f->entry == (uintptr)runtime·newstack)
+			sawnewstack = 1;
+
+		if(pcbuf == nil && f->entry == (uintptr)runtime·morestack && g == m->g0 && sawnewstack) {
+			// The fact that we saw newstack means that morestack
+			// has managed to record its information in m, so we can
+			// use it to keep unwinding the stack.
+			runtime·printf("----- morestack called from goroutine %d -----\n", m->curg->goid);
+			pc = (uintptr)m->morepc;
+			sp = m->morebuf.sp - sizeof(void*);
+			lr = (uintptr)m->morebuf.pc;
+			fp = m->morebuf.sp;
+			sawnewstack = 0;
+			g = m->curg;
+			stk = (Stktop*)g->stackbase;
+			continue;
+		}
+
+		if(pcbuf == nil && f->entry == (uintptr)runtime·lessstack && g == m->g0) {
+			// Lessstack is running on scheduler stack.  Switch to original goroutine.
+			runtime·printf("----- lessstack called from goroutine %d -----\n", m->curg->goid);
+			g = m->curg;
+			stk = (Stktop*)g->stackbase;
+			sp = stk->gobuf.sp;
+			pc = (uintptr)stk->gobuf.pc;
+			fp = nil;
+			lr = 0;
+			continue;
+		}
+
+		// Unwind to next frame.
+		pc = lr;
+		lr = 0;
+		sp = fp;
+		fp = nil;
+	}
+	
+	// Show what created goroutine, except main goroutine (goid 1).
+	if(pcbuf == nil && (pc = g->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && g->goid != 1) {
+		runtime·printf("created by %S\n", f->name);
+		tracepc = pc;	// back up to CALL instruction for funcline.
+		if(n > 0 && pc > f->entry)
+			tracepc--;
+		runtime·printf("\t%S:%d", f->src, runtime·funcline(f, tracepc));
+		if(pc > f->entry)
+			runtime·printf(" +%p", (uintptr)(pc - f->entry));
+		runtime·printf("\n");
+	}
+		
+	return n;
+}
+
+void
+runtime·traceback(byte *pc0, byte *sp, byte*, G *g)
+{
+	runtime·gentraceback(pc0, sp, nil, g, 0, nil, 100);
+}
+
+int32
+runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
+{
+	byte *pc, *sp;
+
+	// our caller's pc, sp.
+	sp = (byte*)&skip;
+	pc = runtime·getcallerpc(&skip);
+
+	return runtime·gentraceback(pc, sp, nil, g, skip, pcbuf, m);
+}
+
+static uintptr
+isclosureentry(uintptr pc)
+{
+	byte *p;
+	int32 i, siz;
+	
+	p = (byte*)pc;
+	if(p < runtime·mheap.arena_start || p+32 > runtime·mheap.arena_used)
+		return 0;
+
+	if(*p == 0xe8) {
+		// CALL fn
+		return pc+5+*(int32*)(p+1);
+	}
+	
+	if(sizeof(uintptr) == 8 && p[0] == 0x48 && p[1] == 0xb9 && p[10] == 0xff && p[11] == 0xd1) {
+		// MOVQ $fn, CX; CALL *CX
+		return *(uintptr*)(p+2);
+	}
+
+	// SUBQ $siz, SP
+	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0x81 || *p++ != 0xec)
+		return 0;
+	siz = *(uint32*)p;
+	p += 4;
+	
+	// MOVQ $q, SI
+	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xbe)
+		return 0;
+	p += sizeof(uintptr);
+
+	// MOVQ SP, DI
+	if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0x89 || *p++ != 0xe7)
+		return 0;
+
+	// CLD on 32-bit
+	if(sizeof(uintptr) == 4 && *p++ != 0xfc)
+		return 0;
+
+	if(siz <= 4*sizeof(uintptr)) {
+		// MOVSQ...
+		for(i=0; i<siz; i+=sizeof(uintptr))
+			if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xa5)
+				return 0;
+	} else {
+		// MOVQ $(siz/8), CX  [32-bit immediate siz/8]
+		if((sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xc7 || *p++ != 0xc1)
+			return 0;
+		p += 4;
+		
+		// REP MOVSQ
+		if(*p++ != 0xf3 || (sizeof(uintptr) == 8 && *p++ != 0x48) || *p++ != 0xa5)
+			return 0;
+	}
+	
+	// CALL fn
+	if(*p == 0xe8) {
+		p++;
+		return (uintptr)p+4 + *(int32*)p;
+	}
+	
+	// MOVQ $fn, CX; CALL *CX
+	if(sizeof(uintptr) != 8 || *p++ != 0x48 || *p++ != 0xb9)
+		return 0;
+
+	pc = *(uintptr*)p;
+	p += 8;
+	
+	if(*p++ != 0xff || *p != 0xd1)
+		return 0;
+
+	return pc;
+}
diff --git a/src/pkg/runtime/type.go b/src/pkg/runtime/type.go
index 30f3ec6..1e0d723 100644
--- a/src/pkg/runtime/type.go
+++ b/src/pkg/runtime/type.go
@@ -27,15 +27,16 @@ type Type interface{}
 // All types begin with a few common fields needed for
 // the interface runtime.
 type commonType struct {
-	size          uintptr // size in bytes
-	hash          uint32  // hash of type; avoids computation in hash tables
-	alg           uint8   // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM)
-	align         uint8   // alignment of variable with this type
-	fieldAlign    uint8   // alignment of struct field with this type
-	kind          uint8   // enumeration for C
-	string        *string // string form; unnecessary  but undeniably useful
-	*uncommonType         // (relatively) uncommon fields
-	ptrToThis     *Type   // pointer to this type, if used in binary or has methods
+	size          uintptr  // size in bytes
+	hash          uint32   // hash of type; avoids computation in hash tables
+	_             uint8    // unused
+	align         uint8    // alignment of variable with this type
+	fieldAlign    uint8    // alignment of struct field with this type
+	kind          uint8    // enumeration for C
+	alg           *uintptr // algorithm table (../runtime/runtime.h:/Alg)
+	string        *string  // string form; unnecessary  but undeniably useful
+	*uncommonType          // (relatively) uncommon fields
+	ptrToThis     *Type    // pointer to this type, if used in binary or has methods
 }
 
 // Values for commonType.kind.
diff --git a/src/pkg/runtime/type.h b/src/pkg/runtime/type.h
index 8c80c62..c1d9fac 100644
--- a/src/pkg/runtime/type.h
+++ b/src/pkg/runtime/type.h
@@ -23,10 +23,11 @@ struct CommonType
 {
 	uintptr size;
 	uint32 hash;
-	uint8 alg;
+	uint8 _unused;
 	uint8 align;
 	uint8 fieldAlign;
 	uint8 kind;
+	Alg *alg;
 	String *string;
 	UncommonType *x;
 	Type *ptrto;
diff --git a/src/pkg/runtime/386/vlop.s b/src/pkg/runtime/vlop_386.s
similarity index 100%
rename from src/pkg/runtime/386/vlop.s
rename to src/pkg/runtime/vlop_386.s
diff --git a/src/pkg/runtime/arm/vlop.s b/src/pkg/runtime/vlop_arm.s
similarity index 100%
rename from src/pkg/runtime/arm/vlop.s
rename to src/pkg/runtime/vlop_arm.s
diff --git a/src/pkg/runtime/386/vlrt.c b/src/pkg/runtime/vlrt_386.c
similarity index 100%
rename from src/pkg/runtime/386/vlrt.c
rename to src/pkg/runtime/vlrt_386.c
diff --git a/src/pkg/runtime/arm/vlrt.c b/src/pkg/runtime/vlrt_arm.c
similarity index 100%
rename from src/pkg/runtime/arm/vlrt.c
rename to src/pkg/runtime/vlrt_arm.c
diff --git a/src/pkg/runtime/windows/386/callback.c b/src/pkg/runtime/windows/386/callback.c
deleted file mode 100644
index 11b3d29..0000000
--- a/src/pkg/runtime/windows/386/callback.c
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "type.h"
-#include "defs.h"
-#include "os.h"
-
-// Will keep all callbacks in a linked list, so they don't get garbage collected.
-typedef	struct	Callback	Callback;
-struct	Callback {
-	Callback*	link;
-	void*		gobody;
-	byte		asmbody;
-};
-
-typedef	struct	Callbacks	Callbacks;
-struct	Callbacks {
-	Lock;
-	Callback*	link;
-	int32		n;
-};
-
-static	Callbacks	cbs;
-
-// Call back from windows dll into go.
-byte *
-runtime·compilecallback(Eface fn, bool cleanstack)
-{
-	FuncType *ft;
-	Type *t;
-	int32 argsize, i, n;
-	byte *p;
-	Callback *c;
-
-	if(fn.type == nil || fn.type->kind != KindFunc)
-		runtime·panicstring("compilecallback: not a function");
-	ft = (FuncType*)fn.type;
-	if(ft->out.len != 1)
-		runtime·panicstring("compilecallback: function must have one output parameter");
-	if(((Type**)ft->out.array)[0]->size != sizeof(uintptr))
-		runtime·panicstring("compilecallback: output parameter size is wrong");
-	argsize = 0;
-	for(i=0; i<ft->in.len; i++) {
-		t = ((Type**)ft->in.array)[i];
-		if(t->size > sizeof(uintptr))
-			runtime·panicstring("compilecallback: input parameter size is wrong");
-		argsize += sizeof(uintptr);
-	}
-
-	// compute size of new fn.
-	// must match code laid out below.
-	n = 1+4;		// MOVL fn, AX
-	n += 1+4;		// MOVL argsize, DX
-	n += 1+4;		// MOVL callbackasm, CX
-	n += 2;			// CALL CX
-	n += 1;			// RET
-	if(cleanstack && argsize!=0)
-		n += 2;		// ... argsize
-
-	runtime·lock(&cbs);
-	for(c = cbs.link; c != nil; c = c->link) {
-		if(c->gobody == fn.data) {
-			runtime·unlock(&cbs);
-			return &c->asmbody;
-		}
-	}
-	if(cbs.n >= 2000)
-		runtime·throw("too many callback functions");
-	c = runtime·mal(sizeof *c + n);
-	c->gobody = fn.data;
-	c->link = cbs.link;
-	cbs.link = c;
-	cbs.n++;
-	runtime·unlock(&cbs);
-
-	p = &c->asmbody;
-
-	// MOVL fn, AX
-	*p++ = 0xb8;
-	*(uint32*)p = (uint32)fn.data;
-	p += 4;
-
-	// MOVL argsize, DX
-	*p++ = 0xba;
-	*(uint32*)p = argsize;
-	p += 4;
-
-	// MOVL callbackasm, CX
-	*p++ = 0xb9;
-	*(uint32*)p = (uint32)runtime·callbackasm;
-	p += 4;
-
-	// CALL CX
-	*p++ = 0xff;
-	*p++ = 0xd1;
-
-	// RET argsize?
-	if(cleanstack && argsize!=0) {
-		*p++ = 0xc2;
-		*(uint16*)p = argsize;
-	} else
-		*p = 0xc3;
-
-	return &c->asmbody;
-}
diff --git a/src/pkg/runtime/windows/386/defs.h b/src/pkg/runtime/windows/386/defs.h
deleted file mode 100644
index 6cc5336..0000000
--- a/src/pkg/runtime/windows/386/defs.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// c:\Users\Hector\Code\go\bin\godefs.exe defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1,
-	MAP_PRIVATE = 0x2,
-	DUPLICATE_SAME_ACCESS = 0x2,
-	THREAD_PRIORITY_HIGHEST = 0x2,
-	SIGINT = 0x2,
-	CTRL_C_EVENT = 0,
-	CTRL_BREAK_EVENT = 0x1,
-	CONTEXT_CONTROL = 0x10001,
-	CONTEXT_FULL = 0x10007,
-	EXCEPTION_ACCESS_VIOLATION = 0xc0000005,
-	EXCEPTION_BREAKPOINT = 0x80000003,
-	EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d,
-	EXCEPTION_FLT_DIVIDE_BY_ZERO = 0xc000008e,
-	EXCEPTION_FLT_INEXACT_RESULT = 0xc000008f,
-	EXCEPTION_FLT_OVERFLOW = 0xc0000091,
-	EXCEPTION_FLT_UNDERFLOW = 0xc0000093,
-	EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094,
-	EXCEPTION_INT_OVERFLOW = 0xc0000095,
-};
-
-// Types
-#pragma pack on
-
-typedef struct ExceptionRecord ExceptionRecord;
-struct ExceptionRecord {
-	uint32 ExceptionCode;
-	uint32 ExceptionFlags;
-	ExceptionRecord *ExceptionRecord;
-	void *ExceptionAddress;
-	uint32 NumberParameters;
-	uint32 ExceptionInformation[15];
-};
-
-typedef struct FloatingSaveArea FloatingSaveArea;
-struct FloatingSaveArea {
-	uint32 ControlWord;
-	uint32 StatusWord;
-	uint32 TagWord;
-	uint32 ErrorOffset;
-	uint32 ErrorSelector;
-	uint32 DataOffset;
-	uint32 DataSelector;
-	uint8 RegisterArea[80];
-	uint32 Cr0NpxState;
-};
-
-typedef struct Context Context;
-struct Context {
-	uint32 ContextFlags;
-	uint32 Dr0;
-	uint32 Dr1;
-	uint32 Dr2;
-	uint32 Dr3;
-	uint32 Dr6;
-	uint32 Dr7;
-	FloatingSaveArea FloatSave;
-	uint32 SegGs;
-	uint32 SegFs;
-	uint32 SegEs;
-	uint32 SegDs;
-	uint32 Edi;
-	uint32 Esi;
-	uint32 Ebx;
-	uint32 Edx;
-	uint32 Ecx;
-	uint32 Eax;
-	uint32 Ebp;
-	uint32 Eip;
-	uint32 SegCs;
-	uint32 EFlags;
-	uint32 Esp;
-	uint32 SegSs;
-	uint8 ExtendedRegisters[512];
-};
-#pragma pack off
diff --git a/src/pkg/runtime/windows/386/signal.c b/src/pkg/runtime/windows/386/signal.c
deleted file mode 100644
index 9c912ed..0000000
--- a/src/pkg/runtime/windows/386/signal.c
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-
-void
-runtime·dumpregs(Context *r)
-{
-	runtime·printf("eax     %x\n", r->Eax);
-	runtime·printf("ebx     %x\n", r->Ebx);
-	runtime·printf("ecx     %x\n", r->Ecx);
-	runtime·printf("edx     %x\n", r->Edx);
-	runtime·printf("edi     %x\n", r->Edi);
-	runtime·printf("esi     %x\n", r->Esi);
-	runtime·printf("ebp     %x\n", r->Ebp);
-	runtime·printf("esp     %x\n", r->Esp);
-	runtime·printf("eip     %x\n", r->Eip);
-	runtime·printf("eflags  %x\n", r->EFlags);
-	runtime·printf("cs      %x\n", r->SegCs);
-	runtime·printf("fs      %x\n", r->SegFs);
-	runtime·printf("gs      %x\n", r->SegGs);
-}
-
-void
-runtime·initsig(int32)
-{
-	runtime·siginit();
-}
-
-uint32
-runtime·sighandler(ExceptionRecord *info, void *frame, Context *r)
-{
-	uintptr *sp;
-	G *gp;
-
-	USED(frame);
-
-	switch(info->ExceptionCode) {
-	case EXCEPTION_BREAKPOINT:
-		r->Eip--;	// because 8l generates 2 bytes for INT3
-		return 1;
-	}
-
-	if((gp = m->curg) != nil && runtime·issigpanic(info->ExceptionCode)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = info->ExceptionCode;
-		gp->sigcode0 = info->ExceptionInformation[0];
-		gp->sigcode1 = info->ExceptionInformation[1];
-		gp->sigpc = r->Eip;
-
-		// Only push runtime·sigpanic if r->eip != 0.
-		// If r->eip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->Eip != 0) {
-			sp = (uintptr*)r->Esp;
-			*--sp = r->Eip;
-			r->Esp = (uintptr)sp;
-		}
-		r->Eip = (uintptr)runtime·sigpanic;
-		return 0;
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	runtime·printf("Exception %x %p %p\n", info->ExceptionCode,
-		info->ExceptionInformation[0], info->ExceptionInformation[1]);
-
-	runtime·printf("PC=%x\n", r->Eip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, m->curg);
-		runtime·tracebackothers(m->curg);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-	return 0;
-}
-
-void
-runtime·dosigprof(Context *r, G *gp)
-{
-	runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp);
-}
diff --git a/src/pkg/runtime/windows/386/sys.s b/src/pkg/runtime/windows/386/sys.s
deleted file mode 100644
index 95ae533..0000000
--- a/src/pkg/runtime/windows/386/sys.s
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "386/asm.h"
-
-// void runtime·asmstdcall(void *c);
-TEXT runtime·asmstdcall(SB),7,$0
-	MOVL	c+0(FP), BX
-
-	// SetLastError(0).
-	MOVL	$0, 0x34(FS)
-
-	// Copy args to the stack.
-	MOVL	SP, BP
-	MOVL	wincall_n(BX), CX	// words
-	MOVL	CX, AX
-	SALL	$2, AX
-	SUBL	AX, SP			// room for args
-	MOVL	SP, DI
-	MOVL	wincall_args(BX), SI
-	CLD
-	REP; MOVSL
-
-	// Call stdcall or cdecl function.
-	// DI SI BP BX are preserved, SP is not
-	CALL	wincall_fn(BX)
-	MOVL	BP, SP
-
-	// Return result.
-	MOVL	c+0(FP), BX
-	MOVL	AX, wincall_r1(BX)
-	MOVL	DX, wincall_r2(BX)
-
-	// GetLastError().
-	MOVL	0x34(FS), AX
-	MOVL	AX, wincall_err(BX)
-
-	RET
-
-// faster get/set last error
-TEXT runtime·getlasterror(SB),7,$0
-	MOVL	0x34(FS), AX
-	RET
-
-TEXT runtime·setlasterror(SB),7,$0
-	MOVL	err+0(FP), AX
-	MOVL	AX, 0x34(FS)
-	RET
-
-TEXT runtime·sigtramp(SB),7,$0
-	PUSHL	BP			// cdecl
-	PUSHL	BX
-	PUSHL	SI
-	PUSHL	DI
-	PUSHL	0(FS)
-	CALL	runtime·sigtramp1(SB)
-	POPL	0(FS)
-	POPL	DI
-	POPL	SI
-	POPL	BX
-	POPL	BP
-	RET
-
-TEXT runtime·sigtramp1(SB),0,$16-40
-	// unwinding?
-	MOVL	info+24(FP), BX
-	MOVL	4(BX), CX		// exception flags
-	ANDL	$6, CX
-	MOVL	$1, AX
-	JNZ	sigdone
-
-	// place ourselves at the top of the SEH chain to
-	// ensure SEH frames lie within thread stack bounds
-	MOVL	frame+28(FP), CX	// our SEH frame
-	MOVL	CX, 0(FS)
-
-	// copy arguments for call to sighandler
-	MOVL	BX, 0(SP)
-	MOVL	CX, 4(SP)
-	MOVL	context+32(FP), BX
-	MOVL	BX, 8(SP)
-	MOVL	dispatcher+36(FP), BX
-	MOVL	BX, 12(SP)
-
-	CALL	runtime·sighandler(SB)
-	TESTL	AX, AX
-	JZ	sigdone
-
-	// call windows default handler early
-	MOVL	4(SP), BX		// our SEH frame
-	MOVL	0(BX), BX		// SEH frame of default handler
-	MOVL	BX, 4(SP)		// set establisher frame
-	CALL	4(BX)
-
-sigdone:
-	RET
-
-TEXT runtime·ctrlhandler(SB),7,$0
-	PUSHL	$runtime·ctrlhandler1(SB)
-	CALL	runtime·externalthreadhandler(SB)
-	MOVL	4(SP), CX
-	ADDL	$12, SP
-	JMP	CX
-
-TEXT runtime·profileloop(SB),7,$0
-	PUSHL	$runtime·profileloop1(SB)
-	CALL	runtime·externalthreadhandler(SB)
-	MOVL	4(SP), CX
-	ADDL	$12, SP
-	JMP	CX
-
-TEXT runtime·externalthreadhandler(SB),7,$0
-	PUSHL	BP
-	MOVL	SP, BP
-	PUSHL	BX
-	PUSHL	SI
-	PUSHL	DI
-	PUSHL	0x2c(FS)
-	MOVL	SP, DX
-
-	// setup dummy m, g
-	SUBL	$m_end, SP		// space for M
-	MOVL	SP, 0(SP)
-	MOVL	$m_end, 4(SP)
-	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
-
-	LEAL	m_tls(SP), CX
-	MOVL	CX, 0x2c(FS)
-	MOVL	SP, m(CX)
-	MOVL	SP, BX
-	SUBL	$g_end, SP		// space for G
-	MOVL	SP, g(CX)
-	MOVL	SP, m_g0(BX)
-
-	MOVL	SP, 0(SP)
-	MOVL	$g_end, 4(SP)
-	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
-	LEAL	-4096(SP), CX
-	MOVL	CX, g_stackguard(SP)
-	MOVL	DX, g_stackbase(SP)
-
-	PUSHL	16(BP)			// arg for handler
-	CALL	8(BP)
-	POPL	CX
-
-	get_tls(CX)
-	MOVL	g(CX), CX
-	MOVL	g_stackbase(CX), SP
-	POPL	0x2c(FS)
-	POPL	DI
-	POPL	SI
-	POPL	BX
-	POPL	BP
-	RET
-
-// Called from dynamic function created by ../thread.c compilecallback,
-// running on Windows stack (not Go stack).
-// BX, BP, SI, DI registers and DF flag are preserved
-// as required by windows callback convention.
-// AX = address of go func we need to call
-// DX = total size of arguments
-//
-TEXT runtime·callbackasm+0(SB),7,$0
-	// preserve whatever's at the memory location that
-	// the callback will use to store the return value
-	LEAL	8(SP), CX
-	PUSHL	0(CX)(DX*1)
-	ADDL	$4, DX			// extend argsize by size of return value
-
-	// save registers as required for windows callback
-	PUSHL	DI
-	PUSHL	SI
-	PUSHL	BP
-	PUSHL	BX
-
-	// set up SEH frame again
-	PUSHL	$runtime·sigtramp(SB)
-	PUSHL	0(FS)
-	MOVL	SP, 0(FS)
-
-	// callback parameters
-	PUSHL	DX
-	PUSHL	CX
-	PUSHL	AX
-
-	CLD
-
-	CALL	runtime·cgocallback(SB)
-
-	POPL	AX
-	POPL	CX
-	POPL	DX
-
-	// pop SEH frame
-	POPL	0(FS)
-	POPL	BX
-
-	// restore registers as required for windows callback
-	POPL	BX
-	POPL	BP
-	POPL	SI
-	POPL	DI
-
-	CLD
-
-	MOVL	-4(CX)(DX*1), AX
-	POPL	-4(CX)(DX*1)
-	RET
-
-// void tstart(M *newm);
-TEXT runtime·tstart(SB),7,$0
-	MOVL	newm+4(SP), CX		// m
-	MOVL	m_g0(CX), DX		// g
-
-	// Set up SEH frame
-	PUSHL	$runtime·sigtramp(SB)
-	PUSHL	0(FS)
-	MOVL	SP, 0(FS)
-
-	// Layout new m scheduler stack on os stack.
-	MOVL	SP, AX
-	MOVL	AX, g_stackbase(DX)
-	SUBL	$(64*1024), AX		// stack size
-	MOVL	AX, g_stackguard(DX)
-
-	// Set up tls.
-	LEAL	m_tls(CX), SI
-	MOVL	SI, 0x2c(FS)
-	MOVL	CX, m(SI)
-	MOVL	DX, g(SI)
-
-	// Someday the convention will be D is always cleared.
-	CLD
-
-	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
-
-	CALL	runtime·mstart(SB)
-
-	// Pop SEH frame
-	MOVL	0(FS), SP
-	POPL	0(FS)
-	POPL	CX
-
-	RET
-
-// uint32 tstart_stdcall(M *newm);
-TEXT runtime·tstart_stdcall(SB),7,$0
-	MOVL	newm+4(SP), BX
-
-	PUSHL	BX
-	CALL	runtime·tstart(SB)
-	POPL	BX
-
-	// Adjust stack for stdcall to return properly.
-	MOVL	(SP), AX		// save return address
-	ADDL	$4, SP			// remove single parameter
-	MOVL	AX, (SP)		// restore return address
-
-	XORL	AX, AX			// return 0 == success
-
-	RET
-
-// setldt(int entry, int address, int limit)
-TEXT runtime·setldt(SB),7,$0
-	MOVL	address+4(FP), CX
-	MOVL	CX, 0x2c(FS)
-	RET
diff --git a/src/pkg/runtime/windows/amd64/callback.c b/src/pkg/runtime/windows/amd64/callback.c
deleted file mode 100644
index d53822e..0000000
--- a/src/pkg/runtime/windows/amd64/callback.c
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "type.h"
-#include "defs.h"
-#include "os.h"
-
-// Will keep all callbacks in a linked list, so they don't get garbage collected.
-typedef	struct	Callback	Callback;
-struct	Callback {
-	Callback*	link;
-	void*		gobody;
-	byte		asmbody;
-};
-
-typedef	struct	Callbacks	Callbacks;
-struct	Callbacks {
-	Lock;
-	Callback*	link;
-	int32		n;
-};
-
-static	Callbacks	cbs;
-
-// Call back from windows dll into go.
-byte *
-runtime·compilecallback(Eface fn, bool /*cleanstack*/)
-{
-	FuncType *ft;
-	Type *t;
-	int32 argsize, i, n;
-	byte *p;
-	Callback *c;
-
-	if(fn.type == nil || fn.type->kind != KindFunc)
-		runtime·panicstring("compilecallback: not a function");
-	ft = (FuncType*)fn.type;
-	if(ft->out.len != 1)
-		runtime·panicstring("compilecallback: function must have one output parameter");
-	if(((Type**)ft->out.array)[0]->size != sizeof(uintptr))
-		runtime·panicstring("compilecallback: output parameter size is wrong");
-	argsize = 0;
-	for(i=0; i<ft->in.len; i++) {
-		t = ((Type**)ft->in.array)[i];
-		if(t->size > sizeof(uintptr))
-			runtime·panicstring("compilecallback: input parameter size is wrong");
-		argsize += sizeof(uintptr);
-	}
-
-	// compute size of new fn.
-	// must match code laid out below.
-	n  = 2+8+1; // MOVQ fn, AX           / PUSHQ AX
-	n += 2+8+1; // MOVQ argsize, AX      / PUSHQ AX
-	n += 2+8;   // MOVQ callbackasm, AX
-	n += 2;     // JMP  AX
-
-	runtime·lock(&cbs);
-	for(c = cbs.link; c != nil; c = c->link) {
-		if(c->gobody == fn.data) {
-			runtime·unlock(&cbs);
-			return &c->asmbody;
-		}
-	}
-	if(cbs.n >= 2000)
-		runtime·throw("too many callback functions");
-	c = runtime·mal(sizeof *c + n);
-	c->gobody = fn.data;
-	c->link = cbs.link;
-	cbs.link = c;
-	cbs.n++;
-	runtime·unlock(&cbs);
-
-	p = &c->asmbody;
-
-	// MOVQ fn, AX
-	*p++ = 0x48;
-	*p++ = 0xb8;
-	*(uint64*)p = (uint64)fn.data;
-	p += 8;
-	// PUSH AX
-	*p++ = 0x50;
-
-	// MOVQ argsize, AX
-	*p++ = 0x48;
-	*p++ = 0xb8;
-	*(uint64*)p = argsize;
-	p += 8;
-	// PUSH AX
-	*p++ = 0x50;
-
-	// MOVQ callbackasm, AX
-	*p++ = 0x48;
-	*p++ = 0xb8;
-	*(uint64*)p = (uint64)runtime·callbackasm;
-	p += 8;
-
-	// JMP AX
-	*p++ = 0xFF;
-	*p++ = 0xE0;
-
-	return &c->asmbody;
-}
diff --git a/src/pkg/runtime/windows/amd64/defs.h b/src/pkg/runtime/windows/amd64/defs.h
deleted file mode 100644
index d5191a3..0000000
--- a/src/pkg/runtime/windows/amd64/defs.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// c:\go\bin\godefs.exe -f -m64 defs.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Constants
-enum {
-	PROT_NONE = 0,
-	PROT_READ = 0x1,
-	PROT_WRITE = 0x2,
-	PROT_EXEC = 0x4,
-	MAP_ANON = 0x1,
-	MAP_PRIVATE = 0x2,
-	DUPLICATE_SAME_ACCESS = 0x2,
-	THREAD_PRIORITY_HIGHEST = 0x2,
-	SIGINT = 0x2,
-	CTRL_C_EVENT = 0,
-	CTRL_BREAK_EVENT = 0x1,
-	CONTEXT_CONTROL = 0x100001,
-	CONTEXT_FULL = 0x10000b,
-	EXCEPTION_ACCESS_VIOLATION = 0xc0000005,
-	EXCEPTION_BREAKPOINT = 0x80000003,
-	EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d,
-	EXCEPTION_FLT_DIVIDE_BY_ZERO = 0xc000008e,
-	EXCEPTION_FLT_INEXACT_RESULT = 0xc000008f,
-	EXCEPTION_FLT_OVERFLOW = 0xc0000091,
-	EXCEPTION_FLT_UNDERFLOW = 0xc0000093,
-	EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094,
-	EXCEPTION_INT_OVERFLOW = 0xc0000095,
-};
-
-// Types
-#pragma pack on
-
-typedef struct ExceptionRecord ExceptionRecord;
-struct ExceptionRecord {
-	uint32 ExceptionCode;
-	uint32 ExceptionFlags;
-	ExceptionRecord *ExceptionRecord;
-	void *ExceptionAddress;
-	uint32 NumberParameters;
-	byte pad_godefs_0[4];
-	uint64 ExceptionInformation[15];
-};
-
-typedef struct M128a M128a;
-struct M128a {
-	uint64 Low;
-	int64 High;
-};
-
-typedef struct Context Context;
-struct Context {
-	uint64 P1Home;
-	uint64 P2Home;
-	uint64 P3Home;
-	uint64 P4Home;
-	uint64 P5Home;
-	uint64 P6Home;
-	uint32 ContextFlags;
-	uint32 MxCsr;
-	uint16 SegCs;
-	uint16 SegDs;
-	uint16 SegEs;
-	uint16 SegFs;
-	uint16 SegGs;
-	uint16 SegSs;
-	uint32 EFlags;
-	uint64 Dr0;
-	uint64 Dr1;
-	uint64 Dr2;
-	uint64 Dr3;
-	uint64 Dr6;
-	uint64 Dr7;
-	uint64 Rax;
-	uint64 Rcx;
-	uint64 Rdx;
-	uint64 Rbx;
-	uint64 Rsp;
-	uint64 Rbp;
-	uint64 Rsi;
-	uint64 Rdi;
-	uint64 R8;
-	uint64 R9;
-	uint64 R10;
-	uint64 R11;
-	uint64 R12;
-	uint64 R13;
-	uint64 R14;
-	uint64 R15;
-	uint64 Rip;
-	byte Pad_godefs_0[512];
-	M128a VectorRegister[26];
-	uint64 VectorControl;
-	uint64 DebugControl;
-	uint64 LastBranchToRip;
-	uint64 LastBranchFromRip;
-	uint64 LastExceptionToRip;
-	uint64 LastExceptionFromRip;
-};
-#pragma pack off
diff --git a/src/pkg/runtime/windows/amd64/rt0.s b/src/pkg/runtime/windows/amd64/rt0.s
deleted file mode 100644
index 35978bc..0000000
--- a/src/pkg/runtime/windows/amd64/rt0.s
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "amd64/asm.h"
-
-TEXT	_rt0_amd64_windows(SB),7,$-8
-	MOVQ	$_rt0_amd64(SB), AX
-	MOVQ	SP, DI
-	JMP	AX
-
-DATA  runtime·iswindows(SB)/4, $1
-GLOBL runtime·iswindows(SB), $4
diff --git a/src/pkg/runtime/windows/amd64/signal.c b/src/pkg/runtime/windows/amd64/signal.c
deleted file mode 100644
index 97106c8..0000000
--- a/src/pkg/runtime/windows/amd64/signal.c
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs.h"
-#include "os.h"
-
-extern void *runtime·sigtramp;
-
-void
-runtime·dumpregs(Context *r)
-{
-	runtime·printf("rax     %X\n", r->Rax);
-	runtime·printf("rbx     %X\n", r->Rbx);
-	runtime·printf("rcx     %X\n", r->Rcx);
-	runtime·printf("rdx     %X\n", r->Rdx);
-	runtime·printf("rdi     %X\n", r->Rdi);
-	runtime·printf("rsi     %X\n", r->Rsi);
-	runtime·printf("rbp     %X\n", r->Rbp);
-	runtime·printf("rsp     %X\n", r->Rsp);
-	runtime·printf("r8      %X\n", r->R8 );
-	runtime·printf("r9      %X\n", r->R9 );
-	runtime·printf("r10     %X\n", r->R10);
-	runtime·printf("r11     %X\n", r->R11);
-	runtime·printf("r12     %X\n", r->R12);
-	runtime·printf("r13     %X\n", r->R13);
-	runtime·printf("r14     %X\n", r->R14);
-	runtime·printf("r15     %X\n", r->R15);
-	runtime·printf("rip     %X\n", r->Rip);
-	runtime·printf("rflags  %X\n", r->EFlags);
-	runtime·printf("cs      %X\n", (uint64)r->SegCs);
-	runtime·printf("fs      %X\n", (uint64)r->SegFs);
-	runtime·printf("gs      %X\n", (uint64)r->SegGs);
-}
-
-void
-runtime·initsig(int32)
-{
-	runtime·siginit();
-	// following line keeps sigtramp alive at link stage
-	// if there's a better way please write it here
-	void *p = runtime·sigtramp;
-	USED(p);
-}
-
-uint32
-runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
-{
-	uintptr *sp;
-
-	switch(info->ExceptionCode) {
-	case EXCEPTION_BREAKPOINT:
-		return 1;
-	}
-
-	if(gp != nil && runtime·issigpanic(info->ExceptionCode)) {
-		// Make it look like a call to the signal func.
-		// Have to pass arguments out of band since
-		// augmenting the stack frame would break
-		// the unwinding code.
-		gp->sig = info->ExceptionCode;
-		gp->sigcode0 = info->ExceptionInformation[0];
-		gp->sigcode1 = info->ExceptionInformation[1];
-		gp->sigpc = r->Rip;
-
-		// Only push runtime·sigpanic if r->rip != 0.
-		// If r->rip == 0, probably panicked because of a
-		// call to a nil func.  Not pushing that onto sp will
-		// make the trace look like a call to runtime·sigpanic instead.
-		// (Otherwise the trace will end at runtime·sigpanic and we
-		// won't get to see who faulted.)
-		if(r->Rip != 0) {
-			sp = (uintptr*)r->Rsp;
-			*--sp = r->Rip;
-			r->Rsp = (uintptr)sp;
-		}
-		r->Rip = (uintptr)runtime·sigpanic;
-		return 0;
-	}
-
-	if(runtime·panicking)	// traceback already printed
-		runtime·exit(2);
-	runtime·panicking = 1;
-
-	runtime·printf("Exception %x %p %p\n", info->ExceptionCode,
-		info->ExceptionInformation[0], info->ExceptionInformation[1]);
-
-	runtime·printf("PC=%X\n", r->Rip);
-	runtime·printf("\n");
-
-	if(runtime·gotraceback()){
-		runtime·traceback((void*)r->Rip, (void*)r->Rsp, 0, gp);
-		runtime·tracebackothers(gp);
-		runtime·dumpregs(r);
-	}
-
-	runtime·exit(2);
-	return 0;
-}
-
-void
-runtime·dosigprof(Context *r, G *gp)
-{
-	runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp);
-}
diff --git a/src/pkg/runtime/windows/amd64/sys.s b/src/pkg/runtime/windows/amd64/sys.s
deleted file mode 100644
index 113db20..0000000
--- a/src/pkg/runtime/windows/amd64/sys.s
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "amd64/asm.h"
-
-#define maxargs 12
-
-// void runtime·asmstdcall(void *c);
-TEXT runtime·asmstdcall(SB),7,$0
-	// asmcgocall will put first argument into CX.
-	PUSHQ	CX			// save for later
-	MOVQ	wincall_fn(CX), AX
-	MOVQ	wincall_args(CX), SI
-	MOVQ	wincall_n(CX), CX
-
-	// SetLastError(0).
-	MOVQ	0x30(GS), DI
-	MOVL	$0, 0x68(DI)
-
-	SUBQ	$(maxargs*8), SP	// room for args
-
-	// Fast version, do not store args on the stack.
-	CMPL	CX, $4
-	JLE	loadregs
-
-	// Check we have enough room for args.
-	CMPL	CX, $maxargs
-	JLE	2(PC)
-	INT	$3			// not enough room -> crash
-
-	// Copy args to the stack.
-	MOVQ	SP, DI
-	CLD
-	REP; MOVSQ
-	MOVQ	SP, SI
-
-loadregs:
-	// Load first 4 args into correspondent registers.
-	MOVQ	0(SI), CX
-	MOVQ	8(SI), DX
-	MOVQ	16(SI), R8
-	MOVQ	24(SI), R9
-
-	// Call stdcall function.
-	CALL	AX
-
-	ADDQ	$(maxargs*8), SP
-
-	// Return result.
-	POPQ	CX
-	MOVQ	AX, wincall_r1(CX)
-
-	// GetLastError().
-	MOVQ	0x30(GS), DI
-	MOVL	0x68(DI), AX
-	MOVQ	AX, wincall_err(CX)
-
-	RET
-
-// faster get/set last error
-TEXT runtime·getlasterror(SB),7,$0
-	MOVQ	0x30(GS), AX
-	MOVL	0x68(AX), AX
-	RET
-
-TEXT runtime·setlasterror(SB),7,$0
-	MOVL	err+0(FP), AX
-	MOVQ	0x30(GS),	CX
-	MOVL	AX, 0x68(CX)
-	RET
-
-TEXT runtime·sigtramp(SB),7,$56
-	// CX: exception record
-	// R8: context
-
-	// unwinding?
-	TESTL	$6, 4(CX)		// exception flags
-	MOVL	$1, AX
-	JNZ	sigdone
-
-	// copy arguments for call to sighandler
-	MOVQ	CX, 0(SP)
-	MOVQ	R8, 8(SP)
-	get_tls(CX)
-	MOVQ	g(CX), CX
-	MOVQ	CX, 16(SP)
-
-	MOVQ	BX, 24(SP)
-	MOVQ	BP, 32(SP)
-	MOVQ	SI, 40(SP)
-	MOVQ	DI, 48(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	MOVQ	24(SP), BX
-	MOVQ	32(SP), BP
-	MOVQ	40(SP), SI
-	MOVQ	48(SP), DI
-sigdone:
-	RET
-
-TEXT runtime·ctrlhandler(SB),7,$8
-	MOVQ	CX, 16(SP)		// spill
-	MOVQ	$runtime·ctrlhandler1(SB), CX
-	MOVQ	CX, 0(SP)
-	CALL	runtime·externalthreadhandler(SB)
-	RET
-
-TEXT runtime·profileloop(SB),7,$8
-	MOVQ	$runtime·profileloop1(SB), CX
-	MOVQ	CX, 0(SP)
-	CALL	runtime·externalthreadhandler(SB)
-	RET
-
-TEXT runtime·externalthreadhandler(SB),7,$0
-	PUSHQ	BP
-	MOVQ	SP, BP
-	PUSHQ	BX
-	PUSHQ	SI
-	PUSHQ	DI
-	PUSHQ	0x58(GS)
-	MOVQ	SP, DX
-
-	// setup dummy m, g
-	SUBQ	$m_end, SP		// space for M
-	MOVQ	SP, 0(SP)
-	MOVQ	$m_end, 8(SP)
-	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
-
-	LEAQ	m_tls(SP), CX
-	MOVQ	CX, 0x58(GS)
-	MOVQ	SP, m(CX)
-	MOVQ	SP, BX
-	SUBQ	$g_end, SP		// space for G
-	MOVQ	SP, g(CX)
-	MOVQ	SP, m_g0(BX)
-
-	MOVQ	SP, 0(SP)
-	MOVQ	$g_end, 8(SP)
-	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
-	LEAQ	-8192(SP), CX
-	MOVQ	CX, g_stackguard(SP)
-	MOVQ	DX, g_stackbase(SP)
-
-	PUSHQ	32(BP)			// arg for handler
-	CALL	16(BP)
-	POPQ	CX
-
-	get_tls(CX)
-	MOVQ	g(CX), CX
-	MOVQ	g_stackbase(CX), SP
-	POPQ	0x58(GS)
-	POPQ	DI
-	POPQ	SI
-	POPQ	BX
-	POPQ	BP
-	RET
-
-// Continuation of thunk function created for each callback by ../thread.c compilecallback,
-// runs on Windows stack (not Go stack).
-// Thunk code designed to have minimal size for it is copied many (up to thousands) times.
-//
-// thunk:
-//	MOVQ	$fn, AX
-//	PUSHQ	AX
-//	MOVQ	$argsize, AX
-//	PUSHQ	AX
-//	MOVQ	$runtime·callbackasm, AX
-//	JMP	AX
-TEXT runtime·callbackasm(SB),7,$0
-	// Construct args vector for cgocallback().
-	// By windows/amd64 calling convention first 4 args are in CX, DX, R8, R9
-	// args from the 5th on are on the stack.
-	// In any case, even if function has 0,1,2,3,4 args, there is reserved
-	// but uninitialized "shadow space" for the first 4 args.
-	// The values are in registers.
-  	MOVQ	CX, (24+0)(SP)
-  	MOVQ	DX, (24+8)(SP)
-  	MOVQ	R8, (24+16)(SP)
-  	MOVQ	R9, (24+24)(SP)
-	// 6l does not accept writing POPQs here issuing a warning "unbalanced PUSH/POP"
-  	MOVQ	0(SP), DX	// POPQ DX
-  	MOVQ	8(SP), AX	// POPQ AX
-	ADDQ	$16, SP
-
-	// preserve whatever's at the memory location that
-	// the callback will use to store the return value
-	LEAQ	8(SP), CX       // args vector, skip return address
-	PUSHQ	0(CX)(DX*1)     // store 8 bytes from just after the args array
-	ADDQ	$8, DX          // extend argsize by size of return value
-
-	// DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
-	// as required by windows callback convention.
-	// 6l does not allow writing many PUSHQs here issuing a warning "nosplit stack overflow"
-	// the warning has no sense as this code uses os thread stack
-	PUSHFQ
-	SUBQ	$64, SP
-	MOVQ	DI, 56(SP)
-	MOVQ	SI, 48(SP)
-	MOVQ	BP, 40(SP)
-	MOVQ	BX, 32(SP)
-	MOVQ	R12, 24(SP)
-	MOVQ	R13, 16(SP)
-	MOVQ	R14, 8(SP)
-	MOVQ	R15, 0(SP)
-
-	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
-	PUSHQ	DX    // uintptr framesize
-	PUSHQ	CX    // void *frame
-	PUSHQ	AX    // void (*fn)(void*)
-	CLD
-	CALL  runtime·cgocallback(SB)
-	POPQ	AX
-	POPQ	CX
-	POPQ	DX
-
-	// restore registers as required for windows callback
-	// 6l does not allow writing many POPs here issuing a warning "nosplit stack overflow"
-	MOVQ	0(SP), R15
-	MOVQ	8(SP), R14
-	MOVQ	16(SP), R13
-	MOVQ	24(SP), R12
-	MOVQ	32(SP), BX
-	MOVQ	40(SP), BP
-	MOVQ	48(SP), SI
-	MOVQ	56(SP), DI
-	ADDQ	$64, SP
-	POPFQ
-
-	MOVL	-8(CX)(DX*1), AX  // return value
-	POPQ	-8(CX)(DX*1)      // restore bytes just after the args
-	RET
-
-TEXT runtime·setstacklimits(SB),7,$0
-	MOVQ	0x30(GS), CX
-	MOVQ	$0, 0x10(CX)
-	MOVQ	$0xffffffffffff, AX
-	MOVQ	AX, 0x08(CX)
-	RET
-
-// uint32 tstart_stdcall(M *newm);
-TEXT runtime·tstart_stdcall(SB),7,$0
-	// CX contains first arg newm
-	MOVQ	m_g0(CX), DX		// g
-
-	// Layout new m scheduler stack on os stack.
-	MOVQ	SP, AX
-	MOVQ	AX, g_stackbase(DX)
-	SUBQ	$(64*1024), AX		// stack size
-	MOVQ	AX, g_stackguard(DX)
-
-	// Set up tls.
-	LEAQ	m_tls(CX), SI
-	MOVQ	SI, 0x58(GS)
-	MOVQ	CX, m(SI)
-	MOVQ	DX, g(SI)
-
-	// Someday the convention will be D is always cleared.
-	CLD
-
-	CALL	runtime·setstacklimits(SB)
-	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
-	CALL	runtime·mstart(SB)
-
-	XORL	AX, AX			// return 0 == success
-	RET
-
-TEXT runtime·notok(SB),7,$0
-	MOVQ	$0xf1, BP
-	MOVQ	BP, (BP)
-	RET
-
-// set tls base to DI
-TEXT runtime·settls(SB),7,$0
-	CALL	runtime·setstacklimits(SB)
-	MOVQ	DI, 0x58(GS)
-	RET
diff --git a/src/pkg/runtime/windows/defs.c b/src/pkg/runtime/windows/defs.c
deleted file mode 100644
index 1b07dfb..0000000
--- a/src/pkg/runtime/windows/defs.c
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <signal.h>
-#include <stdarg.h>
-#include <windef.h>
-#include <winbase.h>
-#include <wincon.h>
-
-enum {
-	$PROT_NONE = 0,
-	$PROT_READ = 1,
-	$PROT_WRITE = 2,
-	$PROT_EXEC = 4,
-
-	$MAP_ANON = 1,
-	$MAP_PRIVATE = 2,
-
-	$DUPLICATE_SAME_ACCESS = DUPLICATE_SAME_ACCESS,
-	$THREAD_PRIORITY_HIGHEST = THREAD_PRIORITY_HIGHEST,
-
-	$SIGINT = SIGINT,
-	$CTRL_C_EVENT = CTRL_C_EVENT,
-	$CTRL_BREAK_EVENT = CTRL_BREAK_EVENT,
-
-	$CONTEXT_CONTROL = CONTEXT_CONTROL,
-	$CONTEXT_FULL = CONTEXT_FULL,
-
-	$EXCEPTION_ACCESS_VIOLATION = STATUS_ACCESS_VIOLATION,
-	$EXCEPTION_BREAKPOINT = STATUS_BREAKPOINT,
-	$EXCEPTION_FLT_DENORMAL_OPERAND = STATUS_FLOAT_DENORMAL_OPERAND,
-	$EXCEPTION_FLT_DIVIDE_BY_ZERO = STATUS_FLOAT_DIVIDE_BY_ZERO,
-	$EXCEPTION_FLT_INEXACT_RESULT = STATUS_FLOAT_INEXACT_RESULT,
-	$EXCEPTION_FLT_OVERFLOW = STATUS_FLOAT_OVERFLOW,
-	$EXCEPTION_FLT_UNDERFLOW = STATUS_FLOAT_UNDERFLOW,
-	$EXCEPTION_INT_DIVIDE_BY_ZERO = STATUS_INTEGER_DIVIDE_BY_ZERO,
-	$EXCEPTION_INT_OVERFLOW = STATUS_INTEGER_OVERFLOW,
-};
-
-typedef EXCEPTION_RECORD $ExceptionRecord;
-#ifdef _X86_
-typedef FLOATING_SAVE_AREA $FloatingSaveArea;
-#endif
-#ifdef _AMD64_
-typedef M128A $M128a;
-#endif
-typedef CONTEXT $Context;
diff --git a/src/pkg/runtime/windows/mem.c b/src/pkg/runtime/windows/mem.c
deleted file mode 100644
index 5d2291f..0000000
--- a/src/pkg/runtime/windows/mem.c
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "os.h"
-#include "defs.h"
-#include "malloc.h"
-
-enum {
-	MEM_COMMIT = 0x1000,
-	MEM_RESERVE = 0x2000,
-	MEM_RELEASE = 0x8000,
-	
-	PAGE_EXECUTE_READWRITE = 0x40,
-};
-
-#pragma dynimport runtime·VirtualAlloc VirtualAlloc "kernel32.dll"
-#pragma dynimport runtime·VirtualFree VirtualFree "kernel32.dll"
-extern void *runtime·VirtualAlloc;
-extern void *runtime·VirtualFree;
-
-void*
-runtime·SysAlloc(uintptr n)
-{
-	mstats.sys += n;
-	return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)(MEM_COMMIT|MEM_RESERVE), (uintptr)PAGE_EXECUTE_READWRITE);
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-	USED(v);
-	USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n)
-{
-	uintptr r;
-
-	mstats.sys -= n;
-	r = (uintptr)runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_RELEASE);
-	if(r == 0)
-		runtime·throw("runtime: failed to release pages");
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n)
-{
-	// v is just a hint.
-	// First try at v.
-	v = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_EXECUTE_READWRITE);
-	if(v != nil)
-		return v;
-	
-	// Next let the kernel choose the address.
-	return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_EXECUTE_READWRITE);
-}
-
-void
-runtime·SysMap(void *v, uintptr n)
-{
-	void *p;
-	
-	mstats.sys += n;
-	p = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_EXECUTE_READWRITE);
-	if(p != v)
-		runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/pkg/runtime/windows/os.h b/src/pkg/runtime/windows/os.h
deleted file mode 100644
index 21277c6..0000000
--- a/src/pkg/runtime/windows/os.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-extern void *runtime·LoadLibraryEx;
-extern void *runtime·GetProcAddress;
-
-// Call a Windows function with stdcall conventions,
-// and switch to os stack during the call.
-#pragma	varargck	countpos	runtime·stdcall	2
-#pragma	varargck	type		runtime·stdcall	void*
-#pragma	varargck	type		runtime·stdcall	uintptr
-void runtime·asmstdcall(void *c);
-void *runtime·stdcall(void *fn, int32 count, ...);
-
-uint32 runtime·getlasterror(void);
-void runtime·setlasterror(uint32 err);
-
-// Function to be called by windows CreateThread
-// to start new os thread.
-uint32 runtime·tstart_stdcall(M *newm);
-
-uint32 runtime·issigpanic(uint32);
-void runtime·sigpanic(void);
-uint32 runtime·ctrlhandler(uint32 type);
-
-// Windows dll function to go callback entry.
-byte *runtime·compilecallback(Eface fn, bool cleanstack);
-void *runtime·callbackasm(void);
diff --git a/src/pkg/runtime/windows/syscall.goc b/src/pkg/runtime/windows/syscall.goc
deleted file mode 100644
index 68c3a4d..0000000
--- a/src/pkg/runtime/windows/syscall.goc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-#include "runtime.h"
-#include "os.h"
-#include "cgocall.h"
-
-func loadlibraryex(filename uintptr) (handle uintptr) {
-	uintptr args[3] = { filename };
-	WinCall c;
-
-	c.fn = runtime·LoadLibraryEx;
-	c.n = 3;
-	c.args = &args[0];
-	runtime·cgocall(runtime·asmstdcall, &c);
-	handle = c.r1;
-}
-
-func getprocaddress(handle uintptr, procname uintptr) (proc uintptr) {
-	WinCall c;
-
-	USED(procname);
-	c.fn = runtime·GetProcAddress;
-	c.n = 2;
-	c.args = &handle;
-	runtime·cgocall(runtime·asmstdcall, &c);
-	proc = c.r1;
-}
-
-func NewCallback(fn Eface) (code uintptr) {
-	code = (uintptr)runtime·compilecallback(fn, true);
-}
-
-func NewCallbackCDecl(fn Eface) (code uintptr) {
-	code = (uintptr)runtime·compilecallback(fn, false);
-}
-
-func Syscall(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
-	WinCall c;
-
-	USED(a2);
-	USED(a3);
-	c.fn = (void*)fn;
-	c.n = nargs;
-	c.args = &a1;
-	runtime·cgocall(runtime·asmstdcall, &c);
-	err = c.err;
-	r1 = c.r1;
-	r2 = c.r2;
-}
-
-func Syscall6(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
-	WinCall c;
-
-	USED(a2);
-	USED(a3);
-	USED(a4);
-	USED(a5);
-	USED(a6);
-	c.fn = (void*)fn;
-	c.n = nargs;
-	c.args = &a1;
-	runtime·cgocall(runtime·asmstdcall, &c);
-	err = c.err;
-	r1 = c.r1;
-	r2 = c.r2;
-}
-
-func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
-	WinCall c;
-
-	USED(a2);
-	USED(a3);
-	USED(a4);
-	USED(a5);
-	USED(a6);
-	USED(a7);
-	USED(a8);
-	USED(a9);
-	c.fn = (void*)fn;
-	c.n = nargs;
-	c.args = &a1;
-	runtime·cgocall(runtime·asmstdcall, &c);
-	err = c.err;
-	r1 = c.r1;
-	r2 = c.r2;
-}
-
-func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
-	WinCall c;
-
-	USED(a2);
-	USED(a3);
-	USED(a4);
-	USED(a5);
-	USED(a6);
-	USED(a7);
-	USED(a8);
-	USED(a9);
-	USED(a10);
-	USED(a11);
-	USED(a12);
-	c.fn = (void*)fn;
-	c.n = nargs;
-	c.args = &a1;
-	runtime·cgocall(runtime·asmstdcall, &c);
-	err = c.err;
-	r1 = c.r1;
-	r2 = c.r2;
-}
diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c
deleted file mode 100644
index 97a42d7..0000000
--- a/src/pkg/runtime/windows/thread.c
+++ /dev/null
@@ -1,437 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "type.h"
-#include "defs.h"
-#include "os.h"
-
-#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
-#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
-#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
-#pragma dynimport runtime·CreateWaitableTimer CreateWaitableTimerA "kernel32.dll"
-#pragma dynimport runtime·DuplicateHandle DuplicateHandle "kernel32.dll"
-#pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll"
-#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
-#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
-#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll"
-#pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll"
-#pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll"
-#pragma dynimport runtime·LoadLibraryEx LoadLibraryExA "kernel32.dll"
-#pragma dynimport runtime·QueryPerformanceCounter QueryPerformanceCounter "kernel32.dll"
-#pragma dynimport runtime·QueryPerformanceFrequency QueryPerformanceFrequency "kernel32.dll"
-#pragma dynimport runtime·ResumeThread ResumeThread "kernel32.dll"
-#pragma dynimport runtime·SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll"
-#pragma dynimport runtime·SetEvent SetEvent "kernel32.dll"
-#pragma dynimport runtime·SetThreadPriority SetThreadPriority "kernel32.dll"
-#pragma dynimport runtime·SetWaitableTimer SetWaitableTimer "kernel32.dll"
-#pragma dynimport runtime·SuspendThread SuspendThread "kernel32.dll"
-#pragma dynimport runtime·timeBeginPeriod timeBeginPeriod "winmm.dll"
-#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll"
-#pragma dynimport runtime·WriteFile WriteFile "kernel32.dll"
-
-extern void *runtime·CloseHandle;
-extern void *runtime·CreateEvent;
-extern void *runtime·CreateThread;
-extern void *runtime·CreateWaitableTimer;
-extern void *runtime·DuplicateHandle;
-extern void *runtime·ExitProcess;
-extern void *runtime·FreeEnvironmentStringsW;
-extern void *runtime·GetEnvironmentStringsW;
-extern void *runtime·GetProcAddress;
-extern void *runtime·GetStdHandle;
-extern void *runtime·GetThreadContext;
-extern void *runtime·LoadLibraryEx;
-extern void *runtime·QueryPerformanceCounter;
-extern void *runtime·QueryPerformanceFrequency;
-extern void *runtime·ResumeThread;
-extern void *runtime·SetConsoleCtrlHandler;
-extern void *runtime·SetEvent;
-extern void *runtime·SetThreadPriority;
-extern void *runtime·SetWaitableTimer;
-extern void *runtime·SuspendThread;
-extern void *runtime·timeBeginPeriod;
-extern void *runtime·WaitForSingleObject;
-extern void *runtime·WriteFile;
-
-static int64 timerfreq;
-
-void
-runtime·osinit(void)
-{
-	// -1 = current process, -2 = current thread
-	runtime·stdcall(runtime·DuplicateHandle, 7,
-		(uintptr)-1, (uintptr)-2, (uintptr)-1, &m->thread,
-		(uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS);
-	runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq);
-	runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1);
-	runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1);
-}
-
-void
-runtime·goenvs(void)
-{
-	extern Slice os·Envs;
-
-	uint16 *env;
-	String *s;
-	int32 i, n;
-	uint16 *p;
-
-	env = runtime·stdcall(runtime·GetEnvironmentStringsW, 0);
-
-	n = 0;
-	for(p=env; *p; n++)
-		p += runtime·findnullw(p)+1;
-
-	s = runtime·malloc(n*sizeof s[0]);
-
-	p = env;
-	for(i=0; i<n; i++) {
-		s[i] = runtime·gostringw(p);
-		p += runtime·findnullw(p)+1;
-	}
-	os·Envs.array = (byte*)s;
-	os·Envs.len = n;
-	os·Envs.cap = n;
-
-	runtime·stdcall(runtime·FreeEnvironmentStringsW, 1, env);
-}
-
-void
-runtime·exit(int32 code)
-{
-	runtime·stdcall(runtime·ExitProcess, 1, (uintptr)code);
-}
-
-int32
-runtime·write(int32 fd, void *buf, int32 n)
-{
-	void *handle;
-	uint32 written;
-
-	written = 0;
-	switch(fd) {
-	case 1:
-		handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-11);
-		break;
-	case 2:
-		handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-12);
-		break;
-	default:
-		return -1;
-	}
-	runtime·stdcall(runtime·WriteFile, 5, handle, buf, (uintptr)n, &written, (uintptr)0);
-	return written;
-}
-
-// Thread-safe allocation of an event.
-static void
-initevent(void **pevent)
-{
-	void *event;
-
-	event = runtime·stdcall(runtime·CreateEvent, 4, (uintptr)0, (uintptr)0, (uintptr)0, (uintptr)0);
-	if(!runtime·casp(pevent, 0, event)) {
-		// Someone else filled it in.  Use theirs.
-		runtime·stdcall(runtime·CloseHandle, 1, event);
-	}
-}
-
-#define LOCK_HELD ((M*)-1)
-
-static void
-eventlock(Lock *l)
-{
-	// Allocate event if needed.
-	if(m->event == nil)
-		initevent(&m->event);
-
-	for(;;) {
-		m->nextwaitm = runtime·atomicloadp(&l->waitm);
-		if(m->nextwaitm == nil) {
-			if(runtime·casp(&l->waitm, nil, LOCK_HELD))
-				return;
-		// Someone else has it.
-		// l->waitm points to a linked list of M's waiting
-		// for this lock, chained through m->nextwaitm.
-		// Queue this M.
-		} else if(runtime·casp(&l->waitm, m->nextwaitm, m))
-			break;
-	}
-
-	// Wait.
-	runtime·stdcall(runtime·WaitForSingleObject, 2, m->event, (uintptr)-1);
-}
-
-static void
-eventunlock(Lock *l)
-{
-	M *mp;
-
-	for(;;) {
-		mp = runtime·atomicloadp(&l->waitm);
-		if(mp == LOCK_HELD) {
-			if(runtime·casp(&l->waitm, LOCK_HELD, nil))
-				return;
-		// Other M's are waiting for the lock.
-		// Dequeue a M.
-		} else if(runtime·casp(&l->waitm, mp, mp->nextwaitm))
-			break;
-	}
-
-	// Wake that M.
-	runtime·stdcall(runtime·SetEvent, 1, mp->event);
-}
-
-void
-runtime·lock(Lock *l)
-{
-	if(m->locks < 0)
-		runtime·throw("lock count");
-	m->locks++;
-	eventlock(l);
-}
-
-void
-runtime·unlock(Lock *l)
-{
-	m->locks--;
-	if(m->locks < 0)
-		runtime·throw("lock count");
-	eventunlock(l);
-}
-
-void
-runtime·noteclear(Note *n)
-{
-	n->lock.waitm = nil;
-	eventlock(&n->lock);
-}
-
-void
-runtime·notewakeup(Note *n)
-{
-	eventunlock(&n->lock);
-}
-
-void
-runtime·notesleep(Note *n)
-{
-	eventlock(&n->lock);
-	eventunlock(&n->lock);	// Let other sleepers find out too.
-}
-
-void
-runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
-{
-	void *thandle;
-
-	USED(stk);
-	USED(g);	// assuming g = m->g0
-	USED(fn);	// assuming fn = mstart
-
-	thandle = runtime·stdcall(runtime·CreateThread, 6,
-		nil, nil, runtime·tstart_stdcall, m, nil, nil);
-	if(thandle == nil) {
-		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror());
-		runtime·throw("runtime.newosproc");
-	}
-	runtime·atomicstorep(&m->thread, thandle);
-}
-
-// Called to initialize a new m (including the bootstrap m).
-void
-runtime·minit(void)
-{
-}
-
-void
-runtime·gettime(int64 *sec, int32 *usec)
-{
-	int64 count;
-
-	runtime·stdcall(runtime·QueryPerformanceCounter, 1, &count);
-	*sec = count / timerfreq;
-	count %= timerfreq;
-	*usec = count*1000000 / timerfreq;
-}
-
-// Calling stdcall on os stack.
-#pragma textflag 7
-void *
-runtime·stdcall(void *fn, int32 count, ...)
-{
-	WinCall c;
-
-	c.fn = fn;
-	c.n = count;
-	c.args = (uintptr*)&count + 1;
-	runtime·asmcgocall(runtime·asmstdcall, &c);
-	return (void*)c.r1;
-}
-
-uint32
-runtime·issigpanic(uint32 code)
-{
-	switch(code) {
-	case EXCEPTION_ACCESS_VIOLATION:
-	case EXCEPTION_INT_DIVIDE_BY_ZERO:
-	case EXCEPTION_INT_OVERFLOW:
-	case EXCEPTION_FLT_DENORMAL_OPERAND:
-	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-	case EXCEPTION_FLT_INEXACT_RESULT:
-	case EXCEPTION_FLT_OVERFLOW:
-	case EXCEPTION_FLT_UNDERFLOW:
-		return 1;
-	}
-	return 0;
-}
-
-void
-runtime·sigpanic(void)
-{
-	switch(g->sig) {
-	case EXCEPTION_ACCESS_VIOLATION:
-		if(g->sigcode1 < 0x1000)
-			runtime·panicstring("invalid memory address or nil pointer dereference");
-		runtime·printf("unexpected fault address %p\n", g->sigcode1);
-		runtime·throw("fault");
-	case EXCEPTION_INT_DIVIDE_BY_ZERO:
-		runtime·panicstring("integer divide by zero");
-	case EXCEPTION_INT_OVERFLOW:
-		runtime·panicstring("integer overflow");
-	case EXCEPTION_FLT_DENORMAL_OPERAND:
-	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-	case EXCEPTION_FLT_INEXACT_RESULT:
-	case EXCEPTION_FLT_OVERFLOW:
-	case EXCEPTION_FLT_UNDERFLOW:
-		runtime·panicstring("floating point error");
-	}
-	runtime·throw("fault");
-}
-
-String
-runtime·signame(int32 sig)
-{
-	int8 *s;
-
-	switch(sig) {
-	case SIGINT:
-		s = "SIGINT: interrupt";
-		break;
-	default:
-		return runtime·emptystring;
-	}
-	return runtime·gostringnocopy((byte*)s);
-}
-
-uint32
-runtime·ctrlhandler1(uint32 type)
-{
-	int32 s;
-
-	switch(type) {
-	case CTRL_C_EVENT:
-	case CTRL_BREAK_EVENT:
-		s = SIGINT;
-		break;
-	default:
-		return 0;
-	}
-
-	if(runtime·sigsend(s))
-		return 1;
-	runtime·exit(2);	// SIGINT, SIGTERM, etc
-	return 0;
-}
-
-extern void runtime·dosigprof(Context *r, G *gp);
-extern void runtime·profileloop(void);
-static void *profiletimer;
-
-static void
-profilem(M *mp)
-{
-	extern M runtime·m0;
-	extern uint32 runtime·tls0[];
-	byte rbuf[sizeof(Context)+15];
-	Context *r;
-	void *tls;
-	G *gp;
-
-	tls = mp->tls;
-	if(mp == &runtime·m0)
-		tls = runtime·tls0;
-	gp = *(G**)tls;
-
-	if(gp != nil && gp != mp->g0 && gp->status != Gsyscall) {
-		// align Context to 16 bytes
-		r = (Context*)((uintptr)(&rbuf[15]) & ~15);
-		r->ContextFlags = CONTEXT_CONTROL;
-		runtime·stdcall(runtime·GetThreadContext, 2, mp->thread, r);
-		runtime·dosigprof(r, gp);
-	}
-}
-
-void
-runtime·profileloop1(void)
-{
-	M *mp, *allm;
-	void *thread;
-
-	runtime·stdcall(runtime·SetThreadPriority, 2,
-		(uintptr)-2, (uintptr)THREAD_PRIORITY_HIGHEST);
-
-	for(;;) {
-		runtime·stdcall(runtime·WaitForSingleObject, 2, profiletimer, (uintptr)-1);
-		allm = runtime·atomicloadp(&runtime·allm);
-		for(mp = allm; mp != nil; mp = mp->alllink) {
-			thread = runtime·atomicloadp(&mp->thread);
-			if(thread == nil)
-				continue;
-			runtime·stdcall(runtime·SuspendThread, 1, thread);
-			if(mp->profilehz != 0)
-				profilem(mp);
-			runtime·stdcall(runtime·ResumeThread, 1, thread);
-		}
-	}
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-	static Lock lock;
-	void *timer, *thread;
-	int32 ms;
-	int64 due;
-
-	runtime·lock(&lock);
-	if(profiletimer == nil) {
-		timer = runtime·stdcall(runtime·CreateWaitableTimer, 3, nil, nil, nil);
-		runtime·atomicstorep(&profiletimer, timer);
-		thread = runtime·stdcall(runtime·CreateThread, 6,
-			nil, nil, runtime·profileloop, nil, nil, nil);
-		runtime·stdcall(runtime·CloseHandle, 1, thread);
-	}
-	runtime·unlock(&lock);
-
-	ms = 0;
-	due = 1LL<<63;
-	if(hz > 0) {
-		ms = 1000 / hz;
-		if(ms == 0)
-			ms = 1;
-		due = ms * -10000;
-	}
-	runtime·stdcall(runtime·SetWaitableTimer, 6,
-		profiletimer, &due, (uintptr)ms, nil, nil, nil);
-	runtime·atomicstore((uint32*)&m->profilehz, hz);
-}
-
-void
-os·sigpipe(void)
-{
-	runtime·throw("too many writes on closed pipe");
-}
diff --git a/src/pkg/scanner/Makefile b/src/pkg/scanner/Makefile
deleted file mode 100644
index db47525..0000000
--- a/src/pkg/scanner/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=scanner
-GOFILES=\
-	scanner.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/scanner/scanner.go b/src/pkg/scanner/scanner.go
deleted file mode 100644
index 8fbcb9c..0000000
--- a/src/pkg/scanner/scanner.go
+++ /dev/null
@@ -1,660 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package scanner provides a scanner and tokenizer for UTF-8-encoded text.
-// It takes an io.Reader providing the source, which then can be tokenized
-// through repeated calls to the Scan function.  For compatibility with
-// existing tools, the NUL character is not allowed (implementation
-// restriction).
-//
-// By default, a Scanner skips white space and Go comments and recognizes all
-// literals as defined by the Go language specification.  It may be
-// customized to recognize only a subset of those literals and to recognize
-// different white space characters.
-//
-// Basic usage pattern:
-//
-//	var s scanner.Scanner
-//	s.Init(src)
-//	tok := s.Scan()
-//	for tok != scanner.EOF {
-//		// do something with tok
-//		tok = s.Scan()
-//	}
-//
-package scanner
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"unicode"
-	"utf8"
-)
-
-// TODO(gri): Consider changing this to use the new (token) Position package.
-
-// A source position is represented by a Position value.
-// A position is valid if Line > 0.
-type Position struct {
-	Filename string // filename, if any
-	Offset   int    // byte offset, starting at 0
-	Line     int    // line number, starting at 1
-	Column   int    // column number, starting at 1 (character count per line)
-}
-
-// IsValid returns true if the position is valid.
-func (pos *Position) IsValid() bool { return pos.Line > 0 }
-
-func (pos Position) String() string {
-	s := pos.Filename
-	if pos.IsValid() {
-		if s != "" {
-			s += ":"
-		}
-		s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
-	}
-	if s == "" {
-		s = "???"
-	}
-	return s
-}
-
-// Predefined mode bits to control recognition of tokens. For instance,
-// to configure a Scanner such that it only recognizes (Go) identifiers,
-// integers, and skips comments, set the Scanner's Mode field to:
-//
-//	ScanIdents | ScanInts | SkipComments
-//
-const (
-	ScanIdents     = 1 << -Ident
-	ScanInts       = 1 << -Int
-	ScanFloats     = 1 << -Float // includes Ints
-	ScanChars      = 1 << -Char
-	ScanStrings    = 1 << -String
-	ScanRawStrings = 1 << -RawString
-	ScanComments   = 1 << -Comment
-	SkipComments   = 1 << -skipComment // if set with ScanComments, comments become white space
-	GoTokens       = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
-)
-
-// The result of Scan is one of the following tokens or a Unicode character.
-const (
-	EOF = -(iota + 1)
-	Ident
-	Int
-	Float
-	Char
-	String
-	RawString
-	Comment
-	skipComment
-)
-
-var tokenString = map[int]string{
-	EOF:       "EOF",
-	Ident:     "Ident",
-	Int:       "Int",
-	Float:     "Float",
-	Char:      "Char",
-	String:    "String",
-	RawString: "RawString",
-	Comment:   "Comment",
-}
-
-// TokenString returns a (visible) string for a token or Unicode character.
-func TokenString(tok int) string {
-	if s, found := tokenString[tok]; found {
-		return s
-	}
-	return fmt.Sprintf("%q", string(tok))
-}
-
-// GoWhitespace is the default value for the Scanner's Whitespace field.
-// Its value selects Go's white space characters.
-const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '
-
-const bufLen = 1024 // at least utf8.UTFMax
-
-// A Scanner implements reading of Unicode characters and tokens from an io.Reader.
-type Scanner struct {
-	// Input
-	src io.Reader
-
-	// Source buffer
-	srcBuf [bufLen + 1]byte // +1 for sentinel for common case of s.next()
-	srcPos int              // reading position (srcBuf index)
-	srcEnd int              // source end (srcBuf index)
-
-	// Source position
-	srcBufOffset int // byte offset of srcBuf[0] in source
-	line         int // line count
-	column       int // character count
-	lastLineLen  int // length of last line in characters (for correct column reporting)
-	lastCharLen  int // length of last character in bytes
-
-	// Token text buffer
-	// Typically, token text is stored completely in srcBuf, but in general
-	// the token text's head may be buffered in tokBuf while the token text's
-	// tail is stored in srcBuf.
-	tokBuf bytes.Buffer // token text head that is not in srcBuf anymore
-	tokPos int          // token text tail position (srcBuf index); valid if >= 0
-	tokEnd int          // token text tail end (srcBuf index)
-
-	// One character look-ahead
-	ch int // character before current srcPos
-
-	// Error is called for each error encountered. If no Error
-	// function is set, the error is reported to os.Stderr.
-	Error func(s *Scanner, msg string)
-
-	// ErrorCount is incremented by one for each error encountered.
-	ErrorCount int
-
-	// The Mode field controls which tokens are recognized. For instance,
-	// to recognize Ints, set the ScanInts bit in Mode. The field may be
-	// changed at any time.
-	Mode uint
-
-	// The Whitespace field controls which characters are recognized
-	// as white space. To recognize a character ch <= ' ' as white space,
-	// set the ch'th bit in Whitespace (the Scanner's behavior is undefined
-	// for values ch > ' '). The field may be changed at any time.
-	Whitespace uint64
-
-	// Current token position. The Offset, Line, and Column fields
-	// are set by Scan(); the Filename field is left untouched by the
-	// Scanner.
-	Position
-}
-
-// Init initializes a Scanner with a new source and returns s.
-// Error is set to nil, ErrorCount is set to 0, Mode is set to GoTokens,
-// and Whitespace is set to GoWhitespace.
-func (s *Scanner) Init(src io.Reader) *Scanner {
-	s.src = src
-
-	// initialize source buffer
-	// (the first call to next() will fill it by calling src.Read)
-	s.srcBuf[0] = utf8.RuneSelf // sentinel
-	s.srcPos = 0
-	s.srcEnd = 0
-
-	// initialize source position
-	s.srcBufOffset = 0
-	s.line = 1
-	s.column = 0
-	s.lastLineLen = 0
-	s.lastCharLen = 0
-
-	// initialize token text buffer
-	// (required for first call to next()).
-	s.tokPos = -1
-
-	// initialize one character look-ahead
-	s.ch = -1 // no char read yet
-
-	// initialize public fields
-	s.Error = nil
-	s.ErrorCount = 0
-	s.Mode = GoTokens
-	s.Whitespace = GoWhitespace
-
-	return s
-}
-
-// TODO(gri): The code for next() and the internal scanner state could benefit
-//            from a rethink. While next() is optimized for the common ASCII
-//            case, the "corrections" needed for proper position tracking undo
-//            some of the attempts for fast-path optimization.
-
-// next reads and returns the next Unicode character. It is designed such
-// that only a minimal amount of work needs to be done in the common ASCII
-// case (one test to check for both ASCII and end-of-buffer, and one test
-// to check for newlines).
-func (s *Scanner) next() int {
-	ch, width := int(s.srcBuf[s.srcPos]), 1
-
-	if ch >= utf8.RuneSelf {
-		// uncommon case: not ASCII or not enough bytes
-		for s.srcPos+utf8.UTFMax > s.srcEnd && !utf8.FullRune(s.srcBuf[s.srcPos:s.srcEnd]) {
-			// not enough bytes: read some more, but first
-			// save away token text if any
-			if s.tokPos >= 0 {
-				s.tokBuf.Write(s.srcBuf[s.tokPos:s.srcPos])
-				s.tokPos = 0
-				// s.tokEnd is set by Scan()
-			}
-			// move unread bytes to beginning of buffer
-			copy(s.srcBuf[0:], s.srcBuf[s.srcPos:s.srcEnd])
-			s.srcBufOffset += s.srcPos
-			// read more bytes
-			// (an io.Reader must return os.EOF when it reaches
-			// the end of what it is reading - simply returning
-			// n == 0 will make this loop retry forever; but the
-			// error is in the reader implementation in that case)
-			i := s.srcEnd - s.srcPos
-			n, err := s.src.Read(s.srcBuf[i:bufLen])
-			s.srcPos = 0
-			s.srcEnd = i + n
-			s.srcBuf[s.srcEnd] = utf8.RuneSelf // sentinel
-			if err != nil {
-				if s.srcEnd == 0 {
-					if s.lastCharLen > 0 {
-						// previous character was not EOF
-						s.column++
-					}
-					s.lastCharLen = 0
-					return EOF
-				}
-				if err != os.EOF {
-					s.error(err.String())
-				}
-				// If err == EOF, we won't be getting more
-				// bytes; break to avoid infinite loop. If
-				// err is something else, we don't know if
-				// we can get more bytes; thus also break.
-				break
-			}
-		}
-		// at least one byte
-		ch = int(s.srcBuf[s.srcPos])
-		if ch >= utf8.RuneSelf {
-			// uncommon case: not ASCII
-			ch, width = utf8.DecodeRune(s.srcBuf[s.srcPos:s.srcEnd])
-			if ch == utf8.RuneError && width == 1 {
-				// advance for correct error position
-				s.srcPos += width
-				s.lastCharLen = width
-				s.column++
-				s.error("illegal UTF-8 encoding")
-				return ch
-			}
-		}
-	}
-
-	// advance
-	s.srcPos += width
-	s.lastCharLen = width
-	s.column++
-
-	// special situations
-	switch ch {
-	case 0:
-		// implementation restriction for compatibility with other tools
-		s.error("illegal character NUL")
-	case '\n':
-		s.line++
-		s.lastLineLen = s.column
-		s.column = 0
-	}
-
-	return ch
-}
-
-// Next reads and returns the next Unicode character.
-// It returns EOF at the end of the source. It reports
-// a read error by calling s.Error, if not nil; otherwise
-// it prints an error message to os.Stderr. Next does not
-// update the Scanner's Position field; use Pos() to
-// get the current position.
-func (s *Scanner) Next() int {
-	s.tokPos = -1 // don't collect token text
-	ch := s.Peek()
-	s.ch = s.next()
-	return ch
-}
-
-// Peek returns the next Unicode character in the source without advancing
-// the scanner. It returns EOF if the scanner's position is at the last
-// character of the source.
-func (s *Scanner) Peek() int {
-	if s.ch < 0 {
-		s.ch = s.next()
-	}
-	return s.ch
-}
-
-func (s *Scanner) error(msg string) {
-	s.ErrorCount++
-	if s.Error != nil {
-		s.Error(s, msg)
-		return
-	}
-	fmt.Fprintf(os.Stderr, "%s: %s\n", s.Position, msg)
-}
-
-func (s *Scanner) scanIdentifier() int {
-	ch := s.next() // read character after first '_' or letter
-	for ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) {
-		ch = s.next()
-	}
-	return ch
-}
-
-func digitVal(ch int) int {
-	switch {
-	case '0' <= ch && ch <= '9':
-		return ch - '0'
-	case 'a' <= ch && ch <= 'f':
-		return ch - 'a' + 10
-	case 'A' <= ch && ch <= 'F':
-		return ch - 'A' + 10
-	}
-	return 16 // larger than any legal digit val
-}
-
-func isDecimal(ch int) bool { return '0' <= ch && ch <= '9' }
-
-func (s *Scanner) scanMantissa(ch int) int {
-	for isDecimal(ch) {
-		ch = s.next()
-	}
-	return ch
-}
-
-func (s *Scanner) scanFraction(ch int) int {
-	if ch == '.' {
-		ch = s.scanMantissa(s.next())
-	}
-	return ch
-}
-
-func (s *Scanner) scanExponent(ch int) int {
-	if ch == 'e' || ch == 'E' {
-		ch = s.next()
-		if ch == '-' || ch == '+' {
-			ch = s.next()
-		}
-		ch = s.scanMantissa(ch)
-	}
-	return ch
-}
-
-func (s *Scanner) scanNumber(ch int) (int, int) {
-	// isDecimal(ch)
-	if ch == '0' {
-		// int or float
-		ch = s.next()
-		if ch == 'x' || ch == 'X' {
-			// hexadecimal int
-			ch = s.next()
-			for digitVal(ch) < 16 {
-				ch = s.next()
-			}
-		} else {
-			// octal int or float
-			seenDecimalDigit := false
-			for isDecimal(ch) {
-				if ch > '7' {
-					seenDecimalDigit = true
-				}
-				ch = s.next()
-			}
-			if s.Mode&ScanFloats != 0 && (ch == '.' || ch == 'e' || ch == 'E') {
-				// float
-				ch = s.scanFraction(ch)
-				ch = s.scanExponent(ch)
-				return Float, ch
-			}
-			// octal int
-			if seenDecimalDigit {
-				s.error("illegal octal number")
-			}
-		}
-		return Int, ch
-	}
-	// decimal int or float
-	ch = s.scanMantissa(ch)
-	if s.Mode&ScanFloats != 0 && (ch == '.' || ch == 'e' || ch == 'E') {
-		// float
-		ch = s.scanFraction(ch)
-		ch = s.scanExponent(ch)
-		return Float, ch
-	}
-	return Int, ch
-}
-
-func (s *Scanner) scanDigits(ch, base, n int) int {
-	for n > 0 && digitVal(ch) < base {
-		ch = s.next()
-		n--
-	}
-	if n > 0 {
-		s.error("illegal char escape")
-	}
-	return ch
-}
-
-func (s *Scanner) scanEscape(quote int) int {
-	ch := s.next() // read character after '/'
-	switch ch {
-	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
-		// nothing to do
-		ch = s.next()
-	case '0', '1', '2', '3', '4', '5', '6', '7':
-		ch = s.scanDigits(ch, 8, 3)
-	case 'x':
-		ch = s.scanDigits(s.next(), 16, 2)
-	case 'u':
-		ch = s.scanDigits(s.next(), 16, 4)
-	case 'U':
-		ch = s.scanDigits(s.next(), 16, 8)
-	default:
-		s.error("illegal char escape")
-	}
-	return ch
-}
-
-func (s *Scanner) scanString(quote int) (n int) {
-	ch := s.next() // read character after quote
-	for ch != quote {
-		if ch == '\n' || ch < 0 {
-			s.error("literal not terminated")
-			return
-		}
-		if ch == '\\' {
-			ch = s.scanEscape(quote)
-		} else {
-			ch = s.next()
-		}
-		n++
-	}
-	return
-}
-
-func (s *Scanner) scanRawString() {
-	ch := s.next() // read character after '`'
-	for ch != '`' {
-		if ch < 0 {
-			s.error("literal not terminated")
-			return
-		}
-		ch = s.next()
-	}
-}
-
-func (s *Scanner) scanChar() {
-	if s.scanString('\'') != 1 {
-		s.error("illegal char literal")
-	}
-}
-
-func (s *Scanner) scanComment(ch int) int {
-	// ch == '/' || ch == '*'
-	if ch == '/' {
-		// line comment
-		ch = s.next() // read character after "//"
-		for ch != '\n' && ch >= 0 {
-			ch = s.next()
-		}
-		return ch
-	}
-
-	// general comment
-	ch = s.next() // read character after "/*"
-	for {
-		if ch < 0 {
-			s.error("comment not terminated")
-			break
-		}
-		ch0 := ch
-		ch = s.next()
-		if ch0 == '*' && ch == '/' {
-			ch = s.next()
-			break
-		}
-	}
-	return ch
-}
-
-// Scan reads the next token or Unicode character from source and returns it.
-// It only recognizes tokens t for which the respective Mode bit (1<<-t) is set.
-// It returns EOF at the end of the source. It reports scanner errors (read and
-// token errors) by calling s.Error, if not nil; otherwise it prints an error
-// message to os.Stderr.
-func (s *Scanner) Scan() int {
-	ch := s.Peek()
-
-	// reset token text position
-	s.tokPos = -1
-
-redo:
-	// skip white space
-	for s.Whitespace&(1<<uint(ch)) != 0 {
-		ch = s.next()
-	}
-
-	// start collecting token text
-	s.tokBuf.Reset()
-	s.tokPos = s.srcPos - s.lastCharLen
-
-	// set token position
-	// (this is a slightly optimized version of the code in Pos())
-	s.Offset = s.srcBufOffset + s.tokPos
-	if s.column > 0 {
-		// common case: last character was not a '\n'
-		s.Line = s.line
-		s.Column = s.column
-	} else {
-		// last character was a '\n'
-		// (we cannot be at the beginning of the source
-		// since we have called next() at least once)
-		s.Line = s.line - 1
-		s.Column = s.lastLineLen
-	}
-
-	// determine token value
-	tok := ch
-	switch {
-	case unicode.IsLetter(ch) || ch == '_':
-		if s.Mode&ScanIdents != 0 {
-			tok = Ident
-			ch = s.scanIdentifier()
-		} else {
-			ch = s.next()
-		}
-	case isDecimal(ch):
-		if s.Mode&(ScanInts|ScanFloats) != 0 {
-			tok, ch = s.scanNumber(ch)
-		} else {
-			ch = s.next()
-		}
-	default:
-		switch ch {
-		case '"':
-			if s.Mode&ScanStrings != 0 {
-				s.scanString('"')
-				tok = String
-			}
-			ch = s.next()
-		case '\'':
-			if s.Mode&ScanChars != 0 {
-				s.scanChar()
-				tok = Char
-			}
-			ch = s.next()
-		case '.':
-			ch = s.next()
-			if isDecimal(ch) && s.Mode&ScanFloats != 0 {
-				tok = Float
-				ch = s.scanMantissa(ch)
-				ch = s.scanExponent(ch)
-			}
-		case '/':
-			ch = s.next()
-			if (ch == '/' || ch == '*') && s.Mode&ScanComments != 0 {
-				if s.Mode&SkipComments != 0 {
-					s.tokPos = -1 // don't collect token text
-					ch = s.scanComment(ch)
-					goto redo
-				}
-				ch = s.scanComment(ch)
-				tok = Comment
-			}
-		case '`':
-			if s.Mode&ScanRawStrings != 0 {
-				s.scanRawString()
-				tok = String
-			}
-			ch = s.next()
-		default:
-			ch = s.next()
-		}
-	}
-
-	// end of token text
-	s.tokEnd = s.srcPos - s.lastCharLen
-
-	s.ch = ch
-	return tok
-}
-
-// Pos returns the position of the character immediately after
-// the character or token returned by the last call to Next or Scan.
-func (s *Scanner) Pos() (pos Position) {
-	pos.Filename = s.Filename
-	pos.Offset = s.srcBufOffset + s.srcPos - s.lastCharLen
-	switch {
-	case s.column > 0:
-		// common case: last character was not a '\n'
-		pos.Line = s.line
-		pos.Column = s.column
-	case s.lastLineLen > 0:
-		// last character was a '\n'
-		pos.Line = s.line - 1
-		pos.Column = s.lastLineLen
-	default:
-		// at the beginning of the source
-		pos.Line = 1
-		pos.Column = 1
-	}
-	return
-}
-
-// TokenText returns the string corresponding to the most recently scanned token.
-// Valid after calling Scan().
-func (s *Scanner) TokenText() string {
-	if s.tokPos < 0 {
-		// no token text
-		return ""
-	}
-
-	if s.tokEnd < 0 {
-		// if EOF was reached, s.tokEnd is set to -1 (s.srcPos == 0)
-		s.tokEnd = s.tokPos
-	}
-
-	if s.tokBuf.Len() == 0 {
-		// common case: the entire token text is still in srcBuf
-		return string(s.srcBuf[s.tokPos:s.tokEnd])
-	}
-
-	// part of the token text was saved in tokBuf: save the rest in
-	// tokBuf as well and return its content
-	s.tokBuf.Write(s.srcBuf[s.tokPos:s.tokEnd])
-	s.tokPos = s.tokEnd // ensure idempotency of TokenText() call
-	return s.tokBuf.String()
-}
diff --git a/src/pkg/scanner/scanner_test.go b/src/pkg/scanner/scanner_test.go
deleted file mode 100644
index 8403d61..0000000
--- a/src/pkg/scanner/scanner_test.go
+++ /dev/null
@@ -1,566 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package scanner
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"strings"
-	"testing"
-	"utf8"
-)
-
-// A StringReader delivers its data one string segment at a time via Read.
-type StringReader struct {
-	data []string
-	step int
-}
-
-func (r *StringReader) Read(p []byte) (n int, err os.Error) {
-	if r.step < len(r.data) {
-		s := r.data[r.step]
-		n = copy(p, s)
-		r.step++
-	} else {
-		err = os.EOF
-	}
-	return
-}
-
-func readRuneSegments(t *testing.T, segments []string) {
-	got := ""
-	want := strings.Join(segments, "")
-	s := new(Scanner).Init(&StringReader{data: segments})
-	for {
-		ch := s.Next()
-		if ch == EOF {
-			break
-		}
-		got += string(ch)
-	}
-	if got != want {
-		t.Errorf("segments=%v got=%s want=%s", segments, got, want)
-	}
-}
-
-var segmentList = [][]string{
-	{},
-	{""},
-	{"日", "本語"},
-	{"\u65e5", "\u672c", "\u8a9e"},
-	{"\U000065e5", " ", "\U0000672c", "\U00008a9e"},
-	{"\xe6", "\x97\xa5\xe6", "\x9c\xac\xe8\xaa\x9e"},
-	{"Hello", ", ", "World", "!"},
-	{"Hello", ", ", "", "World", "!"},
-}
-
-func TestNext(t *testing.T) {
-	for _, s := range segmentList {
-		readRuneSegments(t, s)
-	}
-}
-
-type token struct {
-	tok  int
-	text string
-}
-
-var f100 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-
-var tokenList = []token{
-	{Comment, "// line comments"},
-	{Comment, "//"},
-	{Comment, "////"},
-	{Comment, "// comment"},
-	{Comment, "// /* comment */"},
-	{Comment, "// // comment //"},
-	{Comment, "//" + f100},
-
-	{Comment, "// general comments"},
-	{Comment, "/**/"},
-	{Comment, "/***/"},
-	{Comment, "/* comment */"},
-	{Comment, "/* // comment */"},
-	{Comment, "/* /* comment */"},
-	{Comment, "/*\n comment\n*/"},
-	{Comment, "/*" + f100 + "*/"},
-
-	{Comment, "// identifiers"},
-	{Ident, "a"},
-	{Ident, "a0"},
-	{Ident, "foobar"},
-	{Ident, "abc123"},
-	{Ident, "LGTM"},
-	{Ident, "_"},
-	{Ident, "_abc123"},
-	{Ident, "abc123_"},
-	{Ident, "_abc_123_"},
-	{Ident, "_äöü"},
-	{Ident, "_本"},
-	// TODO for unknown reasons these fail when checking the literals
-	/*
-		token{Ident, "äöü"},
-		token{Ident, "本"},
-	*/
-	{Ident, "aÛ°Û±Û¸"},
-	{Ident, "foo६४"},
-	{Ident, "bar9876"},
-	{Ident, f100},
-
-	{Comment, "// decimal ints"},
-	{Int, "0"},
-	{Int, "1"},
-	{Int, "9"},
-	{Int, "42"},
-	{Int, "1234567890"},
-
-	{Comment, "// octal ints"},
-	{Int, "00"},
-	{Int, "01"},
-	{Int, "07"},
-	{Int, "042"},
-	{Int, "01234567"},
-
-	{Comment, "// hexadecimal ints"},
-	{Int, "0x0"},
-	{Int, "0x1"},
-	{Int, "0xf"},
-	{Int, "0x42"},
-	{Int, "0x123456789abcDEF"},
-	{Int, "0x" + f100},
-	{Int, "0X0"},
-	{Int, "0X1"},
-	{Int, "0XF"},
-	{Int, "0X42"},
-	{Int, "0X123456789abcDEF"},
-	{Int, "0X" + f100},
-
-	{Comment, "// floats"},
-	{Float, "0."},
-	{Float, "1."},
-	{Float, "42."},
-	{Float, "01234567890."},
-	{Float, ".0"},
-	{Float, ".1"},
-	{Float, ".42"},
-	{Float, ".0123456789"},
-	{Float, "0.0"},
-	{Float, "1.0"},
-	{Float, "42.0"},
-	{Float, "01234567890.0"},
-	{Float, "0e0"},
-	{Float, "1e0"},
-	{Float, "42e0"},
-	{Float, "01234567890e0"},
-	{Float, "0E0"},
-	{Float, "1E0"},
-	{Float, "42E0"},
-	{Float, "01234567890E0"},
-	{Float, "0e+10"},
-	{Float, "1e-10"},
-	{Float, "42e+10"},
-	{Float, "01234567890e-10"},
-	{Float, "0E+10"},
-	{Float, "1E-10"},
-	{Float, "42E+10"},
-	{Float, "01234567890E-10"},
-
-	{Comment, "// chars"},
-	{Char, `' '`},
-	{Char, `'a'`},
-	{Char, `'本'`},
-	{Char, `'\a'`},
-	{Char, `'\b'`},
-	{Char, `'\f'`},
-	{Char, `'\n'`},
-	{Char, `'\r'`},
-	{Char, `'\t'`},
-	{Char, `'\v'`},
-	{Char, `'\''`},
-	{Char, `'\000'`},
-	{Char, `'\777'`},
-	{Char, `'\x00'`},
-	{Char, `'\xff'`},
-	{Char, `'\u0000'`},
-	{Char, `'\ufA16'`},
-	{Char, `'\U00000000'`},
-	{Char, `'\U0000ffAB'`},
-
-	{Comment, "// strings"},
-	{String, `" "`},
-	{String, `"a"`},
-	{String, `"本"`},
-	{String, `"\a"`},
-	{String, `"\b"`},
-	{String, `"\f"`},
-	{String, `"\n"`},
-	{String, `"\r"`},
-	{String, `"\t"`},
-	{String, `"\v"`},
-	{String, `"\""`},
-	{String, `"\000"`},
-	{String, `"\777"`},
-	{String, `"\x00"`},
-	{String, `"\xff"`},
-	{String, `"\u0000"`},
-	{String, `"\ufA16"`},
-	{String, `"\U00000000"`},
-	{String, `"\U0000ffAB"`},
-	{String, `"` + f100 + `"`},
-
-	{Comment, "// raw strings"},
-	{String, "``"},
-	{String, "`\\`"},
-	{String, "`" + "\n\n/* foobar */\n\n" + "`"},
-	{String, "`" + f100 + "`"},
-
-	{Comment, "// individual characters"},
-	// NUL character is not allowed
-	{'\x01', "\x01"},
-	{' ' - 1, string(' ' - 1)},
-	{'+', "+"},
-	{'/', "/"},
-	{'.', "."},
-	{'~', "~"},
-	{'(', "("},
-}
-
-func makeSource(pattern string) *bytes.Buffer {
-	var buf bytes.Buffer
-	for _, k := range tokenList {
-		fmt.Fprintf(&buf, pattern, k.text)
-	}
-	return &buf
-}
-
-func checkTok(t *testing.T, s *Scanner, line, got, want int, text string) {
-	if got != want {
-		t.Fatalf("tok = %s, want %s for %q", TokenString(got), TokenString(want), text)
-	}
-	if s.Line != line {
-		t.Errorf("line = %d, want %d for %q", s.Line, line, text)
-	}
-	stext := s.TokenText()
-	if stext != text {
-		t.Errorf("text = %q, want %q", stext, text)
-	} else {
-		// check idempotency of TokenText() call
-		stext = s.TokenText()
-		if stext != text {
-			t.Errorf("text = %q, want %q (idempotency check)", stext, text)
-		}
-	}
-}
-
-func countNewlines(s string) int {
-	n := 0
-	for _, ch := range s {
-		if ch == '\n' {
-			n++
-		}
-	}
-	return n
-}
-
-func testScan(t *testing.T, mode uint) {
-	s := new(Scanner).Init(makeSource(" \t%s\n"))
-	s.Mode = mode
-	tok := s.Scan()
-	line := 1
-	for _, k := range tokenList {
-		if mode&SkipComments == 0 || k.tok != Comment {
-			checkTok(t, s, line, tok, k.tok, k.text)
-			tok = s.Scan()
-		}
-		line += countNewlines(k.text) + 1 // each token is on a new line
-	}
-	checkTok(t, s, line, tok, EOF, "")
-}
-
-func TestScan(t *testing.T) {
-	testScan(t, GoTokens)
-	testScan(t, GoTokens&^SkipComments)
-}
-
-func TestPosition(t *testing.T) {
-	src := makeSource("\t\t\t\t%s\n")
-	s := new(Scanner).Init(src)
-	s.Mode = GoTokens &^ SkipComments
-	s.Scan()
-	pos := Position{"", 4, 1, 5}
-	for _, k := range tokenList {
-		if s.Offset != pos.Offset {
-			t.Errorf("offset = %d, want %d for %q", s.Offset, pos.Offset, k.text)
-		}
-		if s.Line != pos.Line {
-			t.Errorf("line = %d, want %d for %q", s.Line, pos.Line, k.text)
-		}
-		if s.Column != pos.Column {
-			t.Errorf("column = %d, want %d for %q", s.Column, pos.Column, k.text)
-		}
-		pos.Offset += 4 + len(k.text) + 1     // 4 tabs + token bytes + newline
-		pos.Line += countNewlines(k.text) + 1 // each token is on a new line
-		s.Scan()
-	}
-	// make sure there were no token-internal errors reported by scanner
-	if s.ErrorCount != 0 {
-		t.Errorf("%d errors", s.ErrorCount)
-	}
-}
-
-func TestScanZeroMode(t *testing.T) {
-	src := makeSource("%s\n")
-	str := src.String()
-	s := new(Scanner).Init(src)
-	s.Mode = 0       // don't recognize any token classes
-	s.Whitespace = 0 // don't skip any whitespace
-	tok := s.Scan()
-	for i, ch := range str {
-		if tok != ch {
-			t.Fatalf("%d. tok = %s, want %s", i, TokenString(tok), TokenString(ch))
-		}
-		tok = s.Scan()
-	}
-	if tok != EOF {
-		t.Fatalf("tok = %s, want EOF", TokenString(tok))
-	}
-	if s.ErrorCount != 0 {
-		t.Errorf("%d errors", s.ErrorCount)
-	}
-}
-
-func testScanSelectedMode(t *testing.T, mode uint, class int) {
-	src := makeSource("%s\n")
-	s := new(Scanner).Init(src)
-	s.Mode = mode
-	tok := s.Scan()
-	for tok != EOF {
-		if tok < 0 && tok != class {
-			t.Fatalf("tok = %s, want %s", TokenString(tok), TokenString(class))
-		}
-		tok = s.Scan()
-	}
-	if s.ErrorCount != 0 {
-		t.Errorf("%d errors", s.ErrorCount)
-	}
-}
-
-func TestScanSelectedMask(t *testing.T) {
-	testScanSelectedMode(t, 0, 0)
-	testScanSelectedMode(t, ScanIdents, Ident)
-	// Don't test ScanInts and ScanNumbers since some parts of
-	// the floats in the source look like (illegal) octal ints
-	// and ScanNumbers may return either Int or Float.
-	testScanSelectedMode(t, ScanChars, Char)
-	testScanSelectedMode(t, ScanStrings, String)
-	testScanSelectedMode(t, SkipComments, 0)
-	testScanSelectedMode(t, ScanComments, Comment)
-}
-
-func TestScanNext(t *testing.T) {
-	s := new(Scanner).Init(bytes.NewBufferString("if a == bcd /* comment */ {\n\ta += c\n} // line comment ending in eof"))
-	checkTok(t, s, 1, s.Scan(), Ident, "if")
-	checkTok(t, s, 1, s.Scan(), Ident, "a")
-	checkTok(t, s, 1, s.Scan(), '=', "=")
-	checkTok(t, s, 1, s.Next(), '=', "")
-	checkTok(t, s, 1, s.Next(), ' ', "")
-	checkTok(t, s, 1, s.Next(), 'b', "")
-	checkTok(t, s, 1, s.Scan(), Ident, "cd")
-	checkTok(t, s, 1, s.Scan(), '{', "{")
-	checkTok(t, s, 2, s.Scan(), Ident, "a")
-	checkTok(t, s, 2, s.Scan(), '+', "+")
-	checkTok(t, s, 2, s.Next(), '=', "")
-	checkTok(t, s, 2, s.Scan(), Ident, "c")
-	checkTok(t, s, 3, s.Scan(), '}', "}")
-	checkTok(t, s, 3, s.Scan(), -1, "")
-	if s.ErrorCount != 0 {
-		t.Errorf("%d errors", s.ErrorCount)
-	}
-}
-
-func TestScanWhitespace(t *testing.T) {
-	var buf bytes.Buffer
-	var ws uint64
-	// start at 1, NUL character is not allowed
-	for ch := byte(1); ch < ' '; ch++ {
-		buf.WriteByte(ch)
-		ws |= 1 << ch
-	}
-	const orig = 'x'
-	buf.WriteByte(orig)
-
-	s := new(Scanner).Init(&buf)
-	s.Mode = 0
-	s.Whitespace = ws
-	tok := s.Scan()
-	if tok != orig {
-		t.Errorf("tok = %s, want %s", TokenString(tok), TokenString(orig))
-	}
-}
-
-func testError(t *testing.T, src, pos, msg string, tok int) {
-	s := new(Scanner).Init(bytes.NewBufferString(src))
-	errorCalled := false
-	s.Error = func(s *Scanner, m string) {
-		if !errorCalled {
-			// only look at first error
-			if p := s.Pos().String(); p != pos {
-				t.Errorf("pos = %q, want %q for %q", p, pos, src)
-			}
-			if m != msg {
-				t.Errorf("msg = %q, want %q for %q", m, msg, src)
-			}
-			errorCalled = true
-		}
-	}
-	tk := s.Scan()
-	if tk != tok {
-		t.Errorf("tok = %s, want %s for %q", TokenString(tk), TokenString(tok), src)
-	}
-	if !errorCalled {
-		t.Errorf("error handler not called for %q", src)
-	}
-	if s.ErrorCount == 0 {
-		t.Errorf("count = %d, want > 0 for %q", s.ErrorCount, src)
-	}
-}
-
-func TestError(t *testing.T) {
-	testError(t, "\x00", "1:1", "illegal character NUL", 0)
-	testError(t, "\x80", "1:1", "illegal UTF-8 encoding", utf8.RuneError)
-	testError(t, "\xff", "1:1", "illegal UTF-8 encoding", utf8.RuneError)
-
-	testError(t, "a\x00", "1:2", "illegal character NUL", Ident)
-	testError(t, "ab\x80", "1:3", "illegal UTF-8 encoding", Ident)
-	testError(t, "abc\xff", "1:4", "illegal UTF-8 encoding", Ident)
-
-	testError(t, `"a`+"\x00", "1:3", "illegal character NUL", String)
-	testError(t, `"ab`+"\x80", "1:4", "illegal UTF-8 encoding", String)
-	testError(t, `"abc`+"\xff", "1:5", "illegal UTF-8 encoding", String)
-
-	testError(t, "`a"+"\x00", "1:3", "illegal character NUL", String)
-	testError(t, "`ab"+"\x80", "1:4", "illegal UTF-8 encoding", String)
-	testError(t, "`abc"+"\xff", "1:5", "illegal UTF-8 encoding", String)
-
-	testError(t, `'\"'`, "1:3", "illegal char escape", Char)
-	testError(t, `"\'"`, "1:3", "illegal char escape", String)
-
-	testError(t, `01238`, "1:6", "illegal octal number", Int)
-	testError(t, `'aa'`, "1:4", "illegal char literal", Char)
-
-	testError(t, `'`, "1:2", "literal not terminated", Char)
-	testError(t, `'`+"\n", "1:2", "literal not terminated", Char)
-	testError(t, `"abc`, "1:5", "literal not terminated", String)
-	testError(t, `"abc`+"\n", "1:5", "literal not terminated", String)
-	testError(t, "`abc\n", "2:1", "literal not terminated", String)
-	testError(t, `/*/`, "1:4", "comment not terminated", EOF)
-}
-
-func checkPos(t *testing.T, got, want Position) {
-	if got.Offset != want.Offset || got.Line != want.Line || got.Column != want.Column {
-		t.Errorf("got offset, line, column = %d, %d, %d; want %d, %d, %d",
-			got.Offset, got.Line, got.Column, want.Offset, want.Line, want.Column)
-	}
-}
-
-func checkNextPos(t *testing.T, s *Scanner, offset, line, column, char int) {
-	if ch := s.Next(); ch != char {
-		t.Errorf("ch = %s, want %s", TokenString(ch), TokenString(char))
-	}
-	want := Position{Offset: offset, Line: line, Column: column}
-	checkPos(t, s.Pos(), want)
-}
-
-func checkScanPos(t *testing.T, s *Scanner, offset, line, column, char int) {
-	want := Position{Offset: offset, Line: line, Column: column}
-	checkPos(t, s.Pos(), want)
-	if ch := s.Scan(); ch != char {
-		t.Errorf("ch = %s, want %s", TokenString(ch), TokenString(char))
-		if string(ch) != s.TokenText() {
-			t.Errorf("tok = %q, want %q", s.TokenText(), string(ch))
-		}
-	}
-	checkPos(t, s.Position, want)
-}
-
-func TestPos(t *testing.T) {
-	// corner case: empty source
-	s := new(Scanner).Init(bytes.NewBufferString(""))
-	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
-	s.Peek() // peek doesn't affect the position
-	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
-
-	// corner case: source with only a newline
-	s = new(Scanner).Init(bytes.NewBufferString("\n"))
-	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
-	checkNextPos(t, s, 1, 2, 1, '\n')
-	// after EOF position doesn't change
-	for i := 10; i > 0; i-- {
-		checkScanPos(t, s, 1, 2, 1, EOF)
-	}
-	if s.ErrorCount != 0 {
-		t.Errorf("%d errors", s.ErrorCount)
-	}
-
-	// corner case: source with only a single character
-	s = new(Scanner).Init(bytes.NewBufferString("本"))
-	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
-	checkNextPos(t, s, 3, 1, 2, '本')
-	// after EOF position doesn't change
-	for i := 10; i > 0; i-- {
-		checkScanPos(t, s, 3, 1, 2, EOF)
-	}
-	if s.ErrorCount != 0 {
-		t.Errorf("%d errors", s.ErrorCount)
-	}
-
-	// positions after calling Next
-	s = new(Scanner).Init(bytes.NewBufferString("  foo६४  \n\n本語\n"))
-	checkNextPos(t, s, 1, 1, 2, ' ')
-	s.Peek() // peek doesn't affect the position
-	checkNextPos(t, s, 2, 1, 3, ' ')
-	checkNextPos(t, s, 3, 1, 4, 'f')
-	checkNextPos(t, s, 4, 1, 5, 'o')
-	checkNextPos(t, s, 5, 1, 6, 'o')
-	checkNextPos(t, s, 8, 1, 7, '६')
-	checkNextPos(t, s, 11, 1, 8, '४')
-	checkNextPos(t, s, 12, 1, 9, ' ')
-	checkNextPos(t, s, 13, 1, 10, ' ')
-	checkNextPos(t, s, 14, 2, 1, '\n')
-	checkNextPos(t, s, 15, 3, 1, '\n')
-	checkNextPos(t, s, 18, 3, 2, '本')
-	checkNextPos(t, s, 21, 3, 3, '語')
-	checkNextPos(t, s, 22, 4, 1, '\n')
-	// after EOF position doesn't change
-	for i := 10; i > 0; i-- {
-		checkScanPos(t, s, 22, 4, 1, EOF)
-	}
-	if s.ErrorCount != 0 {
-		t.Errorf("%d errors", s.ErrorCount)
-	}
-
-	// positions after calling Scan
-	s = new(Scanner).Init(bytes.NewBufferString("abc\n本語\n\nx"))
-	s.Mode = 0
-	s.Whitespace = 0
-	checkScanPos(t, s, 0, 1, 1, 'a')
-	s.Peek() // peek doesn't affect the position
-	checkScanPos(t, s, 1, 1, 2, 'b')
-	checkScanPos(t, s, 2, 1, 3, 'c')
-	checkScanPos(t, s, 3, 1, 4, '\n')
-	checkScanPos(t, s, 4, 2, 1, '本')
-	checkScanPos(t, s, 7, 2, 2, '語')
-	checkScanPos(t, s, 10, 2, 3, '\n')
-	checkScanPos(t, s, 11, 3, 1, '\n')
-	checkScanPos(t, s, 12, 4, 1, 'x')
-	// after EOF position doesn't change
-	for i := 10; i > 0; i-- {
-		checkScanPos(t, s, 13, 4, 2, EOF)
-	}
-	if s.ErrorCount != 0 {
-		t.Errorf("%d errors", s.ErrorCount)
-	}
-}
diff --git a/src/pkg/smtp/Makefile b/src/pkg/smtp/Makefile
deleted file mode 100644
index 0e7d8d5..0000000
--- a/src/pkg/smtp/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2010 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=smtp
-GOFILES=\
-	auth.go\
-	smtp.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/smtp/auth.go b/src/pkg/smtp/auth.go
deleted file mode 100644
index dd27f8e..0000000
--- a/src/pkg/smtp/auth.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2010 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 smtp
-
-import (
-	"os"
-)
-
-// Auth is implemented by an SMTP authentication mechanism.
-type Auth interface {
-	// Start begins an authentication with a server.
-	// It returns the name of the authentication protocol
-	// and optionally data to include in the initial AUTH message
-	// sent to the server. It can return proto == "" to indicate
-	// that the authentication should be skipped.
-	// If it returns a non-nil os.Error, the SMTP client aborts
-	// the authentication attempt and closes the connection.
-	Start(server *ServerInfo) (proto string, toServer []byte, err os.Error)
-
-	// Next continues the authentication. The server has just sent
-	// the fromServer data. If more is true, the server expects a
-	// response, which Next should return as toServer; otherwise
-	// Next should return toServer == nil.
-	// If Next returns a non-nil os.Error, the SMTP client aborts
-	// the authentication attempt and closes the connection.
-	Next(fromServer []byte, more bool) (toServer []byte, err os.Error)
-}
-
-// ServerInfo records information about an SMTP server.
-type ServerInfo struct {
-	Name string   // SMTP server name
-	TLS  bool     // using TLS, with valid certificate for Name
-	Auth []string // advertised authentication mechanisms
-}
-
-type plainAuth struct {
-	identity, username, password string
-	host                         string
-}
-
-// PlainAuth returns an Auth that implements the PLAIN authentication
-// mechanism as defined in RFC 4616.
-// The returned Auth uses the given username and password to authenticate
-// on TLS connections to host and act as identity. Usually identity will be
-// left blank to act as username.
-func PlainAuth(identity, username, password, host string) Auth {
-	return &plainAuth{identity, username, password, host}
-}
-
-func (a *plainAuth) Start(server *ServerInfo) (string, []byte, os.Error) {
-	if !server.TLS {
-		return "", nil, os.NewError("unencrypted connection")
-	}
-	if server.Name != a.host {
-		return "", nil, os.NewError("wrong host name")
-	}
-	resp := []byte(a.identity + "\x00" + a.username + "\x00" + a.password)
-	return "PLAIN", resp, nil
-}
-
-func (a *plainAuth) Next(fromServer []byte, more bool) ([]byte, os.Error) {
-	if more {
-		// We've already sent everything.
-		return nil, os.NewError("unexpected server challenge")
-	}
-	return nil, nil
-}
diff --git a/src/pkg/smtp/smtp.go b/src/pkg/smtp/smtp.go
deleted file mode 100644
index 2d5e862..0000000
--- a/src/pkg/smtp/smtp.go
+++ /dev/null
@@ -1,294 +0,0 @@
-// Copyright 2010 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 smtp implements the Simple Mail Transfer Protocol as defined in RFC 5321.
-// It also implements the following extensions:
-//	8BITMIME  RFC 1652
-//	AUTH      RFC 2554
-//	STARTTLS  RFC 3207
-// Additional extensions may be handled by clients.
-package smtp
-
-import (
-	"crypto/tls"
-	"encoding/base64"
-	"io"
-	"os"
-	"net"
-	"net/textproto"
-	"strings"
-)
-
-// A Client represents a client connection to an SMTP server.
-type Client struct {
-	// Text is the textproto.Conn used by the Client. It is exported to allow for
-	// clients to add extensions.
-	Text *textproto.Conn
-	// keep a reference to the connection so it can be used to create a TLS
-	// connection later
-	conn net.Conn
-	// whether the Client is using TLS
-	tls        bool
-	serverName string
-	// map of supported extensions
-	ext map[string]string
-	// supported auth mechanisms
-	auth []string
-}
-
-// Dial returns a new Client connected to an SMTP server at addr.
-func Dial(addr string) (*Client, os.Error) {
-	conn, err := net.Dial("tcp", addr)
-	if err != nil {
-		return nil, err
-	}
-	host := addr[:strings.Index(addr, ":")]
-	return NewClient(conn, host)
-}
-
-// NewClient returns a new Client using an existing connection and host as a
-// server name to be used when authenticating.
-func NewClient(conn net.Conn, host string) (*Client, os.Error) {
-	text := textproto.NewConn(conn)
-	_, msg, err := text.ReadResponse(220)
-	if err != nil {
-		text.Close()
-		return nil, err
-	}
-	c := &Client{Text: text, conn: conn, serverName: host}
-	if strings.Contains(msg, "ESMTP") {
-		err = c.ehlo()
-	} else {
-		err = c.helo()
-	}
-	return c, err
-}
-
-// cmd is a convenience function that sends a command and returns the response
-func (c *Client) cmd(expectCode int, format string, args ...interface{}) (int, string, os.Error) {
-	id, err := c.Text.Cmd(format, args...)
-	if err != nil {
-		return 0, "", err
-	}
-	c.Text.StartResponse(id)
-	defer c.Text.EndResponse(id)
-	code, msg, err := c.Text.ReadResponse(expectCode)
-	return code, msg, err
-}
-
-// helo sends the HELO greeting to the server. It should be used only when the
-// server does not support ehlo.
-func (c *Client) helo() os.Error {
-	c.ext = nil
-	_, _, err := c.cmd(250, "HELO localhost")
-	return err
-}
-
-// ehlo sends the EHLO (extended hello) greeting to the server. It
-// should be the preferred greeting for servers that support it.
-func (c *Client) ehlo() os.Error {
-	_, msg, err := c.cmd(250, "EHLO localhost")
-	if err != nil {
-		return err
-	}
-	ext := make(map[string]string)
-	extList := strings.Split(msg, "\n")
-	if len(extList) > 1 {
-		extList = extList[1:]
-		for _, line := range extList {
-			args := strings.SplitN(line, " ", 2)
-			if len(args) > 1 {
-				ext[args[0]] = args[1]
-			} else {
-				ext[args[0]] = ""
-			}
-		}
-	}
-	if mechs, ok := ext["AUTH"]; ok {
-		c.auth = strings.Split(mechs, " ")
-	}
-	c.ext = ext
-	return err
-}
-
-// StartTLS sends the STARTTLS command and encrypts all further communication.
-// Only servers that advertise the STARTTLS extension support this function.
-func (c *Client) StartTLS(config *tls.Config) os.Error {
-	_, _, err := c.cmd(220, "STARTTLS")
-	if err != nil {
-		return err
-	}
-	c.conn = tls.Client(c.conn, config)
-	c.Text = textproto.NewConn(c.conn)
-	c.tls = true
-	return c.ehlo()
-}
-
-// Verify checks the validity of an email address on the server.
-// If Verify returns nil, the address is valid. A non-nil return
-// does not necessarily indicate an invalid address. Many servers
-// will not verify addresses for security reasons.
-func (c *Client) Verify(addr string) os.Error {
-	_, _, err := c.cmd(250, "VRFY %s", addr)
-	return err
-}
-
-// Auth authenticates a client using the provided authentication mechanism.
-// A failed authentication closes the connection.
-// Only servers that advertise the AUTH extension support this function.
-func (c *Client) Auth(a Auth) os.Error {
-	encoding := base64.StdEncoding
-	mech, resp, err := a.Start(&ServerInfo{c.serverName, c.tls, c.auth})
-	if err != nil {
-		c.Quit()
-		return err
-	}
-	resp64 := make([]byte, encoding.EncodedLen(len(resp)))
-	encoding.Encode(resp64, resp)
-	code, msg64, err := c.cmd(0, "AUTH %s %s", mech, resp64)
-	for err == nil {
-		var msg []byte
-		switch code {
-		case 334:
-			msg, err = encoding.DecodeString(msg64)
-		case 235:
-			// the last message isn't base64 because it isn't a challenge
-			msg = []byte(msg64)
-		default:
-			err = &textproto.Error{code, msg64}
-		}
-		resp, err = a.Next(msg, code == 334)
-		if err != nil {
-			// abort the AUTH
-			c.cmd(501, "*")
-			c.Quit()
-			break
-		}
-		if resp == nil {
-			break
-		}
-		resp64 = make([]byte, encoding.EncodedLen(len(resp)))
-		encoding.Encode(resp64, resp)
-		code, msg64, err = c.cmd(0, string(resp64))
-	}
-	return err
-}
-
-// Mail issues a MAIL command to the server using the provided email address.
-// If the server supports the 8BITMIME extension, Mail adds the BODY=8BITMIME
-// parameter.
-// This initiates a mail transaction and is followed by one or more Rcpt calls.
-func (c *Client) Mail(from string) os.Error {
-	cmdStr := "MAIL FROM:<%s>"
-	if c.ext != nil {
-		if _, ok := c.ext["8BITMIME"]; ok {
-			cmdStr += " BODY=8BITMIME"
-		}
-	}
-	_, _, err := c.cmd(250, cmdStr, from)
-	return err
-}
-
-// Rcpt issues a RCPT command to the server using the provided email address.
-// A call to Rcpt must be preceded by a call to Mail and may be followed by
-// a Data call or another Rcpt call.
-func (c *Client) Rcpt(to string) os.Error {
-	_, _, err := c.cmd(25, "RCPT TO:<%s>", to)
-	return err
-}
-
-type dataCloser struct {
-	c *Client
-	io.WriteCloser
-}
-
-func (d *dataCloser) Close() os.Error {
-	d.WriteCloser.Close()
-	_, _, err := d.c.Text.ReadResponse(250)
-	return err
-}
-
-// Data issues a DATA command to the server and returns a writer that
-// can be used to write the data. The caller should close the writer
-// before calling any more methods on c.
-// A call to Data must be preceded by one or more calls to Rcpt.
-func (c *Client) Data() (io.WriteCloser, os.Error) {
-	_, _, err := c.cmd(354, "DATA")
-	if err != nil {
-		return nil, err
-	}
-	return &dataCloser{c, c.Text.DotWriter()}, nil
-}
-
-// SendMail connects to the server at addr, switches to TLS if possible,
-// authenticates with mechanism a if possible, and then sends an email from
-// address from, to addresses to, with message msg.
-func SendMail(addr string, a Auth, from string, to []string, msg []byte) os.Error {
-	c, err := Dial(addr)
-	if err != nil {
-		return err
-	}
-	if ok, _ := c.Extension("STARTTLS"); ok {
-		if err = c.StartTLS(nil); err != nil {
-			return err
-		}
-	}
-	if a != nil && c.ext != nil {
-		if _, ok := c.ext["AUTH"]; ok {
-			if err = c.Auth(a); err != nil {
-				return err
-			}
-		}
-	}
-	if err = c.Mail(from); err != nil {
-		return err
-	}
-	for _, addr := range to {
-		if err = c.Rcpt(addr); err != nil {
-			return err
-		}
-	}
-	w, err := c.Data()
-	if err != nil {
-		return err
-	}
-	_, err = w.Write(msg)
-	if err != nil {
-		return err
-	}
-	err = w.Close()
-	if err != nil {
-		return err
-	}
-	return c.Quit()
-}
-
-// Extension reports whether an extension is support by the server.
-// The extension name is case-insensitive. If the extension is supported,
-// Extension also returns a string that contains any parameters the
-// server specifies for the extension.
-func (c *Client) Extension(ext string) (bool, string) {
-	if c.ext == nil {
-		return false, ""
-	}
-	ext = strings.ToUpper(ext)
-	param, ok := c.ext[ext]
-	return ok, param
-}
-
-// Reset sends the RSET command to the server, aborting the current mail
-// transaction.
-func (c *Client) Reset() os.Error {
-	_, _, err := c.cmd(250, "RSET")
-	return err
-}
-
-// Quit sends the QUIT command and closes the connection to the server.
-func (c *Client) Quit() os.Error {
-	_, _, err := c.cmd(221, "QUIT")
-	if err != nil {
-		return err
-	}
-	return c.Text.Close()
-}
diff --git a/src/pkg/smtp/smtp_test.go b/src/pkg/smtp/smtp_test.go
deleted file mode 100644
index c053557..0000000
--- a/src/pkg/smtp/smtp_test.go
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2010 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 smtp
-
-import (
-	"bufio"
-	"bytes"
-	"io"
-	"net/textproto"
-	"os"
-	"strings"
-	"testing"
-)
-
-type authTest struct {
-	auth       Auth
-	challenges []string
-	name       string
-	responses  []string
-}
-
-var authTests = []authTest{
-	{PlainAuth("", "user", "pass", "testserver"), []string{}, "PLAIN", []string{"\x00user\x00pass"}},
-	{PlainAuth("foo", "bar", "baz", "testserver"), []string{}, "PLAIN", []string{"foo\x00bar\x00baz"}},
-}
-
-func TestAuth(t *testing.T) {
-testLoop:
-	for i, test := range authTests {
-		name, resp, err := test.auth.Start(&ServerInfo{"testserver", true, nil})
-		if name != test.name {
-			t.Errorf("#%d got name %s, expected %s", i, name, test.name)
-		}
-		if !bytes.Equal(resp, []byte(test.responses[0])) {
-			t.Errorf("#%d got response %s, expected %s", i, resp, test.responses[0])
-		}
-		if err != nil {
-			t.Errorf("#%d error: %s", i, err.String())
-		}
-		for j := range test.challenges {
-			challenge := []byte(test.challenges[j])
-			expected := []byte(test.responses[j+1])
-			resp, err := test.auth.Next(challenge, true)
-			if err != nil {
-				t.Errorf("#%d error: %s", i, err.String())
-				continue testLoop
-			}
-			if !bytes.Equal(resp, expected) {
-				t.Errorf("#%d got %s, expected %s", i, resp, expected)
-				continue testLoop
-			}
-		}
-	}
-}
-
-type faker struct {
-	io.ReadWriter
-}
-
-func (f faker) Close() os.Error {
-	return nil
-}
-
-func TestBasic(t *testing.T) {
-	basicServer = strings.Join(strings.Split(basicServer, "\n"), "\r\n")
-	basicClient = strings.Join(strings.Split(basicClient, "\n"), "\r\n")
-
-	var cmdbuf bytes.Buffer
-	bcmdbuf := bufio.NewWriter(&cmdbuf)
-	var fake faker
-	fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(basicServer)), bcmdbuf)
-	c := &Client{Text: textproto.NewConn(fake)}
-
-	if err := c.helo(); err != nil {
-		t.Fatalf("HELO failed: %s", err.String())
-	}
-	if err := c.ehlo(); err == nil {
-		t.Fatalf("Expected first EHLO to fail")
-	}
-	if err := c.ehlo(); err != nil {
-		t.Fatalf("Second EHLO failed: %s", err.String())
-	}
-
-	if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" {
-		t.Fatalf("Expected AUTH supported")
-	}
-	if ok, _ := c.Extension("DSN"); ok {
-		t.Fatalf("Shouldn't support DSN")
-	}
-
-	if err := c.Mail("user at gmail.com"); err == nil {
-		t.Fatalf("MAIL should require authentication")
-	}
-
-	if err := c.Verify("user1 at gmail.com"); err == nil {
-		t.Fatalf("First VRFY: expected no verification")
-	}
-	if err := c.Verify("user2 at gmail.com"); err != nil {
-		t.Fatalf("Second VRFY: expected verification, got %s", err)
-	}
-
-	// fake TLS so authentication won't complain
-	c.tls = true
-	c.serverName = "smtp.google.com"
-	if err := c.Auth(PlainAuth("", "user", "pass", "smtp.google.com")); err != nil {
-		t.Fatalf("AUTH failed: %s", err.String())
-	}
-
-	if err := c.Mail("user at gmail.com"); err != nil {
-		t.Fatalf("MAIL failed: %s", err.String())
-	}
-	if err := c.Rcpt("golang-nuts at googlegroups.com"); err != nil {
-		t.Fatalf("RCPT failed: %s", err.String())
-	}
-	msg := `From: user at gmail.com
-To: golang-nuts at googlegroups.com
-Subject: Hooray for Go
-
-Line 1
-.Leading dot line .
-Goodbye.`
-	w, err := c.Data()
-	if err != nil {
-		t.Fatalf("DATA failed: %s", err.String())
-	}
-	if _, err := w.Write([]byte(msg)); err != nil {
-		t.Fatalf("Data write failed: %s", err.String())
-	}
-	if err := w.Close(); err != nil {
-		t.Fatalf("Bad data response: %s", err.String())
-	}
-
-	if err := c.Quit(); err != nil {
-		t.Fatalf("QUIT failed: %s", err.String())
-	}
-
-	bcmdbuf.Flush()
-	actualcmds := cmdbuf.String()
-	if basicClient != actualcmds {
-		t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, basicClient)
-	}
-}
-
-var basicServer = `250 mx.google.com at your service
-502 Unrecognized command.
-250-mx.google.com at your service
-250-SIZE 35651584
-250-AUTH LOGIN PLAIN
-250 8BITMIME
-530 Authentication required
-252 Send some mail, I'll try my best
-250 User is valid
-235 Accepted
-250 Sender OK
-250 Receiver OK
-354 Go ahead
-250 Data OK
-221 OK
-`
-
-var basicClient = `HELO localhost
-EHLO localhost
-EHLO localhost
-MAIL FROM:<user at gmail.com> BODY=8BITMIME
-VRFY user1 at gmail.com
-VRFY user2 at gmail.com
-AUTH PLAIN AHVzZXIAcGFzcw==
-MAIL FROM:<user at gmail.com> BODY=8BITMIME
-RCPT TO:<golang-nuts at googlegroups.com>
-DATA
-From: user at gmail.com
-To: golang-nuts at googlegroups.com
-Subject: Hooray for Go
-
-Line 1
-..Leading dot line .
-Goodbye.
-.
-QUIT
-`
diff --git a/src/pkg/sort/example_test.go b/src/pkg/sort/example_test.go
new file mode 100644
index 0000000..2224db7
--- /dev/null
+++ b/src/pkg/sort/example_test.go
@@ -0,0 +1,17 @@
+// Copyright 2011 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 sort_test
+
+import (
+	"fmt"
+	"sort"
+)
+
+// [1 2 3 4 5 6]
+func ExampleInts() {
+	s := []int{5, 2, 6, 3, 1, 4} // unsorted
+	sort.Ints(s)
+	fmt.Println(s)
+}
diff --git a/src/pkg/sort/sort.go b/src/pkg/sort/sort.go
index 83ee170..31da3c8 100644
--- a/src/pkg/sort/sort.go
+++ b/src/pkg/sort/sort.go
@@ -191,7 +191,7 @@ func Sort(data Interface) {
 		maxDepth++
 	}
 	maxDepth *= 2
-	quickSort(data, 0, data.Len(), maxDepth)
+	quickSort(data, 0, n, maxDepth)
 }
 
 func IsSorted(data Interface) bool {
@@ -240,14 +240,18 @@ func (p StringSlice) Sort() { Sort(p) }
 
 // Ints sorts a slice of ints in increasing order.
 func Ints(a []int) { Sort(IntSlice(a)) }
+
 // Float64s sorts a slice of float64s in increasing order.
 func Float64s(a []float64) { Sort(Float64Slice(a)) }
+
 // Strings sorts a slice of strings in increasing order.
 func Strings(a []string) { Sort(StringSlice(a)) }
 
 // IntsAreSorted tests whether a slice of ints is sorted in increasing order.
 func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }
+
 // Float64sAreSorted tests whether a slice of float64s is sorted in increasing order.
 func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }
+
 // StringsAreSorted tests whether a slice of strings is sorted in increasing order.
 func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
diff --git a/src/pkg/sort/sort_test.go b/src/pkg/sort/sort_test.go
index a564015..ee8a9d0 100644
--- a/src/pkg/sort/sort_test.go
+++ b/src/pkg/sort/sort_test.go
@@ -7,7 +7,7 @@ package sort_test
 import (
 	"fmt"
 	"math"
-	"rand"
+	"math/rand"
 	. "sort"
 	"strconv"
 	"testing"
diff --git a/src/pkg/strconv/Makefile b/src/pkg/strconv/Makefile
index 823355d..f4e4dfb 100644
--- a/src/pkg/strconv/Makefile
+++ b/src/pkg/strconv/Makefile
@@ -10,6 +10,7 @@ GOFILES=\
 	atof.go\
 	atoi.go\
 	decimal.go\
+	extfloat.go\
 	ftoa.go\
 	itoa.go\
 	quote.go\
diff --git a/src/pkg/strconv/atob.go b/src/pkg/strconv/atob.go
index 98ce750..d0cb097 100644
--- a/src/pkg/strconv/atob.go
+++ b/src/pkg/strconv/atob.go
@@ -4,25 +4,32 @@
 
 package strconv
 
-import "os"
-
-// Atob returns the boolean value represented by the string.
+// ParseBool returns the boolean value represented by the string.
 // It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
 // Any other value returns an error.
-func Atob(str string) (value bool, err os.Error) {
+func ParseBool(str string) (value bool, err error) {
 	switch str {
 	case "1", "t", "T", "true", "TRUE", "True":
 		return true, nil
 	case "0", "f", "F", "false", "FALSE", "False":
 		return false, nil
 	}
-	return false, &NumError{str, os.EINVAL}
+	return false, syntaxError("ParseBool", str)
 }
 
-// Btoa returns "true" or "false" according to the value of the boolean argument
-func Btoa(b bool) string {
+// FormatBool returns "true" or "false" according to the value of b
+func FormatBool(b bool) string {
 	if b {
 		return "true"
 	}
 	return "false"
 }
+
+// AppendBool appends "true" or "false", according to the value of b,
+// to dst and returns the extended buffer.
+func AppendBool(dst []byte, b bool) []byte {
+	if b {
+		return append(dst, "true"...)
+	}
+	return append(dst, "false"...)
+}
diff --git a/src/pkg/strconv/atob_test.go b/src/pkg/strconv/atob_test.go
index 541e60d..a7c1454 100644
--- a/src/pkg/strconv/atob_test.go
+++ b/src/pkg/strconv/atob_test.go
@@ -5,7 +5,6 @@
 package strconv_test
 
 import (
-	"os"
 	. "strconv"
 	"testing"
 )
@@ -13,12 +12,12 @@ import (
 type atobTest struct {
 	in  string
 	out bool
-	err os.Error
+	err error
 }
 
 var atobtests = []atobTest{
-	{"", false, os.EINVAL},
-	{"asdf", false, os.EINVAL},
+	{"", false, ErrSyntax},
+	{"asdf", false, ErrSyntax},
 	{"0", false, nil},
 	{"f", false, nil},
 	{"F", false, nil},
@@ -33,16 +32,16 @@ var atobtests = []atobTest{
 	{"True", true, nil},
 }
 
-func TestAtob(t *testing.T) {
+func TestParseBool(t *testing.T) {
 	for _, test := range atobtests {
-		b, e := Atob(test.in)
+		b, e := ParseBool(test.in)
 		if test.err != nil {
 			// expect an error
 			if e == nil {
 				t.Errorf("%s: expected %s but got nil", test.in, test.err)
 			} else {
 				// NumError assertion must succeed; it's the only thing we return.
-				if test.err != e.(*NumError).Error {
+				if test.err != e.(*NumError).Err {
 					t.Errorf("%s: expected %s but got %s", test.in, test.err, e)
 				}
 			}
diff --git a/src/pkg/strconv/atof.go b/src/pkg/strconv/atof.go
index 86c56f7..42fc431 100644
--- a/src/pkg/strconv/atof.go
+++ b/src/pkg/strconv/atof.go
@@ -12,10 +12,7 @@ package strconv
 //   2) Multiply/divide decimal by powers of two until in range [0.5, 1)
 //   3) Multiply by 2^precision and round to get mantissa.
 
-import (
-	"math"
-	"os"
-)
+import "math"
 
 var optimize = true // can change for testing
 
@@ -266,6 +263,18 @@ func (d *decimal) atof32int() float32 {
 	return f
 }
 
+// Reads a uint64 decimal mantissa, which might be truncated.
+func (d *decimal) atou64() (mant uint64, digits int) {
+	const uint64digits = 19
+	for i, c := range d.d[:d.nd] {
+		if i == uint64digits {
+			return mant, i
+		}
+		mant = 10*mant + uint64(c-'0')
+	}
+	return mant, d.nd
+}
+
 // Exact powers of 10.
 var float64pow10 = []float64{
 	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
@@ -341,28 +350,16 @@ func (d *decimal) atof32() (f float32, ok bool) {
 	return
 }
 
-// Atof32 converts the string s to a 32-bit floating-point number.
-//
-// If s is well-formed and near a valid floating point number,
-// Atof32 returns the nearest floating point number rounded
-// using IEEE754 unbiased rounding.
-//
-// The errors that Atof32 returns have concrete type *NumError
-// and include err.Num = s.
-//
-// If s is not syntactically well-formed, Atof32 returns err.Error = os.EINVAL.
-//
-// If s is syntactically well-formed but is more than 1/2 ULP
-// away from the largest floating point number of the given size,
-// Atof32 returns f = ±Inf, err.Error = os.ERANGE.
-func Atof32(s string) (f float32, err os.Error) {
+const fnParseFloat = "ParseFloat"
+
+func atof32(s string) (f float32, err error) {
 	if val, ok := special(s); ok {
 		return float32(val), nil
 	}
 
 	var d decimal
 	if !d.set(s) {
-		return 0, &NumError{s, os.EINVAL}
+		return 0, syntaxError(fnParseFloat, s)
 	}
 	if optimize {
 		if f, ok := d.atof32(); ok {
@@ -372,44 +369,66 @@ func Atof32(s string) (f float32, err os.Error) {
 	b, ovf := d.floatBits(&float32info)
 	f = math.Float32frombits(uint32(b))
 	if ovf {
-		err = &NumError{s, os.ERANGE}
+		err = rangeError(fnParseFloat, s)
 	}
 	return f, err
 }
 
-// Atof64 converts the string s to a 64-bit floating-point number.
-// Except for the type of its result, its definition is the same as that
-// of Atof32.
-func Atof64(s string) (f float64, err os.Error) {
+func atof64(s string) (f float64, err error) {
 	if val, ok := special(s); ok {
 		return val, nil
 	}
 
 	var d decimal
 	if !d.set(s) {
-		return 0, &NumError{s, os.EINVAL}
+		return 0, syntaxError(fnParseFloat, s)
 	}
 	if optimize {
 		if f, ok := d.atof64(); ok {
 			return f, nil
 		}
+
+		// Try another fast path.
+		ext := new(extFloat)
+		if ok := ext.AssignDecimal(&d); ok {
+			b, ovf := ext.floatBits()
+			f = math.Float64frombits(b)
+			if ovf {
+				err = rangeError(fnParseFloat, s)
+			}
+			return f, err
+		}
 	}
 	b, ovf := d.floatBits(&float64info)
 	f = math.Float64frombits(b)
 	if ovf {
-		err = &NumError{s, os.ERANGE}
+		err = rangeError(fnParseFloat, s)
 	}
 	return f, err
 }
 
-// AtofN converts the string s to a 64-bit floating-point number,
-// but it rounds the result assuming that it will be stored in a value
-// of n bits (32 or 64).
-func AtofN(s string, n int) (f float64, err os.Error) {
-	if n == 32 {
-		f1, err1 := Atof32(s)
+// ParseFloat converts the string s to a floating-point number
+// with the precision specified by bitSize: 32 for float32, or 64 for float64.
+// When bitSize=32, the result still has type float64, but it will be
+// convertible to float32 without changing its value.
+//
+// If s is well-formed and near a valid floating point number,
+// ParseFloat returns the nearest floating point number rounded
+// using IEEE754 unbiased rounding.
+//
+// The errors that ParseFloat returns have concrete type *NumError
+// and include err.Num = s.
+//
+// If s is not syntactically well-formed, ParseFloat returns err.Error = ErrSyntax.
+//
+// If s is syntactically well-formed but is more than 1/2 ULP
+// away from the largest floating point number of the given size,
+// ParseFloat returns f = ±Inf, err.Error = ErrRange.
+func ParseFloat(s string, bitSize int) (f float64, err error) {
+	if bitSize == 32 {
+		f1, err1 := atof32(s)
 		return float64(f1), err1
 	}
-	f1, err1 := Atof64(s)
+	f1, err1 := atof64(s)
 	return f1, err1
 }
diff --git a/src/pkg/strconv/atof_test.go b/src/pkg/strconv/atof_test.go
index 23aafc1..3fa637d 100644
--- a/src/pkg/strconv/atof_test.go
+++ b/src/pkg/strconv/atof_test.go
@@ -5,24 +5,26 @@
 package strconv_test
 
 import (
-	"os"
+	"math"
+	"math/rand"
 	"reflect"
 	. "strconv"
 	"testing"
+	"time"
 )
 
 type atofTest struct {
 	in  string
 	out string
-	err os.Error
+	err error
 }
 
 var atoftests = []atofTest{
-	{"", "0", os.EINVAL},
+	{"", "0", ErrSyntax},
 	{"1", "1", nil},
 	{"+1", "1", nil},
-	{"1x", "0", os.EINVAL},
-	{"1.1.", "0", os.EINVAL},
+	{"1x", "0", ErrSyntax},
+	{"1.1.", "0", ErrSyntax},
 	{"1e23", "1e+23", nil},
 	{"1E23", "1e+23", nil},
 	{"100000000000000000000000", "1e+23", nil},
@@ -56,28 +58,28 @@ var atoftests = []atofTest{
 	{"1.7976931348623157e308", "1.7976931348623157e+308", nil},
 	{"-1.7976931348623157e308", "-1.7976931348623157e+308", nil},
 	// next float64 - too large
-	{"1.7976931348623159e308", "+Inf", os.ERANGE},
-	{"-1.7976931348623159e308", "-Inf", os.ERANGE},
+	{"1.7976931348623159e308", "+Inf", ErrRange},
+	{"-1.7976931348623159e308", "-Inf", ErrRange},
 	// the border is ...158079
 	// borderline - okay
 	{"1.7976931348623158e308", "1.7976931348623157e+308", nil},
 	{"-1.7976931348623158e308", "-1.7976931348623157e+308", nil},
 	// borderline - too large
-	{"1.797693134862315808e308", "+Inf", os.ERANGE},
-	{"-1.797693134862315808e308", "-Inf", os.ERANGE},
+	{"1.797693134862315808e308", "+Inf", ErrRange},
+	{"-1.797693134862315808e308", "-Inf", ErrRange},
 
 	// a little too large
 	{"1e308", "1e+308", nil},
-	{"2e308", "+Inf", os.ERANGE},
-	{"1e309", "+Inf", os.ERANGE},
+	{"2e308", "+Inf", ErrRange},
+	{"1e309", "+Inf", ErrRange},
 
 	// way too large
-	{"1e310", "+Inf", os.ERANGE},
-	{"-1e310", "-Inf", os.ERANGE},
-	{"1e400", "+Inf", os.ERANGE},
-	{"-1e400", "-Inf", os.ERANGE},
-	{"1e400000", "+Inf", os.ERANGE},
-	{"-1e400000", "-Inf", os.ERANGE},
+	{"1e310", "+Inf", ErrRange},
+	{"-1e310", "-Inf", ErrRange},
+	{"1e400", "+Inf", ErrRange},
+	{"-1e400", "-Inf", ErrRange},
+	{"1e400000", "+Inf", ErrRange},
+	{"-1e400000", "-Inf", ErrRange},
 
 	// denormalized
 	{"1e-305", "1e-305", nil},
@@ -99,63 +101,92 @@ var atoftests = []atofTest{
 
 	// try to overflow exponent
 	{"1e-4294967296", "0", nil},
-	{"1e+4294967296", "+Inf", os.ERANGE},
+	{"1e+4294967296", "+Inf", ErrRange},
 	{"1e-18446744073709551616", "0", nil},
-	{"1e+18446744073709551616", "+Inf", os.ERANGE},
+	{"1e+18446744073709551616", "+Inf", ErrRange},
 
 	// Parse errors
-	{"1e", "0", os.EINVAL},
-	{"1e-", "0", os.EINVAL},
-	{".e-1", "0", os.EINVAL},
+	{"1e", "0", ErrSyntax},
+	{"1e-", "0", ErrSyntax},
+	{".e-1", "0", ErrSyntax},
 
 	// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
 	{"2.2250738585072012e-308", "2.2250738585072014e-308", nil},
 	// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
 	{"2.2250738585072011e-308", "2.225073858507201e-308", nil},
+
+	// A very large number (initially wrongly parsed by the fast algorithm).
+	{"4.630813248087435e+307", "4.630813248087435e+307", nil},
+}
+
+type atofSimpleTest struct {
+	x float64
+	s string
 }
 
+var (
+	atofRandomTests        []atofSimpleTest
+	benchmarksRandomBits   [1024]string
+	benchmarksRandomNormal [1024]string
+)
+
 func init() {
 	// The atof routines return NumErrors wrapping
 	// the error and the string.  Convert the table above.
 	for i := range atoftests {
 		test := &atoftests[i]
 		if test.err != nil {
-			test.err = &NumError{test.in, test.err}
+			test.err = &NumError{"ParseFloat", test.in, test.err}
 		}
 	}
+
+	// Generate random inputs for tests and benchmarks
+	rand.Seed(time.Now().UnixNano())
+	if testing.Short() {
+		atofRandomTests = make([]atofSimpleTest, 100)
+	} else {
+		atofRandomTests = make([]atofSimpleTest, 10000)
+	}
+	for i := range atofRandomTests {
+		n := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
+		x := math.Float64frombits(n)
+		s := FormatFloat(x, 'g', -1, 64)
+		atofRandomTests[i] = atofSimpleTest{x, s}
+	}
+
+	for i := range benchmarksRandomBits {
+		bits := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
+		x := math.Float64frombits(bits)
+		benchmarksRandomBits[i] = FormatFloat(x, 'g', -1, 64)
+	}
+
+	for i := range benchmarksRandomNormal {
+		x := rand.NormFloat64()
+		benchmarksRandomNormal[i] = FormatFloat(x, 'g', -1, 64)
+	}
 }
 
 func testAtof(t *testing.T, opt bool) {
 	oldopt := SetOptimize(opt)
 	for i := 0; i < len(atoftests); i++ {
 		test := &atoftests[i]
-		out, err := Atof64(test.in)
-		outs := Ftoa64(out, 'g', -1)
-		if outs != test.out || !reflect.DeepEqual(err, test.err) {
-			t.Errorf("Atof64(%v) = %v, %v want %v, %v",
-				test.in, out, err, test.out, test.err)
-		}
-
-		out, err = AtofN(test.in, 64)
-		outs = FtoaN(out, 'g', -1, 64)
+		out, err := ParseFloat(test.in, 64)
+		outs := FormatFloat(out, 'g', -1, 64)
 		if outs != test.out || !reflect.DeepEqual(err, test.err) {
-			t.Errorf("AtofN(%v, 64) = %v, %v want %v, %v",
+			t.Errorf("ParseFloat(%v, 64) = %v, %v want %v, %v",
 				test.in, out, err, test.out, test.err)
 		}
 
 		if float64(float32(out)) == out {
-			out32, err := Atof32(test.in)
-			outs := Ftoa32(out32, 'g', -1)
-			if outs != test.out || !reflect.DeepEqual(err, test.err) {
-				t.Errorf("Atof32(%v) = %v, %v want %v, %v  # %v",
-					test.in, out32, err, test.out, test.err, out)
+			out, err := ParseFloat(test.in, 32)
+			out32 := float32(out)
+			if float64(out32) != out {
+				t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32))
+				continue
 			}
-
-			out, err := AtofN(test.in, 32)
-			out32 = float32(out)
-			outs = FtoaN(float64(out32), 'g', -1, 32)
+			outs := FormatFloat(float64(out32), 'g', -1, 32)
 			if outs != test.out || !reflect.DeepEqual(err, test.err) {
-				t.Errorf("AtofN(%v, 32) = %v, %v want %v, %v  # %v",
+				t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v  # %v",
 					test.in, out32, err, test.out, test.err, out)
 			}
 		}
@@ -167,26 +198,51 @@ func TestAtof(t *testing.T) { testAtof(t, true) }
 
 func TestAtofSlow(t *testing.T) { testAtof(t, false) }
 
+func TestAtofRandom(t *testing.T) {
+	for _, test := range atofRandomTests {
+		x, _ := ParseFloat(test.s, 64)
+		switch {
+		default:
+			t.Errorf("number %s badly parsed as %b (expected %b)", test.s, x, test.x)
+		case x == test.x:
+		case math.IsNaN(test.x) && math.IsNaN(x):
+		}
+	}
+	t.Logf("tested %d random numbers", len(atofRandomTests))
+}
+
 func BenchmarkAtof64Decimal(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Atof64("33909")
+		ParseFloat("33909", 64)
 	}
 }
 
 func BenchmarkAtof64Float(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Atof64("339.7784")
+		ParseFloat("339.7784", 64)
 	}
 }
 
 func BenchmarkAtof64FloatExp(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Atof64("-5.09e75")
+		ParseFloat("-5.09e75", 64)
 	}
 }
 
 func BenchmarkAtof64Big(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Atof64("123456789123456789123456789")
+		ParseFloat("123456789123456789123456789", 64)
+	}
+}
+
+func BenchmarkAtof64RandomBits(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat(benchmarksRandomBits[i%1024], 64)
+	}
+}
+
+func BenchmarkAtof64RandomFloats(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ParseFloat(benchmarksRandomNormal[i%1024], 64)
 	}
 }
diff --git a/src/pkg/strconv/atoi.go b/src/pkg/strconv/atoi.go
index 5845942..59ef264 100644
--- a/src/pkg/strconv/atoi.go
+++ b/src/pkg/strconv/atoi.go
@@ -4,24 +4,36 @@
 
 package strconv
 
-import "os"
+import "errors"
 
+// ErrRange indicates that a value is out of range for the target type.
+var ErrRange = errors.New("value out of range")
+
+// ErrSyntax indicates that a value does not have the right syntax for the target type.
+var ErrSyntax = errors.New("invalid syntax")
+
+// A NumError records a failed conversion.
 type NumError struct {
-	Num   string
-	Error os.Error
+	Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
+	Num  string // the input
+	Err  error  // the reason the conversion failed (ErrRange, ErrSyntax)
+}
+
+func (e *NumError) Error() string {
+	return "strconv." + e.Func + ": " + `parsing "` + e.Num + `": ` + e.Err.Error()
 }
 
-func (e *NumError) String() string { return `parsing "` + e.Num + `": ` + e.Error.String() }
+func syntaxError(fn, str string) *NumError {
+	return &NumError{fn, str, ErrSyntax}
+}
 
-func computeIntsize() uint {
-	siz := uint(8)
-	for 1<<siz != 0 {
-		siz *= 2
-	}
-	return siz
+func rangeError(fn, str string) *NumError {
+	return &NumError{fn, str, ErrRange}
 }
 
-var IntSize = computeIntsize()
+const intSize = 32 << uint(^uint(0)>>63)
+
+const IntSize = intSize // number of bits in int, uint (32 or 64)
 
 // Return the first number n such that n*base >= 1<<64.
 func cutoff64(base int) uint64 {
@@ -31,22 +43,18 @@ func cutoff64(base int) uint64 {
 	return (1<<64-1)/uint64(base) + 1
 }
 
-// Btoui64 interprets a string s in an arbitrary base b (2 to 36)
-// and returns the corresponding value n.  If b == 0, the base
-// is taken from the string prefix: base 16 for "0x", base 8 for "0",
-// and base 10 otherwise.
-//
-// The errors that Btoui64 returns have concrete type *NumError
-// and include err.Num = s.  If s is empty or contains invalid
-// digits, err.Error = os.EINVAL; if the value corresponding
-// to s cannot be represented by a uint64, err.Error = os.ERANGE.
-func Btoui64(s string, b int) (n uint64, err os.Error) {
-	var cutoff uint64
+// ParseUint is like ParseInt but for unsigned numbers.
+func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
+	var cutoff, maxVal uint64
+
+	if bitSize == 0 {
+		bitSize = int(IntSize)
+	}
 
 	s0 := s
 	switch {
 	case len(s) < 1:
-		err = os.EINVAL
+		err = ErrSyntax
 		goto Error
 
 	case 2 <= b && b <= 36:
@@ -59,7 +67,7 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
 			b = 16
 			s = s[2:]
 			if len(s) < 1 {
-				err = os.EINVAL
+				err = ErrSyntax
 				goto Error
 			}
 		case s[0] == '0':
@@ -69,12 +77,13 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
 		}
 
 	default:
-		err = os.NewError("invalid base " + Itoa(b))
+		err = errors.New("invalid base " + Itoa(b))
 		goto Error
 	}
 
 	n = 0
 	cutoff = cutoff64(b)
+	maxVal = 1<<uint(bitSize) - 1
 
 	for i := 0; i < len(s); i++ {
 		var v byte
@@ -88,28 +97,28 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
 			v = d - 'A' + 10
 		default:
 			n = 0
-			err = os.EINVAL
+			err = ErrSyntax
 			goto Error
 		}
 		if int(v) >= b {
 			n = 0
-			err = os.EINVAL
+			err = ErrSyntax
 			goto Error
 		}
 
 		if n >= cutoff {
 			// n*b overflows
 			n = 1<<64 - 1
-			err = os.ERANGE
+			err = ErrRange
 			goto Error
 		}
 		n *= uint64(b)
 
 		n1 := n + uint64(v)
-		if n1 < n {
+		if n1 < n || n1 > maxVal {
 			// n+v overflows
 			n = 1<<64 - 1
-			err = os.ERANGE
+			err = ErrRange
 			goto Error
 		}
 		n = n1
@@ -118,24 +127,33 @@ func Btoui64(s string, b int) (n uint64, err os.Error) {
 	return n, nil
 
 Error:
-	return n, &NumError{s0, err}
+	return n, &NumError{"ParseUint", s0, err}
 }
 
-// Atoui64 interprets a string s as a decimal number and
-// returns the corresponding value n.
+// ParseInt interprets a string s in the given base (2 to 36) and
+// returns the corresponding value i.  If base == 0, the base is
+// implied by the string's prefix: base 16 for "0x", base 8 for
+// "0", and base 10 otherwise.
 //
-// Atoui64 returns err == os.EINVAL if s is empty or contains invalid digits.
-// It returns err == os.ERANGE if s cannot be represented by a uint64.
-func Atoui64(s string) (n uint64, err os.Error) {
-	return Btoui64(s, 10)
-}
+// The bitSize argument specifies the integer type
+// that the result must fit into.  Bit sizes 0, 8, 16, 32, and 64
+// correspond to int, int8, int16, int32, and int64.
+//
+// The errors that ParseInt returns have concrete type *NumError
+// and include err.Num = s.  If s is empty or contains invalid
+// digits, err.Error = ErrSyntax; if the value corresponding
+// to s cannot be represented by a signed integer of the
+// given size, err.Error = ErrRange.
+func ParseInt(s string, base int, bitSize int) (i int64, err error) {
+	const fnParseInt = "ParseInt"
+
+	if bitSize == 0 {
+		bitSize = int(IntSize)
+	}
 
-// Btoi64 is like Btoui64 but allows signed numbers and
-// returns its result in an int64.
-func Btoi64(s string, base int) (i int64, err os.Error) {
 	// Empty string bad.
 	if len(s) == 0 {
-		return 0, &NumError{s, os.EINVAL}
+		return 0, syntaxError(fnParseInt, s)
 	}
 
 	// Pick off leading sign.
@@ -150,16 +168,18 @@ func Btoi64(s string, base int) (i int64, err os.Error) {
 
 	// Convert unsigned and check range.
 	var un uint64
-	un, err = Btoui64(s, base)
-	if err != nil && err.(*NumError).Error != os.ERANGE {
+	un, err = ParseUint(s, base, bitSize)
+	if err != nil && err.(*NumError).Err != ErrRange {
+		err.(*NumError).Func = fnParseInt
 		err.(*NumError).Num = s0
 		return 0, err
 	}
-	if !neg && un >= 1<<63 {
-		return 1<<63 - 1, &NumError{s0, os.ERANGE}
+	cutoff := uint64(1 << uint(bitSize-1))
+	if !neg && un >= cutoff {
+		return int64(cutoff - 1), rangeError(fnParseInt, s0)
 	}
-	if neg && un > 1<<63 {
-		return -1 << 63, &NumError{s0, os.ERANGE}
+	if neg && un > cutoff {
+		return -int64(cutoff), rangeError(fnParseInt, s0)
 	}
 	n := int64(un)
 	if neg {
@@ -168,35 +188,8 @@ func Btoi64(s string, base int) (i int64, err os.Error) {
 	return n, nil
 }
 
-// Atoi64 is like Atoui64 but allows signed numbers and
-// returns its result in an int64.
-func Atoi64(s string) (i int64, err os.Error) { return Btoi64(s, 10) }
-
-// Atoui is like Atoui64 but returns its result as a uint.
-func Atoui(s string) (i uint, err os.Error) {
-	i1, e1 := Atoui64(s)
-	if e1 != nil && e1.(*NumError).Error != os.ERANGE {
-		return 0, e1
-	}
-	i = uint(i1)
-	if uint64(i) != i1 {
-		return ^uint(0), &NumError{s, os.ERANGE}
-	}
-	return i, nil
-}
-
-// Atoi is like Atoi64 but returns its result as an int.
-func Atoi(s string) (i int, err os.Error) {
-	i1, e1 := Atoi64(s)
-	if e1 != nil && e1.(*NumError).Error != os.ERANGE {
-		return 0, e1
-	}
-	i = int(i1)
-	if int64(i) != i1 {
-		if i1 < 0 {
-			return -1 << (IntSize - 1), &NumError{s, os.ERANGE}
-		}
-		return 1<<(IntSize-1) - 1, &NumError{s, os.ERANGE}
-	}
-	return i, nil
+// Atoi is shorthand for ParseInt(s, 10, 0).
+func Atoi(s string) (i int, err error) {
+	i64, err := ParseInt(s, 10, 0)
+	return int(i64), err
 }
diff --git a/src/pkg/strconv/atoi_test.go b/src/pkg/strconv/atoi_test.go
index 0b9f295..d0e7b61 100644
--- a/src/pkg/strconv/atoi_test.go
+++ b/src/pkg/strconv/atoi_test.go
@@ -5,7 +5,6 @@
 package strconv_test
 
 import (
-	"os"
 	"reflect"
 	. "strconv"
 	"testing"
@@ -14,51 +13,51 @@ import (
 type atoui64Test struct {
 	in  string
 	out uint64
-	err os.Error
+	err error
 }
 
 var atoui64tests = []atoui64Test{
-	{"", 0, os.EINVAL},
+	{"", 0, ErrSyntax},
 	{"0", 0, nil},
 	{"1", 1, nil},
 	{"12345", 12345, nil},
 	{"012345", 12345, nil},
-	{"12345x", 0, os.EINVAL},
+	{"12345x", 0, ErrSyntax},
 	{"98765432100", 98765432100, nil},
 	{"18446744073709551615", 1<<64 - 1, nil},
-	{"18446744073709551616", 1<<64 - 1, os.ERANGE},
-	{"18446744073709551620", 1<<64 - 1, os.ERANGE},
+	{"18446744073709551616", 1<<64 - 1, ErrRange},
+	{"18446744073709551620", 1<<64 - 1, ErrRange},
 }
 
 var btoui64tests = []atoui64Test{
-	{"", 0, os.EINVAL},
+	{"", 0, ErrSyntax},
 	{"0", 0, nil},
 	{"1", 1, nil},
 	{"12345", 12345, nil},
 	{"012345", 012345, nil},
 	{"0x12345", 0x12345, nil},
 	{"0X12345", 0x12345, nil},
-	{"12345x", 0, os.EINVAL},
+	{"12345x", 0, ErrSyntax},
 	{"98765432100", 98765432100, nil},
 	{"18446744073709551615", 1<<64 - 1, nil},
-	{"18446744073709551616", 1<<64 - 1, os.ERANGE},
-	{"18446744073709551620", 1<<64 - 1, os.ERANGE},
+	{"18446744073709551616", 1<<64 - 1, ErrRange},
+	{"18446744073709551620", 1<<64 - 1, ErrRange},
 	{"0xFFFFFFFFFFFFFFFF", 1<<64 - 1, nil},
-	{"0x10000000000000000", 1<<64 - 1, os.ERANGE},
+	{"0x10000000000000000", 1<<64 - 1, ErrRange},
 	{"01777777777777777777777", 1<<64 - 1, nil},
-	{"01777777777777777777778", 0, os.EINVAL},
-	{"02000000000000000000000", 1<<64 - 1, os.ERANGE},
+	{"01777777777777777777778", 0, ErrSyntax},
+	{"02000000000000000000000", 1<<64 - 1, ErrRange},
 	{"0200000000000000000000", 1 << 61, nil},
 }
 
 type atoi64Test struct {
 	in  string
 	out int64
-	err os.Error
+	err error
 }
 
 var atoi64tests = []atoi64Test{
-	{"", 0, os.EINVAL},
+	{"", 0, ErrSyntax},
 	{"0", 0, nil},
 	{"-0", 0, nil},
 	{"1", 1, nil},
@@ -71,14 +70,14 @@ var atoi64tests = []atoi64Test{
 	{"-98765432100", -98765432100, nil},
 	{"9223372036854775807", 1<<63 - 1, nil},
 	{"-9223372036854775807", -(1<<63 - 1), nil},
-	{"9223372036854775808", 1<<63 - 1, os.ERANGE},
+	{"9223372036854775808", 1<<63 - 1, ErrRange},
 	{"-9223372036854775808", -1 << 63, nil},
-	{"9223372036854775809", 1<<63 - 1, os.ERANGE},
-	{"-9223372036854775809", -1 << 63, os.ERANGE},
+	{"9223372036854775809", 1<<63 - 1, ErrRange},
+	{"-9223372036854775809", -1 << 63, ErrRange},
 }
 
 var btoi64tests = []atoi64Test{
-	{"", 0, os.EINVAL},
+	{"", 0, ErrSyntax},
 	{"0", 0, nil},
 	{"-0", 0, nil},
 	{"1", 1, nil},
@@ -89,44 +88,44 @@ var btoi64tests = []atoi64Test{
 	{"-012345", -012345, nil},
 	{"0x12345", 0x12345, nil},
 	{"-0X12345", -0x12345, nil},
-	{"12345x", 0, os.EINVAL},
-	{"-12345x", 0, os.EINVAL},
+	{"12345x", 0, ErrSyntax},
+	{"-12345x", 0, ErrSyntax},
 	{"98765432100", 98765432100, nil},
 	{"-98765432100", -98765432100, nil},
 	{"9223372036854775807", 1<<63 - 1, nil},
 	{"-9223372036854775807", -(1<<63 - 1), nil},
-	{"9223372036854775808", 1<<63 - 1, os.ERANGE},
+	{"9223372036854775808", 1<<63 - 1, ErrRange},
 	{"-9223372036854775808", -1 << 63, nil},
-	{"9223372036854775809", 1<<63 - 1, os.ERANGE},
-	{"-9223372036854775809", -1 << 63, os.ERANGE},
+	{"9223372036854775809", 1<<63 - 1, ErrRange},
+	{"-9223372036854775809", -1 << 63, ErrRange},
 }
 
 type atoui32Test struct {
 	in  string
 	out uint32
-	err os.Error
+	err error
 }
 
 var atoui32tests = []atoui32Test{
-	{"", 0, os.EINVAL},
+	{"", 0, ErrSyntax},
 	{"0", 0, nil},
 	{"1", 1, nil},
 	{"12345", 12345, nil},
 	{"012345", 12345, nil},
-	{"12345x", 0, os.EINVAL},
+	{"12345x", 0, ErrSyntax},
 	{"987654321", 987654321, nil},
 	{"4294967295", 1<<32 - 1, nil},
-	{"4294967296", 1<<32 - 1, os.ERANGE},
+	{"4294967296", 1<<32 - 1, ErrRange},
 }
 
 type atoi32Test struct {
 	in  string
 	out int32
-	err os.Error
+	err error
 }
 
 var atoi32tests = []atoi32Test{
-	{"", 0, os.EINVAL},
+	{"", 0, ErrSyntax},
 	{"0", 0, nil},
 	{"-0", 0, nil},
 	{"1", 1, nil},
@@ -135,16 +134,16 @@ var atoi32tests = []atoi32Test{
 	{"-12345", -12345, nil},
 	{"012345", 12345, nil},
 	{"-012345", -12345, nil},
-	{"12345x", 0, os.EINVAL},
-	{"-12345x", 0, os.EINVAL},
+	{"12345x", 0, ErrSyntax},
+	{"-12345x", 0, ErrSyntax},
 	{"987654321", 987654321, nil},
 	{"-987654321", -987654321, nil},
 	{"2147483647", 1<<31 - 1, nil},
 	{"-2147483647", -(1<<31 - 1), nil},
-	{"2147483648", 1<<31 - 1, os.ERANGE},
+	{"2147483648", 1<<31 - 1, ErrRange},
 	{"-2147483648", -1 << 31, nil},
-	{"2147483649", 1<<31 - 1, os.ERANGE},
-	{"-2147483649", -1 << 31, os.ERANGE},
+	{"2147483649", 1<<31 - 1, ErrRange},
+	{"-2147483649", -1 << 31, ErrRange},
 }
 
 func init() {
@@ -153,45 +152,45 @@ func init() {
 	for i := range atoui64tests {
 		test := &atoui64tests[i]
 		if test.err != nil {
-			test.err = &NumError{test.in, test.err}
+			test.err = &NumError{"ParseUint", test.in, test.err}
 		}
 	}
 	for i := range btoui64tests {
 		test := &btoui64tests[i]
 		if test.err != nil {
-			test.err = &NumError{test.in, test.err}
+			test.err = &NumError{"ParseUint", test.in, test.err}
 		}
 	}
 	for i := range atoi64tests {
 		test := &atoi64tests[i]
 		if test.err != nil {
-			test.err = &NumError{test.in, test.err}
+			test.err = &NumError{"ParseInt", test.in, test.err}
 		}
 	}
 	for i := range btoi64tests {
 		test := &btoi64tests[i]
 		if test.err != nil {
-			test.err = &NumError{test.in, test.err}
+			test.err = &NumError{"ParseInt", test.in, test.err}
 		}
 	}
 	for i := range atoui32tests {
 		test := &atoui32tests[i]
 		if test.err != nil {
-			test.err = &NumError{test.in, test.err}
+			test.err = &NumError{"ParseUint", test.in, test.err}
 		}
 	}
 	for i := range atoi32tests {
 		test := &atoi32tests[i]
 		if test.err != nil {
-			test.err = &NumError{test.in, test.err}
+			test.err = &NumError{"ParseInt", test.in, test.err}
 		}
 	}
 }
 
-func TestAtoui64(t *testing.T) {
+func TestParseUint64(t *testing.T) {
 	for i := range atoui64tests {
 		test := &atoui64tests[i]
-		out, err := Atoui64(test.in)
+		out, err := ParseUint(test.in, 10, 64)
 		if test.out != out || !reflect.DeepEqual(test.err, err) {
 			t.Errorf("Atoui64(%q) = %v, %v want %v, %v",
 				test.in, out, err, test.out, test.err)
@@ -199,21 +198,21 @@ func TestAtoui64(t *testing.T) {
 	}
 }
 
-func TestBtoui64(t *testing.T) {
+func TestParseUint64Base(t *testing.T) {
 	for i := range btoui64tests {
 		test := &btoui64tests[i]
-		out, err := Btoui64(test.in, 0)
+		out, err := ParseUint(test.in, 0, 64)
 		if test.out != out || !reflect.DeepEqual(test.err, err) {
-			t.Errorf("Btoui64(%q) = %v, %v want %v, %v",
+			t.Errorf("ParseUint(%q) = %v, %v want %v, %v",
 				test.in, out, err, test.out, test.err)
 		}
 	}
 }
 
-func TestAtoi64(t *testing.T) {
+func TestParseInt64(t *testing.T) {
 	for i := range atoi64tests {
 		test := &atoi64tests[i]
-		out, err := Atoi64(test.in)
+		out, err := ParseInt(test.in, 10, 64)
 		if test.out != out || !reflect.DeepEqual(test.err, err) {
 			t.Errorf("Atoi64(%q) = %v, %v want %v, %v",
 				test.in, out, err, test.out, test.err)
@@ -221,23 +220,23 @@ func TestAtoi64(t *testing.T) {
 	}
 }
 
-func TestBtoi64(t *testing.T) {
+func TestParseInt64Base(t *testing.T) {
 	for i := range btoi64tests {
 		test := &btoi64tests[i]
-		out, err := Btoi64(test.in, 0)
+		out, err := ParseInt(test.in, 0, 64)
 		if test.out != out || !reflect.DeepEqual(test.err, err) {
-			t.Errorf("Btoi64(%q) = %v, %v want %v, %v",
+			t.Errorf("ParseInt(%q) = %v, %v want %v, %v",
 				test.in, out, err, test.out, test.err)
 		}
 	}
 }
 
-func TestAtoui(t *testing.T) {
+func TestParseUint(t *testing.T) {
 	switch IntSize {
 	case 32:
 		for i := range atoui32tests {
 			test := &atoui32tests[i]
-			out, err := Atoui(test.in)
+			out, err := ParseUint(test.in, 10, 0)
 			if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) {
 				t.Errorf("Atoui(%q) = %v, %v want %v, %v",
 					test.in, out, err, test.out, test.err)
@@ -246,7 +245,7 @@ func TestAtoui(t *testing.T) {
 	case 64:
 		for i := range atoui64tests {
 			test := &atoui64tests[i]
-			out, err := Atoui(test.in)
+			out, err := ParseUint(test.in, 10, 0)
 			if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) {
 				t.Errorf("Atoui(%q) = %v, %v want %v, %v",
 					test.in, out, err, test.out, test.err)
@@ -255,12 +254,12 @@ func TestAtoui(t *testing.T) {
 	}
 }
 
-func TestAtoi(t *testing.T) {
+func TestParseInt(t *testing.T) {
 	switch IntSize {
 	case 32:
 		for i := range atoi32tests {
 			test := &atoi32tests[i]
-			out, err := Atoi(test.in)
+			out, err := ParseInt(test.in, 10, 0)
 			if test.out != int32(out) || !reflect.DeepEqual(test.err, err) {
 				t.Errorf("Atoi(%q) = %v, %v want %v, %v",
 					test.in, out, err, test.out, test.err)
@@ -269,7 +268,7 @@ func TestAtoi(t *testing.T) {
 	case 64:
 		for i := range atoi64tests {
 			test := &atoi64tests[i]
-			out, err := Atoi(test.in)
+			out, err := ParseInt(test.in, 10, 0)
 			if test.out != int64(out) || !reflect.DeepEqual(test.err, err) {
 				t.Errorf("Atoi(%q) = %v, %v want %v, %v",
 					test.in, out, err, test.out, test.err)
@@ -280,24 +279,24 @@ func TestAtoi(t *testing.T) {
 
 func BenchmarkAtoi(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Atoi("12345678")
+		ParseInt("12345678", 10, 0)
 	}
 }
 
 func BenchmarkAtoiNeg(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Atoi("-12345678")
+		ParseInt("-12345678", 10, 0)
 	}
 }
 
 func BenchmarkAtoi64(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Atoi64("12345678901234")
+		ParseInt("12345678901234", 10, 64)
 	}
 }
 
 func BenchmarkAtoi64Neg(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Atoi64("-12345678901234")
+		ParseInt("-12345678901234", 10, 64)
 	}
 }
diff --git a/src/pkg/strconv/decimal.go b/src/pkg/strconv/decimal.go
index f572ea4..cc5591a 100644
--- a/src/pkg/strconv/decimal.go
+++ b/src/pkg/strconv/decimal.go
@@ -14,9 +14,9 @@ package strconv
 type decimal struct {
 	// TODO(rsc): Can make d[] a bit smaller and add
 	// truncated bool;
-	d   [2000]byte // digits
-	nd  int        // number of digits used
-	dp  int        // decimal point
+	d   [800]byte // digits
+	nd  int       // number of digits used
+	dp  int       // decimal point
 	neg bool
 }
 
@@ -102,12 +102,6 @@ func (a *decimal) Assign(v uint64) {
 	trim(a)
 }
 
-func newDecimal(i uint64) *decimal {
-	a := new(decimal)
-	a.Assign(i)
-	return a
-}
-
 // Maximum shift that we can do in one pass without overflow.
 // Signed int has 31 bits, and we have to be able to accommodate 9<<k.
 const maxShift = 27
@@ -303,32 +297,32 @@ func shouldRoundUp(a *decimal, nd int) bool {
 // If nd is zero, it means we're rounding
 // just to the left of the digits, as in
 // 0.09 -> 0.1.
-func (a *decimal) Round(nd int) *decimal {
+func (a *decimal) Round(nd int) {
 	if nd < 0 || nd >= a.nd {
-		return a
+		return
 	}
 	if shouldRoundUp(a, nd) {
-		return a.RoundUp(nd)
+		a.RoundUp(nd)
+	} else {
+		a.RoundDown(nd)
 	}
-	return a.RoundDown(nd)
 }
 
 // Round a down to nd digits (or fewer).
 // Returns receiver for convenience.
-func (a *decimal) RoundDown(nd int) *decimal {
+func (a *decimal) RoundDown(nd int) {
 	if nd < 0 || nd >= a.nd {
-		return a
+		return
 	}
 	a.nd = nd
 	trim(a)
-	return a
 }
 
 // Round a up to nd digits (or fewer).
 // Returns receiver for convenience.
-func (a *decimal) RoundUp(nd int) *decimal {
+func (a *decimal) RoundUp(nd int) {
 	if nd < 0 || nd >= a.nd {
-		return a
+		return
 	}
 
 	// round up
@@ -337,7 +331,7 @@ func (a *decimal) RoundUp(nd int) *decimal {
 		if c < '9' { // can stop after this digit
 			a.d[i]++
 			a.nd = i + 1
-			return a
+			return
 		}
 	}
 
@@ -346,7 +340,6 @@ func (a *decimal) RoundUp(nd int) *decimal {
 	a.d[0] = '1'
 	a.nd = 1
 	a.dp++
-	return a
 }
 
 // Extract integer part, rounded appropriately.
diff --git a/src/pkg/strconv/decimal_test.go b/src/pkg/strconv/decimal_test.go
index deb2e02..13a127f 100644
--- a/src/pkg/strconv/decimal_test.go
+++ b/src/pkg/strconv/decimal_test.go
@@ -70,17 +70,23 @@ var roundtests = []roundTest{
 func TestDecimalRound(t *testing.T) {
 	for i := 0; i < len(roundtests); i++ {
 		test := &roundtests[i]
-		s := NewDecimal(test.i).RoundDown(test.nd).String()
+		d := NewDecimal(test.i)
+		d.RoundDown(test.nd)
+		s := d.String()
 		if s != test.down {
 			t.Errorf("Decimal %v RoundDown %d = %v, want %v",
 				test.i, test.nd, s, test.down)
 		}
-		s = NewDecimal(test.i).Round(test.nd).String()
+		d = NewDecimal(test.i)
+		d.Round(test.nd)
+		s = d.String()
 		if s != test.round {
 			t.Errorf("Decimal %v Round %d = %v, want %v",
 				test.i, test.nd, s, test.down)
 		}
-		s = NewDecimal(test.i).RoundUp(test.nd).String()
+		d = NewDecimal(test.i)
+		d.RoundUp(test.nd)
+		s = d.String()
 		if s != test.up {
 			t.Errorf("Decimal %v RoundUp %d = %v, want %v",
 				test.i, test.nd, s, test.up)
diff --git a/src/pkg/strconv/extfloat.go b/src/pkg/strconv/extfloat.go
new file mode 100644
index 0000000..64ab84f
--- /dev/null
+++ b/src/pkg/strconv/extfloat.go
@@ -0,0 +1,501 @@
+// Copyright 2011 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 strconv
+
+import "math"
+
+// An extFloat represents an extended floating-point number, with more
+// precision than a float64. It does not try to save bits: the
+// number represented by the structure is mant*(2^exp), with a negative
+// sign if neg is true.
+type extFloat struct {
+	mant uint64
+	exp  int
+	neg  bool
+}
+
+// Powers of ten taken from double-conversion library.
+// http://code.google.com/p/double-conversion/
+const (
+	firstPowerOfTen = -348
+	stepPowerOfTen  = 8
+)
+
+var smallPowersOfTen = [...]extFloat{
+	{1 << 63, -63, false},        // 1
+	{0xa << 60, -60, false},      // 1e1
+	{0x64 << 57, -57, false},     // 1e2
+	{0x3e8 << 54, -54, false},    // 1e3
+	{0x2710 << 50, -50, false},   // 1e4
+	{0x186a0 << 47, -47, false},  // 1e5
+	{0xf4240 << 44, -44, false},  // 1e6
+	{0x989680 << 40, -40, false}, // 1e7
+}
+
+var powersOfTen = [...]extFloat{
+	{0xfa8fd5a0081c0288, -1220, false}, // 10^-348
+	{0xbaaee17fa23ebf76, -1193, false}, // 10^-340
+	{0x8b16fb203055ac76, -1166, false}, // 10^-332
+	{0xcf42894a5dce35ea, -1140, false}, // 10^-324
+	{0x9a6bb0aa55653b2d, -1113, false}, // 10^-316
+	{0xe61acf033d1a45df, -1087, false}, // 10^-308
+	{0xab70fe17c79ac6ca, -1060, false}, // 10^-300
+	{0xff77b1fcbebcdc4f, -1034, false}, // 10^-292
+	{0xbe5691ef416bd60c, -1007, false}, // 10^-284
+	{0x8dd01fad907ffc3c, -980, false},  // 10^-276
+	{0xd3515c2831559a83, -954, false},  // 10^-268
+	{0x9d71ac8fada6c9b5, -927, false},  // 10^-260
+	{0xea9c227723ee8bcb, -901, false},  // 10^-252
+	{0xaecc49914078536d, -874, false},  // 10^-244
+	{0x823c12795db6ce57, -847, false},  // 10^-236
+	{0xc21094364dfb5637, -821, false},  // 10^-228
+	{0x9096ea6f3848984f, -794, false},  // 10^-220
+	{0xd77485cb25823ac7, -768, false},  // 10^-212
+	{0xa086cfcd97bf97f4, -741, false},  // 10^-204
+	{0xef340a98172aace5, -715, false},  // 10^-196
+	{0xb23867fb2a35b28e, -688, false},  // 10^-188
+	{0x84c8d4dfd2c63f3b, -661, false},  // 10^-180
+	{0xc5dd44271ad3cdba, -635, false},  // 10^-172
+	{0x936b9fcebb25c996, -608, false},  // 10^-164
+	{0xdbac6c247d62a584, -582, false},  // 10^-156
+	{0xa3ab66580d5fdaf6, -555, false},  // 10^-148
+	{0xf3e2f893dec3f126, -529, false},  // 10^-140
+	{0xb5b5ada8aaff80b8, -502, false},  // 10^-132
+	{0x87625f056c7c4a8b, -475, false},  // 10^-124
+	{0xc9bcff6034c13053, -449, false},  // 10^-116
+	{0x964e858c91ba2655, -422, false},  // 10^-108
+	{0xdff9772470297ebd, -396, false},  // 10^-100
+	{0xa6dfbd9fb8e5b88f, -369, false},  // 10^-92
+	{0xf8a95fcf88747d94, -343, false},  // 10^-84
+	{0xb94470938fa89bcf, -316, false},  // 10^-76
+	{0x8a08f0f8bf0f156b, -289, false},  // 10^-68
+	{0xcdb02555653131b6, -263, false},  // 10^-60
+	{0x993fe2c6d07b7fac, -236, false},  // 10^-52
+	{0xe45c10c42a2b3b06, -210, false},  // 10^-44
+	{0xaa242499697392d3, -183, false},  // 10^-36
+	{0xfd87b5f28300ca0e, -157, false},  // 10^-28
+	{0xbce5086492111aeb, -130, false},  // 10^-20
+	{0x8cbccc096f5088cc, -103, false},  // 10^-12
+	{0xd1b71758e219652c, -77, false},   // 10^-4
+	{0x9c40000000000000, -50, false},   // 10^4
+	{0xe8d4a51000000000, -24, false},   // 10^12
+	{0xad78ebc5ac620000, 3, false},     // 10^20
+	{0x813f3978f8940984, 30, false},    // 10^28
+	{0xc097ce7bc90715b3, 56, false},    // 10^36
+	{0x8f7e32ce7bea5c70, 83, false},    // 10^44
+	{0xd5d238a4abe98068, 109, false},   // 10^52
+	{0x9f4f2726179a2245, 136, false},   // 10^60
+	{0xed63a231d4c4fb27, 162, false},   // 10^68
+	{0xb0de65388cc8ada8, 189, false},   // 10^76
+	{0x83c7088e1aab65db, 216, false},   // 10^84
+	{0xc45d1df942711d9a, 242, false},   // 10^92
+	{0x924d692ca61be758, 269, false},   // 10^100
+	{0xda01ee641a708dea, 295, false},   // 10^108
+	{0xa26da3999aef774a, 322, false},   // 10^116
+	{0xf209787bb47d6b85, 348, false},   // 10^124
+	{0xb454e4a179dd1877, 375, false},   // 10^132
+	{0x865b86925b9bc5c2, 402, false},   // 10^140
+	{0xc83553c5c8965d3d, 428, false},   // 10^148
+	{0x952ab45cfa97a0b3, 455, false},   // 10^156
+	{0xde469fbd99a05fe3, 481, false},   // 10^164
+	{0xa59bc234db398c25, 508, false},   // 10^172
+	{0xf6c69a72a3989f5c, 534, false},   // 10^180
+	{0xb7dcbf5354e9bece, 561, false},   // 10^188
+	{0x88fcf317f22241e2, 588, false},   // 10^196
+	{0xcc20ce9bd35c78a5, 614, false},   // 10^204
+	{0x98165af37b2153df, 641, false},   // 10^212
+	{0xe2a0b5dc971f303a, 667, false},   // 10^220
+	{0xa8d9d1535ce3b396, 694, false},   // 10^228
+	{0xfb9b7cd9a4a7443c, 720, false},   // 10^236
+	{0xbb764c4ca7a44410, 747, false},   // 10^244
+	{0x8bab8eefb6409c1a, 774, false},   // 10^252
+	{0xd01fef10a657842c, 800, false},   // 10^260
+	{0x9b10a4e5e9913129, 827, false},   // 10^268
+	{0xe7109bfba19c0c9d, 853, false},   // 10^276
+	{0xac2820d9623bf429, 880, false},   // 10^284
+	{0x80444b5e7aa7cf85, 907, false},   // 10^292
+	{0xbf21e44003acdd2d, 933, false},   // 10^300
+	{0x8e679c2f5e44ff8f, 960, false},   // 10^308
+	{0xd433179d9c8cb841, 986, false},   // 10^316
+	{0x9e19db92b4e31ba9, 1013, false},  // 10^324
+	{0xeb96bf6ebadf77d9, 1039, false},  // 10^332
+	{0xaf87023b9bf0ee6b, 1066, false},  // 10^340
+}
+
+// floatBits returns the bits of the float64 that best approximates
+// the extFloat passed as receiver. Overflow is set to true if
+// the resulting float64 is ±Inf.
+func (f *extFloat) floatBits() (bits uint64, overflow bool) {
+	flt := &float64info
+	f.Normalize()
+
+	exp := f.exp + 63
+
+	// Exponent too small.
+	if exp < flt.bias+1 {
+		n := flt.bias + 1 - exp
+		f.mant >>= uint(n)
+		exp += n
+	}
+
+	// Extract 1+flt.mantbits bits.
+	mant := f.mant >> (63 - flt.mantbits)
+	if f.mant&(1<<(62-flt.mantbits)) != 0 {
+		// Round up.
+		mant += 1
+	}
+
+	// Rounding might have added a bit; shift down.
+	if mant == 2<<flt.mantbits {
+		mant >>= 1
+		exp++
+	}
+
+	// Infinities.
+	if exp-flt.bias >= 1<<flt.expbits-1 {
+		goto overflow
+	}
+
+	// Denormalized?
+	if mant&(1<<flt.mantbits) == 0 {
+		exp = flt.bias
+	}
+	goto out
+
+overflow:
+	// ±Inf
+	mant = 0
+	exp = 1<<flt.expbits - 1 + flt.bias
+	overflow = true
+
+out:
+	// Assemble bits.
+	bits = mant & (uint64(1)<<flt.mantbits - 1)
+	bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
+	if f.neg {
+		bits |= 1 << (flt.mantbits + flt.expbits)
+	}
+	return
+}
+
+// Assign sets f to the value of x.
+func (f *extFloat) Assign(x float64) {
+	if x < 0 {
+		x = -x
+		f.neg = true
+	}
+	x, f.exp = math.Frexp(x)
+	f.mant = uint64(x * float64(1<<64))
+	f.exp -= 64
+}
+
+// AssignComputeBounds sets f to the value of x and returns
+// lower, upper such that any number in the closed interval
+// [lower, upper] is converted back to x.
+func (f *extFloat) AssignComputeBounds(x float64) (lower, upper extFloat) {
+	// Special cases.
+	bits := math.Float64bits(x)
+	flt := &float64info
+	neg := bits>>(flt.expbits+flt.mantbits) != 0
+	expBiased := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
+	mant := bits & (uint64(1)<<flt.mantbits - 1)
+
+	if expBiased == 0 {
+		// denormalized.
+		f.mant = mant
+		f.exp = 1 + flt.bias - int(flt.mantbits)
+	} else {
+		f.mant = mant | 1<<flt.mantbits
+		f.exp = expBiased + flt.bias - int(flt.mantbits)
+	}
+	f.neg = neg
+
+	upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg}
+	if mant != 0 || expBiased == 1 {
+		lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg}
+	} else {
+		lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg}
+	}
+	return
+}
+
+// Normalize normalizes f so that the highest bit of the mantissa is
+// set, and returns the number by which the mantissa was left-shifted.
+func (f *extFloat) Normalize() uint {
+	if f.mant == 0 {
+		return 0
+	}
+	exp_before := f.exp
+	for f.mant < (1 << 55) {
+		f.mant <<= 8
+		f.exp -= 8
+	}
+	for f.mant < (1 << 63) {
+		f.mant <<= 1
+		f.exp -= 1
+	}
+	return uint(exp_before - f.exp)
+}
+
+// Multiply sets f to the product f*g: the result is correctly rounded,
+// but not normalized.
+func (f *extFloat) Multiply(g extFloat) {
+	fhi, flo := f.mant>>32, uint64(uint32(f.mant))
+	ghi, glo := g.mant>>32, uint64(uint32(g.mant))
+
+	// Cross products.
+	cross1 := fhi * glo
+	cross2 := flo * ghi
+
+	// f.mant*g.mant is fhi*ghi << 64 + (cross1+cross2) << 32 + flo*glo
+	f.mant = fhi*ghi + (cross1 >> 32) + (cross2 >> 32)
+	rem := uint64(uint32(cross1)) + uint64(uint32(cross2)) + ((flo * glo) >> 32)
+	// Round up.
+	rem += (1 << 31)
+
+	f.mant += (rem >> 32)
+	f.exp = f.exp + g.exp + 64
+}
+
+var uint64pow10 = [...]uint64{
+	1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+}
+
+// AssignDecimal sets f to an approximate value of the decimal d. It
+// returns true if the value represented by f is guaranteed to be the
+// best approximation of d after being rounded to a float64. 
+func (f *extFloat) AssignDecimal(d *decimal) (ok bool) {
+	const uint64digits = 19
+	const errorscale = 8
+	mant10, digits := d.atou64()
+	exp10 := d.dp - digits
+	errors := 0 // An upper bound for error, computed in errorscale*ulp.
+
+	if digits < d.nd {
+		// the decimal number was truncated.
+		errors += errorscale / 2
+	}
+
+	f.mant = mant10
+	f.exp = 0
+	f.neg = d.neg
+
+	// Multiply by powers of ten.
+	i := (exp10 - firstPowerOfTen) / stepPowerOfTen
+	if exp10 < firstPowerOfTen || i >= len(powersOfTen) {
+		return false
+	}
+	adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen
+
+	// We multiply by exp%step
+	if digits+adjExp <= uint64digits {
+		// We can multiply the mantissa
+		f.mant *= uint64(float64pow10[adjExp])
+		f.Normalize()
+	} else {
+		f.Normalize()
+		f.Multiply(smallPowersOfTen[adjExp])
+		errors += errorscale / 2
+	}
+
+	// We multiply by 10 to the exp - exp%step.
+	f.Multiply(powersOfTen[i])
+	if errors > 0 {
+		errors += 1
+	}
+	errors += errorscale / 2
+
+	// Normalize
+	shift := f.Normalize()
+	errors <<= shift
+
+	// Now f is a good approximation of the decimal.
+	// Check whether the error is too large: that is, if the mantissa
+	// is perturbated by the error, the resulting float64 will change.
+	// The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits.
+	//
+	// In many cases the approximation will be good enough.
+	const denormalExp = -1023 - 63
+	flt := &float64info
+	var extrabits uint
+	if f.exp <= denormalExp {
+		extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp))
+	} else {
+		extrabits = uint(63 - flt.mantbits)
+	}
+
+	halfway := uint64(1) << (extrabits - 1)
+	mant_extra := f.mant & (1<<extrabits - 1)
+
+	// Do a signed comparison here! If the error estimate could make
+	// the mantissa round differently for the conversion to double,
+	// then we can't give a definite answer.
+	if int64(halfway)-int64(errors) < int64(mant_extra) &&
+		int64(mant_extra) < int64(halfway)+int64(errors) {
+		return false
+	}
+	return true
+}
+
+// Frexp10 is an analogue of math.Frexp for decimal powers. It scales
+// f by an approximate power of ten 10^-exp, and returns exp10, so
+// that f*10^exp10 has the same value as the old f, up to an ulp,
+// as well as the index of 10^-exp in the powersOfTen table.
+// The arguments expMin and expMax constrain the final value of the
+// binary exponent of f.
+func (f *extFloat) frexp10(expMin, expMax int) (exp10, index int) {
+	// it is illegal to call this function with a too restrictive exponent range.
+	if expMax-expMin <= 25 {
+		panic("strconv: invalid exponent range")
+	}
+	// Find power of ten such that x * 10^n has a binary exponent
+	// between expMin and expMax
+	approxExp10 := -(f.exp + 100) * 28 / 93 // log(10)/log(2) is close to 93/28.
+	i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen
+Loop:
+	for {
+		exp := f.exp + powersOfTen[i].exp + 64
+		switch {
+		case exp < expMin:
+			i++
+		case exp > expMax:
+			i--
+		default:
+			break Loop
+		}
+	}
+	// Apply the desired decimal shift on f. It will have exponent
+	// in the desired range. This is multiplication by 10^-exp10.
+	f.Multiply(powersOfTen[i])
+
+	return -(firstPowerOfTen + i*stepPowerOfTen), i
+}
+
+// frexp10Many applies a common shift by a power of ten to a, b, c.
+func frexp10Many(expMin, expMax int, a, b, c *extFloat) (exp10 int) {
+	exp10, i := c.frexp10(expMin, expMax)
+	a.Multiply(powersOfTen[i])
+	b.Multiply(powersOfTen[i])
+	return
+}
+
+// ShortestDecimal stores in d the shortest decimal representation of f
+// which belongs to the open interval (lower, upper), where f is supposed
+// to lie. It returns false whenever the result is unsure. The implementation
+// uses the Grisu3 algorithm.
+func (f *extFloat) ShortestDecimal(d *decimal, lower, upper *extFloat) bool {
+	if f.mant == 0 {
+		d.d[0] = '0'
+		d.nd = 1
+		d.dp = 0
+		d.neg = f.neg
+	}
+	const minExp = -60
+	const maxExp = -32
+	upper.Normalize()
+	// Uniformize exponents.
+	if f.exp > upper.exp {
+		f.mant <<= uint(f.exp - upper.exp)
+		f.exp = upper.exp
+	}
+	if lower.exp > upper.exp {
+		lower.mant <<= uint(lower.exp - upper.exp)
+		lower.exp = upper.exp
+	}
+
+	exp10 := frexp10Many(minExp, maxExp, lower, f, upper)
+	// Take a safety margin due to rounding in frexp10Many, but we lose precision.
+	upper.mant++
+	lower.mant--
+
+	// The shortest representation of f is either rounded up or down, but
+	// in any case, it is a truncation of upper.
+	shift := uint(-upper.exp)
+	integer := uint32(upper.mant >> shift)
+	fraction := upper.mant - (uint64(integer) << shift)
+
+	// How far we can go down from upper until the result is wrong.
+	allowance := upper.mant - lower.mant
+	// How far we should go to get a very precise result.
+	targetDiff := upper.mant - f.mant
+
+	// Count integral digits: there are at most 10.
+	var integerDigits int
+	for i, pow := range uint64pow10 {
+		if uint64(integer) >= pow {
+			integerDigits = i + 1
+		}
+	}
+	for i := 0; i < integerDigits; i++ {
+		pow := uint64pow10[integerDigits-i-1]
+		digit := integer / uint32(pow)
+		d.d[i] = byte(digit + '0')
+		integer -= digit * uint32(pow)
+		// evaluate whether we should stop.
+		if currentDiff := uint64(integer)<<shift + fraction; currentDiff < allowance {
+			d.nd = i + 1
+			d.dp = integerDigits + exp10
+			d.neg = f.neg
+			// Sometimes allowance is so large the last digit might need to be
+			// decremented to get closer to f.
+			return adjustLastDigit(d, currentDiff, targetDiff, allowance, pow<<shift, 2)
+		}
+	}
+	d.nd = integerDigits
+	d.dp = d.nd + exp10
+	d.neg = f.neg
+
+	// Compute digits of the fractional part. At each step fraction does not
+	// overflow. The choice of minExp implies that fraction is less than 2^60.
+	var digit int
+	multiplier := uint64(1)
+	for {
+		fraction *= 10
+		multiplier *= 10
+		digit = int(fraction >> shift)
+		d.d[d.nd] = byte(digit + '0')
+		d.nd++
+		fraction -= uint64(digit) << shift
+		if fraction < allowance*multiplier {
+			// We are in the admissible range. Note that if allowance is about to
+			// overflow, that is, allowance > 2^64/10, the condition is automatically
+			// true due to the limited range of fraction.
+			return adjustLastDigit(d,
+				fraction, targetDiff*multiplier, allowance*multiplier,
+				1<<shift, multiplier*2)
+		}
+	}
+	return false
+}
+
+// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to 
+// d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε.
+// It assumes that a decimal digit is worth ulpDecimal*ε, and that
+// all data is known with a error estimate of ulpBinary*ε.
+func adjustLastDigit(d *decimal, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
+	if ulpDecimal < 2*ulpBinary {
+		// Appromixation is too wide.
+		return false
+	}
+	for currentDiff+ulpDecimal/2+ulpBinary < targetDiff {
+		d.d[d.nd-1]--
+		currentDiff += ulpDecimal
+	}
+	if currentDiff+ulpDecimal <= targetDiff+ulpDecimal/2+ulpBinary {
+		// we have two choices, and don't know what to do.
+		return false
+	}
+	if currentDiff < ulpBinary || currentDiff > maxDiff-ulpBinary {
+		// we went too far
+		return false
+	}
+	if d.nd == 1 && d.d[0] == '0' {
+		// the number has actually reached zero.
+		d.nd = 0
+		d.dp = 0
+	}
+	return true
+}
diff --git a/src/pkg/strconv/fp_test.go b/src/pkg/strconv/fp_test.go
index 3096957..171defa 100644
--- a/src/pkg/strconv/fp_test.go
+++ b/src/pkg/strconv/fp_test.go
@@ -7,6 +7,7 @@ package strconv_test
 import (
 	"bufio"
 	"fmt"
+	"io"
 	"os"
 	"strconv"
 	"strings"
@@ -25,12 +26,12 @@ func pow2(i int) float64 {
 	return pow2(i/2) * pow2(i-i/2)
 }
 
-// Wrapper around strconv.Atof64.  Handles dddddp+ddd (binary exponent)
-// itself, passes the rest on to strconv.Atof64.
+// Wrapper around strconv.ParseFloat(x, 64).  Handles dddddp+ddd (binary exponent)
+// itself, passes the rest on to strconv.ParseFloat.
 func myatof64(s string) (f float64, ok bool) {
 	a := strings.SplitN(s, "p", 2)
 	if len(a) == 2 {
-		n, err := strconv.Atoi64(a[0])
+		n, err := strconv.ParseInt(a[0], 10, 64)
 		if err != nil {
 			return 0, false
 		}
@@ -62,15 +63,15 @@ func myatof64(s string) (f float64, ok bool) {
 		}
 		return v * pow2(e), true
 	}
-	f1, err := strconv.Atof64(s)
+	f1, err := strconv.ParseFloat(s, 64)
 	if err != nil {
 		return 0, false
 	}
 	return f1, true
 }
 
-// Wrapper around strconv.Atof32.  Handles dddddp+ddd (binary exponent)
-// itself, passes the rest on to strconv.Atof32.
+// Wrapper around strconv.ParseFloat(x, 32).  Handles dddddp+ddd (binary exponent)
+// itself, passes the rest on to strconv.ParseFloat.
 func myatof32(s string) (f float32, ok bool) {
 	a := strings.SplitN(s, "p", 2)
 	if len(a) == 2 {
@@ -86,7 +87,8 @@ func myatof32(s string) (f float32, ok bool) {
 		}
 		return float32(float64(n) * pow2(e)), true
 	}
-	f1, err1 := strconv.Atof32(s)
+	f64, err1 := strconv.ParseFloat(s, 32)
+	f1 := float32(f64)
 	if err1 != nil {
 		return 0, false
 	}
@@ -96,7 +98,7 @@ func myatof32(s string) (f float32, ok bool) {
 func TestFp(t *testing.T) {
 	f, err := os.Open("testfp.txt")
 	if err != nil {
-		t.Fatal("testfp: open testfp.txt:", err.String())
+		t.Fatal("testfp: open testfp.txt:", err)
 	}
 	defer f.Close()
 
@@ -105,11 +107,11 @@ func TestFp(t *testing.T) {
 	lineno := 0
 	for {
 		line, err2 := b.ReadString('\n')
-		if err2 == os.EOF {
+		if err2 == io.EOF {
 			break
 		}
 		if err2 != nil {
-			t.Fatal("testfp: read testfp.txt: " + err2.String())
+			t.Fatal("testfp: read testfp.txt: " + err2.Error())
 		}
 		line = line[0 : len(line)-1]
 		lineno++
diff --git a/src/pkg/strconv/ftoa.go b/src/pkg/strconv/ftoa.go
index 07fe806..8eefbee 100644
--- a/src/pkg/strconv/ftoa.go
+++ b/src/pkg/strconv/ftoa.go
@@ -22,8 +22,10 @@ type floatInfo struct {
 var float32info = floatInfo{23, 8, -127}
 var float64info = floatInfo{52, 11, -1023}
 
-// Ftoa32 converts the 32-bit floating-point number f to a string,
-// according to the format fmt and precision prec.
+// FormatFloat converts the floating-point number f to a string,
+// according to the format fmt and precision prec.  It rounds the
+// result assuming that the original was obtained from a floating-point
+// value of bitSize bits (32 for float32, 64 for float64).
 //
 // The format fmt is one of
 // 'b' (-ddddp±ddd, a binary exponent),
@@ -38,32 +40,31 @@ var float64info = floatInfo{52, 11, -1023}
 // For 'e', 'E', and 'f' it is the number of digits after the decimal point.
 // For 'g' and 'G' it is the total number of digits.
 // The special precision -1 uses the smallest number of digits
-// necessary such that Atof32 will return f exactly.
-//
-// Ftoa32(f) is not the same as Ftoa64(float32(f)),
-// because correct rounding and the number of digits
-// needed to identify f depend on the precision of the representation.
-func Ftoa32(f float32, fmt byte, prec int) string {
-	return genericFtoa(uint64(math.Float32bits(f)), fmt, prec, &float32info)
+// necessary such that ParseFloat will return f exactly.
+func FormatFloat(f float64, fmt byte, prec, bitSize int) string {
+	return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize))
 }
 
-// Ftoa64 is like Ftoa32 but converts a 64-bit floating-point number.
-func Ftoa64(f float64, fmt byte, prec int) string {
-	return genericFtoa(math.Float64bits(f), fmt, prec, &float64info)
+// AppendFloat appends the string form of the floating-point number f,
+// as generated by FormatFloat, to dst and returns the extended buffer.
+func AppendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte {
+	return genericFtoa(dst, f, fmt, prec, bitSize)
 }
 
-// FtoaN converts the 64-bit floating-point number f to a string,
-// according to the format fmt and precision prec, but it rounds the
-// result assuming that it was obtained from a floating-point value
-// of n bits (32 or 64).
-func FtoaN(f float64, fmt byte, prec int, n int) string {
-	if n == 32 {
-		return Ftoa32(float32(f), fmt, prec)
+func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
+	var bits uint64
+	var flt *floatInfo
+	switch bitSize {
+	case 32:
+		bits = uint64(math.Float32bits(float32(val)))
+		flt = &float32info
+	case 64:
+		bits = math.Float64bits(val)
+		flt = &float64info
+	default:
+		panic("strconv: illegal AppendFloat/FormatFloat bitSize")
 	}
-	return Ftoa64(f, fmt, prec)
-}
 
-func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
 	neg := bits>>(flt.expbits+flt.mantbits) != 0
 	exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
 	mant := bits & (uint64(1)<<flt.mantbits - 1)
@@ -71,13 +72,16 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
 	switch exp {
 	case 1<<flt.expbits - 1:
 		// Inf, NaN
-		if mant != 0 {
-			return "NaN"
-		}
-		if neg {
-			return "-Inf"
+		var s string
+		switch {
+		case mant != 0:
+			s = "NaN"
+		case neg:
+			s = "-Inf"
+		default:
+			s = "+Inf"
 		}
-		return "+Inf"
+		return append(dst, s...)
 
 	case 0:
 		// denormalized
@@ -91,31 +95,46 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
 
 	// Pick off easy binary format.
 	if fmt == 'b' {
-		return fmtB(neg, mant, exp, flt)
+		return fmtB(dst, neg, mant, exp, flt)
 	}
 
-	// Create exact decimal representation.
-	// The shift is exp - flt.mantbits because mant is a 1-bit integer
-	// followed by a flt.mantbits fraction, and we are treating it as
-	// a 1+flt.mantbits-bit integer.
-	d := newDecimal(mant)
-	d.Shift(exp - int(flt.mantbits))
-
-	// Round appropriately.
 	// Negative precision means "only as much as needed to be exact."
-	shortest := false
-	if prec < 0 {
-		shortest = true
-		roundShortest(d, mant, exp, flt)
-		switch fmt {
-		case 'e', 'E':
-			prec = d.nd - 1
-		case 'f':
-			prec = max(d.nd-d.dp, 0)
-		case 'g', 'G':
-			prec = d.nd
+	shortest := prec < 0
+
+	d := new(decimal)
+	if shortest {
+		ok := false
+		if optimize && bitSize == 64 {
+			// Try Grisu3 algorithm.
+			f := new(extFloat)
+			lower, upper := f.AssignComputeBounds(val)
+			ok = f.ShortestDecimal(d, &lower, &upper)
+		}
+		if !ok {
+			// Create exact decimal representation.
+			// The shift is exp - flt.mantbits because mant is a 1-bit integer
+			// followed by a flt.mantbits fraction, and we are treating it as
+			// a 1+flt.mantbits-bit integer.
+			d.Assign(mant)
+			d.Shift(exp - int(flt.mantbits))
+			roundShortest(d, mant, exp, flt)
+		}
+		// Precision for shortest representation mode.
+		if prec < 0 {
+			switch fmt {
+			case 'e', 'E':
+				prec = d.nd - 1
+			case 'f':
+				prec = max(d.nd-d.dp, 0)
+			case 'g', 'G':
+				prec = d.nd
+			}
 		}
 	} else {
+		// Create exact decimal representation.
+		d.Assign(mant)
+		d.Shift(exp - int(flt.mantbits))
+		// Round appropriately.
 		switch fmt {
 		case 'e', 'E':
 			d.Round(prec + 1)
@@ -131,9 +150,9 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
 
 	switch fmt {
 	case 'e', 'E':
-		return fmtE(neg, d, prec, fmt)
+		return fmtE(dst, neg, d, prec, fmt)
 	case 'f':
-		return fmtF(neg, d, prec)
+		return fmtF(dst, neg, d, prec)
 	case 'g', 'G':
 		// trailing fractional zeros in 'e' form will be trimmed.
 		eprec := prec
@@ -151,15 +170,16 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
 			if prec > d.nd {
 				prec = d.nd
 			}
-			return fmtE(neg, d, prec-1, fmt+'e'-'g')
+			return fmtE(dst, neg, d, prec-1, fmt+'e'-'g')
 		}
 		if prec > d.dp {
 			prec = d.nd
 		}
-		return fmtF(neg, d, max(prec-d.dp, 0))
+		return fmtF(dst, neg, d, max(prec-d.dp, 0))
 	}
 
-	return "%" + string(fmt)
+	// unknown format
+	return append(dst, '%', fmt)
 }
 
 // Round d (= mant * 2^exp) to the shortest number of digits
@@ -172,19 +192,31 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 		return
 	}
 
-	// TODO(rsc): Unless exp == minexp, if the number of digits in d
-	// is less than 17, it seems likely that it would be
-	// the shortest possible number already.  So maybe we can
-	// bail out without doing the extra multiprecision math here.
-
 	// Compute upper and lower such that any decimal number
 	// between upper and lower (possibly inclusive)
 	// will round to the original floating point number.
 
+	// We may see at once that the number is already shortest.
+	//
+	// Suppose d is not denormal, so that 2^exp <= d < 10^dp.
+	// The closest shorter number is at least 10^(dp-nd) away.
+	// The lower/upper bounds computed below are at distance
+	// at most 2^(exp-mantbits).
+	//
+	// So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),
+	// or equivalently log2(10)*(dp-nd) > exp-mantbits.
+	// It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).
+	minexp := flt.bias + 1 // minimum possible exponent
+	if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {
+		// The number is already shortest.
+		return
+	}
+
 	// d = mant << (exp - mantbits)
 	// Next highest floating point number is mant+1 << exp-mantbits.
 	// Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1.
-	upper := newDecimal(mant*2 + 1)
+	upper := new(decimal)
+	upper.Assign(mant*2 + 1)
 	upper.Shift(exp - int(flt.mantbits) - 1)
 
 	// d = mant << (exp - mantbits)
@@ -193,7 +225,6 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 	// in which case the next lowest is mant*2-1 << exp-mantbits-1.
 	// Either way, call it mantlo << explo-mantbits.
 	// Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1.
-	minexp := flt.bias + 1 // minimum possible exponent
 	var mantlo uint64
 	var explo int
 	if mant > 1<<flt.mantbits || exp == minexp {
@@ -203,7 +234,8 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 		mantlo = mant*2 - 1
 		explo = exp - 1
 	}
-	lower := newDecimal(mantlo*2 + 1)
+	lower := new(decimal)
+	lower.Assign(mantlo*2 + 1)
 	lower.Shift(explo - int(flt.mantbits) - 1)
 
 	// The upper and lower bounds are possible outputs only if
@@ -233,7 +265,7 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 
 		// Okay to round up if upper has a different digit and
 		// either upper is inclusive or upper is bigger than the result of rounding up.
-		okup := m != u && (inclusive || i+1 < upper.nd)
+		okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)
 
 		// If it's okay to do either, then round to the nearest one.
 		// If it's okay to do only one, do it.
@@ -252,121 +284,103 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 }
 
 // %e: -d.ddddde±dd
-func fmtE(neg bool, d *decimal, prec int, fmt byte) string {
-	buf := make([]byte, 3+max(prec, 0)+30) // "-0." + prec digits + exp
-	w := 0                                 // write index
-
+func fmtE(dst []byte, neg bool, d *decimal, prec int, fmt byte) []byte {
 	// sign
 	if neg {
-		buf[w] = '-'
-		w++
+		dst = append(dst, '-')
 	}
 
 	// first digit
-	if d.nd == 0 {
-		buf[w] = '0'
-	} else {
-		buf[w] = d.d[0]
+	ch := byte('0')
+	if d.nd != 0 {
+		ch = d.d[0]
 	}
-	w++
+	dst = append(dst, ch)
 
 	// .moredigits
 	if prec > 0 {
-		buf[w] = '.'
-		w++
-		for i := 0; i < prec; i++ {
-			if 1+i < d.nd {
-				buf[w] = d.d[1+i]
-			} else {
-				buf[w] = '0'
+		dst = append(dst, '.')
+		for i := 1; i <= prec; i++ {
+			ch = '0'
+			if i < d.nd {
+				ch = d.d[i]
 			}
-			w++
+			dst = append(dst, ch)
 		}
 	}
 
 	// e±
-	buf[w] = fmt
-	w++
+	dst = append(dst, fmt)
 	exp := d.dp - 1
 	if d.nd == 0 { // special case: 0 has exponent 0
 		exp = 0
 	}
 	if exp < 0 {
-		buf[w] = '-'
+		ch = '-'
 		exp = -exp
 	} else {
-		buf[w] = '+'
+		ch = '+'
 	}
-	w++
+	dst = append(dst, ch)
 
 	// dddd
-	// count digits
-	n := 0
-	for e := exp; e > 0; e /= 10 {
-		n++
-	}
-	// leading zeros
-	for i := n; i < 2; i++ {
-		buf[w] = '0'
-		w++
+	var buf [3]byte
+	i := len(buf)
+	for exp >= 10 {
+		i--
+		buf[i] = byte(exp%10 + '0')
+		exp /= 10
 	}
-	// digits
-	w += n
-	n = 0
-	for e := exp; e > 0; e /= 10 {
-		n++
-		buf[w-n] = byte(e%10 + '0')
+	// exp < 10
+	i--
+	buf[i] = byte(exp + '0')
+
+	// leading zeroes
+	if i > len(buf)-2 {
+		i--
+		buf[i] = '0'
 	}
 
-	return string(buf[0:w])
+	return append(dst, buf[i:]...)
 }
 
 // %f: -ddddddd.ddddd
-func fmtF(neg bool, d *decimal, prec int) string {
-	buf := make([]byte, 1+max(d.dp, 1)+1+max(prec, 0))
-	w := 0
-
+func fmtF(dst []byte, neg bool, d *decimal, prec int) []byte {
 	// sign
 	if neg {
-		buf[w] = '-'
-		w++
+		dst = append(dst, '-')
 	}
 
 	// integer, padded with zeros as needed.
 	if d.dp > 0 {
 		var i int
 		for i = 0; i < d.dp && i < d.nd; i++ {
-			buf[w] = d.d[i]
-			w++
+			dst = append(dst, d.d[i])
 		}
 		for ; i < d.dp; i++ {
-			buf[w] = '0'
-			w++
+			dst = append(dst, '0')
 		}
 	} else {
-		buf[w] = '0'
-		w++
+		dst = append(dst, '0')
 	}
 
 	// fraction
 	if prec > 0 {
-		buf[w] = '.'
-		w++
+		dst = append(dst, '.')
 		for i := 0; i < prec; i++ {
-			if d.dp+i < 0 || d.dp+i >= d.nd {
-				buf[w] = '0'
-			} else {
-				buf[w] = d.d[d.dp+i]
+			ch := byte('0')
+			if j := d.dp + i; 0 <= j && j < d.nd {
+				ch = d.d[j]
 			}
-			w++
+			dst = append(dst, ch)
 		}
 	}
 
-	return string(buf[0:w])
+	return dst
 }
 
 // %b: -ddddddddp+ddd
-func fmtB(neg bool, mant uint64, exp int, flt *floatInfo) string {
+func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
 	var buf [50]byte
 	w := len(buf)
 	exp -= int(flt.mantbits)
@@ -397,7 +411,7 @@ func fmtB(neg bool, mant uint64, exp int, flt *floatInfo) string {
 		w--
 		buf[w] = '-'
 	}
-	return string(buf[w:])
+	return append(dst, buf[w:]...)
 }
 
 func max(a, b int) int {
diff --git a/src/pkg/strconv/ftoa_test.go b/src/pkg/strconv/ftoa_test.go
index 6d361a1..7d8617a 100644
--- a/src/pkg/strconv/ftoa_test.go
+++ b/src/pkg/strconv/ftoa_test.go
@@ -6,6 +6,7 @@ package strconv_test
 
 import (
 	"math"
+	"math/rand"
 	. "strconv"
 	"testing"
 )
@@ -123,28 +124,133 @@ var ftoatests = []ftoaTest{
 	{2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
 	// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
 	{2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
+
+	// Issue 2625.
+	{383260575764816448, 'f', 0, "383260575764816448"},
+	{383260575764816448, 'g', -1, "3.8326057576481645e+17"},
 }
 
 func TestFtoa(t *testing.T) {
 	for i := 0; i < len(ftoatests); i++ {
 		test := &ftoatests[i]
-		s := Ftoa64(test.f, test.fmt, test.prec)
-		if s != test.s {
-			t.Error("test", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
-		}
-		s = FtoaN(test.f, test.fmt, test.prec, 64)
+		s := FormatFloat(test.f, test.fmt, test.prec, 64)
 		if s != test.s {
 			t.Error("testN=64", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
 		}
+		x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 64)
+		if string(x) != "abc"+test.s {
+			t.Error("AppendFloat testN=64", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x))
+		}
 		if float64(float32(test.f)) == test.f && test.fmt != 'b' {
-			s := Ftoa32(float32(test.f), test.fmt, test.prec)
-			if s != test.s {
-				t.Error("test32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
-			}
-			s = FtoaN(test.f, test.fmt, test.prec, 32)
+			s := FormatFloat(test.f, test.fmt, test.prec, 32)
 			if s != test.s {
 				t.Error("testN=32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
 			}
+			x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 32)
+			if string(x) != "abc"+test.s {
+				t.Error("AppendFloat testN=32", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x))
+			}
+		}
+	}
+}
+
+func TestFtoaRandom(t *testing.T) {
+	N := int(1e4)
+	if testing.Short() {
+		N = 100
+	}
+	t.Logf("testing %d random numbers with fast and slow FormatFloat", N)
+	for i := 0; i < N; i++ {
+		bits := uint64(rand.Uint32())<<32 | uint64(rand.Uint32())
+		x := math.Float64frombits(bits)
+		shortFast := FormatFloat(x, 'g', -1, 64)
+		SetOptimize(false)
+		shortSlow := FormatFloat(x, 'g', -1, 64)
+		SetOptimize(true)
+		if shortSlow != shortFast {
+			t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow)
 		}
 	}
 }
+
+func TestAppendFloatDoesntAllocate(t *testing.T) {
+	n := numAllocations(func() {
+		var buf [64]byte
+		AppendFloat(buf[:0], 1.23, 'g', 5, 64)
+	})
+	want := 1 // TODO(bradfitz): this might be 0, once escape analysis is better
+	if n != want {
+		t.Errorf("with local buffer, did %d allocations, want %d", n, want)
+	}
+	n = numAllocations(func() {
+		AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64)
+	})
+	if n != 0 {
+		t.Errorf("with reused buffer, did %d allocations, want 0", n)
+	}
+}
+
+func BenchmarkFormatFloatDecimal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(33909, 'g', -1, 64)
+	}
+}
+
+func BenchmarkFormatFloat(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(339.7784, 'g', -1, 64)
+	}
+}
+
+func BenchmarkFormatFloatExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(-5.09e75, 'g', -1, 64)
+	}
+}
+
+func BenchmarkFormatFloatNegExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(-5.11e-95, 'g', -1, 64)
+	}
+}
+
+func BenchmarkFormatFloatBig(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		FormatFloat(123456789123456789123456789, 'g', -1, 64)
+	}
+}
+
+func BenchmarkAppendFloatDecimal(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		AppendFloat(dst, 33909, 'g', -1, 64)
+	}
+}
+
+func BenchmarkAppendFloat(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		AppendFloat(dst, 339.7784, 'g', -1, 64)
+	}
+}
+
+func BenchmarkAppendFloatExp(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		AppendFloat(dst, -5.09e75, 'g', -1, 64)
+	}
+}
+
+func BenchmarkAppendFloatNegExp(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		AppendFloat(dst, -5.11e-95, 'g', -1, 64)
+	}
+}
+
+func BenchmarkAppendFloatBig(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		AppendFloat(dst, 123456789123456789123456789, 'g', -1, 64)
+	}
+}
diff --git a/src/pkg/strconv/internal_test.go b/src/pkg/strconv/internal_test.go
index 9a7f4f0..d0fa80e 100644
--- a/src/pkg/strconv/internal_test.go
+++ b/src/pkg/strconv/internal_test.go
@@ -6,7 +6,11 @@
 
 package strconv
 
-func NewDecimal(i uint64) *decimal { return newDecimal(i) }
+func NewDecimal(i uint64) *decimal {
+	d := new(decimal)
+	d.Assign(i)
+	return d
+}
 
 func SetOptimize(b bool) bool {
 	old := optimize
diff --git a/src/pkg/strconv/itoa.go b/src/pkg/strconv/itoa.go
index a0a7496..ca40dd7 100644
--- a/src/pkg/strconv/itoa.go
+++ b/src/pkg/strconv/itoa.go
@@ -4,54 +4,124 @@
 
 package strconv
 
-// Uitob64 returns the string representation of i in the given base.
-func Uitob64(u uint64, base uint) string {
-	if base < 2 || 36 < base {
-		panic("invalid base " + Uitoa(base))
-	}
-	if u == 0 {
-		return "0"
-	}
+// FormatUint returns the string representation of i in the given base.
+func FormatUint(i uint64, base int) string {
+	_, s := formatBits(nil, i, base, false, false)
+	return s
+}
 
-	// Assemble decimal in reverse order.
-	var buf [64]byte
-	j := len(buf)
-	b := uint64(base)
-	for u > 0 {
-		j--
-		buf[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[u%b]
-		u /= b
-	}
+// FormatInt returns the string representation of i in the given base.
+func FormatInt(i int64, base int) string {
+	_, s := formatBits(nil, uint64(i), base, i < 0, false)
+	return s
+}
+
+// Itoa is shorthand for FormatInt(i, 10).
+func Itoa(i int) string {
+	return FormatInt(int64(i), 10)
+}
+
+// AppendInt appends the string form of the integer i,
+// as generated by FormatInt, to dst and returns the extended buffer.
+func AppendInt(dst []byte, i int64, base int) []byte {
+	dst, _ = formatBits(dst, uint64(i), base, i < 0, true)
+	return dst
+}
 
-	return string(buf[j:])
+// AppendUint appends the string form of the unsigned integer i,
+// as generated by FormatUint, to dst and returns the extended buffer.
+func AppendUint(dst []byte, i uint64, base int) []byte {
+	dst, _ = formatBits(dst, i, base, false, true)
+	return dst
 }
 
-// Itob64 returns the string representation of i in the given base.
-func Itob64(i int64, base uint) string {
-	if i == 0 {
-		return "0"
+const (
+	digits   = "0123456789abcdefghijklmnopqrstuvwxyz"
+	digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+	digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
+)
+
+var shifts = [len(digits) + 1]uint{
+	1 << 1: 1,
+	1 << 2: 2,
+	1 << 3: 3,
+	1 << 4: 4,
+	1 << 5: 5,
+}
+
+// formatBits computes the string representation of u in the given base.
+// If neg is set, u is treated as negative int64 value. If append_ is
+// set, the string is appended to dst and the resulting byte slice is
+// returned as the first result value; otherwise the string is returned
+// as the second result value.
+//
+func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) {
+	if base < 2 || base > len(digits) {
+		panic("strconv: illegal AppendInt/FormatInt base")
 	}
+	// 2 <= base && base <= len(digits)
 
-	if i < 0 {
-		return "-" + Uitob64(-uint64(i), base)
+	var a [64 + 1]byte // +1 for sign of 64bit value in base 2
+	i := len(a)
+
+	if neg {
+		u = -u
 	}
-	return Uitob64(uint64(i), base)
-}
 
-// Itoa64 returns the decimal string representation of i.
-func Itoa64(i int64) string { return Itob64(i, 10) }
+	// convert bits
+	if base == 10 {
+		// common case: use constants for / and % because
+		// the compiler can optimize it into a multiply+shift,
+		// and unroll loop
+		for u >= 100 {
+			i -= 2
+			q := u / 100
+			j := uintptr(u - q*100)
+			a[i+1] = digits01[j]
+			a[i+0] = digits10[j]
+			u = q
+		}
+		if u >= 10 {
+			i--
+			q := u / 10
+			a[i] = digits[uintptr(u-q*10)]
+			u = q
+		}
 
-// Uitoa64 returns the decimal string representation of i.
-func Uitoa64(i uint64) string { return Uitob64(i, 10) }
+	} else if s := shifts[base]; s > 0 {
+		// base is power of 2: use shifts and masks instead of / and %
+		b := uint64(base)
+		m := uintptr(b) - 1 // == 1<<s - 1
+		for u >= b {
+			i--
+			a[i] = digits[uintptr(u)&m]
+			u >>= s
+		}
 
-// Uitob returns the string representation of i in the given base.
-func Uitob(i uint, base uint) string { return Uitob64(uint64(i), base) }
+	} else {
+		// general case
+		b := uint64(base)
+		for u >= b {
+			i--
+			a[i] = digits[uintptr(u%b)]
+			u /= b
+		}
+	}
 
-// Itob returns the string representation of i in the given base.
-func Itob(i int, base uint) string { return Itob64(int64(i), base) }
+	// u < base
+	i--
+	a[i] = digits[uintptr(u)]
 
-// Itoa returns the decimal string representation of i.
-func Itoa(i int) string { return Itob64(int64(i), 10) }
+	// add sign, if any
+	if neg {
+		i--
+		a[i] = '-'
+	}
 
-// Uitoa returns the decimal string representation of i.
-func Uitoa(i uint) string { return Uitob64(uint64(i), 10) }
+	if append_ {
+		d = append(dst, a[i:]...)
+		return
+	}
+	s = string(a[i:])
+	return
+}
diff --git a/src/pkg/strconv/itoa_test.go b/src/pkg/strconv/itoa_test.go
index 8514b21..d4b09a5 100644
--- a/src/pkg/strconv/itoa_test.go
+++ b/src/pkg/strconv/itoa_test.go
@@ -5,13 +5,14 @@
 package strconv_test
 
 import (
+	"runtime"
 	. "strconv"
 	"testing"
 )
 
 type itob64Test struct {
 	in   int64
-	base uint
+	base int
 	out  string
 }
 
@@ -60,73 +61,43 @@ var itob64tests = []itob64Test{
 
 func TestItoa(t *testing.T) {
 	for _, test := range itob64tests {
-		s := Itob64(test.in, test.base)
+		s := FormatInt(test.in, test.base)
 		if s != test.out {
-			t.Errorf("Itob64(%v, %v) = %v want %v",
+			t.Errorf("FormatInt(%v, %v) = %v want %v",
 				test.in, test.base, s, test.out)
 		}
-
-		if test.in >= 0 {
-			s := Uitob64(uint64(test.in), test.base)
-			if s != test.out {
-				t.Errorf("Uitob64(%v, %v) = %v want %v",
-					test.in, test.base, s, test.out)
-			}
+		x := AppendInt([]byte("abc"), test.in, test.base)
+		if string(x) != "abc"+test.out {
+			t.Errorf("AppendInt(%q, %v, %v) = %q want %v",
+				"abc", test.in, test.base, x, test.out)
 		}
 
-		if int64(int(test.in)) == test.in {
-			s := Itob(int(test.in), test.base)
+		if test.in >= 0 {
+			s := FormatUint(uint64(test.in), test.base)
 			if s != test.out {
-				t.Errorf("Itob(%v, %v) = %v want %v",
+				t.Errorf("FormatUint(%v, %v) = %v want %v",
 					test.in, test.base, s, test.out)
 			}
-
-			if test.in >= 0 {
-				s := Uitob(uint(test.in), test.base)
-				if s != test.out {
-					t.Errorf("Uitob(%v, %v) = %v want %v",
-						test.in, test.base, s, test.out)
-				}
+			x := AppendUint(nil, uint64(test.in), test.base)
+			if string(x) != test.out {
+				t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
+					"abc", uint64(test.in), test.base, x, test.out)
 			}
 		}
 
-		if test.base == 10 {
-			s := Itoa64(test.in)
+		if test.base == 10 && int64(int(test.in)) == test.in {
+			s := Itoa(int(test.in))
 			if s != test.out {
-				t.Errorf("Itoa64(%v) = %v want %v",
+				t.Errorf("Itoa(%v) = %v want %v",
 					test.in, s, test.out)
 			}
-
-			if test.in >= 0 {
-				s := Uitob64(uint64(test.in), test.base)
-				if s != test.out {
-					t.Errorf("Uitob64(%v, %v) = %v want %v",
-						test.in, test.base, s, test.out)
-				}
-			}
-
-			if int64(int(test.in)) == test.in {
-				s := Itoa(int(test.in))
-				if s != test.out {
-					t.Errorf("Itoa(%v) = %v want %v",
-						test.in, s, test.out)
-				}
-
-				if test.in >= 0 {
-					s := Uitoa(uint(test.in))
-					if s != test.out {
-						t.Errorf("Uitoa(%v) = %v want %v",
-							test.in, s, test.out)
-					}
-				}
-			}
 		}
 	}
 }
 
 type uitob64Test struct {
 	in   uint64
-	base uint
+	base int
 	out  string
 }
 
@@ -141,34 +112,77 @@ var uitob64tests = []uitob64Test{
 
 func TestUitoa(t *testing.T) {
 	for _, test := range uitob64tests {
-		s := Uitob64(test.in, test.base)
+		s := FormatUint(test.in, test.base)
 		if s != test.out {
-			t.Errorf("Uitob64(%v, %v) = %v want %v",
+			t.Errorf("FormatUint(%v, %v) = %v want %v",
 				test.in, test.base, s, test.out)
 		}
+		x := AppendUint([]byte("abc"), test.in, test.base)
+		if string(x) != "abc"+test.out {
+			t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
+				"abc", test.in, test.base, x, test.out)
+		}
 
-		if uint64(uint(test.in)) == test.in {
-			s := Uitob(uint(test.in), test.base)
-			if s != test.out {
-				t.Errorf("Uitob(%v, %v) = %v want %v",
-					test.in, test.base, s, test.out)
-			}
+	}
+}
+
+func numAllocations(f func()) int {
+	runtime.UpdateMemStats()
+	n0 := runtime.MemStats.Mallocs
+	f()
+	runtime.UpdateMemStats()
+	return int(runtime.MemStats.Mallocs - n0)
+}
+
+var globalBuf [64]byte
+
+func TestAppendUintDoesntAllocate(t *testing.T) {
+	n := numAllocations(func() {
+		var buf [64]byte
+		AppendInt(buf[:0], 123, 10)
+	})
+	want := 1 // TODO(bradfitz): this might be 0, once escape analysis is better
+	if n != want {
+		t.Errorf("with local buffer, did %d allocations, want %d", n, want)
+	}
+	n = numAllocations(func() {
+		AppendInt(globalBuf[:0], 123, 10)
+	})
+	if n != 0 {
+		t.Errorf("with reused buffer, did %d allocations, want 0", n)
+	}
+}
+
+func BenchmarkFormatInt(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, test := range itob64tests {
+			FormatInt(test.in, test.base)
 		}
+	}
+}
 
-		if test.base == 10 {
-			s := Uitoa64(test.in)
-			if s != test.out {
-				t.Errorf("Uitoa64(%v) = %v want %v",
-					test.in, s, test.out)
-			}
+func BenchmarkAppendInt(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		for _, test := range itob64tests {
+			AppendInt(dst, test.in, test.base)
+		}
+	}
+}
 
-			if uint64(uint(test.in)) == test.in {
-				s := Uitoa(uint(test.in))
-				if s != test.out {
-					t.Errorf("Uitoa(%v) = %v want %v",
-						test.in, s, test.out)
-				}
-			}
+func BenchmarkFormatUint(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, test := range uitob64tests {
+			FormatUint(test.in, test.base)
+		}
+	}
+}
+
+func BenchmarkAppendUint(b *testing.B) {
+	dst := make([]byte, 0, 30)
+	for i := 0; i < b.N; i++ {
+		for _, test := range uitob64tests {
+			AppendUint(dst, test.in, test.base)
 		}
 	}
 }
diff --git a/src/pkg/strconv/quote.go b/src/pkg/strconv/quote.go
index 05e49d3..61dbcae 100644
--- a/src/pkg/strconv/quote.go
+++ b/src/pkg/strconv/quote.go
@@ -6,10 +6,9 @@ package strconv
 
 import (
 	"bytes"
-	"os"
 	"strings"
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 const lowerhex = "0123456789abcdef"
@@ -18,32 +17,32 @@ func quoteWith(s string, quote byte, ASCIIonly bool) string {
 	var buf bytes.Buffer
 	buf.WriteByte(quote)
 	for width := 0; len(s) > 0; s = s[width:] {
-		rune := int(s[0])
+		r := rune(s[0])
 		width = 1
-		if rune >= utf8.RuneSelf {
-			rune, width = utf8.DecodeRuneInString(s)
+		if r >= utf8.RuneSelf {
+			r, width = utf8.DecodeRuneInString(s)
 		}
-		if width == 1 && rune == utf8.RuneError {
+		if width == 1 && r == utf8.RuneError {
 			buf.WriteString(`\x`)
 			buf.WriteByte(lowerhex[s[0]>>4])
 			buf.WriteByte(lowerhex[s[0]&0xF])
 			continue
 		}
-		if rune == int(quote) || rune == '\\' { // always backslashed
+		if r == rune(quote) || r == '\\' { // always backslashed
 			buf.WriteByte('\\')
-			buf.WriteByte(byte(rune))
+			buf.WriteByte(byte(r))
 			continue
 		}
 		if ASCIIonly {
-			if rune <= unicode.MaxASCII && unicode.IsPrint(rune) {
-				buf.WriteRune(rune)
+			if r <= unicode.MaxASCII && unicode.IsPrint(r) {
+				buf.WriteRune(r)
 				continue
 			}
-		} else if unicode.IsPrint(rune) {
-			buf.WriteRune(rune)
+		} else if unicode.IsPrint(r) {
+			buf.WriteRune(r)
 			continue
 		}
-		switch rune {
+		switch r {
 		case '\a':
 			buf.WriteString(`\a`)
 		case '\b':
@@ -60,22 +59,22 @@ func quoteWith(s string, quote byte, ASCIIonly bool) string {
 			buf.WriteString(`\v`)
 		default:
 			switch {
-			case rune < ' ':
+			case r < ' ':
 				buf.WriteString(`\x`)
 				buf.WriteByte(lowerhex[s[0]>>4])
 				buf.WriteByte(lowerhex[s[0]&0xF])
-			case rune > unicode.MaxRune:
-				rune = 0xFFFD
+			case r > unicode.MaxRune:
+				r = 0xFFFD
 				fallthrough
-			case rune < 0x10000:
+			case r < 0x10000:
 				buf.WriteString(`\u`)
 				for s := 12; s >= 0; s -= 4 {
-					buf.WriteByte(lowerhex[rune>>uint(s)&0xF])
+					buf.WriteByte(lowerhex[r>>uint(s)&0xF])
 				}
 			default:
 				buf.WriteString(`\U`)
 				for s := 28; s >= 0; s -= 4 {
-					buf.WriteByte(lowerhex[rune>>uint(s)&0xF])
+					buf.WriteByte(lowerhex[r>>uint(s)&0xF])
 				}
 			}
 		}
@@ -93,6 +92,12 @@ func Quote(s string) string {
 	return quoteWith(s, '"', false)
 }
 
+// AppendQuote appends a double-quoted Go string literal representing s,
+// as generated by Quote, to dst and returns the extended buffer.
+func AppendQuote(dst []byte, s string) []byte {
+	return append(dst, Quote(s)...)
+}
+
 // QuoteToASCII returns a double-quoted Go string literal representing s.
 // The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
 // non-ASCII characters and non-printable characters as defined by
@@ -101,22 +106,40 @@ func QuoteToASCII(s string) string {
 	return quoteWith(s, '"', true)
 }
 
+// AppendQuoteToASCII appends a double-quoted Go string literal representing s,
+// as generated by QuoteToASCII, to dst and returns the extended buffer.
+func AppendQuoteToASCII(dst []byte, s string) []byte {
+	return append(dst, QuoteToASCII(s)...)
+}
+
 // QuoteRune returns a single-quoted Go character literal representing the
 // rune.  The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)
 // for control characters and non-printable characters as defined by
 // unicode.IsPrint.
-func QuoteRune(rune int) string {
+func QuoteRune(r rune) string {
 	// TODO: avoid the allocation here.
-	return quoteWith(string(rune), '\'', false)
+	return quoteWith(string(r), '\'', false)
+}
+
+// AppendQuoteRune appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRune, to dst and returns the extended buffer.
+func AppendQuoteRune(dst []byte, r rune) []byte {
+	return append(dst, QuoteRune(r)...)
 }
 
 // QuoteRuneToASCII returns a single-quoted Go character literal representing
 // the rune.  The returned string uses Go escape sequences (\t, \n, \xFF,
 // \u0100) for non-ASCII characters and non-printable characters as defined
 // by unicode.IsPrint.
-func QuoteRuneToASCII(rune int) string {
+func QuoteRuneToASCII(r rune) string {
 	// TODO: avoid the allocation here.
-	return quoteWith(string(rune), '\'', true)
+	return quoteWith(string(r), '\'', true)
+}
+
+// AppendQuoteRune appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRuneToASCII, to dst and returns the extended buffer.
+func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
+	return append(dst, QuoteRuneToASCII(r)...)
 }
 
 // CanBackquote returns whether the string s would be
@@ -130,8 +153,8 @@ func CanBackquote(s string) bool {
 	return true
 }
 
-func unhex(b byte) (v int, ok bool) {
-	c := int(b)
+func unhex(b byte) (v rune, ok bool) {
+	c := rune(b)
 	switch {
 	case '0' <= c && c <= '9':
 		return c - '0', true
@@ -157,22 +180,22 @@ func unhex(b byte) (v int, ok bool) {
 // If set to a single quote, it permits the sequence \' and disallows unescaped '.
 // If set to a double quote, it permits \" and disallows unescaped ".
 // If set to zero, it does not permit either escape and allows both quote characters to appear unescaped.
-func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string, err os.Error) {
+func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
 	// easy cases
 	switch c := s[0]; {
 	case c == quote && (quote == '\'' || quote == '"'):
-		err = os.EINVAL
+		err = ErrSyntax
 		return
 	case c >= utf8.RuneSelf:
 		r, size := utf8.DecodeRuneInString(s)
 		return r, true, s[size:], nil
 	case c != '\\':
-		return int(s[0]), false, s[1:], nil
+		return rune(s[0]), false, s[1:], nil
 	}
 
 	// hard case: c is backslash
 	if len(s) <= 1 {
-		err = os.EINVAL
+		err = ErrSyntax
 		return
 	}
 	c := s[1]
@@ -203,15 +226,15 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
 		case 'U':
 			n = 8
 		}
-		v := 0
+		var v rune
 		if len(s) < n {
-			err = os.EINVAL
+			err = ErrSyntax
 			return
 		}
 		for j := 0; j < n; j++ {
 			x, ok := unhex(s[j])
 			if !ok {
-				err = os.EINVAL
+				err = ErrSyntax
 				return
 			}
 			v = v<<4 | x
@@ -223,27 +246,28 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
 			break
 		}
 		if v > unicode.MaxRune {
-			err = os.EINVAL
+			err = ErrSyntax
 			return
 		}
 		value = v
 		multibyte = true
 	case '0', '1', '2', '3', '4', '5', '6', '7':
-		v := int(c) - '0'
+		v := rune(c) - '0'
 		if len(s) < 2 {
-			err = os.EINVAL
+			err = ErrSyntax
 			return
 		}
 		for j := 0; j < 2; j++ { // one digit already; two more
-			x := int(s[j]) - '0'
+			x := rune(s[j]) - '0'
 			if x < 0 || x > 7 {
+				err = ErrSyntax
 				return
 			}
 			v = (v << 3) | x
 		}
 		s = s[2:]
 		if v > 255 {
-			err = os.EINVAL
+			err = ErrSyntax
 			return
 		}
 		value = v
@@ -251,12 +275,12 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
 		value = '\\'
 	case '\'', '"':
 		if c != quote {
-			err = os.EINVAL
+			err = ErrSyntax
 			return
 		}
-		value = int(c)
+		value = rune(c)
 	default:
-		err = os.EINVAL
+		err = ErrSyntax
 		return
 	}
 	tail = s
@@ -268,25 +292,41 @@ func UnquoteChar(s string, quote byte) (value int, multibyte bool, tail string,
 // that s quotes.  (If s is single-quoted, it would be a Go
 // character literal; Unquote returns the corresponding
 // one-character string.)
-func Unquote(s string) (t string, err os.Error) {
+func Unquote(s string) (t string, err error) {
 	n := len(s)
 	if n < 2 {
-		return "", os.EINVAL
+		return "", ErrSyntax
 	}
 	quote := s[0]
 	if quote != s[n-1] {
-		return "", os.EINVAL
+		return "", ErrSyntax
 	}
 	s = s[1 : n-1]
 
 	if quote == '`' {
 		if strings.Contains(s, "`") {
-			return "", os.EINVAL
+			return "", ErrSyntax
 		}
 		return s, nil
 	}
 	if quote != '"' && quote != '\'' {
-		return "", os.EINVAL
+		return "", ErrSyntax
+	}
+	if strings.Index(s, "\n") >= 0 {
+		return "", ErrSyntax
+	}
+
+	// Is it trivial?  Avoid allocation.
+	if strings.Index(s, `\`) < 0 && strings.IndexRune(s, rune(quote)) < 0 {
+		switch quote {
+		case '"':
+			return s, nil
+		case '\'':
+			r, size := utf8.DecodeRuneInString(s)
+			if size == len(s) && (r != utf8.RuneError || size != 1) {
+				return s, nil
+			}
+		}
 	}
 
 	var buf bytes.Buffer
@@ -303,7 +343,7 @@ func Unquote(s string) (t string, err os.Error) {
 		}
 		if quote == '\'' && len(s) != 0 {
 			// single-quoted must be single character
-			return "", os.EINVAL
+			return "", ErrSyntax
 		}
 	}
 	return buf.String(), nil
diff --git a/src/pkg/strconv/quote_test.go b/src/pkg/strconv/quote_test.go
index 4d615db..3f544c4 100644
--- a/src/pkg/strconv/quote_test.go
+++ b/src/pkg/strconv/quote_test.go
@@ -5,7 +5,6 @@
 package strconv_test
 
 import (
-	"os"
 	. "strconv"
 	"testing"
 )
@@ -30,6 +29,9 @@ func TestQuote(t *testing.T) {
 		if out := Quote(tt.in); out != tt.out {
 			t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
 		}
+		if out := AppendQuote([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
+			t.Errorf("AppendQuote(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
+		}
 	}
 }
 
@@ -38,11 +40,14 @@ func TestQuoteToASCII(t *testing.T) {
 		if out := QuoteToASCII(tt.in); out != tt.ascii {
 			t.Errorf("QuoteToASCII(%s) = %s, want %s", tt.in, out, tt.ascii)
 		}
+		if out := AppendQuoteToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
+			t.Errorf("AppendQuoteToASCII(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
+		}
 	}
 }
 
 type quoteRuneTest struct {
-	in    int
+	in    rune
 	out   string
 	ascii string
 }
@@ -64,6 +69,9 @@ func TestQuoteRune(t *testing.T) {
 		if out := QuoteRune(tt.in); out != tt.out {
 			t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out)
 		}
+		if out := AppendQuoteRune([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
+			t.Errorf("AppendQuoteRune(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
+		}
 	}
 }
 
@@ -72,6 +80,9 @@ func TestQuoteRuneToASCII(t *testing.T) {
 		if out := QuoteRuneToASCII(tt.in); out != tt.ascii {
 			t.Errorf("QuoteRuneToASCII(%U) = %s, want %s", tt.in, out, tt.ascii)
 		}
+		if out := AppendQuoteRuneToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
+			t.Errorf("AppendQuoteRuneToASCII(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
+		}
 	}
 }
 
@@ -168,6 +179,7 @@ var unquotetests = []unQuoteTest{
 	{"`\\xFF`", `\xFF`},
 	{"`\\377`", `\377`},
 	{"`\\`", `\`},
+	{"`\n`", "\n"},
 	{"`	`", `	`},
 	{"` `", ` `},
 }
@@ -179,7 +191,13 @@ var misquoted = []string{
 	`"'`,
 	`b"`,
 	`"\"`,
+	`"\9"`,
+	`"\19"`,
+	`"\129"`,
 	`'\'`,
+	`'\9'`,
+	`'\19'`,
+	`'\129'`,
 	`'ab'`,
 	`"\x1!"`,
 	`"\U12345678"`,
@@ -189,6 +207,9 @@ var misquoted = []string{
 	"`\"",
 	`"\'"`,
 	`'\"'`,
+	"\"\n\"",
+	"\"\\n\n\"",
+	"'\n'",
 }
 
 func TestUnquote(t *testing.T) {
@@ -206,8 +227,20 @@ func TestUnquote(t *testing.T) {
 	}
 
 	for _, s := range misquoted {
-		if out, err := Unquote(s); out != "" || err != os.EINVAL {
-			t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL)
+		if out, err := Unquote(s); out != "" || err != ErrSyntax {
+			t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", ErrSyntax)
 		}
 	}
 }
+
+func BenchmarkUnquoteEasy(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Unquote(`"Give me a rock, paper and scissors and I will move the world."`)
+	}
+}
+
+func BenchmarkUnquoteHard(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Unquote(`"\x47ive me a \x72ock, \x70aper and \x73cissors and \x49 will move the world."`)
+	}
+}
diff --git a/src/pkg/strings/Makefile b/src/pkg/strings/Makefile
index c1be582..872bb43 100644
--- a/src/pkg/strings/Makefile
+++ b/src/pkg/strings/Makefile
@@ -7,6 +7,7 @@ include ../../Make.inc
 TARG=strings
 GOFILES=\
 	reader.go\
+	replace.go\
 	strings.go\
 
 include ../../Make.pkg
diff --git a/src/pkg/strings/export_test.go b/src/pkg/strings/export_test.go
new file mode 100644
index 0000000..dcfec51
--- /dev/null
+++ b/src/pkg/strings/export_test.go
@@ -0,0 +1,9 @@
+// Copyright 2011 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 strings
+
+func (r *Replacer) Replacer() interface{} {
+	return r.r
+}
diff --git a/src/pkg/strings/reader.go b/src/pkg/strings/reader.go
index eb515de..8ff851f 100644
--- a/src/pkg/strings/reader.go
+++ b/src/pkg/strings/reader.go
@@ -5,8 +5,9 @@
 package strings
 
 import (
-	"os"
-	"utf8"
+	"errors"
+	"io"
+	"unicode/utf8"
 )
 
 // A Reader implements the io.Reader, io.ByteScanner, and
@@ -23,9 +24,9 @@ func (r *Reader) Len() int {
 	return len(r.s) - r.i
 }
 
-func (r *Reader) Read(b []byte) (n int, err os.Error) {
+func (r *Reader) Read(b []byte) (n int, err error) {
 	if r.i >= len(r.s) {
-		return 0, os.EOF
+		return 0, io.EOF
 	}
 	n = copy(b, r.s[r.i:])
 	r.i += n
@@ -33,9 +34,9 @@ func (r *Reader) Read(b []byte) (n int, err os.Error) {
 	return
 }
 
-func (r *Reader) ReadByte() (b byte, err os.Error) {
+func (r *Reader) ReadByte() (b byte, err error) {
 	if r.i >= len(r.s) {
-		return 0, os.EOF
+		return 0, io.EOF
 	}
 	b = r.s[r.i]
 	r.i++
@@ -46,9 +47,9 @@ func (r *Reader) ReadByte() (b byte, err os.Error) {
 // UnreadByte moves the reading position back by one byte.
 // It is an error to call UnreadByte if nothing has been
 // read yet.
-func (r *Reader) UnreadByte() os.Error {
+func (r *Reader) UnreadByte() error {
 	if r.i <= 0 {
-		return os.NewError("strings.Reader: at beginning of string")
+		return errors.New("strings.Reader: at beginning of string")
 	}
 	r.i--
 	r.prevRune = -1
@@ -57,19 +58,19 @@ func (r *Reader) UnreadByte() os.Error {
 
 // ReadRune reads and returns the next UTF-8-encoded
 // Unicode code point from the buffer.
-// If no bytes are available, the error returned is os.EOF.
+// If no bytes are available, the error returned is io.EOF.
 // If the bytes are an erroneous UTF-8 encoding, it
 // consumes one byte and returns U+FFFD, 1.
-func (r *Reader) ReadRune() (rune int, size int, err os.Error) {
+func (r *Reader) ReadRune() (ch rune, size int, err error) {
 	if r.i >= len(r.s) {
-		return 0, 0, os.EOF
+		return 0, 0, io.EOF
 	}
 	r.prevRune = r.i
 	if c := r.s[r.i]; c < utf8.RuneSelf {
 		r.i++
-		return int(c), 1, nil
+		return rune(c), 1, nil
 	}
-	rune, size = utf8.DecodeRuneInString(r.s[r.i:])
+	ch, size = utf8.DecodeRuneInString(r.s[r.i:])
 	r.i += size
 	return
 }
@@ -77,9 +78,9 @@ func (r *Reader) ReadRune() (rune int, size int, err os.Error) {
 // UnreadRune causes the next call to ReadRune to return the same rune
 // as the previous call to ReadRune.
 // The last method called on r must have been ReadRune.
-func (r *Reader) UnreadRune() os.Error {
+func (r *Reader) UnreadRune() error {
 	if r.prevRune < 0 {
-		return os.NewError("strings.Reader: previous operation was not ReadRune")
+		return errors.New("strings.Reader: previous operation was not ReadRune")
 	}
 	r.i = r.prevRune
 	r.prevRune = -1
diff --git a/src/pkg/strings/replace.go b/src/pkg/strings/replace.go
new file mode 100644
index 0000000..f53a96e
--- /dev/null
+++ b/src/pkg/strings/replace.go
@@ -0,0 +1,312 @@
+// Copyright 2011 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 strings
+
+import "io"
+
+// A Replacer replaces a list of strings with replacements.
+type Replacer struct {
+	r replacer
+}
+
+// replacer is the interface that a replacement algorithm needs to implement.
+type replacer interface {
+	Replace(s string) string
+	WriteString(w io.Writer, s string) (n int, err error)
+}
+
+// byteBitmap represents bytes which are sought for replacement.
+// byteBitmap is 256 bits wide, with a bit set for each old byte to be
+// replaced.
+type byteBitmap [256 / 32]uint32
+
+func (m *byteBitmap) set(b byte) {
+	m[b>>5] |= uint32(1 << (b & 31))
+}
+
+// NewReplacer returns a new Replacer from a list of old, new string pairs.
+// Replacements are performed in order, without overlapping matches.
+func NewReplacer(oldnew ...string) *Replacer {
+	if len(oldnew)%2 == 1 {
+		panic("strings.NewReplacer: odd argument count")
+	}
+
+	// Possible implementations.
+	var (
+		bb  byteReplacer
+		bs  byteStringReplacer
+		gen genericReplacer
+	)
+
+	allOldBytes, allNewBytes := true, true
+	for len(oldnew) > 0 {
+		old, new := oldnew[0], oldnew[1]
+		oldnew = oldnew[2:]
+		if len(old) != 1 {
+			allOldBytes = false
+		}
+		if len(new) != 1 {
+			allNewBytes = false
+		}
+
+		// generic
+		gen.p = append(gen.p, pair{old, new})
+
+		// byte -> string
+		if allOldBytes {
+			bs.old.set(old[0])
+			bs.new[old[0]] = []byte(new)
+		}
+
+		// byte -> byte
+		if allOldBytes && allNewBytes {
+			bb.old.set(old[0])
+			bb.new[old[0]] = new[0]
+		}
+	}
+
+	if allOldBytes && allNewBytes {
+		return &Replacer{r: &bb}
+	}
+	if allOldBytes {
+		return &Replacer{r: &bs}
+	}
+	return &Replacer{r: &gen}
+}
+
+// Replace returns a copy of s with all replacements performed.
+func (r *Replacer) Replace(s string) string {
+	return r.r.Replace(s)
+}
+
+// WriteString writes s to w with all replacements performed.
+func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error) {
+	return r.r.WriteString(w, s)
+}
+
+// genericReplacer is the fully generic (and least optimized) algorithm.
+// It's used as a fallback when nothing faster can be used.
+type genericReplacer struct {
+	p []pair
+}
+
+type pair struct{ old, new string }
+
+type appendSliceWriter struct {
+	b []byte
+}
+
+func (w *appendSliceWriter) Write(p []byte) (int, error) {
+	w.b = append(w.b, p...)
+	return len(p), nil
+}
+
+func (r *genericReplacer) Replace(s string) string {
+	// TODO(bradfitz): optimized version
+	n, _ := r.WriteString(discard, s)
+	w := appendSliceWriter{make([]byte, 0, n)}
+	r.WriteString(&w, s)
+	return string(w.b)
+}
+
+func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+	lastEmpty := false // the last replacement was of the empty string
+Input:
+	// TODO(bradfitz): optimized version
+	for i := 0; i < len(s); {
+		for _, p := range r.p {
+			if p.old == "" && lastEmpty {
+				// Don't let old match twice in a row.
+				// (it doesn't advance the input and
+				// would otherwise loop forever)
+				continue
+			}
+			if HasPrefix(s[i:], p.old) {
+				if p.new != "" {
+					wn, err := w.Write([]byte(p.new))
+					n += wn
+					if err != nil {
+						return n, err
+					}
+				}
+				i += len(p.old)
+				lastEmpty = p.old == ""
+				continue Input
+			}
+		}
+		wn, err := w.Write([]byte{s[i]})
+		n += wn
+		if err != nil {
+			return n, err
+		}
+		i++
+	}
+
+	// Final empty match at end.
+	for _, p := range r.p {
+		if p.old == "" {
+			if p.new != "" {
+				wn, err := w.Write([]byte(p.new))
+				n += wn
+				if err != nil {
+					return n, err
+				}
+			}
+			break
+		}
+	}
+
+	return n, nil
+}
+
+// byteReplacer is the implementation that's used when all the "old"
+// and "new" values are single ASCII bytes.
+type byteReplacer struct {
+	// old has a bit set for each old byte that should be replaced.
+	old byteBitmap
+
+	// replacement byte, indexed by old byte. only valid if
+	// corresponding old bit is set.
+	new [256]byte
+}
+
+func (r *byteReplacer) Replace(s string) string {
+	var buf []byte // lazily allocated
+	for i := 0; i < len(s); i++ {
+		b := s[i]
+		if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+			if buf == nil {
+				buf = []byte(s)
+			}
+			buf[i] = r.new[b]
+		}
+	}
+	if buf == nil {
+		return s
+	}
+	return string(buf)
+}
+
+func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+	// TODO(bradfitz): use io.WriteString with slices of s, avoiding allocation.
+	bufsize := 32 << 10
+	if len(s) < bufsize {
+		bufsize = len(s)
+	}
+	buf := make([]byte, bufsize)
+
+	for len(s) > 0 {
+		ncopy := copy(buf, s[:])
+		s = s[ncopy:]
+		for i, b := range buf[:ncopy] {
+			if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+				buf[i] = r.new[b]
+			}
+		}
+		wn, err := w.Write(buf[:ncopy])
+		n += wn
+		if err != nil {
+			return n, err
+		}
+	}
+	return n, nil
+}
+
+// byteStringReplacer is the implementation that's used when all the
+// "old" values are single ASCII bytes but the "new" values vary in
+// size.
+type byteStringReplacer struct {
+	// old has a bit set for each old byte that should be replaced.
+	old byteBitmap
+
+	// replacement string, indexed by old byte. only valid if
+	// corresponding old bit is set.
+	new [256][]byte
+}
+
+func (r *byteStringReplacer) Replace(s string) string {
+	newSize := 0
+	anyChanges := false
+	for i := 0; i < len(s); i++ {
+		b := s[i]
+		if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+			anyChanges = true
+			newSize += len(r.new[b])
+		} else {
+			newSize++
+		}
+	}
+	if !anyChanges {
+		return s
+	}
+	buf := make([]byte, newSize)
+	bi := buf
+	for i := 0; i < len(s); i++ {
+		b := s[i]
+		if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+			n := copy(bi[:], r.new[b])
+			bi = bi[n:]
+		} else {
+			bi[0] = b
+			bi = bi[1:]
+		}
+	}
+	return string(buf)
+}
+
+// WriteString maintains one buffer that's at most 32KB.  The bytes in
+// s are enumerated and the buffer is filled.  If it reaches its
+// capacity or a byte has a replacement, the buffer is flushed to w.
+func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {
+	// TODO(bradfitz): use io.WriteString with slices of s instead.
+	bufsize := 32 << 10
+	if len(s) < bufsize {
+		bufsize = len(s)
+	}
+	buf := make([]byte, bufsize)
+	bi := buf[:0]
+
+	for i := 0; i < len(s); i++ {
+		b := s[i]
+		var new []byte
+		if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+			new = r.new[b]
+		} else {
+			bi = append(bi, b)
+		}
+		if len(bi) == cap(bi) || (len(bi) > 0 && len(new) > 0) {
+			nw, err := w.Write(bi)
+			n += nw
+			if err != nil {
+				return n, err
+			}
+			bi = buf[:0]
+		}
+		if len(new) > 0 {
+			nw, err := w.Write(new)
+			n += nw
+			if err != nil {
+				return n, err
+			}
+		}
+	}
+	if len(bi) > 0 {
+		nw, err := w.Write(bi)
+		n += nw
+		if err != nil {
+			return n, err
+		}
+	}
+	return n, nil
+}
+
+// strings is too low-level to import io/ioutil
+var discard io.Writer = devNull(0)
+
+type devNull int
+
+func (devNull) Write(p []byte) (int, error) {
+	return len(p), nil
+}
diff --git a/src/pkg/strings/replace_test.go b/src/pkg/strings/replace_test.go
new file mode 100644
index 0000000..23c7e2e
--- /dev/null
+++ b/src/pkg/strings/replace_test.go
@@ -0,0 +1,174 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strings_test
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	. "strings"
+	"testing"
+)
+
+var _ = log.Printf
+
+type ReplacerTest struct {
+	r   *Replacer
+	in  string
+	out string
+}
+
+var htmlEscaper = NewReplacer("&", "&", "<", "<", ">", ">", "\"", """)
+
+// The http package's old HTML escaping function.
+func oldhtmlEscape(s string) string {
+	s = Replace(s, "&", "&", -1)
+	s = Replace(s, "<", "<", -1)
+	s = Replace(s, ">", ">", -1)
+	s = Replace(s, "\"", """, -1)
+	s = Replace(s, "'", "'", -1)
+	return s
+}
+
+var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i",
+	"longerst", "most long", "longer", "medium", "long", "short",
+	"X", "Y", "Y", "Z")
+
+var capitalLetters = NewReplacer("a", "A", "b", "B")
+
+var blankToXReplacer = NewReplacer("", "X", "o", "O")
+
+var ReplacerTests = []ReplacerTest{
+	// byte->string
+	{htmlEscaper, "No changes", "No changes"},
+	{htmlEscaper, "I <3 escaping & stuff", "I <3 escaping & stuff"},
+	{htmlEscaper, "&&&", "&&&"},
+
+	// generic
+	{replacer, "fooaaabar", "foo3[aaa]b1[a]r"},
+	{replacer, "long, longerst, longer", "short, most long, medium"},
+	{replacer, "XiX", "YiY"},
+
+	// byte->byte
+	{capitalLetters, "brad", "BrAd"},
+	{capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
+
+	// hitting "" special case
+	{blankToXReplacer, "oo", "XOXOX"},
+}
+
+func TestReplacer(t *testing.T) {
+	for i, tt := range ReplacerTests {
+		if s := tt.r.Replace(tt.in); s != tt.out {
+			t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, tt.out)
+		}
+		var buf bytes.Buffer
+		n, err := tt.r.WriteString(&buf, tt.in)
+		if err != nil {
+			t.Errorf("%d. WriteString: %v", i, err)
+			continue
+		}
+		got := buf.String()
+		if got != tt.out {
+			t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tt.in, got, tt.out)
+			continue
+		}
+		if n != len(tt.out) {
+			t.Errorf("%d. WriteString(%q) wrote correct string but reported %d bytes; want %d (%q)",
+				i, tt.in, n, len(tt.out), tt.out)
+		}
+	}
+}
+
+// pickAlgorithmTest is a test that verifies that given input for a
+// Replacer that we pick the correct algorithm.
+type pickAlgorithmTest struct {
+	r    *Replacer
+	want string // name of algorithm
+}
+
+var pickAlgorithmTests = []pickAlgorithmTest{
+	{capitalLetters, "*strings.byteReplacer"},
+	{NewReplacer("12", "123"), "*strings.genericReplacer"},
+	{NewReplacer("1", "12"), "*strings.byteStringReplacer"},
+	{htmlEscaper, "*strings.byteStringReplacer"},
+}
+
+func TestPickAlgorithm(t *testing.T) {
+	for i, tt := range pickAlgorithmTests {
+		got := fmt.Sprintf("%T", tt.r.Replacer())
+		if got != tt.want {
+			t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want)
+		}
+	}
+}
+
+func BenchmarkGenericMatch(b *testing.B) {
+	str := Repeat("A", 100) + Repeat("B", 100)
+	generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengths forces generic
+	for i := 0; i < b.N; i++ {
+		generic.Replace(str)
+	}
+}
+
+func BenchmarkByteByteNoMatch(b *testing.B) {
+	str := Repeat("A", 100) + Repeat("B", 100)
+	for i := 0; i < b.N; i++ {
+		capitalLetters.Replace(str)
+	}
+}
+
+func BenchmarkByteByteMatch(b *testing.B) {
+	str := Repeat("a", 100) + Repeat("b", 100)
+	for i := 0; i < b.N; i++ {
+		capitalLetters.Replace(str)
+	}
+}
+
+func BenchmarkByteStringMatch(b *testing.B) {
+	str := "<" + Repeat("a", 99) + Repeat("b", 99) + ">"
+	for i := 0; i < b.N; i++ {
+		htmlEscaper.Replace(str)
+	}
+}
+
+func BenchmarkHTMLEscapeNew(b *testing.B) {
+	str := "I <3 to escape HTML & other text too."
+	for i := 0; i < b.N; i++ {
+		htmlEscaper.Replace(str)
+	}
+}
+
+func BenchmarkHTMLEscapeOld(b *testing.B) {
+	str := "I <3 to escape HTML & other text too."
+	for i := 0; i < b.N; i++ {
+		oldhtmlEscape(str)
+	}
+}
+
+// BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces.
+func BenchmarkByteByteReplaces(b *testing.B) {
+	str := Repeat("a", 100) + Repeat("b", 100)
+	for i := 0; i < b.N; i++ {
+		Replace(Replace(str, "a", "A", -1), "b", "B", -1)
+	}
+}
+
+// BenchmarkByteByteMap compares byteByteImpl against Map.
+func BenchmarkByteByteMap(b *testing.B) {
+	str := Repeat("a", 100) + Repeat("b", 100)
+	fn := func(r rune) rune {
+		switch r {
+		case 'a':
+			return 'A'
+		case 'b':
+			return 'B'
+		}
+		return r
+	}
+	for i := 0; i < b.N; i++ {
+		Map(fn, str)
+	}
+}
diff --git a/src/pkg/strings/strings.go b/src/pkg/strings/strings.go
index c547297..b411ba5 100644
--- a/src/pkg/strings/strings.go
+++ b/src/pkg/strings/strings.go
@@ -7,7 +7,7 @@ package strings
 
 import (
 	"unicode"
-	"utf8"
+	"unicode/utf8"
 )
 
 // explode splits s into an array of UTF-8 sequences, one per Unicode character (still strings) up to a maximum of n (n < 0 means no limit).
@@ -21,11 +21,12 @@ func explode(s string, n int) []string {
 		n = l
 	}
 	a := make([]string, n)
-	var size, rune int
+	var size int
+	var ch rune
 	i, cur := 0, 0
 	for ; i+1 < n; i++ {
-		rune, size = utf8.DecodeRuneInString(s[cur:])
-		a[i] = string(rune)
+		ch, size = utf8.DecodeRuneInString(s[cur:])
+		a[i] = string(ch)
 		cur += size
 	}
 	// add the rest, if there is any
@@ -63,7 +64,17 @@ func Count(s, sep string) int {
 
 // Contains returns true if substr is within s.
 func Contains(s, substr string) bool {
-	return Index(s, substr) != -1
+	return Index(s, substr) >= 0
+}
+
+// ContainsAny returns true if any Unicode code points in chars are within s.
+func ContainsAny(s, chars string) bool {
+	return IndexAny(s, chars) >= 0
+}
+
+// ContainsRune returns true if the Unicode code point r is within s.
+func ContainsRune(s string, r rune) bool {
+	return IndexRune(s, r) >= 0
 }
 
 // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
@@ -117,11 +128,11 @@ func LastIndex(s, sep string) int {
 }
 
 // IndexRune returns the index of the first instance of the Unicode code point
-// rune, or -1 if rune is not present in s.
-func IndexRune(s string, rune int) int {
+// r, or -1 if rune is not present in s.
+func IndexRune(s string, r rune) int {
 	switch {
-	case rune < 0x80:
-		b := byte(rune)
+	case r < 0x80:
+		b := byte(r)
 		for i := 0; i < len(s); i++ {
 			if s[i] == b {
 				return i
@@ -129,7 +140,7 @@ func IndexRune(s string, rune int) int {
 		}
 	default:
 		for i, c := range s {
-			if c == rune {
+			if c == r {
 				return i
 			}
 		}
@@ -241,7 +252,7 @@ func Fields(s string) []string {
 // FieldsFunc splits the string s at each run of Unicode code points c satisfying f(c)
 // and returns an array of slices of s. If all code points in s satisfy f(c) or the
 // string is empty, an empty slice is returned.
-func FieldsFunc(s string, f func(int) bool) []string {
+func FieldsFunc(s string, f func(rune) bool) []string {
 	// First count the fields.
 	n := 0
 	inField := false
@@ -268,7 +279,7 @@ func FieldsFunc(s string, f func(int) bool) []string {
 			fieldStart = i
 		}
 	}
-	if fieldStart != -1 { // Last field might end at EOF.
+	if fieldStart >= 0 { // Last field might end at EOF.
 		a[na] = s[fieldStart:]
 	}
 	return a
@@ -310,7 +321,7 @@ func HasSuffix(s, suffix string) bool {
 // Map returns a copy of the string s with all its characters modified
 // according to the mapping function. If mapping returns a negative value, the character is
 // dropped from the string with no replacement.
-func Map(mapping func(rune int) int, s string) string {
+func Map(mapping func(rune) rune, s string) string {
 	// In the worst case, the string can grow when mapped, making
 	// things unpleasant.  But it's so rare we barge in assuming it's
 	// fine.  It could also shrink but that falls out naturally.
@@ -321,18 +332,18 @@ func Map(mapping func(rune int) int, s string) string {
 	var b []byte
 
 	for i, c := range s {
-		rune := mapping(c)
+		r := mapping(c)
 		if b == nil {
-			if rune == c {
+			if r == c {
 				continue
 			}
 			b = make([]byte, maxbytes)
 			nbytes = copy(b, s[:i])
 		}
-		if rune >= 0 {
+		if r >= 0 {
 			wid := 1
-			if rune >= utf8.RuneSelf {
-				wid = utf8.RuneLen(rune)
+			if r >= utf8.RuneSelf {
+				wid = utf8.RuneLen(r)
 			}
 			if nbytes+wid > maxbytes {
 				// Grow the buffer.
@@ -341,7 +352,7 @@ func Map(mapping func(rune int) int, s string) string {
 				copy(nb, b[0:nbytes])
 				b = nb
 			}
-			nbytes += utf8.EncodeRune(b[nbytes:maxbytes], rune)
+			nbytes += utf8.EncodeRune(b[nbytes:maxbytes], r)
 		}
 	}
 	if b == nil {
@@ -375,44 +386,44 @@ func ToTitle(s string) string { return Map(unicode.ToTitle, s) }
 // ToUpperSpecial returns a copy of the string s with all Unicode letters mapped to their
 // upper case, giving priority to the special casing rules.
 func ToUpperSpecial(_case unicode.SpecialCase, s string) string {
-	return Map(func(r int) int { return _case.ToUpper(r) }, s)
+	return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
 }
 
 // ToLowerSpecial returns a copy of the string s with all Unicode letters mapped to their
 // lower case, giving priority to the special casing rules.
 func ToLowerSpecial(_case unicode.SpecialCase, s string) string {
-	return Map(func(r int) int { return _case.ToLower(r) }, s)
+	return Map(func(r rune) rune { return _case.ToLower(r) }, s)
 }
 
 // ToTitleSpecial returns a copy of the string s with all Unicode letters mapped to their
 // title case, giving priority to the special casing rules.
 func ToTitleSpecial(_case unicode.SpecialCase, s string) string {
-	return Map(func(r int) int { return _case.ToTitle(r) }, s)
+	return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
 }
 
 // isSeparator reports whether the rune could mark a word boundary.
 // TODO: update when package unicode captures more of the properties.
-func isSeparator(rune int) bool {
+func isSeparator(r rune) bool {
 	// ASCII alphanumerics and underscore are not separators
-	if rune <= 0x7F {
+	if r <= 0x7F {
 		switch {
-		case '0' <= rune && rune <= '9':
+		case '0' <= r && r <= '9':
 			return false
-		case 'a' <= rune && rune <= 'z':
+		case 'a' <= r && r <= 'z':
 			return false
-		case 'A' <= rune && rune <= 'Z':
+		case 'A' <= r && r <= 'Z':
 			return false
-		case rune == '_':
+		case r == '_':
 			return false
 		}
 		return true
 	}
 	// Letters and digits are not separators
-	if unicode.IsLetter(rune) || unicode.IsDigit(rune) {
+	if unicode.IsLetter(r) || unicode.IsDigit(r) {
 		return false
 	}
 	// Otherwise, all we can do for now is treat spaces as separators.
-	return unicode.IsSpace(rune)
+	return unicode.IsSpace(r)
 }
 
 // BUG(r): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
@@ -425,7 +436,7 @@ func Title(s string) string {
 	// the closure once per rune.
 	prev := ' '
 	return Map(
-		func(r int) int {
+		func(r rune) rune {
 			if isSeparator(prev) {
 				prev = r
 				return unicode.ToTitle(r)
@@ -438,7 +449,7 @@ func Title(s string) string {
 
 // TrimLeftFunc returns a slice of the string s with all leading
 // Unicode code points c satisfying f(c) removed.
-func TrimLeftFunc(s string, f func(r int) bool) string {
+func TrimLeftFunc(s string, f func(rune) bool) string {
 	i := indexFunc(s, f, false)
 	if i == -1 {
 		return ""
@@ -448,7 +459,7 @@ func TrimLeftFunc(s string, f func(r int) bool) string {
 
 // TrimRightFunc returns a slice of the string s with all trailing
 // Unicode code points c satisfying f(c) removed.
-func TrimRightFunc(s string, f func(r int) bool) string {
+func TrimRightFunc(s string, f func(rune) bool) string {
 	i := lastIndexFunc(s, f, false)
 	if i >= 0 && s[i] >= utf8.RuneSelf {
 		_, wid := utf8.DecodeRuneInString(s[i:])
@@ -461,34 +472,34 @@ func TrimRightFunc(s string, f func(r int) bool) string {
 
 // TrimFunc returns a slice of the string s with all leading
 // and trailing Unicode code points c satisfying f(c) removed.
-func TrimFunc(s string, f func(r int) bool) string {
+func TrimFunc(s string, f func(rune) bool) string {
 	return TrimRightFunc(TrimLeftFunc(s, f), f)
 }
 
 // IndexFunc returns the index into s of the first Unicode
 // code point satisfying f(c), or -1 if none do.
-func IndexFunc(s string, f func(r int) bool) int {
+func IndexFunc(s string, f func(rune) bool) int {
 	return indexFunc(s, f, true)
 }
 
 // LastIndexFunc returns the index into s of the last
 // Unicode code point satisfying f(c), or -1 if none do.
-func LastIndexFunc(s string, f func(r int) bool) int {
+func LastIndexFunc(s string, f func(rune) bool) int {
 	return lastIndexFunc(s, f, true)
 }
 
 // indexFunc is the same as IndexFunc except that if
 // truth==false, the sense of the predicate function is
 // inverted.
-func indexFunc(s string, f func(r int) bool, truth bool) int {
+func indexFunc(s string, f func(rune) bool, truth bool) int {
 	start := 0
 	for start < len(s) {
 		wid := 1
-		rune := int(s[start])
-		if rune >= utf8.RuneSelf {
-			rune, wid = utf8.DecodeRuneInString(s[start:])
+		r := rune(s[start])
+		if r >= utf8.RuneSelf {
+			r, wid = utf8.DecodeRuneInString(s[start:])
 		}
-		if f(rune) == truth {
+		if f(r) == truth {
 			return start
 		}
 		start += wid
@@ -499,19 +510,19 @@ func indexFunc(s string, f func(r int) bool, truth bool) int {
 // lastIndexFunc is the same as LastIndexFunc except that if
 // truth==false, the sense of the predicate function is
 // inverted.
-func lastIndexFunc(s string, f func(r int) bool, truth bool) int {
+func lastIndexFunc(s string, f func(rune) bool, truth bool) int {
 	for i := len(s); i > 0; {
-		rune, size := utf8.DecodeLastRuneInString(s[0:i])
+		r, size := utf8.DecodeLastRuneInString(s[0:i])
 		i -= size
-		if f(rune) == truth {
+		if f(r) == truth {
 			return i
 		}
 	}
 	return -1
 }
 
-func makeCutsetFunc(cutset string) func(rune int) bool {
-	return func(rune int) bool { return IndexRune(cutset, rune) != -1 }
+func makeCutsetFunc(cutset string) func(rune) bool {
+	return func(r rune) bool { return IndexRune(cutset, r) >= 0 }
 }
 
 // Trim returns a slice of the string s with all leading and
@@ -583,3 +594,58 @@ func Replace(s, old, new string, n int) string {
 	w += copy(t[w:], s[start:])
 	return string(t[0:w])
 }
+
+// EqualFold reports whether s and t, interpreted as UTF-8 strings,
+// are equal under Unicode case-folding.
+func EqualFold(s, t string) bool {
+	for s != "" && t != "" {
+		// Extract first rune from each string.
+		var sr, tr rune
+		if s[0] < utf8.RuneSelf {
+			sr, s = rune(s[0]), s[1:]
+		} else {
+			r, size := utf8.DecodeRuneInString(s)
+			sr, s = r, s[size:]
+		}
+		if t[0] < utf8.RuneSelf {
+			tr, t = rune(t[0]), t[1:]
+		} else {
+			r, size := utf8.DecodeRuneInString(t)
+			tr, t = r, t[size:]
+		}
+
+		// If they match, keep going; if not, return false.
+
+		// Easy case.
+		if tr == sr {
+			continue
+		}
+
+		// Make sr < tr to simplify what follows.
+		if tr < sr {
+			tr, sr = sr, tr
+		}
+		// Fast check for ASCII.
+		if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
+			// ASCII, and sr is upper case.  tr must be lower case.
+			if tr == sr+'a'-'A' {
+				continue
+			}
+			return false
+		}
+
+		// General case.  SimpleFold(x) returns the next equivalent rune > x
+		// or wraps around to smaller values.
+		r := unicode.SimpleFold(sr)
+		for r != sr && r < tr {
+			r = unicode.SimpleFold(r)
+		}
+		if r == tr {
+			continue
+		}
+		return false
+	}
+
+	// One string is empty.  Are both?
+	return s == t
+}
diff --git a/src/pkg/strings/strings_test.go b/src/pkg/strings/strings_test.go
index 409d4da..54046d6 100644
--- a/src/pkg/strings/strings_test.go
+++ b/src/pkg/strings/strings_test.go
@@ -6,14 +6,13 @@ package strings_test
 
 import (
 	"bytes"
-	"os"
+	"io"
 	"reflect"
-	"strconv"
 	. "strings"
 	"testing"
 	"unicode"
+	"unicode/utf8"
 	"unsafe"
-	"utf8"
 )
 
 func eq(a, b []string) bool {
@@ -120,13 +119,11 @@ func TestLastIndex(t *testing.T)    { runIndexTests(t, LastIndex, "LastIndex", l
 func TestIndexAny(t *testing.T)     { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
 func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) }
 
-type IndexRuneTest struct {
+var indexRuneTests = []struct {
 	s    string
-	rune int
+	rune rune
 	out  int
-}
-
-var indexRuneTests = []IndexRuneTest{
+}{
 	{"a A x", 'A', 2},
 	{"some_text=some_value", '=', 9},
 	{"☺a", 'a', 3},
@@ -145,7 +142,7 @@ const benchmarkString = "some_text=some☺value"
 
 func BenchmarkIndexRune(b *testing.B) {
 	if got := IndexRune(benchmarkString, '☺'); got != 14 {
-		panic("wrong index: got=" + strconv.Itoa(got))
+		b.Fatalf("wrong index: expected 14, got=%d", got)
 	}
 	for i := 0; i < b.N; i++ {
 		IndexRune(benchmarkString, '☺')
@@ -154,7 +151,7 @@ func BenchmarkIndexRune(b *testing.B) {
 
 func BenchmarkIndexRuneFastPath(b *testing.B) {
 	if got := IndexRune(benchmarkString, 'v'); got != 17 {
-		panic("wrong index: got=" + strconv.Itoa(got))
+		b.Fatalf("wrong index: expected 17, got=%d", got)
 	}
 	for i := 0; i < b.N; i++ {
 		IndexRune(benchmarkString, 'v')
@@ -163,20 +160,18 @@ func BenchmarkIndexRuneFastPath(b *testing.B) {
 
 func BenchmarkIndex(b *testing.B) {
 	if got := Index(benchmarkString, "v"); got != 17 {
-		panic("wrong index: got=" + strconv.Itoa(got))
+		b.Fatalf("wrong index: expected 17, got=%d", got)
 	}
 	for i := 0; i < b.N; i++ {
 		Index(benchmarkString, "v")
 	}
 }
 
-type ExplodeTest struct {
+var explodetests = []struct {
 	s string
 	n int
 	a []string
-}
-
-var explodetests = []ExplodeTest{
+}{
 	{"", -1, []string{}},
 	{abcd, 4, []string{"a", "b", "c", "d"}},
 	{faces, 3, []string{"☺", "☻", "☹"}},
@@ -308,15 +303,16 @@ func TestFields(t *testing.T) {
 	}
 }
 
+var FieldsFuncTests = []FieldsTest{
+	{"", []string{}},
+	{"XX", []string{}},
+	{"XXhiXXX", []string{"hi"}},
+	{"aXXbXXXcX", []string{"a", "b", "c"}},
+}
+
 func TestFieldsFunc(t *testing.T) {
-	pred := func(c int) bool { return c == 'X' }
-	var fieldsFuncTests = []FieldsTest{
-		{"", []string{}},
-		{"XX", []string{}},
-		{"XXhiXXX", []string{"hi"}},
-		{"aXXbXXXcX", []string{"a", "b", "c"}},
-	}
-	for _, tt := range fieldsFuncTests {
+	pred := func(c rune) bool { return c == 'X' }
+	for _, tt := range FieldsFuncTests {
 		a := FieldsFunc(tt.s, pred)
 		if !eq(a, tt.a) {
 			t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
@@ -377,31 +373,31 @@ var trimSpaceTests = []StringTest{
 	{"x ☺ ", "x ☺"},
 }
 
-func tenRunes(rune int) string {
-	r := make([]int, 10)
+func tenRunes(ch rune) string {
+	r := make([]rune, 10)
 	for i := range r {
-		r[i] = rune
+		r[i] = ch
 	}
 	return string(r)
 }
 
 // User-defined self-inverse mapping function
-func rot13(rune int) int {
-	step := 13
-	if rune >= 'a' && rune <= 'z' {
-		return ((rune - 'a' + step) % 26) + 'a'
+func rot13(r rune) rune {
+	step := rune(13)
+	if r >= 'a' && r <= 'z' {
+		return ((r - 'a' + step) % 26) + 'a'
 	}
-	if rune >= 'A' && rune <= 'Z' {
-		return ((rune - 'A' + step) % 26) + 'A'
+	if r >= 'A' && r <= 'Z' {
+		return ((r - 'A' + step) % 26) + 'A'
 	}
-	return rune
+	return r
 }
 
 func TestMap(t *testing.T) {
 	// Run a couple of awful growth/shrinkage tests
 	a := tenRunes('a')
 	// 1.  Grow.  This triggers two reallocations in Map.
-	maxRune := func(rune int) int { return unicode.MaxRune }
+	maxRune := func(rune) rune { return unicode.MaxRune }
 	m := Map(maxRune, a)
 	expect := tenRunes(unicode.MaxRune)
 	if m != expect {
@@ -409,7 +405,7 @@ func TestMap(t *testing.T) {
 	}
 
 	// 2. Shrink
-	minRune := func(rune int) int { return 'a' }
+	minRune := func(rune) rune { return 'a' }
 	m = Map(minRune, tenRunes(unicode.MaxRune))
 	expect = a
 	if m != expect {
@@ -431,9 +427,9 @@ func TestMap(t *testing.T) {
 	}
 
 	// 5. Drop
-	dropNotLatin := func(rune int) int {
-		if unicode.Is(unicode.Latin, rune) {
-			return rune
+	dropNotLatin := func(r rune) rune {
+		if unicode.Is(unicode.Latin, r) {
+			return r
 		}
 		return -1
 	}
@@ -444,8 +440,8 @@ func TestMap(t *testing.T) {
 	}
 
 	// 6. Identity
-	identity := func(rune int) int {
-		return rune
+	identity := func(r rune) rune {
+		return r
 	}
 	orig := "Input string that we expect not to be copied."
 	m = Map(identity, orig)
@@ -460,8 +456,8 @@ func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTest
 func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
 
 func BenchmarkMapNoChanges(b *testing.B) {
-	identity := func(rune int) int {
-		return rune
+	identity := func(r rune) rune {
+		return r
 	}
 	for i := 0; i < b.N; i++ {
 		Map(identity, "Some string that won't be modified.")
@@ -491,49 +487,48 @@ func TestSpecialCase(t *testing.T) {
 
 func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
 
-type TrimTest struct {
-	f               func(string, string) string
+var trimTests = []struct {
+	f               string
 	in, cutset, out string
-}
-
-var trimTests = []TrimTest{
-	{Trim, "abba", "a", "bb"},
-	{Trim, "abba", "ab", ""},
-	{TrimLeft, "abba", "ab", ""},
-	{TrimRight, "abba", "ab", ""},
-	{TrimLeft, "abba", "a", "bba"},
-	{TrimRight, "abba", "a", "abb"},
-	{Trim, "<tag>", "<>", "tag"},
-	{Trim, "* listitem", " *", "listitem"},
-	{Trim, `"quote"`, `"`, "quote"},
-	{Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
+}{
+	{"Trim", "abba", "a", "bb"},
+	{"Trim", "abba", "ab", ""},
+	{"TrimLeft", "abba", "ab", ""},
+	{"TrimRight", "abba", "ab", ""},
+	{"TrimLeft", "abba", "a", "bba"},
+	{"TrimRight", "abba", "a", "abb"},
+	{"Trim", "<tag>", "<>", "tag"},
+	{"Trim", "* listitem", " *", "listitem"},
+	{"Trim", `"quote"`, `"`, "quote"},
+	{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
 	//empty string tests
-	{Trim, "abba", "", "abba"},
-	{Trim, "", "123", ""},
-	{Trim, "", "", ""},
-	{TrimLeft, "abba", "", "abba"},
-	{TrimLeft, "", "123", ""},
-	{TrimLeft, "", "", ""},
-	{TrimRight, "abba", "", "abba"},
-	{TrimRight, "", "123", ""},
-	{TrimRight, "", "", ""},
-	{TrimRight, "☺\xc0", "☺", "☺\xc0"},
+	{"Trim", "abba", "", "abba"},
+	{"Trim", "", "123", ""},
+	{"Trim", "", "", ""},
+	{"TrimLeft", "abba", "", "abba"},
+	{"TrimLeft", "", "123", ""},
+	{"TrimLeft", "", "", ""},
+	{"TrimRight", "abba", "", "abba"},
+	{"TrimRight", "", "123", ""},
+	{"TrimRight", "", "", ""},
+	{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
 }
 
 func TestTrim(t *testing.T) {
 	for _, tc := range trimTests {
-		actual := tc.f(tc.in, tc.cutset)
-		var name string
-		switch tc.f {
-		case Trim:
-			name = "Trim"
-		case TrimLeft:
-			name = "TrimLeft"
-		case TrimRight:
-			name = "TrimRight"
+		name := tc.f
+		var f func(string, string) string
+		switch name {
+		case "Trim":
+			f = Trim
+		case "TrimLeft":
+			f = TrimLeft
+		case "TrimRight":
+			f = TrimRight
 		default:
-			t.Error("Undefined trim function")
+			t.Errorf("Undefined trim function %s", name)
 		}
+		actual := f(tc.in, tc.cutset)
 		if actual != tc.out {
 			t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
 		}
@@ -541,7 +536,7 @@ func TestTrim(t *testing.T) {
 }
 
 type predicate struct {
-	f    func(r int) bool
+	f    func(rune) bool
 	name string
 }
 
@@ -549,27 +544,25 @@ var isSpace = predicate{unicode.IsSpace, "IsSpace"}
 var isDigit = predicate{unicode.IsDigit, "IsDigit"}
 var isUpper = predicate{unicode.IsUpper, "IsUpper"}
 var isValidRune = predicate{
-	func(r int) bool {
+	func(r rune) bool {
 		return r != utf8.RuneError
 	},
 	"IsValidRune",
 }
 
-type TrimFuncTest struct {
-	f       predicate
-	in, out string
-}
-
 func not(p predicate) predicate {
 	return predicate{
-		func(r int) bool {
+		func(r rune) bool {
 			return !p.f(r)
 		},
 		"not " + p.name,
 	}
 }
 
-var trimFuncTests = []TrimFuncTest{
+var trimFuncTests = []struct {
+	f       predicate
+	in, out string
+}{
 	{isSpace, space + " hello " + space, "hello"},
 	{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
 	{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
@@ -588,13 +581,11 @@ func TestTrimFunc(t *testing.T) {
 	}
 }
 
-type IndexFuncTest struct {
+var indexFuncTests = []struct {
 	in          string
 	f           predicate
 	first, last int
-}
-
-var indexFuncTests = []IndexFuncTest{
+}{
 	{"", isValidRune, -1, -1},
 	{"abc", isDigit, -1, -1},
 	{"0123", isDigit, 0, 3},
@@ -650,13 +641,13 @@ func equal(m string, s1, s2 string, t *testing.T) bool {
 
 func TestCaseConsistency(t *testing.T) {
 	// Make a string of all the runes.
-	numRunes := unicode.MaxRune + 1
+	numRunes := int(unicode.MaxRune + 1)
 	if testing.Short() {
 		numRunes = 1000
 	}
-	a := make([]int, numRunes)
+	a := make([]rune, numRunes)
 	for i := range a {
-		a[i] = i
+		a[i] = rune(i)
 	}
 	s := string(a)
 	// convert the cases.
@@ -692,12 +683,10 @@ func TestCaseConsistency(t *testing.T) {
 	*/
 }
 
-type RepeatTest struct {
+var RepeatTests = []struct {
 	in, out string
 	count   int
-}
-
-var RepeatTests = []RepeatTest{
+}{
 	{"", "", 0},
 	{"", "", 1},
 	{"", "", 2},
@@ -717,7 +706,7 @@ func TestRepeat(t *testing.T) {
 	}
 }
 
-func runesEqual(a, b []int) bool {
+func runesEqual(a, b []rune) bool {
 	if len(a) != len(b) {
 		return false
 	}
@@ -729,34 +718,32 @@ func runesEqual(a, b []int) bool {
 	return true
 }
 
-type RunesTest struct {
+var RunesTests = []struct {
 	in    string
-	out   []int
+	out   []rune
 	lossy bool
-}
-
-var RunesTests = []RunesTest{
-	{"", []int{}, false},
-	{" ", []int{32}, false},
-	{"ABC", []int{65, 66, 67}, false},
-	{"abc", []int{97, 98, 99}, false},
-	{"\u65e5\u672c\u8a9e", []int{26085, 26412, 35486}, false},
-	{"ab\x80c", []int{97, 98, 0xFFFD, 99}, true},
-	{"ab\xc0c", []int{97, 98, 0xFFFD, 99}, true},
+}{
+	{"", []rune{}, false},
+	{" ", []rune{32}, false},
+	{"ABC", []rune{65, 66, 67}, false},
+	{"abc", []rune{97, 98, 99}, false},
+	{"\u65e5\u672c\u8a9e", []rune{26085, 26412, 35486}, false},
+	{"ab\x80c", []rune{97, 98, 0xFFFD, 99}, true},
+	{"ab\xc0c", []rune{97, 98, 0xFFFD, 99}, true},
 }
 
 func TestRunes(t *testing.T) {
 	for _, tt := range RunesTests {
-		a := []int(tt.in)
+		a := []rune(tt.in)
 		if !runesEqual(a, tt.out) {
-			t.Errorf("[]int(%q) = %v; want %v", tt.in, a, tt.out)
+			t.Errorf("[]rune(%q) = %v; want %v", tt.in, a, tt.out)
 			continue
 		}
 		if !tt.lossy {
 			// can only test reassembly if we didn't lose information
 			s := string(a)
 			if s != tt.in {
-				t.Errorf("string([]int(%q)) = %x; want %x", tt.in, s, tt.in)
+				t.Errorf("string([]rune(%q)) = %x; want %x", tt.in, s, tt.in)
 			}
 		}
 	}
@@ -772,7 +759,7 @@ func TestReadByte(t *testing.T) {
 		var res bytes.Buffer
 		for {
 			b, e := reader.ReadByte()
-			if e == os.EOF {
+			if e == io.EOF {
 				break
 			}
 			if e != nil {
@@ -812,7 +799,7 @@ func TestReadRune(t *testing.T) {
 		res := ""
 		for {
 			r, z, e := reader.ReadRune()
-			if e == os.EOF {
+			if e == io.EOF {
 				break
 			}
 			if e != nil {
@@ -846,14 +833,12 @@ func TestReadRune(t *testing.T) {
 	}
 }
 
-type ReplaceTest struct {
+var ReplaceTests = []struct {
 	in       string
 	old, new string
 	n        int
 	out      string
-}
-
-var ReplaceTests = []ReplaceTest{
+}{
 	{"hello", "l", "L", 0, "hello"},
 	{"hello", "l", "L", -1, "heLLo"},
 	{"hello", "x", "X", -1, "hello"},
@@ -883,11 +868,9 @@ func TestReplace(t *testing.T) {
 	}
 }
 
-type TitleTest struct {
+var TitleTests = []struct {
 	in, out string
-}
-
-var TitleTests = []TitleTest{
+}{
 	{"", ""},
 	{"a", "A"},
 	{" aaa aaa aaa ", " Aaa Aaa Aaa "},
@@ -905,12 +888,10 @@ func TestTitle(t *testing.T) {
 	}
 }
 
-type ContainsTest struct {
+var ContainsTests = []struct {
 	str, substr string
 	expected    bool
-}
-
-var ContainsTests = []ContainsTest{
+}{
 	{"abc", "bc", true},
 	{"abc", "bcd", false},
 	{"abc", "", true},
@@ -925,3 +906,81 @@ func TestContains(t *testing.T) {
 		}
 	}
 }
+
+var ContainsAnyTests = []struct {
+	str, substr string
+	expected    bool
+}{
+	{"", "", false},
+	{"", "a", false},
+	{"", "abc", false},
+	{"a", "", false},
+	{"a", "a", true},
+	{"aaa", "a", true},
+	{"abc", "xyz", false},
+	{"abc", "xcz", true},
+	{"a☺b☻c☹d", "uvw☻xyz", true},
+	{"aRegExp*", ".(|)*+?^$[]", true},
+	{dots + dots + dots, " ", false},
+}
+
+func TestContainsAny(t *testing.T) {
+	for _, ct := range ContainsAnyTests {
+		if ContainsAny(ct.str, ct.substr) != ct.expected {
+			t.Errorf("ContainsAny(%s, %s) = %v, want %v",
+				ct.str, ct.substr, !ct.expected, ct.expected)
+		}
+	}
+}
+
+var ContainsRuneTests = []struct {
+	str      string
+	r        rune
+	expected bool
+}{
+	{"", 'a', false},
+	{"a", 'a', true},
+	{"aaa", 'a', true},
+	{"abc", 'y', false},
+	{"abc", 'c', true},
+	{"a☺b☻c☹d", 'x', false},
+	{"a☺b☻c☹d", '☻', true},
+	{"aRegExp*", '*', true},
+}
+
+func TestContainsRune(t *testing.T) {
+	for _, ct := range ContainsRuneTests {
+		if ContainsRune(ct.str, ct.r) != ct.expected {
+			t.Errorf("ContainsRune(%s, %s) = %v, want %v",
+				ct.str, ct.r, !ct.expected, ct.expected)
+		}
+	}
+}
+
+var EqualFoldTests = []struct {
+	s, t string
+	out  bool
+}{
+	{"abc", "abc", true},
+	{"ABcd", "ABcd", true},
+	{"123abc", "123ABC", true},
+	{"αβδ", "ΑΒΔ", true},
+	{"abc", "xyz", false},
+	{"abc", "XYZ", false},
+	{"abcdefghijk", "abcdefghijX", false},
+	{"abcdefghijk", "abcdefghij\u212A", true},
+	{"abcdefghijK", "abcdefghij\u212A", true},
+	{"abcdefghijkz", "abcdefghij\u212Ay", false},
+	{"abcdefghijKz", "abcdefghij\u212Ay", false},
+}
+
+func TestEqualFold(t *testing.T) {
+	for _, tt := range EqualFoldTests {
+		if out := EqualFold(tt.s, tt.t); out != tt.out {
+			t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out)
+		}
+		if out := EqualFold(tt.t, tt.s); out != tt.out {
+			t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out)
+		}
+	}
+}
diff --git a/src/pkg/sync/atomic/atomic_test.go b/src/pkg/sync/atomic/atomic_test.go
index 02ee24b..ad75576 100644
--- a/src/pkg/sync/atomic/atomic_test.go
+++ b/src/pkg/sync/atomic/atomic_test.go
@@ -1037,7 +1037,7 @@ func TestStoreLoadSeqCst32(t *testing.T) {
 				if my != i && his != i {
 					t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
 				}
-				ack[me][(i-1)%3] = -1
+				StoreInt32(&ack[me][(i-1)%3], -1)
 			}
 			c <- true
 		}(p)
@@ -1078,7 +1078,7 @@ func TestStoreLoadSeqCst64(t *testing.T) {
 				if my != i && his != i {
 					t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
 				}
-				ack[me][(i-1)%3] = -1
+				StoreInt64(&ack[me][(i-1)%3], -1)
 			}
 			c <- true
 		}(p)
diff --git a/src/pkg/sync/mutex.go b/src/pkg/sync/mutex.go
index 2d46c89..4fc0274 100644
--- a/src/pkg/sync/mutex.go
+++ b/src/pkg/sync/mutex.go
@@ -6,6 +6,8 @@
 // exclusion locks.  Other than the Once and WaitGroup types, most are intended
 // for use by low-level library routines.  Higher-level synchronization is
 // better done via channels and communication.
+//
+// Values containing the types defined in this package should not be copied.
 package sync
 
 import (
diff --git a/src/pkg/sync/once_test.go b/src/pkg/sync/once_test.go
index 157a366..37075af 100644
--- a/src/pkg/sync/once_test.go
+++ b/src/pkg/sync/once_test.go
@@ -5,9 +5,9 @@
 package sync_test
 
 import (
+	"runtime"
 	. "sync"
 	"sync/atomic"
-	"runtime"
 	"testing"
 )
 
diff --git a/src/pkg/syscall/Makefile b/src/pkg/syscall/Makefile
index d4dbc38..68a6cd4 100644
--- a/src/pkg/syscall/Makefile
+++ b/src/pkg/syscall/Makefile
@@ -8,7 +8,6 @@ TARG=syscall
 GOFILES=\
 	str.go\
 	syscall.go\
-	syscall_$(GOARCH).go\
 	syscall_$(GOOS).go\
 	syscall_$(GOOS)_$(GOARCH).go\
 	zerrors_$(GOOS)_$(GOARCH).go\
@@ -16,49 +15,72 @@ GOFILES=\
 	zsysnum_$(GOOS)_$(GOARCH).go\
 	ztypes_$(GOOS)_$(GOARCH).go\
 
-GOFILES_freebsd=\
+GOFILES_darwin=\
 	bpf_bsd.go\
+	env_unix.go\
+	exec_bsd.go\
 	exec_unix.go\
 	route_bsd.go\
-	route_freebsd.go\
+	route_darwin.go\
 	sockcmsg_unix.go\
 	syscall_bsd.go\
 	syscall_unix.go\
 
-GOFILES_darwin=\
+GOFILES_freebsd=\
 	bpf_bsd.go\
+	env_unix.go\
+	exec_bsd.go\
 	exec_unix.go\
 	route_bsd.go\
-	route_darwin.go\
+	route_freebsd.go\
 	sockcmsg_unix.go\
 	syscall_bsd.go\
 	syscall_unix.go\
 
 GOFILES_linux=\
+	env_unix.go\
 	exec_unix.go\
+	exec_linux.go\
 	lsf_linux.go\
 	netlink_linux.go\
 	sockcmsg_linux.go\
 	sockcmsg_unix.go\
 	syscall_unix.go\
 
+GOFILES_netbsd=\
+	bpf_bsd.go\
+	env_unix.go\
+	exec_bsd.go\
+	exec_unix.go\
+	route_bsd.go\
+	route_netbsd.go\
+	sockcmsg_unix.go\
+	syscall_bsd.go\
+	syscall_unix.go\
+
 GOFILES_openbsd=\
 	bpf_bsd.go\
+	env_unix.go\
+	exec_bsd.go\
 	exec_unix.go\
 	route_bsd.go\
 	route_openbsd.go\
 	sockcmsg_unix.go\
 	syscall_bsd.go\
 	syscall_unix.go\
+	zsysctl_openbsd.go\
+
+GOFILES_plan9=\
+	env_plan9.go\
+	exec_plan9.go\
 
 GOFILES_windows=\
+	env_windows.go\
 	exec_windows.go\
+	dll_windows.go\
 	zerrors_windows.go\
 	ztypes_windows.go\
 
-GOFILES_plan9=\
-	exec_plan9.go\
-
 OFILES=\
 	asm_$(GOOS)_$(GOARCH).$O\
 
diff --git a/src/pkg/syscall/asm_netbsd_386.s b/src/pkg/syscall/asm_netbsd_386.s
new file mode 100644
index 0000000..ec2065f
--- /dev/null
+++ b/src/pkg/syscall/asm_netbsd_386.s
@@ -0,0 +1,137 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//
+// System call support for 386, NetBSD
+//
+
+// func Syscall(trap int32, a1, a2, a3 int32) (r1, r2, err int32);
+// func Syscall6(trap int32, a1, a2, a3, a4, a5, a6 int32) (r1, r2, err int32);
+// Trap # in AX, args on stack above caller pc.
+
+TEXT	·Syscall(SB),7,$0
+	CALL	runtime·entersyscall(SB)
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$0x80
+	JAE	ok
+	MOVL	$-1, 20(SP)	// r1
+	MOVL	$-1, 24(SP)	// r2
+	MOVL	AX, 28(SP)		// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+ok:
+	MOVL	AX, 20(SP)	// r1
+	MOVL	DX, 24(SP)	// r2
+	MOVL	$0, 28(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall6(SB),7,$0
+	CALL	runtime·entersyscall(SB)
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$0x80
+	JAE	ok6
+	MOVL	$-1, 32(SP)	// r1
+	MOVL	$-1, 36(SP)	// r2
+	MOVL	AX, 40(SP)		// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+ok6:
+	MOVL	AX, 32(SP)	// r1
+	MOVL	DX, 36(SP)	// r2
+	MOVL	$0, 40(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall9(SB),7,$0
+	CALL	runtime·entersyscall(SB)
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$0x80
+	JAE	ok9
+	MOVL	$-1, 44(SP)	// r1
+	MOVL	$-1, 48(SP)	// r2
+	MOVL	AX, 52(SP)		// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+ok9:
+	MOVL	AX, 44(SP)	// r1
+	MOVL	DX, 48(SP)	// r2
+	MOVL	$0, 52(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+
+TEXT ·RawSyscall(SB),7,$0
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$0x80
+	JAE	ok1
+	MOVL	$-1, 20(SP)	// r1
+	MOVL	$-1, 24(SP)	// r2
+	MOVL	AX, 28(SP)		// errno
+	RET
+ok1:
+	MOVL	AX, 20(SP)	// r1
+	MOVL	DX, 24(SP)	// r2
+	MOVL	$0, 28(SP)	// errno
+	RET
+
+TEXT	·RawSyscall6(SB),7,$0
+	MOVL	4(SP), AX	// syscall entry
+	// slide args down on top of system call number
+	LEAL		8(SP), SI
+	LEAL		4(SP), DI
+	CLD
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	MOVSL
+	INT	$0x80
+	JAE	ok2
+	MOVL	$-1, 32(SP)	// r1
+	MOVL	$-1, 36(SP)	// r2
+	MOVL	AX, 40(SP)		// errno
+	RET
+ok2:
+	MOVL	AX, 32(SP)	// r1
+	MOVL	DX, 36(SP)	// r2
+	MOVL	$0, 40(SP)	// errno
+	RET
diff --git a/src/pkg/syscall/asm_netbsd_amd64.s b/src/pkg/syscall/asm_netbsd_amd64.s
new file mode 100644
index 0000000..240e41c
--- /dev/null
+++ b/src/pkg/syscall/asm_netbsd_amd64.s
@@ -0,0 +1,130 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//
+// System call support for AMD64, NetBSD
+//
+
+// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
+// func Syscall6(trap int64, a1, a2, a3, a4, a5, a6 int64) (r1, r2, err int64);
+// func Syscall9(trap int64, a1, a2, a3, a4, a5, a6, a7, a8, a9 int64) (r1, r2, err int64);
+// Trap # in AX, args in DI SI DX, return in AX DX
+
+TEXT	·Syscall(SB),7,$0
+	CALL	runtime·entersyscall(SB)
+	MOVQ	8(SP), AX	// syscall entry
+	MOVQ	16(SP), DI
+	MOVQ	24(SP), SI
+	MOVQ	32(SP), DX
+	MOVQ	$0, R10
+	MOVQ	$0, R8
+	MOVQ	$0, R9
+	SYSCALL
+	JCC	ok
+	MOVQ	$-1, 40(SP)	// r1
+	MOVQ	$0, 48(SP)	// r2
+	MOVQ	AX, 56(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+ok:
+	MOVQ	AX, 40(SP)	// r1
+	MOVQ	DX, 48(SP)	// r2
+	MOVQ	$0, 56(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall6(SB),7,$0
+	CALL	runtime·entersyscall(SB)
+	MOVQ	8(SP), AX	// syscall entry
+	MOVQ	16(SP), DI
+	MOVQ	24(SP), SI
+	MOVQ	32(SP), DX
+	MOVQ	40(SP), R10
+	MOVQ	48(SP), R8
+	MOVQ	56(SP), R9
+	SYSCALL
+	JCC	ok6
+	MOVQ	$-1, 64(SP)	// r1
+	MOVQ	$0, 72(SP)	// r2
+	MOVQ	AX, 80(SP)  	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+ok6:
+	MOVQ	AX, 64(SP)	// r1
+	MOVQ	DX, 72(SP)	// r2
+	MOVQ	$0, 80(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+
+TEXT	·Syscall9(SB),7,$0
+	CALL	runtime·entersyscall(SB)
+	MOVQ	8(SP), AX	// syscall entry
+	MOVQ	16(SP), DI
+	MOVQ	24(SP), SI
+	MOVQ	32(SP), DX
+	MOVQ	40(SP), R10
+	MOVQ	48(SP), R8
+	MOVQ	56(SP), R9
+	MOVQ	64(SP), R11
+	MOVQ	72(SP), R12
+	MOVQ	80(SP), R13
+	SUBQ    $32, SP
+	MOVQ	R11, 8(SP)	// arg 7
+	MOVQ	R12, 16(SP)	// arg 8
+	MOVQ	R13, 24(SP)	// arg 9
+	SYSCALL
+	JCC	ok9
+	ADDQ    $32, SP
+	MOVQ	$-1, 64(SP)	// r1
+	MOVQ	$0, 72(SP)	// r2
+	MOVQ	AX, 80(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+ok9:
+	ADDQ    $32, SP
+	MOVQ	AX, 64(SP)	// r1
+	MOVQ	DX, 72(SP)	// r2
+	MOVQ	$0, 80(SP)	// errno
+	CALL	runtime·exitsyscall(SB)
+	RET
+
+TEXT	·RawSyscall(SB),7,$0
+	MOVQ	16(SP), DI
+	MOVQ	24(SP), SI
+	MOVQ	32(SP), DX
+	MOVQ	$0, R10
+	MOVQ	$0, R8
+	MOVQ	$0, R9
+	MOVQ	8(SP), AX	// syscall entry
+	SYSCALL
+	JCC	ok1
+	MOVQ	$-1, 40(SP)	// r1
+	MOVQ	$0, 48(SP)	// r2
+	MOVQ	AX, 56(SP)	// errno
+	RET
+ok1:
+	MOVQ	AX, 40(SP)	// r1
+	MOVQ	DX, 48(SP)	// r2
+	MOVQ	$0, 56(SP)	// errno
+	RET
+
+TEXT	·RawSyscall6(SB),7,$0
+	MOVQ	16(SP), DI
+	MOVQ	24(SP), SI
+	MOVQ	32(SP), DX
+	MOVQ	40(SP), R10
+	MOVQ	48(SP), R8
+	MOVQ	56(SP), R9
+	MOVQ	8(SP), AX	// syscall entry
+	SYSCALL
+	JCC	ok2
+	MOVQ	$-1, 64(SP)	// r1
+	MOVQ	$0, 72(SP)	// r2
+	MOVQ	AX, 80(SP)	// errno
+	RET
+ok2:
+	MOVQ	AX, 64(SP)	// r1
+	MOVQ	DX, 72(SP)	// r2
+	MOVQ	$0, 80(SP)	// errno
+	RET
diff --git a/src/pkg/syscall/bpf_bsd.go b/src/pkg/syscall/bpf_bsd.go
index 06a2953..f98036c 100644
--- a/src/pkg/syscall/bpf_bsd.go
+++ b/src/pkg/syscall/bpf_bsd.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd openbsd
+// +build darwin freebsd netbsd openbsd
 
 // Berkeley packet filter for BSD variants
 
@@ -20,54 +20,54 @@ func BpfJump(code, k, jt, jf int) *BpfInsn {
 	return &BpfInsn{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
 }
 
-func BpfBuflen(fd int) (int, int) {
+func BpfBuflen(fd int) (int, error) {
 	var l int
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGBLEN, uintptr(unsafe.Pointer(&l)))
-	if e := int(ep); e != 0 {
-		return 0, e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGBLEN, uintptr(unsafe.Pointer(&l)))
+	if err != 0 {
+		return 0, Errno(err)
 	}
-	return l, 0
+	return l, nil
 }
 
-func SetBpfBuflen(fd, l int) (int, int) {
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSBLEN, uintptr(unsafe.Pointer(&l)))
-	if e := int(ep); e != 0 {
-		return 0, e
+func SetBpfBuflen(fd, l int) (int, error) {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSBLEN, uintptr(unsafe.Pointer(&l)))
+	if err != 0 {
+		return 0, Errno(err)
 	}
-	return l, 0
+	return l, nil
 }
 
-func BpfDatalink(fd int) (int, int) {
+func BpfDatalink(fd int) (int, error) {
 	var t int
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGDLT, uintptr(unsafe.Pointer(&t)))
-	if e := int(ep); e != 0 {
-		return 0, e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGDLT, uintptr(unsafe.Pointer(&t)))
+	if err != 0 {
+		return 0, Errno(err)
 	}
-	return t, 0
+	return t, nil
 }
 
-func SetBpfDatalink(fd, t int) (int, int) {
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSDLT, uintptr(unsafe.Pointer(&t)))
-	if e := int(ep); e != 0 {
-		return 0, e
+func SetBpfDatalink(fd, t int) (int, error) {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSDLT, uintptr(unsafe.Pointer(&t)))
+	if err != 0 {
+		return 0, Errno(err)
 	}
-	return t, 0
+	return t, nil
 }
 
-func SetBpfPromisc(fd, m int) int {
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCPROMISC, uintptr(unsafe.Pointer(&m)))
-	if e := int(ep); e != 0 {
-		return e
+func SetBpfPromisc(fd, m int) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCPROMISC, uintptr(unsafe.Pointer(&m)))
+	if err != 0 {
+		return Errno(err)
 	}
-	return 0
+	return nil
 }
 
-func FlushBpf(fd int) int {
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCFLUSH, 0)
-	if e := int(ep); e != 0 {
-		return e
+func FlushBpf(fd int) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCFLUSH, 0)
+	if err != 0 {
+		return Errno(err)
 	}
-	return 0
+	return nil
 }
 
 type ivalue struct {
@@ -75,95 +75,95 @@ type ivalue struct {
 	value int16
 }
 
-func BpfInterface(fd int, name string) (string, int) {
+func BpfInterface(fd int, name string) (string, error) {
 	var iv ivalue
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGETIF, uintptr(unsafe.Pointer(&iv)))
-	if e := int(ep); e != 0 {
-		return "", e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGETIF, uintptr(unsafe.Pointer(&iv)))
+	if err != 0 {
+		return "", Errno(err)
 	}
-	return name, 0
+	return name, nil
 }
 
-func SetBpfInterface(fd int, name string) int {
+func SetBpfInterface(fd int, name string) error {
 	var iv ivalue
 	copy(iv.name[:], []byte(name))
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETIF, uintptr(unsafe.Pointer(&iv)))
-	if e := int(ep); e != 0 {
-		return e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETIF, uintptr(unsafe.Pointer(&iv)))
+	if err != 0 {
+		return Errno(err)
 	}
-	return 0
+	return nil
 }
 
-func BpfTimeout(fd int) (*Timeval, int) {
+func BpfTimeout(fd int) (*Timeval, error) {
 	var tv Timeval
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGRTIMEOUT, uintptr(unsafe.Pointer(&tv)))
-	if e := int(ep); e != 0 {
-		return nil, e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGRTIMEOUT, uintptr(unsafe.Pointer(&tv)))
+	if err != 0 {
+		return nil, Errno(err)
 	}
-	return &tv, 0
+	return &tv, nil
 }
 
-func SetBpfTimeout(fd int, tv *Timeval) int {
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSRTIMEOUT, uintptr(unsafe.Pointer(tv)))
-	if e := int(ep); e != 0 {
-		return e
+func SetBpfTimeout(fd int, tv *Timeval) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSRTIMEOUT, uintptr(unsafe.Pointer(tv)))
+	if err != 0 {
+		return Errno(err)
 	}
-	return 0
+	return nil
 }
 
-func BpfStats(fd int) (*BpfStat, int) {
+func BpfStats(fd int) (*BpfStat, error) {
 	var s BpfStat
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGSTATS, uintptr(unsafe.Pointer(&s)))
-	if e := int(ep); e != 0 {
-		return nil, e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGSTATS, uintptr(unsafe.Pointer(&s)))
+	if err != 0 {
+		return nil, Errno(err)
 	}
-	return &s, 0
+	return &s, nil
 }
 
-func SetBpfImmediate(fd, m int) int {
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCIMMEDIATE, uintptr(unsafe.Pointer(&m)))
-	if e := int(ep); e != 0 {
-		return e
+func SetBpfImmediate(fd, m int) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCIMMEDIATE, uintptr(unsafe.Pointer(&m)))
+	if err != 0 {
+		return Errno(err)
 	}
-	return 0
+	return nil
 }
 
-func SetBpf(fd int, i []BpfInsn) int {
+func SetBpf(fd int, i []BpfInsn) error {
 	var p BpfProgram
 	p.Len = uint32(len(i))
 	p.Insns = (*BpfInsn)(unsafe.Pointer(&i[0]))
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETF, uintptr(unsafe.Pointer(&p)))
-	if e := int(ep); e != 0 {
-		return e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETF, uintptr(unsafe.Pointer(&p)))
+	if err != 0 {
+		return Errno(err)
 	}
-	return 0
+	return nil
 }
 
-func CheckBpfVersion(fd int) int {
+func CheckBpfVersion(fd int) error {
 	var v BpfVersion
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCVERSION, uintptr(unsafe.Pointer(&v)))
-	if e := int(ep); e != 0 {
-		return e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCVERSION, uintptr(unsafe.Pointer(&v)))
+	if err != 0 {
+		return Errno(err)
 	}
 	if v.Major != BPF_MAJOR_VERSION || v.Minor != BPF_MINOR_VERSION {
 		return EINVAL
 	}
-	return 0
+	return nil
 }
 
-func BpfHeadercmpl(fd int) (int, int) {
+func BpfHeadercmpl(fd int) (int, error) {
 	var f int
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGHDRCMPLT, uintptr(unsafe.Pointer(&f)))
-	if e := int(ep); e != 0 {
-		return 0, e
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCGHDRCMPLT, uintptr(unsafe.Pointer(&f)))
+	if err != 0 {
+		return 0, Errno(err)
 	}
-	return f, 0
+	return f, nil
 }
 
-func SetBpfHeadercmpl(fd, f int) int {
-	_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSHDRCMPLT, uintptr(unsafe.Pointer(&f)))
-	if e := int(ep); e != 0 {
-		return e
+func SetBpfHeadercmpl(fd, f int) error {
+	_, _, err := Syscall(SYS_IOCTL, uintptr(fd), BIOCSHDRCMPLT, uintptr(unsafe.Pointer(&f)))
+	if err != 0 {
+		return Errno(err)
 	}
-	return 0
+	return nil
 }
diff --git a/src/pkg/syscall/dll_windows.go b/src/pkg/syscall/dll_windows.go
new file mode 100644
index 0000000..2a45991
--- /dev/null
+++ b/src/pkg/syscall/dll_windows.go
@@ -0,0 +1,249 @@
+// Copyright 2011 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 syscall
+
+import (
+	"sync"
+)
+
+// DLLError describes reasons for DLL load failures.
+type DLLError struct {
+	Err     error
+	ObjName string
+	Msg     string
+}
+
+func (e *DLLError) Error() string { return e.Msg }
+
+// Implemented in ../runtime/windows/syscall.goc.
+func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
+func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
+func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno)
+func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2 uintptr, err Errno)
+func loadlibrary(filename *uint16) (handle, err Errno)
+func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno)
+
+// A DLL implements access to a single DLL.
+type DLL struct {
+	Name   string
+	Handle Handle
+}
+
+// LoadDLL loads DLL file into memory.
+func LoadDLL(name string) (dll *DLL, err error) {
+	h, e := loadlibrary(StringToUTF16Ptr(name))
+	if e != 0 {
+		return nil, &DLLError{
+			Err:     e,
+			ObjName: name,
+			Msg:     "Failed to load " + name + ": " + e.Error(),
+		}
+	}
+	d := &DLL{
+		Name:   name,
+		Handle: Handle(h),
+	}
+	return d, nil
+}
+
+// MustLoadDLL is like LoadDLL but panics if load operation failes.
+func MustLoadDLL(name string) *DLL {
+	d, e := LoadDLL(name)
+	if e != nil {
+		panic(e)
+	}
+	return d
+}
+
+// FindProc searches DLL d for procedure named name and returns *Proc
+// if found. It returns an error if search fails.
+func (d *DLL) FindProc(name string) (proc *Proc, err error) {
+	a, e := getprocaddress(uintptr(d.Handle), StringBytePtr(name))
+	if e != 0 {
+		return nil, &DLLError{
+			Err:     e,
+			ObjName: name,
+			Msg:     "Failed to find " + name + " procedure in " + d.Name + ": " + e.Error(),
+		}
+	}
+	p := &Proc{
+		Dll:  d,
+		Name: name,
+		addr: a,
+	}
+	return p, nil
+}
+
+// MustFindProc is like FindProc but panics if search fails.
+func (d *DLL) MustFindProc(name string) *Proc {
+	p, e := d.FindProc(name)
+	if e != nil {
+		panic(e)
+	}
+	return p
+}
+
+// Release unloads DLL d from memory.
+func (d *DLL) Release() (err error) {
+	return FreeLibrary(d.Handle)
+}
+
+// A Proc implements access to a procedure inside a DLL.
+type Proc struct {
+	Dll  *DLL
+	Name string
+	addr uintptr
+}
+
+// Addr returns the address of the procedure represented by p.
+// The return value can be passed to Syscall to run the procedure.
+func (p *Proc) Addr() uintptr {
+	return p.addr
+}
+
+// Call executes procedure p with arguments a.
+func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, err error) {
+	switch len(a) {
+	case 0:
+		return Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0)
+	case 1:
+		return Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0)
+	case 2:
+		return Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0)
+	case 3:
+		return Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2])
+	case 4:
+		return Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
+	case 5:
+		return Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
+	case 6:
+		return Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
+	case 7:
+		return Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
+	case 8:
+		return Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
+	case 9:
+		return Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
+	case 10:
+		return Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
+	case 11:
+		return Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
+	case 12:
+		return Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
+	case 13:
+		return Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
+	case 14:
+		return Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
+	case 15:
+		return Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
+	default:
+		panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
+	}
+	return
+}
+
+// A LazyDLL implements access to a single DLL.
+// It will delay the load of the DLL until the first
+// call to its Handle method or to one of its
+// LazyProc's Addr method.
+type LazyDLL struct {
+	mu   sync.Mutex
+	dll  *DLL // non nil once DLL is loaded
+	Name string
+}
+
+// Load loads DLL file d.Name into memory. It returns an error if fails.
+// Load will not try to load DLL, if it is already loaded into memory.
+func (d *LazyDLL) Load() error {
+	if d.dll == nil {
+		d.mu.Lock()
+		defer d.mu.Unlock()
+		if d.dll == nil {
+			dll, e := LoadDLL(d.Name)
+			if e != nil {
+				return e
+			}
+			d.dll = dll
+		}
+	}
+	return nil
+}
+
+// mustLoad is like Load but panics if search fails.
+func (d *LazyDLL) mustLoad() {
+	e := d.Load()
+	if e != nil {
+		panic(e)
+	}
+}
+
+// Handle returns d's module handle.
+func (d *LazyDLL) Handle() uintptr {
+	d.mustLoad()
+	return uintptr(d.dll.Handle)
+}
+
+// NewProc returns a LazyProc for accessing the named procedure in the DLL d.
+func (d *LazyDLL) NewProc(name string) *LazyProc {
+	return &LazyProc{l: d, Name: name}
+}
+
+// NewLazyDLL creates new LazyDLL associated with DLL file.
+func NewLazyDLL(name string) *LazyDLL {
+	return &LazyDLL{Name: name}
+}
+
+// A LazyProc implements access to a procedure inside a LazyDLL.
+// It delays the lookup until the Addr method is called.
+type LazyProc struct {
+	mu   sync.Mutex
+	Name string
+	l    *LazyDLL
+	proc *Proc
+}
+
+// Find searches DLL for procedure named p.Name. It returns
+// an error if search fails. Find will not search procedure,
+// if it is already found and loaded into memory.
+func (p *LazyProc) Find() error {
+	if p.proc == nil {
+		p.mu.Lock()
+		defer p.mu.Unlock()
+		if p.proc == nil {
+			e := p.l.Load()
+			if e != nil {
+				return e
+			}
+			proc, e := p.l.dll.FindProc(p.Name)
+			if e != nil {
+				return e
+			}
+			p.proc = proc
+		}
+	}
+	return nil
+}
+
+// mustFind is like Find but panics if search fails.
+func (p *LazyProc) mustFind() {
+	e := p.Find()
+	if e != nil {
+		panic(e)
+	}
+}
+
+// Addr returns the address of the procedure represented by p.
+// The return value can be passed to Syscall to run the procedure.
+func (p *LazyProc) Addr() uintptr {
+	p.mustFind()
+	return p.proc.Addr()
+}
+
+// Call executes procedure p with arguments a.
+func (p *LazyProc) Call(a ...uintptr) (r1, r2 uintptr, err error) {
+	p.mustFind()
+	return p.proc.Call(a...)
+}
diff --git a/src/pkg/syscall/env_plan9.go b/src/pkg/syscall/env_plan9.go
new file mode 100644
index 0000000..5185733
--- /dev/null
+++ b/src/pkg/syscall/env_plan9.go
@@ -0,0 +1,74 @@
+// Copyright 2011 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.
+
+// Plan 9 environment variables.
+
+package syscall
+
+import "errors"
+
+func Getenv(key string) (value string, found bool) {
+	if len(key) == 0 {
+		return "", false
+	}
+	f, e := Open("/env/"+key, O_RDONLY)
+	if e != nil {
+		return "", false
+	}
+	defer Close(f)
+
+	l, _ := Seek(f, 0, 2)
+	Seek(f, 0, 0)
+	buf := make([]byte, l)
+	n, e := Read(f, buf)
+	if e != nil {
+		return "", false
+	}
+
+	if n > 0 && buf[n-1] == 0 {
+		buf = buf[:n-1]
+	}
+	return string(buf), true
+}
+
+func Setenv(key, value string) error {
+	if len(key) == 0 {
+		return errors.New("bad arg in system call")
+	}
+
+	f, e := Create("/env/"+key, O_RDWR, 0666)
+	if e != nil {
+		return e
+	}
+	defer Close(f)
+
+	_, e = Write(f, []byte(value))
+	return nil
+}
+
+func Clearenv() {
+	RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
+}
+
+func Environ() []string {
+	env := make([]string, 0, 100)
+
+	f, e := Open("/env", O_RDONLY)
+	if e != nil {
+		panic(e)
+	}
+	defer Close(f)
+
+	names, e := readdirnames(f)
+	if e != nil {
+		panic(e)
+	}
+
+	for _, k := range names {
+		if v, ok := Getenv(k); ok {
+			env = append(env, k+"="+v)
+		}
+	}
+	return env[0:len(env)]
+}
diff --git a/src/pkg/syscall/env_unix.go b/src/pkg/syscall/env_unix.go
new file mode 100644
index 0000000..8b1868c
--- /dev/null
+++ b/src/pkg/syscall/env_unix.go
@@ -0,0 +1,109 @@
+// Copyright 2010 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 darwin freebsd linux netbsd openbsd
+
+// Unix environment variables.
+
+package syscall
+
+import "sync"
+
+var (
+	// envOnce guards initialization by copyenv, which populates env.
+	envOnce sync.Once
+
+	// envLock guards env and envs.
+	envLock sync.RWMutex
+
+	// env maps from an environment variable to its first occurrence in envs.
+	env map[string]int
+
+	// envs is provided by the runtime. elements are expected to be
+	// of the form "key=value".
+	envs []string
+)
+
+// setenv_c is provided by the runtime, but is a no-op if cgo isn't
+// loaded.
+func setenv_c(k, v string)
+
+func copyenv() {
+	env = make(map[string]int)
+	for i, s := range envs {
+		for j := 0; j < len(s); j++ {
+			if s[j] == '=' {
+				key := s[:j]
+				if _, ok := env[key]; !ok {
+					env[key] = i
+				}
+				break
+			}
+		}
+	}
+}
+
+func Getenv(key string) (value string, found bool) {
+	envOnce.Do(copyenv)
+	if len(key) == 0 {
+		return "", false
+	}
+
+	envLock.RLock()
+	defer envLock.RUnlock()
+
+	i, ok := env[key]
+	if !ok {
+		return "", false
+	}
+	s := envs[i]
+	for i := 0; i < len(s); i++ {
+		if s[i] == '=' {
+			return s[i+1:], true
+		}
+	}
+	return "", false
+}
+
+func Setenv(key, value string) error {
+	envOnce.Do(copyenv)
+	if len(key) == 0 {
+		return EINVAL
+	}
+
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	i, ok := env[key]
+	kv := key + "=" + value
+	if ok {
+		envs[i] = kv
+	} else {
+		i = len(envs)
+		envs = append(envs, kv)
+	}
+	env[key] = i
+	setenv_c(key, value)
+	return nil
+}
+
+func Clearenv() {
+	envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv
+
+	envLock.Lock()
+	defer envLock.Unlock()
+
+	env = make(map[string]int)
+	envs = []string{}
+	// TODO(bradfitz): pass through to C
+}
+
+func Environ() []string {
+	envOnce.Do(copyenv)
+	envLock.RLock()
+	defer envLock.RUnlock()
+	a := make([]string, len(envs))
+	copy(a, envs)
+	return a
+}
diff --git a/src/pkg/syscall/env_windows.go b/src/pkg/syscall/env_windows.go
new file mode 100644
index 0000000..8308f10
--- /dev/null
+++ b/src/pkg/syscall/env_windows.go
@@ -0,0 +1,77 @@
+// Copyright 2010 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.
+
+// Windows environment variables.
+
+package syscall
+
+import (
+	"unicode/utf16"
+	"unsafe"
+)
+
+func Getenv(key string) (value string, found bool) {
+	b := make([]uint16, 100)
+	n, e := GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b)))
+	if n == 0 && e == ERROR_ENVVAR_NOT_FOUND {
+		return "", false
+	}
+	if n > uint32(len(b)) {
+		b = make([]uint16, n)
+		n, e = GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b)))
+		if n > uint32(len(b)) {
+			n = 0
+		}
+	}
+	if n == 0 {
+		return "", false
+	}
+	return string(utf16.Decode(b[0:n])), true
+}
+
+func Setenv(key, value string) error {
+	var v *uint16
+	if len(value) > 0 {
+		v = StringToUTF16Ptr(value)
+	}
+	e := SetEnvironmentVariable(StringToUTF16Ptr(key), v)
+	if e != nil {
+		return e
+	}
+	return nil
+}
+
+func Clearenv() {
+	for _, s := range Environ() {
+		// Environment variables can begin with =
+		// so start looking for the separator = at j=1.
+		// http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
+		for j := 1; j < len(s); j++ {
+			if s[j] == '=' {
+				Setenv(s[0:j], "")
+				break
+			}
+		}
+	}
+}
+
+func Environ() []string {
+	s, e := GetEnvironmentStrings()
+	if e != nil {
+		return nil
+	}
+	defer FreeEnvironmentStrings(s)
+	r := make([]string, 0, 50) // Empty with room to grow.
+	for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(s)); true; i++ {
+		if p[i] == 0 {
+			// empty string marks the end
+			if i <= from {
+				break
+			}
+			r = append(r, string(utf16.Decode(p[from:i])))
+			from = i + 1
+		}
+	}
+	return r
+}
diff --git a/src/pkg/syscall/exec_bsd.go b/src/pkg/syscall/exec_bsd.go
new file mode 100644
index 0000000..fc72c9a
--- /dev/null
+++ b/src/pkg/syscall/exec_bsd.go
@@ -0,0 +1,221 @@
+// Copyright 2011 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 darwin freebsd netbsd openbsd
+
+package syscall
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+type SysProcAttr struct {
+	Chroot     string      // Chroot.
+	Credential *Credential // Credential.
+	Ptrace     bool        // Enable tracing.
+	Setsid     bool        // Create session.
+	Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
+	Setctty    bool        // Set controlling terminal to fd 0
+	Noctty     bool        // Detach fd 0 from controlling terminal
+}
+
+// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
+// If a dup or exec fails, write the errno error to pipe.
+// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
+// In the child, this function must not acquire any locks, because
+// they might have been locked at the time of the fork.  This means
+// no rescheduling, no malloc calls, and no new stack segments.
+// The calls to RawSyscall are okay because they are assembly
+// functions that do not grow the stack.
+func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
+	// Declare all variables at top in case any
+	// declarations require heap allocation (e.g., err1).
+	var (
+		r1, r2 uintptr
+		err1   Errno
+		nextfd int
+		i      int
+	)
+
+	// guard against side effects of shuffling fds below.
+	fd := append([]int(nil), attr.Files...)
+
+	darwin := runtime.GOOS == "darwin"
+
+	// About to call fork.
+	// No more allocation or calls of non-assembly functions.
+	r1, r2, err1 = RawSyscall(SYS_FORK, 0, 0, 0)
+	if err1 != 0 {
+		return 0, err1
+	}
+
+	// On Darwin:
+	//	r1 = child pid in both parent and child.
+	//	r2 = 0 in parent, 1 in child.
+	// Convert to normal Unix r1 = 0 in child.
+	if darwin && r2 == 1 {
+		r1 = 0
+	}
+
+	if r1 != 0 {
+		// parent; return PID
+		return int(r1), 0
+	}
+
+	// Fork succeeded, now in child.
+
+	// Enable tracing if requested.
+	if sys.Ptrace {
+		_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Session ID
+	if sys.Setsid {
+		_, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Set process group
+	if sys.Setpgid {
+		_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Chroot
+	if chroot != nil {
+		_, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// User and groups
+	if cred := sys.Credential; cred != nil {
+		ngroups := uintptr(len(cred.Groups))
+		groups := uintptr(0)
+		if ngroups > 0 {
+			groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
+		}
+		_, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+		_, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+		_, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Chdir
+	if dir != nil {
+		_, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Pass 1: look for fd[i] < i and move those up above len(fd)
+	// so that pass 2 won't stomp on an fd it needs later.
+	nextfd = int(len(fd))
+	if pipe < nextfd {
+		_, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+		RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+		pipe = nextfd
+		nextfd++
+	}
+	for i = 0; i < len(fd); i++ {
+		if fd[i] >= 0 && fd[i] < int(i) {
+			_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
+			if err1 != 0 {
+				goto childerror
+			}
+			RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+			fd[i] = nextfd
+			nextfd++
+			if nextfd == pipe { // don't stomp on pipe
+				nextfd++
+			}
+		}
+	}
+
+	// Pass 2: dup fd[i] down onto i.
+	for i = 0; i < len(fd); i++ {
+		if fd[i] == -1 {
+			RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
+			continue
+		}
+		if fd[i] == int(i) {
+			// dup2(i, i) won't clear close-on-exec flag on Linux,
+			// probably not elsewhere either.
+			_, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0)
+			if err1 != 0 {
+				goto childerror
+			}
+			continue
+		}
+		// The new fd is created NOT close-on-exec,
+		// which is exactly what we want.
+		_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// By convention, we don't close-on-exec the fds we are
+	// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
+	// Programs that know they inherit fds >= 3 will need
+	// to set them close-on-exec.
+	for i = len(fd); i < 3; i++ {
+		RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
+	}
+
+	// Detach fd 0 from tty
+	if sys.Noctty {
+		_, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Make fd 0 the tty
+	if sys.Setctty {
+		_, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCSCTTY), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Time to exec.
+	_, _, err1 = RawSyscall(SYS_EXECVE,
+		uintptr(unsafe.Pointer(argv0)),
+		uintptr(unsafe.Pointer(&argv[0])),
+		uintptr(unsafe.Pointer(&envv[0])))
+
+childerror:
+	// send error code on pipe
+	RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
+	for {
+		RawSyscall(SYS_EXIT, 253, 0, 0)
+	}
+
+	// Calling panic is not actually safe,
+	// but the for loop above won't break
+	// and this shuts up the compiler.
+	panic("unreached")
+}
diff --git a/src/pkg/syscall/exec_linux.go b/src/pkg/syscall/exec_linux.go
new file mode 100644
index 0000000..38b8f9e
--- /dev/null
+++ b/src/pkg/syscall/exec_linux.go
@@ -0,0 +1,231 @@
+// Copyright 2011 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
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+type SysProcAttr struct {
+	Chroot     string      // Chroot.
+	Credential *Credential // Credential.
+	Ptrace     bool        // Enable tracing.
+	Setsid     bool        // Create session.
+	Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
+	Setctty    bool        // Set controlling terminal to fd 0
+	Noctty     bool        // Detach fd 0 from controlling terminal
+	Pdeathsig  int         // Signal that the process will get when its parent dies (Linux only)
+}
+
+// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
+// If a dup or exec fails, write the errno error to pipe.
+// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
+// In the child, this function must not acquire any locks, because
+// they might have been locked at the time of the fork.  This means
+// no rescheduling, no malloc calls, and no new stack segments.
+// The calls to RawSyscall are okay because they are assembly
+// functions that do not grow the stack.
+func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
+	// Declare all variables at top in case any
+	// declarations require heap allocation (e.g., err1).
+	var (
+		r1     uintptr
+		err1   Errno
+		nextfd int
+		i      int
+	)
+
+	// guard against side effects of shuffling fds below.
+	fd := append([]int(nil), attr.Files...)
+
+	// About to call fork.
+	// No more allocation or calls of non-assembly functions.
+	r1, _, err1 = RawSyscall(SYS_FORK, 0, 0, 0)
+	if err1 != 0 {
+		return 0, err1
+	}
+
+	if r1 != 0 {
+		// parent; return PID
+		return int(r1), 0
+	}
+
+	// Fork succeeded, now in child.
+
+	// Parent death signal
+	if sys.Pdeathsig != 0 {
+		_, _, err1 = RawSyscall6(SYS_PRCTL, PR_SET_PDEATHSIG, uintptr(sys.Pdeathsig), 0, 0, 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+
+		// Signal self if parent is already dead. This might cause a
+		// duplicate signal in rare cases, but it won't matter when
+		// using SIGKILL.
+		r1, _, _ = RawSyscall(SYS_GETPPID, 0, 0, 0)
+		if r1 == 1 {
+			pid, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+			_, _, err1 := RawSyscall(SYS_KILL, pid, uintptr(sys.Pdeathsig), 0)
+			if err1 != 0 {
+				goto childerror
+			}
+		}
+	}
+
+	// Enable tracing if requested.
+	if sys.Ptrace {
+		_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Session ID
+	if sys.Setsid {
+		_, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Set process group
+	if sys.Setpgid {
+		_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Chroot
+	if chroot != nil {
+		_, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// User and groups
+	if cred := sys.Credential; cred != nil {
+		ngroups := uintptr(len(cred.Groups))
+		groups := uintptr(0)
+		if ngroups > 0 {
+			groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
+		}
+		_, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+		_, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+		_, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Chdir
+	if dir != nil {
+		_, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Pass 1: look for fd[i] < i and move those up above len(fd)
+	// so that pass 2 won't stomp on an fd it needs later.
+	nextfd = int(len(fd))
+	if pipe < nextfd {
+		_, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+		RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+		pipe = nextfd
+		nextfd++
+	}
+	for i = 0; i < len(fd); i++ {
+		if fd[i] >= 0 && fd[i] < int(i) {
+			_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
+			if err1 != 0 {
+				goto childerror
+			}
+			RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+			fd[i] = nextfd
+			nextfd++
+			if nextfd == pipe { // don't stomp on pipe
+				nextfd++
+			}
+		}
+	}
+
+	// Pass 2: dup fd[i] down onto i.
+	for i = 0; i < len(fd); i++ {
+		if fd[i] == -1 {
+			RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
+			continue
+		}
+		if fd[i] == int(i) {
+			// dup2(i, i) won't clear close-on-exec flag on Linux,
+			// probably not elsewhere either.
+			_, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0)
+			if err1 != 0 {
+				goto childerror
+			}
+			continue
+		}
+		// The new fd is created NOT close-on-exec,
+		// which is exactly what we want.
+		_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// By convention, we don't close-on-exec the fds we are
+	// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
+	// Programs that know they inherit fds >= 3 will need
+	// to set them close-on-exec.
+	for i = len(fd); i < 3; i++ {
+		RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
+	}
+
+	// Detach fd 0 from tty
+	if sys.Noctty {
+		_, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Make fd 0 the tty
+	if sys.Setctty {
+		_, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCSCTTY), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Time to exec.
+	_, _, err1 = RawSyscall(SYS_EXECVE,
+		uintptr(unsafe.Pointer(argv0)),
+		uintptr(unsafe.Pointer(&argv[0])),
+		uintptr(unsafe.Pointer(&envv[0])))
+
+childerror:
+	// send error code on pipe
+	RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
+	for {
+		RawSyscall(SYS_EXIT, 253, 0, 0)
+	}
+
+	// Calling panic is not actually safe,
+	// but the for loop above won't break
+	// and this shuts up the compiler.
+	panic("unreached")
+}
diff --git a/src/pkg/syscall/exec_plan9.go b/src/pkg/syscall/exec_plan9.go
index 66ab1fc..788666b 100644
--- a/src/pkg/syscall/exec_plan9.go
+++ b/src/pkg/syscall/exec_plan9.go
@@ -85,7 +85,7 @@ func gstring(b []byte) (string, []byte) {
 }
 
 // readdirnames returns the names of files inside the directory represented by dirfd.
-func readdirnames(dirfd int) (names []string, err Error) {
+func readdirnames(dirfd int) (names []string, err error) {
 	result := make([]string, 0, 100)
 	var buf [STATMAX]byte
 
@@ -117,7 +117,7 @@ func readdirnames(dirfd int) (names []string, err Error) {
 
 // readdupdevice returns a list of currently opened fds (excluding stdin, stdout, stderr) from the dup device #d.
 // ForkLock should be write locked before calling, so that no new fds would be created while the fd list is being read.
-func readdupdevice() (fds []int, err Error) {
+func readdupdevice() (fds []int, err error) {
 	dupdevfd, err := Open("#d", O_RDONLY)
 
 	if err != nil {
@@ -169,7 +169,7 @@ func init() {
 // no rescheduling, no malloc calls, and no new stack segments.
 // The calls to RawSyscall are okay because they are assembly
 // functions that do not grow the stack.
-func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, attr *ProcAttr, fdsToClose []int, pipe int, rflag int) (pid int, err Error) {
+func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, attr *ProcAttr, fdsToClose []int, pipe int, rflag int) (pid int, err error) {
 	// Declare all variables at top in case any
 	// declarations require heap allocation (e.g., errbuf).
 	var (
@@ -314,7 +314,7 @@ childerror:
 	panic("unreached")
 }
 
-func cexecPipe(p []int) Error {
+func cexecPipe(p []int) error {
 	e := Pipe(p)
 	if e != nil {
 		return e
@@ -351,7 +351,7 @@ type SysProcAttr struct {
 var zeroProcAttr ProcAttr
 var zeroSysProcAttr SysProcAttr
 
-func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error) {
+func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
 	var (
 		p      [2]int
 		n      int
@@ -478,18 +478,18 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error)
 }
 
 // Combination of fork and exec, careful to be thread safe.
-func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err Error) {
+func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
 	return forkExec(argv0, argv, attr)
 }
 
 // StartProcess wraps ForkExec for package os.
-func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err Error) {
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err error) {
 	pid, err = forkExec(argv0, argv, attr)
 	return pid, 0, err
 }
 
 // Ordinary exec.
-func Exec(argv0 string, argv []string, envv []string) (err Error) {
+func Exec(argv0 string, argv []string, envv []string) (err error) {
 	if envv != nil {
 		r1, _, _ := RawSyscall(SYS_RFORK, RFCENVG, 0, 0)
 		if int(r1) == -1 {
@@ -516,10 +516,10 @@ func Exec(argv0 string, argv []string, envv []string) (err Error) {
 		}
 	}
 
-	_, _, e := Syscall(SYS_EXEC,
+	_, _, e1 := Syscall(SYS_EXEC,
 		uintptr(unsafe.Pointer(StringBytePtr(argv0))),
 		uintptr(unsafe.Pointer(&StringSlicePtr(argv)[0])),
 		0)
 
-	return NewError(e)
+	return e1
 }
diff --git a/src/pkg/syscall/exec_unix.go b/src/pkg/syscall/exec_unix.go
index 2399c89..ad3cf48 100644
--- a/src/pkg/syscall/exec_unix.go
+++ b/src/pkg/syscall/exec_unix.go
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 // Fork, exec, wait, etc.
 
 package syscall
 
 import (
+	"runtime"
 	"sync"
 	"unsafe"
 )
@@ -75,9 +76,9 @@ func StringSlicePtr(ss []string) []*byte {
 
 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
 
-func SetNonblock(fd int, nonblocking bool) (errno int) {
+func SetNonblock(fd int, nonblocking bool) (err error) {
 	flag, err := fcntl(fd, F_GETFL, 0)
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	if nonblocking {
@@ -89,202 +90,6 @@ func SetNonblock(fd int, nonblocking bool) (errno int) {
 	return err
 }
 
-// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
-// If a dup or exec fails, write the errno int to pipe.
-// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
-// In the child, this function must not acquire any locks, because
-// they might have been locked at the time of the fork.  This means
-// no rescheduling, no malloc calls, and no new stack segments.
-// The calls to RawSyscall are okay because they are assembly
-// functions that do not grow the stack.
-func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err int) {
-	// Declare all variables at top in case any
-	// declarations require heap allocation (e.g., err1).
-	var r1, r2, err1 uintptr
-	var nextfd int
-	var i int
-
-	// guard against side effects of shuffling fds below.
-	fd := append([]int(nil), attr.Files...)
-
-	darwin := OS == "darwin"
-
-	// About to call fork.
-	// No more allocation or calls of non-assembly functions.
-	r1, r2, err1 = RawSyscall(SYS_FORK, 0, 0, 0)
-	if err1 != 0 {
-		return 0, int(err1)
-	}
-
-	// On Darwin:
-	//	r1 = child pid in both parent and child.
-	//	r2 = 0 in parent, 1 in child.
-	// Convert to normal Unix r1 = 0 in child.
-	if darwin && r2 == 1 {
-		r1 = 0
-	}
-
-	if r1 != 0 {
-		// parent; return PID
-		return int(r1), 0
-	}
-
-	// Fork succeeded, now in child.
-
-	// Enable tracing if requested.
-	if sys.Ptrace {
-		_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// Session ID
-	if sys.Setsid {
-		_, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// Set process group
-	if sys.Setpgid {
-		_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// Chroot
-	if chroot != nil {
-		_, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// User and groups
-	if cred := sys.Credential; cred != nil {
-		ngroups := uintptr(len(cred.Groups))
-		groups := uintptr(0)
-		if ngroups > 0 {
-			groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
-		}
-		_, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0)
-		if err1 != 0 {
-			goto childerror
-		}
-		_, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
-		if err1 != 0 {
-			goto childerror
-		}
-		_, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// Chdir
-	if dir != nil {
-		_, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// Pass 1: look for fd[i] < i and move those up above len(fd)
-	// so that pass 2 won't stomp on an fd it needs later.
-	nextfd = int(len(fd))
-	if pipe < nextfd {
-		_, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
-		if err1 != 0 {
-			goto childerror
-		}
-		RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
-		pipe = nextfd
-		nextfd++
-	}
-	for i = 0; i < len(fd); i++ {
-		if fd[i] >= 0 && fd[i] < int(i) {
-			_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
-			if err1 != 0 {
-				goto childerror
-			}
-			RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
-			fd[i] = nextfd
-			nextfd++
-			if nextfd == pipe { // don't stomp on pipe
-				nextfd++
-			}
-		}
-	}
-
-	// Pass 2: dup fd[i] down onto i.
-	for i = 0; i < len(fd); i++ {
-		if fd[i] == -1 {
-			RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
-			continue
-		}
-		if fd[i] == int(i) {
-			// dup2(i, i) won't clear close-on-exec flag on Linux,
-			// probably not elsewhere either.
-			_, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0)
-			if err1 != 0 {
-				goto childerror
-			}
-			continue
-		}
-		// The new fd is created NOT close-on-exec,
-		// which is exactly what we want.
-		_, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// By convention, we don't close-on-exec the fds we are
-	// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
-	// Programs that know they inherit fds >= 3 will need
-	// to set them close-on-exec.
-	for i = len(fd); i < 3; i++ {
-		RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
-	}
-
-	// Detach fd 0 from tty
-	if sys.Noctty {
-		_, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// Make fd 0 the tty
-	if sys.Setctty {
-		_, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCSCTTY), 0)
-		if err1 != 0 {
-			goto childerror
-		}
-	}
-
-	// Time to exec.
-	_, _, err1 = RawSyscall(SYS_EXECVE,
-		uintptr(unsafe.Pointer(argv0)),
-		uintptr(unsafe.Pointer(&argv[0])),
-		uintptr(unsafe.Pointer(&envv[0])))
-
-childerror:
-	// send error code on pipe
-	RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
-	for {
-		RawSyscall(SYS_EXIT, 253, 0, 0)
-	}
-
-	// Calling panic is not actually safe,
-	// but the for loop above won't break
-	// and this shuts up the compiler.
-	panic("unreached")
-}
-
 // Credential holds user and group identities to be assumed
 // by a child process started by StartProcess.
 type Credential struct {
@@ -302,23 +107,13 @@ type ProcAttr struct {
 	Sys   *SysProcAttr
 }
 
-type SysProcAttr struct {
-	Chroot     string      // Chroot.
-	Credential *Credential // Credential.
-	Ptrace     bool        // Enable tracing.
-	Setsid     bool        // Create session.
-	Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
-	Setctty    bool        // Set controlling terminal to fd 0
-	Noctty     bool        // Detach fd 0 from controlling terminal
-}
-
 var zeroProcAttr ProcAttr
 var zeroSysProcAttr SysProcAttr
 
-func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
+func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
 	var p [2]int
 	var n int
-	var err1 uintptr
+	var err1 Errno
 	var wstatus WaitStatus
 
 	if attr == nil {
@@ -337,7 +132,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
 	argvp := StringSlicePtr(argv)
 	envvp := StringSlicePtr(attr.Env)
 
-	if OS == "freebsd" && len(argv[0]) > len(argv0) {
+	if runtime.GOOS == "freebsd" && len(argv[0]) > len(argv0) {
 		argvp[0] = argv0p
 	}
 
@@ -356,19 +151,20 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
 	ForkLock.Lock()
 
 	// Allocate child status pipe close on exec.
-	if err = Pipe(p[0:]); err != 0 {
+	if err = Pipe(p[0:]); err != nil {
 		goto error
 	}
-	if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
+	if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != nil {
 		goto error
 	}
-	if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
+	if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != nil {
 		goto error
 	}
 
 	// Kick off child.
-	pid, err = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
-	if err != 0 {
+	pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
+	if err1 != 0 {
+		err = Errno(err1)
 		goto error
 	}
 	ForkLock.Unlock()
@@ -377,11 +173,11 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
 	Close(p[1])
 	n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
 	Close(p[0])
-	if err != 0 || n != 0 {
+	if err != nil || n != 0 {
 		if n == int(unsafe.Sizeof(err1)) {
-			err = int(err1)
+			err = Errno(err1)
 		}
-		if err == 0 {
+		if err == nil {
 			err = EPIPE
 		}
 
@@ -395,7 +191,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
 	}
 
 	// Read got EOF, so pipe closed on exec, so exec succeeded.
-	return pid, 0
+	return pid, nil
 
 error:
 	if p[0] >= 0 {
@@ -407,21 +203,21 @@ error:
 }
 
 // Combination of fork and exec, careful to be thread safe.
-func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
+func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
 	return forkExec(argv0, argv, attr)
 }
 
 // StartProcess wraps ForkExec for package os.
-func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err error) {
 	pid, err = forkExec(argv0, argv, attr)
 	return pid, 0, err
 }
 
 // Ordinary exec.
-func Exec(argv0 string, argv []string, envv []string) (err int) {
+func Exec(argv0 string, argv []string, envv []string) (err error) {
 	_, _, err1 := RawSyscall(SYS_EXECVE,
 		uintptr(unsafe.Pointer(StringBytePtr(argv0))),
 		uintptr(unsafe.Pointer(&StringSlicePtr(argv)[0])),
 		uintptr(unsafe.Pointer(&StringSlicePtr(envv)[0])))
-	return int(err1)
+	return Errno(err1)
 }
diff --git a/src/pkg/syscall/exec_windows.go b/src/pkg/syscall/exec_windows.go
index e8b540a..2826e2f 100644
--- a/src/pkg/syscall/exec_windows.go
+++ b/src/pkg/syscall/exec_windows.go
@@ -8,8 +8,8 @@ package syscall
 
 import (
 	"sync"
+	"unicode/utf16"
 	"unsafe"
-	"utf16"
 )
 
 var ForkLock sync.RWMutex
@@ -100,7 +100,7 @@ func makeCmdLine(args []string) string {
 // Last bytes are two UCS-2 NULs, or four NUL bytes.
 func createEnvBlock(envv []string) *uint16 {
 	if len(envv) == 0 {
-		return &utf16.Encode([]int("\x00\x00"))[0]
+		return &utf16.Encode([]rune("\x00\x00"))[0]
 	}
 	length := 0
 	for _, s := range envv {
@@ -118,54 +118,54 @@ func createEnvBlock(envv []string) *uint16 {
 	}
 	copy(b[i:i+1], []byte{0})
 
-	return &utf16.Encode([]int(string(b)))[0]
+	return &utf16.Encode([]rune(string(b)))[0]
 }
 
 func CloseOnExec(fd Handle) {
 	SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
 }
 
-func SetNonblock(fd Handle, nonblocking bool) (errno int) {
-	return 0
+func SetNonblock(fd Handle, nonblocking bool) (err error) {
+	return nil
 }
 
 // getFullPath retrieves the full path of the specified file.
 // Just a wrapper for Windows GetFullPathName api.
-func getFullPath(name string) (path string, err int) {
+func getFullPath(name string) (path string, err error) {
 	p := StringToUTF16Ptr(name)
 	buf := make([]uint16, 100)
 	n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
-	if err != 0 {
+	if err != nil {
 		return "", err
 	}
 	if n > uint32(len(buf)) {
 		// Windows is asking for bigger buffer.
 		buf = make([]uint16, n)
 		n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
-		if err != 0 {
+		if err != nil {
 			return "", err
 		}
 		if n > uint32(len(buf)) {
 			return "", EINVAL
 		}
 	}
-	return UTF16ToString(buf[:n]), 0
+	return UTF16ToString(buf[:n]), nil
 }
 
 func isSlash(c uint8) bool {
 	return c == '\\' || c == '/'
 }
 
-func normalizeDir(dir string) (name string, err int) {
+func normalizeDir(dir string) (name string, err error) {
 	ndir, err := getFullPath(dir)
-	if err != 0 {
+	if err != nil {
 		return "", err
 	}
 	if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) {
 		// dir cannot have \\server\share\path form
 		return "", EINVAL
 	}
-	return ndir, 0
+	return ndir, nil
 }
 
 func volToUpper(ch int) int {
@@ -175,13 +175,13 @@ func volToUpper(ch int) int {
 	return ch
 }
 
-func joinExeDirAndFName(dir, p string) (name string, err int) {
+func joinExeDirAndFName(dir, p string) (name string, err error) {
 	if len(p) == 0 {
 		return "", EINVAL
 	}
 	if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) {
 		// \\server\share\path form
-		return p, 0
+		return p, nil
 	}
 	if len(p) > 1 && p[1] == ':' {
 		// has drive letter
@@ -189,10 +189,10 @@ func joinExeDirAndFName(dir, p string) (name string, err int) {
 			return "", EINVAL
 		}
 		if isSlash(p[2]) {
-			return p, 0
+			return p, nil
 		} else {
 			d, err := normalizeDir(dir)
-			if err != 0 {
+			if err != nil {
 				return "", err
 			}
 			if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
@@ -204,7 +204,7 @@ func joinExeDirAndFName(dir, p string) (name string, err int) {
 	} else {
 		// no drive letter
 		d, err := normalizeDir(dir)
-		if err != 0 {
+		if err != nil {
 			return "", err
 		}
 		if isSlash(p[0]) {
@@ -232,7 +232,7 @@ type SysProcAttr struct {
 var zeroProcAttr ProcAttr
 var zeroSysProcAttr SysProcAttr
 
-func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err error) {
 	if len(argv0) == 0 {
 		return 0, 0, EWINDOWS
 	}
@@ -255,9 +255,9 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
 		// argv0 relative to the current directory, and, only once the new
 		// process is started, it does Chdir(attr.Dir). We are adjusting
 		// for that difference here by making argv0 absolute.
-		var err int
+		var err error
 		argv0, err = joinExeDirAndFName(attr.Dir, argv0)
-		if err != 0 {
+		if err != nil {
 			return 0, 0, err
 		}
 	}
@@ -294,7 +294,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
 	for i := range attr.Files {
 		if attr.Files[i] > 0 {
 			err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
-			if err != 0 {
+			if err != nil {
 				return 0, 0, err
 			}
 			defer CloseHandle(Handle(fd[i]))
@@ -314,14 +314,14 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
 	pi := new(ProcessInformation)
 
 	err = CreateProcess(argv0p, argvp, nil, nil, true, CREATE_UNICODE_ENVIRONMENT, createEnvBlock(attr.Env), dirp, si, pi)
-	if err != 0 {
+	if err != nil {
 		return 0, 0, err
 	}
 	defer CloseHandle(Handle(pi.Thread))
 
-	return int(pi.ProcessId), int(pi.Process), 0
+	return int(pi.ProcessId), int(pi.Process), nil
 }
 
-func Exec(argv0 string, argv []string, envv []string) (err int) {
+func Exec(argv0 string, argv []string, envv []string) (err error) {
 	return EWINDOWS
 }
diff --git a/src/pkg/syscall/lsf_linux.go b/src/pkg/syscall/lsf_linux.go
index f2bd2b7..05d653b 100644
--- a/src/pkg/syscall/lsf_linux.go
+++ b/src/pkg/syscall/lsf_linux.go
@@ -18,10 +18,10 @@ func LsfJump(code, k, jt, jf int) *SockFilter {
 	return &SockFilter{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
 }
 
-func LsfSocket(ifindex, proto int) (int, int) {
+func LsfSocket(ifindex, proto int) (int, error) {
 	var lsall SockaddrLinklayer
 	s, e := Socket(AF_PACKET, SOCK_RAW, proto)
-	if e != 0 {
+	if e != nil {
 		return 0, e
 	}
 	p := (*[2]byte)(unsafe.Pointer(&lsall.Protocol))
@@ -29,11 +29,11 @@ func LsfSocket(ifindex, proto int) (int, int) {
 	p[1] = byte(proto)
 	lsall.Ifindex = ifindex
 	e = Bind(s, &lsall)
-	if e != 0 {
+	if e != nil {
 		Close(s)
 		return 0, e
 	}
-	return s, 0
+	return s, nil
 }
 
 type iflags struct {
@@ -41,17 +41,17 @@ type iflags struct {
 	flags uint16
 }
 
-func SetLsfPromisc(name string, m bool) int {
+func SetLsfPromisc(name string, m bool) error {
 	s, e := Socket(AF_INET, SOCK_DGRAM, 0)
-	if e != 0 {
+	if e != nil {
 		return e
 	}
 	defer Close(s)
 	var ifl iflags
 	copy(ifl.name[:], []byte(name))
 	_, _, ep := Syscall(SYS_IOCTL, uintptr(s), SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
-	if e := int(ep); e != 0 {
-		return e
+	if ep != 0 {
+		return Errno(ep)
 	}
 	if m {
 		ifl.flags |= uint16(IFF_PROMISC)
@@ -59,20 +59,20 @@ func SetLsfPromisc(name string, m bool) int {
 		ifl.flags &= ^uint16(IFF_PROMISC)
 	}
 	_, _, ep = Syscall(SYS_IOCTL, uintptr(s), SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
-	if e := int(ep); e != 0 {
-		return e
+	if ep != 0 {
+		return Errno(ep)
 	}
-	return 0
+	return nil
 }
 
-func AttachLsf(fd int, i []SockFilter) int {
+func AttachLsf(fd int, i []SockFilter) error {
 	var p SockFprog
 	p.Len = uint16(len(i))
 	p.Filter = (*SockFilter)(unsafe.Pointer(&i[0]))
 	return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, uintptr(unsafe.Pointer(&p)), unsafe.Sizeof(p))
 }
 
-func DetachLsf(fd int) int {
+func DetachLsf(fd int) error {
 	var dummy int
 	return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, uintptr(unsafe.Pointer(&dummy)), unsafe.Sizeof(dummy))
 }
diff --git a/src/pkg/syscall/mkall.sh b/src/pkg/syscall/mkall.sh
index 8d1d639..5a25e2c 100755
--- a/src/pkg/syscall/mkall.sh
+++ b/src/pkg/syscall/mkall.sh
@@ -79,6 +79,8 @@ GOOSARCH="${GOOS}_${GOARCH}"
 mksyscall="./mksyscall.pl"
 mkerrors="./mkerrors.sh"
 zerrors="zerrors_$GOOSARCH.go"
+mksysctl=""
+zsysctl="zsysctl_$GOOSARCH.go"
 run="sh"
 
 case "$1" in
@@ -107,77 +109,93 @@ _* | *_ | _)
 	echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
 	exit 1
 	;;
-freebsd_386)
-	mkerrors="$mkerrors -f -m32"
-	mksyscall="./mksyscall.pl -l32"
-	mksysnum="curl -s 'http://svn.freebsd.org/base/head/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
-	mktypes="godefs -gsyscall -f-m32"
-	;;
-freebsd_amd64)
-	mkerrors="$mkerrors -f -m64"
-	mksysnum="curl -s 'http://svn.freebsd.org/base/head/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
-	mktypes="godefs -gsyscall -f-m64"
-	;;
 darwin_386)
-	mkerrors="$mkerrors -f -m32"
+	mkerrors="$mkerrors -m32"
 	mksyscall="./mksyscall.pl -l32"
 	mksysnum="./mksysnum_darwin.pl /usr/include/sys/syscall.h"
-	mktypes="godefs -gsyscall -f-m32"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
 	;;
 darwin_amd64)
-	mkerrors="$mkerrors -f -m64"
+	mkerrors="$mkerrors -m64"
 	mksysnum="./mksysnum_darwin.pl /usr/include/sys/syscall.h"
-	mktypes="godefs -gsyscall -f-m64"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
+	;;
+freebsd_386)
+	mkerrors="$mkerrors -m32"
+	mksyscall="./mksyscall.pl -l32"
+	mksysnum="curl -s 'http://svn.freebsd.org/base/head/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
+	;;
+freebsd_amd64)
+	mkerrors="$mkerrors -m64"
+	mksysnum="curl -s 'http://svn.freebsd.org/base/head/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
 	;;
 linux_386)
-	mkerrors="$mkerrors -f -m32"
+	mkerrors="$mkerrors -m32"
 	mksyscall="./mksyscall.pl -l32"
 	mksysnum="./mksysnum_linux.pl /usr/include/asm/unistd_32.h"
-	mktypes="godefs -gsyscall -f-m32"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
 	;;
 linux_amd64)
-	mkerrors="$mkerrors -f -m64"
+	mkerrors="$mkerrors -m64"
 	mksysnum="./mksysnum_linux.pl /usr/include/asm/unistd_64.h"
-	mktypes="godefs -gsyscall -f-m64"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
 	;;
 linux_arm)
 	mkerrors="$mkerrors"
 	mksyscall="./mksyscall.pl -b32"
 	mksysnum="./mksysnum_linux.pl /usr/include/asm/unistd.h"
-	mktypes="godefs -gsyscall"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
+	;;
+netbsd_386)
+	mkerrors="$mkerrors -m32"
+	mksyscall="./mksyscall.pl -l32 -netbsd"
+	mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
+	;;
+netbsd_amd64)
+	mkerrors="$mkerrors -m64"
+	mksyscall="./mksyscall.pl -netbsd"
+	mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
+	;;
+openbsd_386)
+	mkerrors="$mkerrors -m32"
+	mksyscall="./mksyscall.pl -l32 -openbsd"
+	mksysctl="./mksysctl_openbsd.pl"
+	zsysctl="zsysctl_openbsd.go"
+	mksysnum="curl -s 'http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
+	;;
+openbsd_amd64)
+	mkerrors="$mkerrors -m64"
+	mksyscall="./mksyscall.pl -openbsd"
+	mksysctl="./mksysctl_openbsd.pl"
+	zsysctl="zsysctl_openbsd.go"
+	mksysnum="curl -s 'http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
+	mktypes="GOARCH=$GOARCH cgo -godefs"
+	;;
+plan9_386)
+	mkerrors=
+	mksyscall="./mksyscall.pl -l32 -plan9"
+	mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
+	mktypes="XXX"
 	;;
 windows_386)
 	mksyscall="./mksyscall_windows.pl -l32"
 	mksysnum=
 	mktypes=
-	mkerrors="./mkerrors_windows.sh -f -m32"
+	mkerrors="./mkerrors_windows.sh -m32"
 	zerrors="zerrors_windows.go"
 	;;
 windows_amd64)
 	mksyscall="./mksyscall_windows.pl"
 	mksysnum=
 	mktypes=
-	mkerrors="./mkerrors_windows.sh -f -m32"
+	mkerrors="./mkerrors_windows.sh -m32"
 	zerrors="zerrors_windows.go"
 	;;
-plan9_386)
-	mkerrors=
-	mksyscall="./mksyscall.pl -l32 -plan9"
-	mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h"
-	mktypes="godefs -gsyscall -f -m32"
-	;;
-openbsd_386)
-	mkerrors="$mkerrors -f -m32"
-	mksyscall="./mksyscall.pl -l32 -openbsd"
-	mksysnum="curl -s 'http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
-	mktypes="godefs -gsyscall -f-m32"
-	;;
-openbsd_amd64)
-	mkerrors="$mkerrors -f -m64"
-	mksyscall="./mksyscall.pl -openbsd"
-	mksysnum="curl -s 'http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl"
-	mktypes="godefs -gsyscall -f-m64"
-	;;
 *)
 	echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
 	exit 1
@@ -188,11 +206,12 @@ esac
 	if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
 	syscall_goos="syscall_$GOOS.go"
 	case "$GOOS" in
-	darwin | freebsd | openbsd)
+	darwin | freebsd | netbsd | openbsd)
 		syscall_goos="syscall_bsd.go $syscall_goos"
 		;;
 	esac
+	if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
 	if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos syscall_$GOOSARCH.go |gofmt >zsyscall_$GOOSARCH.go"; fi
 	if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
-	if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.c |gofmt >ztypes_$GOOSARCH.go"; fi
+	if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi
 ) | $run
diff --git a/src/pkg/syscall/mkerrors.sh b/src/pkg/syscall/mkerrors.sh
index 9936b11..9a50cdf 100755
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -15,6 +15,46 @@ GCC=gcc
 
 uname=$(uname)
 
+includes_Darwin='
+#define _DARWIN_C_SOURCE
+#define KERNEL
+#define _DARWIN_USE_64_BIT_INODE
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/ptrace.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_mroute.h>
+#include <termios.h>
+'
+
+includes_FreeBSD='
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <termios.h>
+#include <netinet/ip.h>
+#include <netinet/ip_mroute.h>
+'
+
 includes_Linux='
 #define _LARGEFILE_SOURCE
 #define _LARGEFILE64_SOURCE
@@ -27,6 +67,7 @@ includes_Linux='
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
+#include <sys/prctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <linux/if_addr.h>
@@ -44,44 +85,25 @@ includes_Linux='
 #include <netpacket/packet.h>
 '
 
-includes_Darwin='
-#define _DARWIN_C_SOURCE
-#define KERNEL
-#define _DARWIN_USE_64_BIT_INODE
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/ptrace.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-#include <net/bpf.h>
-#include <net/if.h>
-#include <net/if_types.h>
-#include <net/route.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_mroute.h>
-#include <termios.h>
-'
-
-includes_FreeBSD='
+includes_NetBSD='
 #include <sys/types.h>
+#include <sys/param.h>
 #include <sys/event.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
+#include <sys/termios.h>
+#include <sys/ttycom.h>
 #include <sys/wait.h>
-#include <sys/ioctl.h>
 #include <net/bpf.h>
 #include <net/if.h>
 #include <net/if_types.h>
 #include <net/route.h>
 #include <netinet/in.h>
-#include <termios.h>
+#include <netinet/in_systm.h>
 #include <netinet/ip.h>
 #include <netinet/ip_mroute.h>
+#include <netinet/if_ether.h>
 '
 
 includes_OpenBSD='
@@ -108,6 +130,7 @@ includes_OpenBSD='
 
 includes='
 #include <sys/types.h>
+#include <sys/file.h>
 #include <fcntl.h>
 #include <dirent.h>
 #include <sys/socket.h>
@@ -118,26 +141,22 @@ includes='
 #include <errno.h>
 #include <sys/signal.h>
 #include <signal.h>
+#include <sys/resource.h>
 '
 
-ccflags=""
-next=false
-for i
-do
-	if $next; then
-		ccflags="$ccflags $i"
-		next=false
-	elif [ "$i" = "-f" ]; then
-		next=true
-	fi
-done
+ccflags="$@"
 
-# Write godefs input.
+# Write cgo -godefs input.
 (
+	echo package syscall
+	echo
+	echo '/*'
 	indirect="includes_$(uname)"
 	echo "${!indirect} $includes"
+	echo '*/'
+	echo 'import "C"'
 	echo
-	echo 'enum {'
+	echo 'const ('
 
 	# The gcc command line prints all the #defines
 	# it encounters while processing the input
@@ -157,7 +176,8 @@ done
 		$2 ~ /^E[A-Z0-9_]+$/ ||
 		$2 ~ /^SIG[^_]/ ||
 		$2 ~ /^IN_/ ||
-		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV)_/ ||
+		$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
+		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
 		$2 == "SOMAXCONN" ||
 		$2 == "NAME_MAX" ||
 		$2 == "IFNAMSIZ" ||
@@ -174,18 +194,20 @@ done
 		$2 ~ /^TIOC/ ||
 		$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
 		$2 ~ /^BIOC/ ||
+		$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
+		$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ ||
 		$2 !~ /^(BPF_TIMEVAL)$/ &&
 		$2 ~ /^(BPF|DLT)_/ ||
 		$2 !~ "WMESGLEN" &&
-		$2 ~ /^W[A-Z0-9]+$/ {printf("\t$%s = %s,\n", $2, $2)}
+		$2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)}
 		$2 ~ /^__WCOREFLAG$/ {next}
-		$2 ~ /^__W[A-Z0-9]+$/ {printf("\t$%s = %s,\n", substr($2,3), $2)}
+		$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
 
 		{next}
 	' | sort
 
-	echo '};'
-) >_const.c
+	echo ')'
+) >_const.go
 
 # Pull out just the error names for later.
 errors=$(
@@ -194,10 +216,21 @@ errors=$(
 	sort
 )
 
+# Again, writing regexps to a file.
+echo '#include <errno.h>' | $GCC -x c - -E -dM $ccflags |
+	awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
+	sort >_error.grep
+
 echo '// mkerrors.sh' "$@"
 echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'
 echo
-godefs -c $GCC "$@" -gsyscall "$@" _const.c
+cgo -godefs -- "$@" _const.go >_error.out
+cat _error.out | grep -vf _error.grep
+echo
+echo '// Errors'
+echo 'const ('
+cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/'
+echo ')'
 
 # Run C program to print error strings.
 (
@@ -255,4 +288,4 @@ main(void)
 '
 ) >_errors.c
 
-$GCC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.c
+$GCC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _error.out
diff --git a/src/pkg/syscall/mkerrors_windows.sh b/src/pkg/syscall/mkerrors_windows.sh
index a76f250..13badcd 100755
--- a/src/pkg/syscall/mkerrors_windows.sh
+++ b/src/pkg/syscall/mkerrors_windows.sh
@@ -158,7 +158,7 @@ main(void)
 	printf("\n// Go names for Windows errors.\n");
 	printf("const (\n");
 	for(i=0; i<nelem(goerrors); i++) {
-		printf("\t%s = %s\n", goerrors[i].goname, goerrors[i].winname);
+		printf("\t%s Errno = %s\n", goerrors[i].goname, goerrors[i].winname);
 			
 	}
 	printf(")\n");
@@ -171,7 +171,7 @@ main(void)
 	for(i=0; i<nelem(errors); i++) {
 		printf("\t%s", errors[i].name);
 		if(iota) {
-			printf(" = APPLICATION_ERROR + iota");
+			printf(" Errno = APPLICATION_ERROR + iota");
 			iota = !iota;
 		}
 		printf("\n");
diff --git a/src/pkg/syscall/mksyscall.pl b/src/pkg/syscall/mksyscall.pl
index 213526a..963599c 100755
--- a/src/pkg/syscall/mksyscall.pl
+++ b/src/pkg/syscall/mksyscall.pl
@@ -26,6 +26,7 @@ my $errors = 0;
 my $_32bit = "";
 my $plan9 = 0;
 my $openbsd = 0;
+my $netbsd = 0;
 
 if($ARGV[0] eq "-b32") {
 	$_32bit = "big-endian";
@@ -42,6 +43,10 @@ if($ARGV[0] eq "-openbsd") {
 	$openbsd = 1;
 	shift;
 }
+if($ARGV[0] eq "-netbsd") {
+	$netbsd = 1;
+	shift;
+}
 
 if($ARGV[0] =~ /^-/) {
 	print STDERR "usage: mksyscall.pl [-b32 | -l32] [file ...]\n";
@@ -78,7 +83,7 @@ while(<>) {
 	next if !/^\/\/sys / && !$nonblock;
 
 	# Line must be of the form
-	#	func Open(path string, mode int, perm int) (fd int, errno int)
+	#	func Open(path string, mode int, perm int) (fd int, errno error)
 	# Split into name, in params, out params.
 	if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(SYS_[A-Z0-9_]+))?$/) {
 		print STDERR "$ARGV:$.: malformed //sys declaration\n";
@@ -120,7 +125,7 @@ while(<>) {
 			$text .= "\n";
 			push @args, "uintptr(_p$n)", "uintptr(len($name))";
 			$n++;
-		} elsif($type eq "int64" && $openbsd) {
+		} elsif($type eq "int64" && ($openbsd || $netbsd)) {
 			push @args, "0";
 			if($_32bit eq "big-endian") {
 				push @args, "uintptr($name>>32)", "uintptr($name)";
@@ -177,15 +182,17 @@ while(<>) {
 	# Assign return values.
 	my $body = "";
 	my @ret = ("_", "_", "_");
+	my $do_errno = 0;
 	for(my $i=0; $i<@out; $i++) {
 		my $p = $out[$i];
 		my ($name, $type) = parseparam($p);
 		my $reg = "";
-		if($name eq "errno" && !$plan9) {
+		if($name eq "err" && !$plan9) {
 			$reg = "e1";
 			$ret[2] = $reg;
-		} elsif ($name eq "err" && $plan9) {
-			$ret[0] = "r0";			
+			$do_errno = 1;
+		} elsif($name eq "err" && $plan9) {
+			$ret[0] = "r0";
 			$ret[2] = "e1";
 			next;
 		} else {
@@ -208,7 +215,9 @@ while(<>) {
 			$ret[$i] = sprintf("r%d", $i);
 			$ret[$i+1] = sprintf("r%d", $i+1);
 		}
-		$body .= "\t$name = $type($reg)\n";
+		if($reg ne "e1" || $plan9) {
+			$body .= "\t$name = $type($reg)\n";
+		}
 	}
 	if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
 		$text .= "\t$call\n";
@@ -218,12 +227,14 @@ while(<>) {
 	$text .= $body;
 	
 	if ($plan9 && $ret[2] eq "e1") {
-		$text .= "\terr = nil\n";
 		$text .= "\tif int(r0) == -1 {\n";
-		$text .= "\t\terr = NewError(e1)\n";
+		$text .= "\t\terr = e1\n";
+		$text .= "\t}\n";
+	} elsif ($do_errno) {
+		$text .= "\tif e1 != 0 {\n";
+		$text .= "\t\terr = e1\n";
 		$text .= "\t}\n";
 	}
-
 	$text .= "\treturn\n";
 	$text .= "}\n\n";
 }
diff --git a/src/pkg/syscall/mksyscall_windows.pl b/src/pkg/syscall/mksyscall_windows.pl
index 4b24597..1fb5112 100755
--- a/src/pkg/syscall/mksyscall_windows.pl
+++ b/src/pkg/syscall/mksyscall_windows.pl
@@ -11,16 +11,16 @@
 #	  This includes return parameters.
 #	* The parameter lists must give a type for each argument:
 #	  the (x, y, z int) shorthand is not allowed.
-#	* If the return parameter is an error number, it must be named errno.
+#	* If the return parameter is an error number, it must be named err.
 #	* If go func name needs to be different from it's winapi dll name,
 #	  the winapi name could be specified at the end, after "=" sign, like
-#	  //sys LoadLibrary(libname string) (handle uint32, errno int) = LoadLibraryA
-#	* Each function, that returns errno, needs to supply a condition,
+#	  //sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA
+#	* Each function that returns err needs to supply a condition,
 #	  that return value of winapi will be tested against to
-#	  detect failure. This would set errno to windows "last-error",
-#	  otherwise it will be 0. The value can be provided
+#	  detect failure. This would set err to windows "last-error",
+#	  otherwise it will be nil. The value can be provided
 #	  at end of //sys declaration, like
-#	  //sys LoadLibrary(libname string) (handle uint32, errno int) [failretval==-1] = LoadLibraryA
+#	  //sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA
 #	  and is [failretval==0] by default.
 
 use strict;
@@ -64,6 +64,7 @@ sub parseparam($) {
 	return ($1, $2);
 }
 
+my $package = "";
 my $text = "";
 my $vars = "";
 my $mods = "";
@@ -73,10 +74,14 @@ while(<>) {
 	s/\s+/ /g;
 	s/^\s+//;
 	s/\s+$//;
+	$package = $1 if !$package && /^package (\S+)$/;
 	next if !/^\/\/sys /;
 
+	my $syscalldot = "";
+	$syscalldot = "syscall." if $package ne "syscall";
+
 	# Line must be of the form
-	#	func Open(path string, mode int, perm int) (fd int, errno int)
+	#	func Open(path string, mode int, perm int) (fd int, err error)
 	# Split into name, in params, out params.
 	if(!/^\/\/sys (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:\[failretval(.*)\])?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
 		print STDERR "$ARGV:$.: malformed //sys declaration\n";
@@ -96,7 +101,7 @@ while(<>) {
 	my $modvname = "mod$modname";
 	if($modnames !~ /$modname/) {
 		$modnames .= ".$modname";
-		$mods .= "\t$modvname = NewLazyDLL(\"$modname.dll\")\n";
+		$mods .= "\t$modvname = ${syscalldot}NewLazyDLL(\"$modname.dll\")\n";
 	}
 
 	# System call name.
@@ -165,26 +170,31 @@ while(<>) {
 	my $nargs = @args;
 
 	# Determine which form to use; pad args with zeros.
-	my $asm = "Syscall";
+	my $asm = "${syscalldot}Syscall";
 	if(@args <= 3) {
 		while(@args < 3) {
 			push @args, "0";
 		}
 	} elsif(@args <= 6) {
-		$asm = "Syscall6";
+		$asm = "${syscalldot}Syscall6";
 		while(@args < 6) {
 			push @args, "0";
 		}
 	} elsif(@args <= 9) {
-		$asm = "Syscall9";
+		$asm = "${syscalldot}Syscall9";
 		while(@args < 9) {
 			push @args, "0";
 		}
 	} elsif(@args <= 12) {
-		$asm = "Syscall12";
+		$asm = "${syscalldot}Syscall12";
 		while(@args < 12) {
 			push @args, "0";
 		}
+	} elsif(@args <= 15) {
+		$asm = "${syscalldot}Syscall15";
+		while(@args < 15) {
+			push @args, "0";
+		}
 	} else {
 		print STDERR "$ARGV:$.: too many arguments to system call\n";
 	}
@@ -202,7 +212,7 @@ while(<>) {
 		my $p = $out[$i];
 		my ($name, $type) = parseparam($p);
 		my $reg = "";
-		if($name eq "errno") {
+		if($name eq "err") {
 			$reg = "e1";
 			$ret[2] = $reg;
 		} else {
@@ -233,7 +243,7 @@ while(<>) {
 		if($i == 0) {
 			if($type eq "bool") {
 				$failexpr = "!$name";
-			} elsif($name eq "errno") {
+			} elsif($name eq "err") {
 				$ret[$i] = "r1";
 				$failexpr = "int(r1) $failcond";
 			} else {
@@ -241,16 +251,19 @@ while(<>) {
 			}
 		}
 		$failexpr =~ s/(=)([0-9A-Za-z\-+])/$1 $2/;  # gofmt compatible
-		if($name eq "errno") {
-			# Set errno to "last error" only if returned value indicate failure
+		if($name eq "err") {
+			# Set err to "last error" only if returned value indicate failure
 			$body .= "\tif $failexpr {\n";
 			$body .= "\t\tif $reg != 0 {\n";
 			$body .= "\t\t\t$name = $type($reg)\n";
 			$body .= "\t\t} else {\n";
-			$body .= "\t\t\t$name = EINVAL\n";
+			$body .= "\t\t\t$name = ${syscalldot}EINVAL\n";
 			$body .= "\t\t}\n";
-			$body .= "\t} else {\n";
-			$body .= "\t\t$name = 0\n";
+			$body .= "\t}\n";
+		} elsif($rettype eq "error") {
+			# Set $reg to "error" only if returned value indicate failure
+			$body .= "\tif $reg != 0 {\n";
+			$body .= "\t\t$name = ${syscalldot}Errno($reg)\n";
 			$body .= "\t}\n";
 		} else {
 			$body .= "\t$name = $rettype($reg)\n";
@@ -279,9 +292,14 @@ print <<EOF;
 // $cmdline
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-package syscall
+package $package
 
 import "unsafe"
+EOF
+
+print "import \"syscall\"\n" if $package ne "syscall";
+
+print <<EOF;
 
 var (
 $mods
diff --git a/src/pkg/syscall/mksysctl_openbsd.pl b/src/pkg/syscall/mksysctl_openbsd.pl
new file mode 100755
index 0000000..8e5ccaa
--- /dev/null
+++ b/src/pkg/syscall/mksysctl_openbsd.pl
@@ -0,0 +1,257 @@
+#!/usr/bin/perl
+
+# Copyright 2011 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.
+
+#
+# Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
+#
+# Build a MIB with each entry being an array containing the level, type and
+# a hash that will contain additional entries if the current entry is a node.
+# We then walk this MIB and create a flattened sysctl name to OID hash.
+#
+
+use strict;
+
+my $debug = 0;
+my %ctls = ();
+
+my @headers = qw (
+	sys/sysctl.h
+	sys/socket.h
+	sys/tty.h
+	sys/malloc.h
+	sys/mount.h
+	sys/namei.h
+	sys/sem.h
+	sys/shm.h
+	sys/vmmeter.h
+	uvm/uvm_param.h
+	uvm/uvm_swap_encrypt.h
+	ddb/db_var.h
+	net/if.h
+	net/if_pfsync.h
+	net/pipex.h
+	netinet/in.h
+	netinet/icmp_var.h
+	netinet/igmp_var.h
+	netinet/ip_ah.h
+	netinet/ip_carp.h
+	netinet/ip_divert.h
+	netinet/ip_esp.h
+	netinet/ip_ether.h
+	netinet/ip_gre.h
+	netinet/ip_ipcomp.h
+	netinet/ip_ipip.h
+	netinet/pim_var.h
+	netinet/tcp_var.h
+	netinet/udp_var.h
+	netinet6/in6.h
+	netinet6/ip6_divert.h
+	netinet6/pim6_var.h
+	netinet/icmp6.h
+	netmpls/mpls.h
+);
+
+my @ctls = qw (
+	kern
+	vm
+	fs
+	net
+	#debug				# Special handling required
+	hw
+	#machdep			# Arch specific
+	user
+	ddb
+	#vfs				# Special handling required
+	fs.posix
+	kern.forkstat
+	kern.intrcnt
+	kern.malloc
+	kern.nchstats
+	kern.seminfo
+	kern.shminfo
+	kern.timecounter
+	kern.tty
+	kern.watchdog
+	net.bpf
+	net.ifq
+	net.inet
+	net.inet.ah
+	net.inet.carp
+	net.inet.divert
+	net.inet.esp
+	net.inet.etherip
+	net.inet.gre
+	net.inet.icmp
+	net.inet.igmp
+	net.inet.ip
+	net.inet.ip.ifq
+	net.inet.ipcomp
+	net.inet.ipip
+	net.inet.mobileip
+	net.inet.pfsync
+	net.inet.pim
+	net.inet.tcp
+	net.inet.udp
+	net.inet6
+	net.inet6.divert
+	net.inet6.ip6
+	net.inet6.icmp6
+	net.inet6.pim6
+	net.inet6.tcp6
+	net.inet6.udp6
+	net.mpls
+	net.mpls.ifq
+	net.key
+	net.pflow
+	net.pfsync
+	net.pipex
+	net.rt
+	vm.swapencrypt
+	#vfsgenctl			# Special handling required
+);
+
+# Node name "fixups"
+my %ctl_map = (
+	"ipproto" => "net.inet",
+	"net.inet.ipproto" => "net.inet",
+	"net.inet6.ipv6proto" => "net.inet6",
+	"net.inet6.ipv6" => "net.inet6.ip6",
+	"net.inet.icmpv6" => "net.inet6.icmp6",
+	"net.inet6.divert6" => "net.inet6.divert",
+	"net.inet6.tcp6" => "net.inet.tcp",
+	"net.inet6.udp6" => "net.inet.udp",
+	"mpls" => "net.mpls",
+	"swpenc" => "vm.swapencrypt"
+);
+
+# Node mappings
+my %node_map = (
+	"net.inet.ip.ifq" => "net.ifq",
+	"net.inet.pfsync" => "net.pfsync",
+	"net.mpls.ifq" => "net.ifq"
+);
+
+my $ctlname;
+my %mib = ();
+my %sysctl = ();
+my $node;
+
+sub debug() {
+	print STDERR "$_[0]\n" if $debug;
+}
+
+# Walk the MIB and build a sysctl name to OID mapping.
+sub build_sysctl() {
+	my ($node, $name, $oid) = @_;
+	my %node = %{$node};
+	my @oid = @{$oid};
+
+	foreach my $key (sort keys %node) {
+		my @node = @{$node{$key}};
+		my $nodename = $name.($name ne '' ? '.' : '').$key;
+		my @nodeoid = (@oid, $node[0]);
+		if ($node[1] eq 'CTLTYPE_NODE') {
+			if (exists $node_map{$nodename}) {
+				$node = \%mib;
+				$ctlname = $node_map{$nodename};
+				foreach my $part (split /\./, $ctlname) {
+					$node = \%{@{$$node{$part}}[2]};
+				}
+			} else {
+				$node = $node[2];
+			}
+			&build_sysctl($node, $nodename, \@nodeoid);
+		} elsif ($node[1] ne '') {
+			$sysctl{$nodename} = \@nodeoid;
+		}
+	}
+}
+
+foreach my $ctl (@ctls) {
+	$ctls{$ctl} = $ctl;
+}
+
+# Build MIB
+foreach my $header (@headers) {
+	&debug("Processing $header...");
+	open HEADER, "/usr/include/$header" ||
+	    print STDERR "Failed to open $header\n";
+	while (<HEADER>) {
+		if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ ||
+		    $_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ ||
+		    $_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) {
+			if ($1 eq 'CTL_NAMES') {
+				# Top level.
+				$node = \%mib;
+			} else {
+				# Node.
+				my $nodename = lc($2);
+				if ($header =~ /^netinet\//) {
+					$ctlname = "net.inet.$nodename";
+				} elsif ($header =~ /^netinet6\//) {
+					$ctlname = "net.inet6.$nodename";
+				} elsif ($header =~ /^net\//) {
+					$ctlname = "net.$nodename";
+				} else {
+					$ctlname = "$nodename";
+					$ctlname =~ s/^(fs|net|kern)_/$1\./;
+				}
+				if (exists $ctl_map{$ctlname}) {
+					$ctlname = $ctl_map{$ctlname};
+				}
+				if (not exists $ctls{$ctlname}) {
+					&debug("Ignoring $ctlname...");
+					next;
+				}
+
+				# Walk down from the top of the MIB.
+				$node = \%mib;
+				foreach my $part (split /\./, $ctlname) {
+					if (not exists $$node{$part}) {
+						&debug("Missing node $part");
+						$$node{$part} = [ 0, '', {} ];
+					}
+					$node = \%{@{$$node{$part}}[2]};
+				}
+			}
+
+			# Populate current node with entries.
+			my $i = -1;
+			while (defined($_) && $_ !~ /^}/) {
+				$_ = <HEADER>;
+				$i++ if $_ =~ /{.*}/;
+				next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/;
+				$$node{$1} = [ $i, $2, {} ];
+			}
+		}
+	}
+	close HEADER;
+}
+
+&build_sysctl(\%mib, "", []);
+
+print <<EOF;
+// mksysctl_openbsd.pl
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall;
+
+type mibentry struct {
+	ctlname string
+	ctloid []_C_int
+}
+
+var sysctlMib = []mibentry {
+EOF
+
+foreach my $name (sort keys %sysctl) {
+	my @oid = @{$sysctl{$name}};
+	print "\t{ \"$name\", []_C_int{ ", join(', ', @oid), " } }, \n";
+}
+
+print <<EOF;
+}
+EOF
diff --git a/src/pkg/syscall/mksysnum_netbsd.pl b/src/pkg/syscall/mksysnum_netbsd.pl
new file mode 100755
index 0000000..a300810
--- /dev/null
+++ b/src/pkg/syscall/mksysnum_netbsd.pl
@@ -0,0 +1,51 @@
+#!/usr/bin/perl
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+#
+# Generate system call table for OpenBSD from master list
+# (for example, /usr/src/sys/kern/syscalls.master).
+
+use strict;
+
+my $command = "mksysnum_netbsd.pl " . join(' ', @ARGV);
+
+print <<EOF;
+// $command
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+EOF
+
+my $line = '';
+while(<>){
+	if($line =~ /^(.*)\\$/) {
+		# Handle continuation
+		$line = $1;
+		$_ =~ s/^\s+//;
+		$line .= $_;
+	} else {
+		# New line
+		$line = $_;
+	}
+	next if $line =~ /\\$/;
+	if($line =~ /^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$/) {
+		my $num = $1;
+		my $proto = $6;
+		my $compat = $8;
+		my $name = "$7_$9";
+
+		$name = "$7_$11" if $11 ne '';
+		$name =~ y/a-z/A-Z/;
+
+		if($compat eq '' || $compat eq '30' || $compat eq '50') {
+			print "	$name = $num;  // $proto\n";
+		}
+	}
+}
+
+print <<EOF;
+)
+EOF
diff --git a/src/pkg/syscall/netlink_linux.go b/src/pkg/syscall/netlink_linux.go
index 62d9e15..dc0f684 100644
--- a/src/pkg/syscall/netlink_linux.go
+++ b/src/pkg/syscall/netlink_linux.go
@@ -63,31 +63,28 @@ func newNetlinkRouteRequest(proto, seq, family int) []byte {
 // NetlinkRIB returns routing information base, as known as RIB,
 // which consists of network facility information, states and
 // parameters.
-func NetlinkRIB(proto, family int) ([]byte, int) {
+func NetlinkRIB(proto, family int) ([]byte, error) {
 	var (
-		s     int
-		e     int
 		lsanl SockaddrNetlink
-		seq   int
 		tab   []byte
 	)
 
-	s, e = Socket(AF_NETLINK, SOCK_RAW, 0)
-	if e != 0 {
+	s, e := Socket(AF_NETLINK, SOCK_RAW, 0)
+	if e != nil {
 		return nil, e
 	}
 	defer Close(s)
 
 	lsanl.Family = AF_NETLINK
 	e = Bind(s, &lsanl)
-	if e != 0 {
+	if e != nil {
 		return nil, e
 	}
 
-	seq++
+	seq := 1
 	wb := newNetlinkRouteRequest(proto, seq, family)
 	e = Sendto(s, wb, 0, &lsanl)
-	if e != 0 {
+	if e != nil {
 		return nil, e
 	}
 
@@ -100,7 +97,7 @@ func NetlinkRIB(proto, family int) ([]byte, int) {
 
 		rb = make([]byte, Getpagesize())
 		nr, _, e = Recvfrom(s, rb, 0)
-		if e != 0 {
+		if e != nil {
 			return nil, e
 		}
 		if nr < NLMSG_HDRLEN {
@@ -111,7 +108,7 @@ func NetlinkRIB(proto, family int) ([]byte, int) {
 
 		msgs, _ := ParseNetlinkMessage(rb)
 		for _, m := range msgs {
-			if lsa, e = Getsockname(s); e != 0 {
+			if lsa, e = Getsockname(s); e != nil {
 				return nil, e
 			}
 			switch v := lsa.(type) {
@@ -132,7 +129,7 @@ func NetlinkRIB(proto, family int) ([]byte, int) {
 	}
 
 done:
-	return tab, 0
+	return tab, nil
 }
 
 // NetlinkMessage represents the netlink message.
@@ -143,18 +140,18 @@ type NetlinkMessage struct {
 
 // ParseNetlinkMessage parses buf as netlink messages and returns
 // the slice containing the NetlinkMessage structs.
-func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, int) {
+func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, error) {
 	var (
 		h    *NlMsghdr
 		dbuf []byte
 		dlen int
-		e    int
+		e    error
 		msgs []NetlinkMessage
 	)
 
 	for len(buf) >= NLMSG_HDRLEN {
 		h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf)
-		if e != 0 {
+		if e != nil {
 			break
 		}
 		m := NetlinkMessage{}
@@ -167,12 +164,12 @@ func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, int) {
 	return msgs, e
 }
 
-func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, int) {
+func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, error) {
 	h := (*NlMsghdr)(unsafe.Pointer(&buf[0]))
 	if h.Len < NLMSG_HDRLEN || int(h.Len) > len(buf) {
 		return nil, nil, 0, EINVAL
 	}
-	return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), 0
+	return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil
 }
 
 // NetlinkRouteAttr represents the netlink route attribute.
@@ -184,13 +181,13 @@ type NetlinkRouteAttr struct {
 // ParseNetlinkRouteAttr parses msg's payload as netlink route
 // attributes and returns the slice containing the NetlinkRouteAttr
 // structs.
-func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
+func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, error) {
 	var (
 		buf   []byte
 		a     *RtAttr
 		alen  int
 		vbuf  []byte
-		e     int
+		e     error
 		attrs []NetlinkRouteAttr
 	)
 
@@ -207,7 +204,7 @@ func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
 
 	for len(buf) >= SizeofRtAttr {
 		a, vbuf, alen, e = netlinkRouteAttrAndValue(buf)
-		if e != 0 {
+		if e != nil {
 			break
 		}
 		ra := NetlinkRouteAttr{}
@@ -217,13 +214,13 @@ func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
 		buf = buf[alen:]
 	}
 
-	return attrs, 0
+	return attrs, nil
 }
 
-func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, int) {
+func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, error) {
 	h := (*RtAttr)(unsafe.Pointer(&buf[0]))
 	if h.Len < SizeofRtAttr || int(h.Len) > len(buf) {
 		return nil, nil, 0, EINVAL
 	}
-	return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), 0
+	return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), nil
 }
diff --git a/src/pkg/syscall/route_bsd.go b/src/pkg/syscall/route_bsd.go
index f6b124b..e17d976 100644
--- a/src/pkg/syscall/route_bsd.go
+++ b/src/pkg/syscall/route_bsd.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd openbsd
+// +build darwin freebsd netbsd openbsd
 
 // Routing sockets and messages
 
@@ -29,29 +29,24 @@ func rsaAlignOf(salen int) int {
 // RouteRIB returns routing information base, as known as RIB,
 // which consists of network facility information, states and
 // parameters.
-func RouteRIB(facility, param int) ([]byte, int) {
-	var (
-		tab []byte
-		e   int
-	)
-
+func RouteRIB(facility, param int) ([]byte, error) {
 	mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
 
 	// Find size.
 	n := uintptr(0)
-	if e = sysctl(mib, nil, &n, nil, 0); e != 0 {
-		return nil, e
+	if err := sysctl(mib, nil, &n, nil, 0); err != nil {
+		return nil, err
 	}
 	if n == 0 {
-		return nil, 0
+		return nil, nil
 	}
 
-	tab = make([]byte, n)
-	if e = sysctl(mib, &tab[0], &n, nil, 0); e != 0 {
-		return nil, e
+	tab := make([]byte, n)
+	if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil {
+		return nil, err
 	}
 
-	return tab[:n], 0
+	return tab[:n], nil
 }
 
 // RoutingMessage represents a routing message.
@@ -90,8 +85,8 @@ func (m *RouteMessage) sockaddr() []Sockaddr {
 		rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
 		switch i {
 		case RTAX_DST, RTAX_GATEWAY:
-			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
-			if e != 0 {
+			sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if err != nil {
 				return nil
 			}
 			if i == RTAX_DST {
@@ -133,8 +128,8 @@ func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) {
 	if m.Header.Addrs&RTA_IFP == 0 {
 		return nil
 	}
-	sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
-	if e != 0 {
+	sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
+	if err != nil {
 		return nil
 	}
 	return append(sas, sa)
@@ -162,12 +157,21 @@ func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
 		rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
 		switch i {
 		case RTAX_IFA:
-			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
-			if e != 0 {
+			sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if err != nil {
+				return nil
+			}
+			sas = append(sas, sa)
+		case RTAX_NETMASK:
+			if rsa.Family == AF_UNSPEC {
+				rsa.Family = AF_INET // an old fasion, AF_UNSPEC means AF_INET
+			}
+			sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+			if err != nil {
 				return nil
 			}
 			sas = append(sas, sa)
-		case RTAX_NETMASK, RTAX_BRD:
+		case RTAX_BRD:
 			// nothing to do
 		}
 		buf = buf[rsaAlignOf(int(rsa.Len)):]
@@ -178,7 +182,7 @@ func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
 
 // ParseRoutingMessage parses buf as routing messages and returns
 // the slice containing the RoutingMessage interfaces.
-func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) {
+func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, err error) {
 	for len(buf) >= anyMessageLen {
 		any := (*anyMessage)(unsafe.Pointer(&buf[0]))
 		if any.Version != RTM_VERSION {
@@ -187,11 +191,11 @@ func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) {
 		msgs = append(msgs, any.toRoutingMessage(buf))
 		buf = buf[any.Msglen:]
 	}
-	return msgs, 0
+	return msgs, nil
 }
 
 // ParseRoutingMessage parses msg's payload as raw sockaddrs and
 // returns the slice containing the Sockaddr interfaces.
-func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, errno int) {
-	return append(sas, msg.sockaddr()...), 0
+func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, err error) {
+	return append(sas, msg.sockaddr()...), nil
 }
diff --git a/src/pkg/syscall/route_darwin.go b/src/pkg/syscall/route_darwin.go
index 9d3a701..410e70a 100644
--- a/src/pkg/syscall/route_darwin.go
+++ b/src/pkg/syscall/route_darwin.go
@@ -63,7 +63,7 @@ func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
 		switch i {
 		case RTAX_IFA:
 			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
-			if e != 0 {
+			if e != nil {
 				return nil
 			}
 			sas = append(sas, sa)
diff --git a/src/pkg/syscall/route_freebsd.go b/src/pkg/syscall/route_freebsd.go
index 0d61d08..094e170 100644
--- a/src/pkg/syscall/route_freebsd.go
+++ b/src/pkg/syscall/route_freebsd.go
@@ -63,7 +63,7 @@ func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
 		switch i {
 		case RTAX_IFA:
 			sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
-			if e != 0 {
+			if e != nil {
 				return nil
 			}
 			sas = append(sas, sa)
diff --git a/src/pkg/syscall/route_netbsd.go b/src/pkg/syscall/route_netbsd.go
new file mode 100644
index 0000000..d6d9031
--- /dev/null
+++ b/src/pkg/syscall/route_netbsd.go
@@ -0,0 +1,35 @@
+// Copyright 2011 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.
+
+// Routing sockets and messages for NetBSD
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+	switch any.Type {
+	case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+		p := (*RouteMessage)(unsafe.Pointer(any))
+		rtm := &RouteMessage{}
+		rtm.Header = p.Header
+		rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
+		return rtm
+	case RTM_IFINFO:
+		p := (*InterfaceMessage)(unsafe.Pointer(any))
+		ifm := &InterfaceMessage{}
+		ifm.Header = p.Header
+		ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
+		return ifm
+	case RTM_NEWADDR, RTM_DELADDR:
+		p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+		ifam := &InterfaceAddrMessage{}
+		ifam.Header = p.Header
+		ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
+		return ifam
+	}
+	return nil
+}
diff --git a/src/pkg/syscall/sockcmsg_linux.go b/src/pkg/syscall/sockcmsg_linux.go
index b025ca5..0b4caa1 100644
--- a/src/pkg/syscall/sockcmsg_linux.go
+++ b/src/pkg/syscall/sockcmsg_linux.go
@@ -26,7 +26,7 @@ func UnixCredentials(ucred *Ucred) []byte {
 // ParseUnixCredentials decodes a socket control message that contains
 // credentials in a Ucred structure. To receive such a message, the
 // SO_PASSCRED option must be enabled on the socket.
-func ParseUnixCredentials(msg *SocketControlMessage) (*Ucred, int) {
+func ParseUnixCredentials(msg *SocketControlMessage) (*Ucred, error) {
 	if msg.Header.Level != SOL_SOCKET {
 		return nil, EINVAL
 	}
@@ -34,5 +34,5 @@ func ParseUnixCredentials(msg *SocketControlMessage) (*Ucred, int) {
 		return nil, EINVAL
 	}
 	ucred := *(*Ucred)(unsafe.Pointer(&msg.Data[0]))
-	return &ucred, 0
+	return &ucred, nil
 }
diff --git a/src/pkg/syscall/sockcmsg_unix.go b/src/pkg/syscall/sockcmsg_unix.go
index c9872ae..d279dec 100644
--- a/src/pkg/syscall/sockcmsg_unix.go
+++ b/src/pkg/syscall/sockcmsg_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 // Socket control messages
 
@@ -47,17 +47,17 @@ type SocketControlMessage struct {
 	Data   []byte
 }
 
-func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, int) {
+func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, error) {
 	var (
 		h     *Cmsghdr
 		dbuf  []byte
-		e     int
+		e     error
 		cmsgs []SocketControlMessage
 	)
 
 	for len(buf) >= CmsgLen(0) {
 		h, dbuf, e = socketControlMessageHeaderAndData(buf)
-		if e != 0 {
+		if e != nil {
 			break
 		}
 		m := SocketControlMessage{}
@@ -70,12 +70,12 @@ func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, int) {
 	return cmsgs, e
 }
 
-func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, int) {
+func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, error) {
 	h := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
 	if h.Len < SizeofCmsghdr || int(h.Len) > len(buf) {
 		return nil, nil, EINVAL
 	}
-	return h, buf[cmsgAlignOf(SizeofCmsghdr):], 0
+	return h, buf[cmsgAlignOf(SizeofCmsghdr):], nil
 }
 
 // UnixRights encodes a set of open file descriptors into a socket
@@ -99,7 +99,7 @@ func UnixRights(fds ...int) []byte {
 
 // ParseUnixRights decodes a socket control message that contains an
 // integer array of open file descriptors from another process.
-func ParseUnixRights(msg *SocketControlMessage) ([]int, int) {
+func ParseUnixRights(msg *SocketControlMessage) ([]int, error) {
 	if msg.Header.Level != SOL_SOCKET {
 		return nil, EINVAL
 	}
@@ -111,5 +111,5 @@ func ParseUnixRights(msg *SocketControlMessage) ([]int, int) {
 		fds[j] = int(*(*int32)(unsafe.Pointer(&msg.Data[i])))
 		j++
 	}
-	return fds, 0
+	return fds, nil
 }
diff --git a/src/pkg/syscall/syscall.go b/src/pkg/syscall/syscall.go
index 9f777f5..b10358a 100644
--- a/src/pkg/syscall/syscall.go
+++ b/src/pkg/syscall/syscall.go
@@ -9,8 +9,9 @@
 // packages rather than this one if you can.
 // For details of the functions and data types in this package consult
 // the manuals for the appropriate operating system.
-// These calls return errno == 0 to indicate success; otherwise
-// errno is an operating system error number describing the failure.
+// These calls return err == nil to indicate success; otherwise
+// err is an operating system error describing the failure.
+// On most systems, that error has type syscall.Errno.
 package syscall
 
 // StringByteSlice returns a NUL-terminated slice of bytes
@@ -26,5 +27,13 @@ func StringByteSlice(s string) []byte {
 func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
 
 // Single-word zero for use when we need a valid pointer to 0 bytes.
-// See mksyscall.sh.
+// See mksyscall.pl.
 var _zero uintptr
+
+func (ts *Timespec) Unix() (sec int64, nsec int64) {
+	return int64(ts.Sec), int64(ts.Nsec)
+}
+
+func (tv *Timeval) Unix() (sec int64, nsec int64) {
+	return int64(tv.Sec), int64(tv.Usec) * 1000
+}
diff --git a/src/pkg/syscall/syscall_386.go b/src/pkg/syscall/syscall_386.go
deleted file mode 100644
index cb948b8..0000000
--- a/src/pkg/syscall/syscall_386.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 syscall
-
-const ARCH = "386"
diff --git a/src/pkg/syscall/syscall_amd64.go b/src/pkg/syscall/syscall_amd64.go
deleted file mode 100644
index 75c3eac..0000000
--- a/src/pkg/syscall/syscall_amd64.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 syscall
-
-const ARCH = "amd64"
diff --git a/src/pkg/syscall/syscall_arm.go b/src/pkg/syscall/syscall_arm.go
deleted file mode 100644
index b9d1ca0..0000000
--- a/src/pkg/syscall/syscall_arm.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2010 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 syscall
-
-const ARCH = "arm"
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go
index 59c6f45..16f2098 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd openbsd
+// +build darwin freebsd netbsd openbsd
 
 // BSD system call wrappers shared by *BSD based systems
 // including OS X (Darwin) and FreeBSD.  Like the other
@@ -12,7 +12,10 @@
 
 package syscall
 
-import "unsafe"
+import (
+	"runtime"
+	"unsafe"
+)
 
 /*
  * Pseudo-system calls
@@ -22,22 +25,22 @@ import "unsafe"
 // even linking this function into the binary.  See ../os/getwd.go.
 const ImplementsGetwd = false
 
-func Getwd() (string, int) { return "", ENOTSUP }
+func Getwd() (string, error) { return "", ENOTSUP }
 
 /*
  * Wrapped
  */
 
-//sysnb	getgroups(ngid int, gid *_Gid_t) (n int, errno int)
-//sysnb	setgroups(ngid int, gid *_Gid_t) (errno int)
+//sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
+//sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
 
-func Getgroups() (gids []int, errno int) {
+func Getgroups() (gids []int, err error) {
 	n, err := getgroups(0, nil)
-	if err != 0 {
-		return nil, errno
+	if err != nil {
+		return nil, err
 	}
 	if n == 0 {
-		return nil, 0
+		return nil, nil
 	}
 
 	// Sanity check group count.  Max is 16 on BSD.
@@ -47,8 +50,8 @@ func Getgroups() (gids []int, errno int) {
 
 	a := make([]_Gid_t, n)
 	n, err = getgroups(n, &a[0])
-	if err != 0 {
-		return nil, errno
+	if err != nil {
+		return nil, err
 	}
 	gids = make([]int, n)
 	for i, v := range a[0:n] {
@@ -57,7 +60,7 @@ func Getgroups() (gids []int, errno int) {
 	return
 }
 
-func Setgroups(gids []int) (errno int) {
+func Setgroups(gids []int) (err error) {
 	if len(gids) == 0 {
 		return setgroups(0, nil)
 	}
@@ -69,7 +72,7 @@ func Setgroups(gids []int) (errno int) {
 	return setgroups(len(a), &a[0])
 }
 
-func ReadDirent(fd int, buf []byte) (n int, errno int) {
+func ReadDirent(fd int, buf []byte) (n int, err error) {
 	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
 	// TODO(rsc): Can we use a single global basep for all calls?
 	return Getdirentries(fd, buf, new(uintptr))
@@ -126,38 +129,33 @@ func (w WaitStatus) StopSignal() int {
 
 func (w WaitStatus) TrapCause() int { return -1 }
 
-//sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
+//sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error)
 
-func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
 	var status _C_int
-	wpid, errno = wait4(pid, &status, options, rusage)
+	wpid, err = wait4(pid, &status, options, rusage)
 	if wstatus != nil {
 		*wstatus = WaitStatus(status)
 	}
 	return
 }
 
-func Sleep(ns int64) (errno int) {
-	tv := NsecToTimeval(ns)
-	return Select(0, nil, nil, nil, &tv)
-}
-
-//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
-//sys	bind(s int, addr uintptr, addrlen _Socklen) (errno int)
-//sys	connect(s int, addr uintptr, addrlen _Socklen) (errno int)
-//sysnb	socket(domain int, typ int, proto int) (fd int, errno int)
-//sys	getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int)
-//sys	setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int)
-//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
-//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
-//sys	Shutdown(s int, how int) (errno int)
+//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
+//sys	bind(s int, addr uintptr, addrlen _Socklen) (err error)
+//sys	connect(s int, addr uintptr, addrlen _Socklen) (err error)
+//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
+//sys	getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error)
+//sys	setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error)
+//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sys	Shutdown(s int, how int) (err error)
 
 // For testing: clients can set this flag to force
 // creation of IPv6 sockets to return EAFNOSUPPORT.
 var SocketDisableIPv6 bool
 
 type Sockaddr interface {
-	sockaddr() (ptr uintptr, len _Socklen, errno int) // lowercase; only we can define Sockaddrs
+	sockaddr() (ptr uintptr, len _Socklen, err error) // lowercase; only we can define Sockaddrs
 }
 
 type SockaddrInet4 struct {
@@ -166,7 +164,7 @@ type SockaddrInet4 struct {
 	raw  RawSockaddrInet4
 }
 
-func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, error) {
 	if sa.Port < 0 || sa.Port > 0xFFFF {
 		return 0, 0, EINVAL
 	}
@@ -178,7 +176,7 @@ func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
 	for i := 0; i < len(sa.Addr); i++ {
 		sa.raw.Addr[i] = sa.Addr[i]
 	}
-	return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
+	return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), nil
 }
 
 type SockaddrInet6 struct {
@@ -188,7 +186,7 @@ type SockaddrInet6 struct {
 	raw    RawSockaddrInet6
 }
 
-func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, error) {
 	if sa.Port < 0 || sa.Port > 0xFFFF {
 		return 0, 0, EINVAL
 	}
@@ -201,7 +199,7 @@ func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
 	for i := 0; i < len(sa.Addr); i++ {
 		sa.raw.Addr[i] = sa.Addr[i]
 	}
-	return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
+	return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), nil
 }
 
 type SockaddrUnix struct {
@@ -209,7 +207,7 @@ type SockaddrUnix struct {
 	raw  RawSockaddrUnix
 }
 
-func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, error) {
 	name := sa.Name
 	n := len(name)
 	if n >= len(sa.raw.Path) || n == 0 {
@@ -220,10 +218,10 @@ func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
 	for i := 0; i < n; i++ {
 		sa.raw.Path[i] = int8(name[i])
 	}
-	return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), 0
+	return uintptr(unsafe.Pointer(&sa.raw)), _Socklen(sa.raw.Len), nil
 }
 
-func (sa *SockaddrDatalink) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrDatalink) sockaddr() (uintptr, _Socklen, error) {
 	if sa.Index == 0 {
 		return 0, 0, EINVAL
 	}
@@ -237,10 +235,10 @@ func (sa *SockaddrDatalink) sockaddr() (uintptr, _Socklen, int) {
 	for i := 0; i < len(sa.raw.Data); i++ {
 		sa.raw.Data[i] = sa.Data[i]
 	}
-	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrDatalink, 0
+	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrDatalink, nil
 }
 
-func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
 	switch rsa.Addr.Family {
 	case AF_LINK:
 		pp := (*RawSockaddrDatalink)(unsafe.Pointer(rsa))
@@ -255,7 +253,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		for i := 0; i < len(sa.Data); i++ {
 			sa.Data[i] = pp.Data[i]
 		}
-		return sa, 0
+		return sa, nil
 
 	case AF_UNIX:
 		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
@@ -273,7 +271,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		}
 		bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
 		sa.Name = string(bytes)
-		return sa, 0
+		return sa, nil
 
 	case AF_INET:
 		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
@@ -283,7 +281,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		for i := 0; i < len(sa.Addr); i++ {
 			sa.Addr[i] = pp.Addr[i]
 		}
-		return sa, 0
+		return sa, nil
 
 	case AF_INET6:
 		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
@@ -294,132 +292,168 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		for i := 0; i < len(sa.Addr); i++ {
 			sa.Addr[i] = pp.Addr[i]
 		}
-		return sa, 0
+		return sa, nil
 	}
 	return nil, EAFNOSUPPORT
 }
 
-func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
+func Accept(fd int) (nfd int, sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
-	nfd, errno = accept(fd, &rsa, &len)
-	if errno != 0 {
+	nfd, err = accept(fd, &rsa, &len)
+	if err != nil {
 		return
 	}
-	sa, errno = anyToSockaddr(&rsa)
-	if errno != 0 {
+	sa, err = anyToSockaddr(&rsa)
+	if err != nil {
 		Close(nfd)
 		nfd = 0
 	}
 	return
 }
 
-func Getsockname(fd int) (sa Sockaddr, errno int) {
+func Getsockname(fd int) (sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
-	if errno = getsockname(fd, &rsa, &len); errno != 0 {
+	if err = getsockname(fd, &rsa, &len); err != nil {
 		return
 	}
 	return anyToSockaddr(&rsa)
 }
 
-func Getpeername(fd int) (sa Sockaddr, errno int) {
+func Getpeername(fd int) (sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
-	if errno = getpeername(fd, &rsa, &len); errno != 0 {
+	if err = getpeername(fd, &rsa, &len); err != nil {
 		return
 	}
 	return anyToSockaddr(&rsa)
 }
 
-func Bind(fd int, sa Sockaddr) (errno int) {
+func Bind(fd int, sa Sockaddr) (err error) {
 	ptr, n, err := sa.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	return bind(fd, ptr, n)
 }
 
-func Connect(fd int, sa Sockaddr) (errno int) {
+func Connect(fd int, sa Sockaddr) (err error) {
 	ptr, n, err := sa.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	return connect(fd, ptr, n)
 }
 
-func Socket(domain, typ, proto int) (fd, errno int) {
+func Socket(domain, typ, proto int) (fd int, err error) {
 	if domain == AF_INET6 && SocketDisableIPv6 {
 		return -1, EAFNOSUPPORT
 	}
-	fd, errno = socket(domain, typ, proto)
+	fd, err = socket(domain, typ, proto)
 	return
 }
 
-//sysnb socketpair(domain int, typ int, proto int, fd *[2]int) (errno int)
+//sysnb socketpair(domain int, typ int, proto int, fd *[2]int) (err error)
 
-func Socketpair(domain, typ, proto int) (fd [2]int, errno int) {
-	errno = socketpair(domain, typ, proto, &fd)
+func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
+	err = socketpair(domain, typ, proto, &fd)
 	return
 }
 
-func GetsockoptInt(fd, level, opt int) (value, errno int) {
+func GetsockoptByte(fd, level, opt int) (value byte, err error) {
+	var n byte
+	vallen := _Socklen(1)
+	err = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), &vallen)
+	return n, err
+}
+
+func GetsockoptInt(fd, level, opt int) (value int, err error) {
 	var n int32
 	vallen := _Socklen(4)
-	errno = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), &vallen)
-	return int(n), errno
+	err = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), &vallen)
+	return int(n), err
+}
+
+func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
+	vallen := _Socklen(4)
+	err = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value[0])), &vallen)
+	return value, err
+}
+
+func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
+	var value IPMreq
+	vallen := _Socklen(SizeofIPMreq)
+	err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+	return &value, err
+}
+
+func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
+	var value IPv6Mreq
+	vallen := _Socklen(SizeofIPv6Mreq)
+	err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+	return &value, err
+}
+
+func SetsockoptByte(fd, level, opt int, value byte) (err error) {
+	var n = byte(value)
+	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 1)
 }
 
-func SetsockoptInt(fd, level, opt int, value int) (errno int) {
+func SetsockoptInt(fd, level, opt int, value int) (err error) {
 	var n = int32(value)
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
 }
 
-func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
+func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
+	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value[0])), 4)
+}
+
+func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(tv)), unsafe.Sizeof(*tv))
 }
 
-func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
+func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(l)), unsafe.Sizeof(*l))
 }
 
-func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) {
+func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
 }
 
-func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
 }
 
-func SetsockoptString(fd, level, opt int, s string) (errno int) {
+func SetsockoptString(fd, level, opt int, s string) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&[]byte(s)[0])), uintptr(len(s)))
 }
 
-//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
+//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
 
-func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
+func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
-	if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
+	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
 		return
 	}
-	from, errno = anyToSockaddr(&rsa)
+	from, err = anyToSockaddr(&rsa)
 	return
 }
 
-//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
+//sys sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error)
 
-func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
+func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
 	ptr, n, err := to.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	return sendto(fd, p, flags, ptr, n)
 }
 
-//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
+//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
 
-func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
+func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
 	var msg Msghdr
 	var rsa RawSockaddrAny
 	msg.Name = (*byte)(unsafe.Pointer(&rsa))
@@ -441,27 +475,27 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
 	}
 	msg.Iov = &iov
 	msg.Iovlen = 1
-	if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
+	if n, err = recvmsg(fd, &msg, flags); err != nil {
 		return
 	}
 	oobn = int(msg.Controllen)
 	recvflags = int(msg.Flags)
 	// source address is only specified if the socket is unconnected
 	if rsa.Addr.Family != AF_UNSPEC {
-		from, errno = anyToSockaddr(&rsa)
+		from, err = anyToSockaddr(&rsa)
 	}
 	return
 }
 
-//sys	sendmsg(s int, msg *Msghdr, flags int) (errno int)
+//sys	sendmsg(s int, msg *Msghdr, flags int) (err error)
 
-func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
 	var ptr uintptr
 	var salen _Socklen
 	if to != nil {
-		var err int
+		var err error
 		ptr, salen, err = to.sockaddr()
-		if err != 0 {
+		if err != nil {
 			return err
 		}
 	}
@@ -485,24 +519,15 @@ func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
 	}
 	msg.Iov = &iov
 	msg.Iovlen = 1
-	if errno = sendmsg(fd, &msg, flags); errno != 0 {
+	if err = sendmsg(fd, &msg, flags); err != nil {
 		return
 	}
 	return
 }
 
-// TODO:
-// FreeBSD has IP_SENDIF.  Darwin probably needs BSDLLCTest, see:
-// http://developer.apple.com/mac/library/samplecode/BSDLLCTest/index.html
+//sys	kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error)
 
-// BindToDevice binds the socket associated with fd to device.
-func BindToDevice(fd int, device string) (errno int) {
-	return ENOSYS
-}
-
-//sys	kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int)
-
-func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno int) {
+func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, err error) {
 	var change, event uintptr
 	if len(changes) > 0 {
 		change = uintptr(unsafe.Pointer(&changes[0]))
@@ -513,106 +538,90 @@ func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, errno
 	return kevent(kq, change, len(changes), event, len(events), timeout)
 }
 
-//sys	sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) = SYS___SYSCTL
-
-// Translate "kern.hostname" to []_C_int{0,1,2,3}.
-func nametomib(name string) (mib []_C_int, errno int) {
-	const siz = unsafe.Sizeof(mib[0])
+//sys	sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
 
-	// NOTE(rsc): It seems strange to set the buffer to have
-	// size CTL_MAXNAME+2 but use only CTL_MAXNAME
-	// as the size.  I don't know why the +2 is here, but the
-	// kernel uses +2 for its own implementation of this function.
-	// I am scared that if we don't include the +2 here, the kernel
-	// will silently write 2 words farther than we specify
-	// and we'll get memory corruption.
-	var buf [CTL_MAXNAME + 2]_C_int
-	n := uintptr(CTL_MAXNAME) * siz
-
-	p := (*byte)(unsafe.Pointer(&buf[0]))
-	bytes := StringByteSlice(name)
-
-	// Magic sysctl: "setting" 0.3 to a string name
-	// lets you read back the array of integers form.
-	if errno = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); errno != 0 {
-		return nil, errno
-	}
-	return buf[0 : n/siz], 0
-}
-
-func Sysctl(name string) (value string, errno int) {
+func Sysctl(name string) (value string, err error) {
 	// Translate name to mib number.
-	mib, errno := nametomib(name)
-	if errno != 0 {
-		return "", errno
+	mib, err := nametomib(name)
+	if err != nil {
+		return "", err
 	}
 
 	// Find size.
 	n := uintptr(0)
-	if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 {
-		return "", errno
+	if err = sysctl(mib, nil, &n, nil, 0); err != nil {
+		return "", err
 	}
 	if n == 0 {
-		return "", 0
+		// TODO(jsing): Remove after OpenBSD 5.2 release.
+		// Work around a bug that was fixed after OpenBSD 5.0.
+		// The length for kern.hostname and kern.domainname is always
+		// returned as 0 when a nil value is passed for oldp.
+		if runtime.GOOS == "openbsd" && (name == "kern.hostname" || name == "kern.domainname") {
+			// MAXHOSTNAMELEN
+			n = 256
+		} else {
+			return "", nil
+		}
 	}
 
 	// Read into buffer of that size.
 	buf := make([]byte, n)
-	if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
-		return "", errno
+	if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil {
+		return "", err
 	}
 
 	// Throw away terminating NUL.
 	if n > 0 && buf[n-1] == '\x00' {
 		n--
 	}
-	return string(buf[0:n]), 0
+	return string(buf[0:n]), nil
 }
 
-func SysctlUint32(name string) (value uint32, errno int) {
+func SysctlUint32(name string) (value uint32, err error) {
 	// Translate name to mib number.
-	mib, errno := nametomib(name)
-	if errno != 0 {
-		return 0, errno
+	mib, err := nametomib(name)
+	if err != nil {
+		return 0, err
 	}
 
 	// Read into buffer of that size.
 	n := uintptr(4)
 	buf := make([]byte, 4)
-	if errno = sysctl(mib, &buf[0], &n, nil, 0); errno != 0 {
-		return 0, errno
+	if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil {
+		return 0, err
 	}
 	if n != 4 {
 		return 0, EIO
 	}
-	return *(*uint32)(unsafe.Pointer(&buf[0])), 0
+	return *(*uint32)(unsafe.Pointer(&buf[0])), nil
 }
 
-//sys	utimes(path string, timeval *[2]Timeval) (errno int)
-func Utimes(path string, tv []Timeval) (errno int) {
+//sys	utimes(path string, timeval *[2]Timeval) (err error)
+func Utimes(path string, tv []Timeval) (err error) {
 	if len(tv) != 2 {
 		return EINVAL
 	}
 	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
 }
 
-//sys	futimes(fd int, timeval *[2]Timeval) (errno int)
-func Futimes(fd int, tv []Timeval) (errno int) {
+//sys	futimes(fd int, timeval *[2]Timeval) (err error)
+func Futimes(fd int, tv []Timeval) (err error) {
 	if len(tv) != 2 {
 		return EINVAL
 	}
 	return futimes(fd, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
 }
 
-//sys	fcntl(fd int, cmd int, arg int) (val int, errno int)
+//sys	fcntl(fd int, cmd int, arg int) (val int, err error)
 
 // TODO: wrap
-//	Acct(name nil-string) (errno int)
-//	Gethostuuid(uuid *byte, timeout *Timespec) (errno int)
-//	Madvise(addr *byte, len int, behav int) (errno int)
-//	Mprotect(addr *byte, len int, prot int) (errno int)
-//	Msync(addr *byte, len int, flags int) (errno int)
-//	Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, errno int)
+//	Acct(name nil-string) (err error)
+//	Gethostuuid(uuid *byte, timeout *Timespec) (err error)
+//	Madvise(addr *byte, len int, behav int) (err error)
+//	Mprotect(addr *byte, len int, prot int) (err error)
+//	Msync(addr *byte, len int, flags int) (err error)
+//	Ptrace(req int, pid int, addr uintptr, data int) (ret uintptr, err error)
 
 var mapper = &mmapper{
 	active: make(map[*byte][]byte),
@@ -620,10 +629,10 @@ var mapper = &mmapper{
 	munmap: munmap,
 }
 
-func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
 	return mapper.Mmap(fd, offset, length, prot, flags)
 }
 
-func Munmap(b []byte) (errno int) {
+func Munmap(b []byte) (err error) {
 	return mapper.Munmap(b)
 }
diff --git a/src/pkg/syscall/syscall_darwin.go b/src/pkg/syscall/syscall_darwin.go
index 1bbf1b1..cf876ed 100644
--- a/src/pkg/syscall/syscall_darwin.go
+++ b/src/pkg/syscall/syscall_darwin.go
@@ -14,8 +14,6 @@ package syscall
 
 import "unsafe"
 
-const OS = "darwin"
-
 type SockaddrDatalink struct {
 	Len    uint8
 	Family uint8
@@ -28,6 +26,31 @@ type SockaddrDatalink struct {
 	raw    RawSockaddrDatalink
 }
 
+// Translate "kern.hostname" to []_C_int{0,1,2,3}.
+func nametomib(name string) (mib []_C_int, err error) {
+	const siz = unsafe.Sizeof(mib[0])
+
+	// NOTE(rsc): It seems strange to set the buffer to have
+	// size CTL_MAXNAME+2 but use only CTL_MAXNAME
+	// as the size.  I don't know why the +2 is here, but the
+	// kernel uses +2 for its own implementation of this function.
+	// I am scared that if we don't include the +2 here, the kernel
+	// will silently write 2 words farther than we specify
+	// and we'll get memory corruption.
+	var buf [CTL_MAXNAME + 2]_C_int
+	n := uintptr(CTL_MAXNAME) * siz
+
+	p := (*byte)(unsafe.Pointer(&buf[0]))
+	bytes := StringByteSlice(name)
+
+	// Magic sysctl: "setting" 0.3 to a string name
+	// lets you read back the array of integers form.
+	if err = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); err != nil {
+		return nil, err
+	}
+	return buf[0 : n/siz], nil
+}
+
 // ParseDirent parses up to max directory entries in buf,
 // appending the names to names.  It returns the number
 // bytes consumed from buf, the number of entries added
@@ -56,22 +79,22 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
 	return origlen - len(buf), count, names
 }
 
-//sys   ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
-func PtraceAttach(pid int) (errno int) { return ptrace(PT_ATTACH, pid, 0, 0) }
-func PtraceDetach(pid int) (errno int) { return ptrace(PT_DETACH, pid, 0, 0) }
+//sys   ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
+func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
+func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
 
-//sysnb pipe() (r int, w int, errno int)
+//sysnb pipe() (r int, w int, err error)
 
-func Pipe(p []int) (errno int) {
+func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return EINVAL
 	}
-	p[0], p[1], errno = pipe()
+	p[0], p[1], err = pipe()
 	return
 }
 
 // TODO
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	return -1, ENOSYS
 }
 
@@ -79,97 +102,97 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno
  * Wrapped
  */
 
-//sys	kill(pid int, signum int, posix int) (errno int)
+//sys	kill(pid int, signum int, posix int) (err error)
 
-func Kill(pid int, signum int) (errno int) { return kill(pid, signum, 1) }
+func Kill(pid int, signum int) (err error) { return kill(pid, signum, 1) }
 
 /*
  * Exposed directly
  */
-//sys	Access(path string, mode uint32) (errno int)
-//sys	Adjtime(delta *Timeval, olddelta *Timeval) (errno int)
-//sys	Chdir(path string) (errno int)
-//sys	Chflags(path string, flags int) (errno int)
-//sys	Chmod(path string, mode uint32) (errno int)
-//sys	Chown(path string, uid int, gid int) (errno int)
-//sys	Chroot(path string) (errno int)
-//sys	Close(fd int) (errno int)
-//sysnb	Dup(fd int) (nfd int, errno int)
-//sysnb	Dup2(from int, to int) (errno int)
-//sys	Exchangedata(path1 string, path2 string, options int) (errno int)
+//sys	Access(path string, mode uint32) (err error)
+//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
+//sys	Chdir(path string) (err error)
+//sys	Chflags(path string, flags int) (err error)
+//sys	Chmod(path string, mode uint32) (err error)
+//sys	Chown(path string, uid int, gid int) (err error)
+//sys	Chroot(path string) (err error)
+//sys	Close(fd int) (err error)
+//sysnb	Dup(fd int) (nfd int, err error)
+//sysnb	Dup2(from int, to int) (err error)
+//sys	Exchangedata(path1 string, path2 string, options int) (err error)
 //sys	Exit(code int)
-//sys	Fchdir(fd int) (errno int)
-//sys	Fchflags(path string, flags int) (errno int)
-//sys	Fchmod(fd int, mode uint32) (errno int)
-//sys	Fchown(fd int, uid int, gid int) (errno int)
-//sys	Flock(fd int, how int) (errno int)
-//sys	Fpathconf(fd int, name int) (val int, errno int)
-//sys	Fstat(fd int, stat *Stat_t) (errno int) = SYS_FSTAT64
-//sys	Fstatfs(fd int, stat *Statfs_t) (errno int) = SYS_FSTATFS64
-//sys	Fsync(fd int) (errno int)
-//sys	Ftruncate(fd int, length int64) (errno int)
-//sys	Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) = SYS_GETDIRENTRIES64
+//sys	Fchdir(fd int) (err error)
+//sys	Fchflags(path string, flags int) (err error)
+//sys	Fchmod(fd int, mode uint32) (err error)
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Flock(fd int, how int) (err error)
+//sys	Fpathconf(fd int, name int) (val int, err error)
+//sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
+//sys	Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
+//sys	Fsync(fd int) (err error)
+//sys	Ftruncate(fd int, length int64) (err error)
+//sys	Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
 //sys	Getdtablesize() (size int)
 //sysnb	Getegid() (egid int)
 //sysnb	Geteuid() (uid int)
-//sys	Getfsstat(buf []Statfs_t, flags int) (n int, errno int) = SYS_GETFSSTAT64
+//sys	Getfsstat(buf []Statfs_t, flags int) (n int, err error) = SYS_GETFSSTAT64
 //sysnb	Getgid() (gid int)
-//sysnb	Getpgid(pid int) (pgid int, errno int)
+//sysnb	Getpgid(pid int) (pgid int, err error)
 //sysnb	Getpgrp() (pgrp int)
 //sysnb	Getpid() (pid int)
 //sysnb	Getppid() (ppid int)
-//sys	Getpriority(which int, who int) (prio int, errno int)
-//sysnb	Getrlimit(which int, lim *Rlimit) (errno int)
-//sysnb	Getrusage(who int, rusage *Rusage) (errno int)
-//sysnb	Getsid(pid int) (sid int, errno int)
+//sys	Getpriority(which int, who int) (prio int, err error)
+//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Getrusage(who int, rusage *Rusage) (err error)
+//sysnb	Getsid(pid int) (sid int, err error)
 //sysnb	Getuid() (uid int)
 //sysnb	Issetugid() (tainted bool)
-//sys	Kqueue() (fd int, errno int)
-//sys	Lchown(path string, uid int, gid int) (errno int)
-//sys	Link(path string, link string) (errno int)
-//sys	Listen(s int, backlog int) (errno int)
-//sys	Lstat(path string, stat *Stat_t) (errno int) = SYS_LSTAT64
-//sys	Mkdir(path string, mode uint32) (errno int)
-//sys	Mkfifo(path string, mode uint32) (errno int)
-//sys	Mknod(path string, mode uint32, dev int) (errno int)
-//sys	Open(path string, mode int, perm uint32) (fd int, errno int)
-//sys	Pathconf(path string, name int) (val int, errno int)
-//sys	Pread(fd int, p []byte, offset int64) (n int, errno int)
-//sys	Pwrite(fd int, p []byte, offset int64) (n int, errno int)
-//sys	Read(fd int, p []byte) (n int, errno int)
-//sys	Readlink(path string, buf []byte) (n int, errno int)
-//sys	Rename(from string, to string) (errno int)
-//sys	Revoke(path string) (errno int)
-//sys	Rmdir(path string) (errno int)
-//sys	Seek(fd int, offset int64, whence int) (newoffset int64, errno int) = SYS_LSEEK
-//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int)
-//sys	Setegid(egid int) (errno int)
-//sysnb	Seteuid(euid int) (errno int)
-//sysnb	Setgid(gid int) (errno int)
-//sys	Setlogin(name string) (errno int)
-//sysnb	Setpgid(pid int, pgid int) (errno int)
-//sys	Setpriority(which int, who int, prio int) (errno int)
-//sys	Setprivexec(flag int) (errno int)
-//sysnb	Setregid(rgid int, egid int) (errno int)
-//sysnb	Setreuid(ruid int, euid int) (errno int)
-//sysnb	Setrlimit(which int, lim *Rlimit) (errno int)
-//sysnb	Setsid() (pid int, errno int)
-//sysnb	Settimeofday(tp *Timeval) (errno int)
-//sysnb	Setuid(uid int) (errno int)
-//sys	Stat(path string, stat *Stat_t) (errno int) = SYS_STAT64
-//sys	Statfs(path string, stat *Statfs_t) (errno int) = SYS_STATFS64
-//sys	Symlink(path string, link string) (errno int)
-//sys	Sync() (errno int)
-//sys	Truncate(path string, length int64) (errno int)
+//sys	Kqueue() (fd int, err error)
+//sys	Lchown(path string, uid int, gid int) (err error)
+//sys	Link(path string, link string) (err error)
+//sys	Listen(s int, backlog int) (err error)
+//sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
+//sys	Mkdir(path string, mode uint32) (err error)
+//sys	Mkfifo(path string, mode uint32) (err error)
+//sys	Mknod(path string, mode uint32, dev int) (err error)
+//sys	Open(path string, mode int, perm uint32) (fd int, err error)
+//sys	Pathconf(path string, name int) (val int, err error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys	Read(fd int, p []byte) (n int, err error)
+//sys	Readlink(path string, buf []byte) (n int, err error)
+//sys	Rename(from string, to string) (err error)
+//sys	Revoke(path string) (err error)
+//sys	Rmdir(path string) (err error)
+//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
+//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
+//sys	Setegid(egid int) (err error)
+//sysnb	Seteuid(euid int) (err error)
+//sysnb	Setgid(gid int) (err error)
+//sys	Setlogin(name string) (err error)
+//sysnb	Setpgid(pid int, pgid int) (err error)
+//sys	Setpriority(which int, who int, prio int) (err error)
+//sys	Setprivexec(flag int) (err error)
+//sysnb	Setregid(rgid int, egid int) (err error)
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//sysnb	Setrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Setsid() (pid int, err error)
+//sysnb	Settimeofday(tp *Timeval) (err error)
+//sysnb	Setuid(uid int) (err error)
+//sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
+//sys	Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
+//sys	Symlink(path string, link string) (err error)
+//sys	Sync() (err error)
+//sys	Truncate(path string, length int64) (err error)
 //sys	Umask(newmask int) (oldmask int)
-//sys	Undelete(path string) (errno int)
-//sys	Unlink(path string) (errno int)
-//sys	Unmount(path string, flags int) (errno int)
-//sys	Write(fd int, p []byte) (n int, errno int)
-//sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int)
-//sys   munmap(addr uintptr, length uintptr) (errno int)
-//sys	read(fd int, buf *byte, nbuf int) (n int, errno int)
-//sys	write(fd int, buf *byte, nbuf int) (n int, errno int)
+//sys	Undelete(path string) (err error)
+//sys	Unlink(path string) (err error)
+//sys	Unmount(path string, flags int) (err error)
+//sys	Write(fd int, p []byte) (n int, err error)
+//sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
+//sys   munmap(addr uintptr, length uintptr) (err error)
+//sys	read(fd int, buf *byte, nbuf int) (n int, err error)
+//sys	write(fd int, buf *byte, nbuf int) (n int, err error)
 
 /*
  * Unimplemented
diff --git a/src/pkg/syscall/syscall_darwin_386.go b/src/pkg/syscall/syscall_darwin_386.go
index d76b228..9a8a97d 100644
--- a/src/pkg/syscall/syscall_darwin_386.go
+++ b/src/pkg/syscall/syscall_darwin_386.go
@@ -23,8 +23,8 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
 	return
 }
 
-//sysnb	gettimeofday(tp *Timeval) (sec int32, usec int32, errno int)
-func Gettimeofday(tv *Timeval) (errno int) {
+//sysnb	gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
+func Gettimeofday(tv *Timeval) (err error) {
 	// The tv passed to gettimeofday must be non-nil
 	// but is otherwise unused.  The answers come back
 	// in the two registers.
@@ -52,4 +52,4 @@ func (cmsg *Cmsghdr) SetLen(length int) {
 	cmsg.Len = uint32(length)
 }
 
-func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) // sic
+func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
diff --git a/src/pkg/syscall/syscall_darwin_amd64.go b/src/pkg/syscall/syscall_darwin_amd64.go
index ed43723..2d25e59 100644
--- a/src/pkg/syscall/syscall_darwin_amd64.go
+++ b/src/pkg/syscall/syscall_darwin_amd64.go
@@ -23,8 +23,8 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
 	return
 }
 
-//sysnb	gettimeofday(tp *Timeval) (sec int64, usec int32, errno int)
-func Gettimeofday(tv *Timeval) (errno int) {
+//sysnb	gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
+func Gettimeofday(tv *Timeval) (err error) {
 	// The tv passed to gettimeofday must be non-nil
 	// but is otherwise unused.  The answers come back
 	// in the two registers.
diff --git a/src/pkg/syscall/syscall_freebsd.go b/src/pkg/syscall/syscall_freebsd.go
index 18988c0..5be16da 100644
--- a/src/pkg/syscall/syscall_freebsd.go
+++ b/src/pkg/syscall/syscall_freebsd.go
@@ -14,8 +14,6 @@ package syscall
 
 import "unsafe"
 
-const OS = "freebsd"
-
 type SockaddrDatalink struct {
 	Len    uint8
 	Family uint8
@@ -28,6 +26,31 @@ type SockaddrDatalink struct {
 	raw    RawSockaddrDatalink
 }
 
+// Translate "kern.hostname" to []_C_int{0,1,2,3}.
+func nametomib(name string) (mib []_C_int, err error) {
+	const siz = unsafe.Sizeof(mib[0])
+
+	// NOTE(rsc): It seems strange to set the buffer to have
+	// size CTL_MAXNAME+2 but use only CTL_MAXNAME
+	// as the size.  I don't know why the +2 is here, but the
+	// kernel uses +2 for its own implementation of this function.
+	// I am scared that if we don't include the +2 here, the kernel
+	// will silently write 2 words farther than we specify
+	// and we'll get memory corruption.
+	var buf [CTL_MAXNAME + 2]_C_int
+	n := uintptr(CTL_MAXNAME) * siz
+
+	p := (*byte)(unsafe.Pointer(&buf[0]))
+	bytes := StringByteSlice(name)
+
+	// Magic sysctl: "setting" 0.3 to a string name
+	// lets you read back the array of integers form.
+	if err = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); err != nil {
+		return nil, err
+	}
+	return buf[0 : n/siz], nil
+}
+
 // ParseDirent parses up to max directory entries in buf,
 // appending the names to names.  It returns the number
 // bytes consumed from buf, the number of entries added
@@ -56,109 +79,120 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
 	return origlen - len(buf), count, names
 }
 
-//sysnb pipe() (r int, w int, errno int)
+//sysnb pipe() (r int, w int, err error)
 
-func Pipe(p []int) (errno int) {
+func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return EINVAL
 	}
-	p[0], p[1], errno = pipe()
+	p[0], p[1], err = pipe()
 	return
 }
 
 // TODO
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	return -1, ENOSYS
 }
 
+func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
+	var value IPMreqn
+	vallen := _Socklen(SizeofIPMreqn)
+	errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+	return &value, errno
+}
+
+func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
+	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
+}
+
 /*
  * Exposed directly
  */
-//sys	Access(path string, mode uint32) (errno int)
-//sys	Adjtime(delta *Timeval, olddelta *Timeval) (errno int)
-//sys	Chdir(path string) (errno int)
-//sys	Chflags(path string, flags int) (errno int)
-//sys	Chmod(path string, mode uint32) (errno int)
-//sys	Chown(path string, uid int, gid int) (errno int)
-//sys	Chroot(path string) (errno int)
-//sys	Close(fd int) (errno int)
-//sysnb	Dup(fd int) (nfd int, errno int)
-//sysnb	Dup2(from int, to int) (errno int)
+//sys	Access(path string, mode uint32) (err error)
+//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
+//sys	Chdir(path string) (err error)
+//sys	Chflags(path string, flags int) (err error)
+//sys	Chmod(path string, mode uint32) (err error)
+//sys	Chown(path string, uid int, gid int) (err error)
+//sys	Chroot(path string) (err error)
+//sys	Close(fd int) (err error)
+//sysnb	Dup(fd int) (nfd int, err error)
+//sysnb	Dup2(from int, to int) (err error)
 //sys	Exit(code int)
-//sys	Fchdir(fd int) (errno int)
-//sys	Fchflags(path string, flags int) (errno int)
-//sys	Fchmod(fd int, mode uint32) (errno int)
-//sys	Fchown(fd int, uid int, gid int) (errno int)
-//sys	Flock(fd int, how int) (errno int)
-//sys	Fpathconf(fd int, name int) (val int, errno int)
-//sys	Fstat(fd int, stat *Stat_t) (errno int)
-//sys	Fstatfs(fd int, stat *Statfs_t) (errno int)
-//sys	Fsync(fd int) (errno int)
-//sys	Ftruncate(fd int, length int64) (errno int)
-//sys	Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int)
+//sys	Fchdir(fd int) (err error)
+//sys	Fchflags(path string, flags int) (err error)
+//sys	Fchmod(fd int, mode uint32) (err error)
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Flock(fd int, how int) (err error)
+//sys	Fpathconf(fd int, name int) (val int, err error)
+//sys	Fstat(fd int, stat *Stat_t) (err error)
+//sys	Fstatfs(fd int, stat *Statfs_t) (err error)
+//sys	Fsync(fd int) (err error)
+//sys	Ftruncate(fd int, length int64) (err error)
+//sys	Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
 //sys	Getdtablesize() (size int)
 //sysnb	Getegid() (egid int)
 //sysnb	Geteuid() (uid int)
-//sys	Getfsstat(buf []Statfs_t, flags int) (n int, errno int)
+//sys	Getfsstat(buf []Statfs_t, flags int) (n int, err error)
 //sysnb	Getgid() (gid int)
-//sysnb	Getpgid(pid int) (pgid int, errno int)
+//sysnb	Getpgid(pid int) (pgid int, err error)
 //sysnb	Getpgrp() (pgrp int)
 //sysnb	Getpid() (pid int)
 //sysnb	Getppid() (ppid int)
-//sys	Getpriority(which int, who int) (prio int, errno int)
-//sysnb	Getrlimit(which int, lim *Rlimit) (errno int)
-//sysnb	Getrusage(who int, rusage *Rusage) (errno int)
-//sysnb	Getsid(pid int) (sid int, errno int)
-//sysnb	Gettimeofday(tv *Timeval) (errno int)
+//sys	Getpriority(which int, who int) (prio int, err error)
+//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Getrusage(who int, rusage *Rusage) (err error)
+//sysnb	Getsid(pid int) (sid int, err error)
+//sysnb	Gettimeofday(tv *Timeval) (err error)
 //sysnb	Getuid() (uid int)
 //sys	Issetugid() (tainted bool)
-//sys	Kill(pid int, signum int) (errno int)
-//sys	Kqueue() (fd int, errno int)
-//sys	Lchown(path string, uid int, gid int) (errno int)
-//sys	Link(path string, link string) (errno int)
-//sys	Listen(s int, backlog int) (errno int)
-//sys	Lstat(path string, stat *Stat_t) (errno int)
-//sys	Mkdir(path string, mode uint32) (errno int)
-//sys	Mkfifo(path string, mode uint32) (errno int)
-//sys	Mknod(path string, mode uint32, dev int) (errno int)
-//sys	Nanosleep(time *Timespec, leftover *Timespec) (errno int)
-//sys	Open(path string, mode int, perm uint32) (fd int, errno int)
-//sys	Pathconf(path string, name int) (val int, errno int)
-//sys	Pread(fd int, p []byte, offset int64) (n int, errno int)
-//sys	Pwrite(fd int, p []byte, offset int64) (n int, errno int)
-//sys	Read(fd int, p []byte) (n int, errno int)
-//sys	Readlink(path string, buf []byte) (n int, errno int)
-//sys	Rename(from string, to string) (errno int)
-//sys	Revoke(path string) (errno int)
-//sys	Rmdir(path string) (errno int)
-//sys	Seek(fd int, offset int64, whence int) (newoffset int64, errno int) = SYS_LSEEK
-//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int)
-//sysnb	Setegid(egid int) (errno int)
-//sysnb	Seteuid(euid int) (errno int)
-//sysnb	Setgid(gid int) (errno int)
-//sys	Setlogin(name string) (errno int)
-//sysnb	Setpgid(pid int, pgid int) (errno int)
-//sys	Setpriority(which int, who int, prio int) (errno int)
-//sysnb	Setregid(rgid int, egid int) (errno int)
-//sysnb	Setreuid(ruid int, euid int) (errno int)
-//sysnb	Setrlimit(which int, lim *Rlimit) (errno int)
-//sysnb	Setsid() (pid int, errno int)
-//sysnb	Settimeofday(tp *Timeval) (errno int)
-//sysnb	Setuid(uid int) (errno int)
-//sys	Stat(path string, stat *Stat_t) (errno int)
-//sys	Statfs(path string, stat *Statfs_t) (errno int)
-//sys	Symlink(path string, link string) (errno int)
-//sys	Sync() (errno int)
-//sys	Truncate(path string, length int64) (errno int)
+//sys	Kill(pid int, signum int) (err error)
+//sys	Kqueue() (fd int, err error)
+//sys	Lchown(path string, uid int, gid int) (err error)
+//sys	Link(path string, link string) (err error)
+//sys	Listen(s int, backlog int) (err error)
+//sys	Lstat(path string, stat *Stat_t) (err error)
+//sys	Mkdir(path string, mode uint32) (err error)
+//sys	Mkfifo(path string, mode uint32) (err error)
+//sys	Mknod(path string, mode uint32, dev int) (err error)
+//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
+//sys	Open(path string, mode int, perm uint32) (fd int, err error)
+//sys	Pathconf(path string, name int) (val int, err error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys	Read(fd int, p []byte) (n int, err error)
+//sys	Readlink(path string, buf []byte) (n int, err error)
+//sys	Rename(from string, to string) (err error)
+//sys	Revoke(path string) (err error)
+//sys	Rmdir(path string) (err error)
+//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
+//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
+//sysnb	Setegid(egid int) (err error)
+//sysnb	Seteuid(euid int) (err error)
+//sysnb	Setgid(gid int) (err error)
+//sys	Setlogin(name string) (err error)
+//sysnb	Setpgid(pid int, pgid int) (err error)
+//sys	Setpriority(which int, who int, prio int) (err error)
+//sysnb	Setregid(rgid int, egid int) (err error)
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//sysnb	Setrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Setsid() (pid int, err error)
+//sysnb	Settimeofday(tp *Timeval) (err error)
+//sysnb	Setuid(uid int) (err error)
+//sys	Stat(path string, stat *Stat_t) (err error)
+//sys	Statfs(path string, stat *Statfs_t) (err error)
+//sys	Symlink(path string, link string) (err error)
+//sys	Sync() (err error)
+//sys	Truncate(path string, length int64) (err error)
 //sys	Umask(newmask int) (oldmask int)
-//sys	Undelete(path string) (errno int)
-//sys	Unlink(path string) (errno int)
-//sys	Unmount(path string, flags int) (errno int)
-//sys	Write(fd int, p []byte) (n int, errno int)
-//sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int)
-//sys   munmap(addr uintptr, length uintptr) (errno int)
-//sys	read(fd int, buf *byte, nbuf int) (n int, errno int)
-//sys	write(fd int, buf *byte, nbuf int) (n int, errno int)
+//sys	Undelete(path string) (err error)
+//sys	Unlink(path string) (err error)
+//sys	Unmount(path string, flags int) (err error)
+//sys	Write(fd int, p []byte) (n int, err error)
+//sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
+//sys   munmap(addr uintptr, length uintptr) (err error)
+//sys	read(fd int, buf *byte, nbuf int) (n int, err error)
+//sys	write(fd int, buf *byte, nbuf int) (n int, err error)
 
 /*
  * Unimplemented
diff --git a/src/pkg/syscall/syscall_freebsd_386.go b/src/pkg/syscall/syscall_freebsd_386.go
index d3b5a1b..fa322c5 100644
--- a/src/pkg/syscall/syscall_freebsd_386.go
+++ b/src/pkg/syscall/syscall_freebsd_386.go
@@ -41,4 +41,4 @@ func (cmsg *Cmsghdr) SetLen(length int) {
 	cmsg.Len = uint32(length)
 }
 
-func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) // sic
+func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
diff --git a/src/pkg/syscall/syscall_linux.go b/src/pkg/syscall/syscall_linux.go
index 9fc2605..d0e1627 100644
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -13,51 +13,49 @@ package syscall
 
 import "unsafe"
 
-const OS = "linux"
-
 /*
  * Wrapped
  */
 
-//sys	open(path string, mode int, perm uint32) (fd int, errno int)
-func Open(path string, mode int, perm uint32) (fd int, errno int) {
+//sys	open(path string, mode int, perm uint32) (fd int, err error)
+func Open(path string, mode int, perm uint32) (fd int, err error) {
 	return open(path, mode|O_LARGEFILE, perm)
 }
 
-//sys	openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int)
-func Openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int) {
+//sys	openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
+func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
 	return openat(dirfd, path, flags|O_LARGEFILE, mode)
 }
 
-//sysnb	pipe(p *[2]_C_int) (errno int)
-func Pipe(p []int) (errno int) {
+//sysnb	pipe(p *[2]_C_int) (err error)
+func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return EINVAL
 	}
 	var pp [2]_C_int
-	errno = pipe(&pp)
+	err = pipe(&pp)
 	p[0] = int(pp[0])
 	p[1] = int(pp[1])
 	return
 }
 
-//sys	utimes(path string, times *[2]Timeval) (errno int)
-func Utimes(path string, tv []Timeval) (errno int) {
+//sys	utimes(path string, times *[2]Timeval) (err error)
+func Utimes(path string, tv []Timeval) (err error) {
 	if len(tv) != 2 {
 		return EINVAL
 	}
 	return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
 }
 
-//sys	futimesat(dirfd int, path *byte, times *[2]Timeval) (errno int)
-func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
+//sys	futimesat(dirfd int, path *byte, times *[2]Timeval) (err error)
+func Futimesat(dirfd int, path string, tv []Timeval) (err error) {
 	if len(tv) != 2 {
 		return EINVAL
 	}
 	return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0])))
 }
 
-func Futimes(fd int, tv []Timeval) (errno int) {
+func Futimes(fd int, tv []Timeval) (err error) {
 	// Believe it or not, this is the best we can do on Linux
 	// (and is what glibc does).
 	return Utimes("/proc/self/fd/"+itoa(fd), tv)
@@ -65,27 +63,27 @@ func Futimes(fd int, tv []Timeval) (errno int) {
 
 const ImplementsGetwd = true
 
-//sys	Getcwd(buf []byte) (n int, errno int)
-func Getwd() (wd string, errno int) {
+//sys	Getcwd(buf []byte) (n int, err error)
+func Getwd() (wd string, err error) {
 	var buf [PathMax]byte
 	n, err := Getcwd(buf[0:])
-	if err != 0 {
+	if err != nil {
 		return "", err
 	}
 	// Getcwd returns the number of bytes written to buf, including the NUL.
 	if n < 1 || n > len(buf) || buf[n-1] != 0 {
 		return "", EINVAL
 	}
-	return string(buf[0 : n-1]), 0
+	return string(buf[0 : n-1]), nil
 }
 
-func Getgroups() (gids []int, errno int) {
+func Getgroups() (gids []int, err error) {
 	n, err := getgroups(0, nil)
-	if err != 0 {
-		return nil, errno
+	if err != nil {
+		return nil, err
 	}
 	if n == 0 {
-		return nil, 0
+		return nil, nil
 	}
 
 	// Sanity check group count.  Max is 1<<16 on Linux.
@@ -95,8 +93,8 @@ func Getgroups() (gids []int, errno int) {
 
 	a := make([]_Gid_t, n)
 	n, err = getgroups(n, &a[0])
-	if err != 0 {
-		return nil, errno
+	if err != nil {
+		return nil, err
 	}
 	gids = make([]int, n)
 	for i, v := range a[0:n] {
@@ -105,7 +103,7 @@ func Getgroups() (gids []int, errno int) {
 	return
 }
 
-func Setgroups(gids []int) (errno int) {
+func Setgroups(gids []int) (err error) {
 	if len(gids) == 0 {
 		return setgroups(0, nil)
 	}
@@ -174,20 +172,18 @@ func (w WaitStatus) TrapCause() int {
 	return int(w>>shift) >> 8
 }
 
-//sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int)
-func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+//sys	wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error)
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
 	var status _C_int
-	wpid, errno = wait4(pid, &status, options, rusage)
+	wpid, err = wait4(pid, &status, options, rusage)
 	if wstatus != nil {
 		*wstatus = WaitStatus(status)
 	}
 	return
 }
 
-func Sleep(nsec int64) (errno int) {
-	tv := NsecToTimeval(nsec)
-	_, err := Select(0, nil, nil, nil, &tv)
-	return err
+func Mkfifo(path string, mode uint32) (err error) {
+	return Mknod(path, mode|S_IFIFO, 0)
 }
 
 // For testing: clients can set this flag to force
@@ -195,7 +191,7 @@ func Sleep(nsec int64) (errno int) {
 var SocketDisableIPv6 bool
 
 type Sockaddr interface {
-	sockaddr() (ptr uintptr, len _Socklen, errno int) // lowercase; only we can define Sockaddrs
+	sockaddr() (ptr uintptr, len _Socklen, err error) // lowercase; only we can define Sockaddrs
 }
 
 type SockaddrInet4 struct {
@@ -204,7 +200,7 @@ type SockaddrInet4 struct {
 	raw  RawSockaddrInet4
 }
 
-func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, error) {
 	if sa.Port < 0 || sa.Port > 0xFFFF {
 		return 0, 0, EINVAL
 	}
@@ -215,7 +211,7 @@ func (sa *SockaddrInet4) sockaddr() (uintptr, _Socklen, int) {
 	for i := 0; i < len(sa.Addr); i++ {
 		sa.raw.Addr[i] = sa.Addr[i]
 	}
-	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0
+	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, nil
 }
 
 type SockaddrInet6 struct {
@@ -225,7 +221,7 @@ type SockaddrInet6 struct {
 	raw    RawSockaddrInet6
 }
 
-func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, error) {
 	if sa.Port < 0 || sa.Port > 0xFFFF {
 		return 0, 0, EINVAL
 	}
@@ -237,7 +233,7 @@ func (sa *SockaddrInet6) sockaddr() (uintptr, _Socklen, int) {
 	for i := 0; i < len(sa.Addr); i++ {
 		sa.raw.Addr[i] = sa.Addr[i]
 	}
-	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0
+	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, nil
 }
 
 type SockaddrUnix struct {
@@ -245,7 +241,7 @@ type SockaddrUnix struct {
 	raw  RawSockaddrUnix
 }
 
-func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, error) {
 	name := sa.Name
 	n := len(name)
 	if n >= len(sa.raw.Path) || n == 0 {
@@ -263,7 +259,7 @@ func (sa *SockaddrUnix) sockaddr() (uintptr, _Socklen, int) {
 		sl--
 	}
 
-	return uintptr(unsafe.Pointer(&sa.raw)), sl, 0
+	return uintptr(unsafe.Pointer(&sa.raw)), sl, nil
 }
 
 type SockaddrLinklayer struct {
@@ -276,7 +272,7 @@ type SockaddrLinklayer struct {
 	raw      RawSockaddrLinklayer
 }
 
-func (sa *SockaddrLinklayer) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrLinklayer) sockaddr() (uintptr, _Socklen, error) {
 	if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
 		return 0, 0, EINVAL
 	}
@@ -289,7 +285,7 @@ func (sa *SockaddrLinklayer) sockaddr() (uintptr, _Socklen, int) {
 	for i := 0; i < len(sa.Addr); i++ {
 		sa.raw.Addr[i] = sa.Addr[i]
 	}
-	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrLinklayer, 0
+	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrLinklayer, nil
 }
 
 type SockaddrNetlink struct {
@@ -300,15 +296,15 @@ type SockaddrNetlink struct {
 	raw    RawSockaddrNetlink
 }
 
-func (sa *SockaddrNetlink) sockaddr() (uintptr, _Socklen, int) {
+func (sa *SockaddrNetlink) sockaddr() (uintptr, _Socklen, error) {
 	sa.raw.Family = AF_NETLINK
 	sa.raw.Pad = sa.Pad
 	sa.raw.Pid = sa.Pid
 	sa.raw.Groups = sa.Groups
-	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrNetlink, 0
+	return uintptr(unsafe.Pointer(&sa.raw)), SizeofSockaddrNetlink, nil
 }
 
-func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
 	switch rsa.Addr.Family {
 	case AF_NETLINK:
 		pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa))
@@ -317,7 +313,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		sa.Pad = pp.Pad
 		sa.Pid = pp.Pid
 		sa.Groups = pp.Groups
-		return sa, 0
+		return sa, nil
 
 	case AF_PACKET:
 		pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa))
@@ -330,7 +326,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		for i := 0; i < len(sa.Addr); i++ {
 			sa.Addr[i] = pp.Addr[i]
 		}
-		return sa, 0
+		return sa, nil
 
 	case AF_UNIX:
 		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
@@ -355,7 +351,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		}
 		bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
 		sa.Name = string(bytes)
-		return sa, 0
+		return sa, nil
 
 	case AF_INET:
 		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
@@ -365,7 +361,7 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		for i := 0; i < len(sa.Addr); i++ {
 			sa.Addr[i] = pp.Addr[i]
 		}
-		return sa, 0
+		return sa, nil
 
 	case AF_INET6:
 		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
@@ -376,124 +372,159 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
 		for i := 0; i < len(sa.Addr); i++ {
 			sa.Addr[i] = pp.Addr[i]
 		}
-		return sa, 0
+		return sa, nil
 	}
 	return nil, EAFNOSUPPORT
 }
 
-func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
+func Accept(fd int) (nfd int, sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
-	nfd, errno = accept(fd, &rsa, &len)
-	if errno != 0 {
+	nfd, err = accept(fd, &rsa, &len)
+	if err != nil {
 		return
 	}
-	sa, errno = anyToSockaddr(&rsa)
-	if errno != 0 {
+	sa, err = anyToSockaddr(&rsa)
+	if err != nil {
 		Close(nfd)
 		nfd = 0
 	}
 	return
 }
 
-func Getsockname(fd int) (sa Sockaddr, errno int) {
+func Getsockname(fd int) (sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
-	if errno = getsockname(fd, &rsa, &len); errno != 0 {
+	if err = getsockname(fd, &rsa, &len); err != nil {
 		return
 	}
 	return anyToSockaddr(&rsa)
 }
 
-func Getpeername(fd int) (sa Sockaddr, errno int) {
+func Getpeername(fd int) (sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
-	if errno = getpeername(fd, &rsa, &len); errno != 0 {
+	if err = getpeername(fd, &rsa, &len); err != nil {
 		return
 	}
 	return anyToSockaddr(&rsa)
 }
 
-func Bind(fd int, sa Sockaddr) (errno int) {
+func Bind(fd int, sa Sockaddr) (err error) {
 	ptr, n, err := sa.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	return bind(fd, ptr, n)
 }
 
-func Connect(fd int, sa Sockaddr) (errno int) {
+func Connect(fd int, sa Sockaddr) (err error) {
 	ptr, n, err := sa.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	return connect(fd, ptr, n)
 }
 
-func Socket(domain, typ, proto int) (fd, errno int) {
+func Socket(domain, typ, proto int) (fd int, err error) {
 	if domain == AF_INET6 && SocketDisableIPv6 {
 		return -1, EAFNOSUPPORT
 	}
-	fd, errno = socket(domain, typ, proto)
+	fd, err = socket(domain, typ, proto)
 	return
 }
 
-func Socketpair(domain, typ, proto int) (fd [2]int, errno int) {
-	errno = socketpair(domain, typ, proto, &fd)
+func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
+	err = socketpair(domain, typ, proto, &fd)
 	return
 }
 
-func GetsockoptInt(fd, level, opt int) (value, errno int) {
+func GetsockoptInt(fd, level, opt int) (value int, err error) {
 	var n int32
 	vallen := _Socklen(4)
-	errno = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), &vallen)
-	return int(n), errno
+	err = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), &vallen)
+	return int(n), err
+}
+
+func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
+	vallen := _Socklen(4)
+	err = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value[0])), &vallen)
+	return value, err
+}
+
+func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
+	var value IPMreq
+	vallen := _Socklen(SizeofIPMreq)
+	err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+	return &value, err
+}
+
+func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
+	var value IPMreqn
+	vallen := _Socklen(SizeofIPMreqn)
+	err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+	return &value, err
+}
+
+func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
+	var value IPv6Mreq
+	vallen := _Socklen(SizeofIPv6Mreq)
+	err := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+	return &value, err
 }
 
-func SetsockoptInt(fd, level, opt int, value int) (errno int) {
+func SetsockoptInt(fd, level, opt int, value int) (err error) {
 	var n = int32(value)
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4)
 }
 
-func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
+func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
+	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value[0])), 4)
+}
+
+func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(tv)), unsafe.Sizeof(*tv))
 }
 
-func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
+func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(l)), unsafe.Sizeof(*l))
 }
 
-func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) {
+func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
 }
 
-func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
+func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
 }
 
-func SetsockoptString(fd, level, opt int, s string) (errno int) {
+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
+	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
+}
+
+func SetsockoptString(fd, level, opt int, s string) (err error) {
 	return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&[]byte(s)[0])), uintptr(len(s)))
 }
 
-func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
+func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	var len _Socklen = SizeofSockaddrAny
-	if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
+	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
 		return
 	}
-	from, errno = anyToSockaddr(&rsa)
+	from, err = anyToSockaddr(&rsa)
 	return
 }
 
-func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
+func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
 	ptr, n, err := to.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	return sendto(fd, p, flags, ptr, n)
 }
 
-func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
+func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
 	var msg Msghdr
 	var rsa RawSockaddrAny
 	msg.Name = (*byte)(unsafe.Pointer(&rsa))
@@ -515,25 +546,25 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
 	}
 	msg.Iov = &iov
 	msg.Iovlen = 1
-	if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
+	if n, err = recvmsg(fd, &msg, flags); err != nil {
 		return
 	}
 	oobn = int(msg.Controllen)
 	recvflags = int(msg.Flags)
 	// source address is only specified if the socket is unconnected
 	if rsa.Addr.Family != AF_UNSPEC {
-		from, errno = anyToSockaddr(&rsa)
+		from, err = anyToSockaddr(&rsa)
 	}
 	return
 }
 
-func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
 	var ptr uintptr
 	var salen _Socklen
 	if to != nil {
-		var err int
+		var err error
 		ptr, salen, err = to.sockaddr()
-		if err != 0 {
+		if err != nil {
 			return err
 		}
 	}
@@ -557,20 +588,20 @@ func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
 	}
 	msg.Iov = &iov
 	msg.Iovlen = 1
-	if errno = sendmsg(fd, &msg, flags); errno != 0 {
+	if err = sendmsg(fd, &msg, flags); err != nil {
 		return
 	}
 	return
 }
 
 // BindToDevice binds the socket associated with fd to device.
-func BindToDevice(fd int, device string) (errno int) {
+func BindToDevice(fd int, device string) (err error) {
 	return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)
 }
 
-//sys	ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
+//sys	ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
 
-func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno int) {
+func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) {
 	// The peek requests are machine-size oriented, so we wrap it
 	// to retrieve arbitrary-length data.
 
@@ -586,9 +617,9 @@ func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno in
 	// boundary.
 	n := 0
 	if addr%sizeofPtr != 0 {
-		errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
-		if errno != 0 {
-			return 0, errno
+		err = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
+		if err != nil {
+			return 0, err
 		}
 		n += copy(out, buf[addr%sizeofPtr:])
 		out = out[n:]
@@ -598,27 +629,27 @@ func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno in
 	for len(out) > 0 {
 		// We use an internal buffer to gaurantee alignment.
 		// It's not documented if this is necessary, but we're paranoid.
-		errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
-		if errno != 0 {
-			return n, errno
+		err = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
+		if err != nil {
+			return n, err
 		}
 		copied := copy(out, buf[0:])
 		n += copied
 		out = out[copied:]
 	}
 
-	return n, 0
+	return n, nil
 }
 
-func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
+func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
 	return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out)
 }
 
-func PtracePeekData(pid int, addr uintptr, out []byte) (count int, errno int) {
+func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
 	return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
 }
 
-func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, errno int) {
+func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) {
 	// As for ptracePeek, we need to align our accesses to deal
 	// with the possibility of straddling an invalid page.
 
@@ -626,15 +657,15 @@ func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (c
 	n := 0
 	if addr%sizeofPtr != 0 {
 		var buf [sizeofPtr]byte
-		errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
-		if errno != 0 {
-			return 0, errno
+		err = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
+		if err != nil {
+			return 0, err
 		}
 		n += copy(buf[addr%sizeofPtr:], data)
 		word := *((*uintptr)(unsafe.Pointer(&buf[0])))
-		errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
-		if errno != 0 {
-			return 0, errno
+		err = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
+		if err != nil {
+			return 0, err
 		}
 		data = data[n:]
 	}
@@ -642,9 +673,9 @@ func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (c
 	// Interior.
 	for len(data) > sizeofPtr {
 		word := *((*uintptr)(unsafe.Pointer(&data[0])))
-		errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
-		if errno != 0 {
-			return n, errno
+		err = ptrace(pokeReq, pid, addr+uintptr(n), word)
+		if err != nil {
+			return n, err
 		}
 		n += sizeofPtr
 		data = data[sizeofPtr:]
@@ -653,61 +684,61 @@ func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (c
 	// Trailing edge.
 	if len(data) > 0 {
 		var buf [sizeofPtr]byte
-		errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
-		if errno != 0 {
-			return n, errno
+		err = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
+		if err != nil {
+			return n, err
 		}
 		copy(buf[0:], data)
 		word := *((*uintptr)(unsafe.Pointer(&buf[0])))
-		errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
-		if errno != 0 {
-			return n, errno
+		err = ptrace(pokeReq, pid, addr+uintptr(n), word)
+		if err != nil {
+			return n, err
 		}
 		n += len(data)
 	}
 
-	return n, 0
+	return n, nil
 }
 
-func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
+func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
 	return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data)
 }
 
-func PtracePokeData(pid int, addr uintptr, data []byte) (count int, errno int) {
+func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
 	return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
 }
 
-func PtraceGetRegs(pid int, regsout *PtraceRegs) (errno int) {
+func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
 	return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
 }
 
-func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
+func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
 	return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
 }
 
-func PtraceSetOptions(pid int, options int) (errno int) {
+func PtraceSetOptions(pid int, options int) (err error) {
 	return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
 }
 
-func PtraceGetEventMsg(pid int) (msg uint, errno int) {
+func PtraceGetEventMsg(pid int) (msg uint, err error) {
 	var data _C_long
-	errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
+	err = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
 	msg = uint(data)
 	return
 }
 
-func PtraceCont(pid int, signal int) (errno int) {
+func PtraceCont(pid int, signal int) (err error) {
 	return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
 }
 
-func PtraceSingleStep(pid int) (errno int) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
+func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
 
-func PtraceAttach(pid int) (errno int) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
+func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
 
-func PtraceDetach(pid int) (errno int) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
+func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
 
-//sys	reboot(magic1 uint, magic2 uint, cmd int, arg string) (errno int)
-func Reboot(cmd int) (errno int) {
+//sys	reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error)
+func Reboot(cmd int) (err error) {
 	return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
 }
 
@@ -720,7 +751,7 @@ func clen(n []byte) int {
 	return len(n)
 }
 
-func ReadDirent(fd int, buf []byte) (n int, errno int) {
+func ReadDirent(fd int, buf []byte) (n int, err error) {
 	return Getdents(fd, buf)
 }
 
@@ -745,6 +776,16 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
 	return origlen - len(buf), count, names
 }
 
+//sys	mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)
+func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
+	// Certain file systems get rather angry and EINVAL if you give
+	// them an empty string of data, rather than NULL.
+	if data == "" {
+		return mount(source, target, fstype, flags, nil)
+	}
+	return mount(source, target, fstype, flags, StringBytePtr(data))
+}
+
 // Sendto
 // Recvfrom
 // Socketpair
@@ -752,86 +793,86 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
 /*
  * Direct access
  */
-//sys	Access(path string, mode uint32) (errno int)
-//sys	Acct(path string) (errno int)
-//sys	Adjtimex(buf *Timex) (state int, errno int)
-//sys	Chdir(path string) (errno int)
-//sys	Chmod(path string, mode uint32) (errno int)
-//sys	Chroot(path string) (errno int)
-//sys	Close(fd int) (errno int)
-//sys	Creat(path string, mode uint32) (fd int, errno int)
-//sysnb	Dup(oldfd int) (fd int, errno int)
-//sysnb	Dup2(oldfd int, newfd int) (fd int, errno int)
-//sysnb	EpollCreate(size int) (fd int, errno int)
-//sysnb	EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int)
-//sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int)
+//sys	Access(path string, mode uint32) (err error)
+//sys	Acct(path string) (err error)
+//sys	Adjtimex(buf *Timex) (state int, err error)
+//sys	Chdir(path string) (err error)
+//sys	Chmod(path string, mode uint32) (err error)
+//sys	Chroot(path string) (err error)
+//sys	Close(fd int) (err error)
+//sys	Creat(path string, mode uint32) (fd int, err error)
+//sysnb	Dup(oldfd int) (fd int, err error)
+//sysnb	Dup2(oldfd int, newfd int) (fd int, err error)
+//sysnb	EpollCreate(size int) (fd int, err error)
+//sysnb	EpollCreate1(flag int) (fd int, err error)
+//sysnb	EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
+//sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Exit(code int) = SYS_EXIT_GROUP
-//sys	Faccessat(dirfd int, path string, mode uint32, flags int) (errno int)
-//sys	Fallocate(fd int, mode uint32, off int64, len int64) (errno int)
-//sys	Fchdir(fd int) (errno int)
-//sys	Fchmod(fd int, mode uint32) (errno int)
-//sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int)
-//sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int)
-//sys	fcntl(fd int, cmd int, arg int) (val int, errno int)
-//sys	Fdatasync(fd int) (errno int)
-//sys	Flock(fd int, how int) (errno int)
-//sys	Fsync(fd int) (errno int)
-//sys	Getdents(fd int, buf []byte) (n int, errno int) = SYS_GETDENTS64
-//sysnb	Getpgid(pid int) (pgid int, errno int)
+//sys	Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
+//sys	Fallocate(fd int, mode uint32, off int64, len int64) (err error)
+//sys	Fchdir(fd int) (err error)
+//sys	Fchmod(fd int, mode uint32) (err error)
+//sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
+//sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
+//sys	fcntl(fd int, cmd int, arg int) (val int, err error)
+//sys	Fdatasync(fd int) (err error)
+//sys	Flock(fd int, how int) (err error)
+//sys	Fsync(fd int) (err error)
+//sys	Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
+//sysnb	Getpgid(pid int) (pgid int, err error)
 //sysnb	Getpgrp() (pid int)
 //sysnb	Getpid() (pid int)
 //sysnb	Getppid() (ppid int)
-//sysnb	Getrlimit(resource int, rlim *Rlimit) (errno int)
-//sysnb	Getrusage(who int, rusage *Rusage) (errno int)
+//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error)
+//sysnb	Getrusage(who int, rusage *Rusage) (err error)
 //sysnb	Gettid() (tid int)
-//sys	InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, errno int)
-//sysnb	InotifyInit() (fd int, errno int)
-//sysnb	InotifyInit1(flags int) (fd int, errno int)
-//sysnb	InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int)
-//sysnb	Kill(pid int, sig int) (errno int)
-//sys	Klogctl(typ int, buf []byte) (n int, errno int) = SYS_SYSLOG
-//sys	Link(oldpath string, newpath string) (errno int)
-//sys	Mkdir(path string, mode uint32) (errno int)
-//sys	Mkdirat(dirfd int, path string, mode uint32) (errno int)
-//sys	Mknod(path string, mode uint32, dev int) (errno int)
-//sys	Mknodat(dirfd int, path string, mode uint32, dev int) (errno int)
-//sys	Mount(source string, target string, fstype string, flags int, data string) (errno int)
-//sys	Nanosleep(time *Timespec, leftover *Timespec) (errno int)
-//sys	Pause() (errno int)
-//sys	PivotRoot(newroot string, putold string) (errno int) = SYS_PIVOT_ROOT
-//sys	Read(fd int, p []byte) (n int, errno int)
-//sys	Readlink(path string, buf []byte) (n int, errno int)
-//sys	Rename(oldpath string, newpath string) (errno int)
-//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int)
-//sys	Rmdir(path string) (errno int)
-//sys	Setdomainname(p []byte) (errno int)
-//sys	Sethostname(p []byte) (errno int)
-//sysnb	Setpgid(pid int, pgid int) (errno int)
-//sysnb	Setrlimit(resource int, rlim *Rlimit) (errno int)
-//sysnb	Setsid() (pid int, errno int)
-//sysnb	Settimeofday(tv *Timeval) (errno int)
-//sysnb	Setuid(uid int) (errno int)
-//sys	Symlink(oldpath string, newpath string) (errno int)
+//sys	InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
+//sysnb	InotifyInit() (fd int, err error)
+//sysnb	InotifyInit1(flags int) (fd int, err error)
+//sysnb	InotifyRmWatch(fd int, watchdesc uint32) (success int, err error)
+//sysnb	Kill(pid int, sig int) (err error)
+//sys	Klogctl(typ int, buf []byte) (n int, err error) = SYS_SYSLOG
+//sys	Link(oldpath string, newpath string) (err error)
+//sys	Mkdir(path string, mode uint32) (err error)
+//sys	Mkdirat(dirfd int, path string, mode uint32) (err error)
+//sys	Mknod(path string, mode uint32, dev int) (err error)
+//sys	Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
+//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
+//sys	Pause() (err error)
+//sys	PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
+//sys	Read(fd int, p []byte) (n int, err error)
+//sys	Readlink(path string, buf []byte) (n int, err error)
+//sys	Rename(oldpath string, newpath string) (err error)
+//sys	Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
+//sys	Rmdir(path string) (err error)
+//sys	Setdomainname(p []byte) (err error)
+//sys	Sethostname(p []byte) (err error)
+//sysnb	Setpgid(pid int, pgid int) (err error)
+//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
+//sysnb	Setsid() (pid int, err error)
+//sysnb	Settimeofday(tv *Timeval) (err error)
+//sysnb	Setuid(uid int) (err error)
+//sys	Symlink(oldpath string, newpath string) (err error)
 //sys	Sync()
-//sysnb	Sysinfo(info *Sysinfo_t) (errno int)
-//sys	Tee(rfd int, wfd int, len int, flags int) (n int64, errno int)
-//sysnb	Tgkill(tgid int, tid int, sig int) (errno int)
-//sysnb	Times(tms *Tms) (ticks uintptr, errno int)
+//sysnb	Sysinfo(info *Sysinfo_t) (err error)
+//sys	Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
+//sysnb	Tgkill(tgid int, tid int, sig int) (err error)
+//sysnb	Times(tms *Tms) (ticks uintptr, err error)
 //sysnb	Umask(mask int) (oldmask int)
-//sysnb	Uname(buf *Utsname) (errno int)
-//sys	Unlink(path string) (errno int)
-//sys	Unlinkat(dirfd int, path string) (errno int)
-//sys	Unmount(target string, flags int) (errno int) = SYS_UMOUNT2
-//sys	Unshare(flags int) (errno int)
-//sys	Ustat(dev int, ubuf *Ustat_t) (errno int)
-//sys	Utime(path string, buf *Utimbuf) (errno int)
-//sys	Write(fd int, p []byte) (n int, errno int)
-//sys	exitThread(code int) (errno int) = SYS_EXIT
-//sys	read(fd int, p *byte, np int) (n int, errno int)
-//sys	write(fd int, p *byte, np int) (n int, errno int)
+//sysnb	Uname(buf *Utsname) (err error)
+//sys	Unlink(path string) (err error)
+//sys	Unlinkat(dirfd int, path string) (err error)
+//sys	Unmount(target string, flags int) (err error) = SYS_UMOUNT2
+//sys	Unshare(flags int) (err error)
+//sys	Ustat(dev int, ubuf *Ustat_t) (err error)
+//sys	Utime(path string, buf *Utimbuf) (err error)
+//sys	Write(fd int, p []byte) (n int, err error)
+//sys	exitThread(code int) (err error) = SYS_EXIT
+//sys	read(fd int, p *byte, np int) (n int, err error)
+//sys	write(fd int, p *byte, np int) (n int, err error)
 
 // mmap varies by architecture; see syscall_linux_*.go.
-//sys	munmap(addr uintptr, length uintptr) (errno int)
+//sys	munmap(addr uintptr, length uintptr) (err error)
 
 var mapper = &mmapper{
 	active: make(map[*byte][]byte),
@@ -839,20 +880,20 @@ var mapper = &mmapper{
 	munmap: munmap,
 }
 
-func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
 	return mapper.Mmap(fd, offset, length, prot, flags)
 }
 
-func Munmap(b []byte) (errno int) {
+func Munmap(b []byte) (err error) {
 	return mapper.Munmap(b)
 }
 
-//sys	Madvise(b []byte, advice int) (errno int)
-//sys	Mprotect(b []byte, prot int) (errno int)
-//sys	Mlock(b []byte) (errno int)
-//sys	Munlock(b []byte) (errno int)
-//sys	Mlockall(flags int) (errno int)
-//sys	Munlockall() (errno int)
+//sys	Madvise(b []byte, advice int) (err error)
+//sys	Mprotect(b []byte, prot int) (err error)
+//sys	Mlock(b []byte) (err error)
+//sys	Munlock(b []byte) (err error)
+//sys	Mlockall(flags int) (err error)
+//sys	Munlockall() (err error)
 
 /*
  * Unimplemented
diff --git a/src/pkg/syscall/syscall_linux_386.go b/src/pkg/syscall/syscall_linux_386.go
index 44891de..b833db8 100644
--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -27,39 +27,39 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
 
 // 64-bit file system and 32-bit uid calls
 // (386 default is 32-bit file system and 16-bit uid).
-//sys	Chown(path string, uid int, gid int) (errno int) = SYS_CHOWN32
-//sys	Fchown(fd int, uid int, gid int) (errno int) = SYS_FCHOWN32
-//sys	Fstat(fd int, stat *Stat_t) (errno int) = SYS_FSTAT64
-//sys	Ftruncate(fd int, length int64) (errno int) = SYS_FTRUNCATE64
+//sys	Chown(path string, uid int, gid int) (err error) = SYS_CHOWN32
+//sys	Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
+//sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
+//sys	Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
 //sysnb	Getegid() (egid int) = SYS_GETEGID32
 //sysnb	Geteuid() (euid int) = SYS_GETEUID32
 //sysnb	Getgid() (gid int) = SYS_GETGID32
 //sysnb	Getuid() (uid int) = SYS_GETUID32
-//sys	Ioperm(from int, num int, on int) (errno int)
-//sys	Iopl(level int) (errno int)
-//sys	Lchown(path string, uid int, gid int) (errno int) = SYS_LCHOWN32
-//sys	Lstat(path string, stat *Stat_t) (errno int) = SYS_LSTAT64
-//sys	Pread(fd int, p []byte, offset int64) (n int, errno int) = SYS_PREAD64
-//sys	Pwrite(fd int, p []byte, offset int64) (n int, errno int) = SYS_PWRITE64
-//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) = SYS_SENDFILE64
-//sys	Setfsgid(gid int) (errno int) = SYS_SETFSGID32
-//sys	Setfsuid(uid int) (errno int) = SYS_SETFSUID32
-//sysnb	Setgid(gid int) (errno int) = SYS_SETGID32
-//sysnb	Setregid(rgid int, egid int) (errno int) = SYS_SETREGID32
-//sysnb	Setresgid(rgid int, egid int, sgid int) (errno int) = SYS_SETRESGID32
-//sysnb	Setresuid(ruid int, euid int, suid int) (errno int) = SYS_SETRESUID32
-//sysnb	Setreuid(ruid int, euid int) (errno int) = SYS_SETREUID32
-//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, errno int)
-//sys	Stat(path string, stat *Stat_t) (errno int) = SYS_STAT64
-//sys	SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
-//sys	Truncate(path string, length int64) (errno int) = SYS_TRUNCATE64
-//sysnb	getgroups(n int, list *_Gid_t) (nn int, errno int) = SYS_GETGROUPS32
-//sysnb	setgroups(n int, list *_Gid_t) (errno int) = SYS_SETGROUPS32
-//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int) = SYS__NEWSELECT
-
-//sys	mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, errno int)
-
-func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int) {
+//sys	Ioperm(from int, num int, on int) (err error)
+//sys	Iopl(level int) (err error)
+//sys	Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32
+//sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
+//sys	Setfsgid(gid int) (err error) = SYS_SETFSGID32
+//sys	Setfsuid(uid int) (err error) = SYS_SETFSUID32
+//sysnb	Setgid(gid int) (err error) = SYS_SETGID32
+//sysnb	Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
+//sysnb	Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
+//sysnb	Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32
+//sysnb	Setreuid(ruid int, euid int) (err error) = SYS_SETREUID32
+//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
+//sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
+//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error)
+//sys	Truncate(path string, length int64) (err error) = SYS_TRUNCATE64
+//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error) = SYS_GETGROUPS32
+//sysnb	setgroups(n int, list *_Gid_t) (err error) = SYS_SETGROUPS32
+//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
+
+//sys	mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
+
+func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
 	page := uintptr(offset / 4096)
 	if offset != int64(page)*4096 {
 		return 0, EINVAL
@@ -69,11 +69,11 @@ func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int6
 
 // Underlying system call writes to newoffset via pointer.
 // Implemented in assembly to avoid allocation.
-func Seek(fd int, offset int64, whence int) (newoffset int64, errno int)
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
 
 // Vsyscalls on amd64.
-//sysnb	Gettimeofday(tv *Timeval) (errno int)
-//sysnb	Time(t *Time_t) (tt Time_t, errno int)
+//sysnb	Gettimeofday(tv *Timeval) (err error)
+//sysnb	Time(t *Time_t) (tt Time_t, err error)
 
 // On x86 Linux, all the socket calls go through an extra indirection,
 // I think because the 5-register system call interface can't handle
@@ -103,101 +103,150 @@ const (
 	_RECVMSG     = 17
 )
 
-func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
-func rawsocketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
+func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err Errno)
+func rawsocketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err Errno)
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
-	fd, errno = socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+	fd, e := socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
-	_, errno = rawsocketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, e := rawsocketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
-	_, errno = rawsocketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, e := rawsocketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func socketpair(domain int, typ int, flags int, fd *[2]int) (errno int) {
-	_, errno = rawsocketcall(_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd)), 0, 0)
+func socketpair(domain int, typ int, flags int, fd *[2]int) (err error) {
+	_, e := rawsocketcall(_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd)), 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
-	_, errno = socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, e := socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
-	_, errno = socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, e := socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
-	fd, errno = rawsocketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0)
+func socket(domain int, typ int, proto int) (fd int, err error) {
+	fd, e := rawsocketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
-	_, errno = socketcall(_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
+	_, e := socketcall(_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
-	_, errno = socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), val, vallen, 0)
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
+	_, e := socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), val, vallen, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var base uintptr
 	if len(p) > 0 {
 		base = uintptr(unsafe.Pointer(&p[0]))
 	}
-	n, errno = socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	n, e := socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func sendto(s int, p []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, p []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var base uintptr
 	if len(p) > 0 {
 		base = uintptr(unsafe.Pointer(&p[0]))
 	}
-	_, errno = socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), to, uintptr(addrlen))
+	_, e := socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), to, uintptr(addrlen))
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
-	n, errno = socketcall(_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	n, e := socketcall(_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
-	_, errno = socketcall(_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
+	_, e := socketcall(_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func Listen(s int, n int) (errno int) {
-	_, errno = socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0)
+func Listen(s int, n int) (err error) {
+	_, e := socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func Shutdown(s, how int) (errno int) {
-	_, errno = socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0)
+func Shutdown(s, how int) (err error) {
+	_, e := socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0)
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func Fstatfs(fd int, buf *Statfs_t) (errno int) {
-	_, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
-	errno = int(e1)
+func Fstatfs(fd int, buf *Statfs_t) (err error) {
+	_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
-func Statfs(path string, buf *Statfs_t) (errno int) {
-	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
-	errno = int(e1)
+func Statfs(path string, buf *Statfs_t) (err error) {
+	_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
+	if e != 0 {
+		err = e
+	}
 	return
 }
 
diff --git a/src/pkg/syscall/syscall_linux_amd64.go b/src/pkg/syscall/syscall_linux_amd64.go
index 8b206ad..18b36b7 100644
--- a/src/pkg/syscall/syscall_linux_amd64.go
+++ b/src/pkg/syscall/syscall_linux_amd64.go
@@ -4,59 +4,59 @@
 
 package syscall
 
-//sys	Chown(path string, uid int, gid int) (errno int)
-//sys	Fchown(fd int, uid int, gid int) (errno int)
-//sys	Fstat(fd int, stat *Stat_t) (errno int)
-//sys	Fstatfs(fd int, buf *Statfs_t) (errno int)
-//sys	Ftruncate(fd int, length int64) (errno int)
+//sys	Chown(path string, uid int, gid int) (err error)
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Fstat(fd int, stat *Stat_t) (err error)
+//sys	Fstatfs(fd int, buf *Statfs_t) (err error)
+//sys	Ftruncate(fd int, length int64) (err error)
 //sysnb	Getegid() (egid int)
 //sysnb	Geteuid() (euid int)
 //sysnb	Getgid() (gid int)
 //sysnb	Getuid() (uid int)
-//sys	Ioperm(from int, num int, on int) (errno int)
-//sys	Iopl(level int) (errno int)
-//sys	Lchown(path string, uid int, gid int) (errno int)
-//sys	Listen(s int, n int) (errno int)
-//sys	Lstat(path string, stat *Stat_t) (errno int)
-//sys	Pread(fd int, p []byte, offset int64) (n int, errno int) = SYS_PREAD64
-//sys	Pwrite(fd int, p []byte, offset int64) (n int, errno int) = SYS_PWRITE64
-//sys	Seek(fd int, offset int64, whence int) (off int64, errno int) = SYS_LSEEK
-//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int)
-//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int)
-//sys	Setfsgid(gid int) (errno int)
-//sys	Setfsuid(uid int) (errno int)
-//sysnb	Setgid(gid int) (errno int)
-//sysnb	Setregid(rgid int, egid int) (errno int)
-//sysnb	Setresgid(rgid int, egid int, sgid int) (errno int)
-//sysnb	Setresuid(ruid int, euid int, suid int) (errno int)
-//sysnb	Setreuid(ruid int, euid int) (errno int)
-//sys	Shutdown(fd int, how int) (errno int)
-//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, errno int)
-//sys	Stat(path string, stat *Stat_t) (errno int)
-//sys	Statfs(path string, buf *Statfs_t) (errno int)
-//sys	SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
-//sys	Truncate(path string, length int64) (errno int)
-//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
-//sys	bind(s int, addr uintptr, addrlen _Socklen) (errno int)
-//sys	connect(s int, addr uintptr, addrlen _Socklen) (errno int)
-//sysnb	getgroups(n int, list *_Gid_t) (nn int, errno int)
-//sysnb	setgroups(n int, list *_Gid_t) (errno int)
-//sys	getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int)
-//sys	setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int)
-//sysnb	socket(domain int, typ int, proto int) (fd int, errno int)
-//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int) (errno int)
-//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
-//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
-//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
-//sys	sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
-//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
-//sys	sendmsg(s int, msg *Msghdr, flags int) (errno int)
-//sys	mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int)
+//sys	Ioperm(from int, num int, on int) (err error)
+//sys	Iopl(level int) (err error)
+//sys	Lchown(path string, uid int, gid int) (err error)
+//sys	Listen(s int, n int) (err error)
+//sys	Lstat(path string, stat *Stat_t) (err error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys	Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
+//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
+//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
+//sys	Setfsgid(gid int) (err error)
+//sys	Setfsuid(uid int) (err error)
+//sysnb	Setgid(gid int) (err error)
+//sysnb	Setregid(rgid int, egid int) (err error)
+//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
+//sysnb	Setresuid(ruid int, euid int, suid int) (err error)
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//sys	Shutdown(fd int, how int) (err error)
+//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
+//sys	Stat(path string, stat *Stat_t) (err error)
+//sys	Statfs(path string, buf *Statfs_t) (err error)
+//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error)
+//sys	Truncate(path string, length int64) (err error)
+//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
+//sys	bind(s int, addr uintptr, addrlen _Socklen) (err error)
+//sys	connect(s int, addr uintptr, addrlen _Socklen) (err error)
+//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
+//sysnb	setgroups(n int, list *_Gid_t) (err error)
+//sys	getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error)
+//sys	setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error)
+//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
+//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int) (err error)
+//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
+//sys	sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error)
+//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sys	sendmsg(s int, msg *Msghdr, flags int) (err error)
+//sys	mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
 
 func Getpagesize() int { return 4096 }
 
-func Gettimeofday(tv *Timeval) (errno int)
-func Time(t *Time_t) (tt Time_t, errno int)
+func Gettimeofday(tv *Timeval) (err error)
+func Time(t *Time_t) (tt Time_t, err error)
 
 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
 
diff --git a/src/pkg/syscall/syscall_linux_arm.go b/src/pkg/syscall/syscall_linux_arm.go
index 8c03c76..744e035 100644
--- a/src/pkg/syscall/syscall_linux_arm.go
+++ b/src/pkg/syscall/syscall_linux_arm.go
@@ -25,94 +25,102 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
 
 // Pread and Pwrite are special: they insert padding before the int64.
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	// ARM EABI requires 64-bit arguments should be put in a pair
 	// of registers from an even register number.
 	_, _, e1 := Syscall6(SYS_FTRUNCATE64, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall6(SYS_TRUNCATE64, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length), uintptr(length>>32), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // Seek is defined in assembly.
 
-func Seek(fd int, offset int64, whence int) (newoffset int64, errno int)
-
-//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int)
-//sys	bind(s int, addr uintptr, addrlen _Socklen) (errno int)
-//sys	connect(s int, addr uintptr, addrlen _Socklen) (errno int)
-//sysnb	getgroups(n int, list *_Gid_t) (nn int, errno int) = SYS_GETGROUPS32
-//sysnb	setgroups(n int, list *_Gid_t) (errno int) = SYS_SETGROUPS32
-//sys	getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int)
-//sys	setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int)
-//sysnb	socket(domain int, typ int, proto int) (fd int, errno int)
-//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
-//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int)
-//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int)
-//sys	sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int)
-//sysnb	socketpair(domain int, typ int, flags int, fd *[2]int) (errno int)
-//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
-//sys	sendmsg(s int, msg *Msghdr, flags int) (errno int)
-
-//sys	Chown(path string, uid int, gid int) (errno int)
-//sys	Fchown(fd int, uid int, gid int) (errno int)
-//sys	Fstat(fd int, stat *Stat_t) (errno int) = SYS_FSTAT64
-//sys	Fstatfs(fd int, buf *Statfs_t) (errno int) = SYS_FSTATFS64
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
+
+//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
+//sys	bind(s int, addr uintptr, addrlen _Socklen) (err error)
+//sys	connect(s int, addr uintptr, addrlen _Socklen) (err error)
+//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error) = SYS_GETGROUPS32
+//sysnb	setgroups(n int, list *_Gid_t) (err error) = SYS_SETGROUPS32
+//sys	getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error)
+//sys	setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error)
+//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
+//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
+//sys	sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error)
+//sysnb	socketpair(domain int, typ int, flags int, fd *[2]int) (err error)
+//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sys	sendmsg(s int, msg *Msghdr, flags int) (err error)
+
+//sys	Chown(path string, uid int, gid int) (err error)
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
+//sys	Fstatfs(fd int, buf *Statfs_t) (err error) = SYS_FSTATFS64
 //sysnb	Getegid() (egid int)
 //sysnb	Geteuid() (euid int)
 //sysnb	Getgid() (gid int)
 //sysnb	Getuid() (uid int)
-//sys	Lchown(path string, uid int, gid int) (errno int)
-//sys	Listen(s int, n int) (errno int)
-//sys	Lstat(path string, stat *Stat_t) (errno int) = SYS_LSTAT64
-//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) = SYS_SENDFILE64
-//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int) = SYS__NEWSELECT
-//sys	Setfsgid(gid int) (errno int)
-//sys	Setfsuid(uid int) (errno int)
-//sysnb	Setgid(gid int) (errno int)
-//sysnb	Setregid(rgid int, egid int) (errno int)
-//sysnb	Setresgid(rgid int, egid int, sgid int) (errno int)
-//sysnb	Setresuid(ruid int, euid int, suid int) (errno int)
-//sysnb	Setreuid(ruid int, euid int) (errno int)
-//sys	Shutdown(fd int, how int) (errno int)
-//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, errno int)
-//sys	Stat(path string, stat *Stat_t) (errno int) = SYS_STAT64
-//sys	Statfs(path string, buf *Statfs_t) (errno int) = SYS_STATFS64
+//sys	Lchown(path string, uid int, gid int) (err error)
+//sys	Listen(s int, n int) (err error)
+//sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
+//sys	Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
+//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
+//sys	Setfsgid(gid int) (err error)
+//sys	Setfsuid(uid int) (err error)
+//sysnb	Setgid(gid int) (err error)
+//sysnb	Setregid(rgid int, egid int) (err error)
+//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
+//sysnb	Setresuid(ruid int, euid int, suid int) (err error)
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//sys	Shutdown(fd int, how int) (err error)
+//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
+//sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
+//sys	Statfs(path string, buf *Statfs_t) (err error) = SYS_STATFS64
 
 // Vsyscalls on amd64.
-//sysnb	Gettimeofday(tv *Timeval) (errno int)
-//sysnb	Time(t *Time_t) (tt Time_t, errno int)
+//sysnb	Gettimeofday(tv *Timeval) (err error)
+//sysnb	Time(t *Time_t) (tt Time_t, err error)
 
-//sys	mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, errno int)
+//sys	mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
 
-func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int) {
+func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
 	page := uintptr(offset / 4096)
 	if offset != int64(page)*4096 {
 		return 0, EINVAL
diff --git a/src/pkg/syscall/syscall_netbsd.go b/src/pkg/syscall/syscall_netbsd.go
new file mode 100644
index 0000000..77ca950
--- /dev/null
+++ b/src/pkg/syscall/syscall_netbsd.go
@@ -0,0 +1,434 @@
+// Copyright 2009,2010 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.
+
+// NetBSD system calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates system call stubs.
+// Note that sometimes we use a lowercase //sys name and wrap
+// it in our own nicer implementation, either here or in
+// syscall_bsd.go or syscall_unix.go.
+
+package syscall
+
+import "unsafe"
+
+type SockaddrDatalink struct {
+	Len    uint8
+	Family uint8
+	Index  uint16
+	Type   uint8
+	Nlen   uint8
+	Alen   uint8
+	Slen   uint8
+	Data   [24]int8
+	raw    RawSockaddrDatalink
+}
+
+func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
+
+func nametomib(name string) (mib []_C_int, err error) {
+	return nil, EINVAL
+}
+
+// ParseDirent parses up to max directory entries in buf,
+// appending the names to names. It returns the number
+// bytes consumed from buf, the number of entries added
+// to names, and the new names slice.
+func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
+	origlen := len(buf)
+	for max != 0 && len(buf) > 0 {
+		dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
+		if dirent.Reclen == 0 {
+			buf = nil
+			break
+		}
+		buf = buf[dirent.Reclen:]
+		if dirent.Fileno == 0 { // File absent in directory.
+			continue
+		}
+		bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
+		var name = string(bytes[0:dirent.Namlen])
+		if name == "." || name == ".." { // Useless names
+			continue
+		}
+		max--
+		count++
+		names = append(names, name)
+	}
+	return origlen - len(buf), count, names
+}
+
+//sysnb pipe2(p *[2]_C_int, flags _C_int) (err error)
+func Pipe(p []int) (err error) {
+	if len(p) != 2 {
+		return EINVAL
+	}
+	var pp [2]_C_int
+	err = pipe2(&pp, 0)
+	p[0] = int(pp[0])
+	p[1] = int(pp[1])
+	return
+}
+
+//sys getdents(fd int, buf []byte) (n int, err error)
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	return getdents(fd, buf)
+}
+
+// TODO
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	return -1, ENOSYS
+}
+
+/*
+ * Exposed directly
+ */
+//sys	Access(path string, mode uint32) (err error)
+//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
+//sys	Chdir(path string) (err error)
+//sys	Chflags(path string, flags int) (err error)
+//sys	Chmod(path string, mode uint32) (err error)
+//sys	Chown(path string, uid int, gid int) (err error)
+//sys	Chroot(path string) (err error)
+//sys	Close(fd int) (err error)
+//sysnb	Dup(fd int) (nfd int, err error)
+//sysnb	Dup2(from int, to int) (err error)
+//sys	Exit(code int)
+//sys	Fchdir(fd int) (err error)
+//sys	Fchflags(path string, flags int) (err error)
+//sys	Fchmod(fd int, mode uint32) (err error)
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Flock(fd int, how int) (err error)
+//sys	Fpathconf(fd int, name int) (val int, err error)
+//sys	Fstat(fd int, stat *Stat_t) (err error)
+//sys	Fsync(fd int) (err error)
+//sys	Ftruncate(fd int, length int64) (err error)
+//sysnb	Getegid() (egid int)
+//sysnb	Geteuid() (uid int)
+//sysnb	Getgid() (gid int)
+//sysnb	Getpgid(pid int) (pgid int, err error)
+//sysnb	Getpgrp() (pgrp int)
+//sysnb	Getpid() (pid int)
+//sysnb	Getppid() (ppid int)
+//sys	Getpriority(which int, who int) (prio int, err error)
+//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Getrusage(who int, rusage *Rusage) (err error)
+//sysnb	Getsid(pid int) (sid int, err error)
+//sysnb	Gettimeofday(tv *Timeval) (err error)
+//sysnb	Getuid() (uid int)
+//sys	Issetugid() (tainted bool)
+//sys	Kill(pid int, signum int) (err error)
+//sys	Kqueue() (fd int, err error)
+//sys	Lchown(path string, uid int, gid int) (err error)
+//sys	Link(path string, link string) (err error)
+//sys	Listen(s int, backlog int) (err error)
+//sys	Lstat(path string, stat *Stat_t) (err error)
+//sys	Mkdir(path string, mode uint32) (err error)
+//sys	Mkfifo(path string, mode uint32) (err error)
+//sys	Mknod(path string, mode uint32, dev int) (err error)
+//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
+//sys	Open(path string, mode int, perm uint32) (fd int, err error)
+//sys	Pathconf(path string, name int) (val int, err error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys	Read(fd int, p []byte) (n int, err error)
+//sys	Readlink(path string, buf []byte) (n int, err error)
+//sys	Rename(from string, to string) (err error)
+//sys	Revoke(path string) (err error)
+//sys	Rmdir(path string) (err error)
+//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
+//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
+//sysnb	Setegid(egid int) (err error)
+//sysnb	Seteuid(euid int) (err error)
+//sysnb	Setgid(gid int) (err error)
+//sysnb	Setpgid(pid int, pgid int) (err error)
+//sys	Setpriority(which int, who int, prio int) (err error)
+//sysnb	Setregid(rgid int, egid int) (err error)
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//sysnb	Setrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Setsid() (pid int, err error)
+//sysnb	Settimeofday(tp *Timeval) (err error)
+//sysnb	Setuid(uid int) (err error)
+//sys	Stat(path string, stat *Stat_t) (err error)
+//sys	Symlink(path string, link string) (err error)
+//sys	Sync() (err error)
+//sys	Truncate(path string, length int64) (err error)
+//sys	Umask(newmask int) (oldmask int)
+//sys	Unlink(path string) (err error)
+//sys	Unmount(path string, flags int) (err error)
+//sys	Write(fd int, p []byte) (n int, err error)
+//sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
+//sys	munmap(addr uintptr, length uintptr) (err error)
+//sys	read(fd int, buf *byte, nbuf int) (n int, err error)
+//sys	write(fd int, buf *byte, nbuf int) (n int, err error)
+
+/*
+ * Unimplemented
+ */
+// ____semctl13
+// __clone
+// __fhopen40
+// __fhstat40
+// __fhstatvfs140
+// __fstat30
+// __getcwd
+// __getfh30
+// __getlogin
+// __lstat30
+// __mount50
+// __msgctl13
+// __msync13
+// __ntp_gettime30
+// __posix_chown
+// __posix_fadvise50
+// __posix_fchown
+// __posix_lchown
+// __posix_rename
+// __setlogin
+// __shmctl13
+// __sigaction_sigtramp
+// __sigaltstack14
+// __sigpending14
+// __sigprocmask14
+// __sigsuspend14
+// __sigtimedwait
+// __stat30
+// __syscall
+// __vfork14
+// _ksem_close
+// _ksem_destroy
+// _ksem_getvalue
+// _ksem_init
+// _ksem_open
+// _ksem_post
+// _ksem_trywait
+// _ksem_unlink
+// _ksem_wait
+// _lwp_continue
+// _lwp_create
+// _lwp_ctl
+// _lwp_detach
+// _lwp_exit
+// _lwp_getname
+// _lwp_getprivate
+// _lwp_kill
+// _lwp_park
+// _lwp_self
+// _lwp_setname
+// _lwp_setprivate
+// _lwp_suspend
+// _lwp_unpark
+// _lwp_unpark_all
+// _lwp_wait
+// _lwp_wakeup
+// _pset_bind
+// _sched_getaffinity
+// _sched_getparam
+// _sched_setaffinity
+// _sched_setparam
+// acct
+// aio_cancel
+// aio_error
+// aio_fsync
+// aio_read
+// aio_return
+// aio_suspend
+// aio_write
+// break
+// clock_getres
+// clock_gettime
+// clock_settime
+// compat_09_ogetdomainname
+// compat_09_osetdomainname
+// compat_09_ouname
+// compat_10_omsgsys
+// compat_10_osemsys
+// compat_10_oshmsys
+// compat_12_fstat12
+// compat_12_getdirentries
+// compat_12_lstat12
+// compat_12_msync
+// compat_12_oreboot
+// compat_12_oswapon
+// compat_12_stat12
+// compat_13_sigaction13
+// compat_13_sigaltstack13
+// compat_13_sigpending13
+// compat_13_sigprocmask13
+// compat_13_sigreturn13
+// compat_13_sigsuspend13
+// compat_14___semctl
+// compat_14_msgctl
+// compat_14_shmctl
+// compat_16___sigaction14
+// compat_16___sigreturn14
+// compat_20_fhstatfs
+// compat_20_fstatfs
+// compat_20_getfsstat
+// compat_20_statfs
+// compat_30___fhstat30
+// compat_30___fstat13
+// compat_30___lstat13
+// compat_30___stat13
+// compat_30_fhopen
+// compat_30_fhstat
+// compat_30_fhstatvfs1
+// compat_30_getdents
+// compat_30_getfh
+// compat_30_ntp_gettime
+// compat_30_socket
+// compat_40_mount
+// compat_43_fstat43
+// compat_43_lstat43
+// compat_43_oaccept
+// compat_43_ocreat
+// compat_43_oftruncate
+// compat_43_ogetdirentries
+// compat_43_ogetdtablesize
+// compat_43_ogethostid
+// compat_43_ogethostname
+// compat_43_ogetkerninfo
+// compat_43_ogetpagesize
+// compat_43_ogetpeername
+// compat_43_ogetrlimit
+// compat_43_ogetsockname
+// compat_43_okillpg
+// compat_43_olseek
+// compat_43_ommap
+// compat_43_oquota
+// compat_43_orecv
+// compat_43_orecvfrom
+// compat_43_orecvmsg
+// compat_43_osend
+// compat_43_osendmsg
+// compat_43_osethostid
+// compat_43_osethostname
+// compat_43_osetrlimit
+// compat_43_osigblock
+// compat_43_osigsetmask
+// compat_43_osigstack
+// compat_43_osigvec
+// compat_43_otruncate
+// compat_43_owait
+// compat_43_stat43
+// execve
+// extattr_delete_fd
+// extattr_delete_file
+// extattr_delete_link
+// extattr_get_fd
+// extattr_get_file
+// extattr_get_link
+// extattr_list_fd
+// extattr_list_file
+// extattr_list_link
+// extattr_set_fd
+// extattr_set_file
+// extattr_set_link
+// extattrctl
+// fchroot
+// fdatasync
+// fgetxattr
+// fktrace
+// flistxattr
+// fork
+// fremovexattr
+// fsetxattr
+// fstatvfs1
+// fsync_range
+// getcontext
+// getitimer
+// getvfsstat
+// getxattr
+// ioctl
+// ktrace
+// lchflags
+// lchmod
+// lfs_bmapv
+// lfs_markv
+// lfs_segclean
+// lfs_segwait
+// lgetxattr
+// lio_listio
+// listxattr
+// llistxattr
+// lremovexattr
+// lseek
+// lsetxattr
+// lutimes
+// madvise
+// mincore
+// minherit
+// mlock
+// mlockall
+// modctl
+// mprotect
+// mq_close
+// mq_getattr
+// mq_notify
+// mq_open
+// mq_receive
+// mq_send
+// mq_setattr
+// mq_timedreceive
+// mq_timedsend
+// mq_unlink
+// mremap
+// msgget
+// msgrcv
+// msgsnd
+// munlock
+// munlockall
+// nfssvc
+// ntp_adjtime
+// pmc_control
+// pmc_get_info
+// poll
+// pollts
+// preadv
+// profil
+// pselect
+// pset_assign
+// pset_create
+// pset_destroy
+// ptrace
+// pwritev
+// quotactl
+// rasctl
+// readv
+// reboot
+// removexattr
+// sa_enable
+// sa_preempt
+// sa_register
+// sa_setconcurrency
+// sa_stacks
+// sa_yield
+// sbrk
+// sched_yield
+// semconfig
+// semget
+// semop
+// setcontext
+// setitimer
+// setxattr
+// shmat
+// shmdt
+// shmget
+// sstk
+// statvfs1
+// swapctl
+// sysarch
+// syscall
+// timer_create
+// timer_delete
+// timer_getoverrun
+// timer_gettime
+// timer_settime
+// undelete
+// utrace
+// uuidgen
+// vadvise
+// vfork
+// writev
diff --git a/src/pkg/syscall/syscall_openbsd_386.go b/src/pkg/syscall/syscall_netbsd_386.go
similarity index 100%
copy from src/pkg/syscall/syscall_openbsd_386.go
copy to src/pkg/syscall/syscall_netbsd_386.go
diff --git a/src/pkg/syscall/syscall_netbsd_amd64.go b/src/pkg/syscall/syscall_netbsd_amd64.go
new file mode 100644
index 0000000..17485b1
--- /dev/null
+++ b/src/pkg/syscall/syscall_netbsd_amd64.go
@@ -0,0 +1,42 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+func Getpagesize() int { return 4096 }
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+	ts.Sec = int32(nsec / 1e9)
+	ts.Nsec = nsec % 1e9
+	return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+	nsec += 999 // round up to microsecond
+	tv.Usec = nsec % 1e9 / 1e3
+	tv.Sec = int64(nsec / 1e9)
+	return
+}
+
+func SetKevent(k *Kevent_t, fd, mode, flags int) {
+	k.Ident = uint64(fd)
+	k.Filter = int16(mode)
+	k.Flags = uint16(flags)
+}
+
+func (iov *Iovec) SetLen(length int) {
+	iov.Len = uint64(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+	msghdr.Controllen = uint32(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+	cmsg.Len = uint32(length)
+}
diff --git a/src/pkg/syscall/syscall_openbsd.go b/src/pkg/syscall/syscall_openbsd.go
index da1bd4d..adbbf3d 100644
--- a/src/pkg/syscall/syscall_openbsd.go
+++ b/src/pkg/syscall/syscall_openbsd.go
@@ -14,8 +14,6 @@ package syscall
 
 import "unsafe"
 
-const OS = "openbsd"
-
 type SockaddrDatalink struct {
 	Len    uint8
 	Family uint8
@@ -28,7 +26,29 @@ type SockaddrDatalink struct {
 	raw    RawSockaddrDatalink
 }
 
-func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr)
+func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
+
+func nametomib(name string) (mib []_C_int, err error) {
+
+	// Perform lookup via a binary search
+	left := 0
+	right := len(sysctlMib) - 1
+	for {
+		idx := left + (right-left)/2
+		switch {
+		case name == sysctlMib[idx].ctlname:
+			return sysctlMib[idx].ctloid, nil
+		case name > sysctlMib[idx].ctlname:
+			left = idx + 1
+		default:
+			right = idx - 1
+		}
+		if left > right {
+			break
+		}
+	}
+	return nil, EINVAL
+}
 
 // ParseDirent parses up to max directory entries in buf,
 // appending the names to names. It returns the number
@@ -58,109 +78,109 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
 	return origlen - len(buf), count, names
 }
 
-//sysnb pipe(p *[2]_C_int) (errno int)
-func Pipe(p []int) (errno int) {
+//sysnb pipe(p *[2]_C_int) (err error)
+func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return EINVAL
 	}
 	var pp [2]_C_int
-	errno = pipe(&pp)
+	err = pipe(&pp)
 	p[0] = int(pp[0])
 	p[1] = int(pp[1])
 	return
 }
 
 // TODO
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	return -1, ENOSYS
 }
 
 /*
  * Exposed directly
  */
-//sys	Access(path string, mode uint32) (errno int)
-//sys	Adjtime(delta *Timeval, olddelta *Timeval) (errno int)
-//sys	Chdir(path string) (errno int)
-//sys	Chflags(path string, flags int) (errno int)
-//sys	Chmod(path string, mode uint32) (errno int)
-//sys	Chown(path string, uid int, gid int) (errno int)
-//sys	Chroot(path string) (errno int)
-//sys	Close(fd int) (errno int)
-//sysnb	Dup(fd int) (nfd int, errno int)
-//sysnb	Dup2(from int, to int) (errno int)
+//sys	Access(path string, mode uint32) (err error)
+//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
+//sys	Chdir(path string) (err error)
+//sys	Chflags(path string, flags int) (err error)
+//sys	Chmod(path string, mode uint32) (err error)
+//sys	Chown(path string, uid int, gid int) (err error)
+//sys	Chroot(path string) (err error)
+//sys	Close(fd int) (err error)
+//sysnb	Dup(fd int) (nfd int, err error)
+//sysnb	Dup2(from int, to int) (err error)
 //sys	Exit(code int)
-//sys	Fchdir(fd int) (errno int)
-//sys	Fchflags(path string, flags int) (errno int)
-//sys	Fchmod(fd int, mode uint32) (errno int)
-//sys	Fchown(fd int, uid int, gid int) (errno int)
-//sys	Flock(fd int, how int) (errno int)
-//sys	Fpathconf(fd int, name int) (val int, errno int)
-//sys	Fstat(fd int, stat *Stat_t) (errno int)
-//sys	Fstatfs(fd int, stat *Statfs_t) (errno int)
-//sys	Fsync(fd int) (errno int)
-//sys	Ftruncate(fd int, length int64) (errno int)
-//sys	Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int)
+//sys	Fchdir(fd int) (err error)
+//sys	Fchflags(path string, flags int) (err error)
+//sys	Fchmod(fd int, mode uint32) (err error)
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Flock(fd int, how int) (err error)
+//sys	Fpathconf(fd int, name int) (val int, err error)
+//sys	Fstat(fd int, stat *Stat_t) (err error)
+//sys	Fstatfs(fd int, stat *Statfs_t) (err error)
+//sys	Fsync(fd int) (err error)
+//sys	Ftruncate(fd int, length int64) (err error)
+//sys	Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
 //sysnb	Getegid() (egid int)
 //sysnb	Geteuid() (uid int)
-//sys	Getfsstat(buf []Statfs_t, flags int) (n int, errno int)
+//sys	Getfsstat(buf []Statfs_t, flags int) (n int, err error)
 //sysnb	Getgid() (gid int)
-//sysnb	Getpgid(pid int) (pgid int, errno int)
+//sysnb	Getpgid(pid int) (pgid int, err error)
 //sysnb	Getpgrp() (pgrp int)
 //sysnb	Getpid() (pid int)
 //sysnb	Getppid() (ppid int)
-//sys	Getpriority(which int, who int) (prio int, errno int)
-//sysnb	Getrlimit(which int, lim *Rlimit) (errno int)
-//sysnb	Getrusage(who int, rusage *Rusage) (errno int)
-//sysnb	Getsid(pid int) (sid int, errno int)
-//sysnb	Gettimeofday(tv *Timeval) (errno int)
+//sys	Getpriority(which int, who int) (prio int, err error)
+//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Getrusage(who int, rusage *Rusage) (err error)
+//sysnb	Getsid(pid int) (sid int, err error)
+//sysnb	Gettimeofday(tv *Timeval) (err error)
 //sysnb	Getuid() (uid int)
 //sys	Issetugid() (tainted bool)
-//sys	Kill(pid int, signum int) (errno int)
-//sys	Kqueue() (fd int, errno int)
-//sys	Lchown(path string, uid int, gid int) (errno int)
-//sys	Link(path string, link string) (errno int)
-//sys	Listen(s int, backlog int) (errno int)
-//sys	Lstat(path string, stat *Stat_t) (errno int)
-//sys	Mkdir(path string, mode uint32) (errno int)
-//sys	Mkfifo(path string, mode uint32) (errno int)
-//sys	Mknod(path string, mode uint32, dev int) (errno int)
-//sys	Nanosleep(time *Timespec, leftover *Timespec) (errno int)
-//sys	Open(path string, mode int, perm uint32) (fd int, errno int)
-//sys	Pathconf(path string, name int) (val int, errno int)
-//sys	Pread(fd int, p []byte, offset int64) (n int, errno int)
-//sys	Pwrite(fd int, p []byte, offset int64) (n int, errno int)
-//sys	Read(fd int, p []byte) (n int, errno int)
-//sys	Readlink(path string, buf []byte) (n int, errno int)
-//sys	Rename(from string, to string) (errno int)
-//sys	Revoke(path string) (errno int)
-//sys	Rmdir(path string) (errno int)
-//sys	Seek(fd int, offset int64, whence int) (newoffset int64, errno int) = SYS_LSEEK
-//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int)
-//sysnb	Setegid(egid int) (errno int)
-//sysnb	Seteuid(euid int) (errno int)
-//sysnb	Setgid(gid int) (errno int)
-//sys	Setlogin(name string) (errno int)
-//sysnb	Setpgid(pid int, pgid int) (errno int)
-//sys	Setpriority(which int, who int, prio int) (errno int)
-//sysnb	Setregid(rgid int, egid int) (errno int)
-//sysnb	Setreuid(ruid int, euid int) (errno int)
-//sysnb	Setrlimit(which int, lim *Rlimit) (errno int)
-//sysnb	Setsid() (pid int, errno int)
-//sysnb	Settimeofday(tp *Timeval) (errno int)
-//sysnb	Setuid(uid int) (errno int)
-//sys	Stat(path string, stat *Stat_t) (errno int)
-//sys	Statfs(path string, stat *Statfs_t) (errno int)
-//sys	Symlink(path string, link string) (errno int)
-//sys	Sync() (errno int)
-//sys	Truncate(path string, length int64) (errno int)
+//sys	Kill(pid int, signum int) (err error)
+//sys	Kqueue() (fd int, err error)
+//sys	Lchown(path string, uid int, gid int) (err error)
+//sys	Link(path string, link string) (err error)
+//sys	Listen(s int, backlog int) (err error)
+//sys	Lstat(path string, stat *Stat_t) (err error)
+//sys	Mkdir(path string, mode uint32) (err error)
+//sys	Mkfifo(path string, mode uint32) (err error)
+//sys	Mknod(path string, mode uint32, dev int) (err error)
+//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
+//sys	Open(path string, mode int, perm uint32) (fd int, err error)
+//sys	Pathconf(path string, name int) (val int, err error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys	Read(fd int, p []byte) (n int, err error)
+//sys	Readlink(path string, buf []byte) (n int, err error)
+//sys	Rename(from string, to string) (err error)
+//sys	Revoke(path string) (err error)
+//sys	Rmdir(path string) (err error)
+//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
+//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
+//sysnb	Setegid(egid int) (err error)
+//sysnb	Seteuid(euid int) (err error)
+//sysnb	Setgid(gid int) (err error)
+//sys	Setlogin(name string) (err error)
+//sysnb	Setpgid(pid int, pgid int) (err error)
+//sys	Setpriority(which int, who int, prio int) (err error)
+//sysnb	Setregid(rgid int, egid int) (err error)
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//sysnb	Setrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Setsid() (pid int, err error)
+//sysnb	Settimeofday(tp *Timeval) (err error)
+//sysnb	Setuid(uid int) (err error)
+//sys	Stat(path string, stat *Stat_t) (err error)
+//sys	Statfs(path string, stat *Statfs_t) (err error)
+//sys	Symlink(path string, link string) (err error)
+//sys	Sync() (err error)
+//sys	Truncate(path string, length int64) (err error)
 //sys	Umask(newmask int) (oldmask int)
-//sys	Unlink(path string) (errno int)
-//sys	Unmount(path string, flags int) (errno int)
-//sys	Write(fd int, p []byte) (n int, errno int)
-//sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int)
-//sys	munmap(addr uintptr, length uintptr) (errno int)
-//sys	read(fd int, buf *byte, nbuf int) (n int, errno int)
-//sys	write(fd int, buf *byte, nbuf int) (n int, errno int)
+//sys	Unlink(path string) (err error)
+//sys	Unmount(path string, flags int) (err error)
+//sys	Write(fd int, p []byte) (n int, err error)
+//sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
+//sys	munmap(addr uintptr, length uintptr) (err error)
+//sys	read(fd int, buf *byte, nbuf int) (n int, err error)
+//sys	write(fd int, buf *byte, nbuf int) (n int, err error)
 
 /*
  * Unimplemented
diff --git a/src/pkg/syscall/syscall_plan9.go b/src/pkg/syscall/syscall_plan9.go
index eacdd93..0bbb7ec 100644
--- a/src/pkg/syscall/syscall_plan9.go
+++ b/src/pkg/syscall/syscall_plan9.go
@@ -13,22 +13,15 @@ package syscall
 
 import "unsafe"
 
-const OS = "plan9"
-
 const ImplementsGetwd = true
 
-// An Error can represent any printable error condition.
-type Error interface {
-	String() string
-}
-
 // ErrorString implements Error's String method by returning itself.
 type ErrorString string
 
-func (e ErrorString) String() string { return string(e) }
+func (e ErrorString) Error() string { return string(e) }
 
 // NewError converts s to an ErrorString, which satisfies the Error interface.
-func NewError(s string) Error { return ErrorString(s) }
+func NewError(s string) error { return ErrorString(s) }
 
 var (
 	Stdin  = 0
@@ -43,8 +36,8 @@ var (
 // creation of IPv6 sockets to return EAFNOSUPPORT.
 var SocketDisableIPv6 bool
 
-func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err string)
-func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err string)
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
 
@@ -94,7 +87,7 @@ func Exit(code int) {
 	Exits(&msg)
 }
 
-func readnum(path string) (uint, Error) {
+func readnum(path string) (uint, error) {
 	var b [12]byte
 
 	fd, e := Open(path, O_RDONLY)
@@ -126,15 +119,15 @@ func Getppid() (ppid int) {
 	return int(n)
 }
 
-func Read(fd int, p []byte) (n int, err Error) {
+func Read(fd int, p []byte) (n int, err error) {
 	return Pread(fd, p, -1)
 }
 
-func Write(fd int, p []byte) (n int, err Error) {
+func Write(fd int, p []byte) (n int, err error) {
 	return Pwrite(fd, p, -1)
 }
 
-func Getwd() (wd string, err Error) {
+func Getwd() (wd string, err error) {
 	fd, e := Open(".", O_RDONLY)
 
 	if e != nil {
@@ -145,8 +138,8 @@ func Getwd() (wd string, err Error) {
 	return Fd2path(fd)
 }
 
-//sys	fd2path(fd int, buf []byte) (err Error)
-func Fd2path(fd int) (path string, err Error) {
+//sys	fd2path(fd int, buf []byte) (err error)
+func Fd2path(fd int) (path string, err error) {
 	var buf [512]byte
 
 	e := fd2path(fd, buf[:])
@@ -156,8 +149,8 @@ func Fd2path(fd int) (path string, err Error) {
 	return cstring(buf[:]), nil
 }
 
-//sys	pipe(p *[2]_C_int) (err Error)
-func Pipe(p []int) (err Error) {
+//sys	pipe(p *[2]_C_int) (err error)
+func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return NewError("bad arg in system call")
 	}
@@ -168,26 +161,20 @@ func Pipe(p []int) (err Error) {
 	return
 }
 
-//sys	sleep(millisecs int32) (err Error)
-func Sleep(nsec int64) (err Error) {
-	return sleep(int32((nsec + 999) / 1e6)) // round up to microsecond
-}
-
 // Underlying system call writes to newoffset via pointer.
 // Implemented in assembly to avoid allocation.
 func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)
 
-func Seek(fd int, offset int64, whence int) (newoffset int64, err Error) {
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 	newoffset, e := seek(0, fd, offset, whence)
 
-	err = nil
 	if newoffset == -1 {
 		err = NewError(e)
 	}
 	return
 }
 
-func Mkdir(path string, mode uint32) (err Error) {
+func Mkdir(path string, mode uint32) (err error) {
 	fd, err := Create(path, O_RDONLY, DMDIR|mode)
 
 	if fd != -1 {
@@ -214,8 +201,8 @@ func (w Waitmsg) ExitStatus() int {
 	return 1
 }
 
-//sys	await(s []byte) (n int, err Error)
-func Await(w *Waitmsg) (err Error) {
+//sys	await(s []byte) (n int, err error)
+func Await(w *Waitmsg) (err error) {
 	var buf [512]byte
 	var f [5][]byte
 
@@ -245,14 +232,18 @@ func Await(w *Waitmsg) (err Error) {
 	w.Time[1] = uint32(atoi(f[2]))
 	w.Time[2] = uint32(atoi(f[3]))
 	w.Msg = cstring(f[4])
+	if w.Msg == "''" {
+		// await() returns '' for no error
+		w.Msg = ""
+	}
 	return
 }
 
-func Unmount(name, old string) (err Error) {
+func Unmount(name, old string) (err error) {
 	oldp := uintptr(unsafe.Pointer(StringBytePtr(old)))
 
 	var r0 uintptr
-	var e string
+	var e ErrorString
 
 	// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
 	if name == "" {
@@ -261,14 +252,13 @@ func Unmount(name, old string) (err Error) {
 		r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), oldp, 0)
 	}
 
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e)
+		err = e
 	}
 	return
 }
 
-func Fchdir(fd int) (err Error) {
+func Fchdir(fd int) (err error) {
 	path, err := Fd2path(fd)
 
 	if err != nil {
@@ -278,6 +268,11 @@ func Fchdir(fd int) (err Error) {
 	return Chdir(path)
 }
 
+type Timespec struct {
+	Sec  int32
+	Nsec int32
+}
+
 type Timeval struct {
 	Sec  int32
 	Usec int32
@@ -290,11 +285,10 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
 	return
 }
 
-func DecodeBintime(b []byte) (nsec int64, err Error) {
+func DecodeBintime(b []byte) (nsec int64, err error) {
 	if len(b) != 8 {
 		return -1, NewError("bad /dev/bintime format")
 	}
-	err = nil
 	nsec = int64(b[0])<<56 |
 		int64(b[1])<<48 |
 		int64(b[2])<<40 |
@@ -306,7 +300,7 @@ func DecodeBintime(b []byte) (nsec int64, err Error) {
 	return
 }
 
-func Gettimeofday(tv *Timeval) (err Error) {
+func Gettimeofday(tv *Timeval) (err error) {
 	// TODO(paulzhol): 
 	// avoid reopening a file descriptor for /dev/bintime on each call,
 	// use lower-level calls to avoid allocation.
@@ -337,21 +331,21 @@ func Geteuid() (euid int) { return -1 }
 func Getgid() (gid int)   { return -1 }
 func Getuid() (uid int)   { return -1 }
 
-func Getgroups() (gids []int, err Error) {
+func Getgroups() (gids []int, err error) {
 	return make([]int, 0), nil
 }
 
-//sys	Dup(oldfd int, newfd int) (fd int, err Error)
-//sys	Open(path string, mode int) (fd int, err Error)
-//sys	Create(path string, mode int, perm uint32) (fd int, err Error)
-//sys	Remove(path string) (err Error)
-//sys	Pread(fd int, p []byte, offset int64) (n int, err Error)
-//sys	Pwrite(fd int, p []byte, offset int64) (n int, err Error)
-//sys	Close(fd int) (err Error)
-//sys	Chdir(path string) (err Error)
-//sys	Bind(name string, old string, flag int) (err Error)
-//sys	Mount(fd int, afd int, old string, flag int, aname string) (err Error)
-//sys	Stat(path string, edir []byte) (n int, err Error)
-//sys	Fstat(fd int, edir []byte) (n int, err Error)
-//sys	Wstat(path string, edir []byte) (err Error)
-//sys	Fwstat(fd int, edir []byte) (err Error)
+//sys	Dup(oldfd int, newfd int) (fd int, err error)
+//sys	Open(path string, mode int) (fd int, err error)
+//sys	Create(path string, mode int, perm uint32) (fd int, err error)
+//sys	Remove(path string) (err error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys	Close(fd int) (err error)
+//sys	Chdir(path string) (err error)
+//sys	Bind(name string, old string, flag int) (err error)
+//sys	Mount(fd int, afd int, old string, flag int, aname string) (err error)
+//sys	Stat(path string, edir []byte) (n int, err error)
+//sys	Fstat(fd int, edir []byte) (n int, err error)
+//sys	Wstat(path string, edir []byte) (err error)
+//sys	Fwstat(fd int, edir []byte) (err error)
diff --git a/src/pkg/syscall/syscall_unix.go b/src/pkg/syscall/syscall_unix.go
index 1590b6d..cc1e4f7 100644
--- a/src/pkg/syscall/syscall_unix.go
+++ b/src/pkg/syscall/syscall_unix.go
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package syscall
 
 import (
+	"runtime"
 	"sync"
 	"unsafe"
 )
@@ -17,37 +18,30 @@ var (
 	Stderr = 2
 )
 
-const darwinAMD64 = OS == "darwin" && ARCH == "amd64"
+const darwinAMD64 = runtime.GOOS == "darwin" && runtime.GOARCH == "amd64"
 
-func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
-func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
-func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
-func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
-
-func Errstr(errno int) string {
-	if errno < 0 || errno >= int(len(errors)) {
-		return "error " + itoa(errno)
-	}
-	return errors[errno]
-}
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
 
 // Mmap manager, for use by operating system-specific implementations.
 
 type mmapper struct {
 	sync.Mutex
 	active map[*byte][]byte // active mappings; key is last byte in mapping
-	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, int)
-	munmap func(addr uintptr, length uintptr) int
+	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
+	munmap func(addr uintptr, length uintptr) error
 }
 
-func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
 	if length <= 0 {
 		return nil, EINVAL
 	}
 
 	// Map the requested memory.
 	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
-	if errno != 0 {
+	if errno != nil {
 		return nil, errno
 	}
 
@@ -66,10 +60,10 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d
 	m.Lock()
 	defer m.Unlock()
 	m.active[p] = b
-	return b, 0
+	return b, nil
 }
 
-func (m *mmapper) Munmap(data []byte) (errno int) {
+func (m *mmapper) Munmap(data []byte) (err error) {
 	if len(data) == 0 || len(data) != cap(data) {
 		return EINVAL
 	}
@@ -84,9 +78,36 @@ func (m *mmapper) Munmap(data []byte) (errno int) {
 	}
 
 	// Unmap the memory and update m.
-	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != 0 {
+	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
 		return errno
 	}
-	m.active[p] = nil, false
-	return 0
+	delete(m.active, p)
+	return nil
+}
+
+// An Errno is an unsigned number describing an error condition.
+// It implements the error interface.  The zero Errno is by convention
+// a non-error, so code to convert from Errno to error should use:
+//	err = nil
+//	if errno != 0 {
+//		err = errno
+//	}
+type Errno uintptr
+
+func (e Errno) Error() string {
+	if 0 <= e && int(e) < len(errors) {
+		s := errors[e]
+		if s != "" {
+			return s
+		}
+	}
+	return "errno " + itoa(int(e))
+}
+
+func (e Errno) Temporary() bool {
+	return e == EINTR || e == EMFILE || e.Timeout()
+}
+
+func (e Errno) Timeout() bool {
+	return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
 }
diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go
index 26939cc..45e2994 100644
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -7,13 +7,10 @@
 package syscall
 
 import (
-	"sync"
+	"unicode/utf16"
 	"unsafe"
-	"utf16"
 )
 
-const OS = "windows"
-
 type Handle uintptr
 
 const InvalidHandle = ^Handle(0)
@@ -28,8 +25,8 @@ import (
 	"syscall"
 )
 
-func abort(funcname string, err int) {
-	panic(funcname + " failed: " + syscall.Errstr(err))
+func abort(funcname string, err error) {
+	panic(funcname + " failed: " + err.Error())
 }
 
 func print_version(v uint32) {
@@ -41,12 +38,12 @@ func print_version(v uint32) {
 
 func main() {
 	h, err := syscall.LoadLibrary("kernel32.dll")
-	if err != 0 {
+	if err != nil {
 		abort("LoadLibrary", err)
 	}
 	defer syscall.FreeLibrary(h)
 	proc, err := syscall.GetProcAddress(h, "GetVersion")
-	if err != 0 {
+	if err != nil {
 		abort("GetProcAddress", err)
 	}
 	r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0)
@@ -57,7 +54,7 @@ func main() {
 
 // StringToUTF16 returns the UTF-16 encoding of the UTF-8 string s,
 // with a terminating NUL added.
-func StringToUTF16(s string) []uint16 { return utf16.Encode([]int(s + "\x00")) }
+func StringToUTF16(s string) []uint16 { return utf16.Encode([]rune(s + "\x00")) }
 
 // UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
 // with a terminating NUL removed.
@@ -75,78 +72,38 @@ func UTF16ToString(s []uint16) string {
 // the UTF-8 string s, with a terminating NUL added.
 func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] }
 
-// dll helpers
+func Getpagesize() int { return 4096 }
 
-// Implemented in ../runtime/windows/syscall.goc
-func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr)
-func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
-func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr)
-func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr)
-func loadlibraryex(filename uintptr) (handle uintptr)
-func getprocaddress(handle uintptr, procname uintptr) (proc uintptr)
-
-// A LazyDLL implements access to a single DLL.
-// It will delay the load of the DLL until the first
-// call to its Handle method or to one of its
-// LazyProc's Addr method.
-type LazyDLL struct {
-	mu   sync.Mutex
-	Name string
-	h    uintptr // module handle once dll is loaded
-}
-
-// Handle returns d's module handle.
-func (d *LazyDLL) Handle() uintptr {
-	if d.h == 0 {
-		d.mu.Lock()
-		defer d.mu.Unlock()
-		if d.h == 0 {
-			d.h = loadlibraryex(uintptr(unsafe.Pointer(StringBytePtr(d.Name))))
-			if d.h == 0 {
-				panic("syscall: could not LoadLibraryEx " + d.Name)
-			}
-		}
-	}
-	return d.h
-}
+// Errno is the Windows error number.
+type Errno uintptr
 
-// NewProc returns a LazyProc for accessing the named procedure in the DLL d.
-func (d *LazyDLL) NewProc(name string) *LazyProc {
-	return &LazyProc{dll: d, Name: name}
+func (e Errno) Error() string {
+	// deal with special go errors
+	idx := int(e - APPLICATION_ERROR)
+	if 0 <= idx && idx < len(errors) {
+		return errors[idx]
+	}
+	// ask windows for the remaining errors
+	var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
+	b := make([]uint16, 300)
+	n, err := FormatMessage(flags, 0, uint32(e), 0, b, nil)
+	if err != nil {
+		return "error " + itoa(int(e)) + " (FormatMessage failed with err=" + itoa(int(err.(Errno))) + ")"
+	}
+	// trim terminating \r and \n
+	for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
+	}
+	return string(utf16.Decode(b[:n]))
 }
 
-// NewLazyDLL creates new LazyDLL associated with dll file.
-func NewLazyDLL(name string) *LazyDLL {
-	return &LazyDLL{Name: name}
+func (e Errno) Temporary() bool {
+	return e == EINTR || e == EMFILE || e.Timeout()
 }
 
-// A LazyProc implements access to a procedure inside a LazyDLL.
-// It delays the lookup until the Addr method is called.
-type LazyProc struct {
-	mu   sync.Mutex
-	Name string
-	dll  *LazyDLL
-	addr uintptr
-}
-
-// Addr returns the address of the procedure represented by s.
-// The return value can be passed to Syscall to run the procedure.
-func (s *LazyProc) Addr() uintptr {
-	if s.addr == 0 {
-		s.mu.Lock()
-		defer s.mu.Unlock()
-		if s.addr == 0 {
-			s.addr = getprocaddress(s.dll.Handle(), uintptr(unsafe.Pointer(StringBytePtr(s.Name))))
-			if s.addr == 0 {
-				panic("syscall: could not GetProcAddress for " + s.Name)
-			}
-		}
-	}
-	return s.addr
+func (e Errno) Timeout() bool {
+	return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
 }
 
-func Getpagesize() int { return 4096 }
-
 // Converts a Go function to a function pointer conforming
 // to the stdcall calling convention.  This is useful when
 // interoperating with Windows code requiring callbacks.
@@ -155,94 +112,84 @@ func NewCallback(fn interface{}) uintptr
 
 // windows api calls
 
-//sys	GetLastError() (lasterrno int)
-//sys	LoadLibrary(libname string) (handle Handle, errno int) = LoadLibraryW
-//sys	FreeLibrary(handle Handle) (errno int)
-//sys	GetProcAddress(module Handle, procname string) (proc uintptr, errno int)
-//sys	GetVersion() (ver uint32, errno int)
-//sys	FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, errno int) = FormatMessageW
+//sys	GetLastError() (lasterr error)
+//sys	LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW
+//sys	FreeLibrary(handle Handle) (err error)
+//sys	GetProcAddress(module Handle, procname string) (proc uintptr, err error)
+//sys	GetVersion() (ver uint32, err error)
+//sys	FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
 //sys	ExitProcess(exitcode uint32)
-//sys	CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, errno int) [failretval==InvalidHandle] = CreateFileW
-//sys	ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (errno int)
-//sys	WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (errno int)
-//sys	SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, errno int) [failretval==0xffffffff]
-//sys	CloseHandle(handle Handle) (errno int)
-//sys	GetStdHandle(stdhandle int) (handle Handle, errno int) [failretval==InvalidHandle]
-//sys	FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, errno int) [failretval==InvalidHandle] = FindFirstFileW
-//sys	FindNextFile(handle Handle, data *Win32finddata) (errno int) = FindNextFileW
-//sys	FindClose(handle Handle) (errno int)
-//sys	GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (errno int)
-//sys	GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, errno int) = GetCurrentDirectoryW
-//sys	SetCurrentDirectory(path *uint16) (errno int) = SetCurrentDirectoryW
-//sys	CreateDirectory(path *uint16, sa *SecurityAttributes) (errno int) = CreateDirectoryW
-//sys	RemoveDirectory(path *uint16) (errno int) = RemoveDirectoryW
-//sys	DeleteFile(path *uint16) (errno int) = DeleteFileW
-//sys	MoveFile(from *uint16, to *uint16) (errno int) = MoveFileW
-//sys	GetComputerName(buf *uint16, n *uint32) (errno int) = GetComputerNameW
-//sys	SetEndOfFile(handle Handle) (errno int)
+//sys	CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
+//sys	ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
+//sys	WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
+//sys	SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
+//sys	CloseHandle(handle Handle) (err error)
+//sys	GetStdHandle(stdhandle int) (handle Handle, err error) [failretval==InvalidHandle]
+//sys	FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW
+//sys	FindNextFile(handle Handle, data *Win32finddata) (err error) = FindNextFileW
+//sys	FindClose(handle Handle) (err error)
+//sys	GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error)
+//sys	GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW
+//sys	SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW
+//sys	CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW
+//sys	RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW
+//sys	DeleteFile(path *uint16) (err error) = DeleteFileW
+//sys	MoveFile(from *uint16, to *uint16) (err error) = MoveFileW
+//sys	GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
+//sys	SetEndOfFile(handle Handle) (err error)
 //sys	GetSystemTimeAsFileTime(time *Filetime)
-//sys	sleep(msec uint32) = Sleep
-//sys	GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, errno int) [failretval==0xffffffff]
-//sys	CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, errno int)
-//sys	GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (errno int)
-//sys	CancelIo(s Handle) (errno int)
-//sys	CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (errno int) = CreateProcessW
-//sys	OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, errno int)
-//sys	TerminateProcess(handle Handle, exitcode uint32) (errno int)
-//sys	GetExitCodeProcess(handle Handle, exitcode *uint32) (errno int)
-//sys	GetStartupInfo(startupInfo *StartupInfo) (errno int) = GetStartupInfoW
-//sys	GetCurrentProcess() (pseudoHandle Handle, errno int)
-//sys	DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (errno int)
-//sys	WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, errno int) [failretval==0xffffffff]
-//sys	GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) = GetTempPathW
-//sys	CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (errno int)
-//sys	GetFileType(filehandle Handle) (n uint32, errno int)
-//sys	CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (errno int) = advapi32.CryptAcquireContextW
-//sys	CryptReleaseContext(provhandle Handle, flags uint32) (errno int) = advapi32.CryptReleaseContext
-//sys	CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (errno int) = advapi32.CryptGenRandom
-//sys	GetEnvironmentStrings() (envs *uint16, errno int) [failretval==nil] = kernel32.GetEnvironmentStringsW
-//sys	FreeEnvironmentStrings(envs *uint16) (errno int) = kernel32.FreeEnvironmentStringsW
-//sys	GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) = kernel32.GetEnvironmentVariableW
-//sys	SetEnvironmentVariable(name *uint16, value *uint16) (errno int) = kernel32.SetEnvironmentVariableW
-//sys	SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (errno int)
-//sys	GetFileAttributes(name *uint16) (attrs uint32, errno int) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
-//sys	SetFileAttributes(name *uint16, attrs uint32) (errno int) = kernel32.SetFileAttributesW
-//sys	GetFileAttributesEx(name *uint16, level uint32, info *byte) (errno int) = kernel32.GetFileAttributesExW
+//sys	GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff]
+//sys	CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error)
+//sys	GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error)
+//sys	PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error)
+//sys	CancelIo(s Handle) (err error)
+//sys	CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW
+//sys	OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error)
+//sys	TerminateProcess(handle Handle, exitcode uint32) (err error)
+//sys	GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
+//sys	GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW
+//sys	GetCurrentProcess() (pseudoHandle Handle, err error)
+//sys	DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error)
+//sys	WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff]
+//sys	GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW
+//sys	CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error)
+//sys	GetFileType(filehandle Handle) (n uint32, err error)
+//sys	CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW
+//sys	CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext
+//sys	CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom
+//sys	GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW
+//sys	FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW
+//sys	GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW
+//sys	SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW
+//sys	SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error)
+//sys	GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
+//sys	SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW
+//sys	GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW
 //sys	GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
-//sys	CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, errno int) [failretval==nil] = shell32.CommandLineToArgvW
-//sys	LocalFree(hmem Handle) (handle Handle, errno int) [failretval!=0]
-//sys	SetHandleInformation(handle Handle, mask uint32, flags uint32) (errno int)
-//sys	FlushFileBuffers(handle Handle) (errno int)
-//sys	GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, errno int) = kernel32.GetFullPathNameW
-//sys	CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, errno int) = kernel32.CreateFileMappingW
-//sys	MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, errno int)
-//sys	UnmapViewOfFile(addr uintptr) (errno int)
-//sys	FlushViewOfFile(addr uintptr, length uintptr) (errno int)
-//sys	VirtualLock(addr uintptr, length uintptr) (errno int)
-//sys	VirtualUnlock(addr uintptr, length uintptr) (errno int)
-//sys	TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (errno int) = mswsock.TransmitFile
+//sys	CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
+//sys	LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0]
+//sys	SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)
+//sys	FlushFileBuffers(handle Handle) (err error)
+//sys	GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW
+//sys	CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW
+//sys	MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error)
+//sys	UnmapViewOfFile(addr uintptr) (err error)
+//sys	FlushViewOfFile(addr uintptr, length uintptr) (err error)
+//sys	VirtualLock(addr uintptr, length uintptr) (err error)
+//sys	VirtualUnlock(addr uintptr, length uintptr) (err error)
+//sys	TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile
+//sys	ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW
+//sys	CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW
+//sys	CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore
+//sys	CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore
+//sys	RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW
+//sys	RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey
+//sys	RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW
+//sys	RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
+//sys	RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW
 
 // syscall interface implementation for other packages
 
-func Errstr(errno int) string {
-	// deal with special go errors
-	e := errno - APPLICATION_ERROR
-	if 0 <= e && e < len(errors) {
-		return errors[e]
-	}
-	// ask windows for the remaining errors
-	var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
-	b := make([]uint16, 300)
-	n, err := FormatMessage(flags, 0, uint32(errno), 0, b, nil)
-	if err != 0 {
-		return "error " + itoa(errno) + " (FormatMessage failed with err=" + itoa(err) + ")"
-	}
-	// trim terminating \r and \n
-	for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
-	}
-	return string(utf16.Decode(b[:n]))
-}
-
 func Exit(code int) { ExitProcess(uint32(code)) }
 
 func makeInheritSa() *SecurityAttributes {
@@ -252,7 +199,7 @@ func makeInheritSa() *SecurityAttributes {
 	return &sa
 }
 
-func Open(path string, mode int, perm uint32) (fd Handle, errno int) {
+func Open(path string, mode int, perm uint32) (fd Handle, err error) {
 	if len(path) == 0 {
 		return InvalidHandle, ERROR_FILE_NOT_FOUND
 	}
@@ -291,32 +238,32 @@ func Open(path string, mode int, perm uint32) (fd Handle, errno int) {
 		createmode = OPEN_EXISTING
 	}
 	h, e := CreateFile(StringToUTF16Ptr(path), access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0)
-	return h, int(e)
+	return h, e
 }
 
-func Read(fd Handle, p []byte) (n int, errno int) {
+func Read(fd Handle, p []byte) (n int, err error) {
 	var done uint32
 	e := ReadFile(fd, p, &done, nil)
-	if e != 0 {
+	if e != nil {
 		if e == ERROR_BROKEN_PIPE {
 			// NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin
-			return 0, 0
+			return 0, nil
 		}
 		return 0, e
 	}
-	return int(done), 0
+	return int(done), nil
 }
 
-func Write(fd Handle, p []byte) (n int, errno int) {
+func Write(fd Handle, p []byte) (n int, err error) {
 	var done uint32
 	e := WriteFile(fd, p, &done, nil)
-	if e != 0 {
+	if e != nil {
 		return 0, e
 	}
-	return int(done), 0
+	return int(done), nil
 }
 
-func Seek(fd Handle, offset int64, whence int) (newoffset int64, errno int) {
+func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
 	var w uint32
 	switch whence {
 	case 0:
@@ -334,13 +281,13 @@ func Seek(fd Handle, offset int64, whence int) (newoffset int64, errno int) {
 		return 0, EPIPE
 	}
 	rlo, e := SetFilePointer(fd, lo, &hi, w)
-	if e != 0 {
+	if e != nil {
 		return 0, e
 	}
-	return int64(hi)<<32 + int64(rlo), 0
+	return int64(hi)<<32 + int64(rlo), nil
 }
 
-func Close(fd Handle) (errno int) {
+func Close(fd Handle) (err error) {
 	return CloseHandle(fd)
 }
 
@@ -352,103 +299,99 @@ var (
 
 func getStdHandle(h int) (fd Handle) {
 	r, _ := GetStdHandle(h)
+	CloseOnExec(r)
 	return r
 }
 
 const ImplementsGetwd = true
 
-func Getwd() (wd string, errno int) {
+func Getwd() (wd string, err error) {
 	b := make([]uint16, 300)
 	n, e := GetCurrentDirectory(uint32(len(b)), &b[0])
-	if e != 0 {
+	if e != nil {
 		return "", e
 	}
-	return string(utf16.Decode(b[0:n])), 0
+	return string(utf16.Decode(b[0:n])), nil
 }
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	return SetCurrentDirectory(&StringToUTF16(path)[0])
 }
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	return CreateDirectory(&StringToUTF16(path)[0], nil)
 }
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	return RemoveDirectory(&StringToUTF16(path)[0])
 }
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	return DeleteFile(&StringToUTF16(path)[0])
 }
 
-func Rename(oldpath, newpath string) (errno int) {
+func Rename(oldpath, newpath string) (err error) {
 	from := &StringToUTF16(oldpath)[0]
 	to := &StringToUTF16(newpath)[0]
 	return MoveFile(from, to)
 }
 
-func ComputerName() (name string, errno int) {
+func ComputerName() (name string, err error) {
 	var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
 	b := make([]uint16, n)
 	e := GetComputerName(&b[0], &n)
-	if e != 0 {
+	if e != nil {
 		return "", e
 	}
-	return string(utf16.Decode(b[0:n])), 0
+	return string(utf16.Decode(b[0:n])), nil
 }
 
-func Ftruncate(fd Handle, length int64) (errno int) {
+func Ftruncate(fd Handle, length int64) (err error) {
 	curoffset, e := Seek(fd, 0, 1)
-	if e != 0 {
+	if e != nil {
 		return e
 	}
 	defer Seek(fd, curoffset, 0)
 	_, e = Seek(fd, length, 0)
-	if e != 0 {
+	if e != nil {
 		return e
 	}
 	e = SetEndOfFile(fd)
-	if e != 0 {
+	if e != nil {
 		return e
 	}
-	return 0
+	return nil
 }
 
-func Gettimeofday(tv *Timeval) (errno int) {
+func Gettimeofday(tv *Timeval) (err error) {
 	var ft Filetime
 	GetSystemTimeAsFileTime(&ft)
 	*tv = NsecToTimeval(ft.Nanoseconds())
-	return 0
-}
-
-func Sleep(nsec int64) (errno int) {
-	sleep(uint32((nsec + 1e6 - 1) / 1e6)) // round up to milliseconds
-	return 0
+	return nil
 }
 
-func Pipe(p []Handle) (errno int) {
+func Pipe(p []Handle) (err error) {
 	if len(p) != 2 {
 		return EINVAL
 	}
 	var r, w Handle
 	e := CreatePipe(&r, &w, makeInheritSa(), 0)
-	if e != 0 {
+	if e != nil {
 		return e
 	}
 	p[0] = r
 	p[1] = w
-	return 0
+	return nil
 }
 
-func Utimes(path string, tv []Timeval) (errno int) {
+func Utimes(path string, tv []Timeval) (err error) {
 	if len(tv) != 2 {
 		return EINVAL
 	}
 	h, e := CreateFile(StringToUTF16Ptr(path),
 		FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
 		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
-	if e != 0 {
+	if e != nil {
 		return e
 	}
 	defer Close(h)
@@ -457,17 +400,17 @@ func Utimes(path string, tv []Timeval) (errno int) {
 	return SetFileTime(h, nil, &a, &w)
 }
 
-func Fsync(fd Handle) (errno int) {
+func Fsync(fd Handle) (err error) {
 	return FlushFileBuffers(fd)
 }
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	if mode == 0 {
 		return EINVAL
 	}
 	p := StringToUTF16Ptr(path)
 	attrs, e := GetFileAttributes(p)
-	if e != 0 {
+	if e != nil {
 		return e
 	}
 	if mode&S_IWRITE != 0 {
@@ -480,31 +423,32 @@ func Chmod(path string, mode uint32) (errno int) {
 
 // net api calls
 
-//sys	WSAStartup(verreq uint32, data *WSAData) (sockerrno int) = ws2_32.WSAStartup
-//sys	WSACleanup() (errno int) [failretval==-1] = ws2_32.WSACleanup
-//sys	WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (errno int) [failretval==-1] = ws2_32.WSAIoctl
-//sys	socket(af int32, typ int32, protocol int32) (handle Handle, errno int) [failretval==InvalidHandle] = ws2_32.socket
-//sys	Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (errno int) [failretval==-1] = ws2_32.setsockopt
-//sys	bind(s Handle, name uintptr, namelen int32) (errno int) [failretval==-1] = ws2_32.bind
-//sys	connect(s Handle, name uintptr, namelen int32) (errno int) [failretval==-1] = ws2_32.connect
-//sys	getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (errno int) [failretval==-1] = ws2_32.getsockname
-//sys	getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (errno int) [failretval==-1] = ws2_32.getpeername
-//sys	listen(s Handle, backlog int32) (errno int) [failretval==-1] = ws2_32.listen
-//sys	shutdown(s Handle, how int32) (errno int) [failretval==-1] = ws2_32.shutdown
-//sys	Closesocket(s Handle) (errno int) [failretval==-1] = ws2_32.closesocket
-//sys	AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (errno int) = mswsock.AcceptEx
+//sys	WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup
+//sys	WSACleanup() (err error) [failretval==-1] = ws2_32.WSACleanup
+//sys	WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==-1] = ws2_32.WSAIoctl
+//sys	socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket
+//sys	Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==-1] = ws2_32.setsockopt
+//sys	bind(s Handle, name uintptr, namelen int32) (err error) [failretval==-1] = ws2_32.bind
+//sys	connect(s Handle, name uintptr, namelen int32) (err error) [failretval==-1] = ws2_32.connect
+//sys	getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==-1] = ws2_32.getsockname
+//sys	getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==-1] = ws2_32.getpeername
+//sys	listen(s Handle, backlog int32) (err error) [failretval==-1] = ws2_32.listen
+//sys	shutdown(s Handle, how int32) (err error) [failretval==-1] = ws2_32.shutdown
+//sys	Closesocket(s Handle) (err error) [failretval==-1] = ws2_32.closesocket
+//sys	AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx
 //sys	GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs
-//sys	WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (errno int) [failretval==-1] = ws2_32.WSARecv
-//sys	WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (errno int) [failretval==-1] = ws2_32.WSASend
-//sys	WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32,  from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (errno int) [failretval==-1] = ws2_32.WSARecvFrom
-//sys	WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32,  overlapped *Overlapped, croutine *byte) (errno int) [failretval==-1] = ws2_32.WSASendTo
-//sys	GetHostByName(name string) (h *Hostent, errno int) [failretval==nil] = ws2_32.gethostbyname
-//sys	GetServByName(name string, proto string) (s *Servent, errno int) [failretval==nil] = ws2_32.getservbyname
+//sys	WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==-1] = ws2_32.WSARecv
+//sys	WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==-1] = ws2_32.WSASend
+//sys	WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32,  from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==-1] = ws2_32.WSARecvFrom
+//sys	WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32,  overlapped *Overlapped, croutine *byte) (err error) [failretval==-1] = ws2_32.WSASendTo
+//sys	GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname
+//sys	GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname
 //sys	Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs
-//sys	DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status uint32) = dnsapi.DnsQuery_W
+//sys	GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname
+//sys	DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W
 //sys	DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree
-//sys	GetIfEntry(pIfRow *MibIfRow) (errcode int) = iphlpapi.GetIfEntry
-//sys	GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode int) = iphlpapi.GetAdaptersInfo
+//sys	GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry
+//sys	GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo
 
 // For testing: clients can set this flag to force
 // creation of IPv6 sockets to return EAFNOSUPPORT.
@@ -528,7 +472,7 @@ type RawSockaddrAny struct {
 }
 
 type Sockaddr interface {
-	sockaddr() (ptr uintptr, len int32, errno int) // lowercase; only we can define Sockaddrs
+	sockaddr() (ptr uintptr, len int32, err error) // lowercase; only we can define Sockaddrs
 }
 
 type SockaddrInet4 struct {
@@ -537,7 +481,7 @@ type SockaddrInet4 struct {
 	raw  RawSockaddrInet4
 }
 
-func (sa *SockaddrInet4) sockaddr() (uintptr, int32, int) {
+func (sa *SockaddrInet4) sockaddr() (uintptr, int32, error) {
 	if sa.Port < 0 || sa.Port > 0xFFFF {
 		return 0, 0, EINVAL
 	}
@@ -548,7 +492,7 @@ func (sa *SockaddrInet4) sockaddr() (uintptr, int32, int) {
 	for i := 0; i < len(sa.Addr); i++ {
 		sa.raw.Addr[i] = sa.Addr[i]
 	}
-	return uintptr(unsafe.Pointer(&sa.raw)), int32(unsafe.Sizeof(sa.raw)), 0
+	return uintptr(unsafe.Pointer(&sa.raw)), int32(unsafe.Sizeof(sa.raw)), nil
 }
 
 type SockaddrInet6 struct {
@@ -557,7 +501,7 @@ type SockaddrInet6 struct {
 	Addr   [16]byte
 }
 
-func (sa *SockaddrInet6) sockaddr() (uintptr, int32, int) {
+func (sa *SockaddrInet6) sockaddr() (uintptr, int32, error) {
 	// TODO(brainman): implement SockaddrInet6.sockaddr()
 	return 0, 0, EWINDOWS
 }
@@ -566,12 +510,12 @@ type SockaddrUnix struct {
 	Name string
 }
 
-func (sa *SockaddrUnix) sockaddr() (uintptr, int32, int) {
+func (sa *SockaddrUnix) sockaddr() (uintptr, int32, error) {
 	// TODO(brainman): implement SockaddrUnix.sockaddr()
 	return 0, 0, EWINDOWS
 }
 
-func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, int) {
+func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
 	switch rsa.Addr.Family {
 	case AF_UNIX:
 		return nil, EWINDOWS
@@ -584,7 +528,7 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, int) {
 		for i := 0; i < len(sa.Addr); i++ {
 			sa.Addr[i] = pp.Addr[i]
 		}
-		return sa, 0
+		return sa, nil
 
 	case AF_INET6:
 		return nil, EWINDOWS
@@ -592,68 +536,66 @@ func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, int) {
 	return nil, EAFNOSUPPORT
 }
 
-func Socket(domain, typ, proto int) (fd Handle, errno int) {
+func Socket(domain, typ, proto int) (fd Handle, err error) {
 	if domain == AF_INET6 && SocketDisableIPv6 {
 		return InvalidHandle, EAFNOSUPPORT
 	}
-	h, e := socket(int32(domain), int32(typ), int32(proto))
-	return h, int(e)
+	return socket(int32(domain), int32(typ), int32(proto))
 }
 
-func SetsockoptInt(fd Handle, level, opt int, value int) (errno int) {
+func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
 	v := int32(value)
-	return int(Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v))))
+	return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
 }
 
-func Bind(fd Handle, sa Sockaddr) (errno int) {
+func Bind(fd Handle, sa Sockaddr) (err error) {
 	ptr, n, err := sa.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	return bind(fd, ptr, n)
 }
 
-func Connect(fd Handle, sa Sockaddr) (errno int) {
+func Connect(fd Handle, sa Sockaddr) (err error) {
 	ptr, n, err := sa.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
 	return connect(fd, ptr, n)
 }
 
-func Getsockname(fd Handle) (sa Sockaddr, errno int) {
+func Getsockname(fd Handle) (sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	l := int32(unsafe.Sizeof(rsa))
-	if errno = getsockname(fd, &rsa, &l); errno != 0 {
+	if err = getsockname(fd, &rsa, &l); err != nil {
 		return
 	}
 	return rsa.Sockaddr()
 }
 
-func Getpeername(fd Handle) (sa Sockaddr, errno int) {
+func Getpeername(fd Handle) (sa Sockaddr, err error) {
 	var rsa RawSockaddrAny
 	l := int32(unsafe.Sizeof(rsa))
-	if errno = getpeername(fd, &rsa, &l); errno != 0 {
+	if err = getpeername(fd, &rsa, &l); err != nil {
 		return
 	}
 	return rsa.Sockaddr()
 }
 
-func Listen(s Handle, n int) (errno int) {
-	return int(listen(s, int32(n)))
+func Listen(s Handle, n int) (err error) {
+	return listen(s, int32(n))
 }
 
-func Shutdown(fd Handle, how int) (errno int) {
-	return int(shutdown(fd, int32(how)))
+func Shutdown(fd Handle, how int) (err error) {
+	return shutdown(fd, int32(how))
 }
 
-func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
 	rsa, l, err := to.sockaddr()
-	if err != 0 {
+	if err != nil {
 		return err
 	}
-	errno = WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine)
-	return
+	return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine)
 }
 
 // Invented structures to support what package os expects.
@@ -682,25 +624,27 @@ func (w WaitStatus) Signaled() bool { return false }
 
 func (w WaitStatus) TrapCause() int { return -1 }
 
+// Timespec is an invented structure on Windows, but here for
+// consistency with the syscall package for other operating systems.
+type Timespec struct {
+	Sec  int64
+	Nsec int64
+}
+
 // TODO(brainman): fix all needed for net
 
-func Accept(fd Handle) (nfd Handle, sa Sockaddr, errno int) { return 0, nil, EWINDOWS }
-func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, errno int) {
+func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }
+func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
 	return 0, nil, EWINDOWS
 }
-func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (errno int)       { return EWINDOWS }
-func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (errno int) { return EWINDOWS }
+func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error)       { return EWINDOWS }
+func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS }
 
 type Linger struct {
 	Onoff  int32
 	Linger int32
 }
 
-const (
-	IP_ADD_MEMBERSHIP  = 0xc
-	IP_DROP_MEMBERSHIP = 0xd
-)
-
 type IPMreq struct {
 	Multiaddr [4]byte /* in_addr */
 	Interface [4]byte /* in_addr */
@@ -711,30 +655,30 @@ type IPv6Mreq struct {
 	Interface uint32
 }
 
-func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (errno int) { return EWINDOWS }
-func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (errno int) {
+func GetsockoptInt(fd Handle, level, opt int) (int, error)              { return -1, EWINDOWS }
+func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { return EWINDOWS }
+func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
 	return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
 }
-func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (errno int) { return EWINDOWS }
-func BindToDevice(fd Handle, device string) (errno int)                        { return EWINDOWS }
+func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS }
 
 // TODO(brainman): fix all needed for os
 
 func Getpid() (pid int)   { return -1 }
 func Getppid() (ppid int) { return -1 }
 
-func Fchdir(fd Handle) (errno int)                        { return EWINDOWS }
-func Link(oldpath, newpath string) (errno int)            { return EWINDOWS }
-func Symlink(path, link string) (errno int)               { return EWINDOWS }
-func Readlink(path string, buf []byte) (n int, errno int) { return 0, EWINDOWS }
+func Fchdir(fd Handle) (err error)                        { return EWINDOWS }
+func Link(oldpath, newpath string) (err error)            { return EWINDOWS }
+func Symlink(path, link string) (err error)               { return EWINDOWS }
+func Readlink(path string, buf []byte) (n int, err error) { return 0, EWINDOWS }
 
-func Fchmod(fd Handle, mode uint32) (errno int)        { return EWINDOWS }
-func Chown(path string, uid int, gid int) (errno int)  { return EWINDOWS }
-func Lchown(path string, uid int, gid int) (errno int) { return EWINDOWS }
-func Fchown(fd Handle, uid int, gid int) (errno int)   { return EWINDOWS }
+func Fchmod(fd Handle, mode uint32) (err error)        { return EWINDOWS }
+func Chown(path string, uid int, gid int) (err error)  { return EWINDOWS }
+func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS }
+func Fchown(fd Handle, uid int, gid int) (err error)   { return EWINDOWS }
 
 func Getuid() (uid int)                  { return -1 }
 func Geteuid() (euid int)                { return -1 }
 func Getgid() (gid int)                  { return -1 }
 func Getegid() (egid int)                { return -1 }
-func Getgroups() (gids []int, errno int) { return nil, EWINDOWS }
+func Getgroups() (gids []int, err error) { return nil, EWINDOWS }
diff --git a/src/pkg/syscall/types_darwin.c b/src/pkg/syscall/types_darwin.c
deleted file mode 100644
index 730d7f7..0000000
--- a/src/pkg/syscall/types_darwin.c
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Input to godefs.  See also mkerrors.sh and mkall.sh
- */
-
-#define __DARWIN_UNIX03 0
-#define KERNEL
-#define _DARWIN_USE_64_BIT_INODE
-#include <dirent.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <unistd.h>
-#include <mach/mach.h>
-#include <mach/message.h>
-#include <sys/event.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/param.h>
-#include <sys/ptrace.h>
-#include <sys/resource.h>
-#include <sys/select.h>
-#include <sys/signal.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <net/bpf.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_var.h>
-#include <net/route.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-// Machine characteristics; for internal use.
-
-enum {
-	$sizeofPtr = sizeof(void*),
-	$sizeofShort = sizeof(short),
-	$sizeofInt = sizeof(int),
-	$sizeofLong = sizeof(long),
-	$sizeofLongLong = sizeof(long long),
-};
-
-// Basic types
-
-typedef short $_C_short;
-typedef int $_C_int;
-typedef long $_C_long;
-typedef long long $_C_long_long;
-
-// Time
-
-typedef struct timespec $Timespec;
-typedef struct timeval $Timeval;
-typedef struct timeval32 $Timeval32;
-
-// Processes
-
-typedef struct rusage $Rusage;
-typedef struct rlimit $Rlimit;
-
-typedef gid_t $_Gid_t;
-
-// Files
-
-enum {
-	$O_CLOEXEC = 0,	// not supported
-};
-
-typedef struct stat64 $Stat_t;
-typedef struct statfs64 $Statfs_t;
-typedef struct flock $Flock_t;
-typedef struct fstore $Fstore_t;
-typedef struct radvisory $Radvisory_t;
-typedef struct fbootstraptransfer $Fbootstraptransfer_t;
-typedef struct log2phys $Log2phys_t;
-
-typedef struct dirent $Dirent;
-
-// Sockets
-
-union sockaddr_all {
-	struct sockaddr s1;	// this one gets used for fields
-	struct sockaddr_in s2;	// these pad it out
-	struct sockaddr_in6 s3;
-	struct sockaddr_un s4;
-	struct sockaddr_dl s5;
-};
-
-struct sockaddr_any {
-	struct sockaddr addr;
-	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
-};
-
-typedef struct sockaddr_in $RawSockaddrInet4;
-typedef struct sockaddr_in6 $RawSockaddrInet6;
-typedef struct sockaddr_un $RawSockaddrUnix;
-typedef struct sockaddr_dl $RawSockaddrDatalink;
-typedef struct sockaddr $RawSockaddr;
-typedef struct sockaddr_any $RawSockaddrAny;
-typedef socklen_t $_Socklen;
-typedef struct linger $Linger;
-typedef struct iovec $Iovec;
-typedef struct ip_mreq $IPMreq;
-typedef struct ipv6_mreq $IPv6Mreq;
-typedef struct msghdr $Msghdr;
-typedef struct cmsghdr $Cmsghdr;
-typedef struct in6_pktinfo $Inet6Pktinfo;
-
-enum {
-	$SizeofSockaddrInet4 = sizeof(struct sockaddr_in),
-	$SizeofSockaddrInet6 = sizeof(struct sockaddr_in6),
-	$SizeofSockaddrAny = sizeof(struct sockaddr_any),
-	$SizeofSockaddrUnix = sizeof(struct sockaddr_un),
-	$SizeofSockaddrDatalink = sizeof(struct sockaddr_dl),
-	$SizeofLinger = sizeof(struct linger),
-	$SizeofIPMreq = sizeof(struct ip_mreq),
-	$SizeofIPv6Mreq = sizeof(struct ipv6_mreq),
-	$SizeofMsghdr = sizeof(struct msghdr),
-	$SizeofCmsghdr = sizeof(struct cmsghdr),
-	$SizeofInet6Pktinfo = sizeof(struct in6_pktinfo),
-};
-
-// Ptrace requests
-
-enum {
-	$PTRACE_TRACEME = PT_TRACE_ME,
-	$PTRACE_CONT = PT_CONTINUE,
-	$PTRACE_KILL = PT_KILL,
-};
-
-// Events (kqueue, kevent)
-
-typedef struct kevent $Kevent_t;
-
-// Select
-
-typedef fd_set $FdSet;
-
-// Routing and interface messages
-
-enum {
-	$SizeofIfMsghdr = sizeof(struct if_msghdr),
-	$SizeofIfData = sizeof(struct if_data),
-	$SizeofIfaMsghdr = sizeof(struct ifa_msghdr),
-	$SizeofIfmaMsghdr = sizeof(struct ifma_msghdr),
-	$SizeofIfmaMsghdr2 = sizeof(struct ifma_msghdr2),
-	$SizeofRtMsghdr = sizeof(struct rt_msghdr),
-	$SizeofRtMetrics = sizeof(struct rt_metrics),
-};
-
-typedef struct if_msghdr $IfMsghdr;
-typedef struct if_data $IfData;
-typedef struct ifa_msghdr $IfaMsghdr;
-typedef struct ifma_msghdr $IfmaMsghdr;
-typedef struct ifma_msghdr2 $IfmaMsghdr2;
-typedef struct rt_msghdr $RtMsghdr;
-typedef struct rt_metrics $RtMetrics;
-
-// Berkeley packet filter
-
-enum {
-	$SizeofBpfVersion = sizeof(struct bpf_version),
-	$SizeofBpfStat = sizeof(struct bpf_stat),
-	$SizeofBpfProgram = sizeof(struct bpf_program),
-	$SizeofBpfInsn = sizeof(struct bpf_insn),
-	$SizeofBpfHdr = sizeof(struct bpf_hdr),
-};
-
-typedef struct bpf_version $BpfVersion;
-typedef struct bpf_stat $BpfStat;
-typedef struct bpf_program $BpfProgram;
-typedef struct bpf_insn $BpfInsn;
-typedef struct bpf_hdr $BpfHdr;
diff --git a/src/pkg/syscall/types_darwin.go b/src/pkg/syscall/types_darwin.go
new file mode 100644
index 0000000..424f94e
--- /dev/null
+++ b/src/pkg/syscall/types_darwin.go
@@ -0,0 +1,228 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Input to cgo -godefs.  See also mkerrors.sh and mkall.sh
+*/
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package syscall
+
+/*
+#define __DARWIN_UNIX03 0
+#define KERNEL
+#define _DARWIN_USE_64_BIT_INODE
+#include <dirent.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <mach/mach.h>
+#include <mach/message.h>
+#include <sys/event.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_var.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+enum {
+	sizeofPtr = sizeof(void*),
+};
+
+union sockaddr_all {
+	struct sockaddr s1;	// this one gets used for fields
+	struct sockaddr_in s2;	// these pad it out
+	struct sockaddr_in6 s3;
+	struct sockaddr_un s4;
+	struct sockaddr_dl s5;
+};
+
+struct sockaddr_any {
+	struct sockaddr addr;
+	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+*/
+import "C"
+
+// Machine characteristics; for internal use.
+
+const (
+	sizeofPtr      = C.sizeofPtr
+	sizeofShort    = C.sizeof_short
+	sizeofInt      = C.sizeof_int
+	sizeofLong     = C.sizeof_long
+	sizeofLongLong = C.sizeof_longlong
+)
+
+// Basic types
+
+type (
+	_C_short     C.short
+	_C_int       C.int
+	_C_long      C.long
+	_C_long_long C.longlong
+)
+
+// Time
+
+type Timespec C.struct_timespec
+
+type Timeval C.struct_timeval
+
+type Timeval32 C.struct_timeval32
+
+// Processes
+
+type Rusage C.struct_rusage
+
+type Rlimit C.struct_rlimit
+
+type _Gid_t C.gid_t
+
+// Files
+
+type Stat_t C.struct_stat64
+
+type Statfs_t C.struct_statfs64
+
+type Flock_t C.struct_flock
+
+type Fstore_t C.struct_fstore
+
+type Radvisory_t C.struct_radvisory
+
+type Fbootstraptransfer_t C.struct_fbootstraptransfer
+
+type Log2phys_t C.struct_log2phys
+
+type Fsid C.struct_fsid
+
+type Dirent C.struct_dirent
+
+// Sockets
+
+type RawSockaddrInet4 C.struct_sockaddr_in
+
+type RawSockaddrInet6 C.struct_sockaddr_in6
+
+type RawSockaddrUnix C.struct_sockaddr_un
+
+type RawSockaddrDatalink C.struct_sockaddr_dl
+
+type RawSockaddr C.struct_sockaddr
+
+type RawSockaddrAny C.struct_sockaddr_any
+
+type _Socklen C.socklen_t
+
+type Linger C.struct_linger
+
+type Iovec C.struct_iovec
+
+type IPMreq C.struct_ip_mreq
+
+type IPv6Mreq C.struct_ipv6_mreq
+
+type Msghdr C.struct_msghdr
+
+type Cmsghdr C.struct_cmsghdr
+
+type Inet6Pktinfo C.struct_in6_pktinfo
+
+const (
+	SizeofSockaddrInet4    = C.sizeof_struct_sockaddr_in
+	SizeofSockaddrInet6    = C.sizeof_struct_sockaddr_in6
+	SizeofSockaddrAny      = C.sizeof_struct_sockaddr_any
+	SizeofSockaddrUnix     = C.sizeof_struct_sockaddr_un
+	SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
+	SizeofLinger           = C.sizeof_struct_linger
+	SizeofIPMreq           = C.sizeof_struct_ip_mreq
+	SizeofIPv6Mreq         = C.sizeof_struct_ipv6_mreq
+	SizeofMsghdr           = C.sizeof_struct_msghdr
+	SizeofCmsghdr          = C.sizeof_struct_cmsghdr
+	SizeofInet6Pktinfo     = C.sizeof_struct_in6_pktinfo
+)
+
+// Ptrace requests
+
+const (
+	PTRACE_TRACEME = C.PT_TRACE_ME
+	PTRACE_CONT    = C.PT_CONTINUE
+	PTRACE_KILL    = C.PT_KILL
+)
+
+// Events (kqueue, kevent)
+
+type Kevent_t C.struct_kevent
+
+// Select
+
+type FdSet C.fd_set
+
+// Routing and interface messages
+
+const (
+	SizeofIfMsghdr    = C.sizeof_struct_if_msghdr
+	SizeofIfData      = C.sizeof_struct_if_data
+	SizeofIfaMsghdr   = C.sizeof_struct_ifa_msghdr
+	SizeofIfmaMsghdr  = C.sizeof_struct_ifma_msghdr
+	SizeofIfmaMsghdr2 = C.sizeof_struct_ifma_msghdr2
+	SizeofRtMsghdr    = C.sizeof_struct_rt_msghdr
+	SizeofRtMetrics   = C.sizeof_struct_rt_metrics
+)
+
+type IfMsghdr C.struct_if_msghdr
+
+type IfData C.struct_if_data
+
+type IfaMsghdr C.struct_ifa_msghdr
+
+type IfmaMsghdr C.struct_ifma_msghdr
+
+type IfmaMsghdr2 C.struct_ifma_msghdr2
+
+type RtMsghdr C.struct_rt_msghdr
+
+type RtMetrics C.struct_rt_metrics
+
+// Berkeley packet filter
+
+const (
+	SizeofBpfVersion = C.sizeof_struct_bpf_version
+	SizeofBpfStat    = C.sizeof_struct_bpf_stat
+	SizeofBpfProgram = C.sizeof_struct_bpf_program
+	SizeofBpfInsn    = C.sizeof_struct_bpf_insn
+	SizeofBpfHdr     = C.sizeof_struct_bpf_hdr
+)
+
+type BpfVersion C.struct_bpf_version
+
+type BpfStat C.struct_bpf_stat
+
+type BpfProgram C.struct_bpf_program
+
+type BpfInsn C.struct_bpf_insn
+
+type BpfHdr C.struct_bpf_hdr
diff --git a/src/pkg/syscall/types_freebsd.c b/src/pkg/syscall/types_freebsd.c
deleted file mode 100644
index 1494661..0000000
--- a/src/pkg/syscall/types_freebsd.c
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Input to godefs.  See also mkerrors.sh and mkall.sh
- */
-
-#define KERNEL
-#include <dirent.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/event.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/param.h>
-#include <sys/ptrace.h>
-#include <sys/resource.h>
-#include <sys/select.h>
-#include <sys/signal.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <net/bpf.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/route.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-// Machine characteristics; for internal use.
-
-enum {
-	$sizeofPtr = sizeof(void*),
-	$sizeofShort = sizeof(short),
-	$sizeofInt = sizeof(int),
-	$sizeofLong = sizeof(long),
-	$sizeofLongLong = sizeof(long long),
-};
-
-// Basic types
-
-typedef short $_C_short;
-typedef int $_C_int;
-typedef long $_C_long;
-typedef long long $_C_long_long;
-
-// Time
-
-typedef struct timespec $Timespec;
-typedef struct timeval $Timeval;
-
-// Processes
-
-typedef struct rusage $Rusage;
-typedef struct rlimit $Rlimit;
-
-typedef gid_t $_Gid_t;
-
-// Files
-
-enum {
-	$O_CLOEXEC = 0,	// not supported
-};
-
-enum {	// Directory mode bits
-	$S_IFMT = S_IFMT,
-	$S_IFIFO = S_IFIFO,
-	$S_IFCHR = S_IFCHR,
-	$S_IFDIR = S_IFDIR,
-	$S_IFBLK = S_IFBLK,
-	$S_IFREG = S_IFREG,
-	$S_IFLNK = S_IFLNK,
-	$S_IFSOCK = S_IFSOCK,
-	$S_ISUID = S_ISUID,
-	$S_ISGID = S_ISGID,
-	$S_ISVTX = S_ISVTX,
-	$S_IRUSR = S_IRUSR,
-	$S_IWUSR = S_IWUSR,
-	$S_IXUSR = S_IXUSR,
-};
-
-typedef struct stat $Stat_t;
-typedef struct statfs $Statfs_t;
-typedef struct flock $Flock_t;
-
-typedef struct dirent $Dirent;
-
-// Sockets
-
-union sockaddr_all {
-	struct sockaddr s1;	// this one gets used for fields
-	struct sockaddr_in s2;	// these pad it out
-	struct sockaddr_in6 s3;
-	struct sockaddr_un s4;
-	struct sockaddr_dl s5;
-};
-
-struct sockaddr_any {
-	struct sockaddr addr;
-	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
-};
-
-typedef struct sockaddr_in $RawSockaddrInet4;
-typedef struct sockaddr_in6 $RawSockaddrInet6;
-typedef struct sockaddr_un $RawSockaddrUnix;
-typedef struct sockaddr_dl $RawSockaddrDatalink;
-typedef struct sockaddr $RawSockaddr;
-typedef struct sockaddr_any $RawSockaddrAny;
-typedef socklen_t $_Socklen;
-typedef struct linger $Linger;
-typedef struct iovec $Iovec;
-typedef struct ip_mreq $IPMreq;
-typedef struct ipv6_mreq $IPv6Mreq;
-typedef struct msghdr $Msghdr;
-typedef struct cmsghdr $Cmsghdr;
-typedef struct in6_pktinfo $Inet6Pktinfo;
-
-enum {
-	$SizeofSockaddrInet4 = sizeof(struct sockaddr_in),
-	$SizeofSockaddrInet6 = sizeof(struct sockaddr_in6),
-	$SizeofSockaddrAny = sizeof(struct sockaddr_any),
-	$SizeofSockaddrUnix = sizeof(struct sockaddr_un),
-	$SizeofSockaddrDatalink = sizeof(struct sockaddr_dl),
-	$SizeofLinger = sizeof(struct linger),
-	$SizeofIPMreq = sizeof(struct ip_mreq),
-	$SizeofIPv6Mreq = sizeof(struct ipv6_mreq),
-	$SizeofMsghdr = sizeof(struct msghdr),
-	$SizeofCmsghdr = sizeof(struct cmsghdr),
-	$SizeofInet6Pktinfo = sizeof(struct in6_pktinfo),
-};
-
-// Ptrace requests
-
-enum {
-	$PTRACE_TRACEME = PT_TRACE_ME,
-	$PTRACE_CONT = PT_CONTINUE,
-	$PTRACE_KILL = PT_KILL,
-};
-
-// Events (kqueue, kevent)
-
-typedef struct kevent $Kevent_t;
-
-// Select
-
-typedef fd_set $FdSet;
-
-// Routing and interface messages
-
-enum {
-	$SizeofIfMsghdr = sizeof(struct if_msghdr),
-	$SizeofIfData = sizeof(struct if_data),
-	$SizeofIfaMsghdr = sizeof(struct ifa_msghdr),
-	$SizeofIfmaMsghdr = sizeof(struct ifma_msghdr),
-	$SizeofRtMsghdr = sizeof(struct rt_msghdr),
-	$SizeofRtMetrics = sizeof(struct rt_metrics),
-};
-
-typedef struct if_msghdr $IfMsghdr;
-typedef struct if_data $IfData;
-typedef struct ifa_msghdr $IfaMsghdr;
-typedef struct ifma_msghdr $IfmaMsghdr;
-typedef struct rt_msghdr $RtMsghdr;
-typedef struct rt_metrics $RtMetrics;
-
-// Berkeley packet filter
-
-enum {
-	$SizeofBpfVersion = sizeof(struct bpf_version),
-	$SizeofBpfStat = sizeof(struct bpf_stat),
-	$SizeofBpfZbuf = sizeof(struct bpf_zbuf),
-	$SizeofBpfProgram = sizeof(struct bpf_program),
-	$SizeofBpfInsn = sizeof(struct bpf_insn),
-	$SizeofBpfHdr = sizeof(struct bpf_hdr),
-	$SizeofBpfZbufHeader = sizeof(struct bpf_zbuf_header),
-};
-
-typedef struct bpf_version $BpfVersion;
-typedef struct bpf_stat $BpfStat;
-typedef struct bpf_zbuf $BpfZbuf;
-typedef struct bpf_program $BpfProgram;
-typedef struct bpf_insn $BpfInsn;
-typedef struct bpf_hdr $BpfHdr;
-typedef struct bpf_zbuf_header $BpfZbufHeader;
diff --git a/src/pkg/syscall/types_freebsd.go b/src/pkg/syscall/types_freebsd.go
new file mode 100644
index 0000000..f54b6c4
--- /dev/null
+++ b/src/pkg/syscall/types_freebsd.go
@@ -0,0 +1,240 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Input to cgo -godefs.  See also mkerrors.sh and mkall.sh
+*/
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package syscall
+
+/*
+#define KERNEL
+#include <dirent.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/event.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+enum {
+	sizeofPtr = sizeof(void*),
+};
+
+union sockaddr_all {
+	struct sockaddr s1;	// this one gets used for fields
+	struct sockaddr_in s2;	// these pad it out
+	struct sockaddr_in6 s3;
+	struct sockaddr_un s4;
+	struct sockaddr_dl s5;
+};
+
+struct sockaddr_any {
+	struct sockaddr addr;
+	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+*/
+import "C"
+
+// Machine characteristics; for internal use.
+
+const (
+	sizeofPtr      = C.sizeofPtr
+	sizeofShort    = C.sizeof_short
+	sizeofInt      = C.sizeof_int
+	sizeofLong     = C.sizeof_long
+	sizeofLongLong = C.sizeof_longlong
+)
+
+// Basic types
+
+type (
+	_C_short     C.short
+	_C_int       C.int
+	_C_long      C.long
+	_C_long_long C.longlong
+)
+
+// Time
+
+type Timespec C.struct_timespec
+
+type Timeval C.struct_timeval
+
+// Processes
+
+type Rusage C.struct_rusage
+
+type Rlimit C.struct_rlimit
+
+type _Gid_t C.gid_t
+
+// Files
+
+const (
+	O_CLOEXEC = 0 // not supported
+)
+
+const ( // Directory mode bits
+	S_IFMT   = C.S_IFMT
+	S_IFIFO  = C.S_IFIFO
+	S_IFCHR  = C.S_IFCHR
+	S_IFDIR  = C.S_IFDIR
+	S_IFBLK  = C.S_IFBLK
+	S_IFREG  = C.S_IFREG
+	S_IFLNK  = C.S_IFLNK
+	S_IFSOCK = C.S_IFSOCK
+	S_ISUID  = C.S_ISUID
+	S_ISGID  = C.S_ISGID
+	S_ISVTX  = C.S_ISVTX
+	S_IRUSR  = C.S_IRUSR
+	S_IWUSR  = C.S_IWUSR
+	S_IXUSR  = C.S_IXUSR
+)
+
+type Stat_t C.struct_stat
+
+type Statfs_t C.struct_statfs
+
+type Flock_t C.struct_flock
+
+type Dirent C.struct_dirent
+
+type Fsid C.struct_fsid
+
+// Sockets
+
+type RawSockaddrInet4 C.struct_sockaddr_in
+
+type RawSockaddrInet6 C.struct_sockaddr_in6
+
+type RawSockaddrUnix C.struct_sockaddr_un
+
+type RawSockaddrDatalink C.struct_sockaddr_dl
+
+type RawSockaddr C.struct_sockaddr
+
+type RawSockaddrAny C.struct_sockaddr_any
+
+type _Socklen C.socklen_t
+
+type Linger C.struct_linger
+
+type Iovec C.struct_iovec
+
+type IPMreq C.struct_ip_mreq
+
+type IPMreqn C.struct_ip_mreqn
+
+type IPv6Mreq C.struct_ipv6_mreq
+
+type Msghdr C.struct_msghdr
+
+type Cmsghdr C.struct_cmsghdr
+
+type Inet6Pktinfo C.struct_in6_pktinfo
+
+const (
+	SizeofSockaddrInet4    = C.sizeof_struct_sockaddr_in
+	SizeofSockaddrInet6    = C.sizeof_struct_sockaddr_in6
+	SizeofSockaddrAny      = C.sizeof_struct_sockaddr_any
+	SizeofSockaddrUnix     = C.sizeof_struct_sockaddr_un
+	SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
+	SizeofLinger           = C.sizeof_struct_linger
+	SizeofIPMreq           = C.sizeof_struct_ip_mreq
+	SizeofIPMreqn          = C.sizeof_struct_ip_mreqn
+	SizeofIPv6Mreq         = C.sizeof_struct_ipv6_mreq
+	SizeofMsghdr           = C.sizeof_struct_msghdr
+	SizeofCmsghdr          = C.sizeof_struct_cmsghdr
+	SizeofInet6Pktinfo     = C.sizeof_struct_in6_pktinfo
+)
+
+// Ptrace requests
+
+const (
+	PTRACE_TRACEME = C.PT_TRACE_ME
+	PTRACE_CONT    = C.PT_CONTINUE
+	PTRACE_KILL    = C.PT_KILL
+)
+
+// Events (kqueue, kevent)
+
+type Kevent_t C.struct_kevent
+
+// Select
+
+type FdSet C.fd_set
+
+// Routing and interface messages
+
+const (
+	SizeofIfMsghdr   = C.sizeof_struct_if_msghdr
+	SizeofIfData     = C.sizeof_struct_if_data
+	SizeofIfaMsghdr  = C.sizeof_struct_ifa_msghdr
+	SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
+	SizeofRtMsghdr   = C.sizeof_struct_rt_msghdr
+	SizeofRtMetrics  = C.sizeof_struct_rt_metrics
+)
+
+type IfMsghdr C.struct_if_msghdr
+
+type IfData C.struct_if_data
+
+type IfaMsghdr C.struct_ifa_msghdr
+
+type IfmaMsghdr C.struct_ifma_msghdr
+
+type RtMsghdr C.struct_rt_msghdr
+
+type RtMetrics C.struct_rt_metrics
+
+// Berkeley packet filter
+
+const (
+	SizeofBpfVersion    = C.sizeof_struct_bpf_version
+	SizeofBpfStat       = C.sizeof_struct_bpf_stat
+	SizeofBpfZbuf       = C.sizeof_struct_bpf_zbuf
+	SizeofBpfProgram    = C.sizeof_struct_bpf_program
+	SizeofBpfInsn       = C.sizeof_struct_bpf_insn
+	SizeofBpfHdr        = C.sizeof_struct_bpf_hdr
+	SizeofBpfZbufHeader = C.sizeof_struct_bpf_zbuf_header
+)
+
+type BpfVersion C.struct_bpf_version
+
+type BpfStat C.struct_bpf_stat
+
+type BpfZbuf C.struct_bpf_zbuf
+
+type BpfProgram C.struct_bpf_program
+
+type BpfInsn C.struct_bpf_insn
+
+type BpfHdr C.struct_bpf_hdr
+
+type BpfZbufHeader C.struct_bpf_zbuf_header
diff --git a/src/pkg/syscall/types_linux.c b/src/pkg/syscall/types_linux.c
deleted file mode 100644
index 68d64a3..0000000
--- a/src/pkg/syscall/types_linux.c
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Input to godefs.  See also mkerrors.sh and mkall.sh
- */
-
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-#define _FILE_OFFSET_BITS 64
-#define _GNU_SOURCE
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netpacket/packet.h>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/epoll.h>
-#include <sys/inotify.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/param.h>
-#include <sys/ptrace.h>
-#include <sys/resource.h>
-#include <sys/select.h>
-#include <sys/signal.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/sysinfo.h>
-#include <sys/time.h>
-#include <sys/times.h>
-#include <sys/timex.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <sys/user.h>
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <linux/filter.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <time.h>
-#include <unistd.h>
-#include <ustat.h>
-#include <utime.h>
-
-// Machine characteristics; for internal use.
-
-enum {
-	$sizeofPtr = sizeof(void*),
-	$sizeofShort = sizeof(short),
-	$sizeofInt = sizeof(int),
-	$sizeofLong = sizeof(long),
-	$sizeofLongLong = sizeof(long long),
-	$PathMax = PATH_MAX,
-};
-
-// Basic types
-
-typedef short $_C_short;
-typedef int $_C_int;
-typedef long $_C_long;
-typedef long long $_C_long_long;
-
-// Time
-
-typedef struct timespec $Timespec;
-typedef struct timeval $Timeval;
-typedef struct timex $Timex;
-typedef time_t $Time_t;
-typedef struct tms $Tms;
-typedef struct utimbuf $Utimbuf;
-
-// Processes
-
-typedef struct rusage $Rusage;
-typedef struct rlimit $Rlimit;
-
-typedef gid_t $_Gid_t;
-
-// Files
-
-typedef struct stat $Stat_t;
-typedef struct statfs $Statfs_t;
-
-typedef struct dirent $Dirent;
-
-// Sockets
-
-union sockaddr_all {
-	struct sockaddr s1;	// this one gets used for fields
-	struct sockaddr_in s2;	// these pad it out
-	struct sockaddr_in6 s3;
-	struct sockaddr_un s4;
-	struct sockaddr_ll s5;
-	struct sockaddr_nl s6;
-};
-
-struct sockaddr_any {
-	struct sockaddr addr;
-	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
-};
-
-typedef struct sockaddr_in $RawSockaddrInet4;
-typedef struct sockaddr_in6 $RawSockaddrInet6;
-typedef struct sockaddr_un $RawSockaddrUnix;
-typedef struct sockaddr_ll $RawSockaddrLinklayer;
-typedef struct sockaddr_nl $RawSockaddrNetlink;
-typedef struct sockaddr $RawSockaddr;
-typedef struct sockaddr_any $RawSockaddrAny;
-typedef socklen_t $_Socklen;
-typedef struct linger $Linger;
-typedef struct iovec $Iovec;
-typedef struct ip_mreq $IPMreq;
-typedef struct ipv6_mreq $IPv6Mreq;
-typedef struct msghdr $Msghdr;
-typedef struct cmsghdr $Cmsghdr;
-typedef struct in6_pktinfo $Inet6Pktinfo;
-typedef struct ucred $Ucred;
-
-enum {
-	$SizeofSockaddrInet4 = sizeof(struct sockaddr_in),
-	$SizeofSockaddrInet6 = sizeof(struct sockaddr_in6),
-	$SizeofSockaddrAny = sizeof(struct sockaddr_any),
-	$SizeofSockaddrUnix = sizeof(struct sockaddr_un),
-	$SizeofSockaddrLinklayer = sizeof(struct sockaddr_ll),
-	$SizeofSockaddrNetlink = sizeof(struct sockaddr_nl),
-	$SizeofLinger = sizeof(struct linger),
-	$SizeofIPMreq = sizeof(struct ip_mreq),
-	$SizeofIPv6Mreq = sizeof(struct ipv6_mreq),
-	$SizeofMsghdr = sizeof(struct msghdr),
-	$SizeofCmsghdr = sizeof(struct cmsghdr),
-	$SizeofInet6Pktinfo = sizeof(struct in6_pktinfo),
-	$SizeofUcred = sizeof(struct ucred),
-};
-
-// Netlink routing and interface messages
-
-enum {
-	$IFA_UNSPEC = IFA_UNSPEC,
-	$IFA_ADDRESS = IFA_ADDRESS,
-	$IFA_LOCAL = IFA_LOCAL,
-	$IFA_LABEL = IFA_LABEL,
-	$IFA_BROADCAST = IFA_BROADCAST,
-	$IFA_ANYCAST = IFA_ANYCAST,
-	$IFA_CACHEINFO = IFA_CACHEINFO,
-	$IFA_MULTICAST = IFA_MULTICAST,
-	$IFLA_UNSPEC = IFLA_UNSPEC,
-	$IFLA_ADDRESS = IFLA_ADDRESS,
-	$IFLA_BROADCAST = IFLA_BROADCAST,
-	$IFLA_IFNAME = IFLA_IFNAME,
-	$IFLA_MTU = IFLA_MTU,
-	$IFLA_LINK = IFLA_LINK,
-	$IFLA_QDISC = IFLA_QDISC,
-	$IFLA_STATS = IFLA_STATS,
-	$IFLA_COST = IFLA_COST,
-	$IFLA_PRIORITY = IFLA_PRIORITY,
-	$IFLA_MASTER = IFLA_MASTER,
-	$IFLA_WIRELESS = IFLA_WIRELESS,
-	$IFLA_PROTINFO = IFLA_PROTINFO,
-	$IFLA_TXQLEN = IFLA_TXQLEN,
-	$IFLA_MAP = IFLA_MAP,
-	$IFLA_WEIGHT = IFLA_WEIGHT,
-	$IFLA_OPERSTATE = IFLA_OPERSTATE,
-	$IFLA_LINKMODE = IFLA_LINKMODE,
-	$IFLA_LINKINFO = IFLA_LINKINFO,
-	$IFLA_NET_NS_PID = IFLA_NET_NS_PID,
-	$IFLA_IFALIAS = IFLA_IFALIAS,
-	$IFLA_MAX = IFLA_MAX,
-	$RT_SCOPE_UNIVERSE = RT_SCOPE_UNIVERSE,
-	$RT_SCOPE_SITE = RT_SCOPE_SITE,
-	$RT_SCOPE_LINK = RT_SCOPE_LINK,
-	$RT_SCOPE_HOST = RT_SCOPE_HOST,
-	$RT_SCOPE_NOWHERE = RT_SCOPE_NOWHERE,
-	$RT_TABLE_UNSPEC = RT_TABLE_UNSPEC,
-	$RT_TABLE_COMPAT = RT_TABLE_COMPAT,
-	$RT_TABLE_DEFAULT = RT_TABLE_DEFAULT,
-	$RT_TABLE_MAIN = RT_TABLE_MAIN,
-	$RT_TABLE_LOCAL = RT_TABLE_LOCAL,
-	$RT_TABLE_MAX = RT_TABLE_MAX,
-	$RTA_UNSPEC = RTA_UNSPEC,
-	$RTA_DST = RTA_DST,
-	$RTA_SRC = RTA_SRC,
-	$RTA_IIF = RTA_IIF,
-	$RTA_OIF = RTA_OIF,
-	$RTA_GATEWAY = RTA_GATEWAY,
-	$RTA_PRIORITY = RTA_PRIORITY,
-	$RTA_PREFSRC = RTA_PREFSRC,
-	$RTA_METRICS = RTA_METRICS,
-	$RTA_MULTIPATH = RTA_MULTIPATH,
-	$RTA_FLOW = RTA_FLOW,
-	$RTA_CACHEINFO = RTA_CACHEINFO,
-	$RTA_TABLE = RTA_TABLE,
-	$RTN_UNSPEC = RTN_UNSPEC,
-	$RTN_UNICAST = RTN_UNICAST,
-	$RTN_LOCAL = RTN_LOCAL,
-	$RTN_BROADCAST = RTN_BROADCAST,
-	$RTN_ANYCAST = RTN_ANYCAST,
-	$RTN_MULTICAST = RTN_MULTICAST,
-	$RTN_BLACKHOLE = RTN_BLACKHOLE,
-	$RTN_UNREACHABLE = RTN_UNREACHABLE,
-	$RTN_PROHIBIT = RTN_PROHIBIT,
-	$RTN_THROW = RTN_THROW,
-	$RTN_NAT = RTN_NAT,
-	$RTN_XRESOLVE = RTN_XRESOLVE,
-	$SizeofNlMsghdr = sizeof(struct nlmsghdr),
-	$SizeofNlMsgerr = sizeof(struct nlmsgerr),
-	$SizeofRtGenmsg = sizeof(struct rtgenmsg),
-	$SizeofNlAttr = sizeof(struct nlattr),
-	$SizeofRtAttr = sizeof(struct rtattr),
-	$SizeofIfInfomsg = sizeof(struct ifinfomsg),
-	$SizeofIfAddrmsg = sizeof(struct ifaddrmsg),
-	$SizeofRtMsg = sizeof(struct rtmsg),
-	$SizeofRtNexthop = sizeof(struct rtnexthop),
-};
-
-typedef struct nlmsghdr $NlMsghdr;
-typedef struct nlmsgerr $NlMsgerr;
-typedef struct rtgenmsg $RtGenmsg;
-typedef struct nlattr $NlAttr;
-typedef struct rtattr $RtAttr;
-typedef struct ifinfomsg $IfInfomsg;
-typedef struct ifaddrmsg $IfAddrmsg;
-typedef struct rtmsg $RtMsg;
-typedef struct rtnexthop $RtNexthop;
-
-// Linux socket filter
-
-enum {
-	$SizeofSockFilter = sizeof(struct sock_filter),
-	$SizeofSockFprog = sizeof(struct sock_fprog),
-};
-
-typedef struct sock_filter $SockFilter;
-typedef struct sock_fprog $SockFprog;
-
-// Inotify
-
-typedef struct inotify_event $InotifyEvent;
-
-enum {
-	$SizeofInotifyEvent = sizeof(struct inotify_event)
-};
-
-// Ptrace
-
-// Register structures
-typedef struct user_regs_struct $PtraceRegs;
-
-// Misc
-
-typedef fd_set $FdSet;
-typedef struct sysinfo $Sysinfo_t;
-typedef struct utsname $Utsname;
-typedef struct ustat $Ustat_t;
-
-// The real epoll_event is a union, and godefs doesn't handle it well.
-struct my_epoll_event {
-	uint32_t events;
-	int32_t fd;
-	int32_t pad;
-};
-
-typedef struct my_epoll_event $EpollEvent;
diff --git a/src/pkg/syscall/types_linux.go b/src/pkg/syscall/types_linux.go
new file mode 100644
index 0000000..a02f218
--- /dev/null
+++ b/src/pkg/syscall/types_linux.go
@@ -0,0 +1,452 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Input to cgo -godefs.  See also mkerrors.sh and mkall.sh
+*/
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package syscall
+
+/*
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
+#define _GNU_SOURCE
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netpacket/packet.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/epoll.h>
+#include <sys/inotify.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/sysinfo.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/timex.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/user.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <linux/filter.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <ustat.h>
+#include <utime.h>
+
+enum {
+	sizeofPtr = sizeof(void*),
+};
+
+union sockaddr_all {
+	struct sockaddr s1;	// this one gets used for fields
+	struct sockaddr_in s2;	// these pad it out
+	struct sockaddr_in6 s3;
+	struct sockaddr_un s4;
+	struct sockaddr_ll s5;
+	struct sockaddr_nl s6;
+};
+
+struct sockaddr_any {
+	struct sockaddr addr;
+	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+// copied from /usr/include/linux/un.h 
+struct my_sockaddr_un {
+	sa_family_t sun_family;
+#ifdef __ARM_EABI__
+	// on ARM char is by default unsigned
+	signed char sun_path[108];
+#else
+	char sun_path[108];
+#endif
+};
+
+#ifdef __ARM_EABI__
+typedef struct user_regs PtraceRegs;
+#else
+typedef struct user_regs_struct PtraceRegs;
+#endif
+
+// The real epoll_event is a union, and godefs doesn't handle it well.
+struct my_epoll_event {
+	uint32_t events;
+#ifdef __ARM_EABI__
+	// padding is not specified in linux/eventpoll.h but added to conform to the
+	// alignment requirements of EABI
+	int32_t padFd;
+#endif
+	int32_t fd;
+	int32_t pad;
+};
+
+*/
+import "C"
+
+// Machine characteristics; for internal use.
+
+const (
+	sizeofPtr      = C.sizeofPtr
+	sizeofShort    = C.sizeof_short
+	sizeofInt      = C.sizeof_int
+	sizeofLong     = C.sizeof_long
+	sizeofLongLong = C.sizeof_longlong
+	PathMax        = C.PATH_MAX
+)
+
+// Basic types
+
+type (
+	_C_short     C.short
+	_C_int       C.int
+	_C_long      C.long
+	_C_long_long C.longlong
+)
+
+// Time
+
+type Timespec C.struct_timespec
+
+type Timeval C.struct_timeval
+
+type Timex C.struct_timex
+
+type Time_t C.time_t
+
+type Tms C.struct_tms
+
+type Utimbuf C.struct_utimbuf
+
+// Processes
+
+type Rusage C.struct_rusage
+
+type Rlimit C.struct_rlimit
+
+type _Gid_t C.gid_t
+
+// Files
+
+type Stat_t C.struct_stat
+
+type Statfs_t C.struct_statfs
+
+type Dirent C.struct_dirent
+
+type Fsid C.fsid_t
+
+// Sockets
+
+type RawSockaddrInet4 C.struct_sockaddr_in
+
+type RawSockaddrInet6 C.struct_sockaddr_in6
+
+type RawSockaddrUnix C.struct_my_sockaddr_un
+
+type RawSockaddrLinklayer C.struct_sockaddr_ll
+
+type RawSockaddrNetlink C.struct_sockaddr_nl
+
+type RawSockaddr C.struct_sockaddr
+
+type RawSockaddrAny C.struct_sockaddr_any
+
+type _Socklen C.socklen_t
+
+type Linger C.struct_linger
+
+type Iovec C.struct_iovec
+
+type IPMreq C.struct_ip_mreq
+
+type IPMreqn C.struct_ip_mreqn
+
+type IPv6Mreq C.struct_ipv6_mreq
+
+type Msghdr C.struct_msghdr
+
+type Cmsghdr C.struct_cmsghdr
+
+type Inet4Pktinfo C.struct_in_pktinfo
+
+type Inet6Pktinfo C.struct_in6_pktinfo
+
+type Ucred C.struct_ucred
+
+const (
+	SizeofSockaddrInet4     = C.sizeof_struct_sockaddr_in
+	SizeofSockaddrInet6     = C.sizeof_struct_sockaddr_in6
+	SizeofSockaddrAny       = C.sizeof_struct_sockaddr_any
+	SizeofSockaddrUnix      = C.sizeof_struct_sockaddr_un
+	SizeofSockaddrLinklayer = C.sizeof_struct_sockaddr_ll
+	SizeofSockaddrNetlink   = C.sizeof_struct_sockaddr_nl
+	SizeofLinger            = C.sizeof_struct_linger
+	SizeofIPMreq            = C.sizeof_struct_ip_mreq
+	SizeofIPMreqn           = C.sizeof_struct_ip_mreqn
+	SizeofIPv6Mreq          = C.sizeof_struct_ipv6_mreq
+	SizeofMsghdr            = C.sizeof_struct_msghdr
+	SizeofCmsghdr           = C.sizeof_struct_cmsghdr
+	SizeofInet4Pktinfo      = C.sizeof_struct_in_pktinfo
+	SizeofInet6Pktinfo      = C.sizeof_struct_in6_pktinfo
+	SizeofUcred             = C.sizeof_struct_ucred
+)
+
+// Netlink routing and interface messages
+
+const (
+	IFA_UNSPEC        = C.IFA_UNSPEC
+	IFA_ADDRESS       = C.IFA_ADDRESS
+	IFA_LOCAL         = C.IFA_LOCAL
+	IFA_LABEL         = C.IFA_LABEL
+	IFA_BROADCAST     = C.IFA_BROADCAST
+	IFA_ANYCAST       = C.IFA_ANYCAST
+	IFA_CACHEINFO     = C.IFA_CACHEINFO
+	IFA_MULTICAST     = C.IFA_MULTICAST
+	IFLA_UNSPEC       = C.IFLA_UNSPEC
+	IFLA_ADDRESS      = C.IFLA_ADDRESS
+	IFLA_BROADCAST    = C.IFLA_BROADCAST
+	IFLA_IFNAME       = C.IFLA_IFNAME
+	IFLA_MTU          = C.IFLA_MTU
+	IFLA_LINK         = C.IFLA_LINK
+	IFLA_QDISC        = C.IFLA_QDISC
+	IFLA_STATS        = C.IFLA_STATS
+	IFLA_COST         = C.IFLA_COST
+	IFLA_PRIORITY     = C.IFLA_PRIORITY
+	IFLA_MASTER       = C.IFLA_MASTER
+	IFLA_WIRELESS     = C.IFLA_WIRELESS
+	IFLA_PROTINFO     = C.IFLA_PROTINFO
+	IFLA_TXQLEN       = C.IFLA_TXQLEN
+	IFLA_MAP          = C.IFLA_MAP
+	IFLA_WEIGHT       = C.IFLA_WEIGHT
+	IFLA_OPERSTATE    = C.IFLA_OPERSTATE
+	IFLA_LINKMODE     = C.IFLA_LINKMODE
+	IFLA_LINKINFO     = C.IFLA_LINKINFO
+	IFLA_NET_NS_PID   = C.IFLA_NET_NS_PID
+	IFLA_IFALIAS      = C.IFLA_IFALIAS
+	IFLA_MAX          = C.IFLA_MAX
+	RT_SCOPE_UNIVERSE = C.RT_SCOPE_UNIVERSE
+	RT_SCOPE_SITE     = C.RT_SCOPE_SITE
+	RT_SCOPE_LINK     = C.RT_SCOPE_LINK
+	RT_SCOPE_HOST     = C.RT_SCOPE_HOST
+	RT_SCOPE_NOWHERE  = C.RT_SCOPE_NOWHERE
+	RT_TABLE_UNSPEC   = C.RT_TABLE_UNSPEC
+	RT_TABLE_COMPAT   = C.RT_TABLE_COMPAT
+	RT_TABLE_DEFAULT  = C.RT_TABLE_DEFAULT
+	RT_TABLE_MAIN     = C.RT_TABLE_MAIN
+	RT_TABLE_LOCAL    = C.RT_TABLE_LOCAL
+	RT_TABLE_MAX      = C.RT_TABLE_MAX
+	RTA_UNSPEC        = C.RTA_UNSPEC
+	RTA_DST           = C.RTA_DST
+	RTA_SRC           = C.RTA_SRC
+	RTA_IIF           = C.RTA_IIF
+	RTA_OIF           = C.RTA_OIF
+	RTA_GATEWAY       = C.RTA_GATEWAY
+	RTA_PRIORITY      = C.RTA_PRIORITY
+	RTA_PREFSRC       = C.RTA_PREFSRC
+	RTA_METRICS       = C.RTA_METRICS
+	RTA_MULTIPATH     = C.RTA_MULTIPATH
+	RTA_FLOW          = C.RTA_FLOW
+	RTA_CACHEINFO     = C.RTA_CACHEINFO
+	RTA_TABLE         = C.RTA_TABLE
+	RTN_UNSPEC        = C.RTN_UNSPEC
+	RTN_UNICAST       = C.RTN_UNICAST
+	RTN_LOCAL         = C.RTN_LOCAL
+	RTN_BROADCAST     = C.RTN_BROADCAST
+	RTN_ANYCAST       = C.RTN_ANYCAST
+	RTN_MULTICAST     = C.RTN_MULTICAST
+	RTN_BLACKHOLE     = C.RTN_BLACKHOLE
+	RTN_UNREACHABLE   = C.RTN_UNREACHABLE
+	RTN_PROHIBIT      = C.RTN_PROHIBIT
+	RTN_THROW         = C.RTN_THROW
+	RTN_NAT           = C.RTN_NAT
+	RTN_XRESOLVE      = C.RTN_XRESOLVE
+	SizeofNlMsghdr    = C.sizeof_struct_nlmsghdr
+	SizeofNlMsgerr    = C.sizeof_struct_nlmsgerr
+	SizeofRtGenmsg    = C.sizeof_struct_rtgenmsg
+	SizeofNlAttr      = C.sizeof_struct_nlattr
+	SizeofRtAttr      = C.sizeof_struct_rtattr
+	SizeofIfInfomsg   = C.sizeof_struct_ifinfomsg
+	SizeofIfAddrmsg   = C.sizeof_struct_ifaddrmsg
+	SizeofRtMsg       = C.sizeof_struct_rtmsg
+	SizeofRtNexthop   = C.sizeof_struct_rtnexthop
+)
+
+type NlMsghdr C.struct_nlmsghdr
+
+type NlMsgerr C.struct_nlmsgerr
+
+type RtGenmsg C.struct_rtgenmsg
+
+type NlAttr C.struct_nlattr
+
+type RtAttr C.struct_rtattr
+
+type IfInfomsg C.struct_ifinfomsg
+
+type IfAddrmsg C.struct_ifaddrmsg
+
+type RtMsg C.struct_rtmsg
+
+type RtNexthop C.struct_rtnexthop
+
+// Linux socket filter
+
+const (
+	SizeofSockFilter = C.sizeof_struct_sock_filter
+	SizeofSockFprog  = C.sizeof_struct_sock_fprog
+)
+
+type SockFilter C.struct_sock_filter
+
+type SockFprog C.struct_sock_fprog
+
+// Inotify
+
+type InotifyEvent C.struct_inotify_event
+
+const SizeofInotifyEvent = C.sizeof_struct_inotify_event
+
+// Ptrace
+
+// Register structures
+type PtraceRegs C.PtraceRegs
+
+// Misc
+
+type FdSet C.fd_set
+
+type Sysinfo_t C.struct_sysinfo
+
+type Utsname C.struct_utsname
+
+type Ustat_t C.struct_ustat
+
+type EpollEvent C.struct_my_epoll_event
+
+// Terminal handling
+
+type Termios C.struct_termios
+
+const (
+	VINTR    = C.VINTR
+	VQUIT    = C.VQUIT
+	VERASE   = C.VERASE
+	VKILL    = C.VKILL
+	VEOF     = C.VEOF
+	VTIME    = C.VTIME
+	VMIN     = C.VMIN
+	VSWTC    = C.VSWTC
+	VSTART   = C.VSTART
+	VSTOP    = C.VSTOP
+	VSUSP    = C.VSUSP
+	VEOL     = C.VEOL
+	VREPRINT = C.VREPRINT
+	VDISCARD = C.VDISCARD
+	VWERASE  = C.VWERASE
+	VLNEXT   = C.VLNEXT
+	VEOL2    = C.VEOL2
+	IGNBRK   = C.IGNBRK
+	BRKINT   = C.BRKINT
+	IGNPAR   = C.IGNPAR
+	PARMRK   = C.PARMRK
+	INPCK    = C.INPCK
+	ISTRIP   = C.ISTRIP
+	INLCR    = C.INLCR
+	IGNCR    = C.IGNCR
+	ICRNL    = C.ICRNL
+	IUCLC    = C.IUCLC
+	IXON     = C.IXON
+	IXANY    = C.IXANY
+	IXOFF    = C.IXOFF
+	IMAXBEL  = C.IMAXBEL
+	IUTF8    = C.IUTF8
+	OPOST    = C.OPOST
+	OLCUC    = C.OLCUC
+	ONLCR    = C.ONLCR
+	OCRNL    = C.OCRNL
+	ONOCR    = C.ONOCR
+	ONLRET   = C.ONLRET
+	OFILL    = C.OFILL
+	OFDEL    = C.OFDEL
+	B0       = C.B0
+	B50      = C.B50
+	B75      = C.B75
+	B110     = C.B110
+	B134     = C.B134
+	B150     = C.B150
+	B200     = C.B200
+	B300     = C.B300
+	B600     = C.B600
+	B1200    = C.B1200
+	B1800    = C.B1800
+	B2400    = C.B2400
+	B4800    = C.B4800
+	B9600    = C.B9600
+	B19200   = C.B19200
+	B38400   = C.B38400
+	CSIZE    = C.CSIZE
+	CS5      = C.CS5
+	CS6      = C.CS6
+	CS7      = C.CS7
+	CS8      = C.CS8
+	CSTOPB   = C.CSTOPB
+	CREAD    = C.CREAD
+	PARENB   = C.PARENB
+	PARODD   = C.PARODD
+	HUPCL    = C.HUPCL
+	CLOCAL   = C.CLOCAL
+	B57600   = C.B57600
+	B115200  = C.B115200
+	B230400  = C.B230400
+	B460800  = C.B460800
+	B500000  = C.B500000
+	B576000  = C.B576000
+	B921600  = C.B921600
+	B1000000 = C.B1000000
+	B1152000 = C.B1152000
+	B1500000 = C.B1500000
+	B2000000 = C.B2000000
+	B2500000 = C.B2500000
+	B3000000 = C.B3000000
+	B3500000 = C.B3500000
+	B4000000 = C.B4000000
+	ISIG     = C.ISIG
+	ICANON   = C.ICANON
+	XCASE    = C.XCASE
+	ECHO     = C.ECHO
+	ECHOE    = C.ECHOE
+	ECHOK    = C.ECHOK
+	ECHONL   = C.ECHONL
+	NOFLSH   = C.NOFLSH
+	TOSTOP   = C.TOSTOP
+	ECHOCTL  = C.ECHOCTL
+	ECHOPRT  = C.ECHOPRT
+	ECHOKE   = C.ECHOKE
+	FLUSHO   = C.FLUSHO
+	PENDIN   = C.PENDIN
+	IEXTEN   = C.IEXTEN
+	TCGETS   = C.TCGETS
+	TCSETS   = C.TCSETS
+)
diff --git a/src/pkg/syscall/types_netbsd.go b/src/pkg/syscall/types_netbsd.go
new file mode 100644
index 0000000..6f7ef35
--- /dev/null
+++ b/src/pkg/syscall/types_netbsd.go
@@ -0,0 +1,229 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Input to cgo -godefs.  See also mkerrors.sh and mkall.sh
+*/
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package syscall
+
+/*
+#define KERNEL
+#include <dirent.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+enum {
+	sizeofPtr = sizeof(void*),
+};
+
+union sockaddr_all {
+	struct sockaddr s1;	// this one gets used for fields
+	struct sockaddr_in s2;	// these pad it out
+	struct sockaddr_in6 s3;
+	struct sockaddr_un s4;
+	struct sockaddr_dl s5;
+};
+
+struct sockaddr_any {
+	struct sockaddr addr;
+	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+*/
+import "C"
+
+// Machine characteristics; for internal use.
+
+const (
+	sizeofPtr      = C.sizeofPtr
+	sizeofShort    = C.sizeof_short
+	sizeofInt      = C.sizeof_int
+	sizeofLong     = C.sizeof_long
+	sizeofLongLong = C.sizeof_longlong
+)
+
+// Basic types
+
+type (
+	_C_short     C.short
+	_C_int       C.int
+	_C_long      C.long
+	_C_long_long C.longlong
+)
+
+// Time
+
+type Timespec C.struct_timespec
+
+type Timeval C.struct_timeval
+
+// Processes
+
+type Rusage C.struct_rusage
+
+type Rlimit C.struct_rlimit
+
+type _Gid_t C.gid_t
+
+// Files
+
+const ( // Directory mode bits
+	S_IFMT   = C.S_IFMT
+	S_IFIFO  = C.S_IFIFO
+	S_IFCHR  = C.S_IFCHR
+	S_IFDIR  = C.S_IFDIR
+	S_IFBLK  = C.S_IFBLK
+	S_IFREG  = C.S_IFREG
+	S_IFLNK  = C.S_IFLNK
+	S_IFSOCK = C.S_IFSOCK
+	S_ISUID  = C.S_ISUID
+	S_ISGID  = C.S_ISGID
+	S_ISVTX  = C.S_ISVTX
+	S_IRUSR  = C.S_IRUSR
+	S_IWUSR  = C.S_IWUSR
+	S_IXUSR  = C.S_IXUSR
+)
+
+type Stat_t C.struct_stat
+
+type Statfs_t C.struct_statfs
+
+type Flock_t C.struct_flock
+
+type Dirent C.struct_dirent
+
+type Fsid C.fsid_t
+
+// Sockets
+
+type RawSockaddrInet4 C.struct_sockaddr_in
+
+type RawSockaddrInet6 C.struct_sockaddr_in6
+
+type RawSockaddrUnix C.struct_sockaddr_un
+
+type RawSockaddrDatalink C.struct_sockaddr_dl
+
+type RawSockaddr C.struct_sockaddr
+
+type RawSockaddrAny C.struct_sockaddr_any
+
+type _Socklen C.socklen_t
+
+type Linger C.struct_linger
+
+type Iovec C.struct_iovec
+
+type IPMreq C.struct_ip_mreq
+
+type IPv6Mreq C.struct_ipv6_mreq
+
+type Msghdr C.struct_msghdr
+
+type Cmsghdr C.struct_cmsghdr
+
+type Inet6Pktinfo C.struct_in6_pktinfo
+
+const (
+	SizeofSockaddrInet4    = C.sizeof_struct_sockaddr_in
+	SizeofSockaddrInet6    = C.sizeof_struct_sockaddr_in6
+	SizeofSockaddrAny      = C.sizeof_struct_sockaddr_any
+	SizeofSockaddrUnix     = C.sizeof_struct_sockaddr_un
+	SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
+	SizeofLinger           = C.sizeof_struct_linger
+	SizeofIPMreq           = C.sizeof_struct_ip_mreq
+	SizeofIPv6Mreq         = C.sizeof_struct_ipv6_mreq
+	SizeofMsghdr           = C.sizeof_struct_msghdr
+	SizeofCmsghdr          = C.sizeof_struct_cmsghdr
+	SizeofInet6Pktinfo     = C.sizeof_struct_in6_pktinfo
+)
+
+// Ptrace requests
+
+const (
+	PTRACE_TRACEME = C.PT_TRACE_ME
+	PTRACE_CONT    = C.PT_CONTINUE
+	PTRACE_KILL    = C.PT_KILL
+)
+
+// Events (kqueue, kevent)
+
+type Kevent_t C.struct_kevent
+
+// Select
+
+type FdSet C.fd_set
+
+// Routing and interface messages
+
+const (
+	SizeofIfMsghdr  = C.sizeof_struct_if_msghdr
+	SizeofIfData    = C.sizeof_struct_if_data
+	SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
+	SizeofRtMsghdr  = C.sizeof_struct_rt_msghdr
+	SizeofRtMetrics = C.sizeof_struct_rt_metrics
+)
+
+type IfMsghdr C.struct_if_msghdr
+
+type IfData C.struct_if_data
+
+type IfaMsghdr C.struct_ifa_msghdr
+
+type RtMsghdr C.struct_rt_msghdr
+
+type RtMetrics C.struct_rt_metrics
+
+type Mclpool C.struct_mclpool
+
+// Berkeley packet filter
+
+const (
+	SizeofBpfVersion = C.sizeof_struct_bpf_version
+	SizeofBpfStat    = C.sizeof_struct_bpf_stat
+	SizeofBpfProgram = C.sizeof_struct_bpf_program
+	SizeofBpfInsn    = C.sizeof_struct_bpf_insn
+	SizeofBpfHdr     = C.sizeof_struct_bpf_hdr
+)
+
+type BpfVersion C.struct_bpf_version
+
+type BpfStat C.struct_bpf_stat
+
+type BpfProgram C.struct_bpf_program
+
+type BpfInsn C.struct_bpf_insn
+
+type BpfHdr C.struct_bpf_hdr
+
+type BpfTimeval C.struct_bpf_timeval
diff --git a/src/pkg/syscall/types_openbsd.c b/src/pkg/syscall/types_openbsd.c
deleted file mode 100644
index e51c64e..0000000
--- a/src/pkg/syscall/types_openbsd.c
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Input to godefs.  See also mkerrors.sh and mkall.sh
- */
-
-#define KERNEL
-#include <dirent.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/ptrace.h>
-#include <sys/resource.h>
-#include <sys/select.h>
-#include <sys/signal.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <net/bpf.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/route.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-// Machine characteristics; for internal use.
-
-enum {
-	$sizeofPtr = sizeof(void*),
-	$sizeofShort = sizeof(short),
-	$sizeofInt = sizeof(int),
-	$sizeofLong = sizeof(long),
-	$sizeofLongLong = sizeof(long long),
-};
-
-// Basic types
-
-typedef short $_C_short;
-typedef int $_C_int;
-typedef long $_C_long;
-typedef long long $_C_long_long;
-
-// Time
-
-typedef struct timespec $Timespec;
-typedef struct timeval $Timeval;
-
-// Processes
-
-typedef struct rusage $Rusage;
-typedef struct rlimit $Rlimit;
-
-typedef gid_t $_Gid_t;
-
-// Files
-
-enum {	// Directory mode bits
-	$S_IFMT = S_IFMT,
-	$S_IFIFO = S_IFIFO,
-	$S_IFCHR = S_IFCHR,
-	$S_IFDIR = S_IFDIR,
-	$S_IFBLK = S_IFBLK,
-	$S_IFREG = S_IFREG,
-	$S_IFLNK = S_IFLNK,
-	$S_IFSOCK = S_IFSOCK,
-	$S_ISUID = S_ISUID,
-	$S_ISGID = S_ISGID,
-	$S_ISVTX = S_ISVTX,
-	$S_IRUSR = S_IRUSR,
-	$S_IWUSR = S_IWUSR,
-	$S_IXUSR = S_IXUSR,
-};
-
-typedef struct stat $Stat_t;
-typedef struct statfs $Statfs_t;
-typedef struct flock $Flock_t;
-
-typedef struct dirent $Dirent;
-
-// Sockets
-
-union sockaddr_all {
-	struct sockaddr s1;	// this one gets used for fields
-	struct sockaddr_in s2;	// these pad it out
-	struct sockaddr_in6 s3;
-	struct sockaddr_un s4;
-	struct sockaddr_dl s5;
-};
-
-struct sockaddr_any {
-	struct sockaddr addr;
-	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
-};
-
-typedef struct sockaddr_in $RawSockaddrInet4;
-typedef struct sockaddr_in6 $RawSockaddrInet6;
-typedef struct sockaddr_un $RawSockaddrUnix;
-typedef struct sockaddr_dl $RawSockaddrDatalink;
-typedef struct sockaddr $RawSockaddr;
-typedef struct sockaddr_any $RawSockaddrAny;
-typedef socklen_t $_Socklen;
-typedef struct linger $Linger;
-typedef struct iovec $Iovec;
-typedef struct ip_mreq $IPMreq;
-typedef struct ipv6_mreq $IPv6Mreq;
-typedef struct msghdr $Msghdr;
-typedef struct cmsghdr $Cmsghdr;
-typedef struct in6_pktinfo $Inet6Pktinfo;
-
-enum {
-	$SizeofSockaddrInet4 = sizeof(struct sockaddr_in),
-	$SizeofSockaddrInet6 = sizeof(struct sockaddr_in6),
-	$SizeofSockaddrAny = sizeof(struct sockaddr_any),
-	$SizeofSockaddrUnix = sizeof(struct sockaddr_un),
-	$SizeofSockaddrDatalink = sizeof(struct sockaddr_dl),
-	$SizeofLinger = sizeof(struct linger),
-	$SizeofIPMreq = sizeof(struct ip_mreq),
-	$SizeofIPv6Mreq = sizeof(struct ipv6_mreq),
-	$SizeofMsghdr = sizeof(struct msghdr),
-	$SizeofCmsghdr = sizeof(struct cmsghdr),
-	$SizeofInet6Pktinfo = sizeof(struct in6_pktinfo),
-};
-
-// Ptrace requests
-
-enum {
-	$PTRACE_TRACEME = PT_TRACE_ME,
-	$PTRACE_CONT = PT_CONTINUE,
-	$PTRACE_KILL = PT_KILL,
-};
-
-// Events (kqueue, kevent)
-
-typedef struct kevent $Kevent_t;
-
-// Select
-
-typedef fd_set $FdSet;
-
-// Routing and interface messages
-
-enum {
-	$SizeofIfMsghdr = sizeof(struct if_msghdr),
-	$SizeofIfData = sizeof(struct if_data),
-	$SizeofIfaMsghdr = sizeof(struct ifa_msghdr),
-	$SizeofRtMsghdr = sizeof(struct rt_msghdr),
-	$SizeofRtMetrics = sizeof(struct rt_metrics),
-};
-
-typedef struct if_msghdr $IfMsghdr;
-typedef struct if_data $IfData;
-typedef struct ifa_msghdr $IfaMsghdr;
-typedef struct rt_msghdr $RtMsghdr;
-typedef struct rt_metrics $RtMetrics;
-
-// Berkeley packet filter
-
-enum {
-	$SizeofBpfVersion = sizeof(struct bpf_version),
-	$SizeofBpfStat = sizeof(struct bpf_stat),
-	$SizeofBpfProgram = sizeof(struct bpf_program),
-	$SizeofBpfInsn = sizeof(struct bpf_insn),
-	$SizeofBpfHdr = sizeof(struct bpf_hdr),
-};
-
-typedef struct bpf_version $BpfVersion;
-typedef struct bpf_stat $BpfStat;
-typedef struct bpf_program $BpfProgram;
-typedef struct bpf_insn $BpfInsn;
-typedef struct bpf_hdr $BpfHdr;
-typedef struct bpf_timeval $BpfTimeval;
diff --git a/src/pkg/syscall/types_openbsd.go b/src/pkg/syscall/types_openbsd.go
new file mode 100644
index 0000000..6f7ef35
--- /dev/null
+++ b/src/pkg/syscall/types_openbsd.go
@@ -0,0 +1,229 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Input to cgo -godefs.  See also mkerrors.sh and mkall.sh
+*/
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package syscall
+
+/*
+#define KERNEL
+#include <dirent.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+enum {
+	sizeofPtr = sizeof(void*),
+};
+
+union sockaddr_all {
+	struct sockaddr s1;	// this one gets used for fields
+	struct sockaddr_in s2;	// these pad it out
+	struct sockaddr_in6 s3;
+	struct sockaddr_un s4;
+	struct sockaddr_dl s5;
+};
+
+struct sockaddr_any {
+	struct sockaddr addr;
+	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+*/
+import "C"
+
+// Machine characteristics; for internal use.
+
+const (
+	sizeofPtr      = C.sizeofPtr
+	sizeofShort    = C.sizeof_short
+	sizeofInt      = C.sizeof_int
+	sizeofLong     = C.sizeof_long
+	sizeofLongLong = C.sizeof_longlong
+)
+
+// Basic types
+
+type (
+	_C_short     C.short
+	_C_int       C.int
+	_C_long      C.long
+	_C_long_long C.longlong
+)
+
+// Time
+
+type Timespec C.struct_timespec
+
+type Timeval C.struct_timeval
+
+// Processes
+
+type Rusage C.struct_rusage
+
+type Rlimit C.struct_rlimit
+
+type _Gid_t C.gid_t
+
+// Files
+
+const ( // Directory mode bits
+	S_IFMT   = C.S_IFMT
+	S_IFIFO  = C.S_IFIFO
+	S_IFCHR  = C.S_IFCHR
+	S_IFDIR  = C.S_IFDIR
+	S_IFBLK  = C.S_IFBLK
+	S_IFREG  = C.S_IFREG
+	S_IFLNK  = C.S_IFLNK
+	S_IFSOCK = C.S_IFSOCK
+	S_ISUID  = C.S_ISUID
+	S_ISGID  = C.S_ISGID
+	S_ISVTX  = C.S_ISVTX
+	S_IRUSR  = C.S_IRUSR
+	S_IWUSR  = C.S_IWUSR
+	S_IXUSR  = C.S_IXUSR
+)
+
+type Stat_t C.struct_stat
+
+type Statfs_t C.struct_statfs
+
+type Flock_t C.struct_flock
+
+type Dirent C.struct_dirent
+
+type Fsid C.fsid_t
+
+// Sockets
+
+type RawSockaddrInet4 C.struct_sockaddr_in
+
+type RawSockaddrInet6 C.struct_sockaddr_in6
+
+type RawSockaddrUnix C.struct_sockaddr_un
+
+type RawSockaddrDatalink C.struct_sockaddr_dl
+
+type RawSockaddr C.struct_sockaddr
+
+type RawSockaddrAny C.struct_sockaddr_any
+
+type _Socklen C.socklen_t
+
+type Linger C.struct_linger
+
+type Iovec C.struct_iovec
+
+type IPMreq C.struct_ip_mreq
+
+type IPv6Mreq C.struct_ipv6_mreq
+
+type Msghdr C.struct_msghdr
+
+type Cmsghdr C.struct_cmsghdr
+
+type Inet6Pktinfo C.struct_in6_pktinfo
+
+const (
+	SizeofSockaddrInet4    = C.sizeof_struct_sockaddr_in
+	SizeofSockaddrInet6    = C.sizeof_struct_sockaddr_in6
+	SizeofSockaddrAny      = C.sizeof_struct_sockaddr_any
+	SizeofSockaddrUnix     = C.sizeof_struct_sockaddr_un
+	SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
+	SizeofLinger           = C.sizeof_struct_linger
+	SizeofIPMreq           = C.sizeof_struct_ip_mreq
+	SizeofIPv6Mreq         = C.sizeof_struct_ipv6_mreq
+	SizeofMsghdr           = C.sizeof_struct_msghdr
+	SizeofCmsghdr          = C.sizeof_struct_cmsghdr
+	SizeofInet6Pktinfo     = C.sizeof_struct_in6_pktinfo
+)
+
+// Ptrace requests
+
+const (
+	PTRACE_TRACEME = C.PT_TRACE_ME
+	PTRACE_CONT    = C.PT_CONTINUE
+	PTRACE_KILL    = C.PT_KILL
+)
+
+// Events (kqueue, kevent)
+
+type Kevent_t C.struct_kevent
+
+// Select
+
+type FdSet C.fd_set
+
+// Routing and interface messages
+
+const (
+	SizeofIfMsghdr  = C.sizeof_struct_if_msghdr
+	SizeofIfData    = C.sizeof_struct_if_data
+	SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr
+	SizeofRtMsghdr  = C.sizeof_struct_rt_msghdr
+	SizeofRtMetrics = C.sizeof_struct_rt_metrics
+)
+
+type IfMsghdr C.struct_if_msghdr
+
+type IfData C.struct_if_data
+
+type IfaMsghdr C.struct_ifa_msghdr
+
+type RtMsghdr C.struct_rt_msghdr
+
+type RtMetrics C.struct_rt_metrics
+
+type Mclpool C.struct_mclpool
+
+// Berkeley packet filter
+
+const (
+	SizeofBpfVersion = C.sizeof_struct_bpf_version
+	SizeofBpfStat    = C.sizeof_struct_bpf_stat
+	SizeofBpfProgram = C.sizeof_struct_bpf_program
+	SizeofBpfInsn    = C.sizeof_struct_bpf_insn
+	SizeofBpfHdr     = C.sizeof_struct_bpf_hdr
+)
+
+type BpfVersion C.struct_bpf_version
+
+type BpfStat C.struct_bpf_stat
+
+type BpfProgram C.struct_bpf_program
+
+type BpfInsn C.struct_bpf_insn
+
+type BpfHdr C.struct_bpf_hdr
+
+type BpfTimeval C.struct_bpf_timeval
diff --git a/src/pkg/syscall/types_plan9.c b/src/pkg/syscall/types_plan9.c
index 1da9d37..cd9e15f 100644
--- a/src/pkg/syscall/types_plan9.c
+++ b/src/pkg/syscall/types_plan9.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build ignore
+
 /*
 Input to godefs.  See also mkerrors.sh and mkall.sh
 */
diff --git a/src/pkg/syscall/zerrors_darwin_386.go b/src/pkg/syscall/zerrors_darwin_386.go
index a769fd3..59a1f39 100644
--- a/src/pkg/syscall/zerrors_darwin_386.go
+++ b/src/pkg/syscall/zerrors_darwin_386.go
@@ -1,1091 +1,1179 @@
-// mkerrors.sh -f -m32
+// mkerrors.sh -m32
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -f -m32 -gsyscall -f -m32 _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m32 _const.go
 
 package syscall
 
-// Constants
 const (
-	AF_APPLETALK                = 0x10
-	AF_CCITT                    = 0xa
-	AF_CHAOS                    = 0x5
-	AF_CNT                      = 0x15
-	AF_COIP                     = 0x14
-	AF_DATAKIT                  = 0x9
-	AF_DECnet                   = 0xc
-	AF_DLI                      = 0xd
-	AF_E164                     = 0x1c
-	AF_ECMA                     = 0x8
-	AF_HYLINK                   = 0xf
-	AF_IEEE80211                = 0x25
-	AF_IMPLINK                  = 0x3
-	AF_INET                     = 0x2
-	AF_INET6                    = 0x1e
-	AF_IPX                      = 0x17
-	AF_ISDN                     = 0x1c
-	AF_ISO                      = 0x7
-	AF_LAT                      = 0xe
-	AF_LINK                     = 0x12
-	AF_LOCAL                    = 0x1
-	AF_MAX                      = 0x26
-	AF_NATM                     = 0x1f
-	AF_NDRV                     = 0x1b
-	AF_NETBIOS                  = 0x21
-	AF_NS                       = 0x6
-	AF_OSI                      = 0x7
-	AF_PPP                      = 0x22
-	AF_PUP                      = 0x4
-	AF_RESERVED_36              = 0x24
-	AF_ROUTE                    = 0x11
-	AF_SIP                      = 0x18
-	AF_SNA                      = 0xb
-	AF_SYSTEM                   = 0x20
-	AF_UNIX                     = 0x1
-	AF_UNSPEC                   = 0
-	BIOCFLUSH                   = 0x20004268
-	BIOCGBLEN                   = 0x40044266
-	BIOCGDLT                    = 0x4004426a
-	BIOCGDLTLIST                = 0xc00c4279
-	BIOCGETIF                   = 0x4020426b
-	BIOCGHDRCMPLT               = 0x40044274
-	BIOCGRSIG                   = 0x40044272
-	BIOCGRTIMEOUT               = 0x4008426e
-	BIOCGSEESENT                = 0x40044276
-	BIOCGSTATS                  = 0x4008426f
-	BIOCIMMEDIATE               = 0x80044270
-	BIOCPROMISC                 = 0x20004269
-	BIOCSBLEN                   = 0xc0044266
-	BIOCSDLT                    = 0x80044278
-	BIOCSETF                    = 0x80084267
-	BIOCSETIF                   = 0x8020426c
-	BIOCSHDRCMPLT               = 0x80044275
-	BIOCSRSIG                   = 0x80044273
-	BIOCSRTIMEOUT               = 0x8008426d
-	BIOCSSEESENT                = 0x80044277
-	BIOCVERSION                 = 0x40044271
-	BPF_A                       = 0x10
-	BPF_ABS                     = 0x20
-	BPF_ADD                     = 0
-	BPF_ALIGNMENT               = 0x4
-	BPF_ALU                     = 0x4
-	BPF_AND                     = 0x50
-	BPF_B                       = 0x10
-	BPF_DIV                     = 0x30
-	BPF_H                       = 0x8
-	BPF_IMM                     = 0
-	BPF_IND                     = 0x40
-	BPF_JA                      = 0
-	BPF_JEQ                     = 0x10
-	BPF_JGE                     = 0x30
-	BPF_JGT                     = 0x20
-	BPF_JMP                     = 0x5
-	BPF_JSET                    = 0x40
-	BPF_K                       = 0
-	BPF_LD                      = 0
-	BPF_LDX                     = 0x1
-	BPF_LEN                     = 0x80
-	BPF_LSH                     = 0x60
-	BPF_MAJOR_VERSION           = 0x1
-	BPF_MAXBUFSIZE              = 0x80000
-	BPF_MAXINSNS                = 0x200
-	BPF_MEM                     = 0x60
-	BPF_MEMWORDS                = 0x10
-	BPF_MINBUFSIZE              = 0x20
-	BPF_MINOR_VERSION           = 0x1
-	BPF_MISC                    = 0x7
-	BPF_MSH                     = 0xa0
-	BPF_MUL                     = 0x20
-	BPF_NEG                     = 0x80
-	BPF_OR                      = 0x40
-	BPF_RELEASE                 = 0x30bb6
-	BPF_RET                     = 0x6
-	BPF_RSH                     = 0x70
-	BPF_ST                      = 0x2
-	BPF_STX                     = 0x3
-	BPF_SUB                     = 0x10
-	BPF_TAX                     = 0
-	BPF_TXA                     = 0x80
-	BPF_W                       = 0
-	BPF_X                       = 0x8
-	CTL_MAXNAME                 = 0xc
-	CTL_NET                     = 0x4
-	DLT_APPLE_IP_OVER_IEEE1394  = 0x8a
-	DLT_ARCNET                  = 0x7
-	DLT_ATM_CLIP                = 0x13
-	DLT_ATM_RFC1483             = 0xb
-	DLT_AX25                    = 0x3
-	DLT_CHAOS                   = 0x5
-	DLT_CHDLC                   = 0x68
-	DLT_C_HDLC                  = 0x68
-	DLT_EN10MB                  = 0x1
-	DLT_EN3MB                   = 0x2
-	DLT_FDDI                    = 0xa
-	DLT_IEEE802                 = 0x6
-	DLT_IEEE802_11              = 0x69
-	DLT_IEEE802_11_RADIO        = 0x7f
-	DLT_IEEE802_11_RADIO_AVS    = 0xa3
-	DLT_LINUX_SLL               = 0x71
-	DLT_LOOP                    = 0x6c
-	DLT_NULL                    = 0
-	DLT_PFLOG                   = 0x75
-	DLT_PFSYNC                  = 0x12
-	DLT_PPP                     = 0x9
-	DLT_PPP_BSDOS               = 0x10
-	DLT_PPP_SERIAL              = 0x32
-	DLT_PRONET                  = 0x4
-	DLT_RAW                     = 0xc
-	DLT_SLIP                    = 0x8
-	DLT_SLIP_BSDOS              = 0xf
-	DT_BLK                      = 0x6
-	DT_CHR                      = 0x2
-	DT_DIR                      = 0x4
-	DT_FIFO                     = 0x1
-	DT_LNK                      = 0xa
-	DT_REG                      = 0x8
-	DT_SOCK                     = 0xc
-	DT_UNKNOWN                  = 0
-	DT_WHT                      = 0xe
-	E2BIG                       = 0x7
-	EACCES                      = 0xd
-	EADDRINUSE                  = 0x30
-	EADDRNOTAVAIL               = 0x31
-	EAFNOSUPPORT                = 0x2f
-	EAGAIN                      = 0x23
-	EALREADY                    = 0x25
-	EAUTH                       = 0x50
-	EBADARCH                    = 0x56
-	EBADEXEC                    = 0x55
-	EBADF                       = 0x9
-	EBADMACHO                   = 0x58
-	EBADMSG                     = 0x5e
-	EBADRPC                     = 0x48
-	EBUSY                       = 0x10
-	ECANCELED                   = 0x59
-	ECHILD                      = 0xa
-	ECHO                        = 0x8
-	ECHOCTL                     = 0x40
-	ECHOE                       = 0x2
-	ECHOK                       = 0x4
-	ECHOKE                      = 0x1
-	ECHONL                      = 0x10
-	ECHOPRT                     = 0x20
-	ECONNABORTED                = 0x35
-	ECONNREFUSED                = 0x3d
-	ECONNRESET                  = 0x36
-	EDEADLK                     = 0xb
-	EDESTADDRREQ                = 0x27
-	EDEVERR                     = 0x53
-	EDOM                        = 0x21
-	EDQUOT                      = 0x45
-	EEXIST                      = 0x11
-	EFAULT                      = 0xe
-	EFBIG                       = 0x1b
-	EFTYPE                      = 0x4f
-	EHOSTDOWN                   = 0x40
-	EHOSTUNREACH                = 0x41
-	EIDRM                       = 0x5a
-	EILSEQ                      = 0x5c
-	EINPROGRESS                 = 0x24
-	EINTR                       = 0x4
-	EINVAL                      = 0x16
-	EIO                         = 0x5
-	EISCONN                     = 0x38
-	EISDIR                      = 0x15
-	ELAST                       = 0x67
-	ELOOP                       = 0x3e
-	EMFILE                      = 0x18
-	EMLINK                      = 0x1f
-	EMSGSIZE                    = 0x28
-	EMULTIHOP                   = 0x5f
-	ENAMETOOLONG                = 0x3f
-	ENEEDAUTH                   = 0x51
-	ENETDOWN                    = 0x32
-	ENETRESET                   = 0x34
-	ENETUNREACH                 = 0x33
-	ENFILE                      = 0x17
-	ENOATTR                     = 0x5d
-	ENOBUFS                     = 0x37
-	ENODATA                     = 0x60
-	ENODEV                      = 0x13
-	ENOENT                      = 0x2
-	ENOEXEC                     = 0x8
-	ENOLCK                      = 0x4d
-	ENOLINK                     = 0x61
-	ENOMEM                      = 0xc
-	ENOMSG                      = 0x5b
-	ENOPOLICY                   = 0x67
-	ENOPROTOOPT                 = 0x2a
-	ENOSPC                      = 0x1c
-	ENOSR                       = 0x62
-	ENOSTR                      = 0x63
-	ENOSYS                      = 0x4e
-	ENOTBLK                     = 0xf
-	ENOTCONN                    = 0x39
-	ENOTDIR                     = 0x14
-	ENOTEMPTY                   = 0x42
-	ENOTSOCK                    = 0x26
-	ENOTSUP                     = 0x2d
-	ENOTTY                      = 0x19
-	ENXIO                       = 0x6
-	EOPNOTSUPP                  = 0x66
-	EOVERFLOW                   = 0x54
-	EPERM                       = 0x1
-	EPFNOSUPPORT                = 0x2e
-	EPIPE                       = 0x20
-	EPROCLIM                    = 0x43
-	EPROCUNAVAIL                = 0x4c
-	EPROGMISMATCH               = 0x4b
-	EPROGUNAVAIL                = 0x4a
-	EPROTO                      = 0x64
-	EPROTONOSUPPORT             = 0x2b
-	EPROTOTYPE                  = 0x29
-	EPWROFF                     = 0x52
-	ERANGE                      = 0x22
-	EREMOTE                     = 0x47
-	EROFS                       = 0x1e
-	ERPCMISMATCH                = 0x49
-	ESHLIBVERS                  = 0x57
-	ESHUTDOWN                   = 0x3a
-	ESOCKTNOSUPPORT             = 0x2c
-	ESPIPE                      = 0x1d
-	ESRCH                       = 0x3
-	ESTALE                      = 0x46
-	ETIME                       = 0x65
-	ETIMEDOUT                   = 0x3c
-	ETOOMANYREFS                = 0x3b
-	ETXTBSY                     = 0x1a
-	EUSERS                      = 0x44
-	EVFILT_AIO                  = -0x3
-	EVFILT_FS                   = -0x9
-	EVFILT_MACHPORT             = -0x8
-	EVFILT_PROC                 = -0x5
-	EVFILT_READ                 = -0x1
-	EVFILT_SESSION              = -0xb
-	EVFILT_SIGNAL               = -0x6
-	EVFILT_SYSCOUNT             = 0xb
-	EVFILT_THREADMARKER         = 0xb
-	EVFILT_TIMER                = -0x7
-	EVFILT_USER                 = -0xa
-	EVFILT_VNODE                = -0x4
-	EVFILT_WRITE                = -0x2
-	EV_ADD                      = 0x1
-	EV_CLEAR                    = 0x20
-	EV_DELETE                   = 0x2
-	EV_DISABLE                  = 0x8
-	EV_DISPATCH                 = 0x80
-	EV_ENABLE                   = 0x4
-	EV_EOF                      = 0x8000
-	EV_ERROR                    = 0x4000
-	EV_FLAG0                    = 0x1000
-	EV_FLAG1                    = 0x2000
-	EV_ONESHOT                  = 0x10
-	EV_OOBAND                   = 0x2000
-	EV_POLL                     = 0x1000
-	EV_RECEIPT                  = 0x40
-	EV_SYSFLAGS                 = 0xf000
-	EV_TRIGGER                  = 0x100
-	EWOULDBLOCK                 = 0x23
-	EXDEV                       = 0x12
-	EXTA                        = 0x4b00
-	EXTB                        = 0x9600
-	EXTPROC                     = 0x800
-	FD_CLOEXEC                  = 0x1
-	FD_SETSIZE                  = 0x400
-	F_ADDFILESIGS               = 0x3d
-	F_ADDSIGS                   = 0x3b
-	F_ALLOCATEALL               = 0x4
-	F_ALLOCATECONTIG            = 0x2
-	F_CHKCLEAN                  = 0x29
-	F_DUPFD                     = 0
-	F_FREEZE_FS                 = 0x35
-	F_FULLFSYNC                 = 0x33
-	F_GETFD                     = 0x1
-	F_GETFL                     = 0x3
-	F_GETLK                     = 0x7
-	F_GETOWN                    = 0x5
-	F_GETPATH                   = 0x32
-	F_GETPROTECTIONCLASS        = 0x3e
-	F_GLOBAL_NOCACHE            = 0x37
-	F_LOG2PHYS                  = 0x31
-	F_MARKDEPENDENCY            = 0x3c
-	F_NOCACHE                   = 0x30
-	F_PATHPKG_CHECK             = 0x34
-	F_PEOFPOSMODE               = 0x3
-	F_PREALLOCATE               = 0x2a
-	F_RDADVISE                  = 0x2c
-	F_RDAHEAD                   = 0x2d
-	F_RDLCK                     = 0x1
-	F_READBOOTSTRAP             = 0x2e
-	F_SETFD                     = 0x2
-	F_SETFL                     = 0x4
-	F_SETLK                     = 0x8
-	F_SETLKW                    = 0x9
-	F_SETOWN                    = 0x6
-	F_SETPROTECTIONCLASS        = 0x3f
-	F_SETSIZE                   = 0x2b
-	F_THAW_FS                   = 0x36
-	F_UNLCK                     = 0x2
-	F_VOLPOSMODE                = 0x4
-	F_WRITEBOOTSTRAP            = 0x2f
-	F_WRLCK                     = 0x3
-	IFF_ALLMULTI                = 0x200
-	IFF_ALTPHYS                 = 0x4000
-	IFF_BROADCAST               = 0x2
-	IFF_DEBUG                   = 0x4
-	IFF_LINK0                   = 0x1000
-	IFF_LINK1                   = 0x2000
-	IFF_LINK2                   = 0x4000
-	IFF_LOOPBACK                = 0x8
-	IFF_MULTICAST               = 0x8000
-	IFF_NOARP                   = 0x80
-	IFF_NOTRAILERS              = 0x20
-	IFF_OACTIVE                 = 0x400
-	IFF_POINTOPOINT             = 0x10
-	IFF_PROMISC                 = 0x100
-	IFF_RUNNING                 = 0x40
-	IFF_SIMPLEX                 = 0x800
-	IFF_UP                      = 0x1
-	IFNAMSIZ                    = 0x10
-	IFT_1822                    = 0x2
-	IFT_AAL5                    = 0x31
-	IFT_ARCNET                  = 0x23
-	IFT_ARCNETPLUS              = 0x24
-	IFT_ATM                     = 0x25
-	IFT_BRIDGE                  = 0xd1
-	IFT_CARP                    = 0xf8
-	IFT_CEPT                    = 0x13
-	IFT_DS3                     = 0x1e
-	IFT_ENC                     = 0xf4
-	IFT_EON                     = 0x19
-	IFT_ETHER                   = 0x6
-	IFT_FAITH                   = 0x38
-	IFT_FDDI                    = 0xf
-	IFT_FRELAY                  = 0x20
-	IFT_FRELAYDCE               = 0x2c
-	IFT_GIF                     = 0x37
-	IFT_HDH1822                 = 0x3
-	IFT_HIPPI                   = 0x2f
-	IFT_HSSI                    = 0x2e
-	IFT_HY                      = 0xe
-	IFT_IEEE1394                = 0x90
-	IFT_IEEE8023ADLAG           = 0x88
-	IFT_ISDNBASIC               = 0x14
-	IFT_ISDNPRIMARY             = 0x15
-	IFT_ISO88022LLC             = 0x29
-	IFT_ISO88023                = 0x7
-	IFT_ISO88024                = 0x8
-	IFT_ISO88025                = 0x9
-	IFT_ISO88026                = 0xa
-	IFT_L2VLAN                  = 0x87
-	IFT_LAPB                    = 0x10
-	IFT_LOCALTALK               = 0x2a
-	IFT_LOOP                    = 0x18
-	IFT_MIOX25                  = 0x26
-	IFT_MODEM                   = 0x30
-	IFT_NSIP                    = 0x1b
-	IFT_OTHER                   = 0x1
-	IFT_P10                     = 0xc
-	IFT_P80                     = 0xd
-	IFT_PARA                    = 0x22
-	IFT_PDP                     = 0xff
-	IFT_PFLOG                   = 0xf5
-	IFT_PFSYNC                  = 0xf6
-	IFT_PPP                     = 0x17
-	IFT_PROPMUX                 = 0x36
-	IFT_PROPVIRTUAL             = 0x35
-	IFT_PTPSERIAL               = 0x16
-	IFT_RS232                   = 0x21
-	IFT_SDLC                    = 0x11
-	IFT_SIP                     = 0x1f
-	IFT_SLIP                    = 0x1c
-	IFT_SMDSDXI                 = 0x2b
-	IFT_SMDSICIP                = 0x34
-	IFT_SONET                   = 0x27
-	IFT_SONETPATH               = 0x32
-	IFT_SONETVT                 = 0x33
-	IFT_STARLAN                 = 0xb
-	IFT_STF                     = 0x39
-	IFT_T1                      = 0x12
-	IFT_ULTRA                   = 0x1d
-	IFT_V35                     = 0x2d
-	IFT_X25                     = 0x5
-	IFT_X25DDN                  = 0x4
-	IFT_X25PLE                  = 0x28
-	IFT_XETHER                  = 0x1a
-	IN_CLASSA_HOST              = 0xffffff
-	IN_CLASSA_MAX               = 0x80
-	IN_CLASSA_NET               = 0xff000000
-	IN_CLASSA_NSHIFT            = 0x18
-	IN_CLASSB_HOST              = 0xffff
-	IN_CLASSB_MAX               = 0x10000
-	IN_CLASSB_NET               = 0xffff0000
-	IN_CLASSB_NSHIFT            = 0x10
-	IN_CLASSC_HOST              = 0xff
-	IN_CLASSC_NET               = 0xffffff00
-	IN_CLASSC_NSHIFT            = 0x8
-	IN_CLASSD_HOST              = 0xfffffff
-	IN_CLASSD_NET               = 0xf0000000
-	IN_CLASSD_NSHIFT            = 0x1c
-	IN_LINKLOCALNETNUM          = 0xa9fe0000
-	IN_LOOPBACKNET              = 0x7f
-	IPPROTO_3PC                 = 0x22
-	IPPROTO_ADFS                = 0x44
-	IPPROTO_AH                  = 0x33
-	IPPROTO_AHIP                = 0x3d
-	IPPROTO_APES                = 0x63
-	IPPROTO_ARGUS               = 0xd
-	IPPROTO_AX25                = 0x5d
-	IPPROTO_BHA                 = 0x31
-	IPPROTO_BLT                 = 0x1e
-	IPPROTO_BRSATMON            = 0x4c
-	IPPROTO_CFTP                = 0x3e
-	IPPROTO_CHAOS               = 0x10
-	IPPROTO_CMTP                = 0x26
-	IPPROTO_CPHB                = 0x49
-	IPPROTO_CPNX                = 0x48
-	IPPROTO_DDP                 = 0x25
-	IPPROTO_DGP                 = 0x56
-	IPPROTO_DIVERT              = 0xfe
-	IPPROTO_DONE                = 0x101
-	IPPROTO_DSTOPTS             = 0x3c
-	IPPROTO_EGP                 = 0x8
-	IPPROTO_EMCON               = 0xe
-	IPPROTO_ENCAP               = 0x62
-	IPPROTO_EON                 = 0x50
-	IPPROTO_ESP                 = 0x32
-	IPPROTO_ETHERIP             = 0x61
-	IPPROTO_FRAGMENT            = 0x2c
-	IPPROTO_GGP                 = 0x3
-	IPPROTO_GMTP                = 0x64
-	IPPROTO_GRE                 = 0x2f
-	IPPROTO_HELLO               = 0x3f
-	IPPROTO_HMP                 = 0x14
-	IPPROTO_HOPOPTS             = 0
-	IPPROTO_ICMP                = 0x1
-	IPPROTO_ICMPV6              = 0x3a
-	IPPROTO_IDP                 = 0x16
-	IPPROTO_IDPR                = 0x23
-	IPPROTO_IDRP                = 0x2d
-	IPPROTO_IGMP                = 0x2
-	IPPROTO_IGP                 = 0x55
-	IPPROTO_IGRP                = 0x58
-	IPPROTO_IL                  = 0x28
-	IPPROTO_INLSP               = 0x34
-	IPPROTO_INP                 = 0x20
-	IPPROTO_IP                  = 0
-	IPPROTO_IPCOMP              = 0x6c
-	IPPROTO_IPCV                = 0x47
-	IPPROTO_IPEIP               = 0x5e
-	IPPROTO_IPIP                = 0x4
-	IPPROTO_IPPC                = 0x43
-	IPPROTO_IPV4                = 0x4
-	IPPROTO_IPV6                = 0x29
-	IPPROTO_IRTP                = 0x1c
-	IPPROTO_KRYPTOLAN           = 0x41
-	IPPROTO_LARP                = 0x5b
-	IPPROTO_LEAF1               = 0x19
-	IPPROTO_LEAF2               = 0x1a
-	IPPROTO_MAX                 = 0x100
-	IPPROTO_MAXID               = 0x34
-	IPPROTO_MEAS                = 0x13
-	IPPROTO_MHRP                = 0x30
-	IPPROTO_MICP                = 0x5f
-	IPPROTO_MTP                 = 0x5c
-	IPPROTO_MUX                 = 0x12
-	IPPROTO_ND                  = 0x4d
-	IPPROTO_NHRP                = 0x36
-	IPPROTO_NONE                = 0x3b
-	IPPROTO_NSP                 = 0x1f
-	IPPROTO_NVPII               = 0xb
-	IPPROTO_OSPFIGP             = 0x59
-	IPPROTO_PGM                 = 0x71
-	IPPROTO_PIGP                = 0x9
-	IPPROTO_PIM                 = 0x67
-	IPPROTO_PRM                 = 0x15
-	IPPROTO_PUP                 = 0xc
-	IPPROTO_PVP                 = 0x4b
-	IPPROTO_RAW                 = 0xff
-	IPPROTO_RCCMON              = 0xa
-	IPPROTO_RDP                 = 0x1b
-	IPPROTO_ROUTING             = 0x2b
-	IPPROTO_RSVP                = 0x2e
-	IPPROTO_RVD                 = 0x42
-	IPPROTO_SATEXPAK            = 0x40
-	IPPROTO_SATMON              = 0x45
-	IPPROTO_SCCSP               = 0x60
-	IPPROTO_SDRP                = 0x2a
-	IPPROTO_SEP                 = 0x21
-	IPPROTO_SRPC                = 0x5a
-	IPPROTO_ST                  = 0x7
-	IPPROTO_SVMTP               = 0x52
-	IPPROTO_SWIPE               = 0x35
-	IPPROTO_TCF                 = 0x57
-	IPPROTO_TCP                 = 0x6
-	IPPROTO_TP                  = 0x1d
-	IPPROTO_TPXX                = 0x27
-	IPPROTO_TRUNK1              = 0x17
-	IPPROTO_TRUNK2              = 0x18
-	IPPROTO_TTP                 = 0x54
-	IPPROTO_UDP                 = 0x11
-	IPPROTO_VINES               = 0x53
-	IPPROTO_VISA                = 0x46
-	IPPROTO_VMTP                = 0x51
-	IPPROTO_WBEXPAK             = 0x4f
-	IPPROTO_WBMON               = 0x4e
-	IPPROTO_WSN                 = 0x4a
-	IPPROTO_XNET                = 0xf
-	IPPROTO_XTP                 = 0x24
-	IPV6_BINDV6ONLY             = 0x1b
-	IPV6_CHECKSUM               = 0x1a
-	IPV6_DEFAULT_MULTICAST_HOPS = 0x1
-	IPV6_DEFAULT_MULTICAST_LOOP = 0x1
-	IPV6_DEFHLIM                = 0x40
-	IPV6_DSTOPTS                = 0x17
-	IPV6_FAITH                  = 0x1d
-	IPV6_FLOWINFO_MASK          = 0xffffff0f
-	IPV6_FLOWLABEL_MASK         = 0xffff0f00
-	IPV6_FRAGTTL                = 0x78
-	IPV6_FW_ADD                 = 0x1e
-	IPV6_FW_DEL                 = 0x1f
-	IPV6_FW_FLUSH               = 0x20
-	IPV6_FW_GET                 = 0x22
-	IPV6_FW_ZERO                = 0x21
-	IPV6_HLIMDEC                = 0x1
-	IPV6_HOPLIMIT               = 0x14
-	IPV6_HOPOPTS                = 0x16
-	IPV6_IPSEC_POLICY           = 0x1c
-	IPV6_JOIN_GROUP             = 0xc
-	IPV6_LEAVE_GROUP            = 0xd
-	IPV6_MAXHLIM                = 0xff
-	IPV6_MAXPACKET              = 0xffff
-	IPV6_MMTU                   = 0x500
-	IPV6_MULTICAST_HOPS         = 0xa
-	IPV6_MULTICAST_IF           = 0x9
-	IPV6_MULTICAST_LOOP         = 0xb
-	IPV6_NEXTHOP                = 0x15
-	IPV6_PKTINFO                = 0x13
-	IPV6_PKTOPTIONS             = 0x19
-	IPV6_PORTRANGE              = 0xe
-	IPV6_PORTRANGE_DEFAULT      = 0
-	IPV6_PORTRANGE_HIGH         = 0x1
-	IPV6_PORTRANGE_LOW          = 0x2
-	IPV6_RECVTCLASS             = 0x23
-	IPV6_RTHDR                  = 0x18
-	IPV6_RTHDR_LOOSE            = 0
-	IPV6_RTHDR_STRICT           = 0x1
-	IPV6_RTHDR_TYPE_0           = 0
-	IPV6_SOCKOPT_RESERVED1      = 0x3
-	IPV6_TCLASS                 = 0x24
-	IPV6_UNICAST_HOPS           = 0x4
-	IPV6_V6ONLY                 = 0x1b
-	IPV6_VERSION                = 0x60
-	IPV6_VERSION_MASK           = 0xf0
-	IP_ADD_MEMBERSHIP           = 0xc
-	IP_BOUND_IF                 = 0x19
-	IP_DEFAULT_MULTICAST_LOOP   = 0x1
-	IP_DEFAULT_MULTICAST_TTL    = 0x1
-	IP_DF                       = 0x4000
-	IP_DROP_MEMBERSHIP          = 0xd
-	IP_DUMMYNET_CONFIGURE       = 0x3c
-	IP_DUMMYNET_DEL             = 0x3d
-	IP_DUMMYNET_FLUSH           = 0x3e
-	IP_DUMMYNET_GET             = 0x40
-	IP_FAITH                    = 0x16
-	IP_FW_ADD                   = 0x28
-	IP_FW_DEL                   = 0x29
-	IP_FW_FLUSH                 = 0x2a
-	IP_FW_GET                   = 0x2c
-	IP_FW_RESETLOG              = 0x2d
-	IP_FW_ZERO                  = 0x2b
-	IP_HDRINCL                  = 0x2
-	IP_IPSEC_POLICY             = 0x15
-	IP_MAXPACKET                = 0xffff
-	IP_MAX_MEMBERSHIPS          = 0x14
-	IP_MF                       = 0x2000
-	IP_MSS                      = 0x240
-	IP_MULTICAST_IF             = 0x9
-	IP_MULTICAST_LOOP           = 0xb
-	IP_MULTICAST_TTL            = 0xa
-	IP_MULTICAST_VIF            = 0xe
-	IP_NAT__XXX                 = 0x37
-	IP_OFFMASK                  = 0x1fff
-	IP_OLD_FW_ADD               = 0x32
-	IP_OLD_FW_DEL               = 0x33
-	IP_OLD_FW_FLUSH             = 0x34
-	IP_OLD_FW_GET               = 0x36
-	IP_OLD_FW_RESETLOG          = 0x38
-	IP_OLD_FW_ZERO              = 0x35
-	IP_OPTIONS                  = 0x1
-	IP_PORTRANGE                = 0x13
-	IP_PORTRANGE_DEFAULT        = 0
-	IP_PORTRANGE_HIGH           = 0x1
-	IP_PORTRANGE_LOW            = 0x2
-	IP_RECVDSTADDR              = 0x7
-	IP_RECVIF                   = 0x14
-	IP_RECVOPTS                 = 0x5
-	IP_RECVRETOPTS              = 0x6
-	IP_RECVTTL                  = 0x18
-	IP_RETOPTS                  = 0x8
-	IP_RF                       = 0x8000
-	IP_RSVP_OFF                 = 0x10
-	IP_RSVP_ON                  = 0xf
-	IP_RSVP_VIF_OFF             = 0x12
-	IP_RSVP_VIF_ON              = 0x11
-	IP_STRIPHDR                 = 0x17
-	IP_TOS                      = 0x3
-	IP_TRAFFIC_MGT_BACKGROUND   = 0x41
-	IP_TTL                      = 0x4
-	MADV_CAN_REUSE              = 0x9
-	MADV_DONTNEED               = 0x4
-	MADV_FREE                   = 0x5
-	MADV_FREE_REUSABLE          = 0x7
-	MADV_FREE_REUSE             = 0x8
-	MADV_NORMAL                 = 0
-	MADV_RANDOM                 = 0x1
-	MADV_SEQUENTIAL             = 0x2
-	MADV_WILLNEED               = 0x3
-	MADV_ZERO_WIRED_PAGES       = 0x6
-	MAP_ANON                    = 0x1000
-	MAP_COPY                    = 0x2
-	MAP_FILE                    = 0
-	MAP_FIXED                   = 0x10
-	MAP_HASSEMAPHORE            = 0x200
-	MAP_NOCACHE                 = 0x400
-	MAP_NOEXTEND                = 0x100
-	MAP_NORESERVE               = 0x40
-	MAP_PRIVATE                 = 0x2
-	MAP_RENAME                  = 0x20
-	MAP_RESERVED0080            = 0x80
-	MAP_SHARED                  = 0x1
-	MCL_CURRENT                 = 0x1
-	MCL_FUTURE                  = 0x2
-	MSG_CTRUNC                  = 0x20
-	MSG_DONTROUTE               = 0x4
-	MSG_DONTWAIT                = 0x80
-	MSG_EOF                     = 0x100
-	MSG_EOR                     = 0x8
-	MSG_FLUSH                   = 0x400
-	MSG_HAVEMORE                = 0x2000
-	MSG_HOLD                    = 0x800
-	MSG_NEEDSA                  = 0x10000
-	MSG_OOB                     = 0x1
-	MSG_PEEK                    = 0x2
-	MSG_RCVMORE                 = 0x4000
-	MSG_SEND                    = 0x1000
-	MSG_TRUNC                   = 0x10
-	MSG_WAITALL                 = 0x40
-	MSG_WAITSTREAM              = 0x200
-	MS_ASYNC                    = 0x1
-	MS_DEACTIVATE               = 0x8
-	MS_INVALIDATE               = 0x2
-	MS_KILLPAGES                = 0x4
-	MS_SYNC                     = 0x10
-	NAME_MAX                    = 0xff
-	NET_RT_DUMP                 = 0x1
-	NET_RT_DUMP2                = 0x7
-	NET_RT_FLAGS                = 0x2
-	NET_RT_IFLIST               = 0x3
-	NET_RT_IFLIST2              = 0x6
-	NET_RT_MAXID                = 0x8
-	NET_RT_STAT                 = 0x4
-	NET_RT_TRASH                = 0x5
-	O_ACCMODE                   = 0x3
-	O_ALERT                     = 0x20000000
-	O_APPEND                    = 0x8
-	O_ASYNC                     = 0x40
-	O_CREAT                     = 0x200
-	O_DIRECTORY                 = 0x100000
-	O_DSYNC                     = 0x400000
-	O_EVTONLY                   = 0x8000
-	O_EXCL                      = 0x800
-	O_EXLOCK                    = 0x20
-	O_FSYNC                     = 0x80
-	O_NDELAY                    = 0x4
-	O_NOCTTY                    = 0x20000
-	O_NOFOLLOW                  = 0x100
-	O_NONBLOCK                  = 0x4
-	O_POPUP                     = 0x80000000
-	O_RDONLY                    = 0
-	O_RDWR                      = 0x2
-	O_SHLOCK                    = 0x10
-	O_SYMLINK                   = 0x200000
-	O_SYNC                      = 0x80
-	O_TRUNC                     = 0x400
-	O_WRONLY                    = 0x1
-	PROT_EXEC                   = 0x4
-	PROT_NONE                   = 0
-	PROT_READ                   = 0x1
-	PROT_WRITE                  = 0x2
-	PT_ATTACH                   = 0xa
-	PT_ATTACHEXC                = 0xe
-	PT_CONTINUE                 = 0x7
-	PT_DENY_ATTACH              = 0x1f
-	PT_DETACH                   = 0xb
-	PT_FIRSTMACH                = 0x20
-	PT_FORCEQUOTA               = 0x1e
-	PT_KILL                     = 0x8
-	PT_READ_D                   = 0x2
-	PT_READ_I                   = 0x1
-	PT_READ_U                   = 0x3
-	PT_SIGEXC                   = 0xc
-	PT_STEP                     = 0x9
-	PT_THUPDATE                 = 0xd
-	PT_TRACE_ME                 = 0
-	PT_WRITE_D                  = 0x5
-	PT_WRITE_I                  = 0x4
-	PT_WRITE_U                  = 0x6
-	RTAX_AUTHOR                 = 0x6
-	RTAX_BRD                    = 0x7
-	RTAX_DST                    = 0
-	RTAX_GATEWAY                = 0x1
-	RTAX_GENMASK                = 0x3
-	RTAX_IFA                    = 0x5
-	RTAX_IFP                    = 0x4
-	RTAX_MAX                    = 0x8
-	RTAX_NETMASK                = 0x2
-	RTA_AUTHOR                  = 0x40
-	RTA_BRD                     = 0x80
-	RTA_DST                     = 0x1
-	RTA_GATEWAY                 = 0x2
-	RTA_GENMASK                 = 0x8
-	RTA_IFA                     = 0x20
-	RTA_IFP                     = 0x10
-	RTA_NETMASK                 = 0x4
-	RTF_BLACKHOLE               = 0x1000
-	RTF_BROADCAST               = 0x400000
-	RTF_CLONING                 = 0x100
-	RTF_CONDEMNED               = 0x2000000
-	RTF_DELCLONE                = 0x80
-	RTF_DONE                    = 0x40
-	RTF_DYNAMIC                 = 0x10
-	RTF_GATEWAY                 = 0x2
-	RTF_HOST                    = 0x4
-	RTF_IFREF                   = 0x4000000
-	RTF_IFSCOPE                 = 0x1000000
-	RTF_LLINFO                  = 0x400
-	RTF_LOCAL                   = 0x200000
-	RTF_MODIFIED                = 0x20
-	RTF_MULTICAST               = 0x800000
-	RTF_PINNED                  = 0x100000
-	RTF_PRCLONING               = 0x10000
-	RTF_PROTO1                  = 0x8000
-	RTF_PROTO2                  = 0x4000
-	RTF_PROTO3                  = 0x40000
-	RTF_REJECT                  = 0x8
-	RTF_STATIC                  = 0x800
-	RTF_UP                      = 0x1
-	RTF_WASCLONED               = 0x20000
-	RTF_XRESOLVE                = 0x200
-	RTM_ADD                     = 0x1
-	RTM_CHANGE                  = 0x3
-	RTM_DELADDR                 = 0xd
-	RTM_DELETE                  = 0x2
-	RTM_DELMADDR                = 0x10
-	RTM_GET                     = 0x4
-	RTM_GET2                    = 0x14
-	RTM_IFINFO                  = 0xe
-	RTM_IFINFO2                 = 0x12
-	RTM_LOCK                    = 0x8
-	RTM_LOSING                  = 0x5
-	RTM_MISS                    = 0x7
-	RTM_NEWADDR                 = 0xc
-	RTM_NEWMADDR                = 0xf
-	RTM_NEWMADDR2               = 0x13
-	RTM_OLDADD                  = 0x9
-	RTM_OLDDEL                  = 0xa
-	RTM_REDIRECT                = 0x6
-	RTM_RESOLVE                 = 0xb
-	RTM_RTTUNIT                 = 0xf4240
-	RTM_VERSION                 = 0x5
-	RTV_EXPIRE                  = 0x4
-	RTV_HOPCOUNT                = 0x2
-	RTV_MTU                     = 0x1
-	RTV_RPIPE                   = 0x8
-	RTV_RTT                     = 0x40
-	RTV_RTTVAR                  = 0x80
-	RTV_SPIPE                   = 0x10
-	RTV_SSTHRESH                = 0x20
-	SCM_CREDS                   = 0x3
-	SCM_RIGHTS                  = 0x1
-	SCM_TIMESTAMP               = 0x2
-	SHUT_RD                     = 0
-	SHUT_RDWR                   = 0x2
-	SHUT_WR                     = 0x1
-	SIGABRT                     = 0x6
-	SIGALRM                     = 0xe
-	SIGBUS                      = 0xa
-	SIGCHLD                     = 0x14
-	SIGCONT                     = 0x13
-	SIGEMT                      = 0x7
-	SIGFPE                      = 0x8
-	SIGHUP                      = 0x1
-	SIGILL                      = 0x4
-	SIGINFO                     = 0x1d
-	SIGINT                      = 0x2
-	SIGIO                       = 0x17
-	SIGIOT                      = 0x6
-	SIGKILL                     = 0x9
-	SIGPIPE                     = 0xd
-	SIGPROF                     = 0x1b
-	SIGQUIT                     = 0x3
-	SIGSEGV                     = 0xb
-	SIGSTOP                     = 0x11
-	SIGSYS                      = 0xc
-	SIGTERM                     = 0xf
-	SIGTRAP                     = 0x5
-	SIGTSTP                     = 0x12
-	SIGTTIN                     = 0x15
-	SIGTTOU                     = 0x16
-	SIGURG                      = 0x10
-	SIGUSR1                     = 0x1e
-	SIGUSR2                     = 0x1f
-	SIGVTALRM                   = 0x1a
-	SIGWINCH                    = 0x1c
-	SIGXCPU                     = 0x18
-	SIGXFSZ                     = 0x19
-	SIOCADDMULTI                = 0x80206931
-	SIOCAIFADDR                 = 0x8040691a
-	SIOCALIFADDR                = 0x8118691d
-	SIOCARPIPLL                 = 0xc0206928
-	SIOCATMARK                  = 0x40047307
-	SIOCAUTOADDR                = 0xc0206926
-	SIOCAUTONETMASK             = 0x80206927
-	SIOCDELMULTI                = 0x80206932
-	SIOCDIFADDR                 = 0x80206919
-	SIOCDIFPHYADDR              = 0x80206941
-	SIOCDLIFADDR                = 0x8118691f
-	SIOCGDRVSPEC                = 0xc01c697b
-	SIOCGETSGCNT                = 0xc014721c
-	SIOCGETVIFCNT               = 0xc014721b
-	SIOCGETVLAN                 = 0xc020697f
-	SIOCGHIWAT                  = 0x40047301
-	SIOCGIFADDR                 = 0xc0206921
-	SIOCGIFALTMTU               = 0xc0206948
-	SIOCGIFASYNCMAP             = 0xc020697c
-	SIOCGIFBOND                 = 0xc0206947
-	SIOCGIFBRDADDR              = 0xc0206923
-	SIOCGIFCONF                 = 0xc0086924
-	SIOCGIFDEVMTU               = 0xc0206944
-	SIOCGIFDSTADDR              = 0xc0206922
-	SIOCGIFFLAGS                = 0xc0206911
-	SIOCGIFGENERIC              = 0xc020693a
-	SIOCGIFKPI                  = 0xc0206987
-	SIOCGIFMAC                  = 0xc0206982
-	SIOCGIFMEDIA                = 0xc0286938
-	SIOCGIFMETRIC               = 0xc0206917
-	SIOCGIFMTU                  = 0xc0206933
-	SIOCGIFNETMASK              = 0xc0206925
-	SIOCGIFPDSTADDR             = 0xc0206940
-	SIOCGIFPHYS                 = 0xc0206935
-	SIOCGIFPSRCADDR             = 0xc020693f
-	SIOCGIFSTATUS               = 0xc331693d
-	SIOCGIFVLAN                 = 0xc020697f
-	SIOCGIFWAKEFLAGS            = 0xc0206988
-	SIOCGLIFADDR                = 0xc118691e
-	SIOCGLIFPHYADDR             = 0xc1186943
-	SIOCGLOWAT                  = 0x40047303
-	SIOCGPGRP                   = 0x40047309
-	SIOCIFCREATE                = 0xc0206978
-	SIOCIFCREATE2               = 0xc020697a
-	SIOCIFDESTROY               = 0x80206979
-	SIOCRSLVMULTI               = 0xc008693b
-	SIOCSDRVSPEC                = 0x801c697b
-	SIOCSETVLAN                 = 0x8020697e
-	SIOCSHIWAT                  = 0x80047300
-	SIOCSIFADDR                 = 0x8020690c
-	SIOCSIFALTMTU               = 0x80206945
-	SIOCSIFASYNCMAP             = 0x8020697d
-	SIOCSIFBOND                 = 0x80206946
-	SIOCSIFBRDADDR              = 0x80206913
-	SIOCSIFDSTADDR              = 0x8020690e
-	SIOCSIFFLAGS                = 0x80206910
-	SIOCSIFGENERIC              = 0x80206939
-	SIOCSIFKPI                  = 0x80206986
-	SIOCSIFLLADDR               = 0x8020693c
-	SIOCSIFMAC                  = 0x80206983
-	SIOCSIFMEDIA                = 0xc0206937
-	SIOCSIFMETRIC               = 0x80206918
-	SIOCSIFMTU                  = 0x80206934
-	SIOCSIFNETMASK              = 0x80206916
-	SIOCSIFPHYADDR              = 0x8040693e
-	SIOCSIFPHYS                 = 0x80206936
-	SIOCSIFVLAN                 = 0x8020697e
-	SIOCSLIFPHYADDR             = 0x81186942
-	SIOCSLOWAT                  = 0x80047302
-	SIOCSPGRP                   = 0x80047308
-	SOCK_DGRAM                  = 0x2
-	SOCK_MAXADDRLEN             = 0xff
-	SOCK_RAW                    = 0x3
-	SOCK_RDM                    = 0x4
-	SOCK_SEQPACKET              = 0x5
-	SOCK_STREAM                 = 0x1
-	SOL_SOCKET                  = 0xffff
-	SOMAXCONN                   = 0x80
-	SO_ACCEPTCONN               = 0x2
-	SO_BROADCAST                = 0x20
-	SO_DEBUG                    = 0x1
-	SO_DONTROUTE                = 0x10
-	SO_DONTTRUNC                = 0x2000
-	SO_ERROR                    = 0x1007
-	SO_KEEPALIVE                = 0x8
-	SO_LABEL                    = 0x1010
-	SO_LINGER                   = 0x80
-	SO_LINGER_SEC               = 0x1080
-	SO_NKE                      = 0x1021
-	SO_NOADDRERR                = 0x1023
-	SO_NOSIGPIPE                = 0x1022
-	SO_NOTIFYCONFLICT           = 0x1026
-	SO_NP_EXTENSIONS            = 0x1083
-	SO_NREAD                    = 0x1020
-	SO_NWRITE                   = 0x1024
-	SO_OOBINLINE                = 0x100
-	SO_PEERLABEL                = 0x1011
-	SO_RANDOMPORT               = 0x1082
-	SO_RCVBUF                   = 0x1002
-	SO_RCVLOWAT                 = 0x1004
-	SO_RCVTIMEO                 = 0x1006
-	SO_RESTRICTIONS             = 0x1081
-	SO_RESTRICT_DENYIN          = 0x1
-	SO_RESTRICT_DENYOUT         = 0x2
-	SO_RESTRICT_DENYSET         = 0x80000000
-	SO_REUSEADDR                = 0x4
-	SO_REUSEPORT                = 0x200
-	SO_REUSESHAREUID            = 0x1025
-	SO_SNDBUF                   = 0x1001
-	SO_SNDLOWAT                 = 0x1003
-	SO_SNDTIMEO                 = 0x1005
-	SO_TIMESTAMP                = 0x400
-	SO_TYPE                     = 0x1008
-	SO_UPCALLCLOSEWAIT          = 0x1027
-	SO_USELOOPBACK              = 0x40
-	SO_WANTMORE                 = 0x4000
-	SO_WANTOOBFLAG              = 0x8000
-	S_IEXEC                     = 0x40
-	S_IFBLK                     = 0x6000
-	S_IFCHR                     = 0x2000
-	S_IFDIR                     = 0x4000
-	S_IFIFO                     = 0x1000
-	S_IFLNK                     = 0xa000
-	S_IFMT                      = 0xf000
-	S_IFREG                     = 0x8000
-	S_IFSOCK                    = 0xc000
-	S_IFWHT                     = 0xe000
-	S_IREAD                     = 0x100
-	S_IRGRP                     = 0x20
-	S_IROTH                     = 0x4
-	S_IRUSR                     = 0x100
-	S_IRWXG                     = 0x38
-	S_IRWXO                     = 0x7
-	S_IRWXU                     = 0x1c0
-	S_ISGID                     = 0x400
-	S_ISTXT                     = 0x200
-	S_ISUID                     = 0x800
-	S_ISVTX                     = 0x200
-	S_IWGRP                     = 0x10
-	S_IWOTH                     = 0x2
-	S_IWRITE                    = 0x80
-	S_IWUSR                     = 0x80
-	S_IXGRP                     = 0x8
-	S_IXOTH                     = 0x1
-	S_IXUSR                     = 0x40
-	TCP_CONNECTIONTIMEOUT       = 0x20
-	TCP_KEEPALIVE               = 0x10
-	TCP_MAXBURST                = 0x4
-	TCP_MAXHLEN                 = 0x3c
-	TCP_MAXOLEN                 = 0x28
-	TCP_MAXSEG                  = 0x2
-	TCP_MAXWIN                  = 0xffff
-	TCP_MAX_SACK                = 0x3
-	TCP_MAX_WINSHIFT            = 0xe
-	TCP_MINMSS                  = 0xd8
-	TCP_MINMSSOVERLOAD          = 0x3e8
-	TCP_MSS                     = 0x200
-	TCP_NODELAY                 = 0x1
-	TCP_NOOPT                   = 0x8
-	TCP_NOPUSH                  = 0x4
-	TIOCCBRK                    = 0x2000747a
-	TIOCCDTR                    = 0x20007478
-	TIOCCONS                    = 0x80047462
-	TIOCDCDTIMESTAMP            = 0x40087458
-	TIOCDRAIN                   = 0x2000745e
-	TIOCDSIMICROCODE            = 0x20007455
-	TIOCEXCL                    = 0x2000740d
-	TIOCEXT                     = 0x80047460
-	TIOCFLUSH                   = 0x80047410
-	TIOCGDRAINWAIT              = 0x40047456
-	TIOCGETA                    = 0x402c7413
-	TIOCGETD                    = 0x4004741a
-	TIOCGPGRP                   = 0x40047477
-	TIOCGWINSZ                  = 0x40087468
-	TIOCIXOFF                   = 0x20007480
-	TIOCIXON                    = 0x20007481
-	TIOCMBIC                    = 0x8004746b
-	TIOCMBIS                    = 0x8004746c
-	TIOCMGDTRWAIT               = 0x4004745a
-	TIOCMGET                    = 0x4004746a
-	TIOCMODG                    = 0x40047403
-	TIOCMODS                    = 0x80047404
-	TIOCMSDTRWAIT               = 0x8004745b
-	TIOCMSET                    = 0x8004746d
-	TIOCM_CAR                   = 0x40
-	TIOCM_CD                    = 0x40
-	TIOCM_CTS                   = 0x20
-	TIOCM_DSR                   = 0x100
-	TIOCM_DTR                   = 0x2
-	TIOCM_LE                    = 0x1
-	TIOCM_RI                    = 0x80
-	TIOCM_RNG                   = 0x80
-	TIOCM_RTS                   = 0x4
-	TIOCM_SR                    = 0x10
-	TIOCM_ST                    = 0x8
-	TIOCNOTTY                   = 0x20007471
-	TIOCNXCL                    = 0x2000740e
-	TIOCOUTQ                    = 0x40047473
-	TIOCPKT                     = 0x80047470
-	TIOCPKT_DATA                = 0
-	TIOCPKT_DOSTOP              = 0x20
-	TIOCPKT_FLUSHREAD           = 0x1
-	TIOCPKT_FLUSHWRITE          = 0x2
-	TIOCPKT_IOCTL               = 0x40
-	TIOCPKT_NOSTOP              = 0x10
-	TIOCPKT_START               = 0x8
-	TIOCPKT_STOP                = 0x4
-	TIOCPTYGNAME                = 0x40807453
-	TIOCPTYGRANT                = 0x20007454
-	TIOCPTYUNLK                 = 0x20007452
-	TIOCREMOTE                  = 0x80047469
-	TIOCSBRK                    = 0x2000747b
-	TIOCSCONS                   = 0x20007463
-	TIOCSCTTY                   = 0x20007461
-	TIOCSDRAINWAIT              = 0x80047457
-	TIOCSDTR                    = 0x20007479
-	TIOCSETA                    = 0x802c7414
-	TIOCSETAF                   = 0x802c7416
-	TIOCSETAW                   = 0x802c7415
-	TIOCSETD                    = 0x8004741b
-	TIOCSIG                     = 0x2000745f
-	TIOCSPGRP                   = 0x80047476
-	TIOCSTART                   = 0x2000746e
-	TIOCSTAT                    = 0x20007465
-	TIOCSTI                     = 0x80017472
-	TIOCSTOP                    = 0x2000746f
-	TIOCSWINSZ                  = 0x80087467
-	TIOCTIMESTAMP               = 0x40087459
-	TIOCUCNTL                   = 0x80047466
-	WCONTINUED                  = 0x10
-	WCOREFLAG                   = 0x80
-	WEXITED                     = 0x4
-	WNOHANG                     = 0x1
-	WNOWAIT                     = 0x20
-	WORDSIZE                    = 0x20
-	WSTOPPED                    = 0x8
-	WUNTRACED                   = 0x2
+	AF_APPLETALK                      = 0x10
+	AF_CCITT                          = 0xa
+	AF_CHAOS                          = 0x5
+	AF_CNT                            = 0x15
+	AF_COIP                           = 0x14
+	AF_DATAKIT                        = 0x9
+	AF_DECnet                         = 0xc
+	AF_DLI                            = 0xd
+	AF_E164                           = 0x1c
+	AF_ECMA                           = 0x8
+	AF_HYLINK                         = 0xf
+	AF_IEEE80211                      = 0x25
+	AF_IMPLINK                        = 0x3
+	AF_INET                           = 0x2
+	AF_INET6                          = 0x1e
+	AF_IPX                            = 0x17
+	AF_ISDN                           = 0x1c
+	AF_ISO                            = 0x7
+	AF_LAT                            = 0xe
+	AF_LINK                           = 0x12
+	AF_LOCAL                          = 0x1
+	AF_MAX                            = 0x26
+	AF_NATM                           = 0x1f
+	AF_NDRV                           = 0x1b
+	AF_NETBIOS                        = 0x21
+	AF_NS                             = 0x6
+	AF_OSI                            = 0x7
+	AF_PPP                            = 0x22
+	AF_PUP                            = 0x4
+	AF_RESERVED_36                    = 0x24
+	AF_ROUTE                          = 0x11
+	AF_SIP                            = 0x18
+	AF_SNA                            = 0xb
+	AF_SYSTEM                         = 0x20
+	AF_UNIX                           = 0x1
+	AF_UNSPEC                         = 0x0
+	BIOCFLUSH                         = 0x20004268
+	BIOCGBLEN                         = 0x40044266
+	BIOCGDLT                          = 0x4004426a
+	BIOCGDLTLIST                      = 0xc00c4279
+	BIOCGETIF                         = 0x4020426b
+	BIOCGHDRCMPLT                     = 0x40044274
+	BIOCGRSIG                         = 0x40044272
+	BIOCGRTIMEOUT                     = 0x4010426e
+	BIOCGSEESENT                      = 0x40044276
+	BIOCGSTATS                        = 0x4008426f
+	BIOCIMMEDIATE                     = 0x80044270
+	BIOCPROMISC                       = 0x20004269
+	BIOCSBLEN                         = 0xc0044266
+	BIOCSDLT                          = 0x80044278
+	BIOCSETF                          = 0x80104267
+	BIOCSETIF                         = 0x8020426c
+	BIOCSHDRCMPLT                     = 0x80044275
+	BIOCSRSIG                         = 0x80044273
+	BIOCSRTIMEOUT                     = 0x8010426d
+	BIOCSSEESENT                      = 0x80044277
+	BIOCVERSION                       = 0x40044271
+	BPF_A                             = 0x10
+	BPF_ABS                           = 0x20
+	BPF_ADD                           = 0x0
+	BPF_ALIGNMENT                     = 0x4
+	BPF_ALU                           = 0x4
+	BPF_AND                           = 0x50
+	BPF_B                             = 0x10
+	BPF_DIV                           = 0x30
+	BPF_H                             = 0x8
+	BPF_IMM                           = 0x0
+	BPF_IND                           = 0x40
+	BPF_JA                            = 0x0
+	BPF_JEQ                           = 0x10
+	BPF_JGE                           = 0x30
+	BPF_JGT                           = 0x20
+	BPF_JMP                           = 0x5
+	BPF_JSET                          = 0x40
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
+	BPF_LDX                           = 0x1
+	BPF_LEN                           = 0x80
+	BPF_LSH                           = 0x60
+	BPF_MAJOR_VERSION                 = 0x1
+	BPF_MAXBUFSIZE                    = 0x80000
+	BPF_MAXINSNS                      = 0x200
+	BPF_MEM                           = 0x60
+	BPF_MEMWORDS                      = 0x10
+	BPF_MINBUFSIZE                    = 0x20
+	BPF_MINOR_VERSION                 = 0x1
+	BPF_MISC                          = 0x7
+	BPF_MSH                           = 0xa0
+	BPF_MUL                           = 0x20
+	BPF_NEG                           = 0x80
+	BPF_OR                            = 0x40
+	BPF_RELEASE                       = 0x30bb6
+	BPF_RET                           = 0x6
+	BPF_RSH                           = 0x70
+	BPF_ST                            = 0x2
+	BPF_STX                           = 0x3
+	BPF_SUB                           = 0x10
+	BPF_TAX                           = 0x0
+	BPF_TXA                           = 0x80
+	BPF_W                             = 0x0
+	BPF_X                             = 0x8
+	CTL_MAXNAME                       = 0xc
+	CTL_NET                           = 0x4
+	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
+	DLT_ARCNET                        = 0x7
+	DLT_ATM_CLIP                      = 0x13
+	DLT_ATM_RFC1483                   = 0xb
+	DLT_AX25                          = 0x3
+	DLT_CHAOS                         = 0x5
+	DLT_CHDLC                         = 0x68
+	DLT_C_HDLC                        = 0x68
+	DLT_EN10MB                        = 0x1
+	DLT_EN3MB                         = 0x2
+	DLT_FDDI                          = 0xa
+	DLT_IEEE802                       = 0x6
+	DLT_IEEE802_11                    = 0x69
+	DLT_IEEE802_11_RADIO              = 0x7f
+	DLT_IEEE802_11_RADIO_AVS          = 0xa3
+	DLT_LINUX_SLL                     = 0x71
+	DLT_LOOP                          = 0x6c
+	DLT_NULL                          = 0x0
+	DLT_PFLOG                         = 0x75
+	DLT_PFSYNC                        = 0x12
+	DLT_PPP                           = 0x9
+	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_SERIAL                    = 0x32
+	DLT_PRONET                        = 0x4
+	DLT_RAW                           = 0xc
+	DLT_SLIP                          = 0x8
+	DLT_SLIP_BSDOS                    = 0xf
+	DT_BLK                            = 0x6
+	DT_CHR                            = 0x2
+	DT_DIR                            = 0x4
+	DT_FIFO                           = 0x1
+	DT_LNK                            = 0xa
+	DT_REG                            = 0x8
+	DT_SOCK                           = 0xc
+	DT_UNKNOWN                        = 0x0
+	DT_WHT                            = 0xe
+	ECHO                              = 0x8
+	ECHOCTL                           = 0x40
+	ECHOE                             = 0x2
+	ECHOK                             = 0x4
+	ECHOKE                            = 0x1
+	ECHONL                            = 0x10
+	ECHOPRT                           = 0x20
+	EVFILT_AIO                        = -0x3
+	EVFILT_FS                         = -0x9
+	EVFILT_MACHPORT                   = -0x8
+	EVFILT_PROC                       = -0x5
+	EVFILT_READ                       = -0x1
+	EVFILT_SIGNAL                     = -0x6
+	EVFILT_SYSCOUNT                   = 0xc
+	EVFILT_THREADMARKER               = 0xc
+	EVFILT_TIMER                      = -0x7
+	EVFILT_USER                       = -0xa
+	EVFILT_VM                         = -0xc
+	EVFILT_VNODE                      = -0x4
+	EVFILT_WRITE                      = -0x2
+	EV_ADD                            = 0x1
+	EV_CLEAR                          = 0x20
+	EV_DELETE                         = 0x2
+	EV_DISABLE                        = 0x8
+	EV_DISPATCH                       = 0x80
+	EV_ENABLE                         = 0x4
+	EV_EOF                            = 0x8000
+	EV_ERROR                          = 0x4000
+	EV_FLAG0                          = 0x1000
+	EV_FLAG1                          = 0x2000
+	EV_ONESHOT                        = 0x10
+	EV_OOBAND                         = 0x2000
+	EV_POLL                           = 0x1000
+	EV_RECEIPT                        = 0x40
+	EV_SYSFLAGS                       = 0xf000
+	EXTA                              = 0x4b00
+	EXTB                              = 0x9600
+	EXTPROC                           = 0x800
+	FD_CLOEXEC                        = 0x1
+	FD_SETSIZE                        = 0x400
+	F_ADDFILESIGS                     = 0x3d
+	F_ADDSIGS                         = 0x3b
+	F_ALLOCATEALL                     = 0x4
+	F_ALLOCATECONTIG                  = 0x2
+	F_CHKCLEAN                        = 0x29
+	F_DUPFD                           = 0x0
+	F_DUPFD_CLOEXEC                   = 0x43
+	F_FLUSH_DATA                      = 0x28
+	F_FREEZE_FS                       = 0x35
+	F_FULLFSYNC                       = 0x33
+	F_GETFD                           = 0x1
+	F_GETFL                           = 0x3
+	F_GETLK                           = 0x7
+	F_GETLKPID                        = 0x42
+	F_GETNOSIGPIPE                    = 0x4a
+	F_GETOWN                          = 0x5
+	F_GETPATH                         = 0x32
+	F_GETPATH_MTMINFO                 = 0x47
+	F_GETPROTECTIONCLASS              = 0x3f
+	F_GLOBAL_NOCACHE                  = 0x37
+	F_LOG2PHYS                        = 0x31
+	F_LOG2PHYS_EXT                    = 0x41
+	F_MARKDEPENDENCY                  = 0x3c
+	F_NOCACHE                         = 0x30
+	F_NODIRECT                        = 0x3e
+	F_OK                              = 0x0
+	F_PATHPKG_CHECK                   = 0x34
+	F_PEOFPOSMODE                     = 0x3
+	F_PREALLOCATE                     = 0x2a
+	F_RDADVISE                        = 0x2c
+	F_RDAHEAD                         = 0x2d
+	F_RDLCK                           = 0x1
+	F_READBOOTSTRAP                   = 0x2e
+	F_SETBACKINGSTORE                 = 0x46
+	F_SETFD                           = 0x2
+	F_SETFL                           = 0x4
+	F_SETLK                           = 0x8
+	F_SETLKW                          = 0x9
+	F_SETNOSIGPIPE                    = 0x49
+	F_SETOWN                          = 0x6
+	F_SETPROTECTIONCLASS              = 0x40
+	F_SETSIZE                         = 0x2b
+	F_THAW_FS                         = 0x36
+	F_UNLCK                           = 0x2
+	F_VOLPOSMODE                      = 0x4
+	F_WRITEBOOTSTRAP                  = 0x2f
+	F_WRLCK                           = 0x3
+	IFF_ALLMULTI                      = 0x200
+	IFF_ALTPHYS                       = 0x4000
+	IFF_BROADCAST                     = 0x2
+	IFF_DEBUG                         = 0x4
+	IFF_LINK0                         = 0x1000
+	IFF_LINK1                         = 0x2000
+	IFF_LINK2                         = 0x4000
+	IFF_LOOPBACK                      = 0x8
+	IFF_MULTICAST                     = 0x8000
+	IFF_NOARP                         = 0x80
+	IFF_NOTRAILERS                    = 0x20
+	IFF_OACTIVE                       = 0x400
+	IFF_POINTOPOINT                   = 0x10
+	IFF_PROMISC                       = 0x100
+	IFF_RUNNING                       = 0x40
+	IFF_SIMPLEX                       = 0x800
+	IFF_UP                            = 0x1
+	IFNAMSIZ                          = 0x10
+	IFT_1822                          = 0x2
+	IFT_AAL5                          = 0x31
+	IFT_ARCNET                        = 0x23
+	IFT_ARCNETPLUS                    = 0x24
+	IFT_ATM                           = 0x25
+	IFT_BRIDGE                        = 0xd1
+	IFT_CARP                          = 0xf8
+	IFT_CELLULAR                      = 0xff
+	IFT_CEPT                          = 0x13
+	IFT_DS3                           = 0x1e
+	IFT_ENC                           = 0xf4
+	IFT_EON                           = 0x19
+	IFT_ETHER                         = 0x6
+	IFT_FAITH                         = 0x38
+	IFT_FDDI                          = 0xf
+	IFT_FRELAY                        = 0x20
+	IFT_FRELAYDCE                     = 0x2c
+	IFT_GIF                           = 0x37
+	IFT_HDH1822                       = 0x3
+	IFT_HIPPI                         = 0x2f
+	IFT_HSSI                          = 0x2e
+	IFT_HY                            = 0xe
+	IFT_IEEE1394                      = 0x90
+	IFT_IEEE8023ADLAG                 = 0x88
+	IFT_ISDNBASIC                     = 0x14
+	IFT_ISDNPRIMARY                   = 0x15
+	IFT_ISO88022LLC                   = 0x29
+	IFT_ISO88023                      = 0x7
+	IFT_ISO88024                      = 0x8
+	IFT_ISO88025                      = 0x9
+	IFT_ISO88026                      = 0xa
+	IFT_L2VLAN                        = 0x87
+	IFT_LAPB                          = 0x10
+	IFT_LOCALTALK                     = 0x2a
+	IFT_LOOP                          = 0x18
+	IFT_MIOX25                        = 0x26
+	IFT_MODEM                         = 0x30
+	IFT_NSIP                          = 0x1b
+	IFT_OTHER                         = 0x1
+	IFT_P10                           = 0xc
+	IFT_P80                           = 0xd
+	IFT_PARA                          = 0x22
+	IFT_PDP                           = 0xff
+	IFT_PFLOG                         = 0xf5
+	IFT_PFSYNC                        = 0xf6
+	IFT_PPP                           = 0x17
+	IFT_PROPMUX                       = 0x36
+	IFT_PROPVIRTUAL                   = 0x35
+	IFT_PTPSERIAL                     = 0x16
+	IFT_RS232                         = 0x21
+	IFT_SDLC                          = 0x11
+	IFT_SIP                           = 0x1f
+	IFT_SLIP                          = 0x1c
+	IFT_SMDSDXI                       = 0x2b
+	IFT_SMDSICIP                      = 0x34
+	IFT_SONET                         = 0x27
+	IFT_SONETPATH                     = 0x32
+	IFT_SONETVT                       = 0x33
+	IFT_STARLAN                       = 0xb
+	IFT_STF                           = 0x39
+	IFT_T1                            = 0x12
+	IFT_ULTRA                         = 0x1d
+	IFT_V35                           = 0x2d
+	IFT_X25                           = 0x5
+	IFT_X25DDN                        = 0x4
+	IFT_X25PLE                        = 0x28
+	IFT_XETHER                        = 0x1a
+	IN_CLASSA_HOST                    = 0xffffff
+	IN_CLASSA_MAX                     = 0x80
+	IN_CLASSA_NET                     = 0xff000000
+	IN_CLASSA_NSHIFT                  = 0x18
+	IN_CLASSB_HOST                    = 0xffff
+	IN_CLASSB_MAX                     = 0x10000
+	IN_CLASSB_NET                     = 0xffff0000
+	IN_CLASSB_NSHIFT                  = 0x10
+	IN_CLASSC_HOST                    = 0xff
+	IN_CLASSC_NET                     = 0xffffff00
+	IN_CLASSC_NSHIFT                  = 0x8
+	IN_CLASSD_HOST                    = 0xfffffff
+	IN_CLASSD_NET                     = 0xf0000000
+	IN_CLASSD_NSHIFT                  = 0x1c
+	IN_LINKLOCALNETNUM                = 0xa9fe0000
+	IN_LOOPBACKNET                    = 0x7f
+	IPPROTO_3PC                       = 0x22
+	IPPROTO_ADFS                      = 0x44
+	IPPROTO_AH                        = 0x33
+	IPPROTO_AHIP                      = 0x3d
+	IPPROTO_APES                      = 0x63
+	IPPROTO_ARGUS                     = 0xd
+	IPPROTO_AX25                      = 0x5d
+	IPPROTO_BHA                       = 0x31
+	IPPROTO_BLT                       = 0x1e
+	IPPROTO_BRSATMON                  = 0x4c
+	IPPROTO_CFTP                      = 0x3e
+	IPPROTO_CHAOS                     = 0x10
+	IPPROTO_CMTP                      = 0x26
+	IPPROTO_CPHB                      = 0x49
+	IPPROTO_CPNX                      = 0x48
+	IPPROTO_DDP                       = 0x25
+	IPPROTO_DGP                       = 0x56
+	IPPROTO_DIVERT                    = 0xfe
+	IPPROTO_DONE                      = 0x101
+	IPPROTO_DSTOPTS                   = 0x3c
+	IPPROTO_EGP                       = 0x8
+	IPPROTO_EMCON                     = 0xe
+	IPPROTO_ENCAP                     = 0x62
+	IPPROTO_EON                       = 0x50
+	IPPROTO_ESP                       = 0x32
+	IPPROTO_ETHERIP                   = 0x61
+	IPPROTO_FRAGMENT                  = 0x2c
+	IPPROTO_GGP                       = 0x3
+	IPPROTO_GMTP                      = 0x64
+	IPPROTO_GRE                       = 0x2f
+	IPPROTO_HELLO                     = 0x3f
+	IPPROTO_HMP                       = 0x14
+	IPPROTO_HOPOPTS                   = 0x0
+	IPPROTO_ICMP                      = 0x1
+	IPPROTO_ICMPV6                    = 0x3a
+	IPPROTO_IDP                       = 0x16
+	IPPROTO_IDPR                      = 0x23
+	IPPROTO_IDRP                      = 0x2d
+	IPPROTO_IGMP                      = 0x2
+	IPPROTO_IGP                       = 0x55
+	IPPROTO_IGRP                      = 0x58
+	IPPROTO_IL                        = 0x28
+	IPPROTO_INLSP                     = 0x34
+	IPPROTO_INP                       = 0x20
+	IPPROTO_IP                        = 0x0
+	IPPROTO_IPCOMP                    = 0x6c
+	IPPROTO_IPCV                      = 0x47
+	IPPROTO_IPEIP                     = 0x5e
+	IPPROTO_IPIP                      = 0x4
+	IPPROTO_IPPC                      = 0x43
+	IPPROTO_IPV4                      = 0x4
+	IPPROTO_IPV6                      = 0x29
+	IPPROTO_IRTP                      = 0x1c
+	IPPROTO_KRYPTOLAN                 = 0x41
+	IPPROTO_LARP                      = 0x5b
+	IPPROTO_LEAF1                     = 0x19
+	IPPROTO_LEAF2                     = 0x1a
+	IPPROTO_MAX                       = 0x100
+	IPPROTO_MAXID                     = 0x34
+	IPPROTO_MEAS                      = 0x13
+	IPPROTO_MHRP                      = 0x30
+	IPPROTO_MICP                      = 0x5f
+	IPPROTO_MTP                       = 0x5c
+	IPPROTO_MUX                       = 0x12
+	IPPROTO_ND                        = 0x4d
+	IPPROTO_NHRP                      = 0x36
+	IPPROTO_NONE                      = 0x3b
+	IPPROTO_NSP                       = 0x1f
+	IPPROTO_NVPII                     = 0xb
+	IPPROTO_OSPFIGP                   = 0x59
+	IPPROTO_PGM                       = 0x71
+	IPPROTO_PIGP                      = 0x9
+	IPPROTO_PIM                       = 0x67
+	IPPROTO_PRM                       = 0x15
+	IPPROTO_PUP                       = 0xc
+	IPPROTO_PVP                       = 0x4b
+	IPPROTO_RAW                       = 0xff
+	IPPROTO_RCCMON                    = 0xa
+	IPPROTO_RDP                       = 0x1b
+	IPPROTO_ROUTING                   = 0x2b
+	IPPROTO_RSVP                      = 0x2e
+	IPPROTO_RVD                       = 0x42
+	IPPROTO_SATEXPAK                  = 0x40
+	IPPROTO_SATMON                    = 0x45
+	IPPROTO_SCCSP                     = 0x60
+	IPPROTO_SCTP                      = 0x84
+	IPPROTO_SDRP                      = 0x2a
+	IPPROTO_SEP                       = 0x21
+	IPPROTO_SRPC                      = 0x5a
+	IPPROTO_ST                        = 0x7
+	IPPROTO_SVMTP                     = 0x52
+	IPPROTO_SWIPE                     = 0x35
+	IPPROTO_TCF                       = 0x57
+	IPPROTO_TCP                       = 0x6
+	IPPROTO_TP                        = 0x1d
+	IPPROTO_TPXX                      = 0x27
+	IPPROTO_TRUNK1                    = 0x17
+	IPPROTO_TRUNK2                    = 0x18
+	IPPROTO_TTP                       = 0x54
+	IPPROTO_UDP                       = 0x11
+	IPPROTO_VINES                     = 0x53
+	IPPROTO_VISA                      = 0x46
+	IPPROTO_VMTP                      = 0x51
+	IPPROTO_WBEXPAK                   = 0x4f
+	IPPROTO_WBMON                     = 0x4e
+	IPPROTO_WSN                       = 0x4a
+	IPPROTO_XNET                      = 0xf
+	IPPROTO_XTP                       = 0x24
+	IPV6_2292DSTOPTS                  = 0x17
+	IPV6_2292HOPLIMIT                 = 0x14
+	IPV6_2292HOPOPTS                  = 0x16
+	IPV6_2292NEXTHOP                  = 0x15
+	IPV6_2292PKTINFO                  = 0x13
+	IPV6_2292PKTOPTIONS               = 0x19
+	IPV6_2292RTHDR                    = 0x18
+	IPV6_BINDV6ONLY                   = 0x1b
+	IPV6_BOUND_IF                     = 0x7d
+	IPV6_CHECKSUM                     = 0x1a
+	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
+	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
+	IPV6_DEFHLIM                      = 0x40
+	IPV6_FAITH                        = 0x1d
+	IPV6_FLOWINFO_MASK                = 0xffffff0f
+	IPV6_FLOWLABEL_MASK               = 0xffff0f00
+	IPV6_FRAGTTL                      = 0x78
+	IPV6_FW_ADD                       = 0x1e
+	IPV6_FW_DEL                       = 0x1f
+	IPV6_FW_FLUSH                     = 0x20
+	IPV6_FW_GET                       = 0x22
+	IPV6_FW_ZERO                      = 0x21
+	IPV6_HLIMDEC                      = 0x1
+	IPV6_IPSEC_POLICY                 = 0x1c
+	IPV6_JOIN_GROUP                   = 0xc
+	IPV6_LEAVE_GROUP                  = 0xd
+	IPV6_MAXHLIM                      = 0xff
+	IPV6_MAXOPTHDR                    = 0x800
+	IPV6_MAXPACKET                    = 0xffff
+	IPV6_MAX_GROUP_SRC_FILTER         = 0x200
+	IPV6_MAX_MEMBERSHIPS              = 0xfff
+	IPV6_MAX_SOCK_SRC_FILTER          = 0x80
+	IPV6_MIN_MEMBERSHIPS              = 0x1f
+	IPV6_MMTU                         = 0x500
+	IPV6_MULTICAST_HOPS               = 0xa
+	IPV6_MULTICAST_IF                 = 0x9
+	IPV6_MULTICAST_LOOP               = 0xb
+	IPV6_PORTRANGE                    = 0xe
+	IPV6_PORTRANGE_DEFAULT            = 0x0
+	IPV6_PORTRANGE_HIGH               = 0x1
+	IPV6_PORTRANGE_LOW                = 0x2
+	IPV6_RECVTCLASS                   = 0x23
+	IPV6_RTHDR_LOOSE                  = 0x0
+	IPV6_RTHDR_STRICT                 = 0x1
+	IPV6_RTHDR_TYPE_0                 = 0x0
+	IPV6_SOCKOPT_RESERVED1            = 0x3
+	IPV6_TCLASS                       = 0x24
+	IPV6_UNICAST_HOPS                 = 0x4
+	IPV6_V6ONLY                       = 0x1b
+	IPV6_VERSION                      = 0x60
+	IPV6_VERSION_MASK                 = 0xf0
+	IP_ADD_MEMBERSHIP                 = 0xc
+	IP_ADD_SOURCE_MEMBERSHIP          = 0x46
+	IP_BLOCK_SOURCE                   = 0x48
+	IP_BOUND_IF                       = 0x19
+	IP_DEFAULT_MULTICAST_LOOP         = 0x1
+	IP_DEFAULT_MULTICAST_TTL          = 0x1
+	IP_DF                             = 0x4000
+	IP_DROP_MEMBERSHIP                = 0xd
+	IP_DROP_SOURCE_MEMBERSHIP         = 0x47
+	IP_DUMMYNET_CONFIGURE             = 0x3c
+	IP_DUMMYNET_DEL                   = 0x3d
+	IP_DUMMYNET_FLUSH                 = 0x3e
+	IP_DUMMYNET_GET                   = 0x40
+	IP_FAITH                          = 0x16
+	IP_FW_ADD                         = 0x28
+	IP_FW_DEL                         = 0x29
+	IP_FW_FLUSH                       = 0x2a
+	IP_FW_GET                         = 0x2c
+	IP_FW_RESETLOG                    = 0x2d
+	IP_FW_ZERO                        = 0x2b
+	IP_HDRINCL                        = 0x2
+	IP_IPSEC_POLICY                   = 0x15
+	IP_MAXPACKET                      = 0xffff
+	IP_MAX_GROUP_SRC_FILTER           = 0x200
+	IP_MAX_MEMBERSHIPS                = 0xfff
+	IP_MAX_SOCK_MUTE_FILTER           = 0x80
+	IP_MAX_SOCK_SRC_FILTER            = 0x80
+	IP_MF                             = 0x2000
+	IP_MIN_MEMBERSHIPS                = 0x1f
+	IP_MSFILTER                       = 0x4a
+	IP_MSS                            = 0x240
+	IP_MULTICAST_IF                   = 0x9
+	IP_MULTICAST_IFINDEX              = 0x42
+	IP_MULTICAST_LOOP                 = 0xb
+	IP_MULTICAST_TTL                  = 0xa
+	IP_MULTICAST_VIF                  = 0xe
+	IP_NAT__XXX                       = 0x37
+	IP_OFFMASK                        = 0x1fff
+	IP_OLD_FW_ADD                     = 0x32
+	IP_OLD_FW_DEL                     = 0x33
+	IP_OLD_FW_FLUSH                   = 0x34
+	IP_OLD_FW_GET                     = 0x36
+	IP_OLD_FW_RESETLOG                = 0x38
+	IP_OLD_FW_ZERO                    = 0x35
+	IP_OPTIONS                        = 0x1
+	IP_PKTINFO                        = 0x1a
+	IP_PORTRANGE                      = 0x13
+	IP_PORTRANGE_DEFAULT              = 0x0
+	IP_PORTRANGE_HIGH                 = 0x1
+	IP_PORTRANGE_LOW                  = 0x2
+	IP_RECVDSTADDR                    = 0x7
+	IP_RECVIF                         = 0x14
+	IP_RECVOPTS                       = 0x5
+	IP_RECVPKTINFO                    = 0x1a
+	IP_RECVRETOPTS                    = 0x6
+	IP_RECVTTL                        = 0x18
+	IP_RETOPTS                        = 0x8
+	IP_RF                             = 0x8000
+	IP_RSVP_OFF                       = 0x10
+	IP_RSVP_ON                        = 0xf
+	IP_RSVP_VIF_OFF                   = 0x12
+	IP_RSVP_VIF_ON                    = 0x11
+	IP_STRIPHDR                       = 0x17
+	IP_TOS                            = 0x3
+	IP_TRAFFIC_MGT_BACKGROUND         = 0x41
+	IP_TTL                            = 0x4
+	IP_UNBLOCK_SOURCE                 = 0x49
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
+	MADV_CAN_REUSE                    = 0x9
+	MADV_DONTNEED                     = 0x4
+	MADV_FREE                         = 0x5
+	MADV_FREE_REUSABLE                = 0x7
+	MADV_FREE_REUSE                   = 0x8
+	MADV_NORMAL                       = 0x0
+	MADV_RANDOM                       = 0x1
+	MADV_SEQUENTIAL                   = 0x2
+	MADV_WILLNEED                     = 0x3
+	MADV_ZERO_WIRED_PAGES             = 0x6
+	MAP_ANON                          = 0x1000
+	MAP_COPY                          = 0x2
+	MAP_FILE                          = 0x0
+	MAP_FIXED                         = 0x10
+	MAP_HASSEMAPHORE                  = 0x200
+	MAP_JIT                           = 0x800
+	MAP_NOCACHE                       = 0x400
+	MAP_NOEXTEND                      = 0x100
+	MAP_NORESERVE                     = 0x40
+	MAP_PRIVATE                       = 0x2
+	MAP_RENAME                        = 0x20
+	MAP_RESERVED0080                  = 0x80
+	MAP_SHARED                        = 0x1
+	MCL_CURRENT                       = 0x1
+	MCL_FUTURE                        = 0x2
+	MSG_CTRUNC                        = 0x20
+	MSG_DONTROUTE                     = 0x4
+	MSG_DONTWAIT                      = 0x80
+	MSG_EOF                           = 0x100
+	MSG_EOR                           = 0x8
+	MSG_FLUSH                         = 0x400
+	MSG_HAVEMORE                      = 0x2000
+	MSG_HOLD                          = 0x800
+	MSG_NEEDSA                        = 0x10000
+	MSG_OOB                           = 0x1
+	MSG_PEEK                          = 0x2
+	MSG_RCVMORE                       = 0x4000
+	MSG_SEND                          = 0x1000
+	MSG_TRUNC                         = 0x10
+	MSG_WAITALL                       = 0x40
+	MSG_WAITSTREAM                    = 0x200
+	MS_ASYNC                          = 0x1
+	MS_DEACTIVATE                     = 0x8
+	MS_INVALIDATE                     = 0x2
+	MS_KILLPAGES                      = 0x4
+	MS_SYNC                           = 0x10
+	NAME_MAX                          = 0xff
+	NET_RT_DUMP                       = 0x1
+	NET_RT_DUMP2                      = 0x7
+	NET_RT_FLAGS                      = 0x2
+	NET_RT_IFLIST                     = 0x3
+	NET_RT_IFLIST2                    = 0x6
+	NET_RT_MAXID                      = 0xa
+	NET_RT_STAT                       = 0x4
+	NET_RT_TRASH                      = 0x5
+	NOTE_ABSOLUTE                     = 0x8
+	NOTE_ATTRIB                       = 0x8
+	NOTE_CHILD                        = 0x4
+	NOTE_DELETE                       = 0x1
+	NOTE_EXEC                         = 0x20000000
+	NOTE_EXIT                         = 0x80000000
+	NOTE_EXITSTATUS                   = 0x4000000
+	NOTE_EXTEND                       = 0x4
+	NOTE_FFAND                        = 0x40000000
+	NOTE_FFCOPY                       = 0xc0000000
+	NOTE_FFCTRLMASK                   = 0xc0000000
+	NOTE_FFLAGSMASK                   = 0xffffff
+	NOTE_FFNOP                        = 0x0
+	NOTE_FFOR                         = 0x80000000
+	NOTE_FORK                         = 0x40000000
+	NOTE_LINK                         = 0x10
+	NOTE_LOWAT                        = 0x1
+	NOTE_NONE                         = 0x80
+	NOTE_NSECONDS                     = 0x4
+	NOTE_PCTRLMASK                    = -0x100000
+	NOTE_PDATAMASK                    = 0xfffff
+	NOTE_REAP                         = 0x10000000
+	NOTE_RENAME                       = 0x20
+	NOTE_RESOURCEEND                  = 0x2000000
+	NOTE_REVOKE                       = 0x40
+	NOTE_SECONDS                      = 0x1
+	NOTE_SIGNAL                       = 0x8000000
+	NOTE_TRACK                        = 0x1
+	NOTE_TRACKERR                     = 0x2
+	NOTE_TRIGGER                      = 0x1000000
+	NOTE_USECONDS                     = 0x2
+	NOTE_VM_ERROR                     = 0x10000000
+	NOTE_VM_PRESSURE                  = 0x80000000
+	NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000
+	NOTE_VM_PRESSURE_TERMINATE        = 0x40000000
+	NOTE_WRITE                        = 0x2
+	O_ACCMODE                         = 0x3
+	O_ALERT                           = 0x20000000
+	O_APPEND                          = 0x8
+	O_ASYNC                           = 0x40
+	O_CLOEXEC                         = 0x1000000
+	O_CREAT                           = 0x200
+	O_DIRECTORY                       = 0x100000
+	O_DSYNC                           = 0x400000
+	O_EVTONLY                         = 0x8000
+	O_EXCL                            = 0x800
+	O_EXLOCK                          = 0x20
+	O_FSYNC                           = 0x80
+	O_NDELAY                          = 0x4
+	O_NOCTTY                          = 0x20000
+	O_NOFOLLOW                        = 0x100
+	O_NONBLOCK                        = 0x4
+	O_POPUP                           = 0x80000000
+	O_RDONLY                          = 0x0
+	O_RDWR                            = 0x2
+	O_SHLOCK                          = 0x10
+	O_SYMLINK                         = 0x200000
+	O_SYNC                            = 0x80
+	O_TRUNC                           = 0x400
+	O_WRONLY                          = 0x1
+	PROT_EXEC                         = 0x4
+	PROT_NONE                         = 0x0
+	PROT_READ                         = 0x1
+	PROT_WRITE                        = 0x2
+	PT_ATTACH                         = 0xa
+	PT_ATTACHEXC                      = 0xe
+	PT_CONTINUE                       = 0x7
+	PT_DENY_ATTACH                    = 0x1f
+	PT_DETACH                         = 0xb
+	PT_FIRSTMACH                      = 0x20
+	PT_FORCEQUOTA                     = 0x1e
+	PT_KILL                           = 0x8
+	PT_READ_D                         = 0x2
+	PT_READ_I                         = 0x1
+	PT_READ_U                         = 0x3
+	PT_SIGEXC                         = 0xc
+	PT_STEP                           = 0x9
+	PT_THUPDATE                       = 0xd
+	PT_TRACE_ME                       = 0x0
+	PT_WRITE_D                        = 0x5
+	PT_WRITE_I                        = 0x4
+	PT_WRITE_U                        = 0x6
+	RLIMIT_AS                         = 0x5
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
+	RTAX_AUTHOR                       = 0x6
+	RTAX_BRD                          = 0x7
+	RTAX_DST                          = 0x0
+	RTAX_GATEWAY                      = 0x1
+	RTAX_GENMASK                      = 0x3
+	RTAX_IFA                          = 0x5
+	RTAX_IFP                          = 0x4
+	RTAX_MAX                          = 0x8
+	RTAX_NETMASK                      = 0x2
+	RTA_AUTHOR                        = 0x40
+	RTA_BRD                           = 0x80
+	RTA_DST                           = 0x1
+	RTA_GATEWAY                       = 0x2
+	RTA_GENMASK                       = 0x8
+	RTA_IFA                           = 0x20
+	RTA_IFP                           = 0x10
+	RTA_NETMASK                       = 0x4
+	RTF_BLACKHOLE                     = 0x1000
+	RTF_BROADCAST                     = 0x400000
+	RTF_CLONING                       = 0x100
+	RTF_CONDEMNED                     = 0x2000000
+	RTF_DELCLONE                      = 0x80
+	RTF_DONE                          = 0x40
+	RTF_DYNAMIC                       = 0x10
+	RTF_GATEWAY                       = 0x2
+	RTF_HOST                          = 0x4
+	RTF_IFREF                         = 0x4000000
+	RTF_IFSCOPE                       = 0x1000000
+	RTF_LLINFO                        = 0x400
+	RTF_LOCAL                         = 0x200000
+	RTF_MODIFIED                      = 0x20
+	RTF_MULTICAST                     = 0x800000
+	RTF_PINNED                        = 0x100000
+	RTF_PRCLONING                     = 0x10000
+	RTF_PROTO1                        = 0x8000
+	RTF_PROTO2                        = 0x4000
+	RTF_PROTO3                        = 0x40000
+	RTF_REJECT                        = 0x8
+	RTF_STATIC                        = 0x800
+	RTF_UP                            = 0x1
+	RTF_WASCLONED                     = 0x20000
+	RTF_XRESOLVE                      = 0x200
+	RTM_ADD                           = 0x1
+	RTM_CHANGE                        = 0x3
+	RTM_DELADDR                       = 0xd
+	RTM_DELETE                        = 0x2
+	RTM_DELMADDR                      = 0x10
+	RTM_GET                           = 0x4
+	RTM_GET2                          = 0x14
+	RTM_IFINFO                        = 0xe
+	RTM_IFINFO2                       = 0x12
+	RTM_LOCK                          = 0x8
+	RTM_LOSING                        = 0x5
+	RTM_MISS                          = 0x7
+	RTM_NEWADDR                       = 0xc
+	RTM_NEWMADDR                      = 0xf
+	RTM_NEWMADDR2                     = 0x13
+	RTM_OLDADD                        = 0x9
+	RTM_OLDDEL                        = 0xa
+	RTM_REDIRECT                      = 0x6
+	RTM_RESOLVE                       = 0xb
+	RTM_RTTUNIT                       = 0xf4240
+	RTM_VERSION                       = 0x5
+	RTV_EXPIRE                        = 0x4
+	RTV_HOPCOUNT                      = 0x2
+	RTV_MTU                           = 0x1
+	RTV_RPIPE                         = 0x8
+	RTV_RTT                           = 0x40
+	RTV_RTTVAR                        = 0x80
+	RTV_SPIPE                         = 0x10
+	RTV_SSTHRESH                      = 0x20
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	SCM_CREDS                         = 0x3
+	SCM_RIGHTS                        = 0x1
+	SCM_TIMESTAMP                     = 0x2
+	SCM_TIMESTAMP_MONOTONIC           = 0x4
+	SHUT_RD                           = 0x0
+	SHUT_RDWR                         = 0x2
+	SHUT_WR                           = 0x1
+	SIGABRT                           = 0x6
+	SIGALRM                           = 0xe
+	SIGBUS                            = 0xa
+	SIGCHLD                           = 0x14
+	SIGCONT                           = 0x13
+	SIGEMT                            = 0x7
+	SIGFPE                            = 0x8
+	SIGHUP                            = 0x1
+	SIGILL                            = 0x4
+	SIGINFO                           = 0x1d
+	SIGINT                            = 0x2
+	SIGIO                             = 0x17
+	SIGIOT                            = 0x6
+	SIGKILL                           = 0x9
+	SIGPIPE                           = 0xd
+	SIGPROF                           = 0x1b
+	SIGQUIT                           = 0x3
+	SIGSEGV                           = 0xb
+	SIGSTOP                           = 0x11
+	SIGSYS                            = 0xc
+	SIGTERM                           = 0xf
+	SIGTRAP                           = 0x5
+	SIGTSTP                           = 0x12
+	SIGTTIN                           = 0x15
+	SIGTTOU                           = 0x16
+	SIGURG                            = 0x10
+	SIGUSR1                           = 0x1e
+	SIGUSR2                           = 0x1f
+	SIGVTALRM                         = 0x1a
+	SIGWINCH                          = 0x1c
+	SIGXCPU                           = 0x18
+	SIGXFSZ                           = 0x19
+	SIOCADDMULTI                      = 0x80206931
+	SIOCAIFADDR                       = 0x8040691a
+	SIOCALIFADDR                      = 0x8118691d
+	SIOCARPIPLL                       = 0xc0206928
+	SIOCATMARK                        = 0x40047307
+	SIOCAUTOADDR                      = 0xc0206926
+	SIOCAUTONETMASK                   = 0x80206927
+	SIOCDELMULTI                      = 0x80206932
+	SIOCDIFADDR                       = 0x80206919
+	SIOCDIFPHYADDR                    = 0x80206941
+	SIOCDLIFADDR                      = 0x8118691f
+	SIOCGDRVSPEC                      = 0xc028697b
+	SIOCGETSGCNT                      = 0xc014721c
+	SIOCGETVIFCNT                     = 0xc014721b
+	SIOCGETVLAN                       = 0xc020697f
+	SIOCGHIWAT                        = 0x40047301
+	SIOCGIFADDR                       = 0xc0206921
+	SIOCGIFALTMTU                     = 0xc0206948
+	SIOCGIFASYNCMAP                   = 0xc020697c
+	SIOCGIFBOND                       = 0xc0206947
+	SIOCGIFBRDADDR                    = 0xc0206923
+	SIOCGIFCAP                        = 0xc020695b
+	SIOCGIFCONF                       = 0xc00c6924
+	SIOCGIFDEVMTU                     = 0xc0206944
+	SIOCGIFDSTADDR                    = 0xc0206922
+	SIOCGIFFLAGS                      = 0xc0206911
+	SIOCGIFGENERIC                    = 0xc020693a
+	SIOCGIFKPI                        = 0xc0206987
+	SIOCGIFMAC                        = 0xc0206982
+	SIOCGIFMEDIA                      = 0xc02c6938
+	SIOCGIFMETRIC                     = 0xc0206917
+	SIOCGIFMTU                        = 0xc0206933
+	SIOCGIFNETMASK                    = 0xc0206925
+	SIOCGIFPDSTADDR                   = 0xc0206940
+	SIOCGIFPHYS                       = 0xc0206935
+	SIOCGIFPSRCADDR                   = 0xc020693f
+	SIOCGIFSTATUS                     = 0xc331693d
+	SIOCGIFVLAN                       = 0xc020697f
+	SIOCGIFWAKEFLAGS                  = 0xc0206988
+	SIOCGLIFADDR                      = 0xc118691e
+	SIOCGLIFPHYADDR                   = 0xc1186943
+	SIOCGLOWAT                        = 0x40047303
+	SIOCGPGRP                         = 0x40047309
+	SIOCIFCREATE                      = 0xc0206978
+	SIOCIFCREATE2                     = 0xc020697a
+	SIOCIFDESTROY                     = 0x80206979
+	SIOCRSLVMULTI                     = 0xc010693b
+	SIOCSDRVSPEC                      = 0x8028697b
+	SIOCSETVLAN                       = 0x8020697e
+	SIOCSHIWAT                        = 0x80047300
+	SIOCSIFADDR                       = 0x8020690c
+	SIOCSIFALTMTU                     = 0x80206945
+	SIOCSIFASYNCMAP                   = 0x8020697d
+	SIOCSIFBOND                       = 0x80206946
+	SIOCSIFBRDADDR                    = 0x80206913
+	SIOCSIFCAP                        = 0x8020695a
+	SIOCSIFDSTADDR                    = 0x8020690e
+	SIOCSIFFLAGS                      = 0x80206910
+	SIOCSIFGENERIC                    = 0x80206939
+	SIOCSIFKPI                        = 0x80206986
+	SIOCSIFLLADDR                     = 0x8020693c
+	SIOCSIFMAC                        = 0x80206983
+	SIOCSIFMEDIA                      = 0xc0206937
+	SIOCSIFMETRIC                     = 0x80206918
+	SIOCSIFMTU                        = 0x80206934
+	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFPHYADDR                    = 0x8040693e
+	SIOCSIFPHYS                       = 0x80206936
+	SIOCSIFVLAN                       = 0x8020697e
+	SIOCSLIFPHYADDR                   = 0x81186942
+	SIOCSLOWAT                        = 0x80047302
+	SIOCSPGRP                         = 0x80047308
+	SOCK_DGRAM                        = 0x2
+	SOCK_MAXADDRLEN                   = 0xff
+	SOCK_RAW                          = 0x3
+	SOCK_RDM                          = 0x4
+	SOCK_SEQPACKET                    = 0x5
+	SOCK_STREAM                       = 0x1
+	SOL_SOCKET                        = 0xffff
+	SOMAXCONN                         = 0x80
+	SO_ACCEPTCONN                     = 0x2
+	SO_BROADCAST                      = 0x20
+	SO_DEBUG                          = 0x1
+	SO_DONTROUTE                      = 0x10
+	SO_DONTTRUNC                      = 0x2000
+	SO_ERROR                          = 0x1007
+	SO_KEEPALIVE                      = 0x8
+	SO_LABEL                          = 0x1010
+	SO_LINGER                         = 0x80
+	SO_LINGER_SEC                     = 0x1080
+	SO_NKE                            = 0x1021
+	SO_NOADDRERR                      = 0x1023
+	SO_NOSIGPIPE                      = 0x1022
+	SO_NOTIFYCONFLICT                 = 0x1026
+	SO_NP_EXTENSIONS                  = 0x1083
+	SO_NREAD                          = 0x1020
+	SO_NWRITE                         = 0x1024
+	SO_OOBINLINE                      = 0x100
+	SO_PEERLABEL                      = 0x1011
+	SO_RANDOMPORT                     = 0x1082
+	SO_RCVBUF                         = 0x1002
+	SO_RCVLOWAT                       = 0x1004
+	SO_RCVTIMEO                       = 0x1006
+	SO_RESTRICTIONS                   = 0x1081
+	SO_RESTRICT_DENYIN                = 0x1
+	SO_RESTRICT_DENYOUT               = 0x2
+	SO_RESTRICT_DENYSET               = 0x80000000
+	SO_REUSEADDR                      = 0x4
+	SO_REUSEPORT                      = 0x200
+	SO_REUSESHAREUID                  = 0x1025
+	SO_SNDBUF                         = 0x1001
+	SO_SNDLOWAT                       = 0x1003
+	SO_SNDTIMEO                       = 0x1005
+	SO_TIMESTAMP                      = 0x400
+	SO_TIMESTAMP_MONOTONIC            = 0x800
+	SO_TYPE                           = 0x1008
+	SO_UPCALLCLOSEWAIT                = 0x1027
+	SO_USELOOPBACK                    = 0x40
+	SO_WANTMORE                       = 0x4000
+	SO_WANTOOBFLAG                    = 0x8000
+	S_IEXEC                           = 0x40
+	S_IFBLK                           = 0x6000
+	S_IFCHR                           = 0x2000
+	S_IFDIR                           = 0x4000
+	S_IFIFO                           = 0x1000
+	S_IFLNK                           = 0xa000
+	S_IFMT                            = 0xf000
+	S_IFREG                           = 0x8000
+	S_IFSOCK                          = 0xc000
+	S_IFWHT                           = 0xe000
+	S_IREAD                           = 0x100
+	S_IRGRP                           = 0x20
+	S_IROTH                           = 0x4
+	S_IRUSR                           = 0x100
+	S_IRWXG                           = 0x38
+	S_IRWXO                           = 0x7
+	S_IRWXU                           = 0x1c0
+	S_ISGID                           = 0x400
+	S_ISTXT                           = 0x200
+	S_ISUID                           = 0x800
+	S_ISVTX                           = 0x200
+	S_IWGRP                           = 0x10
+	S_IWOTH                           = 0x2
+	S_IWRITE                          = 0x80
+	S_IWUSR                           = 0x80
+	S_IXGRP                           = 0x8
+	S_IXOTH                           = 0x1
+	S_IXUSR                           = 0x40
+	TCP_CONNECTIONTIMEOUT             = 0x20
+	TCP_KEEPALIVE                     = 0x10
+	TCP_MAXHLEN                       = 0x3c
+	TCP_MAXOLEN                       = 0x28
+	TCP_MAXSEG                        = 0x2
+	TCP_MAXWIN                        = 0xffff
+	TCP_MAX_SACK                      = 0x3
+	TCP_MAX_WINSHIFT                  = 0xe
+	TCP_MINMSS                        = 0xd8
+	TCP_MINMSSOVERLOAD                = 0x3e8
+	TCP_MSS                           = 0x200
+	TCP_NODELAY                       = 0x1
+	TCP_NOOPT                         = 0x8
+	TCP_NOPUSH                        = 0x4
+	TCP_RXT_CONNDROPTIME              = 0x80
+	TCP_RXT_FINDROP                   = 0x100
+	TIOCCBRK                          = 0x2000747a
+	TIOCCDTR                          = 0x20007478
+	TIOCCONS                          = 0x80047462
+	TIOCDCDTIMESTAMP                  = 0x40107458
+	TIOCDRAIN                         = 0x2000745e
+	TIOCDSIMICROCODE                  = 0x20007455
+	TIOCEXCL                          = 0x2000740d
+	TIOCEXT                           = 0x80047460
+	TIOCFLUSH                         = 0x80047410
+	TIOCGDRAINWAIT                    = 0x40047456
+	TIOCGETA                          = 0x40487413
+	TIOCGETD                          = 0x4004741a
+	TIOCGPGRP                         = 0x40047477
+	TIOCGWINSZ                        = 0x40087468
+	TIOCIXOFF                         = 0x20007480
+	TIOCIXON                          = 0x20007481
+	TIOCMBIC                          = 0x8004746b
+	TIOCMBIS                          = 0x8004746c
+	TIOCMGDTRWAIT                     = 0x4004745a
+	TIOCMGET                          = 0x4004746a
+	TIOCMODG                          = 0x40047403
+	TIOCMODS                          = 0x80047404
+	TIOCMSDTRWAIT                     = 0x8004745b
+	TIOCMSET                          = 0x8004746d
+	TIOCM_CAR                         = 0x40
+	TIOCM_CD                          = 0x40
+	TIOCM_CTS                         = 0x20
+	TIOCM_DSR                         = 0x100
+	TIOCM_DTR                         = 0x2
+	TIOCM_LE                          = 0x1
+	TIOCM_RI                          = 0x80
+	TIOCM_RNG                         = 0x80
+	TIOCM_RTS                         = 0x4
+	TIOCM_SR                          = 0x10
+	TIOCM_ST                          = 0x8
+	TIOCNOTTY                         = 0x20007471
+	TIOCNXCL                          = 0x2000740e
+	TIOCOUTQ                          = 0x40047473
+	TIOCPKT                           = 0x80047470
+	TIOCPKT_DATA                      = 0x0
+	TIOCPKT_DOSTOP                    = 0x20
+	TIOCPKT_FLUSHREAD                 = 0x1
+	TIOCPKT_FLUSHWRITE                = 0x2
+	TIOCPKT_IOCTL                     = 0x40
+	TIOCPKT_NOSTOP                    = 0x10
+	TIOCPKT_START                     = 0x8
+	TIOCPKT_STOP                      = 0x4
+	TIOCPTYGNAME                      = 0x40807453
+	TIOCPTYGRANT                      = 0x20007454
+	TIOCPTYUNLK                       = 0x20007452
+	TIOCREMOTE                        = 0x80047469
+	TIOCSBRK                          = 0x2000747b
+	TIOCSCONS                         = 0x20007463
+	TIOCSCTTY                         = 0x20007461
+	TIOCSDRAINWAIT                    = 0x80047457
+	TIOCSDTR                          = 0x20007479
+	TIOCSETA                          = 0x80487414
+	TIOCSETAF                         = 0x80487416
+	TIOCSETAW                         = 0x80487415
+	TIOCSETD                          = 0x8004741b
+	TIOCSIG                           = 0x2000745f
+	TIOCSPGRP                         = 0x80047476
+	TIOCSTART                         = 0x2000746e
+	TIOCSTAT                          = 0x20007465
+	TIOCSTI                           = 0x80017472
+	TIOCSTOP                          = 0x2000746f
+	TIOCSWINSZ                        = 0x80087467
+	TIOCTIMESTAMP                     = 0x40107459
+	TIOCUCNTL                         = 0x80047466
+	WCONTINUED                        = 0x10
+	WCOREFLAG                         = 0x80
+	WEXITED                           = 0x4
+	WNOHANG                           = 0x1
+	WNOWAIT                           = 0x20
+	WORDSIZE                          = 0x20
+	WSTOPPED                          = 0x8
+	WUNTRACED                         = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADARCH        = Errno(0x56)
+	EBADEXEC        = Errno(0x55)
+	EBADF           = Errno(0x9)
+	EBADMACHO       = Errno(0x58)
+	EBADMSG         = Errno(0x5e)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x59)
+	ECHILD          = Errno(0xa)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDEVERR         = Errno(0x53)
+	EDOM            = Errno(0x21)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x5a)
+	EILSEQ          = Errno(0x5c)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x69)
+	ELOOP           = Errno(0x3e)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	EMULTIHOP       = Errno(0x5f)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x5d)
+	ENOBUFS         = Errno(0x37)
+	ENODATA         = Errno(0x60)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOLINK         = Errno(0x61)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x5b)
+	ENOPOLICY       = Errno(0x67)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x62)
+	ENOSTR          = Errno(0x63)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTRECOVERABLE = Errno(0x68)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x2d)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x66)
+	EOVERFLOW       = Errno(0x54)
+	EOWNERDEAD      = Errno(0x69)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTO          = Errno(0x64)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	EPWROFF         = Errno(0x52)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHLIBVERS      = Errno(0x57)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIME           = Errno(0x65)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
 
 // Error table
 var errors = [...]string{
@@ -1192,4 +1280,6 @@ var errors = [...]string{
 	101: "STREAM ioctl timeout",
 	102: "operation not supported on socket",
 	103: "policy not found",
+	104: "state not recoverable",
+	105: "previous owner died",
 }
diff --git a/src/pkg/syscall/zerrors_darwin_amd64.go b/src/pkg/syscall/zerrors_darwin_amd64.go
index 3165fee..12ab27f 100644
--- a/src/pkg/syscall/zerrors_darwin_amd64.go
+++ b/src/pkg/syscall/zerrors_darwin_amd64.go
@@ -1,1091 +1,1179 @@
-// mkerrors.sh -f -m64
+// mkerrors.sh -m64
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -f -m64 -gsyscall -f -m64 _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m64 _const.go
 
 package syscall
 
-// Constants
 const (
-	AF_APPLETALK                = 0x10
-	AF_CCITT                    = 0xa
-	AF_CHAOS                    = 0x5
-	AF_CNT                      = 0x15
-	AF_COIP                     = 0x14
-	AF_DATAKIT                  = 0x9
-	AF_DECnet                   = 0xc
-	AF_DLI                      = 0xd
-	AF_E164                     = 0x1c
-	AF_ECMA                     = 0x8
-	AF_HYLINK                   = 0xf
-	AF_IEEE80211                = 0x25
-	AF_IMPLINK                  = 0x3
-	AF_INET                     = 0x2
-	AF_INET6                    = 0x1e
-	AF_IPX                      = 0x17
-	AF_ISDN                     = 0x1c
-	AF_ISO                      = 0x7
-	AF_LAT                      = 0xe
-	AF_LINK                     = 0x12
-	AF_LOCAL                    = 0x1
-	AF_MAX                      = 0x26
-	AF_NATM                     = 0x1f
-	AF_NDRV                     = 0x1b
-	AF_NETBIOS                  = 0x21
-	AF_NS                       = 0x6
-	AF_OSI                      = 0x7
-	AF_PPP                      = 0x22
-	AF_PUP                      = 0x4
-	AF_RESERVED_36              = 0x24
-	AF_ROUTE                    = 0x11
-	AF_SIP                      = 0x18
-	AF_SNA                      = 0xb
-	AF_SYSTEM                   = 0x20
-	AF_UNIX                     = 0x1
-	AF_UNSPEC                   = 0
-	BIOCFLUSH                   = 0x20004268
-	BIOCGBLEN                   = 0x40044266
-	BIOCGDLT                    = 0x4004426a
-	BIOCGDLTLIST                = 0xc00c4279
-	BIOCGETIF                   = 0x4020426b
-	BIOCGHDRCMPLT               = 0x40044274
-	BIOCGRSIG                   = 0x40044272
-	BIOCGRTIMEOUT               = 0x4008426e
-	BIOCGSEESENT                = 0x40044276
-	BIOCGSTATS                  = 0x4008426f
-	BIOCIMMEDIATE               = 0x80044270
-	BIOCPROMISC                 = 0x20004269
-	BIOCSBLEN                   = 0xc0044266
-	BIOCSDLT                    = 0x80044278
-	BIOCSETF                    = 0x80104267
-	BIOCSETIF                   = 0x8020426c
-	BIOCSHDRCMPLT               = 0x80044275
-	BIOCSRSIG                   = 0x80044273
-	BIOCSRTIMEOUT               = 0x8008426d
-	BIOCSSEESENT                = 0x80044277
-	BIOCVERSION                 = 0x40044271
-	BPF_A                       = 0x10
-	BPF_ABS                     = 0x20
-	BPF_ADD                     = 0
-	BPF_ALIGNMENT               = 0x4
-	BPF_ALU                     = 0x4
-	BPF_AND                     = 0x50
-	BPF_B                       = 0x10
-	BPF_DIV                     = 0x30
-	BPF_H                       = 0x8
-	BPF_IMM                     = 0
-	BPF_IND                     = 0x40
-	BPF_JA                      = 0
-	BPF_JEQ                     = 0x10
-	BPF_JGE                     = 0x30
-	BPF_JGT                     = 0x20
-	BPF_JMP                     = 0x5
-	BPF_JSET                    = 0x40
-	BPF_K                       = 0
-	BPF_LD                      = 0
-	BPF_LDX                     = 0x1
-	BPF_LEN                     = 0x80
-	BPF_LSH                     = 0x60
-	BPF_MAJOR_VERSION           = 0x1
-	BPF_MAXBUFSIZE              = 0x80000
-	BPF_MAXINSNS                = 0x200
-	BPF_MEM                     = 0x60
-	BPF_MEMWORDS                = 0x10
-	BPF_MINBUFSIZE              = 0x20
-	BPF_MINOR_VERSION           = 0x1
-	BPF_MISC                    = 0x7
-	BPF_MSH                     = 0xa0
-	BPF_MUL                     = 0x20
-	BPF_NEG                     = 0x80
-	BPF_OR                      = 0x40
-	BPF_RELEASE                 = 0x30bb6
-	BPF_RET                     = 0x6
-	BPF_RSH                     = 0x70
-	BPF_ST                      = 0x2
-	BPF_STX                     = 0x3
-	BPF_SUB                     = 0x10
-	BPF_TAX                     = 0
-	BPF_TXA                     = 0x80
-	BPF_W                       = 0
-	BPF_X                       = 0x8
-	CTL_MAXNAME                 = 0xc
-	CTL_NET                     = 0x4
-	DLT_APPLE_IP_OVER_IEEE1394  = 0x8a
-	DLT_ARCNET                  = 0x7
-	DLT_ATM_CLIP                = 0x13
-	DLT_ATM_RFC1483             = 0xb
-	DLT_AX25                    = 0x3
-	DLT_CHAOS                   = 0x5
-	DLT_CHDLC                   = 0x68
-	DLT_C_HDLC                  = 0x68
-	DLT_EN10MB                  = 0x1
-	DLT_EN3MB                   = 0x2
-	DLT_FDDI                    = 0xa
-	DLT_IEEE802                 = 0x6
-	DLT_IEEE802_11              = 0x69
-	DLT_IEEE802_11_RADIO        = 0x7f
-	DLT_IEEE802_11_RADIO_AVS    = 0xa3
-	DLT_LINUX_SLL               = 0x71
-	DLT_LOOP                    = 0x6c
-	DLT_NULL                    = 0
-	DLT_PFLOG                   = 0x75
-	DLT_PFSYNC                  = 0x12
-	DLT_PPP                     = 0x9
-	DLT_PPP_BSDOS               = 0x10
-	DLT_PPP_SERIAL              = 0x32
-	DLT_PRONET                  = 0x4
-	DLT_RAW                     = 0xc
-	DLT_SLIP                    = 0x8
-	DLT_SLIP_BSDOS              = 0xf
-	DT_BLK                      = 0x6
-	DT_CHR                      = 0x2
-	DT_DIR                      = 0x4
-	DT_FIFO                     = 0x1
-	DT_LNK                      = 0xa
-	DT_REG                      = 0x8
-	DT_SOCK                     = 0xc
-	DT_UNKNOWN                  = 0
-	DT_WHT                      = 0xe
-	E2BIG                       = 0x7
-	EACCES                      = 0xd
-	EADDRINUSE                  = 0x30
-	EADDRNOTAVAIL               = 0x31
-	EAFNOSUPPORT                = 0x2f
-	EAGAIN                      = 0x23
-	EALREADY                    = 0x25
-	EAUTH                       = 0x50
-	EBADARCH                    = 0x56
-	EBADEXEC                    = 0x55
-	EBADF                       = 0x9
-	EBADMACHO                   = 0x58
-	EBADMSG                     = 0x5e
-	EBADRPC                     = 0x48
-	EBUSY                       = 0x10
-	ECANCELED                   = 0x59
-	ECHILD                      = 0xa
-	ECHO                        = 0x8
-	ECHOCTL                     = 0x40
-	ECHOE                       = 0x2
-	ECHOK                       = 0x4
-	ECHOKE                      = 0x1
-	ECHONL                      = 0x10
-	ECHOPRT                     = 0x20
-	ECONNABORTED                = 0x35
-	ECONNREFUSED                = 0x3d
-	ECONNRESET                  = 0x36
-	EDEADLK                     = 0xb
-	EDESTADDRREQ                = 0x27
-	EDEVERR                     = 0x53
-	EDOM                        = 0x21
-	EDQUOT                      = 0x45
-	EEXIST                      = 0x11
-	EFAULT                      = 0xe
-	EFBIG                       = 0x1b
-	EFTYPE                      = 0x4f
-	EHOSTDOWN                   = 0x40
-	EHOSTUNREACH                = 0x41
-	EIDRM                       = 0x5a
-	EILSEQ                      = 0x5c
-	EINPROGRESS                 = 0x24
-	EINTR                       = 0x4
-	EINVAL                      = 0x16
-	EIO                         = 0x5
-	EISCONN                     = 0x38
-	EISDIR                      = 0x15
-	ELAST                       = 0x67
-	ELOOP                       = 0x3e
-	EMFILE                      = 0x18
-	EMLINK                      = 0x1f
-	EMSGSIZE                    = 0x28
-	EMULTIHOP                   = 0x5f
-	ENAMETOOLONG                = 0x3f
-	ENEEDAUTH                   = 0x51
-	ENETDOWN                    = 0x32
-	ENETRESET                   = 0x34
-	ENETUNREACH                 = 0x33
-	ENFILE                      = 0x17
-	ENOATTR                     = 0x5d
-	ENOBUFS                     = 0x37
-	ENODATA                     = 0x60
-	ENODEV                      = 0x13
-	ENOENT                      = 0x2
-	ENOEXEC                     = 0x8
-	ENOLCK                      = 0x4d
-	ENOLINK                     = 0x61
-	ENOMEM                      = 0xc
-	ENOMSG                      = 0x5b
-	ENOPOLICY                   = 0x67
-	ENOPROTOOPT                 = 0x2a
-	ENOSPC                      = 0x1c
-	ENOSR                       = 0x62
-	ENOSTR                      = 0x63
-	ENOSYS                      = 0x4e
-	ENOTBLK                     = 0xf
-	ENOTCONN                    = 0x39
-	ENOTDIR                     = 0x14
-	ENOTEMPTY                   = 0x42
-	ENOTSOCK                    = 0x26
-	ENOTSUP                     = 0x2d
-	ENOTTY                      = 0x19
-	ENXIO                       = 0x6
-	EOPNOTSUPP                  = 0x66
-	EOVERFLOW                   = 0x54
-	EPERM                       = 0x1
-	EPFNOSUPPORT                = 0x2e
-	EPIPE                       = 0x20
-	EPROCLIM                    = 0x43
-	EPROCUNAVAIL                = 0x4c
-	EPROGMISMATCH               = 0x4b
-	EPROGUNAVAIL                = 0x4a
-	EPROTO                      = 0x64
-	EPROTONOSUPPORT             = 0x2b
-	EPROTOTYPE                  = 0x29
-	EPWROFF                     = 0x52
-	ERANGE                      = 0x22
-	EREMOTE                     = 0x47
-	EROFS                       = 0x1e
-	ERPCMISMATCH                = 0x49
-	ESHLIBVERS                  = 0x57
-	ESHUTDOWN                   = 0x3a
-	ESOCKTNOSUPPORT             = 0x2c
-	ESPIPE                      = 0x1d
-	ESRCH                       = 0x3
-	ESTALE                      = 0x46
-	ETIME                       = 0x65
-	ETIMEDOUT                   = 0x3c
-	ETOOMANYREFS                = 0x3b
-	ETXTBSY                     = 0x1a
-	EUSERS                      = 0x44
-	EVFILT_AIO                  = -0x3
-	EVFILT_FS                   = -0x9
-	EVFILT_MACHPORT             = -0x8
-	EVFILT_PROC                 = -0x5
-	EVFILT_READ                 = -0x1
-	EVFILT_SESSION              = -0xb
-	EVFILT_SIGNAL               = -0x6
-	EVFILT_SYSCOUNT             = 0xb
-	EVFILT_THREADMARKER         = 0xb
-	EVFILT_TIMER                = -0x7
-	EVFILT_USER                 = -0xa
-	EVFILT_VNODE                = -0x4
-	EVFILT_WRITE                = -0x2
-	EV_ADD                      = 0x1
-	EV_CLEAR                    = 0x20
-	EV_DELETE                   = 0x2
-	EV_DISABLE                  = 0x8
-	EV_DISPATCH                 = 0x80
-	EV_ENABLE                   = 0x4
-	EV_EOF                      = 0x8000
-	EV_ERROR                    = 0x4000
-	EV_FLAG0                    = 0x1000
-	EV_FLAG1                    = 0x2000
-	EV_ONESHOT                  = 0x10
-	EV_OOBAND                   = 0x2000
-	EV_POLL                     = 0x1000
-	EV_RECEIPT                  = 0x40
-	EV_SYSFLAGS                 = 0xf000
-	EV_TRIGGER                  = 0x100
-	EWOULDBLOCK                 = 0x23
-	EXDEV                       = 0x12
-	EXTA                        = 0x4b00
-	EXTB                        = 0x9600
-	EXTPROC                     = 0x800
-	FD_CLOEXEC                  = 0x1
-	FD_SETSIZE                  = 0x400
-	F_ADDFILESIGS               = 0x3d
-	F_ADDSIGS                   = 0x3b
-	F_ALLOCATEALL               = 0x4
-	F_ALLOCATECONTIG            = 0x2
-	F_CHKCLEAN                  = 0x29
-	F_DUPFD                     = 0
-	F_FREEZE_FS                 = 0x35
-	F_FULLFSYNC                 = 0x33
-	F_GETFD                     = 0x1
-	F_GETFL                     = 0x3
-	F_GETLK                     = 0x7
-	F_GETOWN                    = 0x5
-	F_GETPATH                   = 0x32
-	F_GETPROTECTIONCLASS        = 0x3e
-	F_GLOBAL_NOCACHE            = 0x37
-	F_LOG2PHYS                  = 0x31
-	F_MARKDEPENDENCY            = 0x3c
-	F_NOCACHE                   = 0x30
-	F_PATHPKG_CHECK             = 0x34
-	F_PEOFPOSMODE               = 0x3
-	F_PREALLOCATE               = 0x2a
-	F_RDADVISE                  = 0x2c
-	F_RDAHEAD                   = 0x2d
-	F_RDLCK                     = 0x1
-	F_READBOOTSTRAP             = 0x2e
-	F_SETFD                     = 0x2
-	F_SETFL                     = 0x4
-	F_SETLK                     = 0x8
-	F_SETLKW                    = 0x9
-	F_SETOWN                    = 0x6
-	F_SETPROTECTIONCLASS        = 0x3f
-	F_SETSIZE                   = 0x2b
-	F_THAW_FS                   = 0x36
-	F_UNLCK                     = 0x2
-	F_VOLPOSMODE                = 0x4
-	F_WRITEBOOTSTRAP            = 0x2f
-	F_WRLCK                     = 0x3
-	IFF_ALLMULTI                = 0x200
-	IFF_ALTPHYS                 = 0x4000
-	IFF_BROADCAST               = 0x2
-	IFF_DEBUG                   = 0x4
-	IFF_LINK0                   = 0x1000
-	IFF_LINK1                   = 0x2000
-	IFF_LINK2                   = 0x4000
-	IFF_LOOPBACK                = 0x8
-	IFF_MULTICAST               = 0x8000
-	IFF_NOARP                   = 0x80
-	IFF_NOTRAILERS              = 0x20
-	IFF_OACTIVE                 = 0x400
-	IFF_POINTOPOINT             = 0x10
-	IFF_PROMISC                 = 0x100
-	IFF_RUNNING                 = 0x40
-	IFF_SIMPLEX                 = 0x800
-	IFF_UP                      = 0x1
-	IFNAMSIZ                    = 0x10
-	IFT_1822                    = 0x2
-	IFT_AAL5                    = 0x31
-	IFT_ARCNET                  = 0x23
-	IFT_ARCNETPLUS              = 0x24
-	IFT_ATM                     = 0x25
-	IFT_BRIDGE                  = 0xd1
-	IFT_CARP                    = 0xf8
-	IFT_CEPT                    = 0x13
-	IFT_DS3                     = 0x1e
-	IFT_ENC                     = 0xf4
-	IFT_EON                     = 0x19
-	IFT_ETHER                   = 0x6
-	IFT_FAITH                   = 0x38
-	IFT_FDDI                    = 0xf
-	IFT_FRELAY                  = 0x20
-	IFT_FRELAYDCE               = 0x2c
-	IFT_GIF                     = 0x37
-	IFT_HDH1822                 = 0x3
-	IFT_HIPPI                   = 0x2f
-	IFT_HSSI                    = 0x2e
-	IFT_HY                      = 0xe
-	IFT_IEEE1394                = 0x90
-	IFT_IEEE8023ADLAG           = 0x88
-	IFT_ISDNBASIC               = 0x14
-	IFT_ISDNPRIMARY             = 0x15
-	IFT_ISO88022LLC             = 0x29
-	IFT_ISO88023                = 0x7
-	IFT_ISO88024                = 0x8
-	IFT_ISO88025                = 0x9
-	IFT_ISO88026                = 0xa
-	IFT_L2VLAN                  = 0x87
-	IFT_LAPB                    = 0x10
-	IFT_LOCALTALK               = 0x2a
-	IFT_LOOP                    = 0x18
-	IFT_MIOX25                  = 0x26
-	IFT_MODEM                   = 0x30
-	IFT_NSIP                    = 0x1b
-	IFT_OTHER                   = 0x1
-	IFT_P10                     = 0xc
-	IFT_P80                     = 0xd
-	IFT_PARA                    = 0x22
-	IFT_PDP                     = 0xff
-	IFT_PFLOG                   = 0xf5
-	IFT_PFSYNC                  = 0xf6
-	IFT_PPP                     = 0x17
-	IFT_PROPMUX                 = 0x36
-	IFT_PROPVIRTUAL             = 0x35
-	IFT_PTPSERIAL               = 0x16
-	IFT_RS232                   = 0x21
-	IFT_SDLC                    = 0x11
-	IFT_SIP                     = 0x1f
-	IFT_SLIP                    = 0x1c
-	IFT_SMDSDXI                 = 0x2b
-	IFT_SMDSICIP                = 0x34
-	IFT_SONET                   = 0x27
-	IFT_SONETPATH               = 0x32
-	IFT_SONETVT                 = 0x33
-	IFT_STARLAN                 = 0xb
-	IFT_STF                     = 0x39
-	IFT_T1                      = 0x12
-	IFT_ULTRA                   = 0x1d
-	IFT_V35                     = 0x2d
-	IFT_X25                     = 0x5
-	IFT_X25DDN                  = 0x4
-	IFT_X25PLE                  = 0x28
-	IFT_XETHER                  = 0x1a
-	IN_CLASSA_HOST              = 0xffffff
-	IN_CLASSA_MAX               = 0x80
-	IN_CLASSA_NET               = 0xff000000
-	IN_CLASSA_NSHIFT            = 0x18
-	IN_CLASSB_HOST              = 0xffff
-	IN_CLASSB_MAX               = 0x10000
-	IN_CLASSB_NET               = 0xffff0000
-	IN_CLASSB_NSHIFT            = 0x10
-	IN_CLASSC_HOST              = 0xff
-	IN_CLASSC_NET               = 0xffffff00
-	IN_CLASSC_NSHIFT            = 0x8
-	IN_CLASSD_HOST              = 0xfffffff
-	IN_CLASSD_NET               = 0xf0000000
-	IN_CLASSD_NSHIFT            = 0x1c
-	IN_LINKLOCALNETNUM          = 0xa9fe0000
-	IN_LOOPBACKNET              = 0x7f
-	IPPROTO_3PC                 = 0x22
-	IPPROTO_ADFS                = 0x44
-	IPPROTO_AH                  = 0x33
-	IPPROTO_AHIP                = 0x3d
-	IPPROTO_APES                = 0x63
-	IPPROTO_ARGUS               = 0xd
-	IPPROTO_AX25                = 0x5d
-	IPPROTO_BHA                 = 0x31
-	IPPROTO_BLT                 = 0x1e
-	IPPROTO_BRSATMON            = 0x4c
-	IPPROTO_CFTP                = 0x3e
-	IPPROTO_CHAOS               = 0x10
-	IPPROTO_CMTP                = 0x26
-	IPPROTO_CPHB                = 0x49
-	IPPROTO_CPNX                = 0x48
-	IPPROTO_DDP                 = 0x25
-	IPPROTO_DGP                 = 0x56
-	IPPROTO_DIVERT              = 0xfe
-	IPPROTO_DONE                = 0x101
-	IPPROTO_DSTOPTS             = 0x3c
-	IPPROTO_EGP                 = 0x8
-	IPPROTO_EMCON               = 0xe
-	IPPROTO_ENCAP               = 0x62
-	IPPROTO_EON                 = 0x50
-	IPPROTO_ESP                 = 0x32
-	IPPROTO_ETHERIP             = 0x61
-	IPPROTO_FRAGMENT            = 0x2c
-	IPPROTO_GGP                 = 0x3
-	IPPROTO_GMTP                = 0x64
-	IPPROTO_GRE                 = 0x2f
-	IPPROTO_HELLO               = 0x3f
-	IPPROTO_HMP                 = 0x14
-	IPPROTO_HOPOPTS             = 0
-	IPPROTO_ICMP                = 0x1
-	IPPROTO_ICMPV6              = 0x3a
-	IPPROTO_IDP                 = 0x16
-	IPPROTO_IDPR                = 0x23
-	IPPROTO_IDRP                = 0x2d
-	IPPROTO_IGMP                = 0x2
-	IPPROTO_IGP                 = 0x55
-	IPPROTO_IGRP                = 0x58
-	IPPROTO_IL                  = 0x28
-	IPPROTO_INLSP               = 0x34
-	IPPROTO_INP                 = 0x20
-	IPPROTO_IP                  = 0
-	IPPROTO_IPCOMP              = 0x6c
-	IPPROTO_IPCV                = 0x47
-	IPPROTO_IPEIP               = 0x5e
-	IPPROTO_IPIP                = 0x4
-	IPPROTO_IPPC                = 0x43
-	IPPROTO_IPV4                = 0x4
-	IPPROTO_IPV6                = 0x29
-	IPPROTO_IRTP                = 0x1c
-	IPPROTO_KRYPTOLAN           = 0x41
-	IPPROTO_LARP                = 0x5b
-	IPPROTO_LEAF1               = 0x19
-	IPPROTO_LEAF2               = 0x1a
-	IPPROTO_MAX                 = 0x100
-	IPPROTO_MAXID               = 0x34
-	IPPROTO_MEAS                = 0x13
-	IPPROTO_MHRP                = 0x30
-	IPPROTO_MICP                = 0x5f
-	IPPROTO_MTP                 = 0x5c
-	IPPROTO_MUX                 = 0x12
-	IPPROTO_ND                  = 0x4d
-	IPPROTO_NHRP                = 0x36
-	IPPROTO_NONE                = 0x3b
-	IPPROTO_NSP                 = 0x1f
-	IPPROTO_NVPII               = 0xb
-	IPPROTO_OSPFIGP             = 0x59
-	IPPROTO_PGM                 = 0x71
-	IPPROTO_PIGP                = 0x9
-	IPPROTO_PIM                 = 0x67
-	IPPROTO_PRM                 = 0x15
-	IPPROTO_PUP                 = 0xc
-	IPPROTO_PVP                 = 0x4b
-	IPPROTO_RAW                 = 0xff
-	IPPROTO_RCCMON              = 0xa
-	IPPROTO_RDP                 = 0x1b
-	IPPROTO_ROUTING             = 0x2b
-	IPPROTO_RSVP                = 0x2e
-	IPPROTO_RVD                 = 0x42
-	IPPROTO_SATEXPAK            = 0x40
-	IPPROTO_SATMON              = 0x45
-	IPPROTO_SCCSP               = 0x60
-	IPPROTO_SDRP                = 0x2a
-	IPPROTO_SEP                 = 0x21
-	IPPROTO_SRPC                = 0x5a
-	IPPROTO_ST                  = 0x7
-	IPPROTO_SVMTP               = 0x52
-	IPPROTO_SWIPE               = 0x35
-	IPPROTO_TCF                 = 0x57
-	IPPROTO_TCP                 = 0x6
-	IPPROTO_TP                  = 0x1d
-	IPPROTO_TPXX                = 0x27
-	IPPROTO_TRUNK1              = 0x17
-	IPPROTO_TRUNK2              = 0x18
-	IPPROTO_TTP                 = 0x54
-	IPPROTO_UDP                 = 0x11
-	IPPROTO_VINES               = 0x53
-	IPPROTO_VISA                = 0x46
-	IPPROTO_VMTP                = 0x51
-	IPPROTO_WBEXPAK             = 0x4f
-	IPPROTO_WBMON               = 0x4e
-	IPPROTO_WSN                 = 0x4a
-	IPPROTO_XNET                = 0xf
-	IPPROTO_XTP                 = 0x24
-	IPV6_BINDV6ONLY             = 0x1b
-	IPV6_CHECKSUM               = 0x1a
-	IPV6_DEFAULT_MULTICAST_HOPS = 0x1
-	IPV6_DEFAULT_MULTICAST_LOOP = 0x1
-	IPV6_DEFHLIM                = 0x40
-	IPV6_DSTOPTS                = 0x17
-	IPV6_FAITH                  = 0x1d
-	IPV6_FLOWINFO_MASK          = 0xffffff0f
-	IPV6_FLOWLABEL_MASK         = 0xffff0f00
-	IPV6_FRAGTTL                = 0x78
-	IPV6_FW_ADD                 = 0x1e
-	IPV6_FW_DEL                 = 0x1f
-	IPV6_FW_FLUSH               = 0x20
-	IPV6_FW_GET                 = 0x22
-	IPV6_FW_ZERO                = 0x21
-	IPV6_HLIMDEC                = 0x1
-	IPV6_HOPLIMIT               = 0x14
-	IPV6_HOPOPTS                = 0x16
-	IPV6_IPSEC_POLICY           = 0x1c
-	IPV6_JOIN_GROUP             = 0xc
-	IPV6_LEAVE_GROUP            = 0xd
-	IPV6_MAXHLIM                = 0xff
-	IPV6_MAXPACKET              = 0xffff
-	IPV6_MMTU                   = 0x500
-	IPV6_MULTICAST_HOPS         = 0xa
-	IPV6_MULTICAST_IF           = 0x9
-	IPV6_MULTICAST_LOOP         = 0xb
-	IPV6_NEXTHOP                = 0x15
-	IPV6_PKTINFO                = 0x13
-	IPV6_PKTOPTIONS             = 0x19
-	IPV6_PORTRANGE              = 0xe
-	IPV6_PORTRANGE_DEFAULT      = 0
-	IPV6_PORTRANGE_HIGH         = 0x1
-	IPV6_PORTRANGE_LOW          = 0x2
-	IPV6_RECVTCLASS             = 0x23
-	IPV6_RTHDR                  = 0x18
-	IPV6_RTHDR_LOOSE            = 0
-	IPV6_RTHDR_STRICT           = 0x1
-	IPV6_RTHDR_TYPE_0           = 0
-	IPV6_SOCKOPT_RESERVED1      = 0x3
-	IPV6_TCLASS                 = 0x24
-	IPV6_UNICAST_HOPS           = 0x4
-	IPV6_V6ONLY                 = 0x1b
-	IPV6_VERSION                = 0x60
-	IPV6_VERSION_MASK           = 0xf0
-	IP_ADD_MEMBERSHIP           = 0xc
-	IP_BOUND_IF                 = 0x19
-	IP_DEFAULT_MULTICAST_LOOP   = 0x1
-	IP_DEFAULT_MULTICAST_TTL    = 0x1
-	IP_DF                       = 0x4000
-	IP_DROP_MEMBERSHIP          = 0xd
-	IP_DUMMYNET_CONFIGURE       = 0x3c
-	IP_DUMMYNET_DEL             = 0x3d
-	IP_DUMMYNET_FLUSH           = 0x3e
-	IP_DUMMYNET_GET             = 0x40
-	IP_FAITH                    = 0x16
-	IP_FW_ADD                   = 0x28
-	IP_FW_DEL                   = 0x29
-	IP_FW_FLUSH                 = 0x2a
-	IP_FW_GET                   = 0x2c
-	IP_FW_RESETLOG              = 0x2d
-	IP_FW_ZERO                  = 0x2b
-	IP_HDRINCL                  = 0x2
-	IP_IPSEC_POLICY             = 0x15
-	IP_MAXPACKET                = 0xffff
-	IP_MAX_MEMBERSHIPS          = 0x14
-	IP_MF                       = 0x2000
-	IP_MSS                      = 0x240
-	IP_MULTICAST_IF             = 0x9
-	IP_MULTICAST_LOOP           = 0xb
-	IP_MULTICAST_TTL            = 0xa
-	IP_MULTICAST_VIF            = 0xe
-	IP_NAT__XXX                 = 0x37
-	IP_OFFMASK                  = 0x1fff
-	IP_OLD_FW_ADD               = 0x32
-	IP_OLD_FW_DEL               = 0x33
-	IP_OLD_FW_FLUSH             = 0x34
-	IP_OLD_FW_GET               = 0x36
-	IP_OLD_FW_RESETLOG          = 0x38
-	IP_OLD_FW_ZERO              = 0x35
-	IP_OPTIONS                  = 0x1
-	IP_PORTRANGE                = 0x13
-	IP_PORTRANGE_DEFAULT        = 0
-	IP_PORTRANGE_HIGH           = 0x1
-	IP_PORTRANGE_LOW            = 0x2
-	IP_RECVDSTADDR              = 0x7
-	IP_RECVIF                   = 0x14
-	IP_RECVOPTS                 = 0x5
-	IP_RECVRETOPTS              = 0x6
-	IP_RECVTTL                  = 0x18
-	IP_RETOPTS                  = 0x8
-	IP_RF                       = 0x8000
-	IP_RSVP_OFF                 = 0x10
-	IP_RSVP_ON                  = 0xf
-	IP_RSVP_VIF_OFF             = 0x12
-	IP_RSVP_VIF_ON              = 0x11
-	IP_STRIPHDR                 = 0x17
-	IP_TOS                      = 0x3
-	IP_TRAFFIC_MGT_BACKGROUND   = 0x41
-	IP_TTL                      = 0x4
-	MADV_CAN_REUSE              = 0x9
-	MADV_DONTNEED               = 0x4
-	MADV_FREE                   = 0x5
-	MADV_FREE_REUSABLE          = 0x7
-	MADV_FREE_REUSE             = 0x8
-	MADV_NORMAL                 = 0
-	MADV_RANDOM                 = 0x1
-	MADV_SEQUENTIAL             = 0x2
-	MADV_WILLNEED               = 0x3
-	MADV_ZERO_WIRED_PAGES       = 0x6
-	MAP_ANON                    = 0x1000
-	MAP_COPY                    = 0x2
-	MAP_FILE                    = 0
-	MAP_FIXED                   = 0x10
-	MAP_HASSEMAPHORE            = 0x200
-	MAP_NOCACHE                 = 0x400
-	MAP_NOEXTEND                = 0x100
-	MAP_NORESERVE               = 0x40
-	MAP_PRIVATE                 = 0x2
-	MAP_RENAME                  = 0x20
-	MAP_RESERVED0080            = 0x80
-	MAP_SHARED                  = 0x1
-	MCL_CURRENT                 = 0x1
-	MCL_FUTURE                  = 0x2
-	MSG_CTRUNC                  = 0x20
-	MSG_DONTROUTE               = 0x4
-	MSG_DONTWAIT                = 0x80
-	MSG_EOF                     = 0x100
-	MSG_EOR                     = 0x8
-	MSG_FLUSH                   = 0x400
-	MSG_HAVEMORE                = 0x2000
-	MSG_HOLD                    = 0x800
-	MSG_NEEDSA                  = 0x10000
-	MSG_OOB                     = 0x1
-	MSG_PEEK                    = 0x2
-	MSG_RCVMORE                 = 0x4000
-	MSG_SEND                    = 0x1000
-	MSG_TRUNC                   = 0x10
-	MSG_WAITALL                 = 0x40
-	MSG_WAITSTREAM              = 0x200
-	MS_ASYNC                    = 0x1
-	MS_DEACTIVATE               = 0x8
-	MS_INVALIDATE               = 0x2
-	MS_KILLPAGES                = 0x4
-	MS_SYNC                     = 0x10
-	NAME_MAX                    = 0xff
-	NET_RT_DUMP                 = 0x1
-	NET_RT_DUMP2                = 0x7
-	NET_RT_FLAGS                = 0x2
-	NET_RT_IFLIST               = 0x3
-	NET_RT_IFLIST2              = 0x6
-	NET_RT_MAXID                = 0x8
-	NET_RT_STAT                 = 0x4
-	NET_RT_TRASH                = 0x5
-	O_ACCMODE                   = 0x3
-	O_ALERT                     = 0x20000000
-	O_APPEND                    = 0x8
-	O_ASYNC                     = 0x40
-	O_CREAT                     = 0x200
-	O_DIRECTORY                 = 0x100000
-	O_DSYNC                     = 0x400000
-	O_EVTONLY                   = 0x8000
-	O_EXCL                      = 0x800
-	O_EXLOCK                    = 0x20
-	O_FSYNC                     = 0x80
-	O_NDELAY                    = 0x4
-	O_NOCTTY                    = 0x20000
-	O_NOFOLLOW                  = 0x100
-	O_NONBLOCK                  = 0x4
-	O_POPUP                     = 0x80000000
-	O_RDONLY                    = 0
-	O_RDWR                      = 0x2
-	O_SHLOCK                    = 0x10
-	O_SYMLINK                   = 0x200000
-	O_SYNC                      = 0x80
-	O_TRUNC                     = 0x400
-	O_WRONLY                    = 0x1
-	PROT_EXEC                   = 0x4
-	PROT_NONE                   = 0
-	PROT_READ                   = 0x1
-	PROT_WRITE                  = 0x2
-	PT_ATTACH                   = 0xa
-	PT_ATTACHEXC                = 0xe
-	PT_CONTINUE                 = 0x7
-	PT_DENY_ATTACH              = 0x1f
-	PT_DETACH                   = 0xb
-	PT_FIRSTMACH                = 0x20
-	PT_FORCEQUOTA               = 0x1e
-	PT_KILL                     = 0x8
-	PT_READ_D                   = 0x2
-	PT_READ_I                   = 0x1
-	PT_READ_U                   = 0x3
-	PT_SIGEXC                   = 0xc
-	PT_STEP                     = 0x9
-	PT_THUPDATE                 = 0xd
-	PT_TRACE_ME                 = 0
-	PT_WRITE_D                  = 0x5
-	PT_WRITE_I                  = 0x4
-	PT_WRITE_U                  = 0x6
-	RTAX_AUTHOR                 = 0x6
-	RTAX_BRD                    = 0x7
-	RTAX_DST                    = 0
-	RTAX_GATEWAY                = 0x1
-	RTAX_GENMASK                = 0x3
-	RTAX_IFA                    = 0x5
-	RTAX_IFP                    = 0x4
-	RTAX_MAX                    = 0x8
-	RTAX_NETMASK                = 0x2
-	RTA_AUTHOR                  = 0x40
-	RTA_BRD                     = 0x80
-	RTA_DST                     = 0x1
-	RTA_GATEWAY                 = 0x2
-	RTA_GENMASK                 = 0x8
-	RTA_IFA                     = 0x20
-	RTA_IFP                     = 0x10
-	RTA_NETMASK                 = 0x4
-	RTF_BLACKHOLE               = 0x1000
-	RTF_BROADCAST               = 0x400000
-	RTF_CLONING                 = 0x100
-	RTF_CONDEMNED               = 0x2000000
-	RTF_DELCLONE                = 0x80
-	RTF_DONE                    = 0x40
-	RTF_DYNAMIC                 = 0x10
-	RTF_GATEWAY                 = 0x2
-	RTF_HOST                    = 0x4
-	RTF_IFREF                   = 0x4000000
-	RTF_IFSCOPE                 = 0x1000000
-	RTF_LLINFO                  = 0x400
-	RTF_LOCAL                   = 0x200000
-	RTF_MODIFIED                = 0x20
-	RTF_MULTICAST               = 0x800000
-	RTF_PINNED                  = 0x100000
-	RTF_PRCLONING               = 0x10000
-	RTF_PROTO1                  = 0x8000
-	RTF_PROTO2                  = 0x4000
-	RTF_PROTO3                  = 0x40000
-	RTF_REJECT                  = 0x8
-	RTF_STATIC                  = 0x800
-	RTF_UP                      = 0x1
-	RTF_WASCLONED               = 0x20000
-	RTF_XRESOLVE                = 0x200
-	RTM_ADD                     = 0x1
-	RTM_CHANGE                  = 0x3
-	RTM_DELADDR                 = 0xd
-	RTM_DELETE                  = 0x2
-	RTM_DELMADDR                = 0x10
-	RTM_GET                     = 0x4
-	RTM_GET2                    = 0x14
-	RTM_IFINFO                  = 0xe
-	RTM_IFINFO2                 = 0x12
-	RTM_LOCK                    = 0x8
-	RTM_LOSING                  = 0x5
-	RTM_MISS                    = 0x7
-	RTM_NEWADDR                 = 0xc
-	RTM_NEWMADDR                = 0xf
-	RTM_NEWMADDR2               = 0x13
-	RTM_OLDADD                  = 0x9
-	RTM_OLDDEL                  = 0xa
-	RTM_REDIRECT                = 0x6
-	RTM_RESOLVE                 = 0xb
-	RTM_RTTUNIT                 = 0xf4240
-	RTM_VERSION                 = 0x5
-	RTV_EXPIRE                  = 0x4
-	RTV_HOPCOUNT                = 0x2
-	RTV_MTU                     = 0x1
-	RTV_RPIPE                   = 0x8
-	RTV_RTT                     = 0x40
-	RTV_RTTVAR                  = 0x80
-	RTV_SPIPE                   = 0x10
-	RTV_SSTHRESH                = 0x20
-	SCM_CREDS                   = 0x3
-	SCM_RIGHTS                  = 0x1
-	SCM_TIMESTAMP               = 0x2
-	SHUT_RD                     = 0
-	SHUT_RDWR                   = 0x2
-	SHUT_WR                     = 0x1
-	SIGABRT                     = 0x6
-	SIGALRM                     = 0xe
-	SIGBUS                      = 0xa
-	SIGCHLD                     = 0x14
-	SIGCONT                     = 0x13
-	SIGEMT                      = 0x7
-	SIGFPE                      = 0x8
-	SIGHUP                      = 0x1
-	SIGILL                      = 0x4
-	SIGINFO                     = 0x1d
-	SIGINT                      = 0x2
-	SIGIO                       = 0x17
-	SIGIOT                      = 0x6
-	SIGKILL                     = 0x9
-	SIGPIPE                     = 0xd
-	SIGPROF                     = 0x1b
-	SIGQUIT                     = 0x3
-	SIGSEGV                     = 0xb
-	SIGSTOP                     = 0x11
-	SIGSYS                      = 0xc
-	SIGTERM                     = 0xf
-	SIGTRAP                     = 0x5
-	SIGTSTP                     = 0x12
-	SIGTTIN                     = 0x15
-	SIGTTOU                     = 0x16
-	SIGURG                      = 0x10
-	SIGUSR1                     = 0x1e
-	SIGUSR2                     = 0x1f
-	SIGVTALRM                   = 0x1a
-	SIGWINCH                    = 0x1c
-	SIGXCPU                     = 0x18
-	SIGXFSZ                     = 0x19
-	SIOCADDMULTI                = 0x80206931
-	SIOCAIFADDR                 = 0x8040691a
-	SIOCALIFADDR                = 0x8118691d
-	SIOCARPIPLL                 = 0xc0206928
-	SIOCATMARK                  = 0x40047307
-	SIOCAUTOADDR                = 0xc0206926
-	SIOCAUTONETMASK             = 0x80206927
-	SIOCDELMULTI                = 0x80206932
-	SIOCDIFADDR                 = 0x80206919
-	SIOCDIFPHYADDR              = 0x80206941
-	SIOCDLIFADDR                = 0x8118691f
-	SIOCGDRVSPEC                = 0xc028697b
-	SIOCGETSGCNT                = 0xc014721c
-	SIOCGETVIFCNT               = 0xc014721b
-	SIOCGETVLAN                 = 0xc020697f
-	SIOCGHIWAT                  = 0x40047301
-	SIOCGIFADDR                 = 0xc0206921
-	SIOCGIFALTMTU               = 0xc0206948
-	SIOCGIFASYNCMAP             = 0xc020697c
-	SIOCGIFBOND                 = 0xc0206947
-	SIOCGIFBRDADDR              = 0xc0206923
-	SIOCGIFCONF                 = 0xc00c6924
-	SIOCGIFDEVMTU               = 0xc0206944
-	SIOCGIFDSTADDR              = 0xc0206922
-	SIOCGIFFLAGS                = 0xc0206911
-	SIOCGIFGENERIC              = 0xc020693a
-	SIOCGIFKPI                  = 0xc0206987
-	SIOCGIFMAC                  = 0xc0206982
-	SIOCGIFMEDIA                = 0xc02c6938
-	SIOCGIFMETRIC               = 0xc0206917
-	SIOCGIFMTU                  = 0xc0206933
-	SIOCGIFNETMASK              = 0xc0206925
-	SIOCGIFPDSTADDR             = 0xc0206940
-	SIOCGIFPHYS                 = 0xc0206935
-	SIOCGIFPSRCADDR             = 0xc020693f
-	SIOCGIFSTATUS               = 0xc331693d
-	SIOCGIFVLAN                 = 0xc020697f
-	SIOCGIFWAKEFLAGS            = 0xc0206988
-	SIOCGLIFADDR                = 0xc118691e
-	SIOCGLIFPHYADDR             = 0xc1186943
-	SIOCGLOWAT                  = 0x40047303
-	SIOCGPGRP                   = 0x40047309
-	SIOCIFCREATE                = 0xc0206978
-	SIOCIFCREATE2               = 0xc020697a
-	SIOCIFDESTROY               = 0x80206979
-	SIOCRSLVMULTI               = 0xc010693b
-	SIOCSDRVSPEC                = 0x8028697b
-	SIOCSETVLAN                 = 0x8020697e
-	SIOCSHIWAT                  = 0x80047300
-	SIOCSIFADDR                 = 0x8020690c
-	SIOCSIFALTMTU               = 0x80206945
-	SIOCSIFASYNCMAP             = 0x8020697d
-	SIOCSIFBOND                 = 0x80206946
-	SIOCSIFBRDADDR              = 0x80206913
-	SIOCSIFDSTADDR              = 0x8020690e
-	SIOCSIFFLAGS                = 0x80206910
-	SIOCSIFGENERIC              = 0x80206939
-	SIOCSIFKPI                  = 0x80206986
-	SIOCSIFLLADDR               = 0x8020693c
-	SIOCSIFMAC                  = 0x80206983
-	SIOCSIFMEDIA                = 0xc0206937
-	SIOCSIFMETRIC               = 0x80206918
-	SIOCSIFMTU                  = 0x80206934
-	SIOCSIFNETMASK              = 0x80206916
-	SIOCSIFPHYADDR              = 0x8040693e
-	SIOCSIFPHYS                 = 0x80206936
-	SIOCSIFVLAN                 = 0x8020697e
-	SIOCSLIFPHYADDR             = 0x81186942
-	SIOCSLOWAT                  = 0x80047302
-	SIOCSPGRP                   = 0x80047308
-	SOCK_DGRAM                  = 0x2
-	SOCK_MAXADDRLEN             = 0xff
-	SOCK_RAW                    = 0x3
-	SOCK_RDM                    = 0x4
-	SOCK_SEQPACKET              = 0x5
-	SOCK_STREAM                 = 0x1
-	SOL_SOCKET                  = 0xffff
-	SOMAXCONN                   = 0x80
-	SO_ACCEPTCONN               = 0x2
-	SO_BROADCAST                = 0x20
-	SO_DEBUG                    = 0x1
-	SO_DONTROUTE                = 0x10
-	SO_DONTTRUNC                = 0x2000
-	SO_ERROR                    = 0x1007
-	SO_KEEPALIVE                = 0x8
-	SO_LABEL                    = 0x1010
-	SO_LINGER                   = 0x80
-	SO_LINGER_SEC               = 0x1080
-	SO_NKE                      = 0x1021
-	SO_NOADDRERR                = 0x1023
-	SO_NOSIGPIPE                = 0x1022
-	SO_NOTIFYCONFLICT           = 0x1026
-	SO_NP_EXTENSIONS            = 0x1083
-	SO_NREAD                    = 0x1020
-	SO_NWRITE                   = 0x1024
-	SO_OOBINLINE                = 0x100
-	SO_PEERLABEL                = 0x1011
-	SO_RANDOMPORT               = 0x1082
-	SO_RCVBUF                   = 0x1002
-	SO_RCVLOWAT                 = 0x1004
-	SO_RCVTIMEO                 = 0x1006
-	SO_RESTRICTIONS             = 0x1081
-	SO_RESTRICT_DENYIN          = 0x1
-	SO_RESTRICT_DENYOUT         = 0x2
-	SO_RESTRICT_DENYSET         = 0x80000000
-	SO_REUSEADDR                = 0x4
-	SO_REUSEPORT                = 0x200
-	SO_REUSESHAREUID            = 0x1025
-	SO_SNDBUF                   = 0x1001
-	SO_SNDLOWAT                 = 0x1003
-	SO_SNDTIMEO                 = 0x1005
-	SO_TIMESTAMP                = 0x400
-	SO_TYPE                     = 0x1008
-	SO_UPCALLCLOSEWAIT          = 0x1027
-	SO_USELOOPBACK              = 0x40
-	SO_WANTMORE                 = 0x4000
-	SO_WANTOOBFLAG              = 0x8000
-	S_IEXEC                     = 0x40
-	S_IFBLK                     = 0x6000
-	S_IFCHR                     = 0x2000
-	S_IFDIR                     = 0x4000
-	S_IFIFO                     = 0x1000
-	S_IFLNK                     = 0xa000
-	S_IFMT                      = 0xf000
-	S_IFREG                     = 0x8000
-	S_IFSOCK                    = 0xc000
-	S_IFWHT                     = 0xe000
-	S_IREAD                     = 0x100
-	S_IRGRP                     = 0x20
-	S_IROTH                     = 0x4
-	S_IRUSR                     = 0x100
-	S_IRWXG                     = 0x38
-	S_IRWXO                     = 0x7
-	S_IRWXU                     = 0x1c0
-	S_ISGID                     = 0x400
-	S_ISTXT                     = 0x200
-	S_ISUID                     = 0x800
-	S_ISVTX                     = 0x200
-	S_IWGRP                     = 0x10
-	S_IWOTH                     = 0x2
-	S_IWRITE                    = 0x80
-	S_IWUSR                     = 0x80
-	S_IXGRP                     = 0x8
-	S_IXOTH                     = 0x1
-	S_IXUSR                     = 0x40
-	TCP_CONNECTIONTIMEOUT       = 0x20
-	TCP_KEEPALIVE               = 0x10
-	TCP_MAXBURST                = 0x4
-	TCP_MAXHLEN                 = 0x3c
-	TCP_MAXOLEN                 = 0x28
-	TCP_MAXSEG                  = 0x2
-	TCP_MAXWIN                  = 0xffff
-	TCP_MAX_SACK                = 0x3
-	TCP_MAX_WINSHIFT            = 0xe
-	TCP_MINMSS                  = 0xd8
-	TCP_MINMSSOVERLOAD          = 0x3e8
-	TCP_MSS                     = 0x200
-	TCP_NODELAY                 = 0x1
-	TCP_NOOPT                   = 0x8
-	TCP_NOPUSH                  = 0x4
-	TIOCCBRK                    = 0x2000747a
-	TIOCCDTR                    = 0x20007478
-	TIOCCONS                    = 0x80047462
-	TIOCDCDTIMESTAMP            = 0x40107458
-	TIOCDRAIN                   = 0x2000745e
-	TIOCDSIMICROCODE            = 0x20007455
-	TIOCEXCL                    = 0x2000740d
-	TIOCEXT                     = 0x80047460
-	TIOCFLUSH                   = 0x80047410
-	TIOCGDRAINWAIT              = 0x40047456
-	TIOCGETA                    = 0x40487413
-	TIOCGETD                    = 0x4004741a
-	TIOCGPGRP                   = 0x40047477
-	TIOCGWINSZ                  = 0x40087468
-	TIOCIXOFF                   = 0x20007480
-	TIOCIXON                    = 0x20007481
-	TIOCMBIC                    = 0x8004746b
-	TIOCMBIS                    = 0x8004746c
-	TIOCMGDTRWAIT               = 0x4004745a
-	TIOCMGET                    = 0x4004746a
-	TIOCMODG                    = 0x40047403
-	TIOCMODS                    = 0x80047404
-	TIOCMSDTRWAIT               = 0x8004745b
-	TIOCMSET                    = 0x8004746d
-	TIOCM_CAR                   = 0x40
-	TIOCM_CD                    = 0x40
-	TIOCM_CTS                   = 0x20
-	TIOCM_DSR                   = 0x100
-	TIOCM_DTR                   = 0x2
-	TIOCM_LE                    = 0x1
-	TIOCM_RI                    = 0x80
-	TIOCM_RNG                   = 0x80
-	TIOCM_RTS                   = 0x4
-	TIOCM_SR                    = 0x10
-	TIOCM_ST                    = 0x8
-	TIOCNOTTY                   = 0x20007471
-	TIOCNXCL                    = 0x2000740e
-	TIOCOUTQ                    = 0x40047473
-	TIOCPKT                     = 0x80047470
-	TIOCPKT_DATA                = 0
-	TIOCPKT_DOSTOP              = 0x20
-	TIOCPKT_FLUSHREAD           = 0x1
-	TIOCPKT_FLUSHWRITE          = 0x2
-	TIOCPKT_IOCTL               = 0x40
-	TIOCPKT_NOSTOP              = 0x10
-	TIOCPKT_START               = 0x8
-	TIOCPKT_STOP                = 0x4
-	TIOCPTYGNAME                = 0x40807453
-	TIOCPTYGRANT                = 0x20007454
-	TIOCPTYUNLK                 = 0x20007452
-	TIOCREMOTE                  = 0x80047469
-	TIOCSBRK                    = 0x2000747b
-	TIOCSCONS                   = 0x20007463
-	TIOCSCTTY                   = 0x20007461
-	TIOCSDRAINWAIT              = 0x80047457
-	TIOCSDTR                    = 0x20007479
-	TIOCSETA                    = 0x80487414
-	TIOCSETAF                   = 0x80487416
-	TIOCSETAW                   = 0x80487415
-	TIOCSETD                    = 0x8004741b
-	TIOCSIG                     = 0x2000745f
-	TIOCSPGRP                   = 0x80047476
-	TIOCSTART                   = 0x2000746e
-	TIOCSTAT                    = 0x20007465
-	TIOCSTI                     = 0x80017472
-	TIOCSTOP                    = 0x2000746f
-	TIOCSWINSZ                  = 0x80087467
-	TIOCTIMESTAMP               = 0x40107459
-	TIOCUCNTL                   = 0x80047466
-	WCONTINUED                  = 0x10
-	WCOREFLAG                   = 0x80
-	WEXITED                     = 0x4
-	WNOHANG                     = 0x1
-	WNOWAIT                     = 0x20
-	WORDSIZE                    = 0x40
-	WSTOPPED                    = 0x8
-	WUNTRACED                   = 0x2
+	AF_APPLETALK                      = 0x10
+	AF_CCITT                          = 0xa
+	AF_CHAOS                          = 0x5
+	AF_CNT                            = 0x15
+	AF_COIP                           = 0x14
+	AF_DATAKIT                        = 0x9
+	AF_DECnet                         = 0xc
+	AF_DLI                            = 0xd
+	AF_E164                           = 0x1c
+	AF_ECMA                           = 0x8
+	AF_HYLINK                         = 0xf
+	AF_IEEE80211                      = 0x25
+	AF_IMPLINK                        = 0x3
+	AF_INET                           = 0x2
+	AF_INET6                          = 0x1e
+	AF_IPX                            = 0x17
+	AF_ISDN                           = 0x1c
+	AF_ISO                            = 0x7
+	AF_LAT                            = 0xe
+	AF_LINK                           = 0x12
+	AF_LOCAL                          = 0x1
+	AF_MAX                            = 0x26
+	AF_NATM                           = 0x1f
+	AF_NDRV                           = 0x1b
+	AF_NETBIOS                        = 0x21
+	AF_NS                             = 0x6
+	AF_OSI                            = 0x7
+	AF_PPP                            = 0x22
+	AF_PUP                            = 0x4
+	AF_RESERVED_36                    = 0x24
+	AF_ROUTE                          = 0x11
+	AF_SIP                            = 0x18
+	AF_SNA                            = 0xb
+	AF_SYSTEM                         = 0x20
+	AF_UNIX                           = 0x1
+	AF_UNSPEC                         = 0x0
+	BIOCFLUSH                         = 0x20004268
+	BIOCGBLEN                         = 0x40044266
+	BIOCGDLT                          = 0x4004426a
+	BIOCGDLTLIST                      = 0xc00c4279
+	BIOCGETIF                         = 0x4020426b
+	BIOCGHDRCMPLT                     = 0x40044274
+	BIOCGRSIG                         = 0x40044272
+	BIOCGRTIMEOUT                     = 0x4010426e
+	BIOCGSEESENT                      = 0x40044276
+	BIOCGSTATS                        = 0x4008426f
+	BIOCIMMEDIATE                     = 0x80044270
+	BIOCPROMISC                       = 0x20004269
+	BIOCSBLEN                         = 0xc0044266
+	BIOCSDLT                          = 0x80044278
+	BIOCSETF                          = 0x80104267
+	BIOCSETIF                         = 0x8020426c
+	BIOCSHDRCMPLT                     = 0x80044275
+	BIOCSRSIG                         = 0x80044273
+	BIOCSRTIMEOUT                     = 0x8010426d
+	BIOCSSEESENT                      = 0x80044277
+	BIOCVERSION                       = 0x40044271
+	BPF_A                             = 0x10
+	BPF_ABS                           = 0x20
+	BPF_ADD                           = 0x0
+	BPF_ALIGNMENT                     = 0x4
+	BPF_ALU                           = 0x4
+	BPF_AND                           = 0x50
+	BPF_B                             = 0x10
+	BPF_DIV                           = 0x30
+	BPF_H                             = 0x8
+	BPF_IMM                           = 0x0
+	BPF_IND                           = 0x40
+	BPF_JA                            = 0x0
+	BPF_JEQ                           = 0x10
+	BPF_JGE                           = 0x30
+	BPF_JGT                           = 0x20
+	BPF_JMP                           = 0x5
+	BPF_JSET                          = 0x40
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
+	BPF_LDX                           = 0x1
+	BPF_LEN                           = 0x80
+	BPF_LSH                           = 0x60
+	BPF_MAJOR_VERSION                 = 0x1
+	BPF_MAXBUFSIZE                    = 0x80000
+	BPF_MAXINSNS                      = 0x200
+	BPF_MEM                           = 0x60
+	BPF_MEMWORDS                      = 0x10
+	BPF_MINBUFSIZE                    = 0x20
+	BPF_MINOR_VERSION                 = 0x1
+	BPF_MISC                          = 0x7
+	BPF_MSH                           = 0xa0
+	BPF_MUL                           = 0x20
+	BPF_NEG                           = 0x80
+	BPF_OR                            = 0x40
+	BPF_RELEASE                       = 0x30bb6
+	BPF_RET                           = 0x6
+	BPF_RSH                           = 0x70
+	BPF_ST                            = 0x2
+	BPF_STX                           = 0x3
+	BPF_SUB                           = 0x10
+	BPF_TAX                           = 0x0
+	BPF_TXA                           = 0x80
+	BPF_W                             = 0x0
+	BPF_X                             = 0x8
+	CTL_MAXNAME                       = 0xc
+	CTL_NET                           = 0x4
+	DLT_APPLE_IP_OVER_IEEE1394        = 0x8a
+	DLT_ARCNET                        = 0x7
+	DLT_ATM_CLIP                      = 0x13
+	DLT_ATM_RFC1483                   = 0xb
+	DLT_AX25                          = 0x3
+	DLT_CHAOS                         = 0x5
+	DLT_CHDLC                         = 0x68
+	DLT_C_HDLC                        = 0x68
+	DLT_EN10MB                        = 0x1
+	DLT_EN3MB                         = 0x2
+	DLT_FDDI                          = 0xa
+	DLT_IEEE802                       = 0x6
+	DLT_IEEE802_11                    = 0x69
+	DLT_IEEE802_11_RADIO              = 0x7f
+	DLT_IEEE802_11_RADIO_AVS          = 0xa3
+	DLT_LINUX_SLL                     = 0x71
+	DLT_LOOP                          = 0x6c
+	DLT_NULL                          = 0x0
+	DLT_PFLOG                         = 0x75
+	DLT_PFSYNC                        = 0x12
+	DLT_PPP                           = 0x9
+	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_SERIAL                    = 0x32
+	DLT_PRONET                        = 0x4
+	DLT_RAW                           = 0xc
+	DLT_SLIP                          = 0x8
+	DLT_SLIP_BSDOS                    = 0xf
+	DT_BLK                            = 0x6
+	DT_CHR                            = 0x2
+	DT_DIR                            = 0x4
+	DT_FIFO                           = 0x1
+	DT_LNK                            = 0xa
+	DT_REG                            = 0x8
+	DT_SOCK                           = 0xc
+	DT_UNKNOWN                        = 0x0
+	DT_WHT                            = 0xe
+	ECHO                              = 0x8
+	ECHOCTL                           = 0x40
+	ECHOE                             = 0x2
+	ECHOK                             = 0x4
+	ECHOKE                            = 0x1
+	ECHONL                            = 0x10
+	ECHOPRT                           = 0x20
+	EVFILT_AIO                        = -0x3
+	EVFILT_FS                         = -0x9
+	EVFILT_MACHPORT                   = -0x8
+	EVFILT_PROC                       = -0x5
+	EVFILT_READ                       = -0x1
+	EVFILT_SIGNAL                     = -0x6
+	EVFILT_SYSCOUNT                   = 0xc
+	EVFILT_THREADMARKER               = 0xc
+	EVFILT_TIMER                      = -0x7
+	EVFILT_USER                       = -0xa
+	EVFILT_VM                         = -0xc
+	EVFILT_VNODE                      = -0x4
+	EVFILT_WRITE                      = -0x2
+	EV_ADD                            = 0x1
+	EV_CLEAR                          = 0x20
+	EV_DELETE                         = 0x2
+	EV_DISABLE                        = 0x8
+	EV_DISPATCH                       = 0x80
+	EV_ENABLE                         = 0x4
+	EV_EOF                            = 0x8000
+	EV_ERROR                          = 0x4000
+	EV_FLAG0                          = 0x1000
+	EV_FLAG1                          = 0x2000
+	EV_ONESHOT                        = 0x10
+	EV_OOBAND                         = 0x2000
+	EV_POLL                           = 0x1000
+	EV_RECEIPT                        = 0x40
+	EV_SYSFLAGS                       = 0xf000
+	EXTA                              = 0x4b00
+	EXTB                              = 0x9600
+	EXTPROC                           = 0x800
+	FD_CLOEXEC                        = 0x1
+	FD_SETSIZE                        = 0x400
+	F_ADDFILESIGS                     = 0x3d
+	F_ADDSIGS                         = 0x3b
+	F_ALLOCATEALL                     = 0x4
+	F_ALLOCATECONTIG                  = 0x2
+	F_CHKCLEAN                        = 0x29
+	F_DUPFD                           = 0x0
+	F_DUPFD_CLOEXEC                   = 0x43
+	F_FLUSH_DATA                      = 0x28
+	F_FREEZE_FS                       = 0x35
+	F_FULLFSYNC                       = 0x33
+	F_GETFD                           = 0x1
+	F_GETFL                           = 0x3
+	F_GETLK                           = 0x7
+	F_GETLKPID                        = 0x42
+	F_GETNOSIGPIPE                    = 0x4a
+	F_GETOWN                          = 0x5
+	F_GETPATH                         = 0x32
+	F_GETPATH_MTMINFO                 = 0x47
+	F_GETPROTECTIONCLASS              = 0x3f
+	F_GLOBAL_NOCACHE                  = 0x37
+	F_LOG2PHYS                        = 0x31
+	F_LOG2PHYS_EXT                    = 0x41
+	F_MARKDEPENDENCY                  = 0x3c
+	F_NOCACHE                         = 0x30
+	F_NODIRECT                        = 0x3e
+	F_OK                              = 0x0
+	F_PATHPKG_CHECK                   = 0x34
+	F_PEOFPOSMODE                     = 0x3
+	F_PREALLOCATE                     = 0x2a
+	F_RDADVISE                        = 0x2c
+	F_RDAHEAD                         = 0x2d
+	F_RDLCK                           = 0x1
+	F_READBOOTSTRAP                   = 0x2e
+	F_SETBACKINGSTORE                 = 0x46
+	F_SETFD                           = 0x2
+	F_SETFL                           = 0x4
+	F_SETLK                           = 0x8
+	F_SETLKW                          = 0x9
+	F_SETNOSIGPIPE                    = 0x49
+	F_SETOWN                          = 0x6
+	F_SETPROTECTIONCLASS              = 0x40
+	F_SETSIZE                         = 0x2b
+	F_THAW_FS                         = 0x36
+	F_UNLCK                           = 0x2
+	F_VOLPOSMODE                      = 0x4
+	F_WRITEBOOTSTRAP                  = 0x2f
+	F_WRLCK                           = 0x3
+	IFF_ALLMULTI                      = 0x200
+	IFF_ALTPHYS                       = 0x4000
+	IFF_BROADCAST                     = 0x2
+	IFF_DEBUG                         = 0x4
+	IFF_LINK0                         = 0x1000
+	IFF_LINK1                         = 0x2000
+	IFF_LINK2                         = 0x4000
+	IFF_LOOPBACK                      = 0x8
+	IFF_MULTICAST                     = 0x8000
+	IFF_NOARP                         = 0x80
+	IFF_NOTRAILERS                    = 0x20
+	IFF_OACTIVE                       = 0x400
+	IFF_POINTOPOINT                   = 0x10
+	IFF_PROMISC                       = 0x100
+	IFF_RUNNING                       = 0x40
+	IFF_SIMPLEX                       = 0x800
+	IFF_UP                            = 0x1
+	IFNAMSIZ                          = 0x10
+	IFT_1822                          = 0x2
+	IFT_AAL5                          = 0x31
+	IFT_ARCNET                        = 0x23
+	IFT_ARCNETPLUS                    = 0x24
+	IFT_ATM                           = 0x25
+	IFT_BRIDGE                        = 0xd1
+	IFT_CARP                          = 0xf8
+	IFT_CELLULAR                      = 0xff
+	IFT_CEPT                          = 0x13
+	IFT_DS3                           = 0x1e
+	IFT_ENC                           = 0xf4
+	IFT_EON                           = 0x19
+	IFT_ETHER                         = 0x6
+	IFT_FAITH                         = 0x38
+	IFT_FDDI                          = 0xf
+	IFT_FRELAY                        = 0x20
+	IFT_FRELAYDCE                     = 0x2c
+	IFT_GIF                           = 0x37
+	IFT_HDH1822                       = 0x3
+	IFT_HIPPI                         = 0x2f
+	IFT_HSSI                          = 0x2e
+	IFT_HY                            = 0xe
+	IFT_IEEE1394                      = 0x90
+	IFT_IEEE8023ADLAG                 = 0x88
+	IFT_ISDNBASIC                     = 0x14
+	IFT_ISDNPRIMARY                   = 0x15
+	IFT_ISO88022LLC                   = 0x29
+	IFT_ISO88023                      = 0x7
+	IFT_ISO88024                      = 0x8
+	IFT_ISO88025                      = 0x9
+	IFT_ISO88026                      = 0xa
+	IFT_L2VLAN                        = 0x87
+	IFT_LAPB                          = 0x10
+	IFT_LOCALTALK                     = 0x2a
+	IFT_LOOP                          = 0x18
+	IFT_MIOX25                        = 0x26
+	IFT_MODEM                         = 0x30
+	IFT_NSIP                          = 0x1b
+	IFT_OTHER                         = 0x1
+	IFT_P10                           = 0xc
+	IFT_P80                           = 0xd
+	IFT_PARA                          = 0x22
+	IFT_PDP                           = 0xff
+	IFT_PFLOG                         = 0xf5
+	IFT_PFSYNC                        = 0xf6
+	IFT_PPP                           = 0x17
+	IFT_PROPMUX                       = 0x36
+	IFT_PROPVIRTUAL                   = 0x35
+	IFT_PTPSERIAL                     = 0x16
+	IFT_RS232                         = 0x21
+	IFT_SDLC                          = 0x11
+	IFT_SIP                           = 0x1f
+	IFT_SLIP                          = 0x1c
+	IFT_SMDSDXI                       = 0x2b
+	IFT_SMDSICIP                      = 0x34
+	IFT_SONET                         = 0x27
+	IFT_SONETPATH                     = 0x32
+	IFT_SONETVT                       = 0x33
+	IFT_STARLAN                       = 0xb
+	IFT_STF                           = 0x39
+	IFT_T1                            = 0x12
+	IFT_ULTRA                         = 0x1d
+	IFT_V35                           = 0x2d
+	IFT_X25                           = 0x5
+	IFT_X25DDN                        = 0x4
+	IFT_X25PLE                        = 0x28
+	IFT_XETHER                        = 0x1a
+	IN_CLASSA_HOST                    = 0xffffff
+	IN_CLASSA_MAX                     = 0x80
+	IN_CLASSA_NET                     = 0xff000000
+	IN_CLASSA_NSHIFT                  = 0x18
+	IN_CLASSB_HOST                    = 0xffff
+	IN_CLASSB_MAX                     = 0x10000
+	IN_CLASSB_NET                     = 0xffff0000
+	IN_CLASSB_NSHIFT                  = 0x10
+	IN_CLASSC_HOST                    = 0xff
+	IN_CLASSC_NET                     = 0xffffff00
+	IN_CLASSC_NSHIFT                  = 0x8
+	IN_CLASSD_HOST                    = 0xfffffff
+	IN_CLASSD_NET                     = 0xf0000000
+	IN_CLASSD_NSHIFT                  = 0x1c
+	IN_LINKLOCALNETNUM                = 0xa9fe0000
+	IN_LOOPBACKNET                    = 0x7f
+	IPPROTO_3PC                       = 0x22
+	IPPROTO_ADFS                      = 0x44
+	IPPROTO_AH                        = 0x33
+	IPPROTO_AHIP                      = 0x3d
+	IPPROTO_APES                      = 0x63
+	IPPROTO_ARGUS                     = 0xd
+	IPPROTO_AX25                      = 0x5d
+	IPPROTO_BHA                       = 0x31
+	IPPROTO_BLT                       = 0x1e
+	IPPROTO_BRSATMON                  = 0x4c
+	IPPROTO_CFTP                      = 0x3e
+	IPPROTO_CHAOS                     = 0x10
+	IPPROTO_CMTP                      = 0x26
+	IPPROTO_CPHB                      = 0x49
+	IPPROTO_CPNX                      = 0x48
+	IPPROTO_DDP                       = 0x25
+	IPPROTO_DGP                       = 0x56
+	IPPROTO_DIVERT                    = 0xfe
+	IPPROTO_DONE                      = 0x101
+	IPPROTO_DSTOPTS                   = 0x3c
+	IPPROTO_EGP                       = 0x8
+	IPPROTO_EMCON                     = 0xe
+	IPPROTO_ENCAP                     = 0x62
+	IPPROTO_EON                       = 0x50
+	IPPROTO_ESP                       = 0x32
+	IPPROTO_ETHERIP                   = 0x61
+	IPPROTO_FRAGMENT                  = 0x2c
+	IPPROTO_GGP                       = 0x3
+	IPPROTO_GMTP                      = 0x64
+	IPPROTO_GRE                       = 0x2f
+	IPPROTO_HELLO                     = 0x3f
+	IPPROTO_HMP                       = 0x14
+	IPPROTO_HOPOPTS                   = 0x0
+	IPPROTO_ICMP                      = 0x1
+	IPPROTO_ICMPV6                    = 0x3a
+	IPPROTO_IDP                       = 0x16
+	IPPROTO_IDPR                      = 0x23
+	IPPROTO_IDRP                      = 0x2d
+	IPPROTO_IGMP                      = 0x2
+	IPPROTO_IGP                       = 0x55
+	IPPROTO_IGRP                      = 0x58
+	IPPROTO_IL                        = 0x28
+	IPPROTO_INLSP                     = 0x34
+	IPPROTO_INP                       = 0x20
+	IPPROTO_IP                        = 0x0
+	IPPROTO_IPCOMP                    = 0x6c
+	IPPROTO_IPCV                      = 0x47
+	IPPROTO_IPEIP                     = 0x5e
+	IPPROTO_IPIP                      = 0x4
+	IPPROTO_IPPC                      = 0x43
+	IPPROTO_IPV4                      = 0x4
+	IPPROTO_IPV6                      = 0x29
+	IPPROTO_IRTP                      = 0x1c
+	IPPROTO_KRYPTOLAN                 = 0x41
+	IPPROTO_LARP                      = 0x5b
+	IPPROTO_LEAF1                     = 0x19
+	IPPROTO_LEAF2                     = 0x1a
+	IPPROTO_MAX                       = 0x100
+	IPPROTO_MAXID                     = 0x34
+	IPPROTO_MEAS                      = 0x13
+	IPPROTO_MHRP                      = 0x30
+	IPPROTO_MICP                      = 0x5f
+	IPPROTO_MTP                       = 0x5c
+	IPPROTO_MUX                       = 0x12
+	IPPROTO_ND                        = 0x4d
+	IPPROTO_NHRP                      = 0x36
+	IPPROTO_NONE                      = 0x3b
+	IPPROTO_NSP                       = 0x1f
+	IPPROTO_NVPII                     = 0xb
+	IPPROTO_OSPFIGP                   = 0x59
+	IPPROTO_PGM                       = 0x71
+	IPPROTO_PIGP                      = 0x9
+	IPPROTO_PIM                       = 0x67
+	IPPROTO_PRM                       = 0x15
+	IPPROTO_PUP                       = 0xc
+	IPPROTO_PVP                       = 0x4b
+	IPPROTO_RAW                       = 0xff
+	IPPROTO_RCCMON                    = 0xa
+	IPPROTO_RDP                       = 0x1b
+	IPPROTO_ROUTING                   = 0x2b
+	IPPROTO_RSVP                      = 0x2e
+	IPPROTO_RVD                       = 0x42
+	IPPROTO_SATEXPAK                  = 0x40
+	IPPROTO_SATMON                    = 0x45
+	IPPROTO_SCCSP                     = 0x60
+	IPPROTO_SCTP                      = 0x84
+	IPPROTO_SDRP                      = 0x2a
+	IPPROTO_SEP                       = 0x21
+	IPPROTO_SRPC                      = 0x5a
+	IPPROTO_ST                        = 0x7
+	IPPROTO_SVMTP                     = 0x52
+	IPPROTO_SWIPE                     = 0x35
+	IPPROTO_TCF                       = 0x57
+	IPPROTO_TCP                       = 0x6
+	IPPROTO_TP                        = 0x1d
+	IPPROTO_TPXX                      = 0x27
+	IPPROTO_TRUNK1                    = 0x17
+	IPPROTO_TRUNK2                    = 0x18
+	IPPROTO_TTP                       = 0x54
+	IPPROTO_UDP                       = 0x11
+	IPPROTO_VINES                     = 0x53
+	IPPROTO_VISA                      = 0x46
+	IPPROTO_VMTP                      = 0x51
+	IPPROTO_WBEXPAK                   = 0x4f
+	IPPROTO_WBMON                     = 0x4e
+	IPPROTO_WSN                       = 0x4a
+	IPPROTO_XNET                      = 0xf
+	IPPROTO_XTP                       = 0x24
+	IPV6_2292DSTOPTS                  = 0x17
+	IPV6_2292HOPLIMIT                 = 0x14
+	IPV6_2292HOPOPTS                  = 0x16
+	IPV6_2292NEXTHOP                  = 0x15
+	IPV6_2292PKTINFO                  = 0x13
+	IPV6_2292PKTOPTIONS               = 0x19
+	IPV6_2292RTHDR                    = 0x18
+	IPV6_BINDV6ONLY                   = 0x1b
+	IPV6_BOUND_IF                     = 0x7d
+	IPV6_CHECKSUM                     = 0x1a
+	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
+	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
+	IPV6_DEFHLIM                      = 0x40
+	IPV6_FAITH                        = 0x1d
+	IPV6_FLOWINFO_MASK                = 0xffffff0f
+	IPV6_FLOWLABEL_MASK               = 0xffff0f00
+	IPV6_FRAGTTL                      = 0x78
+	IPV6_FW_ADD                       = 0x1e
+	IPV6_FW_DEL                       = 0x1f
+	IPV6_FW_FLUSH                     = 0x20
+	IPV6_FW_GET                       = 0x22
+	IPV6_FW_ZERO                      = 0x21
+	IPV6_HLIMDEC                      = 0x1
+	IPV6_IPSEC_POLICY                 = 0x1c
+	IPV6_JOIN_GROUP                   = 0xc
+	IPV6_LEAVE_GROUP                  = 0xd
+	IPV6_MAXHLIM                      = 0xff
+	IPV6_MAXOPTHDR                    = 0x800
+	IPV6_MAXPACKET                    = 0xffff
+	IPV6_MAX_GROUP_SRC_FILTER         = 0x200
+	IPV6_MAX_MEMBERSHIPS              = 0xfff
+	IPV6_MAX_SOCK_SRC_FILTER          = 0x80
+	IPV6_MIN_MEMBERSHIPS              = 0x1f
+	IPV6_MMTU                         = 0x500
+	IPV6_MULTICAST_HOPS               = 0xa
+	IPV6_MULTICAST_IF                 = 0x9
+	IPV6_MULTICAST_LOOP               = 0xb
+	IPV6_PORTRANGE                    = 0xe
+	IPV6_PORTRANGE_DEFAULT            = 0x0
+	IPV6_PORTRANGE_HIGH               = 0x1
+	IPV6_PORTRANGE_LOW                = 0x2
+	IPV6_RECVTCLASS                   = 0x23
+	IPV6_RTHDR_LOOSE                  = 0x0
+	IPV6_RTHDR_STRICT                 = 0x1
+	IPV6_RTHDR_TYPE_0                 = 0x0
+	IPV6_SOCKOPT_RESERVED1            = 0x3
+	IPV6_TCLASS                       = 0x24
+	IPV6_UNICAST_HOPS                 = 0x4
+	IPV6_V6ONLY                       = 0x1b
+	IPV6_VERSION                      = 0x60
+	IPV6_VERSION_MASK                 = 0xf0
+	IP_ADD_MEMBERSHIP                 = 0xc
+	IP_ADD_SOURCE_MEMBERSHIP          = 0x46
+	IP_BLOCK_SOURCE                   = 0x48
+	IP_BOUND_IF                       = 0x19
+	IP_DEFAULT_MULTICAST_LOOP         = 0x1
+	IP_DEFAULT_MULTICAST_TTL          = 0x1
+	IP_DF                             = 0x4000
+	IP_DROP_MEMBERSHIP                = 0xd
+	IP_DROP_SOURCE_MEMBERSHIP         = 0x47
+	IP_DUMMYNET_CONFIGURE             = 0x3c
+	IP_DUMMYNET_DEL                   = 0x3d
+	IP_DUMMYNET_FLUSH                 = 0x3e
+	IP_DUMMYNET_GET                   = 0x40
+	IP_FAITH                          = 0x16
+	IP_FW_ADD                         = 0x28
+	IP_FW_DEL                         = 0x29
+	IP_FW_FLUSH                       = 0x2a
+	IP_FW_GET                         = 0x2c
+	IP_FW_RESETLOG                    = 0x2d
+	IP_FW_ZERO                        = 0x2b
+	IP_HDRINCL                        = 0x2
+	IP_IPSEC_POLICY                   = 0x15
+	IP_MAXPACKET                      = 0xffff
+	IP_MAX_GROUP_SRC_FILTER           = 0x200
+	IP_MAX_MEMBERSHIPS                = 0xfff
+	IP_MAX_SOCK_MUTE_FILTER           = 0x80
+	IP_MAX_SOCK_SRC_FILTER            = 0x80
+	IP_MF                             = 0x2000
+	IP_MIN_MEMBERSHIPS                = 0x1f
+	IP_MSFILTER                       = 0x4a
+	IP_MSS                            = 0x240
+	IP_MULTICAST_IF                   = 0x9
+	IP_MULTICAST_IFINDEX              = 0x42
+	IP_MULTICAST_LOOP                 = 0xb
+	IP_MULTICAST_TTL                  = 0xa
+	IP_MULTICAST_VIF                  = 0xe
+	IP_NAT__XXX                       = 0x37
+	IP_OFFMASK                        = 0x1fff
+	IP_OLD_FW_ADD                     = 0x32
+	IP_OLD_FW_DEL                     = 0x33
+	IP_OLD_FW_FLUSH                   = 0x34
+	IP_OLD_FW_GET                     = 0x36
+	IP_OLD_FW_RESETLOG                = 0x38
+	IP_OLD_FW_ZERO                    = 0x35
+	IP_OPTIONS                        = 0x1
+	IP_PKTINFO                        = 0x1a
+	IP_PORTRANGE                      = 0x13
+	IP_PORTRANGE_DEFAULT              = 0x0
+	IP_PORTRANGE_HIGH                 = 0x1
+	IP_PORTRANGE_LOW                  = 0x2
+	IP_RECVDSTADDR                    = 0x7
+	IP_RECVIF                         = 0x14
+	IP_RECVOPTS                       = 0x5
+	IP_RECVPKTINFO                    = 0x1a
+	IP_RECVRETOPTS                    = 0x6
+	IP_RECVTTL                        = 0x18
+	IP_RETOPTS                        = 0x8
+	IP_RF                             = 0x8000
+	IP_RSVP_OFF                       = 0x10
+	IP_RSVP_ON                        = 0xf
+	IP_RSVP_VIF_OFF                   = 0x12
+	IP_RSVP_VIF_ON                    = 0x11
+	IP_STRIPHDR                       = 0x17
+	IP_TOS                            = 0x3
+	IP_TRAFFIC_MGT_BACKGROUND         = 0x41
+	IP_TTL                            = 0x4
+	IP_UNBLOCK_SOURCE                 = 0x49
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
+	MADV_CAN_REUSE                    = 0x9
+	MADV_DONTNEED                     = 0x4
+	MADV_FREE                         = 0x5
+	MADV_FREE_REUSABLE                = 0x7
+	MADV_FREE_REUSE                   = 0x8
+	MADV_NORMAL                       = 0x0
+	MADV_RANDOM                       = 0x1
+	MADV_SEQUENTIAL                   = 0x2
+	MADV_WILLNEED                     = 0x3
+	MADV_ZERO_WIRED_PAGES             = 0x6
+	MAP_ANON                          = 0x1000
+	MAP_COPY                          = 0x2
+	MAP_FILE                          = 0x0
+	MAP_FIXED                         = 0x10
+	MAP_HASSEMAPHORE                  = 0x200
+	MAP_JIT                           = 0x800
+	MAP_NOCACHE                       = 0x400
+	MAP_NOEXTEND                      = 0x100
+	MAP_NORESERVE                     = 0x40
+	MAP_PRIVATE                       = 0x2
+	MAP_RENAME                        = 0x20
+	MAP_RESERVED0080                  = 0x80
+	MAP_SHARED                        = 0x1
+	MCL_CURRENT                       = 0x1
+	MCL_FUTURE                        = 0x2
+	MSG_CTRUNC                        = 0x20
+	MSG_DONTROUTE                     = 0x4
+	MSG_DONTWAIT                      = 0x80
+	MSG_EOF                           = 0x100
+	MSG_EOR                           = 0x8
+	MSG_FLUSH                         = 0x400
+	MSG_HAVEMORE                      = 0x2000
+	MSG_HOLD                          = 0x800
+	MSG_NEEDSA                        = 0x10000
+	MSG_OOB                           = 0x1
+	MSG_PEEK                          = 0x2
+	MSG_RCVMORE                       = 0x4000
+	MSG_SEND                          = 0x1000
+	MSG_TRUNC                         = 0x10
+	MSG_WAITALL                       = 0x40
+	MSG_WAITSTREAM                    = 0x200
+	MS_ASYNC                          = 0x1
+	MS_DEACTIVATE                     = 0x8
+	MS_INVALIDATE                     = 0x2
+	MS_KILLPAGES                      = 0x4
+	MS_SYNC                           = 0x10
+	NAME_MAX                          = 0xff
+	NET_RT_DUMP                       = 0x1
+	NET_RT_DUMP2                      = 0x7
+	NET_RT_FLAGS                      = 0x2
+	NET_RT_IFLIST                     = 0x3
+	NET_RT_IFLIST2                    = 0x6
+	NET_RT_MAXID                      = 0xa
+	NET_RT_STAT                       = 0x4
+	NET_RT_TRASH                      = 0x5
+	NOTE_ABSOLUTE                     = 0x8
+	NOTE_ATTRIB                       = 0x8
+	NOTE_CHILD                        = 0x4
+	NOTE_DELETE                       = 0x1
+	NOTE_EXEC                         = 0x20000000
+	NOTE_EXIT                         = 0x80000000
+	NOTE_EXITSTATUS                   = 0x4000000
+	NOTE_EXTEND                       = 0x4
+	NOTE_FFAND                        = 0x40000000
+	NOTE_FFCOPY                       = 0xc0000000
+	NOTE_FFCTRLMASK                   = 0xc0000000
+	NOTE_FFLAGSMASK                   = 0xffffff
+	NOTE_FFNOP                        = 0x0
+	NOTE_FFOR                         = 0x80000000
+	NOTE_FORK                         = 0x40000000
+	NOTE_LINK                         = 0x10
+	NOTE_LOWAT                        = 0x1
+	NOTE_NONE                         = 0x80
+	NOTE_NSECONDS                     = 0x4
+	NOTE_PCTRLMASK                    = -0x100000
+	NOTE_PDATAMASK                    = 0xfffff
+	NOTE_REAP                         = 0x10000000
+	NOTE_RENAME                       = 0x20
+	NOTE_RESOURCEEND                  = 0x2000000
+	NOTE_REVOKE                       = 0x40
+	NOTE_SECONDS                      = 0x1
+	NOTE_SIGNAL                       = 0x8000000
+	NOTE_TRACK                        = 0x1
+	NOTE_TRACKERR                     = 0x2
+	NOTE_TRIGGER                      = 0x1000000
+	NOTE_USECONDS                     = 0x2
+	NOTE_VM_ERROR                     = 0x10000000
+	NOTE_VM_PRESSURE                  = 0x80000000
+	NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000
+	NOTE_VM_PRESSURE_TERMINATE        = 0x40000000
+	NOTE_WRITE                        = 0x2
+	O_ACCMODE                         = 0x3
+	O_ALERT                           = 0x20000000
+	O_APPEND                          = 0x8
+	O_ASYNC                           = 0x40
+	O_CLOEXEC                         = 0x1000000
+	O_CREAT                           = 0x200
+	O_DIRECTORY                       = 0x100000
+	O_DSYNC                           = 0x400000
+	O_EVTONLY                         = 0x8000
+	O_EXCL                            = 0x800
+	O_EXLOCK                          = 0x20
+	O_FSYNC                           = 0x80
+	O_NDELAY                          = 0x4
+	O_NOCTTY                          = 0x20000
+	O_NOFOLLOW                        = 0x100
+	O_NONBLOCK                        = 0x4
+	O_POPUP                           = 0x80000000
+	O_RDONLY                          = 0x0
+	O_RDWR                            = 0x2
+	O_SHLOCK                          = 0x10
+	O_SYMLINK                         = 0x200000
+	O_SYNC                            = 0x80
+	O_TRUNC                           = 0x400
+	O_WRONLY                          = 0x1
+	PROT_EXEC                         = 0x4
+	PROT_NONE                         = 0x0
+	PROT_READ                         = 0x1
+	PROT_WRITE                        = 0x2
+	PT_ATTACH                         = 0xa
+	PT_ATTACHEXC                      = 0xe
+	PT_CONTINUE                       = 0x7
+	PT_DENY_ATTACH                    = 0x1f
+	PT_DETACH                         = 0xb
+	PT_FIRSTMACH                      = 0x20
+	PT_FORCEQUOTA                     = 0x1e
+	PT_KILL                           = 0x8
+	PT_READ_D                         = 0x2
+	PT_READ_I                         = 0x1
+	PT_READ_U                         = 0x3
+	PT_SIGEXC                         = 0xc
+	PT_STEP                           = 0x9
+	PT_THUPDATE                       = 0xd
+	PT_TRACE_ME                       = 0x0
+	PT_WRITE_D                        = 0x5
+	PT_WRITE_I                        = 0x4
+	PT_WRITE_U                        = 0x6
+	RLIMIT_AS                         = 0x5
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
+	RTAX_AUTHOR                       = 0x6
+	RTAX_BRD                          = 0x7
+	RTAX_DST                          = 0x0
+	RTAX_GATEWAY                      = 0x1
+	RTAX_GENMASK                      = 0x3
+	RTAX_IFA                          = 0x5
+	RTAX_IFP                          = 0x4
+	RTAX_MAX                          = 0x8
+	RTAX_NETMASK                      = 0x2
+	RTA_AUTHOR                        = 0x40
+	RTA_BRD                           = 0x80
+	RTA_DST                           = 0x1
+	RTA_GATEWAY                       = 0x2
+	RTA_GENMASK                       = 0x8
+	RTA_IFA                           = 0x20
+	RTA_IFP                           = 0x10
+	RTA_NETMASK                       = 0x4
+	RTF_BLACKHOLE                     = 0x1000
+	RTF_BROADCAST                     = 0x400000
+	RTF_CLONING                       = 0x100
+	RTF_CONDEMNED                     = 0x2000000
+	RTF_DELCLONE                      = 0x80
+	RTF_DONE                          = 0x40
+	RTF_DYNAMIC                       = 0x10
+	RTF_GATEWAY                       = 0x2
+	RTF_HOST                          = 0x4
+	RTF_IFREF                         = 0x4000000
+	RTF_IFSCOPE                       = 0x1000000
+	RTF_LLINFO                        = 0x400
+	RTF_LOCAL                         = 0x200000
+	RTF_MODIFIED                      = 0x20
+	RTF_MULTICAST                     = 0x800000
+	RTF_PINNED                        = 0x100000
+	RTF_PRCLONING                     = 0x10000
+	RTF_PROTO1                        = 0x8000
+	RTF_PROTO2                        = 0x4000
+	RTF_PROTO3                        = 0x40000
+	RTF_REJECT                        = 0x8
+	RTF_STATIC                        = 0x800
+	RTF_UP                            = 0x1
+	RTF_WASCLONED                     = 0x20000
+	RTF_XRESOLVE                      = 0x200
+	RTM_ADD                           = 0x1
+	RTM_CHANGE                        = 0x3
+	RTM_DELADDR                       = 0xd
+	RTM_DELETE                        = 0x2
+	RTM_DELMADDR                      = 0x10
+	RTM_GET                           = 0x4
+	RTM_GET2                          = 0x14
+	RTM_IFINFO                        = 0xe
+	RTM_IFINFO2                       = 0x12
+	RTM_LOCK                          = 0x8
+	RTM_LOSING                        = 0x5
+	RTM_MISS                          = 0x7
+	RTM_NEWADDR                       = 0xc
+	RTM_NEWMADDR                      = 0xf
+	RTM_NEWMADDR2                     = 0x13
+	RTM_OLDADD                        = 0x9
+	RTM_OLDDEL                        = 0xa
+	RTM_REDIRECT                      = 0x6
+	RTM_RESOLVE                       = 0xb
+	RTM_RTTUNIT                       = 0xf4240
+	RTM_VERSION                       = 0x5
+	RTV_EXPIRE                        = 0x4
+	RTV_HOPCOUNT                      = 0x2
+	RTV_MTU                           = 0x1
+	RTV_RPIPE                         = 0x8
+	RTV_RTT                           = 0x40
+	RTV_RTTVAR                        = 0x80
+	RTV_SPIPE                         = 0x10
+	RTV_SSTHRESH                      = 0x20
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	SCM_CREDS                         = 0x3
+	SCM_RIGHTS                        = 0x1
+	SCM_TIMESTAMP                     = 0x2
+	SCM_TIMESTAMP_MONOTONIC           = 0x4
+	SHUT_RD                           = 0x0
+	SHUT_RDWR                         = 0x2
+	SHUT_WR                           = 0x1
+	SIGABRT                           = 0x6
+	SIGALRM                           = 0xe
+	SIGBUS                            = 0xa
+	SIGCHLD                           = 0x14
+	SIGCONT                           = 0x13
+	SIGEMT                            = 0x7
+	SIGFPE                            = 0x8
+	SIGHUP                            = 0x1
+	SIGILL                            = 0x4
+	SIGINFO                           = 0x1d
+	SIGINT                            = 0x2
+	SIGIO                             = 0x17
+	SIGIOT                            = 0x6
+	SIGKILL                           = 0x9
+	SIGPIPE                           = 0xd
+	SIGPROF                           = 0x1b
+	SIGQUIT                           = 0x3
+	SIGSEGV                           = 0xb
+	SIGSTOP                           = 0x11
+	SIGSYS                            = 0xc
+	SIGTERM                           = 0xf
+	SIGTRAP                           = 0x5
+	SIGTSTP                           = 0x12
+	SIGTTIN                           = 0x15
+	SIGTTOU                           = 0x16
+	SIGURG                            = 0x10
+	SIGUSR1                           = 0x1e
+	SIGUSR2                           = 0x1f
+	SIGVTALRM                         = 0x1a
+	SIGWINCH                          = 0x1c
+	SIGXCPU                           = 0x18
+	SIGXFSZ                           = 0x19
+	SIOCADDMULTI                      = 0x80206931
+	SIOCAIFADDR                       = 0x8040691a
+	SIOCALIFADDR                      = 0x8118691d
+	SIOCARPIPLL                       = 0xc0206928
+	SIOCATMARK                        = 0x40047307
+	SIOCAUTOADDR                      = 0xc0206926
+	SIOCAUTONETMASK                   = 0x80206927
+	SIOCDELMULTI                      = 0x80206932
+	SIOCDIFADDR                       = 0x80206919
+	SIOCDIFPHYADDR                    = 0x80206941
+	SIOCDLIFADDR                      = 0x8118691f
+	SIOCGDRVSPEC                      = 0xc028697b
+	SIOCGETSGCNT                      = 0xc014721c
+	SIOCGETVIFCNT                     = 0xc014721b
+	SIOCGETVLAN                       = 0xc020697f
+	SIOCGHIWAT                        = 0x40047301
+	SIOCGIFADDR                       = 0xc0206921
+	SIOCGIFALTMTU                     = 0xc0206948
+	SIOCGIFASYNCMAP                   = 0xc020697c
+	SIOCGIFBOND                       = 0xc0206947
+	SIOCGIFBRDADDR                    = 0xc0206923
+	SIOCGIFCAP                        = 0xc020695b
+	SIOCGIFCONF                       = 0xc00c6924
+	SIOCGIFDEVMTU                     = 0xc0206944
+	SIOCGIFDSTADDR                    = 0xc0206922
+	SIOCGIFFLAGS                      = 0xc0206911
+	SIOCGIFGENERIC                    = 0xc020693a
+	SIOCGIFKPI                        = 0xc0206987
+	SIOCGIFMAC                        = 0xc0206982
+	SIOCGIFMEDIA                      = 0xc02c6938
+	SIOCGIFMETRIC                     = 0xc0206917
+	SIOCGIFMTU                        = 0xc0206933
+	SIOCGIFNETMASK                    = 0xc0206925
+	SIOCGIFPDSTADDR                   = 0xc0206940
+	SIOCGIFPHYS                       = 0xc0206935
+	SIOCGIFPSRCADDR                   = 0xc020693f
+	SIOCGIFSTATUS                     = 0xc331693d
+	SIOCGIFVLAN                       = 0xc020697f
+	SIOCGIFWAKEFLAGS                  = 0xc0206988
+	SIOCGLIFADDR                      = 0xc118691e
+	SIOCGLIFPHYADDR                   = 0xc1186943
+	SIOCGLOWAT                        = 0x40047303
+	SIOCGPGRP                         = 0x40047309
+	SIOCIFCREATE                      = 0xc0206978
+	SIOCIFCREATE2                     = 0xc020697a
+	SIOCIFDESTROY                     = 0x80206979
+	SIOCRSLVMULTI                     = 0xc010693b
+	SIOCSDRVSPEC                      = 0x8028697b
+	SIOCSETVLAN                       = 0x8020697e
+	SIOCSHIWAT                        = 0x80047300
+	SIOCSIFADDR                       = 0x8020690c
+	SIOCSIFALTMTU                     = 0x80206945
+	SIOCSIFASYNCMAP                   = 0x8020697d
+	SIOCSIFBOND                       = 0x80206946
+	SIOCSIFBRDADDR                    = 0x80206913
+	SIOCSIFCAP                        = 0x8020695a
+	SIOCSIFDSTADDR                    = 0x8020690e
+	SIOCSIFFLAGS                      = 0x80206910
+	SIOCSIFGENERIC                    = 0x80206939
+	SIOCSIFKPI                        = 0x80206986
+	SIOCSIFLLADDR                     = 0x8020693c
+	SIOCSIFMAC                        = 0x80206983
+	SIOCSIFMEDIA                      = 0xc0206937
+	SIOCSIFMETRIC                     = 0x80206918
+	SIOCSIFMTU                        = 0x80206934
+	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFPHYADDR                    = 0x8040693e
+	SIOCSIFPHYS                       = 0x80206936
+	SIOCSIFVLAN                       = 0x8020697e
+	SIOCSLIFPHYADDR                   = 0x81186942
+	SIOCSLOWAT                        = 0x80047302
+	SIOCSPGRP                         = 0x80047308
+	SOCK_DGRAM                        = 0x2
+	SOCK_MAXADDRLEN                   = 0xff
+	SOCK_RAW                          = 0x3
+	SOCK_RDM                          = 0x4
+	SOCK_SEQPACKET                    = 0x5
+	SOCK_STREAM                       = 0x1
+	SOL_SOCKET                        = 0xffff
+	SOMAXCONN                         = 0x80
+	SO_ACCEPTCONN                     = 0x2
+	SO_BROADCAST                      = 0x20
+	SO_DEBUG                          = 0x1
+	SO_DONTROUTE                      = 0x10
+	SO_DONTTRUNC                      = 0x2000
+	SO_ERROR                          = 0x1007
+	SO_KEEPALIVE                      = 0x8
+	SO_LABEL                          = 0x1010
+	SO_LINGER                         = 0x80
+	SO_LINGER_SEC                     = 0x1080
+	SO_NKE                            = 0x1021
+	SO_NOADDRERR                      = 0x1023
+	SO_NOSIGPIPE                      = 0x1022
+	SO_NOTIFYCONFLICT                 = 0x1026
+	SO_NP_EXTENSIONS                  = 0x1083
+	SO_NREAD                          = 0x1020
+	SO_NWRITE                         = 0x1024
+	SO_OOBINLINE                      = 0x100
+	SO_PEERLABEL                      = 0x1011
+	SO_RANDOMPORT                     = 0x1082
+	SO_RCVBUF                         = 0x1002
+	SO_RCVLOWAT                       = 0x1004
+	SO_RCVTIMEO                       = 0x1006
+	SO_RESTRICTIONS                   = 0x1081
+	SO_RESTRICT_DENYIN                = 0x1
+	SO_RESTRICT_DENYOUT               = 0x2
+	SO_RESTRICT_DENYSET               = 0x80000000
+	SO_REUSEADDR                      = 0x4
+	SO_REUSEPORT                      = 0x200
+	SO_REUSESHAREUID                  = 0x1025
+	SO_SNDBUF                         = 0x1001
+	SO_SNDLOWAT                       = 0x1003
+	SO_SNDTIMEO                       = 0x1005
+	SO_TIMESTAMP                      = 0x400
+	SO_TIMESTAMP_MONOTONIC            = 0x800
+	SO_TYPE                           = 0x1008
+	SO_UPCALLCLOSEWAIT                = 0x1027
+	SO_USELOOPBACK                    = 0x40
+	SO_WANTMORE                       = 0x4000
+	SO_WANTOOBFLAG                    = 0x8000
+	S_IEXEC                           = 0x40
+	S_IFBLK                           = 0x6000
+	S_IFCHR                           = 0x2000
+	S_IFDIR                           = 0x4000
+	S_IFIFO                           = 0x1000
+	S_IFLNK                           = 0xa000
+	S_IFMT                            = 0xf000
+	S_IFREG                           = 0x8000
+	S_IFSOCK                          = 0xc000
+	S_IFWHT                           = 0xe000
+	S_IREAD                           = 0x100
+	S_IRGRP                           = 0x20
+	S_IROTH                           = 0x4
+	S_IRUSR                           = 0x100
+	S_IRWXG                           = 0x38
+	S_IRWXO                           = 0x7
+	S_IRWXU                           = 0x1c0
+	S_ISGID                           = 0x400
+	S_ISTXT                           = 0x200
+	S_ISUID                           = 0x800
+	S_ISVTX                           = 0x200
+	S_IWGRP                           = 0x10
+	S_IWOTH                           = 0x2
+	S_IWRITE                          = 0x80
+	S_IWUSR                           = 0x80
+	S_IXGRP                           = 0x8
+	S_IXOTH                           = 0x1
+	S_IXUSR                           = 0x40
+	TCP_CONNECTIONTIMEOUT             = 0x20
+	TCP_KEEPALIVE                     = 0x10
+	TCP_MAXHLEN                       = 0x3c
+	TCP_MAXOLEN                       = 0x28
+	TCP_MAXSEG                        = 0x2
+	TCP_MAXWIN                        = 0xffff
+	TCP_MAX_SACK                      = 0x3
+	TCP_MAX_WINSHIFT                  = 0xe
+	TCP_MINMSS                        = 0xd8
+	TCP_MINMSSOVERLOAD                = 0x3e8
+	TCP_MSS                           = 0x200
+	TCP_NODELAY                       = 0x1
+	TCP_NOOPT                         = 0x8
+	TCP_NOPUSH                        = 0x4
+	TCP_RXT_CONNDROPTIME              = 0x80
+	TCP_RXT_FINDROP                   = 0x100
+	TIOCCBRK                          = 0x2000747a
+	TIOCCDTR                          = 0x20007478
+	TIOCCONS                          = 0x80047462
+	TIOCDCDTIMESTAMP                  = 0x40107458
+	TIOCDRAIN                         = 0x2000745e
+	TIOCDSIMICROCODE                  = 0x20007455
+	TIOCEXCL                          = 0x2000740d
+	TIOCEXT                           = 0x80047460
+	TIOCFLUSH                         = 0x80047410
+	TIOCGDRAINWAIT                    = 0x40047456
+	TIOCGETA                          = 0x40487413
+	TIOCGETD                          = 0x4004741a
+	TIOCGPGRP                         = 0x40047477
+	TIOCGWINSZ                        = 0x40087468
+	TIOCIXOFF                         = 0x20007480
+	TIOCIXON                          = 0x20007481
+	TIOCMBIC                          = 0x8004746b
+	TIOCMBIS                          = 0x8004746c
+	TIOCMGDTRWAIT                     = 0x4004745a
+	TIOCMGET                          = 0x4004746a
+	TIOCMODG                          = 0x40047403
+	TIOCMODS                          = 0x80047404
+	TIOCMSDTRWAIT                     = 0x8004745b
+	TIOCMSET                          = 0x8004746d
+	TIOCM_CAR                         = 0x40
+	TIOCM_CD                          = 0x40
+	TIOCM_CTS                         = 0x20
+	TIOCM_DSR                         = 0x100
+	TIOCM_DTR                         = 0x2
+	TIOCM_LE                          = 0x1
+	TIOCM_RI                          = 0x80
+	TIOCM_RNG                         = 0x80
+	TIOCM_RTS                         = 0x4
+	TIOCM_SR                          = 0x10
+	TIOCM_ST                          = 0x8
+	TIOCNOTTY                         = 0x20007471
+	TIOCNXCL                          = 0x2000740e
+	TIOCOUTQ                          = 0x40047473
+	TIOCPKT                           = 0x80047470
+	TIOCPKT_DATA                      = 0x0
+	TIOCPKT_DOSTOP                    = 0x20
+	TIOCPKT_FLUSHREAD                 = 0x1
+	TIOCPKT_FLUSHWRITE                = 0x2
+	TIOCPKT_IOCTL                     = 0x40
+	TIOCPKT_NOSTOP                    = 0x10
+	TIOCPKT_START                     = 0x8
+	TIOCPKT_STOP                      = 0x4
+	TIOCPTYGNAME                      = 0x40807453
+	TIOCPTYGRANT                      = 0x20007454
+	TIOCPTYUNLK                       = 0x20007452
+	TIOCREMOTE                        = 0x80047469
+	TIOCSBRK                          = 0x2000747b
+	TIOCSCONS                         = 0x20007463
+	TIOCSCTTY                         = 0x20007461
+	TIOCSDRAINWAIT                    = 0x80047457
+	TIOCSDTR                          = 0x20007479
+	TIOCSETA                          = 0x80487414
+	TIOCSETAF                         = 0x80487416
+	TIOCSETAW                         = 0x80487415
+	TIOCSETD                          = 0x8004741b
+	TIOCSIG                           = 0x2000745f
+	TIOCSPGRP                         = 0x80047476
+	TIOCSTART                         = 0x2000746e
+	TIOCSTAT                          = 0x20007465
+	TIOCSTI                           = 0x80017472
+	TIOCSTOP                          = 0x2000746f
+	TIOCSWINSZ                        = 0x80087467
+	TIOCTIMESTAMP                     = 0x40107459
+	TIOCUCNTL                         = 0x80047466
+	WCONTINUED                        = 0x10
+	WCOREFLAG                         = 0x80
+	WEXITED                           = 0x4
+	WNOHANG                           = 0x1
+	WNOWAIT                           = 0x20
+	WORDSIZE                          = 0x40
+	WSTOPPED                          = 0x8
+	WUNTRACED                         = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADARCH        = Errno(0x56)
+	EBADEXEC        = Errno(0x55)
+	EBADF           = Errno(0x9)
+	EBADMACHO       = Errno(0x58)
+	EBADMSG         = Errno(0x5e)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x59)
+	ECHILD          = Errno(0xa)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDEVERR         = Errno(0x53)
+	EDOM            = Errno(0x21)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x5a)
+	EILSEQ          = Errno(0x5c)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x69)
+	ELOOP           = Errno(0x3e)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	EMULTIHOP       = Errno(0x5f)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x5d)
+	ENOBUFS         = Errno(0x37)
+	ENODATA         = Errno(0x60)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOLINK         = Errno(0x61)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x5b)
+	ENOPOLICY       = Errno(0x67)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x62)
+	ENOSTR          = Errno(0x63)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTRECOVERABLE = Errno(0x68)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x2d)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x66)
+	EOVERFLOW       = Errno(0x54)
+	EOWNERDEAD      = Errno(0x69)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTO          = Errno(0x64)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	EPWROFF         = Errno(0x52)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHLIBVERS      = Errno(0x57)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIME           = Errno(0x65)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
 
 // Error table
 var errors = [...]string{
@@ -1192,4 +1280,6 @@ var errors = [...]string{
 	101: "STREAM ioctl timeout",
 	102: "operation not supported on socket",
 	103: "policy not found",
+	104: "state not recoverable",
+	105: "previous owner died",
 }
diff --git a/src/pkg/syscall/zerrors_freebsd_386.go b/src/pkg/syscall/zerrors_freebsd_386.go
index a77e264..83243d0 100644
--- a/src/pkg/syscall/zerrors_freebsd_386.go
+++ b/src/pkg/syscall/zerrors_freebsd_386.go
@@ -1,13 +1,11 @@
-// mkerrors.sh -f -m32
+// mkerrors.sh -m32
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -f -m32 -gsyscall -f -m32 _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m32 _const.go
 
 package syscall
 
-// Constants
 const (
 	AF_APPLETALK                      = 0x10
 	AF_ARP                            = 0x23
@@ -45,7 +43,7 @@ const (
 	AF_SLOW                           = 0x21
 	AF_SNA                            = 0xb
 	AF_UNIX                           = 0x1
-	AF_UNSPEC                         = 0
+	AF_UNSPEC                         = 0x0
 	AF_VENDOR00                       = 0x27
 	AF_VENDOR01                       = 0x29
 	AF_VENDOR02                       = 0x2b
@@ -128,7 +126,7 @@ const (
 	BIOCVERSION                       = 0x40044271
 	BPF_A                             = 0x10
 	BPF_ABS                           = 0x20
-	BPF_ADD                           = 0
+	BPF_ADD                           = 0x0
 	BPF_ALIGNMENT                     = 0x4
 	BPF_ALU                           = 0x4
 	BPF_AND                           = 0x50
@@ -137,16 +135,16 @@ const (
 	BPF_BUFMODE_ZBUF                  = 0x2
 	BPF_DIV                           = 0x30
 	BPF_H                             = 0x8
-	BPF_IMM                           = 0
+	BPF_IMM                           = 0x0
 	BPF_IND                           = 0x40
-	BPF_JA                            = 0
+	BPF_JA                            = 0x0
 	BPF_JEQ                           = 0x10
 	BPF_JGE                           = 0x30
 	BPF_JGT                           = 0x20
 	BPF_JMP                           = 0x5
 	BPF_JSET                          = 0x40
-	BPF_K                             = 0
-	BPF_LD                            = 0
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
 	BPF_LDX                           = 0x1
 	BPF_LEN                           = 0x80
 	BPF_LSH                           = 0x60
@@ -168,9 +166,9 @@ const (
 	BPF_ST                            = 0x2
 	BPF_STX                           = 0x3
 	BPF_SUB                           = 0x10
-	BPF_TAX                           = 0
+	BPF_TAX                           = 0x0
 	BPF_TXA                           = 0x80
-	BPF_W                             = 0
+	BPF_W                             = 0x0
 	BPF_X                             = 0x8
 	CTL_MAXNAME                       = 0x18
 	CTL_NET                           = 0x4
@@ -260,7 +258,7 @@ const (
 	DLT_MTP2                          = 0x8c
 	DLT_MTP2_WITH_PHDR                = 0x8b
 	DLT_MTP3                          = 0x8d
-	DLT_NULL                          = 0
+	DLT_NULL                          = 0x0
 	DLT_PCI_EXP                       = 0x7d
 	DLT_PFLOG                         = 0x75
 	DLT_PFSYNC                        = 0x79
@@ -311,22 +309,8 @@ const (
 	DT_LNK                            = 0xa
 	DT_REG                            = 0x8
 	DT_SOCK                           = 0xc
-	DT_UNKNOWN                        = 0
+	DT_UNKNOWN                        = 0x0
 	DT_WHT                            = 0xe
-	E2BIG                             = 0x7
-	EACCES                            = 0xd
-	EADDRINUSE                        = 0x30
-	EADDRNOTAVAIL                     = 0x31
-	EAFNOSUPPORT                      = 0x2f
-	EAGAIN                            = 0x23
-	EALREADY                          = 0x25
-	EAUTH                             = 0x50
-	EBADF                             = 0x9
-	EBADMSG                           = 0x59
-	EBADRPC                           = 0x48
-	EBUSY                             = 0x10
-	ECANCELED                         = 0x55
-	ECHILD                            = 0xa
 	ECHO                              = 0x8
 	ECHOCTL                           = 0x40
 	ECHOE                             = 0x2
@@ -334,86 +318,6 @@ const (
 	ECHOKE                            = 0x1
 	ECHONL                            = 0x10
 	ECHOPRT                           = 0x20
-	ECONNABORTED                      = 0x35
-	ECONNREFUSED                      = 0x3d
-	ECONNRESET                        = 0x36
-	EDEADLK                           = 0xb
-	EDESTADDRREQ                      = 0x27
-	EDOM                              = 0x21
-	EDOOFUS                           = 0x58
-	EDQUOT                            = 0x45
-	EEXIST                            = 0x11
-	EFAULT                            = 0xe
-	EFBIG                             = 0x1b
-	EFTYPE                            = 0x4f
-	EHOSTDOWN                         = 0x40
-	EHOSTUNREACH                      = 0x41
-	EIDRM                             = 0x52
-	EILSEQ                            = 0x56
-	EINPROGRESS                       = 0x24
-	EINTR                             = 0x4
-	EINVAL                            = 0x16
-	EIO                               = 0x5
-	EISCONN                           = 0x38
-	EISDIR                            = 0x15
-	ELAST                             = 0x5d
-	ELOOP                             = 0x3e
-	EMFILE                            = 0x18
-	EMLINK                            = 0x1f
-	EMSGSIZE                          = 0x28
-	EMULTIHOP                         = 0x5a
-	ENAMETOOLONG                      = 0x3f
-	ENEEDAUTH                         = 0x51
-	ENETDOWN                          = 0x32
-	ENETRESET                         = 0x34
-	ENETUNREACH                       = 0x33
-	ENFILE                            = 0x17
-	ENOATTR                           = 0x57
-	ENOBUFS                           = 0x37
-	ENODEV                            = 0x13
-	ENOENT                            = 0x2
-	ENOEXEC                           = 0x8
-	ENOLCK                            = 0x4d
-	ENOLINK                           = 0x5b
-	ENOMEM                            = 0xc
-	ENOMSG                            = 0x53
-	ENOPROTOOPT                       = 0x2a
-	ENOSPC                            = 0x1c
-	ENOSYS                            = 0x4e
-	ENOTBLK                           = 0xf
-	ENOTCAPABLE                       = 0x5d
-	ENOTCONN                          = 0x39
-	ENOTDIR                           = 0x14
-	ENOTEMPTY                         = 0x42
-	ENOTSOCK                          = 0x26
-	ENOTSUP                           = 0x2d
-	ENOTTY                            = 0x19
-	ENXIO                             = 0x6
-	EOPNOTSUPP                        = 0x2d
-	EOVERFLOW                         = 0x54
-	EPERM                             = 0x1
-	EPFNOSUPPORT                      = 0x2e
-	EPIPE                             = 0x20
-	EPROCLIM                          = 0x43
-	EPROCUNAVAIL                      = 0x4c
-	EPROGMISMATCH                     = 0x4b
-	EPROGUNAVAIL                      = 0x4a
-	EPROTO                            = 0x5c
-	EPROTONOSUPPORT                   = 0x2b
-	EPROTOTYPE                        = 0x29
-	ERANGE                            = 0x22
-	EREMOTE                           = 0x47
-	EROFS                             = 0x1e
-	ERPCMISMATCH                      = 0x49
-	ESHUTDOWN                         = 0x3a
-	ESOCKTNOSUPPORT                   = 0x2c
-	ESPIPE                            = 0x1d
-	ESRCH                             = 0x3
-	ESTALE                            = 0x46
-	ETIMEDOUT                         = 0x3c
-	ETOOMANYREFS                      = 0x3b
-	ETXTBSY                           = 0x1a
-	EUSERS                            = 0x44
 	EVFILT_AIO                        = -0x3
 	EVFILT_FS                         = -0x9
 	EVFILT_LIO                        = -0xa
@@ -437,8 +341,6 @@ const (
 	EV_ONESHOT                        = 0x10
 	EV_RECEIPT                        = 0x40
 	EV_SYSFLAGS                       = 0xf000
-	EWOULDBLOCK                       = 0x23
-	EXDEV                             = 0x12
 	EXTA                              = 0x4b00
 	EXTB                              = 0x9600
 	EXTPROC                           = 0x800
@@ -446,12 +348,13 @@ const (
 	FD_SETSIZE                        = 0x400
 	F_CANCEL                          = 0x5
 	F_DUP2FD                          = 0xa
-	F_DUPFD                           = 0
+	F_DUPFD                           = 0x0
 	F_GETFD                           = 0x1
 	F_GETFL                           = 0x3
 	F_GETLK                           = 0xb
 	F_GETOWN                          = 0x5
 	F_OGETLK                          = 0x7
+	F_OK                              = 0x0
 	F_OSETLK                          = 0x8
 	F_OSETLKW                         = 0x9
 	F_RDAHEAD                         = 0x10
@@ -746,7 +649,7 @@ const (
 	IPPROTO_GRE                       = 0x2f
 	IPPROTO_HELLO                     = 0x3f
 	IPPROTO_HMP                       = 0x14
-	IPPROTO_HOPOPTS                   = 0
+	IPPROTO_HOPOPTS                   = 0x0
 	IPPROTO_ICMP                      = 0x1
 	IPPROTO_ICMPV6                    = 0x3a
 	IPPROTO_IDP                       = 0x16
@@ -758,7 +661,7 @@ const (
 	IPPROTO_IL                        = 0x28
 	IPPROTO_INLSP                     = 0x34
 	IPPROTO_INP                       = 0x20
-	IPPROTO_IP                        = 0
+	IPPROTO_IP                        = 0x0
 	IPPROTO_IPCOMP                    = 0x6c
 	IPPROTO_IPCV                      = 0x47
 	IPPROTO_IPEIP                     = 0x5e
@@ -868,7 +771,7 @@ const (
 	IPV6_PATHMTU                      = 0x2c
 	IPV6_PKTINFO                      = 0x2e
 	IPV6_PORTRANGE                    = 0xe
-	IPV6_PORTRANGE_DEFAULT            = 0
+	IPV6_PORTRANGE_DEFAULT            = 0x0
 	IPV6_PORTRANGE_HIGH               = 0x1
 	IPV6_PORTRANGE_LOW                = 0x2
 	IPV6_PREFER_TEMPADDR              = 0x3f
@@ -881,9 +784,9 @@ const (
 	IPV6_RECVTCLASS                   = 0x39
 	IPV6_RTHDR                        = 0x33
 	IPV6_RTHDRDSTOPTS                 = 0x23
-	IPV6_RTHDR_LOOSE                  = 0
+	IPV6_RTHDR_LOOSE                  = 0x0
 	IPV6_RTHDR_STRICT                 = 0x1
-	IPV6_RTHDR_TYPE_0                 = 0
+	IPV6_RTHDR_TYPE_0                 = 0x0
 	IPV6_SOCKOPT_RESERVED1            = 0x3
 	IPV6_TCLASS                       = 0x3d
 	IPV6_UNICAST_HOPS                 = 0x4
@@ -944,7 +847,7 @@ const (
 	IP_ONESBCAST                      = 0x17
 	IP_OPTIONS                        = 0x1
 	IP_PORTRANGE                      = 0x13
-	IP_PORTRANGE_DEFAULT              = 0
+	IP_PORTRANGE_DEFAULT              = 0x0
 	IP_PORTRANGE_HIGH                 = 0x1
 	IP_PORTRANGE_LOW                  = 0x2
 	IP_RECVDSTADDR                    = 0x7
@@ -962,6 +865,10 @@ const (
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
 	IP_UNBLOCK_SOURCE                 = 0x49
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
 	MSG_COMPAT                        = 0x8000
 	MSG_CTRUNC                        = 0x20
 	MSG_DONTROUTE                     = 0x4
@@ -994,16 +901,24 @@ const (
 	O_NOCTTY                          = 0x8000
 	O_NOFOLLOW                        = 0x100
 	O_NONBLOCK                        = 0x4
-	O_RDONLY                          = 0
+	O_RDONLY                          = 0x0
 	O_RDWR                            = 0x2
 	O_SHLOCK                          = 0x10
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_TTY_INIT                        = 0x80000
 	O_WRONLY                          = 0x1
+	RLIMIT_AS                         = 0xa
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
 	RTAX_AUTHOR                       = 0x6
 	RTAX_BRD                          = 0x7
-	RTAX_DST                          = 0
+	RTAX_DST                          = 0x0
 	RTAX_GATEWAY                      = 0x1
 	RTAX_GENMASK                      = 0x3
 	RTAX_IFA                          = 0x5
@@ -1070,11 +985,14 @@ const (
 	RTV_SPIPE                         = 0x10
 	RTV_SSTHRESH                      = 0x20
 	RTV_WEIGHT                        = 0x100
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	RUSAGE_THREAD                     = 0x1
 	SCM_BINTIME                       = 0x4
 	SCM_CREDS                         = 0x3
 	SCM_RIGHTS                        = 0x1
 	SCM_TIMESTAMP                     = 0x2
-	SHUT_RD                           = 0
+	SHUT_RD                           = 0x0
 	SHUT_RDWR                         = 0x2
 	SHUT_WR                           = 0x1
 	SIGABRT                           = 0x6
@@ -1270,7 +1188,7 @@ const (
 	TIOCNXCL                          = 0x2000740e
 	TIOCOUTQ                          = 0x40047473
 	TIOCPKT                           = 0x80047470
-	TIOCPKT_DATA                      = 0
+	TIOCPKT_DATA                      = 0x0
 	TIOCPKT_DOSTOP                    = 0x20
 	TIOCPKT_FLUSHREAD                 = 0x1
 	TIOCPKT_FLUSHWRITE                = 0x2
@@ -1305,7 +1223,105 @@ const (
 	WUNTRACED                         = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADF           = Errno(0x9)
+	EBADMSG         = Errno(0x59)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x55)
+	ECHILD          = Errno(0xa)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDOM            = Errno(0x21)
+	EDOOFUS         = Errno(0x58)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x52)
+	EILSEQ          = Errno(0x56)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x5d)
+	ELOOP           = Errno(0x3e)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	EMULTIHOP       = Errno(0x5a)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x57)
+	ENOBUFS         = Errno(0x37)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOLINK         = Errno(0x5b)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x53)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCAPABLE     = Errno(0x5d)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x2d)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x2d)
+	EOVERFLOW       = Errno(0x54)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTO          = Errno(0x5c)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
 
 // Error table
 var errors = [...]string{
diff --git a/src/pkg/syscall/zerrors_freebsd_amd64.go b/src/pkg/syscall/zerrors_freebsd_amd64.go
index ce3c7dd..61f69c9 100644
--- a/src/pkg/syscall/zerrors_freebsd_amd64.go
+++ b/src/pkg/syscall/zerrors_freebsd_amd64.go
@@ -1,13 +1,11 @@
-// mkerrors.sh -f -m64
+// mkerrors.sh -m64
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -f -m64 -gsyscall -f -m64 _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m64 _const.go
 
 package syscall
 
-// Constants
 const (
 	AF_APPLETALK                      = 0x10
 	AF_ARP                            = 0x23
@@ -45,7 +43,7 @@ const (
 	AF_SLOW                           = 0x21
 	AF_SNA                            = 0xb
 	AF_UNIX                           = 0x1
-	AF_UNSPEC                         = 0
+	AF_UNSPEC                         = 0x0
 	AF_VENDOR00                       = 0x27
 	AF_VENDOR01                       = 0x29
 	AF_VENDOR02                       = 0x2b
@@ -128,7 +126,7 @@ const (
 	BIOCVERSION                       = 0x40044271
 	BPF_A                             = 0x10
 	BPF_ABS                           = 0x20
-	BPF_ADD                           = 0
+	BPF_ADD                           = 0x0
 	BPF_ALIGNMENT                     = 0x8
 	BPF_ALU                           = 0x4
 	BPF_AND                           = 0x50
@@ -137,16 +135,16 @@ const (
 	BPF_BUFMODE_ZBUF                  = 0x2
 	BPF_DIV                           = 0x30
 	BPF_H                             = 0x8
-	BPF_IMM                           = 0
+	BPF_IMM                           = 0x0
 	BPF_IND                           = 0x40
-	BPF_JA                            = 0
+	BPF_JA                            = 0x0
 	BPF_JEQ                           = 0x10
 	BPF_JGE                           = 0x30
 	BPF_JGT                           = 0x20
 	BPF_JMP                           = 0x5
 	BPF_JSET                          = 0x40
-	BPF_K                             = 0
-	BPF_LD                            = 0
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
 	BPF_LDX                           = 0x1
 	BPF_LEN                           = 0x80
 	BPF_LSH                           = 0x60
@@ -168,9 +166,9 @@ const (
 	BPF_ST                            = 0x2
 	BPF_STX                           = 0x3
 	BPF_SUB                           = 0x10
-	BPF_TAX                           = 0
+	BPF_TAX                           = 0x0
 	BPF_TXA                           = 0x80
-	BPF_W                             = 0
+	BPF_W                             = 0x0
 	BPF_X                             = 0x8
 	CTL_MAXNAME                       = 0x18
 	CTL_NET                           = 0x4
@@ -260,7 +258,7 @@ const (
 	DLT_MTP2                          = 0x8c
 	DLT_MTP2_WITH_PHDR                = 0x8b
 	DLT_MTP3                          = 0x8d
-	DLT_NULL                          = 0
+	DLT_NULL                          = 0x0
 	DLT_PCI_EXP                       = 0x7d
 	DLT_PFLOG                         = 0x75
 	DLT_PFSYNC                        = 0x79
@@ -311,22 +309,8 @@ const (
 	DT_LNK                            = 0xa
 	DT_REG                            = 0x8
 	DT_SOCK                           = 0xc
-	DT_UNKNOWN                        = 0
+	DT_UNKNOWN                        = 0x0
 	DT_WHT                            = 0xe
-	E2BIG                             = 0x7
-	EACCES                            = 0xd
-	EADDRINUSE                        = 0x30
-	EADDRNOTAVAIL                     = 0x31
-	EAFNOSUPPORT                      = 0x2f
-	EAGAIN                            = 0x23
-	EALREADY                          = 0x25
-	EAUTH                             = 0x50
-	EBADF                             = 0x9
-	EBADMSG                           = 0x59
-	EBADRPC                           = 0x48
-	EBUSY                             = 0x10
-	ECANCELED                         = 0x55
-	ECHILD                            = 0xa
 	ECHO                              = 0x8
 	ECHOCTL                           = 0x40
 	ECHOE                             = 0x2
@@ -334,86 +318,6 @@ const (
 	ECHOKE                            = 0x1
 	ECHONL                            = 0x10
 	ECHOPRT                           = 0x20
-	ECONNABORTED                      = 0x35
-	ECONNREFUSED                      = 0x3d
-	ECONNRESET                        = 0x36
-	EDEADLK                           = 0xb
-	EDESTADDRREQ                      = 0x27
-	EDOM                              = 0x21
-	EDOOFUS                           = 0x58
-	EDQUOT                            = 0x45
-	EEXIST                            = 0x11
-	EFAULT                            = 0xe
-	EFBIG                             = 0x1b
-	EFTYPE                            = 0x4f
-	EHOSTDOWN                         = 0x40
-	EHOSTUNREACH                      = 0x41
-	EIDRM                             = 0x52
-	EILSEQ                            = 0x56
-	EINPROGRESS                       = 0x24
-	EINTR                             = 0x4
-	EINVAL                            = 0x16
-	EIO                               = 0x5
-	EISCONN                           = 0x38
-	EISDIR                            = 0x15
-	ELAST                             = 0x5d
-	ELOOP                             = 0x3e
-	EMFILE                            = 0x18
-	EMLINK                            = 0x1f
-	EMSGSIZE                          = 0x28
-	EMULTIHOP                         = 0x5a
-	ENAMETOOLONG                      = 0x3f
-	ENEEDAUTH                         = 0x51
-	ENETDOWN                          = 0x32
-	ENETRESET                         = 0x34
-	ENETUNREACH                       = 0x33
-	ENFILE                            = 0x17
-	ENOATTR                           = 0x57
-	ENOBUFS                           = 0x37
-	ENODEV                            = 0x13
-	ENOENT                            = 0x2
-	ENOEXEC                           = 0x8
-	ENOLCK                            = 0x4d
-	ENOLINK                           = 0x5b
-	ENOMEM                            = 0xc
-	ENOMSG                            = 0x53
-	ENOPROTOOPT                       = 0x2a
-	ENOSPC                            = 0x1c
-	ENOSYS                            = 0x4e
-	ENOTBLK                           = 0xf
-	ENOTCAPABLE                       = 0x5d
-	ENOTCONN                          = 0x39
-	ENOTDIR                           = 0x14
-	ENOTEMPTY                         = 0x42
-	ENOTSOCK                          = 0x26
-	ENOTSUP                           = 0x2d
-	ENOTTY                            = 0x19
-	ENXIO                             = 0x6
-	EOPNOTSUPP                        = 0x2d
-	EOVERFLOW                         = 0x54
-	EPERM                             = 0x1
-	EPFNOSUPPORT                      = 0x2e
-	EPIPE                             = 0x20
-	EPROCLIM                          = 0x43
-	EPROCUNAVAIL                      = 0x4c
-	EPROGMISMATCH                     = 0x4b
-	EPROGUNAVAIL                      = 0x4a
-	EPROTO                            = 0x5c
-	EPROTONOSUPPORT                   = 0x2b
-	EPROTOTYPE                        = 0x29
-	ERANGE                            = 0x22
-	EREMOTE                           = 0x47
-	EROFS                             = 0x1e
-	ERPCMISMATCH                      = 0x49
-	ESHUTDOWN                         = 0x3a
-	ESOCKTNOSUPPORT                   = 0x2c
-	ESPIPE                            = 0x1d
-	ESRCH                             = 0x3
-	ESTALE                            = 0x46
-	ETIMEDOUT                         = 0x3c
-	ETOOMANYREFS                      = 0x3b
-	ETXTBSY                           = 0x1a
-	EUSERS                            = 0x44
 	EVFILT_AIO                        = -0x3
 	EVFILT_FS                         = -0x9
 	EVFILT_LIO                        = -0xa
@@ -437,8 +341,6 @@ const (
 	EV_ONESHOT                        = 0x10
 	EV_RECEIPT                        = 0x40
 	EV_SYSFLAGS                       = 0xf000
-	EWOULDBLOCK                       = 0x23
-	EXDEV                             = 0x12
 	EXTA                              = 0x4b00
 	EXTB                              = 0x9600
 	EXTPROC                           = 0x800
@@ -446,12 +348,13 @@ const (
 	FD_SETSIZE                        = 0x400
 	F_CANCEL                          = 0x5
 	F_DUP2FD                          = 0xa
-	F_DUPFD                           = 0
+	F_DUPFD                           = 0x0
 	F_GETFD                           = 0x1
 	F_GETFL                           = 0x3
 	F_GETLK                           = 0xb
 	F_GETOWN                          = 0x5
 	F_OGETLK                          = 0x7
+	F_OK                              = 0x0
 	F_OSETLK                          = 0x8
 	F_OSETLKW                         = 0x9
 	F_RDAHEAD                         = 0x10
@@ -746,7 +649,7 @@ const (
 	IPPROTO_GRE                       = 0x2f
 	IPPROTO_HELLO                     = 0x3f
 	IPPROTO_HMP                       = 0x14
-	IPPROTO_HOPOPTS                   = 0
+	IPPROTO_HOPOPTS                   = 0x0
 	IPPROTO_ICMP                      = 0x1
 	IPPROTO_ICMPV6                    = 0x3a
 	IPPROTO_IDP                       = 0x16
@@ -758,7 +661,7 @@ const (
 	IPPROTO_IL                        = 0x28
 	IPPROTO_INLSP                     = 0x34
 	IPPROTO_INP                       = 0x20
-	IPPROTO_IP                        = 0
+	IPPROTO_IP                        = 0x0
 	IPPROTO_IPCOMP                    = 0x6c
 	IPPROTO_IPCV                      = 0x47
 	IPPROTO_IPEIP                     = 0x5e
@@ -868,7 +771,7 @@ const (
 	IPV6_PATHMTU                      = 0x2c
 	IPV6_PKTINFO                      = 0x2e
 	IPV6_PORTRANGE                    = 0xe
-	IPV6_PORTRANGE_DEFAULT            = 0
+	IPV6_PORTRANGE_DEFAULT            = 0x0
 	IPV6_PORTRANGE_HIGH               = 0x1
 	IPV6_PORTRANGE_LOW                = 0x2
 	IPV6_PREFER_TEMPADDR              = 0x3f
@@ -881,9 +784,9 @@ const (
 	IPV6_RECVTCLASS                   = 0x39
 	IPV6_RTHDR                        = 0x33
 	IPV6_RTHDRDSTOPTS                 = 0x23
-	IPV6_RTHDR_LOOSE                  = 0
+	IPV6_RTHDR_LOOSE                  = 0x0
 	IPV6_RTHDR_STRICT                 = 0x1
-	IPV6_RTHDR_TYPE_0                 = 0
+	IPV6_RTHDR_TYPE_0                 = 0x0
 	IPV6_SOCKOPT_RESERVED1            = 0x3
 	IPV6_TCLASS                       = 0x3d
 	IPV6_UNICAST_HOPS                 = 0x4
@@ -944,7 +847,7 @@ const (
 	IP_ONESBCAST                      = 0x17
 	IP_OPTIONS                        = 0x1
 	IP_PORTRANGE                      = 0x13
-	IP_PORTRANGE_DEFAULT              = 0
+	IP_PORTRANGE_DEFAULT              = 0x0
 	IP_PORTRANGE_HIGH                 = 0x1
 	IP_PORTRANGE_LOW                  = 0x2
 	IP_RECVDSTADDR                    = 0x7
@@ -962,6 +865,10 @@ const (
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
 	IP_UNBLOCK_SOURCE                 = 0x49
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
 	MSG_COMPAT                        = 0x8000
 	MSG_CTRUNC                        = 0x20
 	MSG_DONTROUTE                     = 0x4
@@ -994,16 +901,24 @@ const (
 	O_NOCTTY                          = 0x8000
 	O_NOFOLLOW                        = 0x100
 	O_NONBLOCK                        = 0x4
-	O_RDONLY                          = 0
+	O_RDONLY                          = 0x0
 	O_RDWR                            = 0x2
 	O_SHLOCK                          = 0x10
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_TTY_INIT                        = 0x80000
 	O_WRONLY                          = 0x1
+	RLIMIT_AS                         = 0xa
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
 	RTAX_AUTHOR                       = 0x6
 	RTAX_BRD                          = 0x7
-	RTAX_DST                          = 0
+	RTAX_DST                          = 0x0
 	RTAX_GATEWAY                      = 0x1
 	RTAX_GENMASK                      = 0x3
 	RTAX_IFA                          = 0x5
@@ -1070,11 +985,14 @@ const (
 	RTV_SPIPE                         = 0x10
 	RTV_SSTHRESH                      = 0x20
 	RTV_WEIGHT                        = 0x100
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	RUSAGE_THREAD                     = 0x1
 	SCM_BINTIME                       = 0x4
 	SCM_CREDS                         = 0x3
 	SCM_RIGHTS                        = 0x1
 	SCM_TIMESTAMP                     = 0x2
-	SHUT_RD                           = 0
+	SHUT_RD                           = 0x0
 	SHUT_RDWR                         = 0x2
 	SHUT_WR                           = 0x1
 	SIGABRT                           = 0x6
@@ -1270,7 +1188,7 @@ const (
 	TIOCNXCL                          = 0x2000740e
 	TIOCOUTQ                          = 0x40047473
 	TIOCPKT                           = 0x80047470
-	TIOCPKT_DATA                      = 0
+	TIOCPKT_DATA                      = 0x0
 	TIOCPKT_DOSTOP                    = 0x20
 	TIOCPKT_FLUSHREAD                 = 0x1
 	TIOCPKT_FLUSHWRITE                = 0x2
@@ -1305,7 +1223,105 @@ const (
 	WUNTRACED                         = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADF           = Errno(0x9)
+	EBADMSG         = Errno(0x59)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x55)
+	ECHILD          = Errno(0xa)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDOM            = Errno(0x21)
+	EDOOFUS         = Errno(0x58)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x52)
+	EILSEQ          = Errno(0x56)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x5d)
+	ELOOP           = Errno(0x3e)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	EMULTIHOP       = Errno(0x5a)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x57)
+	ENOBUFS         = Errno(0x37)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOLINK         = Errno(0x5b)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x53)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCAPABLE     = Errno(0x5d)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x2d)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x2d)
+	EOVERFLOW       = Errno(0x54)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTO          = Errno(0x5c)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
 
 // Error table
 var errors = [...]string{
diff --git a/src/pkg/syscall/zerrors_linux_386.go b/src/pkg/syscall/zerrors_linux_386.go
index dba66e6..9c3ac9c 100644
--- a/src/pkg/syscall/zerrors_linux_386.go
+++ b/src/pkg/syscall/zerrors_linux_386.go
@@ -1,14 +1,13 @@
-// mkerrors.sh -f -m32
+// mkerrors.sh -m32
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -f -m32 -gsyscall -f -m32 _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m32 _const.go
 
 package syscall
 
-// Constants
 const (
+	AF_ALG                           = 0x26
 	AF_APPLETALK                     = 0x5
 	AF_ASH                           = 0x12
 	AF_ATMPVC                        = 0x8
@@ -16,6 +15,7 @@ const (
 	AF_AX25                          = 0x3
 	AF_BLUETOOTH                     = 0x1f
 	AF_BRIDGE                        = 0x7
+	AF_CAIF                          = 0x25
 	AF_CAN                           = 0x1d
 	AF_DECnet                        = 0xc
 	AF_ECONET                        = 0x13
@@ -30,7 +30,7 @@ const (
 	AF_KEY                           = 0xf
 	AF_LLC                           = 0x1a
 	AF_LOCAL                         = 0x1
-	AF_MAX                           = 0x25
+	AF_MAX                           = 0x27
 	AF_NETBEUI                       = 0xd
 	AF_NETLINK                       = 0x10
 	AF_NETROM                        = 0x6
@@ -45,7 +45,7 @@ const (
 	AF_SNA                           = 0x16
 	AF_TIPC                          = 0x1e
 	AF_UNIX                          = 0x1
-	AF_UNSPEC                        = 0
+	AF_UNSPEC                        = 0x0
 	AF_WANPIPE                       = 0x19
 	AF_X25                           = 0x9
 	ARPHRD_ADAPT                     = 0x108
@@ -90,7 +90,7 @@ const (
 	ARPHRD_LOCALTLK                  = 0x305
 	ARPHRD_LOOPBACK                  = 0x304
 	ARPHRD_METRICOM                  = 0x17
-	ARPHRD_NETROM                    = 0
+	ARPHRD_NETROM                    = 0x0
 	ARPHRD_NONE                      = 0xfffe
 	ARPHRD_PIMREG                    = 0x30b
 	ARPHRD_PPP                       = 0x200
@@ -108,22 +108,22 @@ const (
 	ARPHRD_X25                       = 0x10f
 	BPF_A                            = 0x10
 	BPF_ABS                          = 0x20
-	BPF_ADD                          = 0
+	BPF_ADD                          = 0x0
 	BPF_ALU                          = 0x4
 	BPF_AND                          = 0x50
 	BPF_B                            = 0x10
 	BPF_DIV                          = 0x30
 	BPF_H                            = 0x8
-	BPF_IMM                          = 0
+	BPF_IMM                          = 0x0
 	BPF_IND                          = 0x40
-	BPF_JA                           = 0
+	BPF_JA                           = 0x0
 	BPF_JEQ                          = 0x10
 	BPF_JGE                          = 0x30
 	BPF_JGT                          = 0x20
 	BPF_JMP                          = 0x5
 	BPF_JSET                         = 0x40
-	BPF_K                            = 0
-	BPF_LD                           = 0
+	BPF_K                            = 0x0
+	BPF_LD                           = 0x0
 	BPF_LDX                          = 0x1
 	BPF_LEN                          = 0x80
 	BPF_LSH                          = 0x60
@@ -142,9 +142,9 @@ const (
 	BPF_ST                           = 0x2
 	BPF_STX                          = 0x3
 	BPF_SUB                          = 0x10
-	BPF_TAX                          = 0
+	BPF_TAX                          = 0x0
 	BPF_TXA                          = 0x80
-	BPF_W                            = 0
+	BPF_W                            = 0x0
 	BPF_X                            = 0x8
 	DT_BLK                           = 0x6
 	DT_CHR                           = 0x2
@@ -153,114 +153,8 @@ const (
 	DT_LNK                           = 0xa
 	DT_REG                           = 0x8
 	DT_SOCK                          = 0xc
-	DT_UNKNOWN                       = 0
+	DT_UNKNOWN                       = 0x0
 	DT_WHT                           = 0xe
-	E2BIG                            = 0x7
-	EACCES                           = 0xd
-	EADDRINUSE                       = 0x62
-	EADDRNOTAVAIL                    = 0x63
-	EADV                             = 0x44
-	EAFNOSUPPORT                     = 0x61
-	EAGAIN                           = 0xb
-	EALREADY                         = 0x72
-	EBADE                            = 0x34
-	EBADF                            = 0x9
-	EBADFD                           = 0x4d
-	EBADMSG                          = 0x4a
-	EBADR                            = 0x35
-	EBADRQC                          = 0x38
-	EBADSLT                          = 0x39
-	EBFONT                           = 0x3b
-	EBUSY                            = 0x10
-	ECANCELED                        = 0x7d
-	ECHILD                           = 0xa
-	ECHRNG                           = 0x2c
-	ECOMM                            = 0x46
-	ECONNABORTED                     = 0x67
-	ECONNREFUSED                     = 0x6f
-	ECONNRESET                       = 0x68
-	EDEADLK                          = 0x23
-	EDEADLOCK                        = 0x23
-	EDESTADDRREQ                     = 0x59
-	EDOM                             = 0x21
-	EDOTDOT                          = 0x49
-	EDQUOT                           = 0x7a
-	EEXIST                           = 0x11
-	EFAULT                           = 0xe
-	EFBIG                            = 0x1b
-	EHOSTDOWN                        = 0x70
-	EHOSTUNREACH                     = 0x71
-	EIDRM                            = 0x2b
-	EILSEQ                           = 0x54
-	EINPROGRESS                      = 0x73
-	EINTR                            = 0x4
-	EINVAL                           = 0x16
-	EIO                              = 0x5
-	EISCONN                          = 0x6a
-	EISDIR                           = 0x15
-	EISNAM                           = 0x78
-	EKEYEXPIRED                      = 0x7f
-	EKEYREJECTED                     = 0x81
-	EKEYREVOKED                      = 0x80
-	EL2HLT                           = 0x33
-	EL2NSYNC                         = 0x2d
-	EL3HLT                           = 0x2e
-	EL3RST                           = 0x2f
-	ELIBACC                          = 0x4f
-	ELIBBAD                          = 0x50
-	ELIBEXEC                         = 0x53
-	ELIBMAX                          = 0x52
-	ELIBSCN                          = 0x51
-	ELNRNG                           = 0x30
-	ELOOP                            = 0x28
-	EMEDIUMTYPE                      = 0x7c
-	EMFILE                           = 0x18
-	EMLINK                           = 0x1f
-	EMSGSIZE                         = 0x5a
-	EMULTIHOP                        = 0x48
-	ENAMETOOLONG                     = 0x24
-	ENAVAIL                          = 0x77
-	ENETDOWN                         = 0x64
-	ENETRESET                        = 0x66
-	ENETUNREACH                      = 0x65
-	ENFILE                           = 0x17
-	ENOANO                           = 0x37
-	ENOBUFS                          = 0x69
-	ENOCSI                           = 0x32
-	ENODATA                          = 0x3d
-	ENODEV                           = 0x13
-	ENOENT                           = 0x2
-	ENOEXEC                          = 0x8
-	ENOKEY                           = 0x7e
-	ENOLCK                           = 0x25
-	ENOLINK                          = 0x43
-	ENOMEDIUM                        = 0x7b
-	ENOMEM                           = 0xc
-	ENOMSG                           = 0x2a
-	ENONET                           = 0x40
-	ENOPKG                           = 0x41
-	ENOPROTOOPT                      = 0x5c
-	ENOSPC                           = 0x1c
-	ENOSR                            = 0x3f
-	ENOSTR                           = 0x3c
-	ENOSYS                           = 0x26
-	ENOTBLK                          = 0xf
-	ENOTCONN                         = 0x6b
-	ENOTDIR                          = 0x14
-	ENOTEMPTY                        = 0x27
-	ENOTNAM                          = 0x76
-	ENOTRECOVERABLE                  = 0x83
-	ENOTSOCK                         = 0x58
-	ENOTSUP                          = 0x5f
-	ENOTTY                           = 0x19
-	ENOTUNIQ                         = 0x4c
-	ENXIO                            = 0x6
-	EOPNOTSUPP                       = 0x5f
-	EOVERFLOW                        = 0x4b
-	EOWNERDEAD                       = 0x82
-	EPERM                            = 0x1
-	EPFNOSUPPORT                     = 0x60
-	EPIPE                            = 0x20
 	EPOLLERR                         = 0x8
 	EPOLLET                          = -0x80000000
 	EPOLLHUP                         = 0x10
@@ -279,23 +173,6 @@ const (
 	EPOLL_CTL_DEL                    = 0x2
 	EPOLL_CTL_MOD                    = 0x3
 	EPOLL_NONBLOCK                   = 0x800
-	EPROTO                           = 0x47
-	EPROTONOSUPPORT                  = 0x5d
-	EPROTOTYPE                       = 0x5b
-	ERANGE                           = 0x22
-	EREMCHG                          = 0x4e
-	EREMOTE                          = 0x42
-	EREMOTEIO                        = 0x79
-	ERESTART                         = 0x55
-	ERFKILL                          = 0x84
-	EROFS                            = 0x1e
-	ESHUTDOWN                        = 0x6c
-	ESOCKTNOSUPPORT                  = 0x5e
-	ESPIPE                           = 0x1d
-	ESRCH                            = 0x3
-	ESRMNT                           = 0x45
-	ESTALE                           = 0x74
-	ESTRPIPE                         = 0x56
 	ETH_P_1588                       = 0x88f7
 	ETH_P_8021Q                      = 0x8100
 	ETH_P_802_2                      = 0x4
@@ -310,6 +187,7 @@ const (
 	ETH_P_ATMMPOA                    = 0x884c
 	ETH_P_AX25                       = 0x2
 	ETH_P_BPQ                        = 0x8ff
+	ETH_P_CAIF                       = 0xf7
 	ETH_P_CAN                        = 0xc
 	ETH_P_CONTROL                    = 0x16
 	ETH_P_CUST                       = 0x6006
@@ -333,6 +211,7 @@ const (
 	ETH_P_IPX                        = 0x8137
 	ETH_P_IRDA                       = 0x17
 	ETH_P_LAT                        = 0x6004
+	ETH_P_LINK_CTL                   = 0x886c
 	ETH_P_LOCALTALK                  = 0x9
 	ETH_P_LOOP                       = 0x60
 	ETH_P_MOBITEX                    = 0x15
@@ -358,19 +237,9 @@ const (
 	ETH_P_WAN_PPP                    = 0x7
 	ETH_P_WCCP                       = 0x883e
 	ETH_P_X25                        = 0x805
-	ETIME                            = 0x3e
-	ETIMEDOUT                        = 0x6e
-	ETOOMANYREFS                     = 0x6d
-	ETXTBSY                          = 0x1a
-	EUCLEAN                          = 0x75
-	EUNATCH                          = 0x31
-	EUSERS                           = 0x57
-	EWOULDBLOCK                      = 0xb
-	EXDEV                            = 0x12
-	EXFULL                           = 0x36
 	FD_CLOEXEC                       = 0x1
 	FD_SETSIZE                       = 0x400
-	F_DUPFD                          = 0
+	F_DUPFD                          = 0x0
 	F_DUPFD_CLOEXEC                  = 0x406
 	F_EXLCK                          = 0x4
 	F_GETFD                          = 0x1
@@ -380,11 +249,12 @@ const (
 	F_GETLK64                        = 0xc
 	F_GETOWN                         = 0x9
 	F_GETOWN_EX                      = 0x10
+	F_GETPIPE_SZ                     = 0x408
 	F_GETSIG                         = 0xb
 	F_LOCK                           = 0x1
 	F_NOTIFY                         = 0x402
-	F_OK                             = 0
-	F_RDLCK                          = 0
+	F_OK                             = 0x0
+	F_RDLCK                          = 0x0
 	F_SETFD                          = 0x2
 	F_SETFL                          = 0x4
 	F_SETLEASE                       = 0x400
@@ -394,11 +264,12 @@ const (
 	F_SETLKW64                       = 0xe
 	F_SETOWN                         = 0x8
 	F_SETOWN_EX                      = 0xf
+	F_SETPIPE_SZ                     = 0x407
 	F_SETSIG                         = 0xa
 	F_SHLCK                          = 0x8
 	F_TEST                           = 0x3
 	F_TLOCK                          = 0x2
-	F_ULOCK                          = 0
+	F_ULOCK                          = 0x0
 	F_UNLCK                          = 0x2
 	F_WRLCK                          = 0x1
 	IFA_F_DADFAILED                  = 0x8
@@ -456,6 +327,7 @@ const (
 	IN_DELETE                        = 0x200
 	IN_DELETE_SELF                   = 0x400
 	IN_DONT_FOLLOW                   = 0x2000000
+	IN_EXCL_UNLINK                   = 0x4000000
 	IN_IGNORED                       = 0x8000
 	IN_ISDIR                         = 0x40000000
 	IN_LOOPBACKNET                   = 0x7f
@@ -480,12 +352,12 @@ const (
 	IPPROTO_ESP                      = 0x32
 	IPPROTO_FRAGMENT                 = 0x2c
 	IPPROTO_GRE                      = 0x2f
-	IPPROTO_HOPOPTS                  = 0
+	IPPROTO_HOPOPTS                  = 0x0
 	IPPROTO_ICMP                     = 0x1
 	IPPROTO_ICMPV6                   = 0x3a
 	IPPROTO_IDP                      = 0x16
 	IPPROTO_IGMP                     = 0x2
-	IPPROTO_IP                       = 0
+	IPPROTO_IP                       = 0x0
 	IPPROTO_IPIP                     = 0x4
 	IPPROTO_IPV6                     = 0x29
 	IPPROTO_MTP                      = 0x5c
@@ -527,7 +399,7 @@ const (
 	IPV6_NEXTHOP                     = 0x9
 	IPV6_PKTINFO                     = 0x32
 	IPV6_PMTUDISC_DO                 = 0x2
-	IPV6_PMTUDISC_DONT               = 0
+	IPV6_PMTUDISC_DONT               = 0x0
 	IPV6_PMTUDISC_PROBE              = 0x3
 	IPV6_PMTUDISC_WANT               = 0x1
 	IPV6_RECVDSTOPTS                 = 0x3a
@@ -540,9 +412,9 @@ const (
 	IPV6_ROUTER_ALERT                = 0x16
 	IPV6_RTHDR                       = 0x39
 	IPV6_RTHDRDSTOPTS                = 0x37
-	IPV6_RTHDR_LOOSE                 = 0
+	IPV6_RTHDR_LOOSE                 = 0x0
 	IPV6_RTHDR_STRICT                = 0x1
-	IPV6_RTHDR_TYPE_0                = 0
+	IPV6_RTHDR_TYPE_0                = 0x0
 	IPV6_RXDSTOPTS                   = 0x3b
 	IPV6_RXHOPOPTS                   = 0x36
 	IPV6_TCLASS                      = 0x43
@@ -557,27 +429,34 @@ const (
 	IP_DF                            = 0x4000
 	IP_DROP_MEMBERSHIP               = 0x24
 	IP_DROP_SOURCE_MEMBERSHIP        = 0x28
+	IP_FREEBIND                      = 0xf
 	IP_HDRINCL                       = 0x3
+	IP_IPSEC_POLICY                  = 0x10
 	IP_MAXPACKET                     = 0xffff
 	IP_MAX_MEMBERSHIPS               = 0x14
 	IP_MF                            = 0x2000
+	IP_MINTTL                        = 0x15
 	IP_MSFILTER                      = 0x29
 	IP_MSS                           = 0x240
+	IP_MTU                           = 0xe
 	IP_MTU_DISCOVER                  = 0xa
 	IP_MULTICAST_IF                  = 0x20
 	IP_MULTICAST_LOOP                = 0x22
 	IP_MULTICAST_TTL                 = 0x21
 	IP_OFFMASK                       = 0x1fff
 	IP_OPTIONS                       = 0x4
+	IP_ORIGDSTADDR                   = 0x14
+	IP_PASSSEC                       = 0x12
 	IP_PKTINFO                       = 0x8
 	IP_PKTOPTIONS                    = 0x9
 	IP_PMTUDISC                      = 0xa
 	IP_PMTUDISC_DO                   = 0x2
-	IP_PMTUDISC_DONT                 = 0
+	IP_PMTUDISC_DONT                 = 0x0
 	IP_PMTUDISC_PROBE                = 0x3
 	IP_PMTUDISC_WANT                 = 0x1
 	IP_RECVERR                       = 0xb
 	IP_RECVOPTS                      = 0x6
+	IP_RECVORIGDSTADDR               = 0x14
 	IP_RECVRETOPTS                   = 0x7
 	IP_RECVTOS                       = 0xd
 	IP_RECVTTL                       = 0xc
@@ -585,9 +464,11 @@ const (
 	IP_RF                            = 0x8000
 	IP_ROUTER_ALERT                  = 0x5
 	IP_TOS                           = 0x1
+	IP_TRANSPARENT                   = 0x13
 	IP_TTL                           = 0x2
 	IP_UNBLOCK_SOURCE                = 0x25
-	LINUX_REBOOT_CMD_CAD_OFF         = 0
+	IP_XFRM_POLICY                   = 0x11
+	LINUX_REBOOT_CMD_CAD_OFF         = 0x0
 	LINUX_REBOOT_CMD_CAD_ON          = 0x89abcdef
 	LINUX_REBOOT_CMD_HALT            = 0xcdef0123
 	LINUX_REBOOT_CMD_KEXEC           = 0x45584543
@@ -597,12 +478,18 @@ const (
 	LINUX_REBOOT_CMD_SW_SUSPEND      = 0xd000fce2
 	LINUX_REBOOT_MAGIC1              = 0xfee1dead
 	LINUX_REBOOT_MAGIC2              = 0x28121969
+	LOCK_EX                          = 0x2
+	LOCK_NB                          = 0x4
+	LOCK_SH                          = 0x1
+	LOCK_UN                          = 0x8
 	MADV_DOFORK                      = 0xb
 	MADV_DONTFORK                    = 0xa
 	MADV_DONTNEED                    = 0x4
+	MADV_HUGEPAGE                    = 0xe
 	MADV_HWPOISON                    = 0x64
 	MADV_MERGEABLE                   = 0xc
-	MADV_NORMAL                      = 0
+	MADV_NOHUGEPAGE                  = 0xf
+	MADV_NORMAL                      = 0x0
 	MADV_RANDOM                      = 0x1
 	MADV_REMOVE                      = 0x9
 	MADV_SEQUENTIAL                  = 0x2
@@ -613,9 +500,10 @@ const (
 	MAP_ANONYMOUS                    = 0x20
 	MAP_DENYWRITE                    = 0x800
 	MAP_EXECUTABLE                   = 0x1000
-	MAP_FILE                         = 0
+	MAP_FILE                         = 0x0
 	MAP_FIXED                        = 0x10
 	MAP_GROWSDOWN                    = 0x100
+	MAP_HUGETLB                      = 0x40000
 	MAP_LOCKED                       = 0x2000
 	MAP_NONBLOCK                     = 0x10000
 	MAP_NORESERVE                    = 0x4000
@@ -647,22 +535,38 @@ const (
 	MSG_TRUNC                        = 0x20
 	MSG_TRYHARD                      = 0x4
 	MSG_WAITALL                      = 0x100
+	MSG_WAITFORONE                   = 0x10000
+	MS_ACTIVE                        = 0x40000000
 	MS_ASYNC                         = 0x1
 	MS_BIND                          = 0x1000
+	MS_DIRSYNC                       = 0x80
 	MS_INVALIDATE                    = 0x2
+	MS_I_VERSION                     = 0x800000
+	MS_KERNMOUNT                     = 0x400000
 	MS_MANDLOCK                      = 0x40
 	MS_MGC_MSK                       = 0xffff0000
 	MS_MGC_VAL                       = 0xc0ed0000
+	MS_MOVE                          = 0x2000
 	MS_NOATIME                       = 0x400
 	MS_NODEV                         = 0x4
 	MS_NODIRATIME                    = 0x800
 	MS_NOEXEC                        = 0x8
 	MS_NOSUID                        = 0x2
+	MS_NOUSER                        = -0x80000000
+	MS_POSIXACL                      = 0x10000
+	MS_PRIVATE                       = 0x40000
 	MS_RDONLY                        = 0x1
+	MS_REC                           = 0x4000
+	MS_RELATIME                      = 0x200000
 	MS_REMOUNT                       = 0x20
-	MS_RMT_MASK                      = 0xc51
+	MS_RMT_MASK                      = 0x800051
+	MS_SHARED                        = 0x100000
+	MS_SILENT                        = 0x8000
+	MS_SLAVE                         = 0x80000
+	MS_STRICTATIME                   = 0x1000000
 	MS_SYNC                          = 0x4
 	MS_SYNCHRONOUS                   = 0x10
+	MS_UNBINDABLE                    = 0x20000
 	NAME_MAX                         = 0xff
 	NETLINK_ADD_MEMBERSHIP           = 0x1
 	NETLINK_AUDIT                    = 0x9
@@ -682,7 +586,8 @@ const (
 	NETLINK_NFLOG                    = 0x5
 	NETLINK_NO_ENOBUFS               = 0x5
 	NETLINK_PKTINFO                  = 0x3
-	NETLINK_ROUTE                    = 0
+	NETLINK_RDMA                     = 0x14
+	NETLINK_ROUTE                    = 0x0
 	NETLINK_SCSITRANSPORT            = 0x12
 	NETLINK_SELINUX                  = 0x7
 	NETLINK_UNUSED                   = 0x1
@@ -720,27 +625,27 @@ const (
 	O_DIRECTORY                      = 0x10000
 	O_DSYNC                          = 0x1000
 	O_EXCL                           = 0x80
-	O_FSYNC                          = 0x1000
+	O_FSYNC                          = 0x101000
 	O_LARGEFILE                      = 0x8000
 	O_NDELAY                         = 0x800
 	O_NOATIME                        = 0x40000
 	O_NOCTTY                         = 0x100
 	O_NOFOLLOW                       = 0x20000
 	O_NONBLOCK                       = 0x800
-	O_RDONLY                         = 0
+	O_RDONLY                         = 0x0
 	O_RDWR                           = 0x2
-	O_RSYNC                          = 0x1000
-	O_SYNC                           = 0x1000
+	O_RSYNC                          = 0x101000
+	O_SYNC                           = 0x101000
 	O_TRUNC                          = 0x200
 	O_WRONLY                         = 0x1
 	PACKET_ADD_MEMBERSHIP            = 0x1
 	PACKET_BROADCAST                 = 0x1
 	PACKET_DROP_MEMBERSHIP           = 0x2
 	PACKET_FASTROUTE                 = 0x6
-	PACKET_HOST                      = 0
+	PACKET_HOST                      = 0x0
 	PACKET_LOOPBACK                  = 0x5
 	PACKET_MR_ALLMULTI               = 0x2
-	PACKET_MR_MULTICAST              = 0
+	PACKET_MR_MULTICAST              = 0x0
 	PACKET_MR_PROMISC                = 0x1
 	PACKET_MULTICAST                 = 0x2
 	PACKET_OTHERHOST                 = 0x3
@@ -751,20 +656,68 @@ const (
 	PROT_EXEC                        = 0x4
 	PROT_GROWSDOWN                   = 0x1000000
 	PROT_GROWSUP                     = 0x2000000
-	PROT_NONE                        = 0
+	PROT_NONE                        = 0x0
 	PROT_READ                        = 0x1
 	PROT_WRITE                       = 0x2
+	PR_CAPBSET_DROP                  = 0x18
+	PR_CAPBSET_READ                  = 0x17
+	PR_ENDIAN_BIG                    = 0x0
+	PR_ENDIAN_LITTLE                 = 0x1
+	PR_ENDIAN_PPC_LITTLE             = 0x2
+	PR_FPEMU_NOPRINT                 = 0x1
+	PR_FPEMU_SIGFPE                  = 0x2
+	PR_FP_EXC_ASYNC                  = 0x2
+	PR_FP_EXC_DISABLED               = 0x0
+	PR_FP_EXC_DIV                    = 0x10000
+	PR_FP_EXC_INV                    = 0x100000
+	PR_FP_EXC_NONRECOV               = 0x1
+	PR_FP_EXC_OVF                    = 0x20000
+	PR_FP_EXC_PRECISE                = 0x3
+	PR_FP_EXC_RES                    = 0x80000
+	PR_FP_EXC_SW_ENABLE              = 0x80
+	PR_FP_EXC_UND                    = 0x40000
+	PR_GET_DUMPABLE                  = 0x3
+	PR_GET_ENDIAN                    = 0x13
+	PR_GET_FPEMU                     = 0x9
+	PR_GET_FPEXC                     = 0xb
+	PR_GET_KEEPCAPS                  = 0x7
+	PR_GET_NAME                      = 0x10
+	PR_GET_PDEATHSIG                 = 0x2
+	PR_GET_SECCOMP                   = 0x15
+	PR_GET_SECUREBITS                = 0x1b
+	PR_GET_TIMERSLACK                = 0x1e
+	PR_GET_TIMING                    = 0xd
+	PR_GET_TSC                       = 0x19
+	PR_GET_UNALIGN                   = 0x5
+	PR_MCE_KILL                      = 0x21
+	PR_MCE_KILL_CLEAR                = 0x0
+	PR_MCE_KILL_DEFAULT              = 0x2
+	PR_MCE_KILL_EARLY                = 0x1
+	PR_MCE_KILL_GET                  = 0x22
+	PR_MCE_KILL_LATE                 = 0x0
+	PR_MCE_KILL_SET                  = 0x1
+	PR_SET_DUMPABLE                  = 0x4
+	PR_SET_ENDIAN                    = 0x14
+	PR_SET_FPEMU                     = 0xa
+	PR_SET_FPEXC                     = 0xc
+	PR_SET_KEEPCAPS                  = 0x8
+	PR_SET_NAME                      = 0xf
+	PR_SET_PDEATHSIG                 = 0x1
+	PR_SET_SECCOMP                   = 0x16
+	PR_SET_SECUREBITS                = 0x1c
+	PR_SET_TIMERSLACK                = 0x1d
+	PR_SET_TIMING                    = 0xe
+	PR_SET_TSC                       = 0x1a
+	PR_SET_UNALIGN                   = 0x6
+	PR_TASK_PERF_EVENTS_DISABLE      = 0x1f
+	PR_TASK_PERF_EVENTS_ENABLE       = 0x20
+	PR_TIMING_STATISTICAL            = 0x0
+	PR_TIMING_TIMESTAMP              = 0x1
+	PR_TSC_ENABLE                    = 0x1
+	PR_TSC_SIGSEGV                   = 0x2
+	PR_UNALIGN_NOPRINT               = 0x1
+	PR_UNALIGN_SIGBUS                = 0x2
 	PTRACE_ATTACH                    = 0x10
-	PTRACE_BTS_CLEAR                 = 0x2c
-	PTRACE_BTS_CONFIG                = 0x28
-	PTRACE_BTS_DRAIN                 = 0x2d
-	PTRACE_BTS_GET                   = 0x2b
-	PTRACE_BTS_O_ALLOC               = 0x8
-	PTRACE_BTS_O_SCHED               = 0x2
-	PTRACE_BTS_O_SIGNAL              = 0x4
-	PTRACE_BTS_O_TRACE               = 0x1
-	PTRACE_BTS_SIZE                  = 0x2a
-	PTRACE_BTS_STATUS                = 0x29
 	PTRACE_CONT                      = 0x7
 	PTRACE_DETACH                    = 0x11
 	PTRACE_EVENT_CLONE               = 0x3
@@ -777,6 +730,7 @@ const (
 	PTRACE_GETFPREGS                 = 0xe
 	PTRACE_GETFPXREGS                = 0x12
 	PTRACE_GETREGS                   = 0xc
+	PTRACE_GETREGSET                 = 0x4204
 	PTRACE_GETSIGINFO                = 0x4202
 	PTRACE_GET_THREAD_AREA           = 0x19
 	PTRACE_KILL                      = 0x8
@@ -799,6 +753,7 @@ const (
 	PTRACE_SETFPXREGS                = 0x13
 	PTRACE_SETOPTIONS                = 0x4200
 	PTRACE_SETREGS                   = 0xd
+	PTRACE_SETREGSET                 = 0x4205
 	PTRACE_SETSIGINFO                = 0x4203
 	PTRACE_SET_THREAD_AREA           = 0x1a
 	PTRACE_SINGLEBLOCK               = 0x21
@@ -806,7 +761,15 @@ const (
 	PTRACE_SYSCALL                   = 0x18
 	PTRACE_SYSEMU                    = 0x1f
 	PTRACE_SYSEMU_SINGLESTEP         = 0x20
-	PTRACE_TRACEME                   = 0
+	PTRACE_TRACEME                   = 0x0
+	RLIMIT_AS                        = 0x9
+	RLIMIT_CORE                      = 0x4
+	RLIMIT_CPU                       = 0x0
+	RLIMIT_DATA                      = 0x2
+	RLIMIT_FSIZE                     = 0x1
+	RLIMIT_NOFILE                    = 0x7
+	RLIMIT_STACK                     = 0x3
+	RLIM_INFINITY                    = -0x1
 	RTAX_ADVMSS                      = 0x8
 	RTAX_CWND                        = 0x7
 	RTAX_FEATURES                    = 0xc
@@ -816,18 +779,19 @@ const (
 	RTAX_FEATURE_TIMESTAMP           = 0x4
 	RTAX_HOPLIMIT                    = 0xa
 	RTAX_INITCWND                    = 0xb
+	RTAX_INITRWND                    = 0xe
 	RTAX_LOCK                        = 0x1
-	RTAX_MAX                         = 0xd
+	RTAX_MAX                         = 0xe
 	RTAX_MTU                         = 0x2
 	RTAX_REORDERING                  = 0x9
 	RTAX_RTO_MIN                     = 0xd
 	RTAX_RTT                         = 0x4
 	RTAX_RTTVAR                      = 0x5
 	RTAX_SSTHRESH                    = 0x6
-	RTAX_UNSPEC                      = 0
+	RTAX_UNSPEC                      = 0x0
 	RTAX_WINDOW                      = 0x3
 	RTA_ALIGNTO                      = 0x4
-	RTA_MAX                          = 0xf
+	RTA_MAX                          = 0x10
 	RTCF_DIRECTSRC                   = 0x4000000
 	RTCF_DOREDIRECT                  = 0x1000000
 	RTCF_LOG                         = 0x2000000
@@ -928,20 +892,23 @@ const (
 	RTPROT_RA                        = 0x9
 	RTPROT_REDIRECT                  = 0x1
 	RTPROT_STATIC                    = 0x4
-	RTPROT_UNSPEC                    = 0
+	RTPROT_UNSPEC                    = 0x0
 	RTPROT_XORP                      = 0xe
 	RTPROT_ZEBRA                     = 0xb
 	RT_CLASS_DEFAULT                 = 0xfd
 	RT_CLASS_LOCAL                   = 0xff
 	RT_CLASS_MAIN                    = 0xfe
 	RT_CLASS_MAX                     = 0xff
-	RT_CLASS_UNSPEC                  = 0
+	RT_CLASS_UNSPEC                  = 0x0
+	RUSAGE_CHILDREN                  = -0x1
+	RUSAGE_SELF                      = 0x0
+	RUSAGE_THREAD                    = 0x1
 	SCM_CREDENTIALS                  = 0x2
 	SCM_RIGHTS                       = 0x1
 	SCM_TIMESTAMP                    = 0x1d
 	SCM_TIMESTAMPING                 = 0x25
 	SCM_TIMESTAMPNS                  = 0x23
-	SHUT_RD                          = 0
+	SHUT_RD                          = 0x0
 	SHUT_RDWR                        = 0x2
 	SHUT_WR                          = 0x1
 	SIGABRT                          = 0x6
@@ -1050,7 +1017,7 @@ const (
 	SOL_ATM                          = 0x108
 	SOL_DECNET                       = 0x105
 	SOL_ICMPV6                       = 0x3a
-	SOL_IP                           = 0
+	SOL_IP                           = 0x0
 	SOL_IPV6                         = 0x29
 	SOL_IRDA                         = 0x10a
 	SOL_PACKET                       = 0x107
@@ -1086,6 +1053,7 @@ const (
 	SO_RCVLOWAT                      = 0x12
 	SO_RCVTIMEO                      = 0x14
 	SO_REUSEADDR                     = 0x2
+	SO_RXQ_OVFL                      = 0x28
 	SO_SECURITY_AUTHENTICATION       = 0x16
 	SO_SECURITY_ENCRYPTION_NETWORK   = 0x18
 	SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17
@@ -1097,7 +1065,6 @@ const (
 	SO_TIMESTAMPING                  = 0x25
 	SO_TIMESTAMPNS                   = 0x23
 	SO_TYPE                          = 0x3
-	S_APPEND                         = 0x100
 	S_BLKSIZE                        = 0x200
 	S_IEXEC                          = 0x40
 	S_IFBLK                          = 0x6000
@@ -1108,7 +1075,6 @@ const (
 	S_IFMT                           = 0xf000
 	S_IFREG                          = 0x8000
 	S_IFSOCK                         = 0xc000
-	S_IMMUTABLE                      = 0x200
 	S_IREAD                          = 0x100
 	S_IRGRP                          = 0x20
 	S_IROTH                          = 0x4
@@ -1126,7 +1092,6 @@ const (
 	S_IXGRP                          = 0x8
 	S_IXOTH                          = 0x1
 	S_IXUSR                          = 0x40
-	S_WRITE                          = 0x80
 	TCP_CONGESTION                   = 0xd
 	TCP_CORK                         = 0x3
 	TCP_DEFER_ACCEPT                 = 0x9
@@ -1148,8 +1113,8 @@ const (
 	TIOCCBRK                         = 0x5428
 	TIOCCONS                         = 0x541d
 	TIOCEXCL                         = 0x540c
+	TIOCGDEV                         = 0x80045432
 	TIOCGETD                         = 0x5424
-	TIOCGHAYESESP                    = 0x545e
 	TIOCGICOUNT                      = 0x545d
 	TIOCGLCKTRMIOS                   = 0x5456
 	TIOCGPGRP                        = 0x540f
@@ -1181,10 +1146,11 @@ const (
 	TIOCNXCL                         = 0x540d
 	TIOCOUTQ                         = 0x5411
 	TIOCPKT                          = 0x5420
-	TIOCPKT_DATA                     = 0
+	TIOCPKT_DATA                     = 0x0
 	TIOCPKT_DOSTOP                   = 0x20
 	TIOCPKT_FLUSHREAD                = 0x1
 	TIOCPKT_FLUSHWRITE               = 0x2
+	TIOCPKT_IOCTL                    = 0x40
 	TIOCPKT_NOSTOP                   = 0x10
 	TIOCPKT_START                    = 0x8
 	TIOCPKT_STOP                     = 0x4
@@ -1199,7 +1165,7 @@ const (
 	TIOCSERSWILD                     = 0x5455
 	TIOCSER_TEMT                     = 0x1
 	TIOCSETD                         = 0x5423
-	TIOCSHAYESESP                    = 0x545f
+	TIOCSIG                          = 0x40045436
 	TIOCSLCKTRMIOS                   = 0x5457
 	TIOCSPGRP                        = 0x5410
 	TIOCSPTLCK                       = 0x40045431
@@ -1208,9 +1174,13 @@ const (
 	TIOCSSOFTCAR                     = 0x541a
 	TIOCSTI                          = 0x5412
 	TIOCSWINSZ                       = 0x5414
+	TIOCVHANGUP                      = 0x5437
+	TUNATTACHFILTER                  = 0x400854d5
+	TUNDETACHFILTER                  = 0x400854d6
 	TUNGETFEATURES                   = 0x800454cf
 	TUNGETIFF                        = 0x800454d2
 	TUNGETSNDBUF                     = 0x800454d3
+	TUNGETVNETHDRSZ                  = 0x800454d7
 	TUNSETDEBUG                      = 0x400454c9
 	TUNSETGROUP                      = 0x400454ce
 	TUNSETIFF                        = 0x400454ca
@@ -1221,6 +1191,7 @@ const (
 	TUNSETPERSIST                    = 0x400454cb
 	TUNSETSNDBUF                     = 0x400454d4
 	TUNSETTXFILTER                   = 0x400454d1
+	TUNSETVNETHDRSZ                  = 0x400454d8
 	WALL                             = 0x40000000
 	WCLONE                           = 0x80000000
 	WCONTINUED                       = 0x8
@@ -1233,7 +1204,143 @@ const (
 	WUNTRACED                        = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x62)
+	EADDRNOTAVAIL   = Errno(0x63)
+	EADV            = Errno(0x44)
+	EAFNOSUPPORT    = Errno(0x61)
+	EAGAIN          = Errno(0xb)
+	EALREADY        = Errno(0x72)
+	EBADE           = Errno(0x34)
+	EBADF           = Errno(0x9)
+	EBADFD          = Errno(0x4d)
+	EBADMSG         = Errno(0x4a)
+	EBADR           = Errno(0x35)
+	EBADRQC         = Errno(0x38)
+	EBADSLT         = Errno(0x39)
+	EBFONT          = Errno(0x3b)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x7d)
+	ECHILD          = Errno(0xa)
+	ECHRNG          = Errno(0x2c)
+	ECOMM           = Errno(0x46)
+	ECONNABORTED    = Errno(0x67)
+	ECONNREFUSED    = Errno(0x6f)
+	ECONNRESET      = Errno(0x68)
+	EDEADLK         = Errno(0x23)
+	EDEADLOCK       = Errno(0x23)
+	EDESTADDRREQ    = Errno(0x59)
+	EDOM            = Errno(0x21)
+	EDOTDOT         = Errno(0x49)
+	EDQUOT          = Errno(0x7a)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EHOSTDOWN       = Errno(0x70)
+	EHOSTUNREACH    = Errno(0x71)
+	EHWPOISON       = Errno(0x85)
+	EIDRM           = Errno(0x2b)
+	EILSEQ          = Errno(0x54)
+	EINPROGRESS     = Errno(0x73)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x6a)
+	EISDIR          = Errno(0x15)
+	EISNAM          = Errno(0x78)
+	EKEYEXPIRED     = Errno(0x7f)
+	EKEYREJECTED    = Errno(0x81)
+	EKEYREVOKED     = Errno(0x80)
+	EL2HLT          = Errno(0x33)
+	EL2NSYNC        = Errno(0x2d)
+	EL3HLT          = Errno(0x2e)
+	EL3RST          = Errno(0x2f)
+	ELIBACC         = Errno(0x4f)
+	ELIBBAD         = Errno(0x50)
+	ELIBEXEC        = Errno(0x53)
+	ELIBMAX         = Errno(0x52)
+	ELIBSCN         = Errno(0x51)
+	ELNRNG          = Errno(0x30)
+	ELOOP           = Errno(0x28)
+	EMEDIUMTYPE     = Errno(0x7c)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x5a)
+	EMULTIHOP       = Errno(0x48)
+	ENAMETOOLONG    = Errno(0x24)
+	ENAVAIL         = Errno(0x77)
+	ENETDOWN        = Errno(0x64)
+	ENETRESET       = Errno(0x66)
+	ENETUNREACH     = Errno(0x65)
+	ENFILE          = Errno(0x17)
+	ENOANO          = Errno(0x37)
+	ENOBUFS         = Errno(0x69)
+	ENOCSI          = Errno(0x32)
+	ENODATA         = Errno(0x3d)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOKEY          = Errno(0x7e)
+	ENOLCK          = Errno(0x25)
+	ENOLINK         = Errno(0x43)
+	ENOMEDIUM       = Errno(0x7b)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x2a)
+	ENONET          = Errno(0x40)
+	ENOPKG          = Errno(0x41)
+	ENOPROTOOPT     = Errno(0x5c)
+	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x3f)
+	ENOSTR          = Errno(0x3c)
+	ENOSYS          = Errno(0x26)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x6b)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x27)
+	ENOTNAM         = Errno(0x76)
+	ENOTRECOVERABLE = Errno(0x83)
+	ENOTSOCK        = Errno(0x58)
+	ENOTSUP         = Errno(0x5f)
+	ENOTTY          = Errno(0x19)
+	ENOTUNIQ        = Errno(0x4c)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x5f)
+	EOVERFLOW       = Errno(0x4b)
+	EOWNERDEAD      = Errno(0x82)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x60)
+	EPIPE           = Errno(0x20)
+	EPROTO          = Errno(0x47)
+	EPROTONOSUPPORT = Errno(0x5d)
+	EPROTOTYPE      = Errno(0x5b)
+	ERANGE          = Errno(0x22)
+	EREMCHG         = Errno(0x4e)
+	EREMOTE         = Errno(0x42)
+	EREMOTEIO       = Errno(0x79)
+	ERESTART        = Errno(0x55)
+	ERFKILL         = Errno(0x84)
+	EROFS           = Errno(0x1e)
+	ESHUTDOWN       = Errno(0x6c)
+	ESOCKTNOSUPPORT = Errno(0x5e)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESRMNT          = Errno(0x45)
+	ESTALE          = Errno(0x74)
+	ESTRPIPE        = Errno(0x56)
+	ETIME           = Errno(0x3e)
+	ETIMEDOUT       = Errno(0x6e)
+	ETOOMANYREFS    = Errno(0x6d)
+	ETXTBSY         = Errno(0x1a)
+	EUCLEAN         = Errno(0x75)
+	EUNATCH         = Errno(0x31)
+	EUSERS          = Errno(0x57)
+	EWOULDBLOCK     = Errno(0xb)
+	EXDEV           = Errno(0x12)
+	EXFULL          = Errno(0x36)
+)
 
 // Error table
 var errors = [...]string{
@@ -1366,5 +1473,6 @@ var errors = [...]string{
 	129: "key was rejected by service",
 	130: "owner died",
 	131: "state not recoverable",
-	132: "unknown error 132",
+	132: "operation not possible due to RF-kill",
+	133: "unknown error 133",
 }
diff --git a/src/pkg/syscall/zerrors_linux_amd64.go b/src/pkg/syscall/zerrors_linux_amd64.go
index 1f29287..22d062c 100644
--- a/src/pkg/syscall/zerrors_linux_amd64.go
+++ b/src/pkg/syscall/zerrors_linux_amd64.go
@@ -1,14 +1,13 @@
-// mkerrors.sh -f -m64
+// mkerrors.sh -m64
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -f -m64 -gsyscall -f -m64 _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m64 _const.go
 
 package syscall
 
-// Constants
 const (
+	AF_ALG                           = 0x26
 	AF_APPLETALK                     = 0x5
 	AF_ASH                           = 0x12
 	AF_ATMPVC                        = 0x8
@@ -16,6 +15,7 @@ const (
 	AF_AX25                          = 0x3
 	AF_BLUETOOTH                     = 0x1f
 	AF_BRIDGE                        = 0x7
+	AF_CAIF                          = 0x25
 	AF_CAN                           = 0x1d
 	AF_DECnet                        = 0xc
 	AF_ECONET                        = 0x13
@@ -30,7 +30,7 @@ const (
 	AF_KEY                           = 0xf
 	AF_LLC                           = 0x1a
 	AF_LOCAL                         = 0x1
-	AF_MAX                           = 0x25
+	AF_MAX                           = 0x27
 	AF_NETBEUI                       = 0xd
 	AF_NETLINK                       = 0x10
 	AF_NETROM                        = 0x6
@@ -45,7 +45,7 @@ const (
 	AF_SNA                           = 0x16
 	AF_TIPC                          = 0x1e
 	AF_UNIX                          = 0x1
-	AF_UNSPEC                        = 0
+	AF_UNSPEC                        = 0x0
 	AF_WANPIPE                       = 0x19
 	AF_X25                           = 0x9
 	ARPHRD_ADAPT                     = 0x108
@@ -90,7 +90,7 @@ const (
 	ARPHRD_LOCALTLK                  = 0x305
 	ARPHRD_LOOPBACK                  = 0x304
 	ARPHRD_METRICOM                  = 0x17
-	ARPHRD_NETROM                    = 0
+	ARPHRD_NETROM                    = 0x0
 	ARPHRD_NONE                      = 0xfffe
 	ARPHRD_PIMREG                    = 0x30b
 	ARPHRD_PPP                       = 0x200
@@ -108,22 +108,22 @@ const (
 	ARPHRD_X25                       = 0x10f
 	BPF_A                            = 0x10
 	BPF_ABS                          = 0x20
-	BPF_ADD                          = 0
+	BPF_ADD                          = 0x0
 	BPF_ALU                          = 0x4
 	BPF_AND                          = 0x50
 	BPF_B                            = 0x10
 	BPF_DIV                          = 0x30
 	BPF_H                            = 0x8
-	BPF_IMM                          = 0
+	BPF_IMM                          = 0x0
 	BPF_IND                          = 0x40
-	BPF_JA                           = 0
+	BPF_JA                           = 0x0
 	BPF_JEQ                          = 0x10
 	BPF_JGE                          = 0x30
 	BPF_JGT                          = 0x20
 	BPF_JMP                          = 0x5
 	BPF_JSET                         = 0x40
-	BPF_K                            = 0
-	BPF_LD                           = 0
+	BPF_K                            = 0x0
+	BPF_LD                           = 0x0
 	BPF_LDX                          = 0x1
 	BPF_LEN                          = 0x80
 	BPF_LSH                          = 0x60
@@ -142,9 +142,9 @@ const (
 	BPF_ST                           = 0x2
 	BPF_STX                          = 0x3
 	BPF_SUB                          = 0x10
-	BPF_TAX                          = 0
+	BPF_TAX                          = 0x0
 	BPF_TXA                          = 0x80
-	BPF_W                            = 0
+	BPF_W                            = 0x0
 	BPF_X                            = 0x8
 	DT_BLK                           = 0x6
 	DT_CHR                           = 0x2
@@ -153,114 +153,8 @@ const (
 	DT_LNK                           = 0xa
 	DT_REG                           = 0x8
 	DT_SOCK                          = 0xc
-	DT_UNKNOWN                       = 0
+	DT_UNKNOWN                       = 0x0
 	DT_WHT                           = 0xe
-	E2BIG                            = 0x7
-	EACCES                           = 0xd
-	EADDRINUSE                       = 0x62
-	EADDRNOTAVAIL                    = 0x63
-	EADV                             = 0x44
-	EAFNOSUPPORT                     = 0x61
-	EAGAIN                           = 0xb
-	EALREADY                         = 0x72
-	EBADE                            = 0x34
-	EBADF                            = 0x9
-	EBADFD                           = 0x4d
-	EBADMSG                          = 0x4a
-	EBADR                            = 0x35
-	EBADRQC                          = 0x38
-	EBADSLT                          = 0x39
-	EBFONT                           = 0x3b
-	EBUSY                            = 0x10
-	ECANCELED                        = 0x7d
-	ECHILD                           = 0xa
-	ECHRNG                           = 0x2c
-	ECOMM                            = 0x46
-	ECONNABORTED                     = 0x67
-	ECONNREFUSED                     = 0x6f
-	ECONNRESET                       = 0x68
-	EDEADLK                          = 0x23
-	EDEADLOCK                        = 0x23
-	EDESTADDRREQ                     = 0x59
-	EDOM                             = 0x21
-	EDOTDOT                          = 0x49
-	EDQUOT                           = 0x7a
-	EEXIST                           = 0x11
-	EFAULT                           = 0xe
-	EFBIG                            = 0x1b
-	EHOSTDOWN                        = 0x70
-	EHOSTUNREACH                     = 0x71
-	EIDRM                            = 0x2b
-	EILSEQ                           = 0x54
-	EINPROGRESS                      = 0x73
-	EINTR                            = 0x4
-	EINVAL                           = 0x16
-	EIO                              = 0x5
-	EISCONN                          = 0x6a
-	EISDIR                           = 0x15
-	EISNAM                           = 0x78
-	EKEYEXPIRED                      = 0x7f
-	EKEYREJECTED                     = 0x81
-	EKEYREVOKED                      = 0x80
-	EL2HLT                           = 0x33
-	EL2NSYNC                         = 0x2d
-	EL3HLT                           = 0x2e
-	EL3RST                           = 0x2f
-	ELIBACC                          = 0x4f
-	ELIBBAD                          = 0x50
-	ELIBEXEC                         = 0x53
-	ELIBMAX                          = 0x52
-	ELIBSCN                          = 0x51
-	ELNRNG                           = 0x30
-	ELOOP                            = 0x28
-	EMEDIUMTYPE                      = 0x7c
-	EMFILE                           = 0x18
-	EMLINK                           = 0x1f
-	EMSGSIZE                         = 0x5a
-	EMULTIHOP                        = 0x48
-	ENAMETOOLONG                     = 0x24
-	ENAVAIL                          = 0x77
-	ENETDOWN                         = 0x64
-	ENETRESET                        = 0x66
-	ENETUNREACH                      = 0x65
-	ENFILE                           = 0x17
-	ENOANO                           = 0x37
-	ENOBUFS                          = 0x69
-	ENOCSI                           = 0x32
-	ENODATA                          = 0x3d
-	ENODEV                           = 0x13
-	ENOENT                           = 0x2
-	ENOEXEC                          = 0x8
-	ENOKEY                           = 0x7e
-	ENOLCK                           = 0x25
-	ENOLINK                          = 0x43
-	ENOMEDIUM                        = 0x7b
-	ENOMEM                           = 0xc
-	ENOMSG                           = 0x2a
-	ENONET                           = 0x40
-	ENOPKG                           = 0x41
-	ENOPROTOOPT                      = 0x5c
-	ENOSPC                           = 0x1c
-	ENOSR                            = 0x3f
-	ENOSTR                           = 0x3c
-	ENOSYS                           = 0x26
-	ENOTBLK                          = 0xf
-	ENOTCONN                         = 0x6b
-	ENOTDIR                          = 0x14
-	ENOTEMPTY                        = 0x27
-	ENOTNAM                          = 0x76
-	ENOTRECOVERABLE                  = 0x83
-	ENOTSOCK                         = 0x58
-	ENOTSUP                          = 0x5f
-	ENOTTY                           = 0x19
-	ENOTUNIQ                         = 0x4c
-	ENXIO                            = 0x6
-	EOPNOTSUPP                       = 0x5f
-	EOVERFLOW                        = 0x4b
-	EOWNERDEAD                       = 0x82
-	EPERM                            = 0x1
-	EPFNOSUPPORT                     = 0x60
-	EPIPE                            = 0x20
 	EPOLLERR                         = 0x8
 	EPOLLET                          = -0x80000000
 	EPOLLHUP                         = 0x10
@@ -279,23 +173,6 @@ const (
 	EPOLL_CTL_DEL                    = 0x2
 	EPOLL_CTL_MOD                    = 0x3
 	EPOLL_NONBLOCK                   = 0x800
-	EPROTO                           = 0x47
-	EPROTONOSUPPORT                  = 0x5d
-	EPROTOTYPE                       = 0x5b
-	ERANGE                           = 0x22
-	EREMCHG                          = 0x4e
-	EREMOTE                          = 0x42
-	EREMOTEIO                        = 0x79
-	ERESTART                         = 0x55
-	ERFKILL                          = 0x84
-	EROFS                            = 0x1e
-	ESHUTDOWN                        = 0x6c
-	ESOCKTNOSUPPORT                  = 0x5e
-	ESPIPE                           = 0x1d
-	ESRCH                            = 0x3
-	ESRMNT                           = 0x45
-	ESTALE                           = 0x74
-	ESTRPIPE                         = 0x56
 	ETH_P_1588                       = 0x88f7
 	ETH_P_8021Q                      = 0x8100
 	ETH_P_802_2                      = 0x4
@@ -310,6 +187,7 @@ const (
 	ETH_P_ATMMPOA                    = 0x884c
 	ETH_P_AX25                       = 0x2
 	ETH_P_BPQ                        = 0x8ff
+	ETH_P_CAIF                       = 0xf7
 	ETH_P_CAN                        = 0xc
 	ETH_P_CONTROL                    = 0x16
 	ETH_P_CUST                       = 0x6006
@@ -333,6 +211,7 @@ const (
 	ETH_P_IPX                        = 0x8137
 	ETH_P_IRDA                       = 0x17
 	ETH_P_LAT                        = 0x6004
+	ETH_P_LINK_CTL                   = 0x886c
 	ETH_P_LOCALTALK                  = 0x9
 	ETH_P_LOOP                       = 0x60
 	ETH_P_MOBITEX                    = 0x15
@@ -358,19 +237,9 @@ const (
 	ETH_P_WAN_PPP                    = 0x7
 	ETH_P_WCCP                       = 0x883e
 	ETH_P_X25                        = 0x805
-	ETIME                            = 0x3e
-	ETIMEDOUT                        = 0x6e
-	ETOOMANYREFS                     = 0x6d
-	ETXTBSY                          = 0x1a
-	EUCLEAN                          = 0x75
-	EUNATCH                          = 0x31
-	EUSERS                           = 0x57
-	EWOULDBLOCK                      = 0xb
-	EXDEV                            = 0x12
-	EXFULL                           = 0x36
 	FD_CLOEXEC                       = 0x1
 	FD_SETSIZE                       = 0x400
-	F_DUPFD                          = 0
+	F_DUPFD                          = 0x0
 	F_DUPFD_CLOEXEC                  = 0x406
 	F_EXLCK                          = 0x4
 	F_GETFD                          = 0x1
@@ -380,11 +249,12 @@ const (
 	F_GETLK64                        = 0x5
 	F_GETOWN                         = 0x9
 	F_GETOWN_EX                      = 0x10
+	F_GETPIPE_SZ                     = 0x408
 	F_GETSIG                         = 0xb
 	F_LOCK                           = 0x1
 	F_NOTIFY                         = 0x402
-	F_OK                             = 0
-	F_RDLCK                          = 0
+	F_OK                             = 0x0
+	F_RDLCK                          = 0x0
 	F_SETFD                          = 0x2
 	F_SETFL                          = 0x4
 	F_SETLEASE                       = 0x400
@@ -394,11 +264,12 @@ const (
 	F_SETLKW64                       = 0x7
 	F_SETOWN                         = 0x8
 	F_SETOWN_EX                      = 0xf
+	F_SETPIPE_SZ                     = 0x407
 	F_SETSIG                         = 0xa
 	F_SHLCK                          = 0x8
 	F_TEST                           = 0x3
 	F_TLOCK                          = 0x2
-	F_ULOCK                          = 0
+	F_ULOCK                          = 0x0
 	F_UNLCK                          = 0x2
 	F_WRLCK                          = 0x1
 	IFA_F_DADFAILED                  = 0x8
@@ -456,6 +327,7 @@ const (
 	IN_DELETE                        = 0x200
 	IN_DELETE_SELF                   = 0x400
 	IN_DONT_FOLLOW                   = 0x2000000
+	IN_EXCL_UNLINK                   = 0x4000000
 	IN_IGNORED                       = 0x8000
 	IN_ISDIR                         = 0x40000000
 	IN_LOOPBACKNET                   = 0x7f
@@ -480,12 +352,12 @@ const (
 	IPPROTO_ESP                      = 0x32
 	IPPROTO_FRAGMENT                 = 0x2c
 	IPPROTO_GRE                      = 0x2f
-	IPPROTO_HOPOPTS                  = 0
+	IPPROTO_HOPOPTS                  = 0x0
 	IPPROTO_ICMP                     = 0x1
 	IPPROTO_ICMPV6                   = 0x3a
 	IPPROTO_IDP                      = 0x16
 	IPPROTO_IGMP                     = 0x2
-	IPPROTO_IP                       = 0
+	IPPROTO_IP                       = 0x0
 	IPPROTO_IPIP                     = 0x4
 	IPPROTO_IPV6                     = 0x29
 	IPPROTO_MTP                      = 0x5c
@@ -527,7 +399,7 @@ const (
 	IPV6_NEXTHOP                     = 0x9
 	IPV6_PKTINFO                     = 0x32
 	IPV6_PMTUDISC_DO                 = 0x2
-	IPV6_PMTUDISC_DONT               = 0
+	IPV6_PMTUDISC_DONT               = 0x0
 	IPV6_PMTUDISC_PROBE              = 0x3
 	IPV6_PMTUDISC_WANT               = 0x1
 	IPV6_RECVDSTOPTS                 = 0x3a
@@ -540,9 +412,9 @@ const (
 	IPV6_ROUTER_ALERT                = 0x16
 	IPV6_RTHDR                       = 0x39
 	IPV6_RTHDRDSTOPTS                = 0x37
-	IPV6_RTHDR_LOOSE                 = 0
+	IPV6_RTHDR_LOOSE                 = 0x0
 	IPV6_RTHDR_STRICT                = 0x1
-	IPV6_RTHDR_TYPE_0                = 0
+	IPV6_RTHDR_TYPE_0                = 0x0
 	IPV6_RXDSTOPTS                   = 0x3b
 	IPV6_RXHOPOPTS                   = 0x36
 	IPV6_TCLASS                      = 0x43
@@ -557,27 +429,34 @@ const (
 	IP_DF                            = 0x4000
 	IP_DROP_MEMBERSHIP               = 0x24
 	IP_DROP_SOURCE_MEMBERSHIP        = 0x28
+	IP_FREEBIND                      = 0xf
 	IP_HDRINCL                       = 0x3
+	IP_IPSEC_POLICY                  = 0x10
 	IP_MAXPACKET                     = 0xffff
 	IP_MAX_MEMBERSHIPS               = 0x14
 	IP_MF                            = 0x2000
+	IP_MINTTL                        = 0x15
 	IP_MSFILTER                      = 0x29
 	IP_MSS                           = 0x240
+	IP_MTU                           = 0xe
 	IP_MTU_DISCOVER                  = 0xa
 	IP_MULTICAST_IF                  = 0x20
 	IP_MULTICAST_LOOP                = 0x22
 	IP_MULTICAST_TTL                 = 0x21
 	IP_OFFMASK                       = 0x1fff
 	IP_OPTIONS                       = 0x4
+	IP_ORIGDSTADDR                   = 0x14
+	IP_PASSSEC                       = 0x12
 	IP_PKTINFO                       = 0x8
 	IP_PKTOPTIONS                    = 0x9
 	IP_PMTUDISC                      = 0xa
 	IP_PMTUDISC_DO                   = 0x2
-	IP_PMTUDISC_DONT                 = 0
+	IP_PMTUDISC_DONT                 = 0x0
 	IP_PMTUDISC_PROBE                = 0x3
 	IP_PMTUDISC_WANT                 = 0x1
 	IP_RECVERR                       = 0xb
 	IP_RECVOPTS                      = 0x6
+	IP_RECVORIGDSTADDR               = 0x14
 	IP_RECVRETOPTS                   = 0x7
 	IP_RECVTOS                       = 0xd
 	IP_RECVTTL                       = 0xc
@@ -585,9 +464,11 @@ const (
 	IP_RF                            = 0x8000
 	IP_ROUTER_ALERT                  = 0x5
 	IP_TOS                           = 0x1
+	IP_TRANSPARENT                   = 0x13
 	IP_TTL                           = 0x2
 	IP_UNBLOCK_SOURCE                = 0x25
-	LINUX_REBOOT_CMD_CAD_OFF         = 0
+	IP_XFRM_POLICY                   = 0x11
+	LINUX_REBOOT_CMD_CAD_OFF         = 0x0
 	LINUX_REBOOT_CMD_CAD_ON          = 0x89abcdef
 	LINUX_REBOOT_CMD_HALT            = 0xcdef0123
 	LINUX_REBOOT_CMD_KEXEC           = 0x45584543
@@ -597,12 +478,18 @@ const (
 	LINUX_REBOOT_CMD_SW_SUSPEND      = 0xd000fce2
 	LINUX_REBOOT_MAGIC1              = 0xfee1dead
 	LINUX_REBOOT_MAGIC2              = 0x28121969
+	LOCK_EX                          = 0x2
+	LOCK_NB                          = 0x4
+	LOCK_SH                          = 0x1
+	LOCK_UN                          = 0x8
 	MADV_DOFORK                      = 0xb
 	MADV_DONTFORK                    = 0xa
 	MADV_DONTNEED                    = 0x4
+	MADV_HUGEPAGE                    = 0xe
 	MADV_HWPOISON                    = 0x64
 	MADV_MERGEABLE                   = 0xc
-	MADV_NORMAL                      = 0
+	MADV_NOHUGEPAGE                  = 0xf
+	MADV_NORMAL                      = 0x0
 	MADV_RANDOM                      = 0x1
 	MADV_REMOVE                      = 0x9
 	MADV_SEQUENTIAL                  = 0x2
@@ -613,9 +500,10 @@ const (
 	MAP_ANONYMOUS                    = 0x20
 	MAP_DENYWRITE                    = 0x800
 	MAP_EXECUTABLE                   = 0x1000
-	MAP_FILE                         = 0
+	MAP_FILE                         = 0x0
 	MAP_FIXED                        = 0x10
 	MAP_GROWSDOWN                    = 0x100
+	MAP_HUGETLB                      = 0x40000
 	MAP_LOCKED                       = 0x2000
 	MAP_NONBLOCK                     = 0x10000
 	MAP_NORESERVE                    = 0x4000
@@ -647,22 +535,38 @@ const (
 	MSG_TRUNC                        = 0x20
 	MSG_TRYHARD                      = 0x4
 	MSG_WAITALL                      = 0x100
+	MSG_WAITFORONE                   = 0x10000
+	MS_ACTIVE                        = 0x40000000
 	MS_ASYNC                         = 0x1
 	MS_BIND                          = 0x1000
+	MS_DIRSYNC                       = 0x80
 	MS_INVALIDATE                    = 0x2
+	MS_I_VERSION                     = 0x800000
+	MS_KERNMOUNT                     = 0x400000
 	MS_MANDLOCK                      = 0x40
 	MS_MGC_MSK                       = 0xffff0000
 	MS_MGC_VAL                       = 0xc0ed0000
+	MS_MOVE                          = 0x2000
 	MS_NOATIME                       = 0x400
 	MS_NODEV                         = 0x4
 	MS_NODIRATIME                    = 0x800
 	MS_NOEXEC                        = 0x8
 	MS_NOSUID                        = 0x2
+	MS_NOUSER                        = -0x80000000
+	MS_POSIXACL                      = 0x10000
+	MS_PRIVATE                       = 0x40000
 	MS_RDONLY                        = 0x1
+	MS_REC                           = 0x4000
+	MS_RELATIME                      = 0x200000
 	MS_REMOUNT                       = 0x20
-	MS_RMT_MASK                      = 0xc51
+	MS_RMT_MASK                      = 0x800051
+	MS_SHARED                        = 0x100000
+	MS_SILENT                        = 0x8000
+	MS_SLAVE                         = 0x80000
+	MS_STRICTATIME                   = 0x1000000
 	MS_SYNC                          = 0x4
 	MS_SYNCHRONOUS                   = 0x10
+	MS_UNBINDABLE                    = 0x20000
 	NAME_MAX                         = 0xff
 	NETLINK_ADD_MEMBERSHIP           = 0x1
 	NETLINK_AUDIT                    = 0x9
@@ -682,7 +586,8 @@ const (
 	NETLINK_NFLOG                    = 0x5
 	NETLINK_NO_ENOBUFS               = 0x5
 	NETLINK_PKTINFO                  = 0x3
-	NETLINK_ROUTE                    = 0
+	NETLINK_RDMA                     = 0x14
+	NETLINK_ROUTE                    = 0x0
 	NETLINK_SCSITRANSPORT            = 0x12
 	NETLINK_SELINUX                  = 0x7
 	NETLINK_UNUSED                   = 0x1
@@ -720,27 +625,27 @@ const (
 	O_DIRECTORY                      = 0x10000
 	O_DSYNC                          = 0x1000
 	O_EXCL                           = 0x80
-	O_FSYNC                          = 0x1000
-	O_LARGEFILE                      = 0
+	O_FSYNC                          = 0x101000
+	O_LARGEFILE                      = 0x0
 	O_NDELAY                         = 0x800
 	O_NOATIME                        = 0x40000
 	O_NOCTTY                         = 0x100
 	O_NOFOLLOW                       = 0x20000
 	O_NONBLOCK                       = 0x800
-	O_RDONLY                         = 0
+	O_RDONLY                         = 0x0
 	O_RDWR                           = 0x2
-	O_RSYNC                          = 0x1000
-	O_SYNC                           = 0x1000
+	O_RSYNC                          = 0x101000
+	O_SYNC                           = 0x101000
 	O_TRUNC                          = 0x200
 	O_WRONLY                         = 0x1
 	PACKET_ADD_MEMBERSHIP            = 0x1
 	PACKET_BROADCAST                 = 0x1
 	PACKET_DROP_MEMBERSHIP           = 0x2
 	PACKET_FASTROUTE                 = 0x6
-	PACKET_HOST                      = 0
+	PACKET_HOST                      = 0x0
 	PACKET_LOOPBACK                  = 0x5
 	PACKET_MR_ALLMULTI               = 0x2
-	PACKET_MR_MULTICAST              = 0
+	PACKET_MR_MULTICAST              = 0x0
 	PACKET_MR_PROMISC                = 0x1
 	PACKET_MULTICAST                 = 0x2
 	PACKET_OTHERHOST                 = 0x3
@@ -751,21 +656,69 @@ const (
 	PROT_EXEC                        = 0x4
 	PROT_GROWSDOWN                   = 0x1000000
 	PROT_GROWSUP                     = 0x2000000
-	PROT_NONE                        = 0
+	PROT_NONE                        = 0x0
 	PROT_READ                        = 0x1
 	PROT_WRITE                       = 0x2
+	PR_CAPBSET_DROP                  = 0x18
+	PR_CAPBSET_READ                  = 0x17
+	PR_ENDIAN_BIG                    = 0x0
+	PR_ENDIAN_LITTLE                 = 0x1
+	PR_ENDIAN_PPC_LITTLE             = 0x2
+	PR_FPEMU_NOPRINT                 = 0x1
+	PR_FPEMU_SIGFPE                  = 0x2
+	PR_FP_EXC_ASYNC                  = 0x2
+	PR_FP_EXC_DISABLED               = 0x0
+	PR_FP_EXC_DIV                    = 0x10000
+	PR_FP_EXC_INV                    = 0x100000
+	PR_FP_EXC_NONRECOV               = 0x1
+	PR_FP_EXC_OVF                    = 0x20000
+	PR_FP_EXC_PRECISE                = 0x3
+	PR_FP_EXC_RES                    = 0x80000
+	PR_FP_EXC_SW_ENABLE              = 0x80
+	PR_FP_EXC_UND                    = 0x40000
+	PR_GET_DUMPABLE                  = 0x3
+	PR_GET_ENDIAN                    = 0x13
+	PR_GET_FPEMU                     = 0x9
+	PR_GET_FPEXC                     = 0xb
+	PR_GET_KEEPCAPS                  = 0x7
+	PR_GET_NAME                      = 0x10
+	PR_GET_PDEATHSIG                 = 0x2
+	PR_GET_SECCOMP                   = 0x15
+	PR_GET_SECUREBITS                = 0x1b
+	PR_GET_TIMERSLACK                = 0x1e
+	PR_GET_TIMING                    = 0xd
+	PR_GET_TSC                       = 0x19
+	PR_GET_UNALIGN                   = 0x5
+	PR_MCE_KILL                      = 0x21
+	PR_MCE_KILL_CLEAR                = 0x0
+	PR_MCE_KILL_DEFAULT              = 0x2
+	PR_MCE_KILL_EARLY                = 0x1
+	PR_MCE_KILL_GET                  = 0x22
+	PR_MCE_KILL_LATE                 = 0x0
+	PR_MCE_KILL_SET                  = 0x1
+	PR_SET_DUMPABLE                  = 0x4
+	PR_SET_ENDIAN                    = 0x14
+	PR_SET_FPEMU                     = 0xa
+	PR_SET_FPEXC                     = 0xc
+	PR_SET_KEEPCAPS                  = 0x8
+	PR_SET_NAME                      = 0xf
+	PR_SET_PDEATHSIG                 = 0x1
+	PR_SET_SECCOMP                   = 0x16
+	PR_SET_SECUREBITS                = 0x1c
+	PR_SET_TIMERSLACK                = 0x1d
+	PR_SET_TIMING                    = 0xe
+	PR_SET_TSC                       = 0x1a
+	PR_SET_UNALIGN                   = 0x6
+	PR_TASK_PERF_EVENTS_DISABLE      = 0x1f
+	PR_TASK_PERF_EVENTS_ENABLE       = 0x20
+	PR_TIMING_STATISTICAL            = 0x0
+	PR_TIMING_TIMESTAMP              = 0x1
+	PR_TSC_ENABLE                    = 0x1
+	PR_TSC_SIGSEGV                   = 0x2
+	PR_UNALIGN_NOPRINT               = 0x1
+	PR_UNALIGN_SIGBUS                = 0x2
 	PTRACE_ARCH_PRCTL                = 0x1e
 	PTRACE_ATTACH                    = 0x10
-	PTRACE_BTS_CLEAR                 = 0x2c
-	PTRACE_BTS_CONFIG                = 0x28
-	PTRACE_BTS_DRAIN                 = 0x2d
-	PTRACE_BTS_GET                   = 0x2b
-	PTRACE_BTS_O_ALLOC               = 0x8
-	PTRACE_BTS_O_SCHED               = 0x2
-	PTRACE_BTS_O_SIGNAL              = 0x4
-	PTRACE_BTS_O_TRACE               = 0x1
-	PTRACE_BTS_SIZE                  = 0x2a
-	PTRACE_BTS_STATUS                = 0x29
 	PTRACE_CONT                      = 0x7
 	PTRACE_DETACH                    = 0x11
 	PTRACE_EVENT_CLONE               = 0x3
@@ -778,6 +731,7 @@ const (
 	PTRACE_GETFPREGS                 = 0xe
 	PTRACE_GETFPXREGS                = 0x12
 	PTRACE_GETREGS                   = 0xc
+	PTRACE_GETREGSET                 = 0x4204
 	PTRACE_GETSIGINFO                = 0x4202
 	PTRACE_GET_THREAD_AREA           = 0x19
 	PTRACE_KILL                      = 0x8
@@ -800,6 +754,7 @@ const (
 	PTRACE_SETFPXREGS                = 0x13
 	PTRACE_SETOPTIONS                = 0x4200
 	PTRACE_SETREGS                   = 0xd
+	PTRACE_SETREGSET                 = 0x4205
 	PTRACE_SETSIGINFO                = 0x4203
 	PTRACE_SET_THREAD_AREA           = 0x1a
 	PTRACE_SINGLEBLOCK               = 0x21
@@ -807,7 +762,15 @@ const (
 	PTRACE_SYSCALL                   = 0x18
 	PTRACE_SYSEMU                    = 0x1f
 	PTRACE_SYSEMU_SINGLESTEP         = 0x20
-	PTRACE_TRACEME                   = 0
+	PTRACE_TRACEME                   = 0x0
+	RLIMIT_AS                        = 0x9
+	RLIMIT_CORE                      = 0x4
+	RLIMIT_CPU                       = 0x0
+	RLIMIT_DATA                      = 0x2
+	RLIMIT_FSIZE                     = 0x1
+	RLIMIT_NOFILE                    = 0x7
+	RLIMIT_STACK                     = 0x3
+	RLIM_INFINITY                    = -0x1
 	RTAX_ADVMSS                      = 0x8
 	RTAX_CWND                        = 0x7
 	RTAX_FEATURES                    = 0xc
@@ -817,18 +780,19 @@ const (
 	RTAX_FEATURE_TIMESTAMP           = 0x4
 	RTAX_HOPLIMIT                    = 0xa
 	RTAX_INITCWND                    = 0xb
+	RTAX_INITRWND                    = 0xe
 	RTAX_LOCK                        = 0x1
-	RTAX_MAX                         = 0xd
+	RTAX_MAX                         = 0xe
 	RTAX_MTU                         = 0x2
 	RTAX_REORDERING                  = 0x9
 	RTAX_RTO_MIN                     = 0xd
 	RTAX_RTT                         = 0x4
 	RTAX_RTTVAR                      = 0x5
 	RTAX_SSTHRESH                    = 0x6
-	RTAX_UNSPEC                      = 0
+	RTAX_UNSPEC                      = 0x0
 	RTAX_WINDOW                      = 0x3
 	RTA_ALIGNTO                      = 0x4
-	RTA_MAX                          = 0xf
+	RTA_MAX                          = 0x10
 	RTCF_DIRECTSRC                   = 0x4000000
 	RTCF_DOREDIRECT                  = 0x1000000
 	RTCF_LOG                         = 0x2000000
@@ -929,20 +893,23 @@ const (
 	RTPROT_RA                        = 0x9
 	RTPROT_REDIRECT                  = 0x1
 	RTPROT_STATIC                    = 0x4
-	RTPROT_UNSPEC                    = 0
+	RTPROT_UNSPEC                    = 0x0
 	RTPROT_XORP                      = 0xe
 	RTPROT_ZEBRA                     = 0xb
 	RT_CLASS_DEFAULT                 = 0xfd
 	RT_CLASS_LOCAL                   = 0xff
 	RT_CLASS_MAIN                    = 0xfe
 	RT_CLASS_MAX                     = 0xff
-	RT_CLASS_UNSPEC                  = 0
+	RT_CLASS_UNSPEC                  = 0x0
+	RUSAGE_CHILDREN                  = -0x1
+	RUSAGE_SELF                      = 0x0
+	RUSAGE_THREAD                    = 0x1
 	SCM_CREDENTIALS                  = 0x2
 	SCM_RIGHTS                       = 0x1
 	SCM_TIMESTAMP                    = 0x1d
 	SCM_TIMESTAMPING                 = 0x25
 	SCM_TIMESTAMPNS                  = 0x23
-	SHUT_RD                          = 0
+	SHUT_RD                          = 0x0
 	SHUT_RDWR                        = 0x2
 	SHUT_WR                          = 0x1
 	SIGABRT                          = 0x6
@@ -1051,7 +1018,7 @@ const (
 	SOL_ATM                          = 0x108
 	SOL_DECNET                       = 0x105
 	SOL_ICMPV6                       = 0x3a
-	SOL_IP                           = 0
+	SOL_IP                           = 0x0
 	SOL_IPV6                         = 0x29
 	SOL_IRDA                         = 0x10a
 	SOL_PACKET                       = 0x107
@@ -1087,6 +1054,7 @@ const (
 	SO_RCVLOWAT                      = 0x12
 	SO_RCVTIMEO                      = 0x14
 	SO_REUSEADDR                     = 0x2
+	SO_RXQ_OVFL                      = 0x28
 	SO_SECURITY_AUTHENTICATION       = 0x16
 	SO_SECURITY_ENCRYPTION_NETWORK   = 0x18
 	SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17
@@ -1098,7 +1066,6 @@ const (
 	SO_TIMESTAMPING                  = 0x25
 	SO_TIMESTAMPNS                   = 0x23
 	SO_TYPE                          = 0x3
-	S_APPEND                         = 0x100
 	S_BLKSIZE                        = 0x200
 	S_IEXEC                          = 0x40
 	S_IFBLK                          = 0x6000
@@ -1109,7 +1076,6 @@ const (
 	S_IFMT                           = 0xf000
 	S_IFREG                          = 0x8000
 	S_IFSOCK                         = 0xc000
-	S_IMMUTABLE                      = 0x200
 	S_IREAD                          = 0x100
 	S_IRGRP                          = 0x20
 	S_IROTH                          = 0x4
@@ -1127,7 +1093,6 @@ const (
 	S_IXGRP                          = 0x8
 	S_IXOTH                          = 0x1
 	S_IXUSR                          = 0x40
-	S_WRITE                          = 0x80
 	TCP_CONGESTION                   = 0xd
 	TCP_CORK                         = 0x3
 	TCP_DEFER_ACCEPT                 = 0x9
@@ -1149,8 +1114,8 @@ const (
 	TIOCCBRK                         = 0x5428
 	TIOCCONS                         = 0x541d
 	TIOCEXCL                         = 0x540c
+	TIOCGDEV                         = 0x80045432
 	TIOCGETD                         = 0x5424
-	TIOCGHAYESESP                    = 0x545e
 	TIOCGICOUNT                      = 0x545d
 	TIOCGLCKTRMIOS                   = 0x5456
 	TIOCGPGRP                        = 0x540f
@@ -1182,10 +1147,11 @@ const (
 	TIOCNXCL                         = 0x540d
 	TIOCOUTQ                         = 0x5411
 	TIOCPKT                          = 0x5420
-	TIOCPKT_DATA                     = 0
+	TIOCPKT_DATA                     = 0x0
 	TIOCPKT_DOSTOP                   = 0x20
 	TIOCPKT_FLUSHREAD                = 0x1
 	TIOCPKT_FLUSHWRITE               = 0x2
+	TIOCPKT_IOCTL                    = 0x40
 	TIOCPKT_NOSTOP                   = 0x10
 	TIOCPKT_START                    = 0x8
 	TIOCPKT_STOP                     = 0x4
@@ -1200,7 +1166,7 @@ const (
 	TIOCSERSWILD                     = 0x5455
 	TIOCSER_TEMT                     = 0x1
 	TIOCSETD                         = 0x5423
-	TIOCSHAYESESP                    = 0x545f
+	TIOCSIG                          = 0x40045436
 	TIOCSLCKTRMIOS                   = 0x5457
 	TIOCSPGRP                        = 0x5410
 	TIOCSPTLCK                       = 0x40045431
@@ -1209,9 +1175,13 @@ const (
 	TIOCSSOFTCAR                     = 0x541a
 	TIOCSTI                          = 0x5412
 	TIOCSWINSZ                       = 0x5414
+	TIOCVHANGUP                      = 0x5437
+	TUNATTACHFILTER                  = 0x401054d5
+	TUNDETACHFILTER                  = 0x401054d6
 	TUNGETFEATURES                   = 0x800454cf
 	TUNGETIFF                        = 0x800454d2
 	TUNGETSNDBUF                     = 0x800454d3
+	TUNGETVNETHDRSZ                  = 0x800454d7
 	TUNSETDEBUG                      = 0x400454c9
 	TUNSETGROUP                      = 0x400454ce
 	TUNSETIFF                        = 0x400454ca
@@ -1222,6 +1192,7 @@ const (
 	TUNSETPERSIST                    = 0x400454cb
 	TUNSETSNDBUF                     = 0x400454d4
 	TUNSETTXFILTER                   = 0x400454d1
+	TUNSETVNETHDRSZ                  = 0x400454d8
 	WALL                             = 0x40000000
 	WCLONE                           = 0x80000000
 	WCONTINUED                       = 0x8
@@ -1234,7 +1205,143 @@ const (
 	WUNTRACED                        = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x62)
+	EADDRNOTAVAIL   = Errno(0x63)
+	EADV            = Errno(0x44)
+	EAFNOSUPPORT    = Errno(0x61)
+	EAGAIN          = Errno(0xb)
+	EALREADY        = Errno(0x72)
+	EBADE           = Errno(0x34)
+	EBADF           = Errno(0x9)
+	EBADFD          = Errno(0x4d)
+	EBADMSG         = Errno(0x4a)
+	EBADR           = Errno(0x35)
+	EBADRQC         = Errno(0x38)
+	EBADSLT         = Errno(0x39)
+	EBFONT          = Errno(0x3b)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x7d)
+	ECHILD          = Errno(0xa)
+	ECHRNG          = Errno(0x2c)
+	ECOMM           = Errno(0x46)
+	ECONNABORTED    = Errno(0x67)
+	ECONNREFUSED    = Errno(0x6f)
+	ECONNRESET      = Errno(0x68)
+	EDEADLK         = Errno(0x23)
+	EDEADLOCK       = Errno(0x23)
+	EDESTADDRREQ    = Errno(0x59)
+	EDOM            = Errno(0x21)
+	EDOTDOT         = Errno(0x49)
+	EDQUOT          = Errno(0x7a)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EHOSTDOWN       = Errno(0x70)
+	EHOSTUNREACH    = Errno(0x71)
+	EHWPOISON       = Errno(0x85)
+	EIDRM           = Errno(0x2b)
+	EILSEQ          = Errno(0x54)
+	EINPROGRESS     = Errno(0x73)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x6a)
+	EISDIR          = Errno(0x15)
+	EISNAM          = Errno(0x78)
+	EKEYEXPIRED     = Errno(0x7f)
+	EKEYREJECTED    = Errno(0x81)
+	EKEYREVOKED     = Errno(0x80)
+	EL2HLT          = Errno(0x33)
+	EL2NSYNC        = Errno(0x2d)
+	EL3HLT          = Errno(0x2e)
+	EL3RST          = Errno(0x2f)
+	ELIBACC         = Errno(0x4f)
+	ELIBBAD         = Errno(0x50)
+	ELIBEXEC        = Errno(0x53)
+	ELIBMAX         = Errno(0x52)
+	ELIBSCN         = Errno(0x51)
+	ELNRNG          = Errno(0x30)
+	ELOOP           = Errno(0x28)
+	EMEDIUMTYPE     = Errno(0x7c)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x5a)
+	EMULTIHOP       = Errno(0x48)
+	ENAMETOOLONG    = Errno(0x24)
+	ENAVAIL         = Errno(0x77)
+	ENETDOWN        = Errno(0x64)
+	ENETRESET       = Errno(0x66)
+	ENETUNREACH     = Errno(0x65)
+	ENFILE          = Errno(0x17)
+	ENOANO          = Errno(0x37)
+	ENOBUFS         = Errno(0x69)
+	ENOCSI          = Errno(0x32)
+	ENODATA         = Errno(0x3d)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOKEY          = Errno(0x7e)
+	ENOLCK          = Errno(0x25)
+	ENOLINK         = Errno(0x43)
+	ENOMEDIUM       = Errno(0x7b)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x2a)
+	ENONET          = Errno(0x40)
+	ENOPKG          = Errno(0x41)
+	ENOPROTOOPT     = Errno(0x5c)
+	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x3f)
+	ENOSTR          = Errno(0x3c)
+	ENOSYS          = Errno(0x26)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x6b)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x27)
+	ENOTNAM         = Errno(0x76)
+	ENOTRECOVERABLE = Errno(0x83)
+	ENOTSOCK        = Errno(0x58)
+	ENOTSUP         = Errno(0x5f)
+	ENOTTY          = Errno(0x19)
+	ENOTUNIQ        = Errno(0x4c)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x5f)
+	EOVERFLOW       = Errno(0x4b)
+	EOWNERDEAD      = Errno(0x82)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x60)
+	EPIPE           = Errno(0x20)
+	EPROTO          = Errno(0x47)
+	EPROTONOSUPPORT = Errno(0x5d)
+	EPROTOTYPE      = Errno(0x5b)
+	ERANGE          = Errno(0x22)
+	EREMCHG         = Errno(0x4e)
+	EREMOTE         = Errno(0x42)
+	EREMOTEIO       = Errno(0x79)
+	ERESTART        = Errno(0x55)
+	ERFKILL         = Errno(0x84)
+	EROFS           = Errno(0x1e)
+	ESHUTDOWN       = Errno(0x6c)
+	ESOCKTNOSUPPORT = Errno(0x5e)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESRMNT          = Errno(0x45)
+	ESTALE          = Errno(0x74)
+	ESTRPIPE        = Errno(0x56)
+	ETIME           = Errno(0x3e)
+	ETIMEDOUT       = Errno(0x6e)
+	ETOOMANYREFS    = Errno(0x6d)
+	ETXTBSY         = Errno(0x1a)
+	EUCLEAN         = Errno(0x75)
+	EUNATCH         = Errno(0x31)
+	EUSERS          = Errno(0x57)
+	EWOULDBLOCK     = Errno(0xb)
+	EXDEV           = Errno(0x12)
+	EXFULL          = Errno(0x36)
+)
 
 // Error table
 var errors = [...]string{
@@ -1367,5 +1474,6 @@ var errors = [...]string{
 	129: "key was rejected by service",
 	130: "owner died",
 	131: "state not recoverable",
-	132: "unknown error 132",
+	132: "operation not possible due to RF-kill",
+	133: "unknown error 133",
 }
diff --git a/src/pkg/syscall/zerrors_linux_arm.go b/src/pkg/syscall/zerrors_linux_arm.go
index da91b2a..04834fa 100644
--- a/src/pkg/syscall/zerrors_linux_arm.go
+++ b/src/pkg/syscall/zerrors_linux_arm.go
@@ -1,13 +1,11 @@
 // mkerrors.sh
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -gsyscall _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- _const.go
 
 package syscall
 
-// Constants
 const (
 	AF_APPLETALK                     = 0x5
 	AF_ASH                           = 0x12
@@ -45,7 +43,7 @@ const (
 	AF_SNA                           = 0x16
 	AF_TIPC                          = 0x1e
 	AF_UNIX                          = 0x1
-	AF_UNSPEC                        = 0
+	AF_UNSPEC                        = 0x0
 	AF_WANPIPE                       = 0x19
 	AF_X25                           = 0x9
 	ARPHRD_ADAPT                     = 0x108
@@ -90,7 +88,7 @@ const (
 	ARPHRD_LOCALTLK                  = 0x305
 	ARPHRD_LOOPBACK                  = 0x304
 	ARPHRD_METRICOM                  = 0x17
-	ARPHRD_NETROM                    = 0
+	ARPHRD_NETROM                    = 0x0
 	ARPHRD_NONE                      = 0xfffe
 	ARPHRD_PIMREG                    = 0x30b
 	ARPHRD_PPP                       = 0x200
@@ -108,22 +106,22 @@ const (
 	ARPHRD_X25                       = 0x10f
 	BPF_A                            = 0x10
 	BPF_ABS                          = 0x20
-	BPF_ADD                          = 0
+	BPF_ADD                          = 0x0
 	BPF_ALU                          = 0x4
 	BPF_AND                          = 0x50
 	BPF_B                            = 0x10
 	BPF_DIV                          = 0x30
 	BPF_H                            = 0x8
-	BPF_IMM                          = 0
+	BPF_IMM                          = 0x0
 	BPF_IND                          = 0x40
-	BPF_JA                           = 0
+	BPF_JA                           = 0x0
 	BPF_JEQ                          = 0x10
 	BPF_JGE                          = 0x30
 	BPF_JGT                          = 0x20
 	BPF_JMP                          = 0x5
 	BPF_JSET                         = 0x40
-	BPF_K                            = 0
-	BPF_LD                           = 0
+	BPF_K                            = 0x0
+	BPF_LD                           = 0x0
 	BPF_LDX                          = 0x1
 	BPF_LEN                          = 0x80
 	BPF_LSH                          = 0x60
@@ -142,9 +140,9 @@ const (
 	BPF_ST                           = 0x2
 	BPF_STX                          = 0x3
 	BPF_SUB                          = 0x10
-	BPF_TAX                          = 0
+	BPF_TAX                          = 0x0
 	BPF_TXA                          = 0x80
-	BPF_W                            = 0
+	BPF_W                            = 0x0
 	BPF_X                            = 0x8
 	DT_BLK                           = 0x6
 	DT_CHR                           = 0x2
@@ -153,116 +151,10 @@ const (
 	DT_LNK                           = 0xa
 	DT_REG                           = 0x8
 	DT_SOCK                          = 0xc
-	DT_UNKNOWN                       = 0
+	DT_UNKNOWN                       = 0x0
 	DT_WHT                           = 0xe
-	E2BIG                            = 0x7
-	EACCES                           = 0xd
-	EADDRINUSE                       = 0x62
-	EADDRNOTAVAIL                    = 0x63
-	EADV                             = 0x44
-	EAFNOSUPPORT                     = 0x61
-	EAGAIN                           = 0xb
-	EALREADY                         = 0x72
-	EBADE                            = 0x34
-	EBADF                            = 0x9
-	EBADFD                           = 0x4d
-	EBADMSG                          = 0x4a
-	EBADR                            = 0x35
-	EBADRQC                          = 0x38
-	EBADSLT                          = 0x39
-	EBFONT                           = 0x3b
-	EBUSY                            = 0x10
-	ECANCELED                        = 0x7d
-	ECHILD                           = 0xa
-	ECHRNG                           = 0x2c
-	ECOMM                            = 0x46
-	ECONNABORTED                     = 0x67
-	ECONNREFUSED                     = 0x6f
-	ECONNRESET                       = 0x68
-	EDEADLK                          = 0x23
-	EDEADLOCK                        = 0x23
-	EDESTADDRREQ                     = 0x59
-	EDOM                             = 0x21
-	EDOTDOT                          = 0x49
-	EDQUOT                           = 0x7a
-	EEXIST                           = 0x11
-	EFAULT                           = 0xe
-	EFBIG                            = 0x1b
-	EHOSTDOWN                        = 0x70
-	EHOSTUNREACH                     = 0x71
-	EIDRM                            = 0x2b
-	EILSEQ                           = 0x54
-	EINPROGRESS                      = 0x73
-	EINTR                            = 0x4
-	EINVAL                           = 0x16
-	EIO                              = 0x5
-	EISCONN                          = 0x6a
-	EISDIR                           = 0x15
-	EISNAM                           = 0x78
-	EKEYEXPIRED                      = 0x7f
-	EKEYREJECTED                     = 0x81
-	EKEYREVOKED                      = 0x80
-	EL2HLT                           = 0x33
-	EL2NSYNC                         = 0x2d
-	EL3HLT                           = 0x2e
-	EL3RST                           = 0x2f
 	ELF_NGREG                        = 0x12
 	ELF_PRARGSZ                      = 0x50
-	ELIBACC                          = 0x4f
-	ELIBBAD                          = 0x50
-	ELIBEXEC                         = 0x53
-	ELIBMAX                          = 0x52
-	ELIBSCN                          = 0x51
-	ELNRNG                           = 0x30
-	ELOOP                            = 0x28
-	EMEDIUMTYPE                      = 0x7c
-	EMFILE                           = 0x18
-	EMLINK                           = 0x1f
-	EMSGSIZE                         = 0x5a
-	EMULTIHOP                        = 0x48
-	ENAMETOOLONG                     = 0x24
-	ENAVAIL                          = 0x77
-	ENETDOWN                         = 0x64
-	ENETRESET                        = 0x66
-	ENETUNREACH                      = 0x65
-	ENFILE                           = 0x17
-	ENOANO                           = 0x37
-	ENOBUFS                          = 0x69
-	ENOCSI                           = 0x32
-	ENODATA                          = 0x3d
-	ENODEV                           = 0x13
-	ENOENT                           = 0x2
-	ENOEXEC                          = 0x8
-	ENOKEY                           = 0x7e
-	ENOLCK                           = 0x25
-	ENOLINK                          = 0x43
-	ENOMEDIUM                        = 0x7b
-	ENOMEM                           = 0xc
-	ENOMSG                           = 0x2a
-	ENONET                           = 0x40
-	ENOPKG                           = 0x41
-	ENOPROTOOPT                      = 0x5c
-	ENOSPC                           = 0x1c
-	ENOSR                            = 0x3f
-	ENOSTR                           = 0x3c
-	ENOSYS                           = 0x26
-	ENOTBLK                          = 0xf
-	ENOTCONN                         = 0x6b
-	ENOTDIR                          = 0x14
-	ENOTEMPTY                        = 0x27
-	ENOTNAM                          = 0x76
-	ENOTRECOVERABLE                  = 0x83
-	ENOTSOCK                         = 0x58
-	ENOTSUP                          = 0x5f
-	ENOTTY                           = 0x19
-	ENOTUNIQ                         = 0x4c
-	ENXIO                            = 0x6
-	EOPNOTSUPP                       = 0x5f
-	EOVERFLOW                        = 0x4b
-	EOWNERDEAD                       = 0x82
-	EPERM                            = 0x1
-	EPFNOSUPPORT                     = 0x60
-	EPIPE                            = 0x20
 	EPOLLERR                         = 0x8
 	EPOLLET                          = -0x80000000
 	EPOLLHUP                         = 0x10
@@ -281,23 +173,6 @@ const (
 	EPOLL_CTL_DEL                    = 0x2
 	EPOLL_CTL_MOD                    = 0x3
 	EPOLL_NONBLOCK                   = 0x800
-	EPROTO                           = 0x47
-	EPROTONOSUPPORT                  = 0x5d
-	EPROTOTYPE                       = 0x5b
-	ERANGE                           = 0x22
-	EREMCHG                          = 0x4e
-	EREMOTE                          = 0x42
-	EREMOTEIO                        = 0x79
-	ERESTART                         = 0x55
-	ERFKILL                          = 0x84
-	EROFS                            = 0x1e
-	ESHUTDOWN                        = 0x6c
-	ESOCKTNOSUPPORT                  = 0x5e
-	ESPIPE                           = 0x1d
-	ESRCH                            = 0x3
-	ESRMNT                           = 0x45
-	ESTALE                           = 0x74
-	ESTRPIPE                         = 0x56
 	ETH_P_1588                       = 0x88f7
 	ETH_P_8021Q                      = 0x8100
 	ETH_P_802_2                      = 0x4
@@ -360,19 +235,9 @@ const (
 	ETH_P_WAN_PPP                    = 0x7
 	ETH_P_WCCP                       = 0x883e
 	ETH_P_X25                        = 0x805
-	ETIME                            = 0x3e
-	ETIMEDOUT                        = 0x6e
-	ETOOMANYREFS                     = 0x6d
-	ETXTBSY                          = 0x1a
-	EUCLEAN                          = 0x75
-	EUNATCH                          = 0x31
-	EUSERS                           = 0x57
-	EWOULDBLOCK                      = 0xb
-	EXDEV                            = 0x12
-	EXFULL                           = 0x36
 	FD_CLOEXEC                       = 0x1
 	FD_SETSIZE                       = 0x400
-	F_DUPFD                          = 0
+	F_DUPFD                          = 0x0
 	F_DUPFD_CLOEXEC                  = 0x406
 	F_EXLCK                          = 0x4
 	F_GETFD                          = 0x1
@@ -385,8 +250,8 @@ const (
 	F_GETSIG                         = 0xb
 	F_LOCK                           = 0x1
 	F_NOTIFY                         = 0x402
-	F_OK                             = 0
-	F_RDLCK                          = 0
+	F_OK                             = 0x0
+	F_RDLCK                          = 0x0
 	F_SETFD                          = 0x2
 	F_SETFL                          = 0x4
 	F_SETLEASE                       = 0x400
@@ -400,7 +265,7 @@ const (
 	F_SHLCK                          = 0x8
 	F_TEST                           = 0x3
 	F_TLOCK                          = 0x2
-	F_ULOCK                          = 0
+	F_ULOCK                          = 0x0
 	F_UNLCK                          = 0x2
 	F_WRLCK                          = 0x1
 	IFA_F_DADFAILED                  = 0x8
@@ -482,12 +347,12 @@ const (
 	IPPROTO_ESP                      = 0x32
 	IPPROTO_FRAGMENT                 = 0x2c
 	IPPROTO_GRE                      = 0x2f
-	IPPROTO_HOPOPTS                  = 0
+	IPPROTO_HOPOPTS                  = 0x0
 	IPPROTO_ICMP                     = 0x1
 	IPPROTO_ICMPV6                   = 0x3a
 	IPPROTO_IDP                      = 0x16
 	IPPROTO_IGMP                     = 0x2
-	IPPROTO_IP                       = 0
+	IPPROTO_IP                       = 0x0
 	IPPROTO_IPIP                     = 0x4
 	IPPROTO_IPV6                     = 0x29
 	IPPROTO_MTP                      = 0x5c
@@ -529,7 +394,7 @@ const (
 	IPV6_NEXTHOP                     = 0x9
 	IPV6_PKTINFO                     = 0x32
 	IPV6_PMTUDISC_DO                 = 0x2
-	IPV6_PMTUDISC_DONT               = 0
+	IPV6_PMTUDISC_DONT               = 0x0
 	IPV6_PMTUDISC_PROBE              = 0x3
 	IPV6_PMTUDISC_WANT               = 0x1
 	IPV6_RECVDSTOPTS                 = 0x3a
@@ -542,9 +407,9 @@ const (
 	IPV6_ROUTER_ALERT                = 0x16
 	IPV6_RTHDR                       = 0x39
 	IPV6_RTHDRDSTOPTS                = 0x37
-	IPV6_RTHDR_LOOSE                 = 0
+	IPV6_RTHDR_LOOSE                 = 0x0
 	IPV6_RTHDR_STRICT                = 0x1
-	IPV6_RTHDR_TYPE_0                = 0
+	IPV6_RTHDR_TYPE_0                = 0x0
 	IPV6_RXDSTOPTS                   = 0x3b
 	IPV6_RXHOPOPTS                   = 0x36
 	IPV6_TCLASS                      = 0x43
@@ -575,7 +440,7 @@ const (
 	IP_PKTOPTIONS                    = 0x9
 	IP_PMTUDISC                      = 0xa
 	IP_PMTUDISC_DO                   = 0x2
-	IP_PMTUDISC_DONT                 = 0
+	IP_PMTUDISC_DONT                 = 0x0
 	IP_PMTUDISC_PROBE                = 0x3
 	IP_PMTUDISC_WANT                 = 0x1
 	IP_RECVERR                       = 0xb
@@ -589,7 +454,7 @@ const (
 	IP_TOS                           = 0x1
 	IP_TTL                           = 0x2
 	IP_UNBLOCK_SOURCE                = 0x25
-	LINUX_REBOOT_CMD_CAD_OFF         = 0
+	LINUX_REBOOT_CMD_CAD_OFF         = 0x0
 	LINUX_REBOOT_CMD_CAD_ON          = 0x89abcdef
 	LINUX_REBOOT_CMD_HALT            = 0xcdef0123
 	LINUX_REBOOT_CMD_KEXEC           = 0x45584543
@@ -599,12 +464,16 @@ const (
 	LINUX_REBOOT_CMD_SW_SUSPEND      = 0xd000fce2
 	LINUX_REBOOT_MAGIC1              = 0xfee1dead
 	LINUX_REBOOT_MAGIC2              = 0x28121969
+	LOCK_EX                          = 0x2
+	LOCK_NB                          = 0x4
+	LOCK_SH                          = 0x1
+	LOCK_UN                          = 0x8
 	MADV_DOFORK                      = 0xb
 	MADV_DONTFORK                    = 0xa
 	MADV_DONTNEED                    = 0x4
 	MADV_HWPOISON                    = 0x64
 	MADV_MERGEABLE                   = 0xc
-	MADV_NORMAL                      = 0
+	MADV_NORMAL                      = 0x0
 	MADV_RANDOM                      = 0x1
 	MADV_REMOVE                      = 0x9
 	MADV_SEQUENTIAL                  = 0x2
@@ -614,7 +483,7 @@ const (
 	MAP_ANONYMOUS                    = 0x20
 	MAP_DENYWRITE                    = 0x800
 	MAP_EXECUTABLE                   = 0x1000
-	MAP_FILE                         = 0
+	MAP_FILE                         = 0x0
 	MAP_FIXED                        = 0x10
 	MAP_GROWSDOWN                    = 0x100
 	MAP_LOCKED                       = 0x2000
@@ -682,7 +551,7 @@ const (
 	NETLINK_NFLOG                    = 0x5
 	NETLINK_NO_ENOBUFS               = 0x5
 	NETLINK_PKTINFO                  = 0x3
-	NETLINK_ROUTE                    = 0
+	NETLINK_ROUTE                    = 0x0
 	NETLINK_SCSITRANSPORT            = 0x12
 	NETLINK_SELINUX                  = 0x7
 	NETLINK_UNUSED                   = 0x1
@@ -727,7 +596,7 @@ const (
 	O_NOCTTY                         = 0x100
 	O_NOFOLLOW                       = 0x8000
 	O_NONBLOCK                       = 0x800
-	O_RDONLY                         = 0
+	O_RDONLY                         = 0x0
 	O_RDWR                           = 0x2
 	O_RSYNC                          = 0x1000
 	O_SYNC                           = 0x1000
@@ -737,10 +606,10 @@ const (
 	PACKET_BROADCAST                 = 0x1
 	PACKET_DROP_MEMBERSHIP           = 0x2
 	PACKET_FASTROUTE                 = 0x6
-	PACKET_HOST                      = 0
+	PACKET_HOST                      = 0x0
 	PACKET_LOOPBACK                  = 0x5
 	PACKET_MR_ALLMULTI               = 0x2
-	PACKET_MR_MULTICAST              = 0
+	PACKET_MR_MULTICAST              = 0x0
 	PACKET_MR_PROMISC                = 0x1
 	PACKET_MULTICAST                 = 0x2
 	PACKET_OTHERHOST                 = 0x3
@@ -751,9 +620,67 @@ const (
 	PROT_EXEC                        = 0x4
 	PROT_GROWSDOWN                   = 0x1000000
 	PROT_GROWSUP                     = 0x2000000
-	PROT_NONE                        = 0
+	PROT_NONE                        = 0x0
 	PROT_READ                        = 0x1
 	PROT_WRITE                       = 0x2
+	PR_CAPBSET_DROP                  = 0x18
+	PR_CAPBSET_READ                  = 0x17
+	PR_ENDIAN_BIG                    = 0x0
+	PR_ENDIAN_LITTLE                 = 0x1
+	PR_ENDIAN_PPC_LITTLE             = 0x2
+	PR_FPEMU_NOPRINT                 = 0x1
+	PR_FPEMU_SIGFPE                  = 0x2
+	PR_FP_EXC_ASYNC                  = 0x2
+	PR_FP_EXC_DISABLED               = 0x0
+	PR_FP_EXC_DIV                    = 0x10000
+	PR_FP_EXC_INV                    = 0x100000
+	PR_FP_EXC_NONRECOV               = 0x1
+	PR_FP_EXC_OVF                    = 0x20000
+	PR_FP_EXC_PRECISE                = 0x3
+	PR_FP_EXC_RES                    = 0x80000
+	PR_FP_EXC_SW_ENABLE              = 0x80
+	PR_FP_EXC_UND                    = 0x40000
+	PR_GET_DUMPABLE                  = 0x3
+	PR_GET_ENDIAN                    = 0x13
+	PR_GET_FPEMU                     = 0x9
+	PR_GET_FPEXC                     = 0xb
+	PR_GET_KEEPCAPS                  = 0x7
+	PR_GET_NAME                      = 0x10
+	PR_GET_PDEATHSIG                 = 0x2
+	PR_GET_SECCOMP                   = 0x15
+	PR_GET_SECUREBITS                = 0x1b
+	PR_GET_TIMERSLACK                = 0x1e
+	PR_GET_TIMING                    = 0xd
+	PR_GET_TSC                       = 0x19
+	PR_GET_UNALIGN                   = 0x5
+	PR_MCE_KILL                      = 0x21
+	PR_MCE_KILL_CLEAR                = 0x0
+	PR_MCE_KILL_DEFAULT              = 0x2
+	PR_MCE_KILL_EARLY                = 0x1
+	PR_MCE_KILL_GET                  = 0x22
+	PR_MCE_KILL_LATE                 = 0x0
+	PR_MCE_KILL_SET                  = 0x1
+	PR_SET_DUMPABLE                  = 0x4
+	PR_SET_ENDIAN                    = 0x14
+	PR_SET_FPEMU                     = 0xa
+	PR_SET_FPEXC                     = 0xc
+	PR_SET_KEEPCAPS                  = 0x8
+	PR_SET_NAME                      = 0xf
+	PR_SET_PDEATHSIG                 = 0x1
+	PR_SET_SECCOMP                   = 0x16
+	PR_SET_SECUREBITS                = 0x1c
+	PR_SET_TIMERSLACK                = 0x1d
+	PR_SET_TIMING                    = 0xe
+	PR_SET_TSC                       = 0x1a
+	PR_SET_UNALIGN                   = 0x6
+	PR_TASK_PERF_EVENTS_DISABLE      = 0x1f
+	PR_TASK_PERF_EVENTS_ENABLE       = 0x20
+	PR_TIMING_STATISTICAL            = 0x0
+	PR_TIMING_TIMESTAMP              = 0x1
+	PR_TSC_ENABLE                    = 0x1
+	PR_TSC_SIGSEGV                   = 0x2
+	PR_UNALIGN_NOPRINT               = 0x1
+	PR_UNALIGN_SIGBUS                = 0x2
 	PTRACE_ATTACH                    = 0x10
 	PTRACE_CONT                      = 0x7
 	PTRACE_DETACH                    = 0x11
@@ -797,10 +724,18 @@ const (
 	PTRACE_SET_SYSCALL               = 0x17
 	PTRACE_SINGLESTEP                = 0x9
 	PTRACE_SYSCALL                   = 0x18
-	PTRACE_TRACEME                   = 0
+	PTRACE_TRACEME                   = 0x0
 	PT_DATA_ADDR                     = 0x10004
 	PT_TEXT_ADDR                     = 0x10000
 	PT_TEXT_END_ADDR                 = 0x10008
+	RLIMIT_AS                        = 0x9
+	RLIMIT_CORE                      = 0x4
+	RLIMIT_CPU                       = 0x0
+	RLIMIT_DATA                      = 0x2
+	RLIMIT_FSIZE                     = 0x1
+	RLIMIT_NOFILE                    = 0x7
+	RLIMIT_STACK                     = 0x3
+	RLIM_INFINITY                    = -0x1
 	RTAX_ADVMSS                      = 0x8
 	RTAX_CWND                        = 0x7
 	RTAX_FEATURES                    = 0xc
@@ -818,7 +753,7 @@ const (
 	RTAX_RTT                         = 0x4
 	RTAX_RTTVAR                      = 0x5
 	RTAX_SSTHRESH                    = 0x6
-	RTAX_UNSPEC                      = 0
+	RTAX_UNSPEC                      = 0x0
 	RTAX_WINDOW                      = 0x3
 	RTA_ALIGNTO                      = 0x4
 	RTA_MAX                          = 0xf
@@ -922,20 +857,23 @@ const (
 	RTPROT_RA                        = 0x9
 	RTPROT_REDIRECT                  = 0x1
 	RTPROT_STATIC                    = 0x4
-	RTPROT_UNSPEC                    = 0
+	RTPROT_UNSPEC                    = 0x0
 	RTPROT_XORP                      = 0xe
 	RTPROT_ZEBRA                     = 0xb
 	RT_CLASS_DEFAULT                 = 0xfd
 	RT_CLASS_LOCAL                   = 0xff
 	RT_CLASS_MAIN                    = 0xfe
 	RT_CLASS_MAX                     = 0xff
-	RT_CLASS_UNSPEC                  = 0
+	RT_CLASS_UNSPEC                  = 0x0
+	RUSAGE_CHILDREN                  = -0x1
+	RUSAGE_SELF                      = 0x0
+	RUSAGE_THREAD                    = 0x1
 	SCM_CREDENTIALS                  = 0x2
 	SCM_RIGHTS                       = 0x1
 	SCM_TIMESTAMP                    = 0x1d
 	SCM_TIMESTAMPING                 = 0x25
 	SCM_TIMESTAMPNS                  = 0x23
-	SHUT_RD                          = 0
+	SHUT_RD                          = 0x0
 	SHUT_RDWR                        = 0x2
 	SHUT_WR                          = 0x1
 	SIGABRT                          = 0x6
@@ -1044,7 +982,7 @@ const (
 	SOL_ATM                          = 0x108
 	SOL_DECNET                       = 0x105
 	SOL_ICMPV6                       = 0x3a
-	SOL_IP                           = 0
+	SOL_IP                           = 0x0
 	SOL_IPV6                         = 0x29
 	SOL_IRDA                         = 0x10a
 	SOL_PACKET                       = 0x107
@@ -1173,7 +1111,7 @@ const (
 	TIOCNXCL                         = 0x540d
 	TIOCOUTQ                         = 0x5411
 	TIOCPKT                          = 0x5420
-	TIOCPKT_DATA                     = 0
+	TIOCPKT_DATA                     = 0x0
 	TIOCPKT_DOSTOP                   = 0x20
 	TIOCPKT_FLUSHREAD                = 0x1
 	TIOCPKT_FLUSHWRITE               = 0x2
@@ -1223,7 +1161,142 @@ const (
 	WUNTRACED                        = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x62)
+	EADDRNOTAVAIL   = Errno(0x63)
+	EADV            = Errno(0x44)
+	EAFNOSUPPORT    = Errno(0x61)
+	EAGAIN          = Errno(0xb)
+	EALREADY        = Errno(0x72)
+	EBADE           = Errno(0x34)
+	EBADF           = Errno(0x9)
+	EBADFD          = Errno(0x4d)
+	EBADMSG         = Errno(0x4a)
+	EBADR           = Errno(0x35)
+	EBADRQC         = Errno(0x38)
+	EBADSLT         = Errno(0x39)
+	EBFONT          = Errno(0x3b)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x7d)
+	ECHILD          = Errno(0xa)
+	ECHRNG          = Errno(0x2c)
+	ECOMM           = Errno(0x46)
+	ECONNABORTED    = Errno(0x67)
+	ECONNREFUSED    = Errno(0x6f)
+	ECONNRESET      = Errno(0x68)
+	EDEADLK         = Errno(0x23)
+	EDEADLOCK       = Errno(0x23)
+	EDESTADDRREQ    = Errno(0x59)
+	EDOM            = Errno(0x21)
+	EDOTDOT         = Errno(0x49)
+	EDQUOT          = Errno(0x7a)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EHOSTDOWN       = Errno(0x70)
+	EHOSTUNREACH    = Errno(0x71)
+	EIDRM           = Errno(0x2b)
+	EILSEQ          = Errno(0x54)
+	EINPROGRESS     = Errno(0x73)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x6a)
+	EISDIR          = Errno(0x15)
+	EISNAM          = Errno(0x78)
+	EKEYEXPIRED     = Errno(0x7f)
+	EKEYREJECTED    = Errno(0x81)
+	EKEYREVOKED     = Errno(0x80)
+	EL2HLT          = Errno(0x33)
+	EL2NSYNC        = Errno(0x2d)
+	EL3HLT          = Errno(0x2e)
+	EL3RST          = Errno(0x2f)
+	ELIBACC         = Errno(0x4f)
+	ELIBBAD         = Errno(0x50)
+	ELIBEXEC        = Errno(0x53)
+	ELIBMAX         = Errno(0x52)
+	ELIBSCN         = Errno(0x51)
+	ELNRNG          = Errno(0x30)
+	ELOOP           = Errno(0x28)
+	EMEDIUMTYPE     = Errno(0x7c)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x5a)
+	EMULTIHOP       = Errno(0x48)
+	ENAMETOOLONG    = Errno(0x24)
+	ENAVAIL         = Errno(0x77)
+	ENETDOWN        = Errno(0x64)
+	ENETRESET       = Errno(0x66)
+	ENETUNREACH     = Errno(0x65)
+	ENFILE          = Errno(0x17)
+	ENOANO          = Errno(0x37)
+	ENOBUFS         = Errno(0x69)
+	ENOCSI          = Errno(0x32)
+	ENODATA         = Errno(0x3d)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOKEY          = Errno(0x7e)
+	ENOLCK          = Errno(0x25)
+	ENOLINK         = Errno(0x43)
+	ENOMEDIUM       = Errno(0x7b)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x2a)
+	ENONET          = Errno(0x40)
+	ENOPKG          = Errno(0x41)
+	ENOPROTOOPT     = Errno(0x5c)
+	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x3f)
+	ENOSTR          = Errno(0x3c)
+	ENOSYS          = Errno(0x26)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x6b)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x27)
+	ENOTNAM         = Errno(0x76)
+	ENOTRECOVERABLE = Errno(0x83)
+	ENOTSOCK        = Errno(0x58)
+	ENOTSUP         = Errno(0x5f)
+	ENOTTY          = Errno(0x19)
+	ENOTUNIQ        = Errno(0x4c)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x5f)
+	EOVERFLOW       = Errno(0x4b)
+	EOWNERDEAD      = Errno(0x82)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x60)
+	EPIPE           = Errno(0x20)
+	EPROTO          = Errno(0x47)
+	EPROTONOSUPPORT = Errno(0x5d)
+	EPROTOTYPE      = Errno(0x5b)
+	ERANGE          = Errno(0x22)
+	EREMCHG         = Errno(0x4e)
+	EREMOTE         = Errno(0x42)
+	EREMOTEIO       = Errno(0x79)
+	ERESTART        = Errno(0x55)
+	ERFKILL         = Errno(0x84)
+	EROFS           = Errno(0x1e)
+	ESHUTDOWN       = Errno(0x6c)
+	ESOCKTNOSUPPORT = Errno(0x5e)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESRMNT          = Errno(0x45)
+	ESTALE          = Errno(0x74)
+	ESTRPIPE        = Errno(0x56)
+	ETIME           = Errno(0x3e)
+	ETIMEDOUT       = Errno(0x6e)
+	ETOOMANYREFS    = Errno(0x6d)
+	ETXTBSY         = Errno(0x1a)
+	EUCLEAN         = Errno(0x75)
+	EUNATCH         = Errno(0x31)
+	EUSERS          = Errno(0x57)
+	EWOULDBLOCK     = Errno(0xb)
+	EXDEV           = Errno(0x12)
+	EXFULL          = Errno(0x36)
+)
 
 // Error table
 var errors = [...]string{
diff --git a/src/pkg/syscall/zerrors_netbsd_386.go b/src/pkg/syscall/zerrors_netbsd_386.go
new file mode 100644
index 0000000..52dc69a
--- /dev/null
+++ b/src/pkg/syscall/zerrors_netbsd_386.go
@@ -0,0 +1,1368 @@
+// mkerrors.sh -m32
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m32 _const.go
+
+package syscall
+
+const (
+	AF_APPLETALK                      = 0x10
+	AF_BLUETOOTH                      = 0x20
+	AF_CCITT                          = 0xa
+	AF_CHAOS                          = 0x5
+	AF_CNT                            = 0x15
+	AF_COIP                           = 0x14
+	AF_DATAKIT                        = 0x9
+	AF_DECnet                         = 0xc
+	AF_DLI                            = 0xd
+	AF_E164                           = 0x1a
+	AF_ECMA                           = 0x8
+	AF_ENCAP                          = 0x1c
+	AF_HYLINK                         = 0xf
+	AF_IMPLINK                        = 0x3
+	AF_INET                           = 0x2
+	AF_INET6                          = 0x18
+	AF_IPX                            = 0x17
+	AF_ISDN                           = 0x1a
+	AF_ISO                            = 0x7
+	AF_KEY                            = 0x1e
+	AF_LAT                            = 0xe
+	AF_LINK                           = 0x12
+	AF_LOCAL                          = 0x1
+	AF_MAX                            = 0x24
+	AF_MPLS                           = 0x21
+	AF_NATM                           = 0x1b
+	AF_NS                             = 0x6
+	AF_OSI                            = 0x7
+	AF_PUP                            = 0x4
+	AF_ROUTE                          = 0x11
+	AF_SIP                            = 0x1d
+	AF_SNA                            = 0xb
+	AF_UNIX                           = 0x1
+	AF_UNSPEC                         = 0x0
+	ARPHRD_ETHER                      = 0x1
+	ARPHRD_FRELAY                     = 0xf
+	ARPHRD_IEEE1394                   = 0x18
+	ARPHRD_IEEE802                    = 0x6
+	BIOCFLUSH                         = 0x20004268
+	BIOCGBLEN                         = 0x40044266
+	BIOCGDIRFILT                      = 0x4004427c
+	BIOCGDLT                          = 0x4004426a
+	BIOCGDLTLIST                      = 0xc008427b
+	BIOCGETIF                         = 0x4020426b
+	BIOCGFILDROP                      = 0x40044278
+	BIOCGHDRCMPLT                     = 0x40044274
+	BIOCGRSIG                         = 0x40044273
+	BIOCGRTIMEOUT                     = 0x4008426e
+	BIOCGSTATS                        = 0x4008426f
+	BIOCIMMEDIATE                     = 0x80044270
+	BIOCLOCK                          = 0x20004276
+	BIOCPROMISC                       = 0x20004269
+	BIOCSBLEN                         = 0xc0044266
+	BIOCSDIRFILT                      = 0x8004427d
+	BIOCSDLT                          = 0x8004427a
+	BIOCSETF                          = 0x80084267
+	BIOCSETIF                         = 0x8020426c
+	BIOCSETWF                         = 0x80084277
+	BIOCSFILDROP                      = 0x80044279
+	BIOCSHDRCMPLT                     = 0x80044275
+	BIOCSRSIG                         = 0x80044272
+	BIOCSRTIMEOUT                     = 0x8008426d
+	BIOCVERSION                       = 0x40044271
+	BPF_A                             = 0x10
+	BPF_ABS                           = 0x20
+	BPF_ADD                           = 0x0
+	BPF_ALIGNMENT                     = 0x4
+	BPF_ALU                           = 0x4
+	BPF_AND                           = 0x50
+	BPF_B                             = 0x10
+	BPF_DIRECTION_IN                  = 0x1
+	BPF_DIRECTION_OUT                 = 0x2
+	BPF_DIV                           = 0x30
+	BPF_H                             = 0x8
+	BPF_IMM                           = 0x0
+	BPF_IND                           = 0x40
+	BPF_JA                            = 0x0
+	BPF_JEQ                           = 0x10
+	BPF_JGE                           = 0x30
+	BPF_JGT                           = 0x20
+	BPF_JMP                           = 0x5
+	BPF_JSET                          = 0x40
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
+	BPF_LDX                           = 0x1
+	BPF_LEN                           = 0x80
+	BPF_LSH                           = 0x60
+	BPF_MAJOR_VERSION                 = 0x1
+	BPF_MAXBUFSIZE                    = 0x200000
+	BPF_MAXINSNS                      = 0x200
+	BPF_MEM                           = 0x60
+	BPF_MEMWORDS                      = 0x10
+	BPF_MINBUFSIZE                    = 0x20
+	BPF_MINOR_VERSION                 = 0x1
+	BPF_MISC                          = 0x7
+	BPF_MSH                           = 0xa0
+	BPF_MUL                           = 0x20
+	BPF_NEG                           = 0x80
+	BPF_OR                            = 0x40
+	BPF_RELEASE                       = 0x30bb6
+	BPF_RET                           = 0x6
+	BPF_RSH                           = 0x70
+	BPF_ST                            = 0x2
+	BPF_STX                           = 0x3
+	BPF_SUB                           = 0x10
+	BPF_TAX                           = 0x0
+	BPF_TXA                           = 0x80
+	BPF_W                             = 0x0
+	BPF_X                             = 0x8
+	CTL_MAXNAME                       = 0xc
+	CTL_NET                           = 0x4
+	DLT_ARCNET                        = 0x7
+	DLT_ATM_RFC1483                   = 0xb
+	DLT_AX25                          = 0x3
+	DLT_CHAOS                         = 0x5
+	DLT_EN10MB                        = 0x1
+	DLT_EN3MB                         = 0x2
+	DLT_ENC                           = 0xd
+	DLT_FDDI                          = 0xa
+	DLT_IEEE802                       = 0x6
+	DLT_IEEE802_11                    = 0x69
+	DLT_IEEE802_11_RADIO              = 0x7f
+	DLT_LOOP                          = 0xc
+	DLT_MPLS                          = 0xdb
+	DLT_NULL                          = 0x0
+	DLT_PFLOG                         = 0x75
+	DLT_PFSYNC                        = 0x12
+	DLT_PPP                           = 0x9
+	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_ETHER                     = 0x33
+	DLT_PRONET                        = 0x4
+	DLT_RAW                           = 0xe
+	DLT_SLIP                          = 0x8
+	DLT_SLIP_BSDOS                    = 0xf
+	DT_BLK                            = 0x6
+	DT_CHR                            = 0x2
+	DT_DIR                            = 0x4
+	DT_FIFO                           = 0x1
+	DT_LNK                            = 0xa
+	DT_REG                            = 0x8
+	DT_SOCK                           = 0xc
+	DT_UNKNOWN                        = 0x0
+	EFER_LMA                          = 0x400
+	EFER_LME                          = 0x100
+	EFER_NXE                          = 0x800
+	EFER_SCE                          = 0x1
+	EMT_TAGOVF                        = 0x1
+	EMUL_ENABLED                      = 0x1
+	EMUL_NATIVE                       = 0x2
+	ETHERMIN                          = 0x2e
+	ETHERMTU                          = 0x5dc
+	ETHERTYPE_8023                    = 0x4
+	ETHERTYPE_AARP                    = 0x80f3
+	ETHERTYPE_ACCTON                  = 0x8390
+	ETHERTYPE_AEONIC                  = 0x8036
+	ETHERTYPE_ALPHA                   = 0x814a
+	ETHERTYPE_AMBER                   = 0x6008
+	ETHERTYPE_AMOEBA                  = 0x8145
+	ETHERTYPE_AOE                     = 0x88a2
+	ETHERTYPE_APOLLO                  = 0x80f7
+	ETHERTYPE_APOLLODOMAIN            = 0x8019
+	ETHERTYPE_APPLETALK               = 0x809b
+	ETHERTYPE_APPLITEK                = 0x80c7
+	ETHERTYPE_ARGONAUT                = 0x803a
+	ETHERTYPE_ARP                     = 0x806
+	ETHERTYPE_AT                      = 0x809b
+	ETHERTYPE_ATALK                   = 0x809b
+	ETHERTYPE_ATOMIC                  = 0x86df
+	ETHERTYPE_ATT                     = 0x8069
+	ETHERTYPE_ATTSTANFORD             = 0x8008
+	ETHERTYPE_AUTOPHON                = 0x806a
+	ETHERTYPE_AXIS                    = 0x8856
+	ETHERTYPE_BCLOOP                  = 0x9003
+	ETHERTYPE_BOFL                    = 0x8102
+	ETHERTYPE_CABLETRON               = 0x7034
+	ETHERTYPE_CHAOS                   = 0x804
+	ETHERTYPE_COMDESIGN               = 0x806c
+	ETHERTYPE_COMPUGRAPHIC            = 0x806d
+	ETHERTYPE_COUNTERPOINT            = 0x8062
+	ETHERTYPE_CRONUS                  = 0x8004
+	ETHERTYPE_CRONUSVLN               = 0x8003
+	ETHERTYPE_DCA                     = 0x1234
+	ETHERTYPE_DDE                     = 0x807b
+	ETHERTYPE_DEBNI                   = 0xaaaa
+	ETHERTYPE_DECAM                   = 0x8048
+	ETHERTYPE_DECCUST                 = 0x6006
+	ETHERTYPE_DECDIAG                 = 0x6005
+	ETHERTYPE_DECDNS                  = 0x803c
+	ETHERTYPE_DECDTS                  = 0x803e
+	ETHERTYPE_DECEXPER                = 0x6000
+	ETHERTYPE_DECLAST                 = 0x8041
+	ETHERTYPE_DECLTM                  = 0x803f
+	ETHERTYPE_DECMUMPS                = 0x6009
+	ETHERTYPE_DECNETBIOS              = 0x8040
+	ETHERTYPE_DELTACON                = 0x86de
+	ETHERTYPE_DIDDLE                  = 0x4321
+	ETHERTYPE_DLOG1                   = 0x660
+	ETHERTYPE_DLOG2                   = 0x661
+	ETHERTYPE_DN                      = 0x6003
+	ETHERTYPE_DOGFIGHT                = 0x1989
+	ETHERTYPE_DSMD                    = 0x8039
+	ETHERTYPE_ECMA                    = 0x803
+	ETHERTYPE_ENCRYPT                 = 0x803d
+	ETHERTYPE_ES                      = 0x805d
+	ETHERTYPE_EXCELAN                 = 0x8010
+	ETHERTYPE_EXPERDATA               = 0x8049
+	ETHERTYPE_FLIP                    = 0x8146
+	ETHERTYPE_FLOWCONTROL             = 0x8808
+	ETHERTYPE_FRARP                   = 0x808
+	ETHERTYPE_GENDYN                  = 0x8068
+	ETHERTYPE_HAYES                   = 0x8130
+	ETHERTYPE_HIPPI_FP                = 0x8180
+	ETHERTYPE_HITACHI                 = 0x8820
+	ETHERTYPE_HP                      = 0x8005
+	ETHERTYPE_IEEEPUP                 = 0xa00
+	ETHERTYPE_IEEEPUPAT               = 0xa01
+	ETHERTYPE_IMLBL                   = 0x4c42
+	ETHERTYPE_IMLBLDIAG               = 0x424c
+	ETHERTYPE_IP                      = 0x800
+	ETHERTYPE_IPAS                    = 0x876c
+	ETHERTYPE_IPV6                    = 0x86dd
+	ETHERTYPE_IPX                     = 0x8137
+	ETHERTYPE_IPXNEW                  = 0x8037
+	ETHERTYPE_KALPANA                 = 0x8582
+	ETHERTYPE_LANBRIDGE               = 0x8038
+	ETHERTYPE_LANPROBE                = 0x8888
+	ETHERTYPE_LAT                     = 0x6004
+	ETHERTYPE_LBACK                   = 0x9000
+	ETHERTYPE_LITTLE                  = 0x8060
+	ETHERTYPE_LLDP                    = 0x88cc
+	ETHERTYPE_LOGICRAFT               = 0x8148
+	ETHERTYPE_LOOPBACK                = 0x9000
+	ETHERTYPE_MATRA                   = 0x807a
+	ETHERTYPE_MAX                     = 0xffff
+	ETHERTYPE_MERIT                   = 0x807c
+	ETHERTYPE_MICP                    = 0x873a
+	ETHERTYPE_MOPDL                   = 0x6001
+	ETHERTYPE_MOPRC                   = 0x6002
+	ETHERTYPE_MOTOROLA                = 0x818d
+	ETHERTYPE_MPLS                    = 0x8847
+	ETHERTYPE_MPLS_MCAST              = 0x8848
+	ETHERTYPE_MUMPS                   = 0x813f
+	ETHERTYPE_NBPCC                   = 0x3c04
+	ETHERTYPE_NBPCLAIM                = 0x3c09
+	ETHERTYPE_NBPCLREQ                = 0x3c05
+	ETHERTYPE_NBPCLRSP                = 0x3c06
+	ETHERTYPE_NBPCREQ                 = 0x3c02
+	ETHERTYPE_NBPCRSP                 = 0x3c03
+	ETHERTYPE_NBPDG                   = 0x3c07
+	ETHERTYPE_NBPDGB                  = 0x3c08
+	ETHERTYPE_NBPDLTE                 = 0x3c0a
+	ETHERTYPE_NBPRAR                  = 0x3c0c
+	ETHERTYPE_NBPRAS                  = 0x3c0b
+	ETHERTYPE_NBPRST                  = 0x3c0d
+	ETHERTYPE_NBPSCD                  = 0x3c01
+	ETHERTYPE_NBPVCD                  = 0x3c00
+	ETHERTYPE_NBS                     = 0x802
+	ETHERTYPE_NCD                     = 0x8149
+	ETHERTYPE_NESTAR                  = 0x8006
+	ETHERTYPE_NETBEUI                 = 0x8191
+	ETHERTYPE_NOVELL                  = 0x8138
+	ETHERTYPE_NS                      = 0x600
+	ETHERTYPE_NSAT                    = 0x601
+	ETHERTYPE_NSCOMPAT                = 0x807
+	ETHERTYPE_NTRAILER                = 0x10
+	ETHERTYPE_OS9                     = 0x7007
+	ETHERTYPE_OS9NET                  = 0x7009
+	ETHERTYPE_PACER                   = 0x80c6
+	ETHERTYPE_PAE                     = 0x888e
+	ETHERTYPE_PCS                     = 0x4242
+	ETHERTYPE_PLANNING                = 0x8044
+	ETHERTYPE_PPP                     = 0x880b
+	ETHERTYPE_PPPOE                   = 0x8864
+	ETHERTYPE_PPPOEDISC               = 0x8863
+	ETHERTYPE_PRIMENTS                = 0x7031
+	ETHERTYPE_PUP                     = 0x200
+	ETHERTYPE_PUPAT                   = 0x200
+	ETHERTYPE_QINQ                    = 0x88a8
+	ETHERTYPE_RACAL                   = 0x7030
+	ETHERTYPE_RATIONAL                = 0x8150
+	ETHERTYPE_RAWFR                   = 0x6559
+	ETHERTYPE_RCL                     = 0x1995
+	ETHERTYPE_RDP                     = 0x8739
+	ETHERTYPE_RETIX                   = 0x80f2
+	ETHERTYPE_REVARP                  = 0x8035
+	ETHERTYPE_SCA                     = 0x6007
+	ETHERTYPE_SECTRA                  = 0x86db
+	ETHERTYPE_SECUREDATA              = 0x876d
+	ETHERTYPE_SGITW                   = 0x817e
+	ETHERTYPE_SG_BOUNCE               = 0x8016
+	ETHERTYPE_SG_DIAG                 = 0x8013
+	ETHERTYPE_SG_NETGAMES             = 0x8014
+	ETHERTYPE_SG_RESV                 = 0x8015
+	ETHERTYPE_SIMNET                  = 0x5208
+	ETHERTYPE_SLOW                    = 0x8809
+	ETHERTYPE_SNA                     = 0x80d5
+	ETHERTYPE_SNMP                    = 0x814c
+	ETHERTYPE_SONIX                   = 0xfaf5
+	ETHERTYPE_SPIDER                  = 0x809f
+	ETHERTYPE_SPRITE                  = 0x500
+	ETHERTYPE_STP                     = 0x8181
+	ETHERTYPE_TALARIS                 = 0x812b
+	ETHERTYPE_TALARISMC               = 0x852b
+	ETHERTYPE_TCPCOMP                 = 0x876b
+	ETHERTYPE_TCPSM                   = 0x9002
+	ETHERTYPE_TEC                     = 0x814f
+	ETHERTYPE_TIGAN                   = 0x802f
+	ETHERTYPE_TRAIL                   = 0x1000
+	ETHERTYPE_TRANSETHER              = 0x6558
+	ETHERTYPE_TYMSHARE                = 0x802e
+	ETHERTYPE_UBBST                   = 0x7005
+	ETHERTYPE_UBDEBUG                 = 0x900
+	ETHERTYPE_UBDIAGLOOP              = 0x7002
+	ETHERTYPE_UBDL                    = 0x7000
+	ETHERTYPE_UBNIU                   = 0x7001
+	ETHERTYPE_UBNMC                   = 0x7003
+	ETHERTYPE_VALID                   = 0x1600
+	ETHERTYPE_VARIAN                  = 0x80dd
+	ETHERTYPE_VAXELN                  = 0x803b
+	ETHERTYPE_VEECO                   = 0x8067
+	ETHERTYPE_VEXP                    = 0x805b
+	ETHERTYPE_VGLAB                   = 0x8131
+	ETHERTYPE_VINES                   = 0xbad
+	ETHERTYPE_VINESECHO               = 0xbaf
+	ETHERTYPE_VINESLOOP               = 0xbae
+	ETHERTYPE_VITAL                   = 0xff00
+	ETHERTYPE_VLAN                    = 0x8100
+	ETHERTYPE_VLTLMAN                 = 0x8080
+	ETHERTYPE_VPROD                   = 0x805c
+	ETHERTYPE_VURESERVED              = 0x8147
+	ETHERTYPE_WATERLOO                = 0x8130
+	ETHERTYPE_WELLFLEET               = 0x8103
+	ETHERTYPE_X25                     = 0x805
+	ETHERTYPE_X75                     = 0x801
+	ETHERTYPE_XNSSM                   = 0x9001
+	ETHERTYPE_XTP                     = 0x817d
+	ETHER_ADDR_LEN                    = 0x6
+	ETHER_ALIGN                       = 0x2
+	ETHER_CRC_LEN                     = 0x4
+	ETHER_CRC_POLY_BE                 = 0x4c11db6
+	ETHER_CRC_POLY_LE                 = 0xedb88320
+	ETHER_HDR_LEN                     = 0xe
+	ETHER_MAX_DIX_LEN                 = 0x600
+	ETHER_MAX_LEN                     = 0x5ee
+	ETHER_MIN_LEN                     = 0x40
+	ETHER_TYPE_LEN                    = 0x2
+	ETHER_VLAN_ENCAP_LEN              = 0x4
+	EVFILT_AIO                        = -0x3
+	EVFILT_PROC                       = -0x5
+	EVFILT_READ                       = -0x1
+	EVFILT_SIGNAL                     = -0x6
+	EVFILT_SYSCOUNT                   = 0x7
+	EVFILT_TIMER                      = -0x7
+	EVFILT_VNODE                      = -0x4
+	EVFILT_WRITE                      = -0x2
+	EV_ADD                            = 0x1
+	EV_CLEAR                          = 0x20
+	EV_DELETE                         = 0x2
+	EV_DISABLE                        = 0x8
+	EV_ENABLE                         = 0x4
+	EV_EOF                            = 0x8000
+	EV_ERROR                          = 0x4000
+	EV_FLAG1                          = 0x2000
+	EV_ONESHOT                        = 0x10
+	EV_SYSFLAGS                       = 0xf000
+	EXTA                              = 0x4b00
+	EXTB                              = 0x9600
+	EXTPROC                           = 0x800
+	FD_CLOEXEC                        = 0x1
+	FD_SETSIZE                        = 0x400
+	F_DUPFD                           = 0x0
+	F_DUPFD_CLOEXEC                   = 0xa
+	F_GETFD                           = 0x1
+	F_GETFL                           = 0x3
+	F_GETLK                           = 0x7
+	F_GETOWN                          = 0x5
+	F_RDLCK                           = 0x1
+	F_SETFD                           = 0x2
+	F_SETFL                           = 0x4
+	F_SETLK                           = 0x8
+	F_SETLKW                          = 0x9
+	F_SETOWN                          = 0x6
+	F_UNLCK                           = 0x2
+	F_WRLCK                           = 0x3
+	IFA_ROUTE                         = 0x1
+	IFF_ALLMULTI                      = 0x200
+	IFF_BROADCAST                     = 0x2
+	IFF_CANTCHANGE                    = 0x8e52
+	IFF_DEBUG                         = 0x4
+	IFF_LINK0                         = 0x1000
+	IFF_LINK1                         = 0x2000
+	IFF_LINK2                         = 0x4000
+	IFF_LOOPBACK                      = 0x8
+	IFF_MULTICAST                     = 0x8000
+	IFF_NOARP                         = 0x80
+	IFF_NOTRAILERS                    = 0x20
+	IFF_OACTIVE                       = 0x400
+	IFF_POINTOPOINT                   = 0x10
+	IFF_PROMISC                       = 0x100
+	IFF_RUNNING                       = 0x40
+	IFF_SIMPLEX                       = 0x800
+	IFF_UP                            = 0x1
+	IFNAMSIZ                          = 0x10
+	IFT_1822                          = 0x2
+	IFT_A12MPPSWITCH                  = 0x82
+	IFT_AAL2                          = 0xbb
+	IFT_AAL5                          = 0x31
+	IFT_ADSL                          = 0x5e
+	IFT_AFLANE8023                    = 0x3b
+	IFT_AFLANE8025                    = 0x3c
+	IFT_ARAP                          = 0x58
+	IFT_ARCNET                        = 0x23
+	IFT_ARCNETPLUS                    = 0x24
+	IFT_ASYNC                         = 0x54
+	IFT_ATM                           = 0x25
+	IFT_ATMDXI                        = 0x69
+	IFT_ATMFUNI                       = 0x6a
+	IFT_ATMIMA                        = 0x6b
+	IFT_ATMLOGICAL                    = 0x50
+	IFT_ATMRADIO                      = 0xbd
+	IFT_ATMSUBINTERFACE               = 0x86
+	IFT_ATMVCIENDPT                   = 0xc2
+	IFT_ATMVIRTUAL                    = 0x95
+	IFT_BGPPOLICYACCOUNTING           = 0xa2
+	IFT_BLUETOOTH                     = 0xf8
+	IFT_BRIDGE                        = 0xd1
+	IFT_BSC                           = 0x53
+	IFT_CARP                          = 0xf7
+	IFT_CCTEMUL                       = 0x3d
+	IFT_CEPT                          = 0x13
+	IFT_CES                           = 0x85
+	IFT_CHANNEL                       = 0x46
+	IFT_CNR                           = 0x55
+	IFT_COFFEE                        = 0x84
+	IFT_COMPOSITELINK                 = 0x9b
+	IFT_DCN                           = 0x8d
+	IFT_DIGITALPOWERLINE              = 0x8a
+	IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+	IFT_DLSW                          = 0x4a
+	IFT_DOCSCABLEDOWNSTREAM           = 0x80
+	IFT_DOCSCABLEMACLAYER             = 0x7f
+	IFT_DOCSCABLEUPSTREAM             = 0x81
+	IFT_DOCSCABLEUPSTREAMCHANNEL      = 0xcd
+	IFT_DS0                           = 0x51
+	IFT_DS0BUNDLE                     = 0x52
+	IFT_DS1FDL                        = 0xaa
+	IFT_DS3                           = 0x1e
+	IFT_DTM                           = 0x8c
+	IFT_DUMMY                         = 0xf1
+	IFT_DVBASILN                      = 0xac
+	IFT_DVBASIOUT                     = 0xad
+	IFT_DVBRCCDOWNSTREAM              = 0x93
+	IFT_DVBRCCMACLAYER                = 0x92
+	IFT_DVBRCCUPSTREAM                = 0x94
+	IFT_ECONET                        = 0xce
+	IFT_ENC                           = 0xf4
+	IFT_EON                           = 0x19
+	IFT_EPLRS                         = 0x57
+	IFT_ESCON                         = 0x49
+	IFT_ETHER                         = 0x6
+	IFT_FAITH                         = 0xf3
+	IFT_FAST                          = 0x7d
+	IFT_FASTETHER                     = 0x3e
+	IFT_FASTETHERFX                   = 0x45
+	IFT_FDDI                          = 0xf
+	IFT_FIBRECHANNEL                  = 0x38
+	IFT_FRAMERELAYINTERCONNECT        = 0x3a
+	IFT_FRAMERELAYMPI                 = 0x5c
+	IFT_FRDLCIENDPT                   = 0xc1
+	IFT_FRELAY                        = 0x20
+	IFT_FRELAYDCE                     = 0x2c
+	IFT_FRF16MFRBUNDLE                = 0xa3
+	IFT_FRFORWARD                     = 0x9e
+	IFT_G703AT2MB                     = 0x43
+	IFT_G703AT64K                     = 0x42
+	IFT_GIF                           = 0xf0
+	IFT_GIGABITETHERNET               = 0x75
+	IFT_GR303IDT                      = 0xb2
+	IFT_GR303RDT                      = 0xb1
+	IFT_H323GATEKEEPER                = 0xa4
+	IFT_H323PROXY                     = 0xa5
+	IFT_HDH1822                       = 0x3
+	IFT_HDLC                          = 0x76
+	IFT_HDSL2                         = 0xa8
+	IFT_HIPERLAN2                     = 0xb7
+	IFT_HIPPI                         = 0x2f
+	IFT_HIPPIINTERFACE                = 0x39
+	IFT_HOSTPAD                       = 0x5a
+	IFT_HSSI                          = 0x2e
+	IFT_HY                            = 0xe
+	IFT_IBM370PARCHAN                 = 0x48
+	IFT_IDSL                          = 0x9a
+	IFT_IEEE1394                      = 0x90
+	IFT_IEEE80211                     = 0x47
+	IFT_IEEE80212                     = 0x37
+	IFT_IEEE8023ADLAG                 = 0xa1
+	IFT_IFGSN                         = 0x91
+	IFT_IMT                           = 0xbe
+	IFT_INFINIBAND                    = 0xc7
+	IFT_INTERLEAVE                    = 0x7c
+	IFT_IP                            = 0x7e
+	IFT_IPFORWARD                     = 0x8e
+	IFT_IPOVERATM                     = 0x72
+	IFT_IPOVERCDLC                    = 0x6d
+	IFT_IPOVERCLAW                    = 0x6e
+	IFT_IPSWITCH                      = 0x4e
+	IFT_ISDN                          = 0x3f
+	IFT_ISDNBASIC                     = 0x14
+	IFT_ISDNPRIMARY                   = 0x15
+	IFT_ISDNS                         = 0x4b
+	IFT_ISDNU                         = 0x4c
+	IFT_ISO88022LLC                   = 0x29
+	IFT_ISO88023                      = 0x7
+	IFT_ISO88024                      = 0x8
+	IFT_ISO88025                      = 0x9
+	IFT_ISO88025CRFPINT               = 0x62
+	IFT_ISO88025DTR                   = 0x56
+	IFT_ISO88025FIBER                 = 0x73
+	IFT_ISO88026                      = 0xa
+	IFT_ISUP                          = 0xb3
+	IFT_L2VLAN                        = 0x87
+	IFT_L3IPVLAN                      = 0x88
+	IFT_L3IPXVLAN                     = 0x89
+	IFT_LAPB                          = 0x10
+	IFT_LAPD                          = 0x4d
+	IFT_LAPF                          = 0x77
+	IFT_LINEGROUP                     = 0xd2
+	IFT_LOCALTALK                     = 0x2a
+	IFT_LOOP                          = 0x18
+	IFT_MEDIAMAILOVERIP               = 0x8b
+	IFT_MFSIGLINK                     = 0xa7
+	IFT_MIOX25                        = 0x26
+	IFT_MODEM                         = 0x30
+	IFT_MPC                           = 0x71
+	IFT_MPLS                          = 0xa6
+	IFT_MPLSTUNNEL                    = 0x96
+	IFT_MSDSL                         = 0x8f
+	IFT_MVL                           = 0xbf
+	IFT_MYRINET                       = 0x63
+	IFT_NFAS                          = 0xaf
+	IFT_NSIP                          = 0x1b
+	IFT_OPTICALCHANNEL                = 0xc3
+	IFT_OPTICALTRANSPORT              = 0xc4
+	IFT_OTHER                         = 0x1
+	IFT_P10                           = 0xc
+	IFT_P80                           = 0xd
+	IFT_PARA                          = 0x22
+	IFT_PFLOG                         = 0xf5
+	IFT_PFLOW                         = 0xf9
+	IFT_PFSYNC                        = 0xf6
+	IFT_PLC                           = 0xae
+	IFT_PON155                        = 0xcf
+	IFT_PON622                        = 0xd0
+	IFT_POS                           = 0xab
+	IFT_PPP                           = 0x17
+	IFT_PPPMULTILINKBUNDLE            = 0x6c
+	IFT_PROPATM                       = 0xc5
+	IFT_PROPBWAP2MP                   = 0xb8
+	IFT_PROPCNLS                      = 0x59
+	IFT_PROPDOCSWIRELESSDOWNSTREAM    = 0xb5
+	IFT_PROPDOCSWIRELESSMACLAYER      = 0xb4
+	IFT_PROPDOCSWIRELESSUPSTREAM      = 0xb6
+	IFT_PROPMUX                       = 0x36
+	IFT_PROPVIRTUAL                   = 0x35
+	IFT_PROPWIRELESSP2P               = 0x9d
+	IFT_PTPSERIAL                     = 0x16
+	IFT_PVC                           = 0xf2
+	IFT_Q2931                         = 0xc9
+	IFT_QLLC                          = 0x44
+	IFT_RADIOMAC                      = 0xbc
+	IFT_RADSL                         = 0x5f
+	IFT_REACHDSL                      = 0xc0
+	IFT_RFC1483                       = 0x9f
+	IFT_RS232                         = 0x21
+	IFT_RSRB                          = 0x4f
+	IFT_SDLC                          = 0x11
+	IFT_SDSL                          = 0x60
+	IFT_SHDSL                         = 0xa9
+	IFT_SIP                           = 0x1f
+	IFT_SIPSIG                        = 0xcc
+	IFT_SIPTG                         = 0xcb
+	IFT_SLIP                          = 0x1c
+	IFT_SMDSDXI                       = 0x2b
+	IFT_SMDSICIP                      = 0x34
+	IFT_SONET                         = 0x27
+	IFT_SONETOVERHEADCHANNEL          = 0xb9
+	IFT_SONETPATH                     = 0x32
+	IFT_SONETVT                       = 0x33
+	IFT_SRP                           = 0x97
+	IFT_SS7SIGLINK                    = 0x9c
+	IFT_STACKTOSTACK                  = 0x6f
+	IFT_STARLAN                       = 0xb
+	IFT_T1                            = 0x12
+	IFT_TDLC                          = 0x74
+	IFT_TELINK                        = 0xc8
+	IFT_TERMPAD                       = 0x5b
+	IFT_TR008                         = 0xb0
+	IFT_TRANSPHDLC                    = 0x7b
+	IFT_TUNNEL                        = 0x83
+	IFT_ULTRA                         = 0x1d
+	IFT_USB                           = 0xa0
+	IFT_V11                           = 0x40
+	IFT_V35                           = 0x2d
+	IFT_V36                           = 0x41
+	IFT_V37                           = 0x78
+	IFT_VDSL                          = 0x61
+	IFT_VIRTUALIPADDRESS              = 0x70
+	IFT_VIRTUALTG                     = 0xca
+	IFT_VOICEDID                      = 0xd5
+	IFT_VOICEEM                       = 0x64
+	IFT_VOICEEMFGD                    = 0xd3
+	IFT_VOICEENCAP                    = 0x67
+	IFT_VOICEFGDEANA                  = 0xd4
+	IFT_VOICEFXO                      = 0x65
+	IFT_VOICEFXS                      = 0x66
+	IFT_VOICEOVERATM                  = 0x98
+	IFT_VOICEOVERCABLE                = 0xc6
+	IFT_VOICEOVERFRAMERELAY           = 0x99
+	IFT_VOICEOVERIP                   = 0x68
+	IFT_X213                          = 0x5d
+	IFT_X25                           = 0x5
+	IFT_X25DDN                        = 0x4
+	IFT_X25HUNTGROUP                  = 0x7a
+	IFT_X25MLP                        = 0x79
+	IFT_X25PLE                        = 0x28
+	IFT_XETHER                        = 0x1a
+	IN_CLASSA_HOST                    = 0xffffff
+	IN_CLASSA_MAX                     = 0x80
+	IN_CLASSA_NET                     = 0xff000000
+	IN_CLASSA_NSHIFT                  = 0x18
+	IN_CLASSB_HOST                    = 0xffff
+	IN_CLASSB_MAX                     = 0x10000
+	IN_CLASSB_NET                     = 0xffff0000
+	IN_CLASSB_NSHIFT                  = 0x10
+	IN_CLASSC_HOST                    = 0xff
+	IN_CLASSC_NET                     = 0xffffff00
+	IN_CLASSC_NSHIFT                  = 0x8
+	IN_CLASSD_HOST                    = 0xfffffff
+	IN_CLASSD_NET                     = 0xf0000000
+	IN_CLASSD_NSHIFT                  = 0x1c
+	IN_LOOPBACKNET                    = 0x7f
+	IN_RFC3021_HOST                   = 0x1
+	IN_RFC3021_NET                    = 0xfffffffe
+	IN_RFC3021_NSHIFT                 = 0x1f
+	IPPROTO_AH                        = 0x33
+	IPPROTO_CARP                      = 0x70
+	IPPROTO_DIVERT                    = 0x102
+	IPPROTO_DONE                      = 0x101
+	IPPROTO_DSTOPTS                   = 0x3c
+	IPPROTO_EGP                       = 0x8
+	IPPROTO_ENCAP                     = 0x62
+	IPPROTO_EON                       = 0x50
+	IPPROTO_ESP                       = 0x32
+	IPPROTO_ETHERIP                   = 0x61
+	IPPROTO_FRAGMENT                  = 0x2c
+	IPPROTO_GGP                       = 0x3
+	IPPROTO_GRE                       = 0x2f
+	IPPROTO_HOPOPTS                   = 0x0
+	IPPROTO_ICMP                      = 0x1
+	IPPROTO_ICMPV6                    = 0x3a
+	IPPROTO_IDP                       = 0x16
+	IPPROTO_IGMP                      = 0x2
+	IPPROTO_IP                        = 0x0
+	IPPROTO_IPCOMP                    = 0x6c
+	IPPROTO_IPIP                      = 0x4
+	IPPROTO_IPV4                      = 0x4
+	IPPROTO_IPV6                      = 0x29
+	IPPROTO_MAX                       = 0x100
+	IPPROTO_MAXID                     = 0x103
+	IPPROTO_MOBILE                    = 0x37
+	IPPROTO_MPLS                      = 0x89
+	IPPROTO_NONE                      = 0x3b
+	IPPROTO_PFSYNC                    = 0xf0
+	IPPROTO_PIM                       = 0x67
+	IPPROTO_PUP                       = 0xc
+	IPPROTO_RAW                       = 0xff
+	IPPROTO_ROUTING                   = 0x2b
+	IPPROTO_RSVP                      = 0x2e
+	IPPROTO_TCP                       = 0x6
+	IPPROTO_TP                        = 0x1d
+	IPPROTO_UDP                       = 0x11
+	IPV6_AUTH_LEVEL                   = 0x35
+	IPV6_AUTOFLOWLABEL                = 0x3b
+	IPV6_CHECKSUM                     = 0x1a
+	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
+	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
+	IPV6_DEFHLIM                      = 0x40
+	IPV6_DONTFRAG                     = 0x3e
+	IPV6_DSTOPTS                      = 0x32
+	IPV6_ESP_NETWORK_LEVEL            = 0x37
+	IPV6_ESP_TRANS_LEVEL              = 0x36
+	IPV6_FAITH                        = 0x1d
+	IPV6_FLOWINFO_MASK                = 0xffffff0f
+	IPV6_FLOWLABEL_MASK               = 0xffff0f00
+	IPV6_FRAGTTL                      = 0x78
+	IPV6_HLIMDEC                      = 0x1
+	IPV6_HOPLIMIT                     = 0x2f
+	IPV6_HOPOPTS                      = 0x31
+	IPV6_IPCOMP_LEVEL                 = 0x3c
+	IPV6_JOIN_GROUP                   = 0xc
+	IPV6_LEAVE_GROUP                  = 0xd
+	IPV6_MAXHLIM                      = 0xff
+	IPV6_MAXPACKET                    = 0xffff
+	IPV6_MMTU                         = 0x500
+	IPV6_MULTICAST_HOPS               = 0xa
+	IPV6_MULTICAST_IF                 = 0x9
+	IPV6_MULTICAST_LOOP               = 0xb
+	IPV6_NEXTHOP                      = 0x30
+	IPV6_OPTIONS                      = 0x1
+	IPV6_PATHMTU                      = 0x2c
+	IPV6_PIPEX                        = 0x3f
+	IPV6_PKTINFO                      = 0x2e
+	IPV6_PORTRANGE                    = 0xe
+	IPV6_PORTRANGE_DEFAULT            = 0x0
+	IPV6_PORTRANGE_HIGH               = 0x1
+	IPV6_PORTRANGE_LOW                = 0x2
+	IPV6_RECVDSTOPTS                  = 0x28
+	IPV6_RECVHOPLIMIT                 = 0x25
+	IPV6_RECVHOPOPTS                  = 0x27
+	IPV6_RECVPATHMTU                  = 0x2b
+	IPV6_RECVPKTINFO                  = 0x24
+	IPV6_RECVRTHDR                    = 0x26
+	IPV6_RECVTCLASS                   = 0x39
+	IPV6_RTABLE                       = 0x1021
+	IPV6_RTHDR                        = 0x33
+	IPV6_RTHDRDSTOPTS                 = 0x23
+	IPV6_RTHDR_LOOSE                  = 0x0
+	IPV6_RTHDR_STRICT                 = 0x1
+	IPV6_RTHDR_TYPE_0                 = 0x0
+	IPV6_SOCKOPT_RESERVED1            = 0x3
+	IPV6_TCLASS                       = 0x3d
+	IPV6_UNICAST_HOPS                 = 0x4
+	IPV6_USE_MIN_MTU                  = 0x2a
+	IPV6_V6ONLY                       = 0x1b
+	IPV6_VERSION                      = 0x60
+	IPV6_VERSION_MASK                 = 0xf0
+	IP_ADD_MEMBERSHIP                 = 0xc
+	IP_AUTH_LEVEL                     = 0x14
+	IP_DEFAULT_MULTICAST_LOOP         = 0x1
+	IP_DEFAULT_MULTICAST_TTL          = 0x1
+	IP_DF                             = 0x4000
+	IP_DROP_MEMBERSHIP                = 0xd
+	IP_ESP_NETWORK_LEVEL              = 0x16
+	IP_ESP_TRANS_LEVEL                = 0x15
+	IP_HDRINCL                        = 0x2
+	IP_IPCOMP_LEVEL                   = 0x1d
+	IP_IPSEC_LOCAL_AUTH               = 0x1b
+	IP_IPSEC_LOCAL_CRED               = 0x19
+	IP_IPSEC_LOCAL_ID                 = 0x17
+	IP_IPSEC_REMOTE_AUTH              = 0x1c
+	IP_IPSEC_REMOTE_CRED              = 0x1a
+	IP_IPSEC_REMOTE_ID                = 0x18
+	IP_MAXPACKET                      = 0xffff
+	IP_MAX_MEMBERSHIPS                = 0xfff
+	IP_MF                             = 0x2000
+	IP_MINTTL                         = 0x20
+	IP_MIN_MEMBERSHIPS                = 0xf
+	IP_MSS                            = 0x240
+	IP_MULTICAST_IF                   = 0x9
+	IP_MULTICAST_LOOP                 = 0xb
+	IP_MULTICAST_TTL                  = 0xa
+	IP_OFFMASK                        = 0x1fff
+	IP_OPTIONS                        = 0x1
+	IP_PIPEX                          = 0x22
+	IP_PORTRANGE                      = 0x13
+	IP_PORTRANGE_DEFAULT              = 0x0
+	IP_PORTRANGE_HIGH                 = 0x1
+	IP_PORTRANGE_LOW                  = 0x2
+	IP_RECVDSTADDR                    = 0x7
+	IP_RECVDSTPORT                    = 0x21
+	IP_RECVIF                         = 0x1e
+	IP_RECVOPTS                       = 0x5
+	IP_RECVRETOPTS                    = 0x6
+	IP_RECVRTABLE                     = 0x23
+	IP_RECVTTL                        = 0x1f
+	IP_RETOPTS                        = 0x8
+	IP_RF                             = 0x8000
+	IP_RTABLE                         = 0x1021
+	IP_TOS                            = 0x3
+	IP_TTL                            = 0x4
+	MAP_ET_KVAGUARD                   = 0x10
+	MSG_BCAST                         = 0x100
+	MSG_CTRUNC                        = 0x20
+	MSG_DONTROUTE                     = 0x4
+	MSG_DONTWAIT                      = 0x80
+	MSG_EOR                           = 0x8
+	MSG_MCAST                         = 0x200
+	MSG_OOB                           = 0x1
+	MSG_PEEK                          = 0x2
+	MSG_TRUNC                         = 0x10
+	MSG_WAITALL                       = 0x40
+	NAME_MAX                          = 0xff
+	NET_RT_DUMP                       = 0x1
+	NET_RT_FLAGS                      = 0x2
+	NET_RT_IFLIST                     = 0x3
+	NET_RT_MAXID                      = 0x6
+	NET_RT_STATS                      = 0x4
+	NET_RT_TABLE                      = 0x5
+	O_ACCMODE                         = 0x3
+	O_APPEND                          = 0x8
+	O_ASYNC                           = 0x40
+	O_CLOEXEC                         = 0x10000
+	O_CREAT                           = 0x200
+	O_DIRECTORY                       = 0x20000
+	O_DSYNC                           = 0x80
+	O_EXCL                            = 0x800
+	O_EXLOCK                          = 0x20
+	O_FSYNC                           = 0x80
+	O_NDELAY                          = 0x4
+	O_NOCTTY                          = 0x8000
+	O_NOFOLLOW                        = 0x100
+	O_NONBLOCK                        = 0x4
+	O_RDONLY                          = 0x0
+	O_RDWR                            = 0x2
+	O_RSYNC                           = 0x80
+	O_SHLOCK                          = 0x10
+	O_SYNC                            = 0x80
+	O_TRUNC                           = 0x400
+	O_WRONLY                          = 0x1
+	RTAX_AUTHOR                       = 0x6
+	RTAX_BRD                          = 0x7
+	RTAX_DST                          = 0x0
+	RTAX_GATEWAY                      = 0x1
+	RTAX_GENMASK                      = 0x3
+	RTAX_IFA                          = 0x5
+	RTAX_IFP                          = 0x4
+	RTAX_LABEL                        = 0xa
+	RTAX_MAX                          = 0xb
+	RTAX_NETMASK                      = 0x2
+	RTAX_SRC                          = 0x8
+	RTAX_SRCMASK                      = 0x9
+	RTA_AUTHOR                        = 0x40
+	RTA_BRD                           = 0x80
+	RTA_DST                           = 0x1
+	RTA_GATEWAY                       = 0x2
+	RTA_GENMASK                       = 0x8
+	RTA_IFA                           = 0x20
+	RTA_IFP                           = 0x10
+	RTA_LABEL                         = 0x400
+	RTA_NETMASK                       = 0x4
+	RTA_SRC                           = 0x100
+	RTA_SRCMASK                       = 0x200
+	RTF_ANNOUNCE                      = 0x4000
+	RTF_BLACKHOLE                     = 0x1000
+	RTF_CLONED                        = 0x10000
+	RTF_CLONING                       = 0x100
+	RTF_DONE                          = 0x40
+	RTF_DYNAMIC                       = 0x10
+	RTF_FMASK                         = 0x8f808
+	RTF_GATEWAY                       = 0x2
+	RTF_HOST                          = 0x4
+	RTF_JUMBO                         = 0x80000
+	RTF_LLINFO                        = 0x400
+	RTF_MASK                          = 0x80
+	RTF_MODIFIED                      = 0x20
+	RTF_MPATH                         = 0x40000
+	RTF_MPLS                          = 0x100000
+	RTF_PERMANENT_ARP                 = 0x2000
+	RTF_PROTO1                        = 0x8000
+	RTF_PROTO2                        = 0x4000
+	RTF_PROTO3                        = 0x2000
+	RTF_REJECT                        = 0x8
+	RTF_SOURCE                        = 0x20000
+	RTF_STATIC                        = 0x800
+	RTF_TUNNEL                        = 0x100000
+	RTF_UP                            = 0x1
+	RTF_USETRAILERS                   = 0x8000
+	RTF_XRESOLVE                      = 0x200
+	RTM_ADD                           = 0x1
+	RTM_CHANGE                        = 0x3
+	RTM_DELADDR                       = 0xd
+	RTM_DELETE                        = 0x2
+	RTM_DESYNC                        = 0x10
+	RTM_GET                           = 0x4
+	RTM_IFANNOUNCE                    = 0xf
+	RTM_IFINFO                        = 0xe
+	RTM_LOCK                          = 0x8
+	RTM_LOSING                        = 0x5
+	RTM_MAXSIZE                       = 0x800
+	RTM_MISS                          = 0x7
+	RTM_NEWADDR                       = 0xc
+	RTM_REDIRECT                      = 0x6
+	RTM_RESOLVE                       = 0xb
+	RTM_RTTUNIT                       = 0xf4240
+	RTM_VERSION                       = 0x4
+	RTV_EXPIRE                        = 0x4
+	RTV_HOPCOUNT                      = 0x2
+	RTV_MTU                           = 0x1
+	RTV_RPIPE                         = 0x8
+	RTV_RTT                           = 0x40
+	RTV_RTTVAR                        = 0x80
+	RTV_SPIPE                         = 0x10
+	RTV_SSTHRESH                      = 0x20
+	RT_TABLEID_MAX                    = 0xff
+	SCM_CREDS                         = 0x2
+	SCM_RIGHTS                        = 0x1
+	SCM_TIMESTAMP                     = 0x4
+	SHUT_RD                           = 0x0
+	SHUT_RDWR                         = 0x2
+	SHUT_WR                           = 0x1
+	SIGABRT                           = 0x6
+	SIGALRM                           = 0xe
+	SIGBUS                            = 0xa
+	SIGCHLD                           = 0x14
+	SIGCONT                           = 0x13
+	SIGEMT                            = 0x7
+	SIGFPE                            = 0x8
+	SIGHUP                            = 0x1
+	SIGILL                            = 0x4
+	SIGINFO                           = 0x1d
+	SIGINT                            = 0x2
+	SIGIO                             = 0x17
+	SIGIOT                            = 0x6
+	SIGKILL                           = 0x9
+	SIGPIPE                           = 0xd
+	SIGPROF                           = 0x1b
+	SIGQUIT                           = 0x3
+	SIGSEGV                           = 0xb
+	SIGSTOP                           = 0x11
+	SIGSYS                            = 0xc
+	SIGTERM                           = 0xf
+	SIGTHR                            = 0x20
+	SIGTRAP                           = 0x5
+	SIGTSTP                           = 0x12
+	SIGTTIN                           = 0x15
+	SIGTTOU                           = 0x16
+	SIGURG                            = 0x10
+	SIGUSR1                           = 0x1e
+	SIGUSR2                           = 0x1f
+	SIGVTALRM                         = 0x1a
+	SIGWINCH                          = 0x1c
+	SIGXCPU                           = 0x18
+	SIGXFSZ                           = 0x19
+	SIOCADDMULTI                      = 0x80206931
+	SIOCAIFADDR                       = 0x8040691a
+	SIOCAIFGROUP                      = 0x80246987
+	SIOCALIFADDR                      = 0x8218691c
+	SIOCATMARK                        = 0x40047307
+	SIOCBRDGADD                       = 0x8054693c
+	SIOCBRDGADDS                      = 0x80546941
+	SIOCBRDGARL                       = 0x806e694d
+	SIOCBRDGDADDR                     = 0x80286947
+	SIOCBRDGDEL                       = 0x8054693d
+	SIOCBRDGDELS                      = 0x80546942
+	SIOCBRDGFLUSH                     = 0x80546948
+	SIOCBRDGFRL                       = 0x806e694e
+	SIOCBRDGGCACHE                    = 0xc0146941
+	SIOCBRDGGFD                       = 0xc0146952
+	SIOCBRDGGHT                       = 0xc0146951
+	SIOCBRDGGIFFLGS                   = 0xc054693e
+	SIOCBRDGGMA                       = 0xc0146953
+	SIOCBRDGGPARAM                    = 0xc0386958
+	SIOCBRDGGPRI                      = 0xc0146950
+	SIOCBRDGGRL                       = 0xc028694f
+	SIOCBRDGGSIFS                     = 0xc054693c
+	SIOCBRDGGTO                       = 0xc0146946
+	SIOCBRDGIFS                       = 0xc0546942
+	SIOCBRDGRTS                       = 0xc0186943
+	SIOCBRDGSADDR                     = 0xc0286944
+	SIOCBRDGSCACHE                    = 0x80146940
+	SIOCBRDGSFD                       = 0x80146952
+	SIOCBRDGSHT                       = 0x80146951
+	SIOCBRDGSIFCOST                   = 0x80546955
+	SIOCBRDGSIFFLGS                   = 0x8054693f
+	SIOCBRDGSIFPRIO                   = 0x80546954
+	SIOCBRDGSMA                       = 0x80146953
+	SIOCBRDGSPRI                      = 0x80146950
+	SIOCBRDGSPROTO                    = 0x8014695a
+	SIOCBRDGSTO                       = 0x80146945
+	SIOCBRDGSTXHC                     = 0x80146959
+	SIOCDELMULTI                      = 0x80206932
+	SIOCDIFADDR                       = 0x80206919
+	SIOCDIFGROUP                      = 0x80246989
+	SIOCDIFPHYADDR                    = 0x80206949
+	SIOCDLIFADDR                      = 0x8218691e
+	SIOCGETKALIVE                     = 0xc01869a4
+	SIOCGETLABEL                      = 0x8020699a
+	SIOCGETPFLOW                      = 0xc02069fe
+	SIOCGETPFSYNC                     = 0xc02069f8
+	SIOCGETSGCNT                      = 0xc0147534
+	SIOCGETVIFCNT                     = 0xc0147533
+	SIOCGETVLANPRIO                   = 0xc0206990
+	SIOCGHIWAT                        = 0x40047301
+	SIOCGIFADDR                       = 0xc0206921
+	SIOCGIFASYNCMAP                   = 0xc020697c
+	SIOCGIFBRDADDR                    = 0xc0206923
+	SIOCGIFCONF                       = 0xc0086924
+	SIOCGIFDATA                       = 0xc020691b
+	SIOCGIFDESCR                      = 0xc0206981
+	SIOCGIFDSTADDR                    = 0xc0206922
+	SIOCGIFFLAGS                      = 0xc0206911
+	SIOCGIFGATTR                      = 0xc024698b
+	SIOCGIFGENERIC                    = 0xc020693a
+	SIOCGIFGMEMB                      = 0xc024698a
+	SIOCGIFGROUP                      = 0xc0246988
+	SIOCGIFMEDIA                      = 0xc0286936
+	SIOCGIFMETRIC                     = 0xc0206917
+	SIOCGIFMTU                        = 0xc020697e
+	SIOCGIFNETMASK                    = 0xc0206925
+	SIOCGIFPDSTADDR                   = 0xc0206948
+	SIOCGIFPRIORITY                   = 0xc020699c
+	SIOCGIFPSRCADDR                   = 0xc0206947
+	SIOCGIFRDOMAIN                    = 0xc02069a0
+	SIOCGIFRTLABEL                    = 0xc0206983
+	SIOCGIFTIMESLOT                   = 0xc0206986
+	SIOCGIFXFLAGS                     = 0xc020699e
+	SIOCGLIFADDR                      = 0xc218691d
+	SIOCGLIFPHYADDR                   = 0xc218694b
+	SIOCGLIFPHYRTABLE                 = 0xc02069a2
+	SIOCGLOWAT                        = 0x40047303
+	SIOCGPGRP                         = 0x40047309
+	SIOCGVH                           = 0xc02069f6
+	SIOCIFCREATE                      = 0x8020697a
+	SIOCIFDESTROY                     = 0x80206979
+	SIOCIFGCLONERS                    = 0xc00c6978
+	SIOCSETKALIVE                     = 0x801869a3
+	SIOCSETLABEL                      = 0x80206999
+	SIOCSETPFLOW                      = 0x802069fd
+	SIOCSETPFSYNC                     = 0x802069f7
+	SIOCSETVLANPRIO                   = 0x8020698f
+	SIOCSHIWAT                        = 0x80047300
+	SIOCSIFADDR                       = 0x8020690c
+	SIOCSIFASYNCMAP                   = 0x8020697d
+	SIOCSIFBRDADDR                    = 0x80206913
+	SIOCSIFDESCR                      = 0x80206980
+	SIOCSIFDSTADDR                    = 0x8020690e
+	SIOCSIFFLAGS                      = 0x80206910
+	SIOCSIFGATTR                      = 0x8024698c
+	SIOCSIFGENERIC                    = 0x80206939
+	SIOCSIFLLADDR                     = 0x8020691f
+	SIOCSIFMEDIA                      = 0xc0206935
+	SIOCSIFMETRIC                     = 0x80206918
+	SIOCSIFMTU                        = 0x8020697f
+	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFPHYADDR                    = 0x80406946
+	SIOCSIFPRIORITY                   = 0x8020699b
+	SIOCSIFRDOMAIN                    = 0x8020699f
+	SIOCSIFRTLABEL                    = 0x80206982
+	SIOCSIFTIMESLOT                   = 0x80206985
+	SIOCSIFXFLAGS                     = 0x8020699d
+	SIOCSLIFPHYADDR                   = 0x8218694a
+	SIOCSLIFPHYRTABLE                 = 0x802069a1
+	SIOCSLOWAT                        = 0x80047302
+	SIOCSPGRP                         = 0x80047308
+	SIOCSVH                           = 0xc02069f5
+	SOCK_DGRAM                        = 0x2
+	SOCK_RAW                          = 0x3
+	SOCK_RDM                          = 0x4
+	SOCK_SEQPACKET                    = 0x5
+	SOCK_STREAM                       = 0x1
+	SOL_SOCKET                        = 0xffff
+	SOMAXCONN                         = 0x80
+	SO_ACCEPTCONN                     = 0x2
+	SO_BINDANY                        = 0x1000
+	SO_BROADCAST                      = 0x20
+	SO_DEBUG                          = 0x1
+	SO_DONTROUTE                      = 0x10
+	SO_ERROR                          = 0x1007
+	SO_JUMBO                          = 0x400
+	SO_KEEPALIVE                      = 0x8
+	SO_LINGER                         = 0x80
+	SO_NETPROC                        = 0x1020
+	SO_OOBINLINE                      = 0x100
+	SO_PEERCRED                       = 0x1022
+	SO_RCVBUF                         = 0x1002
+	SO_RCVLOWAT                       = 0x1004
+	SO_RCVTIMEO                       = 0x1006
+	SO_REUSEADDR                      = 0x4
+	SO_REUSEPORT                      = 0x200
+	SO_RTABLE                         = 0x1021
+	SO_SNDBUF                         = 0x1001
+	SO_SNDLOWAT                       = 0x1003
+	SO_SNDTIMEO                       = 0x1005
+	SO_SPLICE                         = 0x1023
+	SO_TIMESTAMP                      = 0x800
+	SO_TYPE                           = 0x1008
+	SO_USELOOPBACK                    = 0x40
+	TCP_MAXBURST                      = 0x4
+	TCP_MAXSEG                        = 0x2
+	TCP_MAXWIN                        = 0xffff
+	TCP_MAX_SACK                      = 0x3
+	TCP_MAX_WINSHIFT                  = 0xe
+	TCP_MD5SIG                        = 0x4
+	TCP_MSS                           = 0x200
+	TCP_NODELAY                       = 0x1
+	TCP_NSTATES                       = 0xb
+	TCP_SACK_ENABLE                   = 0x8
+	TIOCCBRK                          = 0x2000747a
+	TIOCCDTR                          = 0x20007478
+	TIOCCONS                          = 0x80047462
+	TIOCDRAIN                         = 0x2000745e
+	TIOCEXCL                          = 0x2000740d
+	TIOCEXT                           = 0x80047460
+	TIOCFLAG_CLOCAL                   = 0x2
+	TIOCFLAG_CRTSCTS                  = 0x4
+	TIOCFLAG_MDMBUF                   = 0x8
+	TIOCFLAG_PPS                      = 0x10
+	TIOCFLAG_SOFTCAR                  = 0x1
+	TIOCFLUSH                         = 0x80047410
+	TIOCGETA                          = 0x402c7413
+	TIOCGETD                          = 0x4004741a
+	TIOCGFLAGS                        = 0x4004745d
+	TIOCGPGRP                         = 0x40047477
+	TIOCGTSTAMP                       = 0x4008745b
+	TIOCGWINSZ                        = 0x40087468
+	TIOCMBIC                          = 0x8004746b
+	TIOCMBIS                          = 0x8004746c
+	TIOCMGET                          = 0x4004746a
+	TIOCMODG                          = 0x4004746a
+	TIOCMODS                          = 0x8004746d
+	TIOCMSET                          = 0x8004746d
+	TIOCM_CAR                         = 0x40
+	TIOCM_CD                          = 0x40
+	TIOCM_CTS                         = 0x20
+	TIOCM_DSR                         = 0x100
+	TIOCM_DTR                         = 0x2
+	TIOCM_LE                          = 0x1
+	TIOCM_RI                          = 0x80
+	TIOCM_RNG                         = 0x80
+	TIOCM_RTS                         = 0x4
+	TIOCM_SR                          = 0x10
+	TIOCM_ST                          = 0x8
+	TIOCNOTTY                         = 0x20007471
+	TIOCNXCL                          = 0x2000740e
+	TIOCOUTQ                          = 0x40047473
+	TIOCPKT                           = 0x80047470
+	TIOCPKT_DATA                      = 0x0
+	TIOCPKT_DOSTOP                    = 0x20
+	TIOCPKT_FLUSHREAD                 = 0x1
+	TIOCPKT_FLUSHWRITE                = 0x2
+	TIOCPKT_IOCTL                     = 0x40
+	TIOCPKT_NOSTOP                    = 0x10
+	TIOCPKT_START                     = 0x8
+	TIOCPKT_STOP                      = 0x4
+	TIOCREMOTE                        = 0x80047469
+	TIOCSBRK                          = 0x2000747b
+	TIOCSCTTY                         = 0x20007461
+	TIOCSDTR                          = 0x20007479
+	TIOCSETA                          = 0x802c7414
+	TIOCSETAF                         = 0x802c7416
+	TIOCSETAW                         = 0x802c7415
+	TIOCSETD                          = 0x8004741b
+	TIOCSFLAGS                        = 0x8004745c
+	TIOCSIG                           = 0x8004745f
+	TIOCSPGRP                         = 0x80047476
+	TIOCSTART                         = 0x2000746e
+	TIOCSTAT                          = 0x80047465
+	TIOCSTI                           = 0x80017472
+	TIOCSTOP                          = 0x2000746f
+	TIOCSTSTAMP                       = 0x8008745a
+	TIOCSWINSZ                        = 0x80087467
+	TIOCUCNTL                         = 0x80047466
+	WALTSIG                           = 0x4
+	WCONTINUED                        = 0x8
+	WCOREFLAG                         = 0x80
+	WNOHANG                           = 0x1
+	WSTOPPED                          = 0x7f
+	WUNTRACED                         = 0x2
+)
+
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADF           = Errno(0x9)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x58)
+	ECHILD          = Errno(0xa)
+	ECHO            = Errno(0x8)
+	ECHOCTL         = Errno(0x40)
+	ECHOE           = Errno(0x2)
+	ECHOK           = Errno(0x4)
+	ECHOKE          = Errno(0x1)
+	ECHONL          = Errno(0x10)
+	ECHOPRT         = Errno(0x20)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDOM            = Errno(0x21)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x59)
+	EILSEQ          = Errno(0x54)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EIPSEC          = Errno(0x52)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x5b)
+	ELOOP           = Errno(0x3e)
+	EMEDIUMTYPE     = Errno(0x56)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENDRUNDISC      = Errno(0x9)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x53)
+	ENOBUFS         = Errno(0x37)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOMEDIUM       = Errno(0x55)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x5a)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x5b)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x2d)
+	EOVERFLOW       = Errno(0x57)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
+
+// Error table
+var errors = [...]string{
+	1:  "operation not permitted",
+	2:  "no such file or directory",
+	3:  "no such process",
+	4:  "interrupted system call",
+	5:  "input/output error",
+	6:  "device not configured",
+	7:  "argument list too long",
+	8:  "exec format error",
+	9:  "bad file descriptor",
+	10: "no child processes",
+	11: "resource deadlock avoided",
+	12: "cannot allocate memory",
+	13: "permission denied",
+	14: "bad address",
+	15: "block device required",
+	16: "device busy",
+	17: "file exists",
+	18: "cross-device link",
+	19: "operation not supported by device",
+	20: "not a directory",
+	21: "is a directory",
+	22: "invalid argument",
+	23: "too many open files in system",
+	24: "too many open files",
+	25: "inappropriate ioctl for device",
+	26: "text file busy",
+	27: "file too large",
+	28: "no space left on device",
+	29: "illegal seek",
+	30: "read-only file system",
+	31: "too many links",
+	32: "broken pipe",
+	33: "numerical argument out of domain",
+	34: "result too large",
+	35: "resource temporarily unavailable",
+	36: "operation now in progress",
+	37: "operation already in progress",
+	38: "socket operation on non-socket",
+	39: "destination address required",
+	40: "message too long",
+	41: "protocol wrong type for socket",
+	42: "protocol not available",
+	43: "protocol not supported",
+	44: "socket type not supported",
+	45: "operation not supported",
+	46: "protocol family not supported",
+	47: "address family not supported by protocol family",
+	48: "address already in use",
+	49: "can't assign requested address",
+	50: "network is down",
+	51: "network is unreachable",
+	52: "network dropped connection on reset",
+	53: "software caused connection abort",
+	54: "connection reset by peer",
+	55: "no buffer space available",
+	56: "socket is already connected",
+	57: "socket is not connected",
+	58: "can't send after socket shutdown",
+	59: "too many references: can't splice",
+	60: "connection timed out",
+	61: "connection refused",
+	62: "too many levels of symbolic links",
+	63: "file name too long",
+	64: "host is down",
+	65: "no route to host",
+	66: "directory not empty",
+	67: "too many processes",
+	68: "too many users",
+	69: "disc quota exceeded",
+	70: "stale NFS file handle",
+	71: "too many levels of remote in path",
+	72: "RPC struct is bad",
+	73: "RPC version wrong",
+	74: "RPC prog. not avail",
+	75: "program version wrong",
+	76: "bad procedure for program",
+	77: "no locks available",
+	78: "function not implemented",
+	79: "inappropriate file type or format",
+	80: "authentication error",
+	81: "need authenticator",
+	82: "IPsec processing failure",
+	83: "attribute not found",
+	84: "illegal byte sequence",
+	85: "no medium found",
+	86: "wrong medium type",
+	87: "value too large to be stored in data type",
+	88: "operation canceled",
+	89: "identifier removed",
+	90: "no message of desired type",
+	91: "not supported",
+}
diff --git a/src/pkg/syscall/zerrors_netbsd_amd64.go b/src/pkg/syscall/zerrors_netbsd_amd64.go
new file mode 100644
index 0000000..c6367fb
--- /dev/null
+++ b/src/pkg/syscall/zerrors_netbsd_amd64.go
@@ -0,0 +1,1368 @@
+// mkerrors.sh -m64
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m64 _const.go
+
+package syscall
+
+const (
+	AF_APPLETALK                      = 0x10
+	AF_BLUETOOTH                      = 0x20
+	AF_CCITT                          = 0xa
+	AF_CHAOS                          = 0x5
+	AF_CNT                            = 0x15
+	AF_COIP                           = 0x14
+	AF_DATAKIT                        = 0x9
+	AF_DECnet                         = 0xc
+	AF_DLI                            = 0xd
+	AF_E164                           = 0x1a
+	AF_ECMA                           = 0x8
+	AF_ENCAP                          = 0x1c
+	AF_HYLINK                         = 0xf
+	AF_IMPLINK                        = 0x3
+	AF_INET                           = 0x2
+	AF_INET6                          = 0x18
+	AF_IPX                            = 0x17
+	AF_ISDN                           = 0x1a
+	AF_ISO                            = 0x7
+	AF_KEY                            = 0x1e
+	AF_LAT                            = 0xe
+	AF_LINK                           = 0x12
+	AF_LOCAL                          = 0x1
+	AF_MAX                            = 0x24
+	AF_MPLS                           = 0x21
+	AF_NATM                           = 0x1b
+	AF_NS                             = 0x6
+	AF_OSI                            = 0x7
+	AF_PUP                            = 0x4
+	AF_ROUTE                          = 0x11
+	AF_SIP                            = 0x1d
+	AF_SNA                            = 0xb
+	AF_UNIX                           = 0x1
+	AF_UNSPEC                         = 0x0
+	ARPHRD_ETHER                      = 0x1
+	ARPHRD_FRELAY                     = 0xf
+	ARPHRD_IEEE1394                   = 0x18
+	ARPHRD_IEEE802                    = 0x6
+	BIOCFLUSH                         = 0x20004268
+	BIOCGBLEN                         = 0x40044266
+	BIOCGDIRFILT                      = 0x4004427c
+	BIOCGDLT                          = 0x4004426a
+	BIOCGDLTLIST                      = 0xc010427b
+	BIOCGETIF                         = 0x4020426b
+	BIOCGFILDROP                      = 0x40044278
+	BIOCGHDRCMPLT                     = 0x40044274
+	BIOCGRSIG                         = 0x40044273
+	BIOCGRTIMEOUT                     = 0x4010426e
+	BIOCGSTATS                        = 0x4008426f
+	BIOCIMMEDIATE                     = 0x80044270
+	BIOCLOCK                          = 0x20004276
+	BIOCPROMISC                       = 0x20004269
+	BIOCSBLEN                         = 0xc0044266
+	BIOCSDIRFILT                      = 0x8004427d
+	BIOCSDLT                          = 0x8004427a
+	BIOCSETF                          = 0x80104267
+	BIOCSETIF                         = 0x8020426c
+	BIOCSETWF                         = 0x80104277
+	BIOCSFILDROP                      = 0x80044279
+	BIOCSHDRCMPLT                     = 0x80044275
+	BIOCSRSIG                         = 0x80044272
+	BIOCSRTIMEOUT                     = 0x8010426d
+	BIOCVERSION                       = 0x40044271
+	BPF_A                             = 0x10
+	BPF_ABS                           = 0x20
+	BPF_ADD                           = 0x0
+	BPF_ALIGNMENT                     = 0x4
+	BPF_ALU                           = 0x4
+	BPF_AND                           = 0x50
+	BPF_B                             = 0x10
+	BPF_DIRECTION_IN                  = 0x1
+	BPF_DIRECTION_OUT                 = 0x2
+	BPF_DIV                           = 0x30
+	BPF_H                             = 0x8
+	BPF_IMM                           = 0x0
+	BPF_IND                           = 0x40
+	BPF_JA                            = 0x0
+	BPF_JEQ                           = 0x10
+	BPF_JGE                           = 0x30
+	BPF_JGT                           = 0x20
+	BPF_JMP                           = 0x5
+	BPF_JSET                          = 0x40
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
+	BPF_LDX                           = 0x1
+	BPF_LEN                           = 0x80
+	BPF_LSH                           = 0x60
+	BPF_MAJOR_VERSION                 = 0x1
+	BPF_MAXBUFSIZE                    = 0x200000
+	BPF_MAXINSNS                      = 0x200
+	BPF_MEM                           = 0x60
+	BPF_MEMWORDS                      = 0x10
+	BPF_MINBUFSIZE                    = 0x20
+	BPF_MINOR_VERSION                 = 0x1
+	BPF_MISC                          = 0x7
+	BPF_MSH                           = 0xa0
+	BPF_MUL                           = 0x20
+	BPF_NEG                           = 0x80
+	BPF_OR                            = 0x40
+	BPF_RELEASE                       = 0x30bb6
+	BPF_RET                           = 0x6
+	BPF_RSH                           = 0x70
+	BPF_ST                            = 0x2
+	BPF_STX                           = 0x3
+	BPF_SUB                           = 0x10
+	BPF_TAX                           = 0x0
+	BPF_TXA                           = 0x80
+	BPF_W                             = 0x0
+	BPF_X                             = 0x8
+	CTL_MAXNAME                       = 0xc
+	CTL_NET                           = 0x4
+	DLT_ARCNET                        = 0x7
+	DLT_ATM_RFC1483                   = 0xb
+	DLT_AX25                          = 0x3
+	DLT_CHAOS                         = 0x5
+	DLT_EN10MB                        = 0x1
+	DLT_EN3MB                         = 0x2
+	DLT_ENC                           = 0xd
+	DLT_FDDI                          = 0xa
+	DLT_IEEE802                       = 0x6
+	DLT_IEEE802_11                    = 0x69
+	DLT_IEEE802_11_RADIO              = 0x7f
+	DLT_LOOP                          = 0xc
+	DLT_MPLS                          = 0xdb
+	DLT_NULL                          = 0x0
+	DLT_PFLOG                         = 0x75
+	DLT_PFSYNC                        = 0x12
+	DLT_PPP                           = 0x9
+	DLT_PPP_BSDOS                     = 0x10
+	DLT_PPP_ETHER                     = 0x33
+	DLT_PRONET                        = 0x4
+	DLT_RAW                           = 0xe
+	DLT_SLIP                          = 0x8
+	DLT_SLIP_BSDOS                    = 0xf
+	DT_BLK                            = 0x6
+	DT_CHR                            = 0x2
+	DT_DIR                            = 0x4
+	DT_FIFO                           = 0x1
+	DT_LNK                            = 0xa
+	DT_REG                            = 0x8
+	DT_SOCK                           = 0xc
+	DT_UNKNOWN                        = 0x0
+	EFER_LMA                          = 0x400
+	EFER_LME                          = 0x100
+	EFER_NXE                          = 0x800
+	EFER_SCE                          = 0x1
+	EMT_TAGOVF                        = 0x1
+	EMUL_ENABLED                      = 0x1
+	EMUL_NATIVE                       = 0x2
+	ETHERMIN                          = 0x2e
+	ETHERMTU                          = 0x5dc
+	ETHERTYPE_8023                    = 0x4
+	ETHERTYPE_AARP                    = 0x80f3
+	ETHERTYPE_ACCTON                  = 0x8390
+	ETHERTYPE_AEONIC                  = 0x8036
+	ETHERTYPE_ALPHA                   = 0x814a
+	ETHERTYPE_AMBER                   = 0x6008
+	ETHERTYPE_AMOEBA                  = 0x8145
+	ETHERTYPE_AOE                     = 0x88a2
+	ETHERTYPE_APOLLO                  = 0x80f7
+	ETHERTYPE_APOLLODOMAIN            = 0x8019
+	ETHERTYPE_APPLETALK               = 0x809b
+	ETHERTYPE_APPLITEK                = 0x80c7
+	ETHERTYPE_ARGONAUT                = 0x803a
+	ETHERTYPE_ARP                     = 0x806
+	ETHERTYPE_AT                      = 0x809b
+	ETHERTYPE_ATALK                   = 0x809b
+	ETHERTYPE_ATOMIC                  = 0x86df
+	ETHERTYPE_ATT                     = 0x8069
+	ETHERTYPE_ATTSTANFORD             = 0x8008
+	ETHERTYPE_AUTOPHON                = 0x806a
+	ETHERTYPE_AXIS                    = 0x8856
+	ETHERTYPE_BCLOOP                  = 0x9003
+	ETHERTYPE_BOFL                    = 0x8102
+	ETHERTYPE_CABLETRON               = 0x7034
+	ETHERTYPE_CHAOS                   = 0x804
+	ETHERTYPE_COMDESIGN               = 0x806c
+	ETHERTYPE_COMPUGRAPHIC            = 0x806d
+	ETHERTYPE_COUNTERPOINT            = 0x8062
+	ETHERTYPE_CRONUS                  = 0x8004
+	ETHERTYPE_CRONUSVLN               = 0x8003
+	ETHERTYPE_DCA                     = 0x1234
+	ETHERTYPE_DDE                     = 0x807b
+	ETHERTYPE_DEBNI                   = 0xaaaa
+	ETHERTYPE_DECAM                   = 0x8048
+	ETHERTYPE_DECCUST                 = 0x6006
+	ETHERTYPE_DECDIAG                 = 0x6005
+	ETHERTYPE_DECDNS                  = 0x803c
+	ETHERTYPE_DECDTS                  = 0x803e
+	ETHERTYPE_DECEXPER                = 0x6000
+	ETHERTYPE_DECLAST                 = 0x8041
+	ETHERTYPE_DECLTM                  = 0x803f
+	ETHERTYPE_DECMUMPS                = 0x6009
+	ETHERTYPE_DECNETBIOS              = 0x8040
+	ETHERTYPE_DELTACON                = 0x86de
+	ETHERTYPE_DIDDLE                  = 0x4321
+	ETHERTYPE_DLOG1                   = 0x660
+	ETHERTYPE_DLOG2                   = 0x661
+	ETHERTYPE_DN                      = 0x6003
+	ETHERTYPE_DOGFIGHT                = 0x1989
+	ETHERTYPE_DSMD                    = 0x8039
+	ETHERTYPE_ECMA                    = 0x803
+	ETHERTYPE_ENCRYPT                 = 0x803d
+	ETHERTYPE_ES                      = 0x805d
+	ETHERTYPE_EXCELAN                 = 0x8010
+	ETHERTYPE_EXPERDATA               = 0x8049
+	ETHERTYPE_FLIP                    = 0x8146
+	ETHERTYPE_FLOWCONTROL             = 0x8808
+	ETHERTYPE_FRARP                   = 0x808
+	ETHERTYPE_GENDYN                  = 0x8068
+	ETHERTYPE_HAYES                   = 0x8130
+	ETHERTYPE_HIPPI_FP                = 0x8180
+	ETHERTYPE_HITACHI                 = 0x8820
+	ETHERTYPE_HP                      = 0x8005
+	ETHERTYPE_IEEEPUP                 = 0xa00
+	ETHERTYPE_IEEEPUPAT               = 0xa01
+	ETHERTYPE_IMLBL                   = 0x4c42
+	ETHERTYPE_IMLBLDIAG               = 0x424c
+	ETHERTYPE_IP                      = 0x800
+	ETHERTYPE_IPAS                    = 0x876c
+	ETHERTYPE_IPV6                    = 0x86dd
+	ETHERTYPE_IPX                     = 0x8137
+	ETHERTYPE_IPXNEW                  = 0x8037
+	ETHERTYPE_KALPANA                 = 0x8582
+	ETHERTYPE_LANBRIDGE               = 0x8038
+	ETHERTYPE_LANPROBE                = 0x8888
+	ETHERTYPE_LAT                     = 0x6004
+	ETHERTYPE_LBACK                   = 0x9000
+	ETHERTYPE_LITTLE                  = 0x8060
+	ETHERTYPE_LLDP                    = 0x88cc
+	ETHERTYPE_LOGICRAFT               = 0x8148
+	ETHERTYPE_LOOPBACK                = 0x9000
+	ETHERTYPE_MATRA                   = 0x807a
+	ETHERTYPE_MAX                     = 0xffff
+	ETHERTYPE_MERIT                   = 0x807c
+	ETHERTYPE_MICP                    = 0x873a
+	ETHERTYPE_MOPDL                   = 0x6001
+	ETHERTYPE_MOPRC                   = 0x6002
+	ETHERTYPE_MOTOROLA                = 0x818d
+	ETHERTYPE_MPLS                    = 0x8847
+	ETHERTYPE_MPLS_MCAST              = 0x8848
+	ETHERTYPE_MUMPS                   = 0x813f
+	ETHERTYPE_NBPCC                   = 0x3c04
+	ETHERTYPE_NBPCLAIM                = 0x3c09
+	ETHERTYPE_NBPCLREQ                = 0x3c05
+	ETHERTYPE_NBPCLRSP                = 0x3c06
+	ETHERTYPE_NBPCREQ                 = 0x3c02
+	ETHERTYPE_NBPCRSP                 = 0x3c03
+	ETHERTYPE_NBPDG                   = 0x3c07
+	ETHERTYPE_NBPDGB                  = 0x3c08
+	ETHERTYPE_NBPDLTE                 = 0x3c0a
+	ETHERTYPE_NBPRAR                  = 0x3c0c
+	ETHERTYPE_NBPRAS                  = 0x3c0b
+	ETHERTYPE_NBPRST                  = 0x3c0d
+	ETHERTYPE_NBPSCD                  = 0x3c01
+	ETHERTYPE_NBPVCD                  = 0x3c00
+	ETHERTYPE_NBS                     = 0x802
+	ETHERTYPE_NCD                     = 0x8149
+	ETHERTYPE_NESTAR                  = 0x8006
+	ETHERTYPE_NETBEUI                 = 0x8191
+	ETHERTYPE_NOVELL                  = 0x8138
+	ETHERTYPE_NS                      = 0x600
+	ETHERTYPE_NSAT                    = 0x601
+	ETHERTYPE_NSCOMPAT                = 0x807
+	ETHERTYPE_NTRAILER                = 0x10
+	ETHERTYPE_OS9                     = 0x7007
+	ETHERTYPE_OS9NET                  = 0x7009
+	ETHERTYPE_PACER                   = 0x80c6
+	ETHERTYPE_PAE                     = 0x888e
+	ETHERTYPE_PCS                     = 0x4242
+	ETHERTYPE_PLANNING                = 0x8044
+	ETHERTYPE_PPP                     = 0x880b
+	ETHERTYPE_PPPOE                   = 0x8864
+	ETHERTYPE_PPPOEDISC               = 0x8863
+	ETHERTYPE_PRIMENTS                = 0x7031
+	ETHERTYPE_PUP                     = 0x200
+	ETHERTYPE_PUPAT                   = 0x200
+	ETHERTYPE_QINQ                    = 0x88a8
+	ETHERTYPE_RACAL                   = 0x7030
+	ETHERTYPE_RATIONAL                = 0x8150
+	ETHERTYPE_RAWFR                   = 0x6559
+	ETHERTYPE_RCL                     = 0x1995
+	ETHERTYPE_RDP                     = 0x8739
+	ETHERTYPE_RETIX                   = 0x80f2
+	ETHERTYPE_REVARP                  = 0x8035
+	ETHERTYPE_SCA                     = 0x6007
+	ETHERTYPE_SECTRA                  = 0x86db
+	ETHERTYPE_SECUREDATA              = 0x876d
+	ETHERTYPE_SGITW                   = 0x817e
+	ETHERTYPE_SG_BOUNCE               = 0x8016
+	ETHERTYPE_SG_DIAG                 = 0x8013
+	ETHERTYPE_SG_NETGAMES             = 0x8014
+	ETHERTYPE_SG_RESV                 = 0x8015
+	ETHERTYPE_SIMNET                  = 0x5208
+	ETHERTYPE_SLOW                    = 0x8809
+	ETHERTYPE_SNA                     = 0x80d5
+	ETHERTYPE_SNMP                    = 0x814c
+	ETHERTYPE_SONIX                   = 0xfaf5
+	ETHERTYPE_SPIDER                  = 0x809f
+	ETHERTYPE_SPRITE                  = 0x500
+	ETHERTYPE_STP                     = 0x8181
+	ETHERTYPE_TALARIS                 = 0x812b
+	ETHERTYPE_TALARISMC               = 0x852b
+	ETHERTYPE_TCPCOMP                 = 0x876b
+	ETHERTYPE_TCPSM                   = 0x9002
+	ETHERTYPE_TEC                     = 0x814f
+	ETHERTYPE_TIGAN                   = 0x802f
+	ETHERTYPE_TRAIL                   = 0x1000
+	ETHERTYPE_TRANSETHER              = 0x6558
+	ETHERTYPE_TYMSHARE                = 0x802e
+	ETHERTYPE_UBBST                   = 0x7005
+	ETHERTYPE_UBDEBUG                 = 0x900
+	ETHERTYPE_UBDIAGLOOP              = 0x7002
+	ETHERTYPE_UBDL                    = 0x7000
+	ETHERTYPE_UBNIU                   = 0x7001
+	ETHERTYPE_UBNMC                   = 0x7003
+	ETHERTYPE_VALID                   = 0x1600
+	ETHERTYPE_VARIAN                  = 0x80dd
+	ETHERTYPE_VAXELN                  = 0x803b
+	ETHERTYPE_VEECO                   = 0x8067
+	ETHERTYPE_VEXP                    = 0x805b
+	ETHERTYPE_VGLAB                   = 0x8131
+	ETHERTYPE_VINES                   = 0xbad
+	ETHERTYPE_VINESECHO               = 0xbaf
+	ETHERTYPE_VINESLOOP               = 0xbae
+	ETHERTYPE_VITAL                   = 0xff00
+	ETHERTYPE_VLAN                    = 0x8100
+	ETHERTYPE_VLTLMAN                 = 0x8080
+	ETHERTYPE_VPROD                   = 0x805c
+	ETHERTYPE_VURESERVED              = 0x8147
+	ETHERTYPE_WATERLOO                = 0x8130
+	ETHERTYPE_WELLFLEET               = 0x8103
+	ETHERTYPE_X25                     = 0x805
+	ETHERTYPE_X75                     = 0x801
+	ETHERTYPE_XNSSM                   = 0x9001
+	ETHERTYPE_XTP                     = 0x817d
+	ETHER_ADDR_LEN                    = 0x6
+	ETHER_ALIGN                       = 0x2
+	ETHER_CRC_LEN                     = 0x4
+	ETHER_CRC_POLY_BE                 = 0x4c11db6
+	ETHER_CRC_POLY_LE                 = 0xedb88320
+	ETHER_HDR_LEN                     = 0xe
+	ETHER_MAX_DIX_LEN                 = 0x600
+	ETHER_MAX_LEN                     = 0x5ee
+	ETHER_MIN_LEN                     = 0x40
+	ETHER_TYPE_LEN                    = 0x2
+	ETHER_VLAN_ENCAP_LEN              = 0x4
+	EVFILT_AIO                        = -0x3
+	EVFILT_PROC                       = -0x5
+	EVFILT_READ                       = -0x1
+	EVFILT_SIGNAL                     = -0x6
+	EVFILT_SYSCOUNT                   = 0x7
+	EVFILT_TIMER                      = -0x7
+	EVFILT_VNODE                      = -0x4
+	EVFILT_WRITE                      = -0x2
+	EV_ADD                            = 0x1
+	EV_CLEAR                          = 0x20
+	EV_DELETE                         = 0x2
+	EV_DISABLE                        = 0x8
+	EV_ENABLE                         = 0x4
+	EV_EOF                            = 0x8000
+	EV_ERROR                          = 0x4000
+	EV_FLAG1                          = 0x2000
+	EV_ONESHOT                        = 0x10
+	EV_SYSFLAGS                       = 0xf000
+	EXTA                              = 0x4b00
+	EXTB                              = 0x9600
+	EXTPROC                           = 0x800
+	FD_CLOEXEC                        = 0x1
+	FD_SETSIZE                        = 0x400
+	F_DUPFD                           = 0x0
+	F_DUPFD_CLOEXEC                   = 0xa
+	F_GETFD                           = 0x1
+	F_GETFL                           = 0x3
+	F_GETLK                           = 0x7
+	F_GETOWN                          = 0x5
+	F_RDLCK                           = 0x1
+	F_SETFD                           = 0x2
+	F_SETFL                           = 0x4
+	F_SETLK                           = 0x8
+	F_SETLKW                          = 0x9
+	F_SETOWN                          = 0x6
+	F_UNLCK                           = 0x2
+	F_WRLCK                           = 0x3
+	IFA_ROUTE                         = 0x1
+	IFF_ALLMULTI                      = 0x200
+	IFF_BROADCAST                     = 0x2
+	IFF_CANTCHANGE                    = 0x8e52
+	IFF_DEBUG                         = 0x4
+	IFF_LINK0                         = 0x1000
+	IFF_LINK1                         = 0x2000
+	IFF_LINK2                         = 0x4000
+	IFF_LOOPBACK                      = 0x8
+	IFF_MULTICAST                     = 0x8000
+	IFF_NOARP                         = 0x80
+	IFF_NOTRAILERS                    = 0x20
+	IFF_OACTIVE                       = 0x400
+	IFF_POINTOPOINT                   = 0x10
+	IFF_PROMISC                       = 0x100
+	IFF_RUNNING                       = 0x40
+	IFF_SIMPLEX                       = 0x800
+	IFF_UP                            = 0x1
+	IFNAMSIZ                          = 0x10
+	IFT_1822                          = 0x2
+	IFT_A12MPPSWITCH                  = 0x82
+	IFT_AAL2                          = 0xbb
+	IFT_AAL5                          = 0x31
+	IFT_ADSL                          = 0x5e
+	IFT_AFLANE8023                    = 0x3b
+	IFT_AFLANE8025                    = 0x3c
+	IFT_ARAP                          = 0x58
+	IFT_ARCNET                        = 0x23
+	IFT_ARCNETPLUS                    = 0x24
+	IFT_ASYNC                         = 0x54
+	IFT_ATM                           = 0x25
+	IFT_ATMDXI                        = 0x69
+	IFT_ATMFUNI                       = 0x6a
+	IFT_ATMIMA                        = 0x6b
+	IFT_ATMLOGICAL                    = 0x50
+	IFT_ATMRADIO                      = 0xbd
+	IFT_ATMSUBINTERFACE               = 0x86
+	IFT_ATMVCIENDPT                   = 0xc2
+	IFT_ATMVIRTUAL                    = 0x95
+	IFT_BGPPOLICYACCOUNTING           = 0xa2
+	IFT_BLUETOOTH                     = 0xf8
+	IFT_BRIDGE                        = 0xd1
+	IFT_BSC                           = 0x53
+	IFT_CARP                          = 0xf7
+	IFT_CCTEMUL                       = 0x3d
+	IFT_CEPT                          = 0x13
+	IFT_CES                           = 0x85
+	IFT_CHANNEL                       = 0x46
+	IFT_CNR                           = 0x55
+	IFT_COFFEE                        = 0x84
+	IFT_COMPOSITELINK                 = 0x9b
+	IFT_DCN                           = 0x8d
+	IFT_DIGITALPOWERLINE              = 0x8a
+	IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba
+	IFT_DLSW                          = 0x4a
+	IFT_DOCSCABLEDOWNSTREAM           = 0x80
+	IFT_DOCSCABLEMACLAYER             = 0x7f
+	IFT_DOCSCABLEUPSTREAM             = 0x81
+	IFT_DOCSCABLEUPSTREAMCHANNEL      = 0xcd
+	IFT_DS0                           = 0x51
+	IFT_DS0BUNDLE                     = 0x52
+	IFT_DS1FDL                        = 0xaa
+	IFT_DS3                           = 0x1e
+	IFT_DTM                           = 0x8c
+	IFT_DUMMY                         = 0xf1
+	IFT_DVBASILN                      = 0xac
+	IFT_DVBASIOUT                     = 0xad
+	IFT_DVBRCCDOWNSTREAM              = 0x93
+	IFT_DVBRCCMACLAYER                = 0x92
+	IFT_DVBRCCUPSTREAM                = 0x94
+	IFT_ECONET                        = 0xce
+	IFT_ENC                           = 0xf4
+	IFT_EON                           = 0x19
+	IFT_EPLRS                         = 0x57
+	IFT_ESCON                         = 0x49
+	IFT_ETHER                         = 0x6
+	IFT_FAITH                         = 0xf3
+	IFT_FAST                          = 0x7d
+	IFT_FASTETHER                     = 0x3e
+	IFT_FASTETHERFX                   = 0x45
+	IFT_FDDI                          = 0xf
+	IFT_FIBRECHANNEL                  = 0x38
+	IFT_FRAMERELAYINTERCONNECT        = 0x3a
+	IFT_FRAMERELAYMPI                 = 0x5c
+	IFT_FRDLCIENDPT                   = 0xc1
+	IFT_FRELAY                        = 0x20
+	IFT_FRELAYDCE                     = 0x2c
+	IFT_FRF16MFRBUNDLE                = 0xa3
+	IFT_FRFORWARD                     = 0x9e
+	IFT_G703AT2MB                     = 0x43
+	IFT_G703AT64K                     = 0x42
+	IFT_GIF                           = 0xf0
+	IFT_GIGABITETHERNET               = 0x75
+	IFT_GR303IDT                      = 0xb2
+	IFT_GR303RDT                      = 0xb1
+	IFT_H323GATEKEEPER                = 0xa4
+	IFT_H323PROXY                     = 0xa5
+	IFT_HDH1822                       = 0x3
+	IFT_HDLC                          = 0x76
+	IFT_HDSL2                         = 0xa8
+	IFT_HIPERLAN2                     = 0xb7
+	IFT_HIPPI                         = 0x2f
+	IFT_HIPPIINTERFACE                = 0x39
+	IFT_HOSTPAD                       = 0x5a
+	IFT_HSSI                          = 0x2e
+	IFT_HY                            = 0xe
+	IFT_IBM370PARCHAN                 = 0x48
+	IFT_IDSL                          = 0x9a
+	IFT_IEEE1394                      = 0x90
+	IFT_IEEE80211                     = 0x47
+	IFT_IEEE80212                     = 0x37
+	IFT_IEEE8023ADLAG                 = 0xa1
+	IFT_IFGSN                         = 0x91
+	IFT_IMT                           = 0xbe
+	IFT_INFINIBAND                    = 0xc7
+	IFT_INTERLEAVE                    = 0x7c
+	IFT_IP                            = 0x7e
+	IFT_IPFORWARD                     = 0x8e
+	IFT_IPOVERATM                     = 0x72
+	IFT_IPOVERCDLC                    = 0x6d
+	IFT_IPOVERCLAW                    = 0x6e
+	IFT_IPSWITCH                      = 0x4e
+	IFT_ISDN                          = 0x3f
+	IFT_ISDNBASIC                     = 0x14
+	IFT_ISDNPRIMARY                   = 0x15
+	IFT_ISDNS                         = 0x4b
+	IFT_ISDNU                         = 0x4c
+	IFT_ISO88022LLC                   = 0x29
+	IFT_ISO88023                      = 0x7
+	IFT_ISO88024                      = 0x8
+	IFT_ISO88025                      = 0x9
+	IFT_ISO88025CRFPINT               = 0x62
+	IFT_ISO88025DTR                   = 0x56
+	IFT_ISO88025FIBER                 = 0x73
+	IFT_ISO88026                      = 0xa
+	IFT_ISUP                          = 0xb3
+	IFT_L2VLAN                        = 0x87
+	IFT_L3IPVLAN                      = 0x88
+	IFT_L3IPXVLAN                     = 0x89
+	IFT_LAPB                          = 0x10
+	IFT_LAPD                          = 0x4d
+	IFT_LAPF                          = 0x77
+	IFT_LINEGROUP                     = 0xd2
+	IFT_LOCALTALK                     = 0x2a
+	IFT_LOOP                          = 0x18
+	IFT_MEDIAMAILOVERIP               = 0x8b
+	IFT_MFSIGLINK                     = 0xa7
+	IFT_MIOX25                        = 0x26
+	IFT_MODEM                         = 0x30
+	IFT_MPC                           = 0x71
+	IFT_MPLS                          = 0xa6
+	IFT_MPLSTUNNEL                    = 0x96
+	IFT_MSDSL                         = 0x8f
+	IFT_MVL                           = 0xbf
+	IFT_MYRINET                       = 0x63
+	IFT_NFAS                          = 0xaf
+	IFT_NSIP                          = 0x1b
+	IFT_OPTICALCHANNEL                = 0xc3
+	IFT_OPTICALTRANSPORT              = 0xc4
+	IFT_OTHER                         = 0x1
+	IFT_P10                           = 0xc
+	IFT_P80                           = 0xd
+	IFT_PARA                          = 0x22
+	IFT_PFLOG                         = 0xf5
+	IFT_PFLOW                         = 0xf9
+	IFT_PFSYNC                        = 0xf6
+	IFT_PLC                           = 0xae
+	IFT_PON155                        = 0xcf
+	IFT_PON622                        = 0xd0
+	IFT_POS                           = 0xab
+	IFT_PPP                           = 0x17
+	IFT_PPPMULTILINKBUNDLE            = 0x6c
+	IFT_PROPATM                       = 0xc5
+	IFT_PROPBWAP2MP                   = 0xb8
+	IFT_PROPCNLS                      = 0x59
+	IFT_PROPDOCSWIRELESSDOWNSTREAM    = 0xb5
+	IFT_PROPDOCSWIRELESSMACLAYER      = 0xb4
+	IFT_PROPDOCSWIRELESSUPSTREAM      = 0xb6
+	IFT_PROPMUX                       = 0x36
+	IFT_PROPVIRTUAL                   = 0x35
+	IFT_PROPWIRELESSP2P               = 0x9d
+	IFT_PTPSERIAL                     = 0x16
+	IFT_PVC                           = 0xf2
+	IFT_Q2931                         = 0xc9
+	IFT_QLLC                          = 0x44
+	IFT_RADIOMAC                      = 0xbc
+	IFT_RADSL                         = 0x5f
+	IFT_REACHDSL                      = 0xc0
+	IFT_RFC1483                       = 0x9f
+	IFT_RS232                         = 0x21
+	IFT_RSRB                          = 0x4f
+	IFT_SDLC                          = 0x11
+	IFT_SDSL                          = 0x60
+	IFT_SHDSL                         = 0xa9
+	IFT_SIP                           = 0x1f
+	IFT_SIPSIG                        = 0xcc
+	IFT_SIPTG                         = 0xcb
+	IFT_SLIP                          = 0x1c
+	IFT_SMDSDXI                       = 0x2b
+	IFT_SMDSICIP                      = 0x34
+	IFT_SONET                         = 0x27
+	IFT_SONETOVERHEADCHANNEL          = 0xb9
+	IFT_SONETPATH                     = 0x32
+	IFT_SONETVT                       = 0x33
+	IFT_SRP                           = 0x97
+	IFT_SS7SIGLINK                    = 0x9c
+	IFT_STACKTOSTACK                  = 0x6f
+	IFT_STARLAN                       = 0xb
+	IFT_T1                            = 0x12
+	IFT_TDLC                          = 0x74
+	IFT_TELINK                        = 0xc8
+	IFT_TERMPAD                       = 0x5b
+	IFT_TR008                         = 0xb0
+	IFT_TRANSPHDLC                    = 0x7b
+	IFT_TUNNEL                        = 0x83
+	IFT_ULTRA                         = 0x1d
+	IFT_USB                           = 0xa0
+	IFT_V11                           = 0x40
+	IFT_V35                           = 0x2d
+	IFT_V36                           = 0x41
+	IFT_V37                           = 0x78
+	IFT_VDSL                          = 0x61
+	IFT_VIRTUALIPADDRESS              = 0x70
+	IFT_VIRTUALTG                     = 0xca
+	IFT_VOICEDID                      = 0xd5
+	IFT_VOICEEM                       = 0x64
+	IFT_VOICEEMFGD                    = 0xd3
+	IFT_VOICEENCAP                    = 0x67
+	IFT_VOICEFGDEANA                  = 0xd4
+	IFT_VOICEFXO                      = 0x65
+	IFT_VOICEFXS                      = 0x66
+	IFT_VOICEOVERATM                  = 0x98
+	IFT_VOICEOVERCABLE                = 0xc6
+	IFT_VOICEOVERFRAMERELAY           = 0x99
+	IFT_VOICEOVERIP                   = 0x68
+	IFT_X213                          = 0x5d
+	IFT_X25                           = 0x5
+	IFT_X25DDN                        = 0x4
+	IFT_X25HUNTGROUP                  = 0x7a
+	IFT_X25MLP                        = 0x79
+	IFT_X25PLE                        = 0x28
+	IFT_XETHER                        = 0x1a
+	IN_CLASSA_HOST                    = 0xffffff
+	IN_CLASSA_MAX                     = 0x80
+	IN_CLASSA_NET                     = 0xff000000
+	IN_CLASSA_NSHIFT                  = 0x18
+	IN_CLASSB_HOST                    = 0xffff
+	IN_CLASSB_MAX                     = 0x10000
+	IN_CLASSB_NET                     = 0xffff0000
+	IN_CLASSB_NSHIFT                  = 0x10
+	IN_CLASSC_HOST                    = 0xff
+	IN_CLASSC_NET                     = 0xffffff00
+	IN_CLASSC_NSHIFT                  = 0x8
+	IN_CLASSD_HOST                    = 0xfffffff
+	IN_CLASSD_NET                     = 0xf0000000
+	IN_CLASSD_NSHIFT                  = 0x1c
+	IN_LOOPBACKNET                    = 0x7f
+	IN_RFC3021_HOST                   = 0x1
+	IN_RFC3021_NET                    = 0xfffffffe
+	IN_RFC3021_NSHIFT                 = 0x1f
+	IPPROTO_AH                        = 0x33
+	IPPROTO_CARP                      = 0x70
+	IPPROTO_DIVERT                    = 0x102
+	IPPROTO_DONE                      = 0x101
+	IPPROTO_DSTOPTS                   = 0x3c
+	IPPROTO_EGP                       = 0x8
+	IPPROTO_ENCAP                     = 0x62
+	IPPROTO_EON                       = 0x50
+	IPPROTO_ESP                       = 0x32
+	IPPROTO_ETHERIP                   = 0x61
+	IPPROTO_FRAGMENT                  = 0x2c
+	IPPROTO_GGP                       = 0x3
+	IPPROTO_GRE                       = 0x2f
+	IPPROTO_HOPOPTS                   = 0x0
+	IPPROTO_ICMP                      = 0x1
+	IPPROTO_ICMPV6                    = 0x3a
+	IPPROTO_IDP                       = 0x16
+	IPPROTO_IGMP                      = 0x2
+	IPPROTO_IP                        = 0x0
+	IPPROTO_IPCOMP                    = 0x6c
+	IPPROTO_IPIP                      = 0x4
+	IPPROTO_IPV4                      = 0x4
+	IPPROTO_IPV6                      = 0x29
+	IPPROTO_MAX                       = 0x100
+	IPPROTO_MAXID                     = 0x103
+	IPPROTO_MOBILE                    = 0x37
+	IPPROTO_MPLS                      = 0x89
+	IPPROTO_NONE                      = 0x3b
+	IPPROTO_PFSYNC                    = 0xf0
+	IPPROTO_PIM                       = 0x67
+	IPPROTO_PUP                       = 0xc
+	IPPROTO_RAW                       = 0xff
+	IPPROTO_ROUTING                   = 0x2b
+	IPPROTO_RSVP                      = 0x2e
+	IPPROTO_TCP                       = 0x6
+	IPPROTO_TP                        = 0x1d
+	IPPROTO_UDP                       = 0x11
+	IPV6_AUTH_LEVEL                   = 0x35
+	IPV6_AUTOFLOWLABEL                = 0x3b
+	IPV6_CHECKSUM                     = 0x1a
+	IPV6_DEFAULT_MULTICAST_HOPS       = 0x1
+	IPV6_DEFAULT_MULTICAST_LOOP       = 0x1
+	IPV6_DEFHLIM                      = 0x40
+	IPV6_DONTFRAG                     = 0x3e
+	IPV6_DSTOPTS                      = 0x32
+	IPV6_ESP_NETWORK_LEVEL            = 0x37
+	IPV6_ESP_TRANS_LEVEL              = 0x36
+	IPV6_FAITH                        = 0x1d
+	IPV6_FLOWINFO_MASK                = 0xffffff0f
+	IPV6_FLOWLABEL_MASK               = 0xffff0f00
+	IPV6_FRAGTTL                      = 0x78
+	IPV6_HLIMDEC                      = 0x1
+	IPV6_HOPLIMIT                     = 0x2f
+	IPV6_HOPOPTS                      = 0x31
+	IPV6_IPCOMP_LEVEL                 = 0x3c
+	IPV6_JOIN_GROUP                   = 0xc
+	IPV6_LEAVE_GROUP                  = 0xd
+	IPV6_MAXHLIM                      = 0xff
+	IPV6_MAXPACKET                    = 0xffff
+	IPV6_MMTU                         = 0x500
+	IPV6_MULTICAST_HOPS               = 0xa
+	IPV6_MULTICAST_IF                 = 0x9
+	IPV6_MULTICAST_LOOP               = 0xb
+	IPV6_NEXTHOP                      = 0x30
+	IPV6_OPTIONS                      = 0x1
+	IPV6_PATHMTU                      = 0x2c
+	IPV6_PIPEX                        = 0x3f
+	IPV6_PKTINFO                      = 0x2e
+	IPV6_PORTRANGE                    = 0xe
+	IPV6_PORTRANGE_DEFAULT            = 0x0
+	IPV6_PORTRANGE_HIGH               = 0x1
+	IPV6_PORTRANGE_LOW                = 0x2
+	IPV6_RECVDSTOPTS                  = 0x28
+	IPV6_RECVHOPLIMIT                 = 0x25
+	IPV6_RECVHOPOPTS                  = 0x27
+	IPV6_RECVPATHMTU                  = 0x2b
+	IPV6_RECVPKTINFO                  = 0x24
+	IPV6_RECVRTHDR                    = 0x26
+	IPV6_RECVTCLASS                   = 0x39
+	IPV6_RTABLE                       = 0x1021
+	IPV6_RTHDR                        = 0x33
+	IPV6_RTHDRDSTOPTS                 = 0x23
+	IPV6_RTHDR_LOOSE                  = 0x0
+	IPV6_RTHDR_STRICT                 = 0x1
+	IPV6_RTHDR_TYPE_0                 = 0x0
+	IPV6_SOCKOPT_RESERVED1            = 0x3
+	IPV6_TCLASS                       = 0x3d
+	IPV6_UNICAST_HOPS                 = 0x4
+	IPV6_USE_MIN_MTU                  = 0x2a
+	IPV6_V6ONLY                       = 0x1b
+	IPV6_VERSION                      = 0x60
+	IPV6_VERSION_MASK                 = 0xf0
+	IP_ADD_MEMBERSHIP                 = 0xc
+	IP_AUTH_LEVEL                     = 0x14
+	IP_DEFAULT_MULTICAST_LOOP         = 0x1
+	IP_DEFAULT_MULTICAST_TTL          = 0x1
+	IP_DF                             = 0x4000
+	IP_DROP_MEMBERSHIP                = 0xd
+	IP_ESP_NETWORK_LEVEL              = 0x16
+	IP_ESP_TRANS_LEVEL                = 0x15
+	IP_HDRINCL                        = 0x2
+	IP_IPCOMP_LEVEL                   = 0x1d
+	IP_IPSEC_LOCAL_AUTH               = 0x1b
+	IP_IPSEC_LOCAL_CRED               = 0x19
+	IP_IPSEC_LOCAL_ID                 = 0x17
+	IP_IPSEC_REMOTE_AUTH              = 0x1c
+	IP_IPSEC_REMOTE_CRED              = 0x1a
+	IP_IPSEC_REMOTE_ID                = 0x18
+	IP_MAXPACKET                      = 0xffff
+	IP_MAX_MEMBERSHIPS                = 0xfff
+	IP_MF                             = 0x2000
+	IP_MINTTL                         = 0x20
+	IP_MIN_MEMBERSHIPS                = 0xf
+	IP_MSS                            = 0x240
+	IP_MULTICAST_IF                   = 0x9
+	IP_MULTICAST_LOOP                 = 0xb
+	IP_MULTICAST_TTL                  = 0xa
+	IP_OFFMASK                        = 0x1fff
+	IP_OPTIONS                        = 0x1
+	IP_PIPEX                          = 0x22
+	IP_PORTRANGE                      = 0x13
+	IP_PORTRANGE_DEFAULT              = 0x0
+	IP_PORTRANGE_HIGH                 = 0x1
+	IP_PORTRANGE_LOW                  = 0x2
+	IP_RECVDSTADDR                    = 0x7
+	IP_RECVDSTPORT                    = 0x21
+	IP_RECVIF                         = 0x1e
+	IP_RECVOPTS                       = 0x5
+	IP_RECVRETOPTS                    = 0x6
+	IP_RECVRTABLE                     = 0x23
+	IP_RECVTTL                        = 0x1f
+	IP_RETOPTS                        = 0x8
+	IP_RF                             = 0x8000
+	IP_RTABLE                         = 0x1021
+	IP_TOS                            = 0x3
+	IP_TTL                            = 0x4
+	MAP_ET_KVAGUARD                   = 0x10
+	MSG_BCAST                         = 0x100
+	MSG_CTRUNC                        = 0x20
+	MSG_DONTROUTE                     = 0x4
+	MSG_DONTWAIT                      = 0x80
+	MSG_EOR                           = 0x8
+	MSG_MCAST                         = 0x200
+	MSG_OOB                           = 0x1
+	MSG_PEEK                          = 0x2
+	MSG_TRUNC                         = 0x10
+	MSG_WAITALL                       = 0x40
+	NAME_MAX                          = 0xff
+	NET_RT_DUMP                       = 0x1
+	NET_RT_FLAGS                      = 0x2
+	NET_RT_IFLIST                     = 0x3
+	NET_RT_MAXID                      = 0x6
+	NET_RT_STATS                      = 0x4
+	NET_RT_TABLE                      = 0x5
+	O_ACCMODE                         = 0x3
+	O_APPEND                          = 0x8
+	O_ASYNC                           = 0x40
+	O_CLOEXEC                         = 0x10000
+	O_CREAT                           = 0x200
+	O_DIRECTORY                       = 0x20000
+	O_DSYNC                           = 0x80
+	O_EXCL                            = 0x800
+	O_EXLOCK                          = 0x20
+	O_FSYNC                           = 0x80
+	O_NDELAY                          = 0x4
+	O_NOCTTY                          = 0x8000
+	O_NOFOLLOW                        = 0x100
+	O_NONBLOCK                        = 0x4
+	O_RDONLY                          = 0x0
+	O_RDWR                            = 0x2
+	O_RSYNC                           = 0x80
+	O_SHLOCK                          = 0x10
+	O_SYNC                            = 0x80
+	O_TRUNC                           = 0x400
+	O_WRONLY                          = 0x1
+	RTAX_AUTHOR                       = 0x6
+	RTAX_BRD                          = 0x7
+	RTAX_DST                          = 0x0
+	RTAX_GATEWAY                      = 0x1
+	RTAX_GENMASK                      = 0x3
+	RTAX_IFA                          = 0x5
+	RTAX_IFP                          = 0x4
+	RTAX_LABEL                        = 0xa
+	RTAX_MAX                          = 0xb
+	RTAX_NETMASK                      = 0x2
+	RTAX_SRC                          = 0x8
+	RTAX_SRCMASK                      = 0x9
+	RTA_AUTHOR                        = 0x40
+	RTA_BRD                           = 0x80
+	RTA_DST                           = 0x1
+	RTA_GATEWAY                       = 0x2
+	RTA_GENMASK                       = 0x8
+	RTA_IFA                           = 0x20
+	RTA_IFP                           = 0x10
+	RTA_LABEL                         = 0x400
+	RTA_NETMASK                       = 0x4
+	RTA_SRC                           = 0x100
+	RTA_SRCMASK                       = 0x200
+	RTF_ANNOUNCE                      = 0x4000
+	RTF_BLACKHOLE                     = 0x1000
+	RTF_CLONED                        = 0x10000
+	RTF_CLONING                       = 0x100
+	RTF_DONE                          = 0x40
+	RTF_DYNAMIC                       = 0x10
+	RTF_FMASK                         = 0x8f808
+	RTF_GATEWAY                       = 0x2
+	RTF_HOST                          = 0x4
+	RTF_JUMBO                         = 0x80000
+	RTF_LLINFO                        = 0x400
+	RTF_MASK                          = 0x80
+	RTF_MODIFIED                      = 0x20
+	RTF_MPATH                         = 0x40000
+	RTF_MPLS                          = 0x100000
+	RTF_PERMANENT_ARP                 = 0x2000
+	RTF_PROTO1                        = 0x8000
+	RTF_PROTO2                        = 0x4000
+	RTF_PROTO3                        = 0x2000
+	RTF_REJECT                        = 0x8
+	RTF_SOURCE                        = 0x20000
+	RTF_STATIC                        = 0x800
+	RTF_TUNNEL                        = 0x100000
+	RTF_UP                            = 0x1
+	RTF_USETRAILERS                   = 0x8000
+	RTF_XRESOLVE                      = 0x200
+	RTM_ADD                           = 0x1
+	RTM_CHANGE                        = 0x3
+	RTM_DELADDR                       = 0xd
+	RTM_DELETE                        = 0x2
+	RTM_DESYNC                        = 0x10
+	RTM_GET                           = 0x4
+	RTM_IFANNOUNCE                    = 0xf
+	RTM_IFINFO                        = 0xe
+	RTM_LOCK                          = 0x8
+	RTM_LOSING                        = 0x5
+	RTM_MAXSIZE                       = 0x800
+	RTM_MISS                          = 0x7
+	RTM_NEWADDR                       = 0xc
+	RTM_REDIRECT                      = 0x6
+	RTM_RESOLVE                       = 0xb
+	RTM_RTTUNIT                       = 0xf4240
+	RTM_VERSION                       = 0x4
+	RTV_EXPIRE                        = 0x4
+	RTV_HOPCOUNT                      = 0x2
+	RTV_MTU                           = 0x1
+	RTV_RPIPE                         = 0x8
+	RTV_RTT                           = 0x40
+	RTV_RTTVAR                        = 0x80
+	RTV_SPIPE                         = 0x10
+	RTV_SSTHRESH                      = 0x20
+	RT_TABLEID_MAX                    = 0xff
+	SCM_CREDS                         = 0x2
+	SCM_RIGHTS                        = 0x1
+	SCM_TIMESTAMP                     = 0x4
+	SHUT_RD                           = 0x0
+	SHUT_RDWR                         = 0x2
+	SHUT_WR                           = 0x1
+	SIGABRT                           = 0x6
+	SIGALRM                           = 0xe
+	SIGBUS                            = 0xa
+	SIGCHLD                           = 0x14
+	SIGCONT                           = 0x13
+	SIGEMT                            = 0x7
+	SIGFPE                            = 0x8
+	SIGHUP                            = 0x1
+	SIGILL                            = 0x4
+	SIGINFO                           = 0x1d
+	SIGINT                            = 0x2
+	SIGIO                             = 0x17
+	SIGIOT                            = 0x6
+	SIGKILL                           = 0x9
+	SIGPIPE                           = 0xd
+	SIGPROF                           = 0x1b
+	SIGQUIT                           = 0x3
+	SIGSEGV                           = 0xb
+	SIGSTOP                           = 0x11
+	SIGSYS                            = 0xc
+	SIGTERM                           = 0xf
+	SIGTHR                            = 0x20
+	SIGTRAP                           = 0x5
+	SIGTSTP                           = 0x12
+	SIGTTIN                           = 0x15
+	SIGTTOU                           = 0x16
+	SIGURG                            = 0x10
+	SIGUSR1                           = 0x1e
+	SIGUSR2                           = 0x1f
+	SIGVTALRM                         = 0x1a
+	SIGWINCH                          = 0x1c
+	SIGXCPU                           = 0x18
+	SIGXFSZ                           = 0x19
+	SIOCADDMULTI                      = 0x80206931
+	SIOCAIFADDR                       = 0x8040691a
+	SIOCAIFGROUP                      = 0x80286987
+	SIOCALIFADDR                      = 0x8218691c
+	SIOCATMARK                        = 0x40047307
+	SIOCBRDGADD                       = 0x8058693c
+	SIOCBRDGADDS                      = 0x80586941
+	SIOCBRDGARL                       = 0x806e694d
+	SIOCBRDGDADDR                     = 0x80286947
+	SIOCBRDGDEL                       = 0x8058693d
+	SIOCBRDGDELS                      = 0x80586942
+	SIOCBRDGFLUSH                     = 0x80586948
+	SIOCBRDGFRL                       = 0x806e694e
+	SIOCBRDGGCACHE                    = 0xc0146941
+	SIOCBRDGGFD                       = 0xc0146952
+	SIOCBRDGGHT                       = 0xc0146951
+	SIOCBRDGGIFFLGS                   = 0xc058693e
+	SIOCBRDGGMA                       = 0xc0146953
+	SIOCBRDGGPARAM                    = 0xc0406958
+	SIOCBRDGGPRI                      = 0xc0146950
+	SIOCBRDGGRL                       = 0xc030694f
+	SIOCBRDGGSIFS                     = 0xc058693c
+	SIOCBRDGGTO                       = 0xc0146946
+	SIOCBRDGIFS                       = 0xc0586942
+	SIOCBRDGRTS                       = 0xc0206943
+	SIOCBRDGSADDR                     = 0xc0286944
+	SIOCBRDGSCACHE                    = 0x80146940
+	SIOCBRDGSFD                       = 0x80146952
+	SIOCBRDGSHT                       = 0x80146951
+	SIOCBRDGSIFCOST                   = 0x80586955
+	SIOCBRDGSIFFLGS                   = 0x8058693f
+	SIOCBRDGSIFPRIO                   = 0x80586954
+	SIOCBRDGSMA                       = 0x80146953
+	SIOCBRDGSPRI                      = 0x80146950
+	SIOCBRDGSPROTO                    = 0x8014695a
+	SIOCBRDGSTO                       = 0x80146945
+	SIOCBRDGSTXHC                     = 0x80146959
+	SIOCDELMULTI                      = 0x80206932
+	SIOCDIFADDR                       = 0x80206919
+	SIOCDIFGROUP                      = 0x80286989
+	SIOCDIFPHYADDR                    = 0x80206949
+	SIOCDLIFADDR                      = 0x8218691e
+	SIOCGETKALIVE                     = 0xc01869a4
+	SIOCGETLABEL                      = 0x8020699a
+	SIOCGETPFLOW                      = 0xc02069fe
+	SIOCGETPFSYNC                     = 0xc02069f8
+	SIOCGETSGCNT                      = 0xc0207534
+	SIOCGETVIFCNT                     = 0xc0287533
+	SIOCGETVLANPRIO                   = 0xc0206990
+	SIOCGHIWAT                        = 0x40047301
+	SIOCGIFADDR                       = 0xc0206921
+	SIOCGIFASYNCMAP                   = 0xc020697c
+	SIOCGIFBRDADDR                    = 0xc0206923
+	SIOCGIFCONF                       = 0xc0106924
+	SIOCGIFDATA                       = 0xc020691b
+	SIOCGIFDESCR                      = 0xc0206981
+	SIOCGIFDSTADDR                    = 0xc0206922
+	SIOCGIFFLAGS                      = 0xc0206911
+	SIOCGIFGATTR                      = 0xc028698b
+	SIOCGIFGENERIC                    = 0xc020693a
+	SIOCGIFGMEMB                      = 0xc028698a
+	SIOCGIFGROUP                      = 0xc0286988
+	SIOCGIFMEDIA                      = 0xc0306936
+	SIOCGIFMETRIC                     = 0xc0206917
+	SIOCGIFMTU                        = 0xc020697e
+	SIOCGIFNETMASK                    = 0xc0206925
+	SIOCGIFPDSTADDR                   = 0xc0206948
+	SIOCGIFPRIORITY                   = 0xc020699c
+	SIOCGIFPSRCADDR                   = 0xc0206947
+	SIOCGIFRDOMAIN                    = 0xc02069a0
+	SIOCGIFRTLABEL                    = 0xc0206983
+	SIOCGIFTIMESLOT                   = 0xc0206986
+	SIOCGIFXFLAGS                     = 0xc020699e
+	SIOCGLIFADDR                      = 0xc218691d
+	SIOCGLIFPHYADDR                   = 0xc218694b
+	SIOCGLIFPHYRTABLE                 = 0xc02069a2
+	SIOCGLOWAT                        = 0x40047303
+	SIOCGPGRP                         = 0x40047309
+	SIOCGVH                           = 0xc02069f6
+	SIOCIFCREATE                      = 0x8020697a
+	SIOCIFDESTROY                     = 0x80206979
+	SIOCIFGCLONERS                    = 0xc0106978
+	SIOCSETKALIVE                     = 0x801869a3
+	SIOCSETLABEL                      = 0x80206999
+	SIOCSETPFLOW                      = 0x802069fd
+	SIOCSETPFSYNC                     = 0x802069f7
+	SIOCSETVLANPRIO                   = 0x8020698f
+	SIOCSHIWAT                        = 0x80047300
+	SIOCSIFADDR                       = 0x8020690c
+	SIOCSIFASYNCMAP                   = 0x8020697d
+	SIOCSIFBRDADDR                    = 0x80206913
+	SIOCSIFDESCR                      = 0x80206980
+	SIOCSIFDSTADDR                    = 0x8020690e
+	SIOCSIFFLAGS                      = 0x80206910
+	SIOCSIFGATTR                      = 0x8028698c
+	SIOCSIFGENERIC                    = 0x80206939
+	SIOCSIFLLADDR                     = 0x8020691f
+	SIOCSIFMEDIA                      = 0xc0206935
+	SIOCSIFMETRIC                     = 0x80206918
+	SIOCSIFMTU                        = 0x8020697f
+	SIOCSIFNETMASK                    = 0x80206916
+	SIOCSIFPHYADDR                    = 0x80406946
+	SIOCSIFPRIORITY                   = 0x8020699b
+	SIOCSIFRDOMAIN                    = 0x8020699f
+	SIOCSIFRTLABEL                    = 0x80206982
+	SIOCSIFTIMESLOT                   = 0x80206985
+	SIOCSIFXFLAGS                     = 0x8020699d
+	SIOCSLIFPHYADDR                   = 0x8218694a
+	SIOCSLIFPHYRTABLE                 = 0x802069a1
+	SIOCSLOWAT                        = 0x80047302
+	SIOCSPGRP                         = 0x80047308
+	SIOCSVH                           = 0xc02069f5
+	SOCK_DGRAM                        = 0x2
+	SOCK_RAW                          = 0x3
+	SOCK_RDM                          = 0x4
+	SOCK_SEQPACKET                    = 0x5
+	SOCK_STREAM                       = 0x1
+	SOL_SOCKET                        = 0xffff
+	SOMAXCONN                         = 0x80
+	SO_ACCEPTCONN                     = 0x2
+	SO_BINDANY                        = 0x1000
+	SO_BROADCAST                      = 0x20
+	SO_DEBUG                          = 0x1
+	SO_DONTROUTE                      = 0x10
+	SO_ERROR                          = 0x1007
+	SO_JUMBO                          = 0x400
+	SO_KEEPALIVE                      = 0x8
+	SO_LINGER                         = 0x80
+	SO_NETPROC                        = 0x1020
+	SO_OOBINLINE                      = 0x100
+	SO_PEERCRED                       = 0x1022
+	SO_RCVBUF                         = 0x1002
+	SO_RCVLOWAT                       = 0x1004
+	SO_RCVTIMEO                       = 0x1006
+	SO_REUSEADDR                      = 0x4
+	SO_REUSEPORT                      = 0x200
+	SO_RTABLE                         = 0x1021
+	SO_SNDBUF                         = 0x1001
+	SO_SNDLOWAT                       = 0x1003
+	SO_SNDTIMEO                       = 0x1005
+	SO_SPLICE                         = 0x1023
+	SO_TIMESTAMP                      = 0x800
+	SO_TYPE                           = 0x1008
+	SO_USELOOPBACK                    = 0x40
+	TCP_MAXBURST                      = 0x4
+	TCP_MAXSEG                        = 0x2
+	TCP_MAXWIN                        = 0xffff
+	TCP_MAX_SACK                      = 0x3
+	TCP_MAX_WINSHIFT                  = 0xe
+	TCP_MD5SIG                        = 0x4
+	TCP_MSS                           = 0x200
+	TCP_NODELAY                       = 0x1
+	TCP_NSTATES                       = 0xb
+	TCP_SACK_ENABLE                   = 0x8
+	TIOCCBRK                          = 0x2000747a
+	TIOCCDTR                          = 0x20007478
+	TIOCCONS                          = 0x80047462
+	TIOCDRAIN                         = 0x2000745e
+	TIOCEXCL                          = 0x2000740d
+	TIOCEXT                           = 0x80047460
+	TIOCFLAG_CLOCAL                   = 0x2
+	TIOCFLAG_CRTSCTS                  = 0x4
+	TIOCFLAG_MDMBUF                   = 0x8
+	TIOCFLAG_PPS                      = 0x10
+	TIOCFLAG_SOFTCAR                  = 0x1
+	TIOCFLUSH                         = 0x80047410
+	TIOCGETA                          = 0x402c7413
+	TIOCGETD                          = 0x4004741a
+	TIOCGFLAGS                        = 0x4004745d
+	TIOCGPGRP                         = 0x40047477
+	TIOCGTSTAMP                       = 0x4010745b
+	TIOCGWINSZ                        = 0x40087468
+	TIOCMBIC                          = 0x8004746b
+	TIOCMBIS                          = 0x8004746c
+	TIOCMGET                          = 0x4004746a
+	TIOCMODG                          = 0x4004746a
+	TIOCMODS                          = 0x8004746d
+	TIOCMSET                          = 0x8004746d
+	TIOCM_CAR                         = 0x40
+	TIOCM_CD                          = 0x40
+	TIOCM_CTS                         = 0x20
+	TIOCM_DSR                         = 0x100
+	TIOCM_DTR                         = 0x2
+	TIOCM_LE                          = 0x1
+	TIOCM_RI                          = 0x80
+	TIOCM_RNG                         = 0x80
+	TIOCM_RTS                         = 0x4
+	TIOCM_SR                          = 0x10
+	TIOCM_ST                          = 0x8
+	TIOCNOTTY                         = 0x20007471
+	TIOCNXCL                          = 0x2000740e
+	TIOCOUTQ                          = 0x40047473
+	TIOCPKT                           = 0x80047470
+	TIOCPKT_DATA                      = 0x0
+	TIOCPKT_DOSTOP                    = 0x20
+	TIOCPKT_FLUSHREAD                 = 0x1
+	TIOCPKT_FLUSHWRITE                = 0x2
+	TIOCPKT_IOCTL                     = 0x40
+	TIOCPKT_NOSTOP                    = 0x10
+	TIOCPKT_START                     = 0x8
+	TIOCPKT_STOP                      = 0x4
+	TIOCREMOTE                        = 0x80047469
+	TIOCSBRK                          = 0x2000747b
+	TIOCSCTTY                         = 0x20007461
+	TIOCSDTR                          = 0x20007479
+	TIOCSETA                          = 0x802c7414
+	TIOCSETAF                         = 0x802c7416
+	TIOCSETAW                         = 0x802c7415
+	TIOCSETD                          = 0x8004741b
+	TIOCSFLAGS                        = 0x8004745c
+	TIOCSIG                           = 0x8004745f
+	TIOCSPGRP                         = 0x80047476
+	TIOCSTART                         = 0x2000746e
+	TIOCSTAT                          = 0x80047465
+	TIOCSTI                           = 0x80017472
+	TIOCSTOP                          = 0x2000746f
+	TIOCSTSTAMP                       = 0x8008745a
+	TIOCSWINSZ                        = 0x80087467
+	TIOCUCNTL                         = 0x80047466
+	WALTSIG                           = 0x4
+	WCONTINUED                        = 0x8
+	WCOREFLAG                         = 0x80
+	WNOHANG                           = 0x1
+	WSTOPPED                          = 0x7f
+	WUNTRACED                         = 0x2
+)
+
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADF           = Errno(0x9)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x58)
+	ECHILD          = Errno(0xa)
+	ECHO            = Errno(0x8)
+	ECHOCTL         = Errno(0x40)
+	ECHOE           = Errno(0x2)
+	ECHOK           = Errno(0x4)
+	ECHOKE          = Errno(0x1)
+	ECHONL          = Errno(0x10)
+	ECHOPRT         = Errno(0x20)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDOM            = Errno(0x21)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x59)
+	EILSEQ          = Errno(0x54)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EIPSEC          = Errno(0x52)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x5b)
+	ELOOP           = Errno(0x3e)
+	EMEDIUMTYPE     = Errno(0x56)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENDRUNDISC      = Errno(0x9)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x53)
+	ENOBUFS         = Errno(0x37)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOMEDIUM       = Errno(0x55)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x5a)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x5b)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x2d)
+	EOVERFLOW       = Errno(0x57)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
+
+// Error table
+var errors = [...]string{
+	1:  "operation not permitted",
+	2:  "no such file or directory",
+	3:  "no such process",
+	4:  "interrupted system call",
+	5:  "input/output error",
+	6:  "device not configured",
+	7:  "argument list too long",
+	8:  "exec format error",
+	9:  "bad file descriptor",
+	10: "no child processes",
+	11: "resource deadlock avoided",
+	12: "cannot allocate memory",
+	13: "permission denied",
+	14: "bad address",
+	15: "block device required",
+	16: "device busy",
+	17: "file exists",
+	18: "cross-device link",
+	19: "operation not supported by device",
+	20: "not a directory",
+	21: "is a directory",
+	22: "invalid argument",
+	23: "too many open files in system",
+	24: "too many open files",
+	25: "inappropriate ioctl for device",
+	26: "text file busy",
+	27: "file too large",
+	28: "no space left on device",
+	29: "illegal seek",
+	30: "read-only file system",
+	31: "too many links",
+	32: "broken pipe",
+	33: "numerical argument out of domain",
+	34: "result too large",
+	35: "resource temporarily unavailable",
+	36: "operation now in progress",
+	37: "operation already in progress",
+	38: "socket operation on non-socket",
+	39: "destination address required",
+	40: "message too long",
+	41: "protocol wrong type for socket",
+	42: "protocol not available",
+	43: "protocol not supported",
+	44: "socket type not supported",
+	45: "operation not supported",
+	46: "protocol family not supported",
+	47: "address family not supported by protocol family",
+	48: "address already in use",
+	49: "can't assign requested address",
+	50: "network is down",
+	51: "network is unreachable",
+	52: "network dropped connection on reset",
+	53: "software caused connection abort",
+	54: "connection reset by peer",
+	55: "no buffer space available",
+	56: "socket is already connected",
+	57: "socket is not connected",
+	58: "can't send after socket shutdown",
+	59: "too many references: can't splice",
+	60: "connection timed out",
+	61: "connection refused",
+	62: "too many levels of symbolic links",
+	63: "file name too long",
+	64: "host is down",
+	65: "no route to host",
+	66: "directory not empty",
+	67: "too many processes",
+	68: "too many users",
+	69: "disc quota exceeded",
+	70: "stale NFS file handle",
+	71: "too many levels of remote in path",
+	72: "RPC struct is bad",
+	73: "RPC version wrong",
+	74: "RPC prog. not avail",
+	75: "program version wrong",
+	76: "bad procedure for program",
+	77: "no locks available",
+	78: "function not implemented",
+	79: "inappropriate file type or format",
+	80: "authentication error",
+	81: "need authenticator",
+	82: "IPsec processing failure",
+	83: "attribute not found",
+	84: "illegal byte sequence",
+	85: "no medium found",
+	86: "wrong medium type",
+	87: "value too large to be stored in data type",
+	88: "operation canceled",
+	89: "identifier removed",
+	90: "no message of desired type",
+	91: "not supported",
+}
diff --git a/src/pkg/syscall/zerrors_openbsd_386.go b/src/pkg/syscall/zerrors_openbsd_386.go
index e09d9de..00ca00c 100644
--- a/src/pkg/syscall/zerrors_openbsd_386.go
+++ b/src/pkg/syscall/zerrors_openbsd_386.go
@@ -1,13 +1,11 @@
-// mkerrors.sh -f -m32
+// mkerrors.sh -m32
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -f -m32 -gsyscall -f -m32 _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m32 _const.go
 
 package syscall
 
-// Constants
 const (
 	AF_APPLETALK                      = 0x10
 	AF_BLUETOOTH                      = 0x20
@@ -42,7 +40,7 @@ const (
 	AF_SIP                            = 0x1d
 	AF_SNA                            = 0xb
 	AF_UNIX                           = 0x1
-	AF_UNSPEC                         = 0
+	AF_UNSPEC                         = 0x0
 	ARPHRD_ETHER                      = 0x1
 	ARPHRD_FRELAY                     = 0xf
 	ARPHRD_IEEE1394                   = 0x18
@@ -74,7 +72,7 @@ const (
 	BIOCVERSION                       = 0x40044271
 	BPF_A                             = 0x10
 	BPF_ABS                           = 0x20
-	BPF_ADD                           = 0
+	BPF_ADD                           = 0x0
 	BPF_ALIGNMENT                     = 0x4
 	BPF_ALU                           = 0x4
 	BPF_AND                           = 0x50
@@ -83,16 +81,16 @@ const (
 	BPF_DIRECTION_OUT                 = 0x2
 	BPF_DIV                           = 0x30
 	BPF_H                             = 0x8
-	BPF_IMM                           = 0
+	BPF_IMM                           = 0x0
 	BPF_IND                           = 0x40
-	BPF_JA                            = 0
+	BPF_JA                            = 0x0
 	BPF_JEQ                           = 0x10
 	BPF_JGE                           = 0x30
 	BPF_JGT                           = 0x20
 	BPF_JMP                           = 0x5
 	BPF_JSET                          = 0x40
-	BPF_K                             = 0
-	BPF_LD                            = 0
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
 	BPF_LDX                           = 0x1
 	BPF_LEN                           = 0x80
 	BPF_LSH                           = 0x60
@@ -114,9 +112,9 @@ const (
 	BPF_ST                            = 0x2
 	BPF_STX                           = 0x3
 	BPF_SUB                           = 0x10
-	BPF_TAX                           = 0
+	BPF_TAX                           = 0x0
 	BPF_TXA                           = 0x80
-	BPF_W                             = 0
+	BPF_W                             = 0x0
 	BPF_X                             = 0x8
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
@@ -133,7 +131,7 @@ const (
 	DLT_IEEE802_11_RADIO              = 0x7f
 	DLT_LOOP                          = 0xc
 	DLT_MPLS                          = 0xdb
-	DLT_NULL                          = 0
+	DLT_NULL                          = 0x0
 	DLT_PFLOG                         = 0x75
 	DLT_PFSYNC                        = 0x12
 	DLT_PPP                           = 0x9
@@ -150,20 +148,7 @@ const (
 	DT_LNK                            = 0xa
 	DT_REG                            = 0x8
 	DT_SOCK                           = 0xc
-	DT_UNKNOWN                        = 0
-	E2BIG                             = 0x7
-	EACCES                            = 0xd
-	EADDRINUSE                        = 0x30
-	EADDRNOTAVAIL                     = 0x31
-	EAFNOSUPPORT                      = 0x2f
-	EAGAIN                            = 0x23
-	EALREADY                          = 0x25
-	EAUTH                             = 0x50
-	EBADF                             = 0x9
-	EBADRPC                           = 0x48
-	EBUSY                             = 0x10
-	ECANCELED                         = 0x58
-	ECHILD                            = 0xa
+	DT_UNKNOWN                        = 0x0
 	ECHO                              = 0x8
 	ECHOCTL                           = 0x40
 	ECHOE                             = 0x2
@@ -171,88 +156,14 @@ const (
 	ECHOKE                            = 0x1
 	ECHONL                            = 0x10
 	ECHOPRT                           = 0x20
-	ECONNABORTED                      = 0x35
-	ECONNREFUSED                      = 0x3d
-	ECONNRESET                        = 0x36
-	EDEADLK                           = 0xb
-	EDESTADDRREQ                      = 0x27
-	EDOM                              = 0x21
-	EDQUOT                            = 0x45
-	EEXIST                            = 0x11
-	EFAULT                            = 0xe
-	EFBIG                             = 0x1b
 	EFER_LMA                          = 0x400
 	EFER_LME                          = 0x100
 	EFER_NXE                          = 0x800
 	EFER_SCE                          = 0x1
-	EFTYPE                            = 0x4f
-	EHOSTDOWN                         = 0x40
-	EHOSTUNREACH                      = 0x41
-	EIDRM                             = 0x59
-	EILSEQ                            = 0x54
-	EINPROGRESS                       = 0x24
-	EINTR                             = 0x4
-	EINVAL                            = 0x16
-	EIO                               = 0x5
-	EIPSEC                            = 0x52
-	EISCONN                           = 0x38
-	EISDIR                            = 0x15
-	ELAST                             = 0x5b
-	ELOOP                             = 0x3e
-	EMEDIUMTYPE                       = 0x56
-	EMFILE                            = 0x18
-	EMLINK                            = 0x1f
-	EMSGSIZE                          = 0x28
 	EMT_TAGOVF                        = 0x1
 	EMUL_ENABLED                      = 0x1
 	EMUL_NATIVE                       = 0x2
-	ENAMETOOLONG                      = 0x3f
 	ENDRUNDISC                        = 0x9
-	ENEEDAUTH                         = 0x51
-	ENETDOWN                          = 0x32
-	ENETRESET                         = 0x34
-	ENETUNREACH                       = 0x33
-	ENFILE                            = 0x17
-	ENOATTR                           = 0x53
-	ENOBUFS                           = 0x37
-	ENODEV                            = 0x13
-	ENOENT                            = 0x2
-	ENOEXEC                           = 0x8
-	ENOLCK                            = 0x4d
-	ENOMEDIUM                         = 0x55
-	ENOMEM                            = 0xc
-	ENOMSG                            = 0x5a
-	ENOPROTOOPT                       = 0x2a
-	ENOSPC                            = 0x1c
-	ENOSYS                            = 0x4e
-	ENOTBLK                           = 0xf
-	ENOTCONN                          = 0x39
-	ENOTDIR                           = 0x14
-	ENOTEMPTY                         = 0x42
-	ENOTSOCK                          = 0x26
-	ENOTSUP                           = 0x5b
-	ENOTTY                            = 0x19
-	ENXIO                             = 0x6
-	EOPNOTSUPP                        = 0x2d
-	EOVERFLOW                         = 0x57
-	EPERM                             = 0x1
-	EPFNOSUPPORT                      = 0x2e
-	EPIPE                             = 0x20
-	EPROCLIM                          = 0x43
-	EPROCUNAVAIL                      = 0x4c
-	EPROGMISMATCH                     = 0x4b
-	EPROGUNAVAIL                      = 0x4a
-	EPROTONOSUPPORT                   = 0x2b
-	EPROTOTYPE                        = 0x29
-	ERANGE                            = 0x22
-	EREMOTE                           = 0x47
-	EROFS                             = 0x1e
-	ERPCMISMATCH                      = 0x49
-	ESHUTDOWN                         = 0x3a
-	ESOCKTNOSUPPORT                   = 0x2c
-	ESPIPE                            = 0x1d
-	ESRCH                             = 0x3
-	ESTALE                            = 0x46
 	ETHERMIN                          = 0x2e
 	ETHERMTU                          = 0x5dc
 	ETHERTYPE_8023                    = 0x4
@@ -451,10 +362,6 @@ const (
 	ETHER_MIN_LEN                     = 0x40
 	ETHER_TYPE_LEN                    = 0x2
 	ETHER_VLAN_ENCAP_LEN              = 0x4
-	ETIMEDOUT                         = 0x3c
-	ETOOMANYREFS                      = 0x3b
-	ETXTBSY                           = 0x1a
-	EUSERS                            = 0x44
 	EVFILT_AIO                        = -0x3
 	EVFILT_PROC                       = -0x5
 	EVFILT_READ                       = -0x1
@@ -473,19 +380,18 @@ const (
 	EV_FLAG1                          = 0x2000
 	EV_ONESHOT                        = 0x10
 	EV_SYSFLAGS                       = 0xf000
-	EWOULDBLOCK                       = 0x23
-	EXDEV                             = 0x12
 	EXTA                              = 0x4b00
 	EXTB                              = 0x9600
 	EXTPROC                           = 0x800
 	FD_CLOEXEC                        = 0x1
 	FD_SETSIZE                        = 0x400
-	F_DUPFD                           = 0
+	F_DUPFD                           = 0x0
 	F_DUPFD_CLOEXEC                   = 0xa
 	F_GETFD                           = 0x1
 	F_GETFL                           = 0x3
 	F_GETLK                           = 0x7
 	F_GETOWN                          = 0x5
+	F_OK                              = 0x0
 	F_RDLCK                           = 0x1
 	F_SETFD                           = 0x2
 	F_SETFL                           = 0x4
@@ -767,12 +673,12 @@ const (
 	IPPROTO_FRAGMENT                  = 0x2c
 	IPPROTO_GGP                       = 0x3
 	IPPROTO_GRE                       = 0x2f
-	IPPROTO_HOPOPTS                   = 0
+	IPPROTO_HOPOPTS                   = 0x0
 	IPPROTO_ICMP                      = 0x1
 	IPPROTO_ICMPV6                    = 0x3a
 	IPPROTO_IDP                       = 0x16
 	IPPROTO_IGMP                      = 0x2
-	IPPROTO_IP                        = 0
+	IPPROTO_IP                        = 0x0
 	IPPROTO_IPCOMP                    = 0x6c
 	IPPROTO_IPIP                      = 0x4
 	IPPROTO_IPV4                      = 0x4
@@ -823,7 +729,7 @@ const (
 	IPV6_PIPEX                        = 0x3f
 	IPV6_PKTINFO                      = 0x2e
 	IPV6_PORTRANGE                    = 0xe
-	IPV6_PORTRANGE_DEFAULT            = 0
+	IPV6_PORTRANGE_DEFAULT            = 0x0
 	IPV6_PORTRANGE_HIGH               = 0x1
 	IPV6_PORTRANGE_LOW                = 0x2
 	IPV6_RECVDSTOPTS                  = 0x28
@@ -836,9 +742,9 @@ const (
 	IPV6_RTABLE                       = 0x1021
 	IPV6_RTHDR                        = 0x33
 	IPV6_RTHDRDSTOPTS                 = 0x23
-	IPV6_RTHDR_LOOSE                  = 0
+	IPV6_RTHDR_LOOSE                  = 0x0
 	IPV6_RTHDR_STRICT                 = 0x1
-	IPV6_RTHDR_TYPE_0                 = 0
+	IPV6_RTHDR_TYPE_0                 = 0x0
 	IPV6_SOCKOPT_RESERVED1            = 0x3
 	IPV6_TCLASS                       = 0x3d
 	IPV6_UNICAST_HOPS                 = 0x4
@@ -875,7 +781,7 @@ const (
 	IP_OPTIONS                        = 0x1
 	IP_PIPEX                          = 0x22
 	IP_PORTRANGE                      = 0x13
-	IP_PORTRANGE_DEFAULT              = 0
+	IP_PORTRANGE_DEFAULT              = 0x0
 	IP_PORTRANGE_HIGH                 = 0x1
 	IP_PORTRANGE_LOW                  = 0x2
 	IP_RECVDSTADDR                    = 0x7
@@ -890,6 +796,10 @@ const (
 	IP_RTABLE                         = 0x1021
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
 	MAP_ET_KVAGUARD                   = 0x10
 	MSG_BCAST                         = 0x100
 	MSG_CTRUNC                        = 0x20
@@ -922,16 +832,23 @@ const (
 	O_NOCTTY                          = 0x8000
 	O_NOFOLLOW                        = 0x100
 	O_NONBLOCK                        = 0x4
-	O_RDONLY                          = 0
+	O_RDONLY                          = 0x0
 	O_RDWR                            = 0x2
 	O_RSYNC                           = 0x80
 	O_SHLOCK                          = 0x10
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_WRONLY                          = 0x1
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
 	RTAX_AUTHOR                       = 0x6
 	RTAX_BRD                          = 0x7
-	RTAX_DST                          = 0
+	RTAX_DST                          = 0x0
 	RTAX_GATEWAY                      = 0x1
 	RTAX_GENMASK                      = 0x3
 	RTAX_IFA                          = 0x5
@@ -1003,10 +920,14 @@ const (
 	RTV_RTTVAR                        = 0x80
 	RTV_SPIPE                         = 0x10
 	RTV_SSTHRESH                      = 0x20
+	RT_TABLEID_MAX                    = 0xff
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	RUSAGE_THREAD                     = 0x1
 	SCM_CREDS                         = 0x2
 	SCM_RIGHTS                        = 0x1
 	SCM_TIMESTAMP                     = 0x4
-	SHUT_RD                           = 0
+	SHUT_RD                           = 0x0
 	SHUT_RDWR                         = 0x2
 	SHUT_WR                           = 0x1
 	SIGABRT                           = 0x6
@@ -1235,7 +1156,7 @@ const (
 	TIOCNXCL                          = 0x2000740e
 	TIOCOUTQ                          = 0x40047473
 	TIOCPKT                           = 0x80047470
-	TIOCPKT_DATA                      = 0
+	TIOCPKT_DATA                      = 0x0
 	TIOCPKT_DOSTOP                    = 0x20
 	TIOCPKT_FLUSHREAD                 = 0x1
 	TIOCPKT_FLUSHWRITE                = 0x2
@@ -1269,7 +1190,102 @@ const (
 	WUNTRACED                         = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADF           = Errno(0x9)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x58)
+	ECHILD          = Errno(0xa)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDOM            = Errno(0x21)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x59)
+	EILSEQ          = Errno(0x54)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EIPSEC          = Errno(0x52)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x5b)
+	ELOOP           = Errno(0x3e)
+	EMEDIUMTYPE     = Errno(0x56)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x53)
+	ENOBUFS         = Errno(0x37)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOMEDIUM       = Errno(0x55)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x5a)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x5b)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x2d)
+	EOVERFLOW       = Errno(0x57)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
 
 // Error table
 var errors = [...]string{
diff --git a/src/pkg/syscall/zerrors_openbsd_amd64.go b/src/pkg/syscall/zerrors_openbsd_amd64.go
index 10fa5e4..f4e0e2f 100644
--- a/src/pkg/syscall/zerrors_openbsd_amd64.go
+++ b/src/pkg/syscall/zerrors_openbsd_amd64.go
@@ -1,13 +1,11 @@
-// mkerrors.sh -f -m64
+// mkerrors.sh -m64
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
-// godefs -c gcc -f -m64 -gsyscall -f -m64 _const.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m64 _const.go
 
 package syscall
 
-// Constants
 const (
 	AF_APPLETALK                      = 0x10
 	AF_BLUETOOTH                      = 0x20
@@ -42,7 +40,7 @@ const (
 	AF_SIP                            = 0x1d
 	AF_SNA                            = 0xb
 	AF_UNIX                           = 0x1
-	AF_UNSPEC                         = 0
+	AF_UNSPEC                         = 0x0
 	ARPHRD_ETHER                      = 0x1
 	ARPHRD_FRELAY                     = 0xf
 	ARPHRD_IEEE1394                   = 0x18
@@ -74,7 +72,7 @@ const (
 	BIOCVERSION                       = 0x40044271
 	BPF_A                             = 0x10
 	BPF_ABS                           = 0x20
-	BPF_ADD                           = 0
+	BPF_ADD                           = 0x0
 	BPF_ALIGNMENT                     = 0x4
 	BPF_ALU                           = 0x4
 	BPF_AND                           = 0x50
@@ -83,16 +81,16 @@ const (
 	BPF_DIRECTION_OUT                 = 0x2
 	BPF_DIV                           = 0x30
 	BPF_H                             = 0x8
-	BPF_IMM                           = 0
+	BPF_IMM                           = 0x0
 	BPF_IND                           = 0x40
-	BPF_JA                            = 0
+	BPF_JA                            = 0x0
 	BPF_JEQ                           = 0x10
 	BPF_JGE                           = 0x30
 	BPF_JGT                           = 0x20
 	BPF_JMP                           = 0x5
 	BPF_JSET                          = 0x40
-	BPF_K                             = 0
-	BPF_LD                            = 0
+	BPF_K                             = 0x0
+	BPF_LD                            = 0x0
 	BPF_LDX                           = 0x1
 	BPF_LEN                           = 0x80
 	BPF_LSH                           = 0x60
@@ -114,9 +112,9 @@ const (
 	BPF_ST                            = 0x2
 	BPF_STX                           = 0x3
 	BPF_SUB                           = 0x10
-	BPF_TAX                           = 0
+	BPF_TAX                           = 0x0
 	BPF_TXA                           = 0x80
-	BPF_W                             = 0
+	BPF_W                             = 0x0
 	BPF_X                             = 0x8
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
@@ -133,7 +131,7 @@ const (
 	DLT_IEEE802_11_RADIO              = 0x7f
 	DLT_LOOP                          = 0xc
 	DLT_MPLS                          = 0xdb
-	DLT_NULL                          = 0
+	DLT_NULL                          = 0x0
 	DLT_PFLOG                         = 0x75
 	DLT_PFSYNC                        = 0x12
 	DLT_PPP                           = 0x9
@@ -150,20 +148,7 @@ const (
 	DT_LNK                            = 0xa
 	DT_REG                            = 0x8
 	DT_SOCK                           = 0xc
-	DT_UNKNOWN                        = 0
-	E2BIG                             = 0x7
-	EACCES                            = 0xd
-	EADDRINUSE                        = 0x30
-	EADDRNOTAVAIL                     = 0x31
-	EAFNOSUPPORT                      = 0x2f
-	EAGAIN                            = 0x23
-	EALREADY                          = 0x25
-	EAUTH                             = 0x50
-	EBADF                             = 0x9
-	EBADRPC                           = 0x48
-	EBUSY                             = 0x10
-	ECANCELED                         = 0x58
-	ECHILD                            = 0xa
+	DT_UNKNOWN                        = 0x0
 	ECHO                              = 0x8
 	ECHOCTL                           = 0x40
 	ECHOE                             = 0x2
@@ -171,88 +156,14 @@ const (
 	ECHOKE                            = 0x1
 	ECHONL                            = 0x10
 	ECHOPRT                           = 0x20
-	ECONNABORTED                      = 0x35
-	ECONNREFUSED                      = 0x3d
-	ECONNRESET                        = 0x36
-	EDEADLK                           = 0xb
-	EDESTADDRREQ                      = 0x27
-	EDOM                              = 0x21
-	EDQUOT                            = 0x45
-	EEXIST                            = 0x11
-	EFAULT                            = 0xe
-	EFBIG                             = 0x1b
 	EFER_LMA                          = 0x400
 	EFER_LME                          = 0x100
 	EFER_NXE                          = 0x800
 	EFER_SCE                          = 0x1
-	EFTYPE                            = 0x4f
-	EHOSTDOWN                         = 0x40
-	EHOSTUNREACH                      = 0x41
-	EIDRM                             = 0x59
-	EILSEQ                            = 0x54
-	EINPROGRESS                       = 0x24
-	EINTR                             = 0x4
-	EINVAL                            = 0x16
-	EIO                               = 0x5
-	EIPSEC                            = 0x52
-	EISCONN                           = 0x38
-	EISDIR                            = 0x15
-	ELAST                             = 0x5b
-	ELOOP                             = 0x3e
-	EMEDIUMTYPE                       = 0x56
-	EMFILE                            = 0x18
-	EMLINK                            = 0x1f
-	EMSGSIZE                          = 0x28
 	EMT_TAGOVF                        = 0x1
 	EMUL_ENABLED                      = 0x1
 	EMUL_NATIVE                       = 0x2
-	ENAMETOOLONG                      = 0x3f
 	ENDRUNDISC                        = 0x9
-	ENEEDAUTH                         = 0x51
-	ENETDOWN                          = 0x32
-	ENETRESET                         = 0x34
-	ENETUNREACH                       = 0x33
-	ENFILE                            = 0x17
-	ENOATTR                           = 0x53
-	ENOBUFS                           = 0x37
-	ENODEV                            = 0x13
-	ENOENT                            = 0x2
-	ENOEXEC                           = 0x8
-	ENOLCK                            = 0x4d
-	ENOMEDIUM                         = 0x55
-	ENOMEM                            = 0xc
-	ENOMSG                            = 0x5a
-	ENOPROTOOPT                       = 0x2a
-	ENOSPC                            = 0x1c
-	ENOSYS                            = 0x4e
-	ENOTBLK                           = 0xf
-	ENOTCONN                          = 0x39
-	ENOTDIR                           = 0x14
-	ENOTEMPTY                         = 0x42
-	ENOTSOCK                          = 0x26
-	ENOTSUP                           = 0x5b
-	ENOTTY                            = 0x19
-	ENXIO                             = 0x6
-	EOPNOTSUPP                        = 0x2d
-	EOVERFLOW                         = 0x57
-	EPERM                             = 0x1
-	EPFNOSUPPORT                      = 0x2e
-	EPIPE                             = 0x20
-	EPROCLIM                          = 0x43
-	EPROCUNAVAIL                      = 0x4c
-	EPROGMISMATCH                     = 0x4b
-	EPROGUNAVAIL                      = 0x4a
-	EPROTONOSUPPORT                   = 0x2b
-	EPROTOTYPE                        = 0x29
-	ERANGE                            = 0x22
-	EREMOTE                           = 0x47
-	EROFS                             = 0x1e
-	ERPCMISMATCH                      = 0x49
-	ESHUTDOWN                         = 0x3a
-	ESOCKTNOSUPPORT                   = 0x2c
-	ESPIPE                            = 0x1d
-	ESRCH                             = 0x3
-	ESTALE                            = 0x46
 	ETHERMIN                          = 0x2e
 	ETHERMTU                          = 0x5dc
 	ETHERTYPE_8023                    = 0x4
@@ -451,10 +362,6 @@ const (
 	ETHER_MIN_LEN                     = 0x40
 	ETHER_TYPE_LEN                    = 0x2
 	ETHER_VLAN_ENCAP_LEN              = 0x4
-	ETIMEDOUT                         = 0x3c
-	ETOOMANYREFS                      = 0x3b
-	ETXTBSY                           = 0x1a
-	EUSERS                            = 0x44
 	EVFILT_AIO                        = -0x3
 	EVFILT_PROC                       = -0x5
 	EVFILT_READ                       = -0x1
@@ -473,19 +380,18 @@ const (
 	EV_FLAG1                          = 0x2000
 	EV_ONESHOT                        = 0x10
 	EV_SYSFLAGS                       = 0xf000
-	EWOULDBLOCK                       = 0x23
-	EXDEV                             = 0x12
 	EXTA                              = 0x4b00
 	EXTB                              = 0x9600
 	EXTPROC                           = 0x800
 	FD_CLOEXEC                        = 0x1
 	FD_SETSIZE                        = 0x400
-	F_DUPFD                           = 0
+	F_DUPFD                           = 0x0
 	F_DUPFD_CLOEXEC                   = 0xa
 	F_GETFD                           = 0x1
 	F_GETFL                           = 0x3
 	F_GETLK                           = 0x7
 	F_GETOWN                          = 0x5
+	F_OK                              = 0x0
 	F_RDLCK                           = 0x1
 	F_SETFD                           = 0x2
 	F_SETFL                           = 0x4
@@ -767,12 +673,12 @@ const (
 	IPPROTO_FRAGMENT                  = 0x2c
 	IPPROTO_GGP                       = 0x3
 	IPPROTO_GRE                       = 0x2f
-	IPPROTO_HOPOPTS                   = 0
+	IPPROTO_HOPOPTS                   = 0x0
 	IPPROTO_ICMP                      = 0x1
 	IPPROTO_ICMPV6                    = 0x3a
 	IPPROTO_IDP                       = 0x16
 	IPPROTO_IGMP                      = 0x2
-	IPPROTO_IP                        = 0
+	IPPROTO_IP                        = 0x0
 	IPPROTO_IPCOMP                    = 0x6c
 	IPPROTO_IPIP                      = 0x4
 	IPPROTO_IPV4                      = 0x4
@@ -823,7 +729,7 @@ const (
 	IPV6_PIPEX                        = 0x3f
 	IPV6_PKTINFO                      = 0x2e
 	IPV6_PORTRANGE                    = 0xe
-	IPV6_PORTRANGE_DEFAULT            = 0
+	IPV6_PORTRANGE_DEFAULT            = 0x0
 	IPV6_PORTRANGE_HIGH               = 0x1
 	IPV6_PORTRANGE_LOW                = 0x2
 	IPV6_RECVDSTOPTS                  = 0x28
@@ -836,9 +742,9 @@ const (
 	IPV6_RTABLE                       = 0x1021
 	IPV6_RTHDR                        = 0x33
 	IPV6_RTHDRDSTOPTS                 = 0x23
-	IPV6_RTHDR_LOOSE                  = 0
+	IPV6_RTHDR_LOOSE                  = 0x0
 	IPV6_RTHDR_STRICT                 = 0x1
-	IPV6_RTHDR_TYPE_0                 = 0
+	IPV6_RTHDR_TYPE_0                 = 0x0
 	IPV6_SOCKOPT_RESERVED1            = 0x3
 	IPV6_TCLASS                       = 0x3d
 	IPV6_UNICAST_HOPS                 = 0x4
@@ -875,7 +781,7 @@ const (
 	IP_OPTIONS                        = 0x1
 	IP_PIPEX                          = 0x22
 	IP_PORTRANGE                      = 0x13
-	IP_PORTRANGE_DEFAULT              = 0
+	IP_PORTRANGE_DEFAULT              = 0x0
 	IP_PORTRANGE_HIGH                 = 0x1
 	IP_PORTRANGE_LOW                  = 0x2
 	IP_RECVDSTADDR                    = 0x7
@@ -890,6 +796,10 @@ const (
 	IP_RTABLE                         = 0x1021
 	IP_TOS                            = 0x3
 	IP_TTL                            = 0x4
+	LOCK_EX                           = 0x2
+	LOCK_NB                           = 0x4
+	LOCK_SH                           = 0x1
+	LOCK_UN                           = 0x8
 	MAP_ET_KVAGUARD                   = 0x10
 	MSG_BCAST                         = 0x100
 	MSG_CTRUNC                        = 0x20
@@ -922,16 +832,23 @@ const (
 	O_NOCTTY                          = 0x8000
 	O_NOFOLLOW                        = 0x100
 	O_NONBLOCK                        = 0x4
-	O_RDONLY                          = 0
+	O_RDONLY                          = 0x0
 	O_RDWR                            = 0x2
 	O_RSYNC                           = 0x80
 	O_SHLOCK                          = 0x10
 	O_SYNC                            = 0x80
 	O_TRUNC                           = 0x400
 	O_WRONLY                          = 0x1
+	RLIMIT_CORE                       = 0x4
+	RLIMIT_CPU                        = 0x0
+	RLIMIT_DATA                       = 0x2
+	RLIMIT_FSIZE                      = 0x1
+	RLIMIT_NOFILE                     = 0x8
+	RLIMIT_STACK                      = 0x3
+	RLIM_INFINITY                     = 0x7fffffffffffffff
 	RTAX_AUTHOR                       = 0x6
 	RTAX_BRD                          = 0x7
-	RTAX_DST                          = 0
+	RTAX_DST                          = 0x0
 	RTAX_GATEWAY                      = 0x1
 	RTAX_GENMASK                      = 0x3
 	RTAX_IFA                          = 0x5
@@ -1003,10 +920,14 @@ const (
 	RTV_RTTVAR                        = 0x80
 	RTV_SPIPE                         = 0x10
 	RTV_SSTHRESH                      = 0x20
+	RT_TABLEID_MAX                    = 0xff
+	RUSAGE_CHILDREN                   = -0x1
+	RUSAGE_SELF                       = 0x0
+	RUSAGE_THREAD                     = 0x1
 	SCM_CREDS                         = 0x2
 	SCM_RIGHTS                        = 0x1
 	SCM_TIMESTAMP                     = 0x4
-	SHUT_RD                           = 0
+	SHUT_RD                           = 0x0
 	SHUT_RDWR                         = 0x2
 	SHUT_WR                           = 0x1
 	SIGABRT                           = 0x6
@@ -1235,7 +1156,7 @@ const (
 	TIOCNXCL                          = 0x2000740e
 	TIOCOUTQ                          = 0x40047473
 	TIOCPKT                           = 0x80047470
-	TIOCPKT_DATA                      = 0
+	TIOCPKT_DATA                      = 0x0
 	TIOCPKT_DOSTOP                    = 0x20
 	TIOCPKT_FLUSHREAD                 = 0x1
 	TIOCPKT_FLUSHWRITE                = 0x2
@@ -1269,7 +1190,102 @@ const (
 	WUNTRACED                         = 0x2
 )
 
-// Types
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x30)
+	EADDRNOTAVAIL   = Errno(0x31)
+	EAFNOSUPPORT    = Errno(0x2f)
+	EAGAIN          = Errno(0x23)
+	EALREADY        = Errno(0x25)
+	EAUTH           = Errno(0x50)
+	EBADF           = Errno(0x9)
+	EBADRPC         = Errno(0x48)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x58)
+	ECHILD          = Errno(0xa)
+	ECONNABORTED    = Errno(0x35)
+	ECONNREFUSED    = Errno(0x3d)
+	ECONNRESET      = Errno(0x36)
+	EDEADLK         = Errno(0xb)
+	EDESTADDRREQ    = Errno(0x27)
+	EDOM            = Errno(0x21)
+	EDQUOT          = Errno(0x45)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EFTYPE          = Errno(0x4f)
+	EHOSTDOWN       = Errno(0x40)
+	EHOSTUNREACH    = Errno(0x41)
+	EIDRM           = Errno(0x59)
+	EILSEQ          = Errno(0x54)
+	EINPROGRESS     = Errno(0x24)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EIPSEC          = Errno(0x52)
+	EISCONN         = Errno(0x38)
+	EISDIR          = Errno(0x15)
+	ELAST           = Errno(0x5b)
+	ELOOP           = Errno(0x3e)
+	EMEDIUMTYPE     = Errno(0x56)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x28)
+	ENAMETOOLONG    = Errno(0x3f)
+	ENEEDAUTH       = Errno(0x51)
+	ENETDOWN        = Errno(0x32)
+	ENETRESET       = Errno(0x34)
+	ENETUNREACH     = Errno(0x33)
+	ENFILE          = Errno(0x17)
+	ENOATTR         = Errno(0x53)
+	ENOBUFS         = Errno(0x37)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOLCK          = Errno(0x4d)
+	ENOMEDIUM       = Errno(0x55)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x5a)
+	ENOPROTOOPT     = Errno(0x2a)
+	ENOSPC          = Errno(0x1c)
+	ENOSYS          = Errno(0x4e)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x39)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x42)
+	ENOTSOCK        = Errno(0x26)
+	ENOTSUP         = Errno(0x5b)
+	ENOTTY          = Errno(0x19)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x2d)
+	EOVERFLOW       = Errno(0x57)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x2e)
+	EPIPE           = Errno(0x20)
+	EPROCLIM        = Errno(0x43)
+	EPROCUNAVAIL    = Errno(0x4c)
+	EPROGMISMATCH   = Errno(0x4b)
+	EPROGUNAVAIL    = Errno(0x4a)
+	EPROTONOSUPPORT = Errno(0x2b)
+	EPROTOTYPE      = Errno(0x29)
+	ERANGE          = Errno(0x22)
+	EREMOTE         = Errno(0x47)
+	EROFS           = Errno(0x1e)
+	ERPCMISMATCH    = Errno(0x49)
+	ESHUTDOWN       = Errno(0x3a)
+	ESOCKTNOSUPPORT = Errno(0x2c)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESTALE          = Errno(0x46)
+	ETIMEDOUT       = Errno(0x3c)
+	ETOOMANYREFS    = Errno(0x3b)
+	ETXTBSY         = Errno(0x1a)
+	EUSERS          = Errno(0x44)
+	EWOULDBLOCK     = Errno(0x23)
+	EXDEV           = Errno(0x12)
+)
 
 // Error table
 var errors = [...]string{
diff --git a/src/pkg/syscall/zerrors_plan9_386.go b/src/pkg/syscall/zerrors_plan9_386.go
index 65198c3..694fd69 100644
--- a/src/pkg/syscall/zerrors_plan9_386.go
+++ b/src/pkg/syscall/zerrors_plan9_386.go
@@ -1,3 +1,7 @@
+// Copyright 2011 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 syscall
 
 // Constants
diff --git a/src/pkg/syscall/zerrors_windows.go b/src/pkg/syscall/zerrors_windows.go
index 799ed49..afdeae2 100644
--- a/src/pkg/syscall/zerrors_windows.go
+++ b/src/pkg/syscall/zerrors_windows.go
@@ -1,12 +1,12 @@
-// mkerrors_windows.sh -f -m32
+// mkerrors_windows.sh -m32
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
 package syscall
 
 // Go names for Windows errors.
 const (
-	ENOENT  = ERROR_FILE_NOT_FOUND
-	ENOTDIR = ERROR_PATH_NOT_FOUND
+	ENOENT  Errno = ERROR_FILE_NOT_FOUND
+	ENOTDIR Errno = ERROR_PATH_NOT_FOUND
 )
 
 // Windows reserves errors >= 1<<29 for application use.
@@ -14,7 +14,7 @@ const APPLICATION_ERROR = 1 << 29
 
 // Invented values to support what package os and others expects.
 const (
-	E2BIG = APPLICATION_ERROR + iota
+	E2BIG Errno = APPLICATION_ERROR + iota
 	EACCES
 	EADDRINUSE
 	EADDRNOTAVAIL
diff --git a/src/pkg/syscall/zsyscall_darwin_386.go b/src/pkg/syscall/zsyscall_darwin_386.go
index 6d611e8..b952ac4 100644
--- a/src/pkg/syscall/zsyscall_darwin_386.go
+++ b/src/pkg/syscall/zsyscall_darwin_386.go
@@ -7,115 +7,141 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(ngid int, gid *_Gid_t) (errno int) {
+func setgroups(ngid int, gid *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
+func socket(domain int, typ int, proto int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
 	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Shutdown(s int, how int) (errno int) {
+func Shutdown(s int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (errno int) {
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -124,13 +150,15 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
 	}
 	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -138,39 +166,47 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
 	var _p0 unsafe.Pointer
 	if len(mib) > 0 {
 		_p0 = unsafe.Pointer(&mib[0])
@@ -178,147 +214,183 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, timeval *[2]Timeval) (errno int) {
+func utimes(path string, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimes(fd int, timeval *[2]Timeval) (errno int) {
+func futimes(fd int, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func ptrace(request int, pid int, addr uintptr, data uintptr) (errno int) {
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe() (r int, w int, errno int) {
+func pipe() (r int, w int, err error) {
 	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
 	r = int(r0)
 	w = int(r1)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func kill(pid int, signum int, posix int) (errno int) {
+func kill(pid int, signum int, posix int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chflags(path string, flags int) (errno int) {
+func Chflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(fd int) (nfd int, errno int) {
+func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
 	nfd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(from int, to int) (errno int) {
+func Dup2(from int, to int) (err error) {
 	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Exchangedata(path1 string, path2 string, options int) (errno int) {
+func Exchangedata(path1 string, path2 string, options int) (err error) {
 	_, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(StringBytePtr(path1))), uintptr(unsafe.Pointer(StringBytePtr(path2))), uintptr(options))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -331,88 +403,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchflags(path string, flags int) (errno int) {
+func Fchflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fpathconf(fd int, name int) (val int, errno int) {
+func Fpathconf(fd int, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, stat *Statfs_t) (errno int) {
+func Fstatfs(fd int, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -421,7 +513,9 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -451,7 +545,7 @@ func Geteuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
+func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -460,7 +554,9 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -474,10 +570,12 @@ func Getgid() (gid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -507,35 +605,43 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpriority(which int, who int) (prio int, errno int) {
+func Getpriority(which int, who int) (prio int, err error) {
 	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
 	prio = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(which int, lim *Rlimit) (errno int) {
+func Getrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getsid(pid int) (sid int, errno int) {
+func Getsid(pid int) (sid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
 	sid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -557,90 +663,110 @@ func Issetugid() (tainted bool) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kqueue() (fd int, errno int) {
+func Kqueue() (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(path string, link string) (errno int) {
+func Link(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Listen(s int, backlog int) (errno int) {
+func Listen(s int, backlog int) (err error) {
 	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkfifo(path string, mode uint32) (errno int) {
+func Mkfifo(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Open(path string, mode int, perm uint32) (fd int, errno int) {
+func Open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pathconf(path string, name int) (val int, errno int) {
+func Pathconf(path string, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -649,13 +775,15 @@ func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -664,13 +792,15 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -679,13 +809,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -694,193 +826,241 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(from string, to string) (errno int) {
+func Rename(from string, to string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Revoke(path string) (errno int) {
+func Revoke(path string) (err error) {
 	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 	r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0)
 	newoffset = int64(int64(r1)<<32 | int64(r0))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
 	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setegid(egid int) (errno int) {
+func Setegid(egid int) (err error) {
 	_, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seteuid(euid int) (errno int) {
+func Seteuid(euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setlogin(name string) (errno int) {
+func Setlogin(name string) (err error) {
 	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpriority(which int, who int, prio int) (errno int) {
+func Setpriority(which int, who int, prio int) (err error) {
 	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setprivexec(flag int) (errno int) {
+func Setprivexec(flag int) (err error) {
 	_, _, e1 := Syscall(SYS_SETPRIVEXEC, uintptr(flag), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(which int, lim *Rlimit) (errno int) {
+func Setrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tp *Timeval) (errno int) {
+func Settimeofday(tp *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Statfs(path string, stat *Statfs_t) (errno int) {
+func Statfs(path string, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(path string, link string) (errno int) {
+func Symlink(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sync() (errno int) {
+func Sync() (err error) {
 	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -894,31 +1074,37 @@ func Umask(newmask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Undelete(path string) (errno int) {
+func Undelete(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(path string, flags int) (errno int) {
+func Unmount(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -927,51 +1113,63 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
 	r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0)
 	ret = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, errno int) {
+func read(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, errno int) {
+func write(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func gettimeofday(tp *Timeval) (sec int32, usec int32, errno int) {
+func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
 	r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
 	sec = int32(r0)
 	usec = int32(r1)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_darwin_amd64.go b/src/pkg/syscall/zsyscall_darwin_amd64.go
index e26fed4..104ee55 100644
--- a/src/pkg/syscall/zsyscall_darwin_amd64.go
+++ b/src/pkg/syscall/zsyscall_darwin_amd64.go
@@ -7,115 +7,141 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(ngid int, gid *_Gid_t) (errno int) {
+func setgroups(ngid int, gid *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
+func socket(domain int, typ int, proto int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
 	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Shutdown(s int, how int) (errno int) {
+func Shutdown(s int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (errno int) {
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -124,13 +150,15 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
 	}
 	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -138,39 +166,47 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
 	var _p0 unsafe.Pointer
 	if len(mib) > 0 {
 		_p0 = unsafe.Pointer(&mib[0])
@@ -178,147 +214,183 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, timeval *[2]Timeval) (errno int) {
+func utimes(path string, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimes(fd int, timeval *[2]Timeval) (errno int) {
+func futimes(fd int, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func ptrace(request int, pid int, addr uintptr, data uintptr) (errno int) {
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe() (r int, w int, errno int) {
+func pipe() (r int, w int, err error) {
 	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
 	r = int(r0)
 	w = int(r1)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func kill(pid int, signum int, posix int) (errno int) {
+func kill(pid int, signum int, posix int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), uintptr(posix))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chflags(path string, flags int) (errno int) {
+func Chflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(fd int) (nfd int, errno int) {
+func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
 	nfd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(from int, to int) (errno int) {
+func Dup2(from int, to int) (err error) {
 	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Exchangedata(path1 string, path2 string, options int) (errno int) {
+func Exchangedata(path1 string, path2 string, options int) (err error) {
 	_, _, e1 := Syscall(SYS_EXCHANGEDATA, uintptr(unsafe.Pointer(StringBytePtr(path1))), uintptr(unsafe.Pointer(StringBytePtr(path2))), uintptr(options))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -331,88 +403,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchflags(path string, flags int) (errno int) {
+func Fchflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fpathconf(fd int, name int) (val int, errno int) {
+func Fpathconf(fd int, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, stat *Statfs_t) (errno int) {
+func Fstatfs(fd int, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -421,7 +513,9 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -451,7 +545,7 @@ func Geteuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
+func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -460,7 +554,9 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -474,10 +570,12 @@ func Getgid() (gid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -507,35 +605,43 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpriority(which int, who int) (prio int, errno int) {
+func Getpriority(which int, who int) (prio int, err error) {
 	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
 	prio = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(which int, lim *Rlimit) (errno int) {
+func Getrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getsid(pid int) (sid int, errno int) {
+func Getsid(pid int) (sid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
 	sid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -557,90 +663,110 @@ func Issetugid() (tainted bool) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kqueue() (fd int, errno int) {
+func Kqueue() (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(path string, link string) (errno int) {
+func Link(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Listen(s int, backlog int) (errno int) {
+func Listen(s int, backlog int) (err error) {
 	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkfifo(path string, mode uint32) (errno int) {
+func Mkfifo(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Open(path string, mode int, perm uint32) (fd int, errno int) {
+func Open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pathconf(path string, name int) (val int, errno int) {
+func Pathconf(path string, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -649,13 +775,15 @@ func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -664,13 +792,15 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -679,13 +809,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -694,193 +826,241 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(from string, to string) (errno int) {
+func Rename(from string, to string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Revoke(path string) (errno int) {
+func Revoke(path string) (err error) {
 	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 	r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
 	newoffset = int64(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
 	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setegid(egid int) (errno int) {
+func Setegid(egid int) (err error) {
 	_, _, e1 := Syscall(SYS_SETEGID, uintptr(egid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seteuid(euid int) (errno int) {
+func Seteuid(euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setlogin(name string) (errno int) {
+func Setlogin(name string) (err error) {
 	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpriority(which int, who int, prio int) (errno int) {
+func Setpriority(which int, who int, prio int) (err error) {
 	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setprivexec(flag int) (errno int) {
+func Setprivexec(flag int) (err error) {
 	_, _, e1 := Syscall(SYS_SETPRIVEXEC, uintptr(flag), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(which int, lim *Rlimit) (errno int) {
+func Setrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tp *Timeval) (errno int) {
+func Settimeofday(tp *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Statfs(path string, stat *Statfs_t) (errno int) {
+func Statfs(path string, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(path string, link string) (errno int) {
+func Symlink(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sync() (errno int) {
+func Sync() (err error) {
 	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -894,31 +1074,37 @@ func Umask(newmask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Undelete(path string) (errno int) {
+func Undelete(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(path string, flags int) (errno int) {
+func Unmount(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -927,51 +1113,63 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
 	r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos))
 	ret = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, errno int) {
+func read(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, errno int) {
+func write(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func gettimeofday(tp *Timeval) (sec int64, usec int32, errno int) {
+func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) {
 	r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
 	sec = int64(r0)
 	usec = int32(r1)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_freebsd_386.go b/src/pkg/syscall/zsyscall_freebsd_386.go
index 2cf6cba..d219a8d 100644
--- a/src/pkg/syscall/zsyscall_freebsd_386.go
+++ b/src/pkg/syscall/zsyscall_freebsd_386.go
@@ -7,115 +7,141 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(ngid int, gid *_Gid_t) (errno int) {
+func setgroups(ngid int, gid *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
+func socket(domain int, typ int, proto int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
 	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Shutdown(s int, how int) (errno int) {
+func Shutdown(s int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (errno int) {
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -124,13 +150,15 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
 	}
 	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -138,39 +166,47 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
 	var _p0 unsafe.Pointer
 	if len(mib) > 0 {
 		_p0 = unsafe.Pointer(&mib[0])
@@ -178,123 +214,153 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, timeval *[2]Timeval) (errno int) {
+func utimes(path string, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimes(fd int, timeval *[2]Timeval) (errno int) {
+func futimes(fd int, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe() (r int, w int, errno int) {
+func pipe() (r int, w int, err error) {
 	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
 	r = int(r0)
 	w = int(r1)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chflags(path string, flags int) (errno int) {
+func Chflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(fd int) (nfd int, errno int) {
+func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
 	nfd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(from int, to int) (errno int) {
+func Dup2(from int, to int) (err error) {
 	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -307,88 +373,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchflags(path string, flags int) (errno int) {
+func Fchflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fpathconf(fd int, name int) (val int, errno int) {
+func Fpathconf(fd int, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, stat *Statfs_t) (errno int) {
+func Fstatfs(fd int, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), uintptr(length>>32))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -397,7 +483,9 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -427,7 +515,7 @@ func Geteuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
+func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -436,7 +524,9 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -450,10 +540,12 @@ func Getgid() (gid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -483,43 +575,53 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpriority(which int, who int) (prio int, errno int) {
+func Getpriority(which int, who int) (prio int, err error) {
 	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
 	prio = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(which int, lim *Rlimit) (errno int) {
+func Getrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getsid(pid int) (sid int, errno int) {
+func Getsid(pid int) (sid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
 	sid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Gettimeofday(tv *Timeval) (errno int) {
+func Gettimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -541,106 +643,130 @@ func Issetugid() (tainted bool) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, signum int) (errno int) {
+func Kill(pid int, signum int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kqueue() (fd int, errno int) {
+func Kqueue() (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(path string, link string) (errno int) {
+func Link(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Listen(s int, backlog int) (errno int) {
+func Listen(s int, backlog int) (err error) {
 	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkfifo(path string, mode uint32) (errno int) {
+func Mkfifo(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Nanosleep(time *Timespec, leftover *Timespec) (errno int) {
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Open(path string, mode int, perm uint32) (fd int, errno int) {
+func Open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pathconf(path string, name int) (val int, errno int) {
+func Pathconf(path string, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -649,13 +775,15 @@ func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -664,13 +792,15 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -679,13 +809,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -694,185 +826,231 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(from string, to string) (errno int) {
+func Rename(from string, to string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Revoke(path string) (errno int) {
+func Revoke(path string) (err error) {
 	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 	r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(offset>>32), uintptr(whence), 0, 0)
 	newoffset = int64(int64(r1)<<32 | int64(r0))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
 	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setegid(egid int) (errno int) {
+func Setegid(egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seteuid(euid int) (errno int) {
+func Seteuid(euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setlogin(name string) (errno int) {
+func Setlogin(name string) (err error) {
 	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpriority(which int, who int, prio int) (errno int) {
+func Setpriority(which int, who int, prio int) (err error) {
 	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(which int, lim *Rlimit) (errno int) {
+func Setrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tp *Timeval) (errno int) {
+func Settimeofday(tp *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Statfs(path string, stat *Statfs_t) (errno int) {
+func Statfs(path string, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(path string, link string) (errno int) {
+func Symlink(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sync() (errno int) {
+func Sync() (err error) {
 	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -886,31 +1064,37 @@ func Umask(newmask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Undelete(path string) (errno int) {
+func Undelete(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(path string, flags int) (errno int) {
+func Unmount(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -919,41 +1103,51 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
 	r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0)
 	ret = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, errno int) {
+func read(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, errno int) {
+func write(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_freebsd_amd64.go b/src/pkg/syscall/zsyscall_freebsd_amd64.go
index bdbfae9..0e0feaf 100644
--- a/src/pkg/syscall/zsyscall_freebsd_amd64.go
+++ b/src/pkg/syscall/zsyscall_freebsd_amd64.go
@@ -7,115 +7,141 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(ngid int, gid *_Gid_t) (errno int) {
+func setgroups(ngid int, gid *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
+func socket(domain int, typ int, proto int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
 	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Shutdown(s int, how int) (errno int) {
+func Shutdown(s int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (errno int) {
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -124,13 +150,15 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
 	}
 	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -138,39 +166,47 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
 	var _p0 unsafe.Pointer
 	if len(mib) > 0 {
 		_p0 = unsafe.Pointer(&mib[0])
@@ -178,123 +214,153 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, timeval *[2]Timeval) (errno int) {
+func utimes(path string, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimes(fd int, timeval *[2]Timeval) (errno int) {
+func futimes(fd int, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe() (r int, w int, errno int) {
+func pipe() (r int, w int, err error) {
 	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
 	r = int(r0)
 	w = int(r1)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chflags(path string, flags int) (errno int) {
+func Chflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(fd int) (nfd int, errno int) {
+func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
 	nfd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(from int, to int) (errno int) {
+func Dup2(from int, to int) (err error) {
 	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -307,88 +373,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchflags(path string, flags int) (errno int) {
+func Fchflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fpathconf(fd int, name int) (val int, errno int) {
+func Fpathconf(fd int, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, stat *Statfs_t) (errno int) {
+func Fstatfs(fd int, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -397,7 +483,9 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -427,7 +515,7 @@ func Geteuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
+func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -436,7 +524,9 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -450,10 +540,12 @@ func Getgid() (gid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -483,43 +575,53 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpriority(which int, who int) (prio int, errno int) {
+func Getpriority(which int, who int) (prio int, err error) {
 	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
 	prio = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(which int, lim *Rlimit) (errno int) {
+func Getrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getsid(pid int) (sid int, errno int) {
+func Getsid(pid int) (sid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
 	sid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Gettimeofday(tv *Timeval) (errno int) {
+func Gettimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -541,106 +643,130 @@ func Issetugid() (tainted bool) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, signum int) (errno int) {
+func Kill(pid int, signum int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kqueue() (fd int, errno int) {
+func Kqueue() (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(path string, link string) (errno int) {
+func Link(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Listen(s int, backlog int) (errno int) {
+func Listen(s int, backlog int) (err error) {
 	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkfifo(path string, mode uint32) (errno int) {
+func Mkfifo(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Nanosleep(time *Timespec, leftover *Timespec) (errno int) {
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Open(path string, mode int, perm uint32) (fd int, errno int) {
+func Open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pathconf(path string, name int) (val int, errno int) {
+func Pathconf(path string, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -649,13 +775,15 @@ func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -664,13 +792,15 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -679,13 +809,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -694,185 +826,231 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(from string, to string) (errno int) {
+func Rename(from string, to string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Revoke(path string) (errno int) {
+func Revoke(path string) (err error) {
 	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 	r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
 	newoffset = int64(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
 	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setegid(egid int) (errno int) {
+func Setegid(egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seteuid(euid int) (errno int) {
+func Seteuid(euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setlogin(name string) (errno int) {
+func Setlogin(name string) (err error) {
 	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpriority(which int, who int, prio int) (errno int) {
+func Setpriority(which int, who int, prio int) (err error) {
 	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(which int, lim *Rlimit) (errno int) {
+func Setrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tp *Timeval) (errno int) {
+func Settimeofday(tp *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Statfs(path string, stat *Statfs_t) (errno int) {
+func Statfs(path string, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(path string, link string) (errno int) {
+func Symlink(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sync() (errno int) {
+func Sync() (err error) {
 	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -886,31 +1064,37 @@ func Umask(newmask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Undelete(path string) (errno int) {
+func Undelete(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNDELETE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(path string, flags int) (errno int) {
+func Unmount(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -919,41 +1103,51 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
 	r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos))
 	ret = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, errno int) {
+func read(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, errno int) {
+func write(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_linux_386.go b/src/pkg/syscall/zsyscall_linux_386.go
index 4eb522a..8c3a844 100644
--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -7,49 +7,59 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func open(path string, mode int, perm uint32) (fd int, errno int) {
+func open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int) {
+func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
 	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), uintptr(mode), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe(p *[2]_C_int) (errno int) {
+func pipe(p *[2]_C_int) (err error) {
 	_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, times *[2]Timeval) (errno int) {
+func utimes(path string, times *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(times)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimesat(dirfd int, path *byte, times *[2]Timeval) (errno int) {
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getcwd(buf []byte) (n int, errno int) {
+func Getcwd(buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -58,139 +68,192 @@ func Getcwd(buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func ptrace(request int, pid int, addr uintptr, data uintptr) (errno int) {
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func reboot(magic1 uint, magic2 uint, cmd int, arg string) (errno int) {
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
 	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(StringBytePtr(arg))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Acct(path string) (errno int) {
+func Acct(path string) (err error) {
 	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtimex(buf *Timex) (state int, errno int) {
+func Adjtimex(buf *Timex) (state int, err error) {
 	r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
 	state = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Creat(path string, mode uint32) (fd int, errno int) {
+func Creat(path string, mode uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(oldfd int) (fd int, errno int) {
+func Dup(oldfd int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(oldfd), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (fd int, errno int) {
+func Dup2(oldfd int, newfd int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollCreate(size int) (fd int, errno int) {
+func EpollCreate(size int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int) {
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
 	_, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int) {
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(events) > 0 {
 		_p0 = unsafe.Pointer(&events[0])
@@ -199,7 +262,9 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -212,88 +277,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Faccessat(dirfd int, path string, mode uint32, flags int) (errno int) {
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fallocate(fd int, mode uint32, off int64, len int64) (errno int) {
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
 	_, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(off>>32), uintptr(len), uintptr(len>>32))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int) {
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int) {
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fdatasync(fd int) (errno int) {
+func Fdatasync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdents(fd int, buf []byte) (n int, errno int) {
+func Getdents(fd int, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -302,16 +387,20 @@ func Getdents(fd int, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -341,17 +430,21 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(resource int, rlim *Rlimit) (errno int) {
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -365,51 +458,61 @@ func Gettid() (tid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, errno int) {
+func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
 	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(StringBytePtr(pathname))), uintptr(mask))
 	watchdesc = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyInit() (fd int, errno int) {
+func InotifyInit() (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyInit1(flags int) (fd int, errno int) {
+func InotifyInit1(flags int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int) {
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
 	success = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, sig int) (errno int) {
+func Kill(pid int, sig int) (err error) {
 	_, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Klogctl(typ int, buf []byte) (n int, errno int) {
+func Klogctl(typ int, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -418,85 +521,95 @@ func Klogctl(typ int, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(oldpath string, newpath string) (errno int) {
+func Link(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdirat(dirfd int, path string, mode uint32) (errno int) {
+func Mkdirat(dirfd int, path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknodat(dirfd int, path string, mode uint32, dev int) (errno int) {
+func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev), 0, 0)
-	errno = int(e1)
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Mount(source string, target string, fstype string, flags int, data string) (errno int) {
-	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(StringBytePtr(data))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Nanosleep(time *Timespec, leftover *Timespec) (errno int) {
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pause() (errno int) {
+func Pause() (err error) {
 	_, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func PivotRoot(newroot string, putold string) (errno int) {
+func PivotRoot(newroot string, putold string) (err error) {
 	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(StringBytePtr(newroot))), uintptr(unsafe.Pointer(StringBytePtr(putold))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -505,13 +618,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -520,37 +635,45 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(oldpath string, newpath string) (errno int) {
+func Rename(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int) {
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
 	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(newdirfd), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setdomainname(p []byte) (errno int) {
+func Setdomainname(p []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -558,13 +681,15 @@ func Setdomainname(p []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sethostname(p []byte) (errno int) {
+func Sethostname(p []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -572,56 +697,70 @@ func Sethostname(p []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(resource int, rlim *Rlimit) (errno int) {
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tv *Timeval) (errno int) {
+func Settimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(oldpath string, newpath string) (errno int) {
+func Symlink(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -634,35 +773,43 @@ func Sync() {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sysinfo(info *Sysinfo_t) (errno int) {
+func Sysinfo(info *Sysinfo_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Tee(rfd int, wfd int, len int, flags int) (n int64, errno int) {
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
 	r0, r1, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
 	n = int64(int64(r1)<<32 | int64(r0))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Tgkill(tgid int, tid int, sig int) (errno int) {
+func Tgkill(tgid int, tid int, sig int) (err error) {
 	_, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Times(tms *Tms) (ticks uintptr, errno int) {
+func Times(tms *Tms) (ticks uintptr, err error) {
 	r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
 	ticks = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -676,63 +823,77 @@ func Umask(mask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Uname(buf *Utsname) (errno int) {
+func Uname(buf *Utsname) (err error) {
 	_, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlinkat(dirfd int, path string) (errno int) {
+func Unlinkat(dirfd int, path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(target string, flags int) (errno int) {
+func Unmount(target string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unshare(flags int) (errno int) {
+func Unshare(flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ustat(dev int, ubuf *Ustat_t) (errno int) {
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
 	_, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Utime(path string, buf *Utimbuf) (errno int) {
+func Utime(path string, buf *Utimbuf) (err error) {
 	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -741,47 +902,57 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func exitThread(code int) (errno int) {
+func exitThread(code int) (err error) {
 	_, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, p *byte, np int) (n int, errno int) {
+func read(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, p *byte, np int) (n int, errno int) {
+func write(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Madvise(b []byte, advice int) (errno int) {
+func Madvise(b []byte, advice int) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -789,13 +960,15 @@ func Madvise(b []byte, advice int) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mprotect(b []byte, prot int) (errno int) {
+func Mprotect(b []byte, prot int) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -803,13 +976,15 @@ func Mprotect(b []byte, prot int) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mlock(b []byte) (errno int) {
+func Mlock(b []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -817,13 +992,15 @@ func Mlock(b []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Munlock(b []byte) (errno int) {
+func Munlock(b []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -831,55 +1008,69 @@ func Munlock(b []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mlockall(flags int) (errno int) {
+func Mlockall(flags int) (err error) {
 	_, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Munlockall() (errno int) {
+func Munlockall() (err error) {
 	_, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN32, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_FTRUNCATE64, uintptr(fd), uintptr(length), uintptr(length>>32))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -917,39 +1108,47 @@ func Getuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ioperm(from int, num int, on int) (errno int) {
+func Ioperm(from int, num int, on int) (err error) {
 	_, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Iopl(level int) (errno int) {
+func Iopl(level int) (err error) {
 	_, _, e1 := Syscall(SYS_IOPL, uintptr(level), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -958,13 +1157,15 @@ func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -973,156 +1174,194 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	r0, _, e1 := Syscall6(SYS_SENDFILE64, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
 	written = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setfsgid(gid int) (errno int) {
+func Setfsgid(gid int) (err error) {
 	_, _, e1 := Syscall(SYS_SETFSGID32, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setfsuid(uid int) (errno int) {
+func Setfsuid(uid int) (err error) {
 	_, _, e1 := Syscall(SYS_SETFSUID32, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID32, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID32, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setresgid(rgid int, egid int, sgid int) (errno int) {
+func Setresgid(rgid int, egid int, sgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRESGID32, uintptr(rgid), uintptr(egid), uintptr(sgid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setresuid(ruid int, euid int, suid int) (errno int) {
+func Setresuid(ruid int, euid int, suid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRESUID32, uintptr(ruid), uintptr(euid), uintptr(suid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID32, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, errno int) {
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func SyncFileRange(fd int, off int64, n int64, flags int) (errno int) {
+func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE, uintptr(fd), uintptr(off), uintptr(off>>32), uintptr(n), uintptr(n>>32), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_TRUNCATE64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), uintptr(length>>32))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(n int, list *_Gid_t) (nn int, errno int) {
+func getgroups(n int, list *_Gid_t) (nn int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS32, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
 	nn = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(n int, list *_Gid_t) (errno int) {
+func setgroups(n int, list *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS32, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int) {
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS__NEWSELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, errno int) {
+func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) {
 	r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset))
 	xaddr = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Gettimeofday(tv *Timeval) (errno int) {
+func Gettimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Time(t *Time_t) (tt Time_t, errno int) {
+func Time(t *Time_t) (tt Time_t, err error) {
 	r0, _, e1 := RawSyscall(SYS_TIME, uintptr(unsafe.Pointer(t)), 0, 0)
 	tt = Time_t(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_linux_amd64.go b/src/pkg/syscall/zsyscall_linux_amd64.go
index 999ed64..c53fff7 100644
--- a/src/pkg/syscall/zsyscall_linux_amd64.go
+++ b/src/pkg/syscall/zsyscall_linux_amd64.go
@@ -7,49 +7,59 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func open(path string, mode int, perm uint32) (fd int, errno int) {
+func open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int) {
+func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
 	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), uintptr(mode), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe(p *[2]_C_int) (errno int) {
+func pipe(p *[2]_C_int) (err error) {
 	_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, times *[2]Timeval) (errno int) {
+func utimes(path string, times *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(times)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimesat(dirfd int, path *byte, times *[2]Timeval) (errno int) {
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getcwd(buf []byte) (n int, errno int) {
+func Getcwd(buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -58,139 +68,192 @@ func Getcwd(buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func ptrace(request int, pid int, addr uintptr, data uintptr) (errno int) {
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func reboot(magic1 uint, magic2 uint, cmd int, arg string) (errno int) {
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
 	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(StringBytePtr(arg))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Acct(path string) (errno int) {
+func Acct(path string) (err error) {
 	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtimex(buf *Timex) (state int, errno int) {
+func Adjtimex(buf *Timex) (state int, err error) {
 	r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
 	state = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Creat(path string, mode uint32) (fd int, errno int) {
+func Creat(path string, mode uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(oldfd int) (fd int, errno int) {
+func Dup(oldfd int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(oldfd), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (fd int, errno int) {
+func Dup2(oldfd int, newfd int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollCreate(size int) (fd int, errno int) {
+func EpollCreate(size int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int) {
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
 	_, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int) {
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(events) > 0 {
 		_p0 = unsafe.Pointer(&events[0])
@@ -199,7 +262,9 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -212,88 +277,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Faccessat(dirfd int, path string, mode uint32, flags int) (errno int) {
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fallocate(fd int, mode uint32, off int64, len int64) (errno int) {
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
 	_, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(len), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int) {
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int) {
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fdatasync(fd int) (errno int) {
+func Fdatasync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdents(fd int, buf []byte) (n int, errno int) {
+func Getdents(fd int, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -302,16 +387,20 @@ func Getdents(fd int, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -341,17 +430,21 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(resource int, rlim *Rlimit) (errno int) {
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -365,51 +458,61 @@ func Gettid() (tid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, errno int) {
+func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
 	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(StringBytePtr(pathname))), uintptr(mask))
 	watchdesc = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyInit() (fd int, errno int) {
+func InotifyInit() (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyInit1(flags int) (fd int, errno int) {
+func InotifyInit1(flags int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int) {
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
 	success = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, sig int) (errno int) {
+func Kill(pid int, sig int) (err error) {
 	_, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Klogctl(typ int, buf []byte) (n int, errno int) {
+func Klogctl(typ int, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -418,85 +521,95 @@ func Klogctl(typ int, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(oldpath string, newpath string) (errno int) {
+func Link(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdirat(dirfd int, path string, mode uint32) (errno int) {
+func Mkdirat(dirfd int, path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknodat(dirfd int, path string, mode uint32, dev int) (errno int) {
+func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev), 0, 0)
-	errno = int(e1)
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Mount(source string, target string, fstype string, flags int, data string) (errno int) {
-	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(StringBytePtr(data))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Nanosleep(time *Timespec, leftover *Timespec) (errno int) {
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pause() (errno int) {
+func Pause() (err error) {
 	_, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func PivotRoot(newroot string, putold string) (errno int) {
+func PivotRoot(newroot string, putold string) (err error) {
 	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(StringBytePtr(newroot))), uintptr(unsafe.Pointer(StringBytePtr(putold))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -505,13 +618,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -520,37 +635,45 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(oldpath string, newpath string) (errno int) {
+func Rename(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int) {
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
 	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(newdirfd), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setdomainname(p []byte) (errno int) {
+func Setdomainname(p []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -558,13 +681,15 @@ func Setdomainname(p []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sethostname(p []byte) (errno int) {
+func Sethostname(p []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -572,56 +697,70 @@ func Sethostname(p []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(resource int, rlim *Rlimit) (errno int) {
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tv *Timeval) (errno int) {
+func Settimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(oldpath string, newpath string) (errno int) {
+func Symlink(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -634,35 +773,43 @@ func Sync() {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sysinfo(info *Sysinfo_t) (errno int) {
+func Sysinfo(info *Sysinfo_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Tee(rfd int, wfd int, len int, flags int) (n int64, errno int) {
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
 	r0, _, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
 	n = int64(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Tgkill(tgid int, tid int, sig int) (errno int) {
+func Tgkill(tgid int, tid int, sig int) (err error) {
 	_, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Times(tms *Tms) (ticks uintptr, errno int) {
+func Times(tms *Tms) (ticks uintptr, err error) {
 	r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
 	ticks = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -676,63 +823,77 @@ func Umask(mask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Uname(buf *Utsname) (errno int) {
+func Uname(buf *Utsname) (err error) {
 	_, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlinkat(dirfd int, path string) (errno int) {
+func Unlinkat(dirfd int, path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(target string, flags int) (errno int) {
+func Unmount(target string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unshare(flags int) (errno int) {
+func Unshare(flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ustat(dev int, ubuf *Ustat_t) (errno int) {
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
 	_, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Utime(path string, buf *Utimbuf) (errno int) {
+func Utime(path string, buf *Utimbuf) (err error) {
 	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -741,47 +902,57 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func exitThread(code int) (errno int) {
+func exitThread(code int) (err error) {
 	_, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, p *byte, np int) (n int, errno int) {
+func read(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, p *byte, np int) (n int, errno int) {
+func write(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Madvise(b []byte, advice int) (errno int) {
+func Madvise(b []byte, advice int) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -789,13 +960,15 @@ func Madvise(b []byte, advice int) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mprotect(b []byte, prot int) (errno int) {
+func Mprotect(b []byte, prot int) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -803,13 +976,15 @@ func Mprotect(b []byte, prot int) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mlock(b []byte) (errno int) {
+func Mlock(b []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -817,13 +992,15 @@ func Mlock(b []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Munlock(b []byte) (errno int) {
+func Munlock(b []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -831,63 +1008,79 @@ func Munlock(b []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mlockall(flags int) (errno int) {
+func Mlockall(flags int) (err error) {
 	_, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Munlockall() (errno int) {
+func Munlockall() (err error) {
 	_, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, buf *Statfs_t) (errno int) {
+func Fstatfs(fd int, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -925,47 +1118,57 @@ func Getuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ioperm(from int, num int, on int) (errno int) {
+func Ioperm(from int, num int, on int) (err error) {
 	_, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Iopl(level int) (errno int) {
+func Iopl(level int) (err error) {
 	_, _, e1 := Syscall(SYS_IOPL, uintptr(level), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Listen(s int, n int) (errno int) {
+func Listen(s int, n int) (err error) {
 	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -974,13 +1177,15 @@ func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -989,236 +1194,292 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seek(fd int, offset int64, whence int) (off int64, errno int) {
+func Seek(fd int, offset int64, whence int) (off int64, err error) {
 	r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
 	off = int64(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int) {
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
 	written = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setfsgid(gid int) (errno int) {
+func Setfsgid(gid int) (err error) {
 	_, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setfsuid(uid int) (errno int) {
+func Setfsuid(uid int) (err error) {
 	_, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setresgid(rgid int, egid int, sgid int) (errno int) {
+func Setresgid(rgid int, egid int, sgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setresuid(ruid int, euid int, suid int) (errno int) {
+func Setresuid(ruid int, euid int, suid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Shutdown(fd int, how int) (errno int) {
+func Shutdown(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, errno int) {
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
 	r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
 	n = int64(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Statfs(path string, buf *Statfs_t) (errno int) {
+func Statfs(path string, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func SyncFileRange(fd int, off int64, n int64, flags int) (errno int) {
+func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(n int, list *_Gid_t) (nn int, errno int) {
+func getgroups(n int, list *_Gid_t) (nn int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
 	nn = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(n int, list *_Gid_t) (errno int) {
+func setgroups(n int, list *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
 	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
+func socket(domain int, typ int, proto int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (errno int) {
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -1227,13 +1488,15 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
 	}
 	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -1241,32 +1504,40 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int) {
+func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
 	r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
 	xaddr = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_linux_arm.go b/src/pkg/syscall/zsyscall_linux_arm.go
index cd49dab..d739139 100644
--- a/src/pkg/syscall/zsyscall_linux_arm.go
+++ b/src/pkg/syscall/zsyscall_linux_arm.go
@@ -7,49 +7,59 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func open(path string, mode int, perm uint32) (fd int, errno int) {
+func open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int) {
+func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
 	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), uintptr(mode), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe(p *[2]_C_int) (errno int) {
+func pipe(p *[2]_C_int) (err error) {
 	_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, times *[2]Timeval) (errno int) {
+func utimes(path string, times *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(times)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimesat(dirfd int, path *byte, times *[2]Timeval) (errno int) {
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getcwd(buf []byte) (n int, errno int) {
+func Getcwd(buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -58,139 +68,192 @@ func Getcwd(buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func ptrace(request int, pid int, addr uintptr, data uintptr) (errno int) {
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func reboot(magic1 uint, magic2 uint, cmd int, arg string) (errno int) {
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
 	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(StringBytePtr(arg))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Acct(path string) (errno int) {
+func Acct(path string) (err error) {
 	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtimex(buf *Timex) (state int, errno int) {
+func Adjtimex(buf *Timex) (state int, err error) {
 	r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
 	state = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Creat(path string, mode uint32) (fd int, errno int) {
+func Creat(path string, mode uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_CREAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(oldfd int) (fd int, errno int) {
+func Dup(oldfd int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(oldfd), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(oldfd int, newfd int) (fd int, errno int) {
+func Dup2(oldfd int, newfd int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollCreate(size int) (fd int, errno int) {
+func EpollCreate(size int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int) {
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
 	_, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int) {
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(events) > 0 {
 		_p0 = unsafe.Pointer(&events[0])
@@ -199,7 +262,9 @@ func EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -212,88 +277,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Faccessat(dirfd int, path string, mode uint32, flags int) (errno int) {
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fallocate(fd int, mode uint32, off int64, len int64) (errno int) {
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
 	_, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off>>32), uintptr(off), uintptr(len>>32), uintptr(len))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int) {
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int) {
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
 	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fdatasync(fd int) (errno int) {
+func Fdatasync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdents(fd int, buf []byte) (n int, errno int) {
+func Getdents(fd int, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -302,16 +387,20 @@ func Getdents(fd int, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -341,17 +430,21 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(resource int, rlim *Rlimit) (errno int) {
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -365,51 +458,61 @@ func Gettid() (tid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, errno int) {
+func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
 	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(StringBytePtr(pathname))), uintptr(mask))
 	watchdesc = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyInit() (fd int, errno int) {
+func InotifyInit() (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyInit1(flags int) (fd int, errno int) {
+func InotifyInit1(flags int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int) {
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
 	r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
 	success = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, sig int) (errno int) {
+func Kill(pid int, sig int) (err error) {
 	_, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Klogctl(typ int, buf []byte) (n int, errno int) {
+func Klogctl(typ int, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -418,85 +521,95 @@ func Klogctl(typ int, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(oldpath string, newpath string) (errno int) {
+func Link(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdirat(dirfd int, path string, mode uint32) (errno int) {
+func Mkdirat(dirfd int, path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknodat(dirfd int, path string, mode uint32, dev int) (errno int) {
+func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev), 0, 0)
-	errno = int(e1)
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Mount(source string, target string, fstype string, flags int, data string) (errno int) {
-	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(StringBytePtr(source))), uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(unsafe.Pointer(StringBytePtr(fstype))), uintptr(flags), uintptr(unsafe.Pointer(StringBytePtr(data))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Nanosleep(time *Timespec, leftover *Timespec) (errno int) {
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pause() (errno int) {
+func Pause() (err error) {
 	_, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func PivotRoot(newroot string, putold string) (errno int) {
+func PivotRoot(newroot string, putold string) (err error) {
 	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(StringBytePtr(newroot))), uintptr(unsafe.Pointer(StringBytePtr(putold))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -505,13 +618,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -520,37 +635,45 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(oldpath string, newpath string) (errno int) {
+func Rename(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int) {
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
 	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(newdirfd), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setdomainname(p []byte) (errno int) {
+func Setdomainname(p []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -558,13 +681,15 @@ func Setdomainname(p []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sethostname(p []byte) (errno int) {
+func Sethostname(p []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -572,56 +697,70 @@ func Sethostname(p []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(resource int, rlim *Rlimit) (errno int) {
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tv *Timeval) (errno int) {
+func Settimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(oldpath string, newpath string) (errno int) {
+func Symlink(oldpath string, newpath string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(oldpath))), uintptr(unsafe.Pointer(StringBytePtr(newpath))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -634,35 +773,43 @@ func Sync() {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sysinfo(info *Sysinfo_t) (errno int) {
+func Sysinfo(info *Sysinfo_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Tee(rfd int, wfd int, len int, flags int) (n int64, errno int) {
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
 	r0, r1, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
 	n = int64(int64(r0)<<32 | int64(r1))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Tgkill(tgid int, tid int, sig int) (errno int) {
+func Tgkill(tgid int, tid int, sig int) (err error) {
 	_, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Times(tms *Tms) (ticks uintptr, errno int) {
+func Times(tms *Tms) (ticks uintptr, err error) {
 	r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
 	ticks = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -676,63 +823,77 @@ func Umask(mask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Uname(buf *Utsname) (errno int) {
+func Uname(buf *Utsname) (err error) {
 	_, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlinkat(dirfd int, path string) (errno int) {
+func Unlinkat(dirfd int, path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(StringBytePtr(path))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(target string, flags int) (errno int) {
+func Unmount(target string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(StringBytePtr(target))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unshare(flags int) (errno int) {
+func Unshare(flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ustat(dev int, ubuf *Ustat_t) (errno int) {
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
 	_, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Utime(path string, buf *Utimbuf) (errno int) {
+func Utime(path string, buf *Utimbuf) (err error) {
 	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -741,47 +902,57 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func exitThread(code int) (errno int) {
+func exitThread(code int) (err error) {
 	_, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, p *byte, np int) (n int, errno int) {
+func read(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, p *byte, np int) (n int, errno int) {
+func write(fd int, p *byte, np int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Madvise(b []byte, advice int) (errno int) {
+func Madvise(b []byte, advice int) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -789,13 +960,15 @@ func Madvise(b []byte, advice int) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mprotect(b []byte, prot int) (errno int) {
+func Mprotect(b []byte, prot int) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -803,13 +976,15 @@ func Mprotect(b []byte, prot int) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mlock(b []byte) (errno int) {
+func Mlock(b []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -817,13 +992,15 @@ func Mlock(b []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Munlock(b []byte) (errno int) {
+func Munlock(b []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(b) > 0 {
 		_p0 = unsafe.Pointer(&b[0])
@@ -831,112 +1008,138 @@ func Munlock(b []byte) (errno int) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mlockall(flags int) (errno int) {
+func Mlockall(flags int) (err error) {
 	_, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Munlockall() (errno int) {
+func Munlockall() (err error) {
 	_, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(n int, list *_Gid_t) (nn int, errno int) {
+func getgroups(n int, list *_Gid_t) (nn int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS32, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
 	nn = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(n int, list *_Gid_t) (errno int) {
+func setgroups(n int, list *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS32, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
 	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
+func socket(domain int, typ int, proto int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -945,13 +1148,15 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
 	}
 	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -959,64 +1164,80 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, flags int, fd *[2]int) (errno int) {
+func socketpair(domain int, typ int, flags int, fd *[2]int) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, buf *Statfs_t) (errno int) {
+func Fstatfs(fd int, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS64, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -1054,157 +1275,195 @@ func Getuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Listen(s int, n int) (errno int) {
+func Listen(s int, n int) (err error) {
 	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	r0, _, e1 := Syscall6(SYS_SENDFILE64, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
 	written = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int) {
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS__NEWSELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setfsgid(gid int) (errno int) {
+func Setfsgid(gid int) (err error) {
 	_, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setfsuid(uid int) (errno int) {
+func Setfsuid(uid int) (err error) {
 	_, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setresgid(rgid int, egid int, sgid int) (errno int) {
+func Setresgid(rgid int, egid int, sgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setresuid(ruid int, euid int, suid int) (errno int) {
+func Setresuid(ruid int, euid int, suid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Shutdown(fd int, how int) (errno int) {
+func Shutdown(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, errno int) {
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Statfs(path string, buf *Statfs_t) (errno int) {
+func Statfs(path string, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(buf)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Gettimeofday(tv *Timeval) (errno int) {
+func Gettimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Time(t *Time_t) (tt Time_t, errno int) {
+func Time(t *Time_t) (tt Time_t, err error) {
 	r0, _, e1 := RawSyscall(SYS_TIME, uintptr(unsafe.Pointer(t)), 0, 0)
 	tt = Time_t(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, errno int) {
+func mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) {
 	r0, _, e1 := Syscall6(SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset))
 	xaddr = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_netbsd_386.go b/src/pkg/syscall/zsyscall_netbsd_386.go
new file mode 100644
index 0000000..6155a16
--- /dev/null
+++ b/src/pkg/syscall/zsyscall_netbsd_386.go
@@ -0,0 +1,1086 @@
+// mksyscall.pl -l32 -netbsd syscall_bsd.go syscall_netbsd.go syscall_netbsd_386.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(ngid int, gid *_Gid_t) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
+	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+	wpid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
+	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
+	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Shutdown(s int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
+	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
+	var _p0 unsafe.Pointer
+	if len(mib) > 0 {
+		_p0 = unsafe.Pointer(&mib[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, timeval *[2]Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimes(fd int, timeval *[2]Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe2(p *[2]_C_int, flags _C_int) (err error) {
+	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getdents(fd int, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Access(path string, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chflags(path string, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chmod(path string, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chown(path string, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(fd int) (nfd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
+	nfd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup2(from int, to int) (err error) {
+	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+	Syscall(SYS_EXIT, uintptr(code), 0, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchflags(path string, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Flock(fd int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fpathconf(fd int, name int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, stat *Stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fsync(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ftruncate(fd int, length int64) (err error) {
+	_, _, e1 := Syscall6(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+	r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
+	egid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+	r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+	gid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
+	pgid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgrp() (pgrp int) {
+	r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0)
+	pgrp = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+	r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+	pid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (ppid int) {
+	r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0)
+	ppid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
+	prio = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrusage(who int, rusage *Rusage) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getsid(pid int) (sid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
+	sid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Issetugid() (tainted bool) {
+	r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0)
+	tainted = bool(r0 != 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, signum int) (err error) {
+	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kqueue() (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Link(path string, link string) (err error) {
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, backlog int) (err error) {
+	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lstat(path string, stat *Stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdir(path string, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkfifo(path string, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknod(path string, mode uint32, dev int) (err error) {
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Open(path string, mode int, perm uint32) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pathconf(path string, name int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Read(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Readlink(path string, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Rename(from string, to string) (err error) {
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Revoke(path string) (err error) {
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Rmdir(path string) (err error) {
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
+	r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), uintptr(whence), 0)
+	newoffset = int64(int64(r1)<<32 | int64(r0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
+	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setegid(egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seteuid(euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setgid(gid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpgid(pid int, pgid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpriority(which int, who int, prio int) (err error) {
+	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setregid(rgid int, egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setreuid(ruid int, euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Settimeofday(tp *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setuid(uid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Stat(path string, stat *Stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Symlink(path string, link string) (err error) {
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sync() (err error) {
+	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Truncate(path string, length int64) (err error) {
+	_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length), uintptr(length>>32), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(newmask int) (oldmask int) {
+	r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0)
+	oldmask = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unlink(path string) (err error) {
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(path string, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Write(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
+	r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), uintptr(pos>>32), 0)
+	ret = uintptr(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func munmap(addr uintptr, length uintptr) (err error) {
+	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func write(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
diff --git a/src/pkg/syscall/zsyscall_netbsd_amd64.go b/src/pkg/syscall/zsyscall_netbsd_amd64.go
new file mode 100644
index 0000000..d68cd86
--- /dev/null
+++ b/src/pkg/syscall/zsyscall_netbsd_amd64.go
@@ -0,0 +1,1086 @@
+// mksyscall.pl -netbsd syscall_bsd.go syscall_netbsd.go syscall_netbsd_amd64.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(ngid int, gid *_Gid_t) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
+	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+	wpid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
+	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
+	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Shutdown(s int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
+	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
+	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
+	var _p0 unsafe.Pointer
+	if len(mib) > 0 {
+		_p0 = unsafe.Pointer(&mib[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, timeval *[2]Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimes(fd int, timeval *[2]Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe2(p *[2]_C_int, flags _C_int) (err error) {
+	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getdents(fd int, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Access(path string, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chflags(path string, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chmod(path string, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chown(path string, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(fd int) (nfd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
+	nfd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup2(from int, to int) (err error) {
+	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+	Syscall(SYS_EXIT, uintptr(code), 0, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchflags(path string, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Flock(fd int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fpathconf(fd int, name int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstat(fd int, stat *Stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fsync(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ftruncate(fd int, length int64) (err error) {
+	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+	r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
+	egid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+	r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+	gid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
+	pgid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgrp() (pgrp int) {
+	r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0)
+	pgrp = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+	r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+	pid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (ppid int) {
+	r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0)
+	ppid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
+	prio = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrusage(who int, rusage *Rusage) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getsid(pid int) (sid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
+	sid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Issetugid() (tainted bool) {
+	r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0)
+	tainted = bool(r0 != 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, signum int) (err error) {
+	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kqueue() (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Link(path string, link string) (err error) {
+	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, backlog int) (err error) {
+	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lstat(path string, stat *Stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdir(path string, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkfifo(path string, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknod(path string, mode uint32, dev int) (err error) {
+	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Open(path string, mode int, perm uint32) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pathconf(path string, name int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Read(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Readlink(path string, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Rename(from string, to string) (err error) {
+	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Revoke(path string) (err error) {
+	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Rmdir(path string) (err error) {
+	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
+	r0, _, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(whence), 0, 0)
+	newoffset = int64(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
+	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setegid(egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seteuid(euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setgid(gid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpgid(pid int, pgid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpriority(which int, who int, prio int) (err error) {
+	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setregid(rgid int, egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setreuid(ruid int, euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Settimeofday(tp *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setuid(uid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Stat(path string, stat *Stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Symlink(path string, link string) (err error) {
+	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sync() (err error) {
+	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Truncate(path string, length int64) (err error) {
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(newmask int) (oldmask int) {
+	r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0)
+	oldmask = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unlink(path string) (err error) {
+	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(path string, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Write(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
+	r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), 0, 0)
+	ret = uintptr(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func munmap(addr uintptr, length uintptr) (err error) {
+	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func write(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
diff --git a/src/pkg/syscall/zsyscall_openbsd_386.go b/src/pkg/syscall/zsyscall_openbsd_386.go
index ca390cc..7855c21 100644
--- a/src/pkg/syscall/zsyscall_openbsd_386.go
+++ b/src/pkg/syscall/zsyscall_openbsd_386.go
@@ -7,115 +7,141 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(ngid int, gid *_Gid_t) (errno int) {
+func setgroups(ngid int, gid *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
+func socket(domain int, typ int, proto int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
 	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Shutdown(s int, how int) (errno int) {
+func Shutdown(s int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (errno int) {
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -124,13 +150,15 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
 	}
 	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -138,39 +166,47 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
 	var _p0 unsafe.Pointer
 	if len(mib) > 0 {
 		_p0 = unsafe.Pointer(&mib[0])
@@ -178,121 +214,151 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, timeval *[2]Timeval) (errno int) {
+func utimes(path string, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimes(fd int, timeval *[2]Timeval) (errno int) {
+func futimes(fd int, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe(p *[2]_C_int) (errno int) {
+func pipe(p *[2]_C_int) (err error) {
 	_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chflags(path string, flags int) (errno int) {
+func Chflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(fd int) (nfd int, errno int) {
+func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
 	nfd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(from int, to int) (errno int) {
+func Dup2(from int, to int) (err error) {
 	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -305,88 +371,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchflags(path string, flags int) (errno int) {
+func Fchflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fpathconf(fd int, name int) (val int, errno int) {
+func Fpathconf(fd int, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, stat *Statfs_t) (errno int) {
+func Fstatfs(fd int, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall6(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length), uintptr(length>>32), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -395,7 +481,9 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -417,7 +505,7 @@ func Geteuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
+func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -426,7 +514,9 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -440,10 +530,12 @@ func Getgid() (gid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -473,43 +565,53 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpriority(which int, who int) (prio int, errno int) {
+func Getpriority(which int, who int) (prio int, err error) {
 	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
 	prio = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(which int, lim *Rlimit) (errno int) {
+func Getrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getsid(pid int) (sid int, errno int) {
+func Getsid(pid int) (sid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
 	sid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Gettimeofday(tv *Timeval) (errno int) {
+func Gettimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -531,106 +633,130 @@ func Issetugid() (tainted bool) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, signum int) (errno int) {
+func Kill(pid int, signum int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kqueue() (fd int, errno int) {
+func Kqueue() (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(path string, link string) (errno int) {
+func Link(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Listen(s int, backlog int) (errno int) {
+func Listen(s int, backlog int) (err error) {
 	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkfifo(path string, mode uint32) (errno int) {
+func Mkfifo(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Nanosleep(time *Timespec, leftover *Timespec) (errno int) {
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Open(path string, mode int, perm uint32) (fd int, errno int) {
+func Open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pathconf(path string, name int) (val int, errno int) {
+func Pathconf(path string, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -639,13 +765,15 @@ func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -654,13 +782,15 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), uintptr(offset>>32))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -669,13 +799,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -684,185 +816,231 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(from string, to string) (errno int) {
+func Rename(from string, to string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Revoke(path string) (errno int) {
+func Revoke(path string) (err error) {
 	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 	r0, r1, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(offset>>32), uintptr(whence), 0)
 	newoffset = int64(int64(r1)<<32 | int64(r0))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
 	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setegid(egid int) (errno int) {
+func Setegid(egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seteuid(euid int) (errno int) {
+func Seteuid(euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setlogin(name string) (errno int) {
+func Setlogin(name string) (err error) {
 	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpriority(which int, who int, prio int) (errno int) {
+func Setpriority(which int, who int, prio int) (err error) {
 	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(which int, lim *Rlimit) (errno int) {
+func Setrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tp *Timeval) (errno int) {
+func Settimeofday(tp *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Statfs(path string, stat *Statfs_t) (errno int) {
+func Statfs(path string, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(path string, link string) (errno int) {
+func Symlink(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sync() (errno int) {
+func Sync() (err error) {
 	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall6(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length), uintptr(length>>32), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -876,23 +1054,27 @@ func Umask(newmask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(path string, flags int) (errno int) {
+func Unmount(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -901,41 +1083,51 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
 	r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), uintptr(pos>>32), 0)
 	ret = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, errno int) {
+func read(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, errno int) {
+func write(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_openbsd_amd64.go b/src/pkg/syscall/zsyscall_openbsd_amd64.go
index 94ce290..8040750 100644
--- a/src/pkg/syscall/zsyscall_openbsd_amd64.go
+++ b/src/pkg/syscall/zsyscall_openbsd_amd64.go
@@ -7,115 +7,141 @@ import "unsafe"
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getgroups(ngid int, gid *_Gid_t) (n int, errno int) {
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setgroups(ngid int, gid *_Gid_t) (errno int) {
+func setgroups(ngid int, gid *_Gid_t) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, errno int) {
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
 	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
 	wpid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, errno int) {
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func bind(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func bind(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connect(s int, addr uintptr, addrlen _Socklen) (errno int) {
+func connect(s int, addr uintptr, addrlen _Socklen) (err error) {
 	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socket(domain int, typ int, proto int) (fd int, errno int) {
+func socket(domain int, typ int, proto int) (fd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (errno int) {
+func getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) {
 	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (errno int) {
+func setsockopt(s int, level int, name int, val uintptr, vallen uintptr) (err error) {
 	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (errno int) {
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Shutdown(s int, how int) (errno int) {
+func Shutdown(s int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(s), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func socketpair(domain int, typ int, proto int, fd *[2]int) (errno int) {
+func socketpair(domain int, typ int, proto int, fd *[2]int) (err error) {
 	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, errno int) {
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -124,13 +150,15 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl
 	}
 	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno int) {
+func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -138,39 +166,47 @@ func sendto(s int, buf []byte, flags int, to uintptr, addrlen _Socklen) (errno i
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
+func sendmsg(s int, msg *Msghdr, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, errno int) {
+func kevent(kq int, change uintptr, nchange int, event uintptr, nevent int, timeout *Timespec) (n int, err error) {
 	r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (errno int) {
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
 	var _p0 unsafe.Pointer
 	if len(mib) > 0 {
 		_p0 = unsafe.Pointer(&mib[0])
@@ -178,121 +214,151 @@ func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr)
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	_, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func utimes(path string, timeval *[2]Timeval) (errno int) {
+func utimes(path string, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func futimes(fd int, timeval *[2]Timeval) (errno int) {
+func futimes(fd int, timeval *[2]Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fcntl(fd int, cmd int, arg int) (val int, errno int) {
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe(p *[2]_C_int) (errno int) {
+func pipe(p *[2]_C_int) (err error) {
 	_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Access(path string, mode uint32) (errno int) {
+func Access(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Adjtime(delta *Timeval, olddelta *Timeval) (errno int) {
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
 	_, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (errno int) {
+func Chdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chflags(path string, flags int) (errno int) {
+func Chflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chmod(path string, mode uint32) (errno int) {
+func Chmod(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chown(path string, uid int, gid int) (errno int) {
+func Chown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chroot(path string) (errno int) {
+func Chroot(path string) (err error) {
 	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (errno int) {
+func Close(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(fd int) (nfd int, errno int) {
+func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := RawSyscall(SYS_DUP, uintptr(fd), 0, 0)
 	nfd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup2(from int, to int) (errno int) {
+func Dup2(from int, to int) (err error) {
 	_, _, e1 := RawSyscall(SYS_DUP2, uintptr(from), uintptr(to), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -305,88 +371,108 @@ func Exit(code int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchdir(fd int) (errno int) {
+func Fchdir(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchflags(path string, flags int) (errno int) {
+func Fchflags(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchmod(fd int, mode uint32) (errno int) {
+func Fchmod(fd int, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fchown(fd int, uid int, gid int) (errno int) {
+func Fchown(fd int, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Flock(fd int, how int) (errno int) {
+func Flock(fd int, how int) (err error) {
 	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fpathconf(fd int, name int) (val int, errno int) {
+func Fpathconf(fd int, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, stat *Stat_t) (errno int) {
+func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstatfs(fd int, stat *Statfs_t) (errno int) {
+func Fstatfs(fd int, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fsync(fd int) (errno int) {
+func Fsync(fd int) (err error) {
 	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Ftruncate(fd int, length int64) (errno int) {
+func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -395,7 +481,9 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -417,7 +505,7 @@ func Geteuid() (uid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
+func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -426,7 +514,9 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -440,10 +530,12 @@ func Getgid() (gid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpgid(pid int) (pgid int, errno int) {
+func Getpgid(pid int) (pgid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
 	pgid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -473,43 +565,53 @@ func Getppid() (ppid int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getpriority(which int, who int) (prio int, errno int) {
+func Getpriority(which int, who int) (prio int, err error) {
 	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
 	prio = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrlimit(which int, lim *Rlimit) (errno int) {
+func Getrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getrusage(who int, rusage *Rusage) (errno int) {
+func Getrusage(who int, rusage *Rusage) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getsid(pid int) (sid int, errno int) {
+func Getsid(pid int) (sid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0)
 	sid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Gettimeofday(tv *Timeval) (errno int) {
+func Gettimeofday(tv *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -531,106 +633,130 @@ func Issetugid() (tainted bool) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kill(pid int, signum int) (errno int) {
+func Kill(pid int, signum int) (err error) {
 	_, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Kqueue() (fd int, errno int) {
+func Kqueue() (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0)
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lchown(path string, uid int, gid int) (errno int) {
+func Lchown(path string, uid int, gid int) (err error) {
 	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Link(path string, link string) (errno int) {
+func Link(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Listen(s int, backlog int) (errno int) {
+func Listen(s int, backlog int) (err error) {
 	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Lstat(path string, stat *Stat_t) (errno int) {
+func Lstat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkdir(path string, mode uint32) (errno int) {
+func Mkdir(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mkfifo(path string, mode uint32) (errno int) {
+func Mkfifo(path string, mode uint32) (err error) {
 	_, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mknod(path string, mode uint32, dev int) (errno int) {
+func Mknod(path string, mode uint32, dev int) (err error) {
 	_, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(dev))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Nanosleep(time *Timespec, leftover *Timespec) (errno int) {
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
 	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Open(path string, mode int, perm uint32) (fd int, errno int) {
+func Open(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pathconf(path string, name int) (val int, errno int) {
+func Pathconf(path string, name int) (val int, err error) {
 	r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(name), 0)
 	val = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -639,13 +765,15 @@ func Pread(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -654,13 +782,15 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0)
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Read(fd int, p []byte) (n int, errno int) {
+func Read(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -669,13 +799,15 @@ func Read(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Readlink(path string, buf []byte) (n int, errno int) {
+func Readlink(path string, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -684,185 +816,231 @@ func Readlink(path string, buf []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(buf)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rename(from string, to string) (errno int) {
+func Rename(from string, to string) (err error) {
 	_, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(StringBytePtr(from))), uintptr(unsafe.Pointer(StringBytePtr(to))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Revoke(path string) (errno int) {
+func Revoke(path string) (err error) {
 	_, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Rmdir(path string) (errno int) {
+func Rmdir(path string) (err error) {
 	_, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 	r0, _, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(whence), 0, 0)
 	newoffset = int64(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (errno int) {
+func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) {
 	_, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setegid(egid int) (errno int) {
+func Setegid(egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Seteuid(euid int) (errno int) {
+func Seteuid(euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setgid(gid int) (errno int) {
+func Setgid(gid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setlogin(name string) (errno int) {
+func Setlogin(name string) (err error) {
 	_, _, e1 := Syscall(SYS_SETLOGIN, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpgid(pid int, pgid int) (errno int) {
+func Setpgid(pid int, pgid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setpriority(which int, who int, prio int) (errno int) {
+func Setpriority(which int, who int, prio int) (err error) {
 	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setregid(rgid int, egid int) (errno int) {
+func Setregid(rgid int, egid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setreuid(ruid int, euid int) (errno int) {
+func Setreuid(ruid int, euid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setrlimit(which int, lim *Rlimit) (errno int) {
+func Setrlimit(which int, lim *Rlimit) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setsid() (pid int, errno int) {
+func Setsid() (pid int, err error) {
 	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
 	pid = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Settimeofday(tp *Timeval) (errno int) {
+func Settimeofday(tp *Timeval) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Setuid(uid int) (errno int) {
+func Setuid(uid int) (err error) {
 	_, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, stat *Stat_t) (errno int) {
+func Stat(path string, stat *Stat_t) (err error) {
 	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Statfs(path string, stat *Statfs_t) (errno int) {
+func Statfs(path string, stat *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Symlink(path string, link string) (errno int) {
+func Symlink(path string, link string) (err error) {
 	_, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(StringBytePtr(link))), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Sync() (errno int) {
+func Sync() (err error) {
 	_, _, e1 := Syscall(SYS_SYNC, 0, 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Truncate(path string, length int64) (errno int) {
+func Truncate(path string, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, uintptr(length))
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
@@ -876,23 +1054,27 @@ func Umask(newmask int) (oldmask int) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unlink(path string) (errno int) {
+func Unlink(path string) (err error) {
 	_, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Unmount(path string, flags int) (errno int) {
+func Unmount(path string, flags int) (err error) {
 	_, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(flags), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Write(fd int, p []byte) (n int, errno int) {
+func Write(fd int, p []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -901,41 +1083,51 @@ func Write(fd int, p []byte) (n int, errno int) {
 	}
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) {
 	r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), 0, 0)
 	ret = uintptr(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func munmap(addr uintptr, length uintptr) (errno int) {
+func munmap(addr uintptr, length uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func read(fd int, buf *byte, nbuf int) (n int, errno int) {
+func read(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func write(fd int, buf *byte, nbuf int) (n int, errno int) {
+func write(fd int, buf *byte, nbuf int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
 	n = int(r0)
-	errno = int(e1)
+	if e1 != 0 {
+		err = e1
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_plan9_386.go b/src/pkg/syscall/zsyscall_plan9_386.go
index 75c411a..913c28f 100644
--- a/src/pkg/syscall/zsyscall_plan9_386.go
+++ b/src/pkg/syscall/zsyscall_plan9_386.go
@@ -14,7 +14,7 @@ func exits(msg *byte) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func fd2path(fd int, buf []byte) (err Error) {
+func fd2path(fd int, buf []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])
@@ -22,38 +22,25 @@ func fd2path(fd int, buf []byte) (err Error) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe(p *[2]_C_int) (err Error) {
+func pipe(p *[2]_C_int) (err error) {
 	r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func sleep(millisecs int32) (err Error) {
-	r0, _, e1 := Syscall(SYS_SLEEP, uintptr(millisecs), 0, 0)
-	err = nil
-	if int(r0) == -1 {
-		err = NewError(e1)
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func await(s []byte) (n int, err Error) {
+func await(s []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(s) > 0 {
 		_p0 = unsafe.Pointer(&s[0])
@@ -62,63 +49,58 @@ func await(s []byte) (n int, err Error) {
 	}
 	r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0)
 	n = int(r0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Dup(oldfd int, newfd int) (fd int, err Error) {
+func Dup(oldfd int, newfd int) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0)
 	fd = int(r0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Open(path string, mode int) (fd int, err Error) {
+func Open(path string, mode int) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
 	fd = int(r0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Create(path string, mode int, perm uint32) (fd int, err Error) {
+func Create(path string, mode int, perm uint32) (fd int, err error) {
 	r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
 	fd = int(r0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Remove(path string) (err Error) {
+func Remove(path string) (err error) {
 	r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pread(fd int, p []byte, offset int64) (n int, err Error) {
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -127,16 +109,15 @@ func Pread(fd int, p []byte, offset int64) (n int, err Error) {
 	}
 	r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
 	n = int(r0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Pwrite(fd int, p []byte, offset int64) (n int, err Error) {
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(p) > 0 {
 		_p0 = unsafe.Pointer(&p[0])
@@ -145,60 +126,55 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err Error) {
 	}
 	r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
 	n = int(r0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Close(fd int) (err Error) {
+func Close(fd int) (err error) {
 	r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Chdir(path string) (err Error) {
+func Chdir(path string) (err error) {
 	r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(StringBytePtr(path))), 0, 0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Bind(name string, old string, flag int) (err Error) {
+func Bind(name string, old string, flag int) (err error) {
 	r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag))
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Mount(fd int, afd int, old string, flag int, aname string) (err Error) {
+func Mount(fd int, afd int, old string, flag int, aname string) (err error) {
 	r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(StringBytePtr(old))), uintptr(flag), uintptr(unsafe.Pointer(StringBytePtr(aname))), 0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Stat(path string, edir []byte) (n int, err Error) {
+func Stat(path string, edir []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(edir) > 0 {
 		_p0 = unsafe.Pointer(&edir[0])
@@ -207,16 +183,15 @@ func Stat(path string, edir []byte) (n int, err Error) {
 	}
 	r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
 	n = int(r0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fstat(fd int, edir []byte) (n int, err Error) {
+func Fstat(fd int, edir []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(edir) > 0 {
 		_p0 = unsafe.Pointer(&edir[0])
@@ -225,16 +200,15 @@ func Fstat(fd int, edir []byte) (n int, err Error) {
 	}
 	r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
 	n = int(r0)
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Wstat(path string, edir []byte) (err Error) {
+func Wstat(path string, edir []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(edir) > 0 {
 		_p0 = unsafe.Pointer(&edir[0])
@@ -242,16 +216,15 @@ func Wstat(path string, edir []byte) (err Error) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(_p0), uintptr(len(edir)))
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Fwstat(fd int, edir []byte) (err Error) {
+func Fwstat(fd int, edir []byte) (err error) {
 	var _p0 unsafe.Pointer
 	if len(edir) > 0 {
 		_p0 = unsafe.Pointer(&edir[0])
@@ -259,9 +232,8 @@ func Fwstat(fd int, edir []byte) (err Error) {
 		_p0 = unsafe.Pointer(&_zero)
 	}
 	r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir)))
-	err = nil
 	if int(r0) == -1 {
-		err = NewError(e1)
+		err = e1
 	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_windows_386.go b/src/pkg/syscall/zsyscall_windows_386.go
index 845004a..5550975 100644
--- a/src/pkg/syscall/zsyscall_windows_386.go
+++ b/src/pkg/syscall/zsyscall_windows_386.go
@@ -10,169 +10,174 @@ var (
 	modadvapi32 = NewLazyDLL("advapi32.dll")
 	modshell32  = NewLazyDLL("shell32.dll")
 	modmswsock  = NewLazyDLL("mswsock.dll")
+	modcrypt32  = NewLazyDLL("crypt32.dll")
 	modws2_32   = NewLazyDLL("ws2_32.dll")
 	moddnsapi   = NewLazyDLL("dnsapi.dll")
 	modiphlpapi = NewLazyDLL("iphlpapi.dll")
 
-	procGetLastError               = modkernel32.NewProc("GetLastError")
-	procLoadLibraryW               = modkernel32.NewProc("LoadLibraryW")
-	procFreeLibrary                = modkernel32.NewProc("FreeLibrary")
-	procGetProcAddress             = modkernel32.NewProc("GetProcAddress")
-	procGetVersion                 = modkernel32.NewProc("GetVersion")
-	procFormatMessageW             = modkernel32.NewProc("FormatMessageW")
-	procExitProcess                = modkernel32.NewProc("ExitProcess")
-	procCreateFileW                = modkernel32.NewProc("CreateFileW")
-	procReadFile                   = modkernel32.NewProc("ReadFile")
-	procWriteFile                  = modkernel32.NewProc("WriteFile")
-	procSetFilePointer             = modkernel32.NewProc("SetFilePointer")
-	procCloseHandle                = modkernel32.NewProc("CloseHandle")
-	procGetStdHandle               = modkernel32.NewProc("GetStdHandle")
-	procFindFirstFileW             = modkernel32.NewProc("FindFirstFileW")
-	procFindNextFileW              = modkernel32.NewProc("FindNextFileW")
-	procFindClose                  = modkernel32.NewProc("FindClose")
-	procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle")
-	procGetCurrentDirectoryW       = modkernel32.NewProc("GetCurrentDirectoryW")
-	procSetCurrentDirectoryW       = modkernel32.NewProc("SetCurrentDirectoryW")
-	procCreateDirectoryW           = modkernel32.NewProc("CreateDirectoryW")
-	procRemoveDirectoryW           = modkernel32.NewProc("RemoveDirectoryW")
-	procDeleteFileW                = modkernel32.NewProc("DeleteFileW")
-	procMoveFileW                  = modkernel32.NewProc("MoveFileW")
-	procGetComputerNameW           = modkernel32.NewProc("GetComputerNameW")
-	procSetEndOfFile               = modkernel32.NewProc("SetEndOfFile")
-	procGetSystemTimeAsFileTime    = modkernel32.NewProc("GetSystemTimeAsFileTime")
-	procSleep                      = modkernel32.NewProc("Sleep")
-	procGetTimeZoneInformation     = modkernel32.NewProc("GetTimeZoneInformation")
-	procCreateIoCompletionPort     = modkernel32.NewProc("CreateIoCompletionPort")
-	procGetQueuedCompletionStatus  = modkernel32.NewProc("GetQueuedCompletionStatus")
-	procCancelIo                   = modkernel32.NewProc("CancelIo")
-	procCreateProcessW             = modkernel32.NewProc("CreateProcessW")
-	procOpenProcess                = modkernel32.NewProc("OpenProcess")
-	procTerminateProcess           = modkernel32.NewProc("TerminateProcess")
-	procGetExitCodeProcess         = modkernel32.NewProc("GetExitCodeProcess")
-	procGetStartupInfoW            = modkernel32.NewProc("GetStartupInfoW")
-	procGetCurrentProcess          = modkernel32.NewProc("GetCurrentProcess")
-	procDuplicateHandle            = modkernel32.NewProc("DuplicateHandle")
-	procWaitForSingleObject        = modkernel32.NewProc("WaitForSingleObject")
-	procGetTempPathW               = modkernel32.NewProc("GetTempPathW")
-	procCreatePipe                 = modkernel32.NewProc("CreatePipe")
-	procGetFileType                = modkernel32.NewProc("GetFileType")
-	procCryptAcquireContextW       = modadvapi32.NewProc("CryptAcquireContextW")
-	procCryptReleaseContext        = modadvapi32.NewProc("CryptReleaseContext")
-	procCryptGenRandom             = modadvapi32.NewProc("CryptGenRandom")
-	procGetEnvironmentStringsW     = modkernel32.NewProc("GetEnvironmentStringsW")
-	procFreeEnvironmentStringsW    = modkernel32.NewProc("FreeEnvironmentStringsW")
-	procGetEnvironmentVariableW    = modkernel32.NewProc("GetEnvironmentVariableW")
-	procSetEnvironmentVariableW    = modkernel32.NewProc("SetEnvironmentVariableW")
-	procSetFileTime                = modkernel32.NewProc("SetFileTime")
-	procGetFileAttributesW         = modkernel32.NewProc("GetFileAttributesW")
-	procSetFileAttributesW         = modkernel32.NewProc("SetFileAttributesW")
-	procGetFileAttributesExW       = modkernel32.NewProc("GetFileAttributesExW")
-	procGetCommandLineW            = modkernel32.NewProc("GetCommandLineW")
-	procCommandLineToArgvW         = modshell32.NewProc("CommandLineToArgvW")
-	procLocalFree                  = modkernel32.NewProc("LocalFree")
-	procSetHandleInformation       = modkernel32.NewProc("SetHandleInformation")
-	procFlushFileBuffers           = modkernel32.NewProc("FlushFileBuffers")
-	procGetFullPathNameW           = modkernel32.NewProc("GetFullPathNameW")
-	procCreateFileMappingW         = modkernel32.NewProc("CreateFileMappingW")
-	procMapViewOfFile              = modkernel32.NewProc("MapViewOfFile")
-	procUnmapViewOfFile            = modkernel32.NewProc("UnmapViewOfFile")
-	procFlushViewOfFile            = modkernel32.NewProc("FlushViewOfFile")
-	procVirtualLock                = modkernel32.NewProc("VirtualLock")
-	procVirtualUnlock              = modkernel32.NewProc("VirtualUnlock")
-	procTransmitFile               = modmswsock.NewProc("TransmitFile")
-	procWSAStartup                 = modws2_32.NewProc("WSAStartup")
-	procWSACleanup                 = modws2_32.NewProc("WSACleanup")
-	procWSAIoctl                   = modws2_32.NewProc("WSAIoctl")
-	procsocket                     = modws2_32.NewProc("socket")
-	procsetsockopt                 = modws2_32.NewProc("setsockopt")
-	procbind                       = modws2_32.NewProc("bind")
-	procconnect                    = modws2_32.NewProc("connect")
-	procgetsockname                = modws2_32.NewProc("getsockname")
-	procgetpeername                = modws2_32.NewProc("getpeername")
-	proclisten                     = modws2_32.NewProc("listen")
-	procshutdown                   = modws2_32.NewProc("shutdown")
-	procclosesocket                = modws2_32.NewProc("closesocket")
-	procAcceptEx                   = modmswsock.NewProc("AcceptEx")
-	procGetAcceptExSockaddrs       = modmswsock.NewProc("GetAcceptExSockaddrs")
-	procWSARecv                    = modws2_32.NewProc("WSARecv")
-	procWSASend                    = modws2_32.NewProc("WSASend")
-	procWSARecvFrom                = modws2_32.NewProc("WSARecvFrom")
-	procWSASendTo                  = modws2_32.NewProc("WSASendTo")
-	procgethostbyname              = modws2_32.NewProc("gethostbyname")
-	procgetservbyname              = modws2_32.NewProc("getservbyname")
-	procntohs                      = modws2_32.NewProc("ntohs")
-	procDnsQuery_W                 = moddnsapi.NewProc("DnsQuery_W")
-	procDnsRecordListFree          = moddnsapi.NewProc("DnsRecordListFree")
-	procGetIfEntry                 = modiphlpapi.NewProc("GetIfEntry")
-	procGetAdaptersInfo            = modiphlpapi.NewProc("GetAdaptersInfo")
+	procGetLastError                = modkernel32.NewProc("GetLastError")
+	procLoadLibraryW                = modkernel32.NewProc("LoadLibraryW")
+	procFreeLibrary                 = modkernel32.NewProc("FreeLibrary")
+	procGetProcAddress              = modkernel32.NewProc("GetProcAddress")
+	procGetVersion                  = modkernel32.NewProc("GetVersion")
+	procFormatMessageW              = modkernel32.NewProc("FormatMessageW")
+	procExitProcess                 = modkernel32.NewProc("ExitProcess")
+	procCreateFileW                 = modkernel32.NewProc("CreateFileW")
+	procReadFile                    = modkernel32.NewProc("ReadFile")
+	procWriteFile                   = modkernel32.NewProc("WriteFile")
+	procSetFilePointer              = modkernel32.NewProc("SetFilePointer")
+	procCloseHandle                 = modkernel32.NewProc("CloseHandle")
+	procGetStdHandle                = modkernel32.NewProc("GetStdHandle")
+	procFindFirstFileW              = modkernel32.NewProc("FindFirstFileW")
+	procFindNextFileW               = modkernel32.NewProc("FindNextFileW")
+	procFindClose                   = modkernel32.NewProc("FindClose")
+	procGetFileInformationByHandle  = modkernel32.NewProc("GetFileInformationByHandle")
+	procGetCurrentDirectoryW        = modkernel32.NewProc("GetCurrentDirectoryW")
+	procSetCurrentDirectoryW        = modkernel32.NewProc("SetCurrentDirectoryW")
+	procCreateDirectoryW            = modkernel32.NewProc("CreateDirectoryW")
+	procRemoveDirectoryW            = modkernel32.NewProc("RemoveDirectoryW")
+	procDeleteFileW                 = modkernel32.NewProc("DeleteFileW")
+	procMoveFileW                   = modkernel32.NewProc("MoveFileW")
+	procGetComputerNameW            = modkernel32.NewProc("GetComputerNameW")
+	procSetEndOfFile                = modkernel32.NewProc("SetEndOfFile")
+	procGetSystemTimeAsFileTime     = modkernel32.NewProc("GetSystemTimeAsFileTime")
+	procGetTimeZoneInformation      = modkernel32.NewProc("GetTimeZoneInformation")
+	procCreateIoCompletionPort      = modkernel32.NewProc("CreateIoCompletionPort")
+	procGetQueuedCompletionStatus   = modkernel32.NewProc("GetQueuedCompletionStatus")
+	procPostQueuedCompletionStatus  = modkernel32.NewProc("PostQueuedCompletionStatus")
+	procCancelIo                    = modkernel32.NewProc("CancelIo")
+	procCreateProcessW              = modkernel32.NewProc("CreateProcessW")
+	procOpenProcess                 = modkernel32.NewProc("OpenProcess")
+	procTerminateProcess            = modkernel32.NewProc("TerminateProcess")
+	procGetExitCodeProcess          = modkernel32.NewProc("GetExitCodeProcess")
+	procGetStartupInfoW             = modkernel32.NewProc("GetStartupInfoW")
+	procGetCurrentProcess           = modkernel32.NewProc("GetCurrentProcess")
+	procDuplicateHandle             = modkernel32.NewProc("DuplicateHandle")
+	procWaitForSingleObject         = modkernel32.NewProc("WaitForSingleObject")
+	procGetTempPathW                = modkernel32.NewProc("GetTempPathW")
+	procCreatePipe                  = modkernel32.NewProc("CreatePipe")
+	procGetFileType                 = modkernel32.NewProc("GetFileType")
+	procCryptAcquireContextW        = modadvapi32.NewProc("CryptAcquireContextW")
+	procCryptReleaseContext         = modadvapi32.NewProc("CryptReleaseContext")
+	procCryptGenRandom              = modadvapi32.NewProc("CryptGenRandom")
+	procGetEnvironmentStringsW      = modkernel32.NewProc("GetEnvironmentStringsW")
+	procFreeEnvironmentStringsW     = modkernel32.NewProc("FreeEnvironmentStringsW")
+	procGetEnvironmentVariableW     = modkernel32.NewProc("GetEnvironmentVariableW")
+	procSetEnvironmentVariableW     = modkernel32.NewProc("SetEnvironmentVariableW")
+	procSetFileTime                 = modkernel32.NewProc("SetFileTime")
+	procGetFileAttributesW          = modkernel32.NewProc("GetFileAttributesW")
+	procSetFileAttributesW          = modkernel32.NewProc("SetFileAttributesW")
+	procGetFileAttributesExW        = modkernel32.NewProc("GetFileAttributesExW")
+	procGetCommandLineW             = modkernel32.NewProc("GetCommandLineW")
+	procCommandLineToArgvW          = modshell32.NewProc("CommandLineToArgvW")
+	procLocalFree                   = modkernel32.NewProc("LocalFree")
+	procSetHandleInformation        = modkernel32.NewProc("SetHandleInformation")
+	procFlushFileBuffers            = modkernel32.NewProc("FlushFileBuffers")
+	procGetFullPathNameW            = modkernel32.NewProc("GetFullPathNameW")
+	procCreateFileMappingW          = modkernel32.NewProc("CreateFileMappingW")
+	procMapViewOfFile               = modkernel32.NewProc("MapViewOfFile")
+	procUnmapViewOfFile             = modkernel32.NewProc("UnmapViewOfFile")
+	procFlushViewOfFile             = modkernel32.NewProc("FlushViewOfFile")
+	procVirtualLock                 = modkernel32.NewProc("VirtualLock")
+	procVirtualUnlock               = modkernel32.NewProc("VirtualUnlock")
+	procTransmitFile                = modmswsock.NewProc("TransmitFile")
+	procReadDirectoryChangesW       = modkernel32.NewProc("ReadDirectoryChangesW")
+	procCertOpenSystemStoreW        = modcrypt32.NewProc("CertOpenSystemStoreW")
+	procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore")
+	procCertCloseStore              = modcrypt32.NewProc("CertCloseStore")
+	procRegOpenKeyExW               = modadvapi32.NewProc("RegOpenKeyExW")
+	procRegCloseKey                 = modadvapi32.NewProc("RegCloseKey")
+	procRegQueryInfoKeyW            = modadvapi32.NewProc("RegQueryInfoKeyW")
+	procRegEnumKeyExW               = modadvapi32.NewProc("RegEnumKeyExW")
+	procRegQueryValueExW            = modadvapi32.NewProc("RegQueryValueExW")
+	procWSAStartup                  = modws2_32.NewProc("WSAStartup")
+	procWSACleanup                  = modws2_32.NewProc("WSACleanup")
+	procWSAIoctl                    = modws2_32.NewProc("WSAIoctl")
+	procsocket                      = modws2_32.NewProc("socket")
+	procsetsockopt                  = modws2_32.NewProc("setsockopt")
+	procbind                        = modws2_32.NewProc("bind")
+	procconnect                     = modws2_32.NewProc("connect")
+	procgetsockname                 = modws2_32.NewProc("getsockname")
+	procgetpeername                 = modws2_32.NewProc("getpeername")
+	proclisten                      = modws2_32.NewProc("listen")
+	procshutdown                    = modws2_32.NewProc("shutdown")
+	procclosesocket                 = modws2_32.NewProc("closesocket")
+	procAcceptEx                    = modmswsock.NewProc("AcceptEx")
+	procGetAcceptExSockaddrs        = modmswsock.NewProc("GetAcceptExSockaddrs")
+	procWSARecv                     = modws2_32.NewProc("WSARecv")
+	procWSASend                     = modws2_32.NewProc("WSASend")
+	procWSARecvFrom                 = modws2_32.NewProc("WSARecvFrom")
+	procWSASendTo                   = modws2_32.NewProc("WSASendTo")
+	procgethostbyname               = modws2_32.NewProc("gethostbyname")
+	procgetservbyname               = modws2_32.NewProc("getservbyname")
+	procntohs                       = modws2_32.NewProc("ntohs")
+	procgetprotobyname              = modws2_32.NewProc("getprotobyname")
+	procDnsQuery_W                  = moddnsapi.NewProc("DnsQuery_W")
+	procDnsRecordListFree           = moddnsapi.NewProc("DnsRecordListFree")
+	procGetIfEntry                  = modiphlpapi.NewProc("GetIfEntry")
+	procGetAdaptersInfo             = modiphlpapi.NewProc("GetAdaptersInfo")
 )
 
-func GetLastError() (lasterrno int) {
+func GetLastError() (lasterr error) {
 	r0, _, _ := Syscall(procGetLastError.Addr(), 0, 0, 0, 0)
-	lasterrno = int(r0)
+	if r0 != 0 {
+		lasterr = Errno(r0)
+	}
 	return
 }
 
-func LoadLibrary(libname string) (handle Handle, errno int) {
+func LoadLibrary(libname string) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(StringToUTF16Ptr(libname))), 0, 0)
 	handle = Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FreeLibrary(handle Handle) (errno int) {
+func FreeLibrary(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetProcAddress(module Handle, procname string) (proc uintptr, errno int) {
+func GetProcAddress(module Handle, procname string) (proc uintptr, err error) {
 	r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
 	proc = uintptr(r0)
 	if proc == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetVersion() (ver uint32, errno int) {
+func GetVersion() (ver uint32, err error) {
 	r0, _, e1 := Syscall(procGetVersion.Addr(), 0, 0, 0, 0)
 	ver = uint32(r0)
 	if ver == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, errno int) {
+func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) {
 	var _p0 *uint16
 	if len(buf) > 0 {
 		_p0 = &buf[0]
@@ -181,12 +186,10 @@ func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -196,22 +199,20 @@ func ExitProcess(exitcode uint32) {
 	return
 }
 
-func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, errno int) {
+func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) {
 	r0, _, e1 := Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
 	handle = Handle(r0)
 	if handle == InvalidHandle {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (errno int) {
+func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
 	var _p0 *byte
 	if len(buf) > 0 {
 		_p0 = &buf[0]
@@ -219,17 +220,15 @@ func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (
 	r1, _, e1 := Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (errno int) {
+func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
 	var _p0 *byte
 	if len(buf) > 0 {
 		_p0 = &buf[0]
@@ -237,226 +236,194 @@ func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped)
 	r1, _, e1 := Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, errno int) {
+func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) {
 	r0, _, e1 := Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0)
 	newlowoffset = uint32(r0)
 	if newlowoffset == 0xffffffff {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CloseHandle(handle Handle) (errno int) {
+func CloseHandle(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetStdHandle(stdhandle int) (handle Handle, errno int) {
+func GetStdHandle(stdhandle int) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0)
 	handle = Handle(r0)
 	if handle == InvalidHandle {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, errno int) {
+func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0)
 	handle = Handle(r0)
 	if handle == InvalidHandle {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FindNextFile(handle Handle, data *Win32finddata) (errno int) {
+func FindNextFile(handle Handle, data *Win32finddata) (err error) {
 	r1, _, e1 := Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FindClose(handle Handle) (errno int) {
+func FindClose(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (errno int) {
+func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) {
 	r1, _, e1 := Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, errno int) {
+func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) {
 	r0, _, e1 := Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetCurrentDirectory(path *uint16) (errno int) {
+func SetCurrentDirectory(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateDirectory(path *uint16, sa *SecurityAttributes) (errno int) {
+func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) {
 	r1, _, e1 := Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func RemoveDirectory(path *uint16) (errno int) {
+func RemoveDirectory(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func DeleteFile(path *uint16) (errno int) {
+func DeleteFile(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func MoveFile(from *uint16, to *uint16) (errno int) {
+func MoveFile(from *uint16, to *uint16) (err error) {
 	r1, _, e1 := Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetComputerName(buf *uint16, n *uint32) (errno int) {
+func GetComputerName(buf *uint16, n *uint32) (err error) {
 	r1, _, e1 := Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetEndOfFile(handle Handle) (errno int) {
+func SetEndOfFile(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -466,70 +433,69 @@ func GetSystemTimeAsFileTime(time *Filetime) {
 	return
 }
 
-func sleep(msec uint32) {
-	Syscall(procSleep.Addr(), 1, uintptr(msec), 0, 0)
-	return
-}
-
-func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, errno int) {
+func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) {
 	r0, _, e1 := Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0)
 	rc = uint32(r0)
 	if rc == 0xffffffff {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, errno int) {
+func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) {
 	r0, _, e1 := Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0)
 	handle = Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (errno int) {
+func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) {
 	r1, _, e1 := Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CancelIo(s Handle) (errno int) {
+func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) {
+	r1, _, e1 := Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0)
+	if int(r1) == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func CancelIo(s Handle) (err error) {
 	r1, _, e1 := Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (errno int) {
+func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) {
 	var _p0 uint32
 	if inheritHandles {
 		_p0 = 1
@@ -539,17 +505,15 @@ func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityA
 	r1, _, e1 := Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, errno int) {
+func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) {
 	var _p0 uint32
 	if inheritHandle {
 		_p0 = 1
@@ -560,74 +524,64 @@ func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, errn
 	handle = Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func TerminateProcess(handle Handle, exitcode uint32) (errno int) {
+func TerminateProcess(handle Handle, exitcode uint32) (err error) {
 	r1, _, e1 := Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetExitCodeProcess(handle Handle, exitcode *uint32) (errno int) {
+func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) {
 	r1, _, e1 := Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetStartupInfo(startupInfo *StartupInfo) (errno int) {
+func GetStartupInfo(startupInfo *StartupInfo) (err error) {
 	r1, _, e1 := Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetCurrentProcess() (pseudoHandle Handle, errno int) {
+func GetCurrentProcess() (pseudoHandle Handle, err error) {
 	r0, _, e1 := Syscall(procGetCurrentProcess.Addr(), 0, 0, 0, 0)
 	pseudoHandle = Handle(r0)
 	if pseudoHandle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (errno int) {
+func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) {
 	var _p0 uint32
 	if bInheritHandle {
 		_p0 = 1
@@ -637,228 +591,196 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP
 	r1, _, e1 := Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, errno int) {
+func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) {
 	r0, _, e1 := Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0)
 	event = uint32(r0)
 	if event == 0xffffffff {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) {
+func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) {
 	r0, _, e1 := Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (errno int) {
+func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) {
 	r1, _, e1 := Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFileType(filehandle Handle) (n uint32, errno int) {
+func GetFileType(filehandle Handle) (n uint32, err error) {
 	r0, _, e1 := Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0)
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (errno int) {
+func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) {
 	r1, _, e1 := Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CryptReleaseContext(provhandle Handle, flags uint32) (errno int) {
+func CryptReleaseContext(provhandle Handle, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (errno int) {
+func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) {
 	r1, _, e1 := Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf)))
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetEnvironmentStrings() (envs *uint16, errno int) {
+func GetEnvironmentStrings() (envs *uint16, err error) {
 	r0, _, e1 := Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0)
 	envs = (*uint16)(unsafe.Pointer(r0))
 	if envs == nil {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FreeEnvironmentStrings(envs *uint16) (errno int) {
+func FreeEnvironmentStrings(envs *uint16) (err error) {
 	r1, _, e1 := Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) {
+func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) {
 	r0, _, e1 := Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size))
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetEnvironmentVariable(name *uint16, value *uint16) (errno int) {
+func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
 	r1, _, e1 := Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (errno int) {
+func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) {
 	r1, _, e1 := Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFileAttributes(name *uint16) (attrs uint32, errno int) {
+func GetFileAttributes(name *uint16) (attrs uint32, err error) {
 	r0, _, e1 := Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0)
 	attrs = uint32(r0)
 	if attrs == INVALID_FILE_ATTRIBUTES {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetFileAttributes(name *uint16, attrs uint32) (errno int) {
+func SetFileAttributes(name *uint16, attrs uint32) (err error) {
 	r1, _, e1 := Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFileAttributesEx(name *uint16, level uint32, info *byte) (errno int) {
+func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) {
 	r1, _, e1 := Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info)))
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -869,350 +791,400 @@ func GetCommandLine() (cmd *uint16) {
 	return
 }
 
-func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, errno int) {
+func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) {
 	r0, _, e1 := Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0)
 	argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0))
 	if argv == nil {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func LocalFree(hmem Handle) (handle Handle, errno int) {
+func LocalFree(hmem Handle) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0)
 	handle = Handle(r0)
 	if handle != 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetHandleInformation(handle Handle, mask uint32, flags uint32) (errno int) {
+func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags))
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FlushFileBuffers(handle Handle) (errno int) {
+func FlushFileBuffers(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, errno int) {
+func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) {
 	r0, _, e1 := Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0)
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, errno int) {
+func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) {
 	r0, _, e1 := Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name)))
 	handle = Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, errno int) {
+func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) {
 	r0, _, e1 := Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0)
 	addr = uintptr(r0)
 	if addr == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func UnmapViewOfFile(addr uintptr) (errno int) {
+func UnmapViewOfFile(addr uintptr) (err error) {
 	r1, _, e1 := Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FlushViewOfFile(addr uintptr, length uintptr) (errno int) {
+func FlushViewOfFile(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func VirtualLock(addr uintptr, length uintptr) (errno int) {
+func VirtualLock(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func VirtualUnlock(addr uintptr, length uintptr) (errno int) {
+func VirtualUnlock(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (errno int) {
+func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) {
 	r1, _, e1 := Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
+	}
+	return
+}
+
+func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) {
+	var _p0 uint32
+	if watchSubTree {
+		_p0 = 1
 	} else {
-		errno = 0
+		_p0 = 0
+	}
+	r1, _, e1 := Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0)
+	if int(r1) == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) {
+	r0, _, e1 := Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0)
+	store = Handle(r0)
+	if store == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) {
+	r0, _, e1 := Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0)
+	context = (*CertContext)(unsafe.Pointer(r0))
+	if context == nil {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
 	}
 	return
 }
 
-func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) {
+func CertCloseStore(store Handle, flags uint32) (err error) {
+	r1, _, e1 := Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0)
+	if int(r1) == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) {
+	r0, _, _ := Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0)
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func RegCloseKey(key Handle) (regerrno error) {
+	r0, _, _ := Syscall(procRegCloseKey.Addr(), 1, uintptr(key), 0, 0)
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) {
+	r0, _, _ := Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime)))
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
+	r0, _, _ := Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0)
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) {
+	r0, _, _ := Syscall6(procRegQueryValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)))
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
 	r0, _, _ := Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
-	sockerrno = int(r0)
+	if r0 != 0 {
+		sockerr = Errno(r0)
+	}
 	return
 }
 
-func WSACleanup() (errno int) {
+func WSACleanup() (err error) {
 	r1, _, e1 := Syscall(procWSACleanup.Addr(), 0, 0, 0, 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (errno int) {
+func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) {
 	r1, _, e1 := Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func socket(af int32, typ int32, protocol int32) (handle Handle, errno int) {
+func socket(af int32, typ int32, protocol int32) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol))
 	handle = Handle(r0)
 	if handle == InvalidHandle {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (errno int) {
+func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) {
 	r1, _, e1 := Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func bind(s Handle, name uintptr, namelen int32) (errno int) {
+func bind(s Handle, name uintptr, namelen int32) (err error) {
 	r1, _, e1 := Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func connect(s Handle, name uintptr, namelen int32) (errno int) {
+func connect(s Handle, name uintptr, namelen int32) (err error) {
 	r1, _, e1 := Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (errno int) {
+func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
 	r1, _, e1 := Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (errno int) {
+func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
 	r1, _, e1 := Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func listen(s Handle, backlog int32) (errno int) {
+func listen(s Handle, backlog int32) (err error) {
 	r1, _, e1 := Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func shutdown(s Handle, how int32) (errno int) {
+func shutdown(s Handle, how int32) (err error) {
 	r1, _, e1 := Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func Closesocket(s Handle) (errno int) {
+func Closesocket(s Handle) (err error) {
 	r1, _, e1 := Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (errno int) {
+func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) {
 	r1, _, e1 := Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -1222,88 +1194,76 @@ func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen
 	return
 }
 
-func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) {
 	r1, _, e1 := Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) {
 	r1, _, e1 := Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) {
 	r1, _, e1 := Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) {
 	r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetHostByName(name string) (h *Hostent, errno int) {
+func GetHostByName(name string) (h *Hostent, err error) {
 	r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
 	h = (*Hostent)(unsafe.Pointer(r0))
 	if h == nil {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetServByName(name string, proto string) (s *Servent, errno int) {
+func GetServByName(name string, proto string) (s *Servent, err error) {
 	r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(proto))), 0)
 	s = (*Servent)(unsafe.Pointer(r0))
 	if s == nil {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -1314,9 +1274,24 @@ func Ntohs(netshort uint16) (u uint16) {
 	return
 }
 
-func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status uint32) {
+func GetProtoByName(name string) (p *Protoent, err error) {
+	r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	p = (*Protoent)(unsafe.Pointer(r0))
+	if p == nil {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) {
 	r0, _, _ := Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(StringToUTF16Ptr(name))), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr)))
-	status = uint32(r0)
+	if r0 != 0 {
+		status = Errno(r0)
+	}
 	return
 }
 
@@ -1325,14 +1300,18 @@ func DnsRecordListFree(rl *DNSRecord, freetype uint32) {
 	return
 }
 
-func GetIfEntry(pIfRow *MibIfRow) (errcode int) {
+func GetIfEntry(pIfRow *MibIfRow) (errcode error) {
 	r0, _, _ := Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0)
-	errcode = int(r0)
+	if r0 != 0 {
+		errcode = Errno(r0)
+	}
 	return
 }
 
-func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode int) {
+func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) {
 	r0, _, _ := Syscall(procGetAdaptersInfo.Addr(), 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0)
-	errcode = int(r0)
+	if r0 != 0 {
+		errcode = Errno(r0)
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsyscall_windows_amd64.go b/src/pkg/syscall/zsyscall_windows_amd64.go
index 0904085..df1c4f0 100644
--- a/src/pkg/syscall/zsyscall_windows_amd64.go
+++ b/src/pkg/syscall/zsyscall_windows_amd64.go
@@ -10,169 +10,174 @@ var (
 	modadvapi32 = NewLazyDLL("advapi32.dll")
 	modshell32  = NewLazyDLL("shell32.dll")
 	modmswsock  = NewLazyDLL("mswsock.dll")
+	modcrypt32  = NewLazyDLL("crypt32.dll")
 	modws2_32   = NewLazyDLL("ws2_32.dll")
 	moddnsapi   = NewLazyDLL("dnsapi.dll")
 	modiphlpapi = NewLazyDLL("iphlpapi.dll")
 
-	procGetLastError               = modkernel32.NewProc("GetLastError")
-	procLoadLibraryW               = modkernel32.NewProc("LoadLibraryW")
-	procFreeLibrary                = modkernel32.NewProc("FreeLibrary")
-	procGetProcAddress             = modkernel32.NewProc("GetProcAddress")
-	procGetVersion                 = modkernel32.NewProc("GetVersion")
-	procFormatMessageW             = modkernel32.NewProc("FormatMessageW")
-	procExitProcess                = modkernel32.NewProc("ExitProcess")
-	procCreateFileW                = modkernel32.NewProc("CreateFileW")
-	procReadFile                   = modkernel32.NewProc("ReadFile")
-	procWriteFile                  = modkernel32.NewProc("WriteFile")
-	procSetFilePointer             = modkernel32.NewProc("SetFilePointer")
-	procCloseHandle                = modkernel32.NewProc("CloseHandle")
-	procGetStdHandle               = modkernel32.NewProc("GetStdHandle")
-	procFindFirstFileW             = modkernel32.NewProc("FindFirstFileW")
-	procFindNextFileW              = modkernel32.NewProc("FindNextFileW")
-	procFindClose                  = modkernel32.NewProc("FindClose")
-	procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle")
-	procGetCurrentDirectoryW       = modkernel32.NewProc("GetCurrentDirectoryW")
-	procSetCurrentDirectoryW       = modkernel32.NewProc("SetCurrentDirectoryW")
-	procCreateDirectoryW           = modkernel32.NewProc("CreateDirectoryW")
-	procRemoveDirectoryW           = modkernel32.NewProc("RemoveDirectoryW")
-	procDeleteFileW                = modkernel32.NewProc("DeleteFileW")
-	procMoveFileW                  = modkernel32.NewProc("MoveFileW")
-	procGetComputerNameW           = modkernel32.NewProc("GetComputerNameW")
-	procSetEndOfFile               = modkernel32.NewProc("SetEndOfFile")
-	procGetSystemTimeAsFileTime    = modkernel32.NewProc("GetSystemTimeAsFileTime")
-	procSleep                      = modkernel32.NewProc("Sleep")
-	procGetTimeZoneInformation     = modkernel32.NewProc("GetTimeZoneInformation")
-	procCreateIoCompletionPort     = modkernel32.NewProc("CreateIoCompletionPort")
-	procGetQueuedCompletionStatus  = modkernel32.NewProc("GetQueuedCompletionStatus")
-	procCancelIo                   = modkernel32.NewProc("CancelIo")
-	procCreateProcessW             = modkernel32.NewProc("CreateProcessW")
-	procOpenProcess                = modkernel32.NewProc("OpenProcess")
-	procTerminateProcess           = modkernel32.NewProc("TerminateProcess")
-	procGetExitCodeProcess         = modkernel32.NewProc("GetExitCodeProcess")
-	procGetStartupInfoW            = modkernel32.NewProc("GetStartupInfoW")
-	procGetCurrentProcess          = modkernel32.NewProc("GetCurrentProcess")
-	procDuplicateHandle            = modkernel32.NewProc("DuplicateHandle")
-	procWaitForSingleObject        = modkernel32.NewProc("WaitForSingleObject")
-	procGetTempPathW               = modkernel32.NewProc("GetTempPathW")
-	procCreatePipe                 = modkernel32.NewProc("CreatePipe")
-	procGetFileType                = modkernel32.NewProc("GetFileType")
-	procCryptAcquireContextW       = modadvapi32.NewProc("CryptAcquireContextW")
-	procCryptReleaseContext        = modadvapi32.NewProc("CryptReleaseContext")
-	procCryptGenRandom             = modadvapi32.NewProc("CryptGenRandom")
-	procGetEnvironmentStringsW     = modkernel32.NewProc("GetEnvironmentStringsW")
-	procFreeEnvironmentStringsW    = modkernel32.NewProc("FreeEnvironmentStringsW")
-	procGetEnvironmentVariableW    = modkernel32.NewProc("GetEnvironmentVariableW")
-	procSetEnvironmentVariableW    = modkernel32.NewProc("SetEnvironmentVariableW")
-	procSetFileTime                = modkernel32.NewProc("SetFileTime")
-	procGetFileAttributesW         = modkernel32.NewProc("GetFileAttributesW")
-	procSetFileAttributesW         = modkernel32.NewProc("SetFileAttributesW")
-	procGetFileAttributesExW       = modkernel32.NewProc("GetFileAttributesExW")
-	procGetCommandLineW            = modkernel32.NewProc("GetCommandLineW")
-	procCommandLineToArgvW         = modshell32.NewProc("CommandLineToArgvW")
-	procLocalFree                  = modkernel32.NewProc("LocalFree")
-	procSetHandleInformation       = modkernel32.NewProc("SetHandleInformation")
-	procFlushFileBuffers           = modkernel32.NewProc("FlushFileBuffers")
-	procGetFullPathNameW           = modkernel32.NewProc("GetFullPathNameW")
-	procCreateFileMappingW         = modkernel32.NewProc("CreateFileMappingW")
-	procMapViewOfFile              = modkernel32.NewProc("MapViewOfFile")
-	procUnmapViewOfFile            = modkernel32.NewProc("UnmapViewOfFile")
-	procFlushViewOfFile            = modkernel32.NewProc("FlushViewOfFile")
-	procVirtualLock                = modkernel32.NewProc("VirtualLock")
-	procVirtualUnlock              = modkernel32.NewProc("VirtualUnlock")
-	procTransmitFile               = modmswsock.NewProc("TransmitFile")
-	procWSAStartup                 = modws2_32.NewProc("WSAStartup")
-	procWSACleanup                 = modws2_32.NewProc("WSACleanup")
-	procWSAIoctl                   = modws2_32.NewProc("WSAIoctl")
-	procsocket                     = modws2_32.NewProc("socket")
-	procsetsockopt                 = modws2_32.NewProc("setsockopt")
-	procbind                       = modws2_32.NewProc("bind")
-	procconnect                    = modws2_32.NewProc("connect")
-	procgetsockname                = modws2_32.NewProc("getsockname")
-	procgetpeername                = modws2_32.NewProc("getpeername")
-	proclisten                     = modws2_32.NewProc("listen")
-	procshutdown                   = modws2_32.NewProc("shutdown")
-	procclosesocket                = modws2_32.NewProc("closesocket")
-	procAcceptEx                   = modmswsock.NewProc("AcceptEx")
-	procGetAcceptExSockaddrs       = modmswsock.NewProc("GetAcceptExSockaddrs")
-	procWSARecv                    = modws2_32.NewProc("WSARecv")
-	procWSASend                    = modws2_32.NewProc("WSASend")
-	procWSARecvFrom                = modws2_32.NewProc("WSARecvFrom")
-	procWSASendTo                  = modws2_32.NewProc("WSASendTo")
-	procgethostbyname              = modws2_32.NewProc("gethostbyname")
-	procgetservbyname              = modws2_32.NewProc("getservbyname")
-	procntohs                      = modws2_32.NewProc("ntohs")
-	procDnsQuery_W                 = moddnsapi.NewProc("DnsQuery_W")
-	procDnsRecordListFree          = moddnsapi.NewProc("DnsRecordListFree")
-	procGetIfEntry                 = modiphlpapi.NewProc("GetIfEntry")
-	procGetAdaptersInfo            = modiphlpapi.NewProc("GetAdaptersInfo")
+	procGetLastError                = modkernel32.NewProc("GetLastError")
+	procLoadLibraryW                = modkernel32.NewProc("LoadLibraryW")
+	procFreeLibrary                 = modkernel32.NewProc("FreeLibrary")
+	procGetProcAddress              = modkernel32.NewProc("GetProcAddress")
+	procGetVersion                  = modkernel32.NewProc("GetVersion")
+	procFormatMessageW              = modkernel32.NewProc("FormatMessageW")
+	procExitProcess                 = modkernel32.NewProc("ExitProcess")
+	procCreateFileW                 = modkernel32.NewProc("CreateFileW")
+	procReadFile                    = modkernel32.NewProc("ReadFile")
+	procWriteFile                   = modkernel32.NewProc("WriteFile")
+	procSetFilePointer              = modkernel32.NewProc("SetFilePointer")
+	procCloseHandle                 = modkernel32.NewProc("CloseHandle")
+	procGetStdHandle                = modkernel32.NewProc("GetStdHandle")
+	procFindFirstFileW              = modkernel32.NewProc("FindFirstFileW")
+	procFindNextFileW               = modkernel32.NewProc("FindNextFileW")
+	procFindClose                   = modkernel32.NewProc("FindClose")
+	procGetFileInformationByHandle  = modkernel32.NewProc("GetFileInformationByHandle")
+	procGetCurrentDirectoryW        = modkernel32.NewProc("GetCurrentDirectoryW")
+	procSetCurrentDirectoryW        = modkernel32.NewProc("SetCurrentDirectoryW")
+	procCreateDirectoryW            = modkernel32.NewProc("CreateDirectoryW")
+	procRemoveDirectoryW            = modkernel32.NewProc("RemoveDirectoryW")
+	procDeleteFileW                 = modkernel32.NewProc("DeleteFileW")
+	procMoveFileW                   = modkernel32.NewProc("MoveFileW")
+	procGetComputerNameW            = modkernel32.NewProc("GetComputerNameW")
+	procSetEndOfFile                = modkernel32.NewProc("SetEndOfFile")
+	procGetSystemTimeAsFileTime     = modkernel32.NewProc("GetSystemTimeAsFileTime")
+	procGetTimeZoneInformation      = modkernel32.NewProc("GetTimeZoneInformation")
+	procCreateIoCompletionPort      = modkernel32.NewProc("CreateIoCompletionPort")
+	procGetQueuedCompletionStatus   = modkernel32.NewProc("GetQueuedCompletionStatus")
+	procPostQueuedCompletionStatus  = modkernel32.NewProc("PostQueuedCompletionStatus")
+	procCancelIo                    = modkernel32.NewProc("CancelIo")
+	procCreateProcessW              = modkernel32.NewProc("CreateProcessW")
+	procOpenProcess                 = modkernel32.NewProc("OpenProcess")
+	procTerminateProcess            = modkernel32.NewProc("TerminateProcess")
+	procGetExitCodeProcess          = modkernel32.NewProc("GetExitCodeProcess")
+	procGetStartupInfoW             = modkernel32.NewProc("GetStartupInfoW")
+	procGetCurrentProcess           = modkernel32.NewProc("GetCurrentProcess")
+	procDuplicateHandle             = modkernel32.NewProc("DuplicateHandle")
+	procWaitForSingleObject         = modkernel32.NewProc("WaitForSingleObject")
+	procGetTempPathW                = modkernel32.NewProc("GetTempPathW")
+	procCreatePipe                  = modkernel32.NewProc("CreatePipe")
+	procGetFileType                 = modkernel32.NewProc("GetFileType")
+	procCryptAcquireContextW        = modadvapi32.NewProc("CryptAcquireContextW")
+	procCryptReleaseContext         = modadvapi32.NewProc("CryptReleaseContext")
+	procCryptGenRandom              = modadvapi32.NewProc("CryptGenRandom")
+	procGetEnvironmentStringsW      = modkernel32.NewProc("GetEnvironmentStringsW")
+	procFreeEnvironmentStringsW     = modkernel32.NewProc("FreeEnvironmentStringsW")
+	procGetEnvironmentVariableW     = modkernel32.NewProc("GetEnvironmentVariableW")
+	procSetEnvironmentVariableW     = modkernel32.NewProc("SetEnvironmentVariableW")
+	procSetFileTime                 = modkernel32.NewProc("SetFileTime")
+	procGetFileAttributesW          = modkernel32.NewProc("GetFileAttributesW")
+	procSetFileAttributesW          = modkernel32.NewProc("SetFileAttributesW")
+	procGetFileAttributesExW        = modkernel32.NewProc("GetFileAttributesExW")
+	procGetCommandLineW             = modkernel32.NewProc("GetCommandLineW")
+	procCommandLineToArgvW          = modshell32.NewProc("CommandLineToArgvW")
+	procLocalFree                   = modkernel32.NewProc("LocalFree")
+	procSetHandleInformation        = modkernel32.NewProc("SetHandleInformation")
+	procFlushFileBuffers            = modkernel32.NewProc("FlushFileBuffers")
+	procGetFullPathNameW            = modkernel32.NewProc("GetFullPathNameW")
+	procCreateFileMappingW          = modkernel32.NewProc("CreateFileMappingW")
+	procMapViewOfFile               = modkernel32.NewProc("MapViewOfFile")
+	procUnmapViewOfFile             = modkernel32.NewProc("UnmapViewOfFile")
+	procFlushViewOfFile             = modkernel32.NewProc("FlushViewOfFile")
+	procVirtualLock                 = modkernel32.NewProc("VirtualLock")
+	procVirtualUnlock               = modkernel32.NewProc("VirtualUnlock")
+	procTransmitFile                = modmswsock.NewProc("TransmitFile")
+	procReadDirectoryChangesW       = modkernel32.NewProc("ReadDirectoryChangesW")
+	procCertOpenSystemStoreW        = modcrypt32.NewProc("CertOpenSystemStoreW")
+	procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore")
+	procCertCloseStore              = modcrypt32.NewProc("CertCloseStore")
+	procRegOpenKeyExW               = modadvapi32.NewProc("RegOpenKeyExW")
+	procRegCloseKey                 = modadvapi32.NewProc("RegCloseKey")
+	procRegQueryInfoKeyW            = modadvapi32.NewProc("RegQueryInfoKeyW")
+	procRegEnumKeyExW               = modadvapi32.NewProc("RegEnumKeyExW")
+	procRegQueryValueExW            = modadvapi32.NewProc("RegQueryValueExW")
+	procWSAStartup                  = modws2_32.NewProc("WSAStartup")
+	procWSACleanup                  = modws2_32.NewProc("WSACleanup")
+	procWSAIoctl                    = modws2_32.NewProc("WSAIoctl")
+	procsocket                      = modws2_32.NewProc("socket")
+	procsetsockopt                  = modws2_32.NewProc("setsockopt")
+	procbind                        = modws2_32.NewProc("bind")
+	procconnect                     = modws2_32.NewProc("connect")
+	procgetsockname                 = modws2_32.NewProc("getsockname")
+	procgetpeername                 = modws2_32.NewProc("getpeername")
+	proclisten                      = modws2_32.NewProc("listen")
+	procshutdown                    = modws2_32.NewProc("shutdown")
+	procclosesocket                 = modws2_32.NewProc("closesocket")
+	procAcceptEx                    = modmswsock.NewProc("AcceptEx")
+	procGetAcceptExSockaddrs        = modmswsock.NewProc("GetAcceptExSockaddrs")
+	procWSARecv                     = modws2_32.NewProc("WSARecv")
+	procWSASend                     = modws2_32.NewProc("WSASend")
+	procWSARecvFrom                 = modws2_32.NewProc("WSARecvFrom")
+	procWSASendTo                   = modws2_32.NewProc("WSASendTo")
+	procgethostbyname               = modws2_32.NewProc("gethostbyname")
+	procgetservbyname               = modws2_32.NewProc("getservbyname")
+	procntohs                       = modws2_32.NewProc("ntohs")
+	procgetprotobyname              = modws2_32.NewProc("getprotobyname")
+	procDnsQuery_W                  = moddnsapi.NewProc("DnsQuery_W")
+	procDnsRecordListFree           = moddnsapi.NewProc("DnsRecordListFree")
+	procGetIfEntry                  = modiphlpapi.NewProc("GetIfEntry")
+	procGetAdaptersInfo             = modiphlpapi.NewProc("GetAdaptersInfo")
 )
 
-func GetLastError() (lasterrno int) {
+func GetLastError() (lasterr error) {
 	r0, _, _ := Syscall(procGetLastError.Addr(), 0, 0, 0, 0)
-	lasterrno = int(r0)
+	if r0 != 0 {
+		lasterr = Errno(r0)
+	}
 	return
 }
 
-func LoadLibrary(libname string) (handle Handle, errno int) {
+func LoadLibrary(libname string) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(StringToUTF16Ptr(libname))), 0, 0)
 	handle = Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FreeLibrary(handle Handle) (errno int) {
+func FreeLibrary(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetProcAddress(module Handle, procname string) (proc uintptr, errno int) {
+func GetProcAddress(module Handle, procname string) (proc uintptr, err error) {
 	r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
 	proc = uintptr(r0)
 	if proc == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetVersion() (ver uint32, errno int) {
+func GetVersion() (ver uint32, err error) {
 	r0, _, e1 := Syscall(procGetVersion.Addr(), 0, 0, 0, 0)
 	ver = uint32(r0)
 	if ver == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, errno int) {
+func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) {
 	var _p0 *uint16
 	if len(buf) > 0 {
 		_p0 = &buf[0]
@@ -181,12 +186,10 @@ func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -196,22 +199,20 @@ func ExitProcess(exitcode uint32) {
 	return
 }
 
-func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, errno int) {
+func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) {
 	r0, _, e1 := Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
 	handle = Handle(r0)
 	if handle == InvalidHandle {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (errno int) {
+func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
 	var _p0 *byte
 	if len(buf) > 0 {
 		_p0 = &buf[0]
@@ -219,17 +220,15 @@ func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (
 	r1, _, e1 := Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (errno int) {
+func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) {
 	var _p0 *byte
 	if len(buf) > 0 {
 		_p0 = &buf[0]
@@ -237,226 +236,194 @@ func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped)
 	r1, _, e1 := Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, errno int) {
+func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) {
 	r0, _, e1 := Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0)
 	newlowoffset = uint32(r0)
 	if newlowoffset == 0xffffffff {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CloseHandle(handle Handle) (errno int) {
+func CloseHandle(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetStdHandle(stdhandle int) (handle Handle, errno int) {
+func GetStdHandle(stdhandle int) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0)
 	handle = Handle(r0)
 	if handle == InvalidHandle {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, errno int) {
+func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0)
 	handle = Handle(r0)
 	if handle == InvalidHandle {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FindNextFile(handle Handle, data *Win32finddata) (errno int) {
+func FindNextFile(handle Handle, data *Win32finddata) (err error) {
 	r1, _, e1 := Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FindClose(handle Handle) (errno int) {
+func FindClose(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (errno int) {
+func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) {
 	r1, _, e1 := Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, errno int) {
+func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) {
 	r0, _, e1 := Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetCurrentDirectory(path *uint16) (errno int) {
+func SetCurrentDirectory(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateDirectory(path *uint16, sa *SecurityAttributes) (errno int) {
+func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) {
 	r1, _, e1 := Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func RemoveDirectory(path *uint16) (errno int) {
+func RemoveDirectory(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func DeleteFile(path *uint16) (errno int) {
+func DeleteFile(path *uint16) (err error) {
 	r1, _, e1 := Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func MoveFile(from *uint16, to *uint16) (errno int) {
+func MoveFile(from *uint16, to *uint16) (err error) {
 	r1, _, e1 := Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetComputerName(buf *uint16, n *uint32) (errno int) {
+func GetComputerName(buf *uint16, n *uint32) (err error) {
 	r1, _, e1 := Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetEndOfFile(handle Handle) (errno int) {
+func SetEndOfFile(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -466,70 +433,69 @@ func GetSystemTimeAsFileTime(time *Filetime) {
 	return
 }
 
-func sleep(msec uint32) {
-	Syscall(procSleep.Addr(), 1, uintptr(msec), 0, 0)
-	return
-}
-
-func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, errno int) {
+func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) {
 	r0, _, e1 := Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0)
 	rc = uint32(r0)
 	if rc == 0xffffffff {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, errno int) {
+func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) {
 	r0, _, e1 := Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0)
 	handle = Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (errno int) {
+func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) {
 	r1, _, e1 := Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CancelIo(s Handle) (errno int) {
+func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) {
+	r1, _, e1 := Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0)
+	if int(r1) == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func CancelIo(s Handle) (err error) {
 	r1, _, e1 := Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (errno int) {
+func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) {
 	var _p0 uint32
 	if inheritHandles {
 		_p0 = 1
@@ -539,17 +505,15 @@ func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityA
 	r1, _, e1 := Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, errno int) {
+func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) {
 	var _p0 uint32
 	if inheritHandle {
 		_p0 = 1
@@ -560,74 +524,64 @@ func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, errn
 	handle = Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func TerminateProcess(handle Handle, exitcode uint32) (errno int) {
+func TerminateProcess(handle Handle, exitcode uint32) (err error) {
 	r1, _, e1 := Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetExitCodeProcess(handle Handle, exitcode *uint32) (errno int) {
+func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) {
 	r1, _, e1 := Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetStartupInfo(startupInfo *StartupInfo) (errno int) {
+func GetStartupInfo(startupInfo *StartupInfo) (err error) {
 	r1, _, e1 := Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetCurrentProcess() (pseudoHandle Handle, errno int) {
+func GetCurrentProcess() (pseudoHandle Handle, err error) {
 	r0, _, e1 := Syscall(procGetCurrentProcess.Addr(), 0, 0, 0, 0)
 	pseudoHandle = Handle(r0)
 	if pseudoHandle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (errno int) {
+func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) {
 	var _p0 uint32
 	if bInheritHandle {
 		_p0 = 1
@@ -637,228 +591,196 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP
 	r1, _, e1 := Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, errno int) {
+func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) {
 	r0, _, e1 := Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0)
 	event = uint32(r0)
 	if event == 0xffffffff {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) {
+func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) {
 	r0, _, e1 := Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (errno int) {
+func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) {
 	r1, _, e1 := Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFileType(filehandle Handle) (n uint32, errno int) {
+func GetFileType(filehandle Handle) (n uint32, err error) {
 	r0, _, e1 := Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0)
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (errno int) {
+func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) {
 	r1, _, e1 := Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CryptReleaseContext(provhandle Handle, flags uint32) (errno int) {
+func CryptReleaseContext(provhandle Handle, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (errno int) {
+func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) {
 	r1, _, e1 := Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf)))
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetEnvironmentStrings() (envs *uint16, errno int) {
+func GetEnvironmentStrings() (envs *uint16, err error) {
 	r0, _, e1 := Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0)
 	envs = (*uint16)(unsafe.Pointer(r0))
 	if envs == nil {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FreeEnvironmentStrings(envs *uint16) (errno int) {
+func FreeEnvironmentStrings(envs *uint16) (err error) {
 	r1, _, e1 := Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) {
+func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) {
 	r0, _, e1 := Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size))
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetEnvironmentVariable(name *uint16, value *uint16) (errno int) {
+func SetEnvironmentVariable(name *uint16, value *uint16) (err error) {
 	r1, _, e1 := Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (errno int) {
+func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) {
 	r1, _, e1 := Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFileAttributes(name *uint16) (attrs uint32, errno int) {
+func GetFileAttributes(name *uint16) (attrs uint32, err error) {
 	r0, _, e1 := Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0)
 	attrs = uint32(r0)
 	if attrs == INVALID_FILE_ATTRIBUTES {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetFileAttributes(name *uint16, attrs uint32) (errno int) {
+func SetFileAttributes(name *uint16, attrs uint32) (err error) {
 	r1, _, e1 := Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFileAttributesEx(name *uint16, level uint32, info *byte) (errno int) {
+func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) {
 	r1, _, e1 := Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info)))
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -869,350 +791,400 @@ func GetCommandLine() (cmd *uint16) {
 	return
 }
 
-func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, errno int) {
+func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) {
 	r0, _, e1 := Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0)
 	argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0))
 	if argv == nil {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func LocalFree(hmem Handle) (handle Handle, errno int) {
+func LocalFree(hmem Handle) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0)
 	handle = Handle(r0)
 	if handle != 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func SetHandleInformation(handle Handle, mask uint32, flags uint32) (errno int) {
+func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) {
 	r1, _, e1 := Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags))
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FlushFileBuffers(handle Handle) (errno int) {
+func FlushFileBuffers(handle Handle) (err error) {
 	r1, _, e1 := Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, errno int) {
+func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) {
 	r0, _, e1 := Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0)
 	n = uint32(r0)
 	if n == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, errno int) {
+func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) {
 	r0, _, e1 := Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name)))
 	handle = Handle(r0)
 	if handle == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, errno int) {
+func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) {
 	r0, _, e1 := Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0)
 	addr = uintptr(r0)
 	if addr == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func UnmapViewOfFile(addr uintptr) (errno int) {
+func UnmapViewOfFile(addr uintptr) (err error) {
 	r1, _, e1 := Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func FlushViewOfFile(addr uintptr, length uintptr) (errno int) {
+func FlushViewOfFile(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func VirtualLock(addr uintptr, length uintptr) (errno int) {
+func VirtualLock(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func VirtualUnlock(addr uintptr, length uintptr) (errno int) {
+func VirtualUnlock(addr uintptr, length uintptr) (err error) {
 	r1, _, e1 := Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (errno int) {
+func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) {
 	r1, _, e1 := Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
+	}
+	return
+}
+
+func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) {
+	var _p0 uint32
+	if watchSubTree {
+		_p0 = 1
 	} else {
-		errno = 0
+		_p0 = 0
+	}
+	r1, _, e1 := Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0)
+	if int(r1) == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) {
+	r0, _, e1 := Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0)
+	store = Handle(r0)
+	if store == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) {
+	r0, _, e1 := Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0)
+	context = (*CertContext)(unsafe.Pointer(r0))
+	if context == nil {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
 	}
 	return
 }
 
-func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) {
+func CertCloseStore(store Handle, flags uint32) (err error) {
+	r1, _, e1 := Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0)
+	if int(r1) == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) {
+	r0, _, _ := Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0)
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func RegCloseKey(key Handle) (regerrno error) {
+	r0, _, _ := Syscall(procRegCloseKey.Addr(), 1, uintptr(key), 0, 0)
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) {
+	r0, _, _ := Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime)))
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
+	r0, _, _ := Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0)
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) {
+	r0, _, _ := Syscall6(procRegQueryValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen)))
+	if r0 != 0 {
+		regerrno = Errno(r0)
+	}
+	return
+}
+
+func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
 	r0, _, _ := Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
-	sockerrno = int(r0)
+	if r0 != 0 {
+		sockerr = Errno(r0)
+	}
 	return
 }
 
-func WSACleanup() (errno int) {
+func WSACleanup() (err error) {
 	r1, _, e1 := Syscall(procWSACleanup.Addr(), 0, 0, 0, 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (errno int) {
+func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) {
 	r1, _, e1 := Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func socket(af int32, typ int32, protocol int32) (handle Handle, errno int) {
+func socket(af int32, typ int32, protocol int32) (handle Handle, err error) {
 	r0, _, e1 := Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol))
 	handle = Handle(r0)
 	if handle == InvalidHandle {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (errno int) {
+func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) {
 	r1, _, e1 := Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func bind(s Handle, name uintptr, namelen int32) (errno int) {
+func bind(s Handle, name uintptr, namelen int32) (err error) {
 	r1, _, e1 := Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func connect(s Handle, name uintptr, namelen int32) (errno int) {
+func connect(s Handle, name uintptr, namelen int32) (err error) {
 	r1, _, e1 := Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (errno int) {
+func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
 	r1, _, e1 := Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (errno int) {
+func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) {
 	r1, _, e1 := Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func listen(s Handle, backlog int32) (errno int) {
+func listen(s Handle, backlog int32) (err error) {
 	r1, _, e1 := Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func shutdown(s Handle, how int32) (errno int) {
+func shutdown(s Handle, how int32) (err error) {
 	r1, _, e1 := Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func Closesocket(s Handle) (errno int) {
+func Closesocket(s Handle) (err error) {
 	r1, _, e1 := Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (errno int) {
+func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) {
 	r1, _, e1 := Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0)
 	if int(r1) == 0 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -1222,88 +1194,76 @@ func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen
 	return
 }
 
-func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) {
 	r1, _, e1 := Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) {
 	r1, _, e1 := Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0)
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) {
 	r1, _, e1 := Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (errno int) {
+func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) {
 	r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
 	if int(r1) == -1 {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetHostByName(name string) (h *Hostent, errno int) {
+func GetHostByName(name string) (h *Hostent, err error) {
 	r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
 	h = (*Hostent)(unsafe.Pointer(r0))
 	if h == nil {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
 
-func GetServByName(name string, proto string) (s *Servent, errno int) {
+func GetServByName(name string, proto string) (s *Servent, err error) {
 	r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(StringBytePtr(name))), uintptr(unsafe.Pointer(StringBytePtr(proto))), 0)
 	s = (*Servent)(unsafe.Pointer(r0))
 	if s == nil {
 		if e1 != 0 {
-			errno = int(e1)
+			err = error(e1)
 		} else {
-			errno = EINVAL
+			err = EINVAL
 		}
-	} else {
-		errno = 0
 	}
 	return
 }
@@ -1314,9 +1274,24 @@ func Ntohs(netshort uint16) (u uint16) {
 	return
 }
 
-func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status uint32) {
+func GetProtoByName(name string) (p *Protoent, err error) {
+	r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(StringBytePtr(name))), 0, 0)
+	p = (*Protoent)(unsafe.Pointer(r0))
+	if p == nil {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}
+
+func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) {
 	r0, _, _ := Syscall6(procDnsQuery_W.Addr(), 6, uintptr(unsafe.Pointer(StringToUTF16Ptr(name))), uintptr(qtype), uintptr(options), uintptr(unsafe.Pointer(extra)), uintptr(unsafe.Pointer(qrs)), uintptr(unsafe.Pointer(pr)))
-	status = uint32(r0)
+	if r0 != 0 {
+		status = Errno(r0)
+	}
 	return
 }
 
@@ -1325,14 +1300,18 @@ func DnsRecordListFree(rl *DNSRecord, freetype uint32) {
 	return
 }
 
-func GetIfEntry(pIfRow *MibIfRow) (errcode int) {
+func GetIfEntry(pIfRow *MibIfRow) (errcode error) {
 	r0, _, _ := Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0)
-	errcode = int(r0)
+	if r0 != 0 {
+		errcode = Errno(r0)
+	}
 	return
 }
 
-func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode int) {
+func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) {
 	r0, _, _ := Syscall(procGetAdaptersInfo.Addr(), 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0)
-	errcode = int(r0)
+	if r0 != 0 {
+		errcode = Errno(r0)
+	}
 	return
 }
diff --git a/src/pkg/syscall/zsysctl_openbsd.go b/src/pkg/syscall/zsysctl_openbsd.go
new file mode 100644
index 0000000..fb13422
--- /dev/null
+++ b/src/pkg/syscall/zsysctl_openbsd.go
@@ -0,0 +1,292 @@
+// mksysctl_openbsd.pl
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+type mibentry struct {
+	ctlname string
+	ctloid  []_C_int
+}
+
+var sysctlMib = []mibentry{
+	{"ddb.console", []_C_int{9, 6}},
+	{"ddb.log", []_C_int{9, 7}},
+	{"ddb.max_line", []_C_int{9, 3}},
+	{"ddb.max_width", []_C_int{9, 2}},
+	{"ddb.panic", []_C_int{9, 5}},
+	{"ddb.radix", []_C_int{9, 1}},
+	{"ddb.tab_stop_width", []_C_int{9, 4}},
+	{"ddb.trigger", []_C_int{9, 8}},
+	{"fs.posix.setuid", []_C_int{3, 1, 1}},
+	{"hw.allowpowerdown", []_C_int{6, 22}},
+	{"hw.byteorder", []_C_int{6, 4}},
+	{"hw.cpuspeed", []_C_int{6, 12}},
+	{"hw.diskcount", []_C_int{6, 10}},
+	{"hw.disknames", []_C_int{6, 8}},
+	{"hw.diskstats", []_C_int{6, 9}},
+	{"hw.machine", []_C_int{6, 1}},
+	{"hw.model", []_C_int{6, 2}},
+	{"hw.ncpu", []_C_int{6, 3}},
+	{"hw.ncpufound", []_C_int{6, 21}},
+	{"hw.pagesize", []_C_int{6, 7}},
+	{"hw.physmem", []_C_int{6, 19}},
+	{"hw.product", []_C_int{6, 15}},
+	{"hw.serialno", []_C_int{6, 17}},
+	{"hw.setperf", []_C_int{6, 13}},
+	{"hw.usermem", []_C_int{6, 20}},
+	{"hw.uuid", []_C_int{6, 18}},
+	{"hw.vendor", []_C_int{6, 14}},
+	{"hw.version", []_C_int{6, 16}},
+	{"kern.arandom", []_C_int{1, 37}},
+	{"kern.argmax", []_C_int{1, 8}},
+	{"kern.boottime", []_C_int{1, 21}},
+	{"kern.bufcachepercent", []_C_int{1, 72}},
+	{"kern.ccpu", []_C_int{1, 45}},
+	{"kern.clockrate", []_C_int{1, 12}},
+	{"kern.consdev", []_C_int{1, 75}},
+	{"kern.cp_time", []_C_int{1, 40}},
+	{"kern.cp_time2", []_C_int{1, 71}},
+	{"kern.cryptodevallowsoft", []_C_int{1, 53}},
+	{"kern.domainname", []_C_int{1, 22}},
+	{"kern.file", []_C_int{1, 15}},
+	{"kern.file2", []_C_int{1, 73}},
+	{"kern.forkstat", []_C_int{1, 42}},
+	{"kern.fscale", []_C_int{1, 46}},
+	{"kern.fsync", []_C_int{1, 33}},
+	{"kern.hostid", []_C_int{1, 11}},
+	{"kern.hostname", []_C_int{1, 10}},
+	{"kern.intrcnt.nintrcnt", []_C_int{1, 63, 1}},
+	{"kern.job_control", []_C_int{1, 19}},
+	{"kern.malloc.buckets", []_C_int{1, 39, 1}},
+	{"kern.malloc.kmemnames", []_C_int{1, 39, 3}},
+	{"kern.maxclusters", []_C_int{1, 67}},
+	{"kern.maxfiles", []_C_int{1, 7}},
+	{"kern.maxlocksperuid", []_C_int{1, 70}},
+	{"kern.maxpartitions", []_C_int{1, 23}},
+	{"kern.maxproc", []_C_int{1, 6}},
+	{"kern.maxvnodes", []_C_int{1, 5}},
+	{"kern.mbstat", []_C_int{1, 59}},
+	{"kern.msgbuf", []_C_int{1, 48}},
+	{"kern.msgbufsize", []_C_int{1, 38}},
+	{"kern.nchstats", []_C_int{1, 41}},
+	{"kern.netlivelocks", []_C_int{1, 76}},
+	{"kern.nfiles", []_C_int{1, 56}},
+	{"kern.ngroups", []_C_int{1, 18}},
+	{"kern.nosuidcoredump", []_C_int{1, 32}},
+	{"kern.nprocs", []_C_int{1, 47}},
+	{"kern.nselcoll", []_C_int{1, 43}},
+	{"kern.numvnodes", []_C_int{1, 58}},
+	{"kern.osrelease", []_C_int{1, 2}},
+	{"kern.osrevision", []_C_int{1, 3}},
+	{"kern.ostype", []_C_int{1, 1}},
+	{"kern.osversion", []_C_int{1, 27}},
+	{"kern.pool_debug", []_C_int{1, 77}},
+	{"kern.posix1version", []_C_int{1, 17}},
+	{"kern.proc", []_C_int{1, 66}},
+	{"kern.random", []_C_int{1, 31}},
+	{"kern.rawpartition", []_C_int{1, 24}},
+	{"kern.rthreads", []_C_int{1, 74}},
+	{"kern.saved_ids", []_C_int{1, 20}},
+	{"kern.securelevel", []_C_int{1, 9}},
+	{"kern.seminfo", []_C_int{1, 61}},
+	{"kern.shminfo", []_C_int{1, 62}},
+	{"kern.somaxconn", []_C_int{1, 28}},
+	{"kern.sominconn", []_C_int{1, 29}},
+	{"kern.splassert", []_C_int{1, 54}},
+	{"kern.stackgap_random", []_C_int{1, 50}},
+	{"kern.sysvipc_info", []_C_int{1, 51}},
+	{"kern.sysvmsg", []_C_int{1, 34}},
+	{"kern.sysvsem", []_C_int{1, 35}},
+	{"kern.sysvshm", []_C_int{1, 36}},
+	{"kern.timecounter.choice", []_C_int{1, 69, 4}},
+	{"kern.timecounter.hardware", []_C_int{1, 69, 3}},
+	{"kern.timecounter.tick", []_C_int{1, 69, 1}},
+	{"kern.timecounter.timestepwarnings", []_C_int{1, 69, 2}},
+	{"kern.tty.maxptys", []_C_int{1, 44, 6}},
+	{"kern.tty.nptys", []_C_int{1, 44, 7}},
+	{"kern.tty.tk_cancc", []_C_int{1, 44, 4}},
+	{"kern.tty.tk_nin", []_C_int{1, 44, 1}},
+	{"kern.tty.tk_nout", []_C_int{1, 44, 2}},
+	{"kern.tty.tk_rawcc", []_C_int{1, 44, 3}},
+	{"kern.tty.ttyinfo", []_C_int{1, 44, 5}},
+	{"kern.ttycount", []_C_int{1, 57}},
+	{"kern.userasymcrypto", []_C_int{1, 60}},
+	{"kern.usercrypto", []_C_int{1, 52}},
+	{"kern.usermount", []_C_int{1, 30}},
+	{"kern.version", []_C_int{1, 4}},
+	{"kern.vnode", []_C_int{1, 13}},
+	{"kern.watchdog.auto", []_C_int{1, 64, 2}},
+	{"kern.watchdog.period", []_C_int{1, 64, 1}},
+	{"net.bpf.bufsize", []_C_int{4, 31, 1}},
+	{"net.bpf.maxbufsize", []_C_int{4, 31, 2}},
+	{"net.inet.ah.enable", []_C_int{4, 2, 51, 1}},
+	{"net.inet.ah.stats", []_C_int{4, 2, 51, 2}},
+	{"net.inet.carp.allow", []_C_int{4, 2, 112, 1}},
+	{"net.inet.carp.log", []_C_int{4, 2, 112, 3}},
+	{"net.inet.carp.preempt", []_C_int{4, 2, 112, 2}},
+	{"net.inet.carp.stats", []_C_int{4, 2, 112, 4}},
+	{"net.inet.divert.recvspace", []_C_int{4, 2, 258, 1}},
+	{"net.inet.divert.sendspace", []_C_int{4, 2, 258, 2}},
+	{"net.inet.divert.stats", []_C_int{4, 2, 258, 3}},
+	{"net.inet.esp.enable", []_C_int{4, 2, 50, 1}},
+	{"net.inet.esp.stats", []_C_int{4, 2, 50, 4}},
+	{"net.inet.esp.udpencap", []_C_int{4, 2, 50, 2}},
+	{"net.inet.esp.udpencap_port", []_C_int{4, 2, 50, 3}},
+	{"net.inet.etherip.allow", []_C_int{4, 2, 97, 1}},
+	{"net.inet.etherip.stats", []_C_int{4, 2, 97, 2}},
+	{"net.inet.gre.allow", []_C_int{4, 2, 47, 1}},
+	{"net.inet.gre.wccp", []_C_int{4, 2, 47, 2}},
+	{"net.inet.icmp.bmcastecho", []_C_int{4, 2, 1, 2}},
+	{"net.inet.icmp.errppslimit", []_C_int{4, 2, 1, 3}},
+	{"net.inet.icmp.maskrepl", []_C_int{4, 2, 1, 1}},
+	{"net.inet.icmp.rediraccept", []_C_int{4, 2, 1, 4}},
+	{"net.inet.icmp.redirtimeout", []_C_int{4, 2, 1, 5}},
+	{"net.inet.icmp.stats", []_C_int{4, 2, 1, 7}},
+	{"net.inet.icmp.tstamprepl", []_C_int{4, 2, 1, 6}},
+	{"net.inet.igmp.stats", []_C_int{4, 2, 2, 1}},
+	{"net.inet.ip.arpqueued", []_C_int{4, 2, 0, 36}},
+	{"net.inet.ip.encdebug", []_C_int{4, 2, 0, 12}},
+	{"net.inet.ip.forwarding", []_C_int{4, 2, 0, 1}},
+	{"net.inet.ip.ifq.congestion", []_C_int{4, 2, 0, 30, 4}},
+	{"net.inet.ip.ifq.drops", []_C_int{4, 2, 0, 30, 3}},
+	{"net.inet.ip.ifq.len", []_C_int{4, 2, 0, 30, 1}},
+	{"net.inet.ip.ifq.maxlen", []_C_int{4, 2, 0, 30, 2}},
+	{"net.inet.ip.maxqueue", []_C_int{4, 2, 0, 11}},
+	{"net.inet.ip.mforwarding", []_C_int{4, 2, 0, 31}},
+	{"net.inet.ip.mrtproto", []_C_int{4, 2, 0, 34}},
+	{"net.inet.ip.mrtstats", []_C_int{4, 2, 0, 35}},
+	{"net.inet.ip.mtu", []_C_int{4, 2, 0, 4}},
+	{"net.inet.ip.mtudisc", []_C_int{4, 2, 0, 27}},
+	{"net.inet.ip.mtudisctimeout", []_C_int{4, 2, 0, 28}},
+	{"net.inet.ip.multipath", []_C_int{4, 2, 0, 32}},
+	{"net.inet.ip.portfirst", []_C_int{4, 2, 0, 7}},
+	{"net.inet.ip.porthifirst", []_C_int{4, 2, 0, 9}},
+	{"net.inet.ip.porthilast", []_C_int{4, 2, 0, 10}},
+	{"net.inet.ip.portlast", []_C_int{4, 2, 0, 8}},
+	{"net.inet.ip.redirect", []_C_int{4, 2, 0, 2}},
+	{"net.inet.ip.sourceroute", []_C_int{4, 2, 0, 5}},
+	{"net.inet.ip.stats", []_C_int{4, 2, 0, 33}},
+	{"net.inet.ip.ttl", []_C_int{4, 2, 0, 3}},
+	{"net.inet.ipcomp.enable", []_C_int{4, 2, 108, 1}},
+	{"net.inet.ipcomp.stats", []_C_int{4, 2, 108, 2}},
+	{"net.inet.ipip.allow", []_C_int{4, 2, 4, 1}},
+	{"net.inet.ipip.stats", []_C_int{4, 2, 4, 2}},
+	{"net.inet.mobileip.allow", []_C_int{4, 2, 55, 1}},
+	{"net.inet.pfsync.stats", []_C_int{4, 2, 240, 1}},
+	{"net.inet.pim.stats", []_C_int{4, 2, 103, 1}},
+	{"net.inet.tcp.ackonpush", []_C_int{4, 2, 6, 13}},
+	{"net.inet.tcp.always_keepalive", []_C_int{4, 2, 6, 22}},
+	{"net.inet.tcp.baddynamic", []_C_int{4, 2, 6, 6}},
+	{"net.inet.tcp.drop", []_C_int{4, 2, 6, 19}},
+	{"net.inet.tcp.ecn", []_C_int{4, 2, 6, 14}},
+	{"net.inet.tcp.ident", []_C_int{4, 2, 6, 9}},
+	{"net.inet.tcp.keepidle", []_C_int{4, 2, 6, 3}},
+	{"net.inet.tcp.keepinittime", []_C_int{4, 2, 6, 2}},
+	{"net.inet.tcp.keepintvl", []_C_int{4, 2, 6, 4}},
+	{"net.inet.tcp.mssdflt", []_C_int{4, 2, 6, 11}},
+	{"net.inet.tcp.reasslimit", []_C_int{4, 2, 6, 18}},
+	{"net.inet.tcp.rfc1323", []_C_int{4, 2, 6, 1}},
+	{"net.inet.tcp.rfc3390", []_C_int{4, 2, 6, 17}},
+	{"net.inet.tcp.rstppslimit", []_C_int{4, 2, 6, 12}},
+	{"net.inet.tcp.sack", []_C_int{4, 2, 6, 10}},
+	{"net.inet.tcp.sackholelimit", []_C_int{4, 2, 6, 20}},
+	{"net.inet.tcp.slowhz", []_C_int{4, 2, 6, 5}},
+	{"net.inet.tcp.stats", []_C_int{4, 2, 6, 21}},
+	{"net.inet.tcp.synbucketlimit", []_C_int{4, 2, 6, 16}},
+	{"net.inet.tcp.syncachelimit", []_C_int{4, 2, 6, 15}},
+	{"net.inet.udp.baddynamic", []_C_int{4, 2, 17, 2}},
+	{"net.inet.udp.checksum", []_C_int{4, 2, 17, 1}},
+	{"net.inet.udp.recvspace", []_C_int{4, 2, 17, 3}},
+	{"net.inet.udp.sendspace", []_C_int{4, 2, 17, 4}},
+	{"net.inet.udp.stats", []_C_int{4, 2, 17, 5}},
+	{"net.inet6.divert.recvspace", []_C_int{4, 24, 86, 1}},
+	{"net.inet6.divert.sendspace", []_C_int{4, 24, 86, 2}},
+	{"net.inet6.divert.stats", []_C_int{4, 24, 86, 3}},
+	{"net.inet6.icmp6.errppslimit", []_C_int{4, 24, 30, 14}},
+	{"net.inet6.icmp6.mtudisc_hiwat", []_C_int{4, 24, 30, 16}},
+	{"net.inet6.icmp6.mtudisc_lowat", []_C_int{4, 24, 30, 17}},
+	{"net.inet6.icmp6.nd6_debug", []_C_int{4, 24, 30, 18}},
+	{"net.inet6.icmp6.nd6_delay", []_C_int{4, 24, 30, 8}},
+	{"net.inet6.icmp6.nd6_maxnudhint", []_C_int{4, 24, 30, 15}},
+	{"net.inet6.icmp6.nd6_mmaxtries", []_C_int{4, 24, 30, 10}},
+	{"net.inet6.icmp6.nd6_prune", []_C_int{4, 24, 30, 6}},
+	{"net.inet6.icmp6.nd6_umaxtries", []_C_int{4, 24, 30, 9}},
+	{"net.inet6.icmp6.nd6_useloopback", []_C_int{4, 24, 30, 11}},
+	{"net.inet6.icmp6.nodeinfo", []_C_int{4, 24, 30, 13}},
+	{"net.inet6.icmp6.rediraccept", []_C_int{4, 24, 30, 2}},
+	{"net.inet6.icmp6.redirtimeout", []_C_int{4, 24, 30, 3}},
+	{"net.inet6.ip6.accept_rtadv", []_C_int{4, 24, 17, 12}},
+	{"net.inet6.ip6.auto_flowlabel", []_C_int{4, 24, 17, 17}},
+	{"net.inet6.ip6.dad_count", []_C_int{4, 24, 17, 16}},
+	{"net.inet6.ip6.dad_pending", []_C_int{4, 24, 17, 49}},
+	{"net.inet6.ip6.defmcasthlim", []_C_int{4, 24, 17, 18}},
+	{"net.inet6.ip6.forwarding", []_C_int{4, 24, 17, 1}},
+	{"net.inet6.ip6.forwsrcrt", []_C_int{4, 24, 17, 5}},
+	{"net.inet6.ip6.hdrnestlimit", []_C_int{4, 24, 17, 15}},
+	{"net.inet6.ip6.hlim", []_C_int{4, 24, 17, 3}},
+	{"net.inet6.ip6.kame_version", []_C_int{4, 24, 17, 20}},
+	{"net.inet6.ip6.keepfaith", []_C_int{4, 24, 17, 13}},
+	{"net.inet6.ip6.log_interval", []_C_int{4, 24, 17, 14}},
+	{"net.inet6.ip6.maxdynroutes", []_C_int{4, 24, 17, 48}},
+	{"net.inet6.ip6.maxfragpackets", []_C_int{4, 24, 17, 9}},
+	{"net.inet6.ip6.maxfrags", []_C_int{4, 24, 17, 41}},
+	{"net.inet6.ip6.maxifdefrouters", []_C_int{4, 24, 17, 47}},
+	{"net.inet6.ip6.maxifprefixes", []_C_int{4, 24, 17, 46}},
+	{"net.inet6.ip6.mforwarding", []_C_int{4, 24, 17, 42}},
+	{"net.inet6.ip6.mrtproto", []_C_int{4, 24, 17, 8}},
+	{"net.inet6.ip6.mtu", []_C_int{4, 24, 17, 4}},
+	{"net.inet6.ip6.multicast_mtudisc", []_C_int{4, 24, 17, 44}},
+	{"net.inet6.ip6.multipath", []_C_int{4, 24, 17, 43}},
+	{"net.inet6.ip6.neighborgcthresh", []_C_int{4, 24, 17, 45}},
+	{"net.inet6.ip6.redirect", []_C_int{4, 24, 17, 2}},
+	{"net.inet6.ip6.rr_prune", []_C_int{4, 24, 17, 22}},
+	{"net.inet6.ip6.sourcecheck", []_C_int{4, 24, 17, 10}},
+	{"net.inet6.ip6.sourcecheck_logint", []_C_int{4, 24, 17, 11}},
+	{"net.inet6.ip6.use_deprecated", []_C_int{4, 24, 17, 21}},
+	{"net.inet6.ip6.v6only", []_C_int{4, 24, 17, 24}},
+	{"net.key.sadb_dump", []_C_int{4, 30, 1}},
+	{"net.key.spd_dump", []_C_int{4, 30, 2}},
+	{"net.mpls.ifq.congestion", []_C_int{4, 33, 3, 4}},
+	{"net.mpls.ifq.drops", []_C_int{4, 33, 3, 3}},
+	{"net.mpls.ifq.len", []_C_int{4, 33, 3, 1}},
+	{"net.mpls.ifq.maxlen", []_C_int{4, 33, 3, 2}},
+	{"net.mpls.mapttl_ip", []_C_int{4, 33, 5}},
+	{"net.mpls.mapttl_ip6", []_C_int{4, 33, 6}},
+	{"net.mpls.maxloop_inkernel", []_C_int{4, 33, 4}},
+	{"net.mpls.ttl", []_C_int{4, 33, 2}},
+	{"net.pflow.stats", []_C_int{4, 34, 1}},
+	{"net.pipex.enable", []_C_int{4, 35, 1}},
+	{"user.bc_base_max", []_C_int{8, 2}},
+	{"user.bc_dim_max", []_C_int{8, 3}},
+	{"user.bc_scale_max", []_C_int{8, 4}},
+	{"user.bc_string_max", []_C_int{8, 5}},
+	{"user.coll_weights_max", []_C_int{8, 6}},
+	{"user.cs_path", []_C_int{8, 1}},
+	{"user.expr_nest_max", []_C_int{8, 7}},
+	{"user.line_max", []_C_int{8, 8}},
+	{"user.posix2_c_bind", []_C_int{8, 11}},
+	{"user.posix2_c_dev", []_C_int{8, 12}},
+	{"user.posix2_char_term", []_C_int{8, 13}},
+	{"user.posix2_fort_dev", []_C_int{8, 14}},
+	{"user.posix2_fort_run", []_C_int{8, 15}},
+	{"user.posix2_localedef", []_C_int{8, 16}},
+	{"user.posix2_sw_dev", []_C_int{8, 17}},
+	{"user.posix2_upe", []_C_int{8, 18}},
+	{"user.posix2_version", []_C_int{8, 10}},
+	{"user.re_dup_max", []_C_int{8, 9}},
+	{"user.stream_max", []_C_int{8, 19}},
+	{"user.tzname_max", []_C_int{8, 20}},
+	{"vm.anonmin", []_C_int{2, 7}},
+	{"vm.loadavg", []_C_int{2, 2}},
+	{"vm.maxslp", []_C_int{2, 10}},
+	{"vm.nkmempages", []_C_int{2, 6}},
+	{"vm.psstrings", []_C_int{2, 3}},
+	{"vm.swapencrypt.enable", []_C_int{2, 5, 0}},
+	{"vm.swapencrypt.keyscreated", []_C_int{2, 5, 1}},
+	{"vm.swapencrypt.keysdeleted", []_C_int{2, 5, 2}},
+	{"vm.uspace", []_C_int{2, 11}},
+	{"vm.uvmexp", []_C_int{2, 4}},
+	{"vm.vmmeter", []_C_int{2, 1}},
+	{"vm.vnodemin", []_C_int{2, 9}},
+	{"vm.vtextmin", []_C_int{2, 8}},
+}
diff --git a/src/pkg/syscall/zsysnum_darwin_386.go b/src/pkg/syscall/zsysnum_darwin_386.go
index 50aec39..abdef77 100644
--- a/src/pkg/syscall/zsysnum_darwin_386.go
+++ b/src/pkg/syscall/zsysnum_darwin_386.go
@@ -4,352 +4,357 @@
 package syscall
 
 const (
-	SYS_SYSCALL                       = 0
-	SYS_EXIT                          = 1
-	SYS_FORK                          = 2
-	SYS_READ                          = 3
-	SYS_WRITE                         = 4
-	SYS_OPEN                          = 5
-	SYS_CLOSE                         = 6
-	SYS_WAIT4                         = 7
-	SYS_LINK                          = 9
-	SYS_UNLINK                        = 10
-	SYS_CHDIR                         = 12
-	SYS_FCHDIR                        = 13
-	SYS_MKNOD                         = 14
-	SYS_CHMOD                         = 15
-	SYS_CHOWN                         = 16
-	SYS_GETFSSTAT                     = 18
-	SYS_GETPID                        = 20
-	SYS_SETUID                        = 23
-	SYS_GETUID                        = 24
-	SYS_GETEUID                       = 25
-	SYS_PTRACE                        = 26
-	SYS_RECVMSG                       = 27
-	SYS_SENDMSG                       = 28
-	SYS_RECVFROM                      = 29
-	SYS_ACCEPT                        = 30
-	SYS_GETPEERNAME                   = 31
-	SYS_GETSOCKNAME                   = 32
-	SYS_ACCESS                        = 33
-	SYS_CHFLAGS                       = 34
-	SYS_FCHFLAGS                      = 35
-	SYS_SYNC                          = 36
-	SYS_KILL                          = 37
-	SYS_GETPPID                       = 39
-	SYS_DUP                           = 41
-	SYS_PIPE                          = 42
-	SYS_GETEGID                       = 43
-	SYS_PROFIL                        = 44
-	SYS_SIGACTION                     = 46
-	SYS_GETGID                        = 47
-	SYS_SIGPROCMASK                   = 48
-	SYS_GETLOGIN                      = 49
-	SYS_SETLOGIN                      = 50
-	SYS_ACCT                          = 51
-	SYS_SIGPENDING                    = 52
-	SYS_SIGALTSTACK                   = 53
-	SYS_IOCTL                         = 54
-	SYS_REBOOT                        = 55
-	SYS_REVOKE                        = 56
-	SYS_SYMLINK                       = 57
-	SYS_READLINK                      = 58
-	SYS_EXECVE                        = 59
-	SYS_UMASK                         = 60
-	SYS_CHROOT                        = 61
-	SYS_MSYNC                         = 65
-	SYS_VFORK                         = 66
-	SYS_MUNMAP                        = 73
-	SYS_MPROTECT                      = 74
-	SYS_MADVISE                       = 75
-	SYS_MINCORE                       = 78
-	SYS_GETGROUPS                     = 79
-	SYS_SETGROUPS                     = 80
-	SYS_GETPGRP                       = 81
-	SYS_SETPGID                       = 82
-	SYS_SETITIMER                     = 83
-	SYS_SWAPON                        = 85
-	SYS_GETITIMER                     = 86
-	SYS_GETDTABLESIZE                 = 89
-	SYS_DUP2                          = 90
-	SYS_FCNTL                         = 92
-	SYS_SELECT                        = 93
-	SYS_FSYNC                         = 95
-	SYS_SETPRIORITY                   = 96
-	SYS_SOCKET                        = 97
-	SYS_CONNECT                       = 98
-	SYS_GETPRIORITY                   = 100
-	SYS_BIND                          = 104
-	SYS_SETSOCKOPT                    = 105
-	SYS_LISTEN                        = 106
-	SYS_SIGSUSPEND                    = 111
-	SYS_GETTIMEOFDAY                  = 116
-	SYS_GETRUSAGE                     = 117
-	SYS_GETSOCKOPT                    = 118
-	SYS_READV                         = 120
-	SYS_WRITEV                        = 121
-	SYS_SETTIMEOFDAY                  = 122
-	SYS_FCHOWN                        = 123
-	SYS_FCHMOD                        = 124
-	SYS_SETREUID                      = 126
-	SYS_SETREGID                      = 127
-	SYS_RENAME                        = 128
-	SYS_FLOCK                         = 131
-	SYS_MKFIFO                        = 132
-	SYS_SENDTO                        = 133
-	SYS_SHUTDOWN                      = 134
-	SYS_SOCKETPAIR                    = 135
-	SYS_MKDIR                         = 136
-	SYS_RMDIR                         = 137
-	SYS_UTIMES                        = 138
-	SYS_FUTIMES                       = 139
-	SYS_ADJTIME                       = 140
-	SYS_GETHOSTUUID                   = 142
-	SYS_SETSID                        = 147
-	SYS_GETPGID                       = 151
-	SYS_SETPRIVEXEC                   = 152
-	SYS_PREAD                         = 153
-	SYS_PWRITE                        = 154
-	SYS_NFSSVC                        = 155
-	SYS_STATFS                        = 157
-	SYS_FSTATFS                       = 158
-	SYS_UNMOUNT                       = 159
-	SYS_GETFH                         = 161
-	SYS_QUOTACTL                      = 165
-	SYS_MOUNT                         = 167
-	SYS_CSOPS                         = 169
-	SYS_WAITID                        = 173
-	SYS_ADD_PROFIL                    = 176
-	SYS_KDEBUG_TRACE                  = 180
-	SYS_SETGID                        = 181
-	SYS_SETEGID                       = 182
-	SYS_SETEUID                       = 183
-	SYS_SIGRETURN                     = 184
-	SYS_CHUD                          = 185
-	SYS_FDATASYNC                     = 187
-	SYS_STAT                          = 188
-	SYS_FSTAT                         = 189
-	SYS_LSTAT                         = 190
-	SYS_PATHCONF                      = 191
-	SYS_FPATHCONF                     = 192
-	SYS_GETRLIMIT                     = 194
-	SYS_SETRLIMIT                     = 195
-	SYS_GETDIRENTRIES                 = 196
-	SYS_MMAP                          = 197
-	SYS_LSEEK                         = 199
-	SYS_TRUNCATE                      = 200
-	SYS_FTRUNCATE                     = 201
-	SYS___SYSCTL                      = 202
-	SYS_MLOCK                         = 203
-	SYS_MUNLOCK                       = 204
-	SYS_UNDELETE                      = 205
-	SYS_ATSOCKET                      = 206
-	SYS_ATGETMSG                      = 207
-	SYS_ATPUTMSG                      = 208
-	SYS_ATPSNDREQ                     = 209
-	SYS_ATPSNDRSP                     = 210
-	SYS_ATPGETREQ                     = 211
-	SYS_ATPGETRSP                     = 212
-	SYS_MKCOMPLEX                     = 216
-	SYS_STATV                         = 217
-	SYS_LSTATV                        = 218
-	SYS_FSTATV                        = 219
-	SYS_GETATTRLIST                   = 220
-	SYS_SETATTRLIST                   = 221
-	SYS_GETDIRENTRIESATTR             = 222
-	SYS_EXCHANGEDATA                  = 223
-	SYS_SEARCHFS                      = 225
-	SYS_DELETE                        = 226
-	SYS_COPYFILE                      = 227
-	SYS_FGETATTRLIST                  = 228
-	SYS_FSETATTRLIST                  = 229
-	SYS_POLL                          = 230
-	SYS_WATCHEVENT                    = 231
-	SYS_WAITEVENT                     = 232
-	SYS_MODWATCH                      = 233
-	SYS_GETXATTR                      = 234
-	SYS_FGETXATTR                     = 235
-	SYS_SETXATTR                      = 236
-	SYS_FSETXATTR                     = 237
-	SYS_REMOVEXATTR                   = 238
-	SYS_FREMOVEXATTR                  = 239
-	SYS_LISTXATTR                     = 240
-	SYS_FLISTXATTR                    = 241
-	SYS_FSCTL                         = 242
-	SYS_INITGROUPS                    = 243
-	SYS_POSIX_SPAWN                   = 244
-	SYS_FFSCTL                        = 245
-	SYS_NFSCLNT                       = 247
-	SYS_FHOPEN                        = 248
-	SYS_MINHERIT                      = 250
-	SYS_SEMSYS                        = 251
-	SYS_MSGSYS                        = 252
-	SYS_SHMSYS                        = 253
-	SYS_SEMCTL                        = 254
-	SYS_SEMGET                        = 255
-	SYS_SEMOP                         = 256
-	SYS_MSGCTL                        = 258
-	SYS_MSGGET                        = 259
-	SYS_MSGSND                        = 260
-	SYS_MSGRCV                        = 261
-	SYS_SHMAT                         = 262
-	SYS_SHMCTL                        = 263
-	SYS_SHMDT                         = 264
-	SYS_SHMGET                        = 265
-	SYS_SHM_OPEN                      = 266
-	SYS_SHM_UNLINK                    = 267
-	SYS_SEM_OPEN                      = 268
-	SYS_SEM_CLOSE                     = 269
-	SYS_SEM_UNLINK                    = 270
-	SYS_SEM_WAIT                      = 271
-	SYS_SEM_TRYWAIT                   = 272
-	SYS_SEM_POST                      = 273
-	SYS_SEM_GETVALUE                  = 274
-	SYS_SEM_INIT                      = 275
-	SYS_SEM_DESTROY                   = 276
-	SYS_OPEN_EXTENDED                 = 277
-	SYS_UMASK_EXTENDED                = 278
-	SYS_STAT_EXTENDED                 = 279
-	SYS_LSTAT_EXTENDED                = 280
-	SYS_FSTAT_EXTENDED                = 281
-	SYS_CHMOD_EXTENDED                = 282
-	SYS_FCHMOD_EXTENDED               = 283
-	SYS_ACCESS_EXTENDED               = 284
-	SYS_SETTID                        = 285
-	SYS_GETTID                        = 286
-	SYS_SETSGROUPS                    = 287
-	SYS_GETSGROUPS                    = 288
-	SYS_SETWGROUPS                    = 289
-	SYS_GETWGROUPS                    = 290
-	SYS_MKFIFO_EXTENDED               = 291
-	SYS_MKDIR_EXTENDED                = 292
-	SYS_IDENTITYSVC                   = 293
-	SYS_SHARED_REGION_CHECK_NP        = 294
-	SYS_SHARED_REGION_MAP_NP          = 295
-	SYS_VM_PRESSURE_MONITOR           = 296
-	SYS_PSYNCH_RW_LONGRDLOCK          = 297
-	SYS_PSYNCH_RW_YIELDWRLOCK         = 298
-	SYS_PSYNCH_RW_DOWNGRADE           = 299
-	SYS_PSYNCH_RW_UPGRADE             = 300
-	SYS_PSYNCH_MUTEXWAIT              = 301
-	SYS_PSYNCH_MUTEXDROP              = 302
-	SYS_PSYNCH_CVBROAD                = 303
-	SYS_PSYNCH_CVSIGNAL               = 304
-	SYS_PSYNCH_CVWAIT                 = 305
-	SYS_PSYNCH_RW_RDLOCK              = 306
-	SYS_PSYNCH_RW_WRLOCK              = 307
-	SYS_PSYNCH_RW_UNLOCK              = 308
-	SYS_PSYNCH_RW_UNLOCK2             = 309
-	SYS_GETSID                        = 310
-	SYS_SETTID_WITH_PID               = 311
-	SYS_AIO_FSYNC                     = 313
-	SYS_AIO_RETURN                    = 314
-	SYS_AIO_SUSPEND                   = 315
-	SYS_AIO_CANCEL                    = 316
-	SYS_AIO_ERROR                     = 317
-	SYS_AIO_READ                      = 318
-	SYS_AIO_WRITE                     = 319
-	SYS_LIO_LISTIO                    = 320
-	SYS_IOPOLICYSYS                   = 322
-	SYS_MLOCKALL                      = 324
-	SYS_MUNLOCKALL                    = 325
-	SYS_ISSETUGID                     = 327
-	SYS___PTHREAD_KILL                = 328
-	SYS___PTHREAD_SIGMASK             = 329
-	SYS___SIGWAIT                     = 330
-	SYS___DISABLE_THREADSIGNAL        = 331
-	SYS___PTHREAD_MARKCANCEL          = 332
-	SYS___PTHREAD_CANCELED            = 333
-	SYS___SEMWAIT_SIGNAL              = 334
-	SYS_PROC_INFO                     = 336
-	SYS_SENDFILE                      = 337
-	SYS_STAT64                        = 338
-	SYS_FSTAT64                       = 339
-	SYS_LSTAT64                       = 340
-	SYS_STAT64_EXTENDED               = 341
-	SYS_LSTAT64_EXTENDED              = 342
-	SYS_FSTAT64_EXTENDED              = 343
-	SYS_GETDIRENTRIES64               = 344
-	SYS_STATFS64                      = 345
-	SYS_FSTATFS64                     = 346
-	SYS_GETFSSTAT64                   = 347
-	SYS___PTHREAD_CHDIR               = 348
-	SYS___PTHREAD_FCHDIR              = 349
-	SYS_AUDIT                         = 350
-	SYS_AUDITON                       = 351
-	SYS_GETAUID                       = 353
-	SYS_SETAUID                       = 354
-	SYS_GETAUDIT                      = 355
-	SYS_SETAUDIT                      = 356
-	SYS_GETAUDIT_ADDR                 = 357
-	SYS_SETAUDIT_ADDR                 = 358
-	SYS_AUDITCTL                      = 359
-	SYS_BSDTHREAD_CREATE              = 360
-	SYS_BSDTHREAD_TERMINATE           = 361
-	SYS_KQUEUE                        = 362
-	SYS_KEVENT                        = 363
-	SYS_LCHOWN                        = 364
-	SYS_STACK_SNAPSHOT                = 365
-	SYS_BSDTHREAD_REGISTER            = 366
-	SYS_WORKQ_OPEN                    = 367
-	SYS_WORKQ_KERNRETURN              = 368
-	SYS_KEVENT64                      = 369
-	SYS___OLD_SEMWAIT_SIGNAL          = 370
-	SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371
-	SYS_THREAD_SELFID                 = 372
-	SYS___MAC_EXECVE                  = 380
-	SYS___MAC_SYSCALL                 = 381
-	SYS___MAC_GET_FILE                = 382
-	SYS___MAC_SET_FILE                = 383
-	SYS___MAC_GET_LINK                = 384
-	SYS___MAC_SET_LINK                = 385
-	SYS___MAC_GET_PROC                = 386
-	SYS___MAC_SET_PROC                = 387
-	SYS___MAC_GET_FD                  = 388
-	SYS___MAC_SET_FD                  = 389
-	SYS___MAC_GET_PID                 = 390
-	SYS___MAC_GET_LCID                = 391
-	SYS___MAC_GET_LCTX                = 392
-	SYS___MAC_SET_LCTX                = 393
-	SYS_SETLCID                       = 394
-	SYS_GETLCID                       = 395
-	SYS_READ_NOCANCEL                 = 396
-	SYS_WRITE_NOCANCEL                = 397
-	SYS_OPEN_NOCANCEL                 = 398
-	SYS_CLOSE_NOCANCEL                = 399
-	SYS_WAIT4_NOCANCEL                = 400
-	SYS_RECVMSG_NOCANCEL              = 401
-	SYS_SENDMSG_NOCANCEL              = 402
-	SYS_RECVFROM_NOCANCEL             = 403
-	SYS_ACCEPT_NOCANCEL               = 404
-	SYS_MSYNC_NOCANCEL                = 405
-	SYS_FCNTL_NOCANCEL                = 406
-	SYS_SELECT_NOCANCEL               = 407
-	SYS_FSYNC_NOCANCEL                = 408
-	SYS_CONNECT_NOCANCEL              = 409
-	SYS_SIGSUSPEND_NOCANCEL           = 410
-	SYS_READV_NOCANCEL                = 411
-	SYS_WRITEV_NOCANCEL               = 412
-	SYS_SENDTO_NOCANCEL               = 413
-	SYS_PREAD_NOCANCEL                = 414
-	SYS_PWRITE_NOCANCEL               = 415
-	SYS_WAITID_NOCANCEL               = 416
-	SYS_POLL_NOCANCEL                 = 417
-	SYS_MSGSND_NOCANCEL               = 418
-	SYS_MSGRCV_NOCANCEL               = 419
-	SYS_SEM_WAIT_NOCANCEL             = 420
-	SYS_AIO_SUSPEND_NOCANCEL          = 421
-	SYS___SIGWAIT_NOCANCEL            = 422
-	SYS___SEMWAIT_SIGNAL_NOCANCEL     = 423
-	SYS___MAC_MOUNT                   = 424
-	SYS___MAC_GET_MOUNT               = 425
-	SYS___MAC_GETFSSTAT               = 426
-	SYS_FSGETPATH                     = 427
-	SYS_AUDIT_SESSION_SELF            = 428
-	SYS_AUDIT_SESSION_JOIN            = 429
-	SYS_PID_SUSPEND                   = 430
-	SYS_PID_RESUME                    = 431
-	SYS_FILEPORT_MAKEPORT             = 432
-	SYS_FILEPORT_MAKEFD               = 433
-	SYS_MAXSYSCALL                    = 434
+	SYS_SYSCALL                        = 0
+	SYS_EXIT                           = 1
+	SYS_FORK                           = 2
+	SYS_READ                           = 3
+	SYS_WRITE                          = 4
+	SYS_OPEN                           = 5
+	SYS_CLOSE                          = 6
+	SYS_WAIT4                          = 7
+	SYS_LINK                           = 9
+	SYS_UNLINK                         = 10
+	SYS_CHDIR                          = 12
+	SYS_FCHDIR                         = 13
+	SYS_MKNOD                          = 14
+	SYS_CHMOD                          = 15
+	SYS_CHOWN                          = 16
+	SYS_GETFSSTAT                      = 18
+	SYS_GETPID                         = 20
+	SYS_SETUID                         = 23
+	SYS_GETUID                         = 24
+	SYS_GETEUID                        = 25
+	SYS_PTRACE                         = 26
+	SYS_RECVMSG                        = 27
+	SYS_SENDMSG                        = 28
+	SYS_RECVFROM                       = 29
+	SYS_ACCEPT                         = 30
+	SYS_GETPEERNAME                    = 31
+	SYS_GETSOCKNAME                    = 32
+	SYS_ACCESS                         = 33
+	SYS_CHFLAGS                        = 34
+	SYS_FCHFLAGS                       = 35
+	SYS_SYNC                           = 36
+	SYS_KILL                           = 37
+	SYS_GETPPID                        = 39
+	SYS_DUP                            = 41
+	SYS_PIPE                           = 42
+	SYS_GETEGID                        = 43
+	SYS_PROFIL                         = 44
+	SYS_SIGACTION                      = 46
+	SYS_GETGID                         = 47
+	SYS_SIGPROCMASK                    = 48
+	SYS_GETLOGIN                       = 49
+	SYS_SETLOGIN                       = 50
+	SYS_ACCT                           = 51
+	SYS_SIGPENDING                     = 52
+	SYS_SIGALTSTACK                    = 53
+	SYS_IOCTL                          = 54
+	SYS_REBOOT                         = 55
+	SYS_REVOKE                         = 56
+	SYS_SYMLINK                        = 57
+	SYS_READLINK                       = 58
+	SYS_EXECVE                         = 59
+	SYS_UMASK                          = 60
+	SYS_CHROOT                         = 61
+	SYS_MSYNC                          = 65
+	SYS_VFORK                          = 66
+	SYS_MUNMAP                         = 73
+	SYS_MPROTECT                       = 74
+	SYS_MADVISE                        = 75
+	SYS_MINCORE                        = 78
+	SYS_GETGROUPS                      = 79
+	SYS_SETGROUPS                      = 80
+	SYS_GETPGRP                        = 81
+	SYS_SETPGID                        = 82
+	SYS_SETITIMER                      = 83
+	SYS_SWAPON                         = 85
+	SYS_GETITIMER                      = 86
+	SYS_GETDTABLESIZE                  = 89
+	SYS_DUP2                           = 90
+	SYS_FCNTL                          = 92
+	SYS_SELECT                         = 93
+	SYS_FSYNC                          = 95
+	SYS_SETPRIORITY                    = 96
+	SYS_SOCKET                         = 97
+	SYS_CONNECT                        = 98
+	SYS_GETPRIORITY                    = 100
+	SYS_BIND                           = 104
+	SYS_SETSOCKOPT                     = 105
+	SYS_LISTEN                         = 106
+	SYS_SIGSUSPEND                     = 111
+	SYS_GETTIMEOFDAY                   = 116
+	SYS_GETRUSAGE                      = 117
+	SYS_GETSOCKOPT                     = 118
+	SYS_READV                          = 120
+	SYS_WRITEV                         = 121
+	SYS_SETTIMEOFDAY                   = 122
+	SYS_FCHOWN                         = 123
+	SYS_FCHMOD                         = 124
+	SYS_SETREUID                       = 126
+	SYS_SETREGID                       = 127
+	SYS_RENAME                         = 128
+	SYS_FLOCK                          = 131
+	SYS_MKFIFO                         = 132
+	SYS_SENDTO                         = 133
+	SYS_SHUTDOWN                       = 134
+	SYS_SOCKETPAIR                     = 135
+	SYS_MKDIR                          = 136
+	SYS_RMDIR                          = 137
+	SYS_UTIMES                         = 138
+	SYS_FUTIMES                        = 139
+	SYS_ADJTIME                        = 140
+	SYS_GETHOSTUUID                    = 142
+	SYS_SETSID                         = 147
+	SYS_GETPGID                        = 151
+	SYS_SETPRIVEXEC                    = 152
+	SYS_PREAD                          = 153
+	SYS_PWRITE                         = 154
+	SYS_NFSSVC                         = 155
+	SYS_STATFS                         = 157
+	SYS_FSTATFS                        = 158
+	SYS_UNMOUNT                        = 159
+	SYS_GETFH                          = 161
+	SYS_QUOTACTL                       = 165
+	SYS_MOUNT                          = 167
+	SYS_CSOPS                          = 169
+	SYS_WAITID                         = 173
+	SYS_ADD_PROFIL                     = 176
+	SYS_KDEBUG_TRACE                   = 180
+	SYS_SETGID                         = 181
+	SYS_SETEGID                        = 182
+	SYS_SETEUID                        = 183
+	SYS_SIGRETURN                      = 184
+	SYS_CHUD                           = 185
+	SYS_FDATASYNC                      = 187
+	SYS_STAT                           = 188
+	SYS_FSTAT                          = 189
+	SYS_LSTAT                          = 190
+	SYS_PATHCONF                       = 191
+	SYS_FPATHCONF                      = 192
+	SYS_GETRLIMIT                      = 194
+	SYS_SETRLIMIT                      = 195
+	SYS_GETDIRENTRIES                  = 196
+	SYS_MMAP                           = 197
+	SYS_LSEEK                          = 199
+	SYS_TRUNCATE                       = 200
+	SYS_FTRUNCATE                      = 201
+	SYS___SYSCTL                       = 202
+	SYS_MLOCK                          = 203
+	SYS_MUNLOCK                        = 204
+	SYS_UNDELETE                       = 205
+	SYS_ATSOCKET                       = 206
+	SYS_ATGETMSG                       = 207
+	SYS_ATPUTMSG                       = 208
+	SYS_ATPSNDREQ                      = 209
+	SYS_ATPSNDRSP                      = 210
+	SYS_ATPGETREQ                      = 211
+	SYS_ATPGETRSP                      = 212
+	SYS_MKCOMPLEX                      = 216
+	SYS_STATV                          = 217
+	SYS_LSTATV                         = 218
+	SYS_FSTATV                         = 219
+	SYS_GETATTRLIST                    = 220
+	SYS_SETATTRLIST                    = 221
+	SYS_GETDIRENTRIESATTR              = 222
+	SYS_EXCHANGEDATA                   = 223
+	SYS_SEARCHFS                       = 225
+	SYS_DELETE                         = 226
+	SYS_COPYFILE                       = 227
+	SYS_FGETATTRLIST                   = 228
+	SYS_FSETATTRLIST                   = 229
+	SYS_POLL                           = 230
+	SYS_WATCHEVENT                     = 231
+	SYS_WAITEVENT                      = 232
+	SYS_MODWATCH                       = 233
+	SYS_GETXATTR                       = 234
+	SYS_FGETXATTR                      = 235
+	SYS_SETXATTR                       = 236
+	SYS_FSETXATTR                      = 237
+	SYS_REMOVEXATTR                    = 238
+	SYS_FREMOVEXATTR                   = 239
+	SYS_LISTXATTR                      = 240
+	SYS_FLISTXATTR                     = 241
+	SYS_FSCTL                          = 242
+	SYS_INITGROUPS                     = 243
+	SYS_POSIX_SPAWN                    = 244
+	SYS_FFSCTL                         = 245
+	SYS_NFSCLNT                        = 247
+	SYS_FHOPEN                         = 248
+	SYS_MINHERIT                       = 250
+	SYS_SEMSYS                         = 251
+	SYS_MSGSYS                         = 252
+	SYS_SHMSYS                         = 253
+	SYS_SEMCTL                         = 254
+	SYS_SEMGET                         = 255
+	SYS_SEMOP                          = 256
+	SYS_MSGCTL                         = 258
+	SYS_MSGGET                         = 259
+	SYS_MSGSND                         = 260
+	SYS_MSGRCV                         = 261
+	SYS_SHMAT                          = 262
+	SYS_SHMCTL                         = 263
+	SYS_SHMDT                          = 264
+	SYS_SHMGET                         = 265
+	SYS_SHM_OPEN                       = 266
+	SYS_SHM_UNLINK                     = 267
+	SYS_SEM_OPEN                       = 268
+	SYS_SEM_CLOSE                      = 269
+	SYS_SEM_UNLINK                     = 270
+	SYS_SEM_WAIT                       = 271
+	SYS_SEM_TRYWAIT                    = 272
+	SYS_SEM_POST                       = 273
+	SYS_SEM_GETVALUE                   = 274
+	SYS_SEM_INIT                       = 275
+	SYS_SEM_DESTROY                    = 276
+	SYS_OPEN_EXTENDED                  = 277
+	SYS_UMASK_EXTENDED                 = 278
+	SYS_STAT_EXTENDED                  = 279
+	SYS_LSTAT_EXTENDED                 = 280
+	SYS_FSTAT_EXTENDED                 = 281
+	SYS_CHMOD_EXTENDED                 = 282
+	SYS_FCHMOD_EXTENDED                = 283
+	SYS_ACCESS_EXTENDED                = 284
+	SYS_SETTID                         = 285
+	SYS_GETTID                         = 286
+	SYS_SETSGROUPS                     = 287
+	SYS_GETSGROUPS                     = 288
+	SYS_SETWGROUPS                     = 289
+	SYS_GETWGROUPS                     = 290
+	SYS_MKFIFO_EXTENDED                = 291
+	SYS_MKDIR_EXTENDED                 = 292
+	SYS_IDENTITYSVC                    = 293
+	SYS_SHARED_REGION_CHECK_NP         = 294
+	SYS_VM_PRESSURE_MONITOR            = 296
+	SYS_PSYNCH_RW_LONGRDLOCK           = 297
+	SYS_PSYNCH_RW_YIELDWRLOCK          = 298
+	SYS_PSYNCH_RW_DOWNGRADE            = 299
+	SYS_PSYNCH_RW_UPGRADE              = 300
+	SYS_PSYNCH_MUTEXWAIT               = 301
+	SYS_PSYNCH_MUTEXDROP               = 302
+	SYS_PSYNCH_CVBROAD                 = 303
+	SYS_PSYNCH_CVSIGNAL                = 304
+	SYS_PSYNCH_CVWAIT                  = 305
+	SYS_PSYNCH_RW_RDLOCK               = 306
+	SYS_PSYNCH_RW_WRLOCK               = 307
+	SYS_PSYNCH_RW_UNLOCK               = 308
+	SYS_PSYNCH_RW_UNLOCK2              = 309
+	SYS_GETSID                         = 310
+	SYS_SETTID_WITH_PID                = 311
+	SYS_PSYNCH_CVCLRPREPOST            = 312
+	SYS_AIO_FSYNC                      = 313
+	SYS_AIO_RETURN                     = 314
+	SYS_AIO_SUSPEND                    = 315
+	SYS_AIO_CANCEL                     = 316
+	SYS_AIO_ERROR                      = 317
+	SYS_AIO_READ                       = 318
+	SYS_AIO_WRITE                      = 319
+	SYS_LIO_LISTIO                     = 320
+	SYS_IOPOLICYSYS                    = 322
+	SYS_PROCESS_POLICY                 = 323
+	SYS_MLOCKALL                       = 324
+	SYS_MUNLOCKALL                     = 325
+	SYS_ISSETUGID                      = 327
+	SYS___PTHREAD_KILL                 = 328
+	SYS___PTHREAD_SIGMASK              = 329
+	SYS___SIGWAIT                      = 330
+	SYS___DISABLE_THREADSIGNAL         = 331
+	SYS___PTHREAD_MARKCANCEL           = 332
+	SYS___PTHREAD_CANCELED             = 333
+	SYS___SEMWAIT_SIGNAL               = 334
+	SYS_PROC_INFO                      = 336
+	SYS_SENDFILE                       = 337
+	SYS_STAT64                         = 338
+	SYS_FSTAT64                        = 339
+	SYS_LSTAT64                        = 340
+	SYS_STAT64_EXTENDED                = 341
+	SYS_LSTAT64_EXTENDED               = 342
+	SYS_FSTAT64_EXTENDED               = 343
+	SYS_GETDIRENTRIES64                = 344
+	SYS_STATFS64                       = 345
+	SYS_FSTATFS64                      = 346
+	SYS_GETFSSTAT64                    = 347
+	SYS___PTHREAD_CHDIR                = 348
+	SYS___PTHREAD_FCHDIR               = 349
+	SYS_AUDIT                          = 350
+	SYS_AUDITON                        = 351
+	SYS_GETAUID                        = 353
+	SYS_SETAUID                        = 354
+	SYS_GETAUDIT                       = 355
+	SYS_SETAUDIT                       = 356
+	SYS_GETAUDIT_ADDR                  = 357
+	SYS_SETAUDIT_ADDR                  = 358
+	SYS_AUDITCTL                       = 359
+	SYS_BSDTHREAD_CREATE               = 360
+	SYS_BSDTHREAD_TERMINATE            = 361
+	SYS_KQUEUE                         = 362
+	SYS_KEVENT                         = 363
+	SYS_LCHOWN                         = 364
+	SYS_STACK_SNAPSHOT                 = 365
+	SYS_BSDTHREAD_REGISTER             = 366
+	SYS_WORKQ_OPEN                     = 367
+	SYS_WORKQ_KERNRETURN               = 368
+	SYS_KEVENT64                       = 369
+	SYS___OLD_SEMWAIT_SIGNAL           = 370
+	SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL  = 371
+	SYS_THREAD_SELFID                  = 372
+	SYS___MAC_EXECVE                   = 380
+	SYS___MAC_SYSCALL                  = 381
+	SYS___MAC_GET_FILE                 = 382
+	SYS___MAC_SET_FILE                 = 383
+	SYS___MAC_GET_LINK                 = 384
+	SYS___MAC_SET_LINK                 = 385
+	SYS___MAC_GET_PROC                 = 386
+	SYS___MAC_SET_PROC                 = 387
+	SYS___MAC_GET_FD                   = 388
+	SYS___MAC_SET_FD                   = 389
+	SYS___MAC_GET_PID                  = 390
+	SYS___MAC_GET_LCID                 = 391
+	SYS___MAC_GET_LCTX                 = 392
+	SYS___MAC_SET_LCTX                 = 393
+	SYS_SETLCID                        = 394
+	SYS_GETLCID                        = 395
+	SYS_READ_NOCANCEL                  = 396
+	SYS_WRITE_NOCANCEL                 = 397
+	SYS_OPEN_NOCANCEL                  = 398
+	SYS_CLOSE_NOCANCEL                 = 399
+	SYS_WAIT4_NOCANCEL                 = 400
+	SYS_RECVMSG_NOCANCEL               = 401
+	SYS_SENDMSG_NOCANCEL               = 402
+	SYS_RECVFROM_NOCANCEL              = 403
+	SYS_ACCEPT_NOCANCEL                = 404
+	SYS_MSYNC_NOCANCEL                 = 405
+	SYS_FCNTL_NOCANCEL                 = 406
+	SYS_SELECT_NOCANCEL                = 407
+	SYS_FSYNC_NOCANCEL                 = 408
+	SYS_CONNECT_NOCANCEL               = 409
+	SYS_SIGSUSPEND_NOCANCEL            = 410
+	SYS_READV_NOCANCEL                 = 411
+	SYS_WRITEV_NOCANCEL                = 412
+	SYS_SENDTO_NOCANCEL                = 413
+	SYS_PREAD_NOCANCEL                 = 414
+	SYS_PWRITE_NOCANCEL                = 415
+	SYS_WAITID_NOCANCEL                = 416
+	SYS_POLL_NOCANCEL                  = 417
+	SYS_MSGSND_NOCANCEL                = 418
+	SYS_MSGRCV_NOCANCEL                = 419
+	SYS_SEM_WAIT_NOCANCEL              = 420
+	SYS_AIO_SUSPEND_NOCANCEL           = 421
+	SYS___SIGWAIT_NOCANCEL             = 422
+	SYS___SEMWAIT_SIGNAL_NOCANCEL      = 423
+	SYS___MAC_MOUNT                    = 424
+	SYS___MAC_GET_MOUNT                = 425
+	SYS___MAC_GETFSSTAT                = 426
+	SYS_FSGETPATH                      = 427
+	SYS_AUDIT_SESSION_SELF             = 428
+	SYS_AUDIT_SESSION_JOIN             = 429
+	SYS_FILEPORT_MAKEPORT              = 430
+	SYS_FILEPORT_MAKEFD                = 431
+	SYS_AUDIT_SESSION_PORT             = 432
+	SYS_PID_SUSPEND                    = 433
+	SYS_PID_RESUME                     = 434
+	SYS_PID_HIBERNATE                  = 435
+	SYS_PID_SHUTDOWN_SOCKETS           = 436
+	SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438
+	SYS_MAXSYSCALL                     = 439
 )
diff --git a/src/pkg/syscall/zsysnum_darwin_amd64.go b/src/pkg/syscall/zsysnum_darwin_amd64.go
index 50aec39..abdef77 100644
--- a/src/pkg/syscall/zsysnum_darwin_amd64.go
+++ b/src/pkg/syscall/zsysnum_darwin_amd64.go
@@ -4,352 +4,357 @@
 package syscall
 
 const (
-	SYS_SYSCALL                       = 0
-	SYS_EXIT                          = 1
-	SYS_FORK                          = 2
-	SYS_READ                          = 3
-	SYS_WRITE                         = 4
-	SYS_OPEN                          = 5
-	SYS_CLOSE                         = 6
-	SYS_WAIT4                         = 7
-	SYS_LINK                          = 9
-	SYS_UNLINK                        = 10
-	SYS_CHDIR                         = 12
-	SYS_FCHDIR                        = 13
-	SYS_MKNOD                         = 14
-	SYS_CHMOD                         = 15
-	SYS_CHOWN                         = 16
-	SYS_GETFSSTAT                     = 18
-	SYS_GETPID                        = 20
-	SYS_SETUID                        = 23
-	SYS_GETUID                        = 24
-	SYS_GETEUID                       = 25
-	SYS_PTRACE                        = 26
-	SYS_RECVMSG                       = 27
-	SYS_SENDMSG                       = 28
-	SYS_RECVFROM                      = 29
-	SYS_ACCEPT                        = 30
-	SYS_GETPEERNAME                   = 31
-	SYS_GETSOCKNAME                   = 32
-	SYS_ACCESS                        = 33
-	SYS_CHFLAGS                       = 34
-	SYS_FCHFLAGS                      = 35
-	SYS_SYNC                          = 36
-	SYS_KILL                          = 37
-	SYS_GETPPID                       = 39
-	SYS_DUP                           = 41
-	SYS_PIPE                          = 42
-	SYS_GETEGID                       = 43
-	SYS_PROFIL                        = 44
-	SYS_SIGACTION                     = 46
-	SYS_GETGID                        = 47
-	SYS_SIGPROCMASK                   = 48
-	SYS_GETLOGIN                      = 49
-	SYS_SETLOGIN                      = 50
-	SYS_ACCT                          = 51
-	SYS_SIGPENDING                    = 52
-	SYS_SIGALTSTACK                   = 53
-	SYS_IOCTL                         = 54
-	SYS_REBOOT                        = 55
-	SYS_REVOKE                        = 56
-	SYS_SYMLINK                       = 57
-	SYS_READLINK                      = 58
-	SYS_EXECVE                        = 59
-	SYS_UMASK                         = 60
-	SYS_CHROOT                        = 61
-	SYS_MSYNC                         = 65
-	SYS_VFORK                         = 66
-	SYS_MUNMAP                        = 73
-	SYS_MPROTECT                      = 74
-	SYS_MADVISE                       = 75
-	SYS_MINCORE                       = 78
-	SYS_GETGROUPS                     = 79
-	SYS_SETGROUPS                     = 80
-	SYS_GETPGRP                       = 81
-	SYS_SETPGID                       = 82
-	SYS_SETITIMER                     = 83
-	SYS_SWAPON                        = 85
-	SYS_GETITIMER                     = 86
-	SYS_GETDTABLESIZE                 = 89
-	SYS_DUP2                          = 90
-	SYS_FCNTL                         = 92
-	SYS_SELECT                        = 93
-	SYS_FSYNC                         = 95
-	SYS_SETPRIORITY                   = 96
-	SYS_SOCKET                        = 97
-	SYS_CONNECT                       = 98
-	SYS_GETPRIORITY                   = 100
-	SYS_BIND                          = 104
-	SYS_SETSOCKOPT                    = 105
-	SYS_LISTEN                        = 106
-	SYS_SIGSUSPEND                    = 111
-	SYS_GETTIMEOFDAY                  = 116
-	SYS_GETRUSAGE                     = 117
-	SYS_GETSOCKOPT                    = 118
-	SYS_READV                         = 120
-	SYS_WRITEV                        = 121
-	SYS_SETTIMEOFDAY                  = 122
-	SYS_FCHOWN                        = 123
-	SYS_FCHMOD                        = 124
-	SYS_SETREUID                      = 126
-	SYS_SETREGID                      = 127
-	SYS_RENAME                        = 128
-	SYS_FLOCK                         = 131
-	SYS_MKFIFO                        = 132
-	SYS_SENDTO                        = 133
-	SYS_SHUTDOWN                      = 134
-	SYS_SOCKETPAIR                    = 135
-	SYS_MKDIR                         = 136
-	SYS_RMDIR                         = 137
-	SYS_UTIMES                        = 138
-	SYS_FUTIMES                       = 139
-	SYS_ADJTIME                       = 140
-	SYS_GETHOSTUUID                   = 142
-	SYS_SETSID                        = 147
-	SYS_GETPGID                       = 151
-	SYS_SETPRIVEXEC                   = 152
-	SYS_PREAD                         = 153
-	SYS_PWRITE                        = 154
-	SYS_NFSSVC                        = 155
-	SYS_STATFS                        = 157
-	SYS_FSTATFS                       = 158
-	SYS_UNMOUNT                       = 159
-	SYS_GETFH                         = 161
-	SYS_QUOTACTL                      = 165
-	SYS_MOUNT                         = 167
-	SYS_CSOPS                         = 169
-	SYS_WAITID                        = 173
-	SYS_ADD_PROFIL                    = 176
-	SYS_KDEBUG_TRACE                  = 180
-	SYS_SETGID                        = 181
-	SYS_SETEGID                       = 182
-	SYS_SETEUID                       = 183
-	SYS_SIGRETURN                     = 184
-	SYS_CHUD                          = 185
-	SYS_FDATASYNC                     = 187
-	SYS_STAT                          = 188
-	SYS_FSTAT                         = 189
-	SYS_LSTAT                         = 190
-	SYS_PATHCONF                      = 191
-	SYS_FPATHCONF                     = 192
-	SYS_GETRLIMIT                     = 194
-	SYS_SETRLIMIT                     = 195
-	SYS_GETDIRENTRIES                 = 196
-	SYS_MMAP                          = 197
-	SYS_LSEEK                         = 199
-	SYS_TRUNCATE                      = 200
-	SYS_FTRUNCATE                     = 201
-	SYS___SYSCTL                      = 202
-	SYS_MLOCK                         = 203
-	SYS_MUNLOCK                       = 204
-	SYS_UNDELETE                      = 205
-	SYS_ATSOCKET                      = 206
-	SYS_ATGETMSG                      = 207
-	SYS_ATPUTMSG                      = 208
-	SYS_ATPSNDREQ                     = 209
-	SYS_ATPSNDRSP                     = 210
-	SYS_ATPGETREQ                     = 211
-	SYS_ATPGETRSP                     = 212
-	SYS_MKCOMPLEX                     = 216
-	SYS_STATV                         = 217
-	SYS_LSTATV                        = 218
-	SYS_FSTATV                        = 219
-	SYS_GETATTRLIST                   = 220
-	SYS_SETATTRLIST                   = 221
-	SYS_GETDIRENTRIESATTR             = 222
-	SYS_EXCHANGEDATA                  = 223
-	SYS_SEARCHFS                      = 225
-	SYS_DELETE                        = 226
-	SYS_COPYFILE                      = 227
-	SYS_FGETATTRLIST                  = 228
-	SYS_FSETATTRLIST                  = 229
-	SYS_POLL                          = 230
-	SYS_WATCHEVENT                    = 231
-	SYS_WAITEVENT                     = 232
-	SYS_MODWATCH                      = 233
-	SYS_GETXATTR                      = 234
-	SYS_FGETXATTR                     = 235
-	SYS_SETXATTR                      = 236
-	SYS_FSETXATTR                     = 237
-	SYS_REMOVEXATTR                   = 238
-	SYS_FREMOVEXATTR                  = 239
-	SYS_LISTXATTR                     = 240
-	SYS_FLISTXATTR                    = 241
-	SYS_FSCTL                         = 242
-	SYS_INITGROUPS                    = 243
-	SYS_POSIX_SPAWN                   = 244
-	SYS_FFSCTL                        = 245
-	SYS_NFSCLNT                       = 247
-	SYS_FHOPEN                        = 248
-	SYS_MINHERIT                      = 250
-	SYS_SEMSYS                        = 251
-	SYS_MSGSYS                        = 252
-	SYS_SHMSYS                        = 253
-	SYS_SEMCTL                        = 254
-	SYS_SEMGET                        = 255
-	SYS_SEMOP                         = 256
-	SYS_MSGCTL                        = 258
-	SYS_MSGGET                        = 259
-	SYS_MSGSND                        = 260
-	SYS_MSGRCV                        = 261
-	SYS_SHMAT                         = 262
-	SYS_SHMCTL                        = 263
-	SYS_SHMDT                         = 264
-	SYS_SHMGET                        = 265
-	SYS_SHM_OPEN                      = 266
-	SYS_SHM_UNLINK                    = 267
-	SYS_SEM_OPEN                      = 268
-	SYS_SEM_CLOSE                     = 269
-	SYS_SEM_UNLINK                    = 270
-	SYS_SEM_WAIT                      = 271
-	SYS_SEM_TRYWAIT                   = 272
-	SYS_SEM_POST                      = 273
-	SYS_SEM_GETVALUE                  = 274
-	SYS_SEM_INIT                      = 275
-	SYS_SEM_DESTROY                   = 276
-	SYS_OPEN_EXTENDED                 = 277
-	SYS_UMASK_EXTENDED                = 278
-	SYS_STAT_EXTENDED                 = 279
-	SYS_LSTAT_EXTENDED                = 280
-	SYS_FSTAT_EXTENDED                = 281
-	SYS_CHMOD_EXTENDED                = 282
-	SYS_FCHMOD_EXTENDED               = 283
-	SYS_ACCESS_EXTENDED               = 284
-	SYS_SETTID                        = 285
-	SYS_GETTID                        = 286
-	SYS_SETSGROUPS                    = 287
-	SYS_GETSGROUPS                    = 288
-	SYS_SETWGROUPS                    = 289
-	SYS_GETWGROUPS                    = 290
-	SYS_MKFIFO_EXTENDED               = 291
-	SYS_MKDIR_EXTENDED                = 292
-	SYS_IDENTITYSVC                   = 293
-	SYS_SHARED_REGION_CHECK_NP        = 294
-	SYS_SHARED_REGION_MAP_NP          = 295
-	SYS_VM_PRESSURE_MONITOR           = 296
-	SYS_PSYNCH_RW_LONGRDLOCK          = 297
-	SYS_PSYNCH_RW_YIELDWRLOCK         = 298
-	SYS_PSYNCH_RW_DOWNGRADE           = 299
-	SYS_PSYNCH_RW_UPGRADE             = 300
-	SYS_PSYNCH_MUTEXWAIT              = 301
-	SYS_PSYNCH_MUTEXDROP              = 302
-	SYS_PSYNCH_CVBROAD                = 303
-	SYS_PSYNCH_CVSIGNAL               = 304
-	SYS_PSYNCH_CVWAIT                 = 305
-	SYS_PSYNCH_RW_RDLOCK              = 306
-	SYS_PSYNCH_RW_WRLOCK              = 307
-	SYS_PSYNCH_RW_UNLOCK              = 308
-	SYS_PSYNCH_RW_UNLOCK2             = 309
-	SYS_GETSID                        = 310
-	SYS_SETTID_WITH_PID               = 311
-	SYS_AIO_FSYNC                     = 313
-	SYS_AIO_RETURN                    = 314
-	SYS_AIO_SUSPEND                   = 315
-	SYS_AIO_CANCEL                    = 316
-	SYS_AIO_ERROR                     = 317
-	SYS_AIO_READ                      = 318
-	SYS_AIO_WRITE                     = 319
-	SYS_LIO_LISTIO                    = 320
-	SYS_IOPOLICYSYS                   = 322
-	SYS_MLOCKALL                      = 324
-	SYS_MUNLOCKALL                    = 325
-	SYS_ISSETUGID                     = 327
-	SYS___PTHREAD_KILL                = 328
-	SYS___PTHREAD_SIGMASK             = 329
-	SYS___SIGWAIT                     = 330
-	SYS___DISABLE_THREADSIGNAL        = 331
-	SYS___PTHREAD_MARKCANCEL          = 332
-	SYS___PTHREAD_CANCELED            = 333
-	SYS___SEMWAIT_SIGNAL              = 334
-	SYS_PROC_INFO                     = 336
-	SYS_SENDFILE                      = 337
-	SYS_STAT64                        = 338
-	SYS_FSTAT64                       = 339
-	SYS_LSTAT64                       = 340
-	SYS_STAT64_EXTENDED               = 341
-	SYS_LSTAT64_EXTENDED              = 342
-	SYS_FSTAT64_EXTENDED              = 343
-	SYS_GETDIRENTRIES64               = 344
-	SYS_STATFS64                      = 345
-	SYS_FSTATFS64                     = 346
-	SYS_GETFSSTAT64                   = 347
-	SYS___PTHREAD_CHDIR               = 348
-	SYS___PTHREAD_FCHDIR              = 349
-	SYS_AUDIT                         = 350
-	SYS_AUDITON                       = 351
-	SYS_GETAUID                       = 353
-	SYS_SETAUID                       = 354
-	SYS_GETAUDIT                      = 355
-	SYS_SETAUDIT                      = 356
-	SYS_GETAUDIT_ADDR                 = 357
-	SYS_SETAUDIT_ADDR                 = 358
-	SYS_AUDITCTL                      = 359
-	SYS_BSDTHREAD_CREATE              = 360
-	SYS_BSDTHREAD_TERMINATE           = 361
-	SYS_KQUEUE                        = 362
-	SYS_KEVENT                        = 363
-	SYS_LCHOWN                        = 364
-	SYS_STACK_SNAPSHOT                = 365
-	SYS_BSDTHREAD_REGISTER            = 366
-	SYS_WORKQ_OPEN                    = 367
-	SYS_WORKQ_KERNRETURN              = 368
-	SYS_KEVENT64                      = 369
-	SYS___OLD_SEMWAIT_SIGNAL          = 370
-	SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371
-	SYS_THREAD_SELFID                 = 372
-	SYS___MAC_EXECVE                  = 380
-	SYS___MAC_SYSCALL                 = 381
-	SYS___MAC_GET_FILE                = 382
-	SYS___MAC_SET_FILE                = 383
-	SYS___MAC_GET_LINK                = 384
-	SYS___MAC_SET_LINK                = 385
-	SYS___MAC_GET_PROC                = 386
-	SYS___MAC_SET_PROC                = 387
-	SYS___MAC_GET_FD                  = 388
-	SYS___MAC_SET_FD                  = 389
-	SYS___MAC_GET_PID                 = 390
-	SYS___MAC_GET_LCID                = 391
-	SYS___MAC_GET_LCTX                = 392
-	SYS___MAC_SET_LCTX                = 393
-	SYS_SETLCID                       = 394
-	SYS_GETLCID                       = 395
-	SYS_READ_NOCANCEL                 = 396
-	SYS_WRITE_NOCANCEL                = 397
-	SYS_OPEN_NOCANCEL                 = 398
-	SYS_CLOSE_NOCANCEL                = 399
-	SYS_WAIT4_NOCANCEL                = 400
-	SYS_RECVMSG_NOCANCEL              = 401
-	SYS_SENDMSG_NOCANCEL              = 402
-	SYS_RECVFROM_NOCANCEL             = 403
-	SYS_ACCEPT_NOCANCEL               = 404
-	SYS_MSYNC_NOCANCEL                = 405
-	SYS_FCNTL_NOCANCEL                = 406
-	SYS_SELECT_NOCANCEL               = 407
-	SYS_FSYNC_NOCANCEL                = 408
-	SYS_CONNECT_NOCANCEL              = 409
-	SYS_SIGSUSPEND_NOCANCEL           = 410
-	SYS_READV_NOCANCEL                = 411
-	SYS_WRITEV_NOCANCEL               = 412
-	SYS_SENDTO_NOCANCEL               = 413
-	SYS_PREAD_NOCANCEL                = 414
-	SYS_PWRITE_NOCANCEL               = 415
-	SYS_WAITID_NOCANCEL               = 416
-	SYS_POLL_NOCANCEL                 = 417
-	SYS_MSGSND_NOCANCEL               = 418
-	SYS_MSGRCV_NOCANCEL               = 419
-	SYS_SEM_WAIT_NOCANCEL             = 420
-	SYS_AIO_SUSPEND_NOCANCEL          = 421
-	SYS___SIGWAIT_NOCANCEL            = 422
-	SYS___SEMWAIT_SIGNAL_NOCANCEL     = 423
-	SYS___MAC_MOUNT                   = 424
-	SYS___MAC_GET_MOUNT               = 425
-	SYS___MAC_GETFSSTAT               = 426
-	SYS_FSGETPATH                     = 427
-	SYS_AUDIT_SESSION_SELF            = 428
-	SYS_AUDIT_SESSION_JOIN            = 429
-	SYS_PID_SUSPEND                   = 430
-	SYS_PID_RESUME                    = 431
-	SYS_FILEPORT_MAKEPORT             = 432
-	SYS_FILEPORT_MAKEFD               = 433
-	SYS_MAXSYSCALL                    = 434
+	SYS_SYSCALL                        = 0
+	SYS_EXIT                           = 1
+	SYS_FORK                           = 2
+	SYS_READ                           = 3
+	SYS_WRITE                          = 4
+	SYS_OPEN                           = 5
+	SYS_CLOSE                          = 6
+	SYS_WAIT4                          = 7
+	SYS_LINK                           = 9
+	SYS_UNLINK                         = 10
+	SYS_CHDIR                          = 12
+	SYS_FCHDIR                         = 13
+	SYS_MKNOD                          = 14
+	SYS_CHMOD                          = 15
+	SYS_CHOWN                          = 16
+	SYS_GETFSSTAT                      = 18
+	SYS_GETPID                         = 20
+	SYS_SETUID                         = 23
+	SYS_GETUID                         = 24
+	SYS_GETEUID                        = 25
+	SYS_PTRACE                         = 26
+	SYS_RECVMSG                        = 27
+	SYS_SENDMSG                        = 28
+	SYS_RECVFROM                       = 29
+	SYS_ACCEPT                         = 30
+	SYS_GETPEERNAME                    = 31
+	SYS_GETSOCKNAME                    = 32
+	SYS_ACCESS                         = 33
+	SYS_CHFLAGS                        = 34
+	SYS_FCHFLAGS                       = 35
+	SYS_SYNC                           = 36
+	SYS_KILL                           = 37
+	SYS_GETPPID                        = 39
+	SYS_DUP                            = 41
+	SYS_PIPE                           = 42
+	SYS_GETEGID                        = 43
+	SYS_PROFIL                         = 44
+	SYS_SIGACTION                      = 46
+	SYS_GETGID                         = 47
+	SYS_SIGPROCMASK                    = 48
+	SYS_GETLOGIN                       = 49
+	SYS_SETLOGIN                       = 50
+	SYS_ACCT                           = 51
+	SYS_SIGPENDING                     = 52
+	SYS_SIGALTSTACK                    = 53
+	SYS_IOCTL                          = 54
+	SYS_REBOOT                         = 55
+	SYS_REVOKE                         = 56
+	SYS_SYMLINK                        = 57
+	SYS_READLINK                       = 58
+	SYS_EXECVE                         = 59
+	SYS_UMASK                          = 60
+	SYS_CHROOT                         = 61
+	SYS_MSYNC                          = 65
+	SYS_VFORK                          = 66
+	SYS_MUNMAP                         = 73
+	SYS_MPROTECT                       = 74
+	SYS_MADVISE                        = 75
+	SYS_MINCORE                        = 78
+	SYS_GETGROUPS                      = 79
+	SYS_SETGROUPS                      = 80
+	SYS_GETPGRP                        = 81
+	SYS_SETPGID                        = 82
+	SYS_SETITIMER                      = 83
+	SYS_SWAPON                         = 85
+	SYS_GETITIMER                      = 86
+	SYS_GETDTABLESIZE                  = 89
+	SYS_DUP2                           = 90
+	SYS_FCNTL                          = 92
+	SYS_SELECT                         = 93
+	SYS_FSYNC                          = 95
+	SYS_SETPRIORITY                    = 96
+	SYS_SOCKET                         = 97
+	SYS_CONNECT                        = 98
+	SYS_GETPRIORITY                    = 100
+	SYS_BIND                           = 104
+	SYS_SETSOCKOPT                     = 105
+	SYS_LISTEN                         = 106
+	SYS_SIGSUSPEND                     = 111
+	SYS_GETTIMEOFDAY                   = 116
+	SYS_GETRUSAGE                      = 117
+	SYS_GETSOCKOPT                     = 118
+	SYS_READV                          = 120
+	SYS_WRITEV                         = 121
+	SYS_SETTIMEOFDAY                   = 122
+	SYS_FCHOWN                         = 123
+	SYS_FCHMOD                         = 124
+	SYS_SETREUID                       = 126
+	SYS_SETREGID                       = 127
+	SYS_RENAME                         = 128
+	SYS_FLOCK                          = 131
+	SYS_MKFIFO                         = 132
+	SYS_SENDTO                         = 133
+	SYS_SHUTDOWN                       = 134
+	SYS_SOCKETPAIR                     = 135
+	SYS_MKDIR                          = 136
+	SYS_RMDIR                          = 137
+	SYS_UTIMES                         = 138
+	SYS_FUTIMES                        = 139
+	SYS_ADJTIME                        = 140
+	SYS_GETHOSTUUID                    = 142
+	SYS_SETSID                         = 147
+	SYS_GETPGID                        = 151
+	SYS_SETPRIVEXEC                    = 152
+	SYS_PREAD                          = 153
+	SYS_PWRITE                         = 154
+	SYS_NFSSVC                         = 155
+	SYS_STATFS                         = 157
+	SYS_FSTATFS                        = 158
+	SYS_UNMOUNT                        = 159
+	SYS_GETFH                          = 161
+	SYS_QUOTACTL                       = 165
+	SYS_MOUNT                          = 167
+	SYS_CSOPS                          = 169
+	SYS_WAITID                         = 173
+	SYS_ADD_PROFIL                     = 176
+	SYS_KDEBUG_TRACE                   = 180
+	SYS_SETGID                         = 181
+	SYS_SETEGID                        = 182
+	SYS_SETEUID                        = 183
+	SYS_SIGRETURN                      = 184
+	SYS_CHUD                           = 185
+	SYS_FDATASYNC                      = 187
+	SYS_STAT                           = 188
+	SYS_FSTAT                          = 189
+	SYS_LSTAT                          = 190
+	SYS_PATHCONF                       = 191
+	SYS_FPATHCONF                      = 192
+	SYS_GETRLIMIT                      = 194
+	SYS_SETRLIMIT                      = 195
+	SYS_GETDIRENTRIES                  = 196
+	SYS_MMAP                           = 197
+	SYS_LSEEK                          = 199
+	SYS_TRUNCATE                       = 200
+	SYS_FTRUNCATE                      = 201
+	SYS___SYSCTL                       = 202
+	SYS_MLOCK                          = 203
+	SYS_MUNLOCK                        = 204
+	SYS_UNDELETE                       = 205
+	SYS_ATSOCKET                       = 206
+	SYS_ATGETMSG                       = 207
+	SYS_ATPUTMSG                       = 208
+	SYS_ATPSNDREQ                      = 209
+	SYS_ATPSNDRSP                      = 210
+	SYS_ATPGETREQ                      = 211
+	SYS_ATPGETRSP                      = 212
+	SYS_MKCOMPLEX                      = 216
+	SYS_STATV                          = 217
+	SYS_LSTATV                         = 218
+	SYS_FSTATV                         = 219
+	SYS_GETATTRLIST                    = 220
+	SYS_SETATTRLIST                    = 221
+	SYS_GETDIRENTRIESATTR              = 222
+	SYS_EXCHANGEDATA                   = 223
+	SYS_SEARCHFS                       = 225
+	SYS_DELETE                         = 226
+	SYS_COPYFILE                       = 227
+	SYS_FGETATTRLIST                   = 228
+	SYS_FSETATTRLIST                   = 229
+	SYS_POLL                           = 230
+	SYS_WATCHEVENT                     = 231
+	SYS_WAITEVENT                      = 232
+	SYS_MODWATCH                       = 233
+	SYS_GETXATTR                       = 234
+	SYS_FGETXATTR                      = 235
+	SYS_SETXATTR                       = 236
+	SYS_FSETXATTR                      = 237
+	SYS_REMOVEXATTR                    = 238
+	SYS_FREMOVEXATTR                   = 239
+	SYS_LISTXATTR                      = 240
+	SYS_FLISTXATTR                     = 241
+	SYS_FSCTL                          = 242
+	SYS_INITGROUPS                     = 243
+	SYS_POSIX_SPAWN                    = 244
+	SYS_FFSCTL                         = 245
+	SYS_NFSCLNT                        = 247
+	SYS_FHOPEN                         = 248
+	SYS_MINHERIT                       = 250
+	SYS_SEMSYS                         = 251
+	SYS_MSGSYS                         = 252
+	SYS_SHMSYS                         = 253
+	SYS_SEMCTL                         = 254
+	SYS_SEMGET                         = 255
+	SYS_SEMOP                          = 256
+	SYS_MSGCTL                         = 258
+	SYS_MSGGET                         = 259
+	SYS_MSGSND                         = 260
+	SYS_MSGRCV                         = 261
+	SYS_SHMAT                          = 262
+	SYS_SHMCTL                         = 263
+	SYS_SHMDT                          = 264
+	SYS_SHMGET                         = 265
+	SYS_SHM_OPEN                       = 266
+	SYS_SHM_UNLINK                     = 267
+	SYS_SEM_OPEN                       = 268
+	SYS_SEM_CLOSE                      = 269
+	SYS_SEM_UNLINK                     = 270
+	SYS_SEM_WAIT                       = 271
+	SYS_SEM_TRYWAIT                    = 272
+	SYS_SEM_POST                       = 273
+	SYS_SEM_GETVALUE                   = 274
+	SYS_SEM_INIT                       = 275
+	SYS_SEM_DESTROY                    = 276
+	SYS_OPEN_EXTENDED                  = 277
+	SYS_UMASK_EXTENDED                 = 278
+	SYS_STAT_EXTENDED                  = 279
+	SYS_LSTAT_EXTENDED                 = 280
+	SYS_FSTAT_EXTENDED                 = 281
+	SYS_CHMOD_EXTENDED                 = 282
+	SYS_FCHMOD_EXTENDED                = 283
+	SYS_ACCESS_EXTENDED                = 284
+	SYS_SETTID                         = 285
+	SYS_GETTID                         = 286
+	SYS_SETSGROUPS                     = 287
+	SYS_GETSGROUPS                     = 288
+	SYS_SETWGROUPS                     = 289
+	SYS_GETWGROUPS                     = 290
+	SYS_MKFIFO_EXTENDED                = 291
+	SYS_MKDIR_EXTENDED                 = 292
+	SYS_IDENTITYSVC                    = 293
+	SYS_SHARED_REGION_CHECK_NP         = 294
+	SYS_VM_PRESSURE_MONITOR            = 296
+	SYS_PSYNCH_RW_LONGRDLOCK           = 297
+	SYS_PSYNCH_RW_YIELDWRLOCK          = 298
+	SYS_PSYNCH_RW_DOWNGRADE            = 299
+	SYS_PSYNCH_RW_UPGRADE              = 300
+	SYS_PSYNCH_MUTEXWAIT               = 301
+	SYS_PSYNCH_MUTEXDROP               = 302
+	SYS_PSYNCH_CVBROAD                 = 303
+	SYS_PSYNCH_CVSIGNAL                = 304
+	SYS_PSYNCH_CVWAIT                  = 305
+	SYS_PSYNCH_RW_RDLOCK               = 306
+	SYS_PSYNCH_RW_WRLOCK               = 307
+	SYS_PSYNCH_RW_UNLOCK               = 308
+	SYS_PSYNCH_RW_UNLOCK2              = 309
+	SYS_GETSID                         = 310
+	SYS_SETTID_WITH_PID                = 311
+	SYS_PSYNCH_CVCLRPREPOST            = 312
+	SYS_AIO_FSYNC                      = 313
+	SYS_AIO_RETURN                     = 314
+	SYS_AIO_SUSPEND                    = 315
+	SYS_AIO_CANCEL                     = 316
+	SYS_AIO_ERROR                      = 317
+	SYS_AIO_READ                       = 318
+	SYS_AIO_WRITE                      = 319
+	SYS_LIO_LISTIO                     = 320
+	SYS_IOPOLICYSYS                    = 322
+	SYS_PROCESS_POLICY                 = 323
+	SYS_MLOCKALL                       = 324
+	SYS_MUNLOCKALL                     = 325
+	SYS_ISSETUGID                      = 327
+	SYS___PTHREAD_KILL                 = 328
+	SYS___PTHREAD_SIGMASK              = 329
+	SYS___SIGWAIT                      = 330
+	SYS___DISABLE_THREADSIGNAL         = 331
+	SYS___PTHREAD_MARKCANCEL           = 332
+	SYS___PTHREAD_CANCELED             = 333
+	SYS___SEMWAIT_SIGNAL               = 334
+	SYS_PROC_INFO                      = 336
+	SYS_SENDFILE                       = 337
+	SYS_STAT64                         = 338
+	SYS_FSTAT64                        = 339
+	SYS_LSTAT64                        = 340
+	SYS_STAT64_EXTENDED                = 341
+	SYS_LSTAT64_EXTENDED               = 342
+	SYS_FSTAT64_EXTENDED               = 343
+	SYS_GETDIRENTRIES64                = 344
+	SYS_STATFS64                       = 345
+	SYS_FSTATFS64                      = 346
+	SYS_GETFSSTAT64                    = 347
+	SYS___PTHREAD_CHDIR                = 348
+	SYS___PTHREAD_FCHDIR               = 349
+	SYS_AUDIT                          = 350
+	SYS_AUDITON                        = 351
+	SYS_GETAUID                        = 353
+	SYS_SETAUID                        = 354
+	SYS_GETAUDIT                       = 355
+	SYS_SETAUDIT                       = 356
+	SYS_GETAUDIT_ADDR                  = 357
+	SYS_SETAUDIT_ADDR                  = 358
+	SYS_AUDITCTL                       = 359
+	SYS_BSDTHREAD_CREATE               = 360
+	SYS_BSDTHREAD_TERMINATE            = 361
+	SYS_KQUEUE                         = 362
+	SYS_KEVENT                         = 363
+	SYS_LCHOWN                         = 364
+	SYS_STACK_SNAPSHOT                 = 365
+	SYS_BSDTHREAD_REGISTER             = 366
+	SYS_WORKQ_OPEN                     = 367
+	SYS_WORKQ_KERNRETURN               = 368
+	SYS_KEVENT64                       = 369
+	SYS___OLD_SEMWAIT_SIGNAL           = 370
+	SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL  = 371
+	SYS_THREAD_SELFID                  = 372
+	SYS___MAC_EXECVE                   = 380
+	SYS___MAC_SYSCALL                  = 381
+	SYS___MAC_GET_FILE                 = 382
+	SYS___MAC_SET_FILE                 = 383
+	SYS___MAC_GET_LINK                 = 384
+	SYS___MAC_SET_LINK                 = 385
+	SYS___MAC_GET_PROC                 = 386
+	SYS___MAC_SET_PROC                 = 387
+	SYS___MAC_GET_FD                   = 388
+	SYS___MAC_SET_FD                   = 389
+	SYS___MAC_GET_PID                  = 390
+	SYS___MAC_GET_LCID                 = 391
+	SYS___MAC_GET_LCTX                 = 392
+	SYS___MAC_SET_LCTX                 = 393
+	SYS_SETLCID                        = 394
+	SYS_GETLCID                        = 395
+	SYS_READ_NOCANCEL                  = 396
+	SYS_WRITE_NOCANCEL                 = 397
+	SYS_OPEN_NOCANCEL                  = 398
+	SYS_CLOSE_NOCANCEL                 = 399
+	SYS_WAIT4_NOCANCEL                 = 400
+	SYS_RECVMSG_NOCANCEL               = 401
+	SYS_SENDMSG_NOCANCEL               = 402
+	SYS_RECVFROM_NOCANCEL              = 403
+	SYS_ACCEPT_NOCANCEL                = 404
+	SYS_MSYNC_NOCANCEL                 = 405
+	SYS_FCNTL_NOCANCEL                 = 406
+	SYS_SELECT_NOCANCEL                = 407
+	SYS_FSYNC_NOCANCEL                 = 408
+	SYS_CONNECT_NOCANCEL               = 409
+	SYS_SIGSUSPEND_NOCANCEL            = 410
+	SYS_READV_NOCANCEL                 = 411
+	SYS_WRITEV_NOCANCEL                = 412
+	SYS_SENDTO_NOCANCEL                = 413
+	SYS_PREAD_NOCANCEL                 = 414
+	SYS_PWRITE_NOCANCEL                = 415
+	SYS_WAITID_NOCANCEL                = 416
+	SYS_POLL_NOCANCEL                  = 417
+	SYS_MSGSND_NOCANCEL                = 418
+	SYS_MSGRCV_NOCANCEL                = 419
+	SYS_SEM_WAIT_NOCANCEL              = 420
+	SYS_AIO_SUSPEND_NOCANCEL           = 421
+	SYS___SIGWAIT_NOCANCEL             = 422
+	SYS___SEMWAIT_SIGNAL_NOCANCEL      = 423
+	SYS___MAC_MOUNT                    = 424
+	SYS___MAC_GET_MOUNT                = 425
+	SYS___MAC_GETFSSTAT                = 426
+	SYS_FSGETPATH                      = 427
+	SYS_AUDIT_SESSION_SELF             = 428
+	SYS_AUDIT_SESSION_JOIN             = 429
+	SYS_FILEPORT_MAKEPORT              = 430
+	SYS_FILEPORT_MAKEFD                = 431
+	SYS_AUDIT_SESSION_PORT             = 432
+	SYS_PID_SUSPEND                    = 433
+	SYS_PID_RESUME                     = 434
+	SYS_PID_HIBERNATE                  = 435
+	SYS_PID_SHUTDOWN_SOCKETS           = 436
+	SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438
+	SYS_MAXSYSCALL                     = 439
 )
diff --git a/src/pkg/syscall/zsysnum_freebsd_386.go b/src/pkg/syscall/zsysnum_freebsd_386.go
index a5b7b66..e986aba 100644
--- a/src/pkg/syscall/zsysnum_freebsd_386.go
+++ b/src/pkg/syscall/zsysnum_freebsd_386.go
@@ -1,4 +1,4 @@
-// mksysnum_freebsd.sh 
+// mksysnum_freebsd.pl 
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
@@ -33,7 +33,7 @@ const (
 	SYS_ACCEPT                   = 30  // { int accept(int s, \
 	SYS_GETPEERNAME              = 31  // { int getpeername(int fdes, \
 	SYS_GETSOCKNAME              = 32  // { int getsockname(int fdes, \
-	SYS_ACCESS                   = 33  // { int access(char *path, int flags); }
+	SYS_ACCESS                   = 33  // { int access(char *path, int amode); }
 	SYS_CHFLAGS                  = 34  // { int chflags(char *path, int flags); }
 	SYS_FCHFLAGS                 = 35  // { int fchflags(int fd, int flags); }
 	SYS_SYNC                     = 36  // { int sync(void); }
@@ -146,6 +146,9 @@ const (
 	SYS_KTIMER_GETTIME           = 238 // { int ktimer_gettime(int timerid, struct \
 	SYS_KTIMER_GETOVERRUN        = 239 // { int ktimer_getoverrun(int timerid); }
 	SYS_NANOSLEEP                = 240 // { int nanosleep(const struct timespec *rqtp, \
+	SYS_FFCLOCK_GETCOUNTER       = 241 // { int ffclock_getcounter(ffcounter *ffcount); }
+	SYS_FFCLOCK_SETESTIMATE      = 242 // { int ffclock_setestimate( \
+	SYS_FFCLOCK_GETESTIMATE      = 243 // { int ffclock_getestimate( \
 	SYS_NTP_GETTIME              = 248 // { int ntp_gettime(struct ntptimeval *ntvp); }
 	SYS_MINHERIT                 = 250 // { int minherit(void *addr, size_t len, \
 	SYS_RFORK                    = 251 // { int rfork(int flags); }
@@ -215,7 +218,7 @@ const (
 	SYS_EXTATTR_GET_FD           = 372 // { ssize_t extattr_get_fd(int fd, \
 	SYS_EXTATTR_DELETE_FD        = 373 // { int extattr_delete_fd(int fd, \
 	SYS___SETUGID                = 374 // { int __setugid(int flag); }
-	SYS_EACCESS                  = 376 // { int eaccess(char *path, int flags); }
+	SYS_EACCESS                  = 376 // { int eaccess(char *path, int amode); }
 	SYS_NMOUNT                   = 378 // { int nmount(struct iovec *iovp, \
 	SYS___MAC_GET_PROC           = 384 // { int __mac_get_proc(struct mac *mac_p); }
 	SYS___MAC_SET_PROC           = 385 // { int __mac_set_proc(struct mac *mac_p); }
@@ -296,7 +299,7 @@ const (
 	SYS_CPUSET_GETID             = 486 // { int cpuset_getid(cpulevel_t level, \
 	SYS_CPUSET_GETAFFINITY       = 487 // { int cpuset_getaffinity(cpulevel_t level, \
 	SYS_CPUSET_SETAFFINITY       = 488 // { int cpuset_setaffinity(cpulevel_t level, \
-	SYS_FACCESSAT                = 489 // { int faccessat(int fd, char *path, int mode, \
+	SYS_FACCESSAT                = 489 // { int faccessat(int fd, char *path, int amode, \
 	SYS_FCHMODAT                 = 490 // { int fchmodat(int fd, char *path, mode_t mode, \
 	SYS_FCHOWNAT                 = 491 // { int fchownat(int fd, char *path, uid_t uid, \
 	SYS_FEXECVE                  = 492 // { int fexecve(int fd, char **argv, \
@@ -317,5 +320,21 @@ const (
 	SYS_JAIL_REMOVE              = 508 // { int jail_remove(int jid); }
 	SYS_CLOSEFROM                = 509 // { int closefrom(int lowfd); }
 	SYS_LPATHCONF                = 513 // { int lpathconf(char *path, int name); }
+	SYS_CAP_NEW                  = 514 // { int cap_new(int fd, u_int64_t rights); }
+	SYS_CAP_GETRIGHTS            = 515 // { int cap_getrights(int fd, \
+	SYS_CAP_ENTER                = 516 // { int cap_enter(void); }
+	SYS_CAP_GETMODE              = 517 // { int cap_getmode(u_int *modep); }
+	SYS_PDFORK                   = 518 // { int pdfork(int *fdp, int flags); }
+	SYS_PDKILL                   = 519 // { int pdkill(int fd, int signum); }
+	SYS_PDGETPID                 = 520 // { int pdgetpid(int fd, pid_t *pidp); }
 	SYS_PSELECT                  = 522 // { int pselect(int nd, fd_set *in, \
+	SYS_GETLOGINCLASS            = 523 // { int getloginclass(char *namebuf, \
+	SYS_SETLOGINCLASS            = 524 // { int setloginclass(const char *namebuf); }
+	SYS_RCTL_GET_RACCT           = 525 // { int rctl_get_racct(const void *inbufp, \
+	SYS_RCTL_GET_RULES           = 526 // { int rctl_get_rules(const void *inbufp, \
+	SYS_RCTL_GET_LIMITS          = 527 // { int rctl_get_limits(const void *inbufp, \
+	SYS_RCTL_ADD_RULE            = 528 // { int rctl_add_rule(const void *inbufp, \
+	SYS_RCTL_REMOVE_RULE         = 529 // { int rctl_remove_rule(const void *inbufp, \
+	SYS_POSIX_FALLOCATE          = 530 // { int posix_fallocate(int fd, \
+	SYS_POSIX_FADVISE            = 531 // { int posix_fadvise(int fd, off_t offset, \
 )
diff --git a/src/pkg/syscall/zsysnum_freebsd_amd64.go b/src/pkg/syscall/zsysnum_freebsd_amd64.go
index a5b7b66..e986aba 100644
--- a/src/pkg/syscall/zsysnum_freebsd_amd64.go
+++ b/src/pkg/syscall/zsysnum_freebsd_amd64.go
@@ -1,4 +1,4 @@
-// mksysnum_freebsd.sh 
+// mksysnum_freebsd.pl 
 // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
 
 package syscall
@@ -33,7 +33,7 @@ const (
 	SYS_ACCEPT                   = 30  // { int accept(int s, \
 	SYS_GETPEERNAME              = 31  // { int getpeername(int fdes, \
 	SYS_GETSOCKNAME              = 32  // { int getsockname(int fdes, \
-	SYS_ACCESS                   = 33  // { int access(char *path, int flags); }
+	SYS_ACCESS                   = 33  // { int access(char *path, int amode); }
 	SYS_CHFLAGS                  = 34  // { int chflags(char *path, int flags); }
 	SYS_FCHFLAGS                 = 35  // { int fchflags(int fd, int flags); }
 	SYS_SYNC                     = 36  // { int sync(void); }
@@ -146,6 +146,9 @@ const (
 	SYS_KTIMER_GETTIME           = 238 // { int ktimer_gettime(int timerid, struct \
 	SYS_KTIMER_GETOVERRUN        = 239 // { int ktimer_getoverrun(int timerid); }
 	SYS_NANOSLEEP                = 240 // { int nanosleep(const struct timespec *rqtp, \
+	SYS_FFCLOCK_GETCOUNTER       = 241 // { int ffclock_getcounter(ffcounter *ffcount); }
+	SYS_FFCLOCK_SETESTIMATE      = 242 // { int ffclock_setestimate( \
+	SYS_FFCLOCK_GETESTIMATE      = 243 // { int ffclock_getestimate( \
 	SYS_NTP_GETTIME              = 248 // { int ntp_gettime(struct ntptimeval *ntvp); }
 	SYS_MINHERIT                 = 250 // { int minherit(void *addr, size_t len, \
 	SYS_RFORK                    = 251 // { int rfork(int flags); }
@@ -215,7 +218,7 @@ const (
 	SYS_EXTATTR_GET_FD           = 372 // { ssize_t extattr_get_fd(int fd, \
 	SYS_EXTATTR_DELETE_FD        = 373 // { int extattr_delete_fd(int fd, \
 	SYS___SETUGID                = 374 // { int __setugid(int flag); }
-	SYS_EACCESS                  = 376 // { int eaccess(char *path, int flags); }
+	SYS_EACCESS                  = 376 // { int eaccess(char *path, int amode); }
 	SYS_NMOUNT                   = 378 // { int nmount(struct iovec *iovp, \
 	SYS___MAC_GET_PROC           = 384 // { int __mac_get_proc(struct mac *mac_p); }
 	SYS___MAC_SET_PROC           = 385 // { int __mac_set_proc(struct mac *mac_p); }
@@ -296,7 +299,7 @@ const (
 	SYS_CPUSET_GETID             = 486 // { int cpuset_getid(cpulevel_t level, \
 	SYS_CPUSET_GETAFFINITY       = 487 // { int cpuset_getaffinity(cpulevel_t level, \
 	SYS_CPUSET_SETAFFINITY       = 488 // { int cpuset_setaffinity(cpulevel_t level, \
-	SYS_FACCESSAT                = 489 // { int faccessat(int fd, char *path, int mode, \
+	SYS_FACCESSAT                = 489 // { int faccessat(int fd, char *path, int amode, \
 	SYS_FCHMODAT                 = 490 // { int fchmodat(int fd, char *path, mode_t mode, \
 	SYS_FCHOWNAT                 = 491 // { int fchownat(int fd, char *path, uid_t uid, \
 	SYS_FEXECVE                  = 492 // { int fexecve(int fd, char **argv, \
@@ -317,5 +320,21 @@ const (
 	SYS_JAIL_REMOVE              = 508 // { int jail_remove(int jid); }
 	SYS_CLOSEFROM                = 509 // { int closefrom(int lowfd); }
 	SYS_LPATHCONF                = 513 // { int lpathconf(char *path, int name); }
+	SYS_CAP_NEW                  = 514 // { int cap_new(int fd, u_int64_t rights); }
+	SYS_CAP_GETRIGHTS            = 515 // { int cap_getrights(int fd, \
+	SYS_CAP_ENTER                = 516 // { int cap_enter(void); }
+	SYS_CAP_GETMODE              = 517 // { int cap_getmode(u_int *modep); }
+	SYS_PDFORK                   = 518 // { int pdfork(int *fdp, int flags); }
+	SYS_PDKILL                   = 519 // { int pdkill(int fd, int signum); }
+	SYS_PDGETPID                 = 520 // { int pdgetpid(int fd, pid_t *pidp); }
 	SYS_PSELECT                  = 522 // { int pselect(int nd, fd_set *in, \
+	SYS_GETLOGINCLASS            = 523 // { int getloginclass(char *namebuf, \
+	SYS_SETLOGINCLASS            = 524 // { int setloginclass(const char *namebuf); }
+	SYS_RCTL_GET_RACCT           = 525 // { int rctl_get_racct(const void *inbufp, \
+	SYS_RCTL_GET_RULES           = 526 // { int rctl_get_rules(const void *inbufp, \
+	SYS_RCTL_GET_LIMITS          = 527 // { int rctl_get_limits(const void *inbufp, \
+	SYS_RCTL_ADD_RULE            = 528 // { int rctl_add_rule(const void *inbufp, \
+	SYS_RCTL_REMOVE_RULE         = 529 // { int rctl_remove_rule(const void *inbufp, \
+	SYS_POSIX_FALLOCATE          = 530 // { int posix_fallocate(int fd, \
+	SYS_POSIX_FADVISE            = 531 // { int posix_fadvise(int fd, off_t offset, \
 )
diff --git a/src/pkg/syscall/zsysnum_linux_386.go b/src/pkg/syscall/zsysnum_linux_386.go
index 71e21c7..9864c8c 100644
--- a/src/pkg/syscall/zsysnum_linux_386.go
+++ b/src/pkg/syscall/zsysnum_linux_386.go
@@ -338,4 +338,14 @@ const (
 	SYS_PWRITEV                = 334
 	SYS_RT_TGSIGQUEUEINFO      = 335
 	SYS_PERF_EVENT_OPEN        = 336
+	SYS_RECVMMSG               = 337
+	SYS_FANOTIFY_INIT          = 338
+	SYS_FANOTIFY_MARK          = 339
+	SYS_PRLIMIT64              = 340
+	SYS_NAME_TO_HANDLE_AT      = 341
+	SYS_OPEN_BY_HANDLE_AT      = 342
+	SYS_CLOCK_ADJTIME          = 343
+	SYS_SYNCFS                 = 344
+	SYS_SENDMMSG               = 345
+	SYS_SETNS                  = 346
 )
diff --git a/src/pkg/syscall/zsysnum_linux_amd64.go b/src/pkg/syscall/zsysnum_linux_amd64.go
index 77d4eea..cbbff2a 100644
--- a/src/pkg/syscall/zsysnum_linux_amd64.go
+++ b/src/pkg/syscall/zsysnum_linux_amd64.go
@@ -303,4 +303,14 @@ const (
 	SYS_PWRITEV                = 296
 	SYS_RT_TGSIGQUEUEINFO      = 297
 	SYS_PERF_EVENT_OPEN        = 298
+	SYS_RECVMMSG               = 299
+	SYS_FANOTIFY_INIT          = 300
+	SYS_FANOTIFY_MARK          = 301
+	SYS_PRLIMIT64              = 302
+	SYS_NAME_TO_HANDLE_AT      = 303
+	SYS_OPEN_BY_HANDLE_AT      = 304
+	SYS_CLOCK_ADJTIME          = 305
+	SYS_SYNCFS                 = 306
+	SYS_SENDMMSG               = 307
+	SYS_SETNS                  = 308
 )
diff --git a/src/pkg/syscall/zsysnum_linux_arm.go b/src/pkg/syscall/zsysnum_linux_arm.go
index 8d22929..f751556 100644
--- a/src/pkg/syscall/zsysnum_linux_arm.go
+++ b/src/pkg/syscall/zsysnum_linux_arm.go
@@ -1,3 +1,7 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 // hand generated
 
 package syscall
diff --git a/src/pkg/syscall/zsysnum_netbsd_386.go b/src/pkg/syscall/zsysnum_netbsd_386.go
new file mode 100644
index 0000000..e9a0bcf
--- /dev/null
+++ b/src/pkg/syscall/zsysnum_netbsd_386.go
@@ -0,0 +1,274 @@
+// mksysnum_netbsd.pl 
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+	SYS_EXIT                 = 1   // { void|sys||exit(int rval); }
+	SYS_FORK                 = 2   // { int|sys||fork(void); }
+	SYS_READ                 = 3   // { ssize_t|sys||read(int fd, void *buf, size_t nbyte); }
+	SYS_WRITE                = 4   // { ssize_t|sys||write(int fd, const void *buf, size_t nbyte); }
+	SYS_OPEN                 = 5   // { int|sys||open(const char *path, int flags, ... mode_t mode); }
+	SYS_CLOSE                = 6   // { int|sys||close(int fd); }
+	SYS_LINK                 = 9   // { int|sys||link(const char *path, const char *link); }
+	SYS_UNLINK               = 10  // { int|sys||unlink(const char *path); }
+	SYS_CHDIR                = 12  // { int|sys||chdir(const char *path); }
+	SYS_FCHDIR               = 13  // { int|sys||fchdir(int fd); }
+	SYS_CHMOD                = 15  // { int|sys||chmod(const char *path, mode_t mode); }
+	SYS_CHOWN                = 16  // { int|sys||chown(const char *path, uid_t uid, gid_t gid); }
+	SYS_BREAK                = 17  // { int|sys||obreak(char *nsize); }
+	SYS_GETPID               = 20  // { pid_t|sys||getpid_with_ppid(void); }
+	SYS_UNMOUNT              = 22  // { int|sys||unmount(const char *path, int flags); }
+	SYS_SETUID               = 23  // { int|sys||setuid(uid_t uid); }
+	SYS_GETUID               = 24  // { uid_t|sys||getuid_with_euid(void); }
+	SYS_GETEUID              = 25  // { uid_t|sys||geteuid(void); }
+	SYS_PTRACE               = 26  // { int|sys||ptrace(int req, pid_t pid, void *addr, int data); }
+	SYS_RECVMSG              = 27  // { ssize_t|sys||recvmsg(int s, struct msghdr *msg, int flags); }
+	SYS_SENDMSG              = 28  // { ssize_t|sys||sendmsg(int s, const struct msghdr *msg, int flags); }
+	SYS_RECVFROM             = 29  // { ssize_t|sys||recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlenaddr); }
+	SYS_ACCEPT               = 30  // { int|sys||accept(int s, struct sockaddr *name, socklen_t *anamelen); }
+	SYS_GETPEERNAME          = 31  // { int|sys||getpeername(int fdes, struct sockaddr *asa, socklen_t *alen); }
+	SYS_GETSOCKNAME          = 32  // { int|sys||getsockname(int fdes, struct sockaddr *asa, socklen_t *alen); }
+	SYS_ACCESS               = 33  // { int|sys||access(const char *path, int flags); }
+	SYS_CHFLAGS              = 34  // { int|sys||chflags(const char *path, u_long flags); }
+	SYS_FCHFLAGS             = 35  // { int|sys||fchflags(int fd, u_long flags); }
+	SYS_SYNC                 = 36  // { void|sys||sync(void); }
+	SYS_KILL                 = 37  // { int|sys||kill(pid_t pid, int signum); }
+	SYS_GETPPID              = 39  // { pid_t|sys||getppid(void); }
+	SYS_DUP                  = 41  // { int|sys||dup(int fd); }
+	SYS_PIPE                 = 42  // { int|sys||pipe(void); }
+	SYS_GETEGID              = 43  // { gid_t|sys||getegid(void); }
+	SYS_PROFIL               = 44  // { int|sys||profil(char *samples, size_t size, u_long offset, u_int scale); }
+	SYS_KTRACE               = 45  // { int|sys||ktrace(const char *fname, int ops, int facs, pid_t pid); }
+	SYS_GETGID               = 47  // { gid_t|sys||getgid_with_egid(void); }
+	SYS___GETLOGIN           = 49  // { int|sys||__getlogin(char *namebuf, size_t namelen); }
+	SYS___SETLOGIN           = 50  // { int|sys||__setlogin(const char *namebuf); }
+	SYS_ACCT                 = 51  // { int|sys||acct(const char *path); }
+	SYS_IOCTL                = 54  // { int|sys||ioctl(int fd, u_long com, ... void *data); }
+	SYS_REVOKE               = 56  // { int|sys||revoke(const char *path); }
+	SYS_SYMLINK              = 57  // { int|sys||symlink(const char *path, const char *link); }
+	SYS_READLINK             = 58  // { ssize_t|sys||readlink(const char *path, char *buf, size_t count); }
+	SYS_EXECVE               = 59  // { int|sys||execve(const char *path, char * const *argp, char * const *envp); }
+	SYS_UMASK                = 60  // { mode_t|sys||umask(mode_t newmask); }
+	SYS_CHROOT               = 61  // { int|sys||chroot(const char *path); }
+	SYS_VFORK                = 66  // { int|sys||vfork(void); }
+	SYS_SBRK                 = 69  // { int|sys||sbrk(intptr_t incr); }
+	SYS_SSTK                 = 70  // { int|sys||sstk(int incr); }
+	SYS_VADVISE              = 72  // { int|sys||ovadvise(int anom); }
+	SYS_MUNMAP               = 73  // { int|sys||munmap(void *addr, size_t len); }
+	SYS_MPROTECT             = 74  // { int|sys||mprotect(void *addr, size_t len, int prot); }
+	SYS_MADVISE              = 75  // { int|sys||madvise(void *addr, size_t len, int behav); }
+	SYS_MINCORE              = 78  // { int|sys||mincore(void *addr, size_t len, char *vec); }
+	SYS_GETGROUPS            = 79  // { int|sys||getgroups(int gidsetsize, gid_t *gidset); }
+	SYS_SETGROUPS            = 80  // { int|sys||setgroups(int gidsetsize, const gid_t *gidset); }
+	SYS_GETPGRP              = 81  // { int|sys||getpgrp(void); }
+	SYS_SETPGID              = 82  // { int|sys||setpgid(pid_t pid, pid_t pgid); }
+	SYS_DUP2                 = 90  // { int|sys||dup2(int from, int to); }
+	SYS_FCNTL                = 92  // { int|sys||fcntl(int fd, int cmd, ... void *arg); }
+	SYS_FSYNC                = 95  // { int|sys||fsync(int fd); }
+	SYS_SETPRIORITY          = 96  // { int|sys||setpriority(int which, id_t who, int prio); }
+	SYS_CONNECT              = 98  // { int|sys||connect(int s, const struct sockaddr *name, socklen_t namelen); }
+	SYS_GETPRIORITY          = 100 // { int|sys||getpriority(int which, id_t who); }
+	SYS_BIND                 = 104 // { int|sys||bind(int s, const struct sockaddr *name, socklen_t namelen); }
+	SYS_SETSOCKOPT           = 105 // { int|sys||setsockopt(int s, int level, int name, const void *val, socklen_t valsize); }
+	SYS_LISTEN               = 106 // { int|sys||listen(int s, int backlog); }
+	SYS_GETSOCKOPT           = 118 // { int|sys||getsockopt(int s, int level, int name, void *val, socklen_t *avalsize); }
+	SYS_READV                = 120 // { ssize_t|sys||readv(int fd, const struct iovec *iovp, int iovcnt); }
+	SYS_WRITEV               = 121 // { ssize_t|sys||writev(int fd, const struct iovec *iovp, int iovcnt); }
+	SYS_FCHOWN               = 123 // { int|sys||fchown(int fd, uid_t uid, gid_t gid); }
+	SYS_FCHMOD               = 124 // { int|sys||fchmod(int fd, mode_t mode); }
+	SYS_SETREUID             = 126 // { int|sys||setreuid(uid_t ruid, uid_t euid); }
+	SYS_SETREGID             = 127 // { int|sys||setregid(gid_t rgid, gid_t egid); }
+	SYS_RENAME               = 128 // { int|sys||rename(const char *from, const char *to); }
+	SYS_FLOCK                = 131 // { int|sys||flock(int fd, int how); }
+	SYS_MKFIFO               = 132 // { int|sys||mkfifo(const char *path, mode_t mode); }
+	SYS_SENDTO               = 133 // { ssize_t|sys||sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); }
+	SYS_SHUTDOWN             = 134 // { int|sys||shutdown(int s, int how); }
+	SYS_SOCKETPAIR           = 135 // { int|sys||socketpair(int domain, int type, int protocol, int *rsv); }
+	SYS_MKDIR                = 136 // { int|sys||mkdir(const char *path, mode_t mode); }
+	SYS_RMDIR                = 137 // { int|sys||rmdir(const char *path); }
+	SYS_SETSID               = 147 // { int|sys||setsid(void); }
+	SYS_SYSARCH              = 165 // { int|sys||sysarch(int op, void *parms); }
+	SYS_PREAD                = 173 // { ssize_t|sys||pread(int fd, void *buf, size_t nbyte, int PAD, off_t offset); }
+	SYS_PWRITE               = 174 // { ssize_t|sys||pwrite(int fd, const void *buf, size_t nbyte, int PAD, off_t offset); }
+	SYS_NTP_ADJTIME          = 176 // { int|sys||ntp_adjtime(struct timex *tp); }
+	SYS_SETGID               = 181 // { int|sys||setgid(gid_t gid); }
+	SYS_SETEGID              = 182 // { int|sys||setegid(gid_t egid); }
+	SYS_SETEUID              = 183 // { int|sys||seteuid(uid_t euid); }
+	SYS_PATHCONF             = 191 // { long|sys||pathconf(const char *path, int name); }
+	SYS_FPATHCONF            = 192 // { long|sys||fpathconf(int fd, int name); }
+	SYS_GETRLIMIT            = 194 // { int|sys||getrlimit(int which, struct rlimit *rlp); }
+	SYS_SETRLIMIT            = 195 // { int|sys||setrlimit(int which, const struct rlimit *rlp); }
+	SYS_MMAP                 = 197 // { void *|sys||mmap(void *addr, size_t len, int prot, int flags, int fd, long PAD, off_t pos); }
+	SYS_LSEEK                = 199 // { off_t|sys||lseek(int fd, int PAD, off_t offset, int whence); }
+	SYS_TRUNCATE             = 200 // { int|sys||truncate(const char *path, int PAD, off_t length); }
+	SYS_FTRUNCATE            = 201 // { int|sys||ftruncate(int fd, int PAD, off_t length); }
+	SYS___SYSCTL             = 202 // { int|sys||__sysctl(const int *name, u_int namelen, void *old, size_t *oldlenp, const void *new, size_t newlen); }
+	SYS_MLOCK                = 203 // { int|sys||mlock(const void *addr, size_t len); }
+	SYS_MUNLOCK              = 204 // { int|sys||munlock(const void *addr, size_t len); }
+	SYS_UNDELETE             = 205 // { int|sys||undelete(const char *path); }
+	SYS_GETPGID              = 207 // { pid_t|sys||getpgid(pid_t pid); }
+	SYS_REBOOT               = 208 // { int|sys||reboot(int opt, char *bootstr); }
+	SYS_POLL                 = 209 // { int|sys||poll(struct pollfd *fds, u_int nfds, int timeout); }
+	SYS_SEMGET               = 221 // { int|sys||semget(key_t key, int nsems, int semflg); }
+	SYS_SEMOP                = 222 // { int|sys||semop(int semid, struct sembuf *sops, size_t nsops); }
+	SYS_SEMCONFIG            = 223 // { int|sys||semconfig(int flag); }
+	SYS_MSGGET               = 225 // { int|sys||msgget(key_t key, int msgflg); }
+	SYS_MSGSND               = 226 // { int|sys||msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); }
+	SYS_MSGRCV               = 227 // { ssize_t|sys||msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); }
+	SYS_SHMAT                = 228 // { void *|sys||shmat(int shmid, const void *shmaddr, int shmflg); }
+	SYS_SHMDT                = 230 // { int|sys||shmdt(const void *shmaddr); }
+	SYS_SHMGET               = 231 // { int|sys||shmget(key_t key, size_t size, int shmflg); }
+	SYS_TIMER_CREATE         = 235 // { int|sys||timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid); }
+	SYS_TIMER_DELETE         = 236 // { int|sys||timer_delete(timer_t timerid); }
+	SYS_TIMER_GETOVERRUN     = 239 // { int|sys||timer_getoverrun(timer_t timerid); }
+	SYS_FDATASYNC            = 241 // { int|sys||fdatasync(int fd); }
+	SYS_MLOCKALL             = 242 // { int|sys||mlockall(int flags); }
+	SYS_MUNLOCKALL           = 243 // { int|sys||munlockall(void); }
+	SYS_SIGQUEUEINFO         = 245 // { int|sys||sigqueueinfo(pid_t pid, const siginfo_t *info); }
+	SYS_MODCTL               = 246 // { int|sys||modctl(int cmd, void *arg); }
+	SYS___POSIX_RENAME       = 270 // { int|sys||__posix_rename(const char *from, const char *to); }
+	SYS_SWAPCTL              = 271 // { int|sys||swapctl(int cmd, void *arg, int misc); }
+	SYS_MINHERIT             = 273 // { int|sys||minherit(void *addr, size_t len, int inherit); }
+	SYS_LCHMOD               = 274 // { int|sys||lchmod(const char *path, mode_t mode); }
+	SYS_LCHOWN               = 275 // { int|sys||lchown(const char *path, uid_t uid, gid_t gid); }
+	SYS___POSIX_CHOWN        = 283 // { int|sys||__posix_chown(const char *path, uid_t uid, gid_t gid); }
+	SYS___POSIX_FCHOWN       = 284 // { int|sys||__posix_fchown(int fd, uid_t uid, gid_t gid); }
+	SYS___POSIX_LCHOWN       = 285 // { int|sys||__posix_lchown(const char *path, uid_t uid, gid_t gid); }
+	SYS_GETSID               = 286 // { pid_t|sys||getsid(pid_t pid); }
+	SYS___CLONE              = 287 // { pid_t|sys||__clone(int flags, void *stack); }
+	SYS_FKTRACE              = 288 // { int|sys||fktrace(int fd, int ops, int facs, pid_t pid); }
+	SYS_PREADV               = 289 // { ssize_t|sys||preadv(int fd, const struct iovec *iovp, int iovcnt, int PAD, off_t offset); }
+	SYS_PWRITEV              = 290 // { ssize_t|sys||pwritev(int fd, const struct iovec *iovp, int iovcnt, int PAD, off_t offset); }
+	SYS___GETCWD             = 296 // { int|sys||__getcwd(char *bufp, size_t length); }
+	SYS_FCHROOT              = 297 // { int|sys||fchroot(int fd); }
+	SYS_LCHFLAGS             = 304 // { int|sys||lchflags(const char *path, u_long flags); }
+	SYS_ISSETUGID            = 305 // { int|sys||issetugid(void); }
+	SYS_UTRACE               = 306 // { int|sys||utrace(const char *label, void *addr, size_t len); }
+	SYS_GETCONTEXT           = 307 // { int|sys||getcontext(struct __ucontext *ucp); }
+	SYS_SETCONTEXT           = 308 // { int|sys||setcontext(const struct __ucontext *ucp); }
+	SYS__LWP_CREATE          = 309 // { int|sys||_lwp_create(const struct __ucontext *ucp, u_long flags, lwpid_t *new_lwp); }
+	SYS__LWP_EXIT            = 310 // { int|sys||_lwp_exit(void); }
+	SYS__LWP_SELF            = 311 // { lwpid_t|sys||_lwp_self(void); }
+	SYS__LWP_WAIT            = 312 // { int|sys||_lwp_wait(lwpid_t wait_for, lwpid_t *departed); }
+	SYS__LWP_SUSPEND         = 313 // { int|sys||_lwp_suspend(lwpid_t target); }
+	SYS__LWP_CONTINUE        = 314 // { int|sys||_lwp_continue(lwpid_t target); }
+	SYS__LWP_WAKEUP          = 315 // { int|sys||_lwp_wakeup(lwpid_t target); }
+	SYS__LWP_GETPRIVATE      = 316 // { void *|sys||_lwp_getprivate(void); }
+	SYS__LWP_SETPRIVATE      = 317 // { void|sys||_lwp_setprivate(void *ptr); }
+	SYS__LWP_KILL            = 318 // { int|sys||_lwp_kill(lwpid_t target, int signo); }
+	SYS__LWP_DETACH          = 319 // { int|sys||_lwp_detach(lwpid_t target); }
+	SYS__LWP_UNPARK          = 321 // { int|sys||_lwp_unpark(lwpid_t target, const void *hint); }
+	SYS__LWP_UNPARK_ALL      = 322 // { ssize_t|sys||_lwp_unpark_all(const lwpid_t *targets, size_t ntargets, const void *hint); }
+	SYS__LWP_SETNAME         = 323 // { int|sys||_lwp_setname(lwpid_t target, const char *name); }
+	SYS__LWP_GETNAME         = 324 // { int|sys||_lwp_getname(lwpid_t target, char *name, size_t len); }
+	SYS__LWP_CTL             = 325 // { int|sys||_lwp_ctl(int features, struct lwpctl **address); }
+	SYS_SA_REGISTER          = 330 // { int|sys||sa_register(sa_upcall_t new, sa_upcall_t *old, int flags, ssize_t stackinfo_offset); }
+	SYS_SA_STACKS            = 331 // { int|sys||sa_stacks(int num, stack_t *stacks); }
+	SYS_SA_ENABLE            = 332 // { int|sys||sa_enable(void); }
+	SYS_SA_SETCONCURRENCY    = 333 // { int|sys||sa_setconcurrency(int concurrency); }
+	SYS_SA_YIELD             = 334 // { int|sys||sa_yield(void); }
+	SYS_SA_PREEMPT           = 335 // { int|sys||sa_preempt(int sa_id); }
+	SYS___SIGACTION_SIGTRAMP = 340 // { int|sys||__sigaction_sigtramp(int signum, const struct sigaction *nsa, struct sigaction *osa, const void *tramp, int vers); }
+	SYS_PMC_GET_INFO         = 341 // { int|sys||pmc_get_info(int ctr, int op, void *args); }
+	SYS_PMC_CONTROL          = 342 // { int|sys||pmc_control(int ctr, int op, void *args); }
+	SYS_RASCTL               = 343 // { int|sys||rasctl(void *addr, size_t len, int op); }
+	SYS_KQUEUE               = 344 // { int|sys||kqueue(void); }
+	SYS__SCHED_SETPARAM      = 346 // { int|sys||_sched_setparam(pid_t pid, lwpid_t lid, int policy, const struct sched_param *params); }
+	SYS__SCHED_GETPARAM      = 347 // { int|sys||_sched_getparam(pid_t pid, lwpid_t lid, int *policy, struct sched_param *params); }
+	SYS__SCHED_SETAFFINITY   = 348 // { int|sys||_sched_setaffinity(pid_t pid, lwpid_t lid, size_t size, const cpuset_t *cpuset); }
+	SYS__SCHED_GETAFFINITY   = 349 // { int|sys||_sched_getaffinity(pid_t pid, lwpid_t lid, size_t size, cpuset_t *cpuset); }
+	SYS_SCHED_YIELD          = 350 // { int|sys||sched_yield(void); }
+	SYS_FSYNC_RANGE          = 354 // { int|sys||fsync_range(int fd, int flags, off_t start, off_t length); }
+	SYS_UUIDGEN              = 355 // { int|sys||uuidgen(struct uuid *store, int count); }
+	SYS_GETVFSSTAT           = 356 // { int|sys||getvfsstat(struct statvfs *buf, size_t bufsize, int flags); }
+	SYS_STATVFS1             = 357 // { int|sys||statvfs1(const char *path, struct statvfs *buf, int flags); }
+	SYS_FSTATVFS1            = 358 // { int|sys||fstatvfs1(int fd, struct statvfs *buf, int flags); }
+	SYS_EXTATTRCTL           = 360 // { int|sys||extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_FILE     = 361 // { int|sys||extattr_set_file(const char *path, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_FILE     = 362 // { ssize_t|sys||extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_FILE  = 363 // { int|sys||extattr_delete_file(const char *path, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_FD       = 364 // { int|sys||extattr_set_fd(int fd, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_FD       = 365 // { ssize_t|sys||extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_FD    = 366 // { int|sys||extattr_delete_fd(int fd, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_LINK     = 367 // { int|sys||extattr_set_link(const char *path, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_LINK     = 368 // { ssize_t|sys||extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_LINK  = 369 // { int|sys||extattr_delete_link(const char *path, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_LIST_FD      = 370 // { ssize_t|sys||extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); }
+	SYS_EXTATTR_LIST_FILE    = 371 // { ssize_t|sys||extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); }
+	SYS_EXTATTR_LIST_LINK    = 372 // { ssize_t|sys||extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); }
+	SYS_SETXATTR             = 375 // { int|sys||setxattr(const char *path, const char *name, const void *value, size_t size, int flags); }
+	SYS_LSETXATTR            = 376 // { int|sys||lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags); }
+	SYS_FSETXATTR            = 377 // { int|sys||fsetxattr(int fd, const char *name, const void *value, size_t size, int flags); }
+	SYS_GETXATTR             = 378 // { int|sys||getxattr(const char *path, const char *name, void *value, size_t size); }
+	SYS_LGETXATTR            = 379 // { int|sys||lgetxattr(const char *path, const char *name, void *value, size_t size); }
+	SYS_FGETXATTR            = 380 // { int|sys||fgetxattr(int fd, const char *name, void *value, size_t size); }
+	SYS_LISTXATTR            = 381 // { int|sys||listxattr(const char *path, char *list, size_t size); }
+	SYS_LLISTXATTR           = 382 // { int|sys||llistxattr(const char *path, char *list, size_t size); }
+	SYS_FLISTXATTR           = 383 // { int|sys||flistxattr(int fd, char *list, size_t size); }
+	SYS_REMOVEXATTR          = 384 // { int|sys||removexattr(const char *path, const char *name); }
+	SYS_LREMOVEXATTR         = 385 // { int|sys||lremovexattr(const char *path, const char *name); }
+	SYS_FREMOVEXATTR         = 386 // { int|sys||fremovexattr(int fd, const char *name); }
+	SYS_GETDENTS             = 390 // { int|sys|30|getdents(int fd, char *buf, size_t count); }
+	SYS_SOCKET               = 394 // { int|sys|30|socket(int domain, int type, int protocol); }
+	SYS_GETFH                = 395 // { int|sys|30|getfh(const char *fname, void *fhp, size_t *fh_size); }
+	SYS_MOUNT                = 410 // { int|sys|50|mount(const char *type, const char *path, int flags, void *data, size_t data_len); }
+	SYS_MREMAP               = 411 // { void *|sys||mremap(void *old_address, size_t old_size, void *new_address, size_t new_size, int flags); }
+	SYS_PSET_CREATE          = 412 // { int|sys||pset_create(psetid_t *psid); }
+	SYS_PSET_DESTROY         = 413 // { int|sys||pset_destroy(psetid_t psid); }
+	SYS_PSET_ASSIGN          = 414 // { int|sys||pset_assign(psetid_t psid, cpuid_t cpuid, psetid_t *opsid); }
+	SYS__PSET_BIND           = 415 // { int|sys||_pset_bind(idtype_t idtype, id_t first_id, id_t second_id, psetid_t psid, psetid_t *opsid); }
+	SYS_POSIX_FADVISE        = 416 // { int|sys|50|posix_fadvise(int fd, int PAD, off_t offset, off_t len, int advice); }
+	SYS_SELECT               = 417 // { int|sys|50|select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); }
+	SYS_GETTIMEOFDAY         = 418 // { int|sys|50|gettimeofday(struct timeval *tp, void *tzp); }
+	SYS_SETTIMEOFDAY         = 419 // { int|sys|50|settimeofday(const struct timeval *tv, const void *tzp); }
+	SYS_UTIMES               = 420 // { int|sys|50|utimes(const char *path, const struct timeval *tptr); }
+	SYS_ADJTIME              = 421 // { int|sys|50|adjtime(const struct timeval *delta, struct timeval *olddelta); }
+	SYS_FUTIMES              = 423 // { int|sys|50|futimes(int fd, const struct timeval *tptr); }
+	SYS_LUTIMES              = 424 // { int|sys|50|lutimes(const char *path, const struct timeval *tptr); }
+	SYS_SETITIMER            = 425 // { int|sys|50|setitimer(int which, const struct itimerval *itv, struct itimerval *oitv); }
+	SYS_GETITIMER            = 426 // { int|sys|50|getitimer(int which, struct itimerval *itv); }
+	SYS_CLOCK_GETTIME        = 427 // { int|sys|50|clock_gettime(clockid_t clock_id, struct timespec *tp); }
+	SYS_CLOCK_SETTIME        = 428 // { int|sys|50|clock_settime(clockid_t clock_id, const struct timespec *tp); }
+	SYS_CLOCK_GETRES         = 429 // { int|sys|50|clock_getres(clockid_t clock_id, struct timespec *tp); }
+	SYS_NANOSLEEP            = 430 // { int|sys|50|nanosleep(const struct timespec *rqtp, struct timespec *rmtp); }
+	SYS___SIGTIMEDWAIT       = 431 // { int|sys|50|__sigtimedwait(const sigset_t *set, siginfo_t *info, struct timespec *timeout); }
+	SYS__LWP_PARK            = 434 // { int|sys|50|_lwp_park(const struct timespec *ts, lwpid_t unpark, const void *hint, const void *unparkhint); }
+	SYS_KEVENT               = 435 // { int|sys|50|kevent(int fd, const struct kevent *changelist, size_t nchanges, struct kevent *eventlist, size_t nevents, const struct timespec *timeout); }
+	SYS_PSELECT              = 436 // { int|sys|50|pselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, const struct timespec *ts, const sigset_t *mask); }
+	SYS_POLLTS               = 437 // { int|sys|50|pollts(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *mask); }
+	SYS_STAT                 = 439 // { int|sys|50|stat(const char *path, struct stat *ub); }
+	SYS_FSTAT                = 440 // { int|sys|50|fstat(int fd, struct stat *sb); }
+	SYS_LSTAT                = 441 // { int|sys|50|lstat(const char *path, struct stat *ub); }
+	SYS___SEMCTL             = 442 // { int|sys|50|__semctl(int semid, int semnum, int cmd, ... union __semun *arg); }
+	SYS_SHMCTL               = 443 // { int|sys|50|shmctl(int shmid, int cmd, struct shmid_ds *buf); }
+	SYS_MSGCTL               = 444 // { int|sys|50|msgctl(int msqid, int cmd, struct msqid_ds *buf); }
+	SYS_GETRUSAGE            = 445 // { int|sys|50|getrusage(int who, struct rusage *rusage); }
+	SYS_TIMER_SETTIME        = 446 // { int|sys|50|timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue); }
+	SYS_TIMER_GETTIME        = 447 // { int|sys|50|timer_gettime(timer_t timerid, struct itimerspec *value); }
+	SYS_NTP_GETTIME          = 448 // { int|sys|50|ntp_gettime(struct ntptimeval *ntvp); }
+	SYS_WAIT4                = 449 // { int|sys|50|wait4(pid_t pid, int *status, int options, struct rusage *rusage); }
+	SYS_MKNOD                = 450 // { int|sys|50|mknod(const char *path, mode_t mode, dev_t dev); }
+	SYS_FHSTAT               = 451 // { int|sys|50|fhstat(const void *fhp, size_t fh_size, struct stat *sb); }
+	SYS_QUOTACTL             = 452 // { int|sys|50|quotactl(const char *path, struct plistref *pref); }
+	SYS_PIPE2                = 453 // { int|sys||pipe2(int *fildes, int flags); }
+	SYS_DUP3                 = 454 // { int|sys||dup3(int from, int to, int flags); }
+	SYS_KQUEUE1              = 455 // { int|sys||kqueue1(int flags); }
+	SYS_PACCEPT              = 456 // { int|sys||paccept(int s, struct sockaddr *name, socklen_t *anamelen, const sigset_t *mask, int flags); }
+	SYS_LINKAT               = 457 // { int|sys||linkat(int fd1, const char *name1, int fd2, const char *name2, int flags); }
+	SYS_RENAMEAT             = 458 // { int|sys||renameat(int fromfd, const char *from, int tofd, const char *to); }
+	SYS_MKFIFOAT             = 459 // { int|sys||mkfifoat(int fd, const char *path, mode_t mode); }
+	SYS_MKNODAT              = 460 // { int|sys||mknodat(int fd, const char *path, mode_t mode, uint32_t dev); }
+	SYS_MKDIRAT              = 461 // { int|sys||mkdirat(int fd, const char *path, mode_t mode); }
+	SYS_FACCESSAT            = 462 // { int|sys||faccessat(int fd, const char *path, int amode, int flag); }
+	SYS_FCHMODAT             = 463 // { int|sys||fchmodat(int fd, const char *path, mode_t mode, int flag); }
+	SYS_FCHOWNAT             = 464 // { int|sys||fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag); }
+	SYS_FEXECVE              = 465 // { int|sys||fexecve(int fd, char * const *argp, char * const *envp); }
+	SYS_FSTATAT              = 466 // { int|sys||fstatat(int fd, const char *path, struct stat *buf, int flag); }
+	SYS_UTIMENSAT            = 467 // { int|sys||utimensat(int fd, const char *path, const struct timespec *tptr, int flag); }
+	SYS_OPENAT               = 468 // { int|sys||openat(int fd, const char *path, int oflags, ... mode_t mode); }
+	SYS_READLINKAT           = 469 // { int|sys||readlinkat(int fd, const char *path, char *buf, size_t bufsize); }
+	SYS_SYMLINKAT            = 470 // { int|sys||symlinkat(const char *path1, int fd, const char *path2); }
+	SYS_UNLINKAT             = 471 // { int|sys||unlinkat(int fd, const char *path, int flag); }
+	SYS_FUTIMENS             = 472 // { int|sys||futimens(int fd, const struct timespec *tptr); }
+)
diff --git a/src/pkg/syscall/zsysnum_netbsd_amd64.go b/src/pkg/syscall/zsysnum_netbsd_amd64.go
new file mode 100644
index 0000000..e9a0bcf
--- /dev/null
+++ b/src/pkg/syscall/zsysnum_netbsd_amd64.go
@@ -0,0 +1,274 @@
+// mksysnum_netbsd.pl 
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+	SYS_EXIT                 = 1   // { void|sys||exit(int rval); }
+	SYS_FORK                 = 2   // { int|sys||fork(void); }
+	SYS_READ                 = 3   // { ssize_t|sys||read(int fd, void *buf, size_t nbyte); }
+	SYS_WRITE                = 4   // { ssize_t|sys||write(int fd, const void *buf, size_t nbyte); }
+	SYS_OPEN                 = 5   // { int|sys||open(const char *path, int flags, ... mode_t mode); }
+	SYS_CLOSE                = 6   // { int|sys||close(int fd); }
+	SYS_LINK                 = 9   // { int|sys||link(const char *path, const char *link); }
+	SYS_UNLINK               = 10  // { int|sys||unlink(const char *path); }
+	SYS_CHDIR                = 12  // { int|sys||chdir(const char *path); }
+	SYS_FCHDIR               = 13  // { int|sys||fchdir(int fd); }
+	SYS_CHMOD                = 15  // { int|sys||chmod(const char *path, mode_t mode); }
+	SYS_CHOWN                = 16  // { int|sys||chown(const char *path, uid_t uid, gid_t gid); }
+	SYS_BREAK                = 17  // { int|sys||obreak(char *nsize); }
+	SYS_GETPID               = 20  // { pid_t|sys||getpid_with_ppid(void); }
+	SYS_UNMOUNT              = 22  // { int|sys||unmount(const char *path, int flags); }
+	SYS_SETUID               = 23  // { int|sys||setuid(uid_t uid); }
+	SYS_GETUID               = 24  // { uid_t|sys||getuid_with_euid(void); }
+	SYS_GETEUID              = 25  // { uid_t|sys||geteuid(void); }
+	SYS_PTRACE               = 26  // { int|sys||ptrace(int req, pid_t pid, void *addr, int data); }
+	SYS_RECVMSG              = 27  // { ssize_t|sys||recvmsg(int s, struct msghdr *msg, int flags); }
+	SYS_SENDMSG              = 28  // { ssize_t|sys||sendmsg(int s, const struct msghdr *msg, int flags); }
+	SYS_RECVFROM             = 29  // { ssize_t|sys||recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlenaddr); }
+	SYS_ACCEPT               = 30  // { int|sys||accept(int s, struct sockaddr *name, socklen_t *anamelen); }
+	SYS_GETPEERNAME          = 31  // { int|sys||getpeername(int fdes, struct sockaddr *asa, socklen_t *alen); }
+	SYS_GETSOCKNAME          = 32  // { int|sys||getsockname(int fdes, struct sockaddr *asa, socklen_t *alen); }
+	SYS_ACCESS               = 33  // { int|sys||access(const char *path, int flags); }
+	SYS_CHFLAGS              = 34  // { int|sys||chflags(const char *path, u_long flags); }
+	SYS_FCHFLAGS             = 35  // { int|sys||fchflags(int fd, u_long flags); }
+	SYS_SYNC                 = 36  // { void|sys||sync(void); }
+	SYS_KILL                 = 37  // { int|sys||kill(pid_t pid, int signum); }
+	SYS_GETPPID              = 39  // { pid_t|sys||getppid(void); }
+	SYS_DUP                  = 41  // { int|sys||dup(int fd); }
+	SYS_PIPE                 = 42  // { int|sys||pipe(void); }
+	SYS_GETEGID              = 43  // { gid_t|sys||getegid(void); }
+	SYS_PROFIL               = 44  // { int|sys||profil(char *samples, size_t size, u_long offset, u_int scale); }
+	SYS_KTRACE               = 45  // { int|sys||ktrace(const char *fname, int ops, int facs, pid_t pid); }
+	SYS_GETGID               = 47  // { gid_t|sys||getgid_with_egid(void); }
+	SYS___GETLOGIN           = 49  // { int|sys||__getlogin(char *namebuf, size_t namelen); }
+	SYS___SETLOGIN           = 50  // { int|sys||__setlogin(const char *namebuf); }
+	SYS_ACCT                 = 51  // { int|sys||acct(const char *path); }
+	SYS_IOCTL                = 54  // { int|sys||ioctl(int fd, u_long com, ... void *data); }
+	SYS_REVOKE               = 56  // { int|sys||revoke(const char *path); }
+	SYS_SYMLINK              = 57  // { int|sys||symlink(const char *path, const char *link); }
+	SYS_READLINK             = 58  // { ssize_t|sys||readlink(const char *path, char *buf, size_t count); }
+	SYS_EXECVE               = 59  // { int|sys||execve(const char *path, char * const *argp, char * const *envp); }
+	SYS_UMASK                = 60  // { mode_t|sys||umask(mode_t newmask); }
+	SYS_CHROOT               = 61  // { int|sys||chroot(const char *path); }
+	SYS_VFORK                = 66  // { int|sys||vfork(void); }
+	SYS_SBRK                 = 69  // { int|sys||sbrk(intptr_t incr); }
+	SYS_SSTK                 = 70  // { int|sys||sstk(int incr); }
+	SYS_VADVISE              = 72  // { int|sys||ovadvise(int anom); }
+	SYS_MUNMAP               = 73  // { int|sys||munmap(void *addr, size_t len); }
+	SYS_MPROTECT             = 74  // { int|sys||mprotect(void *addr, size_t len, int prot); }
+	SYS_MADVISE              = 75  // { int|sys||madvise(void *addr, size_t len, int behav); }
+	SYS_MINCORE              = 78  // { int|sys||mincore(void *addr, size_t len, char *vec); }
+	SYS_GETGROUPS            = 79  // { int|sys||getgroups(int gidsetsize, gid_t *gidset); }
+	SYS_SETGROUPS            = 80  // { int|sys||setgroups(int gidsetsize, const gid_t *gidset); }
+	SYS_GETPGRP              = 81  // { int|sys||getpgrp(void); }
+	SYS_SETPGID              = 82  // { int|sys||setpgid(pid_t pid, pid_t pgid); }
+	SYS_DUP2                 = 90  // { int|sys||dup2(int from, int to); }
+	SYS_FCNTL                = 92  // { int|sys||fcntl(int fd, int cmd, ... void *arg); }
+	SYS_FSYNC                = 95  // { int|sys||fsync(int fd); }
+	SYS_SETPRIORITY          = 96  // { int|sys||setpriority(int which, id_t who, int prio); }
+	SYS_CONNECT              = 98  // { int|sys||connect(int s, const struct sockaddr *name, socklen_t namelen); }
+	SYS_GETPRIORITY          = 100 // { int|sys||getpriority(int which, id_t who); }
+	SYS_BIND                 = 104 // { int|sys||bind(int s, const struct sockaddr *name, socklen_t namelen); }
+	SYS_SETSOCKOPT           = 105 // { int|sys||setsockopt(int s, int level, int name, const void *val, socklen_t valsize); }
+	SYS_LISTEN               = 106 // { int|sys||listen(int s, int backlog); }
+	SYS_GETSOCKOPT           = 118 // { int|sys||getsockopt(int s, int level, int name, void *val, socklen_t *avalsize); }
+	SYS_READV                = 120 // { ssize_t|sys||readv(int fd, const struct iovec *iovp, int iovcnt); }
+	SYS_WRITEV               = 121 // { ssize_t|sys||writev(int fd, const struct iovec *iovp, int iovcnt); }
+	SYS_FCHOWN               = 123 // { int|sys||fchown(int fd, uid_t uid, gid_t gid); }
+	SYS_FCHMOD               = 124 // { int|sys||fchmod(int fd, mode_t mode); }
+	SYS_SETREUID             = 126 // { int|sys||setreuid(uid_t ruid, uid_t euid); }
+	SYS_SETREGID             = 127 // { int|sys||setregid(gid_t rgid, gid_t egid); }
+	SYS_RENAME               = 128 // { int|sys||rename(const char *from, const char *to); }
+	SYS_FLOCK                = 131 // { int|sys||flock(int fd, int how); }
+	SYS_MKFIFO               = 132 // { int|sys||mkfifo(const char *path, mode_t mode); }
+	SYS_SENDTO               = 133 // { ssize_t|sys||sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); }
+	SYS_SHUTDOWN             = 134 // { int|sys||shutdown(int s, int how); }
+	SYS_SOCKETPAIR           = 135 // { int|sys||socketpair(int domain, int type, int protocol, int *rsv); }
+	SYS_MKDIR                = 136 // { int|sys||mkdir(const char *path, mode_t mode); }
+	SYS_RMDIR                = 137 // { int|sys||rmdir(const char *path); }
+	SYS_SETSID               = 147 // { int|sys||setsid(void); }
+	SYS_SYSARCH              = 165 // { int|sys||sysarch(int op, void *parms); }
+	SYS_PREAD                = 173 // { ssize_t|sys||pread(int fd, void *buf, size_t nbyte, int PAD, off_t offset); }
+	SYS_PWRITE               = 174 // { ssize_t|sys||pwrite(int fd, const void *buf, size_t nbyte, int PAD, off_t offset); }
+	SYS_NTP_ADJTIME          = 176 // { int|sys||ntp_adjtime(struct timex *tp); }
+	SYS_SETGID               = 181 // { int|sys||setgid(gid_t gid); }
+	SYS_SETEGID              = 182 // { int|sys||setegid(gid_t egid); }
+	SYS_SETEUID              = 183 // { int|sys||seteuid(uid_t euid); }
+	SYS_PATHCONF             = 191 // { long|sys||pathconf(const char *path, int name); }
+	SYS_FPATHCONF            = 192 // { long|sys||fpathconf(int fd, int name); }
+	SYS_GETRLIMIT            = 194 // { int|sys||getrlimit(int which, struct rlimit *rlp); }
+	SYS_SETRLIMIT            = 195 // { int|sys||setrlimit(int which, const struct rlimit *rlp); }
+	SYS_MMAP                 = 197 // { void *|sys||mmap(void *addr, size_t len, int prot, int flags, int fd, long PAD, off_t pos); }
+	SYS_LSEEK                = 199 // { off_t|sys||lseek(int fd, int PAD, off_t offset, int whence); }
+	SYS_TRUNCATE             = 200 // { int|sys||truncate(const char *path, int PAD, off_t length); }
+	SYS_FTRUNCATE            = 201 // { int|sys||ftruncate(int fd, int PAD, off_t length); }
+	SYS___SYSCTL             = 202 // { int|sys||__sysctl(const int *name, u_int namelen, void *old, size_t *oldlenp, const void *new, size_t newlen); }
+	SYS_MLOCK                = 203 // { int|sys||mlock(const void *addr, size_t len); }
+	SYS_MUNLOCK              = 204 // { int|sys||munlock(const void *addr, size_t len); }
+	SYS_UNDELETE             = 205 // { int|sys||undelete(const char *path); }
+	SYS_GETPGID              = 207 // { pid_t|sys||getpgid(pid_t pid); }
+	SYS_REBOOT               = 208 // { int|sys||reboot(int opt, char *bootstr); }
+	SYS_POLL                 = 209 // { int|sys||poll(struct pollfd *fds, u_int nfds, int timeout); }
+	SYS_SEMGET               = 221 // { int|sys||semget(key_t key, int nsems, int semflg); }
+	SYS_SEMOP                = 222 // { int|sys||semop(int semid, struct sembuf *sops, size_t nsops); }
+	SYS_SEMCONFIG            = 223 // { int|sys||semconfig(int flag); }
+	SYS_MSGGET               = 225 // { int|sys||msgget(key_t key, int msgflg); }
+	SYS_MSGSND               = 226 // { int|sys||msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); }
+	SYS_MSGRCV               = 227 // { ssize_t|sys||msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); }
+	SYS_SHMAT                = 228 // { void *|sys||shmat(int shmid, const void *shmaddr, int shmflg); }
+	SYS_SHMDT                = 230 // { int|sys||shmdt(const void *shmaddr); }
+	SYS_SHMGET               = 231 // { int|sys||shmget(key_t key, size_t size, int shmflg); }
+	SYS_TIMER_CREATE         = 235 // { int|sys||timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid); }
+	SYS_TIMER_DELETE         = 236 // { int|sys||timer_delete(timer_t timerid); }
+	SYS_TIMER_GETOVERRUN     = 239 // { int|sys||timer_getoverrun(timer_t timerid); }
+	SYS_FDATASYNC            = 241 // { int|sys||fdatasync(int fd); }
+	SYS_MLOCKALL             = 242 // { int|sys||mlockall(int flags); }
+	SYS_MUNLOCKALL           = 243 // { int|sys||munlockall(void); }
+	SYS_SIGQUEUEINFO         = 245 // { int|sys||sigqueueinfo(pid_t pid, const siginfo_t *info); }
+	SYS_MODCTL               = 246 // { int|sys||modctl(int cmd, void *arg); }
+	SYS___POSIX_RENAME       = 270 // { int|sys||__posix_rename(const char *from, const char *to); }
+	SYS_SWAPCTL              = 271 // { int|sys||swapctl(int cmd, void *arg, int misc); }
+	SYS_MINHERIT             = 273 // { int|sys||minherit(void *addr, size_t len, int inherit); }
+	SYS_LCHMOD               = 274 // { int|sys||lchmod(const char *path, mode_t mode); }
+	SYS_LCHOWN               = 275 // { int|sys||lchown(const char *path, uid_t uid, gid_t gid); }
+	SYS___POSIX_CHOWN        = 283 // { int|sys||__posix_chown(const char *path, uid_t uid, gid_t gid); }
+	SYS___POSIX_FCHOWN       = 284 // { int|sys||__posix_fchown(int fd, uid_t uid, gid_t gid); }
+	SYS___POSIX_LCHOWN       = 285 // { int|sys||__posix_lchown(const char *path, uid_t uid, gid_t gid); }
+	SYS_GETSID               = 286 // { pid_t|sys||getsid(pid_t pid); }
+	SYS___CLONE              = 287 // { pid_t|sys||__clone(int flags, void *stack); }
+	SYS_FKTRACE              = 288 // { int|sys||fktrace(int fd, int ops, int facs, pid_t pid); }
+	SYS_PREADV               = 289 // { ssize_t|sys||preadv(int fd, const struct iovec *iovp, int iovcnt, int PAD, off_t offset); }
+	SYS_PWRITEV              = 290 // { ssize_t|sys||pwritev(int fd, const struct iovec *iovp, int iovcnt, int PAD, off_t offset); }
+	SYS___GETCWD             = 296 // { int|sys||__getcwd(char *bufp, size_t length); }
+	SYS_FCHROOT              = 297 // { int|sys||fchroot(int fd); }
+	SYS_LCHFLAGS             = 304 // { int|sys||lchflags(const char *path, u_long flags); }
+	SYS_ISSETUGID            = 305 // { int|sys||issetugid(void); }
+	SYS_UTRACE               = 306 // { int|sys||utrace(const char *label, void *addr, size_t len); }
+	SYS_GETCONTEXT           = 307 // { int|sys||getcontext(struct __ucontext *ucp); }
+	SYS_SETCONTEXT           = 308 // { int|sys||setcontext(const struct __ucontext *ucp); }
+	SYS__LWP_CREATE          = 309 // { int|sys||_lwp_create(const struct __ucontext *ucp, u_long flags, lwpid_t *new_lwp); }
+	SYS__LWP_EXIT            = 310 // { int|sys||_lwp_exit(void); }
+	SYS__LWP_SELF            = 311 // { lwpid_t|sys||_lwp_self(void); }
+	SYS__LWP_WAIT            = 312 // { int|sys||_lwp_wait(lwpid_t wait_for, lwpid_t *departed); }
+	SYS__LWP_SUSPEND         = 313 // { int|sys||_lwp_suspend(lwpid_t target); }
+	SYS__LWP_CONTINUE        = 314 // { int|sys||_lwp_continue(lwpid_t target); }
+	SYS__LWP_WAKEUP          = 315 // { int|sys||_lwp_wakeup(lwpid_t target); }
+	SYS__LWP_GETPRIVATE      = 316 // { void *|sys||_lwp_getprivate(void); }
+	SYS__LWP_SETPRIVATE      = 317 // { void|sys||_lwp_setprivate(void *ptr); }
+	SYS__LWP_KILL            = 318 // { int|sys||_lwp_kill(lwpid_t target, int signo); }
+	SYS__LWP_DETACH          = 319 // { int|sys||_lwp_detach(lwpid_t target); }
+	SYS__LWP_UNPARK          = 321 // { int|sys||_lwp_unpark(lwpid_t target, const void *hint); }
+	SYS__LWP_UNPARK_ALL      = 322 // { ssize_t|sys||_lwp_unpark_all(const lwpid_t *targets, size_t ntargets, const void *hint); }
+	SYS__LWP_SETNAME         = 323 // { int|sys||_lwp_setname(lwpid_t target, const char *name); }
+	SYS__LWP_GETNAME         = 324 // { int|sys||_lwp_getname(lwpid_t target, char *name, size_t len); }
+	SYS__LWP_CTL             = 325 // { int|sys||_lwp_ctl(int features, struct lwpctl **address); }
+	SYS_SA_REGISTER          = 330 // { int|sys||sa_register(sa_upcall_t new, sa_upcall_t *old, int flags, ssize_t stackinfo_offset); }
+	SYS_SA_STACKS            = 331 // { int|sys||sa_stacks(int num, stack_t *stacks); }
+	SYS_SA_ENABLE            = 332 // { int|sys||sa_enable(void); }
+	SYS_SA_SETCONCURRENCY    = 333 // { int|sys||sa_setconcurrency(int concurrency); }
+	SYS_SA_YIELD             = 334 // { int|sys||sa_yield(void); }
+	SYS_SA_PREEMPT           = 335 // { int|sys||sa_preempt(int sa_id); }
+	SYS___SIGACTION_SIGTRAMP = 340 // { int|sys||__sigaction_sigtramp(int signum, const struct sigaction *nsa, struct sigaction *osa, const void *tramp, int vers); }
+	SYS_PMC_GET_INFO         = 341 // { int|sys||pmc_get_info(int ctr, int op, void *args); }
+	SYS_PMC_CONTROL          = 342 // { int|sys||pmc_control(int ctr, int op, void *args); }
+	SYS_RASCTL               = 343 // { int|sys||rasctl(void *addr, size_t len, int op); }
+	SYS_KQUEUE               = 344 // { int|sys||kqueue(void); }
+	SYS__SCHED_SETPARAM      = 346 // { int|sys||_sched_setparam(pid_t pid, lwpid_t lid, int policy, const struct sched_param *params); }
+	SYS__SCHED_GETPARAM      = 347 // { int|sys||_sched_getparam(pid_t pid, lwpid_t lid, int *policy, struct sched_param *params); }
+	SYS__SCHED_SETAFFINITY   = 348 // { int|sys||_sched_setaffinity(pid_t pid, lwpid_t lid, size_t size, const cpuset_t *cpuset); }
+	SYS__SCHED_GETAFFINITY   = 349 // { int|sys||_sched_getaffinity(pid_t pid, lwpid_t lid, size_t size, cpuset_t *cpuset); }
+	SYS_SCHED_YIELD          = 350 // { int|sys||sched_yield(void); }
+	SYS_FSYNC_RANGE          = 354 // { int|sys||fsync_range(int fd, int flags, off_t start, off_t length); }
+	SYS_UUIDGEN              = 355 // { int|sys||uuidgen(struct uuid *store, int count); }
+	SYS_GETVFSSTAT           = 356 // { int|sys||getvfsstat(struct statvfs *buf, size_t bufsize, int flags); }
+	SYS_STATVFS1             = 357 // { int|sys||statvfs1(const char *path, struct statvfs *buf, int flags); }
+	SYS_FSTATVFS1            = 358 // { int|sys||fstatvfs1(int fd, struct statvfs *buf, int flags); }
+	SYS_EXTATTRCTL           = 360 // { int|sys||extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_FILE     = 361 // { int|sys||extattr_set_file(const char *path, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_FILE     = 362 // { ssize_t|sys||extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_FILE  = 363 // { int|sys||extattr_delete_file(const char *path, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_FD       = 364 // { int|sys||extattr_set_fd(int fd, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_FD       = 365 // { ssize_t|sys||extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_FD    = 366 // { int|sys||extattr_delete_fd(int fd, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_SET_LINK     = 367 // { int|sys||extattr_set_link(const char *path, int attrnamespace, const char *attrname, const void *data, size_t nbytes); }
+	SYS_EXTATTR_GET_LINK     = 368 // { ssize_t|sys||extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); }
+	SYS_EXTATTR_DELETE_LINK  = 369 // { int|sys||extattr_delete_link(const char *path, int attrnamespace, const char *attrname); }
+	SYS_EXTATTR_LIST_FD      = 370 // { ssize_t|sys||extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); }
+	SYS_EXTATTR_LIST_FILE    = 371 // { ssize_t|sys||extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); }
+	SYS_EXTATTR_LIST_LINK    = 372 // { ssize_t|sys||extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); }
+	SYS_SETXATTR             = 375 // { int|sys||setxattr(const char *path, const char *name, const void *value, size_t size, int flags); }
+	SYS_LSETXATTR            = 376 // { int|sys||lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags); }
+	SYS_FSETXATTR            = 377 // { int|sys||fsetxattr(int fd, const char *name, const void *value, size_t size, int flags); }
+	SYS_GETXATTR             = 378 // { int|sys||getxattr(const char *path, const char *name, void *value, size_t size); }
+	SYS_LGETXATTR            = 379 // { int|sys||lgetxattr(const char *path, const char *name, void *value, size_t size); }
+	SYS_FGETXATTR            = 380 // { int|sys||fgetxattr(int fd, const char *name, void *value, size_t size); }
+	SYS_LISTXATTR            = 381 // { int|sys||listxattr(const char *path, char *list, size_t size); }
+	SYS_LLISTXATTR           = 382 // { int|sys||llistxattr(const char *path, char *list, size_t size); }
+	SYS_FLISTXATTR           = 383 // { int|sys||flistxattr(int fd, char *list, size_t size); }
+	SYS_REMOVEXATTR          = 384 // { int|sys||removexattr(const char *path, const char *name); }
+	SYS_LREMOVEXATTR         = 385 // { int|sys||lremovexattr(const char *path, const char *name); }
+	SYS_FREMOVEXATTR         = 386 // { int|sys||fremovexattr(int fd, const char *name); }
+	SYS_GETDENTS             = 390 // { int|sys|30|getdents(int fd, char *buf, size_t count); }
+	SYS_SOCKET               = 394 // { int|sys|30|socket(int domain, int type, int protocol); }
+	SYS_GETFH                = 395 // { int|sys|30|getfh(const char *fname, void *fhp, size_t *fh_size); }
+	SYS_MOUNT                = 410 // { int|sys|50|mount(const char *type, const char *path, int flags, void *data, size_t data_len); }
+	SYS_MREMAP               = 411 // { void *|sys||mremap(void *old_address, size_t old_size, void *new_address, size_t new_size, int flags); }
+	SYS_PSET_CREATE          = 412 // { int|sys||pset_create(psetid_t *psid); }
+	SYS_PSET_DESTROY         = 413 // { int|sys||pset_destroy(psetid_t psid); }
+	SYS_PSET_ASSIGN          = 414 // { int|sys||pset_assign(psetid_t psid, cpuid_t cpuid, psetid_t *opsid); }
+	SYS__PSET_BIND           = 415 // { int|sys||_pset_bind(idtype_t idtype, id_t first_id, id_t second_id, psetid_t psid, psetid_t *opsid); }
+	SYS_POSIX_FADVISE        = 416 // { int|sys|50|posix_fadvise(int fd, int PAD, off_t offset, off_t len, int advice); }
+	SYS_SELECT               = 417 // { int|sys|50|select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); }
+	SYS_GETTIMEOFDAY         = 418 // { int|sys|50|gettimeofday(struct timeval *tp, void *tzp); }
+	SYS_SETTIMEOFDAY         = 419 // { int|sys|50|settimeofday(const struct timeval *tv, const void *tzp); }
+	SYS_UTIMES               = 420 // { int|sys|50|utimes(const char *path, const struct timeval *tptr); }
+	SYS_ADJTIME              = 421 // { int|sys|50|adjtime(const struct timeval *delta, struct timeval *olddelta); }
+	SYS_FUTIMES              = 423 // { int|sys|50|futimes(int fd, const struct timeval *tptr); }
+	SYS_LUTIMES              = 424 // { int|sys|50|lutimes(const char *path, const struct timeval *tptr); }
+	SYS_SETITIMER            = 425 // { int|sys|50|setitimer(int which, const struct itimerval *itv, struct itimerval *oitv); }
+	SYS_GETITIMER            = 426 // { int|sys|50|getitimer(int which, struct itimerval *itv); }
+	SYS_CLOCK_GETTIME        = 427 // { int|sys|50|clock_gettime(clockid_t clock_id, struct timespec *tp); }
+	SYS_CLOCK_SETTIME        = 428 // { int|sys|50|clock_settime(clockid_t clock_id, const struct timespec *tp); }
+	SYS_CLOCK_GETRES         = 429 // { int|sys|50|clock_getres(clockid_t clock_id, struct timespec *tp); }
+	SYS_NANOSLEEP            = 430 // { int|sys|50|nanosleep(const struct timespec *rqtp, struct timespec *rmtp); }
+	SYS___SIGTIMEDWAIT       = 431 // { int|sys|50|__sigtimedwait(const sigset_t *set, siginfo_t *info, struct timespec *timeout); }
+	SYS__LWP_PARK            = 434 // { int|sys|50|_lwp_park(const struct timespec *ts, lwpid_t unpark, const void *hint, const void *unparkhint); }
+	SYS_KEVENT               = 435 // { int|sys|50|kevent(int fd, const struct kevent *changelist, size_t nchanges, struct kevent *eventlist, size_t nevents, const struct timespec *timeout); }
+	SYS_PSELECT              = 436 // { int|sys|50|pselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, const struct timespec *ts, const sigset_t *mask); }
+	SYS_POLLTS               = 437 // { int|sys|50|pollts(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *mask); }
+	SYS_STAT                 = 439 // { int|sys|50|stat(const char *path, struct stat *ub); }
+	SYS_FSTAT                = 440 // { int|sys|50|fstat(int fd, struct stat *sb); }
+	SYS_LSTAT                = 441 // { int|sys|50|lstat(const char *path, struct stat *ub); }
+	SYS___SEMCTL             = 442 // { int|sys|50|__semctl(int semid, int semnum, int cmd, ... union __semun *arg); }
+	SYS_SHMCTL               = 443 // { int|sys|50|shmctl(int shmid, int cmd, struct shmid_ds *buf); }
+	SYS_MSGCTL               = 444 // { int|sys|50|msgctl(int msqid, int cmd, struct msqid_ds *buf); }
+	SYS_GETRUSAGE            = 445 // { int|sys|50|getrusage(int who, struct rusage *rusage); }
+	SYS_TIMER_SETTIME        = 446 // { int|sys|50|timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue); }
+	SYS_TIMER_GETTIME        = 447 // { int|sys|50|timer_gettime(timer_t timerid, struct itimerspec *value); }
+	SYS_NTP_GETTIME          = 448 // { int|sys|50|ntp_gettime(struct ntptimeval *ntvp); }
+	SYS_WAIT4                = 449 // { int|sys|50|wait4(pid_t pid, int *status, int options, struct rusage *rusage); }
+	SYS_MKNOD                = 450 // { int|sys|50|mknod(const char *path, mode_t mode, dev_t dev); }
+	SYS_FHSTAT               = 451 // { int|sys|50|fhstat(const void *fhp, size_t fh_size, struct stat *sb); }
+	SYS_QUOTACTL             = 452 // { int|sys|50|quotactl(const char *path, struct plistref *pref); }
+	SYS_PIPE2                = 453 // { int|sys||pipe2(int *fildes, int flags); }
+	SYS_DUP3                 = 454 // { int|sys||dup3(int from, int to, int flags); }
+	SYS_KQUEUE1              = 455 // { int|sys||kqueue1(int flags); }
+	SYS_PACCEPT              = 456 // { int|sys||paccept(int s, struct sockaddr *name, socklen_t *anamelen, const sigset_t *mask, int flags); }
+	SYS_LINKAT               = 457 // { int|sys||linkat(int fd1, const char *name1, int fd2, const char *name2, int flags); }
+	SYS_RENAMEAT             = 458 // { int|sys||renameat(int fromfd, const char *from, int tofd, const char *to); }
+	SYS_MKFIFOAT             = 459 // { int|sys||mkfifoat(int fd, const char *path, mode_t mode); }
+	SYS_MKNODAT              = 460 // { int|sys||mknodat(int fd, const char *path, mode_t mode, uint32_t dev); }
+	SYS_MKDIRAT              = 461 // { int|sys||mkdirat(int fd, const char *path, mode_t mode); }
+	SYS_FACCESSAT            = 462 // { int|sys||faccessat(int fd, const char *path, int amode, int flag); }
+	SYS_FCHMODAT             = 463 // { int|sys||fchmodat(int fd, const char *path, mode_t mode, int flag); }
+	SYS_FCHOWNAT             = 464 // { int|sys||fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag); }
+	SYS_FEXECVE              = 465 // { int|sys||fexecve(int fd, char * const *argp, char * const *envp); }
+	SYS_FSTATAT              = 466 // { int|sys||fstatat(int fd, const char *path, struct stat *buf, int flag); }
+	SYS_UTIMENSAT            = 467 // { int|sys||utimensat(int fd, const char *path, const struct timespec *tptr, int flag); }
+	SYS_OPENAT               = 468 // { int|sys||openat(int fd, const char *path, int oflags, ... mode_t mode); }
+	SYS_READLINKAT           = 469 // { int|sys||readlinkat(int fd, const char *path, char *buf, size_t bufsize); }
+	SYS_SYMLINKAT            = 470 // { int|sys||symlinkat(const char *path1, int fd, const char *path2); }
+	SYS_UNLINKAT             = 471 // { int|sys||unlinkat(int fd, const char *path, int flag); }
+	SYS_FUTIMENS             = 472 // { int|sys||futimens(int fd, const struct timespec *tptr); }
+)
diff --git a/src/pkg/syscall/zsysnum_openbsd_386.go b/src/pkg/syscall/zsysnum_openbsd_386.go
index 71310d8..230da1e 100644
--- a/src/pkg/syscall/zsysnum_openbsd_386.go
+++ b/src/pkg/syscall/zsysnum_openbsd_386.go
@@ -4,204 +4,204 @@
 package syscall
 
 const (
-	SYS_EXIT           = 1   // { void sys_exit(int rval); }
-	SYS_FORK           = 2   // { int sys_fork(void); }
-	SYS_READ           = 3   // { ssize_t sys_read(int fd, void *buf, size_t nbyte); }
-	SYS_WRITE          = 4   // { ssize_t sys_write(int fd, const void *buf, \
-	SYS_OPEN           = 5   // { int sys_open(const char *path, \
-	SYS_CLOSE          = 6   // { int sys_close(int fd); }
-	SYS_WAIT4          = 7   // { pid_t sys_wait4(pid_t pid, int *status, int options, \
-	SYS_LINK           = 9   // { int sys_link(const char *path, const char *link); }
-	SYS_UNLINK         = 10  // { int sys_unlink(const char *path); }
-	SYS_CHDIR          = 12  // { int sys_chdir(const char *path); }
-	SYS_FCHDIR         = 13  // { int sys_fchdir(int fd); }
-	SYS_MKNOD          = 14  // { int sys_mknod(const char *path, mode_t mode, \
-	SYS_CHMOD          = 15  // { int sys_chmod(const char *path, mode_t mode); }
-	SYS_CHOWN          = 16  // { int sys_chown(const char *path, uid_t uid, \
-	SYS_OBREAK         = 17  // { int sys_obreak(char *nsize); } break
-	SYS_GETPID         = 20  // { pid_t sys_getpid(void); }
-	SYS_MOUNT          = 21  // { int sys_mount(const char *type, const char *path, \
-	SYS_UNMOUNT        = 22  // { int sys_unmount(const char *path, int flags); }
-	SYS_SETUID         = 23  // { int sys_setuid(uid_t uid); }
-	SYS_GETUID         = 24  // { uid_t sys_getuid(void); }
-	SYS_GETEUID        = 25  // { uid_t sys_geteuid(void); }
-	SYS_PTRACE         = 26  // { int sys_ptrace(int req, pid_t pid, caddr_t addr, \
-	SYS_RECVMSG        = 27  // { ssize_t sys_recvmsg(int s, struct msghdr *msg, \
-	SYS_SENDMSG        = 28  // { ssize_t sys_sendmsg(int s, \
-	SYS_RECVFROM       = 29  // { ssize_t sys_recvfrom(int s, void *buf, size_t len, \
-	SYS_ACCEPT         = 30  // { int sys_accept(int s, struct sockaddr *name, \
-	SYS_GETPEERNAME    = 31  // { int sys_getpeername(int fdes, struct sockaddr *asa, \
-	SYS_GETSOCKNAME    = 32  // { int sys_getsockname(int fdes, struct sockaddr *asa, \
-	SYS_ACCESS         = 33  // { int sys_access(const char *path, int flags); }
-	SYS_CHFLAGS        = 34  // { int sys_chflags(const char *path, u_int flags); }
-	SYS_FCHFLAGS       = 35  // { int sys_fchflags(int fd, u_int flags); }
-	SYS_SYNC           = 36  // { void sys_sync(void); }
-	SYS_KILL           = 37  // { int sys_kill(int pid, int signum); }
-	SYS_GETPPID        = 39  // { pid_t sys_getppid(void); }
-	SYS_DUP            = 41  // { int sys_dup(int fd); }
-	SYS_GETEGID        = 43  // { gid_t sys_getegid(void); }
-	SYS_PROFIL         = 44  // { int sys_profil(caddr_t samples, size_t size, \
-	SYS_KTRACE         = 45  // { int sys_ktrace(const char *fname, int ops, \
-	SYS_SIGACTION      = 46  // { int sys_sigaction(int signum, \
-	SYS_GETGID         = 47  // { gid_t sys_getgid(void); }
-	SYS_SIGPROCMASK    = 48  // { int sys_sigprocmask(int how, sigset_t mask); }
-	SYS_GETLOGIN       = 49  // { int sys_getlogin(char *namebuf, u_int namelen); }
-	SYS_SETLOGIN       = 50  // { int sys_setlogin(const char *namebuf); }
-	SYS_ACCT           = 51  // { int sys_acct(const char *path); }
-	SYS_SIGPENDING     = 52  // { int sys_sigpending(void); }
-	SYS_OSIGALTSTACK   = 53  // { int sys_osigaltstack(const struct osigaltstack *nss, \
-	SYS_IOCTL          = 54  // { int sys_ioctl(int fd, \
-	SYS_REBOOT         = 55  // { int sys_reboot(int opt); }
-	SYS_REVOKE         = 56  // { int sys_revoke(const char *path); }
-	SYS_SYMLINK        = 57  // { int sys_symlink(const char *path, \
-	SYS_READLINK       = 58  // { int sys_readlink(const char *path, char *buf, \
-	SYS_EXECVE         = 59  // { int sys_execve(const char *path, \
-	SYS_UMASK          = 60  // { mode_t sys_umask(mode_t newmask); }
-	SYS_CHROOT         = 61  // { int sys_chroot(const char *path); }
-	SYS_VFORK          = 66  // { int sys_vfork(void); }
-	SYS_SBRK           = 69  // { int sys_sbrk(int incr); }
-	SYS_SSTK           = 70  // { int sys_sstk(int incr); }
-	SYS_MUNMAP         = 73  // { int sys_munmap(void *addr, size_t len); }
-	SYS_MPROTECT       = 74  // { int sys_mprotect(void *addr, size_t len, \
-	SYS_MADVISE        = 75  // { int sys_madvise(void *addr, size_t len, \
-	SYS_MINCORE        = 78  // { int sys_mincore(void *addr, size_t len, \
-	SYS_GETGROUPS      = 79  // { int sys_getgroups(int gidsetsize, \
-	SYS_SETGROUPS      = 80  // { int sys_setgroups(int gidsetsize, \
-	SYS_GETPGRP        = 81  // { int sys_getpgrp(void); }
-	SYS_SETPGID        = 82  // { int sys_setpgid(pid_t pid, int pgid); }
-	SYS_SETITIMER      = 83  // { int sys_setitimer(int which, \
-	SYS_GETITIMER      = 86  // { int sys_getitimer(int which, \
-	SYS_DUP2           = 90  // { int sys_dup2(int from, int to); }
-	SYS_FCNTL          = 92  // { int sys_fcntl(int fd, int cmd, ... void *arg); }
-	SYS_SELECT         = 93  // { int sys_select(int nd, fd_set *in, fd_set *ou, \
-	SYS_FSYNC          = 95  // { int sys_fsync(int fd); }
-	SYS_SETPRIORITY    = 96  // { int sys_setpriority(int which, id_t who, int prio); }
-	SYS_SOCKET         = 97  // { int sys_socket(int domain, int type, int protocol); }
-	SYS_CONNECT        = 98  // { int sys_connect(int s, const struct sockaddr *name, \
-	SYS_GETPRIORITY    = 100 // { int sys_getpriority(int which, id_t who); }
-	SYS_SIGRETURN      = 103 // { int sys_sigreturn(struct sigcontext *sigcntxp); }
-	SYS_BIND           = 104 // { int sys_bind(int s, const struct sockaddr *name, \
-	SYS_SETSOCKOPT     = 105 // { int sys_setsockopt(int s, int level, int name, \
-	SYS_LISTEN         = 106 // { int sys_listen(int s, int backlog); }
-	SYS_SIGSUSPEND     = 111 // { int sys_sigsuspend(int mask); }
-	SYS_GETTIMEOFDAY   = 116 // { int sys_gettimeofday(struct timeval *tp, \
-	SYS_GETRUSAGE      = 117 // { int sys_getrusage(int who, struct rusage *rusage); }
-	SYS_GETSOCKOPT     = 118 // { int sys_getsockopt(int s, int level, int name, \
-	SYS_READV          = 120 // { ssize_t sys_readv(int fd, \
-	SYS_WRITEV         = 121 // { ssize_t sys_writev(int fd, \
-	SYS_SETTIMEOFDAY   = 122 // { int sys_settimeofday(const struct timeval *tv, \
-	SYS_FCHOWN         = 123 // { int sys_fchown(int fd, uid_t uid, gid_t gid); }
-	SYS_FCHMOD         = 124 // { int sys_fchmod(int fd, mode_t mode); }
-	SYS_SETREUID       = 126 // { int sys_setreuid(uid_t ruid, uid_t euid); }
-	SYS_SETREGID       = 127 // { int sys_setregid(gid_t rgid, gid_t egid); }
-	SYS_RENAME         = 128 // { int sys_rename(const char *from, const char *to); }
-	SYS_FLOCK          = 131 // { int sys_flock(int fd, int how); }
-	SYS_MKFIFO         = 132 // { int sys_mkfifo(const char *path, mode_t mode); }
-	SYS_SENDTO         = 133 // { ssize_t sys_sendto(int s, const void *buf, \
-	SYS_SHUTDOWN       = 134 // { int sys_shutdown(int s, int how); }
-	SYS_SOCKETPAIR     = 135 // { int sys_socketpair(int domain, int type, \
-	SYS_MKDIR          = 136 // { int sys_mkdir(const char *path, mode_t mode); }
-	SYS_RMDIR          = 137 // { int sys_rmdir(const char *path); }
-	SYS_UTIMES         = 138 // { int sys_utimes(const char *path, \
-	SYS_ADJTIME        = 140 // { int sys_adjtime(const struct timeval *delta, \
-	SYS_SETSID         = 147 // { int sys_setsid(void); }
-	SYS_QUOTACTL       = 148 // { int sys_quotactl(const char *path, int cmd, \
-	SYS_NFSSVC         = 155 // { int sys_nfssvc(int flag, void *argp); }
-	SYS_GETFH          = 161 // { int sys_getfh(const char *fname, fhandle_t *fhp); }
-	SYS_SYSARCH        = 165 // { int sys_sysarch(int op, void *parms); }
-	SYS_PREAD          = 173 // { ssize_t sys_pread(int fd, void *buf, \
-	SYS_PWRITE         = 174 // { ssize_t sys_pwrite(int fd, const void *buf, \
-	SYS_SETGID         = 181 // { int sys_setgid(gid_t gid); }
-	SYS_SETEGID        = 182 // { int sys_setegid(gid_t egid); }
-	SYS_SETEUID        = 183 // { int sys_seteuid(uid_t euid); }
-	LFS_BMAPV          = 184 // { int lfs_bmapv(fsid_t *fsidp, \
-	LFS_MARKV          = 185 // { int lfs_markv(fsid_t *fsidp, \
-	LFS_SEGCLEAN       = 186 // { int lfs_segclean(fsid_t *fsidp, u_long segment); }
-	LFS_SEGWAIT        = 187 // { int lfs_segwait(fsid_t *fsidp, struct timeval *tv); }
-	SYS_PATHCONF       = 191 // { long sys_pathconf(const char *path, int name); }
-	SYS_FPATHCONF      = 192 // { long sys_fpathconf(int fd, int name); }
-	SYS_SWAPCTL        = 193 // { int sys_swapctl(int cmd, const void *arg, int misc); }
-	SYS_GETRLIMIT      = 194 // { int sys_getrlimit(int which, \
-	SYS_SETRLIMIT      = 195 // { int sys_setrlimit(int which, \
-	SYS_OGETDIRENTRIES = 196 // { int sys_ogetdirentries(int fd, char *buf, \
-	SYS_MMAP           = 197 // { void *sys_mmap(void *addr, size_t len, int prot, \
-	SYS_LSEEK          = 199 // { off_t sys_lseek(int fd, int pad, off_t offset, \
-	SYS_TRUNCATE       = 200 // { int sys_truncate(const char *path, int pad, \
-	SYS_FTRUNCATE      = 201 // { int sys_ftruncate(int fd, int pad, off_t length); }
-	SYS___SYSCTL       = 202 // { int sys___sysctl(int *name, u_int namelen, \
-	SYS_MLOCK          = 203 // { int sys_mlock(const void *addr, size_t len); }
-	SYS_MUNLOCK        = 204 // { int sys_munlock(const void *addr, size_t len); }
-	SYS_FUTIMES        = 206 // { int sys_futimes(int fd, \
-	SYS_GETPGID        = 207 // { pid_t sys_getpgid(pid_t pid); }
-	SYS_NNPFSPIOCTL    = 208 // { int sys_nnpfspioctl(int operation, char *a_pathP, \
-	SYS_SEMGET         = 221 // { int sys_semget(key_t key, int nsems, int semflg); }
-	SYS_MSGGET         = 225 // { int sys_msgget(key_t key, int msgflg); }
-	SYS_MSGSND         = 226 // { int sys_msgsnd(int msqid, const void *msgp, size_t msgsz, \
-	SYS_MSGRCV         = 227 // { int sys_msgrcv(int msqid, void *msgp, size_t msgsz, \
-	SYS_SHMAT          = 228 // { void *sys_shmat(int shmid, const void *shmaddr, \
-	SYS_SHMDT          = 230 // { int sys_shmdt(const void *shmaddr); }
-	SYS_CLOCK_GETTIME  = 232 // { int sys_clock_gettime(clockid_t clock_id, \
-	SYS_CLOCK_SETTIME  = 233 // { int sys_clock_settime(clockid_t clock_id, \
-	SYS_CLOCK_GETRES   = 234 // { int sys_clock_getres(clockid_t clock_id, \
-	SYS_NANOSLEEP      = 240 // { int sys_nanosleep(const struct timespec *rqtp, \
-	SYS_MINHERIT       = 250 // { int sys_minherit(void *addr, size_t len, \
-	SYS_RFORK          = 251 // { int sys_rfork(int flags); }
-	SYS_POLL           = 252 // { int sys_poll(struct pollfd *fds, \
-	SYS_ISSETUGID      = 253 // { int sys_issetugid(void); }
-	SYS_LCHOWN         = 254 // { int sys_lchown(const char *path, uid_t uid, gid_t gid); }
-	SYS_GETSID         = 255 // { pid_t sys_getsid(pid_t pid); }
-	SYS_MSYNC          = 256 // { int sys_msync(void *addr, size_t len, int flags); }
-	SYS_PIPE           = 263 // { int sys_pipe(int *fdp); }
-	SYS_FHOPEN         = 264 // { int sys_fhopen(const fhandle_t *fhp, int flags); }
-	SYS_PREADV         = 267 // { ssize_t sys_preadv(int fd, \
-	SYS_PWRITEV        = 268 // { ssize_t sys_pwritev(int fd, \
-	SYS_KQUEUE         = 269 // { int sys_kqueue(void); }
-	SYS_KEVENT         = 270 // { int sys_kevent(int fd, \
-	SYS_MLOCKALL       = 271 // { int sys_mlockall(int flags); }
-	SYS_MUNLOCKALL     = 272 // { int sys_munlockall(void); }
-	SYS_GETRESUID      = 281 // { int sys_getresuid(uid_t *ruid, uid_t *euid, \
-	SYS_SETRESUID      = 282 // { int sys_setresuid(uid_t ruid, uid_t euid, \
-	SYS_GETRESGID      = 283 // { int sys_getresgid(gid_t *rgid, gid_t *egid, \
-	SYS_SETRESGID      = 284 // { int sys_setresgid(gid_t rgid, gid_t egid, \
-	SYS_MQUERY         = 286 // { void *sys_mquery(void *addr, size_t len, int prot, \
-	SYS_CLOSEFROM      = 287 // { int sys_closefrom(int fd); }
-	SYS_SIGALTSTACK    = 288 // { int sys_sigaltstack(const struct sigaltstack *nss, \
-	SYS_SHMGET         = 289 // { int sys_shmget(key_t key, size_t size, int shmflg); }
-	SYS_SEMOP          = 290 // { int sys_semop(int semid, struct sembuf *sops, \
-	SYS_STAT           = 291 // { int sys_stat(const char *path, struct stat *ub); }
-	SYS_FSTAT          = 292 // { int sys_fstat(int fd, struct stat *sb); }
-	SYS_LSTAT          = 293 // { int sys_lstat(const char *path, struct stat *ub); }
-	SYS_FHSTAT         = 294 // { int sys_fhstat(const fhandle_t *fhp, \
-	SYS___SEMCTL       = 295 // { int sys___semctl(int semid, int semnum, int cmd, \
-	SYS_SHMCTL         = 296 // { int sys_shmctl(int shmid, int cmd, \
-	SYS_MSGCTL         = 297 // { int sys_msgctl(int msqid, int cmd, \
-	SYS_SCHED_YIELD    = 298 // { int sys_sched_yield(void); }
-	SYS_GETTHRID       = 299 // { pid_t sys_getthrid(void); }
-	SYS_THRSLEEP       = 300 // { int sys_thrsleep(void *ident, clockid_t clock_id, \
-	SYS_THRWAKEUP      = 301 // { int sys_thrwakeup(void *ident, int n); }
-	SYS_THREXIT        = 302 // { void sys_threxit(pid_t *notdead); }
-	SYS_THRSIGDIVERT   = 303 // { int sys_thrsigdivert(sigset_t sigmask, \
-	SYS___GETCWD       = 304 // { int sys___getcwd(char *buf, size_t len); }
-	SYS_ADJFREQ        = 305 // { int sys_adjfreq(const int64_t *freq, \
-	SYS_GETFSSTAT      = 306 // { int sys_getfsstat(struct statfs *buf, size_t bufsize, \
-	SYS_STATFS         = 307 // { int sys_statfs(const char *path, \
-	SYS_FSTATFS        = 308 // { int sys_fstatfs(int fd, struct statfs *buf); }
-	SYS_FHSTATFS       = 309 // { int sys_fhstatfs(const fhandle_t *fhp, \
-	SYS_SETRTABLE      = 310 // { int sys_setrtable(int rtableid); }
-	SYS_GETRTABLE      = 311 // { int sys_getrtable(void); }
-	SYS_GETDIRENTRIES  = 312 // { int sys_getdirentries(int fd, char *buf, \
-	SYS_FACCESSAT      = 313 // { int sys_faccessat(int fd, const char *path, \
-	SYS_FCHMODAT       = 314 // { int sys_fchmodat(int fd, const char *path, \
-	SYS_FCHOWNAT       = 315 // { int sys_fchownat(int fd, const char *path, \
-	SYS_FSTATAT        = 316 // { int sys_fstatat(int fd, const char *path, \
-	SYS_LINKAT         = 317 // { int sys_linkat(int fd1, const char *path1, int fd2, \
-	SYS_MKDIRAT        = 318 // { int sys_mkdirat(int fd, const char *path, \
-	SYS_MKFIFOAT       = 319 // { int sys_mkfifoat(int fd, const char *path, \
-	SYS_MKNODAT        = 320 // { int sys_mknodat(int fd, const char *path, \
-	SYS_OPENAT         = 321 // { int sys_openat(int fd, const char *path, int flags, \
-	SYS_READLINKAT     = 322 // { ssize_t sys_readlinkat(int fd, const char *path, \
-	SYS_RENAMEAT       = 323 // { int sys_renameat(int fromfd, const char *from, \
-	SYS_SYMLINKAT      = 324 // { int sys_symlinkat(const char *path, int fd, \
-	SYS_UNLINKAT       = 325 // { int sys_unlinkat(int fd, const char *path, \
-	SYS_UTIMENSAT      = 326 // { int sys_utimensat(int fd, const char *path, \
+	SYS_EXIT          = 1   // { void sys_exit(int rval); }
+	SYS_FORK          = 2   // { int sys_fork(void); }
+	SYS_READ          = 3   // { ssize_t sys_read(int fd, void *buf, size_t nbyte); }
+	SYS_WRITE         = 4   // { ssize_t sys_write(int fd, const void *buf, \
+	SYS_OPEN          = 5   // { int sys_open(const char *path, \
+	SYS_CLOSE         = 6   // { int sys_close(int fd); }
+	SYS_WAIT4         = 7   // { pid_t sys_wait4(pid_t pid, int *status, int options, \
+	SYS_LINK          = 9   // { int sys_link(const char *path, const char *link); }
+	SYS_UNLINK        = 10  // { int sys_unlink(const char *path); }
+	SYS_CHDIR         = 12  // { int sys_chdir(const char *path); }
+	SYS_FCHDIR        = 13  // { int sys_fchdir(int fd); }
+	SYS_MKNOD         = 14  // { int sys_mknod(const char *path, mode_t mode, \
+	SYS_CHMOD         = 15  // { int sys_chmod(const char *path, mode_t mode); }
+	SYS_CHOWN         = 16  // { int sys_chown(const char *path, uid_t uid, \
+	SYS_OBREAK        = 17  // { int sys_obreak(char *nsize); } break
+	SYS_GETPID        = 20  // { pid_t sys_getpid(void); }
+	SYS_MOUNT         = 21  // { int sys_mount(const char *type, const char *path, \
+	SYS_UNMOUNT       = 22  // { int sys_unmount(const char *path, int flags); }
+	SYS_SETUID        = 23  // { int sys_setuid(uid_t uid); }
+	SYS_GETUID        = 24  // { uid_t sys_getuid(void); }
+	SYS_GETEUID       = 25  // { uid_t sys_geteuid(void); }
+	SYS_PTRACE        = 26  // { int sys_ptrace(int req, pid_t pid, caddr_t addr, \
+	SYS_RECVMSG       = 27  // { ssize_t sys_recvmsg(int s, struct msghdr *msg, \
+	SYS_SENDMSG       = 28  // { ssize_t sys_sendmsg(int s, \
+	SYS_RECVFROM      = 29  // { ssize_t sys_recvfrom(int s, void *buf, size_t len, \
+	SYS_ACCEPT        = 30  // { int sys_accept(int s, struct sockaddr *name, \
+	SYS_GETPEERNAME   = 31  // { int sys_getpeername(int fdes, struct sockaddr *asa, \
+	SYS_GETSOCKNAME   = 32  // { int sys_getsockname(int fdes, struct sockaddr *asa, \
+	SYS_ACCESS        = 33  // { int sys_access(const char *path, int flags); }
+	SYS_CHFLAGS       = 34  // { int sys_chflags(const char *path, u_int flags); }
+	SYS_FCHFLAGS      = 35  // { int sys_fchflags(int fd, u_int flags); }
+	SYS_SYNC          = 36  // { void sys_sync(void); }
+	SYS_KILL          = 37  // { int sys_kill(int pid, int signum); }
+	SYS_GETPPID       = 39  // { pid_t sys_getppid(void); }
+	SYS_DUP           = 41  // { int sys_dup(int fd); }
+	SYS_GETEGID       = 43  // { gid_t sys_getegid(void); }
+	SYS_PROFIL        = 44  // { int sys_profil(caddr_t samples, size_t size, \
+	SYS_KTRACE        = 45  // { int sys_ktrace(const char *fname, int ops, \
+	SYS_SIGACTION     = 46  // { int sys_sigaction(int signum, \
+	SYS_GETGID        = 47  // { gid_t sys_getgid(void); }
+	SYS_SIGPROCMASK   = 48  // { int sys_sigprocmask(int how, sigset_t mask); }
+	SYS_GETLOGIN      = 49  // { int sys_getlogin(char *namebuf, u_int namelen); }
+	SYS_SETLOGIN      = 50  // { int sys_setlogin(const char *namebuf); }
+	SYS_ACCT          = 51  // { int sys_acct(const char *path); }
+	SYS_SIGPENDING    = 52  // { int sys_sigpending(void); }
+	SYS_IOCTL         = 54  // { int sys_ioctl(int fd, \
+	SYS_REBOOT        = 55  // { int sys_reboot(int opt); }
+	SYS_REVOKE        = 56  // { int sys_revoke(const char *path); }
+	SYS_SYMLINK       = 57  // { int sys_symlink(const char *path, \
+	SYS_READLINK      = 58  // { int sys_readlink(const char *path, char *buf, \
+	SYS_EXECVE        = 59  // { int sys_execve(const char *path, \
+	SYS_UMASK         = 60  // { mode_t sys_umask(mode_t newmask); }
+	SYS_CHROOT        = 61  // { int sys_chroot(const char *path); }
+	SYS_VFORK         = 66  // { int sys_vfork(void); }
+	SYS_MUNMAP        = 73  // { int sys_munmap(void *addr, size_t len); }
+	SYS_MPROTECT      = 74  // { int sys_mprotect(void *addr, size_t len, \
+	SYS_MADVISE       = 75  // { int sys_madvise(void *addr, size_t len, \
+	SYS_MINCORE       = 78  // { int sys_mincore(void *addr, size_t len, \
+	SYS_GETGROUPS     = 79  // { int sys_getgroups(int gidsetsize, \
+	SYS_SETGROUPS     = 80  // { int sys_setgroups(int gidsetsize, \
+	SYS_GETPGRP       = 81  // { int sys_getpgrp(void); }
+	SYS_SETPGID       = 82  // { int sys_setpgid(pid_t pid, int pgid); }
+	SYS_SETITIMER     = 83  // { int sys_setitimer(int which, \
+	SYS_GETITIMER     = 86  // { int sys_getitimer(int which, \
+	SYS_DUP2          = 90  // { int sys_dup2(int from, int to); }
+	SYS_FCNTL         = 92  // { int sys_fcntl(int fd, int cmd, ... void *arg); }
+	SYS_SELECT        = 93  // { int sys_select(int nd, fd_set *in, fd_set *ou, \
+	SYS_FSYNC         = 95  // { int sys_fsync(int fd); }
+	SYS_SETPRIORITY   = 96  // { int sys_setpriority(int which, id_t who, int prio); }
+	SYS_SOCKET        = 97  // { int sys_socket(int domain, int type, int protocol); }
+	SYS_CONNECT       = 98  // { int sys_connect(int s, const struct sockaddr *name, \
+	SYS_GETPRIORITY   = 100 // { int sys_getpriority(int which, id_t who); }
+	SYS_SIGRETURN     = 103 // { int sys_sigreturn(struct sigcontext *sigcntxp); }
+	SYS_BIND          = 104 // { int sys_bind(int s, const struct sockaddr *name, \
+	SYS_SETSOCKOPT    = 105 // { int sys_setsockopt(int s, int level, int name, \
+	SYS_LISTEN        = 106 // { int sys_listen(int s, int backlog); }
+	SYS_SIGSUSPEND    = 111 // { int sys_sigsuspend(int mask); }
+	SYS_GETTIMEOFDAY  = 116 // { int sys_gettimeofday(struct timeval *tp, \
+	SYS_GETRUSAGE     = 117 // { int sys_getrusage(int who, struct rusage *rusage); }
+	SYS_GETSOCKOPT    = 118 // { int sys_getsockopt(int s, int level, int name, \
+	SYS_READV         = 120 // { ssize_t sys_readv(int fd, \
+	SYS_WRITEV        = 121 // { ssize_t sys_writev(int fd, \
+	SYS_SETTIMEOFDAY  = 122 // { int sys_settimeofday(const struct timeval *tv, \
+	SYS_FCHOWN        = 123 // { int sys_fchown(int fd, uid_t uid, gid_t gid); }
+	SYS_FCHMOD        = 124 // { int sys_fchmod(int fd, mode_t mode); }
+	SYS_SETREUID      = 126 // { int sys_setreuid(uid_t ruid, uid_t euid); }
+	SYS_SETREGID      = 127 // { int sys_setregid(gid_t rgid, gid_t egid); }
+	SYS_RENAME        = 128 // { int sys_rename(const char *from, const char *to); }
+	SYS_FLOCK         = 131 // { int sys_flock(int fd, int how); }
+	SYS_MKFIFO        = 132 // { int sys_mkfifo(const char *path, mode_t mode); }
+	SYS_SENDTO        = 133 // { ssize_t sys_sendto(int s, const void *buf, \
+	SYS_SHUTDOWN      = 134 // { int sys_shutdown(int s, int how); }
+	SYS_SOCKETPAIR    = 135 // { int sys_socketpair(int domain, int type, \
+	SYS_MKDIR         = 136 // { int sys_mkdir(const char *path, mode_t mode); }
+	SYS_RMDIR         = 137 // { int sys_rmdir(const char *path); }
+	SYS_UTIMES        = 138 // { int sys_utimes(const char *path, \
+	SYS_ADJTIME       = 140 // { int sys_adjtime(const struct timeval *delta, \
+	SYS_SETSID        = 147 // { int sys_setsid(void); }
+	SYS_QUOTACTL      = 148 // { int sys_quotactl(const char *path, int cmd, \
+	SYS_NFSSVC        = 155 // { int sys_nfssvc(int flag, void *argp); }
+	SYS_GETFH         = 161 // { int sys_getfh(const char *fname, fhandle_t *fhp); }
+	SYS_SYSARCH       = 165 // { int sys_sysarch(int op, void *parms); }
+	SYS_PREAD         = 173 // { ssize_t sys_pread(int fd, void *buf, \
+	SYS_PWRITE        = 174 // { ssize_t sys_pwrite(int fd, const void *buf, \
+	SYS_SETGID        = 181 // { int sys_setgid(gid_t gid); }
+	SYS_SETEGID       = 182 // { int sys_setegid(gid_t egid); }
+	SYS_SETEUID       = 183 // { int sys_seteuid(uid_t euid); }
+	LFS_BMAPV         = 184 // { int lfs_bmapv(fsid_t *fsidp, \
+	LFS_MARKV         = 185 // { int lfs_markv(fsid_t *fsidp, \
+	LFS_SEGCLEAN      = 186 // { int lfs_segclean(fsid_t *fsidp, u_long segment); }
+	LFS_SEGWAIT       = 187 // { int lfs_segwait(fsid_t *fsidp, struct timeval *tv); }
+	SYS_PATHCONF      = 191 // { long sys_pathconf(const char *path, int name); }
+	SYS_FPATHCONF     = 192 // { long sys_fpathconf(int fd, int name); }
+	SYS_SWAPCTL       = 193 // { int sys_swapctl(int cmd, const void *arg, int misc); }
+	SYS_GETRLIMIT     = 194 // { int sys_getrlimit(int which, \
+	SYS_SETRLIMIT     = 195 // { int sys_setrlimit(int which, \
+	SYS_MMAP          = 197 // { void *sys_mmap(void *addr, size_t len, int prot, \
+	SYS_LSEEK         = 199 // { off_t sys_lseek(int fd, int pad, off_t offset, \
+	SYS_TRUNCATE      = 200 // { int sys_truncate(const char *path, int pad, \
+	SYS_FTRUNCATE     = 201 // { int sys_ftruncate(int fd, int pad, off_t length); }
+	SYS___SYSCTL      = 202 // { int sys___sysctl(int *name, u_int namelen, \
+	SYS_MLOCK         = 203 // { int sys_mlock(const void *addr, size_t len); }
+	SYS_MUNLOCK       = 204 // { int sys_munlock(const void *addr, size_t len); }
+	SYS_FUTIMES       = 206 // { int sys_futimes(int fd, \
+	SYS_GETPGID       = 207 // { pid_t sys_getpgid(pid_t pid); }
+	SYS_NNPFSPIOCTL   = 208 // { int sys_nnpfspioctl(int operation, char *a_pathP, \
+	SYS_SEMGET        = 221 // { int sys_semget(key_t key, int nsems, int semflg); }
+	SYS_MSGGET        = 225 // { int sys_msgget(key_t key, int msgflg); }
+	SYS_MSGSND        = 226 // { int sys_msgsnd(int msqid, const void *msgp, size_t msgsz, \
+	SYS_MSGRCV        = 227 // { int sys_msgrcv(int msqid, void *msgp, size_t msgsz, \
+	SYS_SHMAT         = 228 // { void *sys_shmat(int shmid, const void *shmaddr, \
+	SYS_SHMDT         = 230 // { int sys_shmdt(const void *shmaddr); }
+	SYS_CLOCK_GETTIME = 232 // { int sys_clock_gettime(clockid_t clock_id, \
+	SYS_CLOCK_SETTIME = 233 // { int sys_clock_settime(clockid_t clock_id, \
+	SYS_CLOCK_GETRES  = 234 // { int sys_clock_getres(clockid_t clock_id, \
+	SYS_NANOSLEEP     = 240 // { int sys_nanosleep(const struct timespec *rqtp, \
+	SYS_MINHERIT      = 250 // { int sys_minherit(void *addr, size_t len, \
+	SYS_RFORK         = 251 // { int sys_rfork(int flags); }
+	SYS_POLL          = 252 // { int sys_poll(struct pollfd *fds, \
+	SYS_ISSETUGID     = 253 // { int sys_issetugid(void); }
+	SYS_LCHOWN        = 254 // { int sys_lchown(const char *path, uid_t uid, gid_t gid); }
+	SYS_GETSID        = 255 // { pid_t sys_getsid(pid_t pid); }
+	SYS_MSYNC         = 256 // { int sys_msync(void *addr, size_t len, int flags); }
+	SYS_PIPE          = 263 // { int sys_pipe(int *fdp); }
+	SYS_FHOPEN        = 264 // { int sys_fhopen(const fhandle_t *fhp, int flags); }
+	SYS_PREADV        = 267 // { ssize_t sys_preadv(int fd, \
+	SYS_PWRITEV       = 268 // { ssize_t sys_pwritev(int fd, \
+	SYS_KQUEUE        = 269 // { int sys_kqueue(void); }
+	SYS_KEVENT        = 270 // { int sys_kevent(int fd, \
+	SYS_MLOCKALL      = 271 // { int sys_mlockall(int flags); }
+	SYS_MUNLOCKALL    = 272 // { int sys_munlockall(void); }
+	SYS_GETRESUID     = 281 // { int sys_getresuid(uid_t *ruid, uid_t *euid, \
+	SYS_SETRESUID     = 282 // { int sys_setresuid(uid_t ruid, uid_t euid, \
+	SYS_GETRESGID     = 283 // { int sys_getresgid(gid_t *rgid, gid_t *egid, \
+	SYS_SETRESGID     = 284 // { int sys_setresgid(gid_t rgid, gid_t egid, \
+	SYS_MQUERY        = 286 // { void *sys_mquery(void *addr, size_t len, int prot, \
+	SYS_CLOSEFROM     = 287 // { int sys_closefrom(int fd); }
+	SYS_SIGALTSTACK   = 288 // { int sys_sigaltstack(const struct sigaltstack *nss, \
+	SYS_SHMGET        = 289 // { int sys_shmget(key_t key, size_t size, int shmflg); }
+	SYS_SEMOP         = 290 // { int sys_semop(int semid, struct sembuf *sops, \
+	SYS_STAT          = 291 // { int sys_stat(const char *path, struct stat *ub); }
+	SYS_FSTAT         = 292 // { int sys_fstat(int fd, struct stat *sb); }
+	SYS_LSTAT         = 293 // { int sys_lstat(const char *path, struct stat *ub); }
+	SYS_FHSTAT        = 294 // { int sys_fhstat(const fhandle_t *fhp, \
+	SYS___SEMCTL      = 295 // { int sys___semctl(int semid, int semnum, int cmd, \
+	SYS_SHMCTL        = 296 // { int sys_shmctl(int shmid, int cmd, \
+	SYS_MSGCTL        = 297 // { int sys_msgctl(int msqid, int cmd, \
+	SYS_SCHED_YIELD   = 298 // { int sys_sched_yield(void); }
+	SYS_GETTHRID      = 299 // { pid_t sys_getthrid(void); }
+	SYS_THRSLEEP      = 300 // { int sys_thrsleep(void *ident, clockid_t clock_id, \
+	SYS_THRWAKEUP     = 301 // { int sys_thrwakeup(void *ident, int n); }
+	SYS_THREXIT       = 302 // { void sys_threxit(pid_t *notdead); }
+	SYS_THRSIGDIVERT  = 303 // { int sys_thrsigdivert(sigset_t sigmask, \
+	SYS___GETCWD      = 304 // { int sys___getcwd(char *buf, size_t len); }
+	SYS_ADJFREQ       = 305 // { int sys_adjfreq(const int64_t *freq, \
+	SYS_GETFSSTAT     = 306 // { int sys_getfsstat(struct statfs *buf, size_t bufsize, \
+	SYS_STATFS        = 307 // { int sys_statfs(const char *path, \
+	SYS_FSTATFS       = 308 // { int sys_fstatfs(int fd, struct statfs *buf); }
+	SYS_FHSTATFS      = 309 // { int sys_fhstatfs(const fhandle_t *fhp, \
+	SYS_SETRTABLE     = 310 // { int sys_setrtable(int rtableid); }
+	SYS_GETRTABLE     = 311 // { int sys_getrtable(void); }
+	SYS_GETDIRENTRIES = 312 // { int sys_getdirentries(int fd, char *buf, \
+	SYS_FACCESSAT     = 313 // { int sys_faccessat(int fd, const char *path, \
+	SYS_FCHMODAT      = 314 // { int sys_fchmodat(int fd, const char *path, \
+	SYS_FCHOWNAT      = 315 // { int sys_fchownat(int fd, const char *path, \
+	SYS_FSTATAT       = 316 // { int sys_fstatat(int fd, const char *path, \
+	SYS_LINKAT        = 317 // { int sys_linkat(int fd1, const char *path1, int fd2, \
+	SYS_MKDIRAT       = 318 // { int sys_mkdirat(int fd, const char *path, \
+	SYS_MKFIFOAT      = 319 // { int sys_mkfifoat(int fd, const char *path, \
+	SYS_MKNODAT       = 320 // { int sys_mknodat(int fd, const char *path, \
+	SYS_OPENAT        = 321 // { int sys_openat(int fd, const char *path, int flags, \
+	SYS_READLINKAT    = 322 // { ssize_t sys_readlinkat(int fd, const char *path, \
+	SYS_RENAMEAT      = 323 // { int sys_renameat(int fromfd, const char *from, \
+	SYS_SYMLINKAT     = 324 // { int sys_symlinkat(const char *path, int fd, \
+	SYS_UNLINKAT      = 325 // { int sys_unlinkat(int fd, const char *path, \
+	SYS_UTIMENSAT     = 326 // { int sys_utimensat(int fd, const char *path, \
+	SYS_FUTIMENS      = 327 // { int sys_futimens(int fd, \
+	SYS___TFORK       = 328 // { int sys___tfork(struct __tfork *param); }
+	SYS___SET_TCB     = 329 // { void sys___set_tcb(void *tcb); }
+	SYS___GET_TCB     = 330 // { void *sys___get_tcb(void); }
 )
diff --git a/src/pkg/syscall/zsysnum_openbsd_amd64.go b/src/pkg/syscall/zsysnum_openbsd_amd64.go
index dc47750..230da1e 100644
--- a/src/pkg/syscall/zsysnum_openbsd_amd64.go
+++ b/src/pkg/syscall/zsysnum_openbsd_amd64.go
@@ -201,4 +201,7 @@ const (
 	SYS_UNLINKAT      = 325 // { int sys_unlinkat(int fd, const char *path, \
 	SYS_UTIMENSAT     = 326 // { int sys_utimensat(int fd, const char *path, \
 	SYS_FUTIMENS      = 327 // { int sys_futimens(int fd, \
+	SYS___TFORK       = 328 // { int sys___tfork(struct __tfork *param); }
+	SYS___SET_TCB     = 329 // { void sys___set_tcb(void *tcb); }
+	SYS___GET_TCB     = 330 // { void *sys___get_tcb(void); }
 )
diff --git a/src/pkg/syscall/ztypes_darwin_386.go b/src/pkg/syscall/ztypes_darwin_386.go
index 0ec74f3..566b021 100644
--- a/src/pkg/syscall/ztypes_darwin_386.go
+++ b/src/pkg/syscall/ztypes_darwin_386.go
@@ -1,54 +1,22 @@
-// godefs -gsyscall -f-m32 types_darwin.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_darwin.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr              = 0x4
-	sizeofShort            = 0x2
-	sizeofInt              = 0x4
-	sizeofLong             = 0x4
-	sizeofLongLong         = 0x8
-	O_CLOEXEC              = 0
-	SizeofSockaddrInet4    = 0x10
-	SizeofSockaddrInet6    = 0x1c
-	SizeofSockaddrAny      = 0x6c
-	SizeofSockaddrUnix     = 0x6a
-	SizeofSockaddrDatalink = 0x14
-	SizeofLinger           = 0x8
-	SizeofIPMreq           = 0x8
-	SizeofIPv6Mreq         = 0x14
-	SizeofMsghdr           = 0x1c
-	SizeofCmsghdr          = 0xc
-	SizeofInet6Pktinfo     = 0x14
-	PTRACE_TRACEME         = 0
-	PTRACE_CONT            = 0x7
-	PTRACE_KILL            = 0x8
-	SizeofIfMsghdr         = 0x70
-	SizeofIfData           = 0x60
-	SizeofIfaMsghdr        = 0x14
-	SizeofIfmaMsghdr       = 0x10
-	SizeofIfmaMsghdr2      = 0x14
-	SizeofRtMsghdr         = 0x5c
-	SizeofRtMetrics        = 0x38
-	SizeofBpfVersion       = 0x4
-	SizeofBpfStat          = 0x8
-	SizeofBpfProgram       = 0x8
-	SizeofBpfInsn          = 0x8
-	SizeofBpfHdr           = 0x14
+	sizeofPtr      = 0x4
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x4
+	sizeofLongLong = 0x8
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int32
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int32
+	_C_long_long int64
+)
 
 type Timespec struct {
 	Sec  int32
@@ -60,6 +28,8 @@ type Timeval struct {
 	Usec int32
 }
 
+type Timeval32 [0]byte
+
 type Rusage struct {
 	Utime    Timeval
 	Stime    Timeval
@@ -115,7 +85,7 @@ type Statfs_t struct {
 	Bavail      uint64
 	Files       uint64
 	Ffree       uint64
-	Fsid        [8]byte /* fsid */
+	Fsid        Fsid
 	Owner       uint32
 	Type        uint32
 	Flags       uint32
@@ -159,14 +129,18 @@ type Log2phys_t struct {
 	Devoffset   int64
 }
 
+type Fsid struct {
+	Val [2]int32
+}
+
 type Dirent struct {
-	Ino          uint64
-	Seekoff      uint64
-	Reclen       uint16
-	Namlen       uint16
-	Type         uint8
-	Name         [1024]int8
-	Pad_godefs_0 [3]byte
+	Ino       uint64
+	Seekoff   uint64
+	Reclen    uint16
+	Namlen    uint16
+	Type      uint8
+	Name      [1024]int8
+	Pad_cgo_0 [3]byte
 }
 
 type RawSockaddrInet4 struct {
@@ -257,6 +231,26 @@ type Inet6Pktinfo struct {
 	Ifindex uint32
 }
 
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x14
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x1c
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
 type Kevent_t struct {
 	Ident  uint32
 	Filter int16
@@ -270,15 +264,25 @@ type FdSet struct {
 	Bits [32]int32
 }
 
+const (
+	SizeofIfMsghdr    = 0x70
+	SizeofIfData      = 0x60
+	SizeofIfaMsghdr   = 0x14
+	SizeofIfmaMsghdr  = 0x10
+	SizeofIfmaMsghdr2 = 0x14
+	SizeofRtMsghdr    = 0x5c
+	SizeofRtMetrics   = 0x38
+)
+
 type IfMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Data         IfData
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Data      IfData
 }
 
 type IfData struct {
@@ -314,51 +318,51 @@ type IfData struct {
 }
 
 type IfaMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Metric       int32
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Metric    int32
 }
 
 type IfmaMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
 }
 
 type IfmaMsghdr2 struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Refcount     int32
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Refcount  int32
 }
 
 type RtMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Flags        int32
-	Addrs        int32
-	Pid          int32
-	Seq          int32
-	Errno        int32
-	Use          int32
-	Inits        uint32
-	Rmx          RtMetrics
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Flags     int32
+	Addrs     int32
+	Pid       int32
+	Seq       int32
+	Errno     int32
+	Use       int32
+	Inits     uint32
+	Rmx       RtMetrics
 }
 
 type RtMetrics struct {
@@ -375,6 +379,14 @@ type RtMetrics struct {
 	Filler   [4]uint32
 }
 
+const (
+	SizeofBpfVersion = 0x4
+	SizeofBpfStat    = 0x8
+	SizeofBpfProgram = 0x8
+	SizeofBpfInsn    = 0x8
+	SizeofBpfHdr     = 0x14
+)
+
 type BpfVersion struct {
 	Major uint16
 	Minor uint16
@@ -398,9 +410,9 @@ type BpfInsn struct {
 }
 
 type BpfHdr struct {
-	Tstamp       Timeval
-	Caplen       uint32
-	Datalen      uint32
-	Hdrlen       uint16
-	Pad_godefs_0 [2]byte
+	Tstamp    Timeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
 }
diff --git a/src/pkg/syscall/ztypes_darwin_amd64.go b/src/pkg/syscall/ztypes_darwin_amd64.go
index f0e8a92..2c65311 100644
--- a/src/pkg/syscall/ztypes_darwin_amd64.go
+++ b/src/pkg/syscall/ztypes_darwin_amd64.go
@@ -1,54 +1,22 @@
-// godefs -gsyscall -f-m64 types_darwin.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_darwin.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr              = 0x8
-	sizeofShort            = 0x2
-	sizeofInt              = 0x4
-	sizeofLong             = 0x8
-	sizeofLongLong         = 0x8
-	O_CLOEXEC              = 0
-	SizeofSockaddrInet4    = 0x10
-	SizeofSockaddrInet6    = 0x1c
-	SizeofSockaddrAny      = 0x6c
-	SizeofSockaddrUnix     = 0x6a
-	SizeofSockaddrDatalink = 0x14
-	SizeofLinger           = 0x8
-	SizeofIPMreq           = 0x8
-	SizeofIPv6Mreq         = 0x14
-	SizeofMsghdr           = 0x30
-	SizeofCmsghdr          = 0xc
-	SizeofInet6Pktinfo     = 0x14
-	PTRACE_TRACEME         = 0
-	PTRACE_CONT            = 0x7
-	PTRACE_KILL            = 0x8
-	SizeofIfMsghdr         = 0x70
-	SizeofIfData           = 0x60
-	SizeofIfaMsghdr        = 0x14
-	SizeofIfmaMsghdr       = 0x10
-	SizeofIfmaMsghdr2      = 0x14
-	SizeofRtMsghdr         = 0x5c
-	SizeofRtMetrics        = 0x38
-	SizeofBpfVersion       = 0x4
-	SizeofBpfStat          = 0x8
-	SizeofBpfProgram       = 0x10
-	SizeofBpfInsn          = 0x8
-	SizeofBpfHdr           = 0x14
+	sizeofPtr      = 0x8
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x8
+	sizeofLongLong = 0x8
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int64
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int64
+	_C_long_long int64
+)
 
 type Timespec struct {
 	Sec  int64
@@ -56,9 +24,9 @@ type Timespec struct {
 }
 
 type Timeval struct {
-	Sec          int64
-	Usec         int32
-	Pad_godefs_0 [4]byte
+	Sec       int64
+	Usec      int32
+	Pad_cgo_0 [4]byte
 }
 
 type Timeval32 struct {
@@ -100,7 +68,7 @@ type Stat_t struct {
 	Uid           uint32
 	Gid           uint32
 	Rdev          int32
-	Pad_godefs_0  [4]byte
+	Pad_cgo_0     [4]byte
 	Atimespec     Timespec
 	Mtimespec     Timespec
 	Ctimespec     Timespec
@@ -122,7 +90,7 @@ type Statfs_t struct {
 	Bavail      uint64
 	Files       uint64
 	Ffree       uint64
-	Fsid        [8]byte /* fsid */
+	Fsid        Fsid
 	Owner       uint32
 	Type        uint32
 	Flags       uint32
@@ -150,9 +118,9 @@ type Fstore_t struct {
 }
 
 type Radvisory_t struct {
-	Offset       int64
-	Count        int32
-	Pad_godefs_0 [4]byte
+	Offset    int64
+	Count     int32
+	Pad_cgo_0 [4]byte
 }
 
 type Fbootstraptransfer_t struct {
@@ -167,14 +135,18 @@ type Log2phys_t struct {
 	Devoffset   int64
 }
 
+type Fsid struct {
+	Val [2]int32
+}
+
 type Dirent struct {
-	Ino          uint64
-	Seekoff      uint64
-	Reclen       uint16
-	Namlen       uint16
-	Type         uint8
-	Name         [1024]int8
-	Pad_godefs_0 [3]byte
+	Ino       uint64
+	Seekoff   uint64
+	Reclen    uint16
+	Namlen    uint16
+	Type      uint8
+	Name      [1024]int8
+	Pad_cgo_0 [3]byte
 }
 
 type RawSockaddrInet4 struct {
@@ -245,15 +217,15 @@ type IPv6Mreq struct {
 }
 
 type Msghdr struct {
-	Name         *byte
-	Namelen      uint32
-	Pad_godefs_0 [4]byte
-	Iov          *Iovec
-	Iovlen       int32
-	Pad_godefs_1 [4]byte
-	Control      *byte
-	Controllen   uint32
-	Flags        int32
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *Iovec
+	Iovlen     int32
+	Pad_cgo_1  [4]byte
+	Control    *byte
+	Controllen uint32
+	Flags      int32
 }
 
 type Cmsghdr struct {
@@ -267,6 +239,26 @@ type Inet6Pktinfo struct {
 	Ifindex uint32
 }
 
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x14
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x30
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
 type Kevent_t struct {
 	Ident  uint64
 	Filter int16
@@ -280,15 +272,25 @@ type FdSet struct {
 	Bits [32]int32
 }
 
+const (
+	SizeofIfMsghdr    = 0x70
+	SizeofIfData      = 0x60
+	SizeofIfaMsghdr   = 0x14
+	SizeofIfmaMsghdr  = 0x10
+	SizeofIfmaMsghdr2 = 0x14
+	SizeofRtMsghdr    = 0x5c
+	SizeofRtMetrics   = 0x38
+)
+
 type IfMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Data         IfData
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Data      IfData
 }
 
 type IfData struct {
@@ -324,51 +326,51 @@ type IfData struct {
 }
 
 type IfaMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Metric       int32
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Metric    int32
 }
 
 type IfmaMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
 }
 
 type IfmaMsghdr2 struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Refcount     int32
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Refcount  int32
 }
 
 type RtMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Flags        int32
-	Addrs        int32
-	Pid          int32
-	Seq          int32
-	Errno        int32
-	Use          int32
-	Inits        uint32
-	Rmx          RtMetrics
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Flags     int32
+	Addrs     int32
+	Pid       int32
+	Seq       int32
+	Errno     int32
+	Use       int32
+	Inits     uint32
+	Rmx       RtMetrics
 }
 
 type RtMetrics struct {
@@ -385,6 +387,14 @@ type RtMetrics struct {
 	Filler   [4]uint32
 }
 
+const (
+	SizeofBpfVersion = 0x4
+	SizeofBpfStat    = 0x8
+	SizeofBpfProgram = 0x10
+	SizeofBpfInsn    = 0x8
+	SizeofBpfHdr     = 0x14
+)
+
 type BpfVersion struct {
 	Major uint16
 	Minor uint16
@@ -396,9 +406,9 @@ type BpfStat struct {
 }
 
 type BpfProgram struct {
-	Len          uint32
-	Pad_godefs_0 [4]byte
-	Insns        *BpfInsn
+	Len       uint32
+	Pad_cgo_0 [4]byte
+	Insns     *BpfInsn
 }
 
 type BpfInsn struct {
@@ -409,9 +419,9 @@ type BpfInsn struct {
 }
 
 type BpfHdr struct {
-	Tstamp       Timeval32
-	Caplen       uint32
-	Datalen      uint32
-	Hdrlen       uint16
-	Pad_godefs_0 [2]byte
+	Tstamp    Timeval32
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
 }
diff --git a/src/pkg/syscall/ztypes_freebsd_386.go b/src/pkg/syscall/ztypes_freebsd_386.go
index 01cf2fb..4149948 100644
--- a/src/pkg/syscall/ztypes_freebsd_386.go
+++ b/src/pkg/syscall/ztypes_freebsd_386.go
@@ -1,69 +1,22 @@
-// godefs -gsyscall -f-m32 types_freebsd.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_freebsd.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr              = 0x4
-	sizeofShort            = 0x2
-	sizeofInt              = 0x4
-	sizeofLong             = 0x4
-	sizeofLongLong         = 0x8
-	O_CLOEXEC              = 0
-	S_IFMT                 = 0xf000
-	S_IFIFO                = 0x1000
-	S_IFCHR                = 0x2000
-	S_IFDIR                = 0x4000
-	S_IFBLK                = 0x6000
-	S_IFREG                = 0x8000
-	S_IFLNK                = 0xa000
-	S_IFSOCK               = 0xc000
-	S_ISUID                = 0x800
-	S_ISGID                = 0x400
-	S_ISVTX                = 0x200
-	S_IRUSR                = 0x100
-	S_IWUSR                = 0x80
-	S_IXUSR                = 0x40
-	SizeofSockaddrInet4    = 0x10
-	SizeofSockaddrInet6    = 0x1c
-	SizeofSockaddrAny      = 0x6c
-	SizeofSockaddrUnix     = 0x6a
-	SizeofSockaddrDatalink = 0x36
-	SizeofLinger           = 0x8
-	SizeofIPMreq           = 0x8
-	SizeofIPv6Mreq         = 0x14
-	SizeofMsghdr           = 0x1c
-	SizeofCmsghdr          = 0xc
-	SizeofInet6Pktinfo     = 0x14
-	PTRACE_TRACEME         = 0
-	PTRACE_CONT            = 0x7
-	PTRACE_KILL            = 0x8
-	SizeofIfMsghdr         = 0x60
-	SizeofIfData           = 0x50
-	SizeofIfaMsghdr        = 0x14
-	SizeofIfmaMsghdr       = 0x10
-	SizeofRtMsghdr         = 0x5c
-	SizeofRtMetrics        = 0x38
-	SizeofBpfVersion       = 0x4
-	SizeofBpfStat          = 0x8
-	SizeofBpfZbuf          = 0xc
-	SizeofBpfProgram       = 0x8
-	SizeofBpfInsn          = 0x8
-	SizeofBpfHdr           = 0x14
-	SizeofBpfZbufHeader    = 0x20
+	sizeofPtr      = 0x4
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x4
+	sizeofLongLong = 0x8
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int32
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int32
+	_C_long_long int64
+)
 
 type Timespec struct {
 	Sec  int32
@@ -101,6 +54,27 @@ type Rlimit struct {
 
 type _Gid_t uint32
 
+const (
+	O_CLOEXEC = 0
+)
+
+const (
+	S_IFMT   = 0xf000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+	S_ISUID  = 0x800
+	S_ISGID  = 0x400
+	S_ISVTX  = 0x200
+	S_IRUSR  = 0x100
+	S_IWUSR  = 0x80
+	S_IXUSR  = 0x40
+)
+
 type Stat_t struct {
 	Dev           uint32
 	Ino           uint32
@@ -119,8 +93,7 @@ type Stat_t struct {
 	Gen           uint32
 	Lspare        int32
 	Birthtimespec Timespec
-	Pad_godefs_0  uint32
-	Pad_godefs_1  uint32
+	Pad_cgo_0     [8]byte
 }
 
 type Statfs_t struct {
@@ -141,7 +114,7 @@ type Statfs_t struct {
 	Spare       [10]uint64
 	Namemax     uint32
 	Owner       uint32
-	Fsid        [8]byte /* fsid */
+	Fsid        Fsid
 	Charspare   [80]int8
 	Fstypename  [16]int8
 	Mntfromname [88]int8
@@ -165,6 +138,10 @@ type Dirent struct {
 	Name   [256]int8
 }
 
+type Fsid struct {
+	Val [2]int32
+}
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
@@ -227,6 +204,12 @@ type IPMreq struct {
 	Interface [4]byte /* in_addr */
 }
 
+type IPMreqn struct {
+	Multiaddr [4]byte /* in_addr */
+	Address   [4]byte /* in_addr */
+	Ifindex   int32
+}
+
 type IPv6Mreq struct {
 	Multiaddr [16]byte /* in6_addr */
 	Interface uint32
@@ -253,6 +236,27 @@ type Inet6Pktinfo struct {
 	Ifindex uint32
 }
 
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x36
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPMreqn          = 0xc
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x1c
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
 type Kevent_t struct {
 	Ident  uint32
 	Filter int16
@@ -266,15 +270,24 @@ type FdSet struct {
 	X__fds_bits [32]uint32
 }
 
+const (
+	SizeofIfMsghdr   = 0x60
+	SizeofIfData     = 0x50
+	SizeofIfaMsghdr  = 0x14
+	SizeofIfmaMsghdr = 0x10
+	SizeofRtMsghdr   = 0x5c
+	SizeofRtMetrics  = 0x38
+)
+
 type IfMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Data         IfData
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Data      IfData
 }
 
 type IfData struct {
@@ -306,40 +319,40 @@ type IfData struct {
 }
 
 type IfaMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Metric       int32
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Metric    int32
 }
 
 type IfmaMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
 }
 
 type RtMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Flags        int32
-	Addrs        int32
-	Pid          int32
-	Seq          int32
-	Errno        int32
-	Fmask        int32
-	Inits        uint32
-	Rmx          RtMetrics
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Flags     int32
+	Addrs     int32
+	Pid       int32
+	Seq       int32
+	Errno     int32
+	Fmask     int32
+	Inits     uint32
+	Rmx       RtMetrics
 }
 
 type RtMetrics struct {
@@ -357,6 +370,16 @@ type RtMetrics struct {
 	Filler   [3]uint32
 }
 
+const (
+	SizeofBpfVersion    = 0x4
+	SizeofBpfStat       = 0x8
+	SizeofBpfZbuf       = 0xc
+	SizeofBpfProgram    = 0x8
+	SizeofBpfInsn       = 0x8
+	SizeofBpfHdr        = 0x14
+	SizeofBpfZbufHeader = 0x20
+)
+
 type BpfVersion struct {
 	Major uint16
 	Minor uint16
@@ -386,11 +409,11 @@ type BpfInsn struct {
 }
 
 type BpfHdr struct {
-	Tstamp       Timeval
-	Caplen       uint32
-	Datalen      uint32
-	Hdrlen       uint16
-	Pad_godefs_0 [2]byte
+	Tstamp    Timeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
 }
 
 type BpfZbufHeader struct {
diff --git a/src/pkg/syscall/ztypes_freebsd_amd64.go b/src/pkg/syscall/ztypes_freebsd_amd64.go
index d6a05ae..80c12f6 100644
--- a/src/pkg/syscall/ztypes_freebsd_amd64.go
+++ b/src/pkg/syscall/ztypes_freebsd_amd64.go
@@ -1,69 +1,22 @@
-// godefs -gsyscall -f-m64 types_freebsd.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_freebsd.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr              = 0x8
-	sizeofShort            = 0x2
-	sizeofInt              = 0x4
-	sizeofLong             = 0x8
-	sizeofLongLong         = 0x8
-	O_CLOEXEC              = 0
-	S_IFMT                 = 0xf000
-	S_IFIFO                = 0x1000
-	S_IFCHR                = 0x2000
-	S_IFDIR                = 0x4000
-	S_IFBLK                = 0x6000
-	S_IFREG                = 0x8000
-	S_IFLNK                = 0xa000
-	S_IFSOCK               = 0xc000
-	S_ISUID                = 0x800
-	S_ISGID                = 0x400
-	S_ISVTX                = 0x200
-	S_IRUSR                = 0x100
-	S_IWUSR                = 0x80
-	S_IXUSR                = 0x40
-	SizeofSockaddrInet4    = 0x10
-	SizeofSockaddrInet6    = 0x1c
-	SizeofSockaddrAny      = 0x6c
-	SizeofSockaddrUnix     = 0x6a
-	SizeofSockaddrDatalink = 0x36
-	SizeofLinger           = 0x8
-	SizeofIPMreq           = 0x8
-	SizeofIPv6Mreq         = 0x14
-	SizeofMsghdr           = 0x30
-	SizeofCmsghdr          = 0xc
-	SizeofInet6Pktinfo     = 0x14
-	PTRACE_TRACEME         = 0
-	PTRACE_CONT            = 0x7
-	PTRACE_KILL            = 0x8
-	SizeofIfMsghdr         = 0xa8
-	SizeofIfData           = 0x98
-	SizeofIfaMsghdr        = 0x14
-	SizeofIfmaMsghdr       = 0x10
-	SizeofRtMsghdr         = 0x98
-	SizeofRtMetrics        = 0x70
-	SizeofBpfVersion       = 0x4
-	SizeofBpfStat          = 0x8
-	SizeofBpfZbuf          = 0x18
-	SizeofBpfProgram       = 0x10
-	SizeofBpfInsn          = 0x8
-	SizeofBpfHdr           = 0x20
-	SizeofBpfZbufHeader    = 0x20
+	sizeofPtr      = 0x8
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x8
+	sizeofLongLong = 0x8
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int64
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int64
+	_C_long_long int64
+)
 
 type Timespec struct {
 	Sec  int64
@@ -101,6 +54,27 @@ type Rlimit struct {
 
 type _Gid_t uint32
 
+const (
+	O_CLOEXEC = 0
+)
+
+const (
+	S_IFMT   = 0xf000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+	S_ISUID  = 0x800
+	S_ISGID  = 0x400
+	S_ISVTX  = 0x200
+	S_IRUSR  = 0x100
+	S_IWUSR  = 0x80
+	S_IXUSR  = 0x40
+)
+
 type Stat_t struct {
 	Dev           uint32
 	Ino           uint32
@@ -119,8 +93,6 @@ type Stat_t struct {
 	Gen           uint32
 	Lspare        int32
 	Birthtimespec Timespec
-	Pad_godefs_0  uint8
-	Pad_godefs_1  uint8
 }
 
 type Statfs_t struct {
@@ -141,7 +113,7 @@ type Statfs_t struct {
 	Spare       [10]uint64
 	Namemax     uint32
 	Owner       uint32
-	Fsid        [8]byte /* fsid */
+	Fsid        Fsid
 	Charspare   [80]int8
 	Fstypename  [16]int8
 	Mntfromname [88]int8
@@ -149,13 +121,13 @@ type Statfs_t struct {
 }
 
 type Flock_t struct {
-	Start        int64
-	Len          int64
-	Pid          int32
-	Type         int16
-	Whence       int16
-	Sysid        int32
-	Pad_godefs_0 [4]byte
+	Start     int64
+	Len       int64
+	Pid       int32
+	Type      int16
+	Whence    int16
+	Sysid     int32
+	Pad_cgo_0 [4]byte
 }
 
 type Dirent struct {
@@ -166,6 +138,10 @@ type Dirent struct {
 	Name   [256]int8
 }
 
+type Fsid struct {
+	Val [2]int32
+}
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
@@ -228,21 +204,27 @@ type IPMreq struct {
 	Interface [4]byte /* in_addr */
 }
 
+type IPMreqn struct {
+	Multiaddr [4]byte /* in_addr */
+	Address   [4]byte /* in_addr */
+	Ifindex   int32
+}
+
 type IPv6Mreq struct {
 	Multiaddr [16]byte /* in6_addr */
 	Interface uint32
 }
 
 type Msghdr struct {
-	Name         *byte
-	Namelen      uint32
-	Pad_godefs_0 [4]byte
-	Iov          *Iovec
-	Iovlen       int32
-	Pad_godefs_1 [4]byte
-	Control      *byte
-	Controllen   uint32
-	Flags        int32
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *Iovec
+	Iovlen     int32
+	Pad_cgo_1  [4]byte
+	Control    *byte
+	Controllen uint32
+	Flags      int32
 }
 
 type Cmsghdr struct {
@@ -256,6 +238,27 @@ type Inet6Pktinfo struct {
 	Ifindex uint32
 }
 
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x36
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPMreqn          = 0xc
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x30
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
 type Kevent_t struct {
 	Ident  uint64
 	Filter int16
@@ -269,15 +272,24 @@ type FdSet struct {
 	X__fds_bits [16]uint64
 }
 
+const (
+	SizeofIfMsghdr   = 0xa8
+	SizeofIfData     = 0x98
+	SizeofIfaMsghdr  = 0x14
+	SizeofIfmaMsghdr = 0x10
+	SizeofRtMsghdr   = 0x98
+	SizeofRtMetrics  = 0x70
+)
+
 type IfMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Data         IfData
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Data      IfData
 }
 
 type IfData struct {
@@ -309,40 +321,40 @@ type IfData struct {
 }
 
 type IfaMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Metric       int32
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Metric    int32
 }
 
 type IfmaMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Addrs        int32
-	Flags        int32
-	Index        uint16
-	Pad_godefs_0 [2]byte
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Addrs     int32
+	Flags     int32
+	Index     uint16
+	Pad_cgo_0 [2]byte
 }
 
 type RtMsghdr struct {
-	Msglen       uint16
-	Version      uint8
-	Type         uint8
-	Index        uint16
-	Pad_godefs_0 [2]byte
-	Flags        int32
-	Addrs        int32
-	Pid          int32
-	Seq          int32
-	Errno        int32
-	Fmask        int32
-	Inits        uint64
-	Rmx          RtMetrics
+	Msglen    uint16
+	Version   uint8
+	Type      uint8
+	Index     uint16
+	Pad_cgo_0 [2]byte
+	Flags     int32
+	Addrs     int32
+	Pid       int32
+	Seq       int32
+	Errno     int32
+	Fmask     int32
+	Inits     uint64
+	Rmx       RtMetrics
 }
 
 type RtMetrics struct {
@@ -360,6 +372,16 @@ type RtMetrics struct {
 	Filler   [3]uint64
 }
 
+const (
+	SizeofBpfVersion    = 0x4
+	SizeofBpfStat       = 0x8
+	SizeofBpfZbuf       = 0x18
+	SizeofBpfProgram    = 0x10
+	SizeofBpfInsn       = 0x8
+	SizeofBpfHdr        = 0x20
+	SizeofBpfZbufHeader = 0x20
+)
+
 type BpfVersion struct {
 	Major uint16
 	Minor uint16
@@ -377,9 +399,9 @@ type BpfZbuf struct {
 }
 
 type BpfProgram struct {
-	Len          uint32
-	Pad_godefs_0 [4]byte
-	Insns        *BpfInsn
+	Len       uint32
+	Pad_cgo_0 [4]byte
+	Insns     *BpfInsn
 }
 
 type BpfInsn struct {
@@ -390,11 +412,11 @@ type BpfInsn struct {
 }
 
 type BpfHdr struct {
-	Tstamp       Timeval
-	Caplen       uint32
-	Datalen      uint32
-	Hdrlen       uint16
-	Pad_godefs_0 [6]byte
+	Tstamp    Timeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [6]byte
 }
 
 type BpfZbufHeader struct {
diff --git a/src/pkg/syscall/ztypes_linux_386.go b/src/pkg/syscall/ztypes_linux_386.go
index 0335eb5..fcead2f 100644
--- a/src/pkg/syscall/ztypes_linux_386.go
+++ b/src/pkg/syscall/ztypes_linux_386.go
@@ -1,119 +1,23 @@
-// godefs -gsyscall -f-m32 types_linux.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr               = 0x4
-	sizeofShort             = 0x2
-	sizeofInt               = 0x4
-	sizeofLong              = 0x4
-	sizeofLongLong          = 0x8
-	PathMax                 = 0x1000
-	SizeofSockaddrInet4     = 0x10
-	SizeofSockaddrInet6     = 0x1c
-	SizeofSockaddrAny       = 0x70
-	SizeofSockaddrUnix      = 0x6e
-	SizeofSockaddrLinklayer = 0x14
-	SizeofSockaddrNetlink   = 0xc
-	SizeofLinger            = 0x8
-	SizeofIPMreq            = 0x8
-	SizeofIPv6Mreq          = 0x14
-	SizeofMsghdr            = 0x1c
-	SizeofCmsghdr           = 0xc
-	SizeofInet6Pktinfo      = 0x14
-	SizeofUcred             = 0xc
-	IFA_UNSPEC              = 0
-	IFA_ADDRESS             = 0x1
-	IFA_LOCAL               = 0x2
-	IFA_LABEL               = 0x3
-	IFA_BROADCAST           = 0x4
-	IFA_ANYCAST             = 0x5
-	IFA_CACHEINFO           = 0x6
-	IFA_MULTICAST           = 0x7
-	IFLA_UNSPEC             = 0
-	IFLA_ADDRESS            = 0x1
-	IFLA_BROADCAST          = 0x2
-	IFLA_IFNAME             = 0x3
-	IFLA_MTU                = 0x4
-	IFLA_LINK               = 0x5
-	IFLA_QDISC              = 0x6
-	IFLA_STATS              = 0x7
-	IFLA_COST               = 0x8
-	IFLA_PRIORITY           = 0x9
-	IFLA_MASTER             = 0xa
-	IFLA_WIRELESS           = 0xb
-	IFLA_PROTINFO           = 0xc
-	IFLA_TXQLEN             = 0xd
-	IFLA_MAP                = 0xe
-	IFLA_WEIGHT             = 0xf
-	IFLA_OPERSTATE          = 0x10
-	IFLA_LINKMODE           = 0x11
-	IFLA_LINKINFO           = 0x12
-	IFLA_NET_NS_PID         = 0x13
-	IFLA_IFALIAS            = 0x14
-	IFLA_MAX                = 0x14
-	RT_SCOPE_UNIVERSE       = 0
-	RT_SCOPE_SITE           = 0xc8
-	RT_SCOPE_LINK           = 0xfd
-	RT_SCOPE_HOST           = 0xfe
-	RT_SCOPE_NOWHERE        = 0xff
-	RT_TABLE_UNSPEC         = 0
-	RT_TABLE_COMPAT         = 0xfc
-	RT_TABLE_DEFAULT        = 0xfd
-	RT_TABLE_MAIN           = 0xfe
-	RT_TABLE_LOCAL          = 0xff
-	RT_TABLE_MAX            = 0xffffffff
-	RTA_UNSPEC              = 0
-	RTA_DST                 = 0x1
-	RTA_SRC                 = 0x2
-	RTA_IIF                 = 0x3
-	RTA_OIF                 = 0x4
-	RTA_GATEWAY             = 0x5
-	RTA_PRIORITY            = 0x6
-	RTA_PREFSRC             = 0x7
-	RTA_METRICS             = 0x8
-	RTA_MULTIPATH           = 0x9
-	RTA_FLOW                = 0xb
-	RTA_CACHEINFO           = 0xc
-	RTA_TABLE               = 0xf
-	RTN_UNSPEC              = 0
-	RTN_UNICAST             = 0x1
-	RTN_LOCAL               = 0x2
-	RTN_BROADCAST           = 0x3
-	RTN_ANYCAST             = 0x4
-	RTN_MULTICAST           = 0x5
-	RTN_BLACKHOLE           = 0x6
-	RTN_UNREACHABLE         = 0x7
-	RTN_PROHIBIT            = 0x8
-	RTN_THROW               = 0x9
-	RTN_NAT                 = 0xa
-	RTN_XRESOLVE            = 0xb
-	SizeofNlMsghdr          = 0x10
-	SizeofNlMsgerr          = 0x14
-	SizeofRtGenmsg          = 0x1
-	SizeofNlAttr            = 0x4
-	SizeofRtAttr            = 0x4
-	SizeofIfInfomsg         = 0x10
-	SizeofIfAddrmsg         = 0x8
-	SizeofRtMsg             = 0xc
-	SizeofRtNexthop         = 0x8
-	SizeofSockFilter        = 0x8
-	SizeofSockFprog         = 0x8
-	SizeofInotifyEvent      = 0x10
+	sizeofPtr      = 0x4
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x4
+	sizeofLongLong = 0x8
+	PathMax        = 0x1000
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int32
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int32
+	_C_long_long int64
+)
 
 type Timespec struct {
 	Sec  int32
@@ -126,37 +30,27 @@ type Timeval struct {
 }
 
 type Timex struct {
-	Modes         uint32
-	Offset        int32
-	Freq          int32
-	Maxerror      int32
-	Esterror      int32
-	Status        int32
-	Constant      int32
-	Precision     int32
-	Tolerance     int32
-	Time          Timeval
-	Tick          int32
-	Ppsfreq       int32
-	Jitter        int32
-	Shift         int32
-	Stabil        int32
-	Jitcnt        int32
-	Calcnt        int32
-	Errcnt        int32
-	Stbcnt        int32
-	Tai           int32
-	Pad_godefs_0  int32
-	Pad_godefs_1  int32
-	Pad_godefs_2  int32
-	Pad_godefs_3  int32
-	Pad_godefs_4  int32
-	Pad_godefs_5  int32
-	Pad_godefs_6  int32
-	Pad_godefs_7  int32
-	Pad_godefs_8  int32
-	Pad_godefs_9  int32
-	Pad_godefs_10 int32
+	Modes     uint32
+	Offset    int32
+	Freq      int32
+	Maxerror  int32
+	Esterror  int32
+	Status    int32
+	Constant  int32
+	Precision int32
+	Tolerance int32
+	Time      Timeval
+	Tick      int32
+	Ppsfreq   int32
+	Jitter    int32
+	Shift     int32
+	Stabil    int32
+	Jitcnt    int32
+	Calcnt    int32
+	Errcnt    int32
+	Stbcnt    int32
+	Tai       int32
+	Pad_cgo_0 [44]byte
 }
 
 type Time_t int32
@@ -200,24 +94,24 @@ type Rlimit struct {
 type _Gid_t uint32
 
 type Stat_t struct {
-	Dev          uint64
-	X__pad1      uint16
-	Pad_godefs_0 [2]byte
-	X__st_ino    uint32
-	Mode         uint32
-	Nlink        uint32
-	Uid          uint32
-	Gid          uint32
-	Rdev         uint64
-	X__pad2      uint16
-	Pad_godefs_1 [2]byte
-	Size         int64
-	Blksize      int32
-	Blocks       int64
-	Atim         Timespec
-	Mtim         Timespec
-	Ctim         Timespec
-	Ino          uint64
+	Dev       uint64
+	X__pad1   uint16
+	Pad_cgo_0 [2]byte
+	X__st_ino uint32
+	Mode      uint32
+	Nlink     uint32
+	Uid       uint32
+	Gid       uint32
+	Rdev      uint64
+	X__pad2   uint16
+	Pad_cgo_1 [2]byte
+	Size      int64
+	Blksize   int32
+	Blocks    int64
+	Atim      Timespec
+	Mtim      Timespec
+	Ctim      Timespec
+	Ino       uint64
 }
 
 type Statfs_t struct {
@@ -228,19 +122,24 @@ type Statfs_t struct {
 	Bavail  uint64
 	Files   uint64
 	Ffree   uint64
-	Fsid    [8]byte /* __fsid_t */
+	Fsid    Fsid
 	Namelen int32
 	Frsize  int32
-	Spare   [5]int32
+	Flags   int32
+	Spare   [4]int32
 }
 
 type Dirent struct {
-	Ino          uint64
-	Off          int64
-	Reclen       uint16
-	Type         uint8
-	Name         [256]int8
-	Pad_godefs_0 [1]byte
+	Ino       uint64
+	Off       int64
+	Reclen    uint16
+	Type      uint8
+	Name      [256]int8
+	Pad_cgo_0 [1]byte
+}
+
+type Fsid struct {
+	X__val [2]int32
 }
 
 type RawSockaddrInet4 struct {
@@ -307,6 +206,12 @@ type IPMreq struct {
 	Interface [4]byte /* in_addr */
 }
 
+type IPMreqn struct {
+	Multiaddr [4]byte /* in_addr */
+	Address   [4]byte /* in_addr */
+	Ifindex   int32
+}
+
 type IPv6Mreq struct {
 	Multiaddr [16]byte /* in6_addr */
 	Interface uint32
@@ -323,9 +228,16 @@ type Msghdr struct {
 }
 
 type Cmsghdr struct {
-	Len   uint32
-	Level int32
-	Type  int32
+	Len          uint32
+	Level        int32
+	Type         int32
+	X__cmsg_data [0]byte
+}
+
+type Inet4Pktinfo struct {
+	Ifindex  int32
+	Spec_dst [4]byte /* in_addr */
+	Addr     [4]byte /* in_addr */
 }
 
 type Inet6Pktinfo struct {
@@ -339,6 +251,102 @@ type Ucred struct {
 	Gid uint32
 }
 
+const (
+	SizeofSockaddrInet4     = 0x10
+	SizeofSockaddrInet6     = 0x1c
+	SizeofSockaddrAny       = 0x70
+	SizeofSockaddrUnix      = 0x6e
+	SizeofSockaddrLinklayer = 0x14
+	SizeofSockaddrNetlink   = 0xc
+	SizeofLinger            = 0x8
+	SizeofIPMreq            = 0x8
+	SizeofIPMreqn           = 0xc
+	SizeofIPv6Mreq          = 0x14
+	SizeofMsghdr            = 0x1c
+	SizeofCmsghdr           = 0xc
+	SizeofInet4Pktinfo      = 0xc
+	SizeofInet6Pktinfo      = 0x14
+	SizeofUcred             = 0xc
+)
+
+const (
+	IFA_UNSPEC        = 0x0
+	IFA_ADDRESS       = 0x1
+	IFA_LOCAL         = 0x2
+	IFA_LABEL         = 0x3
+	IFA_BROADCAST     = 0x4
+	IFA_ANYCAST       = 0x5
+	IFA_CACHEINFO     = 0x6
+	IFA_MULTICAST     = 0x7
+	IFLA_UNSPEC       = 0x0
+	IFLA_ADDRESS      = 0x1
+	IFLA_BROADCAST    = 0x2
+	IFLA_IFNAME       = 0x3
+	IFLA_MTU          = 0x4
+	IFLA_LINK         = 0x5
+	IFLA_QDISC        = 0x6
+	IFLA_STATS        = 0x7
+	IFLA_COST         = 0x8
+	IFLA_PRIORITY     = 0x9
+	IFLA_MASTER       = 0xa
+	IFLA_WIRELESS     = 0xb
+	IFLA_PROTINFO     = 0xc
+	IFLA_TXQLEN       = 0xd
+	IFLA_MAP          = 0xe
+	IFLA_WEIGHT       = 0xf
+	IFLA_OPERSTATE    = 0x10
+	IFLA_LINKMODE     = 0x11
+	IFLA_LINKINFO     = 0x12
+	IFLA_NET_NS_PID   = 0x13
+	IFLA_IFALIAS      = 0x14
+	IFLA_MAX          = 0x1c
+	RT_SCOPE_UNIVERSE = 0x0
+	RT_SCOPE_SITE     = 0xc8
+	RT_SCOPE_LINK     = 0xfd
+	RT_SCOPE_HOST     = 0xfe
+	RT_SCOPE_NOWHERE  = 0xff
+	RT_TABLE_UNSPEC   = 0x0
+	RT_TABLE_COMPAT   = 0xfc
+	RT_TABLE_DEFAULT  = 0xfd
+	RT_TABLE_MAIN     = 0xfe
+	RT_TABLE_LOCAL    = 0xff
+	RT_TABLE_MAX      = 0xffffffff
+	RTA_UNSPEC        = 0x0
+	RTA_DST           = 0x1
+	RTA_SRC           = 0x2
+	RTA_IIF           = 0x3
+	RTA_OIF           = 0x4
+	RTA_GATEWAY       = 0x5
+	RTA_PRIORITY      = 0x6
+	RTA_PREFSRC       = 0x7
+	RTA_METRICS       = 0x8
+	RTA_MULTIPATH     = 0x9
+	RTA_FLOW          = 0xb
+	RTA_CACHEINFO     = 0xc
+	RTA_TABLE         = 0xf
+	RTN_UNSPEC        = 0x0
+	RTN_UNICAST       = 0x1
+	RTN_LOCAL         = 0x2
+	RTN_BROADCAST     = 0x3
+	RTN_ANYCAST       = 0x4
+	RTN_MULTICAST     = 0x5
+	RTN_BLACKHOLE     = 0x6
+	RTN_UNREACHABLE   = 0x7
+	RTN_PROHIBIT      = 0x8
+	RTN_THROW         = 0x9
+	RTN_NAT           = 0xa
+	RTN_XRESOLVE      = 0xb
+	SizeofNlMsghdr    = 0x10
+	SizeofNlMsgerr    = 0x14
+	SizeofRtGenmsg    = 0x1
+	SizeofNlAttr      = 0x4
+	SizeofRtAttr      = 0x4
+	SizeofIfInfomsg   = 0x10
+	SizeofIfAddrmsg   = 0x8
+	SizeofRtMsg       = 0xc
+	SizeofRtNexthop   = 0x8
+)
+
 type NlMsghdr struct {
 	Len   uint32
 	Type  uint16
@@ -402,6 +410,11 @@ type RtNexthop struct {
 	Ifindex int32
 }
 
+const (
+	SizeofSockFilter = 0x8
+	SizeofSockFprog  = 0x8
+)
+
 type SockFilter struct {
 	Code uint16
 	Jt   uint8
@@ -410,9 +423,9 @@ type SockFilter struct {
 }
 
 type SockFprog struct {
-	Len          uint16
-	Pad_godefs_0 [2]byte
-	Filter       *SockFilter
+	Len       uint16
+	Pad_cgo_0 [2]byte
+	Filter    *SockFilter
 }
 
 type InotifyEvent struct {
@@ -420,8 +433,11 @@ type InotifyEvent struct {
 	Mask   uint32
 	Cookie uint32
 	Len    uint32
+	Name   [0]byte
 }
 
+const SizeofInotifyEvent = 0x10
+
 type PtraceRegs struct {
 	Ebx      int32
 	Ecx      int32
@@ -484,3 +500,117 @@ type EpollEvent struct {
 	Fd     int32
 	Pad    int32
 }
+
+type Termios struct {
+	Iflag     uint32
+	Oflag     uint32
+	Cflag     uint32
+	Lflag     uint32
+	Line      uint8
+	Cc        [32]uint8
+	Pad_cgo_0 [3]byte
+	Ispeed    uint32
+	Ospeed    uint32
+}
+
+const (
+	VINTR    = 0x0
+	VQUIT    = 0x1
+	VERASE   = 0x2
+	VKILL    = 0x3
+	VEOF     = 0x4
+	VTIME    = 0x5
+	VMIN     = 0x6
+	VSWTC    = 0x7
+	VSTART   = 0x8
+	VSTOP    = 0x9
+	VSUSP    = 0xa
+	VEOL     = 0xb
+	VREPRINT = 0xc
+	VDISCARD = 0xd
+	VWERASE  = 0xe
+	VLNEXT   = 0xf
+	VEOL2    = 0x10
+	IGNBRK   = 0x1
+	BRKINT   = 0x2
+	IGNPAR   = 0x4
+	PARMRK   = 0x8
+	INPCK    = 0x10
+	ISTRIP   = 0x20
+	INLCR    = 0x40
+	IGNCR    = 0x80
+	ICRNL    = 0x100
+	IUCLC    = 0x200
+	IXON     = 0x400
+	IXANY    = 0x800
+	IXOFF    = 0x1000
+	IMAXBEL  = 0x2000
+	IUTF8    = 0x4000
+	OPOST    = 0x1
+	OLCUC    = 0x2
+	ONLCR    = 0x4
+	OCRNL    = 0x8
+	ONOCR    = 0x10
+	ONLRET   = 0x20
+	OFILL    = 0x40
+	OFDEL    = 0x80
+	B0       = 0x0
+	B50      = 0x1
+	B75      = 0x2
+	B110     = 0x3
+	B134     = 0x4
+	B150     = 0x5
+	B200     = 0x6
+	B300     = 0x7
+	B600     = 0x8
+	B1200    = 0x9
+	B1800    = 0xa
+	B2400    = 0xb
+	B4800    = 0xc
+	B9600    = 0xd
+	B19200   = 0xe
+	B38400   = 0xf
+	CSIZE    = 0x30
+	CS5      = 0x0
+	CS6      = 0x10
+	CS7      = 0x20
+	CS8      = 0x30
+	CSTOPB   = 0x40
+	CREAD    = 0x80
+	PARENB   = 0x100
+	PARODD   = 0x200
+	HUPCL    = 0x400
+	CLOCAL   = 0x800
+	B57600   = 0x1001
+	B115200  = 0x1002
+	B230400  = 0x1003
+	B460800  = 0x1004
+	B500000  = 0x1005
+	B576000  = 0x1006
+	B921600  = 0x1007
+	B1000000 = 0x1008
+	B1152000 = 0x1009
+	B1500000 = 0x100a
+	B2000000 = 0x100b
+	B2500000 = 0x100c
+	B3000000 = 0x100d
+	B3500000 = 0x100e
+	B4000000 = 0x100f
+	ISIG     = 0x1
+	ICANON   = 0x2
+	XCASE    = 0x4
+	ECHO     = 0x8
+	ECHOE    = 0x10
+	ECHOK    = 0x20
+	ECHONL   = 0x40
+	NOFLSH   = 0x80
+	TOSTOP   = 0x100
+	ECHOCTL  = 0x200
+	ECHOPRT  = 0x400
+	ECHOKE   = 0x800
+	FLUSHO   = 0x1000
+	PENDIN   = 0x4000
+	IEXTEN   = 0x8000
+	TCGETS   = 0x5401
+	TCSETS   = 0x5402
+)
diff --git a/src/pkg/syscall/ztypes_linux_amd64.go b/src/pkg/syscall/ztypes_linux_amd64.go
index c97b7f6..d5583a7 100644
--- a/src/pkg/syscall/ztypes_linux_amd64.go
+++ b/src/pkg/syscall/ztypes_linux_amd64.go
@@ -1,119 +1,23 @@
-// godefs -gsyscall -f-m64 types_linux.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr               = 0x8
-	sizeofShort             = 0x2
-	sizeofInt               = 0x4
-	sizeofLong              = 0x8
-	sizeofLongLong          = 0x8
-	PathMax                 = 0x1000
-	SizeofSockaddrInet4     = 0x10
-	SizeofSockaddrInet6     = 0x1c
-	SizeofSockaddrAny       = 0x70
-	SizeofSockaddrUnix      = 0x6e
-	SizeofSockaddrLinklayer = 0x14
-	SizeofSockaddrNetlink   = 0xc
-	SizeofLinger            = 0x8
-	SizeofIPMreq            = 0x8
-	SizeofIPv6Mreq          = 0x14
-	SizeofMsghdr            = 0x38
-	SizeofCmsghdr           = 0x10
-	SizeofInet6Pktinfo      = 0x14
-	SizeofUcred             = 0xc
-	IFA_UNSPEC              = 0
-	IFA_ADDRESS             = 0x1
-	IFA_LOCAL               = 0x2
-	IFA_LABEL               = 0x3
-	IFA_BROADCAST           = 0x4
-	IFA_ANYCAST             = 0x5
-	IFA_CACHEINFO           = 0x6
-	IFA_MULTICAST           = 0x7
-	IFLA_UNSPEC             = 0
-	IFLA_ADDRESS            = 0x1
-	IFLA_BROADCAST          = 0x2
-	IFLA_IFNAME             = 0x3
-	IFLA_MTU                = 0x4
-	IFLA_LINK               = 0x5
-	IFLA_QDISC              = 0x6
-	IFLA_STATS              = 0x7
-	IFLA_COST               = 0x8
-	IFLA_PRIORITY           = 0x9
-	IFLA_MASTER             = 0xa
-	IFLA_WIRELESS           = 0xb
-	IFLA_PROTINFO           = 0xc
-	IFLA_TXQLEN             = 0xd
-	IFLA_MAP                = 0xe
-	IFLA_WEIGHT             = 0xf
-	IFLA_OPERSTATE          = 0x10
-	IFLA_LINKMODE           = 0x11
-	IFLA_LINKINFO           = 0x12
-	IFLA_NET_NS_PID         = 0x13
-	IFLA_IFALIAS            = 0x14
-	IFLA_MAX                = 0x14
-	RT_SCOPE_UNIVERSE       = 0
-	RT_SCOPE_SITE           = 0xc8
-	RT_SCOPE_LINK           = 0xfd
-	RT_SCOPE_HOST           = 0xfe
-	RT_SCOPE_NOWHERE        = 0xff
-	RT_TABLE_UNSPEC         = 0
-	RT_TABLE_COMPAT         = 0xfc
-	RT_TABLE_DEFAULT        = 0xfd
-	RT_TABLE_MAIN           = 0xfe
-	RT_TABLE_LOCAL          = 0xff
-	RT_TABLE_MAX            = 0xffffffff
-	RTA_UNSPEC              = 0
-	RTA_DST                 = 0x1
-	RTA_SRC                 = 0x2
-	RTA_IIF                 = 0x3
-	RTA_OIF                 = 0x4
-	RTA_GATEWAY             = 0x5
-	RTA_PRIORITY            = 0x6
-	RTA_PREFSRC             = 0x7
-	RTA_METRICS             = 0x8
-	RTA_MULTIPATH           = 0x9
-	RTA_FLOW                = 0xb
-	RTA_CACHEINFO           = 0xc
-	RTA_TABLE               = 0xf
-	RTN_UNSPEC              = 0
-	RTN_UNICAST             = 0x1
-	RTN_LOCAL               = 0x2
-	RTN_BROADCAST           = 0x3
-	RTN_ANYCAST             = 0x4
-	RTN_MULTICAST           = 0x5
-	RTN_BLACKHOLE           = 0x6
-	RTN_UNREACHABLE         = 0x7
-	RTN_PROHIBIT            = 0x8
-	RTN_THROW               = 0x9
-	RTN_NAT                 = 0xa
-	RTN_XRESOLVE            = 0xb
-	SizeofNlMsghdr          = 0x10
-	SizeofNlMsgerr          = 0x14
-	SizeofRtGenmsg          = 0x1
-	SizeofNlAttr            = 0x4
-	SizeofRtAttr            = 0x4
-	SizeofIfInfomsg         = 0x10
-	SizeofIfAddrmsg         = 0x8
-	SizeofRtMsg             = 0xc
-	SizeofRtNexthop         = 0x8
-	SizeofSockFilter        = 0x8
-	SizeofSockFprog         = 0x10
-	SizeofInotifyEvent      = 0x10
+	sizeofPtr      = 0x8
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x8
+	sizeofLongLong = 0x8
+	PathMax        = 0x1000
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int64
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int64
+	_C_long_long int64
+)
 
 type Timespec struct {
 	Sec  int64
@@ -126,40 +30,30 @@ type Timeval struct {
 }
 
 type Timex struct {
-	Modes         uint32
-	Pad_godefs_0  [4]byte
-	Offset        int64
-	Freq          int64
-	Maxerror      int64
-	Esterror      int64
-	Status        int32
-	Pad_godefs_1  [4]byte
-	Constant      int64
-	Precision     int64
-	Tolerance     int64
-	Time          Timeval
-	Tick          int64
-	Ppsfreq       int64
-	Jitter        int64
-	Shift         int32
-	Pad_godefs_2  [4]byte
-	Stabil        int64
-	Jitcnt        int64
-	Calcnt        int64
-	Errcnt        int64
-	Stbcnt        int64
-	Tai           int32
-	Pad_godefs_3  int32
-	Pad_godefs_4  int32
-	Pad_godefs_5  int32
-	Pad_godefs_6  int32
-	Pad_godefs_7  int32
-	Pad_godefs_8  int32
-	Pad_godefs_9  int32
-	Pad_godefs_10 int32
-	Pad_godefs_11 int32
-	Pad_godefs_12 int32
-	Pad_godefs_13 int32
+	Modes     uint32
+	Pad_cgo_0 [4]byte
+	Offset    int64
+	Freq      int64
+	Maxerror  int64
+	Esterror  int64
+	Status    int32
+	Pad_cgo_1 [4]byte
+	Constant  int64
+	Precision int64
+	Tolerance int64
+	Time      Timeval
+	Tick      int64
+	Ppsfreq   int64
+	Jitter    int64
+	Shift     int32
+	Pad_cgo_2 [4]byte
+	Stabil    int64
+	Jitcnt    int64
+	Calcnt    int64
+	Errcnt    int64
+	Stbcnt    int64
+	Tai       int32
+	Pad_cgo_3 [44]byte
 }
 
 type Time_t int64
@@ -228,19 +122,24 @@ type Statfs_t struct {
 	Bavail  uint64
 	Files   uint64
 	Ffree   uint64
-	Fsid    [8]byte /* __fsid_t */
+	Fsid    Fsid
 	Namelen int64
 	Frsize  int64
-	Spare   [5]int64
+	Flags   int64
+	Spare   [4]int64
 }
 
 type Dirent struct {
-	Ino          uint64
-	Off          int64
-	Reclen       uint16
-	Type         uint8
-	Name         [256]int8
-	Pad_godefs_0 [5]byte
+	Ino       uint64
+	Off       int64
+	Reclen    uint16
+	Type      uint8
+	Name      [256]int8
+	Pad_cgo_0 [5]byte
+}
+
+type Fsid struct {
+	X__val [2]int32
 }
 
 type RawSockaddrInet4 struct {
@@ -307,27 +206,40 @@ type IPMreq struct {
 	Interface [4]byte /* in_addr */
 }
 
+type IPMreqn struct {
+	Multiaddr [4]byte /* in_addr */
+	Address   [4]byte /* in_addr */
+	Ifindex   int32
+}
+
 type IPv6Mreq struct {
 	Multiaddr [16]byte /* in6_addr */
 	Interface uint32
 }
 
 type Msghdr struct {
-	Name         *byte
-	Namelen      uint32
-	Pad_godefs_0 [4]byte
-	Iov          *Iovec
-	Iovlen       uint64
-	Control      *byte
-	Controllen   uint64
-	Flags        int32
-	Pad_godefs_1 [4]byte
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *Iovec
+	Iovlen     uint64
+	Control    *byte
+	Controllen uint64
+	Flags      int32
+	Pad_cgo_1  [4]byte
 }
 
 type Cmsghdr struct {
-	Len   uint64
-	Level int32
-	Type  int32
+	Len          uint64
+	Level        int32
+	Type         int32
+	X__cmsg_data [0]byte
+}
+
+type Inet4Pktinfo struct {
+	Ifindex  int32
+	Spec_dst [4]byte /* in_addr */
+	Addr     [4]byte /* in_addr */
 }
 
 type Inet6Pktinfo struct {
@@ -341,6 +253,102 @@ type Ucred struct {
 	Gid uint32
 }
 
+const (
+	SizeofSockaddrInet4     = 0x10
+	SizeofSockaddrInet6     = 0x1c
+	SizeofSockaddrAny       = 0x70
+	SizeofSockaddrUnix      = 0x6e
+	SizeofSockaddrLinklayer = 0x14
+	SizeofSockaddrNetlink   = 0xc
+	SizeofLinger            = 0x8
+	SizeofIPMreq            = 0x8
+	SizeofIPMreqn           = 0xc
+	SizeofIPv6Mreq          = 0x14
+	SizeofMsghdr            = 0x38
+	SizeofCmsghdr           = 0x10
+	SizeofInet4Pktinfo      = 0xc
+	SizeofInet6Pktinfo      = 0x14
+	SizeofUcred             = 0xc
+)
+
+const (
+	IFA_UNSPEC        = 0x0
+	IFA_ADDRESS       = 0x1
+	IFA_LOCAL         = 0x2
+	IFA_LABEL         = 0x3
+	IFA_BROADCAST     = 0x4
+	IFA_ANYCAST       = 0x5
+	IFA_CACHEINFO     = 0x6
+	IFA_MULTICAST     = 0x7
+	IFLA_UNSPEC       = 0x0
+	IFLA_ADDRESS      = 0x1
+	IFLA_BROADCAST    = 0x2
+	IFLA_IFNAME       = 0x3
+	IFLA_MTU          = 0x4
+	IFLA_LINK         = 0x5
+	IFLA_QDISC        = 0x6
+	IFLA_STATS        = 0x7
+	IFLA_COST         = 0x8
+	IFLA_PRIORITY     = 0x9
+	IFLA_MASTER       = 0xa
+	IFLA_WIRELESS     = 0xb
+	IFLA_PROTINFO     = 0xc
+	IFLA_TXQLEN       = 0xd
+	IFLA_MAP          = 0xe
+	IFLA_WEIGHT       = 0xf
+	IFLA_OPERSTATE    = 0x10
+	IFLA_LINKMODE     = 0x11
+	IFLA_LINKINFO     = 0x12
+	IFLA_NET_NS_PID   = 0x13
+	IFLA_IFALIAS      = 0x14
+	IFLA_MAX          = 0x1c
+	RT_SCOPE_UNIVERSE = 0x0
+	RT_SCOPE_SITE     = 0xc8
+	RT_SCOPE_LINK     = 0xfd
+	RT_SCOPE_HOST     = 0xfe
+	RT_SCOPE_NOWHERE  = 0xff
+	RT_TABLE_UNSPEC   = 0x0
+	RT_TABLE_COMPAT   = 0xfc
+	RT_TABLE_DEFAULT  = 0xfd
+	RT_TABLE_MAIN     = 0xfe
+	RT_TABLE_LOCAL    = 0xff
+	RT_TABLE_MAX      = 0xffffffff
+	RTA_UNSPEC        = 0x0
+	RTA_DST           = 0x1
+	RTA_SRC           = 0x2
+	RTA_IIF           = 0x3
+	RTA_OIF           = 0x4
+	RTA_GATEWAY       = 0x5
+	RTA_PRIORITY      = 0x6
+	RTA_PREFSRC       = 0x7
+	RTA_METRICS       = 0x8
+	RTA_MULTIPATH     = 0x9
+	RTA_FLOW          = 0xb
+	RTA_CACHEINFO     = 0xc
+	RTA_TABLE         = 0xf
+	RTN_UNSPEC        = 0x0
+	RTN_UNICAST       = 0x1
+	RTN_LOCAL         = 0x2
+	RTN_BROADCAST     = 0x3
+	RTN_ANYCAST       = 0x4
+	RTN_MULTICAST     = 0x5
+	RTN_BLACKHOLE     = 0x6
+	RTN_UNREACHABLE   = 0x7
+	RTN_PROHIBIT      = 0x8
+	RTN_THROW         = 0x9
+	RTN_NAT           = 0xa
+	RTN_XRESOLVE      = 0xb
+	SizeofNlMsghdr    = 0x10
+	SizeofNlMsgerr    = 0x14
+	SizeofRtGenmsg    = 0x1
+	SizeofNlAttr      = 0x4
+	SizeofRtAttr      = 0x4
+	SizeofIfInfomsg   = 0x10
+	SizeofIfAddrmsg   = 0x8
+	SizeofRtMsg       = 0xc
+	SizeofRtNexthop   = 0x8
+)
+
 type NlMsghdr struct {
 	Len   uint32
 	Type  uint16
@@ -404,6 +412,11 @@ type RtNexthop struct {
 	Ifindex int32
 }
 
+const (
+	SizeofSockFilter = 0x8
+	SizeofSockFprog  = 0x10
+)
+
 type SockFilter struct {
 	Code uint16
 	Jt   uint8
@@ -412,9 +425,9 @@ type SockFilter struct {
 }
 
 type SockFprog struct {
-	Len          uint16
-	Pad_godefs_0 [6]byte
-	Filter       *SockFilter
+	Len       uint16
+	Pad_cgo_0 [6]byte
+	Filter    *SockFilter
 }
 
 type InotifyEvent struct {
@@ -422,8 +435,11 @@ type InotifyEvent struct {
 	Mask   uint32
 	Cookie uint32
 	Len    uint32
+	Name   [0]byte
 }
 
+const SizeofInotifyEvent = 0x10
+
 type PtraceRegs struct {
 	R15      uint64
 	R14      uint64
@@ -459,22 +475,22 @@ type FdSet struct {
 }
 
 type Sysinfo_t struct {
-	Uptime       int64
-	Loads        [3]uint64
-	Totalram     uint64
-	Freeram      uint64
-	Sharedram    uint64
-	Bufferram    uint64
-	Totalswap    uint64
-	Freeswap     uint64
-	Procs        uint16
-	Pad          uint16
-	Pad_godefs_0 [4]byte
-	Totalhigh    uint64
-	Freehigh     uint64
-	Unit         uint32
-	X_f          [0]int8
-	Pad_godefs_1 [4]byte
+	Uptime    int64
+	Loads     [3]uint64
+	Totalram  uint64
+	Freeram   uint64
+	Sharedram uint64
+	Bufferram uint64
+	Totalswap uint64
+	Freeswap  uint64
+	Procs     uint16
+	Pad       uint16
+	Pad_cgo_0 [4]byte
+	Totalhigh uint64
+	Freehigh  uint64
+	Unit      uint32
+	X_f       [0]byte
+	Pad_cgo_1 [4]byte
 }
 
 type Utsname struct {
@@ -487,12 +503,12 @@ type Utsname struct {
 }
 
 type Ustat_t struct {
-	Tfree        int32
-	Pad_godefs_0 [4]byte
-	Tinode       uint64
-	Fname        [6]int8
-	Fpack        [6]int8
-	Pad_godefs_1 [4]byte
+	Tfree     int32
+	Pad_cgo_0 [4]byte
+	Tinode    uint64
+	Fname     [6]int8
+	Fpack     [6]int8
+	Pad_cgo_1 [4]byte
 }
 
 type EpollEvent struct {
@@ -500,3 +516,117 @@ type EpollEvent struct {
 	Fd     int32
 	Pad    int32
 }
+
+type Termios struct {
+	Iflag     uint32
+	Oflag     uint32
+	Cflag     uint32
+	Lflag     uint32
+	Line      uint8
+	Cc        [32]uint8
+	Pad_cgo_0 [3]byte
+	Ispeed    uint32
+	Ospeed    uint32
+}
+
+const (
+	VINTR    = 0x0
+	VQUIT    = 0x1
+	VERASE   = 0x2
+	VKILL    = 0x3
+	VEOF     = 0x4
+	VTIME    = 0x5
+	VMIN     = 0x6
+	VSWTC    = 0x7
+	VSTART   = 0x8
+	VSTOP    = 0x9
+	VSUSP    = 0xa
+	VEOL     = 0xb
+	VREPRINT = 0xc
+	VDISCARD = 0xd
+	VWERASE  = 0xe
+	VLNEXT   = 0xf
+	VEOL2    = 0x10
+	IGNBRK   = 0x1
+	BRKINT   = 0x2
+	IGNPAR   = 0x4
+	PARMRK   = 0x8
+	INPCK    = 0x10
+	ISTRIP   = 0x20
+	INLCR    = 0x40
+	IGNCR    = 0x80
+	ICRNL    = 0x100
+	IUCLC    = 0x200
+	IXON     = 0x400
+	IXANY    = 0x800
+	IXOFF    = 0x1000
+	IMAXBEL  = 0x2000
+	IUTF8    = 0x4000
+	OPOST    = 0x1
+	OLCUC    = 0x2
+	ONLCR    = 0x4
+	OCRNL    = 0x8
+	ONOCR    = 0x10
+	ONLRET   = 0x20
+	OFILL    = 0x40
+	OFDEL    = 0x80
+	B0       = 0x0
+	B50      = 0x1
+	B75      = 0x2
+	B110     = 0x3
+	B134     = 0x4
+	B150     = 0x5
+	B200     = 0x6
+	B300     = 0x7
+	B600     = 0x8
+	B1200    = 0x9
+	B1800    = 0xa
+	B2400    = 0xb
+	B4800    = 0xc
+	B9600    = 0xd
+	B19200   = 0xe
+	B38400   = 0xf
+	CSIZE    = 0x30
+	CS5      = 0x0
+	CS6      = 0x10
+	CS7      = 0x20
+	CS8      = 0x30
+	CSTOPB   = 0x40
+	CREAD    = 0x80
+	PARENB   = 0x100
+	PARODD   = 0x200
+	HUPCL    = 0x400
+	CLOCAL   = 0x800
+	B57600   = 0x1001
+	B115200  = 0x1002
+	B230400  = 0x1003
+	B460800  = 0x1004
+	B500000  = 0x1005
+	B576000  = 0x1006
+	B921600  = 0x1007
+	B1000000 = 0x1008
+	B1152000 = 0x1009
+	B1500000 = 0x100a
+	B2000000 = 0x100b
+	B2500000 = 0x100c
+	B3000000 = 0x100d
+	B3500000 = 0x100e
+	B4000000 = 0x100f
+	ISIG     = 0x1
+	ICANON   = 0x2
+	XCASE    = 0x4
+	ECHO     = 0x8
+	ECHOE    = 0x10
+	ECHOK    = 0x20
+	ECHONL   = 0x40
+	NOFLSH   = 0x80
+	TOSTOP   = 0x100
+	ECHOCTL  = 0x200
+	ECHOPRT  = 0x400
+	ECHOKE   = 0x800
+	FLUSHO   = 0x1000
+	PENDIN   = 0x4000
+	IEXTEN   = 0x8000
+	TCGETS   = 0x5401
+	TCSETS   = 0x5402
+)
diff --git a/src/pkg/syscall/ztypes_linux_arm.go b/src/pkg/syscall/ztypes_linux_arm.go
index 3d4aded..c0534fd 100644
--- a/src/pkg/syscall/ztypes_linux_arm.go
+++ b/src/pkg/syscall/ztypes_linux_arm.go
@@ -1,124 +1,23 @@
-// godefs -gsyscall types_linux.c
-
-// MACHINE GENERATED - DO NOT EDIT.
-
-// Manual corrections: TODO(rsc): need to fix godefs
-//	remove duplicate PtraceRegs type
-//	change RawSockaddrUnix field to Path [108]int8 (was uint8)
-//	add padding to EpollEvent
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr               = 0x4
-	sizeofShort             = 0x2
-	sizeofInt               = 0x4
-	sizeofLong              = 0x4
-	sizeofLongLong          = 0x8
-	PathMax                 = 0x1000
-	SizeofSockaddrInet4     = 0x10
-	SizeofSockaddrInet6     = 0x1c
-	SizeofSockaddrAny       = 0x70
-	SizeofSockaddrUnix      = 0x6e
-	SizeofSockaddrLinklayer = 0x14
-	SizeofSockaddrNetlink   = 0xc
-	SizeofLinger            = 0x8
-	SizeofIPMreq            = 0x8
-	SizeofIPv6Mreq          = 0x14
-	SizeofMsghdr            = 0x1c
-	SizeofCmsghdr           = 0xc
-	SizeofInet6Pktinfo      = 0x14
-	SizeofUcred             = 0xc
-	IFA_UNSPEC              = 0
-	IFA_ADDRESS             = 0x1
-	IFA_LOCAL               = 0x2
-	IFA_LABEL               = 0x3
-	IFA_BROADCAST           = 0x4
-	IFA_ANYCAST             = 0x5
-	IFA_CACHEINFO           = 0x6
-	IFA_MULTICAST           = 0x7
-	IFLA_UNSPEC             = 0
-	IFLA_ADDRESS            = 0x1
-	IFLA_BROADCAST          = 0x2
-	IFLA_IFNAME             = 0x3
-	IFLA_MTU                = 0x4
-	IFLA_LINK               = 0x5
-	IFLA_QDISC              = 0x6
-	IFLA_STATS              = 0x7
-	IFLA_COST               = 0x8
-	IFLA_PRIORITY           = 0x9
-	IFLA_MASTER             = 0xa
-	IFLA_WIRELESS           = 0xb
-	IFLA_PROTINFO           = 0xc
-	IFLA_TXQLEN             = 0xd
-	IFLA_MAP                = 0xe
-	IFLA_WEIGHT             = 0xf
-	IFLA_OPERSTATE          = 0x10
-	IFLA_LINKMODE           = 0x11
-	IFLA_LINKINFO           = 0x12
-	IFLA_NET_NS_PID         = 0x13
-	IFLA_IFALIAS            = 0x14
-	IFLA_MAX                = 0x14
-	RT_SCOPE_UNIVERSE       = 0
-	RT_SCOPE_SITE           = 0xc8
-	RT_SCOPE_LINK           = 0xfd
-	RT_SCOPE_HOST           = 0xfe
-	RT_SCOPE_NOWHERE        = 0xff
-	RT_TABLE_UNSPEC         = 0
-	RT_TABLE_COMPAT         = 0xfc
-	RT_TABLE_DEFAULT        = 0xfd
-	RT_TABLE_MAIN           = 0xfe
-	RT_TABLE_LOCAL          = 0xff
-	RT_TABLE_MAX            = 0xffffffff
-	RTA_UNSPEC              = 0
-	RTA_DST                 = 0x1
-	RTA_SRC                 = 0x2
-	RTA_IIF                 = 0x3
-	RTA_OIF                 = 0x4
-	RTA_GATEWAY             = 0x5
-	RTA_PRIORITY            = 0x6
-	RTA_PREFSRC             = 0x7
-	RTA_METRICS             = 0x8
-	RTA_MULTIPATH           = 0x9
-	RTA_FLOW                = 0xb
-	RTA_CACHEINFO           = 0xc
-	RTA_TABLE               = 0xf
-	RTN_UNSPEC              = 0
-	RTN_UNICAST             = 0x1
-	RTN_LOCAL               = 0x2
-	RTN_BROADCAST           = 0x3
-	RTN_ANYCAST             = 0x4
-	RTN_MULTICAST           = 0x5
-	RTN_BLACKHOLE           = 0x6
-	RTN_UNREACHABLE         = 0x7
-	RTN_PROHIBIT            = 0x8
-	RTN_THROW               = 0x9
-	RTN_NAT                 = 0xa
-	RTN_XRESOLVE            = 0xb
-	SizeofNlMsghdr          = 0x10
-	SizeofNlMsgerr          = 0x14
-	SizeofRtGenmsg          = 0x1
-	SizeofNlAttr            = 0x4
-	SizeofRtAttr            = 0x4
-	SizeofIfInfomsg         = 0x10
-	SizeofIfAddrmsg         = 0x8
-	SizeofRtMsg             = 0xc
-	SizeofRtNexthop         = 0x8
-	SizeofSockFilter        = 0x8
-	SizeofSockFprog         = 0x8
-	SizeofInotifyEvent      = 0x10
+	sizeofPtr      = 0x4
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x4
+	sizeofLongLong = 0x8
+	PathMax        = 0x1000
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int32
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int32
+	_C_long_long int64
+)
 
 type Timespec struct {
 	Sec  int32
@@ -131,37 +30,27 @@ type Timeval struct {
 }
 
 type Timex struct {
-	Modes         uint32
-	Offset        int32
-	Freq          int32
-	Maxerror      int32
-	Esterror      int32
-	Status        int32
-	Constant      int32
-	Precision     int32
-	Tolerance     int32
-	Time          Timeval
-	Tick          int32
-	Ppsfreq       int32
-	Jitter        int32
-	Shift         int32
-	Stabil        int32
-	Jitcnt        int32
-	Calcnt        int32
-	Errcnt        int32
-	Stbcnt        int32
-	Tai           int32
-	Pad_godefs_0  int32
-	Pad_godefs_1  int32
-	Pad_godefs_2  int32
-	Pad_godefs_3  int32
-	Pad_godefs_4  int32
-	Pad_godefs_5  int32
-	Pad_godefs_6  int32
-	Pad_godefs_7  int32
-	Pad_godefs_8  int32
-	Pad_godefs_9  int32
-	Pad_godefs_10 int32
+	Modes     uint32
+	Offset    int32
+	Freq      int32
+	Maxerror  int32
+	Esterror  int32
+	Status    int32
+	Constant  int32
+	Precision int32
+	Tolerance int32
+	Time      Timeval
+	Tick      int32
+	Ppsfreq   int32
+	Jitter    int32
+	Shift     int32
+	Stabil    int32
+	Jitcnt    int32
+	Calcnt    int32
+	Errcnt    int32
+	Stbcnt    int32
+	Tai       int32
+	Pad_cgo_0 [44]byte
 }
 
 type Time_t int32
@@ -205,49 +94,53 @@ type Rlimit struct {
 type _Gid_t uint32
 
 type Stat_t struct {
-	Dev          uint64
-	X__pad1      uint16
-	Pad_godefs_0 [2]byte
-	X__st_ino    uint32
-	Mode         uint32
-	Nlink        uint32
-	Uid          uint32
-	Gid          uint32
-	Rdev         uint64
-	X__pad2      uint16
-	Pad_godefs_1 [6]byte
-	Size         int64
-	Blksize      int32
-	Pad_godefs_2 [4]byte
-	Blocks       int64
-	Atim         Timespec
-	Mtim         Timespec
-	Ctim         Timespec
-	Ino          uint64
+	Dev       uint64
+	X__pad1   uint16
+	Pad_cgo_0 [2]byte
+	X__st_ino uint32
+	Mode      uint32
+	Nlink     uint32
+	Uid       uint32
+	Gid       uint32
+	Rdev      uint64
+	X__pad2   uint16
+	Pad_cgo_1 [6]byte
+	Size      int64
+	Blksize   int32
+	Pad_cgo_2 [4]byte
+	Blocks    int64
+	Atim      Timespec
+	Mtim      Timespec
+	Ctim      Timespec
+	Ino       uint64
 }
 
 type Statfs_t struct {
-	Type         int32
-	Bsize        int32
-	Blocks       uint64
-	Bfree        uint64
-	Bavail       uint64
-	Files        uint64
-	Ffree        uint64
-	Fsid         [8]byte /* __fsid_t */
-	Namelen      int32
-	Frsize       int32
-	Spare        [5]int32
-	Pad_godefs_0 [4]byte
+	Type      int32
+	Bsize     int32
+	Blocks    uint64
+	Bfree     uint64
+	Bavail    uint64
+	Files     uint64
+	Ffree     uint64
+	Fsid      Fsid
+	Namelen   int32
+	Frsize    int32
+	Spare     [5]int32
+	Pad_cgo_0 [4]byte
 }
 
 type Dirent struct {
-	Ino          uint64
-	Off          int64
-	Reclen       uint16
-	Type         uint8
-	Name         [256]uint8
-	Pad_godefs_0 [5]byte
+	Ino       uint64
+	Off       int64
+	Reclen    uint16
+	Type      uint8
+	Name      [256]uint8
+	Pad_cgo_0 [5]byte
+}
+
+type Fsid struct {
+	X__val [2]int32
 }
 
 type RawSockaddrInet4 struct {
@@ -314,6 +207,12 @@ type IPMreq struct {
 	Interface [4]byte /* in_addr */
 }
 
+type IPMreqn struct {
+	Multiaddr [4]byte /* in_addr */
+	Address   [4]byte /* in_addr */
+	Ifindex   int32
+}
+
 type IPv6Mreq struct {
 	Multiaddr [16]byte /* in6_addr */
 	Interface uint32
@@ -330,9 +229,16 @@ type Msghdr struct {
 }
 
 type Cmsghdr struct {
-	Len   uint32
-	Level int32
-	Type  int32
+	Len          uint32
+	Level        int32
+	Type         int32
+	X__cmsg_data [0]byte
+}
+
+type Inet4Pktinfo struct {
+	Ifindex  int32
+	Spec_dst [4]byte /* in_addr */
+	Addr     [4]byte /* in_addr */
 }
 
 type Inet6Pktinfo struct {
@@ -346,6 +252,102 @@ type Ucred struct {
 	Gid uint32
 }
 
+const (
+	SizeofSockaddrInet4     = 0x10
+	SizeofSockaddrInet6     = 0x1c
+	SizeofSockaddrAny       = 0x70
+	SizeofSockaddrUnix      = 0x6e
+	SizeofSockaddrLinklayer = 0x14
+	SizeofSockaddrNetlink   = 0xc
+	SizeofLinger            = 0x8
+	SizeofIPMreq            = 0x8
+	SizeofIPMreqn           = 0xc
+	SizeofIPv6Mreq          = 0x14
+	SizeofMsghdr            = 0x1c
+	SizeofCmsghdr           = 0xc
+	SizeofInet4Pktinfo      = 0xc
+	SizeofInet6Pktinfo      = 0x14
+	SizeofUcred             = 0xc
+)
+
+const (
+	IFA_UNSPEC        = 0x0
+	IFA_ADDRESS       = 0x1
+	IFA_LOCAL         = 0x2
+	IFA_LABEL         = 0x3
+	IFA_BROADCAST     = 0x4
+	IFA_ANYCAST       = 0x5
+	IFA_CACHEINFO     = 0x6
+	IFA_MULTICAST     = 0x7
+	IFLA_UNSPEC       = 0x0
+	IFLA_ADDRESS      = 0x1
+	IFLA_BROADCAST    = 0x2
+	IFLA_IFNAME       = 0x3
+	IFLA_MTU          = 0x4
+	IFLA_LINK         = 0x5
+	IFLA_QDISC        = 0x6
+	IFLA_STATS        = 0x7
+	IFLA_COST         = 0x8
+	IFLA_PRIORITY     = 0x9
+	IFLA_MASTER       = 0xa
+	IFLA_WIRELESS     = 0xb
+	IFLA_PROTINFO     = 0xc
+	IFLA_TXQLEN       = 0xd
+	IFLA_MAP          = 0xe
+	IFLA_WEIGHT       = 0xf
+	IFLA_OPERSTATE    = 0x10
+	IFLA_LINKMODE     = 0x11
+	IFLA_LINKINFO     = 0x12
+	IFLA_NET_NS_PID   = 0x13
+	IFLA_IFALIAS      = 0x14
+	IFLA_MAX          = 0x14
+	RT_SCOPE_UNIVERSE = 0x0
+	RT_SCOPE_SITE     = 0xc8
+	RT_SCOPE_LINK     = 0xfd
+	RT_SCOPE_HOST     = 0xfe
+	RT_SCOPE_NOWHERE  = 0xff
+	RT_TABLE_UNSPEC   = 0x0
+	RT_TABLE_COMPAT   = 0xfc
+	RT_TABLE_DEFAULT  = 0xfd
+	RT_TABLE_MAIN     = 0xfe
+	RT_TABLE_LOCAL    = 0xff
+	RT_TABLE_MAX      = 0xffffffff
+	RTA_UNSPEC        = 0x0
+	RTA_DST           = 0x1
+	RTA_SRC           = 0x2
+	RTA_IIF           = 0x3
+	RTA_OIF           = 0x4
+	RTA_GATEWAY       = 0x5
+	RTA_PRIORITY      = 0x6
+	RTA_PREFSRC       = 0x7
+	RTA_METRICS       = 0x8
+	RTA_MULTIPATH     = 0x9
+	RTA_FLOW          = 0xb
+	RTA_CACHEINFO     = 0xc
+	RTA_TABLE         = 0xf
+	RTN_UNSPEC        = 0x0
+	RTN_UNICAST       = 0x1
+	RTN_LOCAL         = 0x2
+	RTN_BROADCAST     = 0x3
+	RTN_ANYCAST       = 0x4
+	RTN_MULTICAST     = 0x5
+	RTN_BLACKHOLE     = 0x6
+	RTN_UNREACHABLE   = 0x7
+	RTN_PROHIBIT      = 0x8
+	RTN_THROW         = 0x9
+	RTN_NAT           = 0xa
+	RTN_XRESOLVE      = 0xb
+	SizeofNlMsghdr    = 0x10
+	SizeofNlMsgerr    = 0x14
+	SizeofRtGenmsg    = 0x1
+	SizeofNlAttr      = 0x4
+	SizeofRtAttr      = 0x4
+	SizeofIfInfomsg   = 0x10
+	SizeofIfAddrmsg   = 0x8
+	SizeofRtMsg       = 0xc
+	SizeofRtNexthop   = 0x8
+)
+
 type NlMsghdr struct {
 	Len   uint32
 	Type  uint16
@@ -409,6 +411,11 @@ type RtNexthop struct {
 	Ifindex int32
 }
 
+const (
+	SizeofSockFilter = 0x8
+	SizeofSockFprog  = 0x8
+)
+
 type SockFilter struct {
 	Code uint16
 	Jt   uint8
@@ -417,9 +424,9 @@ type SockFilter struct {
 }
 
 type SockFprog struct {
-	Len          uint16
-	Pad_godefs_0 [2]byte
-	Filter       *SockFilter
+	Len       uint16
+	Pad_cgo_0 [2]byte
+	Filter    *SockFilter
 }
 
 type InotifyEvent struct {
@@ -427,9 +434,14 @@ type InotifyEvent struct {
 	Mask   uint32
 	Cookie uint32
 	Len    uint32
+	Name   [0]byte
 }
 
-type PtraceRegs struct{}
+const SizeofInotifyEvent = 0x10
+
+type PtraceRegs struct {
+	Uregs [18]uint32
+}
 
 type FdSet struct {
 	Bits [32]int32
@@ -474,3 +486,117 @@ type EpollEvent struct {
 	Fd     int32
 	Pad    int32
 }
+
+type Termios struct {
+	Iflag     uint32
+	Oflag     uint32
+	Cflag     uint32
+	Lflag     uint32
+	Line      uint8
+	Cc        [32]uint8
+	Pad_cgo_0 [3]byte
+	Ispeed    uint32
+	Ospeed    uint32
+}
+
+const (
+	VINTR    = 0x0
+	VQUIT    = 0x1
+	VERASE   = 0x2
+	VKILL    = 0x3
+	VEOF     = 0x4
+	VTIME    = 0x5
+	VMIN     = 0x6
+	VSWTC    = 0x7
+	VSTART   = 0x8
+	VSTOP    = 0x9
+	VSUSP    = 0xa
+	VEOL     = 0xb
+	VREPRINT = 0xc
+	VDISCARD = 0xd
+	VWERASE  = 0xe
+	VLNEXT   = 0xf
+	VEOL2    = 0x10
+	IGNBRK   = 0x1
+	BRKINT   = 0x2
+	IGNPAR   = 0x4
+	PARMRK   = 0x8
+	INPCK    = 0x10
+	ISTRIP   = 0x20
+	INLCR    = 0x40
+	IGNCR    = 0x80
+	ICRNL    = 0x100
+	IUCLC    = 0x200
+	IXON     = 0x400
+	IXANY    = 0x800
+	IXOFF    = 0x1000
+	IMAXBEL  = 0x2000
+	IUTF8    = 0x4000
+	OPOST    = 0x1
+	OLCUC    = 0x2
+	ONLCR    = 0x4
+	OCRNL    = 0x8
+	ONOCR    = 0x10
+	ONLRET   = 0x20
+	OFILL    = 0x40
+	OFDEL    = 0x80
+	B0       = 0x0
+	B50      = 0x1
+	B75      = 0x2
+	B110     = 0x3
+	B134     = 0x4
+	B150     = 0x5
+	B200     = 0x6
+	B300     = 0x7
+	B600     = 0x8
+	B1200    = 0x9
+	B1800    = 0xa
+	B2400    = 0xb
+	B4800    = 0xc
+	B9600    = 0xd
+	B19200   = 0xe
+	B38400   = 0xf
+	CSIZE    = 0x30
+	CS5      = 0x0
+	CS6      = 0x10
+	CS7      = 0x20
+	CS8      = 0x30
+	CSTOPB   = 0x40
+	CREAD    = 0x80
+	PARENB   = 0x100
+	PARODD   = 0x200
+	HUPCL    = 0x400
+	CLOCAL   = 0x800
+	B57600   = 0x1001
+	B115200  = 0x1002
+	B230400  = 0x1003
+	B460800  = 0x1004
+	B500000  = 0x1005
+	B576000  = 0x1006
+	B921600  = 0x1007
+	B1000000 = 0x1008
+	B1152000 = 0x1009
+	B1500000 = 0x100a
+	B2000000 = 0x100b
+	B2500000 = 0x100c
+	B3000000 = 0x100d
+	B3500000 = 0x100e
+	B4000000 = 0x100f
+	ISIG     = 0x1
+	ICANON   = 0x2
+	XCASE    = 0x4
+	ECHO     = 0x8
+	ECHOE    = 0x10
+	ECHOK    = 0x20
+	ECHONL   = 0x40
+	NOFLSH   = 0x80
+	TOSTOP   = 0x100
+	ECHOCTL  = 0x200
+	ECHOPRT  = 0x400
+	ECHOKE   = 0x800
+	FLUSHO   = 0x1000
+	PENDIN   = 0x4000
+	IEXTEN   = 0x8000
+	TCGETS   = 0x5401
+	TCSETS   = 0x5402
+)
diff --git a/src/pkg/syscall/ztypes_netbsd_386.go b/src/pkg/syscall/ztypes_netbsd_386.go
new file mode 100644
index 0000000..ef9f33a
--- /dev/null
+++ b/src/pkg/syscall/ztypes_netbsd_386.go
@@ -0,0 +1,406 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_netbsd.go
+
+package syscall
+
+const (
+	sizeofPtr      = 0x4
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x4
+	sizeofLongLong = 0x8
+)
+
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int32
+	_C_long_long int64
+)
+
+type Timespec struct {
+	Sec  int32
+	Nsec int32
+}
+
+type Timeval struct {
+	Sec  int32
+	Usec int32
+}
+
+type Rusage struct {
+	Utime    Timeval
+	Stime    Timeval
+	Maxrss   int32
+	Ixrss    int32
+	Idrss    int32
+	Isrss    int32
+	Minflt   int32
+	Majflt   int32
+	Nswap    int32
+	Inblock  int32
+	Oublock  int32
+	Msgsnd   int32
+	Msgrcv   int32
+	Nsignals int32
+	Nvcsw    int32
+	Nivcsw   int32
+}
+
+type Rlimit struct {
+	Cur uint64
+	Max uint64
+}
+
+type _Gid_t uint32
+
+const (
+	S_IFMT   = 0xf000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+	S_ISUID  = 0x800
+	S_ISGID  = 0x400
+	S_ISVTX  = 0x200
+	S_IRUSR  = 0x100
+	S_IWUSR  = 0x80
+	S_IXUSR  = 0x40
+)
+
+type Stat_t struct {
+	Dev            int32
+	Ino            uint32
+	Mode           uint32
+	Nlink          uint32
+	Uid            uint32
+	Gid            uint32
+	Rdev           int32
+	Lspare0        int32
+	Atim           Timespec
+	Mtim           Timespec
+	Ctim           Timespec
+	Size           int64
+	Blocks         int64
+	Blksize        uint32
+	Flags          uint32
+	Gen            uint32
+	Lspare1        int32
+	X__st_birthtim Timespec
+	Qspare         [2]int64
+}
+
+type Statfs_t struct {
+	F_flags       uint32
+	F_bsize       uint32
+	F_iosize      uint32
+	F_blocks      uint64
+	F_bfree       uint64
+	F_bavail      int64
+	F_files       uint64
+	F_ffree       uint64
+	F_favail      int64
+	F_syncwrites  uint64
+	F_syncreads   uint64
+	F_asyncwrites uint64
+	F_asyncreads  uint64
+	F_fsid        Fsid
+	F_namemax     uint32
+	F_owner       uint32
+	F_ctime       uint32
+	F_spare       [3]uint32
+	F_fstypename  [16]int8
+	F_mntonname   [90]int8
+	F_mntfromname [90]int8
+	Mount_info    [160]byte
+}
+
+type Flock_t struct {
+	Start  int64
+	Len    int64
+	Pid    int32
+	Type   int16
+	Whence int16
+}
+
+type Dirent struct {
+	Fileno uint64
+	Reclen uint16
+	Namlen uint16
+	Type   uint8
+	Name   [512]int8
+}
+
+type Fsid struct {
+	Val [2]int32
+}
+
+type RawSockaddrInet4 struct {
+	Len    uint8
+	Family uint8
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]int8
+}
+
+type RawSockaddrInet6 struct {
+	Len      uint8
+	Family   uint8
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+	Len    uint8
+	Family uint8
+	Path   [104]int8
+}
+
+type RawSockaddrDatalink struct {
+	Len    uint8
+	Family uint8
+	Index  uint16
+	Type   uint8
+	Nlen   uint8
+	Alen   uint8
+	Slen   uint8
+	Data   [24]int8
+}
+
+type RawSockaddr struct {
+	Len    uint8
+	Family uint8
+	Data   [14]int8
+}
+
+type RawSockaddrAny struct {
+	Addr RawSockaddr
+	Pad  [92]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+	Onoff  int32
+	Linger int32
+}
+
+type Iovec struct {
+	Base *byte
+	Len  uint32
+}
+
+type IPMreq struct {
+	Multiaddr [4]byte /* in_addr */
+	Interface [4]byte /* in_addr */
+}
+
+type IPv6Mreq struct {
+	Multiaddr [16]byte /* in6_addr */
+	Interface uint32
+}
+
+type Msghdr struct {
+	Name       *byte
+	Namelen    uint32
+	Iov        *Iovec
+	Iovlen     uint32
+	Control    *byte
+	Controllen uint32
+	Flags      int32
+}
+
+type Cmsghdr struct {
+	Len   uint32
+	Level int32
+	Type  int32
+}
+
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x20
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x1c
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
+type Kevent_t struct {
+	Ident  uint32
+	Filter int16
+	Flags  uint16
+	Fflags uint32
+	Data   int32
+	Udata  *byte
+}
+
+type FdSet struct {
+	Bits [32]int32
+}
+
+const (
+	SizeofIfMsghdr  = 0xe8
+	SizeofIfData    = 0xd0
+	SizeofIfaMsghdr = 0x18
+	SizeofRtMsghdr  = 0x58
+	SizeofRtMetrics = 0x30
+)
+
+type IfMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Hdrlen  uint16
+	Index   uint16
+	Tableid uint16
+	Pad1    uint8
+	Pad2    uint8
+	Addrs   int32
+	Flags   int32
+	Xflags  int32
+	Data    IfData
+}
+
+type IfData struct {
+	Type         uint8
+	Addrlen      uint8
+	Hdrlen       uint8
+	Link_state   uint8
+	Mtu          uint32
+	Metric       uint32
+	Pad          uint32
+	Baudrate     uint64
+	Ipackets     uint64
+	Ierrors      uint64
+	Opackets     uint64
+	Oerrors      uint64
+	Collisions   uint64
+	Ibytes       uint64
+	Obytes       uint64
+	Imcasts      uint64
+	Omcasts      uint64
+	Iqdrops      uint64
+	Noproto      uint64
+	Capabilities uint32
+	Lastchange   Timeval
+	Mclpool      [7]Mclpool
+}
+
+type IfaMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Hdrlen  uint16
+	Index   uint16
+	Tableid uint16
+	Pad1    uint8
+	Pad2    uint8
+	Addrs   int32
+	Flags   int32
+	Metric  int32
+}
+
+type RtMsghdr struct {
+	Msglen   uint16
+	Version  uint8
+	Type     uint8
+	Hdrlen   uint16
+	Index    uint16
+	Tableid  uint16
+	Priority uint8
+	Mpls     uint8
+	Addrs    int32
+	Flags    int32
+	Fmask    int32
+	Pid      int32
+	Seq      int32
+	Errno    int32
+	Inits    uint32
+	Rmx      RtMetrics
+}
+
+type RtMetrics struct {
+	Pksent   uint64
+	Locks    uint32
+	Mtu      uint32
+	Expire   uint32
+	Refcnt   uint32
+	Hopcount uint32
+	Recvpipe uint32
+	Sendpipe uint32
+	Ssthresh uint32
+	Rtt      uint32
+	Rttvar   uint32
+}
+
+type Mclpool struct {
+	Grown uint32
+	Alive uint16
+	Hwm   uint16
+	Cwm   uint16
+	Lwm   uint16
+}
+
+const (
+	SizeofBpfVersion = 0x4
+	SizeofBpfStat    = 0x8
+	SizeofBpfProgram = 0x8
+	SizeofBpfInsn    = 0x8
+	SizeofBpfHdr     = 0x14
+)
+
+type BpfVersion struct {
+	Major uint16
+	Minor uint16
+}
+
+type BpfStat struct {
+	Recv uint32
+	Drop uint32
+}
+
+type BpfProgram struct {
+	Len   uint32
+	Insns *BpfInsn
+}
+
+type BpfInsn struct {
+	Code uint16
+	Jt   uint8
+	Jf   uint8
+	K    uint32
+}
+
+type BpfHdr struct {
+	Tstamp    BpfTimeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
+}
+
+type BpfTimeval struct {
+	Sec  uint32
+	Usec uint32
+}
diff --git a/src/pkg/syscall/ztypes_netbsd_amd64.go b/src/pkg/syscall/ztypes_netbsd_amd64.go
new file mode 100644
index 0000000..3979d54
--- /dev/null
+++ b/src/pkg/syscall/ztypes_netbsd_amd64.go
@@ -0,0 +1,412 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_netbsd.go
+
+package syscall
+
+const (
+	sizeofPtr      = 0x8
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x8
+	sizeofLongLong = 0x8
+)
+
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int64
+	_C_long_long int64
+)
+
+type Timespec struct {
+	Sec       int32
+	Pad_cgo_0 [4]byte
+	Nsec      int64
+}
+
+type Timeval struct {
+	Sec  int64
+	Usec int64
+}
+
+type Rusage struct {
+	Utime    Timeval
+	Stime    Timeval
+	Maxrss   int64
+	Ixrss    int64
+	Idrss    int64
+	Isrss    int64
+	Minflt   int64
+	Majflt   int64
+	Nswap    int64
+	Inblock  int64
+	Oublock  int64
+	Msgsnd   int64
+	Msgrcv   int64
+	Nsignals int64
+	Nvcsw    int64
+	Nivcsw   int64
+}
+
+type Rlimit struct {
+	Cur uint64
+	Max uint64
+}
+
+type _Gid_t uint32
+
+const (
+	S_IFMT   = 0xf000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+	S_ISUID  = 0x800
+	S_ISGID  = 0x400
+	S_ISVTX  = 0x200
+	S_IRUSR  = 0x100
+	S_IWUSR  = 0x80
+	S_IXUSR  = 0x40
+)
+
+type Stat_t struct {
+	Dev            int32
+	Ino            uint32
+	Mode           uint32
+	Nlink          uint32
+	Uid            uint32
+	Gid            uint32
+	Rdev           int32
+	Lspare0        int32
+	Atim           Timespec
+	Mtim           Timespec
+	Ctim           Timespec
+	Size           int64
+	Blocks         int64
+	Blksize        uint32
+	Flags          uint32
+	Gen            uint32
+	Lspare1        int32
+	X__st_birthtim Timespec
+	Qspare         [2]int64
+}
+
+type Statfs_t struct {
+	F_flags       uint32
+	F_bsize       uint32
+	F_iosize      uint32
+	Pad_cgo_0     [4]byte
+	F_blocks      uint64
+	F_bfree       uint64
+	F_bavail      int64
+	F_files       uint64
+	F_ffree       uint64
+	F_favail      int64
+	F_syncwrites  uint64
+	F_syncreads   uint64
+	F_asyncwrites uint64
+	F_asyncreads  uint64
+	F_fsid        Fsid
+	F_namemax     uint32
+	F_owner       uint32
+	F_ctime       uint32
+	F_spare       [3]uint32
+	F_fstypename  [16]int8
+	F_mntonname   [90]int8
+	F_mntfromname [90]int8
+	Pad_cgo_1     [4]byte
+	Mount_info    [160]byte
+}
+
+type Flock_t struct {
+	Start  int64
+	Len    int64
+	Pid    int32
+	Type   int16
+	Whence int16
+}
+
+type Dirent struct {
+	Fileno uint64
+	Reclen uint16
+	Namlen uint16
+	Type   uint8
+	Name   [512]int8
+}
+
+type Fsid struct {
+	Val [2]int32
+}
+
+type RawSockaddrInet4 struct {
+	Len    uint8
+	Family uint8
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]int8
+}
+
+type RawSockaddrInet6 struct {
+	Len      uint8
+	Family   uint8
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+	Len    uint8
+	Family uint8
+	Path   [104]int8
+}
+
+type RawSockaddrDatalink struct {
+	Len    uint8
+	Family uint8
+	Index  uint16
+	Type   uint8
+	Nlen   uint8
+	Alen   uint8
+	Slen   uint8
+	Data   [24]int8
+}
+
+type RawSockaddr struct {
+	Len    uint8
+	Family uint8
+	Data   [14]int8
+}
+
+type RawSockaddrAny struct {
+	Addr RawSockaddr
+	Pad  [92]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+	Onoff  int32
+	Linger int32
+}
+
+type Iovec struct {
+	Base *byte
+	Len  uint64
+}
+
+type IPMreq struct {
+	Multiaddr [4]byte /* in_addr */
+	Interface [4]byte /* in_addr */
+}
+
+type IPv6Mreq struct {
+	Multiaddr [16]byte /* in6_addr */
+	Interface uint32
+}
+
+type Msghdr struct {
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *Iovec
+	Iovlen     uint32
+	Pad_cgo_1  [4]byte
+	Control    *byte
+	Controllen uint32
+	Flags      int32
+}
+
+type Cmsghdr struct {
+	Len   uint32
+	Level int32
+	Type  int32
+}
+
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x20
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x30
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
+type Kevent_t struct {
+	Ident  uint64
+	Filter int16
+	Flags  uint16
+	Fflags uint32
+	Data   int32
+	Udata  *byte
+}
+
+type FdSet struct {
+	Bits [32]int32
+}
+
+const (
+	SizeofIfMsghdr  = 0xf0
+	SizeofIfData    = 0xd8
+	SizeofIfaMsghdr = 0x18
+	SizeofRtMsghdr  = 0x58
+	SizeofRtMetrics = 0x30
+)
+
+type IfMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Hdrlen  uint16
+	Index   uint16
+	Tableid uint16
+	Pad1    uint8
+	Pad2    uint8
+	Addrs   int32
+	Flags   int32
+	Xflags  int32
+	Data    IfData
+}
+
+type IfData struct {
+	Type       uint8
+	Addrlen    uint8
+	Hdrlen     uint8
+	Link_state uint8
+	Mtu        uint32
+	Metric     uint32
+	Pad        uint32
+	Baudrate   uint64
+	Ipackets   uint64
+	Ierrors    uint64
+	Opackets   uint64
+	Oerrors    uint64
+	Collisions uint64
+	Ibytes     uint64
+	Obytes     uint64
+	Imcasts    uint64
+	Omcasts    uint64
+	Iqdrops    uint64
+	Noproto    uint64
+	Lastchange Timeval
+	Mclpool    [7]Mclpool
+	Pad_cgo_0  [4]byte
+}
+
+type IfaMsghdr struct {
+	Msglen  uint16
+	Version uint8
+	Type    uint8
+	Hdrlen  uint16
+	Index   uint16
+	Tableid uint16
+	Pad1    uint8
+	Pad2    uint8
+	Addrs   int32
+	Flags   int32
+	Metric  int32
+}
+
+type RtMsghdr struct {
+	Msglen   uint16
+	Version  uint8
+	Type     uint8
+	Hdrlen   uint16
+	Index    uint16
+	Tableid  uint16
+	Priority uint8
+	Mpls     uint8
+	Addrs    int32
+	Flags    int32
+	Fmask    int32
+	Pid      int32
+	Seq      int32
+	Errno    int32
+	Inits    uint32
+	Rmx      RtMetrics
+}
+
+type RtMetrics struct {
+	Pksent   uint64
+	Locks    uint32
+	Mtu      uint32
+	Expire   uint32
+	Refcnt   uint32
+	Hopcount uint32
+	Recvpipe uint32
+	Sendpipe uint32
+	Ssthresh uint32
+	Rtt      uint32
+	Rttvar   uint32
+}
+
+type Mclpool struct {
+	Grown uint32
+	Alive uint16
+	Hwm   uint16
+	Cwm   uint16
+	Lwm   uint16
+}
+
+const (
+	SizeofBpfVersion = 0x4
+	SizeofBpfStat    = 0x8
+	SizeofBpfProgram = 0x10
+	SizeofBpfInsn    = 0x8
+	SizeofBpfHdr     = 0x14
+)
+
+type BpfVersion struct {
+	Major uint16
+	Minor uint16
+}
+
+type BpfStat struct {
+	Recv uint32
+	Drop uint32
+}
+
+type BpfProgram struct {
+	Len       uint32
+	Pad_cgo_0 [4]byte
+	Insns     *BpfInsn
+}
+
+type BpfInsn struct {
+	Code uint16
+	Jt   uint8
+	Jf   uint8
+	K    uint32
+}
+
+type BpfHdr struct {
+	Tstamp    BpfTimeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
+}
+
+type BpfTimeval struct {
+	Sec  uint32
+	Usec uint32
+}
diff --git a/src/pkg/syscall/ztypes_openbsd_386.go b/src/pkg/syscall/ztypes_openbsd_386.go
index af6824a..0505f80 100644
--- a/src/pkg/syscall/ztypes_openbsd_386.go
+++ b/src/pkg/syscall/ztypes_openbsd_386.go
@@ -1,65 +1,22 @@
-// godefs -gsyscall -f-m32 types_openbsd.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_openbsd.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr              = 0x4
-	sizeofShort            = 0x2
-	sizeofInt              = 0x4
-	sizeofLong             = 0x4
-	sizeofLongLong         = 0x8
-	S_IFMT                 = 0xf000
-	S_IFIFO                = 0x1000
-	S_IFCHR                = 0x2000
-	S_IFDIR                = 0x4000
-	S_IFBLK                = 0x6000
-	S_IFREG                = 0x8000
-	S_IFLNK                = 0xa000
-	S_IFSOCK               = 0xc000
-	S_ISUID                = 0x800
-	S_ISGID                = 0x400
-	S_ISVTX                = 0x200
-	S_IRUSR                = 0x100
-	S_IWUSR                = 0x80
-	S_IXUSR                = 0x40
-	SizeofSockaddrInet4    = 0x10
-	SizeofSockaddrInet6    = 0x1c
-	SizeofSockaddrAny      = 0x6c
-	SizeofSockaddrUnix     = 0x6a
-	SizeofSockaddrDatalink = 0x20
-	SizeofLinger           = 0x8
-	SizeofIPMreq           = 0x8
-	SizeofIPv6Mreq         = 0x14
-	SizeofMsghdr           = 0x1c
-	SizeofCmsghdr          = 0xc
-	SizeofInet6Pktinfo     = 0x14
-	PTRACE_TRACEME         = 0
-	PTRACE_CONT            = 0x7
-	PTRACE_KILL            = 0x8
-	SizeofIfMsghdr         = 0xe4
-	SizeofIfData           = 0xcc
-	SizeofIfaMsghdr        = 0x18
-	SizeofRtMsghdr         = 0x58
-	SizeofRtMetrics        = 0x30
-	SizeofBpfVersion       = 0x4
-	SizeofBpfStat          = 0x8
-	SizeofBpfProgram       = 0x8
-	SizeofBpfInsn          = 0x8
-	SizeofBpfHdr           = 0x14
+	sizeofPtr      = 0x4
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x4
+	sizeofLongLong = 0x8
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int32
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int32
+	_C_long_long int64
+)
 
 type Timespec struct {
 	Sec  int32
@@ -97,6 +54,23 @@ type Rlimit struct {
 
 type _Gid_t uint32
 
+const (
+	S_IFMT   = 0xf000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+	S_ISUID  = 0x800
+	S_ISGID  = 0x400
+	S_ISVTX  = 0x200
+	S_IRUSR  = 0x100
+	S_IWUSR  = 0x80
+	S_IXUSR  = 0x40
+)
+
 type Stat_t struct {
 	Dev            int32
 	Ino            uint32
@@ -133,7 +107,7 @@ type Statfs_t struct {
 	F_syncreads   uint64
 	F_asyncwrites uint64
 	F_asyncreads  uint64
-	F_fsid        [8]byte /* fsid_t */
+	F_fsid        Fsid
 	F_namemax     uint32
 	F_owner       uint32
 	F_ctime       uint32
@@ -141,7 +115,7 @@ type Statfs_t struct {
 	F_fstypename  [16]int8
 	F_mntonname   [90]int8
 	F_mntfromname [90]int8
-	Mount_info    [160]byte /* mount_info */
+	Mount_info    [160]byte
 }
 
 type Flock_t struct {
@@ -160,6 +134,10 @@ type Dirent struct {
 	Name   [256]int8
 }
 
+type Fsid struct {
+	Val [2]int32
+}
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
@@ -248,6 +226,26 @@ type Inet6Pktinfo struct {
 	Ifindex uint32
 }
 
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x20
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x1c
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
 type Kevent_t struct {
 	Ident  uint32
 	Filter int16
@@ -261,6 +259,14 @@ type FdSet struct {
 	Bits [32]int32
 }
 
+const (
+	SizeofIfMsghdr  = 0xe8
+	SizeofIfData    = 0xd0
+	SizeofIfaMsghdr = 0x18
+	SizeofRtMsghdr  = 0x58
+	SizeofRtMetrics = 0x30
+)
+
 type IfMsghdr struct {
 	Msglen  uint16
 	Version uint8
@@ -277,27 +283,28 @@ type IfMsghdr struct {
 }
 
 type IfData struct {
-	Type       uint8
-	Addrlen    uint8
-	Hdrlen     uint8
-	Link_state uint8
-	Mtu        uint32
-	Metric     uint32
-	Pad        uint32
-	Baudrate   uint64
-	Ipackets   uint64
-	Ierrors    uint64
-	Opackets   uint64
-	Oerrors    uint64
-	Collisions uint64
-	Ibytes     uint64
-	Obytes     uint64
-	Imcasts    uint64
-	Omcasts    uint64
-	Iqdrops    uint64
-	Noproto    uint64
-	Lastchange Timeval
-	Mclpool    [7][12]byte /* mclpool */
+	Type         uint8
+	Addrlen      uint8
+	Hdrlen       uint8
+	Link_state   uint8
+	Mtu          uint32
+	Metric       uint32
+	Pad          uint32
+	Baudrate     uint64
+	Ipackets     uint64
+	Ierrors      uint64
+	Opackets     uint64
+	Oerrors      uint64
+	Collisions   uint64
+	Ibytes       uint64
+	Obytes       uint64
+	Imcasts      uint64
+	Omcasts      uint64
+	Iqdrops      uint64
+	Noproto      uint64
+	Capabilities uint32
+	Lastchange   Timeval
+	Mclpool      [7]Mclpool
 }
 
 type IfaMsghdr struct {
@@ -347,6 +354,22 @@ type RtMetrics struct {
 	Rttvar   uint32
 }
 
+type Mclpool struct {
+	Grown uint32
+	Alive uint16
+	Hwm   uint16
+	Cwm   uint16
+	Lwm   uint16
+}
+
+const (
+	SizeofBpfVersion = 0x4
+	SizeofBpfStat    = 0x8
+	SizeofBpfProgram = 0x8
+	SizeofBpfInsn    = 0x8
+	SizeofBpfHdr     = 0x14
+)
+
 type BpfVersion struct {
 	Major uint16
 	Minor uint16
@@ -370,11 +393,11 @@ type BpfInsn struct {
 }
 
 type BpfHdr struct {
-	Tstamp       BpfTimeval
-	Caplen       uint32
-	Datalen      uint32
-	Hdrlen       uint16
-	Pad_godefs_0 [2]byte
+	Tstamp    BpfTimeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
 }
 
 type BpfTimeval struct {
diff --git a/src/pkg/syscall/ztypes_openbsd_amd64.go b/src/pkg/syscall/ztypes_openbsd_amd64.go
index 01df7e7..4d01578 100644
--- a/src/pkg/syscall/ztypes_openbsd_amd64.go
+++ b/src/pkg/syscall/ztypes_openbsd_amd64.go
@@ -1,70 +1,27 @@
-// godefs -gsyscall -f-m64 types_openbsd.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_openbsd.go
 
 package syscall
 
-// Constants
 const (
-	sizeofPtr              = 0x8
-	sizeofShort            = 0x2
-	sizeofInt              = 0x4
-	sizeofLong             = 0x8
-	sizeofLongLong         = 0x8
-	S_IFMT                 = 0xf000
-	S_IFIFO                = 0x1000
-	S_IFCHR                = 0x2000
-	S_IFDIR                = 0x4000
-	S_IFBLK                = 0x6000
-	S_IFREG                = 0x8000
-	S_IFLNK                = 0xa000
-	S_IFSOCK               = 0xc000
-	S_ISUID                = 0x800
-	S_ISGID                = 0x400
-	S_ISVTX                = 0x200
-	S_IRUSR                = 0x100
-	S_IWUSR                = 0x80
-	S_IXUSR                = 0x40
-	SizeofSockaddrInet4    = 0x10
-	SizeofSockaddrInet6    = 0x1c
-	SizeofSockaddrAny      = 0x6c
-	SizeofSockaddrUnix     = 0x6a
-	SizeofSockaddrDatalink = 0x20
-	SizeofLinger           = 0x8
-	SizeofIPMreq           = 0x8
-	SizeofIPv6Mreq         = 0x14
-	SizeofMsghdr           = 0x30
-	SizeofCmsghdr          = 0xc
-	SizeofInet6Pktinfo     = 0x14
-	PTRACE_TRACEME         = 0
-	PTRACE_CONT            = 0x7
-	PTRACE_KILL            = 0x8
-	SizeofIfMsghdr         = 0xf0
-	SizeofIfData           = 0xd8
-	SizeofIfaMsghdr        = 0x18
-	SizeofRtMsghdr         = 0x58
-	SizeofRtMetrics        = 0x30
-	SizeofBpfVersion       = 0x4
-	SizeofBpfStat          = 0x8
-	SizeofBpfProgram       = 0x10
-	SizeofBpfInsn          = 0x8
-	SizeofBpfHdr           = 0x14
+	sizeofPtr      = 0x8
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x8
+	sizeofLongLong = 0x8
 )
 
-// Types
-
-type _C_short int16
-
-type _C_int int32
-
-type _C_long int64
-
-type _C_long_long int64
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int64
+	_C_long_long int64
+)
 
 type Timespec struct {
-	Sec          int32
-	Pad_godefs_0 [4]byte
-	Nsec         int64
+	Sec       int32
+	Pad_cgo_0 [4]byte
+	Nsec      int64
 }
 
 type Timeval struct {
@@ -98,6 +55,23 @@ type Rlimit struct {
 
 type _Gid_t uint32
 
+const (
+	S_IFMT   = 0xf000
+	S_IFIFO  = 0x1000
+	S_IFCHR  = 0x2000
+	S_IFDIR  = 0x4000
+	S_IFBLK  = 0x6000
+	S_IFREG  = 0x8000
+	S_IFLNK  = 0xa000
+	S_IFSOCK = 0xc000
+	S_ISUID  = 0x800
+	S_ISGID  = 0x400
+	S_ISVTX  = 0x200
+	S_IRUSR  = 0x100
+	S_IWUSR  = 0x80
+	S_IXUSR  = 0x40
+)
+
 type Stat_t struct {
 	Dev            int32
 	Ino            uint32
@@ -124,7 +98,7 @@ type Statfs_t struct {
 	F_flags       uint32
 	F_bsize       uint32
 	F_iosize      uint32
-	Pad_godefs_0  [4]byte
+	Pad_cgo_0     [4]byte
 	F_blocks      uint64
 	F_bfree       uint64
 	F_bavail      int64
@@ -135,7 +109,7 @@ type Statfs_t struct {
 	F_syncreads   uint64
 	F_asyncwrites uint64
 	F_asyncreads  uint64
-	F_fsid        [8]byte /* fsid_t */
+	F_fsid        Fsid
 	F_namemax     uint32
 	F_owner       uint32
 	F_ctime       uint32
@@ -143,8 +117,8 @@ type Statfs_t struct {
 	F_fstypename  [16]int8
 	F_mntonname   [90]int8
 	F_mntfromname [90]int8
-	Pad_godefs_1  [4]byte
-	Mount_info    [160]byte /* mount_info */
+	Pad_cgo_1     [4]byte
+	Mount_info    [160]byte
 }
 
 type Flock_t struct {
@@ -163,6 +137,10 @@ type Dirent struct {
 	Name   [256]int8
 }
 
+type Fsid struct {
+	Val [2]int32
+}
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
@@ -231,15 +209,15 @@ type IPv6Mreq struct {
 }
 
 type Msghdr struct {
-	Name         *byte
-	Namelen      uint32
-	Pad_godefs_0 [4]byte
-	Iov          *Iovec
-	Iovlen       uint32
-	Pad_godefs_1 [4]byte
-	Control      *byte
-	Controllen   uint32
-	Flags        int32
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *Iovec
+	Iovlen     uint32
+	Pad_cgo_1  [4]byte
+	Control    *byte
+	Controllen uint32
+	Flags      int32
 }
 
 type Cmsghdr struct {
@@ -253,6 +231,26 @@ type Inet6Pktinfo struct {
 	Ifindex uint32
 }
 
+const (
+	SizeofSockaddrInet4    = 0x10
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x6c
+	SizeofSockaddrUnix     = 0x6a
+	SizeofSockaddrDatalink = 0x20
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x30
+	SizeofCmsghdr          = 0xc
+	SizeofInet6Pktinfo     = 0x14
+)
+
+const (
+	PTRACE_TRACEME = 0x0
+	PTRACE_CONT    = 0x7
+	PTRACE_KILL    = 0x8
+)
+
 type Kevent_t struct {
 	Ident  uint32
 	Filter int16
@@ -266,6 +264,14 @@ type FdSet struct {
 	Bits [32]int32
 }
 
+const (
+	SizeofIfMsghdr  = 0xf0
+	SizeofIfData    = 0xd8
+	SizeofIfaMsghdr = 0x18
+	SizeofRtMsghdr  = 0x58
+	SizeofRtMetrics = 0x30
+)
+
 type IfMsghdr struct {
 	Msglen  uint16
 	Version uint8
@@ -282,28 +288,28 @@ type IfMsghdr struct {
 }
 
 type IfData struct {
-	Type         uint8
-	Addrlen      uint8
-	Hdrlen       uint8
-	Link_state   uint8
-	Mtu          uint32
-	Metric       uint32
-	Pad          uint32
-	Baudrate     uint64
-	Ipackets     uint64
-	Ierrors      uint64
-	Opackets     uint64
-	Oerrors      uint64
-	Collisions   uint64
-	Ibytes       uint64
-	Obytes       uint64
-	Imcasts      uint64
-	Omcasts      uint64
-	Iqdrops      uint64
-	Noproto      uint64
-	Lastchange   Timeval
-	Mclpool      [7][12]byte /* mclpool */
-	Pad_godefs_0 [4]byte
+	Type       uint8
+	Addrlen    uint8
+	Hdrlen     uint8
+	Link_state uint8
+	Mtu        uint32
+	Metric     uint32
+	Pad        uint32
+	Baudrate   uint64
+	Ipackets   uint64
+	Ierrors    uint64
+	Opackets   uint64
+	Oerrors    uint64
+	Collisions uint64
+	Ibytes     uint64
+	Obytes     uint64
+	Imcasts    uint64
+	Omcasts    uint64
+	Iqdrops    uint64
+	Noproto    uint64
+	Lastchange Timeval
+	Mclpool    [7]Mclpool
+	Pad_cgo_0  [4]byte
 }
 
 type IfaMsghdr struct {
@@ -353,6 +359,22 @@ type RtMetrics struct {
 	Rttvar   uint32
 }
 
+type Mclpool struct {
+	Grown uint32
+	Alive uint16
+	Hwm   uint16
+	Cwm   uint16
+	Lwm   uint16
+}
+
+const (
+	SizeofBpfVersion = 0x4
+	SizeofBpfStat    = 0x8
+	SizeofBpfProgram = 0x10
+	SizeofBpfInsn    = 0x8
+	SizeofBpfHdr     = 0x14
+)
+
 type BpfVersion struct {
 	Major uint16
 	Minor uint16
@@ -364,9 +386,9 @@ type BpfStat struct {
 }
 
 type BpfProgram struct {
-	Len          uint32
-	Pad_godefs_0 [4]byte
-	Insns        *BpfInsn
+	Len       uint32
+	Pad_cgo_0 [4]byte
+	Insns     *BpfInsn
 }
 
 type BpfInsn struct {
@@ -377,11 +399,11 @@ type BpfInsn struct {
 }
 
 type BpfHdr struct {
-	Tstamp       BpfTimeval
-	Caplen       uint32
-	Datalen      uint32
-	Hdrlen       uint16
-	Pad_godefs_0 [2]byte
+	Tstamp    BpfTimeval
+	Caplen    uint32
+	Datalen   uint32
+	Hdrlen    uint16
+	Pad_cgo_0 [2]byte
 }
 
 type BpfTimeval struct {
diff --git a/src/pkg/syscall/ztypes_windows.go b/src/pkg/syscall/ztypes_windows.go
index a3ef1ba..a4840a8 100644
--- a/src/pkg/syscall/ztypes_windows.go
+++ b/src/pkg/syscall/ztypes_windows.go
@@ -1,18 +1,23 @@
+// Copyright 2011 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 syscall
 
 const (
 	// Windows errors.
-	ERROR_FILE_NOT_FOUND      = 2
-	ERROR_PATH_NOT_FOUND      = 3
-	ERROR_NO_MORE_FILES       = 18
-	ERROR_BROKEN_PIPE         = 109
-	ERROR_BUFFER_OVERFLOW     = 111
-	ERROR_INSUFFICIENT_BUFFER = 122
-	ERROR_MOD_NOT_FOUND       = 126
-	ERROR_PROC_NOT_FOUND      = 127
-	ERROR_ENVVAR_NOT_FOUND    = 203
-	ERROR_OPERATION_ABORTED   = 995
-	ERROR_IO_PENDING          = 997
+	ERROR_FILE_NOT_FOUND      Errno = 2
+	ERROR_PATH_NOT_FOUND      Errno = 3
+	ERROR_ACCESS_DENIED       Errno = 5
+	ERROR_NO_MORE_FILES       Errno = 18
+	ERROR_BROKEN_PIPE         Errno = 109
+	ERROR_BUFFER_OVERFLOW     Errno = 111
+	ERROR_INSUFFICIENT_BUFFER Errno = 122
+	ERROR_MOD_NOT_FOUND       Errno = 126
+	ERROR_PROC_NOT_FOUND      Errno = 127
+	ERROR_ENVVAR_NOT_FOUND    Errno = 203
+	ERROR_OPERATION_ABORTED   Errno = 995
+	ERROR_IO_PENDING          Errno = 997
 )
 
 const (
@@ -54,6 +59,7 @@ const (
 	GENERIC_EXECUTE = 0x20000000
 	GENERIC_ALL     = 0x10000000
 
+	FILE_LIST_DIRECTORY   = 0x00000001
 	FILE_APPEND_DATA      = 0x00000004
 	FILE_WRITE_ATTRIBUTES = 0x00000100
 
@@ -75,6 +81,9 @@ const (
 	OPEN_ALWAYS       = 4
 	TRUNCATE_EXISTING = 5
 
+	FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
+	FILE_FLAG_OVERLAPPED       = 0x40000000
+
 	HANDLE_FLAG_INHERIT    = 0x00000001
 	STARTF_USESTDHANDLES   = 0x00000100
 	STARTF_USESHOWWINDOW   = 0x00000001
@@ -134,6 +143,24 @@ const (
 )
 
 const (
+	FILE_NOTIFY_CHANGE_FILE_NAME = 1 << iota
+	FILE_NOTIFY_CHANGE_DIR_NAME
+	FILE_NOTIFY_CHANGE_ATTRIBUTES
+	FILE_NOTIFY_CHANGE_SIZE
+	FILE_NOTIFY_CHANGE_LAST_WRITE
+	FILE_NOTIFY_CHANGE_LAST_ACCESS
+	FILE_NOTIFY_CHANGE_CREATION
+)
+
+const (
+	FILE_ACTION_ADDED = iota + 1
+	FILE_ACTION_REMOVED
+	FILE_ACTION_MODIFIED
+	FILE_ACTION_RENAMED_OLD_NAME
+	FILE_ACTION_RENAMED_NEW_NAME
+)
+
+const (
 	// wincrypt.h
 	PROV_RSA_FULL                    = 1
 	PROV_RSA_SIG                     = 2
@@ -191,6 +218,13 @@ type Overlapped struct {
 	HEvent       Handle
 }
 
+type FileNotifyInformation struct {
+	NextEntryOffset uint32
+	Action          uint32
+	FileNameLength  uint32
+	FileName        uint16
+}
+
 type Filetime struct {
 	LowDateTime  uint32
 	HighDateTime uint32
@@ -339,9 +373,10 @@ const (
 	SOCK_RAW       = 3
 	SOCK_SEQPACKET = 5
 
-	IPPROTO_IP  = 0
-	IPPROTO_TCP = 6
-	IPPROTO_UDP = 17
+	IPPROTO_IP   = 0
+	IPPROTO_IPV6 = 0x29
+	IPPROTO_TCP  = 6
+	IPPROTO_UDP  = 17
 
 	SOL_SOCKET               = 0xffff
 	SO_REUSEADDR             = 4
@@ -353,8 +388,18 @@ const (
 	SO_SNDBUF                = 0x1001
 	SO_UPDATE_ACCEPT_CONTEXT = 0x700b
 
-	IPPROTO_IPV6 = 0x29
-	IPV6_V6ONLY  = 0x1b
+	IP_TOS             = 0x3
+	IP_TTL             = 0x4
+	IP_ADD_MEMBERSHIP  = 0xc
+	IP_DROP_MEMBERSHIP = 0xd
+
+	IPV6_V6ONLY         = 0x1b
+	IPV6_UNICAST_HOPS   = 0x4
+	IPV6_MULTICAST_IF   = 0x9
+	IPV6_MULTICAST_HOPS = 0xa
+	IPV6_MULTICAST_LOOP = 0xb
+	IPV6_JOIN_GROUP     = 0xc
+	IPV6_LEAVE_GROUP    = 0xd
 
 	SOMAXCONN = 0x7fffffff
 
@@ -366,9 +411,6 @@ const (
 
 	WSADESCRIPTION_LEN = 256
 	WSASYS_STATUS_LEN  = 128
-
-	IPV6_JOIN_GROUP  = 12
-	IPV6_LEAVE_GROUP = 13
 )
 
 type WSABuf struct {
@@ -411,6 +453,12 @@ type Hostent struct {
 	AddrList **byte
 }
 
+type Protoent struct {
+	Name    *byte
+	Aliases **byte
+	Proto   uint16
+}
+
 const (
 	DNS_TYPE_A       = 0x0001
 	DNS_TYPE_NS      = 0x0002
@@ -494,6 +542,11 @@ type DNSMXData struct {
 	Pad          uint16
 }
 
+type DNSTXTData struct {
+	StringCount uint16
+	StringArray [1]*uint16
+}
+
 type DNSRecord struct {
 	Next     *DNSRecord
 	Name     *uint16
@@ -611,3 +664,51 @@ type MibIfRow struct {
 	DescrLen        uint32
 	Descr           [MAXLEN_IFDESCR]byte
 }
+
+type CertContext struct {
+	EncodingType uint32
+	EncodedCert  *byte
+	Length       uint32
+	CertInfo     uintptr
+	Store        Handle
+}
+
+const (
+	HKEY_CLASSES_ROOT = 0x80000000 + iota
+	HKEY_CURRENT_USER
+	HKEY_LOCAL_MACHINE
+	HKEY_USERS
+	HKEY_PERFORMANCE_DATA
+	HKEY_CURRENT_CONFIG
+	HKEY_DYN_DATA
+
+	KEY_QUERY_VALUE        = 1
+	KEY_SET_VALUE          = 2
+	KEY_CREATE_SUB_KEY     = 4
+	KEY_ENUMERATE_SUB_KEYS = 8
+	KEY_NOTIFY             = 16
+	KEY_CREATE_LINK        = 32
+	KEY_WRITE              = 0x20006
+	KEY_EXECUTE            = 0x20019
+	KEY_READ               = 0x20019
+	KEY_WOW64_64KEY        = 0x0100
+	KEY_WOW64_32KEY        = 0x0200
+	KEY_ALL_ACCESS         = 0xf003f
+)
+
+const (
+	REG_NONE = iota
+	REG_SZ
+	REG_EXPAND_SZ
+	REG_BINARY
+	REG_DWORD_LITTLE_ENDIAN
+	REG_DWORD_BIG_ENDIAN
+	REG_LINK
+	REG_MULTI_SZ
+	REG_RESOURCE_LIST
+	REG_FULL_RESOURCE_DESCRIPTOR
+	REG_RESOURCE_REQUIREMENTS_LIST
+	REG_QWORD_LITTLE_ENDIAN
+	REG_DWORD = REG_DWORD_LITTLE_ENDIAN
+	REG_QWORD = REG_QWORD_LITTLE_ENDIAN
+)
diff --git a/src/pkg/syslog/Makefile b/src/pkg/syslog/Makefile
deleted file mode 100644
index 82baf72..0000000
--- a/src/pkg/syslog/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=syslog
-GOFILES=\
-	syslog.go\
-	syslog_unix.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/syslog/syslog.go b/src/pkg/syslog/syslog.go
deleted file mode 100644
index 6933372..0000000
--- a/src/pkg/syslog/syslog.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package syslog provides a simple interface to the system log service. It
-// can send messages to the syslog daemon using UNIX domain sockets, UDP, or
-// TCP connections.
-package syslog
-
-import (
-	"fmt"
-	"log"
-	"net"
-	"os"
-)
-
-type Priority int
-
-const (
-	// From /usr/include/sys/syslog.h.
-	// These are the same on Linux, BSD, and OS X.
-	LOG_EMERG Priority = iota
-	LOG_ALERT
-	LOG_CRIT
-	LOG_ERR
-	LOG_WARNING
-	LOG_NOTICE
-	LOG_INFO
-	LOG_DEBUG
-)
-
-// A Writer is a connection to a syslog server.
-type Writer struct {
-	priority Priority
-	prefix   string
-	conn     serverConn
-}
-
-type serverConn interface {
-	writeBytes(p Priority, prefix string, b []byte) (int, os.Error)
-	writeString(p Priority, prefix string, s string) (int, os.Error)
-	close() os.Error
-}
-
-type netConn struct {
-	conn net.Conn
-}
-
-// New establishes a new connection to the system log daemon.
-// Each write to the returned writer sends a log message with
-// the given priority and prefix.
-func New(priority Priority, prefix string) (w *Writer, err os.Error) {
-	return Dial("", "", priority, prefix)
-}
-
-// Dial establishes a connection to a log daemon by connecting
-// to address raddr on the network net.
-// Each write to the returned writer sends a log message with
-// the given priority and prefix.
-func Dial(network, raddr string, priority Priority, prefix string) (w *Writer, err os.Error) {
-	if prefix == "" {
-		prefix = os.Args[0]
-	}
-	var conn serverConn
-	if network == "" {
-		conn, err = unixSyslog()
-	} else {
-		var c net.Conn
-		c, err = net.Dial(network, raddr)
-		conn = netConn{c}
-	}
-	return &Writer{priority, prefix, conn}, err
-}
-
-// Write sends a log message to the syslog daemon.
-func (w *Writer) Write(b []byte) (int, os.Error) {
-	if w.priority > LOG_DEBUG || w.priority < LOG_EMERG {
-		return 0, os.EINVAL
-	}
-	return w.conn.writeBytes(w.priority, w.prefix, b)
-}
-
-func (w *Writer) writeString(p Priority, s string) (int, os.Error) {
-	return w.conn.writeString(p, w.prefix, s)
-}
-
-func (w *Writer) Close() os.Error { return w.conn.close() }
-
-// Emerg logs a message using the LOG_EMERG priority.
-func (w *Writer) Emerg(m string) (err os.Error) {
-	_, err = w.writeString(LOG_EMERG, m)
-	return err
-}
-// Crit logs a message using the LOG_CRIT priority.
-func (w *Writer) Crit(m string) (err os.Error) {
-	_, err = w.writeString(LOG_CRIT, m)
-	return err
-}
-// ERR logs a message using the LOG_ERR priority.
-func (w *Writer) Err(m string) (err os.Error) {
-	_, err = w.writeString(LOG_ERR, m)
-	return err
-}
-
-// Warning logs a message using the LOG_WARNING priority.
-func (w *Writer) Warning(m string) (err os.Error) {
-	_, err = w.writeString(LOG_WARNING, m)
-	return err
-}
-
-// Notice logs a message using the LOG_NOTICE priority.
-func (w *Writer) Notice(m string) (err os.Error) {
-	_, err = w.writeString(LOG_NOTICE, m)
-	return err
-}
-// Info logs a message using the LOG_INFO priority.
-func (w *Writer) Info(m string) (err os.Error) {
-	_, err = w.writeString(LOG_INFO, m)
-	return err
-}
-// Debug logs a message using the LOG_DEBUG priority.
-func (w *Writer) Debug(m string) (err os.Error) {
-	_, err = w.writeString(LOG_DEBUG, m)
-	return err
-}
-
-func (n netConn) writeBytes(p Priority, prefix string, b []byte) (int, os.Error) {
-	return fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, b)
-}
-
-func (n netConn) writeString(p Priority, prefix string, s string) (int, os.Error) {
-	return fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, s)
-}
-
-func (n netConn) close() os.Error {
-	return n.conn.Close()
-}
-
-// NewLogger provides an object that implements the full log.Logger interface,
-// but sends messages to Syslog instead; flag is passed as is to Logger;
-// priority will be used for all messages sent using this interface.
-// All messages are logged with priority p.
-func NewLogger(p Priority, flag int) *log.Logger {
-	s, err := New(p, "")
-	if err != nil {
-		return nil
-	}
-	return log.New(s, "", flag)
-}
diff --git a/src/pkg/syslog/syslog_test.go b/src/pkg/syslog/syslog_test.go
deleted file mode 100644
index 5c0b3e0..0000000
--- a/src/pkg/syslog/syslog_test.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-package syslog
-
-import (
-	"io"
-	"log"
-	"net"
-	"testing"
-)
-
-var serverAddr string
-
-func runSyslog(c net.PacketConn, done chan<- string) {
-	var buf [4096]byte
-	var rcvd string = ""
-	for {
-		n, _, err := c.ReadFrom(buf[0:])
-		if err != nil || n == 0 {
-			break
-		}
-		rcvd += string(buf[0:n])
-	}
-	done <- rcvd
-}
-
-func startServer(done chan<- string) {
-	c, e := net.ListenPacket("udp", "127.0.0.1:0")
-	if e != nil {
-		log.Fatalf("net.ListenPacket failed udp :0 %v", e)
-	}
-	serverAddr = c.LocalAddr().String()
-	c.SetReadTimeout(100e6) // 100ms
-	go runSyslog(c, done)
-}
-
-func skipNetTest(t *testing.T) bool {
-	if testing.Short() {
-		// Depends on syslog daemon running, and sometimes it's not.
-		t.Logf("skipping syslog test during -short")
-		return true
-	}
-	return false
-}
-
-func TestNew(t *testing.T) {
-	if skipNetTest(t) {
-		return
-	}
-	s, err := New(LOG_INFO, "")
-	if err != nil {
-		t.Fatalf("New() failed: %s", err)
-	}
-	// Don't send any messages.
-	s.Close()
-}
-
-func TestNewLogger(t *testing.T) {
-	if skipNetTest(t) {
-		return
-	}
-	f := NewLogger(LOG_INFO, 0)
-	if f == nil {
-		t.Error("NewLogger() failed")
-	}
-}
-
-func TestDial(t *testing.T) {
-	if skipNetTest(t) {
-		return
-	}
-	l, err := Dial("", "", LOG_ERR, "syslog_test")
-	if err != nil {
-		t.Fatalf("Dial() failed: %s", err)
-	}
-	l.Close()
-}
-
-func TestUDPDial(t *testing.T) {
-	done := make(chan string)
-	startServer(done)
-	l, err := Dial("udp", serverAddr, LOG_INFO, "syslog_test")
-	if err != nil {
-		t.Fatalf("syslog.Dial() failed: %s", err)
-	}
-	msg := "udp test"
-	l.Info(msg)
-	expected := "<6>syslog_test: udp test\n"
-	rcvd := <-done
-	if rcvd != expected {
-		t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected)
-	}
-}
-
-func TestWrite(t *testing.T) {
-	done := make(chan string)
-	startServer(done)
-	l, err := Dial("udp", serverAddr, LOG_ERR, "syslog_test")
-	if err != nil {
-		t.Fatalf("syslog.Dial() failed: %s", err)
-	}
-	msg := "write test"
-	_, err = io.WriteString(l, msg)
-	if err != nil {
-		t.Fatalf("WriteString() failed: %s", err)
-	}
-	expected := "<3>syslog_test: write test\n"
-	rcvd := <-done
-	if rcvd != expected {
-		t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected)
-	}
-}
diff --git a/src/pkg/syslog/syslog_unix.go b/src/pkg/syslog/syslog_unix.go
deleted file mode 100644
index b151671..0000000
--- a/src/pkg/syslog/syslog_unix.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syslog
-
-import (
-	"net"
-	"os"
-)
-
-// unixSyslog opens a connection to the syslog daemon running on the
-// local machine using a Unix domain socket.
-
-func unixSyslog() (conn serverConn, err os.Error) {
-	logTypes := []string{"unixgram", "unix"}
-	logPaths := []string{"/dev/log", "/var/run/syslog"}
-	var raddr string
-	for _, network := range logTypes {
-		for _, path := range logPaths {
-			raddr = path
-			conn, err := net.Dial(network, raddr)
-			if err != nil {
-				continue
-			} else {
-				return netConn{conn}, nil
-			}
-		}
-	}
-	return nil, os.NewError("Unix syslog delivery error")
-}
diff --git a/src/pkg/tabwriter/Makefile b/src/pkg/tabwriter/Makefile
deleted file mode 100644
index bdc8887..0000000
--- a/src/pkg/tabwriter/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=tabwriter
-GOFILES=\
-	tabwriter.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/tabwriter/tabwriter.go b/src/pkg/tabwriter/tabwriter.go
deleted file mode 100644
index 2f35d96..0000000
--- a/src/pkg/tabwriter/tabwriter.go
+++ /dev/null
@@ -1,561 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package tabwriter implements a write filter (tabwriter.Writer) that
-// translates tabbed columns in input into properly aligned text.
-//
-// The package is using the Elastic Tabstops algorithm described at
-// http://nickgravgaard.com/elastictabstops/index.html.
-//
-package tabwriter
-
-import (
-	"bytes"
-	"io"
-	"os"
-	"utf8"
-)
-
-// ----------------------------------------------------------------------------
-// Filter implementation
-
-// A cell represents a segment of text terminated by tabs or line breaks.
-// The text itself is stored in a separate buffer; cell only describes the
-// segment's size in bytes, its width in runes, and whether it's an htab
-// ('\t') terminated cell.
-//
-type cell struct {
-	size  int  // cell size in bytes
-	width int  // cell width in runes
-	htab  bool // true if the cell is terminated by an htab ('\t')
-}
-
-// A Writer is a filter that inserts padding around tab-delimited
-// columns in its input to align them in the output.
-//
-// The Writer treats incoming bytes as UTF-8 encoded text consisting
-// of cells terminated by (horizontal or vertical) tabs or line
-// breaks (newline or formfeed characters). Cells in adjacent lines
-// constitute a column. The Writer inserts padding as needed to
-// make all cells in a column have the same width, effectively
-// aligning the columns. It assumes that all characters have the
-// same width except for tabs for which a tabwidth must be specified.
-// Note that cells are tab-terminated, not tab-separated: trailing
-// non-tab text at the end of a line does not form a column cell.
-//
-// The Writer assumes that all Unicode code points have the same width;
-// this may not be true in some fonts.
-//
-// If DiscardEmptyColumns is set, empty columns that are terminated
-// entirely by vertical (or "soft") tabs are discarded. Columns
-// terminated by horizontal (or "hard") tabs are not affected by
-// this flag.
-//
-// If a Writer is configured to filter HTML, HTML tags and entities
-// are simply passed through. The widths of tags and entities are
-// assumed to be zero (tags) and one (entities) for formatting purposes.
-//
-// A segment of text may be escaped by bracketing it with Escape
-// characters. The tabwriter passes escaped text segments through
-// unchanged. In particular, it does not interpret any tabs or line
-// breaks within the segment. If the StripEscape flag is set, the
-// Escape characters are stripped from the output; otherwise they
-// are passed through as well. For the purpose of formatting, the
-// width of the escaped text is always computed excluding the Escape
-// characters.
-//
-// The formfeed character ('\f') acts like a newline but it also
-// terminates all columns in the current line (effectively calling
-// Flush). Cells in the next line start new columns. Unless found
-// inside an HTML tag or inside an escaped text segment, formfeed
-// characters appear as newlines in the output.
-//
-// The Writer must buffer input internally, because proper spacing
-// of one line may depend on the cells in future lines. Clients must
-// call Flush when done calling Write.
-//
-type Writer struct {
-	// configuration
-	output   io.Writer
-	minwidth int
-	tabwidth int
-	padding  int
-	padbytes [8]byte
-	flags    uint
-
-	// current state
-	buf     bytes.Buffer // collected text excluding tabs or line breaks
-	pos     int          // buffer position up to which cell.width of incomplete cell has been computed
-	cell    cell         // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections
-	endChar byte         // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0)
-	lines   [][]cell     // list of lines; each line is a list of cells
-	widths  []int        // list of column widths in runes - re-used during formatting
-}
-
-func (b *Writer) addLine() { b.lines = append(b.lines, []cell{}) }
-
-// Reset the current state.
-func (b *Writer) reset() {
-	b.buf.Reset()
-	b.pos = 0
-	b.cell = cell{}
-	b.endChar = 0
-	b.lines = b.lines[0:0]
-	b.widths = b.widths[0:0]
-	b.addLine()
-}
-
-// Internal representation (current state):
-//
-// - all text written is appended to buf; tabs and line breaks are stripped away
-// - at any given time there is a (possibly empty) incomplete cell at the end
-//   (the cell starts after a tab or line break)
-// - cell.size is the number of bytes belonging to the cell so far
-// - cell.width is text width in runes of that cell from the start of the cell to
-//   position pos; html tags and entities are excluded from this width if html
-//   filtering is enabled
-// - the sizes and widths of processed text are kept in the lines list
-//   which contains a list of cells for each line
-// - the widths list is a temporary list with current widths used during
-//   formatting; it is kept in Writer because it's re-used
-//
-//                    |<---------- size ---------->|
-//                    |                            |
-//                    |<- width ->|<- ignored ->|  |
-//                    |           |             |  |
-// [---processed---tab------------<tag>...</tag>...]
-// ^                  ^                         ^
-// |                  |                         |
-// buf                start of incomplete cell  pos
-
-// Formatting can be controlled with these flags.
-const (
-	// Ignore html tags and treat entities (starting with '&'
-	// and ending in ';') as single characters (width = 1).
-	FilterHTML uint = 1 << iota
-
-	// Strip Escape characters bracketing escaped text segments
-	// instead of passing them through unchanged with the text.
-	StripEscape
-
-	// Force right-alignment of cell content.
-	// Default is left-alignment.
-	AlignRight
-
-	// Handle empty columns as if they were not present in
-	// the input in the first place.
-	DiscardEmptyColumns
-
-	// Always use tabs for indentation columns (i.e., padding of
-	// leading empty cells on the left) independent of padchar.
-	TabIndent
-
-	// Print a vertical bar ('|') between columns (after formatting).
-	// Discarded columns appear as zero-width columns ("||").
-	Debug
-)
-
-// A Writer must be initialized with a call to Init. The first parameter (output)
-// specifies the filter output. The remaining parameters control the formatting:
-//
-//	minwidth	minimal cell width including any padding
-//	tabwidth	width of tab characters (equivalent number of spaces)
-//	padding		padding added to a cell before computing its width
-//	padchar		ASCII char used for padding
-//			if padchar == '\t', the Writer will assume that the
-//			width of a '\t' in the formatted output is tabwidth,
-//			and cells are left-aligned independent of align_left
-//			(for correct-looking results, tabwidth must correspond
-//			to the tab width in the viewer displaying the result)
-//	flags		formatting control
-//
-// To format in tab-separated columns with a tab stop of 8:
-//	b.Init(w, 8, 1, 8, '\t', 0);
-//
-// To format in space-separated columns with at least 4 spaces between columns:
-//	b.Init(w, 0, 4, 8, ' ', 0);
-//
-func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
-	if minwidth < 0 || tabwidth < 0 || padding < 0 {
-		panic("negative minwidth, tabwidth, or padding")
-	}
-	b.output = output
-	b.minwidth = minwidth
-	b.tabwidth = tabwidth
-	b.padding = padding
-	for i := range b.padbytes {
-		b.padbytes[i] = padchar
-	}
-	if padchar == '\t' {
-		// tab padding enforces left-alignment
-		flags &^= AlignRight
-	}
-	b.flags = flags
-
-	b.reset()
-
-	return b
-}
-
-// debugging support (keep code around)
-func (b *Writer) dump() {
-	pos := 0
-	for i, line := range b.lines {
-		print("(", i, ") ")
-		for _, c := range line {
-			print("[", string(b.buf.Bytes()[pos:pos+c.size]), "]")
-			pos += c.size
-		}
-		print("\n")
-	}
-	print("\n")
-}
-
-// local error wrapper so we can distinguish os.Errors we want to return
-// as errors from genuine panics (which we don't want to return as errors)
-type osError struct {
-	err os.Error
-}
-
-func (b *Writer) write0(buf []byte) {
-	n, err := b.output.Write(buf)
-	if n != len(buf) && err == nil {
-		err = os.EIO
-	}
-	if err != nil {
-		panic(osError{err})
-	}
-}
-
-func (b *Writer) writeN(src []byte, n int) {
-	for n > len(src) {
-		b.write0(src)
-		n -= len(src)
-	}
-	b.write0(src[0:n])
-}
-
-var (
-	newline = []byte{'\n'}
-	tabs    = []byte("\t\t\t\t\t\t\t\t")
-)
-
-func (b *Writer) writePadding(textw, cellw int, useTabs bool) {
-	if b.padbytes[0] == '\t' || useTabs {
-		// padding is done with tabs
-		if b.tabwidth == 0 {
-			return // tabs have no width - can't do any padding
-		}
-		// make cellw the smallest multiple of b.tabwidth
-		cellw = (cellw + b.tabwidth - 1) / b.tabwidth * b.tabwidth
-		n := cellw - textw // amount of padding
-		if n < 0 {
-			panic("internal error")
-		}
-		b.writeN(tabs, (n+b.tabwidth-1)/b.tabwidth)
-		return
-	}
-
-	// padding is done with non-tab characters
-	b.writeN(b.padbytes[0:], cellw-textw)
-}
-
-var vbar = []byte{'|'}
-
-func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int) {
-	pos = pos0
-	for i := line0; i < line1; i++ {
-		line := b.lines[i]
-
-		// if TabIndent is set, use tabs to pad leading empty cells
-		useTabs := b.flags&TabIndent != 0
-
-		for j, c := range line {
-			if j > 0 && b.flags&Debug != 0 {
-				// indicate column break
-				b.write0(vbar)
-			}
-
-			if c.size == 0 {
-				// empty cell
-				if j < len(b.widths) {
-					b.writePadding(c.width, b.widths[j], useTabs)
-				}
-			} else {
-				// non-empty cell
-				useTabs = false
-				if b.flags&AlignRight == 0 { // align left
-					b.write0(b.buf.Bytes()[pos : pos+c.size])
-					pos += c.size
-					if j < len(b.widths) {
-						b.writePadding(c.width, b.widths[j], false)
-					}
-				} else { // align right
-					if j < len(b.widths) {
-						b.writePadding(c.width, b.widths[j], false)
-					}
-					b.write0(b.buf.Bytes()[pos : pos+c.size])
-					pos += c.size
-				}
-			}
-		}
-
-		if i+1 == len(b.lines) {
-			// last buffered line - we don't have a newline, so just write
-			// any outstanding buffered data
-			b.write0(b.buf.Bytes()[pos : pos+b.cell.size])
-			pos += b.cell.size
-		} else {
-			// not the last line - write newline
-			b.write0(newline)
-		}
-	}
-	return
-}
-
-// Format the text between line0 and line1 (excluding line1); pos
-// is the buffer position corresponding to the beginning of line0.
-// Returns the buffer position corresponding to the beginning of
-// line1 and an error, if any.
-//
-func (b *Writer) format(pos0 int, line0, line1 int) (pos int) {
-	pos = pos0
-	column := len(b.widths)
-	for this := line0; this < line1; this++ {
-		line := b.lines[this]
-
-		if column < len(line)-1 {
-			// cell exists in this column => this line
-			// has more cells than the previous line
-			// (the last cell per line is ignored because cells are
-			// tab-terminated; the last cell per line describes the
-			// text before the newline/formfeed and does not belong
-			// to a column)
-
-			// print unprinted lines until beginning of block
-			pos = b.writeLines(pos, line0, this)
-			line0 = this
-
-			// column block begin
-			width := b.minwidth // minimal column width
-			discardable := true // true if all cells in this column are empty and "soft"
-			for ; this < line1; this++ {
-				line = b.lines[this]
-				if column < len(line)-1 {
-					// cell exists in this column
-					c := line[column]
-					// update width
-					if w := c.width + b.padding; w > width {
-						width = w
-					}
-					// update discardable
-					if c.width > 0 || c.htab {
-						discardable = false
-					}
-				} else {
-					break
-				}
-			}
-			// column block end
-
-			// discard empty columns if necessary
-			if discardable && b.flags&DiscardEmptyColumns != 0 {
-				width = 0
-			}
-
-			// format and print all columns to the right of this column
-			// (we know the widths of this column and all columns to the left)
-			b.widths = append(b.widths, width) // push width
-			pos = b.format(pos, line0, this)
-			b.widths = b.widths[0 : len(b.widths)-1] // pop width
-			line0 = this
-		}
-	}
-
-	// print unprinted lines until end
-	return b.writeLines(pos, line0, line1)
-}
-
-// Append text to current cell.
-func (b *Writer) append(text []byte) {
-	b.buf.Write(text)
-	b.cell.size += len(text)
-}
-
-// Update the cell width.
-func (b *Writer) updateWidth() {
-	b.cell.width += utf8.RuneCount(b.buf.Bytes()[b.pos:b.buf.Len()])
-	b.pos = b.buf.Len()
-}
-
-// To escape a text segment, bracket it with Escape characters.
-// For instance, the tab in this string "Ignore this tab: \xff\t\xff"
-// does not terminate a cell and constitutes a single character of
-// width one for formatting purposes.
-//
-// The value 0xff was chosen because it cannot appear in a valid UTF-8 sequence.
-//
-const Escape = '\xff'
-
-// Start escaped mode.
-func (b *Writer) startEscape(ch byte) {
-	switch ch {
-	case Escape:
-		b.endChar = Escape
-	case '<':
-		b.endChar = '>'
-	case '&':
-		b.endChar = ';'
-	}
-}
-
-// Terminate escaped mode. If the escaped text was an HTML tag, its width
-// is assumed to be zero for formatting purposes; if it was an HTML entity,
-// its width is assumed to be one. In all other cases, the width is the
-// unicode width of the text.
-//
-func (b *Writer) endEscape() {
-	switch b.endChar {
-	case Escape:
-		b.updateWidth()
-		if b.flags&StripEscape == 0 {
-			b.cell.width -= 2 // don't count the Escape chars
-		}
-	case '>': // tag of zero width
-	case ';':
-		b.cell.width++ // entity, count as one rune
-	}
-	b.pos = b.buf.Len()
-	b.endChar = 0
-}
-
-// Terminate the current cell by adding it to the list of cells of the
-// current line. Returns the number of cells in that line.
-//
-func (b *Writer) terminateCell(htab bool) int {
-	b.cell.htab = htab
-	line := &b.lines[len(b.lines)-1]
-	*line = append(*line, b.cell)
-	b.cell = cell{}
-	return len(*line)
-}
-
-func handlePanic(err *os.Error) {
-	if e := recover(); e != nil {
-		*err = e.(osError).err // re-panics if it's not a local osError
-	}
-}
-
-// Flush should be called after the last call to Write to ensure
-// that any data buffered in the Writer is written to output. Any
-// incomplete escape sequence at the end is simply considered
-// complete for formatting purposes.
-//
-func (b *Writer) Flush() (err os.Error) {
-	defer b.reset() // even in the presence of errors
-	defer handlePanic(&err)
-
-	// add current cell if not empty
-	if b.cell.size > 0 {
-		if b.endChar != 0 {
-			// inside escape - terminate it even if incomplete
-			b.endEscape()
-		}
-		b.terminateCell(false)
-	}
-
-	// format contents of buffer
-	b.format(0, 0, len(b.lines))
-
-	return
-}
-
-var hbar = []byte("---\n")
-
-// Write writes buf to the writer b.
-// The only errors returned are ones encountered
-// while writing to the underlying output stream.
-//
-func (b *Writer) Write(buf []byte) (n int, err os.Error) {
-	defer handlePanic(&err)
-
-	// split text into cells
-	n = 0
-	for i, ch := range buf {
-		if b.endChar == 0 {
-			// outside escape
-			switch ch {
-			case '\t', '\v', '\n', '\f':
-				// end of cell
-				b.append(buf[n:i])
-				b.updateWidth()
-				n = i + 1 // ch consumed
-				ncells := b.terminateCell(ch == '\t')
-				if ch == '\n' || ch == '\f' {
-					// terminate line
-					b.addLine()
-					if ch == '\f' || ncells == 1 {
-						// A '\f' always forces a flush. Otherwise, if the previous
-						// line has only one cell which does not have an impact on
-						// the formatting of the following lines (the last cell per
-						// line is ignored by format()), thus we can flush the
-						// Writer contents.
-						if err = b.Flush(); err != nil {
-							return
-						}
-						if ch == '\f' && b.flags&Debug != 0 {
-							// indicate section break
-							b.write0(hbar)
-						}
-					}
-				}
-
-			case Escape:
-				// start of escaped sequence
-				b.append(buf[n:i])
-				b.updateWidth()
-				n = i
-				if b.flags&StripEscape != 0 {
-					n++ // strip Escape
-				}
-				b.startEscape(Escape)
-
-			case '<', '&':
-				// possibly an html tag/entity
-				if b.flags&FilterHTML != 0 {
-					// begin of tag/entity
-					b.append(buf[n:i])
-					b.updateWidth()
-					n = i
-					b.startEscape(ch)
-				}
-			}
-
-		} else {
-			// inside escape
-			if ch == b.endChar {
-				// end of tag/entity
-				j := i + 1
-				if ch == Escape && b.flags&StripEscape != 0 {
-					j = i // strip Escape
-				}
-				b.append(buf[n:j])
-				n = i + 1 // ch consumed
-				b.endEscape()
-			}
-		}
-	}
-
-	// append leftover text
-	b.append(buf[n:])
-	n = len(buf)
-	return
-}
-
-// NewWriter allocates and initializes a new tabwriter.Writer.
-// The parameters are the same as for the the Init function.
-//
-func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
-	return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags)
-}
diff --git a/src/pkg/tabwriter/tabwriter_test.go b/src/pkg/tabwriter/tabwriter_test.go
deleted file mode 100644
index 6ef7e80..0000000
--- a/src/pkg/tabwriter/tabwriter_test.go
+++ /dev/null
@@ -1,615 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package tabwriter
-
-import (
-	"io"
-	"os"
-	"testing"
-)
-
-type buffer struct {
-	a []byte
-}
-
-func (b *buffer) init(n int) { b.a = make([]byte, n)[0:0] }
-
-func (b *buffer) clear() { b.a = b.a[0:0] }
-
-func (b *buffer) Write(buf []byte) (written int, err os.Error) {
-	n := len(b.a)
-	m := len(buf)
-	if n+m <= cap(b.a) {
-		b.a = b.a[0 : n+m]
-		for i := 0; i < m; i++ {
-			b.a[n+i] = buf[i]
-		}
-	} else {
-		panic("buffer.Write: buffer too small")
-	}
-	return len(buf), nil
-}
-
-func (b *buffer) String() string { return string(b.a) }
-
-func write(t *testing.T, testname string, w *Writer, src string) {
-	written, err := io.WriteString(w, src)
-	if err != nil {
-		t.Errorf("--- test: %s\n--- src:\n%q\n--- write error: %v\n", testname, src, err)
-	}
-	if written != len(src) {
-		t.Errorf("--- test: %s\n--- src:\n%q\n--- written = %d, len(src) = %d\n", testname, src, written, len(src))
-	}
-}
-
-func verify(t *testing.T, testname string, w *Writer, b *buffer, src, expected string) {
-	err := w.Flush()
-	if err != nil {
-		t.Errorf("--- test: %s\n--- src:\n%q\n--- flush error: %v\n", testname, src, err)
-	}
-
-	res := b.String()
-	if res != expected {
-		t.Errorf("--- test: %s\n--- src:\n%q\n--- found:\n%q\n--- expected:\n%q\n", testname, src, res, expected)
-	}
-}
-
-func check(t *testing.T, testname string, minwidth, tabwidth, padding int, padchar byte, flags uint, src, expected string) {
-	var b buffer
-	b.init(1000)
-
-	var w Writer
-	w.Init(&b, minwidth, tabwidth, padding, padchar, flags)
-
-	// write all at once
-	title := testname + " (written all at once)"
-	b.clear()
-	write(t, title, &w, src)
-	verify(t, title, &w, &b, src, expected)
-
-	// write byte-by-byte
-	title = testname + " (written byte-by-byte)"
-	b.clear()
-	for i := 0; i < len(src); i++ {
-		write(t, title, &w, src[i:i+1])
-	}
-	verify(t, title, &w, &b, src, expected)
-
-	// write using Fibonacci slice sizes
-	title = testname + " (written in fibonacci slices)"
-	b.clear()
-	for i, d := 0, 0; i < len(src); {
-		write(t, title, &w, src[i:i+d])
-		i, d = i+d, d+1
-		if i+d > len(src) {
-			d = len(src) - i
-		}
-	}
-	verify(t, title, &w, &b, src, expected)
-}
-
-var tests = []struct {
-	testname                    string
-	minwidth, tabwidth, padding int
-	padchar                     byte
-	flags                       uint
-	src, expected               string
-}{
-	{
-		"1a",
-		8, 0, 1, '.', 0,
-		"",
-		"",
-	},
-
-	{
-		"1a debug",
-		8, 0, 1, '.', Debug,
-		"",
-		"",
-	},
-
-	{
-		"1b esc stripped",
-		8, 0, 1, '.', StripEscape,
-		"\xff\xff",
-		"",
-	},
-
-	{
-		"1b esc",
-		8, 0, 1, '.', 0,
-		"\xff\xff",
-		"\xff\xff",
-	},
-
-	{
-		"1c esc stripped",
-		8, 0, 1, '.', StripEscape,
-		"\xff\t\xff",
-		"\t",
-	},
-
-	{
-		"1c esc",
-		8, 0, 1, '.', 0,
-		"\xff\t\xff",
-		"\xff\t\xff",
-	},
-
-	{
-		"1d esc stripped",
-		8, 0, 1, '.', StripEscape,
-		"\xff\"foo\t\n\tbar\"\xff",
-		"\"foo\t\n\tbar\"",
-	},
-
-	{
-		"1d esc",
-		8, 0, 1, '.', 0,
-		"\xff\"foo\t\n\tbar\"\xff",
-		"\xff\"foo\t\n\tbar\"\xff",
-	},
-
-	{
-		"1e esc stripped",
-		8, 0, 1, '.', StripEscape,
-		"abc\xff\tdef", // unterminated escape
-		"abc\tdef",
-	},
-
-	{
-		"1e esc",
-		8, 0, 1, '.', 0,
-		"abc\xff\tdef", // unterminated escape
-		"abc\xff\tdef",
-	},
-
-	{
-		"2",
-		8, 0, 1, '.', 0,
-		"\n\n\n",
-		"\n\n\n",
-	},
-
-	{
-		"3",
-		8, 0, 1, '.', 0,
-		"a\nb\nc",
-		"a\nb\nc",
-	},
-
-	{
-		"4a",
-		8, 0, 1, '.', 0,
-		"\t", // '\t' terminates an empty cell on last line - nothing to print
-		"",
-	},
-
-	{
-		"4b",
-		8, 0, 1, '.', AlignRight,
-		"\t", // '\t' terminates an empty cell on last line - nothing to print
-		"",
-	},
-
-	{
-		"5",
-		8, 0, 1, '.', 0,
-		"*\t*",
-		"*.......*",
-	},
-
-	{
-		"5b",
-		8, 0, 1, '.', 0,
-		"*\t*\n",
-		"*.......*\n",
-	},
-
-	{
-		"5c",
-		8, 0, 1, '.', 0,
-		"*\t*\t",
-		"*.......*",
-	},
-
-	{
-		"5c debug",
-		8, 0, 1, '.', Debug,
-		"*\t*\t",
-		"*.......|*",
-	},
-
-	{
-		"5d",
-		8, 0, 1, '.', AlignRight,
-		"*\t*\t",
-		".......**",
-	},
-
-	{
-		"6",
-		8, 0, 1, '.', 0,
-		"\t\n",
-		"........\n",
-	},
-
-	{
-		"7a",
-		8, 0, 1, '.', 0,
-		"a) foo",
-		"a) foo",
-	},
-
-	{
-		"7b",
-		8, 0, 1, ' ', 0,
-		"b) foo\tbar",
-		"b) foo  bar",
-	},
-
-	{
-		"7c",
-		8, 0, 1, '.', 0,
-		"c) foo\tbar\t",
-		"c) foo..bar",
-	},
-
-	{
-		"7d",
-		8, 0, 1, '.', 0,
-		"d) foo\tbar\n",
-		"d) foo..bar\n",
-	},
-
-	{
-		"7e",
-		8, 0, 1, '.', 0,
-		"e) foo\tbar\t\n",
-		"e) foo..bar.....\n",
-	},
-
-	{
-		"7f",
-		8, 0, 1, '.', FilterHTML,
-		"f) f<o\t<b>bar</b>\t\n",
-		"f) f<o..<b>bar</b>.....\n",
-	},
-
-	{
-		"7g",
-		8, 0, 1, '.', FilterHTML,
-		"g) f<o\t<b>bar</b>\t non-terminated entity &amp",
-		"g) f<o..<b>bar</b>..... non-terminated entity &amp",
-	},
-
-	{
-		"7g debug",
-		8, 0, 1, '.', FilterHTML | Debug,
-		"g) f<o\t<b>bar</b>\t non-terminated entity &amp",
-		"g) f<o..|<b>bar</b>.....| non-terminated entity &amp",
-	},
-
-	{
-		"8",
-		8, 0, 1, '*', 0,
-		"Hello, world!\n",
-		"Hello, world!\n",
-	},
-
-	{
-		"9a",
-		1, 0, 0, '.', 0,
-		"1\t2\t3\t4\n" +
-			"11\t222\t3333\t44444\n",
-
-		"1.2..3...4\n" +
-			"11222333344444\n",
-	},
-
-	{
-		"9b",
-		1, 0, 0, '.', FilterHTML,
-		"1\t2<!---\f--->\t3\t4\n" + // \f inside HTML is ignored
-			"11\t222\t3333\t44444\n",
-
-		"1.2<!---\f--->..3...4\n" +
-			"11222333344444\n",
-	},
-
-	{
-		"9c",
-		1, 0, 0, '.', 0,
-		"1\t2\t3\t4\f" + // \f causes a newline and flush
-			"11\t222\t3333\t44444\n",
-
-		"1234\n" +
-			"11222333344444\n",
-	},
-
-	{
-		"9c debug",
-		1, 0, 0, '.', Debug,
-		"1\t2\t3\t4\f" + // \f causes a newline and flush
-			"11\t222\t3333\t44444\n",
-
-		"1|2|3|4\n" +
-			"---\n" +
-			"11|222|3333|44444\n",
-	},
-
-	{
-		"10a",
-		5, 0, 0, '.', 0,
-		"1\t2\t3\t4\n",
-		"1....2....3....4\n",
-	},
-
-	{
-		"10b",
-		5, 0, 0, '.', 0,
-		"1\t2\t3\t4\t\n",
-		"1....2....3....4....\n",
-	},
-
-	{
-		"11",
-		8, 0, 1, '.', 0,
-		"本\tb\tc\n" +
-			"aa\t\u672c\u672c\u672c\tcccc\tddddd\n" +
-			"aaa\tbbbb\n",
-
-		"本.......b.......c\n" +
-			"aa......本本本.....cccc....ddddd\n" +
-			"aaa.....bbbb\n",
-	},
-
-	{
-		"12a",
-		8, 0, 1, ' ', AlignRight,
-		"a\tè\tc\t\n" +
-			"aa\tèèè\tcccc\tddddd\t\n" +
-			"aaa\tèèèè\t\n",
-
-		"       a       è       c\n" +
-			"      aa     èèè    cccc   ddddd\n" +
-			"     aaa    èèèè\n",
-	},
-
-	{
-		"12b",
-		2, 0, 0, ' ', 0,
-		"a\tb\tc\n" +
-			"aa\tbbb\tcccc\n" +
-			"aaa\tbbbb\n",
-
-		"a  b  c\n" +
-			"aa bbbcccc\n" +
-			"aaabbbb\n",
-	},
-
-	{
-		"12c",
-		8, 0, 1, '_', 0,
-		"a\tb\tc\n" +
-			"aa\tbbb\tcccc\n" +
-			"aaa\tbbbb\n",
-
-		"a_______b_______c\n" +
-			"aa______bbb_____cccc\n" +
-			"aaa_____bbbb\n",
-	},
-
-	{
-		"13a",
-		4, 0, 1, '-', 0,
-		"4444\t日本語\t22\t1\t333\n" +
-			"999999999\t22\n" +
-			"7\t22\n" +
-			"\t\t\t88888888\n" +
-			"\n" +
-			"666666\t666666\t666666\t4444\n" +
-			"1\t1\t999999999\t0000000000\n",
-
-		"4444------日本語-22--1---333\n" +
-			"999999999-22\n" +
-			"7---------22\n" +
-			"------------------88888888\n" +
-			"\n" +
-			"666666-666666-666666----4444\n" +
-			"1------1------999999999-0000000000\n",
-	},
-
-	{
-		"13b",
-		4, 0, 3, '.', 0,
-		"4444\t333\t22\t1\t333\n" +
-			"999999999\t22\n" +
-			"7\t22\n" +
-			"\t\t\t88888888\n" +
-			"\n" +
-			"666666\t666666\t666666\t4444\n" +
-			"1\t1\t999999999\t0000000000\n",
-
-		"4444........333...22...1...333\n" +
-			"999999999...22\n" +
-			"7...........22\n" +
-			"....................88888888\n" +
-			"\n" +
-			"666666...666666...666666......4444\n" +
-			"1........1........999999999...0000000000\n",
-	},
-
-	{
-		"13c",
-		8, 8, 1, '\t', FilterHTML,
-		"4444\t333\t22\t1\t333\n" +
-			"999999999\t22\n" +
-			"7\t22\n" +
-			"\t\t\t88888888\n" +
-			"\n" +
-			"666666\t666666\t666666\t4444\n" +
-			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
-
-		"4444\t\t333\t22\t1\t333\n" +
-			"999999999\t22\n" +
-			"7\t\t22\n" +
-			"\t\t\t\t88888888\n" +
-			"\n" +
-			"666666\t666666\t666666\t\t4444\n" +
-			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
-	},
-
-	{
-		"14",
-		1, 0, 2, ' ', AlignRight,
-		".0\t.3\t2.4\t-5.1\t\n" +
-			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
-			"5.1\t12.0\t2.4\t-7.0\t\n" +
-			".0\t0.0\t332.0\t8908.0\t\n" +
-			".0\t-.3\t456.4\t22.1\t\n" +
-			".0\t1.2\t44.4\t-13.3\t\t",
-
-		"    .0          .3    2.4    -5.1\n" +
-			"  23.0  12345678.9    2.4  -989.4\n" +
-			"   5.1        12.0    2.4    -7.0\n" +
-			"    .0         0.0  332.0  8908.0\n" +
-			"    .0         -.3  456.4    22.1\n" +
-			"    .0         1.2   44.4   -13.3",
-	},
-
-	{
-		"14 debug",
-		1, 0, 2, ' ', AlignRight | Debug,
-		".0\t.3\t2.4\t-5.1\t\n" +
-			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
-			"5.1\t12.0\t2.4\t-7.0\t\n" +
-			".0\t0.0\t332.0\t8908.0\t\n" +
-			".0\t-.3\t456.4\t22.1\t\n" +
-			".0\t1.2\t44.4\t-13.3\t\t",
-
-		"    .0|          .3|    2.4|    -5.1|\n" +
-			"  23.0|  12345678.9|    2.4|  -989.4|\n" +
-			"   5.1|        12.0|    2.4|    -7.0|\n" +
-			"    .0|         0.0|  332.0|  8908.0|\n" +
-			"    .0|         -.3|  456.4|    22.1|\n" +
-			"    .0|         1.2|   44.4|   -13.3|",
-	},
-
-	{
-		"15a",
-		4, 0, 0, '.', 0,
-		"a\t\tb",
-		"a.......b",
-	},
-
-	{
-		"15b",
-		4, 0, 0, '.', DiscardEmptyColumns,
-		"a\t\tb", // htabs - do not discard column
-		"a.......b",
-	},
-
-	{
-		"15c",
-		4, 0, 0, '.', DiscardEmptyColumns,
-		"a\v\vb",
-		"a...b",
-	},
-
-	{
-		"15d",
-		4, 0, 0, '.', AlignRight | DiscardEmptyColumns,
-		"a\v\vb",
-		"...ab",
-	},
-
-	{
-		"16a",
-		100, 100, 0, '\t', 0,
-		"a\tb\t\td\n" +
-			"a\tb\t\td\te\n" +
-			"a\n" +
-			"a\tb\tc\td\n" +
-			"a\tb\tc\td\te\n",
-
-		"a\tb\t\td\n" +
-			"a\tb\t\td\te\n" +
-			"a\n" +
-			"a\tb\tc\td\n" +
-			"a\tb\tc\td\te\n",
-	},
-
-	{
-		"16b",
-		100, 100, 0, '\t', DiscardEmptyColumns,
-		"a\vb\v\vd\n" +
-			"a\vb\v\vd\ve\n" +
-			"a\n" +
-			"a\vb\vc\vd\n" +
-			"a\vb\vc\vd\ve\n",
-
-		"a\tb\td\n" +
-			"a\tb\td\te\n" +
-			"a\n" +
-			"a\tb\tc\td\n" +
-			"a\tb\tc\td\te\n",
-	},
-
-	{
-		"16b debug",
-		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
-		"a\vb\v\vd\n" +
-			"a\vb\v\vd\ve\n" +
-			"a\n" +
-			"a\vb\vc\vd\n" +
-			"a\vb\vc\vd\ve\n",
-
-		"a\t|b\t||d\n" +
-			"a\t|b\t||d\t|e\n" +
-			"a\n" +
-			"a\t|b\t|c\t|d\n" +
-			"a\t|b\t|c\t|d\t|e\n",
-	},
-
-	{
-		"16c",
-		100, 100, 0, '\t', DiscardEmptyColumns,
-		"a\tb\t\td\n" + // hard tabs - do not discard column
-			"a\tb\t\td\te\n" +
-			"a\n" +
-			"a\tb\tc\td\n" +
-			"a\tb\tc\td\te\n",
-
-		"a\tb\t\td\n" +
-			"a\tb\t\td\te\n" +
-			"a\n" +
-			"a\tb\tc\td\n" +
-			"a\tb\tc\td\te\n",
-	},
-
-	{
-		"16c debug",
-		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
-		"a\tb\t\td\n" + // hard tabs - do not discard column
-			"a\tb\t\td\te\n" +
-			"a\n" +
-			"a\tb\tc\td\n" +
-			"a\tb\tc\td\te\n",
-
-		"a\t|b\t|\t|d\n" +
-			"a\t|b\t|\t|d\t|e\n" +
-			"a\n" +
-			"a\t|b\t|c\t|d\n" +
-			"a\t|b\t|c\t|d\t|e\n",
-	},
-}
-
-func Test(t *testing.T) {
-	for _, e := range tests {
-		check(t, e.testname, e.minwidth, e.tabwidth, e.padding, e.padchar, e.flags, e.src, e.expected)
-	}
-}
diff --git a/src/pkg/template/Makefile b/src/pkg/template/Makefile
deleted file mode 100644
index 730b287..0000000
--- a/src/pkg/template/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=template
-GOFILES=\
-	doc.go\
-	exec.go\
-	funcs.go\
-	helper.go\
-	parse.go\
-	set.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/template/doc.go b/src/pkg/template/doc.go
deleted file mode 100644
index a52f32d..0000000
--- a/src/pkg/template/doc.go
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright 2011 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 template implements data-driven templates for generating textual output
-such as HTML.
-
-Templates are executed by applying them to a data structure. Annotations in the
-template refer to elements of the data structure (typically a field of a struct
-or a key in a map) to control execution and derive values to be displayed.
-Execution of the template walks the structure and sets the cursor, represented
-by a period '.' and called "dot", to the value at the current location in the
-structure as execution proceeds.
-
-The input text for a template is UTF-8-encoded text in any format.
-"Actions"--data evaluations or control structures--are delimited by
-"{{" and "}}"; all text outside actions is copied to the output unchanged.
-Actions may not span newlines, although comments can.
-
-Once constructed, templates and template sets can be executed safely in
-parallel.
-
-Actions
-
-Here is the list of actions. "Arguments" and "pipelines" are evaluations of
-data, defined in detail below.
-
-*/
-//	{{/* a comment */}}
-//		A comment; discarded. May contain newlines.
-//		Comments do not nest.
-/*
-
-	{{pipeline}}
-		The default textual representation of the value of the pipeline
-		is copied to the output.
-
-	{{if pipeline}} T1 {{end}}
-		If the value of the pipeline is empty, no output is generated;
-		otherwise, T1 is executed.  The empty values are false, 0, any
-		nil pointer or interface value, and any array, slice, map, or
-		string of length zero.
-		Dot is unaffected.
-
-	{{if pipeline}} T1 {{else}} T0 {{end}}
-		If the value of the pipeline is empty, T0 is executed;
-		otherwise, T1 is executed.  Dot is unaffected.
-
-	{{range pipeline}} T1 {{end}}
-		The value of the pipeline must be an array, slice, or map. If
-		the value of the pipeline has length zero, nothing is output;
-		otherwise, dot is set to the successive elements of the array,
-		slice, or map and T1 is executed.
-
-	{{range pipeline}} T1 {{else}} T0 {{end}}
-		The value of the pipeline must be an array, slice, or map. If
-		the value of the pipeline has length zero, dot is unaffected and
-		T0 is executed; otherwise, dot is set to the successive elements
-		of the array, slice, or map and T1 is executed.
-
-	{{template "name"}}
-		The template with the specified name is executed with nil data.
-
-	{{template "name" pipeline}}
-		The template with the specified name is executed with dot set
-		to the value of the pipeline.
-
-	{{with pipeline}} T1 {{end}}
-		If the value of the pipeline is empty, no output is generated;
-		otherwise, dot is set to the value of the pipeline and T1 is
-		executed.
-
-	{{with pipeline}} T1 {{else}} T0 {{end}}
-		If the value of the pipeline is empty, dot is unaffected and T0
-		is executed; otherwise, dot is set to the value of the pipeline
-		and T1 is executed.
-
-Arguments
-
-An argument is a simple value, denoted by one of the following.
-
-	- A boolean, string, character, integer, floating-point, imaginary
-	  or complex constant in Go syntax. These behave like Go's untyped
-	  constants, although raw strings may not span newlines.
-	- The character '.' (period):
-		.
-	  The result is the value of dot.
-	- A variable name, which is a (possibly empty) alphanumeric string
-	  preceded by a dollar sign, such as
-		$piOver2
-	  or
-		$
-	  The result is the value of the variable.
-	  Variables are described below.
-	- The name of a field of the data, which must be a struct, preceded
-	  by a period, such as
-		.Field
-	  The result is the value of the field. Field invocations may be
-	  chained:
-	    .Field1.Field2
-	  Fields can also be evaluated on variables, including chaining:
-	    $x.Field1.Field2
-	- The name of a key of the data, which must be a map, preceded
-	  by a period, such as
-		.Key
-	  The result is the map element value indexed by the key.
-	  Key invocations may be chained and combined with fields to any
-	  depth:
-	    .Field1.Key1.Field2.Key2
-	  Although the key must be an alphanumeric identifier, unlike with
-	  field names they do not need to start with an upper case letter.
-	  Keys can also be evaluated on variables, including chaining:
-	    $x.key1.key2
-	- The name of a niladic method of the data, preceded by a period,
-	  such as
-		.Method
-	  The result is the value of invoking the method with dot as the
-	  receiver, dot.Method(). Such a method must have one return value (of
-	  any type) or two return values, the second of which is an os.Error.
-	  If it has two and the returned error is non-nil, execution terminates
-	  and an error is returned to the caller as the value of Execute.
-	  Method invocations may be chained and combined with fields and keys
-	  to any depth:
-	    .Field1.Key1.Method1.Field2.Key2.Method2
-	  Methods can also be evaluated on variables, including chaining:
-	    $x.Method1.Field
-	- The name of a niladic function, such as
-		fun
-	  The result is the value of invoking the function, fun(). The return
-	  types and values behave as in methods. Functions and function
-	  names are described below.
-
-Arguments may evaluate to any type; if they are pointers the implementation
-automatically indirects to the base type when required.
-
-A pipeline is a possibly chained sequence of "commands". A command is a simple
-value (argument) or a function or method call, possibly with multiple arguments:
-
-	Argument
-		The result is the value of evaluating the argument.
-	.Method [Argument...]
-		The method can be alone or the last element of a chain but,
-		unlike methods in the middle of a chain, it can take arguments.
-		The result is the value of calling the method with the
-		arguments:
-			dot.Method(Argument1, etc.)
-	functionName [Argument...]
-		The result is the value of calling the function associated
-		with the name:
-			function(Argument1, etc.)
-		Functions and function names are described below.
-
-Pipelines
-
-A pipeline may be "chained" by separating a sequence of commands with pipeline
-characters '|'. In a chained pipeline, the result of the each command is
-passed as the last argument of the following command. The output of the final
-command in the pipeline is the value of the pipeline.
-
-The output of a command will be either one value or two values, the second of
-which has type os.Error. If that second value is present and evaluates to
-non-nil, execution terminates and the error is returned to the caller of
-Execute.
-
-Variables
-
-A pipeline inside an action may initialize a variable to capture the result.
-The initialization has syntax
-
-	$variable := pipeline
-
-where $variable is the name of the variable. An action that declares a
-variable produces no output.
-
-If a "range" action initializes a variable, the variable is set to the
-successive elements of the iteration.  Also, a "range" may declare two
-variables, separated by a comma:
-
-	$index, $element := pipeline
-
-in which case $index and $element are set to the successive values of the
-array/slice index or map key and element, respectively.  Note that if there is
-only one variable, it is assigned the element; this is opposite to the
-convention in Go range clauses.
-
-A variable's scope extends to the "end" action of the control structure ("if",
-"with", or "range") in which it is declared, or to the end of the template if
-there is no such control structure.  A template invocation does not inherit
-variables from the point of its invocation.
-
-When execution begins, $ is set to the data argument passed to Execute, that is,
-to the starting value of dot.
-
-Examples
-
-Here are some example one-line templates demonstrating pipelines and variables.
-All produce the quoted word "output":
-
-	{{"\"output\""}}
-		A string constant.
-	{{`"output"`}}
-		A raw string constant.
-	{{printf "%q" "output"}}
-		A function call.
-	{{"output" | printf "%q"}}
-		A function call whose final argument comes from the previous
-		command.
-	{{"put" | printf "%s%s" "out" | printf "%q"}}
-		A more elaborate call.
-	{{"output" | printf "%s" | printf "%q"}}
-		A longer chain.
-	{{with "output"}}{{printf "%q" .}}{{end}}
-		A with action using dot.
-	{{with $x := "output" | printf "%q"}}{{$x}}{{end}}
-		A with action that creates and uses a variable.
-	{{with $x := "output"}}{{printf "%q" $x}}{{end}}
-		A with action that uses the variable in another action.
-	{{with $x := "output"}}{{$x | printf "%q"}}{{end}}
-		The same, but pipelined.
-
-Functions
-
-During execution functions are found in three function maps: first in the
-template, then in the "template set" (described below), and finally in the
-global function map. By default, no functions are defined in the template or
-the set but the Funcs methods can be used to add them.
-
-Predefined global functions are named as follows.
-
-	and
-		Returns the boolean AND of its arguments by returning the
-		first empty argument or the last argument, that is,
-		"and x y" behaves as "if x then y else x". All the
-		arguments are evaluated.
-	html
-		Returns the escaped HTML equivalent of the textual
-		representation of its arguments.
-	index
-		Returns the result of indexing its first argument by the
-		following arguments. Thus "index x 1 2 3" is, in Go syntax,
-		x[1][2][3]. Each indexed item must be a map, slice, or array.
-	js
-		Returns the escaped JavaScript equivalent of the textual
-		representation of its arguments.
-	len
-		Returns the integer length of its argument.
-	not
-		Returns the boolean negation of its single argument.
-	or
-		Returns the boolean OR of its arguments by returning the
-		first non-empty argument or the last argument, that is,
-		"or x y" behaves as "if x then x else y". All the
-		arguments are evaluated.
-	print
-		An alias for fmt.Sprint
-	printf
-		An alias for fmt.Sprintf
-	println
-		An alias for fmt.Sprintln
-	urlquery
-		Returns the escaped value of the textual representation of
-		its arguments in a form suitable for embedding in a URL query.
-
-The boolean functions take any zero value to be false and a non-zero value to
-be true.
-
-Template sets
-
-Each template is named by a string specified when it is created.  A template may
-use a template invocation to instantiate another template directly or by its
-name; see the explanation of the template action above. The name is looked up
-in the template set associated with the template.
-
-If no template invocation actions occur in the template, the issue of template
-sets can be ignored.  If it does contain invocations, though, the template
-containing the invocations must be part of a template set in which to look up
-the names.
-
-There are two ways to construct template sets.
-
-The first is to use a Set's Parse method to create a set of named templates from
-a single input defining multiple templates.  The syntax of the definitions is to
-surround each template declaration with a define and end action.
-
-The define action names the template being created by providing a string
-constant. Here is a simple example of input to Set.Parse:
-
-	`{{define "T1"}} definition of template T1 {{end}}
-	{{define "T2"}} definition of template T2 {{end}}
-	{{define "T3"}} {{template "T1"}} {{template "T2"}} {{end}}`
-
-This defines two templates, T1 and T2, and a third T3 that invokes the other two
-when it is executed.
-
-The second way to build a template set is to use Set's Add method to add a
-parsed template to a set.  A template may be bound to at most one set.  If it's
-necessary to have a template in multiple sets, the template definition must be
-parsed multiple times to create distinct *Template values.
-
-Set.Parse may be called multiple times on different inputs to construct the set.
-Two sets may therefore be constructed with a common base set of templates plus,
-through a second Parse call each, specializations for some elements.
-
-A template may be executed directly or through Set.Execute, which executes a
-named template from the set.  To invoke our example above, we might write,
-
-	err := set.Execute(os.Stdout, "T3", "no data needed")
-	if err != nil {
-		log.Fatalf("execution failed: %s", err)
-	}
-*/
-package template
diff --git a/src/pkg/template/exec.go b/src/pkg/template/exec.go
deleted file mode 100644
index e7fad72..0000000
--- a/src/pkg/template/exec.go
+++ /dev/null
@@ -1,674 +0,0 @@
-// Copyright 2011 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 template
-
-import (
-	"fmt"
-	"io"
-	"os"
-	"reflect"
-	"runtime"
-	"strings"
-	"template/parse"
-)
-
-// state represents the state of an execution. It's not part of the
-// template so that multiple executions of the same template
-// can execute in parallel.
-type state struct {
-	tmpl *Template
-	wr   io.Writer
-	line int        // line number for errors
-	vars []variable // push-down stack of variable values.
-}
-
-// variable holds the dynamic value of a variable such as $, $x etc.
-type variable struct {
-	name  string
-	value reflect.Value
-}
-
-// push pushes a new variable on the stack.
-func (s *state) push(name string, value reflect.Value) {
-	s.vars = append(s.vars, variable{name, value})
-}
-
-// mark returns the length of the variable stack.
-func (s *state) mark() int {
-	return len(s.vars)
-}
-
-// pop pops the variable stack up to the mark.
-func (s *state) pop(mark int) {
-	s.vars = s.vars[0:mark]
-}
-
-// setVar overwrites the top-nth variable on the stack. Used by range iterations.
-func (s *state) setVar(n int, value reflect.Value) {
-	s.vars[len(s.vars)-n].value = value
-}
-
-// varValue returns the value of the named variable.
-func (s *state) varValue(name string) reflect.Value {
-	for i := s.mark() - 1; i >= 0; i-- {
-		if s.vars[i].name == name {
-			return s.vars[i].value
-		}
-	}
-	s.errorf("undefined variable: %s", name)
-	return zero
-}
-
-var zero reflect.Value
-
-// errorf formats the error and terminates processing.
-func (s *state) errorf(format string, args ...interface{}) {
-	format = fmt.Sprintf("template: %s:%d: %s", s.tmpl.Name(), s.line, format)
-	panic(fmt.Errorf(format, args...))
-}
-
-// error terminates processing.
-func (s *state) error(err os.Error) {
-	s.errorf("%s", err)
-}
-
-// errRecover is the handler that turns panics into returns from the top
-// level of Parse.
-func errRecover(errp *os.Error) {
-	e := recover()
-	if e != nil {
-		if _, ok := e.(runtime.Error); ok {
-			panic(e)
-		}
-		*errp = e.(os.Error)
-	}
-}
-
-// Execute applies a parsed template to the specified data object,
-// writing the output to wr.
-func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) {
-	defer errRecover(&err)
-	value := reflect.ValueOf(data)
-	state := &state{
-		tmpl: t,
-		wr:   wr,
-		line: 1,
-		vars: []variable{{"$", value}},
-	}
-	if t.Root == nil {
-		state.errorf("must be parsed before execution")
-	}
-	state.walk(value, t.Root)
-	return
-}
-
-// Walk functions step through the major pieces of the template structure,
-// generating output as they go.
-func (s *state) walk(dot reflect.Value, n parse.Node) {
-	switch n := n.(type) {
-	case *parse.ActionNode:
-		s.line = n.Line
-		// Do not pop variables so they persist until next end.
-		// Also, if the action declares variables, don't print the result.
-		val := s.evalPipeline(dot, n.Pipe)
-		if len(n.Pipe.Decl) == 0 {
-			s.printValue(n, val)
-		}
-	case *parse.IfNode:
-		s.line = n.Line
-		s.walkIfOrWith(parse.NodeIf, dot, n.Pipe, n.List, n.ElseList)
-	case *parse.ListNode:
-		for _, node := range n.Nodes {
-			s.walk(dot, node)
-		}
-	case *parse.RangeNode:
-		s.line = n.Line
-		s.walkRange(dot, n)
-	case *parse.TemplateNode:
-		s.line = n.Line
-		s.walkTemplate(dot, n)
-	case *parse.TextNode:
-		if _, err := s.wr.Write(n.Text); err != nil {
-			s.error(err)
-		}
-	case *parse.WithNode:
-		s.line = n.Line
-		s.walkIfOrWith(parse.NodeWith, dot, n.Pipe, n.List, n.ElseList)
-	default:
-		s.errorf("unknown node: %s", n)
-	}
-}
-
-// walkIfOrWith walks an 'if' or 'with' node. The two control structures
-// are identical in behavior except that 'with' sets dot.
-func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
-	defer s.pop(s.mark())
-	val := s.evalPipeline(dot, pipe)
-	truth, ok := isTrue(val)
-	if !ok {
-		s.errorf("if/with can't use %v", val)
-	}
-	if truth {
-		if typ == parse.NodeWith {
-			s.walk(val, list)
-		} else {
-			s.walk(dot, list)
-		}
-	} else if elseList != nil {
-		s.walk(dot, elseList)
-	}
-}
-
-// isTrue returns whether the value is 'true', in the sense of not the zero of its type,
-// and whether the value has a meaningful truth value.
-func isTrue(val reflect.Value) (truth, ok bool) {
-	if !val.IsValid() {
-		// Something like var x interface{}, never set. It's a form of nil.
-		return false, true
-	}
-	switch val.Kind() {
-	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
-		truth = val.Len() > 0
-	case reflect.Bool:
-		truth = val.Bool()
-	case reflect.Complex64, reflect.Complex128:
-		truth = val.Complex() != 0
-	case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
-		truth = !val.IsNil()
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		truth = val.Int() != 0
-	case reflect.Float32, reflect.Float64:
-		truth = val.Float() != 0
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		truth = val.Uint() != 0
-	case reflect.Struct:
-		truth = true // Struct values are always true.
-	default:
-		return
-	}
-	return truth, true
-}
-
-func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
-	defer s.pop(s.mark())
-	val, _ := indirect(s.evalPipeline(dot, r.Pipe))
-	// mark top of stack before any variables in the body are pushed.
-	mark := s.mark()
-	oneIteration := func(index, elem reflect.Value) {
-		// Set top var (lexically the second if there are two) to the element.
-		if len(r.Pipe.Decl) > 0 {
-			s.setVar(1, elem)
-		}
-		// Set next var (lexically the first if there are two) to the index.
-		if len(r.Pipe.Decl) > 1 {
-			s.setVar(2, index)
-		}
-		s.walk(elem, r.List)
-		s.pop(mark)
-	}
-	switch val.Kind() {
-	case reflect.Array, reflect.Slice:
-		if val.Len() == 0 {
-			break
-		}
-		for i := 0; i < val.Len(); i++ {
-			oneIteration(reflect.ValueOf(i), val.Index(i))
-		}
-		return
-	case reflect.Map:
-		if val.Len() == 0 {
-			break
-		}
-		for _, key := range val.MapKeys() {
-			oneIteration(key, val.MapIndex(key))
-		}
-		return
-	case reflect.Chan:
-		if val.IsNil() {
-			break
-		}
-		i := 0
-		for ; ; i++ {
-			elem, ok := val.Recv()
-			if !ok {
-				break
-			}
-			oneIteration(reflect.ValueOf(i), elem)
-		}
-		if i == 0 {
-			break
-		}
-		return
-	case reflect.Invalid:
-		break // An invalid value is likely a nil map, etc. and acts like an empty map.
-	default:
-		s.errorf("range can't iterate over %v", val)
-	}
-	if r.ElseList != nil {
-		s.walk(dot, r.ElseList)
-	}
-}
-
-func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
-	set := s.tmpl.set
-	if set == nil {
-		s.errorf("no set defined in which to invoke template named %q", t.Name)
-	}
-	tmpl := set.tmpl[t.Name]
-	if tmpl == nil {
-		s.errorf("template %q not in set", t.Name)
-	}
-	// Variables declared by the pipeline persist.
-	dot = s.evalPipeline(dot, t.Pipe)
-	newState := *s
-	newState.tmpl = tmpl
-	// No dynamic scoping: template invocations inherit no variables.
-	newState.vars = []variable{{"$", dot}}
-	newState.walk(dot, tmpl.Root)
-}
-
-// Eval functions evaluate pipelines, commands, and their elements and extract
-// values from the data structure by examining fields, calling methods, and so on.
-// The printing of those values happens only through walk functions.
-
-// evalPipeline returns the value acquired by evaluating a pipeline. If the
-// pipeline has a variable declaration, the variable will be pushed on the
-// stack. Callers should therefore pop the stack after they are finished
-// executing commands depending on the pipeline value.
-func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) {
-	if pipe == nil {
-		return
-	}
-	for _, cmd := range pipe.Cmds {
-		value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
-		// If the object has type interface{}, dig down one level to the thing inside.
-		if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
-			value = reflect.ValueOf(value.Interface()) // lovely!
-		}
-	}
-	for _, variable := range pipe.Decl {
-		s.push(variable.Ident[0], value)
-	}
-	return value
-}
-
-func (s *state) notAFunction(args []parse.Node, final reflect.Value) {
-	if len(args) > 1 || final.IsValid() {
-		s.errorf("can't give argument to non-function %s", args[0])
-	}
-}
-
-func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value {
-	firstWord := cmd.Args[0]
-	switch n := firstWord.(type) {
-	case *parse.FieldNode:
-		return s.evalFieldNode(dot, n, cmd.Args, final)
-	case *parse.IdentifierNode:
-		// Must be a function.
-		return s.evalFunction(dot, n.Ident, cmd.Args, final)
-	case *parse.VariableNode:
-		return s.evalVariableNode(dot, n, cmd.Args, final)
-	}
-	s.notAFunction(cmd.Args, final)
-	switch word := firstWord.(type) {
-	case *parse.BoolNode:
-		return reflect.ValueOf(word.True)
-	case *parse.DotNode:
-		return dot
-	case *parse.NumberNode:
-		return s.idealConstant(word)
-	case *parse.StringNode:
-		return reflect.ValueOf(word.Text)
-	}
-	s.errorf("can't evaluate command %q", firstWord)
-	panic("not reached")
-}
-
-// idealConstant is called to return the value of a number in a context where
-// we don't know the type. In that case, the syntax of the number tells us
-// its type, and we use Go rules to resolve.  Note there is no such thing as
-// a uint ideal constant in this situation - the value must be of int type.
-func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
-	// These are ideal constants but we don't know the type
-	// and we have no context.  (If it was a method argument,
-	// we'd know what we need.) The syntax guides us to some extent.
-	switch {
-	case constant.IsComplex:
-		return reflect.ValueOf(constant.Complex128) // incontrovertible.
-	case constant.IsFloat && strings.IndexAny(constant.Text, ".eE") >= 0:
-		return reflect.ValueOf(constant.Float64)
-	case constant.IsInt:
-		n := int(constant.Int64)
-		if int64(n) != constant.Int64 {
-			s.errorf("%s overflows int", constant.Text)
-		}
-		return reflect.ValueOf(n)
-	case constant.IsUint:
-		s.errorf("%s overflows int", constant.Text)
-	}
-	return zero
-}
-
-func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
-	return s.evalFieldChain(dot, dot, field.Ident, args, final)
-}
-
-func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
-	// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
-	value := s.varValue(v.Ident[0])
-	if len(v.Ident) == 1 {
-		return value
-	}
-	return s.evalFieldChain(dot, value, v.Ident[1:], args, final)
-}
-
-// evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
-// dot is the environment in which to evaluate arguments, while
-// receiver is the value being walked along the chain.
-func (s *state) evalFieldChain(dot, receiver reflect.Value, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
-	n := len(ident)
-	for i := 0; i < n-1; i++ {
-		receiver = s.evalField(dot, ident[i], nil, zero, receiver)
-	}
-	// Now if it's a method, it gets the arguments.
-	return s.evalField(dot, ident[n-1], args, final, receiver)
-}
-
-func (s *state) evalFunction(dot reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
-	function, ok := findFunction(name, s.tmpl, s.tmpl.set)
-	if !ok {
-		s.errorf("%q is not a defined function", name)
-	}
-	return s.evalCall(dot, function, name, args, final)
-}
-
-// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
-// The 'final' argument represents the return value from the preceding
-// value of the pipeline, if any.
-func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node, final, receiver reflect.Value) reflect.Value {
-	if !receiver.IsValid() {
-		return zero
-	}
-	typ := receiver.Type()
-	receiver, _ = indirect(receiver)
-	// Unless it's an interface, need to get to a value of type *T to guarantee
-	// we see all methods of T and *T.
-	ptr := receiver
-	if ptr.Kind() != reflect.Interface && ptr.CanAddr() {
-		ptr = ptr.Addr()
-	}
-	if method, ok := methodByName(ptr, fieldName); ok {
-		return s.evalCall(dot, method, fieldName, args, final)
-	}
-	hasArgs := len(args) > 1 || final.IsValid()
-	// It's not a method; is it a field of a struct?
-	receiver, isNil := indirect(receiver)
-	if receiver.Kind() == reflect.Struct {
-		tField, ok := receiver.Type().FieldByName(fieldName)
-		if ok {
-			field := receiver.FieldByIndex(tField.Index)
-			if hasArgs {
-				s.errorf("%s is not a method but has arguments", fieldName)
-			}
-			if tField.PkgPath == "" { // field is exported
-				return field
-			}
-		}
-	}
-	// If it's a map, attempt to use the field name as a key.
-	if receiver.Kind() == reflect.Map {
-		nameVal := reflect.ValueOf(fieldName)
-		if nameVal.Type().AssignableTo(receiver.Type().Key()) {
-			if hasArgs {
-				s.errorf("%s is not a method but has arguments", fieldName)
-			}
-			return receiver.MapIndex(nameVal)
-		}
-	}
-	if isNil {
-		s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
-	}
-	s.errorf("can't evaluate field %s in type %s", fieldName, typ)
-	panic("not reached")
-}
-
-// TODO: delete when reflect's own MethodByName is released.
-func methodByName(receiver reflect.Value, name string) (reflect.Value, bool) {
-	typ := receiver.Type()
-	for i := 0; i < typ.NumMethod(); i++ {
-		if typ.Method(i).Name == name {
-			return receiver.Method(i), true // This value includes the receiver.
-		}
-	}
-	return zero, false
-}
-
-var (
-	osErrorType     = reflect.TypeOf((*os.Error)(nil)).Elem()
-	fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
-)
-
-// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
-// it looks just like a function call.  The arg list, if non-nil, includes (in the manner of the shell), arg[0]
-// as the function itself.
-func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
-	if args != nil {
-		args = args[1:] // Zeroth arg is function name/node; not passed to function.
-	}
-	typ := fun.Type()
-	numIn := len(args)
-	if final.IsValid() {
-		numIn++
-	}
-	numFixed := len(args)
-	if typ.IsVariadic() {
-		numFixed = typ.NumIn() - 1 // last arg is the variadic one.
-		if numIn < numFixed {
-			s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args))
-		}
-	} else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() {
-		s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
-	}
-	if !goodFunc(typ) {
-		s.errorf("can't handle multiple results from method/function %q", name)
-	}
-	// Build the arg list.
-	argv := make([]reflect.Value, numIn)
-	// Args must be evaluated. Fixed args first.
-	i := 0
-	for ; i < numFixed; i++ {
-		argv[i] = s.evalArg(dot, typ.In(i), args[i])
-	}
-	// Now the ... args.
-	if typ.IsVariadic() {
-		argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice.
-		for ; i < len(args); i++ {
-			argv[i] = s.evalArg(dot, argType, args[i])
-		}
-	}
-	// Add final value if necessary.
-	if final.IsValid() {
-		argv[i] = final
-	}
-	result := fun.Call(argv)
-	// If we have an os.Error that is not nil, stop execution and return that error to the caller.
-	if len(result) == 2 && !result[1].IsNil() {
-		s.errorf("error calling %s: %s", name, result[1].Interface().(os.Error))
-	}
-	return result[0]
-}
-
-// validateType guarantees that the value is valid and assignable to the type.
-func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
-	if !value.IsValid() {
-		s.errorf("invalid value; expected %s", typ)
-	}
-	if !value.Type().AssignableTo(typ) {
-		// Does one dereference or indirection work? We could do more, as we
-		// do with method receivers, but that gets messy and method receivers
-		// are much more constrained, so it makes more sense there than here.
-		// Besides, one is almost always all you need.
-		switch {
-		case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
-			value = value.Elem()
-		case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
-			value = value.Addr()
-		default:
-			s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
-		}
-	}
-	return value
-}
-
-func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
-	switch arg := n.(type) {
-	case *parse.DotNode:
-		return s.validateType(dot, typ)
-	case *parse.FieldNode:
-		return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
-	case *parse.VariableNode:
-		return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
-	}
-	switch typ.Kind() {
-	case reflect.Bool:
-		return s.evalBool(typ, n)
-	case reflect.Complex64, reflect.Complex128:
-		return s.evalComplex(typ, n)
-	case reflect.Float32, reflect.Float64:
-		return s.evalFloat(typ, n)
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return s.evalInteger(typ, n)
-	case reflect.Interface:
-		if typ.NumMethod() == 0 {
-			return s.evalEmptyInterface(dot, n)
-		}
-	case reflect.String:
-		return s.evalString(typ, n)
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return s.evalUnsignedInteger(typ, n)
-	}
-	s.errorf("can't handle %s for arg of type %s", n, typ)
-	panic("not reached")
-}
-
-func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
-	if n, ok := n.(*parse.BoolNode); ok {
-		value := reflect.New(typ).Elem()
-		value.SetBool(n.True)
-		return value
-	}
-	s.errorf("expected bool; found %s", n)
-	panic("not reached")
-}
-
-func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
-	if n, ok := n.(*parse.StringNode); ok {
-		value := reflect.New(typ).Elem()
-		value.SetString(n.Text)
-		return value
-	}
-	s.errorf("expected string; found %s", n)
-	panic("not reached")
-}
-
-func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
-	if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
-		value := reflect.New(typ).Elem()
-		value.SetInt(n.Int64)
-		return value
-	}
-	s.errorf("expected integer; found %s", n)
-	panic("not reached")
-}
-
-func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
-	if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
-		value := reflect.New(typ).Elem()
-		value.SetUint(n.Uint64)
-		return value
-	}
-	s.errorf("expected unsigned integer; found %s", n)
-	panic("not reached")
-}
-
-func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
-	if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
-		value := reflect.New(typ).Elem()
-		value.SetFloat(n.Float64)
-		return value
-	}
-	s.errorf("expected float; found %s", n)
-	panic("not reached")
-}
-
-func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
-	if n, ok := n.(*parse.NumberNode); ok && n.IsComplex {
-		value := reflect.New(typ).Elem()
-		value.SetComplex(n.Complex128)
-		return value
-	}
-	s.errorf("expected complex; found %s", n)
-	panic("not reached")
-}
-
-func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
-	switch n := n.(type) {
-	case *parse.BoolNode:
-		return reflect.ValueOf(n.True)
-	case *parse.DotNode:
-		return dot
-	case *parse.FieldNode:
-		return s.evalFieldNode(dot, n, nil, zero)
-	case *parse.IdentifierNode:
-		return s.evalFunction(dot, n.Ident, nil, zero)
-	case *parse.NumberNode:
-		return s.idealConstant(n)
-	case *parse.StringNode:
-		return reflect.ValueOf(n.Text)
-	case *parse.VariableNode:
-		return s.evalVariableNode(dot, n, nil, zero)
-	}
-	s.errorf("can't handle assignment of %s to empty interface argument", n)
-	panic("not reached")
-}
-
-// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
-// We indirect through pointers and empty interfaces (only) because
-// non-empty interfaces have methods we might need.
-func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
-	for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
-		if v.IsNil() {
-			return v, true
-		}
-		if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
-			break
-		}
-	}
-	return v, false
-}
-
-// printValue writes the textual representation of the value to the output of
-// the template.
-func (s *state) printValue(n parse.Node, v reflect.Value) {
-	if v.Kind() == reflect.Ptr {
-		v, _ = indirect(v) // fmt.Fprint handles nil.
-	}
-	if !v.IsValid() {
-		fmt.Fprint(s.wr, "<no value>")
-		return
-	}
-
-	if !v.Type().Implements(fmtStringerType) {
-		if v.CanAddr() && reflect.PtrTo(v.Type()).Implements(fmtStringerType) {
-			v = v.Addr()
-		} else {
-			switch v.Kind() {
-			case reflect.Chan, reflect.Func:
-				s.errorf("can't print %s of type %s", n, v.Type())
-			}
-		}
-	}
-	fmt.Fprint(s.wr, v.Interface())
-}
diff --git a/src/pkg/template/exec_test.go b/src/pkg/template/exec_test.go
deleted file mode 100644
index 8e1894e..0000000
--- a/src/pkg/template/exec_test.go
+++ /dev/null
@@ -1,613 +0,0 @@
-// Copyright 2011 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 template
-
-import (
-	"bytes"
-	"flag"
-	"fmt"
-	"os"
-	"reflect"
-	"sort"
-	"strings"
-	"testing"
-)
-
-var debug = flag.Bool("debug", false, "show the errors produced by the tests")
-
-// T has lots of interesting pieces to use to test execution.
-type T struct {
-	// Basics
-	True        bool
-	I           int
-	U16         uint16
-	X           string
-	FloatZero   float64
-	ComplexZero float64
-	// Nested structs.
-	U *U
-	// Struct with String method.
-	V0     V
-	V1, V2 *V
-	// Slices
-	SI      []int
-	SIEmpty []int
-	SB      []bool
-	// Maps
-	MSI      map[string]int
-	MSIone   map[string]int // one element, for deterministic output
-	MSIEmpty map[string]int
-	MXI      map[interface{}]int
-	MII      map[int]int
-	SMSI     []map[string]int
-	// Empty interfaces; used to see if we can dig inside one.
-	Empty0 interface{} // nil
-	Empty1 interface{}
-	Empty2 interface{}
-	Empty3 interface{}
-	Empty4 interface{}
-	// Non-empty interface.
-	NonEmptyInterface I
-	// Stringer.
-	Str fmt.Stringer
-	// Pointers
-	PI  *int
-	PSI *[]int
-	NIL *int
-	// Template to test evaluation of templates.
-	Tmpl *Template
-}
-
-type U struct {
-	V string
-}
-
-type V struct {
-	j int
-}
-
-func (v *V) String() string {
-	if v == nil {
-		return "nilV"
-	}
-	return fmt.Sprintf("<%d>", v.j)
-}
-
-var tVal = &T{
-	True:   true,
-	I:      17,
-	U16:    16,
-	X:      "x",
-	U:      &U{"v"},
-	V0:     V{6666},
-	V1:     &V{7777}, // leave V2 as nil
-	SI:     []int{3, 4, 5},
-	SB:     []bool{true, false},
-	MSI:    map[string]int{"one": 1, "two": 2, "three": 3},
-	MSIone: map[string]int{"one": 1},
-	MXI:    map[interface{}]int{"one": 1},
-	MII:    map[int]int{1: 1},
-	SMSI: []map[string]int{
-		{"one": 1, "two": 2},
-		{"eleven": 11, "twelve": 12},
-	},
-	Empty1:            3,
-	Empty2:            "empty2",
-	Empty3:            []int{7, 8},
-	Empty4:            &U{"UinEmpty"},
-	NonEmptyInterface: new(T),
-	Str:               os.NewError("foozle"),
-	PI:                newInt(23),
-	PSI:               newIntSlice(21, 22, 23),
-	Tmpl:              Must(New("x").Parse("test template")), // "x" is the value of .X
-}
-
-// A non-empty interface.
-type I interface {
-	Method0() string
-}
-
-var iVal I = tVal
-
-// Helpers for creation.
-func newInt(n int) *int {
-	p := new(int)
-	*p = n
-	return p
-}
-
-func newIntSlice(n ...int) *[]int {
-	p := new([]int)
-	*p = make([]int, len(n))
-	copy(*p, n)
-	return p
-}
-
-// Simple methods with and without arguments.
-func (t *T) Method0() string {
-	return "M0"
-}
-
-func (t *T) Method1(a int) int {
-	return a
-}
-
-func (t *T) Method2(a uint16, b string) string {
-	return fmt.Sprintf("Method2: %d %s", a, b)
-}
-
-func (t *T) MAdd(a int, b []int) []int {
-	v := make([]int, len(b))
-	for i, x := range b {
-		v[i] = x + a
-	}
-	return v
-}
-
-// MSort is used to sort map keys for stable output. (Nice trick!)
-func (t *T) MSort(m map[string]int) []string {
-	keys := make([]string, len(m))
-	i := 0
-	for k := range m {
-		keys[i] = k
-		i++
-	}
-	sort.Strings(keys)
-	return keys
-}
-
-// EPERM returns a value and an os.Error according to its argument.
-func (t *T) EPERM(error bool) (bool, os.Error) {
-	if error {
-		return true, os.EPERM
-	}
-	return false, nil
-}
-
-// A few methods to test chaining.
-func (t *T) GetU() *U {
-	return t.U
-}
-
-func (u *U) TrueFalse(b bool) string {
-	if b {
-		return "true"
-	}
-	return ""
-}
-
-func typeOf(arg interface{}) string {
-	return fmt.Sprintf("%T", arg)
-}
-
-type execTest struct {
-	name   string
-	input  string
-	output string
-	data   interface{}
-	ok     bool
-}
-
-// bigInt and bigUint are hex string representing numbers either side
-// of the max int boundary.
-// We do it this way so the test doesn't depend on ints being 32 bits.
-var (
-	bigInt  = fmt.Sprintf("0x%x", int(1<<uint(reflect.TypeOf(0).Bits()-1)-1))
-	bigUint = fmt.Sprintf("0x%x", uint(1<<uint(reflect.TypeOf(0).Bits()-1)))
-)
-
-var execTests = []execTest{
-	// Trivial cases.
-	{"empty", "", "", nil, true},
-	{"text", "some text", "some text", nil, true},
-
-	// Ideal constants.
-	{"ideal int", "{{typeOf 3}}", "int", 0, true},
-	{"ideal float", "{{typeOf 1.0}}", "float64", 0, true},
-	{"ideal exp float", "{{typeOf 1e1}}", "float64", 0, true},
-	{"ideal complex", "{{typeOf 1i}}", "complex128", 0, true},
-	{"ideal int", "{{typeOf " + bigInt + "}}", "int", 0, true},
-	{"ideal too big", "{{typeOf " + bigUint + "}}", "", 0, false},
-
-	// Fields of structs.
-	{".X", "-{{.X}}-", "-x-", tVal, true},
-	{".U.V", "-{{.U.V}}-", "-v-", tVal, true},
-
-	// Fields on maps.
-	{"map .one", "{{.MSI.one}}", "1", tVal, true},
-	{"map .two", "{{.MSI.two}}", "2", tVal, true},
-	{"map .NO", "{{.MSI.NO}}", "<no value>", tVal, true},
-	{"map .one interface", "{{.MXI.one}}", "1", tVal, true},
-	{"map .WRONG args", "{{.MSI.one 1}}", "", tVal, false},
-	{"map .WRONG type", "{{.MII.one}}", "", tVal, false},
-
-	// Dots of all kinds to test basic evaluation.
-	{"dot int", "<{{.}}>", "<13>", 13, true},
-	{"dot uint", "<{{.}}>", "<14>", uint(14), true},
-	{"dot float", "<{{.}}>", "<15.1>", 15.1, true},
-	{"dot bool", "<{{.}}>", "<true>", true, true},
-	{"dot complex", "<{{.}}>", "<(16.2-17i)>", 16.2 - 17i, true},
-	{"dot string", "<{{.}}>", "<hello>", "hello", true},
-	{"dot slice", "<{{.}}>", "<[-1 -2 -3]>", []int{-1, -2, -3}, true},
-	{"dot map", "<{{.}}>", "<map[two:22 one:11]>", map[string]int{"one": 11, "two": 22}, true},
-	{"dot struct", "<{{.}}>", "<{7 seven}>", struct {
-		a int
-		b string
-	}{7, "seven"}, true},
-
-	// Variables.
-	{"$ int", "{{$}}", "123", 123, true},
-	{"$.I", "{{$.I}}", "17", tVal, true},
-	{"$.U.V", "{{$.U.V}}", "v", tVal, true},
-	{"declare in action", "{{$x := $.U.V}}{{$x}}", "v", tVal, true},
-
-	// Type with String method.
-	{"V{6666}.String()", "-{{.V0}}-", "-<6666>-", tVal, true},
-	{"&V{7777}.String()", "-{{.V1}}-", "-<7777>-", tVal, true},
-	{"(*V)(nil).String()", "-{{.V2}}-", "-nilV-", tVal, true},
-
-	// Pointers.
-	{"*int", "{{.PI}}", "23", tVal, true},
-	{"*[]int", "{{.PSI}}", "[21 22 23]", tVal, true},
-	{"*[]int[1]", "{{index .PSI 1}}", "22", tVal, true},
-	{"NIL", "{{.NIL}}", "<nil>", tVal, true},
-
-	// Empty interfaces holding values.
-	{"empty nil", "{{.Empty0}}", "<no value>", tVal, true},
-	{"empty with int", "{{.Empty1}}", "3", tVal, true},
-	{"empty with string", "{{.Empty2}}", "empty2", tVal, true},
-	{"empty with slice", "{{.Empty3}}", "[7 8]", tVal, true},
-	{"empty with struct", "{{.Empty4}}", "{UinEmpty}", tVal, true},
-	{"empty with struct, field", "{{.Empty4.V}}", "UinEmpty", tVal, true},
-
-	// Method calls.
-	{".Method0", "-{{.Method0}}-", "-M0-", tVal, true},
-	{".Method1(1234)", "-{{.Method1 1234}}-", "-1234-", tVal, true},
-	{".Method1(.I)", "-{{.Method1 .I}}-", "-17-", tVal, true},
-	{".Method2(3, .X)", "-{{.Method2 3 .X}}-", "-Method2: 3 x-", tVal, true},
-	{".Method2(.U16, `str`)", "-{{.Method2 .U16 `str`}}-", "-Method2: 16 str-", tVal, true},
-	{".Method2(.U16, $x)", "{{if $x := .X}}-{{.Method2 .U16 $x}}{{end}}-", "-Method2: 16 x-", tVal, true},
-	{"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true},
-	{"method on chained var",
-		"{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
-		"true", tVal, true},
-	{"chained method",
-		"{{range .MSIone}}{{if $.GetU.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
-		"true", tVal, true},
-	{"chained method on variable",
-		"{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}",
-		"true", tVal, true},
-
-	// Pipelines.
-	{"pipeline", "-{{.Method0 | .Method2 .U16}}-", "-Method2: 16 M0-", tVal, true},
-
-	// If.
-	{"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true},
-	{"if false", "{{if false}}TRUE{{else}}FALSE{{end}}", "FALSE", tVal, true},
-	{"if 1", "{{if 1}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
-	{"if 0", "{{if 0}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
-	{"if 1.5", "{{if 1.5}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
-	{"if 0.0", "{{if .FloatZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
-	{"if 1.5i", "{{if 1.5i}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
-	{"if 0.0i", "{{if .ComplexZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
-	{"if emptystring", "{{if ``}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
-	{"if string", "{{if `notempty`}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
-	{"if emptyslice", "{{if .SIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
-	{"if slice", "{{if .SI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
-	{"if emptymap", "{{if .MSIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
-	{"if map", "{{if .MSI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
-	{"if $x with $y int", "{{if $x := true}}{{with $y := .I}}{{$x}},{{$y}}{{end}}{{end}}", "true,17", tVal, true},
-	{"if $x with $x int", "{{if $x := true}}{{with $x := .I}}{{$x}},{{end}}{{$x}}{{end}}", "17,true", tVal, true},
-
-	// Print etc.
-	{"print", `{{print "hello, print"}}`, "hello, print", tVal, true},
-	{"print", `{{print 1 2 3}}`, "1 2 3", tVal, true},
-	{"println", `{{println 1 2 3}}`, "1 2 3\n", tVal, true},
-	{"printf int", `{{printf "%04x" 127}}`, "007f", tVal, true},
-	{"printf float", `{{printf "%g" 3.5}}`, "3.5", tVal, true},
-	{"printf complex", `{{printf "%g" 1+7i}}`, "(1+7i)", tVal, true},
-	{"printf string", `{{printf "%s" "hello"}}`, "hello", tVal, true},
-	{"printf function", `{{printf "%#q" zeroArgs}}`, "`zeroArgs`", tVal, true},
-	{"printf field", `{{printf "%s" .U.V}}`, "v", tVal, true},
-	{"printf method", `{{printf "%s" .Method0}}`, "M0", tVal, true},
-	{"printf dot", `{{with .I}}{{printf "%d" .}}{{end}}`, "17", tVal, true},
-	{"printf var", `{{with $x := .I}}{{printf "%d" $x}}{{end}}`, "17", tVal, true},
-	{"printf lots", `{{printf "%d %s %g %s" 127 "hello" 7-3i .Method0}}`, "127 hello (7-3i) M0", tVal, true},
-
-	// HTML.
-	{"html", `{{html "<script>alert(\"XSS\");</script>"}}`,
-		"<script>alert("XSS");</script>", nil, true},
-	{"html pipeline", `{{printf "<script>alert(\"XSS\");</script>" | html}}`,
-		"<script>alert("XSS");</script>", nil, true},
-
-	// JavaScript.
-	{"js", `{{js .}}`, `It\'d be nice.`, `It'd be nice.`, true},
-
-	// URL query.
-	{"urlquery", `{{"http://www.example.org/"|urlquery}}`, "http%3A%2F%2Fwww.example.org%2F", nil, true},
-
-	// Booleans
-	{"not", "{{not true}} {{not false}}", "false true", nil, true},
-	{"and", "{{and false 0}} {{and 1 0}} {{and 0 true}} {{and 1 1}}", "false 0 0 1", nil, true},
-	{"or", "{{or 0 0}} {{or 1 0}} {{or 0 true}} {{or 1 1}}", "0 1 true 1", nil, true},
-	{"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true},
-	{"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true},
-
-	// Indexing.
-	{"slice[0]", "{{index .SI 0}}", "3", tVal, true},
-	{"slice[1]", "{{index .SI 1}}", "4", tVal, true},
-	{"slice[HUGE]", "{{index .SI 10}}", "", tVal, false},
-	{"slice[WRONG]", "{{index .SI `hello`}}", "", tVal, false},
-	{"map[one]", "{{index .MSI `one`}}", "1", tVal, true},
-	{"map[two]", "{{index .MSI `two`}}", "2", tVal, true},
-	{"map[NO]", "{{index .MSI `XXX`}}", "", tVal, true},
-	{"map[WRONG]", "{{index .MSI 10}}", "", tVal, false},
-	{"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true},
-
-	// Len.
-	{"slice", "{{len .SI}}", "3", tVal, true},
-	{"map", "{{len .MSI }}", "3", tVal, true},
-	{"len of int", "{{len 3}}", "", tVal, false},
-	{"len of nothing", "{{len .Empty0}}", "", tVal, false},
-
-	// With.
-	{"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true},
-	{"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true},
-	{"with 1", "{{with 1}}{{.}}{{else}}ZERO{{end}}", "1", tVal, true},
-	{"with 0", "{{with 0}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
-	{"with 1.5", "{{with 1.5}}{{.}}{{else}}ZERO{{end}}", "1.5", tVal, true},
-	{"with 0.0", "{{with .FloatZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
-	{"with 1.5i", "{{with 1.5i}}{{.}}{{else}}ZERO{{end}}", "(0+1.5i)", tVal, true},
-	{"with 0.0i", "{{with .ComplexZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
-	{"with emptystring", "{{with ``}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
-	{"with string", "{{with `notempty`}}{{.}}{{else}}EMPTY{{end}}", "notempty", tVal, true},
-	{"with emptyslice", "{{with .SIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
-	{"with slice", "{{with .SI}}{{.}}{{else}}EMPTY{{end}}", "[3 4 5]", tVal, true},
-	{"with emptymap", "{{with .MSIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
-	{"with map", "{{with .MSIone}}{{.}}{{else}}EMPTY{{end}}", "map[one:1]", tVal, true},
-	{"with empty interface, struct field", "{{with .Empty4}}{{.V}}{{end}}", "UinEmpty", tVal, true},
-	{"with $x int", "{{with $x := .I}}{{$x}}{{end}}", "17", tVal, true},
-	{"with $x struct.U.V", "{{with $x := $}}{{$x.U.V}}{{end}}", "v", tVal, true},
-	{"with variable and action", "{{with $x := $}}{{$y := $.U.V}}{{$y}}{{end}}", "v", tVal, true},
-
-	// Range.
-	{"range []int", "{{range .SI}}-{{.}}-{{end}}", "-3--4--5-", tVal, true},
-	{"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true},
-	{"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
-	{"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
-	{"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true},
-	{"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true},
-	{"range map", "{{range .MSI | .MSort}}-{{.}}-{{end}}", "-one--three--two-", tVal, true},
-	{"range empty map no else", "{{range .MSIEmpty}}-{{.}}-{{end}}", "", tVal, true},
-	{"range map else", "{{range .MSI | .MSort}}-{{.}}-{{else}}EMPTY{{end}}", "-one--three--two-", tVal, true},
-	{"range empty map else", "{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
-	{"range empty interface", "{{range .Empty3}}-{{.}}-{{else}}EMPTY{{end}}", "-7--8-", tVal, true},
-	{"range empty nil", "{{range .Empty0}}-{{.}}-{{end}}", "", tVal, true},
-	{"range $x SI", "{{range $x := .SI}}<{{$x}}>{{end}}", "<3><4><5>", tVal, true},
-	{"range $x $y SI", "{{range $x, $y := .SI}}<{{$x}}={{$y}}>{{end}}", "<0=3><1=4><2=5>", tVal, true},
-	{"range $x MSIone", "{{range $x := .MSIone}}<{{$x}}>{{end}}", "<1>", tVal, true},
-	{"range $x $y MSIone", "{{range $x, $y := .MSIone}}<{{$x}}={{$y}}>{{end}}", "<one=1>", tVal, true},
-	{"range $x PSI", "{{range $x := .PSI}}<{{$x}}>{{end}}", "<21><22><23>", tVal, true},
-	{"declare in range", "{{range $x := .PSI}}<{{$foo:=$x}}{{$x}}>{{end}}", "<21><22><23>", tVal, true},
-	{"range count", `{{range $i, $x := count 5}}[{{$i}}]{{$x}}{{end}}`, "[0]a[1]b[2]c[3]d[4]e", tVal, true},
-	{"range nil count", `{{range $i, $x := count 0}}{{else}}empty{{end}}`, "empty", tVal, true},
-
-	// Cute examples.
-	{"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true},
-	{"or as if false", `{{or .SIEmpty "slice is empty"}}`, "slice is empty", tVal, true},
-
-	// Error handling.
-	{"error method, error", "{{.EPERM true}}", "", tVal, false},
-	{"error method, no error", "{{.EPERM false}}", "false", tVal, true},
-
-	// Fixed bugs.
-	// Must separate dot and receiver; otherwise args are evaluated with dot set to variable.
-	{"bug0", "{{range .MSIone}}{{if $.Method1 .}}X{{end}}{{end}}", "X", tVal, true},
-	// Do not loop endlessly in indirect for non-empty interfaces.
-	// The bug appears with *interface only; looped forever.
-	{"bug1", "{{.Method0}}", "M0", &iVal, true},
-	// Was taking address of interface field, so method set was empty.
-	{"bug2", "{{$.NonEmptyInterface.Method0}}", "M0", tVal, true},
-	// Struct values were not legal in with - mere oversight.
-	{"bug3", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true},
-	// Nil interface values in if.
-	{"bug4", "{{if .Empty0}}non-nil{{else}}nil{{end}}", "nil", tVal, true},
-	// Stringer.
-	{"bug5", "{{.Str}}", "foozle", tVal, true},
-	// Args need to be indirected and dereferenced sometimes.
-	{"bug6a", "{{vfunc .V0 .V1}}", "vfunc", tVal, true},
-	{"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true},
-	{"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true},
-	{"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true},
-}
-
-func zeroArgs() string {
-	return "zeroArgs"
-}
-
-func oneArg(a string) string {
-	return "oneArg=" + a
-}
-
-// count returns a channel that will deliver n sequential 1-letter strings starting at "a"
-func count(n int) chan string {
-	if n == 0 {
-		return nil
-	}
-	c := make(chan string)
-	go func() {
-		for i := 0; i < n; i++ {
-			c <- "abcdefghijklmnop"[i : i+1]
-		}
-		close(c)
-	}()
-	return c
-}
-
-// vfunc takes a *V and a V
-func vfunc(V, *V) string {
-	return "vfunc"
-}
-
-func testExecute(execTests []execTest, set *Set, t *testing.T) {
-	b := new(bytes.Buffer)
-	funcs := FuncMap{
-		"count":    count,
-		"oneArg":   oneArg,
-		"typeOf":   typeOf,
-		"vfunc":    vfunc,
-		"zeroArgs": zeroArgs,
-	}
-	for _, test := range execTests {
-		tmpl := New(test.name).Funcs(funcs)
-		_, err := tmpl.ParseInSet(test.input, set)
-		if err != nil {
-			t.Errorf("%s: parse error: %s", test.name, err)
-			continue
-		}
-		b.Reset()
-		err = tmpl.Execute(b, test.data)
-		switch {
-		case !test.ok && err == nil:
-			t.Errorf("%s: expected error; got none", test.name)
-			continue
-		case test.ok && err != nil:
-			t.Errorf("%s: unexpected execute error: %s", test.name, err)
-			continue
-		case !test.ok && err != nil:
-			// expected error, got one
-			if *debug {
-				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
-			}
-		}
-		result := b.String()
-		if result != test.output {
-			t.Errorf("%s: expected\n\t%q\ngot\n\t%q", test.name, test.output, result)
-		}
-	}
-}
-
-func TestExecute(t *testing.T) {
-	testExecute(execTests, nil, t)
-}
-
-// Check that an error from a method flows back to the top.
-func TestExecuteError(t *testing.T) {
-	b := new(bytes.Buffer)
-	tmpl := New("error")
-	_, err := tmpl.Parse("{{.EPERM true}}")
-	if err != nil {
-		t.Fatalf("parse error: %s", err)
-	}
-	err = tmpl.Execute(b, tVal)
-	if err == nil {
-		t.Errorf("expected error; got none")
-	} else if !strings.Contains(err.String(), os.EPERM.String()) {
-		if *debug {
-			fmt.Printf("test execute error: %s\n", err)
-		}
-		t.Errorf("expected os.EPERM; got %s", err)
-	}
-}
-
-func TestJSEscaping(t *testing.T) {
-	testCases := []struct {
-		in, exp string
-	}{
-		{`a`, `a`},
-		{`'foo`, `\'foo`},
-		{`Go "jump" \`, `Go \"jump\" \\`},
-		{`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`},
-		{"unprintable \uFDFF", `unprintable \uFDFF`},
-		{`<html>`, `\x3Chtml\x3E`},
-	}
-	for _, tc := range testCases {
-		s := JSEscapeString(tc.in)
-		if s != tc.exp {
-			t.Errorf("JS escaping [%s] got [%s] want [%s]", tc.in, s, tc.exp)
-		}
-	}
-}
-
-// A nice example: walk a binary tree.
-
-type Tree struct {
-	Val         int
-	Left, Right *Tree
-}
-
-const treeTemplate = `
-	{{define "tree"}}
-	[
-		{{.Val}}
-		{{with .Left}}
-			{{template "tree" .}}
-		{{end}}
-		{{with .Right}}
-			{{template "tree" .}}
-		{{end}}
-	]
-	{{end}}
-`
-
-func TestTree(t *testing.T) {
-	var tree = &Tree{
-		1,
-		&Tree{
-			2, &Tree{
-				3,
-				&Tree{
-					4, nil, nil,
-				},
-				nil,
-			},
-			&Tree{
-				5,
-				&Tree{
-					6, nil, nil,
-				},
-				nil,
-			},
-		},
-		&Tree{
-			7,
-			&Tree{
-				8,
-				&Tree{
-					9, nil, nil,
-				},
-				nil,
-			},
-			&Tree{
-				10,
-				&Tree{
-					11, nil, nil,
-				},
-				nil,
-			},
-		},
-	}
-	set := new(Set)
-	_, err := set.Parse(treeTemplate)
-	if err != nil {
-		t.Fatal("parse error:", err)
-	}
-	var b bytes.Buffer
-	err = set.Execute(&b, "tree", tree)
-	if err != nil {
-		t.Fatal("exec error:", err)
-	}
-	stripSpace := func(r int) int {
-		if r == '\t' || r == '\n' {
-			return -1
-		}
-		return r
-	}
-	result := strings.Map(stripSpace, b.String())
-	const expect = "[1[2[3[4]][5[6]]][7[8[9]][10[11]]]]"
-	if result != expect {
-		t.Errorf("expected %q got %q", expect, result)
-	}
-}
diff --git a/src/pkg/template/funcs.go b/src/pkg/template/funcs.go
deleted file mode 100644
index feb1fd8..0000000
--- a/src/pkg/template/funcs.go
+++ /dev/null
@@ -1,368 +0,0 @@
-// Copyright 2011 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 template
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"reflect"
-	"strings"
-	"unicode"
-	"url"
-	"utf8"
-)
-
-// FuncMap is the type of the map defining the mapping from names to functions.
-// Each function must have either a single return value, or two return values of
-// which the second has type os.Error. If the second argument evaluates to non-nil
-// during execution, execution terminates and Execute returns an error.
-type FuncMap map[string]interface{}
-
-var builtins = FuncMap{
-	"and":      and,
-	"html":     HTMLEscaper,
-	"index":    index,
-	"js":       JSEscaper,
-	"len":      length,
-	"not":      not,
-	"or":       or,
-	"print":    fmt.Sprint,
-	"printf":   fmt.Sprintf,
-	"println":  fmt.Sprintln,
-	"urlquery": URLQueryEscaper,
-}
-
-var builtinFuncs = createValueFuncs(builtins)
-
-// createValueFuncs turns a FuncMap into a map[string]reflect.Value
-func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
-	m := make(map[string]reflect.Value)
-	addValueFuncs(m, funcMap)
-	return m
-}
-
-// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
-func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
-	for name, fn := range in {
-		v := reflect.ValueOf(fn)
-		if v.Kind() != reflect.Func {
-			panic("value for " + name + " not a function")
-		}
-		if !goodFunc(v.Type()) {
-			panic(fmt.Errorf("can't handle multiple results from method/function %q", name))
-		}
-		out[name] = v
-	}
-}
-
-// addFuncs adds to values the functions in funcs. It does no checking of the input -
-// call addValueFuncs first.
-func addFuncs(out, in FuncMap) {
-	for name, fn := range in {
-		out[name] = fn
-	}
-}
-
-// goodFunc checks that the function or method has the right result signature.
-func goodFunc(typ reflect.Type) bool {
-	// We allow functions with 1 result or 2 results where the second is an os.Error.
-	switch {
-	case typ.NumOut() == 1:
-		return true
-	case typ.NumOut() == 2 && typ.Out(1) == osErrorType:
-		return true
-	}
-	return false
-}
-
-// findFunction looks for a function in the template, set, and global map.
-func findFunction(name string, tmpl *Template, set *Set) (reflect.Value, bool) {
-	if tmpl != nil {
-		if fn := tmpl.execFuncs[name]; fn.IsValid() {
-			return fn, true
-		}
-	}
-	if set != nil {
-		if fn := set.execFuncs[name]; fn.IsValid() {
-			return fn, true
-		}
-	}
-	if fn := builtinFuncs[name]; fn.IsValid() {
-		return fn, true
-	}
-	return reflect.Value{}, false
-}
-
-// Indexing.
-
-// index returns the result of indexing its first argument by the following
-// arguments.  Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
-// indexed item must be a map, slice, or array.
-func index(item interface{}, indices ...interface{}) (interface{}, os.Error) {
-	v := reflect.ValueOf(item)
-	for _, i := range indices {
-		index := reflect.ValueOf(i)
-		var isNil bool
-		if v, isNil = indirect(v); isNil {
-			return nil, fmt.Errorf("index of nil pointer")
-		}
-		switch v.Kind() {
-		case reflect.Array, reflect.Slice:
-			var x int64
-			switch index.Kind() {
-			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-				x = index.Int()
-			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-				x = int64(index.Uint())
-			default:
-				return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
-			}
-			if x < 0 || x >= int64(v.Len()) {
-				return nil, fmt.Errorf("index out of range: %d", x)
-			}
-			v = v.Index(int(x))
-		case reflect.Map:
-			if !index.Type().AssignableTo(v.Type().Key()) {
-				return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
-			}
-			if x := v.MapIndex(index); x.IsValid() {
-				v = x
-			} else {
-				v = reflect.Zero(v.Type().Key())
-			}
-		default:
-			return nil, fmt.Errorf("can't index item of type %s", index.Type())
-		}
-	}
-	return v.Interface(), nil
-}
-
-// Length
-
-// length returns the length of the item, with an error if it has no defined length.
-func length(item interface{}) (int, os.Error) {
-	v, isNil := indirect(reflect.ValueOf(item))
-	if isNil {
-		return 0, fmt.Errorf("len of nil pointer")
-	}
-	switch v.Kind() {
-	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
-		return v.Len(), nil
-	}
-	return 0, fmt.Errorf("len of type %s", v.Type())
-}
-
-// Boolean logic.
-
-func truth(a interface{}) bool {
-	t, _ := isTrue(reflect.ValueOf(a))
-	return t
-}
-
-// and computes the Boolean AND of its arguments, returning
-// the first false argument it encounters, or the last argument.
-func and(arg0 interface{}, args ...interface{}) interface{} {
-	if !truth(arg0) {
-		return arg0
-	}
-	for i := range args {
-		arg0 = args[i]
-		if !truth(arg0) {
-			break
-		}
-	}
-	return arg0
-}
-
-// or computes the Boolean OR of its arguments, returning
-// the first true argument it encounters, or the last argument.
-func or(arg0 interface{}, args ...interface{}) interface{} {
-	if truth(arg0) {
-		return arg0
-	}
-	for i := range args {
-		arg0 = args[i]
-		if truth(arg0) {
-			break
-		}
-	}
-	return arg0
-}
-
-// not returns the Boolean negation of its argument.
-func not(arg interface{}) (truth bool) {
-	truth, _ = isTrue(reflect.ValueOf(arg))
-	return !truth
-}
-
-// HTML escaping.
-
-var (
-	htmlQuot = []byte(""") // shorter than """
-	htmlApos = []byte("'") // shorter than "'"
-	htmlAmp  = []byte("&")
-	htmlLt   = []byte("<")
-	htmlGt   = []byte(">")
-)
-
-// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
-func HTMLEscape(w io.Writer, b []byte) {
-	last := 0
-	for i, c := range b {
-		var html []byte
-		switch c {
-		case '"':
-			html = htmlQuot
-		case '\'':
-			html = htmlApos
-		case '&':
-			html = htmlAmp
-		case '<':
-			html = htmlLt
-		case '>':
-			html = htmlGt
-		default:
-			continue
-		}
-		w.Write(b[last:i])
-		w.Write(html)
-		last = i + 1
-	}
-	w.Write(b[last:])
-}
-
-// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
-func HTMLEscapeString(s string) string {
-	// Avoid allocation if we can.
-	if strings.IndexAny(s, `'"&<>`) < 0 {
-		return s
-	}
-	var b bytes.Buffer
-	HTMLEscape(&b, []byte(s))
-	return b.String()
-}
-
-// HTMLEscaper returns the escaped HTML equivalent of the textual
-// representation of its arguments.
-func HTMLEscaper(args ...interface{}) string {
-	ok := false
-	var s string
-	if len(args) == 1 {
-		s, ok = args[0].(string)
-	}
-	if !ok {
-		s = fmt.Sprint(args...)
-	}
-	return HTMLEscapeString(s)
-}
-
-// JavaScript escaping.
-
-var (
-	jsLowUni = []byte(`\u00`)
-	hex      = []byte("0123456789ABCDEF")
-
-	jsBackslash = []byte(`\\`)
-	jsApos      = []byte(`\'`)
-	jsQuot      = []byte(`\"`)
-	jsLt        = []byte(`\x3C`)
-	jsGt        = []byte(`\x3E`)
-)
-
-// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
-func JSEscape(w io.Writer, b []byte) {
-	last := 0
-	for i := 0; i < len(b); i++ {
-		c := b[i]
-
-		if !jsIsSpecial(int(c)) {
-			// fast path: nothing to do
-			continue
-		}
-		w.Write(b[last:i])
-
-		if c < utf8.RuneSelf {
-			// Quotes, slashes and angle brackets get quoted.
-			// Control characters get written as \u00XX.
-			switch c {
-			case '\\':
-				w.Write(jsBackslash)
-			case '\'':
-				w.Write(jsApos)
-			case '"':
-				w.Write(jsQuot)
-			case '<':
-				w.Write(jsLt)
-			case '>':
-				w.Write(jsGt)
-			default:
-				w.Write(jsLowUni)
-				t, b := c>>4, c&0x0f
-				w.Write(hex[t : t+1])
-				w.Write(hex[b : b+1])
-			}
-		} else {
-			// Unicode rune.
-			rune, size := utf8.DecodeRune(b[i:])
-			if unicode.IsPrint(rune) {
-				w.Write(b[i : i+size])
-			} else {
-				// TODO(dsymonds): Do this without fmt?
-				fmt.Fprintf(w, "\\u%04X", rune)
-			}
-			i += size - 1
-		}
-		last = i + 1
-	}
-	w.Write(b[last:])
-}
-
-// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
-func JSEscapeString(s string) string {
-	// Avoid allocation if we can.
-	if strings.IndexFunc(s, jsIsSpecial) < 0 {
-		return s
-	}
-	var b bytes.Buffer
-	JSEscape(&b, []byte(s))
-	return b.String()
-}
-
-func jsIsSpecial(rune int) bool {
-	switch rune {
-	case '\\', '\'', '"', '<', '>':
-		return true
-	}
-	return rune < ' ' || utf8.RuneSelf <= rune
-}
-
-// JSEscaper returns the escaped JavaScript equivalent of the textual
-// representation of its arguments.
-func JSEscaper(args ...interface{}) string {
-	ok := false
-	var s string
-	if len(args) == 1 {
-		s, ok = args[0].(string)
-	}
-	if !ok {
-		s = fmt.Sprint(args...)
-	}
-	return JSEscapeString(s)
-}
-
-// URLQueryEscaper returns the escaped value of the textual representation of
-// its arguments in a form suitable for embedding in a URL query.
-func URLQueryEscaper(args ...interface{}) string {
-	s, ok := "", false
-	if len(args) == 1 {
-		s, ok = args[0].(string)
-	}
-	if !ok {
-		s = fmt.Sprint(args...)
-	}
-	return url.QueryEscape(s)
-}
diff --git a/src/pkg/template/helper.go b/src/pkg/template/helper.go
deleted file mode 100644
index 1dc90f7..0000000
--- a/src/pkg/template/helper.go
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright 2011 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.
-
-// Helper functions to make constructing templates and sets easier.
-
-package template
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-)
-
-// Functions and methods to parse a single template.
-
-// Must is a helper that wraps a call to a function returning (*Template, os.Error)
-// and panics if the error is non-nil. It is intended for use in variable initializations
-// such as
-//	var t = template.Must(template.New("name").Parse("text"))
-func Must(t *Template, err os.Error) *Template {
-	if err != nil {
-		panic(err)
-	}
-	return t
-}
-
-// ParseFile creates a new Template and parses the template definition from
-// the named file.  The template name is the base name of the file.
-func ParseFile(filename string) (*Template, os.Error) {
-	t := New(filepath.Base(filename))
-	return t.ParseFile(filename)
-}
-
-// parseFileInSet creates a new Template and parses the template
-// definition from the named file. The template name is the base name
-// of the file. It also adds the template to the set. Function bindings are
-// checked against those in the set.
-func parseFileInSet(filename string, set *Set) (*Template, os.Error) {
-	t := New(filepath.Base(filename))
-	return t.parseFileInSet(filename, set)
-}
-
-// ParseFile reads the template definition from a file and parses it to
-// construct an internal representation of the template for execution.
-// The returned template will be nil if an error occurs.
-func (t *Template) ParseFile(filename string) (*Template, os.Error) {
-	b, err := ioutil.ReadFile(filename)
-	if err != nil {
-		return nil, err
-	}
-	return t.Parse(string(b))
-}
-
-// parseFileInSet is the same as ParseFile except that function bindings
-// are checked against those in the set and the template is added
-// to the set.
-// The returned template will be nil if an error occurs.
-func (t *Template) parseFileInSet(filename string, set *Set) (*Template, os.Error) {
-	b, err := ioutil.ReadFile(filename)
-	if err != nil {
-		return nil, err
-	}
-	return t.ParseInSet(string(b), set)
-}
-
-// Functions and methods to parse a set.
-
-// SetMust is a helper that wraps a call to a function returning (*Set, os.Error)
-// and panics if the error is non-nil. It is intended for use in variable initializations
-// such as
-//	var s = template.SetMust(template.ParseSetFiles("file"))
-func SetMust(s *Set, err os.Error) *Set {
-	if err != nil {
-		panic(err)
-	}
-	return s
-}
-
-// ParseFiles parses the named files into a set of named templates.
-// Each file must be parseable by itself.
-// If an error occurs, parsing stops and the returned set is nil.
-func (s *Set) ParseFiles(filenames ...string) (*Set, os.Error) {
-	for _, filename := range filenames {
-		b, err := ioutil.ReadFile(filename)
-		if err != nil {
-			return nil, err
-		}
-		_, err = s.Parse(string(b))
-		if err != nil {
-			return nil, err
-		}
-	}
-	return s, nil
-}
-
-// ParseSetFiles creates a new Set and parses the set definition from the
-// named files. Each file must be individually parseable.
-func ParseSetFiles(filenames ...string) (*Set, os.Error) {
-	s := new(Set)
-	for _, filename := range filenames {
-		b, err := ioutil.ReadFile(filename)
-		if err != nil {
-			return nil, err
-		}
-		_, err = s.Parse(string(b))
-		if err != nil {
-			return nil, err
-		}
-	}
-	return s, nil
-}
-
-// ParseGlob parses the set definition from the files identified by the
-// pattern.  The pattern is processed by filepath.Glob and must match at
-// least one file.
-// If an error occurs, parsing stops and the returned set is nil.
-func (s *Set) ParseGlob(pattern string) (*Set, os.Error) {
-	filenames, err := filepath.Glob(pattern)
-	if err != nil {
-		return nil, err
-	}
-	if len(filenames) == 0 {
-		return nil, fmt.Errorf("pattern matches no files: %#q", pattern)
-	}
-	return s.ParseFiles(filenames...)
-}
-
-// ParseSetGlob creates a new Set and parses the set definition from the
-// files identified by the pattern. The pattern is processed by filepath.Glob
-// and must match at least one file.
-func ParseSetGlob(pattern string) (*Set, os.Error) {
-	set, err := new(Set).ParseGlob(pattern)
-	if err != nil {
-		return nil, err
-	}
-	return set, nil
-}
-
-// Functions and methods to parse stand-alone template files into a set.
-
-// ParseTemplateFiles parses the named template files and adds
-// them to the set. Each template will be named the base name of
-// its file.
-// Unlike with ParseFiles, each file should be a stand-alone template
-// definition suitable for Template.Parse (not Set.Parse); that is, the
-// file does not contain {{define}} clauses. ParseTemplateFiles is
-// therefore equivalent to calling the ParseFile function to create
-// individual templates, which are then added to the set.
-// Each file must be parseable by itself.
-// If an error occurs, parsing stops and the returned set is nil.
-func (s *Set) ParseTemplateFiles(filenames ...string) (*Set, os.Error) {
-	for _, filename := range filenames {
-		_, err := parseFileInSet(filename, s)
-		if err != nil {
-			return nil, err
-		}
-	}
-	return s, nil
-}
-
-// ParseTemplateGlob parses the template files matched by the
-// patern and adds them to the set. Each template will be named
-// the base name of its file.
-// Unlike with ParseGlob, each file should be a stand-alone template
-// definition suitable for Template.Parse (not Set.Parse); that is, the
-// file does not contain {{define}} clauses. ParseTemplateGlob is
-// therefore equivalent to calling the ParseFile function to create
-// individual templates, which are then added to the set.
-// Each file must be parseable by itself.
-// If an error occurs, parsing stops and the returned set is nil.
-func (s *Set) ParseTemplateGlob(pattern string) (*Set, os.Error) {
-	filenames, err := filepath.Glob(pattern)
-	if err != nil {
-		return nil, err
-	}
-	for _, filename := range filenames {
-		_, err := parseFileInSet(filename, s)
-		if err != nil {
-			return nil, err
-		}
-	}
-	return s, nil
-}
-
-// ParseTemplateFiles creates a set by parsing the named files,
-// each of which defines a single template. Each template will be
-// named the base name of its file.
-// Unlike with ParseFiles, each file should be a stand-alone template
-// definition suitable for Template.Parse (not Set.Parse); that is, the
-// file does not contain {{define}} clauses. ParseTemplateFiles is
-// therefore equivalent to calling the ParseFile function to create
-// individual templates, which are then added to the set.
-// Each file must be parseable by itself. Parsing stops if an error is
-// encountered.
-func ParseTemplateFiles(filenames ...string) (*Set, os.Error) {
-	set := new(Set)
-	set.init()
-	for _, filename := range filenames {
-		t, err := ParseFile(filename)
-		if err != nil {
-			return nil, err
-		}
-		if err := set.add(t); err != nil {
-			return nil, err
-		}
-	}
-	return set, nil
-}
-
-// ParseTemplateGlob creates a set by parsing the files matched
-// by the pattern, each of which defines a single template. The pattern
-// is processed by filepath.Glob and must match at least one file. Each
-// template will be named the base name of its file.
-// Unlike with ParseGlob, each file should be a stand-alone template
-// definition suitable for Template.Parse (not Set.Parse); that is, the
-// file does not contain {{define}} clauses. ParseTemplateGlob is
-// therefore equivalent to calling the ParseFile function to create
-// individual templates, which are then added to the set.
-// Each file must be parseable by itself. Parsing stops if an error is
-// encountered.
-func ParseTemplateGlob(pattern string) (*Set, os.Error) {
-	set := new(Set)
-	filenames, err := filepath.Glob(pattern)
-	if err != nil {
-		return nil, err
-	}
-	if len(filenames) == 0 {
-		return nil, fmt.Errorf("pattern matches no files: %#q", pattern)
-	}
-	for _, filename := range filenames {
-		t, err := ParseFile(filename)
-		if err != nil {
-			return nil, err
-		}
-		if err := set.add(t); err != nil {
-			return nil, err
-		}
-	}
-	return set, nil
-}
diff --git a/src/pkg/template/parse.go b/src/pkg/template/parse.go
deleted file mode 100644
index b089c59..0000000
--- a/src/pkg/template/parse.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2011 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 template
-
-import (
-	"os"
-	"reflect"
-	"template/parse"
-)
-
-// Template is the representation of a parsed template.
-type Template struct {
-	name string
-	*parse.Tree
-	// We use two maps, one for parsing and one for execution.
-	// This separation makes the API cleaner since it doesn't
-	// expose reflection to the client.
-	parseFuncs FuncMap
-	execFuncs  map[string]reflect.Value
-	set        *Set // can be nil.
-}
-
-// Name returns the name of the template.
-func (t *Template) Name() string {
-	return t.name
-}
-
-// Parsing.
-
-// New allocates a new template with the given name.
-func New(name string) *Template {
-	return &Template{
-		name:       name,
-		parseFuncs: make(FuncMap),
-		execFuncs:  make(map[string]reflect.Value),
-	}
-}
-
-// Funcs adds the elements of the argument map to the template's function
-// map.  It panics if a value in the map is not a function with appropriate
-// return type.
-// The return value is the template, so calls can be chained.
-func (t *Template) Funcs(funcMap FuncMap) *Template {
-	addValueFuncs(t.execFuncs, funcMap)
-	addFuncs(t.parseFuncs, funcMap)
-	return t
-}
-
-// Parse parses the template definition string to construct an internal
-// representation of the template for execution.
-func (t *Template) Parse(s string) (tmpl *Template, err os.Error) {
-	t.Tree, err = parse.New(t.name).Parse(s, t.parseFuncs, builtins)
-	if err != nil {
-		return nil, err
-	}
-	return t, nil
-}
-
-// ParseInSet parses the template definition string to construct an internal
-// representation of the template for execution. It also adds the template
-// to the set.
-// Function bindings are checked against those in the set.
-func (t *Template) ParseInSet(s string, set *Set) (tmpl *Template, err os.Error) {
-	var setFuncs FuncMap
-	if set != nil {
-		setFuncs = set.parseFuncs
-	}
-	t.Tree, err = parse.New(t.name).Parse(s, t.parseFuncs, setFuncs, builtins)
-	if err != nil {
-		return nil, err
-	}
-	t.addToSet(set)
-	return t, nil
-}
-
-// addToSet adds the template to the set, verifying it's not being double-assigned.
-func (t *Template) addToSet(set *Set) {
-	if set == nil || t.set == set {
-		return
-	}
-	// If double-assigned, Add will panic and we will turn that into an error.
-	set.Add(t)
-}
diff --git a/src/pkg/template/parse/Makefile b/src/pkg/template/parse/Makefile
deleted file mode 100644
index fe65858..0000000
--- a/src/pkg/template/parse/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../../Make.inc
-
-TARG=template/parse
-GOFILES=\
-	lex.go\
-	node.go\
-	parse.go\
-	set.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/template/parse/lex.go b/src/pkg/template/parse/lex.go
deleted file mode 100644
index 83ad6c6..0000000
--- a/src/pkg/template/parse/lex.go
+++ /dev/null
@@ -1,472 +0,0 @@
-// Copyright 2011 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 parse
-
-import (
-	"fmt"
-	"strings"
-	"unicode"
-	"utf8"
-)
-
-// item represents a token or text string returned from the scanner.
-type item struct {
-	typ itemType
-	val string
-}
-
-func (i item) String() string {
-	switch {
-	case i.typ == itemEOF:
-		return "EOF"
-	case i.typ == itemError:
-		return i.val
-	case i.typ > itemKeyword:
-		return fmt.Sprintf("<%s>", i.val)
-	case len(i.val) > 10:
-		return fmt.Sprintf("%.10q...", i.val)
-	}
-	return fmt.Sprintf("%q", i.val)
-}
-
-// itemType identifies the type of lex items.
-type itemType int
-
-const (
-	itemError        itemType = iota // error occurred; value is text of error
-	itemBool                         // boolean constant
-	itemChar                         // printable ASCII character; grab bag for comma etc.
-	itemCharConstant                 // character constant
-	itemComplex                      // complex constant (1+2i); imaginary is just a number
-	itemColonEquals                  // colon-equals (':=') introducing a declaration
-	itemEOF
-	itemField      // alphanumeric identifier, starting with '.', possibly chained ('.x.y')
-	itemIdentifier // alphanumeric identifier
-	itemLeftDelim  // left action delimiter
-	itemNumber     // simple number, including imaginary
-	itemPipe       // pipe symbol
-	itemRawString  // raw quoted string (includes quotes)
-	itemRightDelim // right action delimiter
-	itemString     // quoted string (includes quotes)
-	itemText       // plain text
-	itemVariable   // variable starting with '$', such as '$' or  '$1' or '$hello'.
-	// Keywords appear after all the rest.
-	itemKeyword  // used only to delimit the keywords
-	itemDot      // the cursor, spelled '.'.
-	itemDefine   // define keyword
-	itemElse     // else keyword
-	itemEnd      // end keyword
-	itemIf       // if keyword
-	itemRange    // range keyword
-	itemTemplate // template keyword
-	itemWith     // with keyword
-)
-
-// Make the types prettyprint.
-var itemName = map[itemType]string{
-	itemError:        "error",
-	itemBool:         "bool",
-	itemChar:         "char",
-	itemCharConstant: "charconst",
-	itemComplex:      "complex",
-	itemColonEquals:  ":=",
-	itemEOF:          "EOF",
-	itemField:        "field",
-	itemIdentifier:   "identifier",
-	itemLeftDelim:    "left delim",
-	itemNumber:       "number",
-	itemPipe:         "pipe",
-	itemRawString:    "raw string",
-	itemRightDelim:   "right delim",
-	itemString:       "string",
-	itemVariable:     "variable",
-	// keywords
-	itemDot:      ".",
-	itemDefine:   "define",
-	itemElse:     "else",
-	itemIf:       "if",
-	itemEnd:      "end",
-	itemRange:    "range",
-	itemTemplate: "template",
-	itemWith:     "with",
-}
-
-func (i itemType) String() string {
-	s := itemName[i]
-	if s == "" {
-		return fmt.Sprintf("item%d", int(i))
-	}
-	return s
-}
-
-var key = map[string]itemType{
-	".":        itemDot,
-	"define":   itemDefine,
-	"else":     itemElse,
-	"end":      itemEnd,
-	"if":       itemIf,
-	"range":    itemRange,
-	"template": itemTemplate,
-	"with":     itemWith,
-}
-
-const eof = -1
-
-// stateFn represents the state of the scanner as a function that returns the next state.
-type stateFn func(*lexer) stateFn
-
-// lexer holds the state of the scanner.
-type lexer struct {
-	name  string    // the name of the input; used only for error reports.
-	input string    // the string being scanned.
-	state stateFn   // the next lexing function to enter
-	pos   int       // current position in the input.
-	start int       // start position of this item.
-	width int       // width of last rune read from input.
-	items chan item // channel of scanned items.
-}
-
-// next returns the next rune in the input.
-func (l *lexer) next() (rune int) {
-	if l.pos >= len(l.input) {
-		l.width = 0
-		return eof
-	}
-	rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
-	l.pos += l.width
-	return rune
-}
-
-// peek returns but does not consume the next rune in the input.
-func (l *lexer) peek() int {
-	rune := l.next()
-	l.backup()
-	return rune
-}
-
-// backup steps back one rune. Can only be called once per call of next.
-func (l *lexer) backup() {
-	l.pos -= l.width
-}
-
-// emit passes an item back to the client.
-func (l *lexer) emit(t itemType) {
-	l.items <- item{t, l.input[l.start:l.pos]}
-	l.start = l.pos
-}
-
-// ignore skips over the pending input before this point.
-func (l *lexer) ignore() {
-	l.start = l.pos
-}
-
-// accept consumes the next rune if it's from the valid set.
-func (l *lexer) accept(valid string) bool {
-	if strings.IndexRune(valid, l.next()) >= 0 {
-		return true
-	}
-	l.backup()
-	return false
-}
-
-// acceptRun consumes a run of runes from the valid set.
-func (l *lexer) acceptRun(valid string) {
-	for strings.IndexRune(valid, l.next()) >= 0 {
-	}
-	l.backup()
-}
-
-// lineNumber reports which line we're on. Doing it this way
-// means we don't have to worry about peek double counting.
-func (l *lexer) lineNumber() int {
-	return 1 + strings.Count(l.input[:l.pos], "\n")
-}
-
-// error returns an error token and terminates the scan by passing
-// back a nil pointer that will be the next state, terminating l.run.
-func (l *lexer) errorf(format string, args ...interface{}) stateFn {
-	l.items <- item{itemError, fmt.Sprintf(format, args...)}
-	return nil
-}
-
-// nextItem returns the next item from the input.
-func (l *lexer) nextItem() item {
-	for {
-		select {
-		case item := <-l.items:
-			return item
-		default:
-			l.state = l.state(l)
-		}
-	}
-	panic("not reached")
-}
-
-// lex creates a new scanner for the input string.
-func lex(name, input string) *lexer {
-	l := &lexer{
-		name:  name,
-		input: input,
-		state: lexText,
-		items: make(chan item, 2), // Two items of buffering is sufficient for all state functions
-	}
-	return l
-}
-
-// state functions
-
-const (
-	leftDelim    = "{{"
-	rightDelim   = "}}"
-	leftComment  = "{{/*"
-	rightComment = "*/}}"
-)
-
-// lexText scans until an opening action delimiter, "{{".
-func lexText(l *lexer) stateFn {
-	for {
-		if strings.HasPrefix(l.input[l.pos:], leftDelim) {
-			if l.pos > l.start {
-				l.emit(itemText)
-			}
-			return lexLeftDelim
-		}
-		if l.next() == eof {
-			break
-		}
-	}
-	// Correctly reached EOF.
-	if l.pos > l.start {
-		l.emit(itemText)
-	}
-	l.emit(itemEOF)
-	return nil
-}
-
-// lexLeftDelim scans the left delimiter, which is known to be present.
-func lexLeftDelim(l *lexer) stateFn {
-	if strings.HasPrefix(l.input[l.pos:], leftComment) {
-		return lexComment
-	}
-	l.pos += len(leftDelim)
-	l.emit(itemLeftDelim)
-	return lexInsideAction
-}
-
-// lexComment scans a comment. The left comment marker is known to be present.
-func lexComment(l *lexer) stateFn {
-	i := strings.Index(l.input[l.pos:], rightComment)
-	if i < 0 {
-		return l.errorf("unclosed comment")
-	}
-	l.pos += i + len(rightComment)
-	l.ignore()
-	return lexText
-}
-
-// lexRightDelim scans the right delimiter, which is known to be present.
-func lexRightDelim(l *lexer) stateFn {
-	l.pos += len(rightDelim)
-	l.emit(itemRightDelim)
-	return lexText
-}
-
-// lexInsideAction scans the elements inside action delimiters.
-func lexInsideAction(l *lexer) stateFn {
-	// Either number, quoted string, or identifier.
-	// Spaces separate and are ignored.
-	// Pipe symbols separate and are emitted.
-	if strings.HasPrefix(l.input[l.pos:], rightDelim) {
-		return lexRightDelim
-	}
-	switch r := l.next(); {
-	case r == eof || r == '\n':
-		return l.errorf("unclosed action")
-	case isSpace(r):
-		l.ignore()
-	case r == ':':
-		if l.next() != '=' {
-			return l.errorf("expected :=")
-		}
-		l.emit(itemColonEquals)
-	case r == '|':
-		l.emit(itemPipe)
-	case r == '"':
-		return lexQuote
-	case r == '`':
-		return lexRawQuote
-	case r == '$':
-		return lexIdentifier
-	case r == '\'':
-		return lexChar
-	case r == '.':
-		// special look-ahead for ".field" so we don't break l.backup().
-		if l.pos < len(l.input) {
-			r := l.input[l.pos]
-			if r < '0' || '9' < r {
-				return lexIdentifier // itemDot comes from the keyword table.
-			}
-		}
-		fallthrough // '.' can start a number.
-	case r == '+' || r == '-' || ('0' <= r && r <= '9'):
-		l.backup()
-		return lexNumber
-	case isAlphaNumeric(r):
-		l.backup()
-		return lexIdentifier
-	case r <= unicode.MaxASCII && unicode.IsPrint(r):
-		l.emit(itemChar)
-		return lexInsideAction
-	default:
-		return l.errorf("unrecognized character in action: %#U", r)
-	}
-	return lexInsideAction
-}
-
-// lexIdentifier scans an alphanumeric or field.
-func lexIdentifier(l *lexer) stateFn {
-Loop:
-	for {
-		switch r := l.next(); {
-		case isAlphaNumeric(r):
-			// absorb.
-		case r == '.' && (l.input[l.start] == '.' || l.input[l.start] == '$'):
-			// field chaining; absorb into one token.
-		default:
-			l.backup()
-			word := l.input[l.start:l.pos]
-			switch {
-			case key[word] > itemKeyword:
-				l.emit(key[word])
-			case word[0] == '.':
-				l.emit(itemField)
-			case word[0] == '$':
-				l.emit(itemVariable)
-			case word == "true", word == "false":
-				l.emit(itemBool)
-			default:
-				l.emit(itemIdentifier)
-			}
-			break Loop
-		}
-	}
-	return lexInsideAction
-}
-
-// lexChar scans a character constant. The initial quote is already
-// scanned.  Syntax checking is done by the parse.
-func lexChar(l *lexer) stateFn {
-Loop:
-	for {
-		switch l.next() {
-		case '\\':
-			if r := l.next(); r != eof && r != '\n' {
-				break
-			}
-			fallthrough
-		case eof, '\n':
-			return l.errorf("unterminated character constant")
-		case '\'':
-			break Loop
-		}
-	}
-	l.emit(itemCharConstant)
-	return lexInsideAction
-}
-
-// lexNumber scans a number: decimal, octal, hex, float, or imaginary.  This
-// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
-// and "089" - but when it's wrong the input is invalid and the parser (via
-// strconv) will notice.
-func lexNumber(l *lexer) stateFn {
-	if !l.scanNumber() {
-		return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
-	}
-	if sign := l.peek(); sign == '+' || sign == '-' {
-		// Complex: 1+2i.  No spaces, must end in 'i'.
-		if !l.scanNumber() || l.input[l.pos-1] != 'i' {
-			return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
-		}
-		l.emit(itemComplex)
-	} else {
-		l.emit(itemNumber)
-	}
-	return lexInsideAction
-}
-
-func (l *lexer) scanNumber() bool {
-	// Optional leading sign.
-	l.accept("+-")
-	// Is it hex?
-	digits := "0123456789"
-	if l.accept("0") && l.accept("xX") {
-		digits = "0123456789abcdefABCDEF"
-	}
-	l.acceptRun(digits)
-	if l.accept(".") {
-		l.acceptRun(digits)
-	}
-	if l.accept("eE") {
-		l.accept("+-")
-		l.acceptRun("0123456789")
-	}
-	// Is it imaginary?
-	l.accept("i")
-	// Next thing mustn't be alphanumeric.
-	if isAlphaNumeric(l.peek()) {
-		l.next()
-		return false
-	}
-	return true
-}
-
-// lexQuote scans a quoted string.
-func lexQuote(l *lexer) stateFn {
-Loop:
-	for {
-		switch l.next() {
-		case '\\':
-			if r := l.next(); r != eof && r != '\n' {
-				break
-			}
-			fallthrough
-		case eof, '\n':
-			return l.errorf("unterminated quoted string")
-		case '"':
-			break Loop
-		}
-	}
-	l.emit(itemString)
-	return lexInsideAction
-}
-
-// lexRawQuote scans a raw quoted string.
-func lexRawQuote(l *lexer) stateFn {
-Loop:
-	for {
-		switch l.next() {
-		case eof, '\n':
-			return l.errorf("unterminated raw quoted string")
-		case '`':
-			break Loop
-		}
-	}
-	l.emit(itemRawString)
-	return lexInsideAction
-}
-
-// isSpace reports whether r is a space character.
-func isSpace(r int) bool {
-	switch r {
-	case ' ', '\t', '\n', '\r':
-		return true
-	}
-	return false
-}
-
-// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
-func isAlphaNumeric(r int) bool {
-	return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
-}
diff --git a/src/pkg/template/parse/lex_test.go b/src/pkg/template/parse/lex_test.go
deleted file mode 100644
index d71c8e6..0000000
--- a/src/pkg/template/parse/lex_test.go
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2011 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 parse
-
-import (
-	"reflect"
-	"testing"
-)
-
-type lexTest struct {
-	name  string
-	input string
-	items []item
-}
-
-var (
-	tEOF      = item{itemEOF, ""}
-	tLeft     = item{itemLeftDelim, "{{"}
-	tRight    = item{itemRightDelim, "}}"}
-	tRange    = item{itemRange, "range"}
-	tPipe     = item{itemPipe, "|"}
-	tFor      = item{itemIdentifier, "for"}
-	tQuote    = item{itemString, `"abc \n\t\" "`}
-	raw       = "`" + `abc\n\t\" ` + "`"
-	tRawQuote = item{itemRawString, raw}
-)
-
-var lexTests = []lexTest{
-	{"empty", "", []item{tEOF}},
-	{"spaces", " \t\n", []item{{itemText, " \t\n"}, tEOF}},
-	{"text", `now is the time`, []item{{itemText, "now is the time"}, tEOF}},
-	{"text with comment", "hello-{{/* this is a comment */}}-world", []item{
-		{itemText, "hello-"},
-		{itemText, "-world"},
-		tEOF,
-	}},
-	{"punctuation", "{{,@%}}", []item{
-		tLeft,
-		{itemChar, ","},
-		{itemChar, "@"},
-		{itemChar, "%"},
-		tRight,
-		tEOF,
-	}},
-	{"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
-	{"for", `{{for }}`, []item{tLeft, tFor, tRight, tEOF}},
-	{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
-	{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
-	{"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{
-		tLeft,
-		{itemNumber, "1"},
-		{itemNumber, "02"},
-		{itemNumber, "0x14"},
-		{itemNumber, "-7.2i"},
-		{itemNumber, "1e3"},
-		{itemNumber, "+1.2e-4"},
-		{itemNumber, "4.2i"},
-		{itemComplex, "1+2i"},
-		tRight,
-		tEOF,
-	}},
-	{"characters", `{{'a' '\n' '\'' '\\' '\u00FF' '\xFF' '本'}}`, []item{
-		tLeft,
-		{itemCharConstant, `'a'`},
-		{itemCharConstant, `'\n'`},
-		{itemCharConstant, `'\''`},
-		{itemCharConstant, `'\\'`},
-		{itemCharConstant, `'\u00FF'`},
-		{itemCharConstant, `'\xFF'`},
-		{itemCharConstant, `'本'`},
-		tRight,
-		tEOF,
-	}},
-	{"bools", "{{true false}}", []item{
-		tLeft,
-		{itemBool, "true"},
-		{itemBool, "false"},
-		tRight,
-		tEOF,
-	}},
-	{"dot", "{{.}}", []item{
-		tLeft,
-		{itemDot, "."},
-		tRight,
-		tEOF,
-	}},
-	{"dots", "{{.x . .2 .x.y}}", []item{
-		tLeft,
-		{itemField, ".x"},
-		{itemDot, "."},
-		{itemNumber, ".2"},
-		{itemField, ".x.y"},
-		tRight,
-		tEOF,
-	}},
-	{"keywords", "{{range if else end with}}", []item{
-		tLeft,
-		{itemRange, "range"},
-		{itemIf, "if"},
-		{itemElse, "else"},
-		{itemEnd, "end"},
-		{itemWith, "with"},
-		tRight,
-		tEOF,
-	}},
-	{"variables", "{{$c := printf $ $hello $23 $ $var.Field .Method}}", []item{
-		tLeft,
-		{itemVariable, "$c"},
-		{itemColonEquals, ":="},
-		{itemIdentifier, "printf"},
-		{itemVariable, "$"},
-		{itemVariable, "$hello"},
-		{itemVariable, "$23"},
-		{itemVariable, "$"},
-		{itemVariable, "$var.Field"},
-		{itemField, ".Method"},
-		tRight,
-		tEOF,
-	}},
-	{"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{
-		{itemText, "intro "},
-		tLeft,
-		{itemIdentifier, "echo"},
-		{itemIdentifier, "hi"},
-		{itemNumber, "1.2"},
-		tPipe,
-		{itemIdentifier, "noargs"},
-		tPipe,
-		{itemIdentifier, "args"},
-		{itemNumber, "1"},
-		{itemString, `"hi"`},
-		tRight,
-		{itemText, " outro"},
-		tEOF,
-	}},
-	{"declaration", "{{$v := 3}}", []item{
-		tLeft,
-		{itemVariable, "$v"},
-		{itemColonEquals, ":="},
-		{itemNumber, "3"},
-		tRight,
-		tEOF,
-	}},
-	{"2 declarations", "{{$v , $w := 3}}", []item{
-		tLeft,
-		{itemVariable, "$v"},
-		{itemChar, ","},
-		{itemVariable, "$w"},
-		{itemColonEquals, ":="},
-		{itemNumber, "3"},
-		tRight,
-		tEOF,
-	}},
-	// errors
-	{"badchar", "#{{\x01}}", []item{
-		{itemText, "#"},
-		tLeft,
-		{itemError, "unrecognized character in action: U+0001"},
-	}},
-	{"unclosed action", "{{\n}}", []item{
-		tLeft,
-		{itemError, "unclosed action"},
-	}},
-	{"EOF in action", "{{range", []item{
-		tLeft,
-		tRange,
-		{itemError, "unclosed action"},
-	}},
-	{"unclosed quote", "{{\"\n\"}}", []item{
-		tLeft,
-		{itemError, "unterminated quoted string"},
-	}},
-	{"unclosed raw quote", "{{`xx\n`}}", []item{
-		tLeft,
-		{itemError, "unterminated raw quoted string"},
-	}},
-	{"unclosed char constant", "{{'\n}}", []item{
-		tLeft,
-		{itemError, "unterminated character constant"},
-	}},
-	{"bad number", "{{3k}}", []item{
-		tLeft,
-		{itemError, `bad number syntax: "3k"`},
-	}},
-
-	// Fixed bugs
-	// Many elements in an action blew the lookahead until
-	// we made lexInsideAction not loop.
-	{"long pipeline deadlock", "{{|||||}}", []item{
-		tLeft,
-		tPipe,
-		tPipe,
-		tPipe,
-		tPipe,
-		tPipe,
-		tRight,
-		tEOF,
-	}},
-}
-
-// collect gathers the emitted items into a slice.
-func collect(t *lexTest) (items []item) {
-	l := lex(t.name, t.input)
-	for {
-		item := l.nextItem()
-		items = append(items, item)
-		if item.typ == itemEOF || item.typ == itemError {
-			break
-		}
-	}
-	return
-}
-
-func TestLex(t *testing.T) {
-	for _, test := range lexTests {
-		items := collect(&test)
-		if !reflect.DeepEqual(items, test.items) {
-			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
-		}
-	}
-}
diff --git a/src/pkg/template/parse/node.go b/src/pkg/template/parse/node.go
deleted file mode 100644
index 7411327..0000000
--- a/src/pkg/template/parse/node.go
+++ /dev/null
@@ -1,464 +0,0 @@
-// Copyright 2011 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.
-
-// Parse nodes.
-
-package parse
-
-import (
-	"bytes"
-	"fmt"
-	"os"
-	"strconv"
-	"strings"
-)
-
-// A node is an element in the parse tree. The interface is trivial.
-type Node interface {
-	Type() NodeType
-	String() string
-}
-
-// NodeType identifies the type of a parse tree node.
-type NodeType int
-
-// Type returns itself and provides an easy default implementation
-// for embedding in a Node. Embedded in all non-trivial Nodes.
-func (t NodeType) Type() NodeType {
-	return t
-}
-
-const (
-	NodeText       NodeType = iota // Plain text.
-	NodeAction                     // A simple action such as field evaluation.
-	NodeBool                       // A boolean constant.
-	NodeCommand                    // An element of a pipeline.
-	NodeDot                        // The cursor, dot.
-	nodeElse                       // An else action. Not added to tree.
-	nodeEnd                        // An end action. Not added to tree.
-	NodeField                      // A field or method name.
-	NodeIdentifier                 // An identifier; always a function name.
-	NodeIf                         // An if action.
-	NodeList                       // A list of Nodes.
-	NodeNumber                     // A numerical constant.
-	NodePipe                       // A pipeline of commands.
-	NodeRange                      // A range action.
-	NodeString                     // A string constant.
-	NodeTemplate                   // A template invocation action.
-	NodeVariable                   // A $ variable.
-	NodeWith                       // A with action.
-)
-
-// Nodes.
-
-// ListNode holds a sequence of nodes.
-type ListNode struct {
-	NodeType
-	Nodes []Node // The element nodes in lexical order.
-}
-
-func newList() *ListNode {
-	return &ListNode{NodeType: NodeList}
-}
-
-func (l *ListNode) append(n Node) {
-	l.Nodes = append(l.Nodes, n)
-}
-
-func (l *ListNode) String() string {
-	b := new(bytes.Buffer)
-	fmt.Fprint(b, "[")
-	for _, n := range l.Nodes {
-		fmt.Fprint(b, n)
-	}
-	fmt.Fprint(b, "]")
-	return b.String()
-}
-
-// TextNode holds plain text.
-type TextNode struct {
-	NodeType
-	Text []byte // The text; may span newlines.
-}
-
-func newText(text string) *TextNode {
-	return &TextNode{NodeType: NodeText, Text: []byte(text)}
-}
-
-func (t *TextNode) String() string {
-	return fmt.Sprintf("(text: %q)", t.Text)
-}
-
-// PipeNode holds a pipeline with optional declaration
-type PipeNode struct {
-	NodeType
-	Line int             // The line number in the input.
-	Decl []*VariableNode // Variable declarations in lexical order.
-	Cmds []*CommandNode  // The commands in lexical order.
-}
-
-func newPipeline(line int, decl []*VariableNode) *PipeNode {
-	return &PipeNode{NodeType: NodePipe, Line: line, Decl: decl}
-}
-
-func (p *PipeNode) append(command *CommandNode) {
-	p.Cmds = append(p.Cmds, command)
-}
-
-func (p *PipeNode) String() string {
-	if p.Decl != nil {
-		return fmt.Sprintf("%v := %v", p.Decl, p.Cmds)
-	}
-	return fmt.Sprintf("%v", p.Cmds)
-}
-
-// ActionNode holds an action (something bounded by delimiters).
-// Control actions have their own nodes; ActionNode represents simple
-// ones such as field evaluations.
-type ActionNode struct {
-	NodeType
-	Line int       // The line number in the input.
-	Pipe *PipeNode // The pipeline in the action.
-}
-
-func newAction(line int, pipe *PipeNode) *ActionNode {
-	return &ActionNode{NodeType: NodeAction, Line: line, Pipe: pipe}
-}
-
-func (a *ActionNode) String() string {
-	return fmt.Sprintf("(action: %v)", a.Pipe)
-}
-
-// CommandNode holds a command (a pipeline inside an evaluating action).
-type CommandNode struct {
-	NodeType
-	Args []Node // Arguments in lexical order: Identifier, field, or constant.
-}
-
-func newCommand() *CommandNode {
-	return &CommandNode{NodeType: NodeCommand}
-}
-
-func (c *CommandNode) append(arg Node) {
-	c.Args = append(c.Args, arg)
-}
-
-func (c *CommandNode) String() string {
-	return fmt.Sprintf("(command: %v)", c.Args)
-}
-
-// IdentifierNode holds an identifier.
-type IdentifierNode struct {
-	NodeType
-	Ident string // The identifier's name.
-}
-
-// NewIdentifier returns a new IdentifierNode with the given identifier name.
-func NewIdentifier(ident string) *IdentifierNode {
-	return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
-}
-
-func (i *IdentifierNode) String() string {
-	return fmt.Sprintf("I=%s", i.Ident)
-}
-
-// VariableNode holds a list of variable names. The dollar sign is
-// part of the name.
-type VariableNode struct {
-	NodeType
-	Ident []string // Variable names in lexical order.
-}
-
-func newVariable(ident string) *VariableNode {
-	return &VariableNode{NodeType: NodeVariable, Ident: strings.Split(ident, ".")}
-}
-
-func (v *VariableNode) String() string {
-	return fmt.Sprintf("V=%s", v.Ident)
-}
-
-// DotNode holds the special identifier '.'. It is represented by a nil pointer.
-type DotNode bool
-
-func newDot() *DotNode {
-	return nil
-}
-
-func (d *DotNode) Type() NodeType {
-	return NodeDot
-}
-
-func (d *DotNode) String() string {
-	return "{{<.>}}"
-}
-
-// FieldNode holds a field (identifier starting with '.').
-// The names may be chained ('.x.y').
-// The period is dropped from each ident.
-type FieldNode struct {
-	NodeType
-	Ident []string // The identifiers in lexical order.
-}
-
-func newField(ident string) *FieldNode {
-	return &FieldNode{NodeType: NodeField, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
-}
-
-func (f *FieldNode) String() string {
-	return fmt.Sprintf("F=%s", f.Ident)
-}
-
-// BoolNode holds a boolean constant.
-type BoolNode struct {
-	NodeType
-	True bool // The value of the boolean constant.
-}
-
-func newBool(true bool) *BoolNode {
-	return &BoolNode{NodeType: NodeBool, True: true}
-}
-
-func (b *BoolNode) String() string {
-	return fmt.Sprintf("B=%t", b.True)
-}
-
-// NumberNode holds a number: signed or unsigned integer, float, or complex.
-// The value is parsed and stored under all the types that can represent the value.
-// This simulates in a small amount of code the behavior of Go's ideal constants.
-type NumberNode struct {
-	NodeType
-	IsInt      bool       // Number has an integral value.
-	IsUint     bool       // Number has an unsigned integral value.
-	IsFloat    bool       // Number has a floating-point value.
-	IsComplex  bool       // Number is complex.
-	Int64      int64      // The signed integer value.
-	Uint64     uint64     // The unsigned integer value.
-	Float64    float64    // The floating-point value.
-	Complex128 complex128 // The complex value.
-	Text       string     // The original textual representation from the input.
-}
-
-func newNumber(text string, typ itemType) (*NumberNode, os.Error) {
-	n := &NumberNode{NodeType: NodeNumber, Text: text}
-	switch typ {
-	case itemCharConstant:
-		rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
-		if err != nil {
-			return nil, err
-		}
-		if tail != "'" {
-			return nil, fmt.Errorf("malformed character constant: %s", text)
-		}
-		n.Int64 = int64(rune)
-		n.IsInt = true
-		n.Uint64 = uint64(rune)
-		n.IsUint = true
-		n.Float64 = float64(rune) // odd but those are the rules.
-		n.IsFloat = true
-		return n, nil
-	case itemComplex:
-		// fmt.Sscan can parse the pair, so let it do the work.
-		if _, err := fmt.Sscan(text, &n.Complex128); err != nil {
-			return nil, err
-		}
-		n.IsComplex = true
-		n.simplifyComplex()
-		return n, nil
-	}
-	// Imaginary constants can only be complex unless they are zero.
-	if len(text) > 0 && text[len(text)-1] == 'i' {
-		f, err := strconv.Atof64(text[:len(text)-1])
-		if err == nil {
-			n.IsComplex = true
-			n.Complex128 = complex(0, f)
-			n.simplifyComplex()
-			return n, nil
-		}
-	}
-	// Do integer test first so we get 0x123 etc.
-	u, err := strconv.Btoui64(text, 0) // will fail for -0; fixed below.
-	if err == nil {
-		n.IsUint = true
-		n.Uint64 = u
-	}
-	i, err := strconv.Btoi64(text, 0)
-	if err == nil {
-		n.IsInt = true
-		n.Int64 = i
-		if i == 0 {
-			n.IsUint = true // in case of -0.
-			n.Uint64 = u
-		}
-	}
-	// If an integer extraction succeeded, promote the float.
-	if n.IsInt {
-		n.IsFloat = true
-		n.Float64 = float64(n.Int64)
-	} else if n.IsUint {
-		n.IsFloat = true
-		n.Float64 = float64(n.Uint64)
-	} else {
-		f, err := strconv.Atof64(text)
-		if err == nil {
-			n.IsFloat = true
-			n.Float64 = f
-			// If a floating-point extraction succeeded, extract the int if needed.
-			if !n.IsInt && float64(int64(f)) == f {
-				n.IsInt = true
-				n.Int64 = int64(f)
-			}
-			if !n.IsUint && float64(uint64(f)) == f {
-				n.IsUint = true
-				n.Uint64 = uint64(f)
-			}
-		}
-	}
-	if !n.IsInt && !n.IsUint && !n.IsFloat {
-		return nil, fmt.Errorf("illegal number syntax: %q", text)
-	}
-	return n, nil
-}
-
-// simplifyComplex pulls out any other types that are represented by the complex number.
-// These all require that the imaginary part be zero.
-func (n *NumberNode) simplifyComplex() {
-	n.IsFloat = imag(n.Complex128) == 0
-	if n.IsFloat {
-		n.Float64 = real(n.Complex128)
-		n.IsInt = float64(int64(n.Float64)) == n.Float64
-		if n.IsInt {
-			n.Int64 = int64(n.Float64)
-		}
-		n.IsUint = float64(uint64(n.Float64)) == n.Float64
-		if n.IsUint {
-			n.Uint64 = uint64(n.Float64)
-		}
-	}
-}
-
-func (n *NumberNode) String() string {
-	return fmt.Sprintf("N=%s", n.Text)
-}
-
-// StringNode holds a string constant. The value has been "unquoted".
-type StringNode struct {
-	NodeType
-	Quoted string // The original text of the string, with quotes.
-	Text   string // The string, after quote processing.
-}
-
-func newString(orig, text string) *StringNode {
-	return &StringNode{NodeType: NodeString, Quoted: orig, Text: text}
-}
-
-func (s *StringNode) String() string {
-	return fmt.Sprintf("S=%#q", s.Text)
-}
-
-// endNode represents an {{end}} action. It is represented by a nil pointer.
-// It does not appear in the final parse tree.
-type endNode bool
-
-func newEnd() *endNode {
-	return nil
-}
-
-func (e *endNode) Type() NodeType {
-	return nodeEnd
-}
-
-func (e *endNode) String() string {
-	return "{{end}}"
-}
-
-// elseNode represents an {{else}} action. Does not appear in the final tree.
-type elseNode struct {
-	NodeType
-	Line int // The line number in the input.
-}
-
-func newElse(line int) *elseNode {
-	return &elseNode{NodeType: nodeElse, Line: line}
-}
-
-func (e *elseNode) Type() NodeType {
-	return nodeElse
-}
-
-func (e *elseNode) String() string {
-	return "{{else}}"
-}
-
-// BranchNode is the common representation of if, range, and with.
-type BranchNode struct {
-	NodeType
-	Line     int       // The line number in the input.
-	Pipe     *PipeNode // The pipeline to be evaluated.
-	List     *ListNode // What to execute if the value is non-empty.
-	ElseList *ListNode // What to execute if the value is empty (nil if absent).
-}
-
-func (b *BranchNode) String() string {
-	name := ""
-	switch b.NodeType {
-	case NodeIf:
-		name = "if"
-	case NodeRange:
-		name = "range"
-	case NodeWith:
-		name = "with"
-	default:
-		panic("unknown branch type")
-	}
-	if b.ElseList != nil {
-		return fmt.Sprintf("({{%s %s}} %s {{else}} %s)", name, b.Pipe, b.List, b.ElseList)
-	}
-	return fmt.Sprintf("({{%s %s}} %s)", name, b.Pipe, b.List)
-}
-
-// IfNode represents an {{if}} action and its commands.
-type IfNode struct {
-	BranchNode
-}
-
-func newIf(line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
-	return &IfNode{BranchNode{NodeType: NodeIf, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
-}
-
-// RangeNode represents a {{range}} action and its commands.
-type RangeNode struct {
-	BranchNode
-}
-
-func newRange(line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
-	return &RangeNode{BranchNode{NodeType: NodeRange, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
-}
-
-// WithNode represents a {{with}} action and its commands.
-type WithNode struct {
-	BranchNode
-}
-
-func newWith(line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
-	return &WithNode{BranchNode{NodeType: NodeWith, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
-}
-
-// TemplateNode represents a {{template}} action.
-type TemplateNode struct {
-	NodeType
-	Line int       // The line number in the input.
-	Name string    // The name of the template (unquoted).
-	Pipe *PipeNode // The command to evaluate as dot for the template.
-}
-
-func newTemplate(line int, name string, pipe *PipeNode) *TemplateNode {
-	return &TemplateNode{NodeType: NodeTemplate, Line: line, Name: name, Pipe: pipe}
-}
-
-func (t *TemplateNode) String() string {
-	if t.Pipe == nil {
-		return fmt.Sprintf("{{template %q}}", t.Name)
-	}
-	return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
-}
diff --git a/src/pkg/template/parse/parse.go b/src/pkg/template/parse/parse.go
deleted file mode 100644
index 6918074..0000000
--- a/src/pkg/template/parse/parse.go
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright 2011 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 parse builds parse trees for templates.  The grammar is defined
-// in the documents for the template package.
-package parse
-
-import (
-	"fmt"
-	"os"
-	"runtime"
-	"strconv"
-	"unicode"
-)
-
-// Tree is the representation of a parsed template.
-type Tree struct {
-	Name string    // Name is the name of the template.
-	Root *ListNode // Root is the top-level root of the parse tree.
-	// Parsing only; cleared after parse.
-	funcs     []map[string]interface{}
-	lex       *lexer
-	token     [2]item // two-token lookahead for parser.
-	peekCount int
-	vars      []string // variables defined at the moment.
-}
-
-// next returns the next token.
-func (t *Tree) next() item {
-	if t.peekCount > 0 {
-		t.peekCount--
-	} else {
-		t.token[0] = t.lex.nextItem()
-	}
-	return t.token[t.peekCount]
-}
-
-// backup backs the input stream up one token.
-func (t *Tree) backup() {
-	t.peekCount++
-}
-
-// backup2 backs the input stream up two tokens
-func (t *Tree) backup2(t1 item) {
-	t.token[1] = t1
-	t.peekCount = 2
-}
-
-// peek returns but does not consume the next token.
-func (t *Tree) peek() item {
-	if t.peekCount > 0 {
-		return t.token[t.peekCount-1]
-	}
-	t.peekCount = 1
-	t.token[0] = t.lex.nextItem()
-	return t.token[0]
-}
-
-// Parsing.
-
-// New allocates a new template with the given name.
-func New(name string, funcs ...map[string]interface{}) *Tree {
-	return &Tree{
-		Name:  name,
-		funcs: funcs,
-	}
-}
-
-// errorf formats the error and terminates processing.
-func (t *Tree) errorf(format string, args ...interface{}) {
-	t.Root = nil
-	format = fmt.Sprintf("template: %s:%d: %s", t.Name, t.lex.lineNumber(), format)
-	panic(fmt.Errorf(format, args...))
-}
-
-// error terminates processing.
-func (t *Tree) error(err os.Error) {
-	t.errorf("%s", err)
-}
-
-// expect consumes the next token and guarantees it has the required type.
-func (t *Tree) expect(expected itemType, context string) item {
-	token := t.next()
-	if token.typ != expected {
-		t.errorf("expected %s in %s; got %s", expected, context, token)
-	}
-	return token
-}
-
-// unexpected complains about the token and terminates processing.
-func (t *Tree) unexpected(token item, context string) {
-	t.errorf("unexpected %s in %s", token, context)
-}
-
-// recover is the handler that turns panics into returns from the top level of Parse.
-func (t *Tree) recover(errp *os.Error) {
-	e := recover()
-	if e != nil {
-		if _, ok := e.(runtime.Error); ok {
-			panic(e)
-		}
-		if t != nil {
-			t.stopParse()
-		}
-		*errp = e.(os.Error)
-	}
-	return
-}
-
-// startParse starts the template parsing from the lexer.
-func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) {
-	t.Root = nil
-	t.lex = lex
-	t.vars = []string{"$"}
-	t.funcs = funcs
-}
-
-// stopParse terminates parsing.
-func (t *Tree) stopParse() {
-	t.lex = nil
-	t.vars = nil
-	t.funcs = nil
-}
-
-// atEOF returns true if, possibly after spaces, we're at EOF.
-func (t *Tree) atEOF() bool {
-	for {
-		token := t.peek()
-		switch token.typ {
-		case itemEOF:
-			return true
-		case itemText:
-			for _, r := range token.val {
-				if !unicode.IsSpace(r) {
-					return false
-				}
-			}
-			t.next() // skip spaces.
-			continue
-		}
-		break
-	}
-	return false
-}
-
-// Parse parses the template definition string to construct an internal
-// representation of the template for execution.
-func (t *Tree) Parse(s string, funcs ...map[string]interface{}) (tree *Tree, err os.Error) {
-	defer t.recover(&err)
-	t.startParse(funcs, lex(t.Name, s))
-	t.parse(true)
-	t.stopParse()
-	return t, nil
-}
-
-// parse is the helper for Parse.
-// It triggers an error if we expect EOF but don't reach it.
-func (t *Tree) parse(toEOF bool) (next Node) {
-	t.Root, next = t.itemList(true)
-	if toEOF && next != nil {
-		t.errorf("unexpected %s", next)
-	}
-	return next
-}
-
-// itemList:
-//	textOrAction*
-// Terminates at EOF and at {{end}} or {{else}}, which is returned separately.
-// The toEOF flag tells whether we expect to reach EOF.
-func (t *Tree) itemList(toEOF bool) (list *ListNode, next Node) {
-	list = newList()
-	for t.peek().typ != itemEOF {
-		n := t.textOrAction()
-		switch n.Type() {
-		case nodeEnd, nodeElse:
-			return list, n
-		}
-		list.append(n)
-	}
-	if !toEOF {
-		t.unexpected(t.next(), "input")
-	}
-	return list, nil
-}
-
-// textOrAction:
-//	text | action
-func (t *Tree) textOrAction() Node {
-	switch token := t.next(); token.typ {
-	case itemText:
-		return newText(token.val)
-	case itemLeftDelim:
-		return t.action()
-	default:
-		t.unexpected(token, "input")
-	}
-	return nil
-}
-
-// Action:
-//	control
-//	command ("|" command)*
-// Left delim is past. Now get actions.
-// First word could be a keyword such as range.
-func (t *Tree) action() (n Node) {
-	switch token := t.next(); token.typ {
-	case itemElse:
-		return t.elseControl()
-	case itemEnd:
-		return t.endControl()
-	case itemIf:
-		return t.ifControl()
-	case itemRange:
-		return t.rangeControl()
-	case itemTemplate:
-		return t.templateControl()
-	case itemWith:
-		return t.withControl()
-	}
-	t.backup()
-	// Do not pop variables; they persist until "end".
-	return newAction(t.lex.lineNumber(), t.pipeline("command"))
-}
-
-// Pipeline:
-//	field or command
-//	pipeline "|" pipeline
-func (t *Tree) pipeline(context string) (pipe *PipeNode) {
-	var decl []*VariableNode
-	// Are there declarations?
-	for {
-		if v := t.peek(); v.typ == itemVariable {
-			t.next()
-			if next := t.peek(); next.typ == itemColonEquals || next.typ == itemChar {
-				t.next()
-				variable := newVariable(v.val)
-				if len(variable.Ident) != 1 {
-					t.errorf("illegal variable in declaration: %s", v.val)
-				}
-				decl = append(decl, variable)
-				t.vars = append(t.vars, v.val)
-				if next.typ == itemChar && next.val == "," {
-					if context == "range" && len(decl) < 2 {
-						continue
-					}
-					t.errorf("too many declarations in %s", context)
-				}
-			} else {
-				t.backup2(v)
-			}
-		}
-		break
-	}
-	pipe = newPipeline(t.lex.lineNumber(), decl)
-	for {
-		switch token := t.next(); token.typ {
-		case itemRightDelim:
-			if len(pipe.Cmds) == 0 {
-				t.errorf("missing value for %s", context)
-			}
-			return
-		case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
-			itemVariable, itemNumber, itemRawString, itemString:
-			t.backup()
-			pipe.append(t.command())
-		default:
-			t.unexpected(token, context)
-		}
-	}
-	return
-}
-
-func (t *Tree) parseControl(context string) (lineNum int, pipe *PipeNode, list, elseList *ListNode) {
-	lineNum = t.lex.lineNumber()
-	defer t.popVars(len(t.vars))
-	pipe = t.pipeline(context)
-	var next Node
-	list, next = t.itemList(false)
-	switch next.Type() {
-	case nodeEnd: //done
-	case nodeElse:
-		elseList, next = t.itemList(false)
-		if next.Type() != nodeEnd {
-			t.errorf("expected end; found %s", next)
-		}
-		elseList = elseList
-	}
-	return lineNum, pipe, list, elseList
-}
-
-// If:
-//	{{if pipeline}} itemList {{end}}
-//	{{if pipeline}} itemList {{else}} itemList {{end}}
-// If keyword is past.
-func (t *Tree) ifControl() Node {
-	return newIf(t.parseControl("if"))
-}
-
-// Range:
-//	{{range pipeline}} itemList {{end}}
-//	{{range pipeline}} itemList {{else}} itemList {{end}}
-// Range keyword is past.
-func (t *Tree) rangeControl() Node {
-	return newRange(t.parseControl("range"))
-}
-
-// With:
-//	{{with pipeline}} itemList {{end}}
-//	{{with pipeline}} itemList {{else}} itemList {{end}}
-// If keyword is past.
-func (t *Tree) withControl() Node {
-	return newWith(t.parseControl("with"))
-}
-
-// End:
-//	{{end}}
-// End keyword is past.
-func (t *Tree) endControl() Node {
-	t.expect(itemRightDelim, "end")
-	return newEnd()
-}
-
-// Else:
-//	{{else}}
-// Else keyword is past.
-func (t *Tree) elseControl() Node {
-	t.expect(itemRightDelim, "else")
-	return newElse(t.lex.lineNumber())
-}
-
-// Template:
-//	{{template stringValue pipeline}}
-// Template keyword is past.  The name must be something that can evaluate
-// to a string.
-func (t *Tree) templateControl() Node {
-	var name string
-	switch token := t.next(); token.typ {
-	case itemString, itemRawString:
-		s, err := strconv.Unquote(token.val)
-		if err != nil {
-			t.error(err)
-		}
-		name = s
-	default:
-		t.unexpected(token, "template invocation")
-	}
-	var pipe *PipeNode
-	if t.next().typ != itemRightDelim {
-		t.backup()
-		// Do not pop variables; they persist until "end".
-		pipe = t.pipeline("template")
-	}
-	return newTemplate(t.lex.lineNumber(), name, pipe)
-}
-
-// command:
-// space-separated arguments up to a pipeline character or right delimiter.
-// we consume the pipe character but leave the right delim to terminate the action.
-func (t *Tree) command() *CommandNode {
-	cmd := newCommand()
-Loop:
-	for {
-		switch token := t.next(); token.typ {
-		case itemRightDelim:
-			t.backup()
-			break Loop
-		case itemPipe:
-			break Loop
-		case itemError:
-			t.errorf("%s", token.val)
-		case itemIdentifier:
-			if !t.hasFunction(token.val) {
-				t.errorf("function %q not defined", token.val)
-			}
-			cmd.append(NewIdentifier(token.val))
-		case itemDot:
-			cmd.append(newDot())
-		case itemVariable:
-			cmd.append(t.useVar(token.val))
-		case itemField:
-			cmd.append(newField(token.val))
-		case itemBool:
-			cmd.append(newBool(token.val == "true"))
-		case itemCharConstant, itemComplex, itemNumber:
-			number, err := newNumber(token.val, token.typ)
-			if err != nil {
-				t.error(err)
-			}
-			cmd.append(number)
-		case itemString, itemRawString:
-			s, err := strconv.Unquote(token.val)
-			if err != nil {
-				t.error(err)
-			}
-			cmd.append(newString(token.val, s))
-		default:
-			t.unexpected(token, "command")
-		}
-	}
-	if len(cmd.Args) == 0 {
-		t.errorf("empty command")
-	}
-	return cmd
-}
-
-// hasFunction reports if a function name exists in the Tree's maps.
-func (t *Tree) hasFunction(name string) bool {
-	for _, funcMap := range t.funcs {
-		if funcMap == nil {
-			continue
-		}
-		if funcMap[name] != nil {
-			return true
-		}
-	}
-	return false
-}
-
-// popVars trims the variable list to the specified length
-func (t *Tree) popVars(n int) {
-	t.vars = t.vars[:n]
-}
-
-// useVar returns a node for a variable reference. It errors if the
-// variable is not defined.
-func (t *Tree) useVar(name string) Node {
-	v := newVariable(name)
-	for _, varName := range t.vars {
-		if varName == v.Ident[0] {
-			return v
-		}
-	}
-	t.errorf("undefined variable %q", v.Ident[0])
-	return nil
-}
diff --git a/src/pkg/template/parse/parse_test.go b/src/pkg/template/parse/parse_test.go
deleted file mode 100644
index 1928c31..0000000
--- a/src/pkg/template/parse/parse_test.go
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2011 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 parse
-
-import (
-	"flag"
-	"fmt"
-	"testing"
-)
-
-var debug = flag.Bool("debug", false, "show the errors produced by the tests")
-
-type numberTest struct {
-	text      string
-	isInt     bool
-	isUint    bool
-	isFloat   bool
-	isComplex bool
-	int64
-	uint64
-	float64
-	complex128
-}
-
-var numberTests = []numberTest{
-	// basics
-	{"0", true, true, true, false, 0, 0, 0, 0},
-	{"-0", true, true, true, false, 0, 0, 0, 0}, // check that -0 is a uint.
-	{"73", true, true, true, false, 73, 73, 73, 0},
-	{"073", true, true, true, false, 073, 073, 073, 0},
-	{"0x73", true, true, true, false, 0x73, 0x73, 0x73, 0},
-	{"-73", true, false, true, false, -73, 0, -73, 0},
-	{"+73", true, false, true, false, 73, 0, 73, 0},
-	{"100", true, true, true, false, 100, 100, 100, 0},
-	{"1e9", true, true, true, false, 1e9, 1e9, 1e9, 0},
-	{"-1e9", true, false, true, false, -1e9, 0, -1e9, 0},
-	{"-1.2", false, false, true, false, 0, 0, -1.2, 0},
-	{"1e19", false, true, true, false, 0, 1e19, 1e19, 0},
-	{"-1e19", false, false, true, false, 0, 0, -1e19, 0},
-	{"4i", false, false, false, true, 0, 0, 0, 4i},
-	{"-1.2+4.2i", false, false, false, true, 0, 0, 0, -1.2 + 4.2i},
-	{"073i", false, false, false, true, 0, 0, 0, 73i}, // not octal!
-	// complex with 0 imaginary are float (and maybe integer)
-	{"0i", true, true, true, true, 0, 0, 0, 0},
-	{"-1.2+0i", false, false, true, true, 0, 0, -1.2, -1.2},
-	{"-12+0i", true, false, true, true, -12, 0, -12, -12},
-	{"13+0i", true, true, true, true, 13, 13, 13, 13},
-	// funny bases
-	{"0123", true, true, true, false, 0123, 0123, 0123, 0},
-	{"-0x0", true, true, true, false, 0, 0, 0, 0},
-	{"0xdeadbeef", true, true, true, false, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0},
-	// character constants
-	{`'a'`, true, true, true, false, 'a', 'a', 'a', 0},
-	{`'\n'`, true, true, true, false, '\n', '\n', '\n', 0},
-	{`'\\'`, true, true, true, false, '\\', '\\', '\\', 0},
-	{`'\''`, true, true, true, false, '\'', '\'', '\'', 0},
-	{`'\xFF'`, true, true, true, false, 0xFF, 0xFF, 0xFF, 0},
-	{`'パ'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
-	{`'\u30d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
-	{`'\U000030d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
-	// some broken syntax
-	{text: "+-2"},
-	{text: "0x123."},
-	{text: "1e."},
-	{text: "0xi."},
-	{text: "1+2."},
-	{text: "'x"},
-	{text: "'xx'"},
-}
-
-func TestNumberParse(t *testing.T) {
-	for _, test := range numberTests {
-		// If fmt.Sscan thinks it's complex, it's complex.  We can't trust the output
-		// because imaginary comes out as a number.
-		var c complex128
-		typ := itemNumber
-		if test.text[0] == '\'' {
-			typ = itemCharConstant
-		} else {
-			_, err := fmt.Sscan(test.text, &c)
-			if err == nil {
-				typ = itemComplex
-			}
-		}
-		n, err := newNumber(test.text, typ)
-		ok := test.isInt || test.isUint || test.isFloat || test.isComplex
-		if ok && err != nil {
-			t.Errorf("unexpected error for %q: %s", test.text, err)
-			continue
-		}
-		if !ok && err == nil {
-			t.Errorf("expected error for %q", test.text)
-			continue
-		}
-		if !ok {
-			if *debug {
-				fmt.Printf("%s\n\t%s\n", test.text, err)
-			}
-			continue
-		}
-		if n.IsComplex != test.isComplex {
-			t.Errorf("complex incorrect for %q; should be %t", test.text, test.isComplex)
-		}
-		if test.isInt {
-			if !n.IsInt {
-				t.Errorf("expected integer for %q", test.text)
-			}
-			if n.Int64 != test.int64 {
-				t.Errorf("int64 for %q should be %d Is %d", test.text, test.int64, n.Int64)
-			}
-		} else if n.IsInt {
-			t.Errorf("did not expect integer for %q", test.text)
-		}
-		if test.isUint {
-			if !n.IsUint {
-				t.Errorf("expected unsigned integer for %q", test.text)
-			}
-			if n.Uint64 != test.uint64 {
-				t.Errorf("uint64 for %q should be %d Is %d", test.text, test.uint64, n.Uint64)
-			}
-		} else if n.IsUint {
-			t.Errorf("did not expect unsigned integer for %q", test.text)
-		}
-		if test.isFloat {
-			if !n.IsFloat {
-				t.Errorf("expected float for %q", test.text)
-			}
-			if n.Float64 != test.float64 {
-				t.Errorf("float64 for %q should be %g Is %g", test.text, test.float64, n.Float64)
-			}
-		} else if n.IsFloat {
-			t.Errorf("did not expect float for %q", test.text)
-		}
-		if test.isComplex {
-			if !n.IsComplex {
-				t.Errorf("expected complex for %q", test.text)
-			}
-			if n.Complex128 != test.complex128 {
-				t.Errorf("complex128 for %q should be %g Is %g", test.text, test.complex128, n.Complex128)
-			}
-		} else if n.IsComplex {
-			t.Errorf("did not expect complex for %q", test.text)
-		}
-	}
-}
-
-type parseTest struct {
-	name   string
-	input  string
-	ok     bool
-	result string
-}
-
-const (
-	noError  = true
-	hasError = false
-)
-
-var parseTests = []parseTest{
-	{"empty", "", noError,
-		`[]`},
-	{"comment", "{{/*\n\n\n*/}}", noError,
-		`[]`},
-	{"spaces", " \t\n", noError,
-		`[(text: " \t\n")]`},
-	{"text", "some text", noError,
-		`[(text: "some text")]`},
-	{"emptyAction", "{{}}", hasError,
-		`[(action: [])]`},
-	{"field", "{{.X}}", noError,
-		`[(action: [(command: [F=[X]])])]`},
-	{"simple command", "{{printf}}", noError,
-		`[(action: [(command: [I=printf])])]`},
-	{"$ invocation", "{{$}}", noError,
-		"[(action: [(command: [V=[$]])])]"},
-	{"variable invocation", "{{with $x := 3}}{{$x 23}}{{end}}", noError,
-		"[({{with [V=[$x]] := [(command: [N=3])]}} [(action: [(command: [V=[$x] N=23])])])]"},
-	{"variable with fields", "{{$.I}}", noError,
-		"[(action: [(command: [V=[$ I]])])]"},
-	{"multi-word command", "{{printf `%d` 23}}", noError,
-		"[(action: [(command: [I=printf S=`%d` N=23])])]"},
-	{"pipeline", "{{.X|.Y}}", noError,
-		`[(action: [(command: [F=[X]]) (command: [F=[Y]])])]`},
-	{"pipeline with decl", "{{$x := .X|.Y}}", noError,
-		`[(action: [V=[$x]] := [(command: [F=[X]]) (command: [F=[Y]])])]`},
-	{"declaration", "{{.X|.Y}}", noError,
-		`[(action: [(command: [F=[X]]) (command: [F=[Y]])])]`},
-	{"simple if", "{{if .X}}hello{{end}}", noError,
-		`[({{if [(command: [F=[X]])]}} [(text: "hello")])]`},
-	{"if with else", "{{if .X}}true{{else}}false{{end}}", noError,
-		`[({{if [(command: [F=[X]])]}} [(text: "true")] {{else}} [(text: "false")])]`},
-	{"simple range", "{{range .X}}hello{{end}}", noError,
-		`[({{range [(command: [F=[X]])]}} [(text: "hello")])]`},
-	{"chained field range", "{{range .X.Y.Z}}hello{{end}}", noError,
-		`[({{range [(command: [F=[X Y Z]])]}} [(text: "hello")])]`},
-	{"nested range", "{{range .X}}hello{{range .Y}}goodbye{{end}}{{end}}", noError,
-		`[({{range [(command: [F=[X]])]}} [(text: "hello")({{range [(command: [F=[Y]])]}} [(text: "goodbye")])])]`},
-	{"range with else", "{{range .X}}true{{else}}false{{end}}", noError,
-		`[({{range [(command: [F=[X]])]}} [(text: "true")] {{else}} [(text: "false")])]`},
-	{"range over pipeline", "{{range .X|.M}}true{{else}}false{{end}}", noError,
-		`[({{range [(command: [F=[X]]) (command: [F=[M]])]}} [(text: "true")] {{else}} [(text: "false")])]`},
-	{"range []int", "{{range .SI}}{{.}}{{end}}", noError,
-		`[({{range [(command: [F=[SI]])]}} [(action: [(command: [{{<.>}}])])])]`},
-	{"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError,
-		`[({{range [(command: [F=[SI] N=1 N=-3.2i B=true B=false N='a'])]}} [])]`},
-	{"template", "{{template `x`}}", noError,
-		`[{{template "x"}}]`},
-	{"template with arg", "{{template `x` .Y}}", noError,
-		`[{{template "x" [(command: [F=[Y]])]}}]`},
-	{"with", "{{with .X}}hello{{end}}", noError,
-		`[({{with [(command: [F=[X]])]}} [(text: "hello")])]`},
-	{"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError,
-		`[({{with [(command: [F=[X]])]}} [(text: "hello")] {{else}} [(text: "goodbye")])]`},
-	// Errors.
-	{"unclosed action", "hello{{range", hasError, ""},
-	{"unmatched end", "{{end}}", hasError, ""},
-	{"missing end", "hello{{range .x}}", hasError, ""},
-	{"missing end after else", "hello{{range .x}}{{else}}", hasError, ""},
-	{"undefined function", "hello{{undefined}}", hasError, ""},
-	{"undefined variable", "{{$x}}", hasError, ""},
-	{"variable undefined after end", "{{with $x := 4}}{{end}}{{$x}}", hasError, ""},
-	{"variable undefined in template", "{{template $v}}", hasError, ""},
-	{"declare with field", "{{with $x.Y := 4}}{{end}}", hasError, ""},
-	{"template with field ref", "{{template .X}}", hasError, ""},
-	{"template with var", "{{template $v}}", hasError, ""},
-	{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
-	{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
-	{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
-}
-
-var builtins = map[string]interface{}{
-	"printf": fmt.Sprintf,
-}
-
-func TestParse(t *testing.T) {
-	for _, test := range parseTests {
-		tmpl, err := New(test.name).Parse(test.input, builtins)
-		switch {
-		case err == nil && !test.ok:
-			t.Errorf("%q: expected error; got none", test.name)
-			continue
-		case err != nil && test.ok:
-			t.Errorf("%q: unexpected error: %v", test.name, err)
-			continue
-		case err != nil && !test.ok:
-			// expected error, got one
-			if *debug {
-				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
-			}
-			continue
-		}
-		result := tmpl.Root.String()
-		if result != test.result {
-			t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result)
-		}
-	}
-}
diff --git a/src/pkg/template/parse/set.go b/src/pkg/template/parse/set.go
deleted file mode 100644
index dca41ea..0000000
--- a/src/pkg/template/parse/set.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2011 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 parse
-
-import (
-	"fmt"
-	"os"
-	"strconv"
-)
-
-// Set returns a slice of Trees created by parsing the template set
-// definition in the argument string. If an error is encountered,
-// parsing stops and an empty slice is returned with the error.
-func Set(text string, funcs ...map[string]interface{}) (tree map[string]*Tree, err os.Error) {
-	tree = make(map[string]*Tree)
-	defer (*Tree)(nil).recover(&err)
-	lex := lex("set", text)
-	const context = "define clause"
-	for {
-		t := New("set") // name will be updated once we know it.
-		t.startParse(funcs, lex)
-		// Expect EOF or "{{ define name }}".
-		if t.atEOF() {
-			break
-		}
-		t.expect(itemLeftDelim, context)
-		t.expect(itemDefine, context)
-		name := t.expect(itemString, context)
-		t.Name, err = strconv.Unquote(name.val)
-		if err != nil {
-			t.error(err)
-		}
-		t.expect(itemRightDelim, context)
-		end := t.parse(false)
-		if end == nil {
-			t.errorf("unexpected EOF in %s", context)
-		}
-		if end.Type() != nodeEnd {
-			t.errorf("unexpected %s in %s", end, context)
-		}
-		t.stopParse()
-		if _, present := tree[t.Name]; present {
-			return nil, fmt.Errorf("template: %q multiply defined", name)
-		}
-		tree[t.Name] = t
-	}
-	return
-}
diff --git a/src/pkg/template/set.go b/src/pkg/template/set.go
deleted file mode 100644
index f778fd1..0000000
--- a/src/pkg/template/set.go
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2011 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 template
-
-import (
-	"fmt"
-	"io"
-	"os"
-	"reflect"
-	"template/parse"
-)
-
-// Set holds a set of related templates that can refer to one another by name.
-// The zero value represents an empty set.
-// A template may be a member of multiple sets.
-type Set struct {
-	tmpl       map[string]*Template
-	parseFuncs FuncMap
-	execFuncs  map[string]reflect.Value
-}
-
-func (s *Set) init() {
-	if s.tmpl == nil {
-		s.tmpl = make(map[string]*Template)
-		s.parseFuncs = make(FuncMap)
-		s.execFuncs = make(map[string]reflect.Value)
-	}
-}
-
-// Funcs adds the elements of the argument map to the set's function map.  It
-// panics if a value in the map is not a function with appropriate return
-// type.
-// The return value is the set, so calls can be chained.
-func (s *Set) Funcs(funcMap FuncMap) *Set {
-	s.init()
-	addValueFuncs(s.execFuncs, funcMap)
-	addFuncs(s.parseFuncs, funcMap)
-	return s
-}
-
-// Add adds the argument templates to the set. It panics if two templates
-// with the same name are added or if a template is already a member of
-// a set.
-// The return value is the set, so calls can be chained.
-func (s *Set) Add(templates ...*Template) *Set {
-	for _, t := range templates {
-		if err := s.add(t); err != nil {
-			panic(err)
-		}
-	}
-	return s
-}
-
-// add adds the argument template to the set.
-func (s *Set) add(t *Template) os.Error {
-	s.init()
-	if t.set != nil {
-		return fmt.Errorf("template: %q already in a set", t.name)
-	}
-	if _, ok := s.tmpl[t.name]; ok {
-		return fmt.Errorf("template: %q already defined in set", t.name)
-	}
-	s.tmpl[t.name] = t
-	t.set = s
-	return nil
-}
-
-// Template returns the template with the given name in the set,
-// or nil if there is no such template.
-func (s *Set) Template(name string) *Template {
-	return s.tmpl[name]
-}
-
-// FuncMap returns the set's function map.
-func (s *Set) FuncMap() FuncMap {
-	return s.parseFuncs
-}
-
-// Execute applies the named template to the specified data object, writing
-// the output to wr.
-func (s *Set) Execute(wr io.Writer, name string, data interface{}) os.Error {
-	tmpl := s.tmpl[name]
-	if tmpl == nil {
-		return fmt.Errorf("template: no template %q in set", name)
-	}
-	return tmpl.Execute(wr, data)
-}
-
-// Parse parses a string into a set of named templates.  Parse may be called
-// multiple times for a given set, adding the templates defined in the string
-// to the set.  If a template is redefined, the element in the set is
-// overwritten with the new definition.
-func (s *Set) Parse(text string) (*Set, os.Error) {
-	trees, err := parse.Set(text, s.parseFuncs, builtins)
-	if err != nil {
-		return nil, err
-	}
-	s.init()
-	for name, tree := range trees {
-		tmpl := New(name)
-		tmpl.Tree = tree
-		tmpl.addToSet(s)
-		s.tmpl[name] = tmpl
-	}
-	return s, nil
-}
diff --git a/src/pkg/template/set_test.go b/src/pkg/template/set_test.go
deleted file mode 100644
index f437bc7..0000000
--- a/src/pkg/template/set_test.go
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2011 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 template
-
-import (
-	"fmt"
-	"testing"
-)
-
-const (
-	noError  = true
-	hasError = false
-)
-
-type setParseTest struct {
-	name    string
-	input   string
-	ok      bool
-	names   []string
-	results []string
-}
-
-var setParseTests = []setParseTest{
-	{"empty", "", noError,
-		nil,
-		nil},
-	{"one", `{{define "foo"}} FOO {{end}}`, noError,
-		[]string{"foo"},
-		[]string{`[(text: " FOO ")]`}},
-	{"two", `{{define "foo"}} FOO {{end}}{{define "bar"}} BAR {{end}}`, noError,
-		[]string{"foo", "bar"},
-		[]string{`[(text: " FOO ")]`, `[(text: " BAR ")]`}},
-	// errors
-	{"missing end", `{{define "foo"}} FOO `, hasError,
-		nil,
-		nil},
-	{"malformed name", `{{define "foo}} FOO `, hasError,
-		nil,
-		nil},
-}
-
-func TestSetParse(t *testing.T) {
-	for _, test := range setParseTests {
-		set, err := new(Set).Parse(test.input)
-		switch {
-		case err == nil && !test.ok:
-			t.Errorf("%q: expected error; got none", test.name)
-			continue
-		case err != nil && test.ok:
-			t.Errorf("%q: unexpected error: %v", test.name, err)
-			continue
-		case err != nil && !test.ok:
-			// expected error, got one
-			if *debug {
-				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
-			}
-			continue
-		}
-		if set == nil {
-			continue
-		}
-		if len(set.tmpl) != len(test.names) {
-			t.Errorf("%s: wrong number of templates; wanted %d got %d", test.name, len(test.names), len(set.tmpl))
-			continue
-		}
-		for i, name := range test.names {
-			tmpl, ok := set.tmpl[name]
-			if !ok {
-				t.Errorf("%s: can't find template %q", test.name, name)
-				continue
-			}
-			result := tmpl.Root.String()
-			if result != test.results[i] {
-				t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.results[i])
-			}
-		}
-	}
-}
-
-var setExecTests = []execTest{
-	{"empty", "", "", nil, true},
-	{"text", "some text", "some text", nil, true},
-	{"invoke x", `{{template "x" .SI}}`, "TEXT", tVal, true},
-	{"invoke x no args", `{{template "x"}}`, "TEXT", tVal, true},
-	{"invoke dot int", `{{template "dot" .I}}`, "17", tVal, true},
-	{"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
-	{"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
-	{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
-	{"variable declared by template", `{{template "nested" $x=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
-
-	// User-defined function: test argument evaluator.
-	{"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},
-	{"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true},
-}
-
-// These strings are also in testdata/*.
-const setText1 = `
-	{{define "x"}}TEXT{{end}}
-	{{define "dotV"}}{{.V}}{{end}}
-`
-
-const setText2 = `
-	{{define "dot"}}{{.}}{{end}}
-	{{define "nested"}}{{template "dot" .}}{{end}}
-`
-
-func TestSetExecute(t *testing.T) {
-	// Declare a set with a couple of templates first.
-	set := new(Set)
-	_, err := set.Parse(setText1)
-	if err != nil {
-		t.Fatalf("error parsing set: %s", err)
-	}
-	_, err = set.Parse(setText2)
-	if err != nil {
-		t.Fatalf("error parsing set: %s", err)
-	}
-	testExecute(setExecTests, set, t)
-}
-
-func TestSetParseFiles(t *testing.T) {
-	set := new(Set)
-	_, err := set.ParseFiles("DOES NOT EXIST")
-	if err == nil {
-		t.Error("expected error for non-existent file; got none")
-	}
-	_, err = set.ParseFiles("testdata/file1.tmpl", "testdata/file2.tmpl")
-	if err != nil {
-		t.Fatalf("error parsing files: %v", err)
-	}
-	testExecute(setExecTests, set, t)
-}
-
-func TestParseSetFiles(t *testing.T) {
-	set := new(Set)
-	_, err := ParseSetFiles("DOES NOT EXIST")
-	if err == nil {
-		t.Error("expected error for non-existent file; got none")
-	}
-	set, err = ParseSetFiles("testdata/file1.tmpl", "testdata/file2.tmpl")
-	if err != nil {
-		t.Fatalf("error parsing files: %v", err)
-	}
-	testExecute(setExecTests, set, t)
-}
-
-func TestSetParseGlob(t *testing.T) {
-	_, err := new(Set).ParseGlob("DOES NOT EXIST")
-	if err == nil {
-		t.Error("expected error for non-existent file; got none")
-	}
-	_, err = new(Set).ParseGlob("[x")
-	if err == nil {
-		t.Error("expected error for bad pattern; got none")
-	}
-	set, err := new(Set).ParseGlob("testdata/file*.tmpl")
-	if err != nil {
-		t.Fatalf("error parsing files: %v", err)
-	}
-	testExecute(setExecTests, set, t)
-}
-
-func TestParseSetGlob(t *testing.T) {
-	_, err := ParseSetGlob("DOES NOT EXIST")
-	if err == nil {
-		t.Error("expected error for non-existent file; got none")
-	}
-	_, err = ParseSetGlob("[x")
-	if err == nil {
-		t.Error("expected error for bad pattern; got none")
-	}
-	set, err := ParseSetGlob("testdata/file*.tmpl")
-	if err != nil {
-		t.Fatalf("error parsing files: %v", err)
-	}
-	testExecute(setExecTests, set, t)
-}
-
-var templateFileExecTests = []execTest{
-	{"test", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\ntemplate2\n", 0, true},
-}
-
-func TestSetParseTemplateFiles(t *testing.T) {
-	_, err := ParseTemplateFiles("DOES NOT EXIST")
-	if err == nil {
-		t.Error("expected error for non-existent file; got none")
-	}
-	set, err := new(Set).ParseTemplateFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl")
-	if err != nil {
-		t.Fatalf("error parsing files: %v", err)
-	}
-	testExecute(templateFileExecTests, set, t)
-}
-
-func TestParseTemplateFiles(t *testing.T) {
-	_, err := ParseTemplateFiles("DOES NOT EXIST")
-	if err == nil {
-		t.Error("expected error for non-existent file; got none")
-	}
-	set, err := new(Set).ParseTemplateFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl")
-	if err != nil {
-		t.Fatalf("error parsing files: %v", err)
-	}
-	testExecute(templateFileExecTests, set, t)
-}
-
-func TestSetParseTemplateGlob(t *testing.T) {
-	_, err := ParseTemplateGlob("DOES NOT EXIST")
-	if err == nil {
-		t.Error("expected error for non-existent file; got none")
-	}
-	_, err = new(Set).ParseTemplateGlob("[x")
-	if err == nil {
-		t.Error("expected error for bad pattern; got none")
-	}
-	set, err := new(Set).ParseTemplateGlob("testdata/tmpl*.tmpl")
-	if err != nil {
-		t.Fatalf("error parsing files: %v", err)
-	}
-	testExecute(templateFileExecTests, set, t)
-}
-
-func TestParseTemplateGlob(t *testing.T) {
-	_, err := ParseTemplateGlob("DOES NOT EXIST")
-	if err == nil {
-		t.Error("expected error for non-existent file; got none")
-	}
-	_, err = ParseTemplateGlob("[x")
-	if err == nil {
-		t.Error("expected error for bad pattern; got none")
-	}
-	set, err := ParseTemplateGlob("testdata/tmpl*.tmpl")
-	if err != nil {
-		t.Fatalf("error parsing files: %v", err)
-	}
-	testExecute(templateFileExecTests, set, t)
-}
diff --git a/src/pkg/template/testdata/tmpl1.tmpl b/src/pkg/template/testdata/tmpl1.tmpl
deleted file mode 100644
index 3d15b81..0000000
--- a/src/pkg/template/testdata/tmpl1.tmpl
+++ /dev/null
@@ -1 +0,0 @@
-template1
diff --git a/src/pkg/template/testdata/tmpl2.tmpl b/src/pkg/template/testdata/tmpl2.tmpl
deleted file mode 100644
index a374d2f..0000000
--- a/src/pkg/template/testdata/tmpl2.tmpl
+++ /dev/null
@@ -1 +0,0 @@
-template2
diff --git a/src/pkg/testing/Makefile b/src/pkg/testing/Makefile
index 9e8bd17..a0c1232 100644
--- a/src/pkg/testing/Makefile
+++ b/src/pkg/testing/Makefile
@@ -6,7 +6,8 @@ include ../../Make.inc
 
 TARG=testing
 GOFILES=\
-        benchmark.go\
+	benchmark.go\
+	example.go\
 	testing.go\
 
 include ../../Make.pkg
diff --git a/src/pkg/testing/benchmark.go b/src/pkg/testing/benchmark.go
index fd0bd86..0bf567b 100644
--- a/src/pkg/testing/benchmark.go
+++ b/src/pkg/testing/benchmark.go
@@ -25,19 +25,21 @@ type InternalBenchmark struct {
 // B is a type passed to Benchmark functions to manage benchmark
 // timing and to specify the number of iterations to run.
 type B struct {
+	common
 	N         int
 	benchmark InternalBenchmark
-	ns        int64
 	bytes     int64
-	start     int64
+	timerOn   bool
+	result    BenchmarkResult
 }
 
 // StartTimer starts timing a test.  This function is called automatically
 // before a benchmark starts, but it can also used to resume timing after
 // a call to StopTimer.
 func (b *B) StartTimer() {
-	if b.start == 0 {
-		b.start = time.Nanoseconds()
+	if !b.timerOn {
+		b.start = time.Now()
+		b.timerOn = true
 	}
 }
 
@@ -45,19 +47,19 @@ func (b *B) StartTimer() {
 // while performing complex initialization that you don't
 // want to measure.
 func (b *B) StopTimer() {
-	if b.start > 0 {
-		b.ns += time.Nanoseconds() - b.start
+	if b.timerOn {
+		b.duration += time.Now().Sub(b.start)
+		b.timerOn = false
 	}
-	b.start = 0
 }
 
 // ResetTimer sets the elapsed benchmark time to zero.
 // It does not affect whether the timer is running.
 func (b *B) ResetTimer() {
-	if b.start > 0 {
-		b.start = time.Nanoseconds()
+	if b.timerOn {
+		b.start = time.Now()
 	}
-	b.ns = 0
+	b.duration = 0
 }
 
 // SetBytes records the number of bytes processed in a single operation.
@@ -68,7 +70,7 @@ func (b *B) nsPerOp() int64 {
 	if b.N <= 0 {
 		return 0
 	}
-	return b.ns / int64(b.N)
+	return b.duration.Nanoseconds() / int64(b.N)
 }
 
 // runN runs a single benchmark for the specified number of iterations.
@@ -125,23 +127,38 @@ func roundUp(n int) int {
 	return 10 * base
 }
 
-// run times the benchmark function.  It gradually increases the number
+// run times the benchmark function in a separate goroutine.
+func (b *B) run() BenchmarkResult {
+	go b.launch()
+	<-b.signal
+	return b.result
+}
+
+// launch launches the benchmark function.  It gradually increases the number
 // of benchmark iterations until the benchmark runs for a second in order
 // to get a reasonable measurement.  It prints timing information in this form
 //		testing.BenchmarkHello	100000		19 ns/op
-func (b *B) run() BenchmarkResult {
+// launch is run by the fun function as a separate goroutine.
+func (b *B) launch() {
 	// Run the benchmark for a single iteration in case it's expensive.
 	n := 1
+
+	// Signal that we're done whether we return normally
+	// or by FailNow's runtime.Goexit.
+	defer func() {
+		b.signal <- b
+	}()
+
 	b.runN(n)
 	// Run the benchmark for at least the specified amount of time.
-	time := int64(*benchTime * 1e9)
-	for b.ns < time && n < 1e9 {
+	d := time.Duration(*benchTime * float64(time.Second))
+	for !b.failed && b.duration < d && n < 1e9 {
 		last := n
 		// Predict iterations/sec.
 		if b.nsPerOp() == 0 {
 			n = 1e9
 		} else {
-			n = int(time / b.nsPerOp())
+			n = int(d.Nanoseconds() / b.nsPerOp())
 		}
 		// Run more iterations than we think we'll need for a second (1.5x).
 		// Don't grow too fast in case we had timing errors previously.
@@ -151,28 +168,28 @@ func (b *B) run() BenchmarkResult {
 		n = roundUp(n)
 		b.runN(n)
 	}
-	return BenchmarkResult{b.N, b.ns, b.bytes}
+	b.result = BenchmarkResult{b.N, b.duration, b.bytes}
 }
 
 // The results of a benchmark run.
 type BenchmarkResult struct {
-	N     int   // The number of iterations.
-	Ns    int64 // The total time taken.
-	Bytes int64 // Bytes processed in one iteration.
+	N     int           // The number of iterations.
+	T     time.Duration // The total time taken.
+	Bytes int64         // Bytes processed in one iteration.
 }
 
 func (r BenchmarkResult) NsPerOp() int64 {
 	if r.N <= 0 {
 		return 0
 	}
-	return r.Ns / int64(r.N)
+	return r.T.Nanoseconds() / int64(r.N)
 }
 
 func (r BenchmarkResult) mbPerSec() float64 {
-	if r.Bytes <= 0 || r.Ns <= 0 || r.N <= 0 {
+	if r.Bytes <= 0 || r.T <= 0 || r.N <= 0 {
 		return 0
 	}
-	return float64(r.Bytes) * float64(r.N) / float64(r.Ns) * 1e3
+	return (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds()
 }
 
 func (r BenchmarkResult) String() string {
@@ -187,9 +204,9 @@ func (r BenchmarkResult) String() string {
 		// The format specifiers here make sure that
 		// the ones digits line up for all three possible formats.
 		if nsop < 10 {
-			ns = fmt.Sprintf("%13.2f ns/op", float64(r.Ns)/float64(r.N))
+			ns = fmt.Sprintf("%13.2f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
 		} else {
-			ns = fmt.Sprintf("%12.1f ns/op", float64(r.Ns)/float64(r.N))
+			ns = fmt.Sprintf("%12.1f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
 		}
 	}
 	return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
@@ -197,7 +214,7 @@ func (r BenchmarkResult) String() string {
 
 // An internal function but exported because it is cross-package; part of the implementation
 // of gotest.
-func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmarks []InternalBenchmark) {
+func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
 	// If no flag was specified, don't run benchmarks.
 	if len(*matchBenchmarks) == 0 {
 		return
@@ -205,7 +222,7 @@ func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmark
 	for _, Benchmark := range benchmarks {
 		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
 		if err != nil {
-			println("invalid regexp for -test.bench:", err.String())
+			fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.bench: %s\n", err)
 			os.Exit(1)
 		}
 		if !matched {
@@ -213,16 +230,51 @@ func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmark
 		}
 		for _, procs := range cpuList {
 			runtime.GOMAXPROCS(procs)
-			b := &B{benchmark: Benchmark}
+			b := &B{
+				common: common{
+					signal: make(chan interface{}),
+				},
+				benchmark: Benchmark,
+			}
 			benchName := Benchmark.Name
 			if procs != 1 {
 				benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
 			}
-			print(fmt.Sprintf("%s\t", benchName))
+			fmt.Printf("%s\t", benchName)
 			r := b.run()
-			print(fmt.Sprintf("%v\n", r))
+			if b.failed {
+				// The output could be very long here, but probably isn't.
+				// We print it all, regardless, because we don't want to trim the reason
+				// the benchmark failed.
+				fmt.Printf("--- FAIL: %s\n%s", benchName, b.output)
+				continue
+			}
+			fmt.Printf("%v\n", r)
+			// Unlike with tests, we ignore the -chatty flag and always print output for
+			// benchmarks since the output generation time will skew the results.
+			if len(b.output) > 0 {
+				b.trimOutput()
+				fmt.Printf("--- BENCH: %s\n%s", benchName, b.output)
+			}
 			if p := runtime.GOMAXPROCS(-1); p != procs {
-				print(fmt.Sprintf("%s left GOMAXPROCS set to %d\n", benchName, p))
+				fmt.Fprintf(os.Stderr, "testing: %s left GOMAXPROCS set to %d\n", benchName, p)
+			}
+		}
+	}
+}
+
+// trimOutput shortens the output from a benchmark, which can be very long.
+func (b *B) trimOutput() {
+	// The output is likely to appear multiple times because the benchmark
+	// is run multiple times, but at least it will be seen. This is not a big deal
+	// because benchmarks rarely print, but just in case, we trim it if it's too long.
+	const maxNewlines = 10
+	for nlCount, j := 0, 0; j < len(b.output); j++ {
+		if b.output[j] == '\n' {
+			nlCount++
+			if nlCount >= maxNewlines {
+				b.output = append(b.output[:j], "\n\t... [output truncated]\n"...)
+				break
 			}
 		}
 	}
@@ -231,6 +283,11 @@ func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmark
 // Benchmark benchmarks a single function. Useful for creating
 // custom benchmarks that do not use gotest.
 func Benchmark(f func(b *B)) BenchmarkResult {
-	b := &B{benchmark: InternalBenchmark{"", f}}
+	b := &B{
+		common: common{
+			signal: make(chan interface{}),
+		},
+		benchmark: InternalBenchmark{"", f},
+	}
 	return b.run()
 }
diff --git a/src/pkg/testing/example.go b/src/pkg/testing/example.go
new file mode 100644
index 0000000..7f8ff2d
--- /dev/null
+++ b/src/pkg/testing/example.go
@@ -0,0 +1,74 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testing
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"time"
+)
+
+type InternalExample struct {
+	Name   string
+	F      func()
+	Output string
+}
+
+func RunExamples(examples []InternalExample) (ok bool) {
+	ok = true
+
+	var eg InternalExample
+
+	stdout, stderr := os.Stdout, os.Stderr
+
+	for _, eg = range examples {
+		if *chatty {
+			fmt.Printf("=== RUN: %s\n", eg.Name)
+		}
+
+		// capture stdout and stderr
+		r, w, err := os.Pipe()
+		if err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			os.Exit(1)
+		}
+		os.Stdout, os.Stderr = w, w
+		outC := make(chan string)
+		go func() {
+			buf := new(bytes.Buffer)
+			_, err := io.Copy(buf, r)
+			if err != nil {
+				fmt.Fprintf(stderr, "testing: copying pipe: %v\n", err)
+				os.Exit(1)
+			}
+			outC <- buf.String()
+		}()
+
+		// run example
+		t0 := time.Now()
+		eg.F()
+		dt := time.Now().Sub(t0)
+
+		// close pipe, restore stdout/stderr, get output
+		w.Close()
+		os.Stdout, os.Stderr = stdout, stderr
+		out := <-outC
+
+		// report any errors
+		tstr := fmt.Sprintf("(%.2f seconds)", dt.Seconds())
+		if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e {
+			fmt.Printf("--- FAIL: %s %s\ngot:\n%s\nwant:\n%s\n",
+				eg.Name, tstr, g, e)
+			ok = false
+		} else if *chatty {
+			fmt.Printf("--- PASS: %s %s\n", eg.Name, tstr)
+		}
+	}
+
+	return
+}
diff --git a/src/pkg/testing/iotest/logger.go b/src/pkg/testing/iotest/logger.go
index c3bf5df..1475d9b 100644
--- a/src/pkg/testing/iotest/logger.go
+++ b/src/pkg/testing/iotest/logger.go
@@ -7,7 +7,6 @@ package iotest
 import (
 	"io"
 	"log"
-	"os"
 )
 
 type writeLogger struct {
@@ -15,7 +14,7 @@ type writeLogger struct {
 	w      io.Writer
 }
 
-func (l *writeLogger) Write(p []byte) (n int, err os.Error) {
+func (l *writeLogger) Write(p []byte) (n int, err error) {
 	n, err = l.w.Write(p)
 	if err != nil {
 		log.Printf("%s %x: %v", l.prefix, p[0:n], err)
@@ -37,7 +36,7 @@ type readLogger struct {
 	r      io.Reader
 }
 
-func (l *readLogger) Read(p []byte) (n int, err os.Error) {
+func (l *readLogger) Read(p []byte) (n int, err error) {
 	n, err = l.r.Read(p)
 	if err != nil {
 		log.Printf("%s %x: %v", l.prefix, p[0:n], err)
diff --git a/src/pkg/testing/iotest/reader.go b/src/pkg/testing/iotest/reader.go
index dcf5565..ab8dc31 100644
--- a/src/pkg/testing/iotest/reader.go
+++ b/src/pkg/testing/iotest/reader.go
@@ -6,8 +6,8 @@
 package iotest
 
 import (
+	"errors"
 	"io"
-	"os"
 )
 
 // OneByteReader returns a Reader that implements
@@ -18,7 +18,7 @@ type oneByteReader struct {
 	r io.Reader
 }
 
-func (r *oneByteReader) Read(p []byte) (int, os.Error) {
+func (r *oneByteReader) Read(p []byte) (int, error) {
 	if len(p) == 0 {
 		return 0, nil
 	}
@@ -33,7 +33,7 @@ type halfReader struct {
 	r io.Reader
 }
 
-func (r *halfReader) Read(p []byte) (int, os.Error) {
+func (r *halfReader) Read(p []byte) (int, error) {
 	return r.r.Read(p[0 : (len(p)+1)/2])
 }
 
@@ -48,7 +48,7 @@ type dataErrReader struct {
 	data   []byte
 }
 
-func (r *dataErrReader) Read(p []byte) (n int, err os.Error) {
+func (r *dataErrReader) Read(p []byte) (n int, err error) {
 	// loop because first call needs two reads:
 	// one to get data and a second to look for an error.
 	for {
@@ -66,7 +66,7 @@ func (r *dataErrReader) Read(p []byte) (n int, err os.Error) {
 	return
 }
 
-var ErrTimeout = os.NewError("timeout")
+var ErrTimeout = errors.New("timeout")
 
 // TimeoutReader returns ErrTimeout on the second read
 // with no data.  Subsequent calls to read succeed.
@@ -77,7 +77,7 @@ type timeoutReader struct {
 	count int
 }
 
-func (r *timeoutReader) Read(p []byte) (int, os.Error) {
+func (r *timeoutReader) Read(p []byte) (int, error) {
 	r.count++
 	if r.count == 2 {
 		return 0, ErrTimeout
diff --git a/src/pkg/testing/iotest/writer.go b/src/pkg/testing/iotest/writer.go
index 71f504c..af61ab8 100644
--- a/src/pkg/testing/iotest/writer.go
+++ b/src/pkg/testing/iotest/writer.go
@@ -4,10 +4,7 @@
 
 package iotest
 
-import (
-	"io"
-	"os"
-)
+import "io"
 
 // TruncateWriter returns a Writer that writes to w
 // but stops silently after n bytes.
@@ -20,7 +17,7 @@ type truncateWriter struct {
 	n int64
 }
 
-func (t *truncateWriter) Write(p []byte) (n int, err os.Error) {
+func (t *truncateWriter) Write(p []byte) (n int, err error) {
 	if t.n <= 0 {
 		return len(p), nil
 	}
diff --git a/src/pkg/testing/quick/quick.go b/src/pkg/testing/quick/quick.go
index 756a60e..f94c541 100644
--- a/src/pkg/testing/quick/quick.go
+++ b/src/pkg/testing/quick/quick.go
@@ -9,8 +9,7 @@ import (
 	"flag"
 	"fmt"
 	"math"
-	"os"
-	"rand"
+	"math/rand"
 	"reflect"
 	"strings"
 )
@@ -123,9 +122,9 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 		return s, true
 	case reflect.String:
 		numChars := rand.Intn(complexSize)
-		codePoints := make([]int, numChars)
+		codePoints := make([]rune, numChars)
 		for i := 0; i < numChars; i++ {
-			codePoints[i] = rand.Intn(0x10ffff)
+			codePoints[i] = rune(rand.Intn(0x10ffff))
 		}
 		return reflect.ValueOf(string(codePoints)), true
 	case reflect.Struct:
@@ -191,7 +190,7 @@ func (c *Config) getMaxCount() (maxCount int) {
 // used, independent of the functions being tested.
 type SetupError string
 
-func (s SetupError) String() string { return string(s) }
+func (s SetupError) Error() string { return string(s) }
 
 // A CheckError is the result of Check finding an error.
 type CheckError struct {
@@ -199,7 +198,7 @@ type CheckError struct {
 	In    []interface{}
 }
 
-func (s *CheckError) String() string {
+func (s *CheckError) Error() string {
 	return fmt.Sprintf("#%d: failed on input %s", s.Count, toString(s.In))
 }
 
@@ -210,7 +209,7 @@ type CheckEqualError struct {
 	Out2 []interface{}
 }
 
-func (s *CheckEqualError) String() string {
+func (s *CheckEqualError) Error() string {
 	return fmt.Sprintf("#%d: failed on input %s. Output 1: %s. Output 2: %s", s.Count, toString(s.In), toString(s.Out1), toString(s.Out2))
 }
 
@@ -229,7 +228,7 @@ func (s *CheckEqualError) String() string {
 // 			t.Error(err)
 // 		}
 // 	}
-func Check(function interface{}, config *Config) (err os.Error) {
+func Check(function interface{}, config *Config) (err error) {
 	if config == nil {
 		config = &defaultConfig
 	}
@@ -272,7 +271,7 @@ func Check(function interface{}, config *Config) (err os.Error) {
 // It calls f and g repeatedly with arbitrary values for each argument.
 // If f and g return different answers, CheckEqual returns a *CheckEqualError
 // describing the input and the outputs.
-func CheckEqual(f, g interface{}, config *Config) (err os.Error) {
+func CheckEqual(f, g interface{}, config *Config) (err error) {
 	if config == nil {
 		config = &defaultConfig
 	}
@@ -317,7 +316,7 @@ func CheckEqual(f, g interface{}, config *Config) (err os.Error) {
 
 // arbitraryValues writes Values to args such that args contains Values
 // suitable for calling f.
-func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand *rand.Rand) (err os.Error) {
+func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand *rand.Rand) (err error) {
 	if config.Values != nil {
 		config.Values(args, rand)
 		return
diff --git a/src/pkg/testing/quick/quick_test.go b/src/pkg/testing/quick/quick_test.go
index f2618c3..a6cf0dc 100644
--- a/src/pkg/testing/quick/quick_test.go
+++ b/src/pkg/testing/quick/quick_test.go
@@ -5,10 +5,9 @@
 package quick
 
 import (
-	"rand"
+	"math/rand"
 	"reflect"
 	"testing"
-	"os"
 )
 
 func fBool(a bool) bool { return a }
@@ -63,7 +62,7 @@ func fIntptr(a *int) *int {
 	return &b
 }
 
-func reportError(property string, err os.Error, t *testing.T) {
+func reportError(property string, err error, t *testing.T) {
 	if err != nil {
 		t.Errorf("%s: %s", property, err)
 	}
diff --git a/src/pkg/testing/script/script.go b/src/pkg/testing/script/script.go
index afb286f..d8f8093 100644
--- a/src/pkg/testing/script/script.go
+++ b/src/pkg/testing/script/script.go
@@ -7,8 +7,7 @@ package script
 
 import (
 	"fmt"
-	"os"
-	"rand"
+	"math/rand"
 	"reflect"
 	"strings"
 )
@@ -171,7 +170,7 @@ type ReceivedUnexpected struct {
 	ready []*Event
 }
 
-func (r ReceivedUnexpected) String() string {
+func (r ReceivedUnexpected) Error() string {
 	names := make([]string, len(r.ready))
 	for i, v := range r.ready {
 		names[i] = v.name
@@ -183,7 +182,7 @@ func (r ReceivedUnexpected) String() string {
 // Events.
 type SetupError string
 
-func (s SetupError) String() string { return string(s) }
+func (s SetupError) Error() string { return string(s) }
 
 func NewEvent(name string, predecessors []*Event, action action) *Event {
 	e := &Event{name, false, predecessors, action}
@@ -223,7 +222,7 @@ func NewEvent(name string, predecessors []*Event, action action) *Event {
 // the other. At each receive step, all the receive channels are considered,
 // thus Perform may see a value from a channel that is not in the current ready
 // set and fail.
-func Perform(seed int64, events []*Event) (err os.Error) {
+func Perform(seed int64, events []*Event) (err error) {
 	r := rand.New(rand.NewSource(seed))
 
 	channels, err := getChannels(events)
@@ -269,7 +268,7 @@ Outer:
 }
 
 // getChannels returns all the channels listed in any receive events.
-func getChannels(events []*Event) ([]interface{}, os.Error) {
+func getChannels(events []*Event) ([]interface{}, error) {
 	channels := make([]interface{}, len(events))
 
 	j := 0
@@ -326,7 +325,7 @@ type channelRecv struct {
 }
 
 // readyEvents returns the subset of events that are ready.
-func readyEvents(events []*Event) ([]*Event, os.Error) {
+func readyEvents(events []*Event) ([]*Event, error) {
 	ready := make([]*Event, len(events))
 
 	j := 0
diff --git a/src/pkg/testing/testing.go b/src/pkg/testing/testing.go
index ec4a453..f1acb97 100644
--- a/src/pkg/testing/testing.go
+++ b/src/pkg/testing/testing.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Package testing provides support for automated testing of Go packages.
-// It is intended to be used in concert with the ``gotest'' utility, which automates
+// It is intended to be used in concert with the ``go test'' command, which automates
 // execution of any function of the form
 //     func TestXxx(*testing.T)
 // where Xxx can be any alphanumeric string (but the first letter must not be in
@@ -21,10 +21,11 @@
 //             fmt.Sprintf("hello")
 //         }
 //     }
+//
 // The benchmark package will vary b.N until the benchmark function lasts
 // long enough to be timed reliably.  The output
-//     testing.BenchmarkHello	500000	      4076 ns/op
-// means that the loop ran 500000 times at a speed of 4076 ns per loop.
+//     testing.BenchmarkHello    10000000    282 ns/op
+// means that the loop ran 10000000 times at a speed of 282 ns per loop.
 //
 // If a benchmark needs some expensive setup before running, the timer
 // may be stopped:
@@ -36,6 +37,33 @@
 //             big.Len()
 //         }
 //     }
+//
+// The package also runs and verifies example code. Example functions
+// include an introductory comment that is compared with the standard output
+// of the function when the tests are run, as in this example of an example:
+//
+//     // hello
+//     func ExampleHello() {
+//             fmt.Println("hello")
+//     }
+//
+// Example functions without comments are compiled but not executed.
+//
+// The naming convention to declare examples for a function F, a type T and
+// method M on type T are:
+//
+//     func ExampleF() { ... }
+//     func ExampleT() { ... }
+//     func ExampleT_M() { ... }
+//
+// Multiple example functions for a type/function/method may be provided by
+// appending a distinct suffix to the name. The suffix must start with a
+// lower-case letter.
+//
+//     func ExampleF_suffix() { ... }
+//     func ExampleT_suffix() { ... }
+//     func ExampleT_M_suffix() { ... }
+//
 package testing
 
 import (
@@ -44,8 +72,8 @@ import (
 	"os"
 	"runtime"
 	"runtime/pprof"
-	"strings"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -63,19 +91,48 @@ var (
 	memProfile     = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
 	memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
 	cpuProfile     = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
-	timeout        = flag.Int64("test.timeout", 0, "if > 0, sets time limit for tests in seconds")
+	timeout        = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
 	cpuListStr     = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+	parallel       = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
 
 	cpuList []int
 )
 
+// common holds the elements common between T and B and
+// captures common methods such as Errorf.
+type common struct {
+	output   []byte    // Output generated by test or benchmark.
+	failed   bool      // Test or benchmark has failed.
+	start    time.Time // Time test or benchmark started
+	duration time.Duration
+	self     interface{}      // To be sent on signal channel when done.
+	signal   chan interface{} // Output for serial tests.
+}
+
 // Short reports whether the -test.short flag is set.
 func Short() bool {
 	return *short
 }
 
-// Insert final newline if needed and tabs after internal newlines.
-func tabify(s string) string {
+// decorate inserts the final newline if needed and indentation tabs for formatting.
+// If addFileLine is true, it also prefixes the string with the file and line of the call site.
+func decorate(s string, addFileLine bool) string {
+	if addFileLine {
+		_, file, line, ok := runtime.Caller(3) // decorate + log + public function.
+		if ok {
+			// Truncate file name at last file name separator.
+			if index := strings.LastIndex(file, "/"); index >= 0 {
+				file = file[index+1:]
+			} else if index = strings.LastIndex(file, "\\"); index >= 0 {
+				file = file[index+1:]
+			}
+		} else {
+			file = "???"
+			line = 1
+		}
+		s = fmt.Sprintf("%s:%d: %s", file, line, s)
+	}
+	s = "\t" + s // Every line is indented at least one tab.
 	n := len(s)
 	if n > 0 && s[n-1] != '\n' {
 		s += "\n"
@@ -83,7 +140,8 @@ func tabify(s string) string {
 	}
 	for i := 0; i < n-1; i++ { // -1 to avoid final newline
 		if s[i] == '\n' {
-			return s[0:i+1] + "\t" + tabify(s[i+1:n])
+			// Second and subsequent lines are indented an extra tab.
+			return s[0:i+1] + "\t" + decorate(s[i+1:n], false)
 		}
 	}
 	return s
@@ -92,57 +150,86 @@ func tabify(s string) string {
 // T is a type passed to Test functions to manage test state and support formatted test logs.
 // Logs are accumulated during execution and dumped to standard error when done.
 type T struct {
-	errors string
-	failed bool
-	ch     chan *T
+	common
+	name          string    // Name of test.
+	startParallel chan bool // Parallel tests will wait on this.
 }
 
-// Fail marks the Test function as having failed but continues execution.
-func (t *T) Fail() { t.failed = true }
+// Fail marks the function as having failed but continues execution.
+func (c *common) Fail() { c.failed = true }
 
-// Failed returns whether the Test function has failed.
-func (t *T) Failed() bool { return t.failed }
+// Failed returns whether the function has failed.
+func (c *common) Failed() bool { return c.failed }
 
-// FailNow marks the Test function as having failed and stops its execution.
+// FailNow marks the function as having failed and stops its execution.
 // Execution will continue at the next Test.
-func (t *T) FailNow() {
-	t.Fail()
-	t.ch <- t
+func (c *common) FailNow() {
+	c.Fail()
+
+	// Calling runtime.Goexit will exit the goroutine, which
+	// will run the deferred functions in this goroutine,
+	// which will eventually run the deferred lines in tRunner,
+	// which will signal to the test loop that this test is done.
+	//
+	// A previous version of this code said:
+	//
+	//	c.duration = ...
+	//	c.signal <- c.self
+	//	runtime.Goexit()
+	//
+	// This previous version duplicated code (those lines are in
+	// tRunner no matter what), but worse the goroutine teardown
+	// implicit in runtime.Goexit was not guaranteed to complete
+	// before the test exited.  If a test deferred an important cleanup
+	// function (like removing temporary files), there was no guarantee
+	// it would run on a test failure.  Because we send on c.signal during
+	// a top-of-stack deferred function now, we know that the send
+	// only happens after any other stacked defers have completed.
 	runtime.Goexit()
 }
 
-// Log formats its arguments using default formatting, analogous to Print(),
+// log generates the output. It's always at the same stack depth.
+func (c *common) log(s string) {
+	c.output = append(c.output, decorate(s, true)...)
+}
+
+// Log formats its arguments using default formatting, analogous to Println(),
 // and records the text in the error log.
-func (t *T) Log(args ...interface{}) { t.errors += "\t" + tabify(fmt.Sprintln(args...)) }
+func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
 
 // Logf formats its arguments according to the format, analogous to Printf(),
 // and records the text in the error log.
-func (t *T) Logf(format string, args ...interface{}) {
-	t.errors += "\t" + tabify(fmt.Sprintf(format, args...))
-}
+func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
 
 // Error is equivalent to Log() followed by Fail().
-func (t *T) Error(args ...interface{}) {
-	t.Log(args...)
-	t.Fail()
+func (c *common) Error(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.Fail()
 }
 
 // Errorf is equivalent to Logf() followed by Fail().
-func (t *T) Errorf(format string, args ...interface{}) {
-	t.Logf(format, args...)
-	t.Fail()
+func (c *common) Errorf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.Fail()
 }
 
 // Fatal is equivalent to Log() followed by FailNow().
-func (t *T) Fatal(args ...interface{}) {
-	t.Log(args...)
-	t.FailNow()
+func (c *common) Fatal(args ...interface{}) {
+	c.log(fmt.Sprintln(args...))
+	c.FailNow()
 }
 
 // Fatalf is equivalent to Logf() followed by FailNow().
-func (t *T) Fatalf(format string, args ...interface{}) {
-	t.Logf(format, args...)
-	t.FailNow()
+func (c *common) Fatalf(format string, args ...interface{}) {
+	c.log(fmt.Sprintf(format, args...))
+	c.FailNow()
+}
+
+// Parallel signals that this test is to be run in parallel with (and only with) 
+// other parallel tests in this CPU group.
+func (t *T) Parallel() {
+	t.signal <- (*T)(nil) // Release main testing loop
+	<-t.startParallel     // Wait for serial tests to finish
 }
 
 // An internal type but exported because it is cross-package; part of the implementation
@@ -153,73 +240,120 @@ type InternalTest struct {
 }
 
 func tRunner(t *T, test *InternalTest) {
+	t.start = time.Now()
+
+	// When this goroutine is done, either because test.F(t)
+	// returned normally or because a test failure triggered 
+	// a call to runtime.Goexit, record the duration and send
+	// a signal saying that the test is done.
+	defer func() {
+		t.duration = time.Now().Sub(t.start)
+		t.signal <- t
+	}()
+
 	test.F(t)
-	t.ch <- t
 }
 
 // An internal function but exported because it is cross-package; part of the implementation
 // of gotest.
-func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest, benchmarks []InternalBenchmark) {
+func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
 	flag.Parse()
 	parseCpuList()
 
 	before()
 	startAlarm()
-	RunTests(matchString, tests)
+	testOk := RunTests(matchString, tests)
+	exampleOk := RunExamples(examples)
+	if !testOk || !exampleOk {
+		fmt.Println("FAIL")
+		os.Exit(1)
+	}
+	fmt.Println("PASS")
 	stopAlarm()
 	RunBenchmarks(matchString, benchmarks)
 	after()
 }
 
-func RunTests(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) {
-	ok := true
+func (t *T) report() {
+	tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
+	format := "--- %s: %s %s\n%s"
+	if t.failed {
+		fmt.Printf(format, "FAIL", t.name, tstr, t.output)
+	} else if *chatty {
+		fmt.Printf(format, "PASS", t.name, tstr, t.output)
+	}
+}
+
+func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
+	ok = true
 	if len(tests) == 0 {
-		println("testing: warning: no tests to run")
+		fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
+		return
 	}
-	for i := 0; i < len(tests); i++ {
-		matched, err := matchString(*match, tests[i].Name)
-		if err != nil {
-			println("invalid regexp for -test.run:", err.String())
-			os.Exit(1)
-		}
-		if !matched {
-			continue
-		}
-		for _, procs := range cpuList {
-			runtime.GOMAXPROCS(procs)
+	for _, procs := range cpuList {
+		runtime.GOMAXPROCS(procs)
+		// We build a new channel tree for each run of the loop.
+		// collector merges in one channel all the upstream signals from parallel tests.
+		// If all tests pump to the same channel, a bug can occur where a test
+		// kicks off a goroutine that Fails, yet the test still delivers a completion signal,
+		// which skews the counting.
+		var collector = make(chan interface{})
+
+		numParallel := 0
+		startParallel := make(chan bool)
+
+		for i := 0; i < len(tests); i++ {
+			matched, err := matchString(*match, tests[i].Name)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.run: %s\n", err)
+				os.Exit(1)
+			}
+			if !matched {
+				continue
+			}
 			testName := tests[i].Name
 			if procs != 1 {
 				testName = fmt.Sprintf("%s-%d", tests[i].Name, procs)
 			}
+			t := &T{
+				common: common{
+					signal: make(chan interface{}),
+				},
+				name:          testName,
+				startParallel: startParallel,
+			}
+			t.self = t
 			if *chatty {
-				println("=== RUN ", testName)
+				fmt.Printf("=== RUN %s\n", t.name)
 			}
-			ns := -time.Nanoseconds()
-			t := new(T)
-			t.ch = make(chan *T)
 			go tRunner(t, &tests[i])
-			<-t.ch
-			ns += time.Nanoseconds()
-			tstr := fmt.Sprintf("(%.2f seconds)", float64(ns)/1e9)
-			if p := runtime.GOMAXPROCS(-1); t.failed == false && p != procs {
-				t.failed = true
-				t.errors = fmt.Sprintf("%s left GOMAXPROCS set to %d\n", testName, p)
+			out := (<-t.signal).(*T)
+			if out == nil { // Parallel run.
+				go func() {
+					collector <- <-t.signal
+				}()
+				numParallel++
+				continue
 			}
-			if t.failed {
-				println("--- FAIL:", testName, tstr)
-				print(t.errors)
-				ok = false
-			} else if *chatty {
-				println("--- PASS:", testName, tstr)
-				print(t.errors)
+			t.report()
+			ok = ok && !out.failed
+		}
+
+		running := 0
+		for numParallel+running > 0 {
+			if running < *parallel && numParallel > 0 {
+				startParallel <- true
+				running++
+				numParallel--
+				continue
 			}
+			t := (<-collector).(*T)
+			t.report()
+			ok = ok && !t.failed
+			running--
 		}
 	}
-	if !ok {
-		println("FAIL")
-		os.Exit(1)
-	}
-	println("PASS")
+	return
 }
 
 // before runs before all testing.
@@ -266,7 +400,7 @@ var timer *time.Timer
 // startAlarm starts an alarm if requested.
 func startAlarm() {
 	if *timeout > 0 {
-		timer = time.AfterFunc(*timeout*1e9, alarm)
+		timer = time.AfterFunc(*timeout, alarm)
 	}
 }
 
@@ -289,7 +423,7 @@ func parseCpuList() {
 		for _, val := range strings.Split(*cpuListStr, ",") {
 			cpu, err := strconv.Atoi(val)
 			if err != nil || cpu <= 0 {
-				println("invalid value for -test.cpu")
+				fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu", val)
 				os.Exit(1)
 			}
 			cpuList = append(cpuList, cpu)
diff --git a/src/pkg/text/scanner/Makefile b/src/pkg/text/scanner/Makefile
new file mode 100644
index 0000000..c0f28dc
--- /dev/null
+++ b/src/pkg/text/scanner/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=text/scanner
+GOFILES=\
+	scanner.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/text/scanner/scanner.go b/src/pkg/text/scanner/scanner.go
new file mode 100644
index 0000000..f46f63d
--- /dev/null
+++ b/src/pkg/text/scanner/scanner.go
@@ -0,0 +1,670 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package scanner provides a scanner and tokenizer for UTF-8-encoded text.
+// It takes an io.Reader providing the source, which then can be tokenized
+// through repeated calls to the Scan function.  For compatibility with
+// existing tools, the NUL character is not allowed (implementation
+// restriction).
+//
+// By default, a Scanner skips white space and Go comments and recognizes all
+// literals as defined by the Go language specification.  It may be
+// customized to recognize only a subset of those literals and to recognize
+// different white space characters.
+//
+// Basic usage pattern:
+//
+//	var s scanner.Scanner
+//	s.Init(src)
+//	tok := s.Scan()
+//	for tok != scanner.EOF {
+//		// do something with tok
+//		tok = s.Scan()
+//	}
+//
+package scanner
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"unicode"
+	"unicode/utf8"
+)
+
+// TODO(gri): Consider changing this to use the new (token) Position package.
+
+// A source position is represented by a Position value.
+// A position is valid if Line > 0.
+type Position struct {
+	Filename string // filename, if any
+	Offset   int    // byte offset, starting at 0
+	Line     int    // line number, starting at 1
+	Column   int    // column number, starting at 1 (character count per line)
+}
+
+// IsValid returns true if the position is valid.
+func (pos *Position) IsValid() bool { return pos.Line > 0 }
+
+func (pos Position) String() string {
+	s := pos.Filename
+	if pos.IsValid() {
+		if s != "" {
+			s += ":"
+		}
+		s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
+	}
+	if s == "" {
+		s = "???"
+	}
+	return s
+}
+
+// Predefined mode bits to control recognition of tokens. For instance,
+// to configure a Scanner such that it only recognizes (Go) identifiers,
+// integers, and skips comments, set the Scanner's Mode field to:
+//
+//	ScanIdents | ScanInts | SkipComments
+//
+const (
+	ScanIdents     = 1 << -Ident
+	ScanInts       = 1 << -Int
+	ScanFloats     = 1 << -Float // includes Ints
+	ScanChars      = 1 << -Char
+	ScanStrings    = 1 << -String
+	ScanRawStrings = 1 << -RawString
+	ScanComments   = 1 << -Comment
+	SkipComments   = 1 << -skipComment // if set with ScanComments, comments become white space
+	GoTokens       = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
+)
+
+// The result of Scan is one of the following tokens or a Unicode character.
+const (
+	EOF = -(iota + 1)
+	Ident
+	Int
+	Float
+	Char
+	String
+	RawString
+	Comment
+	skipComment
+)
+
+var tokenString = map[rune]string{
+	EOF:       "EOF",
+	Ident:     "Ident",
+	Int:       "Int",
+	Float:     "Float",
+	Char:      "Char",
+	String:    "String",
+	RawString: "RawString",
+	Comment:   "Comment",
+}
+
+// TokenString returns a (visible) string for a token or Unicode character.
+func TokenString(tok rune) string {
+	if s, found := tokenString[tok]; found {
+		return s
+	}
+	return fmt.Sprintf("%q", string(tok))
+}
+
+// GoWhitespace is the default value for the Scanner's Whitespace field.
+// Its value selects Go's white space characters.
+const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '
+
+const bufLen = 1024 // at least utf8.UTFMax
+
+// A Scanner implements reading of Unicode characters and tokens from an io.Reader.
+type Scanner struct {
+	// Input
+	src io.Reader
+
+	// Source buffer
+	srcBuf [bufLen + 1]byte // +1 for sentinel for common case of s.next()
+	srcPos int              // reading position (srcBuf index)
+	srcEnd int              // source end (srcBuf index)
+
+	// Source position
+	srcBufOffset int // byte offset of srcBuf[0] in source
+	line         int // line count
+	column       int // character count
+	lastLineLen  int // length of last line in characters (for correct column reporting)
+	lastCharLen  int // length of last character in bytes
+
+	// Token text buffer
+	// Typically, token text is stored completely in srcBuf, but in general
+	// the token text's head may be buffered in tokBuf while the token text's
+	// tail is stored in srcBuf.
+	tokBuf bytes.Buffer // token text head that is not in srcBuf anymore
+	tokPos int          // token text tail position (srcBuf index); valid if >= 0
+	tokEnd int          // token text tail end (srcBuf index)
+
+	// One character look-ahead
+	ch rune // character before current srcPos
+
+	// Error is called for each error encountered. If no Error
+	// function is set, the error is reported to os.Stderr.
+	Error func(s *Scanner, msg string)
+
+	// ErrorCount is incremented by one for each error encountered.
+	ErrorCount int
+
+	// The Mode field controls which tokens are recognized. For instance,
+	// to recognize Ints, set the ScanInts bit in Mode. The field may be
+	// changed at any time.
+	Mode uint
+
+	// The Whitespace field controls which characters are recognized
+	// as white space. To recognize a character ch <= ' ' as white space,
+	// set the ch'th bit in Whitespace (the Scanner's behavior is undefined
+	// for values ch > ' '). The field may be changed at any time.
+	Whitespace uint64
+
+	// Start position of most recently scanned token; set by Scan.
+	// Calling Init or Next invalidates the position (Line == 0).
+	// The Filename field is always left untouched by the Scanner.
+	// If an error is reported (via Error) and Position is invalid,
+	// the scanner is not inside a token. Call Pos to obtain an error
+	// position in that case.
+	Position
+}
+
+// Init initializes a Scanner with a new source and returns s.
+// Error is set to nil, ErrorCount is set to 0, Mode is set to GoTokens,
+// and Whitespace is set to GoWhitespace.
+func (s *Scanner) Init(src io.Reader) *Scanner {
+	s.src = src
+
+	// initialize source buffer
+	// (the first call to next() will fill it by calling src.Read)
+	s.srcBuf[0] = utf8.RuneSelf // sentinel
+	s.srcPos = 0
+	s.srcEnd = 0
+
+	// initialize source position
+	s.srcBufOffset = 0
+	s.line = 1
+	s.column = 0
+	s.lastLineLen = 0
+	s.lastCharLen = 0
+
+	// initialize token text buffer
+	// (required for first call to next()).
+	s.tokPos = -1
+
+	// initialize one character look-ahead
+	s.ch = -1 // no char read yet
+
+	// initialize public fields
+	s.Error = nil
+	s.ErrorCount = 0
+	s.Mode = GoTokens
+	s.Whitespace = GoWhitespace
+	s.Line = 0 // invalidate token position
+
+	return s
+}
+
+// TODO(gri): The code for next() and the internal scanner state could benefit
+//            from a rethink. While next() is optimized for the common ASCII
+//            case, the "corrections" needed for proper position tracking undo
+//            some of the attempts for fast-path optimization.
+
+// next reads and returns the next Unicode character. It is designed such
+// that only a minimal amount of work needs to be done in the common ASCII
+// case (one test to check for both ASCII and end-of-buffer, and one test
+// to check for newlines).
+func (s *Scanner) next() rune {
+	ch, width := rune(s.srcBuf[s.srcPos]), 1
+
+	if ch >= utf8.RuneSelf {
+		// uncommon case: not ASCII or not enough bytes
+		for s.srcPos+utf8.UTFMax > s.srcEnd && !utf8.FullRune(s.srcBuf[s.srcPos:s.srcEnd]) {
+			// not enough bytes: read some more, but first
+			// save away token text if any
+			if s.tokPos >= 0 {
+				s.tokBuf.Write(s.srcBuf[s.tokPos:s.srcPos])
+				s.tokPos = 0
+				// s.tokEnd is set by Scan()
+			}
+			// move unread bytes to beginning of buffer
+			copy(s.srcBuf[0:], s.srcBuf[s.srcPos:s.srcEnd])
+			s.srcBufOffset += s.srcPos
+			// read more bytes
+			// (an io.Reader must return io.EOF when it reaches
+			// the end of what it is reading - simply returning
+			// n == 0 will make this loop retry forever; but the
+			// error is in the reader implementation in that case)
+			i := s.srcEnd - s.srcPos
+			n, err := s.src.Read(s.srcBuf[i:bufLen])
+			s.srcPos = 0
+			s.srcEnd = i + n
+			s.srcBuf[s.srcEnd] = utf8.RuneSelf // sentinel
+			if err != nil {
+				if s.srcEnd == 0 {
+					if s.lastCharLen > 0 {
+						// previous character was not EOF
+						s.column++
+					}
+					s.lastCharLen = 0
+					return EOF
+				}
+				if err != io.EOF {
+					s.error(err.Error())
+				}
+				// If err == EOF, we won't be getting more
+				// bytes; break to avoid infinite loop. If
+				// err is something else, we don't know if
+				// we can get more bytes; thus also break.
+				break
+			}
+		}
+		// at least one byte
+		ch = rune(s.srcBuf[s.srcPos])
+		if ch >= utf8.RuneSelf {
+			// uncommon case: not ASCII
+			ch, width = utf8.DecodeRune(s.srcBuf[s.srcPos:s.srcEnd])
+			if ch == utf8.RuneError && width == 1 {
+				// advance for correct error position
+				s.srcPos += width
+				s.lastCharLen = width
+				s.column++
+				s.error("illegal UTF-8 encoding")
+				return ch
+			}
+		}
+	}
+
+	// advance
+	s.srcPos += width
+	s.lastCharLen = width
+	s.column++
+
+	// special situations
+	switch ch {
+	case 0:
+		// implementation restriction for compatibility with other tools
+		s.error("illegal character NUL")
+	case '\n':
+		s.line++
+		s.lastLineLen = s.column
+		s.column = 0
+	}
+
+	return ch
+}
+
+// Next reads and returns the next Unicode character.
+// It returns EOF at the end of the source. It reports
+// a read error by calling s.Error, if not nil; otherwise
+// it prints an error message to os.Stderr. Next does not
+// update the Scanner's Position field; use Pos() to
+// get the current position.
+func (s *Scanner) Next() rune {
+	s.tokPos = -1 // don't collect token text
+	s.Line = 0    // invalidate token position
+	ch := s.Peek()
+	s.ch = s.next()
+	return ch
+}
+
+// Peek returns the next Unicode character in the source without advancing
+// the scanner. It returns EOF if the scanner's position is at the last
+// character of the source.
+func (s *Scanner) Peek() rune {
+	if s.ch < 0 {
+		s.ch = s.next()
+	}
+	return s.ch
+}
+
+func (s *Scanner) error(msg string) {
+	s.ErrorCount++
+	if s.Error != nil {
+		s.Error(s, msg)
+		return
+	}
+	pos := s.Position
+	if !pos.IsValid() {
+		pos = s.Pos()
+	}
+	fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
+}
+
+func (s *Scanner) scanIdentifier() rune {
+	ch := s.next() // read character after first '_' or letter
+	for ch == '_' || unicode.IsLetter(ch) || unicode.IsDigit(ch) {
+		ch = s.next()
+	}
+	return ch
+}
+
+func digitVal(ch rune) int {
+	switch {
+	case '0' <= ch && ch <= '9':
+		return int(ch - '0')
+	case 'a' <= ch && ch <= 'f':
+		return int(ch - 'a' + 10)
+	case 'A' <= ch && ch <= 'F':
+		return int(ch - 'A' + 10)
+	}
+	return 16 // larger than any legal digit val
+}
+
+func isDecimal(ch rune) bool { return '0' <= ch && ch <= '9' }
+
+func (s *Scanner) scanMantissa(ch rune) rune {
+	for isDecimal(ch) {
+		ch = s.next()
+	}
+	return ch
+}
+
+func (s *Scanner) scanFraction(ch rune) rune {
+	if ch == '.' {
+		ch = s.scanMantissa(s.next())
+	}
+	return ch
+}
+
+func (s *Scanner) scanExponent(ch rune) rune {
+	if ch == 'e' || ch == 'E' {
+		ch = s.next()
+		if ch == '-' || ch == '+' {
+			ch = s.next()
+		}
+		ch = s.scanMantissa(ch)
+	}
+	return ch
+}
+
+func (s *Scanner) scanNumber(ch rune) (rune, rune) {
+	// isDecimal(ch)
+	if ch == '0' {
+		// int or float
+		ch = s.next()
+		if ch == 'x' || ch == 'X' {
+			// hexadecimal int
+			ch = s.next()
+			for digitVal(ch) < 16 {
+				ch = s.next()
+			}
+		} else {
+			// octal int or float
+			seenDecimalDigit := false
+			for isDecimal(ch) {
+				if ch > '7' {
+					seenDecimalDigit = true
+				}
+				ch = s.next()
+			}
+			if s.Mode&ScanFloats != 0 && (ch == '.' || ch == 'e' || ch == 'E') {
+				// float
+				ch = s.scanFraction(ch)
+				ch = s.scanExponent(ch)
+				return Float, ch
+			}
+			// octal int
+			if seenDecimalDigit {
+				s.error("illegal octal number")
+			}
+		}
+		return Int, ch
+	}
+	// decimal int or float
+	ch = s.scanMantissa(ch)
+	if s.Mode&ScanFloats != 0 && (ch == '.' || ch == 'e' || ch == 'E') {
+		// float
+		ch = s.scanFraction(ch)
+		ch = s.scanExponent(ch)
+		return Float, ch
+	}
+	return Int, ch
+}
+
+func (s *Scanner) scanDigits(ch rune, base, n int) rune {
+	for n > 0 && digitVal(ch) < base {
+		ch = s.next()
+		n--
+	}
+	if n > 0 {
+		s.error("illegal char escape")
+	}
+	return ch
+}
+
+func (s *Scanner) scanEscape(quote rune) rune {
+	ch := s.next() // read character after '/'
+	switch ch {
+	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
+		// nothing to do
+		ch = s.next()
+	case '0', '1', '2', '3', '4', '5', '6', '7':
+		ch = s.scanDigits(ch, 8, 3)
+	case 'x':
+		ch = s.scanDigits(s.next(), 16, 2)
+	case 'u':
+		ch = s.scanDigits(s.next(), 16, 4)
+	case 'U':
+		ch = s.scanDigits(s.next(), 16, 8)
+	default:
+		s.error("illegal char escape")
+	}
+	return ch
+}
+
+func (s *Scanner) scanString(quote rune) (n int) {
+	ch := s.next() // read character after quote
+	for ch != quote {
+		if ch == '\n' || ch < 0 {
+			s.error("literal not terminated")
+			return
+		}
+		if ch == '\\' {
+			ch = s.scanEscape(quote)
+		} else {
+			ch = s.next()
+		}
+		n++
+	}
+	return
+}
+
+func (s *Scanner) scanRawString() {
+	ch := s.next() // read character after '`'
+	for ch != '`' {
+		if ch < 0 {
+			s.error("literal not terminated")
+			return
+		}
+		ch = s.next()
+	}
+}
+
+func (s *Scanner) scanChar() {
+	if s.scanString('\'') != 1 {
+		s.error("illegal char literal")
+	}
+}
+
+func (s *Scanner) scanComment(ch rune) rune {
+	// ch == '/' || ch == '*'
+	if ch == '/' {
+		// line comment
+		ch = s.next() // read character after "//"
+		for ch != '\n' && ch >= 0 {
+			ch = s.next()
+		}
+		return ch
+	}
+
+	// general comment
+	ch = s.next() // read character after "/*"
+	for {
+		if ch < 0 {
+			s.error("comment not terminated")
+			break
+		}
+		ch0 := ch
+		ch = s.next()
+		if ch0 == '*' && ch == '/' {
+			ch = s.next()
+			break
+		}
+	}
+	return ch
+}
+
+// Scan reads the next token or Unicode character from source and returns it.
+// It only recognizes tokens t for which the respective Mode bit (1<<-t) is set.
+// It returns EOF at the end of the source. It reports scanner errors (read and
+// token errors) by calling s.Error, if not nil; otherwise it prints an error
+// message to os.Stderr.
+func (s *Scanner) Scan() rune {
+	ch := s.Peek()
+
+	// reset token text position
+	s.tokPos = -1
+	s.Line = 0
+
+redo:
+	// skip white space
+	for s.Whitespace&(1<<uint(ch)) != 0 {
+		ch = s.next()
+	}
+
+	// start collecting token text
+	s.tokBuf.Reset()
+	s.tokPos = s.srcPos - s.lastCharLen
+
+	// set token position
+	// (this is a slightly optimized version of the code in Pos())
+	s.Offset = s.srcBufOffset + s.tokPos
+	if s.column > 0 {
+		// common case: last character was not a '\n'
+		s.Line = s.line
+		s.Column = s.column
+	} else {
+		// last character was a '\n'
+		// (we cannot be at the beginning of the source
+		// since we have called next() at least once)
+		s.Line = s.line - 1
+		s.Column = s.lastLineLen
+	}
+
+	// determine token value
+	tok := ch
+	switch {
+	case unicode.IsLetter(ch) || ch == '_':
+		if s.Mode&ScanIdents != 0 {
+			tok = Ident
+			ch = s.scanIdentifier()
+		} else {
+			ch = s.next()
+		}
+	case isDecimal(ch):
+		if s.Mode&(ScanInts|ScanFloats) != 0 {
+			tok, ch = s.scanNumber(ch)
+		} else {
+			ch = s.next()
+		}
+	default:
+		switch ch {
+		case '"':
+			if s.Mode&ScanStrings != 0 {
+				s.scanString('"')
+				tok = String
+			}
+			ch = s.next()
+		case '\'':
+			if s.Mode&ScanChars != 0 {
+				s.scanChar()
+				tok = Char
+			}
+			ch = s.next()
+		case '.':
+			ch = s.next()
+			if isDecimal(ch) && s.Mode&ScanFloats != 0 {
+				tok = Float
+				ch = s.scanMantissa(ch)
+				ch = s.scanExponent(ch)
+			}
+		case '/':
+			ch = s.next()
+			if (ch == '/' || ch == '*') && s.Mode&ScanComments != 0 {
+				if s.Mode&SkipComments != 0 {
+					s.tokPos = -1 // don't collect token text
+					ch = s.scanComment(ch)
+					goto redo
+				}
+				ch = s.scanComment(ch)
+				tok = Comment
+			}
+		case '`':
+			if s.Mode&ScanRawStrings != 0 {
+				s.scanRawString()
+				tok = String
+			}
+			ch = s.next()
+		default:
+			ch = s.next()
+		}
+	}
+
+	// end of token text
+	s.tokEnd = s.srcPos - s.lastCharLen
+
+	s.ch = ch
+	return tok
+}
+
+// Pos returns the position of the character immediately after
+// the character or token returned by the last call to Next or Scan.
+func (s *Scanner) Pos() (pos Position) {
+	pos.Filename = s.Filename
+	pos.Offset = s.srcBufOffset + s.srcPos - s.lastCharLen
+	switch {
+	case s.column > 0:
+		// common case: last character was not a '\n'
+		pos.Line = s.line
+		pos.Column = s.column
+	case s.lastLineLen > 0:
+		// last character was a '\n'
+		pos.Line = s.line - 1
+		pos.Column = s.lastLineLen
+	default:
+		// at the beginning of the source
+		pos.Line = 1
+		pos.Column = 1
+	}
+	return
+}
+
+// TokenText returns the string corresponding to the most recently scanned token.
+// Valid after calling Scan().
+func (s *Scanner) TokenText() string {
+	if s.tokPos < 0 {
+		// no token text
+		return ""
+	}
+
+	if s.tokEnd < 0 {
+		// if EOF was reached, s.tokEnd is set to -1 (s.srcPos == 0)
+		s.tokEnd = s.tokPos
+	}
+
+	if s.tokBuf.Len() == 0 {
+		// common case: the entire token text is still in srcBuf
+		return string(s.srcBuf[s.tokPos:s.tokEnd])
+	}
+
+	// part of the token text was saved in tokBuf: save the rest in
+	// tokBuf as well and return its content
+	s.tokBuf.Write(s.srcBuf[s.tokPos:s.tokEnd])
+	s.tokPos = s.tokEnd // ensure idempotency of TokenText() call
+	return s.tokBuf.String()
+}
diff --git a/src/pkg/text/scanner/scanner_test.go b/src/pkg/text/scanner/scanner_test.go
new file mode 100644
index 0000000..bb3adb5
--- /dev/null
+++ b/src/pkg/text/scanner/scanner_test.go
@@ -0,0 +1,563 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package scanner
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"strings"
+	"testing"
+	"unicode/utf8"
+)
+
+// A StringReader delivers its data one string segment at a time via Read.
+type StringReader struct {
+	data []string
+	step int
+}
+
+func (r *StringReader) Read(p []byte) (n int, err error) {
+	if r.step < len(r.data) {
+		s := r.data[r.step]
+		n = copy(p, s)
+		r.step++
+	} else {
+		err = io.EOF
+	}
+	return
+}
+
+func readRuneSegments(t *testing.T, segments []string) {
+	got := ""
+	want := strings.Join(segments, "")
+	s := new(Scanner).Init(&StringReader{data: segments})
+	for {
+		ch := s.Next()
+		if ch == EOF {
+			break
+		}
+		got += string(ch)
+	}
+	if got != want {
+		t.Errorf("segments=%v got=%s want=%s", segments, got, want)
+	}
+}
+
+var segmentList = [][]string{
+	{},
+	{""},
+	{"日", "本語"},
+	{"\u65e5", "\u672c", "\u8a9e"},
+	{"\U000065e5", " ", "\U0000672c", "\U00008a9e"},
+	{"\xe6", "\x97\xa5\xe6", "\x9c\xac\xe8\xaa\x9e"},
+	{"Hello", ", ", "World", "!"},
+	{"Hello", ", ", "", "World", "!"},
+}
+
+func TestNext(t *testing.T) {
+	for _, s := range segmentList {
+		readRuneSegments(t, s)
+	}
+}
+
+type token struct {
+	tok  rune
+	text string
+}
+
+var f100 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+
+var tokenList = []token{
+	{Comment, "// line comments"},
+	{Comment, "//"},
+	{Comment, "////"},
+	{Comment, "// comment"},
+	{Comment, "// /* comment */"},
+	{Comment, "// // comment //"},
+	{Comment, "//" + f100},
+
+	{Comment, "// general comments"},
+	{Comment, "/**/"},
+	{Comment, "/***/"},
+	{Comment, "/* comment */"},
+	{Comment, "/* // comment */"},
+	{Comment, "/* /* comment */"},
+	{Comment, "/*\n comment\n*/"},
+	{Comment, "/*" + f100 + "*/"},
+
+	{Comment, "// identifiers"},
+	{Ident, "a"},
+	{Ident, "a0"},
+	{Ident, "foobar"},
+	{Ident, "abc123"},
+	{Ident, "LGTM"},
+	{Ident, "_"},
+	{Ident, "_abc123"},
+	{Ident, "abc123_"},
+	{Ident, "_abc_123_"},
+	{Ident, "_äöü"},
+	{Ident, "_本"},
+	{Ident, "äöü"},
+	{Ident, "本"},
+	{Ident, "aÛ°Û±Û¸"},
+	{Ident, "foo६४"},
+	{Ident, "bar9876"},
+	{Ident, f100},
+
+	{Comment, "// decimal ints"},
+	{Int, "0"},
+	{Int, "1"},
+	{Int, "9"},
+	{Int, "42"},
+	{Int, "1234567890"},
+
+	{Comment, "// octal ints"},
+	{Int, "00"},
+	{Int, "01"},
+	{Int, "07"},
+	{Int, "042"},
+	{Int, "01234567"},
+
+	{Comment, "// hexadecimal ints"},
+	{Int, "0x0"},
+	{Int, "0x1"},
+	{Int, "0xf"},
+	{Int, "0x42"},
+	{Int, "0x123456789abcDEF"},
+	{Int, "0x" + f100},
+	{Int, "0X0"},
+	{Int, "0X1"},
+	{Int, "0XF"},
+	{Int, "0X42"},
+	{Int, "0X123456789abcDEF"},
+	{Int, "0X" + f100},
+
+	{Comment, "// floats"},
+	{Float, "0."},
+	{Float, "1."},
+	{Float, "42."},
+	{Float, "01234567890."},
+	{Float, ".0"},
+	{Float, ".1"},
+	{Float, ".42"},
+	{Float, ".0123456789"},
+	{Float, "0.0"},
+	{Float, "1.0"},
+	{Float, "42.0"},
+	{Float, "01234567890.0"},
+	{Float, "0e0"},
+	{Float, "1e0"},
+	{Float, "42e0"},
+	{Float, "01234567890e0"},
+	{Float, "0E0"},
+	{Float, "1E0"},
+	{Float, "42E0"},
+	{Float, "01234567890E0"},
+	{Float, "0e+10"},
+	{Float, "1e-10"},
+	{Float, "42e+10"},
+	{Float, "01234567890e-10"},
+	{Float, "0E+10"},
+	{Float, "1E-10"},
+	{Float, "42E+10"},
+	{Float, "01234567890E-10"},
+
+	{Comment, "// chars"},
+	{Char, `' '`},
+	{Char, `'a'`},
+	{Char, `'本'`},
+	{Char, `'\a'`},
+	{Char, `'\b'`},
+	{Char, `'\f'`},
+	{Char, `'\n'`},
+	{Char, `'\r'`},
+	{Char, `'\t'`},
+	{Char, `'\v'`},
+	{Char, `'\''`},
+	{Char, `'\000'`},
+	{Char, `'\777'`},
+	{Char, `'\x00'`},
+	{Char, `'\xff'`},
+	{Char, `'\u0000'`},
+	{Char, `'\ufA16'`},
+	{Char, `'\U00000000'`},
+	{Char, `'\U0000ffAB'`},
+
+	{Comment, "// strings"},
+	{String, `" "`},
+	{String, `"a"`},
+	{String, `"本"`},
+	{String, `"\a"`},
+	{String, `"\b"`},
+	{String, `"\f"`},
+	{String, `"\n"`},
+	{String, `"\r"`},
+	{String, `"\t"`},
+	{String, `"\v"`},
+	{String, `"\""`},
+	{String, `"\000"`},
+	{String, `"\777"`},
+	{String, `"\x00"`},
+	{String, `"\xff"`},
+	{String, `"\u0000"`},
+	{String, `"\ufA16"`},
+	{String, `"\U00000000"`},
+	{String, `"\U0000ffAB"`},
+	{String, `"` + f100 + `"`},
+
+	{Comment, "// raw strings"},
+	{String, "``"},
+	{String, "`\\`"},
+	{String, "`" + "\n\n/* foobar */\n\n" + "`"},
+	{String, "`" + f100 + "`"},
+
+	{Comment, "// individual characters"},
+	// NUL character is not allowed
+	{'\x01', "\x01"},
+	{' ' - 1, string(' ' - 1)},
+	{'+', "+"},
+	{'/', "/"},
+	{'.', "."},
+	{'~', "~"},
+	{'(', "("},
+}
+
+func makeSource(pattern string) *bytes.Buffer {
+	var buf bytes.Buffer
+	for _, k := range tokenList {
+		fmt.Fprintf(&buf, pattern, k.text)
+	}
+	return &buf
+}
+
+func checkTok(t *testing.T, s *Scanner, line int, got, want rune, text string) {
+	if got != want {
+		t.Fatalf("tok = %s, want %s for %q", TokenString(got), TokenString(want), text)
+	}
+	if s.Line != line {
+		t.Errorf("line = %d, want %d for %q", s.Line, line, text)
+	}
+	stext := s.TokenText()
+	if stext != text {
+		t.Errorf("text = %q, want %q", stext, text)
+	} else {
+		// check idempotency of TokenText() call
+		stext = s.TokenText()
+		if stext != text {
+			t.Errorf("text = %q, want %q (idempotency check)", stext, text)
+		}
+	}
+}
+
+func countNewlines(s string) int {
+	n := 0
+	for _, ch := range s {
+		if ch == '\n' {
+			n++
+		}
+	}
+	return n
+}
+
+func testScan(t *testing.T, mode uint) {
+	s := new(Scanner).Init(makeSource(" \t%s\n"))
+	s.Mode = mode
+	tok := s.Scan()
+	line := 1
+	for _, k := range tokenList {
+		if mode&SkipComments == 0 || k.tok != Comment {
+			checkTok(t, s, line, tok, k.tok, k.text)
+			tok = s.Scan()
+		}
+		line += countNewlines(k.text) + 1 // each token is on a new line
+	}
+	checkTok(t, s, line, tok, EOF, "")
+}
+
+func TestScan(t *testing.T) {
+	testScan(t, GoTokens)
+	testScan(t, GoTokens&^SkipComments)
+}
+
+func TestPosition(t *testing.T) {
+	src := makeSource("\t\t\t\t%s\n")
+	s := new(Scanner).Init(src)
+	s.Mode = GoTokens &^ SkipComments
+	s.Scan()
+	pos := Position{"", 4, 1, 5}
+	for _, k := range tokenList {
+		if s.Offset != pos.Offset {
+			t.Errorf("offset = %d, want %d for %q", s.Offset, pos.Offset, k.text)
+		}
+		if s.Line != pos.Line {
+			t.Errorf("line = %d, want %d for %q", s.Line, pos.Line, k.text)
+		}
+		if s.Column != pos.Column {
+			t.Errorf("column = %d, want %d for %q", s.Column, pos.Column, k.text)
+		}
+		pos.Offset += 4 + len(k.text) + 1     // 4 tabs + token bytes + newline
+		pos.Line += countNewlines(k.text) + 1 // each token is on a new line
+		s.Scan()
+	}
+	// make sure there were no token-internal errors reported by scanner
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
+
+func TestScanZeroMode(t *testing.T) {
+	src := makeSource("%s\n")
+	str := src.String()
+	s := new(Scanner).Init(src)
+	s.Mode = 0       // don't recognize any token classes
+	s.Whitespace = 0 // don't skip any whitespace
+	tok := s.Scan()
+	for i, ch := range str {
+		if tok != ch {
+			t.Fatalf("%d. tok = %s, want %s", i, TokenString(tok), TokenString(ch))
+		}
+		tok = s.Scan()
+	}
+	if tok != EOF {
+		t.Fatalf("tok = %s, want EOF", TokenString(tok))
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
+
+func testScanSelectedMode(t *testing.T, mode uint, class rune) {
+	src := makeSource("%s\n")
+	s := new(Scanner).Init(src)
+	s.Mode = mode
+	tok := s.Scan()
+	for tok != EOF {
+		if tok < 0 && tok != class {
+			t.Fatalf("tok = %s, want %s", TokenString(tok), TokenString(class))
+		}
+		tok = s.Scan()
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
+
+func TestScanSelectedMask(t *testing.T) {
+	testScanSelectedMode(t, 0, 0)
+	testScanSelectedMode(t, ScanIdents, Ident)
+	// Don't test ScanInts and ScanNumbers since some parts of
+	// the floats in the source look like (illegal) octal ints
+	// and ScanNumbers may return either Int or Float.
+	testScanSelectedMode(t, ScanChars, Char)
+	testScanSelectedMode(t, ScanStrings, String)
+	testScanSelectedMode(t, SkipComments, 0)
+	testScanSelectedMode(t, ScanComments, Comment)
+}
+
+func TestScanNext(t *testing.T) {
+	s := new(Scanner).Init(bytes.NewBufferString("if a == bcd /* comment */ {\n\ta += c\n} // line comment ending in eof"))
+	checkTok(t, s, 1, s.Scan(), Ident, "if")
+	checkTok(t, s, 1, s.Scan(), Ident, "a")
+	checkTok(t, s, 1, s.Scan(), '=', "=")
+	checkTok(t, s, 0, s.Next(), '=', "")
+	checkTok(t, s, 0, s.Next(), ' ', "")
+	checkTok(t, s, 0, s.Next(), 'b', "")
+	checkTok(t, s, 1, s.Scan(), Ident, "cd")
+	checkTok(t, s, 1, s.Scan(), '{', "{")
+	checkTok(t, s, 2, s.Scan(), Ident, "a")
+	checkTok(t, s, 2, s.Scan(), '+', "+")
+	checkTok(t, s, 0, s.Next(), '=', "")
+	checkTok(t, s, 2, s.Scan(), Ident, "c")
+	checkTok(t, s, 3, s.Scan(), '}', "}")
+	checkTok(t, s, 3, s.Scan(), -1, "")
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
+
+func TestScanWhitespace(t *testing.T) {
+	var buf bytes.Buffer
+	var ws uint64
+	// start at 1, NUL character is not allowed
+	for ch := byte(1); ch < ' '; ch++ {
+		buf.WriteByte(ch)
+		ws |= 1 << ch
+	}
+	const orig = 'x'
+	buf.WriteByte(orig)
+
+	s := new(Scanner).Init(&buf)
+	s.Mode = 0
+	s.Whitespace = ws
+	tok := s.Scan()
+	if tok != orig {
+		t.Errorf("tok = %s, want %s", TokenString(tok), TokenString(orig))
+	}
+}
+
+func testError(t *testing.T, src, pos, msg string, tok rune) {
+	s := new(Scanner).Init(bytes.NewBufferString(src))
+	errorCalled := false
+	s.Error = func(s *Scanner, m string) {
+		if !errorCalled {
+			// only look at first error
+			if p := s.Pos().String(); p != pos {
+				t.Errorf("pos = %q, want %q for %q", p, pos, src)
+			}
+			if m != msg {
+				t.Errorf("msg = %q, want %q for %q", m, msg, src)
+			}
+			errorCalled = true
+		}
+	}
+	tk := s.Scan()
+	if tk != tok {
+		t.Errorf("tok = %s, want %s for %q", TokenString(tk), TokenString(tok), src)
+	}
+	if !errorCalled {
+		t.Errorf("error handler not called for %q", src)
+	}
+	if s.ErrorCount == 0 {
+		t.Errorf("count = %d, want > 0 for %q", s.ErrorCount, src)
+	}
+}
+
+func TestError(t *testing.T) {
+	testError(t, "\x00", "1:1", "illegal character NUL", 0)
+	testError(t, "\x80", "1:1", "illegal UTF-8 encoding", utf8.RuneError)
+	testError(t, "\xff", "1:1", "illegal UTF-8 encoding", utf8.RuneError)
+
+	testError(t, "a\x00", "1:2", "illegal character NUL", Ident)
+	testError(t, "ab\x80", "1:3", "illegal UTF-8 encoding", Ident)
+	testError(t, "abc\xff", "1:4", "illegal UTF-8 encoding", Ident)
+
+	testError(t, `"a`+"\x00", "1:3", "illegal character NUL", String)
+	testError(t, `"ab`+"\x80", "1:4", "illegal UTF-8 encoding", String)
+	testError(t, `"abc`+"\xff", "1:5", "illegal UTF-8 encoding", String)
+
+	testError(t, "`a"+"\x00", "1:3", "illegal character NUL", String)
+	testError(t, "`ab"+"\x80", "1:4", "illegal UTF-8 encoding", String)
+	testError(t, "`abc"+"\xff", "1:5", "illegal UTF-8 encoding", String)
+
+	testError(t, `'\"'`, "1:3", "illegal char escape", Char)
+	testError(t, `"\'"`, "1:3", "illegal char escape", String)
+
+	testError(t, `01238`, "1:6", "illegal octal number", Int)
+	testError(t, `'aa'`, "1:4", "illegal char literal", Char)
+
+	testError(t, `'`, "1:2", "literal not terminated", Char)
+	testError(t, `'`+"\n", "1:2", "literal not terminated", Char)
+	testError(t, `"abc`, "1:5", "literal not terminated", String)
+	testError(t, `"abc`+"\n", "1:5", "literal not terminated", String)
+	testError(t, "`abc\n", "2:1", "literal not terminated", String)
+	testError(t, `/*/`, "1:4", "comment not terminated", EOF)
+}
+
+func checkPos(t *testing.T, got, want Position) {
+	if got.Offset != want.Offset || got.Line != want.Line || got.Column != want.Column {
+		t.Errorf("got offset, line, column = %d, %d, %d; want %d, %d, %d",
+			got.Offset, got.Line, got.Column, want.Offset, want.Line, want.Column)
+	}
+}
+
+func checkNextPos(t *testing.T, s *Scanner, offset, line, column int, char rune) {
+	if ch := s.Next(); ch != char {
+		t.Errorf("ch = %s, want %s", TokenString(ch), TokenString(char))
+	}
+	want := Position{Offset: offset, Line: line, Column: column}
+	checkPos(t, s.Pos(), want)
+}
+
+func checkScanPos(t *testing.T, s *Scanner, offset, line, column int, char rune) {
+	want := Position{Offset: offset, Line: line, Column: column}
+	checkPos(t, s.Pos(), want)
+	if ch := s.Scan(); ch != char {
+		t.Errorf("ch = %s, want %s", TokenString(ch), TokenString(char))
+		if string(ch) != s.TokenText() {
+			t.Errorf("tok = %q, want %q", s.TokenText(), string(ch))
+		}
+	}
+	checkPos(t, s.Position, want)
+}
+
+func TestPos(t *testing.T) {
+	// corner case: empty source
+	s := new(Scanner).Init(bytes.NewBufferString(""))
+	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
+	s.Peek() // peek doesn't affect the position
+	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
+
+	// corner case: source with only a newline
+	s = new(Scanner).Init(bytes.NewBufferString("\n"))
+	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
+	checkNextPos(t, s, 1, 2, 1, '\n')
+	// after EOF position doesn't change
+	for i := 10; i > 0; i-- {
+		checkScanPos(t, s, 1, 2, 1, EOF)
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+
+	// corner case: source with only a single character
+	s = new(Scanner).Init(bytes.NewBufferString("本"))
+	checkPos(t, s.Pos(), Position{Offset: 0, Line: 1, Column: 1})
+	checkNextPos(t, s, 3, 1, 2, '本')
+	// after EOF position doesn't change
+	for i := 10; i > 0; i-- {
+		checkScanPos(t, s, 3, 1, 2, EOF)
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+
+	// positions after calling Next
+	s = new(Scanner).Init(bytes.NewBufferString("  foo६४  \n\n本語\n"))
+	checkNextPos(t, s, 1, 1, 2, ' ')
+	s.Peek() // peek doesn't affect the position
+	checkNextPos(t, s, 2, 1, 3, ' ')
+	checkNextPos(t, s, 3, 1, 4, 'f')
+	checkNextPos(t, s, 4, 1, 5, 'o')
+	checkNextPos(t, s, 5, 1, 6, 'o')
+	checkNextPos(t, s, 8, 1, 7, '६')
+	checkNextPos(t, s, 11, 1, 8, '४')
+	checkNextPos(t, s, 12, 1, 9, ' ')
+	checkNextPos(t, s, 13, 1, 10, ' ')
+	checkNextPos(t, s, 14, 2, 1, '\n')
+	checkNextPos(t, s, 15, 3, 1, '\n')
+	checkNextPos(t, s, 18, 3, 2, '本')
+	checkNextPos(t, s, 21, 3, 3, '語')
+	checkNextPos(t, s, 22, 4, 1, '\n')
+	// after EOF position doesn't change
+	for i := 10; i > 0; i-- {
+		checkScanPos(t, s, 22, 4, 1, EOF)
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+
+	// positions after calling Scan
+	s = new(Scanner).Init(bytes.NewBufferString("abc\n本語\n\nx"))
+	s.Mode = 0
+	s.Whitespace = 0
+	checkScanPos(t, s, 0, 1, 1, 'a')
+	s.Peek() // peek doesn't affect the position
+	checkScanPos(t, s, 1, 1, 2, 'b')
+	checkScanPos(t, s, 2, 1, 3, 'c')
+	checkScanPos(t, s, 3, 1, 4, '\n')
+	checkScanPos(t, s, 4, 2, 1, '本')
+	checkScanPos(t, s, 7, 2, 2, '語')
+	checkScanPos(t, s, 10, 2, 3, '\n')
+	checkScanPos(t, s, 11, 3, 1, '\n')
+	checkScanPos(t, s, 12, 4, 1, 'x')
+	// after EOF position doesn't change
+	for i := 10; i > 0; i-- {
+		checkScanPos(t, s, 13, 4, 2, EOF)
+	}
+	if s.ErrorCount != 0 {
+		t.Errorf("%d errors", s.ErrorCount)
+	}
+}
diff --git a/src/pkg/text/tabwriter/Makefile b/src/pkg/text/tabwriter/Makefile
new file mode 100644
index 0000000..ba1bf57
--- /dev/null
+++ b/src/pkg/text/tabwriter/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=text/tabwriter
+GOFILES=\
+	tabwriter.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/text/tabwriter/tabwriter.go b/src/pkg/text/tabwriter/tabwriter.go
new file mode 100644
index 0000000..201a685
--- /dev/null
+++ b/src/pkg/text/tabwriter/tabwriter.go
@@ -0,0 +1,560 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package tabwriter implements a write filter (tabwriter.Writer) that
+// translates tabbed columns in input into properly aligned text.
+//
+// The package is using the Elastic Tabstops algorithm described at
+// http://nickgravgaard.com/elastictabstops/index.html.
+//
+package tabwriter
+
+import (
+	"bytes"
+	"io"
+	"unicode/utf8"
+)
+
+// ----------------------------------------------------------------------------
+// Filter implementation
+
+// A cell represents a segment of text terminated by tabs or line breaks.
+// The text itself is stored in a separate buffer; cell only describes the
+// segment's size in bytes, its width in runes, and whether it's an htab
+// ('\t') terminated cell.
+//
+type cell struct {
+	size  int  // cell size in bytes
+	width int  // cell width in runes
+	htab  bool // true if the cell is terminated by an htab ('\t')
+}
+
+// A Writer is a filter that inserts padding around tab-delimited
+// columns in its input to align them in the output.
+//
+// The Writer treats incoming bytes as UTF-8 encoded text consisting
+// of cells terminated by (horizontal or vertical) tabs or line
+// breaks (newline or formfeed characters). Cells in adjacent lines
+// constitute a column. The Writer inserts padding as needed to
+// make all cells in a column have the same width, effectively
+// aligning the columns. It assumes that all characters have the
+// same width except for tabs for which a tabwidth must be specified.
+// Note that cells are tab-terminated, not tab-separated: trailing
+// non-tab text at the end of a line does not form a column cell.
+//
+// The Writer assumes that all Unicode code points have the same width;
+// this may not be true in some fonts.
+//
+// If DiscardEmptyColumns is set, empty columns that are terminated
+// entirely by vertical (or "soft") tabs are discarded. Columns
+// terminated by horizontal (or "hard") tabs are not affected by
+// this flag.
+//
+// If a Writer is configured to filter HTML, HTML tags and entities
+// are simply passed through. The widths of tags and entities are
+// assumed to be zero (tags) and one (entities) for formatting purposes.
+//
+// A segment of text may be escaped by bracketing it with Escape
+// characters. The tabwriter passes escaped text segments through
+// unchanged. In particular, it does not interpret any tabs or line
+// breaks within the segment. If the StripEscape flag is set, the
+// Escape characters are stripped from the output; otherwise they
+// are passed through as well. For the purpose of formatting, the
+// width of the escaped text is always computed excluding the Escape
+// characters.
+//
+// The formfeed character ('\f') acts like a newline but it also
+// terminates all columns in the current line (effectively calling
+// Flush). Cells in the next line start new columns. Unless found
+// inside an HTML tag or inside an escaped text segment, formfeed
+// characters appear as newlines in the output.
+//
+// The Writer must buffer input internally, because proper spacing
+// of one line may depend on the cells in future lines. Clients must
+// call Flush when done calling Write.
+//
+type Writer struct {
+	// configuration
+	output   io.Writer
+	minwidth int
+	tabwidth int
+	padding  int
+	padbytes [8]byte
+	flags    uint
+
+	// current state
+	buf     bytes.Buffer // collected text excluding tabs or line breaks
+	pos     int          // buffer position up to which cell.width of incomplete cell has been computed
+	cell    cell         // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections
+	endChar byte         // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0)
+	lines   [][]cell     // list of lines; each line is a list of cells
+	widths  []int        // list of column widths in runes - re-used during formatting
+}
+
+func (b *Writer) addLine() { b.lines = append(b.lines, []cell{}) }
+
+// Reset the current state.
+func (b *Writer) reset() {
+	b.buf.Reset()
+	b.pos = 0
+	b.cell = cell{}
+	b.endChar = 0
+	b.lines = b.lines[0:0]
+	b.widths = b.widths[0:0]
+	b.addLine()
+}
+
+// Internal representation (current state):
+//
+// - all text written is appended to buf; tabs and line breaks are stripped away
+// - at any given time there is a (possibly empty) incomplete cell at the end
+//   (the cell starts after a tab or line break)
+// - cell.size is the number of bytes belonging to the cell so far
+// - cell.width is text width in runes of that cell from the start of the cell to
+//   position pos; html tags and entities are excluded from this width if html
+//   filtering is enabled
+// - the sizes and widths of processed text are kept in the lines list
+//   which contains a list of cells for each line
+// - the widths list is a temporary list with current widths used during
+//   formatting; it is kept in Writer because it's re-used
+//
+//                    |<---------- size ---------->|
+//                    |                            |
+//                    |<- width ->|<- ignored ->|  |
+//                    |           |             |  |
+// [---processed---tab------------<tag>...</tag>...]
+// ^                  ^                         ^
+// |                  |                         |
+// buf                start of incomplete cell  pos
+
+// Formatting can be controlled with these flags.
+const (
+	// Ignore html tags and treat entities (starting with '&'
+	// and ending in ';') as single characters (width = 1).
+	FilterHTML uint = 1 << iota
+
+	// Strip Escape characters bracketing escaped text segments
+	// instead of passing them through unchanged with the text.
+	StripEscape
+
+	// Force right-alignment of cell content.
+	// Default is left-alignment.
+	AlignRight
+
+	// Handle empty columns as if they were not present in
+	// the input in the first place.
+	DiscardEmptyColumns
+
+	// Always use tabs for indentation columns (i.e., padding of
+	// leading empty cells on the left) independent of padchar.
+	TabIndent
+
+	// Print a vertical bar ('|') between columns (after formatting).
+	// Discarded columns appear as zero-width columns ("||").
+	Debug
+)
+
+// A Writer must be initialized with a call to Init. The first parameter (output)
+// specifies the filter output. The remaining parameters control the formatting:
+//
+//	minwidth	minimal cell width including any padding
+//	tabwidth	width of tab characters (equivalent number of spaces)
+//	padding		padding added to a cell before computing its width
+//	padchar		ASCII char used for padding
+//			if padchar == '\t', the Writer will assume that the
+//			width of a '\t' in the formatted output is tabwidth,
+//			and cells are left-aligned independent of align_left
+//			(for correct-looking results, tabwidth must correspond
+//			to the tab width in the viewer displaying the result)
+//	flags		formatting control
+//
+// To format in tab-separated columns with a tab stop of 8:
+//	b.Init(w, 8, 1, 8, '\t', 0);
+//
+// To format in space-separated columns with at least 4 spaces between columns:
+//	b.Init(w, 0, 4, 8, ' ', 0);
+//
+func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
+	if minwidth < 0 || tabwidth < 0 || padding < 0 {
+		panic("negative minwidth, tabwidth, or padding")
+	}
+	b.output = output
+	b.minwidth = minwidth
+	b.tabwidth = tabwidth
+	b.padding = padding
+	for i := range b.padbytes {
+		b.padbytes[i] = padchar
+	}
+	if padchar == '\t' {
+		// tab padding enforces left-alignment
+		flags &^= AlignRight
+	}
+	b.flags = flags
+
+	b.reset()
+
+	return b
+}
+
+// debugging support (keep code around)
+func (b *Writer) dump() {
+	pos := 0
+	for i, line := range b.lines {
+		print("(", i, ") ")
+		for _, c := range line {
+			print("[", string(b.buf.Bytes()[pos:pos+c.size]), "]")
+			pos += c.size
+		}
+		print("\n")
+	}
+	print("\n")
+}
+
+// local error wrapper so we can distinguish errors we want to return
+// as errors from genuine panics (which we don't want to return as errors)
+type osError struct {
+	err error
+}
+
+func (b *Writer) write0(buf []byte) {
+	n, err := b.output.Write(buf)
+	if n != len(buf) && err == nil {
+		err = io.ErrShortWrite
+	}
+	if err != nil {
+		panic(osError{err})
+	}
+}
+
+func (b *Writer) writeN(src []byte, n int) {
+	for n > len(src) {
+		b.write0(src)
+		n -= len(src)
+	}
+	b.write0(src[0:n])
+}
+
+var (
+	newline = []byte{'\n'}
+	tabs    = []byte("\t\t\t\t\t\t\t\t")
+)
+
+func (b *Writer) writePadding(textw, cellw int, useTabs bool) {
+	if b.padbytes[0] == '\t' || useTabs {
+		// padding is done with tabs
+		if b.tabwidth == 0 {
+			return // tabs have no width - can't do any padding
+		}
+		// make cellw the smallest multiple of b.tabwidth
+		cellw = (cellw + b.tabwidth - 1) / b.tabwidth * b.tabwidth
+		n := cellw - textw // amount of padding
+		if n < 0 {
+			panic("internal error")
+		}
+		b.writeN(tabs, (n+b.tabwidth-1)/b.tabwidth)
+		return
+	}
+
+	// padding is done with non-tab characters
+	b.writeN(b.padbytes[0:], cellw-textw)
+}
+
+var vbar = []byte{'|'}
+
+func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int) {
+	pos = pos0
+	for i := line0; i < line1; i++ {
+		line := b.lines[i]
+
+		// if TabIndent is set, use tabs to pad leading empty cells
+		useTabs := b.flags&TabIndent != 0
+
+		for j, c := range line {
+			if j > 0 && b.flags&Debug != 0 {
+				// indicate column break
+				b.write0(vbar)
+			}
+
+			if c.size == 0 {
+				// empty cell
+				if j < len(b.widths) {
+					b.writePadding(c.width, b.widths[j], useTabs)
+				}
+			} else {
+				// non-empty cell
+				useTabs = false
+				if b.flags&AlignRight == 0 { // align left
+					b.write0(b.buf.Bytes()[pos : pos+c.size])
+					pos += c.size
+					if j < len(b.widths) {
+						b.writePadding(c.width, b.widths[j], false)
+					}
+				} else { // align right
+					if j < len(b.widths) {
+						b.writePadding(c.width, b.widths[j], false)
+					}
+					b.write0(b.buf.Bytes()[pos : pos+c.size])
+					pos += c.size
+				}
+			}
+		}
+
+		if i+1 == len(b.lines) {
+			// last buffered line - we don't have a newline, so just write
+			// any outstanding buffered data
+			b.write0(b.buf.Bytes()[pos : pos+b.cell.size])
+			pos += b.cell.size
+		} else {
+			// not the last line - write newline
+			b.write0(newline)
+		}
+	}
+	return
+}
+
+// Format the text between line0 and line1 (excluding line1); pos
+// is the buffer position corresponding to the beginning of line0.
+// Returns the buffer position corresponding to the beginning of
+// line1 and an error, if any.
+//
+func (b *Writer) format(pos0 int, line0, line1 int) (pos int) {
+	pos = pos0
+	column := len(b.widths)
+	for this := line0; this < line1; this++ {
+		line := b.lines[this]
+
+		if column < len(line)-1 {
+			// cell exists in this column => this line
+			// has more cells than the previous line
+			// (the last cell per line is ignored because cells are
+			// tab-terminated; the last cell per line describes the
+			// text before the newline/formfeed and does not belong
+			// to a column)
+
+			// print unprinted lines until beginning of block
+			pos = b.writeLines(pos, line0, this)
+			line0 = this
+
+			// column block begin
+			width := b.minwidth // minimal column width
+			discardable := true // true if all cells in this column are empty and "soft"
+			for ; this < line1; this++ {
+				line = b.lines[this]
+				if column < len(line)-1 {
+					// cell exists in this column
+					c := line[column]
+					// update width
+					if w := c.width + b.padding; w > width {
+						width = w
+					}
+					// update discardable
+					if c.width > 0 || c.htab {
+						discardable = false
+					}
+				} else {
+					break
+				}
+			}
+			// column block end
+
+			// discard empty columns if necessary
+			if discardable && b.flags&DiscardEmptyColumns != 0 {
+				width = 0
+			}
+
+			// format and print all columns to the right of this column
+			// (we know the widths of this column and all columns to the left)
+			b.widths = append(b.widths, width) // push width
+			pos = b.format(pos, line0, this)
+			b.widths = b.widths[0 : len(b.widths)-1] // pop width
+			line0 = this
+		}
+	}
+
+	// print unprinted lines until end
+	return b.writeLines(pos, line0, line1)
+}
+
+// Append text to current cell.
+func (b *Writer) append(text []byte) {
+	b.buf.Write(text)
+	b.cell.size += len(text)
+}
+
+// Update the cell width.
+func (b *Writer) updateWidth() {
+	b.cell.width += utf8.RuneCount(b.buf.Bytes()[b.pos:b.buf.Len()])
+	b.pos = b.buf.Len()
+}
+
+// To escape a text segment, bracket it with Escape characters.
+// For instance, the tab in this string "Ignore this tab: \xff\t\xff"
+// does not terminate a cell and constitutes a single character of
+// width one for formatting purposes.
+//
+// The value 0xff was chosen because it cannot appear in a valid UTF-8 sequence.
+//
+const Escape = '\xff'
+
+// Start escaped mode.
+func (b *Writer) startEscape(ch byte) {
+	switch ch {
+	case Escape:
+		b.endChar = Escape
+	case '<':
+		b.endChar = '>'
+	case '&':
+		b.endChar = ';'
+	}
+}
+
+// Terminate escaped mode. If the escaped text was an HTML tag, its width
+// is assumed to be zero for formatting purposes; if it was an HTML entity,
+// its width is assumed to be one. In all other cases, the width is the
+// unicode width of the text.
+//
+func (b *Writer) endEscape() {
+	switch b.endChar {
+	case Escape:
+		b.updateWidth()
+		if b.flags&StripEscape == 0 {
+			b.cell.width -= 2 // don't count the Escape chars
+		}
+	case '>': // tag of zero width
+	case ';':
+		b.cell.width++ // entity, count as one rune
+	}
+	b.pos = b.buf.Len()
+	b.endChar = 0
+}
+
+// Terminate the current cell by adding it to the list of cells of the
+// current line. Returns the number of cells in that line.
+//
+func (b *Writer) terminateCell(htab bool) int {
+	b.cell.htab = htab
+	line := &b.lines[len(b.lines)-1]
+	*line = append(*line, b.cell)
+	b.cell = cell{}
+	return len(*line)
+}
+
+func handlePanic(err *error) {
+	if e := recover(); e != nil {
+		*err = e.(osError).err // re-panics if it's not a local osError
+	}
+}
+
+// Flush should be called after the last call to Write to ensure
+// that any data buffered in the Writer is written to output. Any
+// incomplete escape sequence at the end is simply considered
+// complete for formatting purposes.
+//
+func (b *Writer) Flush() (err error) {
+	defer b.reset() // even in the presence of errors
+	defer handlePanic(&err)
+
+	// add current cell if not empty
+	if b.cell.size > 0 {
+		if b.endChar != 0 {
+			// inside escape - terminate it even if incomplete
+			b.endEscape()
+		}
+		b.terminateCell(false)
+	}
+
+	// format contents of buffer
+	b.format(0, 0, len(b.lines))
+
+	return
+}
+
+var hbar = []byte("---\n")
+
+// Write writes buf to the writer b.
+// The only errors returned are ones encountered
+// while writing to the underlying output stream.
+//
+func (b *Writer) Write(buf []byte) (n int, err error) {
+	defer handlePanic(&err)
+
+	// split text into cells
+	n = 0
+	for i, ch := range buf {
+		if b.endChar == 0 {
+			// outside escape
+			switch ch {
+			case '\t', '\v', '\n', '\f':
+				// end of cell
+				b.append(buf[n:i])
+				b.updateWidth()
+				n = i + 1 // ch consumed
+				ncells := b.terminateCell(ch == '\t')
+				if ch == '\n' || ch == '\f' {
+					// terminate line
+					b.addLine()
+					if ch == '\f' || ncells == 1 {
+						// A '\f' always forces a flush. Otherwise, if the previous
+						// line has only one cell which does not have an impact on
+						// the formatting of the following lines (the last cell per
+						// line is ignored by format()), thus we can flush the
+						// Writer contents.
+						if err = b.Flush(); err != nil {
+							return
+						}
+						if ch == '\f' && b.flags&Debug != 0 {
+							// indicate section break
+							b.write0(hbar)
+						}
+					}
+				}
+
+			case Escape:
+				// start of escaped sequence
+				b.append(buf[n:i])
+				b.updateWidth()
+				n = i
+				if b.flags&StripEscape != 0 {
+					n++ // strip Escape
+				}
+				b.startEscape(Escape)
+
+			case '<', '&':
+				// possibly an html tag/entity
+				if b.flags&FilterHTML != 0 {
+					// begin of tag/entity
+					b.append(buf[n:i])
+					b.updateWidth()
+					n = i
+					b.startEscape(ch)
+				}
+			}
+
+		} else {
+			// inside escape
+			if ch == b.endChar {
+				// end of tag/entity
+				j := i + 1
+				if ch == Escape && b.flags&StripEscape != 0 {
+					j = i // strip Escape
+				}
+				b.append(buf[n:j])
+				n = i + 1 // ch consumed
+				b.endEscape()
+			}
+		}
+	}
+
+	// append leftover text
+	b.append(buf[n:])
+	n = len(buf)
+	return
+}
+
+// NewWriter allocates and initializes a new tabwriter.Writer.
+// The parameters are the same as for the the Init function.
+//
+func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
+	return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags)
+}
diff --git a/src/pkg/text/tabwriter/tabwriter_test.go b/src/pkg/text/tabwriter/tabwriter_test.go
new file mode 100644
index 0000000..1ffb330
--- /dev/null
+++ b/src/pkg/text/tabwriter/tabwriter_test.go
@@ -0,0 +1,614 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tabwriter
+
+import (
+	"io"
+	"testing"
+)
+
+type buffer struct {
+	a []byte
+}
+
+func (b *buffer) init(n int) { b.a = make([]byte, n)[0:0] }
+
+func (b *buffer) clear() { b.a = b.a[0:0] }
+
+func (b *buffer) Write(buf []byte) (written int, err error) {
+	n := len(b.a)
+	m := len(buf)
+	if n+m <= cap(b.a) {
+		b.a = b.a[0 : n+m]
+		for i := 0; i < m; i++ {
+			b.a[n+i] = buf[i]
+		}
+	} else {
+		panic("buffer.Write: buffer too small")
+	}
+	return len(buf), nil
+}
+
+func (b *buffer) String() string { return string(b.a) }
+
+func write(t *testing.T, testname string, w *Writer, src string) {
+	written, err := io.WriteString(w, src)
+	if err != nil {
+		t.Errorf("--- test: %s\n--- src:\n%q\n--- write error: %v\n", testname, src, err)
+	}
+	if written != len(src) {
+		t.Errorf("--- test: %s\n--- src:\n%q\n--- written = %d, len(src) = %d\n", testname, src, written, len(src))
+	}
+}
+
+func verify(t *testing.T, testname string, w *Writer, b *buffer, src, expected string) {
+	err := w.Flush()
+	if err != nil {
+		t.Errorf("--- test: %s\n--- src:\n%q\n--- flush error: %v\n", testname, src, err)
+	}
+
+	res := b.String()
+	if res != expected {
+		t.Errorf("--- test: %s\n--- src:\n%q\n--- found:\n%q\n--- expected:\n%q\n", testname, src, res, expected)
+	}
+}
+
+func check(t *testing.T, testname string, minwidth, tabwidth, padding int, padchar byte, flags uint, src, expected string) {
+	var b buffer
+	b.init(1000)
+
+	var w Writer
+	w.Init(&b, minwidth, tabwidth, padding, padchar, flags)
+
+	// write all at once
+	title := testname + " (written all at once)"
+	b.clear()
+	write(t, title, &w, src)
+	verify(t, title, &w, &b, src, expected)
+
+	// write byte-by-byte
+	title = testname + " (written byte-by-byte)"
+	b.clear()
+	for i := 0; i < len(src); i++ {
+		write(t, title, &w, src[i:i+1])
+	}
+	verify(t, title, &w, &b, src, expected)
+
+	// write using Fibonacci slice sizes
+	title = testname + " (written in fibonacci slices)"
+	b.clear()
+	for i, d := 0, 0; i < len(src); {
+		write(t, title, &w, src[i:i+d])
+		i, d = i+d, d+1
+		if i+d > len(src) {
+			d = len(src) - i
+		}
+	}
+	verify(t, title, &w, &b, src, expected)
+}
+
+var tests = []struct {
+	testname                    string
+	minwidth, tabwidth, padding int
+	padchar                     byte
+	flags                       uint
+	src, expected               string
+}{
+	{
+		"1a",
+		8, 0, 1, '.', 0,
+		"",
+		"",
+	},
+
+	{
+		"1a debug",
+		8, 0, 1, '.', Debug,
+		"",
+		"",
+	},
+
+	{
+		"1b esc stripped",
+		8, 0, 1, '.', StripEscape,
+		"\xff\xff",
+		"",
+	},
+
+	{
+		"1b esc",
+		8, 0, 1, '.', 0,
+		"\xff\xff",
+		"\xff\xff",
+	},
+
+	{
+		"1c esc stripped",
+		8, 0, 1, '.', StripEscape,
+		"\xff\t\xff",
+		"\t",
+	},
+
+	{
+		"1c esc",
+		8, 0, 1, '.', 0,
+		"\xff\t\xff",
+		"\xff\t\xff",
+	},
+
+	{
+		"1d esc stripped",
+		8, 0, 1, '.', StripEscape,
+		"\xff\"foo\t\n\tbar\"\xff",
+		"\"foo\t\n\tbar\"",
+	},
+
+	{
+		"1d esc",
+		8, 0, 1, '.', 0,
+		"\xff\"foo\t\n\tbar\"\xff",
+		"\xff\"foo\t\n\tbar\"\xff",
+	},
+
+	{
+		"1e esc stripped",
+		8, 0, 1, '.', StripEscape,
+		"abc\xff\tdef", // unterminated escape
+		"abc\tdef",
+	},
+
+	{
+		"1e esc",
+		8, 0, 1, '.', 0,
+		"abc\xff\tdef", // unterminated escape
+		"abc\xff\tdef",
+	},
+
+	{
+		"2",
+		8, 0, 1, '.', 0,
+		"\n\n\n",
+		"\n\n\n",
+	},
+
+	{
+		"3",
+		8, 0, 1, '.', 0,
+		"a\nb\nc",
+		"a\nb\nc",
+	},
+
+	{
+		"4a",
+		8, 0, 1, '.', 0,
+		"\t", // '\t' terminates an empty cell on last line - nothing to print
+		"",
+	},
+
+	{
+		"4b",
+		8, 0, 1, '.', AlignRight,
+		"\t", // '\t' terminates an empty cell on last line - nothing to print
+		"",
+	},
+
+	{
+		"5",
+		8, 0, 1, '.', 0,
+		"*\t*",
+		"*.......*",
+	},
+
+	{
+		"5b",
+		8, 0, 1, '.', 0,
+		"*\t*\n",
+		"*.......*\n",
+	},
+
+	{
+		"5c",
+		8, 0, 1, '.', 0,
+		"*\t*\t",
+		"*.......*",
+	},
+
+	{
+		"5c debug",
+		8, 0, 1, '.', Debug,
+		"*\t*\t",
+		"*.......|*",
+	},
+
+	{
+		"5d",
+		8, 0, 1, '.', AlignRight,
+		"*\t*\t",
+		".......**",
+	},
+
+	{
+		"6",
+		8, 0, 1, '.', 0,
+		"\t\n",
+		"........\n",
+	},
+
+	{
+		"7a",
+		8, 0, 1, '.', 0,
+		"a) foo",
+		"a) foo",
+	},
+
+	{
+		"7b",
+		8, 0, 1, ' ', 0,
+		"b) foo\tbar",
+		"b) foo  bar",
+	},
+
+	{
+		"7c",
+		8, 0, 1, '.', 0,
+		"c) foo\tbar\t",
+		"c) foo..bar",
+	},
+
+	{
+		"7d",
+		8, 0, 1, '.', 0,
+		"d) foo\tbar\n",
+		"d) foo..bar\n",
+	},
+
+	{
+		"7e",
+		8, 0, 1, '.', 0,
+		"e) foo\tbar\t\n",
+		"e) foo..bar.....\n",
+	},
+
+	{
+		"7f",
+		8, 0, 1, '.', FilterHTML,
+		"f) f<o\t<b>bar</b>\t\n",
+		"f) f<o..<b>bar</b>.....\n",
+	},
+
+	{
+		"7g",
+		8, 0, 1, '.', FilterHTML,
+		"g) f<o\t<b>bar</b>\t non-terminated entity &amp",
+		"g) f<o..<b>bar</b>..... non-terminated entity &amp",
+	},
+
+	{
+		"7g debug",
+		8, 0, 1, '.', FilterHTML | Debug,
+		"g) f<o\t<b>bar</b>\t non-terminated entity &amp",
+		"g) f<o..|<b>bar</b>.....| non-terminated entity &amp",
+	},
+
+	{
+		"8",
+		8, 0, 1, '*', 0,
+		"Hello, world!\n",
+		"Hello, world!\n",
+	},
+
+	{
+		"9a",
+		1, 0, 0, '.', 0,
+		"1\t2\t3\t4\n" +
+			"11\t222\t3333\t44444\n",
+
+		"1.2..3...4\n" +
+			"11222333344444\n",
+	},
+
+	{
+		"9b",
+		1, 0, 0, '.', FilterHTML,
+		"1\t2<!---\f--->\t3\t4\n" + // \f inside HTML is ignored
+			"11\t222\t3333\t44444\n",
+
+		"1.2<!---\f--->..3...4\n" +
+			"11222333344444\n",
+	},
+
+	{
+		"9c",
+		1, 0, 0, '.', 0,
+		"1\t2\t3\t4\f" + // \f causes a newline and flush
+			"11\t222\t3333\t44444\n",
+
+		"1234\n" +
+			"11222333344444\n",
+	},
+
+	{
+		"9c debug",
+		1, 0, 0, '.', Debug,
+		"1\t2\t3\t4\f" + // \f causes a newline and flush
+			"11\t222\t3333\t44444\n",
+
+		"1|2|3|4\n" +
+			"---\n" +
+			"11|222|3333|44444\n",
+	},
+
+	{
+		"10a",
+		5, 0, 0, '.', 0,
+		"1\t2\t3\t4\n",
+		"1....2....3....4\n",
+	},
+
+	{
+		"10b",
+		5, 0, 0, '.', 0,
+		"1\t2\t3\t4\t\n",
+		"1....2....3....4....\n",
+	},
+
+	{
+		"11",
+		8, 0, 1, '.', 0,
+		"本\tb\tc\n" +
+			"aa\t\u672c\u672c\u672c\tcccc\tddddd\n" +
+			"aaa\tbbbb\n",
+
+		"本.......b.......c\n" +
+			"aa......本本本.....cccc....ddddd\n" +
+			"aaa.....bbbb\n",
+	},
+
+	{
+		"12a",
+		8, 0, 1, ' ', AlignRight,
+		"a\tè\tc\t\n" +
+			"aa\tèèè\tcccc\tddddd\t\n" +
+			"aaa\tèèèè\t\n",
+
+		"       a       è       c\n" +
+			"      aa     èèè    cccc   ddddd\n" +
+			"     aaa    èèèè\n",
+	},
+
+	{
+		"12b",
+		2, 0, 0, ' ', 0,
+		"a\tb\tc\n" +
+			"aa\tbbb\tcccc\n" +
+			"aaa\tbbbb\n",
+
+		"a  b  c\n" +
+			"aa bbbcccc\n" +
+			"aaabbbb\n",
+	},
+
+	{
+		"12c",
+		8, 0, 1, '_', 0,
+		"a\tb\tc\n" +
+			"aa\tbbb\tcccc\n" +
+			"aaa\tbbbb\n",
+
+		"a_______b_______c\n" +
+			"aa______bbb_____cccc\n" +
+			"aaa_____bbbb\n",
+	},
+
+	{
+		"13a",
+		4, 0, 1, '-', 0,
+		"4444\t日本語\t22\t1\t333\n" +
+			"999999999\t22\n" +
+			"7\t22\n" +
+			"\t\t\t88888888\n" +
+			"\n" +
+			"666666\t666666\t666666\t4444\n" +
+			"1\t1\t999999999\t0000000000\n",
+
+		"4444------日本語-22--1---333\n" +
+			"999999999-22\n" +
+			"7---------22\n" +
+			"------------------88888888\n" +
+			"\n" +
+			"666666-666666-666666----4444\n" +
+			"1------1------999999999-0000000000\n",
+	},
+
+	{
+		"13b",
+		4, 0, 3, '.', 0,
+		"4444\t333\t22\t1\t333\n" +
+			"999999999\t22\n" +
+			"7\t22\n" +
+			"\t\t\t88888888\n" +
+			"\n" +
+			"666666\t666666\t666666\t4444\n" +
+			"1\t1\t999999999\t0000000000\n",
+
+		"4444........333...22...1...333\n" +
+			"999999999...22\n" +
+			"7...........22\n" +
+			"....................88888888\n" +
+			"\n" +
+			"666666...666666...666666......4444\n" +
+			"1........1........999999999...0000000000\n",
+	},
+
+	{
+		"13c",
+		8, 8, 1, '\t', FilterHTML,
+		"4444\t333\t22\t1\t333\n" +
+			"999999999\t22\n" +
+			"7\t22\n" +
+			"\t\t\t88888888\n" +
+			"\n" +
+			"666666\t666666\t666666\t4444\n" +
+			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
+
+		"4444\t\t333\t22\t1\t333\n" +
+			"999999999\t22\n" +
+			"7\t\t22\n" +
+			"\t\t\t\t88888888\n" +
+			"\n" +
+			"666666\t666666\t666666\t\t4444\n" +
+			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
+	},
+
+	{
+		"14",
+		1, 0, 2, ' ', AlignRight,
+		".0\t.3\t2.4\t-5.1\t\n" +
+			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
+			"5.1\t12.0\t2.4\t-7.0\t\n" +
+			".0\t0.0\t332.0\t8908.0\t\n" +
+			".0\t-.3\t456.4\t22.1\t\n" +
+			".0\t1.2\t44.4\t-13.3\t\t",
+
+		"    .0          .3    2.4    -5.1\n" +
+			"  23.0  12345678.9    2.4  -989.4\n" +
+			"   5.1        12.0    2.4    -7.0\n" +
+			"    .0         0.0  332.0  8908.0\n" +
+			"    .0         -.3  456.4    22.1\n" +
+			"    .0         1.2   44.4   -13.3",
+	},
+
+	{
+		"14 debug",
+		1, 0, 2, ' ', AlignRight | Debug,
+		".0\t.3\t2.4\t-5.1\t\n" +
+			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
+			"5.1\t12.0\t2.4\t-7.0\t\n" +
+			".0\t0.0\t332.0\t8908.0\t\n" +
+			".0\t-.3\t456.4\t22.1\t\n" +
+			".0\t1.2\t44.4\t-13.3\t\t",
+
+		"    .0|          .3|    2.4|    -5.1|\n" +
+			"  23.0|  12345678.9|    2.4|  -989.4|\n" +
+			"   5.1|        12.0|    2.4|    -7.0|\n" +
+			"    .0|         0.0|  332.0|  8908.0|\n" +
+			"    .0|         -.3|  456.4|    22.1|\n" +
+			"    .0|         1.2|   44.4|   -13.3|",
+	},
+
+	{
+		"15a",
+		4, 0, 0, '.', 0,
+		"a\t\tb",
+		"a.......b",
+	},
+
+	{
+		"15b",
+		4, 0, 0, '.', DiscardEmptyColumns,
+		"a\t\tb", // htabs - do not discard column
+		"a.......b",
+	},
+
+	{
+		"15c",
+		4, 0, 0, '.', DiscardEmptyColumns,
+		"a\v\vb",
+		"a...b",
+	},
+
+	{
+		"15d",
+		4, 0, 0, '.', AlignRight | DiscardEmptyColumns,
+		"a\v\vb",
+		"...ab",
+	},
+
+	{
+		"16a",
+		100, 100, 0, '\t', 0,
+		"a\tb\t\td\n" +
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+
+		"a\tb\t\td\n" +
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+	},
+
+	{
+		"16b",
+		100, 100, 0, '\t', DiscardEmptyColumns,
+		"a\vb\v\vd\n" +
+			"a\vb\v\vd\ve\n" +
+			"a\n" +
+			"a\vb\vc\vd\n" +
+			"a\vb\vc\vd\ve\n",
+
+		"a\tb\td\n" +
+			"a\tb\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+	},
+
+	{
+		"16b debug",
+		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
+		"a\vb\v\vd\n" +
+			"a\vb\v\vd\ve\n" +
+			"a\n" +
+			"a\vb\vc\vd\n" +
+			"a\vb\vc\vd\ve\n",
+
+		"a\t|b\t||d\n" +
+			"a\t|b\t||d\t|e\n" +
+			"a\n" +
+			"a\t|b\t|c\t|d\n" +
+			"a\t|b\t|c\t|d\t|e\n",
+	},
+
+	{
+		"16c",
+		100, 100, 0, '\t', DiscardEmptyColumns,
+		"a\tb\t\td\n" + // hard tabs - do not discard column
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+
+		"a\tb\t\td\n" +
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+	},
+
+	{
+		"16c debug",
+		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
+		"a\tb\t\td\n" + // hard tabs - do not discard column
+			"a\tb\t\td\te\n" +
+			"a\n" +
+			"a\tb\tc\td\n" +
+			"a\tb\tc\td\te\n",
+
+		"a\t|b\t|\t|d\n" +
+			"a\t|b\t|\t|d\t|e\n" +
+			"a\n" +
+			"a\t|b\t|c\t|d\n" +
+			"a\t|b\t|c\t|d\t|e\n",
+	},
+}
+
+func Test(t *testing.T) {
+	for _, e := range tests {
+		check(t, e.testname, e.minwidth, e.tabwidth, e.padding, e.padchar, e.flags, e.src, e.expected)
+	}
+}
diff --git a/src/pkg/text/template/Makefile b/src/pkg/text/template/Makefile
new file mode 100644
index 0000000..0e83114
--- /dev/null
+++ b/src/pkg/text/template/Makefile
@@ -0,0 +1,15 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=text/template
+GOFILES=\
+	doc.go\
+	exec.go\
+	funcs.go\
+	helper.go\
+	template.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/text/template/doc.go b/src/pkg/text/template/doc.go
new file mode 100644
index 0000000..3be1ec4
--- /dev/null
+++ b/src/pkg/text/template/doc.go
@@ -0,0 +1,327 @@
+// Copyright 2011 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 template implements data-driven templates for generating textual output
+such as HTML.
+
+Templates are executed by applying them to a data structure. Annotations in the
+template refer to elements of the data structure (typically a field of a struct
+or a key in a map) to control execution and derive values to be displayed.
+Execution of the template walks the structure and sets the cursor, represented
+by a period '.' and called "dot", to the value at the current location in the
+structure as execution proceeds.
+
+The input text for a template is UTF-8-encoded text in any format.
+"Actions"--data evaluations or control structures--are delimited by
+"{{" and "}}"; all text outside actions is copied to the output unchanged.
+Actions may not span newlines, although comments can.
+
+Once constructed, a template may be executed safely in parallel.
+
+Actions
+
+Here is the list of actions. "Arguments" and "pipelines" are evaluations of
+data, defined in detail below.
+
+*/
+//	{{/* a comment */}}
+//		A comment; discarded. May contain newlines.
+//		Comments do not nest.
+/*
+
+	{{pipeline}}
+		The default textual representation of the value of the pipeline
+		is copied to the output.
+
+	{{if pipeline}} T1 {{end}}
+		If the value of the pipeline is empty, no output is generated;
+		otherwise, T1 is executed.  The empty values are false, 0, any
+		nil pointer or interface value, and any array, slice, map, or
+		string of length zero.
+		Dot is unaffected.
+
+	{{if pipeline}} T1 {{else}} T0 {{end}}
+		If the value of the pipeline is empty, T0 is executed;
+		otherwise, T1 is executed.  Dot is unaffected.
+
+	{{range pipeline}} T1 {{end}}
+		The value of the pipeline must be an array, slice, or map. If
+		the value of the pipeline has length zero, nothing is output;
+		otherwise, dot is set to the successive elements of the array,
+		slice, or map and T1 is executed. If the value is a map and the
+		keys are of basic type with a defined order ("comparable"), the
+		elements will be visited in sorted key order.
+
+	{{range pipeline}} T1 {{else}} T0 {{end}}
+		The value of the pipeline must be an array, slice, or map. If
+		the value of the pipeline has length zero, dot is unaffected and
+		T0 is executed; otherwise, dot is set to the successive elements
+		of the array, slice, or map and T1 is executed.
+
+	{{template "name"}}
+		The template with the specified name is executed with nil data.
+
+	{{template "name" pipeline}}
+		The template with the specified name is executed with dot set
+		to the value of the pipeline.
+
+	{{with pipeline}} T1 {{end}}
+		If the value of the pipeline is empty, no output is generated;
+		otherwise, dot is set to the value of the pipeline and T1 is
+		executed.
+
+	{{with pipeline}} T1 {{else}} T0 {{end}}
+		If the value of the pipeline is empty, dot is unaffected and T0
+		is executed; otherwise, dot is set to the value of the pipeline
+		and T1 is executed.
+
+Arguments
+
+An argument is a simple value, denoted by one of the following.
+
+	- A boolean, string, character, integer, floating-point, imaginary
+	  or complex constant in Go syntax. These behave like Go's untyped
+	  constants, although raw strings may not span newlines.
+	- The character '.' (period):
+		.
+	  The result is the value of dot.
+	- A variable name, which is a (possibly empty) alphanumeric string
+	  preceded by a dollar sign, such as
+		$piOver2
+	  or
+		$
+	  The result is the value of the variable.
+	  Variables are described below.
+	- The name of a field of the data, which must be a struct, preceded
+	  by a period, such as
+		.Field
+	  The result is the value of the field. Field invocations may be
+	  chained:
+	    .Field1.Field2
+	  Fields can also be evaluated on variables, including chaining:
+	    $x.Field1.Field2
+	- The name of a key of the data, which must be a map, preceded
+	  by a period, such as
+		.Key
+	  The result is the map element value indexed by the key.
+	  Key invocations may be chained and combined with fields to any
+	  depth:
+	    .Field1.Key1.Field2.Key2
+	  Although the key must be an alphanumeric identifier, unlike with
+	  field names they do not need to start with an upper case letter.
+	  Keys can also be evaluated on variables, including chaining:
+	    $x.key1.key2
+	- The name of a niladic method of the data, preceded by a period,
+	  such as
+		.Method
+	  The result is the value of invoking the method with dot as the
+	  receiver, dot.Method(). Such a method must have one return value (of
+	  any type) or two return values, the second of which is an error.
+	  If it has two and the returned error is non-nil, execution terminates
+	  and an error is returned to the caller as the value of Execute.
+	  Method invocations may be chained and combined with fields and keys
+	  to any depth:
+	    .Field1.Key1.Method1.Field2.Key2.Method2
+	  Methods can also be evaluated on variables, including chaining:
+	    $x.Method1.Field
+	- The name of a niladic function, such as
+		fun
+	  The result is the value of invoking the function, fun(). The return
+	  types and values behave as in methods. Functions and function
+	  names are described below.
+
+Arguments may evaluate to any type; if they are pointers the implementation
+automatically indirects to the base type when required.
+
+A pipeline is a possibly chained sequence of "commands". A command is a simple
+value (argument) or a function or method call, possibly with multiple arguments:
+
+	Argument
+		The result is the value of evaluating the argument.
+	.Method [Argument...]
+		The method can be alone or the last element of a chain but,
+		unlike methods in the middle of a chain, it can take arguments.
+		The result is the value of calling the method with the
+		arguments:
+			dot.Method(Argument1, etc.)
+	functionName [Argument...]
+		The result is the value of calling the function associated
+		with the name:
+			function(Argument1, etc.)
+		Functions and function names are described below.
+
+Pipelines
+
+A pipeline may be "chained" by separating a sequence of commands with pipeline
+characters '|'. In a chained pipeline, the result of the each command is
+passed as the last argument of the following command. The output of the final
+command in the pipeline is the value of the pipeline.
+
+The output of a command will be either one value or two values, the second of
+which has type error. If that second value is present and evaluates to
+non-nil, execution terminates and the error is returned to the caller of
+Execute.
+
+Variables
+
+A pipeline inside an action may initialize a variable to capture the result.
+The initialization has syntax
+
+	$variable := pipeline
+
+where $variable is the name of the variable. An action that declares a
+variable produces no output.
+
+If a "range" action initializes a variable, the variable is set to the
+successive elements of the iteration.  Also, a "range" may declare two
+variables, separated by a comma:
+
+	$index, $element := pipeline
+
+in which case $index and $element are set to the successive values of the
+array/slice index or map key and element, respectively.  Note that if there is
+only one variable, it is assigned the element; this is opposite to the
+convention in Go range clauses.
+
+A variable's scope extends to the "end" action of the control structure ("if",
+"with", or "range") in which it is declared, or to the end of the template if
+there is no such control structure.  A template invocation does not inherit
+variables from the point of its invocation.
+
+When execution begins, $ is set to the data argument passed to Execute, that is,
+to the starting value of dot.
+
+Examples
+
+Here are some example one-line templates demonstrating pipelines and variables.
+All produce the quoted word "output":
+
+	{{"\"output\""}}
+		A string constant.
+	{{`"output"`}}
+		A raw string constant.
+	{{printf "%q" "output"}}
+		A function call.
+	{{"output" | printf "%q"}}
+		A function call whose final argument comes from the previous
+		command.
+	{{"put" | printf "%s%s" "out" | printf "%q"}}
+		A more elaborate call.
+	{{"output" | printf "%s" | printf "%q"}}
+		A longer chain.
+	{{with "output"}}{{printf "%q" .}}{{end}}
+		A with action using dot.
+	{{with $x := "output" | printf "%q"}}{{$x}}{{end}}
+		A with action that creates and uses a variable.
+	{{with $x := "output"}}{{printf "%q" $x}}{{end}}
+		A with action that uses the variable in another action.
+	{{with $x := "output"}}{{$x | printf "%q"}}{{end}}
+		The same, but pipelined.
+
+Functions
+
+During execution functions are found in two function maps: first in the
+template, then in the global function map. By default, no functions are defined
+in the template but the Funcs methods can be used to add them.
+
+Predefined global functions are named as follows.
+
+	and
+		Returns the boolean AND of its arguments by returning the
+		first empty argument or the last argument, that is,
+		"and x y" behaves as "if x then y else x". All the
+		arguments are evaluated.
+	html
+		Returns the escaped HTML equivalent of the textual
+		representation of its arguments.
+	index
+		Returns the result of indexing its first argument by the
+		following arguments. Thus "index x 1 2 3" is, in Go syntax,
+		x[1][2][3]. Each indexed item must be a map, slice, or array.
+	js
+		Returns the escaped JavaScript equivalent of the textual
+		representation of its arguments.
+	len
+		Returns the integer length of its argument.
+	not
+		Returns the boolean negation of its single argument.
+	or
+		Returns the boolean OR of its arguments by returning the
+		first non-empty argument or the last argument, that is,
+		"or x y" behaves as "if x then x else y". All the
+		arguments are evaluated.
+	print
+		An alias for fmt.Sprint
+	printf
+		An alias for fmt.Sprintf
+	println
+		An alias for fmt.Sprintln
+	urlquery
+		Returns the escaped value of the textual representation of
+		its arguments in a form suitable for embedding in a URL query.
+
+The boolean functions take any zero value to be false and a non-zero value to
+be true.
+
+Associated templates
+
+Each template is named by a string specified when it is created. Also, each
+template is associated with zero or more other templates that it may invoke by
+name; such associations are transitive and form a name space of templates.
+
+A template may use a template invocation to instantiate another associated
+template; see the explanation of the "template" action above. The name must be
+that of a template associated with the template that contains the invocation.
+
+Nested template definitions
+
+When parsing a template, another template may be defined and associated with the
+template being parsed. Template definitions must appear at the top level of the
+template, much like global variables in a Go program.
+
+The syntax of such definitions is to surround each template declaration with a
+"define" and "end" action.
+
+The define action names the template being created by providing a string
+constant. Here is a simple example:
+
+	`{{define "T1"}}ONE{{end}}
+	{{define "T2"}}TWO{{end}}
+	{{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
+	{{template "T3"}}`
+
+This defines two templates, T1 and T2, and a third T3 that invokes the other two
+when it is executed. Finally it invokes T3. If executed this template will
+produce the text
+
+	ONE TWO
+
+By construction, a template may reside in only one association. If it's
+necessary to have a template addressable from multiple associations, the
+template definition must be parsed multiple times to create distinct *Template
+values.
+
+Parse may be called multiple times to assemble the various associated templates;
+see the ParseFiles and ParseGlob functions and methods for simple ways to parse
+related templates stored in files.
+
+A template may be executed directly or through ExecuteTemplate, which executes
+an associated template identified by name. To invoke our example above, we
+might write,
+
+	err := tmpl.Execute(os.Stdout, "no data needed")
+	if err != nil {
+		log.Fatalf("execution failed: %s", err)
+	}
+
+or to invoke a particular template explicitly by name,
+
+	err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
+	if err != nil {
+		log.Fatalf("execution failed: %s", err)
+	}
+
+*/
+package template
diff --git a/src/pkg/text/template/example_test.go b/src/pkg/text/template/example_test.go
new file mode 100644
index 0000000..b7701ea
--- /dev/null
+++ b/src/pkg/text/template/example_test.go
@@ -0,0 +1,69 @@
+// Copyright 2011 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 template_test
+
+import (
+	"log"
+	"os"
+	"text/template"
+)
+
+// Dear Aunt Mildred,
+// 
+// It was a pleasure to see you at the wedding.
+// Thank you for the lovely bone china tea set.
+// 
+// Best wishes,
+// Josie
+// 
+// Dear Uncle John,
+// 
+// It is a shame you couldn't make it to the wedding.
+// Thank you for the lovely moleskin pants.
+// 
+// Best wishes,
+// Josie
+// 
+// Dear Cousin Rodney,
+// 
+// It is a shame you couldn't make it to the wedding.
+// 
+// Best wishes,
+// Josie
+func ExampleTemplate() {
+	// Define a template.
+	const letter = `
+Dear {{.Name}},
+{{if .Attended}}
+It was a pleasure to see you at the wedding.{{else}}
+It is a shame you couldn't make it to the wedding.{{end}}
+{{with .Gift}}Thank you for the lovely {{.}}.
+{{end}}
+Best wishes,
+Josie
+`
+
+	// Prepare some data to insert into the template.
+	type Recipient struct {
+		Name, Gift string
+		Attended   bool
+	}
+	var recipients = []Recipient{
+		{"Aunt Mildred", "bone china tea set", true},
+		{"Uncle John", "moleskin pants", false},
+		{"Cousin Rodney", "", false},
+	}
+
+	// Create a new template and parse the letter into it.
+	t := template.Must(template.New("letter").Parse(letter))
+
+	// Execute the template for each recipient.
+	for _, r := range recipients {
+		err := t.Execute(os.Stdout, r)
+		if err != nil {
+			log.Println("executing template:", err)
+		}
+	}
+}
diff --git a/src/pkg/text/template/exec.go b/src/pkg/text/template/exec.go
new file mode 100644
index 0000000..973189a
--- /dev/null
+++ b/src/pkg/text/template/exec.go
@@ -0,0 +1,720 @@
+// Copyright 2011 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 template
+
+import (
+	"fmt"
+	"io"
+	"reflect"
+	"runtime"
+	"sort"
+	"strings"
+	"text/template/parse"
+)
+
+// state represents the state of an execution. It's not part of the
+// template so that multiple executions of the same template
+// can execute in parallel.
+type state struct {
+	tmpl *Template
+	wr   io.Writer
+	line int        // line number for errors
+	vars []variable // push-down stack of variable values.
+}
+
+// variable holds the dynamic value of a variable such as $, $x etc.
+type variable struct {
+	name  string
+	value reflect.Value
+}
+
+// push pushes a new variable on the stack.
+func (s *state) push(name string, value reflect.Value) {
+	s.vars = append(s.vars, variable{name, value})
+}
+
+// mark returns the length of the variable stack.
+func (s *state) mark() int {
+	return len(s.vars)
+}
+
+// pop pops the variable stack up to the mark.
+func (s *state) pop(mark int) {
+	s.vars = s.vars[0:mark]
+}
+
+// setVar overwrites the top-nth variable on the stack. Used by range iterations.
+func (s *state) setVar(n int, value reflect.Value) {
+	s.vars[len(s.vars)-n].value = value
+}
+
+// varValue returns the value of the named variable.
+func (s *state) varValue(name string) reflect.Value {
+	for i := s.mark() - 1; i >= 0; i-- {
+		if s.vars[i].name == name {
+			return s.vars[i].value
+		}
+	}
+	s.errorf("undefined variable: %s", name)
+	return zero
+}
+
+var zero reflect.Value
+
+// errorf formats the error and terminates processing.
+func (s *state) errorf(format string, args ...interface{}) {
+	format = fmt.Sprintf("template: %s:%d: %s", s.tmpl.Name(), s.line, format)
+	panic(fmt.Errorf(format, args...))
+}
+
+// error terminates processing.
+func (s *state) error(err error) {
+	s.errorf("%s", err)
+}
+
+// errRecover is the handler that turns panics into returns from the top
+// level of Parse.
+func errRecover(errp *error) {
+	e := recover()
+	if e != nil {
+		switch err := e.(type) {
+		case runtime.Error:
+			panic(e)
+		case error:
+			*errp = err
+		default:
+			panic(e)
+		}
+	}
+}
+
+// ExecuteTemplate applies the template associated with t that has the given name
+// to the specified data object and writes the output to wr.
+func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
+	tmpl := t.tmpl[name]
+	if tmpl == nil {
+		return fmt.Errorf("template: no template %q associated with template %q", name, t.name)
+	}
+	return tmpl.Execute(wr, data)
+}
+
+// Execute applies a parsed template to the specified data object,
+// and writes the output to wr.
+func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
+	defer errRecover(&err)
+	value := reflect.ValueOf(data)
+	state := &state{
+		tmpl: t,
+		wr:   wr,
+		line: 1,
+		vars: []variable{{"$", value}},
+	}
+	if t.Tree == nil || t.Root == nil {
+		state.errorf("%q is an incomplete or empty template", t.name)
+	}
+	state.walk(value, t.Root)
+	return
+}
+
+// Walk functions step through the major pieces of the template structure,
+// generating output as they go.
+func (s *state) walk(dot reflect.Value, n parse.Node) {
+	switch n := n.(type) {
+	case *parse.ActionNode:
+		s.line = n.Line
+		// Do not pop variables so they persist until next end.
+		// Also, if the action declares variables, don't print the result.
+		val := s.evalPipeline(dot, n.Pipe)
+		if len(n.Pipe.Decl) == 0 {
+			s.printValue(n, val)
+		}
+	case *parse.IfNode:
+		s.line = n.Line
+		s.walkIfOrWith(parse.NodeIf, dot, n.Pipe, n.List, n.ElseList)
+	case *parse.ListNode:
+		for _, node := range n.Nodes {
+			s.walk(dot, node)
+		}
+	case *parse.RangeNode:
+		s.line = n.Line
+		s.walkRange(dot, n)
+	case *parse.TemplateNode:
+		s.line = n.Line
+		s.walkTemplate(dot, n)
+	case *parse.TextNode:
+		if _, err := s.wr.Write(n.Text); err != nil {
+			s.error(err)
+		}
+	case *parse.WithNode:
+		s.line = n.Line
+		s.walkIfOrWith(parse.NodeWith, dot, n.Pipe, n.List, n.ElseList)
+	default:
+		s.errorf("unknown node: %s", n)
+	}
+}
+
+// walkIfOrWith walks an 'if' or 'with' node. The two control structures
+// are identical in behavior except that 'with' sets dot.
+func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
+	defer s.pop(s.mark())
+	val := s.evalPipeline(dot, pipe)
+	truth, ok := isTrue(val)
+	if !ok {
+		s.errorf("if/with can't use %v", val)
+	}
+	if truth {
+		if typ == parse.NodeWith {
+			s.walk(val, list)
+		} else {
+			s.walk(dot, list)
+		}
+	} else if elseList != nil {
+		s.walk(dot, elseList)
+	}
+}
+
+// isTrue returns whether the value is 'true', in the sense of not the zero of its type,
+// and whether the value has a meaningful truth value.
+func isTrue(val reflect.Value) (truth, ok bool) {
+	if !val.IsValid() {
+		// Something like var x interface{}, never set. It's a form of nil.
+		return false, true
+	}
+	switch val.Kind() {
+	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+		truth = val.Len() > 0
+	case reflect.Bool:
+		truth = val.Bool()
+	case reflect.Complex64, reflect.Complex128:
+		truth = val.Complex() != 0
+	case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
+		truth = !val.IsNil()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		truth = val.Int() != 0
+	case reflect.Float32, reflect.Float64:
+		truth = val.Float() != 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		truth = val.Uint() != 0
+	case reflect.Struct:
+		truth = true // Struct values are always true.
+	default:
+		return
+	}
+	return truth, true
+}
+
+func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
+	defer s.pop(s.mark())
+	val, _ := indirect(s.evalPipeline(dot, r.Pipe))
+	// mark top of stack before any variables in the body are pushed.
+	mark := s.mark()
+	oneIteration := func(index, elem reflect.Value) {
+		// Set top var (lexically the second if there are two) to the element.
+		if len(r.Pipe.Decl) > 0 {
+			s.setVar(1, elem)
+		}
+		// Set next var (lexically the first if there are two) to the index.
+		if len(r.Pipe.Decl) > 1 {
+			s.setVar(2, index)
+		}
+		s.walk(elem, r.List)
+		s.pop(mark)
+	}
+	switch val.Kind() {
+	case reflect.Array, reflect.Slice:
+		if val.Len() == 0 {
+			break
+		}
+		for i := 0; i < val.Len(); i++ {
+			oneIteration(reflect.ValueOf(i), val.Index(i))
+		}
+		return
+	case reflect.Map:
+		if val.Len() == 0 {
+			break
+		}
+		for _, key := range sortKeys(val.MapKeys()) {
+			oneIteration(key, val.MapIndex(key))
+		}
+		return
+	case reflect.Chan:
+		if val.IsNil() {
+			break
+		}
+		i := 0
+		for ; ; i++ {
+			elem, ok := val.Recv()
+			if !ok {
+				break
+			}
+			oneIteration(reflect.ValueOf(i), elem)
+		}
+		if i == 0 {
+			break
+		}
+		return
+	case reflect.Invalid:
+		break // An invalid value is likely a nil map, etc. and acts like an empty map.
+	default:
+		s.errorf("range can't iterate over %v", val)
+	}
+	if r.ElseList != nil {
+		s.walk(dot, r.ElseList)
+	}
+}
+
+func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
+	tmpl := s.tmpl.tmpl[t.Name]
+	if tmpl == nil {
+		s.errorf("template %q not defined", t.Name)
+	}
+	// Variables declared by the pipeline persist.
+	dot = s.evalPipeline(dot, t.Pipe)
+	newState := *s
+	newState.tmpl = tmpl
+	// No dynamic scoping: template invocations inherit no variables.
+	newState.vars = []variable{{"$", dot}}
+	newState.walk(dot, tmpl.Root)
+}
+
+// Eval functions evaluate pipelines, commands, and their elements and extract
+// values from the data structure by examining fields, calling methods, and so on.
+// The printing of those values happens only through walk functions.
+
+// evalPipeline returns the value acquired by evaluating a pipeline. If the
+// pipeline has a variable declaration, the variable will be pushed on the
+// stack. Callers should therefore pop the stack after they are finished
+// executing commands depending on the pipeline value.
+func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) {
+	if pipe == nil {
+		return
+	}
+	for _, cmd := range pipe.Cmds {
+		value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
+		// If the object has type interface{}, dig down one level to the thing inside.
+		if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
+			value = reflect.ValueOf(value.Interface()) // lovely!
+		}
+	}
+	for _, variable := range pipe.Decl {
+		s.push(variable.Ident[0], value)
+	}
+	return value
+}
+
+func (s *state) notAFunction(args []parse.Node, final reflect.Value) {
+	if len(args) > 1 || final.IsValid() {
+		s.errorf("can't give argument to non-function %s", args[0])
+	}
+}
+
+func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value {
+	firstWord := cmd.Args[0]
+	switch n := firstWord.(type) {
+	case *parse.FieldNode:
+		return s.evalFieldNode(dot, n, cmd.Args, final)
+	case *parse.IdentifierNode:
+		// Must be a function.
+		return s.evalFunction(dot, n.Ident, cmd.Args, final)
+	case *parse.VariableNode:
+		return s.evalVariableNode(dot, n, cmd.Args, final)
+	}
+	s.notAFunction(cmd.Args, final)
+	switch word := firstWord.(type) {
+	case *parse.BoolNode:
+		return reflect.ValueOf(word.True)
+	case *parse.DotNode:
+		return dot
+	case *parse.NumberNode:
+		return s.idealConstant(word)
+	case *parse.StringNode:
+		return reflect.ValueOf(word.Text)
+	}
+	s.errorf("can't evaluate command %q", firstWord)
+	panic("not reached")
+}
+
+// idealConstant is called to return the value of a number in a context where
+// we don't know the type. In that case, the syntax of the number tells us
+// its type, and we use Go rules to resolve.  Note there is no such thing as
+// a uint ideal constant in this situation - the value must be of int type.
+func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
+	// These are ideal constants but we don't know the type
+	// and we have no context.  (If it was a method argument,
+	// we'd know what we need.) The syntax guides us to some extent.
+	switch {
+	case constant.IsComplex:
+		return reflect.ValueOf(constant.Complex128) // incontrovertible.
+	case constant.IsFloat && strings.IndexAny(constant.Text, ".eE") >= 0:
+		return reflect.ValueOf(constant.Float64)
+	case constant.IsInt:
+		n := int(constant.Int64)
+		if int64(n) != constant.Int64 {
+			s.errorf("%s overflows int", constant.Text)
+		}
+		return reflect.ValueOf(n)
+	case constant.IsUint:
+		s.errorf("%s overflows int", constant.Text)
+	}
+	return zero
+}
+
+func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
+	return s.evalFieldChain(dot, dot, field.Ident, args, final)
+}
+
+func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
+	// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
+	value := s.varValue(v.Ident[0])
+	if len(v.Ident) == 1 {
+		return value
+	}
+	return s.evalFieldChain(dot, value, v.Ident[1:], args, final)
+}
+
+// evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
+// dot is the environment in which to evaluate arguments, while
+// receiver is the value being walked along the chain.
+func (s *state) evalFieldChain(dot, receiver reflect.Value, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
+	n := len(ident)
+	for i := 0; i < n-1; i++ {
+		receiver = s.evalField(dot, ident[i], nil, zero, receiver)
+	}
+	// Now if it's a method, it gets the arguments.
+	return s.evalField(dot, ident[n-1], args, final, receiver)
+}
+
+func (s *state) evalFunction(dot reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
+	function, ok := findFunction(name, s.tmpl)
+	if !ok {
+		s.errorf("%q is not a defined function", name)
+	}
+	return s.evalCall(dot, function, name, args, final)
+}
+
+// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
+// The 'final' argument represents the return value from the preceding
+// value of the pipeline, if any.
+func (s *state) evalField(dot reflect.Value, fieldName string, args []parse.Node, final, receiver reflect.Value) reflect.Value {
+	if !receiver.IsValid() {
+		return zero
+	}
+	typ := receiver.Type()
+	receiver, _ = indirect(receiver)
+	// Unless it's an interface, need to get to a value of type *T to guarantee
+	// we see all methods of T and *T.
+	ptr := receiver
+	if ptr.Kind() != reflect.Interface && ptr.CanAddr() {
+		ptr = ptr.Addr()
+	}
+	if method := ptr.MethodByName(fieldName); method.IsValid() {
+		return s.evalCall(dot, method, fieldName, args, final)
+	}
+	hasArgs := len(args) > 1 || final.IsValid()
+	// It's not a method; is it a field of a struct?
+	receiver, isNil := indirect(receiver)
+	if receiver.Kind() == reflect.Struct {
+		tField, ok := receiver.Type().FieldByName(fieldName)
+		if ok {
+			field := receiver.FieldByIndex(tField.Index)
+			if hasArgs {
+				s.errorf("%s is not a method but has arguments", fieldName)
+			}
+			if tField.PkgPath == "" { // field is exported
+				return field
+			}
+		}
+	}
+	// If it's a map, attempt to use the field name as a key.
+	if receiver.Kind() == reflect.Map {
+		nameVal := reflect.ValueOf(fieldName)
+		if nameVal.Type().AssignableTo(receiver.Type().Key()) {
+			if hasArgs {
+				s.errorf("%s is not a method but has arguments", fieldName)
+			}
+			return receiver.MapIndex(nameVal)
+		}
+	}
+	if isNil {
+		s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
+	}
+	s.errorf("can't evaluate field %s in type %s", fieldName, typ)
+	panic("not reached")
+}
+
+var (
+	errorType       = reflect.TypeOf((*error)(nil)).Elem()
+	fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+)
+
+// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
+// it looks just like a function call.  The arg list, if non-nil, includes (in the manner of the shell), arg[0]
+// as the function itself.
+func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node, final reflect.Value) reflect.Value {
+	if args != nil {
+		args = args[1:] // Zeroth arg is function name/node; not passed to function.
+	}
+	typ := fun.Type()
+	numIn := len(args)
+	if final.IsValid() {
+		numIn++
+	}
+	numFixed := len(args)
+	if typ.IsVariadic() {
+		numFixed = typ.NumIn() - 1 // last arg is the variadic one.
+		if numIn < numFixed {
+			s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args))
+		}
+	} else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() {
+		s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
+	}
+	if !goodFunc(typ) {
+		s.errorf("can't handle multiple results from method/function %q", name)
+	}
+	// Build the arg list.
+	argv := make([]reflect.Value, numIn)
+	// Args must be evaluated. Fixed args first.
+	i := 0
+	for ; i < numFixed; i++ {
+		argv[i] = s.evalArg(dot, typ.In(i), args[i])
+	}
+	// Now the ... args.
+	if typ.IsVariadic() {
+		argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice.
+		for ; i < len(args); i++ {
+			argv[i] = s.evalArg(dot, argType, args[i])
+		}
+	}
+	// Add final value if necessary.
+	if final.IsValid() {
+		argv[i] = final
+	}
+	result := fun.Call(argv)
+	// If we have an error that is not nil, stop execution and return that error to the caller.
+	if len(result) == 2 && !result[1].IsNil() {
+		s.errorf("error calling %s: %s", name, result[1].Interface().(error))
+	}
+	return result[0]
+}
+
+// validateType guarantees that the value is valid and assignable to the type.
+func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
+	if !value.IsValid() {
+		switch typ.Kind() {
+		case reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Map, reflect.Slice, reflect.Func:
+			// An untyped nil interface{}. Accept as a proper nil value.
+			value = reflect.Zero(typ)
+		default:
+			s.errorf("invalid value; expected %s", typ)
+		}
+	}
+	if !value.Type().AssignableTo(typ) {
+		// Does one dereference or indirection work? We could do more, as we
+		// do with method receivers, but that gets messy and method receivers
+		// are much more constrained, so it makes more sense there than here.
+		// Besides, one is almost always all you need.
+		switch {
+		case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
+			value = value.Elem()
+		case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
+			value = value.Addr()
+		default:
+			s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
+		}
+	}
+	return value
+}
+
+func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
+	switch arg := n.(type) {
+	case *parse.DotNode:
+		return s.validateType(dot, typ)
+	case *parse.FieldNode:
+		return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
+	case *parse.VariableNode:
+		return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
+	}
+	switch typ.Kind() {
+	case reflect.Bool:
+		return s.evalBool(typ, n)
+	case reflect.Complex64, reflect.Complex128:
+		return s.evalComplex(typ, n)
+	case reflect.Float32, reflect.Float64:
+		return s.evalFloat(typ, n)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return s.evalInteger(typ, n)
+	case reflect.Interface:
+		if typ.NumMethod() == 0 {
+			return s.evalEmptyInterface(dot, n)
+		}
+	case reflect.String:
+		return s.evalString(typ, n)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return s.evalUnsignedInteger(typ, n)
+	}
+	s.errorf("can't handle %s for arg of type %s", n, typ)
+	panic("not reached")
+}
+
+func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
+	if n, ok := n.(*parse.BoolNode); ok {
+		value := reflect.New(typ).Elem()
+		value.SetBool(n.True)
+		return value
+	}
+	s.errorf("expected bool; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
+	if n, ok := n.(*parse.StringNode); ok {
+		value := reflect.New(typ).Elem()
+		value.SetString(n.Text)
+		return value
+	}
+	s.errorf("expected string; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
+	if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
+		value := reflect.New(typ).Elem()
+		value.SetInt(n.Int64)
+		return value
+	}
+	s.errorf("expected integer; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
+	if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
+		value := reflect.New(typ).Elem()
+		value.SetUint(n.Uint64)
+		return value
+	}
+	s.errorf("expected unsigned integer; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
+	if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
+		value := reflect.New(typ).Elem()
+		value.SetFloat(n.Float64)
+		return value
+	}
+	s.errorf("expected float; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
+	if n, ok := n.(*parse.NumberNode); ok && n.IsComplex {
+		value := reflect.New(typ).Elem()
+		value.SetComplex(n.Complex128)
+		return value
+	}
+	s.errorf("expected complex; found %s", n)
+	panic("not reached")
+}
+
+func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
+	switch n := n.(type) {
+	case *parse.BoolNode:
+		return reflect.ValueOf(n.True)
+	case *parse.DotNode:
+		return dot
+	case *parse.FieldNode:
+		return s.evalFieldNode(dot, n, nil, zero)
+	case *parse.IdentifierNode:
+		return s.evalFunction(dot, n.Ident, nil, zero)
+	case *parse.NumberNode:
+		return s.idealConstant(n)
+	case *parse.StringNode:
+		return reflect.ValueOf(n.Text)
+	case *parse.VariableNode:
+		return s.evalVariableNode(dot, n, nil, zero)
+	}
+	s.errorf("can't handle assignment of %s to empty interface argument", n)
+	panic("not reached")
+}
+
+// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
+// We indirect through pointers and empty interfaces (only) because
+// non-empty interfaces have methods we might need.
+func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
+	for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
+		if v.IsNil() {
+			return v, true
+		}
+		if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
+			break
+		}
+	}
+	return v, false
+}
+
+// printValue writes the textual representation of the value to the output of
+// the template.
+func (s *state) printValue(n parse.Node, v reflect.Value) {
+	if v.Kind() == reflect.Ptr {
+		v, _ = indirect(v) // fmt.Fprint handles nil.
+	}
+	if !v.IsValid() {
+		fmt.Fprint(s.wr, "<no value>")
+		return
+	}
+
+	if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
+		if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) {
+			v = v.Addr()
+		} else {
+			switch v.Kind() {
+			case reflect.Chan, reflect.Func:
+				s.errorf("can't print %s of type %s", n, v.Type())
+			}
+		}
+	}
+	fmt.Fprint(s.wr, v.Interface())
+}
+
+// Types to help sort the keys in a map for reproducible output.
+
+type rvs []reflect.Value
+
+func (x rvs) Len() int      { return len(x) }
+func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+type rvInts struct{ rvs }
+
+func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() }
+
+type rvUints struct{ rvs }
+
+func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() }
+
+type rvFloats struct{ rvs }
+
+func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() }
+
+type rvStrings struct{ rvs }
+
+func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() }
+
+// sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys.
+func sortKeys(v []reflect.Value) []reflect.Value {
+	if len(v) <= 1 {
+		return v
+	}
+	switch v[0].Kind() {
+	case reflect.Float32, reflect.Float64:
+		sort.Sort(rvFloats{v})
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		sort.Sort(rvInts{v})
+	case reflect.String:
+		sort.Sort(rvStrings{v})
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		sort.Sort(rvUints{v})
+	}
+	return v
+}
diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go
new file mode 100644
index 0000000..2070cef
--- /dev/null
+++ b/src/pkg/text/template/exec_test.go
@@ -0,0 +1,692 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+var debug = flag.Bool("debug", false, "show the errors produced by the tests")
+
+// T has lots of interesting pieces to use to test execution.
+type T struct {
+	// Basics
+	True        bool
+	I           int
+	U16         uint16
+	X           string
+	FloatZero   float64
+	ComplexZero float64
+	// Nested structs.
+	U *U
+	// Struct with String method.
+	V0     V
+	V1, V2 *V
+	// Struct with Error method.
+	W0     W
+	W1, W2 *W
+	// Slices
+	SI      []int
+	SIEmpty []int
+	SB      []bool
+	// Maps
+	MSI      map[string]int
+	MSIone   map[string]int // one element, for deterministic output
+	MSIEmpty map[string]int
+	MXI      map[interface{}]int
+	MII      map[int]int
+	SMSI     []map[string]int
+	// Empty interfaces; used to see if we can dig inside one.
+	Empty0 interface{} // nil
+	Empty1 interface{}
+	Empty2 interface{}
+	Empty3 interface{}
+	Empty4 interface{}
+	// Non-empty interface.
+	NonEmptyInterface I
+	// Stringer.
+	Str fmt.Stringer
+	Err error
+	// Pointers
+	PI  *int
+	PSI *[]int
+	NIL *int
+	// Template to test evaluation of templates.
+	Tmpl *Template
+}
+
+type U struct {
+	V string
+}
+
+type V struct {
+	j int
+}
+
+func (v *V) String() string {
+	if v == nil {
+		return "nilV"
+	}
+	return fmt.Sprintf("<%d>", v.j)
+}
+
+type W struct {
+	k int
+}
+
+func (w *W) Error() string {
+	if w == nil {
+		return "nilW"
+	}
+	return fmt.Sprintf("[%d]", w.k)
+}
+
+var tVal = &T{
+	True:   true,
+	I:      17,
+	U16:    16,
+	X:      "x",
+	U:      &U{"v"},
+	V0:     V{6666},
+	V1:     &V{7777}, // leave V2 as nil
+	W0:     W{888},
+	W1:     &W{999}, // leave W2 as nil
+	SI:     []int{3, 4, 5},
+	SB:     []bool{true, false},
+	MSI:    map[string]int{"one": 1, "two": 2, "three": 3},
+	MSIone: map[string]int{"one": 1},
+	MXI:    map[interface{}]int{"one": 1},
+	MII:    map[int]int{1: 1},
+	SMSI: []map[string]int{
+		{"one": 1, "two": 2},
+		{"eleven": 11, "twelve": 12},
+	},
+	Empty1:            3,
+	Empty2:            "empty2",
+	Empty3:            []int{7, 8},
+	Empty4:            &U{"UinEmpty"},
+	NonEmptyInterface: new(T),
+	Str:               bytes.NewBuffer([]byte("foozle")),
+	Err:               errors.New("erroozle"),
+	PI:                newInt(23),
+	PSI:               newIntSlice(21, 22, 23),
+	Tmpl:              Must(New("x").Parse("test template")), // "x" is the value of .X
+}
+
+// A non-empty interface.
+type I interface {
+	Method0() string
+}
+
+var iVal I = tVal
+
+// Helpers for creation.
+func newInt(n int) *int {
+	p := new(int)
+	*p = n
+	return p
+}
+
+func newIntSlice(n ...int) *[]int {
+	p := new([]int)
+	*p = make([]int, len(n))
+	copy(*p, n)
+	return p
+}
+
+// Simple methods with and without arguments.
+func (t *T) Method0() string {
+	return "M0"
+}
+
+func (t *T) Method1(a int) int {
+	return a
+}
+
+func (t *T) Method2(a uint16, b string) string {
+	return fmt.Sprintf("Method2: %d %s", a, b)
+}
+
+func (t *T) Method3(v interface{}) string {
+	return fmt.Sprintf("Method3: %v", v)
+}
+
+func (t *T) MAdd(a int, b []int) []int {
+	v := make([]int, len(b))
+	for i, x := range b {
+		v[i] = x + a
+	}
+	return v
+}
+
+// EPERM returns a value and an error according to its argument.
+func (t *T) EPERM(error bool) (bool, error) {
+	if error {
+		return true, os.EPERM
+	}
+	return false, nil
+}
+
+// A few methods to test chaining.
+func (t *T) GetU() *U {
+	return t.U
+}
+
+func (u *U) TrueFalse(b bool) string {
+	if b {
+		return "true"
+	}
+	return ""
+}
+
+func typeOf(arg interface{}) string {
+	return fmt.Sprintf("%T", arg)
+}
+
+type execTest struct {
+	name   string
+	input  string
+	output string
+	data   interface{}
+	ok     bool
+}
+
+// bigInt and bigUint are hex string representing numbers either side
+// of the max int boundary.
+// We do it this way so the test doesn't depend on ints being 32 bits.
+var (
+	bigInt  = fmt.Sprintf("0x%x", int(1<<uint(reflect.TypeOf(0).Bits()-1)-1))
+	bigUint = fmt.Sprintf("0x%x", uint(1<<uint(reflect.TypeOf(0).Bits()-1)))
+)
+
+var execTests = []execTest{
+	// Trivial cases.
+	{"empty", "", "", nil, true},
+	{"text", "some text", "some text", nil, true},
+
+	// Ideal constants.
+	{"ideal int", "{{typeOf 3}}", "int", 0, true},
+	{"ideal float", "{{typeOf 1.0}}", "float64", 0, true},
+	{"ideal exp float", "{{typeOf 1e1}}", "float64", 0, true},
+	{"ideal complex", "{{typeOf 1i}}", "complex128", 0, true},
+	{"ideal int", "{{typeOf " + bigInt + "}}", "int", 0, true},
+	{"ideal too big", "{{typeOf " + bigUint + "}}", "", 0, false},
+
+	// Fields of structs.
+	{".X", "-{{.X}}-", "-x-", tVal, true},
+	{".U.V", "-{{.U.V}}-", "-v-", tVal, true},
+
+	// Fields on maps.
+	{"map .one", "{{.MSI.one}}", "1", tVal, true},
+	{"map .two", "{{.MSI.two}}", "2", tVal, true},
+	{"map .NO", "{{.MSI.NO}}", "<no value>", tVal, true},
+	{"map .one interface", "{{.MXI.one}}", "1", tVal, true},
+	{"map .WRONG args", "{{.MSI.one 1}}", "", tVal, false},
+	{"map .WRONG type", "{{.MII.one}}", "", tVal, false},
+
+	// Dots of all kinds to test basic evaluation.
+	{"dot int", "<{{.}}>", "<13>", 13, true},
+	{"dot uint", "<{{.}}>", "<14>", uint(14), true},
+	{"dot float", "<{{.}}>", "<15.1>", 15.1, true},
+	{"dot bool", "<{{.}}>", "<true>", true, true},
+	{"dot complex", "<{{.}}>", "<(16.2-17i)>", 16.2 - 17i, true},
+	{"dot string", "<{{.}}>", "<hello>", "hello", true},
+	{"dot slice", "<{{.}}>", "<[-1 -2 -3]>", []int{-1, -2, -3}, true},
+	{"dot map", "<{{.}}>", "<map[two:22]>", map[string]int{"two": 22}, true},
+	{"dot struct", "<{{.}}>", "<{7 seven}>", struct {
+		a int
+		b string
+	}{7, "seven"}, true},
+
+	// Variables.
+	{"$ int", "{{$}}", "123", 123, true},
+	{"$.I", "{{$.I}}", "17", tVal, true},
+	{"$.U.V", "{{$.U.V}}", "v", tVal, true},
+	{"declare in action", "{{$x := $.U.V}}{{$x}}", "v", tVal, true},
+
+	// Type with String method.
+	{"V{6666}.String()", "-{{.V0}}-", "-<6666>-", tVal, true},
+	{"&V{7777}.String()", "-{{.V1}}-", "-<7777>-", tVal, true},
+	{"(*V)(nil).String()", "-{{.V2}}-", "-nilV-", tVal, true},
+
+	// Type with Error method.
+	{"W{888}.Error()", "-{{.W0}}-", "-[888]-", tVal, true},
+	{"&W{999}.Error()", "-{{.W1}}-", "-[999]-", tVal, true},
+	{"(*W)(nil).Error()", "-{{.W2}}-", "-nilW-", tVal, true},
+
+	// Pointers.
+	{"*int", "{{.PI}}", "23", tVal, true},
+	{"*[]int", "{{.PSI}}", "[21 22 23]", tVal, true},
+	{"*[]int[1]", "{{index .PSI 1}}", "22", tVal, true},
+	{"NIL", "{{.NIL}}", "<nil>", tVal, true},
+
+	// Empty interfaces holding values.
+	{"empty nil", "{{.Empty0}}", "<no value>", tVal, true},
+	{"empty with int", "{{.Empty1}}", "3", tVal, true},
+	{"empty with string", "{{.Empty2}}", "empty2", tVal, true},
+	{"empty with slice", "{{.Empty3}}", "[7 8]", tVal, true},
+	{"empty with struct", "{{.Empty4}}", "{UinEmpty}", tVal, true},
+	{"empty with struct, field", "{{.Empty4.V}}", "UinEmpty", tVal, true},
+
+	// Method calls.
+	{".Method0", "-{{.Method0}}-", "-M0-", tVal, true},
+	{".Method1(1234)", "-{{.Method1 1234}}-", "-1234-", tVal, true},
+	{".Method1(.I)", "-{{.Method1 .I}}-", "-17-", tVal, true},
+	{".Method2(3, .X)", "-{{.Method2 3 .X}}-", "-Method2: 3 x-", tVal, true},
+	{".Method2(.U16, `str`)", "-{{.Method2 .U16 `str`}}-", "-Method2: 16 str-", tVal, true},
+	{".Method2(.U16, $x)", "{{if $x := .X}}-{{.Method2 .U16 $x}}{{end}}-", "-Method2: 16 x-", tVal, true},
+	{".Method3(nil)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true},
+	{"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true},
+	{"method on chained var",
+		"{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
+		"true", tVal, true},
+	{"chained method",
+		"{{range .MSIone}}{{if $.GetU.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
+		"true", tVal, true},
+	{"chained method on variable",
+		"{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}",
+		"true", tVal, true},
+
+	// Pipelines.
+	{"pipeline", "-{{.Method0 | .Method2 .U16}}-", "-Method2: 16 M0-", tVal, true},
+
+	// If.
+	{"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true},
+	{"if false", "{{if false}}TRUE{{else}}FALSE{{end}}", "FALSE", tVal, true},
+	{"if 1", "{{if 1}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
+	{"if 0", "{{if 0}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"if 1.5", "{{if 1.5}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
+	{"if 0.0", "{{if .FloatZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"if 1.5i", "{{if 1.5i}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
+	{"if 0.0i", "{{if .ComplexZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"if emptystring", "{{if ``}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"if string", "{{if `notempty`}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
+	{"if emptyslice", "{{if .SIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"if slice", "{{if .SI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
+	{"if emptymap", "{{if .MSIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"if map", "{{if .MSI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
+	{"if map unset", "{{if .MXI.none}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"if map not unset", "{{if not .MXI.none}}ZERO{{else}}NON-ZERO{{end}}", "ZERO", tVal, true},
+	{"if $x with $y int", "{{if $x := true}}{{with $y := .I}}{{$x}},{{$y}}{{end}}{{end}}", "true,17", tVal, true},
+	{"if $x with $x int", "{{if $x := true}}{{with $x := .I}}{{$x}},{{end}}{{$x}}{{end}}", "17,true", tVal, true},
+
+	// Print etc.
+	{"print", `{{print "hello, print"}}`, "hello, print", tVal, true},
+	{"print", `{{print 1 2 3}}`, "1 2 3", tVal, true},
+	{"println", `{{println 1 2 3}}`, "1 2 3\n", tVal, true},
+	{"printf int", `{{printf "%04x" 127}}`, "007f", tVal, true},
+	{"printf float", `{{printf "%g" 3.5}}`, "3.5", tVal, true},
+	{"printf complex", `{{printf "%g" 1+7i}}`, "(1+7i)", tVal, true},
+	{"printf string", `{{printf "%s" "hello"}}`, "hello", tVal, true},
+	{"printf function", `{{printf "%#q" zeroArgs}}`, "`zeroArgs`", tVal, true},
+	{"printf field", `{{printf "%s" .U.V}}`, "v", tVal, true},
+	{"printf method", `{{printf "%s" .Method0}}`, "M0", tVal, true},
+	{"printf dot", `{{with .I}}{{printf "%d" .}}{{end}}`, "17", tVal, true},
+	{"printf var", `{{with $x := .I}}{{printf "%d" $x}}{{end}}`, "17", tVal, true},
+	{"printf lots", `{{printf "%d %s %g %s" 127 "hello" 7-3i .Method0}}`, "127 hello (7-3i) M0", tVal, true},
+
+	// HTML.
+	{"html", `{{html "<script>alert(\"XSS\");</script>"}}`,
+		"<script>alert("XSS");</script>", nil, true},
+	{"html pipeline", `{{printf "<script>alert(\"XSS\");</script>" | html}}`,
+		"<script>alert("XSS");</script>", nil, true},
+
+	// JavaScript.
+	{"js", `{{js .}}`, `It\'d be nice.`, `It'd be nice.`, true},
+
+	// URL query.
+	{"urlquery", `{{"http://www.example.org/"|urlquery}}`, "http%3A%2F%2Fwww.example.org%2F", nil, true},
+
+	// Booleans
+	{"not", "{{not true}} {{not false}}", "false true", nil, true},
+	{"and", "{{and false 0}} {{and 1 0}} {{and 0 true}} {{and 1 1}}", "false 0 0 1", nil, true},
+	{"or", "{{or 0 0}} {{or 1 0}} {{or 0 true}} {{or 1 1}}", "0 1 true 1", nil, true},
+	{"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true},
+	{"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true},
+
+	// Indexing.
+	{"slice[0]", "{{index .SI 0}}", "3", tVal, true},
+	{"slice[1]", "{{index .SI 1}}", "4", tVal, true},
+	{"slice[HUGE]", "{{index .SI 10}}", "", tVal, false},
+	{"slice[WRONG]", "{{index .SI `hello`}}", "", tVal, false},
+	{"map[one]", "{{index .MSI `one`}}", "1", tVal, true},
+	{"map[two]", "{{index .MSI `two`}}", "2", tVal, true},
+	{"map[NO]", "{{index .MSI `XXX`}}", "", tVal, true},
+	{"map[WRONG]", "{{index .MSI 10}}", "", tVal, false},
+	{"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true},
+
+	// Len.
+	{"slice", "{{len .SI}}", "3", tVal, true},
+	{"map", "{{len .MSI }}", "3", tVal, true},
+	{"len of int", "{{len 3}}", "", tVal, false},
+	{"len of nothing", "{{len .Empty0}}", "", tVal, false},
+
+	// With.
+	{"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true},
+	{"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true},
+	{"with 1", "{{with 1}}{{.}}{{else}}ZERO{{end}}", "1", tVal, true},
+	{"with 0", "{{with 0}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"with 1.5", "{{with 1.5}}{{.}}{{else}}ZERO{{end}}", "1.5", tVal, true},
+	{"with 0.0", "{{with .FloatZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"with 1.5i", "{{with 1.5i}}{{.}}{{else}}ZERO{{end}}", "(0+1.5i)", tVal, true},
+	{"with 0.0i", "{{with .ComplexZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true},
+	{"with emptystring", "{{with ``}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"with string", "{{with `notempty`}}{{.}}{{else}}EMPTY{{end}}", "notempty", tVal, true},
+	{"with emptyslice", "{{with .SIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"with slice", "{{with .SI}}{{.}}{{else}}EMPTY{{end}}", "[3 4 5]", tVal, true},
+	{"with emptymap", "{{with .MSIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"with map", "{{with .MSIone}}{{.}}{{else}}EMPTY{{end}}", "map[one:1]", tVal, true},
+	{"with empty interface, struct field", "{{with .Empty4}}{{.V}}{{end}}", "UinEmpty", tVal, true},
+	{"with $x int", "{{with $x := .I}}{{$x}}{{end}}", "17", tVal, true},
+	{"with $x struct.U.V", "{{with $x := $}}{{$x.U.V}}{{end}}", "v", tVal, true},
+	{"with variable and action", "{{with $x := $}}{{$y := $.U.V}}{{$y}}{{end}}", "v", tVal, true},
+
+	// Range.
+	{"range []int", "{{range .SI}}-{{.}}-{{end}}", "-3--4--5-", tVal, true},
+	{"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true},
+	{"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
+	{"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true},
+	{"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true},
+	{"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true},
+	{"range empty map no else", "{{range .MSIEmpty}}-{{.}}-{{end}}", "", tVal, true},
+	{"range map else", "{{range .MSI}}-{{.}}-{{else}}EMPTY{{end}}", "-1--3--2-", tVal, true},
+	{"range empty map else", "{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
+	{"range empty interface", "{{range .Empty3}}-{{.}}-{{else}}EMPTY{{end}}", "-7--8-", tVal, true},
+	{"range empty nil", "{{range .Empty0}}-{{.}}-{{end}}", "", tVal, true},
+	{"range $x SI", "{{range $x := .SI}}<{{$x}}>{{end}}", "<3><4><5>", tVal, true},
+	{"range $x $y SI", "{{range $x, $y := .SI}}<{{$x}}={{$y}}>{{end}}", "<0=3><1=4><2=5>", tVal, true},
+	{"range $x MSIone", "{{range $x := .MSIone}}<{{$x}}>{{end}}", "<1>", tVal, true},
+	{"range $x $y MSIone", "{{range $x, $y := .MSIone}}<{{$x}}={{$y}}>{{end}}", "<one=1>", tVal, true},
+	{"range $x PSI", "{{range $x := .PSI}}<{{$x}}>{{end}}", "<21><22><23>", tVal, true},
+	{"declare in range", "{{range $x := .PSI}}<{{$foo:=$x}}{{$x}}>{{end}}", "<21><22><23>", tVal, true},
+	{"range count", `{{range $i, $x := count 5}}[{{$i}}]{{$x}}{{end}}`, "[0]a[1]b[2]c[3]d[4]e", tVal, true},
+	{"range nil count", `{{range $i, $x := count 0}}{{else}}empty{{end}}`, "empty", tVal, true},
+
+	// Cute examples.
+	{"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true},
+	{"or as if false", `{{or .SIEmpty "slice is empty"}}`, "slice is empty", tVal, true},
+
+	// Error handling.
+	{"error method, error", "{{.EPERM true}}", "", tVal, false},
+	{"error method, no error", "{{.EPERM false}}", "false", tVal, true},
+
+	// Fixed bugs.
+	// Must separate dot and receiver; otherwise args are evaluated with dot set to variable.
+	{"bug0", "{{range .MSIone}}{{if $.Method1 .}}X{{end}}{{end}}", "X", tVal, true},
+	// Do not loop endlessly in indirect for non-empty interfaces.
+	// The bug appears with *interface only; looped forever.
+	{"bug1", "{{.Method0}}", "M0", &iVal, true},
+	// Was taking address of interface field, so method set was empty.
+	{"bug2", "{{$.NonEmptyInterface.Method0}}", "M0", tVal, true},
+	// Struct values were not legal in with - mere oversight.
+	{"bug3", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true},
+	// Nil interface values in if.
+	{"bug4", "{{if .Empty0}}non-nil{{else}}nil{{end}}", "nil", tVal, true},
+	// Stringer.
+	{"bug5", "{{.Str}}", "foozle", tVal, true},
+	{"bug5a", "{{.Err}}", "erroozle", tVal, true},
+	// Args need to be indirected and dereferenced sometimes.
+	{"bug6a", "{{vfunc .V0 .V1}}", "vfunc", tVal, true},
+	{"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true},
+	{"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true},
+	{"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true},
+}
+
+func zeroArgs() string {
+	return "zeroArgs"
+}
+
+func oneArg(a string) string {
+	return "oneArg=" + a
+}
+
+// count returns a channel that will deliver n sequential 1-letter strings starting at "a"
+func count(n int) chan string {
+	if n == 0 {
+		return nil
+	}
+	c := make(chan string)
+	go func() {
+		for i := 0; i < n; i++ {
+			c <- "abcdefghijklmnop"[i : i+1]
+		}
+		close(c)
+	}()
+	return c
+}
+
+// vfunc takes a *V and a V
+func vfunc(V, *V) string {
+	return "vfunc"
+}
+
+func testExecute(execTests []execTest, template *Template, t *testing.T) {
+	b := new(bytes.Buffer)
+	funcs := FuncMap{
+		"count":    count,
+		"oneArg":   oneArg,
+		"typeOf":   typeOf,
+		"vfunc":    vfunc,
+		"zeroArgs": zeroArgs,
+	}
+	for _, test := range execTests {
+		var tmpl *Template
+		var err error
+		if template == nil {
+			tmpl, err = New(test.name).Funcs(funcs).Parse(test.input)
+		} else {
+			tmpl, err = template.New(test.name).Funcs(funcs).Parse(test.input)
+		}
+		if err != nil {
+			t.Errorf("%s: parse error: %s", test.name, err)
+			continue
+		}
+		b.Reset()
+		err = tmpl.Execute(b, test.data)
+		switch {
+		case !test.ok && err == nil:
+			t.Errorf("%s: expected error; got none", test.name)
+			continue
+		case test.ok && err != nil:
+			t.Errorf("%s: unexpected execute error: %s", test.name, err)
+			continue
+		case !test.ok && err != nil:
+			// expected error, got one
+			if *debug {
+				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
+			}
+		}
+		result := b.String()
+		if result != test.output {
+			t.Errorf("%s: expected\n\t%q\ngot\n\t%q", test.name, test.output, result)
+		}
+	}
+}
+
+func TestExecute(t *testing.T) {
+	testExecute(execTests, nil, t)
+}
+
+var delimPairs = []string{
+	"", "", // default
+	"{{", "}}", // same as default
+	"<<", ">>", // distinct
+	"|", "|", // same
+	"(日)", "(本)", // peculiar
+}
+
+func TestDelims(t *testing.T) {
+	const hello = "Hello, world"
+	var value = struct{ Str string }{hello}
+	for i := 0; i < len(delimPairs); i += 2 {
+		text := ".Str"
+		left := delimPairs[i+0]
+		trueLeft := left
+		right := delimPairs[i+1]
+		trueRight := right
+		if left == "" { // default case
+			trueLeft = "{{"
+		}
+		if right == "" { // default case
+			trueRight = "}}"
+		}
+		text = trueLeft + text + trueRight
+		// Now add a comment
+		text += trueLeft + "/*comment*/" + trueRight
+		// Now add  an action containing a string.
+		text += trueLeft + `"` + trueLeft + `"` + trueRight
+		// At this point text looks like `{{.Str}}{{/*comment*/}}{{"{{"}}`.
+		tmpl, err := New("delims").Delims(left, right).Parse(text)
+		if err != nil {
+			t.Fatalf("delim %q text %q parse err %s", left, text, err)
+		}
+		var b = new(bytes.Buffer)
+		err = tmpl.Execute(b, value)
+		if err != nil {
+			t.Fatalf("delim %q exec err %s", left, err)
+		}
+		if b.String() != hello+trueLeft {
+			t.Errorf("expected %q got %q", hello+trueLeft, b.String())
+		}
+	}
+}
+
+// Check that an error from a method flows back to the top.
+func TestExecuteError(t *testing.T) {
+	b := new(bytes.Buffer)
+	tmpl := New("error")
+	_, err := tmpl.Parse("{{.EPERM true}}")
+	if err != nil {
+		t.Fatalf("parse error: %s", err)
+	}
+	err = tmpl.Execute(b, tVal)
+	if err == nil {
+		t.Errorf("expected error; got none")
+	} else if !strings.Contains(err.Error(), os.EPERM.Error()) {
+		if *debug {
+			fmt.Printf("test execute error: %s\n", err)
+		}
+		t.Errorf("expected os.EPERM; got %s", err)
+	}
+}
+
+func TestJSEscaping(t *testing.T) {
+	testCases := []struct {
+		in, exp string
+	}{
+		{`a`, `a`},
+		{`'foo`, `\'foo`},
+		{`Go "jump" \`, `Go \"jump\" \\`},
+		{`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`},
+		{"unprintable \uFDFF", `unprintable \uFDFF`},
+		{`<html>`, `\x3Chtml\x3E`},
+	}
+	for _, tc := range testCases {
+		s := JSEscapeString(tc.in)
+		if s != tc.exp {
+			t.Errorf("JS escaping [%s] got [%s] want [%s]", tc.in, s, tc.exp)
+		}
+	}
+}
+
+// A nice example: walk a binary tree.
+
+type Tree struct {
+	Val         int
+	Left, Right *Tree
+}
+
+// Use different delimiters to test Set.Delims.
+const treeTemplate = `
+	(define "tree")
+	[
+		(.Val)
+		(with .Left)
+			(template "tree" .)
+		(end)
+		(with .Right)
+			(template "tree" .)
+		(end)
+	]
+	(end)
+`
+
+func TestTree(t *testing.T) {
+	var tree = &Tree{
+		1,
+		&Tree{
+			2, &Tree{
+				3,
+				&Tree{
+					4, nil, nil,
+				},
+				nil,
+			},
+			&Tree{
+				5,
+				&Tree{
+					6, nil, nil,
+				},
+				nil,
+			},
+		},
+		&Tree{
+			7,
+			&Tree{
+				8,
+				&Tree{
+					9, nil, nil,
+				},
+				nil,
+			},
+			&Tree{
+				10,
+				&Tree{
+					11, nil, nil,
+				},
+				nil,
+			},
+		},
+	}
+	tmpl, err := New("root").Delims("(", ")").Parse(treeTemplate)
+	if err != nil {
+		t.Fatal("parse error:", err)
+	}
+	var b bytes.Buffer
+	stripSpace := func(r rune) rune {
+		if r == '\t' || r == '\n' {
+			return -1
+		}
+		return r
+	}
+	const expect = "[1[2[3[4]][5[6]]][7[8[9]][10[11]]]]"
+	// First by looking up the template.
+	err = tmpl.Lookup("tree").Execute(&b, tree)
+	if err != nil {
+		t.Fatal("exec error:", err)
+	}
+	result := strings.Map(stripSpace, b.String())
+	if result != expect {
+		t.Errorf("expected %q got %q", expect, result)
+	}
+	// Then direct to execution.
+	b.Reset()
+	err = tmpl.ExecuteTemplate(&b, "tree", tree)
+	if err != nil {
+		t.Fatal("exec error:", err)
+	}
+	result = strings.Map(stripSpace, b.String())
+	if result != expect {
+		t.Errorf("expected %q got %q", expect, result)
+	}
+}
diff --git a/src/pkg/text/template/funcs.go b/src/pkg/text/template/funcs.go
new file mode 100644
index 0000000..d6e4bf1
--- /dev/null
+++ b/src/pkg/text/template/funcs.go
@@ -0,0 +1,362 @@
+// Copyright 2011 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 template
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"net/url"
+	"reflect"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// FuncMap is the type of the map defining the mapping from names to functions.
+// Each function must have either a single return value, or two return values of
+// which the second has type error. In that case, if the second (error)
+// argument evaluates to non-nil during execution, execution terminates and
+// Execute returns that error.
+type FuncMap map[string]interface{}
+
+var builtins = FuncMap{
+	"and":      and,
+	"html":     HTMLEscaper,
+	"index":    index,
+	"js":       JSEscaper,
+	"len":      length,
+	"not":      not,
+	"or":       or,
+	"print":    fmt.Sprint,
+	"printf":   fmt.Sprintf,
+	"println":  fmt.Sprintln,
+	"urlquery": URLQueryEscaper,
+}
+
+var builtinFuncs = createValueFuncs(builtins)
+
+// createValueFuncs turns a FuncMap into a map[string]reflect.Value
+func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
+	m := make(map[string]reflect.Value)
+	addValueFuncs(m, funcMap)
+	return m
+}
+
+// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
+func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
+	for name, fn := range in {
+		v := reflect.ValueOf(fn)
+		if v.Kind() != reflect.Func {
+			panic("value for " + name + " not a function")
+		}
+		if !goodFunc(v.Type()) {
+			panic(fmt.Errorf("can't handle multiple results from method/function %q", name))
+		}
+		out[name] = v
+	}
+}
+
+// addFuncs adds to values the functions in funcs. It does no checking of the input -
+// call addValueFuncs first.
+func addFuncs(out, in FuncMap) {
+	for name, fn := range in {
+		out[name] = fn
+	}
+}
+
+// goodFunc checks that the function or method has the right result signature.
+func goodFunc(typ reflect.Type) bool {
+	// We allow functions with 1 result or 2 results where the second is an error.
+	switch {
+	case typ.NumOut() == 1:
+		return true
+	case typ.NumOut() == 2 && typ.Out(1) == errorType:
+		return true
+	}
+	return false
+}
+
+// findFunction looks for a function in the template, and global map.
+func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
+	if tmpl != nil && tmpl.common != nil {
+		if fn := tmpl.execFuncs[name]; fn.IsValid() {
+			return fn, true
+		}
+	}
+	if fn := builtinFuncs[name]; fn.IsValid() {
+		return fn, true
+	}
+	return reflect.Value{}, false
+}
+
+// Indexing.
+
+// index returns the result of indexing its first argument by the following
+// arguments.  Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
+// indexed item must be a map, slice, or array.
+func index(item interface{}, indices ...interface{}) (interface{}, error) {
+	v := reflect.ValueOf(item)
+	for _, i := range indices {
+		index := reflect.ValueOf(i)
+		var isNil bool
+		if v, isNil = indirect(v); isNil {
+			return nil, fmt.Errorf("index of nil pointer")
+		}
+		switch v.Kind() {
+		case reflect.Array, reflect.Slice:
+			var x int64
+			switch index.Kind() {
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+				x = index.Int()
+			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+				x = int64(index.Uint())
+			default:
+				return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
+			}
+			if x < 0 || x >= int64(v.Len()) {
+				return nil, fmt.Errorf("index out of range: %d", x)
+			}
+			v = v.Index(int(x))
+		case reflect.Map:
+			if !index.Type().AssignableTo(v.Type().Key()) {
+				return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
+			}
+			if x := v.MapIndex(index); x.IsValid() {
+				v = x
+			} else {
+				v = reflect.Zero(v.Type().Key())
+			}
+		default:
+			return nil, fmt.Errorf("can't index item of type %s", index.Type())
+		}
+	}
+	return v.Interface(), nil
+}
+
+// Length
+
+// length returns the length of the item, with an error if it has no defined length.
+func length(item interface{}) (int, error) {
+	v, isNil := indirect(reflect.ValueOf(item))
+	if isNil {
+		return 0, fmt.Errorf("len of nil pointer")
+	}
+	switch v.Kind() {
+	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len(), nil
+	}
+	return 0, fmt.Errorf("len of type %s", v.Type())
+}
+
+// Boolean logic.
+
+func truth(a interface{}) bool {
+	t, _ := isTrue(reflect.ValueOf(a))
+	return t
+}
+
+// and computes the Boolean AND of its arguments, returning
+// the first false argument it encounters, or the last argument.
+func and(arg0 interface{}, args ...interface{}) interface{} {
+	if !truth(arg0) {
+		return arg0
+	}
+	for i := range args {
+		arg0 = args[i]
+		if !truth(arg0) {
+			break
+		}
+	}
+	return arg0
+}
+
+// or computes the Boolean OR of its arguments, returning
+// the first true argument it encounters, or the last argument.
+func or(arg0 interface{}, args ...interface{}) interface{} {
+	if truth(arg0) {
+		return arg0
+	}
+	for i := range args {
+		arg0 = args[i]
+		if truth(arg0) {
+			break
+		}
+	}
+	return arg0
+}
+
+// not returns the Boolean negation of its argument.
+func not(arg interface{}) (truth bool) {
+	truth, _ = isTrue(reflect.ValueOf(arg))
+	return !truth
+}
+
+// HTML escaping.
+
+var (
+	htmlQuot = []byte(""") // shorter than """
+	htmlApos = []byte("'") // shorter than "'"
+	htmlAmp  = []byte("&")
+	htmlLt   = []byte("<")
+	htmlGt   = []byte(">")
+)
+
+// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
+func HTMLEscape(w io.Writer, b []byte) {
+	last := 0
+	for i, c := range b {
+		var html []byte
+		switch c {
+		case '"':
+			html = htmlQuot
+		case '\'':
+			html = htmlApos
+		case '&':
+			html = htmlAmp
+		case '<':
+			html = htmlLt
+		case '>':
+			html = htmlGt
+		default:
+			continue
+		}
+		w.Write(b[last:i])
+		w.Write(html)
+		last = i + 1
+	}
+	w.Write(b[last:])
+}
+
+// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
+func HTMLEscapeString(s string) string {
+	// Avoid allocation if we can.
+	if strings.IndexAny(s, `'"&<>`) < 0 {
+		return s
+	}
+	var b bytes.Buffer
+	HTMLEscape(&b, []byte(s))
+	return b.String()
+}
+
+// HTMLEscaper returns the escaped HTML equivalent of the textual
+// representation of its arguments.
+func HTMLEscaper(args ...interface{}) string {
+	ok := false
+	var s string
+	if len(args) == 1 {
+		s, ok = args[0].(string)
+	}
+	if !ok {
+		s = fmt.Sprint(args...)
+	}
+	return HTMLEscapeString(s)
+}
+
+// JavaScript escaping.
+
+var (
+	jsLowUni = []byte(`\u00`)
+	hex      = []byte("0123456789ABCDEF")
+
+	jsBackslash = []byte(`\\`)
+	jsApos      = []byte(`\'`)
+	jsQuot      = []byte(`\"`)
+	jsLt        = []byte(`\x3C`)
+	jsGt        = []byte(`\x3E`)
+)
+
+// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
+func JSEscape(w io.Writer, b []byte) {
+	last := 0
+	for i := 0; i < len(b); i++ {
+		c := b[i]
+
+		if !jsIsSpecial(rune(c)) {
+			// fast path: nothing to do
+			continue
+		}
+		w.Write(b[last:i])
+
+		if c < utf8.RuneSelf {
+			// Quotes, slashes and angle brackets get quoted.
+			// Control characters get written as \u00XX.
+			switch c {
+			case '\\':
+				w.Write(jsBackslash)
+			case '\'':
+				w.Write(jsApos)
+			case '"':
+				w.Write(jsQuot)
+			case '<':
+				w.Write(jsLt)
+			case '>':
+				w.Write(jsGt)
+			default:
+				w.Write(jsLowUni)
+				t, b := c>>4, c&0x0f
+				w.Write(hex[t : t+1])
+				w.Write(hex[b : b+1])
+			}
+		} else {
+			// Unicode rune.
+			r, size := utf8.DecodeRune(b[i:])
+			if unicode.IsPrint(r) {
+				w.Write(b[i : i+size])
+			} else {
+				fmt.Fprintf(w, "\\u%04X", r)
+			}
+			i += size - 1
+		}
+		last = i + 1
+	}
+	w.Write(b[last:])
+}
+
+// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
+func JSEscapeString(s string) string {
+	// Avoid allocation if we can.
+	if strings.IndexFunc(s, jsIsSpecial) < 0 {
+		return s
+	}
+	var b bytes.Buffer
+	JSEscape(&b, []byte(s))
+	return b.String()
+}
+
+func jsIsSpecial(r rune) bool {
+	switch r {
+	case '\\', '\'', '"', '<', '>':
+		return true
+	}
+	return r < ' ' || utf8.RuneSelf <= r
+}
+
+// JSEscaper returns the escaped JavaScript equivalent of the textual
+// representation of its arguments.
+func JSEscaper(args ...interface{}) string {
+	ok := false
+	var s string
+	if len(args) == 1 {
+		s, ok = args[0].(string)
+	}
+	if !ok {
+		s = fmt.Sprint(args...)
+	}
+	return JSEscapeString(s)
+}
+
+// URLQueryEscaper returns the escaped value of the textual representation of
+// its arguments in a form suitable for embedding in a URL query.
+func URLQueryEscaper(args ...interface{}) string {
+	s, ok := "", false
+	if len(args) == 1 {
+		s, ok = args[0].(string)
+	}
+	if !ok {
+		s = fmt.Sprint(args...)
+	}
+	return url.QueryEscape(s)
+}
diff --git a/src/pkg/text/template/helper.go b/src/pkg/text/template/helper.go
new file mode 100644
index 0000000..3636fb5
--- /dev/null
+++ b/src/pkg/text/template/helper.go
@@ -0,0 +1,108 @@
+// Copyright 2011 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.
+
+// Helper functions to make constructing templates easier.
+
+package template
+
+import (
+	"fmt"
+	"io/ioutil"
+	"path/filepath"
+)
+
+// Functions and methods to parse templates.
+
+// Must is a helper that wraps a call to a function returning (*Template, error)
+// and panics if the error is non-nil. It is intended for use in variable
+// initializations such as
+//	var t = template.Must(template.New("name").Parse("text"))
+func Must(t *Template, err error) *Template {
+	if err != nil {
+		panic(err)
+	}
+	return t
+}
+
+// ParseFiles creates a new Template and parses the template definitions from
+// the named files. The returned template's name will have the (base) name and
+// (parsed) contents of the first file. There must be at least one file.
+// If an error occurs, parsing stops and the returned *Template is nil.
+func ParseFiles(filenames ...string) (*Template, error) {
+	return parseFiles(nil, filenames...)
+}
+
+// ParseFiles parses the named files and associates the resulting templates with
+// t. If an error occurs, parsing stops and the returned template is nil;
+// otherwise it is t. There must be at least one file.
+func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
+	return parseFiles(t, filenames...)
+}
+
+// parseFiles is the helper for the method and function. If the argument
+// template is nil, it is created from the first file.
+func parseFiles(t *Template, filenames ...string) (*Template, error) {
+	if len(filenames) == 0 {
+		// Not really a problem, but be consistent.
+		return nil, fmt.Errorf("template: no files named in call to ParseFiles")
+	}
+	for _, filename := range filenames {
+		b, err := ioutil.ReadFile(filename)
+		if err != nil {
+			return nil, err
+		}
+		s := string(b)
+		name := filepath.Base(filename)
+		// First template becomes return value if not already defined,
+		// and we use that one for subsequent New calls to associate
+		// all the templates together. Also, if this file has the same name
+		// as t, this file becomes the contents of t, so
+		//  t, err := New(name).Funcs(xxx).ParseFiles(name)
+		// works. Otherwise we create a new template associated with t.
+		var tmpl *Template
+		if t == nil {
+			t = New(name)
+		}
+		if name == t.Name() {
+			tmpl = t
+		} else {
+			tmpl = t.New(name)
+		}
+		_, err = tmpl.Parse(s)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return t, nil
+}
+
+// ParseGlob creates a new Template and parses the template definitions from the
+// files identified by the pattern, which must match at least one file. The
+// returned template will have the (base) name and (parsed) contents of the
+// first file matched by the pattern. ParseGlob is equivalent to calling
+// ParseFiles with the list of files matched by the pattern.
+func ParseGlob(pattern string) (*Template, error) {
+	return parseGlob(nil, pattern)
+}
+
+// ParseGlob parses the template definitions in the files identified by the
+// pattern and associates the resulting templates with t. The pattern is
+// processed by filepath.Glob and must match at least one file. ParseGlob is
+// equivalent to calling t.ParseFiles with the list of files matched by the
+// pattern.
+func (t *Template) ParseGlob(pattern string) (*Template, error) {
+	return parseGlob(t, pattern)
+}
+
+// parseGlob is the implementation of the function and method ParseGlob.
+func parseGlob(t *Template, pattern string) (*Template, error) {
+	filenames, err := filepath.Glob(pattern)
+	if err != nil {
+		return nil, err
+	}
+	if len(filenames) == 0 {
+		return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
+	}
+	return parseFiles(t, filenames...)
+}
diff --git a/src/pkg/text/template/multi_test.go b/src/pkg/text/template/multi_test.go
new file mode 100644
index 0000000..274f5ef
--- /dev/null
+++ b/src/pkg/text/template/multi_test.go
@@ -0,0 +1,274 @@
+// Copyright 2011 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 template
+
+// Tests for mulitple-template parsing and execution.
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+	"testing"
+	"text/template/parse"
+)
+
+const (
+	noError  = true
+	hasError = false
+)
+
+type multiParseTest struct {
+	name    string
+	input   string
+	ok      bool
+	names   []string
+	results []string
+}
+
+var multiParseTests = []multiParseTest{
+	{"empty", "", noError,
+		nil,
+		nil},
+	{"one", `{{define "foo"}} FOO {{end}}`, noError,
+		[]string{"foo"},
+		[]string{`" FOO "`}},
+	{"two", `{{define "foo"}} FOO {{end}}{{define "bar"}} BAR {{end}}`, noError,
+		[]string{"foo", "bar"},
+		[]string{`" FOO "`, `" BAR "`}},
+	// errors
+	{"missing end", `{{define "foo"}} FOO `, hasError,
+		nil,
+		nil},
+	{"malformed name", `{{define "foo}} FOO `, hasError,
+		nil,
+		nil},
+}
+
+func TestMultiParse(t *testing.T) {
+	for _, test := range multiParseTests {
+		template, err := New("root").Parse(test.input)
+		switch {
+		case err == nil && !test.ok:
+			t.Errorf("%q: expected error; got none", test.name)
+			continue
+		case err != nil && test.ok:
+			t.Errorf("%q: unexpected error: %v", test.name, err)
+			continue
+		case err != nil && !test.ok:
+			// expected error, got one
+			if *debug {
+				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
+			}
+			continue
+		}
+		if template == nil {
+			continue
+		}
+		if len(template.tmpl) != len(test.names)+1 { // +1 for root
+			t.Errorf("%s: wrong number of templates; wanted %d got %d", test.name, len(test.names), len(template.tmpl))
+			continue
+		}
+		for i, name := range test.names {
+			tmpl, ok := template.tmpl[name]
+			if !ok {
+				t.Errorf("%s: can't find template %q", test.name, name)
+				continue
+			}
+			result := tmpl.Root.String()
+			if result != test.results[i] {
+				t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.results[i])
+			}
+		}
+	}
+}
+
+var multiExecTests = []execTest{
+	{"empty", "", "", nil, true},
+	{"text", "some text", "some text", nil, true},
+	{"invoke x", `{{template "x" .SI}}`, "TEXT", tVal, true},
+	{"invoke x no args", `{{template "x"}}`, "TEXT", tVal, true},
+	{"invoke dot int", `{{template "dot" .I}}`, "17", tVal, true},
+	{"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
+	{"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
+	{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
+	{"variable declared by template", `{{template "nested" $x=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
+
+	// User-defined function: test argument evaluator.
+	{"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},
+	{"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true},
+}
+
+// These strings are also in testdata/*.
+const multiText1 = `
+	{{define "x"}}TEXT{{end}}
+	{{define "dotV"}}{{.V}}{{end}}
+`
+
+const multiText2 = `
+	{{define "dot"}}{{.}}{{end}}
+	{{define "nested"}}{{template "dot" .}}{{end}}
+`
+
+func TestMultiExecute(t *testing.T) {
+	// Declare a couple of templates first.
+	template, err := New("root").Parse(multiText1)
+	if err != nil {
+		t.Fatalf("parse error for 1: %s", err)
+	}
+	_, err = template.Parse(multiText2)
+	if err != nil {
+		t.Fatalf("parse error for 2: %s", err)
+	}
+	testExecute(multiExecTests, template, t)
+}
+
+func TestParseFiles(t *testing.T) {
+	_, err := ParseFiles("DOES NOT EXIST")
+	if err == nil {
+		t.Error("expected error for non-existent file; got none")
+	}
+	template := New("root")
+	_, err = template.ParseFiles("testdata/file1.tmpl", "testdata/file2.tmpl")
+	if err != nil {
+		t.Fatalf("error parsing files: %v", err)
+	}
+	testExecute(multiExecTests, template, t)
+}
+
+func TestParseGlob(t *testing.T) {
+	_, err := ParseGlob("DOES NOT EXIST")
+	if err == nil {
+		t.Error("expected error for non-existent file; got none")
+	}
+	_, err = New("error").ParseGlob("[x")
+	if err == nil {
+		t.Error("expected error for bad pattern; got none")
+	}
+	template := New("root")
+	_, err = template.ParseGlob("testdata/file*.tmpl")
+	if err != nil {
+		t.Fatalf("error parsing files: %v", err)
+	}
+	testExecute(multiExecTests, template, t)
+}
+
+// In these tests, actual content (not just template definitions) comes from the parsed files.
+
+var templateFileExecTests = []execTest{
+	{"test", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\n\ny\ntemplate2\n\nx\n", 0, true},
+}
+
+func TestParseFilesWithData(t *testing.T) {
+	template, err := New("root").ParseFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl")
+	if err != nil {
+		t.Fatalf("error parsing files: %v", err)
+	}
+	testExecute(templateFileExecTests, template, t)
+}
+
+func TestParseGlobWithData(t *testing.T) {
+	template, err := New("root").ParseGlob("testdata/tmpl*.tmpl")
+	if err != nil {
+		t.Fatalf("error parsing files: %v", err)
+	}
+	testExecute(templateFileExecTests, template, t)
+}
+
+const (
+	cloneText1 = `{{define "a"}}{{template "b"}}{{template "c"}}{{end}}`
+	cloneText2 = `{{define "b"}}b{{end}}`
+	cloneText3 = `{{define "c"}}root{{end}}`
+	cloneText4 = `{{define "c"}}clone{{end}}`
+)
+
+func TestClone(t *testing.T) {
+	// Create some templates and clone the root.
+	root, err := New("root").Parse(cloneText1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = root.Parse(cloneText2)
+	if err != nil {
+		t.Fatal(err)
+	}
+	clone := root.Clone()
+	// Add variants to both.
+	_, err = root.Parse(cloneText3)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = clone.Parse(cloneText4)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Verify that the clone is self-consistent.
+	for k, v := range clone.tmpl {
+		if k == clone.name && v.tmpl[k] != clone {
+			t.Error("clone does not contain root")
+		}
+		if v != v.tmpl[v.name] {
+			t.Errorf("clone does not contain self for %q", k)
+		}
+	}
+	// Execute root.
+	var b bytes.Buffer
+	err = root.ExecuteTemplate(&b, "a", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if b.String() != "broot" {
+		t.Errorf("expected %q got %q", "broot", b.String())
+	}
+	// Execute copy.
+	b.Reset()
+	err = clone.ExecuteTemplate(&b, "a", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if b.String() != "bclone" {
+		t.Errorf("expected %q got %q", "bclone", b.String())
+	}
+}
+
+func TestAddParseTree(t *testing.T) {
+	// Create some templates.
+	root, err := New("root").Parse(cloneText1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = root.Parse(cloneText2)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Add a new parse tree.
+	tree, err := parse.Parse("cloneText3", cloneText3, "", "", nil, builtins)
+	if err != nil {
+		t.Fatal(err)
+	}
+	added, err := root.AddParseTree("c", tree["c"])
+	// Execute.
+	var b bytes.Buffer
+	err = added.ExecuteTemplate(&b, "a", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if b.String() != "broot" {
+		t.Errorf("expected %q got %q", "broot", b.String())
+	}
+}
+
+func TestRedefinition(t *testing.T) {
+	var tmpl *Template
+	var err error
+	if tmpl, err = New("tmpl1").Parse(`{{define "test"}}foo{{end}}`); err != nil {
+		t.Fatalf("parse 1: %v", err)
+	}
+	if _, err = tmpl.New("tmpl2").Parse(`{{define "test"}}bar{{end}}`); err == nil {
+		t.Fatal("expected error")
+	}
+	if !strings.Contains(err.Error(), "redefinition") {
+		t.Fatalf("expected redefinition error; got %v", err)
+	}
+}
diff --git a/src/pkg/text/template/parse/Makefile b/src/pkg/text/template/parse/Makefile
new file mode 100644
index 0000000..75cade8
--- /dev/null
+++ b/src/pkg/text/template/parse/Makefile
@@ -0,0 +1,13 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../../Make.inc
+
+TARG=text/template/parse
+GOFILES=\
+	lex.go\
+	node.go\
+	parse.go\
+
+include ../../../../Make.pkg
diff --git a/src/pkg/text/template/parse/lex.go b/src/pkg/text/template/parse/lex.go
new file mode 100644
index 0000000..97c19a1
--- /dev/null
+++ b/src/pkg/text/template/parse/lex.go
@@ -0,0 +1,482 @@
+// Copyright 2011 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 parse
+
+import (
+	"fmt"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// item represents a token or text string returned from the scanner.
+type item struct {
+	typ itemType
+	val string
+}
+
+func (i item) String() string {
+	switch {
+	case i.typ == itemEOF:
+		return "EOF"
+	case i.typ == itemError:
+		return i.val
+	case i.typ > itemKeyword:
+		return fmt.Sprintf("<%s>", i.val)
+	case len(i.val) > 10:
+		return fmt.Sprintf("%.10q...", i.val)
+	}
+	return fmt.Sprintf("%q", i.val)
+}
+
+// itemType identifies the type of lex items.
+type itemType int
+
+const (
+	itemError        itemType = iota // error occurred; value is text of error
+	itemBool                         // boolean constant
+	itemChar                         // printable ASCII character; grab bag for comma etc.
+	itemCharConstant                 // character constant
+	itemComplex                      // complex constant (1+2i); imaginary is just a number
+	itemColonEquals                  // colon-equals (':=') introducing a declaration
+	itemEOF
+	itemField      // alphanumeric identifier, starting with '.', possibly chained ('.x.y')
+	itemIdentifier // alphanumeric identifier
+	itemLeftDelim  // left action delimiter
+	itemNumber     // simple number, including imaginary
+	itemPipe       // pipe symbol
+	itemRawString  // raw quoted string (includes quotes)
+	itemRightDelim // right action delimiter
+	itemString     // quoted string (includes quotes)
+	itemText       // plain text
+	itemVariable   // variable starting with '$', such as '$' or  '$1' or '$hello'.
+	// Keywords appear after all the rest.
+	itemKeyword  // used only to delimit the keywords
+	itemDot      // the cursor, spelled '.'.
+	itemDefine   // define keyword
+	itemElse     // else keyword
+	itemEnd      // end keyword
+	itemIf       // if keyword
+	itemRange    // range keyword
+	itemTemplate // template keyword
+	itemWith     // with keyword
+)
+
+// Make the types prettyprint.
+var itemName = map[itemType]string{
+	itemError:        "error",
+	itemBool:         "bool",
+	itemChar:         "char",
+	itemCharConstant: "charconst",
+	itemComplex:      "complex",
+	itemColonEquals:  ":=",
+	itemEOF:          "EOF",
+	itemField:        "field",
+	itemIdentifier:   "identifier",
+	itemLeftDelim:    "left delim",
+	itemNumber:       "number",
+	itemPipe:         "pipe",
+	itemRawString:    "raw string",
+	itemRightDelim:   "right delim",
+	itemString:       "string",
+	itemVariable:     "variable",
+	// keywords
+	itemDot:      ".",
+	itemDefine:   "define",
+	itemElse:     "else",
+	itemIf:       "if",
+	itemEnd:      "end",
+	itemRange:    "range",
+	itemTemplate: "template",
+	itemWith:     "with",
+}
+
+func (i itemType) String() string {
+	s := itemName[i]
+	if s == "" {
+		return fmt.Sprintf("item%d", int(i))
+	}
+	return s
+}
+
+var key = map[string]itemType{
+	".":        itemDot,
+	"define":   itemDefine,
+	"else":     itemElse,
+	"end":      itemEnd,
+	"if":       itemIf,
+	"range":    itemRange,
+	"template": itemTemplate,
+	"with":     itemWith,
+}
+
+const eof = -1
+
+// stateFn represents the state of the scanner as a function that returns the next state.
+type stateFn func(*lexer) stateFn
+
+// lexer holds the state of the scanner.
+type lexer struct {
+	name       string    // the name of the input; used only for error reports.
+	input      string    // the string being scanned.
+	leftDelim  string    // start of action.
+	rightDelim string    // end of action.
+	state      stateFn   // the next lexing function to enter.
+	pos        int       // current position in the input.
+	start      int       // start position of this item.
+	width      int       // width of last rune read from input.
+	items      chan item // channel of scanned items.
+}
+
+// next returns the next rune in the input.
+func (l *lexer) next() (r rune) {
+	if l.pos >= len(l.input) {
+		l.width = 0
+		return eof
+	}
+	r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
+	l.pos += l.width
+	return r
+}
+
+// peek returns but does not consume the next rune in the input.
+func (l *lexer) peek() rune {
+	r := l.next()
+	l.backup()
+	return r
+}
+
+// backup steps back one rune. Can only be called once per call of next.
+func (l *lexer) backup() {
+	l.pos -= l.width
+}
+
+// emit passes an item back to the client.
+func (l *lexer) emit(t itemType) {
+	l.items <- item{t, l.input[l.start:l.pos]}
+	l.start = l.pos
+}
+
+// ignore skips over the pending input before this point.
+func (l *lexer) ignore() {
+	l.start = l.pos
+}
+
+// accept consumes the next rune if it's from the valid set.
+func (l *lexer) accept(valid string) bool {
+	if strings.IndexRune(valid, l.next()) >= 0 {
+		return true
+	}
+	l.backup()
+	return false
+}
+
+// acceptRun consumes a run of runes from the valid set.
+func (l *lexer) acceptRun(valid string) {
+	for strings.IndexRune(valid, l.next()) >= 0 {
+	}
+	l.backup()
+}
+
+// lineNumber reports which line we're on. Doing it this way
+// means we don't have to worry about peek double counting.
+func (l *lexer) lineNumber() int {
+	return 1 + strings.Count(l.input[:l.pos], "\n")
+}
+
+// error returns an error token and terminates the scan by passing
+// back a nil pointer that will be the next state, terminating l.run.
+func (l *lexer) errorf(format string, args ...interface{}) stateFn {
+	l.items <- item{itemError, fmt.Sprintf(format, args...)}
+	return nil
+}
+
+// nextItem returns the next item from the input.
+func (l *lexer) nextItem() item {
+	for {
+		select {
+		case item := <-l.items:
+			return item
+		default:
+			l.state = l.state(l)
+		}
+	}
+	panic("not reached")
+}
+
+// lex creates a new scanner for the input string.
+func lex(name, input, left, right string) *lexer {
+	if left == "" {
+		left = leftDelim
+	}
+	if right == "" {
+		right = rightDelim
+	}
+	l := &lexer{
+		name:       name,
+		input:      input,
+		leftDelim:  left,
+		rightDelim: right,
+		state:      lexText,
+		items:      make(chan item, 2), // Two items of buffering is sufficient for all state functions
+	}
+	return l
+}
+
+// state functions
+
+const (
+	leftDelim    = "{{"
+	rightDelim   = "}}"
+	leftComment  = "/*"
+	rightComment = "*/"
+)
+
+// lexText scans until an opening action delimiter, "{{".
+func lexText(l *lexer) stateFn {
+	for {
+		if strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
+			if l.pos > l.start {
+				l.emit(itemText)
+			}
+			return lexLeftDelim
+		}
+		if l.next() == eof {
+			break
+		}
+	}
+	// Correctly reached EOF.
+	if l.pos > l.start {
+		l.emit(itemText)
+	}
+	l.emit(itemEOF)
+	return nil
+}
+
+// lexLeftDelim scans the left delimiter, which is known to be present.
+func lexLeftDelim(l *lexer) stateFn {
+	if strings.HasPrefix(l.input[l.pos:], l.leftDelim+leftComment) {
+		return lexComment
+	}
+	l.pos += len(l.leftDelim)
+	l.emit(itemLeftDelim)
+	return lexInsideAction
+}
+
+// lexComment scans a comment. The left comment marker is known to be present.
+func lexComment(l *lexer) stateFn {
+	i := strings.Index(l.input[l.pos:], rightComment+l.rightDelim)
+	if i < 0 {
+		return l.errorf("unclosed comment")
+	}
+	l.pos += i + len(rightComment) + len(l.rightDelim)
+	l.ignore()
+	return lexText
+}
+
+// lexRightDelim scans the right delimiter, which is known to be present.
+func lexRightDelim(l *lexer) stateFn {
+	l.pos += len(l.rightDelim)
+	l.emit(itemRightDelim)
+	return lexText
+}
+
+// lexInsideAction scans the elements inside action delimiters.
+func lexInsideAction(l *lexer) stateFn {
+	// Either number, quoted string, or identifier.
+	// Spaces separate and are ignored.
+	// Pipe symbols separate and are emitted.
+	if strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+		return lexRightDelim
+	}
+	switch r := l.next(); {
+	case r == eof || r == '\n':
+		return l.errorf("unclosed action")
+	case isSpace(r):
+		l.ignore()
+	case r == ':':
+		if l.next() != '=' {
+			return l.errorf("expected :=")
+		}
+		l.emit(itemColonEquals)
+	case r == '|':
+		l.emit(itemPipe)
+	case r == '"':
+		return lexQuote
+	case r == '`':
+		return lexRawQuote
+	case r == '$':
+		return lexIdentifier
+	case r == '\'':
+		return lexChar
+	case r == '.':
+		// special look-ahead for ".field" so we don't break l.backup().
+		if l.pos < len(l.input) {
+			r := l.input[l.pos]
+			if r < '0' || '9' < r {
+				return lexIdentifier // itemDot comes from the keyword table.
+			}
+		}
+		fallthrough // '.' can start a number.
+	case r == '+' || r == '-' || ('0' <= r && r <= '9'):
+		l.backup()
+		return lexNumber
+	case isAlphaNumeric(r):
+		l.backup()
+		return lexIdentifier
+	case r <= unicode.MaxASCII && unicode.IsPrint(r):
+		l.emit(itemChar)
+		return lexInsideAction
+	default:
+		return l.errorf("unrecognized character in action: %#U", r)
+	}
+	return lexInsideAction
+}
+
+// lexIdentifier scans an alphanumeric or field.
+func lexIdentifier(l *lexer) stateFn {
+Loop:
+	for {
+		switch r := l.next(); {
+		case isAlphaNumeric(r):
+			// absorb.
+		case r == '.' && (l.input[l.start] == '.' || l.input[l.start] == '$'):
+			// field chaining; absorb into one token.
+		default:
+			l.backup()
+			word := l.input[l.start:l.pos]
+			switch {
+			case key[word] > itemKeyword:
+				l.emit(key[word])
+			case word[0] == '.':
+				l.emit(itemField)
+			case word[0] == '$':
+				l.emit(itemVariable)
+			case word == "true", word == "false":
+				l.emit(itemBool)
+			default:
+				l.emit(itemIdentifier)
+			}
+			break Loop
+		}
+	}
+	return lexInsideAction
+}
+
+// lexChar scans a character constant. The initial quote is already
+// scanned.  Syntax checking is done by the parse.
+func lexChar(l *lexer) stateFn {
+Loop:
+	for {
+		switch l.next() {
+		case '\\':
+			if r := l.next(); r != eof && r != '\n' {
+				break
+			}
+			fallthrough
+		case eof, '\n':
+			return l.errorf("unterminated character constant")
+		case '\'':
+			break Loop
+		}
+	}
+	l.emit(itemCharConstant)
+	return lexInsideAction
+}
+
+// lexNumber scans a number: decimal, octal, hex, float, or imaginary.  This
+// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
+// and "089" - but when it's wrong the input is invalid and the parser (via
+// strconv) will notice.
+func lexNumber(l *lexer) stateFn {
+	if !l.scanNumber() {
+		return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
+	}
+	if sign := l.peek(); sign == '+' || sign == '-' {
+		// Complex: 1+2i.  No spaces, must end in 'i'.
+		if !l.scanNumber() || l.input[l.pos-1] != 'i' {
+			return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
+		}
+		l.emit(itemComplex)
+	} else {
+		l.emit(itemNumber)
+	}
+	return lexInsideAction
+}
+
+func (l *lexer) scanNumber() bool {
+	// Optional leading sign.
+	l.accept("+-")
+	// Is it hex?
+	digits := "0123456789"
+	if l.accept("0") && l.accept("xX") {
+		digits = "0123456789abcdefABCDEF"
+	}
+	l.acceptRun(digits)
+	if l.accept(".") {
+		l.acceptRun(digits)
+	}
+	if l.accept("eE") {
+		l.accept("+-")
+		l.acceptRun("0123456789")
+	}
+	// Is it imaginary?
+	l.accept("i")
+	// Next thing mustn't be alphanumeric.
+	if isAlphaNumeric(l.peek()) {
+		l.next()
+		return false
+	}
+	return true
+}
+
+// lexQuote scans a quoted string.
+func lexQuote(l *lexer) stateFn {
+Loop:
+	for {
+		switch l.next() {
+		case '\\':
+			if r := l.next(); r != eof && r != '\n' {
+				break
+			}
+			fallthrough
+		case eof, '\n':
+			return l.errorf("unterminated quoted string")
+		case '"':
+			break Loop
+		}
+	}
+	l.emit(itemString)
+	return lexInsideAction
+}
+
+// lexRawQuote scans a raw quoted string.
+func lexRawQuote(l *lexer) stateFn {
+Loop:
+	for {
+		switch l.next() {
+		case eof, '\n':
+			return l.errorf("unterminated raw quoted string")
+		case '`':
+			break Loop
+		}
+	}
+	l.emit(itemRawString)
+	return lexInsideAction
+}
+
+// isSpace reports whether r is a space character.
+func isSpace(r rune) bool {
+	switch r {
+	case ' ', '\t', '\n', '\r':
+		return true
+	}
+	return false
+}
+
+// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
+func isAlphaNumeric(r rune) bool {
+	return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
+}
diff --git a/src/pkg/text/template/parse/lex_test.go b/src/pkg/text/template/parse/lex_test.go
new file mode 100644
index 0000000..6ee1b47
--- /dev/null
+++ b/src/pkg/text/template/parse/lex_test.go
@@ -0,0 +1,257 @@
+// Copyright 2011 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 parse
+
+import (
+	"reflect"
+	"testing"
+)
+
+type lexTest struct {
+	name  string
+	input string
+	items []item
+}
+
+var (
+	tEOF      = item{itemEOF, ""}
+	tLeft     = item{itemLeftDelim, "{{"}
+	tRight    = item{itemRightDelim, "}}"}
+	tRange    = item{itemRange, "range"}
+	tPipe     = item{itemPipe, "|"}
+	tFor      = item{itemIdentifier, "for"}
+	tQuote    = item{itemString, `"abc \n\t\" "`}
+	raw       = "`" + `abc\n\t\" ` + "`"
+	tRawQuote = item{itemRawString, raw}
+)
+
+var lexTests = []lexTest{
+	{"empty", "", []item{tEOF}},
+	{"spaces", " \t\n", []item{{itemText, " \t\n"}, tEOF}},
+	{"text", `now is the time`, []item{{itemText, "now is the time"}, tEOF}},
+	{"text with comment", "hello-{{/* this is a comment */}}-world", []item{
+		{itemText, "hello-"},
+		{itemText, "-world"},
+		tEOF,
+	}},
+	{"punctuation", "{{,@%}}", []item{
+		tLeft,
+		{itemChar, ","},
+		{itemChar, "@"},
+		{itemChar, "%"},
+		tRight,
+		tEOF,
+	}},
+	{"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
+	{"for", `{{for }}`, []item{tLeft, tFor, tRight, tEOF}},
+	{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
+	{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
+	{"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{
+		tLeft,
+		{itemNumber, "1"},
+		{itemNumber, "02"},
+		{itemNumber, "0x14"},
+		{itemNumber, "-7.2i"},
+		{itemNumber, "1e3"},
+		{itemNumber, "+1.2e-4"},
+		{itemNumber, "4.2i"},
+		{itemComplex, "1+2i"},
+		tRight,
+		tEOF,
+	}},
+	{"characters", `{{'a' '\n' '\'' '\\' '\u00FF' '\xFF' '本'}}`, []item{
+		tLeft,
+		{itemCharConstant, `'a'`},
+		{itemCharConstant, `'\n'`},
+		{itemCharConstant, `'\''`},
+		{itemCharConstant, `'\\'`},
+		{itemCharConstant, `'\u00FF'`},
+		{itemCharConstant, `'\xFF'`},
+		{itemCharConstant, `'本'`},
+		tRight,
+		tEOF,
+	}},
+	{"bools", "{{true false}}", []item{
+		tLeft,
+		{itemBool, "true"},
+		{itemBool, "false"},
+		tRight,
+		tEOF,
+	}},
+	{"dot", "{{.}}", []item{
+		tLeft,
+		{itemDot, "."},
+		tRight,
+		tEOF,
+	}},
+	{"dots", "{{.x . .2 .x.y}}", []item{
+		tLeft,
+		{itemField, ".x"},
+		{itemDot, "."},
+		{itemNumber, ".2"},
+		{itemField, ".x.y"},
+		tRight,
+		tEOF,
+	}},
+	{"keywords", "{{range if else end with}}", []item{
+		tLeft,
+		{itemRange, "range"},
+		{itemIf, "if"},
+		{itemElse, "else"},
+		{itemEnd, "end"},
+		{itemWith, "with"},
+		tRight,
+		tEOF,
+	}},
+	{"variables", "{{$c := printf $ $hello $23 $ $var.Field .Method}}", []item{
+		tLeft,
+		{itemVariable, "$c"},
+		{itemColonEquals, ":="},
+		{itemIdentifier, "printf"},
+		{itemVariable, "$"},
+		{itemVariable, "$hello"},
+		{itemVariable, "$23"},
+		{itemVariable, "$"},
+		{itemVariable, "$var.Field"},
+		{itemField, ".Method"},
+		tRight,
+		tEOF,
+	}},
+	{"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{
+		{itemText, "intro "},
+		tLeft,
+		{itemIdentifier, "echo"},
+		{itemIdentifier, "hi"},
+		{itemNumber, "1.2"},
+		tPipe,
+		{itemIdentifier, "noargs"},
+		tPipe,
+		{itemIdentifier, "args"},
+		{itemNumber, "1"},
+		{itemString, `"hi"`},
+		tRight,
+		{itemText, " outro"},
+		tEOF,
+	}},
+	{"declaration", "{{$v := 3}}", []item{
+		tLeft,
+		{itemVariable, "$v"},
+		{itemColonEquals, ":="},
+		{itemNumber, "3"},
+		tRight,
+		tEOF,
+	}},
+	{"2 declarations", "{{$v , $w := 3}}", []item{
+		tLeft,
+		{itemVariable, "$v"},
+		{itemChar, ","},
+		{itemVariable, "$w"},
+		{itemColonEquals, ":="},
+		{itemNumber, "3"},
+		tRight,
+		tEOF,
+	}},
+	// errors
+	{"badchar", "#{{\x01}}", []item{
+		{itemText, "#"},
+		tLeft,
+		{itemError, "unrecognized character in action: U+0001"},
+	}},
+	{"unclosed action", "{{\n}}", []item{
+		tLeft,
+		{itemError, "unclosed action"},
+	}},
+	{"EOF in action", "{{range", []item{
+		tLeft,
+		tRange,
+		{itemError, "unclosed action"},
+	}},
+	{"unclosed quote", "{{\"\n\"}}", []item{
+		tLeft,
+		{itemError, "unterminated quoted string"},
+	}},
+	{"unclosed raw quote", "{{`xx\n`}}", []item{
+		tLeft,
+		{itemError, "unterminated raw quoted string"},
+	}},
+	{"unclosed char constant", "{{'\n}}", []item{
+		tLeft,
+		{itemError, "unterminated character constant"},
+	}},
+	{"bad number", "{{3k}}", []item{
+		tLeft,
+		{itemError, `bad number syntax: "3k"`},
+	}},
+
+	// Fixed bugs
+	// Many elements in an action blew the lookahead until
+	// we made lexInsideAction not loop.
+	{"long pipeline deadlock", "{{|||||}}", []item{
+		tLeft,
+		tPipe,
+		tPipe,
+		tPipe,
+		tPipe,
+		tPipe,
+		tRight,
+		tEOF,
+	}},
+}
+
+// collect gathers the emitted items into a slice.
+func collect(t *lexTest, left, right string) (items []item) {
+	l := lex(t.name, t.input, left, right)
+	for {
+		item := l.nextItem()
+		items = append(items, item)
+		if item.typ == itemEOF || item.typ == itemError {
+			break
+		}
+	}
+	return
+}
+
+func TestLex(t *testing.T) {
+	for _, test := range lexTests {
+		items := collect(&test, "", "")
+		if !reflect.DeepEqual(items, test.items) {
+			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+		}
+	}
+}
+
+// Some easy cases from above, but with delimiters $$ and @@
+var lexDelimTests = []lexTest{
+	{"punctuation", "$$,@%{{}}@@", []item{
+		tLeftDelim,
+		{itemChar, ","},
+		{itemChar, "@"},
+		{itemChar, "%"},
+		{itemChar, "{"},
+		{itemChar, "{"},
+		{itemChar, "}"},
+		{itemChar, "}"},
+		tRightDelim,
+		tEOF,
+	}},
+	{"empty action", `$$@@`, []item{tLeftDelim, tRightDelim, tEOF}},
+	{"for", `$$for @@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
+	{"quote", `$$"abc \n\t\" "@@`, []item{tLeftDelim, tQuote, tRightDelim, tEOF}},
+	{"raw quote", "$$" + raw + "@@", []item{tLeftDelim, tRawQuote, tRightDelim, tEOF}},
+}
+
+var (
+	tLeftDelim  = item{itemLeftDelim, "$$"}
+	tRightDelim = item{itemRightDelim, "@@"}
+)
+
+func TestDelims(t *testing.T) {
+	for _, test := range lexDelimTests {
+		items := collect(&test, "$$", "@@")
+		if !reflect.DeepEqual(items, test.items) {
+			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+		}
+	}
+}
diff --git a/src/pkg/text/template/parse/node.go b/src/pkg/text/template/parse/node.go
new file mode 100644
index 0000000..0d030b8
--- /dev/null
+++ b/src/pkg/text/template/parse/node.go
@@ -0,0 +1,496 @@
+// Copyright 2011 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.
+
+// Parse nodes.
+
+package parse
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// A node is an element in the parse tree. The interface is trivial.
+type Node interface {
+	Type() NodeType
+	String() string
+}
+
+// NodeType identifies the type of a parse tree node.
+type NodeType int
+
+// Type returns itself and provides an easy default implementation
+// for embedding in a Node. Embedded in all non-trivial Nodes.
+func (t NodeType) Type() NodeType {
+	return t
+}
+
+const (
+	NodeText       NodeType = iota // Plain text.
+	NodeAction                     // A simple action such as field evaluation.
+	NodeBool                       // A boolean constant.
+	NodeCommand                    // An element of a pipeline.
+	NodeDot                        // The cursor, dot.
+	nodeElse                       // An else action. Not added to tree.
+	nodeEnd                        // An end action. Not added to tree.
+	NodeField                      // A field or method name.
+	NodeIdentifier                 // An identifier; always a function name.
+	NodeIf                         // An if action.
+	NodeList                       // A list of Nodes.
+	NodeNumber                     // A numerical constant.
+	NodePipe                       // A pipeline of commands.
+	NodeRange                      // A range action.
+	NodeString                     // A string constant.
+	NodeTemplate                   // A template invocation action.
+	NodeVariable                   // A $ variable.
+	NodeWith                       // A with action.
+)
+
+// Nodes.
+
+// ListNode holds a sequence of nodes.
+type ListNode struct {
+	NodeType
+	Nodes []Node // The element nodes in lexical order.
+}
+
+func newList() *ListNode {
+	return &ListNode{NodeType: NodeList}
+}
+
+func (l *ListNode) append(n Node) {
+	l.Nodes = append(l.Nodes, n)
+}
+
+func (l *ListNode) String() string {
+	b := new(bytes.Buffer)
+	for _, n := range l.Nodes {
+		fmt.Fprint(b, n)
+	}
+	return b.String()
+}
+
+// TextNode holds plain text.
+type TextNode struct {
+	NodeType
+	Text []byte // The text; may span newlines.
+}
+
+func newText(text string) *TextNode {
+	return &TextNode{NodeType: NodeText, Text: []byte(text)}
+}
+
+func (t *TextNode) String() string {
+	return fmt.Sprintf("%q", t.Text)
+}
+
+// PipeNode holds a pipeline with optional declaration
+type PipeNode struct {
+	NodeType
+	Line int             // The line number in the input.
+	Decl []*VariableNode // Variable declarations in lexical order.
+	Cmds []*CommandNode  // The commands in lexical order.
+}
+
+func newPipeline(line int, decl []*VariableNode) *PipeNode {
+	return &PipeNode{NodeType: NodePipe, Line: line, Decl: decl}
+}
+
+func (p *PipeNode) append(command *CommandNode) {
+	p.Cmds = append(p.Cmds, command)
+}
+
+func (p *PipeNode) String() string {
+	s := ""
+	if len(p.Decl) > 0 {
+		for i, v := range p.Decl {
+			if i > 0 {
+				s += ", "
+			}
+			s += v.String()
+		}
+		s += " := "
+	}
+	for i, c := range p.Cmds {
+		if i > 0 {
+			s += " | "
+		}
+		s += c.String()
+	}
+	return s
+}
+
+// ActionNode holds an action (something bounded by delimiters).
+// Control actions have their own nodes; ActionNode represents simple
+// ones such as field evaluations.
+type ActionNode struct {
+	NodeType
+	Line int       // The line number in the input.
+	Pipe *PipeNode // The pipeline in the action.
+}
+
+func newAction(line int, pipe *PipeNode) *ActionNode {
+	return &ActionNode{NodeType: NodeAction, Line: line, Pipe: pipe}
+}
+
+func (a *ActionNode) String() string {
+	return fmt.Sprintf("{{%s}}", a.Pipe)
+
+}
+
+// CommandNode holds a command (a pipeline inside an evaluating action).
+type CommandNode struct {
+	NodeType
+	Args []Node // Arguments in lexical order: Identifier, field, or constant.
+}
+
+func newCommand() *CommandNode {
+	return &CommandNode{NodeType: NodeCommand}
+}
+
+func (c *CommandNode) append(arg Node) {
+	c.Args = append(c.Args, arg)
+}
+
+func (c *CommandNode) String() string {
+	s := ""
+	for i, arg := range c.Args {
+		if i > 0 {
+			s += " "
+		}
+		s += arg.String()
+	}
+	return s
+}
+
+// IdentifierNode holds an identifier.
+type IdentifierNode struct {
+	NodeType
+	Ident string // The identifier's name.
+}
+
+// NewIdentifier returns a new IdentifierNode with the given identifier name.
+func NewIdentifier(ident string) *IdentifierNode {
+	return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
+}
+
+func (i *IdentifierNode) String() string {
+	return i.Ident
+}
+
+// VariableNode holds a list of variable names. The dollar sign is
+// part of the name.
+type VariableNode struct {
+	NodeType
+	Ident []string // Variable names in lexical order.
+}
+
+func newVariable(ident string) *VariableNode {
+	return &VariableNode{NodeType: NodeVariable, Ident: strings.Split(ident, ".")}
+}
+
+func (v *VariableNode) String() string {
+	s := ""
+	for i, id := range v.Ident {
+		if i > 0 {
+			s += "."
+		}
+		s += id
+	}
+	return s
+}
+
+// DotNode holds the special identifier '.'. It is represented by a nil pointer.
+type DotNode bool
+
+func newDot() *DotNode {
+	return nil
+}
+
+func (d *DotNode) Type() NodeType {
+	return NodeDot
+}
+
+func (d *DotNode) String() string {
+	return "."
+}
+
+// FieldNode holds a field (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The period is dropped from each ident.
+type FieldNode struct {
+	NodeType
+	Ident []string // The identifiers in lexical order.
+}
+
+func newField(ident string) *FieldNode {
+	return &FieldNode{NodeType: NodeField, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
+}
+
+func (f *FieldNode) String() string {
+	s := ""
+	for _, id := range f.Ident {
+		s += "." + id
+	}
+	return s
+}
+
+// BoolNode holds a boolean constant.
+type BoolNode struct {
+	NodeType
+	True bool // The value of the boolean constant.
+}
+
+func newBool(true bool) *BoolNode {
+	return &BoolNode{NodeType: NodeBool, True: true}
+}
+
+func (b *BoolNode) String() string {
+	if b.True {
+		return "true"
+	}
+	return "false"
+}
+
+// NumberNode holds a number: signed or unsigned integer, float, or complex.
+// The value is parsed and stored under all the types that can represent the value.
+// This simulates in a small amount of code the behavior of Go's ideal constants.
+type NumberNode struct {
+	NodeType
+	IsInt      bool       // Number has an integral value.
+	IsUint     bool       // Number has an unsigned integral value.
+	IsFloat    bool       // Number has a floating-point value.
+	IsComplex  bool       // Number is complex.
+	Int64      int64      // The signed integer value.
+	Uint64     uint64     // The unsigned integer value.
+	Float64    float64    // The floating-point value.
+	Complex128 complex128 // The complex value.
+	Text       string     // The original textual representation from the input.
+}
+
+func newNumber(text string, typ itemType) (*NumberNode, error) {
+	n := &NumberNode{NodeType: NodeNumber, Text: text}
+	switch typ {
+	case itemCharConstant:
+		rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
+		if err != nil {
+			return nil, err
+		}
+		if tail != "'" {
+			return nil, fmt.Errorf("malformed character constant: %s", text)
+		}
+		n.Int64 = int64(rune)
+		n.IsInt = true
+		n.Uint64 = uint64(rune)
+		n.IsUint = true
+		n.Float64 = float64(rune) // odd but those are the rules.
+		n.IsFloat = true
+		return n, nil
+	case itemComplex:
+		// fmt.Sscan can parse the pair, so let it do the work.
+		if _, err := fmt.Sscan(text, &n.Complex128); err != nil {
+			return nil, err
+		}
+		n.IsComplex = true
+		n.simplifyComplex()
+		return n, nil
+	}
+	// Imaginary constants can only be complex unless they are zero.
+	if len(text) > 0 && text[len(text)-1] == 'i' {
+		f, err := strconv.ParseFloat(text[:len(text)-1], 64)
+		if err == nil {
+			n.IsComplex = true
+			n.Complex128 = complex(0, f)
+			n.simplifyComplex()
+			return n, nil
+		}
+	}
+	// Do integer test first so we get 0x123 etc.
+	u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below.
+	if err == nil {
+		n.IsUint = true
+		n.Uint64 = u
+	}
+	i, err := strconv.ParseInt(text, 0, 64)
+	if err == nil {
+		n.IsInt = true
+		n.Int64 = i
+		if i == 0 {
+			n.IsUint = true // in case of -0.
+			n.Uint64 = u
+		}
+	}
+	// If an integer extraction succeeded, promote the float.
+	if n.IsInt {
+		n.IsFloat = true
+		n.Float64 = float64(n.Int64)
+	} else if n.IsUint {
+		n.IsFloat = true
+		n.Float64 = float64(n.Uint64)
+	} else {
+		f, err := strconv.ParseFloat(text, 64)
+		if err == nil {
+			n.IsFloat = true
+			n.Float64 = f
+			// If a floating-point extraction succeeded, extract the int if needed.
+			if !n.IsInt && float64(int64(f)) == f {
+				n.IsInt = true
+				n.Int64 = int64(f)
+			}
+			if !n.IsUint && float64(uint64(f)) == f {
+				n.IsUint = true
+				n.Uint64 = uint64(f)
+			}
+		}
+	}
+	if !n.IsInt && !n.IsUint && !n.IsFloat {
+		return nil, fmt.Errorf("illegal number syntax: %q", text)
+	}
+	return n, nil
+}
+
+// simplifyComplex pulls out any other types that are represented by the complex number.
+// These all require that the imaginary part be zero.
+func (n *NumberNode) simplifyComplex() {
+	n.IsFloat = imag(n.Complex128) == 0
+	if n.IsFloat {
+		n.Float64 = real(n.Complex128)
+		n.IsInt = float64(int64(n.Float64)) == n.Float64
+		if n.IsInt {
+			n.Int64 = int64(n.Float64)
+		}
+		n.IsUint = float64(uint64(n.Float64)) == n.Float64
+		if n.IsUint {
+			n.Uint64 = uint64(n.Float64)
+		}
+	}
+}
+
+func (n *NumberNode) String() string {
+	return n.Text
+}
+
+// StringNode holds a string constant. The value has been "unquoted".
+type StringNode struct {
+	NodeType
+	Quoted string // The original text of the string, with quotes.
+	Text   string // The string, after quote processing.
+}
+
+func newString(orig, text string) *StringNode {
+	return &StringNode{NodeType: NodeString, Quoted: orig, Text: text}
+}
+
+func (s *StringNode) String() string {
+	return s.Quoted
+}
+
+// endNode represents an {{end}} action. It is represented by a nil pointer.
+// It does not appear in the final parse tree.
+type endNode bool
+
+func newEnd() *endNode {
+	return nil
+}
+
+func (e *endNode) Type() NodeType {
+	return nodeEnd
+}
+
+func (e *endNode) String() string {
+	return "{{end}}"
+}
+
+// elseNode represents an {{else}} action. Does not appear in the final tree.
+type elseNode struct {
+	NodeType
+	Line int // The line number in the input.
+}
+
+func newElse(line int) *elseNode {
+	return &elseNode{NodeType: nodeElse, Line: line}
+}
+
+func (e *elseNode) Type() NodeType {
+	return nodeElse
+}
+
+func (e *elseNode) String() string {
+	return "{{else}}"
+}
+
+// BranchNode is the common representation of if, range, and with.
+type BranchNode struct {
+	NodeType
+	Line     int       // The line number in the input.
+	Pipe     *PipeNode // The pipeline to be evaluated.
+	List     *ListNode // What to execute if the value is non-empty.
+	ElseList *ListNode // What to execute if the value is empty (nil if absent).
+}
+
+func (b *BranchNode) String() string {
+	name := ""
+	switch b.NodeType {
+	case NodeIf:
+		name = "if"
+	case NodeRange:
+		name = "range"
+	case NodeWith:
+		name = "with"
+	default:
+		panic("unknown branch type")
+	}
+	if b.ElseList != nil {
+		return fmt.Sprintf("{{%s %s}}%s{{else}}%s{{end}}", name, b.Pipe, b.List, b.ElseList)
+	}
+	return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List)
+}
+
+// IfNode represents an {{if}} action and its commands.
+type IfNode struct {
+	BranchNode
+}
+
+func newIf(line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
+	return &IfNode{BranchNode{NodeType: NodeIf, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+// RangeNode represents a {{range}} action and its commands.
+type RangeNode struct {
+	BranchNode
+}
+
+func newRange(line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
+	return &RangeNode{BranchNode{NodeType: NodeRange, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+// WithNode represents a {{with}} action and its commands.
+type WithNode struct {
+	BranchNode
+}
+
+func newWith(line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
+	return &WithNode{BranchNode{NodeType: NodeWith, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+// TemplateNode represents a {{template}} action.
+type TemplateNode struct {
+	NodeType
+	Line int       // The line number in the input.
+	Name string    // The name of the template (unquoted).
+	Pipe *PipeNode // The command to evaluate as dot for the template.
+}
+
+func newTemplate(line int, name string, pipe *PipeNode) *TemplateNode {
+	return &TemplateNode{NodeType: NodeTemplate, Line: line, Name: name, Pipe: pipe}
+}
+
+func (t *TemplateNode) String() string {
+	if t.Pipe == nil {
+		return fmt.Sprintf("{{template %q}}", t.Name)
+	}
+	return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
+}
diff --git a/src/pkg/text/template/parse/parse.go b/src/pkg/text/template/parse/parse.go
new file mode 100644
index 0000000..4da7566
--- /dev/null
+++ b/src/pkg/text/template/parse/parse.go
@@ -0,0 +1,526 @@
+// Copyright 2011 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 parse builds parse trees for templates.  The grammar is defined
+// in the documents for the template package.
+package parse
+
+import (
+	"bytes"
+	"fmt"
+	"runtime"
+	"strconv"
+	"unicode"
+)
+
+// Tree is the representation of a single parsed template.
+type Tree struct {
+	Name string    // name of the template represented by the tree.
+	Root *ListNode // top-level root of the tree.
+	// Parsing only; cleared after parse.
+	funcs     []map[string]interface{}
+	lex       *lexer
+	token     [2]item // two-token lookahead for parser.
+	peekCount int
+	vars      []string // variables defined at the moment.
+}
+
+// Parse returns a map from template name to parse.Tree, created by parsing the
+// templates described in the argument string. The top-level template will be
+// given the specified name. If an error is encountered, parsing stops and an
+// empty map is returned with the error.
+func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) {
+	treeSet = make(map[string]*Tree)
+	_, err = New(name).Parse(text, leftDelim, rightDelim, treeSet, funcs...)
+	return
+}
+
+// next returns the next token.
+func (t *Tree) next() item {
+	if t.peekCount > 0 {
+		t.peekCount--
+	} else {
+		t.token[0] = t.lex.nextItem()
+	}
+	return t.token[t.peekCount]
+}
+
+// backup backs the input stream up one token.
+func (t *Tree) backup() {
+	t.peekCount++
+}
+
+// backup2 backs the input stream up two tokens
+func (t *Tree) backup2(t1 item) {
+	t.token[1] = t1
+	t.peekCount = 2
+}
+
+// peek returns but does not consume the next token.
+func (t *Tree) peek() item {
+	if t.peekCount > 0 {
+		return t.token[t.peekCount-1]
+	}
+	t.peekCount = 1
+	t.token[0] = t.lex.nextItem()
+	return t.token[0]
+}
+
+// Parsing.
+
+// New allocates a new parse tree with the given name.
+func New(name string, funcs ...map[string]interface{}) *Tree {
+	return &Tree{
+		Name:  name,
+		funcs: funcs,
+	}
+}
+
+// errorf formats the error and terminates processing.
+func (t *Tree) errorf(format string, args ...interface{}) {
+	t.Root = nil
+	format = fmt.Sprintf("template: %s:%d: %s", t.Name, t.lex.lineNumber(), format)
+	panic(fmt.Errorf(format, args...))
+}
+
+// error terminates processing.
+func (t *Tree) error(err error) {
+	t.errorf("%s", err)
+}
+
+// expect consumes the next token and guarantees it has the required type.
+func (t *Tree) expect(expected itemType, context string) item {
+	token := t.next()
+	if token.typ != expected {
+		t.errorf("expected %s in %s; got %s", expected, context, token)
+	}
+	return token
+}
+
+// expectEither consumes the next token and guarantees it has one of the required types.
+func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
+	token := t.next()
+	if token.typ != expected1 && token.typ != expected2 {
+		t.errorf("expected %s or %s in %s; got %s", expected1, expected2, context, token)
+	}
+	return token
+}
+
+// unexpected complains about the token and terminates processing.
+func (t *Tree) unexpected(token item, context string) {
+	t.errorf("unexpected %s in %s", token, context)
+}
+
+// recover is the handler that turns panics into returns from the top level of Parse.
+func (t *Tree) recover(errp *error) {
+	e := recover()
+	if e != nil {
+		if _, ok := e.(runtime.Error); ok {
+			panic(e)
+		}
+		if t != nil {
+			t.stopParse()
+		}
+		*errp = e.(error)
+	}
+	return
+}
+
+// startParse initializes the parser, using the lexer.
+func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) {
+	t.Root = nil
+	t.lex = lex
+	t.vars = []string{"$"}
+	t.funcs = funcs
+}
+
+// stopParse terminates parsing.
+func (t *Tree) stopParse() {
+	t.lex = nil
+	t.vars = nil
+	t.funcs = nil
+}
+
+// atEOF returns true if, possibly after spaces, we're at EOF.
+func (t *Tree) atEOF() bool {
+	for {
+		token := t.peek()
+		switch token.typ {
+		case itemEOF:
+			return true
+		case itemText:
+			for _, r := range token.val {
+				if !unicode.IsSpace(r) {
+					return false
+				}
+			}
+			t.next() // skip spaces.
+			continue
+		}
+		break
+	}
+	return false
+}
+
+// Parse parses the template definition string to construct a representation of
+// the template for execution. If either action delimiter string is empty, the
+// default ("{{" or "}}") is used. Embedded template definitions are added to
+// the treeSet map.
+func (t *Tree) Parse(s, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
+	defer t.recover(&err)
+	t.startParse(funcs, lex(t.Name, s, leftDelim, rightDelim))
+	t.parse(treeSet)
+	t.add(treeSet)
+	t.stopParse()
+	return t, nil
+}
+
+// add adds tree to the treeSet.
+func (t *Tree) add(treeSet map[string]*Tree) {
+	tree := treeSet[t.Name]
+	if tree == nil || IsEmptyTree(tree.Root) {
+		treeSet[t.Name] = t
+		return
+	}
+	if !IsEmptyTree(t.Root) {
+		t.errorf("template: multiple definition of template %q", t.Name)
+	}
+}
+
+// IsEmptyTree reports whether this tree (node) is empty of everything but space.
+func IsEmptyTree(n Node) bool {
+	switch n := n.(type) {
+	case *ActionNode:
+	case *IfNode:
+	case *ListNode:
+		for _, node := range n.Nodes {
+			if !IsEmptyTree(node) {
+				return false
+			}
+		}
+		return true
+	case *RangeNode:
+	case *TemplateNode:
+	case *TextNode:
+		return len(bytes.TrimSpace(n.Text)) == 0
+	case *WithNode:
+	default:
+		panic("unknown node: " + n.String())
+	}
+	return false
+}
+
+// parse is the top-level parser for a template, essentially the same
+// as itemList except it also parses {{define}} actions.
+// It runs to EOF.
+func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
+	t.Root = newList()
+	for t.peek().typ != itemEOF {
+		if t.peek().typ == itemLeftDelim {
+			delim := t.next()
+			if t.next().typ == itemDefine {
+				newT := New("definition") // name will be updated once we know it.
+				newT.startParse(t.funcs, t.lex)
+				newT.parseDefinition(treeSet)
+				continue
+			}
+			t.backup2(delim)
+		}
+		n := t.textOrAction()
+		if n.Type() == nodeEnd {
+			t.errorf("unexpected %s", n)
+		}
+		t.Root.append(n)
+	}
+	return nil
+}
+
+// parseDefinition parses a {{define}} ...  {{end}} template definition and
+// installs the definition in the treeSet map.  The "define" keyword has already
+// been scanned.
+func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
+	const context = "define clause"
+	name := t.expectOneOf(itemString, itemRawString, context)
+	var err error
+	t.Name, err = strconv.Unquote(name.val)
+	if err != nil {
+		t.error(err)
+	}
+	t.expect(itemRightDelim, context)
+	var end Node
+	t.Root, end = t.itemList()
+	if end.Type() != nodeEnd {
+		t.errorf("unexpected %s in %s", end, context)
+	}
+	t.stopParse()
+	t.add(treeSet)
+}
+
+// itemList:
+//	textOrAction*
+// Terminates at {{end}} or {{else}}, returned separately.
+func (t *Tree) itemList() (list *ListNode, next Node) {
+	list = newList()
+	for t.peek().typ != itemEOF {
+		n := t.textOrAction()
+		switch n.Type() {
+		case nodeEnd, nodeElse:
+			return list, n
+		}
+		list.append(n)
+	}
+	t.errorf("unexpected EOF")
+	return
+}
+
+// textOrAction:
+//	text | action
+func (t *Tree) textOrAction() Node {
+	switch token := t.next(); token.typ {
+	case itemText:
+		return newText(token.val)
+	case itemLeftDelim:
+		return t.action()
+	default:
+		t.unexpected(token, "input")
+	}
+	return nil
+}
+
+// Action:
+//	control
+//	command ("|" command)*
+// Left delim is past. Now get actions.
+// First word could be a keyword such as range.
+func (t *Tree) action() (n Node) {
+	switch token := t.next(); token.typ {
+	case itemElse:
+		return t.elseControl()
+	case itemEnd:
+		return t.endControl()
+	case itemIf:
+		return t.ifControl()
+	case itemRange:
+		return t.rangeControl()
+	case itemTemplate:
+		return t.templateControl()
+	case itemWith:
+		return t.withControl()
+	}
+	t.backup()
+	// Do not pop variables; they persist until "end".
+	return newAction(t.lex.lineNumber(), t.pipeline("command"))
+}
+
+// Pipeline:
+//	field or command
+//	pipeline "|" pipeline
+func (t *Tree) pipeline(context string) (pipe *PipeNode) {
+	var decl []*VariableNode
+	// Are there declarations?
+	for {
+		if v := t.peek(); v.typ == itemVariable {
+			t.next()
+			if next := t.peek(); next.typ == itemColonEquals || next.typ == itemChar {
+				t.next()
+				variable := newVariable(v.val)
+				if len(variable.Ident) != 1 {
+					t.errorf("illegal variable in declaration: %s", v.val)
+				}
+				decl = append(decl, variable)
+				t.vars = append(t.vars, v.val)
+				if next.typ == itemChar && next.val == "," {
+					if context == "range" && len(decl) < 2 {
+						continue
+					}
+					t.errorf("too many declarations in %s", context)
+				}
+			} else {
+				t.backup2(v)
+			}
+		}
+		break
+	}
+	pipe = newPipeline(t.lex.lineNumber(), decl)
+	for {
+		switch token := t.next(); token.typ {
+		case itemRightDelim:
+			if len(pipe.Cmds) == 0 {
+				t.errorf("missing value for %s", context)
+			}
+			return
+		case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
+			itemVariable, itemNumber, itemRawString, itemString:
+			t.backup()
+			pipe.append(t.command())
+		default:
+			t.unexpected(token, context)
+		}
+	}
+	return
+}
+
+func (t *Tree) parseControl(context string) (lineNum int, pipe *PipeNode, list, elseList *ListNode) {
+	lineNum = t.lex.lineNumber()
+	defer t.popVars(len(t.vars))
+	pipe = t.pipeline(context)
+	var next Node
+	list, next = t.itemList()
+	switch next.Type() {
+	case nodeEnd: //done
+	case nodeElse:
+		elseList, next = t.itemList()
+		if next.Type() != nodeEnd {
+			t.errorf("expected end; found %s", next)
+		}
+		elseList = elseList
+	}
+	return lineNum, pipe, list, elseList
+}
+
+// If:
+//	{{if pipeline}} itemList {{end}}
+//	{{if pipeline}} itemList {{else}} itemList {{end}}
+// If keyword is past.
+func (t *Tree) ifControl() Node {
+	return newIf(t.parseControl("if"))
+}
+
+// Range:
+//	{{range pipeline}} itemList {{end}}
+//	{{range pipeline}} itemList {{else}} itemList {{end}}
+// Range keyword is past.
+func (t *Tree) rangeControl() Node {
+	return newRange(t.parseControl("range"))
+}
+
+// With:
+//	{{with pipeline}} itemList {{end}}
+//	{{with pipeline}} itemList {{else}} itemList {{end}}
+// If keyword is past.
+func (t *Tree) withControl() Node {
+	return newWith(t.parseControl("with"))
+}
+
+// End:
+//	{{end}}
+// End keyword is past.
+func (t *Tree) endControl() Node {
+	t.expect(itemRightDelim, "end")
+	return newEnd()
+}
+
+// Else:
+//	{{else}}
+// Else keyword is past.
+func (t *Tree) elseControl() Node {
+	t.expect(itemRightDelim, "else")
+	return newElse(t.lex.lineNumber())
+}
+
+// Template:
+//	{{template stringValue pipeline}}
+// Template keyword is past.  The name must be something that can evaluate
+// to a string.
+func (t *Tree) templateControl() Node {
+	var name string
+	switch token := t.next(); token.typ {
+	case itemString, itemRawString:
+		s, err := strconv.Unquote(token.val)
+		if err != nil {
+			t.error(err)
+		}
+		name = s
+	default:
+		t.unexpected(token, "template invocation")
+	}
+	var pipe *PipeNode
+	if t.next().typ != itemRightDelim {
+		t.backup()
+		// Do not pop variables; they persist until "end".
+		pipe = t.pipeline("template")
+	}
+	return newTemplate(t.lex.lineNumber(), name, pipe)
+}
+
+// command:
+// space-separated arguments up to a pipeline character or right delimiter.
+// we consume the pipe character but leave the right delim to terminate the action.
+func (t *Tree) command() *CommandNode {
+	cmd := newCommand()
+Loop:
+	for {
+		switch token := t.next(); token.typ {
+		case itemRightDelim:
+			t.backup()
+			break Loop
+		case itemPipe:
+			break Loop
+		case itemError:
+			t.errorf("%s", token.val)
+		case itemIdentifier:
+			if !t.hasFunction(token.val) {
+				t.errorf("function %q not defined", token.val)
+			}
+			cmd.append(NewIdentifier(token.val))
+		case itemDot:
+			cmd.append(newDot())
+		case itemVariable:
+			cmd.append(t.useVar(token.val))
+		case itemField:
+			cmd.append(newField(token.val))
+		case itemBool:
+			cmd.append(newBool(token.val == "true"))
+		case itemCharConstant, itemComplex, itemNumber:
+			number, err := newNumber(token.val, token.typ)
+			if err != nil {
+				t.error(err)
+			}
+			cmd.append(number)
+		case itemString, itemRawString:
+			s, err := strconv.Unquote(token.val)
+			if err != nil {
+				t.error(err)
+			}
+			cmd.append(newString(token.val, s))
+		default:
+			t.unexpected(token, "command")
+		}
+	}
+	if len(cmd.Args) == 0 {
+		t.errorf("empty command")
+	}
+	return cmd
+}
+
+// hasFunction reports if a function name exists in the Tree's maps.
+func (t *Tree) hasFunction(name string) bool {
+	for _, funcMap := range t.funcs {
+		if funcMap == nil {
+			continue
+		}
+		if funcMap[name] != nil {
+			return true
+		}
+	}
+	return false
+}
+
+// popVars trims the variable list to the specified length
+func (t *Tree) popVars(n int) {
+	t.vars = t.vars[:n]
+}
+
+// useVar returns a node for a variable reference. It errors if the
+// variable is not defined.
+func (t *Tree) useVar(name string) Node {
+	v := newVariable(name)
+	for _, varName := range t.vars {
+		if varName == v.Ident[0] {
+			return v
+		}
+	}
+	t.errorf("undefined variable %q", v.Ident[0])
+	return nil
+}
diff --git a/src/pkg/text/template/parse/parse_test.go b/src/pkg/text/template/parse/parse_test.go
new file mode 100644
index 0000000..13c5548
--- /dev/null
+++ b/src/pkg/text/template/parse/parse_test.go
@@ -0,0 +1,286 @@
+// Copyright 2011 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 parse
+
+import (
+	"flag"
+	"fmt"
+	"testing"
+)
+
+var debug = flag.Bool("debug", false, "show the errors produced by the tests")
+
+type numberTest struct {
+	text      string
+	isInt     bool
+	isUint    bool
+	isFloat   bool
+	isComplex bool
+	int64
+	uint64
+	float64
+	complex128
+}
+
+var numberTests = []numberTest{
+	// basics
+	{"0", true, true, true, false, 0, 0, 0, 0},
+	{"-0", true, true, true, false, 0, 0, 0, 0}, // check that -0 is a uint.
+	{"73", true, true, true, false, 73, 73, 73, 0},
+	{"073", true, true, true, false, 073, 073, 073, 0},
+	{"0x73", true, true, true, false, 0x73, 0x73, 0x73, 0},
+	{"-73", true, false, true, false, -73, 0, -73, 0},
+	{"+73", true, false, true, false, 73, 0, 73, 0},
+	{"100", true, true, true, false, 100, 100, 100, 0},
+	{"1e9", true, true, true, false, 1e9, 1e9, 1e9, 0},
+	{"-1e9", true, false, true, false, -1e9, 0, -1e9, 0},
+	{"-1.2", false, false, true, false, 0, 0, -1.2, 0},
+	{"1e19", false, true, true, false, 0, 1e19, 1e19, 0},
+	{"-1e19", false, false, true, false, 0, 0, -1e19, 0},
+	{"4i", false, false, false, true, 0, 0, 0, 4i},
+	{"-1.2+4.2i", false, false, false, true, 0, 0, 0, -1.2 + 4.2i},
+	{"073i", false, false, false, true, 0, 0, 0, 73i}, // not octal!
+	// complex with 0 imaginary are float (and maybe integer)
+	{"0i", true, true, true, true, 0, 0, 0, 0},
+	{"-1.2+0i", false, false, true, true, 0, 0, -1.2, -1.2},
+	{"-12+0i", true, false, true, true, -12, 0, -12, -12},
+	{"13+0i", true, true, true, true, 13, 13, 13, 13},
+	// funny bases
+	{"0123", true, true, true, false, 0123, 0123, 0123, 0},
+	{"-0x0", true, true, true, false, 0, 0, 0, 0},
+	{"0xdeadbeef", true, true, true, false, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0},
+	// character constants
+	{`'a'`, true, true, true, false, 'a', 'a', 'a', 0},
+	{`'\n'`, true, true, true, false, '\n', '\n', '\n', 0},
+	{`'\\'`, true, true, true, false, '\\', '\\', '\\', 0},
+	{`'\''`, true, true, true, false, '\'', '\'', '\'', 0},
+	{`'\xFF'`, true, true, true, false, 0xFF, 0xFF, 0xFF, 0},
+	{`'パ'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
+	{`'\u30d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
+	{`'\U000030d1'`, true, true, true, false, 0x30d1, 0x30d1, 0x30d1, 0},
+	// some broken syntax
+	{text: "+-2"},
+	{text: "0x123."},
+	{text: "1e."},
+	{text: "0xi."},
+	{text: "1+2."},
+	{text: "'x"},
+	{text: "'xx'"},
+}
+
+func TestNumberParse(t *testing.T) {
+	for _, test := range numberTests {
+		// If fmt.Sscan thinks it's complex, it's complex.  We can't trust the output
+		// because imaginary comes out as a number.
+		var c complex128
+		typ := itemNumber
+		if test.text[0] == '\'' {
+			typ = itemCharConstant
+		} else {
+			_, err := fmt.Sscan(test.text, &c)
+			if err == nil {
+				typ = itemComplex
+			}
+		}
+		n, err := newNumber(test.text, typ)
+		ok := test.isInt || test.isUint || test.isFloat || test.isComplex
+		if ok && err != nil {
+			t.Errorf("unexpected error for %q: %s", test.text, err)
+			continue
+		}
+		if !ok && err == nil {
+			t.Errorf("expected error for %q", test.text)
+			continue
+		}
+		if !ok {
+			if *debug {
+				fmt.Printf("%s\n\t%s\n", test.text, err)
+			}
+			continue
+		}
+		if n.IsComplex != test.isComplex {
+			t.Errorf("complex incorrect for %q; should be %t", test.text, test.isComplex)
+		}
+		if test.isInt {
+			if !n.IsInt {
+				t.Errorf("expected integer for %q", test.text)
+			}
+			if n.Int64 != test.int64 {
+				t.Errorf("int64 for %q should be %d Is %d", test.text, test.int64, n.Int64)
+			}
+		} else if n.IsInt {
+			t.Errorf("did not expect integer for %q", test.text)
+		}
+		if test.isUint {
+			if !n.IsUint {
+				t.Errorf("expected unsigned integer for %q", test.text)
+			}
+			if n.Uint64 != test.uint64 {
+				t.Errorf("uint64 for %q should be %d Is %d", test.text, test.uint64, n.Uint64)
+			}
+		} else if n.IsUint {
+			t.Errorf("did not expect unsigned integer for %q", test.text)
+		}
+		if test.isFloat {
+			if !n.IsFloat {
+				t.Errorf("expected float for %q", test.text)
+			}
+			if n.Float64 != test.float64 {
+				t.Errorf("float64 for %q should be %g Is %g", test.text, test.float64, n.Float64)
+			}
+		} else if n.IsFloat {
+			t.Errorf("did not expect float for %q", test.text)
+		}
+		if test.isComplex {
+			if !n.IsComplex {
+				t.Errorf("expected complex for %q", test.text)
+			}
+			if n.Complex128 != test.complex128 {
+				t.Errorf("complex128 for %q should be %g Is %g", test.text, test.complex128, n.Complex128)
+			}
+		} else if n.IsComplex {
+			t.Errorf("did not expect complex for %q", test.text)
+		}
+	}
+}
+
+type parseTest struct {
+	name   string
+	input  string
+	ok     bool
+	result string // what the user would see in an error message.
+}
+
+const (
+	noError  = true
+	hasError = false
+)
+
+var parseTests = []parseTest{
+	{"empty", "", noError,
+		``},
+	{"comment", "{{/*\n\n\n*/}}", noError,
+		``},
+	{"spaces", " \t\n", noError,
+		`" \t\n"`},
+	{"text", "some text", noError,
+		`"some text"`},
+	{"emptyAction", "{{}}", hasError,
+		`{{}}`},
+	{"field", "{{.X}}", noError,
+		`{{.X}}`},
+	{"simple command", "{{printf}}", noError,
+		`{{printf}}`},
+	{"$ invocation", "{{$}}", noError,
+		"{{$}}"},
+	{"variable invocation", "{{with $x := 3}}{{$x 23}}{{end}}", noError,
+		"{{with $x := 3}}{{$x 23}}{{end}}"},
+	{"variable with fields", "{{$.I}}", noError,
+		"{{$.I}}"},
+	{"multi-word command", "{{printf `%d` 23}}", noError,
+		"{{printf `%d` 23}}"},
+	{"pipeline", "{{.X|.Y}}", noError,
+		`{{.X | .Y}}`},
+	{"pipeline with decl", "{{$x := .X|.Y}}", noError,
+		`{{$x := .X | .Y}}`},
+	{"simple if", "{{if .X}}hello{{end}}", noError,
+		`{{if .X}}"hello"{{end}}`},
+	{"if with else", "{{if .X}}true{{else}}false{{end}}", noError,
+		`{{if .X}}"true"{{else}}"false"{{end}}`},
+	{"simple range", "{{range .X}}hello{{end}}", noError,
+		`{{range .X}}"hello"{{end}}`},
+	{"chained field range", "{{range .X.Y.Z}}hello{{end}}", noError,
+		`{{range .X.Y.Z}}"hello"{{end}}`},
+	{"nested range", "{{range .X}}hello{{range .Y}}goodbye{{end}}{{end}}", noError,
+		`{{range .X}}"hello"{{range .Y}}"goodbye"{{end}}{{end}}`},
+	{"range with else", "{{range .X}}true{{else}}false{{end}}", noError,
+		`{{range .X}}"true"{{else}}"false"{{end}}`},
+	{"range over pipeline", "{{range .X|.M}}true{{else}}false{{end}}", noError,
+		`{{range .X | .M}}"true"{{else}}"false"{{end}}`},
+	{"range []int", "{{range .SI}}{{.}}{{end}}", noError,
+		`{{range .SI}}{{.}}{{end}}`},
+	{"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError,
+		`{{range .SI 1 -3.2i true false 'a'}}{{end}}`},
+	{"template", "{{template `x`}}", noError,
+		`{{template "x"}}`},
+	{"template with arg", "{{template `x` .Y}}", noError,
+		`{{template "x" .Y}}`},
+	{"with", "{{with .X}}hello{{end}}", noError,
+		`{{with .X}}"hello"{{end}}`},
+	{"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError,
+		`{{with .X}}"hello"{{else}}"goodbye"{{end}}`},
+	// Errors.
+	{"unclosed action", "hello{{range", hasError, ""},
+	{"unmatched end", "{{end}}", hasError, ""},
+	{"missing end", "hello{{range .x}}", hasError, ""},
+	{"missing end after else", "hello{{range .x}}{{else}}", hasError, ""},
+	{"undefined function", "hello{{undefined}}", hasError, ""},
+	{"undefined variable", "{{$x}}", hasError, ""},
+	{"variable undefined after end", "{{with $x := 4}}{{end}}{{$x}}", hasError, ""},
+	{"variable undefined in template", "{{template $v}}", hasError, ""},
+	{"declare with field", "{{with $x.Y := 4}}{{end}}", hasError, ""},
+	{"template with field ref", "{{template .X}}", hasError, ""},
+	{"template with var", "{{template $v}}", hasError, ""},
+	{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
+	{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
+	{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
+}
+
+var builtins = map[string]interface{}{
+	"printf": fmt.Sprintf,
+}
+
+func TestParse(t *testing.T) {
+	for _, test := range parseTests {
+		tmpl, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree), builtins)
+		switch {
+		case err == nil && !test.ok:
+			t.Errorf("%q: expected error; got none", test.name)
+			continue
+		case err != nil && test.ok:
+			t.Errorf("%q: unexpected error: %v", test.name, err)
+			continue
+		case err != nil && !test.ok:
+			// expected error, got one
+			if *debug {
+				fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
+			}
+			continue
+		}
+		result := tmpl.Root.String()
+		if result != test.result {
+			t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result)
+		}
+	}
+}
+
+type isEmptyTest struct {
+	name  string
+	input string
+	empty bool
+}
+
+var isEmptyTests = []isEmptyTest{
+	{"empty", ``, true},
+	{"nonempty", `hello`, false},
+	{"spaces only", " \t\n \t\n", true},
+	{"definition", `{{define "x"}}something{{end}}`, true},
+	{"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
+	{"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n}}", false},
+	{"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false},
+}
+
+func TestIsEmpty(t *testing.T) {
+	for _, test := range isEmptyTests {
+		tree, err := New("root").Parse(test.input, "", "", make(map[string]*Tree), nil)
+		if err != nil {
+			t.Errorf("%q: unexpected error: %v", test.name, err)
+			continue
+		}
+		if empty := IsEmptyTree(tree.Root); empty != test.empty {
+			t.Errorf("%q: expected %t got %t", test.name, test.empty, empty)
+		}
+	}
+}
diff --git a/src/pkg/text/template/template.go b/src/pkg/text/template/template.go
new file mode 100644
index 0000000..87e39d3
--- /dev/null
+++ b/src/pkg/text/template/template.go
@@ -0,0 +1,212 @@
+// Copyright 2011 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 template
+
+import (
+	"fmt"
+	"reflect"
+	"text/template/parse"
+)
+
+// common holds the information shared by related templates.
+type common struct {
+	tmpl map[string]*Template
+	// We use two maps, one for parsing and one for execution.
+	// This separation makes the API cleaner since it doesn't
+	// expose reflection to the client.
+	parseFuncs FuncMap
+	execFuncs  map[string]reflect.Value
+}
+
+// Template is the representation of a parsed template. The *parse.Tree
+// field is exported only for use by html/template and should be treated
+// as unexported by all other clients.
+type Template struct {
+	name string
+	*parse.Tree
+	*common
+	leftDelim  string
+	rightDelim string
+}
+
+// New allocates a new template with the given name.
+func New(name string) *Template {
+	return &Template{
+		name: name,
+	}
+}
+
+// Name returns the name of the template.
+func (t *Template) Name() string {
+	return t.name
+}
+
+// New allocates a new template associated with the given one and with the same
+// delimiters. The association, which is transitive, allows one template to
+// invoke another with a {{template}} action.
+func (t *Template) New(name string) *Template {
+	t.init()
+	return &Template{
+		name:       name,
+		common:     t.common,
+		leftDelim:  t.leftDelim,
+		rightDelim: t.rightDelim,
+	}
+}
+
+func (t *Template) init() {
+	if t.common == nil {
+		t.common = new(common)
+		t.tmpl = make(map[string]*Template)
+		t.parseFuncs = make(FuncMap)
+		t.execFuncs = make(map[string]reflect.Value)
+	}
+}
+
+// Clone returns a duplicate of the template, including all associated
+// templates. The actual representation is not copied, but the name space of
+// associated templates is, so further calls to Parse in the copy will add
+// templates to the copy but not to the original. Clone can be used to prepare
+// common templates and use them with variant definitions for other templates by
+// adding the variants after the clone is made.
+func (t *Template) Clone() *Template {
+	nt := t.copy(nil)
+	nt.init()
+	nt.tmpl[t.name] = nt
+	for k, v := range t.tmpl {
+		if k == t.name { // Already installed.
+			continue
+		}
+		// The associated templates share nt's common structure.
+		tmpl := v.copy(nt.common)
+		nt.tmpl[k] = tmpl
+	}
+	for k, v := range t.parseFuncs {
+		nt.parseFuncs[k] = v
+	}
+	for k, v := range t.execFuncs {
+		nt.execFuncs[k] = v
+	}
+	return nt
+}
+
+// copy returns a shallow copy of t, with common set to the argument.
+func (t *Template) copy(c *common) *Template {
+	nt := New(t.name)
+	nt.Tree = t.Tree
+	nt.common = c
+	nt.leftDelim = t.leftDelim
+	nt.rightDelim = t.rightDelim
+	return nt
+}
+
+// AddParseTree creates a new template with the name and parse tree
+// and associates it with t.
+func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
+	if t.tmpl[name] != nil {
+		return nil, fmt.Errorf("template: redefinition of template %q", name)
+	}
+	nt := t.New(name)
+	nt.Tree = tree
+	t.tmpl[name] = nt
+	return nt, nil
+}
+
+// Templates returns a slice of the templates associated with t, including t
+// itself.
+func (t *Template) Templates() []*Template {
+	// Return a slice so we don't expose the map.
+	m := make([]*Template, 0, len(t.tmpl))
+	for _, v := range t.tmpl {
+		m = append(m, v)
+	}
+	return m
+}
+
+// Delims sets the action delimiters to the specified strings, to be used in
+// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
+// definitions will inherit the settings. An empty delimiter stands for the
+// corresponding default: {{ or }}.
+// The return value is the template, so calls can be chained.
+func (t *Template) Delims(left, right string) *Template {
+	t.leftDelim = left
+	t.rightDelim = right
+	return t
+}
+
+// Funcs adds the elements of the argument map to the template's function map.
+// It panics if a value in the map is not a function with appropriate return
+// type. However, it is legal to overwrite elements of the map. The return
+// value is the template, so calls can be chained.
+func (t *Template) Funcs(funcMap FuncMap) *Template {
+	t.init()
+	addValueFuncs(t.execFuncs, funcMap)
+	addFuncs(t.parseFuncs, funcMap)
+	return t
+}
+
+// Lookup returns the template with the given name that is associated with t,
+// or nil if there is no such template.
+func (t *Template) Lookup(name string) *Template {
+	if t.common == nil {
+		return nil
+	}
+	return t.tmpl[name]
+}
+
+// Parse parses a string into a template. Nested template definitions will be
+// associated with the top-level template t. Parse may be called multiple times
+// to parse definitions of templates to associate with t. It is an error if a
+// resulting template is non-empty (contains content other than template
+// definitions) and would replace a non-empty template with the same name.
+// (In multiple calls to Parse with the same receiver template, only one call
+// can contain text other than space, comments, and template definitions.)
+func (t *Template) Parse(text string) (*Template, error) {
+	t.init()
+	trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)
+	if err != nil {
+		return nil, err
+	}
+	// Add the newly parsed trees, including the one for t, into our common structure.
+	for name, tree := range trees {
+		// If the name we parsed is the name of this template, overwrite this template.
+		// The associate method checks it's not a redefinition.
+		tmpl := t
+		if name != t.name {
+			tmpl = t.New(name)
+		}
+		// Even if t == tmpl, we need to install it in the common.tmpl map.
+		if err := t.associate(tmpl); err != nil {
+			return nil, err
+		}
+		tmpl.Tree = tree
+		tmpl.leftDelim = t.leftDelim
+		tmpl.rightDelim = t.rightDelim
+	}
+	return t, nil
+}
+
+// associate installs the new template into the group of templates associated
+// with t. It is an error to reuse a name except to overwrite an empty
+// template. The two are already known to share the common structure.
+func (t *Template) associate(new *Template) error {
+	if new.common != t.common {
+		panic("internal error: associate not common")
+	}
+	name := new.name
+	if old := t.tmpl[name]; old != nil {
+		oldIsEmpty := parse.IsEmptyTree(old.Root)
+		newIsEmpty := new.Tree != nil && parse.IsEmptyTree(new.Root)
+		if !oldIsEmpty && !newIsEmpty {
+			return fmt.Errorf("template: redefinition of template %q", name)
+		}
+		if newIsEmpty {
+			// Whether old is empty or not, new is empty; no reason to replace old.
+			return nil
+		}
+	}
+	t.tmpl[name] = new
+	return nil
+}
diff --git a/src/pkg/template/testdata/file1.tmpl b/src/pkg/text/template/testdata/file1.tmpl
similarity index 100%
rename from src/pkg/template/testdata/file1.tmpl
rename to src/pkg/text/template/testdata/file1.tmpl
diff --git a/src/pkg/template/testdata/file2.tmpl b/src/pkg/text/template/testdata/file2.tmpl
similarity index 100%
rename from src/pkg/template/testdata/file2.tmpl
rename to src/pkg/text/template/testdata/file2.tmpl
diff --git a/src/pkg/text/template/testdata/tmpl1.tmpl b/src/pkg/text/template/testdata/tmpl1.tmpl
new file mode 100644
index 0000000..b72b3a3
--- /dev/null
+++ b/src/pkg/text/template/testdata/tmpl1.tmpl
@@ -0,0 +1,3 @@
+template1
+{{define "x"}}x{{end}}
+{{template "y"}}
diff --git a/src/pkg/text/template/testdata/tmpl2.tmpl b/src/pkg/text/template/testdata/tmpl2.tmpl
new file mode 100644
index 0000000..16beba6
--- /dev/null
+++ b/src/pkg/text/template/testdata/tmpl2.tmpl
@@ -0,0 +1,3 @@
+template2
+{{define "y"}}y{{end}}
+{{template "x"}}
diff --git a/src/pkg/time/Makefile b/src/pkg/time/Makefile
index 473e7ea..9f61329 100644
--- a/src/pkg/time/Makefile
+++ b/src/pkg/time/Makefile
@@ -8,28 +8,28 @@ TARG=time
 GOFILES=\
 	format.go\
 	sleep.go\
-	sys.go\
 	tick.go\
 	time.go\
+	zoneinfo.go\
 
 GOFILES_freebsd=\
 	sys_unix.go\
-	zoneinfo_posix.go\
 	zoneinfo_unix.go\
 
 GOFILES_darwin=\
 	sys_unix.go\
-	zoneinfo_posix.go\
 	zoneinfo_unix.go\
 
 GOFILES_linux=\
 	sys_unix.go\
-	zoneinfo_posix.go\
+	zoneinfo_unix.go\
+
+GOFILES_netbsd=\
+	sys_unix.go\
 	zoneinfo_unix.go\
 
 GOFILES_openbsd=\
 	sys_unix.go\
-	zoneinfo_posix.go\
 	zoneinfo_unix.go\
 
 GOFILES_windows=\
@@ -38,7 +38,6 @@ GOFILES_windows=\
 
 GOFILES_plan9=\
 	sys_plan9.go\
-	zoneinfo_posix.go\
 	zoneinfo_plan9.go\
 
 GOFILES+=$(GOFILES_$(GOOS))
diff --git a/src/pkg/time/example_test.go b/src/pkg/time/example_test.go
new file mode 100644
index 0000000..153b1a3
--- /dev/null
+++ b/src/pkg/time/example_test.go
@@ -0,0 +1,58 @@
+// Copyright 2011 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 time_test
+
+import (
+	"fmt"
+	"time"
+)
+
+func expensiveCall() {}
+
+func ExampleDuration() {
+	t0 := time.Now()
+	expensiveCall()
+	t1 := time.Now()
+	fmt.Printf("The call took %v to run.\n", t1.Sub(t0))
+}
+
+var c chan int
+
+func handle(int) {}
+
+func ExampleAfter() {
+	select {
+	case m := <-c:
+		handle(m)
+	case <-time.After(5 * time.Minute):
+		fmt.Println("timed out")
+	}
+}
+
+func ExampleSleep() {
+	time.Sleep(100 * time.Millisecond)
+}
+
+func statusUpdate() string { return "" }
+
+func ExampleTick() {
+	c := time.Tick(1 * time.Minute)
+	for now := range c {
+		fmt.Printf("%v %s\n", now, statusUpdate())
+	}
+}
+
+func ExampleMonth() {
+	_, month, day := time.Now().Date()
+	if month == time.November && day == 10 {
+		fmt.Println("Happy Go day!")
+	}
+}
+
+// Go launched at Tue Nov 10 15:00:00 -0800 PST 2009
+func ExampleDate() {
+	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+	fmt.Printf("Go launched at %s\n", t.Local())
+}
diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go
index 0701cc9..76bf6ff 100644
--- a/src/pkg/time/format.go
+++ b/src/pkg/time/format.go
@@ -1,10 +1,10 @@
+// Copyright 2010 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 time
 
-import (
-	"bytes"
-	"os"
-	"strconv"
-)
+import "errors"
 
 const (
 	numeric = iota
@@ -45,12 +45,12 @@ const (
 	UnixDate = "Mon Jan _2 15:04:05 MST 2006"
 	RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
 	RFC822   = "02 Jan 06 1504 MST"
-	// RFC822 with Zulu time.
-	RFC822Z = "02 Jan 06 1504 -0700"
-	RFC850  = "Monday, 02-Jan-06 15:04:05 MST"
-	RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
-	RFC3339 = "2006-01-02T15:04:05Z07:00"
-	Kitchen = "3:04PM"
+	RFC822Z  = "02 Jan 06 1504 -0700" // RFC822 with numeric zone
+	RFC850   = "Monday, 02-Jan-06 15:04:05 MST"
+	RFC1123  = "Mon, 02 Jan 2006 15:04:05 MST"
+	RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
+	RFC3339  = "2006-01-02T15:04:05Z07:00"
+	Kitchen  = "3:04PM"
 	// Handy time stamps.
 	Stamp      = "Jan _2 15:04:05"
 	StampMilli = "Jan _2 15:04:05.000"
@@ -232,17 +232,78 @@ var longMonthNames = []string{
 	"December",
 }
 
-func lookup(tab []string, val string) (int, string, os.Error) {
+// match returns true if s1 and s2 match ignoring case.
+// It is assumed s1 and s2 are the same length.
+func match(s1, s2 string) bool {
+	for i := 0; i < len(s1); i++ {
+		c1 := s1[i]
+		c2 := s2[i]
+		if c1 != c2 {
+			// Switch to lower-case; 'a'-'A' is known to be a single bit.
+			c1 |= 'a' - 'A'
+			c2 |= 'a' - 'A'
+			if c1 != c2 || c1 < 'a' || c1 > 'z' {
+				return false
+			}
+		}
+	}
+	return true
+}
+
+func lookup(tab []string, val string) (int, string, error) {
 	for i, v := range tab {
-		if len(val) >= len(v) && val[0:len(v)] == v {
+		if len(val) >= len(v) && match(val[0:len(v)], v) {
 			return i, val[len(v):], nil
 		}
 	}
 	return -1, val, errBad
 }
 
+// Duplicates functionality in strconv, but avoids dependency.
+func itoa(x int) string {
+	var buf [32]byte
+	n := len(buf)
+	if x == 0 {
+		return "0"
+	}
+	u := uint(x)
+	if x < 0 {
+		u = -u
+	}
+	for u > 0 {
+		n--
+		buf[n] = byte(u%10 + '0')
+		u /= 10
+	}
+	if x < 0 {
+		n--
+		buf[n] = '-'
+	}
+	return string(buf[n:])
+}
+
+// Never printed, just needs to be non-nil for return by atoi.
+var atoiError = errors.New("time: invalid number")
+
+// Duplicates functionality in strconv, but avoids dependency.
+func atoi(s string) (x int, err error) {
+	neg := false
+	if s != "" && s[0] == '-' {
+		neg = true
+		s = s[1:]
+	}
+	x, rem, err := leadingInt(s)
+	if err != nil || rem != "" {
+		return 0, atoiError
+	}
+	if neg {
+		x = -x
+	}
+	return x, nil
+}
+
 func pad(i int, padding string) string {
-	s := strconv.Itoa(i)
+	s := itoa(i)
 	if i < 10 {
 		s = padding + s
 	}
@@ -255,7 +316,7 @@ func zeroPad(i int) string { return pad(i, "0") }
 func formatNano(nanosec, n int) string {
 	// User might give us bad data. Make sure it's positive and in range.
 	// They'll get nonsense output but it will have the right format.
-	s := strconv.Uitoa(uint(nanosec) % 1e9)
+	s := itoa(int(uint(nanosec) % 1e9))
 	// Zero pad left without fmt.
 	if len(s) < 9 {
 		s = "000000000"[:9-len(s)] + s
@@ -266,14 +327,38 @@ func formatNano(nanosec, n int) string {
 	return "." + s[:n]
 }
 
+// String returns the time formatted using the format string
+//	"Mon Jan _2 15:04:05 -0700 MST 2006"
+func (t Time) String() string {
+	return t.Format("Mon Jan _2 15:04:05 -0700 MST 2006")
+}
+
+type buffer []byte
+
+func (b *buffer) WriteString(s string) {
+	*b = append(*b, s...)
+}
+
+func (b *buffer) String() string {
+	return string([]byte(*b))
+}
+
 // Format returns a textual representation of the time value formatted
 // according to layout.  The layout defines the format by showing the
 // representation of a standard time, which is then used to describe
 // the time to be formatted.  Predefined layouts ANSIC, UnixDate,
 // RFC3339 and others describe standard representations. For more
 // information about the formats, see the documentation for ANSIC.
-func (t *Time) Format(layout string) string {
-	b := new(bytes.Buffer)
+func (t Time) Format(layout string) string {
+	var (
+		year  int = -1
+		month Month
+		day   int
+		hour  int = -1
+		min   int
+		sec   int
+		b     buffer
+	)
 	// Each iteration generates one std value.
 	for {
 		prefix, std, suffix := nextStdChunk(layout)
@@ -281,62 +366,92 @@ func (t *Time) Format(layout string) string {
 		if std == "" {
 			break
 		}
+
+		// Compute year, month, day if needed.
+		if year < 0 {
+			// Jan 01 02 2006
+			if a, z := std[0], std[len(std)-1]; a == 'J' || a == 'j' || z == '1' || z == '2' || z == '6' {
+				year, month, day = t.Date()
+			}
+		}
+
+		// Compute hour, minute, second if needed.
+		if hour < 0 {
+			// 03 04 05 15 pm
+			if z := std[len(std)-1]; z == '3' || z == '4' || z == '5' || z == 'm' || z == 'M' {
+				hour, min, sec = t.Clock()
+			}
+		}
+
 		var p string
 		switch std {
 		case stdYear:
-			p = zeroPad(int(t.Year % 100))
+			p = zeroPad(year % 100)
 		case stdLongYear:
-			p = strconv.Itoa64(t.Year)
+			p = itoa(year)
 		case stdMonth:
-			p = shortMonthNames[t.Month]
+			p = month.String()[:3]
 		case stdLongMonth:
-			p = longMonthNames[t.Month]
+			p = month.String()
 		case stdNumMonth:
-			p = strconv.Itoa(t.Month)
+			p = itoa(int(month))
 		case stdZeroMonth:
-			p = zeroPad(t.Month)
+			p = zeroPad(int(month))
 		case stdWeekDay:
-			p = shortDayNames[t.Weekday()]
+			p = t.Weekday().String()[:3]
 		case stdLongWeekDay:
-			p = longDayNames[t.Weekday()]
+			p = t.Weekday().String()
 		case stdDay:
-			p = strconv.Itoa(t.Day)
+			p = itoa(day)
 		case stdUnderDay:
-			p = pad(t.Day, " ")
+			p = pad(day, " ")
 		case stdZeroDay:
-			p = zeroPad(t.Day)
+			p = zeroPad(day)
 		case stdHour:
-			p = zeroPad(t.Hour)
+			p = zeroPad(hour)
 		case stdHour12:
 			// Noon is 12PM, midnight is 12AM.
-			hr := t.Hour % 12
+			hr := hour % 12
 			if hr == 0 {
 				hr = 12
 			}
-			p = strconv.Itoa(hr)
+			p = itoa(hr)
 		case stdZeroHour12:
 			// Noon is 12PM, midnight is 12AM.
-			hr := t.Hour % 12
+			hr := hour % 12
 			if hr == 0 {
 				hr = 12
 			}
 			p = zeroPad(hr)
 		case stdMinute:
-			p = strconv.Itoa(t.Minute)
+			p = itoa(min)
 		case stdZeroMinute:
-			p = zeroPad(t.Minute)
+			p = zeroPad(min)
 		case stdSecond:
-			p = strconv.Itoa(t.Second)
+			p = itoa(sec)
 		case stdZeroSecond:
-			p = zeroPad(t.Second)
+			p = zeroPad(sec)
+		case stdPM:
+			if hour >= 12 {
+				p = "PM"
+			} else {
+				p = "AM"
+			}
+		case stdpm:
+			if hour >= 12 {
+				p = "pm"
+			} else {
+				p = "am"
+			}
 		case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumColonTZ:
 			// Ugly special case.  We cheat and take the "Z" variants
 			// to mean "the time zone as formatted for ISO 8601".
-			if t.ZoneOffset == 0 && std[0] == 'Z' {
+			_, offset := t.Zone()
+			if offset == 0 && std[0] == 'Z' {
 				p = "Z"
 				break
 			}
-			zone := t.ZoneOffset / 60 // convert to minutes
+			zone := offset / 60 // convert to minutes
 			if zone < 0 {
 				p = "-"
 				zone = -zone
@@ -348,25 +463,14 @@ func (t *Time) Format(layout string) string {
 				p += ":"
 			}
 			p += zeroPad(zone % 60)
-		case stdPM:
-			if t.Hour >= 12 {
-				p = "PM"
-			} else {
-				p = "AM"
-			}
-		case stdpm:
-			if t.Hour >= 12 {
-				p = "pm"
-			} else {
-				p = "am"
-			}
 		case stdTZ:
-			if t.Zone != "" {
-				p = t.Zone
+			name, offset := t.Zone()
+			if name != "" {
+				p = name
 			} else {
 				// No time zone known for this time, but we must print one.
 				// Use the -0700 format.
-				zone := t.ZoneOffset / 60 // convert to minutes
+				zone := offset / 60 // convert to minutes
 				if zone < 0 {
 					p = "-"
 					zone = -zone
@@ -378,7 +482,7 @@ func (t *Time) Format(layout string) string {
 			}
 		default:
 			if len(std) >= 2 && std[0:2] == ".0" {
-				p = formatNano(t.Nanosecond, len(std)-1)
+				p = formatNano(t.Nanosecond(), len(std)-1)
 			}
 		}
 		b.WriteString(p)
@@ -387,15 +491,7 @@ func (t *Time) Format(layout string) string {
 	return b.String()
 }
 
-// String returns a Unix-style representation of the time value.
-func (t *Time) String() string {
-	if t == nil {
-		return "<nil>"
-	}
-	return t.Format(UnixDate)
-}
-
-var errBad = os.NewError("bad value for field") // placeholder not passed to user
+var errBad = errors.New("bad value for field") // placeholder not passed to user
 
 // ParseError describes a problem parsing a time string.
 type ParseError struct {
@@ -406,17 +502,21 @@ type ParseError struct {
 	Message    string
 }
 
-// String is the string representation of a ParseError.
-func (e *ParseError) String() string {
+func quote(s string) string {
+	return "\"" + s + "\""
+}
+
+// Error returns the string representation of a ParseError.
+func (e *ParseError) Error() string {
 	if e.Message == "" {
 		return "parsing time " +
-			strconv.Quote(e.Value) + " as " +
-			strconv.Quote(e.Layout) + ": cannot parse " +
-			strconv.Quote(e.ValueElem) + " as " +
-			strconv.Quote(e.LayoutElem)
+			quote(e.Value) + " as " +
+			quote(e.Layout) + ": cannot parse " +
+			quote(e.ValueElem) + " as " +
+			quote(e.LayoutElem)
 	}
 	return "parsing time " +
-		strconv.Quote(e.Value) + e.Message
+		quote(e.Value) + e.Message
 }
 
 // isDigit returns true if s[i] is a decimal digit, false if not or
@@ -432,7 +532,7 @@ func isDigit(s string, i int) bool {
 // getnum parses s[0:1] or s[0:2] (fixed forces the latter)
 // as a decimal integer and returns the integer and the
 // remainder of the string.
-func getnum(s string, fixed bool) (int, string, os.Error) {
+func getnum(s string, fixed bool) (int, string, error) {
 	if !isDigit(s, 0) {
 		return 0, s, errBad
 	}
@@ -454,7 +554,7 @@ func cutspace(s string) string {
 
 // skip removes the given prefix from value,
 // treating runs of space characters as equivalent.
-func skip(value, prefix string) (string, os.Error) {
+func skip(value, prefix string) (string, error) {
 	for len(prefix) > 0 {
 		if prefix[0] == ' ' {
 			if len(value) > 0 && value[0] != ' ' {
@@ -480,30 +580,42 @@ func skip(value, prefix string) (string, os.Error) {
 // representations.For more information about the formats, see the
 // documentation for ANSIC.
 //
-// Only those elements present in the value will be set in the returned time
-// structure.  Also, if the input string represents an inconsistent time
-// (such as having the wrong day of the week), the returned value will also
-// be inconsistent.  In any case, the elements of the returned time will be
-// sane: hours in 0..23, minutes in 0..59, day of month in 1..31, etc.
+// Elements omitted from the value are assumed to be zero, or when
+// zero is impossible, one, so parsing "3:04pm" returns the time
+// corresponding to Jan 1, year 0, 15:04:00 UTC.
 // Years must be in the range 0000..9999. The day of the week is checked
 // for syntax but it is otherwise ignored.
-func Parse(alayout, avalue string) (*Time, os.Error) {
-	var t Time
+func Parse(layout, value string) (Time, error) {
+	alayout, avalue := layout, value
 	rangeErrString := "" // set if a value is out of range
 	amSet := false       // do we need to subtract 12 from the hour for midnight?
 	pmSet := false       // do we need to add 12 to the hour?
-	layout, value := alayout, avalue
+
+	// Time being constructed.
+	var (
+		year       int
+		month      int = 1 // January
+		day        int = 1
+		hour       int
+		min        int
+		sec        int
+		nsec       int
+		z          *Location
+		zoneOffset int = -1
+		zoneName   string
+	)
+
 	// Each iteration processes one std value.
 	for {
-		var err os.Error
+		var err error
 		prefix, std, suffix := nextStdChunk(layout)
 		value, err = skip(value, prefix)
 		if err != nil {
-			return nil, &ParseError{alayout, avalue, prefix, value, ""}
+			return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
 		}
 		if len(std) == 0 {
 			if len(value) != 0 {
-				return nil, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
+				return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
 			}
 			break
 		}
@@ -516,11 +628,11 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 				break
 			}
 			p, value = value[0:2], value[2:]
-			t.Year, err = strconv.Atoi64(p)
-			if t.Year >= 69 { // Unix time starts Dec 31 1969 in some time zones
-				t.Year += 1900
+			year, err = atoi(p)
+			if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
+				year += 1900
 			} else {
-				t.Year += 2000
+				year += 2000
 			}
 		case stdLongYear:
 			if len(value) < 4 || !isDigit(value, 0) {
@@ -528,14 +640,14 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 				break
 			}
 			p, value = value[0:4], value[4:]
-			t.Year, err = strconv.Atoi64(p)
+			year, err = atoi(p)
 		case stdMonth:
-			t.Month, value, err = lookup(shortMonthNames, value)
+			month, value, err = lookup(shortMonthNames, value)
 		case stdLongMonth:
-			t.Month, value, err = lookup(longMonthNames, value)
+			month, value, err = lookup(longMonthNames, value)
 		case stdNumMonth, stdZeroMonth:
-			t.Month, value, err = getnum(value, std == stdZeroMonth)
-			if t.Month <= 0 || 12 < t.Month {
+			month, value, err = getnum(value, std == stdZeroMonth)
+			if month <= 0 || 12 < month {
 				rangeErrString = "month"
 			}
 		case stdWeekDay:
@@ -547,29 +659,28 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 			if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
 				value = value[1:]
 			}
-			t.Day, value, err = getnum(value, std == stdZeroDay)
-			if t.Day < 0 || 31 < t.Day {
-				// TODO: be more thorough in date check?
+			day, value, err = getnum(value, std == stdZeroDay)
+			if day < 0 || 31 < day {
 				rangeErrString = "day"
 			}
 		case stdHour:
-			t.Hour, value, err = getnum(value, false)
-			if t.Hour < 0 || 24 <= t.Hour {
+			hour, value, err = getnum(value, false)
+			if hour < 0 || 24 <= hour {
 				rangeErrString = "hour"
 			}
 		case stdHour12, stdZeroHour12:
-			t.Hour, value, err = getnum(value, std == stdZeroHour12)
-			if t.Hour < 0 || 12 < t.Hour {
+			hour, value, err = getnum(value, std == stdZeroHour12)
+			if hour < 0 || 12 < hour {
 				rangeErrString = "hour"
 			}
 		case stdMinute, stdZeroMinute:
-			t.Minute, value, err = getnum(value, std == stdZeroMinute)
-			if t.Minute < 0 || 60 <= t.Minute {
+			min, value, err = getnum(value, std == stdZeroMinute)
+			if min < 0 || 60 <= min {
 				rangeErrString = "minute"
 			}
 		case stdSecond, stdZeroSecond:
-			t.Second, value, err = getnum(value, std == stdZeroSecond)
-			if t.Second < 0 || 60 <= t.Second {
+			sec, value, err = getnum(value, std == stdZeroSecond)
+			if sec < 0 || 60 <= sec {
 				rangeErrString = "second"
 			}
 			// Special case: do we have a fractional second but no
@@ -584,16 +695,44 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 				n := 2
 				for ; n < len(value) && isDigit(value, n); n++ {
 				}
-				rangeErrString, err = t.parseNanoseconds(value, n)
+				nsec, rangeErrString, err = parseNanoseconds(value, n)
 				value = value[n:]
 			}
+		case stdPM:
+			if len(value) < 2 {
+				err = errBad
+				break
+			}
+			p, value = value[0:2], value[2:]
+			switch p {
+			case "PM":
+				pmSet = true
+			case "AM":
+				amSet = true
+			default:
+				err = errBad
+			}
+		case stdpm:
+			if len(value) < 2 {
+				err = errBad
+				break
+			}
+			p, value = value[0:2], value[2:]
+			switch p {
+			case "pm":
+				pmSet = true
+			case "am":
+				amSet = true
+			default:
+				err = errBad
+			}
 		case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ:
 			if std[0] == 'Z' && len(value) >= 1 && value[0] == 'Z' {
 				value = value[1:]
-				t.Zone = "UTC"
+				z = UTC
 				break
 			}
-			var sign, hh, mm string
+			var sign, hour, min string
 			if std == stdISO8601ColonTZ || std == stdNumColonTZ {
 				if len(value) < 6 {
 					err = errBad
@@ -603,65 +742,38 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 					err = errBad
 					break
 				}
-				sign, hh, mm, value = value[0:1], value[1:3], value[4:6], value[6:]
+				sign, hour, min, value = value[0:1], value[1:3], value[4:6], value[6:]
 			} else if std == stdNumShortTZ {
 				if len(value) < 3 {
 					err = errBad
 					break
 				}
-				sign, hh, mm, value = value[0:1], value[1:3], "00", value[3:]
+				sign, hour, min, value = value[0:1], value[1:3], "00", value[3:]
 			} else {
 				if len(value) < 5 {
 					err = errBad
 					break
 				}
-				sign, hh, mm, value = value[0:1], value[1:3], value[3:5], value[5:]
+				sign, hour, min, value = value[0:1], value[1:3], value[3:5], value[5:]
 			}
-			var hr, min int
-			hr, err = strconv.Atoi(hh)
+			var hr, mm int
+			hr, err = atoi(hour)
 			if err == nil {
-				min, err = strconv.Atoi(mm)
+				mm, err = atoi(min)
 			}
-			t.ZoneOffset = (hr*60 + min) * 60 // offset is in seconds
+			zoneOffset = (hr*60 + mm) * 60 // offset is in seconds
 			switch sign[0] {
 			case '+':
 			case '-':
-				t.ZoneOffset = -t.ZoneOffset
-			default:
-				err = errBad
-			}
-		case stdPM:
-			if len(value) < 2 {
-				err = errBad
-				break
-			}
-			p, value = value[0:2], value[2:]
-			switch p {
-			case "PM":
-				pmSet = true
-			case "AM":
-				amSet = true
-			default:
-				err = errBad
-			}
-		case stdpm:
-			if len(value) < 2 {
-				err = errBad
-				break
-			}
-			p, value = value[0:2], value[2:]
-			switch p {
-			case "pm":
-				pmSet = true
-			case "am":
-				amSet = true
+				zoneOffset = -zoneOffset
 			default:
 				err = errBad
 			}
 		case stdTZ:
 			// Does it look like a time zone?
 			if len(value) >= 3 && value[0:3] == "UTC" {
-				t.Zone, value = value[0:3], value[3:]
+				z = UTC
+				value = value[3:]
 				break
 			}
 
@@ -682,47 +794,86 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
 				break
 			}
 			// It's a valid format.
-			t.Zone = p
-			// Can we find its offset?
-			if offset, found := lookupByName(p); found {
-				t.ZoneOffset = offset
-			}
+			zoneName = p
 		default:
 			if len(value) < len(std) {
 				err = errBad
 				break
 			}
 			if len(std) >= 2 && std[0:2] == ".0" {
-				rangeErrString, err = t.parseNanoseconds(value, len(std))
+				nsec, rangeErrString, err = parseNanoseconds(value, len(std))
 				value = value[len(std):]
 			}
 		}
 		if rangeErrString != "" {
-			return nil, &ParseError{alayout, avalue, std, value, ": " + rangeErrString + " out of range"}
+			return Time{}, &ParseError{alayout, avalue, std, value, ": " + rangeErrString + " out of range"}
 		}
 		if err != nil {
-			return nil, &ParseError{alayout, avalue, std, value, ""}
+			return Time{}, &ParseError{alayout, avalue, std, value, ""}
 		}
 	}
-	if pmSet && t.Hour < 12 {
-		t.Hour += 12
-	} else if amSet && t.Hour == 12 {
-		t.Hour = 0
+	if pmSet && hour < 12 {
+		hour += 12
+	} else if amSet && hour == 12 {
+		hour = 0
+	}
+
+	// TODO: be more aggressive checking day?
+	if z != nil {
+		return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
+	}
+
+	t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
+	if zoneOffset != -1 {
+		t.sec -= int64(zoneOffset)
+
+		// Look for local zone with the given offset.
+		// If that zone was in effect at the given time, use it.
+		name, offset, _, _, _ := Local.lookup(t.sec + internalToUnix)
+		if offset == zoneOffset && (zoneName == "" || name == zoneName) {
+			t.loc = Local
+			return t, nil
+		}
+
+		// Otherwise create fake zone to record offset.
+		t.loc = FixedZone(zoneName, zoneOffset)
+		return t, nil
 	}
-	return &t, nil
+
+	if zoneName != "" {
+		// Look for local zone with the given offset.
+		// If that zone was in effect at the given time, use it.
+		offset, _, ok := Local.lookupName(zoneName)
+		if ok {
+			name, off, _, _, _ := Local.lookup(t.sec + internalToUnix - int64(offset))
+			if name == zoneName && off == offset {
+				t.sec -= int64(offset)
+				t.loc = Local
+				return t, nil
+			}
+		}
+
+		// Otherwise, create fake zone with unknown offset.
+		t.loc = FixedZone(zoneName, 0)
+		return t, nil
+	}
+
+	// Otherwise, fall back to UTC.
+	return t, nil
 }
 
-func (t *Time) parseNanoseconds(value string, nbytes int) (rangErrString string, err os.Error) {
+func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
 	if value[0] != '.' {
-		return "", errBad
+		err = errBad
+		return
 	}
-	var ns int
-	ns, err = strconv.Atoi(value[1:nbytes])
+	ns, err = atoi(value[1:nbytes])
 	if err != nil {
-		return "", err
+		return
 	}
 	if ns < 0 || 1e9 <= ns {
-		return "fractional second", nil
+		rangeErrString = "fractional second"
+		return
 	}
 	// We need nanoseconds, which means scaling by the number
 	// of missing digits in the format, maximum length 10. If it's
@@ -731,6 +882,128 @@ func (t *Time) parseNanoseconds(value string, nbytes int) (rangErrString string,
 	for i := 0; i < scaleDigits; i++ {
 		ns *= 10
 	}
-	t.Nanosecond = ns
 	return
 }
+
+var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
+
+// leadingInt consumes the leading [0-9]* from s.
+func leadingInt(s string) (x int, rem string, err error) {
+	i := 0
+	for ; i < len(s); i++ {
+		c := s[i]
+		if c < '0' || c > '9' {
+			break
+		}
+		if x >= (1<<31-10)/10 {
+			// overflow
+			return 0, "", errLeadingInt
+		}
+		x = x*10 + int(c) - '0'
+	}
+	return x, s[i:], nil
+}
+
+var unitMap = map[string]float64{
+	"ns": float64(Nanosecond),
+	"us": float64(Microsecond),
+	"µs": float64(Microsecond), // U+00B5 = micro symbol
+	"μs": float64(Microsecond), // U+03BC = Greek letter mu
+	"ms": float64(Millisecond),
+	"s":  float64(Second),
+	"m":  float64(Minute),
+	"h":  float64(Hour),
+}
+
+// ParseDuration parses a duration string.
+// A duration string is a possibly signed sequence of
+// decimal numbers, each with optional fraction and a unit suffix,
+// such as "300ms", "-1.5h" or "2h45m".
+// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
+func ParseDuration(s string) (Duration, error) {
+	// [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
+	orig := s
+	f := float64(0)
+	neg := false
+
+	// Consume [-+]?
+	if s != "" {
+		c := s[0]
+		if c == '-' || c == '+' {
+			neg = c == '-'
+			s = s[1:]
+		}
+	}
+	// Special case: if all that is left is "0", this is zero.
+	if s == "0" {
+		return 0, nil
+	}
+	if s == "" {
+		return 0, errors.New("time: invalid duration " + orig)
+	}
+	for s != "" {
+		g := float64(0) // this element of the sequence
+
+		var x int
+		var err error
+
+		// The next character must be [0-9.]
+		if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
+			return 0, errors.New("time: invalid duration " + orig)
+		}
+		// Consume [0-9]*
+		pl := len(s)
+		x, s, err = leadingInt(s)
+		if err != nil {
+			return 0, errors.New("time: invalid duration " + orig)
+		}
+		g = float64(x)
+		pre := pl != len(s) // whether we consumed anything before a period
+
+		// Consume (\.[0-9]*)?
+		post := false
+		if s != "" && s[0] == '.' {
+			s = s[1:]
+			pl := len(s)
+			x, s, err = leadingInt(s)
+			if err != nil {
+				return 0, errors.New("time: invalid duration " + orig)
+			}
+			scale := 1
+			for n := pl - len(s); n > 0; n-- {
+				scale *= 10
+			}
+			g += float64(x) / float64(scale)
+			post = pl != len(s)
+		}
+		if !pre && !post {
+			// no digits (e.g. ".s" or "-.s")
+			return 0, errors.New("time: invalid duration " + orig)
+		}
+
+		// Consume unit.
+		i := 0
+		for ; i < len(s); i++ {
+			c := s[i]
+			if c == '.' || ('0' <= c && c <= '9') {
+				break
+			}
+		}
+		if i == 0 {
+			return 0, errors.New("time: missing unit in duration " + orig)
+		}
+		u := s[:i]
+		s = s[i:]
+		unit, ok := unitMap[u]
+		if !ok {
+			return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
+		}
+
+		f += g * unit
+	}
+
+	if neg {
+		f = -f
+	}
+	return Duration(f), nil
+}
diff --git a/src/pkg/time/internal_test.go b/src/pkg/time/internal_test.go
index d7e7076..b753896 100644
--- a/src/pkg/time/internal_test.go
+++ b/src/pkg/time/internal_test.go
@@ -6,7 +6,8 @@ package time
 
 func init() {
 	// force US/Pacific for time zone tests
-	onceSetupZone.Do(setupTestingZone)
+	localOnce.Do(initTestingZone)
 }
 
 var Interrupt = interrupt
+var DaysIn = daysIn
diff --git a/src/pkg/time/sleep.go b/src/pkg/time/sleep.go
index 314622d..27820b0 100644
--- a/src/pkg/time/sleep.go
+++ b/src/pkg/time/sleep.go
@@ -4,174 +4,92 @@
 
 package time
 
-import (
-	"container/heap"
-	"sync"
-)
+// Sleep pauses the current goroutine for the duration d.
+func Sleep(d Duration)
 
-// The Timer type represents a single event.
-// When the Timer expires, the current time will be sent on C
-// unless the Timer represents an AfterFunc event.
-type Timer struct {
-	C <-chan int64
-	t int64       // The absolute time that the event should fire.
-	f func(int64) // The function to call when the event fires.
-	i int         // The event's index inside eventHeap.
-}
-
-type timerHeap []*Timer
-
-// forever is the absolute time (in ns) of an event that is forever away.
-const forever = 1 << 62
-
-// maxSleepTime is the maximum length of time that a sleeper
-// sleeps for before checking if it is defunct.
-const maxSleepTime = 1e9
-
-var (
-	// timerMutex guards the variables inside this var group.
-	timerMutex sync.Mutex
-
-	// timers holds a binary heap of pending events, terminated with a sentinel.
-	timers timerHeap
-
-	// currentSleeper is an ever-incrementing counter which represents
-	// the current sleeper. It allows older sleepers to detect that they are
-	// defunct and exit.
-	currentSleeper int64
-)
-
-func init() {
-	timers.Push(&Timer{t: forever}) // sentinel
+func nano() int64 {
+	sec, nsec := now()
+	return sec*1e9 + int64(nsec)
 }
 
-// NewTimer creates a new Timer that will send
-// the current time on its channel after at least ns nanoseconds.
-func NewTimer(ns int64) *Timer {
-	c := make(chan int64, 1)
-	e := after(ns, func(t int64) { c <- t })
-	e.C = c
-	return e
+// Interface to timers implemented in package runtime.
+// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
+type runtimeTimer struct {
+	i      int32
+	when   int64
+	period int64
+	f      func(int64, interface{})
+	arg    interface{}
 }
 
-// After waits at least ns nanoseconds before sending the current time
-// on the returned channel.
-// It is equivalent to NewTimer(ns).C.
-func After(ns int64) <-chan int64 {
-	return NewTimer(ns).C
-}
+func startTimer(*runtimeTimer)
+func stopTimer(*runtimeTimer) bool
 
-// AfterFunc waits at least ns nanoseconds before calling f
-// in its own goroutine. It returns a Timer that can
-// be used to cancel the call using its Stop method.
-func AfterFunc(ns int64, f func()) *Timer {
-	return after(ns, func(_ int64) {
-		go f()
-	})
+// The Timer type represents a single event.
+// When the Timer expires, the current time will be sent on C,
+// unless the Timer was created by AfterFunc.
+type Timer struct {
+	C <-chan Time
+	r runtimeTimer
 }
 
 // Stop prevents the Timer from firing.
 // It returns true if the call stops the timer, false if the timer has already
 // expired or stopped.
-func (e *Timer) Stop() (ok bool) {
-	timerMutex.Lock()
-	// Avoid removing the first event in the queue so that
-	// we don't start a new sleeper unnecessarily.
-	if e.i > 0 {
-		heap.Remove(timers, e.i)
-	}
-	ok = e.f != nil
-	e.f = nil
-	timerMutex.Unlock()
-	return
+func (t *Timer) Stop() (ok bool) {
+	return stopTimer(&t.r)
 }
 
-// after is the implementation of After and AfterFunc.
-// When the current time is after ns, it calls f with the current time.
-// It assumes that f will not block.
-func after(ns int64, f func(int64)) (e *Timer) {
-	now := Nanoseconds()
-	t := now + ns
-	if ns > 0 && t < now {
-		panic("time: time overflow")
-	}
-	timerMutex.Lock()
-	t0 := timers[0].t
-	e = &Timer{nil, t, f, -1}
-	heap.Push(timers, e)
-	// Start a new sleeper if the new event is before
-	// the first event in the queue. If the length of time
-	// until the new event is at least maxSleepTime,
-	// then we're guaranteed that the sleeper will wake up
-	// in time to service it, so no new sleeper is needed.
-	if t0 > t && (t0 == forever || ns < maxSleepTime) {
-		currentSleeper++
-		go sleeper(currentSleeper)
+// NewTimer creates a new Timer that will send
+// the current time on its channel after at least duration d.
+func NewTimer(d Duration) *Timer {
+	c := make(chan Time, 1)
+	t := &Timer{
+		C: c,
+		r: runtimeTimer{
+			when: nano() + int64(d),
+			f:    sendTime,
+			arg:  c,
+		},
 	}
-	timerMutex.Unlock()
-	return
+	startTimer(&t.r)
+	return t
 }
 
-// sleeper continually looks at the earliest event in the queue, waits until it happens,
-// then removes any events in the queue that are due. It stops when the queue
-// is empty or when another sleeper has been started.
-func sleeper(sleeperId int64) {
-	timerMutex.Lock()
-	e := timers[0]
-	t := Nanoseconds()
-	for e.t != forever {
-		if dt := e.t - t; dt > 0 {
-			if dt > maxSleepTime {
-				dt = maxSleepTime
-			}
-			timerMutex.Unlock()
-			sysSleep(dt)
-			timerMutex.Lock()
-			if currentSleeper != sleeperId {
-				// Another sleeper has been started, making this one redundant.
-				break
-			}
-		}
-		e = timers[0]
-		t = Nanoseconds()
-		for t >= e.t {
-			if e.f != nil {
-				e.f(t)
-				e.f = nil
-			}
-			heap.Pop(timers)
-			e = timers[0]
-		}
+func sendTime(now int64, c interface{}) {
+	// Non-blocking send of time on c.
+	// Used in NewTimer, it cannot block anyway (buffer).
+	// Used in NewTicker, dropping sends on the floor is
+	// the desired behavior when the reader gets behind,
+	// because the sends are periodic.
+	select {
+	case c.(chan Time) <- Unix(0, now):
+	default:
 	}
-	timerMutex.Unlock()
-}
-
-func (timerHeap) Len() int {
-	return len(timers)
-}
-
-func (timerHeap) Less(i, j int) bool {
-	return timers[i].t < timers[j].t
 }
 
-func (timerHeap) Swap(i, j int) {
-	timers[i], timers[j] = timers[j], timers[i]
-	timers[i].i = i
-	timers[j].i = j
+// After waits for the duration to elapse and then sends the current time
+// on the returned channel.
+// It is equivalent to NewTimer(d).C.
+func After(d Duration) <-chan Time {
+	return NewTimer(d).C
 }
 
-func (timerHeap) Push(x interface{}) {
-	e := x.(*Timer)
-	e.i = len(timers)
-	timers = append(timers, e)
+// AfterFunc waits for the duration to elapse and then calls f
+// in its own goroutine. It returns a Timer that can
+// be used to cancel the call using its Stop method.
+func AfterFunc(d Duration, f func()) *Timer {
+	t := &Timer{
+		r: runtimeTimer{
+			when: nano() + int64(d),
+			f:    goFunc,
+			arg:  f,
+		},
+	}
+	startTimer(&t.r)
+	return t
 }
 
-func (timerHeap) Pop() interface{} {
-	// TODO: possibly shrink array.
-	n := len(timers) - 1
-	e := timers[n]
-	timers[n] = nil
-	timers = timers[0:n]
-	e.i = -1
-	return e
+func goFunc(now int64, arg interface{}) {
+	go arg.(func())()
 }
diff --git a/src/pkg/time/sleep_test.go b/src/pkg/time/sleep_test.go
index b6b88f6..b12a5a1 100644
--- a/src/pkg/time/sleep_test.go
+++ b/src/pkg/time/sleep_test.go
@@ -5,24 +5,26 @@
 package time_test
 
 import (
+	"errors"
 	"fmt"
-	"os"
-	"testing"
+	"runtime"
 	"sort"
+	"sync/atomic"
+	"testing"
 	. "time"
 )
 
 func TestSleep(t *testing.T) {
-	const delay = int64(100e6)
+	const delay = 100 * Millisecond
 	go func() {
 		Sleep(delay / 2)
 		Interrupt()
 	}()
-	start := Nanoseconds()
+	start := Now()
 	Sleep(delay)
-	duration := Nanoseconds() - start
+	duration := Now().Sub(start)
 	if duration < delay {
-		t.Fatalf("Sleep(%d) slept for only %d ns", delay, duration)
+		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
 	}
 }
 
@@ -37,7 +39,7 @@ func TestAfterFunc(t *testing.T) {
 		i--
 		if i >= 0 {
 			AfterFunc(0, f)
-			Sleep(1e9)
+			Sleep(1 * Second)
 		} else {
 			c <- true
 		}
@@ -47,6 +49,23 @@ func TestAfterFunc(t *testing.T) {
 	<-c
 }
 
+func TestAfterStress(t *testing.T) {
+	stop := uint32(0)
+	go func() {
+		for atomic.LoadUint32(&stop) == 0 {
+			runtime.GC()
+			// Need to yield, because otherwise
+			// the main goroutine will never set the stop flag.
+			runtime.Gosched()
+		}
+	}()
+	c := Tick(1)
+	for i := 0; i < 100; i++ {
+		<-c
+	}
+	atomic.StoreUint32(&stop, 1)
+}
+
 func BenchmarkAfterFunc(b *testing.B) {
 	i := b.N
 	c := make(chan bool)
@@ -72,47 +91,45 @@ func BenchmarkAfter(b *testing.B) {
 
 func BenchmarkStop(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		NewTimer(1e9).Stop()
+		NewTimer(1 * Second).Stop()
 	}
 }
 
 func TestAfter(t *testing.T) {
-	const delay = int64(100e6)
-	start := Nanoseconds()
+	const delay = 100 * Millisecond
+	start := Now()
 	end := <-After(delay)
-	if duration := Nanoseconds() - start; duration < delay {
-		t.Fatalf("After(%d) slept for only %d ns", delay, duration)
+	if duration := Now().Sub(start); duration < delay {
+		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
 	}
-	if min := start + delay; end < min {
-		t.Fatalf("After(%d) expect >= %d, got %d", delay, min, end)
+	if min := start.Add(delay); end.Before(min) {
+		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
 	}
 }
 
 func TestAfterTick(t *testing.T) {
 	const (
-		Delta = 100 * 1e6
+		Delta = 100 * Millisecond
 		Count = 10
 	)
-	t0 := Nanoseconds()
+	t0 := Now()
 	for i := 0; i < Count; i++ {
 		<-After(Delta)
 	}
-	t1 := Nanoseconds()
-	ns := t1 - t0
-	target := int64(Delta * Count)
-	slop := target * 2 / 10
-	if ns < target-slop || ns > target+slop {
-		t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target))
+	t1 := Now()
+	d := t1.Sub(t0)
+	target := Delta * Count
+	if d < target*9/10 || d > target*30/10 {
+		t.Fatalf("%d ticks of %s took %s, expected %s", Count, Delta, d, target)
 	}
 }
 
 func TestAfterStop(t *testing.T) {
-	const msec = 1e6
-	AfterFunc(100*msec, func() {})
-	t0 := NewTimer(50 * msec)
+	AfterFunc(100*Millisecond, func() {})
+	t0 := NewTimer(50 * Millisecond)
 	c1 := make(chan bool, 1)
-	t1 := AfterFunc(150*msec, func() { c1 <- true })
-	c2 := After(200 * msec)
+	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
+	c2 := After(200 * Millisecond)
 	if !t0.Stop() {
 		t.Fatalf("failed to stop event 0")
 	}
@@ -136,7 +153,7 @@ func TestAfterQueuing(t *testing.T) {
 	// This test flakes out on some systems,
 	// so we'll try it a few times before declaring it a failure.
 	const attempts = 3
-	err := os.NewError("!=nil")
+	err := errors.New("!=nil")
 	for i := 0; i < attempts && err != nil; i++ {
 		if err = testAfterQueuing(t); err != nil {
 			t.Logf("attempt %v failed: %v", i, err)
@@ -151,38 +168,53 @@ var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}
 
 type afterResult struct {
 	slot int
-	t    int64
+	t    Time
 }
 
-func await(slot int, result chan<- afterResult, ac <-chan int64) {
+func await(slot int, result chan<- afterResult, ac <-chan Time) {
 	result <- afterResult{slot, <-ac}
 }
 
-func testAfterQueuing(t *testing.T) os.Error {
+func testAfterQueuing(t *testing.T) error {
 	const (
-		Delta = 100 * 1e6
+		Delta = 100 * Millisecond
 	)
 	// make the result channel buffered because we don't want
 	// to depend on channel queueing semantics that might
 	// possibly change in the future.
 	result := make(chan afterResult, len(slots))
 
-	t0 := Nanoseconds()
+	t0 := Now()
 	for _, slot := range slots {
-		go await(slot, result, After(int64(slot)*Delta))
+		go await(slot, result, After(Duration(slot)*Delta))
 	}
 	sort.Ints(slots)
 	for _, slot := range slots {
 		r := <-result
 		if r.slot != slot {
-			return fmt.Errorf("after queue got slot %d, expected %d", r.slot, slot)
+			return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
 		}
-		ns := r.t - t0
-		target := int64(slot * Delta)
-		slop := int64(Delta) / 4
-		if ns < target-slop || ns > target+slop {
-			return fmt.Errorf("after queue slot %d arrived at %g, expected [%g,%g]", slot, float64(ns), float64(target-slop), float64(target+slop))
+		dt := r.t.Sub(t0)
+		target := Duration(slot) * Delta
+		if dt < target-Delta/2 || dt > target+Delta*10 {
+			return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
 		}
 	}
 	return nil
 }
+
+func TestTimerStopStress(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+	for i := 0; i < 100; i++ {
+		go func(i int) {
+			timer := AfterFunc(2*Second, func() {
+				t.Fatalf("timer %d was not stopped", i)
+			})
+			Sleep(1 * Second)
+			timer.Stop()
+		}(i)
+	}
+	Sleep(3 * Second)
+}
diff --git a/src/pkg/time/sys.go b/src/pkg/time/sys.go
deleted file mode 100644
index 9fde3b3..0000000
--- a/src/pkg/time/sys.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package time
-
-import "os"
-
-// Seconds reports the number of seconds since the Unix epoch,
-// January 1, 1970 00:00:00 UTC.
-func Seconds() int64 {
-	sec, _, err := os.Time()
-	if err != nil {
-		panic(err)
-	}
-	return sec
-}
-
-// Nanoseconds reports the number of nanoseconds since the Unix epoch,
-// January 1, 1970 00:00:00 UTC.
-func Nanoseconds() int64 {
-	sec, nsec, err := os.Time()
-	if err != nil {
-		panic(err)
-	}
-	return sec*1e9 + nsec
-}
-
-// Sleep pauses the current goroutine for at least ns nanoseconds.
-// Higher resolution sleeping may be provided by syscall.Nanosleep 
-// on some operating systems.
-func Sleep(ns int64) os.Error {
-	_, err := sleep(Nanoseconds(), ns)
-	return err
-}
-
-// sleep takes the current time and a duration,
-// pauses for at least ns nanoseconds, and
-// returns the current time and an error.
-func sleep(t, ns int64) (int64, os.Error) {
-	// TODO(cw): use monotonic-time once it's available
-	end := t + ns
-	for t < end {
-		err := sysSleep(end - t)
-		if err != nil {
-			return 0, err
-		}
-		t = Nanoseconds()
-	}
-	return t, nil
-}
diff --git a/src/pkg/time/sys_plan9.go b/src/pkg/time/sys_plan9.go
index 9ae0161..c7cfa79 100644
--- a/src/pkg/time/sys_plan9.go
+++ b/src/pkg/time/sys_plan9.go
@@ -2,22 +2,39 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package time
+// +build plan9
 
-import (
-	"os"
-	"syscall"
-)
+package time
 
-func sysSleep(t int64) os.Error {
-	err := syscall.Sleep(t)
-	if err != nil {
-		return os.NewSyscallError("sleep", err)
-	}
-	return nil
-}
+import "syscall"
 
 // for testing: whatever interrupts a sleep
 func interrupt() {
 	// cannot predict pid, don't want to kill group
 }
+
+// readFile reads and returns the content of the named file.
+// It is a trivial implementation of ioutil.ReadFile, reimplemented
+// here to avoid depending on io/ioutil or os.
+func readFile(name string) ([]byte, error) {
+	f, err := syscall.Open(name, syscall.O_RDONLY)
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.Close(f)
+	var (
+		buf [4096]byte
+		ret []byte
+		n   int
+	)
+	for {
+		n, err = syscall.Read(f, buf[:])
+		if n > 0 {
+			ret = append(ret, buf[:n]...)
+		}
+		if n == 0 || err != nil {
+			break
+		}
+	}
+	return ret, err
+}
diff --git a/src/pkg/time/sys_unix.go b/src/pkg/time/sys_unix.go
index 0119bdf..56a7414 100644
--- a/src/pkg/time/sys_unix.go
+++ b/src/pkg/time/sys_unix.go
@@ -2,24 +2,39 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 package time
 
-import (
-	"os"
-	"syscall"
-)
-
-func sysSleep(t int64) os.Error {
-	errno := syscall.Sleep(t)
-	if errno != 0 && errno != syscall.EINTR {
-		return os.NewSyscallError("sleep", errno)
-	}
-	return nil
-}
+import "syscall"
 
 // for testing: whatever interrupts a sleep
 func interrupt() {
-	syscall.Kill(os.Getpid(), syscall.SIGCHLD)
+	syscall.Kill(syscall.Getpid(), syscall.SIGCHLD)
+}
+
+// readFile reads and returns the content of the named file.
+// It is a trivial implementation of ioutil.ReadFile, reimplemented
+// here to avoid depending on io/ioutil or os.
+func readFile(name string) ([]byte, error) {
+	f, err := syscall.Open(name, syscall.O_RDONLY, 0)
+	if err != nil {
+		return nil, err
+	}
+	defer syscall.Close(f)
+	var (
+		buf [4096]byte
+		ret []byte
+		n   int
+	)
+	for {
+		n, err = syscall.Read(f, buf[:])
+		if n > 0 {
+			ret = append(ret, buf[:n]...)
+		}
+		if n == 0 || err != nil {
+			break
+		}
+	}
+	return ret, err
 }
diff --git a/src/pkg/time/sys_windows.go b/src/pkg/time/sys_windows.go
index feff90b..8c7242f 100644
--- a/src/pkg/time/sys_windows.go
+++ b/src/pkg/time/sys_windows.go
@@ -4,19 +4,6 @@
 
 package time
 
-import (
-	"os"
-	"syscall"
-)
-
-func sysSleep(t int64) os.Error {
-	errno := syscall.Sleep(t)
-	if errno != 0 && errno != syscall.EINTR {
-		return os.NewSyscallError("sleep", errno)
-	}
-	return nil
-}
-
 // for testing: whatever interrupts a sleep
 func interrupt() {
 }
diff --git a/src/pkg/time/tick.go b/src/pkg/time/tick.go
index 852bae9..8c6b9bc 100644
--- a/src/pkg/time/tick.go
+++ b/src/pkg/time/tick.go
@@ -4,174 +4,50 @@
 
 package time
 
-import (
-	"os"
-	"sync"
-)
+import "errors"
 
 // A Ticker holds a synchronous channel that delivers `ticks' of a clock
 // at intervals.
 type Ticker struct {
-	C        <-chan int64 // The channel on which the ticks are delivered.
-	c        chan<- int64 // The same channel, but the end we use.
-	ns       int64
-	shutdown chan bool // Buffered channel used to signal shutdown.
-	nextTick int64
-	next     *Ticker
+	C <-chan Time // The channel on which the ticks are delivered.
+	r runtimeTimer
+}
+
+// NewTicker returns a new Ticker containing a channel that will send the
+// time with a period specified by the duration argument.
+// It adjusts the intervals or drops ticks to make up for slow receivers.
+// The duration d must be greater than zero; if not, NewTicker will panic.
+func NewTicker(d Duration) *Ticker {
+	if d <= 0 {
+		panic(errors.New("non-positive interval for NewTicker"))
+	}
+	// Give the channel a 1-element time buffer.
+	// If the client falls behind while reading, we drop ticks
+	// on the floor until the client catches up.
+	c := make(chan Time, 1)
+	t := &Ticker{
+		C: c,
+		r: runtimeTimer{
+			when:   nano() + int64(d),
+			period: int64(d),
+			f:      sendTime,
+			arg:    c,
+		},
+	}
+	startTimer(&t.r)
+	return t
 }
 
 // Stop turns off a ticker.  After Stop, no more ticks will be sent.
 func (t *Ticker) Stop() {
-	select {
-	case t.shutdown <- true:
-		// ok
-	default:
-		// Stop in progress already
-	}
+	stopTimer(&t.r)
 }
 
 // Tick is a convenience wrapper for NewTicker providing access to the ticking
 // channel only.  Useful for clients that have no need to shut down the ticker.
-func Tick(ns int64) <-chan int64 {
-	if ns <= 0 {
+func Tick(d Duration) <-chan Time {
+	if d <= 0 {
 		return nil
 	}
-	return NewTicker(ns).C
-}
-
-type alarmer struct {
-	wakeUp   chan bool // wakeup signals sent/received here
-	wakeMeAt chan int64
-	wakeTime int64
-}
-
-// Set alarm to go off at time ns, if not already set earlier.
-func (a *alarmer) set(ns int64) {
-	switch {
-	case a.wakeTime > ns:
-		// Next tick we expect is too late; shut down the late runner
-		// and (after fallthrough) start a new wakeLoop.
-		close(a.wakeMeAt)
-		fallthrough
-	case a.wakeMeAt == nil:
-		// There's no wakeLoop, start one.
-		a.wakeMeAt = make(chan int64)
-		a.wakeUp = make(chan bool, 1)
-		go wakeLoop(a.wakeMeAt, a.wakeUp)
-		fallthrough
-	case a.wakeTime == 0:
-		// Nobody else is waiting; it's just us.
-		a.wakeTime = ns
-		a.wakeMeAt <- ns
-	default:
-		// There's already someone scheduled.
-	}
-}
-
-// Channel to notify tickerLoop of new Tickers being created.
-var newTicker chan *Ticker
-
-func startTickerLoop() {
-	newTicker = make(chan *Ticker)
-	go tickerLoop()
-}
-
-// wakeLoop delivers ticks at scheduled times, sleeping until the right moment.
-// If another, earlier Ticker is created while it sleeps, tickerLoop() will start a new
-// wakeLoop and signal that this one is done by closing the wakeMeAt channel.
-func wakeLoop(wakeMeAt chan int64, wakeUp chan bool) {
-	for wakeAt := range wakeMeAt {
-		Sleep(wakeAt - Nanoseconds())
-		wakeUp <- true
-	}
-}
-
-// A single tickerLoop serves all ticks to Tickers.  It waits for two events:
-// either the creation of a new Ticker or a tick from the alarm,
-// signaling a time to wake up one or more Tickers.
-func tickerLoop() {
-	// Represents the next alarm to be delivered.
-	var alarm alarmer
-	var now, wakeTime int64
-	var tickers *Ticker
-	for {
-		select {
-		case t := <-newTicker:
-			// Add Ticker to list
-			t.next = tickers
-			tickers = t
-			// Arrange for a new alarm if this one precedes the existing one.
-			alarm.set(t.nextTick)
-		case <-alarm.wakeUp:
-			now = Nanoseconds()
-			wakeTime = now + 1e15 // very long in the future
-			var prev *Ticker = nil
-			// Scan list of tickers, delivering updates to those
-			// that need it and determining the next wake time.
-			// TODO(r): list should be sorted in time order.
-			for t := tickers; t != nil; t = t.next {
-				select {
-				case <-t.shutdown:
-					// Ticker is done; remove it from list.
-					if prev == nil {
-						tickers = t.next
-					} else {
-						prev.next = t.next
-					}
-					continue
-				default:
-				}
-				if t.nextTick <= now {
-					if len(t.c) == 0 {
-						// Only send if there's room.  We must not block.
-						// The channel is allocated with a one-element
-						// buffer, which is sufficient: if he hasn't picked
-						// up the last tick, no point in sending more.
-						t.c <- now
-					}
-					t.nextTick += t.ns
-					if t.nextTick <= now {
-						// Still behind; advance in one big step.
-						t.nextTick += (now - t.nextTick + t.ns) / t.ns * t.ns
-					}
-				}
-				if t.nextTick < wakeTime {
-					wakeTime = t.nextTick
-				}
-				prev = t
-			}
-			if tickers != nil {
-				// Please send wakeup at earliest required time.
-				// If there are no tickers, don't bother.
-				alarm.wakeTime = wakeTime
-				alarm.wakeMeAt <- wakeTime
-			} else {
-				alarm.wakeTime = 0
-			}
-		}
-	}
-}
-
-var onceStartTickerLoop sync.Once
-
-// NewTicker returns a new Ticker containing a channel that will
-// send the time, in nanoseconds, every ns nanoseconds.  It adjusts the
-// intervals to make up for pauses in delivery of the ticks. The value of
-// ns must be greater than zero; if not, NewTicker will panic.
-func NewTicker(ns int64) *Ticker {
-	if ns <= 0 {
-		panic(os.NewError("non-positive interval for NewTicker"))
-	}
-	c := make(chan int64, 1) //  See comment on send in tickerLoop
-	t := &Ticker{
-		C:        c,
-		c:        c,
-		ns:       ns,
-		shutdown: make(chan bool, 1),
-		nextTick: Nanoseconds() + ns,
-	}
-	onceStartTickerLoop.Do(startTickerLoop)
-	// must be run in background so global Tickers can be created
-	go func() { newTicker <- t }()
-	return t
+	return NewTicker(d).C
 }
diff --git a/src/pkg/time/tick_test.go b/src/pkg/time/tick_test.go
index 4dcb639..3634934 100644
--- a/src/pkg/time/tick_test.go
+++ b/src/pkg/time/tick_test.go
@@ -11,21 +11,21 @@ import (
 
 func TestTicker(t *testing.T) {
 	const (
-		Delta = 100 * 1e6
+		Delta = 100 * Millisecond
 		Count = 10
 	)
 	ticker := NewTicker(Delta)
-	t0 := Nanoseconds()
+	t0 := Now()
 	for i := 0; i < Count; i++ {
 		<-ticker.C
 	}
 	ticker.Stop()
-	t1 := Nanoseconds()
-	ns := t1 - t0
-	target := int64(Delta * Count)
+	t1 := Now()
+	dt := t1.Sub(t0)
+	target := Delta * Count
 	slop := target * 2 / 10
-	if ns < target-slop || ns > target+slop {
-		t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target))
+	if dt < target-slop || dt > target+slop {
+		t.Fatalf("%d %s ticks took %s, expected [%s,%s]", Count, Delta, dt, target-slop, target+slop)
 	}
 	// Now test that the ticker stopped
 	Sleep(2 * Delta)
diff --git a/src/pkg/time/time.go b/src/pkg/time/time.go
index 859b316..39d4b95 100644
--- a/src/pkg/time/time.go
+++ b/src/pkg/time/time.go
@@ -3,11 +3,111 @@
 // license that can be found in the LICENSE file.
 
 // Package time provides functionality for measuring and displaying time.
+//
+// The calendrical calculations always assume a Gregorian calendar.
 package time
 
-// Days of the week.
+import "errors"
+
+// A Time represents an instant in time with nanosecond precision.
+//
+// Programs using times should typically store and pass them as values,
+// not pointers.  That is, time variables and struct fields should be of
+// type time.Time, not *time.Time.
+//
+// Time instants can be compared using the Before, After, and Equal methods.
+// The Sub method subtracts two instants, producing a Duration.
+// The Add method adds a Time and a Duration, producing a Time.
+//
+// The zero value of type Time is January 1, year 1, 00:00:00.000000000 UTC.
+// As this time is unlikely to come up in practice, the IsZero method gives
+// a simple way of detecting a time that has not been initialized explicitly.
+//
+// Each Time has associated with it a Location, consulted when computing the
+// presentation form of the time, such as in the Format, Hour, and Year methods.
+// The methods Local, UTC, and In return a Time with a specific location.
+// Changing the location in this way changes only the presentation; it does not
+// change the instant in time being denoted and therefore does not affect the
+// computations described in earlier paragraphs.
+//
+type Time struct {
+	// sec gives the number of seconds elapsed since
+	// January 1, year 1 00:00:00 UTC.
+	sec int64
+
+	// nsec specifies a non-negative nanosecond
+	// offset within the second named by Seconds.
+	// It must be in the range [0, 999999999].
+	nsec int32
+
+	// loc specifies the Location that should be used to
+	// determine the minute, hour, month, day, and year
+	// that correspond to this Time.
+	// Only the zero Time has a nil Location.
+	// In that case it is interpreted to mean UTC.
+	loc *Location
+}
+
+// After reports whether the time instant t is after u.
+func (t Time) After(u Time) bool {
+	return t.sec > u.sec || t.sec == u.sec && t.nsec > u.nsec
+}
+
+// Before reports whether the time instant t is before u.
+func (t Time) Before(u Time) bool {
+	return t.sec < u.sec || t.sec == u.sec && t.nsec < u.nsec
+}
+
+// Equal reports whether t and u represent the same time instant.
+// Two times can be equal even if they are in different locations.
+// For example, 6:00 +0200 CEST and 4:00 UTC are Equal.
+// This comparison is different from using t == u, which also compares
+// the locations.
+func (t Time) Equal(u Time) bool {
+	return t.sec == u.sec && t.nsec == u.nsec
+}
+
+// A Month specifies a month of the year (January = 1, ...).
+type Month int
+
 const (
-	Sunday = iota
+	January Month = 1 + iota
+	February
+	March
+	April
+	May
+	June
+	July
+	August
+	September
+	October
+	November
+	December
+)
+
+var months = [...]string{
+	"January",
+	"February",
+	"March",
+	"April",
+	"May",
+	"June",
+	"July",
+	"August",
+	"September",
+	"October",
+	"November",
+	"December",
+}
+
+// String returns the English name of the month ("January", "February", ...).
+func (m Month) String() string { return months[m-1] }
+
+// A Weekday specifies a day of the week (Sunday = 0, ...).
+type Weekday int
+
+const (
+	Sunday Weekday = iota
 	Monday
 	Tuesday
 	Wednesday
@@ -16,224 +116,895 @@ const (
 	Saturday
 )
 
-// Time is the struct representing a parsed time value.
-type Time struct {
-	Year                 int64  // 2006 is 2006
-	Month, Day           int    // Jan-2 is 1, 2
-	Hour, Minute, Second int    // 15:04:05 is 15, 4, 5.
-	Nanosecond           int    // Fractional second.
-	ZoneOffset           int    // seconds east of UTC, e.g. -7*60*60 for -0700
-	Zone                 string // e.g., "MST"
+var days = [...]string{
+	"Sunday",
+	"Monday",
+	"Tuesday",
+	"Wednesday",
+	"Thursday",
+	"Friday",
+	"Saturday",
+}
+
+// String returns the English name of the day ("Sunday", "Monday", ...).
+func (d Weekday) String() string { return days[d] }
+
+// Computations on time.
+//
+// The zero value for a Time is defined to be
+//	January 1, year 1, 00:00:00.000000000 UTC
+// which (1) looks like a zero, or as close as you can get in a date
+// (1-1-1 00:00:00 UTC), (2) is unlikely enough to arise in practice to
+// be a suitable "not set" sentinel, unlike Jan 1 1970, and (3) has a
+// non-negative year even in time zones west of UTC, unlike 1-1-0
+// 00:00:00 UTC, which would be 12-31-(-1) 19:00:00 in New York.
+//
+// The zero Time value does not force a specific epoch for the time
+// representation.  For example, to use the Unix epoch internally, we
+// could define that to distinguish a zero value from Jan 1 1970, that
+// time would be represented by sec=-1, nsec=1e9.  However, it does
+// suggest a representation, namely using 1-1-1 00:00:00 UTC as the
+// epoch, and that's what we do.
+//
+// The Add and Sub computations are oblivious to the choice of epoch.
+//
+// The presentation computations - year, month, minute, and so on - all
+// rely heavily on division and modulus by positive constants.  For
+// calendrical calculations we want these divisions to round down, even
+// for negative values, so that the remainder is always positive, but
+// Go's division (like most hardware divison instructions) rounds to
+// zero.  We can still do those computations and then adjust the result
+// for a negative numerator, but it's annoying to write the adjustment
+// over and over.  Instead, we can change to a different epoch so long
+// ago that all the times we care about will be positive, and then round
+// to zero and round down coincide.  These presentation routines already
+// have to add the zone offset, so adding the translation to the
+// alternate epoch is cheap.  For example, having a non-negative time t
+// means that we can write
+//
+//	sec = t % 60
+//
+// instead of
+//
+//	sec = t % 60
+//	if sec < 0 {
+//		sec += 60
+//	}
+//
+// everywhere.
+//
+// The calendar runs on an exact 400 year cycle: a 400-year calendar
+// printed for 1970-2469 will apply as well to 2470-2869.  Even the days
+// of the week match up.  It simplifies the computations to choose the
+// cycle boundaries so that the exceptional years are always delayed as
+// long as possible.  That means choosing a year equal to 1 mod 400, so
+// that the first leap year is the 4th year, the first missed leap year
+// is the 100th year, and the missed missed leap year is the 400th year.
+// So we'd prefer instead to print a calendar for 2001-2400 and reuse it
+// for 2401-2800.
+//
+// Finally, it's convenient if the delta between the Unix epoch and
+// long-ago epoch is representable by an int64 constant.
+//
+// These three considerations—choose an epoch as early as possible, that
+// uses a year equal to 1 mod 400, and that is no more than 2⁶³ seconds
+// earlier than 1970—bring us to the year -292277022399.  We refer to
+// this year as the absolute zero year, and to times measured as a uint64
+// seconds since this year as absolute times.
+//
+// Times measured as an int64 seconds since the year 1—the representation
+// used for Time's sec field—are called internal times.
+//
+// Times measured as an int64 seconds since the year 1970 are called Unix
+// times.
+//
+// It is tempting to just use the year 1 as the absolute epoch, defining
+// that the routines are only valid for years >= 1.  However, the
+// routines would then be invalid when displaying the epoch in time zones
+// west of UTC, since it is year 0.  It doesn't seem tenable to say that
+// printing the zero time correctly isn't supported in half the time
+// zones.  By comparison, it's reasonable to mishandle some times in
+// the year -292277022399.
+//
+// All this is opaque to clients of the API and can be changed if a
+// better implementation presents itself.
+
+const (
+	// The unsigned zero year for internal calculations.
+	// Must be 1 mod 400, and times before it will not compute correctly,
+	// but otherwise can be changed at will.
+	absoluteZeroYear = -292277022399
+
+	// The year of the zero Time.
+	// Assumed by the unixToInternal computation below.
+	internalYear = 1
+
+	// The year of the zero Unix time.
+	unixYear = 1970
+
+	// Offsets to convert between internal and absolute or Unix times.
+	absoluteToInternal int64 = (absoluteZeroYear - internalYear) * 365.2425 * secondsPerDay
+	internalToAbsolute       = -absoluteToInternal
+
+	unixToInternal int64 = (1969*365 + 1969/4 - 1969/100 + 1969/400) * secondsPerDay
+	internalToUnix int64 = -unixToInternal
+)
+
+// IsZero reports whether t represents the zero time instant,
+// January 1, year 1, 00:00:00 UTC.
+func (t Time) IsZero() bool {
+	return t.sec == 0 && t.nsec == 0
+}
+
+// abs returns the time t as an absolute time, adjusted by the zone offset.
+// It is called when computing a presentation property like Month or Hour.
+func (t Time) abs() uint64 {
+	l := t.loc
+	if l == nil {
+		l = &utcLoc
+	}
+	// Avoid function call if we hit the local time cache.
+	sec := t.sec + internalToUnix
+	if l != &utcLoc {
+		if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
+			sec += int64(l.cacheZone.offset)
+		} else {
+			_, offset, _, _, _ := l.lookup(sec)
+			sec += int64(offset)
+		}
+	}
+	return uint64(sec + (unixToInternal + internalToAbsolute))
+}
+
+// Date returns the year, month, and day in which t occurs.
+func (t Time) Date() (year int, month Month, day int) {
+	year, month, day, _ = t.date(true)
+	return
+}
+
+// Year returns the year in which t occurs.
+func (t Time) Year() int {
+	year, _, _, _ := t.date(false)
+	return year
+}
+
+// Month returns the month of the year specified by t.
+func (t Time) Month() Month {
+	_, month, _, _ := t.date(true)
+	return month
+}
+
+// Day returns the day of the month specified by t.
+func (t Time) Day() int {
+	_, _, day, _ := t.date(true)
+	return day
+}
+
+// Weekday returns the day of the week specified by t.
+func (t Time) Weekday() Weekday {
+	// January 1 of the absolute year, like January 1 of 2001, was a Monday.
+	sec := (t.abs() + uint64(Monday)*secondsPerDay) % secondsPerWeek
+	return Weekday(int(sec) / secondsPerDay)
 }
 
-var nonleapyear = []int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
-var leapyear = []int{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+// ISOWeek returns the ISO 8601 year and week number in which t occurs.
+// Week ranges from 1 to 53. Jan 01 to Jan 03 of year n might belong to
+// week 52 or 53 of year n-1, and Dec 29 to Dec 31 might belong to week 1
+// of year n+1.
+func (t Time) ISOWeek() (year, week int) {
+	year, month, day, yday := t.date(true)
+	wday := int(t.Weekday()+6) % 7 // weekday but Monday = 0.
+	const (
+		Mon int = iota
+		Tue
+		Wed
+		Thu
+		Fri
+		Sat
+		Sun
+	)
+
+	// Calculate week as number of Mondays in year up to
+	// and including today, plus 1 because the first week is week 0.
+	// Putting the + 1 inside the numerator as a + 7 keeps the
+	// numerator from being negative, which would cause it to
+	// round incorrectly.
+	week = (yday - wday + 7) / 7
+
+	// The week number is now correct under the assumption
+	// that the first Monday of the year is in week 1.
+	// If Jan 1 is a Tuesday, Wednesday, or Thursday, the first Monday
+	// is actually in week 2.
+	jan1wday := (wday - yday + 7*53) % 7
+	if Tue <= jan1wday && jan1wday <= Thu {
+		week++
+	}
+
+	// If the week number is still 0, we're in early January but in
+	// the last week of last year.
+	if week == 0 {
+		year--
+		week = 52
+		// A year has 53 weeks when Jan 1 or Dec 31 is a Thursday,
+		// meaning Jan 1 of the next year is a Friday
+		// or it was a leap year and Jan 1 of the next year is a Saturday.
+		if jan1wday == Fri || (jan1wday == Sat && isLeap(year)) {
+			week++
+		}
+	}
 
-func months(year int64) []int {
-	if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
-		return leapyear
+	// December 29 to 31 are in week 1 of next year if
+	// they are after the last Thursday of the year and
+	// December 31 is a Monday, Tuesday, or Wednesday.
+	if month == December && day >= 29 && wday < Thu {
+		if dec31wday := (wday + 31 - day) % 7; Mon <= dec31wday && dec31wday <= Wed {
+			year++
+			week = 1
+		}
 	}
-	return nonleapyear
+
+	return
+}
+
+// Clock returns the hour, minute, and second within the day specified by t.
+func (t Time) Clock() (hour, min, sec int) {
+	sec = int(t.abs() % secondsPerDay)
+	hour = sec / secondsPerHour
+	sec -= hour * secondsPerHour
+	min = sec / secondsPerMinute
+	sec -= min * secondsPerMinute
+	return
+}
+
+// Hour returns the hour within the day specified by t, in the range [0, 23].
+func (t Time) Hour() int {
+	return int(t.abs()%secondsPerDay) / secondsPerHour
+}
+
+// Minute returns the minute offset within the hour specified by t, in the range [0, 59].
+func (t Time) Minute() int {
+	return int(t.abs()%secondsPerHour) / secondsPerMinute
+}
+
+// Second returns the second offset within the minute specified by t, in the range [0, 59].
+func (t Time) Second() int {
+	return int(t.abs() % secondsPerMinute)
+}
+
+// Nanosecond returns the nanosecond offset within the second specified by t,
+// in the range [0, 999999999].
+func (t Time) Nanosecond() int {
+	return int(t.nsec)
 }
 
+// A Duration represents the elapsed time between two instants
+// as an int64 nanosecond count.  The representation limits the
+// largest representable duration to approximately 290 years.
+type Duration int64
+
+// Common durations.  There is no definition for units of Day or larger
+// to avoid confusion across daylight savings time zone transitions.
 const (
-	secondsPerDay   = 24 * 60 * 60
-	daysPer400Years = 365*400 + 97
-	daysPer100Years = 365*100 + 24
-	daysPer4Years   = 365*4 + 1
-	days1970To2001  = 31*365 + 8
+	Nanosecond  Duration = 1
+	Microsecond          = 1000 * Nanosecond
+	Millisecond          = 1000 * Microsecond
+	Second               = 1000 * Millisecond
+	Minute               = 60 * Second
+	Hour                 = 60 * Minute
 )
 
-// SecondsToUTC converts sec, in number of seconds since the Unix epoch,
-// into a parsed Time value in the UTC time zone.
-func SecondsToUTC(sec int64) *Time {
-	t := new(Time)
+// Duration returns a string representing the duration in the form "72h3m0.5s".
+// Leading zero units are omitted.  As a special case, durations less than one
+// second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure
+// that the leading digit is non-zero.  The zero duration formats as 0,
+// with no unit.
+func (d Duration) String() string {
+	// Largest time is 2540400h10m10.000000000s
+	var buf [32]byte
+	w := len(buf)
+
+	u := uint64(d)
+	neg := d < 0
+	if neg {
+		u = -u
+	}
 
-	// Split into time and day.
-	day := sec / secondsPerDay
-	sec -= day * secondsPerDay
-	if sec < 0 {
-		day--
-		sec += secondsPerDay
+	if u < uint64(Second) {
+		// Special case: if duration is smaller than a second,
+		// use smaller units, like 1.2ms
+		var (
+			prec int
+			unit byte
+		)
+		switch {
+		case u == 0:
+			return "0"
+		case u < uint64(Microsecond):
+			// print nanoseconds
+			prec = 0
+			unit = 'n'
+		case u < uint64(Millisecond):
+			// print microseconds
+			prec = 3
+			unit = 'u'
+		default:
+			// print milliseconds
+			prec = 6
+			unit = 'm'
+		}
+		w -= 2
+		buf[w] = unit
+		buf[w+1] = 's'
+		w, u = fmtFrac(buf[:w], u, prec)
+		w = fmtInt(buf[:w], u)
+	} else {
+		w--
+		buf[w] = 's'
+
+		w, u = fmtFrac(buf[:w], u, 9)
+
+		// u is now integer seconds
+		w = fmtInt(buf[:w], u%60)
+		u /= 60
+
+		// u is now integer minutes
+		if u > 0 {
+			w--
+			buf[w] = 'm'
+			w = fmtInt(buf[:w], u%60)
+			u /= 60
+
+			// u is now integer hours
+			// Stop at hours because days can be different lengths.
+			if u > 0 {
+				w--
+				buf[w] = 'h'
+				w = fmtInt(buf[:w], u)
+			}
+		}
 	}
 
-	// Time
-	t.Hour = int(sec / 3600)
-	t.Minute = int((sec / 60) % 60)
-	t.Second = int(sec % 60)
+	if neg {
+		w--
+		buf[w] = '-'
+	}
 
-	// Change day from 0 = 1970 to 0 = 2001,
-	// to make leap year calculations easier
-	// (2001 begins 4-, 100-, and 400-year cycles ending in a leap year.)
-	day -= days1970To2001
+	return string(buf[w:])
+}
+
+// fmtFrac formats the fraction of v/10**prec (e.g., ".12345") into the
+// tail of buf, omitting trailing zeros.  it omits the decimal
+// point too when the fraction is 0.  It returns the index where the
+// output bytes begin and the value v/10**prec.
+func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) {
+	// Omit trailing zeros up to and including decimal point.
+	w := len(buf)
+	print := false
+	for i := 0; i < prec; i++ {
+		digit := v % 10
+		print = print || digit != 0
+		if print {
+			w--
+			buf[w] = byte(digit) + '0'
+		}
+		v /= 10
+	}
+	if print {
+		w--
+		buf[w] = '.'
+	}
+	return w, v
+}
 
-	year := int64(2001)
-	if day < 0 {
-		// Go back enough 400 year cycles to make day positive.
-		n := -day/daysPer400Years + 1
-		year -= 400 * n
-		day += daysPer400Years * n
+// fmtInt formats v into the tail of buf.
+// It returns the index where the output begins.
+func fmtInt(buf []byte, v uint64) int {
+	w := len(buf)
+	if v == 0 {
+		w--
+		buf[w] = '0'
+	} else {
+		for v > 0 {
+			w--
+			buf[w] = byte(v%10) + '0'
+			v /= 10
+		}
 	}
+	return w
+}
 
-	// Cut off 400 year cycles.
-	n := day / daysPer400Years
-	year += 400 * n
-	day -= daysPer400Years * n
+// Nanoseconds returns the duration as an integer nanosecond count.
+func (d Duration) Nanoseconds() int64 { return int64(d) }
+
+// These methods return float64 because the dominant
+// use case is for printing a floating point number like 1.5s, and
+// a truncation to integer would make them not useful in those cases.
+// Splitting the integer and fraction ourselves guarantees that
+// converting the returned float64 to an integer rounds the same
+// way that a pure integer conversion would have, even in cases
+// where, say, float64(d.Nanoseconds())/1e9 would have rounded
+// differently.
+
+// Seconds returns the duration as a floating point number of seconds.
+func (d Duration) Seconds() float64 {
+	sec := d / Second
+	nsec := d % Second
+	return float64(sec) + float64(nsec)*1e-9
+}
 
-	// Cut off 100-year cycles
-	n = day / daysPer100Years
-	if n > 3 { // happens on last day of 400th year
-		n = 3
+// Minutes returns the duration as a floating point number of minutes.
+func (d Duration) Minutes() float64 {
+	min := d / Minute
+	nsec := d % Minute
+	return float64(min) + float64(nsec)*(1e-9/60)
+}
+
+// Hours returns the duration as a floating point number of hours.
+func (d Duration) Hours() float64 {
+	hour := d / Hour
+	nsec := d % Hour
+	return float64(hour) + float64(nsec)*(1e-9/60/60)
+}
+
+// Add returns the time t+d.
+func (t Time) Add(d Duration) Time {
+	t.sec += int64(d / 1e9)
+	t.nsec += int32(d % 1e9)
+	if t.nsec >= 1e9 {
+		t.sec++
+		t.nsec -= 1e9
+	} else if t.nsec < 0 {
+		t.sec--
+		t.nsec += 1e9
 	}
-	year += 100 * n
-	day -= daysPer100Years * n
+	return t
+}
 
-	// Cut off 4-year cycles
-	n = day / daysPer4Years
-	if n > 24 { // happens on last day of 100th year
-		n = 24
+// Sub returns the duration t-u.
+// To compute t-d for a duration d, use t.Add(-d).
+func (t Time) Sub(u Time) Duration {
+	return Duration(t.sec-u.sec)*Second + Duration(t.nsec-u.nsec)
+}
+
+// Since returns the time elapsed since t.
+// It is shorthand for time.Now().Sub(t).
+func Since(t Time) Duration {
+	return Now().Sub(t)
+}
+
+// AddDate returns the time corresponding to adding the
+// given number of years, months, and days to t.
+// For example, AddDate(-1, 2, 3) applied to January 1, 2011
+// returns March 4, 2010.
+//
+// AddDate normalizes its result in the same way that Date does,
+// so, for example, adding one month to October 31 yields
+// December 1, the normalized form for November 31.
+func (t Time) AddDate(years int, months int, days int) Time {
+	year, month, day := t.Date()
+	hour, min, sec := t.Clock()
+	return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.loc)
+}
+
+const (
+	secondsPerMinute = 60
+	secondsPerHour   = 60 * 60
+	secondsPerDay    = 24 * secondsPerHour
+	secondsPerWeek   = 7 * secondsPerDay
+	daysPer400Years  = 365*400 + 97
+	daysPer100Years  = 365*100 + 24
+	daysPer4Years    = 365*4 + 1
+	days1970To2001   = 31*365 + 8
+)
+
+// date computes the year and, only when full=true,
+// the month and day in which t occurs.
+func (t Time) date(full bool) (year int, month Month, day int, yday int) {
+	// Split into time and day.
+	d := t.abs() / secondsPerDay
+
+	// Account for 400 year cycles.
+	n := d / daysPer400Years
+	y := 400 * n
+	d -= daysPer400Years * n
+
+	// Cut off 100-year cycles.
+	// The last cycle has one extra leap year, so on the last day
+	// of that year, day / daysPer100Years will be 4 instead of 3.
+	// Cut it back down to 3 by subtracting n>>2.
+	n = d / daysPer100Years
+	n -= n >> 2
+	y += 100 * n
+	d -= daysPer100Years * n
+
+	// Cut off 4-year cycles.
+	// The last cycle has a missing leap year, which does not
+	// affect the computation.
+	n = d / daysPer4Years
+	y += 4 * n
+	d -= daysPer4Years * n
+
+	// Cut off years within a 4-year cycle.
+	// The last year is a leap year, so on the last day of that year,
+	// day / 365 will be 4 instead of 3.  Cut it back down to 3
+	// by subtracting n>>2.
+	n = d / 365
+	n -= n >> 2
+	y += n
+	d -= 365 * n
+
+	year = int(int64(y) + absoluteZeroYear)
+	yday = int(d)
+
+	if !full {
+		return
 	}
-	year += 4 * n
-	day -= daysPer4Years * n
 
-	// Cut off non-leap years.
-	n = day / 365
-	if n > 3 { // happens on last day of 4th year
-		n = 3
+	day = yday
+	if isLeap(year) {
+		// Leap year
+		switch {
+		case day > 31+29-1:
+			// After leap day; pretend it wasn't there.
+			day--
+		case day == 31+29-1:
+			// Leap day.
+			month = February
+			day = 29
+			return
+		}
 	}
-	year += n
-	day -= 365 * n
 
-	t.Year = year
+	// Estimate month on assumption that every month has 31 days.
+	// The estimate may be too low by at most one month, so adjust.
+	month = Month(day / 31)
+	end := int(daysBefore[month+1])
+	var begin int
+	if day >= end {
+		month++
+		begin = end
+	} else {
+		begin = int(daysBefore[month])
+	}
 
-	// If someone ever needs yearday,
-	// tyearday = day (+1?)
+	month++ // because January is 1
+	day = day - begin + 1
+	return
+}
+
+// daysBefore[m] counts the number of days in a non-leap year
+// before month m begins.  There is an entry for m=12, counting
+// the number of days before January of next year (365).
+var daysBefore = [...]int32{
+	0,
+	31,
+	31 + 28,
+	31 + 28 + 31,
+	31 + 28 + 31 + 30,
+	31 + 28 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
+}
 
-	months := months(year)
-	var m int
-	yday := int(day)
-	for m = 0; m < 12 && yday >= months[m]; m++ {
-		yday -= months[m]
+func daysIn(m Month, year int) int {
+	if m == February && isLeap(year) {
+		return 29
 	}
-	t.Month = m + 1
-	t.Day = yday + 1
-	t.Zone = "UTC"
+	return int(daysBefore[m] - daysBefore[m-1])
+}
 
-	return t
+// Provided by package runtime.
+func now() (sec int64, nsec int32)
+
+// Now returns the current local time.
+func Now() Time {
+	sec, nsec := now()
+	return Time{sec + unixToInternal, nsec, Local}
 }
 
-// NanosecondsToUTC converts nsec, in number of nanoseconds since the Unix epoch,
-// into a parsed Time value in the UTC time zone.
-func NanosecondsToUTC(nsec int64) *Time {
-	// This one calls SecondsToUTC rather than the other way around because
-	// that admits a much larger span of time; NanosecondsToUTC is limited
-	// to a few hundred years only.
-	t := SecondsToUTC(nsec / 1e9)
-	t.Nanosecond = int(nsec % 1e9)
+// UTC returns t with the location set to UTC.
+func (t Time) UTC() Time {
+	t.loc = UTC
 	return t
 }
 
-// UTC returns the current time as a parsed Time value in the UTC time zone.
-func UTC() *Time { return NanosecondsToUTC(Nanoseconds()) }
-
-// SecondsToLocalTime converts sec, in number of seconds since the Unix epoch,
-// into a parsed Time value in the local time zone.
-func SecondsToLocalTime(sec int64) *Time {
-	z, offset := lookupTimezone(sec)
-	t := SecondsToUTC(sec + int64(offset))
-	t.Zone = z
-	t.ZoneOffset = offset
+// Local returns t with the location set to local time.
+func (t Time) Local() Time {
+	t.loc = Local
 	return t
 }
 
-// NanosecondsToLocalTime converts nsec, in number of nanoseconds since the Unix epoch,
-// into a parsed Time value in the local time zone.
-func NanosecondsToLocalTime(nsec int64) *Time {
-	t := SecondsToLocalTime(nsec / 1e9)
-	t.Nanosecond = int(nsec % 1e9)
+// In returns t with the location information set to loc.
+//
+// In panics if loc is nil.
+func (t Time) In(loc *Location) Time {
+	if loc == nil {
+		panic("time: missing Location in call to Time.In")
+	}
+	t.loc = loc
 	return t
 }
 
-// LocalTime returns the current time as a parsed Time value in the local time zone.
-func LocalTime() *Time { return NanosecondsToLocalTime(Nanoseconds()) }
+// Location returns the time zone information associated with t.
+func (t Time) Location() *Location {
+	l := t.loc
+	if l == nil {
+		l = UTC
+	}
+	return l
+}
+
+// Zone computes the time zone in effect at time t, returning the abbreviated
+// name of the zone (such as "CET") and its offset in seconds east of UTC.
+func (t Time) Zone() (name string, offset int) {
+	name, offset, _, _, _ = t.loc.lookup(t.sec + internalToUnix)
+	return
+}
+
+// Unix returns the Unix time, the number of seconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) Unix() int64 {
+	return t.sec + internalToUnix
+}
+
+// UnixNano returns the Unix time, the number of nanoseconds elapsed
+// since January 1, 1970 UTC.
+func (t Time) UnixNano() int64 {
+	return (t.sec+internalToUnix)*1e9 + int64(t.nsec)
+}
+
+type gobError string
+
+func (g gobError) Error() string { return string(g) }
 
-// Seconds returns the number of seconds since January 1, 1970 represented by the
-// parsed Time value.
-func (t *Time) Seconds() int64 {
-	// First, accumulate days since January 1, 2001.
-	// Using 2001 instead of 1970 makes the leap-year
-	// handling easier (see SecondsToUTC), because
-	// it is at the beginning of the 4-, 100-, and 400-year cycles.
-	day := int64(0)
+const timeGobVersion byte = 1
 
-	// Rewrite year to be >= 2001.
-	year := t.Year
-	if year < 2001 {
-		n := (2001-year)/400 + 1
-		year += 400 * n
-		day -= daysPer400Years * n
+// GobEncode implements the gob.GobEncoder interface.
+func (t Time) GobEncode() ([]byte, error) {
+	var offsetMin int16 // minutes east of UTC. -1 is UTC.
+
+	if t.Location() == &utcLoc {
+		offsetMin = -1
+	} else {
+		_, offset := t.Zone()
+		if offset%60 != 0 {
+			return nil, errors.New("Time.GobEncode: zone offset has fractional minute")
+		}
+		offset /= 60
+		if offset < -32768 || offset == -1 || offset > 32767 {
+			return nil, errors.New("Time.GobEncode: unexpected zone offset")
+		}
+		offsetMin = int16(offset)
 	}
 
-	// Add in days from 400-year cycles.
-	n := (year - 2001) / 400
-	year -= 400 * n
-	day += daysPer400Years * n
+	enc := []byte{
+		timeGobVersion,    // byte 0 : version
+		byte(t.sec >> 56), // bytes 1-8: seconds
+		byte(t.sec >> 48),
+		byte(t.sec >> 40),
+		byte(t.sec >> 32),
+		byte(t.sec >> 24),
+		byte(t.sec >> 16),
+		byte(t.sec >> 8),
+		byte(t.sec),
+		byte(t.nsec >> 24), // bytes 9-12: nanoseconds
+		byte(t.nsec >> 16),
+		byte(t.nsec >> 8),
+		byte(t.nsec),
+		byte(offsetMin >> 8), // bytes 13-14: zone offset in minutes
+		byte(offsetMin),
+	}
 
-	// Add in 100-year cycles.
-	n = (year - 2001) / 100
-	year -= 100 * n
-	day += daysPer100Years * n
+	return enc, nil
+}
 
-	// Add in 4-year cycles.
-	n = (year - 2001) / 4
-	year -= 4 * n
-	day += daysPer4Years * n
+// GobDecode implements the gob.GobDecoder interface.
+func (t *Time) GobDecode(buf []byte) error {
+	if len(buf) == 0 {
+		return errors.New("Time.GobDecode: no data")
+	}
 
-	// Add in non-leap years.
-	n = year - 2001
-	day += 365 * n
+	if buf[0] != timeGobVersion {
+		return errors.New("Time.GobDecode: unsupported version")
+	}
 
-	// Add in days this year.
-	months := months(t.Year)
-	for m := 0; m < t.Month-1; m++ {
-		day += int64(months[m])
+	if len(buf) != /*version*/ 1+ /*sec*/ 8+ /*nsec*/ 4+ /*zone offset*/ 2 {
+		return errors.New("Time.GobDecode: invalid length")
 	}
-	day += int64(t.Day - 1)
 
-	// Convert days to seconds since January 1, 2001.
-	sec := day * secondsPerDay
+	buf = buf[1:]
+	t.sec = int64(buf[7]) | int64(buf[6])<<8 | int64(buf[5])<<16 | int64(buf[4])<<24 |
+		int64(buf[3])<<32 | int64(buf[2])<<40 | int64(buf[1])<<48 | int64(buf[0])<<56
 
-	// Add in time elapsed today.
-	sec += int64(t.Hour) * 3600
-	sec += int64(t.Minute) * 60
-	sec += int64(t.Second)
+	buf = buf[8:]
+	t.nsec = int32(buf[3]) | int32(buf[2])<<8 | int32(buf[1])<<16 | int32(buf[0])<<24
+
+	buf = buf[4:]
+	offset := int(int16(buf[1])|int16(buf[0])<<8) * 60
+
+	if offset == -1*60 {
+		t.loc = &utcLoc
+	} else if _, localoff, _, _, _ := Local.lookup(t.sec + internalToUnix); offset == localoff {
+		t.loc = Local
+	} else {
+		t.loc = FixedZone("", offset)
+	}
+
+	return nil
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+// Time is formatted as RFC3339.
+func (t Time) MarshalJSON() ([]byte, error) {
+	yearInt := t.Year()
+	if yearInt < 0 || yearInt > 9999 {
+		return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
+	}
+
+	// We need a four-digit year, but Format produces variable-width years.
+	year := itoa(yearInt)
+	year = "0000"[:4-len(year)] + year
+
+	var formattedTime string
+	if t.nsec == 0 {
+		// RFC3339, no fractional second
+		formattedTime = t.Format("-01-02T15:04:05Z07:00")
+	} else {
+		// RFC3339 with fractional second
+		formattedTime = t.Format("-01-02T15:04:05.000000000Z07:00")
+
+		// Trim trailing zeroes from fractional second.
+		const nanoEnd = 24 // Index of last digit of fractional second
+		var i int
+		for i = nanoEnd; formattedTime[i] == '0'; i-- {
+			// Seek backwards until first significant digit is found.
+		}
+
+		formattedTime = formattedTime[:i+1] + formattedTime[nanoEnd+1:]
+	}
 
-	// Convert from seconds since 2001 to seconds since 1970.
-	sec += days1970To2001 * secondsPerDay
+	buf := make([]byte, 0, 1+len(year)+len(formattedTime)+1)
+	buf = append(buf, '"')
+	buf = append(buf, year...)
+	buf = append(buf, formattedTime...)
+	buf = append(buf, '"')
+	return buf, nil
+}
 
-	// Account for local time zone.
-	sec -= int64(t.ZoneOffset)
-	return sec
+// UnmarshalJSON implements the json.Unmarshaler interface.
+// Time is expected in RFC3339 format.
+func (t *Time) UnmarshalJSON(data []byte) (err error) {
+	*t, err = Parse("\""+RFC3339+"\"", string(data))
+	// Fractional seconds are handled implicitly by Parse.
+	return
+}
+
+// Unix returns the local Time corresponding to the given Unix time,
+// sec seconds and nsec nanoseconds since January 1, 1970 UTC.
+// It is valid to pass nsec outside the range [0, 999999999].
+func Unix(sec int64, nsec int64) Time {
+	if nsec < 0 || nsec >= 1e9 {
+		n := nsec / 1e9
+		sec += n
+		nsec -= n * 1e9
+		if nsec < 0 {
+			nsec += 1e9
+			sec--
+		}
+	}
+	return Time{sec + unixToInternal, int32(nsec), Local}
 }
 
-// Nanoseconds returns the number of nanoseconds since January 1, 1970 represented by the
-// parsed Time value.
-func (t *Time) Nanoseconds() int64 {
-	return t.Seconds()*1e9 + int64(t.Nanosecond)
+func isLeap(year int) bool {
+	return year%4 == 0 && (year%100 != 0 || year%400 == 0)
+}
+
+// norm returns nhi, nlo such that
+//	hi * base + lo == nhi * base + nlo
+//	0 <= nlo < base
+func norm(hi, lo, base int) (nhi, nlo int) {
+	if lo < 0 {
+		n := (-lo-1)/base + 1
+		hi -= n
+		lo += n * base
+	}
+	if lo >= base {
+		n := lo / base
+		hi += n
+		lo -= n * base
+	}
+	return hi, lo
 }
 
-// Weekday returns the time's day of the week. Sunday is day 0.
-func (t *Time) Weekday() int {
-	sec := t.Seconds() + int64(t.ZoneOffset)
-	day := sec / secondsPerDay
-	sec -= day * secondsPerDay
-	if sec < 0 {
-		day--
+// Date returns the Time corresponding to
+//	yyyy-mm-dd hh:mm:ss + nsec nanoseconds
+// in the appropriate zone for that time in the given location.
+//
+// The month, day, hour, min, sec, and nsec values may be outside
+// their usual ranges and will be normalized during the conversion.
+// For example, October 32 converts to November 1.
+//
+// A daylight savings time transition skips or repeats times.
+// For example, in the United States, March 13, 2011 2:15am never occurred,
+// while November 6, 2011 1:15am occurred twice.  In such cases, the
+// choice of time zone, and therefore the time, is not well-defined.
+// Date returns a time that is correct in one of the two zones involved
+// in the transition, but it does not guarantee which.
+//
+// Date panics if loc is nil.
+func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {
+	if loc == nil {
+		panic("time: missing Location in call to Date")
 	}
-	// Day 0 = January 1, 1970 was a Thursday
-	weekday := int((day + Thursday) % 7)
-	if weekday < 0 {
-		weekday += 7
+
+	// Normalize month, overflowing into year.
+	m := int(month) - 1
+	year, m = norm(year, m, 12)
+	month = Month(m) + 1
+
+	// Normalize nsec, sec, min, hour, overflowing into day.
+	sec, nsec = norm(sec, nsec, 1e9)
+	min, sec = norm(min, sec, 60)
+	hour, min = norm(hour, min, 60)
+	day, hour = norm(day, hour, 24)
+
+	y := uint64(int64(year) - absoluteZeroYear)
+
+	// Compute days since the absolute epoch.
+
+	// Add in days from 400-year cycles.
+	n := y / 400
+	y -= 400 * n
+	d := daysPer400Years * n
+
+	// Add in 100-year cycles.
+	n = y / 100
+	y -= 100 * n
+	d += daysPer100Years * n
+
+	// Add in 4-year cycles.
+	n = y / 4
+	y -= 4 * n
+	d += daysPer4Years * n
+
+	// Add in non-leap years.
+	n = y
+	d += 365 * n
+
+	// Add in days before this month.
+	d += uint64(daysBefore[month-1])
+	if isLeap(year) && month >= March {
+		d++ // February 29
 	}
-	return weekday
+
+	// Add in days before today.
+	d += uint64(day - 1)
+
+	// Add in time elapsed today.
+	abs := d * secondsPerDay
+	abs += uint64(hour*secondsPerHour + min*secondsPerMinute + sec)
+
+	unix := int64(abs) + (absoluteToInternal + internalToUnix)
+
+	// Look for zone offset for t, so we can adjust to UTC.
+	// The lookup function expects UTC, so we pass t in the
+	// hope that it will not be too close to a zone transition,
+	// and then adjust if it is.
+	_, offset, _, start, end := loc.lookup(unix)
+	if offset != 0 {
+		switch utc := unix - int64(offset); {
+		case utc < start:
+			_, offset, _, _, _ = loc.lookup(start - 1)
+		case utc >= end:
+			_, offset, _, _, _ = loc.lookup(end)
+		}
+		unix -= int64(offset)
+	}
+
+	return Time{unix + unixToInternal, int32(nsec), loc}
 }
diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go
index fe0f348..cdc1c39 100644
--- a/src/pkg/time/time_test.go
+++ b/src/pkg/time/time_test.go
@@ -5,6 +5,10 @@
 package time_test
 
 import (
+	"bytes"
+	"encoding/gob"
+	"encoding/json"
+	"math/rand"
 	"strconv"
 	"strings"
 	"testing"
@@ -16,73 +20,89 @@ import (
 // won't be. The purpose of this test is to at least explain why some of
 // the subsequent tests fail.
 func TestZoneData(t *testing.T) {
-	lt := LocalTime()
+	lt := Now()
 	// PST is 8 hours west, PDT is 7 hours west.  We could use the name but it's not unique.
-	if off := lt.ZoneOffset; off != -8*60*60 && off != -7*60*60 {
-		t.Errorf("Unable to find US Pacific time zone data for testing; time zone is %q offset %d", lt.Zone, off)
+	if name, off := lt.Zone(); off != -8*60*60 && off != -7*60*60 {
+		t.Errorf("Unable to find US Pacific time zone data for testing; time zone is %q offset %d", name, off)
 		t.Error("Likely problem: the time zone files have not been installed.")
 	}
 }
 
+// parsedTime is the struct representing a parsed time value.
+type parsedTime struct {
+	Year                 int
+	Month                Month
+	Day                  int
+	Hour, Minute, Second int // 15:04:05 is 15, 4, 5.
+	Nanosecond           int // Fractional second.
+	Weekday              Weekday
+	ZoneOffset           int    // seconds east of UTC, e.g. -7*60*60 for -0700
+	Zone                 string // e.g., "MST"
+}
+
 type TimeTest struct {
 	seconds int64
-	golden  Time
+	golden  parsedTime
 }
 
 var utctests = []TimeTest{
-	{0, Time{1970, 1, 1, 0, 0, 0, 0, 0, "UTC"}},
-	{1221681866, Time{2008, 9, 17, 20, 4, 26, 0, 0, "UTC"}},
-	{-1221681866, Time{1931, 4, 16, 3, 55, 34, 0, 0, "UTC"}},
-	{-11644473600, Time{1601, 1, 1, 0, 0, 0, 0, 0, "UTC"}},
-	{599529660, Time{1988, 12, 31, 0, 1, 0, 0, 0, "UTC"}},
-	{978220860, Time{2000, 12, 31, 0, 1, 0, 0, 0, "UTC"}},
-	{1e18, Time{31688740476, 10, 23, 1, 46, 40, 0, 0, "UTC"}},
-	{-1e18, Time{-31688736537, 3, 10, 22, 13, 20, 0, 0, "UTC"}},
-	{0x7fffffffffffffff, Time{292277026596, 12, 4, 15, 30, 7, 0, 0, "UTC"}},
-	{-0x8000000000000000, Time{-292277022657, 1, 27, 8, 29, 52, 0, 0, "UTC"}},
+	{0, parsedTime{1970, January, 1, 0, 0, 0, 0, Thursday, 0, "UTC"}},
+	{1221681866, parsedTime{2008, September, 17, 20, 4, 26, 0, Wednesday, 0, "UTC"}},
+	{-1221681866, parsedTime{1931, April, 16, 3, 55, 34, 0, Thursday, 0, "UTC"}},
+	{-11644473600, parsedTime{1601, January, 1, 0, 0, 0, 0, Monday, 0, "UTC"}},
+	{599529660, parsedTime{1988, December, 31, 0, 1, 0, 0, Saturday, 0, "UTC"}},
+	{978220860, parsedTime{2000, December, 31, 0, 1, 0, 0, Sunday, 0, "UTC"}},
 }
 
 var nanoutctests = []TimeTest{
-	{0, Time{1970, 1, 1, 0, 0, 0, 1e8, 0, "UTC"}},
-	{1221681866, Time{2008, 9, 17, 20, 4, 26, 2e8, 0, "UTC"}},
+	{0, parsedTime{1970, January, 1, 0, 0, 0, 1e8, Thursday, 0, "UTC"}},
+	{1221681866, parsedTime{2008, September, 17, 20, 4, 26, 2e8, Wednesday, 0, "UTC"}},
 }
 
 var localtests = []TimeTest{
-	{0, Time{1969, 12, 31, 16, 0, 0, 0, -8 * 60 * 60, "PST"}},
-	{1221681866, Time{2008, 9, 17, 13, 4, 26, 0, -7 * 60 * 60, "PDT"}},
+	{0, parsedTime{1969, December, 31, 16, 0, 0, 0, Wednesday, -8 * 60 * 60, "PST"}},
+	{1221681866, parsedTime{2008, September, 17, 13, 4, 26, 0, Wednesday, -7 * 60 * 60, "PDT"}},
 }
 
 var nanolocaltests = []TimeTest{
-	{0, Time{1969, 12, 31, 16, 0, 0, 1e8, -8 * 60 * 60, "PST"}},
-	{1221681866, Time{2008, 9, 17, 13, 4, 26, 3e8, -7 * 60 * 60, "PDT"}},
-}
-
-func same(t, u *Time) bool {
-	return t.Year == u.Year &&
-		t.Month == u.Month &&
-		t.Day == u.Day &&
-		t.Hour == u.Hour &&
-		t.Minute == u.Minute &&
-		t.Second == u.Second &&
-		t.Nanosecond == u.Nanosecond &&
-		t.Weekday() == u.Weekday() &&
-		t.ZoneOffset == u.ZoneOffset &&
-		t.Zone == u.Zone
+	{0, parsedTime{1969, December, 31, 16, 0, 0, 1e8, Wednesday, -8 * 60 * 60, "PST"}},
+	{1221681866, parsedTime{2008, September, 17, 13, 4, 26, 3e8, Wednesday, -7 * 60 * 60, "PDT"}},
+}
+
+func same(t Time, u *parsedTime) bool {
+	// Check aggregates.
+	year, month, day := t.Date()
+	hour, min, sec := t.Clock()
+	name, offset := t.Zone()
+	if year != u.Year || month != u.Month || day != u.Day ||
+		hour != u.Hour || min != u.Minute || sec != u.Second ||
+		name != u.Zone || offset != u.ZoneOffset {
+		return false
+	}
+	// Check individual entries.
+	return t.Year() == u.Year &&
+		t.Month() == u.Month &&
+		t.Day() == u.Day &&
+		t.Hour() == u.Hour &&
+		t.Minute() == u.Minute &&
+		t.Second() == u.Second &&
+		t.Nanosecond() == u.Nanosecond &&
+		t.Weekday() == u.Weekday
 }
 
 func TestSecondsToUTC(t *testing.T) {
 	for _, test := range utctests {
 		sec := test.seconds
 		golden := &test.golden
-		tm := SecondsToUTC(sec)
-		newsec := tm.Seconds()
+		tm := Unix(sec, 0).UTC()
+		newsec := tm.Unix()
 		if newsec != sec {
 			t.Errorf("SecondsToUTC(%d).Seconds() = %d", sec, newsec)
 		}
 		if !same(tm, golden) {
-			t.Errorf("SecondsToUTC(%d):", sec)
+			t.Errorf("SecondsToUTC(%d):  // %#v", sec, tm)
 			t.Errorf("  want=%+v", *golden)
-			t.Errorf("  have=%+v", *tm)
+			t.Errorf("  have=%v", tm.Format(RFC3339+" MST"))
 		}
 	}
 }
@@ -91,15 +111,15 @@ func TestNanosecondsToUTC(t *testing.T) {
 	for _, test := range nanoutctests {
 		golden := &test.golden
 		nsec := test.seconds*1e9 + int64(golden.Nanosecond)
-		tm := NanosecondsToUTC(nsec)
-		newnsec := tm.Nanoseconds()
+		tm := Unix(0, nsec).UTC()
+		newnsec := tm.Unix()*1e9 + int64(tm.Nanosecond())
 		if newnsec != nsec {
 			t.Errorf("NanosecondsToUTC(%d).Nanoseconds() = %d", nsec, newnsec)
 		}
 		if !same(tm, golden) {
 			t.Errorf("NanosecondsToUTC(%d):", nsec)
 			t.Errorf("  want=%+v", *golden)
-			t.Errorf("  have=%+v", *tm)
+			t.Errorf("  have=%+v", tm.Format(RFC3339+" MST"))
 		}
 	}
 }
@@ -108,38 +128,38 @@ func TestSecondsToLocalTime(t *testing.T) {
 	for _, test := range localtests {
 		sec := test.seconds
 		golden := &test.golden
-		tm := SecondsToLocalTime(sec)
-		newsec := tm.Seconds()
+		tm := Unix(sec, 0)
+		newsec := tm.Unix()
 		if newsec != sec {
 			t.Errorf("SecondsToLocalTime(%d).Seconds() = %d", sec, newsec)
 		}
 		if !same(tm, golden) {
 			t.Errorf("SecondsToLocalTime(%d):", sec)
 			t.Errorf("  want=%+v", *golden)
-			t.Errorf("  have=%+v", *tm)
+			t.Errorf("  have=%+v", tm.Format(RFC3339+" MST"))
 		}
 	}
 }
 
-func TestNanoecondsToLocalTime(t *testing.T) {
+func TestNanosecondsToLocalTime(t *testing.T) {
 	for _, test := range nanolocaltests {
 		golden := &test.golden
 		nsec := test.seconds*1e9 + int64(golden.Nanosecond)
-		tm := NanosecondsToLocalTime(nsec)
-		newnsec := tm.Nanoseconds()
+		tm := Unix(0, nsec)
+		newnsec := tm.Unix()*1e9 + int64(tm.Nanosecond())
 		if newnsec != nsec {
 			t.Errorf("NanosecondsToLocalTime(%d).Seconds() = %d", nsec, newnsec)
 		}
 		if !same(tm, golden) {
 			t.Errorf("NanosecondsToLocalTime(%d):", nsec)
 			t.Errorf("  want=%+v", *golden)
-			t.Errorf("  have=%+v", *tm)
+			t.Errorf("  have=%+v", tm.Format(RFC3339+" MST"))
 		}
 	}
 }
 
 func TestSecondsToUTCAndBack(t *testing.T) {
-	f := func(sec int64) bool { return SecondsToUTC(sec).Seconds() == sec }
+	f := func(sec int64) bool { return Unix(sec, 0).UTC().Unix() == sec }
 	f32 := func(sec int32) bool { return f(int64(sec)) }
 	cfg := &quick.Config{MaxCount: 10000}
 
@@ -153,7 +173,11 @@ func TestSecondsToUTCAndBack(t *testing.T) {
 }
 
 func TestNanosecondsToUTCAndBack(t *testing.T) {
-	f := func(nsec int64) bool { return NanosecondsToUTC(nsec).Nanoseconds() == nsec }
+	f := func(nsec int64) bool {
+		t := Unix(0, nsec).UTC()
+		ns := t.Unix()*1e9 + int64(t.Nanosecond())
+		return ns == nsec
+	}
 	f32 := func(nsec int32) bool { return f(int64(nsec)) }
 	cfg := &quick.Config{MaxCount: 10000}
 
@@ -173,9 +197,9 @@ type TimeFormatTest struct {
 }
 
 var rfc3339Formats = []TimeFormatTest{
-	{Time{2008, 9, 17, 20, 4, 26, 0, 0, "UTC"}, "2008-09-17T20:04:26Z"},
-	{Time{1994, 9, 17, 20, 4, 26, 0, -18000, "EST"}, "1994-09-17T20:04:26-05:00"},
-	{Time{2000, 12, 26, 1, 15, 6, 0, 15600, "OTO"}, "2000-12-26T01:15:06+04:20"},
+	{Date(2008, 9, 17, 20, 4, 26, 0, UTC), "2008-09-17T20:04:26Z"},
+	{Date(1994, 9, 17, 20, 4, 26, 0, FixedZone("EST", -18000)), "1994-09-17T20:04:26-05:00"},
+	{Date(2000, 12, 26, 1, 15, 6, 0, FixedZone("OTO", 15600)), "2000-12-26T01:15:06+04:20"},
 }
 
 func TestRFC3339Conversion(t *testing.T) {
@@ -201,6 +225,7 @@ var formatTests = []FormatTest{
 	{"RFC822", RFC822, "04 Feb 09 2100 PST"},
 	{"RFC850", RFC850, "Wednesday, 04-Feb-09 21:00:57 PST"},
 	{"RFC1123", RFC1123, "Wed, 04 Feb 2009 21:00:57 PST"},
+	{"RFC1123Z", RFC1123Z, "Wed, 04 Feb 2009 21:00:57 -0800"},
 	{"RFC3339", RFC3339, "2009-02-04T21:00:57-08:00"},
 	{"Kitchen", Kitchen, "9:00PM"},
 	{"am/pm", "3pm", "9pm"},
@@ -215,7 +240,7 @@ var formatTests = []FormatTest{
 
 func TestFormat(t *testing.T) {
 	// The numeric time represents Thu Feb  4 21:00:57.012345678 PST 2010
-	time := NanosecondsToLocalTime(1233810057012345678)
+	time := Unix(0, 1233810057012345678)
 	for _, test := range formatTests {
 		result := time.Format(test.format)
 		if result != test.result {
@@ -228,10 +253,10 @@ type ParseTest struct {
 	name       string
 	format     string
 	value      string
-	hasTZ      bool  // contains a time zone
-	hasWD      bool  // contains a weekday
-	yearSign   int64 // sign of year
-	fracDigits int   // number of digits of fractional second
+	hasTZ      bool // contains a time zone
+	hasWD      bool // contains a weekday
+	yearSign   int  // sign of year
+	fracDigits int  // number of digits of fractional second
 }
 
 var parseTests = []ParseTest{
@@ -240,6 +265,7 @@ var parseTests = []ParseTest{
 	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
 	{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57 PST", true, true, 1, 0},
 	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57 PST", true, true, 1, 0},
+	{"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57 -0800", true, true, 1, 0},
 	{"RFC3339", RFC3339, "2010-02-04T21:00:57-08:00", true, false, 1, 0},
 	{"custom: \"2006-01-02 15:04:05-07\"", "2006-01-02 15:04:05-07", "2010-02-04 21:00:57-08", true, false, 1, 0},
 	// Optional fractional seconds.
@@ -248,10 +274,14 @@ var parseTests = []ParseTest{
 	{"RubyDate", RubyDate, "Thu Feb 04 21:00:57.012 -0800 2010", true, true, 1, 3},
 	{"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57.0123 PST", true, true, 1, 4},
 	{"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57.01234 PST", true, true, 1, 5},
+	{"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57.01234 -0800", true, true, 1, 5},
 	{"RFC3339", RFC3339, "2010-02-04T21:00:57.012345678-08:00", true, false, 1, 9},
 	// Amount of white space should not matter.
 	{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
 	{"ANSIC", ANSIC, "Thu      Feb     4     21:00:57     2010", false, true, 1, 0},
+	// Case should not matter
+	{"ANSIC", ANSIC, "THU FEB 4 21:00:57 2010", false, true, 1, 0},
+	{"ANSIC", ANSIC, "thu feb 4 21:00:57 2010", false, true, 1, 0},
 	// Fractional seconds.
 	{"millisecond", "Mon Jan _2 15:04:05.000 2006", "Thu Feb  4 21:00:57.012 2010", false, true, 1, 3},
 	{"microsecond", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb  4 21:00:57.012345 2010", false, true, 1, 6},
@@ -292,47 +322,48 @@ func TestRubyParse(t *testing.T) {
 	}
 }
 
-func checkTime(time *Time, test *ParseTest, t *testing.T) {
+func checkTime(time Time, test *ParseTest, t *testing.T) {
 	// The time should be Thu Feb  4 21:00:57 PST 2010
-	if test.yearSign*time.Year != 2010 {
-		t.Errorf("%s: bad year: %d not %d", test.name, time.Year, 2010)
+	if test.yearSign*time.Year() != 2010 {
+		t.Errorf("%s: bad year: %d not %d", test.name, time.Year(), 2010)
 	}
-	if time.Month != 2 {
-		t.Errorf("%s: bad month: %d not %d", test.name, time.Month, 2)
+	if time.Month() != February {
+		t.Errorf("%s: bad month: %s not %s", test.name, time.Month(), February)
 	}
-	if time.Day != 4 {
-		t.Errorf("%s: bad day: %d not %d", test.name, time.Day, 4)
+	if time.Day() != 4 {
+		t.Errorf("%s: bad day: %d not %d", test.name, time.Day(), 4)
 	}
-	if time.Hour != 21 {
-		t.Errorf("%s: bad hour: %d not %d", test.name, time.Hour, 21)
+	if time.Hour() != 21 {
+		t.Errorf("%s: bad hour: %d not %d", test.name, time.Hour(), 21)
 	}
-	if time.Minute != 0 {
-		t.Errorf("%s: bad minute: %d not %d", test.name, time.Minute, 0)
+	if time.Minute() != 0 {
+		t.Errorf("%s: bad minute: %d not %d", test.name, time.Minute(), 0)
 	}
-	if time.Second != 57 {
-		t.Errorf("%s: bad second: %d not %d", test.name, time.Second, 57)
+	if time.Second() != 57 {
+		t.Errorf("%s: bad second: %d not %d", test.name, time.Second(), 57)
 	}
 	// Nanoseconds must be checked against the precision of the input.
-	nanosec, err := strconv.Atoui("012345678"[:test.fracDigits] + "000000000"[:9-test.fracDigits])
+	nanosec, err := strconv.ParseUint("012345678"[:test.fracDigits]+"000000000"[:9-test.fracDigits], 10, 0)
 	if err != nil {
 		panic(err)
 	}
-	if time.Nanosecond != int(nanosec) {
-		t.Errorf("%s: bad nanosecond: %d not %d", test.name, time.Nanosecond, nanosec)
+	if time.Nanosecond() != int(nanosec) {
+		t.Errorf("%s: bad nanosecond: %d not %d", test.name, time.Nanosecond(), nanosec)
 	}
-	if test.hasTZ && time.ZoneOffset != -28800 {
-		t.Errorf("%s: bad tz offset: %d not %d", test.name, time.ZoneOffset, -28800)
+	name, offset := time.Zone()
+	if test.hasTZ && offset != -28800 {
+		t.Errorf("%s: bad tz offset: %s %d not %d", test.name, name, offset, -28800)
 	}
-	if test.hasWD && time.Weekday() != 4 {
-		t.Errorf("%s: bad weekday: %d not %d", test.name, time.Weekday(), 4)
+	if test.hasWD && time.Weekday() != Thursday {
+		t.Errorf("%s: bad weekday: %s not %s", test.name, time.Weekday(), Thursday)
 	}
 }
 
 func TestFormatAndParse(t *testing.T) {
 	const fmt = "Mon MST " + RFC3339 // all fields
 	f := func(sec int64) bool {
-		t1 := SecondsToLocalTime(sec)
-		if t1.Year < 1000 || t1.Year > 9999 {
+		t1 := Unix(sec, 0)
+		if t1.Year() < 1000 || t1.Year() > 9999 {
 			// not required to work
 			return true
 		}
@@ -341,8 +372,8 @@ func TestFormatAndParse(t *testing.T) {
 			t.Errorf("error: %s", err)
 			return false
 		}
-		if !same(t1, t2) {
-			t.Errorf("different: %q %q", t1, t2)
+		if t1.Unix() != t2.Unix() || t1.Nanosecond() != t2.Nanosecond() {
+			t.Errorf("FormatAndParse %d: %q(%d) %q(%d)", sec, t1, t1.Unix(), t2, t2.Unix())
 			return false
 		}
 		return true
@@ -381,14 +412,14 @@ func TestParseErrors(t *testing.T) {
 		_, err := Parse(test.format, test.value)
 		if err == nil {
 			t.Errorf("expected error for %q %q", test.format, test.value)
-		} else if strings.Index(err.String(), test.expect) < 0 {
+		} else if strings.Index(err.Error(), test.expect) < 0 {
 			t.Errorf("expected error with %q for %q %q; got %s", test.expect, test.format, test.value, err)
 		}
 	}
 }
 
 func TestNoonIs12PM(t *testing.T) {
-	noon := Time{Hour: 12}
+	noon := Date(0, January, 1, 12, 0, 0, 0, UTC)
 	const expect = "12:00PM"
 	got := noon.Format("3:04PM")
 	if got != expect {
@@ -401,7 +432,7 @@ func TestNoonIs12PM(t *testing.T) {
 }
 
 func TestMidnightIs12AM(t *testing.T) {
-	midnight := Time{Hour: 0}
+	midnight := Date(0, January, 1, 0, 0, 0, 0, UTC)
 	expect := "12:00AM"
 	got := midnight.Format("3:04PM")
 	if got != expect {
@@ -418,15 +449,15 @@ func Test12PMIsNoon(t *testing.T) {
 	if err != nil {
 		t.Fatal("error parsing date:", err)
 	}
-	if noon.Hour != 12 {
-		t.Errorf("got %d; expect 12", noon.Hour)
+	if noon.Hour() != 12 {
+		t.Errorf("got %d; expect 12", noon.Hour())
 	}
 	noon, err = Parse("03:04PM", "12:00PM")
 	if err != nil {
 		t.Fatal("error parsing date:", err)
 	}
-	if noon.Hour != 12 {
-		t.Errorf("got %d; expect 12", noon.Hour)
+	if noon.Hour() != 12 {
+		t.Errorf("got %d; expect 12", noon.Hour())
 	}
 }
 
@@ -435,15 +466,15 @@ func Test12AMIsMidnight(t *testing.T) {
 	if err != nil {
 		t.Fatal("error parsing date:", err)
 	}
-	if midnight.Hour != 0 {
-		t.Errorf("got %d; expect 0", midnight.Hour)
+	if midnight.Hour() != 0 {
+		t.Errorf("got %d; expect 0", midnight.Hour())
 	}
 	midnight, err = Parse("03:04PM", "12:00AM")
 	if err != nil {
 		t.Fatal("error parsing date:", err)
 	}
-	if midnight.Hour != 0 {
-		t.Errorf("got %d; expect 0", midnight.Hour)
+	if midnight.Hour() != 0 {
+		t.Errorf("got %d; expect 0", midnight.Hour())
 	}
 }
 
@@ -457,7 +488,7 @@ func TestMissingZone(t *testing.T) {
 	expect := "Thu Feb  2 16:10:03 -0500 2006" // -0500 not EST
 	str := time.Format(UnixDate)               // uses MST as its time zone
 	if str != expect {
-		t.Errorf("expected %q got %q", expect, str)
+		t.Errorf("got %s; expect %s", str, expect)
 	}
 }
 
@@ -467,25 +498,409 @@ func TestMinutesInTimeZone(t *testing.T) {
 		t.Fatal("error parsing date:", err)
 	}
 	expected := (1*60 + 23) * 60
-	if time.ZoneOffset != expected {
-		t.Errorf("ZoneOffset incorrect, expected %d got %d", expected, time.ZoneOffset)
+	_, offset := time.Zone()
+	if offset != expected {
+		t.Errorf("ZoneOffset = %d, want %d", offset, expected)
+	}
+}
+
+type ISOWeekTest struct {
+	year       int // year
+	month, day int // month and day
+	yex        int // expected year
+	wex        int // expected week
+}
+
+var isoWeekTests = []ISOWeekTest{
+	{1981, 1, 1, 1981, 1}, {1982, 1, 1, 1981, 53}, {1983, 1, 1, 1982, 52},
+	{1984, 1, 1, 1983, 52}, {1985, 1, 1, 1985, 1}, {1986, 1, 1, 1986, 1},
+	{1987, 1, 1, 1987, 1}, {1988, 1, 1, 1987, 53}, {1989, 1, 1, 1988, 52},
+	{1990, 1, 1, 1990, 1}, {1991, 1, 1, 1991, 1}, {1992, 1, 1, 1992, 1},
+	{1993, 1, 1, 1992, 53}, {1994, 1, 1, 1993, 52}, {1995, 1, 2, 1995, 1},
+	{1996, 1, 1, 1996, 1}, {1996, 1, 7, 1996, 1}, {1996, 1, 8, 1996, 2},
+	{1997, 1, 1, 1997, 1}, {1998, 1, 1, 1998, 1}, {1999, 1, 1, 1998, 53},
+	{2000, 1, 1, 1999, 52}, {2001, 1, 1, 2001, 1}, {2002, 1, 1, 2002, 1},
+	{2003, 1, 1, 2003, 1}, {2004, 1, 1, 2004, 1}, {2005, 1, 1, 2004, 53},
+	{2006, 1, 1, 2005, 52}, {2007, 1, 1, 2007, 1}, {2008, 1, 1, 2008, 1},
+	{2009, 1, 1, 2009, 1}, {2010, 1, 1, 2009, 53}, {2010, 1, 1, 2009, 53},
+	{2011, 1, 1, 2010, 52}, {2011, 1, 2, 2010, 52}, {2011, 1, 3, 2011, 1},
+	{2011, 1, 4, 2011, 1}, {2011, 1, 5, 2011, 1}, {2011, 1, 6, 2011, 1},
+	{2011, 1, 7, 2011, 1}, {2011, 1, 8, 2011, 1}, {2011, 1, 9, 2011, 1},
+	{2011, 1, 10, 2011, 2}, {2011, 1, 11, 2011, 2}, {2011, 6, 12, 2011, 23},
+	{2011, 6, 13, 2011, 24}, {2011, 12, 25, 2011, 51}, {2011, 12, 26, 2011, 52},
+	{2011, 12, 27, 2011, 52}, {2011, 12, 28, 2011, 52}, {2011, 12, 29, 2011, 52},
+	{2011, 12, 30, 2011, 52}, {2011, 12, 31, 2011, 52}, {1995, 1, 1, 1994, 52},
+	{2012, 1, 1, 2011, 52}, {2012, 1, 2, 2012, 1}, {2012, 1, 8, 2012, 1},
+	{2012, 1, 9, 2012, 2}, {2012, 12, 23, 2012, 51}, {2012, 12, 24, 2012, 52},
+	{2012, 12, 30, 2012, 52}, {2012, 12, 31, 2013, 1}, {2013, 1, 1, 2013, 1},
+	{2013, 1, 6, 2013, 1}, {2013, 1, 7, 2013, 2}, {2013, 12, 22, 2013, 51},
+	{2013, 12, 23, 2013, 52}, {2013, 12, 29, 2013, 52}, {2013, 12, 30, 2014, 1},
+	{2014, 1, 1, 2014, 1}, {2014, 1, 5, 2014, 1}, {2014, 1, 6, 2014, 2},
+	{2015, 1, 1, 2015, 1}, {2016, 1, 1, 2015, 53}, {2017, 1, 1, 2016, 52},
+	{2018, 1, 1, 2018, 1}, {2019, 1, 1, 2019, 1}, {2020, 1, 1, 2020, 1},
+	{2021, 1, 1, 2020, 53}, {2022, 1, 1, 2021, 52}, {2023, 1, 1, 2022, 52},
+	{2024, 1, 1, 2024, 1}, {2025, 1, 1, 2025, 1}, {2026, 1, 1, 2026, 1},
+	{2027, 1, 1, 2026, 53}, {2028, 1, 1, 2027, 52}, {2029, 1, 1, 2029, 1},
+	{2030, 1, 1, 2030, 1}, {2031, 1, 1, 2031, 1}, {2032, 1, 1, 2032, 1},
+	{2033, 1, 1, 2032, 53}, {2034, 1, 1, 2033, 52}, {2035, 1, 1, 2035, 1},
+	{2036, 1, 1, 2036, 1}, {2037, 1, 1, 2037, 1}, {2038, 1, 1, 2037, 53},
+	{2039, 1, 1, 2038, 52}, {2040, 1, 1, 2039, 52},
+}
+
+func TestISOWeek(t *testing.T) {
+	// Selected dates and corner cases
+	for _, wt := range isoWeekTests {
+		dt := Date(wt.year, Month(wt.month), wt.day, 0, 0, 0, 0, UTC)
+		y, w := dt.ISOWeek()
+		if w != wt.wex || y != wt.yex {
+			t.Errorf("got %d/%d; expected %d/%d for %d-%02d-%02d",
+				y, w, wt.yex, wt.wex, wt.year, wt.month, wt.day)
+		}
+	}
+
+	// The only real invariant: Jan 04 is in week 1
+	for year := 1950; year < 2100; year++ {
+		if y, w := Date(year, January, 4, 0, 0, 0, 0, UTC).ISOWeek(); y != year || w != 1 {
+			t.Errorf("got %d/%d; expected %d/1 for Jan 04", y, w, year)
+		}
 	}
 }
 
-func BenchmarkSeconds(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		Seconds()
+var durationTests = []struct {
+	str string
+	d   Duration
+}{
+	{"0", 0},
+	{"1ns", 1 * Nanosecond},
+	{"1.1us", 1100 * Nanosecond},
+	{"2.2ms", 2200 * Microsecond},
+	{"3.3s", 3300 * Millisecond},
+	{"4m5s", 4*Minute + 5*Second},
+	{"4m5.001s", 4*Minute + 5001*Millisecond},
+	{"5h6m7.001s", 5*Hour + 6*Minute + 7001*Millisecond},
+	{"8m0.000000001s", 8*Minute + 1*Nanosecond},
+	{"2562047h47m16.854775807s", 1<<63 - 1},
+	{"-2562047h47m16.854775808s", -1 << 63},
+}
+
+func TestDurationString(t *testing.T) {
+	for _, tt := range durationTests {
+		if str := tt.d.String(); str != tt.str {
+			t.Errorf("Duration(%d).String() = %s, want %s", int64(tt.d), str, tt.str)
+		}
+		if tt.d > 0 {
+			if str := (-tt.d).String(); str != "-"+tt.str {
+				t.Errorf("Duration(%d).String() = %s, want %s", int64(-tt.d), str, "-"+tt.str)
+			}
+		}
 	}
 }
 
-func BenchmarkNanoseconds(b *testing.B) {
+var dateTests = []struct {
+	year, month, day, hour, min, sec, nsec int
+	z                                      *Location
+	unix                                   int64
+}{
+	{2011, 11, 6, 1, 0, 0, 0, Local, 1320566400},   // 1:00:00 PDT
+	{2011, 11, 6, 1, 59, 59, 0, Local, 1320569999}, // 1:59:59 PDT
+	{2011, 11, 6, 2, 0, 0, 0, Local, 1320573600},   // 2:00:00 PST
+
+	{2011, 3, 13, 1, 0, 0, 0, Local, 1300006800},   // 1:00:00 PST
+	{2011, 3, 13, 1, 59, 59, 0, Local, 1300010399}, // 1:59:59 PST
+	{2011, 3, 13, 3, 0, 0, 0, Local, 1300010400},   // 3:00:00 PDT
+	{2011, 3, 13, 2, 30, 0, 0, Local, 1300008600},  // 2:30:00 PDT ≡ 1:30 PST
+
+	// Many names for Fri Nov 18 7:56:35 PST 2011
+	{2011, 11, 18, 7, 56, 35, 0, Local, 1321631795},                 // Nov 18 7:56:35
+	{2011, 11, 19, -17, 56, 35, 0, Local, 1321631795},               // Nov 19 -17:56:35
+	{2011, 11, 17, 31, 56, 35, 0, Local, 1321631795},                // Nov 17 31:56:35
+	{2011, 11, 18, 6, 116, 35, 0, Local, 1321631795},                // Nov 18 6:116:35
+	{2011, 10, 49, 7, 56, 35, 0, Local, 1321631795},                 // Oct 49 7:56:35
+	{2011, 11, 18, 7, 55, 95, 0, Local, 1321631795},                 // Nov 18 7:55:95
+	{2011, 11, 18, 7, 56, 34, 1e9, Local, 1321631795},               // Nov 18 7:56:34 + 10⁹ns
+	{2011, 12, -12, 7, 56, 35, 0, Local, 1321631795},                // Dec -21 7:56:35
+	{2012, 1, -43, 7, 56, 35, 0, Local, 1321631795},                 // Jan -52 7:56:35 2012
+	{2012, int(January - 2), 18, 7, 56, 35, 0, Local, 1321631795},   // (Jan-2) 18 7:56:35 2012
+	{2010, int(December + 11), 18, 7, 56, 35, 0, Local, 1321631795}, // (Dec+11) 18 7:56:35 2010
+}
+
+func TestDate(t *testing.T) {
+	for _, tt := range dateTests {
+		time := Date(tt.year, Month(tt.month), tt.day, tt.hour, tt.min, tt.sec, tt.nsec, tt.z)
+		want := Unix(tt.unix, 0)
+		if !time.Equal(want) {
+			t.Errorf("Date(%d, %d, %d, %d, %d, %d, %d, %s) = %v, want %v",
+				tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec, tt.nsec, tt.z,
+				time, want)
+		}
+	}
+}
+
+// Several ways of getting from
+// Fri Nov 18 7:56:35 PST 2011
+// to
+// Thu Mar 19 7:56:35 PST 2016
+var addDateTests = []struct {
+	years, months, days int
+}{
+	{4, 4, 1},
+	{3, 16, 1},
+	{3, 15, 30},
+	{5, -6, -18 - 30 - 12},
+}
+
+func TestAddDate(t *testing.T) {
+	t0 := Date(2011, 11, 18, 7, 56, 35, 0, UTC)
+	t1 := Date(2016, 3, 19, 7, 56, 35, 0, UTC)
+	for _, at := range addDateTests {
+		time := t0.AddDate(at.years, at.months, at.days)
+		if !time.Equal(t1) {
+			t.Errorf("AddDate(%d, %d, %d) = %v, want %v",
+				at.years, at.months, at.days,
+				time, t1)
+		}
+	}
+}
+
+var daysInTests = []struct {
+	year, month, di int
+}{
+	{2011, 1, 31},  // January, first month, 31 days
+	{2011, 2, 28},  // February, non-leap year, 28 days
+	{2012, 2, 29},  // February, leap year, 29 days
+	{2011, 6, 30},  // June, 30 days
+	{2011, 12, 31}, // December, last month, 31 days
+}
+
+func TestDaysIn(t *testing.T) {
+	// The daysIn function is not exported.
+	// Test the daysIn function via the `var DaysIn = daysIn`
+	// statement in the internal_test.go file.
+	for _, tt := range daysInTests {
+		di := DaysIn(Month(tt.month), tt.year)
+		if di != tt.di {
+			t.Errorf("got %d; expected %d for %d-%02d",
+				di, tt.di, tt.year, tt.month)
+		}
+	}
+}
+
+func TestAddToExactSecond(t *testing.T) {
+	// Add an amount to the current time to round it up to the next exact second.
+	// This test checks that the nsec field still lies within the range [0, 999999999].
+	t1 := Now()
+	t2 := t1.Add(Second - Duration(t1.Nanosecond()))
+	sec := (t1.Second() + 1) % 60
+	if t2.Second() != sec || t2.Nanosecond() != 0 {
+		t.Errorf("sec = %d, nsec = %d, want sec = %d, nsec = 0", t2.Second(), t2.Nanosecond(), sec)
+	}
+}
+
+func equalTimeAndZone(a, b Time) bool {
+	aname, aoffset := a.Zone()
+	bname, boffset := b.Zone()
+	return a.Equal(b) && aoffset == boffset && aname == bname
+}
+
+var gobTests = []Time{
+	Date(0, 1, 2, 3, 4, 5, 6, UTC),
+	Date(7, 8, 9, 10, 11, 12, 13, FixedZone("", 0)),
+	Unix(81985467080890095, 0x76543210), // Time.sec: 0x0123456789ABCDEF
+	Time{},                              // nil location
+	Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", 32767*60)),
+	Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", -32768*60)),
+}
+
+func TestTimeGob(t *testing.T) {
+	var b bytes.Buffer
+	enc := gob.NewEncoder(&b)
+	dec := gob.NewDecoder(&b)
+	for _, tt := range gobTests {
+		var gobtt Time
+		if err := enc.Encode(&tt); err != nil {
+			t.Errorf("%v gob Encode error = %q, want nil", tt, err)
+		} else if err := dec.Decode(&gobtt); err != nil {
+			t.Errorf("%v gob Decode error = %q, want nil", tt, err)
+		} else if !equalTimeAndZone(gobtt, tt) {
+			t.Errorf("Decoded time = %v, want %v", gobtt, tt)
+		}
+		b.Reset()
+	}
+}
+
+var invalidEncodingTests = []struct {
+	bytes []byte
+	want  string
+}{
+	{[]byte{}, "Time.GobDecode: no data"},
+	{[]byte{0, 2, 3}, "Time.GobDecode: unsupported version"},
+	{[]byte{1, 2, 3}, "Time.GobDecode: invalid length"},
+}
+
+func TestInvalidTimeGob(t *testing.T) {
+	for _, tt := range invalidEncodingTests {
+		var ignored Time
+		err := ignored.GobDecode(tt.bytes)
+		if err == nil || err.Error() != tt.want {
+			t.Errorf("time.GobDecode(%#v) error = %v, want %v", tt.bytes, err, tt.want)
+		}
+	}
+}
+
+var notEncodableTimes = []struct {
+	time Time
+	want string
+}{
+	{Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 1)), "Time.GobEncode: zone offset has fractional minute"},
+	{Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -1*60)), "Time.GobEncode: unexpected zone offset"},
+	{Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -32769*60)), "Time.GobEncode: unexpected zone offset"},
+	{Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 32768*60)), "Time.GobEncode: unexpected zone offset"},
+}
+
+func TestNotGobEncodableTime(t *testing.T) {
+	for _, tt := range notEncodableTimes {
+		_, err := tt.time.GobEncode()
+		if err == nil || err.Error() != tt.want {
+			t.Errorf("%v GobEncode error = %v, want %v", tt.time, err, tt.want)
+		}
+	}
+}
+
+var jsonTests = []struct {
+	time Time
+	json string
+}{
+	{Date(9999, 4, 12, 23, 20, 50, .52*1e9, UTC), `"9999-04-12T23:20:50.52Z"`},
+	{Date(1996, 12, 19, 16, 39, 57, 0, Local), `"1996-12-19T16:39:57-08:00"`},
+	{Date(0, 1, 1, 0, 0, 0, 1, FixedZone("", 1*60)), `"0000-01-01T00:00:00.000000001+00:01"`},
+}
+
+func TestTimeJSON(t *testing.T) {
+	for _, tt := range jsonTests {
+		var jsonTime Time
+
+		if jsonBytes, err := json.Marshal(tt.time); err != nil {
+			t.Errorf("%v json.Marshal error = %v, want nil", tt.time, err)
+		} else if string(jsonBytes) != tt.json {
+			t.Errorf("%v JSON = %q, want %q", tt.time, string(jsonBytes), tt.json)
+		} else if err = json.Unmarshal(jsonBytes, &jsonTime); err != nil {
+			t.Errorf("%v json.Unmarshal error = %v, want nil", tt.time, err)
+		} else if !equalTimeAndZone(jsonTime, tt.time) {
+			t.Errorf("Unmarshaled time = %v, want %v", jsonTime, tt.time)
+		}
+	}
+}
+
+func TestInvalidTimeJSON(t *testing.T) {
+	var tt Time
+	err := json.Unmarshal([]byte(`{"now is the time":"buddy"}`), &tt)
+	_, isParseErr := err.(*ParseError)
+	if !isParseErr {
+		t.Errorf("expected *time.ParseError unmarshaling JSON, got %v", err)
+	}
+}
+
+var notJSONEncodableTimes = []struct {
+	time Time
+	want string
+}{
+	{Date(10000, 1, 1, 0, 0, 0, 0, UTC), "Time.MarshalJSON: year outside of range [0,9999]"},
+	{Date(-1, 1, 1, 0, 0, 0, 0, UTC), "Time.MarshalJSON: year outside of range [0,9999]"},
+}
+
+func TestNotJSONEncodableTime(t *testing.T) {
+	for _, tt := range notJSONEncodableTimes {
+		_, err := tt.time.MarshalJSON()
+		if err == nil || err.Error() != tt.want {
+			t.Errorf("%v MarshalJSON error = %v, want %v", tt.time, err, tt.want)
+		}
+	}
+}
+
+var parseDurationTests = []struct {
+	in   string
+	ok   bool
+	want Duration
+}{
+	// simple
+	{"0", true, 0},
+	{"5s", true, 5 * Second},
+	{"30s", true, 30 * Second},
+	{"1478s", true, 1478 * Second},
+	// sign
+	{"-5s", true, -5 * Second},
+	{"+5s", true, 5 * Second},
+	{"-0", true, 0},
+	{"+0", true, 0},
+	// decimal
+	{"5.0s", true, 5 * Second},
+	{"5.6s", true, 5*Second + 600*Millisecond},
+	{"5.s", true, 5 * Second},
+	{".5s", true, 500 * Millisecond},
+	{"1.0s", true, 1 * Second},
+	{"1.00s", true, 1 * Second},
+	{"1.004s", true, 1*Second + 4*Millisecond},
+	{"1.0040s", true, 1*Second + 4*Millisecond},
+	{"100.00100s", true, 100*Second + 1*Millisecond},
+	// different units
+	{"10ns", true, 10 * Nanosecond},
+	{"11us", true, 11 * Microsecond},
+	{"12µs", true, 12 * Microsecond}, // U+00B5
+	{"12μs", true, 12 * Microsecond}, // U+03BC
+	{"13ms", true, 13 * Millisecond},
+	{"14s", true, 14 * Second},
+	{"15m", true, 15 * Minute},
+	{"16h", true, 16 * Hour},
+	// composite durations
+	{"3h30m", true, 3*Hour + 30*Minute},
+	{"10.5s4m", true, 4*Minute + 10*Second + 500*Millisecond},
+	{"-2m3.4s", true, -(2*Minute + 3*Second + 400*Millisecond)},
+	{"1h2m3s4ms5us6ns", true, 1*Hour + 2*Minute + 3*Second + 4*Millisecond + 5*Microsecond + 6*Nanosecond},
+	{"39h9m14.425s", true, 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
+
+	// errors
+	{"", false, 0},
+	{"3", false, 0},
+	{"-", false, 0},
+	{"s", false, 0},
+	{".", false, 0},
+	{"-.", false, 0},
+	{".s", false, 0},
+	{"+.s", false, 0},
+}
+
+func TestParseDuration(t *testing.T) {
+	for _, tc := range parseDurationTests {
+		d, err := ParseDuration(tc.in)
+		if tc.ok && (err != nil || d != tc.want) {
+			t.Errorf("ParseDuration(%q) = %v, %v, want %v, nil", tc.in, d, err, tc.want)
+		} else if !tc.ok && err == nil {
+			t.Errorf("ParseDuration(%q) = _, nil, want _, non-nil", tc.in)
+		}
+	}
+}
+
+func TestParseDurationRoundTrip(t *testing.T) {
+	for i := 0; i < 100; i++ {
+		// Resolutions finer than milliseconds will result in
+		// imprecise round-trips.
+		d0 := Duration(rand.Int31()) * Millisecond
+		s := d0.String()
+		d1, err := ParseDuration(s)
+		if err != nil || d0 != d1 {
+			t.Errorf("round-trip failed: %d => %q => %d, %v", d0, s, d1, err)
+		}
+	}
+}
+
+func BenchmarkNow(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		Nanoseconds()
+		Now()
 	}
 }
 
 func BenchmarkFormat(b *testing.B) {
-	time := SecondsToLocalTime(1265346057)
+	time := Unix(1265346057, 0)
 	for i := 0; i < b.N; i++ {
 		time.Format("Mon Jan  2 15:04:05 2006")
 	}
@@ -496,3 +911,31 @@ func BenchmarkParse(b *testing.B) {
 		Parse(ANSIC, "Mon Jan  2 15:04:05 2006")
 	}
 }
+
+func BenchmarkHour(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		_ = t.Hour()
+	}
+}
+
+func BenchmarkSecond(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		_ = t.Second()
+	}
+}
+
+func BenchmarkYear(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		_ = t.Year()
+	}
+}
+
+func BenchmarkDay(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		_ = t.Day()
+	}
+}
diff --git a/src/pkg/time/zoneinfo.go b/src/pkg/time/zoneinfo.go
new file mode 100644
index 0000000..aca56e7
--- /dev/null
+++ b/src/pkg/time/zoneinfo.go
@@ -0,0 +1,191 @@
+// Copyright 2011 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 time
+
+import "sync"
+
+// A Location maps time instants to the zone in use at that time.
+// Typically, the Location represents the collection of time offsets
+// in use in a geographical area, such as CEST and CET for central Europe.
+type Location struct {
+	name string
+	zone []zone
+	tx   []zoneTrans
+
+	// Most lookups will be for the current time.
+	// To avoid the binary search through tx, keep a
+	// static one-element cache that gives the correct
+	// zone for the time when the Location was created.
+	// if cacheStart <= t <= cacheEnd,
+	// lookup can return cacheZone.
+	// The units for cacheStart and cacheEnd are seconds
+	// since January 1, 1970 UTC, to match the argument
+	// to lookup.
+	cacheStart int64
+	cacheEnd   int64
+	cacheZone  *zone
+}
+
+// A zone represents a single time zone such as CEST or CET.
+type zone struct {
+	name   string // abbreviated name, "CET"
+	offset int    // seconds east of UTC
+	isDST  bool   // is this zone Daylight Savings Time?
+}
+
+// A zoneTrans represents a single time zone transition.
+type zoneTrans struct {
+	when         int64 // transition time, in seconds since 1970 GMT
+	index        uint8 // the index of the zone that goes into effect at that time
+	isstd, isutc bool  // ignored - no idea what these mean
+}
+
+// UTC represents Universal Coordinated Time (UTC).
+var UTC *Location = &utcLoc
+
+// utcLoc is separate so that get can refer to &utcLoc
+// and ensure that it never returns a nil *Location,
+// even if a badly behaved client has changed UTC.
+var utcLoc = Location{name: "UTC"}
+
+// Local represents the system's local time zone.
+var Local *Location = &localLoc
+
+// localLoc is separate so that initLocal can initialize
+// it even if a client has changed Local.
+var localLoc Location
+var localOnce sync.Once
+
+func (l *Location) get() *Location {
+	if l == nil {
+		return &utcLoc
+	}
+	if l == &localLoc {
+		localOnce.Do(initLocal)
+	}
+	return l
+}
+
+// String returns a descriptive name for the time zone information,
+// corresponding to the argument to LoadLocation.
+func (l *Location) String() string {
+	return l.get().name
+}
+
+// FixedZone returns a Location that always uses
+// the given zone name and offset (seconds east of UTC).
+func FixedZone(name string, offset int) *Location {
+	l := &Location{
+		name:       name,
+		zone:       []zone{{name, offset, false}},
+		tx:         []zoneTrans{{-1 << 63, 0, false, false}},
+		cacheStart: -1 << 63,
+		cacheEnd:   1<<63 - 1,
+	}
+	l.cacheZone = &l.zone[0]
+	return l
+}
+
+// lookup returns information about the time zone in use at an
+// instant in time expressed as seconds since January 1, 1970 00:00:00 UTC.
+//
+// The returned information gives the name of the zone (such as "CET"),
+// the start and end times bracketing sec when that zone is in effect,
+// the offset in seconds east of UTC (such as -5*60*60), and whether
+// the daylight savings is being observed at that time.
+func (l *Location) lookup(sec int64) (name string, offset int, isDST bool, start, end int64) {
+	l = l.get()
+
+	if len(l.tx) == 0 {
+		name = "UTC"
+		offset = 0
+		isDST = false
+		start = -1 << 63
+		end = 1<<63 - 1
+		return
+	}
+
+	if zone := l.cacheZone; zone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
+		name = zone.name
+		offset = zone.offset
+		isDST = zone.isDST
+		start = l.cacheStart
+		end = l.cacheEnd
+		return
+	}
+
+	// Binary search for entry with largest time <= sec.
+	// Not using sort.Search to avoid dependencies.
+	tx := l.tx
+	end = 1<<63 - 1
+	for len(tx) > 1 {
+		m := len(tx) / 2
+		lim := tx[m].when
+		if sec < lim {
+			end = lim
+			tx = tx[0:m]
+		} else {
+			tx = tx[m:]
+		}
+	}
+	zone := &l.zone[tx[0].index]
+	name = zone.name
+	offset = zone.offset
+	isDST = zone.isDST
+	start = tx[0].when
+	// end = maintained during the search
+	return
+}
+
+// lookupName returns information about the time zone with
+// the given name (such as "EST").
+func (l *Location) lookupName(name string) (offset int, isDST bool, ok bool) {
+	l = l.get()
+	for i := range l.zone {
+		zone := &l.zone[i]
+		if zone.name == name {
+			return zone.offset, zone.isDST, true
+		}
+	}
+	return
+}
+
+// lookupOffset returns information about the time zone with
+// the given offset (such as -5*60*60).
+func (l *Location) lookupOffset(offset int) (name string, isDST bool, ok bool) {
+	l = l.get()
+	for i := range l.zone {
+		zone := &l.zone[i]
+		if zone.offset == offset {
+			return zone.name, zone.isDST, true
+		}
+	}
+	return
+}
+
+// NOTE(rsc): Eventually we will need to accept the POSIX TZ environment
+// syntax too, but I don't feel like implementing it today.
+
+// NOTE(rsc): Using the IANA names below means ensuring we have access
+// to the database.  Probably we will ship the files in $GOROOT/lib/zoneinfo/
+// and only look there if there are no system files available (such as on Windows).
+// The files total 200 kB.
+
+// LoadLocation returns the Location with the given name.
+//
+// If the name is "" or "UTC", LoadLocation returns UTC.
+// If the name is "Local", LoadLocation returns Local.
+//
+// Otherwise, the name is taken to be a location name corresponding to a file
+// in the IANA Time Zone database, such as "America/New_York".
+func LoadLocation(name string) (*Location, error) {
+	if name == "" || name == "UTC" {
+		return UTC, nil
+	}
+	if name == "Local" {
+		return Local, nil
+	}
+	return loadLocation(name)
+}
diff --git a/src/pkg/time/zoneinfo_plan9.go b/src/pkg/time/zoneinfo_plan9.go
index 577ef85..9c052d4 100644
--- a/src/pkg/time/zoneinfo_plan9.go
+++ b/src/pkg/time/zoneinfo_plan9.go
@@ -7,69 +7,151 @@
 package time
 
 import (
-	"os"
-	"strconv"
-	"strings"
+	"errors"
+	"syscall"
 )
 
-func parseZones(s string) (zt []zonetime) {
-	f := strings.Fields(s)
+var badData = errors.New("malformed time zone information")
+
+func isSpace(r rune) bool {
+	return r == ' ' || r == '\t' || r == '\n'
+}
+
+// Copied from strings to avoid a dependency.
+func fields(s string) []string {
+	// First count the fields.
+	n := 0
+	inField := false
+	for _, rune := range s {
+		wasInField := inField
+		inField = !isSpace(rune)
+		if inField && !wasInField {
+			n++
+		}
+	}
+
+	// Now create them.
+	a := make([]string, n)
+	na := 0
+	fieldStart := -1 // Set to -1 when looking for start of field.
+	for i, rune := range s {
+		if isSpace(rune) {
+			if fieldStart >= 0 {
+				a[na] = s[fieldStart:i]
+				na++
+				fieldStart = -1
+			}
+		} else if fieldStart == -1 {
+			fieldStart = i
+		}
+	}
+	if fieldStart >= 0 { // Last field might end at EOF.
+		a[na] = s[fieldStart:]
+	}
+	return a
+}
+
+func loadZoneData(s string) (l *Location, err error) {
+	f := fields(s)
 	if len(f) < 4 {
-		return
+		if len(f) == 2 && f[0] == "GMT" {
+			return UTC, nil
+		}
+		return nil, badData
 	}
 
+	var zones [2]zone
+
 	// standard timezone offset
-	o, err := strconv.Atoi(f[1])
+	o, err := atoi(f[1])
 	if err != nil {
-		return
+		return nil, badData
 	}
-	std := &zone{name: f[0], utcoff: o, isdst: false}
+	zones[0] = zone{name: f[0], offset: o, isDST: false}
 
 	// alternate timezone offset
-	o, err = strconv.Atoi(f[3])
+	o, err = atoi(f[3])
 	if err != nil {
-		return
+		return nil, badData
 	}
-	dst := &zone{name: f[2], utcoff: o, isdst: true}
+	zones[1] = zone{name: f[2], offset: o, isDST: true}
 
 	// transition time pairs
+	var tx []zoneTrans
 	f = f[4:]
 	for i := 0; i < len(f); i++ {
-		z := std
+		zi := 0
 		if i%2 == 0 {
-			z = dst
+			zi = 1
 		}
-		t, err := strconv.Atoi(f[i])
+		t, err := atoi(f[i])
 		if err != nil {
-			return nil
+			return nil, badData
+		}
+		t -= zones[0].offset
+		tx = append(tx, zoneTrans{when: int64(t), index: uint8(zi)})
+	}
+
+	// Committed to succeed.
+	l = &Location{zone: zones[:], tx: tx}
+
+	// Fill in the cache with information about right now,
+	// since that will be the most common lookup.
+	sec, _ := now()
+	for i := range tx {
+		if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
+			l.cacheStart = tx[i].when
+			l.cacheEnd = 1<<63 - 1
+			if i+1 < len(tx) {
+				l.cacheEnd = tx[i+1].when
+			}
+			l.cacheZone = &l.zone[tx[i].index]
 		}
-		t -= std.utcoff
-		zt = append(zt, zonetime{time: int32(t), zone: z})
 	}
-	return
+
+	return l, nil
 }
 
-func setupZone() {
-	t, err := os.Getenverror("timezone")
+func loadZoneFile(name string) (*Location, error) {
+	b, err := readFile(name)
 	if err != nil {
-		// do nothing: use UTC
-		return
+		return nil, err
 	}
-	zones = parseZones(t)
+	return loadZoneData(string(b))
 }
 
-func setupTestingZone() {
-	f, err := os.Open("/adm/timezone/US_Pacific")
-	if err != nil {
+func initTestingZone() {
+	if z, err := loadZoneFile("/adm/timezone/US_Pacific"); err == nil {
+		localLoc = *z
 		return
 	}
-	defer f.Close()
-	l, _ := f.Seek(0, 2)
-	f.Seek(0, 0)
-	buf := make([]byte, l)
-	_, err = f.Read(buf)
-	if err != nil {
-		return
+
+	// Fall back to UTC.
+	localLoc.name = "UTC"
+}
+
+func initLocal() {
+	t, ok := syscall.Getenv("timezone")
+	if ok {
+		if z, err := loadZoneData(t); err == nil {
+			localLoc = *z
+			return
+		}
+	} else {
+		if z, err := loadZoneFile("/adm/timezone/local"); err == nil {
+			localLoc = *z
+			localLoc.name = "Local"
+			return
+		}
+	}
+
+	// Fall back to UTC.
+	localLoc.name = "UTC"
+}
+
+func loadLocation(name string) (*Location, error) {
+	if z, err := loadZoneFile("/adm/timezone/" + name); err == nil {
+		return z, nil
 	}
-	zones = parseZones(string(buf))
+	return nil, errors.New("unknown time zone " + name)
 }
diff --git a/src/pkg/time/zoneinfo_posix.go b/src/pkg/time/zoneinfo_posix.go
deleted file mode 100644
index b0fa6c3..0000000
--- a/src/pkg/time/zoneinfo_posix.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2011 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 darwin freebsd linux openbsd plan9
-
-package time
-
-import "sync"
-
-// Parsed representation
-type zone struct {
-	utcoff int
-	isdst  bool
-	name   string
-}
-
-type zonetime struct {
-	time         int32 // transition time, in seconds since 1970 GMT
-	zone         *zone // the zone that goes into effect at that time
-	isstd, isutc bool  // ignored - no idea what these mean
-}
-
-var zones []zonetime
-var onceSetupZone sync.Once
-
-// Look up the correct time zone (daylight savings or not) for the given unix time, in the current location.
-func lookupTimezone(sec int64) (zone string, offset int) {
-	onceSetupZone.Do(setupZone)
-	if len(zones) == 0 {
-		return "UTC", 0
-	}
-
-	// Binary search for entry with largest time <= sec
-	tz := zones
-	for len(tz) > 1 {
-		m := len(tz) / 2
-		if sec < int64(tz[m].time) {
-			tz = tz[0:m]
-		} else {
-			tz = tz[m:]
-		}
-	}
-	z := tz[0].zone
-	return z.name, z.utcoff
-}
-
-// lookupByName returns the time offset for the
-// time zone with the given abbreviation. It only considers
-// time zones that apply to the current system.
-// For example, for a system configured as being in New York,
-// it only recognizes "EST" and "EDT".
-// For a system in San Francisco, "PST" and "PDT".
-// For a system in Sydney, "EST" and "EDT", though they have
-// different meanings than they do in New York.
-func lookupByName(name string) (off int, found bool) {
-	onceSetupZone.Do(setupZone)
-	for _, z := range zones {
-		if name == z.zone.name {
-			return z.zone.utcoff, true
-		}
-	}
-	return 0, false
-}
diff --git a/src/pkg/time/zoneinfo_unix.go b/src/pkg/time/zoneinfo_unix.go
index 0dc4235..540b653 100644
--- a/src/pkg/time/zoneinfo_unix.go
+++ b/src/pkg/time/zoneinfo_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
+// +build darwin freebsd linux netbsd openbsd
 
 // Parse "zoneinfo" time zone file.
 // This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others.
@@ -12,8 +12,8 @@
 package time
 
 import (
-	"io/ioutil"
-	"os"
+	"errors"
+	"syscall"
 )
 
 const (
@@ -65,18 +65,20 @@ func byteString(p []byte) string {
 	return string(p)
 }
 
-func parseinfo(bytes []byte) (zt []zonetime, ok bool) {
+var badData = errors.New("malformed time zone information")
+
+func loadZoneData(bytes []byte) (l *Location, err error) {
 	d := data{bytes, false}
 
 	// 4-byte magic "TZif"
 	if magic := d.read(4); string(magic) != "TZif" {
-		return nil, false
+		return nil, badData
 	}
 
 	// 1-byte version, then 15 bytes of padding
 	var p []byte
 	if p = d.read(16); len(p) != 16 || p[0] != 0 && p[0] != '2' {
-		return nil, false
+		return nil, badData
 	}
 
 	// six big-endian 32-bit integers:
@@ -98,7 +100,7 @@ func parseinfo(bytes []byte) (zt []zonetime, ok bool) {
 	for i := 0; i < 6; i++ {
 		nn, ok := d.big4()
 		if !ok {
-			return nil, false
+			return nil, badData
 		}
 		n[i] = int(nn)
 	}
@@ -127,7 +129,7 @@ func parseinfo(bytes []byte) (zt []zonetime, ok bool) {
 	isutc := d.read(n[NUTCLocal])
 
 	if d.error { // ran out of data
-		return nil, false
+		return nil, badData
 	}
 
 	// If version == 2, the entire file repeats, this time using
@@ -137,84 +139,119 @@ func parseinfo(bytes []byte) (zt []zonetime, ok bool) {
 	// Now we can build up a useful data structure.
 	// First the zone information.
 	//	utcoff[4] isdst[1] nameindex[1]
-	z := make([]zone, n[NZone])
-	for i := 0; i < len(z); i++ {
+	zone := make([]zone, n[NZone])
+	for i := range zone {
 		var ok bool
 		var n uint32
 		if n, ok = zonedata.big4(); !ok {
-			return nil, false
+			return nil, badData
 		}
-		z[i].utcoff = int(n)
+		zone[i].offset = int(n)
 		var b byte
 		if b, ok = zonedata.byte(); !ok {
-			return nil, false
+			return nil, badData
 		}
-		z[i].isdst = b != 0
+		zone[i].isDST = b != 0
 		if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) {
-			return nil, false
+			return nil, badData
 		}
-		z[i].name = byteString(abbrev[b:])
+		zone[i].name = byteString(abbrev[b:])
 	}
 
 	// Now the transition time info.
-	zt = make([]zonetime, n[NTime])
-	for i := 0; i < len(zt); i++ {
+	tx := make([]zoneTrans, n[NTime])
+	for i := range tx {
 		var ok bool
 		var n uint32
 		if n, ok = txtimes.big4(); !ok {
-			return nil, false
+			return nil, badData
 		}
-		zt[i].time = int32(n)
-		if int(txzones[i]) >= len(z) {
-			return nil, false
+		tx[i].when = int64(int32(n))
+		if int(txzones[i]) >= len(zone) {
+			return nil, badData
 		}
-		zt[i].zone = &z[txzones[i]]
+		tx[i].index = txzones[i]
 		if i < len(isstd) {
-			zt[i].isstd = isstd[i] != 0
+			tx[i].isstd = isstd[i] != 0
 		}
 		if i < len(isutc) {
-			zt[i].isutc = isutc[i] != 0
+			tx[i].isutc = isutc[i] != 0
+		}
+	}
+
+	// Commited to succeed.
+	l = &Location{zone: zone, tx: tx}
+
+	// Fill in the cache with information about right now,
+	// since that will be the most common lookup.
+	sec, _ := now()
+	for i := range tx {
+		if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
+			l.cacheStart = tx[i].when
+			l.cacheEnd = 1<<63 - 1
+			if i+1 < len(tx) {
+				l.cacheEnd = tx[i+1].when
+			}
+			l.cacheZone = &l.zone[tx[i].index]
 		}
 	}
-	return zt, true
+
+	return l, nil
 }
 
-func readinfofile(name string) ([]zonetime, bool) {
-	buf, err := ioutil.ReadFile(name)
+func loadZoneFile(name string) (l *Location, err error) {
+	buf, err := readFile(name)
 	if err != nil {
-		return nil, false
+		return
 	}
-	return parseinfo(buf)
+	return loadZoneData(buf)
+}
+
+func initTestingZone() {
+	syscall.Setenv("TZ", "America/Los_Angeles")
+	initLocal()
 }
 
-func setupTestingZone() {
-	os.Setenv("TZ", "America/Los_Angeles")
-	setupZone()
+// Many systems use /usr/share/zoneinfo, Solaris 2 has
+// /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.
+var zoneDirs = []string{
+	"/usr/share/zoneinfo/",
+	"/usr/share/lib/zoneinfo/",
+	"/usr/lib/locale/TZ/",
 }
 
-func setupZone() {
+func initLocal() {
 	// consult $TZ to find the time zone to use.
 	// no $TZ means use the system default /etc/localtime.
 	// $TZ="" means use UTC.
 	// $TZ="foo" means use /usr/share/zoneinfo/foo.
-	// Many systems use /usr/share/zoneinfo, Solaris 2 has
-	// /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.
-	zoneDirs := []string{"/usr/share/zoneinfo/",
-		"/usr/share/lib/zoneinfo/",
-		"/usr/lib/locale/TZ/"}
 
-	tz, err := os.Getenverror("TZ")
+	tz, ok := syscall.Getenv("TZ")
 	switch {
-	case err == os.ENOENV:
-		zones, _ = readinfofile("/etc/localtime")
-	case len(tz) > 0:
-		for _, zoneDir := range zoneDirs {
-			var ok bool
-			if zones, ok = readinfofile(zoneDir + tz); ok {
-				break
-			}
+	case !ok:
+		z, err := loadZoneFile("/etc/localtime")
+		if err == nil {
+			localLoc = *z
+			localLoc.name = "Local"
+			return
+		}
+	case tz != "" && tz != "UTC":
+		if z, err := loadLocation(tz); err == nil {
+			localLoc = *z
+			return
+		}
+	}
+
+	// Fall back to UTC.
+	localLoc.name = "UTC"
+}
+
+func loadLocation(name string) (*Location, error) {
+	for _, zoneDir := range zoneDirs {
+		if z, err := loadZoneFile(zoneDir + name); err == nil {
+			z.name = name
+			return z, nil
 		}
-	case len(tz) == 0:
-		// do nothing: use UTC
 	}
+	return nil, errors.New("unknown time zone " + name)
 }
diff --git a/src/pkg/time/zoneinfo_windows.go b/src/pkg/time/zoneinfo_windows.go
index 41c4819..beef4de 100644
--- a/src/pkg/time/zoneinfo_windows.go
+++ b/src/pkg/time/zoneinfo_windows.go
@@ -5,34 +5,21 @@
 package time
 
 import (
+	"errors"
 	"syscall"
-	"sync"
-	"os"
 )
 
-// BUG(brainman): The Windows implementation assumes that
-// this year's rules for daylight savings time apply to all previous
-// and future years as well.
-
-// TODO(brainman): use GetDynamicTimeZoneInformation, whenever possible (Vista and up),
-// to improve on situation described in the bug above.
-
-type zone struct {
-	name                  string
-	offset                int
-	year                  int64
-	month, day, dayofweek int
-	hour, minute, second  int
-	abssec                int64
-	prev                  *zone
-}
+// TODO(rsc): Fall back to copy of zoneinfo files.
 
-// BUG(rsc): On Windows, time zone abbreviations are unavailable.
-// This package constructs them using the capital letters from a longer
-// time zone description.
+// BUG(brainman,rsc): On Windows, the operating system does not provide complete
+// time zone information.
+// The implementation assumes that this year's rules for daylight savings
+// time apply to all previous and future years as well. 
+// Also, time zone abbreviations are unavailable.  The implementation constructs
+// them using the capital letters from a longer time zone description.	
 
-// Populate zone struct with Windows supplied information. Returns true, if data is valid.
-func (z *zone) populate(bias, biasdelta int32, d *syscall.Systemtime, name []uint16) (dateisgood bool) {
+// abbrev returns the abbreviation to use for the given zone name.
+func abbrev(name []uint16) string {
 	// name is 'Pacific Standard Time' but we want 'PST'.
 	// Extract just capital letters.  It's not perfect but the
 	// information we need is not available from the kernel.
@@ -41,147 +28,101 @@ func (z *zone) populate(bias, biasdelta int32, d *syscall.Systemtime, name []uin
 	//
 	// http://social.msdn.microsoft.com/Forums/eu/vclanguage/thread/a87e1d25-fb71-4fe0-ae9c-a9578c9753eb
 	// http://stackoverflow.com/questions/4195948/windows-time-zone-abbreviations-in-asp-net
-	short := make([]uint16, len(name))
-	w := 0
+	var short []rune
 	for _, c := range name {
 		if 'A' <= c && c <= 'Z' {
-			short[w] = c
-			w++
-		}
-	}
-	z.name = syscall.UTF16ToString(short[:w])
-
-	z.offset = int(bias)
-	z.year = int64(d.Year)
-	z.month = int(d.Month)
-	z.day = int(d.Day)
-	z.dayofweek = int(d.DayOfWeek)
-	z.hour = int(d.Hour)
-	z.minute = int(d.Minute)
-	z.second = int(d.Second)
-	dateisgood = d.Month != 0
-	if dateisgood {
-		z.offset += int(biasdelta)
-	}
-	z.offset = -z.offset * 60
-	return
-}
-
-// Pre-calculate cutoff time in seconds since the Unix epoch, if data is supplied in "absolute" format.
-func (z *zone) preCalculateAbsSec() {
-	if z.year != 0 {
-		t := &Time{
-			Year:   z.year,
-			Month:  int(z.month),
-			Day:    int(z.day),
-			Hour:   int(z.hour),
-			Minute: int(z.minute),
-			Second: int(z.second),
+			short = append(short, rune(c))
 		}
-		z.abssec = t.Seconds()
-		// Time given is in "local" time. Adjust it for "utc".
-		z.abssec -= int64(z.prev.offset)
 	}
+	return string(short)
 }
 
-// Convert zone cutoff time to sec in number of seconds since the Unix epoch, given particular year.
-func (z *zone) cutoffSeconds(year int64) int64 {
+// pseudoUnix returns the pseudo-Unix time (seconds since Jan 1 1970 *LOCAL TIME*)
+// denoted by the system date+time d in the given year.
+// It is up to the caller to convert this local time into a UTC-based time.
+func pseudoUnix(year int, d *syscall.Systemtime) int64 {
 	// Windows specifies daylight savings information in "day in month" format:
-	// z.month is month number (1-12)
-	// z.dayofweek is appropriate weekday (Sunday=0 to Saturday=6)
-	// z.day is week within the month (1 to 5, where 5 is last week of the month)
-	// z.hour, z.minute and z.second are absolute time
-	t := &Time{
-		Year:   year,
-		Month:  int(z.month),
-		Day:    1,
-		Hour:   int(z.hour),
-		Minute: int(z.minute),
-		Second: int(z.second),
-	}
-	t = SecondsToUTC(t.Seconds())
-	i := int(z.dayofweek) - t.Weekday()
+	// d.Month is month number (1-12)
+	// d.DayOfWeek is appropriate weekday (Sunday=0 to Saturday=6)
+	// d.Day is week within the month (1 to 5, where 5 is last week of the month)
+	// d.Hour, d.Minute and d.Second are absolute time
+	day := 1
+	t := Date(year, Month(d.Month), day, int(d.Hour), int(d.Minute), int(d.Second), 0, UTC)
+	i := int(d.DayOfWeek) - int(t.Weekday())
 	if i < 0 {
 		i += 7
 	}
-	t.Day += i
-	if week := int(z.day) - 1; week < 4 {
-		t.Day += week * 7
+	day += i
+	if week := int(d.Day) - 1; week < 4 {
+		day += week * 7
 	} else {
 		// "Last" instance of the day.
-		t.Day += 4 * 7
-		if t.Day > months(year)[t.Month] {
-			t.Day -= 7
+		day += 4 * 7
+		if day > daysIn(Month(d.Month), year) {
+			day -= 7
 		}
 	}
-	// Result is in "local" time. Adjust it for "utc".
-	return t.Seconds() - int64(z.prev.offset)
+	return t.sec + int64(day-1)*secondsPerDay + internalToUnix
 }
 
-// Is t before the cutoff for switching to z?
-func (z *zone) isBeforeCutoff(t *Time) bool {
-	var coff int64
-	if z.year == 0 {
-		// "day in month" format used
-		coff = z.cutoffSeconds(t.Year)
-	} else {
-		// "absolute" format used
-		coff = z.abssec
-	}
-	return t.Seconds() < coff
-}
-
-type zoneinfo struct {
-	disabled         bool // daylight saving time is not used locally
-	offsetIfDisabled int
-	januaryIsStd     bool // is january 1 standard time?
-	std, dst         zone
-}
+func initLocalFromTZI(i *syscall.Timezoneinformation) {
+	l := &localLoc
 
-// Pick zone (std or dst) t time belongs to.
-func (zi *zoneinfo) pickZone(t *Time) *zone {
-	z := &zi.std
-	if tz.januaryIsStd {
-		if !zi.dst.isBeforeCutoff(t) && zi.std.isBeforeCutoff(t) {
-			// after switch to daylight time and before the switch back to standard
-			z = &zi.dst
-		}
-	} else {
-		if zi.std.isBeforeCutoff(t) || !zi.dst.isBeforeCutoff(t) {
-			// before switch to standard time or after the switch back to daylight
-			z = &zi.dst
-		}
+	nzone := 1
+	if i.StandardDate.Month > 0 {
+		nzone++
 	}
-	return z
-}
-
-var tz zoneinfo
-var initError os.Error
-var onceSetupZone sync.Once
+	l.zone = make([]zone, nzone)
 
-func setupZone() {
-	var i syscall.Timezoneinformation
-	if _, e := syscall.GetTimeZoneInformation(&i); e != 0 {
-		initError = os.NewSyscallError("GetTimeZoneInformation", e)
+	std := &l.zone[0]
+	std.name = abbrev(i.StandardName[0:])
+	if nzone == 1 {
+		// No daylight savings.
+		std.offset = -int(i.Bias) * 60
+		l.cacheStart = -1 << 63
+		l.cacheEnd = 1<<63 - 1
+		l.cacheZone = std
 		return
 	}
-	setupZoneFromTZI(&i)
-}
 
-func setupZoneFromTZI(i *syscall.Timezoneinformation) {
-	if !tz.std.populate(i.Bias, i.StandardBias, &i.StandardDate, i.StandardName[0:]) {
-		tz.disabled = true
-		tz.offsetIfDisabled = tz.std.offset
-		return
+	// StandardBias must be ignored if StandardDate is not set,
+	// so this computation is delayed until after the nzone==1
+	// return above.
+	std.offset = -int(i.Bias+i.StandardBias) * 60
+
+	dst := &l.zone[1]
+	dst.name = abbrev(i.DaylightName[0:])
+	dst.offset = -int(i.Bias+i.DaylightBias) * 60
+	dst.isDST = true
+
+	// Arrange so that d0 is first transition date, d1 second,
+	// i0 is index of zone after first transition, i1 second.
+	d0 := &i.StandardDate
+	d1 := &i.DaylightDate
+	i0 := 0
+	i1 := 1
+	if d0.Month > d1.Month {
+		d0, d1 = d1, d0
+		i0, i1 = i1, i0
+	}
+
+	// 2 tx per year, 100 years on each side of this year
+	l.tx = make([]zoneTrans, 400)
+
+	t := Now().UTC()
+	year := t.Year()
+	txi := 0
+	for y := year - 100; y < year+100; y++ {
+		tx := &l.tx[txi]
+		tx.when = pseudoUnix(y, d0) - int64(l.zone[i1].offset)
+		tx.index = uint8(i0)
+		txi++
+
+		tx = &l.tx[txi]
+		tx.when = pseudoUnix(y, d1) - int64(l.zone[i0].offset)
+		tx.index = uint8(i1)
+		txi++
 	}
-	tz.std.prev = &tz.dst
-	tz.dst.populate(i.Bias, i.DaylightBias, &i.DaylightDate, i.DaylightName[0:])
-	tz.dst.prev = &tz.std
-	tz.std.preCalculateAbsSec()
-	tz.dst.preCalculateAbsSec()
-	// Is january 1 standard time this year?
-	t := UTC()
-	tz.januaryIsStd = tz.dst.cutoffSeconds(t.Year) < tz.std.cutoffSeconds(t.Year)
 }
 
 var usPacific = syscall.Timezoneinformation{
@@ -197,53 +138,20 @@ var usPacific = syscall.Timezoneinformation{
 	DaylightBias: -60,
 }
 
-func setupTestingZone() {
-	setupZoneFromTZI(&usPacific)
+func initTestingZone() {
+	initLocalFromTZI(&usPacific)
 }
 
-// Look up the correct time zone (daylight savings or not) for the given unix time, in the current location.
-func lookupTimezone(sec int64) (zone string, offset int) {
-	onceSetupZone.Do(setupZone)
-	if initError != nil {
-		return "", 0
-	}
-	if tz.disabled {
-		return "", tz.offsetIfDisabled
-	}
-	t := SecondsToUTC(sec)
-	z := &tz.std
-	if tz.std.year == 0 {
-		// "day in month" format used
-		z = tz.pickZone(t)
-	} else {
-		// "absolute" format used
-		if tz.std.year == t.Year {
-			// we have rule for the year in question
-			z = tz.pickZone(t)
-		} else {
-			// we do not have any information for that year,
-			// will assume standard offset all year around
-		}
+func initLocal() {
+	var i syscall.Timezoneinformation
+	if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
+		localLoc.name = "UTC"
+		return
 	}
-	return z.name, z.offset
+	initLocalFromTZI(&i)
 }
 
-// lookupByName returns the time offset for the
-// time zone with the given abbreviation. It only considers
-// time zones that apply to the current system.
-func lookupByName(name string) (off int, found bool) {
-	onceSetupZone.Do(setupZone)
-	if initError != nil {
-		return 0, false
-	}
-	if tz.disabled {
-		return tz.offsetIfDisabled, false
-	}
-	switch name {
-	case tz.std.name:
-		return tz.std.offset, true
-	case tz.dst.name:
-		return tz.dst.offset, true
-	}
-	return 0, false
+// TODO(rsc): Implement.
+func loadLocation(name string) (*Location, error) {
+	return nil, errors.New("unknown time zone " + name)
 }
diff --git a/src/pkg/try/Makefile b/src/pkg/try/Makefile
deleted file mode 100644
index 06981a6..0000000
--- a/src/pkg/try/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=try
-GOFILES=\
-	try.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/try/try.go b/src/pkg/try/try.go
deleted file mode 100644
index 2a3dbf9..0000000
--- a/src/pkg/try/try.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2010 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 try contains the executable part of the gotry command.
-// It is not intended for general use.
-package try
-
-import (
-	"fmt"
-	"io"
-	"os"
-	"reflect"
-	"unicode"
-)
-
-var output io.Writer = os.Stdout // redirected when testing
-
-// Main is called directly from the gotry-generated Go source file to perform
-// the evaluations.
-func Main(pkg, firstArg string, functions map[string]interface{}, args []interface{}) {
-	switch len(args) {
-	case 0:
-		// Nothing to do.
-	case 1:
-		// Compiler has already evaluated the expression; just print the result.
-		printSlice(firstArg, args)
-	default:
-		// See if methods satisfy the expressions.
-		tryMethods(pkg, firstArg, args)
-		// See if functions satisfy the expressions.
-		for name, fn := range functions {
-			tryFunction(pkg, name, fn, args)
-		}
-	}
-}
-
-// printSlice prints the zeroth element of the args slice, which should (by construction)
-// itself be a slice of interface{}.
-func printSlice(firstArg string, args []interface{}) {
-	// Args should be length 1 and a slice.
-	if len(args) != 1 {
-		return
-	}
-	arg, ok := args[0].([]interface{})
-	if !ok {
-		return
-	}
-	fmt.Fprintf(output, "%s = ", firstArg)
-	if len(arg) > 1 {
-		fmt.Fprint(output, "(")
-	}
-	for i, a := range arg {
-		if i > 0 {
-			fmt.Fprint(output, ", ")
-		}
-		fmt.Fprintf(output, "%#v", a)
-	}
-	if len(arg) > 1 {
-		fmt.Fprint(output, ")")
-	}
-	fmt.Fprint(output, "\n")
-}
-
-// tryMethods sees if the zeroth arg has methods, and if so treats them as potential
-// functions to satisfy the remaining arguments.
-func tryMethods(pkg, firstArg string, args []interface{}) {
-	defer func() { recover() }()
-	// Is the first argument something with methods?
-	v := reflect.ValueOf(args[0])
-	typ := v.Type()
-	if typ.NumMethod() == 0 {
-		return
-	}
-	for i := 0; i < typ.NumMethod(); i++ {
-		if unicode.IsUpper(int(typ.Method(i).Name[0])) {
-			tryMethod(pkg, firstArg, typ.Method(i), args)
-		}
-	}
-}
-
-// tryMethod converts a method to a function for tryOneFunction.
-func tryMethod(pkg, firstArg string, method reflect.Method, args []interface{}) {
-	rfn := method.Func
-	typ := method.Type
-	name := method.Name
-	tryOneFunction(pkg, firstArg, name, typ, rfn, args)
-}
-
-// tryFunction sees if fn satisfies the arguments.
-func tryFunction(pkg, name string, fn interface{}, args []interface{}) {
-	defer func() { recover() }()
-	rfn := reflect.ValueOf(fn)
-	typ := rfn.Type()
-	tryOneFunction(pkg, "", name, typ, rfn, args)
-}
-
-// tryOneFunction is the common code for tryMethod and tryFunction.
-func tryOneFunction(pkg, firstArg, name string, typ reflect.Type, rfn reflect.Value, args []interface{}) {
-	// Any results?
-	if typ.NumOut() == 0 {
-		return // Nothing to do.
-	}
-	// Right number of arguments + results?
-	if typ.NumIn()+typ.NumOut() != len(args) {
-		return
-	}
-	// Right argument and result types?
-	for i, a := range args {
-		if i < typ.NumIn() {
-			if !compatible(a, typ.In(i)) {
-				return
-			}
-		} else {
-			if !compatible(a, typ.Out(i-typ.NumIn())) {
-				return
-			}
-		}
-	}
-	// Build the call args.
-	argsVal := make([]reflect.Value, typ.NumIn()+typ.NumOut())
-	for i, a := range args {
-		argsVal[i] = reflect.ValueOf(a)
-	}
-	// Call the function and see if the results are as expected.
-	resultVal := rfn.Call(argsVal[:typ.NumIn()])
-	for i, v := range resultVal {
-		if !reflect.DeepEqual(v.Interface(), args[i+typ.NumIn()]) {
-			return
-		}
-	}
-	// Present the result including a godoc command to get more information.
-	firstIndex := 0
-	if firstArg != "" {
-		fmt.Fprintf(output, "%s.%s(", firstArg, name)
-		firstIndex = 1
-	} else {
-		fmt.Fprintf(output, "%s.%s(", pkg, name)
-	}
-	for i := firstIndex; i < typ.NumIn(); i++ {
-		if i > firstIndex {
-			fmt.Fprint(output, ", ")
-		}
-		fmt.Fprintf(output, "%#v", args[i])
-	}
-	fmt.Fprint(output, ") = ")
-	if typ.NumOut() > 1 {
-		fmt.Fprint(output, "(")
-	}
-	for i := 0; i < typ.NumOut(); i++ {
-		if i > 0 {
-			fmt.Fprint(output, ", ")
-		}
-		fmt.Fprintf(output, "%#v", resultVal[i].Interface())
-	}
-	if typ.NumOut() > 1 {
-		fmt.Fprint(output, ")")
-	}
-	fmt.Fprintf(output, "  // godoc %s %s\n", pkg, name)
-}
-
-// compatible reports whether the argument is compatible with the type.
-func compatible(arg interface{}, typ reflect.Type) bool {
-	if reflect.TypeOf(arg) == typ {
-		return true
-	}
-	if arg == nil {
-		// nil is OK if the type is an interface.
-		if typ.Kind() == reflect.Interface {
-			return true
-		}
-	}
-	return false
-}
diff --git a/src/pkg/try/try_test.go b/src/pkg/try/try_test.go
deleted file mode 100644
index 617b2c7..0000000
--- a/src/pkg/try/try_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2010 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 try
-
-import (
-	"bytes"
-	"regexp" // Used as the package to try.
-	"testing"
-)
-
-// The global functions in package regexp at time of writing.
-// Doesn't need to be updated unless the entries in this list become invalid.
-var functions = map[string]interface{}{
-	"Compile":     regexp.Compile,
-	"Match":       regexp.Match,
-	"MatchString": regexp.MatchString,
-	"MustCompile": regexp.MustCompile,
-	"QuoteMeta":   regexp.QuoteMeta,
-}
-
-// A wraps arguments to make the test cases nicer to read.
-func A(args ...interface{}) []interface{} {
-	return args
-}
-
-type Test struct {
-	firstArg string // only needed if there is exactly one argument
-	result   string // minus final newline; might be just the godoc string
-	args     []interface{}
-}
-
-var testRE = regexp.MustCompile("a(.)(.)d")
-
-var tests = []Test{
-	// A simple expression.  The final value is a slice in case the expression is multivalue.
-	{"3+4", "3+4 = 7", A([]interface{}{7})},
-	// A search for a function.
-	{"", "regexp QuoteMeta", A("([])", `\(\[\]\)`)},
-	// A search for a function with multiple return values.
-	{"", "regexp MatchString", A("abc", "xabcd", true, nil)},
-	// Searches for methods.
-	{"", "regexp MatchString", A(testRE, "xabcde", true)},
-	{"", "regexp NumSubexp", A(testRE, 2)},
-}
-
-func TestAll(t *testing.T) {
-	re := regexp.MustCompile(".*// godoc ")
-	for _, test := range tests {
-		b := new(bytes.Buffer)
-		output = b
-		Main("regexp", test.firstArg, functions, test.args)
-		expect := test.result + "\n"
-		got := re.ReplaceAllString(b.String(), "")
-		if got != expect {
-			t.Errorf("expected %q; got %q", expect, got)
-		}
-	}
-}
diff --git a/src/pkg/unicode/Makefile b/src/pkg/unicode/Makefile
index 55ed5b2..4472a6c 100644
--- a/src/pkg/unicode/Makefile
+++ b/src/pkg/unicode/Makefile
@@ -17,7 +17,7 @@ include ../../Make.pkg
 CLEANFILES+=maketables
 
 maketables: maketables.go
-	$(GC) maketables.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) maketables.go
 	$(LD) -o maketables maketables.$O
 
 tables:	maketables
diff --git a/src/pkg/unicode/digit.go b/src/pkg/unicode/digit.go
index 6793fd7..4800bd6 100644
--- a/src/pkg/unicode/digit.go
+++ b/src/pkg/unicode/digit.go
@@ -5,9 +5,9 @@
 package unicode
 
 // IsDigit reports whether the rune is a decimal digit.
-func IsDigit(rune int) bool {
-	if rune <= MaxLatin1 {
-		return '0' <= rune && rune <= '9'
+func IsDigit(r rune) bool {
+	if r <= MaxLatin1 {
+		return '0' <= r && r <= '9'
 	}
-	return Is(Digit, rune)
+	return Is(Digit, r)
 }
diff --git a/src/pkg/unicode/digit_test.go b/src/pkg/unicode/digit_test.go
index ae3c0ec..551c42a 100644
--- a/src/pkg/unicode/digit_test.go
+++ b/src/pkg/unicode/digit_test.go
@@ -9,7 +9,7 @@ import (
 	. "unicode"
 )
 
-var testDigit = []int{
+var testDigit = []rune{
 	0x0030,
 	0x0039,
 	0x0661,
@@ -68,7 +68,7 @@ var testDigit = []int{
 	0x1D7CE,
 }
 
-var testLetter = []int{
+var testLetter = []rune{
 	0x0041,
 	0x0061,
 	0x00AA,
@@ -118,7 +118,7 @@ func TestDigit(t *testing.T) {
 
 // Test that the special case in IsDigit agrees with the table
 func TestDigitOptimization(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		if Is(Digit, i) != IsDigit(i) {
 			t.Errorf("IsDigit(U+%04X) disagrees with Is(Digit)", i)
 		}
diff --git a/src/pkg/unicode/graphic.go b/src/pkg/unicode/graphic.go
index d482aac..2904da6 100644
--- a/src/pkg/unicode/graphic.go
+++ b/src/pkg/unicode/graphic.go
@@ -31,13 +31,13 @@ var PrintRanges = []*RangeTable{
 // IsGraphic reports whether the rune is defined as a Graphic by Unicode.
 // Such characters include letters, marks, numbers, punctuation, symbols, and
 // spaces, from categories L, M, N, P, S, Zs.
-func IsGraphic(rune int) bool {
-	// We cast to uint32 to avoid the extra test for negative,
-	// and in the index we cast to uint8 to avoid the range check.
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&pg != 0
+func IsGraphic(r rune) bool {
+	// We convert to uint32 to avoid the extra test for negative,
+	// and in the index we convert to uint8 to avoid the range check.
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pg != 0
 	}
-	return IsOneOf(GraphicRanges, rune)
+	return IsOneOf(GraphicRanges, r)
 }
 
 // IsPrint reports whether the rune is defined as printable by Go. Such
@@ -45,18 +45,18 @@ func IsGraphic(rune int) bool {
 // ASCII space character, from categories L, M, N, P, S and the ASCII space
 // character.  This categorization is the same as IsGraphic except that the
 // only spacing character is ASCII space, U+0020.
-func IsPrint(rune int) bool {
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&pp != 0
+func IsPrint(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pp != 0
 	}
-	return IsOneOf(PrintRanges, rune)
+	return IsOneOf(PrintRanges, r)
 }
 
 // IsOneOf reports whether the rune is a member of one of the ranges.
 // The rune is known to be above Latin-1.
-func IsOneOf(set []*RangeTable, rune int) bool {
+func IsOneOf(set []*RangeTable, r rune) bool {
 	for _, inside := range set {
-		if Is(inside, rune) {
+		if Is(inside, r) {
 			return true
 		}
 	}
@@ -66,43 +66,43 @@ func IsOneOf(set []*RangeTable, rune int) bool {
 // IsControl reports whether the rune is a control character.
 // The C (Other) Unicode category includes more code points
 // such as surrogates; use Is(C, rune) to test for them.
-func IsControl(rune int) bool {
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&pC != 0
+func IsControl(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pC != 0
 	}
 	// All control characters are < Latin1Max.
 	return false
 }
 
 // IsLetter reports whether the rune is a letter (category L).
-func IsLetter(rune int) bool {
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&(pLu|pLl) != 0
+func IsLetter(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&(pLu|pLl) != 0
 	}
-	return Is(Letter, rune)
+	return Is(Letter, r)
 }
 
 // IsMark reports whether the rune is a mark character (category M).
-func IsMark(rune int) bool {
+func IsMark(r rune) bool {
 	// There are no mark characters in Latin-1.
-	return Is(Mark, rune)
+	return Is(Mark, r)
 }
 
 // IsNumber reports whether the rune is a number (category N).
-func IsNumber(rune int) bool {
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&pN != 0
+func IsNumber(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pN != 0
 	}
-	return Is(Number, rune)
+	return Is(Number, r)
 }
 
 // IsPunct reports whether the rune is a Unicode punctuation character
 // (category P).
-func IsPunct(rune int) bool {
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&pP != 0
+func IsPunct(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pP != 0
 	}
-	return Is(Punct, rune)
+	return Is(Punct, r)
 }
 
 // IsSpace reports whether the rune is a space character as defined
@@ -111,22 +111,22 @@ func IsPunct(rune int) bool {
 //	'\t', '\n', '\v', '\f', '\r', ' ', U+0085 (NEL), U+00A0 (NBSP).
 // Other definitions of spacing characters are set by category
 // Z and property Pattern_White_Space.
-func IsSpace(rune int) bool {
+func IsSpace(r rune) bool {
 	// This property isn't the same as Z; special-case it.
-	if uint32(rune) <= MaxLatin1 {
-		switch rune {
+	if uint32(r) <= MaxLatin1 {
+		switch r {
 		case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0:
 			return true
 		}
 		return false
 	}
-	return Is(White_Space, rune)
+	return Is(White_Space, r)
 }
 
 // IsSymbol reports whether the rune is a symbolic character.
-func IsSymbol(rune int) bool {
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&pS != 0
+func IsSymbol(r rune) bool {
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pS != 0
 	}
-	return Is(Symbol, rune)
+	return Is(Symbol, r)
 }
diff --git a/src/pkg/unicode/graphic_test.go b/src/pkg/unicode/graphic_test.go
index 77c679f..7b1f620 100644
--- a/src/pkg/unicode/graphic_test.go
+++ b/src/pkg/unicode/graphic_test.go
@@ -13,7 +13,7 @@ import (
 // in the Latin-1 range through the property table.
 
 func TestIsControlLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsControl(i)
 		want := false
 		switch {
@@ -29,7 +29,7 @@ func TestIsControlLatin1(t *testing.T) {
 }
 
 func TestIsLetterLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsLetter(i)
 		want := Is(Letter, i)
 		if got != want {
@@ -39,7 +39,7 @@ func TestIsLetterLatin1(t *testing.T) {
 }
 
 func TestIsUpperLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsUpper(i)
 		want := Is(Upper, i)
 		if got != want {
@@ -49,7 +49,7 @@ func TestIsUpperLatin1(t *testing.T) {
 }
 
 func TestIsLowerLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsLower(i)
 		want := Is(Lower, i)
 		if got != want {
@@ -59,7 +59,7 @@ func TestIsLowerLatin1(t *testing.T) {
 }
 
 func TestNumberLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsNumber(i)
 		want := Is(Number, i)
 		if got != want {
@@ -69,7 +69,7 @@ func TestNumberLatin1(t *testing.T) {
 }
 
 func TestIsPrintLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsPrint(i)
 		want := IsOneOf(PrintRanges, i)
 		if i == ' ' {
@@ -82,7 +82,7 @@ func TestIsPrintLatin1(t *testing.T) {
 }
 
 func TestIsGraphicLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsGraphic(i)
 		want := IsOneOf(GraphicRanges, i)
 		if got != want {
@@ -92,7 +92,7 @@ func TestIsGraphicLatin1(t *testing.T) {
 }
 
 func TestIsPunctLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsPunct(i)
 		want := Is(Punct, i)
 		if got != want {
@@ -102,7 +102,7 @@ func TestIsPunctLatin1(t *testing.T) {
 }
 
 func TestIsSpaceLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsSpace(i)
 		want := Is(White_Space, i)
 		if got != want {
@@ -112,7 +112,7 @@ func TestIsSpaceLatin1(t *testing.T) {
 }
 
 func TestIsSymbolLatin1(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		got := IsSymbol(i)
 		want := Is(Symbol, i)
 		if got != want {
diff --git a/src/pkg/unicode/letter.go b/src/pkg/unicode/letter.go
index 38a11c4..dcc160a 100644
--- a/src/pkg/unicode/letter.go
+++ b/src/pkg/unicode/letter.go
@@ -7,10 +7,10 @@
 package unicode
 
 const (
-	MaxRune         = 0x10FFFF // Maximum valid Unicode code point.
-	ReplacementChar = 0xFFFD   // Represents invalid code points.
-	MaxASCII        = 0x7F     // maximum ASCII value.
-	MaxLatin1       = 0xFF     // maximum Latin-1 value.
+	MaxRune         = '\U0010FFFF' // Maximum valid Unicode code point.
+	ReplacementChar = '\uFFFD'     // Represents invalid code points.
+	MaxASCII        = '\u007F'     // maximum ASCII value.
+	MaxLatin1       = '\u00FF'     // maximum Latin-1 value.
 )
 
 // RangeTable defines a set of Unicode code points by listing the ranges of
@@ -71,7 +71,7 @@ const (
 	MaxCase
 )
 
-type d [MaxCase]int32 // to make the CaseRanges text shorter
+type d [MaxCase]rune // to make the CaseRanges text shorter
 
 // If the Delta field of a CaseRange is UpperLower or LowerUpper, it means
 // this CaseRange represents a sequence of the form (say)
@@ -81,17 +81,17 @@ const (
 )
 
 // is16 uses binary search to test whether rune is in the specified slice of 16-bit ranges.
-func is16(ranges []Range16, rune uint16) bool {
+func is16(ranges []Range16, r uint16) bool {
 	// binary search over ranges
 	lo := 0
 	hi := len(ranges)
 	for lo < hi {
 		m := lo + (hi-lo)/2
-		r := ranges[m]
-		if r.Lo <= rune && rune <= r.Hi {
-			return (rune-r.Lo)%r.Stride == 0
+		range_ := ranges[m]
+		if range_.Lo <= r && r <= range_.Hi {
+			return (r-range_.Lo)%range_.Stride == 0
 		}
-		if rune < r.Lo {
+		if r < range_.Lo {
 			hi = m
 		} else {
 			lo = m + 1
@@ -101,17 +101,17 @@ func is16(ranges []Range16, rune uint16) bool {
 }
 
 // is32 uses binary search to test whether rune is in the specified slice of 32-bit ranges.
-func is32(ranges []Range32, rune uint32) bool {
+func is32(ranges []Range32, r uint32) bool {
 	// binary search over ranges
 	lo := 0
 	hi := len(ranges)
 	for lo < hi {
 		m := lo + (hi-lo)/2
-		r := ranges[m]
-		if r.Lo <= rune && rune <= r.Hi {
-			return (rune-r.Lo)%r.Stride == 0
+		range_ := ranges[m]
+		if range_.Lo <= r && r <= range_.Hi {
+			return (r-range_.Lo)%range_.Stride == 0
 		}
-		if rune < r.Lo {
+		if r < range_.Lo {
 			hi = m
 		} else {
 			lo = m + 1
@@ -121,11 +121,11 @@ func is32(ranges []Range32, rune uint32) bool {
 }
 
 // Is tests whether rune is in the specified table of ranges.
-func Is(rangeTab *RangeTable, rune int) bool {
+func Is(rangeTab *RangeTable, r rune) bool {
 	// common case: rune is ASCII or Latin-1.
-	if uint32(rune) <= MaxLatin1 {
+	if uint32(r) <= MaxLatin1 {
 		// Only need to check R16, since R32 is always >= 1<<16.
-		r16 := uint16(rune)
+		r16 := uint16(r)
 		for _, r := range rangeTab.R16 {
 			if r16 > r.Hi {
 				continue
@@ -138,44 +138,44 @@ func Is(rangeTab *RangeTable, rune int) bool {
 		return false
 	}
 	r16 := rangeTab.R16
-	if len(r16) > 0 && rune <= int(r16[len(r16)-1].Hi) {
-		return is16(r16, uint16(rune))
+	if len(r16) > 0 && r <= rune(r16[len(r16)-1].Hi) {
+		return is16(r16, uint16(r))
 	}
 	r32 := rangeTab.R32
-	if len(r32) > 0 && rune >= int(r32[0].Lo) {
-		return is32(r32, uint32(rune))
+	if len(r32) > 0 && r >= rune(r32[0].Lo) {
+		return is32(r32, uint32(r))
 	}
 	return false
 }
 
 // IsUpper reports whether the rune is an upper case letter.
-func IsUpper(rune int) bool {
+func IsUpper(r rune) bool {
 	// See comment in IsGraphic.
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&pLu != 0
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pLu != 0
 	}
-	return Is(Upper, rune)
+	return Is(Upper, r)
 }
 
 // IsLower reports whether the rune is a lower case letter.
-func IsLower(rune int) bool {
+func IsLower(r rune) bool {
 	// See comment in IsGraphic.
-	if uint32(rune) <= MaxLatin1 {
-		return properties[uint8(rune)]&pLl != 0
+	if uint32(r) <= MaxLatin1 {
+		return properties[uint8(r)]&pLl != 0
 	}
-	return Is(Lower, rune)
+	return Is(Lower, r)
 }
 
 // IsTitle reports whether the rune is a title case letter.
-func IsTitle(rune int) bool {
-	if rune <= MaxLatin1 {
+func IsTitle(r rune) bool {
+	if r <= MaxLatin1 {
 		return false
 	}
-	return Is(Title, rune)
+	return Is(Title, r)
 }
 
 // to maps the rune using the specified case mapping.
-func to(_case int, rune int, caseRange []CaseRange) int {
+func to(_case int, r rune, caseRange []CaseRange) rune {
 	if _case < 0 || MaxCase <= _case {
 		return ReplacementChar // as reasonable an error as any
 	}
@@ -184,9 +184,9 @@ func to(_case int, rune int, caseRange []CaseRange) int {
 	hi := len(caseRange)
 	for lo < hi {
 		m := lo + (hi-lo)/2
-		r := caseRange[m]
-		if int(r.Lo) <= rune && rune <= int(r.Hi) {
-			delta := int(r.Delta[_case])
+		cr := caseRange[m]
+		if rune(cr.Lo) <= r && r <= rune(cr.Hi) {
+			delta := rune(cr.Delta[_case])
 			if delta > MaxRune {
 				// In an Upper-Lower sequence, which always starts with
 				// an UpperCase letter, the real deltas always look like:
@@ -198,82 +198,82 @@ func to(_case int, rune int, caseRange []CaseRange) int {
 				// bit in the sequence offset.
 				// The constants UpperCase and TitleCase are even while LowerCase
 				// is odd so we take the low bit from _case.
-				return int(r.Lo) + ((rune-int(r.Lo))&^1 | _case&1)
+				return rune(cr.Lo) + ((r-rune(cr.Lo))&^1 | rune(_case&1))
 			}
-			return rune + delta
+			return r + delta
 		}
-		if rune < int(r.Lo) {
+		if r < rune(cr.Lo) {
 			hi = m
 		} else {
 			lo = m + 1
 		}
 	}
-	return rune
+	return r
 }
 
 // To maps the rune to the specified case: UpperCase, LowerCase, or TitleCase.
-func To(_case int, rune int) int {
-	return to(_case, rune, CaseRanges)
+func To(_case int, r rune) rune {
+	return to(_case, r, CaseRanges)
 }
 
 // ToUpper maps the rune to upper case.
-func ToUpper(rune int) int {
-	if rune <= MaxASCII {
-		if 'a' <= rune && rune <= 'z' {
-			rune -= 'a' - 'A'
+func ToUpper(r rune) rune {
+	if r <= MaxASCII {
+		if 'a' <= r && r <= 'z' {
+			r -= 'a' - 'A'
 		}
-		return rune
+		return r
 	}
-	return To(UpperCase, rune)
+	return To(UpperCase, r)
 }
 
 // ToLower maps the rune to lower case.
-func ToLower(rune int) int {
-	if rune <= MaxASCII {
-		if 'A' <= rune && rune <= 'Z' {
-			rune += 'a' - 'A'
+func ToLower(r rune) rune {
+	if r <= MaxASCII {
+		if 'A' <= r && r <= 'Z' {
+			r += 'a' - 'A'
 		}
-		return rune
+		return r
 	}
-	return To(LowerCase, rune)
+	return To(LowerCase, r)
 }
 
 // ToTitle maps the rune to title case.
-func ToTitle(rune int) int {
-	if rune <= MaxASCII {
-		if 'a' <= rune && rune <= 'z' { // title case is upper case for ASCII
-			rune -= 'a' - 'A'
+func ToTitle(r rune) rune {
+	if r <= MaxASCII {
+		if 'a' <= r && r <= 'z' { // title case is upper case for ASCII
+			r -= 'a' - 'A'
 		}
-		return rune
+		return r
 	}
-	return To(TitleCase, rune)
+	return To(TitleCase, r)
 }
 
 // ToUpper maps the rune to upper case giving priority to the special mapping.
-func (special SpecialCase) ToUpper(rune int) int {
-	r := to(UpperCase, rune, []CaseRange(special))
-	if r == rune {
-		r = ToUpper(rune)
+func (special SpecialCase) ToUpper(r rune) rune {
+	r1 := to(UpperCase, r, []CaseRange(special))
+	if r1 == r {
+		r1 = ToUpper(r)
 	}
-	return r
+	return r1
 }
 
 // ToTitle maps the rune to title case giving priority to the special mapping.
-func (special SpecialCase) ToTitle(rune int) int {
-	r := to(TitleCase, rune, []CaseRange(special))
-	if r == rune {
-		r = ToTitle(rune)
+func (special SpecialCase) ToTitle(r rune) rune {
+	r1 := to(TitleCase, r, []CaseRange(special))
+	if r1 == r {
+		r1 = ToTitle(r)
 	}
-	return r
+	return r1
 }
 
 // ToLower maps the rune to lower case giving priority to the special mapping.
-func (special SpecialCase) ToLower(rune int) int {
-	r := to(LowerCase, rune, []CaseRange(special))
-	if r == rune {
-		r = ToLower(rune)
+func (special SpecialCase) ToLower(r rune) rune {
+	r1 := to(LowerCase, r, []CaseRange(special))
+	if r1 == r {
+		r1 = ToLower(r)
 	}
-	return r
+	return r1
 }
 
 // caseOrbit is defined in tables.go as []foldPair.  Right now all the
@@ -300,27 +300,27 @@ type foldPair struct {
 //
 //	SimpleFold('1') = '1'
 //
-func SimpleFold(rune int) int {
+func SimpleFold(r rune) rune {
 	// Consult caseOrbit table for special cases.
 	lo := 0
 	hi := len(caseOrbit)
 	for lo < hi {
 		m := lo + (hi-lo)/2
-		if int(caseOrbit[m].From) < rune {
+		if rune(caseOrbit[m].From) < r {
 			lo = m + 1
 		} else {
 			hi = m
 		}
 	}
-	if lo < len(caseOrbit) && int(caseOrbit[lo].From) == rune {
-		return int(caseOrbit[lo].To)
+	if lo < len(caseOrbit) && rune(caseOrbit[lo].From) == r {
+		return rune(caseOrbit[lo].To)
 	}
 
 	// No folding specified.  This is a one- or two-element
 	// equivalence class containing rune and ToLower(rune)
 	// and ToUpper(rune) if they are different from rune.
-	if l := ToLower(rune); l != rune {
+	if l := ToLower(r); l != r {
 		return l
 	}
-	return ToUpper(rune)
+	return ToUpper(r)
 }
diff --git a/src/pkg/unicode/letter_test.go b/src/pkg/unicode/letter_test.go
index 8d2665a..2d80562 100644
--- a/src/pkg/unicode/letter_test.go
+++ b/src/pkg/unicode/letter_test.go
@@ -9,7 +9,7 @@ import (
 	. "unicode"
 )
 
-var upperTest = []int{
+var upperTest = []rune{
 	0x41,
 	0xc0,
 	0xd8,
@@ -33,7 +33,7 @@ var upperTest = []int{
 	0x1d7ca,
 }
 
-var notupperTest = []int{
+var notupperTest = []rune{
 	0x40,
 	0x5b,
 	0x61,
@@ -46,7 +46,7 @@ var notupperTest = []int{
 	0x10000,
 }
 
-var letterTest = []int{
+var letterTest = []rune{
 	0x41,
 	0x61,
 	0xaa,
@@ -82,7 +82,7 @@ var letterTest = []int{
 	0x2fa1d,
 }
 
-var notletterTest = []int{
+var notletterTest = []rune{
 	0x20,
 	0x35,
 	0x375,
@@ -94,7 +94,7 @@ var notletterTest = []int{
 }
 
 // Contains all the special cased Latin-1 chars.
-var spaceTest = []int{
+var spaceTest = []rune{
 	0x09,
 	0x0a,
 	0x0b,
@@ -108,7 +108,8 @@ var spaceTest = []int{
 }
 
 type caseT struct {
-	cas, in, out int
+	cas     int
+	in, out rune
 }
 
 var caseTest = []caseT{
@@ -327,7 +328,7 @@ func TestIsSpace(t *testing.T) {
 // Check that the optimizations for IsLetter etc. agree with the tables.
 // We only need to check the Latin-1 range.
 func TestLetterOptimizations(t *testing.T) {
-	for i := 0; i <= MaxLatin1; i++ {
+	for i := rune(0); i <= MaxLatin1; i++ {
 		if Is(Letter, i) != IsLetter(i) {
 			t.Errorf("IsLetter(U+%04X) disagrees with Is(Letter)", i)
 		}
@@ -356,8 +357,8 @@ func TestLetterOptimizations(t *testing.T) {
 }
 
 func TestTurkishCase(t *testing.T) {
-	lower := []int("abcçdefgğhıijklmnoöprsştuüvyz")
-	upper := []int("ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ")
+	lower := []rune("abcçdefgğhıijklmnoöprsştuüvyz")
+	upper := []rune("ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ")
 	for i, l := range lower {
 		u := upper[i]
 		if TurkishCase.ToLower(l) != l {
@@ -416,13 +417,13 @@ var simpleFoldTests = []string{
 
 func TestSimpleFold(t *testing.T) {
 	for _, tt := range simpleFoldTests {
-		cycle := []int(tt)
-		rune := cycle[len(cycle)-1]
+		cycle := []rune(tt)
+		r := cycle[len(cycle)-1]
 		for _, out := range cycle {
-			if r := SimpleFold(rune); r != out {
-				t.Errorf("SimpleFold(%#U) = %#U, want %#U", rune, r, out)
+			if r := SimpleFold(r); r != out {
+				t.Errorf("SimpleFold(%#U) = %#U, want %#U", r, r, out)
 			}
-			rune = out
+			r = out
 		}
 	}
 }
diff --git a/src/pkg/unicode/maketables.go b/src/pkg/unicode/maketables.go
index b586bc6..393f8ea 100644
--- a/src/pkg/unicode/maketables.go
+++ b/src/pkg/unicode/maketables.go
@@ -11,14 +11,15 @@ import (
 	"bufio"
 	"flag"
 	"fmt"
-	"http"
+	"io"
 	"log"
+	"net/http"
 	"os"
 	"path/filepath"
+	"regexp"
 	"sort"
 	"strconv"
 	"strings"
-	"regexp"
 	"unicode"
 )
 
@@ -77,7 +78,7 @@ func open(url string) *reader {
 		}
 		return &reader{bufio.NewReader(fd), fd, nil}
 	}
-	resp, err := http.Get(*dataURL)
+	resp, err := http.Get(url)
 	if err != nil {
 		logger.Fatal(err)
 	}
@@ -155,13 +156,13 @@ var fieldName = []string{
 // This contains only the properties we're interested in.
 type Char struct {
 	field     []string // debugging only; could be deleted if we take out char.dump()
-	codePoint uint32   // if zero, this index is not a valid code point.
+	codePoint rune     // if zero, this index is not a valid code point.
 	category  string
-	upperCase int
-	lowerCase int
-	titleCase int
-	foldCase  int // simple case folding
-	caseOrbit int // next in simple case folding orbit
+	upperCase rune
+	lowerCase rune
+	titleCase rune
+	foldCase  rune // simple case folding
+	caseOrbit rune // next in simple case folding orbit
 }
 
 // Scripts.txt has form:
@@ -178,7 +179,7 @@ var chars = make([]Char, MaxChar+1)
 var scripts = make(map[string][]Script)
 var props = make(map[string][]Script) // a property looks like a script; can share the format
 
-var lastChar uint32 = 0
+var lastChar rune = 0
 
 // In UnicodeData.txt, some ranges are marked like this:
 //	3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
@@ -198,11 +199,11 @@ func parseCategory(line string) (state State) {
 	if len(field) != NumField {
 		logger.Fatalf("%5s: %d fields (expected %d)\n", line, len(field), NumField)
 	}
-	point, err := strconv.Btoui64(field[FCodePoint], 16)
+	point, err := strconv.ParseUint(field[FCodePoint], 16, 64)
 	if err != nil {
 		logger.Fatalf("%.5s...: %s", line, err)
 	}
-	lastChar = uint32(point)
+	lastChar = rune(point)
 	if point == 0 {
 		return // not interesting and we use 0 as unset
 	}
@@ -256,35 +257,42 @@ func (char *Char) letter(u, l, t string) {
 	char.titleCase = char.letterValue(t, "T")
 }
 
-func (char *Char) letterValue(s string, cas string) int {
+func (char *Char) letterValue(s string, cas string) rune {
 	if s == "" {
 		return 0
 	}
-	v, err := strconv.Btoui64(s, 16)
+	v, err := strconv.ParseUint(s, 16, 64)
 	if err != nil {
 		char.dump(cas)
 		logger.Fatalf("%U: bad letter(%s): %s", char.codePoint, s, err)
 	}
-	return int(v)
+	return rune(v)
 }
 
 func allCategories() []string {
-	a := make([]string, len(category))
-	i := 0
+	a := make([]string, 0, len(category))
 	for k := range category {
-		a[i] = k
-		i++
+		a = append(a, k)
 	}
+	sort.Strings(a)
 	return a
 }
 
 func all(scripts map[string][]Script) []string {
-	a := make([]string, len(scripts))
-	i := 0
+	a := make([]string, 0, len(scripts))
 	for k := range scripts {
-		a[i] = k
-		i++
+		a = append(a, k)
+	}
+	sort.Strings(a)
+	return a
+}
+
+func allCatFold(m map[string]map[rune]bool) []string {
+	a := make([]string, 0, len(m))
+	for k := range m {
+		a = append(a, k)
 	}
+	sort.Strings(a)
 	return a
 }
 
@@ -301,7 +309,7 @@ func version() string {
 	return "Unknown"
 }
 
-func categoryOp(code int, class uint8) bool {
+func categoryOp(code rune, class uint8) bool {
 	category := chars[code].category
 	return len(category) > 0 && category[0] == class
 }
@@ -311,11 +319,11 @@ func loadChars() {
 		flag.Set("data", *url+"UnicodeData.txt")
 	}
 	input := open(*dataURL)
-	var first uint32 = 0
+	var first rune = 0
 	for {
 		line, err := input.ReadString('\n')
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				break
 			}
 			logger.Fatal(err)
@@ -352,7 +360,7 @@ func loadCasefold() {
 	for {
 		line, err := input.ReadString('\n')
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				break
 			}
 			logger.Fatal(err)
@@ -369,15 +377,15 @@ func loadCasefold() {
 			// Only care about 'common' and 'simple' foldings.
 			continue
 		}
-		p1, err := strconv.Btoui64(field[0], 16)
+		p1, err := strconv.ParseUint(field[0], 16, 64)
 		if err != nil {
 			logger.Fatalf("CaseFolding.txt %.5s...: %s", line, err)
 		}
-		p2, err := strconv.Btoui64(field[2], 16)
+		p2, err := strconv.ParseUint(field[2], 16, 64)
 		if err != nil {
 			logger.Fatalf("CaseFolding.txt %.5s...: %s", line, err)
 		}
-		chars[p1].foldCase = int(p2)
+		chars[p1].foldCase = rune(p2)
 	}
 	input.close()
 }
@@ -411,7 +419,7 @@ func printCategories() {
 	if *tablelist == "all" {
 		fmt.Println("// Categories is the set of Unicode data tables.")
 		fmt.Println("var Categories = map[string] *RangeTable {")
-		for k := range category {
+		for _, k := range allCategories() {
 			fmt.Printf("\t%q: %s,\n", k, k)
 		}
 		fmt.Print("}\n\n")
@@ -470,12 +478,12 @@ func printCategories() {
 			decl := fmt.Sprintf("var _%s = &RangeTable{\n", name)
 			dumpRange(
 				decl,
-				func(code int) bool { return categoryOp(code, name[0]) })
+				func(code rune) bool { return categoryOp(code, name[0]) })
 			continue
 		}
 		dumpRange(
 			fmt.Sprintf("var _%s = &RangeTable{\n", name),
-			func(code int) bool { return chars[code].category == name })
+			func(code rune) bool { return chars[code].category == name })
 	}
 	decl.Sort()
 	fmt.Println("var (")
@@ -485,23 +493,23 @@ func printCategories() {
 	fmt.Print(")\n\n")
 }
 
-type Op func(code int) bool
+type Op func(code rune) bool
 
 const format = "\t\t{0x%04x, 0x%04x, %d},\n"
 
 func dumpRange(header string, inCategory Op) {
 	fmt.Print(header)
-	next := 0
+	next := rune(0)
 	fmt.Print("\tR16: []Range16{\n")
 	// one Range for each iteration
 	count := &range16Count
 	size := 16
 	for {
 		// look for start of range
-		for next < len(chars) && !inCategory(next) {
+		for next < rune(len(chars)) && !inCategory(next) {
 			next++
 		}
-		if next >= len(chars) {
+		if next >= rune(len(chars)) {
 			// no characters remain
 			break
 		}
@@ -509,14 +517,14 @@ func dumpRange(header string, inCategory Op) {
 		// start of range
 		lo := next
 		hi := next
-		stride := 1
+		stride := rune(1)
 		// accept lo
 		next++
 		// look for another character to set the stride
-		for next < len(chars) && !inCategory(next) {
+		for next < rune(len(chars)) && !inCategory(next) {
 			next++
 		}
-		if next >= len(chars) {
+		if next >= rune(len(chars)) {
 			// no more characters
 			fmt.Printf(format, lo, hi, stride)
 			break
@@ -524,7 +532,7 @@ func dumpRange(header string, inCategory Op) {
 		// set stride
 		stride = next - lo
 		// check for length of run. next points to first jump in stride
-		for i := next; i < len(chars); i++ {
+		for i := next; i < rune(len(chars)); i++ {
 			if inCategory(i) == (((i - lo) % stride) == 0) {
 				// accept
 				if inCategory(i) {
@@ -577,11 +585,11 @@ func fullCategoryTest(list []string) {
 			logger.Fatalf("unknown table %q", name)
 		}
 		if len(name) == 1 {
-			verifyRange(name, func(code int) bool { return categoryOp(code, name[0]) }, r)
+			verifyRange(name, func(code rune) bool { return categoryOp(code, name[0]) }, r)
 		} else {
 			verifyRange(
 				name,
-				func(code int) bool { return chars[code].category == name },
+				func(code rune) bool { return chars[code].category == name },
 				r)
 		}
 	}
@@ -589,7 +597,8 @@ func fullCategoryTest(list []string) {
 
 func verifyRange(name string, inCategory Op, table *unicode.RangeTable) {
 	count := 0
-	for i := range chars {
+	for j := range chars {
+		i := rune(j)
 		web := inCategory(i)
 		pkg := unicode.Is(table, i)
 		if web != pkg {
@@ -619,13 +628,13 @@ func parseScript(line string, scripts map[string][]Script) {
 	if len(matches) != 4 {
 		logger.Fatalf("%s: %d matches (expected 3)\n", line, len(matches))
 	}
-	lo, err := strconv.Btoui64(matches[1], 16)
+	lo, err := strconv.ParseUint(matches[1], 16, 64)
 	if err != nil {
 		logger.Fatalf("%.5s...: %s", line, err)
 	}
 	hi := lo
 	if len(matches[2]) > 2 { // ignore leading ..
-		hi, err = strconv.Btoui64(matches[2][2:], 16)
+		hi, err = strconv.ParseUint(matches[2][2:], 16, 64)
 		if err != nil {
 			logger.Fatalf("%.5s...: %s", line, err)
 		}
@@ -661,7 +670,7 @@ func fullScriptTest(list []string, installed map[string]*unicode.RangeTable, scr
 		}
 		for _, script := range scripts[name] {
 			for r := script.lo; r <= script.hi; r++ {
-				if !unicode.Is(installed[name], int(r)) {
+				if !unicode.Is(installed[name], rune(r)) {
 					fmt.Fprintf(os.Stderr, "%U: not in script %s\n", r, name)
 				}
 			}
@@ -690,7 +699,7 @@ func printScriptOrProperty(doProps bool) {
 	for {
 		line, err := input.ReadString('\n')
 		if err != nil {
-			if err == os.EOF {
+			if err == io.EOF {
 				break
 			}
 			logger.Fatal(err)
@@ -724,7 +733,7 @@ func printScriptOrProperty(doProps bool) {
 			fmt.Println("// Scripts is the set of Unicode script tables.")
 			fmt.Println("var Scripts = map[string] *RangeTable{")
 		}
-		for k := range table {
+		for _, k := range all(table) {
 			fmt.Printf("\t%q: %s,\n", k, k)
 		}
 		fmt.Print("}\n\n")
@@ -771,11 +780,11 @@ const (
 )
 
 type caseState struct {
-	point        int
+	point        rune
 	_case        int
-	deltaToUpper int
-	deltaToLower int
-	deltaToTitle int
+	deltaToUpper rune
+	deltaToLower rune
+	deltaToTitle rune
 }
 
 // Is d a continuation of the state of c?
@@ -866,10 +875,10 @@ func (c *caseState) isLowerUpper() bool {
 	return true
 }
 
-func getCaseState(i int) (c *caseState) {
+func getCaseState(i rune) (c *caseState) {
 	c = &caseState{point: i, _case: CaseNone}
 	ch := &chars[i]
-	switch int(ch.codePoint) {
+	switch ch.codePoint {
 	case 0:
 		c._case = CaseMissing // Will get NUL wrong but that doesn't matter
 		return
@@ -923,7 +932,7 @@ func printCases() {
 	var startState *caseState    // the start of a run; nil for not active
 	var prevState = &caseState{} // the state of the previous character
 	for i := range chars {
-		state := getCaseState(i)
+		state := getCaseState(rune(i))
 		if state.adjacent(prevState) {
 			prevState = state
 			continue
@@ -963,15 +972,16 @@ func printCaseRange(lo, hi *caseState) {
 }
 
 // If the cased value in the Char is 0, it means use the rune itself.
-func caseIt(rune, cased int) int {
+func caseIt(r, cased rune) rune {
 	if cased == 0 {
-		return rune
+		return r
 	}
 	return cased
 }
 
 func fullCaseTest() {
-	for i, c := range chars {
+	for j, c := range chars {
+		i := rune(j)
 		lower := unicode.ToLower(i)
 		want := caseIt(i, c.lowerCase)
 		if lower != want {
@@ -1026,10 +1036,17 @@ func printLatinProperties() {
 	fmt.Printf("}\n\n")
 }
 
+type runeSlice []rune
+
+func (p runeSlice) Len() int           { return len(p) }
+func (p runeSlice) Less(i, j int) bool { return p[i] < p[j] }
+func (p runeSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
 func printCasefold() {
 	// Build list of case-folding groups attached to each canonical folded char (typically lower case).
-	var caseOrbit = make([][]int, MaxChar+1)
-	for i := range chars {
+	var caseOrbit = make([][]rune, MaxChar+1)
+	for j := range chars {
+		i := rune(j)
 		c := &chars[i]
 		if c.foldCase == 0 {
 			continue
@@ -1042,7 +1059,8 @@ func printCasefold() {
 	}
 
 	// Insert explicit 1-element groups when assuming [lower, upper] would be wrong.
-	for i := range chars {
+	for j := range chars {
+		i := rune(j)
 		c := &chars[i]
 		f := c.foldCase
 		if f == 0 {
@@ -1051,7 +1069,7 @@ func printCasefold() {
 		orb := caseOrbit[f]
 		if orb == nil && (c.upperCase != 0 && c.upperCase != i || c.lowerCase != 0 && c.lowerCase != i) {
 			// Default assumption of [upper, lower] is wrong.
-			caseOrbit[i] = []int{i}
+			caseOrbit[i] = []rune{i}
 		}
 	}
 
@@ -1067,7 +1085,7 @@ func printCasefold() {
 		if orb == nil {
 			continue
 		}
-		sort.Ints(orb)
+		sort.Sort(runeSlice(orb))
 		c := orb[len(orb)-1]
 		for _, d := range orb {
 			chars[c].caseOrbit = d
@@ -1080,14 +1098,14 @@ func printCasefold() {
 	// Tables of category and script folding exceptions: code points
 	// that must be added when interpreting a particular category/script
 	// in a case-folding context.
-	cat := make(map[string]map[int]bool)
+	cat := make(map[string]map[rune]bool)
 	for name := range category {
 		if x := foldExceptions(inCategory(name)); len(x) > 0 {
 			cat[name] = x
 		}
 	}
 
-	scr := make(map[string]map[int]bool)
+	scr := make(map[string]map[rune]bool)
 	for name := range scripts {
 		if x := foldExceptions(inScript(name)); len(x) > 0 {
 			cat[name] = x
@@ -1099,9 +1117,10 @@ func printCasefold() {
 }
 
 // inCategory returns a list of all the runes in the category.
-func inCategory(name string) []int {
-	var x []int
-	for i := range chars {
+func inCategory(name string) []rune {
+	var x []rune
+	for j := range chars {
+		i := rune(j)
 		c := &chars[i]
 		if c.category == name || len(name) == 1 && len(c.category) > 1 && c.category[0] == name[0] {
 			x = append(x, i)
@@ -1111,11 +1130,11 @@ func inCategory(name string) []int {
 }
 
 // inScript returns a list of all the runes in the script.
-func inScript(name string) []int {
-	var x []int
+func inScript(name string) []rune {
+	var x []rune
 	for _, s := range scripts[name] {
 		for c := s.lo; c <= s.hi; c++ {
-			x = append(x, int(c))
+			x = append(x, rune(c))
 		}
 	}
 	return x
@@ -1123,9 +1142,9 @@ func inScript(name string) []int {
 
 // foldExceptions returns a list of all the runes fold-equivalent
 // to runes in class but not in class themselves.
-func foldExceptions(class []int) map[int]bool {
+func foldExceptions(class []rune) map[rune]bool {
 	// Create map containing class and all fold-equivalent chars.
-	m := make(map[int]bool)
+	m := make(map[rune]bool)
 	for _, r := range class {
 		c := &chars[r]
 		if c.caseOrbit == 0 {
@@ -1152,7 +1171,7 @@ func foldExceptions(class []int) map[int]bool {
 
 	// Remove class itself.
 	for _, r := range class {
-		m[r] = false, false
+		delete(m, r)
 	}
 
 	// What's left is the exceptions.
@@ -1173,7 +1192,8 @@ var comment = map[string]string{
 
 func printCaseOrbit() {
 	if *test {
-		for i := range chars {
+		for j := range chars {
+			i := rune(j)
 			c := &chars[i]
 			f := c.caseOrbit
 			if f == 0 {
@@ -1203,7 +1223,7 @@ func printCaseOrbit() {
 	fmt.Printf("}\n\n")
 }
 
-func printCatFold(name string, m map[string]map[int]bool) {
+func printCatFold(name string, m map[string]map[rune]bool) {
 	if *test {
 		var pkgMap map[string]*unicode.RangeTable
 		if name == "FoldCategory" {
@@ -1223,7 +1243,7 @@ func printCatFold(name string, m map[string]map[int]bool) {
 			}
 			n := 0
 			for _, r := range t.R16 {
-				for c := int(r.Lo); c <= int(r.Hi); c += int(r.Stride) {
+				for c := rune(r.Lo); c <= rune(r.Hi); c += rune(r.Stride) {
 					if !v[c] {
 						fmt.Fprintf(os.Stderr, "unicode.%s[%q] contains %#U, should not\n", name, k, c)
 					}
@@ -1231,7 +1251,7 @@ func printCatFold(name string, m map[string]map[int]bool) {
 				}
 			}
 			for _, r := range t.R32 {
-				for c := int(r.Lo); c <= int(r.Hi); c += int(r.Stride) {
+				for c := rune(r.Lo); c <= rune(r.Hi); c += rune(r.Stride) {
 					if !v[c] {
 						fmt.Fprintf(os.Stderr, "unicode.%s[%q] contains %#U, should not\n", name, k, c)
 					}
@@ -1247,14 +1267,15 @@ func printCatFold(name string, m map[string]map[int]bool) {
 
 	fmt.Print(comment[name])
 	fmt.Printf("var %s = map[string]*RangeTable{\n", name)
-	for name := range m {
+	for _, name := range allCatFold(m) {
 		fmt.Printf("\t%q: fold%s,\n", name, name)
 	}
 	fmt.Printf("}\n\n")
-	for name, class := range m {
+	for _, name := range allCatFold(m) {
+		class := m[name]
 		dumpRange(
 			fmt.Sprintf("var fold%s = &RangeTable{\n", name),
-			func(code int) bool { return class[code] })
+			func(code rune) bool { return class[code] })
 	}
 }
 
diff --git a/src/pkg/unicode/script_test.go b/src/pkg/unicode/script_test.go
index b37ad18..1c5b801 100644
--- a/src/pkg/unicode/script_test.go
+++ b/src/pkg/unicode/script_test.go
@@ -10,7 +10,7 @@ import (
 )
 
 type T struct {
-	rune   int
+	rune   rune
 	script string
 }
 
@@ -206,7 +206,7 @@ func TestScripts(t *testing.T) {
 		if !Is(Scripts[test.script], test.rune) {
 			t.Errorf("IsScript(%U, %s) = false, want true", test.rune, test.script)
 		}
-		notTested[test.script] = false, false
+		delete(notTested, test.script)
 	}
 	for _, test := range outTest {
 		if Is(Scripts[test.script], test.rune) {
@@ -230,7 +230,7 @@ func TestCategories(t *testing.T) {
 		if !Is(Categories[test.script], test.rune) {
 			t.Errorf("IsCategory(%U, %s) = false, want true", test.rune, test.script)
 		}
-		notTested[test.script] = false, false
+		delete(notTested, test.script)
 	}
 	for k := range notTested {
 		t.Error("category not tested:", k)
@@ -249,7 +249,7 @@ func TestProperties(t *testing.T) {
 		if !Is(Properties[test.script], test.rune) {
 			t.Errorf("IsCategory(%U, %s) = false, want true", test.rune, test.script)
 		}
-		notTested[test.script] = false, false
+		delete(notTested, test.script)
 	}
 	for k := range notTested {
 		t.Error("property not tested:", k)
diff --git a/src/pkg/unicode/tables.go b/src/pkg/unicode/tables.go
index 88b5c0f..a3b8826 100644
--- a/src/pkg/unicode/tables.go
+++ b/src/pkg/unicode/tables.go
@@ -9,227 +9,42 @@ const Version = "6.0.0"
 
 // Categories is the set of Unicode data tables.
 var Categories = map[string]*RangeTable{
-	"Lm": Lm,
-	"Ll": Ll,
 	"C":  C,
-	"M":  M,
+	"Cc": Cc,
+	"Cf": Cf,
+	"Co": Co,
+	"Cs": Cs,
 	"L":  L,
+	"Ll": Ll,
+	"Lm": Lm,
+	"Lo": Lo,
+	"Lt": Lt,
+	"Lu": Lu,
+	"M":  M,
+	"Mc": Mc,
+	"Me": Me,
+	"Mn": Mn,
 	"N":  N,
+	"Nd": Nd,
+	"Nl": Nl,
+	"No": No,
 	"P":  P,
+	"Pc": Pc,
+	"Pd": Pd,
+	"Pe": Pe,
+	"Pf": Pf,
+	"Pi": Pi,
+	"Po": Po,
+	"Ps": Ps,
 	"S":  S,
+	"Sc": Sc,
+	"Sk": Sk,
+	"Sm": Sm,
+	"So": So,
 	"Z":  Z,
-	"Me": Me,
-	"Mc": Mc,
-	"Mn": Mn,
 	"Zl": Zl,
 	"Zp": Zp,
 	"Zs": Zs,
-	"Cs": Cs,
-	"Co": Co,
-	"Cf": Cf,
-	"Cc": Cc,
-	"Po": Po,
-	"Pi": Pi,
-	"Pf": Pf,
-	"Pe": Pe,
-	"Pd": Pd,
-	"Pc": Pc,
-	"Ps": Ps,
-	"Nd": Nd,
-	"Nl": Nl,
-	"No": No,
-	"So": So,
-	"Sm": Sm,
-	"Sk": Sk,
-	"Sc": Sc,
-	"Lu": Lu,
-	"Lt": Lt,
-	"Lo": Lo,
-}
-
-var _Lm = &RangeTable{
-	R16: []Range16{
-		{0x02b0, 0x02c1, 1},
-		{0x02c6, 0x02d1, 1},
-		{0x02e0, 0x02e4, 1},
-		{0x02ec, 0x02ee, 2},
-		{0x0374, 0x037a, 6},
-		{0x0559, 0x0640, 231},
-		{0x06e5, 0x06e6, 1},
-		{0x07f4, 0x07f5, 1},
-		{0x07fa, 0x081a, 32},
-		{0x0824, 0x0828, 4},
-		{0x0971, 0x0e46, 1237},
-		{0x0ec6, 0x10fc, 566},
-		{0x17d7, 0x1843, 108},
-		{0x1aa7, 0x1c78, 465},
-		{0x1c79, 0x1c7d, 1},
-		{0x1d2c, 0x1d61, 1},
-		{0x1d78, 0x1d9b, 35},
-		{0x1d9c, 0x1dbf, 1},
-		{0x2071, 0x207f, 14},
-		{0x2090, 0x209c, 1},
-		{0x2c7d, 0x2d6f, 242},
-		{0x2e2f, 0x3005, 470},
-		{0x3031, 0x3035, 1},
-		{0x303b, 0x309d, 98},
-		{0x309e, 0x30fc, 94},
-		{0x30fd, 0x30fe, 1},
-		{0xa015, 0xa4f8, 1251},
-		{0xa4f9, 0xa4fd, 1},
-		{0xa60c, 0xa67f, 115},
-		{0xa717, 0xa71f, 1},
-		{0xa770, 0xa788, 24},
-		{0xa9cf, 0xaa70, 161},
-		{0xaadd, 0xff70, 21651},
-		{0xff9e, 0xff9f, 1},
-	},
-}
-
-var _Ll = &RangeTable{
-	R16: []Range16{
-		{0x0061, 0x007a, 1},
-		{0x00aa, 0x00b5, 11},
-		{0x00ba, 0x00df, 37},
-		{0x00e0, 0x00f6, 1},
-		{0x00f8, 0x00ff, 1},
-		{0x0101, 0x0137, 2},
-		{0x0138, 0x0148, 2},
-		{0x0149, 0x0177, 2},
-		{0x017a, 0x017e, 2},
-		{0x017f, 0x0180, 1},
-		{0x0183, 0x0185, 2},
-		{0x0188, 0x018c, 4},
-		{0x018d, 0x0192, 5},
-		{0x0195, 0x0199, 4},
-		{0x019a, 0x019b, 1},
-		{0x019e, 0x01a1, 3},
-		{0x01a3, 0x01a5, 2},
-		{0x01a8, 0x01aa, 2},
-		{0x01ab, 0x01ad, 2},
-		{0x01b0, 0x01b4, 4},
-		{0x01b6, 0x01b9, 3},
-		{0x01ba, 0x01bd, 3},
-		{0x01be, 0x01bf, 1},
-		{0x01c6, 0x01cc, 3},
-		{0x01ce, 0x01dc, 2},
-		{0x01dd, 0x01ef, 2},
-		{0x01f0, 0x01f3, 3},
-		{0x01f5, 0x01f9, 4},
-		{0x01fb, 0x0233, 2},
-		{0x0234, 0x0239, 1},
-		{0x023c, 0x023f, 3},
-		{0x0240, 0x0242, 2},
-		{0x0247, 0x024f, 2},
-		{0x0250, 0x0293, 1},
-		{0x0295, 0x02af, 1},
-		{0x0371, 0x0373, 2},
-		{0x0377, 0x037b, 4},
-		{0x037c, 0x037d, 1},
-		{0x0390, 0x03ac, 28},
-		{0x03ad, 0x03ce, 1},
-		{0x03d0, 0x03d1, 1},
-		{0x03d5, 0x03d7, 1},
-		{0x03d9, 0x03ef, 2},
-		{0x03f0, 0x03f3, 1},
-		{0x03f5, 0x03fb, 3},
-		{0x03fc, 0x0430, 52},
-		{0x0431, 0x045f, 1},
-		{0x0461, 0x0481, 2},
-		{0x048b, 0x04bf, 2},
-		{0x04c2, 0x04ce, 2},
-		{0x04cf, 0x0527, 2},
-		{0x0561, 0x0587, 1},
-		{0x1d00, 0x1d2b, 1},
-		{0x1d62, 0x1d77, 1},
-		{0x1d79, 0x1d9a, 1},
-		{0x1e01, 0x1e95, 2},
-		{0x1e96, 0x1e9d, 1},
-		{0x1e9f, 0x1eff, 2},
-		{0x1f00, 0x1f07, 1},
-		{0x1f10, 0x1f15, 1},
-		{0x1f20, 0x1f27, 1},
-		{0x1f30, 0x1f37, 1},
-		{0x1f40, 0x1f45, 1},
-		{0x1f50, 0x1f57, 1},
-		{0x1f60, 0x1f67, 1},
-		{0x1f70, 0x1f7d, 1},
-		{0x1f80, 0x1f87, 1},
-		{0x1f90, 0x1f97, 1},
-		{0x1fa0, 0x1fa7, 1},
-		{0x1fb0, 0x1fb4, 1},
-		{0x1fb6, 0x1fb7, 1},
-		{0x1fbe, 0x1fc2, 4},
-		{0x1fc3, 0x1fc4, 1},
-		{0x1fc6, 0x1fc7, 1},
-		{0x1fd0, 0x1fd3, 1},
-		{0x1fd6, 0x1fd7, 1},
-		{0x1fe0, 0x1fe7, 1},
-		{0x1ff2, 0x1ff4, 1},
-		{0x1ff6, 0x1ff7, 1},
-		{0x210a, 0x210e, 4},
-		{0x210f, 0x2113, 4},
-		{0x212f, 0x2139, 5},
-		{0x213c, 0x213d, 1},
-		{0x2146, 0x2149, 1},
-		{0x214e, 0x2184, 54},
-		{0x2c30, 0x2c5e, 1},
-		{0x2c61, 0x2c65, 4},
-		{0x2c66, 0x2c6c, 2},
-		{0x2c71, 0x2c73, 2},
-		{0x2c74, 0x2c76, 2},
-		{0x2c77, 0x2c7c, 1},
-		{0x2c81, 0x2ce3, 2},
-		{0x2ce4, 0x2cec, 8},
-		{0x2cee, 0x2d00, 18},
-		{0x2d01, 0x2d25, 1},
-		{0xa641, 0xa66d, 2},
-		{0xa681, 0xa697, 2},
-		{0xa723, 0xa72f, 2},
-		{0xa730, 0xa731, 1},
-		{0xa733, 0xa771, 2},
-		{0xa772, 0xa778, 1},
-		{0xa77a, 0xa77c, 2},
-		{0xa77f, 0xa787, 2},
-		{0xa78c, 0xa78e, 2},
-		{0xa791, 0xa7a1, 16},
-		{0xa7a3, 0xa7a9, 2},
-		{0xa7fa, 0xfb00, 21254},
-		{0xfb01, 0xfb06, 1},
-		{0xfb13, 0xfb17, 1},
-		{0xff41, 0xff5a, 1},
-	},
-	R32: []Range32{
-		{0x10428, 0x1044f, 1},
-		{0x1d41a, 0x1d433, 1},
-		{0x1d44e, 0x1d454, 1},
-		{0x1d456, 0x1d467, 1},
-		{0x1d482, 0x1d49b, 1},
-		{0x1d4b6, 0x1d4b9, 1},
-		{0x1d4bb, 0x1d4bd, 2},
-		{0x1d4be, 0x1d4c3, 1},
-		{0x1d4c5, 0x1d4cf, 1},
-		{0x1d4ea, 0x1d503, 1},
-		{0x1d51e, 0x1d537, 1},
-		{0x1d552, 0x1d56b, 1},
-		{0x1d586, 0x1d59f, 1},
-		{0x1d5ba, 0x1d5d3, 1},
-		{0x1d5ee, 0x1d607, 1},
-		{0x1d622, 0x1d63b, 1},
-		{0x1d656, 0x1d66f, 1},
-		{0x1d68a, 0x1d6a5, 1},
-		{0x1d6c2, 0x1d6da, 1},
-		{0x1d6dc, 0x1d6e1, 1},
-		{0x1d6fc, 0x1d714, 1},
-		{0x1d716, 0x1d71b, 1},
-		{0x1d736, 0x1d74e, 1},
-		{0x1d750, 0x1d755, 1},
-		{0x1d770, 0x1d788, 1},
-		{0x1d78a, 0x1d78f, 1},
-		{0x1d7aa, 0x1d7c2, 1},
-		{0x1d7c4, 0x1d7c9, 1},
-		{0x1d7cb, 0x1d7cb, 1},
-	},
 }
 
 var _C = &RangeTable{
@@ -258,195 +73,47 @@ var _C = &RangeTable{
 	},
 }
 
-var _M = &RangeTable{
+var _Cc = &RangeTable{
 	R16: []Range16{
-		{0x0300, 0x036f, 1},
-		{0x0483, 0x0489, 1},
-		{0x0591, 0x05bd, 1},
-		{0x05bf, 0x05c1, 2},
-		{0x05c2, 0x05c4, 2},
-		{0x05c5, 0x05c7, 2},
-		{0x0610, 0x061a, 1},
-		{0x064b, 0x065f, 1},
-		{0x0670, 0x06d6, 102},
-		{0x06d7, 0x06dc, 1},
-		{0x06df, 0x06e4, 1},
-		{0x06e7, 0x06e8, 1},
-		{0x06ea, 0x06ed, 1},
-		{0x0711, 0x0730, 31},
-		{0x0731, 0x074a, 1},
-		{0x07a6, 0x07b0, 1},
-		{0x07eb, 0x07f3, 1},
-		{0x0816, 0x0819, 1},
-		{0x081b, 0x0823, 1},
-		{0x0825, 0x0827, 1},
-		{0x0829, 0x082d, 1},
-		{0x0859, 0x085b, 1},
-		{0x0900, 0x0903, 1},
-		{0x093a, 0x093c, 1},
-		{0x093e, 0x094f, 1},
-		{0x0951, 0x0957, 1},
-		{0x0962, 0x0963, 1},
-		{0x0981, 0x0983, 1},
-		{0x09bc, 0x09be, 2},
-		{0x09bf, 0x09c4, 1},
-		{0x09c7, 0x09c8, 1},
-		{0x09cb, 0x09cd, 1},
-		{0x09d7, 0x09e2, 11},
-		{0x09e3, 0x0a01, 30},
-		{0x0a02, 0x0a03, 1},
-		{0x0a3c, 0x0a3e, 2},
-		{0x0a3f, 0x0a42, 1},
-		{0x0a47, 0x0a48, 1},
-		{0x0a4b, 0x0a4d, 1},
-		{0x0a51, 0x0a70, 31},
-		{0x0a71, 0x0a75, 4},
-		{0x0a81, 0x0a83, 1},
-		{0x0abc, 0x0abe, 2},
-		{0x0abf, 0x0ac5, 1},
-		{0x0ac7, 0x0ac9, 1},
-		{0x0acb, 0x0acd, 1},
-		{0x0ae2, 0x0ae3, 1},
-		{0x0b01, 0x0b03, 1},
-		{0x0b3c, 0x0b3e, 2},
-		{0x0b3f, 0x0b44, 1},
-		{0x0b47, 0x0b48, 1},
-		{0x0b4b, 0x0b4d, 1},
-		{0x0b56, 0x0b57, 1},
-		{0x0b62, 0x0b63, 1},
-		{0x0b82, 0x0bbe, 60},
-		{0x0bbf, 0x0bc2, 1},
-		{0x0bc6, 0x0bc8, 1},
-		{0x0bca, 0x0bcd, 1},
-		{0x0bd7, 0x0c01, 42},
-		{0x0c02, 0x0c03, 1},
-		{0x0c3e, 0x0c44, 1},
-		{0x0c46, 0x0c48, 1},
-		{0x0c4a, 0x0c4d, 1},
-		{0x0c55, 0x0c56, 1},
-		{0x0c62, 0x0c63, 1},
-		{0x0c82, 0x0c83, 1},
-		{0x0cbc, 0x0cbe, 2},
-		{0x0cbf, 0x0cc4, 1},
-		{0x0cc6, 0x0cc8, 1},
-		{0x0cca, 0x0ccd, 1},
-		{0x0cd5, 0x0cd6, 1},
-		{0x0ce2, 0x0ce3, 1},
-		{0x0d02, 0x0d03, 1},
-		{0x0d3e, 0x0d44, 1},
-		{0x0d46, 0x0d48, 1},
-		{0x0d4a, 0x0d4d, 1},
-		{0x0d57, 0x0d62, 11},
-		{0x0d63, 0x0d82, 31},
-		{0x0d83, 0x0dca, 71},
-		{0x0dcf, 0x0dd4, 1},
-		{0x0dd6, 0x0dd8, 2},
-		{0x0dd9, 0x0ddf, 1},
-		{0x0df2, 0x0df3, 1},
-		{0x0e31, 0x0e34, 3},
-		{0x0e35, 0x0e3a, 1},
-		{0x0e47, 0x0e4e, 1},
-		{0x0eb1, 0x0eb4, 3},
-		{0x0eb5, 0x0eb9, 1},
-		{0x0ebb, 0x0ebc, 1},
-		{0x0ec8, 0x0ecd, 1},
-		{0x0f18, 0x0f19, 1},
-		{0x0f35, 0x0f39, 2},
-		{0x0f3e, 0x0f3f, 1},
-		{0x0f71, 0x0f84, 1},
-		{0x0f86, 0x0f87, 1},
-		{0x0f8d, 0x0f97, 1},
-		{0x0f99, 0x0fbc, 1},
-		{0x0fc6, 0x102b, 101},
-		{0x102c, 0x103e, 1},
-		{0x1056, 0x1059, 1},
-		{0x105e, 0x1060, 1},
-		{0x1062, 0x1064, 1},
-		{0x1067, 0x106d, 1},
-		{0x1071, 0x1074, 1},
-		{0x1082, 0x108d, 1},
-		{0x108f, 0x109a, 11},
-		{0x109b, 0x109d, 1},
-		{0x135d, 0x135f, 1},
-		{0x1712, 0x1714, 1},
-		{0x1732, 0x1734, 1},
-		{0x1752, 0x1753, 1},
-		{0x1772, 0x1773, 1},
-		{0x17b6, 0x17d3, 1},
-		{0x17dd, 0x180b, 46},
-		{0x180c, 0x180d, 1},
-		{0x18a9, 0x1920, 119},
-		{0x1921, 0x192b, 1},
-		{0x1930, 0x193b, 1},
-		{0x19b0, 0x19c0, 1},
-		{0x19c8, 0x19c9, 1},
-		{0x1a17, 0x1a1b, 1},
-		{0x1a55, 0x1a5e, 1},
-		{0x1a60, 0x1a7c, 1},
-		{0x1a7f, 0x1b00, 129},
-		{0x1b01, 0x1b04, 1},
-		{0x1b34, 0x1b44, 1},
-		{0x1b6b, 0x1b73, 1},
-		{0x1b80, 0x1b82, 1},
-		{0x1ba1, 0x1baa, 1},
-		{0x1be6, 0x1bf3, 1},
-		{0x1c24, 0x1c37, 1},
-		{0x1cd0, 0x1cd2, 1},
-		{0x1cd4, 0x1ce8, 1},
-		{0x1ced, 0x1cf2, 5},
-		{0x1dc0, 0x1de6, 1},
-		{0x1dfc, 0x1dff, 1},
-		{0x20d0, 0x20f0, 1},
-		{0x2cef, 0x2cf1, 1},
-		{0x2d7f, 0x2de0, 97},
-		{0x2de1, 0x2dff, 1},
-		{0x302a, 0x302f, 1},
-		{0x3099, 0x309a, 1},
-		{0xa66f, 0xa672, 1},
-		{0xa67c, 0xa67d, 1},
-		{0xa6f0, 0xa6f1, 1},
-		{0xa802, 0xa806, 4},
-		{0xa80b, 0xa823, 24},
-		{0xa824, 0xa827, 1},
-		{0xa880, 0xa881, 1},
-		{0xa8b4, 0xa8c4, 1},
-		{0xa8e0, 0xa8f1, 1},
-		{0xa926, 0xa92d, 1},
-		{0xa947, 0xa953, 1},
-		{0xa980, 0xa983, 1},
-		{0xa9b3, 0xa9c0, 1},
-		{0xaa29, 0xaa36, 1},
-		{0xaa43, 0xaa4c, 9},
-		{0xaa4d, 0xaa7b, 46},
-		{0xaab0, 0xaab2, 2},
-		{0xaab3, 0xaab4, 1},
-		{0xaab7, 0xaab8, 1},
-		{0xaabe, 0xaabf, 1},
-		{0xaac1, 0xabe3, 290},
-		{0xabe4, 0xabea, 1},
-		{0xabec, 0xabed, 1},
-		{0xfb1e, 0xfe00, 738},
-		{0xfe01, 0xfe0f, 1},
-		{0xfe20, 0xfe26, 1},
+		{0x0001, 0x001f, 1},
+		{0x007f, 0x009f, 1},
+	},
+}
+
+var _Cf = &RangeTable{
+	R16: []Range16{
+		{0x00ad, 0x0600, 1363},
+		{0x0601, 0x0603, 1},
+		{0x06dd, 0x070f, 50},
+		{0x17b4, 0x17b5, 1},
+		{0x200b, 0x200f, 1},
+		{0x202a, 0x202e, 1},
+		{0x2060, 0x2064, 1},
+		{0x206a, 0x206f, 1},
+		{0xfeff, 0xfff9, 250},
+		{0xfffa, 0xfffb, 1},
 	},
 	R32: []Range32{
-		{0x101fd, 0x10a01, 2052},
-		{0x10a02, 0x10a03, 1},
-		{0x10a05, 0x10a06, 1},
-		{0x10a0c, 0x10a0f, 1},
-		{0x10a38, 0x10a3a, 1},
-		{0x10a3f, 0x11000, 1473},
-		{0x11001, 0x11002, 1},
-		{0x11038, 0x11046, 1},
-		{0x11080, 0x11082, 1},
-		{0x110b0, 0x110ba, 1},
-		{0x1d165, 0x1d169, 1},
-		{0x1d16d, 0x1d172, 1},
-		{0x1d17b, 0x1d182, 1},
-		{0x1d185, 0x1d18b, 1},
-		{0x1d1aa, 0x1d1ad, 1},
-		{0x1d242, 0x1d244, 1},
-		{0xe0100, 0xe01ef, 1},
+		{0x110bd, 0x1d173, 49334},
+		{0x1d174, 0x1d17a, 1},
+		{0xe0001, 0xe0020, 31},
+		{0xe0021, 0xe007f, 1},
+	},
+}
+
+var _Co = &RangeTable{
+	R16: []Range16{
+		{0xe000, 0xf8ff, 1},
+	},
+	R32: []Range32{
+		{0xf0000, 0xffffd, 1},
+		{0x100000, 0x10fffd, 1},
+	},
+}
+
+var _Cs = &RangeTable{
+	R16: []Range16{
+		{0xd800, 0xdfff, 1},
 	},
 }
 
@@ -871,1518 +538,192 @@ var _L = &RangeTable{
 	},
 }
 
-var _N = &RangeTable{
+var _Ll = &RangeTable{
 	R16: []Range16{
-		{0x0030, 0x0039, 1},
-		{0x00b2, 0x00b3, 1},
-		{0x00b9, 0x00bc, 3},
-		{0x00bd, 0x00be, 1},
-		{0x0660, 0x0669, 1},
-		{0x06f0, 0x06f9, 1},
-		{0x07c0, 0x07c9, 1},
-		{0x0966, 0x096f, 1},
-		{0x09e6, 0x09ef, 1},
-		{0x09f4, 0x09f9, 1},
-		{0x0a66, 0x0a6f, 1},
-		{0x0ae6, 0x0aef, 1},
-		{0x0b66, 0x0b6f, 1},
-		{0x0b72, 0x0b77, 1},
-		{0x0be6, 0x0bf2, 1},
-		{0x0c66, 0x0c6f, 1},
-		{0x0c78, 0x0c7e, 1},
-		{0x0ce6, 0x0cef, 1},
-		{0x0d66, 0x0d75, 1},
-		{0x0e50, 0x0e59, 1},
-		{0x0ed0, 0x0ed9, 1},
-		{0x0f20, 0x0f33, 1},
-		{0x1040, 0x1049, 1},
-		{0x1090, 0x1099, 1},
-		{0x1369, 0x137c, 1},
-		{0x16ee, 0x16f0, 1},
-		{0x17e0, 0x17e9, 1},
-		{0x17f0, 0x17f9, 1},
-		{0x1810, 0x1819, 1},
-		{0x1946, 0x194f, 1},
-		{0x19d0, 0x19da, 1},
-		{0x1a80, 0x1a89, 1},
-		{0x1a90, 0x1a99, 1},
-		{0x1b50, 0x1b59, 1},
-		{0x1bb0, 0x1bb9, 1},
-		{0x1c40, 0x1c49, 1},
-		{0x1c50, 0x1c59, 1},
-		{0x2070, 0x2074, 4},
-		{0x2075, 0x2079, 1},
-		{0x2080, 0x2089, 1},
-		{0x2150, 0x2182, 1},
-		{0x2185, 0x2189, 1},
-		{0x2460, 0x249b, 1},
-		{0x24ea, 0x24ff, 1},
-		{0x2776, 0x2793, 1},
-		{0x2cfd, 0x3007, 778},
-		{0x3021, 0x3029, 1},
-		{0x3038, 0x303a, 1},
-		{0x3192, 0x3195, 1},
-		{0x3220, 0x3229, 1},
-		{0x3251, 0x325f, 1},
-		{0x3280, 0x3289, 1},
-		{0x32b1, 0x32bf, 1},
-		{0xa620, 0xa629, 1},
-		{0xa6e6, 0xa6ef, 1},
-		{0xa830, 0xa835, 1},
-		{0xa8d0, 0xa8d9, 1},
-		{0xa900, 0xa909, 1},
-		{0xa9d0, 0xa9d9, 1},
-		{0xaa50, 0xaa59, 1},
-		{0xabf0, 0xabf9, 1},
-		{0xff10, 0xff19, 1},
+		{0x0061, 0x007a, 1},
+		{0x00aa, 0x00b5, 11},
+		{0x00ba, 0x00df, 37},
+		{0x00e0, 0x00f6, 1},
+		{0x00f8, 0x00ff, 1},
+		{0x0101, 0x0137, 2},
+		{0x0138, 0x0148, 2},
+		{0x0149, 0x0177, 2},
+		{0x017a, 0x017e, 2},
+		{0x017f, 0x0180, 1},
+		{0x0183, 0x0185, 2},
+		{0x0188, 0x018c, 4},
+		{0x018d, 0x0192, 5},
+		{0x0195, 0x0199, 4},
+		{0x019a, 0x019b, 1},
+		{0x019e, 0x01a1, 3},
+		{0x01a3, 0x01a5, 2},
+		{0x01a8, 0x01aa, 2},
+		{0x01ab, 0x01ad, 2},
+		{0x01b0, 0x01b4, 4},
+		{0x01b6, 0x01b9, 3},
+		{0x01ba, 0x01bd, 3},
+		{0x01be, 0x01bf, 1},
+		{0x01c6, 0x01cc, 3},
+		{0x01ce, 0x01dc, 2},
+		{0x01dd, 0x01ef, 2},
+		{0x01f0, 0x01f3, 3},
+		{0x01f5, 0x01f9, 4},
+		{0x01fb, 0x0233, 2},
+		{0x0234, 0x0239, 1},
+		{0x023c, 0x023f, 3},
+		{0x0240, 0x0242, 2},
+		{0x0247, 0x024f, 2},
+		{0x0250, 0x0293, 1},
+		{0x0295, 0x02af, 1},
+		{0x0371, 0x0373, 2},
+		{0x0377, 0x037b, 4},
+		{0x037c, 0x037d, 1},
+		{0x0390, 0x03ac, 28},
+		{0x03ad, 0x03ce, 1},
+		{0x03d0, 0x03d1, 1},
+		{0x03d5, 0x03d7, 1},
+		{0x03d9, 0x03ef, 2},
+		{0x03f0, 0x03f3, 1},
+		{0x03f5, 0x03fb, 3},
+		{0x03fc, 0x0430, 52},
+		{0x0431, 0x045f, 1},
+		{0x0461, 0x0481, 2},
+		{0x048b, 0x04bf, 2},
+		{0x04c2, 0x04ce, 2},
+		{0x04cf, 0x0527, 2},
+		{0x0561, 0x0587, 1},
+		{0x1d00, 0x1d2b, 1},
+		{0x1d62, 0x1d77, 1},
+		{0x1d79, 0x1d9a, 1},
+		{0x1e01, 0x1e95, 2},
+		{0x1e96, 0x1e9d, 1},
+		{0x1e9f, 0x1eff, 2},
+		{0x1f00, 0x1f07, 1},
+		{0x1f10, 0x1f15, 1},
+		{0x1f20, 0x1f27, 1},
+		{0x1f30, 0x1f37, 1},
+		{0x1f40, 0x1f45, 1},
+		{0x1f50, 0x1f57, 1},
+		{0x1f60, 0x1f67, 1},
+		{0x1f70, 0x1f7d, 1},
+		{0x1f80, 0x1f87, 1},
+		{0x1f90, 0x1f97, 1},
+		{0x1fa0, 0x1fa7, 1},
+		{0x1fb0, 0x1fb4, 1},
+		{0x1fb6, 0x1fb7, 1},
+		{0x1fbe, 0x1fc2, 4},
+		{0x1fc3, 0x1fc4, 1},
+		{0x1fc6, 0x1fc7, 1},
+		{0x1fd0, 0x1fd3, 1},
+		{0x1fd6, 0x1fd7, 1},
+		{0x1fe0, 0x1fe7, 1},
+		{0x1ff2, 0x1ff4, 1},
+		{0x1ff6, 0x1ff7, 1},
+		{0x210a, 0x210e, 4},
+		{0x210f, 0x2113, 4},
+		{0x212f, 0x2139, 5},
+		{0x213c, 0x213d, 1},
+		{0x2146, 0x2149, 1},
+		{0x214e, 0x2184, 54},
+		{0x2c30, 0x2c5e, 1},
+		{0x2c61, 0x2c65, 4},
+		{0x2c66, 0x2c6c, 2},
+		{0x2c71, 0x2c73, 2},
+		{0x2c74, 0x2c76, 2},
+		{0x2c77, 0x2c7c, 1},
+		{0x2c81, 0x2ce3, 2},
+		{0x2ce4, 0x2cec, 8},
+		{0x2cee, 0x2d00, 18},
+		{0x2d01, 0x2d25, 1},
+		{0xa641, 0xa66d, 2},
+		{0xa681, 0xa697, 2},
+		{0xa723, 0xa72f, 2},
+		{0xa730, 0xa731, 1},
+		{0xa733, 0xa771, 2},
+		{0xa772, 0xa778, 1},
+		{0xa77a, 0xa77c, 2},
+		{0xa77f, 0xa787, 2},
+		{0xa78c, 0xa78e, 2},
+		{0xa791, 0xa7a1, 16},
+		{0xa7a3, 0xa7a9, 2},
+		{0xa7fa, 0xfb00, 21254},
+		{0xfb01, 0xfb06, 1},
+		{0xfb13, 0xfb17, 1},
+		{0xff41, 0xff5a, 1},
 	},
 	R32: []Range32{
-		{0x10107, 0x10133, 1},
-		{0x10140, 0x10178, 1},
-		{0x1018a, 0x10320, 406},
-		{0x10321, 0x10323, 1},
-		{0x10341, 0x1034a, 9},
-		{0x103d1, 0x103d5, 1},
-		{0x104a0, 0x104a9, 1},
-		{0x10858, 0x1085f, 1},
-		{0x10916, 0x1091b, 1},
-		{0x10a40, 0x10a47, 1},
-		{0x10a7d, 0x10a7e, 1},
-		{0x10b58, 0x10b5f, 1},
-		{0x10b78, 0x10b7f, 1},
-		{0x10e60, 0x10e7e, 1},
-		{0x11052, 0x1106f, 1},
-		{0x12400, 0x12462, 1},
-		{0x1d360, 0x1d371, 1},
-		{0x1d7ce, 0x1d7ff, 1},
-		{0x1f100, 0x1f10a, 1},
+		{0x10428, 0x1044f, 1},
+		{0x1d41a, 0x1d433, 1},
+		{0x1d44e, 0x1d454, 1},
+		{0x1d456, 0x1d467, 1},
+		{0x1d482, 0x1d49b, 1},
+		{0x1d4b6, 0x1d4b9, 1},
+		{0x1d4bb, 0x1d4bd, 2},
+		{0x1d4be, 0x1d4c3, 1},
+		{0x1d4c5, 0x1d4cf, 1},
+		{0x1d4ea, 0x1d503, 1},
+		{0x1d51e, 0x1d537, 1},
+		{0x1d552, 0x1d56b, 1},
+		{0x1d586, 0x1d59f, 1},
+		{0x1d5ba, 0x1d5d3, 1},
+		{0x1d5ee, 0x1d607, 1},
+		{0x1d622, 0x1d63b, 1},
+		{0x1d656, 0x1d66f, 1},
+		{0x1d68a, 0x1d6a5, 1},
+		{0x1d6c2, 0x1d6da, 1},
+		{0x1d6dc, 0x1d6e1, 1},
+		{0x1d6fc, 0x1d714, 1},
+		{0x1d716, 0x1d71b, 1},
+		{0x1d736, 0x1d74e, 1},
+		{0x1d750, 0x1d755, 1},
+		{0x1d770, 0x1d788, 1},
+		{0x1d78a, 0x1d78f, 1},
+		{0x1d7aa, 0x1d7c2, 1},
+		{0x1d7c4, 0x1d7c9, 1},
+		{0x1d7cb, 0x1d7cb, 1},
 	},
 }
 
-var _P = &RangeTable{
+var _Lm = &RangeTable{
 	R16: []Range16{
-		{0x0021, 0x0023, 1},
-		{0x0025, 0x002a, 1},
-		{0x002c, 0x002f, 1},
-		{0x003a, 0x003b, 1},
-		{0x003f, 0x0040, 1},
-		{0x005b, 0x005d, 1},
-		{0x005f, 0x007b, 28},
-		{0x007d, 0x00a1, 36},
-		{0x00ab, 0x00b7, 12},
-		{0x00bb, 0x00bf, 4},
-		{0x037e, 0x0387, 9},
-		{0x055a, 0x055f, 1},
-		{0x0589, 0x058a, 1},
-		{0x05be, 0x05c0, 2},
-		{0x05c3, 0x05c6, 3},
-		{0x05f3, 0x05f4, 1},
-		{0x0609, 0x060a, 1},
-		{0x060c, 0x060d, 1},
-		{0x061b, 0x061e, 3},
-		{0x061f, 0x066a, 75},
-		{0x066b, 0x066d, 1},
-		{0x06d4, 0x0700, 44},
-		{0x0701, 0x070d, 1},
-		{0x07f7, 0x07f9, 1},
-		{0x0830, 0x083e, 1},
-		{0x085e, 0x0964, 262},
-		{0x0965, 0x0970, 11},
-		{0x0df4, 0x0e4f, 91},
-		{0x0e5a, 0x0e5b, 1},
-		{0x0f04, 0x0f12, 1},
-		{0x0f3a, 0x0f3d, 1},
-		{0x0f85, 0x0fd0, 75},
-		{0x0fd1, 0x0fd4, 1},
-		{0x0fd9, 0x0fda, 1},
-		{0x104a, 0x104f, 1},
-		{0x10fb, 0x1361, 614},
-		{0x1362, 0x1368, 1},
-		{0x1400, 0x166d, 621},
-		{0x166e, 0x169b, 45},
-		{0x169c, 0x16eb, 79},
-		{0x16ec, 0x16ed, 1},
-		{0x1735, 0x1736, 1},
-		{0x17d4, 0x17d6, 1},
-		{0x17d8, 0x17da, 1},
-		{0x1800, 0x180a, 1},
-		{0x1944, 0x1945, 1},
-		{0x1a1e, 0x1a1f, 1},
-		{0x1aa0, 0x1aa6, 1},
-		{0x1aa8, 0x1aad, 1},
-		{0x1b5a, 0x1b60, 1},
-		{0x1bfc, 0x1bff, 1},
-		{0x1c3b, 0x1c3f, 1},
-		{0x1c7e, 0x1c7f, 1},
-		{0x1cd3, 0x2010, 829},
-		{0x2011, 0x2027, 1},
-		{0x2030, 0x2043, 1},
-		{0x2045, 0x2051, 1},
-		{0x2053, 0x205e, 1},
-		{0x207d, 0x207e, 1},
-		{0x208d, 0x208e, 1},
-		{0x2329, 0x232a, 1},
-		{0x2768, 0x2775, 1},
-		{0x27c5, 0x27c6, 1},
-		{0x27e6, 0x27ef, 1},
-		{0x2983, 0x2998, 1},
-		{0x29d8, 0x29db, 1},
-		{0x29fc, 0x29fd, 1},
-		{0x2cf9, 0x2cfc, 1},
-		{0x2cfe, 0x2cff, 1},
-		{0x2d70, 0x2e00, 144},
-		{0x2e01, 0x2e2e, 1},
-		{0x2e30, 0x2e31, 1},
-		{0x3001, 0x3003, 1},
-		{0x3008, 0x3011, 1},
-		{0x3014, 0x301f, 1},
-		{0x3030, 0x303d, 13},
-		{0x30a0, 0x30fb, 91},
-		{0xa4fe, 0xa4ff, 1},
-		{0xa60d, 0xa60f, 1},
-		{0xa673, 0xa67e, 11},
-		{0xa6f2, 0xa6f7, 1},
-		{0xa874, 0xa877, 1},
-		{0xa8ce, 0xa8cf, 1},
-		{0xa8f8, 0xa8fa, 1},
-		{0xa92e, 0xa92f, 1},
-		{0xa95f, 0xa9c1, 98},
-		{0xa9c2, 0xa9cd, 1},
-		{0xa9de, 0xa9df, 1},
-		{0xaa5c, 0xaa5f, 1},
-		{0xaade, 0xaadf, 1},
-		{0xabeb, 0xfd3e, 20819},
-		{0xfd3f, 0xfe10, 209},
-		{0xfe11, 0xfe19, 1},
-		{0xfe30, 0xfe52, 1},
-		{0xfe54, 0xfe61, 1},
-		{0xfe63, 0xfe68, 5},
-		{0xfe6a, 0xfe6b, 1},
-		{0xff01, 0xff03, 1},
-		{0xff05, 0xff0a, 1},
-		{0xff0c, 0xff0f, 1},
-		{0xff1a, 0xff1b, 1},
-		{0xff1f, 0xff20, 1},
-		{0xff3b, 0xff3d, 1},
-		{0xff3f, 0xff5b, 28},
-		{0xff5d, 0xff5f, 2},
-		{0xff60, 0xff65, 1},
-	},
-	R32: []Range32{
-		{0x10100, 0x10101, 1},
-		{0x1039f, 0x103d0, 49},
-		{0x10857, 0x1091f, 200},
-		{0x1093f, 0x10a50, 273},
-		{0x10a51, 0x10a58, 1},
-		{0x10a7f, 0x10b39, 186},
-		{0x10b3a, 0x10b3f, 1},
-		{0x11047, 0x1104d, 1},
-		{0x110bb, 0x110bc, 1},
-		{0x110be, 0x110c1, 1},
-		{0x12470, 0x12473, 1},
+		{0x02b0, 0x02c1, 1},
+		{0x02c6, 0x02d1, 1},
+		{0x02e0, 0x02e4, 1},
+		{0x02ec, 0x02ee, 2},
+		{0x0374, 0x037a, 6},
+		{0x0559, 0x0640, 231},
+		{0x06e5, 0x06e6, 1},
+		{0x07f4, 0x07f5, 1},
+		{0x07fa, 0x081a, 32},
+		{0x0824, 0x0828, 4},
+		{0x0971, 0x0e46, 1237},
+		{0x0ec6, 0x10fc, 566},
+		{0x17d7, 0x1843, 108},
+		{0x1aa7, 0x1c78, 465},
+		{0x1c79, 0x1c7d, 1},
+		{0x1d2c, 0x1d61, 1},
+		{0x1d78, 0x1d9b, 35},
+		{0x1d9c, 0x1dbf, 1},
+		{0x2071, 0x207f, 14},
+		{0x2090, 0x209c, 1},
+		{0x2c7d, 0x2d6f, 242},
+		{0x2e2f, 0x3005, 470},
+		{0x3031, 0x3035, 1},
+		{0x303b, 0x309d, 98},
+		{0x309e, 0x30fc, 94},
+		{0x30fd, 0x30fe, 1},
+		{0xa015, 0xa4f8, 1251},
+		{0xa4f9, 0xa4fd, 1},
+		{0xa60c, 0xa67f, 115},
+		{0xa717, 0xa71f, 1},
+		{0xa770, 0xa788, 24},
+		{0xa9cf, 0xaa70, 161},
+		{0xaadd, 0xff70, 21651},
+		{0xff9e, 0xff9f, 1},
 	},
 }
 
-var _S = &RangeTable{
-	R16: []Range16{
-		{0x0024, 0x002b, 7},
-		{0x003c, 0x003e, 1},
-		{0x005e, 0x0060, 2},
-		{0x007c, 0x007e, 2},
-		{0x00a2, 0x00a9, 1},
-		{0x00ac, 0x00ae, 2},
-		{0x00af, 0x00b1, 1},
-		{0x00b4, 0x00b8, 2},
-		{0x00d7, 0x00f7, 32},
-		{0x02c2, 0x02c5, 1},
-		{0x02d2, 0x02df, 1},
-		{0x02e5, 0x02eb, 1},
-		{0x02ed, 0x02ef, 2},
-		{0x02f0, 0x02ff, 1},
-		{0x0375, 0x0384, 15},
-		{0x0385, 0x03f6, 113},
-		{0x0482, 0x0606, 388},
-		{0x0607, 0x0608, 1},
-		{0x060b, 0x060e, 3},
-		{0x060f, 0x06de, 207},
-		{0x06e9, 0x06fd, 20},
-		{0x06fe, 0x07f6, 248},
-		{0x09f2, 0x09f3, 1},
-		{0x09fa, 0x09fb, 1},
-		{0x0af1, 0x0b70, 127},
-		{0x0bf3, 0x0bfa, 1},
-		{0x0c7f, 0x0d79, 250},
-		{0x0e3f, 0x0f01, 194},
-		{0x0f02, 0x0f03, 1},
-		{0x0f13, 0x0f17, 1},
-		{0x0f1a, 0x0f1f, 1},
-		{0x0f34, 0x0f38, 2},
-		{0x0fbe, 0x0fc5, 1},
-		{0x0fc7, 0x0fcc, 1},
-		{0x0fce, 0x0fcf, 1},
-		{0x0fd5, 0x0fd8, 1},
-		{0x109e, 0x109f, 1},
-		{0x1360, 0x1390, 48},
-		{0x1391, 0x1399, 1},
-		{0x17db, 0x1940, 357},
-		{0x19de, 0x19ff, 1},
-		{0x1b61, 0x1b6a, 1},
-		{0x1b74, 0x1b7c, 1},
-		{0x1fbd, 0x1fbf, 2},
-		{0x1fc0, 0x1fc1, 1},
-		{0x1fcd, 0x1fcf, 1},
-		{0x1fdd, 0x1fdf, 1},
-		{0x1fed, 0x1fef, 1},
-		{0x1ffd, 0x1ffe, 1},
-		{0x2044, 0x2052, 14},
-		{0x207a, 0x207c, 1},
-		{0x208a, 0x208c, 1},
-		{0x20a0, 0x20b9, 1},
-		{0x2100, 0x2101, 1},
-		{0x2103, 0x2106, 1},
-		{0x2108, 0x2109, 1},
-		{0x2114, 0x2116, 2},
-		{0x2117, 0x2118, 1},
-		{0x211e, 0x2123, 1},
-		{0x2125, 0x2129, 2},
-		{0x212e, 0x213a, 12},
-		{0x213b, 0x2140, 5},
-		{0x2141, 0x2144, 1},
-		{0x214a, 0x214d, 1},
-		{0x214f, 0x2190, 65},
-		{0x2191, 0x2328, 1},
-		{0x232b, 0x23f3, 1},
-		{0x2400, 0x2426, 1},
-		{0x2440, 0x244a, 1},
-		{0x249c, 0x24e9, 1},
-		{0x2500, 0x26ff, 1},
-		{0x2701, 0x2767, 1},
-		{0x2794, 0x27c4, 1},
-		{0x27c7, 0x27ca, 1},
-		{0x27cc, 0x27ce, 2},
-		{0x27cf, 0x27e5, 1},
-		{0x27f0, 0x2982, 1},
-		{0x2999, 0x29d7, 1},
-		{0x29dc, 0x29fb, 1},
-		{0x29fe, 0x2b4c, 1},
-		{0x2b50, 0x2b59, 1},
-		{0x2ce5, 0x2cea, 1},
-		{0x2e80, 0x2e99, 1},
-		{0x2e9b, 0x2ef3, 1},
-		{0x2f00, 0x2fd5, 1},
-		{0x2ff0, 0x2ffb, 1},
-		{0x3004, 0x3012, 14},
-		{0x3013, 0x3020, 13},
-		{0x3036, 0x3037, 1},
-		{0x303e, 0x303f, 1},
-		{0x309b, 0x309c, 1},
-		{0x3190, 0x3191, 1},
-		{0x3196, 0x319f, 1},
-		{0x31c0, 0x31e3, 1},
-		{0x3200, 0x321e, 1},
-		{0x322a, 0x3250, 1},
-		{0x3260, 0x327f, 1},
-		{0x328a, 0x32b0, 1},
-		{0x32c0, 0x32fe, 1},
-		{0x3300, 0x33ff, 1},
-		{0x4dc0, 0x4dff, 1},
-		{0xa490, 0xa4c6, 1},
-		{0xa700, 0xa716, 1},
-		{0xa720, 0xa721, 1},
-		{0xa789, 0xa78a, 1},
-		{0xa828, 0xa82b, 1},
-		{0xa836, 0xa839, 1},
-		{0xaa77, 0xaa79, 1},
-		{0xfb29, 0xfbb2, 137},
-		{0xfbb3, 0xfbc1, 1},
-		{0xfdfc, 0xfdfd, 1},
-		{0xfe62, 0xfe64, 2},
-		{0xfe65, 0xfe66, 1},
-		{0xfe69, 0xff04, 155},
-		{0xff0b, 0xff1c, 17},
-		{0xff1d, 0xff1e, 1},
-		{0xff3e, 0xff40, 2},
-		{0xff5c, 0xff5e, 2},
-		{0xffe0, 0xffe6, 1},
-		{0xffe8, 0xffee, 1},
-		{0xfffc, 0xfffd, 1},
-	},
-	R32: []Range32{
-		{0x10102, 0x10137, 53},
-		{0x10138, 0x1013f, 1},
-		{0x10179, 0x10189, 1},
-		{0x10190, 0x1019b, 1},
-		{0x101d0, 0x101fc, 1},
-		{0x1d000, 0x1d0f5, 1},
-		{0x1d100, 0x1d126, 1},
-		{0x1d129, 0x1d164, 1},
-		{0x1d16a, 0x1d16c, 1},
-		{0x1d183, 0x1d184, 1},
-		{0x1d18c, 0x1d1a9, 1},
-		{0x1d1ae, 0x1d1dd, 1},
-		{0x1d200, 0x1d241, 1},
-		{0x1d245, 0x1d300, 187},
-		{0x1d301, 0x1d356, 1},
-		{0x1d6c1, 0x1d6db, 26},
-		{0x1d6fb, 0x1d715, 26},
-		{0x1d735, 0x1d74f, 26},
-		{0x1d76f, 0x1d789, 26},
-		{0x1d7a9, 0x1d7c3, 26},
-		{0x1f000, 0x1f02b, 1},
-		{0x1f030, 0x1f093, 1},
-		{0x1f0a0, 0x1f0ae, 1},
-		{0x1f0b1, 0x1f0be, 1},
-		{0x1f0c1, 0x1f0cf, 1},
-		{0x1f0d1, 0x1f0df, 1},
-		{0x1f110, 0x1f12e, 1},
-		{0x1f130, 0x1f169, 1},
-		{0x1f170, 0x1f19a, 1},
-		{0x1f1e6, 0x1f202, 1},
-		{0x1f210, 0x1f23a, 1},
-		{0x1f240, 0x1f248, 1},
-		{0x1f250, 0x1f251, 1},
-		{0x1f300, 0x1f320, 1},
-		{0x1f330, 0x1f335, 1},
-		{0x1f337, 0x1f37c, 1},
-		{0x1f380, 0x1f393, 1},
-		{0x1f3a0, 0x1f3c4, 1},
-		{0x1f3c6, 0x1f3ca, 1},
-		{0x1f3e0, 0x1f3f0, 1},
-		{0x1f400, 0x1f43e, 1},
-		{0x1f440, 0x1f442, 2},
-		{0x1f443, 0x1f4f7, 1},
-		{0x1f4f9, 0x1f4fc, 1},
-		{0x1f500, 0x1f53d, 1},
-		{0x1f550, 0x1f567, 1},
-		{0x1f5fb, 0x1f5ff, 1},
-		{0x1f601, 0x1f610, 1},
-		{0x1f612, 0x1f614, 1},
-		{0x1f616, 0x1f61c, 2},
-		{0x1f61d, 0x1f61e, 1},
-		{0x1f620, 0x1f625, 1},
-		{0x1f628, 0x1f62b, 1},
-		{0x1f62d, 0x1f630, 3},
-		{0x1f631, 0x1f633, 1},
-		{0x1f635, 0x1f640, 1},
-		{0x1f645, 0x1f64f, 1},
-		{0x1f680, 0x1f6c5, 1},
-		{0x1f700, 0x1f773, 1},
-	},
-}
-
-var _Z = &RangeTable{
-	R16: []Range16{
-		{0x0020, 0x00a0, 128},
-		{0x1680, 0x180e, 398},
-		{0x2000, 0x200a, 1},
-		{0x2028, 0x2029, 1},
-		{0x202f, 0x205f, 48},
-		{0x3000, 0x3000, 1},
-	},
-}
-
-var _Me = &RangeTable{
-	R16: []Range16{
-		{0x0488, 0x0489, 1},
-		{0x20dd, 0x20e0, 1},
-		{0x20e2, 0x20e4, 1},
-		{0xa670, 0xa672, 1},
-	},
-}
-
-var _Mc = &RangeTable{
-	R16: []Range16{
-		{0x0903, 0x093b, 56},
-		{0x093e, 0x0940, 1},
-		{0x0949, 0x094c, 1},
-		{0x094e, 0x094f, 1},
-		{0x0982, 0x0983, 1},
-		{0x09be, 0x09c0, 1},
-		{0x09c7, 0x09c8, 1},
-		{0x09cb, 0x09cc, 1},
-		{0x09d7, 0x0a03, 44},
-		{0x0a3e, 0x0a40, 1},
-		{0x0a83, 0x0abe, 59},
-		{0x0abf, 0x0ac0, 1},
-		{0x0ac9, 0x0acb, 2},
-		{0x0acc, 0x0b02, 54},
-		{0x0b03, 0x0b3e, 59},
-		{0x0b40, 0x0b47, 7},
-		{0x0b48, 0x0b4b, 3},
-		{0x0b4c, 0x0b57, 11},
-		{0x0bbe, 0x0bbf, 1},
-		{0x0bc1, 0x0bc2, 1},
-		{0x0bc6, 0x0bc8, 1},
-		{0x0bca, 0x0bcc, 1},
-		{0x0bd7, 0x0c01, 42},
-		{0x0c02, 0x0c03, 1},
-		{0x0c41, 0x0c44, 1},
-		{0x0c82, 0x0c83, 1},
-		{0x0cbe, 0x0cc0, 2},
-		{0x0cc1, 0x0cc4, 1},
-		{0x0cc7, 0x0cc8, 1},
-		{0x0cca, 0x0ccb, 1},
-		{0x0cd5, 0x0cd6, 1},
-		{0x0d02, 0x0d03, 1},
-		{0x0d3e, 0x0d40, 1},
-		{0x0d46, 0x0d48, 1},
-		{0x0d4a, 0x0d4c, 1},
-		{0x0d57, 0x0d82, 43},
-		{0x0d83, 0x0dcf, 76},
-		{0x0dd0, 0x0dd1, 1},
-		{0x0dd8, 0x0ddf, 1},
-		{0x0df2, 0x0df3, 1},
-		{0x0f3e, 0x0f3f, 1},
-		{0x0f7f, 0x102b, 172},
-		{0x102c, 0x1031, 5},
-		{0x1038, 0x103b, 3},
-		{0x103c, 0x1056, 26},
-		{0x1057, 0x1062, 11},
-		{0x1063, 0x1064, 1},
-		{0x1067, 0x106d, 1},
-		{0x1083, 0x1084, 1},
-		{0x1087, 0x108c, 1},
-		{0x108f, 0x109a, 11},
-		{0x109b, 0x109c, 1},
-		{0x17b6, 0x17be, 8},
-		{0x17bf, 0x17c5, 1},
-		{0x17c7, 0x17c8, 1},
-		{0x1923, 0x1926, 1},
-		{0x1929, 0x192b, 1},
-		{0x1930, 0x1931, 1},
-		{0x1933, 0x1938, 1},
-		{0x19b0, 0x19c0, 1},
-		{0x19c8, 0x19c9, 1},
-		{0x1a19, 0x1a1b, 1},
-		{0x1a55, 0x1a57, 2},
-		{0x1a61, 0x1a63, 2},
-		{0x1a64, 0x1a6d, 9},
-		{0x1a6e, 0x1a72, 1},
-		{0x1b04, 0x1b35, 49},
-		{0x1b3b, 0x1b3d, 2},
-		{0x1b3e, 0x1b41, 1},
-		{0x1b43, 0x1b44, 1},
-		{0x1b82, 0x1ba1, 31},
-		{0x1ba6, 0x1ba7, 1},
-		{0x1baa, 0x1be7, 61},
-		{0x1bea, 0x1bec, 1},
-		{0x1bee, 0x1bf2, 4},
-		{0x1bf3, 0x1c24, 49},
-		{0x1c25, 0x1c2b, 1},
-		{0x1c34, 0x1c35, 1},
-		{0x1ce1, 0x1cf2, 17},
-		{0xa823, 0xa824, 1},
-		{0xa827, 0xa880, 89},
-		{0xa881, 0xa8b4, 51},
-		{0xa8b5, 0xa8c3, 1},
-		{0xa952, 0xa953, 1},
-		{0xa983, 0xa9b4, 49},
-		{0xa9b5, 0xa9ba, 5},
-		{0xa9bb, 0xa9bd, 2},
-		{0xa9be, 0xa9c0, 1},
-		{0xaa2f, 0xaa30, 1},
-		{0xaa33, 0xaa34, 1},
-		{0xaa4d, 0xaa7b, 46},
-		{0xabe3, 0xabe4, 1},
-		{0xabe6, 0xabe7, 1},
-		{0xabe9, 0xabea, 1},
-		{0xabec, 0xabec, 1},
-	},
-	R32: []Range32{
-		{0x11000, 0x11000, 1},
-		{0x11002, 0x11082, 128},
-		{0x110b0, 0x110b2, 1},
-		{0x110b7, 0x110b8, 1},
-		{0x1d165, 0x1d166, 1},
-		{0x1d16d, 0x1d172, 1},
-	},
-}
-
-var _Mn = &RangeTable{
-	R16: []Range16{
-		{0x0300, 0x036f, 1},
-		{0x0483, 0x0487, 1},
-		{0x0591, 0x05bd, 1},
-		{0x05bf, 0x05c1, 2},
-		{0x05c2, 0x05c4, 2},
-		{0x05c5, 0x05c7, 2},
-		{0x0610, 0x061a, 1},
-		{0x064b, 0x065f, 1},
-		{0x0670, 0x06d6, 102},
-		{0x06d7, 0x06dc, 1},
-		{0x06df, 0x06e4, 1},
-		{0x06e7, 0x06e8, 1},
-		{0x06ea, 0x06ed, 1},
-		{0x0711, 0x0730, 31},
-		{0x0731, 0x074a, 1},
-		{0x07a6, 0x07b0, 1},
-		{0x07eb, 0x07f3, 1},
-		{0x0816, 0x0819, 1},
-		{0x081b, 0x0823, 1},
-		{0x0825, 0x0827, 1},
-		{0x0829, 0x082d, 1},
-		{0x0859, 0x085b, 1},
-		{0x0900, 0x0902, 1},
-		{0x093a, 0x093c, 2},
-		{0x0941, 0x0948, 1},
-		{0x094d, 0x0951, 4},
-		{0x0952, 0x0957, 1},
-		{0x0962, 0x0963, 1},
-		{0x0981, 0x09bc, 59},
-		{0x09c1, 0x09c4, 1},
-		{0x09cd, 0x09e2, 21},
-		{0x09e3, 0x0a01, 30},
-		{0x0a02, 0x0a3c, 58},
-		{0x0a41, 0x0a42, 1},
-		{0x0a47, 0x0a48, 1},
-		{0x0a4b, 0x0a4d, 1},
-		{0x0a51, 0x0a70, 31},
-		{0x0a71, 0x0a75, 4},
-		{0x0a81, 0x0a82, 1},
-		{0x0abc, 0x0ac1, 5},
-		{0x0ac2, 0x0ac5, 1},
-		{0x0ac7, 0x0ac8, 1},
-		{0x0acd, 0x0ae2, 21},
-		{0x0ae3, 0x0b01, 30},
-		{0x0b3c, 0x0b3f, 3},
-		{0x0b41, 0x0b44, 1},
-		{0x0b4d, 0x0b56, 9},
-		{0x0b62, 0x0b63, 1},
-		{0x0b82, 0x0bc0, 62},
-		{0x0bcd, 0x0c3e, 113},
-		{0x0c3f, 0x0c40, 1},
-		{0x0c46, 0x0c48, 1},
-		{0x0c4a, 0x0c4d, 1},
-		{0x0c55, 0x0c56, 1},
-		{0x0c62, 0x0c63, 1},
-		{0x0cbc, 0x0cbf, 3},
-		{0x0cc6, 0x0ccc, 6},
-		{0x0ccd, 0x0ce2, 21},
-		{0x0ce3, 0x0d41, 94},
-		{0x0d42, 0x0d44, 1},
-		{0x0d4d, 0x0d62, 21},
-		{0x0d63, 0x0dca, 103},
-		{0x0dd2, 0x0dd4, 1},
-		{0x0dd6, 0x0e31, 91},
-		{0x0e34, 0x0e3a, 1},
-		{0x0e47, 0x0e4e, 1},
-		{0x0eb1, 0x0eb4, 3},
-		{0x0eb5, 0x0eb9, 1},
-		{0x0ebb, 0x0ebc, 1},
-		{0x0ec8, 0x0ecd, 1},
-		{0x0f18, 0x0f19, 1},
-		{0x0f35, 0x0f39, 2},
-		{0x0f71, 0x0f7e, 1},
-		{0x0f80, 0x0f84, 1},
-		{0x0f86, 0x0f87, 1},
-		{0x0f8d, 0x0f97, 1},
-		{0x0f99, 0x0fbc, 1},
-		{0x0fc6, 0x102d, 103},
-		{0x102e, 0x1030, 1},
-		{0x1032, 0x1037, 1},
-		{0x1039, 0x103a, 1},
-		{0x103d, 0x103e, 1},
-		{0x1058, 0x1059, 1},
-		{0x105e, 0x1060, 1},
-		{0x1071, 0x1074, 1},
-		{0x1082, 0x1085, 3},
-		{0x1086, 0x108d, 7},
-		{0x109d, 0x135d, 704},
-		{0x135e, 0x135f, 1},
-		{0x1712, 0x1714, 1},
-		{0x1732, 0x1734, 1},
-		{0x1752, 0x1753, 1},
-		{0x1772, 0x1773, 1},
-		{0x17b7, 0x17bd, 1},
-		{0x17c6, 0x17c9, 3},
-		{0x17ca, 0x17d3, 1},
-		{0x17dd, 0x180b, 46},
-		{0x180c, 0x180d, 1},
-		{0x18a9, 0x1920, 119},
-		{0x1921, 0x1922, 1},
-		{0x1927, 0x1928, 1},
-		{0x1932, 0x1939, 7},
-		{0x193a, 0x193b, 1},
-		{0x1a17, 0x1a18, 1},
-		{0x1a56, 0x1a58, 2},
-		{0x1a59, 0x1a5e, 1},
-		{0x1a60, 0x1a62, 2},
-		{0x1a65, 0x1a6c, 1},
-		{0x1a73, 0x1a7c, 1},
-		{0x1a7f, 0x1b00, 129},
-		{0x1b01, 0x1b03, 1},
-		{0x1b34, 0x1b36, 2},
-		{0x1b37, 0x1b3a, 1},
-		{0x1b3c, 0x1b42, 6},
-		{0x1b6b, 0x1b73, 1},
-		{0x1b80, 0x1b81, 1},
-		{0x1ba2, 0x1ba5, 1},
-		{0x1ba8, 0x1ba9, 1},
-		{0x1be6, 0x1be8, 2},
-		{0x1be9, 0x1bed, 4},
-		{0x1bef, 0x1bf1, 1},
-		{0x1c2c, 0x1c33, 1},
-		{0x1c36, 0x1c37, 1},
-		{0x1cd0, 0x1cd2, 1},
-		{0x1cd4, 0x1ce0, 1},
-		{0x1ce2, 0x1ce8, 1},
-		{0x1ced, 0x1dc0, 211},
-		{0x1dc1, 0x1de6, 1},
-		{0x1dfc, 0x1dff, 1},
-		{0x20d0, 0x20dc, 1},
-		{0x20e1, 0x20e5, 4},
-		{0x20e6, 0x20f0, 1},
-		{0x2cef, 0x2cf1, 1},
-		{0x2d7f, 0x2de0, 97},
-		{0x2de1, 0x2dff, 1},
-		{0x302a, 0x302f, 1},
-		{0x3099, 0x309a, 1},
-		{0xa66f, 0xa67c, 13},
-		{0xa67d, 0xa6f0, 115},
-		{0xa6f1, 0xa802, 273},
-		{0xa806, 0xa80b, 5},
-		{0xa825, 0xa826, 1},
-		{0xa8c4, 0xa8e0, 28},
-		{0xa8e1, 0xa8f1, 1},
-		{0xa926, 0xa92d, 1},
-		{0xa947, 0xa951, 1},
-		{0xa980, 0xa982, 1},
-		{0xa9b3, 0xa9b6, 3},
-		{0xa9b7, 0xa9b9, 1},
-		{0xa9bc, 0xaa29, 109},
-		{0xaa2a, 0xaa2e, 1},
-		{0xaa31, 0xaa32, 1},
-		{0xaa35, 0xaa36, 1},
-		{0xaa43, 0xaa4c, 9},
-		{0xaab0, 0xaab2, 2},
-		{0xaab3, 0xaab4, 1},
-		{0xaab7, 0xaab8, 1},
-		{0xaabe, 0xaabf, 1},
-		{0xaac1, 0xabe5, 292},
-		{0xabe8, 0xabed, 5},
-		{0xfb1e, 0xfe00, 738},
-		{0xfe01, 0xfe0f, 1},
-		{0xfe20, 0xfe26, 1},
-	},
-	R32: []Range32{
-		{0x101fd, 0x10a01, 2052},
-		{0x10a02, 0x10a03, 1},
-		{0x10a05, 0x10a06, 1},
-		{0x10a0c, 0x10a0f, 1},
-		{0x10a38, 0x10a3a, 1},
-		{0x10a3f, 0x11001, 1474},
-		{0x11038, 0x11046, 1},
-		{0x11080, 0x11081, 1},
-		{0x110b3, 0x110b6, 1},
-		{0x110b9, 0x110ba, 1},
-		{0x1d167, 0x1d169, 1},
-		{0x1d17b, 0x1d182, 1},
-		{0x1d185, 0x1d18b, 1},
-		{0x1d1aa, 0x1d1ad, 1},
-		{0x1d242, 0x1d244, 1},
-		{0xe0100, 0xe01ef, 1},
-	},
-}
-
-var _Zl = &RangeTable{
-	R16: []Range16{
-		{0x2028, 0x2028, 1},
-	},
-}
-
-var _Zp = &RangeTable{
-	R16: []Range16{
-		{0x2029, 0x2029, 1},
-	},
-}
-
-var _Zs = &RangeTable{
-	R16: []Range16{
-		{0x0020, 0x00a0, 128},
-		{0x1680, 0x180e, 398},
-		{0x2000, 0x200a, 1},
-		{0x202f, 0x205f, 48},
-		{0x3000, 0x3000, 1},
-	},
-}
-
-var _Cs = &RangeTable{
-	R16: []Range16{
-		{0xd800, 0xdfff, 1},
-	},
-}
-
-var _Co = &RangeTable{
-	R16: []Range16{
-		{0xe000, 0xf8ff, 1},
-	},
-	R32: []Range32{
-		{0xf0000, 0xffffd, 1},
-		{0x100000, 0x10fffd, 1},
-	},
-}
-
-var _Cf = &RangeTable{
-	R16: []Range16{
-		{0x00ad, 0x0600, 1363},
-		{0x0601, 0x0603, 1},
-		{0x06dd, 0x070f, 50},
-		{0x17b4, 0x17b5, 1},
-		{0x200b, 0x200f, 1},
-		{0x202a, 0x202e, 1},
-		{0x2060, 0x2064, 1},
-		{0x206a, 0x206f, 1},
-		{0xfeff, 0xfff9, 250},
-		{0xfffa, 0xfffb, 1},
-	},
-	R32: []Range32{
-		{0x110bd, 0x1d173, 49334},
-		{0x1d174, 0x1d17a, 1},
-		{0xe0001, 0xe0020, 31},
-		{0xe0021, 0xe007f, 1},
-	},
-}
-
-var _Cc = &RangeTable{
-	R16: []Range16{
-		{0x0001, 0x001f, 1},
-		{0x007f, 0x009f, 1},
-	},
-}
-
-var _Po = &RangeTable{
-	R16: []Range16{
-		{0x0021, 0x0023, 1},
-		{0x0025, 0x0027, 1},
-		{0x002a, 0x002e, 2},
-		{0x002f, 0x003a, 11},
-		{0x003b, 0x003f, 4},
-		{0x0040, 0x005c, 28},
-		{0x00a1, 0x00b7, 22},
-		{0x00bf, 0x037e, 703},
-		{0x0387, 0x055a, 467},
-		{0x055b, 0x055f, 1},
-		{0x0589, 0x05c0, 55},
-		{0x05c3, 0x05c6, 3},
-		{0x05f3, 0x05f4, 1},
-		{0x0609, 0x060a, 1},
-		{0x060c, 0x060d, 1},
-		{0x061b, 0x061e, 3},
-		{0x061f, 0x066a, 75},
-		{0x066b, 0x066d, 1},
-		{0x06d4, 0x0700, 44},
-		{0x0701, 0x070d, 1},
-		{0x07f7, 0x07f9, 1},
-		{0x0830, 0x083e, 1},
-		{0x085e, 0x0964, 262},
-		{0x0965, 0x0970, 11},
-		{0x0df4, 0x0e4f, 91},
-		{0x0e5a, 0x0e5b, 1},
-		{0x0f04, 0x0f12, 1},
-		{0x0f85, 0x0fd0, 75},
-		{0x0fd1, 0x0fd4, 1},
-		{0x0fd9, 0x0fda, 1},
-		{0x104a, 0x104f, 1},
-		{0x10fb, 0x1361, 614},
-		{0x1362, 0x1368, 1},
-		{0x166d, 0x166e, 1},
-		{0x16eb, 0x16ed, 1},
-		{0x1735, 0x1736, 1},
-		{0x17d4, 0x17d6, 1},
-		{0x17d8, 0x17da, 1},
-		{0x1800, 0x1805, 1},
-		{0x1807, 0x180a, 1},
-		{0x1944, 0x1945, 1},
-		{0x1a1e, 0x1a1f, 1},
-		{0x1aa0, 0x1aa6, 1},
-		{0x1aa8, 0x1aad, 1},
-		{0x1b5a, 0x1b60, 1},
-		{0x1bfc, 0x1bff, 1},
-		{0x1c3b, 0x1c3f, 1},
-		{0x1c7e, 0x1c7f, 1},
-		{0x1cd3, 0x2016, 835},
-		{0x2017, 0x2020, 9},
-		{0x2021, 0x2027, 1},
-		{0x2030, 0x2038, 1},
-		{0x203b, 0x203e, 1},
-		{0x2041, 0x2043, 1},
-		{0x2047, 0x2051, 1},
-		{0x2053, 0x2055, 2},
-		{0x2056, 0x205e, 1},
-		{0x2cf9, 0x2cfc, 1},
-		{0x2cfe, 0x2cff, 1},
-		{0x2d70, 0x2e00, 144},
-		{0x2e01, 0x2e06, 5},
-		{0x2e07, 0x2e08, 1},
-		{0x2e0b, 0x2e0e, 3},
-		{0x2e0f, 0x2e16, 1},
-		{0x2e18, 0x2e19, 1},
-		{0x2e1b, 0x2e1e, 3},
-		{0x2e1f, 0x2e2a, 11},
-		{0x2e2b, 0x2e2e, 1},
-		{0x2e30, 0x2e31, 1},
-		{0x3001, 0x3003, 1},
-		{0x303d, 0x30fb, 190},
-		{0xa4fe, 0xa4ff, 1},
-		{0xa60d, 0xa60f, 1},
-		{0xa673, 0xa67e, 11},
-		{0xa6f2, 0xa6f7, 1},
-		{0xa874, 0xa877, 1},
-		{0xa8ce, 0xa8cf, 1},
-		{0xa8f8, 0xa8fa, 1},
-		{0xa92e, 0xa92f, 1},
-		{0xa95f, 0xa9c1, 98},
-		{0xa9c2, 0xa9cd, 1},
-		{0xa9de, 0xa9df, 1},
-		{0xaa5c, 0xaa5f, 1},
-		{0xaade, 0xaadf, 1},
-		{0xabeb, 0xfe10, 21029},
-		{0xfe11, 0xfe16, 1},
-		{0xfe19, 0xfe30, 23},
-		{0xfe45, 0xfe46, 1},
-		{0xfe49, 0xfe4c, 1},
-		{0xfe50, 0xfe52, 1},
-		{0xfe54, 0xfe57, 1},
-		{0xfe5f, 0xfe61, 1},
-		{0xfe68, 0xfe6a, 2},
-		{0xfe6b, 0xff01, 150},
-		{0xff02, 0xff03, 1},
-		{0xff05, 0xff07, 1},
-		{0xff0a, 0xff0e, 2},
-		{0xff0f, 0xff1a, 11},
-		{0xff1b, 0xff1f, 4},
-		{0xff20, 0xff3c, 28},
-		{0xff61, 0xff64, 3},
-		{0xff65, 0xff65, 1},
-	},
-	R32: []Range32{
-		{0x10100, 0x10100, 1},
-		{0x10101, 0x1039f, 670},
-		{0x103d0, 0x10857, 1159},
-		{0x1091f, 0x1093f, 32},
-		{0x10a50, 0x10a58, 1},
-		{0x10a7f, 0x10b39, 186},
-		{0x10b3a, 0x10b3f, 1},
-		{0x11047, 0x1104d, 1},
-		{0x110bb, 0x110bc, 1},
-		{0x110be, 0x110c1, 1},
-		{0x12470, 0x12473, 1},
-	},
-}
-
-var _Pi = &RangeTable{
-	R16: []Range16{
-		{0x00ab, 0x2018, 8045},
-		{0x201b, 0x201c, 1},
-		{0x201f, 0x2039, 26},
-		{0x2e02, 0x2e04, 2},
-		{0x2e09, 0x2e0c, 3},
-		{0x2e1c, 0x2e20, 4},
-	},
-}
-
-var _Pf = &RangeTable{
-	R16: []Range16{
-		{0x00bb, 0x2019, 8030},
-		{0x201d, 0x203a, 29},
-		{0x2e03, 0x2e05, 2},
-		{0x2e0a, 0x2e0d, 3},
-		{0x2e1d, 0x2e21, 4},
-	},
-}
-
-var _Pe = &RangeTable{
-	R16: []Range16{
-		{0x0029, 0x005d, 52},
-		{0x007d, 0x0f3b, 3774},
-		{0x0f3d, 0x169c, 1887},
-		{0x2046, 0x207e, 56},
-		{0x208e, 0x232a, 668},
-		{0x2769, 0x2775, 2},
-		{0x27c6, 0x27e7, 33},
-		{0x27e9, 0x27ef, 2},
-		{0x2984, 0x2998, 2},
-		{0x29d9, 0x29db, 2},
-		{0x29fd, 0x2e23, 1062},
-		{0x2e25, 0x2e29, 2},
-		{0x3009, 0x3011, 2},
-		{0x3015, 0x301b, 2},
-		{0x301e, 0x301f, 1},
-		{0xfd3f, 0xfe18, 217},
-		{0xfe36, 0xfe44, 2},
-		{0xfe48, 0xfe5a, 18},
-		{0xfe5c, 0xfe5e, 2},
-		{0xff09, 0xff3d, 52},
-		{0xff5d, 0xff63, 3},
-	},
-}
-
-var _Pd = &RangeTable{
-	R16: []Range16{
-		{0x002d, 0x058a, 1373},
-		{0x05be, 0x1400, 3650},
-		{0x1806, 0x2010, 2058},
-		{0x2011, 0x2015, 1},
-		{0x2e17, 0x2e1a, 3},
-		{0x301c, 0x3030, 20},
-		{0x30a0, 0xfe31, 52625},
-		{0xfe32, 0xfe58, 38},
-		{0xfe63, 0xff0d, 170},
-	},
-}
-
-var _Pc = &RangeTable{
-	R16: []Range16{
-		{0x005f, 0x203f, 8160},
-		{0x2040, 0x2054, 20},
-		{0xfe33, 0xfe34, 1},
-		{0xfe4d, 0xfe4f, 1},
-		{0xff3f, 0xff3f, 1},
-	},
-}
-
-var _Ps = &RangeTable{
-	R16: []Range16{
-		{0x0028, 0x005b, 51},
-		{0x007b, 0x0f3a, 3775},
-		{0x0f3c, 0x169b, 1887},
-		{0x201a, 0x201e, 4},
-		{0x2045, 0x207d, 56},
-		{0x208d, 0x2329, 668},
-		{0x2768, 0x2774, 2},
-		{0x27c5, 0x27e6, 33},
-		{0x27e8, 0x27ee, 2},
-		{0x2983, 0x2997, 2},
-		{0x29d8, 0x29da, 2},
-		{0x29fc, 0x2e22, 1062},
-		{0x2e24, 0x2e28, 2},
-		{0x3008, 0x3010, 2},
-		{0x3014, 0x301a, 2},
-		{0x301d, 0xfd3e, 52513},
-		{0xfe17, 0xfe35, 30},
-		{0xfe37, 0xfe43, 2},
-		{0xfe47, 0xfe59, 18},
-		{0xfe5b, 0xfe5d, 2},
-		{0xff08, 0xff3b, 51},
-		{0xff5b, 0xff5f, 4},
-		{0xff62, 0xff62, 1},
-	},
-}
-
-var _Nd = &RangeTable{
-	R16: []Range16{
-		{0x0030, 0x0039, 1},
-		{0x0660, 0x0669, 1},
-		{0x06f0, 0x06f9, 1},
-		{0x07c0, 0x07c9, 1},
-		{0x0966, 0x096f, 1},
-		{0x09e6, 0x09ef, 1},
-		{0x0a66, 0x0a6f, 1},
-		{0x0ae6, 0x0aef, 1},
-		{0x0b66, 0x0b6f, 1},
-		{0x0be6, 0x0bef, 1},
-		{0x0c66, 0x0c6f, 1},
-		{0x0ce6, 0x0cef, 1},
-		{0x0d66, 0x0d6f, 1},
-		{0x0e50, 0x0e59, 1},
-		{0x0ed0, 0x0ed9, 1},
-		{0x0f20, 0x0f29, 1},
-		{0x1040, 0x1049, 1},
-		{0x1090, 0x1099, 1},
-		{0x17e0, 0x17e9, 1},
-		{0x1810, 0x1819, 1},
-		{0x1946, 0x194f, 1},
-		{0x19d0, 0x19d9, 1},
-		{0x1a80, 0x1a89, 1},
-		{0x1a90, 0x1a99, 1},
-		{0x1b50, 0x1b59, 1},
-		{0x1bb0, 0x1bb9, 1},
-		{0x1c40, 0x1c49, 1},
-		{0x1c50, 0x1c59, 1},
-		{0xa620, 0xa629, 1},
-		{0xa8d0, 0xa8d9, 1},
-		{0xa900, 0xa909, 1},
-		{0xa9d0, 0xa9d9, 1},
-		{0xaa50, 0xaa59, 1},
-		{0xabf0, 0xabf9, 1},
-		{0xff10, 0xff19, 1},
-	},
-	R32: []Range32{
-		{0x104a0, 0x104a9, 1},
-		{0x11066, 0x1106f, 1},
-		{0x1d7ce, 0x1d7ff, 1},
-	},
-}
-
-var _Nl = &RangeTable{
-	R16: []Range16{
-		{0x16ee, 0x16f0, 1},
-		{0x2160, 0x2182, 1},
-		{0x2185, 0x2188, 1},
-		{0x3007, 0x3021, 26},
-		{0x3022, 0x3029, 1},
-		{0x3038, 0x303a, 1},
-		{0xa6e6, 0xa6ef, 1},
-	},
-	R32: []Range32{
-		{0x10140, 0x10174, 1},
-		{0x10341, 0x1034a, 9},
-		{0x103d1, 0x103d5, 1},
-		{0x12400, 0x12462, 1},
-	},
-}
-
-var _No = &RangeTable{
-	R16: []Range16{
-		{0x00b2, 0x00b3, 1},
-		{0x00b9, 0x00bc, 3},
-		{0x00bd, 0x00be, 1},
-		{0x09f4, 0x09f9, 1},
-		{0x0b72, 0x0b77, 1},
-		{0x0bf0, 0x0bf2, 1},
-		{0x0c78, 0x0c7e, 1},
-		{0x0d70, 0x0d75, 1},
-		{0x0f2a, 0x0f33, 1},
-		{0x1369, 0x137c, 1},
-		{0x17f0, 0x17f9, 1},
-		{0x19da, 0x2070, 1686},
-		{0x2074, 0x2079, 1},
-		{0x2080, 0x2089, 1},
-		{0x2150, 0x215f, 1},
-		{0x2189, 0x2460, 727},
-		{0x2461, 0x249b, 1},
-		{0x24ea, 0x24ff, 1},
-		{0x2776, 0x2793, 1},
-		{0x2cfd, 0x3192, 1173},
-		{0x3193, 0x3195, 1},
-		{0x3220, 0x3229, 1},
-		{0x3251, 0x325f, 1},
-		{0x3280, 0x3289, 1},
-		{0x32b1, 0x32bf, 1},
-		{0xa830, 0xa835, 1},
-	},
-	R32: []Range32{
-		{0x10107, 0x10133, 1},
-		{0x10175, 0x10178, 1},
-		{0x1018a, 0x10320, 406},
-		{0x10321, 0x10323, 1},
-		{0x10858, 0x1085f, 1},
-		{0x10916, 0x1091b, 1},
-		{0x10a40, 0x10a47, 1},
-		{0x10a7d, 0x10a7e, 1},
-		{0x10b58, 0x10b5f, 1},
-		{0x10b78, 0x10b7f, 1},
-		{0x10e60, 0x10e7e, 1},
-		{0x11052, 0x11065, 1},
-		{0x1d360, 0x1d371, 1},
-		{0x1f100, 0x1f10a, 1},
-	},
-}
-
-var _So = &RangeTable{
-	R16: []Range16{
-		{0x00a6, 0x00a7, 1},
-		{0x00a9, 0x00ae, 5},
-		{0x00b0, 0x00b6, 6},
-		{0x0482, 0x060e, 396},
-		{0x060f, 0x06de, 207},
-		{0x06e9, 0x06fd, 20},
-		{0x06fe, 0x07f6, 248},
-		{0x09fa, 0x0b70, 374},
-		{0x0bf3, 0x0bf8, 1},
-		{0x0bfa, 0x0c7f, 133},
-		{0x0d79, 0x0f01, 392},
-		{0x0f02, 0x0f03, 1},
-		{0x0f13, 0x0f17, 1},
-		{0x0f1a, 0x0f1f, 1},
-		{0x0f34, 0x0f38, 2},
-		{0x0fbe, 0x0fc5, 1},
-		{0x0fc7, 0x0fcc, 1},
-		{0x0fce, 0x0fcf, 1},
-		{0x0fd5, 0x0fd8, 1},
-		{0x109e, 0x109f, 1},
-		{0x1360, 0x1390, 48},
-		{0x1391, 0x1399, 1},
-		{0x1940, 0x19de, 158},
-		{0x19df, 0x19ff, 1},
-		{0x1b61, 0x1b6a, 1},
-		{0x1b74, 0x1b7c, 1},
-		{0x2100, 0x2101, 1},
-		{0x2103, 0x2106, 1},
-		{0x2108, 0x2109, 1},
-		{0x2114, 0x2116, 2},
-		{0x2117, 0x211e, 7},
-		{0x211f, 0x2123, 1},
-		{0x2125, 0x2129, 2},
-		{0x212e, 0x213a, 12},
-		{0x213b, 0x214a, 15},
-		{0x214c, 0x214d, 1},
-		{0x214f, 0x2195, 70},
-		{0x2196, 0x2199, 1},
-		{0x219c, 0x219f, 1},
-		{0x21a1, 0x21a2, 1},
-		{0x21a4, 0x21a5, 1},
-		{0x21a7, 0x21ad, 1},
-		{0x21af, 0x21cd, 1},
-		{0x21d0, 0x21d1, 1},
-		{0x21d3, 0x21d5, 2},
-		{0x21d6, 0x21f3, 1},
-		{0x2300, 0x2307, 1},
-		{0x230c, 0x231f, 1},
-		{0x2322, 0x2328, 1},
-		{0x232b, 0x237b, 1},
-		{0x237d, 0x239a, 1},
-		{0x23b4, 0x23db, 1},
-		{0x23e2, 0x23f3, 1},
-		{0x2400, 0x2426, 1},
-		{0x2440, 0x244a, 1},
-		{0x249c, 0x24e9, 1},
-		{0x2500, 0x25b6, 1},
-		{0x25b8, 0x25c0, 1},
-		{0x25c2, 0x25f7, 1},
-		{0x2600, 0x266e, 1},
-		{0x2670, 0x26ff, 1},
-		{0x2701, 0x2767, 1},
-		{0x2794, 0x27bf, 1},
-		{0x2800, 0x28ff, 1},
-		{0x2b00, 0x2b2f, 1},
-		{0x2b45, 0x2b46, 1},
-		{0x2b50, 0x2b59, 1},
-		{0x2ce5, 0x2cea, 1},
-		{0x2e80, 0x2e99, 1},
-		{0x2e9b, 0x2ef3, 1},
-		{0x2f00, 0x2fd5, 1},
-		{0x2ff0, 0x2ffb, 1},
-		{0x3004, 0x3012, 14},
-		{0x3013, 0x3020, 13},
-		{0x3036, 0x3037, 1},
-		{0x303e, 0x303f, 1},
-		{0x3190, 0x3191, 1},
-		{0x3196, 0x319f, 1},
-		{0x31c0, 0x31e3, 1},
-		{0x3200, 0x321e, 1},
-		{0x322a, 0x3250, 1},
-		{0x3260, 0x327f, 1},
-		{0x328a, 0x32b0, 1},
-		{0x32c0, 0x32fe, 1},
-		{0x3300, 0x33ff, 1},
-		{0x4dc0, 0x4dff, 1},
-		{0xa490, 0xa4c6, 1},
-		{0xa828, 0xa82b, 1},
-		{0xa836, 0xa837, 1},
-		{0xa839, 0xaa77, 574},
-		{0xaa78, 0xaa79, 1},
-		{0xfdfd, 0xffe4, 487},
-		{0xffe8, 0xffed, 5},
-		{0xffee, 0xfffc, 14},
-		{0xfffd, 0xfffd, 1},
-	},
-	R32: []Range32{
-		{0x10102, 0x10102, 1},
-		{0x10137, 0x1013f, 1},
-		{0x10179, 0x10189, 1},
-		{0x10190, 0x1019b, 1},
-		{0x101d0, 0x101fc, 1},
-		{0x1d000, 0x1d0f5, 1},
-		{0x1d100, 0x1d126, 1},
-		{0x1d129, 0x1d164, 1},
-		{0x1d16a, 0x1d16c, 1},
-		{0x1d183, 0x1d184, 1},
-		{0x1d18c, 0x1d1a9, 1},
-		{0x1d1ae, 0x1d1dd, 1},
-		{0x1d200, 0x1d241, 1},
-		{0x1d245, 0x1d300, 187},
-		{0x1d301, 0x1d356, 1},
-		{0x1f000, 0x1f02b, 1},
-		{0x1f030, 0x1f093, 1},
-		{0x1f0a0, 0x1f0ae, 1},
-		{0x1f0b1, 0x1f0be, 1},
-		{0x1f0c1, 0x1f0cf, 1},
-		{0x1f0d1, 0x1f0df, 1},
-		{0x1f110, 0x1f12e, 1},
-		{0x1f130, 0x1f169, 1},
-		{0x1f170, 0x1f19a, 1},
-		{0x1f1e6, 0x1f202, 1},
-		{0x1f210, 0x1f23a, 1},
-		{0x1f240, 0x1f248, 1},
-		{0x1f250, 0x1f251, 1},
-		{0x1f300, 0x1f320, 1},
-		{0x1f330, 0x1f335, 1},
-		{0x1f337, 0x1f37c, 1},
-		{0x1f380, 0x1f393, 1},
-		{0x1f3a0, 0x1f3c4, 1},
-		{0x1f3c6, 0x1f3ca, 1},
-		{0x1f3e0, 0x1f3f0, 1},
-		{0x1f400, 0x1f43e, 1},
-		{0x1f440, 0x1f442, 2},
-		{0x1f443, 0x1f4f7, 1},
-		{0x1f4f9, 0x1f4fc, 1},
-		{0x1f500, 0x1f53d, 1},
-		{0x1f550, 0x1f567, 1},
-		{0x1f5fb, 0x1f5ff, 1},
-		{0x1f601, 0x1f610, 1},
-		{0x1f612, 0x1f614, 1},
-		{0x1f616, 0x1f61c, 2},
-		{0x1f61d, 0x1f61e, 1},
-		{0x1f620, 0x1f625, 1},
-		{0x1f628, 0x1f62b, 1},
-		{0x1f62d, 0x1f630, 3},
-		{0x1f631, 0x1f633, 1},
-		{0x1f635, 0x1f640, 1},
-		{0x1f645, 0x1f64f, 1},
-		{0x1f680, 0x1f6c5, 1},
-		{0x1f700, 0x1f773, 1},
-	},
-}
-
-var _Sm = &RangeTable{
-	R16: []Range16{
-		{0x002b, 0x003c, 17},
-		{0x003d, 0x003e, 1},
-		{0x007c, 0x007e, 2},
-		{0x00ac, 0x00b1, 5},
-		{0x00d7, 0x00f7, 32},
-		{0x03f6, 0x0606, 528},
-		{0x0607, 0x0608, 1},
-		{0x2044, 0x2052, 14},
-		{0x207a, 0x207c, 1},
-		{0x208a, 0x208c, 1},
-		{0x2118, 0x2140, 40},
-		{0x2141, 0x2144, 1},
-		{0x214b, 0x2190, 69},
-		{0x2191, 0x2194, 1},
-		{0x219a, 0x219b, 1},
-		{0x21a0, 0x21a6, 3},
-		{0x21ae, 0x21ce, 32},
-		{0x21cf, 0x21d2, 3},
-		{0x21d4, 0x21f4, 32},
-		{0x21f5, 0x22ff, 1},
-		{0x2308, 0x230b, 1},
-		{0x2320, 0x2321, 1},
-		{0x237c, 0x239b, 31},
-		{0x239c, 0x23b3, 1},
-		{0x23dc, 0x23e1, 1},
-		{0x25b7, 0x25c1, 10},
-		{0x25f8, 0x25ff, 1},
-		{0x266f, 0x27c0, 337},
-		{0x27c1, 0x27c4, 1},
-		{0x27c7, 0x27ca, 1},
-		{0x27cc, 0x27ce, 2},
-		{0x27cf, 0x27e5, 1},
-		{0x27f0, 0x27ff, 1},
-		{0x2900, 0x2982, 1},
-		{0x2999, 0x29d7, 1},
-		{0x29dc, 0x29fb, 1},
-		{0x29fe, 0x2aff, 1},
-		{0x2b30, 0x2b44, 1},
-		{0x2b47, 0x2b4c, 1},
-		{0xfb29, 0xfe62, 825},
-		{0xfe64, 0xfe66, 1},
-		{0xff0b, 0xff1c, 17},
-		{0xff1d, 0xff1e, 1},
-		{0xff5c, 0xff5e, 2},
-		{0xffe2, 0xffe9, 7},
-		{0xffea, 0xffec, 1},
-	},
-	R32: []Range32{
-		{0x1d6c1, 0x1d6db, 26},
-		{0x1d6fb, 0x1d715, 26},
-		{0x1d735, 0x1d74f, 26},
-		{0x1d76f, 0x1d789, 26},
-		{0x1d7a9, 0x1d7c3, 26},
-	},
-}
-
-var _Sk = &RangeTable{
-	R16: []Range16{
-		{0x005e, 0x0060, 2},
-		{0x00a8, 0x00af, 7},
-		{0x00b4, 0x00b8, 4},
-		{0x02c2, 0x02c5, 1},
-		{0x02d2, 0x02df, 1},
-		{0x02e5, 0x02eb, 1},
-		{0x02ed, 0x02ef, 2},
-		{0x02f0, 0x02ff, 1},
-		{0x0375, 0x0384, 15},
-		{0x0385, 0x1fbd, 7224},
-		{0x1fbf, 0x1fc1, 1},
-		{0x1fcd, 0x1fcf, 1},
-		{0x1fdd, 0x1fdf, 1},
-		{0x1fed, 0x1fef, 1},
-		{0x1ffd, 0x1ffe, 1},
-		{0x309b, 0x309c, 1},
-		{0xa700, 0xa716, 1},
-		{0xa720, 0xa721, 1},
-		{0xa789, 0xa78a, 1},
-		{0xfbb2, 0xfbc1, 1},
-		{0xff3e, 0xff40, 2},
-		{0xffe3, 0xffe3, 1},
-	},
-}
-
-var _Sc = &RangeTable{
-	R16: []Range16{
-		{0x0024, 0x00a2, 126},
-		{0x00a3, 0x00a5, 1},
-		{0x060b, 0x09f2, 999},
-		{0x09f3, 0x09fb, 8},
-		{0x0af1, 0x0bf9, 264},
-		{0x0e3f, 0x17db, 2460},
-		{0x20a0, 0x20b9, 1},
-		{0xa838, 0xfdfc, 21956},
-		{0xfe69, 0xff04, 155},
-		{0xffe0, 0xffe1, 1},
-		{0xffe5, 0xffe6, 1},
-	},
-}
-
-var _Lu = &RangeTable{
-	R16: []Range16{
-		{0x0041, 0x005a, 1},
-		{0x00c0, 0x00d6, 1},
-		{0x00d8, 0x00de, 1},
-		{0x0100, 0x0136, 2},
-		{0x0139, 0x0147, 2},
-		{0x014a, 0x0178, 2},
-		{0x0179, 0x017d, 2},
-		{0x0181, 0x0182, 1},
-		{0x0184, 0x0186, 2},
-		{0x0187, 0x0189, 2},
-		{0x018a, 0x018b, 1},
-		{0x018e, 0x0191, 1},
-		{0x0193, 0x0194, 1},
-		{0x0196, 0x0198, 1},
-		{0x019c, 0x019d, 1},
-		{0x019f, 0x01a0, 1},
-		{0x01a2, 0x01a6, 2},
-		{0x01a7, 0x01a9, 2},
-		{0x01ac, 0x01ae, 2},
-		{0x01af, 0x01b1, 2},
-		{0x01b2, 0x01b3, 1},
-		{0x01b5, 0x01b7, 2},
-		{0x01b8, 0x01bc, 4},
-		{0x01c4, 0x01cd, 3},
-		{0x01cf, 0x01db, 2},
-		{0x01de, 0x01ee, 2},
-		{0x01f1, 0x01f4, 3},
-		{0x01f6, 0x01f8, 1},
-		{0x01fa, 0x0232, 2},
-		{0x023a, 0x023b, 1},
-		{0x023d, 0x023e, 1},
-		{0x0241, 0x0243, 2},
-		{0x0244, 0x0246, 1},
-		{0x0248, 0x024e, 2},
-		{0x0370, 0x0372, 2},
-		{0x0376, 0x0386, 16},
-		{0x0388, 0x038a, 1},
-		{0x038c, 0x038e, 2},
-		{0x038f, 0x0391, 2},
-		{0x0392, 0x03a1, 1},
-		{0x03a3, 0x03ab, 1},
-		{0x03cf, 0x03d2, 3},
-		{0x03d3, 0x03d4, 1},
-		{0x03d8, 0x03ee, 2},
-		{0x03f4, 0x03f7, 3},
-		{0x03f9, 0x03fa, 1},
-		{0x03fd, 0x042f, 1},
-		{0x0460, 0x0480, 2},
-		{0x048a, 0x04c0, 2},
-		{0x04c1, 0x04cd, 2},
-		{0x04d0, 0x0526, 2},
-		{0x0531, 0x0556, 1},
-		{0x10a0, 0x10c5, 1},
-		{0x1e00, 0x1e94, 2},
-		{0x1e9e, 0x1efe, 2},
-		{0x1f08, 0x1f0f, 1},
-		{0x1f18, 0x1f1d, 1},
-		{0x1f28, 0x1f2f, 1},
-		{0x1f38, 0x1f3f, 1},
-		{0x1f48, 0x1f4d, 1},
-		{0x1f59, 0x1f5f, 2},
-		{0x1f68, 0x1f6f, 1},
-		{0x1fb8, 0x1fbb, 1},
-		{0x1fc8, 0x1fcb, 1},
-		{0x1fd8, 0x1fdb, 1},
-		{0x1fe8, 0x1fec, 1},
-		{0x1ff8, 0x1ffb, 1},
-		{0x2102, 0x2107, 5},
-		{0x210b, 0x210d, 1},
-		{0x2110, 0x2112, 1},
-		{0x2115, 0x2119, 4},
-		{0x211a, 0x211d, 1},
-		{0x2124, 0x212a, 2},
-		{0x212b, 0x212d, 1},
-		{0x2130, 0x2133, 1},
-		{0x213e, 0x213f, 1},
-		{0x2145, 0x2183, 62},
-		{0x2c00, 0x2c2e, 1},
-		{0x2c60, 0x2c62, 2},
-		{0x2c63, 0x2c64, 1},
-		{0x2c67, 0x2c6d, 2},
-		{0x2c6e, 0x2c70, 1},
-		{0x2c72, 0x2c75, 3},
-		{0x2c7e, 0x2c80, 1},
-		{0x2c82, 0x2ce2, 2},
-		{0x2ceb, 0x2ced, 2},
-		{0xa640, 0xa66c, 2},
-		{0xa680, 0xa696, 2},
-		{0xa722, 0xa72e, 2},
-		{0xa732, 0xa76e, 2},
-		{0xa779, 0xa77d, 2},
-		{0xa77e, 0xa786, 2},
-		{0xa78b, 0xa78d, 2},
-		{0xa790, 0xa7a0, 16},
-		{0xa7a2, 0xa7a8, 2},
-		{0xff21, 0xff3a, 1},
-	},
-	R32: []Range32{
-		{0x10400, 0x10427, 1},
-		{0x1d400, 0x1d419, 1},
-		{0x1d434, 0x1d44d, 1},
-		{0x1d468, 0x1d481, 1},
-		{0x1d49c, 0x1d49e, 2},
-		{0x1d49f, 0x1d4a5, 3},
-		{0x1d4a6, 0x1d4a9, 3},
-		{0x1d4aa, 0x1d4ac, 1},
-		{0x1d4ae, 0x1d4b5, 1},
-		{0x1d4d0, 0x1d4e9, 1},
-		{0x1d504, 0x1d505, 1},
-		{0x1d507, 0x1d50a, 1},
-		{0x1d50d, 0x1d514, 1},
-		{0x1d516, 0x1d51c, 1},
-		{0x1d538, 0x1d539, 1},
-		{0x1d53b, 0x1d53e, 1},
-		{0x1d540, 0x1d544, 1},
-		{0x1d546, 0x1d54a, 4},
-		{0x1d54b, 0x1d550, 1},
-		{0x1d56c, 0x1d585, 1},
-		{0x1d5a0, 0x1d5b9, 1},
-		{0x1d5d4, 0x1d5ed, 1},
-		{0x1d608, 0x1d621, 1},
-		{0x1d63c, 0x1d655, 1},
-		{0x1d670, 0x1d689, 1},
-		{0x1d6a8, 0x1d6c0, 1},
-		{0x1d6e2, 0x1d6fa, 1},
-		{0x1d71c, 0x1d734, 1},
-		{0x1d756, 0x1d76e, 1},
-		{0x1d790, 0x1d7a8, 1},
-		{0x1d7ca, 0x1d7ca, 1},
-	},
-}
-
-var _Lt = &RangeTable{
-	R16: []Range16{
-		{0x01c5, 0x01cb, 3},
-		{0x01f2, 0x1f88, 7574},
-		{0x1f89, 0x1f8f, 1},
-		{0x1f98, 0x1f9f, 1},
-		{0x1fa8, 0x1faf, 1},
-		{0x1fbc, 0x1fcc, 16},
-		{0x1ffc, 0x1ffc, 1},
-	},
-}
-
-var _Lo = &RangeTable{
+var _Lo = &RangeTable{
 	R16: []Range16{
 		{0x01bb, 0x01c0, 5},
 		{0x01c1, 0x01c3, 1},
@@ -2655,49 +996,1708 @@ var _Lo = &RangeTable{
 		{0xffda, 0xffdc, 1},
 	},
 	R32: []Range32{
-		{0x10000, 0x1000b, 1},
-		{0x1000d, 0x10026, 1},
-		{0x10028, 0x1003a, 1},
-		{0x1003c, 0x1003d, 1},
-		{0x1003f, 0x1004d, 1},
-		{0x10050, 0x1005d, 1},
-		{0x10080, 0x100fa, 1},
-		{0x10280, 0x1029c, 1},
-		{0x102a0, 0x102d0, 1},
-		{0x10300, 0x1031e, 1},
-		{0x10330, 0x10340, 1},
-		{0x10342, 0x10349, 1},
-		{0x10380, 0x1039d, 1},
-		{0x103a0, 0x103c3, 1},
-		{0x103c8, 0x103cf, 1},
-		{0x10450, 0x1049d, 1},
-		{0x10800, 0x10805, 1},
-		{0x10808, 0x1080a, 2},
-		{0x1080b, 0x10835, 1},
-		{0x10837, 0x10838, 1},
-		{0x1083c, 0x1083f, 3},
-		{0x10840, 0x10855, 1},
-		{0x10900, 0x10915, 1},
-		{0x10920, 0x10939, 1},
-		{0x10a00, 0x10a10, 16},
-		{0x10a11, 0x10a13, 1},
-		{0x10a15, 0x10a17, 1},
-		{0x10a19, 0x10a33, 1},
-		{0x10a60, 0x10a7c, 1},
-		{0x10b00, 0x10b35, 1},
-		{0x10b40, 0x10b55, 1},
-		{0x10b60, 0x10b72, 1},
-		{0x10c00, 0x10c48, 1},
-		{0x11003, 0x11037, 1},
-		{0x11083, 0x110af, 1},
-		{0x12000, 0x1236e, 1},
-		{0x13000, 0x1342e, 1},
-		{0x16800, 0x16a38, 1},
-		{0x1b000, 0x1b001, 1},
-		{0x20000, 0x2a6d6, 1},
-		{0x2a700, 0x2b734, 1},
-		{0x2b740, 0x2b81d, 1},
-		{0x2f800, 0x2fa1d, 1},
+		{0x10000, 0x1000b, 1},
+		{0x1000d, 0x10026, 1},
+		{0x10028, 0x1003a, 1},
+		{0x1003c, 0x1003d, 1},
+		{0x1003f, 0x1004d, 1},
+		{0x10050, 0x1005d, 1},
+		{0x10080, 0x100fa, 1},
+		{0x10280, 0x1029c, 1},
+		{0x102a0, 0x102d0, 1},
+		{0x10300, 0x1031e, 1},
+		{0x10330, 0x10340, 1},
+		{0x10342, 0x10349, 1},
+		{0x10380, 0x1039d, 1},
+		{0x103a0, 0x103c3, 1},
+		{0x103c8, 0x103cf, 1},
+		{0x10450, 0x1049d, 1},
+		{0x10800, 0x10805, 1},
+		{0x10808, 0x1080a, 2},
+		{0x1080b, 0x10835, 1},
+		{0x10837, 0x10838, 1},
+		{0x1083c, 0x1083f, 3},
+		{0x10840, 0x10855, 1},
+		{0x10900, 0x10915, 1},
+		{0x10920, 0x10939, 1},
+		{0x10a00, 0x10a10, 16},
+		{0x10a11, 0x10a13, 1},
+		{0x10a15, 0x10a17, 1},
+		{0x10a19, 0x10a33, 1},
+		{0x10a60, 0x10a7c, 1},
+		{0x10b00, 0x10b35, 1},
+		{0x10b40, 0x10b55, 1},
+		{0x10b60, 0x10b72, 1},
+		{0x10c00, 0x10c48, 1},
+		{0x11003, 0x11037, 1},
+		{0x11083, 0x110af, 1},
+		{0x12000, 0x1236e, 1},
+		{0x13000, 0x1342e, 1},
+		{0x16800, 0x16a38, 1},
+		{0x1b000, 0x1b001, 1},
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+		{0x2f800, 0x2fa1d, 1},
+	},
+}
+
+var _Lt = &RangeTable{
+	R16: []Range16{
+		{0x01c5, 0x01cb, 3},
+		{0x01f2, 0x1f88, 7574},
+		{0x1f89, 0x1f8f, 1},
+		{0x1f98, 0x1f9f, 1},
+		{0x1fa8, 0x1faf, 1},
+		{0x1fbc, 0x1fcc, 16},
+		{0x1ffc, 0x1ffc, 1},
+	},
+}
+
+var _Lu = &RangeTable{
+	R16: []Range16{
+		{0x0041, 0x005a, 1},
+		{0x00c0, 0x00d6, 1},
+		{0x00d8, 0x00de, 1},
+		{0x0100, 0x0136, 2},
+		{0x0139, 0x0147, 2},
+		{0x014a, 0x0178, 2},
+		{0x0179, 0x017d, 2},
+		{0x0181, 0x0182, 1},
+		{0x0184, 0x0186, 2},
+		{0x0187, 0x0189, 2},
+		{0x018a, 0x018b, 1},
+		{0x018e, 0x0191, 1},
+		{0x0193, 0x0194, 1},
+		{0x0196, 0x0198, 1},
+		{0x019c, 0x019d, 1},
+		{0x019f, 0x01a0, 1},
+		{0x01a2, 0x01a6, 2},
+		{0x01a7, 0x01a9, 2},
+		{0x01ac, 0x01ae, 2},
+		{0x01af, 0x01b1, 2},
+		{0x01b2, 0x01b3, 1},
+		{0x01b5, 0x01b7, 2},
+		{0x01b8, 0x01bc, 4},
+		{0x01c4, 0x01cd, 3},
+		{0x01cf, 0x01db, 2},
+		{0x01de, 0x01ee, 2},
+		{0x01f1, 0x01f4, 3},
+		{0x01f6, 0x01f8, 1},
+		{0x01fa, 0x0232, 2},
+		{0x023a, 0x023b, 1},
+		{0x023d, 0x023e, 1},
+		{0x0241, 0x0243, 2},
+		{0x0244, 0x0246, 1},
+		{0x0248, 0x024e, 2},
+		{0x0370, 0x0372, 2},
+		{0x0376, 0x0386, 16},
+		{0x0388, 0x038a, 1},
+		{0x038c, 0x038e, 2},
+		{0x038f, 0x0391, 2},
+		{0x0392, 0x03a1, 1},
+		{0x03a3, 0x03ab, 1},
+		{0x03cf, 0x03d2, 3},
+		{0x03d3, 0x03d4, 1},
+		{0x03d8, 0x03ee, 2},
+		{0x03f4, 0x03f7, 3},
+		{0x03f9, 0x03fa, 1},
+		{0x03fd, 0x042f, 1},
+		{0x0460, 0x0480, 2},
+		{0x048a, 0x04c0, 2},
+		{0x04c1, 0x04cd, 2},
+		{0x04d0, 0x0526, 2},
+		{0x0531, 0x0556, 1},
+		{0x10a0, 0x10c5, 1},
+		{0x1e00, 0x1e94, 2},
+		{0x1e9e, 0x1efe, 2},
+		{0x1f08, 0x1f0f, 1},
+		{0x1f18, 0x1f1d, 1},
+		{0x1f28, 0x1f2f, 1},
+		{0x1f38, 0x1f3f, 1},
+		{0x1f48, 0x1f4d, 1},
+		{0x1f59, 0x1f5f, 2},
+		{0x1f68, 0x1f6f, 1},
+		{0x1fb8, 0x1fbb, 1},
+		{0x1fc8, 0x1fcb, 1},
+		{0x1fd8, 0x1fdb, 1},
+		{0x1fe8, 0x1fec, 1},
+		{0x1ff8, 0x1ffb, 1},
+		{0x2102, 0x2107, 5},
+		{0x210b, 0x210d, 1},
+		{0x2110, 0x2112, 1},
+		{0x2115, 0x2119, 4},
+		{0x211a, 0x211d, 1},
+		{0x2124, 0x212a, 2},
+		{0x212b, 0x212d, 1},
+		{0x2130, 0x2133, 1},
+		{0x213e, 0x213f, 1},
+		{0x2145, 0x2183, 62},
+		{0x2c00, 0x2c2e, 1},
+		{0x2c60, 0x2c62, 2},
+		{0x2c63, 0x2c64, 1},
+		{0x2c67, 0x2c6d, 2},
+		{0x2c6e, 0x2c70, 1},
+		{0x2c72, 0x2c75, 3},
+		{0x2c7e, 0x2c80, 1},
+		{0x2c82, 0x2ce2, 2},
+		{0x2ceb, 0x2ced, 2},
+		{0xa640, 0xa66c, 2},
+		{0xa680, 0xa696, 2},
+		{0xa722, 0xa72e, 2},
+		{0xa732, 0xa76e, 2},
+		{0xa779, 0xa77d, 2},
+		{0xa77e, 0xa786, 2},
+		{0xa78b, 0xa78d, 2},
+		{0xa790, 0xa7a0, 16},
+		{0xa7a2, 0xa7a8, 2},
+		{0xff21, 0xff3a, 1},
+	},
+	R32: []Range32{
+		{0x10400, 0x10427, 1},
+		{0x1d400, 0x1d419, 1},
+		{0x1d434, 0x1d44d, 1},
+		{0x1d468, 0x1d481, 1},
+		{0x1d49c, 0x1d49e, 2},
+		{0x1d49f, 0x1d4a5, 3},
+		{0x1d4a6, 0x1d4a9, 3},
+		{0x1d4aa, 0x1d4ac, 1},
+		{0x1d4ae, 0x1d4b5, 1},
+		{0x1d4d0, 0x1d4e9, 1},
+		{0x1d504, 0x1d505, 1},
+		{0x1d507, 0x1d50a, 1},
+		{0x1d50d, 0x1d514, 1},
+		{0x1d516, 0x1d51c, 1},
+		{0x1d538, 0x1d539, 1},
+		{0x1d53b, 0x1d53e, 1},
+		{0x1d540, 0x1d544, 1},
+		{0x1d546, 0x1d54a, 4},
+		{0x1d54b, 0x1d550, 1},
+		{0x1d56c, 0x1d585, 1},
+		{0x1d5a0, 0x1d5b9, 1},
+		{0x1d5d4, 0x1d5ed, 1},
+		{0x1d608, 0x1d621, 1},
+		{0x1d63c, 0x1d655, 1},
+		{0x1d670, 0x1d689, 1},
+		{0x1d6a8, 0x1d6c0, 1},
+		{0x1d6e2, 0x1d6fa, 1},
+		{0x1d71c, 0x1d734, 1},
+		{0x1d756, 0x1d76e, 1},
+		{0x1d790, 0x1d7a8, 1},
+		{0x1d7ca, 0x1d7ca, 1},
+	},
+}
+
+var _M = &RangeTable{
+	R16: []Range16{
+		{0x0300, 0x036f, 1},
+		{0x0483, 0x0489, 1},
+		{0x0591, 0x05bd, 1},
+		{0x05bf, 0x05c1, 2},
+		{0x05c2, 0x05c4, 2},
+		{0x05c5, 0x05c7, 2},
+		{0x0610, 0x061a, 1},
+		{0x064b, 0x065f, 1},
+		{0x0670, 0x06d6, 102},
+		{0x06d7, 0x06dc, 1},
+		{0x06df, 0x06e4, 1},
+		{0x06e7, 0x06e8, 1},
+		{0x06ea, 0x06ed, 1},
+		{0x0711, 0x0730, 31},
+		{0x0731, 0x074a, 1},
+		{0x07a6, 0x07b0, 1},
+		{0x07eb, 0x07f3, 1},
+		{0x0816, 0x0819, 1},
+		{0x081b, 0x0823, 1},
+		{0x0825, 0x0827, 1},
+		{0x0829, 0x082d, 1},
+		{0x0859, 0x085b, 1},
+		{0x0900, 0x0903, 1},
+		{0x093a, 0x093c, 1},
+		{0x093e, 0x094f, 1},
+		{0x0951, 0x0957, 1},
+		{0x0962, 0x0963, 1},
+		{0x0981, 0x0983, 1},
+		{0x09bc, 0x09be, 2},
+		{0x09bf, 0x09c4, 1},
+		{0x09c7, 0x09c8, 1},
+		{0x09cb, 0x09cd, 1},
+		{0x09d7, 0x09e2, 11},
+		{0x09e3, 0x0a01, 30},
+		{0x0a02, 0x0a03, 1},
+		{0x0a3c, 0x0a3e, 2},
+		{0x0a3f, 0x0a42, 1},
+		{0x0a47, 0x0a48, 1},
+		{0x0a4b, 0x0a4d, 1},
+		{0x0a51, 0x0a70, 31},
+		{0x0a71, 0x0a75, 4},
+		{0x0a81, 0x0a83, 1},
+		{0x0abc, 0x0abe, 2},
+		{0x0abf, 0x0ac5, 1},
+		{0x0ac7, 0x0ac9, 1},
+		{0x0acb, 0x0acd, 1},
+		{0x0ae2, 0x0ae3, 1},
+		{0x0b01, 0x0b03, 1},
+		{0x0b3c, 0x0b3e, 2},
+		{0x0b3f, 0x0b44, 1},
+		{0x0b47, 0x0b48, 1},
+		{0x0b4b, 0x0b4d, 1},
+		{0x0b56, 0x0b57, 1},
+		{0x0b62, 0x0b63, 1},
+		{0x0b82, 0x0bbe, 60},
+		{0x0bbf, 0x0bc2, 1},
+		{0x0bc6, 0x0bc8, 1},
+		{0x0bca, 0x0bcd, 1},
+		{0x0bd7, 0x0c01, 42},
+		{0x0c02, 0x0c03, 1},
+		{0x0c3e, 0x0c44, 1},
+		{0x0c46, 0x0c48, 1},
+		{0x0c4a, 0x0c4d, 1},
+		{0x0c55, 0x0c56, 1},
+		{0x0c62, 0x0c63, 1},
+		{0x0c82, 0x0c83, 1},
+		{0x0cbc, 0x0cbe, 2},
+		{0x0cbf, 0x0cc4, 1},
+		{0x0cc6, 0x0cc8, 1},
+		{0x0cca, 0x0ccd, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0ce2, 0x0ce3, 1},
+		{0x0d02, 0x0d03, 1},
+		{0x0d3e, 0x0d44, 1},
+		{0x0d46, 0x0d48, 1},
+		{0x0d4a, 0x0d4d, 1},
+		{0x0d57, 0x0d62, 11},
+		{0x0d63, 0x0d82, 31},
+		{0x0d83, 0x0dca, 71},
+		{0x0dcf, 0x0dd4, 1},
+		{0x0dd6, 0x0dd8, 2},
+		{0x0dd9, 0x0ddf, 1},
+		{0x0df2, 0x0df3, 1},
+		{0x0e31, 0x0e34, 3},
+		{0x0e35, 0x0e3a, 1},
+		{0x0e47, 0x0e4e, 1},
+		{0x0eb1, 0x0eb4, 3},
+		{0x0eb5, 0x0eb9, 1},
+		{0x0ebb, 0x0ebc, 1},
+		{0x0ec8, 0x0ecd, 1},
+		{0x0f18, 0x0f19, 1},
+		{0x0f35, 0x0f39, 2},
+		{0x0f3e, 0x0f3f, 1},
+		{0x0f71, 0x0f84, 1},
+		{0x0f86, 0x0f87, 1},
+		{0x0f8d, 0x0f97, 1},
+		{0x0f99, 0x0fbc, 1},
+		{0x0fc6, 0x102b, 101},
+		{0x102c, 0x103e, 1},
+		{0x1056, 0x1059, 1},
+		{0x105e, 0x1060, 1},
+		{0x1062, 0x1064, 1},
+		{0x1067, 0x106d, 1},
+		{0x1071, 0x1074, 1},
+		{0x1082, 0x108d, 1},
+		{0x108f, 0x109a, 11},
+		{0x109b, 0x109d, 1},
+		{0x135d, 0x135f, 1},
+		{0x1712, 0x1714, 1},
+		{0x1732, 0x1734, 1},
+		{0x1752, 0x1753, 1},
+		{0x1772, 0x1773, 1},
+		{0x17b6, 0x17d3, 1},
+		{0x17dd, 0x180b, 46},
+		{0x180c, 0x180d, 1},
+		{0x18a9, 0x1920, 119},
+		{0x1921, 0x192b, 1},
+		{0x1930, 0x193b, 1},
+		{0x19b0, 0x19c0, 1},
+		{0x19c8, 0x19c9, 1},
+		{0x1a17, 0x1a1b, 1},
+		{0x1a55, 0x1a5e, 1},
+		{0x1a60, 0x1a7c, 1},
+		{0x1a7f, 0x1b00, 129},
+		{0x1b01, 0x1b04, 1},
+		{0x1b34, 0x1b44, 1},
+		{0x1b6b, 0x1b73, 1},
+		{0x1b80, 0x1b82, 1},
+		{0x1ba1, 0x1baa, 1},
+		{0x1be6, 0x1bf3, 1},
+		{0x1c24, 0x1c37, 1},
+		{0x1cd0, 0x1cd2, 1},
+		{0x1cd4, 0x1ce8, 1},
+		{0x1ced, 0x1cf2, 5},
+		{0x1dc0, 0x1de6, 1},
+		{0x1dfc, 0x1dff, 1},
+		{0x20d0, 0x20f0, 1},
+		{0x2cef, 0x2cf1, 1},
+		{0x2d7f, 0x2de0, 97},
+		{0x2de1, 0x2dff, 1},
+		{0x302a, 0x302f, 1},
+		{0x3099, 0x309a, 1},
+		{0xa66f, 0xa672, 1},
+		{0xa67c, 0xa67d, 1},
+		{0xa6f0, 0xa6f1, 1},
+		{0xa802, 0xa806, 4},
+		{0xa80b, 0xa823, 24},
+		{0xa824, 0xa827, 1},
+		{0xa880, 0xa881, 1},
+		{0xa8b4, 0xa8c4, 1},
+		{0xa8e0, 0xa8f1, 1},
+		{0xa926, 0xa92d, 1},
+		{0xa947, 0xa953, 1},
+		{0xa980, 0xa983, 1},
+		{0xa9b3, 0xa9c0, 1},
+		{0xaa29, 0xaa36, 1},
+		{0xaa43, 0xaa4c, 9},
+		{0xaa4d, 0xaa7b, 46},
+		{0xaab0, 0xaab2, 2},
+		{0xaab3, 0xaab4, 1},
+		{0xaab7, 0xaab8, 1},
+		{0xaabe, 0xaabf, 1},
+		{0xaac1, 0xabe3, 290},
+		{0xabe4, 0xabea, 1},
+		{0xabec, 0xabed, 1},
+		{0xfb1e, 0xfe00, 738},
+		{0xfe01, 0xfe0f, 1},
+		{0xfe20, 0xfe26, 1},
+	},
+	R32: []Range32{
+		{0x101fd, 0x10a01, 2052},
+		{0x10a02, 0x10a03, 1},
+		{0x10a05, 0x10a06, 1},
+		{0x10a0c, 0x10a0f, 1},
+		{0x10a38, 0x10a3a, 1},
+		{0x10a3f, 0x11000, 1473},
+		{0x11001, 0x11002, 1},
+		{0x11038, 0x11046, 1},
+		{0x11080, 0x11082, 1},
+		{0x110b0, 0x110ba, 1},
+		{0x1d165, 0x1d169, 1},
+		{0x1d16d, 0x1d172, 1},
+		{0x1d17b, 0x1d182, 1},
+		{0x1d185, 0x1d18b, 1},
+		{0x1d1aa, 0x1d1ad, 1},
+		{0x1d242, 0x1d244, 1},
+		{0xe0100, 0xe01ef, 1},
+	},
+}
+
+var _Mc = &RangeTable{
+	R16: []Range16{
+		{0x0903, 0x093b, 56},
+		{0x093e, 0x0940, 1},
+		{0x0949, 0x094c, 1},
+		{0x094e, 0x094f, 1},
+		{0x0982, 0x0983, 1},
+		{0x09be, 0x09c0, 1},
+		{0x09c7, 0x09c8, 1},
+		{0x09cb, 0x09cc, 1},
+		{0x09d7, 0x0a03, 44},
+		{0x0a3e, 0x0a40, 1},
+		{0x0a83, 0x0abe, 59},
+		{0x0abf, 0x0ac0, 1},
+		{0x0ac9, 0x0acb, 2},
+		{0x0acc, 0x0b02, 54},
+		{0x0b03, 0x0b3e, 59},
+		{0x0b40, 0x0b47, 7},
+		{0x0b48, 0x0b4b, 3},
+		{0x0b4c, 0x0b57, 11},
+		{0x0bbe, 0x0bbf, 1},
+		{0x0bc1, 0x0bc2, 1},
+		{0x0bc6, 0x0bc8, 1},
+		{0x0bca, 0x0bcc, 1},
+		{0x0bd7, 0x0c01, 42},
+		{0x0c02, 0x0c03, 1},
+		{0x0c41, 0x0c44, 1},
+		{0x0c82, 0x0c83, 1},
+		{0x0cbe, 0x0cc0, 2},
+		{0x0cc1, 0x0cc4, 1},
+		{0x0cc7, 0x0cc8, 1},
+		{0x0cca, 0x0ccb, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0d02, 0x0d03, 1},
+		{0x0d3e, 0x0d40, 1},
+		{0x0d46, 0x0d48, 1},
+		{0x0d4a, 0x0d4c, 1},
+		{0x0d57, 0x0d82, 43},
+		{0x0d83, 0x0dcf, 76},
+		{0x0dd0, 0x0dd1, 1},
+		{0x0dd8, 0x0ddf, 1},
+		{0x0df2, 0x0df3, 1},
+		{0x0f3e, 0x0f3f, 1},
+		{0x0f7f, 0x102b, 172},
+		{0x102c, 0x1031, 5},
+		{0x1038, 0x103b, 3},
+		{0x103c, 0x1056, 26},
+		{0x1057, 0x1062, 11},
+		{0x1063, 0x1064, 1},
+		{0x1067, 0x106d, 1},
+		{0x1083, 0x1084, 1},
+		{0x1087, 0x108c, 1},
+		{0x108f, 0x109a, 11},
+		{0x109b, 0x109c, 1},
+		{0x17b6, 0x17be, 8},
+		{0x17bf, 0x17c5, 1},
+		{0x17c7, 0x17c8, 1},
+		{0x1923, 0x1926, 1},
+		{0x1929, 0x192b, 1},
+		{0x1930, 0x1931, 1},
+		{0x1933, 0x1938, 1},
+		{0x19b0, 0x19c0, 1},
+		{0x19c8, 0x19c9, 1},
+		{0x1a19, 0x1a1b, 1},
+		{0x1a55, 0x1a57, 2},
+		{0x1a61, 0x1a63, 2},
+		{0x1a64, 0x1a6d, 9},
+		{0x1a6e, 0x1a72, 1},
+		{0x1b04, 0x1b35, 49},
+		{0x1b3b, 0x1b3d, 2},
+		{0x1b3e, 0x1b41, 1},
+		{0x1b43, 0x1b44, 1},
+		{0x1b82, 0x1ba1, 31},
+		{0x1ba6, 0x1ba7, 1},
+		{0x1baa, 0x1be7, 61},
+		{0x1bea, 0x1bec, 1},
+		{0x1bee, 0x1bf2, 4},
+		{0x1bf3, 0x1c24, 49},
+		{0x1c25, 0x1c2b, 1},
+		{0x1c34, 0x1c35, 1},
+		{0x1ce1, 0x1cf2, 17},
+		{0xa823, 0xa824, 1},
+		{0xa827, 0xa880, 89},
+		{0xa881, 0xa8b4, 51},
+		{0xa8b5, 0xa8c3, 1},
+		{0xa952, 0xa953, 1},
+		{0xa983, 0xa9b4, 49},
+		{0xa9b5, 0xa9ba, 5},
+		{0xa9bb, 0xa9bd, 2},
+		{0xa9be, 0xa9c0, 1},
+		{0xaa2f, 0xaa30, 1},
+		{0xaa33, 0xaa34, 1},
+		{0xaa4d, 0xaa7b, 46},
+		{0xabe3, 0xabe4, 1},
+		{0xabe6, 0xabe7, 1},
+		{0xabe9, 0xabea, 1},
+		{0xabec, 0xabec, 1},
+	},
+	R32: []Range32{
+		{0x11000, 0x11000, 1},
+		{0x11002, 0x11082, 128},
+		{0x110b0, 0x110b2, 1},
+		{0x110b7, 0x110b8, 1},
+		{0x1d165, 0x1d166, 1},
+		{0x1d16d, 0x1d172, 1},
+	},
+}
+
+var _Me = &RangeTable{
+	R16: []Range16{
+		{0x0488, 0x0489, 1},
+		{0x20dd, 0x20e0, 1},
+		{0x20e2, 0x20e4, 1},
+		{0xa670, 0xa672, 1},
+	},
+}
+
+var _Mn = &RangeTable{
+	R16: []Range16{
+		{0x0300, 0x036f, 1},
+		{0x0483, 0x0487, 1},
+		{0x0591, 0x05bd, 1},
+		{0x05bf, 0x05c1, 2},
+		{0x05c2, 0x05c4, 2},
+		{0x05c5, 0x05c7, 2},
+		{0x0610, 0x061a, 1},
+		{0x064b, 0x065f, 1},
+		{0x0670, 0x06d6, 102},
+		{0x06d7, 0x06dc, 1},
+		{0x06df, 0x06e4, 1},
+		{0x06e7, 0x06e8, 1},
+		{0x06ea, 0x06ed, 1},
+		{0x0711, 0x0730, 31},
+		{0x0731, 0x074a, 1},
+		{0x07a6, 0x07b0, 1},
+		{0x07eb, 0x07f3, 1},
+		{0x0816, 0x0819, 1},
+		{0x081b, 0x0823, 1},
+		{0x0825, 0x0827, 1},
+		{0x0829, 0x082d, 1},
+		{0x0859, 0x085b, 1},
+		{0x0900, 0x0902, 1},
+		{0x093a, 0x093c, 2},
+		{0x0941, 0x0948, 1},
+		{0x094d, 0x0951, 4},
+		{0x0952, 0x0957, 1},
+		{0x0962, 0x0963, 1},
+		{0x0981, 0x09bc, 59},
+		{0x09c1, 0x09c4, 1},
+		{0x09cd, 0x09e2, 21},
+		{0x09e3, 0x0a01, 30},
+		{0x0a02, 0x0a3c, 58},
+		{0x0a41, 0x0a42, 1},
+		{0x0a47, 0x0a48, 1},
+		{0x0a4b, 0x0a4d, 1},
+		{0x0a51, 0x0a70, 31},
+		{0x0a71, 0x0a75, 4},
+		{0x0a81, 0x0a82, 1},
+		{0x0abc, 0x0ac1, 5},
+		{0x0ac2, 0x0ac5, 1},
+		{0x0ac7, 0x0ac8, 1},
+		{0x0acd, 0x0ae2, 21},
+		{0x0ae3, 0x0b01, 30},
+		{0x0b3c, 0x0b3f, 3},
+		{0x0b41, 0x0b44, 1},
+		{0x0b4d, 0x0b56, 9},
+		{0x0b62, 0x0b63, 1},
+		{0x0b82, 0x0bc0, 62},
+		{0x0bcd, 0x0c3e, 113},
+		{0x0c3f, 0x0c40, 1},
+		{0x0c46, 0x0c48, 1},
+		{0x0c4a, 0x0c4d, 1},
+		{0x0c55, 0x0c56, 1},
+		{0x0c62, 0x0c63, 1},
+		{0x0cbc, 0x0cbf, 3},
+		{0x0cc6, 0x0ccc, 6},
+		{0x0ccd, 0x0ce2, 21},
+		{0x0ce3, 0x0d41, 94},
+		{0x0d42, 0x0d44, 1},
+		{0x0d4d, 0x0d62, 21},
+		{0x0d63, 0x0dca, 103},
+		{0x0dd2, 0x0dd4, 1},
+		{0x0dd6, 0x0e31, 91},
+		{0x0e34, 0x0e3a, 1},
+		{0x0e47, 0x0e4e, 1},
+		{0x0eb1, 0x0eb4, 3},
+		{0x0eb5, 0x0eb9, 1},
+		{0x0ebb, 0x0ebc, 1},
+		{0x0ec8, 0x0ecd, 1},
+		{0x0f18, 0x0f19, 1},
+		{0x0f35, 0x0f39, 2},
+		{0x0f71, 0x0f7e, 1},
+		{0x0f80, 0x0f84, 1},
+		{0x0f86, 0x0f87, 1},
+		{0x0f8d, 0x0f97, 1},
+		{0x0f99, 0x0fbc, 1},
+		{0x0fc6, 0x102d, 103},
+		{0x102e, 0x1030, 1},
+		{0x1032, 0x1037, 1},
+		{0x1039, 0x103a, 1},
+		{0x103d, 0x103e, 1},
+		{0x1058, 0x1059, 1},
+		{0x105e, 0x1060, 1},
+		{0x1071, 0x1074, 1},
+		{0x1082, 0x1085, 3},
+		{0x1086, 0x108d, 7},
+		{0x109d, 0x135d, 704},
+		{0x135e, 0x135f, 1},
+		{0x1712, 0x1714, 1},
+		{0x1732, 0x1734, 1},
+		{0x1752, 0x1753, 1},
+		{0x1772, 0x1773, 1},
+		{0x17b7, 0x17bd, 1},
+		{0x17c6, 0x17c9, 3},
+		{0x17ca, 0x17d3, 1},
+		{0x17dd, 0x180b, 46},
+		{0x180c, 0x180d, 1},
+		{0x18a9, 0x1920, 119},
+		{0x1921, 0x1922, 1},
+		{0x1927, 0x1928, 1},
+		{0x1932, 0x1939, 7},
+		{0x193a, 0x193b, 1},
+		{0x1a17, 0x1a18, 1},
+		{0x1a56, 0x1a58, 2},
+		{0x1a59, 0x1a5e, 1},
+		{0x1a60, 0x1a62, 2},
+		{0x1a65, 0x1a6c, 1},
+		{0x1a73, 0x1a7c, 1},
+		{0x1a7f, 0x1b00, 129},
+		{0x1b01, 0x1b03, 1},
+		{0x1b34, 0x1b36, 2},
+		{0x1b37, 0x1b3a, 1},
+		{0x1b3c, 0x1b42, 6},
+		{0x1b6b, 0x1b73, 1},
+		{0x1b80, 0x1b81, 1},
+		{0x1ba2, 0x1ba5, 1},
+		{0x1ba8, 0x1ba9, 1},
+		{0x1be6, 0x1be8, 2},
+		{0x1be9, 0x1bed, 4},
+		{0x1bef, 0x1bf1, 1},
+		{0x1c2c, 0x1c33, 1},
+		{0x1c36, 0x1c37, 1},
+		{0x1cd0, 0x1cd2, 1},
+		{0x1cd4, 0x1ce0, 1},
+		{0x1ce2, 0x1ce8, 1},
+		{0x1ced, 0x1dc0, 211},
+		{0x1dc1, 0x1de6, 1},
+		{0x1dfc, 0x1dff, 1},
+		{0x20d0, 0x20dc, 1},
+		{0x20e1, 0x20e5, 4},
+		{0x20e6, 0x20f0, 1},
+		{0x2cef, 0x2cf1, 1},
+		{0x2d7f, 0x2de0, 97},
+		{0x2de1, 0x2dff, 1},
+		{0x302a, 0x302f, 1},
+		{0x3099, 0x309a, 1},
+		{0xa66f, 0xa67c, 13},
+		{0xa67d, 0xa6f0, 115},
+		{0xa6f1, 0xa802, 273},
+		{0xa806, 0xa80b, 5},
+		{0xa825, 0xa826, 1},
+		{0xa8c4, 0xa8e0, 28},
+		{0xa8e1, 0xa8f1, 1},
+		{0xa926, 0xa92d, 1},
+		{0xa947, 0xa951, 1},
+		{0xa980, 0xa982, 1},
+		{0xa9b3, 0xa9b6, 3},
+		{0xa9b7, 0xa9b9, 1},
+		{0xa9bc, 0xaa29, 109},
+		{0xaa2a, 0xaa2e, 1},
+		{0xaa31, 0xaa32, 1},
+		{0xaa35, 0xaa36, 1},
+		{0xaa43, 0xaa4c, 9},
+		{0xaab0, 0xaab2, 2},
+		{0xaab3, 0xaab4, 1},
+		{0xaab7, 0xaab8, 1},
+		{0xaabe, 0xaabf, 1},
+		{0xaac1, 0xabe5, 292},
+		{0xabe8, 0xabed, 5},
+		{0xfb1e, 0xfe00, 738},
+		{0xfe01, 0xfe0f, 1},
+		{0xfe20, 0xfe26, 1},
+	},
+	R32: []Range32{
+		{0x101fd, 0x10a01, 2052},
+		{0x10a02, 0x10a03, 1},
+		{0x10a05, 0x10a06, 1},
+		{0x10a0c, 0x10a0f, 1},
+		{0x10a38, 0x10a3a, 1},
+		{0x10a3f, 0x11001, 1474},
+		{0x11038, 0x11046, 1},
+		{0x11080, 0x11081, 1},
+		{0x110b3, 0x110b6, 1},
+		{0x110b9, 0x110ba, 1},
+		{0x1d167, 0x1d169, 1},
+		{0x1d17b, 0x1d182, 1},
+		{0x1d185, 0x1d18b, 1},
+		{0x1d1aa, 0x1d1ad, 1},
+		{0x1d242, 0x1d244, 1},
+		{0xe0100, 0xe01ef, 1},
+	},
+}
+
+var _N = &RangeTable{
+	R16: []Range16{
+		{0x0030, 0x0039, 1},
+		{0x00b2, 0x00b3, 1},
+		{0x00b9, 0x00bc, 3},
+		{0x00bd, 0x00be, 1},
+		{0x0660, 0x0669, 1},
+		{0x06f0, 0x06f9, 1},
+		{0x07c0, 0x07c9, 1},
+		{0x0966, 0x096f, 1},
+		{0x09e6, 0x09ef, 1},
+		{0x09f4, 0x09f9, 1},
+		{0x0a66, 0x0a6f, 1},
+		{0x0ae6, 0x0aef, 1},
+		{0x0b66, 0x0b6f, 1},
+		{0x0b72, 0x0b77, 1},
+		{0x0be6, 0x0bf2, 1},
+		{0x0c66, 0x0c6f, 1},
+		{0x0c78, 0x0c7e, 1},
+		{0x0ce6, 0x0cef, 1},
+		{0x0d66, 0x0d75, 1},
+		{0x0e50, 0x0e59, 1},
+		{0x0ed0, 0x0ed9, 1},
+		{0x0f20, 0x0f33, 1},
+		{0x1040, 0x1049, 1},
+		{0x1090, 0x1099, 1},
+		{0x1369, 0x137c, 1},
+		{0x16ee, 0x16f0, 1},
+		{0x17e0, 0x17e9, 1},
+		{0x17f0, 0x17f9, 1},
+		{0x1810, 0x1819, 1},
+		{0x1946, 0x194f, 1},
+		{0x19d0, 0x19da, 1},
+		{0x1a80, 0x1a89, 1},
+		{0x1a90, 0x1a99, 1},
+		{0x1b50, 0x1b59, 1},
+		{0x1bb0, 0x1bb9, 1},
+		{0x1c40, 0x1c49, 1},
+		{0x1c50, 0x1c59, 1},
+		{0x2070, 0x2074, 4},
+		{0x2075, 0x2079, 1},
+		{0x2080, 0x2089, 1},
+		{0x2150, 0x2182, 1},
+		{0x2185, 0x2189, 1},
+		{0x2460, 0x249b, 1},
+		{0x24ea, 0x24ff, 1},
+		{0x2776, 0x2793, 1},
+		{0x2cfd, 0x3007, 778},
+		{0x3021, 0x3029, 1},
+		{0x3038, 0x303a, 1},
+		{0x3192, 0x3195, 1},
+		{0x3220, 0x3229, 1},
+		{0x3251, 0x325f, 1},
+		{0x3280, 0x3289, 1},
+		{0x32b1, 0x32bf, 1},
+		{0xa620, 0xa629, 1},
+		{0xa6e6, 0xa6ef, 1},
+		{0xa830, 0xa835, 1},
+		{0xa8d0, 0xa8d9, 1},
+		{0xa900, 0xa909, 1},
+		{0xa9d0, 0xa9d9, 1},
+		{0xaa50, 0xaa59, 1},
+		{0xabf0, 0xabf9, 1},
+		{0xff10, 0xff19, 1},
+	},
+	R32: []Range32{
+		{0x10107, 0x10133, 1},
+		{0x10140, 0x10178, 1},
+		{0x1018a, 0x10320, 406},
+		{0x10321, 0x10323, 1},
+		{0x10341, 0x1034a, 9},
+		{0x103d1, 0x103d5, 1},
+		{0x104a0, 0x104a9, 1},
+		{0x10858, 0x1085f, 1},
+		{0x10916, 0x1091b, 1},
+		{0x10a40, 0x10a47, 1},
+		{0x10a7d, 0x10a7e, 1},
+		{0x10b58, 0x10b5f, 1},
+		{0x10b78, 0x10b7f, 1},
+		{0x10e60, 0x10e7e, 1},
+		{0x11052, 0x1106f, 1},
+		{0x12400, 0x12462, 1},
+		{0x1d360, 0x1d371, 1},
+		{0x1d7ce, 0x1d7ff, 1},
+		{0x1f100, 0x1f10a, 1},
+	},
+}
+
+var _Nd = &RangeTable{
+	R16: []Range16{
+		{0x0030, 0x0039, 1},
+		{0x0660, 0x0669, 1},
+		{0x06f0, 0x06f9, 1},
+		{0x07c0, 0x07c9, 1},
+		{0x0966, 0x096f, 1},
+		{0x09e6, 0x09ef, 1},
+		{0x0a66, 0x0a6f, 1},
+		{0x0ae6, 0x0aef, 1},
+		{0x0b66, 0x0b6f, 1},
+		{0x0be6, 0x0bef, 1},
+		{0x0c66, 0x0c6f, 1},
+		{0x0ce6, 0x0cef, 1},
+		{0x0d66, 0x0d6f, 1},
+		{0x0e50, 0x0e59, 1},
+		{0x0ed0, 0x0ed9, 1},
+		{0x0f20, 0x0f29, 1},
+		{0x1040, 0x1049, 1},
+		{0x1090, 0x1099, 1},
+		{0x17e0, 0x17e9, 1},
+		{0x1810, 0x1819, 1},
+		{0x1946, 0x194f, 1},
+		{0x19d0, 0x19d9, 1},
+		{0x1a80, 0x1a89, 1},
+		{0x1a90, 0x1a99, 1},
+		{0x1b50, 0x1b59, 1},
+		{0x1bb0, 0x1bb9, 1},
+		{0x1c40, 0x1c49, 1},
+		{0x1c50, 0x1c59, 1},
+		{0xa620, 0xa629, 1},
+		{0xa8d0, 0xa8d9, 1},
+		{0xa900, 0xa909, 1},
+		{0xa9d0, 0xa9d9, 1},
+		{0xaa50, 0xaa59, 1},
+		{0xabf0, 0xabf9, 1},
+		{0xff10, 0xff19, 1},
+	},
+	R32: []Range32{
+		{0x104a0, 0x104a9, 1},
+		{0x11066, 0x1106f, 1},
+		{0x1d7ce, 0x1d7ff, 1},
+	},
+}
+
+var _Nl = &RangeTable{
+	R16: []Range16{
+		{0x16ee, 0x16f0, 1},
+		{0x2160, 0x2182, 1},
+		{0x2185, 0x2188, 1},
+		{0x3007, 0x3021, 26},
+		{0x3022, 0x3029, 1},
+		{0x3038, 0x303a, 1},
+		{0xa6e6, 0xa6ef, 1},
+	},
+	R32: []Range32{
+		{0x10140, 0x10174, 1},
+		{0x10341, 0x1034a, 9},
+		{0x103d1, 0x103d5, 1},
+		{0x12400, 0x12462, 1},
+	},
+}
+
+var _No = &RangeTable{
+	R16: []Range16{
+		{0x00b2, 0x00b3, 1},
+		{0x00b9, 0x00bc, 3},
+		{0x00bd, 0x00be, 1},
+		{0x09f4, 0x09f9, 1},
+		{0x0b72, 0x0b77, 1},
+		{0x0bf0, 0x0bf2, 1},
+		{0x0c78, 0x0c7e, 1},
+		{0x0d70, 0x0d75, 1},
+		{0x0f2a, 0x0f33, 1},
+		{0x1369, 0x137c, 1},
+		{0x17f0, 0x17f9, 1},
+		{0x19da, 0x2070, 1686},
+		{0x2074, 0x2079, 1},
+		{0x2080, 0x2089, 1},
+		{0x2150, 0x215f, 1},
+		{0x2189, 0x2460, 727},
+		{0x2461, 0x249b, 1},
+		{0x24ea, 0x24ff, 1},
+		{0x2776, 0x2793, 1},
+		{0x2cfd, 0x3192, 1173},
+		{0x3193, 0x3195, 1},
+		{0x3220, 0x3229, 1},
+		{0x3251, 0x325f, 1},
+		{0x3280, 0x3289, 1},
+		{0x32b1, 0x32bf, 1},
+		{0xa830, 0xa835, 1},
+	},
+	R32: []Range32{
+		{0x10107, 0x10133, 1},
+		{0x10175, 0x10178, 1},
+		{0x1018a, 0x10320, 406},
+		{0x10321, 0x10323, 1},
+		{0x10858, 0x1085f, 1},
+		{0x10916, 0x1091b, 1},
+		{0x10a40, 0x10a47, 1},
+		{0x10a7d, 0x10a7e, 1},
+		{0x10b58, 0x10b5f, 1},
+		{0x10b78, 0x10b7f, 1},
+		{0x10e60, 0x10e7e, 1},
+		{0x11052, 0x11065, 1},
+		{0x1d360, 0x1d371, 1},
+		{0x1f100, 0x1f10a, 1},
+	},
+}
+
+var _P = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x0023, 1},
+		{0x0025, 0x002a, 1},
+		{0x002c, 0x002f, 1},
+		{0x003a, 0x003b, 1},
+		{0x003f, 0x0040, 1},
+		{0x005b, 0x005d, 1},
+		{0x005f, 0x007b, 28},
+		{0x007d, 0x00a1, 36},
+		{0x00ab, 0x00b7, 12},
+		{0x00bb, 0x00bf, 4},
+		{0x037e, 0x0387, 9},
+		{0x055a, 0x055f, 1},
+		{0x0589, 0x058a, 1},
+		{0x05be, 0x05c0, 2},
+		{0x05c3, 0x05c6, 3},
+		{0x05f3, 0x05f4, 1},
+		{0x0609, 0x060a, 1},
+		{0x060c, 0x060d, 1},
+		{0x061b, 0x061e, 3},
+		{0x061f, 0x066a, 75},
+		{0x066b, 0x066d, 1},
+		{0x06d4, 0x0700, 44},
+		{0x0701, 0x070d, 1},
+		{0x07f7, 0x07f9, 1},
+		{0x0830, 0x083e, 1},
+		{0x085e, 0x0964, 262},
+		{0x0965, 0x0970, 11},
+		{0x0df4, 0x0e4f, 91},
+		{0x0e5a, 0x0e5b, 1},
+		{0x0f04, 0x0f12, 1},
+		{0x0f3a, 0x0f3d, 1},
+		{0x0f85, 0x0fd0, 75},
+		{0x0fd1, 0x0fd4, 1},
+		{0x0fd9, 0x0fda, 1},
+		{0x104a, 0x104f, 1},
+		{0x10fb, 0x1361, 614},
+		{0x1362, 0x1368, 1},
+		{0x1400, 0x166d, 621},
+		{0x166e, 0x169b, 45},
+		{0x169c, 0x16eb, 79},
+		{0x16ec, 0x16ed, 1},
+		{0x1735, 0x1736, 1},
+		{0x17d4, 0x17d6, 1},
+		{0x17d8, 0x17da, 1},
+		{0x1800, 0x180a, 1},
+		{0x1944, 0x1945, 1},
+		{0x1a1e, 0x1a1f, 1},
+		{0x1aa0, 0x1aa6, 1},
+		{0x1aa8, 0x1aad, 1},
+		{0x1b5a, 0x1b60, 1},
+		{0x1bfc, 0x1bff, 1},
+		{0x1c3b, 0x1c3f, 1},
+		{0x1c7e, 0x1c7f, 1},
+		{0x1cd3, 0x2010, 829},
+		{0x2011, 0x2027, 1},
+		{0x2030, 0x2043, 1},
+		{0x2045, 0x2051, 1},
+		{0x2053, 0x205e, 1},
+		{0x207d, 0x207e, 1},
+		{0x208d, 0x208e, 1},
+		{0x2329, 0x232a, 1},
+		{0x2768, 0x2775, 1},
+		{0x27c5, 0x27c6, 1},
+		{0x27e6, 0x27ef, 1},
+		{0x2983, 0x2998, 1},
+		{0x29d8, 0x29db, 1},
+		{0x29fc, 0x29fd, 1},
+		{0x2cf9, 0x2cfc, 1},
+		{0x2cfe, 0x2cff, 1},
+		{0x2d70, 0x2e00, 144},
+		{0x2e01, 0x2e2e, 1},
+		{0x2e30, 0x2e31, 1},
+		{0x3001, 0x3003, 1},
+		{0x3008, 0x3011, 1},
+		{0x3014, 0x301f, 1},
+		{0x3030, 0x303d, 13},
+		{0x30a0, 0x30fb, 91},
+		{0xa4fe, 0xa4ff, 1},
+		{0xa60d, 0xa60f, 1},
+		{0xa673, 0xa67e, 11},
+		{0xa6f2, 0xa6f7, 1},
+		{0xa874, 0xa877, 1},
+		{0xa8ce, 0xa8cf, 1},
+		{0xa8f8, 0xa8fa, 1},
+		{0xa92e, 0xa92f, 1},
+		{0xa95f, 0xa9c1, 98},
+		{0xa9c2, 0xa9cd, 1},
+		{0xa9de, 0xa9df, 1},
+		{0xaa5c, 0xaa5f, 1},
+		{0xaade, 0xaadf, 1},
+		{0xabeb, 0xfd3e, 20819},
+		{0xfd3f, 0xfe10, 209},
+		{0xfe11, 0xfe19, 1},
+		{0xfe30, 0xfe52, 1},
+		{0xfe54, 0xfe61, 1},
+		{0xfe63, 0xfe68, 5},
+		{0xfe6a, 0xfe6b, 1},
+		{0xff01, 0xff03, 1},
+		{0xff05, 0xff0a, 1},
+		{0xff0c, 0xff0f, 1},
+		{0xff1a, 0xff1b, 1},
+		{0xff1f, 0xff20, 1},
+		{0xff3b, 0xff3d, 1},
+		{0xff3f, 0xff5b, 28},
+		{0xff5d, 0xff5f, 2},
+		{0xff60, 0xff65, 1},
+	},
+	R32: []Range32{
+		{0x10100, 0x10101, 1},
+		{0x1039f, 0x103d0, 49},
+		{0x10857, 0x1091f, 200},
+		{0x1093f, 0x10a50, 273},
+		{0x10a51, 0x10a58, 1},
+		{0x10a7f, 0x10b39, 186},
+		{0x10b3a, 0x10b3f, 1},
+		{0x11047, 0x1104d, 1},
+		{0x110bb, 0x110bc, 1},
+		{0x110be, 0x110c1, 1},
+		{0x12470, 0x12473, 1},
+	},
+}
+
+var _Pc = &RangeTable{
+	R16: []Range16{
+		{0x005f, 0x203f, 8160},
+		{0x2040, 0x2054, 20},
+		{0xfe33, 0xfe34, 1},
+		{0xfe4d, 0xfe4f, 1},
+		{0xff3f, 0xff3f, 1},
+	},
+}
+
+var _Pd = &RangeTable{
+	R16: []Range16{
+		{0x002d, 0x058a, 1373},
+		{0x05be, 0x1400, 3650},
+		{0x1806, 0x2010, 2058},
+		{0x2011, 0x2015, 1},
+		{0x2e17, 0x2e1a, 3},
+		{0x301c, 0x3030, 20},
+		{0x30a0, 0xfe31, 52625},
+		{0xfe32, 0xfe58, 38},
+		{0xfe63, 0xff0d, 170},
+	},
+}
+
+var _Pe = &RangeTable{
+	R16: []Range16{
+		{0x0029, 0x005d, 52},
+		{0x007d, 0x0f3b, 3774},
+		{0x0f3d, 0x169c, 1887},
+		{0x2046, 0x207e, 56},
+		{0x208e, 0x232a, 668},
+		{0x2769, 0x2775, 2},
+		{0x27c6, 0x27e7, 33},
+		{0x27e9, 0x27ef, 2},
+		{0x2984, 0x2998, 2},
+		{0x29d9, 0x29db, 2},
+		{0x29fd, 0x2e23, 1062},
+		{0x2e25, 0x2e29, 2},
+		{0x3009, 0x3011, 2},
+		{0x3015, 0x301b, 2},
+		{0x301e, 0x301f, 1},
+		{0xfd3f, 0xfe18, 217},
+		{0xfe36, 0xfe44, 2},
+		{0xfe48, 0xfe5a, 18},
+		{0xfe5c, 0xfe5e, 2},
+		{0xff09, 0xff3d, 52},
+		{0xff5d, 0xff63, 3},
+	},
+}
+
+var _Pf = &RangeTable{
+	R16: []Range16{
+		{0x00bb, 0x2019, 8030},
+		{0x201d, 0x203a, 29},
+		{0x2e03, 0x2e05, 2},
+		{0x2e0a, 0x2e0d, 3},
+		{0x2e1d, 0x2e21, 4},
+	},
+}
+
+var _Pi = &RangeTable{
+	R16: []Range16{
+		{0x00ab, 0x2018, 8045},
+		{0x201b, 0x201c, 1},
+		{0x201f, 0x2039, 26},
+		{0x2e02, 0x2e04, 2},
+		{0x2e09, 0x2e0c, 3},
+		{0x2e1c, 0x2e20, 4},
+	},
+}
+
+var _Po = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x0023, 1},
+		{0x0025, 0x0027, 1},
+		{0x002a, 0x002e, 2},
+		{0x002f, 0x003a, 11},
+		{0x003b, 0x003f, 4},
+		{0x0040, 0x005c, 28},
+		{0x00a1, 0x00b7, 22},
+		{0x00bf, 0x037e, 703},
+		{0x0387, 0x055a, 467},
+		{0x055b, 0x055f, 1},
+		{0x0589, 0x05c0, 55},
+		{0x05c3, 0x05c6, 3},
+		{0x05f3, 0x05f4, 1},
+		{0x0609, 0x060a, 1},
+		{0x060c, 0x060d, 1},
+		{0x061b, 0x061e, 3},
+		{0x061f, 0x066a, 75},
+		{0x066b, 0x066d, 1},
+		{0x06d4, 0x0700, 44},
+		{0x0701, 0x070d, 1},
+		{0x07f7, 0x07f9, 1},
+		{0x0830, 0x083e, 1},
+		{0x085e, 0x0964, 262},
+		{0x0965, 0x0970, 11},
+		{0x0df4, 0x0e4f, 91},
+		{0x0e5a, 0x0e5b, 1},
+		{0x0f04, 0x0f12, 1},
+		{0x0f85, 0x0fd0, 75},
+		{0x0fd1, 0x0fd4, 1},
+		{0x0fd9, 0x0fda, 1},
+		{0x104a, 0x104f, 1},
+		{0x10fb, 0x1361, 614},
+		{0x1362, 0x1368, 1},
+		{0x166d, 0x166e, 1},
+		{0x16eb, 0x16ed, 1},
+		{0x1735, 0x1736, 1},
+		{0x17d4, 0x17d6, 1},
+		{0x17d8, 0x17da, 1},
+		{0x1800, 0x1805, 1},
+		{0x1807, 0x180a, 1},
+		{0x1944, 0x1945, 1},
+		{0x1a1e, 0x1a1f, 1},
+		{0x1aa0, 0x1aa6, 1},
+		{0x1aa8, 0x1aad, 1},
+		{0x1b5a, 0x1b60, 1},
+		{0x1bfc, 0x1bff, 1},
+		{0x1c3b, 0x1c3f, 1},
+		{0x1c7e, 0x1c7f, 1},
+		{0x1cd3, 0x2016, 835},
+		{0x2017, 0x2020, 9},
+		{0x2021, 0x2027, 1},
+		{0x2030, 0x2038, 1},
+		{0x203b, 0x203e, 1},
+		{0x2041, 0x2043, 1},
+		{0x2047, 0x2051, 1},
+		{0x2053, 0x2055, 2},
+		{0x2056, 0x205e, 1},
+		{0x2cf9, 0x2cfc, 1},
+		{0x2cfe, 0x2cff, 1},
+		{0x2d70, 0x2e00, 144},
+		{0x2e01, 0x2e06, 5},
+		{0x2e07, 0x2e08, 1},
+		{0x2e0b, 0x2e0e, 3},
+		{0x2e0f, 0x2e16, 1},
+		{0x2e18, 0x2e19, 1},
+		{0x2e1b, 0x2e1e, 3},
+		{0x2e1f, 0x2e2a, 11},
+		{0x2e2b, 0x2e2e, 1},
+		{0x2e30, 0x2e31, 1},
+		{0x3001, 0x3003, 1},
+		{0x303d, 0x30fb, 190},
+		{0xa4fe, 0xa4ff, 1},
+		{0xa60d, 0xa60f, 1},
+		{0xa673, 0xa67e, 11},
+		{0xa6f2, 0xa6f7, 1},
+		{0xa874, 0xa877, 1},
+		{0xa8ce, 0xa8cf, 1},
+		{0xa8f8, 0xa8fa, 1},
+		{0xa92e, 0xa92f, 1},
+		{0xa95f, 0xa9c1, 98},
+		{0xa9c2, 0xa9cd, 1},
+		{0xa9de, 0xa9df, 1},
+		{0xaa5c, 0xaa5f, 1},
+		{0xaade, 0xaadf, 1},
+		{0xabeb, 0xfe10, 21029},
+		{0xfe11, 0xfe16, 1},
+		{0xfe19, 0xfe30, 23},
+		{0xfe45, 0xfe46, 1},
+		{0xfe49, 0xfe4c, 1},
+		{0xfe50, 0xfe52, 1},
+		{0xfe54, 0xfe57, 1},
+		{0xfe5f, 0xfe61, 1},
+		{0xfe68, 0xfe6a, 2},
+		{0xfe6b, 0xff01, 150},
+		{0xff02, 0xff03, 1},
+		{0xff05, 0xff07, 1},
+		{0xff0a, 0xff0e, 2},
+		{0xff0f, 0xff1a, 11},
+		{0xff1b, 0xff1f, 4},
+		{0xff20, 0xff3c, 28},
+		{0xff61, 0xff64, 3},
+		{0xff65, 0xff65, 1},
+	},
+	R32: []Range32{
+		{0x10100, 0x10100, 1},
+		{0x10101, 0x1039f, 670},
+		{0x103d0, 0x10857, 1159},
+		{0x1091f, 0x1093f, 32},
+		{0x10a50, 0x10a58, 1},
+		{0x10a7f, 0x10b39, 186},
+		{0x10b3a, 0x10b3f, 1},
+		{0x11047, 0x1104d, 1},
+		{0x110bb, 0x110bc, 1},
+		{0x110be, 0x110c1, 1},
+		{0x12470, 0x12473, 1},
+	},
+}
+
+var _Ps = &RangeTable{
+	R16: []Range16{
+		{0x0028, 0x005b, 51},
+		{0x007b, 0x0f3a, 3775},
+		{0x0f3c, 0x169b, 1887},
+		{0x201a, 0x201e, 4},
+		{0x2045, 0x207d, 56},
+		{0x208d, 0x2329, 668},
+		{0x2768, 0x2774, 2},
+		{0x27c5, 0x27e6, 33},
+		{0x27e8, 0x27ee, 2},
+		{0x2983, 0x2997, 2},
+		{0x29d8, 0x29da, 2},
+		{0x29fc, 0x2e22, 1062},
+		{0x2e24, 0x2e28, 2},
+		{0x3008, 0x3010, 2},
+		{0x3014, 0x301a, 2},
+		{0x301d, 0xfd3e, 52513},
+		{0xfe17, 0xfe35, 30},
+		{0xfe37, 0xfe43, 2},
+		{0xfe47, 0xfe59, 18},
+		{0xfe5b, 0xfe5d, 2},
+		{0xff08, 0xff3b, 51},
+		{0xff5b, 0xff5f, 4},
+		{0xff62, 0xff62, 1},
+	},
+}
+
+var _S = &RangeTable{
+	R16: []Range16{
+		{0x0024, 0x002b, 7},
+		{0x003c, 0x003e, 1},
+		{0x005e, 0x0060, 2},
+		{0x007c, 0x007e, 2},
+		{0x00a2, 0x00a9, 1},
+		{0x00ac, 0x00ae, 2},
+		{0x00af, 0x00b1, 1},
+		{0x00b4, 0x00b8, 2},
+		{0x00d7, 0x00f7, 32},
+		{0x02c2, 0x02c5, 1},
+		{0x02d2, 0x02df, 1},
+		{0x02e5, 0x02eb, 1},
+		{0x02ed, 0x02ef, 2},
+		{0x02f0, 0x02ff, 1},
+		{0x0375, 0x0384, 15},
+		{0x0385, 0x03f6, 113},
+		{0x0482, 0x0606, 388},
+		{0x0607, 0x0608, 1},
+		{0x060b, 0x060e, 3},
+		{0x060f, 0x06de, 207},
+		{0x06e9, 0x06fd, 20},
+		{0x06fe, 0x07f6, 248},
+		{0x09f2, 0x09f3, 1},
+		{0x09fa, 0x09fb, 1},
+		{0x0af1, 0x0b70, 127},
+		{0x0bf3, 0x0bfa, 1},
+		{0x0c7f, 0x0d79, 250},
+		{0x0e3f, 0x0f01, 194},
+		{0x0f02, 0x0f03, 1},
+		{0x0f13, 0x0f17, 1},
+		{0x0f1a, 0x0f1f, 1},
+		{0x0f34, 0x0f38, 2},
+		{0x0fbe, 0x0fc5, 1},
+		{0x0fc7, 0x0fcc, 1},
+		{0x0fce, 0x0fcf, 1},
+		{0x0fd5, 0x0fd8, 1},
+		{0x109e, 0x109f, 1},
+		{0x1360, 0x1390, 48},
+		{0x1391, 0x1399, 1},
+		{0x17db, 0x1940, 357},
+		{0x19de, 0x19ff, 1},
+		{0x1b61, 0x1b6a, 1},
+		{0x1b74, 0x1b7c, 1},
+		{0x1fbd, 0x1fbf, 2},
+		{0x1fc0, 0x1fc1, 1},
+		{0x1fcd, 0x1fcf, 1},
+		{0x1fdd, 0x1fdf, 1},
+		{0x1fed, 0x1fef, 1},
+		{0x1ffd, 0x1ffe, 1},
+		{0x2044, 0x2052, 14},
+		{0x207a, 0x207c, 1},
+		{0x208a, 0x208c, 1},
+		{0x20a0, 0x20b9, 1},
+		{0x2100, 0x2101, 1},
+		{0x2103, 0x2106, 1},
+		{0x2108, 0x2109, 1},
+		{0x2114, 0x2116, 2},
+		{0x2117, 0x2118, 1},
+		{0x211e, 0x2123, 1},
+		{0x2125, 0x2129, 2},
+		{0x212e, 0x213a, 12},
+		{0x213b, 0x2140, 5},
+		{0x2141, 0x2144, 1},
+		{0x214a, 0x214d, 1},
+		{0x214f, 0x2190, 65},
+		{0x2191, 0x2328, 1},
+		{0x232b, 0x23f3, 1},
+		{0x2400, 0x2426, 1},
+		{0x2440, 0x244a, 1},
+		{0x249c, 0x24e9, 1},
+		{0x2500, 0x26ff, 1},
+		{0x2701, 0x2767, 1},
+		{0x2794, 0x27c4, 1},
+		{0x27c7, 0x27ca, 1},
+		{0x27cc, 0x27ce, 2},
+		{0x27cf, 0x27e5, 1},
+		{0x27f0, 0x2982, 1},
+		{0x2999, 0x29d7, 1},
+		{0x29dc, 0x29fb, 1},
+		{0x29fe, 0x2b4c, 1},
+		{0x2b50, 0x2b59, 1},
+		{0x2ce5, 0x2cea, 1},
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+		{0x2ff0, 0x2ffb, 1},
+		{0x3004, 0x3012, 14},
+		{0x3013, 0x3020, 13},
+		{0x3036, 0x3037, 1},
+		{0x303e, 0x303f, 1},
+		{0x309b, 0x309c, 1},
+		{0x3190, 0x3191, 1},
+		{0x3196, 0x319f, 1},
+		{0x31c0, 0x31e3, 1},
+		{0x3200, 0x321e, 1},
+		{0x322a, 0x3250, 1},
+		{0x3260, 0x327f, 1},
+		{0x328a, 0x32b0, 1},
+		{0x32c0, 0x32fe, 1},
+		{0x3300, 0x33ff, 1},
+		{0x4dc0, 0x4dff, 1},
+		{0xa490, 0xa4c6, 1},
+		{0xa700, 0xa716, 1},
+		{0xa720, 0xa721, 1},
+		{0xa789, 0xa78a, 1},
+		{0xa828, 0xa82b, 1},
+		{0xa836, 0xa839, 1},
+		{0xaa77, 0xaa79, 1},
+		{0xfb29, 0xfbb2, 137},
+		{0xfbb3, 0xfbc1, 1},
+		{0xfdfc, 0xfdfd, 1},
+		{0xfe62, 0xfe64, 2},
+		{0xfe65, 0xfe66, 1},
+		{0xfe69, 0xff04, 155},
+		{0xff0b, 0xff1c, 17},
+		{0xff1d, 0xff1e, 1},
+		{0xff3e, 0xff40, 2},
+		{0xff5c, 0xff5e, 2},
+		{0xffe0, 0xffe6, 1},
+		{0xffe8, 0xffee, 1},
+		{0xfffc, 0xfffd, 1},
+	},
+	R32: []Range32{
+		{0x10102, 0x10137, 53},
+		{0x10138, 0x1013f, 1},
+		{0x10179, 0x10189, 1},
+		{0x10190, 0x1019b, 1},
+		{0x101d0, 0x101fc, 1},
+		{0x1d000, 0x1d0f5, 1},
+		{0x1d100, 0x1d126, 1},
+		{0x1d129, 0x1d164, 1},
+		{0x1d16a, 0x1d16c, 1},
+		{0x1d183, 0x1d184, 1},
+		{0x1d18c, 0x1d1a9, 1},
+		{0x1d1ae, 0x1d1dd, 1},
+		{0x1d200, 0x1d241, 1},
+		{0x1d245, 0x1d300, 187},
+		{0x1d301, 0x1d356, 1},
+		{0x1d6c1, 0x1d6db, 26},
+		{0x1d6fb, 0x1d715, 26},
+		{0x1d735, 0x1d74f, 26},
+		{0x1d76f, 0x1d789, 26},
+		{0x1d7a9, 0x1d7c3, 26},
+		{0x1f000, 0x1f02b, 1},
+		{0x1f030, 0x1f093, 1},
+		{0x1f0a0, 0x1f0ae, 1},
+		{0x1f0b1, 0x1f0be, 1},
+		{0x1f0c1, 0x1f0cf, 1},
+		{0x1f0d1, 0x1f0df, 1},
+		{0x1f110, 0x1f12e, 1},
+		{0x1f130, 0x1f169, 1},
+		{0x1f170, 0x1f19a, 1},
+		{0x1f1e6, 0x1f202, 1},
+		{0x1f210, 0x1f23a, 1},
+		{0x1f240, 0x1f248, 1},
+		{0x1f250, 0x1f251, 1},
+		{0x1f300, 0x1f320, 1},
+		{0x1f330, 0x1f335, 1},
+		{0x1f337, 0x1f37c, 1},
+		{0x1f380, 0x1f393, 1},
+		{0x1f3a0, 0x1f3c4, 1},
+		{0x1f3c6, 0x1f3ca, 1},
+		{0x1f3e0, 0x1f3f0, 1},
+		{0x1f400, 0x1f43e, 1},
+		{0x1f440, 0x1f442, 2},
+		{0x1f443, 0x1f4f7, 1},
+		{0x1f4f9, 0x1f4fc, 1},
+		{0x1f500, 0x1f53d, 1},
+		{0x1f550, 0x1f567, 1},
+		{0x1f5fb, 0x1f5ff, 1},
+		{0x1f601, 0x1f610, 1},
+		{0x1f612, 0x1f614, 1},
+		{0x1f616, 0x1f61c, 2},
+		{0x1f61d, 0x1f61e, 1},
+		{0x1f620, 0x1f625, 1},
+		{0x1f628, 0x1f62b, 1},
+		{0x1f62d, 0x1f630, 3},
+		{0x1f631, 0x1f633, 1},
+		{0x1f635, 0x1f640, 1},
+		{0x1f645, 0x1f64f, 1},
+		{0x1f680, 0x1f6c5, 1},
+		{0x1f700, 0x1f773, 1},
+	},
+}
+
+var _Sc = &RangeTable{
+	R16: []Range16{
+		{0x0024, 0x00a2, 126},
+		{0x00a3, 0x00a5, 1},
+		{0x060b, 0x09f2, 999},
+		{0x09f3, 0x09fb, 8},
+		{0x0af1, 0x0bf9, 264},
+		{0x0e3f, 0x17db, 2460},
+		{0x20a0, 0x20b9, 1},
+		{0xa838, 0xfdfc, 21956},
+		{0xfe69, 0xff04, 155},
+		{0xffe0, 0xffe1, 1},
+		{0xffe5, 0xffe6, 1},
+	},
+}
+
+var _Sk = &RangeTable{
+	R16: []Range16{
+		{0x005e, 0x0060, 2},
+		{0x00a8, 0x00af, 7},
+		{0x00b4, 0x00b8, 4},
+		{0x02c2, 0x02c5, 1},
+		{0x02d2, 0x02df, 1},
+		{0x02e5, 0x02eb, 1},
+		{0x02ed, 0x02ef, 2},
+		{0x02f0, 0x02ff, 1},
+		{0x0375, 0x0384, 15},
+		{0x0385, 0x1fbd, 7224},
+		{0x1fbf, 0x1fc1, 1},
+		{0x1fcd, 0x1fcf, 1},
+		{0x1fdd, 0x1fdf, 1},
+		{0x1fed, 0x1fef, 1},
+		{0x1ffd, 0x1ffe, 1},
+		{0x309b, 0x309c, 1},
+		{0xa700, 0xa716, 1},
+		{0xa720, 0xa721, 1},
+		{0xa789, 0xa78a, 1},
+		{0xfbb2, 0xfbc1, 1},
+		{0xff3e, 0xff40, 2},
+		{0xffe3, 0xffe3, 1},
+	},
+}
+
+var _Sm = &RangeTable{
+	R16: []Range16{
+		{0x002b, 0x003c, 17},
+		{0x003d, 0x003e, 1},
+		{0x007c, 0x007e, 2},
+		{0x00ac, 0x00b1, 5},
+		{0x00d7, 0x00f7, 32},
+		{0x03f6, 0x0606, 528},
+		{0x0607, 0x0608, 1},
+		{0x2044, 0x2052, 14},
+		{0x207a, 0x207c, 1},
+		{0x208a, 0x208c, 1},
+		{0x2118, 0x2140, 40},
+		{0x2141, 0x2144, 1},
+		{0x214b, 0x2190, 69},
+		{0x2191, 0x2194, 1},
+		{0x219a, 0x219b, 1},
+		{0x21a0, 0x21a6, 3},
+		{0x21ae, 0x21ce, 32},
+		{0x21cf, 0x21d2, 3},
+		{0x21d4, 0x21f4, 32},
+		{0x21f5, 0x22ff, 1},
+		{0x2308, 0x230b, 1},
+		{0x2320, 0x2321, 1},
+		{0x237c, 0x239b, 31},
+		{0x239c, 0x23b3, 1},
+		{0x23dc, 0x23e1, 1},
+		{0x25b7, 0x25c1, 10},
+		{0x25f8, 0x25ff, 1},
+		{0x266f, 0x27c0, 337},
+		{0x27c1, 0x27c4, 1},
+		{0x27c7, 0x27ca, 1},
+		{0x27cc, 0x27ce, 2},
+		{0x27cf, 0x27e5, 1},
+		{0x27f0, 0x27ff, 1},
+		{0x2900, 0x2982, 1},
+		{0x2999, 0x29d7, 1},
+		{0x29dc, 0x29fb, 1},
+		{0x29fe, 0x2aff, 1},
+		{0x2b30, 0x2b44, 1},
+		{0x2b47, 0x2b4c, 1},
+		{0xfb29, 0xfe62, 825},
+		{0xfe64, 0xfe66, 1},
+		{0xff0b, 0xff1c, 17},
+		{0xff1d, 0xff1e, 1},
+		{0xff5c, 0xff5e, 2},
+		{0xffe2, 0xffe9, 7},
+		{0xffea, 0xffec, 1},
+	},
+	R32: []Range32{
+		{0x1d6c1, 0x1d6db, 26},
+		{0x1d6fb, 0x1d715, 26},
+		{0x1d735, 0x1d74f, 26},
+		{0x1d76f, 0x1d789, 26},
+		{0x1d7a9, 0x1d7c3, 26},
+	},
+}
+
+var _So = &RangeTable{
+	R16: []Range16{
+		{0x00a6, 0x00a7, 1},
+		{0x00a9, 0x00ae, 5},
+		{0x00b0, 0x00b6, 6},
+		{0x0482, 0x060e, 396},
+		{0x060f, 0x06de, 207},
+		{0x06e9, 0x06fd, 20},
+		{0x06fe, 0x07f6, 248},
+		{0x09fa, 0x0b70, 374},
+		{0x0bf3, 0x0bf8, 1},
+		{0x0bfa, 0x0c7f, 133},
+		{0x0d79, 0x0f01, 392},
+		{0x0f02, 0x0f03, 1},
+		{0x0f13, 0x0f17, 1},
+		{0x0f1a, 0x0f1f, 1},
+		{0x0f34, 0x0f38, 2},
+		{0x0fbe, 0x0fc5, 1},
+		{0x0fc7, 0x0fcc, 1},
+		{0x0fce, 0x0fcf, 1},
+		{0x0fd5, 0x0fd8, 1},
+		{0x109e, 0x109f, 1},
+		{0x1360, 0x1390, 48},
+		{0x1391, 0x1399, 1},
+		{0x1940, 0x19de, 158},
+		{0x19df, 0x19ff, 1},
+		{0x1b61, 0x1b6a, 1},
+		{0x1b74, 0x1b7c, 1},
+		{0x2100, 0x2101, 1},
+		{0x2103, 0x2106, 1},
+		{0x2108, 0x2109, 1},
+		{0x2114, 0x2116, 2},
+		{0x2117, 0x211e, 7},
+		{0x211f, 0x2123, 1},
+		{0x2125, 0x2129, 2},
+		{0x212e, 0x213a, 12},
+		{0x213b, 0x214a, 15},
+		{0x214c, 0x214d, 1},
+		{0x214f, 0x2195, 70},
+		{0x2196, 0x2199, 1},
+		{0x219c, 0x219f, 1},
+		{0x21a1, 0x21a2, 1},
+		{0x21a4, 0x21a5, 1},
+		{0x21a7, 0x21ad, 1},
+		{0x21af, 0x21cd, 1},
+		{0x21d0, 0x21d1, 1},
+		{0x21d3, 0x21d5, 2},
+		{0x21d6, 0x21f3, 1},
+		{0x2300, 0x2307, 1},
+		{0x230c, 0x231f, 1},
+		{0x2322, 0x2328, 1},
+		{0x232b, 0x237b, 1},
+		{0x237d, 0x239a, 1},
+		{0x23b4, 0x23db, 1},
+		{0x23e2, 0x23f3, 1},
+		{0x2400, 0x2426, 1},
+		{0x2440, 0x244a, 1},
+		{0x249c, 0x24e9, 1},
+		{0x2500, 0x25b6, 1},
+		{0x25b8, 0x25c0, 1},
+		{0x25c2, 0x25f7, 1},
+		{0x2600, 0x266e, 1},
+		{0x2670, 0x26ff, 1},
+		{0x2701, 0x2767, 1},
+		{0x2794, 0x27bf, 1},
+		{0x2800, 0x28ff, 1},
+		{0x2b00, 0x2b2f, 1},
+		{0x2b45, 0x2b46, 1},
+		{0x2b50, 0x2b59, 1},
+		{0x2ce5, 0x2cea, 1},
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+		{0x2ff0, 0x2ffb, 1},
+		{0x3004, 0x3012, 14},
+		{0x3013, 0x3020, 13},
+		{0x3036, 0x3037, 1},
+		{0x303e, 0x303f, 1},
+		{0x3190, 0x3191, 1},
+		{0x3196, 0x319f, 1},
+		{0x31c0, 0x31e3, 1},
+		{0x3200, 0x321e, 1},
+		{0x322a, 0x3250, 1},
+		{0x3260, 0x327f, 1},
+		{0x328a, 0x32b0, 1},
+		{0x32c0, 0x32fe, 1},
+		{0x3300, 0x33ff, 1},
+		{0x4dc0, 0x4dff, 1},
+		{0xa490, 0xa4c6, 1},
+		{0xa828, 0xa82b, 1},
+		{0xa836, 0xa837, 1},
+		{0xa839, 0xaa77, 574},
+		{0xaa78, 0xaa79, 1},
+		{0xfdfd, 0xffe4, 487},
+		{0xffe8, 0xffed, 5},
+		{0xffee, 0xfffc, 14},
+		{0xfffd, 0xfffd, 1},
+	},
+	R32: []Range32{
+		{0x10102, 0x10102, 1},
+		{0x10137, 0x1013f, 1},
+		{0x10179, 0x10189, 1},
+		{0x10190, 0x1019b, 1},
+		{0x101d0, 0x101fc, 1},
+		{0x1d000, 0x1d0f5, 1},
+		{0x1d100, 0x1d126, 1},
+		{0x1d129, 0x1d164, 1},
+		{0x1d16a, 0x1d16c, 1},
+		{0x1d183, 0x1d184, 1},
+		{0x1d18c, 0x1d1a9, 1},
+		{0x1d1ae, 0x1d1dd, 1},
+		{0x1d200, 0x1d241, 1},
+		{0x1d245, 0x1d300, 187},
+		{0x1d301, 0x1d356, 1},
+		{0x1f000, 0x1f02b, 1},
+		{0x1f030, 0x1f093, 1},
+		{0x1f0a0, 0x1f0ae, 1},
+		{0x1f0b1, 0x1f0be, 1},
+		{0x1f0c1, 0x1f0cf, 1},
+		{0x1f0d1, 0x1f0df, 1},
+		{0x1f110, 0x1f12e, 1},
+		{0x1f130, 0x1f169, 1},
+		{0x1f170, 0x1f19a, 1},
+		{0x1f1e6, 0x1f202, 1},
+		{0x1f210, 0x1f23a, 1},
+		{0x1f240, 0x1f248, 1},
+		{0x1f250, 0x1f251, 1},
+		{0x1f300, 0x1f320, 1},
+		{0x1f330, 0x1f335, 1},
+		{0x1f337, 0x1f37c, 1},
+		{0x1f380, 0x1f393, 1},
+		{0x1f3a0, 0x1f3c4, 1},
+		{0x1f3c6, 0x1f3ca, 1},
+		{0x1f3e0, 0x1f3f0, 1},
+		{0x1f400, 0x1f43e, 1},
+		{0x1f440, 0x1f442, 2},
+		{0x1f443, 0x1f4f7, 1},
+		{0x1f4f9, 0x1f4fc, 1},
+		{0x1f500, 0x1f53d, 1},
+		{0x1f550, 0x1f567, 1},
+		{0x1f5fb, 0x1f5ff, 1},
+		{0x1f601, 0x1f610, 1},
+		{0x1f612, 0x1f614, 1},
+		{0x1f616, 0x1f61c, 2},
+		{0x1f61d, 0x1f61e, 1},
+		{0x1f620, 0x1f625, 1},
+		{0x1f628, 0x1f62b, 1},
+		{0x1f62d, 0x1f630, 3},
+		{0x1f631, 0x1f633, 1},
+		{0x1f635, 0x1f640, 1},
+		{0x1f645, 0x1f64f, 1},
+		{0x1f680, 0x1f6c5, 1},
+		{0x1f700, 0x1f773, 1},
+	},
+}
+
+var _Z = &RangeTable{
+	R16: []Range16{
+		{0x0020, 0x00a0, 128},
+		{0x1680, 0x180e, 398},
+		{0x2000, 0x200a, 1},
+		{0x2028, 0x2029, 1},
+		{0x202f, 0x205f, 48},
+		{0x3000, 0x3000, 1},
+	},
+}
+
+var _Zl = &RangeTable{
+	R16: []Range16{
+		{0x2028, 0x2028, 1},
+	},
+}
+
+var _Zp = &RangeTable{
+	R16: []Range16{
+		{0x2029, 0x2029, 1},
+	},
+}
+
+var _Zs = &RangeTable{
+	R16: []Range16{
+		{0x0020, 0x00a0, 128},
+		{0x1680, 0x180e, 398},
+		{0x2000, 0x200a, 1},
+		{0x202f, 0x205f, 48},
+		{0x3000, 0x3000, 1},
 	},
 }
 
@@ -2757,262 +2757,186 @@ var (
 
 // Scripts is the set of Unicode script tables.
 var Scripts = map[string]*RangeTable{
-	"Katakana":               Katakana,
-	"Malayalam":              Malayalam,
-	"Phags_Pa":               Phags_Pa,
-	"Inscriptional_Parthian": Inscriptional_Parthian,
-	"Latin":                  Latin,
-	"Inscriptional_Pahlavi":  Inscriptional_Pahlavi,
-	"Osmanya":                Osmanya,
-	"Khmer":                  Khmer,
-	"Inherited":              Inherited,
-	"Telugu":                 Telugu,
-	"Samaritan":              Samaritan,
+	"Arabic":                 Arabic,
+	"Armenian":               Armenian,
+	"Avestan":                Avestan,
+	"Balinese":               Balinese,
+	"Bamum":                  Bamum,
+	"Batak":                  Batak,
+	"Bengali":                Bengali,
 	"Bopomofo":               Bopomofo,
-	"Imperial_Aramaic":       Imperial_Aramaic,
-	"Kaithi":                 Kaithi,
-	"Mandaic":                Mandaic,
-	"Old_South_Arabian":      Old_South_Arabian,
-	"Kayah_Li":               Kayah_Li,
-	"New_Tai_Lue":            New_Tai_Lue,
-	"Tai_Le":                 Tai_Le,
-	"Kharoshthi":             Kharoshthi,
-	"Common":                 Common,
-	"Kannada":                Kannada,
-	"Old_Turkic":             Old_Turkic,
-	"Tamil":                  Tamil,
-	"Tagalog":                Tagalog,
 	"Brahmi":                 Brahmi,
-	"Arabic":                 Arabic,
-	"Tagbanwa":               Tagbanwa,
+	"Braille":                Braille,
+	"Buginese":               Buginese,
+	"Buhid":                  Buhid,
 	"Canadian_Aboriginal":    Canadian_Aboriginal,
-	"Tibetan":                Tibetan,
+	"Carian":                 Carian,
+	"Cham":                   Cham,
+	"Cherokee":               Cherokee,
+	"Common":                 Common,
 	"Coptic":                 Coptic,
-	"Hiragana":               Hiragana,
-	"Limbu":                  Limbu,
+	"Cuneiform":              Cuneiform,
+	"Cypriot":                Cypriot,
+	"Cyrillic":               Cyrillic,
+	"Deseret":                Deseret,
+	"Devanagari":             Devanagari,
 	"Egyptian_Hieroglyphs":   Egyptian_Hieroglyphs,
-	"Avestan":                Avestan,
-	"Myanmar":                Myanmar,
-	"Armenian":               Armenian,
-	"Sinhala":                Sinhala,
-	"Bengali":                Bengali,
+	"Ethiopic":               Ethiopic,
+	"Georgian":               Georgian,
+	"Glagolitic":             Glagolitic,
+	"Gothic":                 Gothic,
 	"Greek":                  Greek,
-	"Cham":                   Cham,
-	"Hebrew":                 Hebrew,
-	"Meetei_Mayek":           Meetei_Mayek,
-	"Saurashtra":             Saurashtra,
+	"Gujarati":               Gujarati,
+	"Gurmukhi":               Gurmukhi,
+	"Han":                    Han,
 	"Hangul":                 Hangul,
-	"Runic":                  Runic,
-	"Deseret":                Deseret,
-	"Lisu":                   Lisu,
-	"Sundanese":              Sundanese,
-	"Glagolitic":             Glagolitic,
-	"Oriya":                  Oriya,
-	"Buhid":                  Buhid,
-	"Ethiopic":               Ethiopic,
+	"Hanunoo":                Hanunoo,
+	"Hebrew":                 Hebrew,
+	"Hiragana":               Hiragana,
+	"Imperial_Aramaic":       Imperial_Aramaic,
+	"Inherited":              Inherited,
+	"Inscriptional_Pahlavi":  Inscriptional_Pahlavi,
+	"Inscriptional_Parthian": Inscriptional_Parthian,
 	"Javanese":               Javanese,
-	"Syloti_Nagri":           Syloti_Nagri,
-	"Vai":                    Vai,
-	"Cherokee":               Cherokee,
+	"Kaithi":                 Kaithi,
+	"Kannada":                Kannada,
+	"Katakana":               Katakana,
+	"Kayah_Li":               Kayah_Li,
+	"Kharoshthi":             Kharoshthi,
+	"Khmer":                  Khmer,
+	"Lao":                    Lao,
+	"Latin":                  Latin,
+	"Lepcha":                 Lepcha,
+	"Limbu":                  Limbu,
+	"Linear_B":               Linear_B,
+	"Lisu":                   Lisu,
+	"Lycian":                 Lycian,
+	"Lydian":                 Lydian,
+	"Malayalam":              Malayalam,
+	"Mandaic":                Mandaic,
+	"Meetei_Mayek":           Meetei_Mayek,
+	"Mongolian":              Mongolian,
+	"Myanmar":                Myanmar,
+	"New_Tai_Lue":            New_Tai_Lue,
+	"Nko":                    Nko,
 	"Ogham":                  Ogham,
-	"Batak":                  Batak,
-	"Syriac":                 Syriac,
-	"Gurmukhi":               Gurmukhi,
-	"Tai_Tham":               Tai_Tham,
 	"Ol_Chiki":               Ol_Chiki,
-	"Mongolian":              Mongolian,
-	"Hanunoo":                Hanunoo,
-	"Cypriot":                Cypriot,
-	"Buginese":               Buginese,
-	"Bamum":                  Bamum,
-	"Lepcha":                 Lepcha,
-	"Thaana":                 Thaana,
+	"Old_Italic":             Old_Italic,
 	"Old_Persian":            Old_Persian,
-	"Cuneiform":              Cuneiform,
+	"Old_South_Arabian":      Old_South_Arabian,
+	"Old_Turkic":             Old_Turkic,
+	"Oriya":                  Oriya,
+	"Osmanya":                Osmanya,
+	"Phags_Pa":               Phags_Pa,
+	"Phoenician":             Phoenician,
 	"Rejang":                 Rejang,
-	"Georgian":               Georgian,
+	"Runic":                  Runic,
+	"Samaritan":              Samaritan,
+	"Saurashtra":             Saurashtra,
 	"Shavian":                Shavian,
-	"Lycian":                 Lycian,
-	"Nko":                    Nko,
-	"Yi":                     Yi,
-	"Lao":                    Lao,
-	"Linear_B":               Linear_B,
-	"Old_Italic":             Old_Italic,
+	"Sinhala":                Sinhala,
+	"Sundanese":              Sundanese,
+	"Syloti_Nagri":           Syloti_Nagri,
+	"Syriac":                 Syriac,
+	"Tagalog":                Tagalog,
+	"Tagbanwa":               Tagbanwa,
+	"Tai_Le":                 Tai_Le,
+	"Tai_Tham":               Tai_Tham,
 	"Tai_Viet":               Tai_Viet,
-	"Devanagari":             Devanagari,
-	"Lydian":                 Lydian,
+	"Tamil":                  Tamil,
+	"Telugu":                 Telugu,
+	"Thaana":                 Thaana,
+	"Thai":                   Thai,
+	"Tibetan":                Tibetan,
 	"Tifinagh":               Tifinagh,
 	"Ugaritic":               Ugaritic,
-	"Thai":                   Thai,
-	"Cyrillic":               Cyrillic,
-	"Gujarati":               Gujarati,
-	"Carian":                 Carian,
-	"Phoenician":             Phoenician,
-	"Balinese":               Balinese,
-	"Braille":                Braille,
-	"Han":                    Han,
-	"Gothic":                 Gothic,
-}
-
-var _Katakana = &RangeTable{
-	R16: []Range16{
-		{0x30a1, 0x30fa, 1},
-		{0x30fd, 0x30ff, 1},
-		{0x31f0, 0x31ff, 1},
-		{0x32d0, 0x32fe, 1},
-		{0x3300, 0x3357, 1},
-		{0xff66, 0xff6f, 1},
-		{0xff71, 0xff9d, 1},
-	},
-	R32: []Range32{
-		{0x1b000, 0x1b000, 1},
-	},
-}
-
-var _Malayalam = &RangeTable{
-	R16: []Range16{
-		{0x0d02, 0x0d03, 1},
-		{0x0d05, 0x0d0c, 1},
-		{0x0d0e, 0x0d10, 1},
-		{0x0d12, 0x0d3a, 1},
-		{0x0d3d, 0x0d44, 1},
-		{0x0d46, 0x0d48, 1},
-		{0x0d4a, 0x0d4e, 1},
-		{0x0d57, 0x0d57, 1},
-		{0x0d60, 0x0d63, 1},
-		{0x0d66, 0x0d75, 1},
-		{0x0d79, 0x0d7f, 1},
-	},
+	"Vai":                    Vai,
+	"Yi":                     Yi,
 }
 
-var _Phags_Pa = &RangeTable{
+var _Arabic = &RangeTable{
 	R16: []Range16{
-		{0xa840, 0xa877, 1},
+		{0x0600, 0x0603, 1},
+		{0x0606, 0x060b, 1},
+		{0x060d, 0x061a, 1},
+		{0x061e, 0x061e, 1},
+		{0x0620, 0x063f, 1},
+		{0x0641, 0x064a, 1},
+		{0x0656, 0x065e, 1},
+		{0x066a, 0x066f, 1},
+		{0x0671, 0x06dc, 1},
+		{0x06de, 0x06ff, 1},
+		{0x0750, 0x077f, 1},
+		{0xfb50, 0xfbc1, 1},
+		{0xfbd3, 0xfd3d, 1},
+		{0xfd50, 0xfd8f, 1},
+		{0xfd92, 0xfdc7, 1},
+		{0xfdf0, 0xfdfc, 1},
+		{0xfe70, 0xfe74, 1},
+		{0xfe76, 0xfefc, 1},
 	},
-}
-
-var _Inscriptional_Parthian = &RangeTable{
-	R16: []Range16{},
 	R32: []Range32{
-		{0x10b40, 0x10b55, 1},
-		{0x10b58, 0x10b5f, 1},
+		{0x10e60, 0x10e7e, 1},
 	},
 }
 
-var _Latin = &RangeTable{
+var _Armenian = &RangeTable{
 	R16: []Range16{
-		{0x0041, 0x005a, 1},
-		{0x0061, 0x007a, 1},
-		{0x00aa, 0x00aa, 1},
-		{0x00ba, 0x00ba, 1},
-		{0x00c0, 0x00d6, 1},
-		{0x00d8, 0x00f6, 1},
-		{0x00f8, 0x02b8, 1},
-		{0x02e0, 0x02e4, 1},
-		{0x1d00, 0x1d25, 1},
-		{0x1d2c, 0x1d5c, 1},
-		{0x1d62, 0x1d65, 1},
-		{0x1d6b, 0x1d77, 1},
-		{0x1d79, 0x1dbe, 1},
-		{0x1e00, 0x1eff, 1},
-		{0x2071, 0x2071, 1},
-		{0x207f, 0x207f, 1},
-		{0x2090, 0x209c, 1},
-		{0x212a, 0x212b, 1},
-		{0x2132, 0x2132, 1},
-		{0x214e, 0x214e, 1},
-		{0x2160, 0x2188, 1},
-		{0x2c60, 0x2c7f, 1},
-		{0xa722, 0xa787, 1},
-		{0xa78b, 0xa78e, 1},
-		{0xa790, 0xa791, 1},
-		{0xa7a0, 0xa7a9, 1},
-		{0xa7fa, 0xa7ff, 1},
-		{0xfb00, 0xfb06, 1},
-		{0xff21, 0xff3a, 1},
-		{0xff41, 0xff5a, 1},
-	},
-}
-
-var _Inscriptional_Pahlavi = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10b60, 0x10b72, 1},
-		{0x10b78, 0x10b7f, 1},
+		{0x0531, 0x0556, 1},
+		{0x0559, 0x055f, 1},
+		{0x0561, 0x0587, 1},
+		{0x058a, 0x058a, 1},
+		{0xfb13, 0xfb17, 1},
 	},
 }
 
-var _Osmanya = &RangeTable{
+var _Avestan = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x10480, 0x1049d, 1},
-		{0x104a0, 0x104a9, 1},
+		{0x10b00, 0x10b35, 1},
+		{0x10b39, 0x10b3f, 1},
 	},
 }
 
-var _Khmer = &RangeTable{
-	R16: []Range16{
-		{0x1780, 0x17dd, 1},
-		{0x17e0, 0x17e9, 1},
-		{0x17f0, 0x17f9, 1},
-		{0x19e0, 0x19ff, 1},
+var _Balinese = &RangeTable{
+	R16: []Range16{
+		{0x1b00, 0x1b4b, 1},
+		{0x1b50, 0x1b7c, 1},
 	},
 }
 
-var _Inherited = &RangeTable{
+var _Bamum = &RangeTable{
 	R16: []Range16{
-		{0x0300, 0x036f, 1},
-		{0x0485, 0x0486, 1},
-		{0x064b, 0x0655, 1},
-		{0x065f, 0x065f, 1},
-		{0x0670, 0x0670, 1},
-		{0x0951, 0x0952, 1},
-		{0x1cd0, 0x1cd2, 1},
-		{0x1cd4, 0x1ce0, 1},
-		{0x1ce2, 0x1ce8, 1},
-		{0x1ced, 0x1ced, 1},
-		{0x1dc0, 0x1de6, 1},
-		{0x1dfc, 0x1dff, 1},
-		{0x200c, 0x200d, 1},
-		{0x20d0, 0x20f0, 1},
-		{0x302a, 0x302d, 1},
-		{0x3099, 0x309a, 1},
-		{0xfe00, 0xfe0f, 1},
-		{0xfe20, 0xfe26, 1},
+		{0xa6a0, 0xa6f7, 1},
 	},
 	R32: []Range32{
-		{0x101fd, 0x101fd, 1},
-		{0x1d167, 0x1d169, 1},
-		{0x1d17b, 0x1d182, 1},
-		{0x1d185, 0x1d18b, 1},
-		{0x1d1aa, 0x1d1ad, 1},
-		{0xe0100, 0xe01ef, 1},
+		{0x16800, 0x16a38, 1},
 	},
 }
 
-var _Telugu = &RangeTable{
+var _Batak = &RangeTable{
 	R16: []Range16{
-		{0x0c01, 0x0c03, 1},
-		{0x0c05, 0x0c0c, 1},
-		{0x0c0e, 0x0c10, 1},
-		{0x0c12, 0x0c28, 1},
-		{0x0c2a, 0x0c33, 1},
-		{0x0c35, 0x0c39, 1},
-		{0x0c3d, 0x0c44, 1},
-		{0x0c46, 0x0c48, 1},
-		{0x0c4a, 0x0c4d, 1},
-		{0x0c55, 0x0c56, 1},
-		{0x0c58, 0x0c59, 1},
-		{0x0c60, 0x0c63, 1},
-		{0x0c66, 0x0c6f, 1},
-		{0x0c78, 0x0c7f, 1},
+		{0x1bc0, 0x1bf3, 1},
+		{0x1bfc, 0x1bff, 1},
 	},
 }
 
-var _Samaritan = &RangeTable{
+var _Bengali = &RangeTable{
 	R16: []Range16{
-		{0x0800, 0x082d, 1},
-		{0x0830, 0x083e, 1},
+		{0x0981, 0x0983, 1},
+		{0x0985, 0x098c, 1},
+		{0x098f, 0x0990, 1},
+		{0x0993, 0x09a8, 1},
+		{0x09aa, 0x09b0, 1},
+		{0x09b2, 0x09b2, 1},
+		{0x09b6, 0x09b9, 1},
+		{0x09bc, 0x09c4, 1},
+		{0x09c7, 0x09c8, 1},
+		{0x09cb, 0x09ce, 1},
+		{0x09d7, 0x09d7, 1},
+		{0x09dc, 0x09dd, 1},
+		{0x09df, 0x09e3, 1},
+		{0x09e6, 0x09fb, 1},
 	},
 }
 
@@ -3024,68 +2948,59 @@ var _Bopomofo = &RangeTable{
 	},
 }
 
-var _Imperial_Aramaic = &RangeTable{
+var _Brahmi = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x10840, 0x10855, 1},
-		{0x10857, 0x1085f, 1},
+		{0x11000, 0x1104d, 1},
+		{0x11052, 0x1106f, 1},
 	},
 }
 
-var _Kaithi = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x11080, 0x110c1, 1},
+var _Braille = &RangeTable{
+	R16: []Range16{
+		{0x2800, 0x28ff, 1},
 	},
 }
 
-var _Mandaic = &RangeTable{
+var _Buginese = &RangeTable{
 	R16: []Range16{
-		{0x0840, 0x085b, 1},
-		{0x085e, 0x085e, 1},
+		{0x1a00, 0x1a1b, 1},
+		{0x1a1e, 0x1a1f, 1},
 	},
 }
 
-var _Old_South_Arabian = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10a60, 0x10a7f, 1},
+var _Buhid = &RangeTable{
+	R16: []Range16{
+		{0x1740, 0x1753, 1},
 	},
 }
 
-var _Kayah_Li = &RangeTable{
+var _Canadian_Aboriginal = &RangeTable{
 	R16: []Range16{
-		{0xa900, 0xa92f, 1},
+		{0x1400, 0x167f, 1},
+		{0x18b0, 0x18f5, 1},
 	},
 }
 
-var _New_Tai_Lue = &RangeTable{
-	R16: []Range16{
-		{0x1980, 0x19ab, 1},
-		{0x19b0, 0x19c9, 1},
-		{0x19d0, 0x19da, 1},
-		{0x19de, 0x19df, 1},
+var _Carian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x102a0, 0x102d0, 1},
 	},
 }
 
-var _Tai_Le = &RangeTable{
+var _Cham = &RangeTable{
 	R16: []Range16{
-		{0x1950, 0x196d, 1},
-		{0x1970, 0x1974, 1},
+		{0xaa00, 0xaa36, 1},
+		{0xaa40, 0xaa4d, 1},
+		{0xaa50, 0xaa59, 1},
+		{0xaa5c, 0xaa5f, 1},
 	},
 }
 
-var _Kharoshthi = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10a00, 0x10a03, 1},
-		{0x10a05, 0x10a06, 1},
-		{0x10a0c, 0x10a13, 1},
-		{0x10a15, 0x10a17, 1},
-		{0x10a19, 0x10a33, 1},
-		{0x10a38, 0x10a3a, 1},
-		{0x10a3f, 0x10a47, 1},
-		{0x10a50, 0x10a58, 1},
+var _Cherokee = &RangeTable{
+	R16: []Range16{
+		{0x13a0, 0x13f4, 1},
 	},
 }
 
@@ -3265,147 +3180,62 @@ var _Common = &RangeTable{
 	},
 }
 
-var _Kannada = &RangeTable{
+var _Coptic = &RangeTable{
 	R16: []Range16{
-		{0x0c82, 0x0c83, 1},
-		{0x0c85, 0x0c8c, 1},
-		{0x0c8e, 0x0c90, 1},
-		{0x0c92, 0x0ca8, 1},
-		{0x0caa, 0x0cb3, 1},
-		{0x0cb5, 0x0cb9, 1},
-		{0x0cbc, 0x0cc4, 1},
-		{0x0cc6, 0x0cc8, 1},
-		{0x0cca, 0x0ccd, 1},
-		{0x0cd5, 0x0cd6, 1},
-		{0x0cde, 0x0cde, 1},
-		{0x0ce0, 0x0ce3, 1},
-		{0x0ce6, 0x0cef, 1},
-		{0x0cf1, 0x0cf2, 1},
+		{0x03e2, 0x03ef, 1},
+		{0x2c80, 0x2cf1, 1},
+		{0x2cf9, 0x2cff, 1},
 	},
 }
 
-var _Old_Turkic = &RangeTable{
+var _Cuneiform = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x10c00, 0x10c48, 1},
-	},
-}
-
-var _Tamil = &RangeTable{
-	R16: []Range16{
-		{0x0b82, 0x0b83, 1},
-		{0x0b85, 0x0b8a, 1},
-		{0x0b8e, 0x0b90, 1},
-		{0x0b92, 0x0b95, 1},
-		{0x0b99, 0x0b9a, 1},
-		{0x0b9c, 0x0b9c, 1},
-		{0x0b9e, 0x0b9f, 1},
-		{0x0ba3, 0x0ba4, 1},
-		{0x0ba8, 0x0baa, 1},
-		{0x0bae, 0x0bb9, 1},
-		{0x0bbe, 0x0bc2, 1},
-		{0x0bc6, 0x0bc8, 1},
-		{0x0bca, 0x0bcd, 1},
-		{0x0bd0, 0x0bd0, 1},
-		{0x0bd7, 0x0bd7, 1},
-		{0x0be6, 0x0bfa, 1},
-	},
-}
-
-var _Tagalog = &RangeTable{
-	R16: []Range16{
-		{0x1700, 0x170c, 1},
-		{0x170e, 0x1714, 1},
+		{0x12000, 0x1236e, 1},
+		{0x12400, 0x12462, 1},
+		{0x12470, 0x12473, 1},
 	},
 }
 
-var _Brahmi = &RangeTable{
+var _Cypriot = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x11000, 0x1104d, 1},
-		{0x11052, 0x1106f, 1},
-	},
-}
-
-var _Arabic = &RangeTable{
-	R16: []Range16{
-		{0x0600, 0x0603, 1},
-		{0x0606, 0x060b, 1},
-		{0x060d, 0x061a, 1},
-		{0x061e, 0x061e, 1},
-		{0x0620, 0x063f, 1},
-		{0x0641, 0x064a, 1},
-		{0x0656, 0x065e, 1},
-		{0x066a, 0x066f, 1},
-		{0x0671, 0x06dc, 1},
-		{0x06de, 0x06ff, 1},
-		{0x0750, 0x077f, 1},
-		{0xfb50, 0xfbc1, 1},
-		{0xfbd3, 0xfd3d, 1},
-		{0xfd50, 0xfd8f, 1},
-		{0xfd92, 0xfdc7, 1},
-		{0xfdf0, 0xfdfc, 1},
-		{0xfe70, 0xfe74, 1},
-		{0xfe76, 0xfefc, 1},
-	},
-	R32: []Range32{
-		{0x10e60, 0x10e7e, 1},
-	},
-}
-
-var _Tagbanwa = &RangeTable{
-	R16: []Range16{
-		{0x1760, 0x176c, 1},
-		{0x176e, 0x1770, 1},
-		{0x1772, 0x1773, 1},
-	},
-}
-
-var _Canadian_Aboriginal = &RangeTable{
-	R16: []Range16{
-		{0x1400, 0x167f, 1},
-		{0x18b0, 0x18f5, 1},
-	},
-}
-
-var _Tibetan = &RangeTable{
-	R16: []Range16{
-		{0x0f00, 0x0f47, 1},
-		{0x0f49, 0x0f6c, 1},
-		{0x0f71, 0x0f97, 1},
-		{0x0f99, 0x0fbc, 1},
-		{0x0fbe, 0x0fcc, 1},
-		{0x0fce, 0x0fd4, 1},
-		{0x0fd9, 0x0fda, 1},
+		{0x10800, 0x10805, 1},
+		{0x10808, 0x10808, 1},
+		{0x1080a, 0x10835, 1},
+		{0x10837, 0x10838, 1},
+		{0x1083c, 0x1083c, 1},
+		{0x1083f, 0x1083f, 1},
 	},
 }
 
-var _Coptic = &RangeTable{
+var _Cyrillic = &RangeTable{
 	R16: []Range16{
-		{0x03e2, 0x03ef, 1},
-		{0x2c80, 0x2cf1, 1},
-		{0x2cf9, 0x2cff, 1},
+		{0x0400, 0x0484, 1},
+		{0x0487, 0x0527, 1},
+		{0x1d2b, 0x1d2b, 1},
+		{0x1d78, 0x1d78, 1},
+		{0x2de0, 0x2dff, 1},
+		{0xa640, 0xa673, 1},
+		{0xa67c, 0xa697, 1},
 	},
 }
 
-var _Hiragana = &RangeTable{
-	R16: []Range16{
-		{0x3041, 0x3096, 1},
-		{0x309d, 0x309f, 1},
-	},
+var _Deseret = &RangeTable{
+	R16: []Range16{},
 	R32: []Range32{
-		{0x1b001, 0x1b001, 1},
-		{0x1f200, 0x1f200, 1},
+		{0x10400, 0x1044f, 1},
 	},
 }
 
-var _Limbu = &RangeTable{
+var _Devanagari = &RangeTable{
 	R16: []Range16{
-		{0x1900, 0x191c, 1},
-		{0x1920, 0x192b, 1},
-		{0x1930, 0x193b, 1},
-		{0x1940, 0x1940, 1},
-		{0x1944, 0x194f, 1},
+		{0x0900, 0x0950, 1},
+		{0x0953, 0x0963, 1},
+		{0x0966, 0x096f, 1},
+		{0x0971, 0x0977, 1},
+		{0x0979, 0x097f, 1},
+		{0xa8e0, 0xa8fb, 1},
 	},
 }
 
@@ -3416,63 +3246,63 @@ var _Egyptian_Hieroglyphs = &RangeTable{
 	},
 }
 
-var _Avestan = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10b00, 0x10b35, 1},
-		{0x10b39, 0x10b3f, 1},
-	},
-}
-
-var _Myanmar = &RangeTable{
+var _Ethiopic = &RangeTable{
 	R16: []Range16{
-		{0x1000, 0x109f, 1},
-		{0xaa60, 0xaa7b, 1},
+		{0x1200, 0x1248, 1},
+		{0x124a, 0x124d, 1},
+		{0x1250, 0x1256, 1},
+		{0x1258, 0x1258, 1},
+		{0x125a, 0x125d, 1},
+		{0x1260, 0x1288, 1},
+		{0x128a, 0x128d, 1},
+		{0x1290, 0x12b0, 1},
+		{0x12b2, 0x12b5, 1},
+		{0x12b8, 0x12be, 1},
+		{0x12c0, 0x12c0, 1},
+		{0x12c2, 0x12c5, 1},
+		{0x12c8, 0x12d6, 1},
+		{0x12d8, 0x1310, 1},
+		{0x1312, 0x1315, 1},
+		{0x1318, 0x135a, 1},
+		{0x135d, 0x137c, 1},
+		{0x1380, 0x1399, 1},
+		{0x2d80, 0x2d96, 1},
+		{0x2da0, 0x2da6, 1},
+		{0x2da8, 0x2dae, 1},
+		{0x2db0, 0x2db6, 1},
+		{0x2db8, 0x2dbe, 1},
+		{0x2dc0, 0x2dc6, 1},
+		{0x2dc8, 0x2dce, 1},
+		{0x2dd0, 0x2dd6, 1},
+		{0x2dd8, 0x2dde, 1},
+		{0xab01, 0xab06, 1},
+		{0xab09, 0xab0e, 1},
+		{0xab11, 0xab16, 1},
+		{0xab20, 0xab26, 1},
+		{0xab28, 0xab2e, 1},
 	},
 }
 
-var _Armenian = &RangeTable{
+var _Georgian = &RangeTable{
 	R16: []Range16{
-		{0x0531, 0x0556, 1},
-		{0x0559, 0x055f, 1},
-		{0x0561, 0x0587, 1},
-		{0x058a, 0x058a, 1},
-		{0xfb13, 0xfb17, 1},
+		{0x10a0, 0x10c5, 1},
+		{0x10d0, 0x10fa, 1},
+		{0x10fc, 0x10fc, 1},
+		{0x2d00, 0x2d25, 1},
 	},
 }
 
-var _Sinhala = &RangeTable{
+var _Glagolitic = &RangeTable{
 	R16: []Range16{
-		{0x0d82, 0x0d83, 1},
-		{0x0d85, 0x0d96, 1},
-		{0x0d9a, 0x0db1, 1},
-		{0x0db3, 0x0dbb, 1},
-		{0x0dbd, 0x0dbd, 1},
-		{0x0dc0, 0x0dc6, 1},
-		{0x0dca, 0x0dca, 1},
-		{0x0dcf, 0x0dd4, 1},
-		{0x0dd6, 0x0dd6, 1},
-		{0x0dd8, 0x0ddf, 1},
-		{0x0df2, 0x0df4, 1},
+		{0x2c00, 0x2c2e, 1},
+		{0x2c30, 0x2c5e, 1},
 	},
 }
 
-var _Bengali = &RangeTable{
-	R16: []Range16{
-		{0x0981, 0x0983, 1},
-		{0x0985, 0x098c, 1},
-		{0x098f, 0x0990, 1},
-		{0x0993, 0x09a8, 1},
-		{0x09aa, 0x09b0, 1},
-		{0x09b2, 0x09b2, 1},
-		{0x09b6, 0x09b9, 1},
-		{0x09bc, 0x09c4, 1},
-		{0x09c7, 0x09c8, 1},
-		{0x09cb, 0x09ce, 1},
-		{0x09d7, 0x09d7, 1},
-		{0x09dc, 0x09dd, 1},
-		{0x09df, 0x09e3, 1},
-		{0x09e6, 0x09fb, 1},
+var _Gothic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10330, 0x1034a, 1},
 	},
 }
 
@@ -3516,40 +3346,66 @@ var _Greek = &RangeTable{
 	},
 }
 
-var _Cham = &RangeTable{
+var _Gujarati = &RangeTable{
 	R16: []Range16{
-		{0xaa00, 0xaa36, 1},
-		{0xaa40, 0xaa4d, 1},
-		{0xaa50, 0xaa59, 1},
-		{0xaa5c, 0xaa5f, 1},
+		{0x0a81, 0x0a83, 1},
+		{0x0a85, 0x0a8d, 1},
+		{0x0a8f, 0x0a91, 1},
+		{0x0a93, 0x0aa8, 1},
+		{0x0aaa, 0x0ab0, 1},
+		{0x0ab2, 0x0ab3, 1},
+		{0x0ab5, 0x0ab9, 1},
+		{0x0abc, 0x0ac5, 1},
+		{0x0ac7, 0x0ac9, 1},
+		{0x0acb, 0x0acd, 1},
+		{0x0ad0, 0x0ad0, 1},
+		{0x0ae0, 0x0ae3, 1},
+		{0x0ae6, 0x0aef, 1},
+		{0x0af1, 0x0af1, 1},
 	},
 }
 
-var _Hebrew = &RangeTable{
+var _Gurmukhi = &RangeTable{
 	R16: []Range16{
-		{0x0591, 0x05c7, 1},
-		{0x05d0, 0x05ea, 1},
-		{0x05f0, 0x05f4, 1},
-		{0xfb1d, 0xfb36, 1},
-		{0xfb38, 0xfb3c, 1},
-		{0xfb3e, 0xfb3e, 1},
-		{0xfb40, 0xfb41, 1},
-		{0xfb43, 0xfb44, 1},
-		{0xfb46, 0xfb4f, 1},
+		{0x0a01, 0x0a03, 1},
+		{0x0a05, 0x0a0a, 1},
+		{0x0a0f, 0x0a10, 1},
+		{0x0a13, 0x0a28, 1},
+		{0x0a2a, 0x0a30, 1},
+		{0x0a32, 0x0a33, 1},
+		{0x0a35, 0x0a36, 1},
+		{0x0a38, 0x0a39, 1},
+		{0x0a3c, 0x0a3c, 1},
+		{0x0a3e, 0x0a42, 1},
+		{0x0a47, 0x0a48, 1},
+		{0x0a4b, 0x0a4d, 1},
+		{0x0a51, 0x0a51, 1},
+		{0x0a59, 0x0a5c, 1},
+		{0x0a5e, 0x0a5e, 1},
+		{0x0a66, 0x0a75, 1},
 	},
 }
 
-var _Meetei_Mayek = &RangeTable{
+var _Han = &RangeTable{
 	R16: []Range16{
-		{0xabc0, 0xabed, 1},
-		{0xabf0, 0xabf9, 1},
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+		{0x3005, 0x3005, 1},
+		{0x3007, 0x3007, 1},
+		{0x3021, 0x3029, 1},
+		{0x3038, 0x303b, 1},
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcb, 1},
+		{0xf900, 0xfa2d, 1},
+		{0xfa30, 0xfa6d, 1},
+		{0xfa70, 0xfad9, 1},
 	},
-}
-
-var _Saurashtra = &RangeTable{
-	R16: []Range16{
-		{0xa880, 0xa8c4, 1},
-		{0xa8ce, 0xa8d9, 1},
+	R32: []Range32{
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+		{0x2f800, 0x2fa1d, 1},
 	},
 }
 
@@ -3572,183 +3428,307 @@ var _Hangul = &RangeTable{
 	},
 }
 
-var _Runic = &RangeTable{
-	R16: []Range16{
-		{0x16a0, 0x16ea, 1},
-		{0x16ee, 0x16f0, 1},
+var _Hanunoo = &RangeTable{
+	R16: []Range16{
+		{0x1720, 0x1734, 1},
+	},
+}
+
+var _Hebrew = &RangeTable{
+	R16: []Range16{
+		{0x0591, 0x05c7, 1},
+		{0x05d0, 0x05ea, 1},
+		{0x05f0, 0x05f4, 1},
+		{0xfb1d, 0xfb36, 1},
+		{0xfb38, 0xfb3c, 1},
+		{0xfb3e, 0xfb3e, 1},
+		{0xfb40, 0xfb41, 1},
+		{0xfb43, 0xfb44, 1},
+		{0xfb46, 0xfb4f, 1},
+	},
+}
+
+var _Hiragana = &RangeTable{
+	R16: []Range16{
+		{0x3041, 0x3096, 1},
+		{0x309d, 0x309f, 1},
+	},
+	R32: []Range32{
+		{0x1b001, 0x1b001, 1},
+		{0x1f200, 0x1f200, 1},
+	},
+}
+
+var _Imperial_Aramaic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10840, 0x10855, 1},
+		{0x10857, 0x1085f, 1},
+	},
+}
+
+var _Inherited = &RangeTable{
+	R16: []Range16{
+		{0x0300, 0x036f, 1},
+		{0x0485, 0x0486, 1},
+		{0x064b, 0x0655, 1},
+		{0x065f, 0x065f, 1},
+		{0x0670, 0x0670, 1},
+		{0x0951, 0x0952, 1},
+		{0x1cd0, 0x1cd2, 1},
+		{0x1cd4, 0x1ce0, 1},
+		{0x1ce2, 0x1ce8, 1},
+		{0x1ced, 0x1ced, 1},
+		{0x1dc0, 0x1de6, 1},
+		{0x1dfc, 0x1dff, 1},
+		{0x200c, 0x200d, 1},
+		{0x20d0, 0x20f0, 1},
+		{0x302a, 0x302d, 1},
+		{0x3099, 0x309a, 1},
+		{0xfe00, 0xfe0f, 1},
+		{0xfe20, 0xfe26, 1},
+	},
+	R32: []Range32{
+		{0x101fd, 0x101fd, 1},
+		{0x1d167, 0x1d169, 1},
+		{0x1d17b, 0x1d182, 1},
+		{0x1d185, 0x1d18b, 1},
+		{0x1d1aa, 0x1d1ad, 1},
+		{0xe0100, 0xe01ef, 1},
+	},
+}
+
+var _Inscriptional_Pahlavi = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10b60, 0x10b72, 1},
+		{0x10b78, 0x10b7f, 1},
 	},
 }
 
-var _Deseret = &RangeTable{
+var _Inscriptional_Parthian = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x10400, 0x1044f, 1},
+		{0x10b40, 0x10b55, 1},
+		{0x10b58, 0x10b5f, 1},
 	},
 }
 
-var _Lisu = &RangeTable{
+var _Javanese = &RangeTable{
 	R16: []Range16{
-		{0xa4d0, 0xa4ff, 1},
+		{0xa980, 0xa9cd, 1},
+		{0xa9cf, 0xa9d9, 1},
+		{0xa9de, 0xa9df, 1},
 	},
 }
 
-var _Sundanese = &RangeTable{
-	R16: []Range16{
-		{0x1b80, 0x1baa, 1},
-		{0x1bae, 0x1bb9, 1},
+var _Kaithi = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x11080, 0x110c1, 1},
 	},
 }
 
-var _Glagolitic = &RangeTable{
+var _Kannada = &RangeTable{
 	R16: []Range16{
-		{0x2c00, 0x2c2e, 1},
-		{0x2c30, 0x2c5e, 1},
+		{0x0c82, 0x0c83, 1},
+		{0x0c85, 0x0c8c, 1},
+		{0x0c8e, 0x0c90, 1},
+		{0x0c92, 0x0ca8, 1},
+		{0x0caa, 0x0cb3, 1},
+		{0x0cb5, 0x0cb9, 1},
+		{0x0cbc, 0x0cc4, 1},
+		{0x0cc6, 0x0cc8, 1},
+		{0x0cca, 0x0ccd, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0cde, 0x0cde, 1},
+		{0x0ce0, 0x0ce3, 1},
+		{0x0ce6, 0x0cef, 1},
+		{0x0cf1, 0x0cf2, 1},
 	},
 }
 
-var _Oriya = &RangeTable{
+var _Katakana = &RangeTable{
 	R16: []Range16{
-		{0x0b01, 0x0b03, 1},
-		{0x0b05, 0x0b0c, 1},
-		{0x0b0f, 0x0b10, 1},
-		{0x0b13, 0x0b28, 1},
-		{0x0b2a, 0x0b30, 1},
-		{0x0b32, 0x0b33, 1},
-		{0x0b35, 0x0b39, 1},
-		{0x0b3c, 0x0b44, 1},
-		{0x0b47, 0x0b48, 1},
-		{0x0b4b, 0x0b4d, 1},
-		{0x0b56, 0x0b57, 1},
-		{0x0b5c, 0x0b5d, 1},
-		{0x0b5f, 0x0b63, 1},
-		{0x0b66, 0x0b77, 1},
+		{0x30a1, 0x30fa, 1},
+		{0x30fd, 0x30ff, 1},
+		{0x31f0, 0x31ff, 1},
+		{0x32d0, 0x32fe, 1},
+		{0x3300, 0x3357, 1},
+		{0xff66, 0xff6f, 1},
+		{0xff71, 0xff9d, 1},
+	},
+	R32: []Range32{
+		{0x1b000, 0x1b000, 1},
 	},
 }
 
-var _Buhid = &RangeTable{
+var _Kayah_Li = &RangeTable{
 	R16: []Range16{
-		{0x1740, 0x1753, 1},
+		{0xa900, 0xa92f, 1},
 	},
 }
 
-var _Ethiopic = &RangeTable{
-	R16: []Range16{
-		{0x1200, 0x1248, 1},
-		{0x124a, 0x124d, 1},
-		{0x1250, 0x1256, 1},
-		{0x1258, 0x1258, 1},
-		{0x125a, 0x125d, 1},
-		{0x1260, 0x1288, 1},
-		{0x128a, 0x128d, 1},
-		{0x1290, 0x12b0, 1},
-		{0x12b2, 0x12b5, 1},
-		{0x12b8, 0x12be, 1},
-		{0x12c0, 0x12c0, 1},
-		{0x12c2, 0x12c5, 1},
-		{0x12c8, 0x12d6, 1},
-		{0x12d8, 0x1310, 1},
-		{0x1312, 0x1315, 1},
-		{0x1318, 0x135a, 1},
-		{0x135d, 0x137c, 1},
-		{0x1380, 0x1399, 1},
-		{0x2d80, 0x2d96, 1},
-		{0x2da0, 0x2da6, 1},
-		{0x2da8, 0x2dae, 1},
-		{0x2db0, 0x2db6, 1},
-		{0x2db8, 0x2dbe, 1},
-		{0x2dc0, 0x2dc6, 1},
-		{0x2dc8, 0x2dce, 1},
-		{0x2dd0, 0x2dd6, 1},
-		{0x2dd8, 0x2dde, 1},
-		{0xab01, 0xab06, 1},
-		{0xab09, 0xab0e, 1},
-		{0xab11, 0xab16, 1},
-		{0xab20, 0xab26, 1},
-		{0xab28, 0xab2e, 1},
+var _Kharoshthi = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10a00, 0x10a03, 1},
+		{0x10a05, 0x10a06, 1},
+		{0x10a0c, 0x10a13, 1},
+		{0x10a15, 0x10a17, 1},
+		{0x10a19, 0x10a33, 1},
+		{0x10a38, 0x10a3a, 1},
+		{0x10a3f, 0x10a47, 1},
+		{0x10a50, 0x10a58, 1},
 	},
 }
 
-var _Javanese = &RangeTable{
+var _Khmer = &RangeTable{
 	R16: []Range16{
-		{0xa980, 0xa9cd, 1},
-		{0xa9cf, 0xa9d9, 1},
-		{0xa9de, 0xa9df, 1},
+		{0x1780, 0x17dd, 1},
+		{0x17e0, 0x17e9, 1},
+		{0x17f0, 0x17f9, 1},
+		{0x19e0, 0x19ff, 1},
 	},
 }
 
-var _Syloti_Nagri = &RangeTable{
+var _Lao = &RangeTable{
 	R16: []Range16{
-		{0xa800, 0xa82b, 1},
+		{0x0e81, 0x0e82, 1},
+		{0x0e84, 0x0e84, 1},
+		{0x0e87, 0x0e88, 1},
+		{0x0e8a, 0x0e8a, 1},
+		{0x0e8d, 0x0e8d, 1},
+		{0x0e94, 0x0e97, 1},
+		{0x0e99, 0x0e9f, 1},
+		{0x0ea1, 0x0ea3, 1},
+		{0x0ea5, 0x0ea5, 1},
+		{0x0ea7, 0x0ea7, 1},
+		{0x0eaa, 0x0eab, 1},
+		{0x0ead, 0x0eb9, 1},
+		{0x0ebb, 0x0ebd, 1},
+		{0x0ec0, 0x0ec4, 1},
+		{0x0ec6, 0x0ec6, 1},
+		{0x0ec8, 0x0ecd, 1},
+		{0x0ed0, 0x0ed9, 1},
+		{0x0edc, 0x0edd, 1},
 	},
 }
 
-var _Vai = &RangeTable{
+var _Latin = &RangeTable{
 	R16: []Range16{
-		{0xa500, 0xa62b, 1},
+		{0x0041, 0x005a, 1},
+		{0x0061, 0x007a, 1},
+		{0x00aa, 0x00aa, 1},
+		{0x00ba, 0x00ba, 1},
+		{0x00c0, 0x00d6, 1},
+		{0x00d8, 0x00f6, 1},
+		{0x00f8, 0x02b8, 1},
+		{0x02e0, 0x02e4, 1},
+		{0x1d00, 0x1d25, 1},
+		{0x1d2c, 0x1d5c, 1},
+		{0x1d62, 0x1d65, 1},
+		{0x1d6b, 0x1d77, 1},
+		{0x1d79, 0x1dbe, 1},
+		{0x1e00, 0x1eff, 1},
+		{0x2071, 0x2071, 1},
+		{0x207f, 0x207f, 1},
+		{0x2090, 0x209c, 1},
+		{0x212a, 0x212b, 1},
+		{0x2132, 0x2132, 1},
+		{0x214e, 0x214e, 1},
+		{0x2160, 0x2188, 1},
+		{0x2c60, 0x2c7f, 1},
+		{0xa722, 0xa787, 1},
+		{0xa78b, 0xa78e, 1},
+		{0xa790, 0xa791, 1},
+		{0xa7a0, 0xa7a9, 1},
+		{0xa7fa, 0xa7ff, 1},
+		{0xfb00, 0xfb06, 1},
+		{0xff21, 0xff3a, 1},
+		{0xff41, 0xff5a, 1},
 	},
 }
 
-var _Cherokee = &RangeTable{
+var _Lepcha = &RangeTable{
 	R16: []Range16{
-		{0x13a0, 0x13f4, 1},
+		{0x1c00, 0x1c37, 1},
+		{0x1c3b, 0x1c49, 1},
+		{0x1c4d, 0x1c4f, 1},
 	},
 }
 
-var _Ogham = &RangeTable{
+var _Limbu = &RangeTable{
 	R16: []Range16{
-		{0x1680, 0x169c, 1},
+		{0x1900, 0x191c, 1},
+		{0x1920, 0x192b, 1},
+		{0x1930, 0x193b, 1},
+		{0x1940, 0x1940, 1},
+		{0x1944, 0x194f, 1},
 	},
 }
 
-var _Batak = &RangeTable{
-	R16: []Range16{
-		{0x1bc0, 0x1bf3, 1},
-		{0x1bfc, 0x1bff, 1},
+var _Linear_B = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10000, 0x1000b, 1},
+		{0x1000d, 0x10026, 1},
+		{0x10028, 0x1003a, 1},
+		{0x1003c, 0x1003d, 1},
+		{0x1003f, 0x1004d, 1},
+		{0x10050, 0x1005d, 1},
+		{0x10080, 0x100fa, 1},
 	},
 }
 
-var _Syriac = &RangeTable{
+var _Lisu = &RangeTable{
 	R16: []Range16{
-		{0x0700, 0x070d, 1},
-		{0x070f, 0x074a, 1},
-		{0x074d, 0x074f, 1},
+		{0xa4d0, 0xa4ff, 1},
 	},
 }
 
-var _Gurmukhi = &RangeTable{
+var _Lycian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10280, 0x1029c, 1},
+	},
+}
+
+var _Lydian = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10920, 0x10939, 1},
+		{0x1093f, 0x1093f, 1},
+	},
+}
+
+var _Malayalam = &RangeTable{
 	R16: []Range16{
-		{0x0a01, 0x0a03, 1},
-		{0x0a05, 0x0a0a, 1},
-		{0x0a0f, 0x0a10, 1},
-		{0x0a13, 0x0a28, 1},
-		{0x0a2a, 0x0a30, 1},
-		{0x0a32, 0x0a33, 1},
-		{0x0a35, 0x0a36, 1},
-		{0x0a38, 0x0a39, 1},
-		{0x0a3c, 0x0a3c, 1},
-		{0x0a3e, 0x0a42, 1},
-		{0x0a47, 0x0a48, 1},
-		{0x0a4b, 0x0a4d, 1},
-		{0x0a51, 0x0a51, 1},
-		{0x0a59, 0x0a5c, 1},
-		{0x0a5e, 0x0a5e, 1},
-		{0x0a66, 0x0a75, 1},
+		{0x0d02, 0x0d03, 1},
+		{0x0d05, 0x0d0c, 1},
+		{0x0d0e, 0x0d10, 1},
+		{0x0d12, 0x0d3a, 1},
+		{0x0d3d, 0x0d44, 1},
+		{0x0d46, 0x0d48, 1},
+		{0x0d4a, 0x0d4e, 1},
+		{0x0d57, 0x0d57, 1},
+		{0x0d60, 0x0d63, 1},
+		{0x0d66, 0x0d75, 1},
+		{0x0d79, 0x0d7f, 1},
 	},
 }
 
-var _Tai_Tham = &RangeTable{
+var _Mandaic = &RangeTable{
 	R16: []Range16{
-		{0x1a20, 0x1a5e, 1},
-		{0x1a60, 0x1a7c, 1},
-		{0x1a7f, 0x1a89, 1},
-		{0x1a90, 0x1a99, 1},
-		{0x1aa0, 0x1aad, 1},
+		{0x0840, 0x085b, 1},
+		{0x085e, 0x085e, 1},
 	},
 }
 
-var _Ol_Chiki = &RangeTable{
+var _Meetei_Mayek = &RangeTable{
 	R16: []Range16{
-		{0x1c50, 0x1c7f, 1},
+		{0xabc0, 0xabed, 1},
+		{0xabf0, 0xabf9, 1},
 	},
 }
 
@@ -3763,673 +3743,459 @@ var _Mongolian = &RangeTable{
 	},
 }
 
-var _Hanunoo = &RangeTable{
+var _Myanmar = &RangeTable{
 	R16: []Range16{
-		{0x1720, 0x1734, 1},
-	},
-}
-
-var _Cypriot = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10800, 0x10805, 1},
-		{0x10808, 0x10808, 1},
-		{0x1080a, 0x10835, 1},
-		{0x10837, 0x10838, 1},
-		{0x1083c, 0x1083c, 1},
-		{0x1083f, 0x1083f, 1},
+		{0x1000, 0x109f, 1},
+		{0xaa60, 0xaa7b, 1},
 	},
 }
 
-var _Buginese = &RangeTable{
+var _New_Tai_Lue = &RangeTable{
 	R16: []Range16{
-		{0x1a00, 0x1a1b, 1},
-		{0x1a1e, 0x1a1f, 1},
+		{0x1980, 0x19ab, 1},
+		{0x19b0, 0x19c9, 1},
+		{0x19d0, 0x19da, 1},
+		{0x19de, 0x19df, 1},
 	},
 }
 
-var _Bamum = &RangeTable{
+var _Nko = &RangeTable{
 	R16: []Range16{
-		{0xa6a0, 0xa6f7, 1},
-	},
-	R32: []Range32{
-		{0x16800, 0x16a38, 1},
+		{0x07c0, 0x07fa, 1},
 	},
 }
 
-var _Lepcha = &RangeTable{
+var _Ogham = &RangeTable{
 	R16: []Range16{
-		{0x1c00, 0x1c37, 1},
-		{0x1c3b, 0x1c49, 1},
-		{0x1c4d, 0x1c4f, 1},
+		{0x1680, 0x169c, 1},
 	},
 }
 
-var _Thaana = &RangeTable{
+var _Ol_Chiki = &RangeTable{
 	R16: []Range16{
-		{0x0780, 0x07b1, 1},
+		{0x1c50, 0x1c7f, 1},
 	},
 }
 
-var _Old_Persian = &RangeTable{
+var _Old_Italic = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x103a0, 0x103c3, 1},
-		{0x103c8, 0x103d5, 1},
+		{0x10300, 0x1031e, 1},
+		{0x10320, 0x10323, 1},
 	},
 }
 
-var _Cuneiform = &RangeTable{
+var _Old_Persian = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x12000, 0x1236e, 1},
-		{0x12400, 0x12462, 1},
-		{0x12470, 0x12473, 1},
-	},
-}
-
-var _Rejang = &RangeTable{
-	R16: []Range16{
-		{0xa930, 0xa953, 1},
-		{0xa95f, 0xa95f, 1},
-	},
-}
-
-var _Georgian = &RangeTable{
-	R16: []Range16{
-		{0x10a0, 0x10c5, 1},
-		{0x10d0, 0x10fa, 1},
-		{0x10fc, 0x10fc, 1},
-		{0x2d00, 0x2d25, 1},
+		{0x103a0, 0x103c3, 1},
+		{0x103c8, 0x103d5, 1},
 	},
 }
 
-var _Shavian = &RangeTable{
+var _Old_South_Arabian = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x10450, 0x1047f, 1},
+		{0x10a60, 0x10a7f, 1},
 	},
 }
 
-var _Lycian = &RangeTable{
+var _Old_Turkic = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x10280, 0x1029c, 1},
+		{0x10c00, 0x10c48, 1},
 	},
 }
 
-var _Nko = &RangeTable{
+var _Oriya = &RangeTable{
 	R16: []Range16{
-		{0x07c0, 0x07fa, 1},
+		{0x0b01, 0x0b03, 1},
+		{0x0b05, 0x0b0c, 1},
+		{0x0b0f, 0x0b10, 1},
+		{0x0b13, 0x0b28, 1},
+		{0x0b2a, 0x0b30, 1},
+		{0x0b32, 0x0b33, 1},
+		{0x0b35, 0x0b39, 1},
+		{0x0b3c, 0x0b44, 1},
+		{0x0b47, 0x0b48, 1},
+		{0x0b4b, 0x0b4d, 1},
+		{0x0b56, 0x0b57, 1},
+		{0x0b5c, 0x0b5d, 1},
+		{0x0b5f, 0x0b63, 1},
+		{0x0b66, 0x0b77, 1},
 	},
 }
 
-var _Yi = &RangeTable{
-	R16: []Range16{
-		{0xa000, 0xa48c, 1},
-		{0xa490, 0xa4c6, 1},
+var _Osmanya = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10480, 0x1049d, 1},
+		{0x104a0, 0x104a9, 1},
 	},
 }
 
-var _Lao = &RangeTable{
+var _Phags_Pa = &RangeTable{
 	R16: []Range16{
-		{0x0e81, 0x0e82, 1},
-		{0x0e84, 0x0e84, 1},
-		{0x0e87, 0x0e88, 1},
-		{0x0e8a, 0x0e8a, 1},
-		{0x0e8d, 0x0e8d, 1},
-		{0x0e94, 0x0e97, 1},
-		{0x0e99, 0x0e9f, 1},
-		{0x0ea1, 0x0ea3, 1},
-		{0x0ea5, 0x0ea5, 1},
-		{0x0ea7, 0x0ea7, 1},
-		{0x0eaa, 0x0eab, 1},
-		{0x0ead, 0x0eb9, 1},
-		{0x0ebb, 0x0ebd, 1},
-		{0x0ec0, 0x0ec4, 1},
-		{0x0ec6, 0x0ec6, 1},
-		{0x0ec8, 0x0ecd, 1},
-		{0x0ed0, 0x0ed9, 1},
-		{0x0edc, 0x0edd, 1},
-	},
-}
-
-var _Linear_B = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10000, 0x1000b, 1},
-		{0x1000d, 0x10026, 1},
-		{0x10028, 0x1003a, 1},
-		{0x1003c, 0x1003d, 1},
-		{0x1003f, 0x1004d, 1},
-		{0x10050, 0x1005d, 1},
-		{0x10080, 0x100fa, 1},
+		{0xa840, 0xa877, 1},
 	},
 }
 
-var _Old_Italic = &RangeTable{
+var _Phoenician = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x10300, 0x1031e, 1},
-		{0x10320, 0x10323, 1},
+		{0x10900, 0x1091b, 1},
+		{0x1091f, 0x1091f, 1},
 	},
 }
 
-var _Tai_Viet = &RangeTable{
+var _Rejang = &RangeTable{
 	R16: []Range16{
-		{0xaa80, 0xaac2, 1},
-		{0xaadb, 0xaadf, 1},
+		{0xa930, 0xa953, 1},
+		{0xa95f, 0xa95f, 1},
 	},
 }
 
-var _Devanagari = &RangeTable{
+var _Runic = &RangeTable{
 	R16: []Range16{
-		{0x0900, 0x0950, 1},
-		{0x0953, 0x0963, 1},
-		{0x0966, 0x096f, 1},
-		{0x0971, 0x0977, 1},
-		{0x0979, 0x097f, 1},
-		{0xa8e0, 0xa8fb, 1},
+		{0x16a0, 0x16ea, 1},
+		{0x16ee, 0x16f0, 1},
 	},
 }
 
-var _Lydian = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10920, 0x10939, 1},
-		{0x1093f, 0x1093f, 1},
+var _Samaritan = &RangeTable{
+	R16: []Range16{
+		{0x0800, 0x082d, 1},
+		{0x0830, 0x083e, 1},
 	},
 }
 
-var _Tifinagh = &RangeTable{
+var _Saurashtra = &RangeTable{
 	R16: []Range16{
-		{0x2d30, 0x2d65, 1},
-		{0x2d6f, 0x2d70, 1},
-		{0x2d7f, 0x2d7f, 1},
+		{0xa880, 0xa8c4, 1},
+		{0xa8ce, 0xa8d9, 1},
 	},
 }
 
-var _Ugaritic = &RangeTable{
+var _Shavian = &RangeTable{
 	R16: []Range16{},
 	R32: []Range32{
-		{0x10380, 0x1039d, 1},
-		{0x1039f, 0x1039f, 1},
-	},
-}
-
-var _Thai = &RangeTable{
-	R16: []Range16{
-		{0x0e01, 0x0e3a, 1},
-		{0x0e40, 0x0e5b, 1},
+		{0x10450, 0x1047f, 1},
 	},
 }
 
-var _Cyrillic = &RangeTable{
+var _Sinhala = &RangeTable{
 	R16: []Range16{
-		{0x0400, 0x0484, 1},
-		{0x0487, 0x0527, 1},
-		{0x1d2b, 0x1d2b, 1},
-		{0x1d78, 0x1d78, 1},
-		{0x2de0, 0x2dff, 1},
-		{0xa640, 0xa673, 1},
-		{0xa67c, 0xa697, 1},
+		{0x0d82, 0x0d83, 1},
+		{0x0d85, 0x0d96, 1},
+		{0x0d9a, 0x0db1, 1},
+		{0x0db3, 0x0dbb, 1},
+		{0x0dbd, 0x0dbd, 1},
+		{0x0dc0, 0x0dc6, 1},
+		{0x0dca, 0x0dca, 1},
+		{0x0dcf, 0x0dd4, 1},
+		{0x0dd6, 0x0dd6, 1},
+		{0x0dd8, 0x0ddf, 1},
+		{0x0df2, 0x0df4, 1},
 	},
 }
 
-var _Gujarati = &RangeTable{
+var _Sundanese = &RangeTable{
 	R16: []Range16{
-		{0x0a81, 0x0a83, 1},
-		{0x0a85, 0x0a8d, 1},
-		{0x0a8f, 0x0a91, 1},
-		{0x0a93, 0x0aa8, 1},
-		{0x0aaa, 0x0ab0, 1},
-		{0x0ab2, 0x0ab3, 1},
-		{0x0ab5, 0x0ab9, 1},
-		{0x0abc, 0x0ac5, 1},
-		{0x0ac7, 0x0ac9, 1},
-		{0x0acb, 0x0acd, 1},
-		{0x0ad0, 0x0ad0, 1},
-		{0x0ae0, 0x0ae3, 1},
-		{0x0ae6, 0x0aef, 1},
-		{0x0af1, 0x0af1, 1},
+		{0x1b80, 0x1baa, 1},
+		{0x1bae, 0x1bb9, 1},
 	},
 }
 
-var _Carian = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x102a0, 0x102d0, 1},
+var _Syloti_Nagri = &RangeTable{
+	R16: []Range16{
+		{0xa800, 0xa82b, 1},
 	},
 }
 
-var _Phoenician = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10900, 0x1091b, 1},
-		{0x1091f, 0x1091f, 1},
+var _Syriac = &RangeTable{
+	R16: []Range16{
+		{0x0700, 0x070d, 1},
+		{0x070f, 0x074a, 1},
+		{0x074d, 0x074f, 1},
 	},
 }
 
-var _Balinese = &RangeTable{
+var _Tagalog = &RangeTable{
 	R16: []Range16{
-		{0x1b00, 0x1b4b, 1},
-		{0x1b50, 0x1b7c, 1},
+		{0x1700, 0x170c, 1},
+		{0x170e, 0x1714, 1},
 	},
 }
 
-var _Braille = &RangeTable{
+var _Tagbanwa = &RangeTable{
 	R16: []Range16{
-		{0x2800, 0x28ff, 1},
+		{0x1760, 0x176c, 1},
+		{0x176e, 0x1770, 1},
+		{0x1772, 0x1773, 1},
 	},
 }
 
-var _Han = &RangeTable{
+var _Tai_Le = &RangeTable{
 	R16: []Range16{
-		{0x2e80, 0x2e99, 1},
-		{0x2e9b, 0x2ef3, 1},
-		{0x2f00, 0x2fd5, 1},
-		{0x3005, 0x3005, 1},
-		{0x3007, 0x3007, 1},
-		{0x3021, 0x3029, 1},
-		{0x3038, 0x303b, 1},
-		{0x3400, 0x4db5, 1},
-		{0x4e00, 0x9fcb, 1},
-		{0xf900, 0xfa2d, 1},
-		{0xfa30, 0xfa6d, 1},
-		{0xfa70, 0xfad9, 1},
-	},
-	R32: []Range32{
-		{0x20000, 0x2a6d6, 1},
-		{0x2a700, 0x2b734, 1},
-		{0x2b740, 0x2b81d, 1},
-		{0x2f800, 0x2fa1d, 1},
+		{0x1950, 0x196d, 1},
+		{0x1970, 0x1974, 1},
 	},
 }
 
-var _Gothic = &RangeTable{
-	R16: []Range16{},
-	R32: []Range32{
-		{0x10330, 0x1034a, 1},
+var _Tai_Tham = &RangeTable{
+	R16: []Range16{
+		{0x1a20, 0x1a5e, 1},
+		{0x1a60, 0x1a7c, 1},
+		{0x1a7f, 0x1a89, 1},
+		{0x1a90, 0x1a99, 1},
+		{0x1aa0, 0x1aad, 1},
 	},
 }
 
-var (
-	Arabic                 = _Arabic                 // Arabic is the set of Unicode characters in script Arabic.
-	Armenian               = _Armenian               // Armenian is the set of Unicode characters in script Armenian.
-	Avestan                = _Avestan                // Avestan is the set of Unicode characters in script Avestan.
-	Balinese               = _Balinese               // Balinese is the set of Unicode characters in script Balinese.
-	Bamum                  = _Bamum                  // Bamum is the set of Unicode characters in script Bamum.
-	Batak                  = _Batak                  // Batak is the set of Unicode characters in script Batak.
-	Bengali                = _Bengali                // Bengali is the set of Unicode characters in script Bengali.
-	Bopomofo               = _Bopomofo               // Bopomofo is the set of Unicode characters in script Bopomofo.
-	Brahmi                 = _Brahmi                 // Brahmi is the set of Unicode characters in script Brahmi.
-	Braille                = _Braille                // Braille is the set of Unicode characters in script Braille.
-	Buginese               = _Buginese               // Buginese is the set of Unicode characters in script Buginese.
-	Buhid                  = _Buhid                  // Buhid is the set of Unicode characters in script Buhid.
-	Canadian_Aboriginal    = _Canadian_Aboriginal    // Canadian_Aboriginal is the set of Unicode characters in script Canadian_Aboriginal.
-	Carian                 = _Carian                 // Carian is the set of Unicode characters in script Carian.
-	Cham                   = _Cham                   // Cham is the set of Unicode characters in script Cham.
-	Cherokee               = _Cherokee               // Cherokee is the set of Unicode characters in script Cherokee.
-	Common                 = _Common                 // Common is the set of Unicode characters in script Common.
-	Coptic                 = _Coptic                 // Coptic is the set of Unicode characters in script Coptic.
-	Cuneiform              = _Cuneiform              // Cuneiform is the set of Unicode characters in script Cuneiform.
-	Cypriot                = _Cypriot                // Cypriot is the set of Unicode characters in script Cypriot.
-	Cyrillic               = _Cyrillic               // Cyrillic is the set of Unicode characters in script Cyrillic.
-	Deseret                = _Deseret                // Deseret is the set of Unicode characters in script Deseret.
-	Devanagari             = _Devanagari             // Devanagari is the set of Unicode characters in script Devanagari.
-	Egyptian_Hieroglyphs   = _Egyptian_Hieroglyphs   // Egyptian_Hieroglyphs is the set of Unicode characters in script Egyptian_Hieroglyphs.
-	Ethiopic               = _Ethiopic               // Ethiopic is the set of Unicode characters in script Ethiopic.
-	Georgian               = _Georgian               // Georgian is the set of Unicode characters in script Georgian.
-	Glagolitic             = _Glagolitic             // Glagolitic is the set of Unicode characters in script Glagolitic.
-	Gothic                 = _Gothic                 // Gothic is the set of Unicode characters in script Gothic.
-	Greek                  = _Greek                  // Greek is the set of Unicode characters in script Greek.
-	Gujarati               = _Gujarati               // Gujarati is the set of Unicode characters in script Gujarati.
-	Gurmukhi               = _Gurmukhi               // Gurmukhi is the set of Unicode characters in script Gurmukhi.
-	Han                    = _Han                    // Han is the set of Unicode characters in script Han.
-	Hangul                 = _Hangul                 // Hangul is the set of Unicode characters in script Hangul.
-	Hanunoo                = _Hanunoo                // Hanunoo is the set of Unicode characters in script Hanunoo.
-	Hebrew                 = _Hebrew                 // Hebrew is the set of Unicode characters in script Hebrew.
-	Hiragana               = _Hiragana               // Hiragana is the set of Unicode characters in script Hiragana.
-	Imperial_Aramaic       = _Imperial_Aramaic       // Imperial_Aramaic is the set of Unicode characters in script Imperial_Aramaic.
-	Inherited              = _Inherited              // Inherited is the set of Unicode characters in script Inherited.
-	Inscriptional_Pahlavi  = _Inscriptional_Pahlavi  // Inscriptional_Pahlavi is the set of Unicode characters in script Inscriptional_Pahlavi.
-	Inscriptional_Parthian = _Inscriptional_Parthian // Inscriptional_Parthian is the set of Unicode characters in script Inscriptional_Parthian.
-	Javanese               = _Javanese               // Javanese is the set of Unicode characters in script Javanese.
-	Kaithi                 = _Kaithi                 // Kaithi is the set of Unicode characters in script Kaithi.
-	Kannada                = _Kannada                // Kannada is the set of Unicode characters in script Kannada.
-	Katakana               = _Katakana               // Katakana is the set of Unicode characters in script Katakana.
-	Kayah_Li               = _Kayah_Li               // Kayah_Li is the set of Unicode characters in script Kayah_Li.
-	Kharoshthi             = _Kharoshthi             // Kharoshthi is the set of Unicode characters in script Kharoshthi.
-	Khmer                  = _Khmer                  // Khmer is the set of Unicode characters in script Khmer.
-	Lao                    = _Lao                    // Lao is the set of Unicode characters in script Lao.
-	Latin                  = _Latin                  // Latin is the set of Unicode characters in script Latin.
-	Lepcha                 = _Lepcha                 // Lepcha is the set of Unicode characters in script Lepcha.
-	Limbu                  = _Limbu                  // Limbu is the set of Unicode characters in script Limbu.
-	Linear_B               = _Linear_B               // Linear_B is the set of Unicode characters in script Linear_B.
-	Lisu                   = _Lisu                   // Lisu is the set of Unicode characters in script Lisu.
-	Lycian                 = _Lycian                 // Lycian is the set of Unicode characters in script Lycian.
-	Lydian                 = _Lydian                 // Lydian is the set of Unicode characters in script Lydian.
-	Malayalam              = _Malayalam              // Malayalam is the set of Unicode characters in script Malayalam.
-	Mandaic                = _Mandaic                // Mandaic is the set of Unicode characters in script Mandaic.
-	Meetei_Mayek           = _Meetei_Mayek           // Meetei_Mayek is the set of Unicode characters in script Meetei_Mayek.
-	Mongolian              = _Mongolian              // Mongolian is the set of Unicode characters in script Mongolian.
-	Myanmar                = _Myanmar                // Myanmar is the set of Unicode characters in script Myanmar.
-	New_Tai_Lue            = _New_Tai_Lue            // New_Tai_Lue is the set of Unicode characters in script New_Tai_Lue.
-	Nko                    = _Nko                    // Nko is the set of Unicode characters in script Nko.
-	Ogham                  = _Ogham                  // Ogham is the set of Unicode characters in script Ogham.
-	Ol_Chiki               = _Ol_Chiki               // Ol_Chiki is the set of Unicode characters in script Ol_Chiki.
-	Old_Italic             = _Old_Italic             // Old_Italic is the set of Unicode characters in script Old_Italic.
-	Old_Persian            = _Old_Persian            // Old_Persian is the set of Unicode characters in script Old_Persian.
-	Old_South_Arabian      = _Old_South_Arabian      // Old_South_Arabian is the set of Unicode characters in script Old_South_Arabian.
-	Old_Turkic             = _Old_Turkic             // Old_Turkic is the set of Unicode characters in script Old_Turkic.
-	Oriya                  = _Oriya                  // Oriya is the set of Unicode characters in script Oriya.
-	Osmanya                = _Osmanya                // Osmanya is the set of Unicode characters in script Osmanya.
-	Phags_Pa               = _Phags_Pa               // Phags_Pa is the set of Unicode characters in script Phags_Pa.
-	Phoenician             = _Phoenician             // Phoenician is the set of Unicode characters in script Phoenician.
-	Rejang                 = _Rejang                 // Rejang is the set of Unicode characters in script Rejang.
-	Runic                  = _Runic                  // Runic is the set of Unicode characters in script Runic.
-	Samaritan              = _Samaritan              // Samaritan is the set of Unicode characters in script Samaritan.
-	Saurashtra             = _Saurashtra             // Saurashtra is the set of Unicode characters in script Saurashtra.
-	Shavian                = _Shavian                // Shavian is the set of Unicode characters in script Shavian.
-	Sinhala                = _Sinhala                // Sinhala is the set of Unicode characters in script Sinhala.
-	Sundanese              = _Sundanese              // Sundanese is the set of Unicode characters in script Sundanese.
-	Syloti_Nagri           = _Syloti_Nagri           // Syloti_Nagri is the set of Unicode characters in script Syloti_Nagri.
-	Syriac                 = _Syriac                 // Syriac is the set of Unicode characters in script Syriac.
-	Tagalog                = _Tagalog                // Tagalog is the set of Unicode characters in script Tagalog.
-	Tagbanwa               = _Tagbanwa               // Tagbanwa is the set of Unicode characters in script Tagbanwa.
-	Tai_Le                 = _Tai_Le                 // Tai_Le is the set of Unicode characters in script Tai_Le.
-	Tai_Tham               = _Tai_Tham               // Tai_Tham is the set of Unicode characters in script Tai_Tham.
-	Tai_Viet               = _Tai_Viet               // Tai_Viet is the set of Unicode characters in script Tai_Viet.
-	Tamil                  = _Tamil                  // Tamil is the set of Unicode characters in script Tamil.
-	Telugu                 = _Telugu                 // Telugu is the set of Unicode characters in script Telugu.
-	Thaana                 = _Thaana                 // Thaana is the set of Unicode characters in script Thaana.
-	Thai                   = _Thai                   // Thai is the set of Unicode characters in script Thai.
-	Tibetan                = _Tibetan                // Tibetan is the set of Unicode characters in script Tibetan.
-	Tifinagh               = _Tifinagh               // Tifinagh is the set of Unicode characters in script Tifinagh.
-	Ugaritic               = _Ugaritic               // Ugaritic is the set of Unicode characters in script Ugaritic.
-	Vai                    = _Vai                    // Vai is the set of Unicode characters in script Vai.
-	Yi                     = _Yi                     // Yi is the set of Unicode characters in script Yi.
-)
-
-// Generated by running
-//	maketables --props=all --url=http://www.unicode.org/Public/6.0.0/ucd/
-// DO NOT EDIT
+var _Tai_Viet = &RangeTable{
+	R16: []Range16{
+		{0xaa80, 0xaac2, 1},
+		{0xaadb, 0xaadf, 1},
+	},
+}
 
-// Properties is the set of Unicode property tables.
-var Properties = map[string]*RangeTable{
-	"Pattern_Syntax":                     Pattern_Syntax,
-	"Other_ID_Start":                     Other_ID_Start,
-	"Pattern_White_Space":                Pattern_White_Space,
-	"Other_Lowercase":                    Other_Lowercase,
-	"Soft_Dotted":                        Soft_Dotted,
-	"Hex_Digit":                          Hex_Digit,
-	"ASCII_Hex_Digit":                    ASCII_Hex_Digit,
-	"Deprecated":                         Deprecated,
-	"Terminal_Punctuation":               Terminal_Punctuation,
-	"Quotation_Mark":                     Quotation_Mark,
-	"Other_ID_Continue":                  Other_ID_Continue,
-	"Bidi_Control":                       Bidi_Control,
-	"Variation_Selector":                 Variation_Selector,
-	"Noncharacter_Code_Point":            Noncharacter_Code_Point,
-	"Other_Math":                         Other_Math,
-	"Unified_Ideograph":                  Unified_Ideograph,
-	"Hyphen":                             Hyphen,
-	"IDS_Binary_Operator":                IDS_Binary_Operator,
-	"Logical_Order_Exception":            Logical_Order_Exception,
-	"Radical":                            Radical,
-	"Other_Uppercase":                    Other_Uppercase,
-	"STerm":                              STerm,
-	"Other_Alphabetic":                   Other_Alphabetic,
-	"Diacritic":                          Diacritic,
-	"Extender":                           Extender,
-	"Join_Control":                       Join_Control,
-	"Ideographic":                        Ideographic,
-	"Dash":                               Dash,
-	"IDS_Trinary_Operator":               IDS_Trinary_Operator,
-	"Other_Grapheme_Extend":              Other_Grapheme_Extend,
-	"Other_Default_Ignorable_Code_Point": Other_Default_Ignorable_Code_Point,
-	"White_Space":                        White_Space,
+var _Tamil = &RangeTable{
+	R16: []Range16{
+		{0x0b82, 0x0b83, 1},
+		{0x0b85, 0x0b8a, 1},
+		{0x0b8e, 0x0b90, 1},
+		{0x0b92, 0x0b95, 1},
+		{0x0b99, 0x0b9a, 1},
+		{0x0b9c, 0x0b9c, 1},
+		{0x0b9e, 0x0b9f, 1},
+		{0x0ba3, 0x0ba4, 1},
+		{0x0ba8, 0x0baa, 1},
+		{0x0bae, 0x0bb9, 1},
+		{0x0bbe, 0x0bc2, 1},
+		{0x0bc6, 0x0bc8, 1},
+		{0x0bca, 0x0bcd, 1},
+		{0x0bd0, 0x0bd0, 1},
+		{0x0bd7, 0x0bd7, 1},
+		{0x0be6, 0x0bfa, 1},
+	},
 }
 
-var _Pattern_Syntax = &RangeTable{
+var _Telugu = &RangeTable{
 	R16: []Range16{
-		{0x0021, 0x002f, 1},
-		{0x003a, 0x0040, 1},
-		{0x005b, 0x005e, 1},
-		{0x0060, 0x0060, 1},
-		{0x007b, 0x007e, 1},
-		{0x00a1, 0x00a7, 1},
-		{0x00a9, 0x00a9, 1},
-		{0x00ab, 0x00ac, 1},
-		{0x00ae, 0x00ae, 1},
-		{0x00b0, 0x00b1, 1},
-		{0x00b6, 0x00b6, 1},
-		{0x00bb, 0x00bb, 1},
-		{0x00bf, 0x00bf, 1},
-		{0x00d7, 0x00d7, 1},
-		{0x00f7, 0x00f7, 1},
-		{0x2010, 0x2027, 1},
-		{0x2030, 0x203e, 1},
-		{0x2041, 0x2053, 1},
-		{0x2055, 0x205e, 1},
-		{0x2190, 0x245f, 1},
-		{0x2500, 0x2775, 1},
-		{0x2794, 0x2bff, 1},
-		{0x2e00, 0x2e7f, 1},
-		{0x3001, 0x3003, 1},
-		{0x3008, 0x3020, 1},
-		{0x3030, 0x3030, 1},
-		{0xfd3e, 0xfd3f, 1},
-		{0xfe45, 0xfe46, 1},
+		{0x0c01, 0x0c03, 1},
+		{0x0c05, 0x0c0c, 1},
+		{0x0c0e, 0x0c10, 1},
+		{0x0c12, 0x0c28, 1},
+		{0x0c2a, 0x0c33, 1},
+		{0x0c35, 0x0c39, 1},
+		{0x0c3d, 0x0c44, 1},
+		{0x0c46, 0x0c48, 1},
+		{0x0c4a, 0x0c4d, 1},
+		{0x0c55, 0x0c56, 1},
+		{0x0c58, 0x0c59, 1},
+		{0x0c60, 0x0c63, 1},
+		{0x0c66, 0x0c6f, 1},
+		{0x0c78, 0x0c7f, 1},
 	},
 }
 
-var _Other_ID_Start = &RangeTable{
+var _Thaana = &RangeTable{
 	R16: []Range16{
-		{0x2118, 0x2118, 1},
-		{0x212e, 0x212e, 1},
-		{0x309b, 0x309c, 1},
+		{0x0780, 0x07b1, 1},
 	},
 }
 
-var _Pattern_White_Space = &RangeTable{
+var _Thai = &RangeTable{
 	R16: []Range16{
-		{0x0009, 0x000d, 1},
-		{0x0020, 0x0020, 1},
-		{0x0085, 0x0085, 1},
-		{0x200e, 0x200f, 1},
-		{0x2028, 0x2029, 1},
+		{0x0e01, 0x0e3a, 1},
+		{0x0e40, 0x0e5b, 1},
 	},
 }
 
-var _Other_Lowercase = &RangeTable{
+var _Tibetan = &RangeTable{
 	R16: []Range16{
-		{0x02b0, 0x02b8, 1},
-		{0x02c0, 0x02c1, 1},
-		{0x02e0, 0x02e4, 1},
-		{0x0345, 0x0345, 1},
-		{0x037a, 0x037a, 1},
-		{0x1d2c, 0x1d61, 1},
-		{0x1d78, 0x1d78, 1},
-		{0x1d9b, 0x1dbf, 1},
-		{0x2090, 0x2094, 1},
-		{0x2170, 0x217f, 1},
-		{0x24d0, 0x24e9, 1},
-		{0x2c7d, 0x2c7d, 1},
-		{0xa770, 0xa770, 1},
+		{0x0f00, 0x0f47, 1},
+		{0x0f49, 0x0f6c, 1},
+		{0x0f71, 0x0f97, 1},
+		{0x0f99, 0x0fbc, 1},
+		{0x0fbe, 0x0fcc, 1},
+		{0x0fce, 0x0fd4, 1},
+		{0x0fd9, 0x0fda, 1},
 	},
 }
 
-var _Soft_Dotted = &RangeTable{
+var _Tifinagh = &RangeTable{
 	R16: []Range16{
-		{0x0069, 0x006a, 1},
-		{0x012f, 0x012f, 1},
-		{0x0249, 0x0249, 1},
-		{0x0268, 0x0268, 1},
-		{0x029d, 0x029d, 1},
-		{0x02b2, 0x02b2, 1},
-		{0x03f3, 0x03f3, 1},
-		{0x0456, 0x0456, 1},
-		{0x0458, 0x0458, 1},
-		{0x1d62, 0x1d62, 1},
-		{0x1d96, 0x1d96, 1},
-		{0x1da4, 0x1da4, 1},
-		{0x1da8, 0x1da8, 1},
-		{0x1e2d, 0x1e2d, 1},
-		{0x1ecb, 0x1ecb, 1},
-		{0x2071, 0x2071, 1},
-		{0x2148, 0x2149, 1},
-		{0x2c7c, 0x2c7c, 1},
-	},
-	R32: []Range32{
-		{0x1d422, 0x1d423, 1},
-		{0x1d456, 0x1d457, 1},
-		{0x1d48a, 0x1d48b, 1},
-		{0x1d4be, 0x1d4bf, 1},
-		{0x1d4f2, 0x1d4f3, 1},
-		{0x1d526, 0x1d527, 1},
-		{0x1d55a, 0x1d55b, 1},
-		{0x1d58e, 0x1d58f, 1},
-		{0x1d5c2, 0x1d5c3, 1},
-		{0x1d5f6, 0x1d5f7, 1},
-		{0x1d62a, 0x1d62b, 1},
-		{0x1d65e, 0x1d65f, 1},
-		{0x1d692, 0x1d693, 1},
+		{0x2d30, 0x2d65, 1},
+		{0x2d6f, 0x2d70, 1},
+		{0x2d7f, 0x2d7f, 1},
 	},
 }
 
-var _Hex_Digit = &RangeTable{
-	R16: []Range16{
-		{0x0030, 0x0039, 1},
-		{0x0041, 0x0046, 1},
-		{0x0061, 0x0066, 1},
-		{0xff10, 0xff19, 1},
-		{0xff21, 0xff26, 1},
-		{0xff41, 0xff46, 1},
+var _Ugaritic = &RangeTable{
+	R16: []Range16{},
+	R32: []Range32{
+		{0x10380, 0x1039d, 1},
+		{0x1039f, 0x1039f, 1},
 	},
 }
 
-var _ASCII_Hex_Digit = &RangeTable{
+var _Vai = &RangeTable{
 	R16: []Range16{
-		{0x0030, 0x0039, 1},
-		{0x0041, 0x0046, 1},
-		{0x0061, 0x0066, 1},
+		{0xa500, 0xa62b, 1},
 	},
 }
 
-var _Deprecated = &RangeTable{
+var _Yi = &RangeTable{
 	R16: []Range16{
-		{0x0149, 0x0149, 1},
-		{0x0673, 0x0673, 1},
-		{0x0f77, 0x0f77, 1},
-		{0x0f79, 0x0f79, 1},
-		{0x17a3, 0x17a4, 1},
-		{0x206a, 0x206f, 1},
-		{0x2329, 0x232a, 1},
-	},
-	R32: []Range32{
-		{0xe0001, 0xe0001, 1},
-		{0xe0020, 0xe007f, 1},
+		{0xa000, 0xa48c, 1},
+		{0xa490, 0xa4c6, 1},
 	},
 }
 
-var _Terminal_Punctuation = &RangeTable{
-	R16: []Range16{
-		{0x0021, 0x0021, 1},
-		{0x002c, 0x002c, 1},
-		{0x002e, 0x002e, 1},
-		{0x003a, 0x003b, 1},
-		{0x003f, 0x003f, 1},
-		{0x037e, 0x037e, 1},
-		{0x0387, 0x0387, 1},
-		{0x0589, 0x0589, 1},
-		{0x05c3, 0x05c3, 1},
-		{0x060c, 0x060c, 1},
-		{0x061b, 0x061b, 1},
-		{0x061f, 0x061f, 1},
-		{0x06d4, 0x06d4, 1},
-		{0x0700, 0x070a, 1},
-		{0x070c, 0x070c, 1},
-		{0x07f8, 0x07f9, 1},
-		{0x0830, 0x083e, 1},
-		{0x085e, 0x085e, 1},
-		{0x0964, 0x0965, 1},
-		{0x0e5a, 0x0e5b, 1},
-		{0x0f08, 0x0f08, 1},
-		{0x0f0d, 0x0f12, 1},
-		{0x104a, 0x104b, 1},
-		{0x1361, 0x1368, 1},
-		{0x166d, 0x166e, 1},
-		{0x16eb, 0x16ed, 1},
-		{0x17d4, 0x17d6, 1},
-		{0x17da, 0x17da, 1},
-		{0x1802, 0x1805, 1},
-		{0x1808, 0x1809, 1},
-		{0x1944, 0x1945, 1},
-		{0x1aa8, 0x1aab, 1},
-		{0x1b5a, 0x1b5b, 1},
-		{0x1b5d, 0x1b5f, 1},
-		{0x1c3b, 0x1c3f, 1},
-		{0x1c7e, 0x1c7f, 1},
-		{0x203c, 0x203d, 1},
-		{0x2047, 0x2049, 1},
-		{0x2e2e, 0x2e2e, 1},
-		{0x3001, 0x3002, 1},
-		{0xa4fe, 0xa4ff, 1},
-		{0xa60d, 0xa60f, 1},
-		{0xa6f3, 0xa6f7, 1},
-		{0xa876, 0xa877, 1},
-		{0xa8ce, 0xa8cf, 1},
-		{0xa92f, 0xa92f, 1},
-		{0xa9c7, 0xa9c9, 1},
-		{0xaa5d, 0xaa5f, 1},
-		{0xaadf, 0xaadf, 1},
-		{0xabeb, 0xabeb, 1},
-		{0xfe50, 0xfe52, 1},
-		{0xfe54, 0xfe57, 1},
-		{0xff01, 0xff01, 1},
-		{0xff0c, 0xff0c, 1},
-		{0xff0e, 0xff0e, 1},
-		{0xff1a, 0xff1b, 1},
-		{0xff1f, 0xff1f, 1},
-		{0xff61, 0xff61, 1},
-		{0xff64, 0xff64, 1},
-	},
-	R32: []Range32{
-		{0x1039f, 0x1039f, 1},
-		{0x103d0, 0x103d0, 1},
-		{0x10857, 0x10857, 1},
-		{0x1091f, 0x1091f, 1},
-		{0x10b3a, 0x10b3f, 1},
-		{0x11047, 0x1104d, 1},
-		{0x110be, 0x110c1, 1},
-		{0x12470, 0x12473, 1},
-	},
-}
+var (
+	Arabic                 = _Arabic                 // Arabic is the set of Unicode characters in script Arabic.
+	Armenian               = _Armenian               // Armenian is the set of Unicode characters in script Armenian.
+	Avestan                = _Avestan                // Avestan is the set of Unicode characters in script Avestan.
+	Balinese               = _Balinese               // Balinese is the set of Unicode characters in script Balinese.
+	Bamum                  = _Bamum                  // Bamum is the set of Unicode characters in script Bamum.
+	Batak                  = _Batak                  // Batak is the set of Unicode characters in script Batak.
+	Bengali                = _Bengali                // Bengali is the set of Unicode characters in script Bengali.
+	Bopomofo               = _Bopomofo               // Bopomofo is the set of Unicode characters in script Bopomofo.
+	Brahmi                 = _Brahmi                 // Brahmi is the set of Unicode characters in script Brahmi.
+	Braille                = _Braille                // Braille is the set of Unicode characters in script Braille.
+	Buginese               = _Buginese               // Buginese is the set of Unicode characters in script Buginese.
+	Buhid                  = _Buhid                  // Buhid is the set of Unicode characters in script Buhid.
+	Canadian_Aboriginal    = _Canadian_Aboriginal    // Canadian_Aboriginal is the set of Unicode characters in script Canadian_Aboriginal.
+	Carian                 = _Carian                 // Carian is the set of Unicode characters in script Carian.
+	Cham                   = _Cham                   // Cham is the set of Unicode characters in script Cham.
+	Cherokee               = _Cherokee               // Cherokee is the set of Unicode characters in script Cherokee.
+	Common                 = _Common                 // Common is the set of Unicode characters in script Common.
+	Coptic                 = _Coptic                 // Coptic is the set of Unicode characters in script Coptic.
+	Cuneiform              = _Cuneiform              // Cuneiform is the set of Unicode characters in script Cuneiform.
+	Cypriot                = _Cypriot                // Cypriot is the set of Unicode characters in script Cypriot.
+	Cyrillic               = _Cyrillic               // Cyrillic is the set of Unicode characters in script Cyrillic.
+	Deseret                = _Deseret                // Deseret is the set of Unicode characters in script Deseret.
+	Devanagari             = _Devanagari             // Devanagari is the set of Unicode characters in script Devanagari.
+	Egyptian_Hieroglyphs   = _Egyptian_Hieroglyphs   // Egyptian_Hieroglyphs is the set of Unicode characters in script Egyptian_Hieroglyphs.
+	Ethiopic               = _Ethiopic               // Ethiopic is the set of Unicode characters in script Ethiopic.
+	Georgian               = _Georgian               // Georgian is the set of Unicode characters in script Georgian.
+	Glagolitic             = _Glagolitic             // Glagolitic is the set of Unicode characters in script Glagolitic.
+	Gothic                 = _Gothic                 // Gothic is the set of Unicode characters in script Gothic.
+	Greek                  = _Greek                  // Greek is the set of Unicode characters in script Greek.
+	Gujarati               = _Gujarati               // Gujarati is the set of Unicode characters in script Gujarati.
+	Gurmukhi               = _Gurmukhi               // Gurmukhi is the set of Unicode characters in script Gurmukhi.
+	Han                    = _Han                    // Han is the set of Unicode characters in script Han.
+	Hangul                 = _Hangul                 // Hangul is the set of Unicode characters in script Hangul.
+	Hanunoo                = _Hanunoo                // Hanunoo is the set of Unicode characters in script Hanunoo.
+	Hebrew                 = _Hebrew                 // Hebrew is the set of Unicode characters in script Hebrew.
+	Hiragana               = _Hiragana               // Hiragana is the set of Unicode characters in script Hiragana.
+	Imperial_Aramaic       = _Imperial_Aramaic       // Imperial_Aramaic is the set of Unicode characters in script Imperial_Aramaic.
+	Inherited              = _Inherited              // Inherited is the set of Unicode characters in script Inherited.
+	Inscriptional_Pahlavi  = _Inscriptional_Pahlavi  // Inscriptional_Pahlavi is the set of Unicode characters in script Inscriptional_Pahlavi.
+	Inscriptional_Parthian = _Inscriptional_Parthian // Inscriptional_Parthian is the set of Unicode characters in script Inscriptional_Parthian.
+	Javanese               = _Javanese               // Javanese is the set of Unicode characters in script Javanese.
+	Kaithi                 = _Kaithi                 // Kaithi is the set of Unicode characters in script Kaithi.
+	Kannada                = _Kannada                // Kannada is the set of Unicode characters in script Kannada.
+	Katakana               = _Katakana               // Katakana is the set of Unicode characters in script Katakana.
+	Kayah_Li               = _Kayah_Li               // Kayah_Li is the set of Unicode characters in script Kayah_Li.
+	Kharoshthi             = _Kharoshthi             // Kharoshthi is the set of Unicode characters in script Kharoshthi.
+	Khmer                  = _Khmer                  // Khmer is the set of Unicode characters in script Khmer.
+	Lao                    = _Lao                    // Lao is the set of Unicode characters in script Lao.
+	Latin                  = _Latin                  // Latin is the set of Unicode characters in script Latin.
+	Lepcha                 = _Lepcha                 // Lepcha is the set of Unicode characters in script Lepcha.
+	Limbu                  = _Limbu                  // Limbu is the set of Unicode characters in script Limbu.
+	Linear_B               = _Linear_B               // Linear_B is the set of Unicode characters in script Linear_B.
+	Lisu                   = _Lisu                   // Lisu is the set of Unicode characters in script Lisu.
+	Lycian                 = _Lycian                 // Lycian is the set of Unicode characters in script Lycian.
+	Lydian                 = _Lydian                 // Lydian is the set of Unicode characters in script Lydian.
+	Malayalam              = _Malayalam              // Malayalam is the set of Unicode characters in script Malayalam.
+	Mandaic                = _Mandaic                // Mandaic is the set of Unicode characters in script Mandaic.
+	Meetei_Mayek           = _Meetei_Mayek           // Meetei_Mayek is the set of Unicode characters in script Meetei_Mayek.
+	Mongolian              = _Mongolian              // Mongolian is the set of Unicode characters in script Mongolian.
+	Myanmar                = _Myanmar                // Myanmar is the set of Unicode characters in script Myanmar.
+	New_Tai_Lue            = _New_Tai_Lue            // New_Tai_Lue is the set of Unicode characters in script New_Tai_Lue.
+	Nko                    = _Nko                    // Nko is the set of Unicode characters in script Nko.
+	Ogham                  = _Ogham                  // Ogham is the set of Unicode characters in script Ogham.
+	Ol_Chiki               = _Ol_Chiki               // Ol_Chiki is the set of Unicode characters in script Ol_Chiki.
+	Old_Italic             = _Old_Italic             // Old_Italic is the set of Unicode characters in script Old_Italic.
+	Old_Persian            = _Old_Persian            // Old_Persian is the set of Unicode characters in script Old_Persian.
+	Old_South_Arabian      = _Old_South_Arabian      // Old_South_Arabian is the set of Unicode characters in script Old_South_Arabian.
+	Old_Turkic             = _Old_Turkic             // Old_Turkic is the set of Unicode characters in script Old_Turkic.
+	Oriya                  = _Oriya                  // Oriya is the set of Unicode characters in script Oriya.
+	Osmanya                = _Osmanya                // Osmanya is the set of Unicode characters in script Osmanya.
+	Phags_Pa               = _Phags_Pa               // Phags_Pa is the set of Unicode characters in script Phags_Pa.
+	Phoenician             = _Phoenician             // Phoenician is the set of Unicode characters in script Phoenician.
+	Rejang                 = _Rejang                 // Rejang is the set of Unicode characters in script Rejang.
+	Runic                  = _Runic                  // Runic is the set of Unicode characters in script Runic.
+	Samaritan              = _Samaritan              // Samaritan is the set of Unicode characters in script Samaritan.
+	Saurashtra             = _Saurashtra             // Saurashtra is the set of Unicode characters in script Saurashtra.
+	Shavian                = _Shavian                // Shavian is the set of Unicode characters in script Shavian.
+	Sinhala                = _Sinhala                // Sinhala is the set of Unicode characters in script Sinhala.
+	Sundanese              = _Sundanese              // Sundanese is the set of Unicode characters in script Sundanese.
+	Syloti_Nagri           = _Syloti_Nagri           // Syloti_Nagri is the set of Unicode characters in script Syloti_Nagri.
+	Syriac                 = _Syriac                 // Syriac is the set of Unicode characters in script Syriac.
+	Tagalog                = _Tagalog                // Tagalog is the set of Unicode characters in script Tagalog.
+	Tagbanwa               = _Tagbanwa               // Tagbanwa is the set of Unicode characters in script Tagbanwa.
+	Tai_Le                 = _Tai_Le                 // Tai_Le is the set of Unicode characters in script Tai_Le.
+	Tai_Tham               = _Tai_Tham               // Tai_Tham is the set of Unicode characters in script Tai_Tham.
+	Tai_Viet               = _Tai_Viet               // Tai_Viet is the set of Unicode characters in script Tai_Viet.
+	Tamil                  = _Tamil                  // Tamil is the set of Unicode characters in script Tamil.
+	Telugu                 = _Telugu                 // Telugu is the set of Unicode characters in script Telugu.
+	Thaana                 = _Thaana                 // Thaana is the set of Unicode characters in script Thaana.
+	Thai                   = _Thai                   // Thai is the set of Unicode characters in script Thai.
+	Tibetan                = _Tibetan                // Tibetan is the set of Unicode characters in script Tibetan.
+	Tifinagh               = _Tifinagh               // Tifinagh is the set of Unicode characters in script Tifinagh.
+	Ugaritic               = _Ugaritic               // Ugaritic is the set of Unicode characters in script Ugaritic.
+	Vai                    = _Vai                    // Vai is the set of Unicode characters in script Vai.
+	Yi                     = _Yi                     // Yi is the set of Unicode characters in script Yi.
+)
 
-var _Quotation_Mark = &RangeTable{
-	R16: []Range16{
-		{0x0022, 0x0022, 1},
-		{0x0027, 0x0027, 1},
-		{0x00ab, 0x00ab, 1},
-		{0x00bb, 0x00bb, 1},
-		{0x2018, 0x201f, 1},
-		{0x2039, 0x203a, 1},
-		{0x300c, 0x300f, 1},
-		{0x301d, 0x301f, 1},
-		{0xfe41, 0xfe44, 1},
-		{0xff02, 0xff02, 1},
-		{0xff07, 0xff07, 1},
-		{0xff62, 0xff63, 1},
-	},
+// Generated by running
+//	maketables --props=all --url=http://www.unicode.org/Public/6.0.0/ucd/
+// DO NOT EDIT
+
+// Properties is the set of Unicode property tables.
+var Properties = map[string]*RangeTable{
+	"ASCII_Hex_Digit":                    ASCII_Hex_Digit,
+	"Bidi_Control":                       Bidi_Control,
+	"Dash":                               Dash,
+	"Deprecated":                         Deprecated,
+	"Diacritic":                          Diacritic,
+	"Extender":                           Extender,
+	"Hex_Digit":                          Hex_Digit,
+	"Hyphen":                             Hyphen,
+	"IDS_Binary_Operator":                IDS_Binary_Operator,
+	"IDS_Trinary_Operator":               IDS_Trinary_Operator,
+	"Ideographic":                        Ideographic,
+	"Join_Control":                       Join_Control,
+	"Logical_Order_Exception":            Logical_Order_Exception,
+	"Noncharacter_Code_Point":            Noncharacter_Code_Point,
+	"Other_Alphabetic":                   Other_Alphabetic,
+	"Other_Default_Ignorable_Code_Point": Other_Default_Ignorable_Code_Point,
+	"Other_Grapheme_Extend":              Other_Grapheme_Extend,
+	"Other_ID_Continue":                  Other_ID_Continue,
+	"Other_ID_Start":                     Other_ID_Start,
+	"Other_Lowercase":                    Other_Lowercase,
+	"Other_Math":                         Other_Math,
+	"Other_Uppercase":                    Other_Uppercase,
+	"Pattern_Syntax":                     Pattern_Syntax,
+	"Pattern_White_Space":                Pattern_White_Space,
+	"Quotation_Mark":                     Quotation_Mark,
+	"Radical":                            Radical,
+	"STerm":                              STerm,
+	"Soft_Dotted":                        Soft_Dotted,
+	"Terminal_Punctuation":               Terminal_Punctuation,
+	"Unified_Ideograph":                  Unified_Ideograph,
+	"Variation_Selector":                 Variation_Selector,
+	"White_Space":                        White_Space,
 }
 
-var _Other_ID_Continue = &RangeTable{
+var _ASCII_Hex_Digit = &RangeTable{
 	R16: []Range16{
-		{0x00b7, 0x00b7, 1},
-		{0x0387, 0x0387, 1},
-		{0x1369, 0x1371, 1},
-		{0x19da, 0x19da, 1},
+		{0x0030, 0x0039, 1},
+		{0x0041, 0x0046, 1},
+		{0x0061, 0x0066, 1},
 	},
 }
 
@@ -4440,164 +4206,203 @@ var _Bidi_Control = &RangeTable{
 	},
 }
 
-var _Variation_Selector = &RangeTable{
+var _Dash = &RangeTable{
 	R16: []Range16{
-		{0x180b, 0x180d, 1},
-		{0xfe00, 0xfe0f, 1},
-	},
-	R32: []Range32{
-		{0xe0100, 0xe01ef, 1},
+		{0x002d, 0x002d, 1},
+		{0x058a, 0x058a, 1},
+		{0x05be, 0x05be, 1},
+		{0x1400, 0x1400, 1},
+		{0x1806, 0x1806, 1},
+		{0x2010, 0x2015, 1},
+		{0x2053, 0x2053, 1},
+		{0x207b, 0x207b, 1},
+		{0x208b, 0x208b, 1},
+		{0x2212, 0x2212, 1},
+		{0x2e17, 0x2e17, 1},
+		{0x2e1a, 0x2e1a, 1},
+		{0x301c, 0x301c, 1},
+		{0x3030, 0x3030, 1},
+		{0x30a0, 0x30a0, 1},
+		{0xfe31, 0xfe32, 1},
+		{0xfe58, 0xfe58, 1},
+		{0xfe63, 0xfe63, 1},
+		{0xff0d, 0xff0d, 1},
 	},
 }
 
-var _Noncharacter_Code_Point = &RangeTable{
+var _Deprecated = &RangeTable{
 	R16: []Range16{
-		{0xfdd0, 0xfdef, 1},
-		{0xfffe, 0xffff, 1},
+		{0x0149, 0x0149, 1},
+		{0x0673, 0x0673, 1},
+		{0x0f77, 0x0f77, 1},
+		{0x0f79, 0x0f79, 1},
+		{0x17a3, 0x17a4, 1},
+		{0x206a, 0x206f, 1},
+		{0x2329, 0x232a, 1},
 	},
 	R32: []Range32{
-		{0x1fffe, 0x1ffff, 1},
-		{0x2fffe, 0x2ffff, 1},
-		{0x3fffe, 0x3ffff, 1},
-		{0x4fffe, 0x4ffff, 1},
-		{0x5fffe, 0x5ffff, 1},
-		{0x6fffe, 0x6ffff, 1},
-		{0x7fffe, 0x7ffff, 1},
-		{0x8fffe, 0x8ffff, 1},
-		{0x9fffe, 0x9ffff, 1},
-		{0xafffe, 0xaffff, 1},
-		{0xbfffe, 0xbffff, 1},
-		{0xcfffe, 0xcffff, 1},
-		{0xdfffe, 0xdffff, 1},
-		{0xefffe, 0xeffff, 1},
-		{0xffffe, 0xfffff, 1},
-		{0x10fffe, 0x10ffff, 1},
+		{0xe0001, 0xe0001, 1},
+		{0xe0020, 0xe007f, 1},
 	},
 }
 
-var _Other_Math = &RangeTable{
+var _Diacritic = &RangeTable{
 	R16: []Range16{
 		{0x005e, 0x005e, 1},
-		{0x03d0, 0x03d2, 1},
-		{0x03d5, 0x03d5, 1},
-		{0x03f0, 0x03f1, 1},
-		{0x03f4, 0x03f5, 1},
-		{0x2016, 0x2016, 1},
-		{0x2032, 0x2034, 1},
-		{0x2040, 0x2040, 1},
-		{0x2061, 0x2064, 1},
-		{0x207d, 0x207e, 1},
-		{0x208d, 0x208e, 1},
-		{0x20d0, 0x20dc, 1},
-		{0x20e1, 0x20e1, 1},
-		{0x20e5, 0x20e6, 1},
-		{0x20eb, 0x20ef, 1},
-		{0x2102, 0x2102, 1},
-		{0x2107, 0x2107, 1},
-		{0x210a, 0x2113, 1},
-		{0x2115, 0x2115, 1},
-		{0x2119, 0x211d, 1},
-		{0x2124, 0x2124, 1},
-		{0x2128, 0x2129, 1},
-		{0x212c, 0x212d, 1},
-		{0x212f, 0x2131, 1},
-		{0x2133, 0x2138, 1},
-		{0x213c, 0x213f, 1},
-		{0x2145, 0x2149, 1},
-		{0x2195, 0x2199, 1},
-		{0x219c, 0x219f, 1},
-		{0x21a1, 0x21a2, 1},
-		{0x21a4, 0x21a5, 1},
-		{0x21a7, 0x21a7, 1},
-		{0x21a9, 0x21ad, 1},
-		{0x21b0, 0x21b1, 1},
-		{0x21b6, 0x21b7, 1},
-		{0x21bc, 0x21cd, 1},
-		{0x21d0, 0x21d1, 1},
-		{0x21d3, 0x21d3, 1},
-		{0x21d5, 0x21db, 1},
-		{0x21dd, 0x21dd, 1},
-		{0x21e4, 0x21e5, 1},
-		{0x23b4, 0x23b5, 1},
-		{0x23b7, 0x23b7, 1},
-		{0x23d0, 0x23d0, 1},
-		{0x23e2, 0x23e2, 1},
-		{0x25a0, 0x25a1, 1},
-		{0x25ae, 0x25b6, 1},
-		{0x25bc, 0x25c0, 1},
-		{0x25c6, 0x25c7, 1},
-		{0x25ca, 0x25cb, 1},
-		{0x25cf, 0x25d3, 1},
-		{0x25e2, 0x25e2, 1},
-		{0x25e4, 0x25e4, 1},
-		{0x25e7, 0x25ec, 1},
-		{0x2605, 0x2606, 1},
-		{0x2640, 0x2640, 1},
-		{0x2642, 0x2642, 1},
-		{0x2660, 0x2663, 1},
-		{0x266d, 0x266e, 1},
-		{0x27c5, 0x27c6, 1},
-		{0x27e6, 0x27ef, 1},
-		{0x2983, 0x2998, 1},
-		{0x29d8, 0x29db, 1},
-		{0x29fc, 0x29fd, 1},
-		{0xfe61, 0xfe61, 1},
-		{0xfe63, 0xfe63, 1},
-		{0xfe68, 0xfe68, 1},
-		{0xff3c, 0xff3c, 1},
+		{0x0060, 0x0060, 1},
+		{0x00a8, 0x00a8, 1},
+		{0x00af, 0x00af, 1},
+		{0x00b4, 0x00b4, 1},
+		{0x00b7, 0x00b8, 1},
+		{0x02b0, 0x034e, 1},
+		{0x0350, 0x0357, 1},
+		{0x035d, 0x0362, 1},
+		{0x0374, 0x0375, 1},
+		{0x037a, 0x037a, 1},
+		{0x0384, 0x0385, 1},
+		{0x0483, 0x0487, 1},
+		{0x0559, 0x0559, 1},
+		{0x0591, 0x05a1, 1},
+		{0x05a3, 0x05bd, 1},
+		{0x05bf, 0x05bf, 1},
+		{0x05c1, 0x05c2, 1},
+		{0x05c4, 0x05c4, 1},
+		{0x064b, 0x0652, 1},
+		{0x0657, 0x0658, 1},
+		{0x06df, 0x06e0, 1},
+		{0x06e5, 0x06e6, 1},
+		{0x06ea, 0x06ec, 1},
+		{0x0730, 0x074a, 1},
+		{0x07a6, 0x07b0, 1},
+		{0x07eb, 0x07f5, 1},
+		{0x0818, 0x0819, 1},
+		{0x093c, 0x093c, 1},
+		{0x094d, 0x094d, 1},
+		{0x0951, 0x0954, 1},
+		{0x0971, 0x0971, 1},
+		{0x09bc, 0x09bc, 1},
+		{0x09cd, 0x09cd, 1},
+		{0x0a3c, 0x0a3c, 1},
+		{0x0a4d, 0x0a4d, 1},
+		{0x0abc, 0x0abc, 1},
+		{0x0acd, 0x0acd, 1},
+		{0x0b3c, 0x0b3c, 1},
+		{0x0b4d, 0x0b4d, 1},
+		{0x0bcd, 0x0bcd, 1},
+		{0x0c4d, 0x0c4d, 1},
+		{0x0cbc, 0x0cbc, 1},
+		{0x0ccd, 0x0ccd, 1},
+		{0x0d4d, 0x0d4d, 1},
+		{0x0dca, 0x0dca, 1},
+		{0x0e47, 0x0e4c, 1},
+		{0x0e4e, 0x0e4e, 1},
+		{0x0ec8, 0x0ecc, 1},
+		{0x0f18, 0x0f19, 1},
+		{0x0f35, 0x0f35, 1},
+		{0x0f37, 0x0f37, 1},
+		{0x0f39, 0x0f39, 1},
+		{0x0f3e, 0x0f3f, 1},
+		{0x0f82, 0x0f84, 1},
+		{0x0f86, 0x0f87, 1},
+		{0x0fc6, 0x0fc6, 1},
+		{0x1037, 0x1037, 1},
+		{0x1039, 0x103a, 1},
+		{0x1087, 0x108d, 1},
+		{0x108f, 0x108f, 1},
+		{0x109a, 0x109b, 1},
+		{0x17c9, 0x17d3, 1},
+		{0x17dd, 0x17dd, 1},
+		{0x1939, 0x193b, 1},
+		{0x1a75, 0x1a7c, 1},
+		{0x1a7f, 0x1a7f, 1},
+		{0x1b34, 0x1b34, 1},
+		{0x1b44, 0x1b44, 1},
+		{0x1b6b, 0x1b73, 1},
+		{0x1baa, 0x1baa, 1},
+		{0x1c36, 0x1c37, 1},
+		{0x1c78, 0x1c7d, 1},
+		{0x1cd0, 0x1ce8, 1},
+		{0x1ced, 0x1ced, 1},
+		{0x1d2c, 0x1d6a, 1},
+		{0x1dc4, 0x1dcf, 1},
+		{0x1dfd, 0x1dff, 1},
+		{0x1fbd, 0x1fbd, 1},
+		{0x1fbf, 0x1fc1, 1},
+		{0x1fcd, 0x1fcf, 1},
+		{0x1fdd, 0x1fdf, 1},
+		{0x1fed, 0x1fef, 1},
+		{0x1ffd, 0x1ffe, 1},
+		{0x2cef, 0x2cf1, 1},
+		{0x2e2f, 0x2e2f, 1},
+		{0x302a, 0x302f, 1},
+		{0x3099, 0x309c, 1},
+		{0x30fc, 0x30fc, 1},
+		{0xa66f, 0xa66f, 1},
+		{0xa67c, 0xa67d, 1},
+		{0xa67f, 0xa67f, 1},
+		{0xa6f0, 0xa6f1, 1},
+		{0xa717, 0xa721, 1},
+		{0xa788, 0xa788, 1},
+		{0xa8c4, 0xa8c4, 1},
+		{0xa8e0, 0xa8f1, 1},
+		{0xa92b, 0xa92e, 1},
+		{0xa953, 0xa953, 1},
+		{0xa9b3, 0xa9b3, 1},
+		{0xa9c0, 0xa9c0, 1},
+		{0xaa7b, 0xaa7b, 1},
+		{0xaabf, 0xaac2, 1},
+		{0xabec, 0xabed, 1},
+		{0xfb1e, 0xfb1e, 1},
+		{0xfe20, 0xfe26, 1},
 		{0xff3e, 0xff3e, 1},
+		{0xff40, 0xff40, 1},
+		{0xff70, 0xff70, 1},
+		{0xff9e, 0xff9f, 1},
+		{0xffe3, 0xffe3, 1},
 	},
 	R32: []Range32{
-		{0x1d400, 0x1d454, 1},
-		{0x1d456, 0x1d49c, 1},
-		{0x1d49e, 0x1d49f, 1},
-		{0x1d4a2, 0x1d4a2, 1},
-		{0x1d4a5, 0x1d4a6, 1},
-		{0x1d4a9, 0x1d4ac, 1},
-		{0x1d4ae, 0x1d4b9, 1},
-		{0x1d4bb, 0x1d4bb, 1},
-		{0x1d4bd, 0x1d4c3, 1},
-		{0x1d4c5, 0x1d505, 1},
-		{0x1d507, 0x1d50a, 1},
-		{0x1d50d, 0x1d514, 1},
-		{0x1d516, 0x1d51c, 1},
-		{0x1d51e, 0x1d539, 1},
-		{0x1d53b, 0x1d53e, 1},
-		{0x1d540, 0x1d544, 1},
-		{0x1d546, 0x1d546, 1},
-		{0x1d54a, 0x1d550, 1},
-		{0x1d552, 0x1d6a5, 1},
-		{0x1d6a8, 0x1d6c0, 1},
-		{0x1d6c2, 0x1d6da, 1},
-		{0x1d6dc, 0x1d6fa, 1},
-		{0x1d6fc, 0x1d714, 1},
-		{0x1d716, 0x1d734, 1},
-		{0x1d736, 0x1d74e, 1},
-		{0x1d750, 0x1d76e, 1},
-		{0x1d770, 0x1d788, 1},
-		{0x1d78a, 0x1d7a8, 1},
-		{0x1d7aa, 0x1d7c2, 1},
-		{0x1d7c4, 0x1d7cb, 1},
-		{0x1d7ce, 0x1d7ff, 1},
+		{0x110b9, 0x110ba, 1},
+		{0x1d167, 0x1d169, 1},
+		{0x1d16d, 0x1d172, 1},
+		{0x1d17b, 0x1d182, 1},
+		{0x1d185, 0x1d18b, 1},
+		{0x1d1aa, 0x1d1ad, 1},
 	},
 }
 
-var _Unified_Ideograph = &RangeTable{
+var _Extender = &RangeTable{
 	R16: []Range16{
-		{0x3400, 0x4db5, 1},
-		{0x4e00, 0x9fcb, 1},
-		{0xfa0e, 0xfa0f, 1},
-		{0xfa11, 0xfa11, 1},
-		{0xfa13, 0xfa14, 1},
-		{0xfa1f, 0xfa1f, 1},
-		{0xfa21, 0xfa21, 1},
-		{0xfa23, 0xfa24, 1},
-		{0xfa27, 0xfa29, 1},
+		{0x00b7, 0x00b7, 1},
+		{0x02d0, 0x02d1, 1},
+		{0x0640, 0x0640, 1},
+		{0x07fa, 0x07fa, 1},
+		{0x0e46, 0x0e46, 1},
+		{0x0ec6, 0x0ec6, 1},
+		{0x1843, 0x1843, 1},
+		{0x1aa7, 0x1aa7, 1},
+		{0x1c36, 0x1c36, 1},
+		{0x1c7b, 0x1c7b, 1},
+		{0x3005, 0x3005, 1},
+		{0x3031, 0x3035, 1},
+		{0x309d, 0x309e, 1},
+		{0x30fc, 0x30fe, 1},
+		{0xa015, 0xa015, 1},
+		{0xa60c, 0xa60c, 1},
+		{0xa9cf, 0xa9cf, 1},
+		{0xaa70, 0xaa70, 1},
+		{0xaadd, 0xaadd, 1},
+		{0xff70, 0xff70, 1},
 	},
-	R32: []Range32{
-		{0x20000, 0x2a6d6, 1},
-		{0x2a700, 0x2b734, 1},
-		{0x2b740, 0x2b81d, 1},
+}
+
+var _Hex_Digit = &RangeTable{
+	R16: []Range16{
+		{0x0030, 0x0039, 1},
+		{0x0041, 0x0046, 1},
+		{0x0061, 0x0066, 1},
+		{0xff10, 0xff19, 1},
+		{0xff21, 0xff26, 1},
+		{0xff41, 0xff46, 1},
 	},
 }
 
@@ -4623,82 +4428,69 @@ var _IDS_Binary_Operator = &RangeTable{
 	},
 }
 
-var _Logical_Order_Exception = &RangeTable{
+var _IDS_Trinary_Operator = &RangeTable{
 	R16: []Range16{
-		{0x0e40, 0x0e44, 1},
-		{0x0ec0, 0x0ec4, 1},
-		{0xaab5, 0xaab6, 1},
-		{0xaab9, 0xaab9, 1},
-		{0xaabb, 0xaabc, 1},
+		{0x2ff2, 0x2ff3, 1},
 	},
 }
 
-var _Radical = &RangeTable{
+var _Ideographic = &RangeTable{
 	R16: []Range16{
-		{0x2e80, 0x2e99, 1},
-		{0x2e9b, 0x2ef3, 1},
-		{0x2f00, 0x2fd5, 1},
+		{0x3006, 0x3007, 1},
+		{0x3021, 0x3029, 1},
+		{0x3038, 0x303a, 1},
+		{0x3400, 0x4db5, 1},
+		{0x4e00, 0x9fcb, 1},
+		{0xf900, 0xfa2d, 1},
+		{0xfa30, 0xfa6d, 1},
+		{0xfa70, 0xfad9, 1},
+	},
+	R32: []Range32{
+		{0x20000, 0x2a6d6, 1},
+		{0x2a700, 0x2b734, 1},
+		{0x2b740, 0x2b81d, 1},
+		{0x2f800, 0x2fa1d, 1},
 	},
 }
 
-var _Other_Uppercase = &RangeTable{
+var _Join_Control = &RangeTable{
 	R16: []Range16{
-		{0x2160, 0x216f, 1},
-		{0x24b6, 0x24cf, 1},
+		{0x200c, 0x200d, 1},
 	},
 }
 
-var _STerm = &RangeTable{
+var _Logical_Order_Exception = &RangeTable{
 	R16: []Range16{
-		{0x0021, 0x0021, 1},
-		{0x002e, 0x002e, 1},
-		{0x003f, 0x003f, 1},
-		{0x055c, 0x055c, 1},
-		{0x055e, 0x055e, 1},
-		{0x0589, 0x0589, 1},
-		{0x061f, 0x061f, 1},
-		{0x06d4, 0x06d4, 1},
-		{0x0700, 0x0702, 1},
-		{0x07f9, 0x07f9, 1},
-		{0x0964, 0x0965, 1},
-		{0x104a, 0x104b, 1},
-		{0x1362, 0x1362, 1},
-		{0x1367, 0x1368, 1},
-		{0x166e, 0x166e, 1},
-		{0x1735, 0x1736, 1},
-		{0x1803, 0x1803, 1},
-		{0x1809, 0x1809, 1},
-		{0x1944, 0x1945, 1},
-		{0x1aa8, 0x1aab, 1},
-		{0x1b5a, 0x1b5b, 1},
-		{0x1b5e, 0x1b5f, 1},
-		{0x1c3b, 0x1c3c, 1},
-		{0x1c7e, 0x1c7f, 1},
-		{0x203c, 0x203d, 1},
-		{0x2047, 0x2049, 1},
-		{0x2e2e, 0x2e2e, 1},
-		{0x3002, 0x3002, 1},
-		{0xa4ff, 0xa4ff, 1},
-		{0xa60e, 0xa60f, 1},
-		{0xa6f3, 0xa6f3, 1},
-		{0xa6f7, 0xa6f7, 1},
-		{0xa876, 0xa877, 1},
-		{0xa8ce, 0xa8cf, 1},
-		{0xa92f, 0xa92f, 1},
-		{0xa9c8, 0xa9c9, 1},
-		{0xaa5d, 0xaa5f, 1},
-		{0xabeb, 0xabeb, 1},
-		{0xfe52, 0xfe52, 1},
-		{0xfe56, 0xfe57, 1},
-		{0xff01, 0xff01, 1},
-		{0xff0e, 0xff0e, 1},
-		{0xff1f, 0xff1f, 1},
-		{0xff61, 0xff61, 1},
+		{0x0e40, 0x0e44, 1},
+		{0x0ec0, 0x0ec4, 1},
+		{0xaab5, 0xaab6, 1},
+		{0xaab9, 0xaab9, 1},
+		{0xaabb, 0xaabc, 1},
+	},
+}
+
+var _Noncharacter_Code_Point = &RangeTable{
+	R16: []Range16{
+		{0xfdd0, 0xfdef, 1},
+		{0xfffe, 0xffff, 1},
 	},
 	R32: []Range32{
-		{0x10a56, 0x10a57, 1},
-		{0x11047, 0x11048, 1},
-		{0x110be, 0x110c1, 1},
+		{0x1fffe, 0x1ffff, 1},
+		{0x2fffe, 0x2ffff, 1},
+		{0x3fffe, 0x3ffff, 1},
+		{0x4fffe, 0x4ffff, 1},
+		{0x5fffe, 0x5ffff, 1},
+		{0x6fffe, 0x6ffff, 1},
+		{0x7fffe, 0x7ffff, 1},
+		{0x8fffe, 0x8ffff, 1},
+		{0x9fffe, 0x9ffff, 1},
+		{0xafffe, 0xaffff, 1},
+		{0xbfffe, 0xbffff, 1},
+		{0xcfffe, 0xcffff, 1},
+		{0xdfffe, 0xdffff, 1},
+		{0xefffe, 0xeffff, 1},
+		{0xffffe, 0xfffff, 1},
+		{0x10fffe, 0x10ffff, 1},
 	},
 }
 
@@ -4844,257 +4636,465 @@ var _Other_Alphabetic = &RangeTable{
 		{0xfb1e, 0xfb1e, 1},
 	},
 	R32: []Range32{
-		{0x10a01, 0x10a03, 1},
-		{0x10a05, 0x10a06, 1},
-		{0x10a0c, 0x10a0f, 1},
-		{0x11000, 0x11002, 1},
-		{0x11038, 0x11045, 1},
-		{0x11082, 0x11082, 1},
-		{0x110b0, 0x110b8, 1},
+		{0x10a01, 0x10a03, 1},
+		{0x10a05, 0x10a06, 1},
+		{0x10a0c, 0x10a0f, 1},
+		{0x11000, 0x11002, 1},
+		{0x11038, 0x11045, 1},
+		{0x11082, 0x11082, 1},
+		{0x110b0, 0x110b8, 1},
+	},
+}
+
+var _Other_Default_Ignorable_Code_Point = &RangeTable{
+	R16: []Range16{
+		{0x034f, 0x034f, 1},
+		{0x115f, 0x1160, 1},
+		{0x2065, 0x2069, 1},
+		{0x3164, 0x3164, 1},
+		{0xffa0, 0xffa0, 1},
+		{0xfff0, 0xfff8, 1},
+	},
+	R32: []Range32{
+		{0xe0000, 0xe0000, 1},
+		{0xe0002, 0xe001f, 1},
+		{0xe0080, 0xe00ff, 1},
+		{0xe01f0, 0xe0fff, 1},
+	},
+}
+
+var _Other_Grapheme_Extend = &RangeTable{
+	R16: []Range16{
+		{0x09be, 0x09be, 1},
+		{0x09d7, 0x09d7, 1},
+		{0x0b3e, 0x0b3e, 1},
+		{0x0b57, 0x0b57, 1},
+		{0x0bbe, 0x0bbe, 1},
+		{0x0bd7, 0x0bd7, 1},
+		{0x0cc2, 0x0cc2, 1},
+		{0x0cd5, 0x0cd6, 1},
+		{0x0d3e, 0x0d3e, 1},
+		{0x0d57, 0x0d57, 1},
+		{0x0dcf, 0x0dcf, 1},
+		{0x0ddf, 0x0ddf, 1},
+		{0x200c, 0x200d, 1},
+		{0xff9e, 0xff9f, 1},
+	},
+	R32: []Range32{
+		{0x1d165, 0x1d165, 1},
+		{0x1d16e, 0x1d172, 1},
+	},
+}
+
+var _Other_ID_Continue = &RangeTable{
+	R16: []Range16{
+		{0x00b7, 0x00b7, 1},
+		{0x0387, 0x0387, 1},
+		{0x1369, 0x1371, 1},
+		{0x19da, 0x19da, 1},
+	},
+}
+
+var _Other_ID_Start = &RangeTable{
+	R16: []Range16{
+		{0x2118, 0x2118, 1},
+		{0x212e, 0x212e, 1},
+		{0x309b, 0x309c, 1},
+	},
+}
+
+var _Other_Lowercase = &RangeTable{
+	R16: []Range16{
+		{0x02b0, 0x02b8, 1},
+		{0x02c0, 0x02c1, 1},
+		{0x02e0, 0x02e4, 1},
+		{0x0345, 0x0345, 1},
+		{0x037a, 0x037a, 1},
+		{0x1d2c, 0x1d61, 1},
+		{0x1d78, 0x1d78, 1},
+		{0x1d9b, 0x1dbf, 1},
+		{0x2090, 0x2094, 1},
+		{0x2170, 0x217f, 1},
+		{0x24d0, 0x24e9, 1},
+		{0x2c7d, 0x2c7d, 1},
+		{0xa770, 0xa770, 1},
+	},
+}
+
+var _Other_Math = &RangeTable{
+	R16: []Range16{
+		{0x005e, 0x005e, 1},
+		{0x03d0, 0x03d2, 1},
+		{0x03d5, 0x03d5, 1},
+		{0x03f0, 0x03f1, 1},
+		{0x03f4, 0x03f5, 1},
+		{0x2016, 0x2016, 1},
+		{0x2032, 0x2034, 1},
+		{0x2040, 0x2040, 1},
+		{0x2061, 0x2064, 1},
+		{0x207d, 0x207e, 1},
+		{0x208d, 0x208e, 1},
+		{0x20d0, 0x20dc, 1},
+		{0x20e1, 0x20e1, 1},
+		{0x20e5, 0x20e6, 1},
+		{0x20eb, 0x20ef, 1},
+		{0x2102, 0x2102, 1},
+		{0x2107, 0x2107, 1},
+		{0x210a, 0x2113, 1},
+		{0x2115, 0x2115, 1},
+		{0x2119, 0x211d, 1},
+		{0x2124, 0x2124, 1},
+		{0x2128, 0x2129, 1},
+		{0x212c, 0x212d, 1},
+		{0x212f, 0x2131, 1},
+		{0x2133, 0x2138, 1},
+		{0x213c, 0x213f, 1},
+		{0x2145, 0x2149, 1},
+		{0x2195, 0x2199, 1},
+		{0x219c, 0x219f, 1},
+		{0x21a1, 0x21a2, 1},
+		{0x21a4, 0x21a5, 1},
+		{0x21a7, 0x21a7, 1},
+		{0x21a9, 0x21ad, 1},
+		{0x21b0, 0x21b1, 1},
+		{0x21b6, 0x21b7, 1},
+		{0x21bc, 0x21cd, 1},
+		{0x21d0, 0x21d1, 1},
+		{0x21d3, 0x21d3, 1},
+		{0x21d5, 0x21db, 1},
+		{0x21dd, 0x21dd, 1},
+		{0x21e4, 0x21e5, 1},
+		{0x23b4, 0x23b5, 1},
+		{0x23b7, 0x23b7, 1},
+		{0x23d0, 0x23d0, 1},
+		{0x23e2, 0x23e2, 1},
+		{0x25a0, 0x25a1, 1},
+		{0x25ae, 0x25b6, 1},
+		{0x25bc, 0x25c0, 1},
+		{0x25c6, 0x25c7, 1},
+		{0x25ca, 0x25cb, 1},
+		{0x25cf, 0x25d3, 1},
+		{0x25e2, 0x25e2, 1},
+		{0x25e4, 0x25e4, 1},
+		{0x25e7, 0x25ec, 1},
+		{0x2605, 0x2606, 1},
+		{0x2640, 0x2640, 1},
+		{0x2642, 0x2642, 1},
+		{0x2660, 0x2663, 1},
+		{0x266d, 0x266e, 1},
+		{0x27c5, 0x27c6, 1},
+		{0x27e6, 0x27ef, 1},
+		{0x2983, 0x2998, 1},
+		{0x29d8, 0x29db, 1},
+		{0x29fc, 0x29fd, 1},
+		{0xfe61, 0xfe61, 1},
+		{0xfe63, 0xfe63, 1},
+		{0xfe68, 0xfe68, 1},
+		{0xff3c, 0xff3c, 1},
+		{0xff3e, 0xff3e, 1},
+	},
+	R32: []Range32{
+		{0x1d400, 0x1d454, 1},
+		{0x1d456, 0x1d49c, 1},
+		{0x1d49e, 0x1d49f, 1},
+		{0x1d4a2, 0x1d4a2, 1},
+		{0x1d4a5, 0x1d4a6, 1},
+		{0x1d4a9, 0x1d4ac, 1},
+		{0x1d4ae, 0x1d4b9, 1},
+		{0x1d4bb, 0x1d4bb, 1},
+		{0x1d4bd, 0x1d4c3, 1},
+		{0x1d4c5, 0x1d505, 1},
+		{0x1d507, 0x1d50a, 1},
+		{0x1d50d, 0x1d514, 1},
+		{0x1d516, 0x1d51c, 1},
+		{0x1d51e, 0x1d539, 1},
+		{0x1d53b, 0x1d53e, 1},
+		{0x1d540, 0x1d544, 1},
+		{0x1d546, 0x1d546, 1},
+		{0x1d54a, 0x1d550, 1},
+		{0x1d552, 0x1d6a5, 1},
+		{0x1d6a8, 0x1d6c0, 1},
+		{0x1d6c2, 0x1d6da, 1},
+		{0x1d6dc, 0x1d6fa, 1},
+		{0x1d6fc, 0x1d714, 1},
+		{0x1d716, 0x1d734, 1},
+		{0x1d736, 0x1d74e, 1},
+		{0x1d750, 0x1d76e, 1},
+		{0x1d770, 0x1d788, 1},
+		{0x1d78a, 0x1d7a8, 1},
+		{0x1d7aa, 0x1d7c2, 1},
+		{0x1d7c4, 0x1d7cb, 1},
+		{0x1d7ce, 0x1d7ff, 1},
+	},
+}
+
+var _Other_Uppercase = &RangeTable{
+	R16: []Range16{
+		{0x2160, 0x216f, 1},
+		{0x24b6, 0x24cf, 1},
+	},
+}
+
+var _Pattern_Syntax = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x002f, 1},
+		{0x003a, 0x0040, 1},
+		{0x005b, 0x005e, 1},
+		{0x0060, 0x0060, 1},
+		{0x007b, 0x007e, 1},
+		{0x00a1, 0x00a7, 1},
+		{0x00a9, 0x00a9, 1},
+		{0x00ab, 0x00ac, 1},
+		{0x00ae, 0x00ae, 1},
+		{0x00b0, 0x00b1, 1},
+		{0x00b6, 0x00b6, 1},
+		{0x00bb, 0x00bb, 1},
+		{0x00bf, 0x00bf, 1},
+		{0x00d7, 0x00d7, 1},
+		{0x00f7, 0x00f7, 1},
+		{0x2010, 0x2027, 1},
+		{0x2030, 0x203e, 1},
+		{0x2041, 0x2053, 1},
+		{0x2055, 0x205e, 1},
+		{0x2190, 0x245f, 1},
+		{0x2500, 0x2775, 1},
+		{0x2794, 0x2bff, 1},
+		{0x2e00, 0x2e7f, 1},
+		{0x3001, 0x3003, 1},
+		{0x3008, 0x3020, 1},
+		{0x3030, 0x3030, 1},
+		{0xfd3e, 0xfd3f, 1},
+		{0xfe45, 0xfe46, 1},
+	},
+}
+
+var _Pattern_White_Space = &RangeTable{
+	R16: []Range16{
+		{0x0009, 0x000d, 1},
+		{0x0020, 0x0020, 1},
+		{0x0085, 0x0085, 1},
+		{0x200e, 0x200f, 1},
+		{0x2028, 0x2029, 1},
+	},
+}
+
+var _Quotation_Mark = &RangeTable{
+	R16: []Range16{
+		{0x0022, 0x0022, 1},
+		{0x0027, 0x0027, 1},
+		{0x00ab, 0x00ab, 1},
+		{0x00bb, 0x00bb, 1},
+		{0x2018, 0x201f, 1},
+		{0x2039, 0x203a, 1},
+		{0x300c, 0x300f, 1},
+		{0x301d, 0x301f, 1},
+		{0xfe41, 0xfe44, 1},
+		{0xff02, 0xff02, 1},
+		{0xff07, 0xff07, 1},
+		{0xff62, 0xff63, 1},
+	},
+}
+
+var _Radical = &RangeTable{
+	R16: []Range16{
+		{0x2e80, 0x2e99, 1},
+		{0x2e9b, 0x2ef3, 1},
+		{0x2f00, 0x2fd5, 1},
+	},
+}
+
+var _STerm = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x0021, 1},
+		{0x002e, 0x002e, 1},
+		{0x003f, 0x003f, 1},
+		{0x055c, 0x055c, 1},
+		{0x055e, 0x055e, 1},
+		{0x0589, 0x0589, 1},
+		{0x061f, 0x061f, 1},
+		{0x06d4, 0x06d4, 1},
+		{0x0700, 0x0702, 1},
+		{0x07f9, 0x07f9, 1},
+		{0x0964, 0x0965, 1},
+		{0x104a, 0x104b, 1},
+		{0x1362, 0x1362, 1},
+		{0x1367, 0x1368, 1},
+		{0x166e, 0x166e, 1},
+		{0x1735, 0x1736, 1},
+		{0x1803, 0x1803, 1},
+		{0x1809, 0x1809, 1},
+		{0x1944, 0x1945, 1},
+		{0x1aa8, 0x1aab, 1},
+		{0x1b5a, 0x1b5b, 1},
+		{0x1b5e, 0x1b5f, 1},
+		{0x1c3b, 0x1c3c, 1},
+		{0x1c7e, 0x1c7f, 1},
+		{0x203c, 0x203d, 1},
+		{0x2047, 0x2049, 1},
+		{0x2e2e, 0x2e2e, 1},
+		{0x3002, 0x3002, 1},
+		{0xa4ff, 0xa4ff, 1},
+		{0xa60e, 0xa60f, 1},
+		{0xa6f3, 0xa6f3, 1},
+		{0xa6f7, 0xa6f7, 1},
+		{0xa876, 0xa877, 1},
+		{0xa8ce, 0xa8cf, 1},
+		{0xa92f, 0xa92f, 1},
+		{0xa9c8, 0xa9c9, 1},
+		{0xaa5d, 0xaa5f, 1},
+		{0xabeb, 0xabeb, 1},
+		{0xfe52, 0xfe52, 1},
+		{0xfe56, 0xfe57, 1},
+		{0xff01, 0xff01, 1},
+		{0xff0e, 0xff0e, 1},
+		{0xff1f, 0xff1f, 1},
+		{0xff61, 0xff61, 1},
+	},
+	R32: []Range32{
+		{0x10a56, 0x10a57, 1},
+		{0x11047, 0x11048, 1},
+		{0x110be, 0x110c1, 1},
 	},
 }
 
-var _Diacritic = &RangeTable{
+var _Soft_Dotted = &RangeTable{
 	R16: []Range16{
-		{0x005e, 0x005e, 1},
-		{0x0060, 0x0060, 1},
-		{0x00a8, 0x00a8, 1},
-		{0x00af, 0x00af, 1},
-		{0x00b4, 0x00b4, 1},
-		{0x00b7, 0x00b8, 1},
-		{0x02b0, 0x034e, 1},
-		{0x0350, 0x0357, 1},
-		{0x035d, 0x0362, 1},
-		{0x0374, 0x0375, 1},
-		{0x037a, 0x037a, 1},
-		{0x0384, 0x0385, 1},
-		{0x0483, 0x0487, 1},
-		{0x0559, 0x0559, 1},
-		{0x0591, 0x05a1, 1},
-		{0x05a3, 0x05bd, 1},
-		{0x05bf, 0x05bf, 1},
-		{0x05c1, 0x05c2, 1},
-		{0x05c4, 0x05c4, 1},
-		{0x064b, 0x0652, 1},
-		{0x0657, 0x0658, 1},
-		{0x06df, 0x06e0, 1},
-		{0x06e5, 0x06e6, 1},
-		{0x06ea, 0x06ec, 1},
-		{0x0730, 0x074a, 1},
-		{0x07a6, 0x07b0, 1},
-		{0x07eb, 0x07f5, 1},
-		{0x0818, 0x0819, 1},
-		{0x093c, 0x093c, 1},
-		{0x094d, 0x094d, 1},
-		{0x0951, 0x0954, 1},
-		{0x0971, 0x0971, 1},
-		{0x09bc, 0x09bc, 1},
-		{0x09cd, 0x09cd, 1},
-		{0x0a3c, 0x0a3c, 1},
-		{0x0a4d, 0x0a4d, 1},
-		{0x0abc, 0x0abc, 1},
-		{0x0acd, 0x0acd, 1},
-		{0x0b3c, 0x0b3c, 1},
-		{0x0b4d, 0x0b4d, 1},
-		{0x0bcd, 0x0bcd, 1},
-		{0x0c4d, 0x0c4d, 1},
-		{0x0cbc, 0x0cbc, 1},
-		{0x0ccd, 0x0ccd, 1},
-		{0x0d4d, 0x0d4d, 1},
-		{0x0dca, 0x0dca, 1},
-		{0x0e47, 0x0e4c, 1},
-		{0x0e4e, 0x0e4e, 1},
-		{0x0ec8, 0x0ecc, 1},
-		{0x0f18, 0x0f19, 1},
-		{0x0f35, 0x0f35, 1},
-		{0x0f37, 0x0f37, 1},
-		{0x0f39, 0x0f39, 1},
-		{0x0f3e, 0x0f3f, 1},
-		{0x0f82, 0x0f84, 1},
-		{0x0f86, 0x0f87, 1},
-		{0x0fc6, 0x0fc6, 1},
-		{0x1037, 0x1037, 1},
-		{0x1039, 0x103a, 1},
-		{0x1087, 0x108d, 1},
-		{0x108f, 0x108f, 1},
-		{0x109a, 0x109b, 1},
-		{0x17c9, 0x17d3, 1},
-		{0x17dd, 0x17dd, 1},
-		{0x1939, 0x193b, 1},
-		{0x1a75, 0x1a7c, 1},
-		{0x1a7f, 0x1a7f, 1},
-		{0x1b34, 0x1b34, 1},
-		{0x1b44, 0x1b44, 1},
-		{0x1b6b, 0x1b73, 1},
-		{0x1baa, 0x1baa, 1},
-		{0x1c36, 0x1c37, 1},
-		{0x1c78, 0x1c7d, 1},
-		{0x1cd0, 0x1ce8, 1},
-		{0x1ced, 0x1ced, 1},
-		{0x1d2c, 0x1d6a, 1},
-		{0x1dc4, 0x1dcf, 1},
-		{0x1dfd, 0x1dff, 1},
-		{0x1fbd, 0x1fbd, 1},
-		{0x1fbf, 0x1fc1, 1},
-		{0x1fcd, 0x1fcf, 1},
-		{0x1fdd, 0x1fdf, 1},
-		{0x1fed, 0x1fef, 1},
-		{0x1ffd, 0x1ffe, 1},
-		{0x2cef, 0x2cf1, 1},
-		{0x2e2f, 0x2e2f, 1},
-		{0x302a, 0x302f, 1},
-		{0x3099, 0x309c, 1},
-		{0x30fc, 0x30fc, 1},
-		{0xa66f, 0xa66f, 1},
-		{0xa67c, 0xa67d, 1},
-		{0xa67f, 0xa67f, 1},
-		{0xa6f0, 0xa6f1, 1},
-		{0xa717, 0xa721, 1},
-		{0xa788, 0xa788, 1},
-		{0xa8c4, 0xa8c4, 1},
-		{0xa8e0, 0xa8f1, 1},
-		{0xa92b, 0xa92e, 1},
-		{0xa953, 0xa953, 1},
-		{0xa9b3, 0xa9b3, 1},
-		{0xa9c0, 0xa9c0, 1},
-		{0xaa7b, 0xaa7b, 1},
-		{0xaabf, 0xaac2, 1},
-		{0xabec, 0xabed, 1},
-		{0xfb1e, 0xfb1e, 1},
-		{0xfe20, 0xfe26, 1},
-		{0xff3e, 0xff3e, 1},
-		{0xff40, 0xff40, 1},
-		{0xff70, 0xff70, 1},
-		{0xff9e, 0xff9f, 1},
-		{0xffe3, 0xffe3, 1},
+		{0x0069, 0x006a, 1},
+		{0x012f, 0x012f, 1},
+		{0x0249, 0x0249, 1},
+		{0x0268, 0x0268, 1},
+		{0x029d, 0x029d, 1},
+		{0x02b2, 0x02b2, 1},
+		{0x03f3, 0x03f3, 1},
+		{0x0456, 0x0456, 1},
+		{0x0458, 0x0458, 1},
+		{0x1d62, 0x1d62, 1},
+		{0x1d96, 0x1d96, 1},
+		{0x1da4, 0x1da4, 1},
+		{0x1da8, 0x1da8, 1},
+		{0x1e2d, 0x1e2d, 1},
+		{0x1ecb, 0x1ecb, 1},
+		{0x2071, 0x2071, 1},
+		{0x2148, 0x2149, 1},
+		{0x2c7c, 0x2c7c, 1},
+	},
+	R32: []Range32{
+		{0x1d422, 0x1d423, 1},
+		{0x1d456, 0x1d457, 1},
+		{0x1d48a, 0x1d48b, 1},
+		{0x1d4be, 0x1d4bf, 1},
+		{0x1d4f2, 0x1d4f3, 1},
+		{0x1d526, 0x1d527, 1},
+		{0x1d55a, 0x1d55b, 1},
+		{0x1d58e, 0x1d58f, 1},
+		{0x1d5c2, 0x1d5c3, 1},
+		{0x1d5f6, 0x1d5f7, 1},
+		{0x1d62a, 0x1d62b, 1},
+		{0x1d65e, 0x1d65f, 1},
+		{0x1d692, 0x1d693, 1},
+	},
+}
+
+var _Terminal_Punctuation = &RangeTable{
+	R16: []Range16{
+		{0x0021, 0x0021, 1},
+		{0x002c, 0x002c, 1},
+		{0x002e, 0x002e, 1},
+		{0x003a, 0x003b, 1},
+		{0x003f, 0x003f, 1},
+		{0x037e, 0x037e, 1},
+		{0x0387, 0x0387, 1},
+		{0x0589, 0x0589, 1},
+		{0x05c3, 0x05c3, 1},
+		{0x060c, 0x060c, 1},
+		{0x061b, 0x061b, 1},
+		{0x061f, 0x061f, 1},
+		{0x06d4, 0x06d4, 1},
+		{0x0700, 0x070a, 1},
+		{0x070c, 0x070c, 1},
+		{0x07f8, 0x07f9, 1},
+		{0x0830, 0x083e, 1},
+		{0x085e, 0x085e, 1},
+		{0x0964, 0x0965, 1},
+		{0x0e5a, 0x0e5b, 1},
+		{0x0f08, 0x0f08, 1},
+		{0x0f0d, 0x0f12, 1},
+		{0x104a, 0x104b, 1},
+		{0x1361, 0x1368, 1},
+		{0x166d, 0x166e, 1},
+		{0x16eb, 0x16ed, 1},
+		{0x17d4, 0x17d6, 1},
+		{0x17da, 0x17da, 1},
+		{0x1802, 0x1805, 1},
+		{0x1808, 0x1809, 1},
+		{0x1944, 0x1945, 1},
+		{0x1aa8, 0x1aab, 1},
+		{0x1b5a, 0x1b5b, 1},
+		{0x1b5d, 0x1b5f, 1},
+		{0x1c3b, 0x1c3f, 1},
+		{0x1c7e, 0x1c7f, 1},
+		{0x203c, 0x203d, 1},
+		{0x2047, 0x2049, 1},
+		{0x2e2e, 0x2e2e, 1},
+		{0x3001, 0x3002, 1},
+		{0xa4fe, 0xa4ff, 1},
+		{0xa60d, 0xa60f, 1},
+		{0xa6f3, 0xa6f7, 1},
+		{0xa876, 0xa877, 1},
+		{0xa8ce, 0xa8cf, 1},
+		{0xa92f, 0xa92f, 1},
+		{0xa9c7, 0xa9c9, 1},
+		{0xaa5d, 0xaa5f, 1},
+		{0xaadf, 0xaadf, 1},
+		{0xabeb, 0xabeb, 1},
+		{0xfe50, 0xfe52, 1},
+		{0xfe54, 0xfe57, 1},
+		{0xff01, 0xff01, 1},
+		{0xff0c, 0xff0c, 1},
+		{0xff0e, 0xff0e, 1},
+		{0xff1a, 0xff1b, 1},
+		{0xff1f, 0xff1f, 1},
+		{0xff61, 0xff61, 1},
+		{0xff64, 0xff64, 1},
 	},
 	R32: []Range32{
-		{0x110b9, 0x110ba, 1},
-		{0x1d167, 0x1d169, 1},
-		{0x1d16d, 0x1d172, 1},
-		{0x1d17b, 0x1d182, 1},
-		{0x1d185, 0x1d18b, 1},
-		{0x1d1aa, 0x1d1ad, 1},
-	},
-}
-
-var _Extender = &RangeTable{
-	R16: []Range16{
-		{0x00b7, 0x00b7, 1},
-		{0x02d0, 0x02d1, 1},
-		{0x0640, 0x0640, 1},
-		{0x07fa, 0x07fa, 1},
-		{0x0e46, 0x0e46, 1},
-		{0x0ec6, 0x0ec6, 1},
-		{0x1843, 0x1843, 1},
-		{0x1aa7, 0x1aa7, 1},
-		{0x1c36, 0x1c36, 1},
-		{0x1c7b, 0x1c7b, 1},
-		{0x3005, 0x3005, 1},
-		{0x3031, 0x3035, 1},
-		{0x309d, 0x309e, 1},
-		{0x30fc, 0x30fe, 1},
-		{0xa015, 0xa015, 1},
-		{0xa60c, 0xa60c, 1},
-		{0xa9cf, 0xa9cf, 1},
-		{0xaa70, 0xaa70, 1},
-		{0xaadd, 0xaadd, 1},
-		{0xff70, 0xff70, 1},
-	},
-}
-
-var _Join_Control = &RangeTable{
-	R16: []Range16{
-		{0x200c, 0x200d, 1},
+		{0x1039f, 0x1039f, 1},
+		{0x103d0, 0x103d0, 1},
+		{0x10857, 0x10857, 1},
+		{0x1091f, 0x1091f, 1},
+		{0x10b3a, 0x10b3f, 1},
+		{0x11047, 0x1104d, 1},
+		{0x110be, 0x110c1, 1},
+		{0x12470, 0x12473, 1},
 	},
 }
 
-var _Ideographic = &RangeTable{
+var _Unified_Ideograph = &RangeTable{
 	R16: []Range16{
-		{0x3006, 0x3007, 1},
-		{0x3021, 0x3029, 1},
-		{0x3038, 0x303a, 1},
 		{0x3400, 0x4db5, 1},
 		{0x4e00, 0x9fcb, 1},
-		{0xf900, 0xfa2d, 1},
-		{0xfa30, 0xfa6d, 1},
-		{0xfa70, 0xfad9, 1},
+		{0xfa0e, 0xfa0f, 1},
+		{0xfa11, 0xfa11, 1},
+		{0xfa13, 0xfa14, 1},
+		{0xfa1f, 0xfa1f, 1},
+		{0xfa21, 0xfa21, 1},
+		{0xfa23, 0xfa24, 1},
+		{0xfa27, 0xfa29, 1},
 	},
 	R32: []Range32{
 		{0x20000, 0x2a6d6, 1},
 		{0x2a700, 0x2b734, 1},
 		{0x2b740, 0x2b81d, 1},
-		{0x2f800, 0x2fa1d, 1},
-	},
-}
-
-var _Dash = &RangeTable{
-	R16: []Range16{
-		{0x002d, 0x002d, 1},
-		{0x058a, 0x058a, 1},
-		{0x05be, 0x05be, 1},
-		{0x1400, 0x1400, 1},
-		{0x1806, 0x1806, 1},
-		{0x2010, 0x2015, 1},
-		{0x2053, 0x2053, 1},
-		{0x207b, 0x207b, 1},
-		{0x208b, 0x208b, 1},
-		{0x2212, 0x2212, 1},
-		{0x2e17, 0x2e17, 1},
-		{0x2e1a, 0x2e1a, 1},
-		{0x301c, 0x301c, 1},
-		{0x3030, 0x3030, 1},
-		{0x30a0, 0x30a0, 1},
-		{0xfe31, 0xfe32, 1},
-		{0xfe58, 0xfe58, 1},
-		{0xfe63, 0xfe63, 1},
-		{0xff0d, 0xff0d, 1},
-	},
-}
-
-var _IDS_Trinary_Operator = &RangeTable{
-	R16: []Range16{
-		{0x2ff2, 0x2ff3, 1},
-	},
-}
-
-var _Other_Grapheme_Extend = &RangeTable{
-	R16: []Range16{
-		{0x09be, 0x09be, 1},
-		{0x09d7, 0x09d7, 1},
-		{0x0b3e, 0x0b3e, 1},
-		{0x0b57, 0x0b57, 1},
-		{0x0bbe, 0x0bbe, 1},
-		{0x0bd7, 0x0bd7, 1},
-		{0x0cc2, 0x0cc2, 1},
-		{0x0cd5, 0x0cd6, 1},
-		{0x0d3e, 0x0d3e, 1},
-		{0x0d57, 0x0d57, 1},
-		{0x0dcf, 0x0dcf, 1},
-		{0x0ddf, 0x0ddf, 1},
-		{0x200c, 0x200d, 1},
-		{0xff9e, 0xff9f, 1},
-	},
-	R32: []Range32{
-		{0x1d165, 0x1d165, 1},
-		{0x1d16e, 0x1d172, 1},
 	},
 }
 
-var _Other_Default_Ignorable_Code_Point = &RangeTable{
+var _Variation_Selector = &RangeTable{
 	R16: []Range16{
-		{0x034f, 0x034f, 1},
-		{0x115f, 0x1160, 1},
-		{0x2065, 0x2069, 1},
-		{0x3164, 0x3164, 1},
-		{0xffa0, 0xffa0, 1},
-		{0xfff0, 0xfff8, 1},
+		{0x180b, 0x180d, 1},
+		{0xfe00, 0xfe0f, 1},
 	},
 	R32: []Range32{
-		{0xe0000, 0xe0000, 1},
-		{0xe0002, 0xe001f, 1},
-		{0xe0080, 0xe00ff, 1},
-		{0xe01f0, 0xe0fff, 1},
+		{0xe0100, 0xe01ef, 1},
 	},
 }
 
@@ -5746,15 +5746,40 @@ var caseOrbit = []foldPair{
 // simple case folding to code points inside the category.
 // If there is no entry for a category name, there are no such points.
 var FoldCategory = map[string]*RangeTable{
-	"Ll":        foldLl,
-	"Inherited": foldInherited,
-	"M":         foldM,
-	"L":         foldL,
-	"Mn":        foldMn,
 	"Common":    foldCommon,
 	"Greek":     foldGreek,
-	"Lu":        foldLu,
+	"Inherited": foldInherited,
+	"L":         foldL,
+	"Ll":        foldLl,
 	"Lt":        foldLt,
+	"Lu":        foldLu,
+	"M":         foldM,
+	"Mn":        foldMn,
+}
+
+var foldCommon = &RangeTable{
+	R16: []Range16{
+		{0x039c, 0x03bc, 32},
+	},
+}
+
+var foldGreek = &RangeTable{
+	R16: []Range16{
+		{0x00b5, 0x0345, 656},
+	},
+}
+
+var foldInherited = &RangeTable{
+	R16: []Range16{
+		{0x0399, 0x03b9, 32},
+		{0x1fbe, 0x1fbe, 1},
+	},
+}
+
+var foldL = &RangeTable{
+	R16: []Range16{
+		{0x0345, 0x0345, 1},
+	},
 }
 
 var foldLl = &RangeTable{
@@ -5861,42 +5886,17 @@ var foldLl = &RangeTable{
 	},
 }
 
-var foldInherited = &RangeTable{
-	R16: []Range16{
-		{0x0399, 0x03b9, 32},
-		{0x1fbe, 0x1fbe, 1},
-	},
-}
-
-var foldM = &RangeTable{
-	R16: []Range16{
-		{0x0399, 0x03b9, 32},
-		{0x1fbe, 0x1fbe, 1},
-	},
-}
-
-var foldL = &RangeTable{
-	R16: []Range16{
-		{0x0345, 0x0345, 1},
-	},
-}
-
-var foldMn = &RangeTable{
-	R16: []Range16{
-		{0x0399, 0x03b9, 32},
-		{0x1fbe, 0x1fbe, 1},
-	},
-}
-
-var foldCommon = &RangeTable{
-	R16: []Range16{
-		{0x039c, 0x03bc, 32},
-	},
-}
-
-var foldGreek = &RangeTable{
+var foldLt = &RangeTable{
 	R16: []Range16{
-		{0x00b5, 0x0345, 656},
+		{0x01c4, 0x01c6, 2},
+		{0x01c7, 0x01c9, 2},
+		{0x01ca, 0x01cc, 2},
+		{0x01f1, 0x01f3, 2},
+		{0x1f80, 0x1f87, 1},
+		{0x1f90, 0x1f97, 1},
+		{0x1fa0, 0x1fa7, 1},
+		{0x1fb3, 0x1fc3, 16},
+		{0x1ff3, 0x1ff3, 1},
 	},
 }
 
@@ -6000,17 +6000,17 @@ var foldLu = &RangeTable{
 	},
 }
 
-var foldLt = &RangeTable{
+var foldM = &RangeTable{
 	R16: []Range16{
-		{0x01c4, 0x01c6, 2},
-		{0x01c7, 0x01c9, 2},
-		{0x01ca, 0x01cc, 2},
-		{0x01f1, 0x01f3, 2},
-		{0x1f80, 0x1f87, 1},
-		{0x1f90, 0x1f97, 1},
-		{0x1fa0, 0x1fa7, 1},
-		{0x1fb3, 0x1fc3, 16},
-		{0x1ff3, 0x1ff3, 1},
+		{0x0399, 0x03b9, 32},
+		{0x1fbe, 0x1fbe, 1},
+	},
+}
+
+var foldMn = &RangeTable{
+	R16: []Range16{
+		{0x0399, 0x03b9, 32},
+		{0x1fbe, 0x1fbe, 1},
 	},
 }
 
diff --git a/src/pkg/unicode/utf16/Makefile b/src/pkg/unicode/utf16/Makefile
new file mode 100644
index 0000000..f64b3c8
--- /dev/null
+++ b/src/pkg/unicode/utf16/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=unicode/utf16
+GOFILES=\
+	utf16.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/unicode/utf16/utf16.go b/src/pkg/unicode/utf16/utf16.go
new file mode 100644
index 0000000..2b2eb28
--- /dev/null
+++ b/src/pkg/unicode/utf16/utf16.go
@@ -0,0 +1,101 @@
+// Copyright 2010 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 utf16 implements encoding and decoding of UTF-16 sequences.
+package utf16
+
+import "unicode"
+
+const (
+	// 0xd800-0xdc00 encodes the high 10 bits of a pair.
+	// 0xdc00-0xe000 encodes the low 10 bits of a pair.
+	// the value is those 20 bits plus 0x10000.
+	surr1 = 0xd800
+	surr2 = 0xdc00
+	surr3 = 0xe000
+
+	surrSelf = 0x10000
+)
+
+// IsSurrogate returns true if the specified Unicode code point
+// can appear in a surrogate pair.
+func IsSurrogate(r rune) bool {
+	return surr1 <= r && r < surr3
+}
+
+// DecodeRune returns the UTF-16 decoding of a surrogate pair.
+// If the pair is not a valid UTF-16 surrogate pair, DecodeRune returns
+// the Unicode replacement code point U+FFFD.
+func DecodeRune(r1, r2 rune) rune {
+	if surr1 <= r1 && r1 < surr2 && surr2 <= r2 && r2 < surr3 {
+		return (rune(r1)-surr1)<<10 | (rune(r2) - surr2) + 0x10000
+	}
+	return unicode.ReplacementChar
+}
+
+// EncodeRune returns the UTF-16 surrogate pair r1, r2 for the given rune.
+// If the rune is not a valid Unicode code point or does not need encoding,
+// EncodeRune returns U+FFFD, U+FFFD.
+func EncodeRune(r rune) (r1, r2 rune) {
+	if r < surrSelf || r > unicode.MaxRune || IsSurrogate(r) {
+		return unicode.ReplacementChar, unicode.ReplacementChar
+	}
+	r -= surrSelf
+	return surr1 + (r>>10)&0x3ff, surr2 + r&0x3ff
+}
+
+// Encode returns the UTF-16 encoding of the Unicode code point sequence s.
+func Encode(s []rune) []uint16 {
+	n := len(s)
+	for _, v := range s {
+		if v >= surrSelf {
+			n++
+		}
+	}
+
+	a := make([]uint16, n)
+	n = 0
+	for _, v := range s {
+		switch {
+		case v < 0, surr1 <= v && v < surr3, v > unicode.MaxRune:
+			v = unicode.ReplacementChar
+			fallthrough
+		case v < surrSelf:
+			a[n] = uint16(v)
+			n++
+		default:
+			r1, r2 := EncodeRune(v)
+			a[n] = uint16(r1)
+			a[n+1] = uint16(r2)
+			n += 2
+		}
+	}
+	return a[0:n]
+}
+
+// Decode returns the Unicode code point sequence represented
+// by the UTF-16 encoding s.
+func Decode(s []uint16) []rune {
+	a := make([]rune, len(s))
+	n := 0
+	for i := 0; i < len(s); i++ {
+		switch r := s[i]; {
+		case surr1 <= r && r < surr2 && i+1 < len(s) &&
+			surr2 <= s[i+1] && s[i+1] < surr3:
+			// valid surrogate sequence
+			a[n] = DecodeRune(rune(r), rune(s[i+1]))
+			i++
+			n++
+		case surr1 <= r && r < surr3:
+			// invalid surrogate sequence
+			a[n] = unicode.ReplacementChar
+			n++
+		default:
+			// normal rune
+			a[n] = rune(r)
+			n++
+		}
+	}
+	return a[0:n]
+}
diff --git a/src/pkg/unicode/utf16/utf16_test.go b/src/pkg/unicode/utf16/utf16_test.go
new file mode 100644
index 0000000..d453b2f
--- /dev/null
+++ b/src/pkg/unicode/utf16/utf16_test.go
@@ -0,0 +1,91 @@
+// Copyright 2010 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 utf16_test
+
+import (
+	"reflect"
+	"testing"
+	"unicode"
+	. "unicode/utf16"
+)
+
+type encodeTest struct {
+	in  []rune
+	out []uint16
+}
+
+var encodeTests = []encodeTest{
+	{[]rune{1, 2, 3, 4}, []uint16{1, 2, 3, 4}},
+	{[]rune{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff},
+		[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff}},
+	{[]rune{'a', 'b', 0xd7ff, 0xd800, 0xdfff, 0xe000, 0x110000, -1},
+		[]uint16{'a', 'b', 0xd7ff, 0xfffd, 0xfffd, 0xe000, 0xfffd, 0xfffd}},
+}
+
+func TestEncode(t *testing.T) {
+	for _, tt := range encodeTests {
+		out := Encode(tt.in)
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("Encode(%x) = %x; want %x", tt.in, out, tt.out)
+		}
+	}
+}
+
+func TestEncodeRune(t *testing.T) {
+	for i, tt := range encodeTests {
+		j := 0
+		for _, r := range tt.in {
+			r1, r2 := EncodeRune(r)
+			if r < 0x10000 || r > unicode.MaxRune {
+				if j >= len(tt.out) {
+					t.Errorf("#%d: ran out of tt.out", i)
+					break
+				}
+				if r1 != unicode.ReplacementChar || r2 != unicode.ReplacementChar {
+					t.Errorf("EncodeRune(%#x) = %#x, %#x; want 0xfffd, 0xfffd", r, r1, r2)
+				}
+				j++
+			} else {
+				if j+1 >= len(tt.out) {
+					t.Errorf("#%d: ran out of tt.out", i)
+					break
+				}
+				if r1 != rune(tt.out[j]) || r2 != rune(tt.out[j+1]) {
+					t.Errorf("EncodeRune(%#x) = %#x, %#x; want %#x, %#x", r, r1, r2, tt.out[j], tt.out[j+1])
+				}
+				j += 2
+				dec := DecodeRune(r1, r2)
+				if dec != r {
+					t.Errorf("DecodeRune(%#x, %#x) = %#x; want %#x", r1, r2, dec, r)
+				}
+			}
+		}
+		if j != len(tt.out) {
+			t.Errorf("#%d: EncodeRune didn't generate enough output", i)
+		}
+	}
+}
+
+type decodeTest struct {
+	in  []uint16
+	out []rune
+}
+
+var decodeTests = []decodeTest{
+	{[]uint16{1, 2, 3, 4}, []rune{1, 2, 3, 4}},
+	{[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff},
+		[]rune{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff}},
+	{[]uint16{0xd800, 'a'}, []rune{0xfffd, 'a'}},
+	{[]uint16{0xdfff}, []rune{0xfffd}},
+}
+
+func TestDecode(t *testing.T) {
+	for _, tt := range decodeTests {
+		out := Decode(tt.in)
+		if !reflect.DeepEqual(out, tt.out) {
+			t.Errorf("Decode(%x) = %x; want %x", tt.in, out, tt.out)
+		}
+	}
+}
diff --git a/src/pkg/unicode/utf8/Makefile b/src/pkg/unicode/utf8/Makefile
new file mode 100644
index 0000000..b6c36f0
--- /dev/null
+++ b/src/pkg/unicode/utf8/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../Make.inc
+
+TARG=unicode/utf8
+GOFILES=\
+	utf8.go\
+
+include ../../../Make.pkg
diff --git a/src/pkg/unicode/utf8/utf8.go b/src/pkg/unicode/utf8/utf8.go
new file mode 100644
index 0000000..a5f9983
--- /dev/null
+++ b/src/pkg/unicode/utf8/utf8.go
@@ -0,0 +1,391 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package utf8 implements functions and constants to support text encoded in
+// UTF-8. This package calls a Unicode character a rune for brevity.
+package utf8
+
+import "unicode" // only needed for a couple of constants
+
+// Numbers fundamental to the encoding.
+const (
+	RuneError = unicode.ReplacementChar // the "error" Rune or "replacement character".
+	RuneSelf  = 0x80                    // characters below Runeself are represented as themselves in a single byte.
+	UTFMax    = 4                       // maximum number of bytes of a UTF-8 encoded Unicode character.
+)
+
+const (
+	t1 = 0x00 // 0000 0000
+	tx = 0x80 // 1000 0000
+	t2 = 0xC0 // 1100 0000
+	t3 = 0xE0 // 1110 0000
+	t4 = 0xF0 // 1111 0000
+	t5 = 0xF8 // 1111 1000
+
+	maskx = 0x3F // 0011 1111
+	mask2 = 0x1F // 0001 1111
+	mask3 = 0x0F // 0000 1111
+	mask4 = 0x07 // 0000 0111
+
+	rune1Max = 1<<7 - 1
+	rune2Max = 1<<11 - 1
+	rune3Max = 1<<16 - 1
+	rune4Max = 1<<21 - 1
+)
+
+func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
+	n := len(p)
+	if n < 1 {
+		return RuneError, 0, true
+	}
+	c0 := p[0]
+
+	// 1-byte, 7-bit sequence?
+	if c0 < tx {
+		return rune(c0), 1, false
+	}
+
+	// unexpected continuation byte?
+	if c0 < t2 {
+		return RuneError, 1, false
+	}
+
+	// need first continuation byte
+	if n < 2 {
+		return RuneError, 1, true
+	}
+	c1 := p[1]
+	if c1 < tx || t2 <= c1 {
+		return RuneError, 1, false
+	}
+
+	// 2-byte, 11-bit sequence?
+	if c0 < t3 {
+		r = rune(c0&mask2)<<6 | rune(c1&maskx)
+		if r <= rune1Max {
+			return RuneError, 1, false
+		}
+		return r, 2, false
+	}
+
+	// need second continuation byte
+	if n < 3 {
+		return RuneError, 1, true
+	}
+	c2 := p[2]
+	if c2 < tx || t2 <= c2 {
+		return RuneError, 1, false
+	}
+
+	// 3-byte, 16-bit sequence?
+	if c0 < t4 {
+		r = rune(c0&mask3)<<12 | rune(c1&maskx)<<6 | rune(c2&maskx)
+		if r <= rune2Max {
+			return RuneError, 1, false
+		}
+		return r, 3, false
+	}
+
+	// need third continuation byte
+	if n < 4 {
+		return RuneError, 1, true
+	}
+	c3 := p[3]
+	if c3 < tx || t2 <= c3 {
+		return RuneError, 1, false
+	}
+
+	// 4-byte, 21-bit sequence?
+	if c0 < t5 {
+		r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
+		if r <= rune3Max {
+			return RuneError, 1, false
+		}
+		return r, 4, false
+	}
+
+	// error
+	return RuneError, 1, false
+}
+
+func decodeRuneInStringInternal(s string) (r rune, size int, short bool) {
+	n := len(s)
+	if n < 1 {
+		return RuneError, 0, true
+	}
+	c0 := s[0]
+
+	// 1-byte, 7-bit sequence?
+	if c0 < tx {
+		return rune(c0), 1, false
+	}
+
+	// unexpected continuation byte?
+	if c0 < t2 {
+		return RuneError, 1, false
+	}
+
+	// need first continuation byte
+	if n < 2 {
+		return RuneError, 1, true
+	}
+	c1 := s[1]
+	if c1 < tx || t2 <= c1 {
+		return RuneError, 1, false
+	}
+
+	// 2-byte, 11-bit sequence?
+	if c0 < t3 {
+		r = rune(c0&mask2)<<6 | rune(c1&maskx)
+		if r <= rune1Max {
+			return RuneError, 1, false
+		}
+		return r, 2, false
+	}
+
+	// need second continuation byte
+	if n < 3 {
+		return RuneError, 1, true
+	}
+	c2 := s[2]
+	if c2 < tx || t2 <= c2 {
+		return RuneError, 1, false
+	}
+
+	// 3-byte, 16-bit sequence?
+	if c0 < t4 {
+		r = rune(c0&mask3)<<12 | rune(c1&maskx)<<6 | rune(c2&maskx)
+		if r <= rune2Max {
+			return RuneError, 1, false
+		}
+		return r, 3, false
+	}
+
+	// need third continuation byte
+	if n < 4 {
+		return RuneError, 1, true
+	}
+	c3 := s[3]
+	if c3 < tx || t2 <= c3 {
+		return RuneError, 1, false
+	}
+
+	// 4-byte, 21-bit sequence?
+	if c0 < t5 {
+		r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
+		if r <= rune3Max {
+			return RuneError, 1, false
+		}
+		return r, 4, false
+	}
+
+	// error
+	return RuneError, 1, false
+}
+
+// FullRune reports whether the bytes in p begin with a full UTF-8 encoding of a rune.
+// An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
+func FullRune(p []byte) bool {
+	_, _, short := decodeRuneInternal(p)
+	return !short
+}
+
+// FullRuneInString is like FullRune but its input is a string.
+func FullRuneInString(s string) bool {
+	_, _, short := decodeRuneInStringInternal(s)
+	return !short
+}
+
+// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and its width in bytes.
+func DecodeRune(p []byte) (r rune, size int) {
+	r, size, _ = decodeRuneInternal(p)
+	return
+}
+
+// DecodeRuneInString is like DecodeRune but its input is a string.
+func DecodeRuneInString(s string) (r rune, size int) {
+	r, size, _ = decodeRuneInStringInternal(s)
+	return
+}
+
+// DecodeLastRune unpacks the last UTF-8 encoding in p
+// and returns the rune and its width in bytes.
+func DecodeLastRune(p []byte) (r rune, size int) {
+	end := len(p)
+	if end == 0 {
+		return RuneError, 0
+	}
+	start := end - 1
+	r = rune(p[start])
+	if r < RuneSelf {
+		return r, 1
+	}
+	// guard against O(n^2) behavior when traversing
+	// backwards through strings with long sequences of
+	// invalid UTF-8.
+	lim := end - UTFMax
+	if lim < 0 {
+		lim = 0
+	}
+	for start--; start >= lim; start-- {
+		if RuneStart(p[start]) {
+			break
+		}
+	}
+	if start < 0 {
+		start = 0
+	}
+	r, size = DecodeRune(p[start:end])
+	if start+size != end {
+		return RuneError, 1
+	}
+	return r, size
+}
+
+// DecodeLastRuneInString is like DecodeLastRune but its input is a string.
+func DecodeLastRuneInString(s string) (r rune, size int) {
+	end := len(s)
+	if end == 0 {
+		return RuneError, 0
+	}
+	start := end - 1
+	r = rune(s[start])
+	if r < RuneSelf {
+		return r, 1
+	}
+	// guard against O(n^2) behavior when traversing
+	// backwards through strings with long sequences of
+	// invalid UTF-8.
+	lim := end - UTFMax
+	if lim < 0 {
+		lim = 0
+	}
+	for start--; start >= lim; start-- {
+		if RuneStart(s[start]) {
+			break
+		}
+	}
+	if start < 0 {
+		start = 0
+	}
+	r, size = DecodeRuneInString(s[start:end])
+	if start+size != end {
+		return RuneError, 1
+	}
+	return r, size
+}
+
+// RuneLen returns the number of bytes required to encode the rune.
+func RuneLen(r rune) int {
+	switch {
+	case r <= rune1Max:
+		return 1
+	case r <= rune2Max:
+		return 2
+	case r <= rune3Max:
+		return 3
+	case r <= rune4Max:
+		return 4
+	}
+	return -1
+}
+
+// EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune.
+// It returns the number of bytes written.
+func EncodeRune(p []byte, r rune) int {
+	// Negative values are erroneous.  Making it unsigned addresses the problem.
+	if uint32(r) <= rune1Max {
+		p[0] = byte(r)
+		return 1
+	}
+
+	if uint32(r) <= rune2Max {
+		p[0] = t2 | byte(r>>6)
+		p[1] = tx | byte(r)&maskx
+		return 2
+	}
+
+	if uint32(r) > unicode.MaxRune {
+		r = RuneError
+	}
+
+	if uint32(r) <= rune3Max {
+		p[0] = t3 | byte(r>>12)
+		p[1] = tx | byte(r>>6)&maskx
+		p[2] = tx | byte(r)&maskx
+		return 3
+	}
+
+	p[0] = t4 | byte(r>>18)
+	p[1] = tx | byte(r>>12)&maskx
+	p[2] = tx | byte(r>>6)&maskx
+	p[3] = tx | byte(r)&maskx
+	return 4
+}
+
+// RuneCount returns the number of runes in p.  Erroneous and short
+// encodings are treated as single runes of width 1 byte.
+func RuneCount(p []byte) int {
+	i := 0
+	var n int
+	for n = 0; i < len(p); n++ {
+		if p[i] < RuneSelf {
+			i++
+		} else {
+			_, size := DecodeRune(p[i:])
+			i += size
+		}
+	}
+	return n
+}
+
+// RuneCountInString is like RuneCount but its input is a string.
+func RuneCountInString(s string) (n int) {
+	for _ = range s {
+		n++
+	}
+	return
+}
+
+// RuneStart reports whether the byte could be the first byte of
+// an encoded rune.  Second and subsequent bytes always have the top
+// two bits set to 10.
+func RuneStart(b byte) bool { return b&0xC0 != 0x80 }
+
+// Valid reports whether p consists entirely of valid UTF-8-encoded runes.
+func Valid(p []byte) bool {
+	i := 0
+	for i < len(p) {
+		if p[i] < RuneSelf {
+			i++
+		} else {
+			_, size := DecodeRune(p[i:])
+			if size == 1 {
+				// All valid runes of size of 1 (those
+				// below RuneSelf) were handled above.
+				// This must be a RuneError.
+				return false
+			}
+			i += size
+		}
+	}
+	return true
+}
+
+// ValidString reports whether s consists entirely of valid UTF-8-encoded runes.
+func ValidString(s string) bool {
+	for i, r := range s {
+		if r == RuneError {
+			// The RuneError value can be an error
+			// sentinel value (if it's size 1) or the same
+			// value encoded properly. Decode it to see if
+			// it's the 1 byte sentinel value.
+			_, size := DecodeRuneInString(s[i:])
+			if size == 1 {
+				return false
+			}
+		}
+	}
+	return true
+}
diff --git a/src/pkg/unicode/utf8/utf8_test.go b/src/pkg/unicode/utf8/utf8_test.go
new file mode 100644
index 0000000..6351426
--- /dev/null
+++ b/src/pkg/unicode/utf8/utf8_test.go
@@ -0,0 +1,344 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package utf8_test
+
+import (
+	"bytes"
+	"testing"
+	. "unicode/utf8"
+)
+
+type Utf8Map struct {
+	r   rune
+	str string
+}
+
+var utf8map = []Utf8Map{
+	{0x0000, "\x00"},
+	{0x0001, "\x01"},
+	{0x007e, "\x7e"},
+	{0x007f, "\x7f"},
+	{0x0080, "\xc2\x80"},
+	{0x0081, "\xc2\x81"},
+	{0x00bf, "\xc2\xbf"},
+	{0x00c0, "\xc3\x80"},
+	{0x00c1, "\xc3\x81"},
+	{0x00c8, "\xc3\x88"},
+	{0x00d0, "\xc3\x90"},
+	{0x00e0, "\xc3\xa0"},
+	{0x00f0, "\xc3\xb0"},
+	{0x00f8, "\xc3\xb8"},
+	{0x00ff, "\xc3\xbf"},
+	{0x0100, "\xc4\x80"},
+	{0x07ff, "\xdf\xbf"},
+	{0x0800, "\xe0\xa0\x80"},
+	{0x0801, "\xe0\xa0\x81"},
+	{0xfffe, "\xef\xbf\xbe"},
+	{0xffff, "\xef\xbf\xbf"},
+	{0x10000, "\xf0\x90\x80\x80"},
+	{0x10001, "\xf0\x90\x80\x81"},
+	{0x10fffe, "\xf4\x8f\xbf\xbe"},
+	{0x10ffff, "\xf4\x8f\xbf\xbf"},
+	{0xFFFD, "\xef\xbf\xbd"},
+}
+
+var testStrings = []string{
+	"",
+	"abcd",
+	"☺☻☹",
+	"日a本b語ç日ð本Ê語þ日¥本¼語i日©",
+	"日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©",
+	"\x80\x80\x80\x80",
+}
+
+func TestFullRune(t *testing.T) {
+	for i := 0; i < len(utf8map); i++ {
+		m := utf8map[i]
+		b := []byte(m.str)
+		if !FullRune(b) {
+			t.Errorf("FullRune(%q) (%U) = false, want true", b, m.r)
+		}
+		s := m.str
+		if !FullRuneInString(s) {
+			t.Errorf("FullRuneInString(%q) (%U) = false, want true", s, m.r)
+		}
+		b1 := b[0 : len(b)-1]
+		if FullRune(b1) {
+			t.Errorf("FullRune(%q) = true, want false", b1)
+		}
+		s1 := string(b1)
+		if FullRuneInString(s1) {
+			t.Errorf("FullRune(%q) = true, want false", s1)
+		}
+	}
+}
+
+func TestEncodeRune(t *testing.T) {
+	for i := 0; i < len(utf8map); i++ {
+		m := utf8map[i]
+		b := []byte(m.str)
+		var buf [10]byte
+		n := EncodeRune(buf[0:], m.r)
+		b1 := buf[0:n]
+		if !bytes.Equal(b, b1) {
+			t.Errorf("EncodeRune(%#04x) = %q want %q", m.r, b1, b)
+		}
+	}
+}
+
+func TestDecodeRune(t *testing.T) {
+	for i := 0; i < len(utf8map); i++ {
+		m := utf8map[i]
+		b := []byte(m.str)
+		r, size := DecodeRune(b)
+		if r != m.r || size != len(b) {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, m.r, len(b))
+		}
+		s := m.str
+		r, size = DecodeRuneInString(s)
+		if r != m.r || size != len(b) {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", s, r, size, m.r, len(b))
+		}
+
+		// there's an extra byte that bytes left behind - make sure trailing byte works
+		r, size = DecodeRune(b[0:cap(b)])
+		if r != m.r || size != len(b) {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, m.r, len(b))
+		}
+		s = m.str + "\x00"
+		r, size = DecodeRuneInString(s)
+		if r != m.r || size != len(b) {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, m.r, len(b))
+		}
+
+		// make sure missing bytes fail
+		wantsize := 1
+		if wantsize >= len(b) {
+			wantsize = 0
+		}
+		r, size = DecodeRune(b[0 : len(b)-1])
+		if r != RuneError || size != wantsize {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b[0:len(b)-1], r, size, RuneError, wantsize)
+		}
+		s = m.str[0 : len(m.str)-1]
+		r, size = DecodeRuneInString(s)
+		if r != RuneError || size != wantsize {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, RuneError, wantsize)
+		}
+
+		// make sure bad sequences fail
+		if len(b) == 1 {
+			b[0] = 0x80
+		} else {
+			b[len(b)-1] = 0x7F
+		}
+		r, size = DecodeRune(b)
+		if r != RuneError || size != 1 {
+			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, RuneError, 1)
+		}
+		s = string(b)
+		r, size = DecodeRune(b)
+		if r != RuneError || size != 1 {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, RuneError, 1)
+		}
+
+	}
+}
+
+// Check that DecodeRune and DecodeLastRune correspond to
+// the equivalent range loop.
+func TestSequencing(t *testing.T) {
+	for _, ts := range testStrings {
+		for _, m := range utf8map {
+			for _, s := range []string{ts + m.str, m.str + ts, ts + m.str + ts} {
+				testSequence(t, s)
+			}
+		}
+	}
+}
+
+// Check that a range loop and a []int conversion visit the same runes.
+// Not really a test of this package, but the assumption is used here and
+// it's good to verify
+func TestIntConversion(t *testing.T) {
+	for _, ts := range testStrings {
+		runes := []rune(ts)
+		if RuneCountInString(ts) != len(runes) {
+			t.Errorf("%q: expected %d runes; got %d", ts, len(runes), RuneCountInString(ts))
+			break
+		}
+		i := 0
+		for _, r := range ts {
+			if r != runes[i] {
+				t.Errorf("%q[%d]: expected %c (%U); got %c (%U)", ts, i, runes[i], runes[i], r, r)
+			}
+			i++
+		}
+	}
+}
+
+func testSequence(t *testing.T, s string) {
+	type info struct {
+		index int
+		r     rune
+	}
+	index := make([]info, len(s))
+	b := []byte(s)
+	si := 0
+	j := 0
+	for i, r := range s {
+		if si != i {
+			t.Errorf("Sequence(%q) mismatched index %d, want %d", s, si, i)
+			return
+		}
+		index[j] = info{i, r}
+		j++
+		r1, size1 := DecodeRune(b[i:])
+		if r != r1 {
+			t.Errorf("DecodeRune(%q) = %#04x, want %#04x", s[i:], r1, r)
+			return
+		}
+		r2, size2 := DecodeRuneInString(s[i:])
+		if r != r2 {
+			t.Errorf("DecodeRuneInString(%q) = %#04x, want %#04x", s[i:], r2, r)
+			return
+		}
+		if size1 != size2 {
+			t.Errorf("DecodeRune/DecodeRuneInString(%q) size mismatch %d/%d", s[i:], size1, size2)
+			return
+		}
+		si += size1
+	}
+	j--
+	for si = len(s); si > 0; {
+		r1, size1 := DecodeLastRune(b[0:si])
+		r2, size2 := DecodeLastRuneInString(s[0:si])
+		if size1 != size2 {
+			t.Errorf("DecodeLastRune/DecodeLastRuneInString(%q, %d) size mismatch %d/%d", s, si, size1, size2)
+			return
+		}
+		if r1 != index[j].r {
+			t.Errorf("DecodeLastRune(%q, %d) = %#04x, want %#04x", s, si, r1, index[j].r)
+			return
+		}
+		if r2 != index[j].r {
+			t.Errorf("DecodeLastRuneInString(%q, %d) = %#04x, want %#04x", s, si, r2, index[j].r)
+			return
+		}
+		si -= size1
+		if si != index[j].index {
+			t.Errorf("DecodeLastRune(%q) index mismatch at %d, want %d", s, si, index[j].index)
+			return
+		}
+		j--
+	}
+	if si != 0 {
+		t.Errorf("DecodeLastRune(%q) finished at %d, not 0", s, si)
+	}
+}
+
+// Check that negative runes encode as U+FFFD.
+func TestNegativeRune(t *testing.T) {
+	errorbuf := make([]byte, UTFMax)
+	errorbuf = errorbuf[0:EncodeRune(errorbuf, RuneError)]
+	buf := make([]byte, UTFMax)
+	buf = buf[0:EncodeRune(buf, -1)]
+	if !bytes.Equal(buf, errorbuf) {
+		t.Errorf("incorrect encoding [% x] for -1; expected [% x]", buf, errorbuf)
+	}
+}
+
+type RuneCountTest struct {
+	in  string
+	out int
+}
+
+var runecounttests = []RuneCountTest{
+	{"abcd", 4},
+	{"☺☻☹", 3},
+	{"1,2,3,4", 7},
+	{"\xe2\x00", 2},
+}
+
+func TestRuneCount(t *testing.T) {
+	for i := 0; i < len(runecounttests); i++ {
+		tt := runecounttests[i]
+		if out := RuneCountInString(tt.in); out != tt.out {
+			t.Errorf("RuneCountInString(%q) = %d, want %d", tt.in, out, tt.out)
+		}
+		if out := RuneCount([]byte(tt.in)); out != tt.out {
+			t.Errorf("RuneCount(%q) = %d, want %d", tt.in, out, tt.out)
+		}
+	}
+}
+
+type ValidTest struct {
+	in  string
+	out bool
+}
+
+var validTests = []ValidTest{
+	{"", true},
+	{"a", true},
+	{"abc", true},
+	{"Ж", true},
+	{"ЖЖ", true},
+	{"брэд-ЛГТМ", true},
+	{"☺☻☹", true},
+	{string([]byte{66, 250}), false},
+	{string([]byte{66, 250, 67}), false},
+	{"a\uFFFDb", true},
+}
+
+func TestValid(t *testing.T) {
+	for i, tt := range validTests {
+		if Valid([]byte(tt.in)) != tt.out {
+			t.Errorf("%d. Valid(%q) = %v; want %v", i, tt.in, !tt.out, tt.out)
+		}
+		if ValidString(tt.in) != tt.out {
+			t.Errorf("%d. ValidString(%q) = %v; want %v", i, tt.in, !tt.out, tt.out)
+		}
+	}
+}
+
+func BenchmarkRuneCountTenASCIIChars(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		RuneCountInString("0123456789")
+	}
+}
+
+func BenchmarkRuneCountTenJapaneseChars(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		RuneCountInString("日本語日本語日本語日")
+	}
+}
+
+func BenchmarkEncodeASCIIRune(b *testing.B) {
+	buf := make([]byte, UTFMax)
+	for i := 0; i < b.N; i++ {
+		EncodeRune(buf, 'a')
+	}
+}
+
+func BenchmarkEncodeJapaneseRune(b *testing.B) {
+	buf := make([]byte, UTFMax)
+	for i := 0; i < b.N; i++ {
+		EncodeRune(buf, '本')
+	}
+}
+
+func BenchmarkDecodeASCIIRune(b *testing.B) {
+	a := []byte{'a'}
+	for i := 0; i < b.N; i++ {
+		DecodeRune(a)
+	}
+}
+
+func BenchmarkDecodeJapaneseRune(b *testing.B) {
+	nihon := []byte("本")
+	for i := 0; i < b.N; i++ {
+		DecodeRune(nihon)
+	}
+}
diff --git a/src/pkg/unsafe/unsafe.go b/src/pkg/unsafe/unsafe.go
index c49f54d..4955c2f 100644
--- a/src/pkg/unsafe/unsafe.go
+++ b/src/pkg/unsafe/unsafe.go
@@ -52,7 +52,7 @@ func Unreflect(typ interface{}, addr Pointer) (ret interface{})
 
 // New allocates and returns a pointer to memory for a new value of the given type.
 // The typ is assumed to hold a pointer to a runtime type.
-// Callers should use reflect.MakeZero instead of invoking unsafe.New directly.
+// Callers should use reflect.New or reflect.Zero instead of invoking unsafe.New directly.
 func New(typ interface{}) Pointer
 
 // NewArray allocates and returns a pointer to an array of n elements of the given type.
diff --git a/src/pkg/url/Makefile b/src/pkg/url/Makefile
deleted file mode 100644
index b9267bd..0000000
--- a/src/pkg/url/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=url
-GOFILES=\
-	url.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/url/url.go b/src/pkg/url/url.go
deleted file mode 100644
index 9d19348..0000000
--- a/src/pkg/url/url.go
+++ /dev/null
@@ -1,685 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package URL parses URLs and implements query escaping.
-// See RFC 3986.
-package url
-
-import (
-	"os"
-	"strconv"
-	"strings"
-)
-
-// Error reports an error and the operation and URL that caused it.
-type Error struct {
-	Op    string
-	URL   string
-	Error os.Error
-}
-
-func (e *Error) String() string { return e.Op + " " + e.URL + ": " + e.Error.String() }
-
-func ishex(c byte) bool {
-	switch {
-	case '0' <= c && c <= '9':
-		return true
-	case 'a' <= c && c <= 'f':
-		return true
-	case 'A' <= c && c <= 'F':
-		return true
-	}
-	return false
-}
-
-func unhex(c byte) byte {
-	switch {
-	case '0' <= c && c <= '9':
-		return c - '0'
-	case 'a' <= c && c <= 'f':
-		return c - 'a' + 10
-	case 'A' <= c && c <= 'F':
-		return c - 'A' + 10
-	}
-	return 0
-}
-
-type encoding int
-
-const (
-	encodePath encoding = 1 + iota
-	encodeUserPassword
-	encodeQueryComponent
-	encodeFragment
-	encodeOpaque
-)
-
-type EscapeError string
-
-func (e EscapeError) String() string {
-	return "invalid URL escape " + strconv.Quote(string(e))
-}
-
-// Return true if the specified character should be escaped when
-// appearing in a URL string, according to RFC 2396.
-// When 'all' is true the full range of reserved characters are matched.
-func shouldEscape(c byte, mode encoding) bool {
-	// RFC 2396 §2.3 Unreserved characters (alphanum)
-	if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' {
-		return false
-	}
-	switch c {
-	case '-', '_', '.', '!', '~', '*', '\'', '(', ')': // §2.3 Unreserved characters (mark)
-		return false
-
-	case '$', '&', '+', ',', '/', ':', ';', '=', '?', '@': // §2.2 Reserved characters (reserved)
-		// Different sections of the URL allow a few of
-		// the reserved characters to appear unescaped.
-		switch mode {
-		case encodePath: // §3.3
-			// The RFC allows : @ & = + $ , but saves / ; for assigning
-			// meaning to individual path segments.  This package
-			// only manipulates the path as a whole, so we allow those
-			// last two as well.  Clients that need to distinguish between
-			// `/foo;y=z/bar` and `/foo%3by=z/bar` will have to re-decode RawPath.
-			// That leaves only ? to escape.
-			return c == '?'
-
-		case encodeUserPassword: // §3.2.2
-			// The RFC allows ; : & = + $ , in userinfo, so we must escape only @ and /.
-			// The parsing of userinfo treats : as special so we must escape that too.
-			return c == '@' || c == '/' || c == ':'
-
-		case encodeQueryComponent: // §3.4
-			// The RFC reserves (so we must escape) everything.
-			return true
-
-		case encodeFragment: // §4.1
-			// The RFC text is silent but the grammar allows
-			// everything, so escape nothing.
-			return false
-
-		case encodeOpaque: // §3 opaque_part
-			// The RFC allows opaque_part to use all characters
-			// except that the leading / must be escaped.
-			// (We implement that case in String.)
-			return false
-		}
-	}
-
-	// Everything else must be escaped.
-	return true
-}
-
-// QueryUnescape does the inverse transformation of QueryEscape, converting
-// %AB into the byte 0xAB and '+' into ' ' (space). It returns an error if
-// any % is not followed by two hexadecimal digits.
-func QueryUnescape(s string) (string, os.Error) {
-	return unescape(s, encodeQueryComponent)
-}
-
-// unescape unescapes a string; the mode specifies
-// which section of the URL string is being unescaped.
-func unescape(s string, mode encoding) (string, os.Error) {
-	// Count %, check that they're well-formed.
-	n := 0
-	hasPlus := false
-	for i := 0; i < len(s); {
-		switch s[i] {
-		case '%':
-			n++
-			if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
-				s = s[i:]
-				if len(s) > 3 {
-					s = s[0:3]
-				}
-				return "", EscapeError(s)
-			}
-			i += 3
-		case '+':
-			hasPlus = mode == encodeQueryComponent
-			i++
-		default:
-			i++
-		}
-	}
-
-	if n == 0 && !hasPlus {
-		return s, nil
-	}
-
-	t := make([]byte, len(s)-2*n)
-	j := 0
-	for i := 0; i < len(s); {
-		switch s[i] {
-		case '%':
-			t[j] = unhex(s[i+1])<<4 | unhex(s[i+2])
-			j++
-			i += 3
-		case '+':
-			if mode == encodeQueryComponent {
-				t[j] = ' '
-			} else {
-				t[j] = '+'
-			}
-			j++
-			i++
-		default:
-			t[j] = s[i]
-			j++
-			i++
-		}
-	}
-	return string(t), nil
-}
-
-// QueryEscape escapes the string so it can be safely placed
-// inside a URL query.
-func QueryEscape(s string) string {
-	return escape(s, encodeQueryComponent)
-}
-
-func escape(s string, mode encoding) string {
-	spaceCount, hexCount := 0, 0
-	for i := 0; i < len(s); i++ {
-		c := s[i]
-		if shouldEscape(c, mode) {
-			if c == ' ' && mode == encodeQueryComponent {
-				spaceCount++
-			} else {
-				hexCount++
-			}
-		}
-	}
-
-	if spaceCount == 0 && hexCount == 0 {
-		return s
-	}
-
-	t := make([]byte, len(s)+2*hexCount)
-	j := 0
-	for i := 0; i < len(s); i++ {
-		switch c := s[i]; {
-		case c == ' ' && mode == encodeQueryComponent:
-			t[j] = '+'
-			j++
-		case shouldEscape(c, mode):
-			t[j] = '%'
-			t[j+1] = "0123456789ABCDEF"[c>>4]
-			t[j+2] = "0123456789ABCDEF"[c&15]
-			j += 3
-		default:
-			t[j] = s[i]
-			j++
-		}
-	}
-	return string(t)
-}
-
-// UnescapeUserinfo parses the RawUserinfo field of a URL
-// as the form user or user:password and unescapes and returns
-// the two halves.
-//
-// This functionality should only be used with legacy web sites.
-// RFC 2396 warns that interpreting Userinfo this way
-// ``is NOT RECOMMENDED, because the passing of authentication
-// information in clear text (such as URI) has proven to be a
-// security risk in almost every case where it has been used.''
-func UnescapeUserinfo(rawUserinfo string) (user, password string, err os.Error) {
-	u, p := split(rawUserinfo, ':', true)
-	if user, err = unescape(u, encodeUserPassword); err != nil {
-		return "", "", err
-	}
-	if password, err = unescape(p, encodeUserPassword); err != nil {
-		return "", "", err
-	}
-	return
-}
-
-// EscapeUserinfo combines user and password in the form
-// user:password (or just user if password is empty) and then
-// escapes it for use as the URL.RawUserinfo field.
-//
-// This functionality should only be used with legacy web sites.
-// RFC 2396 warns that interpreting Userinfo this way
-// ``is NOT RECOMMENDED, because the passing of authentication
-// information in clear text (such as URI) has proven to be a
-// security risk in almost every case where it has been used.''
-func EscapeUserinfo(user, password string) string {
-	raw := escape(user, encodeUserPassword)
-	if password != "" {
-		raw += ":" + escape(password, encodeUserPassword)
-	}
-	return raw
-}
-
-// A URL represents a parsed URL (technically, a URI reference).
-// The general form represented is:
-//	scheme://[userinfo@]host/path[?query][#fragment]
-// The Raw, RawAuthority, RawPath, and RawQuery fields are in "wire format"
-// (special characters must be hex-escaped if not meant to have special meaning).
-// All other fields are logical values; '+' or '%' represent themselves.
-//
-// The various Raw values are supplied in wire format because
-// clients typically have to split them into pieces before further
-// decoding.
-type URL struct {
-	Raw          string // the original string
-	Scheme       string // scheme
-	RawAuthority string // [userinfo@]host
-	RawUserinfo  string // userinfo
-	Host         string // host
-	RawPath      string // /path[?query][#fragment]
-	Path         string // /path
-	OpaquePath   bool   // path is opaque (unrooted when scheme is present)
-	RawQuery     string // query
-	Fragment     string // fragment
-}
-
-// Maybe rawurl is of the form scheme:path.
-// (Scheme must be [a-zA-Z][a-zA-Z0-9+-.]*)
-// If so, return scheme, path; else return "", rawurl.
-func getscheme(rawurl string) (scheme, path string, err os.Error) {
-	for i := 0; i < len(rawurl); i++ {
-		c := rawurl[i]
-		switch {
-		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
-		// do nothing
-		case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.':
-			if i == 0 {
-				return "", rawurl, nil
-			}
-		case c == ':':
-			if i == 0 {
-				return "", "", os.NewError("missing protocol scheme")
-			}
-			return rawurl[0:i], rawurl[i+1:], nil
-		default:
-			// we have encountered an invalid character,
-			// so there is no valid scheme
-			return "", rawurl, nil
-		}
-	}
-	return "", rawurl, nil
-}
-
-// Maybe s is of the form t c u.
-// If so, return t, c u (or t, u if cutc == true).
-// If not, return s, "".
-func split(s string, c byte, cutc bool) (string, string) {
-	for i := 0; i < len(s); i++ {
-		if s[i] == c {
-			if cutc {
-				return s[0:i], s[i+1:]
-			}
-			return s[0:i], s[i:]
-		}
-	}
-	return s, ""
-}
-
-// Parse parses rawurl into a URL structure.
-// The string rawurl is assumed not to have a #fragment suffix.
-// (Web browsers strip #fragment before sending the URL to a web server.)
-// The rawurl may be relative or absolute.
-func Parse(rawurl string) (url *URL, err os.Error) {
-	return parse(rawurl, false)
-}
-
-// ParseRequest parses rawurl into a URL structure.  It assumes that
-// rawurl was received from an HTTP request, so the rawurl is interpreted
-// only as an absolute URI or an absolute path.
-// The string rawurl is assumed not to have a #fragment suffix.
-// (Web browsers strip #fragment before sending the URL to a web server.)
-func ParseRequest(rawurl string) (url *URL, err os.Error) {
-	return parse(rawurl, true)
-}
-
-// parse parses a URL from a string in one of two contexts.  If
-// viaRequest is true, the URL is assumed to have arrived via an HTTP request,
-// in which case only absolute URLs or path-absolute relative URLs are allowed.
-// If viaRequest is false, all forms of relative URLs are allowed.
-func parse(rawurl string, viaRequest bool) (url *URL, err os.Error) {
-	var (
-		leadingSlash bool
-		path         string
-	)
-
-	if rawurl == "" {
-		err = os.NewError("empty url")
-		goto Error
-	}
-	url = new(URL)
-	url.Raw = rawurl
-
-	// Split off possible leading "http:", "mailto:", etc.
-	// Cannot contain escaped characters.
-	if url.Scheme, path, err = getscheme(rawurl); err != nil {
-		goto Error
-	}
-	leadingSlash = strings.HasPrefix(path, "/")
-
-	if url.Scheme != "" && !leadingSlash {
-		// RFC 2396:
-		// Absolute URI (has scheme) with non-rooted path
-		// is uninterpreted.  It doesn't even have a ?query.
-		// This is the case that handles mailto:name at example.com.
-		url.RawPath = path
-
-		if url.Path, err = unescape(path, encodeOpaque); err != nil {
-			goto Error
-		}
-		url.OpaquePath = true
-	} else {
-		if viaRequest && !leadingSlash {
-			err = os.NewError("invalid URI for request")
-			goto Error
-		}
-
-		// Split off query before parsing path further.
-		url.RawPath = path
-		path, query := split(path, '?', false)
-		if len(query) > 1 {
-			url.RawQuery = query[1:]
-		}
-
-		// Maybe path is //authority/path
-		if (url.Scheme != "" || !viaRequest) &&
-			strings.HasPrefix(path, "//") && !strings.HasPrefix(path, "///") {
-			url.RawAuthority, path = split(path[2:], '/', false)
-			url.RawPath = url.RawPath[2+len(url.RawAuthority):]
-		}
-
-		// Split authority into userinfo at host.
-		// If there's no @, split's default is wrong.  Check explicitly.
-		var rawHost string
-		if strings.Index(url.RawAuthority, "@") < 0 {
-			rawHost = url.RawAuthority
-		} else {
-			url.RawUserinfo, rawHost = split(url.RawAuthority, '@', true)
-		}
-
-		// We leave RawAuthority only in raw form because clients
-		// of common protocols should be using Userinfo and Host
-		// instead.  Clients that wish to use RawAuthority will have to
-		// interpret it themselves: RFC 2396 does not define the meaning.
-
-		if strings.Contains(rawHost, "%") {
-			// Host cannot contain escaped characters.
-			err = os.NewError("hexadecimal escape in host")
-			goto Error
-		}
-		url.Host = rawHost
-
-		if url.Path, err = unescape(path, encodePath); err != nil {
-			goto Error
-		}
-	}
-	return url, nil
-
-Error:
-	return nil, &Error{"parse", rawurl, err}
-
-}
-
-// ParseWithReference is like Parse but allows a trailing #fragment.
-func ParseWithReference(rawurlref string) (url *URL, err os.Error) {
-	// Cut off #frag.
-	rawurl, frag := split(rawurlref, '#', false)
-	if url, err = Parse(rawurl); err != nil {
-		return nil, err
-	}
-	url.Raw += frag
-	url.RawPath += frag
-	if len(frag) > 1 {
-		frag = frag[1:]
-		if url.Fragment, err = unescape(frag, encodeFragment); err != nil {
-			return nil, &Error{"parse", rawurl, err}
-		}
-	}
-	return url, nil
-}
-
-// String reassembles url into a valid URL string.
-//
-// There are redundant fields stored in the URL structure:
-// the String method consults Scheme, Path, Host, RawUserinfo,
-// RawQuery, and Fragment, but not Raw, RawPath or RawAuthority.
-func (url *URL) String() string {
-	result := ""
-	if url.Scheme != "" {
-		result += url.Scheme + ":"
-	}
-	if url.Host != "" || url.RawUserinfo != "" {
-		result += "//"
-		if url.RawUserinfo != "" {
-			// hide the password, if any
-			info := url.RawUserinfo
-			if i := strings.Index(info, ":"); i >= 0 {
-				info = info[0:i] + ":******"
-			}
-			result += info + "@"
-		}
-		result += url.Host
-	}
-	if url.OpaquePath {
-		path := url.Path
-		if strings.HasPrefix(path, "/") {
-			result += "%2f"
-			path = path[1:]
-		}
-		result += escape(path, encodeOpaque)
-	} else {
-		result += escape(url.Path, encodePath)
-	}
-	if url.RawQuery != "" {
-		result += "?" + url.RawQuery
-	}
-	if url.Fragment != "" {
-		result += "#" + escape(url.Fragment, encodeFragment)
-	}
-	return result
-}
-
-// Values maps a string key to a list of values.
-// It is typically used for query parameters and form values.
-// Unlike in the http.Header map, the keys in a Values map
-// are case-sensitive.
-type Values map[string][]string
-
-// Get gets the first value associated with the given key.
-// If there are no values associated with the key, Get returns
-// the empty string. To access multiple values, use the map
-// directly.
-func (v Values) Get(key string) string {
-	if v == nil {
-		return ""
-	}
-	vs, ok := v[key]
-	if !ok || len(vs) == 0 {
-		return ""
-	}
-	return vs[0]
-}
-
-// Set sets the key to value. It replaces any existing
-// values.
-func (v Values) Set(key, value string) {
-	v[key] = []string{value}
-}
-
-// Add adds the key to value. It appends to any existing
-// values associated with key.
-func (v Values) Add(key, value string) {
-	v[key] = append(v[key], value)
-}
-
-// Del deletes the values associated with key.
-func (v Values) Del(key string) {
-	v[key] = nil, false
-}
-
-// ParseQuery parses the URL-encoded query string and returns
-// a map listing the values specified for each key.
-// ParseQuery always returns a non-nil map containing all the
-// valid query parameters found; err describes the first decoding error
-// encountered, if any.
-func ParseQuery(query string) (m Values, err os.Error) {
-	m = make(Values)
-	err = parseQuery(m, query)
-	return
-}
-
-func parseQuery(m Values, query string) (err os.Error) {
-	for query != "" {
-		key := query
-		if i := strings.IndexAny(key, "&;"); i >= 0 {
-			key, query = key[:i], key[i+1:]
-		} else {
-			query = ""
-		}
-		if key == "" {
-			continue
-		}
-		value := ""
-		if i := strings.Index(key, "="); i >= 0 {
-			key, value = key[:i], key[i+1:]
-		}
-		key, err1 := QueryUnescape(key)
-		if err1 != nil {
-			err = err1
-			continue
-		}
-		value, err1 = QueryUnescape(value)
-		if err1 != nil {
-			err = err1
-			continue
-		}
-		m[key] = append(m[key], value)
-	}
-	return err
-}
-
-// Encode encodes the values into ``URL encoded'' form.
-// e.g. "foo=bar&bar=baz"
-func (v Values) Encode() string {
-	if v == nil {
-		return ""
-	}
-	parts := make([]string, 0, len(v)) // will be large enough for most uses
-	for k, vs := range v {
-		prefix := QueryEscape(k) + "="
-		for _, v := range vs {
-			parts = append(parts, prefix+QueryEscape(v))
-		}
-	}
-	return strings.Join(parts, "&")
-}
-
-// resolvePath applies special path segments from refs and applies
-// them to base, per RFC 2396.
-func resolvePath(basepath string, refpath string) string {
-	base := strings.Split(basepath, "/")
-	refs := strings.Split(refpath, "/")
-	if len(base) == 0 {
-		base = []string{""}
-	}
-	for idx, ref := range refs {
-		switch {
-		case ref == ".":
-			base[len(base)-1] = ""
-		case ref == "..":
-			newLen := len(base) - 1
-			if newLen < 1 {
-				newLen = 1
-			}
-			base = base[0:newLen]
-			base[len(base)-1] = ""
-		default:
-			if idx == 0 || base[len(base)-1] == "" {
-				base[len(base)-1] = ref
-			} else {
-				base = append(base, ref)
-			}
-		}
-	}
-	return strings.Join(base, "/")
-}
-
-// IsAbs returns true if the URL is absolute.
-func (url *URL) IsAbs() bool {
-	return url.Scheme != ""
-}
-
-// Parse parses a URL in the context of a base URL.  The URL in ref
-// may be relative or absolute.  Parse returns nil, err on parse
-// failure, otherwise its return value is the same as ResolveReference.
-func (base *URL) Parse(ref string) (*URL, os.Error) {
-	refurl, err := Parse(ref)
-	if err != nil {
-		return nil, err
-	}
-	return base.ResolveReference(refurl), nil
-}
-
-// ResolveReference resolves a URI reference to an absolute URI from
-// an absolute base URI, per RFC 2396 Section 5.2.  The URI reference
-// may be relative or absolute.  ResolveReference always returns a new
-// URL instance, even if the returned URL is identical to either the
-// base or reference. If ref is an absolute URL, then ResolveReference
-// ignores base and returns a copy of ref.
-func (base *URL) ResolveReference(ref *URL) *URL {
-	url := new(URL)
-	switch {
-	case ref.IsAbs():
-		*url = *ref
-	default:
-		// relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]
-		*url = *base
-		if ref.RawAuthority != "" {
-			// The "net_path" case.
-			url.RawAuthority = ref.RawAuthority
-			url.Host = ref.Host
-			url.RawUserinfo = ref.RawUserinfo
-		}
-		switch {
-		case url.OpaquePath:
-			url.Path = ref.Path
-			url.RawPath = ref.RawPath
-			url.RawQuery = ref.RawQuery
-		case strings.HasPrefix(ref.Path, "/"):
-			// The "abs_path" case.
-			url.Path = ref.Path
-			url.RawPath = ref.RawPath
-			url.RawQuery = ref.RawQuery
-		default:
-			// The "rel_path" case.
-			path := resolvePath(base.Path, ref.Path)
-			if !strings.HasPrefix(path, "/") {
-				path = "/" + path
-			}
-			url.Path = path
-			url.RawPath = url.Path
-			url.RawQuery = ref.RawQuery
-			if ref.RawQuery != "" {
-				url.RawPath += "?" + url.RawQuery
-			}
-		}
-
-		url.Fragment = ref.Fragment
-	}
-	url.Raw = url.String()
-	return url
-}
-
-// Query parses RawQuery and returns the corresponding values.
-func (u *URL) Query() Values {
-	v, _ := ParseQuery(u.RawQuery)
-	return v
-}
-
-// EncodedPath returns the URL's path in "URL path encoded" form.
-func (u *URL) EncodedPath() string {
-	return escape(u.Path, encodePath)
-}
diff --git a/src/pkg/url/url_test.go b/src/pkg/url/url_test.go
deleted file mode 100644
index 8c27e18..0000000
--- a/src/pkg/url/url_test.go
+++ /dev/null
@@ -1,750 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package url
-
-import (
-	"fmt"
-	"os"
-	"reflect"
-	"testing"
-)
-
-type URLTest struct {
-	in        string
-	out       *URL
-	roundtrip string // expected result of reserializing the URL; empty means same as "in".
-}
-
-var urltests = []URLTest{
-	// no path
-	{
-		"http://www.google.com",
-		&URL{
-			Raw:          "http://www.google.com",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-		},
-		"",
-	},
-	// path
-	{
-		"http://www.google.com/",
-		&URL{
-			Raw:          "http://www.google.com/",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-			RawPath:      "/",
-			Path:         "/",
-		},
-		"",
-	},
-	// path with hex escaping
-	{
-		"http://www.google.com/file%20one%26two",
-		&URL{
-			Raw:          "http://www.google.com/file%20one%26two",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-			RawPath:      "/file%20one%26two",
-			Path:         "/file one&two",
-		},
-		"http://www.google.com/file%20one&two",
-	},
-	// user
-	{
-		"ftp://webmaster@www.google.com/",
-		&URL{
-			Raw:          "ftp://webmaster@www.google.com/",
-			Scheme:       "ftp",
-			RawAuthority: "webmaster at www.google.com",
-			RawUserinfo:  "webmaster",
-			Host:         "www.google.com",
-			RawPath:      "/",
-			Path:         "/",
-		},
-		"",
-	},
-	// escape sequence in username
-	{
-		"ftp://john%20doe@www.google.com/",
-		&URL{
-			Raw:          "ftp://john%20doe@www.google.com/",
-			Scheme:       "ftp",
-			RawAuthority: "john%20doe at www.google.com",
-			RawUserinfo:  "john%20doe",
-			Host:         "www.google.com",
-			RawPath:      "/",
-			Path:         "/",
-		},
-		"ftp://john%20doe@www.google.com/",
-	},
-	// query
-	{
-		"http://www.google.com/?q=go+language",
-		&URL{
-			Raw:          "http://www.google.com/?q=go+language",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-			RawPath:      "/?q=go+language",
-			Path:         "/",
-			RawQuery:     "q=go+language",
-		},
-		"",
-	},
-	// query with hex escaping: NOT parsed
-	{
-		"http://www.google.com/?q=go%20language",
-		&URL{
-			Raw:          "http://www.google.com/?q=go%20language",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-			RawPath:      "/?q=go%20language",
-			Path:         "/",
-			RawQuery:     "q=go%20language",
-		},
-		"",
-	},
-	// %20 outside query
-	{
-		"http://www.google.com/a%20b?q=c+d",
-		&URL{
-			Raw:          "http://www.google.com/a%20b?q=c+d",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-			RawPath:      "/a%20b?q=c+d",
-			Path:         "/a b",
-			RawQuery:     "q=c+d",
-		},
-		"",
-	},
-	// path without leading /, so no query parsing
-	{
-		"http:www.google.com/?q=go+language",
-		&URL{
-			Raw:        "http:www.google.com/?q=go+language",
-			Scheme:     "http",
-			RawPath:    "www.google.com/?q=go+language",
-			Path:       "www.google.com/?q=go+language",
-			OpaquePath: true,
-		},
-		"http:www.google.com/?q=go+language",
-	},
-	// path without leading /, so no query parsing
-	{
-		"http:%2f%2fwww.google.com/?q=go+language",
-		&URL{
-			Raw:        "http:%2f%2fwww.google.com/?q=go+language",
-			Scheme:     "http",
-			RawPath:    "%2f%2fwww.google.com/?q=go+language",
-			Path:       "//www.google.com/?q=go+language",
-			OpaquePath: true,
-		},
-		"http:%2f/www.google.com/?q=go+language",
-	},
-	// non-authority
-	{
-		"mailto:/webmaster at golang.org",
-		&URL{
-			Raw:     "mailto:/webmaster at golang.org",
-			Scheme:  "mailto",
-			RawPath: "/webmaster at golang.org",
-			Path:    "/webmaster at golang.org",
-		},
-		"",
-	},
-	// non-authority
-	{
-		"mailto:webmaster at golang.org",
-		&URL{
-			Raw:        "mailto:webmaster at golang.org",
-			Scheme:     "mailto",
-			RawPath:    "webmaster at golang.org",
-			Path:       "webmaster at golang.org",
-			OpaquePath: true,
-		},
-		"",
-	},
-	// unescaped :// in query should not create a scheme
-	{
-		"/foo?query=http://bad",
-		&URL{
-			Raw:      "/foo?query=http://bad",
-			RawPath:  "/foo?query=http://bad",
-			Path:     "/foo",
-			RawQuery: "query=http://bad",
-		},
-		"",
-	},
-	// leading // without scheme should create an authority
-	{
-		"//foo",
-		&URL{
-			RawAuthority: "foo",
-			Raw:          "//foo",
-			Host:         "foo",
-			Scheme:       "",
-			RawPath:      "",
-			Path:         "",
-		},
-		"",
-	},
-	// leading // without scheme, with userinfo, path, and query
-	{
-		"//user at foo/path?a=b",
-		&URL{
-			Raw:          "//user at foo/path?a=b",
-			RawAuthority: "user at foo",
-			RawUserinfo:  "user",
-			Scheme:       "",
-			RawPath:      "/path?a=b",
-			Path:         "/path",
-			RawQuery:     "a=b",
-			Host:         "foo",
-		},
-		"",
-	},
-	// Three leading slashes isn't an authority, but doesn't return an error.
-	// (We can't return an error, as this code is also used via
-	// ServeHTTP -> ReadRequest -> Parse, which is arguably a
-	// different URL parsing context, but currently shares the
-	// same codepath)
-	{
-		"///threeslashes",
-		&URL{
-			RawAuthority: "",
-			Raw:          "///threeslashes",
-			Host:         "",
-			Scheme:       "",
-			RawPath:      "///threeslashes",
-			Path:         "///threeslashes",
-		},
-		"",
-	},
-	{
-		"http://user:password@google.com",
-		&URL{
-			Raw:          "http://user:password@google.com",
-			Scheme:       "http",
-			RawAuthority: "user:password at google.com",
-			RawUserinfo:  "user:password",
-			Host:         "google.com",
-		},
-		"http://user:******@google.com",
-	},
-	{
-		"http://user:longerpass@google.com",
-		&URL{
-			Raw:          "http://user:longerpass@google.com",
-			Scheme:       "http",
-			RawAuthority: "user:longerpass at google.com",
-			RawUserinfo:  "user:longerpass",
-			Host:         "google.com",
-		},
-		"http://user:******@google.com",
-	},
-}
-
-var urlnofragtests = []URLTest{
-	{
-		"http://www.google.com/?q=go+language#foo",
-		&URL{
-			Raw:          "http://www.google.com/?q=go+language#foo",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-			RawPath:      "/?q=go+language#foo",
-			Path:         "/",
-			RawQuery:     "q=go+language#foo",
-		},
-		"",
-	},
-}
-
-var urlfragtests = []URLTest{
-	{
-		"http://www.google.com/?q=go+language#foo",
-		&URL{
-			Raw:          "http://www.google.com/?q=go+language#foo",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-			RawPath:      "/?q=go+language#foo",
-			Path:         "/",
-			RawQuery:     "q=go+language",
-			Fragment:     "foo",
-		},
-		"",
-	},
-	{
-		"http://www.google.com/?q=go+language#foo%26bar",
-		&URL{
-			Raw:          "http://www.google.com/?q=go+language#foo%26bar",
-			Scheme:       "http",
-			RawAuthority: "www.google.com",
-			Host:         "www.google.com",
-			RawPath:      "/?q=go+language#foo%26bar",
-			Path:         "/",
-			RawQuery:     "q=go+language",
-			Fragment:     "foo&bar",
-		},
-		"http://www.google.com/?q=go+language#foo&bar",
-	},
-}
-
-// more useful string for debugging than fmt's struct printer
-func ufmt(u *URL) string {
-	return fmt.Sprintf("raw=%q, scheme=%q, rawpath=%q, auth=%q, userinfo=%q, host=%q, path=%q, rawq=%q, frag=%q",
-		u.Raw, u.Scheme, u.RawPath, u.RawAuthority, u.RawUserinfo,
-		u.Host, u.Path, u.RawQuery, u.Fragment)
-}
-
-func DoTest(t *testing.T, parse func(string) (*URL, os.Error), name string, tests []URLTest) {
-	for _, tt := range tests {
-		u, err := parse(tt.in)
-		if err != nil {
-			t.Errorf("%s(%q) returned error %s", name, tt.in, err)
-			continue
-		}
-		if !reflect.DeepEqual(u, tt.out) {
-			t.Errorf("%s(%q):\n\thave %v\n\twant %v\n",
-				name, tt.in, ufmt(u), ufmt(tt.out))
-		}
-	}
-}
-
-func TestParse(t *testing.T) {
-	DoTest(t, Parse, "Parse", urltests)
-	DoTest(t, Parse, "Parse", urlnofragtests)
-}
-
-func TestParseWithReference(t *testing.T) {
-	DoTest(t, ParseWithReference, "ParseWithReference", urltests)
-	DoTest(t, ParseWithReference, "ParseWithReference", urlfragtests)
-}
-
-const pathThatLooksSchemeRelative = "//not.a.user at not.a.host/just/a/path"
-
-var parseRequestUrlTests = []struct {
-	url           string
-	expectedValid bool
-}{
-	{"http://foo.com", true},
-	{"http://foo.com/", true},
-	{"http://foo.com/path", true},
-	{"/", true},
-	{pathThatLooksSchemeRelative, true},
-	{"//not.a.user@%66%6f%6f.com/just/a/path/also", true},
-	{"foo.html", false},
-	{"../dir/", false},
-}
-
-func TestParseRequest(t *testing.T) {
-	for _, test := range parseRequestUrlTests {
-		_, err := ParseRequest(test.url)
-		valid := err == nil
-		if valid != test.expectedValid {
-			t.Errorf("Expected valid=%v for %q; got %v", test.expectedValid, test.url, valid)
-		}
-	}
-
-	url, err := ParseRequest(pathThatLooksSchemeRelative)
-	if err != nil {
-		t.Fatalf("Unexpected error %v", err)
-	}
-	if url.Path != pathThatLooksSchemeRelative {
-		t.Errorf("Expected path %q; got %q", pathThatLooksSchemeRelative, url.Path)
-	}
-}
-
-func DoTestString(t *testing.T, parse func(string) (*URL, os.Error), name string, tests []URLTest) {
-	for _, tt := range tests {
-		u, err := parse(tt.in)
-		if err != nil {
-			t.Errorf("%s(%q) returned error %s", name, tt.in, err)
-			continue
-		}
-		s := u.String()
-		expected := tt.in
-		if len(tt.roundtrip) > 0 {
-			expected = tt.roundtrip
-		}
-		if s != expected {
-			t.Errorf("%s(%q).String() == %q (expected %q)", name, tt.in, s, expected)
-		}
-	}
-}
-
-func TestURLString(t *testing.T) {
-	DoTestString(t, Parse, "Parse", urltests)
-	DoTestString(t, Parse, "Parse", urlnofragtests)
-	DoTestString(t, ParseWithReference, "ParseWithReference", urltests)
-	DoTestString(t, ParseWithReference, "ParseWithReference", urlfragtests)
-}
-
-type EscapeTest struct {
-	in  string
-	out string
-	err os.Error
-}
-
-var unescapeTests = []EscapeTest{
-	{
-		"",
-		"",
-		nil,
-	},
-	{
-		"abc",
-		"abc",
-		nil,
-	},
-	{
-		"1%41",
-		"1A",
-		nil,
-	},
-	{
-		"1%41%42%43",
-		"1ABC",
-		nil,
-	},
-	{
-		"%4a",
-		"J",
-		nil,
-	},
-	{
-		"%6F",
-		"o",
-		nil,
-	},
-	{
-		"%", // not enough characters after %
-		"",
-		EscapeError("%"),
-	},
-	{
-		"%a", // not enough characters after %
-		"",
-		EscapeError("%a"),
-	},
-	{
-		"%1", // not enough characters after %
-		"",
-		EscapeError("%1"),
-	},
-	{
-		"123%45%6", // not enough characters after %
-		"",
-		EscapeError("%6"),
-	},
-	{
-		"%zzzzz", // invalid hex digits
-		"",
-		EscapeError("%zz"),
-	},
-}
-
-func TestUnescape(t *testing.T) {
-	for _, tt := range unescapeTests {
-		actual, err := QueryUnescape(tt.in)
-		if actual != tt.out || (err != nil) != (tt.err != nil) {
-			t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", tt.in, actual, err, tt.out, tt.err)
-		}
-	}
-}
-
-var escapeTests = []EscapeTest{
-	{
-		"",
-		"",
-		nil,
-	},
-	{
-		"abc",
-		"abc",
-		nil,
-	},
-	{
-		"one two",
-		"one+two",
-		nil,
-	},
-	{
-		"10%",
-		"10%25",
-		nil,
-	},
-	{
-		" ?&=#+%!<>#\"{}|\\^[]`☺\t",
-		"+%3F%26%3D%23%2B%25!%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09",
-		nil,
-	},
-}
-
-func TestEscape(t *testing.T) {
-	for _, tt := range escapeTests {
-		actual := QueryEscape(tt.in)
-		if tt.out != actual {
-			t.Errorf("QueryEscape(%q) = %q, want %q", tt.in, actual, tt.out)
-		}
-
-		// for bonus points, verify that escape:unescape is an identity.
-		roundtrip, err := QueryUnescape(actual)
-		if roundtrip != tt.in || err != nil {
-			t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", actual, roundtrip, err, tt.in, "[no error]")
-		}
-	}
-}
-
-type UserinfoTest struct {
-	User     string
-	Password string
-	Raw      string
-}
-
-var userinfoTests = []UserinfoTest{
-	{"user", "password", "user:password"},
-	{"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
-		"foo%3Abar:~!%40%23$%25%5E&*()_+%7B%7D%7C%5B%5D%5C-=%60%3A;'%22%3C%3E?,.%2F"},
-}
-
-func TestEscapeUserinfo(t *testing.T) {
-	for _, tt := range userinfoTests {
-		if raw := EscapeUserinfo(tt.User, tt.Password); raw != tt.Raw {
-			t.Errorf("EscapeUserinfo(%q, %q) = %q, want %q", tt.User, tt.Password, raw, tt.Raw)
-		}
-	}
-}
-
-func TestUnescapeUserinfo(t *testing.T) {
-	for _, tt := range userinfoTests {
-		if user, pass, err := UnescapeUserinfo(tt.Raw); user != tt.User || pass != tt.Password || err != nil {
-			t.Errorf("UnescapeUserinfo(%q) = %q, %q, %v, want %q, %q, nil", tt.Raw, user, pass, err, tt.User, tt.Password)
-		}
-	}
-}
-
-type EncodeQueryTest struct {
-	m         Values
-	expected  string
-	expected1 string
-}
-
-var encodeQueryTests = []EncodeQueryTest{
-	{nil, "", ""},
-	{Values{"q": {"puppies"}, "oe": {"utf8"}}, "q=puppies&oe=utf8", "oe=utf8&q=puppies"},
-	{Values{"q": {"dogs", "&", "7"}}, "q=dogs&q=%26&q=7", "q=dogs&q=%26&q=7"},
-}
-
-func TestEncodeQuery(t *testing.T) {
-	for _, tt := range encodeQueryTests {
-		if q := tt.m.Encode(); q != tt.expected && q != tt.expected1 {
-			t.Errorf(`EncodeQuery(%+v) = %q, want %q`, tt.m, q, tt.expected)
-		}
-	}
-}
-
-var resolvePathTests = []struct {
-	base, ref, expected string
-}{
-	{"a/b", ".", "a/"},
-	{"a/b", "c", "a/c"},
-	{"a/b", "..", ""},
-	{"a/", "..", ""},
-	{"a/", "../..", ""},
-	{"a/b/c", "..", "a/"},
-	{"a/b/c", "../d", "a/d"},
-	{"a/b/c", ".././d", "a/d"},
-	{"a/b", "./..", ""},
-	{"a/./b", ".", "a/./"},
-	{"a/../", ".", "a/../"},
-	{"a/.././b", "c", "a/.././c"},
-}
-
-func TestResolvePath(t *testing.T) {
-	for _, test := range resolvePathTests {
-		got := resolvePath(test.base, test.ref)
-		if got != test.expected {
-			t.Errorf("For %q + %q got %q; expected %q", test.base, test.ref, got, test.expected)
-		}
-	}
-}
-
-var resolveReferenceTests = []struct {
-	base, rel, expected string
-}{
-	// Absolute URL references
-	{"http://foo.com?a=b", "https://bar.com/", "https://bar.com/"},
-	{"http://foo.com/", "https://bar.com/?a=b", "https://bar.com/?a=b"},
-	{"http://foo.com/bar", "mailto:foo at example.com", "mailto:foo at example.com"},
-
-	// Path-absolute references
-	{"http://foo.com/bar", "/baz", "http://foo.com/baz"},
-	{"http://foo.com/bar?a=b#f", "/baz", "http://foo.com/baz"},
-	{"http://foo.com/bar?a=b", "/baz?c=d", "http://foo.com/baz?c=d"},
-
-	// Scheme-relative
-	{"https://foo.com/bar?a=b", "//bar.com/quux", "https://bar.com/quux"},
-
-	// Path-relative references:
-
-	// ... current directory
-	{"http://foo.com", ".", "http://foo.com/"},
-	{"http://foo.com/bar", ".", "http://foo.com/"},
-	{"http://foo.com/bar/", ".", "http://foo.com/bar/"},
-
-	// ... going down
-	{"http://foo.com", "bar", "http://foo.com/bar"},
-	{"http://foo.com/", "bar", "http://foo.com/bar"},
-	{"http://foo.com/bar/baz", "quux", "http://foo.com/bar/quux"},
-
-	// ... going up
-	{"http://foo.com/bar/baz", "../quux", "http://foo.com/quux"},
-	{"http://foo.com/bar/baz", "../../../../../quux", "http://foo.com/quux"},
-	{"http://foo.com/bar", "..", "http://foo.com/"},
-	{"http://foo.com/bar/baz", "./..", "http://foo.com/"},
-
-	// "." and ".." in the base aren't special
-	{"http://foo.com/dot/./dotdot/../foo/bar", "../baz", "http://foo.com/dot/./dotdot/../baz"},
-
-	// Triple dot isn't special
-	{"http://foo.com/bar", "...", "http://foo.com/..."},
-
-	// Fragment
-	{"http://foo.com/bar", ".#frag", "http://foo.com/#frag"},
-}
-
-func TestResolveReference(t *testing.T) {
-	mustParse := func(url string) *URL {
-		u, err := ParseWithReference(url)
-		if err != nil {
-			t.Fatalf("Expected URL to parse: %q, got error: %v", url, err)
-		}
-		return u
-	}
-	for _, test := range resolveReferenceTests {
-		base := mustParse(test.base)
-		rel := mustParse(test.rel)
-		url := base.ResolveReference(rel)
-		urlStr := url.String()
-		if urlStr != test.expected {
-			t.Errorf("Resolving %q + %q != %q; got %q", test.base, test.rel, test.expected, urlStr)
-		}
-	}
-
-	// Test that new instances are returned.
-	base := mustParse("http://foo.com/")
-	abs := base.ResolveReference(mustParse("."))
-	if base == abs {
-		t.Errorf("Expected no-op reference to return new URL instance.")
-	}
-	barRef := mustParse("http://bar.com/")
-	abs = base.ResolveReference(barRef)
-	if abs == barRef {
-		t.Errorf("Expected resolution of absolute reference to return new URL instance.")
-	}
-
-	// Test the convenience wrapper too
-	base = mustParse("http://foo.com/path/one/")
-	abs, _ = base.Parse("../two")
-	expected := "http://foo.com/path/two"
-	if abs.String() != expected {
-		t.Errorf("Parse wrapper got %q; expected %q", abs.String(), expected)
-	}
-	_, err := base.Parse("")
-	if err == nil {
-		t.Errorf("Expected an error from Parse wrapper parsing an empty string.")
-	}
-
-}
-
-func TestQueryValues(t *testing.T) {
-	u, _ := Parse("http://x.com?foo=bar&bar=1&bar=2")
-	v := u.Query()
-	if len(v) != 2 {
-		t.Errorf("got %d keys in Query values, want 2", len(v))
-	}
-	if g, e := v.Get("foo"), "bar"; g != e {
-		t.Errorf("Get(foo) = %q, want %q", g, e)
-	}
-	// Case sensitive:
-	if g, e := v.Get("Foo"), ""; g != e {
-		t.Errorf("Get(Foo) = %q, want %q", g, e)
-	}
-	if g, e := v.Get("bar"), "1"; g != e {
-		t.Errorf("Get(bar) = %q, want %q", g, e)
-	}
-	if g, e := v.Get("baz"), ""; g != e {
-		t.Errorf("Get(baz) = %q, want %q", g, e)
-	}
-	v.Del("bar")
-	if g, e := v.Get("bar"), ""; g != e {
-		t.Errorf("second Get(bar) = %q, want %q", g, e)
-	}
-}
-
-type parseTest struct {
-	query string
-	out   Values
-}
-
-var parseTests = []parseTest{
-	{
-		query: "a=1&b=2",
-		out:   Values{"a": []string{"1"}, "b": []string{"2"}},
-	},
-	{
-		query: "a=1&a=2&a=banana",
-		out:   Values{"a": []string{"1", "2", "banana"}},
-	},
-	{
-		query: "ascii=%3Ckey%3A+0x90%3E",
-		out:   Values{"ascii": []string{"<key: 0x90>"}},
-	},
-	{
-		query: "a=1;b=2",
-		out:   Values{"a": []string{"1"}, "b": []string{"2"}},
-	},
-	{
-		query: "a=1&a=2;a=banana",
-		out:   Values{"a": []string{"1", "2", "banana"}},
-	},
-}
-
-func TestParseQuery(t *testing.T) {
-	for i, test := range parseTests {
-		form, err := ParseQuery(test.query)
-		if err != nil {
-			t.Errorf("test %d: Unexpected error: %v", i, err)
-			continue
-		}
-		if len(form) != len(test.out) {
-			t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out))
-		}
-		for k, evs := range test.out {
-			vs, ok := form[k]
-			if !ok {
-				t.Errorf("test %d: Missing key %q", i, k)
-				continue
-			}
-			if len(vs) != len(evs) {
-				t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs))
-				continue
-			}
-			for j, ev := range evs {
-				if v := vs[j]; v != ev {
-					t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev)
-				}
-			}
-		}
-	}
-}
diff --git a/src/pkg/utf16/Makefile b/src/pkg/utf16/Makefile
deleted file mode 100644
index 8a564fb..0000000
--- a/src/pkg/utf16/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=utf16
-GOFILES=\
-	utf16.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/utf16/utf16.go b/src/pkg/utf16/utf16.go
deleted file mode 100644
index 372e38a..0000000
--- a/src/pkg/utf16/utf16.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2010 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 utf16 implements encoding and decoding of UTF-16 sequences.
-package utf16
-
-import "unicode"
-
-const (
-	// 0xd800-0xdc00 encodes the high 10 bits of a pair.
-	// 0xdc00-0xe000 encodes the low 10 bits of a pair.
-	// the value is those 20 bits plus 0x10000.
-	surr1 = 0xd800
-	surr2 = 0xdc00
-	surr3 = 0xe000
-
-	surrSelf = 0x10000
-)
-
-// IsSurrogate returns true if the specified Unicode code point
-// can appear in a surrogate pair.
-func IsSurrogate(rune int) bool {
-	return surr1 <= rune && rune < surr3
-}
-
-// DecodeRune returns the UTF-16 decoding of a surrogate pair.
-// If the pair is not a valid UTF-16 surrogate pair, DecodeRune returns
-// the Unicode replacement code point U+FFFD.
-func DecodeRune(r1, r2 int) int {
-	if surr1 <= r1 && r1 < surr2 && surr2 <= r2 && r2 < surr3 {
-		return (int(r1)-surr1)<<10 | (int(r2) - surr2) + 0x10000
-	}
-	return unicode.ReplacementChar
-}
-
-// EncodeRune returns the UTF-16 surrogate pair r1, r2 for the given rune.
-// If the rune is not a valid Unicode code point or does not need encoding,
-// EncodeRune returns U+FFFD, U+FFFD.
-func EncodeRune(rune int) (r1, r2 int) {
-	if rune < surrSelf || rune > unicode.MaxRune || IsSurrogate(rune) {
-		return unicode.ReplacementChar, unicode.ReplacementChar
-	}
-	rune -= surrSelf
-	return surr1 + (rune>>10)&0x3ff, surr2 + rune&0x3ff
-}
-
-// Encode returns the UTF-16 encoding of the Unicode code point sequence s.
-func Encode(s []int) []uint16 {
-	n := len(s)
-	for _, v := range s {
-		if v >= surrSelf {
-			n++
-		}
-	}
-
-	a := make([]uint16, n)
-	n = 0
-	for _, v := range s {
-		switch {
-		case v < 0, surr1 <= v && v < surr3, v > unicode.MaxRune:
-			v = unicode.ReplacementChar
-			fallthrough
-		case v < surrSelf:
-			a[n] = uint16(v)
-			n++
-		default:
-			r1, r2 := EncodeRune(v)
-			a[n] = uint16(r1)
-			a[n+1] = uint16(r2)
-			n += 2
-		}
-	}
-	return a[0:n]
-}
-
-// Decode returns the Unicode code point sequence represented
-// by the UTF-16 encoding s.
-func Decode(s []uint16) []int {
-	a := make([]int, len(s))
-	n := 0
-	for i := 0; i < len(s); i++ {
-		switch r := s[i]; {
-		case surr1 <= r && r < surr2 && i+1 < len(s) &&
-			surr2 <= s[i+1] && s[i+1] < surr3:
-			// valid surrogate sequence
-			a[n] = DecodeRune(int(r), int(s[i+1]))
-			i++
-			n++
-		case surr1 <= r && r < surr3:
-			// invalid surrogate sequence
-			a[n] = unicode.ReplacementChar
-			n++
-		default:
-			// normal rune
-			a[n] = int(r)
-			n++
-		}
-	}
-	return a[0:n]
-}
diff --git a/src/pkg/utf16/utf16_test.go b/src/pkg/utf16/utf16_test.go
deleted file mode 100644
index 2b9fb3d..0000000
--- a/src/pkg/utf16/utf16_test.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2010 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 utf16_test
-
-import (
-	"fmt"
-	"reflect"
-	"testing"
-	"unicode"
-	. "utf16"
-)
-
-type encodeTest struct {
-	in  []int
-	out []uint16
-}
-
-var encodeTests = []encodeTest{
-	{[]int{1, 2, 3, 4}, []uint16{1, 2, 3, 4}},
-	{[]int{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff},
-		[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff}},
-	{[]int{'a', 'b', 0xd7ff, 0xd800, 0xdfff, 0xe000, 0x110000, -1},
-		[]uint16{'a', 'b', 0xd7ff, 0xfffd, 0xfffd, 0xe000, 0xfffd, 0xfffd}},
-}
-
-func TestEncode(t *testing.T) {
-	for _, tt := range encodeTests {
-		out := Encode(tt.in)
-		if !reflect.DeepEqual(out, tt.out) {
-			t.Errorf("Encode(%v) = %v; want %v", hex(tt.in), hex16(out), hex16(tt.out))
-		}
-	}
-}
-
-func TestEncodeRune(t *testing.T) {
-	for i, tt := range encodeTests {
-		j := 0
-		for _, r := range tt.in {
-			r1, r2 := EncodeRune(r)
-			if r < 0x10000 || r > unicode.MaxRune {
-				if j >= len(tt.out) {
-					t.Errorf("#%d: ran out of tt.out", i)
-					break
-				}
-				if r1 != unicode.ReplacementChar || r2 != unicode.ReplacementChar {
-					t.Errorf("EncodeRune(%#x) = %#x, %#x; want 0xfffd, 0xfffd", r, r1, r2)
-				}
-				j++
-			} else {
-				if j+1 >= len(tt.out) {
-					t.Errorf("#%d: ran out of tt.out", i)
-					break
-				}
-				if r1 != int(tt.out[j]) || r2 != int(tt.out[j+1]) {
-					t.Errorf("EncodeRune(%#x) = %#x, %#x; want %#x, %#x", r, r1, r2, tt.out[j], tt.out[j+1])
-				}
-				j += 2
-				dec := DecodeRune(r1, r2)
-				if dec != r {
-					t.Errorf("DecodeRune(%#x, %#x) = %#x; want %#x", r1, r2, dec, r)
-				}
-			}
-		}
-		if j != len(tt.out) {
-			t.Errorf("#%d: EncodeRune didn't generate enough output", i)
-		}
-	}
-}
-
-type decodeTest struct {
-	in  []uint16
-	out []int
-}
-
-var decodeTests = []decodeTest{
-	{[]uint16{1, 2, 3, 4}, []int{1, 2, 3, 4}},
-	{[]uint16{0xffff, 0xd800, 0xdc00, 0xd800, 0xdc01, 0xd808, 0xdf45, 0xdbff, 0xdfff},
-		[]int{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff}},
-	{[]uint16{0xd800, 'a'}, []int{0xfffd, 'a'}},
-	{[]uint16{0xdfff}, []int{0xfffd}},
-}
-
-func TestDecode(t *testing.T) {
-	for _, tt := range decodeTests {
-		out := Decode(tt.in)
-		if !reflect.DeepEqual(out, tt.out) {
-			t.Errorf("Decode(%v) = %v; want %v", hex16(tt.in), hex(out), hex(tt.out))
-		}
-	}
-}
-
-type hex []int
-
-func (h hex) Format(f fmt.State, c int) {
-	fmt.Fprint(f, "[")
-	for i, v := range h {
-		if i > 0 {
-			fmt.Fprint(f, " ")
-		}
-		fmt.Fprintf(f, "%x", v)
-	}
-	fmt.Fprint(f, "]")
-}
-
-type hex16 []uint16
-
-func (h hex16) Format(f fmt.State, c int) {
-	fmt.Fprint(f, "[")
-	for i, v := range h {
-		if i > 0 {
-			fmt.Fprint(f, " ")
-		}
-		fmt.Fprintf(f, "%x", v)
-	}
-	fmt.Fprint(f, "]")
-}
diff --git a/src/pkg/utf8/Makefile b/src/pkg/utf8/Makefile
deleted file mode 100644
index b3574ba..0000000
--- a/src/pkg/utf8/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=utf8
-GOFILES=\
-	string.go\
-	utf8.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/utf8/string.go b/src/pkg/utf8/string.go
deleted file mode 100644
index 83b56b9..0000000
--- a/src/pkg/utf8/string.go
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package utf8
-
-// String wraps a regular string with a small structure that provides more
-// efficient indexing by code point index, as opposed to byte index.
-// Scanning incrementally forwards or backwards is O(1) per index operation
-// (although not as fast a range clause going forwards).  Random access is
-// O(N) in the length of the string, but the overhead is less than always
-// scanning from the beginning.
-// If the string is ASCII, random access is O(1).
-// Unlike the built-in string type, String has internal mutable state and
-// is not thread-safe.
-type String struct {
-	str      string
-	numRunes int
-	// If width > 0, the rune at runePos starts at bytePos and has the specified width.
-	width    int
-	bytePos  int
-	runePos  int
-	nonASCII int // byte index of the first non-ASCII rune.
-}
-
-// NewString returns a new UTF-8 string with the provided contents.
-func NewString(contents string) *String {
-	return new(String).Init(contents)
-}
-
-// Init initializes an existing String to hold the provided contents.
-// It returns a pointer to the initialized String.
-func (s *String) Init(contents string) *String {
-	s.str = contents
-	s.bytePos = 0
-	s.runePos = 0
-	for i := 0; i < len(contents); i++ {
-		if contents[i] >= RuneSelf {
-			// Not ASCII.
-			s.numRunes = RuneCountInString(contents)
-			_, s.width = DecodeRuneInString(contents)
-			s.nonASCII = i
-			return s
-		}
-	}
-	// ASCII is simple.  Also, the empty string is ASCII.
-	s.numRunes = len(contents)
-	s.width = 0
-	s.nonASCII = len(contents)
-	return s
-}
-
-// String returns the contents of the String.  This method also means the
-// String is directly printable by fmt.Print.
-func (s *String) String() string {
-	return s.str
-}
-
-// RuneCount returns the number of runes (Unicode code points) in the String.
-func (s *String) RuneCount() int {
-	return s.numRunes
-}
-
-// IsASCII returns a boolean indicating whether the String contains only ASCII bytes.
-func (s *String) IsASCII() bool {
-	return s.width == 0
-}
-
-// Slice returns the string sliced at rune positions [i:j].
-func (s *String) Slice(i, j int) string {
-	// ASCII is easy.  Let the compiler catch the indexing error if there is one.
-	if j < s.nonASCII {
-		return s.str[i:j]
-	}
-	if i < 0 || j > s.numRunes || i > j {
-		panic(sliceOutOfRange)
-	}
-	if i == j {
-		return ""
-	}
-	// For non-ASCII, after At(i), bytePos is always the position of the indexed character.
-	var low, high int
-	switch {
-	case i < s.nonASCII:
-		low = i
-	case i == s.numRunes:
-		low = len(s.str)
-	default:
-		s.At(i)
-		low = s.bytePos
-	}
-	switch {
-	case j == s.numRunes:
-		high = len(s.str)
-	default:
-		s.At(j)
-		high = s.bytePos
-	}
-	return s.str[low:high]
-}
-
-// At returns the rune with index i in the String.  The sequence of runes is the same
-// as iterating over the contents with a "for range" clause.
-func (s *String) At(i int) int {
-	// ASCII is easy.  Let the compiler catch the indexing error if there is one.
-	if i < s.nonASCII {
-		return int(s.str[i])
-	}
-
-	// Now we do need to know the index is valid.
-	if i < 0 || i >= s.numRunes {
-		panic(outOfRange)
-	}
-
-	var rune int
-
-	// Five easy common cases: within 1 spot of bytePos/runePos, or the beginning, or the end.
-	// With these cases, all scans from beginning or end work in O(1) time per rune.
-	switch {
-
-	case i == s.runePos-1: // backing up one rune
-		rune, s.width = DecodeLastRuneInString(s.str[0:s.bytePos])
-		s.runePos = i
-		s.bytePos -= s.width
-		return rune
-	case i == s.runePos+1: // moving ahead one rune
-		s.runePos = i
-		s.bytePos += s.width
-		fallthrough
-	case i == s.runePos:
-		rune, s.width = DecodeRuneInString(s.str[s.bytePos:])
-		return rune
-	case i == 0: // start of string
-		rune, s.width = DecodeRuneInString(s.str)
-		s.runePos = 0
-		s.bytePos = 0
-		return rune
-
-	case i == s.numRunes-1: // last rune in string
-		rune, s.width = DecodeLastRuneInString(s.str)
-		s.runePos = i
-		s.bytePos = len(s.str) - s.width
-		return rune
-	}
-
-	// We need to do a linear scan.  There are three places to start from:
-	// 1) The beginning
-	// 2) bytePos/runePos.
-	// 3) The end
-	// Choose the closest in rune count, scanning backwards if necessary.
-	forward := true
-	if i < s.runePos {
-		// Between beginning and pos.  Which is closer?
-		// Since both i and runePos are guaranteed >= nonASCII, that's the
-		// lowest location we need to start from.
-		if i < (s.runePos-s.nonASCII)/2 {
-			// Scan forward from beginning
-			s.bytePos, s.runePos = s.nonASCII, s.nonASCII
-		} else {
-			// Scan backwards from where we are
-			forward = false
-		}
-	} else {
-		// Between pos and end.  Which is closer?
-		if i-s.runePos < (s.numRunes-s.runePos)/2 {
-			// Scan forward from pos
-		} else {
-			// Scan backwards from end
-			s.bytePos, s.runePos = len(s.str), s.numRunes
-			forward = false
-		}
-	}
-	if forward {
-		// TODO: Is it much faster to use a range loop for this scan?
-		for {
-			rune, s.width = DecodeRuneInString(s.str[s.bytePos:])
-			if s.runePos == i {
-				break
-			}
-			s.runePos++
-			s.bytePos += s.width
-		}
-	} else {
-		for {
-			rune, s.width = DecodeLastRuneInString(s.str[0:s.bytePos])
-			s.runePos--
-			s.bytePos -= s.width
-			if s.runePos == i {
-				break
-			}
-		}
-	}
-	return rune
-}
-
-// We want the panic in At(i) to satisfy os.Error, because that's what
-// runtime panics satisfy, but we can't import os.  This is our solution.
-
-// error is the type of the error returned if a user calls String.At(i) with i out of range.
-// It satisfies os.Error and runtime.Error.
-type error string
-
-func (err error) String() string {
-	return string(err)
-}
-
-func (err error) RunTimeError() {
-}
-
-var outOfRange = error("utf8.String: index out of range")
-var sliceOutOfRange = error("utf8.String: slice index out of range")
diff --git a/src/pkg/utf8/string_test.go b/src/pkg/utf8/string_test.go
deleted file mode 100644
index f376b62..0000000
--- a/src/pkg/utf8/string_test.go
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package utf8_test
-
-import (
-	"rand"
-	"testing"
-	. "utf8"
-)
-
-func TestScanForwards(t *testing.T) {
-	for _, s := range testStrings {
-		runes := []int(s)
-		str := NewString(s)
-		if str.RuneCount() != len(runes) {
-			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
-			break
-		}
-		for i, expect := range runes {
-			got := str.At(i)
-			if got != expect {
-				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
-			}
-		}
-	}
-}
-
-func TestScanBackwards(t *testing.T) {
-	for _, s := range testStrings {
-		runes := []int(s)
-		str := NewString(s)
-		if str.RuneCount() != len(runes) {
-			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
-			break
-		}
-		for i := len(runes) - 1; i >= 0; i-- {
-			expect := runes[i]
-			got := str.At(i)
-			if got != expect {
-				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
-			}
-		}
-	}
-}
-
-func randCount() int {
-	if testing.Short() {
-		return 100
-	}
-	return 100000
-}
-
-func TestRandomAccess(t *testing.T) {
-	for _, s := range testStrings {
-		if len(s) == 0 {
-			continue
-		}
-		runes := []int(s)
-		str := NewString(s)
-		if str.RuneCount() != len(runes) {
-			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
-			break
-		}
-		for j := 0; j < randCount(); j++ {
-			i := rand.Intn(len(runes))
-			expect := runes[i]
-			got := str.At(i)
-			if got != expect {
-				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
-			}
-		}
-	}
-}
-
-func TestRandomSliceAccess(t *testing.T) {
-	for _, s := range testStrings {
-		if len(s) == 0 || s[0] == '\x80' { // the bad-UTF-8 string fools this simple test
-			continue
-		}
-		runes := []int(s)
-		str := NewString(s)
-		if str.RuneCount() != len(runes) {
-			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
-			break
-		}
-		for k := 0; k < randCount(); k++ {
-			i := rand.Intn(len(runes))
-			j := rand.Intn(len(runes) + 1)
-			if i > j { // include empty strings
-				continue
-			}
-			expect := string(runes[i:j])
-			got := str.Slice(i, j)
-			if got != expect {
-				t.Errorf("%s[%d:%d]: expected %q got %q", s, i, j, expect, got)
-			}
-		}
-	}
-}
-
-func TestLimitSliceAccess(t *testing.T) {
-	for _, s := range testStrings {
-		str := NewString(s)
-		if str.Slice(0, 0) != "" {
-			t.Error("failure with empty slice at beginning")
-		}
-		nr := RuneCountInString(s)
-		if str.Slice(nr, nr) != "" {
-			t.Error("failure with empty slice at end")
-		}
-	}
-}
diff --git a/src/pkg/utf8/utf8.go b/src/pkg/utf8/utf8.go
deleted file mode 100644
index 8910e17..0000000
--- a/src/pkg/utf8/utf8.go
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package utf8 implements functions and constants to support text encoded in
-// UTF-8. This package calls a Unicode character a rune for brevity.
-package utf8
-
-import "unicode" // only needed for a couple of constants
-
-// Numbers fundamental to the encoding.
-const (
-	RuneError = unicode.ReplacementChar // the "error" Rune or "replacement character".
-	RuneSelf  = 0x80                    // characters below Runeself are represented as themselves in a single byte.
-	UTFMax    = 4                       // maximum number of bytes of a UTF-8 encoded Unicode character.
-)
-
-const (
-	t1 = 0x00 // 0000 0000
-	tx = 0x80 // 1000 0000
-	t2 = 0xC0 // 1100 0000
-	t3 = 0xE0 // 1110 0000
-	t4 = 0xF0 // 1111 0000
-	t5 = 0xF8 // 1111 1000
-
-	maskx = 0x3F // 0011 1111
-	mask2 = 0x1F // 0001 1111
-	mask3 = 0x0F // 0000 1111
-	mask4 = 0x07 // 0000 0111
-
-	rune1Max = 1<<7 - 1
-	rune2Max = 1<<11 - 1
-	rune3Max = 1<<16 - 1
-	rune4Max = 1<<21 - 1
-)
-
-func decodeRuneInternal(p []byte) (rune, size int, short bool) {
-	n := len(p)
-	if n < 1 {
-		return RuneError, 0, true
-	}
-	c0 := p[0]
-
-	// 1-byte, 7-bit sequence?
-	if c0 < tx {
-		return int(c0), 1, false
-	}
-
-	// unexpected continuation byte?
-	if c0 < t2 {
-		return RuneError, 1, false
-	}
-
-	// need first continuation byte
-	if n < 2 {
-		return RuneError, 1, true
-	}
-	c1 := p[1]
-	if c1 < tx || t2 <= c1 {
-		return RuneError, 1, false
-	}
-
-	// 2-byte, 11-bit sequence?
-	if c0 < t3 {
-		rune = int(c0&mask2)<<6 | int(c1&maskx)
-		if rune <= rune1Max {
-			return RuneError, 1, false
-		}
-		return rune, 2, false
-	}
-
-	// need second continuation byte
-	if n < 3 {
-		return RuneError, 1, true
-	}
-	c2 := p[2]
-	if c2 < tx || t2 <= c2 {
-		return RuneError, 1, false
-	}
-
-	// 3-byte, 16-bit sequence?
-	if c0 < t4 {
-		rune = int(c0&mask3)<<12 | int(c1&maskx)<<6 | int(c2&maskx)
-		if rune <= rune2Max {
-			return RuneError, 1, false
-		}
-		return rune, 3, false
-	}
-
-	// need third continuation byte
-	if n < 4 {
-		return RuneError, 1, true
-	}
-	c3 := p[3]
-	if c3 < tx || t2 <= c3 {
-		return RuneError, 1, false
-	}
-
-	// 4-byte, 21-bit sequence?
-	if c0 < t5 {
-		rune = int(c0&mask4)<<18 | int(c1&maskx)<<12 | int(c2&maskx)<<6 | int(c3&maskx)
-		if rune <= rune3Max {
-			return RuneError, 1, false
-		}
-		return rune, 4, false
-	}
-
-	// error
-	return RuneError, 1, false
-}
-
-func decodeRuneInStringInternal(s string) (rune, size int, short bool) {
-	n := len(s)
-	if n < 1 {
-		return RuneError, 0, true
-	}
-	c0 := s[0]
-
-	// 1-byte, 7-bit sequence?
-	if c0 < tx {
-		return int(c0), 1, false
-	}
-
-	// unexpected continuation byte?
-	if c0 < t2 {
-		return RuneError, 1, false
-	}
-
-	// need first continuation byte
-	if n < 2 {
-		return RuneError, 1, true
-	}
-	c1 := s[1]
-	if c1 < tx || t2 <= c1 {
-		return RuneError, 1, false
-	}
-
-	// 2-byte, 11-bit sequence?
-	if c0 < t3 {
-		rune = int(c0&mask2)<<6 | int(c1&maskx)
-		if rune <= rune1Max {
-			return RuneError, 1, false
-		}
-		return rune, 2, false
-	}
-
-	// need second continuation byte
-	if n < 3 {
-		return RuneError, 1, true
-	}
-	c2 := s[2]
-	if c2 < tx || t2 <= c2 {
-		return RuneError, 1, false
-	}
-
-	// 3-byte, 16-bit sequence?
-	if c0 < t4 {
-		rune = int(c0&mask3)<<12 | int(c1&maskx)<<6 | int(c2&maskx)
-		if rune <= rune2Max {
-			return RuneError, 1, false
-		}
-		return rune, 3, false
-	}
-
-	// need third continuation byte
-	if n < 4 {
-		return RuneError, 1, true
-	}
-	c3 := s[3]
-	if c3 < tx || t2 <= c3 {
-		return RuneError, 1, false
-	}
-
-	// 4-byte, 21-bit sequence?
-	if c0 < t5 {
-		rune = int(c0&mask4)<<18 | int(c1&maskx)<<12 | int(c2&maskx)<<6 | int(c3&maskx)
-		if rune <= rune3Max {
-			return RuneError, 1, false
-		}
-		return rune, 4, false
-	}
-
-	// error
-	return RuneError, 1, false
-}
-
-// FullRune reports whether the bytes in p begin with a full UTF-8 encoding of a rune.
-// An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
-func FullRune(p []byte) bool {
-	_, _, short := decodeRuneInternal(p)
-	return !short
-}
-
-// FullRuneInString is like FullRune but its input is a string.
-func FullRuneInString(s string) bool {
-	_, _, short := decodeRuneInStringInternal(s)
-	return !short
-}
-
-// DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and its width in bytes.
-func DecodeRune(p []byte) (rune, size int) {
-	rune, size, _ = decodeRuneInternal(p)
-	return
-}
-
-// DecodeRuneInString is like DecodeRune but its input is a string.
-func DecodeRuneInString(s string) (rune, size int) {
-	rune, size, _ = decodeRuneInStringInternal(s)
-	return
-}
-
-// DecodeLastRune unpacks the last UTF-8 encoding in p
-// and returns the rune and its width in bytes.
-func DecodeLastRune(p []byte) (rune, size int) {
-	end := len(p)
-	if end == 0 {
-		return RuneError, 0
-	}
-	start := end - 1
-	rune = int(p[start])
-	if rune < RuneSelf {
-		return rune, 1
-	}
-	// guard against O(n^2) behavior when traversing
-	// backwards through strings with long sequences of
-	// invalid UTF-8.
-	lim := end - UTFMax
-	if lim < 0 {
-		lim = 0
-	}
-	for start--; start >= lim; start-- {
-		if RuneStart(p[start]) {
-			break
-		}
-	}
-	if start < 0 {
-		start = 0
-	}
-	rune, size = DecodeRune(p[start:end])
-	if start+size != end {
-		return RuneError, 1
-	}
-	return rune, size
-}
-
-// DecodeLastRuneInString is like DecodeLastRune but its input is a string.
-func DecodeLastRuneInString(s string) (rune, size int) {
-	end := len(s)
-	if end == 0 {
-		return RuneError, 0
-	}
-	start := end - 1
-	rune = int(s[start])
-	if rune < RuneSelf {
-		return rune, 1
-	}
-	// guard against O(n^2) behavior when traversing
-	// backwards through strings with long sequences of
-	// invalid UTF-8.
-	lim := end - UTFMax
-	if lim < 0 {
-		lim = 0
-	}
-	for start--; start >= lim; start-- {
-		if RuneStart(s[start]) {
-			break
-		}
-	}
-	if start < 0 {
-		start = 0
-	}
-	rune, size = DecodeRuneInString(s[start:end])
-	if start+size != end {
-		return RuneError, 1
-	}
-	return rune, size
-}
-
-// RuneLen returns the number of bytes required to encode the rune.
-func RuneLen(rune int) int {
-	switch {
-	case rune <= rune1Max:
-		return 1
-	case rune <= rune2Max:
-		return 2
-	case rune <= rune3Max:
-		return 3
-	case rune <= rune4Max:
-		return 4
-	}
-	return -1
-}
-
-// EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune.
-// It returns the number of bytes written.
-func EncodeRune(p []byte, rune int) int {
-	// Negative values are erroneous.  Making it unsigned addresses the problem.
-	r := uint(rune)
-
-	if r <= rune1Max {
-		p[0] = byte(r)
-		return 1
-	}
-
-	if r <= rune2Max {
-		p[0] = t2 | byte(r>>6)
-		p[1] = tx | byte(r)&maskx
-		return 2
-	}
-
-	if r > unicode.MaxRune {
-		r = RuneError
-	}
-
-	if r <= rune3Max {
-		p[0] = t3 | byte(r>>12)
-		p[1] = tx | byte(r>>6)&maskx
-		p[2] = tx | byte(r)&maskx
-		return 3
-	}
-
-	p[0] = t4 | byte(r>>18)
-	p[1] = tx | byte(r>>12)&maskx
-	p[2] = tx | byte(r>>6)&maskx
-	p[3] = tx | byte(r)&maskx
-	return 4
-}
-
-// RuneCount returns the number of runes in p.  Erroneous and short
-// encodings are treated as single runes of width 1 byte.
-func RuneCount(p []byte) int {
-	i := 0
-	var n int
-	for n = 0; i < len(p); n++ {
-		if p[i] < RuneSelf {
-			i++
-		} else {
-			_, size := DecodeRune(p[i:])
-			i += size
-		}
-	}
-	return n
-}
-
-// RuneCountInString is like RuneCount but its input is a string.
-func RuneCountInString(s string) (n int) {
-	for _ = range s {
-		n++
-	}
-	return
-}
-
-// RuneStart reports whether the byte could be the first byte of
-// an encoded rune.  Second and subsequent bytes always have the top
-// two bits set to 10.
-func RuneStart(b byte) bool { return b&0xC0 != 0x80 }
diff --git a/src/pkg/utf8/utf8_test.go b/src/pkg/utf8/utf8_test.go
deleted file mode 100644
index 7a1db93..0000000
--- a/src/pkg/utf8/utf8_test.go
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package utf8_test
-
-import (
-	"bytes"
-	"testing"
-	. "utf8"
-)
-
-type Utf8Map struct {
-	rune int
-	str  string
-}
-
-var utf8map = []Utf8Map{
-	{0x0000, "\x00"},
-	{0x0001, "\x01"},
-	{0x007e, "\x7e"},
-	{0x007f, "\x7f"},
-	{0x0080, "\xc2\x80"},
-	{0x0081, "\xc2\x81"},
-	{0x00bf, "\xc2\xbf"},
-	{0x00c0, "\xc3\x80"},
-	{0x00c1, "\xc3\x81"},
-	{0x00c8, "\xc3\x88"},
-	{0x00d0, "\xc3\x90"},
-	{0x00e0, "\xc3\xa0"},
-	{0x00f0, "\xc3\xb0"},
-	{0x00f8, "\xc3\xb8"},
-	{0x00ff, "\xc3\xbf"},
-	{0x0100, "\xc4\x80"},
-	{0x07ff, "\xdf\xbf"},
-	{0x0800, "\xe0\xa0\x80"},
-	{0x0801, "\xe0\xa0\x81"},
-	{0xfffe, "\xef\xbf\xbe"},
-	{0xffff, "\xef\xbf\xbf"},
-	{0x10000, "\xf0\x90\x80\x80"},
-	{0x10001, "\xf0\x90\x80\x81"},
-	{0x10fffe, "\xf4\x8f\xbf\xbe"},
-	{0x10ffff, "\xf4\x8f\xbf\xbf"},
-	{0xFFFD, "\xef\xbf\xbd"},
-}
-
-var testStrings = []string{
-	"",
-	"abcd",
-	"☺☻☹",
-	"日a本b語ç日ð本Ê語þ日¥本¼語i日©",
-	"日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©",
-	"\x80\x80\x80\x80",
-}
-
-func TestFullRune(t *testing.T) {
-	for i := 0; i < len(utf8map); i++ {
-		m := utf8map[i]
-		b := []byte(m.str)
-		if !FullRune(b) {
-			t.Errorf("FullRune(%q) (%U) = false, want true", b, m.rune)
-		}
-		s := m.str
-		if !FullRuneInString(s) {
-			t.Errorf("FullRuneInString(%q) (%U) = false, want true", s, m.rune)
-		}
-		b1 := b[0 : len(b)-1]
-		if FullRune(b1) {
-			t.Errorf("FullRune(%q) = true, want false", b1)
-		}
-		s1 := string(b1)
-		if FullRuneInString(s1) {
-			t.Errorf("FullRune(%q) = true, want false", s1)
-		}
-	}
-}
-
-func TestEncodeRune(t *testing.T) {
-	for i := 0; i < len(utf8map); i++ {
-		m := utf8map[i]
-		b := []byte(m.str)
-		var buf [10]byte
-		n := EncodeRune(buf[0:], m.rune)
-		b1 := buf[0:n]
-		if !bytes.Equal(b, b1) {
-			t.Errorf("EncodeRune(%#04x) = %q want %q", m.rune, b1, b)
-		}
-	}
-}
-
-func TestDecodeRune(t *testing.T) {
-	for i := 0; i < len(utf8map); i++ {
-		m := utf8map[i]
-		b := []byte(m.str)
-		rune, size := DecodeRune(b)
-		if rune != m.rune || size != len(b) {
-			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, rune, size, m.rune, len(b))
-		}
-		s := m.str
-		rune, size = DecodeRuneInString(s)
-		if rune != m.rune || size != len(b) {
-			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", s, rune, size, m.rune, len(b))
-		}
-
-		// there's an extra byte that bytes left behind - make sure trailing byte works
-		rune, size = DecodeRune(b[0:cap(b)])
-		if rune != m.rune || size != len(b) {
-			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, rune, size, m.rune, len(b))
-		}
-		s = m.str + "\x00"
-		rune, size = DecodeRuneInString(s)
-		if rune != m.rune || size != len(b) {
-			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, rune, size, m.rune, len(b))
-		}
-
-		// make sure missing bytes fail
-		wantsize := 1
-		if wantsize >= len(b) {
-			wantsize = 0
-		}
-		rune, size = DecodeRune(b[0 : len(b)-1])
-		if rune != RuneError || size != wantsize {
-			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b[0:len(b)-1], rune, size, RuneError, wantsize)
-		}
-		s = m.str[0 : len(m.str)-1]
-		rune, size = DecodeRuneInString(s)
-		if rune != RuneError || size != wantsize {
-			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, rune, size, RuneError, wantsize)
-		}
-
-		// make sure bad sequences fail
-		if len(b) == 1 {
-			b[0] = 0x80
-		} else {
-			b[len(b)-1] = 0x7F
-		}
-		rune, size = DecodeRune(b)
-		if rune != RuneError || size != 1 {
-			t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, rune, size, RuneError, 1)
-		}
-		s = string(b)
-		rune, size = DecodeRune(b)
-		if rune != RuneError || size != 1 {
-			t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, rune, size, RuneError, 1)
-		}
-
-	}
-}
-
-// Check that DecodeRune and DecodeLastRune correspond to
-// the equivalent range loop.
-func TestSequencing(t *testing.T) {
-	for _, ts := range testStrings {
-		for _, m := range utf8map {
-			for _, s := range []string{ts + m.str, m.str + ts, ts + m.str + ts} {
-				testSequence(t, s)
-			}
-		}
-	}
-}
-
-// Check that a range loop and a []int conversion visit the same runes.
-// Not really a test of this package, but the assumption is used here and
-// it's good to verify
-func TestIntConversion(t *testing.T) {
-	for _, ts := range testStrings {
-		runes := []int(ts)
-		if RuneCountInString(ts) != len(runes) {
-			t.Errorf("%q: expected %d runes; got %d", ts, len(runes), RuneCountInString(ts))
-			break
-		}
-		i := 0
-		for _, r := range ts {
-			if r != runes[i] {
-				t.Errorf("%q[%d]: expected %c (%U); got %c (%U)", ts, i, runes[i], runes[i], r, r)
-			}
-			i++
-		}
-	}
-}
-
-func testSequence(t *testing.T, s string) {
-	type info struct {
-		index int
-		rune  int
-	}
-	index := make([]info, len(s))
-	b := []byte(s)
-	si := 0
-	j := 0
-	for i, r := range s {
-		if si != i {
-			t.Errorf("Sequence(%q) mismatched index %d, want %d", s, si, i)
-			return
-		}
-		index[j] = info{i, r}
-		j++
-		rune1, size1 := DecodeRune(b[i:])
-		if r != rune1 {
-			t.Errorf("DecodeRune(%q) = %#04x, want %#04x", s[i:], rune1, r)
-			return
-		}
-		rune2, size2 := DecodeRuneInString(s[i:])
-		if r != rune2 {
-			t.Errorf("DecodeRuneInString(%q) = %#04x, want %#04x", s[i:], rune2, r)
-			return
-		}
-		if size1 != size2 {
-			t.Errorf("DecodeRune/DecodeRuneInString(%q) size mismatch %d/%d", s[i:], size1, size2)
-			return
-		}
-		si += size1
-	}
-	j--
-	for si = len(s); si > 0; {
-		rune1, size1 := DecodeLastRune(b[0:si])
-		rune2, size2 := DecodeLastRuneInString(s[0:si])
-		if size1 != size2 {
-			t.Errorf("DecodeLastRune/DecodeLastRuneInString(%q, %d) size mismatch %d/%d", s, si, size1, size2)
-			return
-		}
-		if rune1 != index[j].rune {
-			t.Errorf("DecodeLastRune(%q, %d) = %#04x, want %#04x", s, si, rune1, index[j].rune)
-			return
-		}
-		if rune2 != index[j].rune {
-			t.Errorf("DecodeLastRuneInString(%q, %d) = %#04x, want %#04x", s, si, rune2, index[j].rune)
-			return
-		}
-		si -= size1
-		if si != index[j].index {
-			t.Errorf("DecodeLastRune(%q) index mismatch at %d, want %d", s, si, index[j].index)
-			return
-		}
-		j--
-	}
-	if si != 0 {
-		t.Errorf("DecodeLastRune(%q) finished at %d, not 0", s, si)
-	}
-}
-
-// Check that negative runes encode as U+FFFD.
-func TestNegativeRune(t *testing.T) {
-	errorbuf := make([]byte, UTFMax)
-	errorbuf = errorbuf[0:EncodeRune(errorbuf, RuneError)]
-	buf := make([]byte, UTFMax)
-	buf = buf[0:EncodeRune(buf, -1)]
-	if !bytes.Equal(buf, errorbuf) {
-		t.Errorf("incorrect encoding [% x] for -1; expected [% x]", buf, errorbuf)
-	}
-}
-
-type RuneCountTest struct {
-	in  string
-	out int
-}
-
-var runecounttests = []RuneCountTest{
-	{"abcd", 4},
-	{"☺☻☹", 3},
-	{"1,2,3,4", 7},
-	{"\xe2\x00", 2},
-}
-
-func TestRuneCount(t *testing.T) {
-	for i := 0; i < len(runecounttests); i++ {
-		tt := runecounttests[i]
-		if out := RuneCountInString(tt.in); out != tt.out {
-			t.Errorf("RuneCountInString(%q) = %d, want %d", tt.in, out, tt.out)
-		}
-		if out := RuneCount([]byte(tt.in)); out != tt.out {
-			t.Errorf("RuneCount(%q) = %d, want %d", tt.in, out, tt.out)
-		}
-	}
-}
-
-func BenchmarkRuneCountTenASCIIChars(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		RuneCountInString("0123456789")
-	}
-}
-
-func BenchmarkRuneCountTenJapaneseChars(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		RuneCountInString("日本語日本語日本語日")
-	}
-}
-
-func BenchmarkEncodeASCIIRune(b *testing.B) {
-	buf := make([]byte, UTFMax)
-	for i := 0; i < b.N; i++ {
-		EncodeRune(buf, 'a')
-	}
-}
-
-func BenchmarkEncodeJapaneseRune(b *testing.B) {
-	buf := make([]byte, UTFMax)
-	for i := 0; i < b.N; i++ {
-		EncodeRune(buf, '本')
-	}
-}
-
-func BenchmarkDecodeASCIIRune(b *testing.B) {
-	a := []byte{'a'}
-	for i := 0; i < b.N; i++ {
-		DecodeRune(a)
-	}
-}
-
-func BenchmarkDecodeJapaneseRune(b *testing.B) {
-	nihon := []byte("本")
-	for i := 0; i < b.N; i++ {
-		DecodeRune(nihon)
-	}
-}
diff --git a/src/pkg/websocket/Makefile b/src/pkg/websocket/Makefile
deleted file mode 100644
index 25131de..0000000
--- a/src/pkg/websocket/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-include ../../Make.inc
-
-TARG=websocket
-GOFILES=\
-	client.go\
-	server.go\
-	websocket.go\
-	hixie.go\
-	hybi.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/websocket/client.go b/src/pkg/websocket/client.go
deleted file mode 100644
index 7497ac6..0000000
--- a/src/pkg/websocket/client.go
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
-	"bufio"
-	"crypto/tls"
-	"io"
-	"net"
-	"os"
-	"url"
-)
-
-// DialError is an error that occurs while dialling a websocket server.
-type DialError struct {
-	*Config
-	Error os.Error
-}
-
-func (e *DialError) String() string {
-	return "websocket.Dial " + e.Config.Location.String() + ": " + e.Error.String()
-}
-
-// NewConfig creates a new WebSocket config for client connection.
-func NewConfig(server, origin string) (config *Config, err os.Error) {
-	config = new(Config)
-	config.Version = ProtocolVersionHybi
-	config.Location, err = url.ParseRequest(server)
-	if err != nil {
-		return
-	}
-	config.Origin, err = url.ParseRequest(origin)
-	if err != nil {
-		return
-	}
-	return
-}
-
-// NewClient creates a new WebSocket client connection over rwc.
-func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err os.Error) {
-	br := bufio.NewReader(rwc)
-	bw := bufio.NewWriter(rwc)
-	switch config.Version {
-	case ProtocolVersionHixie75:
-		err = hixie75ClientHandshake(config, br, bw)
-	case ProtocolVersionHixie76, ProtocolVersionHybi00:
-		err = hixie76ClientHandshake(config, br, bw)
-	case ProtocolVersionHybi:
-		err = hybiClientHandshake(config, br, bw)
-	default:
-		err = ErrBadProtocolVersion
-	}
-	if err != nil {
-		return
-	}
-	buf := bufio.NewReadWriter(br, bw)
-	switch config.Version {
-	case ProtocolVersionHixie75, ProtocolVersionHixie76, ProtocolVersionHybi00:
-		ws = newHixieClientConn(config, buf, rwc)
-	case ProtocolVersionHybi:
-		ws = newHybiClientConn(config, buf, rwc)
-	}
-	return
-}
-
-/*
-Dial opens a new client connection to a WebSocket.
-
-A trivial example client:
-
-	package main
-
-	import (
-		"http"
-		"log"
-		"strings"
-		"websocket"
-	)
-
-	func main() {
-		origin := "http://localhost/"
-		url := "ws://localhost/ws" 
-		ws, err := websocket.Dial(url, "", origin)
-		if err != nil {
-			log.Fatal(err)
-		}
-		if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
-			log.Fatal(err)
-		}
-		var msg = make([]byte, 512);
-		if n, err := ws.Read(msg); err != nil {
-			log.Fatal(err)
-		}
-		// use msg[0:n]
-	}
-*/
-func Dial(url_, protocol, origin string) (ws *Conn, err os.Error) {
-	config, err := NewConfig(url_, origin)
-	if err != nil {
-		return nil, err
-	}
-	return DialConfig(config)
-}
-
-// DialConfig opens a new client connection to a WebSocket with a config.
-func DialConfig(config *Config) (ws *Conn, err os.Error) {
-	var client net.Conn
-	if config.Location == nil {
-		return nil, &DialError{config, ErrBadWebSocketLocation}
-	}
-	if config.Origin == nil {
-		return nil, &DialError{config, ErrBadWebSocketOrigin}
-	}
-	switch config.Location.Scheme {
-	case "ws":
-		client, err = net.Dial("tcp", config.Location.Host)
-
-	case "wss":
-		client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
-
-	default:
-		err = ErrBadScheme
-	}
-	if err != nil {
-		goto Error
-	}
-
-	ws, err = NewClient(config, client)
-	if err != nil {
-		goto Error
-	}
-	return
-
-Error:
-	return nil, &DialError{config, err}
-}
diff --git a/src/pkg/websocket/hixie.go b/src/pkg/websocket/hixie.go
deleted file mode 100644
index b755a5c..0000000
--- a/src/pkg/websocket/hixie.go
+++ /dev/null
@@ -1,694 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-// This file implements a protocol of Hixie draft version 75 and 76
-// (draft 76 equals to hybi 00)
-
-import (
-	"bufio"
-	"bytes"
-	"container/vector"
-	"crypto/md5"
-	"encoding/binary"
-	"fmt"
-	"http"
-	"io"
-	"io/ioutil"
-	"os"
-	"rand"
-	"strconv"
-	"strings"
-	"url"
-)
-
-// An aray of characters to be randomly inserted to construct Sec-WebSocket-Key
-// value. It holds characters from ranges U+0021 to U+002F and U+003A to U+007E.
-// See Step 21 in Section 4.1 Opening handshake.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#page-22
-var secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte
-
-func init() {
-	i := 0
-	for ch := byte(0x21); ch < 0x30; ch++ {
-		secKeyRandomChars[i] = ch
-		i++
-	}
-	for ch := byte(0x3a); ch < 0x7F; ch++ {
-		secKeyRandomChars[i] = ch
-		i++
-	}
-}
-
-type byteReader interface {
-	ReadByte() (byte, os.Error)
-}
-
-// readHixieLength reads frame length for frame type 0x80-0xFF
-// as defined in Hixie draft.
-// See section 4.2 Data framing.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-4.2
-func readHixieLength(r byteReader) (length int64, lengthFields []byte, err os.Error) {
-	for {
-		c, err := r.ReadByte()
-		if err != nil {
-			return 0, nil, err
-		}
-		lengthFields = append(lengthFields, c)
-		length = length*128 + int64(c&0x7f)
-		if c&0x80 == 0 {
-			break
-		}
-	}
-	return
-}
-
-// A hixieLengthFrameReader is a reader for frame type 0x80-0xFF
-// as defined in hixie draft.
-type hixieLengthFrameReader struct {
-	reader    io.Reader
-	FrameType byte
-	Length    int64
-	header    *bytes.Buffer
-	length    int
-}
-
-func (frame *hixieLengthFrameReader) Read(msg []byte) (n int, err os.Error) {
-	return frame.reader.Read(msg)
-}
-
-func (frame *hixieLengthFrameReader) PayloadType() byte {
-	if frame.FrameType == '\xff' && frame.Length == 0 {
-		return CloseFrame
-	}
-	return UnknownFrame
-}
-
-func (frame *hixieLengthFrameReader) HeaderReader() io.Reader {
-	if frame.header == nil {
-		return nil
-	}
-	if frame.header.Len() == 0 {
-		frame.header = nil
-		return nil
-	}
-	return frame.header
-}
-
-func (frame *hixieLengthFrameReader) TrailerReader() io.Reader { return nil }
-
-func (frame *hixieLengthFrameReader) Len() (n int) { return frame.length }
-
-// A HixieSentinelFrameReader is a reader for frame type 0x00-0x7F
-// as defined in hixie draft.
-type hixieSentinelFrameReader struct {
-	reader      *bufio.Reader
-	FrameType   byte
-	header      *bytes.Buffer
-	data        []byte
-	seenTrailer bool
-	trailer     *bytes.Buffer
-}
-
-func (frame *hixieSentinelFrameReader) Read(msg []byte) (n int, err os.Error) {
-	if len(frame.data) == 0 {
-		if frame.seenTrailer {
-			return 0, os.EOF
-		}
-		frame.data, err = frame.reader.ReadSlice('\xff')
-		if err == nil {
-			frame.seenTrailer = true
-			frame.data = frame.data[:len(frame.data)-1] // trim \xff
-			frame.trailer = bytes.NewBuffer([]byte{0xff})
-		}
-	}
-	n = copy(msg, frame.data)
-	frame.data = frame.data[n:]
-	return n, err
-}
-
-func (frame *hixieSentinelFrameReader) PayloadType() byte {
-	if frame.FrameType == 0 {
-		return TextFrame
-	}
-	return UnknownFrame
-}
-
-func (frame *hixieSentinelFrameReader) HeaderReader() io.Reader {
-	if frame.header == nil {
-		return nil
-	}
-	if frame.header.Len() == 0 {
-		frame.header = nil
-		return nil
-	}
-	return frame.header
-}
-
-func (frame *hixieSentinelFrameReader) TrailerReader() io.Reader {
-	if frame.trailer == nil {
-		return nil
-	}
-	if frame.trailer.Len() == 0 {
-		frame.trailer = nil
-		return nil
-	}
-	return frame.trailer
-}
-
-func (frame *hixieSentinelFrameReader) Len() int { return -1 }
-
-// A HixieFrameReaderFactory creates new frame reader based on its frame type.
-type hixieFrameReaderFactory struct {
-	*bufio.Reader
-}
-
-func (buf hixieFrameReaderFactory) NewFrameReader() (r frameReader, err os.Error) {
-	var header []byte
-	var b byte
-	b, err = buf.ReadByte()
-	if err != nil {
-		return
-	}
-	header = append(header, b)
-	if b&0x80 == 0x80 {
-		length, lengthFields, err := readHixieLength(buf.Reader)
-		if err != nil {
-			return nil, err
-		}
-		if length == 0 {
-			return nil, os.EOF
-		}
-		header = append(header, lengthFields...)
-		return &hixieLengthFrameReader{
-			reader:    io.LimitReader(buf.Reader, length),
-			FrameType: b,
-			Length:    length,
-			header:    bytes.NewBuffer(header)}, err
-	}
-	return &hixieSentinelFrameReader{
-		reader:    buf.Reader,
-		FrameType: b,
-		header:    bytes.NewBuffer(header)}, err
-}
-
-type hixiFrameWriter struct {
-	writer *bufio.Writer
-}
-
-func (frame *hixiFrameWriter) Write(msg []byte) (n int, err os.Error) {
-	frame.writer.WriteByte(0)
-	frame.writer.Write(msg)
-	frame.writer.WriteByte(0xff)
-	err = frame.writer.Flush()
-	return len(msg), err
-}
-
-func (frame *hixiFrameWriter) Close() os.Error { return nil }
-
-type hixiFrameWriterFactory struct {
-	*bufio.Writer
-}
-
-func (buf hixiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err os.Error) {
-	if payloadType != TextFrame {
-		return nil, ErrNotSupported
-	}
-	return &hixiFrameWriter{writer: buf.Writer}, nil
-}
-
-type hixiFrameHandler struct {
-	conn *Conn
-}
-
-func (handler *hixiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err os.Error) {
-	if header := frame.HeaderReader(); header != nil {
-		io.Copy(ioutil.Discard, header)
-	}
-	if frame.PayloadType() != TextFrame {
-		io.Copy(ioutil.Discard, frame)
-		return nil, nil
-	}
-	return frame, nil
-}
-
-func (handler *hixiFrameHandler) WriteClose(_ int) (err os.Error) {
-	closingFrame := []byte{'\xff', '\x00'}
-	handler.conn.buf.Write(closingFrame)
-	return handler.conn.buf.Flush()
-}
-
-// newHixiConn creates a new WebSocket connection speaking hixie draft protocol.
-func newHixieConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-	if buf == nil {
-		br := bufio.NewReader(rwc)
-		bw := bufio.NewWriter(rwc)
-		buf = bufio.NewReadWriter(br, bw)
-	}
-	ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
-		frameReaderFactory: hixieFrameReaderFactory{buf.Reader},
-		frameWriterFactory: hixiFrameWriterFactory{buf.Writer},
-		PayloadType:        TextFrame}
-	ws.frameHandler = &hixiFrameHandler{ws}
-	return ws
-}
-
-// getChallengeResponse computes the expected response from the
-// challenge as described in section 5.1 Opening Handshake steps 42 to
-// 43 of http://www.whatwg.org/specs/web-socket-protocol/
-func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err os.Error) {
-	// 41. Let /challenge/ be the concatenation of /number_1/, expressed
-	// a big-endian 32 bit integer, /number_2/, expressed in a big-
-	// endian 32 bit integer, and the eight bytes of /key_3/ in the
-	// order they were sent to the wire.
-	challenge := make([]byte, 16)
-	binary.BigEndian.PutUint32(challenge[0:], number1)
-	binary.BigEndian.PutUint32(challenge[4:], number2)
-	copy(challenge[8:], key3)
-
-	// 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big-
-	// endian 128 bit string.
-	h := md5.New()
-	if _, err = h.Write(challenge); err != nil {
-		return
-	}
-	expected = h.Sum()
-	return
-}
-
-// Generates handshake key as described in 4.1 Opening handshake step 16 to 22.
-// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func generateKeyNumber() (key string, number uint32) {
-	// 16.  Let /spaces_n/ be a random integer from 1 to 12 inclusive.
-	spaces := rand.Intn(12) + 1
-
-	// 17. Let /max_n/ be the largest integer not greater than
-	//     4,294,967,295 divided by /spaces_n/
-	max := int(4294967295 / uint32(spaces))
-
-	// 18. Let /number_n/ be a random integer from 0 to /max_n/ inclusive.
-	number = uint32(rand.Intn(max + 1))
-
-	// 19. Let /product_n/ be the result of multiplying /number_n/ and
-	//     /spaces_n/ together.
-	product := number * uint32(spaces)
-
-	// 20. Let /key_n/ be a string consisting of /product_n/, expressed
-	// in base ten using the numerals in the range U+0030 DIGIT ZERO (0)
-	// to U+0039 DIGIT NINE (9).
-	key = fmt.Sprintf("%d", product)
-
-	// 21. Insert between one and twelve random characters from the ranges
-	//     U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
-	//     positions.
-	n := rand.Intn(12) + 1
-	for i := 0; i < n; i++ {
-		pos := rand.Intn(len(key)) + 1
-		ch := secKeyRandomChars[rand.Intn(len(secKeyRandomChars))]
-		key = key[0:pos] + string(ch) + key[pos:]
-	}
-
-	// 22. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random
-	//     positions other than the start or end of the string.
-	for i := 0; i < spaces; i++ {
-		pos := rand.Intn(len(key)-1) + 1
-		key = key[0:pos] + " " + key[pos:]
-	}
-
-	return
-}
-
-// Generates handshake key_3 as described in 4.1 Opening handshake step 26.
-// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func generateKey3() (key []byte) {
-	// 26. Let /key3/ be a string consisting of eight random bytes (or
-	//  equivalently, a random 64 bit integer encoded in big-endian order).
-	key = make([]byte, 8)
-	for i := 0; i < 8; i++ {
-		key[i] = byte(rand.Intn(256))
-	}
-	return
-}
-
-// Cilent handhake described in (soon obsolete)
-// draft-ietf-hybi-thewebsocket-protocol-00
-// (draft-hixie-thewebsocket-protocol-76) 
-func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
-	switch config.Version {
-	case ProtocolVersionHixie76, ProtocolVersionHybi00:
-	default:
-		panic("wrong protocol version.")
-	}
-	// 4.1. Opening handshake.
-	// Step 5.  send a request line.
-	bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")
-
-	// Step 6-14. push request headers in fields.
-	var fields vector.StringVector
-	fields.Push("Upgrade: WebSocket\r\n")
-	fields.Push("Connection: Upgrade\r\n")
-	fields.Push("Host: " + config.Location.Host + "\r\n")
-	fields.Push("Origin: " + config.Origin.String() + "\r\n")
-	if len(config.Protocol) > 0 {
-		if len(config.Protocol) != 1 {
-			return ErrBadWebSocketProtocol
-		}
-		fields.Push("Sec-WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
-	}
-	// TODO(ukai): Step 15. send cookie if any.
-
-	// Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
-	key1, number1 := generateKeyNumber()
-	key2, number2 := generateKeyNumber()
-	if config.handshakeData != nil {
-		key1 = config.handshakeData["key1"]
-		n, err := strconv.Atoui(config.handshakeData["number1"])
-		if err != nil {
-			panic(err)
-		}
-		number1 = uint32(n)
-		key2 = config.handshakeData["key2"]
-		n, err = strconv.Atoui(config.handshakeData["number2"])
-		if err != nil {
-			panic(err)
-		}
-		number2 = uint32(n)
-	}
-	fields.Push("Sec-WebSocket-Key1: " + key1 + "\r\n")
-	fields.Push("Sec-WebSocket-Key2: " + key2 + "\r\n")
-
-	// Step 24. shuffle fields and send them out.
-	for i := 1; i < len(fields); i++ {
-		j := rand.Intn(i)
-		fields[i], fields[j] = fields[j], fields[i]
-	}
-	for i := 0; i < len(fields); i++ {
-		bw.WriteString(fields[i])
-	}
-	// Step 25. send CRLF.
-	bw.WriteString("\r\n")
-
-	// Step 26. generate 8 bytes random key.
-	key3 := generateKey3()
-	if config.handshakeData != nil {
-		key3 = []byte(config.handshakeData["key3"])
-	}
-	// Step 27. send it out.
-	bw.Write(key3)
-	if err = bw.Flush(); err != nil {
-		return
-	}
-
-	// Step 28-29, 32-40. read response from server.
-	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
-	if err != nil {
-		return err
-	}
-	// Step 30. check response code is 101.
-	if resp.StatusCode != 101 {
-		return ErrBadStatus
-	}
-
-	// Step 41. check websocket headers.
-	if resp.Header.Get("Upgrade") != "WebSocket" ||
-		strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
-		return ErrBadUpgrade
-	}
-
-	if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() {
-		return ErrBadWebSocketOrigin
-	}
-
-	if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() {
-		return ErrBadWebSocketLocation
-	}
-
-	if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] {
-		return ErrBadWebSocketProtocol
-	}
-
-	// Step 42-43. get expected data from challenge data.
-	expected, err := getChallengeResponse(number1, number2, key3)
-	if err != nil {
-		return err
-	}
-
-	// Step 44. read 16 bytes from server.
-	reply := make([]byte, 16)
-	if _, err = io.ReadFull(br, reply); err != nil {
-		return err
-	}
-
-	// Step 45. check the reply equals to expected data.
-	if !bytes.Equal(expected, reply) {
-		return ErrChallengeResponse
-	}
-	// WebSocket connection is established.
-	return
-}
-
-// Client Handshake described in (soon obsolete)
-// draft-hixie-thewebsocket-protocol-75.
-func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
-	if config.Version != ProtocolVersionHixie75 {
-		panic("wrong protocol version.")
-	}
-	bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")
-	bw.WriteString("Upgrade: WebSocket\r\n")
-	bw.WriteString("Connection: Upgrade\r\n")
-	bw.WriteString("Host: " + config.Location.Host + "\r\n")
-	bw.WriteString("Origin: " + config.Origin.String() + "\r\n")
-	if len(config.Protocol) > 0 {
-		if len(config.Protocol) != 1 {
-			return ErrBadWebSocketProtocol
-		}
-		bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
-	}
-	bw.WriteString("\r\n")
-	bw.Flush()
-	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
-	if err != nil {
-		return
-	}
-	if resp.Status != "101 Web Socket Protocol Handshake" {
-		return ErrBadStatus
-	}
-	if resp.Header.Get("Upgrade") != "WebSocket" ||
-		resp.Header.Get("Connection") != "Upgrade" {
-		return ErrBadUpgrade
-	}
-	if resp.Header.Get("Websocket-Origin") != config.Origin.String() {
-		return ErrBadWebSocketOrigin
-	}
-	if resp.Header.Get("Websocket-Location") != config.Location.String() {
-		return ErrBadWebSocketLocation
-	}
-	if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] {
-		return ErrBadWebSocketProtocol
-	}
-	return
-}
-
-// newHixieClientConn returns new WebSocket connection speaking hixie draft protocol.
-func newHixieClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
-	return newHixieConn(config, buf, rwc, nil)
-}
-
-// Gets key number from Sec-WebSocket-Key<n>: field as described
-// in 5.2 Sending the server's opening handshake, 4.
-func getKeyNumber(s string) (r uint32) {
-	// 4. Let /key-number_n/ be the digits (characters in the range
-	// U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_1/,
-	// interpreted as a base ten integer, ignoring all other characters
-	// in /key_n/.
-	r = 0
-	for i := 0; i < len(s); i++ {
-		if s[i] >= '0' && s[i] <= '9' {
-			r = r*10 + uint32(s[i]) - '0'
-		}
-	}
-	return
-}
-
-// A Hixie76ServerHandshaker performs a server handshake using
-// hixie draft 76 protocol.
-type hixie76ServerHandshaker struct {
-	*Config
-	challengeResponse []byte
-}
-
-func (c *hixie76ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err os.Error) {
-	c.Version = ProtocolVersionHybi00
-	if req.Method != "GET" {
-		return http.StatusMethodNotAllowed, ErrBadRequestMethod
-	}
-	// HTTP version can be safely ignored.
-
-	if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
-		strings.ToLower(req.Header.Get("Connection")) != "upgrade" {
-		return http.StatusBadRequest, ErrNotWebSocket
-	}
-
-	// TODO(ukai): check Host
-	c.Origin, err = url.ParseRequest(req.Header.Get("Origin"))
-	if err != nil {
-		return http.StatusBadRequest, err
-	}
-
-	key1 := req.Header.Get("Sec-Websocket-Key1")
-	if key1 == "" {
-		return http.StatusBadRequest, ErrChallengeResponse
-	}
-	key2 := req.Header.Get("Sec-Websocket-Key2")
-	if key2 == "" {
-		return http.StatusBadRequest, ErrChallengeResponse
-	}
-	key3 := make([]byte, 8)
-	if _, err := io.ReadFull(buf, key3); err != nil {
-		return http.StatusBadRequest, ErrChallengeResponse
-	}
-
-	var scheme string
-	if req.TLS != nil {
-		scheme = "wss"
-	} else {
-		scheme = "ws"
-	}
-	c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RawPath)
-	if err != nil {
-		return http.StatusBadRequest, err
-	}
-
-	// Step 4. get key number in Sec-WebSocket-Key<n> fields.
-	keyNumber1 := getKeyNumber(key1)
-	keyNumber2 := getKeyNumber(key2)
-
-	// Step 5. get number of spaces in Sec-WebSocket-Key<n> fields.
-	space1 := uint32(strings.Count(key1, " "))
-	space2 := uint32(strings.Count(key2, " "))
-	if space1 == 0 || space2 == 0 {
-		return http.StatusBadRequest, ErrChallengeResponse
-	}
-
-	// Step 6. key number must be an integral multiple of spaces.
-	if keyNumber1%space1 != 0 || keyNumber2%space2 != 0 {
-		return http.StatusBadRequest, ErrChallengeResponse
-	}
-
-	// Step 7. let part be key number divided by spaces.
-	part1 := keyNumber1 / space1
-	part2 := keyNumber2 / space2
-
-	// Step 8. let challenge be concatenation of part1, part2 and key3.
-	// Step 9. get MD5 fingerprint of challenge.
-	c.challengeResponse, err = getChallengeResponse(part1, part2, key3)
-	if err != nil {
-		return http.StatusInternalServerError, err
-	}
-	protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
-	protocols := strings.Split(protocol, ",")
-	for i := 0; i < len(protocols); i++ {
-		c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
-	}
-
-	return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hixie76ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err os.Error) {
-	if len(c.Protocol) > 0 {
-		if len(c.Protocol) != 1 {
-			return ErrBadWebSocketProtocol
-		}
-	}
-
-	// Step 10. send response status line.
-	buf.WriteString("HTTP/1.1 101 WebSocket Protocol Handshake\r\n")
-	// Step 11. send response headers.
-	buf.WriteString("Upgrade: WebSocket\r\n")
-	buf.WriteString("Connection: Upgrade\r\n")
-	buf.WriteString("Sec-WebSocket-Origin: " + c.Origin.String() + "\r\n")
-	buf.WriteString("Sec-WebSocket-Location: " + c.Location.String() + "\r\n")
-	if len(c.Protocol) > 0 {
-		buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
-	}
-	// Step 12. send CRLF.
-	buf.WriteString("\r\n")
-	// Step 13. send response data.
-	buf.Write(c.challengeResponse)
-	return buf.Flush()
-}
-
-func (c *hixie76ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
-	return newHixieServerConn(c.Config, buf, rwc, request)
-}
-
-// A hixie75ServerHandshaker performs a server handshake using
-// hixie draft 75 protocol.
-type hixie75ServerHandshaker struct {
-	*Config
-}
-
-func (c *hixie75ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err os.Error) {
-	c.Version = ProtocolVersionHixie75
-	if req.Method != "GET" || req.Proto != "HTTP/1.1" {
-		return http.StatusMethodNotAllowed, ErrBadRequestMethod
-	}
-	if req.Header.Get("Upgrade") != "WebSocket" {
-		return http.StatusBadRequest, ErrNotWebSocket
-	}
-	if req.Header.Get("Connection") != "Upgrade" {
-		return http.StatusBadRequest, ErrNotWebSocket
-	}
-	c.Origin, err = url.ParseRequest(strings.TrimSpace(req.Header.Get("Origin")))
-	if err != nil {
-		return http.StatusBadRequest, err
-	}
-
-	var scheme string
-	if req.TLS != nil {
-		scheme = "wss"
-	} else {
-		scheme = "ws"
-	}
-	c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RawPath)
-	if err != nil {
-		return http.StatusBadRequest, err
-	}
-	protocol := strings.TrimSpace(req.Header.Get("Websocket-Protocol"))
-	protocols := strings.Split(protocol, ",")
-	for i := 0; i < len(protocols); i++ {
-		c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
-	}
-
-	return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hixie75ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err os.Error) {
-	if len(c.Protocol) > 0 {
-		if len(c.Protocol) != 1 {
-			return ErrBadWebSocketProtocol
-		}
-	}
-
-	buf.WriteString("HTTP/1.1 101 Web Socket Protocol Handshake\r\n")
-	buf.WriteString("Upgrade: WebSocket\r\n")
-	buf.WriteString("Connection: Upgrade\r\n")
-	buf.WriteString("WebSocket-Origin: " + c.Origin.String() + "\r\n")
-	buf.WriteString("WebSocket-Location: " + c.Location.String() + "\r\n")
-	if len(c.Protocol) > 0 {
-		buf.WriteString("WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
-	}
-	buf.WriteString("\r\n")
-	return buf.Flush()
-}
-
-func (c *hixie75ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
-	return newHixieServerConn(c.Config, buf, rwc, request)
-}
-
-// newHixieServerConn returns a new WebSocket connection speaking hixie draft protocol.
-func newHixieServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-	return newHixieConn(config, buf, rwc, request)
-}
diff --git a/src/pkg/websocket/hixie_test.go b/src/pkg/websocket/hixie_test.go
deleted file mode 100644
index a480b66..0000000
--- a/src/pkg/websocket/hixie_test.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2011 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 websocket
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"http"
-	"os"
-	"strings"
-	"testing"
-	"url"
-)
-
-// Test the getChallengeResponse function with values from section
-// 5.1 of the specification steps 18, 26, and 43 from
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func TestHixie76Challenge(t *testing.T) {
-	var part1 uint32 = 777007543
-	var part2 uint32 = 114997259
-	key3 := []byte{0x47, 0x30, 0x22, 0x2D, 0x5A, 0x3F, 0x47, 0x58}
-	expected := []byte("0st3Rl&q-2ZU^weu")
-
-	response, err := getChallengeResponse(part1, part2, key3)
-	if err != nil {
-		t.Errorf("getChallengeResponse: returned error %v", err)
-		return
-	}
-	if !bytes.Equal(expected, response) {
-		t.Errorf("getChallengeResponse: expected %q got %q", expected, response)
-	}
-}
-
-func TestHixie76ClientHandshake(t *testing.T) {
-	b := bytes.NewBuffer([]byte{})
-	bw := bufio.NewWriter(b)
-	br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 WebSocket Protocol Handshake
-Upgrade: WebSocket
-Connection: Upgrade
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Location: ws://example.com/demo
-Sec-WebSocket-Protocol: sample
-
-8jKS'y:G*Co,Wxa-`))
-
-	var err os.Error
-	config := new(Config)
-	config.Location, err = url.ParseRequest("ws://example.com/demo")
-	if err != nil {
-		t.Fatal("location url", err)
-	}
-	config.Origin, err = url.ParseRequest("http://example.com")
-	if err != nil {
-		t.Fatal("origin url", err)
-	}
-	config.Protocol = append(config.Protocol, "sample")
-	config.Version = ProtocolVersionHixie76
-
-	config.handshakeData = map[string]string{
-		"key1":    "4 @1  46546xW%0l 1 5",
-		"number1": "829309203",
-		"key2":    "12998 5 Y3 1  .P00",
-		"number2": "259970620",
-		"key3":    "^n:ds[4U",
-	}
-	err = hixie76ClientHandshake(config, br, bw)
-	if err != nil {
-		t.Errorf("handshake failed: %v", err)
-	}
-	req, err := http.ReadRequest(bufio.NewReader(b))
-	if err != nil {
-		t.Errorf("read request: %v", err)
-	}
-	if req.Method != "GET" {
-		t.Errorf("request method expected GET, but got %q", req.Method)
-	}
-	if req.RawURL != "/demo" {
-		t.Errorf("request path expected /demo, but got %q", req.RawURL)
-	}
-	if req.Proto != "HTTP/1.1" {
-		t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
-	}
-	if req.Host != "example.com" {
-		t.Errorf("request Host expected example.com, but got %v", req.Host)
-	}
-	var expectedHeader = map[string]string{
-		"Connection":             "Upgrade",
-		"Upgrade":                "WebSocket",
-		"Origin":                 "http://example.com",
-		"Sec-Websocket-Key1":     config.handshakeData["key1"],
-		"Sec-Websocket-Key2":     config.handshakeData["key2"],
-		"Sec-WebSocket-Protocol": config.Protocol[0],
-	}
-	for k, v := range expectedHeader {
-		if req.Header.Get(k) != v {
-			t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
-		}
-	}
-}
-
-func TestHixie76ServerHandshake(t *testing.T) {
-	config := new(Config)
-	handshaker := &hixie76ServerHandshaker{Config: config}
-	br := bufio.NewReader(strings.NewReader(`GET /demo HTTP/1.1
-Host: example.com
-Connection: Upgrade
-Sec-WebSocket-Key2: 12998 5 Y3 1  .P00
-Sec-WebSocket-Protocol: sample
-Upgrade: WebSocket
-Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5
-Origin: http://example.com
-
-^n:ds[4U`))
-	req, err := http.ReadRequest(br)
-	if err != nil {
-		t.Fatal("request", err)
-	}
-	code, err := handshaker.ReadHandshake(br, req)
-	if err != nil {
-		t.Errorf("handshake failed: %v", err)
-	}
-	if code != http.StatusSwitchingProtocols {
-		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
-	}
-	b := bytes.NewBuffer([]byte{})
-	bw := bufio.NewWriter(b)
-
-	err = handshaker.AcceptHandshake(bw)
-	if err != nil {
-		t.Errorf("handshake response failed: %v", err)
-	}
-	expectedResponse := strings.Join([]string{
-		"HTTP/1.1 101 WebSocket Protocol Handshake",
-		"Upgrade: WebSocket",
-		"Connection: Upgrade",
-		"Sec-WebSocket-Origin: http://example.com",
-		"Sec-WebSocket-Location: ws://example.com/demo",
-		"Sec-WebSocket-Protocol: sample",
-		"", ""}, "\r\n") + "8jKS'y:G*Co,Wxa-"
-	if b.String() != expectedResponse {
-		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
-	}
-}
-
-func TestHixie76SkipLengthFrame(t *testing.T) {
-	b := []byte{'\x80', '\x01', 'x', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
-	buf := bytes.NewBuffer(b)
-	br := bufio.NewReader(buf)
-	bw := bufio.NewWriter(buf)
-	config := newConfig(t, "/")
-	ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
-	msg := make([]byte, 5)
-	n, err := ws.Read(msg)
-	if err != nil {
-		t.Errorf("Read: %v", err)
-	}
-	if !bytes.Equal(b[4:9], msg[0:n]) {
-		t.Errorf("Read: expected %q got %q", b[4:9], msg[0:n])
-	}
-}
-
-func TestHixie76SkipNoUTF8Frame(t *testing.T) {
-	b := []byte{'\x01', 'n', '\xff', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
-	buf := bytes.NewBuffer(b)
-	br := bufio.NewReader(buf)
-	bw := bufio.NewWriter(buf)
-	config := newConfig(t, "/")
-	ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
-	msg := make([]byte, 5)
-	n, err := ws.Read(msg)
-	if err != nil {
-		t.Errorf("Read: %v", err)
-	}
-	if !bytes.Equal(b[4:9], msg[0:n]) {
-		t.Errorf("Read: expected %q got %q", b[4:9], msg[0:n])
-	}
-}
-
-func TestHixie76ClosingFrame(t *testing.T) {
-	b := []byte{0, 'h', 'e', 'l', 'l', 'o', '\xff'}
-	buf := bytes.NewBuffer(b)
-	br := bufio.NewReader(buf)
-	bw := bufio.NewWriter(buf)
-	config := newConfig(t, "/")
-	ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
-	msg := make([]byte, 5)
-	n, err := ws.Read(msg)
-	if err != nil {
-		t.Errorf("read: %v", err)
-	}
-	if !bytes.Equal(b[1:6], msg[0:n]) {
-		t.Errorf("Read: expected %q got %q", b[1:6], msg[0:n])
-	}
-	n, err = ws.Read(msg)
-	if err != os.EOF {
-		t.Errorf("read: %v", err)
-	}
-}
diff --git a/src/pkg/websocket/hybi.go b/src/pkg/websocket/hybi.go
deleted file mode 100644
index cad4718..0000000
--- a/src/pkg/websocket/hybi.go
+++ /dev/null
@@ -1,515 +0,0 @@
-// Copyright 2011 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 websocket
-
-// This file implements a protocol of hybi draft.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10
-
-import (
-	"bufio"
-	"bytes"
-	"crypto/rand"
-	"crypto/sha1"
-	"encoding/base64"
-	"encoding/binary"
-	"fmt"
-	"http"
-	"io"
-	"io/ioutil"
-	"os"
-	"strings"
-	"url"
-)
-
-const (
-	websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
-
-	closeStatusNormal          = 1000
-	closeStatusGoingAway       = 1001
-	closeStatusProtocolError   = 1002
-	closeStatusUnsupportedData = 1003
-	closeStatusFrameTooLarge   = 1004
-	closeStatusNoStatusRcvd    = 1005
-	closeStatusAbnormalClosure = 1006
-
-	maxControlFramePayloadLength = 125
-)
-
-var (
-	ErrBadMaskingKey         = &ProtocolError{"bad masking key"}
-	ErrBadPongMessage        = &ProtocolError{"bad pong message"}
-	ErrBadClosingStatus      = &ProtocolError{"bad closing status"}
-	ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
-	ErrNotImplemented        = &ProtocolError{"not implemented"}
-)
-
-// A hybiFrameHeader is a frame header as defined in hybi draft.
-type hybiFrameHeader struct {
-	Fin        bool
-	Rsv        [3]bool
-	OpCode     byte
-	Length     int64
-	MaskingKey []byte
-
-	data *bytes.Buffer
-}
-
-// A hybiFrameReader is a reader for hybi frame.
-type hybiFrameReader struct {
-	reader io.Reader
-
-	header hybiFrameHeader
-	pos    int64
-	length int
-}
-
-func (frame *hybiFrameReader) Read(msg []byte) (n int, err os.Error) {
-	n, err = frame.reader.Read(msg)
-	if err != nil {
-		return 0, err
-	}
-	if frame.header.MaskingKey != nil {
-		for i := 0; i < n; i++ {
-			msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
-			frame.pos++
-		}
-	}
-	return n, err
-}
-
-func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
-
-func (frame *hybiFrameReader) HeaderReader() io.Reader {
-	if frame.header.data == nil {
-		return nil
-	}
-	if frame.header.data.Len() == 0 {
-		return nil
-	}
-	return frame.header.data
-}
-
-func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
-
-func (frame *hybiFrameReader) Len() (n int) { return frame.length }
-
-// A hybiFrameReaderFactory creates new frame reader based on its frame type.
-type hybiFrameReaderFactory struct {
-	*bufio.Reader
-}
-
-// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
-// See Section 4.2 Base Frameing protocol for detail.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10#section-4.2
-func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err os.Error) {
-	hybiFrame := new(hybiFrameReader)
-	frame = hybiFrame
-	var header []byte
-	var b byte
-	// First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
-	b, err = buf.ReadByte()
-	if err != nil {
-		return
-	}
-	header = append(header, b)
-	hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
-	for i := 0; i < 3; i++ {
-		j := uint(6 - i)
-		hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
-	}
-	hybiFrame.header.OpCode = header[0] & 0x0f
-
-	// Second byte. Mask/Payload len(7bits)
-	b, err = buf.ReadByte()
-	if err != nil {
-		return
-	}
-	header = append(header, b)
-	mask := (b & 0x80) != 0
-	b &= 0x7f
-	lengthFields := 0
-	switch {
-	case b <= 125: // Payload length 7bits.
-		hybiFrame.header.Length = int64(b)
-	case b == 126: // Payload length 7+16bits
-		lengthFields = 2
-	case b == 127: // Payload length 7+64bits
-		lengthFields = 8
-	}
-	for i := 0; i < lengthFields; i++ {
-		b, err = buf.ReadByte()
-		if err != nil {
-			return
-		}
-		header = append(header, b)
-		hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
-	}
-	if mask {
-		// Masking key. 4 bytes.
-		for i := 0; i < 4; i++ {
-			b, err = buf.ReadByte()
-			if err != nil {
-				return
-			}
-			header = append(header, b)
-			hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
-		}
-	}
-	hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
-	hybiFrame.header.data = bytes.NewBuffer(header)
-	hybiFrame.length = len(header) + int(hybiFrame.header.Length)
-	return
-}
-
-// A HybiFrameWriter is a writer for hybi frame.
-type hybiFrameWriter struct {
-	writer *bufio.Writer
-
-	header *hybiFrameHeader
-}
-
-func (frame *hybiFrameWriter) Write(msg []byte) (n int, err os.Error) {
-	var header []byte
-	var b byte
-	if frame.header.Fin {
-		b |= 0x80
-	}
-	for i := 0; i < 3; i++ {
-		if frame.header.Rsv[i] {
-			j := uint(6 - i)
-			b |= 1 << j
-		}
-	}
-	b |= frame.header.OpCode
-	header = append(header, b)
-	if frame.header.MaskingKey != nil {
-		b = 0x80
-	} else {
-		b = 0
-	}
-	lengthFields := 0
-	length := len(msg)
-	switch {
-	case length <= 125:
-		b |= byte(length)
-	case length < 65536:
-		b |= 126
-		lengthFields = 2
-	default:
-		b |= 127
-		lengthFields = 8
-	}
-	header = append(header, b)
-	for i := 0; i < lengthFields; i++ {
-		j := uint((lengthFields - i - 1) * 8)
-		b = byte((length >> j) & 0xff)
-		header = append(header, b)
-	}
-	if frame.header.MaskingKey != nil {
-		if len(frame.header.MaskingKey) != 4 {
-			return 0, ErrBadMaskingKey
-		}
-		header = append(header, frame.header.MaskingKey...)
-		frame.writer.Write(header)
-		var data []byte
-
-		for i := 0; i < length; i++ {
-			data = append(data, msg[i]^frame.header.MaskingKey[i%4])
-		}
-		frame.writer.Write(data)
-		err = frame.writer.Flush()
-		return length, err
-	}
-	frame.writer.Write(header)
-	frame.writer.Write(msg)
-	err = frame.writer.Flush()
-	return length, err
-}
-
-func (frame *hybiFrameWriter) Close() os.Error { return nil }
-
-type hybiFrameWriterFactory struct {
-	*bufio.Writer
-	needMaskingKey bool
-}
-
-func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err os.Error) {
-	frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
-	if buf.needMaskingKey {
-		frameHeader.MaskingKey, err = generateMaskingKey()
-		if err != nil {
-			return nil, err
-		}
-	}
-	return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
-}
-
-type hybiFrameHandler struct {
-	conn        *Conn
-	payloadType byte
-}
-
-func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err os.Error) {
-	if handler.conn.IsServerConn() {
-		// The client MUST mask all frames sent to the server.
-		if frame.(*hybiFrameReader).header.MaskingKey == nil {
-			handler.WriteClose(closeStatusProtocolError)
-			return nil, os.EOF
-		}
-	}
-	if header := frame.HeaderReader(); header != nil {
-		io.Copy(ioutil.Discard, header)
-	}
-	switch frame.PayloadType() {
-	case ContinuationFrame:
-		frame.(*hybiFrameReader).header.OpCode = handler.payloadType
-	case TextFrame, BinaryFrame:
-		handler.payloadType = frame.PayloadType()
-	case CloseFrame:
-		return nil, os.EOF
-	case PingFrame:
-		pingMsg := make([]byte, maxControlFramePayloadLength)
-		n, err := io.ReadFull(frame, pingMsg)
-		if err != nil && err != io.ErrUnexpectedEOF {
-			return nil, err
-		}
-		io.Copy(ioutil.Discard, frame)
-		n, err = handler.WritePong(pingMsg[:n])
-		if err != nil {
-			return nil, err
-		}
-		return nil, nil
-	case PongFrame:
-		return nil, ErrNotImplemented
-	}
-	return frame, nil
-}
-
-func (handler *hybiFrameHandler) WriteClose(status int) (err os.Error) {
-	w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
-	if err != nil {
-		return err
-	}
-	msg := make([]byte, 2)
-	binary.BigEndian.PutUint16(msg, uint16(status))
-	_, err = w.Write(msg)
-	w.Close()
-	return err
-}
-
-func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err os.Error) {
-	w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
-	if err != nil {
-		return 0, err
-	}
-	n, err = w.Write(msg)
-	w.Close()
-	return n, err
-}
-
-// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
-func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-	if buf == nil {
-		br := bufio.NewReader(rwc)
-		bw := bufio.NewWriter(rwc)
-		buf = bufio.NewReadWriter(br, bw)
-	}
-	ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
-		frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
-		frameWriterFactory: hybiFrameWriterFactory{
-			buf.Writer, request == nil},
-		PayloadType:        TextFrame,
-		defaultCloseStatus: closeStatusNormal}
-	ws.frameHandler = &hybiFrameHandler{conn: ws}
-	return ws
-}
-
-// generateMaskingKey generates a masking key for a frame.
-func generateMaskingKey() (maskingKey []byte, err os.Error) {
-	maskingKey = make([]byte, 4)
-	if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
-		return
-	}
-	return
-}
-
-// genetateNonce geneates a nonce consisting of a randomly selected 16-byte
-// value that has been base64-encoded.
-func generateNonce() (nonce []byte) {
-	key := make([]byte, 16)
-	if _, err := io.ReadFull(rand.Reader, key); err != nil {
-		panic(err)
-	}
-	nonce = make([]byte, 24)
-	base64.StdEncoding.Encode(nonce, key)
-	return
-}
-
-// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
-// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
-func getNonceAccept(nonce []byte) (expected []byte, err os.Error) {
-	h := sha1.New()
-	if _, err = h.Write(nonce); err != nil {
-		return
-	}
-	if _, err = h.Write([]byte(websocketGUID)); err != nil {
-		return
-	}
-	expected = make([]byte, 28)
-	base64.StdEncoding.Encode(expected, h.Sum())
-	return
-}
-
-// Client handhake described in draft-ietf-hybi-thewebsocket-protocol-09
-func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
-	if config.Version != ProtocolVersionHybi {
-		panic("wrong protocol version.")
-	}
-
-	bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")
-
-	bw.WriteString("Host: " + config.Location.Host + "\r\n")
-	bw.WriteString("Upgrade: websocket\r\n")
-	bw.WriteString("Connection: Upgrade\r\n")
-	nonce := generateNonce()
-	if config.handshakeData != nil {
-		nonce = []byte(config.handshakeData["key"])
-	}
-	bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
-	bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
-	bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
-	if len(config.Protocol) > 0 {
-		bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
-	}
-	// TODO(ukai): send extensions.
-	// TODO(ukai): send cookie if any.
-
-	bw.WriteString("\r\n")
-	if err = bw.Flush(); err != nil {
-		return err
-	}
-
-	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
-	if err != nil {
-		return err
-	}
-	if resp.StatusCode != 101 {
-		return ErrBadStatus
-	}
-	if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
-		strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
-		return ErrBadUpgrade
-	}
-	expectedAccept, err := getNonceAccept(nonce)
-	if err != nil {
-		return err
-	}
-	if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
-		return ErrChallengeResponse
-	}
-	if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
-		return ErrUnsupportedExtensions
-	}
-	offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
-	if offeredProtocol != "" {
-		protocolMatched := false
-		for i := 0; i < len(config.Protocol); i++ {
-			if config.Protocol[i] == offeredProtocol {
-				protocolMatched = true
-				break
-			}
-		}
-		if !protocolMatched {
-			return ErrBadWebSocketProtocol
-		}
-		config.Protocol = []string{offeredProtocol}
-	}
-
-	return nil
-}
-
-// newHybiClientConn creates a client WebSocket connection after handshake.
-func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
-	return newHybiConn(config, buf, rwc, nil)
-}
-
-// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
-type hybiServerHandshaker struct {
-	*Config
-	accept []byte
-}
-
-func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err os.Error) {
-	c.Version = ProtocolVersionHybi
-	if req.Method != "GET" {
-		return http.StatusMethodNotAllowed, ErrBadRequestMethod
-	}
-	// HTTP version can be safely ignored.
-
-	if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
-		strings.ToLower(req.Header.Get("Connection")) != "upgrade" {
-		return http.StatusBadRequest, ErrNotWebSocket
-	}
-
-	key := req.Header.Get("Sec-Websocket-Key")
-	if key == "" {
-		return http.StatusBadRequest, ErrChallengeResponse
-	}
-	version := req.Header.Get("Sec-Websocket-Version")
-	if version != fmt.Sprintf("%d", c.Version) {
-		return http.StatusBadRequest, ErrBadWebSocketVersion
-	}
-	c.Origin, err = url.ParseRequest(req.Header.Get("Sec-Websocket-Origin"))
-	if err != nil {
-		return http.StatusBadRequest, err
-	}
-	var scheme string
-	if req.TLS != nil {
-		scheme = "wss"
-	} else {
-		scheme = "ws"
-	}
-	c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RawPath)
-	if err != nil {
-		return http.StatusBadRequest, err
-	}
-	protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
-	protocols := strings.Split(protocol, ",")
-	for i := 0; i < len(protocols); i++ {
-		c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
-	}
-	c.accept, err = getNonceAccept([]byte(key))
-	if err != nil {
-		return http.StatusInternalServerError, err
-	}
-	return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err os.Error) {
-	if len(c.Protocol) > 0 {
-		if len(c.Protocol) != 1 {
-			return ErrBadWebSocketProtocol
-		}
-	}
-	buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
-	buf.WriteString("Upgrade: websocket\r\n")
-	buf.WriteString("Connection: Upgrade\r\n")
-	buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
-	if len(c.Protocol) > 0 {
-		buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
-	}
-	// TODO(ukai): support extensions
-	buf.WriteString("\r\n")
-	return buf.Flush()
-}
-
-func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-	return newHybiServerConn(c.Config, buf, rwc, request)
-}
-
-// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
-func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-	return newHybiConn(config, buf, rwc, request)
-}
diff --git a/src/pkg/websocket/hybi_test.go b/src/pkg/websocket/hybi_test.go
deleted file mode 100644
index c437819..0000000
--- a/src/pkg/websocket/hybi_test.go
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2011 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 websocket
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"http"
-	"os"
-	"strings"
-	"testing"
-	"url"
-)
-
-// Test the getNonceAccept function with values in
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-09
-func TestSecWebSocketAccept(t *testing.T) {
-	nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
-	expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
-	accept, err := getNonceAccept(nonce)
-	if err != nil {
-		t.Errorf("getNonceAccept: returned error %v", err)
-		return
-	}
-	if !bytes.Equal(expected, accept) {
-		t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
-	}
-}
-
-func TestHybiClientHandshake(t *testing.T) {
-	b := bytes.NewBuffer([]byte{})
-	bw := bufio.NewWriter(b)
-	br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-Sec-WebSocket-Protocol: chat
-
-`))
-	var err os.Error
-	config := new(Config)
-	config.Location, err = url.ParseRequest("ws://server.example.com/chat")
-	if err != nil {
-		t.Fatal("location url", err)
-	}
-	config.Origin, err = url.ParseRequest("http://example.com")
-	if err != nil {
-		t.Fatal("origin url", err)
-	}
-	config.Protocol = append(config.Protocol, "chat")
-	config.Protocol = append(config.Protocol, "superchat")
-	config.Version = ProtocolVersionHybi
-
-	config.handshakeData = map[string]string{
-		"key": "dGhlIHNhbXBsZSBub25jZQ==",
-	}
-	err = hybiClientHandshake(config, br, bw)
-	if err != nil {
-		t.Errorf("handshake failed: %v", err)
-	}
-	req, err := http.ReadRequest(bufio.NewReader(b))
-	if err != nil {
-		t.Errorf("read request: %v", err)
-	}
-	if req.Method != "GET" {
-		t.Errorf("request method expected GET, but got %q", req.Method)
-	}
-	if req.RawURL != "/chat" {
-		t.Errorf("request path expected /demo, but got %q", req.RawURL)
-	}
-	if req.Proto != "HTTP/1.1" {
-		t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
-	}
-	if req.Host != "server.example.com" {
-		t.Errorf("request Host expected example.com, but got %v", req.Host)
-	}
-	var expectedHeader = map[string]string{
-		"Connection":             "Upgrade",
-		"Upgrade":                "websocket",
-		"Sec-Websocket-Key":      config.handshakeData["key"],
-		"Sec-Websocket-Origin":   config.Origin.String(),
-		"Sec-Websocket-Protocol": "chat, superchat",
-		"Sec-Websocket-Version":  fmt.Sprintf("%d", ProtocolVersionHybi),
-	}
-	for k, v := range expectedHeader {
-		if req.Header.Get(k) != v {
-			t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
-		}
-	}
-}
-
-func TestHybiServerHandshake(t *testing.T) {
-	config := new(Config)
-	handshaker := &hybiServerHandshaker{Config: config}
-	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 8
-
-`))
-	req, err := http.ReadRequest(br)
-	if err != nil {
-		t.Fatal("request", err)
-	}
-	code, err := handshaker.ReadHandshake(br, req)
-	if err != nil {
-		t.Errorf("handshake failed: %v", err)
-	}
-	if code != http.StatusSwitchingProtocols {
-		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
-	}
-	b := bytes.NewBuffer([]byte{})
-	bw := bufio.NewWriter(b)
-
-	config.Protocol = []string{"chat"}
-
-	err = handshaker.AcceptHandshake(bw)
-	if err != nil {
-		t.Errorf("handshake response failed: %v", err)
-	}
-	expectedResponse := strings.Join([]string{
-		"HTTP/1.1 101 Switching Protocols",
-		"Upgrade: websocket",
-		"Connection: Upgrade",
-		"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
-		"Sec-WebSocket-Protocol: chat",
-		"", ""}, "\r\n")
-
-	if b.String() != expectedResponse {
-		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
-	}
-}
-
-func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
-	b := bytes.NewBuffer([]byte{})
-	frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
-	w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
-	w.(*hybiFrameWriter).header = frameHeader
-	_, err := w.Write(testPayload)
-	w.Close()
-	if err != nil {
-		t.Errorf("Write error %q", err)
-	}
-	var expectedFrame []byte
-	expectedFrame = append(expectedFrame, testHeader...)
-	expectedFrame = append(expectedFrame, testMaskedPayload...)
-	if !bytes.Equal(expectedFrame, b.Bytes()) {
-		t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
-	}
-	frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
-	r, err := frameReaderFactory.NewFrameReader()
-	if err != nil {
-		t.Errorf("Read error %q", err)
-	}
-	if header := r.HeaderReader(); header == nil {
-		t.Errorf("no header")
-	} else {
-		actualHeader := make([]byte, r.Len())
-		n, err := header.Read(actualHeader)
-		if err != nil {
-			t.Errorf("Read header error %q", err)
-		} else {
-			if n < len(testHeader) {
-				t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
-			}
-			if !bytes.Equal(testHeader, actualHeader[:n]) {
-				t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
-			}
-		}
-	}
-	if trailer := r.TrailerReader(); trailer != nil {
-		t.Errorf("unexpected trailer %q", trailer)
-	}
-	frame := r.(*hybiFrameReader)
-	if frameHeader.Fin != frame.header.Fin ||
-		frameHeader.OpCode != frame.header.OpCode ||
-		len(testPayload) != int(frame.header.Length) {
-		t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
-	}
-	payload := make([]byte, len(testPayload))
-	_, err = r.Read(payload)
-	if err != nil {
-		t.Errorf("read %v", err)
-	}
-	if !bytes.Equal(testPayload, payload) {
-		t.Errorf("payload %q vs %q", testPayload, payload)
-	}
-}
-
-func TestHybiShortTextFrame(t *testing.T) {
-	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
-	payload := []byte("hello")
-	testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
-
-	payload = make([]byte, 125)
-	testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
-}
-
-func TestHybiShortMaskedTextFrame(t *testing.T) {
-	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
-		MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
-	payload := []byte("hello")
-	maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
-	header := []byte{0x81, 0x85}
-	header = append(header, frameHeader.MaskingKey...)
-	testHybiFrame(t, header, payload, maskedPayload, frameHeader)
-}
-
-func TestHybiShortBinaryFrame(t *testing.T) {
-	frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
-	payload := []byte("hello")
-	testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
-
-	payload = make([]byte, 125)
-	testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
-}
-
-func TestHybiControlFrame(t *testing.T) {
-	frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
-	payload := []byte("hello")
-	testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
-
-	frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
-	testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
-
-	frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
-	payload = []byte{0x03, 0xe8} // 1000
-	testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
-}
-
-func TestHybiLongFrame(t *testing.T) {
-	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
-	payload := make([]byte, 126)
-	testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
-
-	payload = make([]byte, 65535)
-	testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
-
-	payload = make([]byte, 65536)
-	testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
-}
-
-func TestHybiRead(t *testing.T) {
-	wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
-		0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
-		0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
-	br := bufio.NewReader(bytes.NewBuffer(wireData))
-	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
-	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
-	msg := make([]byte, 512)
-	n, err := conn.Read(msg)
-	if err != nil {
-		t.Errorf("read 1st frame, error %q", err)
-	}
-	if n != 5 {
-		t.Errorf("read 1st frame, expect 5, got %d", n)
-	}
-	if !bytes.Equal(wireData[2:7], msg[:n]) {
-		t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
-	}
-	n, err = conn.Read(msg)
-	if err != nil {
-		t.Errorf("read 2nd frame, error %q", err)
-	}
-	if n != 5 {
-		t.Errorf("read 2nd frame, expect 5, got %d", n)
-	}
-	if !bytes.Equal(wireData[16:21], msg[:n]) {
-		t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
-	}
-	n, err = conn.Read(msg)
-	if err == nil {
-		t.Errorf("read not EOF")
-	}
-	if n != 0 {
-		t.Errorf("expect read 0, got %d", n)
-	}
-}
-
-func TestHybiShortRead(t *testing.T) {
-	wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
-		0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
-		0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
-	br := bufio.NewReader(bytes.NewBuffer(wireData))
-	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
-	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
-	step := 0
-	pos := 0
-	expectedPos := []int{2, 5, 16, 19}
-	expectedLen := []int{3, 2, 3, 2}
-	for {
-		msg := make([]byte, 3)
-		n, err := conn.Read(msg)
-		if step >= len(expectedPos) {
-			if err == nil {
-				t.Errorf("read not EOF")
-			}
-			if n != 0 {
-				t.Errorf("expect read 0, got %d", n)
-			}
-			return
-		}
-		pos = expectedPos[step]
-		endPos := pos + expectedLen[step]
-		if err != nil {
-			t.Errorf("read from %d, got error %q", pos, err)
-			return
-		}
-		if n != endPos-pos {
-			t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
-		}
-		if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
-			t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
-		}
-		step++
-	}
-}
-
-func TestHybiReadWithMasking(t *testing.T) {
-	wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
-		0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
-		0x89, 0x05, 'h', 'e', 'l', 'l', 'o',
-		0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
-		0x9a, 0xec, 0xc6, 0x48, 0x89, // world
-	}
-	br := bufio.NewReader(bytes.NewBuffer(wireData))
-	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
-	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
-	expected := [][]byte{[]byte("hello"), []byte("world")}
-
-	msg := make([]byte, 512)
-	n, err := conn.Read(msg)
-	if err != nil {
-		t.Errorf("read 1st frame, error %q", err)
-	}
-	if n != 5 {
-		t.Errorf("read 1st frame, expect 5, got %d", n)
-	}
-	if !bytes.Equal(expected[0], msg[:n]) {
-		t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
-	}
-
-	n, err = conn.Read(msg)
-	if err != nil {
-		t.Errorf("read 2nd frame, error %q", err)
-	}
-	if n != 5 {
-		t.Errorf("read 2nd frame, expect 5, got %d", n)
-	}
-	if !bytes.Equal(expected[1], msg[:n]) {
-		t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
-	}
-
-	n, err = conn.Read(msg)
-	if err == nil {
-		t.Errorf("read not EOF")
-	}
-	if n != 0 {
-		t.Errorf("expect read 0, got %d", n)
-	}
-}
diff --git a/src/pkg/websocket/server.go b/src/pkg/websocket/server.go
deleted file mode 100644
index 8f6a6a9..0000000
--- a/src/pkg/websocket/server.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
-	"bufio"
-	"fmt"
-	"http"
-	"io"
-	"os"
-)
-
-func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request) (conn *Conn, err os.Error) {
-	config := new(Config)
-	var hs serverHandshaker = &hybiServerHandshaker{Config: config}
-	code, err := hs.ReadHandshake(buf.Reader, req)
-	if err != nil {
-		hs = &hixie76ServerHandshaker{Config: config}
-		code, err = hs.ReadHandshake(buf.Reader, req)
-	}
-	if err != nil {
-		hs = &hixie75ServerHandshaker{Config: config}
-		code, err = hs.ReadHandshake(buf.Reader, req)
-	}
-	if err != nil {
-		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
-		buf.WriteString("\r\n")
-		buf.WriteString(err.String())
-		return
-	}
-	config.Protocol = nil
-
-	err = hs.AcceptHandshake(buf.Writer)
-	if err != nil {
-		return
-	}
-	conn = hs.NewServerConn(buf, rwc, req)
-	return
-}
-
-/*
-Handler is an interface to a WebSocket.
-
-A trivial example server:
-
-	package main
-
-	import (
-		"http"
-		"io"
-		"websocket"
-	)
-
-	// Echo the data received on the WebSocket.
-	func EchoServer(ws *websocket.Conn) {
-		io.Copy(ws, ws);
-	}
-
-	func main() {
-		http.Handle("/echo", websocket.Handler(EchoServer));
-		err := http.ListenAndServe(":12345", nil);
-		if err != nil {
-			panic("ListenAndServe: " + err.String())
-		}
-	}
-*/
-type Handler func(*Conn)
-
-// ServeHTTP implements the http.Handler interface for a Web Socket
-func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
-	rwc, buf, err := w.(http.Hijacker).Hijack()
-	if err != nil {
-		panic("Hijack failed: " + err.String())
-		return
-	}
-	// The server should abort the WebSocket connection if it finds
-	// the client did not send a handshake that matches with protocol
-	// specification.
-	defer rwc.Close()
-	conn, err := newServerConn(rwc, buf, req)
-	if err != nil {
-		return
-	}
-	if conn == nil {
-		panic("unepxected nil conn")
-	}
-	h(conn)
-}
diff --git a/src/pkg/websocket/websocket.go b/src/pkg/websocket/websocket.go
deleted file mode 100644
index d57d114..0000000
--- a/src/pkg/websocket/websocket.go
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package websocket implements a client and server for the WebSocket protocol.
-// The protocol is defined at http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol
-package websocket
-
-import (
-	"bufio"
-	"crypto/tls"
-	"http"
-	"io"
-	"io/ioutil"
-	"json"
-	"net"
-	"os"
-	"url"
-)
-
-const (
-	ProtocolVersionHixie75 = -75
-	ProtocolVersionHixie76 = -76
-	ProtocolVersionHybi00  = 0
-	ProtocolVersionHybi    = 8
-
-	ContinuationFrame = 0
-	TextFrame         = 1
-	BinaryFrame       = 2
-	CloseFrame        = 8
-	PingFrame         = 9
-	PongFrame         = 10
-	UnknownFrame      = 255
-)
-
-// WebSocket protocol errors.
-type ProtocolError struct {
-	ErrorString string
-}
-
-func (err ProtocolError) String() string { return err.ErrorString }
-
-var (
-	ErrBadProtocolVersion   = ProtocolError{"bad protocol version"}
-	ErrBadScheme            = ProtocolError{"bad scheme"}
-	ErrBadStatus            = ProtocolError{"bad status"}
-	ErrBadUpgrade           = ProtocolError{"missing or bad upgrade"}
-	ErrBadWebSocketOrigin   = ProtocolError{"missing or bad WebSocket-Origin"}
-	ErrBadWebSocketLocation = ProtocolError{"missing or bad WebSocket-Location"}
-	ErrBadWebSocketProtocol = ProtocolError{"missing or bad WebSocket-Protocol"}
-	ErrBadWebSocketVersion  = ProtocolError{"missing or bad WebSocket Version"}
-	ErrChallengeResponse    = ProtocolError{"mismatch challenge/response"}
-	ErrBadFrame             = ProtocolError{"bad frame"}
-	ErrBadFrameBoundary     = ProtocolError{"not on frame boundary"}
-	ErrNotWebSocket         = ProtocolError{"not websocket protocol"}
-	ErrBadRequestMethod     = ProtocolError{"bad method"}
-	ErrNotSupported         = ProtocolError{"not supported"}
-)
-
-// Addr is an implementation of net.Addr for WebSocket.
-type Addr struct {
-	*url.URL
-}
-
-// Network returns the network type for a WebSocket, "websocket".
-func (addr *Addr) Network() string { return "websocket" }
-
-// Config is a WebSocket configuration
-type Config struct {
-	// A WebSocket server address.
-	Location *url.URL
-
-	// A Websocket client origin.
-	Origin *url.URL
-
-	// WebSocket subprotocols.
-	Protocol []string
-
-	// WebSocket protocol version.
-	Version int
-
-	// TLS config for secure WebSocket (wss).
-	TlsConfig *tls.Config
-
-	handshakeData map[string]string
-}
-
-// serverHandshaker is an interface to handle WebSocket server side handshake.
-type serverHandshaker interface {
-	// ReadHandshake reads handshake request message from client.
-	// Returns http response code and error if any.
-	ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err os.Error)
-
-	// AcceptHandshake accepts the client handshake request and sends
-	// handshake response back to client.
-	AcceptHandshake(buf *bufio.Writer) (err os.Error)
-
-	// NewServerConn creates a new WebSocket connection.
-	NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
-}
-
-// frameReader is an interface to read a WebSocket frame.
-type frameReader interface {
-	// Reader is to read payload of the frame.
-	io.Reader
-
-	// PayloadType returns payload type.
-	PayloadType() byte
-
-	// HeaderReader returns a reader to read header of the frame.
-	HeaderReader() io.Reader
-
-	// TrailerReader returns a reader to read trailer of the frame.
-	// If it returns nil, there is no trailer in the frame.
-	TrailerReader() io.Reader
-
-	// Len returns total length of the frame, including header and trailer.
-	Len() int
-}
-
-// frameReaderFactory is an interface to creates new frame reader.
-type frameReaderFactory interface {
-	NewFrameReader() (r frameReader, err os.Error)
-}
-
-// frameWriter is an interface to write a WebSocket frame.
-type frameWriter interface {
-	// Writer is to write playload of the frame.
-	io.WriteCloser
-}
-
-// frameWriterFactory is an interface to create new frame writer.
-type frameWriterFactory interface {
-	NewFrameWriter(payloadType byte) (w frameWriter, err os.Error)
-}
-
-type frameHandler interface {
-	HandleFrame(frame frameReader) (r frameReader, err os.Error)
-	WriteClose(status int) (err os.Error)
-}
-
-// Conn represents a WebSocket connection.
-type Conn struct {
-	config  *Config
-	request *http.Request
-
-	buf *bufio.ReadWriter
-	rwc io.ReadWriteCloser
-
-	frameReaderFactory
-	frameReader
-
-	frameWriterFactory
-
-	frameHandler
-	PayloadType        byte
-	defaultCloseStatus int
-}
-
-// Read implements the io.Reader interface:
-// it reads data of a frame from the WebSocket connection.
-// if msg is not large enough for the frame data, it fills the msg and next Read
-// will read the rest of the frame data.
-// it reads Text frame or Binary frame.
-func (ws *Conn) Read(msg []byte) (n int, err os.Error) {
-again:
-	if ws.frameReader == nil {
-		frame, err := ws.frameReaderFactory.NewFrameReader()
-		if err != nil {
-			return 0, err
-		}
-		ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
-		if err != nil {
-			return 0, err
-		}
-		if ws.frameReader == nil {
-			goto again
-		}
-	}
-	n, err = ws.frameReader.Read(msg)
-	if err == os.EOF {
-		if trailer := ws.frameReader.TrailerReader(); trailer != nil {
-			io.Copy(ioutil.Discard, trailer)
-		}
-		ws.frameReader = nil
-		goto again
-	}
-	return n, err
-}
-
-// Write implements the io.Writer interface:
-// it writes data as a frame to the WebSocket connection.
-func (ws *Conn) Write(msg []byte) (n int, err os.Error) {
-	w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
-	if err != nil {
-		return 0, err
-	}
-	n, err = w.Write(msg)
-	w.Close()
-	if err != nil {
-		return n, err
-	}
-	return n, err
-}
-
-// Close implements the io.Closer interface.
-func (ws *Conn) Close() os.Error {
-	err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
-	if err != nil {
-		return err
-	}
-	return ws.rwc.Close()
-}
-
-func (ws *Conn) IsClientConn() bool { return ws.request == nil }
-func (ws *Conn) IsServerConn() bool { return ws.request != nil }
-
-// LocalAddr returns the WebSocket Origin for the connection for client, or
-// the WebSocket location for server.
-func (ws *Conn) LocalAddr() net.Addr {
-	if ws.IsClientConn() {
-		return &Addr{ws.config.Origin}
-	}
-	return &Addr{ws.config.Location}
-}
-
-// RemoteAddr returns the WebSocket location for the connection for client, or
-// the Websocket Origin for server.
-func (ws *Conn) RemoteAddr() net.Addr {
-	if ws.IsClientConn() {
-		return &Addr{ws.config.Location}
-	}
-	return &Addr{ws.config.Origin}
-}
-
-// SetTimeout sets the connection's network timeout in nanoseconds.
-func (ws *Conn) SetTimeout(nsec int64) os.Error {
-	if conn, ok := ws.rwc.(net.Conn); ok {
-		return conn.SetTimeout(nsec)
-	}
-	return os.EINVAL
-}
-
-// SetReadTimeout sets the connection's network read timeout in nanoseconds.
-func (ws *Conn) SetReadTimeout(nsec int64) os.Error {
-	if conn, ok := ws.rwc.(net.Conn); ok {
-		return conn.SetReadTimeout(nsec)
-	}
-	return os.EINVAL
-}
-
-// SetWriteTimeout sets the connection's network write timeout in nanoseconds.
-func (ws *Conn) SetWriteTimeout(nsec int64) os.Error {
-	if conn, ok := ws.rwc.(net.Conn); ok {
-		return conn.SetWriteTimeout(nsec)
-	}
-	return os.EINVAL
-}
-
-// Config returns the WebSocket config.
-func (ws *Conn) Config() *Config { return ws.config }
-
-// Request returns the http request upgraded to the WebSocket.
-// It is nil for client side.
-func (ws *Conn) Request() *http.Request { return ws.request }
-
-// Codec represents a symmetric pair of functions that implement a codec.
-type Codec struct {
-	Marshal   func(v interface{}) (data []byte, payloadType byte, err os.Error)
-	Unmarshal func(data []byte, payloadType byte, v interface{}) (err os.Error)
-}
-
-// Send sends v marshaled by cd.Marshal as single frame to ws.
-func (cd Codec) Send(ws *Conn, v interface{}) (err os.Error) {
-	if err != nil {
-		return err
-	}
-	data, payloadType, err := cd.Marshal(v)
-	if err != nil {
-		return err
-	}
-	w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
-	_, err = w.Write(data)
-	w.Close()
-	return err
-}
-
-// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
-func (cd Codec) Receive(ws *Conn, v interface{}) (err os.Error) {
-	if ws.frameReader != nil {
-		_, err = io.Copy(ioutil.Discard, ws.frameReader)
-		if err != nil {
-			return err
-		}
-		ws.frameReader = nil
-	}
-again:
-	frame, err := ws.frameReaderFactory.NewFrameReader()
-	if err != nil {
-		return err
-	}
-	frame, err = ws.frameHandler.HandleFrame(frame)
-	if err != nil {
-		return err
-	}
-	if frame == nil {
-		goto again
-	}
-	payloadType := frame.PayloadType()
-	data, err := ioutil.ReadAll(frame)
-	if err != nil {
-		return err
-	}
-	return cd.Unmarshal(data, payloadType, v)
-}
-
-func marshal(v interface{}) (msg []byte, payloadType byte, err os.Error) {
-	switch data := v.(type) {
-	case string:
-		return []byte(data), TextFrame, nil
-	case []byte:
-		return data, BinaryFrame, nil
-	}
-	return nil, UnknownFrame, ErrNotSupported
-}
-
-func unmarshal(msg []byte, payloadType byte, v interface{}) (err os.Error) {
-	switch data := v.(type) {
-	case *string:
-		*data = string(msg)
-		return nil
-	case *[]byte:
-		*data = msg
-		return nil
-	}
-	return ErrNotSupported
-}
-
-/*
-Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
-To send/receive text frame, use string type.
-To send/receive binary frame, use []byte type.
-
-Trivial usage:
-
-	import "websocket"
-
-	// receive text frame
-	var message string
-	websocket.Message.Receive(ws, &message)
-
-	// send text frame
-	message = "hello"
-	websocket.Message.Send(ws, message)
-
-	// receive binary frame
-	var data []byte
-	websocket.Message.Receive(ws, &data)
-
-	// send binary frame
-	data = []byte{0, 1, 2}
-	websocket.Message.Send(ws, data)
-
-*/
-var Message = Codec{marshal, unmarshal}
-
-func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err os.Error) {
-	msg, err = json.Marshal(v)
-	return msg, TextFrame, err
-}
-
-func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err os.Error) {
-	return json.Unmarshal(msg, v)
-}
-
-/*
-JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
-
-Trival usage:
-
-	import "websocket"
-
-	type T struct {
-		Msg string
-		Count int
-	}
-
-	// receive JSON type T
-	var data T
-	websocket.JSON.Receive(ws, &data)
-
-	// send JSON type T
-	websocket.JSON.Send(ws, data)
-*/
-var JSON = Codec{jsonMarshal, jsonUnmarshal}
diff --git a/src/pkg/websocket/websocket_test.go b/src/pkg/websocket/websocket_test.go
deleted file mode 100644
index d2834cd..0000000
--- a/src/pkg/websocket/websocket_test.go
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package websocket
-
-import (
-	"bytes"
-	"fmt"
-	"http"
-	"http/httptest"
-	"io"
-	"log"
-	"net"
-	"strings"
-	"sync"
-	"testing"
-	"url"
-)
-
-var serverAddr string
-var once sync.Once
-
-func echoServer(ws *Conn) { io.Copy(ws, ws) }
-
-type Count struct {
-	S string
-	N int
-}
-
-func countServer(ws *Conn) {
-	for {
-		var count Count
-		err := JSON.Receive(ws, &count)
-		if err != nil {
-			return
-		}
-		count.N++
-		count.S = strings.Repeat(count.S, count.N)
-		err = JSON.Send(ws, count)
-		if err != nil {
-			return
-		}
-	}
-}
-
-func startServer() {
-	http.Handle("/echo", Handler(echoServer))
-	http.Handle("/count", Handler(countServer))
-	server := httptest.NewServer(nil)
-	serverAddr = server.Listener.Addr().String()
-	log.Print("Test WebSocket server listening on ", serverAddr)
-}
-
-func newConfig(t *testing.T, path string) *Config {
-	config, _ := NewConfig(fmt.Sprintf("ws://%s%s", serverAddr, path), "http://localhost")
-	return config
-}
-
-func TestEcho(t *testing.T) {
-	once.Do(startServer)
-
-	// websocket.Dial()
-	client, err := net.Dial("tcp", serverAddr)
-	if err != nil {
-		t.Fatal("dialing", err)
-	}
-	conn, err := NewClient(newConfig(t, "/echo"), client)
-	if err != nil {
-		t.Errorf("WebSocket handshake error: %v", err)
-		return
-	}
-
-	msg := []byte("hello, world\n")
-	if _, err := conn.Write(msg); err != nil {
-		t.Errorf("Write: %v", err)
-	}
-	var actual_msg = make([]byte, 512)
-	n, err := conn.Read(actual_msg)
-	if err != nil {
-		t.Errorf("Read: %v", err)
-	}
-	actual_msg = actual_msg[0:n]
-	if !bytes.Equal(msg, actual_msg) {
-		t.Errorf("Echo: expected %q got %q", msg, actual_msg)
-	}
-	conn.Close()
-}
-
-func TestAddr(t *testing.T) {
-	once.Do(startServer)
-
-	// websocket.Dial()
-	client, err := net.Dial("tcp", serverAddr)
-	if err != nil {
-		t.Fatal("dialing", err)
-	}
-	conn, err := NewClient(newConfig(t, "/echo"), client)
-	if err != nil {
-		t.Errorf("WebSocket handshake error: %v", err)
-		return
-	}
-
-	ra := conn.RemoteAddr().String()
-	if !strings.HasPrefix(ra, "ws://") || !strings.HasSuffix(ra, "/echo") {
-		t.Errorf("Bad remote addr: %v", ra)
-	}
-	la := conn.LocalAddr().String()
-	if !strings.HasPrefix(la, "http://") {
-		t.Errorf("Bad local addr: %v", la)
-	}
-	conn.Close()
-}
-
-func TestCount(t *testing.T) {
-	once.Do(startServer)
-
-	// websocket.Dial()
-	client, err := net.Dial("tcp", serverAddr)
-	if err != nil {
-		t.Fatal("dialing", err)
-	}
-	conn, err := NewClient(newConfig(t, "/count"), client)
-	if err != nil {
-		t.Errorf("WebSocket handshake error: %v", err)
-		return
-	}
-
-	var count Count
-	count.S = "hello"
-	if err := JSON.Send(conn, count); err != nil {
-		t.Errorf("Write: %v", err)
-	}
-	if err := JSON.Receive(conn, &count); err != nil {
-		t.Errorf("Read: %v", err)
-	}
-	if count.N != 1 {
-		t.Errorf("count: expected %d got %d", 1, count.N)
-	}
-	if count.S != "hello" {
-		t.Errorf("count: expected %q got %q", "hello", count.S)
-	}
-	if err := JSON.Send(conn, count); err != nil {
-		t.Errorf("Write: %v", err)
-	}
-	if err := JSON.Receive(conn, &count); err != nil {
-		t.Errorf("Read: %v", err)
-	}
-	if count.N != 2 {
-		t.Errorf("count: expected %d got %d", 2, count.N)
-	}
-	if count.S != "hellohello" {
-		t.Errorf("count: expected %q got %q", "hellohello", count.S)
-	}
-	conn.Close()
-}
-
-func TestWithQuery(t *testing.T) {
-	once.Do(startServer)
-
-	client, err := net.Dial("tcp", serverAddr)
-	if err != nil {
-		t.Fatal("dialing", err)
-	}
-
-	config := newConfig(t, "/echo")
-	config.Location, err = url.ParseRequest(fmt.Sprintf("ws://%s/echo?q=v", serverAddr))
-	if err != nil {
-		t.Fatal("location url", err)
-	}
-
-	ws, err := NewClient(config, client)
-	if err != nil {
-		t.Errorf("WebSocket handshake: %v", err)
-		return
-	}
-	ws.Close()
-}
-
-func TestWithProtocol(t *testing.T) {
-	once.Do(startServer)
-
-	client, err := net.Dial("tcp", serverAddr)
-	if err != nil {
-		t.Fatal("dialing", err)
-	}
-
-	config := newConfig(t, "/echo")
-	config.Protocol = append(config.Protocol, "test")
-
-	ws, err := NewClient(config, client)
-	if err != nil {
-		t.Errorf("WebSocket handshake: %v", err)
-		return
-	}
-	ws.Close()
-}
-
-func TestHTTP(t *testing.T) {
-	once.Do(startServer)
-
-	// If the client did not send a handshake that matches the protocol
-	// specification, the server should abort the WebSocket connection.
-	_, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
-	if err == nil {
-		t.Error("Get: unexpected success")
-		return
-	}
-	urlerr, ok := err.(*url.Error)
-	if !ok {
-		t.Errorf("Get: not url.Error %#v", err)
-		return
-	}
-	if urlerr.Error != io.ErrUnexpectedEOF {
-		t.Errorf("Get: error %#v", err)
-		return
-	}
-}
-
-func TestTrailingSpaces(t *testing.T) {
-	// http://code.google.com/p/go/issues/detail?id=955
-	// The last runs of this create keys with trailing spaces that should not be
-	// generated by the client.
-	once.Do(startServer)
-	config := newConfig(t, "/echo")
-	for i := 0; i < 30; i++ {
-		// body
-		ws, err := DialConfig(config)
-		if err != nil {
-			t.Error("Dial failed:", err.String())
-			break
-		}
-		ws.Close()
-	}
-}
-
-func TestSmallBuffer(t *testing.T) {
-	// http://code.google.com/p/go/issues/detail?id=1145
-	// Read should be able to handle reading a fragment of a frame.
-	once.Do(startServer)
-
-	// websocket.Dial()
-	client, err := net.Dial("tcp", serverAddr)
-	if err != nil {
-		t.Fatal("dialing", err)
-	}
-	conn, err := NewClient(newConfig(t, "/echo"), client)
-	if err != nil {
-		t.Errorf("WebSocket handshake error: %v", err)
-		return
-	}
-
-	msg := []byte("hello, world\n")
-	if _, err := conn.Write(msg); err != nil {
-		t.Errorf("Write: %v", err)
-	}
-	var small_msg = make([]byte, 8)
-	n, err := conn.Read(small_msg)
-	if err != nil {
-		t.Errorf("Read: %v", err)
-	}
-	if !bytes.Equal(msg[:len(small_msg)], small_msg) {
-		t.Errorf("Echo: expected %q got %q", msg[:len(small_msg)], small_msg)
-	}
-	var second_msg = make([]byte, len(msg))
-	n, err = conn.Read(second_msg)
-	if err != nil {
-		t.Errorf("Read: %v", err)
-	}
-	second_msg = second_msg[0:n]
-	if !bytes.Equal(msg[len(small_msg):], second_msg) {
-		t.Errorf("Echo: expected %q got %q", msg[len(small_msg):], second_msg)
-	}
-	conn.Close()
-}
diff --git a/src/pkg/xml/Makefile b/src/pkg/xml/Makefile
deleted file mode 100644
index d66c498..0000000
--- a/src/pkg/xml/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2009 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.inc
-
-TARG=xml
-
-GOFILES=\
-	marshal.go\
-	read.go\
-	xml.go\
-
-include ../../Make.pkg
diff --git a/src/pkg/xml/atom_test.go b/src/pkg/xml/atom_test.go
deleted file mode 100644
index d365510..0000000
--- a/src/pkg/xml/atom_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2011 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 xml
-
-var atomValue = &Feed{
-	Title:   "Example Feed",
-	Link:    []Link{{Href: "http://example.org/"}},
-	Updated: ParseTime("2003-12-13T18:30:02Z"),
-	Author:  Person{Name: "John Doe"},
-	Id:      "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6",
-
-	Entry: []Entry{
-		{
-			Title:   "Atom-Powered Robots Run Amok",
-			Link:    []Link{{Href: "http://example.org/2003/12/13/atom03"}},
-			Id:      "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
-			Updated: ParseTime("2003-12-13T18:30:02Z"),
-			Summary: NewText("Some text."),
-		},
-	},
-}
-
-var atomXml = `` +
-	`<feed xmlns="http://www.w3.org/2005/Atom">` +
-	`<Title>Example Feed</Title>` +
-	`<Id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</Id>` +
-	`<Link href="http://example.org/"></Link>` +
-	`<Updated>2003-12-13T18:30:02Z</Updated>` +
-	`<Author><Name>John Doe</Name><URI></URI><Email></Email></Author>` +
-	`<Entry>` +
-	`<Title>Atom-Powered Robots Run Amok</Title>` +
-	`<Id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</Id>` +
-	`<Link href="http://example.org/2003/12/13/atom03"></Link>` +
-	`<Updated>2003-12-13T18:30:02Z</Updated>` +
-	`<Author><Name></Name><URI></URI><Email></Email></Author>` +
-	`<Summary>Some text.</Summary>` +
-	`</Entry>` +
-	`</feed>`
-
-func ParseTime(str string) Time {
-	return Time(str)
-}
-
-func NewText(text string) Text {
-	return Text{
-		Body: text,
-	}
-}
diff --git a/src/pkg/xml/embed_test.go b/src/pkg/xml/embed_test.go
deleted file mode 100644
index ec7f478..0000000
--- a/src/pkg/xml/embed_test.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2010 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 xml
-
-import "testing"
-
-type C struct {
-	Name string
-	Open bool
-}
-
-type A struct {
-	XMLName Name `xml:"http://domain a"`
-	C
-	B      B
-	FieldA string
-}
-
-type B struct {
-	XMLName Name `xml:"b"`
-	C
-	FieldB string
-}
-
-const _1a = `
-<?xml version="1.0" encoding="UTF-8"?>
-<a xmlns="http://domain">
-  <name>KmlFile</name>
-  <open>1</open>
-  <b>
-    <name>Absolute</name>
-    <open>0</open>
-    <fieldb>bar</fieldb>
-  </b>
-  <fielda>foo</fielda>
-</a>
-`
-
-// Tests that embedded structs are marshalled.
-func TestEmbedded1(t *testing.T) {
-	var a A
-	if e := Unmarshal(StringReader(_1a), &a); e != nil {
-		t.Fatalf("Unmarshal: %s", e)
-	}
-	if a.FieldA != "foo" {
-		t.Fatalf("Unmarshal: expected 'foo' but found '%s'", a.FieldA)
-	}
-	if a.Name != "KmlFile" {
-		t.Fatalf("Unmarshal: expected 'KmlFile' but found '%s'", a.Name)
-	}
-	if !a.Open {
-		t.Fatal("Unmarshal: expected 'true' but found otherwise")
-	}
-	if a.B.FieldB != "bar" {
-		t.Fatalf("Unmarshal: expected 'bar' but found '%s'", a.B.FieldB)
-	}
-	if a.B.Name != "Absolute" {
-		t.Fatalf("Unmarshal: expected 'Absolute' but found '%s'", a.B.Name)
-	}
-	if a.B.Open {
-		t.Fatal("Unmarshal: expected 'false' but found otherwise")
-	}
-}
-
-type A2 struct {
-	XMLName Name `xml:"http://domain a"`
-	XY      string
-	Xy      string
-}
-
-const _2a = `
-<?xml version="1.0" encoding="UTF-8"?>
-<a xmlns="http://domain">
-  <xy>foo</xy>
-</a>
-`
-
-// Tests that conflicting field names get excluded.
-func TestEmbedded2(t *testing.T) {
-	var a A2
-	if e := Unmarshal(StringReader(_2a), &a); e != nil {
-		t.Fatalf("Unmarshal: %s", e)
-	}
-	if a.XY != "" {
-		t.Fatalf("Unmarshal: expected empty string but found '%s'", a.XY)
-	}
-	if a.Xy != "" {
-		t.Fatalf("Unmarshal: expected empty string but found '%s'", a.Xy)
-	}
-}
-
-type A3 struct {
-	XMLName Name `xml:"http://domain a"`
-	xy      string
-}
-
-// Tests that private fields are not set.
-func TestEmbedded3(t *testing.T) {
-	var a A3
-	if e := Unmarshal(StringReader(_2a), &a); e != nil {
-		t.Fatalf("Unmarshal: %s", e)
-	}
-	if a.xy != "" {
-		t.Fatalf("Unmarshal: expected empty string but found '%s'", a.xy)
-	}
-}
-
-type A4 struct {
-	XMLName Name `xml:"http://domain a"`
-	Any     string
-}
-
-// Tests that private fields are not set.
-func TestEmbedded4(t *testing.T) {
-	var a A4
-	if e := Unmarshal(StringReader(_2a), &a); e != nil {
-		t.Fatalf("Unmarshal: %s", e)
-	}
-	if a.Any != "foo" {
-		t.Fatalf("Unmarshal: expected 'foo' but found '%s'", a.Any)
-	}
-}
diff --git a/src/pkg/xml/marshal.go b/src/pkg/xml/marshal.go
deleted file mode 100644
index 8396dba..0000000
--- a/src/pkg/xml/marshal.go
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright 2011 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 xml
-
-import (
-	"bufio"
-	"io"
-	"os"
-	"reflect"
-	"strconv"
-	"strings"
-)
-
-const (
-	// A generic XML header suitable for use with the output of Marshal and
-	// MarshalIndent.  This is not automatically added to any output of this
-	// package, it is provided as a convenience.
-	Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
-)
-
-// A Marshaler can produce well-formatted XML representing its internal state.
-// It is used by both Marshal and MarshalIndent.
-type Marshaler interface {
-	MarshalXML() ([]byte, os.Error)
-}
-
-type printer struct {
-	*bufio.Writer
-}
-
-// Marshal writes an XML-formatted representation of v to w.
-//
-// If v implements Marshaler, then Marshal calls its MarshalXML method.
-// Otherwise, Marshal uses the following procedure to create the XML.
-//
-// Marshal handles an array or slice by marshalling each of the elements.
-// Marshal handles a pointer by marshalling the value it points at or, if the
-// pointer is nil, by writing nothing.  Marshal handles an interface value by
-// marshalling the value it contains or, if the interface value is nil, by
-// writing nothing.  Marshal handles all other data by writing one or more XML
-// elements containing the data.
-//
-// The name for the XML elements is taken from, in order of preference:
-//     - the tag on an XMLName field, if the data is a struct
-//     - the value of an XMLName field of type xml.Name
-//     - the tag of the struct field used to obtain the data
-//     - the name of the struct field used to obtain the data
-//     - the name '???'.
-//
-// The XML element for a struct contains marshalled elements for each of the
-// exported fields of the struct, with these exceptions:
-//     - the XMLName field, described above, is omitted.
-//     - a field with tag "attr" becomes an attribute in the XML element.
-//     - a field with tag "chardata" is written as character data,
-//        not as an XML element.
-//     - a field with tag "innerxml" is written verbatim,
-//        not subject to the usual marshalling procedure.
-//
-// If a field uses a tag "a>b>c", then the element c will be nested inside
-// parent elements a and b.  Fields that appear next to each other that name
-// the same parent will be enclosed in one XML element.  For example:
-//
-//	type Result struct {
-//		XMLName   xml.Name `xml:"result"`
-//		FirstName string   `xml:"person>name>first"`
-//		LastName  string   `xml:"person>name>last"`
-//		Age       int      `xml:"person>age"`
-//	}
-//
-//	xml.Marshal(w, &Result{FirstName: "John", LastName: "Doe", Age: 42})
-//
-// would be marshalled as:
-//
-//	<result>
-//		<person>
-//			<name>
-//				<first>John</first>
-//				<last>Doe</last>
-//			</name>
-//			<age>42</age>
-//		</person>
-//	</result>
-//
-// Marshal will return an error if asked to marshal a channel, function, or map.
-func Marshal(w io.Writer, v interface{}) (err os.Error) {
-	p := &printer{bufio.NewWriter(w)}
-	err = p.marshalValue(reflect.ValueOf(v), "???")
-	p.Flush()
-	return err
-}
-
-func (p *printer) marshalValue(val reflect.Value, name string) os.Error {
-	if !val.IsValid() {
-		return nil
-	}
-
-	kind := val.Kind()
-	typ := val.Type()
-
-	// Try Marshaler
-	if typ.NumMethod() > 0 {
-		if marshaler, ok := val.Interface().(Marshaler); ok {
-			bytes, err := marshaler.MarshalXML()
-			if err != nil {
-				return err
-			}
-			p.Write(bytes)
-			return nil
-		}
-	}
-
-	// Drill into pointers/interfaces
-	if kind == reflect.Ptr || kind == reflect.Interface {
-		if val.IsNil() {
-			return nil
-		}
-		return p.marshalValue(val.Elem(), name)
-	}
-
-	// Slices and arrays iterate over the elements. They do not have an enclosing tag.
-	if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
-		for i, n := 0, val.Len(); i < n; i++ {
-			if err := p.marshalValue(val.Index(i), name); err != nil {
-				return err
-			}
-		}
-		return nil
-	}
-
-	// Find XML name
-	xmlns := ""
-	if kind == reflect.Struct {
-		if f, ok := typ.FieldByName("XMLName"); ok {
-			if tag := f.Tag.Get("xml"); tag != "" {
-				if i := strings.Index(tag, " "); i >= 0 {
-					xmlns, name = tag[:i], tag[i+1:]
-				} else {
-					name = tag
-				}
-			} else if v, ok := val.FieldByIndex(f.Index).Interface().(Name); ok && v.Local != "" {
-				xmlns, name = v.Space, v.Local
-			}
-		}
-	}
-
-	p.WriteByte('<')
-	p.WriteString(name)
-
-	// Attributes
-	if kind == reflect.Struct {
-		if len(xmlns) > 0 {
-			p.WriteString(` xmlns="`)
-			Escape(p, []byte(xmlns))
-			p.WriteByte('"')
-		}
-
-		for i, n := 0, typ.NumField(); i < n; i++ {
-			if f := typ.Field(i); f.PkgPath == "" && f.Tag.Get("xml") == "attr" {
-				if f.Type.Kind() == reflect.String {
-					if str := val.Field(i).String(); str != "" {
-						p.WriteByte(' ')
-						p.WriteString(strings.ToLower(f.Name))
-						p.WriteString(`="`)
-						Escape(p, []byte(str))
-						p.WriteByte('"')
-					}
-				}
-			}
-		}
-	}
-	p.WriteByte('>')
-
-	switch k := val.Kind(); k {
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		p.WriteString(strconv.Itoa64(val.Int()))
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		p.WriteString(strconv.Uitoa64(val.Uint()))
-	case reflect.Float32, reflect.Float64:
-		p.WriteString(strconv.Ftoa64(val.Float(), 'g', -1))
-	case reflect.String:
-		Escape(p, []byte(val.String()))
-	case reflect.Bool:
-		p.WriteString(strconv.Btoa(val.Bool()))
-	case reflect.Array:
-		// will be [...]byte
-		bytes := make([]byte, val.Len())
-		for i := range bytes {
-			bytes[i] = val.Index(i).Interface().(byte)
-		}
-		Escape(p, bytes)
-	case reflect.Slice:
-		// will be []byte
-		bytes := val.Interface().([]byte)
-		Escape(p, bytes)
-	case reflect.Struct:
-		s := parentStack{printer: p}
-		for i, n := 0, val.NumField(); i < n; i++ {
-			if f := typ.Field(i); f.Name != "XMLName" && f.PkgPath == "" {
-				name := f.Name
-				vf := val.Field(i)
-				switch tag := f.Tag.Get("xml"); tag {
-				case "":
-					s.trim(nil)
-				case "chardata":
-					if tk := f.Type.Kind(); tk == reflect.String {
-						Escape(p, []byte(vf.String()))
-					} else if tk == reflect.Slice {
-						if elem, ok := vf.Interface().([]byte); ok {
-							Escape(p, elem)
-						}
-					}
-					continue
-				case "innerxml":
-					iface := vf.Interface()
-					switch raw := iface.(type) {
-					case []byte:
-						p.Write(raw)
-						continue
-					case string:
-						p.WriteString(raw)
-						continue
-					}
-				case "attr":
-					continue
-				default:
-					parents := strings.Split(tag, ">")
-					if len(parents) == 1 {
-						parents, name = nil, tag
-					} else {
-						parents, name = parents[:len(parents)-1], parents[len(parents)-1]
-						if parents[0] == "" {
-							parents[0] = f.Name
-						}
-					}
-
-					s.trim(parents)
-					if !(vf.Kind() == reflect.Ptr || vf.Kind() == reflect.Interface) || !vf.IsNil() {
-						s.push(parents[len(s.stack):])
-					}
-				}
-
-				if err := p.marshalValue(vf, name); err != nil {
-					return err
-				}
-			}
-		}
-		s.trim(nil)
-	default:
-		return &UnsupportedTypeError{typ}
-	}
-
-	p.WriteByte('<')
-	p.WriteByte('/')
-	p.WriteString(name)
-	p.WriteByte('>')
-
-	return nil
-}
-
-type parentStack struct {
-	*printer
-	stack []string
-}
-
-// trim updates the XML context to match the longest common prefix of the stack
-// and the given parents.  A closing tag will be written for every parent
-// popped.  Passing a zero slice or nil will close all the elements.
-func (s *parentStack) trim(parents []string) {
-	split := 0
-	for ; split < len(parents) && split < len(s.stack); split++ {
-		if parents[split] != s.stack[split] {
-			break
-		}
-	}
-
-	for i := len(s.stack) - 1; i >= split; i-- {
-		s.WriteString("</")
-		s.WriteString(s.stack[i])
-		s.WriteByte('>')
-	}
-
-	s.stack = parents[:split]
-}
-
-// push adds parent elements to the stack and writes open tags.
-func (s *parentStack) push(parents []string) {
-	for i := 0; i < len(parents); i++ {
-		s.WriteString("<")
-		s.WriteString(parents[i])
-		s.WriteByte('>')
-	}
-	s.stack = append(s.stack, parents...)
-}
-
-// A MarshalXMLError is returned when Marshal or MarshalIndent encounter a type
-// that cannot be converted into XML.
-type UnsupportedTypeError struct {
-	Type reflect.Type
-}
-
-func (e *UnsupportedTypeError) String() string {
-	return "xml: unsupported type: " + e.Type.String()
-}
diff --git a/src/pkg/xml/marshal_test.go b/src/pkg/xml/marshal_test.go
deleted file mode 100644
index ad3aa97..0000000
--- a/src/pkg/xml/marshal_test.go
+++ /dev/null
@@ -1,428 +0,0 @@
-// Copyright 2011 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 xml
-
-import (
-	"reflect"
-	"testing"
-
-	"os"
-	"bytes"
-	"strings"
-	"strconv"
-)
-
-type DriveType int
-
-const (
-	HyperDrive DriveType = iota
-	ImprobabilityDrive
-)
-
-type Passenger struct {
-	Name   []string `xml:"name"`
-	Weight float32  `xml:"weight"`
-}
-
-type Ship struct {
-	XMLName Name `xml:"spaceship"`
-
-	Name      string       `xml:"attr"`
-	Pilot     string       `xml:"attr"`
-	Drive     DriveType    `xml:"drive"`
-	Age       uint         `xml:"age"`
-	Passenger []*Passenger `xml:"passenger"`
-	secret    string
-}
-
-type RawXML string
-
-func (rx RawXML) MarshalXML() ([]byte, os.Error) {
-	return []byte(rx), nil
-}
-
-type NamedType string
-
-type Port struct {
-	XMLName Name   `xml:"port"`
-	Type    string `xml:"attr"`
-	Number  string `xml:"chardata"`
-}
-
-type Domain struct {
-	XMLName Name   `xml:"domain"`
-	Country string `xml:"attr"`
-	Name    []byte `xml:"chardata"`
-}
-
-type Book struct {
-	XMLName Name   `xml:"book"`
-	Title   string `xml:"chardata"`
-}
-
-type SecretAgent struct {
-	XMLName   Name   `xml:"agent"`
-	Handle    string `xml:"attr"`
-	Identity  string
-	Obfuscate string `xml:"innerxml"`
-}
-
-type NestedItems struct {
-	XMLName Name     `xml:"result"`
-	Items   []string `xml:">item"`
-	Item1   []string `xml:"Items>item1"`
-}
-
-type NestedOrder struct {
-	XMLName Name   `xml:"result"`
-	Field1  string `xml:"parent>c"`
-	Field2  string `xml:"parent>b"`
-	Field3  string `xml:"parent>a"`
-}
-
-type MixedNested struct {
-	XMLName Name   `xml:"result"`
-	A       string `xml:"parent1>a"`
-	B       string `xml:"b"`
-	C       string `xml:"parent1>parent2>c"`
-	D       string `xml:"parent1>d"`
-}
-
-type NilTest struct {
-	A interface{} `xml:"parent1>parent2>a"`
-	B interface{} `xml:"parent1>b"`
-	C interface{} `xml:"parent1>parent2>c"`
-}
-
-type Service struct {
-	XMLName Name    `xml:"service"`
-	Domain  *Domain `xml:"host>domain"`
-	Port    *Port   `xml:"host>port"`
-	Extra1  interface{}
-	Extra2  interface{} `xml:"host>extra2"`
-}
-
-var nilStruct *Ship
-
-var marshalTests = []struct {
-	Value     interface{}
-	ExpectXML string
-}{
-	// Test nil marshals to nothing
-	{Value: nil, ExpectXML: ``},
-	{Value: nilStruct, ExpectXML: ``},
-
-	// Test value types (no tag name, so ???)
-	{Value: true, ExpectXML: `<???>true</???>`},
-	{Value: int(42), ExpectXML: `<???>42</???>`},
-	{Value: int8(42), ExpectXML: `<???>42</???>`},
-	{Value: int16(42), ExpectXML: `<???>42</???>`},
-	{Value: int32(42), ExpectXML: `<???>42</???>`},
-	{Value: uint(42), ExpectXML: `<???>42</???>`},
-	{Value: uint8(42), ExpectXML: `<???>42</???>`},
-	{Value: uint16(42), ExpectXML: `<???>42</???>`},
-	{Value: uint32(42), ExpectXML: `<???>42</???>`},
-	{Value: float32(1.25), ExpectXML: `<???>1.25</???>`},
-	{Value: float64(1.25), ExpectXML: `<???>1.25</???>`},
-	{Value: uintptr(0xFFDD), ExpectXML: `<???>65501</???>`},
-	{Value: "gopher", ExpectXML: `<???>gopher</???>`},
-	{Value: []byte("gopher"), ExpectXML: `<???>gopher</???>`},
-	{Value: "</>", ExpectXML: `<???></></???>`},
-	{Value: []byte("</>"), ExpectXML: `<???></></???>`},
-	{Value: [3]byte{'<', '/', '>'}, ExpectXML: `<???></></???>`},
-	{Value: NamedType("potato"), ExpectXML: `<???>potato</???>`},
-	{Value: []int{1, 2, 3}, ExpectXML: `<???>1</???><???>2</???><???>3</???>`},
-	{Value: [3]int{1, 2, 3}, ExpectXML: `<???>1</???><???>2</???><???>3</???>`},
-
-	// Test innerxml
-	{Value: RawXML("</>"), ExpectXML: `</>`},
-	{
-		Value: &SecretAgent{
-			Handle:    "007",
-			Identity:  "James Bond",
-			Obfuscate: "<redacted/>",
-		},
-		//ExpectXML: `<agent handle="007"><redacted/></agent>`,
-		ExpectXML: `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
-	},
-
-	// Test structs
-	{Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
-	{Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
-	{Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="<unix>"></port>`},
-	{Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&friends</domain>`},
-	{Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride & Prejudice</book>`},
-	{Value: atomValue, ExpectXML: atomXml},
-	{
-		Value: &Ship{
-			Name:  "Heart of Gold",
-			Pilot: "Computer",
-			Age:   1,
-			Drive: ImprobabilityDrive,
-			Passenger: []*Passenger{
-				&Passenger{
-					Name:   []string{"Zaphod", "Beeblebrox"},
-					Weight: 7.25,
-				},
-				&Passenger{
-					Name:   []string{"Trisha", "McMillen"},
-					Weight: 5.5,
-				},
-				&Passenger{
-					Name:   []string{"Ford", "Prefect"},
-					Weight: 7,
-				},
-				&Passenger{
-					Name:   []string{"Arthur", "Dent"},
-					Weight: 6.75,
-				},
-			},
-		},
-		ExpectXML: `<spaceship name="Heart of Gold" pilot="Computer">` +
-			`<drive>` + strconv.Itoa(int(ImprobabilityDrive)) + `</drive>` +
-			`<age>1</age>` +
-			`<passenger>` +
-			`<name>Zaphod</name>` +
-			`<name>Beeblebrox</name>` +
-			`<weight>7.25</weight>` +
-			`</passenger>` +
-			`<passenger>` +
-			`<name>Trisha</name>` +
-			`<name>McMillen</name>` +
-			`<weight>5.5</weight>` +
-			`</passenger>` +
-			`<passenger>` +
-			`<name>Ford</name>` +
-			`<name>Prefect</name>` +
-			`<weight>7</weight>` +
-			`</passenger>` +
-			`<passenger>` +
-			`<name>Arthur</name>` +
-			`<name>Dent</name>` +
-			`<weight>6.75</weight>` +
-			`</passenger>` +
-			`</spaceship>`,
-	},
-	// Test a>b
-	{
-		Value: NestedItems{Items: []string{}, Item1: []string{}},
-		ExpectXML: `<result>` +
-			`<Items>` +
-			`</Items>` +
-			`</result>`,
-	},
-	{
-		Value: NestedItems{Items: []string{}, Item1: []string{"A"}},
-		ExpectXML: `<result>` +
-			`<Items>` +
-			`<item1>A</item1>` +
-			`</Items>` +
-			`</result>`,
-	},
-	{
-		Value: NestedItems{Items: []string{"A", "B"}, Item1: []string{}},
-		ExpectXML: `<result>` +
-			`<Items>` +
-			`<item>A</item>` +
-			`<item>B</item>` +
-			`</Items>` +
-			`</result>`,
-	},
-	{
-		Value: NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},
-		ExpectXML: `<result>` +
-			`<Items>` +
-			`<item>A</item>` +
-			`<item>B</item>` +
-			`<item1>C</item1>` +
-			`</Items>` +
-			`</result>`,
-	},
-	{
-		Value: NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
-		ExpectXML: `<result>` +
-			`<parent>` +
-			`<c>C</c>` +
-			`<b>B</b>` +
-			`<a>A</a>` +
-			`</parent>` +
-			`</result>`,
-	},
-	{
-		Value: NilTest{A: "A", B: nil, C: "C"},
-		ExpectXML: `<???>` +
-			`<parent1>` +
-			`<parent2><a>A</a></parent2>` +
-			`<parent2><c>C</c></parent2>` +
-			`</parent1>` +
-			`</???>`,
-	},
-	{
-		Value: MixedNested{A: "A", B: "B", C: "C", D: "D"},
-		ExpectXML: `<result>` +
-			`<parent1><a>A</a></parent1>` +
-			`<b>B</b>` +
-			`<parent1>` +
-			`<parent2><c>C</c></parent2>` +
-			`<d>D</d>` +
-			`</parent1>` +
-			`</result>`,
-	},
-	{
-		Value:     Service{Port: &Port{Number: "80"}},
-		ExpectXML: `<service><host><port>80</port></host></service>`,
-	},
-	{
-		Value:     Service{},
-		ExpectXML: `<service></service>`,
-	},
-	{
-		Value: Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},
-		ExpectXML: `<service>` +
-			`<host><port>80</port></host>` +
-			`<Extra1>A</Extra1>` +
-			`<host><extra2>B</extra2></host>` +
-			`</service>`,
-	},
-	{
-		Value: Service{Port: &Port{Number: "80"}, Extra2: "example"},
-		ExpectXML: `<service>` +
-			`<host><port>80</port></host>` +
-			`<host><extra2>example</extra2></host>` +
-			`</service>`,
-	},
-}
-
-func TestMarshal(t *testing.T) {
-	for idx, test := range marshalTests {
-		buf := bytes.NewBuffer(nil)
-		err := Marshal(buf, test.Value)
-		if err != nil {
-			t.Errorf("#%d: Error: %s", idx, err)
-			continue
-		}
-		if got, want := buf.String(), test.ExpectXML; got != want {
-			if strings.Contains(want, "\n") {
-				t.Errorf("#%d: marshal(%#v) - GOT:\n%s\nWANT:\n%s", idx, test.Value, got, want)
-			} else {
-				t.Errorf("#%d: marshal(%#v) = %#q want %#q", idx, test.Value, got, want)
-			}
-		}
-	}
-}
-
-var marshalErrorTests = []struct {
-	Value      interface{}
-	ExpectErr  string
-	ExpectKind reflect.Kind
-}{
-	{
-		Value:      make(chan bool),
-		ExpectErr:  "xml: unsupported type: chan bool",
-		ExpectKind: reflect.Chan,
-	},
-	{
-		Value: map[string]string{
-			"question": "What do you get when you multiply six by nine?",
-			"answer":   "42",
-		},
-		ExpectErr:  "xml: unsupported type: map[string] string",
-		ExpectKind: reflect.Map,
-	},
-	{
-		Value:      map[*Ship]bool{nil: false},
-		ExpectErr:  "xml: unsupported type: map[*xml.Ship] bool",
-		ExpectKind: reflect.Map,
-	},
-}
-
-func TestMarshalErrors(t *testing.T) {
-	for idx, test := range marshalErrorTests {
-		buf := bytes.NewBuffer(nil)
-		err := Marshal(buf, test.Value)
-		if got, want := err, test.ExpectErr; got == nil {
-			t.Errorf("#%d: want error %s", idx, want)
-			continue
-		} else if got.String() != want {
-			t.Errorf("#%d: marshal(%#v) = [error] %q, want %q", idx, test.Value, got, want)
-		}
-		if got, want := err.(*UnsupportedTypeError).Type.Kind(), test.ExpectKind; got != want {
-			t.Errorf("#%d: marshal(%#v) = [error kind] %s, want %s", idx, test.Value, got, want)
-		}
-	}
-}
-
-// Do invertibility testing on the various structures that we test
-func TestUnmarshal(t *testing.T) {
-	for i, test := range marshalTests {
-		// Skip the nil pointers
-		if i <= 1 {
-			continue
-		}
-
-		var dest interface{}
-
-		switch test.Value.(type) {
-		case *Ship, Ship:
-			dest = &Ship{}
-		case *Port, Port:
-			dest = &Port{}
-		case *Domain, Domain:
-			dest = &Domain{}
-		case *Feed, Feed:
-			dest = &Feed{}
-		default:
-			continue
-		}
-
-		buffer := bytes.NewBufferString(test.ExpectXML)
-		err := Unmarshal(buffer, dest)
-
-		// Don't compare XMLNames
-		switch fix := dest.(type) {
-		case *Ship:
-			fix.XMLName = Name{}
-		case *Port:
-			fix.XMLName = Name{}
-		case *Domain:
-			fix.XMLName = Name{}
-		case *Feed:
-			fix.XMLName = Name{}
-			fix.Author.InnerXML = ""
-			for i := range fix.Entry {
-				fix.Entry[i].Author.InnerXML = ""
-			}
-		}
-
-		if err != nil {
-			t.Errorf("#%d: unexpected error: %#v", i, err)
-		} else if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
-			t.Errorf("#%d: unmarshal(%#s) = %#v, want %#v", i, test.ExpectXML, got, want)
-		}
-	}
-}
-
-func BenchmarkMarshal(b *testing.B) {
-	idx := len(marshalTests) - 1
-	test := marshalTests[idx]
-
-	buf := bytes.NewBuffer(nil)
-	for i := 0; i < b.N; i++ {
-		Marshal(buf, test.Value)
-		buf.Truncate(0)
-	}
-}
-
-func BenchmarkUnmarshal(b *testing.B) {
-	idx := len(marshalTests) - 1
-	test := marshalTests[idx]
-	sm := &Ship{}
-	xml := []byte(test.ExpectXML)
-
-	for i := 0; i < b.N; i++ {
-		buffer := bytes.NewBuffer(xml)
-		Unmarshal(buffer, sm)
-	}
-}
diff --git a/src/pkg/xml/read.go b/src/pkg/xml/read.go
deleted file mode 100644
index 786b69f..0000000
--- a/src/pkg/xml/read.go
+++ /dev/null
@@ -1,631 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package xml
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"reflect"
-	"strconv"
-	"strings"
-	"unicode"
-	"utf8"
-)
-
-// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
-// an XML element is an order-dependent collection of anonymous
-// values, while a data structure is an order-independent collection
-// of named values.
-// See package json for a textual representation more suitable
-// to data structures.
-
-// Unmarshal parses an XML element from r and uses the
-// reflect library to fill in an arbitrary struct, slice, or string
-// pointed at by val.  Well-formed data that does not fit
-// into val is discarded.
-//
-// For example, given these definitions:
-//
-//	type Email struct {
-//		Where string `xml:"attr"`
-//		Addr  string
-//	}
-//
-//	type Result struct {
-//		XMLName xml.Name `xml:"result"`
-//		Name	string
-//		Phone	string
-//		Email	[]Email
-//		Groups  []string `xml:"group>value"`
-//	}
-//
-//	result := Result{Name: "name", Phone: "phone", Email: nil}
-//
-// unmarshalling the XML input
-//
-//	<result>
-//		<email where="home">
-//			<addr>gre at example.com</addr>
-//		</email>
-//		<email where='work'>
-//			<addr>gre at work.com</addr>
-//		</email>
-//		<name>Grace R. Emlin</name>
-// 		<group>
-// 			<value>Friends</value>
-// 			<value>Squash</value>
-// 		</group>
-//		<address>123 Main Street</address>
-//	</result>
-//
-// via Unmarshal(r, &result) is equivalent to assigning
-//
-//	r = Result{xml.Name{"", "result"},
-//		"Grace R. Emlin", // name
-//		"phone",	  // no phone given
-//		[]Email{
-//			Email{"home", "gre at example.com"},
-//			Email{"work", "gre at work.com"},
-//		},
-//		[]string{"Friends", "Squash"},
-//	}
-//
-// Note that the field r.Phone has not been modified and
-// that the XML <address> element was discarded. Also, the field
-// Groups was assigned considering the element path provided in the
-// field tag.
-//
-// Because Unmarshal uses the reflect package, it can only assign
-// to exported (upper case) fields.  Unmarshal uses a case-insensitive
-// comparison to match XML element names to struct field names.
-//
-// Unmarshal maps an XML element to a struct using the following rules.
-// In the rules, the tag of a field refers to the value associated with the
-// key 'xml' in the struct field's tag (see the example above).
-//
-//   * If the struct has a field of type []byte or string with tag "innerxml",
-//      Unmarshal accumulates the raw XML nested inside the element
-//      in that field.  The rest of the rules still apply.
-//
-//   * If the struct has a field named XMLName of type xml.Name,
-//      Unmarshal records the element name in that field.
-//
-//   * If the XMLName field has an associated tag of the form
-//      "name" or "namespace-URL name", the XML element must have
-//      the given name (and, optionally, name space) or else Unmarshal
-//      returns an error.
-//
-//   * If the XML element has an attribute whose name matches a
-//      struct field of type string with tag "attr", Unmarshal records
-//      the attribute value in that field.
-//
-//   * If the XML element contains character data, that data is
-//      accumulated in the first struct field that has tag "chardata".
-//      The struct field may have type []byte or string.
-//      If there is no such field, the character data is discarded.
-//
-//   * If the XML element contains comments, they are accumulated in
-//      the first struct field that has tag "comments".  The struct
-//      field may have type []byte or string.  If there is no such
-//      field, the comments are discarded.
-//
-//   * If the XML element contains a sub-element whose name matches
-//      the prefix of a tag formatted as "a>b>c", unmarshal
-//      will descend into the XML structure looking for elements with the
-//      given names, and will map the innermost elements to that struct field.
-//      A tag starting with ">" is equivalent to one starting
-//      with the field name followed by ">".
-//
-//   * If the XML element contains a sub-element whose name
-//      matches a field whose tag is neither "attr" nor "chardata",
-//      Unmarshal maps the sub-element to that struct field.
-//      Otherwise, if the struct has a field named Any, unmarshal
-//      maps the sub-element to that struct field.
-//
-// Unmarshal maps an XML element to a string or []byte by saving the
-// concatenation of that element's character data in the string or
-// []byte.
-//
-// Unmarshal maps an attribute value to a string or []byte by saving
-// the value in the string or slice.
-//
-// Unmarshal maps an XML element to a slice by extending the length of
-// the slice and mapping the element to the newly created value.
-//
-// Unmarshal maps an XML element or attribute value to a bool by
-// setting it to the boolean value represented by the string.
-//
-// Unmarshal maps an XML element or attribute value to an integer or
-// floating-point field by setting the field to the result of
-// interpreting the string value in decimal.  There is no check for
-// overflow.
-//
-// Unmarshal maps an XML element to an xml.Name by recording the
-// element name.
-//
-// Unmarshal maps an XML element to a pointer by setting the pointer
-// to a freshly allocated value and then mapping the element to that value.
-//
-func Unmarshal(r io.Reader, val interface{}) os.Error {
-	v := reflect.ValueOf(val)
-	if v.Kind() != reflect.Ptr {
-		return os.NewError("non-pointer passed to Unmarshal")
-	}
-	p := NewParser(r)
-	elem := v.Elem()
-	err := p.unmarshal(elem, nil)
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
-// An UnmarshalError represents an error in the unmarshalling process.
-type UnmarshalError string
-
-func (e UnmarshalError) String() string { return string(e) }
-
-// A TagPathError represents an error in the unmarshalling process
-// caused by the use of field tags with conflicting paths.
-type TagPathError struct {
-	Struct       reflect.Type
-	Field1, Tag1 string
-	Field2, Tag2 string
-}
-
-func (e *TagPathError) String() string {
-	return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2)
-}
-
-// The Parser's Unmarshal method is like xml.Unmarshal
-// except that it can be passed a pointer to the initial start element,
-// useful when a client reads some raw XML tokens itself
-// but also defers to Unmarshal for some elements.
-// Passing a nil start element indicates that Unmarshal should
-// read the token stream to find the start element.
-func (p *Parser) Unmarshal(val interface{}, start *StartElement) os.Error {
-	v := reflect.ValueOf(val)
-	if v.Kind() != reflect.Ptr {
-		return os.NewError("non-pointer passed to Unmarshal")
-	}
-	return p.unmarshal(v.Elem(), start)
-}
-
-// fieldName strips invalid characters from an XML name
-// to create a valid Go struct name.  It also converts the
-// name to lower case letters.
-func fieldName(original string) string {
-
-	var i int
-	//remove leading underscores
-	for i = 0; i < len(original) && original[i] == '_'; i++ {
-	}
-
-	return strings.Map(
-		func(x int) int {
-			if x == '_' || unicode.IsDigit(x) || unicode.IsLetter(x) {
-				return unicode.ToLower(x)
-			}
-			return -1
-		},
-		original[i:])
-}
-
-// Unmarshal a single XML element into val.
-func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
-	// Find start element if we need it.
-	if start == nil {
-		for {
-			tok, err := p.Token()
-			if err != nil {
-				return err
-			}
-			if t, ok := tok.(StartElement); ok {
-				start = &t
-				break
-			}
-		}
-	}
-
-	if pv := val; pv.Kind() == reflect.Ptr {
-		if pv.IsNil() {
-			pv.Set(reflect.New(pv.Type().Elem()))
-		}
-		val = pv.Elem()
-	}
-
-	var (
-		data         []byte
-		saveData     reflect.Value
-		comment      []byte
-		saveComment  reflect.Value
-		saveXML      reflect.Value
-		saveXMLIndex int
-		saveXMLData  []byte
-		sv           reflect.Value
-		styp         reflect.Type
-		fieldPaths   map[string]pathInfo
-	)
-
-	switch v := val; v.Kind() {
-	default:
-		return os.NewError("unknown type " + v.Type().String())
-
-	case reflect.Slice:
-		typ := v.Type()
-		if typ.Elem().Kind() == reflect.Uint8 {
-			// []byte
-			saveData = v
-			break
-		}
-
-		// Slice of element values.
-		// Grow slice.
-		n := v.Len()
-		if n >= v.Cap() {
-			ncap := 2 * n
-			if ncap < 4 {
-				ncap = 4
-			}
-			new := reflect.MakeSlice(typ, n, ncap)
-			reflect.Copy(new, v)
-			v.Set(new)
-		}
-		v.SetLen(n + 1)
-
-		// Recur to read element into slice.
-		if err := p.unmarshal(v.Index(n), start); err != nil {
-			v.SetLen(n)
-			return err
-		}
-		return nil
-
-	case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String:
-		saveData = v
-
-	case reflect.Struct:
-		if _, ok := v.Interface().(Name); ok {
-			v.Set(reflect.ValueOf(start.Name))
-			break
-		}
-
-		sv = v
-		typ := sv.Type()
-		styp = typ
-		// Assign name.
-		if f, ok := typ.FieldByName("XMLName"); ok {
-			// Validate element name.
-			if tag := f.Tag.Get("xml"); tag != "" {
-				ns := ""
-				i := strings.LastIndex(tag, " ")
-				if i >= 0 {
-					ns, tag = tag[0:i], tag[i+1:]
-				}
-				if tag != start.Name.Local {
-					return UnmarshalError("expected element type <" + tag + "> but have <" + start.Name.Local + ">")
-				}
-				if ns != "" && ns != start.Name.Space {
-					e := "expected element <" + tag + "> in name space " + ns + " but have "
-					if start.Name.Space == "" {
-						e += "no name space"
-					} else {
-						e += start.Name.Space
-					}
-					return UnmarshalError(e)
-				}
-			}
-
-			// Save
-			v := sv.FieldByIndex(f.Index)
-			if _, ok := v.Interface().(Name); !ok {
-				return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name")
-			}
-			v.Set(reflect.ValueOf(start.Name))
-		}
-
-		// Assign attributes.
-		// Also, determine whether we need to save character data or comments.
-		for i, n := 0, typ.NumField(); i < n; i++ {
-			f := typ.Field(i)
-			switch f.Tag.Get("xml") {
-			case "attr":
-				strv := sv.FieldByIndex(f.Index)
-				// Look for attribute.
-				val := ""
-				k := strings.ToLower(f.Name)
-				for _, a := range start.Attr {
-					if fieldName(a.Name.Local) == k {
-						val = a.Value
-						break
-					}
-				}
-				copyValue(strv, []byte(val))
-
-			case "comment":
-				if !saveComment.IsValid() {
-					saveComment = sv.FieldByIndex(f.Index)
-				}
-
-			case "chardata":
-				if !saveData.IsValid() {
-					saveData = sv.FieldByIndex(f.Index)
-				}
-
-			case "innerxml":
-				if !saveXML.IsValid() {
-					saveXML = sv.FieldByIndex(f.Index)
-					if p.saved == nil {
-						saveXMLIndex = 0
-						p.saved = new(bytes.Buffer)
-					} else {
-						saveXMLIndex = p.savedOffset()
-					}
-				}
-
-			default:
-				if tag := f.Tag.Get("xml"); strings.Contains(tag, ">") {
-					if fieldPaths == nil {
-						fieldPaths = make(map[string]pathInfo)
-					}
-					path := strings.ToLower(tag)
-					if strings.HasPrefix(tag, ">") {
-						path = strings.ToLower(f.Name) + path
-					}
-					if strings.HasSuffix(tag, ">") {
-						path = path[:len(path)-1]
-					}
-					err := addFieldPath(sv, fieldPaths, path, f.Index)
-					if err != nil {
-						return err
-					}
-				}
-			}
-		}
-	}
-
-	// Find end element.
-	// Process sub-elements along the way.
-Loop:
-	for {
-		var savedOffset int
-		if saveXML.IsValid() {
-			savedOffset = p.savedOffset()
-		}
-		tok, err := p.Token()
-		if err != nil {
-			return err
-		}
-		switch t := tok.(type) {
-		case StartElement:
-			// Sub-element.
-			// Look up by tag name.
-			if sv.IsValid() {
-				k := fieldName(t.Name.Local)
-
-				if fieldPaths != nil {
-					if _, found := fieldPaths[k]; found {
-						if err := p.unmarshalPaths(sv, fieldPaths, k, &t); err != nil {
-							return err
-						}
-						continue Loop
-					}
-				}
-
-				match := func(s string) bool {
-					// check if the name matches ignoring case
-					if strings.ToLower(s) != k {
-						return false
-					}
-					// now check that it's public
-					c, _ := utf8.DecodeRuneInString(s)
-					return unicode.IsUpper(c)
-				}
-
-				f, found := styp.FieldByNameFunc(match)
-				if !found { // fall back to mop-up field named "Any"
-					f, found = styp.FieldByName("Any")
-				}
-				if found {
-					if err := p.unmarshal(sv.FieldByIndex(f.Index), &t); err != nil {
-						return err
-					}
-					continue Loop
-				}
-			}
-			// Not saving sub-element but still have to skip over it.
-			if err := p.Skip(); err != nil {
-				return err
-			}
-
-		case EndElement:
-			if saveXML.IsValid() {
-				saveXMLData = p.saved.Bytes()[saveXMLIndex:savedOffset]
-				if saveXMLIndex == 0 {
-					p.saved = nil
-				}
-			}
-			break Loop
-
-		case CharData:
-			if saveData.IsValid() {
-				data = append(data, t...)
-			}
-
-		case Comment:
-			if saveComment.IsValid() {
-				comment = append(comment, t...)
-			}
-		}
-	}
-
-	if err := copyValue(saveData, data); err != nil {
-		return err
-	}
-
-	switch t := saveComment; t.Kind() {
-	case reflect.String:
-		t.SetString(string(comment))
-	case reflect.Slice:
-		t.Set(reflect.ValueOf(comment))
-	}
-
-	switch t := saveXML; t.Kind() {
-	case reflect.String:
-		t.SetString(string(saveXMLData))
-	case reflect.Slice:
-		t.Set(reflect.ValueOf(saveXMLData))
-	}
-
-	return nil
-}
-
-func copyValue(dst reflect.Value, src []byte) (err os.Error) {
-	// Helper functions for integer and unsigned integer conversions
-	var itmp int64
-	getInt64 := func() bool {
-		itmp, err = strconv.Atoi64(string(src))
-		// TODO: should check sizes
-		return err == nil
-	}
-	var utmp uint64
-	getUint64 := func() bool {
-		utmp, err = strconv.Atoui64(string(src))
-		// TODO: check for overflow?
-		return err == nil
-	}
-	var ftmp float64
-	getFloat64 := func() bool {
-		ftmp, err = strconv.Atof64(string(src))
-		// TODO: check for overflow?
-		return err == nil
-	}
-
-	// Save accumulated data and comments
-	switch t := dst; t.Kind() {
-	case reflect.Invalid:
-		// Probably a comment, handled below
-	default:
-		return os.NewError("cannot happen: unknown type " + t.Type().String())
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		if !getInt64() {
-			return err
-		}
-		t.SetInt(itmp)
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		if !getUint64() {
-			return err
-		}
-		t.SetUint(utmp)
-	case reflect.Float32, reflect.Float64:
-		if !getFloat64() {
-			return err
-		}
-		t.SetFloat(ftmp)
-	case reflect.Bool:
-		value, err := strconv.Atob(strings.TrimSpace(string(src)))
-		if err != nil {
-			return err
-		}
-		t.SetBool(value)
-	case reflect.String:
-		t.SetString(string(src))
-	case reflect.Slice:
-		t.Set(reflect.ValueOf(src))
-	}
-	return nil
-}
-
-type pathInfo struct {
-	fieldIdx []int
-	complete bool
-}
-
-// addFieldPath takes an element path such as "a>b>c" and fills the
-// paths map with all paths leading to it ("a", "a>b", and "a>b>c").
-// It is okay for paths to share a common, shorter prefix but not ok
-// for one path to itself be a prefix of another.
-func addFieldPath(sv reflect.Value, paths map[string]pathInfo, path string, fieldIdx []int) os.Error {
-	if info, found := paths[path]; found {
-		return tagError(sv, info.fieldIdx, fieldIdx)
-	}
-	paths[path] = pathInfo{fieldIdx, true}
-	for {
-		i := strings.LastIndex(path, ">")
-		if i < 0 {
-			break
-		}
-		path = path[:i]
-		if info, found := paths[path]; found {
-			if info.complete {
-				return tagError(sv, info.fieldIdx, fieldIdx)
-			}
-		} else {
-			paths[path] = pathInfo{fieldIdx, false}
-		}
-	}
-	return nil
-
-}
-
-func tagError(sv reflect.Value, idx1 []int, idx2 []int) os.Error {
-	t := sv.Type()
-	f1 := t.FieldByIndex(idx1)
-	f2 := t.FieldByIndex(idx2)
-	return &TagPathError{t, f1.Name, f1.Tag.Get("xml"), f2.Name, f2.Tag.Get("xml")}
-}
-
-// unmarshalPaths walks down an XML structure looking for
-// wanted paths, and calls unmarshal on them.
-func (p *Parser) unmarshalPaths(sv reflect.Value, paths map[string]pathInfo, path string, start *StartElement) os.Error {
-	if info, _ := paths[path]; info.complete {
-		return p.unmarshal(sv.FieldByIndex(info.fieldIdx), start)
-	}
-	for {
-		tok, err := p.Token()
-		if err != nil {
-			return err
-		}
-		switch t := tok.(type) {
-		case StartElement:
-			k := path + ">" + fieldName(t.Name.Local)
-			if _, found := paths[k]; found {
-				if err := p.unmarshalPaths(sv, paths, k, &t); err != nil {
-					return err
-				}
-				continue
-			}
-			if err := p.Skip(); err != nil {
-				return err
-			}
-		case EndElement:
-			return nil
-		}
-	}
-	panic("unreachable")
-}
-
-// Have already read a start element.
-// Read tokens until we find the end element.
-// Token is taking care of making sure the
-// end element matches the start element we saw.
-func (p *Parser) Skip() os.Error {
-	for {
-		tok, err := p.Token()
-		if err != nil {
-			return err
-		}
-		switch t := tok.(type) {
-		case StartElement:
-			if err := p.Skip(); err != nil {
-				return err
-			}
-		case EndElement:
-			return nil
-		}
-	}
-	panic("unreachable")
-}
diff --git a/src/pkg/xml/read_test.go b/src/pkg/xml/read_test.go
deleted file mode 100644
index 2126da3..0000000
--- a/src/pkg/xml/read_test.go
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package xml
-
-import (
-	"reflect"
-	"testing"
-)
-
-// Stripped down Atom feed data structures.
-
-func TestUnmarshalFeed(t *testing.T) {
-	var f Feed
-	if err := Unmarshal(StringReader(atomFeedString), &f); err != nil {
-		t.Fatalf("Unmarshal: %s", err)
-	}
-	if !reflect.DeepEqual(f, atomFeed) {
-		t.Fatalf("have %#v\nwant %#v", f, atomFeed)
-	}
-}
-
-// hget http://codereview.appspot.com/rss/mine/rsc
-const atomFeedString = `
-<?xml version="1.0" encoding="utf-8"?>
-<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><li-nk href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></li-nk><id>http://codereview.appspot.com/</id><updated>2009-10-04T01:35:58+00:00</updated><author><name>rietveld<></name></author><entry><title>rietveld: an attempt at pubsubhubbub
-</title><link hre-f="http://codereview.appspot.com/126085" rel="alternate"></link><updated>2009-10-04T01:35:58+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:134d9179c41f806be79b3a5f7877d19a</id><summary type="html">
-  An attempt at adding pubsubhubbub support to Rietveld.
-http://code.google.com/p/pubsubhubbub
-http://code.google.com/p/rietveld/issues/detail?id=155
-
-The server side of the protocol is trivial:
-  1. add a &lt;link rel=&quot;hub&quot; href=&quot;hub-server&quot;&gt; tag to all
-     feeds that will be pubsubhubbubbed.
-  2. every time one of those feeds changes, tell the hub
-     with a simple POST request.
-
-I have tested this by adding debug prints to a local hub
-server and checking that the server got the right publish
-requests.
-
-I can&#39;t quite get the server to work, but I think the bug
-is not in my code.  I think that the server expects to be
-able to grab the feed and see the feed&#39;s actual URL in
-the link rel=&quot;self&quot;, but the default value for that drops
-the :port from the URL, and I cannot for the life of me
-figure out how to get the Atom generator deep inside
-django not to do that, or even where it is doing that,
-or even what code is running to generate the Atom feed.
-(I thought I knew but I added some assert False statements
-and it kept running!)
-
-Ignoring that particular problem, I would appreciate
-feedback on the right way to get the two values at
-the top of feeds.py marked NOTE(rsc).
-
-
-</summary></entry><entry><title>rietveld: correct tab handling
-</title><link href="http://codereview.appspot.com/124106" rel="alternate"></link><updated>2009-10-03T23:02:17+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:0a2a4f19bb815101f0ba2904aed7c35a</id><summary type="html">
-  This fixes the buggy tab rendering that can be seen at
-http://codereview.appspot.com/116075/diff/1/2
-
-The fundamental problem was that the tab code was
-not being told what column the text began in, so it
-didn&#39;t know where to put the tab stops.  Another problem
-was that some of the code assumed that string byte
-offsets were the same as column offsets, which is only
-true if there are no tabs.
-
-In the process of fixing this, I cleaned up the arguments
-to Fold and ExpandTabs and renamed them Break and
-_ExpandTabs so that I could be sure that I found all the
-call sites.  I also wanted to verify that ExpandTabs was
-not being used from outside intra_region_diff.py.
-
-
-</summary></entry></feed> 	   `
-
-type Feed struct {
-	XMLName Name `xml:"http://www.w3.org/2005/Atom feed"`
-	Title   string
-	Id      string
-	Link    []Link
-	Updated Time
-	Author  Person
-	Entry   []Entry
-}
-
-type Entry struct {
-	Title   string
-	Id      string
-	Link    []Link
-	Updated Time
-	Author  Person
-	Summary Text
-}
-
-type Link struct {
-	Rel  string `xml:"attr"`
-	Href string `xml:"attr"`
-}
-
-type Person struct {
-	Name     string
-	URI      string
-	Email    string
-	InnerXML string `xml:"innerxml"`
-}
-
-type Text struct {
-	Type string `xml:"attr"`
-	Body string `xml:"chardata"`
-}
-
-type Time string
-
-var atomFeed = Feed{
-	XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
-	Title:   "Code Review - My issues",
-	Link: []Link{
-		{Rel: "alternate", Href: "http://codereview.appspot.com/"},
-		{Rel: "self", Href: "http://codereview.appspot.com/rss/mine/rsc"},
-	},
-	Id:      "http://codereview.appspot.com/",
-	Updated: "2009-10-04T01:35:58+00:00",
-	Author: Person{
-		Name:     "rietveld<>",
-		InnerXML: "<name>rietveld<></name>",
-	},
-	Entry: []Entry{
-		{
-			Title: "rietveld: an attempt at pubsubhubbub\n",
-			Link: []Link{
-				{Rel: "alternate", Href: "http://codereview.appspot.com/126085"},
-			},
-			Updated: "2009-10-04T01:35:58+00:00",
-			Author: Person{
-				Name:     "email-address-removed",
-				InnerXML: "<name>email-address-removed</name>",
-			},
-			Id: "urn:md5:134d9179c41f806be79b3a5f7877d19a",
-			Summary: Text{
-				Type: "html",
-				Body: `
-  An attempt at adding pubsubhubbub support to Rietveld.
-http://code.google.com/p/pubsubhubbub
-http://code.google.com/p/rietveld/issues/detail?id=155
-
-The server side of the protocol is trivial:
-  1. add a <link rel="hub" href="hub-server"> tag to all
-     feeds that will be pubsubhubbubbed.
-  2. every time one of those feeds changes, tell the hub
-     with a simple POST request.
-
-I have tested this by adding debug prints to a local hub
-server and checking that the server got the right publish
-requests.
-
-I can't quite get the server to work, but I think the bug
-is not in my code.  I think that the server expects to be
-able to grab the feed and see the feed's actual URL in
-the link rel="self", but the default value for that drops
-the :port from the URL, and I cannot for the life of me
-figure out how to get the Atom generator deep inside
-django not to do that, or even where it is doing that,
-or even what code is running to generate the Atom feed.
-(I thought I knew but I added some assert False statements
-and it kept running!)
-
-Ignoring that particular problem, I would appreciate
-feedback on the right way to get the two values at
-the top of feeds.py marked NOTE(rsc).
-
-
-`,
-			},
-		},
-		{
-			Title: "rietveld: correct tab handling\n",
-			Link: []Link{
-				{Rel: "alternate", Href: "http://codereview.appspot.com/124106"},
-			},
-			Updated: "2009-10-03T23:02:17+00:00",
-			Author: Person{
-				Name:     "email-address-removed",
-				InnerXML: "<name>email-address-removed</name>",
-			},
-			Id: "urn:md5:0a2a4f19bb815101f0ba2904aed7c35a",
-			Summary: Text{
-				Type: "html",
-				Body: `
-  This fixes the buggy tab rendering that can be seen at
-http://codereview.appspot.com/116075/diff/1/2
-
-The fundamental problem was that the tab code was
-not being told what column the text began in, so it
-didn't know where to put the tab stops.  Another problem
-was that some of the code assumed that string byte
-offsets were the same as column offsets, which is only
-true if there are no tabs.
-
-In the process of fixing this, I cleaned up the arguments
-to Fold and ExpandTabs and renamed them Break and
-_ExpandTabs so that I could be sure that I found all the
-call sites.  I also wanted to verify that ExpandTabs was
-not being used from outside intra_region_diff.py.
-
-
-`,
-			},
-		},
-	},
-}
-
-type FieldNameTest struct {
-	in, out string
-}
-
-var FieldNameTests = []FieldNameTest{
-	{"Profile-Image", "profileimage"},
-	{"_score", "score"},
-}
-
-func TestFieldName(t *testing.T) {
-	for _, tt := range FieldNameTests {
-		a := fieldName(tt.in)
-		if a != tt.out {
-			t.Fatalf("have %#v\nwant %#v\n\n", a, tt.out)
-		}
-	}
-}
-
-const pathTestString = `
-<result>
-    <before>1</before>
-    <items>
-        <item1>
-            <value>A</value>
-        </item1>
-        <item2>
-            <value>B</value>
-        </item2>
-        <Item1>
-            <Value>C</Value>
-            <Value>D</Value>
-        </Item1>
-    </items>
-    <after>2</after>
-</result>
-`
-
-type PathTestItem struct {
-	Value string
-}
-
-type PathTestA struct {
-	Items         []PathTestItem `xml:">item1"`
-	Before, After string
-}
-
-type PathTestB struct {
-	Other         []PathTestItem `xml:"items>Item1"`
-	Before, After string
-}
-
-type PathTestC struct {
-	Values1       []string `xml:"items>item1>value"`
-	Values2       []string `xml:"items>item2>value"`
-	Before, After string
-}
-
-type PathTestSet struct {
-	Item1 []PathTestItem
-}
-
-type PathTestD struct {
-	Other         PathTestSet `xml:"items>"`
-	Before, After string
-}
-
-var pathTests = []interface{}{
-	&PathTestA{Items: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
-	&PathTestB{Other: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"},
-	&PathTestC{Values1: []string{"A", "C", "D"}, Values2: []string{"B"}, Before: "1", After: "2"},
-	&PathTestD{Other: PathTestSet{Item1: []PathTestItem{{"A"}, {"D"}}}, Before: "1", After: "2"},
-}
-
-func TestUnmarshalPaths(t *testing.T) {
-	for _, pt := range pathTests {
-		v := reflect.New(reflect.TypeOf(pt).Elem()).Interface()
-		if err := Unmarshal(StringReader(pathTestString), v); err != nil {
-			t.Fatalf("Unmarshal: %s", err)
-		}
-		if !reflect.DeepEqual(v, pt) {
-			t.Fatalf("have %#v\nwant %#v", v, pt)
-		}
-	}
-}
-
-type BadPathTestA struct {
-	First  string `xml:"items>item1"`
-	Other  string `xml:"items>item2"`
-	Second string `xml:"items>"`
-}
-
-type BadPathTestB struct {
-	Other  string `xml:"items>item2>value"`
-	First  string `xml:"items>item1"`
-	Second string `xml:"items>item1>value"`
-}
-
-var badPathTests = []struct {
-	v, e interface{}
-}{
-	{&BadPathTestA{}, &TagPathError{reflect.TypeOf(BadPathTestA{}), "First", "items>item1", "Second", "items>"}},
-	{&BadPathTestB{}, &TagPathError{reflect.TypeOf(BadPathTestB{}), "First", "items>item1", "Second", "items>item1>value"}},
-}
-
-func TestUnmarshalBadPaths(t *testing.T) {
-	for _, tt := range badPathTests {
-		err := Unmarshal(StringReader(pathTestString), tt.v)
-		if !reflect.DeepEqual(err, tt.e) {
-			t.Fatalf("Unmarshal with %#v didn't fail properly: %#v", tt.v, err)
-		}
-	}
-}
-
-func TestUnmarshalAttrs(t *testing.T) {
-	var f AttrTest
-	if err := Unmarshal(StringReader(attrString), &f); err != nil {
-		t.Fatalf("Unmarshal: %s", err)
-	}
-	if !reflect.DeepEqual(f, attrStruct) {
-		t.Fatalf("have %#v\nwant %#v", f, attrStruct)
-	}
-}
-
-type AttrTest struct {
-	Test1 Test1
-	Test2 Test2
-}
-
-type Test1 struct {
-	Int   int     `xml:"attr"`
-	Float float64 `xml:"attr"`
-	Uint8 uint8   `xml:"attr"`
-}
-
-type Test2 struct {
-	Bool bool `xml:"attr"`
-}
-
-const attrString = `
-<?xml version="1.0" charset="utf-8"?>
-<attrtest>
-  <test1 int="8" float="23.5" uint8="255"/>
-  <test2 bool="true"/>
-</attrtest>
-`
-
-var attrStruct = AttrTest{
-	Test1: Test1{
-		Int:   8,
-		Float: 23.5,
-		Uint8: 255,
-	},
-	Test2: Test2{
-		Bool: true,
-	},
-}
diff --git a/src/pkg/xml/xml.go b/src/pkg/xml/xml.go
deleted file mode 100644
index e7ba44e..0000000
--- a/src/pkg/xml/xml.go
+++ /dev/null
@@ -1,1694 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package xml implements a simple XML 1.0 parser that
-// understands XML name spaces.
-package xml
-
-// References:
-//    Annotated XML spec: http://www.xml.com/axml/testaxml.htm
-//    XML name spaces: http://www.w3.org/TR/REC-xml-names/
-
-// TODO(rsc):
-//	Test error handling.
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io"
-	"os"
-	"strconv"
-	"strings"
-	"unicode"
-	"utf8"
-)
-
-// A SyntaxError represents a syntax error in the XML input stream.
-type SyntaxError struct {
-	Msg  string
-	Line int
-}
-
-func (e *SyntaxError) String() string {
-	return "XML syntax error on line " + strconv.Itoa(e.Line) + ": " + e.Msg
-}
-
-// A Name represents an XML name (Local) annotated
-// with a name space identifier (Space).
-// In tokens returned by Parser.Token, the Space identifier
-// is given as a canonical URL, not the short prefix used
-// in the document being parsed.
-type Name struct {
-	Space, Local string
-}
-
-// An Attr represents an attribute in an XML element (Name=Value).
-type Attr struct {
-	Name  Name
-	Value string
-}
-
-// A Token is an interface holding one of the token types:
-// StartElement, EndElement, CharData, Comment, ProcInst, or Directive.
-type Token interface{}
-
-// A StartElement represents an XML start element.
-type StartElement struct {
-	Name Name
-	Attr []Attr
-}
-
-func (e StartElement) Copy() StartElement {
-	attrs := make([]Attr, len(e.Attr))
-	copy(e.Attr, attrs)
-	e.Attr = attrs
-	return e
-}
-
-// An EndElement represents an XML end element.
-type EndElement struct {
-	Name Name
-}
-
-// A CharData represents XML character data (raw text),
-// in which XML escape sequences have been replaced by
-// the characters they represent.
-type CharData []byte
-
-func makeCopy(b []byte) []byte {
-	b1 := make([]byte, len(b))
-	copy(b1, b)
-	return b1
-}
-
-func (c CharData) Copy() CharData { return CharData(makeCopy(c)) }
-
-// A Comment represents an XML comment of the form <!--comment-->.
-// The bytes do not include the <!-- and --> comment markers.
-type Comment []byte
-
-func (c Comment) Copy() Comment { return Comment(makeCopy(c)) }
-
-// A ProcInst represents an XML processing instruction of the form <?target inst?>
-type ProcInst struct {
-	Target string
-	Inst   []byte
-}
-
-func (p ProcInst) Copy() ProcInst {
-	p.Inst = makeCopy(p.Inst)
-	return p
-}
-
-// A Directive represents an XML directive of the form <!text>.
-// The bytes do not include the <! and > markers.
-type Directive []byte
-
-func (d Directive) Copy() Directive { return Directive(makeCopy(d)) }
-
-// CopyToken returns a copy of a Token.
-func CopyToken(t Token) Token {
-	switch v := t.(type) {
-	case CharData:
-		return v.Copy()
-	case Comment:
-		return v.Copy()
-	case Directive:
-		return v.Copy()
-	case ProcInst:
-		return v.Copy()
-	case StartElement:
-		return v.Copy()
-	}
-	return t
-}
-
-// A Parser represents an XML parser reading a particular input stream.
-// The parser assumes that its input is encoded in UTF-8.
-type Parser struct {
-	// Strict defaults to true, enforcing the requirements
-	// of the XML specification.
-	// If set to false, the parser allows input containing common
-	// mistakes:
-	//	* If an element is missing an end tag, the parser invents
-	//	  end tags as necessary to keep the return values from Token
-	//	  properly balanced.
-	//	* In attribute values and character data, unknown or malformed
-	//	  character entities (sequences beginning with &) are left alone.
-	//
-	// Setting:
-	//
-	//	p.Strict = false;
-	//	p.AutoClose = HTMLAutoClose;
-	//	p.Entity = HTMLEntity
-	//
-	// creates a parser that can handle typical HTML.
-	Strict bool
-
-	// When Strict == false, AutoClose indicates a set of elements to
-	// consider closed immediately after they are opened, regardless
-	// of whether an end element is present.
-	AutoClose []string
-
-	// Entity can be used to map non-standard entity names to string replacements.
-	// The parser behaves as if these standard mappings are present in the map,
-	// regardless of the actual map content:
-	//
-	//	"lt": "<",
-	//	"gt": ">",
-	//	"amp": "&",
-	//	"apos": "'",
-	//	"quot": `"`,
-	Entity map[string]string
-
-	// CharsetReader, if non-nil, defines a function to generate
-	// charset-conversion readers, converting from the provided
-	// non-UTF-8 charset into UTF-8. If CharsetReader is nil or
-	// returns an error, parsing stops with an error. One of the
-	// the CharsetReader's result values must be non-nil.
-	CharsetReader func(charset string, input io.Reader) (io.Reader, os.Error)
-
-	r         io.ByteReader
-	buf       bytes.Buffer
-	saved     *bytes.Buffer
-	stk       *stack
-	free      *stack
-	needClose bool
-	toClose   Name
-	nextToken Token
-	nextByte  int
-	ns        map[string]string
-	err       os.Error
-	line      int
-	tmp       [32]byte
-}
-
-// NewParser creates a new XML parser reading from r.
-func NewParser(r io.Reader) *Parser {
-	p := &Parser{
-		ns:       make(map[string]string),
-		nextByte: -1,
-		line:     1,
-		Strict:   true,
-	}
-	p.switchToReader(r)
-	return p
-}
-
-// Token returns the next XML token in the input stream.
-// At the end of the input stream, Token returns nil, os.EOF.
-//
-// Slices of bytes in the returned token data refer to the
-// parser's internal buffer and remain valid only until the next
-// call to Token.  To acquire a copy of the bytes, call CopyToken
-// or the token's Copy method.
-//
-// Token expands self-closing elements such as <br/>
-// into separate start and end elements returned by successive calls.
-//
-// Token guarantees that the StartElement and EndElement
-// tokens it returns are properly nested and matched:
-// if Token encounters an unexpected end element,
-// it will return an error.
-//
-// Token implements XML name spaces as described by
-// http://www.w3.org/TR/REC-xml-names/.  Each of the
-// Name structures contained in the Token has the Space
-// set to the URL identifying its name space when known.
-// If Token encounters an unrecognized name space prefix,
-// it uses the prefix as the Space rather than report an error.
-func (p *Parser) Token() (t Token, err os.Error) {
-	if p.nextToken != nil {
-		t = p.nextToken
-		p.nextToken = nil
-	} else if t, err = p.RawToken(); err != nil {
-		return
-	}
-
-	if !p.Strict {
-		if t1, ok := p.autoClose(t); ok {
-			p.nextToken = t
-			t = t1
-		}
-	}
-	switch t1 := t.(type) {
-	case StartElement:
-		// In XML name spaces, the translations listed in the
-		// attributes apply to the element name and
-		// to the other attribute names, so process
-		// the translations first.
-		for _, a := range t1.Attr {
-			if a.Name.Space == "xmlns" {
-				v, ok := p.ns[a.Name.Local]
-				p.pushNs(a.Name.Local, v, ok)
-				p.ns[a.Name.Local] = a.Value
-			}
-			if a.Name.Space == "" && a.Name.Local == "xmlns" {
-				// Default space for untagged names
-				v, ok := p.ns[""]
-				p.pushNs("", v, ok)
-				p.ns[""] = a.Value
-			}
-		}
-
-		p.translate(&t1.Name, true)
-		for i := range t1.Attr {
-			p.translate(&t1.Attr[i].Name, false)
-		}
-		p.pushElement(t1.Name)
-		t = t1
-
-	case EndElement:
-		p.translate(&t1.Name, true)
-		if !p.popElement(&t1) {
-			return nil, p.err
-		}
-		t = t1
-	}
-	return
-}
-
-// Apply name space translation to name n.
-// The default name space (for Space=="")
-// applies only to element names, not to attribute names.
-func (p *Parser) translate(n *Name, isElementName bool) {
-	switch {
-	case n.Space == "xmlns":
-		return
-	case n.Space == "" && !isElementName:
-		return
-	case n.Space == "" && n.Local == "xmlns":
-		return
-	}
-	if v, ok := p.ns[n.Space]; ok {
-		n.Space = v
-	}
-}
-
-func (p *Parser) switchToReader(r io.Reader) {
-	// Get efficient byte at a time reader.
-	// Assume that if reader has its own
-	// ReadByte, it's efficient enough.
-	// Otherwise, use bufio.
-	if rb, ok := r.(io.ByteReader); ok {
-		p.r = rb
-	} else {
-		p.r = bufio.NewReader(r)
-	}
-}
-
-// Parsing state - stack holds old name space translations
-// and the current set of open elements.  The translations to pop when
-// ending a given tag are *below* it on the stack, which is
-// more work but forced on us by XML.
-type stack struct {
-	next *stack
-	kind int
-	name Name
-	ok   bool
-}
-
-const (
-	stkStart = iota
-	stkNs
-)
-
-func (p *Parser) push(kind int) *stack {
-	s := p.free
-	if s != nil {
-		p.free = s.next
-	} else {
-		s = new(stack)
-	}
-	s.next = p.stk
-	s.kind = kind
-	p.stk = s
-	return s
-}
-
-func (p *Parser) pop() *stack {
-	s := p.stk
-	if s != nil {
-		p.stk = s.next
-		s.next = p.free
-		p.free = s
-	}
-	return s
-}
-
-// Record that we are starting an element with the given name.
-func (p *Parser) pushElement(name Name) {
-	s := p.push(stkStart)
-	s.name = name
-}
-
-// Record that we are changing the value of ns[local].
-// The old value is url, ok.
-func (p *Parser) pushNs(local string, url string, ok bool) {
-	s := p.push(stkNs)
-	s.name.Local = local
-	s.name.Space = url
-	s.ok = ok
-}
-
-// Creates a SyntaxError with the current line number.
-func (p *Parser) syntaxError(msg string) os.Error {
-	return &SyntaxError{Msg: msg, Line: p.line}
-}
-
-// Record that we are ending an element with the given name.
-// The name must match the record at the top of the stack,
-// which must be a pushElement record.
-// After popping the element, apply any undo records from
-// the stack to restore the name translations that existed
-// before we saw this element.
-func (p *Parser) popElement(t *EndElement) bool {
-	s := p.pop()
-	name := t.Name
-	switch {
-	case s == nil || s.kind != stkStart:
-		p.err = p.syntaxError("unexpected end element </" + name.Local + ">")
-		return false
-	case s.name.Local != name.Local:
-		if !p.Strict {
-			p.needClose = true
-			p.toClose = t.Name
-			t.Name = s.name
-			return true
-		}
-		p.err = p.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
-		return false
-	case s.name.Space != name.Space:
-		p.err = p.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
-			"closed by </" + name.Local + "> in space " + name.Space)
-		return false
-	}
-
-	// Pop stack until a Start is on the top, undoing the
-	// translations that were associated with the element we just closed.
-	for p.stk != nil && p.stk.kind != stkStart {
-		s := p.pop()
-		p.ns[s.name.Local] = s.name.Space, s.ok
-	}
-
-	return true
-}
-
-// If the top element on the stack is autoclosing and
-// t is not the end tag, invent the end tag.
-func (p *Parser) autoClose(t Token) (Token, bool) {
-	if p.stk == nil || p.stk.kind != stkStart {
-		return nil, false
-	}
-	name := strings.ToLower(p.stk.name.Local)
-	for _, s := range p.AutoClose {
-		if strings.ToLower(s) == name {
-			// This one should be auto closed if t doesn't close it.
-			et, ok := t.(EndElement)
-			if !ok || et.Name.Local != name {
-				return EndElement{p.stk.name}, true
-			}
-			break
-		}
-	}
-	return nil, false
-}
-
-// RawToken is like Token but does not verify that
-// start and end elements match and does not translate
-// name space prefixes to their corresponding URLs.
-func (p *Parser) RawToken() (Token, os.Error) {
-	if p.err != nil {
-		return nil, p.err
-	}
-	if p.needClose {
-		// The last element we read was self-closing and
-		// we returned just the StartElement half.
-		// Return the EndElement half now.
-		p.needClose = false
-		return EndElement{p.toClose}, nil
-	}
-
-	b, ok := p.getc()
-	if !ok {
-		return nil, p.err
-	}
-
-	if b != '<' {
-		// Text section.
-		p.ungetc(b)
-		data := p.text(-1, false)
-		if data == nil {
-			return nil, p.err
-		}
-		return CharData(data), nil
-	}
-
-	if b, ok = p.mustgetc(); !ok {
-		return nil, p.err
-	}
-	switch b {
-	case '/':
-		// </: End element
-		var name Name
-		if name, ok = p.nsname(); !ok {
-			if p.err == nil {
-				p.err = p.syntaxError("expected element name after </")
-			}
-			return nil, p.err
-		}
-		p.space()
-		if b, ok = p.mustgetc(); !ok {
-			return nil, p.err
-		}
-		if b != '>' {
-			p.err = p.syntaxError("invalid characters between </" + name.Local + " and >")
-			return nil, p.err
-		}
-		return EndElement{name}, nil
-
-	case '?':
-		// <?: Processing instruction.
-		// TODO(rsc): Should parse the <?xml declaration to make sure
-		// the version is 1.0 and the encoding is UTF-8.
-		var target string
-		if target, ok = p.name(); !ok {
-			if p.err == nil {
-				p.err = p.syntaxError("expected target name after <?")
-			}
-			return nil, p.err
-		}
-		p.space()
-		p.buf.Reset()
-		var b0 byte
-		for {
-			if b, ok = p.mustgetc(); !ok {
-				return nil, p.err
-			}
-			p.buf.WriteByte(b)
-			if b0 == '?' && b == '>' {
-				break
-			}
-			b0 = b
-		}
-		data := p.buf.Bytes()
-		data = data[0 : len(data)-2] // chop ?>
-
-		if target == "xml" {
-			enc := procInstEncoding(string(data))
-			if enc != "" && enc != "utf-8" && enc != "UTF-8" {
-				if p.CharsetReader == nil {
-					p.err = fmt.Errorf("xml: encoding %q declared but Parser.CharsetReader is nil", enc)
-					return nil, p.err
-				}
-				newr, err := p.CharsetReader(enc, p.r.(io.Reader))
-				if err != nil {
-					p.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
-					return nil, p.err
-				}
-				if newr == nil {
-					panic("CharsetReader returned a nil Reader for charset " + enc)
-				}
-				p.switchToReader(newr)
-			}
-		}
-		return ProcInst{target, data}, nil
-
-	case '!':
-		// <!: Maybe comment, maybe CDATA.
-		if b, ok = p.mustgetc(); !ok {
-			return nil, p.err
-		}
-		switch b {
-		case '-': // <!-
-			// Probably <!-- for a comment.
-			if b, ok = p.mustgetc(); !ok {
-				return nil, p.err
-			}
-			if b != '-' {
-				p.err = p.syntaxError("invalid sequence <!- not part of <!--")
-				return nil, p.err
-			}
-			// Look for terminator.
-			p.buf.Reset()
-			var b0, b1 byte
-			for {
-				if b, ok = p.mustgetc(); !ok {
-					return nil, p.err
-				}
-				p.buf.WriteByte(b)
-				if b0 == '-' && b1 == '-' && b == '>' {
-					break
-				}
-				b0, b1 = b1, b
-			}
-			data := p.buf.Bytes()
-			data = data[0 : len(data)-3] // chop -->
-			return Comment(data), nil
-
-		case '[': // <![
-			// Probably <![CDATA[.
-			for i := 0; i < 6; i++ {
-				if b, ok = p.mustgetc(); !ok {
-					return nil, p.err
-				}
-				if b != "CDATA["[i] {
-					p.err = p.syntaxError("invalid <![ sequence")
-					return nil, p.err
-				}
-			}
-			// Have <![CDATA[.  Read text until ]]>.
-			data := p.text(-1, true)
-			if data == nil {
-				return nil, p.err
-			}
-			return CharData(data), nil
-		}
-
-		// Probably a directive: <!DOCTYPE ...>, <!ENTITY ...>, etc.
-		// We don't care, but accumulate for caller. Quoted angle
-		// brackets do not count for nesting.
-		p.buf.Reset()
-		p.buf.WriteByte(b)
-		inquote := uint8(0)
-		depth := 0
-		for {
-			if b, ok = p.mustgetc(); !ok {
-				return nil, p.err
-			}
-			if inquote == 0 && b == '>' && depth == 0 {
-				break
-			}
-			p.buf.WriteByte(b)
-			switch {
-			case b == inquote:
-				inquote = 0
-
-			case inquote != 0:
-				// in quotes, no special action
-
-			case b == '\'' || b == '"':
-				inquote = b
-
-			case b == '>' && inquote == 0:
-				depth--
-
-			case b == '<' && inquote == 0:
-				depth++
-			}
-		}
-		return Directive(p.buf.Bytes()), nil
-	}
-
-	// Must be an open element like <a href="foo">
-	p.ungetc(b)
-
-	var (
-		name  Name
-		empty bool
-		attr  []Attr
-	)
-	if name, ok = p.nsname(); !ok {
-		if p.err == nil {
-			p.err = p.syntaxError("expected element name after <")
-		}
-		return nil, p.err
-	}
-
-	attr = make([]Attr, 0, 4)
-	for {
-		p.space()
-		if b, ok = p.mustgetc(); !ok {
-			return nil, p.err
-		}
-		if b == '/' {
-			empty = true
-			if b, ok = p.mustgetc(); !ok {
-				return nil, p.err
-			}
-			if b != '>' {
-				p.err = p.syntaxError("expected /> in element")
-				return nil, p.err
-			}
-			break
-		}
-		if b == '>' {
-			break
-		}
-		p.ungetc(b)
-
-		n := len(attr)
-		if n >= cap(attr) {
-			nattr := make([]Attr, n, 2*cap(attr))
-			copy(nattr, attr)
-			attr = nattr
-		}
-		attr = attr[0 : n+1]
-		a := &attr[n]
-		if a.Name, ok = p.nsname(); !ok {
-			if p.err == nil {
-				p.err = p.syntaxError("expected attribute name in element")
-			}
-			return nil, p.err
-		}
-		p.space()
-		if b, ok = p.mustgetc(); !ok {
-			return nil, p.err
-		}
-		if b != '=' {
-			if p.Strict {
-				p.err = p.syntaxError("attribute name without = in element")
-				return nil, p.err
-			} else {
-				p.ungetc(b)
-				a.Value = a.Name.Local
-			}
-		} else {
-			p.space()
-			data := p.attrval()
-			if data == nil {
-				return nil, p.err
-			}
-			a.Value = string(data)
-		}
-	}
-	if empty {
-		p.needClose = true
-		p.toClose = name
-	}
-	return StartElement{name, attr}, nil
-}
-
-func (p *Parser) attrval() []byte {
-	b, ok := p.mustgetc()
-	if !ok {
-		return nil
-	}
-	// Handle quoted attribute values
-	if b == '"' || b == '\'' {
-		return p.text(int(b), false)
-	}
-	// Handle unquoted attribute values for strict parsers
-	if p.Strict {
-		p.err = p.syntaxError("unquoted or missing attribute value in element")
-		return nil
-	}
-	// Handle unquoted attribute values for unstrict parsers
-	p.ungetc(b)
-	p.buf.Reset()
-	for {
-		b, ok = p.mustgetc()
-		if !ok {
-			return nil
-		}
-		// http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
-		if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' ||
-			'0' <= b && b <= '9' || b == '_' || b == ':' || b == '-' {
-			p.buf.WriteByte(b)
-		} else {
-			p.ungetc(b)
-			break
-		}
-	}
-	return p.buf.Bytes()
-}
-
-// Skip spaces if any
-func (p *Parser) space() {
-	for {
-		b, ok := p.getc()
-		if !ok {
-			return
-		}
-		switch b {
-		case ' ', '\r', '\n', '\t':
-		default:
-			p.ungetc(b)
-			return
-		}
-	}
-}
-
-// Read a single byte.
-// If there is no byte to read, return ok==false
-// and leave the error in p.err.
-// Maintain line number.
-func (p *Parser) getc() (b byte, ok bool) {
-	if p.err != nil {
-		return 0, false
-	}
-	if p.nextByte >= 0 {
-		b = byte(p.nextByte)
-		p.nextByte = -1
-	} else {
-		b, p.err = p.r.ReadByte()
-		if p.err != nil {
-			return 0, false
-		}
-		if p.saved != nil {
-			p.saved.WriteByte(b)
-		}
-	}
-	if b == '\n' {
-		p.line++
-	}
-	return b, true
-}
-
-// Return saved offset.
-// If we did ungetc (nextByte >= 0), have to back up one.
-func (p *Parser) savedOffset() int {
-	n := p.saved.Len()
-	if p.nextByte >= 0 {
-		n--
-	}
-	return n
-}
-
-// Must read a single byte.
-// If there is no byte to read,
-// set p.err to SyntaxError("unexpected EOF")
-// and return ok==false
-func (p *Parser) mustgetc() (b byte, ok bool) {
-	if b, ok = p.getc(); !ok {
-		if p.err == os.EOF {
-			p.err = p.syntaxError("unexpected EOF")
-		}
-	}
-	return
-}
-
-// Unread a single byte.
-func (p *Parser) ungetc(b byte) {
-	if b == '\n' {
-		p.line--
-	}
-	p.nextByte = int(b)
-}
-
-var entity = map[string]int{
-	"lt":   '<',
-	"gt":   '>',
-	"amp":  '&',
-	"apos": '\'',
-	"quot": '"',
-}
-
-// Read plain text section (XML calls it character data).
-// If quote >= 0, we are in a quoted string and need to find the matching quote.
-// If cdata == true, we are in a <![CDATA[ section and need to find ]]>.
-// On failure return nil and leave the error in p.err.
-func (p *Parser) text(quote int, cdata bool) []byte {
-	var b0, b1 byte
-	var trunc int
-	p.buf.Reset()
-Input:
-	for {
-		b, ok := p.getc()
-		if !ok {
-			if cdata {
-				if p.err == os.EOF {
-					p.err = p.syntaxError("unexpected EOF in CDATA section")
-				}
-				return nil
-			}
-			break Input
-		}
-
-		// <![CDATA[ section ends with ]]>.
-		// It is an error for ]]> to appear in ordinary text.
-		if b0 == ']' && b1 == ']' && b == '>' {
-			if cdata {
-				trunc = 2
-				break Input
-			}
-			p.err = p.syntaxError("unescaped ]]> not in CDATA section")
-			return nil
-		}
-
-		// Stop reading text if we see a <.
-		if b == '<' && !cdata {
-			if quote >= 0 {
-				p.err = p.syntaxError("unescaped < inside quoted string")
-				return nil
-			}
-			p.ungetc('<')
-			break Input
-		}
-		if quote >= 0 && b == byte(quote) {
-			break Input
-		}
-		if b == '&' && !cdata {
-			// Read escaped character expression up to semicolon.
-			// XML in all its glory allows a document to define and use
-			// its own character names with <!ENTITY ...> directives.
-			// Parsers are required to recognize lt, gt, amp, apos, and quot
-			// even if they have not been declared.  That's all we allow.
-			var i int
-			for i = 0; i < len(p.tmp); i++ {
-				var ok bool
-				p.tmp[i], ok = p.getc()
-				if !ok {
-					if p.err == os.EOF {
-						p.err = p.syntaxError("unexpected EOF")
-					}
-					return nil
-				}
-				c := p.tmp[i]
-				if c == ';' {
-					break
-				}
-				if 'a' <= c && c <= 'z' ||
-					'A' <= c && c <= 'Z' ||
-					'0' <= c && c <= '9' ||
-					c == '_' || c == '#' {
-					continue
-				}
-				p.ungetc(c)
-				break
-			}
-			s := string(p.tmp[0:i])
-			if i >= len(p.tmp) {
-				if !p.Strict {
-					b0, b1 = 0, 0
-					p.buf.WriteByte('&')
-					p.buf.Write(p.tmp[0:i])
-					continue Input
-				}
-				p.err = p.syntaxError("character entity expression &" + s + "... too long")
-				return nil
-			}
-			var haveText bool
-			var text string
-			if i >= 2 && s[0] == '#' {
-				var n uint64
-				var err os.Error
-				if i >= 3 && s[1] == 'x' {
-					n, err = strconv.Btoui64(s[2:], 16)
-				} else {
-					n, err = strconv.Btoui64(s[1:], 10)
-				}
-				if err == nil && n <= unicode.MaxRune {
-					text = string(n)
-					haveText = true
-				}
-			} else {
-				if r, ok := entity[s]; ok {
-					text = string(r)
-					haveText = true
-				} else if p.Entity != nil {
-					text, haveText = p.Entity[s]
-				}
-			}
-			if !haveText {
-				if !p.Strict {
-					b0, b1 = 0, 0
-					p.buf.WriteByte('&')
-					p.buf.Write(p.tmp[0:i])
-					continue Input
-				}
-				p.err = p.syntaxError("invalid character entity &" + s + ";")
-				return nil
-			}
-			p.buf.Write([]byte(text))
-			b0, b1 = 0, 0
-			continue Input
-		}
-		p.buf.WriteByte(b)
-		b0, b1 = b1, b
-	}
-	data := p.buf.Bytes()
-	data = data[0 : len(data)-trunc]
-
-	// Inspect each rune for being a disallowed character.
-	buf := data
-	for len(buf) > 0 {
-		r, size := utf8.DecodeRune(buf)
-		if r == utf8.RuneError && size == 1 {
-			p.err = p.syntaxError("invalid UTF-8")
-			return nil
-		}
-		buf = buf[size:]
-		if !isInCharacterRange(r) {
-			p.err = p.syntaxError(fmt.Sprintf("illegal character code %U", r))
-			return nil
-		}
-	}
-
-	// Must rewrite \r and \r\n into \n.
-	w := 0
-	for r := 0; r < len(data); r++ {
-		b := data[r]
-		if b == '\r' {
-			if r+1 < len(data) && data[r+1] == '\n' {
-				continue
-			}
-			b = '\n'
-		}
-		data[w] = b
-		w++
-	}
-	return data[0:w]
-}
-
-// Decide whether the given rune is in the XML Character Range, per
-// the Char production of http://www.xml.com/axml/testaxml.htm,
-// Section 2.2 Characters.
-func isInCharacterRange(rune int) (inrange bool) {
-	return rune == 0x09 ||
-		rune == 0x0A ||
-		rune == 0x0D ||
-		rune >= 0x20 && rune <= 0xDF77 ||
-		rune >= 0xE000 && rune <= 0xFFFD ||
-		rune >= 0x10000 && rune <= 0x10FFFF
-}
-
-// Get name space name: name with a : stuck in the middle.
-// The part before the : is the name space identifier.
-func (p *Parser) nsname() (name Name, ok bool) {
-	s, ok := p.name()
-	if !ok {
-		return
-	}
-	i := strings.Index(s, ":")
-	if i < 0 {
-		name.Local = s
-	} else {
-		name.Space = s[0:i]
-		name.Local = s[i+1:]
-	}
-	return name, true
-}
-
-// Get name: /first(first|second)*/
-// Do not set p.err if the name is missing (unless unexpected EOF is received):
-// let the caller provide better context.
-func (p *Parser) name() (s string, ok bool) {
-	var b byte
-	if b, ok = p.mustgetc(); !ok {
-		return
-	}
-
-	// As a first approximation, we gather the bytes [A-Za-z_:.-\x80-\xFF]*
-	if b < utf8.RuneSelf && !isNameByte(b) {
-		p.ungetc(b)
-		return "", false
-	}
-	p.buf.Reset()
-	p.buf.WriteByte(b)
-	for {
-		if b, ok = p.mustgetc(); !ok {
-			return
-		}
-		if b < utf8.RuneSelf && !isNameByte(b) {
-			p.ungetc(b)
-			break
-		}
-		p.buf.WriteByte(b)
-	}
-
-	// Then we check the characters.
-	s = p.buf.String()
-	for i, c := range s {
-		if !unicode.Is(first, c) && (i == 0 || !unicode.Is(second, c)) {
-			p.err = p.syntaxError("invalid XML name: " + s)
-			return "", false
-		}
-	}
-	return s, true
-}
-
-func isNameByte(c byte) bool {
-	return 'A' <= c && c <= 'Z' ||
-		'a' <= c && c <= 'z' ||
-		'0' <= c && c <= '9' ||
-		c == '_' || c == ':' || c == '.' || c == '-'
-}
-
-// These tables were generated by cut and paste from Appendix B of
-// the XML spec at http://www.xml.com/axml/testaxml.htm
-// and then reformatting.  First corresponds to (Letter | '_' | ':')
-// and second corresponds to NameChar.
-
-var first = &unicode.RangeTable{
-	R16: []unicode.Range16{
-		{0x003A, 0x003A, 1},
-		{0x0041, 0x005A, 1},
-		{0x005F, 0x005F, 1},
-		{0x0061, 0x007A, 1},
-		{0x00C0, 0x00D6, 1},
-		{0x00D8, 0x00F6, 1},
-		{0x00F8, 0x00FF, 1},
-		{0x0100, 0x0131, 1},
-		{0x0134, 0x013E, 1},
-		{0x0141, 0x0148, 1},
-		{0x014A, 0x017E, 1},
-		{0x0180, 0x01C3, 1},
-		{0x01CD, 0x01F0, 1},
-		{0x01F4, 0x01F5, 1},
-		{0x01FA, 0x0217, 1},
-		{0x0250, 0x02A8, 1},
-		{0x02BB, 0x02C1, 1},
-		{0x0386, 0x0386, 1},
-		{0x0388, 0x038A, 1},
-		{0x038C, 0x038C, 1},
-		{0x038E, 0x03A1, 1},
-		{0x03A3, 0x03CE, 1},
-		{0x03D0, 0x03D6, 1},
-		{0x03DA, 0x03E0, 2},
-		{0x03E2, 0x03F3, 1},
-		{0x0401, 0x040C, 1},
-		{0x040E, 0x044F, 1},
-		{0x0451, 0x045C, 1},
-		{0x045E, 0x0481, 1},
-		{0x0490, 0x04C4, 1},
-		{0x04C7, 0x04C8, 1},
-		{0x04CB, 0x04CC, 1},
-		{0x04D0, 0x04EB, 1},
-		{0x04EE, 0x04F5, 1},
-		{0x04F8, 0x04F9, 1},
-		{0x0531, 0x0556, 1},
-		{0x0559, 0x0559, 1},
-		{0x0561, 0x0586, 1},
-		{0x05D0, 0x05EA, 1},
-		{0x05F0, 0x05F2, 1},
-		{0x0621, 0x063A, 1},
-		{0x0641, 0x064A, 1},
-		{0x0671, 0x06B7, 1},
-		{0x06BA, 0x06BE, 1},
-		{0x06C0, 0x06CE, 1},
-		{0x06D0, 0x06D3, 1},
-		{0x06D5, 0x06D5, 1},
-		{0x06E5, 0x06E6, 1},
-		{0x0905, 0x0939, 1},
-		{0x093D, 0x093D, 1},
-		{0x0958, 0x0961, 1},
-		{0x0985, 0x098C, 1},
-		{0x098F, 0x0990, 1},
-		{0x0993, 0x09A8, 1},
-		{0x09AA, 0x09B0, 1},
-		{0x09B2, 0x09B2, 1},
-		{0x09B6, 0x09B9, 1},
-		{0x09DC, 0x09DD, 1},
-		{0x09DF, 0x09E1, 1},
-		{0x09F0, 0x09F1, 1},
-		{0x0A05, 0x0A0A, 1},
-		{0x0A0F, 0x0A10, 1},
-		{0x0A13, 0x0A28, 1},
-		{0x0A2A, 0x0A30, 1},
-		{0x0A32, 0x0A33, 1},
-		{0x0A35, 0x0A36, 1},
-		{0x0A38, 0x0A39, 1},
-		{0x0A59, 0x0A5C, 1},
-		{0x0A5E, 0x0A5E, 1},
-		{0x0A72, 0x0A74, 1},
-		{0x0A85, 0x0A8B, 1},
-		{0x0A8D, 0x0A8D, 1},
-		{0x0A8F, 0x0A91, 1},
-		{0x0A93, 0x0AA8, 1},
-		{0x0AAA, 0x0AB0, 1},
-		{0x0AB2, 0x0AB3, 1},
-		{0x0AB5, 0x0AB9, 1},
-		{0x0ABD, 0x0AE0, 0x23},
-		{0x0B05, 0x0B0C, 1},
-		{0x0B0F, 0x0B10, 1},
-		{0x0B13, 0x0B28, 1},
-		{0x0B2A, 0x0B30, 1},
-		{0x0B32, 0x0B33, 1},
-		{0x0B36, 0x0B39, 1},
-		{0x0B3D, 0x0B3D, 1},
-		{0x0B5C, 0x0B5D, 1},
-		{0x0B5F, 0x0B61, 1},
-		{0x0B85, 0x0B8A, 1},
-		{0x0B8E, 0x0B90, 1},
-		{0x0B92, 0x0B95, 1},
-		{0x0B99, 0x0B9A, 1},
-		{0x0B9C, 0x0B9C, 1},
-		{0x0B9E, 0x0B9F, 1},
-		{0x0BA3, 0x0BA4, 1},
-		{0x0BA8, 0x0BAA, 1},
-		{0x0BAE, 0x0BB5, 1},
-		{0x0BB7, 0x0BB9, 1},
-		{0x0C05, 0x0C0C, 1},
-		{0x0C0E, 0x0C10, 1},
-		{0x0C12, 0x0C28, 1},
-		{0x0C2A, 0x0C33, 1},
-		{0x0C35, 0x0C39, 1},
-		{0x0C60, 0x0C61, 1},
-		{0x0C85, 0x0C8C, 1},
-		{0x0C8E, 0x0C90, 1},
-		{0x0C92, 0x0CA8, 1},
-		{0x0CAA, 0x0CB3, 1},
-		{0x0CB5, 0x0CB9, 1},
-		{0x0CDE, 0x0CDE, 1},
-		{0x0CE0, 0x0CE1, 1},
-		{0x0D05, 0x0D0C, 1},
-		{0x0D0E, 0x0D10, 1},
-		{0x0D12, 0x0D28, 1},
-		{0x0D2A, 0x0D39, 1},
-		{0x0D60, 0x0D61, 1},
-		{0x0E01, 0x0E2E, 1},
-		{0x0E30, 0x0E30, 1},
-		{0x0E32, 0x0E33, 1},
-		{0x0E40, 0x0E45, 1},
-		{0x0E81, 0x0E82, 1},
-		{0x0E84, 0x0E84, 1},
-		{0x0E87, 0x0E88, 1},
-		{0x0E8A, 0x0E8D, 3},
-		{0x0E94, 0x0E97, 1},
-		{0x0E99, 0x0E9F, 1},
-		{0x0EA1, 0x0EA3, 1},
-		{0x0EA5, 0x0EA7, 2},
-		{0x0EAA, 0x0EAB, 1},
-		{0x0EAD, 0x0EAE, 1},
-		{0x0EB0, 0x0EB0, 1},
-		{0x0EB2, 0x0EB3, 1},
-		{0x0EBD, 0x0EBD, 1},
-		{0x0EC0, 0x0EC4, 1},
-		{0x0F40, 0x0F47, 1},
-		{0x0F49, 0x0F69, 1},
-		{0x10A0, 0x10C5, 1},
-		{0x10D0, 0x10F6, 1},
-		{0x1100, 0x1100, 1},
-		{0x1102, 0x1103, 1},
-		{0x1105, 0x1107, 1},
-		{0x1109, 0x1109, 1},
-		{0x110B, 0x110C, 1},
-		{0x110E, 0x1112, 1},
-		{0x113C, 0x1140, 2},
-		{0x114C, 0x1150, 2},
-		{0x1154, 0x1155, 1},
-		{0x1159, 0x1159, 1},
-		{0x115F, 0x1161, 1},
-		{0x1163, 0x1169, 2},
-		{0x116D, 0x116E, 1},
-		{0x1172, 0x1173, 1},
-		{0x1175, 0x119E, 0x119E - 0x1175},
-		{0x11A8, 0x11AB, 0x11AB - 0x11A8},
-		{0x11AE, 0x11AF, 1},
-		{0x11B7, 0x11B8, 1},
-		{0x11BA, 0x11BA, 1},
-		{0x11BC, 0x11C2, 1},
-		{0x11EB, 0x11F0, 0x11F0 - 0x11EB},
-		{0x11F9, 0x11F9, 1},
-		{0x1E00, 0x1E9B, 1},
-		{0x1EA0, 0x1EF9, 1},
-		{0x1F00, 0x1F15, 1},
-		{0x1F18, 0x1F1D, 1},
-		{0x1F20, 0x1F45, 1},
-		{0x1F48, 0x1F4D, 1},
-		{0x1F50, 0x1F57, 1},
-		{0x1F59, 0x1F5B, 0x1F5B - 0x1F59},
-		{0x1F5D, 0x1F5D, 1},
-		{0x1F5F, 0x1F7D, 1},
-		{0x1F80, 0x1FB4, 1},
-		{0x1FB6, 0x1FBC, 1},
-		{0x1FBE, 0x1FBE, 1},
-		{0x1FC2, 0x1FC4, 1},
-		{0x1FC6, 0x1FCC, 1},
-		{0x1FD0, 0x1FD3, 1},
-		{0x1FD6, 0x1FDB, 1},
-		{0x1FE0, 0x1FEC, 1},
-		{0x1FF2, 0x1FF4, 1},
-		{0x1FF6, 0x1FFC, 1},
-		{0x2126, 0x2126, 1},
-		{0x212A, 0x212B, 1},
-		{0x212E, 0x212E, 1},
-		{0x2180, 0x2182, 1},
-		{0x3007, 0x3007, 1},
-		{0x3021, 0x3029, 1},
-		{0x3041, 0x3094, 1},
-		{0x30A1, 0x30FA, 1},
-		{0x3105, 0x312C, 1},
-		{0x4E00, 0x9FA5, 1},
-		{0xAC00, 0xD7A3, 1},
-	},
-}
-
-var second = &unicode.RangeTable{
-	R16: []unicode.Range16{
-		{0x002D, 0x002E, 1},
-		{0x0030, 0x0039, 1},
-		{0x00B7, 0x00B7, 1},
-		{0x02D0, 0x02D1, 1},
-		{0x0300, 0x0345, 1},
-		{0x0360, 0x0361, 1},
-		{0x0387, 0x0387, 1},
-		{0x0483, 0x0486, 1},
-		{0x0591, 0x05A1, 1},
-		{0x05A3, 0x05B9, 1},
-		{0x05BB, 0x05BD, 1},
-		{0x05BF, 0x05BF, 1},
-		{0x05C1, 0x05C2, 1},
-		{0x05C4, 0x0640, 0x0640 - 0x05C4},
-		{0x064B, 0x0652, 1},
-		{0x0660, 0x0669, 1},
-		{0x0670, 0x0670, 1},
-		{0x06D6, 0x06DC, 1},
-		{0x06DD, 0x06DF, 1},
-		{0x06E0, 0x06E4, 1},
-		{0x06E7, 0x06E8, 1},
-		{0x06EA, 0x06ED, 1},
-		{0x06F0, 0x06F9, 1},
-		{0x0901, 0x0903, 1},
-		{0x093C, 0x093C, 1},
-		{0x093E, 0x094C, 1},
-		{0x094D, 0x094D, 1},
-		{0x0951, 0x0954, 1},
-		{0x0962, 0x0963, 1},
-		{0x0966, 0x096F, 1},
-		{0x0981, 0x0983, 1},
-		{0x09BC, 0x09BC, 1},
-		{0x09BE, 0x09BF, 1},
-		{0x09C0, 0x09C4, 1},
-		{0x09C7, 0x09C8, 1},
-		{0x09CB, 0x09CD, 1},
-		{0x09D7, 0x09D7, 1},
-		{0x09E2, 0x09E3, 1},
-		{0x09E6, 0x09EF, 1},
-		{0x0A02, 0x0A3C, 0x3A},
-		{0x0A3E, 0x0A3F, 1},
-		{0x0A40, 0x0A42, 1},
-		{0x0A47, 0x0A48, 1},
-		{0x0A4B, 0x0A4D, 1},
-		{0x0A66, 0x0A6F, 1},
-		{0x0A70, 0x0A71, 1},
-		{0x0A81, 0x0A83, 1},
-		{0x0ABC, 0x0ABC, 1},
-		{0x0ABE, 0x0AC5, 1},
-		{0x0AC7, 0x0AC9, 1},
-		{0x0ACB, 0x0ACD, 1},
-		{0x0AE6, 0x0AEF, 1},
-		{0x0B01, 0x0B03, 1},
-		{0x0B3C, 0x0B3C, 1},
-		{0x0B3E, 0x0B43, 1},
-		{0x0B47, 0x0B48, 1},
-		{0x0B4B, 0x0B4D, 1},
-		{0x0B56, 0x0B57, 1},
-		{0x0B66, 0x0B6F, 1},
-		{0x0B82, 0x0B83, 1},
-		{0x0BBE, 0x0BC2, 1},
-		{0x0BC6, 0x0BC8, 1},
-		{0x0BCA, 0x0BCD, 1},
-		{0x0BD7, 0x0BD7, 1},
-		{0x0BE7, 0x0BEF, 1},
-		{0x0C01, 0x0C03, 1},
-		{0x0C3E, 0x0C44, 1},
-		{0x0C46, 0x0C48, 1},
-		{0x0C4A, 0x0C4D, 1},
-		{0x0C55, 0x0C56, 1},
-		{0x0C66, 0x0C6F, 1},
-		{0x0C82, 0x0C83, 1},
-		{0x0CBE, 0x0CC4, 1},
-		{0x0CC6, 0x0CC8, 1},
-		{0x0CCA, 0x0CCD, 1},
-		{0x0CD5, 0x0CD6, 1},
-		{0x0CE6, 0x0CEF, 1},
-		{0x0D02, 0x0D03, 1},
-		{0x0D3E, 0x0D43, 1},
-		{0x0D46, 0x0D48, 1},
-		{0x0D4A, 0x0D4D, 1},
-		{0x0D57, 0x0D57, 1},
-		{0x0D66, 0x0D6F, 1},
-		{0x0E31, 0x0E31, 1},
-		{0x0E34, 0x0E3A, 1},
-		{0x0E46, 0x0E46, 1},
-		{0x0E47, 0x0E4E, 1},
-		{0x0E50, 0x0E59, 1},
-		{0x0EB1, 0x0EB1, 1},
-		{0x0EB4, 0x0EB9, 1},
-		{0x0EBB, 0x0EBC, 1},
-		{0x0EC6, 0x0EC6, 1},
-		{0x0EC8, 0x0ECD, 1},
-		{0x0ED0, 0x0ED9, 1},
-		{0x0F18, 0x0F19, 1},
-		{0x0F20, 0x0F29, 1},
-		{0x0F35, 0x0F39, 2},
-		{0x0F3E, 0x0F3F, 1},
-		{0x0F71, 0x0F84, 1},
-		{0x0F86, 0x0F8B, 1},
-		{0x0F90, 0x0F95, 1},
-		{0x0F97, 0x0F97, 1},
-		{0x0F99, 0x0FAD, 1},
-		{0x0FB1, 0x0FB7, 1},
-		{0x0FB9, 0x0FB9, 1},
-		{0x20D0, 0x20DC, 1},
-		{0x20E1, 0x3005, 0x3005 - 0x20E1},
-		{0x302A, 0x302F, 1},
-		{0x3031, 0x3035, 1},
-		{0x3099, 0x309A, 1},
-		{0x309D, 0x309E, 1},
-		{0x30FC, 0x30FE, 1},
-	},
-}
-
-// HTMLEntity is an entity map containing translations for the
-// standard HTML entity characters.
-var HTMLEntity = htmlEntity
-
-var htmlEntity = map[string]string{
-	/*
-		hget http://www.w3.org/TR/html4/sgml/entities.html |
-		ssam '
-			,y /\>/ x/\<(.|\n)+/ s/\n/ /g
-			,x v/^\<!ENTITY/d
-			,s/\<!ENTITY ([^ ]+) .*U\+([0-9A-F][0-9A-F][0-9A-F][0-9A-F]) .+/	"\1": "\\u\2",/g
-		'
-	*/
-	"nbsp":     "\u00A0",
-	"iexcl":    "\u00A1",
-	"cent":     "\u00A2",
-	"pound":    "\u00A3",
-	"curren":   "\u00A4",
-	"yen":      "\u00A5",
-	"brvbar":   "\u00A6",
-	"sect":     "\u00A7",
-	"uml":      "\u00A8",
-	"copy":     "\u00A9",
-	"ordf":     "\u00AA",
-	"laquo":    "\u00AB",
-	"not":      "\u00AC",
-	"shy":      "\u00AD",
-	"reg":      "\u00AE",
-	"macr":     "\u00AF",
-	"deg":      "\u00B0",
-	"plusmn":   "\u00B1",
-	"sup2":     "\u00B2",
-	"sup3":     "\u00B3",
-	"acute":    "\u00B4",
-	"micro":    "\u00B5",
-	"para":     "\u00B6",
-	"middot":   "\u00B7",
-	"cedil":    "\u00B8",
-	"sup1":     "\u00B9",
-	"ordm":     "\u00BA",
-	"raquo":    "\u00BB",
-	"frac14":   "\u00BC",
-	"frac12":   "\u00BD",
-	"frac34":   "\u00BE",
-	"iquest":   "\u00BF",
-	"Agrave":   "\u00C0",
-	"Aacute":   "\u00C1",
-	"Acirc":    "\u00C2",
-	"Atilde":   "\u00C3",
-	"Auml":     "\u00C4",
-	"Aring":    "\u00C5",
-	"AElig":    "\u00C6",
-	"Ccedil":   "\u00C7",
-	"Egrave":   "\u00C8",
-	"Eacute":   "\u00C9",
-	"Ecirc":    "\u00CA",
-	"Euml":     "\u00CB",
-	"Igrave":   "\u00CC",
-	"Iacute":   "\u00CD",
-	"Icirc":    "\u00CE",
-	"Iuml":     "\u00CF",
-	"ETH":      "\u00D0",
-	"Ntilde":   "\u00D1",
-	"Ograve":   "\u00D2",
-	"Oacute":   "\u00D3",
-	"Ocirc":    "\u00D4",
-	"Otilde":   "\u00D5",
-	"Ouml":     "\u00D6",
-	"times":    "\u00D7",
-	"Oslash":   "\u00D8",
-	"Ugrave":   "\u00D9",
-	"Uacute":   "\u00DA",
-	"Ucirc":    "\u00DB",
-	"Uuml":     "\u00DC",
-	"Yacute":   "\u00DD",
-	"THORN":    "\u00DE",
-	"szlig":    "\u00DF",
-	"agrave":   "\u00E0",
-	"aacute":   "\u00E1",
-	"acirc":    "\u00E2",
-	"atilde":   "\u00E3",
-	"auml":     "\u00E4",
-	"aring":    "\u00E5",
-	"aelig":    "\u00E6",
-	"ccedil":   "\u00E7",
-	"egrave":   "\u00E8",
-	"eacute":   "\u00E9",
-	"ecirc":    "\u00EA",
-	"euml":     "\u00EB",
-	"igrave":   "\u00EC",
-	"iacute":   "\u00ED",
-	"icirc":    "\u00EE",
-	"iuml":     "\u00EF",
-	"eth":      "\u00F0",
-	"ntilde":   "\u00F1",
-	"ograve":   "\u00F2",
-	"oacute":   "\u00F3",
-	"ocirc":    "\u00F4",
-	"otilde":   "\u00F5",
-	"ouml":     "\u00F6",
-	"divide":   "\u00F7",
-	"oslash":   "\u00F8",
-	"ugrave":   "\u00F9",
-	"uacute":   "\u00FA",
-	"ucirc":    "\u00FB",
-	"uuml":     "\u00FC",
-	"yacute":   "\u00FD",
-	"thorn":    "\u00FE",
-	"yuml":     "\u00FF",
-	"fnof":     "\u0192",
-	"Alpha":    "\u0391",
-	"Beta":     "\u0392",
-	"Gamma":    "\u0393",
-	"Delta":    "\u0394",
-	"Epsilon":  "\u0395",
-	"Zeta":     "\u0396",
-	"Eta":      "\u0397",
-	"Theta":    "\u0398",
-	"Iota":     "\u0399",
-	"Kappa":    "\u039A",
-	"Lambda":   "\u039B",
-	"Mu":       "\u039C",
-	"Nu":       "\u039D",
-	"Xi":       "\u039E",
-	"Omicron":  "\u039F",
-	"Pi":       "\u03A0",
-	"Rho":      "\u03A1",
-	"Sigma":    "\u03A3",
-	"Tau":      "\u03A4",
-	"Upsilon":  "\u03A5",
-	"Phi":      "\u03A6",
-	"Chi":      "\u03A7",
-	"Psi":      "\u03A8",
-	"Omega":    "\u03A9",
-	"alpha":    "\u03B1",
-	"beta":     "\u03B2",
-	"gamma":    "\u03B3",
-	"delta":    "\u03B4",
-	"epsilon":  "\u03B5",
-	"zeta":     "\u03B6",
-	"eta":      "\u03B7",
-	"theta":    "\u03B8",
-	"iota":     "\u03B9",
-	"kappa":    "\u03BA",
-	"lambda":   "\u03BB",
-	"mu":       "\u03BC",
-	"nu":       "\u03BD",
-	"xi":       "\u03BE",
-	"omicron":  "\u03BF",
-	"pi":       "\u03C0",
-	"rho":      "\u03C1",
-	"sigmaf":   "\u03C2",
-	"sigma":    "\u03C3",
-	"tau":      "\u03C4",
-	"upsilon":  "\u03C5",
-	"phi":      "\u03C6",
-	"chi":      "\u03C7",
-	"psi":      "\u03C8",
-	"omega":    "\u03C9",
-	"thetasym": "\u03D1",
-	"upsih":    "\u03D2",
-	"piv":      "\u03D6",
-	"bull":     "\u2022",
-	"hellip":   "\u2026",
-	"prime":    "\u2032",
-	"Prime":    "\u2033",
-	"oline":    "\u203E",
-	"frasl":    "\u2044",
-	"weierp":   "\u2118",
-	"image":    "\u2111",
-	"real":     "\u211C",
-	"trade":    "\u2122",
-	"alefsym":  "\u2135",
-	"larr":     "\u2190",
-	"uarr":     "\u2191",
-	"rarr":     "\u2192",
-	"darr":     "\u2193",
-	"harr":     "\u2194",
-	"crarr":    "\u21B5",
-	"lArr":     "\u21D0",
-	"uArr":     "\u21D1",
-	"rArr":     "\u21D2",
-	"dArr":     "\u21D3",
-	"hArr":     "\u21D4",
-	"forall":   "\u2200",
-	"part":     "\u2202",
-	"exist":    "\u2203",
-	"empty":    "\u2205",
-	"nabla":    "\u2207",
-	"isin":     "\u2208",
-	"notin":    "\u2209",
-	"ni":       "\u220B",
-	"prod":     "\u220F",
-	"sum":      "\u2211",
-	"minus":    "\u2212",
-	"lowast":   "\u2217",
-	"radic":    "\u221A",
-	"prop":     "\u221D",
-	"infin":    "\u221E",
-	"ang":      "\u2220",
-	"and":      "\u2227",
-	"or":       "\u2228",
-	"cap":      "\u2229",
-	"cup":      "\u222A",
-	"int":      "\u222B",
-	"there4":   "\u2234",
-	"sim":      "\u223C",
-	"cong":     "\u2245",
-	"asymp":    "\u2248",
-	"ne":       "\u2260",
-	"equiv":    "\u2261",
-	"le":       "\u2264",
-	"ge":       "\u2265",
-	"sub":      "\u2282",
-	"sup":      "\u2283",
-	"nsub":     "\u2284",
-	"sube":     "\u2286",
-	"supe":     "\u2287",
-	"oplus":    "\u2295",
-	"otimes":   "\u2297",
-	"perp":     "\u22A5",
-	"sdot":     "\u22C5",
-	"lceil":    "\u2308",
-	"rceil":    "\u2309",
-	"lfloor":   "\u230A",
-	"rfloor":   "\u230B",
-	"lang":     "\u2329",
-	"rang":     "\u232A",
-	"loz":      "\u25CA",
-	"spades":   "\u2660",
-	"clubs":    "\u2663",
-	"hearts":   "\u2665",
-	"diams":    "\u2666",
-	"quot":     "\u0022",
-	"amp":      "\u0026",
-	"lt":       "\u003C",
-	"gt":       "\u003E",
-	"OElig":    "\u0152",
-	"oelig":    "\u0153",
-	"Scaron":   "\u0160",
-	"scaron":   "\u0161",
-	"Yuml":     "\u0178",
-	"circ":     "\u02C6",
-	"tilde":    "\u02DC",
-	"ensp":     "\u2002",
-	"emsp":     "\u2003",
-	"thinsp":   "\u2009",
-	"zwnj":     "\u200C",
-	"zwj":      "\u200D",
-	"lrm":      "\u200E",
-	"rlm":      "\u200F",
-	"ndash":    "\u2013",
-	"mdash":    "\u2014",
-	"lsquo":    "\u2018",
-	"rsquo":    "\u2019",
-	"sbquo":    "\u201A",
-	"ldquo":    "\u201C",
-	"rdquo":    "\u201D",
-	"bdquo":    "\u201E",
-	"dagger":   "\u2020",
-	"Dagger":   "\u2021",
-	"permil":   "\u2030",
-	"lsaquo":   "\u2039",
-	"rsaquo":   "\u203A",
-	"euro":     "\u20AC",
-}
-
-// HTMLAutoClose is the set of HTML elements that
-// should be considered to close automatically.
-var HTMLAutoClose = htmlAutoClose
-
-var htmlAutoClose = []string{
-	/*
-		hget http://www.w3.org/TR/html4/loose.dtd |
-		9 sed -n 's/<!ELEMENT (.*) - O EMPTY.+/	"\1",/p' | tr A-Z a-z
-	*/
-	"basefont",
-	"br",
-	"area",
-	"link",
-	"img",
-	"param",
-	"hr",
-	"input",
-	"col     ",
-	"frame",
-	"isindex",
-	"base",
-	"meta",
-}
-
-var (
-	esc_quot = []byte(""") // shorter than """
-	esc_apos = []byte("'") // shorter than "'"
-	esc_amp  = []byte("&")
-	esc_lt   = []byte("<")
-	esc_gt   = []byte(">")
-)
-
-// Escape writes to w the properly escaped XML equivalent
-// of the plain text data s.
-func Escape(w io.Writer, s []byte) {
-	var esc []byte
-	last := 0
-	for i, c := range s {
-		switch c {
-		case '"':
-			esc = esc_quot
-		case '\'':
-			esc = esc_apos
-		case '&':
-			esc = esc_amp
-		case '<':
-			esc = esc_lt
-		case '>':
-			esc = esc_gt
-		default:
-			continue
-		}
-		w.Write(s[last:i])
-		w.Write(esc)
-		last = i + 1
-	}
-	w.Write(s[last:])
-}
-
-// procInstEncoding parses the `encoding="..."` or `encoding='...'`
-// value out of the provided string, returning "" if not found.
-func procInstEncoding(s string) string {
-	// TODO: this parsing is somewhat lame and not exact.
-	// It works for all actual cases, though.
-	idx := strings.Index(s, "encoding=")
-	if idx == -1 {
-		return ""
-	}
-	v := s[idx+len("encoding="):]
-	if v == "" {
-		return ""
-	}
-	if v[0] != '\'' && v[0] != '"' {
-		return ""
-	}
-	idx = strings.IndexRune(v[1:], int(v[0]))
-	if idx == -1 {
-		return ""
-	}
-	return v[1 : idx+1]
-}
diff --git a/src/pkg/xml/xml_test.go b/src/pkg/xml/xml_test.go
deleted file mode 100644
index 6407624..0000000
--- a/src/pkg/xml/xml_test.go
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package xml
-
-import (
-	"bytes"
-	"io"
-	"os"
-	"reflect"
-	"strings"
-	"testing"
-)
-
-const testInput = `
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<body xmlns:foo="ns1" xmlns="ns2" xmlns:tag="ns3" ` +
-	"\r\n\t" + `  >
-  <hello lang="en">World <>'" &#x767d;鵬ç¿”</hello>
-  <goodbye />
-  <outer foo:attr="value" xmlns:tag="ns4">
-    <inner/>
-  </outer>
-  <tag:name>
-    <![CDATA[Some text here.]]>
-  </tag:name>
-</body><!-- missing final newline -->`
-
-var rawTokens = []Token{
-	CharData([]byte("\n")),
-	ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`),
-	),
-	CharData([]byte("\n")),
-	StartElement{Name{"", "body"}, []Attr{{Name{"xmlns", "foo"}, "ns1"}, {Name{"", "xmlns"}, "ns2"}, {Name{"xmlns", "tag"}, "ns3"}}},
-	CharData([]byte("\n  ")),
-	StartElement{Name{"", "hello"}, []Attr{{Name{"", "lang"}, "en"}}},
-	CharData([]byte("World <>'\" 白鵬翔")),
-	EndElement{Name{"", "hello"}},
-	CharData([]byte("\n  ")),
-	StartElement{Name{"", "goodbye"}, nil},
-	EndElement{Name{"", "goodbye"}},
-	CharData([]byte("\n  ")),
-	StartElement{Name{"", "outer"}, []Attr{{Name{"foo", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
-	CharData([]byte("\n    ")),
-	StartElement{Name{"", "inner"}, nil},
-	EndElement{Name{"", "inner"}},
-	CharData([]byte("\n  ")),
-	EndElement{Name{"", "outer"}},
-	CharData([]byte("\n  ")),
-	StartElement{Name{"tag", "name"}, nil},
-	CharData([]byte("\n    ")),
-	CharData([]byte("Some text here.")),
-	CharData([]byte("\n  ")),
-	EndElement{Name{"tag", "name"}},
-	CharData([]byte("\n")),
-	EndElement{Name{"", "body"}},
-	Comment([]byte(" missing final newline ")),
-}
-
-var cookedTokens = []Token{
-	CharData([]byte("\n")),
-	ProcInst{"xml", []byte(`version="1.0" encoding="UTF-8"`)},
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"`),
-	),
-	CharData([]byte("\n")),
-	StartElement{Name{"ns2", "body"}, []Attr{{Name{"xmlns", "foo"}, "ns1"}, {Name{"", "xmlns"}, "ns2"}, {Name{"xmlns", "tag"}, "ns3"}}},
-	CharData([]byte("\n  ")),
-	StartElement{Name{"ns2", "hello"}, []Attr{{Name{"", "lang"}, "en"}}},
-	CharData([]byte("World <>'\" 白鵬翔")),
-	EndElement{Name{"ns2", "hello"}},
-	CharData([]byte("\n  ")),
-	StartElement{Name{"ns2", "goodbye"}, nil},
-	EndElement{Name{"ns2", "goodbye"}},
-	CharData([]byte("\n  ")),
-	StartElement{Name{"ns2", "outer"}, []Attr{{Name{"ns1", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
-	CharData([]byte("\n    ")),
-	StartElement{Name{"ns2", "inner"}, nil},
-	EndElement{Name{"ns2", "inner"}},
-	CharData([]byte("\n  ")),
-	EndElement{Name{"ns2", "outer"}},
-	CharData([]byte("\n  ")),
-	StartElement{Name{"ns3", "name"}, nil},
-	CharData([]byte("\n    ")),
-	CharData([]byte("Some text here.")),
-	CharData([]byte("\n  ")),
-	EndElement{Name{"ns3", "name"}},
-	CharData([]byte("\n")),
-	EndElement{Name{"ns2", "body"}},
-	Comment([]byte(" missing final newline ")),
-}
-
-const testInputAltEncoding = `
-<?xml version="1.0" encoding="x-testing-uppercase"?>
-<TAG>VALUE</TAG>`
-
-var rawTokensAltEncoding = []Token{
-	CharData([]byte("\n")),
-	ProcInst{"xml", []byte(`version="1.0" encoding="x-testing-uppercase"`)},
-	CharData([]byte("\n")),
-	StartElement{Name{"", "tag"}, nil},
-	CharData([]byte("value")),
-	EndElement{Name{"", "tag"}},
-}
-
-var xmlInput = []string{
-	// unexpected EOF cases
-	"<",
-	"<t",
-	"<t ",
-	"<t/",
-	"<!",
-	"<!-",
-	"<!--",
-	"<!--c-",
-	"<!--c--",
-	"<!d",
-	"<t></",
-	"<t></t",
-	"<?",
-	"<?p",
-	"<t a",
-	"<t a=",
-	"<t a='",
-	"<t a=''",
-	"<t/><![",
-	"<t/><![C",
-	"<t/><![CDATA[d",
-	"<t/><![CDATA[d]",
-	"<t/><![CDATA[d]]",
-
-	// other Syntax errors
-	"<>",
-	"<t/a",
-	"<0 />",
-	"<?0 >",
-	//	"<!0 >",	// let the Token() caller handle
-	"</0>",
-	"<t 0=''>",
-	"<t a='&'>",
-	"<t a='<'>",
-	"<t> c;</t>",
-	"<t a>",
-	"<t a=>",
-	"<t a=v>",
-	//	"<![CDATA[d]]>",	// let the Token() caller handle
-	"<t></e>",
-	"<t></>",
-	"<t></t!",
-	"<t>cdata]]></t>",
-}
-
-type stringReader struct {
-	s   string
-	off int
-}
-
-func (r *stringReader) Read(b []byte) (n int, err os.Error) {
-	if r.off >= len(r.s) {
-		return 0, os.EOF
-	}
-	for r.off < len(r.s) && n < len(b) {
-		b[n] = r.s[r.off]
-		n++
-		r.off++
-	}
-	return
-}
-
-func (r *stringReader) ReadByte() (b byte, err os.Error) {
-	if r.off >= len(r.s) {
-		return 0, os.EOF
-	}
-	b = r.s[r.off]
-	r.off++
-	return
-}
-
-func StringReader(s string) io.Reader { return &stringReader{s, 0} }
-
-func TestRawToken(t *testing.T) {
-	p := NewParser(StringReader(testInput))
-	testRawToken(t, p, rawTokens)
-}
-
-type downCaser struct {
-	t *testing.T
-	r io.ByteReader
-}
-
-func (d *downCaser) ReadByte() (c byte, err os.Error) {
-	c, err = d.r.ReadByte()
-	if c >= 'A' && c <= 'Z' {
-		c += 'a' - 'A'
-	}
-	return
-}
-
-func (d *downCaser) Read(p []byte) (int, os.Error) {
-	d.t.Fatalf("unexpected Read call on downCaser reader")
-	return 0, os.EINVAL
-}
-
-func TestRawTokenAltEncoding(t *testing.T) {
-	sawEncoding := ""
-	p := NewParser(StringReader(testInputAltEncoding))
-	p.CharsetReader = func(charset string, input io.Reader) (io.Reader, os.Error) {
-		sawEncoding = charset
-		if charset != "x-testing-uppercase" {
-			t.Fatalf("unexpected charset %q", charset)
-		}
-		return &downCaser{t, input.(io.ByteReader)}, nil
-	}
-	testRawToken(t, p, rawTokensAltEncoding)
-}
-
-func TestRawTokenAltEncodingNoConverter(t *testing.T) {
-	p := NewParser(StringReader(testInputAltEncoding))
-	token, err := p.RawToken()
-	if token == nil {
-		t.Fatalf("expected a token on first RawToken call")
-	}
-	if err != nil {
-		t.Fatal(err)
-	}
-	token, err = p.RawToken()
-	if token != nil {
-		t.Errorf("expected a nil token; got %#v", token)
-	}
-	if err == nil {
-		t.Fatalf("expected an error on second RawToken call")
-	}
-	const encoding = "x-testing-uppercase"
-	if !strings.Contains(err.String(), encoding) {
-		t.Errorf("expected error to contain %q; got error: %v",
-			encoding, err)
-	}
-}
-
-func testRawToken(t *testing.T, p *Parser, rawTokens []Token) {
-	for i, want := range rawTokens {
-		have, err := p.RawToken()
-		if err != nil {
-			t.Fatalf("token %d: unexpected error: %s", i, err)
-		}
-		if !reflect.DeepEqual(have, want) {
-			t.Errorf("token %d = %#v want %#v", i, have, want)
-		}
-	}
-}
-
-// Ensure that directives (specifically !DOCTYPE) include the complete
-// text of any nested directives, noting that < and > do not change
-// nesting depth if they are in single or double quotes.
-
-var nestedDirectivesInput = `
-<!DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]>
-<!DOCTYPE [<!ENTITY xlt ">">]>
-<!DOCTYPE [<!ENTITY xlt "<">]>
-<!DOCTYPE [<!ENTITY xlt '>'>]>
-<!DOCTYPE [<!ENTITY xlt '<'>]>
-<!DOCTYPE [<!ENTITY xlt '">'>]>
-<!DOCTYPE [<!ENTITY xlt "'<">]>
-`
-
-var nestedDirectivesTokens = []Token{
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`)),
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE [<!ENTITY xlt ">">]`)),
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE [<!ENTITY xlt "<">]`)),
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE [<!ENTITY xlt '>'>]`)),
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE [<!ENTITY xlt '<'>]`)),
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE [<!ENTITY xlt '">'>]`)),
-	CharData([]byte("\n")),
-	Directive([]byte(`DOCTYPE [<!ENTITY xlt "'<">]`)),
-	CharData([]byte("\n")),
-}
-
-func TestNestedDirectives(t *testing.T) {
-	p := NewParser(StringReader(nestedDirectivesInput))
-
-	for i, want := range nestedDirectivesTokens {
-		have, err := p.Token()
-		if err != nil {
-			t.Fatalf("token %d: unexpected error: %s", i, err)
-		}
-		if !reflect.DeepEqual(have, want) {
-			t.Errorf("token %d = %#v want %#v", i, have, want)
-		}
-	}
-}
-
-func TestToken(t *testing.T) {
-	p := NewParser(StringReader(testInput))
-
-	for i, want := range cookedTokens {
-		have, err := p.Token()
-		if err != nil {
-			t.Fatalf("token %d: unexpected error: %s", i, err)
-		}
-		if !reflect.DeepEqual(have, want) {
-			t.Errorf("token %d = %#v want %#v", i, have, want)
-		}
-	}
-}
-
-func TestSyntax(t *testing.T) {
-	for i := range xmlInput {
-		p := NewParser(StringReader(xmlInput[i]))
-		var err os.Error
-		for _, err = p.Token(); err == nil; _, err = p.Token() {
-		}
-		if _, ok := err.(*SyntaxError); !ok {
-			t.Fatalf(`xmlInput "%s": expected SyntaxError not received`, xmlInput[i])
-		}
-	}
-}
-
-type allScalars struct {
-	True1     bool
-	True2     bool
-	False1    bool
-	False2    bool
-	Int       int
-	Int8      int8
-	Int16     int16
-	Int32     int32
-	Int64     int64
-	Uint      int
-	Uint8     uint8
-	Uint16    uint16
-	Uint32    uint32
-	Uint64    uint64
-	Uintptr   uintptr
-	Float32   float32
-	Float64   float64
-	String    string
-	PtrString *string
-}
-
-var all = allScalars{
-	True1:     true,
-	True2:     true,
-	False1:    false,
-	False2:    false,
-	Int:       1,
-	Int8:      -2,
-	Int16:     3,
-	Int32:     -4,
-	Int64:     5,
-	Uint:      6,
-	Uint8:     7,
-	Uint16:    8,
-	Uint32:    9,
-	Uint64:    10,
-	Uintptr:   11,
-	Float32:   13.0,
-	Float64:   14.0,
-	String:    "15",
-	PtrString: &sixteen,
-}
-
-var sixteen = "16"
-
-const testScalarsInput = `<allscalars>
-	<true1>true</true1>
-	<true2>1</true2>
-	<false1>false</false1>
-	<false2>0</false2>
-	<int>1</int>
-	<int8>-2</int8>
-	<int16>3</int16>
-	<int32>-4</int32>
-	<int64>5</int64>
-	<uint>6</uint>
-	<uint8>7</uint8>
-	<uint16>8</uint16>
-	<uint32>9</uint32>
-	<uint64>10</uint64>
-	<uintptr>11</uintptr>
-	<float>12.0</float>
-	<float32>13.0</float32>
-	<float64>14.0</float64>
-	<string>15</string>
-	<ptrstring>16</ptrstring>
-</allscalars>`
-
-func TestAllScalars(t *testing.T) {
-	var a allScalars
-	buf := bytes.NewBufferString(testScalarsInput)
-	err := Unmarshal(buf, &a)
-
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !reflect.DeepEqual(a, all) {
-		t.Errorf("have %+v want %+v", a, all)
-	}
-}
-
-type item struct {
-	Field_a string
-}
-
-func TestIssue569(t *testing.T) {
-	data := `<item><field_a>abcd</field_a></item>`
-	var i item
-	buf := bytes.NewBufferString(data)
-	err := Unmarshal(buf, &i)
-
-	if err != nil || i.Field_a != "abcd" {
-		t.Fatal("Expecting abcd")
-	}
-}
-
-func TestUnquotedAttrs(t *testing.T) {
-	data := "<tag attr=azAZ09:-_\t>"
-	p := NewParser(StringReader(data))
-	p.Strict = false
-	token, err := p.Token()
-	if _, ok := err.(*SyntaxError); ok {
-		t.Errorf("Unexpected error: %v", err)
-	}
-	if token.(StartElement).Name.Local != "tag" {
-		t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
-	}
-	attr := token.(StartElement).Attr[0]
-	if attr.Value != "azAZ09:-_" {
-		t.Errorf("Unexpected attribute value: %v", attr.Value)
-	}
-	if attr.Name.Local != "attr" {
-		t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
-	}
-}
-
-func TestValuelessAttrs(t *testing.T) {
-	tests := [][3]string{
-		{"<p nowrap>", "p", "nowrap"},
-		{"<p nowrap >", "p", "nowrap"},
-		{"<input checked/>", "input", "checked"},
-		{"<input checked />", "input", "checked"},
-	}
-	for _, test := range tests {
-		p := NewParser(StringReader(test[0]))
-		p.Strict = false
-		token, err := p.Token()
-		if _, ok := err.(*SyntaxError); ok {
-			t.Errorf("Unexpected error: %v", err)
-		}
-		if token.(StartElement).Name.Local != test[1] {
-			t.Errorf("Unexpected tag name: %v", token.(StartElement).Name.Local)
-		}
-		attr := token.(StartElement).Attr[0]
-		if attr.Value != test[2] {
-			t.Errorf("Unexpected attribute value: %v", attr.Value)
-		}
-		if attr.Name.Local != test[2] {
-			t.Errorf("Unexpected attribute name: %v", attr.Name.Local)
-		}
-	}
-}
-
-func TestCopyTokenCharData(t *testing.T) {
-	data := []byte("same data")
-	var tok1 Token = CharData(data)
-	tok2 := CopyToken(tok1)
-	if !reflect.DeepEqual(tok1, tok2) {
-		t.Error("CopyToken(CharData) != CharData")
-	}
-	data[1] = 'o'
-	if reflect.DeepEqual(tok1, tok2) {
-		t.Error("CopyToken(CharData) uses same buffer.")
-	}
-}
-
-func TestCopyTokenStartElement(t *testing.T) {
-	elt := StartElement{Name{"", "hello"}, []Attr{{Name{"", "lang"}, "en"}}}
-	var tok1 Token = elt
-	tok2 := CopyToken(tok1)
-	if !reflect.DeepEqual(tok1, tok2) {
-		t.Error("CopyToken(StartElement) != StartElement")
-	}
-	elt.Attr[0] = Attr{Name{"", "lang"}, "de"}
-	if reflect.DeepEqual(tok1, tok2) {
-		t.Error("CopyToken(CharData) uses same buffer.")
-	}
-}
-
-func TestSyntaxErrorLineNum(t *testing.T) {
-	testInput := "<P>Foo<P>\n\n<P>Bar</>\n"
-	p := NewParser(StringReader(testInput))
-	var err os.Error
-	for _, err = p.Token(); err == nil; _, err = p.Token() {
-	}
-	synerr, ok := err.(*SyntaxError)
-	if !ok {
-		t.Error("Expected SyntaxError.")
-	}
-	if synerr.Line != 3 {
-		t.Error("SyntaxError didn't have correct line number.")
-	}
-}
-
-func TestTrailingRawToken(t *testing.T) {
-	input := `<FOO></FOO>  `
-	p := NewParser(StringReader(input))
-	var err os.Error
-	for _, err = p.RawToken(); err == nil; _, err = p.RawToken() {
-	}
-	if err != os.EOF {
-		t.Fatalf("p.RawToken() = _, %v, want _, os.EOF", err)
-	}
-}
-
-func TestTrailingToken(t *testing.T) {
-	input := `<FOO></FOO>  `
-	p := NewParser(StringReader(input))
-	var err os.Error
-	for _, err = p.Token(); err == nil; _, err = p.Token() {
-	}
-	if err != os.EOF {
-		t.Fatalf("p.Token() = _, %v, want _, os.EOF", err)
-	}
-}
-
-func TestEntityInsideCDATA(t *testing.T) {
-	input := `<test><![CDATA[ &val=foo ]]></test>`
-	p := NewParser(StringReader(input))
-	var err os.Error
-	for _, err = p.Token(); err == nil; _, err = p.Token() {
-	}
-	if err != os.EOF {
-		t.Fatalf("p.Token() = _, %v, want _, os.EOF", err)
-	}
-}
-
-// The last three tests (respectively one for characters in attribute
-// names and two for character entities) pass not because of code
-// changed for issue 1259, but instead pass with the given messages
-// from other parts of xml.Parser.  I provide these to note the
-// current behavior of situations where one might think that character
-// range checking would detect the error, but it does not in fact.
-
-var characterTests = []struct {
-	in  string
-	err string
-}{
-	{"\x12<doc/>", "illegal character code U+0012"},
-	{"<?xml version=\"1.0\"?>\x0b<doc/>", "illegal character code U+000B"},
-	{"\xef\xbf\xbe<doc/>", "illegal character code U+FFFE"},
-	{"<?xml version=\"1.0\"?><doc>\r\n<hiya/>\x07<toots/></doc>", "illegal character code U+0007"},
-	{"<?xml version=\"1.0\"?><doc \x12='value'>what's up</doc>", "expected attribute name in element"},
-	{"<doc>&\x01;</doc>", "invalid character entity &;"},
-	{"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &;"},
-}
-
-func TestDisallowedCharacters(t *testing.T) {
-
-	for i, tt := range characterTests {
-		p := NewParser(StringReader(tt.in))
-		var err os.Error
-
-		for err == nil {
-			_, err = p.Token()
-		}
-		synerr, ok := err.(*SyntaxError)
-		if !ok {
-			t.Fatalf("input %d p.Token() = _, %v, want _, *SyntaxError", i, err)
-		}
-		if synerr.Msg != tt.err {
-			t.Fatalf("input %d synerr.Msg wrong: want '%s', got '%s'", i, tt.err, synerr.Msg)
-		}
-	}
-}
-
-type procInstEncodingTest struct {
-	expect, got string
-}
-
-var procInstTests = []struct {
-	input, expect string
-}{
-	{`version="1.0" encoding="utf-8"`, "utf-8"},
-	{`version="1.0" encoding='utf-8'`, "utf-8"},
-	{`version="1.0" encoding='utf-8' `, "utf-8"},
-	{`version="1.0" encoding=utf-8`, ""},
-	{`encoding="FOO" `, "FOO"},
-}
-
-func TestProcInstEncoding(t *testing.T) {
-	for _, test := range procInstTests {
-		got := procInstEncoding(test.input)
-		if got != test.expect {
-			t.Errorf("procInstEncoding(%q) = %q; want %q", test.input, got, test.expect)
-		}
-	}
-}
diff --git a/src/run.bash b/src/run.bash
index a9689bf..8cc04a7 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -31,21 +31,55 @@ xcd() {
 }
 
 if $rebuild; then
+	if $USE_GO_TOOL; then
+		echo
+		echo '# Package builds'
+		time go install -a -v std
+	else
+		(xcd pkg
+			gomake clean
+			time gomake install
+		) || exit $?
+	fi
+fi
+
+if $USE_GO_TOOL; then
+	echo
+	echo '# Package tests'
+	time go test std -short
+else
 	(xcd pkg
-		gomake clean
-		time gomake install
+	gomake testshort
 	) || exit $?
 fi
 
-(xcd pkg
-gomake testshort
-) || exit $?
+if $USE_GO_TOOL; then
+	echo
+	echo '# runtime -cpu=1,2,4'
+	go test runtime -short -cpu=1,2,4
+else
+	(xcd pkg/runtime;
+	gotest -short -cpu=1,2,4
+	) || exit $?
+fi
 
-(xcd pkg/sync;
-GOMAXPROCS=10 gomake testshort
-) || exit $?
+if $USE_GO_TOOL; then
+	echo
+	echo '# sync -cpu=10'
+	go test sync -short -cpu=10
+else
+	(xcd pkg/sync;
+	GOMAXPROCS=10 gomake testshort
+	) || exit $?
+fi
 
-(xcd cmd/ebnflint
+if $USE_GO_TOOL; then
+	echo
+	echo '# Build bootstrap scripts'
+	./buildscript.sh
+fi
+
+(xcd pkg/exp/ebnflint
 time gomake test
 ) || exit $?
 
@@ -63,12 +97,19 @@ gomake clean
 ) || exit $?
 
 [ "$CGO_ENABLED" != 1 ] ||
-[ "$GOHOSTOS" == windows ] ||
 (xcd ../misc/cgo/test
 gomake clean
 gotest
 ) || exit $?
 
+[ "$CGO_ENABLED" != 1 ] ||
+[ "$GOHOSTOS" == windows ] ||
+[ "$GOHOSTOS" == darwin ] ||
+(xcd ../misc/cgo/testso
+gomake clean
+./test.bash
+) || exit $?
+
 (xcd ../doc/progs
 time ./run
 ) || exit $?
@@ -89,11 +130,14 @@ do
 done
 
 [ "$GOARCH" == arm ] ||
-(xcd ../test/bench
+(xcd ../test/bench/shootout
 ./timing.sh -test
 ) || exit $?
 
-[ "$GOHOSTOS" == windows ] ||
+(xcd ../test/bench/go1
+gomake test
+) || exit $?
+
 (xcd ../test
 ./run
 ) || exit $?
diff --git a/test/alias.go b/test/alias.go
new file mode 100644
index 0000000..639a9ca
--- /dev/null
+++ b/test/alias.go
@@ -0,0 +1,32 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 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
+
+// Test that error messages say what the source file says
+// (uint8 vs byte, int32 vs. rune).
+
+import (
+	"fmt"
+	"unicode/utf8"
+)
+
+func f(byte)  {}
+func g(uint8) {}
+
+func main() {
+	var x float64
+	f(x) // ERROR "byte"
+	g(x) // ERROR "uint8"
+
+	// Test across imports.
+
+	var ff fmt.Formatter
+	var fs fmt.State
+	ff.Format(fs, x) // ERROR "rune"
+
+	utf8.RuneStart(x) // ERROR "byte"
+}
diff --git a/test/alias1.go b/test/alias1.go
new file mode 100644
index 0000000..e8ef8a2
--- /dev/null
+++ b/test/alias1.go
@@ -0,0 +1,54 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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
+
+// Test that dynamic interface checks treat byte=uint8
+// and rune=int or rune=int32.
+
+func main() {
+	var x interface{}
+
+	x = byte(1)
+	switch x.(type) {
+	case uint8:
+		// ok
+	default:
+		println("byte != uint8")
+	}
+
+	x = uint8(2)
+	switch x.(type) {
+	case byte:
+		// ok
+	default:
+		println("uint8 != byte")
+	}
+
+	rune32 := false
+	x = rune(3)
+	switch x.(type) {
+	case int:
+		// ok
+	case int32:
+		// must be new code
+		rune32 = true
+	default:
+		println("rune != int and rune != int32")
+	}
+
+	if rune32 {
+		x = int32(4)
+	} else {
+		x = int(5)
+	}
+	switch x.(type) {
+	case rune:
+		// ok
+	default:
+		println("int (or int32) != rune")
+	}
+}
diff --git a/test/append.go b/test/append.go
index 96421c3..e178f46 100644
--- a/test/append.go
+++ b/test/append.go
@@ -63,6 +63,11 @@ var tests = []struct {
 	{"byte i", append([]byte{0, 1, 2}, []byte{3}...), []byte{0, 1, 2, 3}},
 	{"byte j", append([]byte{0, 1, 2}, []byte{3, 4, 5}...), []byte{0, 1, 2, 3, 4, 5}},
 
+	{"bytestr a", append([]byte{}, "0"...), []byte("0")},
+	{"bytestr b", append([]byte{}, "0123"...), []byte("0123")},
+
+	{"bytestr c", append([]byte("012"), "3"...), []byte("0123")},
+	{"bytestr d", append([]byte("012"), "345"...), []byte("012345")},
 
 	{"int16 a", append([]int16{}), []int16{}},
 	{"int16 b", append([]int16{}, 0), []int16{0}},
diff --git a/test/assign.go b/test/assign.go
index 5947138..2192f9e 100644
--- a/test/assign.go
+++ b/test/assign.go
@@ -16,38 +16,38 @@ type T struct {
 func main() {
 	{
 		var x, y sync.Mutex
-		x = y	// ERROR "assignment.*Mutex"
+		x = y // ok
 		_ = x
 	}
 	{
 		var x, y T
-		x = y	// ERROR "assignment.*Mutex"
+		x = y // ok
 		_ = x
 	}
 	{
 		var x, y [2]sync.Mutex
-		x = y	// ERROR "assignment.*Mutex"
+		x = y // ok
 		_ = x
 	}
 	{
 		var x, y [2]T
-		x = y	// ERROR "assignment.*Mutex"
+		x = y // ok
 		_ = x
 	}
 	{
-		x := sync.Mutex{0, 0}	// ERROR "assignment.*Mutex"
+		x := sync.Mutex{0, 0} // ERROR "assignment.*Mutex"
 		_ = x
 	}
 	{
-		x := sync.Mutex{key: 0}	// ERROR "(unknown|assignment).*Mutex"
+		x := sync.Mutex{key: 0} // ERROR "(unknown|assignment).*Mutex"
 		_ = x
 	}
 	{
-		x := &sync.Mutex{}	// ok
-		var y sync.Mutex	// ok
-		y = *x	// ERROR "assignment.*Mutex"
-		*x = y	// ERROR "assignment.*Mutex"
+		x := &sync.Mutex{} // ok
+		var y sync.Mutex   // ok
+		y = *x             // ok
+		*x = y             // ok
 		_ = x
 		_ = y
-	}		
+	}
 }
diff --git a/test/bench/Makefile b/test/bench/Makefile
deleted file mode 100644
index 145fe0c..0000000
--- a/test/bench/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2011 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../src/Make.inc
-
-all:
-	@echo "make clean or timing"
-
-timing:
-	./timing.sh
-
-clean:
-	rm -f [568].out *.[568]
diff --git a/test/bench/chameneosredux.go b/test/bench/chameneosredux.go
deleted file mode 100644
index 2cb1440..0000000
--- a/test/bench/chameneosredux.go
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"strconv"
-)
-
-const (
-	blue = iota
-	red
-	yellow
-	ncol
-)
-
-var complement = [...]int{
-	red | red<<2: red,
-	red | yellow<<2: blue,
-	red | blue<<2: yellow,
-	yellow | red<<2: blue,
-	yellow | yellow<<2: yellow,
-	yellow | blue<<2: red,
-	blue | red<<2: yellow,
-	blue | yellow<<2: red,
-	blue | blue<<2: blue,
-}
-
-var colname = [...]string{
-	blue: "blue",
-	red: "red",
-	yellow: "yellow",
-}
-
-// information about the current state of a creature.
-type info struct {
-	colour int // creature's current colour.
-	name   int // creature's name.
-}
-
-// exclusive access data-structure kept inside meetingplace.
-// if mate is nil, it indicates there's no creature currently waiting;
-// otherwise the creature's info is stored in info, and
-// it is waiting to receive its mate's information on the mate channel.
-type rendez struct {
-	n    int         // current number of encounters.
-	mate chan<- info // creature waiting when non-nil.
-	info info        // info about creature waiting.
-}
-
-// result sent by each creature at the end of processing.
-type result struct {
-	met  int
-	same int
-}
-
-var n = 600
-
-func main() {
-	flag.Parse()
-	if flag.NArg() > 0 {
-		n, _ = strconv.Atoi(flag.Arg(0))
-	}
-
-	for c0 := 0; c0 < ncol; c0++ {
-		for c1 := 0; c1 < ncol; c1++ {
-			fmt.Printf("%s + %s -> %s\n", colname[c0], colname[c1], colname[complement[c0|c1<<2]])
-		}
-	}
-	fmt.Print("\n")
-
-	pallmall([]int{blue, red, yellow})
-	pallmall([]int{blue, red, yellow, red, yellow, blue, red, yellow, red, blue})
-}
-
-func pallmall(cols []int) {
-
-	// invariant: meetingplace always contains a value unless a creature
-	// is currently dealing with it (whereupon it must put it back).
-	meetingplace := make(chan rendez, 1)
-	meetingplace <- rendez{n: 0}
-
-	ended := make(chan result)
-	msg := ""
-	for i, col := range cols {
-		go creature(info{col, i}, meetingplace, ended)
-		msg += " " + colname[col]
-	}
-	fmt.Println(msg)
-	tot := 0
-	// wait for all results
-	for _ = range cols {
-		result := <-ended
-		tot += result.met
-		fmt.Printf("%v%v\n", result.met, spell(result.same, true))
-	}
-	fmt.Printf("%v\n\n", spell(tot, true))
-}
-
-// in this function, variables ending in 0 refer to the local creature,
-// variables ending in 1 to the creature we've met.
-func creature(info0 info, meetingplace chan rendez, ended chan result) {
-	c0 := make(chan info)
-	met := 0
-	same := 0
-	for {
-		var othername int
-		// get access to rendez data and decide what to do.
-		switch r := <-meetingplace; {
-		case r.n >= n:
-			// if no more meetings left, then send our result data and exit.
-			meetingplace <- rendez{n: r.n}
-			ended <- result{met, same}
-			return
-		case r.mate == nil:
-			// no creature waiting; wait for someone to meet us,
-			// get their info and send our info in reply.
-			meetingplace <- rendez{n: r.n, info: info0, mate: c0}
-			info1 := <-c0
-			othername = info1.name
-			info0.colour = complement[info0.colour|info1.colour<<2]
-		default:
-			// another creature is waiting for us with its info;
-			// increment meeting count,
-			// send them our info in reply.
-			r.n++
-			meetingplace <- rendez{n: r.n, mate: nil}
-			r.mate <- info0
-			othername = r.info.name
-			info0.colour = complement[info0.colour|r.info.colour<<2]
-		}
-		if othername == info0.name {
-			same++
-		}
-		met++
-	}
-}
-
-var digits = [...]string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
-
-func spell(n int, required bool) string {
-	if n == 0 && !required {
-		return ""
-	}
-	return spell(n/10, false) + " " + digits[n%10]
-}
diff --git a/test/bench/fasta.go b/test/bench/fasta.go
deleted file mode 100644
index d13edd5..0000000
--- a/test/bench/fasta.go
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on C program by by Petr Prokhorenkov.
- */
-
-package main
-
-import (
-	"flag"
-	"os"
-)
-
-var out = make(buffer, 0, 32768)
-
-var n = flag.Int("n", 1000, "length of result")
-
-const Line = 60
-
-func Repeat(alu []byte, n int) {
-	buf := append(alu, alu...)
-	off := 0
-	for n > 0 {
-		m := n
-		if m > Line {
-			m = Line
-		}
-		buf1 := out.NextWrite(m + 1)
-		copy(buf1, buf[off:])
-		buf1[m] = '\n'
-		if off += m; off >= len(alu) {
-			off -= len(alu)
-		}
-		n -= m
-	}
-}
-
-const (
-	IM = 139968
-	IA = 3877
-	IC = 29573
-
-	LookupSize  = 4096
-	LookupScale float64 = LookupSize - 1
-)
-
-var rand uint32 = 42
-
-type Acid struct {
-	sym   byte
-	prob  float64
-	cprob float64
-	next  *Acid
-}
-
-func computeLookup(acid []Acid) *[LookupSize]*Acid {
-	var lookup [LookupSize]*Acid
-	var p float64
-	for i := range acid {
-		p += acid[i].prob
-		acid[i].cprob = p * LookupScale
-		if i > 0 {
-			acid[i-1].next = &acid[i]
-		}
-	}
-	acid[len(acid)-1].cprob = 1.0 * LookupScale
-
-	j := 0
-	for i := range lookup {
-		for acid[j].cprob < float64(i) {
-			j++
-		}
-		lookup[i] = &acid[j]
-	}
-
-	return &lookup
-}
-
-func Random(acid []Acid, n int) {
-	lookup := computeLookup(acid)
-	for n > 0 {
-		m := n
-		if m > Line {
-			m = Line
-		}
-		buf := out.NextWrite(m + 1)
-		f := LookupScale / IM
-		myrand := rand
-		for i := 0; i < m; i++ {
-			myrand = (myrand*IA + IC) % IM
-			r := float64(int(myrand)) * f
-			a := lookup[int(r)]
-			for a.cprob < r {
-				a = a.next
-			}
-			buf[i] = a.sym
-		}
-		rand = myrand
-		buf[m] = '\n'
-		n -= m
-	}
-}
-
-func main() {
-	defer out.Flush()
-
-	flag.Parse()
-
-	iub := []Acid{
-		{prob: 0.27, sym: 'a'},
-		{prob: 0.12, sym: 'c'},
-		{prob: 0.12, sym: 'g'},
-		{prob: 0.27, sym: 't'},
-		{prob: 0.02, sym: 'B'},
-		{prob: 0.02, sym: 'D'},
-		{prob: 0.02, sym: 'H'},
-		{prob: 0.02, sym: 'K'},
-		{prob: 0.02, sym: 'M'},
-		{prob: 0.02, sym: 'N'},
-		{prob: 0.02, sym: 'R'},
-		{prob: 0.02, sym: 'S'},
-		{prob: 0.02, sym: 'V'},
-		{prob: 0.02, sym: 'W'},
-		{prob: 0.02, sym: 'Y'},
-	}
-
-	homosapiens := []Acid{
-		{prob: 0.3029549426680, sym: 'a'},
-		{prob: 0.1979883004921, sym: 'c'},
-		{prob: 0.1975473066391, sym: 'g'},
-		{prob: 0.3015094502008, sym: 't'},
-	}
-
-	alu := []byte(
-		"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
-			"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
-			"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
-			"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
-			"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
-			"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
-			"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA")
-
-	out.WriteString(">ONE Homo sapiens alu\n")
-	Repeat(alu, 2**n)
-	out.WriteString(">TWO IUB ambiguity codes\n")
-	Random(iub, 3**n)
-	out.WriteString(">THREE Homo sapiens frequency\n")
-	Random(homosapiens, 5**n)
-}
-
-
-type buffer []byte
-
-func (b *buffer) Flush() {
-	p := *b
-	if len(p) > 0 {
-		os.Stdout.Write(p)
-	}
-	*b = p[0:0]
-}
-
-func (b *buffer) WriteString(s string) {
-	p := b.NextWrite(len(s))
-	copy(p, s)
-}
-
-func (b *buffer) NextWrite(n int) []byte {
-	p := *b
-	if len(p)+n > cap(p) {
-		b.Flush()
-		p = *b
-	}
-	out := p[len(p) : len(p)+n]
-	*b = p[:len(p)+n]
-	return out
-}
diff --git a/test/bench/garbage/Makefile b/test/bench/garbage/Makefile
new file mode 100644
index 0000000..8002a20
--- /dev/null
+++ b/test/bench/garbage/Makefile
@@ -0,0 +1,28 @@
+# Copyright 2010 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../src/Make.inc
+
+ALL=\
+	parser\
+	peano\
+	tree\
+	tree2\
+
+all: $(addsuffix .out, $(ALL))
+
+%.$O: %.go stats.go
+	$(GC) $(GCFLAGS) $(GCIMPORTS) $*.go stats.go
+
+%.out: %.$O
+	$(LD) -o $@ $*.$O
+
+%.bench: %.out
+	time ./$*.out
+
+bench: $(addsuffix .bench, $(ALL))
+
+clean:
+	rm -f *.[$(OS)] $(addsuffix .out, $(ALL))
+
diff --git a/test/bench/garbage/parser.go b/test/bench/garbage/parser.go
new file mode 100644
index 0000000..9e15f6c
--- /dev/null
+++ b/test/bench/garbage/parser.go
@@ -0,0 +1,224 @@
+// Copyright 2010 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.
+
+// Garbage collection benchmark: parse Go packages repeatedly.
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+	"log"
+	"net/http"
+	_ "net/http/pprof"
+	"os"
+	"path"
+	"runtime"
+	"strings"
+	"time"
+)
+
+var serve = flag.String("serve", "", "serve http on this address at end")
+
+func isGoFile(dir os.FileInfo) bool {
+	return !dir.IsDir() &&
+		!strings.HasPrefix(dir.Name(), ".") && // ignore .files
+		path.Ext(dir.Name()) == ".go"
+}
+
+func isPkgFile(dir os.FileInfo) bool {
+	return isGoFile(dir) &&
+		!strings.HasSuffix(dir.Name(), "_test.go") // ignore test files
+}
+
+func pkgName(filename string) string {
+	file, err := parser.ParseFile(token.NewFileSet(), filename, nil, parser.PackageClauseOnly)
+	if err != nil || file == nil {
+		return ""
+	}
+	return file.Name.Name
+}
+
+func parseDir(dirpath string) map[string]*ast.Package {
+	// the package name is the directory name within its parent
+	// (use dirname instead of path because dirname is clean; i.e. has no trailing '/')
+	_, pkgname := path.Split(dirpath)
+
+	// filter function to select the desired .go files
+	filter := func(d os.FileInfo) bool {
+		if isPkgFile(d) {
+			// Some directories contain main packages: Only accept
+			// files that belong to the expected package so that
+			// parser.ParsePackage doesn't return "multiple packages
+			// found" errors.
+			// Additionally, accept the special package name
+			// fakePkgName if we are looking at cmd documentation.
+			name := pkgName(dirpath + "/" + d.Name())
+			return name == pkgname
+		}
+		return false
+	}
+
+	// get package AST
+	pkgs, err := parser.ParseDir(token.NewFileSet(), dirpath, filter, parser.ParseComments)
+	if err != nil {
+		println("parse", dirpath, err.Error())
+		panic("fail")
+	}
+	return pkgs
+}
+
+func main() {
+	st := &runtime.MemStats
+	packages = append(packages, packages...)
+	packages = append(packages, packages...)
+	n := flag.Int("n", 4, "iterations")
+	p := flag.Int("p", len(packages), "# of packages to keep in memory")
+	flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
+	flag.Parse()
+
+	var lastParsed []map[string]*ast.Package
+	var t0 time.Time
+	pkgroot := runtime.GOROOT() + "/src/pkg/"
+	for pass := 0; pass < 2; pass++ {
+		// Once the heap is grown to full size, reset counters.
+		// This hides the start-up pauses, which are much smaller
+		// than the normal pauses and would otherwise make
+		// the average look much better than it actually is.
+		st.NumGC = 0
+		st.PauseTotalNs = 0
+		t0 = time.Now()
+
+		for i := 0; i < *n; i++ {
+			parsed := make([]map[string]*ast.Package, *p)
+			for j := range parsed {
+				parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
+			}
+			if i+1 == *n && *serve != "" {
+				lastParsed = parsed
+			}
+		}
+		runtime.GC()
+		runtime.GC()
+	}
+	t1 := time.Now()
+
+	fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
+		st.Alloc, st.TotalAlloc,
+		st.Sys,
+		st.Mallocs, float64(st.PauseTotalNs)/1e9,
+		st.NumGC, float64(st.PauseTotalNs)/1e9/float64(st.NumGC))
+
+	/*
+		fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free")
+		for _, s := range st.BySize {
+			fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
+		}
+	*/
+	// Standard gotest benchmark output, collected by build dashboard.
+	gcstats("BenchmarkParser", *n, t1.Sub(t0))
+
+	if *serve != "" {
+		log.Fatal(http.ListenAndServe(*serve, nil))
+		println(lastParsed)
+	}
+}
+
+var packages = []string{
+	"archive/tar",
+	"encoding/asn1",
+	"math/big",
+	"bufio",
+	"bytes",
+	"math/cmplx",
+	"compress/flate",
+	"compress/gzip",
+	"compress/zlib",
+	"container/heap",
+	"container/list",
+	"container/ring",
+	"crypto/aes",
+	"crypto/blowfish",
+	"crypto/hmac",
+	"crypto/md4",
+	"crypto/md5",
+	"crypto/rand",
+	"crypto/rc4",
+	"crypto/rsa",
+	"crypto/sha1",
+	"crypto/sha256",
+	"crypto/sha512",
+	"crypto/subtle",
+	"crypto/tls",
+	"crypto/x509",
+	"crypto/xtea",
+	"debug/dwarf",
+	"debug/macho",
+	"debug/elf",
+	"debug/gosym",
+	"exp/ebnf",
+	"encoding/ascii85",
+	"encoding/base64",
+	"encoding/binary",
+	"encoding/git85",
+	"encoding/hex",
+	"encoding/pem",
+	"os/exec",
+	"flag",
+	"fmt",
+	"go/ast",
+	"go/doc",
+	"go/parser",
+	"go/printer",
+	"go/scanner",
+	"go/token",
+	"encoding/gob",
+	"hash",
+	"hash/adler32",
+	"hash/crc32",
+	"hash/crc64",
+	"net/http",
+	"image",
+	"image/jpeg",
+	"image/png",
+	"io",
+	"io/ioutil",
+	"encoding/json",
+	"log",
+	"math",
+	"mime",
+	"net",
+	"os",
+	"os/signal",
+	"patch",
+	"path",
+	"math/rand",
+	"reflect",
+	"regexp",
+	"net/rpc",
+	"runtime",
+	"text/scanner",
+	"sort",
+	"net/smtp",
+	"strconv",
+	"strings",
+	"sync",
+	"syscall",
+	"log/syslog",
+	"text/tabwriter",
+	"text/template",
+	"testing",
+	"testing/iotest",
+	"testing/quick",
+	"testing/script",
+	"time",
+	"unicode",
+	"unicode/utf8",
+	"unicode/utf16",
+	"websocket",
+	"encoding/xml",
+}
diff --git a/test/bench/garbage/peano.go b/test/bench/garbage/peano.go
new file mode 100644
index 0000000..f1ad6ed
--- /dev/null
+++ b/test/bench/garbage/peano.go
@@ -0,0 +1,121 @@
+// $G $F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"fmt"
+	"runtime"
+	"time"
+)
+
+type Number struct {
+	next *Number
+}
+
+// -------------------------------------
+// Peano primitives
+
+func zero() *Number { return nil }
+
+func is_zero(x *Number) bool { return x == nil }
+
+func add1(x *Number) *Number {
+	e := new(Number)
+	e.next = x
+	return e
+}
+
+func sub1(x *Number) *Number { return x.next }
+
+func add(x, y *Number) *Number {
+	if is_zero(y) {
+		return x
+	}
+
+	return add(add1(x), sub1(y))
+}
+
+func mul(x, y *Number) *Number {
+	if is_zero(x) || is_zero(y) {
+		return zero()
+	}
+
+	return add(mul(x, sub1(y)), x)
+}
+
+func fact(n *Number) *Number {
+	if is_zero(n) {
+		return add1(zero())
+	}
+
+	return mul(fact(sub1(n)), n)
+}
+
+// -------------------------------------
+// Helpers to generate/count Peano integers
+
+func gen(n int) *Number {
+	if n > 0 {
+		return add1(gen(n - 1))
+	}
+
+	return zero()
+}
+
+func count(x *Number) int {
+	if is_zero(x) {
+		return 0
+	}
+
+	return count(sub1(x)) + 1
+}
+
+func check(x *Number, expected int) {
+	var c = count(x)
+	if c != expected {
+		panic(fmt.Sprintf("error: found %d; expected %d", c, expected))
+	}
+}
+
+// -------------------------------------
+// Test basic functionality
+
+func verify() {
+	check(zero(), 0)
+	check(add1(zero()), 1)
+	check(gen(10), 10)
+
+	check(add(gen(3), zero()), 3)
+	check(add(zero(), gen(4)), 4)
+	check(add(gen(3), gen(4)), 7)
+
+	check(mul(zero(), zero()), 0)
+	check(mul(gen(3), zero()), 0)
+	check(mul(zero(), gen(4)), 0)
+	check(mul(gen(3), add1(zero())), 3)
+	check(mul(add1(zero()), gen(4)), 4)
+	check(mul(gen(3), gen(4)), 12)
+
+	check(fact(zero()), 1)
+	check(fact(add1(zero())), 1)
+	check(fact(gen(5)), 120)
+}
+
+// -------------------------------------
+// Factorial
+
+func main() {
+	t0 := time.Now()
+	verify()
+	for i := 0; i <= 9; i++ {
+		print(i, "! = ", count(fact(gen(i))), "\n")
+	}
+	runtime.GC()
+	t1 := time.Now()
+
+	gcstats("BenchmarkPeano", 1, t1.Sub(t0))
+}
diff --git a/test/bench/garbage/stats.go b/test/bench/garbage/stats.go
new file mode 100644
index 0000000..985e7ea
--- /dev/null
+++ b/test/bench/garbage/stats.go
@@ -0,0 +1,46 @@
+// Copyright 2010 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"
+	"runtime"
+	"sort"
+	"time"
+)
+
+func gcstats(name string, n int, t time.Duration) {
+	st := &runtime.MemStats
+	fmt.Printf("garbage.%sMem Alloc=%d/%d Heap=%d NextGC=%d Mallocs=%d\n", name, st.Alloc, st.TotalAlloc, st.Sys, st.NextGC, st.Mallocs)
+	fmt.Printf("garbage.%s %d %d ns/op\n", name, n, t.Nanoseconds()/int64(n))
+	fmt.Printf("garbage.%sLastPause 1 %d ns/op\n", name, st.PauseNs[(st.NumGC-1)%uint32(len(st.PauseNs))])
+	fmt.Printf("garbage.%sPause %d %d ns/op\n", name, st.NumGC, int64(st.PauseTotalNs)/int64(st.NumGC))
+	nn := int(st.NumGC)
+	if nn >= len(st.PauseNs) {
+		nn = len(st.PauseNs)
+	}
+	t1, t2, t3, t4, t5 := tukey5(st.PauseNs[0:nn])
+	fmt.Printf("garbage.%sPause5: %d %d %d %d %d\n", name, t1, t2, t3, t4, t5)
+
+	//	fmt.Printf("garbage.%sScan: %v\n", name, st.ScanDist)
+}
+
+type T []uint64
+
+func (t T) Len() int           { return len(t) }
+func (t T) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
+func (t T) Less(i, j int) bool { return t[i] < t[j] }
+
+func tukey5(raw []uint64) (lo, q1, q2, q3, hi uint64) {
+	x := make(T, len(raw))
+	copy(x, raw)
+	sort.Sort(T(x))
+	lo = x[0]
+	q1 = x[len(x)/4]
+	q2 = x[len(x)/2]
+	q3 = x[len(x)*3/4]
+	hi = x[len(x)-1]
+	return
+}
diff --git a/test/bench/garbage/tree.go b/test/bench/garbage/tree.go
new file mode 100644
index 0000000..0a3ec23
--- /dev/null
+++ b/test/bench/garbage/tree.go
@@ -0,0 +1,100 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ * based on C program by Kevin Carson
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"time"
+)
+
+var n = flag.Int("n", 16, "depth")
+
+type Node struct {
+	item        int
+	left, right *Node
+}
+
+func bottomUpTree(item, depth int) *Node {
+	if depth <= 0 {
+		return &Node{item: item}
+	}
+	return &Node{item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1)}
+}
+
+func (n *Node) itemCheck() int {
+	if n.left == nil {
+		return n.item
+	}
+	return n.item + n.left.itemCheck() - n.right.itemCheck()
+}
+
+const minDepth = 4
+
+func main() {
+	flag.Parse()
+
+	t0 := time.Now()
+
+	maxDepth := *n
+	if minDepth+2 > *n {
+		maxDepth = minDepth + 2
+	}
+	stretchDepth := maxDepth + 1
+
+	check := bottomUpTree(0, stretchDepth).itemCheck()
+	fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check)
+
+	longLivedTree := bottomUpTree(0, maxDepth)
+
+	for depth := minDepth; depth <= maxDepth; depth += 2 {
+		iterations := 1 << uint(maxDepth-depth+minDepth)
+		check = 0
+
+		for i := 1; i <= iterations; i++ {
+			check += bottomUpTree(i, depth).itemCheck()
+			check += bottomUpTree(-i, depth).itemCheck()
+		}
+		fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check)
+	}
+	fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck())
+
+	t1 := time.Now()
+
+	// Standard gotest benchmark output, collected by build dashboard.
+	gcstats("BenchmarkTree", *n, t1.Sub(t0))
+}
diff --git a/test/bench/garbage/tree2.go b/test/bench/garbage/tree2.go
new file mode 100644
index 0000000..6d78f72
--- /dev/null
+++ b/test/bench/garbage/tree2.go
@@ -0,0 +1,88 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"log"
+	"os"
+	"runtime"
+	"runtime/pprof"
+	"unsafe"
+)
+
+const BranchingFactor = 4
+
+type Object struct {
+	child [BranchingFactor]*Object
+}
+
+var (
+	cpus       = flag.Int("cpus", 1, "number of cpus to use")
+	heapsize   = flag.Int64("heapsize", 100*1024*1024, "size of the heap in bytes")
+	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+
+	lastPauseNs uint64 = 0
+	lastFree    uint64 = 0
+	heap        *Object
+	calls       [20]int
+	numobjects  int64
+)
+
+func buildHeap() {
+	objsize := int64(unsafe.Sizeof(Object{}))
+	heap, _ = buildTree(float64(objsize), float64(*heapsize), 0)
+	fmt.Printf("*** built heap: %.0f MB; (%d objects * %d bytes)\n",
+		float64(*heapsize)/1048576, numobjects, objsize)
+}
+
+func buildTree(objsize, size float64, depth int) (*Object, float64) {
+	calls[depth]++
+	x := &Object{}
+	numobjects++
+	subtreeSize := (size - objsize) / BranchingFactor
+	alloc := objsize
+	for i := 0; i < BranchingFactor && alloc < size; i++ {
+		c, n := buildTree(objsize, subtreeSize, depth+1)
+		x.child[i] = c
+		alloc += n
+	}
+	return x, alloc
+}
+
+func gc() {
+	runtime.GC()
+	runtime.UpdateMemStats()
+	pause := runtime.MemStats.PauseTotalNs
+	inuse := runtime.MemStats.Alloc
+	free := runtime.MemStats.TotalAlloc - inuse
+	fmt.Printf("gc pause: %8.3f ms; collect: %8.0f MB; heapsize: %8.0f MB\n",
+		float64(pause-lastPauseNs)/1e6,
+		float64(free-lastFree)/1048576,
+		float64(inuse)/1048576)
+	lastPauseNs = pause
+	lastFree = free
+}
+
+func main() {
+	flag.Parse()
+	buildHeap()
+	runtime.GOMAXPROCS(*cpus)
+	runtime.UpdateMemStats()
+	lastPauseNs = runtime.MemStats.PauseTotalNs
+	lastFree = runtime.MemStats.TotalAlloc - runtime.MemStats.Alloc
+	if *cpuprofile != "" {
+		f, err := os.Create(*cpuprofile)
+		if err != nil {
+			log.Fatal(err)
+		}
+		pprof.StartCPUProfile(f)
+		defer pprof.StopCPUProfile()
+	}
+	for i := 0; i < 10; i++ {
+		gc()
+	}
+}
diff --git a/test/bench/go1/Makefile b/test/bench/go1/Makefile
new file mode 100644
index 0000000..9484743
--- /dev/null
+++ b/test/bench/go1/Makefile
@@ -0,0 +1,7 @@
+include $(GOROOT)/src/Make.inc
+
+TARG=go1
+GOFILES=\
+	dummy.go\
+
+include $(GOROOT)/src/Make.pkg
diff --git a/test/bench/go1/binarytree_test.go b/test/bench/go1/binarytree_test.go
new file mode 100644
index 0000000..c64c4b8
--- /dev/null
+++ b/test/bench/go1/binarytree_test.go
@@ -0,0 +1,63 @@
+// Copyright 2011 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 benchmark, taken from the shootout, tests garbage collector
+// performance by generating and discarding large binary trees.
+
+package go1
+
+import "testing"
+
+type binaryNode struct {
+	item        int
+	left, right *binaryNode
+}
+
+func bottomUpTree(item, depth int) *binaryNode {
+	if depth <= 0 {
+		return &binaryNode{item: item}
+	}
+	return &binaryNode{item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1)}
+}
+
+func (n *binaryNode) itemCheck() int {
+	if n.left == nil {
+		return n.item
+	}
+	return n.item + n.left.itemCheck() - n.right.itemCheck()
+}
+
+const minDepth = 4
+
+func binarytree(n int) {
+	maxDepth := n
+	if minDepth+2 > n {
+		maxDepth = minDepth + 2
+	}
+	stretchDepth := maxDepth + 1
+
+	check := bottomUpTree(0, stretchDepth).itemCheck()
+	//fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check)
+
+	longLivedTree := bottomUpTree(0, maxDepth)
+
+	for depth := minDepth; depth <= maxDepth; depth += 2 {
+		iterations := 1 << uint(maxDepth-depth+minDepth)
+		check = 0
+
+		for i := 1; i <= iterations; i++ {
+			check += bottomUpTree(i, depth).itemCheck()
+			check += bottomUpTree(-i, depth).itemCheck()
+		}
+		//fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check)
+	}
+	longLivedTree.itemCheck()
+	//fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck())
+}
+
+func BenchmarkBinaryTree17(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		binarytree(17)
+	}
+}
diff --git a/test/bench/go1/dummy.go b/test/bench/go1/dummy.go
new file mode 100644
index 0000000..4956bc7
--- /dev/null
+++ b/test/bench/go1/dummy.go
@@ -0,0 +1,3 @@
+package go1
+
+// Nothing to see here: everything is in the _test files.
diff --git a/test/bench/go1/fannkuch_test.go b/test/bench/go1/fannkuch_test.go
new file mode 100644
index 0000000..ae45bfd
--- /dev/null
+++ b/test/bench/go1/fannkuch_test.go
@@ -0,0 +1,84 @@
+// Copyright 2011 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 benchmark, taken from the shootout, tests array indexing
+// and array bounds elimination performance.
+
+package go1
+
+import "testing"
+
+func fannkuch(n int) int {
+	if n < 1 {
+		return 0
+	}
+
+	n1 := n - 1
+	perm := make([]int, n)
+	perm1 := make([]int, n)
+	count := make([]int, n)
+
+	for i := 0; i < n; i++ {
+		perm1[i] = i // initial (trivial) permutation
+	}
+
+	r := n
+	didpr := 0
+	flipsMax := 0
+	for {
+		if didpr < 30 {
+			didpr++
+		}
+		for ; r != 1; r-- {
+			count[r-1] = r
+		}
+
+		if perm1[0] != 0 && perm1[n1] != n1 {
+			flips := 0
+			for i := 1; i < n; i++ { // perm = perm1
+				perm[i] = perm1[i]
+			}
+			k := perm1[0] // cache perm[0] in k
+			for {         // k!=0 ==> k>0
+				for i, j := 1, k-1; i < j; i, j = i+1, j-1 {
+					perm[i], perm[j] = perm[j], perm[i]
+				}
+				flips++
+				// Now exchange k (caching perm[0]) and perm[k]... with care!
+				j := perm[k]
+				perm[k] = k
+				k = j
+				if k == 0 {
+					break
+				}
+			}
+			if flipsMax < flips {
+				flipsMax = flips
+			}
+		}
+
+		for ; r < n; r++ {
+			// rotate down perm[0..r] by one
+			perm0 := perm1[0]
+			for i := 0; i < r; i++ {
+				perm1[i] = perm1[i+1]
+			}
+			perm1[r] = perm0
+			count[r]--
+			if count[r] > 0 {
+				break
+			}
+		}
+		if r == n {
+			return flipsMax
+		}
+	}
+	return 0
+}
+
+func BenchmarkFannkuch11(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		fannkuch(11)
+	}
+}
diff --git a/test/bench/go1/fasta_test.go b/test/bench/go1/fasta_test.go
new file mode 100644
index 0000000..dcb2d10
--- /dev/null
+++ b/test/bench/go1/fasta_test.go
@@ -0,0 +1,164 @@
+// Copyright 2011 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 go1
+
+// Not a benchmark; input for revcomp.
+
+var fasta25m = fasta(25e6)
+
+func fasta(n int) []byte {
+	out := make(fastaBuffer, 0, 11*n)
+
+	iub := []fastaAcid{
+		{prob: 0.27, sym: 'a'},
+		{prob: 0.12, sym: 'c'},
+		{prob: 0.12, sym: 'g'},
+		{prob: 0.27, sym: 't'},
+		{prob: 0.02, sym: 'B'},
+		{prob: 0.02, sym: 'D'},
+		{prob: 0.02, sym: 'H'},
+		{prob: 0.02, sym: 'K'},
+		{prob: 0.02, sym: 'M'},
+		{prob: 0.02, sym: 'N'},
+		{prob: 0.02, sym: 'R'},
+		{prob: 0.02, sym: 'S'},
+		{prob: 0.02, sym: 'V'},
+		{prob: 0.02, sym: 'W'},
+		{prob: 0.02, sym: 'Y'},
+	}
+
+	homosapiens := []fastaAcid{
+		{prob: 0.3029549426680, sym: 'a'},
+		{prob: 0.1979883004921, sym: 'c'},
+		{prob: 0.1975473066391, sym: 'g'},
+		{prob: 0.3015094502008, sym: 't'},
+	}
+
+	alu := []byte(
+		"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
+			"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
+			"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
+			"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
+			"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
+			"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
+			"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA")
+
+	out.WriteString(">ONE Homo sapiens alu\n")
+	fastaRepeat(&out, alu, 2*n)
+	out.WriteString(">TWO IUB ambiguity codes\n")
+	fastaRandom(&out, iub, 3*n)
+	out.WriteString(">THREE Homo sapiens frequency\n")
+	fastaRandom(&out, homosapiens, 5*n)
+	return out
+}
+
+type fastaBuffer []byte
+
+func (b *fastaBuffer) Flush() {
+	panic("flush")
+}
+
+func (b *fastaBuffer) WriteString(s string) {
+	p := b.NextWrite(len(s))
+	copy(p, s)
+}
+
+func (b *fastaBuffer) NextWrite(n int) []byte {
+	p := *b
+	if len(p)+n > cap(p) {
+		b.Flush()
+		p = *b
+	}
+	out := p[len(p) : len(p)+n]
+	*b = p[:len(p)+n]
+	return out
+}
+
+const fastaLine = 60
+
+func fastaRepeat(out *fastaBuffer, alu []byte, n int) {
+	buf := append(alu, alu...)
+	off := 0
+	for n > 0 {
+		m := n
+		if m > fastaLine {
+			m = fastaLine
+		}
+		buf1 := out.NextWrite(m + 1)
+		copy(buf1, buf[off:])
+		buf1[m] = '\n'
+		if off += m; off >= len(alu) {
+			off -= len(alu)
+		}
+		n -= m
+	}
+}
+
+const (
+	fastaLookupSize          = 4096
+	fastaLookupScale float64 = fastaLookupSize - 1
+)
+
+var fastaRand uint32 = 42
+
+type fastaAcid struct {
+	sym   byte
+	prob  float64
+	cprob float64
+	next  *fastaAcid
+}
+
+func fastaComputeLookup(acid []fastaAcid) *[fastaLookupSize]*fastaAcid {
+	var lookup [fastaLookupSize]*fastaAcid
+	var p float64
+	for i := range acid {
+		p += acid[i].prob
+		acid[i].cprob = p * fastaLookupScale
+		if i > 0 {
+			acid[i-1].next = &acid[i]
+		}
+	}
+	acid[len(acid)-1].cprob = 1.0 * fastaLookupScale
+
+	j := 0
+	for i := range lookup {
+		for acid[j].cprob < float64(i) {
+			j++
+		}
+		lookup[i] = &acid[j]
+	}
+
+	return &lookup
+}
+
+func fastaRandom(out *fastaBuffer, acid []fastaAcid, n int) {
+	const (
+		IM = 139968
+		IA = 3877
+		IC = 29573
+	)
+	lookup := fastaComputeLookup(acid)
+	for n > 0 {
+		m := n
+		if m > fastaLine {
+			m = fastaLine
+		}
+		buf := out.NextWrite(m + 1)
+		f := fastaLookupScale / IM
+		myrand := fastaRand
+		for i := 0; i < m; i++ {
+			myrand = (myrand*IA + IC) % IM
+			r := float64(int(myrand)) * f
+			a := lookup[int(r)]
+			for a.cprob < r {
+				a = a.next
+			}
+			buf[i] = a.sym
+		}
+		fastaRand = myrand
+		buf[m] = '\n'
+		n -= m
+	}
+}
diff --git a/test/bench/go1/gob_test.go b/test/bench/go1/gob_test.go
new file mode 100644
index 0000000..00eeed5
--- /dev/null
+++ b/test/bench/go1/gob_test.go
@@ -0,0 +1,95 @@
+// Copyright 2011 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 benchmark tests gob encoding and decoding performance.
+
+package go1
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/json"
+	"io/ioutil"
+	"log"
+	"reflect"
+	"testing"
+)
+
+var (
+	gobbytes []byte
+	gobdata  *JSONResponse
+)
+
+func gobinit() {
+	// gobinit is called after json's init,
+	// because it uses jsondata.
+	gobdata = gobResponse(&jsondata)
+
+	var buf bytes.Buffer
+	if err := gob.NewEncoder(&buf).Encode(gobdata); err != nil {
+		panic(err)
+	}
+	gobbytes = buf.Bytes()
+
+	var r JSONResponse
+	if err := gob.NewDecoder(bytes.NewBuffer(gobbytes)).Decode(&r); err != nil {
+		panic(err)
+	}
+	if !reflect.DeepEqual(gobdata, &r) {
+		log.Printf("%v\n%v", jsondata, r)
+		b, _ := json.Marshal(&jsondata)
+		br, _ := json.Marshal(&r)
+		log.Printf("%s\n%s\n", b, br)
+		panic("gob: encode+decode lost data")
+	}
+}
+
+// gob turns [] into null, so make a copy of the data structure like that
+func gobResponse(r *JSONResponse) *JSONResponse {
+	return &JSONResponse{gobNode(r.Tree), r.Username}
+}
+
+func gobNode(n *JSONNode) *JSONNode {
+	n1 := new(JSONNode)
+	*n1 = *n
+	if len(n1.Kids) == 0 {
+		n1.Kids = nil
+	} else {
+		for i, k := range n1.Kids {
+			n1.Kids[i] = gobNode(k)
+		}
+	}
+	return n1
+}
+
+func gobdec() {
+	if gobbytes == nil {
+		panic("gobdata not initialized")
+	}
+	var r JSONResponse
+	if err := gob.NewDecoder(bytes.NewBuffer(gobbytes)).Decode(&r); err != nil {
+		panic(err)
+	}
+	_ = r
+}
+
+func gobenc() {
+	if err := gob.NewEncoder(ioutil.Discard).Encode(&gobdata); err != nil {
+		panic(err)
+	}
+}
+
+func BenchmarkGobDecode(b *testing.B) {
+	b.SetBytes(int64(len(gobbytes)))
+	for i := 0; i < b.N; i++ {
+		gobdec()
+	}
+}
+
+func BenchmarkGobEncode(b *testing.B) {
+	b.SetBytes(int64(len(gobbytes)))
+	for i := 0; i < b.N; i++ {
+		gobenc()
+	}
+}
diff --git a/test/bench/go1/gzip_test.go b/test/bench/go1/gzip_test.go
new file mode 100644
index 0000000..c9eeb17
--- /dev/null
+++ b/test/bench/go1/gzip_test.go
@@ -0,0 +1,69 @@
+// Copyright 2011 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 benchmark tests gzip and gunzip performance.
+
+package go1
+
+import (
+	"bytes"
+	gz "compress/gzip"
+	"io"
+	"io/ioutil"
+	"testing"
+)
+
+var (
+	jsongunz = bytes.Repeat(jsonbytes, 10)
+	jsongz   []byte
+)
+
+func init() {
+	var buf bytes.Buffer
+	c, err := gz.NewWriter(&buf)
+	if err != nil {
+		panic(err)
+	}
+	c.Write(jsongunz)
+	c.Close()
+	jsongz = buf.Bytes()
+}
+
+func gzip() {
+	c, err := gz.NewWriter(ioutil.Discard)
+	if err != nil {
+		panic(err)
+	}
+	if _, err := c.Write(jsongunz); err != nil {
+		panic(err)
+	}
+	if err := c.Close(); err != nil {
+		panic(err)
+	}
+}
+
+func gunzip() {
+	r, err := gz.NewReader(bytes.NewBuffer(jsongz))
+	if err != nil {
+		panic(err)
+	}
+	if _, err := io.Copy(ioutil.Discard, r); err != nil {
+		panic(err)
+	}
+	r.Close()
+}
+
+func BenchmarkGzip(b *testing.B) {
+	b.SetBytes(int64(len(jsongunz)))
+	for i := 0; i < b.N; i++ {
+		gzip()
+	}
+}
+
+func BenchmarkGunzip(b *testing.B) {
+	b.SetBytes(int64(len(jsongunz)))
+	for i := 0; i < b.N; i++ {
+		gunzip()
+	}
+}
diff --git a/test/bench/go1/json_test.go b/test/bench/go1/json_test.go
new file mode 100644
index 0000000..5a30121
--- /dev/null
+++ b/test/bench/go1/json_test.go
@@ -0,0 +1,84 @@
+// Copyright 2011 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 benchmark tests JSON encoding and decoding performance.
+
+package go1
+
+import (
+	"compress/bzip2"
+	"encoding/base64"
+	"encoding/json"
+	"io"
+	"io/ioutil"
+	"strings"
+	"testing"
+)
+
+var (
+	jsonbytes []byte
+	jsondata  JSONResponse
+)
+
+func init() {
+	var r io.Reader
+	r = strings.NewReader(jsonbz2_base64)
+	r = base64.NewDecoder(base64.StdEncoding, r)
+	r = bzip2.NewReader(r)
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		panic(err)
+	}
+	jsonbytes = b
+
+	if err := json.Unmarshal(jsonbytes, &jsondata); err != nil {
+		panic(err)
+	}
+	gobinit()
+}
+
+type JSONResponse struct {
+	Tree     *JSONNode `json:"tree"`
+	Username string    `json:"username"`
+}
+
+type JSONNode struct {
+	Name     string      `json:"name"`
+	Kids     []*JSONNode `json:"kids"`
+	CLWeight float64     `json:"cl_weight"`
+	Touches  int         `json:"touches"`
+	MinT     int64       `json:"min_t"`
+	MaxT     int64       `json:"max_t"`
+	MeanT    int64       `json:"mean_t"`
+}
+
+func jsondec() {
+	var r JSONResponse
+	if err := json.Unmarshal(jsonbytes, &r); err != nil {
+		panic(err)
+	}
+	_ = r
+}
+
+func jsonenc() {
+	buf, err := json.Marshal(&jsondata)
+	if err != nil {
+		panic(err)
+	}
+	_ = buf
+}
+
+func BenchmarkJSONEncode(b *testing.B) {
+	b.SetBytes(int64(len(jsonbytes)))
+	for i := 0; i < b.N; i++ {
+		jsonenc()
+	}
+}
+
+func BenchmarkJSONDecode(b *testing.B) {
+	b.SetBytes(int64(len(jsonbytes)))
+	for i := 0; i < b.N; i++ {
+		jsondec()
+	}
+}
diff --git a/test/bench/go1/jsondata_test.go b/test/bench/go1/jsondata_test.go
new file mode 100644
index 0000000..7d42c96
--- /dev/null
+++ b/test/bench/go1/jsondata_test.go
@@ -0,0 +1,1818 @@
+// Copyright 2011 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.
+
+// Input for JSON and other benchmarks.
+// This was generated by starting with a 2MB JSON file with actual data
+// about open source revision history, then compressing with bzip2 -9,
+// then encoding to base64 with openssl enc -e -base64.
+// The result is 125kB of source instead of 2MB.
+// We compile the data into the binary so that the benchmark is
+// a stand-alone binary that can be copied easily from machine to
+// machine.  json_test.go decodes this during init.
+
+package go1
+
+var jsonbz2_base64 = "QlpoOTFBWSZTWZ0H0LkG0bxfgFH8UAf/8D////q////6YSvJveAAAAAH3ddt7gAN" +
+	"FrKppN9gw0gA++fGB9xKkUpX0YWTENCgqzUW1tlsyMB2w9nnvNSigNyS+3cui5zA" +
+	"AAAAAAAAAI4kILu6ytuWTLBbaPXfc+A+PQEgNAG1ZMBYWnWwPoFrGjoBnYMumlUF" +
+	"UKA7NVBQgut30zzu8eM2tsoapJ7u41djLsxZarplSoJouxrdfHrHPSiqAGgkAD6D" +
+	"QfT0ABu7gG1qDtdVHVXp7vWuBoBk2wEOjKChQ5bvbh3riupXZycASbaiQEECRKib" +
+	"ZFJFtqWjR7bsGoaa1lIFPRoKVQKoJFyqbWr5OB1Aie2pobm1EJKqVBU1EE2lCg6a" +
+	"AUBV9hqL00q9btQ0J9hqu2zavWVdjI6aAusU22tNa+8m70GjRqarKRWtUDW2yFBI" +
+	"1kBrrqrxeX3AyB9AD0wAAAeZ6weqV1rVu8UVICgAAABeDn2cAAd9gAACI+7DvjHo" +
+	"j73u8X2dDXT2x6adeFOTNe7BvavozFezkV1xXtJzu8H0983QAHr5aPT42iem53fX" +
+	"23IDr7YejQNtVVZr24gGgB0VQffPXH18g9DoaDW8vt729h9bt72XsKth0ANxgodG" +
+	"iRxvYclAAAAAnpqRtgGvcbo9ABpy6aPQADRZ3aACjyox4NawKCqNdA6offa1WtPc" +
+	"fdjQUPvauprcLoPe2oaplp2w7cnOHdlF27xvPY1QU67vc8goBRttLYKaHXkPAAAA" +
+	"AAdyFFaYCVClAVSlCqVSilFUKEgoNT0CAQCBAk00g1T0jQNNPSbKADQxAJEBESIg" +
+	"Seomk9EB6mjQ0NNGgAAAAkEgkiGk0CR6U9CNNNNNPQRo0ANAaAAk9UpEQmoNNRqe" +
+	"U02o00AAADQABoACJEAlKamUCjZT9UGnqAAG1AGgAAAFRJCAQCBA0SYjTKbQmqea" +
+	"p6YU2o09Q9TT00nAlwPEuSelCeXl28B3IYIQHEwXUMSCvlAYS5LkrZn+XhHHAXZz" +
+	"FTJHAzrKZzYWC0pthA9SCmbkyVzoHbSUjhnAfBrYpwWYIB7GRjOjDQqokMbJENSO" +
+	"SBCN0WhaRhQWpVuoOLN0NPRed7eO5eW2lv5L+X/jf7EpJkEUNMJKZREogmkjMgZJ" +
+	"BiEEEliRIUKAoiaSEoDQZJBhKEZEQySQCAIIFNIMwCiSYRSYzKMkSSlI0xZMZKko" +
+	"RKlRtkmWJIrNNIBEJEYiJBhGMMkWYxRqUsmjKJMmCFJMaSmiyDSaEJtBIJpANKMN" +
+	"JEkpGQAYjLNETGUBRAlBKURgsC0wzKZhRmhiYIQZIsZCIIMiiNmFCCiSZNjI0khE" +
+	"AYSEUkjTMSZskZKRQWJoRNBI2IojZmMhTIkQEgyREEMoomDSiYxAZMECFCSKIkGg" +
+	"kIDIw2MNAlgyA0SmKWSSyIaRCSDDIkZmNGghgyAEoERokkWTA0xZBEQhmUSBGmaQ" +
+	"aQBFmRJMokwxIyRSWbAkbCUFlAhgUISJIRkySYhAxoUARCSaIJMkyiZJNBMyGRIh" +
+	"Y0komKImgMDI/038qLf/av/bWSNVEtmFRx/2aaDVmKkY0NkIRDGJEWoEGLf9g9MV" +
+	"UJWGSu0pWVpSOdWDVjQJGRSChGBGDGhNNMYYwjEsaFISGPT3TbFXk873Xq8vPa9b" +
+	"0dcco0UEPXIl/+em0IMHNYJaXBEsiKQh/7QwsC9gAauDvWtMEBWhGBIBAerIYlBU" +
+	"SzPasze15BfAyGrr284QNjGNEmaUphiMxEMwCZjAYRpMiZBMpEMkkQzIwTDu5zru" +
+	"Xd1xdQ6A6E7m7d03OLnXOxd3HBu50dl0JOhxS4HdHczuO647uuLu6650O67t3Duu" +
+	"3DucukzRKIMhsUjSQQxDIzQJgxohEkYTYkZsAxSDGCJJERhpEAygoZRESSEjMpFE" +
+	"0UpJlBkIYwoyQ7/2f9H/Py8roY3wEn8nr7+72ybZtybdqY06yp1tjGVmsmJvG48y" +
+	"89EXnvy9F6OvX0vpBSIEiSRAmgSASYSkCGBkyc5J63pgiRBNsJW2xjGmmNsf9v7R" +
+	"z1rueFmZcfXzw/zTGRYxsYm2NjbbfXD64GtivKx5t9eubzmsMTbf9rTfKRsYx7YR" +
+	"jHWL7OoAJpsFBJgyAEzSJiLHxfJKWQgSlJjGduRqRxDIoETG4wj+VgUjnMt5PXnm" +
+	"vEQwO7ojzu7lxu7uasg9T00zjrtcaG2RKIwyHx2vUcbjd0OXXvfNafFE3u3t7bu9" +
+	"TpJ1t6SKh9vi13hQUX4d307pPHt553zxxHMGb4KrbbvJGTCcNs3WmOyG2fg5vsuZ" +
+	"jMi+lacpNcvr0XeKDnafDcIvhyL7927rr7/Pzfj7qLVW5dFKIg8+fKpuxf+vfhB+" +
+	"73vWXz3qCPPfw32Mn4c/9mtONctW/fc1sYad9JYn/D1DlDPoyyc7D5bSi3ncMPNH" +
+	"bWmvm42eODHImqooiuXwn95XZlmKYKGK7KdA6lrgzZpEiUccypzKofPy4kbjq6Nh" +
+	"o/ou++j5g2i5alDG/G3Cb0yaOY3lH7wd83fLG1uQ0nDG18UHnnOOsy+Y4u2Nv5Hl" +
+	"jTCKmSJYyBhnB1Lbbafjgaat8zzctvDjPPy7e5IdyZHPSTxq/zkHjinrI5v0/nmG" +
+	"Pp+JUz4odkc9b4/cze19oRNOjG2wb+PkWtt4RRjbBsfupHPO3Mmgc18az57U+TM7" +
+	"gQsH90UPHJCZN4WsaY383qkbxxO20pI23JHbCr3ssnqkVFJG/lN5x6yQydwiaSA6" +
+	"rcgBoSxEDRKIuS1slJsq1MtS6koA5+jFGb17XFu0owrTZZSqsjrkmLVo2tSN44ac" +
+	"fvD3aWfOerth5lG/Jlkfp6bqUbOZs2FpVptDIwCuWVgqIgkgJMtDBFi+2FpRDhEI" +
+	"JAKJtPXloMoKGWpU0YvH9h2nx/hxra8/8UoaoWbia9EeoTlN7Bd5PNdcCDKemn+L" +
+	"cY2qMUXGibc0a33/wjqMN0s8PmTeeup76JA7aKr1nMbhIkn1aX4m5rTPH4aOBlTQ" +
+	"I35HXHwtJ9z1XuF9EQDwDnCS3S9W358a/E4pTeTSVvyKGWTK/n4Xp7V4dB64Ua3Q" +
+	"BIaDtzTsXpXV1k9E54ousxG/XtEhuaGmyCefTL/r3478anc78deNRjg9uchGVxVD" +
+	"Fq6cMZqIdp0ihq0xoIf1zldyBS011SFzq08qfSxV8u0cT70dZgp8ebjk800pU8m2" +
+	"s1kKdj+zvmBEEU+P0+FlzrhOf/ifG2tOsmrlp7B88bbCY9u1VFK7YavjSQ7xtE94" +
+	"3aiJb59/et60wn2vrgeV/jeNd+O/Wt/fp6dNf7iJA5QICcGyiKgpFEFQiCjEGEQC" +
+	"LBIioACSIqiCxSCqIxJIw1GQ0Ua1Vam2qYsmg1rVTbQlmjVbWbaGLbU1kWtlqWrN" +
+	"LVNNaaQICZqIhD/QiASyQCUEBKiRKRAJSUiASySKRAJSD/zAgJUghMIgEojKiCf+" +
+	"CIBP9wICfq+/889/0uxkuba/pJdybzbJvEsZ/CpEx89uGn3OONVtyYDHCGIxNyIx" +
+	"JsYgJYbH+I5RK73DuMZminldjp3e8QpDJju1QToo7pQFEpABpEV4CLQo2QicBAbo" +
+	"SEINjsMsDt9BO4nJzGstqAmgEJwhRyggJYoMJE0sJoa0zOdEgXdwiQssy4L3pzbM" +
+	"CwOaLEYFDBQKzaJCjFh2yhQOHbgLVMHXFUf7jhKTXPWsNDuEPXRHfJuLlKqls5Tx" +
+	"pCC1IgIHnTm5PeWkwwjobODcCdTCa0YoDvMlcZwvmQTkg8KC06oALrhzZqrQmQq6" +
+	"E28rdrSUxBeLkBshIKRh04g4LDdsmTCpNKSszbu9lHOoAwkmTDrOKCmSqExdOsOV" +
+	"D1XsAQpFVMukLCcGYGVFpAp4Bg0VnXFFjjdC8avBE6BepA3q6bOgot8LtHTiIlkb" +
+	"ARVEcldJoYt4Pimls9rpBzDNzeMwOdNAdSkWo4CrsTZ065yPaODXMCkcZCarR0LU" +
+	"voX1R3nDEsLtlyklMo3qrYHIguO1Ci7xRXFwJZjfTrtZfAyzUKhgJcLOIzeTvWjG" +
+	"zDE27OYME6dM3Z2kVeKcV1I4jKga0x3vCKlcUmkjRE1Zzsmxsq7L3zOnQ8wzeGDZ" +
+	"pQO0uN0NpZhcQSuVETbLL2zvKTzqjtBhwIXGaksi8rYKx2Wi6C1J3Ulb1dwqkjat" +
+	"FU6mO1F5Ii+bGnOMaOlc5EKekFDaQ9tjCU1yqcE66xRVh1ndLcBt7ThNI8LbowKP" +
+	"Md0AHRNhdYOJksYIQETYuK3ytX1UEkFHZLCghijoBdFzCgKJmlJSADdF5CnsMoIp" +
+	"pMjeqUgBrXACCcshXWsqyAgenB7IMoT6ZghKl5ljwkJTUVQuhTp3YIWgQCl8eBO7" +
+	"FTzwWGBEw8BDaLuSqMmM0wWE6QVsFIpRwmCRA128BCKpdaVunHbkyuScBsqeFjLJ" +
+	"qAw0WUUIhMN3S5Keua7Wynjnew31G8jecPcVIYxGw3trGziGoCdTHKPOEpO5732V" +
+	"4lnVA4VvKsc+R4OHHQz2JkHFdwSzeiDBUGBiQAJcznd7Z0oCmMykE5KjZuKCyKhd" +
+	"5nTSBBtu1sj6s2JCiZBgpYdOIM4luy6evBlYUYldUQQZKOoAiZL4d7fe003l07CD" +
+	"omKNzZgXiveIrzXjCZel4BcyY752rec3eRoT6jAGZAGEc3kkZQhLcVNCq+qVFSim" +
+	"BuCKZeQr5FF85WTJZzIXXwto0cB2CpntlWr0xWTfLt1yrDg8503VJAdH0uqes4bJ" +
+	"d5wsYFakMZlVS7lsEko6gj0LqyENh3rvG7qYJiQ9xoY33UthsUwRtEF6HUjtHWGA" +
+	"1q5N1HNgiI7rFa5QiEzuCDZ03KzKswfM7185zaRUkRyiUUssQSPAwlc6CAaa2KwB" +
+	"CwsOVTUrpamy4uS+mkF2pVMrpWpG7eYkYjcqSMY+pyDKhDILMmR5HGGc5ml4LJEa" +
+	"A2sxQOlwRDZ0WyiDjMTFnLRKRw6sK02ph9cZnMe8fZrmsJ0710vNY0uY4QFbSrzd" +
+	"WY7FvR2oW0ZI0zyUKMETaoJFAUTUyWuaSjAQt4DbxyqAYcj2ysQneAWKMQAWMoBB" +
+	"hIT0HPY5ne8L49gqYBFQhCXlCmzuzQImhRcjCApqiwAmbWJbzsY5reBB1xT5l5T1" +
+	"ybWy6V0tnJKrLM5WHNy+RpkM2cyZ5hebCcdg7aCc7IdY80lCFwSGCAXNmQXb2QRQ" +
+	"x7k3NRDGXELYQ1gsQhhUDum3ZE72ughHRdRDe5Te6qw1u1LB7lbNrJow7QT1uAV3" +
+	"LMgyxdGjCMORl8Gn2BQuwIUzm8BtHWJnZGBtieoICDTvKJbIMisQ2U1BCZoZlhQX" +
+	"ygQBW0jtgQdslCYNcrXVNnBA+zLTmqmqYeS9YapA12zNGgCPsUFmdoio3ByWaNXs" +
+	"7NrZuGMrSZWRJA0vOHdOWzMw8kjKrskdtyHLanDtiyJzpWVgjo+aaaAkqTKWLcdw" +
+	"xANHQyoZ1XdCK2biAxFgjnDMsxEk4wrWTKgmoae5DQbpESptb1u3Dbpe6qOAZBKa" +
+	"UBJKBZeiCwEJ0WgjFAInS4JGF6SCWBfA6F3ud3YtJTVontzKvsRDk5lipuE0+KVI" +
+	"KnHbGmhhDdShYAZ20BJi8hNs22nd3MxNWKTyqlNVdr1vFs1kiRRBRoZYJt1SAw2W" +
+	"IVY7gXmtBFNaclgFQFjwnNh/g2AZt0p2YbFHgZ1ZkUHIuCAEMTDITBEMBgx4Ecgg" +
+	"OwyuETQ7GUQsGRFZENlWXORDAZBg5I2Qg0CU0NEcuCVhf8E4pyCmHivNaJAP8Dg6" +
+	"HMU/BCCcRX/CAZi3FTsR+gqagg7gfXVQF3AFS45ig+iMnICOKROLlQG9QyjKyxqt" +
+	"rL7DL2NWEoOARpsJENtjCQigyaiVbD8RcRpvD0dJYxh4KmINWGAOAshCD2ihhCBU" +
+	"w7Rz2iEeFpgIN0kKqUcbsJC1I9OQR1ARqIJlDBA9OIaiEhhK4RqJxpaG4HNX26+L" +
+	"L2uVbzYr6uxSpDYDItapRNSDSPMC40zShplaragEHVTTzmCYzRWDaG4boqxNVpQe" +
+	"/U/8feVF+H1z3Iy2hnvDyeOt5n1QI23zarZHe9m7tUTEm75vIImeGztcNqf8/DK0" +
+	"7AS3hyuujbWlvld0RqQIdaW8VAyyAqKpJUEU5BBqICLiixEH2fZwoinThP1ruaww" +
+	"Wxs79RpIWIc1I6VkHrWTkb36HKsT8aCEdYQp8dyc8nHc5Tn1GZ9DqfXs+w6jU5vi" +
+	"5KOwjHVB4s9RJbGxesXpEnueovCTuXRSXfPMqMjxq9le4We74avJg7nrh8fkY4r3" +
+	"uTybuqrI5WCNRuBiLUVuMAR02HDRwNFmhVQC0wOxtAjoECQdIAuc+ZfaLo6O0IVM" +
+	"EV4FEtlx4W2FCCd0Phvqkylm+T5VSzgZCqK7UNZc+X11LEfD369NnPNn684h236W" +
+	"bTiIcgobiiYguzQoGj4YxXj++cs4Tz0qdHkwXXYuqOxh4RlKlgXcTb+ZT58LL54/" +
+	"X5UkWd6UwSUtKWg8ezAgn3LlVGy99KvHea5jdcQUuTpOwzdqe2VOu9t12gz7+79S" +
+	"tp9hZGnb9KZ0+UWVGOfa8PL8MePzZ2jpXPc6c8Sz56UZnuR7VyqryWOdve7uxH+f" +
+	"7i9zTaJuakt23DIbPPKW3WvwvI5hyr5WOMzSpMgcRs3ZkcLrNrzmzOP/kkQSPs/c" +
+	"fx/623+62xX7H7t/15ZmW2yT/C26fxC/1B/Nm/4vHf4Y/W83vZdxnDDNatLLf4zJ" +
+	"2SOOSTXtmh6bgfkM/aUg/9rYz+ROs5f0f7Np83tXE0ON27ynOf4eduzHucnkr/bP" +
+	"/xPo+Tm1N30cm7RXZ2cox/U5Js3cZ8ctGrXWkfP6/AuC4YHo+wmtGj+jDpRjOnhC" +
+	"Rui6MS/oi+aX3Nt6cccYzh37RNxmjpw854P83H24dWtaabtnmK/F6q09XRzP6HOT" +
+	"UEd6oETQUHmXUt2toYLMjFiMiAgDhaE2Dii0fPTcNGH7p5jf0kPg3fXkttKDMGej" +
+	"3IKP2KJOlt/R+CT7PcY3AZxsoa+WREFD5vk4TdXR6uRq+MzKxSvDrq2ak+c2275m" +
+	"d5ettnJp+4/Y+HV6qxudXLdedt6uSdTKGaMJP6jNbZZww68/M8PzplDqYusu8ZQB" +
+	"AFQUJ8y9CB2DjMriYXiyEoiFRoNAmCWWSMuP4EvGSYUfk7ut8CD78n+j+iqqihWU" +
+	"fmZb8RVjX9LiIokXhgfqc+hjbZR8xHTSG2NvltyeEkBoz+i+EBqwZMS3bqJsEaIa" +
+	"GhUYwpTgGQIwCHFSPHf9PH5soVQwNtyu3LdB4H7h7qHvPtJPgw2vhhBmwPscrZ9i" +
+	"B0ofZ8/K22LZTR+R6NBmMbWj+o8N5NK4btPxmPo3Yvl53M08zTwps2Ux8n29W7or" +
+	"ecnOTH4LDyKfk9eenmurrptb6EDAylMSyCFoPt68A+P2W2rxpvgRO7eOTE06p78T" +
+	"pM095szdT5dJNkqV9yvdk2KjRq7ZNv2M/zD1uISNH5LRt2dPbXxwgg+aSTdJarr4" +
+	"+t4IO5+isaqdYSfl2IOJ0ntA756tsBY3I66SOBHlU+0+8bWUbHdtxa1P2y83z5Pv" +
+	"NqJ29h6ymz5tztPN04yw5+OsUx767u+t4Wb68vvztvPsCb27OnbrgHffegij8Dbt" +
+	"R+cpqFnrpoO2jCj+dtrCBfwtFtxfNrZd9ZcQzVPa9qbeq8duMYmVfF+2cTONb3u2" +
+	"m+N7LwZwK24TMUPA/s1xS2PJ211vg1JfBUXQLO2tMacGtLJmttPE59YWnForCNrr" +
+	"vbv4+/xy7+NG7BfXbnqKVTuo0DMuFW6c/DBvb4i5+crr56qLSmCHWi131w0DRNem" +
+	"G8J8mWF6/BavOE5YJruAqh/e19oRd79a8j2xXHhVteYnEW9a1AvE2WHFHnr7Wf43" +
+	"p9q/GjSGtZb51XBDR5fZe/afXwzt1jTi0aTqd5pQ9xPS9+tflc68V3+R30RS3anM" +
+	"Z7/OYoK83au2vY962u/PmnmvWmcymeWxxPne1H49bc+va/KVHaqJxTgrqcN7zDZ2" +
+	"TweudXvavlknvqpsg6zC6+IavvB2enbrx754TjNRir97rpG62S7VPnth+nn9KvmF" +
+	"thTinXkTrfbYcr54eVPbFQRF11vTW9+CcB+4r3XRpMtsKWHnhn3dFDF7PYpQoLeU" +
+	"zh639UyDF5ouhQerfW+FKROlO2lJwm+UDcwvkjwQ51nx2aQ+iINt/lkDDTrmb2vr" +
+	"xryHii648Xu/tF6QHbUcIFxgYRp4+V7eaLG64b2su+ONNxKEDlYjMR1Fuhvauj8z" +
+	"eus/aeYa2iB/Va1tuuH2zjOvxxxonwsbYInfrnTPNs504yedSRkJR0jeaBvNr5mG" +
+	"nFr5TFHNub0FVE3034E+q7tfF5n54uuT4o+28bYpzjhtI6mfB4jbVMEd31VAR4vi" +
+	"GN8Tu4umaeq9qLGLNUsvpQu/8faJd34UW2pXhjvaq0NFmKDNZ7UjVrNM4aXvd5pS" +
+	"g7LW/5p7955Vtvf6tsMfFl9rs3VvkKnfvemaXnFPGd4je+Y3iU3nXv37xz8/Ot5b" +
+	"nc6a2J+dPSXnLYpvqfBk7ZifA8RiUeNNauSKONwZWKpMDsKhPt+f5X25+dAjco/6" +
+	"X52E/Ys3128FfCeI+sV1Ngs+8/j7+sqrWwKe/0ydfK2xlW+++7Sx8Nr09NQEOaq5" +
+	"Z21TVe+3euawND9LPk1eaTWOD2M1bXSfq32fH5WrqCSRodPHmm85a3Gq8/ldR8zn" +
+	"NtO6s/E5oRyyZ1pX09q7BTxk/n5j1O8Yr8nSj+qezJTO/bzuIo9vLwYbxnRYVVut" +
+	"OL7dQJYPFNnRyNDLjWmONtQBd1AxDZA39o0QEps8eiBrSOQO+M2yN/b3A0Mr9bVG" +
+	"5A42A3LcI0uBvqcxzal1tziFTfaXakSnUaaNpTxpS+3avWO1hvyyUtPUe+uu45yi" +
+	"4aeNNM2GnS0nrucvjF/OGhoOnW1aB+Lxnmzq3GyztaXeuQpomp1FUXt7Rffavj8e" +
+	"Jxqux8eyex3ftOU4rXxtxMYwPRqwXX3Rcbx8dn9s3YtPa1XrnZx3dqikI3E1b3fP" +
+	"b83aGWPme0CcoGvA1o2PWLs1K+ceH4fTFuVHzrGWGpHci+dabeFi0V6m3aE68H73" +
+	"Zw10nviGOyJI6DzqzFDysrN7Vt3elS/jFreqKx+UpRu/mfHbO2Jz7663zp9WvTov" +
+	"vvvi14Hr7KrTbRduDN4R+UTmqrtsy2L5ZVHyb3Y6t0R06bVXuuJsOJpv5TdGqPBn" +
+	"vjuRp2u8z2WyNdKcny5v9uOfk2vv7aaeetW8z7wtz15nB6WenehxSnftgbkj3tWd" +
+	"Mah+7rRbrONx6m49l1arhpoQIQzabRKaTwFVPoKPOmlsaT9tWeFUp8/XrDuFrtXT" +
+	"1Ap74Ub+kFY8KMkmQ4I7OOw17bYmTediZ0ZtqXZakoO7cey6d0rpPrCrpmfgHM/b" +
+	"a7hjUcJ7c3OM2GCCHLLJ9KNHOb1c199tbZc8EKX0o9vETvYazOKX1tnTN9u/0fij" +
+	"7WpVRTrmmb7c73x2zlpOsWq3PBNjMryyVim+k6qIHV8cZzrm1NNNtGG3WiU222+q" +
+	"WvilXLVPDTtuujYqnq92HkjtPrnhn8wfFVRtPKbMlam+ja2nZNWzVGx40FOJoI1m" +
+	"jzX8RMGuvpd/eu+lF81TFb00pDIz9nRKTd6RSnvt2s+s7+qqt/jhaRHwyffKQ/z0" +
+	"/tG3K+dUXivrmu3jC03fjSsNvPfd9sob+3xr8iPBlBljpK63v6fnbHtxKpDNFNx4" +
+	"fWXi+m1XLycVHAWwI7iooCKfX4XX8vjqgNOk/E9udJqie7fMu3gr4Snj7XtqUiPX" +
+	"k/dmGsfHvAp85erxqS/xs1bwlgkOcUNz9VxavzsJ6RvKmczE3Qfa3x8N7dfP19fV" +
+	"5zBafd0+t4Gv1r9dSf3T6+afWJ0nyP0YagjzqAokAsvA5HMvICycScGRH5DZSUA+" +
+	"4yHCgQfxOdfUK0SiI3A5uCNvta9mxHytvJydnbe2vh3ekY7Rp0aKfJeTkcPDZ8Nm" +
+	"PB3NTaen67W1s5nLDjLOzJpdra8zzbuJp5Pt6W7cnZU5vM2/Y6dMPz9e5Tcsdwed" +
+	"g3dJ1jb2DdpxJIz0Z0kNPqBsn92/s4FF+N/glGnYgij0wPhQuH0EH5P7jwhh/JyC" +
+	"zw+Z3IMdOXTp3K3ZOHCvyezHJs5atrTSjQcMZLMtxWHd4dXKNgxw4aZq3nzb+1vu" +
+	"cjpvN/b6mqqpFQxWMPRn6H4LFK8ID7PD0s4SMs9KL0KMPT9CxUqLPxoSUfQf0KPy" +
+	"Lhh9D1vz6H9jW/B0emjPs4eCR1R8HP7MbkZSDnGyW2fQzpoFHCz0g/k0/c8XzYzM" +
+	"Xg5v2dmmnecnavJvG6+L5VVNPmrir5NP/86vZ5HJ8Nnbq3mj04tjyV4Y9nm2eh0f" +
+	"qafNu7Pns6K05Gnm+zfa1ps3fD43tuO76Gt3pHDu2Z4fN0c3eclcM5W46KqvgrfL" +
+	"ZZ8Ozk5zj2t+GJ1OZux01LfBLof2MVLIb+iTTw/Qko8MWFEI2oiP1WGGjYyKLrbb" +
+	"fh6PuDD7yk3srttD0dPqECggsURwgcKHFYVt9Z+a1C4nm6Upa9L3uLtW7mx0YcK4" +
+	"Kx0dfZa/Ltw8n9hXZ89reu1qDcLLcHUQNwHtoWoGtuURwwrIGERCPzCr0EbZJDNy" +
+	"QYwp37N0hT9ZQ2foLh0PmQ4bKfLwekfRti0fBA/YfU4d3PrbbDZ6xtdCy8gjwLiJ" +
+	"ERJhI2+1B1WIF0FdF1DCwjKkl0UI4z0M6fVMf6venWbllsbtgcPvILqxNlq6efK2" +
+	"Sq6vRw6K51ebu01V9Z5ui4IUOJjUBhQUeqIhoDPBJAf0TLYPoToLip4WdGkzxt/Z" +
+	"762yzA4Qhhh4oHIv3KIDT5KmZlTKwtaWOeREM8623/B6elo8Q1JxiWAgQncQECgM" +
+	"LAiWAQRUxWNHd3dxdjkaybr2VslNjq7NlVT2j4cJ2ejho/Rk05YtfCzu1xat+Hdu" +
+	"91cvNxDspIbRFIVURFCyHQYewlUKLjAgdUHOqqFXQdDAGooOZKIyENwSUKq4sEFR" +
+	"yNRMUadp0PLpEZlE3GfqYaDKGQcHDf7nD8kmHDRh4fwWWYffjxw24caYWfk0mkeN" +
+	"D4SFGhHiVFbu2EkgtHFezxIqaWnaEdzJFsqSNEFKpZXphid250aNmnZo7ZMVlx7m" +
+	"zFVXDo03KvK3TTdqZZZ0j34LqeGyvh6K8ns4bdrequzHYrNt5jMmO7tq3Hk9GTU6" +
+	"GMOGnzTTgbO08zq5PJjdy74zObhx6M8nJu5Vc+Lbm9uVj1ezk3q17t3D0exwYMKB" +
+	"pTOURDWRGaXREECYuJhxzxhETUu8mXv9Vjp48d1lC0/f0WGgxkH1HjiPyUUeFBGO" +
+	"am8bm7o07t3Vu5lah4OzS3020qqBK4ICgQPb8h8fj69n+3hleET5+1Kk1maNSlav" +
+	"R9c8+++/Pnenwej1erxtb6HV2SCSSdrJHVYHikZUg1ZVkDtUEypDVQZTN8kDSwll" +
+	"keMwS78akNOMiJQQc3dihLlKj+oCG7aEM7oG4kZW1NVLsxIVjJxmQMVBiUTaWsgY" +
+	"DYxiQYyPuBXhdUKWrZb79D15ra7uMfLW1eW8dXOaiNhdxQslkuUzMFKgagC1Ehom" +
+	"iOOZC4AyO5qNxXMVogEhIpqSNRe4grNtR7emHctEhpNtsXLSm9xOTBmOSDYeNILY" +
+	"2DG2ibk3hUFnKtvTMXYBFsiI1xxoHjiBJg0ZhC2Vig602I1PKTNWvbUbYm/JAG0U" +
+	"aUsNNFafJHs1SpG5rY8UsGwe7VRhp+PJFmpjr15ahtvTFpqhuKWCg24WKj7kpybZ" +
+	"c6V5CsG96jMayx1GWUOgDVCIZKqhixI3lLuejpuwX0E8/UR6+vsvzdYqEqnmqYPr" +
+	"ynyiMGXW2W+XV42wNasYmujHR/B20ne7B8uftj52a23ykGf0r2Fya3xEEDcibiTQ" +
+	"0lZLgyC2ePfZkNiK8bqa+t/uN5kVHlxN3dckC7FJia9ve/Uugg2wm6UBkqXOGuys" +
+	"qBJmITKhYQIImk5o5EECZQKpHrRxXGOTi2LXQmqWh6LhdyTi01SqSQ3VOEDXmHyx" +
+	"eGS7oe6mzQZ5CDD00rOtqeKJjKBw+ee+cWoiUVDVLJ/FhK0iGh1VeKiES0TeYm9Y" +
+	"aEWwQmDQoQiRwvF1pOMzCkqwS5CmptDqzik403jShJgqi2UaBbWZmCIlgrKzuoHE" +
+	"I80UvVUMTR9bJIWy6iiIAxXukg2P4TDx8uds7uzmTTj2cu9+82j892bLO1fYjuV1" +
+	"nOX+0ET1+9s/q59/SSQJI/0pffnnpk32yWNNLZIyLEInER1S3+6lv+L1te04VnqI" +
+	"JI1eRIDos0ygqI/u84V/ySnvUfr5/o6avXhuP26/+dG413/yfDY/hOza/3m6353D" +
+	"FQf4gPLyckmNf0/Z+79v75+CaSQkY8In6aqSH03WX6Z0X9VQB/vFWq6C5csRuvBZ" +
+	"nX9ytV12MkIm7FR+DLJ9H6IBOuiLogQGQ/eRgyJJAx+aYLFFoFE+nXZEmdeEk51K" +
+	"K8zR4ejlk1Rjyd9OlGOU1IHRC4Twt1lj8fuDSl+toyn7KlPBdN9GfhbdlfyOpi2j" +
+	"7n1z3jf4hxzT5xvpenii/OQ9atPRJOV8YpWSsyBkCMSKpoqNVJ4qi6kbGS0oTp5U" +
+	"Ze+1/H5LYmU6Uu362dTHpJsyInEO5DvTRhC0noXDbUrY0aAqh/N252CZJLYxRLww" +
+	"eDIgJvhTpSsrEJ4SVDvd9S6BwlgfShNMd9KmGrWk3I52ZEqkIKJiiDZgpwVrTuGm" +
+	"0Uo/ZLXM3bFdFTPSQCOxHSpDGrWnDhd5Y05Lm5qtLILG02ERoixRXRkaboZjM9Fm" +
+	"XShtFC7OcoJwLVrbJ2vpmlco5wxxJm17X2pWtUowXbS88ViaVfl1mbDdKMZhHFFV" +
+	"CHEiCc2ed3C08Xm0T2nd6Uv1K0yITQlBsslUGWxQP4OXJVEfYPWUXA+kdcuh/+HP" +
+	"wWUH7diyuFPB1lyF6ZrDIprJE4SEZ7msK+k6P1h5hh3qskj4roZNzZTZjCbg2ePa" +
+	"UWtQoyUuGzm+j26e5Sjd6d8bPnh8J/3oPU17aMyljAcLyiBhr8j7ZOg/Q3IF/0Ta" +
+	"f6XwNY0RdbAzegLT47336Ne7qtUughSk2m77D7Kk/viknCAADCufnfnmfRa+PuZ8" +
+	"GbDsi+jRFrzw3ixPHSw07DIXufXiw4eHq9LyQfWZnFx+S0TQXRM1QT6QbNSZJj8m" +
+	"7UMbjp4V/ZPnp3lbJ4dvxkSfH+zJaG1+r41D+t7jCD0giVFEsaiSGe8yzuQcIPsg" +
+	"7JTIOFnT68Mlm/XtHO4/DVboellFEFwpf9tkkmQRHs6yXoRCkuKPxU4Z4SueGdIi" +
+	"CB3cE9RKuhrCdlwcyTChsiIXrJwrTvs9M61zkDIsOaTPnYckuRlvrVGxZx0zpzzt" +
+	"8L7s4WtdLbRACW2FaHvN2uU7i5n0qt00Kgy9iK7Jba3/3pNiLNMrM1XhIIBPZHET" +
+	"RypdGC5pZhk1rtje4i3zM6TWPeYQEE2ICad2RgNnBwoZOXY1T9NwigxKQAH9P9Hz" +
+	"7gx+I7Cg/gWYSkB3Ml8YRVoO+7qZcd04606nOv7+wkB9/5D9dwJKJD9w/pOUxtmf" +
+	"p+39YZxm/5BaSsnQxtYbRsXraiFwqdRNWIdK5L46DjXUSMMKSKJGX16puhl1MLFs" +
+	"NjnoaUBMXnCJ+Kus2EV8F1F0KGG54HeshTQt8laFCKcUvV0VSQaPOy1KydMvj2Ez" +
+	"AewDB4P7DzDchscafa/a6vq62dZRm3G2jIrBxhr3MevBrYhskfQQhIEa0BTQhzBU" +
+	"xFWQUuAIPIiFQc+2IfQGI/BwLEPA90bT/w9O6Hlgj+ABZZYIk4UKMgIv5BFETg9o" +
+	"QqCd/YV/CKsIEgWiK+Iqgr+QaKBHSWPIIpYAYOlqJTAzWgXcJAWQkSQfBkVzkTkt" +
+	"EBuCK4412dduYOlRLbTkd6BOG9mJ3lkOMIivftOjRKpUQ1n8N8AXRv85sESi9I3B" +
+	"wqNAL+SbEH87kA4Q0iLxfAXQzIiiJA+Dio0PfHBFET4KwoGEuhuF0X0+Od6iPDZB" +
+	"vqe2ZbNmwwwQNnblG4ZREfEADnQldENc+vyD2hPFPDVaTmO6ErcB2CSrJHawjBeT" +
+	"Lu1HHXecOXpfFifajXzf803to/li3IQraCMnXE7aNaF+UhNCJJ6bST1yCMSEkvrk" +
+	"EZsiJnq9YnIRyfoE3qs1+5g4qCjgAB/d3LXII3r+NecgG/A/EBhNc2cEhOijxJO0" +
+	"FJewHGBzK1YnNiLkAPBkUztU2GMpL0j31B6VEaAuiEtObw0ViA2Qo2CQrPgdgapv" +
+	"FCGKU5zwAX48rSmSGfCh0sBAp5Vw+mHYBmgyfBvQ2gE9Qiw2eCK950Urem/KrOD7" +
+	"tAApA2iLxtGRmFUGVZgNFMIQi7APICVtlUdVP5fqGLX9TEJBSYcWuJiEgyD+whr8" +
+	"Qt4j0BCvhFy3AUJAHpE2ATCfY/XP0YM68EHwJaHTWChL8gPdCT9IoJW04ShPtj4h" +
+	"rXUO1N+9eNBzh958PwJ3onum3eftLwTIIDagDw+o2Baej5qT77qlol7lfPlQODAr" +
+	"7Qiue8ErGKQIVtOQ+yuebQ9jz0QHR0XSF1f1oB0wm+nhBsV5Dgxx5TjC7ifRJgWQ" +
+	"JQKDKZ5QcF8aA+2FRB9siyFbQEtXEFsiyD1KeYp4vn1kdk65sBN3fx5t3nO/Y59A" +
+	"R189AT77u6pOAXgcINOFPg0rAnT4ODvDpDvB+Q6AjhNjrJ2a9VBRzOAGZ6eDgd4b" +
+	"NoM0UeBxPD5FreuGt6Dwo9RFdb8nAiAa2R1p49xif5Sm4cGGg5x+6ZreF2MUxiIK" +
+	"+gryR/PfnDI6Q9Gn57KlMJ5766E3pkiWtHqD0EedIKlAC3QaBfbl/j82SCLdu7yW" +
+	"v6Hmk/T9Y/qXglgiQ/aIREU3sfkhFsOhToBSbFaUQBrYeBo78wWrCIiT9D1wcVo4" +
+	"GjuBz3joxqZU7bQDFwmjB5e74MBLoK0PA4QkclbwijNF7qEEoFkFRROi0IZfN0sI" +
+	"zwihRtDz4T7ibJnxZdmKq4qOeIUAbh8KmERXb9nKQ+5QdzgDPcJjvxw6bZ3TBIWY" +
+	"SSeN4U3EZkhKxct8oIiTDi7lqOt3Kvi/tFCQEsImhN98ZBnWjLEBK6dw+FxgB1I+" +
+	"dDUAkMR8mm+NWReOPvBhDZjk4boMpjxoBGF5Lqkt7tL3kyTUNCK+PoZx3oUqB7h4" +
+	"5wEXO/lduTg4NfIqAh8ZfJSAcG/jGkuHA8qr7Ro13OwIJLia9u+yBZ0dicUAxwCA" +
+	"kEDreMjHsNGLghIQjFyrYc98oQaGSKediKrHfuebY7DkhSaKvv+X/oH7Ij+oKSLw" +
+	"2kgfoPv0+vpfWeMjRqQk6L7QtAATi0oNZJzgYxP1w4HgU8+oYPhFESAjAyvt302e" +
+	"CDaAWgGAh7Xub6oUY6dMeNnQh4yl+Nm1AA19panR4CYHnOGiidVdfdsdGvhv6Zx0" +
+	"jjJBqQawcqukBR4Ux34pXobqCIL3lHdgOad5nLqYjUZgE4QvtAltbhvPRFES+goc" +
+	"QfyAkiF/e4WiKYNUIFjKWJZA5fwJczRRibFGT6zCHofhgW8eydxvZ1UFHu97Toow" +
+	"8FguNJpiKoCc0GQAn4ceHt3K0i1feYVcihrJaNBCZJgh3FO6ENqkEW9eLD7vi6wf" +
+	"fT7OU2J7Zn4VPfXdnohaADg6HCzQSKlLKttUpsb9HGGYyM1kdbG3LRyKBaAlAEQi" +
+	"6K3SwEpXNuY3BAQX+wSMOhQK6JuJ9BbiQxBRmAuim0FUeeYULAUKioFQBh8aR3Mo" +
+	"71V1gxByA7oX2gGDQe8klFNQQNSjx5kWPD8XwbJrOHhrmPG1eVz2hyCeCzw70QRm" +
+	"PBaXfmHpq4d6Cj30CwL4FmzRhVE1Z3PXGd4oUT3RT2fXIk3Tn6hAxuw6R4ZKzAfB" +
+	"E2O4JIhAk0YDAlY3e4AHkEgAr74ycQwAnQW7rtlcpF6JZA7VNu66JrCcgjUCEFCE" +
+	"RpghIiGj2TWA7EMd0aiCjpcIQOLL43hkAKrIRD57bdINOGQ01LwiQc32iwDYCMaA" +
+	"kHwImA5vu3GtiupPVup02YPe4G+iICJJzomO2gryY5W3M5zx7DfU8YCDsEXiG6zV" +
+	"+xuOJIG8KOYoQjJHHsGD13J0uAvNmGVfCbv+KJrzyu7cZk07DszWZjii34Z5Oq4J" +
+	"YoGxovONSVdyqdDaiI5o1E9gZEO+MOknbKrd3vCGjWOSCrnI7Ux2qgrF1ozkJ12i" +
+	"qiB+Qq2iQl6eKyIKevnnG4vy6vIfKJt1EpCX9n+P6PQpAeBRKJQ1sOYCWlkXAgV6" +
+	"zM7YJl8sa21D2vb7geeO2SpmkzN+KTwlzt0iohA2AcDPLw1FWDBUJvFW9ggVk6Dx" +
+	"nW8ShTWwRlT1sHHJyMsXFDhNL6q7kI6WJJzpELbUQNVIhmsRVy0ajWqqiK9NrXLa" +
+	"rEhagikVJEOvbHSFh2axoim1j1bJkioWVpJnTIwotJdInhXvflf6SU/PPQX0bTPh" +
+	"CdsP29ywEL0SWUfTCD7EJL6ETkKMZq+XfvOV9/V1w3yP6vw8Bs00Num+z8M7mbcc" +
+	"Nyaf49zDIxUaQ2EvqlaeEBsxpWMXnJV3xw2Tk85CvjXKxcvj69eMUfMr8bW8bRbU" +
+	"onKyW5YZYTLbI2sO+23t750Nk8klcxbgYLeIcQe/QCQJFkWj+oMfqaThzaIrMI2P" +
+	"7OfFp/TvReP9gGjSGXxEeEVFAmDkEvv9VUZSkBPbMF8w/60D9GpeH1QCFw55QkLu" +
+	"z9IAXDqKnNMEC9ziBCmelf4wfDqr8bOBhgIc0RJII4qPuV5Nz9AAJ6ARU+oPi6hT" +
+	"+q8gwvYgoidW+M0fbI8rtLFtXO8iTUFlJvXeyFxmJtnkC7zuiaT8nGztzQSqBLOU" +
+	"ovW3gp+vzfBxm7PhlVblQM2bd+/Rh4dPRBvEDSXngueiAwyDAY7g52aB58+eG+XC" +
+	"rEW8lGS1QUeWOAT3cakjvwRHNevLrWRGxOBmTNeUHz5BNT4o+AkxZAgM8CgQuYt7" +
+	"U5ikqOco13h+zN5A3dAfUbWApJdeQtkMkEkG1iAUlofiG95daxu0Xul4UwF56lZ8" +
+	"3m8LyQBioWOMnxAZw8H19FHnTZSfCQ8UKukI6IKbgi2EROEVBFDkVQRmNCWiK5gK" +
+	"gjqIqofRAygkWCEQQOEBE3AUBUywFE+iCoPxHKo4qQYSR0uWSDgsC3LBC2FUgIbA" +
+	"gEIgr0IFBFEV2beEGgOV2VCEkasTeUI35YWoqjQQJBJsaVFsgnIIYIegAZiYinAC" +
+	"KCHIB8L9aSU2jqpgHDRm0jioEdaHayC8iYiN6RSgqyRLYbpYJZUhzsQdYEVBA3EU" +
+	"HoIwQQ3BFaiKBRPagNKp4YAbiYCICDIIOliTxeOOGnL2EcaOMNDMGJjKNGgchDj/" +
+	"BKwYSZqRlgLQR7nzcAWpLACURHNK7oqAsUjajiiYMTUESEVX6ICF+TFgwSIL3tKF" +
+	"+9aliQFdBBB/IK0AryCL37njuaj74l8yZNHN1lSjgfcTgmPsJRZVGcrSr8IEjldQ" +
+	"KtmKapHX0QlsIki0IuSRcABgN0Gs+4HbDqPIFBxJiVh3OSukGiQvd5nogLDQRteh" +
+	"2MyW2SI9oRhikH4T0jXdxNxJF2Xnskl3AVffHjA67x2y8y73Yo5mAE1DhsMmXJEc" +
+	"XQigaZcogCwOAJSmvkK59/AZt5r6CHoKYtZF6XRWBxO/0HFiG/lmwBS0IXvAvwXw" +
+	"uNK56cJCuiEUIhAnVsVC0oQ/LDomFtpZXfIu324pRnto5FdNUA7OBqemCvdxU76w" +
+	"rnterFGPG+6Q45tXnD6WRacT+nbNIk1JCPpi9vz6KPo0aWTYVCFR78pPNQgpwlQo" +
+	"7nZl96ldo0qhd6oAriD7PYX3YjYi6+KtyURx0Dh5o389ggNbU0B+KOiBJNO/YO34" +
+	"6a7wfKK5PBjVqgozX5yrvYe4b+g/eQESyAJYADkx6QeCQZ6hHDToVxoz61c19ymI" +
+	"QUB4ySSEGSTHhMs0Tr7Of7v5ZHrYzWRqmxy/D2PVnfrHr7nmk6vMiLt6Pfbbft76" +
+	"NqFfrnncwD0EdL8qWqmCRcAGdrsAgwQV6XyemW3csQRzF17hRM8sNaA5u41TovvJ" +
+	"lL6Jmj0Qdj3rXVUPYlIJEIbMcN6Qo+y6+Gy6V0pk2Gw6o2eXyfFnBOzAXCDYADzR" +
+	"CSnRaQYZ+hwQZ0h7sXXIQK0DQwbFchiJ7Akq/buuqEJT+FvwSPhCs1JX34emWkc1" +
+	"+0JlH7mgV6fdrze3n1BaU/HP0Ip6Az60FlmH0F+FDieRNSpsh3JnZieg899kMapx" +
+	"A2AgedvbfYhjt7fwdfgTf5O/lUCeRAZEpJHwvsvi+d3wMBEna+Z6+GGGgCoek/BW" +
+	"dQo/JYryYiLihedIULrmV2fAYIU15yOAfqwHuI8EwYI7aM8kO0X6aYygiiUvGaA5" +
+	"AqKrb3bLK3Bu/ws6awNQMldRV/OihvSGeGuLuQ5zhdKQyvBbunGHiqbSVBLCBBR3" +
+	"sJmkCunDAXHHd4eQxhEGRYdBzZu7UXXMiBb3M0jRVaMN1xw04qyJ8G6DCyAXnHwZ" +
+	"RDcJFX32jyXoosS3eitAOfuZFfqdLyQBCCB3aIfY2OMhjfbVA5gUvI4NI0ulOm0b" +
+	"1FDfrFHR10hZU+ODKMCViSStxuklLxyrOzBrvpkTD7nncH/YWN/xZ/cWB4MEWMjo" +
+	"uNq+pDjINyCJIMft7GzDNPmQMmfKO8C3BCupq3ah8aC+3PLydaANlYxbybhnNhxC" +
+	"RTyS5wfe8lJ5C60b3pGVdQBEF12XTIjMtk1B3sJLjW843JTV6tmmB3szzW8PCNWR" +
+	"3yd28o27CnITe6LTd1rriEPv+r+W/Lr2jtO7uzN3c4O+Tfc02jcUkrJR8QctADA0" +
+	"gXSiA676RwOkRHURdCHLXIqelq5LOSTVlo0mrcKsbgjhEjApzpaorkBLDgWikaMD" +
+	"WBmkEQLF3ZzJGd55Vbo6iJbSXTzOm0HEagBiaN6SrGSjgMe8kJ1BRvIDKb2rTVuv" +
+	"UjayCQnFgki2WkEJGRQCMRewEqK/x1GDBcgGSKNrCGtI59lyNKkdOrQ0UCJT/tYC" +
+	"QsXuKTErgmB/L7qWQAgjObGxtYRpoNAhObSe0Yb86I/8koc5eNsi+mHWzWtVmg20" +
+	"+QHoAlFmGJHkyHlQ13uGhptHj5jDJQi8LDIbkOBvKk72hX8sJ7ueW16GHGq4y9iI" +
+	"j3yMYtSIbDhrWwlmqZXVJRCqouUAUhKKoGCwqjpq43WTfM2qub+jk2T4GKHeyOVj" +
+	"tYdlk++2vs+/+x5NvlJOLPYmGRLWSHhDrPt8vLxjo69Xl+W2ESbJz6o+epO91qFW" +
+	"HfEcnfU/36UAcqgbZ7xi7DdKjmP6OdAd8+vBt/QtBnxhQ5Y55yjps21VoCjTyYLL" +
+	"1CSAQTQgB7K2FHCvBzdvNMXNbRQpcZKHabwUfuGc374PhwMYpCQXoDnJZi+6wEgi" +
+	"AiX71dMRdTfvYRIwt14Tk5HPrJ9sRIYwCUOkZlDd4TvtfPdgHxB1w21pzT08CJyh" +
+	"7Xc8oYd9ZaSpdBvqDRYUDhA4KO7b0HDw6Hwa7XttFLJvwUIDpRXAcDIRWHS+aUSz" +
+	"xocp5qowJUFyIVcKHx7WHevE5XHZxO+4peTzkklyu0YuiXbLEIJQUcsg9pabkI/h" +
+	"od3gISwZ4fwv1Xzc/OeFHgwtN7OIIX02fD0/FYKloiIWHTB7PYJwBsz1ERDlrZJE" +
+	"YDEhYassKO0HhjnoW2l4pHuKoFBPAi0IHcnEsMNIUlBMw4wqCkAz69wRdbCpCqYV" +
+	"IiZOnuCR9k4a5ZjWNKYUSxiFzpNQQUVwU0iIm9GbESmCr3RFQr1Uigjc4jisu4pJ" +
+	"puPoO5yOeZt1LgztDDSQtUkU+DXS9idDpAhOhoTBeU7AAikkj6CLUxCIImIIc+BM" +
+	"GVzqBtTlqMISI1Sc4AgyKiD4gcWAivyJqEowpHETkhIOIUiJAsq4g6inSDsxKRWg" +
+	"Yt+3owIGgQI7FgKRip6JhDOMYUVRT0TqgKJELhtSrt5BLVIqtKhEQLggZJ4QhiQR" +
+	"Gq0Cqrhtk6wQnTdrZdiQdLJbBMJNwoI5yOuHOpAbHCioJ0J6YhibSGY1HllCJmB4" +
+	"jcrMaFD0ewXkW4ejjFIZTGKo4JHcpSBBPtd0Qxs1vmR1w4jyA/Q8IHSlHwHq+Ee/" +
+	"WKYiGSG4HC6NiRUCLF32CGopcnwE7g8WC7D27ysTrEzHoRC9BQyGYAhkqhOQBwpF" +
+	"wUlY3keYQrRXorRFPA+GhTj5pDpAE7BLgAlbrkDpk7XdBkMCe7aC56ythMcLyB5M" +
+	"qB1IiizVK6jgSzmXFAgGIgqwIgA6EtEewNxEDMEKsvoUzTnlKA5iDnmtY0XrFdi7" +
+	"oO1avSIz4+XbDYhpYNbXls12lualldWW6Rmvp3XiSn4tr7H2DBIdge2UHx5TmHNI" +
+	"B0iD6NlFC9gO0A7Si+DLWvYUsE7DYKO6BRETeHLcg6SAFuaZ2hO+UAetihqZiOFA" +
+	"GI9nCa1gvgaJXoNNThLNEDOVQpTOKJxUxb7ouRUN5KMOSuV3bdQuokVEdMKFDQPm" +
+	"AmkMhmx1/f2bHBC8ijYJk50C6E0XqgwMJ6K9wOKaAATyGEoaSjjPogj2CyAOQRZk" +
+	"JxFQViYRM0i+Ei8gAZiihW1WUkg7JgoKGBijbIMenRopoooFjRhdB5EbkD0B3K05" +
+	"69Q6zqcbkOM1FpwnoGyJMqYsuqUojv8cZ1sKM4tO5+rCm9ZZJCE6fbttA7APREM1" +
+	"9CSIPRp816UCN9JJBPsHGQVvYZdivqFy+EDnwVAwp4cGED2KJDVUXA7yrAlwDiMK" +
+	"5xTOPCYrIplcSlucCUpqSpZoxggu32wzjnF2FlIidoAllPOFbJzD2SICWniGwEiA" +
+	"3QNDcV1ngXIKepNW41sRWLhvPSg1vwFIhjFd0VnVLBR9WMhksUIIoiX6b6aI6gwm" +
+	"eWGTazqFhRbYz6BwdaC+k9L6lESGVK0KgKYufORB0fYYzTnBemj4BH2gEaHaaIrv" +
+	"fxwDWvTnqdY6WgKUpgSoZrcEXkiQwPFhy9jFIQUORTJpUAFrhENwKQV1OLa5FQdh" +
+	"FEEkFVhFQCQVCRUlRhtibMFYg7DmjWQ0vBThVntDVh0KBEg8z0VFZ1dnlwvOxCyV" +
+	"yFg6KORRzKtb9eVaU6PsPpQ6vqCxMQymmlu1MoOofNGJrbSJqCnCG0ZkU3SmgEqj" +
+	"ljqxILxoC0NXXqMYPKZsTNGgseiQX1Um+tDnWCzEFM5KYaQwiK2hebBFtFvWbIKl" +
+	"A0gySQIKEVUFY1qkKQisEBDEYcpVOMqLjVHCwFV4coAKcGYVaniPIi0IDFCEO6py" +
+	"iK3Sb5QtwUTkeVRqSZvgtiPRiC9YmOGphARNmQ6kLF5Mm9RN5UknKirNlCkLBMDw" +
+	"LZGwouEWmYel0VvPJk0f9vqDgB1OMRmKZKIzWahOGd6NWRFAnCIXEL6B0Uc2fl5P" +
+	"sIeQC1FobsyuXXTiCpCs4yTW8WkdGVi02BNTSDmtnKPWeq9Y4twF4gEpDgiKRGKA" +
+	"rATvQoMREzE7FMRAK9ixd+aTuQoIDMYQZSoQTcKEAaDgwLsSRHUTmeBlwAjqJW12" +
+	"haMGnPdB7Rko8t7UYLQRAzDoHldEqn4zfIlR+ahTFDj40bkEs7N9ubb1r5Pkz4P7" +
+	"KmacMbzsQ60kjr28eWZT5fOlM3PVqKOMRxDR3mUfp54ZLqzcSJorg+9hoxMGzVzk" +
+	"E32DW2JtbU2qrPLpN5Xpxamjzu8wb1lW8jakUx6dIsLnCxQwpEzLzYbSCTWTEZrw" +
+	"p0sG2G5EvMnZyhFFF5tTkG1AZohFJveaYcvskKd5SozIJ5nClUEHKNtLZSLNdA29" +
+	"uDYo7sXxjC44bazLkkiHu8qrYzJnnJ2oQ08SqTZVlzXJN05fOLkVt9y4SAdhsUds" +
+	"ETItUioA4xSCJRd2ihTicgxYcOnBhN2OXCLbNOTBhkqTgh2g0U4XAdMYmaJDRnHR" +
+	"R4Lu3sBvFYojVUFkFCHnDpF0yh0wkgezuLUwW6maOnVNAne9DRbH+AAHETar2+Ft" +
+	"41Wuaum2jm5bd3WKQkCQUMg9FB/ynAQTMVeIB8oh6CKP0EAQxoFOUgEEvm7+N6n5" +
+	"WSrmuWdsdiR+nu8pv3szvUcbeXbM8Y2rYHrC4l+zyLjDfmIMYVsENPkK9m6v+lyT" +
+	"5D1f3aEZuONmS117lX6NWkjPZo21sYFwu55fns3WZHrU9bIXYmXLdyesJJhtZsyP" +
+	"8XuYeY2qPLzk8i2eMXprLlTUee8pZwCQX5F0LaW8MCu2YWI+FoVCAHBD2BOl9jQc" +
+	"oGoiISmkexUTRuFCkqlW4ITOGyomsKYHBjZrY5wncn7k8ejM3ET0XYlJU8VglCrh" +
+	"D1mEVbUgnLS6ENcMUAAwOwooznxlE7lPuAKOBPjKFlnYC6ADqLSrEfFWgZgi07lQ" +
+	"JqzHsmsUg1ZBbG7lW9a5qOWxHURNRDgomOIhVc+e4RuBqAVWjExp9ZXgMJ2l+KEV" +
+	"vOwwHQfplT6irimoKktr1mTvMn1AI6Nj8IOjnF6dHXSm3bQx3SNAEqFigcKwa6F/" +
+	"BubLQ9vcq85KsS6AydGpaE6qtgkARpz1BKuNSoGBOgBQ5A1kBa73YHOdtULNUiHq" +
+	"pDygDESZngsBXWfdQdUGGBnhtbsFzJEXO68eFC4N2M3gCnwhLjo2sgkKuQ/2GLWH" +
+	"g0I67776B8O/3enHovnD5QgD5SX19KJhml4fQjZ7+0Q5JZrA6YidgWYyY4jl8xSV" +
+	"sK0myHtg0AKidGTG7nAv1K6y5UVikEpJJeVcrzdb0hpFKVRzLlSn17KMaMkjCTLM" +
+	"QQ0FPTr0SQkXhEVoyWhvoQ9yPsIB3yDPeHXPwPw9rkIoDOGz49jxbEtALl682Rhs" +
+	"0JwxZeyKgGTMoB+YAhZz8Qa9iOMdcWRB55QGYQwryLwiXDkQLgYR9ATDOHVU8lId" +
+	"eOvOCO8PhtQKPJPaSS5gH9u2h8QPjqFhzWX1iUDkBGGRdQFORGvidcljOQQDzVBl" +
+	"TGG2UR07istKQkPDezFCw0PURkJVk1fFtUDEY3CtDUhqIFYmbk+TNC9bRLgC1B2Q" +
+	"hmoGNNdEXHTlVNGEVIJL1zKJJcvOiDo0nuITwMO7aogoMQulp1Uzxq+a5SU07uZm" +
+	"vE1CJnZZ70OyN16aWcbe7CfhB0W5dv9C6SR3sHAFMHzkGZVhljT9BtpAZFGb0IBh" +
+	"iANn4yVtUWWNjZlODZOyQgvvs4J4XQtR3HQo1zIKaCGoA3MHDeDBQRyGSIusq+Iu" +
+	"UOnPeNgBZsMVdUK/MA7M74eXN+cCMybrgKkJpI2AViGsH9t9NE2mTXEAH2u1lnrn" +
+	"3EhxUTGqz2uqtiqAhUVEQ7IFAI05ncwTfKHWxRzwOqtWiKznM7zWPbVzw4j5iIaD" +
+	"SHW84UBRM2Z3vmt3R7bnF9KAsRXK5MOIWdxy1IhO4yIpyYRjiTl6klPndDcCERED" +
+	"fIAlT9GeQO/FHYQ4IvbAcQGRxYyPYeZewWBoEX3dzOxpl0F2A6Xk4RptVObwVYvR" +
+	"JgUdJSoUBw0WAB93YAWGu4uiaiu2D0oQ6CQqYz2svjWxM5GLngT4hPu9PIny6IsR" +
+	"ZwrtKctQEYHDXdoRqg5oQ2uSsX4bCJ3NGGNxFpY9K9jfyTMPt60P9tHlUE941bvY" +
+	"0CWQSCsNUdyq41StOyY05v6ryYNfhWLruNAJjmG6yfUmfUshkQw5BAYqlskE4XZZ" +
+	"0rCcTJIRvQcxBsbodFNqdCpMhmSYhrWBxkg7XIf371jehCbUwexm4dGgVDsU5gmy" +
+	"ARYrMvjRHnRAjrEi0GYc5Y6OiwRdCNAUhDcJxjcBNIBhrUp2G6ndXbO7n1V1kivl" +
+	"8XxGjFDj0HsLjFztVYhL2gQARiRjzTgeTHDnuVV3Z6EWdEVx3o6ECjQ5rCJk6KO7" +
+	"JyyngW7FaBI8Q0m90Hkz6/HSOXw7wPcGEkM3MXsytQGxEqIOeR5s569+9oW4M1qt" +
+	"CS6KKEewSrVVQ9Z2x1nmgZsV5A2G0sh3RXUp64xy5NrrMXvw/jH9rrG9Vbajixah" +
+	"aXPO4PyEx5aentlmgg3UzPNcyQmn8jm7WpaxrIJeGcWmiyb2JVHMgUcgNYWQZ8qR" +
+	"l9nHMTRw3MikGYWca2t3QhhaYddzCOLk1SxmG3vec1U7jhzaLKrbNpl7cveuJ4GT" +
+	"VKmHNOGIKDJJCa1hZpVTd9ddzdqXynyK3LQF/1fvHvFwDEEAgG7s21nIU4+UAFqO" +
+	"BOzZXxvafGAJlsTLa0vUiRYNbsqb6jMCVwky24SylLvbtzhy4U047dzRIGiqxGqI" +
+	"kIjQID2qNEqudsyoALL7RxclL04W5tQJ5QDpK7RHXccMSIKzBREj6ROmSpdaVrt4" +
+	"adqfw1EQX0QzEHsCa660tktLxhOLIkn2OyUnq6l1++dxH9/n3L2c8+25+V4ffTlL" +
+	"WbIZ6mIoWFkymTGcEwjhh9wUdmPPecx/I04eIAX8Pfv3s8Jw7Rz+F57P356BfL1E" +
+	"2R485lDJBs/Jx45HbNb+1znkLrlQVg2n3Z3ePSJuR7bhMxd8mt5Ml7Cna2v47Av2" +
+	"ShobDchLus/dr8YRijOCfI/aoS1CEk62/SwaX0d+zqSS4TLcKBNHf3WDoO6NgvqD" +
+	"AcAR82hL32rdu4FRZaPc4BSzInYiK90PsiBLMdwBZzGeZDD4g5u3gUBylQUbarAR" +
+	"BUBIVnQqbgplEWh9veEZod7p4BlUkk5VEijGEoh0dAiX2FHNFOZcC5CaW4XLEDTI" +
+	"SgogmLJAKIqAY78+xmDgxem8eRwYA+e+7Gs7BLa59uFG8ZoVeVgy9USRkUkhykQ2" +
+	"gdhQBuNLAzEGQWz6uWiSqgkgPFhL1X2+0eYLcIcj3iZyxIJ5vmkDHss1UAY9Kwmu" +
+	"cUvi7vEKuyu0GwhCTA/yoyJyKgfHT7x1mgrpxkN4KkOQXU5C2Mg4GpNJatXYSKiD" +
+	"qMyBxJCb3pESGxB3ecBzpYGNW/OquelOkMMQhLMNvp2CszyQXClDLJFNasPABkrG" +
+	"Mqh3NC4P2iBrGm2BOkclnvhVhaRISz3tcWC4e3pxcma792AaxCl7oESlxfjoIKJ7" +
+	"a2FiDuAweHtnbwXS5c7GQzEPRFNwEFkCQFcwLhdUKEAz2x8RGVU4dMOHfKVIFIhm" +
+	"2iWtGuVMhENpjLWFciSZlotHBr+3aNL0JXa8XgqPAEd6EVpKnkMUG11O6XJWr5Yd" +
+	"e1Z9xlu5eR7mJ0wHvDupi0w9qHg0QgciAVh2IX6IXeOlrntOQTFZdBawzrREld3j" +
+	"PlFqXVGJkUYTNlohLiPDOszjjML0boQtWicWm1LQfEJgpwVZEwVAf1rpwKDiWeW2" +
+	"T44FofGx9X7FflnTv57B7RWfe+Ko/xh7BrfbW16MdhYNV5PvlOkBqBZnJhkCwWXb" +
+	"ALoENInGVVyEpJHrMH1FM5yhFxZi6xvmHQaSOdy8vvLlDQ0cip0Q10A0glmjphjg" +
+	"AtXhh5sC2DuE7wOi1ogHvNgoaKThOzB1lxriiGCeshTQvqL89HPQ+io6J1Omxss5" +
+	"Zv6kfi67wFWe2dNZFCyzJZwresuVNd9sV2RTnE5N7GjnjtGhDOLCGejhEM4VqEAY" +
+	"I4iKBkRFL4BZuzJlfc28UAYvBA0puE6ZecsRdO8V2w3M1t4YGKaBMQ9gzlCEQ22W" +
+	"BSqbwKaRdjkQHC4ixmWzxGIaJQxyRAxHr6FlXRHCtOM7Ur2KSG17m5xIKQuaUIjp" +
+	"KPU4oul3DGBPUe9XNE5SjJ7usYsvJroDQcDTaLFrKnCLS1aqHqo1vSGEySRhymq1" +
+	"0Ub2JdLjui5Cg0OgAyFwRzuTtrLIETnek84awMtCp9ESClI6GC70L6VcHG5I5VRM" +
+	"DxkDYaht0wnKaDRTpUruQQOhrJt5eU9zwnDZsQC8XLboLBCToaxiPIoixht299g1" +
+	"eAN4RdbBM3PFsKrg6ERTws9wPEE53AHu9HnSjwnUOBSNrBA70oCmilLYPe+DGDgh" +
+	"6AG94FT/EZfpoKj3EISVg8QpAngqM8vmA3SBJCvRSw6yhCJNdyVUolCjZPDeXsG9" +
+	"6bxkCEDL4kgQb0NHSghSvjbgTCRImOgQX9g5YQnK1JnCHQir06levMFKVYkHy0hY" +
+	"Iko0oj33Fl52C2vKsBIXYs0AwtC0BAVsqkEI2A51DCQ4czmzpfPFmm+b8ANnSoK6" +
+	"NuBO5JsE9wB54ZFkSd6awB68gOzx6BZkU0W41kPJp0tdlQoNWMl5ouXnVwAAOBQV" +
+	"QtmwACYSMN8JJSXDEpDDXCxMzIoc1vtUCyI83wsQowQmOdEQeu+6wUTUVTUZ6V0G" +
+	"BjiUxQLwwVYDEAdoXZoZo9PK2kLxhW04FenMCowg8QhwJC6ISvJoZdAMI4RxmXl9" +
+	"WGpq1m5QDogASIegEgDIpUXcDP6wOlBb2oB2J7FIYiZ3rGZXNIJf2atRcQbYVDkx" +
+	"Cz1D0GsdMvIO8NzFYSwtpbyZ1nGAWozaQYNERCAeNIRK/KCxiAvTnMSeKBcSoITt" +
+	"OIamG40xIsICd7QGYq7g5yMZSfYIBjSC8cIthVOmEmzl5cjRRQSFEKnIqSKUG2y0" +
+	"d4pDaUQkJ5CMiAKrdvrMLFEIFbQrfWW0hD7GB2FrFcwCpSROwIDjxYYPX3mjKzEA" +
+	"oiIESUYpR3ygcvabgvYb5JsUBDar6xA08yYdnJ3dmc8KkH6un9F+sESctLBFkQGm" +
+	"Ta0bPig+sM/K4rcNlicUhXGvkeO2yqSZ5oKmK7mzQnIIpTd6txohrPWxC+w7O7Xd" +
+	"9LQtO6uqZLhzsHZpRcxYOi1CFignFLhwDuxorIb1rsUMRBHkUkH9+wAqL2aiyPoA" +
+	"lLwUclJO0yK/pNNLRBkAgxgRJDowL+MDbn7aFmDs3Zum7TMmpl6eNnnKXjW+cIZL" +
+	"KTUDBhEK8ciqkQeV7o9nO+RdjYhyConjMQRTBWmeLu3GkKYbSDZ+NFythpRclB0u" +
+	"+MM9hIPy379/P5JvRp9K7Hh8rACxIThkR9bC/mjT79r7kMrZfL3DsQq9dPzd80jy" +
+	"omUQ0MGQccce3Fj7MWzP6VNxLUm/pBuxmmyioIE45y9suzCqg25nIpkvY49evNI1" +
+	"vdkD9EHHY32D6/Wt95wXiY14QGHv6Tupr4QlovqZsUxN/gppAOiLCJKKRQoB3Tq7" +
+	"wOD2KVRzt/RlCRyIOQHSOSr3uh4krxkmwT/BsrQ79YvUxmCBsaLPe3BE9rd44cRs" +
+	"EtHttA6UiBxgHNHMBs2t3WoqicOUCJ/pdOhWwXx0xzvjx3O0KVN84or1DOx3VbmY" +
+	"XBKjiLHHQ6cosigwdb8KKicNL3O90EPY3XkwoBs5FPf48Tw4m8Z4osEyHXmsb2fA" +
+	"Ok4HFRdQRcU7OGXaHlQhmiCfcEzj2hQNDNA6MRu4t68O2Z1CjKZpojvIZ6gSyZPH" +
+	"rL9rdnsgo9LEDXNXd1XbuepmStaOYiD4/r5zmElX0N6F0Tz3VCoRv4sIsFhYUIgI" +
+	"numbH4pN2G+IcL7ABCaNu1mNj6QkUIMAhtoR0MMPiEUwHvdwMF50hG8QYCTnhfkt" +
+	"UMX5FQVzDOdATVLQbTBOoetSGcCjNrjgN51GgITFdoNWnL64lJHbNklnJKcjAsED" +
+	"6LlEuu3zlPY6SEcibIy1pLUAd0IHMRZuIwhRlzAXsU1wRK4F5NYIkTsbgaGKAOrk" +
+	"3mDdrs9oHE5vbz3eO7IwqJxcJxDru7DPr5kZnfTpXLnLVEx7eQEex5Vc10EW/bNS" +
+	"/UN3fOWkQhgOwHG8e4Yi8HiGe47HhLNWwnMlMsrBHoa5VyAyXB8ny2xOvMcOHDgH" +
+	"b3EqkrzSChHUyZmLI+6hu7wISKUqFFKTFWDllLromzIiucDwBOQQ1kp6KGChwrGN" +
+	"IdiidKkg6IolNojcrO0BeJ7r7kxA8TUb1OsJ0DwXlDQCiVkWTKjwgEQoLqhDMXRo" +
+	"Qo9pGorE3XPYHlVcm/Fl0ZUNWuXAbPgxVowsObJtykwDZmd3Rs9kF7ovtgP9gQ+4" +
+	"ImoCUYDVbTqWeNIfHhQ3fcGSykKPKGvzG0gw0ZETg97odgi+CtWJvpYu2qwoTAIs" +
+	"E9R6CGlAcEl9tTTwETIhk6KNV2KAPhQLimtCFryG/Hiw3nYgO3u3TfEJHQuFVBHi" +
+	"QGsiLqgzs4bdm1MO8CUwBqvDVp0jQlTrbg64FHW97NcVIgioHQCAjzim4h2byc6c" +
+	"ANEWA7Wm3xWoYIRbEHeZqnzzDMAxmjmtCjoyJRko4E6qJSoabUiR5UHY4rwkhjGi" +
+	"57nGCJQGyYa6EIE1ZkbQuFKKxvM0KGlAUTD2PCxzTTr3sa2oAwP2Ie5M1JRb4eh8" +
+	"NazCTDn7w1nJjXI8EDCKsUADgQVYSIv0oS9b+UA6gPIs1SOiIhCIbAeri0sZgp2q" +
+	"Cjt1qVoBinB93WUFd3i+GNTr0BMoqCtDIo66aNKIkZtiCtBFYTxRAkbRGHW4E2Qa" +
+	"wGELRMBSlDORfaNHjJo8HetTIRdgB0R/fXAbO2dWJb6DfUEsipYiw5A0GnF8Ezhv" +
+	"GlTxeCaEA4SjJdyifLMm9GUIqQiABhBNrSrnBJZwcLnsUPG8AVmRARIaJRIAl2Aq" +
+	"vN8GsE1zgnAAG4OQm/dxkQHKoewTW3RsFeU7RIFDvSeKq6tmLIwK8gvYW2oipkRT" +
+	"wRjRc2uNOhMZYE5yw8o4PRldld0CRW1Do6zyeWGLAfbpCqPTGDSqcoJXE1eKBT20" +
+	"VES/Gir1g0EQCpg7m5ZtoK5GATGOZsXKcwCUdiYw78huOate6CDObwFxCKBgXHBB" +
+	"V6vNFaO1koc5AG7nTRtcl9SatzUT+2esG3qOOQchoqjI0MZiYEGiTyVZp67hPaez" +
+	"0Y0m6xKBzy6R5ZAO9vJiMqshjhrIky5HVSaeZ5qEyNVLWOJtWG+4jGMGDZuXubu+" +
+	"1BVxAySGWyePnaGc7uXgXUFUo7J3BHWdzfN0ndx97DRHhMuD3FIbtcmDu9FIUiHM" +
+	"wvJzV1rl7V3DAElvIjuzuAN5aVFegjAg8oRCh3gtOg4EUlSNQ+g+YCsNL0DFoWiB" +
+	"8GhSYOOE2b5zZHnFEUAwcmIWCMHBxMSoJhWMWrtE4EJmAmGLhxoTvSHCijrgpjFw" +
+	"YaJ00WnSJr+RmC5jFqtEbUiI3kQFaXgg7vKLYF/fBgwaV+EnRk9XQKQPOgkBdnA8" +
+	"kKDUtNQ28kWcA2LCiCujWK5nSsg+u2au4siUCIIuFgTFpAqiDAnZW7L63Tx5sg/t" +
+	"IR5eMo5HINaaOXDMrHyG8ytg+NvLtlHBkBo9kRnrKYt8/qyVqWjj5VEqVy3GpUqV" +
+	"hixKBqJGzkfhHgoFl/X1yrlEscB5vLEAKPAYyGQRirBKEZm6RZfA9cJGIMRHO5ca" +
+	"CEW/DnIynaC2XohJQkB3yhFrMFq3qxHJ4+QOtEUb2wG1dJBDDTr2sZrvJ4RcRMbT" +
+	"qH2Jdooaxt0NjDiScucKju2YzYaBBzvUkkz7Rs5QxX2gwjkdYD4UtQubOAigAFmX" +
+	"wNXZ4di59KNNkgtapzDO5Ze1RNDg3lGlzmLiBgSsl48e7xxrPEEVA8DigDOnCoWC" +
+	"NyRTfSavpnxLQ91Rqpqq7DJKoyD2FuCLkgrmASASJuqhEdivR0jzeV9CZNSuy7ox" +
+	"U34bo3ZBM43NBAmhDigDK71FQEKZjWNaenQQjAhUwtFmR3diUG9KvqSEILrtcrnK" +
+	"JYMYsRyZAMUMhxGC3SmHeUddC8aQDaajNAGHbXfMJnKQ3Io5u809jIeOAiCmGwEc" +
+	"SGxFf2Mh3Ck7Q8NmAQs8MQPGwLfoDFgfOCTl3U4o3sLxM3kkQktElpUOIQi8KGes" +
+	"JJoQV1lFdBdVKBU8i65cXjg3ziOG1RVyGUA5EA1Bz2PdlZvXiVd3sCFzpi7ZkuuA" +
+	"okzCH5e60sadzfeQCtFe9t3jHrFGwPRHJzHlWiIzEmgstR6IY+MDjh98XwynDQJ9" +
+	"BcV2odeecqlvFnFC/t9u3NHjnIqGa7bYikVnM+yf5vO/or7fvUJSIr379aG/2n64" +
+	"/p2BO0/o9sxrOt3vIpd9x5yvc+etFPveVHuePsUB3DIaidl4CxRx010k46whEN0I" +
+	"g9O0ug506JYDlFzQbuZEuMBAWvO6IBV8LQl756E4B76UHCsGLzEOHBSd+XvXk9WI" +
+	"YMbfg56ndwHELY0vRDPXRQ99d6bL5OdJIUUzbJDqWMfi11tQANmXKblIsgFamLRx" +
+	"GwxzOeJQdSQi75cWKugYgDTZ3sYwfDRyoBTFJzhNZdKia3kOBcotQFEQCbS2nCSC" +
+	"TtEiEuncq5ywL4jCuAjum3CYQzZnvAElVp2RRCOSGjCgOCgk5JdEY3YqtbGzSJKS" +
+	"UdKYzo16eoPENGLo0phETPJZ6OIkAK9m+kPCOQTXKwGmFeO3Qo9mYJjmt47wpZ4n" +
+	"OUCpkBXxs5+EADfPu0KwMIEgyIE6Rn15vJ9n2j32MTvEFNRG+O5FKG2lrAqyh+Tf" +
+	"Rzh4eWFJaDwsQTEaSEdaoYgZ1LlWfjUAeC8q2dWnJ0LQ8IrFg6vYcrdprGOfYLx4" +
+	"1uAB00NBrexzAOhxEV0hJgfdnNpAR2yetGXXTyUK7POeMFSwUcyK0k54TYZ3BFZc" +
+	"82vsHiaF0rspFEpTTqjrGMohOJwo131kTcrGNoxl7VJWqRTYNtAAJC7V+xyyGxzg" +
+	"D6IYN9WtIiQNBELyUK0RY7CBDsyDhV4eNdSOX7wMOkXgGQkRysCNmAEPpdYUaOma" +
+	"XGtvRVaKBTpnHMGXsHRzNvcHtrkV4qMS3LQYC7AFDRgeIQXw4+CQaigKJZLolFEe" +
+	"ynETG9VkDEWb3PCLQWZvtb1uyQ9OCb2ljqdYeYVQUVrlhSmZCCLoCzeq3qihdKlC" +
+	"FCVu9GdtanaDaeoee8Gh0XfV746AG0mFR3grOkNaEV4oAxcwugi+5mLavDgNyeab" +
+	"aPNUAdaRx6GueEE8UgBraaEPEBA90Hd0IoiYKzzLeyC+QP86S24oNGgPN7VEZLkc" +
+	"3KKB9yaO3suM7dsqIyXBAyaPJIVawzuyNy8Uis1TN6MwDW+Sc8Jp63uyww2NEo+W" +
+	"pXWbpGdzmc2qkqcY5CJNMqipmJnZ7lPXMBYk5A0CO8LEGgRCLCyFEGqDni6GFwh4" +
+	"ISrK96I0lzDiiuVYcpktYea5V0fSBQQ4HLSCYxVJEIpIEG1ivgPWGQ9zRCT5pzks" +
+	"lUdNyhMqyFLVbXZ+dbaAL5MolnGQ0f2Y0lbErTW9N9zvnf1PL7QhIQj5Qqg9+9Ze" +
+	"cP2k9FIfAnPPeCQEemCDu+PpovnNLGt2xn12fm+7k++eYUe5zI3I85qKYoJjmjnl" +
+	"nmGtQxhZ8OrjWLs29chu705lyXsj00pO0r01isVaNX6Hs8cRtAzPRBUpl8Xo2aUU" +
+	"RMFSH1bMAjgAzlpfCL5AHePjDzgQW5sEzApAHGDajlxaEJMRENKpBhNAm92ON0Jo" +
+	"cKOslyv1CmpWvaQTDp2e7sgwMWOxFETVedrRILOecthi4+kHbXO7UCGYShLGHMPL" +
+	"BFyJnklnbddyTMMgm68FBsVzHACN16/QBHAADr0hyZ57ivEsZjdscOB4MukOoq75" +
+	"3Sm6oznxvBWSoYDs0mM85hVF3AUJAQhIC+IAnAQ0nYeBojTtDDu9fb2ZgfOvvEtI" +
+	"Ir4U3SSAbviqYgJSp4BnTGwbatDG9A3mGF9hEO+hcZwvmsmKw4IUUYSm04b969eJ" +
+	"yhd9UFNe3iSa87znSZ8uMCA9unXVOthwgCtrI694ULz3RAeRPJ0dGGH4cQq8+E1k" +
+	"N2XKOIV8b7t0k3pInQ2SYhUaCSxLkRMIbumyj4sTVz8/OCjnFqV6iuYCrEQETZhg" +
+	"aTaO1M91eVU+0dN5lIKE0hY+6ZhdH8xPatSu9IGjiSBRxdlYhnVgx3DM3OmAAPUh" +
+	"oivOGZEA50UKDKlBGKmuKZHM7ZnaIrey9kZzbWmTBux5hLriaXv3sCjh3RSQN2Km" +
+	"seQirWUXffY2PUwR4ix73JkV2Xnrhe5wc7ATvBMNCGsQ9s1jt3XLtQAW0gIAsK7i" +
+	"GYMN4XZoBFGRARR6qCjNIi9RgC+TuutUGw5urUrW9IBs3WmZh5j0JAQtReBHKKCw" +
+	"Ao1BYPjdMlMyTuA3z3s5HrzxCD7DNUpI9NKK1QCbU3u6DYiKaA7sOUSYFvgSL2GV" +
+	"56raInCNge3z1vokDQ4oBA7DVZChDpWQ6HOcrY+5Qi5tmkDUUFPEQNwVKiIBqChg" +
+	"igm4JIiXEAJEBKiKBIihiUjIdguH3TxtEV8CLnCZZJXuZrns5yGzNcQqb5nRD8Kf" +
+	"Ejj1uLimHfFsXzlUZzvk7zxYPeGzkRdgYzYoe7Nc34mq1NfS0+Tpc572vBToIi+h" +
+	"NC8Ksk0wShGEgp3jOt0s2159erxfPx1eTb02DQXSuDB5AkTVTpTmMjNgcOdrKEzr" +
+	"tc4aYgDJqgdKhmhE3HZulPmAHB7632oFlcTlmCvKgosDR7ft7TOgZfTYJwR7AXuW" +
+	"/S8+gIFeKNjkv3u7oLzAyBFiIY4bJOh4OuYdqgOIWvESJAdRUwkRH0TBzeSHfdN6" +
+	"Bz4E9oSSCWPhUXvDkFmbZ2uSLokHIEKenMqeTFXgg3poKBEk9zF2SbQhJap4uGJJ" +
+	"FC6V1rXoCFhRw7YcnMjkezOEULe98ME6Ds0IYzERWbF33DHNcyL7qBnaeKKU8Wx9" +
+	"AYMaYwHMmO44OFPK1nebx24PdpQEPFOIOCGGRgnfbPFFecB7CSMybA7NNoCJdWkq" +
+	"A6uxgQHTSlzjN02jfYhsKEJKfK3grm8IX6/ZCr04RBTyJ2sbuCdybNeEICJ26MbJ" +
+	"jeDS6wgqPaR9ormfdmFDLWdBF0bbY2212EiKqJfXchQkdNNXrLktUifqXfCq84+8" +
+	"Z6VhYN5i5hktLGeDvDyUvWWAs27y4SHHMOtg0Rag4RHHJZJzJpVzqEypuBMu2xKI" +
+	"MQEgIgDMNB440aFxBiGgVIhdjaNkyK8RRKsepNlmwLGE3pI5dmBEqgxMdV0KaHO8" +
+	"HhyQ2xG2KGDGNoGzBt7biE+kQ6Bod7WXByC2xtI4zTaLsEoGd3XlmZdylWF1alnb" +
+	"M69mJMgnkxqru4Oogy+Ri7zgqVzMxct3GGZgXGSdkzJjhyAuE2PZ723DJwTyMnjh" +
+	"l3tHY5VDpUieCoJmSC8uhRWOsIvHrs3IcXRWXW5dAv7/778fUJpA9gUVtiDse9fX" +
+	"eLqjFjg9tC9YHmeTlFWicKAUpOimCqgEtGlSNGcpe3u66YHC5aNSJLww2kUhcBCo" +
+	"sQJBzkAYmK7l1EZTiK2JEzDnWILQWZzI5NHO5yHsQScKeLA3Y1UxANcWcBcAXTZC" +
+	"nG3WEshvETCEE/bPauJ2LcYYpkGUUtAj4AMoK/tv6dyS4In1VQtIbiS0kHqwagwE" +
+	"s2PM5itnuLiqWW680Rhkknpn2RxZA/NquFxL9qJ+MWTj/aqbZM1Eg28nmVVm5HKs" +
+	"lPLjlU2yZl+lLy2b+bKSNUYSElldBP7yb+gMMPeIR9GJowRgkgRoYVdqHQlwIDLQ" +
+	"aiI6H1XmnDYFAee304yulhRgMIl8rODvjPsYDh4FRB4lS0XTd85zYMBdO9uA1XQj" +
+	"EQiIrzFbmDjy+83gvNdxScSEU2bnSmgAjjhZ0eHKQtVyg3vI5fSCEKUQLGWCcN64" +
+	"SoBE1gka0aWw7IlYUoJeMdqQ5ytWEITjsqzKm8ZQESwE6E2CN4IIUSEnUYdM0vGl" +
+	"bHppfLXOIXBTSfWIgFSl6IChy+B0e4/JZIPYtHBc8xqqNyEaYZAWKNvfjpvJ6pXN" +
+	"iRCGxlbePrTJreU3HXYA2d8CBSRKa51BpHeF0vGi5yH3vMvA8hjcyHuijgTurUuj" +
+	"QcspGgZqbDJsCwLljxYqwh0UedgzggA1oQPI1qSzDKyyTLBusjazKdKbN8Mpiiht" +
+	"tahHCFFJFECD5lOaLBoYNnSA5Vo0uVRGun3s3jbMCD8MAOHpiyBtrvGjhr1I4Kam" +
+	"hC90hDDgrxsCgbMgmSDrjyPJSVi0W46roi+Blde3oaM85BCOMlkvxXOBKzLEV9tx" +
+	"jdKcCx5V102vHRvAEBovGic6QBeiErtETJWKgpIgxvYmMdZt+YQ8c1CsakICg2WZ" +
+	"YJ1wKg5NIYcsHI7TKYIG9UiK5Dh3nMiYQyjsFTApEA2cmsjhUIqrYHeoS28gi1UT" +
+	"O+eZXGRAHUG1Gwk33qXWInhbyo5dSTqBDuQtgRSK2UpGW9OB04oooTkj1I1XpEzE" +
+	"sEzSF8gCdoVyiYDkYCLfSn0SyX2hCQQsiaxSyGKpCEVn+T+7ACroi7X8aJopBWVZ" +
+	"ZWHIQaTx4SNUeLDFSxevebd+cHKoaR+Uldj4hZiyxAxiEJPs55pQEVzsqkE5E3EK" +
+	"C8Zrl12Z6ZyL3XJIIiYtC1Axc5KDSj612cHXeoDiFrcpuKKB6LCLGCsgEWAcjIYi" +
+	"7hqF7Haj4908uyiAKrcawQQ5bsgLte4FvgR3kPuHtlEgneUBi6RqG4DiDmJiBIgS" +
+	"VKzW6RQTsDZDRB7vFB/Npbn3thjxnOfz03l8o4iPr5vcTXayIrevu4elRUVaMYKB" +
+	"TVWh4hpU3OBfMUdpqaMvN5RfQRHEA5SRsCqgNvSaSWAjxg2Sce8tmpLwQTzaEJKY" +
+	"a7vw4DMq4BBwDCYqTySZ5Y4qUEBqrTyjRBdDSeJIR3x93G24dW0Fsfb52b53LqcB" +
+	"LxkrVu+jOgAOVeWKSAPYajZnWDo8DQrwVXMRLreCHM8HdKQ7MnILkIj3MoONh0TW" +
+	"CXGY8bOCBgAXDflHcvJbxkD4icpcbMiA0ObDPeZMm9qh4TsxeYSrNdsERNogpnNA" +
+	"iWcLBMk3AFNaaFs84CFDeDFXxodhl7a9MyVyMFFD0AIGiNGCvoSCLqpw0errcmtJ" +
+	"ZMaVMLAkEC6A0HNHB9bcXzSDliqUfebISAiIRkyhvuGM41wC0GZ9e14N0k1dvH2j" +
+	"IIzL0HDgOgo2Teq2QOrLViXLanCQRVQkcYimjkTcFagkgFwMQzjIhkESKoRYDARO" +
+	"OUM3MEMWezt6GgSuFhS2HQXOveJgcUGzsH1FZhnVaE8D1kRDjrF+riAwE0VbuVvu" +
+	"Wx0Vo0Ivo3snYbRflxgcfJwR3m0ICx85dsSDvT3cZ29Q4CWGBQLggyCKEiARitqr" +
+	"sNm0fTrW3Krxa102dakYpVhqwhVCrC2SGOlkRk1UlqBaSVYVJYN7ERi1FAbW+G3z" +
+	"51re5VjVbm5W5UlbmrUmM9t/6/T6vv9Po7vhq+xJDxqrZJCSN4A9ebXxyczXxmoN" +
+	"33VoVPS3BLDLLHbi5spPNZK0uCZvZgZzc23MBvtLdad1ruTZJGVJwaelJw113fR8" +
+	"rnExqR0PrSFjAyjjVUETBCGwkwwK3s287kNjE+yu0Hbm242i5VRLlk0STTSgxaFK" +
+	"RQ77zTcyWsiGy8yIrLiHHJjtG1A2Yw3W9UlzdFd2HcNCqkQgyani4Bu3NroVFnYL" +
+	"2HzDRFdvTmig2HcOnFxATrA0TnGma3YZz0ymbsQAYJGBFbqwZSEku3x21FBfCArF" +
+	"0wi6MyRrQQhzxXZCortLApgcocDruDxkuASSjkkCRHHVa1oVlDu7SymYTanF4+3W" +
+	"eROwxPvSBh9NNJ8ik1JAnwJivP2b/k6eXnnoQc+e3REtcmUhKCgg9oIgj3cO94cZ" +
+	"1/yZZPYXmLsEVzL9wyayYqdoLf7u7cMaiHlnOXVcjK1tFvlVLZVUn6CtS/Dc2MGy" +
+	"jQgfhC2Kdjr3P4oF82DpTA7dJI8fmoIQcC1skeRzKgLQfdKJKWsxDeDRAOkVD1Uj" +
+	"6REe5pkkFtcBVDyBmsYcJiDPKL4QYIAKg3pFBYsEheQysfqhKb7Z5Wjm10jpNiZp" +
+	"B5IyQBQMUV05k5WF025JblIlxOjYPTSQS14ht99a4g4RAIMEXBQ9VYdUOnAHboCb" +
+	"AM8xBqUidwUIqCaNuDndlLcheCQRzyDZsza6jpcC8J5t93uI52DOCUmxyBWG6xjU" +
+	"DfvcQN2R3loD2RQpUCyjb0Nnj8jM44gOI4HkYOhJNFBUaBwiiugHBtgmVWWcPJ2v" +
+	"AGlYg8pB1knDeEQyYzoFW+nZieSuAOXHdpQnYHIIvsnV62gW62oGOQSq0ZHQmkz6" +
+	"ve09eR6+As6PaDEAPBAjCRxHiizSKSWE3lI8fDOCDmGnmVpNbi8eUVoBcnjVYXJH" +
+	"Wy5Y+Ig8gsiDUDTA6xDbTXjDHGKyNg20+8AoKRpUzjVgeIneyymHNIhlOlRveBNb" +
+	"AyNu+YZy5q7JQKKSSPDgYkgOZ54N9vTDVhqc6UhuwvCADsV5z0KRpEITXj4+mgml" +
+	"oIZg4a71Zlm7m0gkdp4U3zAnK2iHrqjsxi8S8sDdGDo9ucdGhjq81Jfa1MiJSKcB" +
+	"A701FV6aw8Hp7V9EURNiZNADwG3dhrhp2xsMQdoNaPWpg17FE8O8dR1VHRzpUzs4" +
+	"oW8uITBTDYPLynlwZDIItG+CIpXe2AKuCI7Qs1rnC94AEyGbMuhIPF1HgmbONCmS" +
+	"5k7bSMjXhXQp1OCjmkAGTvLOmI0HOAt3YzBQRFgqFp2bepbOC2EIwJLOpBSCVEHI" +
+	"kdNxHOkAQs0VIpgJl4XMHMjEgid0t3FO8MJhYYXY8sERIghdxq3vQKeC72BkdCeG" +
+	"xRxAiGkDGK5LYsCK3AWW+AM5VQaWqrkJ3NiK8HR0Oyaird7M0013PrNY4oA67ZPe" +
+	"zuDTrV0oZMsRpR7ZipzQ1jzg4Ut53oN2DS2qHRF3Qms17VFoJ5zQGLHnTQ1WhcBQ" +
+	"uEUTQhQjEQUHI85hT5R2UYC3twsue/zOINAzYK9Mg24cwzR4rXfuB43f5g0wg+ma" +
+	"n54RRErdutOia0EPZPBoCriZ3WIjYiAiY9ycBy8PvV0fdNCtr1kSkUTFpWjZQ33A" +
+	"Gh0a7ep6g4nkWoASDIDjZq/BgHfve9jgEEhzWCeQR7Hli6A20uwCorkhnm7lK6hw" +
+	"1GyiXCVzPlIK80MpCjwRAoagLZOVxmZA+eBSGhCIL9tBXabrpw47c5zKNaAKO4sL" +
+	"7KvUaVGgeYA4XSjsTXG+b3fBFtoGLhoKvIHohI5zzHSwDMUyPCJ8Zjolsa6FJ1An" +
+	"5EizYQKcpor6HHhk6GdulzXbHMekayul6RlzuOIXQHGhtCOsOrdgh5yBUI4QD6cJ" +
+	"CNmU1QYJoXJADgxaZvbMMEEkHSPshs7OGaJOF613Nd0CBj2PIi+PXV5W90bvAECz" +
+	"SV7CKiJiGUeZErQbfUGQNmjhny5vomzEBFviHjwiiJ0o1E52tFzGaXbdCZ4hwwYE" +
+	"QPQQkQZFRB5oqVQlVfs5E1NSQq6LJmIhqJUJBkSTmKRwxxBG4hmGYgYhOlbgcIM3" +
+	"Qhnd3c1BbjEYvIhbZzEQRGBE2cgI5W4RhHpgCsRsjcdWFMN0olQDA5nd4AckRPbG" +
+	"2+i25y8WqkxW8Wupq+jB2ymQckBbjqGGJ2AtMuBuG4BrSNp5MsuWwgXbcCXcIAxo" +
+	"J5BTSW05do8jzcwVXNZNxgxuimapGRGRMeE3YqpoRFQVEB1gVMQgYxo7G7bmRDES" +
+	"u71hcZac1QBCRIHe0LZAbAbHxDwuLIhFlGQ311uRlODv9YkCQRH+Eh/r6Q/7bT83" +
+	"9x/Fr+4/N+xjJ/ef+if6dubx/+uT/af5yl/qO7x5v6rVWuWZlZjM5eZ/VustitjY" +
+	"3HC0dHExsx/qOenTOnMdJLi6X+gqTDD7MX/BpCpmFwf/C6fg79fommh7CkD5icKI" +
+	"rVSTX/Uh8fGFGKs+lPgrQH+bz8pu235HwdPyPCs0aP60bPSYwmirZ/oP34xfQ1wP" +
+	"pnDAX5KPS23/G6nZ/TKCJiCNS5oIRTN0GCKEmhG9kYgIrr/UH+fx/tEuBL+6UPJP" +
+	"b3bTrJphJ0Vu8PmOnIeyvm4J8dKtpVV7Nxk1Ldm7r2f9z6VbD/lVr/jIa0/ZP2/6" +
+	"fsPJ4euM7/l/w/Hbe2qPmk4Gye8+XFXSsxt8HE/hOObeMcPpNPb7slXdTm6OZ/v/" +
+	"5dVzU58rFtJ4e3yv9l6buQsjiD1R2Np9hTyeTt6+038W47SRy6PY06E+P3JOgWaQ" +
+	"hHAkkR/Xh/2ncXif2afyf4Svf5NvY3/UP3JXCqfaxkZRL/J3CPDzFxNGAzKcQTnd" +
+	"cHPayzzbvLxDd1UnVvMbTw9BywcPDfsc2zm/nyMfDmf932T7p87KrxgyeFftQ+tf" +
+	"Cfh7HZyeE2aj8Ld3bXw43xb83/u3I6WSftIeD/xbZE/8bwT5H1OjB9vDc2fr8Q+u" +
+	"397X9Gf+PSdnVOzpP8PP+c7z52c3SP5Gtkn9kn/w7H1cp+5o+HrPZPv7uTykTn4t" +
+	"qMW5ktlnN5X7r3/GJDMMmGVMJN7siu/yfnqffmvSXMu6ft6bOJlTaKqp/L3k/g2n" +
+	"c/7fv5SH4e7wSNdHTnGSe7brKd9m2+rfs+75c1sWpbaXqOkkpTo6LvZVDoKaaPJd" +
+	"rf6/wabfy//P+Ses/dNe1Wv4P05eaf0Xg/vluP7Okm/5eu4+LJMnvJ6vyfdiuNK0" +
+	"Wbn2ZOW7k/O5dVV1S0twqcn6SMKzp/2y3c5D8U7EssiWcxtqybtlfi2p2J1xcn7G" +
+	"nI/NwcrP+tfj8/scv7QZ8v3tjkfXsw7Hk28PhyNkcPY3e7To4dLZXs52SnOcp+0v" +
+	"BzIaa0rMZV/r4j+X7dHd5OqeK/l2Ng6ZCf3R4MsiMaozClqv621/Cfwfp/G2c4GO" +
+	"dLV9XSfLMq1YzWaxrDFXxLOJ3YfCa+Wpzeb8XWTm+JzP+IICf93/kNaqLaNrWSqi" +
+	"ttajRqjbapmqtpS2qxVk1bUlWpNqLRWpZqtJNKo1U0ttRsy20zVJqrG2wBY1sVoL" +
+	"FUWJs1ikLFTK0am2RVFYUrYNFpNtTCoNYjWpaFbG0TKLTDY1RrJSWwCVU1K0mkrG" +
+	"yUpUbZDVikMW0bZkYotZMmZGLRsY0KIViLGjRsUWxtRUzFiTQaisJEzIaWTNYIjU" +
+	"RhTZsyUWxsUUlY2oyRsm1G1k1MhLM2Q2gWRRMpDGE0zA0ktFBaZGyBETCCMgSEaj" +
+	"EWjaJKU2NqZFooxiokSIyMMUIWEaiMhQoIiiqQmIYEkRhFpEhYqSGCLFCKEMEEGT" +
+	"9mvzf2fuM6SFZC4Qd9fugRia8BBCIvlh/UPmUoYBieRgSMiPA/zM5kG80OwWXxVB" +
+	"kDKCgX+vVRm/7UQIDInnOZ/vuDq/4D8+p51Kq1Jw/kWTzvI4d9a7SyLfWstuvCsR" +
+	"8vO+Ve9WpNJv7s7+fuL8JV+dboUuDPzER7chJZ58smGb6bfHJ+/wytuIdr6d7a47" +
+	"bq+tvU9ubKTxSujpWpbkOGArKSYHFiSSfHgG2RPcG5lSlkRGbrdlTVFVeA1pC41W" +
+	"V8XE0QYWbMrorO7DWTBoBRpgyaqKdSFItuzQ+QpmRRpSUkgkAkgVhutQk5vCYVVC" +
+	"2pCBtTYcnZA1HRmQ5KEKUJCjE441UykKrp04rW12EaksMjEqCmiOKKAiIoVAjHHG" +
+	"4Oy2vMLFphr2skmltbAj2yHto+/C1qRSHQI0oYJy4xPAK0hBhkBkzKGIDKfqR5fu" +
+	"9Rb6jriPwFfrT57/BORRUS2uxaWe/23vw/VDRJUNDKbcoql9hR1STaoUKFJAhAE0" +
+	"AZZLjCTR5qxIgYLhyUQktqwQ0LakMUoDZaYvf1dL7/UTZGZSt/h0bF8bOrkShINm" +
+	"UC5JVQoULQdWFmExZOwxx6b/nrJEIzcATXe9RX4uAjQuZbT7+8dvCcTe970nE51j" +
+	"cmac2WktrRIBr8KKqmFiShChQWsTPnID4M0CSyZe7rltE0/bIvrM+YcPthAH85JJ" +
+	"219mY5mjPQZhiZDYZA1DzBlAjUcjXvLL8BABMGVQh/A/vPwUfqX/5kl6UGGJn8FC" +
+	"P2GG+QceVRTNvxzts75paBK7NzM7TzVVUzlIqqif8NJKRImR08cg2cHrQWxKYcNh" +
+	"OjnHzz+YPyaL9PWNrPR37fFaHr23fpcy+YYGWlsuQf4q7bXFjzjZ66t5DEnZsqLU" +
+	"ixYlKiy0ibZsjalZamaizKs1laSpmk2ratltZbWSta0bazUrFJs0ttalazaQUhKg" +
+	"lSUAqyQoWSKtotVYtSmoyW220arUsoo1tpLaNtMsmtaaYsVTbS2UtJgram22rCkS" +
+	"qQSxISyQS0FSSyM1KaS2laa0lhNFGhYWigRULZFiyykqoCxFBKRFSItCrIUWLKak" +
+	"ppY2WbY2tps1pm2ymqbabbLNiZojaZkrFMKZrKzaWVptZtppijZNM2SzKmmxsRab" +
+	"LZs2K1NVqWqEzMlJtmqVRjVNZWllSVLM0LNNZpalZokSlltLasJRUqopUpZIElIE" +
+	"lkqrYjVi0aSNqWmLKpslJtFRBbSbbMy1KoplRspaNlNUrNUaaak2mpVFTZVGxk2a" +
+	"GTSWmzaCpKbNJW2WqWqKMmNk1GkKUtk2ysrLNs2WwyrMqKpqZmmmKxtmqayKZlUk" +
+	"qNltKlRSm2StUtbLWxTNUqlspo1ZtltNKRIqGm0tlRtNmmalNGZYybMozNNKkxpI" +
+	"2i2ULJqUrGyyxJslNGpZmtNSsrNWZY222yttmrVNTbWZZMms2lllbKstpmrNMUmp" +
+	"KqUtptKyaplKbRSbJbLNplZtqM1KKbabU1ZSUAmUaxpZjUkhUmyZmxbRSltNsrMq" +
+	"qVbNtslSptEzVrMqaazNpmkqZsxExpJSk1itlWqay1KppYopMUkkkmbLNlMymsxS" +
+	"0TKlNjKbA1TLLLU0lTWalTNMilKmys2ZY2mqViUVKSyksmapVNqSJRqxZSyylMlS" +
+	"yLFSWRUliWKLJPR487tzxPbvpf6y887/zT6h9UmfSx2PLPXLE2t67TNb+d8616jt" +
+	"tPkeNmjOnd2bULjnN/5x19I3dES+7KaAHB8sg9OaIHogcFmowcPkd56v4UKiqJhg" +
+	"oAU9AHxYiJSboAuO2tYkauzYowUsXVGVlc0nYOpihEKtGCELstXcQR40ZwxcKms+" +
+	"7pFjCoGnlWDFSsNDI2M37zbDfLv3avdlnZZ+BC52UzTjZKLth+XpejoaOcVlvLIp" +
+	"Bt0bICZGx12W3MemDI+BEABpXP87P4rJiq/on3ucmKl3H2qkVoDOXeBVIHThRlRW" +
+	"oIeneSsFb5P81QBgJOLBARAX3nH8/r/f8w3ilqIGYIs2ETpWjUrVBz3ap+abPKWH" +
+	"pLM3ltPx/+N/Wbt1NbzHN6yn49NkVXLjHsi0YsxWYxt0mpP5liJ0D/BK861JPxVJ" +
+	"KrrKd1DEsjkf2fd+E1sqc+0G02nKaZP3/wWYV/JKhVSKU/9f2kP+Es6z7k/gUksW" +
+	"JYe1an/921pBsrUdXyfSH+6h3N4k/jE5ItS1VTkajSXnZgf5UtgpKk2jaxZibyd4" +
+	"83LeR6x6+RPw/T0lWWVLOy4k54wllqVWtTTUvHd5G6VXZwcLVpZCyOySqT/VUqI2" +
+	"a3OjB+BJ/c5vJ17xaYezrA2WTu8JipWJ34en5WSThOGGFkqslgxWw1Riyit2TjUk" +
+	"4m2SJs+3WFSYNQcR9lN+j4j1noP93VyHCfI7cNMSZzH2ZNRThulseIk/yU5KdXt9" +
+	"v7zmbk+gjtO690cSQSoFfmmeBxfI+vqGsirzNH5C+xTw2WGGHE0X+u176U0uLoPT" +
+	"OEn+qsbDvaA4s+lX8EqpJzPrH0sloeXR1c9OiqmXer0zgSe5ZrT6ScTDZPxHCbPN" +
+	"0R5uo6u07SaTyP+1LS2qfontI4sTqU/nOnq3gQE3PlZlmWZRJYUsqyJ2P6PJ+L5/" +
+	"D8Jssqnh8+u+2ca0nxwRAJ32knCcvhmYySY8DlHwPRZOyxVSqrmc5yn+vVN35FkO" +
+	"yvNZM/ORPMmjIkxNtLVRf1qQ3ksieqJL38h25PbeROj0cV6GFHWIPN2qxXorv7Oc" +
+	"ifauTZXzYwjFM+LPNWr/a58p5xuD9uXn6b8HdXj7TiR9vZIw7HVkmGI8569eqqvk" +
+	"P0vhi5cxU9euWvzV52lG6lLCSmYWK8coeiN0jxImMiT1bT9FffylTz7SRs5vwq1O" +
+	"E1BPxdk4PSI/RJu9WoSzsTH6v0nJ8nrzi+ITko3SqSvxOJ2nukqKkpNLHec/hfS3" +
+	"JEnzWJ39PoktklpWMyyPh/0Tc9E9Kdo5IemeY1NR+smI8T/dPNYrc5nXv9t9sHUa" +
+	"mQsqCq1PemmmTVTeR5UqqSopSlKWFOYaL87JVmxycMd8wy5fM2Yw/RXl8vbb5SVb" +
+	"u3zORyjjG3DhlMKM111l6sSk+BAMLpSjqdn8I5U+moXwXX5p0Z+Ev8Zh48/wLRnq" +
+	"sVOvKupu7tEKFfaNwYH8/Ci1xHTYAbREOEoEoBMbtSSnI7QnHvPpNvIrSaUlVwno" +
+	"cA2T6JPxOc9Hjj805OqKqKTKMtvz7PuSa/Ze7Y4TXj0keaMVJIBO6TUtNbu22/rK" +
+	"Ik20pV+zX62sR+LTYvA/nP8S/x/z/y/t/m/n/s/ozh/TTT0zNN8l832eeZrP1ft7" +
+	"l855ZP0+7P2fht+Mct5xlvGpyPw3YySSq45XU1bSyrab5ycrjjicbfT6o/FPun2h" +
+	"kqLVQZw1OrdGyq/AmFG8iUYmGjHDOy2YstLLBnKVZJvoZpv/dskjgWfX0jmmn+XT" +
+	"9EpEKhcAUlB/eYz+SbNu4qNSSEC7hItGyfhotsOAf9SwdHA8hOJqR/DyaGA0EVqI" +
+	"SKD6AWMbIK+iFwiWZNpCAwgFlSy1TRu/m2NnOmMXFK6UuExRVkRZMoar/6uXRP9P" +
+	"7ZP87LZwYx0FWaYU5vlVTqmnh1eev7szJOiq4leaII1cL9t51vM2+LzXlfVqKWyp" +
+	"WvCVPQwScjU2St+kOba054lwkpIqTJm2mrtWuoYNioqjXh9ZCcg4fauRyifOQnf6" +
+	"SGRSfxqdVrKlWU2qUzZplGsprUmLRsRajVG1FqI0mwhqNsVY0VqNYxgASIkzAhPb" +
+	"KKjCrJLVvcYYOJOH+vt9D6MOVhCbzFWO4yRsEfXvzBp0P+0m6q/l61TUNMPwDbP4" +
+	"A4ZborpXA29kUhELXpos8r3drnud3G50Si5VJtefj+9ZVvVRlXCz1Xg6KThMk4mm" +
+	"/BxViVUbKrUw0nSUxVm8OjGchs/DpN495AGe5+K5OvXzvbUNNMVStZlSc5ucwd3W" +
+	"l4u1dm3WlJobdG41bAbKyodIBU0lRgRgW0aw1kwVrIutSyFWNio1Fc3UKqqpRju5" +
+	"Aadp5fl5udRTjI1JPdwpAh5+pEn8lE/gwPC4SP7yQ/wfmhzK6WLcLLBfzaejXg5N" +
+	"ROtJbDGTLY1NWSMQ3kPP8tNlbsFLO0khJHEnOD8iIBLHY5E5Vaioqq6mHOzViRnO" +
+	"TJDV5noj3lYCpbB/UKCPiSPRFBjGEsHZXWOmMUqqoqjVmVmoGFKNXF5UqRqditja" +
+	"VqjRtTTJJCSNK2SIBLIlcoL93JoaGmSYppju7taVJZUVshVKnwaD0EH7hMmp/h+o" +
+	"Pbiejj/LCXLxi+sY57t+Gq/cILqWSklksgVasVYdKi3aLGlcq4fh/b/0JI17/hz9" +
+	"I5p2kpb6oqMezcw1GWkqUylkKqYsxkpUqrKj6ahmlf3ytR/QMwpaUHB8iNiv9K/z" +
+	"0K6HAP93CkfDPEO0tLILS0pZtCxDEo+smm6SnpFqPN8mB8k84m6eFkLPr2/b9vvq" +
+	"30sMxTJbKbV41vETNRjrYhAm0Kmypb2ozMJGlqo0oyt7s1+ZqRGE5GDhx9HdIoQm" +
+	"hH5pdOT8GMwPVn9cd2LOKocJYqpE2fJibmxMRhVjdipjJLKxv8lUwhE3F+9vM/Z+" +
+	"96zDku8juRY8ZkygVpQhCSGE5vWjeiSSO8ZFx43qYwI0q4xeFMojCEBoYwhDwpBe" +
+	"iHCkNkSihsIJhUNuES4aChQwWFNLDYrSqqVumBhK0xiN2qw02aBvWoQRkbNJJAkj" +
+	"HBk/f0jBi0Qj3trasZSWJAABGGhpyETY2mx2GGObpTObWrb351Vt6QURN7vvOMuZ" +
+	"MryvV8esvd69S9JGxrTRiEw0k5hoCqjCFy3INRaqNJwakaGEikSrNSYRWTRj019T" +
+	"4CORqY4ubfHfS36+r2c6tibQpT7uqxK5TMRXftJ83l0OEKb1aVXy8jZKtwphii1E" +
+	"32XPN122+997zbb3qg2rFWEspycmx5fi63iHJ04NMLBsItv9IBqEOmT9g+SGvcbp" +
+	"+/hdEfGRojRGhaIFKIYxkBlxKkgcNtjbaQ3UpIqYgYoKWc8GtGtpwV4rXQ74tWyW" +
+	"WrSqxFk4NRFSeaScu5yP8VExZEm6XE4chWxqNGXXVJkYnR2cdHk8WdGYy2vCmNjq" +
+	"ybrMN1FOOcToskqqI6hQJYpkEaNCNn6FTLldFQjIRVoB+utwbXmdbmWEDBprGCfA" +
+	"JCZRpKqRYfq2e+7Cq5cNSfueE8nT0BAAmYe3/Q5/hbbwssFCXp+OE9EkGFrg00fG" +
+	"yXabHiy3EqpTo/Z9bfo+ZtPrQAuNWcI9+eSwSa/nYd7oXFadmUYi1ukq/ac5AAQE" +
+	"7du1t6q7K4YbOHkbtuq8NNGMZw/VibN2MKnJyZJzVzbk8nnizzY8nI5Pu2KrwXrL" +
+	"dm6nQ57aXMY8TsVyIDC5bX0WfDw+jTpp6QuEj7W1TMvq8Zyu9vdXFD+nVQXfaj5R" +
+	"BRz2fkfnvWnhDIyYKVitWiZZUs64DB3WmYY2xUAXs0Cakm2Wq5otBR1e9IE4xR6I" +
+	"UQ1xETvEmN8IlSLEh0Um6u2FSoE1m8LDpW1Hm4TFaGovlKmdEOVumVxam7bCipxu" +
+	"T6y5i4+SRHYrzydyzSvjm0vMKixJqmXoTSKKjLRTRkxS7yrSDPFa3nQXLkJi0PGz" +
+	"Ue3b6kGdih7KjMMNAjQzQTDB/OKQ8KFuO0yGQmIsJJJLKKGQAQmMosKAsZY1R0kL" +
+	"PhQaaKZWN45u7TtPs7uvVu7uqsd2mxpMjs4adWm7k2YxhWGOTRjkw3YppSco2dSD" +
+	"nDT6F8LNCzhHRwSHThhZCw/JCkWC0Z4GlllmHQk0JGWItJaemBYmSUfC/CzGtdOZ" +
+	"glpafCCzTTeNljGYrTsbK77srM0abuHRsdXENonRVgs/PvuqzvZPJURUwfRVTFTL" +
+	"HP5c+u4dT7LGDtNFEMwhcRariKthqTD1vPM95zBVA62rlBLfaioIouD1obsxmY4/" +
+	"SLbB1fe/WE5wvNs4XW/dM+pCuTReSLHk06DGF0WkGUHXGlrLY4aDxn3fHt8HuzrJ" +
+	"2+aMDPlI78q6bHxj5uF2TCFwbZMGRZ9YDJhIWy5Kgdxy7a9+tDiflePrabvyHDj9" +
+	"YiBjKMXYZIRdTNJHAOT6taIRRhwL6k4WH8MdqdOHDZ5XET0kKmF2Bk/gCivPTwLD" +
+	"D6OnV3Btj6vA6NAoRYdIDZ/GwT5X5/HRth0F6JgMp8aAo/b8aP0dVD3bWzoGD9jA" +
+	"IdGjWJpqFEIwOEjh+nBfY8Pv9ThAfIA+v1W1zDh98+IKpRNs2Kmxah79W223bEUj" +
+	"8FgfYebzbUyGl4S8AJvIixBOhDSmA2GYKhWeUS6ADRDvpmoClc1nZxo2BcF8lMAq" +
+	"GbIksqALJKpZprIel0G/UM0/NROWO2EHdl8baxjfvVc1Dz9VKlRqHhPwoX/hRooL" +
+	"hYtcLETvFJPN1IgE2b15FDZI8kftKHm25vocSMiWe502fv/5wLI7POSTnpHiVNkn" +
+	"KN0f5ylSllDaC8/EnNMn8bMOXdHDBEkioNT/Kpjl5T/FSNstpVTGKjCyZJilljk0" +
+	"WCJtTbKttU1vQ16RREbZJVRVnrJY8VbpfQ4jCfGExUvOtzOch1jTc+c6fhbzdJ+T" +
+	"ZjocHhp7tOTg0hqFHEdpzHf3mFU3tGUGnq9aOgRXwlMPc4oqofnnzkevPke8ocXV" +
+	"cWn5KA/wBIoOBRh4tKPhq0owg6MZB0JF0/BAeEjICzw6dNpJCSLZwqAGV7MVmZlz" +
+	"FW3GuSbWrY1tbz6cEBX5/031t5Xq26tD0eeTKPanZz5maen48Hmfm+rh8R/tsevt" +
+	"95vOVW8muQ0/dwn6qkVSPxsTydUx6UtRVtlfoqMjse8kMZUj0SSye7/KVZXR81mz" +
+	"STUJXk04fITUm7Y+EeH1SIBLCfsshViYpJybG/429HOeflhiyJoizZZJqnHAaUfl" +
+	"IkvOJH3SKlVJFWbJPqT6ux9pskzdwrJy6NBxBPGkSiqK9nE/6yaHtOaOIlPR5ned" +
+	"BwjqrLOVGfdvOzy8zy6OTpB8JJ5O35aTvUnmpOHOTST7q5Tt4SqsKqrKU8ZMLO59" +
+	"VefKuttZmLKmGsVuzxJ4xtmOsbzj7jrHOnDaObg2tvZVLY2bG06W4xJ2PRXowWn6" +
+	"Q2qskgjIGgwGL/Z/7+qho/gPTXh36jmR1w9demMo4Y8k1PnrL5bLq5qtlHMrhcTx" +
+	"qkjHMqVQDGMFtMg0tkKYtmljaZTJIMj9NFIipt2BtNmmpK5MDFVUUwrJvjElbUrM" +
+	"i23kbNn7H7hCiP4ZebpITlFV4hhqmRLE7Z94lSPPmM6+HR5PY6k0ntVq21Nlhixw" +
+	"sJ52ZHpNNQajs6c9vfpv6ZntOE9LGPhh91dhtbjq2MjZvtil0zo6r+jL2H8eLj18" +
+	"yGzWRNcm9I5GokcOjGnDG7SaaFYxVOitW1Wmzf9NOstsnBXsVhrLaczNWymFZQmR" +
+	"BAR4hXFLIMn8tE0KNiGlQnWdm5TOjQdS2GXGiCBhAiR3+IuNtczrWRxLegSYOFQ8" +
+	"aNwQ5pS1bOmZvMuM2Titbss3zVUdd41y8iQI3cC+BYszD3iyYZAxufkk+P8nXHL9" +
+	"uAF6kyiw54eRvOBZOAlO2Jkks3WNzvOHZTF8wXjOnz157FNv8IdeqWn4QqxyMzjd" +
+	"ovNzuHBnGNqB8UypLJspmo/PZrnERR2PqVzauvfqDryP7Z+vQD7IISU+56T4JDTE" +
+	"q+pP9KlpI+PV4dT1ixJrec504hI0p0ainusxoch3Rf1aTnA9yf8ixfufD/nGTaR+" +
+	"r9Yxn56qBqi9vX5hPpZKpLI37GNPZmMfbbfbh2nCcj2D8Z5XfTA5tD/UrkhsSybh" +
+	"P3xy2n8vXr3+fHF+jbhrfffrgpMdwyKsEIABftZxWHn6eRPx3H4XyvkzMnSq9ves" +
+	"52gWBe8WN0R5UW63ukJQWFQ4oKhAJyCJnQEqDppQlchLgECaszI1WAe5g4MUFyh0" +
+	"anCQg4mSNdSo2xtqgYJ+eC6eYyu+bd9QOSufIb1aqsFPuqFWSpbKUpWlKojFKpSj" +
+	"ujZZcdbOTOI0xFWRNkIpGoH4pGFJpP3gr/zxFkAWoqElVYP4Gt/X38U271ZrEysV" +
+	"o23KuyJZatOZ0Kp4TXVYhqbvrZeRB/cPmRH1kRtuErUZW4UhQwwgBj0NR/V3kMY7" +
+	"EobIBcOQukBiqbEGpMmJiq+WZWm2LXZ6qn6+3RY7yG3Jww0zZ0a0T9xZo9U2SMjs" +
+	"PDENqfk7N482T5PLSV+d2a1f1eexrCMfZXsuIkyj/nLJDF6pYr8eHJ6TBVV87tmm" +
+	"a7bz+ky6PN897u1CATUrOcfrYT7WLUnZUkfzoytVKsFSxI3TkSuWTSN9Jpp5QZrw" +
+	"J9vP1+nTbT6eldk/oc3RMOhp4yJZ4IUQxBgmiHJjtlz2GvOHReN9+iGp4Jktksd2" +
+	"Fk4SV2/JatrxIFOH9wap6FtHEfVGhB1sDwiGOwtcvTAgVkF6fh/XVVVUQaOqOQog" +
+	"5PKIzrA2mJiXdzzLWRbIZCyUxgbN2zVNiK1HWZJuqUsH34W6Tk5MbyVmv9jI2aSL" +
+	"I2VKRQpzmQyE8pC1C1EUiox5RWwS9UwZLy63VpJNJfEm63WubJNNHJJO5+RurZhi" +
+	"qlWMUlah+7hqpN26aksmYnEl+2jDzy2sWVaxhxo0sy3GKzqg4dVFnqiH/Afo6ZOB" +
+	"w6/25A/kKKi+ipEIiyL9rIz61tdfOz5b9tOLlSqe0SxNVPNTFk/XTHSxksktjnfv" +
+	"TFaebEYVxUzjImU3vFMtuuFx2WDCnNvkJhZJpZDkrlXW3eZtcuKZcvAedJhwsO8s" +
+	"JvKWfGcuMmSVOdMuPtO5iTO25qE9ntOJ7c8nKZfwxh1UZJbaturhTFgc4VklKumu" +
+	"lWXlu5AcQCTBIkaKGFUrEV2UU/n8/HpxHWKqpiLFVxDTtu0ZLFI6kEKTsGEUPGDF" +
+	"OyKFmi9fCJPgqu54sCIJ6uD6eDlOsdVOSppKzATwfi2t4CPHgfLsRZAITsgfqQ3S" +
+	"VryjsJs6HWRGyuXSEjvQFceInojgi66B/Jn9YGev5OSROQPgpDM311czh5pv7QH1" +
+	"mjYdG88T0Y6lKoky/ahYfzsf2FLP37iw0iHVc4G1T+qGtRbbYqpbLVXmWjUYsWtd" +
+	"3blc3NcosbFotRq1lJaLZLMX+yeAaVGqxZhXrnN4O7p233eKV527HTl3dF67ngUT" +
+	"DIWkYklBhCDIYMo0DsbYvZpkT5KZKN0lGEqTdkzEsUySxKGyAtr23/mYGEIYA2ic" +
+	"NDzgWF6BTisD+sxSj0YjKCGUBhaU0dbAuSAVMAWdJKS0UVTIyJw03tpPFQtSP5Zb" +
+	"pmLpJw4T+ko4c5H5d37d2YZYsw/VekqVFiu6LIkAnOUupHbpVuhXVTePKxVB0bps" +
+	"xhwtW3SVTpJP4oliflH2jl+CLI6HIdidSOtEWxPwTYaOFsTDdMOO9lshLUSxbIu5" +
+	"uldYJIE/CVEfQGnw3KR8rEXXfhMiZYN1TKw6ox209eLH1yz6Qd55slpUwKmJGhpV" +
+	"YEWZi/Z/B+/mfovmdoZ+b+KH47xRdEr1MjJ+9ZGEk8zDzXfoia3VNrVu2HqivcwY" +
+	"3Cn7tM3ujFGxSqYs/dy22jfJLV3mNSTmx6I9vwKifsrmelJXD6zmOk4e/y1x5u6N" +
+	"kaNqieX17yTTwyGtH46H4Fak1c3Kk5z/ZZaK7PU4mLKJZX6ySfl593p1JU4nVzP4" +
+	"uonn80Sf8PxBATaSfrZLZLbUFOifY8b/OQOkPKRJYuHzE80n8kWiVZVKKsiPyj7f" +
+	"1czhH4I6GHur5ngfJsPHxaVDwbH4JEAnRdt8Mbc25sbc26WpK369rsq2Jk7ybJJ7" +
+	"nc7O76eHpxPLzn7OkGqH8mmR+h6xJVRVTckP3rP/RST+xYn6JzHM8ErZP8IJf7oK" +
+	"am6yrFq3COr+Gv1fkE1ZskzBUlfkrr8b8hzk8yxE2fNMfNrmi187J8z+Bmx2Wzuo" +
+	"upumHT834f0K/hL3SkSzQ2U85TkrZYbKMVKVsprfbMMsmUWyWP1W3DVjWss1MNMa" +
+	"H1WP6OTaGllrnZoiAS6ssfNp5sy3o6d+z1Phfsunc9WPbpmXPm3eqbeJ3nCllcoS" +
+	"R9y0sQeiKPWxdMHSL5yAm6DOmnZx9/de80IwLgMAwP8AgoIErJWSGzBhMaRbyCyG" +
+	"/KI3YnIr+zatN5zJm9iJx5FlEPllZszjniMMODP1NDhIdNGSUoDpyr2MFiNFAp7m" +
+	"dhmsM3rn7xcKDPsQKdNOmEcqRWE10Vn0f5jdKeQdD+sX9BD/gPSY95PtG5r5T0HY" +
+	"ruV86045uEMRVSihTsyZa8MesmkTJVlLKqkjBRhG+JG9NNZ4h9alqTnNfxllQNGA" +
+	"0GINwKMDY0ZDqh5V+GFsqw2G6lfuxMZjyPPPVzVO+/y341ul3m+NvxltY2IqNsRY" +
+	"1tTEiANRtZmKiypqJVJKtpSltTk/sPm7/O/dRNKm7YOQYxq6uWOcR7KE3fYnBOUc" +
+	"rZ8tbxGpQnw+T1h+E9UnrJ+6E4e77/fdEqziI7b4QxqWvgPVY2JuUihvCTzqWzax" +
+	"J8k0/ueZNn2cHv/723l7vkvl321HbIYegUM+f6eVz7iFR6+P17uMwF+AHuHwfOrG" +
+	"7J7tnlJLoqxiJZp7OkanzOMm8/JPR9k3N9px0iV2kiN/2MZWOp+Dmehw93hD9FiR" +
+	"9EvPnH5sfKX5VzOWREnZyUU+va6YuauVpl1jSzGGKqpqKIOVA2BEIIMpS3xoVbiJ" +
+	"DZ+4+ep9reEaqbrqJ9X9jOrrvJSr+/C3LCqZIomMTTGl5droWwvUnqT7fVasJ7Q3" +
+	"Vdshbp9jH8pBJ6bD2U+Cd/hZbX9ay6kU8KxTu8ttbZlm1Zpptjy1hjMVabYxkKUR" +
+	"gyjKMrbFpVVpilVWFxd4lsXb8MOW7fVipDJxhwVyRmzTVLLxkzco2dz5NnmsjnxG" +
+	"SQ0xLOUGItVGqYkjaPOd1ixXJ8pvAbHrxPhNAgJ168Kvepi5THZi1Orm5ld4ad8r" +
+	"162e8Lnx2rLKuWUXYSACKn+0Q+UPkiWkUT/jy4+mbc//nw1tlzru26a16nw/ipmj" +
+	"oukAwgMmggdSKdGbGU/Iprgvjn77Ct2WhTTOcy5KZMORZMZRWwQ6QquGZW1JTVlg" +
+	"QmM8osKKGDGMJIGMIBsiwhShSkqxMPy+3NPLDrbgVBbDqzyCBgWZKJrEQiRzR54q" +
+	"wia4gUepCJo2SzrcVXl3bH+sTOvr0qFHlmMYpGEQaiFZjEgQmdarIu7T2kdmRlAF" +
+	"SkKsnConJTZVYwmzOAdnDjWUlQbpLqEmzOttyWq429ehDBlMRRpyaUji5o2uW/LZ" +
+	"8wQgAFSMYB0Wdnuk9X8nH0naSH9JI+g9o2Gzu5nUVw9VrujeRN048OjNoP8LOjhS" +
+	"uG/rTtFPk8g307qhpyc48W4wop6dLpbpG62VarE1XE8iOyVK9ztXvOYw0JoSwJZJ" +
+	"Ftfft+V8JibSreNomUqaifeYC3fJ5fCnZQIMR8DDQUIxtbZGzGjKKNDyRspoqZqZ" +
+	"ossZ6UUDMFZKUgwYwsMaaYqaYrCr66wtypjY2abpVSX/mXeSNkaJPqgQhw2mmMjH" +
+	"EHymdzJLzYsvmuuvVbsqy6m7aYqyZnGoerqj3UePiyIVZIoqKthYOZ6vGFsYpWJz" +
+	"5ns4SY/yi4BSSyktv0dXbf1b1fl9fp9+36YjGvdRRMDFkx6Pp9wzFt1H2f0Y5CMb" +
+	"VjGyUszErxN3k9ks0S1Zk8IeitT1VrI3R37ye53Th502X+9254a+co8o7nMnWdCi" +
+	"wosHYmvktSVSyC6P4FSTb4evj8e+aNQ/gr3by2tmlU3bI5CjjaesCuuOTInFMxR6" +
+	"BGGiWW1NjQqsYxKUlU0qtak2QF9FdGkKOPTjiqoqd6H0PuA+KaOAwX65yfbt0Uu2" +
+	"t+9+OvxwswtdK+Z6T46z9ur6JavYqrVySsYUxinbay2mTZRVK1bWMy8Hm/TRaetZ" +
+	"W+L6HJ1GI7KbTEnokj3nzVNViyloqqryY4aU20msYtW5mTfBtWDH/fMFA6MUxGMR" +
+	"NFAuSNrZk1GrtLMg2RpFCqVUaUsYRZMiN2Nim9bnyPI1L5d7amo7nk142ZMm73SJ" +
+	"/eoPU902bpY5T5yQ6ffJkrLbKvs844reynK6fNsroOIGSOqTdhDZO0IlkpYiq6Oz" +
+	"Fkc0U/fPTYvU9bxWXZeLi5F902sZZU2ysGSmlVu0qcXTGyX5KS21VKrYw87pVnOc" +
+	"iN204sTwOM8R5cJLXpE8sT3gdCaTqejSJPFnanubqkqvQ5+EkEjrFki/syRPSKqx" +
+	"ixHNf1x69+Xp6t6l5LGF8d0xI7umlRgxkIYgsKQGahBGMdwkbbIclCjg2oW00iZA" +
+	"hDSVAoDGhqhIDTC4UGjDNVSwINaWT7/c+6B936RGV91beaH+tFpClUqVar6a57xS" +
+	"1YsdOxwxj98iTq3teHw5yT2NnV6Ms+s+NR8b24bKw/NWKKqqZhiqnM8QftpfQb+C" +
+	"Vs3lZLSSASqcfM7yVxGYledbnrN50XJBATYaCsBtFYJlZR2SKwb21+jqRiNFI0Sa" +
+	"rSjgiATZnWelW7O0mbziCfju7ylzo7WSqylsYp0JpjJU0qaMlJUUVhGilWTZudCx" +
+	"M+kc+l5uTSG84qLYv2ZJMli2qrILI2Tqln4cMqNhAj4gogAncslWOiwaV+BwnPnE" +
+	"jdp7E6UlqPtYJYV9Tg3WI95FkO6beZO8nlbeyYVc7od2tLylZPKLTp1I35t2iLsk" +
+	"ipSBQqtbUX19H2kWD8z2PyVPmh9rLUcrDSKQsTJIfukqY7Hl5DzdPLdUqq1+LJp5" +
+	"emzvHWPLN9YtWeh+2WzylkbFNlTCyVWKZpKyQ4YwqnWq3kKzCwje4lWdzTuDbTZx" +
+	"x4bJ8tzHGu7m3prWSakaVZncMwY02dcu7kznctvM5MknBXCmwVtKfU0xWphkowpi" +
+	"VsxiVW7I2rWqtRhwpcXDoaZN1MN6tYlKrh3GpWUlJLvXd43OuslSWQ0fVcxqeL+B" +
+	"Xv1rpQyBqdm7e1Ra8loulyubVzbXOGoNVpN1/mjcbxaAiUP6xnhT7z2IJaTCQVgt" +
+	"DpQcGFJgWSBTA5batqKV5l3ruu7XC3NyZRFeT486vWm68lRqMyRNpSzSpsi1KyzL" +
+	"GmTS2azSVMZqtq2bay1a0raVmmyq2yqikIVCwBSIqSpJJKsVBYgSKsBLSopRkS2t" +
+	"tKmrVKmA1rSpZU2JTWWSGtUtmsrMWKVLLVRCkSkEqQS0GpKlKZllNtK0WFGTNpZY" +
+	"2lmmZKZLbWbabW0ttZTSTFMklmzbbTaajUNZaVNKzWaipYqKmU2mMk2lilaVplhZ" +
+	"MykpmlSwamzZsrUtUJCNs2xE2zWbLJpmmmlSyzaYzNqWpssspZTaqtm1VbJlmm01" +
+	"kzUtDKks1LIK020pKUpNRlKTSlmUprKzRSmk1NTZZJrNhJIZMlSpNJDMktbNVDEs" +
+	"mpKFKVJtllm0ps2WzabGsbM2aQtmsJaMkNaVJmssNbZtbMprNYqWVKlaTUapJmGz" +
+	"RClCZhpmEmZpEympqWZmWbRs0SaY0lNTU2lqbLNtts1tsrNtKqSWmGWWW0tZrNiG" +
+	"Uy2ylLU2jJWUySmlNmpspWFKJrTVkE1lJmakWTZmUtpS0rKyqpVsilmsNrWWbLMq" +
+	"aVLFlNmazabZtNppoZJEkxlJIlplYbNUMaaVKhIUylmxaWkEslm2WoAZmYGmm02k" +
+	"mZ9vNcym/zYZ1m/E+UySfg39LUVVWb+0CAnu+IVnzkTYexs7ufDm0VjDZ7mmLPDC" +
+	"jvRkCK4NH4KYIPfTEsxAJVJTCY4MNNqKqTgrJkmjRkVkyN9MMuNskxW0mmjTSlSs" +
+	"RiUzxDKZmvWVXm9Y8a6VLqbbWXtSMLsZGTNoSqYkyYjI2VEskoLRRUbRRsbWkqSt" +
+	"Sau0WgopMsq6V0SZehQ82kyxbJsqq2k6xbaqqpy8chxElkKVybMPBqa1jIGLJqNa" +
+	"WSNnw5w5rJRVJ8pXQahwWUzyp0wnz/U0hIEiEYfzEVFZGtr8GqLFqNUUa0pVZVFV" +
+	"lLVsEy7VF1qILVeGEk2aS+WJki7F2pqD7InRyG/WjNbxTzY7E029eTdr/1ZJlhzx" +
+	"xZEk7TYxZI2Vk4yI8WLZEUcfOpyzjm2I50sicpFjzHRZKelYLMxipnrpolbK2wP3" +
+	"Gj5QrZ3mE7dW70dJN3aTWPvGzFnLOYscQkecNk/KdSbVattW/g8tatRJ9BbaVmTU" +
+	"cNkbE5NiRgCjqJjBFYYMQEpXT39BIxlLWwvLhFGpGWUqKViqxkcZkznhqQLSNrGQ" +
+	"hBUdGYxN2kbWNpAzdTVXSs46S3TNK5yd26mxXO7tXNdm0m6bRbSTJvK6rpKW2TFt" +
+	"vPLvJbNaSixoxKyEmNk0kWK0SdjZs2NohYnAsejhFowruXCQlUVFqVGpE0UGZIZE" +
+	"c3lktTo03a6N+EiflSdFScJJ0xKRxN5+ZDlCLZB9FWySZUtkhL9OWNS5Kx7HmGk3" +
+	"Zm+vn/kuSquatyCwYtGGhIxpQKVBh9sws7qnJ2thu+NtlbJbljpdXFmFp6I0cN3V" +
+	"hW7RqTNacWNJ80k/pbIVr82CR/iVzKp1fJPyjz7u0PGnOl53LbDvYakR0ZJD8qm5" +
+	"9mWLpEWRzhu+1n9OUKT1kn8VOh3p4lv5ZjCqf3P82pWjKmxUzVvxpOH8eDZPhDwf" +
+	"ii4JZZPcJ67Ts94+JJ8JN6n2RXJ/iPpDEN5uehqR3Yxju2bXbGDrRv6T0R5vdxJO" +
+	"R2mD+4dUjVjZFQf6RFZJ8rFskqu7VMy3EjDuzE2K5wH1nnG971lZjE1GMMpMLzVo" +
+	"tmMJoN2gv8yApnCpgihcVoiUFH+c9nnbz+momOTD2WTT5sRko0skZYttki1bLSVY" +
+	"mmMY0wqhWnGhdSllSSW9z4amEW8VfPq+6qyaeu2jZNvXtEl6ptryvUoxwqtXN1Fm" +
+	"Yqyc7Jqlsb2TXkulki/galjcAwqxIxJEkIZjxWvohjDLbjDg3VHCdKtlCUmTvHq1" +
+	"g1bKsb1nufaqpD0uQWNon9Cdrrb3LTMlSbUTSbK0ohajIvgjH+99Bt8p3n6qleSV" +
+	"ZE6o9h2eHZRzpwc3OYmK009E9R328jxMbJvFH6StQnM1NNmLDBWdD/DwdQc+bD7v" +
+	"Uoz8D4pQaY3jgmo4UpCiqrGzZpNbC5h/TXGpNqn1Vaok4ZPk4KphiwyWJy5ZHRwf" +
+	"oiZC34h6SrVlWif7FRHs1+Nuh+L5Hs6k7WWyNKyald2mpMaNp8+jr5z3H5HpDpU/" +
+	"yqPXPAk91O6UFo2PK2u5jy7lWy35Kw+iPIqfOySOpNDJ1k4nqsilXhkeZbW8c56z" +
+	"Rx1kbkR1nBpJ1VUPWotkR0rdsQsexSuL+5pk+Mk2l/i7Oi6XGwkvE5JyD6Ifc0l8" +
+	"iIBO6c0DixXt8Wk0H6+6WxFliWWWhO5P1UUsfx/o/JZJ9iprtPkmjEsfWdqnbtat" +
+	"q24OckqqqnQw+6k7EfBZHMentbUafUcOiqVVVYFUlFKKqejEY6Y+lfo+ubdLJdCu" +
+	"RFXLgVQwrGW3GIYJWGCYwwtWWlUskYxZ+emKaZHyQfWMWTUkP9FV7wTx+WRVUrZI" +
+	"0/KPlYWlUqaINRpIxmMlMfoeftr+7+JP2H69M/jD8xaKRKgSrdibLHI0VxjbdHGN" +
+	"jQd0aMDA0QIQWEpTRDGZrq3R00OH8GFjuAD9iwhU2MP6wiGD+jp0Ymd06Ksv5piO" +
+	"Uq1rMkwZkiw2SmZIUHD5pP5P1qcNmkgD9vum0hi+X4S/PJ3/mfi9rbspyye2Fk1Y" +
+	"tSqo+5O33q0nAeTHbg7lc2zBxS2K2xjL/dLmkWZGHQNxp9NkyrGxuvp9akHp3+A3" +
+	"ROSdXUb1air5yyvdI8km6PrIgEskaR1ceOmv5q4dpNp4dofKup3NzUTxsvxlZbZ/" +
+	"V7KshwsVcSqwxapT6487uYnOE9IdPT5DshyR8GTg8yZIxO7D2Xoe8wbPD2vkrki1" +
+	"J6oe6xXDYppjTbDezUkdjZXVjE75bVWXRUdldu05D4OvVbD8SxVZLZ009nJEkSTN" +
+	"7Y8kpPWH5pUvT49iIMA9AfIDJEZQpYI0oY5HlZOHxMMSe9WuihVMpamSnEH4RE9Z" +
+	"aWlkKsWrVSPdFT2zJGJOHBVlVUrpTJRywuMlV0T9myzARkClqiJX70kgpcYzsakR" +
+	"kiRXw/k/H9sfrouz/j/oVDN7/u1hxCRIRZULOfq+KvHsxm1M2jkhY7WeUc1j/ARD" +
+	"X9g55b0y0OAkCC5cP+IWkuBkJyInN3reK6uz5oJ3cmh5kk5SOROSWbV3cz6GtQbZ" +
+	"KFKWuNFtiyrDpfLMzGSYWFVpVVZYebEEsBqBXBsjMbarG2x/fZQ+jLYbHHqNwzdK" +
+	"EarMZjYxuuOPbI9sySN6HDIRKMbSRBlKUoJjSMbaV15eryvBqvJXDYi8l107GrKu" +
+	"rrePql/G999PfuvQQNubc1orFGJnz9/3e/n38NvhXHdrlX0hVyULe2vF4tSELMby" +
+	"nXaVdIyzVzptzbpG0kYyrYmUstRUilMV6qhiUaXUqU2t22sqVUgIrrtLQ1QdExSK" +
+	"lSKNIKNDYBCEhONtcvec081daISsVrnNwhsmVFh9UnkeSpU/Ucu0cHJG1Tws6MbG" +
+	"5/FVq2qhSlIpMbqkdPrfnJsRP5LJP3kl8j+YotqNDkj+2rYWxbJPER5OzzamSJYm" +
+	"ofxdXtOqPt84dU9J+/4gPBe8BUHiJMP6uXrNpwqwttVSaxGF+jEifCpFfxSkr9mc" +
+	"32c3S3Szbd2ZoiFIb5ZGYtnEkdJ+Try/CPL9Mi5mMdh+Ug/lZFsslk+ZJ6Es33Tm" +
+	"ZHKzR+qo+jHqk0bPR7vVXJrn+XaeaslpRZLB6fWTy0fm4NJO9fzVkjpKW2+cmMea" +
+	"KKivw3yNm0nsxo0qY/JPx9o926TeJg2Itr4mV3UibG6zyzGVVRZRZzUmJYrYjeJP" +
+	"tG57vdmClZ7rv1y8228aKmVl6+qvZfKRcLOG6ldOqd/Vu6vnzdTvHSaWdJCUkjhk" +
+	"kn7Gk+eiZHzRJjshqSwqyDyZ80X6SPqx722PQanWebyOhb9n7djstjZ4dY2OQxL8" +
+	"hdS7hgfQ+5CDkj7o7K4g5yNpyOpPqRywlpQRSDKSubGQjFYyaHIAwiqRam0sMSLC" +
+	"sJviL0yJ2OkeKEslhZYLLIdXuqTrJIqKaZP1acJCcH4eh1+kfB93b1WTnIpa+SDt" +
+	"JnSUSfEhNliaKTnK6bk2NUtOpwxwxVUbNmx5x8lIqppySP7fkeJPkfA/GZNlaB85" +
+	"U/xOGz7nG7VxLbFvOJRc267dY5TS32y82q967Sok5Aw3FStphVLMYoq5nJ05S7XG" +
+	"3bTWXLtislaIjwcKpUlVZ5bNl3MjhW/1ibOUVX6bGO9ltr3qNM4ZOuTmdlJHaTrd" +
+	"opbJmZI0WRqsr4Q/tfrZ3oi2RVBaIqi1MzEkmVJ0pnG2r43k6qGCL9Kkpczv4SeP" +
+	"sFeTIEBc3DtAZcH6XxGW7Yaw+DznoSqyrouIMcMHbjD/FBny/X179rvtjikQCcgQ" +
+	"E4HS222zVI+KD/aP1IS0pJSBYzn2USdPSTTu868arlGQodZ/tyxVyU5RrlBdEqjR" +
+	"+4KCHQDi6aQjlScf+T5kjee1Xoxo/SOOyTCd1xDlX+YN/MVvtOj2tXZXckMqqZHZ" +
+	"EKEQlkdnL7Jdydlgmev89uU78j5cSJ/l8dkmE7rhzD8qadHMH4jZj3nDGPdwajh7" +
+	"sMdnVu5ujXXl+T1/u4LOHgw0+z8FGBY2M89iIokYQvh0gpDsMgXC5N6MMVWqIDKF" +
+	"k7Bhi7LCa12ZnoYVi5gcGP9X5TyVn5jjpmK38e0H0yNy9sy6krJx2NyXEkufYjPY" +
+	"35HJdzHaIWeWpGch1C2GpaeIIyAyJiVK/Gotmvs6vH4XixysdNfO67ZuafPse3Xt" +
+	"czmeH1mHV6i2qvNHrsuyeFJj1OGjd4Zq4YLjGTExlUsVV/xcbG0nNuxlxTLllUUB" +
+	"hE0vYrX0AxuvoyLWYktLUDBX8H5cYsLkOfeXyz9A4QbZ7J00FTnG94VNve5NkYen" +
+	"LptnR61av5SHOPZVdEI2fk5/k3VxOX5PckzZv1ec8TchyRzOOqs5zOUkm0wWPJVW" +
+	"TC1sxMVVTWOfpWxnsx/JmyBRsFWNsiIqoVUFReZrK80s5jqpOqvOS43zEuyOx1cp" +
+	"0Y8OhOW7ME8lk6LCeFLjEsFSqpSyelXJhXAcdpsp0Y6/OqpWhUMVm2xjyTgU6nrw" +
+	"6yszFUttktLZVtnXi3kuDRtDz/sJ5OxXV22LVZKMYxihA2Q/Dq/NjZ+535t7PF0a" +
+	"3E6sM0t90PBzJHT5SRrz+MtSHquWXGSMc07ChTvJ7sjSm49U8JK0NlKrXIMbnnPC" +
+	"0qUqjU5Jxyt7ynN5e/kM7y2YxjGrVeTE5xqbVT8LiY6bpo+ZdRG82/fr1m22xZSB" +
+	"38PxIyNMShQiH6G9hXLOZK6w3N5+X72HFAxu5NSfRpW6afRXqo8VJGH9x5ObPuVJ" +
+	"QLAiFlH6/u/FbMJ3EnnDq7T0En449m8JHNPxcyzXSV7BCP9JENSIjTahAiKfMpQX" +
+	"fhvwg6xjTyfA09UakjGjZSMkcm0k69uDQkz5aTWCW2iz7hlcSciTjD3IoFZBYmNt" +
+	"odoFMMIkDWQjASGk0NA76DcIySAGLYwAZPQkVbS9raOCXx0N4NPJAcpTE24YEIYy" +
+	"g7CfLWmi2E1TDcjdkTMXE0qKsqvYI1Rc1zUWKjBt3dZMYLSc1V8teNrSwW867u67" +
+	"u3XWz3uiTDJ7uup6aktGEa9d1hTNubvV2q883d3IoqVnZHRyRZT547K2nlbs57pm" +
+	"7cLQoYwF2iZPBBH+5LQ7dYkkhI6u5sNK9nPxux2bnayrYrkTq+u7erJbBUNziMaP" +
+	"rppVcY3SxyySyySfFXkjZSuA61FVMKi5jFHB+UxNKWOqcRzfOSQki42nkQs97JyK" +
+	"5amm58SFk3LVSU0uj7SQfqwEfho1r92H6uG22K2lVz+Uf5sqP0dLN/GejmK0sxrP" +
+	"xz1m2/05yx4ONjCbJH9A+8QkhIqoJKiRIQWkkRKAK20HGfR9lFGh2vmzMyyCig/w" +
+	"mlAinByNccszHu826vNs08OjdXU3GzSpwG2/sZ6SHoyTSVw0slcGjSBnq4UMw08I" +
+	"tvw4uHqDA/w6OSCRnyIh/MH46rxmTFxdHacVc+uD3HvflqHvL7RI7e5edJqb4ZU4" +
+	"09uYztwe+W/IpAaOoyLcwQVPk3k69Fffn6zXZ3kION0cYOXDuS+3vzTOm/K7Mq6H" +
+	"OlZUd7Pxxdl9t69NorsK6eU6442+am88vu73UsgRoV5Z211tTDr33RPyM6/XfL5U" +
+	"EDhtlOMGIOhqVFDMLDExeDQGHON0fZdtpnTpZ6cD6JBkGJpUx0Y0WuppUjCvDGzH" +
+	"Jsmjd0VyNNnRZ1Y1MNHaMbOGzcp3VttssZwsk0gsTGWj6gLXG8FJpoGGjp6NmZZI" +
+	"mQYvcYoaIEFW2vkM2ui4SWaSMLtv6RnW2Q1A4FIHgMRpRK4eNjfwZ5oqGaaSMo5b" +
+	"dknhw4SbOELPGyXLyqGoGSSqSomY1HBBVkQqys9MCWL1YjTEvrT/lW/HvnSpG2HG" +
+	"W0YwPtoufZQEsPWkFdi4q6Bs3tkoppX5Eiaqo5JX1UtH2/gzrxnmXNzE5gfF8iGh" +
+	"wMagId9OeGfjPxGKTtKHVVJ7vT6eMIaVB+wH3n3+jxV4Svh6l0hS2vo/Hxp46W8T" +
+	"mStcsHMrio8lNypolKYqrT5AyFDChtZGHuINKBspBGKg7kJt6Bo8fNBswFHISJJt" +
+	"PcLdHk1+NWshZCgqnMZITrDX2VnDFGhCe+9um2kaWy3BLFDrBte5ISqMa3whRNX2" +
+	"hdsSnCgdmnJiwaaFmqxgEhoSkmS4W5nnc2pOkjMCi0Pn4WGjUumeTCfLJJ1jYrHx" +
+	"jaFRrCj5qXWxkTinm7fk9Hu2JvELPk8MMVKpWKtKq1iVVKKUxXlx31G9Tw/vO6Mb" +
+	"E80lYmSJp0FRrDJyLJ51U9ZI6GiLTUsTlnZqBqxHcOldSSip2iosJI2Ehx0kHxDZ" +
+	"/AZNzYUGDTXrMplachkVuS1tsiYIYyt2mzZDErJJWTTEalrQplZC7YM+li2SUoxV" +
+	"VZY0yZkycNIiDcCJMaGNe5kXBpN+8HIUgoKqYnY1JISR6tshCE6JhknVjg6cMhWn" +
+	"JNlbSdppsotV9zG202HYjiEnmTz+E7xXhSrLv5ZtdazVbW2hjEYNKDGEBkJ9/vy+" +
+	"vnrFURs1YvpvLuyE245w0VLL1kr7cOg/Ba/Qf0QM8JPxZLLOStL5KZ+faXr7LE9j" +
+	"17oH4+OiR8orIu4h/RAagtxGICYpOWtBCN8eXMu7rl485VKQmKi+aU6rwbyfLXpr" +
+	"161+qbettfqWN0pL88tJbgpKWur4a8ki2arIszGhZJVK03h6o84nieE+RSDA2EJn" +
+	"ygppzrRHjjDHHjQ3oAGNIa0QIJjBiGd8s3glSnsMZSEY1I4BqCBOrFtgXZ7YoGff" +
+	"5SOeYkWToVOR6a7/Dmyl7pPebOTUlLEYebR5Ikzr5O+azEJXRy731dGOXtcW5mTx" +
+	"HG7GnHVxIbSbnuyUslYdMltVhpO7tytjo3Cx2IyGZDKmmWOxCaYRisSq0VhSVpit" +
+	"JWkrS3VY0DcaigxKkRFVBNRkkg1UhOMurldw8knJjznZobpJOCnNMtmM9JI/gses" +
+	"Dl0es/T0c4b+aSO5yy8it57PtER7yQ49svq6K2KoqVhjFUqmm02P9rP+enbyTaJy" +
+	"k7zyB5VdEyRHyqE2jlT/N+4jPJHNVfOPajFtvo+bRIhxDIiAREIBEBHmAseJvCKp" +
+	"aWSr3OREAnaST8LJp9TClbcGN022eOxs0mObY5x+f0+u0ck5RKKUopJrgB87bebv" +
+	"yv5u7W3q/fvzQ+JGypskPUreRLIrmybatMsX0a/RksaxtIKIX8sn739qsebzOZiG" +
+	"by7s3vdaJR6Dj2macG0WSRT7SDN9KC4xmGSRgRYwaf7MbwGIOPrP6Rb8N/DY1I1H" +
+	"JIkrMaQbxJHdIbifDkh15l2d27BHRHVPKch+6RBzeUnBMtctc4pKUyuu2upJrlrq" +
+	"667pW6+1t+6Vk20JkkpYV59A5unxbofu3vn21Ey/s+HYx9zasPu1JNm5an1x85Hp" +
+	"GG1LFk0RAJ1kfSK+E9UPntJMsjrKWnc/YuFg5pe8Oyx5qIpZEbwKh7e7yTBhymws" +
+	"JtGzb8PDzkfvPfLZJ5yR/o9pH2H9KqdtVVX7VbbWI2Nmr22lllliKehVTXVI09Cd" +
+	"Z/Ou/e1aKs8lfvPiSD3/Bks8PeYcuVmGgTKW2WyVY/isZRxJN2T4vyfP0vRyfZZK" +
+	"rbaZNZsTidKX8ofEcnunxzNEJWu9xbuQ3w1er3T4Y3g7/gteJ4WVbTtmn85O7lJ/" +
+	"VEnkTJ9atqsYYYeujDUxIwoxR56sknNj7SbuGneRs8nq4fJO2cpuiWKioslVKlRS" +
+	"pJZ/ULtdlKi0b+Z81+yixKtJIPDdvJ+LvDu0SyY/h7/w/FiNs+mias1cSpOznIPK" +
+	"yrHt1CY942YTzH+yrZIoqhOEiZIT845d3T6Pps/6Ofl4bEm9vIZB/UJBbEtgRgyB" +
+	"QrgTP96/o80lj8FrpZ3WuiX6brraSSqxRuxjTFUbWarrGGKMDbBcSioFSqf3ZLaC" +
+	"XBlKqfB9CZLWcmutdlVXXxEzqHZVo2a5uZjrbE5X5CvSKi2WpbDaOR0OqaV2Vjxq" +
+	"myEND13YGGgTBqRBqAkgipVktsk1bJm28lu2ll5dkUpklpVLKkqjThs7SaJqeWRG" +
+	"VasWSxZLZu4aIgE5GtmzUkyWRexTG+WO1qi40I7X+GXLi6g1d5IU5Kydn5ZoeE4k" +
+	"iNK7HJJHZ32hk/RzVTRzKwrOelrcXxZCb6V8ambb6i+3z7g8vV7o2qRK3bNfx+d9" +
+	"az5ZypWyvNOJkq2zTDGW3I2kxsrRVg0qaU6NmxvJVssZPf5Ch3jJZiNskkJC5thW" +
+	"jziKca5yYTlK0RAJy2l5f1mHrY2Dc6OkI2TTTy2TGVsRATPxGssjZRlnpIg3iSRi" +
+	"xI5OR2SOZJPl5/ncvR8vln1Y/uaaeTGFSl5VO11Z1vnvja5W9Kw09ahkgtDDYyAY" +
+	"Qw/WRKMp5aFVusKrZpjSKdZ3v58tazxmJb6NXQlD2AabBtG1MLD6P6xKQChW0XsB" +
+	"77Y5z/JBkkMXpKgXiWquYcP3Pv6+I4oBI7HediIrxI/Ei95EsFOQPxkk78pP8rbI" +
+	"tJ+v+lu6eiHk6+Kqz+L5PSR4npITj7fgsgl+q1VWGLPweJJjUnC/Grtc/J2G01ZT" +
+	"LW5ObQ+bnkr8xJ/5P/vSSP+C1jG1YK0Y1sao1qoiqxtFbG1bFRtUa1sVo1trGrG1" +
+	"RZKNo0UFSilTNtRtGjYIEClGbbBQhUJBpCDY1o0bFbGCxY1MoNG2zTaLUEKzFBMN" +
+	"tUbFY2iqKIjEUlZKixqNsW0UY22i2g0agirFbYrFtJiNJbSao1sWMUUUUbWNslpL" +
+	"WNjajFopFMhJGxRRttjbBtYNtoo0YrRqAKKLUkmqi2sSVY2oNFaNotsVoyQVaNGo" +
+	"o2ooqxaNUUbFQoYQ1o1WLUG2xVgybYtGtFRgmVk1iqZFQlJrG1sbWTajRaLFaTUU" +
+	"VRtSW0bVFWxasFWIsVosatiqii1GLaNaNGpINqg2jVoihmxFti2DGqiqNFrFslti" +
+	"qMZJm2sYTbGLaiKiNYrRRGsbWLbQWoi0WNGo21irG2RMpRo1GK2Koo1ii1i22C1i" +
+	"1RqA2o2jbRRjWi1jatG0lUBWzNUWo2xpRTRVG1G1Ftii2pLWTahQqKi1otitJqNU" +
+	"lGjJNKqI0Rq2i2yaxjbRqMUVYjQaKwVRtFjWiCyFiKsRbUWiosmsaiqjY22iqLQb" +
+	"X5/99f4p/uUf0tf5/9K/qseg/3/8O3Ejr31kY1gc5A1pvXCxCkNiwvOQZYLITeUx" +
+	"5CNobGwqJ5o3bWtQ2oqajkZRrRj1prYW5TG2RkzhxibIud1zezbDrRBn8s2xsbHZ" +
+	"Ilaaujw873Rttris4cJCx42DgiHZM67LEm5mczQU0zdbGxtvENm4RY8axrs0rvvB" +
+	"2Lmhu9ZH1rnXlfnhQMwstTWMgZ24VXZJdzdKmphdlKOvHF5Ypc1co3WpPG5UchDH" +
+	"HthGXu6jHcIFa8oQrWt53ErY2jQyDFGQGaaj15BbvaLTDPKU2xY9Mj2zrW2Hba2J" +
+	"jEwZb1mshmPWcZdXPGGDOQ4hqWsZbxqyLQ6ysx+Pu9UmOHJEyavWvHjbPPnsX1XI" +
+	"iq+W3w8Tu+Ry16Js2+QVNGKUjZLWwXGBxtiE2hFTSXGBGkBjMu6xtIYNFQM1yBbp" +
+	"9u0ksTStorHkolJ3E5XN5tOFjhjhwmVcOxEtLHxyyr7N9lk1DJaN0qwpiCBpBAPG" +
+	"3V0ccPvd0Avs82rSKmAnj7RQAdYSdYbzJjI4URnJfO3TT4xQ26ahpseRDUtS+MKb" +
+	"aVjQ9wg3lnedmecmuQV2y44ptKaHyuZcF1u1JXKJlu6pRPSTudsbp5qixXfWcnpx" +
+	"PboouIu6q3vjI6ci2PuVosvF0bH3kaaLyFWNsiaLGxxWqGnvHH4d8MyQpjfcyGZA" +
+	"6+PHVbTd22SxshNhjBvMiBiocsG2M5zFRj1yyQh5C7vZX53zDy85X19hw6XAhSc4" +
+	"4HRB2w2Jzqalk90qqeRM9JrLjIlc2+tvhMyT2eUuq4MdumMqyCenJRHTk1OZudfS" +
+	"+VfKOcyA5HHezeQrJxq2piOM5vIJjY0fYvMt9eOLt3WsvDtG97S85zOs8DAjs7dX" +
+	"vmFFxB5l4hvFFWKjG6TIUmyWmMme3cQzNyatha2CUx7UUluGUDYW7GzYGPvUZVUN" +
+	"2QruGNDbQ2NtNsoEDGs5S4Sw7tuXObFDTJmQpdzuUSm7gDGi7IElwyNbNWUW5apw" +
+	"r1xMC2oS5tUYZA2cHGiAzve7XardJ2IuYysvZR0Ku5Ck+2RL65bzSHlFlxDxNMK5" +
+	"TWUzcfeFomjrOXGkuCogWNpZb5Tmyes2YdxqRBmU6GoIV0TPJNojDDaqLiTC92lI" +
+	"44VORRdd7f/n2zez072fHsVc0lJBrBTJO0dTCCHBnnJ7l4TDb0xvuQrWjqhowcNm" +
+	"KETZaeWn2MKO9JNMjipkZF31GWlSxcYpJydb5hSnINMGPuEOnRLL4UV1hvIPGKBl" +
+	"ZvS4ydl0W3uRzvMAxgqY2gIYc5EjKevtHG5vkRZfTi704pm64VOlm9mnddnhX1d8" +
+	"i11nlLfO43hvIUvkhnaDTed1UYzb4SQy8iOZJY0OXGtwdkbrl6UMLqQoOxj6wqcm" +
+	"67PRzUcwOOdgLJgvlpWuyLe1MNGlSR9cdZItEm9xaWRy5l21raQcOMenbGPjUtId" +
+	"5L5rfXWQr2NbGd5BXI6+tVcA2rcJgTsa6HJhyR9JZrTaSuTN7tG94c7fN54bJ5gK" +
+	"AteSmybgHEB3lSGHTGcmecrPGjWNw+WA2uNR0erioM73usN6veTkgxmQtzC+7W1C" +
+	"52SQlmXcODt80oUQQutphmedzHoa0Pb5uGiUik1kXE7ZGybH16ydOZNOpe5Sgesh" +
+	"jsIhgWSTnObvd7JYyX1O5WwQQTtFWii2tYujUsWbw0ezmrTNw5aVPbIMBpLsctzL" +
+	"3e82boiMG5yOnOmm8fMsldyWw025uHyFFYaQ8uhZTsWKiNp8JA35OM6ztkc5IRzb" +
+	"yi5eshOO7RfQUENxDrF3qvnKutTq2OI2Axlgzi73va5to5kVtHbQ7Y32Dd1k3HCj" +
+	"LIPSN73VuOclVLYXpmseBJzbNvLSDWByI7kReScm2jiac6ztXZGkbaiCAyO2QzIX" +
+	"Td7J06xss3ieAXL4jMoKMHsszhnY2tu+PYncmERURzYjb7rVmXU5FSXuzzzvke8r" +
+	"flq8UMwGzmKayKZkWIVa8gdUzJzlgqDkEC5XJt6MpysuebzMk5crS96OkqQR3Dkz" +
+	"ElgmcLoCwfLTbkIR3GXy81m+S4PlrND69sIGpuN6O4g2ktmwgkuHKu9wyznIiYqH" +
+	"xh287t87BEPFkERt85JvWK2OrjtJEX2u3Obs84debd0rw7zdeXMFzOZDJ3NvLmvO" +
+	"W98l52eec8Ovx3URCkNEx+BY1uglDVhy3y0UPJcKyiDZjGbewQ+bM3Edm6FJOvzz" +
+	"azuclkGaGMcYNlfJEmxcZb4M0d5vObBOO3PN5hD0onSZ5O7GGzFbRbOZzlE2Rhka" +
+	"wphx0zrlixjRccimW65Ok1uZQ8tkA7rSLGbUGzJIZew32hAFkPnNVhE9MqWiOw47" +
+	"zozjty6kNk1N83UI0ZAZmzwzHu5NUqQyQow0vktdqtUDtNuQOWVDBrlBzZMzs4tf" +
+	"bbgLjvOVlw1POknTok9nX1y1i108eGb3lqIbyXdFm5ZQ1N1rdRtQsbwYcJmHBeXW" +
+	"2qMDeacg55NcqOxlx5mVneeFYjRYeJ0ckbFCkO9HPGh6Uz0YirAec3cAaT2SN9TI" +
+	"dhI4eu6xRjeuwlnHtcd9I6I7mnNQujxohaKtvuAQd6d17CIoMjnTcYTJ0gzDnLog" +
+	"y87zLa4RIWrjb3QJV4OaRG3hmhxMjBaozkkzdTcUbRtJzGncsju30dDubirvs7xZ" +
+	"JuXdqYd7zsWQFdt5eUcWbvOEb3hdO1zObnI7UeWd7m7t8zw5eWdMmpq9lvkl1O2s" +
+	"33XNPfK3sTSyZwcbL7OVx6ZFd7y47nYjGcfOl5WUbFK6jGO85fdlu+Oj//MUFZJl" +
+	"NZf1tARwa8BV+AQDgQB3/wP+ffir////pgsXwAAAAAAAAAAAADkAFvAB9CgCqKvh" +
+	"wIIRClJBQGt931KcB7ue29fOM4xl8OCCgCOsAD4gAMCCqAgigO4wANPNs0ABQWrw" +
+	"W94D7vhh57CBAWsPbK21bY1p2NSlc29vnvroj5VJCRUilcbPtq+nc7762bq+rYxo" +
+	"GIRFFTW+199fPB8oqqVSlUqJfA6522q9YIUQr2e0dTolBEUApKpKdxdyiq9PcxXp" +
+	"pT7XA1zw2DoUqJQtbhzOqiUFUEnrTwsJplFOzKlPLNubxmlvLabHh70vPbs9VSlU" +
+	"C2aInZnWUtKa6kV06iV7xWDfctwDvZfbVSHSMzex1T1Xu3dbtgdcgV00eRqTtivM" +
+	"xlkDWp3c5VXc0tLhitmrNiVChF12zldtJ3W27okKoCs8t8djvZ9jdAPWi0r3HoNJ" +
+	"bs1XKl3dVs7jAPbHmZ03gFeUl02d2aYcR6bmqg6173G4GXhqegQBAgTQSUPUEGEP" +
+	"UZGTAA1PCCSJVT9owqPVMeqfiQAIxGJkYAEmkSIQjRRphCT1GTygAPU9TTTEACT1" +
+	"SkiFPIj1MSaNAAAAAAAApSICIoiTMqepgUaeyoaaAaMgBiBUSIIIgRoEJkmqaek2" +
+	"po0BkZAPU+d9mfOtn2399/UaZITRTREBAJMILEUSZiSKkYAEmGm0IokQKAYlDGAS" +
+	"ykCCmWJBQBpkaKQLBIiZhJpSzJEhDTRCEkUETEKMxQRSIxiaGQREwxpZEg0KYgAa" +
+	"EkAGJGE0ilIIhQZFLKTCMSQMkBYoRIUkFIkmkQMZhGYyJkQwIUUkTQwJslEQk0IA" +
+	"pAEEkJCIRQLAGUhJM0NCzNDKbFlk0QYEaSCihZRNABJhCZRFKJFkxIKRmDJEZZSi" +
+	"mhJRNkEjGUIIIGFMpgaQMaSRjJEYTCYoGlEQpmzGZLISlRlCGEIIyYMaZKkpiCNI" +
+	"jIURTTTGkmkaGUWKRNiEM1ERkZEjIyMxIQJRjBkKTBJiUyzM0BhkLMYkJEwQBQGh" +
+	"pGWTRjKIE0SYCUjDSIhmGkyEZlMZjCAYYkpimEBMZlEghCUskyWQyUZiGYJlEmSz" +
+	"MmKRiQMLMxTTBlJoiJphJImIigzIpSYzFIo2MUASSpKIRJiaBiFAGGmgIUlEgSMm" +
+	"BGIZqYzQIwIpIljMJIKSZE0FmAxg2IjIaNLAaEhIsCyTEgyGYokNMEzTMUiNiMNg" +
+	"jRMMYSSQQhMghBgAGCEoEY0SkZlCiRhRQSiZEQgKMGQFIkkGIySy0CZQEqIshpMx" +
+	"jGSUUKGSQogUJJAMg0YhCooUJTKEgJoUopZCiYLEUsIkGESLIajJokJjEQJgDSli" +
+	"QhGIaADEBsWJJAYmkoDQjIJNCNGUEwGZIEkqYjAsbMbGjBAZkgkBKRjQGUQQTKZg" +
+	"ymhiQIhECNhhmMyEMgjBMYCJTZBEhSMpk0zGlEyZSjGFFRQpIykkjFCoJoxhpIQS" +
+	"JoRZIZMRmiLJEMwSJgibCaJghRAEyggkQySTISQBSIJJMyjWKAQSQKQYKLDSDRFg" +
+	"gaYDJhkRBqJiSBkSyBmQJhFNBESMWJkmpEwkjEQxQomI0wJiRijNKCQQNNhaYhlk" +
+	"whhLKEYJKExEESAzLCSURhIAQIJEpiQklAmZ/txdd3XdcOzl3Oc4ca53bsdc53c7" +
+	"k7runOugoiVLVlto221GpSpUtitttttEqtCirbVttrWLW0VsraQEkhMxSAMkmAyS" +
+	"CjDSRDJCCJBly6RMJSkkEJIMhCAo0wEkgYIkQzrd2YCBRMZSmJTCjKhmJIEiTDJM" +
+	"0SUsIxIEkkRTRMyEhJCSBIBsKBMmAohgwmJIkkCQaYkkCGSJkxCMCTruhzdNjaVq" +
+	"NGI1qqn/H/D+f92/9N7/nf+x/T/BM7+j/3Df5s4H91tC/+oosD+/gYNHpnVNy5J2" +
+	"alEaZU/66SB3/PXf/7//et/nu+/f9KKr9VSKdhIptIjKzARQZZiqimGUFLMlVWMj" +
+	"MSUU2oif8IKKYIhlVIpkBgFFMIYCimSU/8VUimSiVoFFMUof/mCin/KqkU/1/2/7" +
+	"ipn+uSn/P/jZ/qZLjiqHKWmltwNK6udN0mKLpTbnFbHSxf6h/6WePKShwUl1VbdK" +
+	"GyqU5ooa/vt32BeA5cSpdlPaWguWZVUxZht422i4WJpNsWzjjnNrttYxBLESWBXA" +
+	"to5UMFuThmsrEMqjbDpYOmG3M9440VM3kpxzZ0ZLjiqHSXODDEyJisUWWKaaZVEW" +
+	"drHTWsbg1ZFVRmRGCMFFhITKNXhUhsLAnAXFVTa2xYZviazvp7z20VOkudsVqq3j" +
+	"OeGtvWOVhDnvvuoOynI6VhVKbaPHLclddm+VRwsd9tpyhwG6KG0tNMuNM0w1YZC1" +
+	"SUMAuLhnLQOupddA65UOXPDKoZRXMpLJUsrlyDY2utozHDrg6uimKZS0WgtDKos4" +
+	"KnPMppbMLnNIaySc5TMHGbaxTuqd6qpHacO527Xh33/xUTIdWeKTmjbsg0PYKnmC" +
+	"1lVSd88uqKGOW10E52BMkmKtkyldBFsScY1nFJZktZQvRzSd5S0O9PG43nhMOVRs" +
+	"OXHDbwU5iQ1kkWZEeZGOqNqS6xHOJZZIhTExGkq6rcObBbGrBOaqc8OmmJTzI751" +
+	"Vi7Tx0LbY0JUgoOEmzhjjnptxIKus546uBtXLO4JkyYP+eAcAAHOD6fr9j9V+RH2" +
+	"S/L/QXTV3dz8SL/T8qH5noZQLPqGwlvR6dhx2TVtfs9W4cn6VF1Rfst5hq6EbM2q" +
+	"dokF7YlT+AevC278qkbLKawmh4pJzRaPv9leNe26uHhSuwBuLK+a3xCu7uCt8ICc" +
+	"hqAubTDuymwW6zBsaun77TDCZizuwBP7lwSttmpSykZaG/3IVw50MThjdLpDuH0k" +
+	"DTDN0e2mvqqKkAmVy9EDwysGysaREKB2NormNHUwj0vgO6IiGsJpEuyQETJyWsUL" +
+	"zZWvlFrieCawpUQgzlKTRwiZJXKyzbD3ulpxiGZ3uqqknBCteytK6wxraGufXo4j" +
+	"6Ql84X68MHo9PTm7GxF43W97OVuPemu2nSInel9rnXmRB4ZmN2FaIWPHWBY1gskI" +
+	"XduCgbTFmxaE5YSihkBIUBZk43EhJxOAqFTkTEgZg/58BOXSVo8zbqfJfApfLFzo" +
+	"w/f/d25jXyxD+I/OeU0dcx/x/aRkaa7TXU9oVlOfGYMm7+LW4ifNnrp1XifHFxMu" +
+	"5IbmiCprTZzImVSR0Qa8znKbkRuKQuyr1cokqPHOIDMit4yc4kkbdortTU60qgIp" +
+	"BnSrVsKMeuZ4NPFFXo3ratpwLFLGtrbRUbc6dxjlHMt30iALUHtqu5g6R2+W8fwX" +
+	"w/9tjnDISkwpFIFITGooZI4IpEG2wm2m2Gk22+NttNFNpstJJJJL4r7Fo9BaHfpy" +
+	"dVdT9v6/JXtG67C17waENSlYvNK2F2WomFGFDQgRHIUKMGMIWE4Qp1LPYVOJ3ajX" +
+	"ij0R2SiUikUutMpXscLDown53VRa5NdNBc3ojNNaETWjiHFD0SSCCSSSCDKT2PSI" +
+	"aiwTiy0mbTO6iKbZNVIZ/GZuWsmDvZ2jyAcoTPVEi8HyYNj0fsH+BpVN61a8JAiY" +
+	"SJvPsFnwgTI1HXbhbNF1FnpCTeho7rSi2EUjT83q/Cmc4nETmio0AIuw3CbLSbKx" +
+	"plU6HxSnZ2X76jMxwG6zEfg/GT47sv4GvUeZiImjSpzqWhp1koVUQmYgZfQYMrIw" +
+	"zgqXzPClmVSyPgXckhxZXzdVcKyu4Qi0aa7hpB4IJs6THDITGdymCiiMCFZjbbD1" +
+	"Zs2RDWNrUlQ/P8x6SH7v7Pz/8fq/1tn9U3lWuTf1JnUUMBZ0zXwlfGtzjVdDGdNw" +
+	"/Wb/TcYvZhOV0yvddt9942XK1inv3hKPY1yG22ftVJYGIHecMa1WHrVRdWNFu82a" +
+	"cxAgPKsqap3SvCX1k9lfXPem9N6bX0uaUbPfM+K4StqpjulMkJsnYV74vTdMY1Ed" +
+	"oFSIZ4/h6sOvXBROO5iA46Ydg4cPQkTnMmYnMTmTOZL0JQOVaKsWLsGxYqhdCCQM" +
+	"UGxBBBEJ7+U3578j0euaooSZ6QPtSOwWKBXnFoZlecqTfq1/RtQ4OItiMpbHqNXS" +
+	"LBpu9xQ9UiKIOt8lmoPPrrV81xoI5KWxvXhM3vY8pR7qqK4YLstYwxOVYstg0KRO" +
+	"i1fLX6rgTrxlmqlbrkE9LEGeIed9k26rGnWed6Nh06p11O87aBEwmLoD3HcEEAkE" +
+	"GRBBBBBEkFZVQUUkTHdrccRvm2/fthj1pS2KWAbKGFox0dOmXvOlr51nWKGJum43" +
+	"BBBIJBq/KsYn0ippp9W01W5ZRjbTSfDNkM7isVOp5Wk82WrJNLTsbRZZzsMYDiQS" +
+	"QQGRB573Pe988yZmZmaB0HgHcz7ZHJKFgkEgyIkiSS9eHnk2SvPDryK1aqqqmtW4" +
+	"PSycD/w8sflE+v8v83/dyIplqpb1llszKa0Kl8tWXbMGzMy8XWnF0X937o/wO4fq" +
+	"0+r7tk9qe2FJ6z3CkozLYqzEKiqUFDKGP7kqsHaWq1aDYcCQokp/eU+vt7uZp4fD" +
+	"vw29FcKUSuratW2rX7I00/UcnqCIfPyP4ftqCVUyNaqZi2P7Lo2/nvtw1Ntxu2Ov" +
+	"M1cLOMOjTdl/Jw/jqwjhrHX7ljvTS0Ng9YWklWliFUpZUiCjOKclNiKmjWdFMjuo" +
+	"dSAo96JmslmGgyCeUmmjEtITqi4DqWXTg4318osVuX2Vfa63aYJNvvZpHIUVXXbr" +
+	"pPMYqxKrXRvoXCGuFnXhSb4SVZtAm6ojtvuIBkdOcqdgEZ6lcZZFN1kPKhJJhRBr" +
+	"WEQyIWkl1hnFU3uys63k4eJJlSIMlKqoErDI6G4EEUnpZfaOrlixLp9DvOUpB4Ta" +
+	"n2/ZW/q+fvPhH07t9H4MT16XESiARMKUE/rVVU3KNwDooJ7dlAzgnD7EhScMIYxZ" +
+	"/mOidHDestpVUIAEgC0t7/m9fLzzvPVb1fK+s+Y+f0Pon6xzJ9vzOD8R9GeLf1T5" +
+	"3aq222kVRIqwftW1VyfHRO+89MPe5zaktbKQr49+/jZmajwxNu3Zk7fVWkSWG+K2" +
+	"a1xZlKFOw5BlJpDTgyzEORiGVhmzt4tctufPV1DsnIxdsV3SbUdlXBrTgwnt41HJ" +
+	"0263X9faPss1y+iNSMUfp/X6ff7/6/TW98cccp1bYjhzq/3uXPJj5bT8/7W+nhNo" +
+	"/69v1+jGyfY/aaf9UV6T6SQPl1Bq30rH6H4yV69J/bdqqKoSHon4AEpmUtPAez+t" +
+	"92Y5lOj2CJ7CYdkZxf0D3R/XfsuFMS/C43Nv5T9sfMZV4L/G9pvd03/3mq9yzlm2" +
+	"xVJVkOV0LvETLzsJRx4cqu6dXdXXuPQcCHb7ePRk7He904sDcwdra7Nt9q7VFY9l" +
+	"7jUQJW14xnuJPn7/TMw/3fPn4+Pj6o/Cx3cXKtqlrD9PRbmYZme3mP9E/y7G36I/" +
+	"LH+Z9Pht8Afun7v7tJGbXiaeU0eH+Gn5fst6/K+NqmUrWijbu3DZSH3hD6nZ+o9S" +
+	"qiIxVVjIQnk5/AzMrhcclKH4STg5bfDDGO33aTpJ0rlQeHwTE4GVRAlhOxMpdgNv" +
+	"3ajAlCIVM6Qe6uKg9yOwUV9eRvl2dAWQKng+meXZoWhDqzCyCFDwHzqlW653rPFy" +
+	"aXH00S9/SI7ZIaPaDOu/U2err6Wt0/RGxFCJ/FfXywJ+Z0NuUscckrzN2LlS+4To" +
+	"ymv403aBj+06Tl0T6Xne5mhKZXrsbvOuKiXR7e6HiOm9CknWsik7Lmvsvrn08oTa" +
+	"aD3VS6R5uebW2codGHht9KN5dWRYyrvSKCuOIvhyuzboi48y0eX0b1ZEk7XR2mzQ" +
+	"lIxgob6yp54pmGTlmwZ30l56vdry8vuvXD4hdHdkDKTAhgiUo5KUmzxNmilIqOOR" +
+	"j4IT356J9N4UeHHbOSSOyBPJ7lSGRJEjG2PX7P+mxdE4E9kZhSbrNHt+LR6oxuXC" +
+	"xtS3UxPlEzA5XpdlqQj4iqskZZ3pmdTpI2hJsTma3b8RF/EoYxU2m5oFB5TT0rss" +
+	"2w8zlr3Bw9jYwgtNtPCzmmpqJwmZzfsew9o+/u+NCiXjuaEvhdu9cDRPzPZbreMo" +
+	"pkxCrlWTi29L4pZEMIlfLbK+xSL0Zqy7IjaLss0ZGYsGcMGrgagM+zilXFMbIldU" +
+	"QarxUPisyxhSqeew68PlX96+Vn81ovsttNN7r2tOwJnj1OGZ6GmypFEL/OURjEXj" +
+	"xamLJXj4pVTillprNqvk5OqCY8vVrvLm3qoKGDgxzLgEkqry6tOg257kmNzyTdlj" +
+	"Q8tAmWAyU3697unetmwupGywUXVcTN9MqL1479u2I2tsRZbvyj68/LNRM01plhvS" +
+	"bN5NcjrrccL8Htyj+BCrHefe9PVPN5zrUH+1Pb6rXdo22uWWd/EfwZZbUr34gOaZ" +
+	"1MdLqLC9RP7u6RSO3a3RxXP8X0wBLkn9FRxLMv9CJEbYsiOpgpUSoa5GSlIQU0ym" +
+	"1JJSRLorCY+OqjQVlihaqBciZcOS7lgmERMS0iZQTN2xVFERDdrxbKJtzCzbbXC5" +
+	"bTm3j1zMs1uqI3AHShpYzQRbTYKYrZRILVpDLWCCHKKFK04Pz6l9+B8QwVBx3HZ3" +
+	"pHj9L3wPqk8LV2RT9q1kZcelVkMztswvhMxRjp826SggOKFASfzLUZH+Trbl452C" +
+	"rv71T9Wht51YV3hXG4QPJdqV3uZz13mwrzVZnjVLbVn+YVe62EzchMqtzShLkKPE" +
+	"dMnTiMTvOqRJbzVhxDI1dd1rQhiTqmcLOhwiEgTPFVyLB/BYxVVJ0qTbe0X+E2NJ" +
+	"5FQil9Im2yK4hAhROqTbaIFD7Kzyqk3ny25Hm6dGXKvdrsl+j9LTNJyMbczUREDG" +
+	"XgVzlti/gxxcK9lmrQmuXy00nPZ1ZnYMCOztzV44ehTr4++n1Tt21RvA1/+natOd" +
+	"+etlwD45o3FOGbqiF43Vsp2VA9kWCP6ERX78Jds3aZdJHuSiVaYad/n73gTnNOq8" +
+	"bUvQV1ck9/tFEv8o/X7P+1ZhaugDmvV+7UkaQ/vHB7fX5WVgRokFFMNzV0S7rpL5" +
+	"fPt5HpdvXdsa8XNCJ3dO64RjAXp5PJc5siQE7p10k7q5MlxQkHbwYYb37js+uXMr" +
+	"XQD53nebkY+JEQ3Kr6j5LcbHtxRKez7rjvN74ZI/binYF32Tatmu8Be6TXLsrqtU" +
+	"SyjpPtDkefbc/yap8EMZR59eNbE1KJt1yzjkr8IrBj8d5+WZHW1FCToyAsXOUEXr" +
+	"Wtq1r5tZb+GoluBz2+U8FT3va2RkKc6WR3ZeNn4iq1okKrUThD2MqptNGqiTJ4M2" +
+	"f9u45+/nwFAQyTz4I8lDKWkdQxJJEruEVFU6mHlMh/SyVffytduOEYY+qcVewuWR" +
+	"7sCx2jKWaQSEq05Vh2otTsmLP8nxVuGAJlL6CQ0fXzP22Mn0O/dc+RzxqdnXq/N3" +
+	"KIZUKGEwHCFgyKwJcqXSyY9+KkWLMIVwWZW84+AK/Bz5wnaLI44LmU90x/EkyBYo" +
+	"YS1EJA9jWfE+/5tRUV1ipCoof2zsjgKQ8vpHUIwQU4hNNSOW4tYulfaqfz6P4wYH" +
+	"GDM4DID3+NqN1ONUA/PfuPMRXS88tk7zKq/wt5RmaVy9WAxsjPw3pHVUomq01Y27" +
+	"q1V1m7Yd2KfWl+O5Zq7729d9zZ0l0p3fEcrJ5YgfbvWje7O3f3xZrowIWRkq4O+T" +
+	"FRyxJpiWo4lFPH3WrGdl4cvrRgQWOs7e+Rm7Fg5SGPs7K8wII3++tGhUMYuglST7" +
+	"5KtdoyntNOHVVlYkvFyJtG6k2rcPNYnRazDvM0jtv9e0GxHtPw9lbsVHo999iMnW" +
+	"ySQyREBBJkSLp6BsnvG/p9faVUKlPzdQ/ZVIRVFqLwVZA3bCzzChJo/VG3vBX5SF" +
+	"rWK1RZmzbONI5WDQJSoSvFrWQPYWLVWpk4wJi851alamk1f8QZvBepyqUITCUW1M" +
+	"PO3E+bYpbGJWorqrG+spHFPy6ovW+piPxPDpvMK9cLBMXT02D897907tO7q6Tqpw" +
+	"mu19VLVj5w68m9aLxrh5pRd60Z1Y7OPlnWyT67h8VWsGO4nUUKiC8Pu5yxhCT898" +
+	"xuvPfY+fhoRK5T5qvf5+ore9q8fDLTyk2u/mia2vXGhbTXwjpwro94vOKUYpdrNK" +
+	"/ilIKJN59XedxQPPGvYqUmlTpq88kgneW7DHmiG23HMo7Zsh04+H7xMdo7xOJJtY" +
+	"eizcYZdt7XbKVK6OL4vQLe/M+3jq86SgU5889oFKfPVuxF3wlFrkIun9efjz79d+" +
+	"wYeN/C+u3m1rd0jFGq9X89KmLLXN2C5Po/veZd64ndf3MKIxsceKwWTeL7MD3i1L" +
+	"FVj6xz2pzr8QKCFNCFKpIp+xTH6JnyBsNsPitQloYgqd1l5g4jhq6cPDUvHlmwrI" +
+	"oOhRQkOJcJfIaDs0KhNWaJJhi4g5WXdYcDKbkpiy7o20IRRpRFyOFooQ42GI3+Su" +
+	"oMuUwozR5RSK47UcIoQsIwhhRiAXHRoVM/c+S9/l9R47JC+j+m/Feaff6jz8TUQc" +
+	"fBu36cbfXyrsgqiUIyVfLNwCKvgnlBRwKKm+brfbFcOClV8LfTPJElZDw+Yw7n3R" +
+	"/39I96pWacn74akmCfZk9N7Hnbmfnm+G9N9IIVf233Vjv2K+dmOqXTgm/cpSxjx5" +
+	"NoTM+aO9xtTisCE1pRXSdT2doOxqKdUb7MQGth/hkgx+xCAlvCV3TRG0Ce6IyQW7" +
+	"O5ROkRaOiwj2YN2coi/fFuizw675bLOfJnWg2VO7rRIEXexnFH3XUPPfxRcRGzXs" +
+	"xpAtbS7eu63smcY2W+6RTU1psvDNdHE51pxd+N1FlWJbYbvu4qRoHx0s6pEIRV8N" +
+	"xbCsclUVRe1t0Tr9/qt689+zMRbOMBXqvBVD8KyFEO9HimPzqLzwaL5e+3ZBPN5Y" +
+	"7c/Kfp4kQCKdTjmOa/v154+n3TBe7/D3+v6r+/voinkqWoitVotACCo664ufF4Po" +
+	"3J6cfruz8fcQTLL13Kd1yNXLle7zzhNiNjuuwY3dvT6en4e/3/ffT7fX3eKmQXX0" +
+	"/wDQj59+yNfHDLb2ngE11HTs1D00z1Rmnx+dfhwbhbzuLp0qd0QHMBspKuzzC3ON" +
+	"dfyL9+3rQfBoYPjz4zsDVN+WG7vLnXx9Tr2sSvtE8MUa1li7Bpqrgl9mbKWWkUrS" +
+	"xt51NbR1yPPlQlNbX2vpMO6OipAZVCnOzMdCcdMd8ANNA3fU9nxFkfotXt+qp9oP" +
+	"k+AQUQa8iUvJUoSVIGwuzKjMpmM+3+Z0JJ9oAjV234RfrNBxtZMos3vCkrhlcmZX" +
+	"JZqK1aqYUg1pqK4fwfD1WX0eSASEKQ/xP5j5X1rQTbnv3OI8ip3bm/IdSENUwIVV" +
+	"CBlkpUlnZ2REw9p9/blysnsiOzjy+3xKhFfg6Y9VKDt267q3dT8u8J9NhYJotAkH" +
+	"UBPU1WdVV2dPq97X2saP9b/I78+d+hJa9dsO8Dq7uuiXBGuVPDdiDl5sgMgCCkTR" +
+	"ucudbu90qcSryhxzaniH091sPgD3KHqWgJEDwpMCgIuFF5DDtnI77sGMf+eGrB8U" +
+	"CUkTW1qLEWR7RSwstGmUIlsNwAQgEqgykQQLO1knr6u1ttq21Hb6I+XSd9/RPL0/" +
+	"pE9I8J/gr8OkY248frxb8ffHG2a4zitLxY9lPyn2k/bD85+59xlp+/KfS6jzTDGV" +
+	"KlCSXUKDuGBA2GxzjS7K6hA7uoAgSlLYS2qL/6jhPn+y2y2u3o2Tt0/s8v7+lrl/" +
+	"tPT9O/Fvbfdk0V+HtoX6P4/h5fh/Zzr65P+z5dyH9HPb4K1fuqT5PuQMhcP2210T" +
+	"TD6Tx8InpqHwj333mVmPK+Lfw/Zy/VOHTmPh/Y4e230Y6cunLw2flSdvb90NP4n7" +
+	"P7x+yfRP3enyjwH7P7Pb7p+s+0w6WTLFVJtJ7fRw+3jh93hw0r/PVq20NKhwUT+m" +
+	"nppNp/lXTSUy24lK/p9p+x+7bhT5Y/39es1H9J9h/LTt/Ha6djhODEY0qtFflRyn" +
+	"0FY5fsE/Dp0+HL/Lb9lnh6YcP0Ym32Y/Rwp+H3k/Kf3z7vTy8I+K+yj22wqny+Ps" +
+	"dv3/tbwj0m1dOmO2g8Kfo4emjSqXi3tw+KtNzhy7Y8PwY/U/sn9o/l8PSD+utZcW" +
+	"37Ph7krkPur4qw0fu31nGszW2itKPy7n5Y+v8W+vzZf2Onp4K8qjB+bb8v8tOH1H" +
+	"B8o/l+O9+G0tG1pa21taN/eU7knnyMCjBUlf4T4Nvg4a8W9DpG34af0dOXz/L8Bt" +
+	"/Lo8d/GXPh9HDFcPhj+ngr92if2dHMPk+xw0x+XptPtbdPTbXxbFcOvGltuZktu3" +
+	"B29JpHD9/l+75T24fcjp/93tG58fLFy/Nc1mOE2PTw+O7a/KsP1dPKz1Ielp65m3" +
+	"Lly5mZmOW2qiqrJOg0SUOpO/Ym4AUdn91ovgujOz4FB0MBZWJO4mPoNtb+7266rf" +
+	"z9zM1txqittGlEv4/jbbCTioBO/q3CKi49u7fnvTo05uxVVX8Y0CiogUNx5JLet3" +
+	"YPFu7NOEC+62c7AwsFCz2reusG9vMFWax1VlAwU1dUyIEhit6aC7Du7M7VdNstC1" +
+	"lXlm7XRkSLM0jajTZqNBA9IW4mqEa7U3XwsODHDZVYjuyTqypLVdoZbqcyjdlRjo" +
+	"dkyjWpGBmkajVWlJ1DzMPPfJIIJJJJPAQDIGiiFDI221bW79r+Dx4685zOUWtrbb" +
+	"fyOzogfCvL38Olr2TVKbaW0vvu6QF5fnnbMxw4f2Y/dynRyqptyw2Smnj++v21rW" +
+	"uHL/Sh6afEfd+rg7tq21/aO38mnw4SfDyY9KYm/9rcSPu/X7Jy8DtpVNp/s39X6P" +
+	"xVjyn28Mf2culqrID0/Z9WNK9+LbXseXB+yp9IezTttsnsw0m2J9HPXrTWa1mZcr" +
+	"Y5Fj9fX8f16/rtx/W/7ccT29K9P8fS2fRp+r4CerERJEebBr/HVX8Y2yv6ZK4N87" +
+	"Oc3/UFSf54kQJDPt4hEQISiNsJ19vv6d5ePOXnLnKlVRMqnKJRN8HOc4eHnBzoIH" +
+	"MpAZ5mOq2Kzf1XTznObSPHfYLFdt2e53f+MGA8zED54z4hfEg7rRJfbXkeq33bpR" +
+	"ebgJAwUvLQPVZKKFSSDRYI4wwgQCBcqqHmqrcrro/+ISKcn/1pVyxUc+791ve+Gi" +
+	"7f91U5/UtURLrEFwxif/K7mLJLLBmTJklllMbAuMlEryqfWitYksSyFR0c9WGSW2" +
+	"NMjKZLbGmSTzVb7Jbba9lttvnPje29ykZaxopllRLYrTpUlc4iY8qqyI5d705MZv" +
+	"u1ZllGstGZYT7z6Z6plQwqduumGQywMcHwrK86pav3RTHhW18XfjLFYyWbjorjna" +
+	"TttpVOBUpg27Ou7MrMMyszLdHBzymitUJ4Tz0dVMpiyXRJDbskep0BN7JGO8mdHV" +
+	"Pd1TStUzfsg4eXuWE9PVt2juEFWDZr24eiXW5DE7KjZzEOuNZG7I2ocWRlLYLVvF" +
+	"GIucZOLIbpOKjLLUtRat4sjIGnHJoJtX59aGaxoZtSn3kjr/BfvvEueqYoavHjKx" +
+	"lfTkQc9PwqlPyjh+1Tjaztea0tZo/XVFD512U2EDj9tVTpSLeu7zGstZacdMaS3H" +
+	"LvcS+9fHUcNsArlVO3L8To+YZW3QdvX46+4ZlyqnDs2vzrkqcOL7lnnrnu8/OY54" +
+	"O1Vp+VBoMO5sxa7ODUmwnEJvqyTdRq22yZN7KutPTVelXigrJvTW7bYeEeJUxwNk" +
+	"NlWq21IcSHn3w6MTx68cHTacUEfeN4zPFzT3uFY7X3XTNafe0tNeKqbVU8s+c5mt" +
+	"7E7erU+HTx2Su+OmvhpwPmcIeHwW7qx29oNMLvh0fHz44pNODegO6ZMEIgYczrCT" +
+	"WdKk8MDFGSiuOOdBzS1zZzVoqio5kOTtbKzi7aNMZgoHKdbV9Dlq7N0h523x9+6i" +
+	"49cdHhy5L3Kdee8uTrlo5JI8MkRs0xx3Jy2Vtbxbho8Fzs+RYy555fVjxRvjk17q" +
+	"u+TeMhUNSCJxOGSaXOJIampROLhmaO2zc6CyY2kbd7PgiY9Mkmm76s3Tx7yp8fnf" +
+	"E1+NlrW6nhoz1fPXb3ymeTtuRGa89uIgybYSRnch0uU2n5K6nymfCrxsnUc7yc9N" +
+	"gY+UCpqeMhw3YTjNExOOB6OpwmBt07D27E2yOkgo92SedsjGFb5T4cKHWuV2M8cF" +
+	"8zMy4FsuJXHLaRIdimuHBprXH3TZTtjDi8eLZ0dKHf427eFdKGF72HenvID6MMOn" +
+	"bCLWNsgpUEoZZG/vyoPxPnHd+D3Y+H3rpjqclZUisODjFbL69xIOG+QclTpogxxw" +
+	"qNO9m2ni+V9vD2uz1tpoxtt5t1PjrlVPhy7WwKnZHuC3ruTKRLY2yUlqGlKqWkiW" +
+	"y9iHnhPZO0rN94N2brW8hut0yR51BrPKXs7JGxb5AnRiZTl2Xq1hpiXy8iczq1p0" +
+	"4OUvW9g8WPrtcenxbXL58ic8LgbnL1I0m4MeNSM4zVJrWW9uI3DW3tqHzluUwxR9" +
+	"+s0Vc0hpweORY4VOtNXbALUCyXLqNFcCR7xxw8jTkStO873DPfY017vHfEhE5xAu" +
+	"lh+U9Pt+W9++O/u05zeb4c7pzjRaWurtlU91y/Pj38bnSo+8PfvF8I5SNJ62aL20" +
+	"QZtJUXrrTO3rYPXw+NeuFWmevi1C41Gt1m2DMqHmySGsXd4XEMFkBpCUlZSTWAUm" +
+	"a5gWmZLEQcLCwtjR0rZplkWrZuMqsNpWrMyvBJ5/Gff5lT3FTnKql0x9H4PU/DTX" +
+	"OxAXime7qULq7DqoaFW7tVaVWymOAghDdEltpIwwyIooHivfPjSHoqKy0NCBIRpB" +
+	"IGQK8fXhPBpMTMhc4OCJWMuxlIYammJ2sgEEXEs8oDopthFpLOUlVTJVAqKGFoiu" +
+	"fFmCKtsq1oM33uOW59vV16cDSvt7p7+u80IySXnVy5lF3Mz5ZLDu9ZrDzoUPrekc" +
+	"9Ie3XnPlekWLviZo7sWzm9WT4r4vmvd4+Mn1zI9eadvv8/FYv0fllb9OdHfmF98c" +
+	"xiihhSVRBRSemqq32pgz4bzMD6OjNYamHHHp0WsLbYyKxZ3mLD52kY91zW6fPB9d" +
+	"GObcd2fPPjX0d4du7bA4tvfmSzb6t9NouC2GU+LHHGJNXK4s3xiY6MfbxT4Z83cZ" +
+	"UuZDLGk0mY/Z/iHrRxSY3S1SG9mvzS+bvxc44Th6JqNHLLC4ZR+p+NfpU+sMTeHg" +
+	"a67ZI7LO0gsjRa278NqHpyOH+PRsdMcqF5x65vjp0KeJjqR4dknzo+Zsle+oZmSN" +
+	"f8ttztuTWnh+4V2fpXP02u7ttibExiUsNhbdfPzh1+rQ09U+enFtXS5qQkjjxMd8" +
+	"MkkY56cYwqZcb6vi222vU9cyYersXMh7cOOI2Y7Viz6BNspac/J9fjp3RQw/gqpU" +
+	"1kIPpx1mbn6DEJI5wLjKElOj3z3XAvFr+HD+fSn8rhs166dJp1CBw82PeVw26dIv" +
+	"7MUi/KQbLXXHt4nPh0fSOYs35zI1WtZGrbfqaOvlNp6VywnitCl7G/RjngwTGOXw" +
+	"v3ThnnFFDb8PHJ2lL1vMzxiXS7Hci9P169PULTtp8MorSZB25VNA4Pw6X609+3Vz" +
+	"WTVcyRy2dbt8H177mEWSRvh8M+vSerjnx/SZfuZ0beIXSUuzna/Om+czLbbbVfTz" +
+	"54naAdd+pE26qa+jh4iOkG3g+U1FmjxmGX6Gj40+jLEntyrIn7/D+T8fy1+Pjjup" +
+	"Bc3CtbNuXO2tRdulIu21ItGsL9ccDt6aEtrxfwXjqcDx58HqqhesQkkFR5Hw5s+Y" +
+	"95rjxZ49Zxzzzs55zny5Y/Trf42ninShp2tC5MykPXPDq/HSuOcy/Hrg+uXOZjhw" +
+	"qpi7evQ+G3aueLbIW2pPLBOXPB2k0qeWcvH8dPX3537NGVVjFVhhjKxliVkqkjay" +
+	"ptqZq2S1WktJVZNtVJa0VtCm2mzbZsiNNZVVSy2ti1tS2Sq3md9hy4638z5PHNMz" +
+	"Ix3IfMkD8jgU/hevg0z6O9vrhfx2u0pdXi4ooddn1WwLTt3u0dtfx13/DwegMQYQ" +
+	"wdp85zgwAfA3hJq69eh7Lu7zLGHl5V6eivCu1elHunTwnjRy61p714uThUcOOcz8" +
+	"O1cqxabWOunLt5Rw9iSJHt3F3y3WWZdtujHhx50iRPHtKachw2vnz8eK369x98Ov" +
+	"hw2vztQt4JRlnK9QFCycOHEpchMB0Ym5SeIlIUMnPFcafA3klDSwWSTX9VVFP3k/" +
+	"KQ0+nzF4rj5wtvArh604+dqCN3Qjz0VcqypVmrlXVlSVcqyiSeckRld1JlJlRlJB" +
+	"zmlk1LS0RqoTfWN3vzzprfXjY+ZUWT9c+ednqsvvSSJCkAXphQSFpCgXIwRJFQeP" +
+	"HfxpU2Op7pg4ZhX80D8P0HcE+tvtafe0PslS2h6bEUphB+Trt9zcMySlFfrXx8s6" +
+	"aKGUneDdfjQ99/yYfX7l9meCDI/bvJDJAQgdu6SzNW3eZlBQykZoKrwo37d0TaW2" +
+	"0DnfHOPJfg278PvnXg+re/l0U+vfj83QmJIyIhDN53JH5Px9XhPr2/DXcY+NzGJO" +
+	"6t1p8J77+GH2+xfbwXyN7S7ySU8e36ZcY2cmX9ZqJVTbyyJ9LNd2Hy9pFJjOJx48" +
+	"YJh9fxDDVU7nuPtjdzVxq4025elJxy5kTGLIXu3JDla90qnLmi/u/hOXSqnQu+mf" +
+	"lpHZt8sRqH7saHSSEQXU251XwY4dOFRt18lS6cUnTgWreu+m18JO/RkmYWb9Oofm" +
+	"aH1PPXk244ZeFEhws+fI7cknaR6D4fDdfBuITwr5+BweumnDtjA5GjvZpuOHS0si" +
+	"Djw9vK9vVXw3M4takTts7RicqcARg31RQ03CvXwCPOWh+DxPrrPL04oI3S1HWXPL" +
+	"V28NsefHEu5KGKEqe8NJPYLCCHQMJCQ7PR5y21rbPLh6zyKm7rpxn60/GG3l6l0b" +
+	"Mqm2VCL8CsOWG2Qe5VVUemVS2xUlz8FNVTjEzB3gTsxNJ2NL8fkcfOEhUaCuYPW1" +
+	"wuNRLHrVBHPnUBbfGqqnLbx2unVlEqcfFU674T6+c8eHON8cbcPxnVY79dPSQXrj" +
+	"j02ctOXInljHDTacJEg5ZB5GNDvHrWNOquSOU5GHgGIrXB8Q3PTh49XFuZnMke3D" +
+	"Pi349tnTc2x78ZbabfvzMff1Q00qpoqlPdKqaqUObw73hT5rm2u3Djb92qrt3QRw" +
+	"acoV3xS8qpNypaaM8CBy9599F75+N8/OM7xre29w+OXpOnjtyeGSEgrypPNCAvLz" +
+	"gjvv0nE4N8L06x27SNPjUeRJEjXk3zlzOGsVtiMq9O5Hkcp2VPh8K+XJ7XZx9Zvt" +
+	"531nPHGb550jpsrvKpnZ7X182tPp4nB2m23Dj50a+PuHwWvHvJzCvWfD1elNOsfN" +
+	"SEgw75bTbwkkc52410eGuLbzmZkZvvVmtPrz195lSMXTdO+GvWa25VN0UMpetNG+" +
+	"NwU07IY+Tmk5PCX1drtxw6VwlEnsyq9FxYhCRtIhPTOT09a7ZutZpiLA6pDtYY3V" +
+	"5igfFU4zU4brTy7ejat64Qejh0SJHTSTZ3u3h212EB3mgeekTleTDmSOOVnfrh6P" +
+	"Y8ntJJ7Pr2KTqnMOYbga2JznETGW1bGqmrY4zLwt8niQD18xElWURb94FyqjnAZ3" +
+	"z6YJ1iOcC2nMPuqLNVQhSiLLqoyCroXV+YwVxq9cddcOZJtS0iqScZGJbLQOBQXO" +
+	"HE9q+9mbo5znrM8crxzyCVKhGIK9qoKpR4L0FF29epznKxmhKoosQGVDU2h3Ay47" +
+	"SFIJE+nw88FX5l03vzu+JfbrzePF0kBSZvDVsr5KaIWZmJzqUoIpQrMhASe/z86c" +
+	"6HyL3ZqezLvn2w0+aVZ7vTMRFUZPLRe7Rk+Uox4XrFfp8/Xz18+/jybiRw7VvURT" +
+	"5MeVT3Td4+Ma5xHFTVt3xxqcror7cx5cZbWPo78+Fcp3j1jCSRIxTy4+XByxM192" +
+	"To8aO6enDlp8Tpwnp5LwvE56l2zffqYlRPPQ4gQywiSLYYacvPXtw/DHocyrt2j0" +
+	"e/enNm57m0qsB8YrRH1Lrhwgi85HTIViqnpHjX5odbWnqdJNpywNzy5F55CTpz3b" +
+	"Offvji3GWujD788zPCvnTt/r5SH4mbMvVznmrtcufVxUd3tFD8H+XCVA9+aArHR5" +
+	"t2MPNpfFspyylwe0mEjs5oJOvfjxfnnNXNbdJPJ5YcaYgXzEbNNe/DNpS95PXWbX" +
+	"Lj5me++lriwkeI4ck6bca2nHauuzfPTyrxRXIm23TPacNjajfNUa97T754q3c0rP" +
+	"IE5Nere/DaZzyBPTHL667M6YMUiwUw84c4W+5rlfVR6zxCzaeKly9x9x6DhaooPI" +
+	"1CNpPHVtq129Z3bpzpOM14nhw8c8mvgVGdYiu3n1jtni6FPTxEt8uOLVAnqxzGvU" +
+	"4XXlc09EDkrS68VHEuLovfh0kKjn16nx2624KnuSnHXYVkIprh8uKrXkxp5Z3aqc" +
+	"aeE59GkSJ0a8drt6aX+06Y9W1WYqdPi+di9Pw6evm8zGnrTzvvv+GSuG79/XDiov" +
+	"H0qepaxPYPTbhXBj1xR4w6Tg6NcOybV4+Om+3X41ItLvfGlU341TWO2R7tSuZO+O" +
+	"3asyajzIENvnh5J4Xw8OuDlfBN8GUCx4420ZVU52z250coXTppy6fELl7Rjpy+nP" +
+	"x28cG3ng7sNCRkisEe3Ltzt62dtbszTgXpLw27ePvRw+vlFcKR0ekbTaMSHDJB5e" +
+	"nZ8vLbTt78dG25fCwkJ//etW1scxPdFsVVsi0tFqS177RsuXJMklSkhrEjSwORa5" +
+	"3WlxTnZfjFJJ8qqYtJkGIYaQX+CRXd/3dKH8uAJ8Y9cu+OcSSPAL6Gs336Z468Zz" +
+	"vNxQRIyXt3dm7s0SAwKIJ5wEk8AwcCHFznBwg8o1kzNO72t3vAPY+sfngZ9dFb0o" +
+	"+X4H6XmWneYezTTiKIZ4CUUD4QEQCdPGmwTwkyTaXmJ2d+i8PAPAvDjERepd2Z2U" +
+	"tFeZqfopOh7VAjAeQ8BPpenxxACAkEQhEExObQ9XlR+e37Iw1mN+ICD34z4TEzKK" +
+	"dyQ5oUQnsRgHH1l1ker09IZ4KIqyrFUOLmqZbKLYUGaGAgOcGgdbwVvRho1lbYNU" +
+	"cdPj1zU4ogY7l1TxfNNPT+zP92ta1Xu6TpY6QeISM9/hrny59kjOErh+Ht2BPj57" +
+	"6L5BzgoCDQAx6HNqd9+Dyvbt27Lq3osAuFDt/Zv5zu78vxMXPz5rDDqp1z+Pi2nh" +
+	"zxuQkFAnqvWm2HD09db9dvJvpZ775mY/Nd5n5du34vVU6F+N+jTb5SesToqJfaen" +
+	"DXwdO+bu81I8knny2dLk+lPtFD493Hx70x8+ZnD/LrkygIFr4AcZGrTDQcMwVWSB" +
+	"UIKC4cStoBZZEzt+9tptwYhbUixKXVLSo3XvhOmipnoTQ+XBJCdfHJ8r47yZmPlN" +
+	"tp88W+HnzreZnj2dX2cPfT3zCQm3ifI8tvCeDfBNnl0nnzDynndrPNObjUhIM70k" +
+	"+Phvzu5niebfbE8NY1HHuJBzqbt41px6TjT2wnuOfnskTlZwenlVTqj+HnLFtEu3" +
+	"oQOnRi96VHqH1D1c+g/IZ9nQp1cZlfv1606UPjEUVw/C6dh+Pz4Dro+bIdOl2OTP" +
+	"vLTZ5+7/XSX29Bv0PSCdHY28GJ5eY3ddXvTet3d8H187Yn31vrt8fNKu1D4+cOuX" +
+	"InT13p65ql8fJv74217Pm/vXbqk3NtnkqrqnTkK7wpfdhA+r975xmcNIp7Twznji" +
+	"evTlp74w9peduGxXiNdczaymNYnPSSSSFdH57db5cA+GzcQeEkOBjPVentzlrtHQ" +
+	"fBtWJ18UIb3yjguww+BUcg8J5eHbljZU09Ja1euOjrmjp59ooZ2hzKN2Qay4mLA1" +
+	"pTOLMipVkiB0k7w4rISoDm5vGxYTTI8ymFxmtm+OGuNY5ZPbcqyxJP8qLkqcrsuN" +
+	"XvVCjgr1Q3zy6o5T0ZznGJlVeY1Td52qu2m5V2aq1GXbu10ddY3rOrpy0u3G0gaI" +
+	"oCqoGaZwMADnKp1up7vrdzvSOe91CCUrW9pWJcngyfSVtIngw8zxCUFzpAJs+tb5" +
+	"Zsn1j4Dp7628zYe6Rgm2wa9FYc1vkPNMB5NQ8Ic3l160dXv1c6zek8W9yRs1O1TS" +
+	"z1rN1EhwklOMD2NGX6ryTXTqgq+B6Y+TGD0AgzsO3XvudNp0bcBy7fASeOUcunRo" +
+	"167Ew2GNnFZG/O7eEsenI5SHrvvWZ2addPjD+TtfXdODuwvq5huPLaODCtE0ntOn" +
+	"L4e8t7dJ5M07bNC1FSRtpsdzzppPfI7dxw1640x8bjJekxsa5Y8VNtjEcBtCWwcl" +
+	"ZTbCJcD8HrfbHN5KHTo4Fp819fe92ONY4erddMSl2w76PG6tcHtZwrlPXKVGjFac" +
+	"1j+rOTbp5jOXJwuP10ofsoU9Td33dv3n1t2cqdfj9Pvyqk2efPmZ48XTl0KlODvM" +
+	"5h0nx+MfdEOnxtt86WaVU/eucz4+eu3ZVKY+v3r850xVTdadrjormihyN/evHXTl" +
+	"OFR1cY65NTCcRp8FenYLLIlUW8sJOnpScPWt7tZIJtsSOmHB33atvt8eF2+HHiQg" +
+	"NCRxrt5ejjpt8Lh0U4HvntHLtejv64WuYovx4cvjudsIfUUV5bOXl6xXKF8KXjpP" +
+	"vQ+fOmXao1fF8OImWnu/i1atr4deV54zS60z0kRUkUeKm8HijJ0r4pFq7Fh+ZW0p" +
+	"aNBfXr10NlfrR0278/Td06Kxn1/HSm+H8Kqdssebvr9V00fgPx9owrAzk/h42KL1" +
+	"67fvfB4VPiUIfGBcH0P4etPoVyKa5fXxT68OOsAuVItPWj1w165dPPO3Prp1euH7" +
+	"9fds6coXoqU5gR9Lj1cVXDfOfUFnHKJcn73553ve94fphI76boE5x5eZtBy+Ht3z" +
+	"2NsO2PGCnbwrDt+Pq4KodNhA28Ozw9e3Tlac0vVRrljGXXjK74Z2eHlKbXHRrpJ2" +
+	"M2gxJI5S8WzbWJB5fOzzK0ngIDK6THQVqb+66e221x72x9UW+rxDexdJ8d+/O9Zr" +
+	"M1mXw8jyxjie+j29RJENvabZofCnhWL1wD3ljj4BcQ54OO0GkHSQe/IN7t4HfjuD" +
+	"tPHLp3KlkOazq8sUy9Y3tjOLJlCzMmaWi4d78Kd+VQ0sVjFFisKSwqlNNSpaCyMY" +
+	"JhUqbN41WLJEmRFsshFLI70wpzxVDVJQOGVDMCz+Yz50FeeCnxee+p0OKhjnr5nP" +
+	"et8cb4wgYO5ud9c665eXro2ZltpaqQ2VAWc7xIg8F9WbmVmuss1wH46NPSq6o+75" +
+	"r6ndGvN2auHmEkDx6GEenCEQjUVKH6S7o7nqeTy/VH1TrvmVfi24LBBw8xYwSNpE" +
+	"8sJnV1c5fbaj7DwBMORMfPLNZvLOcobrd4s2vvkgcp4VXw0SckHZ8PbX4yw2pF80" +
+	"01SGzT3e1kxTTTd04UOGN4uYNHi8W+3ItR+t5UkOHvho7WGOo9fXnnm5jU28kkcn" +
+	"h8ar34DKQz8PS+0UNLpvX12vxVVT4FixZRLGVTCKg7d6NpMKY20fHFHbPHAd9cW8" +
+	"W3B6uvHn1lut71682+3b0eekCcIhIfPBfemlNvtyBHAV/OuTYkcsZ7vxb3PCthAc" +
+	"J5Tp8ErwsxlI0n3rzjvR4rr5meB17QHbhSBLIyHa1ZzsIKrDw6gTDhlwJiwFxV7C" +
+	"TiTvjH4uOQLhBYpFs7g9iZz1eObpyecFTp09Ydve/h67KmyAMb5631VNtmzEgiaH" +
+	"voEEA9jOcHBB6Y5jttTflN4ntsbyJB2kkiqnekzu324+Oz6u+mggPLyZ359BJ5B0" +
+	"H75vv+O98cccbcv12976z0kU9dPnSF745HyYQ33cpPXoOXLOhUp0DfHblUbbed8u" +
+	"lr64ejy5Ydw69Z2I9N+ed8a3ve9zh58tTm3kTpI2VpN8Mb84XPTbiYlSnHxsVKd7" +
+	"5NOQ9jvhPHro9jznCFWeydPNaNzME08nR6LWss1Ouel7em2Jvht075zNukuFDuk1" +
+	"adIWgfePGTgVKdrr4ziPTO8PPDtjuAh51atsnp486Ws04OcX3GrzMsVSx9Po989d" +
+	"4u9uULJywb+G3r10Y9F054GPrm4+L04ZJJkqxvxw8zVtr078cZmaVPNF8eWOnzjt" +
+	"m+Dzp6MOXKqbXT5aKmzzblVTg1w8Fy8+g7bfFrpVSnXPW1fHbb1XDGGpmJERNfAa" +
+	"YbUdLIY1MzGDJvWaVJua1NSM8i0YiLdVbblrW5bVtO8YJSMqFKEhgmDmWUhjLJDM" +
+	"DKMoiZY0CluHGm7ksuQolpmExItaAGFEt1JhFAmUBNrbKCiJTAyJZtArEMXRREHC" +
+	"ZTHBRGRExxlmSkstEbmFe7IABXoWWFGHTOoGks2lkVQKlwsertIkulaYxU1YkYar" +
+	"IugRakIpIA20qUYZmFcabhmNazfPjwNMIdbaUG3czeq/mv+/sp9452V9fRjeX3nA" +
+	"+uetKRd6dGlzfHRVjgAwXV1frY5IFJFDJHyc4IKXOHll1l7lpW8epW5ML2nMCWfF" +
+	"zdoNoJaHyyw0D1bEtW98yTVcnh6l4fNM870OjJT1pY+N9aOlHSOoPVAjvfOy6XY2" +
+	"YjllLzgBwOAG54zy9JMd5d5Q8hgek7RpQ8GnkrxxqqbKdNcHfWnS55Ncmdbrjhq8" +
+	"o7ZUGlvWBfCumh2vHI1+9s962fXxMfAcquYF86TrDOPl1vW8b/pXKecTuBeH0U+L" +
+	"2fGp45XJw718Z9c+sP5PnLvB4ymlt2KlHLXaTto+Lz741xvN7za4jqJInjts1qe5" +
+	"S8qL8mlDH49Q5+dZrXjzpsqcd5m9LldKpvtv4EDZ8DPrN/Putb32490+paWvg7pO" +
+	"vrlKWmnnI72+pedYn31Y0duGm3a9uBOGOHp0h1SV29OedcZxres3mbt32npptw7E" +
+	"xetpdUUOnblLt5m2eaqlyh4KfAeqHL66aztyzHfh69Zol/TfR5kRkieuPNq2+3lo" +
+	"JODHljhPalUp+OsY+bVGsXp3+KNK9OtuXLOAJqZoZPU24tuyRwnGurXKohrzvvvN" +
+	"a1ts2nXKnipqQDwxOu8bJI6ZfCCZCNw6XfbiBozK29Oz5zmLqvm1x9cipT7Klty8" +
+	"pOF329uON9fPvbr1pzeMpPe+Hr3sIHq4+uc3mZ3PLvZO09OHTzESDs426htwdn3f" +
+	"VRW3ZttTnnnM+rHbw7G+GlU7XPMqrzx1qcbOsdvGePMYn1vf33e97bkXTF7M1573" +
+	"x3nTpy0frx3VKHxzqqHTh4ED3htxzp0rR7w7XpnFbjBaMsMAti2WdMGWWphmA3IG" +
+	"ILJKMBLTKBQMAVWSsjIorJMWW8bZqzbphIxqPLNyrUqhpj+j5VOekvjvVUYBwAAa" +
+	"KM8rSbnby5mMvMGZKspWru7uiVau7t3V3cu7uqaSIWAE8B4eAc8bruXXY8ta9Ryl" +
+	"s10jpy+y++675d2EUSCjzzqZO093qYXV3T5vii7tdBPVdZIj3ygmbS4u+tw9U5gd" +
+	"efWVrXZ6tawSHPWTXMsxnk4iq+i56tphw8+ToZ4O5ATgW0MkEcLw296lNsfrDk50" +
+	"J1jPLRV90fWN0hz8XrpcPBenvXi8edeZs4mllq+utW458+TOnpnKJE+E9OPI7Lq6" +
+	"OG1pjRt3w5fVc9jp+Ncu5Uh7FTth7vi3HHbwktHIvTl5d+3CHhU0LhwySh1NMXTX" +
+	"faqcvPWZmV6OkmSyxFrWcJrWi1kksrvvgqr6xW9zj1ymeq4dcNajmbSDkR2mTlry" +
+	"5AnE7fgk9Tk978Fs2pXhPvjltkl3AXoF93yfjrr84+98655556eaKe/TcvX8+tDp" +
+	"+Pi1RQ8fdUu2pvFdMbdPAQGNN8ivU7S9Ryc166k8yJc5IdVFdb88+uu+/zeZveuG" +
+	"j1wuL35UllCnrTCt7IYcNxThFFbQtqjNZgXr60baY2hffWp4+ubvM/NIWzW5Uj1D" +
+	"p8eU+ZTg3naukLoZzl+a1n3vGta8samSFp7nvlKVuVxKevXTjTg2duJ3SfNK066b" +
+	"lwcPF5xw2+0cZJzrx68c3veNZrGOHXbTSSRwPSDE242fCWz4vTsVKYqOF4bx775p" +
+	"0xeOddrOpVXqcPaqqOW22WtV88c4xmZY7dL6ei956V67bbVtWu+nzM5fLQ6pS9sJ" +
+	"RXrzSp0cNSpHqF1oswXg7xoeipTO2OO3gSMFkwqyWwWmzzmd5mSrkIb9W0R4V052" +
+	"4SQ8m/L07yCFN+NEinDh32PHfHDzfDTYp2pF9vXXneZ84x6vcPRzRtDb1rS9KNoj" +
+	"G3tt8trVSm4nKzy3R6xxhOMVR5krVhMyjGXOrVEkqjaow3ghlCSpZNWBcVaxL3Fc" +
+	"Y9ZJpkrnJzlzh3m8wze+XP8uV2KlNuHovYPm99afPmu8VUqUJ47l3jmZl5eHCqbb" +
+	"HO7xlEBFcBA5Jb3t32Zl9tPvd2smGycKE9uyfDQQPDS8Ltb4qBF9a8qnudmpDwX4" +
+	"+wdtdWPrzp5ZJ51IafAcnZAsPkypcqpRFBAcxIYWs3vTR50fEtvnqdcUo/dUXwei" +
+	"bTydGiJ4PFIOWjex8NM77ddunuIT3rfm5Wc23BHly1Kmmj152czh1j2qUpWYqJEq" +
+	"vL10rcCedpLOreZEjlnPpzu3bt2Pe9pIbbhG5VdskX49R4c9PrbZr3tVMdOn17de" +
+	"nw+aNedrTuVI+Pjo67O359n1jijiSSJ9jstJAwAWh6D6ObOekTEOeh3nAr2g7ynr" +
+	"8xXTOMYFcwj5xiIpx8cwczh8LfyjzhSPBt74x6zvdzHlySLo8nCSRsk0eS6TRbxm" +
+	"Z3wnmxmnHMkNhygxjtJKwkU83mOviqqNjty5d4e44KmUaw855t7i6cPI8nbp5Sqj" +
+	"jbpFk2djdy3yk88pG+mJSHbOXfhw58IK24kkSC+DzcXXnNW612O4HXcPOwd+O0Fl" +
+	"8PvuZjsCx5376uzwIG+WIPHLtDGueXTEg7dMzfR0JnnGHYm9idAqLLCyKsqxZVXx" +
+	"lbdLKpppSUky2SmfGld42pFyh9d+861rCugePr6r6xOggdtdPr4hx457uTlQ/lju" +
+	"vcrnltjnbtqu9rUk6cL7e+9cX1mt71d5mJrs2PD2zySR16d72kTx67dPB2rKOy76" +
+	"78XpyWhUp8dXq0t/AX04768zWa18ejz5cuUnls27TZy4O2rxRtxcg11S6cfNoYO+" +
+	"+madlcs6drb67VY8K3zSk4YqtLvupO/Da6JNXUsg3mJLapKtWFixTMIxiMYqYxW1" +
+	"DMkpmVKMqXrbSzMt9/sqIqP+t/93+I/0n5Sn7T+QT8zf0X7f+TD+B4CttqUP4hlE" +
+	"RRRTARIfupD+YUw/Q0KfxO/YVFVv5cOFw/8J24f+hMf6Mf+DF/3MXL//P7Nv+9/D" +
+	"R8PD7NE/L5Y0/73/Q5TalV9v/fbLbfTY6Wd/hbKsn7vhvhcttfh9p/Rx9F7ThpoO" +
+	"zo/of+imn7jnrLbavsef4r/UcA+RPuf3Q+f9UqkU/8ap/+MFIjMqlZkqslsVZsrV" +
+	"JUlRZLa2yy2qaRaWWqRTKzaZooGCAwg+x/nV+FYg+fi2+gz8s/Z89W73ufUfZfMZ" +
+	"rG5jSeX2+tXiLy5tM25ZFqjVUHVXHVO7t3Rjfk7WWV5Xd3zfCC7d74/Bsvzb8BBp" +
+	"uu3U3zvXOnzxjyszB3F1Lpzy88Auvjt8OJfX88hg8tvPa23zrze8IBCEkACBACSe" +
+	"svoy46IiKqqiKiKrmbpczNUAkJJCTVerLbqur773rXpy1c6c7tea+Z7XygAnXQEQ" +
+	"RJmCo+i1VHsgGMnt6oTG4h52C6u8SvLrMP/waB4Bwc2A8sBaDwhBB/o7aeobMefe" +
+	"uPi73vZt7rVet2rb0T0fQ/9rykNCbO/hd3LcnNv0nxbJpOOM9dbX3aauDKzP4RVk" +
+	"8gGChiP3tin+2Ko0zGvv8rm997r3xV1pt67QJwiEFqEG2tbkdFH93DBwDjIPBfPi" +
+	"1V5aFeIAHWiKoxX7fYcN7XsJzs2YByCqCB9JkFUVQVTA6PRvzz5effmf8/OC9PMp" +
+	"C+ZtzACFV1K3GMDvG5p00Ri2rRwdRGfGJGZluZmRrhVWSvlPXhbVm0jUeerZfHWX" +
+	"OyPb4dvG7fq7d2YuV64ePXrvx6mb41zvjnrfDiqrwFcQ9VbJCMKmIWYsyFKsKZAp" +
+	"mGYZYsykKYZSrJYGZBVZVDChZKsAxJMKFRiFQZVKxBZKLJJhJTbbapSlmzRec3cV" +
+	"XShD4BDzmq1wkRIYPpUFVy20DjqcYA1wAOHwq+O9r3vWre0sCbAG9xdKyeSrfivb" +
+	"QO34ZArRrbCmGhJ6LPbla+t+POc5nw7qzbdSzdq7p0eJSUbVXZtq6NOrQouWy7TR" +
+	"Es2HZNRu1Stu7Ysi26gMq7VS751zzvXPF5506HQJCRi6HLltz9uN8Xm7zDLmXMwz" +
+	"p7a33LluY0zKuVZCe1T/O/Vl8LrrrqrrpOIUG2dJip/z1f+mv/K98HqwOlWunXPV" +
+	"64nVSTpZbdoyVil8PHTcq/c4iSP+Kkth+WA/sxSm2JD/tMfEf8rSNT+n1kfxMmZY" +
+	"y5UmMVMVJ8ZbwcyYSf/ThUxkMMoOz+R2qaP6HTarlv9RaiqxhI8PDkHT+8nW3ZOm" +
+	"t1jbpR/acHDtXbA6Tww1EzKi2KTySO7N2ZTCkq7jYh702RpxAodJwef/IaXmsXK/" +
+	"lMbLbeD/FpyuGQfEv6LSrGVZhmSxSSgoikttRbLU9uW0NrwxmKrwfsj9zZ07ekki" +
+	"Ej2irVcqtMxjTEjVXdf6P9p/KOcsyr/syrMkfUEhI+3yT4fG7atVVren4qxU6V/T" +
+	"taOFf5Mj/xYPqwPYq8bLlYHT7x9X86t2frOsP+5UnmbJUjANvKTCvZwkj4T2/Xbt" +
+	"J9f3uJLlxpGGJJwQ+9LUNxUfu/pLKj7vl9RwfBGH822fqJ8ukk8mkR2V7eCdNCih" +
+	"4rqR/FLZ4nb6xyNCn1IfeRyyRO0OnsT1CDQ+jZX2q4iaXcThcJadGG5K+NMY2w4X" +
+	"V16pdJLb4bb6ykpDJjVVSiyDx2/Ppatf7fHfqTzbxrUmrdbU+rGg1FD5mI/V8tSf" +
+	"V8o1D9E2nlH/Sfrsr/yHD/OP4SeoUU/V+sYwlSp/5mPQ/3D64aVkKRGlSewWP9VC" +
+	"GFgUGZCQwsROn6CqH9BPpvLYlK20kmjUqRVZgh9aaGzdo/4oxbVDFP9/xGOTxP+x" +
+	"g6H8uhV0ykMME8OXjcocLSqeqxYyhl2P6/5Hp5nNLf8IonRUqUNjY/DbO5llxWJF" +
+	"SKUSsy3EiYhPJ+cGHd98MzE64M+DAkD4YiKRisRkTDMpmR+sxk9icopWw4WnC1/0" +
+	"5aVMf79WMpaf9tje5Pm9MTeot7xUVJUoSR1ibG8TG+mE9pDBpFKsllWe3HKtI8x6" +
+	"SfEmFttpJpEsCWDSlS/NdtwJ44ls8MVRi1bmLU08xzI4bQf8lyf3o/X58cfuZXke" +
+	"jA9K/Wkv/oCpOX8AoptO3imxpWsWZVKaPlFYOn5ekY1bMWGWYopWjCWGKaLTIGkP" +
+	"wFSZp1BRTc+o1ds/D/mY0uThaKlVSilOHlj2XFcG5JxLZUjayIhAAACEhJTX703r" +
+	"bKxG0kYoRihhijZMYwxZWGEbWSBqVDlZMpZTZStskllbfWleql5taVJKGgnkxRrC" +
+	"VSqptInylG2SrIwx+wwoppFCiU2sGh/NQbbQhTFWSmMltqpy9NIxK+lX6Y+UYTIb" +
+	"ZDzMDN6G/c8HjdYsVEVWSZxbtU0dN3q1u3bFRfC4kqOpVSPLo0pZSIiQOFnZ0d4q" +
+	"sQkz4Qqa1DlekfEJApicdLA4a9OMxhyvFegkCmuM2yHU5NScI25iY4U24jHLltts" +
+	"7StNCk4frJzwu0Y6VjDDFk5RppNKqlRASOcpVq3MyVYiVt25mTCT+oTRDRPR2CKq" +
+	"KWrVqlUrlqaNSrjDopxKbp6upXldb1PU9s4hJGJA1VbLTiRJ7eok2sM+UHLbthMQ" +
+	"UFfLLbZVqqyVK+p1Equ3tpthzYl7KWLEMTEq4Ll3YoV5stLbid+m7alklmvcxMyY" +
+	"aGFGVGL1wYwx7R6xjFy7cn0pouDotHyZkzo/hptTZOkPyO1emWMxhjZLl04IdDYK" +
+	"mkh1kK4y2TMxcjHDmvtbZMWE+zDHXCnuD8yQLIjg4UlcKxjHr9gopzYxfuda1rEs" +
+	"eHCK6OCQ6xT4Pju3n5/X9kkiEj6cN+/vl+uaZ5gYN/g5JlAUHSDiUhoOAhwMFMVB" +
+	"c3DDHMN3DFulS0xrgWmW4W5cMuZhWta1rW21tbbRzrJVtBe+ulvYM/s8dPjcuY66" +
+	"qqqisgnSPat2gVwbVEysKVgXdk1QJsk8RJCBD2v8tenlrnM3edFeqa8Zu7mq1raU" +
+	"mEZP6xTGt6zMkdvq9uZwdp7PTR2nSvKidMcnTDZCbRQfLpsjVtrN222z1LI9jbbS" +
+	"Yde7dtk6DgycBMmW9OTcaTFMfB8NtuYiTvVscobNGKRo6Wb4zDniY3e2mSmsjJQJ" +
+	"4EQ2vqQkRVGM8qYh3v0q2rPteqmFz2k1KQNMUOrLk2hBsGYs7NRoFGZ5rKHrKVFW" +
+	"Up3oJ4GS+bM2pvedTh2+z59qcemFaIM+lnMKY/XLM2leOJtTiZEVfbeon1+vwZOB" +
+	"hQgviaCMyAjYhRqyLmywXa6sJtAjY0ekbBVdHErI5ucHJgQ4jsRIimS+VhHvLz2P" +
+	"o9PoKp4fLy9uDHljDyKyG7cVtjlTlwPJ2wD56Xk02ttipijbGTs6TRK6R26babRK" +
+	"3K25I5U6OTolR0fLt24J9HaeVeHM4svhpuNNlYp5eDRNLKaWrGQiqmZbs0Tlo8Bp" +
+	"tppto4ThGn0cT6OnAeX+R8K25e3KOzaUpVttKUnlUhZWFTasOmERzfpmb6O47lt3" +
+	"Whna6EmiB7nAKT0eA/sERTa2uhyCini85zJ/DpU/B/+m3fJ/wH9Y9AkiPcclOX2Y" +
+	"n/g2elK/4y2ikYKwUzMZcuJVFe362bbaGluwykCmE8ysyzLFrmryuvj1Xz/S9/AA" +
+	"AF15cn4TbNPgsRs7cOFV/dG3g0p+7T5dL60/tdkgpyzk/3v8imkP80cFiv6KUxX9" +
+	"LGz9Vfy9n0NI+HBMGjFPGRfU20/oK/wT+7+V6CiR4ktktkvJP6O5j9KtpUGP1T4k" +
+	"kf+7GZWMJ/d/NKP8Ksq/q7hRyh+q/vOT/iN1f/NGJt/f9yWf5H9z+wKWITjGZjP2" +
+	"GmInSyTkRo2qVStSThT8HxX8MximI2dIqo04dIbQvxbWO2MVGkVTxHSI0R/h0eev" +
+	"LpWSyT2p9GP8P1y2m2c1q8325VIvE485eDI9AlOHKGBw4JhDiv5HUmnSO00Q40Je" +
+	"rcSSy5GXLGVUp2n0eDpFE6T4Y/r+er5YqJai+n4MphhmLSwD8QKQoGSRJ/o+6YvW" +
+	"aSVmfLS2qpnMM9WmHTRzMJxy0qHVaVETOYZ1ScEwOJ9g0NPAmjGk0rStNtsbQ5MG" +
+	"2BivKYNI9Fvbiqv8b+qqdv6PL9GI+O0lco7fpI4cEi8XLlw2kn5YnpWFTwgTabky" +
+	"liH7Ax+fy+323r5BIEhez17ddXMxVVQFUOdlCkEiQJigNAR9MV9a+Xx16vk7dzgH" +
+	"lDoGcCQ74xnfnz3rzzvXO4dlaYNK5NOUkh4fqSweoaJidvSK2eXFtkPPEfCh9Gkm" +
+	"XRyk9PzmZVzMqjDGleXlHlJE5ZMZSrZt/Vu5MHK/2HZNP2ivmSPQ/6qw/Hu3mR+n" +
+	"CmQgJH8fUlH/NlVMZjKHCWNsfyX3+p/53h/1MZA1UFrEx/2ManCu/BiYs5NIwfyV" +
+	"9hsjSn/V9nhY5PhjI7Ullm1JVllLfJtZNrGVSVH0hBWtW0eniUKWCpQplb1tteSG" +
+	"W0qTK02llaKdJIwk+rhGI29xHeDU7WszdtKrDKsoRP1Geg1MyhiYmBApJgHZ+sFf" +
+	"yDkcXDK/ydg+VJSP5sSdLVsKtSHjkwmzZhbIuvbvTXnHN1BiMYylZk7k/LKCYDYH" +
+	"X13JBDq8YZURZWoixpkaIyJuN7+dTwztXv57+nThHDDHBkYhVKpPSK0UGMMYTbsK" +
+	"VqDzx4I8qh0+G90AAla9VKVWaW0s7IZmGGCsGJhhSnC6DSPacu07EkRI5jWcLUjw" +
+	"/d2+p5LbfLw/ft4tspaVjDMYWjCpQqLBUhDSjgT+k9T8hNA7KVTkkn2GnDBRs4gq" +
+	"HgJXCnB8vaJ5e0/l/WLbZbFLFUpVRJECIT7iSv69sHJkTAi1mJkzExpMsxUqaYaU" +
+	"miWTRpNtI5UcttEXFPVdQaiwV/wNOFTaFSaL45y+41lrMYcvR0CijhslcNI/0x5X" +
+	"Yo0kXy7cq/RMSNtOU8qn+U1IPp+mXMmZbhJ0PZ5BISOpVSySG3jR/pLeKmXKxwbv" +
+	"w08D+N6WzGTJkSeyhTax4Km0mkp+2qVI0rFU2n8SvhDnkx7T+ba3mQuaiT5PhZj/" +
+	"BPIPTKvh1If7V05H+Z/nVSKcn+SK/2dX9F/Uvj+tYktW6Y9SJs9U8H2+uGZNORKn" +
+	"w6+2/Cqtq2vpfTblsuXEmsGzllqypVLFYDCVIQ9J3NuEfwGnxGlfyMeYjQf6WRG+" +
+	"x+JPz9kl/QyP6sMY0xZf5xV/I/U5f+p6o7h0sRjp934eHA9K9T3ZcSNLGkno0CQk" +
+	"YVp8JT0vFuFfq7kInwp9TyTE+k95/GX6qj9zhqP1y390T8OTsAJxZv0pBjS09ndu" +
+	"/queeVeI9GunPNTJtIrybqni5552x0a9g4GMHRBAAhHYgg4OGOTGIx0md24x2cp1" +
+	"ws56tnBhyqW7W22GlI2+w+z4NJHpLENNvsSMmLVcLMVj9GSBNLTXNtfwxi4U4bKw" +
+	"MhtuWyY+2mWYp5ttKqpA6paj8vKRxEawvhY0NIfgfiH9z+yajt60n97P+eZ9rS0x" +
+	"W0+VV/0sP8sevxzxZkupTbH8sPl/D6tcrSqnhp05PlHCOok2cFqHB+kTvuQ+xWMY" +
+	"xjkg4SNqTWUt19K/fat9iuFW5XN8JyNMVvGVP7r82PqvjL7jtfwP8yYr+QqSfsJ/" +
+	"jvt2zClUVYzM/e1n9tRN7Zd5buwMVVKqRKoVR2YxVWrU0/hHBU0sekk5eWPDSfeZ" +
+	"dQOaqRT0r4rFtLHeZaEkiKs8vN+vcjw/CGRlxRVkq1SPDFexPt0FOvhPFuY6Tbab" +
+	"lve6MycQ4l0tzYO2m5eZhoWcZUOk7NTTLtwdLblt25Jy6YaTDpixoPYKKYtMSx4V" +
+	"/I+Nn+ZdTDBNJM+LfQOkttkfVOk7faSBw+y2ei5ZhaxgYP9nmnNi2FstI8cfri5j" +
+	"4bHPFumZbbbybHMpMg5WROgw+Q29S8lhiiGULhSjSdtjNpsyIlsyhYqxbcJrYw+o" +
+	"k8CH6HRjSvDSMVFQqqko0xiIclqrGrAw0hpi/ouV/i2foVy/oK1INsn/LKzEnZt0" +
+	"0/TfY/WWsZMkwqJFKpVKpSGE5kJD5cnT5T6BPRj2k+rIH3fSdvy2kEdD9W0T4tsh" +
+	"+40PbR+xRPpJN8azaR9OJJrfGcJHGHBw2OTGMmHPduPz+ryTH3/TGTMY0bTThPa/" +
+	"xbhjyxUTFkr8JJwYmivf1xmZJq2ySlSoJPBIfK/rASBSF+cM/nZk213bMmBX5laT" +
+	"Tg0VqrbakxFiRzCeLg1rQx4xf2Vq/pUjo01d0k/Vy7frMy3JIUqSKj8lG44ZP1xk" +
+	"y5bcTEsHL9YMZLGF+0n1bjZ+MHj6OXau8pg6GVof9Cv/Y9BbWvn632UMYJoMElJr" +
+	"W1JQhbfu5MliIQxxyxlFWYJJSo/lsdkj/9Utg244/f72xHsUqlRVMGPuJWipOBhj" +
+	"qEkxqGNgop68j+4/mhRTtlWMEwwuUKKdDCxGGldP8X8NFUz85NW01rD7NpifMq2W" +
+	"o7dpQsUxivU9S0/zYuHDin8gytmwSEj4WYqVwrKqFn2kfvYWyx06X1X93T+Vj5iv" +
+	"X+C0fH6nAMNqMKFVXg8nuEYKKk2Rtat7V7zXsSJCUSSRT1tPuvGtNOFnGGB1Pnt/" +
+	"MW1VDT4EQ56UUWLFFBZqjHB69cXANNLJbE0k2zdlNHR0OU056txtowmLOO1WSsa6" +
+	"mpA1B7TlxdF+0uvItZVay3b0whrGdccXinUpEidgaTHSdubVUqqtqqabViKw14Em" +
+	"JmDeVXXLyvKySljtLGMq1t/wTEMgWhujLDJRJgxkJlQy5UMlB40srBFeLlq7bpq9" +
+	"ptq0rbSxohSrCmSRMyzLLLMSFMMqVksswFVkqTKplkqwklGCsCyqplQsWLGMZZmT" +
+	"JwN3COMLWLVtt2fFUij5Hs/SR03sfZ5nglZWZjJSqn822RTBpyxvWHlVKjTbGVtS" +
+	"KqskrbRpKaRWKlUqSk4VwY4cYMNTGkW1bk5Mk2jbg0RUmojT0wxxKQVYhbbLZbFB" +
+	"oqok2slvxSlrqul/g7aXHwxix/68Toof7qkpOaD4wC2yq1EwXZiapV6/hsyJvBiy" +
+	"EnDHppUrseSqqll+rGDc5R6WrvWH+G9by3kboLdJKq9H7sVW0OfMc6vWl01qZLMZ" +
+	"GXXa6QEItcit7KxXTeedbF5N5WV5LJkt1ZLKLEMplYlj+iTA1EdNMJwtIUTETRhJ" +
+	"/Shi7iTFIxhiMSWYFgxhilFclagZLPw+zk+h+o0bMSmKxOFfTOrm2TbWXbWV6uG2" +
+	"zX+jEamLH9lX+6Yr/YLxH1w5c28qRqX++P6v9czJ/Bpq0wP7uyQ7eB+Vf7n/N/A4" +
+	"I+n6Oyqaf8ybStl8Wgvg5aMWKcsqRmLCpH+JHY7+o/ZUcf8bQ0syoa0yWdpVOGka" +
+	"ZNpjvIUVJ+ZH6qhX3fZFanSyHdkYpGWGxtjGKcNMNKwlSpDgp8KdD2cj9bMv9zY2" +
+	"4SHDkmkf2xkDCf6LKQfCpoFaOJ9BoH5TDi2/9rCRhPqSKlR9EcmpFLro0rH4U5fo" +
+	"dOMs3lzLMZaKYNommiU6RuIh0nD/kT7lH58Cz8XLMuKhGo2V06T/Rhf9p9apP5P0" +
+	"/xq2rWqv1erT/PLMqx/K0O2Dg/csyqf8VH92myX+Z8BRTxbZHaYmgsP/J9QmCR+7" +
+	"y/0+qv0fCnyiPJSHCaH4SEiYfT7Hsxa06QsXGmMqTClIxIpRFUn8jGqv7oxG3iH0" +
+	"WUiCZpN8b6/n1+1fkq7ffeV5XQXGJARn3MyZKRCosJhcTJSYUEP9MYaSlQxKRSo4" +
+	"T/usWhVI0Ps/HwzGMyRhR1q2WLastVljMZmYxjw3K6VX+qMduROGGFymqf4nekcJ" +
+	"jClisYLIPl8mk0rZwHtB+viyyk+VPL1HuRApl/cZMDw+MZfZt7Tx7LCpLZS/LK6S" +
+	"W2SkqS0scvTSTnLcGk28PRKVpMSUr4PizlmNNE8YGrZq/51JSfi7Ts2T+5Tuf5cL" +
+	"UaX6LUnQaR5PlE+ZyTiUqVaOZTHx9XDIqqOjpwldJmO7TbfS5VtUwninQ/6Jhf1N" +
+	"p/3sSnS7Y/q9Btj4/60tF5xmT9MwRXPy8PM4fiKUOh/FVVREYiiQhAhEa3qu3nv2" +
+	"d7+q9S8O8rb0Bs06WlE0arExG4ZViJk4YG2Gl1NmRsyoMpaZV7PclFEkhkSN7T1+" +
+	"jx5uV62pGsk5ajBRIogIzWpucxals3vLLZmGWmKYUqcpZRpGE2OC4rasjHDE4E3a" +
+	"VkxkzLZJSckySoFD8JNDSmOGxNtM2uJgwFUYSjFFUqlFGExq2zQorAowoxy2rlV/" +
+	"wdJPWk8RjHBV2lsFjhYX+gysyZkxh0f3RhVg/4UcJ6TuScH1VPy29yH5DloLCqpU" +
+	"qInySSwxRKrl+50K0qqo24TykjydiqiUngn5KlPjr2zMmZmZlXDMt/QmnwPDD7q8" +
+	"JHcLH4WjVHYxiwsKx8JjVH90Yz02rRwptHkY4fT6Ksmn8HZHweLk7kPRGKpyh/eq" +
+	"bPRt8Jw9H0f9riJN29Ik05PjeYzM7a+qenD4QbH4OfJwfZMB9ytJtyhXEiMJiVNH" +
+	"cUPwV4H6o7H3fBXSflFn+Sn3kdp9U/HhSqjtSP/YlJJT9D1KWFG1D7Gn2HR9iD60" +
+	"4ZhiiTUjaPujNmxMUhRQMUxVYpiKFSJkVJXJrRuOpD+nmZJ/LmR07HlWk3VZMyK/" +
+	"m/D6vP7Ztqy2BISPUCQkdu9bzXnqeuj9E79X9hjUSttuMzBuJcLcpmDmXFzLmW0a" +
+	"Nra22stGjRo3xd71/j7CrbuqNuCV+Pn7RiTiM9JJIEgAeHxJdEfM80MFtPnBMxsr" +
+	"AgcxJUHBQgNneHDhd46b0pvHTJccMlKYUIk+5RcOXp7Ryfl0Nnc0n5iTGzpiTkxo" +
+	"FCf/H09mHBodkFJS2Z2cs427TqZEjg2XKgms0uWP9EwnyRTKCH4BWvY2oHETm/gw" +
+	"zIiIJE4SQGl2Ck88xdoqynSIaAsnIZAHItqcqEkc5usa5371h9/ghm6wvaD++Ev8" +
+	"O9O1aUzFPwkL4FbXvIfOvp571rp7GmKUGlYdK/70n+m237Stjy2V0w2w6YfZFPh9" +
+	"Hg06PAx0ppwTTGGySp/LydK8/p8z7d2Zmabu+zmXHZJtVDh9axBEEQczHKc39VaV" +
+	"T4x8bLS/TE/iYRwjwdM0rY+rUH8HTgw/pHI4Jporpt5nzbKmLJH82WyJNK5mnJ4D" +
+	"eABtlKSyi0srSV+jHaGkaf0oL5Xqr49f2cO3KPHdVlOlxT2Lbotv5H7Pq5pfnuZz" +
+	"/dmMfvq7Hqnxosaf5U5j9bbH6/WKPbcO7bK+EPh5IfmR4cj2lOqW0RIh+qOFlpQ4" +
+	"QPJP14ba1ay0a5WMszhMV5f9J609T6PlI9nB/Z+ltJpZfELlyFYfUpiTUrTJy1Ra" +
+	"mlkyy1arGFKjH1SmRptiNFKlHlOxTypVNuJAVJ4ErlpVbYWdnGukOx25SUDvhmkJ" +
+	"SKvuGWZYZZExglQqFSfb9gSRHe26lLJVfZjBJ/oiPHr3rq/pJEQkegQkCw6m6pxf" +
+	"vmXePsQvn9xLQI6KSRQIAG3bEGfh7NUKcK53UPq8OHUkcacJyvTMdOk6aVZtbeXD" +
+	"JrDQwQRBjBWHXQ31cy5mBlRZ6IYlcEmEU04Y4cGEw43ZacPubU5VthDlicPuw5tq" +
+	"27YxgrGOOrbLbUDHk2YqK5Y+iuHLp5DT4+JNH2/Z8HtbEa9pifS5hRZbRbRJLmJk" +
+	"tJK4MBO+IfGu7xq/hYNWnTpGnT2zPJAB7pIdsgDnjwae+mHsZcy3KXSR8U8MMHx3" +
+	"67L6cwtaVLbW0oONWeD2UwAhlkYAd9PyGVl2b951gXi5PVcb8QkPLMTq0gBWTz4K" +
+	"b75X2bmGXKOkz4+PNebXzvhX0lvnW92FLBBb7Y5NtIVito4Viq+U3q3G5KxpPY05" +
+	"fL8uNtqqVHwkaYHg7TTw5Y28GPVWo6bO3c2dGOmk5G3CG38p48S6HjlsNF2N5UG3" +
+	"rhMMNpgtTb7iCOst5UUraeXaRgqdGFNmIlmjFNDbT2JT0+HDbb6fWUsvKq43XF85" +
+	"mSaaDRzytq8wj6ofRCj5SpbawpLGJ941qyZFjLKFSaYxiaJLLaQhJJAkhvLrtqoC" +
+	"ttttq21FiQaI9vwrDxA5e0qy21HycDgaRwSPs8Q8LbbbaEEqJAA+29r5V87e9va2" +
+	"19Eb4CSiIivrXz3xYwYxlsMdqma+mXMuMrKWCsMVUFYvUsRaVppRgxw1JXOMb3mL" +
+	"yozTBtdtNjDDApBMAoSHCRowphkwjDBucNtDaRKMMYKomhyNY0ck0nxv7WzTGIgK" +
+	"aWfqbVi/VMlGxYTH9BkkfLWrfruDbbbdSUqaY2JUcG9pYR+O0/p+5jB/JZUMKxWI" +
+	"qpUVIKVEVQxZMcum5tZISSZskAD4W+H59LNJklKlfGlrqabJQptdXKqVKsqlUqOA" +
+	"aRSiVP6PeBAlSQJCTLBC22236NPq6ejHcSd2rZE7YfVPKyfUT4b7fr8WyefXfb6N" +
+	"MyWzwG2mEp4bur6pan33d8BXGubpOl5ed4jcsltUaNEoRiM8GkA0MS2li5l+V2vw" +
+	"4XIm74fHps8HR/jS/q+HQ8pSv0K84J8+flIn1SJ6+UsU+C0c9Aop1HStKsYGMDKx" +
+	"VVbVX8PI4Q6YTdhxS2Nirbpbf9Rt6er8OQx00quK/pxvKLQgCMAPno3LmmAsuG5c" +
+	"3ARCCJ9nkfLTE07UWQ+xE4dfZtP3VPs7YjtMjphyP+UhGz0R9z8FYVLWVdq/Htqr" +
+	"8qLbe2t9wr6vumCB9f/1f4sdo/2GBgKKf9A+qrofyy5yaOmGMYh/zf7gpXixGz8L" +
+	"+5/xfK/0YL8tv7GR+gqTsvxJ9Ht9VkkLIxYsKqMPDNH2Sv8q0SrVcBPlIf3fwNJ/" +
+	"tUtJJygp7lJ+qPdeOJP8PnGm0/cbR/Cu1iq/DodIqyKlElfh9ROO50qsVPQ/KWck" +
+	"mmleZE/KwjD935YnpOIH6pJJkrJ2Ojg/KkmBVi22RUNKkxWowxU7iMnlaqlgNpJ8" +
+	"pj7iYnkVUWTvh03PCvJ5UwWAO+/U+8rwtQ/m/pYcu7dSLkkqlUIKb4AdxPxWQX6d" +
+	"K8cR/srlNn5QkJHSlU6YlWNKsqyjRa1ZMrLLMYBj6NRJ0TlhNqV6ntwbHC0tcGIM" +
+	"SikWx6q/J86IAjICaXDPuClJRcO8kmItQriaGCUlFzXDGSLiFQTqmfrNOzl03Ole" +
+	"IMWrYKKbCrtOGYDoM00bf+1W6hV/xyoRH9H1kIxEKqEqwhOh0fbf3XzNt1ZIaQ/Z" +
+	"Tcp8CVPCpx/rV4xb9LJRO2FfAhRPU75RFAhEnDwrLCvgVkHFpWj6sNJo0rweXtOp" +
+	"yT+x5Tl0wTwqLD3pVXSJ+5+RtPl5TqEhVD+w7piTk2lwGKf1bfq5W39Vr75V8q/9" +
+	"/wWTBGo2g0WqS2itFWqKtY1WosWrRVYrUaxWiqxasa220FtqxFVbQaNUaotGxFsb" +
+	"axtbSaLbG2tYrRrVGoitRVEa2iitFFbRqi2xWxVtitrFaqNrRbGrVFWsVtrFqoBZ" +
+	"kqzAMyJmCrMpSsxarGraooi2o1WxaqxYkirFkFgSQP+X9/8v5ZP6G0/tc4bk13k3" +
+	"JrvDkTm8Quc3Qw/xo2mMqVokQel047gDu6KK9vXSItvS8kwSVIXbC5SCkWVJiFZg" +
+	"hUtoVKxalLbdMKjlWErKlStSeOmTUeNgu7o2dzriub3bxvGBNRCbu64Y4kT37cPB" +
+	"IVhFJFkUhs5l65OBc/xyiJn9pvMTp04GA55Yats2p3krH/20yE1IIqJ4GE72HU7u" +
+	"YYM8Ubq87w0emUBOg4KzHejc5vnlBVjwWj2JDp78uxUmIZjGSSXv2+C+Vk2buCu5" +
+	"waLzxxtCqTeYuYkzGRiwWkxWMbuiWxbDiVZW3Hey4sc9aW7DLDfXXvBO8UcMOrE6" +
+	"ZHKIJJkSMuZM51ZhDeUpVpMillJZpvURzSaUu8TxmWyQ4sN1HLGJuVCyo1rGYzbr" +
+	"G6nipyrXO7Z7vS43pcWFeb5bU4saY8yVux4640jFLmIWjVTaVtUu6xHFmprC7jGK" +
+	"0oY3kblGmTI1k3ubEQo4klMaSc87iGrnc67p0dLLSaMM8WbgykoqxHuhUIiSVgcN" +
+	"s4ReusZ2W9pwcOl7l6OFfAh11ZNRZnWh576MW2q1bFKxVnLe+3xhp5sO/llybe2u" +
+	"6vZwQiJ63JuaKKNCGBLFFoua715rvMY1dJZyLBbrOZ5XV5qeIKQWC7JDCltJRnjc" +
+	"MWVKILJ3QpiLVSjwUMweGw6NEzJrF1i1Fr4tLGZjFiWmbSyagjBTJHzlDjD4ecQ6" +
+	"82snBkEBIfIt4B0kgWTyUekmpzCiQ5yh1wM4G8SeOG+NNwKdjDrIdZ3nnxc5azJS" +
+	"gWIWMigBFTrbdrcC3d1FulyStyYtcJGJReZlFmTVNTS4yPGPG6m4mU4UpUnHfhrr" +
+	"wWZWNdRvxxpo63XA16Gk8d9EE0Xhw0MmKiDFJNWV25mGqnfPHiSZDmy0tLVotC9m" +
+	"E3s7B8efHiO2NasFiqCyLUrMVTLjOkidBUijvl11NMuFdid4Pnq556pj0CZeWiKi" +
+	"RE4EFhe7nIB0MWSoVFVEKlEgdTKChKRIxmMBSnnMiG9dA90RI90p4oXnQyoVOzwO" +
+	"XmFFm7kU1EJfOeLl7pwCnXR2AkONIgVXEixG8HO3zk2uUXZ4KDRPGOMQcFigu6MB" +
+	"AynwUr5tMSp4Zm3S97lkYwrKbmYdS7N0thbaW8cMcuPGm2iNlkxeVSsrDdwwNvjm" +
+	"OMsQWV0bYCzEe/EuduWNOYe4t4neTnLWQ7yaysyt7Nq5jW3w84tro7rFbxrm3ROc" +
+	"yItTKia31oMVVVzMmKibuKkZYOb3Z3UnBYN1JxUtiasqwcnVw0qRd45sTvWJOrIZ" +
+	"cp3W8pbyud6rMm8TWW/KOlHvrjW2vNJMEmW6wk8+aSBDqHZe3wLGK4+WYxQYao+a" +
+	"FMLu3Zia4DJiYsHLW8vWVSaquNQVVUQ7dSGGWs7cgmMXdseVDzwzwgEvmRsCB5fB" +
+	"QVQXq0Zj5wJrB6UFaTgUTjAXmHe6AjIdsFIpFIYZ5zPJpMFN97axjrOebjescSIe" +
+	"OlxIjJYuYzMCWWMVihKxiTtW+9a1edTMrhldTnO8F0E1nhOr4yVONeDjTro3vk4e" +
+	"VFXbfM/6MUFZJlNZZ+RMiADvEl+AAvwQB3/wP//fyr////pgQg94DwHe94+e89AU" +
+	"H2NBDuwvr6eX3b72JJyiefd58+Vd8GQIqkiC6wJSbBm5uQAAAKq7u5JKoSaaqQKQ" +
+	"l21VBRUlVJEKkqkqklKlVSiCooVFg+BcYAA+7T5I+gBL4hzdzp5AMgOtGq4ADa13" +
+	"bYpbuB97AXvu0OR1329gffKPus6EiQIGhBMJE8hNE02U9Q0NDQGhp+qYgkgCIklT" +
+	"0IaaZADQAAAAAAaeiIiUn6JqJgaI2hNGAA0Bk9QAmgk9VJJEyZJ6npNlNNBoZoTC" +
+	"NDaTRkD1BiBEiAiKRKekw0mIBpo0aMTQZMjI00YIkiARpomQhkE1EfqnqNA02oAA" +
+	"Bo53OJuRwkNrkuMUJOhNQiCKMocWFChEEQrUGVTGgg0sMW2bqgkJBgahUxttdb03" +
+	"1poJEQAhSSeqS4RwucrgpgGDRopQUVIkNExkDQSGATIZGCmTCKIkUjZJZESZSaMx" +
+	"BmaRQQFlNGJKRIQihnBz6Pqb1dXa7ucrjgmcuCGgbYNpgK8AKEFIr8o4gKQFwMGj" +
+	"vveHmstx7CuEmmgYnRQhB3iu/mzlcrWdLQASIoDpmY0D1WpCxNppg6VoTStS8btY" +
+	"ssBpPUaC7k8vu+aXzwycRqJj4XNyCaEL8W6PxaWpQ2NtCG2kMTE6TpoDCHUaLpoa" +
+	"W1Dm0upHlZaDritXaTgmhQQNtsojjagMpMIthjtQ0xZUttPCv+T0I+nD/mkZQ8ZD" +
+	"zjB4ZdHI+/AJQaEvDFvWEt9eecKhyJv73XRVYff5934ryHcPuxRvk/OTX8AQBAXI" +
+	"YIooDEBEg2yTSZqtrWliJNFtWstQg22mzaljNU2WpmzNipNtVbdVtq9Gq1bKqplA" +
+	"FijAQQWAEEEFi/vVAFgAq0IILEWRBPH+qAgv4VAEvYexHwNTvPzKQKnq9pQt7ith" +
+	"SFQE3KoT92BcQS5rF1INoi0BQOEBIieUUBAgVIw0feYQlJIxilA5IyloT2iIDEdI" +
+	"qoG946hlU0gdFhujgx6GOFTZJSSpDwQuVTcllZOqH4ZyZC0BlmkC4cCwsYRI2uGk" +
+	"ouXauJiysgW2UY5iFJOlmzOCGH4iZGZYXJxDLdJ5I+okgLjdFcGyxGcTuXzC2QNL" +
+	"MmgZDlHJwpxaWwzw0jjTdXZYSK7Qr5tMVE1KLGpqexpkXBFICAcNsKQUZzMFIgVm" +
+	"knN2YKiGSuBbRzatIQgm+KaQZAS8uDHTnWrudlkM5iRrvStxKFwKKVWkrxS0Gc5b" +
+	"46jB4beDQDNZhiAYwuRpE1mlIxJctXj6hyy5cxgiVA40kzeEpxsaUJjkvd5gjFhh" +
+	"XMuSAhJw0YIxgxczl8mAJ0klHCWrkkchWY7a9j4Nu7SQ0sThJQxDvI40wEU4mYE8" +
+	"5vWPNKDdBTZq8WAka53apCRSSNpCqgUBIEqkKIRCCLDdFlqlxAohLqDOd5oy51ju" +
+	"LwUEYBLpqiqzTi6CEFgheJY6jhnYUa1qiwwzdN4qAkZJTTMxtG2YbaURoLQYUs8E" +
+	"LNMt81O4S4MhIrqC8Y2RJqiBikskgX1Ls0fwJ4OCaGBlINkgmKE6hXECwCkyUOuw" +
+	"dQqIBJJNGXYw2m6AgaYHhuJJJCxy4jkmrBKJZbYWNXa3ElQyVBKsZAmKeWFLmqL/" +
+	"aqWV6VDzrw/jTfYq6/bw8pT5+4NHZ5DpJIDo3mpeN6SJGMka7izeeoko43C2Epfp" +
+	"g4TpoXY3puxOTFNpHLlJkTMJ/cig8exbJ4wXM1wqI/cnSPX4zRN3hNeGDNBlDPCc" +
+	"RjKdSlEXMcLYVo5zrESzdhn5oQgF7Vy7d/xXre3+0a929Re2659oOIpGmnWprpit" +
+	"uWOpOh/bvzdU3UXeNVH5d/XiT9umGfzpTP5/9FU8nQ2l+WGPykDtzW8+x9V9eEZL" +
+	"xXZrntkuw70ekWyrvMhHrucZm9KfynpN9pZTE+0MTHTPffeZ6Ne/Z488WceGj41e" +
+	"xPJ4/IOaZmtZu7us13BA3KgkZGgZhXkEnmKKSCdMrtunVFC2hCzVzNmb4pa9MrfR" +
+	"5L368R+A5cTbzcuFIBItqqa9ZJWrv440HQdtONRRNMqQLRvCoXjJsHsNjp3oqjTU" +
+	"nuUk+tSSqY06SBeONJjOPZlitBWP2Y/a4myrWhja8Y48ITl3w70cPAUvOLu3N73x" +
+	"oNCWxRXKJMZBOcsIiYNsbb6IqgA1MYWCyzFLX46tyDIsrZmBdV11KBpmbcG2jSmW" +
+	"klZqbJwQmXHcfS+kqBbvzhoFYwQVevOaUWDtMkiQ4OL3wfiGhdLDJF2oWKWCGRKi" +
+	"hQlR9vBWB8QPr7h+/XlnwgBkZ6IHoruquvYHPb3d2c9Vu1qFs4DoTfPOZy5eaTfG" +
+	"EbeW2TVkZWcjbLyy5fXm3YKb4ufb/wb81JfR8qaTCaWBkN5OAgOisFhTR2+eXXkc" +
+	"3pGtx5da9R7O60uzr4vD1ctQeFni4kxCBF61C2yR4amYWm6emxGhMsrBSNygglLJ" +
+	"ju41nhlzS1oTvHIJ3iKAtp6aslyLp2Xz4u2mDjOOFZxL3c45xPx8u1djCMsttzHL" +
+	"vlwW7OA48Dxvhzz0vTvl3lSnfgXC1bTvQOQPN9u0GMqUZDiUu+0SqNTncw4JrOJd" +
+	"C5ae2h229JhHJcsamPYtGY2nqSYKK7ZkCWcOaeo6wnA5uE6UmOicOKSlx01thtO2" +
+	"U5RWOvTw6+Fysmd8Kd83F6zpjTvnstmbnM78jhR6FmzlfenLa9NuMaGgsxrWUpGv" +
+	"xczOq5bXKtNQPDHEHk5QkHLA7Ei3HDC6vuGTk25mxRUpKKkrlGpasCNz44/k+3tD" +
+	"wDe5wjgdDHrPy8gsg2W5zWGfiMkjEJmgQcnm7BcPMOgmPy6pIvZOyXeDh5m5rpxh" +
+	"u2O72A7GexroWfc4Pg/Hs7+FoQ8r9jIQtaxoXODg+TR8z0PRzeAOoeeRuMi7hdOS" +
+	"81h4GqNyguIRmNhQKnFMJWaZLQzV+urXgFRWKiY8ZIxJo6GynpoUkgAnNj57hPkk" +
+	"CiIEgKoYhUZF/EFX75QYsoLiXAfylQHsFzFbiMlVTCoUCVRu0SOlVOuaqN2WvP1c" +
+	"77nObXJxriiMINSQogBTFkqqmEoC2VXvQXneIkUdJiMdJihT4fO2rWLdy1y9kXJW" +
+	"wjNZBRy2pfGS/8Lwdy9Cmq8fh9iYjz/X4mvTlzXpX65f5J38LH6DNGfi2efIIvIZ" +
+	"10n5NE1kN59vlWXnOfKiq7ER8fWpiWWAkhS+t+LrfbL2atTnX7FlB6UvlXavrdWX" +
+	"HX4WKTvtWbyZlXdbue7pYypbJ5UnERU0llbaJ5ZvPfC98s8bTLO12ZXNItLa866P" +
+	"2611pp3tR1vrwgjnvvzhWTmUw9oSQv1dZnBnZnRGfK8QzR5ObplZCCc5ujfT9R6v" +
+	"JL1s8iD5lDfnIokmLJsX6RI1PafLCcKs/Tg4AkOMBDBIQit/raxnAKMUBAZBr9yq" +
+	"s1/QXIbVpWgIAgmEILgYvh0yWOUmv3jAUfKBfkdBqK0fOeYVyHCSZHQ6VMFk2HIr" +
+	"sD0RNdD7WUaPgRyIZcjoUkiB+YRfCWIeIcpVQPm6Q1BfgQaJofhQUEMgZOGDeJA9" +
+	"IPcCCRV4AUgAYPdw6IdQASI4FnXKQHmcg2w6ALxIMpE3ZaAxxeCoTJ0HTJEbxQOz" +
+	"vOl4O5xZ05zeiMkPQD3Jg7lQsvJS7KCkLTfpQmQlEPQs76EiGVGr9s8U7Q7yKUh6" +
+	"XQJAgcEPOW6rmfKxk0kYB6NnWeroUq8BmBHowHKGqH4gESifAlozD0+eQ0j4kT02" +
+	"LZ4WaPDW2w+IYtHZeImTcCWCRQLWBxyHfijRhjIpsF6jmAN08BB4SheIvMCQv3O9" +
+	"IBxhPz0SkvgHt3FCKbZGAMBDgJArIhI9BSIY8gc5jHmj+E+p9S/UAPryP36WOYnx" +
+	"34Ii7m5qkMm9mPRFNHfnTkYoj0GQr4OOeHrNeCzAYlhhc5B9Dx8dhsYr6Q8qgkWn" +
+	"ZzILYoTDz4BIKReoEWCYEF+GtaVpIuJ9O+zUiaxtJE68pepgbqZg0bMuPgcmlPnY" +
+	"g6RPUYjuCge0Uj8+CFpsWlfLghvvAgHOAUAaHOuBCwTEJ1iNdj0An37bTZlzLF7r" +
+	"i8nzHeJWS8Y6zJjrLCcqH4JHhRMidIZSkw8EIub4C6LDowDzJO0NYq0kILgV0Xug" +
+	"kCCZveXnig8iigRgdCLAPCpCoaA8AMX+M94icjIEiHwoKCEQhEX3HtmPnzHMo4T8" +
+	"NPcs2WZJYUlDwPX7E5AKIDuKSJ5wxZlKKsPwLwU8KDrAPQyZ+Jla9ISK/IHBC8hL" +
+	"AJi8KMiPQXfpqpK+sINQSQJGgioXVwYxvvIhV0sJEIsZpIely4rWA1B7CQPyZJLQ" +
+	"OahcYOxhvMPiDui49WezMfDbrdT686aJ+EQ2kJErap94yg2ISh+eqqB0QQPpBERM" +
+	"BBR+wkAAH2CA+KJEV+wAFcxBkBfIpkCZ2gULsgCIciHoB1hJQ9gIEguUgoVulKgg" +
+	"ntUcGAJr0oJHR6UMgdYB4JHEEfADtXgvEGyLL8+ama2oQMkPuYKfH8tziwAEEz7M" +
+	"qXYXsAoQHsjwQYik4/RunvQcfeEFs6nFYUjPo+WPguYCD9BY7j7j/PYGCWLpEvWu" +
+	"7/IZokD080Zk5wSD1AVqPRbsHEFBSr0sXtjlDoV5UI6IgNFeEvHffv4n0LiGvfQ5" +
+	"KFaH4Gqpz0Mxh9UDG/SNxy6H6DRQBcV+sBle8GiGx3QAXgqTMlrqSTAkr2SSQEFV" +
+	"9QEYOxHymNgdkGXw8Y+fRsHrgXw0GR09kMpCq5MlDiZDzgGOLxJuHDgRqQOet5Kp" +
+	"ezggkS1jSF0MO0JZ2yqQKSLF7UIgkEZK5OM/HYXOHJeOW9vBr8HHbkuWPxox6fms" +
+	"GumVzMqBnqecSQsuBDogwNRVQM9eBnKY0b2gZRHesEG2rOE4hkmdWB6V5y1KgqA1" +
+	"BGhikPMUQmrL7akye+mkvllmGuOkpMekkiTCSRACmrhLIlulAF9N5rthlpQ/XQkp" +
+	"01zssYOxeeIYRSTWbG2KBe2SOKBXQ5DU55aOtIvBbCk+zYig+CBkc6wH3bQOiaPv" +
+	"iscLEZjILNSSmX9OdgQXgna+HtgT0K4DwhmvgWOYSV0NSQuh8OHmg/ExtAoX4Pob" +
+	"q+dVHoXJ7hVNiGlVA2bGEGEH1bRIRBDhCQDs2oQtWIbppQHsVDJEQ2qoEALIiIJh" +
+	"iA5Ibr489zs18KLdIk2wVcpFRBx6+tiaCCj5EMxEzMCxQyTxJ8gAo5ZcS4gmZqKG" +
+	"0IlJiAbs+AEAgERPIieEQN50HzB2KnFiLFTJR7Q0qNQ4QXyCtKqBvJY82LSiEDtD" +
+	"SMDyDTVAlMx1KR0pMIRUiJ7YF7xSGDGU8MEIMgEjhWgojVGuXwHA5gtwUckHgZqo" +
+	"ezI2FDLsfUAQ3ZjoWaTPcjarhqjpVVrhZIQ6SsgnCohVS0itMJYhS0GK7o0K+ky5" +
+	"Y7gH3tCGO3xVQLLkMHlUMsfgQTLECRQxOLscliplNO4omhGOIJICZNgKF+kPDnyh" +
+	"3ErwNoatDOLWiFE0bhwyOBJEYDfGHjaG8xFtMBoWYA6HNgFycuim5Q7p2qoGrMrZ" +
+	"iV9I6DYoCVwCNjaBmh9VIACEQL8wi1kyAWKD09rwynBSL7BDbiUwABZHykpFUzkw" +
+	"tIaZSwCn04GkNoQOlasfSOXAYa64AHCJyMVG81eg8guTY5JtM+Empxh2Tu34PTsv" +
+	"KYzszJQ7oZY4pJ7Ci6JrOjEozq8F0gbgliwihrt8mJA2tda3aqkAfanxBmq2ZHU5" +
+	"0MvBycGZje43sNn5CYiGYNwJBIRNj/EqmR34YYffKj41OKr74Ihj1OnAC82B5rJS" +
+	"xuPCk5SnOICrQbAWFCMDZEMllsNkyUZkhMzrWJAiQm+4YC0K62MK0mlrmIc8DWIE" +
+	"FjI4sXzhL8vpkYEZwSigrGArDcBGj0gGFAr4FqGFQ1SOjTvH0TulJ1XWHAIDBQFU" +
+	"2BL7SBXa+99dSAvxCgIPnOIVhPMmTqqgYRFDUUEsUuxDfjmwMpaAek0+O9i+KyRp" +
+	"AG8DGE3qEdlsT9H5BPmUugch5YLMiAwTAkdnj7Y3zvRe4V3q41uohGNQNXT1Czcw" +
+	"ZOHoCYis+EOsTzziYOV5ZAwqoHrl2ATKFHnpRssDzmLdSlJDg7CCwocglqhuE+Eo" +
+	"jpsHOFogASPtXBwKZ802h3flM1s1tZA8sM4cPDnAT6uS6umbSt9nww6rDoI6wdYP" +
+	"ABwCkD4MpyWUDjtRIBzdU79HbBiX3vcZZGYTeQOlZsLH/hj78oFxFCAR3XQLAaGA" +
+	"dDiPltBD5eyxp0sa6DUCQ9yB3omnTqYzNOQ7dGkZocqlwqH9pIRCGyUGWBqQyCxy" +
+	"ehq7n/X63fbu3lvZivHbt2xc3MNMke2l6Uc4OiBRsMViTMcmSUZzTiouB0cMzMDc" +
+	"MhAn5DyXqlkdoH6TOX/ia/RnX2fHg6KQTF18xSwHCgLERnIs7MqnDBCuu5uA3wgA" +
+	"RixX8J05hR8PDApxlQIJmGtpRVjPTQ4WhDIBRyoZ5o1kdEjBho15A6uhLHeFCwXL" +
+	"+9soCWWtfZsFJSQSLh/i4cADpq1VAz4GFTiJjhUbKosgl7B751ekmAW8qEBkjrpJ" +
+	"Tsj2D0AkIBD0X4qoEMX0AA0zQzao5o5TTzd5LNDKrnPfRfO1p44OgI4xIzjnvqR2" +
+	"Kz5Gwg+DJUL4dAjsyge+pYSePvEmKovgUXXilLjBfO4fT3oTYGwHVC0J2gKaO2qo" +
+	"GfZ3ymu7AqTWofKKHc998pr01xD2hKFgCFCO1eIWDjYeGgvGgWPaFTjzJlNzf2GX" +
+	"XyGuBywpbCI9aM6UO+tOtaQSqpWu2BesY5kXgwTFHTUPCg+y8oeXVwQ7yjsYrMak" +
+	"XS4XXDAJlUBAhUGk7oKAYdKTLFPcGom1CBxTjSRRsoYbfcOs9iE2BKVx8w4aN9z7" +
+	"7xds1BTpEnKyEY4TEIk3XeTS9hcaRANIX4k22qCDj84dwRJjo5YkxitJJAO9xXTk" +
+	"OFA/MS7JYZDxNviHhoYrl0bDxFvhTQwSQimhAnQFiYoaaHrMgkYrCOGBtDa5Bmne" +
+	"OFKwdG8DmOpCyvhqGYNRcB69KAlJSFA5hCUHKDE4GFcRwyRmEbfPPpveJJIDaQgw" +
+	"rWJ/P78yCMO9svE7GZpvnPSWaCtoEgL2jLabbxBVKIsbSY3YtJJ+NjNh8b8AilDw" +
+	"UPusGoZAu82EYImSRSk5GnwVIKWpSvFeBQnOAdAMuTV9DgEQgQgvrro7JHSHZZfM" +
+	"JCKmTtQFOCceAYcT265PCAg2SE+XhMkKlPgHB9+HTOoLI8s4BJuk9F7wqDCjRw6y" +
+	"D8yVeukRZ7qrFZYrAMMmhmgFDKEdZztkqFY4HuEkfuhz9pTsXzFtqqB5Tv5gsZ8h" +
+	"mh8x8wAfZSHNyDX0vZDTySL94fOjqfD0KHsVflvrWX5ow8Q0QhFVMbcpmX80Ezgf" +
+	"HYjMuA8wLy42E7Sz3rziuCIB2DsghxkkRy0Bzp6FVAA8MKcFvSjqknlxdHAT0wDn" +
+	"07kBQcd9oLK7tKmnZYnZZrh6DrhvciJ0ss6vdzXdwMQKJMWT7tXSHPByoD9hWNqM" +
+	"OwE85ypXmQLQwbXSkJWY6qxCwo6HFcFLCAk6bCVHFyYQc5H6Ezm+mNHD03wkk6j7" +
+	"m480R07W+QkhCKSnJVvGUvBBlRzDZDeeaNvGwHd0PT2wTy2HnkWtuMhkklgK66LZ" +
+	"BC6hKMJnOxOpo4YaB5V7rgiiWQXGCiJrYk4Y59qslhcA8/XJNJQLb+5tUzHJCBgj" +
+	"Qx3GrzzHn6xmZ9A0PtV9dbezpCHExoEDwlrH8dllA4YEY1mhsA0dIPPsj4Mi73vz" +
+	"nrsvJLs5YqABDfroHBg+ShQ0IgOs44NI4F8CIIsVXHQ6z3KS4MOhdxigYOImz2UG" +
+	"gJAuBhpsgLrldXnhNQ4jLCUyTxyhrIrwuyYrqo6MJzQ2Wl3AdDzKOb3Cydryz5Do" +
+	"pHBHMKBNdAOAdXJhYMgMb2s9Fp70MSClw9KpTbdzhHAuMGAtobHQJ2SURvgbbhyt" +
+	"BecsuXl+2jKigzt7goBTjmpC8RowanZdxJOhWjwhwrm99FSiJ2OgLLnm8pnjT1Fc" +
+	"CXCc0JaZijcmjpDACeVTrZneXxGRA+184I985kcHQIQIEFMgWfO635rg0SZSO/at" +
+	"HtcUKa3TZ8OJoImYsgRoKAhiZKIBUsG7yTOFlDFncMU9EG4CMLUKMxbiCaMDYdhs" +
+	"JSKdyLFJCQmviCCLgGuUz81ptojXx2oe4d2iHnAkVSdhzcfH2K2UnIQ9u0F30MHB" +
+	"OBY0UHMYYjgCQTAWMbwXTZQXaOgnfjckJ+BO475Zyfo8/R0NlEMBq8c94sZJiNrn" +
+	"yJ8OoMIDQPjt9uJK8Rk5aFDYbJfWSynwRhgIbQoB0+IsZPFGy4yADzZLYokaBywD" +
+	"CRmTeH5tmhDzPmA2rD32gaqneqHMNqA3FgsMePDM9KB69ebN4HOAhc26eoGFI1QJ" +
+	"m898wsO5qZxBxcWUgvtw5Q8AMEOOJJ8HEEk6B45ZyIoFaB5KW8FLb/M4KYSZIP/T" +
+	"y/DoMk5Ami3wPAH8EyWhTaUsFlQ+g6AEFdgHlJWNLpOCvdk3q+hWdqbTJWRS1dey" +
+	"wOAQwQUmsxpFozUQbFTRcPzhmHw0BxsEHFHdI2kUHjDkRPSGAp3SUo8BEdPPPTw4" +
+	"44KbQ4SZsIKdYe3WCo1EtM7zKTu1VAoZ7hPFDfU88SlCY2aHVSnVAOBA5wzuGlcH" +
+	"Rs8STcvGCu0xIzUFjkwcvlheRAzgRbJkzf/N0YjQwJYrJ16VzC1gueMTW4Rt5rYT" +
+	"IRNwYQYtHOtSD6ShBHOQzP37jm+TT/gvnq0DgyDuezyZv7FGKF8j4kpFLwakHPsy" +
+	"LSDphCyxQLl7xgnr+Pl8wbTsF8dx04kwB75wFRLdNRIBmhw2pH3UCbB9EgE9z5eI" +
+	"BPN3vYxzTZ4nEgVR4qoGQtM+BuGwlgV1WoHG4EaoNASMhGBgXYFRVYIXlASg6LSg" +
+	"GqeHmiyAsDilBBOqQsS4Og5rap1miKqAdUA6AdYTWmgTRQWeULDLBzlSEcEEDJbB" +
+	"4nTaBTC2glnEXi2haNhLoJcdgCNAkhcqbCc44gFrBrre1RE7eydRrtb9wdNITgOo" +
+	"j4QWulZiLl9z7V6DbnFmgcimAjOFhQs7UI75C551aKdXmUEHKSvEOCldH1YzE3wo" +
+	"E42BxwHl9Xk7YSa0g1vV9CriIWOztgqD6DgKN3AvOkS3ODdnTdtll+abk1SRIIGv" +
+	"fALBUOBR7ZFBZ4BUpBnSQ4hFHFEZ473Y3P+zY7O60Rs1LaWqHHIcwa8txlB4jJJE" +
+	"w5YZFHWAZUEtKyoIGdMwDYlA+A9mFgSZbOw4M6OOSmPkMl1OYzvpRASmvvXmUjTp" +
+	"8joGG1lR1cQpEEugzJBUyZnlygzInkeR9IZ+wHyATZQgPmd1ZmIUecB8pAzd6P0t" +
+	"AUK45zvDzCusNxdKPDohseJeeAI6ZvadwEcFQCRCgsXNcDfG6wqIm732cGQgwkIA" +
+	"SKEgydIjIZQ4a2thurU6wysrTQQglytZnEFtKoQOjdqfOmiDah274ym7EDxm9s9L" +
+	"CegGgMopkIt4LQ1Xtb9yBS7B2LUpK7hUpgHQVCXmwmbMOQqGHhGVvfpgEjVDoew6" +
+	"qNbwaB5vajnexW8pSBC73poOsSDMENqjGDoVUvvCS9M4jdfRrEmuQYwM5KDSHMK3" +
+	"B64lqG9DhQ0JoNQHlDlAPccRKnfODi2TDOoYNSZAcBzrUAVglyHGRUI0bMziEWOU" +
+	"JYnAOUMt6Rku3X2Za5l+nJIHiJXNq4xzccGdzaqu4qJJiDRBAN2TBKurol+bv9SB" +
+	"CSAX8+8Hl/r7sZnxy9PYe6Z7cvs98YtZ/SwPrgMD9OXynBh/XzxwXwdWFeXp/iVD" +
+	"kMgNriWpJDP1n5azCg6/xxxEvwpxkfhIP9s+2nQ/fn4vF9+jJ+ngfdWL4CPb5czf" +
+	"UQwvVtZEuz7Om9iWrwP/ePX0KAP0+V9inRoSgybccCP6dPd+K+f24YnQ9YpYUGst" +
+	"TKKFMYQdT2HL0fr+fbVW3qvv1NLVbRWSUrVJUxgSVjWktRaoqKNrFWmUUVMjUUmp" +
+	"li0zKazDabQ0YKDYxZMGg1BpRpYUwpQCMhoC8nsJe4+Dy3Xr8S8ifkOz/vaP7ETx" +
+	"FiYoqdkOeLbBtH+bHadmz2QGsccbGX7OU2D+LhZDxGPjMsOyV+DZO9PSeDPkEcZO" +
+	"SS8UzBJ+ecnUZhlZ9ZyM/ad22YYrjBcAz/3V2B8/JiuT7ED9kw+rGGSGmqTbJiMm" +
+	"LSysmTaS0aks2bSzWlZtg1EpSSYlNkqItCalNFstNttqaprSmpS0pqU1LNFgKpZV" +
+	"srWWrM0lJM1bEW0qbEmiLVtRGZUbSprWbNaLUqaks021KtbS2RlllbMsywtspLGj" +
+	"SaVEzMYk2NmzWptlrJWmSoRZSsptlZZLRGTaNKm2LJmmyUmSWRk0WpqlUZJJiWlp" +
+	"tkjGjUy01TaUkrKzSlLTMzAbNg2KlpJMl63e7/d+ENF1fgGLHuf56NGdqOvg7hSN" +
+	"iHHED5NKzQnm2yaAQJTIxieFJM3ij3X3qh5AHBhk2riuNRvBd1dJNK/o55W5e1NX" +
+	"ks/nngBUDz7INtUfFdK0JrgNgbjAdgkJGRczQCngL6Zh4BT2UW6xEWOCC4FzQuaj" +
+	"OxoBErUsV1z6K8cAICwJGRj6fB5iCC6h8QhiZB9qLr5NFyCenPzIPnc0WwotMInx" +
+	"4sAoHfMU5HgU6hhRBkppj/FgHNLt0ubr4APQXPI06DXqSSyDZid8zuPuLwXKN4cj" +
+	"jq/w8zETQQQXn+w0DiEJEiKh7fzQ5LMfgQXmXrdtA+sBzTIigGxVCwsOYhmJycnC" +
+	"CGplhE8/sdAhQXcsIRJFJISEJE8flHQO6cgR0ZCoE/TcCd+BBP7orIml5zlZgw9K" +
+	"QKKpGkiwgESxpnXK9pYwUAa89ij5sPoUYZjQ0lyAcxQc/xtRzIOJISJHL7Ny0JDw" +
+	"BwZa4MDUFR8D5CCCwzTyVsZejnQapAVGYICC5dDXtXOsmZXMO7mFWN7P56mEGIAc" +
+	"JHHBsharUAUcAp9UrviBIAxJ08i+RBO3Ah2QAgiK4kThwo8sDCf0aftxqENQKMTv" +
+	"TZBCNMVoDJwdi4fVhYNQyMy4KjH6SlEAvexZaMCmxViqK0e1JpDA33Zg0xuGQl9E" +
+	"hiQvQ2FHNA6XqGDe6CB3obIHAhBD+L/2H7JweCnNu3h8F/bQAgQghowH1UAW3ICg" +
+	"LRMWh9MD3nL6B5zvW/rtbABAW7j9J/ubhTjE1Dh6fjPlrh4F1mHx9l6oKaKdL9MC" +
+	"Czogscg9WEHR1P1lXLtPyv2av6+Uc38L73W4ynzSHQzT7n4a9fw9G0pHvHQQT3Ww" +
+	"CpsYtnkcGJdhEoMqdwTQQQWf8H7l+Sm0erEmuPTqAC3f/RC5LqgrQdfyPN+J3eTy" +
+	"V4GlQVzdO0KeqEArm/KUORmgILgIYcAUkDE9WuptiUObqmYfnmExHY8cNvsWx4o2" +
+	"QtFrwFybGSaII/YzOu4hsM00VwmYOAJQ3KQY+rag56UiZKVHIpnxryUn41uF8d2K" +
+	"fszLbyzAkMTuQc1BJQQHPuhBBej0s+yiFTpnRcrVGp26/SPoGgGLAjmBAhpnAPYi" +
+	"hGHgg8hN+hAh0NObgHp2R/M6Jo+S9Uw80pUFedRU1bYFRVog6sTPEHADwMAG0oUe" +
+	"ZTzCfk4pmd1M7BJIMNGsaaugBm+bdBpLDSNwIBiBVKx5dQgre1pCrhP2FD5vX9bb" +
+	"a28/PP14155vN5a8GIiRRgLCSaKIJMBu9u1u/IdZNWhKp6tcoZGbueNNIlSQLYOV" +
+	"guF/I1QEFvm6liJuQ/g648tjVjId/WMg6iEQnkcuhltYdGxoELryIDySIMiK9wD4" +
+	"MbBiPihigLkeo0OhARBcol9jMSNhf2ITsgILYNseps5hodZnnUYfDxJFi4UQzXNx" +
+	"EsQsWIsPUhf4XvqFHwQ+WPfTBIHct1LIZYv2+juqALF8D9dhxOkM18bdDBT3QEFx" +
+	"IIWRNxv+UV8R+J/0R2XJbrEIOYHU+pkgRzsDEdIZEebTO4gQJeqofJbdkqra4esL" +
+	"roGjHL6Gsy4rZI+PElgZlHIH1++YJmDEhF6psaR1U3IWVmpF3VwE9oiTMpi8Nzz+" +
+	"aHRDUDwW+WIdt3zPNOewJzPCB9E6jmCYHFX8LoITudMz7/N1SyV8kTcL0XLh4A7N" +
+	"JzfBgyjFkYbKgC8xPTQ2NEVHr3NX3I8oB8QLJn4JCrIRrrR5SSiELOBCqIlECSOq" +
+	"AgtNF/5UYIUAbvmgBgPL1xIT9UkTRqqrX53ixpCNGKHEwP1PwJh+ma3ptrBwODbq" +
+	"SORcDEiR6PVwOxokOUEsjBbkzcaucQzU4IBkiIQDSXJdCotjbIzzDs8lfNscXA3I" +
+	"EjvBoCBmX1Xq+IE6m5+HREB7xUkefMhRTIUUVEoGUY2sxAvjsdB3GZnYoMTuuOZk" +
+	"0IILqZh+sKgLQ1ULBUF4SYf1u+nDkki7SjNoBQWIGv3PuY3TIDM1QtuJ3SNep/DE" +
+	"5GEdQMHhYWdISJCEh+RRD7S+bd8OK+sbha0qU3NES7e5JJCEsxa4lA5ucJdrboo7" +
+	"v42uXj7XKXZXimppWTWQJDU2Uks0imZSWU2bLZWUpEzCgmWQzZKmlstNa2pqlKaa" +
+	"aU0pppMDbLLVlqzSSa2lTEtKzZJmtWpNSkylFpqsptkZrNNSzS1S2bNoqllIpMmS" +
+	"lmYDKLKzVm1LKVNkglKVKmyy0EstNixZmkjEiWms2xGFpVEWVNNKkSaWUpmMKLNQ" +
+	"l1leHUD7BQQf0nxooh+rfDYdYFRbCkgUOlBI6EukdLgodLEh6iosAIZUDGcFIBnT" +
+	"5PfxeXIybIEK3a2JhwXN4a5XZyCUN1QHKuKm53cudZGkYw+CUhgAg4jiFUxQcoWX" +
+	"ZiDnC1kcAxisjx4FhBuB1RLpkW/L1JdQMQyPlqBhAGDxWuoWKaLLctSBSGSu4x/U" +
+	"+UGMFxxCH7+CQBDUTBsMAfQX99QooSAcCZEiD6vqNtZoMtphkjx94b82mEcdDU6C" +
+	"GIfhpBNHRGdiSEhKQ5wXmRP0FuHscjHIQQXE+/JA9QIe5u/rPZ7iGp3RjqDlESQZ" +
+	"JCQm/LYfclj52MSyQjrCotj6Nhs9YNtpjG0eYiFHs4e+RkLZGv6lQVs25H8UcydI" +
+	"dBwSSJWZ2GkMV5JBvs3IEHqRvh5VCbiosL1RQbNSevAFkgodQSGXyDwMAKI48pbY" +
+	"nKYY5o3AkxfgcNu/2TS8/z4OpVwpwYLoslFDS0dpbVLklyLktcy0qrt1rkkVDQKa" +
+	"U5mIfn7qbHUwB+pUzzDYgdOwHNMsQqIeAQgWJ7CdQLne/Uch/L74GbnkIeSHVY7B" +
+	"6HzdzDBZDLh9FDDd7l51/E5mJCBgdFYeAu3YglszcA0yVJwA+V7zU+xXQdNIJq0w" +
+	"kfMItgm3gj2uGRgGUX4BpO2ZVeDftfXE9vP1ve16wzwEEF4VAF3VrV67Ndd89m7O" +
+	"GA6EokveXN9MfaQsQ3ZZKcK50mcwJlSsZTgk98c5KYw84IzEZbkvNTsNqzPLKyHo" +
+	"Px0sFlfMO5q7Gy/RLjgGa3WwaF0oI5J5CEBrzAuFdT9Mc82Cdw1XLYdAocXnucxw" +
+	"MDq4Gb5ImDg/Y1aNUuciSSLGs30w7o64wiPJkCOJGESEZEDZGBLmOHlrwGGQG1zj" +
+	"MtuCoxq7RpQlgtQ/YQ5xHKBJJHiia0FHVsRLGQe6Aj+2KgIUQACACiJEFxCraZaP" +
+	"BqeGpHqJ2lIlZ0RymyqrLMZVKEz6wYDwNnVwEvXcGMYxgkEpwJK03QsQ0IAGhJqy" +
+	"CBkmqpjC2e6t4I+Zf0JUTC8cgiBBIMOpm5aNIYWCqlcG2GZjNkLK8i6B/LSEtoDR" +
+	"RIJtyOGwPFu5CEb0Y2d1QVrHSAerk2mlwOR0esAyQ5waYkWyRMAgkNlX1WA43hGO" +
+	"YdDY3OWXJQzDIuXC51atcCh9k/jjTxk4r31uGHUMNV7DyEEFu9aoidiNHFzHFW3k" +
+	"pl23DYUqswRQLrmUK++C6OIeCEEGO4Oxqcy5rvYfEQIEszhUi+UBMa/NHV+bZCGB" +
+	"BmDsfjN+oGAKjwgfAOjBz3eAT0JSBhgZHiXA7HejAOj31UJ0cC5soXLOxcOBUy41" +
+	"LJM6Q8Jwpx4F2KjgcPvn3BRaXEe2Z4vPu2/yeP+aH5JvaiC4fKQAcndicHNDcD9b" +
+	"ShgrZAQXSGTpCSlPzKD5gwnhsz+p8ujoewiFBY3pKLSeXXMDRxzJq44NJzlzG7rV" +
+	"oWrj1/nLbhdUFc+SIUCENGZwNenyhKIbAqfWTOCRY+YUj3gzmpUR68AgUjUPy+0G" +
+	"2hIxUaJCNpMRpoFYjY0WIzNmFoMaNFtEYklpFixGtGxg0UUVJoKiwYNaTRqTKQRU" +
+	"G1Bo221i1VFhYBqNjRFIKqgpJIRS7/L9Xk8v315svJO9OR4u/ONn5FGPE3fMqdtS" +
+	"xkZBu7kta5NbuU8MxyZMYMgmsNmMhnKfGmtyIG2LzBpqWYIbdmCYi0lYLJxwCFFa" +
+	"zJE6zEudHD27ZzbOeSgpk/HnkQbT7twqaaJXNvUzMuUt1hyhU7ceZcph42+VTlXU" +
+	"cZ9UZZJyYojLjaeJHfJU1UZUEmBfLumu8yW5skuyE9uh2BmVxJZi6KxaXBNwSolw" +
+	"BqBcQLj3ucNZIYZLYtirLu3brW6UYgZgZJiDIGiwpsgg7g1AITkgM6FHITxDDnGt" +
+	"4SDHzZbL5s8fec5PCq5DOzDRdWS+0h5Y2INZak1D29cpVyb2aVrV3Wlt7rQhLa3e" +
+	"m3ZwPNcXywE2Qesk1XN24HvZ2Xa6nlm8Pf/xdyRThQkO1NjuAA=="
diff --git a/test/bench/go1/revcomp_test.go b/test/bench/go1/revcomp_test.go
new file mode 100644
index 0000000..9256164
--- /dev/null
+++ b/test/bench/go1/revcomp_test.go
@@ -0,0 +1,85 @@
+// Copyright 2011 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 benchmark, taken from the shootout, tests array indexing
+// and array bounds elimination performance.
+
+package go1
+
+import (
+	"bufio"
+	"bytes"
+	"io/ioutil"
+	"testing"
+)
+
+var revCompTable = [256]uint8{
+	'A': 'T', 'a': 'T',
+	'C': 'G', 'c': 'G',
+	'G': 'C', 'g': 'C',
+	'T': 'A', 't': 'A',
+	'U': 'A', 'u': 'A',
+	'M': 'K', 'm': 'K',
+	'R': 'Y', 'r': 'Y',
+	'W': 'W', 'w': 'W',
+	'S': 'S', 's': 'S',
+	'Y': 'R', 'y': 'R',
+	'K': 'M', 'k': 'M',
+	'V': 'B', 'v': 'B',
+	'H': 'D', 'h': 'D',
+	'D': 'H', 'd': 'H',
+	'B': 'V', 'b': 'V',
+	'N': 'N', 'n': 'N',
+}
+
+func revcomp(data []byte) {
+	in := bufio.NewReader(bytes.NewBuffer(data))
+	out := ioutil.Discard
+	buf := make([]byte, 1024*1024)
+	line, err := in.ReadSlice('\n')
+	for err == nil {
+		out.Write(line)
+
+		// Accumulate reversed complement in buf[w:]
+		nchar := 0
+		w := len(buf)
+		for {
+			line, err = in.ReadSlice('\n')
+			if err != nil || line[0] == '>' {
+				break
+			}
+			line = line[0 : len(line)-1]
+			nchar += len(line)
+			if len(line)+nchar/60+128 >= w {
+				nbuf := make([]byte, len(buf)*5)
+				copy(nbuf[len(nbuf)-len(buf):], buf)
+				w += len(nbuf) - len(buf)
+				buf = nbuf
+			}
+
+			// This loop is the bottleneck.
+			for _, c := range line {
+				w--
+				buf[w] = revCompTable[c]
+			}
+		}
+
+		// Copy down to beginning of buffer, inserting newlines.
+		// The loop left room for the newlines and 128 bytes of padding.
+		i := 0
+		for j := w; j < len(buf); j += 60 {
+			n := copy(buf[i:i+60], buf[j:])
+			buf[i+n] = '\n'
+			i += n + 1
+		}
+		out.Write(buf[0:i])
+	}
+}
+
+func BenchmarkRevcomp25M(b *testing.B) {
+	b.SetBytes(int64(len(fasta25m)))
+	for i := 0; i < b.N; i++ {
+		revcomp(fasta25m)
+	}
+}
diff --git a/test/bench/go1/template_test.go b/test/bench/go1/template_test.go
new file mode 100644
index 0000000..db4839a
--- /dev/null
+++ b/test/bench/go1/template_test.go
@@ -0,0 +1,76 @@
+// Copyright 2011 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 benchmark tests text/template throughput,
+// converting a large data structure with a simple template.
+
+package go1
+
+import (
+	"bytes"
+	"io/ioutil"
+	"strings"
+	"testing"
+	"text/template"
+)
+
+// After removing \t and \n this generates identical output to
+// json.Marshal, making it easy to test for correctness.
+const tmplText = `
+{
+	"tree":{{template "node" .Tree}},
+	"username":"{{.Username}}"
+}
+{{define "node"}}
+{
+	"name":"{{.Name}}",
+	"kids":[
+	{{range $i, $k := .Kids}}
+		{{if $i}}
+			,
+		{{end}}
+		{{template "node" $k}}
+	{{end}}
+	],
+	"cl_weight":{{.CLWeight}},
+	"touches":{{.Touches}},
+	"min_t":{{.MinT}},
+	"max_t":{{.MaxT}},
+	"mean_t":{{.MeanT}}
+}
+{{end}}
+`
+
+func stripTabNL(r rune) rune {
+	if r == '\t' || r == '\n' {
+		return -1
+	}
+	return r
+}
+
+var tmpl = template.Must(template.New("main").Parse(strings.Map(stripTabNL, tmplText)))
+
+func init() {
+	var buf bytes.Buffer
+	if err := tmpl.Execute(&buf, &jsondata); err != nil {
+		panic(err)
+	}
+	if !bytes.Equal(buf.Bytes(), jsonbytes) {
+		println(buf.Len(), len(jsonbytes))
+		panic("wrong output")
+	}
+}
+
+func tmplexec() {
+	if err := tmpl.Execute(ioutil.Discard, &jsondata); err != nil {
+		panic(err)
+	}
+}
+
+func BenchmarkTemplate(b *testing.B) {
+	b.SetBytes(int64(len(jsonbytes)))
+	for i := 0; i < b.N; i++ {
+		tmplexec()
+	}
+}
diff --git a/test/bench/meteor-contest.go b/test/bench/meteor-contest.go
deleted file mode 100644
index 6660810..0000000
--- a/test/bench/meteor-contest.go
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on meteor-contest.c by Christian Vosteen
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-)
-
-var max_solutions = flag.Int("n", 2100, "maximum number of solutions")
-
-
-func boolInt(b bool) int8 {
-	if b {
-		return 1
-	}
-	return 0
-}
-
-/* The board is a 50 cell hexagonal pattern.  For    . . . . .
- * maximum speed the board will be implemented as     . . . . .
- * 50 bits, which will fit into a 64 bit long long   . . . . .
- * int.                                               . . . . .
- *                                                   . . . . .
- * I will represent 0's as empty cells and 1's        . . . . .
- * as full cells.                                    . . . . .
- *                                                    . . . . .
- *                                                   . . . . .
- *                                                    . . . . .
- */
-
-var board uint64 = 0xFFFC000000000000
-
-/* The puzzle pieces must be specified by the path followed
- * from one end to the other along 12 hexagonal directions.
- *
- *   Piece 0   Piece 1   Piece 2   Piece 3   Piece 4
- *
- *  O O O O    O   O O   O O O     O O O     O   O
- *         O    O O           O       O       O O
- *                           O         O         O
- *
- *   Piece 5   Piece 6   Piece 7   Piece 8   Piece 9
- *
- *    O O O     O O       O O     O O        O O O O
- *       O O       O O       O       O O O        O
- *                  O       O O
- *
- * I had to make it 12 directions because I wanted all of the
- * piece definitions to fit into the same size arrays.  It is
- * not possible to define piece 4 in terms of the 6 cardinal
- * directions in 4 moves.
- */
-
-const (
-	E = iota
-	ESE
-	SE
-	S
-	SW
-	WSW
-	W
-	WNW
-	NW
-	N
-	NE
-	ENE
-	PIVOT
-)
-
-var piece_def = [10][4]int8{
-	[4]int8{E, E, E, SE},
-	[4]int8{SE, E, NE, E},
-	[4]int8{E, E, SE, SW},
-	[4]int8{E, E, SW, SE},
-	[4]int8{SE, E, NE, S},
-	[4]int8{E, E, SW, E},
-	[4]int8{E, SE, SE, NE},
-	[4]int8{E, SE, SE, W},
-	[4]int8{E, SE, E, E},
-	[4]int8{E, E, E, SW},
-}
-
-
-/* To minimize the amount of work done in the recursive solve function below,
- * I'm going to allocate enough space for all legal rotations of each piece
- * at each position on the board. That's 10 pieces x 50 board positions x
- * 12 rotations.  However, not all 12 rotations will fit on every cell, so
- * I'll have to keep count of the actual number that do.
- * The pieces are going to be unsigned long long ints just like the board so
- * they can be bitwise-anded with the board to determine if they fit.
- * I'm also going to record the next possible open cell for each piece and
- * location to reduce the burden on the solve function.
- */
-var (
-	pieces       [10][50][12]uint64
-	piece_counts [10][50]int
-	next_cell    [10][50][12]int8
-)
-
-/* Returns the direction rotated 60 degrees clockwise */
-func rotate(dir int8) int8 { return (dir + 2) % PIVOT }
-
-/* Returns the direction flipped on the horizontal axis */
-func flip(dir int8) int8 { return (PIVOT - dir) % PIVOT }
-
-
-/* Returns the new cell index from the specified cell in the
- * specified direction.  The index is only valid if the
- * starting cell and direction have been checked by the
- * out_of_bounds function first.
- */
-func shift(cell, dir int8) int8 {
-	switch dir {
-	case E:
-		return cell + 1
-	case ESE:
-		if ((cell / 5) % 2) != 0 {
-			return cell + 7
-		} else {
-			return cell + 6
-		}
-	case SE:
-		if ((cell / 5) % 2) != 0 {
-			return cell + 6
-		} else {
-			return cell + 5
-		}
-	case S:
-		return cell + 10
-	case SW:
-		if ((cell / 5) % 2) != 0 {
-			return cell + 5
-		} else {
-			return cell + 4
-		}
-	case WSW:
-		if ((cell / 5) % 2) != 0 {
-			return cell + 4
-		} else {
-			return cell + 3
-		}
-	case W:
-		return cell - 1
-	case WNW:
-		if ((cell / 5) % 2) != 0 {
-			return cell - 6
-		} else {
-			return cell - 7
-		}
-	case NW:
-		if ((cell / 5) % 2) != 0 {
-			return cell - 5
-		} else {
-			return cell - 6
-		}
-	case N:
-		return cell - 10
-	case NE:
-		if ((cell / 5) % 2) != 0 {
-			return cell - 4
-		} else {
-			return cell - 5
-		}
-	case ENE:
-		if ((cell / 5) % 2) != 0 {
-			return cell - 3
-		} else {
-			return cell - 4
-		}
-	}
-	return cell
-}
-
-/* Returns wether the specified cell and direction will land outside
- * of the board.  Used to determine if a piece is at a legal board
- * location or not.
- */
-func out_of_bounds(cell, dir int8) bool {
-	switch dir {
-	case E:
-		return cell%5 == 4
-	case ESE:
-		i := cell % 10
-		return i == 4 || i == 8 || i == 9 || cell >= 45
-	case SE:
-		return cell%10 == 9 || cell >= 45
-	case S:
-		return cell >= 40
-	case SW:
-		return cell%10 == 0 || cell >= 45
-	case WSW:
-		i := cell % 10
-		return i == 0 || i == 1 || i == 5 || cell >= 45
-	case W:
-		return cell%5 == 0
-	case WNW:
-		i := cell % 10
-		return i == 0 || i == 1 || i == 5 || cell < 5
-	case NW:
-		return cell%10 == 0 || cell < 5
-	case N:
-		return cell < 10
-	case NE:
-		return cell%10 == 9 || cell < 5
-	case ENE:
-		i := cell % 10
-		return i == 4 || i == 8 || i == 9 || cell < 5
-	}
-	return false
-}
-
-/* Rotate a piece 60 degrees clockwise */
-func rotate_piece(piece int) {
-	for i := 0; i < 4; i++ {
-		piece_def[piece][i] = rotate(piece_def[piece][i])
-	}
-}
-
-/* Flip a piece along the horizontal axis */
-func flip_piece(piece int) {
-	for i := 0; i < 4; i++ {
-		piece_def[piece][i] = flip(piece_def[piece][i])
-	}
-}
-
-/* Convenience function to quickly calculate all of the indices for a piece */
-func calc_cell_indices(cell []int8, piece int, index int8) {
-	cell[0] = index
-	for i := 1; i < 5; i++ {
-		cell[i] = shift(cell[i-1], piece_def[piece][i-1])
-	}
-}
-
-/* Convenience function to quickly calculate if a piece fits on the board */
-func cells_fit_on_board(cell []int8, piece int) bool {
-	return !out_of_bounds(cell[0], piece_def[piece][0]) &&
-		!out_of_bounds(cell[1], piece_def[piece][1]) &&
-		!out_of_bounds(cell[2], piece_def[piece][2]) &&
-		!out_of_bounds(cell[3], piece_def[piece][3])
-}
-
-/* Returns the lowest index of the cells of a piece.
- * I use the lowest index that a piece occupies as the index for looking up
- * the piece in the solve function.
- */
-func minimum_of_cells(cell []int8) int8 {
-	minimum := cell[0]
-	for i := 1; i < 5; i++ {
-		if cell[i] < minimum {
-			minimum = cell[i]
-		}
-	}
-	return minimum
-}
-
-/* Calculate the lowest possible open cell if the piece is placed on the board.
- * Used to later reduce the amount of time searching for open cells in the
- * solve function.
- */
-func first_empty_cell(cell []int8, minimum int8) int8 {
-	first_empty := minimum
-	for first_empty == cell[0] || first_empty == cell[1] ||
-		first_empty == cell[2] || first_empty == cell[3] ||
-		first_empty == cell[4] {
-		first_empty++
-	}
-	return first_empty
-}
-
-/* Generate the unsigned long long int that will later be anded with the
- * board to determine if it fits.
- */
-func bitmask_from_cells(cell []int8) uint64 {
-	var piece_mask uint64
-	for i := 0; i < 5; i++ {
-		piece_mask |= 1 << uint(cell[i])
-	}
-	return piece_mask
-}
-
-/* Record the piece and other important information in arrays that will
- * later be used by the solve function.
- */
-func record_piece(piece int, minimum int8, first_empty int8, piece_mask uint64) {
-	pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask
-	next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty
-	piece_counts[piece][minimum]++
-}
-
-
-/* Fill the entire board going cell by cell.  If any cells are "trapped"
- * they will be left alone.
- */
-func fill_contiguous_space(board []int8, index int8) {
-	if board[index] == 1 {
-		return
-	}
-	board[index] = 1
-	if !out_of_bounds(index, E) {
-		fill_contiguous_space(board, shift(index, E))
-	}
-	if !out_of_bounds(index, SE) {
-		fill_contiguous_space(board, shift(index, SE))
-	}
-	if !out_of_bounds(index, SW) {
-		fill_contiguous_space(board, shift(index, SW))
-	}
-	if !out_of_bounds(index, W) {
-		fill_contiguous_space(board, shift(index, W))
-	}
-	if !out_of_bounds(index, NW) {
-		fill_contiguous_space(board, shift(index, NW))
-	}
-	if !out_of_bounds(index, NE) {
-		fill_contiguous_space(board, shift(index, NE))
-	}
-}
-
-
-/* To thin the number of pieces, I calculate if any of them trap any empty
- * cells at the edges.  There are only a handful of exceptions where the
- * the board can be solved with the trapped cells.  For example:  piece 8 can
- * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0
- * can split the board in half where both halves are viable.
- */
-func has_island(cell []int8, piece int) bool {
-	temp_board := make([]int8, 50)
-	var i int
-	for i = 0; i < 5; i++ {
-		temp_board[cell[i]] = 1
-	}
-	i = 49
-	for temp_board[i] == 1 {
-		i--
-	}
-	fill_contiguous_space(temp_board, int8(i))
-	c := 0
-	for i = 0; i < 50; i++ {
-		if temp_board[i] == 0 {
-			c++
-		}
-	}
-	if c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) ||
-		(c%5 == 0 && piece == 0) {
-		return false
-	}
-	return true
-}
-
-
-/* Calculate all six rotations of the specified piece at the specified index.
- * We calculate only half of piece 3's rotations.  This is because any solution
- * found has an identical solution rotated 180 degrees.  Thus we can reduce the
- * number of attempted pieces in the solve algorithm by not including the 180-
- * degree-rotated pieces of ONE of the pieces.  I chose piece 3 because it gave
- * me the best time ;)
- */
-func calc_six_rotations(piece, index int) {
-	cell := make([]int8, 5)
-	for rotation := 0; rotation < 6; rotation++ {
-		if piece != 3 || rotation < 3 {
-			calc_cell_indices(cell, piece, int8(index))
-			if cells_fit_on_board(cell, piece) && !has_island(cell, piece) {
-				minimum := minimum_of_cells(cell)
-				first_empty := first_empty_cell(cell, minimum)
-				piece_mask := bitmask_from_cells(cell)
-				record_piece(piece, minimum, first_empty, piece_mask)
-			}
-		}
-		rotate_piece(piece)
-	}
-}
-
-/* Calculate every legal rotation for each piece at each board location. */
-func calc_pieces() {
-	for piece := 0; piece < 10; piece++ {
-		for index := 0; index < 50; index++ {
-			calc_six_rotations(piece, index)
-			flip_piece(piece)
-			calc_six_rotations(piece, index)
-		}
-	}
-}
-
-
-/* Calculate all 32 possible states for a 5-bit row and all rows that will
- * create islands that follow any of the 32 possible rows.  These pre-
- * calculated 5-bit rows will be used to find islands in a partially solved
- * board in the solve function.
- */
-const (
-	ROW_MASK    = 0x1F
-	TRIPLE_MASK = 0x7FFF
-)
-
-var (
-	all_rows = [32]int8{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,
-	}
-	bad_even_rows   [32][32]int8
-	bad_odd_rows    [32][32]int8
-	bad_even_triple [32768]int8
-	bad_odd_triple  [32768]int8
-)
-
-func rows_bad(row1, row2 int8, even bool) int8 {
-	/* even is referring to row1 */
-	var row2_shift int8
-	/* Test for blockages at same index and shifted index */
-	if even {
-		row2_shift = ((row2 << 1) & ROW_MASK) | 0x01
-	} else {
-		row2_shift = (row2 >> 1) | 0x10
-	}
-	block := ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift)
-	/* Test for groups of 0's */
-	in_zeroes := false
-	group_okay := false
-	for i := uint8(0); i < 5; i++ {
-		if row1&(1<<i) != 0 {
-			if in_zeroes {
-				if !group_okay {
-					return 1
-				}
-				in_zeroes = false
-				group_okay = false
-			}
-		} else {
-			if !in_zeroes {
-				in_zeroes = true
-			}
-			if (block & (1 << i)) == 0 {
-				group_okay = true
-			}
-		}
-	}
-	if in_zeroes {
-		return boolInt(!group_okay)
-	}
-	return 0
-}
-
-/* Check for cases where three rows checked sequentially cause a false
- * positive.  One scenario is when 5 cells may be surrounded where piece 5
- * or 7 can fit.  The other scenario is when piece 2 creates a hook shape.
- */
-func triple_is_okay(row1, row2, row3 int, even bool) bool {
-	if even {
-		/* There are four cases:
-		 * row1: 00011  00001  11001  10101
-		 * row2: 01011  00101  10001  10001
-		 * row3: 011??  00110  ?????  ?????
-		 */
-		return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) ||
-			((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) ||
-			((row1 == 0x19) && (row2 == 0x11)) ||
-			((row1 == 0x15) && (row2 == 0x11))
-	}
-	/* There are two cases:
-	 * row1: 10011  10101
-	 * row2: 10001  10001
-	 * row3: ?????  ?????
-	 */
-	return ((row1 == 0x13) && (row2 == 0x11)) ||
-		((row1 == 0x15) && (row2 == 0x11))
-}
-
-func calc_rows() {
-	for row1 := int8(0); row1 < 32; row1++ {
-		for row2 := int8(0); row2 < 32; row2++ {
-			bad_even_rows[row1][row2] = rows_bad(row1, row2, true)
-			bad_odd_rows[row1][row2] = rows_bad(row1, row2, false)
-		}
-	}
-	for row1 := 0; row1 < 32; row1++ {
-		for row2 := 0; row2 < 32; row2++ {
-			for row3 := 0; row3 < 32; row3++ {
-				result1 := bad_even_rows[row1][row2]
-				result2 := bad_odd_rows[row2][row3]
-				if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, true) {
-					bad_even_triple[row1+(row2*32)+(row3*1024)] = 0
-				} else {
-					bad_even_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0)
-				}
-
-				result1 = bad_odd_rows[row1][row2]
-				result2 = bad_even_rows[row2][row3]
-				if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, false) {
-					bad_odd_triple[row1+(row2*32)+(row3*1024)] = 0
-				} else {
-					bad_odd_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0)
-				}
-			}
-		}
-	}
-}
-
-
-/* Calculate islands while solving the board.
- */
-func boardHasIslands(cell int8) int8 {
-	/* Too low on board, don't bother checking */
-	if cell >= 40 {
-		return 0
-	}
-	current_triple := (board >> uint((cell/5)*5)) & TRIPLE_MASK
-	if (cell/5)%2 != 0 {
-		return bad_odd_triple[current_triple]
-	}
-	return bad_even_triple[current_triple]
-}
-
-
-/* The recursive solve algorithm.  Try to place each permutation in the upper-
- * leftmost empty cell.  Mark off available pieces as it goes along.
- * Because the board is a bit mask, the piece number and bit mask must be saved
- * at each successful piece placement.  This data is used to create a 50 char
- * array if a solution is found.
- */
-var (
-	avail          uint16 = 0x03FF
-	sol_nums       [10]int8
-	sol_masks      [10]uint64
-	solutions      [2100][50]int8
-	solution_count = 0
-)
-
-func record_solution() {
-	for sol_no := 0; sol_no < 10; sol_no++ {
-		sol_mask := sol_masks[sol_no]
-		for index := 0; index < 50; index++ {
-			if sol_mask&1 == 1 {
-				solutions[solution_count][index] = sol_nums[sol_no]
-				/* Board rotated 180 degrees is a solution too! */
-				solutions[solution_count+1][49-index] = sol_nums[sol_no]
-			}
-			sol_mask = sol_mask >> 1
-		}
-	}
-	solution_count += 2
-}
-
-func solve(depth, cell int8) {
-	if solution_count >= *max_solutions {
-		return
-	}
-
-	for board&(1<<uint(cell)) != 0 {
-		cell++
-	}
-
-	for piece := int8(0); piece < 10; piece++ {
-		var piece_no_mask uint16 = 1 << uint(piece)
-		if avail&piece_no_mask == 0 {
-			continue
-		}
-		avail ^= piece_no_mask
-		max_rots := piece_counts[piece][cell]
-		piece_mask := pieces[piece][cell]
-		for rotation := 0; rotation < max_rots; rotation++ {
-			if board&piece_mask[rotation] == 0 {
-				sol_nums[depth] = piece
-				sol_masks[depth] = piece_mask[rotation]
-				if depth == 9 {
-					/* Solution found!!!!!11!!ONE! */
-					record_solution()
-					avail ^= piece_no_mask
-					return
-				}
-				board |= piece_mask[rotation]
-				if boardHasIslands(next_cell[piece][cell][rotation]) == 0 {
-					solve(depth+1, next_cell[piece][cell][rotation])
-				}
-				board ^= piece_mask[rotation]
-			}
-		}
-		avail ^= piece_no_mask
-	}
-}
-
-/* pretty print a board in the specified hexagonal format */
-func pretty(b *[50]int8) {
-	for i := 0; i < 50; i += 10 {
-		fmt.Printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0',
-			b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0',
-			b[i+7]+'0', b[i+8]+'0', b[i+9]+'0')
-	}
-	fmt.Printf("\n")
-}
-
-/* Find smallest and largest solutions */
-func smallest_largest() (smallest, largest *[50]int8) {
-	smallest = &solutions[0]
-	largest = &solutions[0]
-	for i := 1; i < solution_count; i++ {
-		candidate := &solutions[i]
-		for j, s := range *smallest {
-			c := candidate[j]
-			if c == s {
-				continue
-			}
-			if c < s {
-				smallest = candidate
-			}
-			break
-		}
-		for j, s := range *largest {
-			c := candidate[j]
-			if c == s {
-				continue
-			}
-			if c > s {
-				largest = candidate
-			}
-			break
-		}
-	}
-	return
-}
-
-func main() {
-	flag.Parse()
-	calc_pieces()
-	calc_rows()
-	solve(0, 0)
-	fmt.Printf("%d solutions found\n\n", solution_count)
-	smallest, largest := smallest_largest()
-	pretty(smallest)
-	pretty(largest)
-}
diff --git a/test/bench/nbody.go b/test/bench/nbody.go
deleted file mode 100644
index e9f4517..0000000
--- a/test/bench/nbody.go
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on C program by Christoph Bauer
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"math"
-)
-
-var n = flag.Int("n", 1000, "number of iterations")
-
-type Body struct {
-	x, y, z, vx, vy, vz, mass float64
-}
-
-const (
-	solarMass   = 4 * math.Pi * math.Pi
-	daysPerYear = 365.24
-)
-
-func (b *Body) offsetMomentum(px, py, pz float64) {
-	b.vx = -px / solarMass
-	b.vy = -py / solarMass
-	b.vz = -pz / solarMass
-}
-
-type System []*Body
-
-func NewSystem(body []Body) System {
-	n := make(System, len(body))
-	for i := 0; i < len(body); i++ {
-		n[i] = new(Body) // copy to avoid overwriting the inputs
-		*n[i] = body[i]
-	}
-	var px, py, pz float64
-	for _, body := range n {
-		px += body.vx * body.mass
-		py += body.vy * body.mass
-		pz += body.vz * body.mass
-	}
-	n[0].offsetMomentum(px, py, pz)
-	return n
-}
-
-func (sys System) energy() float64 {
-	var e float64
-	for i, body := range sys {
-		e += 0.5 * body.mass *
-			(body.vx*body.vx + body.vy*body.vy + body.vz*body.vz)
-		for j := i + 1; j < len(sys); j++ {
-			body2 := sys[j]
-			dx := body.x - body2.x
-			dy := body.y - body2.y
-			dz := body.z - body2.z
-			distance := math.Sqrt(dx*dx + dy*dy + dz*dz)
-			e -= (body.mass * body2.mass) / distance
-		}
-	}
-	return e
-}
-
-func (sys System) advance(dt float64) {
-	for i, body := range sys {
-		for j := i + 1; j < len(sys); j++ {
-			body2 := sys[j]
-			dx := body.x - body2.x
-			dy := body.y - body2.y
-			dz := body.z - body2.z
-
-			dSquared := dx*dx + dy*dy + dz*dz
-			distance := math.Sqrt(dSquared)
-			mag := dt / (dSquared * distance)
-
-			body.vx -= dx * body2.mass * mag
-			body.vy -= dy * body2.mass * mag
-			body.vz -= dz * body2.mass * mag
-
-			body2.vx += dx * body.mass * mag
-			body2.vy += dy * body.mass * mag
-			body2.vz += dz * body.mass * mag
-		}
-	}
-
-	for _, body := range sys {
-		body.x += dt * body.vx
-		body.y += dt * body.vy
-		body.z += dt * body.vz
-	}
-}
-
-var (
-	jupiter = Body{
-		x: 4.84143144246472090e+00,
-		y: -1.16032004402742839e+00,
-		z: -1.03622044471123109e-01,
-		vx: 1.66007664274403694e-03 * daysPerYear,
-		vy: 7.69901118419740425e-03 * daysPerYear,
-		vz: -6.90460016972063023e-05 * daysPerYear,
-		mass: 9.54791938424326609e-04 * solarMass,
-	}
-	saturn = Body{
-		x: 8.34336671824457987e+00,
-		y: 4.12479856412430479e+00,
-		z: -4.03523417114321381e-01,
-		vx: -2.76742510726862411e-03 * daysPerYear,
-		vy: 4.99852801234917238e-03 * daysPerYear,
-		vz: 2.30417297573763929e-05 * daysPerYear,
-		mass: 2.85885980666130812e-04 * solarMass,
-	}
-	uranus = Body{
-		x: 1.28943695621391310e+01,
-		y: -1.51111514016986312e+01,
-		z: -2.23307578892655734e-01,
-		vx: 2.96460137564761618e-03 * daysPerYear,
-		vy: 2.37847173959480950e-03 * daysPerYear,
-		vz: -2.96589568540237556e-05 * daysPerYear,
-		mass: 4.36624404335156298e-05 * solarMass,
-	}
-	neptune = Body{
-		x: 1.53796971148509165e+01,
-		y: -2.59193146099879641e+01,
-		z: 1.79258772950371181e-01,
-		vx: 2.68067772490389322e-03 * daysPerYear,
-		vy: 1.62824170038242295e-03 * daysPerYear,
-		vz: -9.51592254519715870e-05 * daysPerYear,
-		mass: 5.15138902046611451e-05 * solarMass,
-	}
-	sun = Body{
-		mass: solarMass,
-	}
-)
-
-func main() {
-	flag.Parse()
-
-	system := NewSystem([]Body{sun, jupiter, saturn, uranus, neptune})
-	fmt.Printf("%.9f\n", system.energy())
-	for i := 0; i < *n; i++ {
-		system.advance(0.01)
-	}
-	fmt.Printf("%.9f\n", system.energy())
-}
diff --git a/test/bench/pidigits.go b/test/bench/pidigits.go
deleted file mode 100644
index e593121..0000000
--- a/test/bench/pidigits.go
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on pidigits.c (by Paolo Bonzini & Sean Bartlett,
- *                      modified by Michael Mellor)
- */
-
-package main
-
-import (
-	"big"
-	"flag"
-	"fmt"
-)
-
-var n = flag.Int("n", 27, "number of digits")
-var silent = flag.Bool("s", false, "don't print result")
-
-var (
-	tmp1  = big.NewInt(0)
-	tmp2  = big.NewInt(0)
-	tmp3  = big.NewInt(0)
-	y2    = big.NewInt(0)
-	bigk  = big.NewInt(0)
-	numer = big.NewInt(1)
-	accum = big.NewInt(0)
-	denom = big.NewInt(1)
-	ten   = big.NewInt(10)
-)
-
-func extract_digit() int64 {
-	if numer.Cmp(accum) > 0 {
-		return -1
-	}
-
-	// Compute (numer * 3 + accum) / denom
-	tmp1.Lsh(numer, 1)
-	tmp1.Add(tmp1, numer)
-	tmp1.Add(tmp1, accum)
-	tmp1.DivMod(tmp1, denom, tmp2)
-
-	// Now, if (numer * 4 + accum) % denom...
-	tmp2.Add(tmp2, numer)
-
-	// ... is normalized, then the two divisions have the same result.
-	if tmp2.Cmp(denom) >= 0 {
-		return -1
-	}
-
-	return tmp1.Int64()
-}
-
-func next_term(k int64) {
-	y2.SetInt64(k*2 + 1)
-	bigk.SetInt64(k)
-
-	tmp1.Lsh(numer, 1)
-	accum.Add(accum, tmp1)
-	accum.Mul(accum, y2)
-	numer.Mul(numer, bigk)
-	denom.Mul(denom, y2)
-}
-
-func eliminate_digit(d int64) {
-	tmp3.SetInt64(d)
-	accum.Sub(accum, tmp3.Mul(denom, tmp3))
-	accum.Mul(accum, ten)
-	numer.Mul(numer, ten)
-}
-
-func printf(s string, arg ...interface{}) {
-	if !*silent {
-		fmt.Printf(s, arg...)
-	}
-}
-
-func main() {
-	flag.Parse()
-
-	var m int // 0 <= m < 10
-	for i, k := 0, int64(0); ; {
-		d := int64(-1)
-		for d < 0 {
-			k++
-			next_term(k)
-			d = extract_digit()
-		}
-
-		printf("%c", d+'0')
-
-		i++
-		m = i % 10
-		if m == 0 {
-			printf("\t:%d\n", i)
-		}
-		if i >= *n {
-			break
-		}
-		eliminate_digit(d)
-	}
-
-	if m > 0 {
-		printf("%s\t:%d\n", "          "[m:10], *n)
-	}
-}
diff --git a/test/bench/regex-dna-parallel.go b/test/bench/regex-dna-parallel.go
deleted file mode 100644
index 1335e4d..0000000
--- a/test/bench/regex-dna-parallel.go
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"runtime"
-	"regexp"
-)
-
-var variants = []string{
-	"agggtaaa|tttaccct",
-	"[cgt]gggtaaa|tttaccc[acg]",
-	"a[act]ggtaaa|tttacc[agt]t",
-	"ag[act]gtaaa|tttac[agt]ct",
-	"agg[act]taaa|ttta[agt]cct",
-	"aggg[acg]aaa|ttt[cgt]ccct",
-	"agggt[cgt]aa|tt[acg]accct",
-	"agggta[cgt]a|t[acg]taccct",
-	"agggtaa[cgt]|[acg]ttaccct",
-}
-
-type Subst struct {
-	pat, repl string
-}
-
-var substs = []Subst{
-	Subst{"B", "(c|g|t)"},
-	Subst{"D", "(a|g|t)"},
-	Subst{"H", "(a|c|t)"},
-	Subst{"K", "(g|t)"},
-	Subst{"M", "(a|c)"},
-	Subst{"N", "(a|c|g|t)"},
-	Subst{"R", "(a|g)"},
-	Subst{"S", "(c|g)"},
-	Subst{"V", "(a|c|g)"},
-	Subst{"W", "(a|t)"},
-	Subst{"Y", "(c|t)"},
-}
-
-func countMatches(pat string, bytes []byte) int {
-	re := regexp.MustCompile(pat)
-	n := 0
-	for {
-		e := re.FindIndex(bytes)
-		if e == nil {
-			break
-		}
-		n++
-		bytes = bytes[e[1]:]
-	}
-	return n
-}
-
-func main() {
-	runtime.GOMAXPROCS(4)
-	bytes, err := ioutil.ReadAll(os.Stdin)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "can't read input: %s\n", err)
-		os.Exit(2)
-	}
-	ilen := len(bytes)
-	// Delete the comment lines and newlines
-	bytes = regexp.MustCompile("(>[^\n]+)?\n").ReplaceAll(bytes, []byte{})
-	clen := len(bytes)
-
-	mresults := make([]chan int, len(variants))
-	for i, s := range variants {
-		ch := make(chan int)
-		mresults[i] = ch
-		go func(ss string) {
-			ch <- countMatches(ss, bytes)
-		}(s)
-	}
-
-	lenresult := make(chan int)
-	bb := bytes
-	go func() {
-		for _, sub := range substs {
-			bb = regexp.MustCompile(sub.pat).ReplaceAll(bb, []byte(sub.repl))
-		}
-		lenresult <- len(bb)
-	}()
-
-	for i, s := range variants {
-		fmt.Printf("%s %d\n", s, <-mresults[i])
-	}
-	fmt.Printf("\n%d\n%d\n%d\n", ilen, clen, <-lenresult)
-}
diff --git a/test/bench/shootout/Makefile b/test/bench/shootout/Makefile
new file mode 100644
index 0000000..e1c9b7b
--- /dev/null
+++ b/test/bench/shootout/Makefile
@@ -0,0 +1,14 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../src/Make.inc
+
+all:
+	@echo "make clean or timing"
+
+timing:
+	./timing.sh
+
+clean:
+	rm -f [568].out *.[568]
diff --git a/test/bench/binary-tree-freelist.go b/test/bench/shootout/binary-tree-freelist.go
similarity index 100%
rename from test/bench/binary-tree-freelist.go
rename to test/bench/shootout/binary-tree-freelist.go
diff --git a/test/bench/binary-tree-freelist.txt b/test/bench/shootout/binary-tree-freelist.txt
similarity index 100%
rename from test/bench/binary-tree-freelist.txt
rename to test/bench/shootout/binary-tree-freelist.txt
diff --git a/test/bench/binary-tree.c b/test/bench/shootout/binary-tree.c
similarity index 100%
rename from test/bench/binary-tree.c
rename to test/bench/shootout/binary-tree.c
diff --git a/test/bench/binary-tree.go b/test/bench/shootout/binary-tree.go
similarity index 100%
rename from test/bench/binary-tree.go
rename to test/bench/shootout/binary-tree.go
diff --git a/test/bench/binary-tree.txt b/test/bench/shootout/binary-tree.txt
similarity index 100%
rename from test/bench/binary-tree.txt
rename to test/bench/shootout/binary-tree.txt
diff --git a/test/bench/chameneosredux.c b/test/bench/shootout/chameneosredux.c
similarity index 100%
rename from test/bench/chameneosredux.c
rename to test/bench/shootout/chameneosredux.c
diff --git a/test/bench/shootout/chameneosredux.go b/test/bench/shootout/chameneosredux.go
new file mode 100644
index 0000000..3395798
--- /dev/null
+++ b/test/bench/shootout/chameneosredux.go
@@ -0,0 +1,180 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"strconv"
+)
+
+const (
+	blue = iota
+	red
+	yellow
+	ncol
+)
+
+var complement = [...]int{
+	red | red<<2:       red,
+	red | yellow<<2:    blue,
+	red | blue<<2:      yellow,
+	yellow | red<<2:    blue,
+	yellow | yellow<<2: yellow,
+	yellow | blue<<2:   red,
+	blue | red<<2:      yellow,
+	blue | yellow<<2:   red,
+	blue | blue<<2:     blue,
+}
+
+var colname = [...]string{
+	blue:   "blue",
+	red:    "red",
+	yellow: "yellow",
+}
+
+// information about the current state of a creature.
+type info struct {
+	colour int // creature's current colour.
+	name   int // creature's name.
+}
+
+// exclusive access data-structure kept inside meetingplace.
+// if mate is nil, it indicates there's no creature currently waiting;
+// otherwise the creature's info is stored in info, and
+// it is waiting to receive its mate's information on the mate channel.
+type rendez struct {
+	n    int         // current number of encounters.
+	mate chan<- info // creature waiting when non-nil.
+	info info        // info about creature waiting.
+}
+
+// result sent by each creature at the end of processing.
+type result struct {
+	met  int
+	same int
+}
+
+var n = 600
+
+func main() {
+	flag.Parse()
+	if flag.NArg() > 0 {
+		n, _ = strconv.Atoi(flag.Arg(0))
+	}
+
+	for c0 := 0; c0 < ncol; c0++ {
+		for c1 := 0; c1 < ncol; c1++ {
+			fmt.Printf("%s + %s -> %s\n", colname[c0], colname[c1], colname[complement[c0|c1<<2]])
+		}
+	}
+	fmt.Print("\n")
+
+	pallmall([]int{blue, red, yellow})
+	pallmall([]int{blue, red, yellow, red, yellow, blue, red, yellow, red, blue})
+}
+
+func pallmall(cols []int) {
+
+	// invariant: meetingplace always contains a value unless a creature
+	// is currently dealing with it (whereupon it must put it back).
+	meetingplace := make(chan rendez, 1)
+	meetingplace <- rendez{n: 0}
+
+	ended := make(chan result)
+	msg := ""
+	for i, col := range cols {
+		go creature(info{col, i}, meetingplace, ended)
+		msg += " " + colname[col]
+	}
+	fmt.Println(msg)
+	tot := 0
+	// wait for all results
+	for _ = range cols {
+		result := <-ended
+		tot += result.met
+		fmt.Printf("%v%v\n", result.met, spell(result.same, true))
+	}
+	fmt.Printf("%v\n\n", spell(tot, true))
+}
+
+// in this function, variables ending in 0 refer to the local creature,
+// variables ending in 1 to the creature we've met.
+func creature(info0 info, meetingplace chan rendez, ended chan result) {
+	c0 := make(chan info)
+	met := 0
+	same := 0
+	for {
+		var othername int
+		// get access to rendez data and decide what to do.
+		switch r := <-meetingplace; {
+		case r.n >= n:
+			// if no more meetings left, then send our result data and exit.
+			meetingplace <- rendez{n: r.n}
+			ended <- result{met, same}
+			return
+		case r.mate == nil:
+			// no creature waiting; wait for someone to meet us,
+			// get their info and send our info in reply.
+			meetingplace <- rendez{n: r.n, info: info0, mate: c0}
+			info1 := <-c0
+			othername = info1.name
+			info0.colour = complement[info0.colour|info1.colour<<2]
+		default:
+			// another creature is waiting for us with its info;
+			// increment meeting count,
+			// send them our info in reply.
+			r.n++
+			meetingplace <- rendez{n: r.n, mate: nil}
+			r.mate <- info0
+			othername = r.info.name
+			info0.colour = complement[info0.colour|r.info.colour<<2]
+		}
+		if othername == info0.name {
+			same++
+		}
+		met++
+	}
+}
+
+var digits = [...]string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
+
+func spell(n int, required bool) string {
+	if n == 0 && !required {
+		return ""
+	}
+	return spell(n/10, false) + " " + digits[n%10]
+}
diff --git a/test/bench/chameneosredux.txt b/test/bench/shootout/chameneosredux.txt
similarity index 100%
rename from test/bench/chameneosredux.txt
rename to test/bench/shootout/chameneosredux.txt
diff --git a/test/bench/fannkuch-parallel.go b/test/bench/shootout/fannkuch-parallel.go
similarity index 100%
rename from test/bench/fannkuch-parallel.go
rename to test/bench/shootout/fannkuch-parallel.go
diff --git a/test/bench/fannkuch-parallel.txt b/test/bench/shootout/fannkuch-parallel.txt
similarity index 100%
rename from test/bench/fannkuch-parallel.txt
rename to test/bench/shootout/fannkuch-parallel.txt
diff --git a/test/bench/fannkuch.c b/test/bench/shootout/fannkuch.c
similarity index 100%
rename from test/bench/fannkuch.c
rename to test/bench/shootout/fannkuch.c
diff --git a/test/bench/fannkuch.go b/test/bench/shootout/fannkuch.go
similarity index 100%
rename from test/bench/fannkuch.go
rename to test/bench/shootout/fannkuch.go
diff --git a/test/bench/fannkuch.txt b/test/bench/shootout/fannkuch.txt
similarity index 100%
rename from test/bench/fannkuch.txt
rename to test/bench/shootout/fannkuch.txt
diff --git a/test/bench/fasta-1000.out b/test/bench/shootout/fasta-1000.out
similarity index 100%
rename from test/bench/fasta-1000.out
rename to test/bench/shootout/fasta-1000.out
diff --git a/test/bench/fasta.c b/test/bench/shootout/fasta.c
similarity index 100%
rename from test/bench/fasta.c
rename to test/bench/shootout/fasta.c
diff --git a/test/bench/shootout/fasta.go b/test/bench/shootout/fasta.go
new file mode 100644
index 0000000..17ff5da
--- /dev/null
+++ b/test/bench/shootout/fasta.go
@@ -0,0 +1,205 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ * Based on C program by by Petr Prokhorenkov.
+ */
+
+package main
+
+import (
+	"flag"
+	"os"
+)
+
+var out = make(buffer, 0, 32768)
+
+var n = flag.Int("n", 1000, "length of result")
+
+const Line = 60
+
+func Repeat(alu []byte, n int) {
+	buf := append(alu, alu...)
+	off := 0
+	for n > 0 {
+		m := n
+		if m > Line {
+			m = Line
+		}
+		buf1 := out.NextWrite(m + 1)
+		copy(buf1, buf[off:])
+		buf1[m] = '\n'
+		if off += m; off >= len(alu) {
+			off -= len(alu)
+		}
+		n -= m
+	}
+}
+
+const (
+	IM = 139968
+	IA = 3877
+	IC = 29573
+
+	LookupSize          = 4096
+	LookupScale float64 = LookupSize - 1
+)
+
+var rand uint32 = 42
+
+type Acid struct {
+	sym   byte
+	prob  float64
+	cprob float64
+	next  *Acid
+}
+
+func computeLookup(acid []Acid) *[LookupSize]*Acid {
+	var lookup [LookupSize]*Acid
+	var p float64
+	for i := range acid {
+		p += acid[i].prob
+		acid[i].cprob = p * LookupScale
+		if i > 0 {
+			acid[i-1].next = &acid[i]
+		}
+	}
+	acid[len(acid)-1].cprob = 1.0 * LookupScale
+
+	j := 0
+	for i := range lookup {
+		for acid[j].cprob < float64(i) {
+			j++
+		}
+		lookup[i] = &acid[j]
+	}
+
+	return &lookup
+}
+
+func Random(acid []Acid, n int) {
+	lookup := computeLookup(acid)
+	for n > 0 {
+		m := n
+		if m > Line {
+			m = Line
+		}
+		buf := out.NextWrite(m + 1)
+		f := LookupScale / IM
+		myrand := rand
+		for i := 0; i < m; i++ {
+			myrand = (myrand*IA + IC) % IM
+			r := float64(int(myrand)) * f
+			a := lookup[int(r)]
+			for a.cprob < r {
+				a = a.next
+			}
+			buf[i] = a.sym
+		}
+		rand = myrand
+		buf[m] = '\n'
+		n -= m
+	}
+}
+
+func main() {
+	defer out.Flush()
+
+	flag.Parse()
+
+	iub := []Acid{
+		{prob: 0.27, sym: 'a'},
+		{prob: 0.12, sym: 'c'},
+		{prob: 0.12, sym: 'g'},
+		{prob: 0.27, sym: 't'},
+		{prob: 0.02, sym: 'B'},
+		{prob: 0.02, sym: 'D'},
+		{prob: 0.02, sym: 'H'},
+		{prob: 0.02, sym: 'K'},
+		{prob: 0.02, sym: 'M'},
+		{prob: 0.02, sym: 'N'},
+		{prob: 0.02, sym: 'R'},
+		{prob: 0.02, sym: 'S'},
+		{prob: 0.02, sym: 'V'},
+		{prob: 0.02, sym: 'W'},
+		{prob: 0.02, sym: 'Y'},
+	}
+
+	homosapiens := []Acid{
+		{prob: 0.3029549426680, sym: 'a'},
+		{prob: 0.1979883004921, sym: 'c'},
+		{prob: 0.1975473066391, sym: 'g'},
+		{prob: 0.3015094502008, sym: 't'},
+	}
+
+	alu := []byte(
+		"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
+			"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
+			"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
+			"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
+			"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
+			"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
+			"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA")
+
+	out.WriteString(">ONE Homo sapiens alu\n")
+	Repeat(alu, 2**n)
+	out.WriteString(">TWO IUB ambiguity codes\n")
+	Random(iub, 3**n)
+	out.WriteString(">THREE Homo sapiens frequency\n")
+	Random(homosapiens, 5**n)
+}
+
+type buffer []byte
+
+func (b *buffer) Flush() {
+	p := *b
+	if len(p) > 0 {
+		os.Stdout.Write(p)
+	}
+	*b = p[0:0]
+}
+
+func (b *buffer) WriteString(s string) {
+	p := b.NextWrite(len(s))
+	copy(p, s)
+}
+
+func (b *buffer) NextWrite(n int) []byte {
+	p := *b
+	if len(p)+n > cap(p) {
+		b.Flush()
+		p = *b
+	}
+	out := p[len(p) : len(p)+n]
+	*b = p[:len(p)+n]
+	return out
+}
diff --git a/test/bench/fasta.txt b/test/bench/shootout/fasta.txt
similarity index 100%
rename from test/bench/fasta.txt
rename to test/bench/shootout/fasta.txt
diff --git a/test/bench/k-nucleotide-parallel.go b/test/bench/shootout/k-nucleotide-parallel.go
similarity index 100%
rename from test/bench/k-nucleotide-parallel.go
rename to test/bench/shootout/k-nucleotide-parallel.go
diff --git a/test/bench/k-nucleotide-parallel.txt b/test/bench/shootout/k-nucleotide-parallel.txt
similarity index 100%
rename from test/bench/k-nucleotide-parallel.txt
rename to test/bench/shootout/k-nucleotide-parallel.txt
diff --git a/test/bench/k-nucleotide.c b/test/bench/shootout/k-nucleotide.c
similarity index 100%
rename from test/bench/k-nucleotide.c
rename to test/bench/shootout/k-nucleotide.c
diff --git a/test/bench/k-nucleotide.go b/test/bench/shootout/k-nucleotide.go
similarity index 100%
rename from test/bench/k-nucleotide.go
rename to test/bench/shootout/k-nucleotide.go
diff --git a/test/bench/k-nucleotide.txt b/test/bench/shootout/k-nucleotide.txt
similarity index 100%
rename from test/bench/k-nucleotide.txt
rename to test/bench/shootout/k-nucleotide.txt
diff --git a/test/bench/mandelbrot.c b/test/bench/shootout/mandelbrot.c
similarity index 100%
rename from test/bench/mandelbrot.c
rename to test/bench/shootout/mandelbrot.c
diff --git a/test/bench/mandelbrot.go b/test/bench/shootout/mandelbrot.go
similarity index 100%
rename from test/bench/mandelbrot.go
rename to test/bench/shootout/mandelbrot.go
diff --git a/test/bench/mandelbrot.txt b/test/bench/shootout/mandelbrot.txt
similarity index 100%
rename from test/bench/mandelbrot.txt
rename to test/bench/shootout/mandelbrot.txt
diff --git a/test/bench/meteor-contest.c b/test/bench/shootout/meteor-contest.c
similarity index 100%
rename from test/bench/meteor-contest.c
rename to test/bench/shootout/meteor-contest.c
diff --git a/test/bench/shootout/meteor-contest.go b/test/bench/shootout/meteor-contest.go
new file mode 100644
index 0000000..34a4e23
--- /dev/null
+++ b/test/bench/shootout/meteor-contest.go
@@ -0,0 +1,656 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ * based on meteor-contest.c by Christian Vosteen
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+)
+
+var max_solutions = flag.Int("n", 2100, "maximum number of solutions")
+
+func boolInt(b bool) int8 {
+	if b {
+		return 1
+	}
+	return 0
+}
+
+/* The board is a 50 cell hexagonal pattern.  For    . . . . .
+ * maximum speed the board will be implemented as     . . . . .
+ * 50 bits, which will fit into a 64 bit long long   . . . . .
+ * int.                                               . . . . .
+ *                                                   . . . . .
+ * I will represent 0's as empty cells and 1's        . . . . .
+ * as full cells.                                    . . . . .
+ *                                                    . . . . .
+ *                                                   . . . . .
+ *                                                    . . . . .
+ */
+
+var board uint64 = 0xFFFC000000000000
+
+/* The puzzle pieces must be specified by the path followed
+ * from one end to the other along 12 hexagonal directions.
+ *
+ *   Piece 0   Piece 1   Piece 2   Piece 3   Piece 4
+ *
+ *  O O O O    O   O O   O O O     O O O     O   O
+ *         O    O O           O       O       O O
+ *                           O         O         O
+ *
+ *   Piece 5   Piece 6   Piece 7   Piece 8   Piece 9
+ *
+ *    O O O     O O       O O     O O        O O O O
+ *       O O       O O       O       O O O        O
+ *                  O       O O
+ *
+ * I had to make it 12 directions because I wanted all of the
+ * piece definitions to fit into the same size arrays.  It is
+ * not possible to define piece 4 in terms of the 6 cardinal
+ * directions in 4 moves.
+ */
+
+const (
+	E = iota
+	ESE
+	SE
+	S
+	SW
+	WSW
+	W
+	WNW
+	NW
+	N
+	NE
+	ENE
+	PIVOT
+)
+
+var piece_def = [10][4]int8{
+	[4]int8{E, E, E, SE},
+	[4]int8{SE, E, NE, E},
+	[4]int8{E, E, SE, SW},
+	[4]int8{E, E, SW, SE},
+	[4]int8{SE, E, NE, S},
+	[4]int8{E, E, SW, E},
+	[4]int8{E, SE, SE, NE},
+	[4]int8{E, SE, SE, W},
+	[4]int8{E, SE, E, E},
+	[4]int8{E, E, E, SW},
+}
+
+/* To minimize the amount of work done in the recursive solve function below,
+ * I'm going to allocate enough space for all legal rotations of each piece
+ * at each position on the board. That's 10 pieces x 50 board positions x
+ * 12 rotations.  However, not all 12 rotations will fit on every cell, so
+ * I'll have to keep count of the actual number that do.
+ * The pieces are going to be unsigned long long ints just like the board so
+ * they can be bitwise-anded with the board to determine if they fit.
+ * I'm also going to record the next possible open cell for each piece and
+ * location to reduce the burden on the solve function.
+ */
+var (
+	pieces       [10][50][12]uint64
+	piece_counts [10][50]int
+	next_cell    [10][50][12]int8
+)
+
+/* Returns the direction rotated 60 degrees clockwise */
+func rotate(dir int8) int8 { return (dir + 2) % PIVOT }
+
+/* Returns the direction flipped on the horizontal axis */
+func flip(dir int8) int8 { return (PIVOT - dir) % PIVOT }
+
+/* Returns the new cell index from the specified cell in the
+ * specified direction.  The index is only valid if the
+ * starting cell and direction have been checked by the
+ * out_of_bounds function first.
+ */
+func shift(cell, dir int8) int8 {
+	switch dir {
+	case E:
+		return cell + 1
+	case ESE:
+		if ((cell / 5) % 2) != 0 {
+			return cell + 7
+		} else {
+			return cell + 6
+		}
+	case SE:
+		if ((cell / 5) % 2) != 0 {
+			return cell + 6
+		} else {
+			return cell + 5
+		}
+	case S:
+		return cell + 10
+	case SW:
+		if ((cell / 5) % 2) != 0 {
+			return cell + 5
+		} else {
+			return cell + 4
+		}
+	case WSW:
+		if ((cell / 5) % 2) != 0 {
+			return cell + 4
+		} else {
+			return cell + 3
+		}
+	case W:
+		return cell - 1
+	case WNW:
+		if ((cell / 5) % 2) != 0 {
+			return cell - 6
+		} else {
+			return cell - 7
+		}
+	case NW:
+		if ((cell / 5) % 2) != 0 {
+			return cell - 5
+		} else {
+			return cell - 6
+		}
+	case N:
+		return cell - 10
+	case NE:
+		if ((cell / 5) % 2) != 0 {
+			return cell - 4
+		} else {
+			return cell - 5
+		}
+	case ENE:
+		if ((cell / 5) % 2) != 0 {
+			return cell - 3
+		} else {
+			return cell - 4
+		}
+	}
+	return cell
+}
+
+/* Returns wether the specified cell and direction will land outside
+ * of the board.  Used to determine if a piece is at a legal board
+ * location or not.
+ */
+func out_of_bounds(cell, dir int8) bool {
+	switch dir {
+	case E:
+		return cell%5 == 4
+	case ESE:
+		i := cell % 10
+		return i == 4 || i == 8 || i == 9 || cell >= 45
+	case SE:
+		return cell%10 == 9 || cell >= 45
+	case S:
+		return cell >= 40
+	case SW:
+		return cell%10 == 0 || cell >= 45
+	case WSW:
+		i := cell % 10
+		return i == 0 || i == 1 || i == 5 || cell >= 45
+	case W:
+		return cell%5 == 0
+	case WNW:
+		i := cell % 10
+		return i == 0 || i == 1 || i == 5 || cell < 5
+	case NW:
+		return cell%10 == 0 || cell < 5
+	case N:
+		return cell < 10
+	case NE:
+		return cell%10 == 9 || cell < 5
+	case ENE:
+		i := cell % 10
+		return i == 4 || i == 8 || i == 9 || cell < 5
+	}
+	return false
+}
+
+/* Rotate a piece 60 degrees clockwise */
+func rotate_piece(piece int) {
+	for i := 0; i < 4; i++ {
+		piece_def[piece][i] = rotate(piece_def[piece][i])
+	}
+}
+
+/* Flip a piece along the horizontal axis */
+func flip_piece(piece int) {
+	for i := 0; i < 4; i++ {
+		piece_def[piece][i] = flip(piece_def[piece][i])
+	}
+}
+
+/* Convenience function to quickly calculate all of the indices for a piece */
+func calc_cell_indices(cell []int8, piece int, index int8) {
+	cell[0] = index
+	for i := 1; i < 5; i++ {
+		cell[i] = shift(cell[i-1], piece_def[piece][i-1])
+	}
+}
+
+/* Convenience function to quickly calculate if a piece fits on the board */
+func cells_fit_on_board(cell []int8, piece int) bool {
+	return !out_of_bounds(cell[0], piece_def[piece][0]) &&
+		!out_of_bounds(cell[1], piece_def[piece][1]) &&
+		!out_of_bounds(cell[2], piece_def[piece][2]) &&
+		!out_of_bounds(cell[3], piece_def[piece][3])
+}
+
+/* Returns the lowest index of the cells of a piece.
+ * I use the lowest index that a piece occupies as the index for looking up
+ * the piece in the solve function.
+ */
+func minimum_of_cells(cell []int8) int8 {
+	minimum := cell[0]
+	for i := 1; i < 5; i++ {
+		if cell[i] < minimum {
+			minimum = cell[i]
+		}
+	}
+	return minimum
+}
+
+/* Calculate the lowest possible open cell if the piece is placed on the board.
+ * Used to later reduce the amount of time searching for open cells in the
+ * solve function.
+ */
+func first_empty_cell(cell []int8, minimum int8) int8 {
+	first_empty := minimum
+	for first_empty == cell[0] || first_empty == cell[1] ||
+		first_empty == cell[2] || first_empty == cell[3] ||
+		first_empty == cell[4] {
+		first_empty++
+	}
+	return first_empty
+}
+
+/* Generate the unsigned long long int that will later be anded with the
+ * board to determine if it fits.
+ */
+func bitmask_from_cells(cell []int8) uint64 {
+	var piece_mask uint64
+	for i := 0; i < 5; i++ {
+		piece_mask |= 1 << uint(cell[i])
+	}
+	return piece_mask
+}
+
+/* Record the piece and other important information in arrays that will
+ * later be used by the solve function.
+ */
+func record_piece(piece int, minimum int8, first_empty int8, piece_mask uint64) {
+	pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask
+	next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty
+	piece_counts[piece][minimum]++
+}
+
+/* Fill the entire board going cell by cell.  If any cells are "trapped"
+ * they will be left alone.
+ */
+func fill_contiguous_space(board []int8, index int8) {
+	if board[index] == 1 {
+		return
+	}
+	board[index] = 1
+	if !out_of_bounds(index, E) {
+		fill_contiguous_space(board, shift(index, E))
+	}
+	if !out_of_bounds(index, SE) {
+		fill_contiguous_space(board, shift(index, SE))
+	}
+	if !out_of_bounds(index, SW) {
+		fill_contiguous_space(board, shift(index, SW))
+	}
+	if !out_of_bounds(index, W) {
+		fill_contiguous_space(board, shift(index, W))
+	}
+	if !out_of_bounds(index, NW) {
+		fill_contiguous_space(board, shift(index, NW))
+	}
+	if !out_of_bounds(index, NE) {
+		fill_contiguous_space(board, shift(index, NE))
+	}
+}
+
+/* To thin the number of pieces, I calculate if any of them trap any empty
+ * cells at the edges.  There are only a handful of exceptions where the
+ * the board can be solved with the trapped cells.  For example:  piece 8 can
+ * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0
+ * can split the board in half where both halves are viable.
+ */
+func has_island(cell []int8, piece int) bool {
+	temp_board := make([]int8, 50)
+	var i int
+	for i = 0; i < 5; i++ {
+		temp_board[cell[i]] = 1
+	}
+	i = 49
+	for temp_board[i] == 1 {
+		i--
+	}
+	fill_contiguous_space(temp_board, int8(i))
+	c := 0
+	for i = 0; i < 50; i++ {
+		if temp_board[i] == 0 {
+			c++
+		}
+	}
+	if c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) ||
+		(c%5 == 0 && piece == 0) {
+		return false
+	}
+	return true
+}
+
+/* Calculate all six rotations of the specified piece at the specified index.
+ * We calculate only half of piece 3's rotations.  This is because any solution
+ * found has an identical solution rotated 180 degrees.  Thus we can reduce the
+ * number of attempted pieces in the solve algorithm by not including the 180-
+ * degree-rotated pieces of ONE of the pieces.  I chose piece 3 because it gave
+ * me the best time ;)
+ */
+func calc_six_rotations(piece, index int) {
+	cell := make([]int8, 5)
+	for rotation := 0; rotation < 6; rotation++ {
+		if piece != 3 || rotation < 3 {
+			calc_cell_indices(cell, piece, int8(index))
+			if cells_fit_on_board(cell, piece) && !has_island(cell, piece) {
+				minimum := minimum_of_cells(cell)
+				first_empty := first_empty_cell(cell, minimum)
+				piece_mask := bitmask_from_cells(cell)
+				record_piece(piece, minimum, first_empty, piece_mask)
+			}
+		}
+		rotate_piece(piece)
+	}
+}
+
+/* Calculate every legal rotation for each piece at each board location. */
+func calc_pieces() {
+	for piece := 0; piece < 10; piece++ {
+		for index := 0; index < 50; index++ {
+			calc_six_rotations(piece, index)
+			flip_piece(piece)
+			calc_six_rotations(piece, index)
+		}
+	}
+}
+
+/* Calculate all 32 possible states for a 5-bit row and all rows that will
+ * create islands that follow any of the 32 possible rows.  These pre-
+ * calculated 5-bit rows will be used to find islands in a partially solved
+ * board in the solve function.
+ */
+const (
+	ROW_MASK    = 0x1F
+	TRIPLE_MASK = 0x7FFF
+)
+
+var (
+	all_rows = [32]int8{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,
+	}
+	bad_even_rows   [32][32]int8
+	bad_odd_rows    [32][32]int8
+	bad_even_triple [32768]int8
+	bad_odd_triple  [32768]int8
+)
+
+func rows_bad(row1, row2 int8, even bool) int8 {
+	/* even is referring to row1 */
+	var row2_shift int8
+	/* Test for blockages at same index and shifted index */
+	if even {
+		row2_shift = ((row2 << 1) & ROW_MASK) | 0x01
+	} else {
+		row2_shift = (row2 >> 1) | 0x10
+	}
+	block := ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift)
+	/* Test for groups of 0's */
+	in_zeroes := false
+	group_okay := false
+	for i := uint8(0); i < 5; i++ {
+		if row1&(1<<i) != 0 {
+			if in_zeroes {
+				if !group_okay {
+					return 1
+				}
+				in_zeroes = false
+				group_okay = false
+			}
+		} else {
+			if !in_zeroes {
+				in_zeroes = true
+			}
+			if (block & (1 << i)) == 0 {
+				group_okay = true
+			}
+		}
+	}
+	if in_zeroes {
+		return boolInt(!group_okay)
+	}
+	return 0
+}
+
+/* Check for cases where three rows checked sequentially cause a false
+ * positive.  One scenario is when 5 cells may be surrounded where piece 5
+ * or 7 can fit.  The other scenario is when piece 2 creates a hook shape.
+ */
+func triple_is_okay(row1, row2, row3 int, even bool) bool {
+	if even {
+		/* There are four cases:
+		 * row1: 00011  00001  11001  10101
+		 * row2: 01011  00101  10001  10001
+		 * row3: 011??  00110  ?????  ?????
+		 */
+		return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) ||
+			((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) ||
+			((row1 == 0x19) && (row2 == 0x11)) ||
+			((row1 == 0x15) && (row2 == 0x11))
+	}
+	/* There are two cases:
+	 * row1: 10011  10101
+	 * row2: 10001  10001
+	 * row3: ?????  ?????
+	 */
+	return ((row1 == 0x13) && (row2 == 0x11)) ||
+		((row1 == 0x15) && (row2 == 0x11))
+}
+
+func calc_rows() {
+	for row1 := int8(0); row1 < 32; row1++ {
+		for row2 := int8(0); row2 < 32; row2++ {
+			bad_even_rows[row1][row2] = rows_bad(row1, row2, true)
+			bad_odd_rows[row1][row2] = rows_bad(row1, row2, false)
+		}
+	}
+	for row1 := 0; row1 < 32; row1++ {
+		for row2 := 0; row2 < 32; row2++ {
+			for row3 := 0; row3 < 32; row3++ {
+				result1 := bad_even_rows[row1][row2]
+				result2 := bad_odd_rows[row2][row3]
+				if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, true) {
+					bad_even_triple[row1+(row2*32)+(row3*1024)] = 0
+				} else {
+					bad_even_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0)
+				}
+
+				result1 = bad_odd_rows[row1][row2]
+				result2 = bad_even_rows[row2][row3]
+				if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, false) {
+					bad_odd_triple[row1+(row2*32)+(row3*1024)] = 0
+				} else {
+					bad_odd_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0)
+				}
+			}
+		}
+	}
+}
+
+/* Calculate islands while solving the board.
+ */
+func boardHasIslands(cell int8) int8 {
+	/* Too low on board, don't bother checking */
+	if cell >= 40 {
+		return 0
+	}
+	current_triple := (board >> uint((cell/5)*5)) & TRIPLE_MASK
+	if (cell/5)%2 != 0 {
+		return bad_odd_triple[current_triple]
+	}
+	return bad_even_triple[current_triple]
+}
+
+/* The recursive solve algorithm.  Try to place each permutation in the upper-
+ * leftmost empty cell.  Mark off available pieces as it goes along.
+ * Because the board is a bit mask, the piece number and bit mask must be saved
+ * at each successful piece placement.  This data is used to create a 50 char
+ * array if a solution is found.
+ */
+var (
+	avail          uint16 = 0x03FF
+	sol_nums       [10]int8
+	sol_masks      [10]uint64
+	solutions      [2100][50]int8
+	solution_count = 0
+)
+
+func record_solution() {
+	for sol_no := 0; sol_no < 10; sol_no++ {
+		sol_mask := sol_masks[sol_no]
+		for index := 0; index < 50; index++ {
+			if sol_mask&1 == 1 {
+				solutions[solution_count][index] = sol_nums[sol_no]
+				/* Board rotated 180 degrees is a solution too! */
+				solutions[solution_count+1][49-index] = sol_nums[sol_no]
+			}
+			sol_mask = sol_mask >> 1
+		}
+	}
+	solution_count += 2
+}
+
+func solve(depth, cell int8) {
+	if solution_count >= *max_solutions {
+		return
+	}
+
+	for board&(1<<uint(cell)) != 0 {
+		cell++
+	}
+
+	for piece := int8(0); piece < 10; piece++ {
+		var piece_no_mask uint16 = 1 << uint(piece)
+		if avail&piece_no_mask == 0 {
+			continue
+		}
+		avail ^= piece_no_mask
+		max_rots := piece_counts[piece][cell]
+		piece_mask := pieces[piece][cell]
+		for rotation := 0; rotation < max_rots; rotation++ {
+			if board&piece_mask[rotation] == 0 {
+				sol_nums[depth] = piece
+				sol_masks[depth] = piece_mask[rotation]
+				if depth == 9 {
+					/* Solution found!!!!!11!!ONE! */
+					record_solution()
+					avail ^= piece_no_mask
+					return
+				}
+				board |= piece_mask[rotation]
+				if boardHasIslands(next_cell[piece][cell][rotation]) == 0 {
+					solve(depth+1, next_cell[piece][cell][rotation])
+				}
+				board ^= piece_mask[rotation]
+			}
+		}
+		avail ^= piece_no_mask
+	}
+}
+
+/* pretty print a board in the specified hexagonal format */
+func pretty(b *[50]int8) {
+	for i := 0; i < 50; i += 10 {
+		fmt.Printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0',
+			b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0',
+			b[i+7]+'0', b[i+8]+'0', b[i+9]+'0')
+	}
+	fmt.Printf("\n")
+}
+
+/* Find smallest and largest solutions */
+func smallest_largest() (smallest, largest *[50]int8) {
+	smallest = &solutions[0]
+	largest = &solutions[0]
+	for i := 1; i < solution_count; i++ {
+		candidate := &solutions[i]
+		for j, s := range *smallest {
+			c := candidate[j]
+			if c == s {
+				continue
+			}
+			if c < s {
+				smallest = candidate
+			}
+			break
+		}
+		for j, s := range *largest {
+			c := candidate[j]
+			if c == s {
+				continue
+			}
+			if c > s {
+				largest = candidate
+			}
+			break
+		}
+	}
+	return
+}
+
+func main() {
+	flag.Parse()
+	calc_pieces()
+	calc_rows()
+	solve(0, 0)
+	fmt.Printf("%d solutions found\n\n", solution_count)
+	smallest, largest := smallest_largest()
+	pretty(smallest)
+	pretty(largest)
+}
diff --git a/test/bench/meteor-contest.txt b/test/bench/shootout/meteor-contest.txt
similarity index 100%
rename from test/bench/meteor-contest.txt
rename to test/bench/shootout/meteor-contest.txt
diff --git a/test/bench/nbody.c b/test/bench/shootout/nbody.c
similarity index 100%
rename from test/bench/nbody.c
rename to test/bench/shootout/nbody.c
diff --git a/test/bench/shootout/nbody.go b/test/bench/shootout/nbody.go
new file mode 100644
index 0000000..988f3ba
--- /dev/null
+++ b/test/bench/shootout/nbody.go
@@ -0,0 +1,177 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ * based on C program by Christoph Bauer
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"math"
+)
+
+var n = flag.Int("n", 1000, "number of iterations")
+
+type Body struct {
+	x, y, z, vx, vy, vz, mass float64
+}
+
+const (
+	solarMass   = 4 * math.Pi * math.Pi
+	daysPerYear = 365.24
+)
+
+func (b *Body) offsetMomentum(px, py, pz float64) {
+	b.vx = -px / solarMass
+	b.vy = -py / solarMass
+	b.vz = -pz / solarMass
+}
+
+type System []*Body
+
+func NewSystem(body []Body) System {
+	n := make(System, len(body))
+	for i := 0; i < len(body); i++ {
+		n[i] = new(Body) // copy to avoid overwriting the inputs
+		*n[i] = body[i]
+	}
+	var px, py, pz float64
+	for _, body := range n {
+		px += body.vx * body.mass
+		py += body.vy * body.mass
+		pz += body.vz * body.mass
+	}
+	n[0].offsetMomentum(px, py, pz)
+	return n
+}
+
+func (sys System) energy() float64 {
+	var e float64
+	for i, body := range sys {
+		e += 0.5 * body.mass *
+			(body.vx*body.vx + body.vy*body.vy + body.vz*body.vz)
+		for j := i + 1; j < len(sys); j++ {
+			body2 := sys[j]
+			dx := body.x - body2.x
+			dy := body.y - body2.y
+			dz := body.z - body2.z
+			distance := math.Sqrt(dx*dx + dy*dy + dz*dz)
+			e -= (body.mass * body2.mass) / distance
+		}
+	}
+	return e
+}
+
+func (sys System) advance(dt float64) {
+	for i, body := range sys {
+		for j := i + 1; j < len(sys); j++ {
+			body2 := sys[j]
+			dx := body.x - body2.x
+			dy := body.y - body2.y
+			dz := body.z - body2.z
+
+			dSquared := dx*dx + dy*dy + dz*dz
+			distance := math.Sqrt(dSquared)
+			mag := dt / (dSquared * distance)
+
+			body.vx -= dx * body2.mass * mag
+			body.vy -= dy * body2.mass * mag
+			body.vz -= dz * body2.mass * mag
+
+			body2.vx += dx * body.mass * mag
+			body2.vy += dy * body.mass * mag
+			body2.vz += dz * body.mass * mag
+		}
+	}
+
+	for _, body := range sys {
+		body.x += dt * body.vx
+		body.y += dt * body.vy
+		body.z += dt * body.vz
+	}
+}
+
+var (
+	jupiter = Body{
+		x:    4.84143144246472090e+00,
+		y:    -1.16032004402742839e+00,
+		z:    -1.03622044471123109e-01,
+		vx:   1.66007664274403694e-03 * daysPerYear,
+		vy:   7.69901118419740425e-03 * daysPerYear,
+		vz:   -6.90460016972063023e-05 * daysPerYear,
+		mass: 9.54791938424326609e-04 * solarMass,
+	}
+	saturn = Body{
+		x:    8.34336671824457987e+00,
+		y:    4.12479856412430479e+00,
+		z:    -4.03523417114321381e-01,
+		vx:   -2.76742510726862411e-03 * daysPerYear,
+		vy:   4.99852801234917238e-03 * daysPerYear,
+		vz:   2.30417297573763929e-05 * daysPerYear,
+		mass: 2.85885980666130812e-04 * solarMass,
+	}
+	uranus = Body{
+		x:    1.28943695621391310e+01,
+		y:    -1.51111514016986312e+01,
+		z:    -2.23307578892655734e-01,
+		vx:   2.96460137564761618e-03 * daysPerYear,
+		vy:   2.37847173959480950e-03 * daysPerYear,
+		vz:   -2.96589568540237556e-05 * daysPerYear,
+		mass: 4.36624404335156298e-05 * solarMass,
+	}
+	neptune = Body{
+		x:    1.53796971148509165e+01,
+		y:    -2.59193146099879641e+01,
+		z:    1.79258772950371181e-01,
+		vx:   2.68067772490389322e-03 * daysPerYear,
+		vy:   1.62824170038242295e-03 * daysPerYear,
+		vz:   -9.51592254519715870e-05 * daysPerYear,
+		mass: 5.15138902046611451e-05 * solarMass,
+	}
+	sun = Body{
+		mass: solarMass,
+	}
+)
+
+func main() {
+	flag.Parse()
+
+	system := NewSystem([]Body{sun, jupiter, saturn, uranus, neptune})
+	fmt.Printf("%.9f\n", system.energy())
+	for i := 0; i < *n; i++ {
+		system.advance(0.01)
+	}
+	fmt.Printf("%.9f\n", system.energy())
+}
diff --git a/test/bench/nbody.txt b/test/bench/shootout/nbody.txt
similarity index 100%
rename from test/bench/nbody.txt
rename to test/bench/shootout/nbody.txt
diff --git a/test/bench/pidigits.c b/test/bench/shootout/pidigits.c
similarity index 100%
rename from test/bench/pidigits.c
rename to test/bench/shootout/pidigits.c
diff --git a/test/bench/shootout/pidigits.go b/test/bench/shootout/pidigits.go
new file mode 100644
index 0000000..a0f21a9
--- /dev/null
+++ b/test/bench/shootout/pidigits.go
@@ -0,0 +1,135 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ * based on pidigits.c (by Paolo Bonzini & Sean Bartlett,
+ *                      modified by Michael Mellor)
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"math/big"
+)
+
+var n = flag.Int("n", 27, "number of digits")
+var silent = flag.Bool("s", false, "don't print result")
+
+var (
+	tmp1  = big.NewInt(0)
+	tmp2  = big.NewInt(0)
+	tmp3  = big.NewInt(0)
+	y2    = big.NewInt(0)
+	bigk  = big.NewInt(0)
+	numer = big.NewInt(1)
+	accum = big.NewInt(0)
+	denom = big.NewInt(1)
+	ten   = big.NewInt(10)
+)
+
+func extract_digit() int64 {
+	if numer.Cmp(accum) > 0 {
+		return -1
+	}
+
+	// Compute (numer * 3 + accum) / denom
+	tmp1.Lsh(numer, 1)
+	tmp1.Add(tmp1, numer)
+	tmp1.Add(tmp1, accum)
+	tmp1.DivMod(tmp1, denom, tmp2)
+
+	// Now, if (numer * 4 + accum) % denom...
+	tmp2.Add(tmp2, numer)
+
+	// ... is normalized, then the two divisions have the same result.
+	if tmp2.Cmp(denom) >= 0 {
+		return -1
+	}
+
+	return tmp1.Int64()
+}
+
+func next_term(k int64) {
+	y2.SetInt64(k*2 + 1)
+	bigk.SetInt64(k)
+
+	tmp1.Lsh(numer, 1)
+	accum.Add(accum, tmp1)
+	accum.Mul(accum, y2)
+	numer.Mul(numer, bigk)
+	denom.Mul(denom, y2)
+}
+
+func eliminate_digit(d int64) {
+	tmp3.SetInt64(d)
+	accum.Sub(accum, tmp3.Mul(denom, tmp3))
+	accum.Mul(accum, ten)
+	numer.Mul(numer, ten)
+}
+
+func printf(s string, arg ...interface{}) {
+	if !*silent {
+		fmt.Printf(s, arg...)
+	}
+}
+
+func main() {
+	flag.Parse()
+
+	var m int // 0 <= m < 10
+	for i, k := 0, int64(0); ; {
+		d := int64(-1)
+		for d < 0 {
+			k++
+			next_term(k)
+			d = extract_digit()
+		}
+
+		printf("%c", d+'0')
+
+		i++
+		m = i % 10
+		if m == 0 {
+			printf("\t:%d\n", i)
+		}
+		if i >= *n {
+			break
+		}
+		eliminate_digit(d)
+	}
+
+	if m > 0 {
+		printf("%s\t:%d\n", "          "[m:10], *n)
+	}
+}
diff --git a/test/bench/pidigits.txt b/test/bench/shootout/pidigits.txt
similarity index 100%
rename from test/bench/pidigits.txt
rename to test/bench/shootout/pidigits.txt
diff --git a/test/bench/shootout/regex-dna-parallel.go b/test/bench/shootout/regex-dna-parallel.go
new file mode 100644
index 0000000..9c6d421
--- /dev/null
+++ b/test/bench/shootout/regex-dna-parallel.go
@@ -0,0 +1,124 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ */
+
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"regexp"
+	"runtime"
+)
+
+var variants = []string{
+	"agggtaaa|tttaccct",
+	"[cgt]gggtaaa|tttaccc[acg]",
+	"a[act]ggtaaa|tttacc[agt]t",
+	"ag[act]gtaaa|tttac[agt]ct",
+	"agg[act]taaa|ttta[agt]cct",
+	"aggg[acg]aaa|ttt[cgt]ccct",
+	"agggt[cgt]aa|tt[acg]accct",
+	"agggta[cgt]a|t[acg]taccct",
+	"agggtaa[cgt]|[acg]ttaccct",
+}
+
+type Subst struct {
+	pat, repl string
+}
+
+var substs = []Subst{
+	Subst{"B", "(c|g|t)"},
+	Subst{"D", "(a|g|t)"},
+	Subst{"H", "(a|c|t)"},
+	Subst{"K", "(g|t)"},
+	Subst{"M", "(a|c)"},
+	Subst{"N", "(a|c|g|t)"},
+	Subst{"R", "(a|g)"},
+	Subst{"S", "(c|g)"},
+	Subst{"V", "(a|c|g)"},
+	Subst{"W", "(a|t)"},
+	Subst{"Y", "(c|t)"},
+}
+
+func countMatches(pat string, bytes []byte) int {
+	re := regexp.MustCompile(pat)
+	n := 0
+	for {
+		e := re.FindIndex(bytes)
+		if e == nil {
+			break
+		}
+		n++
+		bytes = bytes[e[1]:]
+	}
+	return n
+}
+
+func main() {
+	runtime.GOMAXPROCS(4)
+	bytes, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "can't read input: %s\n", err)
+		os.Exit(2)
+	}
+	ilen := len(bytes)
+	// Delete the comment lines and newlines
+	bytes = regexp.MustCompile("(>[^\n]+)?\n").ReplaceAll(bytes, []byte{})
+	clen := len(bytes)
+
+	mresults := make([]chan int, len(variants))
+	for i, s := range variants {
+		ch := make(chan int)
+		mresults[i] = ch
+		go func(ss string) {
+			ch <- countMatches(ss, bytes)
+		}(s)
+	}
+
+	lenresult := make(chan int)
+	bb := bytes
+	go func() {
+		for _, sub := range substs {
+			bb = regexp.MustCompile(sub.pat).ReplaceAll(bb, []byte(sub.repl))
+		}
+		lenresult <- len(bb)
+	}()
+
+	for i, s := range variants {
+		fmt.Printf("%s %d\n", s, <-mresults[i])
+	}
+	fmt.Printf("\n%d\n%d\n%d\n", ilen, clen, <-lenresult)
+}
diff --git a/test/bench/regex-dna-parallel.txt b/test/bench/shootout/regex-dna-parallel.txt
similarity index 100%
rename from test/bench/regex-dna-parallel.txt
rename to test/bench/shootout/regex-dna-parallel.txt
diff --git a/test/bench/regex-dna.c b/test/bench/shootout/regex-dna.c
similarity index 100%
rename from test/bench/regex-dna.c
rename to test/bench/shootout/regex-dna.c
diff --git a/test/bench/regex-dna.go b/test/bench/shootout/regex-dna.go
similarity index 100%
rename from test/bench/regex-dna.go
rename to test/bench/shootout/regex-dna.go
diff --git a/test/bench/regex-dna.txt b/test/bench/shootout/regex-dna.txt
similarity index 100%
rename from test/bench/regex-dna.txt
rename to test/bench/shootout/regex-dna.txt
diff --git a/test/bench/reverse-complement.c b/test/bench/shootout/reverse-complement.c
similarity index 100%
rename from test/bench/reverse-complement.c
rename to test/bench/shootout/reverse-complement.c
diff --git a/test/bench/reverse-complement.go b/test/bench/shootout/reverse-complement.go
similarity index 100%
rename from test/bench/reverse-complement.go
rename to test/bench/shootout/reverse-complement.go
diff --git a/test/bench/reverse-complement.txt b/test/bench/shootout/reverse-complement.txt
similarity index 100%
rename from test/bench/reverse-complement.txt
rename to test/bench/shootout/reverse-complement.txt
diff --git a/test/bench/spectral-norm-parallel.go b/test/bench/shootout/spectral-norm-parallel.go
similarity index 100%
rename from test/bench/spectral-norm-parallel.go
rename to test/bench/shootout/spectral-norm-parallel.go
diff --git a/test/bench/spectral-norm.c b/test/bench/shootout/spectral-norm.c
similarity index 100%
rename from test/bench/spectral-norm.c
rename to test/bench/shootout/spectral-norm.c
diff --git a/test/bench/spectral-norm.go b/test/bench/shootout/spectral-norm.go
similarity index 100%
rename from test/bench/spectral-norm.go
rename to test/bench/shootout/spectral-norm.go
diff --git a/test/bench/spectral-norm.txt b/test/bench/shootout/spectral-norm.txt
similarity index 100%
rename from test/bench/spectral-norm.txt
rename to test/bench/shootout/spectral-norm.txt
diff --git a/test/bench/threadring.c b/test/bench/shootout/threadring.c
similarity index 100%
rename from test/bench/threadring.c
rename to test/bench/shootout/threadring.c
diff --git a/test/bench/shootout/threadring.go b/test/bench/shootout/threadring.go
new file mode 100644
index 0000000..e76dd0b
--- /dev/null
+++ b/test/bench/shootout/threadring.go
@@ -0,0 +1,71 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"os"
+)
+
+var n = flag.Int("n", 1000, "how many passes")
+
+const Nthread = 503
+
+func f(i int, in <-chan int, out chan<- int) {
+	for {
+		n := <-in
+		if n == 0 {
+			fmt.Printf("%d\n", i)
+			os.Exit(0)
+		}
+		out <- n - 1
+	}
+}
+
+func main() {
+	flag.Parse()
+
+	one := make(chan int) // will be input to thread 1
+	var in, out chan int = nil, one
+	for i := 1; i <= Nthread-1; i++ {
+		in, out = out, make(chan int)
+		go f(i, in, out)
+	}
+	go f(Nthread, out, one)
+	one <- *n
+	<-make(chan int) // hang until ring completes
+}
diff --git a/test/bench/threadring.txt b/test/bench/shootout/threadring.txt
similarity index 100%
rename from test/bench/threadring.txt
rename to test/bench/shootout/threadring.txt
diff --git a/test/bench/timing.log b/test/bench/shootout/timing.log
similarity index 100%
rename from test/bench/timing.log
rename to test/bench/shootout/timing.log
diff --git a/test/bench/shootout/timing.sh b/test/bench/shootout/timing.sh
new file mode 100755
index 0000000..3e190e1
--- /dev/null
+++ b/test/bench/shootout/timing.sh
@@ -0,0 +1,205 @@
+#!/usr/bin/env bash
+# Copyright 2009 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+set -e
+
+eval $(gomake --no-print-directory -f ../../../src/Make.inc go-env)
+PATH=.:$PATH
+
+havegccgo=false
+if which gccgo >/dev/null 2>&1
+then
+	havegccgo=true
+fi
+
+mode=run
+case X"$1" in
+X-test)
+	mode=test
+	shift
+esac
+
+gc() {
+	$GC $1.go; $LD $1.$O
+}
+
+gc_B() {
+	$GC -B $1.go; $LD $1.$O
+}
+
+runonly() {
+	if [ $mode = run ]
+	then
+		"$@"
+	fi
+}
+
+run() {
+	if [ $mode = test ]
+	then
+		if echo $1 | grep -q '^gc '
+		then
+			$1	# compile the program
+			program=$(echo $1 | sed 's/gc //')
+			shift
+			echo $program
+			$1 <fasta-1000.out > /tmp/$$
+			case $program in
+			chameneosredux)
+				# exact numbers may vary but non-numbers should match
+				grep -v '[0-9]' /tmp/$$ > /tmp/$$x
+				grep -v '[0-9]' chameneosredux.txt > /tmp/$$y
+				cmp /tmp/$$x /tmp/$$y
+				rm -f /tmp/$$ /tmp/$$x /tmp/$$y
+				;;
+			*)
+				cmp /tmp/$$ $program.txt
+				rm -f /tmp/$$
+			esac
+		fi
+		return
+	fi
+	if ! $havegccgo && echo $1 | grep -q '^gccgo '
+	then
+		return
+	fi
+	echo -n '	'$1'	'
+	$1
+	shift
+	
+	echo $((time -p $* >/dev/null) 2>&1) | awk '{print $4 "u " $6 "s " $2 "r"}'
+}
+
+fasta() {
+	runonly echo 'fasta -n 25000000'
+	run 'gcc -O2 fasta.c' a.out 25000000
+	run 'gccgo -O2 fasta.go' a.out -n 25000000	#commented out until WriteString is in bufio
+	run 'gc fasta' $O.out -n 25000000
+	run 'gc_B fasta' $O.out -n 25000000
+}
+
+revcomp() {
+	runonly gcc -O2 fasta.c
+	runonly a.out 25000000 > x
+	runonly echo 'reverse-complement < output-of-fasta-25000000'
+	run 'gcc -O2 reverse-complement.c' a.out < x
+	run 'gccgo -O2 reverse-complement.go' a.out < x
+	run 'gc reverse-complement' $O.out < x
+	run 'gc_B reverse-complement' $O.out < x
+	rm x
+}
+
+nbody() {
+	runonly echo 'nbody -n 50000000'
+	run 'gcc -O2 -lm nbody.c' a.out 50000000
+	run 'gccgo -O2 nbody.go' a.out -n 50000000
+	run 'gc nbody' $O.out -n 50000000
+	run 'gc_B nbody' $O.out -n 50000000
+}
+
+binarytree() {
+	runonly echo 'binary-tree 15 # too slow to use 20'
+	run 'gcc -O2 binary-tree.c -lm' a.out 15
+	run 'gccgo -O2 binary-tree.go' a.out -n 15
+	run 'gccgo -O2 binary-tree-freelist.go' $O.out -n 15
+	run 'gc binary-tree' $O.out -n 15
+	run 'gc binary-tree-freelist' $O.out -n 15
+}
+
+fannkuch() {
+	runonly echo 'fannkuch 12'
+	run 'gcc -O2 fannkuch.c' a.out 12
+	run 'gccgo -O2 fannkuch.go' a.out -n 12
+	run 'gccgo -O2 fannkuch-parallel.go' a.out -n 12
+	run 'gc fannkuch' $O.out -n 12
+	run 'gc fannkuch-parallel' $O.out -n 12
+	run 'gc_B fannkuch' $O.out -n 12
+}
+
+regexdna() {
+	runonly gcc -O2 fasta.c
+	runonly a.out 100000 > x
+	runonly echo 'regex-dna 100000'
+	run 'gcc -O2 regex-dna.c -lpcre' a.out <x
+	run 'gccgo -O2 regex-dna.go' a.out <x
+	run 'gccgo -O2 regex-dna-parallel.go' a.out <x
+	run 'gc regex-dna' $O.out <x
+	run 'gc regex-dna-parallel' $O.out <x
+	run 'gc_B regex-dna' $O.out <x
+	rm x
+}
+
+spectralnorm() {
+	runonly echo 'spectral-norm 5500'
+	run 'gcc -O2 spectral-norm.c -lm' a.out 5500
+	run 'gccgo -O2 spectral-norm.go' a.out -n 5500
+	run 'gc spectral-norm' $O.out -n 5500
+	run 'gc_B spectral-norm' $O.out -n 5500
+}
+
+knucleotide() {
+	runonly gcc -O2 fasta.c
+	runonly a.out 1000000 > x  # should be using 25000000
+	runonly echo 'k-nucleotide 1000000'
+	run 'gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0' a.out <x
+	run 'gccgo -O2 k-nucleotide.go' a.out <x
+	run 'gccgo -O2 k-nucleotide-parallel.go' a.out <x
+	run 'gc k-nucleotide' $O.out <x
+	run 'gc k-nucleotide-parallel' $O.out <x
+	run 'gc_B k-nucleotide' $O.out <x
+	rm x
+}
+
+mandelbrot() {
+	runonly echo 'mandelbrot 16000'
+	run 'gcc -O2 mandelbrot.c' a.out 16000
+	run 'gccgo -O2 mandelbrot.go' a.out -n 16000
+	run 'gc mandelbrot' $O.out -n 16000
+	run 'gc_B mandelbrot' $O.out -n 16000
+}
+
+meteor() {
+	runonly echo 'meteor 2098'
+	run 'gcc -O2 meteor-contest.c' a.out 2098
+	run 'gccgo -O2 meteor-contest.go' a.out -n 2098
+	run 'gc meteor-contest' $O.out -n 2098
+	run 'gc_B  meteor-contest' $O.out -n 2098
+}
+
+pidigits() {
+	runonly echo 'pidigits 10000'
+	run 'gcc -O2 pidigits.c -lgmp' a.out 10000
+	run 'gccgo -O2 pidigits.go' a.out -n 10000
+	run 'gc pidigits' $O.out -n 10000
+	run 'gc_B  pidigits' $O.out -n 10000
+}
+
+threadring() {
+	runonly echo 'threadring 50000000'
+	run 'gcc -O2 threadring.c -lpthread' a.out 50000000
+	run 'gccgo -O2 threadring.go' a.out -n 50000000
+	run 'gc threadring' $O.out -n 50000000
+}
+
+chameneos() {
+	runonly echo 'chameneos 6000000'
+	run 'gcc -O2 chameneosredux.c -lpthread' a.out 6000000
+	run 'gccgo -O2 chameneosredux.go' a.out 6000000
+	run 'gc chameneosredux' $O.out 6000000
+}
+
+case $# in
+0)
+	run="fasta revcomp nbody binarytree fannkuch regexdna spectralnorm knucleotide mandelbrot meteor pidigits threadring chameneos"
+	;;
+*)
+	run=$*
+esac
+
+for i in $run
+do
+	$i
+	runonly echo
+done
diff --git a/test/bench/threadring.go b/test/bench/threadring.go
deleted file mode 100644
index 031908a..0000000
--- a/test/bench/threadring.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"os"
-)
-
-var n = flag.Int("n", 1000, "how many passes")
-
-const Nthread = 503
-
-func f(i int, in <-chan int, out chan<- int) {
-	for {
-		n := <-in
-		if n == 0 {
-			fmt.Printf("%d\n", i)
-			os.Exit(0)
-		}
-		out <- n-1
-	}
-}
-
-func main() {
-	flag.Parse()
-
-	one := make(chan int) // will be input to thread 1
-	var in, out chan int = nil, one
-	for i := 1; i <= Nthread-1; i++ {
-		in, out = out, make(chan int)
-		go f(i, in, out)
-	}
-	go f(Nthread, out, one)
-	one <- *n
-	<-make(chan int) // hang until ring completes
-}
diff --git a/test/bench/timing.sh b/test/bench/timing.sh
deleted file mode 100755
index 473c9b3..0000000
--- a/test/bench/timing.sh
+++ /dev/null
@@ -1,205 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2009 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-set -e
-
-eval $(gomake --no-print-directory -f ../../src/Make.inc go-env)
-PATH=.:$PATH
-
-havegccgo=false
-if which gccgo >/dev/null 2>&1
-then
-	havegccgo=true
-fi
-
-mode=run
-case X"$1" in
-X-test)
-	mode=test
-	shift
-esac
-
-gc() {
-	$GC $1.go; $LD $1.$O
-}
-
-gc_B() {
-	$GC -B $1.go; $LD $1.$O
-}
-
-runonly() {
-	if [ $mode = run ]
-	then
-		"$@"
-	fi
-}
-
-run() {
-	if [ $mode = test ]
-	then
-		if echo $1 | grep -q '^gc '
-		then
-			$1	# compile the program
-			program=$(echo $1 | sed 's/gc //')
-			shift
-			echo $program
-			$1 <fasta-1000.out > /tmp/$$
-			case $program in
-			chameneosredux)
-				# exact numbers may vary but non-numbers should match
-				grep -v '[0-9]' /tmp/$$ > /tmp/$$x
-				grep -v '[0-9]' chameneosredux.txt > /tmp/$$y
-				cmp /tmp/$$x /tmp/$$y
-				rm -f /tmp/$$ /tmp/$$x /tmp/$$y
-				;;
-			*)
-				cmp /tmp/$$ $program.txt
-				rm -f /tmp/$$
-			esac
-		fi
-		return
-	fi
-	if ! $havegccgo && echo $1 | grep -q '^gccgo '
-	then
-		return
-	fi
-	echo -n '	'$1'	'
-	$1
-	shift
-	
-	echo $((time -p $* >/dev/null) 2>&1) | awk '{print $4 "u " $6 "s " $2 "r"}'
-}
-
-fasta() {
-	runonly echo 'fasta -n 25000000'
-	run 'gcc -O2 fasta.c' a.out 25000000
-	run 'gccgo -O2 fasta.go' a.out -n 25000000	#commented out until WriteString is in bufio
-	run 'gc fasta' $O.out -n 25000000
-	run 'gc_B fasta' $O.out -n 25000000
-}
-
-revcomp() {
-	runonly gcc -O2 fasta.c
-	runonly a.out 25000000 > x
-	runonly echo 'reverse-complement < output-of-fasta-25000000'
-	run 'gcc -O2 reverse-complement.c' a.out < x
-	run 'gccgo -O2 reverse-complement.go' a.out < x
-	run 'gc reverse-complement' $O.out < x
-	run 'gc_B reverse-complement' $O.out < x
-	rm x
-}
-
-nbody() {
-	runonly echo 'nbody -n 50000000'
-	run 'gcc -O2 -lm nbody.c' a.out 50000000
-	run 'gccgo -O2 nbody.go' a.out -n 50000000
-	run 'gc nbody' $O.out -n 50000000
-	run 'gc_B nbody' $O.out -n 50000000
-}
-
-binarytree() {
-	runonly echo 'binary-tree 15 # too slow to use 20'
-	run 'gcc -O2 binary-tree.c -lm' a.out 15
-	run 'gccgo -O2 binary-tree.go' a.out -n 15
-	run 'gccgo -O2 binary-tree-freelist.go' $O.out -n 15
-	run 'gc binary-tree' $O.out -n 15
-	run 'gc binary-tree-freelist' $O.out -n 15
-}
-
-fannkuch() {
-	runonly echo 'fannkuch 12'
-	run 'gcc -O2 fannkuch.c' a.out 12
-	run 'gccgo -O2 fannkuch.go' a.out -n 12
-	run 'gccgo -O2 fannkuch-parallel.go' a.out -n 12
-	run 'gc fannkuch' $O.out -n 12
-	run 'gc fannkuch-parallel' $O.out -n 12
-	run 'gc_B fannkuch' $O.out -n 12
-}
-
-regexdna() {
-	runonly gcc -O2 fasta.c
-	runonly a.out 100000 > x
-	runonly echo 'regex-dna 100000'
-	run 'gcc -O2 regex-dna.c -lpcre' a.out <x
-	run 'gccgo -O2 regex-dna.go' a.out <x
-	run 'gccgo -O2 regex-dna-parallel.go' a.out <x
-	run 'gc regex-dna' $O.out <x
-	run 'gc regex-dna-parallel' $O.out <x
-	run 'gc_B regex-dna' $O.out <x
-	rm x
-}
-
-spectralnorm() {
-	runonly echo 'spectral-norm 5500'
-	run 'gcc -O2 spectral-norm.c -lm' a.out 5500
-	run 'gccgo -O2 spectral-norm.go' a.out -n 5500
-	run 'gc spectral-norm' $O.out -n 5500
-	run 'gc_B spectral-norm' $O.out -n 5500
-}
-
-knucleotide() {
-	runonly gcc -O2 fasta.c
-	runonly a.out 1000000 > x  # should be using 25000000
-	runonly echo 'k-nucleotide 1000000'
-	run 'gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0' a.out <x
-	run 'gccgo -O2 k-nucleotide.go' a.out <x
-	run 'gccgo -O2 k-nucleotide-parallel.go' a.out <x
-	run 'gc k-nucleotide' $O.out <x
-	run 'gc k-nucleotide-parallel' $O.out <x
-	run 'gc_B k-nucleotide' $O.out <x
-	rm x
-}
-
-mandelbrot() {
-	runonly echo 'mandelbrot 16000'
-	run 'gcc -O2 mandelbrot.c' a.out 16000
-	run 'gccgo -O2 mandelbrot.go' a.out -n 16000
-	run 'gc mandelbrot' $O.out -n 16000
-	run 'gc_B mandelbrot' $O.out -n 16000
-}
-
-meteor() {
-	runonly echo 'meteor 2098'
-	run 'gcc -O2 meteor-contest.c' a.out 2098
-	run 'gccgo -O2 meteor-contest.go' a.out -n 2098
-	run 'gc meteor-contest' $O.out -n 2098
-	run 'gc_B  meteor-contest' $O.out -n 2098
-}
-
-pidigits() {
-	runonly echo 'pidigits 10000'
-	run 'gcc -O2 pidigits.c -lgmp' a.out 10000
-	run 'gccgo -O2 pidigits.go' a.out -n 10000
-	run 'gc pidigits' $O.out -n 10000
-	run 'gc_B  pidigits' $O.out -n 10000
-}
-
-threadring() {
-	runonly echo 'threadring 50000000'
-	run 'gcc -O2 threadring.c -lpthread' a.out 50000000
-	run 'gccgo -O2 threadring.go' a.out -n 50000000
-	run 'gc threadring' $O.out -n 50000000
-}
-
-chameneos() {
-	runonly echo 'chameneos 6000000'
-	run 'gcc -O2 chameneosredux.c -lpthread' a.out 6000000
-	run 'gccgo -O2 chameneosredux.go' a.out 6000000
-	run 'gc chameneosredux' $O.out 6000000
-}
-
-case $# in
-0)
-	run="fasta revcomp nbody binarytree fannkuch regexdna spectralnorm knucleotide mandelbrot meteor pidigits threadring chameneos"
-	;;
-*)
-	run=$*
-esac
-
-for i in $run
-do
-	$i
-	runonly echo
-done
diff --git a/test/blank.go b/test/blank.go
index 681a5e7..d6c9e79 100644
--- a/test/blank.go
+++ b/test/blank.go
@@ -101,6 +101,46 @@ func main() {
 	}
 
 	h(a, b)
+	
+	m()
+}
+
+type I interface {
+	M(_ int, y int)
+}
+
+type TI struct{}
+
+func (TI) M(x int, y int) {
+	if x != y {
+		println("invalid M call:", x, y)
+		panic("bad M")
+	}
+}
+
+var fp = func(_ int, y int) {}
+
+func init() {
+	fp = fp1
+}
+
+func fp1(x, y int) {
+	if x != y {
+		println("invalid fp1 call:", x, y)
+		panic("bad fp1")
+	}
+}
+
+
+func m() {
+	var i I
+	
+	i = TI{}
+	i.M(1, 1)
+	i.M(2, 2)
+	
+	fp(1, 1)
+	fp(2, 2)
 }
 
 // useless but legal
@@ -120,3 +160,4 @@ func _() {
 func ff() {
 	var _ int = 1
 }
+
diff --git a/test/blank1.go b/test/blank1.go
index 5bc1efc..bcc7846 100644
--- a/test/blank1.go
+++ b/test/blank1.go
@@ -9,4 +9,5 @@ package _	// ERROR "invalid package name _"
 func main() {
 	_()	// ERROR "cannot use _ as value"
 	x := _+1	// ERROR "cannot use _ as value"
+	_ = x
 }
diff --git a/test/bugs/bug367.dir/main.go b/test/bugs/bug367.dir/main.go
deleted file mode 100644
index ab5d170..0000000
--- a/test/bugs/bug367.dir/main.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package main
-
-import (
-	"./p"
-)
-
-type T struct{ *p.S }
-
-func main() {
-	var t T
-	p.F(t)
-}
diff --git a/test/bugs/bug367.dir/p.go b/test/bugs/bug367.dir/p.go
deleted file mode 100644
index 4e27d4e..0000000
--- a/test/bugs/bug367.dir/p.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package p
-
-type T struct{ x int }
-type S struct{}
-
-func (p *S) get() T {
-	return T{0}
-}
-
-type I interface {
-	get() T
-}
-
-func F(i I) {
-	_ = i.get()
-}
diff --git a/test/bugs/bug367.go b/test/bugs/bug367.go
deleted file mode 100644
index 073e3b1..0000000
--- a/test/bugs/bug367.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out || echo BUG: should not fail
-
-// Copyright 2011 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.
-
-ignored
diff --git a/test/bugs/bug395.go b/test/bugs/bug395.go
new file mode 100644
index 0000000..adf7449
--- /dev/null
+++ b/test/bugs/bug395.go
@@ -0,0 +1,22 @@
+// echo bug395 is broken  # takes 90+ seconds to break
+// # $G $D/$F.go || echo bug395
+
+// Copyright 2011 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 1909
+// Would OOM due to exponential recursion on Foo's expanded methodset in nodefmt
+package test
+
+type Foo interface {
+	Bar() interface {
+		Foo
+	}
+	Baz() interface {
+		Foo
+	}
+	Bug() interface {
+		Foo
+	}
+}
diff --git a/test/chan/doubleselect.go b/test/chan/doubleselect.go
index 3c7412e..f8d50c9 100644
--- a/test/chan/doubleselect.go
+++ b/test/chan/doubleselect.go
@@ -82,5 +82,4 @@ func main() {
 	// However, the result of the bug linked to at the top is that we'll
 	// end up panicking with: "throw: bad g->status in ready".
 	recver(cmux)
-	print("PASS\n")
 }
diff --git a/test/chan/goroutines.go b/test/chan/goroutines.go
index d8f8803..371a173 100644
--- a/test/chan/goroutines.go
+++ b/test/chan/goroutines.go
@@ -21,7 +21,7 @@ func f(left, right chan int) {
 func main() {
 	var n = 10000
 	if len(os.Args) > 1 {
-		var err os.Error
+		var err error
 		n, err = strconv.Atoi(os.Args[1])
 		if err != nil {
 			print("bad arg\n")
diff --git a/test/chan/nonblock.go b/test/chan/nonblock.go
index 33afb32..9addf12 100644
--- a/test/chan/nonblock.go
+++ b/test/chan/nonblock.go
@@ -279,5 +279,4 @@ func main() {
 			<-sync
 		}
 	}
-	print("PASS\n")
 }
diff --git a/test/chan/perm.go b/test/chan/perm.go
index 038ff94..a43df19 100644
--- a/test/chan/perm.go
+++ b/test/chan/perm.go
@@ -48,4 +48,11 @@ func main() {
 	case x := <-cs: // ERROR "receive"
 		_ = x
 	}
+
+	for _ = range cs {// ERROR "receive"
+	}
+
+	close(c)
+	close(cs)
+	close(cr)  // ERROR "receive"
 }
diff --git a/test/chan/select4.go b/test/chan/select4.go
index 46618ac..26a55e6 100644
--- a/test/chan/select4.go
+++ b/test/chan/select4.go
@@ -1,5 +1,9 @@
 // $G $D/$F.go && $L $F.$A && ./$A.out
 
+// Copyright 2010 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
 
 func f() *int {
diff --git a/test/chan/select5.go b/test/chan/select5.go
index 6071821..cc2cc71 100644
--- a/test/chan/select5.go
+++ b/test/chan/select5.go
@@ -18,7 +18,7 @@ import (
 	"fmt"
 	"io"
 	"os"
-	"template"
+	"text/template"
 )
 
 func main() {
diff --git a/test/chan/select7.go b/test/chan/select7.go
new file mode 100644
index 0000000..5fed6cb
--- /dev/null
+++ b/test/chan/select7.go
@@ -0,0 +1,68 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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 select when discarding a value.
+
+package main
+
+import "runtime"
+
+func recv1(c <-chan int) {
+	<-c
+}
+
+func recv2(c <-chan int) {
+	select {
+	case <-c:
+	}
+}
+
+func recv3(c <-chan int) {
+	c2 := make(chan int)
+	select {
+	case <-c:
+	case <-c2:
+	}
+}
+
+func send1(recv func(<-chan int)) {
+	c := make(chan int)
+	go recv(c)
+	runtime.Gosched()
+	c <- 1
+}
+
+func send2(recv func(<-chan int)) {
+	c := make(chan int)
+	go recv(c)
+	runtime.Gosched()
+	select {
+	case c <- 1:
+	}
+}
+
+func send3(recv func(<-chan int)) {
+	c := make(chan int)
+	go recv(c)
+	runtime.Gosched()
+	c2 := make(chan int)
+	select {
+	case c <- 1:
+	case c2 <- 1:
+	}
+}
+
+func main() {
+	send1(recv1)
+	send2(recv1)
+	send3(recv1)
+	send1(recv2)
+	send2(recv2)
+	send3(recv2)
+	send1(recv3)
+	send2(recv3)
+	send3(recv3)
+}
diff --git a/test/closedchan.go b/test/closedchan.go
index 95314b3..c2bbec5 100644
--- a/test/closedchan.go
+++ b/test/closedchan.go
@@ -11,6 +11,10 @@
 
 package main
 
+import "os"
+
+var failed bool
+
 type Chan interface {
 	Send(int)
 	Nbsend(int) bool
@@ -225,19 +229,23 @@ func test1(c Chan) {
 		// recv a close signal (a zero value)
 		if x := c.Recv(); x != 0 {
 			println("test1: recv on closed:", x, c.Impl())
+			failed = true
 		}
 		if x, ok := c.Recv2(); x != 0 || ok {
 			println("test1: recv2 on closed:", x, ok, c.Impl())
+			failed = true
 		}
 
 		// should work with select: received a value without blocking, so selected == true.
 		x, selected := c.Nbrecv()
 		if x != 0 || !selected {
 			println("test1: recv on closed nb:", x, selected, c.Impl())
+			failed = true
 		}
 		x, ok, selected := c.Nbrecv2()
 		if x != 0 || ok || !selected {
 			println("test1: recv2 on closed nb:", x, ok, selected, c.Impl())
+			failed = true
 		}
 	}
 
@@ -247,12 +255,14 @@ func test1(c Chan) {
 	// the value should have been discarded.
 	if x := c.Recv(); x != 0 {
 		println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
+		failed = true
 	}
 
 	// similarly Send.
 	shouldPanic(func() { c.Send(2) })
 	if x := c.Recv(); x != 0 {
 		println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
+		failed = true
 	}
 }
 
@@ -260,6 +270,7 @@ func testasync1(c Chan) {
 	// should be able to get the last value via Recv
 	if x := c.Recv(); x != 1 {
 		println("testasync1: Recv did not get 1:", x, c.Impl())
+		failed = true
 	}
 
 	test1(c)
@@ -269,6 +280,7 @@ func testasync2(c Chan) {
 	// should be able to get the last value via Recv2
 	if x, ok := c.Recv2(); x != 1 || !ok {
 		println("testasync1: Recv did not get 1, true:", x, ok, c.Impl())
+		failed = true
 	}
 
 	test1(c)
@@ -278,6 +290,7 @@ func testasync3(c Chan) {
 	// should be able to get the last value via Nbrecv
 	if x, selected := c.Nbrecv(); x != 1 || !selected {
 		println("testasync2: Nbrecv did not get 1, true:", x, selected, c.Impl())
+		failed = true
 	}
 
 	test1(c)
@@ -287,6 +300,7 @@ func testasync4(c Chan) {
 	// should be able to get the last value via Nbrecv2
 	if x, ok, selected := c.Nbrecv2(); x != 1 || !ok || !selected {
 		println("testasync2: Nbrecv did not get 1, true, true:", x, ok, selected, c.Impl())
+		failed = true
 	}
 	test1(c)
 }
@@ -327,4 +341,19 @@ func main() {
 			testclosed(mk(closedasync()))
 		}
 	}
+	
+	var ch chan int	
+	shouldPanic(func() {
+		close(ch)
+	})
+	
+	ch = make(chan int)
+	close(ch)
+	shouldPanic(func() {
+		close(ch)
+	})
+
+	if failed {
+		os.Exit(1)
+	}
 }
diff --git a/test/closure.go b/test/closure.go
index 3033c02..97da1dd 100644
--- a/test/closure.go
+++ b/test/closure.go
@@ -6,6 +6,8 @@
 
 package main
 
+import "runtime"
+
 var c = make(chan int)
 
 func check(a []int) {
@@ -76,8 +78,9 @@ func h() {
 
 func newfunc() func(int) int { return func(x int) int { return x } }
 
-
 func main() {
+	var fail bool
+
 	go f()
 	check([]int{1, 4, 5, 4})
 
@@ -89,17 +92,26 @@ func main() {
 	go h()
 	check([]int{100, 200, 101, 201, 500, 101, 201, 500})
 
+	runtime.UpdateMemStats()
+        n0 := runtime.MemStats.Mallocs
+
 	x, y := newfunc(), newfunc()
-	if x == y {
-		println("newfunc returned same func")
-		panic("fail")
-	}
 	if x(1) != 1 || y(2) != 2 {
 		println("newfunc returned broken funcs")
-		panic("fail")
+		fail = true
+	}
+
+	runtime.UpdateMemStats()
+        if n0 != runtime.MemStats.Mallocs {
+		println("newfunc allocated unexpectedly")
+		fail = true
 	}
 
 	ff(1)
+
+	if fail {
+		panic("fail") 
+	}
 }
 
 func ff(x int) {
diff --git a/test/cmp.go b/test/cmp.go
new file mode 100644
index 0000000..d51a11a
--- /dev/null
+++ b/test/cmp.go
@@ -0,0 +1,400 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+var global bool
+func use(b bool) { global = b }
+
+func stringptr(s string) uintptr { return *(*uintptr)(unsafe.Pointer(&s)) }
+
+func isfalse(b bool) {
+	if b {
+		// stack will explain where
+		panic("wanted false, got true")
+	}
+}
+
+func istrue(b bool) {
+	if !b {
+		// stack will explain where
+		panic("wanted true, got false")
+	}
+}
+
+type T *int
+
+func main() {
+	var a []int
+	var b map[string]int
+
+	var c string = "hello"
+	var d string = "hel" // try to get different pointer
+	d = d + "lo"
+	if stringptr(c) == stringptr(d) {
+		panic("compiler too smart -- got same string")
+	}
+
+	var e = make(chan int)
+
+	var ia interface{} = a
+	var ib interface{} = b
+	var ic interface{} = c
+	var id interface{} = d
+	var ie interface{} = e
+
+	// these comparisons are okay because
+	// string compare is okay and the others
+	// are comparisons where the types differ.
+	isfalse(ia == ib)
+	isfalse(ia == ic)
+	isfalse(ia == id)
+	isfalse(ib == ic)
+	isfalse(ib == id)
+	istrue(ic == id)
+	istrue(ie == ie)
+
+	istrue(ia != ib)
+	istrue(ia != ic)
+	istrue(ia != id)
+	istrue(ib != ic)
+	istrue(ib != id)
+	isfalse(ic != id)
+	isfalse(ie != ie)
+
+	// these are not okay, because there is no comparison on slices or maps.
+	//isfalse(a == ib)
+	//isfalse(a == ic)
+	//isfalse(a == id)
+	//isfalse(b == ic)
+	//isfalse(b == id)
+
+	istrue(c == id)
+	istrue(e == ie)
+
+	//isfalse(ia == b)
+	isfalse(ia == c)
+	isfalse(ia == d)
+	isfalse(ib == c)
+	isfalse(ib == d)
+	istrue(ic == d)
+	istrue(ie == e)
+
+	//istrue(a != ib)
+	//istrue(a != ic)
+	//istrue(a != id)
+	//istrue(b != ic)
+	//istrue(b != id)
+	isfalse(c != id)
+	isfalse(e != ie)
+
+	//istrue(ia != b)
+	istrue(ia != c)
+	istrue(ia != d)
+	istrue(ib != c)
+	istrue(ib != d)
+	isfalse(ic != d)
+	isfalse(ie != e)
+
+	// 6g used to let this go through as true.
+	var g uint64 = 123
+	var h int64 = 123
+	var ig interface{} = g
+	var ih interface{} = h
+	isfalse(ig == ih)
+	istrue(ig != ih)
+
+	// map of interface should use == on interface values,
+	// not memory.
+	var m = make(map[interface{}]int)
+	m[ic] = 1
+	m[id] = 2
+	if m[c] != 2 {
+		println("m[c] = ", m[c])
+		panic("bad m[c]")
+	}
+
+	// non-interface comparisons
+	{
+		c := make(chan int)
+		c1 := (<-chan int)(c)
+		c2 := (chan<- int)(c)
+		istrue(c == c1)
+		istrue(c == c2)
+		istrue(c1 == c)
+		istrue(c2 == c)
+
+		isfalse(c != c1)
+		isfalse(c != c2)
+		isfalse(c1 != c)
+		isfalse(c2 != c)
+
+		d := make(chan int)
+		isfalse(c == d)
+		isfalse(d == c)
+		isfalse(d == c1)
+		isfalse(d == c2)
+		isfalse(c1 == d)
+		isfalse(c2 == d)
+
+		istrue(c != d)
+		istrue(d != c)
+		istrue(d != c1)
+		istrue(d != c2)
+		istrue(c1 != d)
+		istrue(c2 != d)
+	}
+
+	// named types vs not
+	{
+		var x = new(int)
+		var y T
+		var z T = x
+
+		isfalse(x == y)
+		istrue(x == z)
+		isfalse(y == z)
+
+		isfalse(y == x)
+		istrue(z == x)
+		isfalse(z == y)
+
+		istrue(x != y)
+		isfalse(x != z)
+		istrue(y != z)
+
+		istrue(y != x)
+		isfalse(z != x)
+		istrue(z != y)
+	}
+
+	// structs
+	{
+		var x = struct {
+			x int
+			y string
+		}{1, "hi"}
+		var y = struct {
+			x int
+			y string
+		}{2, "bye"}
+		var z = struct {
+			x int
+			y string
+		}{1, "hi"}
+
+		isfalse(x == y)
+		isfalse(y == x)
+		isfalse(y == z)
+		isfalse(z == y)
+		istrue(x == z)
+		istrue(z == x)
+
+		istrue(x != y)
+		istrue(y != x)
+		istrue(y != z)
+		istrue(z != y)
+		isfalse(x != z)
+		isfalse(z != x)
+
+		var m = make(map[struct {
+			x int
+			y string
+		}]int)
+		m[x] = 10
+		m[y] = 20
+		m[z] = 30
+		istrue(m[x] == 30)
+		istrue(m[y] == 20)
+		istrue(m[z] == 30)
+		istrue(m[x] != 10)
+		isfalse(m[x] != 30)
+		isfalse(m[y] != 20)
+		isfalse(m[z] != 30)
+		isfalse(m[x] == 10)
+
+		var m1 = make(map[struct {
+			x int
+			y string
+		}]struct {
+			x int
+			y string
+		})
+		m1[x] = x
+		m1[y] = y
+		m1[z] = z
+		istrue(m1[x] == z)
+		istrue(m1[y] == y)
+		istrue(m1[z] == z)
+		istrue(m1[x] == x)
+		isfalse(m1[x] != z)
+		isfalse(m1[y] != y)
+		isfalse(m1[z] != z)
+		isfalse(m1[x] != x)
+
+		var ix, iy, iz interface{} = x, y, z
+
+		isfalse(ix == iy)
+		isfalse(iy == ix)
+		isfalse(iy == iz)
+		isfalse(iz == iy)
+		istrue(ix == iz)
+		istrue(iz == ix)
+
+		isfalse(x == iy)
+		isfalse(y == ix)
+		isfalse(y == iz)
+		isfalse(z == iy)
+		istrue(x == iz)
+		istrue(z == ix)
+
+		isfalse(ix == y)
+		isfalse(iy == x)
+		isfalse(iy == z)
+		isfalse(iz == y)
+		istrue(ix == z)
+		istrue(iz == x)
+
+		istrue(ix != iy)
+		istrue(iy != ix)
+		istrue(iy != iz)
+		istrue(iz != iy)
+		isfalse(ix != iz)
+		isfalse(iz != ix)
+
+		istrue(x != iy)
+		istrue(y != ix)
+		istrue(y != iz)
+		istrue(z != iy)
+		isfalse(x != iz)
+		isfalse(z != ix)
+
+		istrue(ix != y)
+		istrue(iy != x)
+		istrue(iy != z)
+		istrue(iz != y)
+		isfalse(ix != z)
+		isfalse(iz != x)
+	}
+
+	// arrays
+	{
+		var x = [2]string{"1", "hi"}
+		var y = [2]string{"2", "bye"}
+		var z = [2]string{"1", "hi"}
+
+		isfalse(x == y)
+		isfalse(y == x)
+		isfalse(y == z)
+		isfalse(z == y)
+		istrue(x == z)
+		istrue(z == x)
+
+		istrue(x != y)
+		istrue(y != x)
+		istrue(y != z)
+		istrue(z != y)
+		isfalse(x != z)
+		isfalse(z != x)
+
+		var m = make(map[[2]string]int)
+		m[x] = 10
+		m[y] = 20
+		m[z] = 30
+		istrue(m[x] == 30)
+		istrue(m[y] == 20)
+		istrue(m[z] == 30)
+		isfalse(m[x] != 30)
+		isfalse(m[y] != 20)
+		isfalse(m[z] != 30)
+
+		var ix, iy, iz interface{} = x, y, z
+
+		isfalse(ix == iy)
+		isfalse(iy == ix)
+		isfalse(iy == iz)
+		isfalse(iz == iy)
+		istrue(ix == iz)
+		istrue(iz == ix)
+
+		isfalse(x == iy)
+		isfalse(y == ix)
+		isfalse(y == iz)
+		isfalse(z == iy)
+		istrue(x == iz)
+		istrue(z == ix)
+
+		isfalse(ix == y)
+		isfalse(iy == x)
+		isfalse(iy == z)
+		isfalse(iz == y)
+		istrue(ix == z)
+		istrue(iz == x)
+
+		istrue(ix != iy)
+		istrue(iy != ix)
+		istrue(iy != iz)
+		istrue(iz != iy)
+		isfalse(ix != iz)
+		isfalse(iz != ix)
+
+		istrue(x != iy)
+		istrue(y != ix)
+		istrue(y != iz)
+		istrue(z != iy)
+		isfalse(x != iz)
+		isfalse(z != ix)
+
+		istrue(ix != y)
+		istrue(iy != x)
+		istrue(iy != z)
+		istrue(iz != y)
+		isfalse(ix != z)
+		isfalse(iz != x)
+	}
+
+	shouldPanic(p1)
+	shouldPanic(p2)
+	shouldPanic(p3)
+	shouldPanic(p4)
+}
+
+func p1() {
+	var a []int
+	var ia interface{} = a
+	use(ia == ia)
+}
+
+func p2() {
+	var b []int
+	var ib interface{} = b
+	use(ib == ib)
+}
+
+func p3() {
+	var a []int
+	var ia interface{} = a
+	var m = make(map[interface{}]int)
+	m[ia] = 1
+}
+
+func p4() {
+	var b []int
+	var ib interface{} = b
+	var m = make(map[interface{}]int)
+	m[ib] = 1
+}
+
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("function should panic")
+		}
+	}()
+	f()
+}
diff --git a/test/cmp1.go b/test/cmp1.go
deleted file mode 100644
index 698544c..0000000
--- a/test/cmp1.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-func use(bool) {}
-
-func stringptr(s string) uintptr { return *(*uintptr)(unsafe.Pointer(&s)) }
-
-func isfalse(b bool) {
-	if b {
-		// stack will explain where
-		panic("wanted false, got true")
-	}
-}
-
-func istrue(b bool) {
-	if !b {
-		// stack will explain where
-		panic("wanted true, got false")
-	}
-}
-
-type T *int
-
-func main() {
-	var a []int
-	var b map[string]int
-
-	var c string = "hello"
-	var d string = "hel" // try to get different pointer
-	d = d + "lo"
-	if stringptr(c) == stringptr(d) {
-		panic("compiler too smart -- got same string")
-	}
-
-	var e = make(chan int)
-
-	var ia interface{} = a
-	var ib interface{} = b
-	var ic interface{} = c
-	var id interface{} = d
-	var ie interface{} = e
-
-	// these comparisons are okay because
-	// string compare is okay and the others
-	// are comparisons where the types differ.
-	isfalse(ia == ib)
-	isfalse(ia == ic)
-	isfalse(ia == id)
-	isfalse(ib == ic)
-	isfalse(ib == id)
-	istrue(ic == id)
-	istrue(ie == ie)
-	
-	// these are okay because one side of the
-	// comparison need only be assignable to the other.
-	isfalse(a == ib)
-	isfalse(a == ic)
-	isfalse(a == id)
-	isfalse(b == ic)
-	isfalse(b == id)
-	istrue(c == id)
-	istrue(e == ie)
-
-	isfalse(ia == b)
-	isfalse(ia == c)
-	isfalse(ia == d)
-	isfalse(ib == c)
-	isfalse(ib == d)
-	istrue(ic == d)
-	istrue(ie == e)
-
-	// 6g used to let this go through as true.
-	var g uint64 = 123
-	var h int64 = 123
-	var ig interface{} = g
-	var ih interface{} = h
-	isfalse(ig == ih)
-
-	// map of interface should use == on interface values,
-	// not memory.
-	// TODO: should m[c], m[d] be valid here?
-	var m = make(map[interface{}]int)
-	m[ic] = 1
-	m[id] = 2
-	if m[ic] != 2 {
-		println("m[ic] = ", m[ic])
-		panic("bad m[ic]")
-	}
-	
-	// non-interface comparisons
-	{
-		c := make(chan int)
-		c1 := (<-chan int)(c)
-		c2 := (chan<- int)(c)
-		istrue(c == c1)
-		istrue(c == c2)
-		istrue(c1 == c)
-		istrue(c2 == c)
-		
-		d := make(chan int)
-		isfalse(c == d)
-		isfalse(d == c)
-		isfalse(d == c1)
-		isfalse(d == c2)
-		isfalse(c1 == d)
-		isfalse(c2 == d)
-	}
-
-	// named types vs not
-	{
-		var x = new(int)
-		var y T
-		var z T = x
-		
-		isfalse(x == y)
-		istrue(x == z)
-		isfalse(y == z)
-
-		isfalse(y == x)
-		istrue(z == x)
-		isfalse(z == y)
-	}
-}
diff --git a/test/cmp2.go b/test/cmp2.go
deleted file mode 100644
index f6f124f..0000000
--- a/test/cmp2.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// $G $D/$F.go && $L $F.$A && ! ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-func use(bool) { }
-
-func main() {
-	var a []int
-	var ia interface{} = a
-	use(ia == ia)
-}
diff --git a/test/cmp3.go b/test/cmp3.go
deleted file mode 100644
index dd90bfb..0000000
--- a/test/cmp3.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// $G $D/$F.go && $L $F.$A && ! ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-func use(bool) { }
-
-func main() {
-	var b []int
-	var ib interface{} = b
-	use(ib == ib)
-}
diff --git a/test/cmp4.go b/test/cmp4.go
deleted file mode 100644
index 3f9b2c0..0000000
--- a/test/cmp4.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// $G $D/$F.go && $L $F.$A && ! ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-func main() {
-	var a []int
-	var ia interface{} = a
-	var m = make(map[interface{}] int)
-	m[ia] = 1
-}
diff --git a/test/cmp5.go b/test/cmp5.go
deleted file mode 100644
index 3a7d733..0000000
--- a/test/cmp5.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// $G $D/$F.go && $L $F.$A && ! ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-func main() {
-	var b []int
-	var ib interface{} = b
-	var m = make(map[interface{}] int)
-	m[ib] = 1
-}
diff --git a/test/cmp6.go b/test/cmp6.go
index b3ea8ff..0113a69 100644
--- a/test/cmp6.go
+++ b/test/cmp6.go
@@ -11,7 +11,7 @@ func use(bool) {}
 type T1 *int
 type T2 *int
 
-type T3 struct {}
+type T3 struct{ z []int }
 
 var t3 T3
 
@@ -21,12 +21,12 @@ func main() {
 	// so chan int can be compared against
 	// directional channels but channel of different
 	// direction cannot be compared against each other.
-	var c1 chan <-int
+	var c1 chan<- int
 	var c2 <-chan int
 	var c3 chan int
-	
-	use(c1 == c2)	// ERROR "invalid operation|incompatible"
-	use(c2 == c1)	// ERROR "invalid operation|incompatible"
+
+	use(c1 == c2) // ERROR "invalid operation|incompatible"
+	use(c2 == c1) // ERROR "invalid operation|incompatible"
 	use(c1 == c3)
 	use(c2 == c2)
 	use(c3 == c1)
@@ -36,14 +36,32 @@ func main() {
 	var p1 T1
 	var p2 T2
 	var p3 *int
-	
-	use(p1 == p2)	// ERROR "invalid operation|incompatible"
-	use(p2 == p1)	// ERROR "invalid operation|incompatible"
+
+	use(p1 == p2) // ERROR "invalid operation|incompatible"
+	use(p2 == p1) // ERROR "invalid operation|incompatible"
 	use(p1 == p3)
 	use(p2 == p2)
 	use(p3 == p1)
 	use(p3 == p2)
-	
+
 	// Comparison of structs should have a good message
-	use(t3 == t3)	// ERROR "struct|expected"
+	use(t3 == t3) // ERROR "struct|expected"
+
+	// Slices, functions, and maps too.
+	var x []int
+	var f func()
+	var m map[int]int
+	use(x == x) // ERROR "slice can only be compared to nil"
+	use(f == f) // ERROR "func can only be compared to nil"
+	use(m == m) // ERROR "map can only be compared to nil"
+
+	// Comparison with interface that cannot return true
+	// (would panic).
+	var i interface{}
+	use(i == x) // ERROR "invalid operation"
+	use(x == i) // ERROR "invalid operation"
+	use(i == f) // ERROR "invalid operation"
+	use(f == i) // ERROR "invalid operation"
+	use(i == m) // ERROR "invalid operation"
+	use(m == i) // ERROR "invalid operation"
 }
diff --git a/test/cmplxdivide.go b/test/cmplxdivide.go
index 6a67b17..461ee97 100644
--- a/test/cmplxdivide.go
+++ b/test/cmplxdivide.go
@@ -9,14 +9,14 @@
 package main
 
 import (
-	"cmath"
 	"fmt"
 	"math"
+	"math/cmplx"
 )
 
-type Test struct{
-	f, g	complex128
-	out	complex128
+type Test struct {
+	f, g complex128
+	out  complex128
 }
 
 var nan = math.NaN()
@@ -25,9 +25,9 @@ var negzero = math.Copysign(0, -1)
 
 func calike(a, b complex128) bool {
 	switch {
-	case cmath.IsInf(a) && cmath.IsInf(b):
+	case cmplx.IsInf(a) && cmplx.IsInf(b):
 		return true
-	case cmath.IsNaN(a) && cmath.IsNaN(b):
+	case cmplx.IsNaN(a) && cmplx.IsNaN(b):
 		return true
 	}
 	return a == b
@@ -36,7 +36,7 @@ func calike(a, b complex128) bool {
 func main() {
 	bad := false
 	for _, t := range tests {
-		x := t.f/t.g
+		x := t.f / t.g
 		if !calike(x, t.out) {
 			if !bad {
 				fmt.Printf("BUG\n")
diff --git a/test/complit.go b/test/complit.go
index f5f7aca..8dfc71d 100644
--- a/test/complit.go
+++ b/test/complit.go
@@ -31,6 +31,18 @@ func eq(a []*R) {
 	}
 }
 
+func teq(t *T, n int) {
+	for i := 0; i < n; i++ {
+		if t == nil || t.i != i {
+			panic("bad")
+		}
+		t = t.next
+	}
+	if t != nil {
+		panic("bad")
+	}
+}
+
 type P struct {
 	a, b int
 }
@@ -46,6 +58,9 @@ func main() {
 	var tp *T
 	tp = &T{0, 7.2, "hi", &t}
 
+	tl := &T{i: 0, next: &T{i: 1, next: &T{i: 2, next: &T{i: 3, next: &T{i: 4}}}}}
+	teq(tl, 5)
+
 	a1 := []int{1, 2, 3}
 	if len(a1) != 3 {
 		panic("a1")
@@ -93,6 +108,7 @@ func main() {
 	}
 
 	eq([]*R{itor(0), itor(1), itor(2), itor(3), itor(4), itor(5)})
+	eq([]*R{{0}, {1}, {2}, {3}, {4}, {5}})
 
 	p1 := NewP(1, 2)
 	p2 := NewP(1, 2)
diff --git a/test/complit1.go b/test/complit1.go
new file mode 100644
index 0000000..aaf701f
--- /dev/null
+++ b/test/complit1.go
@@ -0,0 +1,39 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 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
+
+var m map[int][3]int
+
+func f() [3]int
+
+func fp() *[3]int
+
+var mp map[int]*[3]int
+
+var (
+	_ = [3]int{1, 2, 3}[:] // ERROR "slice of unaddressable value"
+	_ = m[0][:]            // ERROR "slice of unaddressable value"
+	_ = f()[:]             // ERROR "slice of unaddressable value"
+
+	// these are okay because they are slicing a pointer to an array
+	_ = (&[3]int{1, 2, 3})[:]
+	_ = mp[0][:]
+	_ = fp()[:]
+)
+
+type T struct {
+	i    int
+	f    float64
+	s    string
+	next *T
+}
+
+var (
+	_ = &T{0, 0, "", nil}               // ok
+	_ = &T{i: 0, f: 0, s: "", next: {}} // ERROR "missing type in composite literal"
+	_ = &T{0, 0, "", {}}                // ERROR "missing type in composite literal"
+)
diff --git a/test/convert1.go b/test/convert1.go
new file mode 100644
index 0000000..9de1b7e
--- /dev/null
+++ b/test/convert1.go
@@ -0,0 +1,96 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 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
+
+type Tbyte []byte
+type Trune []rune
+type Tint64 []int64
+type Tstring string
+
+func main() {
+	s := "hello"
+	sb := []byte("hello")
+	sr := []rune("hello")
+	si := []int64{'h', 'e', 'l', 'l', 'o'}
+
+	ts := Tstring(s)
+	tsb := Tbyte(sb)
+	tsr := Trune(sr)
+	tsi := Tint64(si)
+
+	_ = string(s)
+	_ = []byte(s)
+	_ = []rune(s)
+	_ = []int64(s) // ERROR "cannot convert.*\[\]int64"
+	_ = Tstring(s)
+	_ = Tbyte(s)
+	_ = Trune(s)
+	_ = Tint64(s) // ERROR "cannot convert.*Tint64"
+
+	_ = string(sb)
+	_ = []byte(sb)
+	_ = []rune(sb)  // ERROR "cannot convert.*\[\]rune"
+	_ = []int64(sb) // ERROR "cannot convert.*\[\]int64"
+	_ = Tstring(sb)
+	_ = Tbyte(sb)
+	_ = Trune(sb)  // ERROR "cannot convert.*Trune"
+	_ = Tint64(sb) // ERROR "cannot convert.*Tint64"
+
+	_ = string(sr)
+	_ = []byte(sr) // ERROR "cannot convert.*\[\]byte"
+	_ = []rune(sr)
+	_ = []int64(sr) // ERROR "cannot convert.*\[\]int64"
+	_ = Tstring(sr)
+	_ = Tbyte(sr) // ERROR "cannot convert.*Tbyte"
+	_ = Trune(sr)
+	_ = Tint64(sr) // ERROR "cannot convert.*Tint64"
+
+	_ = string(si) // ERROR "cannot convert.* string"
+	_ = []byte(si) // ERROR "cannot convert.*\[\]byte"
+	_ = []rune(si) // ERROR "cannot convert.*\[\]rune"
+	_ = []int64(si)
+	_ = Tstring(si) // ERROR "cannot convert.*Tstring"
+	_ = Tbyte(si)   // ERROR "cannot convert.*Tbyte"
+	_ = Trune(si)   // ERROR "cannot convert.*Trune"
+	_ = Tint64(si)
+
+	_ = string(ts)
+	_ = []byte(ts)
+	_ = []rune(ts)
+	_ = []int64(ts) // ERROR "cannot convert.*\[\]int64"
+	_ = Tstring(ts)
+	_ = Tbyte(ts)
+	_ = Trune(ts)
+	_ = Tint64(ts) // ERROR "cannot convert.*Tint64"
+
+	_ = string(tsb)
+	_ = []byte(tsb)
+	_ = []rune(tsb)  // ERROR "cannot convert.*\[\]rune"
+	_ = []int64(tsb) // ERROR "cannot convert.*\[\]int64"
+	_ = Tstring(tsb)
+	_ = Tbyte(tsb)
+	_ = Trune(tsb)  // ERROR "cannot convert.*Trune"
+	_ = Tint64(tsb) // ERROR "cannot convert.*Tint64"
+
+	_ = string(tsr)
+	_ = []byte(tsr) // ERROR "cannot convert.*\[\]byte"
+	_ = []rune(tsr)
+	_ = []int64(tsr) // ERROR "cannot convert.*\[\]int64"
+	_ = Tstring(tsr)
+	_ = Tbyte(tsr) // ERROR "cannot convert.*Tbyte"
+	_ = Trune(tsr)
+	_ = Tint64(tsr) // ERROR "cannot convert.*Tint64"
+
+	_ = string(tsi) // ERROR "cannot convert.* string"
+	_ = []byte(tsi) // ERROR "cannot convert.*\[\]byte"
+	_ = []rune(tsi) // ERROR "cannot convert.*\[\]rune"
+	_ = []int64(tsi)
+	_ = Tstring(tsi) // ERROR "cannot convert.*Tstring"
+	_ = Tbyte(tsi)   // ERROR "cannot convert.*Tbyte"
+	_ = Trune(tsi)   // ERROR "cannot convert.*Trune"
+	_ = Tint64(tsi)
+}
diff --git a/test/convlit.go b/test/convlit.go
index 90ac549..1e82d1f 100644
--- a/test/convlit.go
+++ b/test/convlit.go
@@ -36,7 +36,7 @@ var good3 int = 1e9
 var good4 float64 = 1e20
 
 // explicit conversion of string is okay
-var _ = []int("abc")
+var _ = []rune("abc")
 var _ = []byte("abc")
 
 // implicit is not
@@ -47,20 +47,20 @@ var _ []byte = "abc" // ERROR "cannot use|incompatible|invalid"
 type Tstring string
 
 var ss Tstring = "abc"
-var _ = []int(ss)
+var _ = []rune(ss)
 var _ = []byte(ss)
 
 // implicit is still not
-var _ []int = ss  // ERROR "cannot use|incompatible|invalid"
+var _ []rune = ss // ERROR "cannot use|incompatible|invalid"
 var _ []byte = ss // ERROR "cannot use|incompatible|invalid"
 
-// named slice is not
-type Tint []int
+// named slice is now ok
+type Trune []rune
 type Tbyte []byte
 
-var _ = Tint("abc")  // ERROR "convert|incompatible|invalid"
-var _ = Tbyte("abc") // ERROR "convert|incompatible|invalid"
+var _ = Trune("abc") // ok
+var _ = Tbyte("abc") // ok
 
 // implicit is still not
-var _ Tint = "abc"  // ERROR "cannot use|incompatible|invalid"
+var _ Trune = "abc" // ERROR "cannot use|incompatible|invalid"
 var _ Tbyte = "abc" // ERROR "cannot use|incompatible|invalid"
diff --git a/test/crlf.go b/test/crlf.go
new file mode 100644
index 0000000..292b63b
--- /dev/null
+++ b/test/crlf.go
@@ -0,0 +1,52 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
+// $G tmp.go && $L tmp.$A && ./$A.out
+// rm -f tmp.go
+
+// Copyright 2011 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 source files and strings containing \r and \r\n.
+
+package main
+
+import (
+	"fmt"
+	"strings"
+)
+
+func main() {
+	prog = strings.Replace(prog, "BQ", "`", -1)
+	prog = strings.Replace(prog, "CR", "\r", -1)
+	fmt.Print(prog)
+}
+
+var prog = `
+package main
+CR
+
+import "fmt"
+
+var CR s = "hello\n" + CR
+	" world"CR
+
+var t = BQhelloCR
+ worldBQ
+
+var u = BQhCReCRlCRlCRoCR
+ worldBQ
+
+var golden = "hello\n world"
+
+func main() {
+	if s != golden {
+		fmt.Printf("s=%q, want %q", s, golden)
+	}
+	if t != golden {
+		fmt.Printf("t=%q, want %q", t, golden)
+	}
+	if u != golden {
+		fmt.Printf("u=%q, want %q", u, golden)
+	}
+}
+`
diff --git a/test/ddd1.go b/test/ddd1.go
index 83e32de..6d84248 100644
--- a/test/ddd1.go
+++ b/test/ddd1.go
@@ -15,8 +15,8 @@ var (
 	_ = sum()
 	_ = sum(1.0, 2.0)
 	_ = sum(1.5)      // ERROR "integer"
-	_ = sum("hello")  // ERROR "string.*as type int|incompatible"
-	_ = sum([]int{1}) // ERROR "slice literal.*as type int|incompatible"
+	_ = sum("hello")  // ERROR ".hello. .type string. as type int|incompatible"
+	_ = sum([]int{1}) // ERROR "\[\]int literal.*as type int|incompatible"
 )
 
 type T []T
diff --git a/test/deferprint.go b/test/deferprint.go
index f1e7526..0e0c618 100644
--- a/test/deferprint.go
+++ b/test/deferprint.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
+// $G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out
 
 // Copyright 2010 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/deferprint.out b/test/deferprint.out
new file mode 100644
index 0000000..a71cfce
--- /dev/null
+++ b/test/deferprint.out
@@ -0,0 +1,2 @@
+printing: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+42 true false true +1.500000e+000 world 0x0 [0/0]0x0 0x0 0x0 255
diff --git a/test/dwarf/linedirectives.go b/test/dwarf/linedirectives.go
old mode 100755
new mode 100644
diff --git a/test/env.go b/test/env.go
index 28113bc..a4b9d05 100644
--- a/test/env.go
+++ b/test/env.go
@@ -14,7 +14,7 @@ import (
 func main() {
 	ga, e0 := os.Getenverror("GOARCH")
 	if e0 != nil {
-		print("$GOARCH: ", e0.String(), "\n")
+		print("$GOARCH: ", e0.Error(), "\n")
 		os.Exit(1)
 	}
 	if ga != runtime.GOARCH {
@@ -23,7 +23,7 @@ func main() {
 	}
 	xxx, e1 := os.Getenverror("DOES_NOT_EXIST")
 	if e1 != os.ENOENV {
-		print("$DOES_NOT_EXIST=", xxx, "; err = ", e1.String(), "\n")
+		print("$DOES_NOT_EXIST=", xxx, "; err = ", e1.Error(), "\n")
 		os.Exit(1)
 	}
 }
diff --git a/test/escape2.go b/test/escape2.go
index dbe0c69..73b2a7e 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -1,4 +1,4 @@
-// errchk -0 $G -m $D/$F.go
+// errchk -0 $G -m -l $D/$F.go
 
 // Copyright 2010 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -6,25 +6,28 @@
 
 package foo
 
-import "unsafe"
+import (
+	"fmt"
+	"unsafe"
+)
 
 var gxx *int
 
-func foo1(x int) { // ERROR "moved to heap: NAME-x"
-	gxx = &x  // ERROR "&x escapes to heap"
+func foo1(x int) { // ERROR "moved to heap: x"
+	gxx = &x // ERROR "&x escapes to heap"
 }
 
-func foo2(yy *int) { // ERROR "leaking param: NAME-yy"
+func foo2(yy *int) { // ERROR "leaking param: yy"
 	gxx = yy
 }
 
-func foo3(x int) *int { // ERROR "moved to heap: NAME-x"
-	return &x  // ERROR "&x escapes to heap"
+func foo3(x int) *int { // ERROR "moved to heap: x"
+	return &x // ERROR "&x escapes to heap"
 }
 
 type T *T
 
-func foo3b(t T) { // ERROR "leaking param: NAME-t"
+func foo3b(t T) { // ERROR "leaking param: t"
 	*t = t
 }
 
@@ -35,10 +38,10 @@ func foo4(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape"
 
 // xx isn't going anywhere, so taking address of yy is ok
 func foo5(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape"
-	xx = &yy  // ERROR "&yy does not escape"
+	xx = &yy // ERROR "&yy does not escape"
 }
 
-func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: NAME-yy"
+func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: yy"
 	*xx = yy
 }
 
@@ -51,7 +54,7 @@ func foo8(xx, yy *int) int { // ERROR "xx does not escape" "yy does not escape"
 	return *xx
 }
 
-func foo9(xx, yy *int) *int { // ERROR "leaking param: NAME-xx" "leaking param: NAME-yy"
+func foo9(xx, yy *int) *int { // ERROR "leaking param: xx" "leaking param: yy"
 	xx = yy
 	return xx
 }
@@ -62,15 +65,15 @@ func foo10(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape"
 
 func foo11() int {
 	x, y := 0, 42
-	xx := &x  // ERROR "&x does not escape"
-	yy := &y  // ERROR "&y does not escape"
+	xx := &x // ERROR "&x does not escape"
+	yy := &y // ERROR "&y does not escape"
 	*xx = *yy
 	return x
 }
 
 var xxx **int
 
-func foo12(yyy **int) { // ERROR "leaking param: NAME-yyy"
+func foo12(yyy **int) { // ERROR "leaking param: yyy"
 	xxx = yyy
 }
 
@@ -82,11 +85,11 @@ func foo14(yyy **int) { // ERROR "yyy does not escape"
 	**xxx = **yyy
 }
 
-func foo15(yy *int) { // ERROR "moved to heap: NAME-yy"
-	xxx = &yy  // ERROR "&yy escapes to heap"
+func foo15(yy *int) { // ERROR "moved to heap: yy"
+	xxx = &yy // ERROR "&yy escapes to heap"
 }
 
-func foo16(yy *int) { // ERROR "leaking param: NAME-yy"
+func foo16(yy *int) { // ERROR "leaking param: yy"
 	*xxx = yy
 }
 
@@ -94,8 +97,8 @@ func foo17(yy *int) { // ERROR "yy does not escape"
 	**xxx = *yy
 }
 
-func foo18(y int) { // ERROR "moved to heap: "NAME-y"
-	*xxx = &y  // ERROR "&y escapes to heap"
+func foo18(y int) { // ERROR "moved to heap: "y"
+	*xxx = &y // ERROR "&y escapes to heap"
 }
 
 func foo19(y int) {
@@ -108,26 +111,52 @@ type Bar struct {
 }
 
 func NewBar() *Bar {
-	return &Bar{42, nil} // ERROR "&struct literal escapes to heap"
+	return &Bar{42, nil} // ERROR "&Bar literal escapes to heap"
 }
 
-func NewBarp(x *int) *Bar { // ERROR "leaking param: NAME-x"
-	return &Bar{42, x} // ERROR "&struct literal escapes to heap"
+func NewBarp(x *int) *Bar { // ERROR "leaking param: x"
+	return &Bar{42, x} // ERROR "&Bar literal escapes to heap"
 }
 
 func NewBarp2(x *int) *Bar { // ERROR "x does not escape"
-	return &Bar{*x, nil} // ERROR "&struct literal escapes to heap"
+	return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap"
 }
 
 func (b *Bar) NoLeak() int { // ERROR "b does not escape"
 	return *(b.ii)
 }
 
+func (b *Bar) Leak() *int { // ERROR "leaking param: b"
+	return &b.i // ERROR "&b.i escapes to heap"
+}
+
 func (b *Bar) AlsoNoLeak() *int { // ERROR "b does not escape"
 	return b.ii
 }
 
-func goLeak(b *Bar) {  // ERROR "leaking param: NAME-b"
+func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b"
+	return b.ii
+}
+
+func (b Bar) LeaksToo() *int { // ERROR "leaking param: b"
+	v := 0	// ERROR "moved to heap: v"
+	b.ii = &v // ERROR "&v escapes"
+	return b.ii
+}
+
+func (b *Bar) LeaksABit() *int { // ERROR "b does not escape"
+	v := 0	// ERROR "moved to heap: v"
+	b.ii = &v // ERROR "&v escapes"
+	return b.ii
+}
+
+func (b Bar) StillNoLeak() int { // ERROR "b does not escape"
+	v := 0
+	b.ii = &v // ERROR "&v does not escape"
+	return b.i
+}
+
+func goLeak(b *Bar) { // ERROR "leaking param: b"
 	go b.NoLeak()
 }
 
@@ -137,72 +166,76 @@ type Bar2 struct {
 }
 
 func NewBar2() *Bar2 {
-	return &Bar2{[12]int{42}, nil} // ERROR "&struct literal escapes to heap"
+	return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap"
 }
 
 func (b *Bar2) NoLeak() int { // ERROR "b does not escape"
 	return b.i[0]
 }
 
-func (b *Bar2) Leak() []int { // ERROR "leaking param: NAME-b"
-	return b.i[:]  // ERROR "&b.i escapes to heap"
+func (b *Bar2) Leak() []int { // ERROR "leaking param: b"
+	return b.i[:] // ERROR "b.i escapes to heap"
 }
 
 func (b *Bar2) AlsoNoLeak() []int { // ERROR "b does not escape"
 	return b.ii[0:1]
 }
 
-func (b *Bar2) LeakSelf() { // ERROR "leaking param: NAME-b"
-	b.ii = b.i[0:4]  // ERROR "&b.i escapes to heap"
+func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape"
+	return b.i
 }
 
-func (b *Bar2) LeakSelf2() { // ERROR "leaking param: NAME-b"
+func (b *Bar2) LeakSelf() { // ERROR "leaking param: b"
+	b.ii = b.i[0:4] // ERROR "b.i escapes to heap"
+}
+
+func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b"
 	var buf []int
-	buf = b.i[0:]  // ERROR "&b.i escapes to heap"
+	buf = b.i[0:] // ERROR "b.i escapes to heap"
 	b.ii = buf
 }
 
 func foo21() func() int {
-	x := 42 // ERROR "moved to heap: NAME-x"
-	return func() int {  // ERROR "func literal escapes to heap"
-		return x  // ERROR "&x escapes to heap"
+	x := 42             // ERROR "moved to heap: x"
+	return func() int { // ERROR "func literal escapes to heap"
+		return x // ERROR "&x escapes to heap"
 	}
 }
 
 func foo22() int {
 	x := 42
-	return func() int {  // ERROR "func literal does not escape"
+	return func() int { // ERROR "func literal does not escape"
 		return x
 	}()
 }
 
-func foo23(x int) func() int { // ERROR "moved to heap: NAME-x"
-	return func() int {  // ERROR "func literal escapes to heap"
-		return x  // ERROR "&x escapes to heap"
+func foo23(x int) func() int { // ERROR "moved to heap: x"
+	return func() int { // ERROR "func literal escapes to heap"
+		return x // ERROR "&x escapes to heap"
 	}
 }
 
-func foo23a(x int) func() int { // ERROR "moved to heap: NAME-x"
-	f := func() int {  // ERROR "func literal escapes to heap"
-		return x  // ERROR "&x escapes to heap"
+func foo23a(x int) func() int { // ERROR "moved to heap: x"
+	f := func() int { // ERROR "func literal escapes to heap"
+		return x // ERROR "&x escapes to heap"
 	}
 	return f
 }
 
-func foo23b(x int) *(func() int) { // ERROR "moved to heap: NAME-x"
-	f := func() int { return x } // ERROR "moved to heap: NAME-f" "func literal escapes to heap" "&x escapes to heap"
-	return &f  // ERROR "&f escapes to heap"
+func foo23b(x int) *(func() int) { // ERROR "moved to heap: x"
+	f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap"
+	return &f                    // ERROR "&f escapes to heap"
 }
 
 func foo24(x int) int {
-	return func() int {  // ERROR "func literal does not escape"
+	return func() int { // ERROR "func literal does not escape"
 		return x
 	}()
 }
 
 var x *int
 
-func fooleak(xx *int) int { // ERROR "leaking param: NAME-xx"
+func fooleak(xx *int) int { // ERROR "leaking param: xx"
 	x = xx
 	return *x
 }
@@ -211,12 +244,12 @@ func foonoleak(xx *int) int { // ERROR "xx does not escape"
 	return *x + *xx
 }
 
-func foo31(x int) int { // ERROR "moved to heap: NAME-x"
-	return fooleak(&x)  // ERROR "&x escapes to heap"
+func foo31(x int) int { // ERROR "moved to heap: x"
+	return fooleak(&x) // ERROR "&x escapes to heap"
 }
 
 func foo32(x int) int {
-	return foonoleak(&x)  // ERROR "&x does not escape"
+	return foonoleak(&x) // ERROR "&x does not escape"
 }
 
 type Foo struct {
@@ -227,7 +260,7 @@ type Foo struct {
 var F Foo
 var pf *Foo
 
-func (f *Foo) fooleak() { // ERROR "leaking param: NAME-f"
+func (f *Foo) fooleak() { // ERROR "leaking param: f"
 	pf = f
 }
 
@@ -235,7 +268,7 @@ func (f *Foo) foonoleak() { // ERROR "f does not escape"
 	F.x = f.x
 }
 
-func (f *Foo) Leak() { // ERROR "leaking param: NAME-f"
+func (f *Foo) Leak() { // ERROR "leaking param: f"
 	f.fooleak()
 }
 
@@ -243,19 +276,19 @@ func (f *Foo) NoLeak() { // ERROR "f does not escape"
 	f.foonoleak()
 }
 
-func foo41(x int) { // ERROR "moved to heap: NAME-x"
-	F.xx = &x  // ERROR "&x escapes to heap"
+func foo41(x int) { // ERROR "moved to heap: x"
+	F.xx = &x // ERROR "&x escapes to heap"
 }
 
-func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: NAME-x"
-	f.xx = &x  // ERROR "&x escapes to heap"
+func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: x"
+	f.xx = &x // ERROR "&x escapes to heap"
 }
 
-func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: NAME-x"
-	f.xx = &x  // ERROR "&x escapes to heap"
+func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: x"
+	f.xx = &x // ERROR "&x escapes to heap"
 }
 
-func foo44(yy *int) { // ERROR "leaking param: NAME-yy"
+func foo44(yy *int) { // ERROR "leaking param: yy"
 	F.xx = yy
 }
 
@@ -267,73 +300,73 @@ func (f *Foo) foo46() { // ERROR "f does not escape"
 	F.xx = f.xx
 }
 
-func (f *Foo) foo47() { // ERROR "leaking param: NAME-f"
-	f.xx = &f.x  // ERROR "&f.x escapes to heap"
+func (f *Foo) foo47() { // ERROR "leaking param: f"
+	f.xx = &f.x // ERROR "&f.x escapes to heap"
 }
 
 var ptrSlice []*int
 
-func foo50(i *int) { // ERROR "leaking param: NAME-i"
+func foo50(i *int) { // ERROR "leaking param: i"
 	ptrSlice[0] = i
 }
 
 var ptrMap map[*int]*int
 
-func foo51(i *int) { // ERROR "leaking param: NAME-i"
+func foo51(i *int) { // ERROR "leaking param: i"
 	ptrMap[i] = i
 }
 
-func indaddr1(x int) *int { // ERROR "moved to heap: NAME-x"
-	return &x  // ERROR "&x escapes to heap"
+func indaddr1(x int) *int { // ERROR "moved to heap: x"
+	return &x // ERROR "&x escapes to heap"
 }
 
-func indaddr2(x *int) *int { // ERROR "leaking param: NAME-x"
-	return *&x  // ERROR "&x does not escape"
+func indaddr2(x *int) *int { // ERROR "leaking param: x"
+	return *&x // ERROR "&x does not escape"
 }
 
-func indaddr3(x *int32) *int { // ERROR "leaking param: NAME-x"
-	return *(**int)(unsafe.Pointer(&x))  // ERROR "&x does not escape"
+func indaddr3(x *int32) *int { // ERROR "leaking param: x"
+	return *(**int)(unsafe.Pointer(&x)) // ERROR "&x does not escape"
 }
 
 // From package math:
 
 func Float32bits(f float32) uint32 {
-	return *(*uint32)(unsafe.Pointer(&f))  // ERROR "&f does not escape"
+	return *(*uint32)(unsafe.Pointer(&f)) // ERROR "&f does not escape"
 }
 
 func Float32frombits(b uint32) float32 {
-	return *(*float32)(unsafe.Pointer(&b))  // ERROR "&b does not escape"
+	return *(*float32)(unsafe.Pointer(&b)) // ERROR "&b does not escape"
 }
 
 func Float64bits(f float64) uint64 {
-	return *(*uint64)(unsafe.Pointer(&f))  // ERROR "&f does not escape"
+	return *(*uint64)(unsafe.Pointer(&f)) // ERROR "&f does not escape"
 }
 
 func Float64frombits(b uint64) float64 {
-	return *(*float64)(unsafe.Pointer(&b))  // ERROR "&b does not escape"
+	return *(*float64)(unsafe.Pointer(&b)) // ERROR "&b does not escape"
 }
 
 // contrast with
-func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: NAME-f"
-	return (*uint64)(unsafe.Pointer(&f))  // ERROR "&f escapes to heap"
+func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f"
+	return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap"
 }
 
-func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: NAME-f"
+func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f"
 	return (*uint64)(unsafe.Pointer(f))
 }
 
-func typesw(i interface{}) *int { // ERROR "leaking param: NAME-i"
+func typesw(i interface{}) *int { // ERROR "leaking param: i"
 	switch val := i.(type) {
 	case *int:
 		return val
 	case *int8:
-		v := int(*val) // ERROR "moved to heap: NAME-v"
-		return &v  // ERROR "&v escapes to heap"
+		v := int(*val) // ERROR "moved to heap: v"
+		return &v      // ERROR "&v escapes to heap"
 	}
 	return nil
 }
 
-func exprsw(i *int) *int { // ERROR "leaking param: NAME-i"
+func exprsw(i *int) *int { // ERROR "leaking param: i"
 	switch j := i; *j + 110 {
 	case 12:
 		return j
@@ -345,7 +378,7 @@ func exprsw(i *int) *int { // ERROR "leaking param: NAME-i"
 }
 
 // assigning to an array element is like assigning to the array
-func foo60(i *int) *int { // ERROR "leaking param: NAME-i"
+func foo60(i *int) *int { // ERROR "leaking param: i"
 	var a [12]*int
 	a[0] = i
 	return a[1]
@@ -358,7 +391,7 @@ func foo60a(i *int) *int { // ERROR "i does not escape"
 }
 
 // assigning to a struct field  is like assigning to the struct
-func foo61(i *int) *int { // ERROR "leaking param: NAME-i"
+func foo61(i *int) *int { // ERROR "leaking param: i"
 	type S struct {
 		a, b *int
 	}
@@ -379,7 +412,7 @@ func foo61a(i *int) *int { // ERROR "i does not escape"
 // assigning to a struct field is like assigning to the struct but
 // here this subtlety is lost, since s.a counts as an assignment to a
 // track-losing dereference.
-func foo62(i *int) *int { // ERROR "leaking param: NAME-i"
+func foo62(i *int) *int { // ERROR "leaking param: i"
 	type S struct {
 		a, b *int
 	}
@@ -395,11 +428,11 @@ type M interface {
 func foo63(m M) { // ERROR "m does not escape"
 }
 
-func foo64(m M) { // ERROR "leaking param: NAME-m"
+func foo64(m M) { // ERROR "leaking param: m"
 	m.M()
 }
 
-func foo64b(m M) { // ERROR "leaking param: NAME-m"
+func foo64b(m M) { // ERROR "leaking param: m"
 	defer m.M()
 }
 
@@ -409,12 +442,12 @@ func (MV) M() {}
 
 func foo65() {
 	var mv MV
-	foo63(&mv)  // ERROR "&mv does not escape"
+	foo63(&mv) // ERROR "&mv does not escape"
 }
 
 func foo66() {
-	var mv MV // ERROR "moved to heap: NAME-mv"
-	foo64(&mv)  // ERROR "&mv escapes to heap"
+	var mv MV  // ERROR "moved to heap: mv"
+	foo64(&mv) // ERROR "&mv escapes to heap"
 }
 
 func foo67() {
@@ -427,37 +460,37 @@ func foo68() {
 	foo64(mv) // escapes but it's an int so irrelevant
 }
 
-func foo69(m M) { // ERROR "leaking param: NAME-m"
+func foo69(m M) { // ERROR "leaking param: m"
 	foo64(m)
 }
 
-func foo70(mv1 *MV, m M) { // ERROR "leaking param: NAME-mv1" "leaking param: NAME-m"
+func foo70(mv1 *MV, m M) { // ERROR "leaking param: mv1" "leaking param: m"
 	m = mv1
 	foo64(m)
 }
 
-func foo71(x *int) []*int { // ERROR "leaking param: NAME-x"
+func foo71(x *int) []*int { // ERROR "leaking param: x"
 	var y []*int
 	y = append(y, x)
 	return y
 }
 
-func foo71a(x int) []*int { // ERROR "moved to heap: NAME-x"
+func foo71a(x int) []*int { // ERROR "moved to heap: x"
 	var y []*int
-	y = append(y, &x)  // ERROR "&x escapes to heap"
+	y = append(y, &x) // ERROR "&x escapes to heap"
 	return y
 }
 
 func foo72() {
 	var x int
 	var y [1]*int
-	y[0] = &x  // ERROR "&x does not escape"
+	y[0] = &x // ERROR "&x does not escape"
 }
 
 func foo72aa() [10]*int {
-	var x int // ERROR "moved to heap: NAME-x"
+	var x int // ERROR "moved to heap: x"
 	var y [10]*int
-	y[0] = &x  // ERROR "&x escapes to heap"
+	y[0] = &x // ERROR "&x escapes to heap"
 	return y
 }
 
@@ -465,7 +498,7 @@ func foo72a() {
 	var y [10]*int
 	for i := 0; i < 10; i++ {
 		// escapes its scope
-		x := i // ERROR "moved to heap: NAME-x"
+		x := i    // ERROR "moved to heap: x"
 		y[i] = &x // ERROR "&x escapes to heap"
 	}
 	return
@@ -474,45 +507,45 @@ func foo72a() {
 func foo72b() [10]*int {
 	var y [10]*int
 	for i := 0; i < 10; i++ {
-		x := i // ERROR "moved to heap: NAME-x"
-		y[i] = &x  // ERROR "&x escapes to heap"
+		x := i    // ERROR "moved to heap: x"
+		y[i] = &x // ERROR "&x escapes to heap"
 	}
 	return y
 }
 
 // issue 2145
 func foo73() {
-	s := []int{3, 2, 1} // ERROR "slice literal does not escape"
+	s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
 	for _, v := range s {
-		vv := v        // ERROR "moved to heap: NAME-vv"
+		vv := v // ERROR "moved to heap: vv"
 		// actually just escapes its scope
 		defer func() { // ERROR "func literal escapes to heap"
-			println(vv)  // ERROR "&vv escapes to heap"
+			println(vv) // ERROR "&vv escapes to heap"
 		}()
 	}
 }
 
 func foo74() {
-	s := []int{3, 2, 1} // ERROR "slice literal does not escape"
+	s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
 	for _, v := range s {
-		vv := v        // ERROR "moved to heap: NAME-vv"
+		vv := v // ERROR "moved to heap: vv"
 		// actually just escapes its scope
 		fn := func() { // ERROR "func literal escapes to heap"
-			println(vv)  // ERROR "&vv escapes to heap"
+			println(vv) // ERROR "&vv escapes to heap"
 		}
 		defer fn()
 	}
 }
 
-func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: NAME-y"
+func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y"
 	return y
 }
 
-func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: NAME-x"
-	return &x[0]  // ERROR "&x.0. escapes to heap"
+func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: x"
+	return &x[0] // ERROR "&x.0. escapes to heap"
 }
 
-func foo75(z *int) { // ERROR "leaking param: NAME-z"
+func foo75(z *int) { // ERROR "leaking param: z"
 	myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
 }
 
@@ -520,11 +553,11 @@ func foo75a(z *int) { // ERROR "z does not escape"
 	myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
 }
 
-func foo76(z *int) { // ERROR "leaking param: NAME-z"
+func foo76(z *int) { // ERROR "leaking param: z"
 	myprint(nil, z) // ERROR "[.][.][.] argument does not escape"
 }
 
-func foo76a(z *int) { // ERROR "leaking param: NAME-z"
+func foo76a(z *int) { // ERROR "leaking param: z"
 	myprint1(nil, z) // ERROR "[.][.][.] argument escapes to heap"
 }
 
@@ -561,17 +594,17 @@ func foo77(z []interface{}) { // ERROR "z does not escape"
 	myprint(nil, z...) // z does not escape
 }
 
-func foo77a(z []interface{}) { // ERROR "leaking param: NAME-z"
+func foo77a(z []interface{}) { // ERROR "leaking param: z"
 	myprint1(nil, z...)
 }
 
-func foo78(z int) *int { // ERROR "moved to heap: NAME-z"
-	return &z  // ERROR "&z escapes to heap"
+func foo78(z int) *int { // ERROR "moved to heap: z"
+	return &z // ERROR "&z escapes to heap"
 }
 
-func foo78a(z int) *int { // ERROR "moved to heap: NAME-z"
-	y := &z  // ERROR "&z escapes to heap"
-	x := &y  // ERROR "&y does not escape"
+func foo78a(z int) *int { // ERROR "moved to heap: z"
+	y := &z   // ERROR "&z escapes to heap"
+	x := &y   // ERROR "&y does not escape"
 	return *x // really return y
 }
 
@@ -606,19 +639,19 @@ type LimitedFooer struct {
 	N int64
 }
 
-func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: NAME-r"
-	return &LimitedFooer{r, n} // ERROR "&struct literal escapes to heap"
+func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r"
+	return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap"
 }
 
-func foo90(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
-	return map[*int]*int{nil: x} // ERROR "map literal escapes to heap"
+func foo90(x *int) map[*int]*int { // ERROR "leaking param: x"
+	return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap"
 }
 
-func foo91(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
-	return map[*int]*int{x: nil} // ERROR "map literal escapes to heap"
+func foo91(x *int) map[*int]*int { // ERROR "leaking param: x"
+	return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap"
 }
 
-func foo92(x *int) [2]*int { // ERROR "leaking param: NAME-x"
+func foo92(x *int) [2]*int { // ERROR "leaking param: x"
 	return [2]*int{x, nil}
 }
 
@@ -642,7 +675,7 @@ func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape"
 }
 
 // does leak x
-func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: NAME-x"
+func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: x"
 	m[x] = x
 }
 
@@ -652,7 +685,7 @@ func foo96(m []*int) *int { // ERROR "m does not escape"
 }
 
 // does leak m
-func foo97(m [1]*int) *int { // ERROR "leaking param: NAME-m"
+func foo97(m [1]*int) *int { // ERROR "leaking param: m"
 	return m[0]
 }
 
@@ -662,7 +695,7 @@ func foo98(m map[int]*int) *int { // ERROR "m does not escape"
 }
 
 // does leak m
-func foo99(m *[1]*int) []*int { // ERROR "leaking param: NAME-m"
+func foo99(m *[1]*int) []*int { // ERROR "leaking param: m"
 	return m[:]
 }
 
@@ -675,7 +708,7 @@ func foo100(m []*int) *int { // ERROR "m does not escape"
 }
 
 // does leak m
-func foo101(m [1]*int) *int { // ERROR "leaking param: NAME-m"
+func foo101(m [1]*int) *int { // ERROR "leaking param: m"
 	for _, v := range m {
 		return v
 	}
@@ -684,14 +717,14 @@ func foo101(m [1]*int) *int { // ERROR "leaking param: NAME-m"
 
 // does not leak m
 func foo101a(m [1]*int) *int { // ERROR "m does not escape"
-	for i := range m { // ERROR "moved to heap: NAME-i"
-		return &i  // ERROR "&i escapes to heap"
+	for i := range m { // ERROR "moved to heap: i"
+		return &i // ERROR "&i escapes to heap"
 	}
 	return nil
 }
 
 // does leak x
-func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: NAME-x"
+func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: x"
 	m[0] = x
 }
 
@@ -703,89 +736,89 @@ func foo103(m [1]*int, x *int) { // ERROR "m does not escape" "x does not escape
 var y []*int
 
 // does not leak x
-func foo104(x []*int) {  // ERROR "x does not escape"
+func foo104(x []*int) { // ERROR "x does not escape"
 	copy(y, x)
 }
 
 // does not leak x
-func foo105(x []*int) {  // ERROR "x does not escape"
+func foo105(x []*int) { // ERROR "x does not escape"
 	_ = append(y, x...)
 }
 
 // does leak x
-func foo106(x *int) { // ERROR "leaking param: NAME-x"
+func foo106(x *int) { // ERROR "leaking param: x"
 	_ = append(y, x)
 }
 
-func foo107(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
-	return map[*int]*int{x: nil} // ERROR "map literal escapes to heap"
+func foo107(x *int) map[*int]*int { // ERROR "leaking param: x"
+	return map[*int]*int{x: nil} // ERROR "map.* literal escapes to heap"
 }
 
-func foo108(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
-	return map[*int]*int{nil: x} // ERROR "map literal escapes to heap"
+func foo108(x *int) map[*int]*int { // ERROR "leaking param: x"
+	return map[*int]*int{nil: x} // ERROR "map.* literal escapes to heap"
 }
 
-func foo109(x *int) *int { // ERROR "leaking param: NAME-x"
-	m := map[*int]*int{x: nil}  // ERROR "map literal does not escape"
+func foo109(x *int) *int { // ERROR "leaking param: x"
+	m := map[*int]*int{x: nil} // ERROR "map.* literal does not escape"
 	for k, _ := range m {
 		return k
 	}
 	return nil
 }
 
-func foo110(x *int) *int { // ERROR "leaking param: NAME-x"
-	m := map[*int]*int{nil: x}  // ERROR "map literal does not escape"
+func foo110(x *int) *int { // ERROR "leaking param: x"
+	m := map[*int]*int{nil: x} // ERROR "map.* literal does not escape"
 	return m[nil]
 }
 
-func foo111(x *int) *int { // ERROR "leaking param: NAME-x"
-	m := []*int{x}  // ERROR "slice literal does not escape"
+func foo111(x *int) *int { // ERROR "leaking param: x"
+	m := []*int{x} // ERROR "\[\]\*int literal does not escape"
 	return m[0]
 }
 
-func foo112(x *int) *int { // ERROR "leaking param: NAME-x"
+func foo112(x *int) *int { // ERROR "leaking param: x"
 	m := [1]*int{x}
 	return m[0]
 }
 
-func foo113(x *int) *int { // ERROR "leaking param: NAME-x"
+func foo113(x *int) *int { // ERROR "leaking param: x"
 	m := Bar{ii: x}
 	return m.ii
 }
 
-func foo114(x *int) *int { // ERROR "leaking param: NAME-x"
-	m := &Bar{ii: x}  // ERROR "&struct literal does not escape"
+func foo114(x *int) *int { // ERROR "leaking param: x"
+	m := &Bar{ii: x} // ERROR "&Bar literal does not escape"
 	return m.ii
 }
 
-func foo115(x *int) *int { // ERROR "leaking param: NAME-x"
+func foo115(x *int) *int { // ERROR "leaking param: x"
 	return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1))
 }
 
 func foo116(b bool) *int {
 	if b {
-		x := 1  // ERROR "moved to heap: NAME-x"
-		return &x  // ERROR "&x escapes to heap"
+		x := 1    // ERROR "moved to heap: x"
+		return &x // ERROR "&x escapes to heap"
 	} else {
-		y := 1  // ERROR "moved to heap: NAME-y"
-		return &y  // ERROR "&y escapes to heap"
+		y := 1    // ERROR "moved to heap: y"
+		return &y // ERROR "&y escapes to heap"
 	}
 	return nil
 }
 
-func foo117(unknown func(interface{})) {  // ERROR "unknown does not escape"
-	x := 1 // ERROR "moved to heap: NAME-x"
+func foo117(unknown func(interface{})) { // ERROR "unknown does not escape"
+	x := 1      // ERROR "moved to heap: x"
 	unknown(&x) // ERROR "&x escapes to heap"
 }
 
-func foo118(unknown func(*int)) {  // ERROR "unknown does not escape"
-	x := 1 // ERROR "moved to heap: NAME-x"
+func foo118(unknown func(*int)) { // ERROR "unknown does not escape"
+	x := 1      // ERROR "moved to heap: x"
 	unknown(&x) // ERROR "&x escapes to heap"
 }
 
 func external(*int)
 
-func foo119(x *int) {  // ERROR "leaking param: NAME-x"
+func foo119(x *int) { // ERROR "leaking param: x"
 	external(x)
 }
 
@@ -993,3 +1026,39 @@ L100:
 	goto L99
 	goto L100
 }
+
+func foo121() {
+	for i := 0; i < 10; i++ {
+		defer myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap"
+		go myprint(nil, i)    // ERROR "[.][.][.] argument escapes to heap"
+	}
+}
+
+// same as foo121 but check across import
+func foo121b() {
+	for i := 0; i < 10; i++ {
+		defer fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap"
+		go fmt.Printf("%d", i)    // ERROR "[.][.][.] argument escapes to heap"
+	}
+}
+
+// a harmless forward jump
+func foo122() {
+	var i *int
+
+	goto L1
+L1:
+	i = new(int) // ERROR "does not escape"
+	_ = i
+}
+
+// a backward jump, increases loopdepth
+func foo123() {
+	var i *int
+
+L1:
+	i = new(int) // ERROR "escapes"
+
+	goto L1
+	_ = i
+}
diff --git a/test/fixedbugs/bug014.go b/test/fixedbugs/bug014.go
index dac2ce5..38a6e51 100644
--- a/test/fixedbugs/bug014.go
+++ b/test/fixedbugs/bug014.go
@@ -11,4 +11,5 @@ func main() {
 	var c01 uint8 = '\07';  // ERROR "oct|char"
 	var cx0 uint8 = '\x0';  // ERROR "hex|char"
 	var cx1 uint8 = '\x';  // ERROR "hex|char"
+	_, _, _, _ = c00, c01, cx0, cx1
 }
diff --git a/test/fixedbugs/bug027.go b/test/fixedbugs/bug027.go
index acc295d..cf2daae 100644
--- a/test/fixedbugs/bug027.go
+++ b/test/fixedbugs/bug027.go
@@ -6,53 +6,76 @@
 
 package main
 
+import "fmt"
+
 type Element interface {
 }
 
 type Vector struct {
-	nelem int;
-	elem []Element;
+	nelem int
+	elem  []Element
 }
 
 func New() *Vector {
-	v := new(Vector);
-	v.nelem = 0;
-	v.elem = make([]Element, 10);
-	return v;
+	v := new(Vector)
+	v.nelem = 0
+	v.elem = make([]Element, 10)
+	return v
 }
 
 func (v *Vector) At(i int) Element {
-	return v.elem[i];
+	return v.elem[i]
 }
 
 func (v *Vector) Insert(e Element) {
-	v.elem[v.nelem] = e;
-	v.nelem++;
+	v.elem[v.nelem] = e
+	v.nelem++
 }
 
 func main() {
-	type I struct { val int; };
-	i0 := new(I); i0.val = 0;
-	i1 := new(I); i1.val = 11;
-	i2 := new(I); i2.val = 222;
-	i3 := new(I); i3.val = 3333;
-	i4 := new(I); i4.val = 44444;
-	v := New();
-	print("hi\n");
-	v.Insert(i4);
-	v.Insert(i3);
-	v.Insert(i2);
-	v.Insert(i1);
-	v.Insert(i0);
+	type I struct{ val int }
+	i0 := new(I)
+	i0.val = 0
+	i1 := new(I)
+	i1.val = 11
+	i2 := new(I)
+	i2.val = 222
+	i3 := new(I)
+	i3.val = 3333
+	i4 := new(I)
+	i4.val = 44444
+	v := New()
+	r := "hi\n"
+	v.Insert(i4)
+	v.Insert(i3)
+	v.Insert(i2)
+	v.Insert(i1)
+	v.Insert(i0)
 	for i := 0; i < v.nelem; i++ {
-		var x *I;
-		x = v.At(i).(*I);
-		print(i, " ", x.val, "\n");  // prints correct list
+		var x *I
+		x = v.At(i).(*I)
+		r += fmt.Sprintln(i, x.val) // prints correct list
 	}
 	for i := 0; i < v.nelem; i++ {
-		print(i, " ", v.At(i).(*I).val, "\n");
+		r += fmt.Sprintln(i, v.At(i).(*I).val)
+	}
+	expect := `hi
+0 44444
+1 3333
+2 222
+3 11
+4 0
+0 44444
+1 3333
+2 222
+3 11
+4 0
+`
+	if r != expect {
+		panic(r)
 	}
 }
+
 /*
 bug027.go:50: illegal types for operand
 	(<Element>I{}) CONV (<I>{})
diff --git a/test/fixedbugs/bug067.go b/test/fixedbugs/bug067.go
index b812f01..328d191 100644
--- a/test/fixedbugs/bug067.go
+++ b/test/fixedbugs/bug067.go
@@ -10,6 +10,6 @@ var c chan int
 
 func main() {
 	c = make(chan int);
-	go func() { print("ok\n"); c <- 0 } ();
+	go func() { c <- 0 } ();
 	<-c
 }
diff --git a/test/fixedbugs/bug070.go b/test/fixedbugs/bug070.go
index 6afdd46..24ac779 100644
--- a/test/fixedbugs/bug070.go
+++ b/test/fixedbugs/bug070.go
@@ -6,20 +6,35 @@
 
 package main
 
+import "fmt"
+
 func main() {
-	var i, k int;
-	outer:
-	for k=0; k<2; k++ {
-		print("outer loop top k ", k, "\n");
-		if k != 0 { panic("k not zero") }  // inner loop breaks this one every time
-		for i=0; i<2; i++ {
-			if i != 0 { panic("i not zero") }  // loop breaks every time
-			print("inner loop top i ", i, "\n");
+	var i, k int
+	var r string
+outer:
+	for k = 0; k < 2; k++ {
+		r += fmt.Sprintln("outer loop top k", k)
+		if k != 0 {
+			panic("k not zero")
+		} // inner loop breaks this one every time
+		for i = 0; i < 2; i++ {
+			if i != 0 {
+				panic("i not zero")
+			} // loop breaks every time
+			r += fmt.Sprintln("inner loop top i", i)
 			if true {
-				print("do break\n");
-				break outer;
+				r += "do break\n"
+				break outer
 			}
 		}
 	}
-	print("broke\n");
+	r += "broke\n"
+	expect := `outer loop top k 0
+inner loop top i 0
+do break
+broke
+`
+	if r != expect {
+		panic(r)
+	}
 }
diff --git a/test/fixedbugs/bug093.go b/test/fixedbugs/bug093.go
index f80eee0..52d92c7 100644
--- a/test/fixedbugs/bug093.go
+++ b/test/fixedbugs/bug093.go
@@ -10,7 +10,6 @@ type S struct {
 }
 
 func (p *S) M() {
-	print("M\n");
 }
 
 type I interface {
diff --git a/test/fixedbugs/bug107.go b/test/fixedbugs/bug107.go
index d0b062a..0554bbc 100644
--- a/test/fixedbugs/bug107.go
+++ b/test/fixedbugs/bug107.go
@@ -6,7 +6,7 @@
 
 package main
 import os "os"
-type _ os.Error
+type _ os.FileInfo
 func f() (os int) {
 	 // In the next line "os" should refer to the result variable, not
 	 // to the package.
diff --git a/test/fixedbugs/bug108.go b/test/fixedbugs/bug108.go
index 5c7649f..10e406d 100644
--- a/test/fixedbugs/bug108.go
+++ b/test/fixedbugs/bug108.go
@@ -7,4 +7,5 @@
 package main
 func f() {
 	v := 1 << 1025;		// ERROR "overflow|stupid shift"
+	_ = v
 }
diff --git a/test/fixedbugs/bug113.go b/test/fixedbugs/bug113.go
index 4fd322d..4ca07dc 100644
--- a/test/fixedbugs/bug113.go
+++ b/test/fixedbugs/bug113.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should not succeed)
+// $G $D/$F.go && $L $F.$A && ./$A.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -21,8 +21,24 @@ func main() {
 	if foo2(v2) != 1 {
 		panic(2)
 	}
+	
+	shouldPanic(p1)
+}
+
+func p1() {
+	var i I
+	i = 1
 	var v3 = i.(int32) // This type conversion should fail at runtime.
 	if foo2(v3) != 1 {
 		panic(3)
 	}
 }
+
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("function should panic")
+		}
+	}()
+	f()
+}
diff --git a/test/fixedbugs/bug120.go b/test/fixedbugs/bug120.go
index 2a71957..bf401bf 100644
--- a/test/fixedbugs/bug120.go
+++ b/test/fixedbugs/bug120.go
@@ -41,16 +41,16 @@ func main() {
 	ok := true
 	for i := 0; i < len(tests); i++ {
 		t := tests[i]
-		v := strconv.Ftoa64(t.f, 'g', -1)
+		v := strconv.FormatFloat(t.f, 'g', -1, 64)
 		if v != t.out {
 			println("Bad float64 const:", t.in, "want", t.out, "got", v)
-			x, err := strconv.Atof64(t.out)
+			x, err := strconv.ParseFloat(t.out, 64)
 			if err != nil {
 				println("bug120: strconv.Atof64", t.out)
 				panic("fail")
 			}
-			println("\twant exact:", strconv.Ftoa64(x, 'g', 1000))
-			println("\tgot exact: ", strconv.Ftoa64(t.f, 'g', 1000))
+			println("\twant exact:", strconv.FormatFloat(x, 'g', 1000, 64))
+			println("\tgot exact: ", strconv.FormatFloat(t.f, 'g', 1000, 64))
 			ok = false
 		}
 	}
diff --git a/test/fixedbugs/bug141.go b/test/fixedbugs/bug141.go
index 756ba30..1b125e5 100644
--- a/test/fixedbugs/bug141.go
+++ b/test/fixedbugs/bug141.go
@@ -20,7 +20,7 @@ type Getter interface {
 
 func f1(p Empty) {
 	switch x := p.(type) {
-	default: println("failed to match interface"); os.Exit(1);
+	default: println("failed to match interface", x); os.Exit(1);
 	case Getter: break;
 	}
 
diff --git a/test/fixedbugs/bug148.go b/test/fixedbugs/bug148.go
index daedff1..251020c 100644
--- a/test/fixedbugs/bug148.go
+++ b/test/fixedbugs/bug148.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ! ./$A.out || echo BUG: should crash
+// $G $D/$F.go && $L $F.$A && ./$A.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -8,6 +8,8 @@ package main
 
 type T struct {a, b int};
 
+func println(x, y int) { }
+
 func f(x interface{}) interface{} {
 	type T struct {a, b int};
 
@@ -24,16 +26,29 @@ func main() {
 	inner_T := f(nil);
 	f(inner_T);
 
+	shouldPanic(p1)
+}
+
+func p1() {
 	outer_T := T{5, 7};
 	f(outer_T);
 }
 
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("function should panic")
+		}
+	}()
+	f()
+}
+
 /*
 This prints:
 
 2 3
 5 7
 
-but it should crash: The type assertion on line 14 should fail
+but it should crash: The type assertion on line 18 should fail
 for the 2nd call to f with outer_T.
 */
diff --git a/test/fixedbugs/bug175.go b/test/fixedbugs/bug175.go
index a8f6e3c..1ca1415 100644
--- a/test/fixedbugs/bug175.go
+++ b/test/fixedbugs/bug175.go
@@ -10,5 +10,5 @@ func f() (int, bool) { return 0, true }
 
 func main() {
 	x, y := f(), 2;	// ERROR "multi"
+	_, _ = x, y
 }
-
diff --git a/test/fixedbugs/bug200.go b/test/fixedbugs/bug200.go
index 123f687..63b8633 100644
--- a/test/fixedbugs/bug200.go
+++ b/test/fixedbugs/bug200.go
@@ -12,7 +12,7 @@ func main() {
 	// and worse, compiled the wrong code
 	// for one of them.
 	var x interface{};
-	switch v := x.(type) {
+	switch x.(type) {
 	case func(int):
 	case func(f int):	// ERROR "duplicate"
 	}
diff --git a/test/fixedbugs/bug204.go b/test/fixedbugs/bug204.go
index d4534c2..adf0aaf 100644
--- a/test/fixedbugs/bug204.go
+++ b/test/fixedbugs/bug204.go
@@ -7,18 +7,18 @@
 package main
 
 func main() {
-	nchar := 0;
-	a := []int { '日', '本', '語', 0xFFFD };
+	nchar := 0
+	a := []rune{'日', '本', '語', 0xFFFD}
 	for _, char := range "日本語\xc0" {
 		if nchar >= len(a) {
-			println("BUG");
-			break;
+			println("BUG")
+			break
 		}
 		if char != a[nchar] {
-			println("expected", a[nchar], "got", char);
-			println("BUG");
-			break;
+			println("expected", a[nchar], "got", char)
+			println("BUG")
+			break
 		}
-		nchar++;
+		nchar++
 	}
 }
diff --git a/test/fixedbugs/bug213.go b/test/fixedbugs/bug213.go
index 07d9f90..4d81dbb 100644
--- a/test/fixedbugs/bug213.go
+++ b/test/fixedbugs/bug213.go
@@ -7,7 +7,7 @@
 package main
 func main() {
 	var v interface{} = 0;
-	switch x := v.(type) {
+	switch v.(type) {
 	case int:
 		fallthrough;		// ERROR "fallthrough"
 	default:
diff --git a/test/fixedbugs/bug220.go b/test/fixedbugs/bug220.go
deleted file mode 100644
index ff027dd..0000000
--- a/test/fixedbugs/bug220.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// $G $D/$F.go || echo BUG: bug220
-
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-func main() {
-	m := make(map[int]map[uint]float64)
-
-	m[0] = make(map[uint]float64), false // 6g used to reject this
-	m[1] = nil
-}
diff --git a/test/fixedbugs/bug222.dir/chanbug.go b/test/fixedbugs/bug222.dir/chanbug.go
index 9194927..1692024 100644
--- a/test/fixedbugs/bug222.dir/chanbug.go
+++ b/test/fixedbugs/bug222.dir/chanbug.go
@@ -1,3 +1,7 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file
+
 package chanbug
 var C chan<- (chan int)
 var D chan<- func()
diff --git a/test/fixedbugs/bug222.dir/chanbug2.go b/test/fixedbugs/bug222.dir/chanbug2.go
index 73e1667..109581d 100644
--- a/test/fixedbugs/bug222.dir/chanbug2.go
+++ b/test/fixedbugs/bug222.dir/chanbug2.go
@@ -1,2 +1,6 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file
+
 package Bar
 import _ "chanbug"
diff --git a/test/fixedbugs/bug226.dir/x.go b/test/fixedbugs/bug226.dir/x.go
deleted file mode 100644
index 64d7a29..0000000
--- a/test/fixedbugs/bug226.dir/x.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package x
-
-type T struct { x, Y int }
-
-func (t T) M()
diff --git a/test/fixedbugs/bug226.dir/y.go b/test/fixedbugs/bug226.dir/y.go
deleted file mode 100644
index c66d592..0000000
--- a/test/fixedbugs/bug226.dir/y.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package y
-
-import "./x"
-
-func f() {
-	ok := new(x.T);
-	var ok1 x.T;
-	ok2 := &ok1;
-	ok3 := &x.T{};
-	ok4 := &x.T{Y:2};
-	_ = x.T{};
-	_ = x.T{Y:2};
-	
-	ok1.M();
-	bad1 := *ok;	// ERROR "assignment.*T"
-	bad2 := ok1;	// ERROR "assignment.*T"
-	*ok4 = ok1;	// ERROR "assignment.*T"
-	*ok4 = *ok2;	// ERROR "assignment.*T"
-	ok1 = *ok4;	// ERROR "assignment.*T"
-	_ = bad1;
-	_ = bad2;
-	_ = ok4;
-	_ = ok3;
-	_ = ok2;
-	_ = ok1;
-	_ = ok;
-}
diff --git a/test/fixedbugs/bug226.go b/test/fixedbugs/bug226.go
deleted file mode 100644
index 5457a64..0000000
--- a/test/fixedbugs/bug226.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// $G $D/$F.dir/x.go && errchk $G $D/$F.dir/y.go
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-ignored
diff --git a/test/fixedbugs/bug229.go b/test/fixedbugs/bug229.go
index 6c9de9b..a70a926 100644
--- a/test/fixedbugs/bug229.go
+++ b/test/fixedbugs/bug229.go
@@ -12,9 +12,9 @@ func main() {
 	var t testing.T
 	
 	// make sure error mentions that
-	// ch is unexported, not just "ch not found".
+	// name is unexported, not just "name not found".
 
-	t.ch = nil	// ERROR "unexported"
+	t.name = nil	// ERROR "unexported"
 	
 	println(testing.anyLowercaseName("asdf"))	// ERROR "unexported" "undefined: testing.anyLowercaseName"
 }
diff --git a/test/fixedbugs/bug242.go b/test/fixedbugs/bug242.go
index 839dccd..d80ae76 100644
--- a/test/fixedbugs/bug242.go
+++ b/test/fixedbugs/bug242.go
@@ -93,7 +93,8 @@ func main() {
 
 	m[13] = 'B'
 	//  13        14
-	m[gint()] = gbyte(), false
+	delete(m, gint())
+	gbyte()
 	if _, present := m[13]; present {
 		println("bad map removal")
 		panic("fail")
diff --git a/test/fixedbugs/bug243.go b/test/fixedbugs/bug243.go
index 95514cf..e3ddf0e 100644
--- a/test/fixedbugs/bug243.go
+++ b/test/fixedbugs/bug243.go
@@ -6,7 +6,7 @@
 
 package main
 
-import "os"
+import "errors"
 
 // Issue 481: closures and var declarations
 // with multiple variables assigned from one
@@ -22,7 +22,7 @@ func main() {
 		}
 	}()
 
-	var conn, _ = Dial("tcp", "", listen.Addr().String())
+	var conn, _ = Dial("tcp", "", listen.Addr().Error())
 	_ = conn
 }
 
@@ -37,8 +37,8 @@ func Listen(x, y string) (T, string) {
 	return global, y
 }
 
-func (t T) Addr() os.Error {
-	return os.NewError("stringer")
+func (t T) Addr() error {
+	return errors.New("stringer")
 }
 
 func (t T) Accept() (int, string) {
diff --git a/test/fixedbugs/bug248.dir/bug0.go b/test/fixedbugs/bug248.dir/bug0.go
index 7fc7401..78433f5 100644
--- a/test/fixedbugs/bug248.dir/bug0.go
+++ b/test/fixedbugs/bug248.dir/bug0.go
@@ -1,3 +1,7 @@
+// Copyright 2010 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 p
 
 type T struct {
diff --git a/test/fixedbugs/bug248.dir/bug1.go b/test/fixedbugs/bug248.dir/bug1.go
index 7fc7401..78433f5 100644
--- a/test/fixedbugs/bug248.dir/bug1.go
+++ b/test/fixedbugs/bug248.dir/bug1.go
@@ -1,3 +1,7 @@
+// Copyright 2010 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 p
 
 type T struct {
diff --git a/test/fixedbugs/bug248.dir/bug2.go b/test/fixedbugs/bug248.dir/bug2.go
index b6c816a..ba547d6 100644
--- a/test/fixedbugs/bug248.dir/bug2.go
+++ b/test/fixedbugs/bug248.dir/bug2.go
@@ -1,3 +1,7 @@
+// Copyright 2010 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 (
@@ -80,7 +84,7 @@ func main() {
 		case 2:
 			i = 3.14
 		}
-		switch k := i.(type) {
+		switch i.(type) {
 		case p0.T:
 			if j != 0 {
 				println("type switch p0.T")
diff --git a/test/fixedbugs/bug248.dir/bug3.go b/test/fixedbugs/bug248.dir/bug3.go
index e5a2449..4a56c5c 100644
--- a/test/fixedbugs/bug248.dir/bug3.go
+++ b/test/fixedbugs/bug248.dir/bug3.go
@@ -1,3 +1,7 @@
+// Copyright 2010 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 (
diff --git a/test/fixedbugs/bug251.go b/test/fixedbugs/bug251.go
index c94ad2a..385f28d 100644
--- a/test/fixedbugs/bug251.go
+++ b/test/fixedbugs/bug251.go
@@ -16,6 +16,6 @@ type I2 interface {
 }
 
 
-var i1 I1 = i2 // GC_ERROR "missing m method|need type assertion"
+var i1 I1 = i2
 var i2 I2
 var i2a I2 = i1
diff --git a/test/fixedbugs/bug257.go b/test/fixedbugs/bug257.go
index 713c424..1b32475 100644
--- a/test/fixedbugs/bug257.go
+++ b/test/fixedbugs/bug257.go
@@ -20047,11 +20047,10 @@ var gettysburg = "  Four score and seven years ago our fathers brought forth on\
 	"\n" +
 	"Abraham Lincoln, November 19, 1863, Gettysburg, Pennsylvania\n"
 
-
 func main() {
 	m := md5.New()
 	io.WriteString(m, data)
-	hash := fmt.Sprintf("%x", m.Sum())
+	hash := fmt.Sprintf("%x", m.Sum(nil))
 	if hash != "525f06bc62a65017cd2217d7584e5920" {
 		println("BUG a", hash)
 		return
@@ -20059,7 +20058,7 @@ func main() {
 
 	m = md5.New()
 	io.WriteString(m, gettysburg)
-	hash = fmt.Sprintf("%x", m.Sum())
+	hash = fmt.Sprintf("%x", m.Sum(nil))
 	if hash != "d7ec5d9d47a4d166091e8d9ebd7ea0aa" {
 		println("BUG gettysburg", hash)
 		println(len(gettysburg))
diff --git a/test/fixedbugs/bug260.go b/test/fixedbugs/bug260.go
index 34757c7..39d29b4 100644
--- a/test/fixedbugs/bug260.go
+++ b/test/fixedbugs/bug260.go
@@ -1,5 +1,9 @@
 // $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug260 failed
 
+// Copyright 2010 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 structures pack densely, according to the alignment of the largest field.
 
 package main
@@ -24,8 +28,8 @@ func main() {
 	report := len(os.Args) > 1
 	status := 0
 	var b1 [10]T1
-	a0, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[0])[2:], 16)
-	a1, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[1])[2:], 16)
+	a0, _ := strconv.ParseUint(fmt.Sprintf("%p", &b1[0])[2:], 16, 64)
+	a1, _ := strconv.ParseUint(fmt.Sprintf("%p", &b1[1])[2:], 16, 64)
 	if a1 != a0+1 {
 		fmt.Println("FAIL")
 		if report {
@@ -34,8 +38,8 @@ func main() {
 		status = 1
 	}
 	var b2 [10]T2
-	a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[0])[2:], 16)
-	a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[1])[2:], 16)
+	a0, _ = strconv.ParseUint(fmt.Sprintf("%p", &b2[0])[2:], 16, 64)
+	a1, _ = strconv.ParseUint(fmt.Sprintf("%p", &b2[1])[2:], 16, 64)
 	if a1 != a0+2 {
 		if status == 0 {
 			fmt.Println("FAIL")
@@ -46,8 +50,8 @@ func main() {
 		}
 	}
 	var b4 [10]T4
-	a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[0])[2:], 16)
-	a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[1])[2:], 16)
+	a0, _ = strconv.ParseUint(fmt.Sprintf("%p", &b4[0])[2:], 16, 64)
+	a1, _ = strconv.ParseUint(fmt.Sprintf("%p", &b4[1])[2:], 16, 64)
 	if a1 != a0+4 {
 		if status == 0 {
 			fmt.Println("FAIL")
diff --git a/test/fixedbugs/bug262.go b/test/fixedbugs/bug262.go
index 66f580b..f5f2c35 100644
--- a/test/fixedbugs/bug262.go
+++ b/test/fixedbugs/bug262.go
@@ -18,9 +18,9 @@ func f() string {
 	return "abc"
 }
 
-func g() *os.Error {
+func g() *error {
 	trace += "g"
-	var x os.Error
+	var x error
 	return &x
 }
 
@@ -35,7 +35,6 @@ func i() *int {
 	return &i
 }
 
-
 func main() {
 	m := make(map[string]int)
 	m[f()], *g() = strconv.Atoi(h())
@@ -43,7 +42,7 @@ func main() {
 		println("BUG", m["abc"], trace)
 		panic("fail")
 	}
-	mm := make(map[string]os.Error)
+	mm := make(map[string]error)
 	trace = ""
 	mm["abc"] = os.EINVAL
 	*i(), mm[f()] = strconv.Atoi(h())
diff --git a/test/fixedbugs/bug268.go b/test/fixedbugs/bug268.go
deleted file mode 100644
index a38d054..0000000
--- a/test/fixedbugs/bug268.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
-
-// Copyright 2010 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.
-
-// http://code.google.com/p/go/issues/detail?id=745
-
-package main
-
-type T1 struct {
-	T2 *T2
-}
-
-type T2 struct {
-	T3 *T3
-}
-
-type T3 struct {
-	T4 []*T4
-}
-
-type T4 struct {
-	X int
-}
-
-func f() *T1 {
-	x := &T1{
-		&T2{
-			&T3{
-				[1]*T4{
-					&T4{5},
-				}[0:],
-			},
-		},
-	}
-	return x
-}
-
-func g(x int) {
-	if x == 0 {
-		return
-	}
-	g(x-1)
-}
-
-func main() {
-	x := f()
-	g(100) // smash temporaries left over on stack
-	if x.T2.T3.T4[0].X != 5 {
-		println("BUG", x.T2.T3.T4[0].X)
-	}
-}
diff --git a/test/fixedbugs/bug270.go b/test/fixedbugs/bug270.go
deleted file mode 100644
index a9cda7b..0000000
--- a/test/fixedbugs/bug270.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// $G $D/$F.go
-
-// Copyright 2010 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.
-
-// http://code.google.com/p/go/issues/detail?id=746
-
-package main
-
-type I interface { F() }
-
-type T struct{}
-
-func (T) F() {}
-
-func main() {
-	switch I(T{}).(type) {
-	case interface{}:
-	}
-}
diff --git a/test/fixedbugs/bug285.go b/test/fixedbugs/bug285.go
index 544d348..7eed8fb 100644
--- a/test/fixedbugs/bug285.go
+++ b/test/fixedbugs/bug285.go
@@ -45,20 +45,6 @@ func main() {
 	mp[p] = 42
 	mp[&T{7}] = 42
 
-	type F func(x int)
-	f := func(x int) {}
-	mf := make(map[F]int)
-	mf[nil] = 42
-	mf[f] = 42
-	mf[func(x int) {}] = 42
-
-	type M map[int]int
-	m := make(M)
-	mm := make(map[M]int)
-	mm[nil] = 42
-	mm[m] = 42
-	mm[make(M)] = 42
-
 	type C chan int
 	c := make(C)
 	mc := make(map[C]int)
diff --git a/test/fixedbugs/bug286.go b/test/fixedbugs/bug286.go
index 94423be..eb67838 100644
--- a/test/fixedbugs/bug286.go
+++ b/test/fixedbugs/bug286.go
@@ -12,16 +12,14 @@ type I interface {
 	f()
 }
 
-
 var callee string
-var error bool
+var error_ bool
 
 type T int
 
 func (t *T) f() { callee = "f" }
 func (i *T) g() { callee = "g" }
 
-
 // test1 and test2 are the same except that in the interface J
 // the entries are swapped. test2 and test3 are the same except
 // that in test3 the interface J is declared outside the function.
@@ -36,11 +34,10 @@ func test1(x I) {
 	x.(J).f()
 	if callee != "f" {
 		println("test1 called", callee)
-		error = true
+		error_ = true
 	}
 }
 
-
 func test2(x I) {
 	type J interface {
 		g()
@@ -49,11 +46,10 @@ func test2(x I) {
 	x.(J).f()
 	if callee != "f" {
 		println("test2 called", callee)
-		error = true
+		error_ = true
 	}
 }
 
-
 type J interface {
 	g()
 	I
@@ -63,7 +59,7 @@ func test3(x I) {
 	x.(J).f()
 	if callee != "f" {
 		println("test3 called", callee)
-		error = true
+		error_ = true
 	}
 }
 
@@ -72,7 +68,7 @@ func main() {
 	test1(x)
 	test2(x)
 	test3(x)
-	if error {
+	if error_ {
 		panic("wrong method called")
 	}
 }
diff --git a/test/fixedbugs/bug309.go b/test/fixedbugs/bug309.go
index 07bebae..d893916 100644
--- a/test/fixedbugs/bug309.go
+++ b/test/fixedbugs/bug309.go
@@ -15,5 +15,7 @@ func foo(t interface{}, c chan int) {
 		case <-c:
 			// bug was: internal compiler error: var without type, init: v
 		}
+	default:
+		_ = v
 	}
 }
diff --git a/test/fixedbugs/bug310.go b/test/fixedbugs/bug310.go
deleted file mode 100644
index 191f3ed..0000000
--- a/test/fixedbugs/bug310.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// errchk $G $D/$F.go
-
-// Copyright 2010 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 p
-
-import (
-	"bytes"
-	"fmt"
-)
-
-type t int
-
-func main() {
-	_ = t.bar	// ERROR "no method"
-	var b bytes.Buffer
-	fmt.Print(b)	// ERROR "implicit assignment"
-}
diff --git a/test/fixedbugs/bug326.go b/test/fixedbugs/bug326.go
index efdd0ef..7e123e3 100644
--- a/test/fixedbugs/bug326.go
+++ b/test/fixedbugs/bug326.go
@@ -6,36 +6,34 @@
 
 package p
 
-import "os"
-
-func f() (_ int, err os.Error) {
+func f() (_ int, err error) {
 	return
 }
 
-func g() (x int, _ os.Error) {
+func g() (x int, _ error) {
 	return
 }
 
-func h() (_ int, _ os.Error) {
+func h() (_ int, _ error) {
 	return
 }
 
-func i() (int, os.Error) {
-	return	// ERROR "not enough arguments to return"
+func i() (int, error) {
+	return // ERROR "not enough arguments to return"
 }
 
-func f1() (_ int, err os.Error) {
+func f1() (_ int, err error) {
 	return 1, nil
 }
 
-func g1() (x int, _ os.Error) {
+func g1() (x int, _ error) {
 	return 1, nil
 }
 
-func h1() (_ int, _ os.Error) {
+func h1() (_ int, _ error) {
 	return 1, nil
 }
 
-func ii() (int, os.Error) {
+func ii() (int, error) {
 	return 1, nil
 }
diff --git a/test/fixedbugs/bug328.go b/test/fixedbugs/bug328.go
index 64041f4..8252983 100644
--- a/test/fixedbugs/bug328.go
+++ b/test/fixedbugs/bug328.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
+// $G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out
 
 // Copyright 2011 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug328.out b/test/fixedbugs/bug328.out
new file mode 100644
index 0000000..9982566
--- /dev/null
+++ b/test/fixedbugs/bug328.out
@@ -0,0 +1 @@
+0x0
diff --git a/test/fixedbugs/bug331.go b/test/fixedbugs/bug331.go
index 28aee1d..6c5acd1 100644
--- a/test/fixedbugs/bug331.go
+++ b/test/fixedbugs/bug331.go
@@ -6,22 +6,22 @@
 
 package main
 
-import "os"
+import "io"
 
-func f() (_ string, x float64, err os.Error) {
+func f() (_ string, x float64, err error) {
 	return
 }
 
-func g() (_ string, x float64, err os.Error) {
-	return "hello", 3.14, os.EOF
+func g() (_ string, x float64, err error) {
+	return "hello", 3.14, io.EOF
 }
 
-var _ func() (string, float64, os.Error) = f
-var _ func() (string, float64, os.Error) = g
+var _ func() (string, float64, error) = f
+var _ func() (string, float64, error) = g
 
 func main() {
 	x, y, z := g()
-	if x != "hello" || y != 3.14 || z != os.EOF {
+	if x != "hello" || y != 3.14 || z != io.EOF {
 		println("wrong", x, len(x), y, z)
 	}
 }
diff --git a/test/fixedbugs/bug340.go b/test/fixedbugs/bug340.go
index 461cc6c..34cc013 100644
--- a/test/fixedbugs/bug340.go
+++ b/test/fixedbugs/bug340.go
@@ -10,8 +10,8 @@ package main
 
 func main() {
 	var x interface{}
-	switch t := x.(type) { // ERROR "0 is not a type"
-	case 0:
-		t.x = 1 // ERROR "type interface \{ \}"
+	switch t := x.(type) {
+	case 0:		// ERROR "type"
+		t.x = 1 // ERROR "type interface \{\}|reference to undefined field or method"
 	}
 }
diff --git a/test/fixedbugs/bug345.dir/main.go b/test/fixedbugs/bug345.dir/main.go
index 5bdc713..ddba8da 100644
--- a/test/fixedbugs/bug345.dir/main.go
+++ b/test/fixedbugs/bug345.dir/main.go
@@ -22,7 +22,7 @@ func main() {
 	// main.go:27: cannot use &x (type *"io".SectionReader) as type *"/Users/rsc/g/go/test/fixedbugs/bug345.dir/io".SectionReader in function argument
 
 	var w io.Writer
-	bufio.NewWriter(w)  // ERROR "test/io"
+	bufio.NewWriter(w)  // ERROR "test/io|has incompatible type"
 	var x goio.SectionReader
-	io.SR(&x)  // ERROR "test/io"
+	io.SR(&x)  // ERROR "test/io|has incompatible type"
 }
diff --git a/test/fixedbugs/bug350.go b/test/fixedbugs/bug350.go
index aac2949..f8df3f5 100644
--- a/test/fixedbugs/bug350.go
+++ b/test/fixedbugs/bug350.go
@@ -8,8 +8,8 @@ package main
 
 type T int
 
-func (T) m() {}
-func (T) m() {} // ERROR "T[.]m redeclared"
+func (T) m() {} // GCCGO_ERROR "previous"
+func (T) m() {} // ERROR "T[.]m redeclared|redefinition"
 
-func (*T) p() {}
-func (*T) p() {} // ERROR "[(][*]T[)][.]p redeclared"
+func (*T) p() {} // GCCGO_ERROR "previous"
+func (*T) p() {} // ERROR "[(][*]T[)][.]p redeclared|redefinition"
diff --git a/test/fixedbugs/bug351.go b/test/fixedbugs/bug351.go
index 2f631bb..9625c6a 100644
--- a/test/fixedbugs/bug351.go
+++ b/test/fixedbugs/bug351.go
@@ -9,5 +9,5 @@ package main
 var x int
 
 func main() {
-	(x) := 0  // ERROR "non-name [(]x[)]"
+	(x) := 0  // ERROR "non-name [(]x[)]|non-name on left side"
 }
diff --git a/test/fixedbugs/bug354.go b/test/fixedbugs/bug354.go
index 1f6a6dc..a95256e 100644
--- a/test/fixedbugs/bug354.go
+++ b/test/fixedbugs/bug354.go
@@ -9,12 +9,8 @@
 
 package main
 
-import (
-	"os"
-)
-
 type Inner struct {
-	F func() os.Error
+	F func() error
 }
 
 type Outer struct {
@@ -23,4 +19,4 @@ type Outer struct {
 
 // calls makeclosure twice on same closure
 
-var Foo = Outer{[]Inner{Inner{func() os.Error{ return nil }}}}
+var Foo = Outer{[]Inner{Inner{func() error { return nil }}}}
diff --git a/test/fixedbugs/bug358.go b/test/fixedbugs/bug358.go
index f43709b..82fbf7f 100644
--- a/test/fixedbugs/bug358.go
+++ b/test/fixedbugs/bug358.go
@@ -10,8 +10,8 @@
 package main
 
 import (
-	"http"
 	"io/ioutil"	// GCCGO_ERROR "imported and not used"
+	"net/http"
 	"os"
 )
 
diff --git a/test/fixedbugs/bug359.go b/test/fixedbugs/bug359.go
deleted file mode 100644
index 3701499..0000000
--- a/test/fixedbugs/bug359.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// errchk $G $D/$F.go
-
-// Copyright 2011 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 1910
-// error on wrong line
-
-package main
-
-import "container/list"
-
-type Painting struct {
-	fragments list.List // private
-}
-
-func (p Painting) Foo() {
-	for e := p.fragments; e.Front() != nil; {  // ERROR "unexported field|hidden field"
-	}
-}
-
-// from comment 4 of issue 1910
-type Foo interface {
-	Run(a int) (a int)  // ERROR "a redeclared|redefinition|previous"
-}
diff --git a/test/fixedbugs/bug363.go b/test/fixedbugs/bug363.go
index 04fcfe1..9347ec2 100644
--- a/test/fixedbugs/bug363.go
+++ b/test/fixedbugs/bug363.go
@@ -17,5 +17,5 @@ func main() {
 	println(b)
 
 	var c int64 = (1<<i) + 4.0  // ok - it's all int64
-	println(b)
+	println(c)
 }
diff --git a/test/fixedbugs/bug364.go b/test/fixedbugs/bug364.go
index a174534..a933121 100644
--- a/test/fixedbugs/bug364.go
+++ b/test/fixedbugs/bug364.go
@@ -1,3 +1,9 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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"
diff --git a/test/fixedbugs/bug365.go b/test/fixedbugs/bug365.go
index ce69505..bc8c2c5 100644
--- a/test/fixedbugs/bug365.go
+++ b/test/fixedbugs/bug365.go
@@ -12,11 +12,11 @@
 package main
 
 type S struct {
-	err os.Error  // ERROR "undefined|expected package"
+	err foo.Bar // ERROR "undefined|expected package"
 	Num int
 }
 
 func main() {
 	s := S{}
-	_ = s.Num  // no error here please
+	_ = s.Num // no error here please
 }
diff --git a/test/fixedbugs/bug367.dir/main.go b/test/fixedbugs/bug367.dir/main.go
new file mode 100644
index 0000000..c278e4d
--- /dev/null
+++ b/test/fixedbugs/bug367.dir/main.go
@@ -0,0 +1,28 @@
+// Copyright 2011 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 (
+	"./p"
+)
+
+type T struct{ *p.S }
+type I interface {
+	get()
+}
+
+func main() {
+	var t T
+	p.F(t)
+	var x interface{} = t
+	_, ok := x.(I)
+	if ok {
+		panic("should not satisfy main.I")
+	}
+	_, ok = x.(p.I)
+	if !ok {
+		panic("should satisfy p.I")
+	}
+}
diff --git a/test/fixedbugs/bug367.dir/p.go b/test/fixedbugs/bug367.dir/p.go
new file mode 100644
index 0000000..2028f74
--- /dev/null
+++ b/test/fixedbugs/bug367.dir/p.go
@@ -0,0 +1,19 @@
+// Copyright 2011 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 p
+
+type T struct{ x int }
+type S struct{}
+
+func (p *S) get() {
+}
+
+type I interface {
+	get()
+}
+
+func F(i I) {
+	i.get()
+}
diff --git a/test/fixedbugs/bug367.go b/test/fixedbugs/bug367.go
new file mode 100644
index 0000000..25d11a1
--- /dev/null
+++ b/test/fixedbugs/bug367.go
@@ -0,0 +1,7 @@
+// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out || echo BUG: should not fail
+
+// Copyright 2011 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 ignored
diff --git a/test/fixedbugs/bug368.go b/test/fixedbugs/bug368.go
new file mode 100644
index 0000000..8d94f53
--- /dev/null
+++ b/test/fixedbugs/bug368.go
@@ -0,0 +1,26 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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
+
+// 5g bug used to set up the 0 for -f() before calling f,
+// and the call to f smashed the register.
+
+func f(n int) int {
+	s := 0
+	for i := 0; i < n; i++ {
+		s += i>>1
+	}
+	return s
+}
+
+func main() {
+	x := -f(100)
+	if x != -2450 {
+		println(x)
+		panic("broken")
+	}
+}
diff --git a/test/fixedbugs/bug369.dir/pkg.go b/test/fixedbugs/bug369.dir/pkg.go
new file mode 100644
index 0000000..cf57041
--- /dev/null
+++ b/test/fixedbugs/bug369.dir/pkg.go
@@ -0,0 +1,15 @@
+// Copyright 2011 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 pkg
+
+func NonASCII(b []byte, i int) int {
+	for i = 0; i < len(b); i++ {
+		if b[i] >= 0x80 {
+			break
+		}
+	}
+	return i
+}
+
diff --git a/test/fixedbugs/bug369.go b/test/fixedbugs/bug369.go
new file mode 100644
index 0000000..8eb23ee
--- /dev/null
+++ b/test/fixedbugs/bug369.go
@@ -0,0 +1,59 @@
+// $G -N -o slow.$A $D/bug369.dir/pkg.go &&
+// $G -o fast.$A $D/bug369.dir/pkg.go &&
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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 compiling with optimization turned on produces faster code.
+
+package main
+
+import (
+	"flag"
+	"os"
+	"runtime"
+	"testing"
+
+	fast "./fast"
+	slow "./slow"
+)
+
+var buf = make([]byte, 1048576)
+
+func BenchmarkFastNonASCII(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		fast.NonASCII(buf, 0)
+	}
+}
+
+func BenchmarkSlowNonASCII(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		slow.NonASCII(buf, 0)
+	}
+}
+
+func main() {
+	os.Args = []string{os.Args[0], "-test.benchtime=0.1"}
+	flag.Parse()
+	
+	rslow := testing.Benchmark(BenchmarkSlowNonASCII)
+	rfast := testing.Benchmark(BenchmarkFastNonASCII)
+	tslow := rslow.NsPerOp()
+	tfast := rfast.NsPerOp()
+
+	// Optimization should be good for at least 2x, but be forgiving.
+	// On the ARM simulator we see closer to 1.5x.
+	speedup := float64(tslow)/float64(tfast)
+	want := 1.8
+	if runtime.GOARCH == "arm" {
+		want = 1.3
+	}
+	if speedup < want {
+		// TODO(rsc): doesn't work on linux-amd64 or darwin-amd64 builders, nor on
+		// a Lenovo x200 (linux-amd64) laptop.
+		//println("fast:", tfast, "slow:", tslow, "speedup:", speedup, "want:", want)
+		//println("not fast enough")
+	}
+}
diff --git a/test/fixedbugs/bug370.go b/test/fixedbugs/bug370.go
new file mode 100644
index 0000000..9cb45f6
--- /dev/null
+++ b/test/fixedbugs/bug370.go
@@ -0,0 +1,18 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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
+
+// issue 2337
+// The program deadlocked.
+
+import "runtime"
+
+func main() {
+	runtime.GOMAXPROCS(2)
+	runtime.GC()
+	runtime.GOMAXPROCS(1)
+}
diff --git a/test/fixedbugs/bug371.go b/test/fixedbugs/bug371.go
new file mode 100644
index 0000000..bf993df
--- /dev/null
+++ b/test/fixedbugs/bug371.go
@@ -0,0 +1,24 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2343
+
+package main
+
+type T struct {}
+
+func (t *T) pm() {}
+func (t T) m() {}
+
+func main() {
+	p := &T{}
+	p.pm()
+	p.m()
+
+	q := &p
+	q.m()  // ERROR "requires explicit dereference"
+	q.pm()
+}
diff --git a/test/fixedbugs/bug372.go b/test/fixedbugs/bug372.go
new file mode 100644
index 0000000..a6f7208
--- /dev/null
+++ b/test/fixedbugs/bug372.go
@@ -0,0 +1,28 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug372
+
+// Copyright 2011 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 2355
+package main
+
+type T struct {}
+func (T) m() string { return "T" }
+
+type TT struct {
+	T
+	m func() string
+}
+
+
+func ff() string { return "ff" }
+
+func main() {
+	var tt TT
+	tt.m = ff
+
+	if tt.m() != "ff" {
+		println(tt.m(), "!= \"ff\"")
+	}
+}
diff --git a/test/fixedbugs/bug373.go b/test/fixedbugs/bug373.go
new file mode 100644
index 0000000..934a6c7
--- /dev/null
+++ b/test/fixedbugs/bug373.go
@@ -0,0 +1,32 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 873, 2162
+
+package foo
+
+func f(x interface{}) {
+	switch t := x.(type) {  // ERROR "declared and not used"
+	case int:
+	}
+}
+
+func g(x interface{}) {
+	switch t := x.(type) {
+	case int:
+	case float32:
+		println(t)
+	}
+}
+
+func h(x interface{}) {
+	switch t := x.(type) {
+	case int:
+	case float32:
+	default:
+		println(t)
+	}
+}
diff --git a/test/fixedbugs/bug374.go b/test/fixedbugs/bug374.go
new file mode 100644
index 0000000..2e6f27a
--- /dev/null
+++ b/test/fixedbugs/bug374.go
@@ -0,0 +1,20 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 1556
+package foo
+
+type I interface {
+	m() int
+}
+
+type T int
+
+var _ I = T(0)
+
+func (T) m(buf []byte) (a int, b xxxx) {  // ERROR "xxxx"
+	return 0, nil
+}
\ No newline at end of file
diff --git a/test/fixedbugs/bug375.go b/test/fixedbugs/bug375.go
new file mode 100644
index 0000000..5273585
--- /dev/null
+++ b/test/fixedbugs/bug375.go
@@ -0,0 +1,19 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug375
+
+// Copyright 2011 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 2423
+
+package main
+
+func main() {
+	var x interface{} = "hello"
+
+	switch x {
+	case "hello":
+	default:
+		println("FAIL")
+	}
+}
diff --git a/test/fixedbugs/bug376.go b/test/fixedbugs/bug376.go
new file mode 100644
index 0000000..1efbeec
--- /dev/null
+++ b/test/fixedbugs/bug376.go
@@ -0,0 +1,11 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 1951
+package foo
+import "unsafe"
+var v = unsafe.Sizeof  // ERROR "must be called"
+
diff --git a/test/fixedbugs/bug377.dir/one.go b/test/fixedbugs/bug377.dir/one.go
new file mode 100644
index 0000000..e29b813
--- /dev/null
+++ b/test/fixedbugs/bug377.dir/one.go
@@ -0,0 +1,10 @@
+// Copyright 2011 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 one
+
+func Foo() (n int64, _ *int) {
+	return 42, nil
+}
+
diff --git a/test/fixedbugs/bug377.dir/two.go b/test/fixedbugs/bug377.dir/two.go
new file mode 100644
index 0000000..2a10812
--- /dev/null
+++ b/test/fixedbugs/bug377.dir/two.go
@@ -0,0 +1,8 @@
+// Copyright 2011 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 two
+
+import _ "./one"
+
diff --git a/test/fixedbugs/bug377.go b/test/fixedbugs/bug377.go
new file mode 100644
index 0000000..e905e34
--- /dev/null
+++ b/test/fixedbugs/bug377.go
@@ -0,0 +1,9 @@
+// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go
+
+// Copyright 2011 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 1802
+
+package ignored
diff --git a/test/fixedbugs/bug378.go b/test/fixedbugs/bug378.go
new file mode 100644
index 0000000..b393b3d
--- /dev/null
+++ b/test/fixedbugs/bug378.go
@@ -0,0 +1,19 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug378
+
+// Copyright 2011 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 2497
+
+package main
+
+type Header struct{}
+func (h Header) Method() {}
+
+var _ interface{} = Header{}
+
+func main() {
+  	type X Header
+  	var _ interface{} = X{}
+}
diff --git a/test/fixedbugs/bug379.go b/test/fixedbugs/bug379.go
new file mode 100644
index 0000000..3dd3d29
--- /dev/null
+++ b/test/fixedbugs/bug379.go
@@ -0,0 +1,18 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2452.
+
+// Check that the error messages says 
+//	bug378.go:17: 1 + 2 not used
+// and not
+//	bug378.go:17: 1 not used
+
+package main
+
+func main() {
+	1 + 2 // ERROR "1 \+ 2 not used|value computed is not used"
+}
diff --git a/test/fixedbugs/bug380.go b/test/fixedbugs/bug380.go
new file mode 100644
index 0000000..75b5806
--- /dev/null
+++ b/test/fixedbugs/bug380.go
@@ -0,0 +1,11 @@
+// $G $D/$F.go
+
+// Copyright 2011 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.
+
+// Used to cause a typechecking loop error.
+
+package pkg
+type T map[int]string
+var q = &T{}
diff --git a/test/fixedbugs/bug381.go b/test/fixedbugs/bug381.go
new file mode 100644
index 0000000..3f3232b
--- /dev/null
+++ b/test/fixedbugs/bug381.go
@@ -0,0 +1,20 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2276.
+
+// Check that the error messages says 
+//	bug378.go:19: unsafe.Alignof(0) not used
+// and not
+//	bug378.go:19: 4 not used
+
+package main
+
+import "unsafe"
+
+func main() {
+	unsafe.Alignof(0) // ERROR "unsafe\.Alignof|value computed is not used"
+}
diff --git a/test/fixedbugs/bug382.dir/pkg.go b/test/fixedbugs/bug382.dir/pkg.go
new file mode 100644
index 0000000..f8d75d4
--- /dev/null
+++ b/test/fixedbugs/bug382.dir/pkg.go
@@ -0,0 +1,7 @@
+// Copyright 2011 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 pkg
+type T struct {}
+var E T
diff --git a/test/fixedbugs/bug382.go b/test/fixedbugs/bug382.go
new file mode 100644
index 0000000..3f5d05c
--- /dev/null
+++ b/test/fixedbugs/bug382.go
@@ -0,0 +1,14 @@
+// $G $D/$F.dir/pkg.go && $G $D/$F.go || echo "Bug 382"
+
+// Copyright 2011 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 2529
+
+package main
+import "./pkg"
+
+var x = pkg.E
+
+var fo = struct {F pkg.T}{F: x}
diff --git a/test/fixedbugs/bug383.go b/test/fixedbugs/bug383.go
new file mode 100644
index 0000000..9dccff5
--- /dev/null
+++ b/test/fixedbugs/bug383.go
@@ -0,0 +1,13 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2520
+
+package main
+func main() {
+	if 2e9 { }      // ERROR "2e.09"
+	if 3.14+1i { }  // ERROR "3.14 . 1i"
+}
\ No newline at end of file
diff --git a/test/fixedbugs/bug384.go b/test/fixedbugs/bug384.go
new file mode 100644
index 0000000..b3d6466
--- /dev/null
+++ b/test/fixedbugs/bug384.go
@@ -0,0 +1,12 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2500
+
+package foo
+
+// Check that we only get root cause message, no further complaints about r undefined
+func (r *indexWriter) foo() {}  // ERROR "undefined.*indexWriter"
diff --git a/test/fixedbugs/bug385_32.go b/test/fixedbugs/bug385_32.go
new file mode 100644
index 0000000..a009f66
--- /dev/null
+++ b/test/fixedbugs/bug385_32.go
@@ -0,0 +1,14 @@
+// [ $O == 6 ] || errchk $G -e $D/$F.go
+
+// Copyright 2011 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 2444
+
+package main
+func main() {
+	var arr [1000200030]int   // ERROR "type .* too large"
+	arr_bkup := arr
+	_ = arr_bkup
+}
\ No newline at end of file
diff --git a/test/fixedbugs/bug385_64.go b/test/fixedbugs/bug385_64.go
new file mode 100644
index 0000000..701be0d
--- /dev/null
+++ b/test/fixedbugs/bug385_64.go
@@ -0,0 +1,15 @@
+// [ $O != 6 ]  || errchk $G -e $D/$F.go
+
+// Copyright 2011 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 2444
+
+package main
+func main() {  // ERROR "stack frame too large"
+	var arr [1000200030]int
+	arr_bkup := arr
+	_ = arr_bkup
+}
+
diff --git a/test/fixedbugs/bug386.go b/test/fixedbugs/bug386.go
new file mode 100644
index 0000000..85b8d30
--- /dev/null
+++ b/test/fixedbugs/bug386.go
@@ -0,0 +1,12 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2451, 2452 
+package foo
+
+func f() error { return 0 } // ERROR "cannot use 0 .type int."
+
+func g() error { return -1 }  // ERROR "cannot use -1 .type int."
\ No newline at end of file
diff --git a/test/fixedbugs/bug387.go b/test/fixedbugs/bug387.go
new file mode 100644
index 0000000..c9db4ae
--- /dev/null
+++ b/test/fixedbugs/bug387.go
@@ -0,0 +1,30 @@
+// $G $D/$F.go || echo "Bug387"
+
+// Copyright 2011 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 2549
+
+/*  Used to die with
+missing typecheck: [7f5bf07b4438]
+
+.   AS l(45)
+.   .   NAME-main.autotmp_0017 u(1) a(1) l(45) x(0+0) class(PAUTO)
+esc(N) tc(1) used(1) ARRAY-[2]string
+internal compiler error: missing typecheck 
+*/
+package main
+
+import (
+        "fmt"
+        "path/filepath"
+)
+
+func main() {
+        switch _, err := filepath.Glob(filepath.Join(".", "vnc")); {
+        case err != nil:
+                fmt.Println(err)
+        }
+}
+
diff --git a/test/fixedbugs/bug388.go b/test/fixedbugs/bug388.go
new file mode 100644
index 0000000..d480e85
--- /dev/null
+++ b/test/fixedbugs/bug388.go
@@ -0,0 +1,39 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2231
+
+package main
+import "runtime"
+
+func foo(runtime.UintType, i int) {  // ERROR "cannot declare name runtime.UintType"
+	println(i, runtime.UintType) 
+}
+
+func bar(i int) {
+	runtime.UintType := i       // ERROR "cannot declare name runtime.UintType"
+	println(runtime.UintType)
+}
+
+func baz() {
+	main.i := 1	// ERROR "non-name main.i"
+	println(main.i)
+}
+
+func qux() {
+	var main.i	// ERROR "unexpected [.]"
+	println(main.i)
+}
+
+func corge() {
+	var foo.i int  // ERROR "unexpected [.]"
+	println(foo.i)
+}
+
+func main() {
+	foo(42,43)
+	bar(1969)
+}
diff --git a/test/fixedbugs/bug389.go b/test/fixedbugs/bug389.go
new file mode 100644
index 0000000..40d6c41
--- /dev/null
+++ b/test/fixedbugs/bug389.go
@@ -0,0 +1,12 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2563
+package foo
+
+func fn(a float32) {}
+
+var f func(arg int) = fn  // ERROR "cannot use fn .type func.float32.. as type func.int. in assignment"
\ No newline at end of file
diff --git a/test/fixedbugs/bug390.go b/test/fixedbugs/bug390.go
new file mode 100644
index 0000000..9ee5bc9
--- /dev/null
+++ b/test/fixedbugs/bug390.go
@@ -0,0 +1,16 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 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 2627 -- unsafe.Pointer type isn't handled nicely in some errors
+
+package main
+
+import "unsafe"
+
+func main() {
+	var x *int
+	_ = unsafe.Pointer(x) - unsafe.Pointer(x) // ERROR "operator - not defined on unsafe.Pointer"
+}
diff --git a/test/fixedbugs/bug391.go b/test/fixedbugs/bug391.go
new file mode 100644
index 0000000..8150718
--- /dev/null
+++ b/test/fixedbugs/bug391.go
@@ -0,0 +1,14 @@
+// $G $D/$F.go || echo "Issue2576"
+
+// Copyright 2011 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 2576
+package bug
+
+type T struct { a int }
+
+func f(t T) {
+        switch _, _ = t.a, t.a; {}
+}
\ No newline at end of file
diff --git a/test/fixedbugs/bug392.dir/one.go b/test/fixedbugs/bug392.dir/one.go
new file mode 100644
index 0000000..a701725
--- /dev/null
+++ b/test/fixedbugs/bug392.dir/one.go
@@ -0,0 +1,22 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Functions that the inliner exported incorrectly.
+
+package one
+
+type T int
+
+// Issue 2678
+func F1(T *T) bool { return T == nil }
+
+// Issue 2682.
+func F2(c chan int) bool { return c == (<-chan int)(nil) }
+
+// Use of single named return value.
+func F3() (ret []int) { return append(ret, 1) }
+
+// Call of inlined method with blank receiver.
+func (_ *T) M() int { return 1 }
+func (t *T) MM() int { return t.M() }
diff --git a/test/fixedbugs/bug392.dir/two.go b/test/fixedbugs/bug392.dir/two.go
new file mode 100644
index 0000000..b0ce26d
--- /dev/null
+++ b/test/fixedbugs/bug392.dir/two.go
@@ -0,0 +1,20 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Use the functions in one.go so that the inlined
+// forms get type-checked.
+
+package two
+
+import "./one"
+
+func use() {
+	one.F1(nil)
+	one.F2(nil)
+	one.F3()
+
+	var t *one.T
+	t.M()
+	t.MM()
+}
diff --git a/test/fixedbugs/bug392.go b/test/fixedbugs/bug392.go
new file mode 100644
index 0000000..50af600
--- /dev/null
+++ b/test/fixedbugs/bug392.go
@@ -0,0 +1,7 @@
+// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go
+
+// Copyright 2011 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 ignored
diff --git a/test/fixedbugs/bug393.go b/test/fixedbugs/bug393.go
new file mode 100644
index 0000000..e21b9c4
--- /dev/null
+++ b/test/fixedbugs/bug393.go
@@ -0,0 +1,30 @@
+// $G $D/$F.go || echo BUG: bug393
+
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 2672
+// was trying binary search with an interface type
+
+package main
+
+func f(x interface{}) int {
+	switch x {
+	case 1:
+		return 1
+	case 2:
+		return 2
+	case 3:
+		return 3
+	case 4:
+		return 4
+	case "5":
+		return 5
+	case "6":
+		return 6
+	default:
+		return 7
+	}
+	panic("switch")
+}
diff --git a/test/fixedbugs/bug394.go b/test/fixedbugs/bug394.go
new file mode 100644
index 0000000..4d0f090
--- /dev/null
+++ b/test/fixedbugs/bug394.go
@@ -0,0 +1,10 @@
+// errchk $G $D/$F.go
+
+// Copyright 2011 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 2598
+package foo
+
+return nil // ERROR "non-declaration statement outside function body"
diff --git a/test/fixedbugs/bug396.dir/one.go b/test/fixedbugs/bug396.dir/one.go
new file mode 100644
index 0000000..7902a07
--- /dev/null
+++ b/test/fixedbugs/bug396.dir/one.go
@@ -0,0 +1,9 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package one
+
+type T struct { int }
+
+func New(i int) T { return T{i} }
diff --git a/test/fixedbugs/bug396.dir/two.go b/test/fixedbugs/bug396.dir/two.go
new file mode 100644
index 0000000..9b32508
--- /dev/null
+++ b/test/fixedbugs/bug396.dir/two.go
@@ -0,0 +1,14 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Use the functions in one.go so that the inlined
+// forms get type-checked.
+
+package two
+
+import "./one"
+
+func use() {
+	_ = one.New(1)
+}
\ No newline at end of file
diff --git a/test/fixedbugs/bug396.go b/test/fixedbugs/bug396.go
new file mode 100644
index 0000000..50af600
--- /dev/null
+++ b/test/fixedbugs/bug396.go
@@ -0,0 +1,7 @@
+// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go
+
+// Copyright 2011 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 ignored
diff --git a/test/fixedbugs/bug397.go b/test/fixedbugs/bug397.go
new file mode 100644
index 0000000..cc8bfc0
--- /dev/null
+++ b/test/fixedbugs/bug397.go
@@ -0,0 +1,13 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 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
+
+// Issue 2623
+var m = map[string]int {
+	"abc":1,
+	1:2, // ERROR "cannot use 1.*as type string in map key"
+}
diff --git a/test/fixedbugs/bug398.go b/test/fixedbugs/bug398.go
new file mode 100644
index 0000000..1eee229
--- /dev/null
+++ b/test/fixedbugs/bug398.go
@@ -0,0 +1,24 @@
+// $G $D/$F.go
+
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Used to crash compiler in interface type equality check.
+
+package p
+
+type I1 interface {
+      F() interface{I1}
+}
+
+type I2 interface {
+      F() interface{I2}
+}       
+
+var v1 I1
+var v2 I2
+
+func f() bool {
+       return v1 == v2
+}
diff --git a/test/fixedbugs/bug399.go b/test/fixedbugs/bug399.go
new file mode 100644
index 0000000..25f6351
--- /dev/null
+++ b/test/fixedbugs/bug399.go
@@ -0,0 +1,15 @@
+// $G $D/$F.go || echo "Bug399"
+
+// Copyright 2011 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 2674
+
+package main
+const dow = "\000\003"
+
+func main() {
+	println(int(dow[1]))
+}
+
diff --git a/test/fixedbugs/bug401.go b/test/fixedbugs/bug401.go
new file mode 100644
index 0000000..553e217
--- /dev/null
+++ b/test/fixedbugs/bug401.go
@@ -0,0 +1,46 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo "Bug401"
+
+// Copyright 2011 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 2582
+package main
+
+type T struct{}
+
+func (T) cplx() complex128 {
+	for false {
+	} // avoid inlining
+	return complex(1, 0)
+}
+
+func (T) cplx2() complex128 {
+	return complex(0, 1)
+}
+
+type I interface {
+	cplx() complex128
+}
+
+func main() {
+
+	var t T
+
+	if v := real(t.cplx()); v != 1 {
+		panic("not-inlined complex call failed")
+	}
+	_ = imag(t.cplx())
+
+	_ = real(t.cplx2())
+	if v := imag(t.cplx2()); v != 1 {
+		panic("potentially inlined complex call failed")
+	}
+
+	var i I
+	i = t
+	if v := real(i.cplx()); v != 1 {
+		panic("potentially inlined complex call failed")
+	}
+	_ = imag(i.cplx())
+}
diff --git a/test/func2.go b/test/func2.go
index 5a6d7d0..87e7819 100644
--- a/test/func2.go
+++ b/test/func2.go
@@ -5,7 +5,6 @@
 // license that can be found in the LICENSE file.
 
 package main
-import os "os"
 
 type t1 int
 type t2 int
@@ -23,7 +22,7 @@ func f8(os int) int
 func f9(os int) int {
 	return os
 }
-func f10(err os.Error) os.Error {
+func f10(err error) error {
 	return err
 }
 func f11(t1 string) string {
diff --git a/test/func4.go b/test/func4.go
index 69ce56a..2a1a932 100644
--- a/test/func4.go
+++ b/test/func4.go
@@ -11,4 +11,5 @@ var notmain func()
 func main() {
 	var x = &main		// ERROR "address of|invalid"
 	main = notmain	// ERROR "assign to|invalid"
+	_ = x
 }
diff --git a/test/func8.go b/test/func8.go
new file mode 100644
index 0000000..bb61064
--- /dev/null
+++ b/test/func8.go
@@ -0,0 +1,47 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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
+
+var calledf int
+
+func f() int {
+	calledf++
+	return 0
+}
+
+func g() int {
+	return calledf
+}
+
+var xy string
+
+func x() bool {
+	for false {
+	} // no inlining
+	xy += "x"
+	return false
+}
+
+func y() string {
+	for false {
+	} // no inlining
+	xy += "y"
+	return "abc"
+}
+
+func main() {
+	if f() == g() {
+		println("wrong f,g order")
+	}
+
+	if x() == (y() == "abc") {
+		panic("wrong compare")
+	}
+	if xy != "xy" {
+		println("wrong x,y order")
+	}
+}
diff --git a/test/garbage/Makefile b/test/garbage/Makefile
deleted file mode 100644
index e833843..0000000
--- a/test/garbage/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2010 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../src/Make.inc
-
-ALL=\
-	parser\
-	peano\
-	tree\
-
-all: $(addsuffix .out, $(ALL))
-
-%.$O: %.go stats.go
-	$(GC) $*.go stats.go
-
-%.out: %.$O
-	$(LD) -o $@ $*.$O
-
-%.bench: %.out
-	./$*.out
-
-bench: $(addsuffix .bench, $(ALL))
-
-clean:
-	rm -f *.[$(OS)] $(addsuffix .out, $(ALL))
-
diff --git a/test/garbage/parser.go b/test/garbage/parser.go
deleted file mode 100644
index 19a96bc..0000000
--- a/test/garbage/parser.go
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2010 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.
-
-// Garbage collection benchmark: parse Go packages repeatedly.
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"go/ast"
-	"go/parser"
-	"go/token"
-	"os"
-	"path"
-	"runtime"
-	"strings"
-	"time"
-	"http"
-	_ "http/pprof"
-	"log"
-)
-
-var serve = flag.String("serve", "", "serve http on this address at end")
-
-func isGoFile(dir *os.FileInfo) bool {
-	return dir.IsRegular() &&
-		!strings.HasPrefix(dir.Name, ".") && // ignore .files
-		path.Ext(dir.Name) == ".go"
-}
-
-func isPkgFile(dir *os.FileInfo) bool {
-	return isGoFile(dir) &&
-		!strings.HasSuffix(dir.Name, "_test.go") // ignore test files
-}
-
-func pkgName(filename string) string {
-	file, err := parser.ParseFile(token.NewFileSet(), filename, nil, parser.PackageClauseOnly)
-	if err != nil || file == nil {
-		return ""
-	}
-	return file.Name.Name
-}
-
-func parseDir(dirpath string) map[string]*ast.Package {
-	// the package name is the directory name within its parent
-	// (use dirname instead of path because dirname is clean; i.e. has no trailing '/')
-	_, pkgname := path.Split(dirpath)
-
-	// filter function to select the desired .go files
-	filter := func(d *os.FileInfo) bool {
-		if isPkgFile(d) {
-			// Some directories contain main packages: Only accept
-			// files that belong to the expected package so that
-			// parser.ParsePackage doesn't return "multiple packages
-			// found" errors.
-			// Additionally, accept the special package name
-			// fakePkgName if we are looking at cmd documentation.
-			name := pkgName(dirpath + "/" + d.Name)
-			return name == pkgname
-		}
-		return false
-	}
-
-	// get package AST
-	pkgs, err := parser.ParseDir(token.NewFileSet(), dirpath, filter, parser.ParseComments)
-	if err != nil {
-		println("parse", dirpath, err.String())
-		panic("fail")
-	}
-	return pkgs
-}
-
-func main() {
-	runtime.GOMAXPROCS(4)
-	go func() {}()
-	go func() {}()
-	go func() {}()
-	st := &runtime.MemStats
-	packages = append(packages, packages...)
-	packages = append(packages, packages...)
-	n := flag.Int("n", 4, "iterations")
-	p := flag.Int("p", len(packages), "# of packages to keep in memory")
-	flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
-	flag.Parse()
-
-	var lastParsed []map[string]*ast.Package
-	var t0 int64
-	pkgroot := runtime.GOROOT() + "/src/pkg/"
-	for pass := 0; pass < 2; pass++ {
-		// Once the heap is grown to full size, reset counters.
-		// This hides the start-up pauses, which are much smaller
-		// than the normal pauses and would otherwise make
-		// the average look much better than it actually is.
-		st.NumGC = 0
-		st.PauseTotalNs = 0
-		t0 = time.Nanoseconds()
-
-		for i := 0; i < *n; i++ {
-			parsed := make([]map[string]*ast.Package, *p)
-			for j := range parsed {
-				parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
-			}
-			if i+1 == *n && *serve != "" {
-				lastParsed = parsed
-			}
-		}
-		runtime.GC()
-		runtime.GC()
-	}
-	t1 := time.Nanoseconds()
-
-	fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
-		st.Alloc, st.TotalAlloc,
-		st.Sys,
-		st.Mallocs, float64(st.PauseTotalNs)/1e9,
-		st.NumGC, float64(st.PauseTotalNs)/1e9/float64(st.NumGC))
-
-	/*
-		fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free")
-		for _, s := range st.BySize {
-			fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
-		}
-	*/
-	// Standard gotest benchmark output, collected by build dashboard.
-	gcstats("BenchmarkParser", *n, t1-t0)
-
-	if *serve != "" {
-		log.Fatal(http.ListenAndServe(*serve, nil))
-		println(lastParsed)
-	}
-}
-
-
-var packages = []string{
-	"archive/tar",
-	"asn1",
-	"big",
-	"bufio",
-	"bytes",
-	"cmath",
-	"compress/flate",
-	"compress/gzip",
-	"compress/zlib",
-	"container/heap",
-	"container/list",
-	"container/ring",
-	"container/vector",
-	"crypto/aes",
-	"crypto/block",
-	"crypto/blowfish",
-	"crypto/hmac",
-	"crypto/md4",
-	"crypto/md5",
-	"crypto/rand",
-	"crypto/rc4",
-	"crypto/rsa",
-	"crypto/sha1",
-	"crypto/sha256",
-	"crypto/sha512",
-	"crypto/subtle",
-	"crypto/tls",
-	"crypto/x509",
-	"crypto/xtea",
-	"debug/dwarf",
-	"debug/macho",
-	"debug/elf",
-	"debug/gosym",
-	"debug/proc",
-	"ebnf",
-	"encoding/ascii85",
-	"encoding/base64",
-	"encoding/binary",
-	"encoding/git85",
-	"encoding/hex",
-	"encoding/pem",
-	"exec",
-	"exp/datafmt",
-	"exp/draw",
-	"exp/eval",
-	"exp/iterable",
-	"expvar",
-	"flag",
-	"fmt",
-	"go/ast",
-	"go/doc",
-	"go/parser",
-	"go/printer",
-	"go/scanner",
-	"go/token",
-	"gob",
-	"hash",
-	"hash/adler32",
-	"hash/crc32",
-	"hash/crc64",
-	"http",
-	"image",
-	"image/jpeg",
-	"image/png",
-	"io",
-	"io/ioutil",
-	"json",
-	"log",
-	"math",
-	"mime",
-	"net",
-	"os",
-	"os/signal",
-	"patch",
-	"path",
-	"rand",
-	"reflect",
-	"regexp",
-	"rpc",
-	"runtime",
-	"scanner",
-	"sort",
-	"smtp",
-	"strconv",
-	"strings",
-	"sync",
-	"syscall",
-	"syslog",
-	"tabwriter",
-	"template",
-	"testing",
-	"testing/iotest",
-	"testing/quick",
-	"testing/script",
-	"time",
-	"unicode",
-	"utf8",
-	"utf16",
-	"websocket",
-	"xml",
-}
diff --git a/test/garbage/peano.go b/test/garbage/peano.go
deleted file mode 100644
index b4d3185..0000000
--- a/test/garbage/peano.go
+++ /dev/null
@@ -1,135 +0,0 @@
-// $G $F.go && $L $F.$A && ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-	"fmt"
-	"runtime"
-	"time"
-)
-
-
-type Number struct {
-	next *Number
-}
-
-
-// -------------------------------------
-// Peano primitives
-
-func zero() *Number { return nil }
-
-
-func is_zero(x *Number) bool { return x == nil }
-
-
-func add1(x *Number) *Number {
-	e := new(Number)
-	e.next = x
-	return e
-}
-
-
-func sub1(x *Number) *Number { return x.next }
-
-
-func add(x, y *Number) *Number {
-	if is_zero(y) {
-		return x
-	}
-
-	return add(add1(x), sub1(y))
-}
-
-
-func mul(x, y *Number) *Number {
-	if is_zero(x) || is_zero(y) {
-		return zero()
-	}
-
-	return add(mul(x, sub1(y)), x)
-}
-
-
-func fact(n *Number) *Number {
-	if is_zero(n) {
-		return add1(zero())
-	}
-
-	return mul(fact(sub1(n)), n)
-}
-
-
-// -------------------------------------
-// Helpers to generate/count Peano integers
-
-func gen(n int) *Number {
-	if n > 0 {
-		return add1(gen(n - 1))
-	}
-
-	return zero()
-}
-
-
-func count(x *Number) int {
-	if is_zero(x) {
-		return 0
-	}
-
-	return count(sub1(x)) + 1
-}
-
-
-func check(x *Number, expected int) {
-	var c = count(x)
-	if c != expected {
-		panic(fmt.Sprintf("error: found %d; expected %d", c, expected))
-	}
-}
-
-
-// -------------------------------------
-// Test basic functionality
-
-func verify() {
-	check(zero(), 0)
-	check(add1(zero()), 1)
-	check(gen(10), 10)
-
-	check(add(gen(3), zero()), 3)
-	check(add(zero(), gen(4)), 4)
-	check(add(gen(3), gen(4)), 7)
-
-	check(mul(zero(), zero()), 0)
-	check(mul(gen(3), zero()), 0)
-	check(mul(zero(), gen(4)), 0)
-	check(mul(gen(3), add1(zero())), 3)
-	check(mul(add1(zero()), gen(4)), 4)
-	check(mul(gen(3), gen(4)), 12)
-
-	check(fact(zero()), 1)
-	check(fact(add1(zero())), 1)
-	check(fact(gen(5)), 120)
-}
-
-
-// -------------------------------------
-// Factorial
-
-
-func main() {
-	t0 := time.Nanoseconds()
-	verify()
-	for i := 0; i <= 9; i++ {
-		print(i, "! = ", count(fact(gen(i))), "\n")
-	}
-	runtime.GC()
-	t1 := time.Nanoseconds()
-
-	gcstats("BenchmarkPeano", 1, t1-t0)
-}
diff --git a/test/garbage/stats.go b/test/garbage/stats.go
deleted file mode 100644
index 474e6ad..0000000
--- a/test/garbage/stats.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2010 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"
-	"runtime"
-	"sort"
-)
-
-func gcstats(name string, n int, t int64) {
-	st := &runtime.MemStats
-	fmt.Printf("garbage.%sMem Alloc=%d/%d Heap=%d NextGC=%d Mallocs=%d\n", name, st.Alloc, st.TotalAlloc, st.Sys, st.NextGC, st.Mallocs)
-	fmt.Printf("garbage.%s %d %d ns/op\n", name, n, t/int64(n))
-	fmt.Printf("garbage.%sLastPause 1 %d ns/op\n", name, st.PauseNs[(st.NumGC-1)%uint32(len(st.PauseNs))])
-	fmt.Printf("garbage.%sPause %d %d ns/op\n", name, st.NumGC, int64(st.PauseTotalNs)/int64(st.NumGC))
-	nn := int(st.NumGC)
-	if nn >= len(st.PauseNs) {
-		nn = len(st.PauseNs)
-	}
-	t1, t2, t3, t4, t5 := tukey5(st.PauseNs[0:nn])
-	fmt.Printf("garbage.%sPause5: %d %d %d %d %d\n", name, t1, t2, t3, t4, t5)
-	
-//	fmt.Printf("garbage.%sScan: %v\n", name, st.ScanDist)
-}
-
-type T []uint64
-func (t T) Len() int { return len(t) }
-func (t T) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
-func (t T) Less(i, j int) bool { return t[i] < t[j] }
-
-func tukey5(raw []uint64) (lo, q1, q2, q3, hi uint64) {
-	x := make(T, len(raw))
-	copy(x, raw)
-	sort.Sort(T(x))
-	lo = x[0]
-	q1 = x[len(x)/4]
-	q2 = x[len(x)/2]
-	q3 = x[len(x)*3/4]
-	hi = x[len(x)-1]
-	return
-}
diff --git a/test/garbage/tree.go b/test/garbage/tree.go
deleted file mode 100644
index c5eae97..0000000
--- a/test/garbage/tree.go
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on C program by Kevin Carson
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"time"
-)
-
-var n = flag.Int("n", 16, "depth")
-
-type Node struct {
-	item        int
-	left, right *Node
-}
-
-func bottomUpTree(item, depth int) *Node {
-	if depth <= 0 {
-		return &Node{item: item}
-	}
-	return &Node{item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1)}
-}
-
-func (n *Node) itemCheck() int {
-	if n.left == nil {
-		return n.item
-	}
-	return n.item + n.left.itemCheck() - n.right.itemCheck()
-}
-
-const minDepth = 4
-
-func main() {
-	flag.Parse()
-
-	t0 := time.Nanoseconds()
-
-	maxDepth := *n
-	if minDepth+2 > *n {
-		maxDepth = minDepth + 2
-	}
-	stretchDepth := maxDepth + 1
-
-	check := bottomUpTree(0, stretchDepth).itemCheck()
-	fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check)
-
-	longLivedTree := bottomUpTree(0, maxDepth)
-
-	for depth := minDepth; depth <= maxDepth; depth += 2 {
-		iterations := 1 << uint(maxDepth-depth+minDepth)
-		check = 0
-
-		for i := 1; i <= iterations; i++ {
-			check += bottomUpTree(i, depth).itemCheck()
-			check += bottomUpTree(-i, depth).itemCheck()
-		}
-		fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check)
-	}
-	fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck())
-
-	t1 := time.Nanoseconds()
-
-	// Standard gotest benchmark output, collected by build dashboard.
-	gcstats("BenchmarkTree", *n, t1-t0)
-}
diff --git a/test/golden.out b/test/golden.out
index fc4b81d..e0b4cf6 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -1,161 +1,19 @@
 
 == ./
 
-=========== ./cmp2.go
-panic: runtime error: comparing uncomparable type []int
-
-=========== ./cmp3.go
-panic: runtime error: comparing uncomparable type []int
-
-=========== ./cmp4.go
-panic: runtime error: hash of unhashable type []int
-
-=========== ./cmp5.go
-panic: runtime error: hash of unhashable type []int
-
-=========== ./deferprint.go
-printing: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
-42 true false true +1.500000e+000 world 0x0 [0/0]0x0 0x0 0x0 255
-
-=========== ./goprint.go
-42 true false true +1.500000e+000 world 0x0 [0/0]0x0 0x0 0x0 255
-
-=========== ./helloworld.go
-hello, world
-
-=========== ./peano.go
-0! = 1
-1! = 1
-2! = 2
-3! = 6
-4! = 24
-5! = 120
-6! = 720
-7! = 5040
-8! = 40320
-9! = 362880
-
-=========== ./printbig.go
--9223372036854775808
-9223372036854775807
-
-=========== ./sigchld.go
-survived SIGCHLD
-
-=========== ./turing.go
-Hello World!
-
 == ken/
 
-=========== ken/cplx0.go
-(+5.000000e+000+6.000000e+000i)
-(+5.000000e+000+6.000000e+000i)
-(+5.000000e+000+6.000000e+000i)
-(+5.000000e+000+6.000000e+000i)
-
-=========== ken/cplx3.go
-(+1.292308e+000-1.384615e-001i)
-(+1.292308e+000-1.384615e-001i)
-
-=========== ken/cplx4.go
-c = (-5.000000-6.000000i)
-c = (5.000000+6.000000i)
-c = (5.000000+6.000000i)
-c = (5.000000+6.000000i)
-c = (5+6i)
-c = (13+7i)
-
-=========== ken/cplx5.go
-(+5.000000e+000-5.000000e+000i)
-(+5.000000e+000-5.000000e+000i)
-(+5.000000e+000-5.000000e+000i)
-(+5.000000e+000-5.000000e+000i)
-(+5.000000e+000-5.000000e+000i)
-(+5.000000e+000-5.000000e+000i)
-(+5.000000e+000-5.000000e+000i)
-
-=========== ken/intervar.go
- print 1 bio 2 file 3 -- abc
-
-=========== ken/label.go
-100
-
-=========== ken/rob1.go
-9876543210
-
-=========== ken/rob2.go
-(defn foo (add 12 34))
-
-=========== ken/simpprint.go
-hello world
-
-=========== ken/simpswitch.go
-0out01out12out2aout34out4fiveout56out6aout78out89out9
-
-=========== ken/string.go
-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz
-
 == chan/
 
-=========== chan/doubleselect.go
-PASS
-
-=========== chan/nonblock.go
-PASS
-
 == interface/
 
-=========== interface/fail.go
-panic: interface conversion: *main.S is not main.I: missing method Foo
-
-=========== interface/returntype.go
-panic: interface conversion: *main.S is not main.I2: missing method Name
-
-== nilptr/
-
 == syntax/
 
 == dwarf/
 
 == fixedbugs/
 
-=========== fixedbugs/bug027.go
-hi
-0 44444
-1 3333
-2 222
-3 11
-4 0
-0 44444
-1 3333
-2 222
-3 11
-4 0
-
-=========== fixedbugs/bug067.go
-ok
-
-=========== fixedbugs/bug070.go
-outer loop top k 0
-inner loop top i 0
-do break
-broke
-
-=========== fixedbugs/bug093.go
-M
-
-=========== fixedbugs/bug113.go
-panic: interface conversion: interface is int, not int32
-
-=========== fixedbugs/bug148.go
-2 3
-panic: interface conversion: interface is main.T, not main.T
-
-=========== fixedbugs/bug328.go
-0x0
-
 == bugs/
 
-=========== bugs/bug367.go
-panic: interface conversion: main.T is not p.I: missing method get
-BUG: should not fail
+=========== bugs/bug395.go
+bug395 is broken
diff --git a/test/goprint.go b/test/goprint.go
index c0e34c7..53ed055 100644
--- a/test/goprint.go
+++ b/test/goprint.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
+// $G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out
 
 // Copyright 2011 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/goprint.out b/test/goprint.out
new file mode 100644
index 0000000..da3919e
--- /dev/null
+++ b/test/goprint.out
@@ -0,0 +1 @@
+42 true false true +1.500000e+000 world 0x0 [0/0]0x0 0x0 0x0 255
diff --git a/test/helloworld.go b/test/helloworld.go
index e55a74b..16c95f0 100644
--- a/test/helloworld.go
+++ b/test/helloworld.go
@@ -1,4 +1,4 @@
-// $G $F.go && $L $F.$A && ./$A.out
+// $G $F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/helloworld.out b/test/helloworld.out
new file mode 100644
index 0000000..4b5fa63
--- /dev/null
+++ b/test/helloworld.out
@@ -0,0 +1 @@
+hello, world
diff --git a/test/import.go b/test/import.go
index 9633034..bd83dc3 100644
--- a/test/import.go
+++ b/test/import.go
@@ -13,13 +13,12 @@ import _os_ "os"
 import "os"
 import . "os"
 
-func f(e os.Error)
+func f(e *os.File)
 
 func main() {
-	var _e_ _os_.Error
-	var dot Error
+	var _e_ *_os_.File
+	var dot *File
 
 	f(_e_)
 	f(dot)
 }
-
diff --git a/test/indirect1.go b/test/indirect1.go
index 0fd5c19..ecb4f13 100644
--- a/test/indirect1.go
+++ b/test/indirect1.go
@@ -65,4 +65,5 @@ func f() {
 		cap(b2)+	// ERROR "illegal|invalid|must be"
 		cap(b3)+
 		cap(b4)	// ERROR "illegal|invalid|must be"
+	_ = x
 }
diff --git a/test/init1.go b/test/init1.go
new file mode 100644
index 0000000..9ce3c12
--- /dev/null
+++ b/test/init1.go
@@ -0,0 +1,44 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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 goroutines and garbage collection run during init.
+
+package main
+
+import "runtime"
+
+var x []byte
+
+func init() {
+	c := make(chan int)
+	go send(c)
+	<-c
+	
+	const chunk = 1<<20
+	runtime.UpdateMemStats()
+	sys := runtime.MemStats.Sys	
+	b := make([]byte, chunk)
+	for i := range b {
+		b[i] = byte(i%10 + '0')
+	}
+	s := string(b)
+	for i := 0; i < 1000; i++ {
+		x = []byte(s)
+	}
+	runtime.UpdateMemStats()
+	sys1 := runtime.MemStats.Sys
+	if sys1-sys > chunk*50 {
+		println("allocated 1000 chunks of", chunk, "and used ", sys1-sys, "memory")
+	}
+}
+
+func send(c chan int) {
+	c <- 1
+}
+
+func main() {
+}
+
diff --git a/test/initsyscall.go b/test/initsyscall.go
index b5e5812..d0c26d2 100644
--- a/test/initsyscall.go
+++ b/test/initsyscall.go
@@ -19,9 +19,8 @@ func f() {
 
 func init() {
 	go f()
-	time.Nanoseconds()
+	time.Now()
 }
 
 func main() {
 }
-
diff --git a/test/interface/fail.go b/test/interface/fail.go
index 3e741d3..0c20bcf 100644
--- a/test/interface/fail.go
+++ b/test/interface/fail.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ! ./$A.out
+// $G $D/$F.go && $L $F.$A && ./$A.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -13,6 +13,10 @@ type I interface {
 }
 
 func main() {
+	shouldPanic(p1)
+}
+
+func p1() {
 	var s *S
 	var i I
 	var e interface {}
@@ -21,6 +25,14 @@ func main() {
 	_ = i
 }
 
-// hide S down here to avoid static warning
 type S struct {
 }
+
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("function should panic")
+		}
+	}()
+	f()
+}
diff --git a/test/interface/fake.go b/test/interface/fake.go
index bdc5b90..ddb8325 100644
--- a/test/interface/fake.go
+++ b/test/interface/fake.go
@@ -12,20 +12,20 @@ package main
 import "reflect"
 
 type T struct {
-	f float32
-	g float32
+	F float32
+	G float32
 
-	s string
-	t string
+	S string
+	T string
 
-	u uint32
-	v uint32
+	U uint32
+	V uint32
 
-	w uint32
-	x uint32
+	W uint32
+	X uint32
 
-	y uint32
-	z uint32
+	Y uint32
+	Z uint32
 }
 
 func add(s, t string) string {
@@ -40,16 +40,16 @@ func assert(b bool) {
 
 func main() {
 	var x T
-	x.f = 1.0
-	x.g = x.f
-	x.s = add("abc", "def")
-	x.t = add("abc", "def")
-	x.u = 1
-	x.v = 2
-	x.w = 1 << 28
-	x.x = 2 << 28
-	x.y = 0x12345678
-	x.z = x.y
+	x.F = 1.0
+	x.G = x.F
+	x.S = add("abc", "def")
+	x.T = add("abc", "def")
+	x.U = 1
+	x.V = 2
+	x.W = 1 << 28
+	x.X = 2 << 28
+	x.Y = 0x12345678
+	x.Z = x.Y
 
 	// check mem and string
 	v := reflect.ValueOf(x)
diff --git a/test/interface/noeq.go b/test/interface/noeq.go
new file mode 100644
index 0000000..3c2ea59
--- /dev/null
+++ b/test/interface/noeq.go
@@ -0,0 +1,39 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: interface/noeq
+
+// Copyright 2011 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.
+
+// Interface values containing types that cannot be compared for equality.
+
+package main
+
+func main() {
+	cmp(1)
+
+	var (
+		m map[int]int
+		s struct{ x []int }
+		f func()
+	)
+	noCmp(m)
+	noCmp(s)
+	noCmp(f)
+}
+
+func cmp(x interface{}) bool {
+	return x == x
+}
+
+func noCmp(x interface{}) {
+	shouldPanic(func() { cmp(x) })
+}
+
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("function should panic")
+		}
+	}()
+	f()
+}
diff --git a/test/interface/recursive1.go b/test/interface/recursive1.go
new file mode 100644
index 0000000..2c93a28
--- /dev/null
+++ b/test/interface/recursive1.go
@@ -0,0 +1,15 @@
+// true  # used by recursive2
+
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type I1 interface {
+	F() I2
+}
+
+type I2 interface {
+	I1
+}
diff --git a/test/interface/recursive2.go b/test/interface/recursive2.go
new file mode 100644
index 0000000..a7f9ab5
--- /dev/null
+++ b/test/interface/recursive2.go
@@ -0,0 +1,22 @@
+// $G $D/recursive1.go && $G $D/$F.go
+
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that the mutually recursive types in recursive1.go made it
+// intact and with the same meaning, by assigning to or using them.
+
+package main
+
+import "./recursive1"
+
+func main() {
+	var i1 p.I1
+	var i2 p.I2
+	i1 = i2
+	i2 = i1
+	i1 = i2.F()
+	i2 = i1.F()
+	_, _ = i1, i2
+}
diff --git a/test/interface/returntype.go b/test/interface/returntype.go
index c526b3b..5cf0836 100644
--- a/test/interface/returntype.go
+++ b/test/interface/returntype.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && (! ./$A.out || echo BUG: should not succeed)
+// $G $D/$F.go && $L $F.$A && ./$A.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -18,8 +18,21 @@ type I1 interface { Name() int8 }
 type I2 interface { Name() int64 }
 
 func main() {
+	shouldPanic(p1)
+}
+
+func p1() {
 	var i1 I1
 	var s *S
 	i1 = s
 	print(i1.(I2).Name())
 }
+
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("function should panic")
+		}
+	}()
+	f()
+}
diff --git a/test/ken/cplx0.go b/test/ken/cplx0.go
index ba1fa19..f38ce5b 100644
--- a/test/ken/cplx0.go
+++ b/test/ken/cplx0.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
+// $G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out
 
 // Copyright 2010 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/ken/cplx0.out b/test/ken/cplx0.out
new file mode 100644
index 0000000..7627c28
--- /dev/null
+++ b/test/ken/cplx0.out
@@ -0,0 +1,4 @@
+(+5.000000e+000+6.000000e+000i)
+(+5.000000e+000+6.000000e+000i)
+(+5.000000e+000+6.000000e+000i)
+(+5.000000e+000+6.000000e+000i)
diff --git a/test/ken/cplx3.go b/test/ken/cplx3.go
index fa6ff1d..048c93e 100644
--- a/test/ken/cplx3.go
+++ b/test/ken/cplx3.go
@@ -19,10 +19,29 @@ const (
 func main() {
 	c0 := C1
 	c0 = (c0 + c0 + c0) / (c0 + c0 + 3i)
-	println(c0)
+	r, i := real(c0), imag(c0)
+	d := r - 1.292308
+	if d < 0 {
+		d = - d
+	}
+	if d > 1e-6 {
+		println(r, "!= 1.292308")
+		panic(0)
+	}
+	d = i + 0.1384615
+	if d < 0 {
+		d = - d
+	}
+	if d > 1e-6 {
+		println(i, "!= -0.1384615")
+		panic(0)
+	}
 
 	c := *(*complex128)(unsafe.Pointer(&c0))
-	println(c)
+	if c != c0 {
+		println(c, "!=", c)
+		panic(0)
+	}
 
 	var a interface{}
 	switch c := reflect.ValueOf(a); c.Kind() {
diff --git a/test/ken/cplx4.go b/test/ken/cplx4.go
index 8524e47..738afcd 100644
--- a/test/ken/cplx4.go
+++ b/test/ken/cplx4.go
@@ -15,30 +15,44 @@ const (
 	C1 = R + I // ADD(5,6)
 )
 
-func doprint(c complex128) { fmt.Printf("c = %f\n", c) }
+func want(s, w string) {
+	if s != w {
+		panic(s + " != " + w)
+	}
+}
+
+func doprint(c complex128, w string) {
+	s := fmt.Sprintf("%f", c)
+	want(s, w)
+}
 
 func main() {
 
 	// constants
-	fmt.Printf("c = %f\n", -C1)
-	doprint(C1)
+	s := fmt.Sprintf("%f", -C1)
+	want(s, "(-5.000000-6.000000i)")
+	doprint(C1, "(5.000000+6.000000i)")
 
 	// variables
 	c1 := C1
-	fmt.Printf("c = %f\n", c1)
-	doprint(c1)
+	s = fmt.Sprintf("%f", c1)
+	want(s, "(5.000000+6.000000i)")
+	doprint(c1, "(5.000000+6.000000i)")
 
 	// 128
 	c2 := complex128(C1)
-	fmt.Printf("c = %G\n", c2)
+	s = fmt.Sprintf("%G", c2)
+	want(s, "(5+6i)")
 
 	// real, imag, complex
 	c3 := complex(real(c2)+3, imag(c2)-5) + c2
-	fmt.Printf("c = %G\n", c3)
+	s = fmt.Sprintf("%G", c3)
+	want(s, "(13+7i)")
 
 	// compiler used to crash on nested divide
 	c4 := complex(real(c3/2), imag(c3/2))
 	if c4 != c3/2 {
 		fmt.Printf("BUG: c3 = %G != c4 = %G\n", c3, c4)
+		panic(0)
 	}
 }
diff --git a/test/ken/cplx5.go b/test/ken/cplx5.go
index d425a7c..e669667 100644
--- a/test/ken/cplx5.go
+++ b/test/ken/cplx5.go
@@ -19,36 +19,52 @@ func main() {
 	for i := 0; i < len(a); i++ {
 		a[i] = complex(float64(i), float64(-i))
 	}
-	println(a[5])
+	if a[5] != 5-5i {
+		panic(a[5])
+	}
 
 	// slice of complex128
 	s = make([]complex128, len(a))
 	for i := 0; i < len(s); i++ {
 		s[i] = a[i]
 	}
-	println(s[5])
+	if s[5] != 5-5i {
+		panic(s[5])
+	}
 
 	// chan
 	c = make(chan complex128)
 	go chantest(c)
-	println(<-c)
+	vc := <-c
+	if vc != 5-5i {
+		panic(vc)
+	}
 
 	// pointer of complex128
 	v := a[5]
 	pv := &v
-	println(*pv)
+	if *pv != 5-5i {
+		panic(*pv)
+	}
 
 	// field of complex128
 	f.c = a[5]
-	println(f.c)
+	if f.c != 5-5i {
+		panic(f.c)
+	}
 
 	// map of complex128
 	m = make(map[complex128]complex128)
 	for i := 0; i < len(s); i++ {
 		m[-a[i]] = a[i]
 	}
-	println(m[5i-5])
-	println(m[complex(-5, 5)])
+	if m[5i-5] != 5-5i {
+		panic(m[5i-5])
+	}
+	vm := m[complex(-5, 5)]
+	if vm != 5-5i {
+		panic(vm)
+	}
 }
 
 func chantest(c chan complex128) { c <- a[5] }
diff --git a/test/ken/divconst.go b/test/ken/divconst.go
index c3b9092..5a64d16 100644
--- a/test/ken/divconst.go
+++ b/test/ken/divconst.go
@@ -6,7 +6,7 @@
 
 package main
 
-import "rand"
+import "math/rand"
 
 const Count = 1e5
 
diff --git a/test/ken/intervar.go b/test/ken/intervar.go
index c2aaaa8..73d1b06 100644
--- a/test/ken/intervar.go
+++ b/test/ken/intervar.go
@@ -7,7 +7,7 @@
 package main
 
 type	Iputs	interface {
-	puts	(s string);
+	puts	(s string) string;
 }
 
 // ---------
@@ -17,9 +17,9 @@ type	Print	struct {
 	put	Iputs;
 }
 
-func (p *Print) dop() {
-	print(" print ", p.whoami);
-	p.put.puts("abc");
+func (p *Print) dop() string {
+	r := " print " + string(p.whoami + '0')
+	return r + p.put.puts("abc");
 }
 
 // ---------
@@ -29,9 +29,9 @@ type	Bio	struct {
 	put	Iputs;
 }
 
-func (b *Bio) puts(s string) {
-	print(" bio ", b.whoami);
-	b.put.puts(s);
+func (b *Bio) puts(s string) string {
+	r := " bio " + string(b.whoami + '0')
+	return r + b.put.puts(s);
 }
 
 // ---------
@@ -41,8 +41,8 @@ type	File	struct {
 	put	Iputs;
 }
 
-func (f *File) puts(s string) {
-	print(" file ", f.whoami, " -- ", s);
+func (f *File) puts(s string) string {
+	return " file " + string(f.whoami + '0') + " -- " + s
 }
 
 func
@@ -59,6 +59,9 @@ main() {
 
 	f.whoami = 3;
 
-	p.dop();
-	print("\n");
+	r := p.dop();
+	expected := " print 1 bio 2 file 3 -- abc"
+	if r != expected {
+		panic(r + " != " + expected)
+	}
 }
diff --git a/test/ken/label.go b/test/ken/label.go
index 770f33e..7a509f0 100644
--- a/test/ken/label.go
+++ b/test/ken/label.go
@@ -4,33 +4,29 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-
 package main
 
-func
-main() {
-	i := 0;
+func main() {
+	i := 0
 	if false {
-		goto gogoloop;
+		goto gogoloop
 	}
 	if false {
-		goto gogoloop;
+		goto gogoloop
 	}
 	if false {
-		goto gogoloop;
+		goto gogoloop
 	}
-	goto gogoloop;
+	goto gogoloop
 
-// backward declared
+	// backward declared
 loop:
-	i = i+1;
+	i = i + 1
 	if i < 100 {
-		goto loop;
+		goto loop
 	}
-	print(i);
-	print("\n");
-	return;
+	return
 
 gogoloop:
-	goto loop;
+	goto loop
 }
diff --git a/test/ken/modconst.go b/test/ken/modconst.go
index acb8831..c2603a0 100644
--- a/test/ken/modconst.go
+++ b/test/ken/modconst.go
@@ -6,7 +6,7 @@
 
 package main
 
-import "rand"
+import "math/rand"
 
 const Count = 1e5
 
diff --git a/test/ken/rob1.go b/test/ken/rob1.go
index 0335066..a5854b9 100644
--- a/test/ken/rob1.go
+++ b/test/ken/rob1.go
@@ -7,61 +7,64 @@
 package main
 
 type Item interface {
-	Print();
+	Print() string
 }
 
 type ListItem struct {
-	item    Item;
-	next    *ListItem;
+	item Item
+	next *ListItem
 }
 
 type List struct {
-	head    *ListItem;
+	head *ListItem
 }
 
 func (list *List) Init() {
-	list.head = nil;
+	list.head = nil
 }
 
 func (list *List) Insert(i Item) {
-	item := new(ListItem);
-	item.item = i;
-	item.next = list.head;
-	list.head = item;
+	item := new(ListItem)
+	item.item = i
+	item.next = list.head
+	list.head = item
 }
 
-func (list *List) Print() {
-	i := list.head;
+func (list *List) Print() string {
+	r := ""
+	i := list.head
 	for i != nil {
-		i.item.Print();
-		i = i.next;
+		r += i.item.Print()
+		i = i.next
 	}
+	return r
 }
 
 // Something to put in a list
 type Integer struct {
-	val		int;
+	val int
 }
 
 func (this *Integer) Init(i int) *Integer {
-	this.val = i;
-	return this;
+	this.val = i
+	return this
 }
 
-func (this *Integer) Print() {
-	print(this.val);
+func (this *Integer) Print() string {
+	return string(this.val + '0')
 }
 
-func
-main() {
-	list := new(List);
-	list.Init();
+func main() {
+	list := new(List)
+	list.Init()
 	for i := 0; i < 10; i = i + 1 {
-		integer := new(Integer);
-		integer.Init(i);
-		list.Insert(integer);
+		integer := new(Integer)
+		integer.Init(i)
+		list.Insert(integer)
 	}
 
-	list.Print();
-	print("\n");
+	r := list.Print()
+	if r != "9876543210" {
+		panic(r)
+	}
 }
diff --git a/test/ken/rob2.go b/test/ken/rob2.go
index af63e4d..d13e244 100644
--- a/test/ken/rob2.go
+++ b/test/ken/rob2.go
@@ -4,269 +4,274 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-
 package main
 
-const nilchar = 0;
+import "fmt"
+
+const nilchar = 0
 
 type Atom struct {
-	str		string;
-	integer		int;
-	next		*Slist;	/* in hash bucket */
+	str     string
+	integer int
+	next    *Slist /* in hash bucket */
 }
 
 type List struct {
-	car		*Slist;
-	cdr*Slist;
+	car *Slist
+	cdr *Slist
 }
 
 type Slist struct {
-	isatom		bool;
-	isstring	bool;
+	isatom   bool
+	isstring bool
 	//union {
-	atom		Atom;
-	list		List;
+	atom Atom
+	list List
 	//} u;
 
 }
 
 func (this *Slist) Car() *Slist {
-	return this.list.car;
+	return this.list.car
 }
 
 func (this *Slist) Cdr() *Slist {
-	return this.list.cdr;
+	return this.list.cdr
 }
 
 func (this *Slist) String() string {
-	return this.atom.str;
+	return this.atom.str
 }
 
 func (this *Slist) Integer() int {
-	return this.atom.integer;
+	return this.atom.integer
 }
 
 func (slist *Slist) Free() {
 	if slist == nil {
-		return;
+		return
 	}
 	if slist.isatom {
-//		free(slist.String());
+		//		free(slist.String());
 	} else {
-		slist.Car().Free();
-		slist.Cdr().Free();
+		slist.Car().Free()
+		slist.Cdr().Free()
 	}
-//	free(slist);
+	//	free(slist);
 }
 
 //Slist* atom(byte *s, int i);
 
-var token int;
-var peekc int = -1;
-var lineno int32 = 1;
+var token int
+var peekc int = -1
+var lineno int32 = 1
 
-var input string;
-var inputindex int = 0;
-var tokenbuf [100]byte;
-var tokenlen int = 0;
+var input string
+var inputindex int = 0
+var tokenbuf [100]byte
+var tokenlen int = 0
 
-const EOF int = -1;
+const EOF int = -1
 
 func main() {
-	var list *Slist;
+	var list *Slist
 
-	OpenFile();
-	for ;; {
-		list = Parse();
+	OpenFile()
+	for {
+		list = Parse()
 		if list == nil {
-			break;
+			break
+		}
+		r := list.Print()
+		list.Free()
+		if r != "(defn foo (add 12 34))" {
+			panic(r)
 		}
-		list.Print();
-		list.Free();
-		break;
+		break
 	}
 }
 
-func (slist *Slist) PrintOne(doparen bool) {
+func (slist *Slist) PrintOne(doparen bool) string {
 	if slist == nil {
-		return;
+		return ""
 	}
+	var r string
 	if slist.isatom {
 		if slist.isstring {
-			print(slist.String());
+			r = slist.String()
 		} else {
-			print(slist.Integer());
+			r = fmt.Sprintf("%v", slist.Integer())
 		}
 	} else {
 		if doparen {
-			print("(" );
+			r += "("
 		}
-		slist.Car().PrintOne(true);
+		r += slist.Car().PrintOne(true)
 		if slist.Cdr() != nil {
-			print(" ");
-			slist.Cdr().PrintOne(false);
+			r += " "
+			r += slist.Cdr().PrintOne(false)
 		}
 		if doparen {
-			print(")");
+			r += ")"
 		}
 	}
+	return r
 }
 
-func (slist *Slist) Print() {
-	slist.PrintOne(true);
-	print("\n");
+func (slist *Slist) Print() string {
+	return slist.PrintOne(true)
 }
 
 func Get() int {
-	var c int;
+	var c int
 
 	if peekc >= 0 {
-		c = peekc;
-		peekc = -1;
+		c = peekc
+		peekc = -1
 	} else {
-		c = int(input[inputindex]);
-		inputindex++;
+		c = int(input[inputindex])
+		inputindex++
 		if c == '\n' {
-			lineno = lineno + 1;
+			lineno = lineno + 1
 		}
 		if c == nilchar {
-			inputindex = inputindex - 1;
-			c = EOF;
+			inputindex = inputindex - 1
+			c = EOF
 		}
 	}
-	return c;
+	return c
 }
 
 func WhiteSpace(c int) bool {
-	return c == ' ' || c == '\t' || c == '\r' || c == '\n';
+	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
 }
 
 func NextToken() {
-	var i, c int;
+	var i, c int
 
-	tokenbuf[0] = nilchar;	// clear previous token
-	c = Get();
+	tokenbuf[0] = nilchar // clear previous token
+	c = Get()
 	for WhiteSpace(c) {
-		c = Get();
+		c = Get()
 	}
 	switch c {
 	case EOF:
-		token = EOF;
+		token = EOF
 	case '(', ')':
-		token = c;
-		break;
+		token = c
+		break
 	default:
-		for i = 0; i < 100 - 1; {	// sizeof tokenbuf - 1
-			tokenbuf[i] = byte(c);
-			i = i + 1;
-			c = Get();
+		for i = 0; i < 100-1; { // sizeof tokenbuf - 1
+			tokenbuf[i] = byte(c)
+			i = i + 1
+			c = Get()
 			if c == EOF {
-				break;
+				break
 			}
 			if WhiteSpace(c) || c == ')' {
-				peekc = c;
-				break;
+				peekc = c
+				break
 			}
 		}
-		if i >= 100 - 1 {	// sizeof tokenbuf - 1
-			panic("atom too long\n");
+		if i >= 100-1 { // sizeof tokenbuf - 1
+			panic("atom too long\n")
 		}
-		tokenlen = i;
-		tokenbuf[i] = nilchar;
+		tokenlen = i
+		tokenbuf[i] = nilchar
 		if '0' <= tokenbuf[0] && tokenbuf[0] <= '9' {
-			token = '0';
+			token = '0'
 		} else {
-			token = 'A';
+			token = 'A'
 		}
 	}
 }
 
 func Expect(c int) {
 	if token != c {
-		print("parse error: expected ", c, "\n");
-		panic("parse");
+		print("parse error: expected ", c, "\n")
+		panic("parse")
 	}
-	NextToken();
+	NextToken()
 }
 
 // Parse a non-parenthesized list up to a closing paren or EOF
 func ParseList() *Slist {
-	var slist, retval *Slist;
-
-	slist = new(Slist);
-	slist.list.car = nil;
-	slist.list.cdr = nil;
-	slist.isatom = false;
-	slist.isstring = false;
-
-	retval = slist;
-	for ;; {
-		slist.list.car = Parse();
-		if token == ')' || token == EOF {	// empty cdr
-			break;
+	var slist, retval *Slist
+
+	slist = new(Slist)
+	slist.list.car = nil
+	slist.list.cdr = nil
+	slist.isatom = false
+	slist.isstring = false
+
+	retval = slist
+	for {
+		slist.list.car = Parse()
+		if token == ')' || token == EOF { // empty cdr
+			break
 		}
-		slist.list.cdr = new(Slist);
-		slist = slist.list.cdr;
+		slist.list.cdr = new(Slist)
+		slist = slist.list.cdr
 	}
-	return retval;
+	return retval
 }
 
-func atom(i int) *Slist	{ // BUG: uses tokenbuf; should take argument)
-	var slist *Slist;
+func atom(i int) *Slist { // BUG: uses tokenbuf; should take argument)
+	var slist *Slist
 
-	slist = new(Slist);
+	slist = new(Slist)
 	if token == '0' {
-		slist.atom.integer = i;
-		slist.isstring = false;
+		slist.atom.integer = i
+		slist.isstring = false
 	} else {
-		slist.atom.str = string(tokenbuf[0:tokenlen]);
-		slist.isstring = true;
+		slist.atom.str = string(tokenbuf[0:tokenlen])
+		slist.isstring = true
 	}
-	slist.isatom = true;
-	return slist;
+	slist.isatom = true
+	return slist
 }
 
-func atoi() int	{ // BUG: uses tokenbuf; should take argument)
-	var v int = 0;
+func atoi() int { // BUG: uses tokenbuf; should take argument)
+	var v int = 0
 	for i := 0; i < tokenlen && '0' <= tokenbuf[i] && tokenbuf[i] <= '9'; i = i + 1 {
-		v = 10 * v + int(tokenbuf[i] - '0');
+		v = 10*v + int(tokenbuf[i]-'0')
 	}
-	return v;
+	return v
 }
 
 func Parse() *Slist {
-	var slist *Slist;
+	var slist *Slist
 
 	if token == EOF || token == ')' {
-		return nil;
+		return nil
 	}
 	if token == '(' {
-		NextToken();
-		slist = ParseList();
-		Expect(')');
-		return slist;
+		NextToken()
+		slist = ParseList()
+		Expect(')')
+		return slist
 	} else {
 		// Atom
 		switch token {
 		case EOF:
-			return nil;
+			return nil
 		case '0':
-			slist = atom(atoi());
+			slist = atom(atoi())
 		case '"', 'A':
-			slist = atom(0);
+			slist = atom(0)
 		default:
-			slist = nil;
-			print("unknown token: ", token, "\n");
+			slist = nil
+			print("unknown token: ", token, "\n")
 		}
-		NextToken();
-		return slist;
+		NextToken()
+		return slist
 	}
-	return nil;
+	return nil
 }
 
 func OpenFile() {
-	input = "(defn foo (add 12 34))\n\x00";
-	inputindex = 0;
-	peekc = -1;		// BUG
-	NextToken();
+	input = "(defn foo (add 12 34))\n\x00"
+	inputindex = 0
+	peekc = -1 // BUG
+	NextToken()
 }
diff --git a/test/ken/simpprint.go b/test/ken/simpprint.go
deleted file mode 100644
index 6077f7e..0000000
--- a/test/ken/simpprint.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-
-package main
-
-func
-main() {
-	print("hello world\n");
-}
diff --git a/test/ken/simpswitch.go b/test/ken/simpswitch.go
index ab5dd35..710af2e 100644
--- a/test/ken/simpswitch.go
+++ b/test/ken/simpswitch.go
@@ -6,19 +6,21 @@
 
 package main
 
-func
-main() {
-	a := 3;
-	for i:=0; i<10; i=i+1 {
-		switch(i) {
+func main() {
+	r := ""
+	a := 3
+	for i := 0; i < 10; i = i + 1 {
+		switch i {
 		case 5:
-			print("five");
-		case a,7:
-			print("a");
+			r += "five"
+		case a, 7:
+			r += "a"
 		default:
-			print(i);
+			r += string(i + '0')
 		}
-		print("out", i);
+		r += "out" + string(i+'0')
+	}
+	if r != "0out01out12out2aout34out4fiveout56out6aout78out89out9" {
+		panic(r)
 	}
-	print("\n");
 }
diff --git a/test/ken/string.go b/test/ken/string.go
index cbedad4..e051082 100644
--- a/test/ken/string.go
+++ b/test/ken/string.go
@@ -1,4 +1,4 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
+// $G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -71,16 +71,14 @@ func main() {
 	/* create string with integer constant */
 	c = string('x')
 	if c != "x" {
-		print("create int ", c)
-		panic("fail")
+		panic("create int " + c)
 	}
 
 	/* create string with integer variable */
 	v := 'x'
 	c = string(v)
 	if c != "x" {
-		print("create int ", c)
-		panic("fail")
+		panic("create int " + c)
 	}
 
 	/* create string with byte array */
@@ -90,19 +88,17 @@ func main() {
 	z1[2] = 'c'
 	c = string(z1[0:])
 	if c != "abc" {
-		print("create byte array ", c)
-		panic("fail")
+		panic("create byte array " + c)
 	}
 
 	/* create string with int array */
-	var z2 [3]int
+	var z2 [3]rune
 	z2[0] = 'a'
 	z2[1] = '\u1234'
 	z2[2] = 'c'
 	c = string(z2[0:])
 	if c != "a\u1234c" {
-		print("create int array ", c)
-		panic("fail")
+		panic("create int array " + c)
 	}
 
 	/* create string with byte array pointer */
@@ -112,7 +108,6 @@ func main() {
 	z3[2] = 'c'
 	c = string(z3[0:])
 	if c != "abc" {
-		print("create array pointer ", c)
-		panic("fail")
+		panic("create array pointer " + c)
 	}
 }
diff --git a/test/ken/string.out b/test/ken/string.out
new file mode 100644
index 0000000..8bc36bc
--- /dev/null
+++ b/test/ken/string.out
@@ -0,0 +1 @@
+abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz-abcxyz
diff --git a/test/mallocfin.go b/test/mallocfin.go
index dc6d74b..ff62392 100644
--- a/test/mallocfin.go
+++ b/test/mallocfin.go
@@ -47,18 +47,28 @@ func finalB(b *B) {
 	nfinal++
 }
 
+func nofinalB(b *B) {
+	panic("nofinalB run")
+}
+
 func main() {
 	runtime.GOMAXPROCS(4)
 	for i = 0; i < N; i++ {
 		b := &B{i}
 		a := &A{b, i}
+		c := new(B)
+		runtime.SetFinalizer(c, nofinalB)
 		runtime.SetFinalizer(b, finalB)
 		runtime.SetFinalizer(a, finalA)
+		runtime.SetFinalizer(c, nil)
 	}
 	for i := 0; i < N; i++ {
 		runtime.GC()
 		runtime.Gosched()
 		time.Sleep(1e6)
+		if nfinal >= N*8/10 {
+			break
+		}
 	}
 	if nfinal < N*8/10 {
 		println("not enough finalizing:", nfinal, "/", N)
diff --git a/test/mallocrand.go b/test/mallocrand.go
index f014b44..726e367 100644
--- a/test/mallocrand.go
+++ b/test/mallocrand.go
@@ -10,7 +10,7 @@ package main
 
 import (
 	"flag"
-	"rand"
+	"math/rand"
 	"runtime"
 	"unsafe"
 )
diff --git a/test/mallocrep.go b/test/mallocrep.go
index 9f47e52..cffcd16 100644
--- a/test/mallocrep.go
+++ b/test/mallocrep.go
@@ -33,6 +33,7 @@ func bigger() {
 
 func main() {
 	runtime.GC()               // clean up garbage from init
+	runtime.UpdateMemStats()   // first call can do some allocations
 	runtime.MemProfileRate = 0 // disable profiler
 	runtime.MemStats.Alloc = 0 // ignore stacks
 	flag.Parse()
diff --git a/test/map.go b/test/map.go
index c396349..1c66986 100644
--- a/test/map.go
+++ b/test/map.go
@@ -8,6 +8,7 @@ package main
 
 import (
 	"fmt"
+	"math"
 	"strconv"
 )
 
@@ -488,4 +489,160 @@ func main() {
 	for _, _ = range mnil {
 		panic("range mnil")
 	}
+
+	testfloat()
+}
+
+func testfloat() {
+	// Test floating point numbers in maps.
+	// Two map keys refer to the same entry if the keys are ==.
+	// The special cases, then, are that +0 == -0 and that NaN != NaN.
+
+	{
+		var (
+			pz   = float32(0)
+			nz   = math.Float32frombits(1 << 31)
+			nana = float32(math.NaN())
+			nanb = math.Float32frombits(math.Float32bits(nana) ^ 2)
+		)
+
+		m := map[float32]string{
+			pz:   "+0",
+			nana: "NaN",
+			nanb: "NaN",
+		}
+		if m[pz] != "+0" {
+			fmt.Println("float32 map cannot read back m[+0]:", m[pz])
+		}
+		if m[nz] != "+0" {
+			fmt.Println("float32 map does not treat", pz, "and", nz, "as equal for read")
+			fmt.Println("float32 map does not treat -0 and +0 as equal for read")
+		}
+		m[nz] = "-0"
+		if m[pz] != "-0" {
+			fmt.Println("float32 map does not treat -0 and +0 as equal for write")
+		}
+		if _, ok := m[nana]; ok {
+			fmt.Println("float32 map allows NaN lookup (a)")
+		}
+		if _, ok := m[nanb]; ok {
+			fmt.Println("float32 map allows NaN lookup (b)")
+		}
+		if len(m) != 3 {
+			fmt.Println("float32 map should have 3 entries:", m)
+		}
+		m[nana] = "NaN"
+		m[nanb] = "NaN"
+		if len(m) != 5 {
+			fmt.Println("float32 map should have 5 entries:", m)
+		}
+	}
+
+	{
+		var (
+			pz   = float64(0)
+			nz   = math.Float64frombits(1 << 63)
+			nana = float64(math.NaN())
+			nanb = math.Float64frombits(math.Float64bits(nana) ^ 2)
+		)
+
+		m := map[float64]string{
+			pz:   "+0",
+			nana: "NaN",
+			nanb: "NaN",
+		}
+		if m[nz] != "+0" {
+			fmt.Println("float64 map does not treat -0 and +0 as equal for read")
+		}
+		m[nz] = "-0"
+		if m[pz] != "-0" {
+			fmt.Println("float64 map does not treat -0 and +0 as equal for write")
+		}
+		if _, ok := m[nana]; ok {
+			fmt.Println("float64 map allows NaN lookup (a)")
+		}
+		if _, ok := m[nanb]; ok {
+			fmt.Println("float64 map allows NaN lookup (b)")
+		}
+		if len(m) != 3 {
+			fmt.Println("float64 map should have 3 entries:", m)
+		}
+		m[nana] = "NaN"
+		m[nanb] = "NaN"
+		if len(m) != 5 {
+			fmt.Println("float64 map should have 5 entries:", m)
+		}
+	}
+
+	{
+		var (
+			pz   = complex64(0)
+			nz   = complex(0, math.Float32frombits(1<<31))
+			nana = complex(5, float32(math.NaN()))
+			nanb = complex(5, math.Float32frombits(math.Float32bits(float32(math.NaN()))^2))
+		)
+
+		m := map[complex64]string{
+			pz:   "+0",
+			nana: "NaN",
+			nanb: "NaN",
+		}
+		if m[nz] != "+0" {
+			fmt.Println("complex64 map does not treat -0 and +0 as equal for read")
+		}
+		m[nz] = "-0"
+		if m[pz] != "-0" {
+			fmt.Println("complex64 map does not treat -0 and +0 as equal for write")
+		}
+		if _, ok := m[nana]; ok {
+			fmt.Println("complex64 map allows NaN lookup (a)")
+		}
+		if _, ok := m[nanb]; ok {
+			fmt.Println("complex64 map allows NaN lookup (b)")
+		}
+		if len(m) != 3 {
+			fmt.Println("complex64 map should have 3 entries:", m)
+		}
+		m[nana] = "NaN"
+		m[nanb] = "NaN"
+		if len(m) != 5 {
+			fmt.Println("complex64 map should have 5 entries:", m)
+		}
+	}
+
+	{
+		var (
+			pz   = complex128(0)
+			nz   = complex(0, math.Float64frombits(1<<63))
+			nana = complex(5, float64(math.NaN()))
+			nanb = complex(5, math.Float64frombits(math.Float64bits(float64(math.NaN()))^2))
+		)
+
+		m := map[complex128]string{
+			pz:   "+0",
+			nana: "NaN",
+			nanb: "NaN",
+		}
+		if m[nz] != "+0" {
+			fmt.Println("complex128 map does not treat -0 and +0 as equal for read")
+		}
+		m[nz] = "-0"
+		if m[pz] != "-0" {
+			fmt.Println("complex128 map does not treat -0 and +0 as equal for write")
+		}
+		if _, ok := m[nana]; ok {
+			fmt.Println("complex128 map allows NaN lookup (a)")
+		}
+		if _, ok := m[nanb]; ok {
+			fmt.Println("complex128 map allows NaN lookup (b)")
+		}
+		if len(m) != 3 {
+			fmt.Println("complex128 map should have 3 entries:", m)
+		}
+		m[nana] = "NaN"
+		m[nanb] = "NaN"
+		if len(m) != 5 {
+			fmt.Println("complex128 map should have 5 entries:", m)
+		}
+	}
 }
diff --git a/test/map1.go b/test/map1.go
index 3a56cf0..6af1056 100644
--- a/test/map1.go
+++ b/test/map1.go
@@ -12,16 +12,16 @@ type v bool
 
 var (
 	// valid
-	_ map[int8]v 
-	_ map[uint8]v 
-	_ map[int16]v 
-	_ map[uint16]v 
-	_ map[int32]v 
-	_ map[uint32]v 
-	_ map[int64]v 
-	_ map[uint64]v 
-	_ map[int]v 
-	_ map[uint]v 
+	_ map[int8]v
+	_ map[uint8]v
+	_ map[int16]v
+	_ map[uint16]v
+	_ map[int32]v
+	_ map[uint32]v
+	_ map[int64]v
+	_ map[uint64]v
+	_ map[int]v
+	_ map[uint]v
 	_ map[uintptr]v
 	_ map[float32]v
 	_ map[float64]v
@@ -30,12 +30,12 @@ var (
 	_ map[bool]v
 	_ map[string]v
 	_ map[chan int]v
-	_ map[func()]v
 	_ map[*int]v
-	_ map[map[int]int]v
+	_ map[struct{}]v
+	_ map[[10]int]v
 
 	// invalid
-	_ map[struct{}]v // ERROR "invalid map key"
-	_ map[[]int]v  // ERROR "invalid map key"
-	_ map[[10]int]v // ERROR "invalid map key"
+	_ map[[]int]v       // ERROR "invalid map key"
+	_ map[func()]v      // ERROR "invalid map key"
+	_ map[map[int]int]v // ERROR "invalid map key"
 )
diff --git a/test/named1.go b/test/named1.go
index 7e7aab9..499b77b 100644
--- a/test/named1.go
+++ b/test/named1.go
@@ -41,7 +41,6 @@ func main() {
 	asBool(i < j)  // ERROR "cannot use.*type bool.*as type Bool"
 
 	_, b = m[2] // ERROR "cannot .* bool.*type Bool"
-	m[2] = 1, b // ERROR "cannot use.*type Bool.*as type bool"
 
 	var inter interface{}
 	_, b = inter.(Map) // ERROR "cannot .* bool.*type Bool"
@@ -55,8 +54,8 @@ func main() {
 
 	_, bb := <-c
 	asBool(bb) // ERROR "cannot use.*type bool.*as type Bool"
-	_, b = <-c     // ERROR "cannot .* bool.*type Bool"
+	_, b = <-c // ERROR "cannot .* bool.*type Bool"
 	_ = b
 
-	asString(String(slice)) // ERROR "cannot .*type Slice.*type String"
+	asString(String(slice)) // ok
 }
diff --git a/test/nil.go b/test/nil.go
index 30cc270..efcf4f7 100644
--- a/test/nil.go
+++ b/test/nil.go
@@ -150,7 +150,7 @@ func maptest() {
 		m[2] = 3
 	})
 	shouldPanic(func() {
-		m[2] = 0, false
+		delete(m, 2)
 	})
 }
 
diff --git a/test/nilptr.go b/test/nilptr.go
new file mode 100644
index 0000000..b0c1df2
--- /dev/null
+++ b/test/nilptr.go
@@ -0,0 +1,129 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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 "unsafe"
+
+// Having a big address space means that indexing
+// at a 256 MB offset from a nil pointer might not
+// cause a memory access fault. This test checks
+// that Go is doing the correct explicit checks to catch
+// these nil pointer accesses, not just relying on the hardware.
+var dummy [256 << 20]byte // give us a big address space
+
+func main() {
+	// the test only tests what we intend to test
+	// if dummy starts in the first 256 MB of memory.
+	// otherwise there might not be anything mapped
+	// at the address that might be accidentally
+	// dereferenced below.
+	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
+		panic("dummy too far out")
+	}
+
+	shouldPanic(p1)
+	shouldPanic(p2)
+	shouldPanic(p3)
+	shouldPanic(p4)
+	shouldPanic(p5)
+	shouldPanic(p6)
+	shouldPanic(p7)
+	shouldPanic(p8)
+	shouldPanic(p9)
+	shouldPanic(p10)
+}
+
+func shouldPanic(f func()) {
+	defer func() {
+		if recover() == nil {
+			panic("memory reference did not panic")
+		}
+	}()
+	f()
+}
+
+func p1() {
+	// Array index.
+	var p *[1 << 30]byte = nil
+	println(p[256<<20]) // very likely to be inside dummy, but should panic
+}
+
+var xb byte
+
+func p2() {
+	var p *[1 << 30]byte = nil
+	xb = 123
+
+	// Array index.
+	println(p[uintptr(unsafe.Pointer(&xb))]) // should panic
+}
+
+func p3() {
+	// Array to slice.
+	var p *[1 << 30]byte = nil
+	var x []byte = p[0:] // should panic
+	_ = x
+}
+
+var q *[1 << 30]byte
+
+func p4() {
+	// Array to slice.
+	var x []byte
+	var y = &x
+	*y = q[0:] // should crash (uses arraytoslice runtime routine)
+}
+
+func fb([]byte) {
+	panic("unreachable")
+}
+
+func p5() {
+	// Array to slice.
+	var p *[1 << 30]byte = nil
+	fb(p[0:]) // should crash
+}
+
+func p6() {
+	// Array to slice.
+	var p *[1 << 30]byte = nil
+	var _ []byte = p[10 : len(p)-10] // should crash
+}
+
+type T struct {
+	x [256 << 20]byte
+	i int
+}
+
+func f() *T {
+	return nil
+}
+
+var y *T
+var x = &y
+
+func p7() {
+	// Struct field access with large offset.
+	println(f().i) // should crash
+}
+
+func p8() {
+	// Struct field access with large offset.
+	println((*x).i) // should crash
+}
+
+func p9() {
+	// Struct field access with large offset.
+	var t *T
+	println(&t.i) // should crash
+}
+
+func p10() {
+	// Struct field access with large offset.
+	var t *T
+	println(t.i) // should crash
+}
diff --git a/test/nilptr/arrayindex.go b/test/nilptr/arrayindex.go
deleted file mode 100644
index fa26532..0000000
--- a/test/nilptr/arrayindex.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var x byte
-
-func main() {
-	var p *[1<<30]byte = nil
-	x = 123
-
-	// The problem here is not the use of unsafe:
-	// it is that indexing into p[] with a large
-	// enough index jumps out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	// Pointer offsets and array indices, if they are
-	// very large, need to dereference the base pointer
-	// to trigger a trap.
-	println(p[uintptr(unsafe.Pointer(&x))])	// should crash
-}
diff --git a/test/nilptr/arrayindex1.go b/test/nilptr/arrayindex1.go
deleted file mode 100644
index 64f46e1..0000000
--- a/test/nilptr/arrayindex1.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var dummy [512<<20]byte	// give us a big address space
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into p[] with a large
-	// enough index jumps out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	// Pointer offsets and array indices, if they are
-	// very large, need to dereference the base pointer
-	// to trigger a trap.
-	var p *[1<<30]byte = nil
-	println(p[256<<20])	// very likely to be inside dummy, but should crash
-}
diff --git a/test/nilptr/arraytoslice.go b/test/nilptr/arraytoslice.go
deleted file mode 100644
index 03879fb..0000000
--- a/test/nilptr/arraytoslice.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-func f([]byte) {
-	panic("unreachable")
-}
-
-var dummy [512<<20]byte	// give us a big address space
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into p[] with a large
-	// enough index can jump out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	//
-	// To avoid needing a check on every slice beyond the
-	// usual len and cap, we require the *array -> slice
-	// conversion to do the check.
-	var p *[1<<30]byte = nil
-	f(p[0:])	// should crash
-}
diff --git a/test/nilptr/arraytoslice1.go b/test/nilptr/arraytoslice1.go
deleted file mode 100644
index c86070f..0000000
--- a/test/nilptr/arraytoslice1.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var dummy [512<<20]byte	// give us a big address space
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into p[] with a large
-	// enough index can jump out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	//
-	// To avoid needing a check on every slice beyond the
-	// usual len and cap, we require the *array -> slice
-	// conversion to do the check.
-	var p *[1<<30]byte = nil
-	var x []byte = p[0:]	// should crash
-	_ = x
-}
diff --git a/test/nilptr/arraytoslice2.go b/test/nilptr/arraytoslice2.go
deleted file mode 100644
index 68ea440..0000000
--- a/test/nilptr/arraytoslice2.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var dummy [512<<20]byte	// give us a big address space
-var q *[1<<30]byte
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into p[] with a large
-	// enough index can jump out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	//
-	// To avoid needing a check on every slice beyond the
-	// usual len and cap, we require the *array -> slice
-	// conversion to do the check.
-	var x []byte
-	var y = &x
-	*y = q[0:]	// should crash (uses arraytoslice runtime routine)
-}
diff --git a/test/nilptr/slicearray.go b/test/nilptr/slicearray.go
deleted file mode 100644
index 26ca427..0000000
--- a/test/nilptr/slicearray.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var dummy [512<<20]byte	// give us a big address space
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into p[] with a large
-	// enough index can jump out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	//
-	// To avoid needing a check on every slice beyond the
-	// usual len and cap, we require the slice operation
-	// to do the check.
-	var p *[1<<30]byte = nil
-	var _ []byte = p[10:len(p)-10]	// should crash
-}
diff --git a/test/nilptr/structfield.go b/test/nilptr/structfield.go
deleted file mode 100644
index 35196bb..0000000
--- a/test/nilptr/structfield.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var dummy [512<<20]byte	// give us a big address space
-type T struct {
-	x [256<<20] byte
-	i int
-}
-
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into t with a large
-	// enough index can jump out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	// We require the pointer dereference to check.
-	var t *T
-	println(t.i)	// should crash
-}
diff --git a/test/nilptr/structfield1.go b/test/nilptr/structfield1.go
deleted file mode 100644
index 7c7abed..0000000
--- a/test/nilptr/structfield1.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var dummy [512<<20]byte	// give us a big address space
-type T struct {
-	x [256<<20] byte
-	i int
-}
-
-func f() *T {
-	return nil
-}
-
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into t with a large
-	// enough index can jump out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	// We require the pointer dereference to check.
-	println(f().i)	// should crash
-}
diff --git a/test/nilptr/structfield2.go b/test/nilptr/structfield2.go
deleted file mode 100644
index 02a44f1..0000000
--- a/test/nilptr/structfield2.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var dummy [512<<20]byte	// give us a big address space
-type T struct {
-	x [256<<20] byte
-	i int
-}
-
-var y *T
-var x = &y
-
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into t with a large
-	// enough index can jump out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	// We require the pointer dereference to check.
-	println((*x).i)	// should crash
-}
diff --git a/test/nilptr/structfieldaddr.go b/test/nilptr/structfieldaddr.go
deleted file mode 100644
index f3177ba..0000000
--- a/test/nilptr/structfieldaddr.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// $G $D/$F.go && $L $F.$A &&
-//	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-var dummy [512<<20]byte	// give us a big address space
-type T struct {
-	x [256<<20] byte
-	i int
-}
-
-func main() {
-	// the test only tests what we intend to test
-	// if dummy starts in the first 256 MB of memory.
-	// otherwise there might not be anything mapped
-	// at the address that might be accidentally
-	// dereferenced below.
-	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
-		panic("dummy too far out")
-	}
-
-	// The problem here is that indexing into t with a large
-	// enough index can jump out of the unmapped section
-	// at the beginning of memory and into valid memory.
-	// We require the address calculation to check.
-	var t *T
-	println(&t.i)	// should crash
-}
diff --git a/test/peano.go b/test/peano.go
index f4c59d1..dd4c36e 100644
--- a/test/peano.go
+++ b/test/peano.go
@@ -8,7 +8,6 @@ package main
 
 type Number *Number
 
-
 // -------------------------------------
 // Peano primitives
 
@@ -16,24 +15,20 @@ func zero() *Number {
 	return nil
 }
 
-
 func is_zero(x *Number) bool {
 	return x == nil
 }
 
-
 func add1(x *Number) *Number {
 	e := new(Number)
 	*e = x
 	return e
 }
 
-
 func sub1(x *Number) *Number {
 	return *x
 }
 
-
 func add(x, y *Number) *Number {
 	if is_zero(y) {
 		return x
@@ -42,7 +37,6 @@ func add(x, y *Number) *Number {
 	return add(add1(x), sub1(y))
 }
 
-
 func mul(x, y *Number) *Number {
 	if is_zero(x) || is_zero(y) {
 		return zero()
@@ -51,7 +45,6 @@ func mul(x, y *Number) *Number {
 	return add(mul(x, sub1(y)), x)
 }
 
-
 func fact(n *Number) *Number {
 	if is_zero(n) {
 		return add1(zero())
@@ -60,7 +53,6 @@ func fact(n *Number) *Number {
 	return mul(fact(sub1(n)), n)
 }
 
-
 // -------------------------------------
 // Helpers to generate/count Peano integers
 
@@ -72,7 +64,6 @@ func gen(n int) *Number {
 	return zero()
 }
 
-
 func count(x *Number) int {
 	if is_zero(x) {
 		return 0
@@ -81,7 +72,6 @@ func count(x *Number) int {
 	return count(sub1(x)) + 1
 }
 
-
 func check(x *Number, expected int) {
 	var c = count(x)
 	if c != expected {
@@ -90,7 +80,6 @@ func check(x *Number, expected int) {
 	}
 }
 
-
 // -------------------------------------
 // Test basic functionality
 
@@ -115,12 +104,19 @@ func init() {
 	check(fact(gen(5)), 120)
 }
 
-
 // -------------------------------------
 // Factorial
 
+var results = [...]int{
+	1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,
+	39916800, 479001600,
+}
+
 func main() {
 	for i := 0; i <= 9; i++ {
-		print(i, "! = ", count(fact(gen(i))), "\n")
+		if f := count(fact(gen(i))); f != results[i] {
+			println("FAIL:", i, "!:", f, "!=", results[i])
+			panic(0)
+		}
 	}
 }
diff --git a/test/printbig.go b/test/printbig.go
index bbb7070..d867bdc 100644
--- a/test/printbig.go
+++ b/test/printbig.go
@@ -1,4 +1,4 @@
-// $G $F.go && $L $F.$A && ./$A.out
+// $G $F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/printbig.out b/test/printbig.out
new file mode 100644
index 0000000..6a16b15
--- /dev/null
+++ b/test/printbig.out
@@ -0,0 +1,2 @@
+-9223372036854775808
+9223372036854775807
diff --git a/test/range.go b/test/range.go
index 91ccd63..8411945 100644
--- a/test/range.go
+++ b/test/range.go
@@ -172,7 +172,7 @@ func makestring() string {
 }
 
 func teststring() {
-	s := 0
+	var s rune
 	nmake = 0
 	for _, v := range makestring() {
 		s += v
@@ -208,7 +208,7 @@ func teststring1() {
 
 func makemap() map[int]int {
 	nmake++
-	return map[int]int{0:'a', 1:'b', 2:'c', 3:'d', 4:'☺'}
+	return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
 }
 
 func testmap() {
diff --git a/test/recover2.go b/test/recover2.go
index 9affe25..b5db6f0 100644
--- a/test/recover2.go
+++ b/test/recover2.go
@@ -11,10 +11,7 @@
 
 package main
 
-import (
-	"os"
-	"strings"
-)
+import "strings"
 
 var x = make([]byte, 10)
 
@@ -33,7 +30,7 @@ func mustRecover(s string) {
 	if v == nil {
 		panic("expected panic")
 	}
-	if e := v.(os.Error).String(); strings.Index(e, s) < 0 {
+	if e := v.(error).Error(); strings.Index(e, s) < 0 {
 		panic("want: " + s + "; have: " + e)
 	}
 }
@@ -63,6 +60,7 @@ func test4() {
 
 type T struct {
 	a, b int
+	c    []int
 }
 
 func test5() {
diff --git a/test/recover3.go b/test/recover3.go
index 2aa1df6..60ade9b 100644
--- a/test/recover3.go
+++ b/test/recover3.go
@@ -35,7 +35,7 @@ func check(name string, f func(), err string) {
 			println(name, "panicked but not with runtime.Error")
 			return
 		}
-		s := runt.String()
+		s := runt.Error()
 		if strings.Index(s, err) < 0 {
 			bug()
 			println(name, "panicked with", s, "not", err)
diff --git a/test/reorder.go b/test/reorder.go
new file mode 100644
index 0000000..67d0752
--- /dev/null
+++ b/test/reorder.go
@@ -0,0 +1,121 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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.
+
+// Check reordering of assignments.
+
+package main
+
+import "fmt"
+
+func main() {
+	p1()
+	p2()
+	p3()
+	p4()
+	p5()
+	p6()
+	p7()
+	p8()
+}
+
+var gx []int
+
+func f(i int) int {
+	return gx[i]
+}
+
+func check(x []int, x0, x1, x2 int) {
+	if x[0] != x0 || x[1] != x1 || x[2] != x2 {
+		fmt.Printf("%v, want %d,%d,%d\n", x, x0, x1, x2)
+		panic("failed")
+	}
+}
+
+func check3(x, y, z, xx, yy, zz int) {
+	if x != xx || y != yy || z != zz {
+		fmt.Printf("%d,%d,%d, want %d,%d,%d\n", x, y, z, xx, yy, zz)
+		panic("failed")
+	}
+}
+
+func p1() {
+	x := []int{1,2,3}
+	i := 0
+	i, x[i] = 1, 100
+	_ = i
+	check(x, 100, 2, 3)
+}
+
+func p2() {
+	x := []int{1,2,3}
+	i := 0
+	x[i], i = 100, 1
+	_ = i
+	check(x, 100, 2, 3)
+}
+
+func p3() {
+	x := []int{1,2,3}
+	y := x
+	gx = x
+	x[1], y[0] = f(0), f(1)
+	check(x, 2, 1, 3)
+}
+
+func p4() {
+	x := []int{1,2,3}
+	y := x
+	gx = x
+	x[1], y[0] = gx[0], gx[1]
+	check(x, 2, 1, 3)
+}
+
+func p5() {
+	x := []int{1,2,3}
+	y := x
+	p := &x[0]
+	q := &x[1]
+	*p, *q = x[1], y[0]
+	check(x, 2, 1, 3)
+}
+
+func p6() {
+	x := 1
+	y := 2
+	z := 3
+	px := &x
+	py := &y
+	*px, *py = y, x
+	check3(x, y, z, 2, 1, 3)	
+}
+
+func f1(x, y, z int) (xx, yy, zz int) {
+	return x, y, z
+}
+
+func f2() (x, y, z int) {
+	return f1(2, 1, 3)
+}
+
+func p7() {
+	x, y, z := f2()
+	check3(x, y, z, 2, 1, 3)
+}
+
+func p8() {
+	x := []int{1,2,3}
+
+	defer func() {
+		err := recover()
+		if err == nil {
+			panic("not panicking")
+		}
+		check(x, 100, 2, 3)
+	}()
+
+	i := 0
+	i, x[i], x[5] = 1, 100, 500
+}
diff --git a/test/reorder2.go b/test/reorder2.go
new file mode 100644
index 0000000..3e14985
--- /dev/null
+++ b/test/reorder2.go
@@ -0,0 +1,174 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2010 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.
+
+// derived from fixedbugs/bug294.go
+
+package main
+
+var log string
+
+type TT int
+
+func (t TT) a(s string) TT {
+	log += "a(" + s + ")"
+	return t
+}
+
+func (TT) b(s string) string {
+	log += "b(" + s + ")"
+	return s
+}
+
+type F func(s string) F
+
+func a(s string) F {
+	log += "a(" + s + ")"
+	return F(a)
+}
+
+func b(s string) string {
+	log += "b(" + s + ")"
+	return s
+}
+
+type I interface {
+	a(s string) I
+	b(s string) string
+}
+
+type T1 int
+
+func (t T1) a(s string) I {
+	log += "a(" + s + ")"
+	return t
+}
+
+func (T1) b(s string) string {
+	log += "b(" + s + ")"
+	return s
+}
+
+// f(g(), h()) where g is not inlinable but h is will have the same problem.
+// As will x := g() + h() (same conditions).
+// And g() <- h().
+func f(x, y string) {
+	log += "f(" + x + ", " + y + ")"
+}
+
+func ff(x, y string) {
+	for false {
+	} // prevent inl
+	log += "ff(" + x + ", " + y + ")"
+}
+
+func h(x string) string {
+	log += "h(" + x + ")"
+	return x
+}
+
+func g(x string) string {
+	for false {
+	} // prevent inl
+	log += "g(" + x + ")"
+	return x
+}
+
+func main() {
+	err := 0
+	var t TT
+	if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+		println("expecting a(1)a(2)a(3) , got ", log)
+		err++
+	}
+	log = ""
+
+	if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+		println("expecting a(1)b(2)a(2), got ", log)
+		err++
+	}
+	log = ""
+	if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+		println("expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+		err++
+	}
+	log = ""
+	var i I = T1(0)
+	if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+		println("expecting a(6)ba(7)ba(8)ba(9), got", log)
+		err++
+	}
+	log = ""
+
+	if s := t.a("1").b("3"); log != "a(1)b(3)" || s != "3" {
+		println("expecting a(1)b(3) and 3, got ", log, " and ", s)
+		err++
+	}
+	log = ""
+
+	if s := t.a("1").a(t.b("2")).b("3") + t.a("4").b("5"); log != "a(1)b(2)a(2)b(3)a(4)b(5)" || s != "35" {
+		println("expecting a(1)b(2)a(2)b(3)a(4)b(5) and 35, got ", log, " and ", s)
+		err++
+	}
+	log = ""
+
+	if s := t.a("4").b("5") + t.a("1").a(t.b("2")).b("3"); log != "a(4)b(5)a(1)b(2)a(2)b(3)" || s != "53" {
+		println("expecting a(4)b(5)a(1)b(2)a(2)b(3) and 35, got ", log, " and ", s)
+		err++
+	}
+	log = ""
+
+	if ff(g("1"), g("2")); log != "g(1)g(2)ff(1, 2)" {
+		println("expecting g(1)g(2)ff..., got ", log)
+		err++
+	}
+	log = ""
+
+	if ff(g("1"), h("2")); log != "g(1)h(2)ff(1, 2)" {
+		println("expecting g(1)h(2)ff..., got ", log)
+		err++
+	}
+	log = ""
+
+	if ff(h("1"), g("2")); log != "h(1)g(2)ff(1, 2)" {
+		println("expecting h(1)g(2)ff..., got ", log)
+		err++
+	}
+	log = ""
+
+	if ff(h("1"), h("2")); log != "h(1)h(2)ff(1, 2)" {
+		println("expecting h(1)h(2)ff..., got ", log)
+		err++
+	}
+	log = ""
+
+	if s := g("1") + g("2"); log != "g(1)g(2)" || s != "12" {
+		println("expecting g1g2 and 12, got ", log, " and ", s)
+		err++
+	}
+	log = ""
+
+	if s := g("1") + h("2"); log != "g(1)h(2)" || s != "12" {
+		println("expecting g1h2 and 12, got ", log, " and ", s)
+		err++
+	}
+	log = ""
+
+	if s := h("1") + g("2"); log != "h(1)g(2)" || s != "12" {
+		println("expecting h1g2 and 12, got ", log, " and ", s)
+		err++
+	}
+	log = ""
+
+	if s := h("1") + h("2"); log != "h(1)h(2)" || s != "12" {
+		println("expecting h1h2 and 12, got ", log, " and ", s)
+		err++
+	}
+	log = ""
+
+	if err > 0 {
+		panic("fail")
+	}
+}
diff --git a/test/run b/test/run
index 844ee5f..03c91ee 100755
--- a/test/run
+++ b/test/run
@@ -23,7 +23,7 @@ Xarm)
 	exit 1
 esac
 
-export G=${A}g
+export G="${A}g ${GCFLAGS}"
 export L=${A}l
 export GOTRACEBACK=0
 export LANG=C
@@ -53,7 +53,7 @@ filterout() {
 	grep '^'"$2"'$' $1 >/dev/null
 }
 
-for dir in . ken chan interface nilptr syntax dwarf fixedbugs bugs
+for dir in . ken chan interface syntax dwarf fixedbugs bugs
 do
 	echo
 	echo '==' $dir'/'
diff --git a/test/rune.go b/test/rune.go
new file mode 100644
index 0000000..3386972
--- /dev/null
+++ b/test/rune.go
@@ -0,0 +1,44 @@
+// $G $D/$F.go
+
+// Copyright 2011 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
+
+var (
+	r0 = 'a'
+	r1 = 'a'+1
+	r2 = 1+'a'
+	r3 = 'a'*2
+	r4 = 'a'/2
+	r5 = 'a'<<1
+	r6 = 'b'<<2
+	r7 int32
+
+	r = []rune{r0, r1, r2, r3, r4, r5, r6, r7}
+)
+
+var (
+	f0 = 1.2
+	f1 = 1.2/'a'
+
+	f = []float64{f0, f1}
+)
+
+var (
+	i0 = 1
+	i1 = 1<<'\x01'
+	
+	i = []int{i0, i1}
+)
+
+const (
+	maxRune = '\U0010FFFF'
+)
+
+var (
+	b0 = maxRune < r0
+	
+	b = []bool{b0}
+)
diff --git a/test/sigchld.go b/test/sigchld.go
index 1fb2e21..e7c3d5a 100644
--- a/test/sigchld.go
+++ b/test/sigchld.go
@@ -1,4 +1,5 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
+// [ "$GOOS" == windows ] ||
+// ($G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out)
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/sigchld.out b/test/sigchld.out
new file mode 100644
index 0000000..477d025
--- /dev/null
+++ b/test/sigchld.out
@@ -0,0 +1 @@
+survived SIGCHLD
diff --git a/test/solitaire.go b/test/solitaire.go
index c789bf2..473a1d1 100644
--- a/test/solitaire.go
+++ b/test/solitaire.go
@@ -14,7 +14,7 @@ const N = 11 + 1 // length of a board row (+1 for newline)
 // The board must be surrounded by 2 illegal fields in each direction
 // so that move() doesn't need to check the board boundaries. Periods
 // represent illegal fields, ● are pegs, and ○ are holes.
-var board = []int(
+var board = []rune(
 	`...........
 ...........
 ....●●●....
@@ -28,7 +28,6 @@ var board = []int(
 ...........
 `)
 
-
 // center is the position of the center hole if there is a single one;
 // otherwise it is -1.
 var center int
@@ -46,7 +45,6 @@ func init() {
 	}
 }
 
-
 var moves int // number of times move is called
 
 // move tests if there is a peg at position pos that can jump over another peg
@@ -63,7 +61,6 @@ func move(pos, dir int) bool {
 	return false
 }
 
-
 // unmove reverts a previously executed valid move.
 func unmove(pos, dir int) {
 	board[pos] = '●'
@@ -71,7 +68,6 @@ func unmove(pos, dir int) {
 	board[pos+2*dir] = 'â—‹'
 }
 
-
 // solve tries to find a sequence of moves such that there is only one peg left
 // at the end; if center is >= 0, that last peg must be in the center position.
 // If a solution is found, solve prints the board after each move in a backward
@@ -110,7 +106,6 @@ func solve() bool {
 	return false
 }
 
-
 func main() {
 	if !solve() {
 		println("no solution found")
diff --git a/test/string_lit.go b/test/string_lit.go
index 4358dd8..c702a05 100644
--- a/test/string_lit.go
+++ b/test/string_lit.go
@@ -35,14 +35,14 @@ func assert(a, b, c string) {
 }
 
 const (
-	gx1 = "aä本☺"
-	gx2 = "aä\xFF\xFF本☺"
+	gx1    = "aä本☺"
+	gx2    = "aä\xFF\xFF本☺"
 	gx2fix = "aä\uFFFD\uFFFD本☺"
 )
 
 var (
-	gr1 = []int(gx1)
-	gr2 = []int(gx2)
+	gr1 = []rune(gx1)
+	gr2 = []rune(gx2)
 	gb1 = []byte(gx1)
 	gb2 = []byte(gx2)
 )
@@ -93,26 +93,26 @@ func main() {
 
 	// test large runes. perhaps not the most logical place for this test.
 	var r int32
-	r = 0x10ffff;	// largest rune value
+	r = 0x10ffff // largest rune value
 	s = string(r)
 	assert(s, "\xf4\x8f\xbf\xbf", "largest rune")
 	r = 0x10ffff + 1
 	s = string(r)
 	assert(s, "\xef\xbf\xbd", "too-large rune")
 
-	assert(string(gr1), gx1, "global ->[]int")
-	assert(string(gr2), gx2fix, "global invalid ->[]int")
+	assert(string(gr1), gx1, "global ->[]rune")
+	assert(string(gr2), gx2fix, "global invalid ->[]rune")
 	assert(string(gb1), gx1, "->[]byte")
 	assert(string(gb2), gx2, "global invalid ->[]byte")
 
 	var (
-		r1 = []int(gx1)
-		r2 = []int(gx2)
+		r1 = []rune(gx1)
+		r2 = []rune(gx2)
 		b1 = []byte(gx1)
 		b2 = []byte(gx2)
 	)
-	assert(string(r1), gx1, "->[]int")
-	assert(string(r2), gx2fix, "invalid ->[]int")
+	assert(string(r1), gx1, "->[]rune")
+	assert(string(r2), gx2fix, "invalid ->[]rune")
 	assert(string(b1), gx1, "->[]byte")
 	assert(string(b2), gx2, "invalid ->[]byte")
 
diff --git a/test/stringrange.go b/test/stringrange.go
index d5ada26..6a7063e 100644
--- a/test/stringrange.go
+++ b/test/stringrange.go
@@ -9,28 +9,29 @@ package main
 import (
 	"fmt"
 	"os"
-	"utf8"
+	"unicode/utf8"
 )
 
 func main() {
 	s := "\000\123\x00\xca\xFE\u0123\ubabe\U0000babe\U0010FFFFx"
-	expect := []int{ 0, 0123, 0, 0xFFFD, 0xFFFD, 0x123, 0xbabe, 0xbabe, 0x10FFFF, 'x' }
+	expect := []rune{0, 0123, 0, 0xFFFD, 0xFFFD, 0x123, 0xbabe, 0xbabe, 0x10FFFF, 'x'}
 	offset := 0
-	var i, c int
+	var i int
+	var c rune
 	ok := true
 	cnum := 0
 	for i, c = range s {
-		rune, size := utf8.DecodeRuneInString(s[i:len(s)])  // check it another way
+		r, size := utf8.DecodeRuneInString(s[i:len(s)]) // check it another way
 		if i != offset {
 			fmt.Printf("unexpected offset %d not %d\n", i, offset)
 			ok = false
 		}
-		if rune != expect[cnum] {
-			fmt.Printf("unexpected rune %d from DecodeRuneInString: %x not %x\n", i, rune, expect[cnum])
+		if r != expect[cnum] {
+			fmt.Printf("unexpected rune %d from DecodeRuneInString: %x not %x\n", i, r, expect[cnum])
 			ok = false
 		}
 		if c != expect[cnum] {
-			fmt.Printf("unexpected rune %d from range: %x not %x\n", i, rune, expect[cnum])
+			fmt.Printf("unexpected rune %d from range: %x not %x\n", i, r, expect[cnum])
 			ok = false
 		}
 		offset += size
diff --git a/test/switch.go b/test/switch.go
index 0c253d6..bed027c 100644
--- a/test/switch.go
+++ b/test/switch.go
@@ -19,48 +19,75 @@ func main() {
 	hello := "hello"
 
 	switch true {
-	case i5 < 5: assert(false, "<")
-	case i5 == 5: assert(true, "!")
-	case i5 > 5: assert(false, ">")
+	case i5 < 5:
+		assert(false, "<")
+	case i5 == 5:
+		assert(true, "!")
+	case i5 > 5:
+		assert(false, ">")
 	}
 
 	switch {
-	case i5 < 5: assert(false, "<")
-	case i5 == 5: assert(true, "!")
-	case i5 > 5: assert(false, ">")
+	case i5 < 5:
+		assert(false, "<")
+	case i5 == 5:
+		assert(true, "!")
+	case i5 > 5:
+		assert(false, ">")
 	}
 
 	switch x := 5; true {
-	case i5 < x: assert(false, "<")
-	case i5 == x: assert(true, "!")
-	case i5 > x: assert(false, ">")
+	case i5 < x:
+		assert(false, "<")
+	case i5 == x:
+		assert(true, "!")
+	case i5 > x:
+		assert(false, ">")
 	}
 
 	switch x := 5; true {
-	case i5 < x: assert(false, "<")
-	case i5 == x: assert(true, "!")
-	case i5 > x: assert(false, ">")
+	case i5 < x:
+		assert(false, "<")
+	case i5 == x:
+		assert(true, "!")
+	case i5 > x:
+		assert(false, ">")
 	}
 
 	switch i5 {
-	case 0: assert(false, "0")
-	case 1: assert(false, "1")
-	case 2: assert(false, "2")
-	case 3: assert(false, "3")
-	case 4: assert(false, "4")
-	case 5: assert(true, "5")
-	case 6: assert(false, "6")
-	case 7: assert(false, "7")
-	case 8: assert(false, "8")
-	case 9: assert(false, "9")
-	default: assert(false, "default")
+	case 0:
+		assert(false, "0")
+	case 1:
+		assert(false, "1")
+	case 2:
+		assert(false, "2")
+	case 3:
+		assert(false, "3")
+	case 4:
+		assert(false, "4")
+	case 5:
+		assert(true, "5")
+	case 6:
+		assert(false, "6")
+	case 7:
+		assert(false, "7")
+	case 8:
+		assert(false, "8")
+	case 9:
+		assert(false, "9")
+	default:
+		assert(false, "default")
 	}
 
 	switch i5 {
-	case 0,1,2,3,4: assert(false, "4")
-	case 5: assert(true, "5")
-	case 6,7,8,9: assert(false, "9")
-	default: assert(false, "default")
+	case 0, 1, 2, 3, 4:
+		assert(false, "4")
+	case 5:
+		assert(true, "5")
+	case 6, 7, 8, 9:
+		assert(false, "9")
+	default:
+		assert(false, "default")
 	}
 
 	switch i5 {
@@ -68,72 +95,188 @@ func main() {
 	case 1:
 	case 2:
 	case 3:
-	case 4: assert(false, "4")
-	case 5: assert(true, "5")
+	case 4:
+		assert(false, "4")
+	case 5:
+		assert(true, "5")
 	case 6:
 	case 7:
 	case 8:
 	case 9:
-	default: assert(i5 == 5, "good")
+	default:
+		assert(i5 == 5, "good")
 	}
 
 	switch i5 {
-	case 0: dummy := 0; _ = dummy; fallthrough
-	case 1: dummy := 0; _ = dummy; fallthrough
-	case 2: dummy := 0; _ = dummy; fallthrough
-	case 3: dummy := 0; _ = dummy; fallthrough
-	case 4: dummy := 0; _ = dummy; assert(false, "4")
-	case 5: dummy := 0; _ = dummy; fallthrough
-	case 6: dummy := 0; _ = dummy; fallthrough
-	case 7: dummy := 0; _ = dummy; fallthrough
-	case 8: dummy := 0; _ = dummy; fallthrough
-	case 9: dummy := 0; _ = dummy; fallthrough
-	default: dummy := 0; _ = dummy; assert(i5 == 5, "good")
+	case 0:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 1:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 2:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 3:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 4:
+		dummy := 0
+		_ = dummy
+		assert(false, "4")
+	case 5:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 6:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 7:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 8:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 9:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	default:
+		dummy := 0
+		_ = dummy
+		assert(i5 == 5, "good")
 	}
 
 	fired := false
 	switch i5 {
-	case 0: dummy := 0; _ = dummy; fallthrough;  // tests scoping of cases
-	case 1: dummy := 0; _ = dummy; fallthrough
-	case 2: dummy := 0; _ = dummy; fallthrough
-	case 3: dummy := 0; _ = dummy; fallthrough
-	case 4: dummy := 0; _ = dummy; assert(false, "4")
-	case 5: dummy := 0; _ = dummy; fallthrough
-	case 6: dummy := 0; _ = dummy; fallthrough
-	case 7: dummy := 0; _ = dummy; fallthrough
-	case 8: dummy := 0; _ = dummy; fallthrough
-	case 9: dummy := 0; _ = dummy; fallthrough
-	default: dummy := 0; _ = dummy; fired = !fired; assert(i5 == 5, "good")
+	case 0:
+		dummy := 0
+		_ = dummy
+		fallthrough // tests scoping of cases
+	case 1:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 2:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 3:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 4:
+		dummy := 0
+		_ = dummy
+		assert(false, "4")
+	case 5:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 6:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 7:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 8:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	case 9:
+		dummy := 0
+		_ = dummy
+		fallthrough
+	default:
+		dummy := 0
+		_ = dummy
+		fired = !fired
+		assert(i5 == 5, "good")
 	}
 	assert(fired, "fired")
 
 	count := 0
 	switch i5 {
-	case 0: count = count + 1; fallthrough
-	case 1: count = count + 1; fallthrough
-	case 2: count = count + 1; fallthrough
-	case 3: count = count + 1; fallthrough
-	case 4: count = count + 1; assert(false, "4")
-	case 5: count = count + 1; fallthrough
-	case 6: count = count + 1; fallthrough
-	case 7: count = count + 1; fallthrough
-	case 8: count = count + 1; fallthrough
-	case 9: count = count + 1; fallthrough
-	default: assert(i5 == count, "good")
+	case 0:
+		count = count + 1
+		fallthrough
+	case 1:
+		count = count + 1
+		fallthrough
+	case 2:
+		count = count + 1
+		fallthrough
+	case 3:
+		count = count + 1
+		fallthrough
+	case 4:
+		count = count + 1
+		assert(false, "4")
+	case 5:
+		count = count + 1
+		fallthrough
+	case 6:
+		count = count + 1
+		fallthrough
+	case 7:
+		count = count + 1
+		fallthrough
+	case 8:
+		count = count + 1
+		fallthrough
+	case 9:
+		count = count + 1
+		fallthrough
+	default:
+		assert(i5 == count, "good")
 	}
 	assert(fired, "fired")
 
 	switch hello {
-	case "wowie": assert(false, "wowie")
-	case "hello": assert(true, "hello")
-	case "jumpn": assert(false, "jumpn")
-	default: assert(false, "default")
+	case "wowie":
+		assert(false, "wowie")
+	case "hello":
+		assert(true, "hello")
+	case "jumpn":
+		assert(false, "jumpn")
+	default:
+		assert(false, "default")
 	}
 
 	fired = false
 	switch i := i5 + 2; i {
-	case i7: fired = true
-	default: assert(false, "fail")
+	case i7:
+		fired = true
+	default:
+		assert(false, "fail")
 	}
 	assert(fired, "var")
+
+	// switch on nil-only comparison types
+	switch f := func() {}; f {
+	case nil:
+		assert(false, "f should not be nil")
+	default:
+	}
+
+	switch m := make(map[int]int); m {
+	case nil:
+		assert(false, "m should not be nil")
+	default:
+	}
+
+	switch a := make([]int, 1); a {
+	case nil:
+		assert(false, "m should not be nil")
+	default:
+	}
 }
diff --git a/test/switch3.go b/test/switch3.go
new file mode 100644
index 0000000..e91499d
--- /dev/null
+++ b/test/switch3.go
@@ -0,0 +1,58 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 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
+
+type I interface {
+	M()
+}
+
+func bad() {
+	var i I
+	var s string
+
+	switch i {
+	case s: // ERROR "mismatched types string and I"
+	}
+
+	switch s {
+	case i: // ERROR "mismatched types I and string"
+	}
+
+	var m, m1 map[int]int
+	switch m {
+	case nil:
+	case m1: // ERROR "can only compare map m to nil"
+	default:
+	}
+
+	var a, a1 []int
+	switch a {
+	case nil:
+	case a1: // ERROR "can only compare slice a to nil"
+	default:
+	}
+
+	var f, f1 func()
+	switch f {
+	case nil:
+	case f1: // ERROR "can only compare func f to nil"
+	default:
+	}
+}
+
+func good() {
+	var i interface{}
+	var s string
+
+	switch i {
+	case s:
+	}
+
+	switch s {
+	case i:
+	}
+}
diff --git a/test/turing.go b/test/turing.go
index 0af39de..366982e 100644
--- a/test/turing.go
+++ b/test/turing.go
@@ -10,42 +10,47 @@ package main
 
 var p, pc int
 var a [30000]byte
+
 const prog = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.!"
 
 func scan(dir int) {
 	for nest := dir; dir*nest > 0; pc += dir {
 		switch prog[pc+dir] {
-			case ']':
-				nest--
-			case '[':
-				nest++
+		case ']':
+			nest--
+		case '[':
+			nest++
 		}
 	}
 }
 
 func main() {
+	r := ""
 	for {
 		switch prog[pc] {
-			case '>':
-					p++
-			case '<':
-					p--
-			case '+':
-					a[p]++
-			case '-':
-					a[p]--
-			case '.':
-					print(string(a[p]))
-			case '[':
-				if a[p] == 0 {
-					scan(1)
-				}
-			case ']':
-				if a[p] != 0 {
-					scan(-1)
-				}
-			default:
-					return
+		case '>':
+			p++
+		case '<':
+			p--
+		case '+':
+			a[p]++
+		case '-':
+			a[p]--
+		case '.':
+			r += string(a[p])
+		case '[':
+			if a[p] == 0 {
+				scan(1)
+			}
+		case ']':
+			if a[p] != 0 {
+				scan(-1)
+			}
+		default:
+			if r != "Hello World!\n" {
+				panic(r)
+			}
+			return
 		}
 		pc++
 	}
diff --git a/test/typeswitch.go b/test/typeswitch.go
index 83fb098..aa911f9 100644
--- a/test/typeswitch.go
+++ b/test/typeswitch.go
@@ -82,9 +82,9 @@ func main() {
 		case []int:
 			assert(x[3] == 3 && i == Array, "array")
 		case map[string]int:
-			assert(x == m && i == Map, "map")
+			assert(x != nil && i == Map, "map")
 		case func(i int) interface{}:
-			assert(x == f && i == Func, "fun")
+			assert(x != nil && i == Func, "fun")
 		default:
 			assert(false, "unknown")
 		}
@@ -111,5 +111,4 @@ func main() {
 	default:
 		assert(false, "switch 4 unknown")
 	}
-
 }
diff --git a/test/typeswitch3.go b/test/typeswitch3.go
new file mode 100644
index 0000000..0789801
--- /dev/null
+++ b/test/typeswitch3.go
@@ -0,0 +1,35 @@
+// errchk $G -e $D/$F.go
+
+// Copyright 2011 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 (
+	"io"
+)
+
+type I interface {
+	M()
+}
+
+func main(){
+	var x I
+	switch x.(type) {
+	case string:	// ERROR "impossible"
+		println("FAIL")
+	}
+	
+	// Issue 2700: if the case type is an interface, nothing is impossible
+	
+	var r io.Reader
+	
+	_, _ = r.(io.Writer)
+	
+	switch r.(type) {
+	case io.Writer:
+	}
+}
+
+
diff --git a/test/utf.go b/test/utf.go
index a93fc29..9fba581 100644
--- a/test/utf.go
+++ b/test/utf.go
@@ -6,10 +6,10 @@
 
 package main
 
-import "utf8"
+import "unicode/utf8"
 
 func main() {
-	var chars [6] int
+	var chars [6]rune
 	chars[0] = 'a'
 	chars[1] = 'b'
 	chars[2] = 'c'
@@ -21,16 +21,22 @@ func main() {
 		s += string(chars[i])
 	}
 	var l = len(s)
-	for w, i, j := 0,0,0; i < l; i += w {
-		var r int
+	for w, i, j := 0, 0, 0; i < l; i += w {
+		var r rune
 		r, w = utf8.DecodeRuneInString(s[i:len(s)])
-		if w == 0 { panic("zero width in string") }
-		if r != chars[j] { panic("wrong value from string") }
+		if w == 0 {
+			panic("zero width in string")
+		}
+		if r != chars[j] {
+			panic("wrong value from string")
+		}
 		j++
 	}
 	// encoded as bytes:  'a' 'b' 'c' e6 97 a5 e6 9c ac e8 aa 9e
 	const L = 12
-	if L != l { panic("wrong length constructing array") }
+	if L != l {
+		panic("wrong length constructing array")
+	}
 	a := make([]byte, L)
 	a[0] = 'a'
 	a[1] = 'b'
@@ -44,11 +50,15 @@ func main() {
 	a[9] = 0xe8
 	a[10] = 0xaa
 	a[11] = 0x9e
-	for w, i, j := 0,0,0; i < L; i += w {
-		var r int
+	for w, i, j := 0, 0, 0; i < L; i += w {
+		var r rune
 		r, w = utf8.DecodeRune(a[i:L])
-		if w == 0 { panic("zero width in bytes") }
-		if r != chars[j] { panic("wrong value from bytes") }
+		if w == 0 {
+			panic("zero width in bytes")
+		}
+		if r != chars[j] {
+			panic("wrong value from bytes")
+		}
 		j++
 	}
 }
diff --git a/test/vectors.go b/test/vectors.go
deleted file mode 100644
index ed5905d..0000000
--- a/test/vectors.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// $G $F.go && $L $F.$A && ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "container/vector"
-
-
-type S struct {
-	val int
-}
-
-
-func (p *S) Init(val int) *S {
-	p.val = val
-	return p
-}
-
-
-func test0() {
-	v := new(vector.Vector)
-	if v.Len() != 0 {
-		print("len = ", v.Len(), "\n")
-		panic("fail")
-	}
-}
-
-
-func test1() {
-	var a [1000]*S
-	for i := 0; i < len(a); i++ {
-		a[i] = new(S).Init(i)
-	}
-
-	v := new(vector.Vector)
-	for i := 0; i < len(a); i++ {
-		v.Insert(0, a[i])
-		if v.Len() != i+1 {
-			print("len = ", v.Len(), "\n")
-			panic("fail")
-		}
-	}
-
-	for i := 0; i < v.Len(); i++ {
-		x := v.At(i).(*S)
-		if x.val != v.Len()-i-1 {
-			print("expected ", i, ", found ", x.val, "\n")
-			panic("fail")
-		}
-	}
-
-	for v.Len() > 10 {
-		v.Delete(10)
-	}
-}
-
-
-func main() {
-	test0()
-	test1()
-}
diff --git a/test/zerodivide.go b/test/zerodivide.go
index 1948528..3b08e77 100644
--- a/test/zerodivide.go
+++ b/test/zerodivide.go
@@ -9,13 +9,10 @@ package main
 import (
 	"fmt"
 	"math"
+	"runtime"
 	"strings"
 )
 
-type Error interface {
-	String() string
-}
-
 type ErrorTest struct {
 	name string
 	fn   func()
@@ -161,10 +158,10 @@ var errorTests = []ErrorTest{
 	ErrorTest{"complex128 1/0", func() { use(e128 / d128) }, ""},
 }
 
-func error(fn func()) (error string) {
+func error_(fn func()) (error string) {
 	defer func() {
 		if e := recover(); e != nil {
-			error = e.(Error).String()
+			error = e.(runtime.Error).Error()
 		}
 	}()
 	fn()
@@ -199,7 +196,7 @@ func main() {
 		if t.err != "" {
 			continue
 		}
-		err := error(t.fn)
+		err := error_(t.fn)
 		switch {
 		case t.err == "" && err == "":
 			// fine

-- 
Packaging for Google Go



More information about the Pkg-google-commits mailing list